/*
 * „Die kühne Anmeldung" — specs/2026-09-07-login-bold-design.md. Brand rules
 * per stckstck/brand; hex lives in :root and nowhere else.
 *
 * 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.
 *
 * TWO DEVIATIONS, both because /login/link shares this file. The role tokens
 * sit on :root, not on `.login` (§2.12), so a page without that class still
 * resolves them; the light reserve stays on `.login[data-theme='hell']`. And
 * the shell, the wordmark band and the plate are BASE rules — §4 shares this
 * shell across all three pages. T7 gives /login/link its plate and canvas.
 */

:root {
  /* brand layer — hex lives here and nowhere else */
  --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`. §6.5 lists
   the gaps to close first. */
.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);
  /* Kohle carries further on Papier: the lattice is a notch weaker. */
  --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. */
@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: `.card form` is display:flex and an
   attribute selector loses to a class one; both steps showed at once. */
[hidden] {
  display: none !important;
}

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


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

.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);
}

.ground {
  position: fixed;
  inset: 0;
  z-index: 0;
  background: var(--g-bg);
  pointer-events: none;
}

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


.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;
}

.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;
}

/* --ink-3: --stahl on Kohle is 3.44:1 and this is a string (R-6). */
.mono-line {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.3;
  letter-spacing: 0.22em;
  color: var(--ink-3);
}


/* The plate's inside: one column, one gap, §2.1 / §2.2 padding. */
.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;
}

/* „Du bist abgemeldet." is a HEADLINE (§5.2): #notice REPLACES the step-1
   headline; the `.sub` stays (R-8). `~` is the SIBLING combinator and
   #form-email is a level deeper inside `.card`, so §5.2's own selector would
   never fire. */
#notice:not([hidden]) ~ .card #form-email h1 {
  display: none;
}

/* And it does not survive the step change: login.js never sets `hidden` back
   on #notice, so without this the sign-out headline stacks above „Schau in
   dein Postfach." The subject is step 1 BEING GONE rather than step 2 being
   here, because the plate has a THIRD state since the passkey offer, which
   hides both forms and carries its own h1. Where `:has()` is missing the rule
   is simply dropped. */
.card-col:has(#form-email[hidden]) #notice {
  display: none;
}


/* A transparent box: the forms and the status as one block. */
.card {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

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

/* The spec's `.f-label` under this page's shipped class name. */
.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. Resting border --ink-off, NOT --plate-line-2
   (R-4): --kohle-3 on --kohle-2 is 1.11:1, no boundary at all, 1.4.11. */
.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 (§2.9). One input, six drawn slots: `one-time-code`, the
   keyboard suggestion and a pasted code all survive one input. The bars are
   aria-hidden and light up on `pattern`. The row rests at --ink-off, not
   --plate-line-2, which is 1.11:1 on the plate and invisible. */
.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: 8px 0 12px;
}

.code-slots span {
  flex: 1;
  height: 2px;
  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. */
.check,
.turnstile:not(:empty) {
  min-height: 65px;
}

/* THE CHALLENGE MUST NOT PUSH THE PLATE OFF THE PHONE (MAJOR-3). `flexible`
   needs 300 px, 358 are there at 390, and `overflow-x: auto` keeps what a
   320 px screen is short in this box (F-01). */
.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;
}


/* ORANGE IS THE EDGE, NOT THE PLATE. 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` — login.js reads `.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);
}

/* A disabled resend carries the countdown; only the underline goes. */
.linkish:disabled {
  text-decoration: none;
  cursor: default;
}


/* Its own challenge, its button, and the line that answers „wo ist die
   Mail?". A second, optional action, so it sits under a rule. */
.resend {
  padding-top: 10px;
  border-top: 1px solid var(--plate-line);
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
}

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


/* The accent is on the BORDER, nothing pulses, an empty status renders
   nothing. `error` is --rot, not orange (R-11). */
.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'],
.status[data-tone='note'] {
  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);
}

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


.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);
}


/* MINOR-7: the way off the page during an error state (task-7-report.md). */
.card:has(#status[data-tone='error']) #to-login[hidden] {
  display: flex !important;
}

/* 860px is the website's one breakpoint. The phone (§2.1): three bands, the
   wordmark on the floor of what is left, the plate nailed to the bottom edge
   where the thumb is. */
@media (max-width: 860px) {
  .wrap {
    display: flex;
    flex: 1;
    flex-direction: column;
    /* `center` is vertical in the grid, horizontal here */
    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;
  }
}

/* The plate keeps all of its padding (358 px inner at 390, the widget needs
   300), so the band above gives the room back on a small phone. */
@media (max-width: 400px) {
  .mark-col {
    gap: 10px;
    padding-top: 20px;
    padding-bottom: 22px;
  }
}


/* a1-a3: only the address is mono; a chosen row is an edge, never a fill. */
:is(#pick-for, #none-for) [data-i18n] {
  font-family: inherit;
  color: inherit;
}

/* M2 switch plate (design a4): the business the code is for. */
.tenant-hint {
  padding: 10px 12px;
  border: 1px solid var(--plate-line);
  font-size: 13.5px;
  color: var(--ink-2);
}

.tenant-hint b {
  color: var(--ink);
}

.pick {
  display: grid;
  border: 1px solid var(--plate-line);
}

.pick-row {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  min-height: 62px;
  padding: 10px 14px;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--plate-line);
  text-align: left;
  cursor: pointer;
  color: var(--ink);
}

.pick-row:first-child {
  border-top: 0;
}

.pick-row:hover {
  background: var(--plate-line-2);
}

.pick-row[aria-checked='true'] {
  background: color-mix(in srgb, var(--orange) 16%, transparent);
  box-shadow: inset 2px 0 0 var(--orange);
}

.pick-radio {
  width: 16px;
  height: 16px;
  border: 1px solid var(--ink-off);
  display: grid;
  place-items: center;
}

.pick-row[aria-checked='true'] .pick-radio {
  border-color: var(--orange);
}

.pick-row[aria-checked='true'] .pick-radio::after {
  content: '';
  width: 6px;
  height: 6px;
  background: var(--orange);
}

.pick-main {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.pick-main strong {
  font-size: 16px;
}

.pick-meta {
  font-size: 13px;
  color: var(--ink-3);
}

.pick-tag {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--ink-3);
  border: 1px solid var(--plate-line);
  padding: 2px 6px;
}

.inv {
  display: grid;
  gap: 10px;
}

.inv-card {
  display: grid;
  gap: 10px;
  padding: 14px 16px;
  border: 1px solid var(--plate-line);
  background: var(--field);
}

.inv-what {
  font-size: 15.5px;
  line-height: 1.4;
}

.inv-by {
  font-size: 12.5px;
  color: var(--ink-3);
}

.inv-act {
  display: flex;
  gap: 10px;
  align-items: center;
}

.pbtn.sm {
  min-height: 40px;
  font-size: 14px;
  width: auto;
  padding: 0 18px 0 28px;
}

.inv-act .ghost {
  min-height: 40px;
  padding: 0 16px;
  background: transparent;
  border: 1px solid var(--ink-off);
  color: var(--ink-2);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
}

.inv-act .ghost:hover {
  border-color: var(--ink-3);
  color: var(--ink);
}

.inv-done {
  font-size: 13.5px;
  color: var(--ink-2);
  border-left: 2px solid var(--ink-off);
  padding-left: 12px;
}

.inv-card[data-state='accepted'] .inv-done {
  border-left-color: var(--orange);
}

.badge-row {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.appstore {
  display: inline-block;
  line-height: 0;
}
