/* Leakplate v2 — blocks.css
 *
 * The page stylesheet. Linked third, after tokens.css and tokens-dark.css, and it types no hex:
 * every colour here is a token from DESIGN.md §2, so `bin/contrast.mjs` measuring those two
 * files is measuring this page too.
 *
 * The whole site is one idea — a technical plate read on graph paper — so there is no card, no
 * gradient, no shadow except --shadow-plate on the hero, and --r-none is the default radius.
 * DESIGN.md §14 is the list this file was written against.
 */

/* ------------------------------------------------------------------------------- fonts
 * Self-hosted, both OFL, licences shipped beside the files. Three files, 52 KB.
 * Only the variable display face is preloaded: the mono is used below the fold first. */

@font-face {
  font-family: 'Space Grotesk Variable';
  src: url('fonts/space-grotesk-latin-wght-normal.woff2') format('woff2-variations');
  font-weight: 300 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('fonts/ibm-plex-mono-latin-400-normal.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('fonts/ibm-plex-mono-latin-500-normal.woff2') format('woff2');
  font-weight: 500; font-style: normal; font-display: swap;
}

/* --------------------------------------------------------------------------------- base */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--frost-050);
  color: var(--graphite-700);
  font-family: var(--font-display);
  font-size: var(--step-body);
  line-height: var(--lh-body);
  /* DESIGN.md §4: the blueprint grid is real and visible, painted on the page ground once so
   * sections sit on it and look drawn rather than placed. Majors line up with the 64px rhythm
   * and minors with the 4px spacing scale. */
  background-image:
    repeating-linear-gradient(to right,  var(--frost-200) 0 1px, transparent 1px var(--grid-major)),
    repeating-linear-gradient(to bottom, var(--frost-200) 0 1px, transparent 1px var(--grid-major)),
    repeating-linear-gradient(to right,  color-mix(in srgb, var(--frost-300) 45%, transparent) 0 1px, transparent 1px var(--grid-minor)),
    repeating-linear-gradient(to bottom, color-mix(in srgb, var(--frost-300) 45%, transparent) 0 1px, transparent 1px var(--grid-minor));
}

h1, h2, h3, p, ul, ol, figure { margin: 0; }
img, svg, video { display: block; max-width: 100%; }

h1 {
  font-size: var(--step-h1); line-height: var(--lh-h1); letter-spacing: var(--tr-h1);
  font-weight: 600; color: var(--graphite-900); max-width: 16ch;
}
h2 {
  font-size: var(--step-h2); line-height: var(--lh-h2); letter-spacing: var(--tr-h2);
  font-weight: 600; color: var(--graphite-900); max-width: 20ch;
}
.lead { font-size: var(--step-lead); line-height: var(--lh-lead); max-width: var(--measure-lead); }
.cap {
  font-size: var(--step-caption); line-height: var(--lh-caption);
  color: var(--graphite-500); max-width: var(--measure-caption);
}

a { color: var(--ice-500); text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }

/* The one thing no visitor should have to tab past the whole nav to reach. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 9;
  background: var(--frost-050); color: var(--graphite-900);
  padding: var(--space-3) var(--space-4); border: var(--bw-hairline) solid var(--frost-200);
}
.skip:focus { left: var(--page-margin); top: var(--space-2); }

.wrap, .hdr, .hero, .blk, .call, .ft, .illus {
  max-width: calc(var(--content-max) + var(--page-margin) * 2);
  margin-inline: auto;
  padding-inline: var(--page-margin);
}

/* ------------------------------------------------------------------------------ header */

.hdr {
  display: flex; align-items: center; gap: var(--space-6);
  padding-block: var(--space-4);
  border-bottom: var(--bw-hairline) solid var(--frost-200);
  background: var(--frost-050);
}
.brand {
  display: inline-flex; align-items: center; gap: var(--space-2);
  color: var(--graphite-900); text-decoration: none;
  font-weight: 600; letter-spacing: -0.01em;
}
.mark { width: 24px; height: 24px; color: var(--graphite-900); --logo-ice: var(--ice-400); }
.nav { display: flex; gap: var(--space-5); margin-left: auto; font-size: var(--step-caption); }
.nav a { color: var(--graphite-700); text-decoration: none; }
.nav a:hover { color: var(--ice-500); text-decoration: underline; text-underline-offset: 0.18em; }

/* -------------------------------------------------------------------------------- hero
 *
 * Not text-left / card-right. That composition is on the forbidden list in the DESIGN BAR v2
 * block of AGENTS.md because all five inherited sites wore it. Here the sentence sits above a
 * full-width plate, and the plate is the product moment.
 *
 * The plate is 1200px of 16:9 and the text above it is 300px tall, so on a 1440x900 fold all
 * six record rows and the whole gauge are above the line — measured with ts-shoot-fold, not
 * assumed.
 */

.hero { position: relative; padding-block: var(--space-5) var(--space-section); }
/* Measured, not guessed: ts-shoot-fold put the plate's top at y=407 on a 1440x900 fold, which
 * cut the sixth record row — and the two empty slots in rows 5 and 6 are the argument the whole
 * page makes. Tightening the four gaps above the plate by 32px is what moves the sixth row back
 * above the line without shrinking the drawing. */
.hero-say { display: grid; gap: var(--space-3); }
.cta-row {
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap;
  margin-top: 0; margin-bottom: var(--space-5);
}

.btn {
  display: inline-block; text-decoration: none;
  background: var(--graphite-900); color: var(--frost-050);
  font-family: var(--font-display); font-weight: 500; font-size: var(--step-body);
  padding: 14px 24px; border: 0; border-radius: var(--r-control);
  transition: background var(--dur-state) var(--ease-state);
}
.btn:hover { background: var(--graphite-700); }

/* DESIGN.md §5 and §11.1: the honest line is this tag beside the CTA, never a bar at the top
 * of the page. The 5px open circle is --ice-400, which is a non-text mark and allowed to be. */
.tag {
  display: inline-flex; align-items: center; gap: var(--space-2);
  /* The display face, and no tracking. DESIGN.md §5 fixes this tag's size, colour, border and
   * leading circle but not its family; §3 fixes the rest — "the citation chip is the only
   * tracked-out type", and a numeral is never set in the display face but this is a sentence
   * with no numeral in it. Set in tracked-out mono it read as a string of code beside the CTA. */
  font-family: var(--font-display); font-size: var(--step-cite); line-height: 1.45;
  color: var(--graphite-500);
  border: var(--bw-hairline) solid var(--frost-200); border-radius: var(--r-chip);
  padding: 7px 10px;
}
.tag::before {
  content: ''; width: 5px; height: 5px; border-radius: 50%;
  border: 1px solid var(--ice-400); flex: none;
}

/* Phaidra's device: a drafting rail down the page margin with one open circle on it, level
 * with the gauge's centreline. Decorative, so it is hidden from assistive tech. */
.rail { display: none; }
@media (min-width: 1200px) {
  .rail {
    display: block; position: absolute; left: calc(var(--page-margin) / 2); top: var(--space-6);
    width: 1px; bottom: var(--space-section); background: var(--frost-300);
  }
  .rail::after {
    content: ''; position: absolute; left: -3px; top: 62%;
    width: 7px; height: 7px; border-radius: 50%; border: 1px solid var(--ice-400);
    background: var(--frost-050);
  }
}

/* The one shadow on the site, and the reason for it: it lets the video sit *on* the graph
 * paper rather than in it (DESIGN.md §4). */
.plate-hero {
  position: relative;
  background: var(--frost-100);
  border: var(--bw-plate) solid var(--frost-200);
  box-shadow: var(--shadow-plate);
}
.plate-hero img, .plate-hero video { width: 100%; height: auto; background: var(--frost-100); }
.plate-hero figcaption {
  font-family: var(--font-data); font-size: var(--step-cite); letter-spacing: var(--tr-cite);
  color: var(--graphite-500);
  padding: var(--space-3) var(--space-4);
  border-top: var(--bw-hairline) solid var(--frost-200);
}

/* ------------------------------------------------------------------- the visual blocks */

.blk { padding-block: var(--space-section); }
.blk > h2 + .cap { margin-top: var(--space-3); }
.draw { margin-top: var(--space-7); }
.draw svg { width: 100%; height: auto; }
.draw--plate svg { background: var(--frost-100); }

/* One drawing per viewport. `display: none` keeps the other out of the accessibility tree,
 * so a screen reader is read one figure and not two (DESIGN.md §12). */
.fig--narrow { display: none; }
@media (max-width: 767px) {
  .fig--wide { display: none; }
  .fig--narrow { display: block; }
}

/* SVG type. Every numeral, cite and record value is the data face with tabular figures, which
 * is the rule that makes this site look like itself (DESIGN.md §3). */
.draw text { font-family: var(--font-data); font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1, 'zero' 1; font-weight: 400; }
.draw text.p { font-family: var(--font-display); font-variant-numeric: normal; }
.draw text.v { font-weight: 500; }
.draw text.h3 { font-weight: 500; letter-spacing: var(--tr-h3); }
.draw text.cite { letter-spacing: var(--tr-cite); }

.f-g700 { fill: var(--graphite-700); }
.f-g500 { fill: var(--graphite-500); }
.f-g400 { fill: var(--graphite-400); }
.f-ice700 { fill: var(--ice-700); }
.f-steam050 { fill: var(--steam-050); }
.f-steam300 { fill: var(--steam-300); }

.s-frost200 { stroke: var(--frost-200); }
.s-frost300 { stroke: var(--frost-300); }
.s-vault700 { stroke: var(--vault-700); }
.s-ice150 { stroke: var(--ice-150); }
.s-ramp1 { stroke: var(--ice-ramp-1); }
.s-ramp2 { stroke: var(--ice-ramp-2); }
.s-ramp3 { stroke: var(--ice-ramp-3); }

.chip rect { fill: none; stroke: var(--frost-200); stroke-width: 1; }
.chip .chip-tick { fill: var(--ice-400); stroke: none; }
.chip--dark rect { stroke: var(--vault-700); }
.chip--dark .chip-tick { fill: var(--ice-150); }

/* Bar ends are square, not the dataviz skill's 4px round: this system's radius is 0 and
 * consistency with the plate wins (DESIGN.md §6.4). */
.bar { stroke: none; }
.bar--full { fill: var(--graphite-400); }
.bar--added { fill: var(--graphite-700); }
.node { fill: var(--ice-400); }
.plate-edge { fill: var(--frost-100); stroke: var(--frost-200); stroke-width: var(--bw-plate); }
.slot { fill: none; stroke: var(--graphite-400); stroke-width: 1; stroke-dasharray: 3 3; }

/* The hit target is the whole row, not the 2px mark (DESIGN.md §6.5). */
.hit { cursor: default; }

/* ------------------------------------------------------- the one inverted band (§5, §9) */

.band {
  background: var(--vault-900);
  color: var(--steam-050);
  max-width: none;
  padding-inline: max(var(--page-margin), calc(50vw - var(--content-max) / 2));
}
.band h2 { color: var(--steam-050); }
.band .cap { color: var(--steam-300); }

/* ------------------------------------------------------------------- illustrative line */

.illus {
  font-family: var(--font-data); font-size: var(--step-caption); color: var(--graphite-500);
  padding-block: var(--space-7) 0;
}

/* -------------------------------------------------------------------------- the call */

.call {
  padding-block: var(--space-section);
  display: grid; gap: var(--space-8);
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: start;
}
.call-say { display: grid; gap: var(--space-3); }

.form {
  display: grid; gap: var(--space-4) var(--space-4);
  grid-template-columns: 1fr 1fr;
  background: var(--frost-100);
  border: var(--bw-plate) solid var(--frost-200);
  padding: var(--space-6);
}
.form-intro, .form-foot, .f--wide, .hp { grid-column: 1 / -1; }
.form-intro { font-size: var(--step-caption); color: var(--graphite-500); }
.form-foot { font-size: var(--step-cite); line-height: 1.5; color: var(--graphite-500); font-family: var(--font-data); }

.f { display: grid; gap: var(--space-2); }
.f label { font-size: var(--step-caption); color: var(--graphite-500); }
.f input, .f select, .f textarea {
  font: inherit; font-size: var(--step-body);
  color: var(--graphite-700); background: var(--frost-050);
  border: var(--bw-hairline) solid var(--frost-200); border-radius: var(--r-control);
  min-height: 44px; padding: 10px 12px; width: 100%;
  transition: border-color var(--dur-state) var(--ease-state);
}
.f textarea { min-height: 88px; resize: vertical; }
.f input:hover, .f select:hover, .f textarea:hover { border-color: var(--graphite-400); }

/* There is no red on this site, not even here. A field that needs attention gets the 2px
 * --graphite-900 border and a sentence saying what is missing (DESIGN.md §11.3). */
.f [aria-invalid="true"] { border: var(--bw-plate) solid var(--graphite-900); }
.err {
  font-size: var(--step-caption); color: var(--graphite-700);
  border-left: var(--bw-plate) solid var(--graphite-900); padding-left: var(--space-3);
}
.err[hidden] { display: none; }

.consent { display: grid; grid-template-columns: auto 1fr; gap: var(--space-3); align-items: start; }
.consent input { min-height: 0; width: 18px; height: 18px; margin-top: 3px; }
.consent label { font-size: var(--step-caption); color: var(--graphite-700); }
.consent .err { grid-column: 1 / -1; }

.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.submit { display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; }
.submit button {
  font-family: var(--font-display); font-weight: 500; font-size: var(--step-body);
  background: var(--graphite-900); color: var(--frost-050);
  border: 0; border-radius: var(--r-control); padding: 14px 24px; cursor: pointer;
  transition: background var(--dur-state) var(--ease-state);
}
.submit button:hover { background: var(--graphite-700); }
.submit button[disabled] { background: var(--graphite-500); cursor: default; }
.live { font-size: var(--step-caption); color: var(--graphite-700); }

/* Sent replaces the form, so nobody re-submits what already went (UX-COPY.md states table). */
.form[data-state="done"] > :not(.live-wrap):not(.submit),
.form[data-state="already"] > :not(.live-wrap):not(.submit) { display: none; }
.form[data-state="done"] .submit button,
.form[data-state="already"] .submit button { display: none; }

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

.ft {
  border-top: var(--bw-hairline) solid var(--frost-200);
  background: var(--frost-100);
  padding-block: var(--space-6);
  max-width: none;
}
.ft > * { max-width: var(--content-max); margin-inline: auto; }
.ft-nav { display: flex; gap: var(--space-5); flex-wrap: wrap; margin-bottom: var(--space-4); font-size: var(--step-caption); }
.ft p { font-size: var(--step-caption); color: var(--graphite-500); }

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

@media (max-width: 1199px) {
  .call { grid-template-columns: 1fr; gap: var(--space-6); }
}
@media (max-width: 767px) {
  :root { --space-section: var(--space-8); --page-margin: 20px; }
  body {
    /* Below 768px only the majors are painted: minors at 8px on a 390px screen are noise. */
    background-image:
      repeating-linear-gradient(to right,  var(--frost-200) 0 1px, transparent 1px var(--grid-major)),
      repeating-linear-gradient(to bottom, var(--frost-200) 0 1px, transparent 1px var(--grid-major));
  }
  .hdr { flex-wrap: wrap; gap: var(--space-2); padding-block: var(--space-3); }
  .nav { margin-left: 0; width: 100%; gap: var(--space-4); flex-wrap: wrap; font-size: var(--step-cite); }
  .hero { padding-block: var(--space-5) var(--space-section); }
  .cta-row { margin-bottom: var(--space-5); }
  .btn, .submit button { width: 100%; text-align: center; }
  .form { grid-template-columns: 1fr; padding: var(--space-5); }
  h1 { max-width: none; }
}

/* ---------------------------------------------------------------------- reduced motion
 *
 * DESIGN.md §7: the <video> is not rendered at all and the poster <img> takes its place at the
 * same dimensions, so nothing shifts and the story still lands. hero.js enforces the first
 * half; this is the half that stops anything else from moving. */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important;
  }
}
