/* ------------------------------------------------------------------
   Aqlama · Recording — the account screens (board C1)
   /login, /signup (+ its "check your email" state), /verify, /accept-invite,
   /forgot-password, /reset-password.

   Layered ON TOP of /style.css: THIS SHEET HOLDS NO HEX COLOUR. The board
   block reads the --ui-* tokens of /ui.css's :root, the base rules read
   style.css's (test/auth-board-c1.test.js fails a hex here).

   ONE FRAME FOR ALL SIX PAGES (polish round 2026-10-19, see the board block
   below): a top bar, a brand hero, and the form as a sheet (a phone) or a card
   beside the brand panel (>= 1024px). Every board rule
   is written under `.board` (the class on <body>), so the base rules below
   stay the FIRST occurrence of their own text -- test/signup-page-wiring.test.js
   reads them with indexOf. Direction comes from logical properties only; there
   is no [dir=] block to keep in sync.
------------------------------------------------------------------ */
.auth-body {
  min-height: 100vh;
}

/* ------------------------------------------------------------------
   The language toggle (msa onboarding spec, D1)
   THE SAME PILL /user-chrome.js PAINTS INTO THE SIGNED-IN NAV, under its own
   class, because that rule is scoped `.user-nav .nav-lang` and an auth page has
   no .user-nav. The 44px floor is LOAD-BEARING rather than defensive: MEASURED,
   this control is 34.40px tall without it and 44.00px with it, in both
   languages. The board's look (13px / 500, an 8px corner) is under `.board`.
------------------------------------------------------------------ */
.auth-lang {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding: 8px 14px;
  border: 1px solid var(--hair-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--brand);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: background 150ms ease, border-color 150ms ease;
}
.auth-lang:hover { background: var(--brand-soft); border-color: var(--brand); }
.auth-lang:focus-visible {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
@media (prefers-reduced-motion: reduce) {
  .auth-lang { transition: none; }
}

/* ------------------------------------------------------------------
   Form
------------------------------------------------------------------ */
.auth-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.auth-field {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.auth-label {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--warm-2);
  font-weight: 600;
}
.auth-field input,
.auth-field select {
  width: 100%;
  background: var(--card);
  color: var(--ink);
  border: 1px solid var(--hair);
  border-radius: 7px;
  padding: 12px 13px;
  font-family: var(--font-body);
  /* 16px IS THE iOS THRESHOLD, not a taste choice -- the same rule
     '.meta-form input' in style.css already carries: mobile Safari zooms the
     viewport on focusing any input below 16px and never zooms back. The board
     draws these at the page's 14px; the zoom is worse than two pixels. */
  font-size: 16px;
  font-weight: 500;
  line-height: 1.3;
  /* A finger is not a mouse pointer. */
  min-height: 44px;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
.auth-field input::placeholder {
  color: var(--warm-2);
  opacity: 0.8;
}
.auth-field input:hover:not(:focus) {
  border-color: var(--hair-strong);
}
.auth-field input:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-soft);
}
/* Only flag fields the user actually touched + left wrong. */
.auth-field input:user-invalid {
  border-color: var(--danger);
}
.auth-field input:user-invalid:focus {
  box-shadow: 0 0 0 3px var(--danger-soft);
}

/* ------------------------------------------------------------------
   Error area
------------------------------------------------------------------ */
.auth-error {
  background: var(--danger-soft);
  border: 1px solid rgba(169, 50, 38, 0.3);
  /* LOGICAL, NOT PHYSICAL (spec D3): the accent belongs on the edge the
     sentence STARTS at. It must come AFTER the `border` shorthand above. The
     board draws the note with no accent (`.board .auth-error`). */
  border-inline-start: 3px solid var(--danger);
  border-radius: 6px;
  padding: 10px 12px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--danger);
  font-weight: 500;
}

/* ------------------------------------------------------------------
   Submit button — reuses button.action from style.css
------------------------------------------------------------------ */
.auth-form button.action {
  margin-top: 4px;
  margin-bottom: 0;
  padding: 13px 18px;
  /* A FLOOR: a later padding or font-size change must not be able to drop the
     primary button of a phone flow below 44px in silence. */
  min-height: 44px;
}
/* Subtle "working" affordance while the request is in flight. */
.auth-form button.action[aria-busy="true"] {
  opacity: 0.7;
  cursor: progress;
}

/* ------------------------------------------------------------------
   Switch link, and the forgot link
------------------------------------------------------------------ */
.auth-switch {
  margin: 20px 0 0;
  text-align: center;
  font-size: 13px;
  color: var(--warm-1);
}
.auth-switch a {
  color: var(--brand);
  font-weight: 600;
}
.auth-switch a:hover { color: var(--brand-deep); }
/* Both render well under a finger's worth of height. The hit area is extended
   past the visual bounds rather than the type grown. */
.auth-switch a,
.auth-forgot { position: relative; }
.auth-switch a::after,
.auth-forgot::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}
.auth-forgot {
  font-size: 12px;
  font-weight: 600;
  color: var(--brand);
  text-decoration: none;
}
.auth-forgot:hover { color: var(--brand-deep); text-decoration: underline; }

/* ------------------------------------------------------------------
   Success note (forgot-password, /verify's answers) — mirrors .auth-error
------------------------------------------------------------------ */
.auth-success {
  background: var(--moss-soft);
  border: 1px solid rgba(74, 107, 58, 0.3);
  /* Logical for the same reason .auth-error is, and changed WITH it. */
  border-inline-start: 3px solid var(--moss);
  border-radius: 6px;
  padding: 10px 12px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--moss);
  font-weight: 500;
}

/* ------------------------------------------------------------------
   Password visibility toggle (injected by public/auth.js)
------------------------------------------------------------------ */
.password-wrap {
  position: relative;
  display: block;
}
/* THE EYE SITS AT THE END OF THE FIELD IN BOTH DIRECTIONS (spec D3): the
   logical forms compute to the physical ones in ltr, and there is no
   [dir="rtl"] override block to keep in sync. ORDER MATTERS: `.auth-field
   input` sets `padding` as a shorthand and this block comes later at equal
   specificity, so this longhand wins. */
.password-wrap input { padding-inline-end: 46px; }
.password-toggle {
  position: absolute;
  top: 50%;
  inset-inline-end: 6px;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  margin: 0;
  background: none;
  border: none;
  border-radius: 6px;
  color: var(--warm-2);
  cursor: pointer;
}
.password-toggle:hover { color: var(--ink); }
.password-toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--brand-soft);
  color: var(--brand);
}
.password-toggle svg { width: 20px; height: 20px; display: block; }

@media (prefers-reduced-motion: reduce) {
  .auth-field input { transition: none; }
}


/* ==================================================================
   THE ACCOUNT SCREENS, "DAYLIGHT KUFI" (polish round 2026-10-19; spec
   D:/tmp/polish-2026-10-19/frontend-onboarding.md §2.5). Everything below
   is scoped to `.board` (the class on <body> of all six account pages) and
   reads the --ui-* tokens /ui.css defines; this sheet still holds no hex.
   /ui.css loads after this sheet and sets the faces for every body in scope.

   ONE FRAME FOR ALL SIX PAGES:
     main.board-shell
       header.board-appbar        the logo and the language
       div.auth-stage
         aside.auth-hero          the brand panel (start side)
         div.auth-sheet           the form: a body column, then the dock
   PHONE: the hero sits on the brand tint and the white sheet overlaps it by
   24px; the dock is stuck to the bottom of the screen, in thumb reach.
   >= 1024px: two columns, max 1120px, vertically centred in the screen: the
   brand panel on the start side, the form as a 440px card. No dock.

   SPECIFICITY IS DELIBERATE. The shared primary button is `button.action`
   in public/style.css (0,1,1) and `.auth-form button.action` above (0,2,1);
   every override here is spelled long enough to win, and this block sits at
   the END of the sheet so the base selectors above are still the FIRST
   occurrence of their own text (test/signup-page-wiring.test.js reads them
   with indexOf). Direction comes from logical properties only.
   ================================================================== */
.board {
  font-size: 16px;
  line-height: 1.5;
}

/* THE SHELL: the full screen, the brand tint behind the hero. 100dvh WITH
   100vh FIRST so a browser without the dynamic unit still fills the screen. */
.board .board-shell {
  max-width: none;
  margin: 0;
  padding: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--ui-tint);
}

/* ---- the top bar: on the tint, no line ------------------------------- */
.board .board-appbar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: 56px;
  padding: 0 16px;
  background: transparent;
  border: 0;
  box-shadow: none;
}
/* The logo is a link that carries a pending ?next=; the whole bar height is
   its hit area. */
.board .board-mark {
  min-width: 0;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
.board .board-mark img { height: 26px; width: auto; }
/* The language pill: a white chip on the tint. The 44px floor lives on the
   base rule; the visible chip is smaller and its hit area is not. */
.board .auth-lang {
  min-height: 44px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--ui-r-pill);
  background: var(--ui-surface);
  box-shadow: var(--ui-e1);
  color: var(--ui-brand);
  font-size: 14px;
  font-weight: 600;
}
.board .auth-lang:hover { background: var(--ui-surface); color: var(--ui-brand-press); border-color: transparent; }

/* ---- the stage: hero over sheet on a phone ---------------------------- */
.board .auth-stage {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

/* ---- the hero: the brand panel ------------------------------------------ */
.board .auth-hero {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 8px 16px 48px;
}
/* A display line: 30/40 on a phone. Noto Kufi for Arabic (owner). */
.board .auth-hero-title {
  margin: 0;
  max-width: none;
  font-size: 24px;
  font-weight: 700;
  line-height: 34px;
  letter-spacing: -0.01em;
  color: var(--ui-ink);
  overflow-wrap: anywhere;
}
.board .auth-hero-title:lang(ar) { font-family: var(--ui-font-ar-head); line-height: 40px; letter-spacing: 0; }
.board .auth-hero-sub {
  margin: 0;
  font-size: 16px;
  line-height: 26px;
  color: var(--ui-ink-2);
}
/* THE DIAMOND WAVEFORM: the logo's diamonds as a recording. Decoration only
   (aria-hidden in the markup); one gold diamond, the rest brand blue. */
.board .auth-wave { display: block; width: auto; height: 32px; margin-top: 8px; overflow: visible; }
.board .auth-wave path { fill: var(--ui-brand); }
.board .auth-wave .is-gold { fill: var(--ui-gold); }
/* The account pages' hero carries the full logo, so the bar's small one steps aside
   (visibility, not display: the language pill keeps its end of the bar). */
.board .auth-hero-logo { display: block; width: 112px; height: auto; margin-bottom: 4px; }
.board .board-shell:has(.auth-hero-logo) .board-mark { visibility: hidden; }
/* Lines the brand panel carries only when it has room for them (>= 1024). */
.board .auth-hero-wide { display: none; }

/* ---- the sheet: white, rounded at the top, over the hero --------------- */
.board .auth-sheet {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  margin-top: -24px;
  border-radius: var(--ui-r-xl) var(--ui-r-xl) 0 0;
  background: var(--ui-surface);
  box-shadow: var(--ui-e3);
}

/* THE FORM HAS TO GROW, AND THIS WAS MEASURED RATHER THAN REASONED:
   `.auth-form` is a flex column, but as a flex ITEM its default is
   `flex: 0 1 auto`, so the dock sat mid-screen on every page short enough not
   to scroll. `gap: 0` so the shared 16px gap does not land between the body
   and the dock. */
.board .auth-form {
  flex: 1 1 auto;
  gap: 0;
}
/* /verify's two forms sit INSIDE the body column, one after the other. */
.board .board-inline {
  flex: none;
  gap: 16px;
}

/* ---- the body column ------------------------------------------------------ */
/* Top-aligned. `flex: 1 0 auto` is insurance: the day anything above it
   constrains its height, nothing shrinks the body past its content. */
.board .board-scroll {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 20px;
  padding: 28px 16px 24px;
}

/* ---- the sheet's heading and its line --------------------------------------- */
.board .board-intro {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
/* The title role: 24/32, 650. No full stop at the end of any heading (spec §1.1). */
.board .board-intro-title,
.board .auth-sheet-title {
  margin: 0;
  font-size: 24px;
  font-weight: 650;
  line-height: 32px;
  letter-spacing: -0.005em;
  color: var(--ui-ink);
}
.board .board-intro-title:lang(ar),
.board .auth-sheet-title:lang(ar) {
  font-family: var(--ui-font-ar-head);
  font-weight: 700;
  line-height: 38px;
  letter-spacing: 0;
}
.board .board-intro-sub {
  margin: 0;
  font-size: 16px;
  line-height: 26px;
  color: var(--ui-ink-2);
}

/* ---- the fields ------------------------------------------------------------------ */
.board .board-card {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
/* A FIELD IS A LABEL OVER A VALUE: a one-column, two-row grid. The label
   sits ABOVE its value so the value owns the whole row (MEASURED at 320:
   240px against 140.9px of "you@example.com" at the 16px iOS floor). */
.board .board-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto;
  row-gap: 8px;
  padding: 0;
  border: 0;
}
.board .board-row-k {
  grid-column: 1;
  grid-row: 1;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  line-height: 22px;
  color: var(--ui-ink-2);
}
.board .board-row > input,
.board .board-row > .password-wrap {
  grid-column: 1;
  grid-row: 2;
  min-width: 0;
}
/* The field keeps `.auth-field input`'s 16px type and 44px floor and takes the
   new box: 52px, a sunken fill, no border at rest, the 12px radius. */
.board .board-row input {
  height: 52px;
  padding: 0 16px;
  border: 0;
  border-radius: var(--ui-r-m);
  background: var(--ui-sunken);
  color: var(--ui-ink);
  font-weight: 400;
  box-shadow: none;
  transition: background-color var(--ui-t-state) var(--ui-ease-out), box-shadow var(--ui-t-state) var(--ui-ease-out);
  /* THE EMAIL FIELD CARRIES dir="ltr" AND THAT USED TO STRAND ITS VALUE ON THE
     FAR SIDE OF ITS ROW. `match-parent` resolves against the PARENT's
     direction, so the value lands where its own label is in BOTH languages
     while the input keeps running left-to-right inside itself. `start` for a
     browser that knows neither; the prefixed value is the shipping path on
     Blink and WebKit; the unprefixed line last. */
  text-align: start;
  text-align: -webkit-match-parent;
  text-align: match-parent;
}
.board .board-row input::placeholder { font-weight: 400; color: var(--ui-ink-3); opacity: 1; }
.board .auth-field input:hover:not(:focus) { background: var(--ui-sunken-2); }
/* The eye keeps its reservation: `.password-wrap input` above sets
   padding-inline-end at (0,1,1) and the `padding: 0 16px` here is (0,2,1),
   which WINS whatever the order -- so without this line the eye sits on top of
   the last character typed. 46 = the 44px button plus the 2px it is inset by. */
.board .board-row .password-wrap input { padding-inline-end: 46px; }
/* THE EYE IS 44px: the shared button is 34 x 34, under the touch floor. */
.board .password-toggle {
  width: 44px;
  height: 44px;
  inset-inline-end: 2px;
  border-radius: var(--ui-r-m);
  color: var(--ui-ink-2);
}
.board .password-toggle:hover { background: var(--ui-brand-soft); color: var(--ui-brand); }
/* Focus: a white fill, a brand ring inside and the soft focus halo outside. */
.board .auth-field input:focus,
.board .auth-field input:focus-visible {
  outline: none;
  background: var(--ui-surface);
  box-shadow: inset 0 0 0 2px var(--ui-brand), var(--ui-focus);
}
.board .auth-lang:focus-visible,
.board .password-toggle:focus-visible,
.board a.action:focus-visible,
.board .auth-form button.action:focus-visible {
  outline: 2px solid var(--ui-brand);
  outline-offset: 2px;
  box-shadow: none;
}
/* Only a field the person touched and left wrong. */
.board .auth-field input:user-invalid { box-shadow: inset 0 0 0 2px var(--ui-bad); }
.board .auth-field input:user-invalid:focus { box-shadow: inset 0 0 0 2px var(--ui-bad), var(--ui-focus); }

/* ---- the link under the fields (Forgot password, the resend line) ---------- */
.board .board-aside {
  margin: -4px 0 0;
  font-size: 14px;
  line-height: 22px;
  text-align: start;
  color: var(--ui-ink-2);
}
.board .board-aside a,
.board .auth-forgot {
  font-size: 14px;
  font-weight: 600;
  color: var(--ui-brand);
  text-decoration: none;
}
.board .board-aside a:hover,
.board .auth-forgot:hover { color: var(--ui-brand-press); text-decoration: underline; text-underline-offset: 3px; }

/* ---- the line between /verify's two forms ------------------------------------ */
.board .board-sep {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 4px 0;
  font-size: 14px;
  line-height: 22px;
  color: var(--ui-ink-3);
}
.board .board-sep::before,
.board .board-sep::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--ui-line);
}

/* ---- the dock ------------------------------------------------------------------- */
/* `position: sticky; bottom: 0` inside the full-height column: the primary
   action sits at the bottom of the VIEWPORT while there is page left below it
   and settles at the end of the document when there is not -- in thumb reach
   without ever floating over the last field. A shadow, never a line.
   env(safe-area-inset-bottom) RESOLVES TO 0px HERE and that is correct: these
   pages do not set viewport-fit=cover. */
.board .board-sticky {
  position: sticky;
  bottom: 0;
  z-index: 2;
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 16px calc(16px + env(safe-area-inset-bottom, 0px));
  background: var(--ui-surface);
  border: 0;
  box-shadow: var(--ui-e-dock);
}
/* /verify's dock carries one line: no band, no shadow. */
.board .board-sticky-plain {
  position: static;
  box-shadow: none;
}
/* THE PRIMARY BUTTON: 52px on a phone, the 12px radius, brand fill and its
   own shadow, 16/600. (0,3,1) beats `.auth-form button.action` (0,2,1) and
   public/style.css's `button.action` (0,1,1); the base rule is left alone
   because it states the 44px floor. */
.board .auth-form button.action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin: 0;
  min-height: 52px;
  padding: 0 24px;
  border: 0;
  border-radius: var(--ui-r-m);
  background: var(--ui-brand);
  color: var(--ui-on-brand);
  box-shadow: var(--ui-e-brand);
  font-size: 16px;
  font-weight: 600;
  line-height: 24px;
  letter-spacing: normal;
  text-transform: none;
  transition: background-color var(--ui-t-press) var(--ui-ease-out), transform var(--ui-t-press) var(--ui-ease-out);
  -webkit-tap-highlight-color: transparent;
  /* The in-flight ring below is positioned against this box. */
  position: relative;
}
.board .auth-form button.action:hover:not(:disabled) { background: var(--ui-brand-press); color: var(--ui-on-brand); }
.board .auth-form button.action:active:not(:disabled) { transform: scale(0.98); background: var(--ui-brand-press); }
/* The same box for a link that looks like the button (the check-your-email
   dock's "send it again"). */
.board a.action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 52px;
  padding: 0 24px;
  border-radius: var(--ui-r-m);
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  text-decoration: none;
}
/* The secondary button: a white surface with resting depth and no border.
   (0,4,0) on hover beats public/style.css's `button.action:hover:not(:disabled)`
   (0,3,1), which would turn the quiet button blue. */
.board .action-secondary,
.board .auth-form button.action.action-secondary {
  background: var(--ui-surface);
  color: var(--ui-ink);
  border: 0;
  box-shadow: var(--ui-e1), inset 0 0 0 1px var(--ui-line);
}
.board .action-secondary:hover:not(:disabled),
.board .auth-form button.action.action-secondary:hover:not(:disabled) {
  background: var(--ui-sunken);
  color: var(--ui-ink);
}
/* PRESSED, AND THE PAGE SAYS SO. `button.action:disabled` takes the button to
   0.35, which on a slow phone is indistinguishable from one that has switched
   itself off, so the next thing a thumb does is press it again. A request in
   flight is the opposite of a dead control: the fill goes DARKER, and a ring
   turns at the inline start. (0,4,1) beats `button.action:disabled`. The label
   does not move: the ring is absolutely positioned in the button's padding. */
.board .auth-form button.action[aria-busy="true"] {
  opacity: 1;
  background: var(--ui-brand-press);
  cursor: progress;
}
.board .auth-form button.action[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset-inline-start: 18px;
  top: 50%;
  width: 18px;
  height: 18px;
  margin-top: -9px;
  border: 2px solid var(--ui-brand-line);
  border-top-color: var(--ui-on-brand);
  border-radius: 50%;
  animation: board-spin 700ms linear infinite;
}
@keyframes board-spin { to { transform: rotate(360deg); } }

/* THE REFUSAL AND THE GOOD NEWS: a tinted note with an icon and the words,
   never colour alone. */
.board .auth-error,
.board .auth-success {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  border: 0;
  border-radius: var(--ui-r-m);
  padding: 12px 16px;
  font-size: 14px;
  font-weight: 500;
  line-height: 22px;
}
.board .auth-error[hidden],
.board .auth-success[hidden] { display: none; }
.board .auth-error {
  background: var(--ui-bad-tint);
  color: var(--ui-bad-deep);
}
.board .auth-success {
  background: var(--ui-ok-tint);
  color: var(--ui-ok);
}
.board .auth-error::before,
.board .auth-success::before {
  content: "!";
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--ui-bad);
  color: var(--ui-on-brand);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
}
.board .auth-success::before { content: "\2713"; background: var(--ui-ok); }
/* The switch line under the button. No rule above it and no margin: the dock's
   own gap places it. The 44px hit area hangs DOWN from the link, not centred
   on it, so it never reaches back into the button above. */
.board .board-sticky .auth-switch {
  margin: 0;
  padding: 4px 0 0;
  border-top: 0;
  font-size: 14px;
  line-height: 22px;
  color: var(--ui-ink-2);
}
.board .board-sticky .auth-switch a {
  font-weight: 600;
  color: var(--ui-brand);
  text-decoration: none;
}
.board .board-sticky .auth-switch a:hover { color: var(--ui-brand-press); text-decoration: underline; text-underline-offset: 3px; }
.board .auth-switch a::after {
  top: 0;
  transform: none;
}
.board .turnstile-slot { margin: 0; }

/* ---- "Check your email" ------------------------------------------------------ */
.board .board-done {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
.board .board-done[hidden] { display: none; }
.board .board-done-body {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 32px 16px;
  text-align: center;
}
.board .board-mark-badge {
  width: 72px;
  height: 72px;
  border-radius: var(--ui-r-l);
  background: var(--ui-tint);
  color: var(--ui-brand);
  display: flex;
  align-items: center;
  justify-content: center;
}
.board .board-done-sub { max-width: 320px; }
.board .board-done-sub bdi { font-weight: 600; color: var(--ui-ink); }

/* ---- >= 1024px: two columns, centred, no dock -------------------------------- */
@media (min-width: 1024px) {
  /* The paper itself: the brand side is not a panel any more (owner,
     2026-10-20: the logo, big, on the page). */
  .board .board-shell { background: var(--ui-bg); }
  .board .board-appbar {
    width: 100%;
    max-width: 1240px;
    height: 72px;
    margin: 0 auto;
    padding: 0 32px;
  }
  .board .auth-stage {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 460px;
    align-items: center;
    align-content: center;
    column-gap: 72px;
    width: 100%;
    max-width: 1240px;
    margin: 0 auto;
    padding: 24px 32px 88px;
  }
  /* The brand side: in DOM order first, so it takes the START column (the
     right in Arabic, the left in English) with no [dir] fork. The full logo,
     the headline in Aqlama blue, the diamond line, centred. */
  .board .auth-hero {
    align-self: stretch;
    align-items: center;
    justify-content: center;
    gap: 14px;
    min-height: 520px;
    padding: 48px 0;
    text-align: center;
  }
  .board .auth-hero-logo { width: 360px; margin-bottom: 20px; }
  .board .auth-hero .auth-hero-title { color: var(--ui-brand-press); }
  .board .auth-hero .auth-hero-sub { color: var(--ui-ink-3); }
  .board .auth-hero-wide { display: block; }
  .board .auth-hero-title {
    max-width: none;
    font-size: 40px;
    line-height: 52px;
    letter-spacing: -0.015em;
  }
  .board .auth-hero-title:lang(ar) { line-height: 62px; letter-spacing: 0; }
  .board .auth-hero-sub { max-width: 34ch; font-size: 18px; line-height: 28px; }
  .board .auth-wave { height: 56px; margin-top: 20px; }
  /* The form as a card. */
  .board .auth-sheet {
    flex: none;
    margin: 0;
    padding: 40px;
    border-radius: var(--ui-r-xl);
  }
  .board .board-scroll { padding: 0; gap: 24px; }
  .board .board-intro-title,
  .board .auth-sheet-title { font-size: 28px; line-height: 36px; }
  .board .board-intro-title:lang(ar),
  .board .auth-sheet-title:lang(ar) { line-height: 44px; }
  /* No dock on a desktop: the actions are the card's own foot. */
  .board .board-sticky {
    position: static;
    padding: 24px 0 0;
    background: transparent;
    box-shadow: none;
  }
  .board .auth-form button.action,
  .board a.action { min-height: 48px; }
  .board .board-done-body { padding: 8px 0 24px; }
}


/* ------------------------------------------------------------------
   E2 (spec E section 4.1): the honeypot's container and the Turnstile slot.
   .visually-hidden takes the honeypot out of sight AND out of the layout
   without `display:none`, which some form-filling bots skip. A person never
   sees it, and aria-hidden plus tabindex=-1 keep it out of a screen reader and
   the tab order. .turnstile-slot is EMPTY until a script renders the widget
   into it -- which happens only while FEATURE_PEOPLE is on and a site key is
   configured -- so an empty slot takes no room.
------------------------------------------------------------------ */
.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.turnstile-slot { margin: 0 0 10px; }
.turnstile-slot:empty { display: none; }

@media (prefers-reduced-motion: reduce) {
  /* THE RING STOPS TURNING AND DOES NOT DISAPPEAR. It is the only thing on the
     button that says a request is in flight; what goes is the motion, not the
     signal. */
  .board .auth-form button.action[aria-busy="true"]::after { animation: none; }
}
