/*
 * The apex signup page, wearing the same ground and the same plate the login
 * page wears (specs/2026-09-07-login-bold-design.md §4.2). Brand rules per
 * stckstck/brand; hex lives in :root and nowhere else.
 *
 * TOKEN BLOCK: copied VERBATIM from public/styles.css (the login page), which
 * copied it from the website repo. Source: website src/styles/tokens.css.
 * DEVIATIONS: none in the brand block; one in the role tokens, below. Until
 * there is a shared token package (there is not — see the workspace
 * CLAUDE.md §4), copying and naming the source is the rule; a deviation has
 * to be justified here, at the head of the copy.
 *
 * ADDED HEX, justified at the top of the copy (root CLAUDE.md §4). This :root
 * copies brand/tokens/tokens.css: --linie-hell and --orange-text come from it
 * 1:1. --kohle-3, --gold and --rot are NOT in it — they are decided
 * in the Desk's apps/app/sheet-app/src/styles/tokens.css (--kohle-3 also in
 * apps/admin/web/src/styles/tokens.css, „a third dark step") and are copied
 * from there unchanged. Nothing invented, no value adjusted.
 *
 * ONE DEVIATION FROM SPEC §2.12, for the same reason public/styles.css has
 * it: the role tokens sit on :root, not on `.login`. `body`'s own
 * `background: var(--g-bg)` (the no-flash rule, §3.4) sits OUTSIDE the
 * `.login`-classed <main>, so a `.login`-scoped custom property would not
 * reach it. The light reserve still sits on `.login[data-theme='hell']`
 * (§2.11), exactly as public/styles.css does.
 *
 * THE ONE THING THIS PAGE HAS THAT THE LOGIN PAGE DOES NOT is a third-party
 * iframe it cannot style: Stripe's Payment Element. Its inside is parametrized
 * from signup.js's `appearance.variables`, which is why three hex values live
 * in that file — the only sanctioned hex outside a :root block in this repo.
 *
 * THE FOUR-STEP RAIL (`.rail`) IS UNCHANGED BY THIS CUT (spec §4.2, §9.3), so
 * it moves onto the plate exactly as it was — but the plate is a lighter
 * ground than the old page's, and `.rail-step`'s resting `--stahl` at 11px
 * measures 3.15:1 there (was 3.44:1 on the old background), below AA's
 * 4.5:1 for text this size. Not fixed here: the brief froze the rail byte
 * for byte and this is a colour value, not a copy error. §9.3 decides.
 */

:root {
  --kohle: #141414;
  --kohle-2: #1d1d1b;
  --kohle-3: #262624;
  --papier: #f4f4f1;
  --orange: #e8641f;
  --orange-dunkel: #d5560f;
  --orange-text: #b74f18;
  --stahl: #6b6b66;
  --nebel: #9a9a94;
  --linie: #2a2a2a;
  --linie-hell: #dddbd4;
  --gold: #c9a227;
  --rot: #e5484d;
  --sans: 'Schibsted Grotesk', 'Helvetica Neue', Arial, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;

  /* motion */
  --t-push: 0.42s;
  --ease-push: cubic-bezier(0.4, 0, 0.2, 1);
  --t-base: 140ms;
  --ease: cubic-bezier(0.2, 0.6, 0.3, 1);

  /* the ten role tokens (§2.12), dark */
  --plate: var(--kohle-2);
  --plate-line: var(--linie);
  --plate-line-2: var(--kohle-3);
  --ink: var(--papier);
  --ink-2: rgba(244, 244, 241, 0.8);
  --ink-3: var(--nebel);
  --ink-off: var(--stahl);
  --field: var(--kohle);
  --accent-ink: var(--orange);
  --on-accent: var(--kohle);

  /* the ground's four (§3.3), the last three read by ground.js */
  --g-bg: var(--kohle);
  --g-line: rgba(244, 244, 241, 0.13);
  --g-ink: rgba(244, 244, 241, 0.34);
  --g-accent: var(--orange);
}

/* Not a slower animation — no animation (§6.6). */
@media (prefers-reduced-motion: reduce) {
  :root {
    --t-push: 0ms;
    --t-base: 0ms;
  }
}

/* THE LIGHT RESERVE (§2.11), inert — nothing sets `data-theme`. */
.login[data-theme='hell'] {
  --plate: var(--papier);
  --plate-line: var(--linie-hell);
  --plate-line-2: color-mix(in srgb, var(--kohle) 13%, var(--papier));
  --ink: var(--kohle);
  --ink-2: color-mix(in srgb, var(--kohle) 84%, transparent);
  --ink-3: color-mix(in srgb, var(--kohle) 67%, transparent);
  /* --stahl, NOT --nebel: --nebel on Papier is 2.57:1 (R-5). */
  --ink-off: var(--stahl);
  --field: color-mix(in srgb, var(--kohle) 4%, var(--papier));
  /* Full --orange is 3.04:1 on Papier and cannot be ink there. */
  --accent-ink: var(--orange-text);
  --on-accent: var(--kohle);
  --g-bg: color-mix(in srgb, var(--kohle) 5%, var(--papier));
  --g-line: rgba(20, 20, 20, 0.15);
  --g-ink: rgba(20, 20, 20, 0.38);
  --g-accent: var(--orange-text);
}

/* Variable Fonts, selbst gehostet (latin-Subset, eine woff2 je Familie) — the
   SHARED files at the assets root, the same two the login page loads. Not
   copied into this directory: one typeface, one cache entry. */
@font-face {
  font-family: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('/fonts/schibsted.woff2') format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url('/fonts/jetbrains.woff2') format('woff2');
}

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  /* --g-bg: no flash before ground.js paints. */
  background: var(--g-bg);
  color: var(--ink);
  font-family: var(--sans);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

button,
input {
  font: inherit;
  color: inherit;
}

/*
 * `hidden` must beat the layout rules below. `.card form` sets display:flex,
 * and a bare attribute selector loses to a class selector on specificity —
 * which showed every step of the form at once on the login page. Four steps
 * here instead of two, so the same rule matters four times over. Pinned by
 * test/loginProxy.workers.test.ts.
 */
[hidden] {
  display: none !important;
}

:focus-visible {
  outline: 2px solid var(--orange);
  outline-offset: 3px;
}

/* ---------------------------------------------------------------- layout */

.page {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: var(--g-bg);
  color: var(--ink);
}

/* The desk. The clamps hit 1fr / 500px, gap 96 at 1440 and stop the page
   scrolling sideways below that — same shell the login page uses (§4). */
.wrap {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 40px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(340px, 40vw, 500px);
  gap: clamp(40px, 6.7vw, 96px);
  align-items: center;
}

.locale-switch {
  position: absolute;
  top: -40px;
  right: 40px;
  display: flex;
  align-items: center;
  gap: 7px;
  font: 700 11px/1 var(--mono);
  letter-spacing: 0.12em;
  color: var(--ink-3);
}

.locale-switch button {
  padding: 5px 2px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

.locale-switch button[aria-pressed='true'] {
  border-bottom-color: var(--accent-ink);
  color: var(--ink);
}

/* THE GROUND (§3.4). `fixed`: the page can outgrow the viewport, and an
   absolute ground would grow with it (R-12). */
.ground {
  position: fixed;
  inset: 0;
  z-index: 0;
  background: var(--g-bg);
  pointer-events: none;
}

.ground canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* ------------------------------------------------------------- wordmark */

.mark-col {
  display: flex;
  flex-direction: column;
  gap: 30px;
  align-items: flex-start;
  min-width: 0;
}

.home {
  text-decoration: none;
  color: var(--ink);
  display: inline-flex;
}

/* The website's stacked wordmark: each line is justified edge to edge inside
   a fixed 3.35em box, so STACK sits exactly above STOCK. The order is never
   swapped, and the accent letters are the A and the O. */
.wordmark {
  display: flex;
  flex-direction: column;
  width: 3.35em;
  font-family: var(--sans);
  font-weight: 900;
  font-size: clamp(76px, 9.2vw, 132px);
  line-height: 0.9;
  letter-spacing: -0.01em;
}

.row {
  display: flex;
  justify-content: space-between;
}

.accent {
  color: var(--accent-ink);
}

.claim {
  font-size: 19px;
  line-height: 1.6;
  color: var(--ink-3);
  max-width: 26ch;
  text-wrap: pretty;
}

.mono-line {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.3;
  letter-spacing: 0.22em;
  color: var(--ink-3);
}

/* ----------------------------------------------------------------- copy */

/* The plate's inside: one column, one gap — same numbers public/styles.css
   uses (§2.1 / §2.2). */
.card-col {
  display: flex;
  flex-direction: column;
  gap: 15px;
  padding: 38px 36px 34px;
}

/* THE PLATE (§2.3), the surface only. Opaque — „Linien statt Glas" — one
   hairline border, and the pictogram's crossbar as an INSET shadow, so the
   band belongs to the plate. */
.plate {
  position: relative;
  z-index: 1;
  background: var(--plate);
  border: 1px solid var(--plate-line);
  box-shadow: inset 0 3px 0 var(--orange);
}

.eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.3;
  letter-spacing: 0.28em;
  color: var(--accent-ink);
}

h1 {
  font-size: 40px;
  font-weight: 900;
  line-height: 1.06;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.sub {
  font-size: 15.5px;
  line-height: 1.55;
  color: var(--ink-3);
  max-width: 40ch;
  text-wrap: pretty;
}

/* ----------------------------------------------------------------- rail */

/*
 * Four steps, drawn as a row of lines rather than as a bar that fills. A
 * filling bar implies progress the user has not made yet; a line per step
 * states exactly where they are. The step numbers are tabular so the row's
 * width does not change between 01 and 04.
 */
.rail {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  list-style: none;
  padding: 0;
  margin-top: 12px;
  /* The rail's „E-MAIL" and the field's „E-MAIL-ADRESSE" are the same 11 px
     mono caps and read as one wrapped string at 0 px apart (B-1). */
  margin-bottom: 15px;
}

.rail-step {
  display: flex;
  flex-direction: column;
  gap: 4px;
  border-top: 2px solid var(--linie);
  padding-top: 8px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.3;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  /* --stahl is 3.15:1 at 11 px and fails AA; --ink-3 is 5.97:1 (§9.3). */
  color: var(--ink-3);
}

.rail-num {
  font-variant-numeric: tabular-nums;
}

/* --ink-2 (10.17:1), so `done` still reads a tier above `todo`'s --ink-3. */
.rail-step[data-state='done'] {
  border-top-color: var(--stahl);
  color: var(--ink-2);
}

.rail-step[data-state='current'] {
  border-top-color: var(--orange);
  color: var(--papier);
}

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

/* A transparent box: the forms and the status as one block — the plate is
   the one surface now, so `.card` no longer draws its own (§4). */
.card {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.card form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Mono uppercase caption above a field — the website's `.label` idiom.
   Uppercase is allowed here precisely because it is a Mono label; the BUTTON
   below stays mixed case, per the copy doc's rule 6. */
.label {
  display: block;
  margin-bottom: 7px;
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.3;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* A class on the <input> itself — the login page's `.field` idiom (§2.5).
   Resting border --ink-off, NOT --plate-line-2 (R-4). */
.field {
  width: 100%;
  min-height: 50px;
  padding: 0 14px;
  background: var(--field);
  border: 1px solid var(--ink-off);
  color: var(--ink);
  /* 16px: anything smaller and iOS zooms the page on focus. */
  font-size: 16px;
}

.field::placeholder {
  color: var(--ink-off);
}

/* The outline is kept transparent, so forced-colors mode still paints one. */
.field:focus-visible {
  outline-color: transparent;
  outline-offset: 0;
  border-color: var(--accent-ink);
  box-shadow: 0 0 0 2px var(--plate), 0 0 0 4px var(--accent-ink);
}

.field[aria-invalid='true'] {
  border-color: var(--rot);
}

/* THE CODE STEP (m-7(a), T6+T7 review). Lifted verbatim from public/styles.css
   so both doors ask for the same six digits the same way: one input, six
   drawn slots. `one-time-code` plus a pasted code both survive one input. */
.code-in {
  min-height: 64px;
  padding: 0 8px;
  font-family: var(--mono);
  font-size: 26px;
  letter-spacing: 0.52em;
  text-indent: 0.52em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.code-slots {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.code-slots span {
  flex: 1;
  height: 2px;
  /* --ink-off (3.15:1); --plate-line-2 is 1.11:1 and invisible (B-8). */
  background: var(--ink-off);
  transition: background var(--t-base) var(--ease);
}

.code-in:valid ~ .code-slots span {
  background: var(--orange);
}

/* 65 px is a MINIMUM: the staging test key hangs a red band under the widget
   and the box grows. A fixed height would hide it (login page's `.check`
   rule, same reason). */
.turnstile:not(:empty) {
  min-height: 65px;
}

/* And it is reserved BEFORE the widget exists, or the primary CTA jumps 32 px
   under the pointer the moment Turnstile mounts (B-3) — `:not(:empty)` above
   is false in exactly that window. The id is safe here: /signup/ has no
   lazily rendered resend widget, the one reason /login/ uses `.check`. */
#turnstile-widget {
  min-height: 65px;
}

/* THE CHALLENGE MUST NOT PUSH THE PLATE OFF THE PHONE. `overflow-x: auto`
   keeps what a 320 px screen is short in this box (login page's F-01 fix). */
.turnstile {
  max-width: 100%;
  overflow-x: auto;
}

.sent-to {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-3);
}

.sent-to span {
  font-family: var(--mono);
  color: var(--ink);
  word-break: break-all;
}

/* -------------------------------------------------------- payment step */

/*
 * Stripe's iframe. We own the box, not the contents: the height is reserved so
 * the card does not jump when the element finishes loading, and the inside is
 * parametrized from signup.js's appearance variables.
 */
.payment-element {
  min-height: 200px;
}

/* Nothing mounted, nothing reserved. Stripe inserts its container the moment
   mount() runs, so this only ever matches on the one path where the Element
   never arrives — the 3DS redirect return, which restores the payment step
   from a document that has no Element in it. A 200px void that will never fill
   is a promise the page cannot keep. */
.payment-element:empty {
  min-height: 0;
}

/* The invoice address, mounted in the same moment and out of the same Elements
   group. Taller than the card because it is six labelled rows rather than one —
   and the reservation earns its keep here more than anywhere on this page: the
   two consent boxes and the submit sit directly BELOW it, and a form that grows
   into place under a finger already on its way to the button is how a click
   lands where the button used to be. Same :empty reset, same reason. */
.address-element {
  min-height: 300px;
}

.address-element:empty {
  min-height: 0;
}

/* ------------------------------------------------------ plan picker */

/*
 * The tariff cards (stckstck/admin#36, pricing design 2026-09-22): each card
 * is a <label> around a real radio, so selection — pointer, Tab, Arrow,
 * Space — is the platform's, and the selected card is painted from the
 * input's own state via :has(). No click-only div anywhere.
 */
.plan-row {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  border: 0;
  padding: 0;
  margin: 0;
}

.plan-row legend {
  padding: 0;
}

.plan-intro {
  margin-top: -3px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-3);
}

/* Two-up while the plate has room (>= 2×200px plus the gap), stacked on a
   phone — the plate itself narrows with the viewport below 860px. */
.plan-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px;
}

.plan-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 16px 18px;
  background: var(--field);
  border: 1px solid var(--ink-off);
  cursor: pointer;
}

/* The card answers its input: chosen and focusing states are the input's. */
.plan-card:has(input:checked) {
  border-color: var(--orange);
  box-shadow: inset 0 0 0 1px var(--orange);
}

.plan-card:has(input:focus-visible) {
  border-color: var(--accent-ink);
  box-shadow: 0 0 0 2px var(--plate), 0 0 0 4px var(--accent-ink);
}

.plan-card:has(input[aria-invalid='true']) {
  border-color: var(--rot);
}

.plan-choice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.plan-name {
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.plan-row input[type='radio'] {
  accent-color: var(--orange);
  width: 18px;
  height: 18px;
  margin: 0;
  flex: none;
}

.plan-for {
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--ink-3);
}

.plan-price {
  margin-top: 2px;
  font-size: 13px;
  color: var(--ink-3);
}

.plan-amount {
  margin-right: 4px;
  font-family: var(--sans);
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.plan-limit {
  padding: 10px 0;
  border-top: 1px solid var(--plate-line-2);
  border-bottom: 1px solid var(--plate-line-2);
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
}

.plan-features {
  margin: 2px 0 0;
  padding-left: 18px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink-3);
}

.plan-fine {
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-3);
}

/* The picker's own status line: reuses .status (the left rule, the tones),
   only the top margin differs — the fieldset's gap already spaces it. */
.plan-status {
  margin-top: 0;
}

/* The trial sentence. Set apart by a line, not by a colour: it is the one
   claim on this page a customer is entitled to hold us to. PROSE, not a
   table: tabular-nums here would also set the full stop and the comma to
   digit width in Schibsted Grotesk — „Heute 0 €. Nach" reads with a gap
   before the full stop. The values carry their own tabular-nums where
   alignment matters (the .num spans under .promo-summary).
   (stckstck/admin#28; same cause as .promo-summary, #27.) */
.honest {
  border-left: 2px solid var(--orange);
  padding-left: 14px;
  font-size: 14px;
  line-height: 1.55;
  font-variant-numeric: normal;
  color: var(--ink);
}

.check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-3);
  cursor: pointer;
}

/* accent-color paints the native checkbox in the brand accent without
   rebuilding it — no custom SVG, no pseudo-element, keyboard behaviour and
   the required-attribute semantics intact. */
.check input[type='checkbox'] {
  accent-color: var(--orange);
  width: 18px;
  height: 18px;
  margin-top: 1px;
  flex: none;
}

.check a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.check a:hover {
  color: var(--accent-ink);
}

/* ------------------------------------------------------ promotion code */

/* The field and its button on one line that WRAPS rather than scrolls: at
   360 px the plate's 328 px carry both, and anything narrower drops the button
   under the field instead of pushing the plate sideways (stckstck/admin#27). */
.promo-line {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* A code, not a word: Mono and tabular, like every machine value here. */
.promo-in {
  flex: 1 1 10rem;
  min-width: 0;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}

/* The secondary button: a line in the resting ink, no fill and no Push, so
   the orange edge stays the one primary action on this form (#btn-pay). */
.sbtn {
  flex: 0 0 auto;
  min-height: 50px;
  padding: 0 18px;
  background: transparent;
  border: 1px solid var(--ink-off);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 700;
  font-size: 15px;
  line-height: 1.2;
  cursor: pointer;
}

.sbtn:is(:hover, :focus-visible):not(:disabled) {
  border-color: var(--accent-ink);
}

.sbtn:disabled {
  opacity: 0.45;
  pointer-events: none;
}

.promo-status {
  margin-top: 10px;
}

/* The summary wears .honest (the line, the size): it is a price claim, the
   same kind of sentence a customer is entitled to hold us to. The prose is
   normal-numeral since .honest itself gave up tabular-nums (#28); the
   values below keep tabular-nums on their own span. */
.promo-summary {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 12px;
}

/* The values inside the sentences: the code, the plan, the amounts. */
.promo-summary .num {
  font-family: var(--mono);
  font-size: 0.93em;
  font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------- button */

/* ORANGE IS THE EDGE, NOT THE PLATE — the login page's `.pbtn` idiom (§2.6).
   At rest the plate's surface, a 1 px orange edge, full-contrast text; the
   FILL is only the Push. The spans stay `.dot` / `.lbl` — signup.js reads
   `.lbl` off `button.querySelector('.lbl')`. */
.pbtn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 52px;
  padding: 0 22px;
  background: transparent;
  border: 1px solid var(--orange);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 700;
  font-size: 16px;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
}

.pbtn .dot {
  position: absolute;
  z-index: 1;
  left: 12px;
  top: 50%;
  width: 8px;
  height: 8px;
  margin-top: -4px;
  background: var(--orange);
  transition: transform var(--t-push) var(--ease-push);
}

.pbtn .lbl {
  position: relative;
  z-index: 2;
  transition: color var(--t-base) var(--ease);
}

.pbtn:is(:hover, :focus-visible):not(:disabled) .dot {
  transform: scale(90);
}

.pbtn:is(:hover, :focus-visible):not(:disabled) .lbl {
  color: var(--on-accent);
}

.pbtn:disabled {
  opacity: 0.45;
  pointer-events: none;
}

/* 44 px, the touch-target floor. */
.linkish {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  background: none;
  border: none;
  padding: 0;
  align-self: flex-start;
  font-size: 14px;
  color: var(--ink-3);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.linkish:hover {
  color: var(--accent-ink);
}

/* --------------------------------------------------------------- status */

/*
 * Honest states. The chip idiom comes from the website's draft banner: the
 * accent is carried by the BORDER, the text stays legible, and nothing
 * pulses, glows or animates. An empty status renders nothing at all rather
 * than reserving a box that says something is wrong when nothing is.
 */
.status:empty {
  display: none;
}

.status {
  border-left: 2px solid var(--ink-off);
  padding-left: 13px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-3);
}

.status[data-tone='working'],
.status[data-tone='ok'],
.status[data-tone='error'] {
  color: var(--ink-2);
}

.status[data-tone='working'] {
  border-left-color: var(--ink-3);
}

.status[data-tone='ok'] {
  border-left-color: var(--accent-ink);
}

.status[data-tone='error'] {
  border-left-color: var(--rot);
}

.hint {
  margin-top: 10px;
  padding-left: 16px;
  font-size: 14px;
}

.hint a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.hint a:hover {
  color: var(--accent-ink);
}

/* The collection notice under the three consent boxes (release-notes spec
   D10 / §6.2 #14). It reuses .hint's type scale and corrects exactly one
   thing: the 16px inset belongs to the status block's left rule and has
   nothing to align to here. No new colour, no hex. */
.hint--consent {
  padding-left: 0;
  color: var(--ink-3);
}

/* -------------------------------------------------------- not available */

/* The pre-launch state. Same card frame the flow it replaces used to carry,
   now in role tokens: same numbers, same shape, only the hex is renamed. */
.notice {
  margin-top: 12px;
  background: var(--plate);
  border: 1px solid var(--plate-line);
  border-left: 2px solid var(--orange);
  padding: 32px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink);
}

.notice a {
  color: var(--ink-3);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.notice a:hover {
  color: var(--accent-ink);
}

/* Compact disclosure shown above every step of the friendly signup flow. */
.notice--friendly {
  margin: 0 0 15px;
  padding: 12px 14px;
  font-size: 13px;
  line-height: 1.5;
}

/* --------------------------------------------------------------- switch */

/* The way to the OTHER page, at the TOP of the plate, phone too (R-1). */
.switch {
  font-size: 13px;
  color: var(--ink-3);
}

.switch a {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.switch a:hover {
  color: var(--accent-ink);
}

/* The legal row and the social row: both are Mono because both are labels,
   both sit at the weakest LEGIBLE text colour on Kohle (--stahl is not a
   text colour here — root CLAUDE.md §4), and neither competes with the form
   above them. `a` without an href renders as plain text — which is what the
   legal row is until signup.js fills the URLs in. */
.legal-links,
.social {
  font-family: var(--mono);
  font-size: 11px;
  line-height: 1.6;
  letter-spacing: 0.12em;
  color: var(--ink-3);
}

.legal-links {
  margin-top: 8px;
}

.social {
  margin-top: 4px;
}

.legal-links a,
.social a {
  color: var(--ink-3);
  text-decoration: none;
}

.legal-links a:hover,
.social a:hover {
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ------------------------------------------------------------ responsive */

/* 860px is the website's one breakpoint. The phone: three bands, the
   wordmark on the floor of what is left, the plate nailed to the bottom edge
   where the thumb is — same anatomy public/styles.css uses (§2.1). */
@media (max-width: 860px) {
  .wrap {
    display: flex;
    flex: 1;
    flex-direction: column;
    align-items: stretch;
    max-width: none;
    padding: 0;
  }
  .locale-switch {
    top: 14px;
    right: 16px;
  }
  .mark-col {
    flex: 1;
    justify-content: flex-end;
    gap: 12px;
    padding: 24px 20px 26px;
  }
  .wordmark {
    font-size: 76px;
  }
  .claim {
    font-size: 15px;
    line-height: 1.5;
    max-width: 22ch;
  }
  .mono-line {
    font-size: 10px;
  }
  /* Decorative, and R-1 has just spent the phone's spare line (R-2). */
  .eyebrow {
    display: none;
  }
  .card-col {
    gap: 14px;
    padding: 20px 16px max(26px, env(safe-area-inset-bottom));
  }
  .plate {
    border: 0;
    border-top: 1px solid var(--plate-line);
  }
  h1 {
    font-size: 26px;
  }
  .sub {
    font-size: 14px;
  }
  .notice {
    padding: 24px;
  }
  /* Four mono labels do not fit across a phone; the numbers alone still say
     where the flow is, and the current step keeps its name. */
  .rail-step .rail-name {
    display: none;
  }
  .rail-step[data-state='current'] .rail-name {
    display: block;
  }
}

/* The plate keeps all of its padding, so the band above gives the room back
   on a small phone — same query public/styles.css uses. */
@media (max-width: 400px) {
  .mark-col {
    gap: 10px;
    padding-top: 20px;
    padding-bottom: 22px;
  }
}
