/* Moniker — Solari split-flap departure board.
   The board is the product's data model made visible: a code on the left, a real
   destination on the right, a status. Every value that is measured is set in the
   mono; every value that is announced is set in flap lettering. */

@font-face {
  font-family: 'Archivo';
  src: url('/fonts/archivo-var-latin.woff2') format('woff2-variations');
  font-weight: 400 900;
  font-stretch: 62% 125%;
  font-display: swap;
}
@font-face {
  font-family: 'Chivo Mono';
  src: url('/fonts/chivomono-var-latin.woff2') format('woff2-variations');
  font-weight: 300 700;
  font-display: swap;
}

:root {
  /* Board */
  --void: #0c0e10;
  --board: #14171a;
  --slot: #1b1f23;
  --enamel: #383e45;
  --hinge: #0a0c0d;
  --rule: #2a3037;

  /* Ink */
  --flap: #f2e6c9;
  --flap-dim: #8f9299;
  --ink-quiet: #9ba3ac;

  /* Signals */
  --amber: #e8b21c;
  --amber-deep: #b8840b;
  --amber-ink: #17130a;
  --halt: #e0492c;
  --live: #4bb98a;

  --mono: 'Chivo Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --sans: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --gut: clamp(1.15rem, 3.2vw, 2.5rem);
  --ease: cubic-bezier(0.16, 0.84, 0.24, 1);
}

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

html {
  background: var(--void);
  /* The board's own scrollbar, not the platform's. */
  scrollbar-color: var(--enamel) var(--void);
}

body {
  margin: 0;
  min-height: 100vh;
  background:
    /* Slot shading: the board is built of horizontal flap slots, so the ground
       carries their seam rather than a flat fill. */
    repeating-linear-gradient(180deg,
      rgba(255, 255, 255, 0.014) 0 1px,
      transparent 1px 4px),
    radial-gradient(120% 70% at 50% -10%, #1c2126 0%, var(--board) 46%, var(--void) 100%);
  color: var(--flap);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  text-underline-offset: 0.22em;
}

::selection { background: var(--amber); color: var(--amber-ink); }

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

.sprite { position: absolute; }
.sprite symbol { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: square; }

.vh {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: absolute; left: 0.75rem; top: -3.5rem; z-index: 20;
  padding: 0.6rem 1rem;
  background: var(--amber); color: var(--amber-ink);
  font: 600 0.8rem/1 var(--mono); letter-spacing: 0.06em; text-transform: uppercase;
  text-decoration: none;
  transition: top 140ms var(--ease);
}
.skip:focus { top: 0.75rem; }

/* ---------------------------------------------------------------- board frame */

.board {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* The enamel frame: a real board is a bezel around the slots. */
  border: 1px solid var(--enamel);
  border-top-width: 0;
  margin: 0 auto;
  max-width: 1560px;
}

.board__edge {
  position: absolute; inset: 0;
  pointer-events: none;
  /* Inner shadow of the bezel plus the specular line along the top hinge. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    inset 0 0 0 1px rgba(0, 0, 0, 0.5),
    inset 0 22px 40px -22px rgba(0, 0, 0, 0.9);
}

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

.rail {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: clamp(0.9rem, 2.4vw, 1.9rem);
  padding: clamp(0.85rem, 2vw, 1.15rem) var(--gut);
  border-bottom: 1px solid var(--rule);
  background: linear-gradient(180deg, #191d21, #12151800);
}

.plate {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--enamel);
  background: linear-gradient(180deg, #21262b, #171b1f);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
}

.plate--mark {
  padding: 0.42rem 0.85rem;
  font: 800 clamp(0.95rem, 1.5vw, 1.12rem)/1 var(--sans);
  font-stretch: 78%;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--amber);
}

.rail__title {
  margin: 0;
  font: 700 clamp(0.94rem, 1.6vw, 1.12rem)/1 var(--sans);
  font-stretch: 82%;
  letter-spacing: 0.02em;
  color: var(--flap);
}

.rail__station {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  font: 500 0.78rem/1 var(--mono);
}
.rail__station-key {
  color: var(--flap-dim);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.rail__station-value {
  color: var(--flap);
  letter-spacing: 0.03em;
  font-weight: 600;
}

/* -------------------------------------------------------------- column heads */

.heads {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr) auto;
  gap: clamp(0.75rem, 2vw, 1.75rem);
  padding: 0.5rem var(--gut);
  border-bottom: 1px solid var(--rule);
  background: var(--hinge);
}

.heads__cell {
  font: 600 0.68rem/1 var(--mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--flap-dim);
}
.heads__cell--end { text-align: right; }
.heads__cell--num { text-align: right; }

.heads--bay {
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) 5.5rem auto;
}

/* ----------------------------------------------------------------- the desk */

.sheet { flex: 1; }

.desk {
  border-bottom: 1px solid var(--rule);
  background: linear-gradient(180deg, var(--slot), #141719);
}

.desk__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr) auto;
  gap: clamp(0.75rem, 2vw, 1.75rem);
  align-items: start;
  padding: clamp(1.5rem, 4vw, 2.6rem) var(--gut) clamp(1.15rem, 2.6vw, 1.6rem);
}

.field { min-width: 0; }

.label {
  display: block;
  margin: 0 0 0.6rem;
  font: 600 0.68rem/1 var(--mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--flap-dim);
}
.label--end { text-align: right; }

/* The name field: the input is transparent and sits exactly over its own flap
   rendering, so what you type IS the display. One object, not a preview. */

.namefield {
  position: relative;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0 0.1em;
  padding-bottom: 0.7rem;
  border-bottom: 2px solid var(--enamel);
  transition: border-color 160ms var(--ease);
}
.namefield:has(.namefield__input:focus-visible) { border-bottom-color: var(--amber); }
.namefield[data-invalid='true'] { border-bottom-color: var(--halt); }

.namefield__prefix {
  font: 500 clamp(0.95rem, 1.7vw, 1.35rem)/1 var(--mono);
  letter-spacing: 0.01em;
  color: var(--flap-dim);
  white-space: nowrap;
}

/* The slot holds the flap rendering and the real input stacked on one another,
   so it grows with the typed value instead of being a fixed box. It is also the
   size container the tiles measure themselves against, and the carriage they
   scroll inside once a name is longer than the column can show at a legible
   size — a real board moves its rank rather than setting 48 unreadable tiles. */
.namefield__slot {
  position: relative;
  display: grid;
  align-content: center;
  container-type: inline-size;
  overflow: hidden;
  flex: 1 1 8ch;
  min-width: 8ch;
  min-height: clamp(2.1rem, 6.4vw, 4.4rem);
}

/* One tile pitch, one advance. Every tile in the field is exactly `--pitch`
   wide, and the invisible input is set in the mono — a fixed advance — with its
   letter-spacing solved so one character occupies exactly that pitch plus the
   gap. The caret therefore lands on the tile it belongs to at any slot count,
   including a 48-character name that has to scroll.

   0.78em is not arbitrary: `m` is the widest glyph the alias charset allows at
   this weight and stretch, at 0.70em, and the tile has to hold it without
   clipping. Its 2px carries the tile's own border, which does not scale with the
   type. Narrow letters therefore sit in a lot of air, which is what a real board
   looks like — the flap is one size and the letter is whatever it is. */
.namefield__slot .flaps,
.namefield__input {
  --pitch: calc(0.78em + 2px);
  /* The size at which the whole rank still fits the column. Each character costs
     the pitch plus the 2px gap; the count is `slots`, not `slots - 1`, because
     letter-spacing also trails the last character — sized to the tiles alone the
     input would scroll by that one gap and shift a rank that actually fits.
     Below the floor in `max()` the rank stops shrinking and travels instead. */
  --fit: calc((100cqw - var(--slots, 7) * 4px) / (var(--slots, 7) * 0.78));
  font-size: max(1.05rem, min(clamp(2.1rem, 6.4vw, 4.4rem), var(--fit)));
}

.namefield__slot .flaps {
  /* The carriage. `--scroll` mirrors the input's own scrollLeft, so a name too
     long for the column moves its rank under a stationary caret. */
  transform: translateX(calc(-1 * var(--scroll, 0px)));
  will-change: transform;
}

/* Uniform tiles: a board's flaps are all one size, and it is that fixed pitch
   the caret is aligned to. */
.namefield__slot .flap {
  width: var(--pitch);
  min-width: 0;
  padding-left: 0;
  padding-right: 0;
}

.namefield__input {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 1.34em;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  /* Transparent text: the flaps below render the value. The caret stays visible
     and the field stays a real, selectable text input. */
  color: transparent;
  caret-color: var(--amber);
  font-family: var(--mono);
  font-weight: 500;
  line-height: 1.34em;
  letter-spacing: calc(var(--pitch) + 2px - 1ch);
}
.namefield__input:focus { outline: none; }
.namefield__input::selection { background: var(--amber); color: transparent; }
.namefield__input::placeholder { color: transparent; }

/* ------------------------------------------------------------------- flaps */

.flaps {
  display: flex;
  align-items: stretch;
  gap: 2px;
  font: 700 clamp(2.1rem, 6.4vw, 4.4rem)/1 var(--sans);
  font-stretch: 74%;
  letter-spacing: 0.01em;
}

.flap {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0.62em;
  padding: 0.16em 0.05em 0.17em;
  background: linear-gradient(180deg, #24292e 0%, #1a1e22 49%, #171b1e 51%, #0f1214 100%);
  border: 1px solid #2c3238;
  color: var(--flap);
  /* The hinge seam across the middle of every real flap tile. */
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    inset 0 -1px 0 rgba(0, 0, 0, 0.55);
}
.flap::after {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 1px;
  background: var(--hinge);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05);
}

.flap--blank {
  color: var(--flap-dim);
  background: linear-gradient(180deg, #1a1e22 0%, #15181b 49%, #131619 51%, #0d0f11 100%);
}

/* The flip: a tile that just changed drops its top half like a real flap. The
   animation is 130ms and never blocks input — the character is already correct
   when it starts. */
@keyframes flap-drop {
  from { transform: perspective(340px) rotateX(-58deg); filter: brightness(1.5); }
  to   { transform: perspective(340px) rotateX(0deg); filter: brightness(1); }
}
.flap--turn {
  animation: flap-drop 130ms var(--ease) both;
  transform-origin: 50% 50%;
}

/* The small rank used in board rows and the claim plate. No caret is aligned to
   it, so a long name is free to take a second rank rather than push the row
   sideways — which is what a real board does when a destination is too long. */
.flaps--sm {
  font: 700 clamp(1.15rem, 2.6vw, 1.6rem)/1 var(--sans);
  font-stretch: 74%;
  flex-wrap: wrap;
  gap: 1.5px;
}
.flaps--sm .flap { min-width: 0.6em; padding: 0.13em 0.04em 0.14em; }

/* ------------------------------------------------------- hints & destination */

.hint {
  margin: 0.75rem 0 0;
  max-width: 46ch;
  font: 400 0.8rem/1.5 var(--mono);
  color: var(--ink-quiet);
}

.hint--halt { color: #f0a08c; }

.input {
  width: 100%;
  padding: 0.62rem 0 0.7rem;
  border: 0;
  border-bottom: 2px solid var(--enamel);
  background: transparent;
  color: var(--flap);
  font: 500 clamp(0.95rem, 1.35vw, 1.06rem)/1.35 var(--mono);
  letter-spacing: 0.005em;
  transition: border-color 160ms var(--ease);
}
.input::placeholder { color: #6b7278; }
.input:focus-visible { outline: none; border-bottom-color: var(--amber); }
.input[data-invalid='true'] { border-bottom-color: var(--halt); }

.resolved {
  margin: 0.75rem 0 0;
  font: 500 0.82rem/1.55 var(--mono);
  color: var(--flap-dim);
  overflow-wrap: anywhere;
}
.resolved__empty { color: #6b7278; }
.resolved__host { color: var(--flap); font-weight: 600; }
.resolved__path { color: var(--flap-dim); }
.resolved__scheme {
  color: var(--live);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: 0.72rem;
  margin-right: 0.5rem;
}
.resolved__halt { color: #f0a08c; }

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

.field--status { justify-self: end; }

.status {
  display: block;
  text-align: right;
  font: 600 0.86rem/1.3 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--flap-dim);
  white-space: nowrap;
}
.status[data-tone='ready'] { color: var(--flap-dim); }
.status[data-tone='live'] { color: var(--live); }
.status[data-tone='halt'] { color: var(--halt); }
.status[data-tone='work'] { color: var(--amber); }

/* The working state pulses the way a board's own indicator does. */
@keyframes status-pulse { 50% { opacity: 0.35; } }
.status[data-tone='work'] { animation: status-pulse 900ms ease-in-out infinite; }

/* ------------------------------------------------------------- action plate */

.desk__action { padding: 0 var(--gut) clamp(1.5rem, 3.4vw, 2.2rem); }

.plate--go {
  width: 100%;
  padding: clamp(0.95rem, 2vw, 1.2rem) 1.5rem;
  border: 1px solid var(--amber-deep);
  background: linear-gradient(180deg, #f0c33c, var(--amber) 52%, #cf9d10);
  color: var(--amber-ink);
  font: 800 clamp(0.95rem, 1.7vw, 1.15rem)/1 var(--sans);
  font-stretch: 80%;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45), 0 3px 0 -1px #8f6706;
  transition: transform 110ms var(--ease), filter 140ms var(--ease), box-shadow 110ms var(--ease);
}
.plate--go:hover { filter: brightness(1.08); }
.plate--go:active {
  transform: translateY(2px);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 1px 0 -1px #8f6706;
}
.plate--go[disabled] {
  cursor: not-allowed;
  background: linear-gradient(180deg, #4a4f55, #3a3f44);
  border-color: #4a4f55;
  color: #9ba3ac;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}
.plate--go[data-busy='true'] { cursor: progress; }

/* Claimed: the plate does not move or change size, it changes job. The pointer
   is already there, so copying costs no travel. */
.plate--go[data-mode='copy'] {
  background: linear-gradient(180deg, #6fd6a6, var(--live) 52%, #2f9a6e);
  border-color: #2f9a6e;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4), 0 3px 0 -1px #1f6e4e;
  color: #08130e;
}
.plate--go[data-mode='copy']:active { box-shadow: inset 0 1px 0 rgba(255,255,255,0.28), 0 1px 0 -1px #1f6e4e; }

/* ------------------------------------------------------------- key handover */

.keynote {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0 0.85rem;
  margin: 0 var(--gut) clamp(1.5rem, 3.4vw, 2.2rem);
  padding: clamp(0.85rem, 2vw, 1.1rem) clamp(1rem, 2.4vw, 1.35rem);
  background: var(--hinge);
  border: 1px solid var(--rule);
  /* The hazard stripe: this is the one irreversible fact on the page. */
  border-left: 0;
  position: relative;
  overflow: hidden;
}
.keynote::before {
  content: '';
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 10px;
  background: repeating-linear-gradient(-45deg,
    var(--amber) 0 6px, var(--amber-ink) 6px 12px);
}
.keynote { padding-left: calc(clamp(1rem, 2.4vw, 1.35rem) + 10px); }

.keynote__icon { color: var(--amber); width: 20px; height: 20px; margin-top: 0.1rem; }
.keynote__text { margin: 0; font: 500 0.83rem/1.55 var(--mono); color: var(--ink-quiet); }
.keynote__text strong { color: var(--flap); font-weight: 600; }

/* ------------------------------------------------------------------ the bay */

.bay { padding-bottom: clamp(2rem, 5vw, 3.5rem); }

.bay__rail {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding: clamp(1.4rem, 3.2vw, 2.2rem) var(--gut) clamp(0.85rem, 2vw, 1.1rem);
}

.bay__title {
  margin: 0;
  font: 700 clamp(1rem, 1.7vw, 1.18rem)/1 var(--sans);
  font-stretch: 82%;
  letter-spacing: 0.03em;
  color: var(--flap);
}

.bay__note {
  margin: 0;
  font: 500 0.78rem/1 var(--mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--flap-dim);
}

.rows { list-style: none; margin: 0; padding: 0; }

.row {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr) 5.5rem auto;
  gap: clamp(0.75rem, 2vw, 1.75rem);
  align-items: center;
  padding: clamp(0.85rem, 2vw, 1.15rem) var(--gut);
  border-bottom: 1px solid var(--rule);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.016), transparent);
}
.row:nth-child(even) { background: rgba(0, 0, 0, 0.22); }
.row:hover { background: rgba(232, 178, 28, 0.045); }

/* A row that just landed reads as newly turned. */
@keyframes row-land {
  from { background: rgba(232, 178, 28, 0.22); }
  to   { background: rgba(232, 178, 28, 0); }
}
.row[data-fresh='true'] { animation: row-land 1400ms var(--ease) both; }

.row__cell { min-width: 0; }

.row__link {
  display: inline-flex;
  align-items: baseline;
  gap: 0.35rem;
  flex-wrap: wrap;
  text-decoration: none;
  color: inherit;
}
.row__prefix {
  font: 500 0.82rem/1 var(--mono);
  color: var(--flap-dim);
  letter-spacing: 0.02em;
}
.row__link:hover .flap { border-color: #3c444b; color: #fff6e0; }

.row__cell--dest { display: grid; gap: 0.15rem; }
.row__host {
  font: 600 0.88rem/1.35 var(--mono);
  color: var(--flap);
  overflow-wrap: anywhere;
}
.row__path {
  font: 400 0.78rem/1.4 var(--mono);
  color: var(--flap-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.row__cell--num { text-align: right; }
.counter {
  font: 600 1.15rem/1 var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--flap);
}
.counter[data-zero='true'] { color: #5d646b; }

.row__cell--keys { display: flex; gap: 0.4rem; justify-content: flex-end; }

.key {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.46rem 0.7rem;
  border: 1px solid var(--enamel);
  background: linear-gradient(180deg, #21262b, #171b1f);
  color: var(--ink-quiet);
  font: 600 0.72rem/1 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
  transition: color 130ms var(--ease), border-color 130ms var(--ease), background 130ms var(--ease);
}
.key:hover { color: var(--flap); border-color: #4b535b; }
.key__icon { width: 15px; height: 15px; flex: none; }
.key[aria-expanded='true'] { color: var(--amber); border-color: var(--amber-deep); }
.key[data-done='true'] { color: var(--live); border-color: #2f9a6e; }
.key--halt:hover { color: var(--halt); border-color: #8d3220; background: linear-gradient(180deg, #2a1b17, #1d1310); }
.key[data-arm='true'] {
  color: var(--amber-ink);
  border-color: #8d3220;
  background: repeating-linear-gradient(-45deg, var(--halt) 0 7px, #b83a22 7px 14px);
}
.key[disabled] { opacity: 0.45; cursor: not-allowed; }

/* --------------------------------------------------------------- QR drawer */

.row__drawer { grid-column: 1 / -1; }
.row__drawer:not([hidden]) {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: clamp(0.9rem, 2.4vw, 1.6rem);
  align-items: center;
  margin-top: clamp(0.85rem, 2vw, 1.15rem);
  padding: clamp(0.9rem, 2.2vw, 1.25rem);
  background: var(--hinge);
  border: 1px solid var(--rule);
}

.qr {
  display: block;
  width: clamp(116px, 15vw, 156px);
  height: auto;
  /* The code prints as ink on the board's own cream, not on white. */
  background: var(--flap);
  padding: 9px;
}

.qr__aside { display: grid; gap: 0.55rem; min-width: 0; }
.qr__label {
  margin: 0;
  font: 600 0.68rem/1 var(--mono);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--flap-dim);
}
.qr__url {
  margin: 0;
  font: 600 clamp(0.86rem, 1.5vw, 1rem)/1.4 var(--mono);
  color: var(--flap);
  overflow-wrap: anywhere;
}
.qr__note { margin: 0; font: 400 0.78rem/1.5 var(--mono); color: var(--ink-quiet); }

.qr__download {
  justify-self: start;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.46rem 0.7rem;
  border: 1px solid var(--enamel);
  background: linear-gradient(180deg, #21262b, #171b1f);
  color: var(--ink-quiet);
  font: 600 0.72rem/1 var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
}
.qr__download:hover { color: var(--flap); border-color: #4b535b; }

/* ------------------------------------------------------------ empty & delete */

.vacant {
  padding: clamp(1.6rem, 4vw, 2.6rem) var(--gut) clamp(1.8rem, 4vw, 2.8rem);
  border-bottom: 1px solid var(--rule);
  background: rgba(0, 0, 0, 0.22);
}
.vacant__lead {
  margin: 0 0 0.7rem;
  font: 700 clamp(1.05rem, 2.2vw, 1.35rem)/1.2 var(--sans);
  font-stretch: 80%;
  letter-spacing: 0.02em;
  color: var(--flap-dim);
}
.vacant__body {
  margin: 0;
  max-width: 68ch;
  font: 400 0.86rem/1.65 var(--mono);
  color: var(--ink-quiet);
}

.confirm {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
  margin-top: clamp(0.85rem, 2vw, 1.15rem);
  padding: 0.9rem 1.1rem 0.9rem calc(1.1rem + 10px);
  position: relative;
  overflow: hidden;
  background: #1d1310;
  border: 1px solid #8d3220;
}
.confirm::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0; width: 10px;
  background: repeating-linear-gradient(-45deg, var(--halt) 0 6px, #17130a 6px 12px);
}
.confirm__text { margin: 0; flex: 1 1 22ch; font: 500 0.83rem/1.5 var(--mono); color: #f0c4b8; }
.confirm__text strong { color: #fff; font-weight: 600; }

/* -------------------------------------------------------------------- foot */

.foot {
  padding: clamp(1.4rem, 3.2vw, 2.2rem) var(--gut) clamp(2rem, 4.5vw, 3rem);
  border-top: 1px solid var(--rule);
  background: var(--hinge);
  display: grid;
  gap: 0.6rem;
}
.foot__line {
  margin: 0;
  max-width: 74ch;
  font: 400 0.82rem/1.6 var(--mono);
  color: var(--ink-quiet);
}
.foot__line--dim { color: #6b7278; }
.foot code {
  font: 600 0.95em/1 var(--mono);
  color: var(--flap);
  background: rgba(255, 255, 255, 0.05);
  padding: 0.1em 0.35em;
}

/* --------------------------------------------------------------- responsive
   The board restructures rather than shrinking its type: columns stack, the
   column heads retire (each cell carries its own label), and the name field
   keeps its full display scale because it is the product. */

@media (max-width: 900px) {
  .desk__grid { grid-template-columns: minmax(0, 1fr); gap: clamp(1.5rem, 4vw, 2rem); }
  .field--status { justify-self: start; }
  .label--end, .status { text-align: left; }
  .heads:not(.heads--bay) { display: none; }
  .heads--bay { grid-template-columns: minmax(0, 1fr) 4.5rem auto; }
  .heads--bay .heads__cell:nth-child(2) { display: none; }

  .row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      'name    num'
      'dest    dest'
      'keys    keys';
    row-gap: 0.7rem;
  }
  .row__cell--name { grid-area: name; }
  .row__cell--dest { grid-area: dest; }
  .row__cell--num { grid-area: num; }
  .row__cell--keys { grid-area: keys; justify-content: flex-start; }
  .row__drawer:not([hidden]) { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 560px) {
  .rail {
    grid-template-columns: auto 1fr;
    row-gap: 0.55rem;
  }
  .rail__station { grid-column: 1 / -1; }
  .heads--bay { display: none; }

  /* The station prefix takes its own line so the rank gets the whole column.
     Sharing the line costs it roughly half the width, which at this size is the
     difference between a twelve-character name reading whole and travelling. */
  .namefield__slot { flex-basis: 100%; }
  .namefield__prefix { font-size: 0.88rem; }

  /* Icon-only keys at this width. The label is hidden visually but stays in the
     accessibility tree, which `display: none` would have taken away. */
  .key .key__text {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
  .key { padding: 0.5rem 0.62rem; }
  .qr__download .key__text {
    position: static; width: auto; height: auto; clip-path: none;
  }
  .board { border-left: 0; border-right: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .flap--turn { animation: none; }
  .row[data-fresh='true'] { animation: none; }
  .status[data-tone='work'] { animation: none; }
  *, *::before, *::after {
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}

/* Some visitors force a light system theme; the board is a physical object with
   its own color, so it does not invert, but the ambient page does soften. */
@media (forced-colors: active) {
  .flap, .key, .plate, .input, .namefield { border-color: CanvasText; }
  .plate--go { forced-color-adjust: none; }
}
