/* Syncproof — styles.css
   Plain CSS, no build step. Tokens first, then layout/components in page order.

   ============================================================
   DECLARED fg/bg PAIRS (every pair the design uses, for the contrast audit —
   see build report for the measured ratio table). "Ground" = the LIGHTEST
   surface a token can land on, per the design brief's instruction to check
   against raised plates, not just the page background.

   Dark room:
   1.  --fg          on --ink     (body text, page ground)
   2.  --fg          on --ink-2   (body text, raised plate / ledger box)
   3.  --fg-muted    on --ink     (muted text, page ground)
   4.  --fg-muted    on --ink-2   (muted text, ledger box — brief flags this
                                   one explicitly, 4.5:1+ required)
   5.  --ink         on --accent  (CTA button fill: dark ink on amber)
   6.  --accent      on --ink-2   (wordmark "proof", accent-tag fill context)
   7.  --status-ok   on --ink-2   (ledger status dot, non-text UI, 3:1)
   8.  --status-warn on --ink-2   (= --accent, non-text UI, 3:1)
   9.  --status-fail on --ink-2   (ledger status dot, non-text UI, 3:1)
   10. --border-dark on --ink-2   (topbar/ledger-box/footer hairlines + link
                                   underlines — decorative dividers, not a
                                   WCAG 1.4.11 UI-component boundary; checked
                                   anyway, not gated at 3:1)

   Paper room:
   11. --fg-ink       on --paper    (body text, page ground)
   12. --fg-ink       on --paper-2  (body text, raised plate)
   13. --fg-ink-muted on --paper    (muted text / mono labels, page ground)
   14. --fg-ink-muted on --paper-2  (muted text, raised plate)
   15. --border-paper on --paper    (hairline rule, decorative — not gated,
                                     checked anyway)
   ============================================================ */

/* ---------- self-hosted fonts ----------
   IBM Plex Sans: variable font, wght 400–700, one latin woff2 (45,712 bytes).
   IBM Plex Mono: static weight 400, one latin woff2 (14,708 bytes) + one
   1,368-byte supplemental subset for two glyphs (→ № ) missing from
   Google's "latin" grouping — see the font-face rule below for why.
   All three from Google Fonts' css2 API (Chrome UA). Metric-matched
   fallback for Plex Sans only, per brief — see build report for the
   measured size-adjust method (Playwright, real font vs Arial). */
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-sans-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;
}

/* raw OS/2 metrics: sTypoAscender 1025 / sTypoDescender -275 / sTypoLineGap 0,
   unitsPerEm 1000 → 102.50% / 27.50% / 0.00% (fontTools, USE_TYPO_METRICS set).
   size-adjust measured live in headless Chromium (Playwright): the string
   "The quick brown fox jumps over the lazy dog — nothing overwritten blind.
   0123456789" at 400/100px, real IBM Plex Sans 3885.109375px vs Arial
   3830.03125px → 3885.109375 / 3830.03125 = 1.014381 → 101.44%.
   overrides = raw ÷ 1.014381: 102.50→101.05%, 27.50→27.11%, 0→0.00%. */
@font-face {
  font-family: "IBM Plex Sans Fallback";
  src: local("Arial");
  size-adjust: 101.44%;
  ascent-override: 101.05%;
  descent-override: 27.11%;
  line-gap-override: 0%;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-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;
}
/* Google's "latin" subset omits → (U+2192) and № (U+2116) — verified by
   direct fontTools cmap inspection, not assumed — even though the ledger
   copy uses both. A second, tiny (1,368 byte) subset patches exactly those
   two codepoints rather than widening the primary file or substituting
   different characters into the copy. */
@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-mono-symbols.woff2") format("woff2");
  unicode-range: U+2116, U+2192;
}

/* ---------- tokens ---------- */
:root {
  /* colour — dark ops ground */
  --ink: #0e1116;
  --ink-2: #161b23;
  --ink-3: #1f2630;
  --border-dark: #2a3342;

  /* colour — light paper room */
  --paper: #f4f2ec;
  --paper-2: #ffffff;
  --border-paper: #ddd6c8;

  /* colour — foreground */
  --fg: #e8eaed;
  --fg-muted: #9aa3b2;
  --fg-ink: #1a2029;
  --fg-ink-muted: #4d5a6b;

  /* colour — accent (reserved: CTA fills, the REJECTED ledger row, focus is
     the browser default and untouched) */
  --accent: #e8a13d;

  /* colour — ledger status (data colours, dark room / ledger only) */
  --status-ok: #5fb87a;
  --status-warn: #e8a13d;
  --status-fail: #e06c5f;

  /* type faces */
  --sans: "IBM Plex Sans", "IBM Plex Sans Fallback", Arial, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", "Consolas", monospace;

  /* fluid type scale — one clamp per step, rem in the preferred term so
     browser zoom / OS text-size preference still moves these (pattern 02). */
  --fs-label: clamp(0.75rem, 0.72rem + 0.14vw, 0.8125rem);
  --fs-ledger: clamp(0.8125rem, 0.79rem + 0.1vw, 0.9375rem);
  --fs-body: clamp(1rem, 0.97rem + 0.14vw, 1.0625rem);
  --fs-body-lg: clamp(1.125rem, 1.06rem + 0.28vw, 1.3125rem);
  --fs-h3: clamp(1.375rem, 1.25rem + 0.56vw, 1.625rem);
  --fs-h2: clamp(1.75rem, 1.5rem + 1.1vw, 2.25rem);
  --fs-h1: clamp(2.5rem, 1.9rem + 2.6vw, 3.75rem);
  --fs-wordmark: clamp(1.125rem, 1.08rem + 0.2vw, 1.25rem);

  /* motion — named tokens, nothing sitewide gets a bespoke transition */
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --t-fast: 150ms;
  --t-med: 400ms;
  --t-slow: 700ms;

  /* layout */
  --content-w: 1080px;
  --measure: 68ch;
}

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: 1.55;
  background: var(--ink);
  color: var(--fg);
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; }
ul { margin: 0; padding: 0; }
h1, h2, h3, p { margin: 0; }
/* native focus ring — untouched, no outline overrides anywhere in this file */

/* ---------- skip link ---------- */
.skip-link {
  position: absolute;
  left: 1rem;
  top: -3rem;
  background: var(--accent);
  color: var(--ink);
  padding: .6rem 1rem;
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: .08em;
  z-index: 100;
  transition: top var(--t-fast) var(--ease-out);
}
.skip-link:focus {
  top: 1rem;
}

/* ---------- visually hidden (a11y-only content) ---------- */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- colour rooms (pattern 06) ---------- */
.room-dark {
  background: var(--ink);
  color: var(--fg);
}
.room-paper {
  background: var(--paper);
  color: var(--fg-ink);
}

/* ---------- layout shell ---------- */
.wrap {
  max-width: var(--content-w);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}
.section {
  padding-block: clamp(3.5rem, 8vw, 7rem);
}

/* mono section index label (pattern 09 — case+weight carries hierarchy) */
.section-label {
  display: block;
  font-family: var(--mono);
  font-size: var(--fs-label);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--fg-muted);
  margin-block-end: 1rem;
}
.room-paper .section-label { color: var(--fg-ink-muted); }

.section-heading {
  font-size: var(--fs-h2);
  font-weight: 650;
  line-height: 1.15;
  letter-spacing: -0.01em;
  max-width: 26ch;
}

/* ---------- top bar ---------- */
.topbar {
  border-bottom: 1px solid var(--border-dark);
}
.topbar .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: 1.25rem;
  gap: 1rem;
}
.wordmark {
  font-family: var(--sans);
  font-weight: 650;
  font-size: var(--fs-wordmark);
  letter-spacing: -0.01em;
  text-decoration: none;
}
.wordmark .w-sync { color: var(--fg); }
.wordmark .w-proof { color: var(--accent); }

.topbar-link {
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: .08em;
  text-decoration: underline;
  text-decoration-color: var(--border-dark);
  text-underline-offset: .25em;
  padding: .5rem;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  transition: text-decoration-color var(--t-fast) var(--ease-out);
}
.topbar-link:hover { text-decoration-color: var(--accent); }

/* ---------- hero (00) ---------- */
.hero {
  padding-block: clamp(3rem, 8vw, 6rem) clamp(3.5rem, 8vw, 6rem);
}
.hero-grid {
  display: grid;
  gap: clamp(2.5rem, 6vw, 4rem);
}
@media (min-width: 900px) {
  .hero-grid { grid-template-columns: 1.05fr .95fr; align-items: start; }
}
.hero h1 {
  font-size: var(--fs-h1);
  font-weight: 650;
  line-height: 1.06;
  letter-spacing: -0.015em;
  margin-block: .75rem 1.25rem;
  max-width: 16ch;
}
.hero .lede {
  font-size: var(--fs-body-lg);
  color: var(--fg-muted);
  max-width: 46ch;
  margin-block-end: 1.75rem;
}
.hero-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin-block-start: 1rem;
}
.hero-meta .status-note {
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--fg-muted);
}

/* CTA button — accent fill + dark ink (pattern 04, the reserved use) */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: 44px;
  padding: .85rem 1.5rem;
  background: var(--accent);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 600;
  font-size: var(--fs-body);
  text-decoration: none;
  border: none;
  border-radius: 3px;
  transition: transform var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out);
}
.btn:hover { box-shadow: 0 0 0 1px var(--accent), 0 6px 18px -6px rgba(232, 161, 61, .45); }
@media (prefers-reduced-motion: no-preference) {
  .btn:active { transform: scale(.97); }
}

/* ---------- ledger ---------- */
.ledger-box {
  background: var(--ink-2);
  border: 1px solid var(--border-dark);
  border-radius: 4px;
  padding: clamp(1rem, 2.5vw, 1.5rem);
  /* fixed block-size so font swap / row rotation never shifts layout (CLS 0) */
  min-block-size: clamp(23rem, 26rem + 4vw, 28rem);
}
.ledger {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: .5rem;
}
.ledger li {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  padding: .55rem .65rem .55rem .75rem;
  border-left: 3px solid transparent;
  font-family: var(--mono);
  font-size: var(--fs-ledger);
  line-height: 1.5;
}
.ledger .dot {
  flex: none;
  inline-size: .5rem;
  block-size: .5rem;
  border-radius: 50%;
  margin-block-start: .5em;
}
.ledger li[data-status="ok"] .dot { background: var(--status-ok); }
.ledger li[data-status="warn"] .dot { background: var(--status-warn); }
.ledger li[data-status="fail"] .dot { background: var(--status-fail); }

.ledger .row-text { color: var(--fg); }
.ledger .row-detail { color: var(--fg-muted); }

.ledger li.is-promoted {
  border-left-color: var(--accent);
  background: rgba(232, 161, 61, .08);
}
.ledger .tag-accent {
  display: inline-block;
  background: var(--accent);
  color: var(--ink);
  font-weight: 600;
  padding: .05em .45em;
  border-radius: 2px;
}

/* animated ticking window — additive: only enters when JS has confirmed
   motion is allowed AND it has taken over the list (pattern 03/29). The
   base rules above are already the complete, static, readable resting
   state — nothing here is required for the page to be correct.
   No max-block-size / overflow: hidden here on purpose: app.js rotates
   rows (appendChild of the first child), so the row count is always 8 and
   total height is order-invariant — there's no layout shift to clip
   against, and clipping was hiding the REJECTED/RESOLVED pair that is the
   whole point of the hero. .ledger-box keeps the min-block-size that
   guards CLS on font swap. */
@media (prefers-reduced-motion: no-preference) {
  .ledger[data-animated] {
    display: block;
  }
  .ledger[data-animated] li.row-entering {
    animation: row-in var(--t-slow) var(--ease-out);
  }
  /* Rotating the first row to the bottom instantly reflows every other row
     upward by that row's height (row heights vary because row-detail text
     wraps) — with no animation on that shift, it read as a snap. A brief
     fade on the row that's about to move softens the departure without
     trying to animate the reflow of the other seven (no FLIP elsewhere in
     this file, so keep this consistent: a fade, not a position tween). */
  .ledger[data-animated] li.row-leaving {
    transition: opacity var(--t-fast) var(--ease-out);
    opacity: .25;
  }
}
@keyframes row-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---------- scroll reveal (pattern 29) — additive, trigger-once ---------- */
.reveal { opacity: 1; transform: none; }
@media (prefers-reduced-motion: no-preference) {
  .reveal[data-armed] { opacity: 0; transform: translateY(1.5rem); }
  .reveal {
    transition: opacity var(--t-slow) var(--ease-out), transform var(--t-slow) var(--ease-out);
  }
}

/* ---------- single-column measure (01, 03 intro, 04) ----------
   These are the page's only single-column text sections; left inside the
   1080px .wrap with no measure of their own, they read as a narrow left
   column dumping all its whitespace on the right at wide viewports. Cap
   the label+heading+prose trio at the sans measure and center that as one
   column so the leftover space splits evenly. Two-column layouts (02's
   split rows, 03's in-v1/not-yet grid, the pricing block) live outside
   this class and are untouched. */
.col-single {
  max-width: var(--measure);
  margin-inline: auto;
}

/* ---------- problem (01) ---------- */
.prose {
  max-width: 62ch;
}
.prose p + p { margin-block-start: 1.1em; }
.prose-spaced { margin-block-start: 1.5rem; }
.not-yet-note { color: var(--fg-ink-muted); }
.mechanics-list { margin-block-start: 1.5rem; }
.room-paper h2 { color: var(--fg-ink); }
.room-paper .prose { color: var(--fg-ink); }
.room-paper .prose em { font-style: italic; }

/* ---------- mechanics (02) — alternating split rows (pattern 15) ----------
   Flip which side the tag column sits on via flex-direction: row-reverse on
   even rows — DOM order (tag, then heading+body) never changes, only the
   visual side, so reading/tab order stays constant per the pattern's a11y
   guard. */
.mechanics-row {
  display: flex;
  flex-direction: column;
  gap: .75rem;
  padding-block: clamp(2rem, 5vw, 3rem);
  border-block-start: 1px solid var(--border-paper);
}
.mechanics-row:first-of-type { border-block-start: none; }
@media (min-width: 760px) {
  .mechanics-row {
    flex-direction: row;
    gap: clamp(2rem, 5vw, 4rem);
    align-items: baseline;
  }
  .mechanics-row:nth-of-type(even) { flex-direction: row-reverse; }
  .mechanics-row .mechanics-tag-col { flex: 0 0 11rem; }
  .mechanics-row .mechanics-body-col { flex: 1 1 auto; }
}
.mechanics-tag {
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--fg-ink-muted);
}
.mechanics-row h3 {
  font-size: var(--fs-h3);
  font-weight: 650;
  color: var(--fg-ink);
  margin-block: .5rem .5rem;
  max-width: 22ch;
}
.mechanics-row p {
  color: var(--fg-ink-muted);
  max-width: var(--measure);
}

/* ---------- scope (03) ---------- */
.scope-grid {
  display: grid;
  gap: clamp(2rem, 5vw, 3rem);
  margin-block-start: 2rem;
}
@media (min-width: 760px) {
  .scope-grid { grid-template-columns: 1fr 1fr; }
}
.scope-grid h3 {
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--fg-ink-muted);
  margin-block-end: 1rem;
}
.scope-grid ul { list-style: none; }
.scope-grid li {
  color: var(--fg-ink);
  padding-block: .5rem;
  border-block-start: 1px solid var(--border-paper);
}
.scope-grid li:first-child { border-block-start: none; }
.scope-grid .not-yet {
  color: var(--fg-ink-muted);
}
.scope-grid .not-yet li { color: var(--fg-ink-muted); border-block-start-color: var(--border-paper); }

/* pricing statement — its own small block, not a footnote of the "not yet"
   column. Reuses already-audited colour pairs (fg-ink-muted/fg-ink on
   paper, border-paper on paper) rather than introducing new ones. */
.pricing-block {
  margin-block-start: clamp(2rem, 5vw, 3rem);
  padding: 1.25rem 1.5rem;
  border: 1px solid var(--border-paper);
  border-radius: 4px;
}
.pricing-label {
  display: block;
  font-family: var(--mono);
  font-size: var(--fs-label);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--fg-ink-muted);
  margin-block-end: .5rem;
}
.pricing-block p {
  color: var(--fg-ink);
  max-width: var(--measure);
}

/* ---------- early access (04) ---------- */
.early-access {
  text-align: left;
}
.early-access h2 { max-width: 20ch; }
.early-access .prose { color: var(--fg-muted); margin-block: 1.25rem 2rem; }
.early-access .prose p { color: var(--fg-muted); }

/* ---------- footer ---------- */
.site-footer {
  border-block-start: 1px solid var(--border-dark);
  padding-block: clamp(2rem, 5vw, 3rem);
  font-size: var(--fs-body);
  color: var(--fg-muted);
}
.site-footer a {
  color: var(--fg);
  text-decoration: underline;
  text-decoration-color: var(--border-dark);
  text-underline-offset: .2em;
  transition: text-decoration-color var(--t-fast) var(--ease-out);
}
.site-footer a:hover { text-decoration-color: var(--accent); }
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.5rem;
  margin-block: 1rem;
  list-style: none;
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: .08em;
}
.footer-fine {
  font-size: var(--fs-label);
  color: var(--fg-muted);
  margin-block-start: 1rem;
}

/* ---------- legal pages (privacy / terms) ---------- */
.legal-page .wrap {
  max-width: var(--measure);
  padding-block: clamp(3rem, 8vw, 5rem);
}
.legal-page h1 {
  font-size: var(--fs-h1);
  font-weight: 650;
  line-height: 1.1;
  margin-block-end: .5rem;
}
.legal-page .updated {
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--fg-ink-muted);
  margin-block-end: 2.5rem;
}
.legal-page h2 {
  font-size: var(--fs-h3);
  font-weight: 650;
  color: var(--fg-ink);
  margin-block: 2.25rem .75rem;
}
.legal-page h3 {
  font-size: var(--fs-body-lg);
  font-weight: 650;
  color: var(--fg-ink);
  margin-block: 1.5rem .5rem;
}
.legal-page p, .legal-page li { color: var(--fg-ink); }
.legal-page p + p, .legal-page ul + p, .legal-page p + ul { margin-block-start: 1em; }
.legal-page hr {
  border: none;
  border-block-start: 1px solid var(--border-paper);
  margin-block: 2rem;
}
.legal-page ul, .legal-page ol { padding-inline-start: 1.25em; }
.legal-page li + li { margin-block-start: .35em; }
.legal-page a { text-decoration: underline; color: var(--fg-ink); text-decoration-color: var(--border-paper); }
.legal-page a:hover { text-decoration-color: var(--fg-ink); }
.legal-page code {
  font-family: var(--mono);
  font-size: .92em;
  background: var(--paper-2);
  padding: .1em .35em;
  border-radius: 2px;
}
.legal-page table {
  border-collapse: collapse;
  width: 100%;
  margin-block: 1.25rem;
  font-size: var(--fs-body);
}
.legal-page th, .legal-page td {
  text-align: left;
  padding: .6rem .75rem;
  border: 1px solid var(--border-paper);
  vertical-align: top;
}
.legal-page th {
  background: var(--paper-2);
  font-weight: 650;
}
.legal-back {
  display: inline-block;
  margin-block-end: 2rem;
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: .08em;
}

/* pending-content notice (shown only if a legal page ships before its
   source markdown exists — see build report) */
.content-pending {
  border: 1px dashed var(--border-paper);
  padding: 1rem 1.25rem;
  color: var(--fg-ink-muted);
  font-family: var(--mono);
  font-size: var(--fs-label);
  text-transform: uppercase;
  letter-spacing: .06em;
}
