/* ============================================================
   Desk Anvil — THE DEPARTURE BOARD
   The replacement visual world (seed 432d75a6, form: rail concourse
   split-flap board). Homepage-only visual system; tool and policy pages
   use the separate shared styles.css system.

   Rules carried over and non-negotiable:
   - zero external requests. Fonts are SELF-HOSTED, never a CDN.
   - green / amber / red belong to the extensions' status semantics.
     Here they finally agree with the world: a departure board already
     uses amber for delay and red for cancelled.
   - light is the committed ground. The BOARD is the dark object on it.
   ============================================================ */

/* ---------- type ----------
   The public build deliberately uses system fonts. The previous draft
   referenced four font files that were never present, creating failed
   requests without changing the rendered result. The narrow system stack
   keeps the station-board character; the body stack stays native and fast. */

:root {
  color-scheme: light;

  --display: "Roboto Condensed", "Arial Narrow", "Helvetica Neue Condensed",
             "Liberation Sans Narrow", Arial, sans-serif;
  --body: ui-sans-serif, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;

  /* the concourse: bright, cool, daylight through glass */
  --ground: #eef1f5;
  --surface: #ffffff;
  --rule: #d3d9e2;
  --rule-strong: #b3bcc9;
  --rail: #c8d0dc;
  --grid: rgba(75, 87, 199, .055);
  --ink: #12151b;
  --ink-soft: #4c5563;

  /* the board: a real object, matte and dark, sitting on that ground */
  --board: #15181e;
  --board-cell: #1c2029;
  --board-cell-alt: #191d25;
  --board-ink: #f2f4f8;
  --board-ink-soft: #949eae;
  --frame-top: #454c57;
  --frame-bottom: #232830;

  /* brand */
  --accent: #4b57c7;
  --accent-blue: #2f70d9;
  --accent-hover: #3e49ad;
  --accent-soft: #eef0ff;
  --accent-on: #ffffff;
  --accent-lift: #8b95ee;   /* the indigo that survives on the dark board */

  /* status — on the light ground */
  --ok: #17794a;
  --warn: #9a5b06;
  --bad: #b3271d;
  --ok-soft: #e4f4ec;
  --warn-soft: #fbf0dd;
  --bad-soft: #fbe9e7;
  /* status — on the board, where a delay lamp is genuinely amber */
  --ok-lamp: #3fcf83;
  --warn-lamp: #f0a92e;
  --bad-lamp: #f4695a;

  --content: 82.5rem;
  --pad: clamp(1.2rem, 4vw, 4rem);
  --section: clamp(5rem, 9vw, 8rem);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --dur: 200ms;
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --ground: #0e1116;
  --surface: #161a21;
  --rule: #262c36;
  --rule-strong: #39414e;
  --rail: #2f3743;
  --grid: rgba(155, 140, 255, .06);
  --ink: #eef1f6;
  --ink-soft: #9aa4b3;
  --accent: #9b8cff;
  --accent-hover: #b6abff;
  --accent-soft: #1d1946;
  --accent-on: #0e1116;
  --ok: #3fcf83; --warn: #f0a92e; --bad: #f4695a;
  --ok-soft: #10241a; --warn-soft: #2a2110; --bad-soft: #2b1416;
}

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0; background: var(--ground); color: var(--ink);
  font-family: var(--body); font-size: 1.0625rem; line-height: 1.65;
  -webkit-font-smoothing: antialiased; overflow-x: hidden;
}

h1, h2, h3 {
  font-family: var(--display); font-weight: 700;
  line-height: .96; margin: 0 0 .4em; text-wrap: balance;
}
h1 {
  font-size: clamp(3.4rem, 7.3vw, 6.75rem);
  text-transform: uppercase; letter-spacing: -.025em;
}
h2 { font-size: clamp(2.45rem, 5vw, 4.5rem); letter-spacing: -.035em; }
h3 { font-size: 1.2rem; letter-spacing: -.015em; line-height: 1.15; }
p { margin: 0 0 1rem; max-width: 66ch; }
a { color: var(--accent); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { color: var(--accent-hover); }
img, svg { max-width: 100%; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }
::selection { background: var(--accent); color: var(--accent-on); }
:root { scrollbar-color: var(--rule-strong) transparent; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--rule-strong); border-radius: 999px;
  border: 3px solid var(--ground); background-clip: padding-box;
}

.wrap {
  width: 100%; max-width: var(--content); margin-inline: auto;
  padding-inline: var(--pad); border-inline: 1px solid var(--rail);
}
.narrow { max-width: 760px; }
section { padding-block: var(--section); }

/* A board label: the small tracked caps used on signage, never a
   decorative kicker — it always names a real column or service. */
.signal {
  display: inline-flex; align-items: center; gap: .65rem;
  font-family: var(--display); font-size: .75rem; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-soft);
  margin: 0 0 1rem;
}
.signal::before {
  content: ""; width: 1.75rem; height: 2px; flex: 0 0 auto;
  background: linear-gradient(90deg, var(--accent), var(--accent-blue));
}

.section-head {
  display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(18rem, .8fr);
  gap: clamp(2rem, 7vw, 7rem); align-items: end;
}
.section-head > p { color: var(--ink-soft); margin: 0 0 .55rem; }

/* ---------- header ----------
   Light on purpose. The BOARD is the only dark object on this page; when
   the header was steel too, the page had three dark blocks and the board
   stopped being special. It also put the monogram's near-black D on a
   near-black ground, where it simply could not be read. */
.site-header {
  position: sticky; top: 0; z-index: 20;
  background: var(--ground);
  background: color-mix(in srgb, var(--ground) 90%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rule);
}
.site-header .wrap {
  position: relative;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; min-height: 76px;
}
.wordmark {
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: var(--display); font-weight: 700; font-size: 1.1875rem;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink); text-decoration: none; white-space: nowrap;
}
/* The approved DA monogram. An image rather than a masked shape because
   the mark carries its own violet-to-blue gradient, which a single-colour
   mask cannot express. Source of truth for the full-size original:
   assets/branding/logos/3-approved/. */
.wordmark .dot {
  width: 42px; height: 42px; flex: 0 0 auto;
  background: url("assets/brand/deskanvil-mark.png") no-repeat center / contain;
}
.site-header .wordmark { font-size: 1.3125rem; }
.header-actions { display: flex; align-items: center; gap: 1.25rem; }

/* Station signage, not a button. A bordered ghost button in a header is
   the dated pattern; a tracked-caps link belongs to this world. */
.nav-link {
  font-family: var(--display); font-size: .8125rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft); text-decoration: none;
  padding-bottom: 2px; border-bottom: 1px solid transparent;
  transition: color var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
.nav-link:hover { color: var(--ink); border-bottom-color: var(--accent); }

/* A real switch: a track, both states visible, and a knob that travels to
   the one you are in. An icon-only button gave no read on which state was
   active — a switch shows its own position. */
.theme-switch {
  position: relative; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: space-between;
  width: 64px; height: 34px; padding: 0 9px;
  border: 1px solid var(--rule-strong); border-radius: 999px;
  background: var(--surface); cursor: pointer;
  transition: border-color var(--dur) var(--ease-out);
}
.theme-switch:hover { border-color: var(--ink-soft); }
.theme-switch .knob {
  position: absolute; top: 3px; left: 3px;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 1px 3px rgba(10, 12, 18, .3);
  transition: transform var(--dur) var(--ease-out);
}
:root[data-theme="dark"] .theme-switch .knob { transform: translateX(30px); }
.theme-switch svg {
  position: relative; z-index: 1; width: 15px; height: 15px;
  color: var(--ink-soft); transition: color var(--dur) var(--ease-out);
}
/* whichever icon the knob is sitting on reads against the accent */
.theme-switch .i-sun { color: #fff; }
:root[data-theme="dark"] .theme-switch .i-sun { color: var(--ink-soft); }
:root[data-theme="dark"] .theme-switch .i-moon { color: #fff; }

@media (prefers-reduced-motion: reduce) {
  .theme-switch .knob { transition: none; }
}

/* The monogram's D is near-black, so on a dark ground it needs the
   light-D variant. Same mark, repainted, not inverted. */
:root[data-theme="dark"] .wordmark .dot {
  background-image: url("assets/brand/deskanvil-mark-dark.png");
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 46px; padding: .7rem 1.35rem;
  font-family: var(--display); font-size: .9375rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  border: 1px solid transparent; border-radius: 7px;
  text-decoration: none; cursor: pointer;
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out);
}
.btn-primary {
  background: linear-gradient(120deg, var(--accent), var(--accent-blue));
  color: #fff; box-shadow: 0 4px 0 color-mix(in srgb, var(--accent) 62%, #111 38%);
  transform: translateY(0);
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out),
              box-shadow var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.btn-primary:hover {
  background: linear-gradient(120deg, var(--accent-hover), #1766dc);
  color: #fff; transform: translateY(1px); box-shadow: 0 3px 0 color-mix(in srgb, var(--accent) 62%, #111 38%);
}
.btn-ghost { background: transparent; color: #d5dbe3; border-color: rgba(255,255,255,.3); }
.btn-ghost:hover { background: rgba(255,255,255,.1); color: #fff; }
.btn-line { background: transparent; color: var(--ink); border-color: var(--rule-strong); }
.btn-line:hover { background: var(--surface); border-color: var(--ink); color: var(--ink); }
.btn-lg { min-height: 54px; padding: .9rem 1.7rem; font-size: 1rem; }

/* ---------- hero ---------- */
.hero {
  position: relative; isolation: isolate; overflow: clip;
  padding-block: clamp(4rem, 8vw, 7rem) clamp(4rem, 7vw, 6rem);
}
.hero::before {
  content: ""; position: absolute; z-index: -1; inset: 0;
  background-image:
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 32px 32px;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,.7) 45%, transparent 88%);
  mask-image: linear-gradient(to bottom, #000 0%, rgba(0,0,0,.7) 45%, transparent 88%);
}
.hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(20rem, .75fr);
  gap: clamp(2.5rem, 6vw, 6rem); align-items: start;
}
.hero-grid > *, .section-head > *, .maker-grid > *, .close-grid > *,
.footer-top > *, .footer-columns > * { min-width: 0; }
.hero h1 { max-width: 13ch; margin-bottom: 0; }
.hero-copy { padding-bottom: 0; }
.hero .lede {
  font-size: clamp(1.0625rem, 1.7vw, 1.1875rem);
  color: var(--ink-soft); max-width: 41ch; margin: 0;
}
.hero-cta { display: flex; flex-wrap: wrap; gap: .7rem; margin-top: 1.9rem; }
.hero-copy .hero-cta { align-items: stretch; }
.hero-copy .hero-cta .btn { flex: 1 1 12rem; padding-inline: 1.1rem; }
/* The lead CTA still presses down on hover. A solid shadow avoids the pale
   1px compositing seam the mixed-colour shadow created below it. */
.hero-copy .btn-primary { box-shadow: 0 4px 0 #302b95; }
.hero-copy .btn-primary:hover { transform: translateY(1px); box-shadow: 0 3px 0 #302b95; }
.hero-trust {
  display: flex; flex-wrap: wrap; gap: .55rem 1rem;
  list-style: none; padding: 0; margin: 1.35rem 0 0;
  color: var(--ink-soft); font-family: var(--display); font-size: .75rem;
  font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
}
.hero-trust li { display: inline-flex; align-items: center; gap: .4rem; }
.hero-trust li::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-blue));
}

/* ---------- THE BOARD ----------
   The page's one authored object. Fixed columns that never move, rows
   that are live entities, and a status cell that flips to its verdict. */
.board {
  margin-top: clamp(3.5rem, 7vw, 6rem);
  /* brushed steel: fine vertical grain over the frame's gradient, so the
     frame reads as a milled object rather than a CSS gradient */
  background:
    repeating-linear-gradient(90deg,
      rgba(255,255,255,.045) 0 1px, rgba(0,0,0,.03) 1px 2px, transparent 2px 4px),
    linear-gradient(180deg, var(--frame-top), var(--frame-bottom));
  padding: 10px; border-radius: 8px;
  box-shadow: 0 34px 90px rgba(12, 16, 24, .25), 0 7px 18px rgba(12, 16, 24, .16);
}
.board-inner { position: relative; background: var(--board); border-radius: 3px; overflow: hidden; }
.board-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: .85rem 1.1rem; border-bottom: 1px solid #0c0f14;
}
.board-title {
  font-family: var(--display); font-size: .8125rem; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: var(--board-ink-soft);
}
.board-clock {
  font-family: var(--display); font-size: .8125rem; font-weight: 700;
  letter-spacing: .16em; color: var(--board-ink-soft);
}

.board-scroll { overflow-x: auto; }
.board-table { width: 100%; border-collapse: collapse; min-width: 40rem; }
.board-table th {
  font-family: var(--display); font-size: .6875rem; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; text-align: left;
  color: var(--board-ink-soft); padding: .7rem 1.1rem;
  border-bottom: 1px solid #0c0f14; white-space: nowrap;
}
.board-table td {
  padding: .85rem 1.1rem; border-bottom: 1px solid #0c0f14;
  font-family: var(--display); font-size: .9375rem; font-weight: 600;
  letter-spacing: .04em; color: var(--board-ink); vertical-align: middle;
}
.board-table tr:last-child td { border-bottom: 0; }
.board-table tr:nth-child(even) td { background: var(--board-cell-alt); }
.board-table tr:nth-child(odd) td { background: var(--board-cell); }
.cell-link { font-family: var(--mono); font-size: .8125rem; letter-spacing: 0; }
.cell-tag { color: var(--board-ink-soft); font-family: var(--mono); font-size: .8125rem; letter-spacing: 0; }
.cell-tag.mine { color: var(--board-ink); }

/* the flap: a status cell that lands on its verdict */
.flap {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--display); font-size: .8125rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; white-space: nowrap;
}
.flap .lamp {
  width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto;
  background: var(--board-ink-soft);
}
.flap.ok  { color: var(--ok-lamp);  } .flap.ok .lamp  { background: var(--ok-lamp);  }
.flap.warn{ color: var(--warn-lamp);} .flap.warn .lamp{ background: var(--warn-lamp);}
.flap.bad { color: var(--bad-lamp); } .flap.bad .lamp { background: var(--bad-lamp); }
.flap.none{ color: var(--board-ink-soft); }

/* The homepage demonstrates a real Inspector control: additional internal
   redirect paths can be classified without following them. The control sits
   inside the instrument because it changes the board directly. */
.no-js .board-config { display: none; }
.board-config {
  display: grid; grid-template-columns: minmax(12rem, .7fr) minmax(19rem, 1.1fr) minmax(18rem, 1fr);
  align-items: center; gap: .7rem 1rem;
  padding: .9rem 1.1rem; border-top: 1px solid #0c0f14;
  background: #11151c;
}
.board-config label {
  font-family: var(--display); font-size: .6875rem; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--board-ink-soft);
}
.board-config-entry { display: flex; min-width: 0; }
.board-config input {
  width: 100%; min-width: 0; height: 40px; padding: 0 .8rem;
  border: 1px solid #394150; border-right: 0; border-radius: 4px 0 0 4px;
  background: var(--board-cell); color: var(--board-ink);
  font-family: var(--mono); font-size: .8125rem;
}
.board-config input::placeholder { color: #707a8c; }
.board-config input:focus-visible {
  position: relative; z-index: 1; outline: 2px solid var(--accent-lift); outline-offset: 1px;
}
.board-config input[aria-invalid="true"] { border-color: var(--bad-lamp); }
.board-config button {
  min-width: 5.5rem; height: 40px; padding: 0 .9rem;
  border: 1px solid #4a55d7; border-radius: 0 4px 4px 0;
  background: linear-gradient(120deg, var(--accent), #1766dc); color: #fff;
  font-family: var(--display); font-size: .6875rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; cursor: pointer;
  transition: filter var(--dur) var(--ease-out), border-color var(--dur) var(--ease-out);
}
.board-config button:hover { filter: brightness(1.12); border-color: #7782ff; }
.board-config button:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.board-config p {
  margin: 0; color: var(--board-ink-soft); font-size: .75rem; line-height: 1.45;
}
.board-config code { color: var(--board-ink); }
.board-demo-row.is-recognized td { background: #202630; }

@keyframes verdict-settle {
  0% { opacity: .2; transform: translateY(-5px) rotateX(70deg); }
  100% { opacity: 1; transform: none; }
}
.flap-text.reclassified { animation: verdict-settle 320ms var(--ease-out); }

.board-foot {
  display: flex; justify-content: space-between; gap: 1.5rem;
  padding: .9rem 1.1rem; border-top: 1px solid #0c0f14;
  font-family: var(--display); font-size: .75rem; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase; color: var(--board-ink-soft);
}
.board-swipe { display: none; color: var(--accent-lift); white-space: nowrap; }

/* ---------- the timetable: same discipline, printed not lit ----------
   Deliberately NOT another dark board. The hero is the live board; this
   is the printed sheet beside it, so clicking through never feels like
   nothing happened. */
/* The ruled block bleeds past the text column so a hover fill has room to
   breathe on both sides instead of clamping to the words. The padding is
   permanent — nothing animates layout. */
.timetable { border-top: 2px solid var(--ink); margin: clamp(2.5rem, 5vw, 4.5rem) 0 0; }
.tt-row {
  display: grid; gap: .55rem 2rem; padding: 2rem 1.25rem;
  border-bottom: 1px solid var(--rule); align-items: start;
  text-decoration: none; color: inherit;
  /* paint only — nothing here animates layout */
  transition: background var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
@media (min-width: 52rem) {
  .tt-row { grid-template-columns: minmax(0, 20rem) minmax(0, 1fr) auto; align-items: center; }
}
.tt-featured {
  margin-inline: -1px; padding: clamp(2rem, 4vw, 3rem);
  background: var(--surface); border: 1px solid var(--rule);
  box-shadow: inset 4px 0 0 var(--accent);
}
/* Hover is the row's own rule drawn heavier, not a grey fill. The flat
   panel-fill highlight is the dated table pattern; this is the discipline
   the ligne claire challenger donated when it placed — selection is the
   same line, drawn with more weight. Inset shadow, so nothing reflows. */
a.tt-row:hover {
  background: color-mix(in srgb, var(--surface) 72%, transparent); color: inherit;
  box-shadow: inset 0 -2px 0 var(--ink);
}
a.tt-row.tt-featured:hover { box-shadow: inset 4px 0 0 var(--accent), inset 0 -2px 0 var(--ink); }
a.tt-row:hover .tt-name { color: var(--accent-blue); }
a.tt-row:hover .tt-what { color: var(--ink); }
.tt-featured .tt-name::after {
  content: " →"; display: inline-block; opacity: 0; transform: translateX(-.45em);
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
a.tt-featured:hover .tt-name::after { opacity: 1; transform: none; }
a.tt-featured:hover .tt-state.next { color: var(--accent-hover); }
.tt-name, .tt-what { transition: color var(--dur) var(--ease-out); }
.tt-name {
  font-family: var(--display); font-size: clamp(1.25rem, 2vw, 1.55rem); font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; color: var(--ink);
}
.tt-what { color: var(--ink-soft); margin: 0; font-size: .9375rem; max-width: 52ch; }
.tt-state {
  font-family: var(--display); font-size: .75rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; white-space: nowrap;
  display: inline-flex; align-items: center; gap: .5rem; color: var(--ink-soft);
}
.tt-state .lamp { width: 8px; height: 8px; border-radius: 50%; background: var(--rule-strong); }
.tt-state.next { color: var(--accent); }
.tt-state.next .lamp { background: var(--accent); }
/* A shipped tool reads as a live signal, not as the next thing queued.
   Violet means "coming"; the ok lamp means "you can install this now". */
.tt-state.live { color: var(--ok); }
.tt-state.live .lamp { background: var(--ok-lamp); }
/* Unreleased rows were falling back to the grey rule token, which read as
   "dead" rather than "not yet". Amber is the honest middle state. */
.tt-state:not(.live):not(.next) { color: var(--ink-soft); }
.tt-state:not(.live):not(.next) .lamp { background: var(--warn); }
.tt-verdicts { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .6rem; }
.tag {
  font-family: var(--display); font-size: .6875rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  padding: .22rem .5rem; border-radius: 2px;
}
.tag.ok { background: var(--ok-soft); color: var(--ok); }
.tag.warn { background: var(--warn-soft); color: var(--warn); }
.tag.bad { background: var(--bad-soft); color: var(--bad); }
.tag.none { background: var(--surface); color: var(--ink-soft); border: 1px solid var(--rule); }

/* ---------- service notices (the four rules) ---------- */
.notices {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  list-style: none; padding: 0; margin: clamp(2.5rem, 5vw, 4.5rem) 0 0;
  border-top: 1px solid var(--rule-strong); border-left: 1px solid var(--rule-strong);
}
.notices li {
  min-height: 18rem; padding: clamp(2rem, 4vw, 3.5rem);
  border-right: 1px solid var(--rule-strong); border-bottom: 1px solid var(--rule-strong);
  background: color-mix(in srgb, var(--surface) 58%, transparent);
}
.notice-no {
  display: block; margin-bottom: clamp(2rem, 5vw, 4rem);
  font-family: var(--mono); font-size: .75rem; color: var(--accent);
}
.notices h3 { color: var(--ink); margin: 0 0 1rem; font-size: clamp(1.4rem, 2.3vw, 2rem); }
.notices p { margin: 0; color: var(--ink-soft); font-size: 1rem; max-width: 44ch; }

/* ---------- maker ---------- */
.maker-section { background: var(--surface); padding-block: 0; }
.maker-grid {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(20rem, .9fr);
  gap: clamp(3rem, 9vw, 9rem); padding-block: var(--section);
}
.maker-copy { align-self: end; }
.maker-copy p { color: var(--ink-soft); }
.maker-copy p:last-child { margin-bottom: 0; }

/* ---------- closing band ---------- */
.close-band { background: var(--board); color: var(--board-ink); }
.close-band .wrap { border-color: rgba(255,255,255,.12); }
.close-grid {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(20rem, .9fr);
  gap: clamp(3rem, 9vw, 9rem); align-items: end;
}
.close-band h2 { color: #fff; }
.close-band p { color: var(--board-ink-soft); }
.close-band .signal { color: var(--board-ink-soft); }
.close-band .hero-cta { margin-top: 1.5rem; }
/* Keep the blue finish that gives the CTA life, but start close enough to it
   that the left edge reads as a button colour, not a separate accent stripe. */
.close-band .btn-primary { background: linear-gradient(120deg, #4b51d3, var(--accent-blue)); }
.close-band .btn-primary:hover { background: linear-gradient(120deg, #4147c7, #1766dc); }

/* ---------- footer ---------- */
.site-footer {
  background: linear-gradient(180deg, var(--frame-top), var(--frame-bottom));
  color: #aeb6c2; font-size: .9375rem;
}
.site-footer .wrap { padding-block: clamp(3.5rem, 7vw, 6rem) 2.5rem; border-color: rgba(255,255,255,.12); }
.site-footer a { color: #dde2e9; text-decoration: none; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.dead-reckoning-link { display: inline-flex; align-items: center; gap: .34em; }
.site-footer .wordmark .dot { background-image: url("assets/brand/deskanvil-mark-dark.png"); }
.footer-top {
  display: grid; grid-template-columns: minmax(15rem, .8fr) minmax(0, 1.7fr);
  gap: clamp(3rem, 8vw, 8rem); align-items: start;
}
.footer-columns { display: grid; grid-template-columns: 1.4fr .8fr 1fr; gap: clamp(2rem, 5vw, 5rem); }
.footer-links { display: flex; flex-direction: column; align-items: flex-start; gap: .65rem; }
.footer-label {
  margin-bottom: .5rem; color: #fff; font-family: var(--display); font-size: .75rem;
  font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
}
.footer-meta { font-size: .8125rem; color: #8f98a5; }
.footer-legal { margin-top: clamp(2.5rem, 6vw, 5rem); padding-top: 1.25rem; border-top: 1px solid rgba(255,255,255,.12); }

/* ---------- motion ----------
   The board's own motion in life: rows resolve one after another, and a
   row about to change shows its lamp before the verdict lands. That is
   the page's single authored moment. Nothing is hidden in CSS — the
   script adds the hidden state only once it knows motion is welcome. */
.anim { opacity: 0; transform: translateY(10px); }
.anim.in { opacity: 1; transform: none; transition: opacity 460ms var(--ease-out), transform 460ms var(--ease-out); }
.anim-board { opacity: 0; transform: translateY(22px) scale(.992); }
.anim-board.in {
  opacity: 1; transform: none;
  transition: opacity 700ms var(--ease-out), transform 700ms var(--ease-out);
}

/* The flap mechanism itself lives in the script: each verdict cascades
   through characters and settles left to right, which is what the board
   does in life. CSS only holds the lamp, which lights BEFORE its verdict
   lands — the pre-commit visibility this direction was raised on. */
.flap-text { display: inline-block; min-width: 7ch; }
.anim-board .flap .lamp { opacity: 0; }
.anim-board.in .flap .lamp { opacity: 1; transition: opacity 200ms linear; }
.anim-board.in tr:nth-child(1) .flap .lamp { transition-delay: 120ms; }
.anim-board.in tr:nth-child(2) .flap .lamp { transition-delay: 300ms; }
.anim-board.in tr:nth-child(3) .flap .lamp { transition-delay: 480ms; }
.anim-board.in tr:nth-child(4) .flap .lamp { transition-delay: 660ms; }

/* the board is an instrument you can look down — rows respond */
.board-table tbody tr td { transition: background var(--dur) var(--ease-out); }
.board-table tbody tr:hover td { background: #262c38; }

/* A departure that is imminent blinks. The Inspector IS next out, so the
   lamp carries real information rather than decoration. Runs only while
   the row is on screen. */
@keyframes lamp-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
.tt-row.live .tt-state.next .lamp,
.tt-state.live .lamp { animation: lamp-pulse 2.4s ease-in-out infinite; }

/* the sticky bar earns a shadow only once it is actually floating */
.site-header { transition: box-shadow var(--dur) var(--ease-out); }
.site-header.scrolled { box-shadow: 0 8px 24px rgba(12, 16, 24, .10); }

@media (prefers-reduced-motion: reduce) {
  .anim, .anim.in, .anim-board, .anim-board.in, .anim-board .flap .lamp {
    opacity: 1; transform: none; animation: none; transition: none;
  }
  .tt-row.live .tt-state.next .lamp,
  .tt-state.live .lamp { animation: none; }
  .flap-text.reclassified { animation: none; }
}

@media (max-width: 64rem) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }
  .hero h1 { max-width: 15ch; }
  .hero-copy { max-width: 46rem; padding-bottom: 0; }
  .hero .lede { max-width: 58ch; }
  .hero-copy .hero-cta .btn { flex: 0 1 auto; }
  .maker-grid, .close-grid { grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }
  .maker-copy { max-width: 50rem; }
  .footer-top { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 52rem) {
  .section-head { grid-template-columns: minmax(0, 1fr); gap: 1.25rem; }
  .section-head > p { max-width: 48rem; }
  .notices { grid-template-columns: minmax(0, 1fr); }
  .notices li { min-height: 0; }
  .notice-no { margin-bottom: 2rem; }
  .board-config { grid-template-columns: minmax(0, 1fr); }
  .footer-columns { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 46rem) {
  .header-actions .nav-link { display: none; }
  .theme-switch { position: absolute; right: var(--pad); top: 50%; transform: translateY(-50%); }
  .board-swipe {
    display: inline-flex; position: absolute; z-index: 2; top: 4.25rem; right: .7rem;
    padding: .25rem .45rem; border: 1px solid #394150; border-radius: 3px;
    background: rgba(15, 18, 24, .92); color: var(--accent-lift);
  }
  .board-foot { display: block; }
}

@media (max-width: 32rem) {
  :root { --pad: 1.05rem; }
  .wrap { border-inline: 0; }
  .site-header .wrap { min-height: 66px; }
  .wordmark { gap: .45rem; font-size: 1rem; letter-spacing: .08em; }
  .site-header .wordmark { font-size: 1.125rem; }
  .wordmark .dot { width: 36px; height: 36px; }
  .theme-switch { width: 58px; height: 32px; }
  .theme-switch .knob { width: 24px; height: 24px; }
  :root[data-theme="dark"] .theme-switch .knob { transform: translateX(26px); }
  h1 { font-size: clamp(2.8rem, 15vw, 4.2rem); }
  h2 { font-size: clamp(2.2rem, 12vw, 3.35rem); }
  .hero { padding-block: 3.5rem 4rem; }
  .hero-grid { gap: 1.8rem; }
  .hero-copy .hero-cta .btn { flex: 1 1 100%; }
  .hero-trust { display: grid; gap: .55rem; }
  .board { margin-inline: -.25rem; padding: 5px; border-radius: 6px; }
  .board-head { align-items: flex-start; }
  .board-title, .board-clock { font-size: .6875rem; }
  .board-table { min-width: 44rem; }
  .board-foot { font-size: .6875rem; }
  .tt-row, .tt-featured { padding: 1.65rem 0; }
  .tt-featured { margin: 0; padding-inline: 1rem; }
  .hero-cta .btn { width: 100%; }
  .footer-columns { grid-template-columns: minmax(0, 1fr); }
}

/* ---- Coming soon: Perch (Windows app) --------------------------------------------------
   A second product line on a publisher-first page, so it gets its own band rather than a
   row that reads like another browser tool. The preview is drawn in HTML with sample
   sessions (no real prompts); swap in a clean real capture once one exists. */
.soon-band { background: var(--board); color: var(--board-ink); }
.soon-band .wrap { border-color: rgba(255,255,255,.12); }
.soon-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(19rem, 25rem); gap: clamp(2.5rem, 7vw, 6rem); align-items: center; }
.soon-band h2 { color: #fff; }
.soon-band p { color: var(--board-ink-soft); }
.soon-band .signal { color: var(--board-ink-soft); }
.soon-points { list-style: none; margin: 1.4rem 0 0; padding: 0; display: grid; gap: .6rem; }
.soon-points li { display: flex; gap: .65rem; color: var(--board-ink); line-height: 1.45; }
.soon-points li::before { content: ""; flex: none; width: 7px; height: 7px; margin-top: .55em; border-radius: 2px; background: var(--accent-lift); }
.soon-meta { margin-top: 1.4rem; font-size: .9rem; }
.soon-band .hero-cta { margin-top: 1.6rem; }
.soon-band .btn-ghost { color: #fff; }

.perch-preview { position: relative; display: flex; gap: .7rem; align-items: stretch; }
.perch-card { flex: 1; background: #1d212b; border: 1px solid rgba(255,255,255,.08); border-radius: 12px 0 0 12px; padding: 1rem; box-shadow: 0 18px 50px rgba(0,0,0,.35); font-size: .82rem; }
.perch-strip { width: 34px; flex: none; align-self: center; display: flex; flex-direction: column; align-items: center; gap: .55rem; padding: .8rem 0; background: #1d212b; border: 1px solid rgba(255,255,255,.08); border-radius: 9px 0 0 9px; }
.perch-dot { width: 8px; height: 8px; border-radius: 2px; background: #a7a5b3; }
.perch-dot.working { width: 10px; height: 10px; background: #f2c14e; box-shadow: 0 0 9px rgba(242,193,78,.8); }
.perch-dot.needs { width: 10px; height: 10px; background: #b57bff; box-shadow: 0 0 9px rgba(181,123,255,.8); }
.perch-dot.done { background: #70c99a; }
.perch-dot.limit { background: #ff5a64; }
.perch-head { display: flex; justify-content: space-between; align-items: center; color: #fff; font-weight: 600; margin-bottom: .7rem; }
.perch-label { font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; color: var(--accent-lift); font-weight: 700; margin: .8rem 0 .45rem; }
.perch-row { display: flex; justify-content: space-between; align-items: center; gap: .6rem; padding: .45rem .55rem; margin-bottom: .35rem; border-radius: 7px; background: #262b37; color: var(--board-ink); }
.perch-row span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.perch-chip { flex: none; font-size: .66rem; font-weight: 700; letter-spacing: .03em; padding: .12rem .45rem; border-radius: 5px; border: 1px solid; }
.perch-chip.working { color: #f2c14e; border-color: rgba(242,193,78,.55); background: rgba(242,193,78,.12); }
.perch-chip.needs { color: #c9a2ff; border-color: rgba(181,123,255,.6); background: rgba(181,123,255,.14); }
.perch-chip.done { color: #8fd6a8; border-color: rgba(143,214,168,.45); background: rgba(143,214,168,.1); }
.perch-chip.limit { color: #ff8a92; border-color: rgba(255,90,100,.55); background: rgba(255,90,100,.12); }
.perch-bar { display: grid; grid-template-columns: 2.6rem 1fr auto; gap: .55rem; align-items: center; color: var(--board-ink-soft); margin-bottom: .2rem; }
.perch-track { height: 6px; border-radius: 3px; background: rgba(255,255,255,.12); overflow: hidden; }
.perch-track i { display: block; height: 100%; border-radius: 3px; background: #70c99a; }
.perch-timer { margin: 0 0 .5rem 3.15rem; font-size: .74rem; color: var(--board-ink); }
.perch-caption { margin-top: .8rem; font-size: .78rem; color: var(--board-ink-soft); }
@media (max-width: 860px) {
  .soon-grid { grid-template-columns: 1fr; }
}

/* Platform mark inside a button: the site now lists a Windows app too, so extension CTAs say "Chrome". */
.btn-icon { display: inline-block; width: 1.1em; height: 1.1em; margin-right: .55em; vertical-align: -.18em; background: currentColor;
  -webkit-mask: url("assets/icons/chrome.svg") center / contain no-repeat; mask: url("assets/icons/chrome.svg") center / contain no-repeat; }
.tt-platform { font-weight: 500; opacity: .6; }

/* Perch preview, round 2: agent marks, a shelf, and a looping drag-out of a screenshot. */
.perch-mark { width: 13px; height: 13px; flex: none; fill: none; stroke-width: 2.2; stroke-linecap: round; }
.perch-mark.claude { stroke: #d97757; }
.perch-mark.codex { stroke: #ededf2; }
.perch-row .perch-title { display: flex; align-items: center; gap: .45rem; min-width: 0; }
.perch-row .perch-title span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.perch-strip { gap: .5rem; }
.perch-slot { display: flex; flex-direction: column; align-items: center; gap: .3rem; }
.perch-slot .perch-mark { width: 10px; height: 10px; }
.perch-shelf { display: grid; grid-template-columns: 1fr 1fr; gap: .8rem; margin-top: .2rem; }
.perch-pile { position: relative; height: 62px; display: flex; justify-content: center; align-items: center; }
.perch-shot { position: absolute; width: 70px; height: 44px; border-radius: 5px; background: #34343f; padding: 2px; box-shadow: 0 3px 10px rgba(0,0,0,.45); }
.perch-shot i { display: block; width: 100%; height: 100%; border-radius: 3px;
  background: linear-gradient(#262b37 0 22%, transparent 22%), repeating-linear-gradient(#3b4252 0 3px, transparent 3px 8px) 8px 14px / 60% 60% no-repeat, #1b1f28; }
.perch-shot.back { transform: rotate(-8deg) translate(-7px, 2px); opacity: .85; }
.perch-shot.mid { transform: rotate(6deg) translate(6px, 0); opacity: .92; }
.perch-shot.front { z-index: 2; }
.perch-page { position: absolute; width: 40px; height: 52px; background: #f7f5fb; clip-path: polygon(0 0, 76% 0, 100% 18%, 100% 100%, 0 100%); box-shadow: 0 3px 10px rgba(0,0,0,.4); }
.perch-page.back { transform: rotate(-12deg) translate(-8px, 2px); opacity: .8; }
.perch-page b { position: absolute; left: 50%; bottom: 7px; transform: translateX(-50%); font: 700 7px/1 system-ui, sans-serif; color: #fff; background: #6d5dfb; border-radius: 2px; padding: 2px 3px; }
.perch-pill { display: block; text-align: center; margin-top: .25rem; font-size: .68rem; color: var(--board-ink-soft); }
.perch-cursor { position: absolute; z-index: 3; width: 14px; height: 14px; left: 50%; top: 50%; opacity: 0; pointer-events: none; }
.perch-cursor svg { width: 100%; height: 100%; fill: #fff; stroke: #15181e; stroke-width: 1.2; }
@media (prefers-reduced-motion: no-preference) {
  .perch-shot.front { animation: perch-drag 5.5s ease-in-out infinite; }
  .perch-cursor { animation: perch-cursor 5.5s ease-in-out infinite; }
}
@keyframes perch-drag {
  0%, 22% { transform: none; box-shadow: 0 3px 10px rgba(0,0,0,.45); }
  32% { transform: scale(1.15); box-shadow: 0 0 0 2px #a99bff, 0 10px 24px rgba(0,0,0,.5); }
  58% { transform: translate(-150px, -40px) rotate(-4deg) scale(1.08); box-shadow: 0 0 0 2px #a99bff, 0 14px 30px rgba(0,0,0,.55); opacity: 1; }
  66% { transform: translate(-150px, -40px) rotate(-4deg) scale(1.08); opacity: 0; }
  76% { transform: none; opacity: 0; }
  86%, 100% { transform: none; opacity: 1; }
}
@keyframes perch-cursor {
  0%, 18% { opacity: 0; transform: translate(10px, 12px); }
  26%, 32% { opacity: 1; transform: translate(4px, 6px); }
  58% { opacity: 1; transform: translate(-146px, -34px); }
  66%, 100% { opacity: 0; transform: translate(-146px, -34px); }
}

/* Perch preview, round 3: matte frosted glass (reference: owner-picked Webflow "Matt Glass" study).
   Blurred colour orbs sit behind; the panel and strip are frosted layers with an inner top highlight
   and an inner shadow for thickness. The preview tilts slightly toward the pointer (JS, reduced-motion aware). */
.perch-stage { position: relative; padding: 2.2rem 1.2rem; perspective: 900px; }
.perch-stage::before, .perch-stage::after, .perch-orb { content: ""; position: absolute; border-radius: 50%; filter: blur(42px); opacity: .55; pointer-events: none; }
.perch-stage::before { width: 190px; height: 190px; left: -10px; top: 8%; background: #7b5cff; }
.perch-stage::after { width: 160px; height: 160px; right: 0; bottom: 4%; background: #d97757; opacity: .45; }
.perch-orb { width: 120px; height: 120px; right: 22%; top: 38%; background: #3fbf8a; opacity: .35; }
.perch-stage .perch-preview { transform-style: preserve-3d; transition: transform .25s ease-out; will-change: transform; }
.perch-stage .perch-card,
.perch-stage .perch-strip {
  background: rgba(255,255,255,.055);
  -webkit-backdrop-filter: blur(22px) saturate(150%); backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid rgba(255,255,255,.13);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), inset 0 -18px 40px rgba(0,0,0,.28), 0 24px 60px rgba(0,0,0,.45);
}
.perch-stage .perch-row { background: rgba(255,255,255,.06); box-shadow: inset 0 1px 0 rgba(255,255,255,.07); }
.perch-stage .perch-shot { background: rgba(255,255,255,.14); }
.perch-stage .perch-caption { position: relative; }

/* Perch preview, round 4.
   Strip: like the app on a side edge - square then mark side by side, each square in a fixed 10px slot so
   every mark lines up in one column.
   Shelf: hovering a pile fans its cards into a row (the app's spread), and pauses the drag loop. */
.perch-stage .perch-strip { width: 40px; padding: .75rem 0; gap: .55rem; }
.perch-slot { flex-direction: row; gap: 4px; align-items: center; }
.perch-slot .perch-dotbox { width: 10px; height: 10px; display: flex; align-items: center; justify-content: center; flex: none; }
.perch-slot .perch-dot { width: 6px; height: 6px; }
.perch-slot .perch-dot.working, .perch-slot .perch-dot.needs { width: 10px; height: 10px; }
.perch-slot .perch-dot.done, .perch-slot .perch-dot.limit { width: 7px; height: 7px; }
.perch-slot .perch-mark { width: 10px; height: 10px; }

.perch-pile { cursor: grab; }
.perch-shot, .perch-page { transition: transform .35s cubic-bezier(.2,.8,.2,1), box-shadow .25s ease; }
.perch-pile:hover .perch-shot.front { animation: none; }
.perch-pile:hover .perch-cursor { animation: none; opacity: 0; }
.perch-pile:hover .perch-shot.back { transform: translateX(-58px) rotate(0deg); opacity: 1; }
.perch-pile:hover .perch-shot.mid { transform: translateX(0) rotate(0deg); opacity: 1; }
.perch-pile:hover .perch-shot.front { transform: translateX(58px); }
.perch-pile:hover .perch-page.back { transform: translateX(-24px) rotate(0deg); opacity: 1; }
.perch-pile:hover .perch-page:not(.back) { transform: translateX(24px); }
.perch-pile .perch-shot:hover, .perch-pile .perch-page:hover { z-index: 5; box-shadow: 0 0 0 2px #a99bff, 0 10px 24px rgba(0,0,0,.5); }
.perch-pile:hover .perch-shot:hover { transform: var(--spread, none) scale(1.14); }
.perch-pile:hover .perch-shot.back:hover { transform: translateX(-58px) scale(1.14); }
.perch-pile:hover .perch-shot.mid:hover { transform: scale(1.14); }
.perch-pile:hover .perch-shot.front:hover { transform: translateX(58px) scale(1.14); }
.perch-pile:hover .perch-page.back:hover { transform: translateX(-24px) scale(1.12); }
.perch-pile:hover .perch-page:not(.back):hover { transform: translateX(24px) scale(1.12); }

/* "Coming soon" made alive, in the site's departure-board language: a ticker that runs sideways across
   the top of the band, and a blinking lamp on the label. Static for reduced motion. */
.soon-band { position: relative; overflow: hidden; }
.soon-ticker { position: absolute; top: 0; left: 0; right: 0; height: 2.1rem; display: flex; align-items: center; overflow: hidden;
  border-bottom: 1px solid rgba(255,255,255,.1); background: rgba(255,255,255,.035);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.soon-ticker-track { display: flex; flex: none; white-space: nowrap; }
.soon-ticker-track span { padding-right: 2.2rem; font: 700 .72rem/1 var(--font-mono, ui-monospace, "Cascadia Mono", Consolas, monospace); letter-spacing: .22em; text-transform: uppercase; color: var(--board-ink-soft); }
.soon-ticker-track span b { color: #f2c14e; font-weight: 700; }
.soon-band > .wrap { padding-top: 2.1rem; }
.soon-lamp { display: inline-block; width: 8px; height: 8px; margin-right: .5rem; border-radius: 50%; background: #f2c14e; box-shadow: 0 0 10px rgba(242,193,78,.9); vertical-align: .05em; }
@media (prefers-reduced-motion: no-preference) {
  .soon-ticker-track { animation: soon-ticker 28s linear infinite; }
  .soon-lamp { animation: soon-lamp 1.6s ease-in-out infinite; }
}
@keyframes soon-ticker { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes soon-lamp { 0%, 100% { opacity: 1; } 50% { opacity: .25; box-shadow: none; } }