/* ==========================================================================
   workley landing — style.css
   Implements docs/AI_LAB_BRAND_SYSTEM.md (DARK preset, MONO mode, pairing A)
   as bound by docs/WORKLEY_SITE_SPEC.md. Grayscale carries the design; the
   only non-gray pixels are --ok inside status/terminal UI.
   ========================================================================== */

/* 0a · Fonts — local, no CDN (Geist variable 400-600, SIL OFL). Site renders
   fully offline; zero external requests, matching the product's zero-egress
   posture. Decision E, 2026-07-17, founder-approved: replaces the prior
   Google Fonts CDN link. Range 400-600 covers weight 540 used by h1/h2. */
@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("vendor/fonts/geist-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("vendor/fonts/geist-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("vendor/fonts/geist-mono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("vendor/fonts/geist-mono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Signature-motif glyphs — box-drawing pipeline, arrows, blocks, geometric
   status marks — subset from the same OFL Geist v1.7.2 release (spec §2
   Decision E, brand §6 motifs 3-4). Without these the motifs render in the
   visitor's system mono and the locked pipeline's corners shatter. */
@font-face {
  font-family: "Geist";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("vendor/fonts/geist-symbols.woff2") format("woff2");
  unicode-range: U+2190-21FF, U+2205, U+2500-25FF, U+2713, U+26A0;
}
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("vendor/fonts/geist-mono-symbols.woff2") format("woff2");
  unicode-range: U+2190-21FF, U+2205, U+2500-25FF, U+2713, U+26A0;
}
/* Geist Mono genuinely lacks these five (∅ ▸ ▾ ✓ ⚠); vendored from
   JetBrains Mono (SIL OFL, the declared fallback). Advance is 600/1000em —
   identical to Geist Mono's — so no size-adjust is needed (verified with
   fontTools hmtx). Declared last: this face wins for exactly these points. */
@font-face {
  font-family: "Geist Mono";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("vendor/fonts/jetbrains-mono-symbols.woff2") format("woff2");
  unicode-range: U+2205, U+25B8, U+25BE, U+2713, U+26A0;
}

/* 0 · Tokens — brand system §3.1 (DARK), §4.2, §5 */
:root {
  color-scheme: dark;
  --bg:        #0A0A0A;
  --surface:   #111111;
  --surface-2: #191919;
  --ink:       #EDEDED;
  --ink-2:     #A1A1A1;
  --ink-3:     #6E6E6E;
  --line:      rgba(255,255,255,0.09);
  --line-2:    rgba(255,255,255,0.18);
  --accent:    var(--ink);   /* MONO mode — never overridden on this site */
  --accent-fg: var(--bg);
  --ok: #2EBD85;  --warn: #D4A72C;  --err: #E5534B;   /* status-only */

  --font-display: "Geist", system-ui, sans-serif;
  --font-mono: "Geist Mono", "JetBrains Mono", ui-monospace, monospace;

  --container: 1120px;
  --radius: 4px;
  --pad-section: clamp(88px, 12vw, 152px);
  --nav-h: 64px;
}

/* 1 · Reset-lite */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 400 1rem/1.65 var(--font-display);
  -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; }
h1, h2, h3, p, ol, ul, figure { margin: 0; }

::selection { background: var(--ink); color: var(--bg); }  /* brand §3.3 */

/* 2 · Type — brand §4.2 */
h1, .h1 {
  font: 540 clamp(2.5rem, 6vw, 4.5rem)/1.06 var(--font-display);
  letter-spacing: -0.03em;
  text-wrap: balance;
}
h2 {
  font: 540 clamp(1.6rem, 3.2vw, 2.4rem)/1.15 var(--font-display);
  letter-spacing: -0.02em;
  text-wrap: balance;
}
p { max-width: 66ch; color: var(--ink-2); }
.hero-sub, .section-line, .cta-line, .card-body, .stage-line { text-wrap: pretty; }  /* rag parity with use.css */

.eyebrow {
  font: 500 12px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-3);
  max-width: none;
}
.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* 3 · Layout */
.container {
  max-width: var(--container);
  margin: 0 auto;
  padding-inline: 24px;
}
.section {
  border-top: 1px solid var(--line);   /* hairline section rules — brand §5 */
  padding-block: var(--pad-section);
  scroll-margin-top: calc(var(--nav-h) + 24px);
}
.section:focus { outline: none; }  /* tabindex=-1 scroll targets */
.section-head { margin-bottom: clamp(40px, 6vw, 64px); }
.section-head .eyebrow { margin-bottom: 20px; }
.section-line { margin-top: 16px; }

/* Focus — visible ring on every interactive element */
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: fixed; top: 12px; left: 12px; z-index: 200;
  transform: translateY(-64px);
  font: 500 12px/1 var(--font-mono); text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--bg); background: var(--ink);
  padding: 10px 14px; border-radius: var(--radius); text-decoration: none;
}
.skip-link:focus-visible { transform: none; outline-offset: 2px; }

/* 4 · Buttons & links — brand §7 */
.btn {
  display: inline-block;
  white-space: nowrap;
  font: 500 13px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 13px 22px;
  border-radius: var(--radius);
  border: 1px solid var(--ink);
  background: var(--ink);
  color: var(--bg);
  text-decoration: none;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
@media (hover: hover) {
  .btn:hover { background: transparent; color: var(--ink); }        /* invert */
}
.btn:active { background: var(--surface-2); color: var(--ink); }
.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line-2); }
@media (hover: hover) {
  .btn--ghost:hover { border-color: var(--ink); background: transparent; }
}

a { color: inherit; }
.link-ghost {
  font: 400 13.5px/1 var(--font-mono);
  color: var(--ink-2);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line-2);
  transition: color 0.18s ease, text-decoration-color 0.18s ease;
}
@media (hover: hover) {
  .link-ghost:hover { color: var(--ink); text-decoration-color: var(--ink); }
}

/* 5 · Nav — brand §7, site spec §3.1 */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  height: var(--nav-h);
  border-bottom: 1px solid var(--line);
  background: var(--bg);
  transition: background 0.18s ease;
}
.nav.is-scrolled {
  background: rgba(10, 10, 10, 0.78);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
}
.nav-inner {
  height: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: 24px;
}
.wordmark {
  font: 500 17px/1 var(--font-display);
  color: var(--ink);
  text-decoration: none;
  letter-spacing: -0.01em;
}
.nav-right { display: flex; align-items: center; gap: 22px; }
.nav-link {
  font: 400 13px/1 var(--font-mono);
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.18s ease;
}
@media (hover: hover) {
  .nav-link:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
}
.nav-meta { font: 400 12px/1 var(--font-mono); color: var(--ink-3); white-space: nowrap; }
.nav-btn { padding: 10px 16px; }

/* Status chip — motif 2. Pill radius sanctioned for status chips only. */
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  font: 500 11px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 6px 11px;
  white-space: nowrap;
}
.dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--ok);
  display: inline-block;
  animation: pulse 2.2s ease-in-out infinite;
}
@keyframes pulse { 50% { opacity: 0.3; } }

/* 6 · Hero — site spec §3.2, 7/5 split */
.hero {
  padding-top: calc(var(--nav-h) + clamp(72px, 11vh, 128px));
  padding-bottom: var(--pad-section);
}
.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(40px, 5vw, 72px);
  align-items: center;
}
/* DEBT-1 §6 audit: hero eyebrow carries a privacy claim — not colophon-class;
   lifted from --ink-3 to --ink-2 (site honesty pass 2026-07-17). */
.hero-copy .eyebrow { margin-bottom: 28px; color: var(--ink-2); }
.hero-sub { margin-top: 28px; font-size: 1.0625rem; }
.cta-row { margin-top: 36px; display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }

.h1 .line { display: block; overflow: hidden; }
.h1 .line-inner { display: inline-block; }

/* 7 · Terminal blocks — brand §6 motif 3 */
.term {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  font: 400 13.5px/1.7 var(--font-mono);
  color: var(--ink);
}
.term-bar {
  display: flex; gap: 6px; align-items: center;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  color: var(--ink-3);
  font-size: 12px;
}
.term-bar i {
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--line-2);   /* grayscale, NOT macOS colors */
  flex: none;
}
.term-bar span { margin-left: 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.term pre {
  padding: 16px 18px; margin: 0;
  overflow-x: auto;
  font: inherit;
  font-variant-numeric: tabular-nums;
}
.term .ok { color: var(--ok); font-weight: 400; }   /* status-only green */
.term .dim, .term .tl.dim { color: var(--ink-3); }
/* Scrollbars inside the artifacts stay on the MONO ramp — UA-default
   chrome is a non-ramp element inside the most-photographed blocks. */
.term pre, .pipe-wrap {
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
}
.term pre::-webkit-scrollbar, .pipe-wrap::-webkit-scrollbar { height: 8px; }
.term pre::-webkit-scrollbar-thumb, .pipe-wrap::-webkit-scrollbar-thumb {
  background: var(--line-2);
  border-radius: 4px;
}
.term pre::-webkit-scrollbar-track, .pipe-wrap::-webkit-scrollbar-track { background: transparent; }
.cursor::after { content: "▌"; animation: blink 1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }
/* Landing dry-run terminal shares the .readout 640px measure below it —
   adjacent quiet sections read as one artifact width (brand §7). ID-scoped:
   use.html's .dryrun copy is untouched. */
#dryrun-term { max-width: 640px; }

/* Brief artifact — type scales to its container so the longest locked line
   (56ch) renders un-clipped at every width (site spec §5). 34 ≈ 56ch ×
   Geist Mono advance 0.607em; 38px = pre padding + border. */
.hero-art { container-type: inline-size; }
.brief { font-size: clamp(11px, calc((100cqw - 38px) / 34), 13.5px); }
.brief .tl { display: block; min-width: max-content; }
.brief .k { color: var(--ink-3); }
/* DEBT-1 §6 audit: the sign-off line is a trust claim ("nothing in this brief
   left your machine.") — state-bearing, not colophon; lifted to --ink-2.
   The divider glyph line above it stays --ink-3 (pure decoration). */
.brief .tl.dim:last-child { color: var(--ink-2); }
.brief .loop01 { display: block; min-width: max-content; transition: background 0.18s ease; }
@media (hover: hover) {
  .brief .loop01:hover { background: var(--surface-2); }   /* site spec §3.2 */
}
.brief .cursor { margin-left: 1ch; }
.term-draw {
  position: absolute; inset: -1px;
  width: calc(100% + 2px); height: calc(100% + 2px);
  pointer-events: none;
  display: none;   /* only shown during the load draw, .motion below */
}
.term-draw rect {
  x: 0.5px; y: 0.5px;
  width: calc(100% - 1px); height: calc(100% - 1px);
  fill: none; stroke: var(--line-2); stroke-width: 1;
}

/* 8 · HOW — pipeline + stages, site spec §3.3 */
.pipe-wrap { overflow-x: auto; margin-bottom: clamp(40px, 6vw, 56px); }
.pipeline {
  margin: 0;
  font: 400 13px/1.25 var(--font-mono);   /* tight so box-drawing connects */
  color: var(--ink-2);
  min-width: max-content;
}
.pipeline .p4, .pipeline .p5 { color: var(--ink); }   /* the moat stages */

.stages { list-style: none; margin: 0; padding: 0; }
.stage {
  display: grid;
  grid-template-columns: 56px 160px minmax(0, 1fr);
  gap: 16px;
  align-items: baseline;
  padding: 18px 0;
  border-top: 1px solid var(--line);
}
.stage:last-child { border-bottom: 1px solid var(--line); }
.stage-num {
  font: 500 13px/1.65 var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-2);   /* §6: numbers never sub-AA (stage map cross-refs these) */
}
.stage-title { font: 500 1.0625rem/1.5 var(--font-display); color: var(--ink); }
.stage-line { color: var(--ink-2); max-width: 66ch; }

/* 9 · Readout table — LOCAL, site spec §3.5 */
table { border-collapse: collapse; }
.readout {
  width: 100%; max-width: 640px;
  font: 400 14px/1.65 var(--font-mono);
}
.readout tr { border-top: 1px solid var(--line); transition: background 0.18s ease; }
.readout tr:last-child { border-bottom: 1px solid var(--line); }
@media (hover: hover) {
  .readout tr:hover { background: var(--surface); }
}
.readout th {
  text-align: left; font-weight: 400; color: var(--ink-2);  /* §6: trust-table labels are state-bearing */
  padding: 13px 24px 13px 0; white-space: nowrap;
}
.readout td { text-align: right; color: var(--ink); padding: 13px 0; }

/* 10 · Stage map — site spec §3.6 */
.matrix {
  width: 100%; max-width: 760px;
  font: 400 14px/1.65 var(--font-mono);
}
.matrix thead th {
  font: 500 11px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-2);   /* §6: headers required to parse the comparative claim */
  text-align: left;
  padding: 0 24px 12px 0;
  font-weight: 500;
}
.matrix tbody tr { border-top: 1px solid var(--line); transition: background 0.18s ease; }
.matrix tbody tr:last-child { border-bottom: 1px solid var(--line); }
@media (hover: hover) {
  .matrix tbody tr:hover { background: var(--surface); }
}
.matrix th[scope="row"] { text-align: left; font-weight: 400; padding: 14px 24px 14px 0; }
.matrix td { padding: 14px 24px 14px 0; }
.matrix td:last-child, .matrix th:last-child { padding-right: 0; }
.matrix .is-dim th, .matrix .is-dim td { color: var(--ink-2); }
.matrix .is-full th, .matrix .is-full td { color: var(--ink); }

/* 11 · Pricing cards — brand §7, site spec §3.7.
   Four rungs in one left-to-right row: the row IS the metered axis, price
   ascending. Only Business carries a button (lead capture, founder decision
   2026-07-26); the other three are pre-release statements of fact, and the
   page already offers the waitlist three times. */
.cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 20px;
}
.card {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 24px;
  display: flex; flex-direction: column; align-items: flex-start;
  transition: border-color 0.18s ease, transform 0.18s ease;
}
@media (hover: hover) {
  .card:hover { border-color: var(--line-2); transform: translateY(-2px); }
}
.card-title { font: 500 1.0625rem/1.4 var(--font-display); color: var(--ink); }
.card-price { font: 400 1.375rem/1.2 var(--font-mono); color: var(--ink); margin-top: 14px; }
.card-per { font-size: 13px; color: var(--ink-2); }
/* Business has no number to set at price size; matching it would give the one
   plan you can't buy the loudest figure on the row. */
.card-price--text { font-size: 1.0625rem; color: var(--ink-2); }
/* The metered number. §6: state-bearing, so never sub-AA. */
.card-meter {
  margin-top: 8px;
  font: 400 13px/1.4 var(--font-mono);
  color: var(--ink-2);
}
.card-body { margin-top: 18px; padding-bottom: 20px; font-size: 0.9375rem; }
.card-btn { margin-top: auto; }
/* Business's route out. A text link, not a button: pre-release there is no
   dedicated business route (it shares the waitlist), and overstating the
   affordance would promise a desk that doesn't exist yet. */
.card-link { margin-top: auto; }

/* The flat axis, stated once: a ruled spec-sheet row of the surfaces no plan
   meters. Same readout idiom as §9/§10 — this is data, not a feature list. */
.unmetered {
  margin-top: 20px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px 24px 26px;
}
/* §6: this label is what the block claims, not a navigational kicker. */
.unmetered .eyebrow { color: var(--ink-2); }
.unmetered-list {
  margin-top: 18px;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.unmetered-list li {
  font: 400 13px/1.5 var(--font-mono);
  color: var(--ink);
  padding: 13px 16px 13px 0;
}
.unmetered-list li + li { border-left: 1px solid var(--line); padding-left: 16px; }
.unmetered-line { margin-top: 18px; font-size: 0.9375rem; max-width: 68ch; }
.fn-ref a {
  font: 400 10px/1 var(--font-mono);
  color: var(--ink-2);   /* §6: actionable (link) — never sub-AA */
  text-decoration: none;
}
@media (hover: hover) {
  .fn-ref a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
}

/* 12 · Final CTA — the one sanctioned centered section, site spec §3.8 */
.cta-inner, .dl-inner { text-align: center; display: flex; flex-direction: column; align-items: center; }   /* .dl-inner = use.html's download block — shared primitive lives here */
.cta-line { margin-top: 20px; max-width: 46ch; }
.waitlist {
  margin-top: 36px;
  display: flex; gap: 12px;
  width: 100%; max-width: 440px;
}
.input {
  flex: 1; min-width: 0;
  font: 400 14px/1 var(--font-mono);
  color: var(--ink);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 13px 16px;
  transition: border-color 0.18s ease;
}
.input::placeholder { color: var(--ink-2); }  /* §6: hint on the sole conversion action */
/* Pointer focus: border only, no ring — brand §7 forbids a glow and a mouse
   user who just clicked the field does not need to be told where they are. */
.input:focus { outline: none; border-color: var(--ink); }
/* Keyboard focus: the same 2px ink ring every other control gets (Q-105).
   The old rule killed the outline for BOTH modalities, which left the page's
   sole conversion control with a 1px border shift as its entire focus
   indicator — the weakest indicator on the page on the one element that most
   needs one. Declared after the :focus rule; equal specificity, later wins. */
.input:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* Chrome autofill paints pale yellow — a block of color on the sole
   conversion element. Repaint it inside the grayscale ramp (brand §10). */
.input:-webkit-autofill,
.input:-webkit-autofill:hover,
.input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--ink);
  -webkit-box-shadow: 0 0 0 1000px var(--surface-2) inset;
  caret-color: var(--ink);
}
.form-note {
  margin-top: 14px;
  font: 400 12.5px/1.6 var(--font-mono);
  color: var(--ink-2);
  min-height: 1.6em;
}
.form-note.is-err { color: var(--ink); }
.cta-meta {
  margin-top: 18px;
  font: 400 12px/1 var(--font-mono);
  letter-spacing: 0.04em;
  color: var(--ink-2);   /* §6: repeats the privacy claim — state-bearing */
}

/* 13 · Footer — footnotes + colophon + status chip, site spec §3.9 */
.footer {
  border-top: 1px solid var(--line);
  padding: 48px 0 40px;
}
.footnote {
  font: 400 12.5px/1.7 var(--font-mono);
  color: var(--ink-2);   /* §6: substantiation disclaimer for the pricing claim */
  max-width: none;
}
.footnote.is-hit { color: var(--ink); transition: color 0.18s ease; }   /* lit once the ¹ ref lands on it */

/* Illustrative-figures marker (2026-07-26). Lives HERE, not use.css, because
   index.html loads only this sheet and carries the same demo figures as /use.
   Mirrors the treatment brief.py `_footer()` gives DISCLOSURE_LINE: one short
   mono line, byte-identical everywhere, adjacent to the numbers it qualifies.
   --ink-2 is mandatory, not stylistic — SITE_HONESTY_PASS §2 ruling 9: a
   substantiation disclaimer never gets to be the least legible text on the page. */
.fig-note {
  margin-top: 12px;
  font: 500 12px/1.5 var(--font-mono);
  color: var(--ink-2);
  max-width: none;
}
.foot-row {
  margin-top: 28px;
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}
.colophon { font: 400 12.5px/1.7 var(--font-mono); color: var(--ink-3); max-width: none; }

/* 14 · Motion initial states — applied only when .motion is on <html>.
   Reduced-motion users never get these: everything renders final instantly
   (site spec §4); the cursor still blinks (steps(), allowed). */
.motion [data-reveal] { opacity: 0; }
.motion [data-reveal-group] > * { opacity: 0; }
.motion .h1 .line-inner { transform: translateY(110%); }
.motion .h1 .line-inner { will-change: transform; }   /* released by app.js post-reveal */
.motion .ps { opacity: 0; }
.motion .brief { border-color: transparent; }
.motion .brief .term-bar,
.motion .brief .tl { opacity: 0; }
.motion .brief .cursor { visibility: hidden; }
.motion .term-draw { display: block; }
.motion .term-draw rect { stroke-dasharray: 1; stroke-dashoffset: 1; }

@media (prefers-reduced-motion: reduce) {
  .dot { animation: none; }   /* rests at full opacity — the cursor blink is the one sanctioned persistent animation */
}

/* 15 · Responsive */
@media (max-width: 1000px) {
  .hero-grid { grid-template-columns: minmax(0, 1fr); }
  .hero-art { max-width: 640px; }
  .stage { grid-template-columns: 44px 120px minmax(0, 1fr); }
  /* The ladder folds 4 → 2×2. Reading order still ascends by price. */
  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; max-width: 880px; }
  .card { padding: 28px; }
  /* 5 ruled columns can't hold their labels below ~1000px: fold to a
     stacked readout, hairline per row instead of per column. */
  .unmetered { max-width: 880px; }
  .unmetered-list { grid-template-columns: minmax(0, 1fr); border-bottom: none; }
  .unmetered-list li { padding: 11px 0; border-bottom: 1px solid var(--line); }
  .unmetered-list li + li { border-left: none; padding-left: 0; }
}
@media (max-width: 860px) {
  .nav-link:not([href="use.html"]):not([aria-current="page"]), .nav-meta { display: none; }
}
/* ==========================================================================
   16 · MacBook intro — brief §8 addendum. CSS 3D perspective port of the
   EBW MacIntro: a rendered MONO laptop (machined aluminium in grayscale —
   founder call 2026-07-25, superseding §8's wireframe; the wireframe read
   as a bundle of lines, not a machine), screen = the real hero cloned at
   runtime. Every animated property is transform/opacity; the p=0 pose
   lives in CSS so the pre-JS first frame is already the start frame.

   Skip gates (brief §8): the whole feature exists only under html.motion
   (reduced-motion never gets the class; app.js removes it if GSAP fails)
   AND ≥768px. html.mi-off is app.js's abort switch (init failure, or
   viewport gate) — spacer collapses, stage never renders, zero cost.
   ========================================================================== */
.mi-spacer, .mi-stage, .mi-skip { display: none; }
html.motion .mi-spacer { display: block; height: 200vh; }
html.motion .mi-stage { display: block; }
html.motion .mi-skip { display: inline-block; }
/* later rules at equal specificity win: the abort switch and the gates */
html.mi-off .mi-spacer, html.mi-off .mi-stage, html.mi-off .mi-skip { display: none; }
@media (max-width: 767.98px), (prefers-reduced-motion: reduce) {
  html.motion .mi-spacer, html.motion .mi-stage, html.motion .mi-skip { display: none; }
}

.mi-stage {
  position: fixed; inset: 0; z-index: 95;   /* under the nav (100) */
  background: var(--bg);
  pointer-events: none;
  /* founder note 2026-07-18: the CLOSED laptop must read from frame one —
     the machined edges start bright and ease down to a hairline as the lid
     opens and the screen takes over (app.js drives both vars with
     progress). Same two vars as the wireframe build; they now light the
     chamfers of a solid shell instead of drawing its outline. */
  --mi-stroke: rgba(255, 255, 255, 0.62);
  --mi-stroke-2: rgba(255, 255, 255, 0.3);
  /* aluminium, lit from above — MONO: every stop is neutral gray */
  --mi-alu: linear-gradient(180deg, #33333a 0%, #26262c 13%, #1d1d22 58%, #16161a 100%);
}
/* telephoto — 3200 not 2200: with a rendered base at true MacBook depth, the
   shorter lens splayed the front of the machine into a wedge. Longer lens =
   product-shot geometry. Handoff is unaffected (at p=1 nothing is rotated
   or z-offset, so perspective has no effect on the screen). */
.mi-persp { position: absolute; inset: 0; perspective: 3200px; }

/* the laptop group — viewport-sized so identity transform = exact handoff */
.mi-mac {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
  transform: translate3d(0, -3%, 0) scale3d(0.34, 0.34, 0.34) rotateX(12deg) rotateY(-16deg);
}

/* lid: screen + 20px shell all round (6px aluminium rim, 14px black glass
   bezel — MacBook Pro proportion at a 1440px viewport); hinge
   (transform-origin) at its bottom edge. */
.mi-lid {
  position: absolute; inset: -20px;
  transform-origin: 50% 100%;
  transform-style: preserve-3d;
  will-change: transform;
  transform: rotateX(26deg);   /* open, screen leaning back — never closed */
}
.mi-lid-front, .mi-lid-back {
  position: absolute; inset: 0;
  backface-visibility: hidden;
  border-radius: 16px;
  background: var(--mi-alu);
}
/* no border — .mi-screen's inset must stay exactly 20px for the handoff.
   The edges are chamfers (inset shadows), which cost no layout: bright
   along the top where the light is, dimmer down the sides. */
.mi-lid-front {
  box-shadow:
    inset 0 1.5px 0 var(--mi-stroke),
    inset 1.5px 0 0 var(--mi-stroke-2),
    inset -1.5px 0 0 var(--mi-stroke-2),
    inset 0 -1.5px 0 var(--mi-stroke-2);
}
.mi-lid-back {
  transform: rotateY(180deg);
  display: grid; place-items: center;
  background: linear-gradient(180deg, #16161a 0%, #1d1d22 45%, #2a2a30 100%);
  box-shadow: inset 0 1.5px 0 var(--mi-stroke);   /* far-edge highlight */
}
/* display glass: one black slab under the screen, so the 14px inside the
   aluminium rim reads as bezel rather than as a gap */
.mi-glass {
  position: absolute; inset: 6px;
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(255,255,255,0.055), rgba(255,255,255,0) 34%), #050506;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.05);
}

/* deck: extends toward the viewer from the hinge line, at real MacBook Pro
   base proportions (1000 x 697) rather than at the lid's footprint. The lid
   is viewport-shaped — far wider than a real 1.43:1 MacBook lid — so
   matching its depth squashes the keyboard into something no MacBook has;
   matching the machine instead keeps the keyboard photographic and puts the
   palm rest below the frame, exactly where a product shot crops it.
   Surface is a generated vector — keycaps, speaker grilles, trackpad,
   screen spill (media/mac-deck.svg, built by scripts/gen-mac-deck.mjs).
   The gradient under it is the first-paint fallback: a solid metal plate,
   never a hole. Static pose. */
.mi-deck {
  position: absolute; left: -20px; right: -20px;
  top: calc(100% + 22px); height: auto;
  aspect-ratio: 1000 / 697;
  transform-origin: 50% 0;
  transform: rotateX(64deg);   /* start: keyboard face pitched to camera */
  border-radius: 18px;
  background:
    url("media/mac-deck.svg") center / 100% 100% no-repeat,
    var(--mi-alu);
  transform-style: preserve-3d;
  will-change: transform;
}
/* the front wall of the base — hinged off the deck's front edge and stood
   back up perpendicular to it. Without it the machine is a sheet of metal;
   with it, it has a body. 4.4% of the deck's depth = 11mm of a 248mm base. */
.mi-wall {
  position: absolute; left: 0; right: 0; top: 100%;
  height: 4.4%;
  transform-origin: 50% 0;
  transform: rotateX(-90deg);
  border-radius: 0 0 14px 14px;
  /* it faces the camera, away from the light above: darker than the deck,
     with the machined top edge doing the reading */
  background: linear-gradient(180deg, #17171b 0%, #101014 55%, #0a0a0d 100%);
  box-shadow: inset 0 1.2px 0 var(--mi-stroke-2);
}

/* the screen — exactly the viewport at identity (lid inset −20, no border,
   screen inset 20). No border of its own: at handoff its edge must be
   invisible; the fading .mi-bezel overlay carries the screen outline
   mid-scrub. */
.mi-screen {
  position: absolute; inset: 20px;
  overflow: hidden;
  background: var(--bg);
}
/* everything that must not survive the handoff lives in here: the screen
   outline, the notch biting into the display, and the glass sheen. app.js
   fades the whole overlay out between p 0.86 and 0.95. */
.mi-bezel {
  position: absolute; inset: 0; z-index: 5;
  box-shadow: inset 0 0 0 1px var(--line-2);
  border-radius: 2px;
}
.mi-bezel::before {   /* notch */
  content: ""; position: absolute; top: 0; left: 50%;
  width: 96px; height: 13px; margin-left: -48px;
  background: #050506;
  border-radius: 0 0 7px 7px;
  box-shadow: inset 0 -1px 0 rgba(255,255,255,0.05);
}
.mi-bezel::after {    /* glass sheen — the display is behind glass, not open */
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(104deg, rgba(255,255,255,0.045) 0%, rgba(255,255,255,0) 26%, rgba(255,255,255,0) 74%, rgba(255,255,255,0.02) 100%);
}

/* browser chrome — the term-bar idiom: grayscale dots, mono URL field */
.mi-chrome {
  position: absolute; inset: 0 0 auto 0; height: 42px; z-index: 3;
  display: flex; align-items: center; gap: 6px;
  padding: 0 14px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  will-change: transform;
}
.mi-chrome i { width: 9px; height: 9px; border-radius: 50%; background: var(--line-2); flex: none; }
.mi-url {
  position: relative; margin-left: 8px;
  display: flex; align-items: center;
  min-width: 19rem; max-width: 460px; flex: 1;
  height: 30px; padding: 0 10px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font: 400 14px/1 var(--font-mono);
  color: var(--ink-3);
  transition: border-color 0.18s ease;
}
.mi-url.is-focus { border-color: var(--ink); }
.mi-typed { color: var(--ink); white-space: pre; }
.mi-caret { margin-left: 1px; color: var(--ink); opacity: 0; }
.mi-ph { position: absolute; left: 10px; }

/* screen content column — sits below the chrome bar, rises to 0 at the
   final beat while the bar slides away, so p=1 shows the page at (0,0) */
.mi-col {
  position: absolute; inset: 0;
  transform: translate3d(0, 42px, 0);
  will-change: transform;
}
.mi-loader {
  position: absolute; inset: 0 0 auto 0; height: 2px; z-index: 4;
  background: var(--ink);
  transform-origin: left;
  transform: scaleX(0); opacity: 0;
}
.mi-newtab {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
}
.mi-mark {
  width: 48px; height: 48px;
  display: grid; place-items: center;
  border: 1px solid var(--line-2); border-radius: 6px;
  font: 500 20px/1 var(--font-mono); color: var(--ink);
}
/* on the closed shell the mark is etched into the metal, not boxed */
.mi-lid-back .mi-mark {
  width: auto; height: auto; border: 0;
  font: 500 96px/1 var(--font-display);
  color: rgba(255, 255, 255, 0.12);
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
}
.mi-newtab-label {
  font: 500 11px/1 var(--font-mono);
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--ink-3);
}
.mi-page {
  position: absolute; inset: 0 0 auto 0; min-height: 100%;
  background: var(--bg);
  opacity: 0;
}
.mi-dark { position: absolute; inset: 0; z-index: 6; background: var(--surface); }

/* the cloned h1/pipeline render in FINAL visual state — the .motion initial
   states (style.css §14) match them by class; these outrank them. The brief
   is deliberately NOT pinned: its §14 hidden start state stands so the
   signature arrival (spec §4) plays inside the screen — app.js scopes the
   identical timeline to the clone and forces final state by p = 0.86. */
.motion .mi-page .h1 .line-inner { transform: none; }
.motion .mi-page .ps { opacity: 1; }

.mi-hint {
  position: absolute; inset: auto 0 28px 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  font: 500 11px/1 var(--font-mono);
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--ink-2);   /* §6: an instruction — state-bearing */
}
.mi-hint-glyph {
  color: var(--ink-3);
  letter-spacing: 0;
  animation: mi-nudge 1.6s ease-in-out infinite;
}
@keyframes mi-nudge { 50% { transform: translateY(6px); } }

.mi-skip {
  position: fixed; top: calc(var(--nav-h) + 16px); right: 24px; z-index: 96;
  pointer-events: auto;
}

/* 15 · Responsive (continued) */
@media (max-width: 640px) {
  .container { padding-inline: 16px; }
  .eyebrow { line-height: 1.5; }   /* wrapped uppercase lines must not collide */
  .nav-inner { gap: 10px; }
  .nav-right { gap: 6px; }
  .nav-btn { padding: 9px 7px; font-size: 11px; letter-spacing: 0.05em; }
  .chip { padding: 5px 6px; letter-spacing: 0.03em; font-size: 10px; }
  .wordmark { font-size: 16px; }
  .cards { grid-template-columns: 1fr; }
  .stage { grid-template-columns: 44px minmax(0, 1fr); }
  .stage-line { grid-column: 2; }
  .waitlist { flex-direction: column; }
  .waitlist .btn { width: 100%; text-align: center; }
  .term pre { padding: 12px; }
  /* Tighter pre padding at this width: 26px = 12×2 + border. */
  .brief { font-size: clamp(11px, calc((100cqw - 26px) / 34), 13.5px); }
  /* Dry-run block: longest locked line = 54ch; fit it at small widths. */
  .dryrun { font-size: clamp(11px, calc((100vw - 58px) / 33), 13.5px); }
  #dryrun-term pre { white-space: pre-wrap; }
  /* Full-bleed the pipeline scroller: boxes crop at the screen edge
     (standard continuation affordance) and recover 32px of diagram. */
  .pipe-wrap { margin-inline: -16px; padding-inline: 16px; }
  .foot-row { justify-content: flex-start; }
  .cta-meta { line-height: 1.6; }   /* wrapped lines must not collide (same precedent as .eyebrow above) */
}

/* ≤480px: the brief's 56ch loop rows can't fit at the 11px clamp floor
   (fit-to-width would need ~9px, below the DEBT-2 legibility floor) —
   wrap is the only lawful fix. Inert 481-640px; locked copy untouched. */
@media (max-width: 480px) {
  .brief .tl, .brief .loop01 { min-width: 0; white-space: pre-wrap; }
}

/* DEBT-2, second half — the reflow has to keep the column, not just the size.
   Wrapping alone left `3h 10m /wk` starting at column 0 on its own line, where
   it reads as a fourth record rather than as loop 01's hours. Right-aligning
   the wrapped tail restores the artifact's only real layout claim: title left,
   hours right. Text is byte-identical; this is alignment, not copy.

   400px is derived, not guessed. The clamp is
   `clamp(11px, (100cqw - 26px)/34, 13.5px)`, so the floor takes over exactly
   when `(100cqw - 26px)/34 < 11px` — i.e. below a 400px container. That is
   also the exact first width at which a 56-char row stops fitting (measured:
   at container 401px the widest row is 375px into 375px of content box and
   does not wrap; at 400px and below it must). Above the threshold the rows
   never wrap and `text-align-last` has no last-line-that-isn't-the-only-line
   to act on, so the query never fires there. Container query, not a viewport
   one, because the artifact sits in two different columns (index hero vs
   use.html `.art-cq`) at the same viewport width. */
@container (max-width: 399.98px) {
  .brief .tl-row { text-align-last: right; }
}

/* Sub-16px inputs make iOS Safari auto-zoom on focus — the conversion
   action would open with a viewport lurch. pointer: coarse also covers
   iPads/large phones above the 640px breakpoint. */
@media (pointer: coarse) {
  .input { font-size: 16px; }
}

/* 17 · Print — a skeptical operator files the privacy claims as PDF.
   Tokens are brand §3.2 LIGHT verbatim; intro chrome and unfired motion
   states are neutralized so nothing prints blank or dark-on-white. */
@media print {
  html.motion .mi-spacer, html.motion .mi-stage, html.motion .mi-skip, .rail, .skip-link { display: none; }
  .nav { position: static; }
  :root {
    --bg: #FCFCFC;
    --surface: #F4F4F4;
    --surface-2: #FFFFFF;
    --ink: #111111;
    --ink-2: #565656;
    --ink-3: #8A8A8A;
    --line: #E5E5E5;
    --line-2: #CFCFCF;
  }
  body { background: #fff; }
  .motion [data-reveal], .motion [data-reveal-group] > *, .motion .ps,
  .motion .brief .term-bar, .motion .brief .tl { opacity: 1 !important; transform: none !important; }
  .motion .h1 .line-inner { transform: none !important; }
  .motion .brief { border-color: var(--line) !important; }
  video { display: none; }
}
