/*
  0800Labs — Pre-launch site stylesheet.
  Design system source of truth: knowledge/VISUAL_IDENTITY.md (v2 —
  "quiet workday luxury × laboratory precision"). Do not introduce
  colours, fonts, or decorative motifs not documented there without a
  founder decision recorded in knowledge/DECISIONS.md.

  v2 architecture note: sections are wrapped in a surface class
  (.surface-navy / .surface-bone / .surface-ink) which sets the
  --surface-* custom properties. Shared components (buttons, hairlines,
  cards, badges) read those properties instead of hardcoded colours, so
  the same markup works correctly regardless of which surface it sits
  on. This is what makes Navy/Bone alternation possible without a
  parallel set of light/dark component styles.
*/

:root {
  /* Raw palette — knowledge/VISUAL_IDENTITY.md §1 */
  --navy: #0B0E1A;
  --ink: #08090D;
  --bone: #F2F0E9;
  --cyan: #1EC8F0;
  --cyan-dark: #0E8FB0;
  /* Cyan Deep — 2026-09-19 accessibility addition, not a v2 EVOLUTION
     value. Same hue/saturation family as Cyan and Cyan Dark, darkened
     until cyan-toned text clears 4.5:1 on Bone (computed: 4.93:1).
     Cyan Dark's own ~3.3:1 on Bone is enough for large text/graphics
     but not normal text — see knowledge/VISUAL_IDENTITY.md §1. */
  --cyan-deep: #0A7090;
  --off-white: #F8FAFC;
  --slate: #5A6580;

  --font-display: 'Syne', system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'Courier New', monospace;
  --font-serif: 'Lora', Georgia, serif;
  --font-sans: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  /* Default surface tokens — match the Navy body default, so any
     element outside an explicit .surface-* wrapper (e.g. an <hr>
     sitting between two sections) still resolves sensibly instead of
     rendering with an invalid/unset custom property. */
  --surface-bg: var(--navy);
  --surface-text: var(--off-white);
  --surface-muted: #9AA3B8;
  --surface-border: rgba(248, 250, 252, 0.14);
  --surface-border-strong: rgba(248, 250, 252, 0.3);
  /* Surface-scoped signal colour — resolves to Cyan everywhere except
     Bone, where plain Cyan text/focus-rings fail WCAG 2.2 AA contrast
     (1.74:1, needs 4.5:1 for text / 3:1 for a focus indicator). Every
     rule that renders Cyan as text or an outline (not a decorative
     rule/border/box-shadow) should read this token, not --cyan
     directly, so the fix can't regress if reused on a new surface. */
  --surface-signal: var(--cyan);

  --container-width: 1100px;
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.75rem;
  --space-4: 2.75rem;
  --space-5: 4.5rem;
  --space-6: 7rem;
}

*, *::before, *::after { box-sizing: border-box; }

html { color-scheme: light dark; }

body {
  margin: 0;
  background: var(--navy);
  color: var(--off-white);
  font-family: var(--font-sans);
  font-style: normal;
  font-size: 1.0625rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img, svg { max-width: 100%; display: block; }

a { color: inherit; text-decoration-color: var(--cyan); text-underline-offset: 0.2em; }
a:hover { color: var(--surface-signal); }

a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 2px solid var(--surface-signal);
  outline-offset: 3px;
}

h1, h2, h3, h4 {
  font-weight: 700;
  font-style: normal;
  line-height: 1.12;
  letter-spacing: -0.01em;
  margin: 0 0 var(--space-2);
}

/* Syne is a display asset for major moments only — opt in per-element
   with .display (homepage hero, About's opening statement). h1 is NOT
   automatically Syne: continuous large Syne on every h1 (every Field
   Note, every interior page) is exactly the "oversized display type on
   every heading" SaaS-risk driver VISUAL_IDENTITY.md §3 and §12 warn
   against. Interior h1s fall through to the same restrained sans as
   h2/h3 below. */
.display {
  font-family: var(--font-display);
  font-weight: 800;
}

h2, h3, h4 { font-family: var(--font-sans); }

h1 { font-size: clamp(2.1rem, 4.5vw + 1rem, 3.6rem); }
h2 { font-size: clamp(1.5rem, 2.2vw + 1rem, 2.15rem); }
h3 { font-size: clamp(1.15rem, 1.2vw + 1rem, 1.4rem); }

p { margin: 0 0 var(--space-2); }

/* Editorial accent — Lora Italic, used deliberately sparingly:
   pull-quotes and one hero line. NOT the running body voice — see
   VISUAL_IDENTITY.md §3 ("not as a default running voice"). Long-form
   article text (.article-body) reads in plain sans; only a genuine
   pull-quote/editorial accent gets the italic serif treatment. */
.pull-quote, .editorial {
  font-family: var(--font-serif);
  font-style: italic;
}

.mono {
  font-family: var(--font-mono);
  font-style: normal;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.signal { color: var(--cyan); }

.container {
  width: 100%;
  max-width: var(--container-width);
  margin-inline: auto;
  padding-inline: var(--space-2);
}

@media (min-width: 640px) {
  .container { padding-inline: var(--space-3); }
}

.section { padding-block: var(--space-5); }

/* ============================================================
   Surfaces — the core of v2's rhythm. Navy and Bone alternate as
   the two major surfaces; Ink is reserved for the darkest/most
   institutional moments (header, footer, conversion destination).
   ============================================================ */
.surface-navy {
  --surface-bg: var(--navy);
  --surface-text: var(--off-white);
  --surface-muted: #9AA3B8;
  --surface-border: rgba(248, 250, 252, 0.14);
  --surface-border-strong: rgba(248, 250, 252, 0.3);
  --surface-signal: var(--cyan);
  background: var(--surface-bg);
  color: var(--surface-text);
}

.surface-bone {
  --surface-bg: var(--bone);
  --surface-text: var(--ink);
  --surface-muted: var(--slate);
  --surface-border: rgba(8, 9, 13, 0.14);
  --surface-border-strong: rgba(8, 9, 13, 0.32);
  /* The one functional change in this rule set: plain Cyan text/focus
     rings fail WCAG 2.2 AA on Bone (1.74:1). Cyan Deep clears 4.5:1. */
  --surface-signal: var(--cyan-deep);
  background: var(--surface-bg);
  color: var(--surface-text);
  /* Real irregular paper grain, not a repeating dot lattice. The
     previous radial-gradient(...) on a fixed 5px grid was mechanically
     perfect — that regularity is exactly what makes a fake texture
     read as generated rather than physical, since real paper fibre has
     no fixed pitch. This is an SVG fractal-noise filter instead:
     genuinely non-repeating grain, alpha kept near-invisible (see the
     feColorMatrix alpha row) so it reads as tactility, not decoration.
     Closer to what a macro shot of real paper actually looks like. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220' viewBox='0 0 220 220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0.03  0 0 0 0 0.035  0 0 0 0 0.051  0.07 0 0 0 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-repeat: repeat;
}

.surface-ink {
  --surface-bg: var(--ink);
  --surface-text: var(--off-white);
  --surface-muted: #8A93A8;
  --surface-border: rgba(248, 250, 252, 0.14);
  --surface-border-strong: rgba(248, 250, 252, 0.3);
  --surface-signal: var(--cyan);
  background: var(--surface-bg);
  color: var(--surface-text);
}

.text-muted { color: var(--surface-muted); }

.hairline {
  border: none;
  border-top: 1px solid var(--surface-border);
  margin: 0;
}

/* Skip link */
.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--cyan);
  color: var(--ink);
  padding: var(--space-1) var(--space-2);
  z-index: 100;
  font-family: var(--font-mono);
  font-weight: 700;
}

.skip-link:focus { left: var(--space-2); top: var(--space-2); }

/* Header — kept on Navy as fixed institutional chrome around the
   alternating content surfaces. */
.site-header {
  border-bottom: 1px solid rgba(248, 250, 252, 0.14);
  position: sticky;
  top: 0;
  background: rgba(11, 14, 26, 0.94);
  backdrop-filter: blur(6px);
  z-index: 50;
}

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: var(--space-2);
}

/* ============================================================
   Homepage only: header floats transparently over the hero photo
   instead of sitting in its own solid bar above it, so the hero reads
   as one uninterrupted full-bleed frame. Scoped to body.page-home so
   every other page keeps the plain sticky/solid header unchanged.
   Goes solid again once the hero has scrolled out of view (toggled by
   main.js's heroHeaderObserver, an IntersectionObserver — no scroll
   listener), so navigation stays legible over the lighter Bone/photo
   surfaces further down the page.
   ============================================================ */
.page-home .site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  background: linear-gradient(to bottom, rgba(8, 9, 13, 0.55) 0%, rgba(8, 9, 13, 0) 100%);
  border-bottom-color: transparent;
  backdrop-filter: none;
  transition: background 300ms ease, border-color 300ms ease, backdrop-filter 300ms ease;
}

.page-home .site-header.header-solid {
  background: rgba(11, 14, 26, 0.94);
  border-bottom-color: rgba(248, 250, 252, 0.14);
  backdrop-filter: blur(6px);
}

.wordmark {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.1rem;
  color: var(--off-white);
  text-decoration: none;
  letter-spacing: -0.01em;
}

.wordmark:hover { color: var(--cyan); }

.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: none;
  border: 1px solid rgba(248, 250, 252, 0.3);
  color: var(--off-white);
  font-family: var(--font-sans);
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.4rem 0.7rem;
  cursor: pointer;
}

.primary-nav { display: flex; align-items: center; gap: var(--space-4); }

.primary-nav ul {
  list-style: none;
  display: flex;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
}

/* Italic-serif navigation is explicitly rejected in v2 — plain,
   restrained system sans only. See VISUAL_IDENTITY.md §3.
   Scoped to .primary-nav ul a (the actual nav links), NOT .primary-nav
   a generally — the CTA button (.btn.btn-solid) sits as a sibling of
   the <ul>, not inside it. 2026-09-14 bug: this rule used to read
   ".primary-nav a" and, at (0,0,1,1), was MORE specific than
   ".btn-solid" alone (0,0,1,0), so its color: off-white silently beat
   .btn-solid's color: ink on the nav CTA. Harmless while .btn-solid's
   fill was cyan (off-white-on-cyan still read fine by accident); once
   .btn-solid's fill became off-white, this produced invisible
   white-on-white text on the header CTA specifically. Scoping to
   "ul a" removes the accidental specificity fight entirely rather
   than patching it with a second override or !important. */
.primary-nav ul a {
  position: relative;
  text-decoration: none;
  font-family: var(--font-sans);
  font-style: normal;
  font-size: 0.94rem;
  color: var(--off-white);
  padding-bottom: 0.2rem;
}

.primary-nav ul a[aria-current="page"] { color: var(--cyan); }

/* Underline-wipe on hover/focus — a considered, single-purpose
   interaction rather than a colour change alone. transform-only
   (GPU-safe), matching the site's existing motion convention. */
.primary-nav ul a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--cyan);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 220ms ease;
}

.primary-nav ul a:hover::after,
.primary-nav ul a:focus-visible::after { transform: scaleX(1); }

@media (max-width: 780px) {
  .nav-toggle { display: inline-flex; }
  .primary-nav {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    background: var(--navy);
    border-bottom: 1px solid rgba(248, 250, 252, 0.14);
    padding: var(--space-2);
    display: none;
  }
  .primary-nav.is-open { display: flex; }
  .primary-nav ul { flex-direction: column; gap: var(--space-2); }
  .primary-nav .btn { text-align: center; }
}

@media (min-width: 781px) {
  .nav-toggle { display: none; }
  .primary-nav { display: flex !important; }
}

/* ============================================================
   Buttons — neutral sans UI by default. Outline buttons use the
   surrounding surface's own border/text colour, not cyan, so cyan
   stays a signal rather than a repeated UI colour.
   VISUAL_IDENTITY.md §1 ("occasional high-value CTA").
   ============================================================ */
.btn {
  display: inline-block;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 0.65rem 1.1rem;
  border: 1px solid var(--surface-border-strong);
  color: var(--surface-text);
  background: transparent;
  cursor: pointer;
  transition: border-color 200ms ease, color 200ms ease, background 200ms ease, transform 150ms ease;
}

.btn:hover { border-color: var(--cyan); color: var(--cyan); transform: translateY(-1px); }

/* Restrained physical feedback on press — a 1px settle, not a bounce.
   Kept deliberately subtle to match the "physical ritual, not digital
   gimmickry" register (ARCHETYPE.md principle 6). */
.btn:active { transform: translateY(1px); }

/* 2026-09-14: was a solid cyan fill — founder feedback (measured
   against longines.com as the "premium" reference) named this the
   single biggest tell against the brand's own "cyan is a signal, not
   a fill" rule (VISUAL_IDENTITY.md §1: cyan should target ~5-10% of a
   composition, never a dominant surface) — a bright saturated block on
   every page's highest-contrast element read as fintech/SaaS, not
   quiet workday luxury. Replaced with the same neutral off-white/ink
   fill the rest of the identity already uses, with the primary action
   distinguished by a thin cyan inset rule instead of a cyan block —
   cyan still marks it, it just isn't the button's whole body. */
.btn-solid {
  background: var(--off-white);
  border-color: var(--off-white);
  color: var(--ink);
  box-shadow: inset 0 -3px 0 0 var(--cyan);
}

.btn-solid:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--off-white);
  box-shadow: inset 0 -3px 0 0 var(--cyan);
}

.btn-lg { font-size: 0.92rem; padding: 0.9rem 1.6rem; }

/* ============================================================
   Hero — full-bleed photo, text overlaid at the bottom via scrim.
   2026-09-12: replaced the earlier asymmetric split (text left /
   small framed video right) with this full-bleed treatment when the
   hero image changed from the "Office Chair Commute" video
   (native 816x464 — upscaled to full-bleed, it visibly blurred) to
   the "Ways to Call in Sick" still (native 1672x941, more than 2x the
   resolution, so full-bleed here doesn't soften on a normal desktop
   viewport). Reuses the same full-bleed pattern already proven on the
   Field Test 001 / Foundation editorial banners rather than inventing
   a new one.
   ============================================================ */
.hero { position: relative; }

.hero-photo {
  overflow: hidden;
  min-height: min(88vh, 760px);
  display: flex;
  align-items: flex-end;
}

.hero-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;
}

.hero-photo .scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(8, 9, 13, 0.9) 0%, rgba(8, 9, 13, 0.65) 22%, rgba(8, 9, 13, 0.15) 45%, rgba(8, 9, 13, 0) 65%);
}

.hero-photo-content {
  position: relative;
  z-index: 1;
  padding-block: var(--space-4) var(--space-5);
}

.hero .kicker {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--cyan);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--space-2);
}

.hero h1 { max-width: 16ch; font-size: clamp(2.3rem, 5vw + 1rem, 3.9rem); margin-bottom: var(--space-2); }

/* One of the few deliberate Lora-italic moments — a single-line
   editorial accent, not a paragraph. Kept deliberately quieter than
   the headline so the h1 reads as the unambiguous focal point. */
.hero .lede {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 1.05rem;
  max-width: 38ch;
  color: #C7CCDA;
}

.hero .cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin-top: var(--space-3); }

/* ============================================================
   Quiet typographic hero — 2026-09-19 homepage restructure
   (Direction A: Typography-Led Editorial, chosen over a documentary
   photo-led direction after an Impeccable design-comp review). Opens
   the homepage on Bone with no photography, trading the previous
   full-bleed photo hero's opening weight for restraint and hierarchy.
   The real Field Test 001 photo section further down the page is
   untouched — this is about the opening beat only, not a site-wide
   no-imagery rule.
   Self-contained, not built on .hero/.hero-photo: .hero .kicker
   hardcodes var(--cyan) and .hero .lede hardcodes a light grey
   (#C7CCDA), both safe only on the dark/photo background .hero was
   previously always paired with. Reusing either unmodified on this
   Bone surface would silently reintroduce the exact WCAG 2.2 AA
   contrast failure fixed elsewhere on 2026-09-19 (see
   knowledge/VISUAL_IDENTITY.md §1) — so this component defines its
   own surface-aware versions instead of extending .hero's.
   ============================================================ */
.hero-type {
  position: relative;
  padding-top: var(--space-6);
  padding-bottom: var(--space-6);
}
.hero-type .kicker {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: var(--surface-signal);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--space-2);
}
.hero-type h1 {
  max-width: 16ch;
  font-size: clamp(2.3rem, 5vw + 1rem, 3.9rem);
  margin-top: var(--space-3);
  margin-bottom: var(--space-2);
}
.hero-type .lede {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: 1.05rem;
  max-width: 34ch;
  color: var(--surface-muted);
}
.hero-type .cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-3);
}
/* Corner citation stamp, echoing the footer's existing .page-ref
   convention (e.g. "Ref · FN·019 · 2026.09.18") at the top of the page
   instead of only the bottom — same real-date device, not a second
   invented one. Two lines: a fixed "REF / HOME" label (the "/" is the
   one deliberate cyan mark — --surface-signal, not raw --cyan, since
   this sits on .surface-bone and raw cyan text fails WCAG there) and
   a live date line kept current by main.js. Updates once a day
   (UK midnight) — no ticking clock, no live seconds: a stamped
   dateline, not a running clock (see knowledge/VISUAL_IDENTITY.md's
   "physical, not digital" test and §12's SaaS-dashboard/terminal
   warning — a live clock was considered and explicitly rejected). */
.hero-ref {
  position: absolute;
  top: var(--space-3);
  right: 0;
  text-align: right;
  font-family: var(--font-mono);
  text-transform: uppercase;
  color: var(--surface-muted);
}
.hero-ref-label {
  display: block;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
}
.hero-ref-mark { color: var(--surface-signal); }
.hero-ref-date {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}
@media (max-width: 780px) {
  .hero-ref { position: static; display: block; text-align: right; margin-bottom: var(--space-3); }
}

/* Dense, evidence-forward counterweight to the quiet hero/worldview
   beats either side of it (Direction A's "alternate density
   explicitly" principle) ahead of the existing .architecture-strip,
   added 2026-09-19 for the homepage's Workday Hydration section.
   2026-09-20: dropped the mono font-family this originally carried —
   it put two full sentences of body prose in the Mono "laboratory"
   tier, which DESIGN.md reserves for short annotations (timestamps,
   codes, labels), and it made the same copy render in two different
   typefaces depending on whether you read it here or on
   workday-hydration.html (plain body text there). Density now comes
   from size/color/line-height on the same sans body font, not a
   typeface swap. */
.density-block { padding-top: var(--space-2); }
.density-block .definition-line {
  font-size: 0.95rem;
  color: var(--surface-muted);
  max-width: 58ch;
  line-height: 1.6;
  margin-bottom: var(--space-1);
}

/* ============================================================
   Split layout — recognition moment, category section, Field Test
   001. Media pane defaults second; .split-flip puts it first.
   ============================================================ */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  align-items: center;
}

.split-flip .split-media { order: -1; }

@media (max-width: 780px) {
  .split { grid-template-columns: 1fr; }
  .split-flip .split-media { order: 0; }
}

/* Media-frame placeholder — a "reserved print" treatment: a quiet,
   evenly-toned mat with a fine inset border and a small corner
   caption, rather than a busy hatch pattern that reads as an
   unfinished wireframe box. Add <img> inside to replace — sizing/
   position already handled, no restructuring needed later. */
.media-frame {
  position: relative;
  border: 1px solid var(--surface-border-strong);
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: rgba(90, 101, 128, 0.06);
  box-shadow: inset 0 0 0 6px var(--surface-bg), inset 0 0 0 7px var(--surface-border);
}

.media-frame.wide { aspect-ratio: 16 / 10; }
.media-frame.square { aspect-ratio: 1 / 1; }

.media-frame img,
.media-frame video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.hero-video-frame video { object-position: center 55%; }

/* Pending state for a media-frame with no <img> yet — registration-mark
   corners and a small mono label, borrowing the same interface/notation
   vocabulary as the hero's ghost-time treatment, so an empty frame reads
   as "reserved for a specific photograph" rather than an unfinished box.
   Remove the .pending class (and this markup) the moment a real <img>
   is added — this is a waiting-room treatment, not a permanent design. */
.media-frame.pending::before,
.media-frame.pending::after {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  border: 1px solid rgba(248, 250, 252, 0.22);
}
.media-frame.pending::before { top: 10px; left: 10px; border-right: none; border-bottom: none; }
.media-frame.pending::after { bottom: 10px; right: 10px; border-left: none; border-top: none; }

.media-frame.pending .pending-label {
  position: absolute;
  bottom: var(--space-2);
  left: var(--space-2);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(248, 250, 252, 0.32);
}

/* Field log — a typographic stand-in for a photograph that doesn't
   exist yet, used instead of an empty "awaiting photography" frame.
   Content is drawn directly from VISUAL_IDENTITY.md §5's own
   illustrative shot list, presented as research notation (what we're
   watching for) rather than a placeholder apology — laboratory
   register, not a lifestyle-photo substitute. Swap for real
   photography once shot; either way this reads as deliberate content,
   not a waiting state. */
.field-log {
  border: 1px solid var(--surface-border-strong);
  aspect-ratio: 16 / 10;
  padding: var(--space-3);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-2);
}

.field-log-label {
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--surface-muted);
}

.field-log-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  font-size: 0.92rem;
}

.field-log-list li {
  display: flex;
  gap: var(--space-2);
  border-top: 1px solid var(--surface-border);
  padding-block: 0.55rem;
}

.field-log-list li:first-child { border-top: none; padding-top: 0; }
.field-log-list li:last-child { padding-bottom: 0; }

.field-log-list .mono {
  color: var(--surface-signal);
  min-width: 3.4em;
  flex-shrink: 0;
}

.media-caption {
  font-size: 0.7rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--surface-muted);
  margin-top: var(--space-2);
}

/* Recognition moment */
.recognition-text .time-giant {
  font-family: var(--font-mono);
  font-size: clamp(2.25rem, 6vw, 3.75rem);
  color: var(--cyan);
  display: block;
  margin-bottom: var(--space-2);
}

.recognition-text p { max-width: 46ch; font-size: 1.05rem; }

/* Badges — neutral by default (Working / TBC / Draft / status tags).
   Deliberately not cyan: these are informational, not a signal or
   a selection state. */
.badge, .status-tag {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--surface-border-strong);
  color: var(--surface-muted);
  margin-bottom: var(--space-2);
}

/* 0800 architecture strip (simple version, used on /workday-hydration) */
.architecture-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 0;
  border-top: 1px solid var(--surface-border);
  border-bottom: 1px solid var(--surface-border);
  margin-block: var(--space-3);
}

.architecture-strip .slot { padding: var(--space-3) var(--space-2); border-left: 1px solid var(--surface-border); }
.architecture-strip .slot:first-child { border-left: none; }

.architecture-strip .code {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--surface-signal);
  font-size: 1.1rem;
  display: block;
  margin-bottom: 0.35rem;
}

.architecture-strip .label { font-size: 0.85rem; color: var(--surface-muted); }

/* Full-bleed variant — strip breaks the .container pattern and spans
   the viewport edge-to-edge, reading as a control panel rather than
   a page section. Lives as a sibling of .container, not inside it. */
.architecture-strip--bleed {
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  padding-inline: var(--space-2);
}
@media (min-width: 640px) {
  .architecture-strip--bleed { padding-inline: var(--space-3); }
}

/* Below 780px, five equal grid columns get too cramped to read
   comfortably (each under ~70px). Swap to a swipeable horizontal
   strip instead of letting auto-fit wrap into an uneven second row —
   same five timestamps, touch-scrollable one at a time. */
@media (max-width: 780px) {
  .architecture-strip--bleed {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .architecture-strip--bleed::-webkit-scrollbar { display: none; }
  .architecture-strip--bleed .slot {
    flex: 0 0 62%;
    scroll-snap-align: start;
  }
}

/* ============================================================
   Editorial banner — full-bleed real photography with a bold stamped
   title, breaking out of the .container pattern like
   .architecture-strip--bleed does. One big deliberate photographic
   moment per use, not a background texture — the image should be the
   whole point of the section, per marketing/CREATIVE_SYSTEM.md's
   "Edited, Not Generated" doctrine (strong cropping, editorial
   tension) rather than a decorative backdrop behind more copy.
   ============================================================ */
.editorial-banner {
  position: relative;
  overflow: hidden;
  min-height: min(64vh, 520px);
  display: flex;
  align-items: flex-end;
}

.editorial-banner img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.editorial-banner .scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(8, 9, 13, 0.75) 0%, rgba(8, 9, 13, 0.2) 45%, rgba(8, 9, 13, 0) 68%);
}

.editorial-banner-content {
  position: relative;
  z-index: 1;
  width: 100%;
  padding-block: var(--space-4) var(--space-4);
}

.editorial-banner .kicker {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--cyan);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--space-2);
}

.editorial-banner h2 {
  font-family: var(--font-display);
  font-weight: 800;
  text-transform: uppercase;
  color: var(--off-white);
  font-size: clamp(1.8rem, 5vw, 3.2rem);
  line-height: 1.05;
  max-width: 18ch;
  margin: 0 0 var(--space-2);
}

.editorial-banner-content p {
  color: rgba(248, 250, 252, 0.85);
  max-width: 46ch;
  margin: 0 0 var(--space-2);
  font-size: 0.98rem;
}

.editorial-banner-content a { color: var(--off-white); text-decoration-color: var(--cyan); }

.editorial-banner-top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1;
  padding: var(--space-3);
}
.editorial-banner-top .kicker { margin-bottom: 0; }

/* Quiet variant — for a photograph that already carries its own text
   (a prop, a printed artefact) and doesn't need a second stamped
   headline competing with it. Marginal kicker/caption only. */
.editorial-banner--quiet .editorial-banner-content { display: flex; flex-direction: column; }
.editorial-banner--quiet .mono-caption {
  align-self: flex-end;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  color: rgba(248, 250, 252, 0.82);
  text-align: right;
  max-width: 32ch;
  margin: 0;
}

/* Pull-quote — one of the deliberate Lora-italic moments, framed by
   a single cyan signal line (Field Test 001 and similar). */
.pull-quote {
  font-size: clamp(1.35rem, 2vw + 1rem, 1.85rem);
  line-height: 1.4;
  border-left: 2px solid var(--cyan);
  padding-left: var(--space-3);
  margin: var(--space-3) 0;
}

/* Cards (Field Notes) */
.card-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  margin-top: var(--space-3);
}

.card { border-top: 1px solid var(--surface-border); padding-top: var(--space-2); }

.card .eyebrow {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--surface-signal);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  display: block;
  margin-bottom: 0.4rem;
}

.card h3 { margin-bottom: 0.5rem; }
.card h3 a { text-decoration: none; color: var(--surface-text); }
.card h3 a:hover { color: var(--surface-signal); }
.card p { color: var(--surface-muted); font-size: 0.98rem; }

.card-media { margin-bottom: var(--space-2); }
.card.has-media { border-top: none; padding-top: 0; }

/* ============================================================
   Homepage: Latest Field Notes — specimen log treatment.
   Scoped entirely to .specimen-grid / .field-log-archive so it
   never touches the shared .card / .field-log-list components
   used on field-notes.html and about.html. Reuses only existing
   tokens (--cyan, --navy, --surface-*, --font-mono) — no new
   colors, no border-radius, motion limited to transform/opacity
   per the site's existing GPU-safe convention.
   ============================================================ */
.specimen-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  grid-template-rows: repeat(2, auto);
  gap: 1px;
  background: var(--surface-border);
  border: 1px solid var(--surface-border);
  margin-top: var(--space-3);
}

.specimen-card {
  position: relative;
  overflow: hidden;
  background: var(--surface-bg);
  padding: var(--space-3);
  border-left: 2px solid transparent;
  transition: border-color 250ms ease, transform 250ms ease, box-shadow 250ms ease;
}

/* Faint oversized numeral behind each card, echoing the same
   ghost-numeral device already used in the homepage hero
   (.hero-media .ghost-time) — not a new visual language, the same
   one extended. Uses var(--surface-text) + opacity rather than a
   hardcoded color so it adapts correctly on both this section's dark
   (navy) and light (bone) theme variants. aria-hidden: it repeats
   the same number already in .specimen-code, so it carries no
   information of its own. */
.specimen-ghost {
  position: absolute;
  right: -0.04em;
  bottom: -0.14em;
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: clamp(4.5rem, 13vw, 8.5rem);
  color: var(--surface-text);
  opacity: 0.05;
  line-height: 1;
  letter-spacing: -0.02em;
  pointer-events: none;
  user-select: none;
  z-index: 0;
}

.specimen-card > *:not(.specimen-ghost) { position: relative; z-index: 1; }

.specimen-card--primary {
  grid-column: 1;
  grid-row: 1 / 3;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.specimen-card:hover {
  border-left-color: var(--cyan);
  transform: translateX(3px);
  box-shadow: -10px 0 28px -14px rgba(30, 200, 240, 0.4);
}

.digit-roll { font-variant-numeric: tabular-nums; }

.specimen-code {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  color: var(--surface-signal);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  display: block;
  margin-bottom: 0.5rem;
}

.specimen-card--primary h3 { font-size: clamp(1.4rem, 1.1vw + 1.1rem, 1.95rem); }
.specimen-card h3 { margin-bottom: 0.5rem; }
.specimen-card h3 a { text-decoration: none; color: var(--surface-text); }
.specimen-card h3 a:hover { color: var(--surface-signal); }
.specimen-card p { color: var(--surface-muted); font-size: 0.95rem; }

@media (max-width: 780px) {
  .specimen-grid { grid-template-columns: 1fr; }
  .specimen-card--primary { grid-column: 1; grid-row: auto; }
}

.field-log-archive {
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
  border-top: 1px solid var(--surface-border);
}

.field-log-archive li { border-bottom: 1px solid var(--surface-border); }

.field-log-archive a {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding-block: 0.85rem;
  text-decoration: none;
  color: var(--surface-text);
  transition: transform 200ms ease, color 200ms ease;
}

.field-log-archive a:hover { color: var(--surface-signal); transform: translateX(0.5rem); }

.field-log-archive .specimen-code {
  min-width: 9.5em;
  flex-shrink: 0;
  margin-bottom: 0;
  color: var(--surface-muted);
  transition: color 200ms ease;
}

.field-log-archive a:hover .specimen-code { color: var(--surface-signal); }
.field-log-archive .archive-title { flex: 1; }

.field-log-archive .archive-arrow {
  font-family: var(--font-mono);
  flex-shrink: 0;
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity 200ms ease, transform 200ms ease;
}

.field-log-archive a:hover .archive-arrow { opacity: 1; transform: translateX(0); }

@media (max-width: 780px) {
  .field-log-archive a { flex-wrap: wrap; }
  .field-log-archive .specimen-code { min-width: 0; }
}

/* About page "Different disciplines" list — replaces a 6-item equal
   card-grid (the generic auto-fill 3x2 box pattern) with a two-column
   label/description row list, since the six disciplines are
   deliberately peer/equal by content (no natural 1-big+5-small
   hierarchy to force), matching the site's other hairline-divided
   list patterns rather than introducing a third grid style. */
.discipline-list {
  list-style: none;
  margin: var(--space-3) 0 0;
  padding: 0;
  border-top: 1px solid var(--surface-border);
}

.discipline-list li {
  display: grid;
  grid-template-columns: 12rem 1fr;
  gap: var(--space-3);
  padding-block: var(--space-3);
  border-bottom: 1px solid var(--surface-border);
}

.discipline-list .discipline-label {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  /* var(--surface-signal), not var(--cyan) directly — 2026-09-19: this
     component is now also used on a Bone surface (homepage Expertise
     section), where plain Cyan text fails WCAG 2.2 AA contrast
     (1.74:1). Previously safe by accident: About's usage is Navy-only.
     See knowledge/VISUAL_IDENTITY.md §1. */
  color: var(--surface-signal);
  padding-top: 0.2em;
}

.discipline-list h3 { margin-bottom: 0.35rem; }
.discipline-list p { color: var(--surface-muted); font-size: 0.95rem; margin: 0; }

@media (max-width: 780px) {
  .discipline-list li { grid-template-columns: 1fr; gap: var(--space-1); }
}

/* Article (Field Note / Workday Hydration essay) */
.article-header { padding-block: var(--space-5) var(--space-3); }
.article-header .dek { font-size: 1.1rem; color: var(--surface-muted); max-width: 46ch; }

.article-body { max-width: 62ch; }
.article-body p { font-size: 1.08rem; }
.article-body p:first-of-type { font-size: 1.2rem; }

/* FAQ accordion — native <details>/<summary>, no JS. Used wherever a
   Questions block appears (article pages, workday-hydration.html). */
.faq-list { margin-top: var(--space-2); }
.faq-item { border-top: 1px solid var(--surface-border); }
.faq-item:last-child { border-bottom: 1px solid var(--surface-border); }
.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-3) 0;
  cursor: pointer;
  list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary h3 { margin: 0; font-size: 1.05rem; font-weight: 600; }
.faq-icon {
  flex-shrink: 0;
  width: 1rem;
  height: 1rem;
  position: relative;
  transition: transform 0.2s ease;
}
.faq-icon::before, .faq-icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--surface-muted);
  transform: translate(-50%, -50%);
}
.faq-icon::before { width: 0.8rem; height: 1.5px; }
.faq-icon::after { width: 1.5px; height: 0.8rem; }
.faq-item[open] .faq-icon { transform: rotate(45deg); }
.faq-item[open] summary h3 { color: var(--surface-signal); }
.faq-answer { padding-bottom: var(--space-3); }
.faq-answer p { color: var(--surface-muted); font-size: 1.08rem; margin-top: 0; }
.faq-answer p:last-child { margin-bottom: 0; }

/* Marginalia — sources set apart in a margin column rather than run
   inline in the prose, the way a research document, not a webpage,
   handles citations. Proof-of-concept on a few Field Notes; stacks
   below 781px, matching the site's actual mobile/desktop convention
   (max-width: 780px / min-width: 781px, used by the nav toggle,
   .split, and .architecture-strip--bleed). 2026-09-19: corrected from
   769px, which this comment previously (and incorrectly) claimed was
   that same convention — it wasn't; nothing else in this file uses
   769px, and the two-column grid below needs at least as much room as
   the desktop nav does, so the 1px window where they disagreed showed
   a desktop article layout under a still-mobile nav. */
.article-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}
@media (min-width: 781px) {
  .article-layout {
    grid-template-columns: minmax(0, 62ch) minmax(200px, 260px);
    align-items: start;
    gap: var(--space-5);
  }
  .article-layout .article-body { max-width: none; }
}

.article-marginalia {
  border-top: 1px solid var(--surface-border);
  padding-top: var(--space-3);
}
@media (min-width: 781px) {
  .article-marginalia {
    border-top: none;
    border-left: 1px solid var(--surface-border);
    padding-top: 0;
    padding-left: var(--space-3);
    position: sticky;
    top: var(--space-4);
  }
}
.article-marginalia .marginalia-label {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--surface-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: var(--space-1);
}
.article-marginalia p:not(.marginalia-label) {
  font-size: 0.85rem;
  color: var(--surface-muted);
  line-height: 1.6;
  margin: 0;
}
.article-marginalia ul {
  margin: 0;
  padding-left: 1.1em;
}
.article-marginalia li {
  font-size: 0.85rem;
  color: var(--surface-muted);
  line-height: 1.6;
  margin-bottom: 0.5em;
}
.article-marginalia li:last-child { margin-bottom: 0; }

/* Institutional/utility prose (About, placeholders) — sans, not italic */
.prose { max-width: 58ch; font-size: 1.05rem; }

.related { border-top: 1px solid var(--surface-border); padding-block: var(--space-4); margin-top: var(--space-4); }

.related ul { list-style: none; padding: 0; margin: var(--space-2) 0 0; display: flex; flex-direction: column; gap: 0.5rem; }
.related a { font-family: var(--font-mono); font-size: 0.9rem; text-decoration: underline; text-decoration-color: var(--surface-border-strong); }

/* ============================================================
   Waitlist — conversion destination. Ink surface, centered, larger
   type, so it reads as the page's arrival point. Shared across all
   pages via one class + the .surface-ink wrapper.
   ============================================================ */
.waitlist-section { padding-block: var(--space-6); text-align: center; }
.waitlist-section .container { max-width: 640px; }
.waitlist-section .eyebrow-standalone { justify-content: center; }
.waitlist-section h2 { font-size: clamp(1.9rem, 3.5vw + 1rem, 2.75rem); }
.waitlist-section > .container > p { margin-inline: auto; }

.waitlist-form { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-3); max-width: 34rem; }
.waitlist-section .waitlist-form { margin-inline: auto; justify-content: center; }

.waitlist-form .field { flex: 1 1 240px; display: flex; flex-direction: column; gap: 0.35rem; text-align: left; }

.waitlist-form label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: var(--surface-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.waitlist-form input[type="email"] {
  background: transparent;
  border: 1px solid var(--surface-border-strong);
  color: var(--surface-text);
  font-family: var(--font-sans);
  font-size: 1rem;
  padding: 0.7rem 0.85rem;
}

.waitlist-form input[type="email"]::placeholder { color: var(--surface-muted); }
.waitlist-form button { align-self: flex-end; }

.waitlist-note { font-size: 0.82rem; color: var(--surface-muted); margin-top: var(--space-2); max-width: 34rem; }
.waitlist-section .waitlist-note { margin-inline: auto; }

.waitlist-status { font-family: var(--font-mono); font-size: 0.85rem; margin-top: var(--space-2); min-height: 1.2em; }
.waitlist-status[data-state="error"] { color: #d98a2b; }
.waitlist-status[data-state="ok"] { color: var(--cyan); }

/* Cookie consent banner — quiet bottom bar, not a modal takeover,
   matching the brand's "physical ritual, not digital gimmickry"
   register used elsewhere (see .btn:active above). Ink surface so it
   reads as a distinct strip rather than blending into Navy content. */
.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 100;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--ink);
  color: var(--off-white);
  border-top: 1px solid var(--surface-border-strong);
  box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.3);
}

.cookie-banner-text {
  margin: 0;
  max-width: 62ch;
  font-size: 0.92rem;
  line-height: 1.5;
}

.cookie-banner-text a { text-decoration: underline; text-decoration-color: var(--cyan); }

.cookie-banner-actions { display: flex; gap: var(--space-2); flex-shrink: 0; }

@media (max-width: 640px) {
  .cookie-banner { flex-direction: column; align-items: stretch; text-align: center; }
  .cookie-banner-actions { justify-content: center; }
}

/* Footer */
.site-footer { padding-block: var(--space-4); }

.footer-grid { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-4); }
.footer-grid nav ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.footer-grid a { text-decoration: none; font-size: 0.92rem; font-family: var(--font-sans); }

.footer-legal { display: flex; gap: var(--space-2); margin-top: var(--space-4); font-family: var(--font-mono); font-size: 0.75rem; color: var(--surface-muted); }
.footer-legal a { color: var(--surface-muted); }

.footer-fine { margin-top: var(--space-2); font-family: var(--font-mono); font-size: 0.7rem; color: var(--surface-muted); }

/* Page reference stamp — a quiet, truthful document-control line on
   every page's footer, extending the Field Notes specimen-code system
   (FN·019 etc.) site-wide rather than confining it to articles. Each
   code and date is real (the page's own content_id, or its actual git
   last-modified date for non-Field-Note pages) — never decorative or
   invented. See knowledge/VISUAL_IDENTITY.md §3: Mono is "the
   laboratory/system layer" of the identity.
   2026-09-20: brought in line with the homepage hero stamp's "editorial
   reference system" redesign — bumped off the 10.56px undersized-text
   floor to 11.52px (matching the hero date line), reformatted the date
   from YYYY.MM.DD to the hero's "DD MON YYYY" (one date format site-
   wide, not two), and added the same single cyan registration mark
   (--surface-signal, not raw --cyan — this renders on both Bone and
   Navy footers depending on page) on the first separator only. Also
   dropped the old opacity:0.65 muting in favour of relying on
   --surface-muted alone for quietness: opacity applies to the whole
   subtree's compositing, so it was flattening the new cyan mark into
   the same faintness as the surrounding grey text, defeating the
   point of a deliberate signal colour — a child's own opacity can't
   undo that, only removing the parent's opacity can. This stamp
   itself stays static per page (a real last-touched date, not a live
   "today") — only the hero's own date is live; see main.js. */
.page-ref {
  margin-top: 0.35rem;
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--surface-muted);
}
.page-ref-mark { color: var(--surface-signal); }

/* Utility */
.mt-0 { margin-top: 0; }

.eyebrow-standalone {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: 0.78rem;
  color: var(--surface-signal);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  display: block;
  margin-bottom: var(--space-2);
}

/* ============================================================
   Scroll reveal — a single, motivated fade + 8px rise on section
   entry (hierarchy: draws attention to the next section as it
   arrives). Motion intensity target 3-4/10 — nothing scroll-hijacked,
   no parallax. Safe by default: content is fully visible unless JS
   confirms it ran (.js on <html>, set by main.js) AND the visitor
   hasn't asked for reduced motion — so no-JS visitors, JS-error
   visitors, and reduced-motion visitors always see full content with
   no animation and no risk of a stuck-invisible section. See main.js.
   ============================================================ */
.reveal { opacity: 1; transform: none; }

@media (prefers-reduced-motion: no-preference) {
  html.js .reveal {
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 0.5s ease, transform 0.5s ease;
  }
  html.js .reveal.is-visible {
    opacity: 1;
    transform: none;
  }

  /* Quiet scale-in accent for one specific photograph (the Field Test
     001 / Creative image on the homepage) — settles from 97% to 100%
     scale as it enters view, instead of the plain rise .reveal gives
     everything else. Two classes (0,0,2,0) beats plain .reveal
     (0,0,1,0) regardless of source order, so this cleanly overrides
     just the transform for elements that opt in, without touching
     .reveal's behaviour anywhere else on the site. */
  html.js .reveal.reveal-scale { transform: scale(0.97); }
  html.js .reveal.reveal-scale.is-visible { transform: scale(1); }
}

/* Honeypot field — invisible to sighted users and screen readers
   (aria-hidden + off-screen), present for bots. See main.js. Kept
   off-screen rather than display:none, which some bots skip filling
   correctly either way, but this is the more robust convention. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

