/* ============================================================
   Glacierwoods — identity UI

   One stylesheet for every screen idp-ui serves. Token values are
   copied from design/glacierwoods-design/tokens/ rather than linked:
   design/ sits outside the Bazel graph (ADR-0001, ADR-0018) and this
   binary must carry everything it serves.

   Font filenames below are rewritten to content-addressed URLs when
   the server starts. A filename lives here and in assets_test.go; a
   rename moves both. url() must use double quotes — the rewriter and
   its startup guard both match on them, so a single-quoted url() is
   skipped by each and 404s in the browser.
   ============================================================ */

/* Each face is split by subset, so the browser fetches latin-ext only when the
   text calls for it. The unicode-range on both halves is what keeps the pair
   disjoint: two faces matching one family, style and weight with no range
   declared do not compose — the later wins for every codepoint and the other
   is dead. */
@font-face {
  font-family: 'Spectral';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/spectral-400-latin-ext.a62b9bdf669d.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Spectral';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/spectral-400-latin.bcb83e9c56d4.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Spectral';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/spectral-500-latin-ext.38331492f591.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Spectral';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/spectral-500-latin.79ce505722da.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Hanken Grotesk ships as a variable font: one file per subset spans the range. */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/hanken-grotesk-var-latin-ext.a1376a563717.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/static/hanken-grotesk-var-latin.1f21c6eaa000.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/ibm-plex-mono-400-latin-ext.f1050dc5317b.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/ibm-plex-mono-400-latin.c36f509c0a8f.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/ibm-plex-mono-500-latin-ext.77f03e26f981.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/ibm-plex-mono-500-latin.a76f53ca6612.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Families */
  --font-display: 'Spectral', 'Iowan Old Style', Georgia, serif;
  --font-sans: 'Hanken Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  --weight-semibold: 600;

  --text-body: 1.0625rem;
  --text-small: 0.9375rem;
  --text-label: 0.75rem;
  --tracking-wide: 0.08em;

  /* Palette — the dark half only; every idp-ui screen is on charred wood. */
  --bark-950: #14100c;
  --bark-900: #1e1812;
  --spruce-700: #2e4031;
  --superior-500: #4b85a3;
  --superior-400: #7da9c1;
  --birch-50: #faf8f3;
  --birch-100: #f3efe6;

  --surface-ground: #0f0c08;
  --surface-inverse: var(--bark-900);
  --text-on-dark: var(--birch-100);
  --text-on-dark-muted: #b9ab98;
  --line-on-dark: rgba(243, 239, 230, 0.18);
  --fill-on-dark: rgba(243, 239, 230, 0.03);
  --superior-on-bark: var(--superior-500);

  /* Validation red, lightened for legibility on bark. The ember tokens are
     tuned for light surfaces and go muddy here. */
  --gw-error: #d98b7c;
  --gw-success: #a6b099;

  --radius-xs: 2px;
  --radius-sm: 4px;
  --radius-md: 8px;
  --shadow-lg: 0 20px 48px rgba(20, 16, 12, 0.14);
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 20px;
  background: var(--surface-ground);
  color: var(--text-on-dark);
  font-family: var(--font-sans);
  font-size: var(--text-body);
  -webkit-font-smoothing: antialiased;
}

/* ---------- The card ---------- */

.gw-card {
  position: relative;
  width: 100%;
  max-width: 440px;
  /* The bottom padding is the roofline's room. The card grows with whatever
     Kratos returns, so the watermark has no fixed empty region to sit in and
     would otherwise cross the last line of content. */
  padding: 42px 40px 104px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--surface-inverse);
  box-shadow: var(--shadow-lg);
}

/* The roofline, sunk almost out of sight. Decorative: aria-hidden in markup. */
.gw-watermark {
  position: absolute;
  right: 26px;
  bottom: 22px;
  width: 180px;
  height: auto;
  opacity: 0.05;
  z-index: 0;
  pointer-events: none;
}

.gw-card > *:not(.gw-watermark) { position: relative; z-index: 1; }

.gw-tick {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 22px;
}
.gw-tick::before {
  content: "";
  width: 20px;
  height: 1px;
  flex: none;
  background: var(--superior-on-bark);
}
.gw-coord {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--superior-on-bark);
}

.gw-wordmark {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.05rem;
  color: var(--birch-50);
}

.gw-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.5rem;
  letter-spacing: -0.01em;
  line-height: 1.15;
  color: var(--birch-50);
  margin: 14px 0 6px;
}

.gw-sub {
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--text-on-dark-muted);
  margin: 0;
}

.gw-foot {
  margin-top: 28px;
  padding-top: 24px;
}

.gw-link {
  color: var(--superior-on-bark);
  text-decoration: none;
  font-size: 0.8rem;
}
.gw-link:hover { color: var(--superior-400); }

.gw-ref {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--text-on-dark-muted);
}

/* ---------- Node primitives ---------- */

/* Kratos owns field order and presence; this styles whatever arrives. */
.gw-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.gw-label {
  font-size: var(--text-label);
  font-weight: 600;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--text-on-dark-muted);
}

.gw-input {
  width: 100%;
  font-family: var(--font-sans);
  font-size: var(--text-body);
  color: var(--text-on-dark);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line-on-dark);
  border-radius: 0;
  /* Weighted downward: Kratos supplies no placeholder, so an empty field is
     genuinely empty and the label should sit near where the text will be
     rather than adrift above a bare rule. */
  padding: 0.3rem 0 0.6rem;
  outline: none;
}
.gw-input::placeholder { color: var(--text-on-dark-muted); }
.gw-input:focus-visible { border-bottom-color: var(--superior-on-bark); }
.gw-input:disabled { opacity: 0.45; }

/* A field Kratos flagged. The label reddens too, so the association is
   visible and not carried by the input border alone. */
.gw-field--error .gw-input { border-bottom-color: var(--gw-error); }
.gw-field--error .gw-label { color: var(--gw-error); }

/* Recovery codes are typed, not scanned: mono, loosened. */
.gw-input--code {
  font-family: var(--font-mono);
  letter-spacing: 0.14em;
}

/* The 6-digit second-factor box. */
.gw-code-input {
  width: 100%;
  font-family: var(--font-mono);
  font-size: 1.5rem;
  letter-spacing: 0.5em;
  text-indent: 0.5em;
  color: var(--birch-50);
  text-align: center;
  background: var(--fill-on-dark);
  border: 1px solid var(--line-on-dark);
  border-radius: var(--radius-sm);
  padding: 0.85rem 0.5rem;
  outline: none;
}
.gw-code-input::placeholder { color: var(--text-on-dark-muted); }
.gw-code-input:focus-visible { border-color: var(--superior-on-bark); }

.gw-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  width: 100%;
  font-family: var(--font-sans);
  font-weight: var(--weight-semibold);
  font-size: var(--text-small);
  letter-spacing: 0.04em;
  line-height: 1;
  padding: 0.95rem 1.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.gw-btn--primary {
  background: var(--birch-50);
  color: var(--bark-900);
}
.gw-btn--outline {
  background: transparent;
  color: var(--birch-50);
  border-color: var(--line-on-dark);
}
/* Provider buttons keep their own mark and wording; the brand supplies only
   the surface they sit on. Apple and Google both require the mark be
   unmodified and the button no less prominent than other options. */
.gw-btn--provider {
  background: var(--bark-950);
  color: var(--birch-50);
  border-color: var(--line-on-dark);
}
/* Carries no weight of its own: for the action that leaves the page rather
   than changing anything on it. */
.gw-btn--ghost {
  background: transparent;
  color: var(--text-on-dark-muted);
}
/* Unlinking a method, or replacing a set of codes that still work. Outlined
   rather than filled — it is the answer to a question the page asked, not the
   thing the page wants. */
.gw-btn--danger {
  background: transparent;
  color: var(--gw-error);
  border-color: var(--gw-error);
}
/* Beside a row rather than under a form, so it sizes to its label. */
.gw-btn--sm {
  width: auto;
  flex: none;
  padding: 0.6rem 1rem;
  font-size: 0.8125rem;
}
/* An anchor styled as a button is still an anchor. */
a.gw-btn { text-decoration: none; }

.gw-btn:disabled { opacity: 0.45; cursor: default; }
.gw-btn:focus-visible,
.gw-link:focus-visible {
  outline: 2px solid var(--superior-on-bark);
  outline-offset: 2px;
}

/* TOTP secret and recovery-code blocks. Both get printed or screenshotted,
   so they wrap rather than scroll and keep their contrast on paper. */
.gw-secret {
  font-family: var(--font-mono);
  font-size: 0.95rem;
  letter-spacing: 0.08em;
  color: var(--birch-50);
  background: var(--fill-on-dark);
  border: 1px solid var(--line-on-dark);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
  margin: 0;
  white-space: pre-wrap;
  word-break: break-all;
}

/* The enrolment QR arrives as a data: URI. White plate: scanners need the
   quiet zone light, and the card is too dark to read through. */
.gw-qr {
  display: block;
  width: 180px;
  height: 180px;
  background: #ffffff;
  padding: 10px;
  border-radius: var(--radius-sm);
}

/* ---------- Messages ---------- */

/* Kratos types every message info | error | success, at flow level and at
   node level. Both scopes, all three types. */
.gw-alert {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 14px 16px;
  border: 1px solid var(--line-on-dark);
  border-left-width: 3px;
  border-radius: var(--radius-sm);
  background: var(--fill-on-dark);
  font-size: 0.88rem;
  line-height: 1.45;
}
.gw-alert + .gw-alert { margin-top: 10px; }
.gw-alert--error { border-left-color: var(--gw-error); }
.gw-alert--success { border-left-color: var(--gw-success); }
.gw-alert--info { border-left-color: var(--superior-on-bark); }
.gw-alert-body { color: var(--text-on-dark-muted); margin: 0; }

.gw-msg {
  font-size: 0.78rem;
  margin: 0;
}
.gw-msg--error { color: var(--gw-error); }
.gw-msg--success { color: var(--gw-success); }
.gw-msg--info { color: var(--text-on-dark-muted); }

/* ---------- Group sections ---------- */

/* Kratos returns a flat node list; the renderer buckets it by group so the
   page reads as sections rather than a stack of peers. */
.gw-group {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.gw-group + .gw-group { margin-top: 24px; }

/* Social buttons sit closer together than form fields do. */
.gw-group--oidc { gap: 12px; }

/* The passkey affordance is an alternative to the password, not a step
   after it — the divider carries that, so no extra top margin. */
.gw-group--passkey + .gw-group,
.gw-divider + .gw-group { margin-top: 0; }

.gw-divider {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 24px 0 20px;
}
.gw-divider::before,
.gw-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line-on-dark);
}
.gw-divider-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-on-dark-muted);
}

/* ---------- Identity and client chrome ---------- */

/* Shown once identity is established — second factor, re-authentication,
   consent. Says who is being confirmed without re-asking. */
.gw-chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  align-self: flex-start;
  padding: 8px 14px;
  border: 1px solid var(--line-on-dark);
  border-radius: 999px;
  background: var(--fill-on-dark);
}
.gw-chip-text {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-on-dark);
}

/* The OAuth2 client asking for access. */
.gw-client {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 16px 18px;
  border: 1px solid var(--line-on-dark);
  border-radius: var(--radius-sm);
  background: var(--fill-on-dark);
}
.gw-client-glyph {
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: var(--radius-xs);
  background: var(--spruce-700);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.15rem;
  color: var(--birch-50);
}
.gw-client-name {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--birch-50);
}
.gw-client-meta {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--text-on-dark-muted);
  margin-top: 2px;
}

/* What a client is asking for, in plain words. */
.gw-scope {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 0;
  border-top: 1px solid var(--line-on-dark);
}
.gw-scope-icon { color: #a6b099; flex: none; margin-top: 1px; }
.gw-scope-name {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-on-dark);
}
.gw-scope-detail {
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--text-on-dark-muted);
  margin-top: 3px;
}

.gw-eyebrow {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-on-dark-muted);
  margin: 24px 0 0;
}

/* ---------- Outcome states ---------- */

.gw-halo {
  width: 64px;
  height: 64px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line-on-dark);
  background: var(--fill-on-dark);
  color: var(--text-on-dark-muted);
}

.gw-halo--saved { color: var(--gw-success); }
.gw-halo--passkey { color: var(--superior-on-bark); }

.gw-done { margin-top: 26px; }

/* The mark at reading size, on the one screen that leads with it. */
.gw-roofline {
  display: block;
  width: 60px;
  height: auto;
  color: var(--birch-50);
  margin-bottom: 6px;
}

.gw-skip {
  display: inline-block;
  margin-top: 18px;
}

/* ---------- The account overview ---------- */

/* Settings is a list of things you own, so it is wider than a form: a row
   needs room for what the thing is, what state it is in, and the one action,
   side by side. */
.gw-card--wide { max-width: 560px; }

.gw-account-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.gw-rows { margin-top: 14px; }

.gw-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding: 22px 0;
  border-top: 1px solid var(--line-on-dark);
}
.gw-row:first-child { border-top: none; }
.gw-row-body { flex: 1; min-width: 0; }

.gw-row-key {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-on-dark-muted);
  margin: 0 0 8px;
}

.gw-row-value {
  font-size: 0.92rem;
  line-height: 1.5;
  color: var(--text-on-dark);
  margin: 0;
}

/* One enrolled passkey. */
.gw-pk {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0 0;
  color: var(--gw-success);
}
.gw-pk-name { font-size: 0.88rem; color: var(--text-on-dark); }
.gw-pk-date {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  letter-spacing: 0.04em;
  color: var(--text-on-dark-muted);
}

/* ---------- The paper inset ---------- */

/* The TOTP secret and QR, and the recovery codes: the artifacts a person
   photographs, prints, or copies onto a card that goes in a drawer. Pale text
   on charred wood does none of that well, so they sit on paper instead — a
   light surface inside the dark card, carrying its own palette. */
.gw-paper {
  --paper-surface: #faf8f3;
  --paper-sunk: #efeae0;
  --paper-line: rgba(20, 16, 12, 0.14);
  --paper-text: #14100c;
  --paper-muted: #6b6055;
  --paper-faint: #a89d90;

  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 18px;
  margin-top: 22px;
  padding: 22px 24px;
  border-radius: var(--radius-sm);
  background: var(--paper-surface);
  color: var(--paper-text);
}

.gw-paper-title {
  flex-basis: 100%;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--paper-muted);
  margin: 0;
}

/* The form the inset introduces is not part of it. */
.gw-paper + .gw-group,
.gw-download + .gw-group { margin-top: 22px; }

/* On paper the secret block inverts: dark type, hairline rule, no glow. */
.gw-paper .gw-secret {
  flex: 1;
  min-width: 12ch;
  color: var(--paper-text);
  background: var(--paper-sunk);
  border-color: var(--paper-line);
  letter-spacing: 0.1em;
  /* A setup key is transcribed character by character into a phone. Breaking
     it mid-group turns one line into two that look like two keys; wrapping at
     the spaces Kratos already put in keeps each group whole. */
  word-break: normal;
  overflow-wrap: break-word;
}

.gw-paper .gw-qr {
  width: 112px;
  height: 112px;
  padding: 6px;
}

/* Recovery codes. Two columns so ten codes read as a block rather than a
   list, and spent ones stay visible — a struck-through code tells someone
   the sheet is theirs and partly used, where a missing line tells them
   nothing. */
.gw-codes {
  flex-basis: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 28px;
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: var(--font-mono);
  font-size: 0.95rem;
  letter-spacing: 0.08em;
  color: var(--paper-text);
}
.gw-code--used {
  color: var(--paper-faint);
  text-decoration: line-through;
}

.gw-download { margin-top: 16px; }

/* ---------- Print ---------- */

/* Someone printing this page wants the codes and nothing else. Printing is the
   browser's own dialog; the page carries no script beyond Kratos's WebAuthn
   helper. */
@media print {
  body { background: #ffffff; padding: 0; display: block; }
  .gw-card {
    max-width: none;
    padding: 0;
    background: #ffffff;
    box-shadow: none;
    border-radius: 0;
  }
  .gw-watermark,
  .gw-tick,
  .gw-btn,
  .gw-skip,
  .gw-halo,
  .gw-alert { display: none; }

  .gw-wordmark, .gw-title, .gw-sub { color: #14100c; }

  .gw-paper {
    margin: 0;
    padding: 0;
    /* The struck-through codes carry meaning, so the browser must not drop
       the colour that distinguishes them when it economises on ink. */
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }
}

/* ---------- Small screens ---------- */

@media (max-width: 520px) {
  body { padding: 0; align-items: stretch; }
  .gw-card {
    max-width: none;
    min-height: 100vh;
    padding: 36px 24px 104px;
    border-radius: 0;
    box-shadow: none;
  }
  .gw-watermark { width: 150px; }
}

/* Kratos's own field errors must stay legible when the OS forces contrast. */
@media (forced-colors: active) {
  .gw-input, .gw-code-input, .gw-btn { border: 1px solid; }
}
