/* Surplus Pilot — the public page.

   Deliberately the same palette as the app (app/static/style.css), because the
   first thing someone does after reading this is open the app, and a different
   blue there would read as a different product.

   Rules held to throughout, because breaking them is what makes a page look
   generated rather than made:

   - hairlines, not drop shadows. One shadow exists, on the primary button.
   - no gradients as MATERIAL. A gradient may describe light falling off a
     surface, because that is what light does. It may never stand in for brushed
     metal or glass — that is the tell that nobody built the thing.
   - the hero is left-aligned. A centred headline over two centred buttons is
     the template every tool ships with.
   - part numbers, prices and confidences are set in mono. In this trade that
     is not decoration; it is how the number is written on the part.
   - one accent colour. Colour is reserved for state — matched, refused,
     caveat — so that when it appears it means something.
   - SHARP CORNERS on anything structural. Steel edges are sharp. A radius on a
     panel, a rack or a breaker is the single loudest cue that a page was
     assembled from rounded rectangles instead of drawn.

   TWO ZONES, since 26 Sept. The page was entirely dark, which made the hero
   the only thing it could be - there was nothing for it to be darker *than*.
   Now the warehouse is dark and everything after it is light, and that is the
   argument: surplus arrives in a dim building and leaves as a clean, listed,
   white-background photograph. The palette says the same thing the product
   does.

   Light is the DEFAULT here. Dark is scoped to `.dark-zone`, which the hero
   carries. Components below read only from tokens, so a component dropped into
   either zone takes that zone's colours with no extra rules.

   Contrast is measured, not eyeballed: `python tools/contrast.py` checks every
   pair that carries text and fails the build of anything below target. */

:root {
  color-scheme: light;

  /* ---- surfaces, lightest to deepest ------------------------------------ */
  /* Three distinct levels, and only ONE of them is blue.
     The page was #f4f8fb - a blue tint under everything - with white cards on
     top of it, which is a dashboard. The page is a neutral now, surfaces are
     white against it, and pale blue is spent where it means something: the
     navigation and the closing invitation. */
  --bg:        #f5f6f7;   /* the page: neutral, not tinted */
  --surface:   #ffffff;   /* a surface that sits ON the page */
  --surface-2: #eceef0;   /* a quieter surface */
  --band:      #dae8f3;   /* pale blue. Nav and the closing section only. */
  --band-deep: #c6dbeb;
  --panel:     #ffffff;

  /* ---- ink -------------------------------------------------------------- */
  --ink:       #0f1d2e;
  --ink-2:     #33506e;
  --dim:       #4c6480;
  --text:      var(--ink);      /* legacy alias, still referenced below */

  /* ---- hairlines. No drop shadows except the primary button. ------------- */
  --line:      #c3d6e6;
  --line-soft: #dfeaf3;

  /* ---- navy: every primary action, selected state and outline icon ------ */
  --navy:      #123a61;
  --navy-hi:   #1a5183;   /* hover */
  --navy-lo:   #0c2a47;   /* active / pressed */
  --on-navy:   #ffffff;

  /* ---- the warm neon, carried through sparingly -------------------------
     Two values, because the tube colour cannot be read as text on white. The
     glow stays #ff8a2b wherever it is LIGHT; anything that has to be read at
     text size uses --neon-ink. */
  --neon:      #ff8a2b;
  --neon-ink:  #8a4109;
  --neon-wash: #fdeee0;
  --neon-core: #ffdcb0;
  --neon-deep: #c44a12;
  --argon:     #2f7f9c;
  --glass:     #2f363c;

  --accent:    var(--navy);
  --on-accent: var(--on-navy);

  /* ---- state ------------------------------------------------------------ */
  --ok:        #1d7a45;
  --ok-ink:    #14562f;
  --ok-wash:   #e2f3e8;
  --warn:      #8a5a05;
  --warn-wash: #fcf0d9;
  --bad:       #a3271c;
  --bad-ink:   #8c2016;
  --bad-wash:  #fbe6e3;
  --tag-ok-bg: var(--ok-wash);
  --tag-bad-bg: var(--bad-wash);

  --focus:     #1a5183;

  --sans: Archivo, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI",
          Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", "Cascadia Mono",
          "Roboto Mono", Menlo, Consolas, monospace;

  --wrap: 1180px;
  --wrap-wide: 1360px;
  --gutter: 24px;

  /* The sticky navigation bar's own height: 16px of padding top and bottom,
     the CTA button between them, and the hairline under it. The hero is sized
     to the window MINUS this, which is the whole reason it is written down
     rather than left implicit - change the nav padding and the hero stops
     reaching the bottom of the screen. Verified by measurement, not by
     adding the numbers up. */
  --nav-h: 75px;
}

/* The warehouse. Everything inside keeps the old dark palette, so the hero
   reads as the same room it was rendered in. */
.dark-zone {
  color-scheme: dark;

  /* The building. Desaturated blue-grey concrete and steel, never black. */
  --bg: #14181c;
  --band: #191e23;
  --panel: #1c2228;
  --text: #e6eaed;
  --dim: #8d98a2;
  --line: #2b333a;
  --line-soft: #222a31;

  /* Neon gas burns orange-red. Argon with mercury burns blue-white. Those are
     the two colours on this page and they are the two real ones. Nothing is
     fully saturated, because a tube never is. */
  --neon: #ff8a2b;
  --neon-core: #ffdcb0;
  --neon-deep: #c44a12;
  --argon: #7fc7de;
  --glass: #2f363c;          /* an UNLIT tube: grey, faintly green, dusty */

  --surface: #1c2228;
  --surface-2: #232a31;
  --ink: #e6eaed;
  --ink-2: #b4bec7;

  /* Navy at the light-zone value (#123a61) has a 1.6:1 contrast against this
     wall - the button would have no visible edge. So the dark zone uses navy
     lifted until the BUTTON separates from the panel, not just its label:
     3.3:1 against the panel, 5.5:1 for white on top of it. Same family, same
     read, and the primary action looks like the same control it is further
     down the page. */
  --navy: #2a6ba8;
  --navy-hi: #3781c4;
  --navy-lo: #1d5183;
  --on-navy: #ffffff;
  --neon-ink: #ffb066;
  --neon-wash: #2a1a0c;

  --accent: #ff8a2b;
  --on-accent: #241004;
  --ok: #6fc38a;
  --ok-ink: #8ed6a6;
  --ok-wash: #16281d;
  --warn: #e0a83c;
  --warn-wash: #2b2210;
  --bad: #e0685c;
  --bad-ink: #ef8a80;
  --bad-wash: #2c1714;
  --tag-ok-bg: #16281d;
  --tag-bad-bg: #2c1714;

  --focus: #ff8a2b;
}

* { box-sizing: border-box; }

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

/* Smooth scrolling is DESKTOP ONLY. It is an animation - an anchor click
   becomes a half-second glide - and the phone experience is meant to have
   none. Same for anyone who asked for reduced motion. */
@media (min-width: 761px) and (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* A blanket stop, so a transition added later cannot quietly opt itself in. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }
.wrap.narrow { max-width: 760px; }

a { color: var(--navy); text-decoration: none; }
a:hover { text-decoration: underline; }

.mono { font-family: var(--mono); font-variant-ligatures: none; }
.dim { color: var(--dim); }
.small { font-size: 14px; }

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

/* ---------------------------------------------------------------- nav */

.nav {
  position: sticky; top: 0; z-index: 10;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
  max-width: none; margin: 0;
  padding: 16px max(var(--gutter), calc((100% - var(--wrap-wide)) / 2));
  background: var(--band);
  border-bottom: 1px solid var(--line);
}
.nav::after {
  content: ""; position: absolute; left: var(--gutter); right: var(--gutter);
  bottom: 0; height: 1px; background: transparent;
}

.wordmark {
  display: inline-flex; align-items: center; gap: 11px;
  color: var(--ink); font-weight: 700; font-size: 19px; letter-spacing: -.016em;
}
.wordmark:hover { text-decoration: none; }
.wordmark svg { color: var(--navy); flex: none; }

.nav nav { display: flex; align-items: center; gap: 24px; }
.nav nav a { color: var(--ink-2); font-size: 15px; }
.nav nav a:hover { color: var(--ink); text-decoration: none; }

/* The nav CTA is the page's one repeated action, so it looks like the action
   it repeats: the same navy as the hero button, not a coloured link. */
.nav-cta {
  color: var(--on-navy) !important;
  font-weight: 550;
  padding: 8px 15px;
  background: var(--navy);
  border: 1px solid var(--navy);
  border-radius: 8px;
}
.nav-cta:hover {
  text-decoration: none;
  background: var(--navy-hi); border-color: var(--navy-hi);
}
.nav-cta:active { background: var(--navy-lo); border-color: var(--navy-lo); }

/* Sign in reads as a control rather than another section link, because it
   leaves the page. Quiet, but not hidden - it is the one thing an existing
   user is here for. */
.nav-signin {
  color: var(--ink) !important;
  font-weight: 500;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
}
.nav-signin:hover {
  text-decoration: none;
  border-color: var(--navy); color: var(--navy) !important;
}

@media (max-width: 720px) {
  .nav nav a:not(.nav-cta):not(.nav-signin) { display: none; }
  .nav nav { gap: 10px; }
  .nav-cta { display: none; }        /* the hero repeats it two lines down */
}

/* ------------------------------------------------------------- sections */

section { padding: clamp(60px, 7vw, 104px) 0; }

/* A band is now a PALE BLUE section, not a slightly-different dark one. Used
   for the sections that should read as a held moment - the closing early
   access, and anything selected. Most sections stay on the page background so
   the bands mean something when they appear. */
section.band { background: var(--band); border-block: 1px solid var(--line); }
section.band-deep { background: var(--band-deep); }


h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -.03em; }

h1 {
  font-size: clamp(2.5rem, 6.6vw, 4.3rem);
  line-height: 1.02;
  margin: 0 0 26px;
}

h2 {
  font-size: clamp(1.75rem, 3.6vw, 2.5rem);
  line-height: 1.12;
  margin: 0 0 22px;
  max-width: 20ch;
}
section.band h2, section h2 { max-width: 24ch; }

h3 { font-size: 1.0625rem; letter-spacing: -.015em; margin: 0 0 6px; }

/* Readable measure. Long lines are the fastest way to make a page feel
   like it was poured in rather than set. */
.prose { max-width: 64ch; color: var(--dim); }
.prose p { margin: 0 0 18px; }
.prose p:last-child { margin-bottom: 0; }
.prose strong { color: var(--text); font-weight: 550; }

.caption { margin: 22px 0 0; font-size: 14px; color: var(--dim); max-width: 60ch; }

/* ----------------------------------------------------------------- hero */

.hero {
  max-width: var(--wrap); margin: 0 auto;
  padding: 72px var(--gutter) 88px;
  display: grid; grid-template-columns: 1.05fr .95fr; gap: 56px; align-items: start;
}
@media (max-width: 900px) {
  .hero { grid-template-columns: 1fr; gap: 44px; padding: 44px var(--gutter) 64px; }
}

.eyebrow {
  margin: 0 0 20px;
  font-family: var(--mono);
  font-size: 12.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--dim);
}

.lede {
  max-width: 58ch;
  margin: 0 0 34px;
  font-size: clamp(1.0625rem, 1.6vw, 1.1875rem);
  line-height: 1.58;
  color: var(--dim);
}
.lede strong { color: var(--text); font-weight: 600; font-family: var(--mono); font-size: .96em; }

.cta-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 0 24px;
  border: 1px solid var(--navy); border-radius: 9px;
  background: var(--navy); color: var(--on-navy);
  font: inherit; font-weight: 550; font-size: 16px;
  box-shadow: 0 1px 2px rgba(17,20,26,.16);
  cursor: pointer;
}
.btn:hover {
  text-decoration: none;
  background: var(--navy-hi); border-color: var(--navy-hi);
}
.btn:active { background: var(--navy-lo); border-color: var(--navy-lo); }
.btn[disabled], .btn[aria-disabled="true"] {
  background: var(--surface-2); border-color: var(--line);
  color: var(--dim); box-shadow: none; cursor: not-allowed;
}

.btn.ghost {
  background: var(--surface); color: var(--ink);
  border-color: var(--line); box-shadow: none;
}
.btn.ghost:hover { background: var(--surface-2); border-color: var(--navy); }
.btn.ghost:active { background: var(--band); }

/* One focus ring for the whole page. It is offset so it never sits on top of
   the control's own border, and it uses a token so the dark zone gets a ring
   that is visible against a dark wall rather than a navy one that vanishes. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 4px;
}

.fineprint { margin: 20px 0 0; font-size: 14px; color: var(--dim); }

/* ------------------------------------------------- the plate read panel

   The argument of the whole product in one object: every string the reader
   transcribed off the nameplate, and the catalogue's verdict on each. No
   competitor shows this, because for everyone else the rejected lines are the
   embarrassing part. For us they are the product. */

.plate {
  margin: 0;
  border: 1px solid var(--line); border-radius: 12px;
  background: var(--panel); overflow: hidden;
  font-family: var(--mono);
}
.plate-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 13px 18px; border-bottom: 1px solid var(--line-soft);
  font-size: 12px; letter-spacing: .07em; text-transform: uppercase; color: var(--dim);
}
.plate-rows { list-style: none; margin: 0; padding: 0; }
.plate-rows li {
  display: grid; grid-template-columns: 1fr auto; gap: 6px 14px;
  align-items: baseline;
  padding: 11px 18px; border-bottom: 1px solid var(--line-soft);
}
.plate-rows li:last-child { border-bottom: 0; }
.plate-rows .str { font-size: 15px; color: #939cab; }
.plate-rows .why {
  font-size: 12px; color: #939cab; text-align: right; font-family: var(--sans);
}
.plate-rows li.out .str { text-decoration: line-through; text-decoration-color: #b9c1cc; }
.plate-rows li.hit { background: var(--tag-ok-bg); border-bottom-color: transparent; }
.plate-rows li.hit .str {
  color: var(--text); font-size: 19px; font-weight: 600; letter-spacing: -.01em;
}
.plate-rows li.hit .why { color: var(--ok); font-weight: 550; }
.plate-foot {
  margin: 0; padding: 13px 18px; border-top: 1px solid var(--line-soft);
  font-size: 12.5px; color: var(--dim); font-family: var(--sans); line-height: 1.5;
}

/* ---------------------------------------------------------------- cards */

.two-up {
  display: grid; grid-template-columns: 1fr 1fr; gap: 20px;
  margin-top: 44px;
  align-items: start;
}
@media (max-width: 760px) { .two-up { grid-template-columns: 1fr; } }

.card {
  margin: 0;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
}
.card-head { padding: 14px 20px; border-bottom: 1px solid var(--line-soft); }
.card-body { padding: 20px; }

.badge {
  display: inline-block; padding: 4px 10px; border-radius: 999px;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .04em;
  text-transform: uppercase;
}
.badge.ok  { background: var(--tag-ok-bg);  color: var(--ok); }
.badge.bad { background: var(--tag-bad-bg); color: var(--bad); }

.mpn {
  margin: 0 0 4px;
  font-family: var(--mono);
  font-size: clamp(1.375rem, 3vw, 1.75rem);
  font-weight: 600; letter-spacing: -.01em;
}
.mpn.muted { color: var(--dim); }

.brand { margin: 0 0 18px; color: var(--dim); font-size: 15px; }

/* A definition list, not a table: these are facts about one thing, and the
   labels want to sit quietly to the left of the values. */
.kv { margin: 0; display: grid; grid-template-columns: 9.5em 1fr; gap: 0; }
.kv dt {
  padding: 9px 0; border-top: 1px solid var(--line-soft);
  font-size: 13.5px; color: var(--dim);
}
.kv dd {
  margin: 0; padding: 9px 0; border-top: 1px solid var(--line-soft);
  font-size: 14.5px;
}
.kv dd.warn { color: var(--warn); }
@media (max-width: 460px) {
  .kv { grid-template-columns: 1fr; }
  .kv dt { padding-bottom: 0; border-top: 1px solid var(--line-soft); }
  .kv dd { padding-top: 2px; border-top: 0; }
}

.card.refuse { border-color: #eccbc6; }

.price-card { max-width: 420px; margin-top: 40px; }
.price-card .label {
  margin: 0 0 6px; font-size: 13.5px; color: var(--dim);
}
.price-card .big {
  margin: 0; font-size: 2.75rem; font-weight: 600; letter-spacing: -.03em;
  line-height: 1;
}
.price-card .band-line {
  margin: 8px 0 18px; font-size: 14px; color: var(--dim);
}

/* ---------------------------------------------------------------- steps */

.steps { list-style: none; margin: 44px 0 0; padding: 0; }
.steps li {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 0 20px;
  padding: 26px 0;
  border-top: 1px solid var(--line);
  max-width: 78ch;
}
.steps li:last-child { border-bottom: 1px solid var(--line); }
.steps .num {
  grid-row: span 2;
  font-family: var(--mono); font-size: 13px; color: var(--accent);
  padding-top: 3px;
}
.steps h3 { grid-column: 2; }
.steps p { grid-column: 2; margin: 0; color: var(--dim); max-width: 60ch; }

@media (max-width: 520px) {
  .steps li { grid-template-columns: 30px 1fr; gap: 0 14px; }
}

/* ----------------------------------------------------------------- nots */

.nots { list-style: none; margin: 34px 0 0; padding: 0; max-width: 66ch; }
.nots li {
  padding: 20px 0 20px 26px;
  border-top: 1px solid var(--line);
  color: var(--dim);
  position: relative;
}
.nots li:last-child { border-bottom: 1px solid var(--line); }
.nots li::before {
  content: ""; position: absolute; left: 0; top: 30px;
  width: 11px; height: 1.5px; background: var(--bad);
}
.nots strong { color: var(--text); font-weight: 600; }

/* ------------------------------------------------------------- waitlist */

/* The form is a COLUMN now: label, field, full-width button. It used to be a
   flex row with `flex: 1 1 260px` on the input, and once the card wrapped it
   onto its own line that flex-grow stretched it to the row's full height -
   a 140px tall single-line email box. Stacked, there is no row to fill. */
.waitlist {
  display: block;
  margin: 0;
  max-width: none;
}
.waitlist input {
  display: block;
  width: 100%;
  min-height: 48px; height: 48px; padding: 0 14px;
  border: 1px solid var(--line); border-radius: 9px;
  background: var(--surface); color: var(--ink);
  font: inherit; font-size: 16px;
}
.waitlist input::placeholder { color: #9aa3b0; }
.waitlist input:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 2px; border-color: var(--focus);
}
.waitlist input[aria-invalid="true"] { border-color: var(--bad); }

.formnote { margin: 14px 0 0; font-size: 14.5px; min-height: 1.2em; }
.formnote.ok  { color: var(--ok); }
.formnote.err { color: var(--bad); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* --------------------------------------------------------------- footer */

/* Three columns: who this is, the legal links, and the trademark notice.
   It was one left-aligned paragraph block.

   Written in this stylesheet's own idiom rather than in utility classes -
   there is no Tailwind on this site, so `border-t border-slate-200 py-12`
   has to become the hairline, the token and the padding that everything else
   here already uses. Colours are --dim and --ink-2, which tools/contrast.py
   already measures against this background at 5.64:1 and 8.36:1, rather than
   two new hex values nothing checks. */
footer {
  padding: 56px 0 64px;
  border-top: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--dim);
}

.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, auto) minmax(0, 1.5fr);
  gap: clamp(28px, 4vw, 72px);
  align-items: start;
}

footer p { margin: 0 0 8px; max-width: 70ch; font-size: 13.5px; line-height: 1.6; }
footer .mono { color: var(--text); }

/* Grid children default to min-width:auto, which lets a long word push a
   column wider than its track. The disclaimer is one long paragraph. */
.foot-brand,
.foot-col { min-width: 0; }

.foot-logo {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
  color: var(--ink);
  font-weight: 600;
  font-size: 15px;
  letter-spacing: -.012em;
}
.foot-logo svg { color: var(--navy); flex: none; }

.foot-beta {
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim);
  border: 1px solid var(--line);
  padding: 2px 7px;
}

.foot-head {
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.foot-disclaimer p { max-width: 62ch; margin: 0; }

/* Stacked on a phone, in the order somebody would read them. */
@media (max-width: 760px) {
  footer { padding: 40px 0 48px; }
  .foot-grid { grid-template-columns: 1fr; gap: 32px; }
}

/* ----------------------------------------------------------------- dark
   There is no light version any more. The sign is the light source, so a
   daylight palette would leave nothing for it to be brighter than. The old
   prefers-color-scheme block is gone rather than kept as a second theme
   nobody maintains — a page that ships two palettes and only ever looks at
   one of them is how the unreadable-in-dark-mode bug happens. */
