/* ══════════════════════════════════════════════════════════════════
   SITE.CSS — architecture root
   ══════════════════════════════════════════════════════════════════
   This file declares the site's cascade-layer order and owns the
   three foundation layers (tokens, base, components) plus the nav/
   footer chrome used on every page. It is the FIRST stylesheet
   linked on every page.

   LAYER ORDER (low → high priority, regardless of file load order):

     tokens      design tokens — colors, type, spacing (:root vars)
     base        reset + bare element defaults (body, a, ::selection)
     utilities   single-purpose helper classes (.label, .rise, .rv)
     components  reusable cross-page chrome (nav, footer, .sec-head)
     templates   shared multi-section page patterns (home, case-study,
                 contact, how-i-build — one file per template family)
     pages       page-specific instance overrides (about.css,
                 folio.css, droplove.css, etc.)

   Cascade layers make this order authoritative no matter how CSS
   specificity or file order would normally resolve a conflict — a
   single-class rule in a `pages` layer ALWAYS beats a rule in
   `components`, even an ID selector. This is what makes the system
   scale: new page CSS never has to fight existing component CSS for
   specificity, and component CSS never has to fight page CSS to stay
   in place. To add a new layer (e.g. a future `overrides` escape
   hatch), extend the declaration below — every file that already
   wraps itself in these layer names slots in automatically.

   HOW TO EXTEND:
     • New shared UI (used on 3+ pages)?      → components layer, this file
       or a new components/*.css file, as the design system grows.
     • New page-family pattern (used by a     → templates layer,
       set of same-shaped pages)?               new file in css/
     • One-off tweaks for a single page?      → pages layer,
                                                 css/<page-name>.css
   ══════════════════════════════════════════════════════════════════ */

@layer tokens, base, utilities, components, templates, pages;

@layer tokens {
  :root {
    /* color */
    --paper:   #F2F1ED;
    --paper-2: #ECEBE6;
    --ink:     #161514;
    --mid:     #68655F; /* darkened from #8A8781 — WCAG AA fix, see decisions.md */
    --line:    #DDDBD4;
    --rosa:    #0000D5; /* Site accent, used widely (nav, footer, links, focus rings) */
    --signal:  #0000D5; /* same accent, newer/rarer token name — finding/flow markers, outcome eyebrow, "full breakdown" link; legacy --rosa remapped to match */

    /* type */
    --display: 'Newsreader', Georgia, 'Times New Roman', serif;
    --body:    'Geist', system-ui, sans-serif;
    --mono:    'Geist Mono', ui-monospace, monospace;

    /* ── TYPE SCALE (v2) — static UI/reading steps + fluid display ──────
       Every size in the site now points at one of these. Static steps
       10–23px; display steps clamp on ONE shared 380→1440px slope, so a
       heading never overtakes a larger heading between breakpoints.
       This file is the sole, authoritative source for the scale —
       css/type-system.css was a dead, unloaded v2-migration draft and was
       deleted 2026-08-30 (see docs/decisions.md). Full rationale + per-role
       migration map: the Type System v2 specimen, styleguide-type.html. */
    --fs-10: 0.625rem;  --fs-11: 0.6875rem; --fs-12: 0.75rem;
    --fs-13: 0.8125rem; --fs-14: 0.875rem;  --fs-16: 1rem;
    --fs-18: 1.125rem;  --fs-20: 1.25rem;   --fs-23: 1.4375rem;
    --fs-serif-lede: clamp(19px, calc(16.85px + 0.57vw), 25px);
    --fs-d1: clamp(28px, calc(23.70px + 1.13vw),  40px);
    --fs-d2: clamp(32px, calc(23.40px + 2.26vw),  56px);
    --fs-d3: clamp(40px, calc(24.20px + 4.15vw),  84px);
    --fs-d4: clamp(44px, calc(19.60px + 6.42vw), 112px);
    --fs-d5: clamp(56px, 8.6vw, 136px);   /* home hero h1 — larger one-off slope */
    --fs-num:    clamp(30px, calc(25px + 1.32vw), 44px);
    --fs-num-xl: clamp(80px, calc(37px + 11.3vw), 200px);
    /* leading */
    --lh-solid: 1;   --lh-hero: 1.05; --lh-snug: 1.2; --lh-title: 1.3;
    --lh-ui: 1.5;    --lh-body: 1.62; --lh-prose: 1.75;
    /* tracking — a function of size, not a free choice */
    --tr-tight: -0.02em; --tr-snug: -0.01em; --tr-flat: 0;
    --tr-caps: 0.08em;   --tr-caps-wide: 0.12em;
    /* weight — replaces the stray 750/800/850 in the case-study CSS */
    --w-reg: 400; --w-med: 500; --w-semi: 600; --w-bold: 700;
    --w-serif: 400; --w-serif-strong: 500;

    /* ── SPACING SCALE (v2) ────────────────────────────────────────────
       The rhythm the site already uses, named. Static steps on a doubling-ish
       ramp (4→64) for gaps/padding inside components; --pad stays the fluid
       page gutter; --space-section is the fluid vertical block padding that
       clamp(...var(--pad)) rules were all re-deriving by hand. */
    --space-3xs: 4px;   --space-2xs: 8px;   --space-xs: 12px;
    --space-sm: 16px;   --space-md: 20px;   --space-lg: 24px;
    --space-xl: 32px;   --space-2xl: 48px;  --space-3xl: 64px;
    --space-section: clamp(36px, 6vh, 64px);   /* block/section vertical padding */

    /* ── COLOR (v2) ────────────────────────────────────────────────────
       Semantic aliases over the existing raw tokens (which stay for
       backwards-compat). New page CSS should reach for these; one accent
       only — --accent === --signal === --rosa, ink sets every heading. */
    --surface:        var(--paper);     /* page ground */
    --surface-raised: var(--paper-2);   /* bands, cards, sec-head */
    --text:           var(--ink);       /* primary text & every heading */
    --text-muted:     var(--mid);       /* secondary / meta (WCAG-AA on paper) */
    --border:         var(--line);      /* hairlines */
    --accent:         var(--rosa);      /* the single accent — links, markers, focus */

    /* Screens type-roles (see css/screens.css and the four *-mockup.css
       generated files, which hold the values directly since the Phase 3
       refactor). Literal stacks, NOT
       var(--mono), so they are not shadowed by the product --sans/--serif/
       --mono each mockup redefines inside .wf-embed. --display/--body are
       already safe (mockups don't redefine them). */
    --site-mono: 'Geist Mono', ui-monospace, monospace; /* presentational eyebrows inside .wf-embed */
    --anno-type: 'Geist', system-ui, sans-serif; /* UX annotation voice, shared across projects — plain sans, not mono */
    --site-paper: #F2F1ED; /* chrome/annotation background inside .wf-embed, not var(--paper) — Halyard's
      .wf-embed redefines --paper (#FAFBFC, its own product token) locally, which silently wins over the
      site's paper tone for anything inside it that references the unprefixed var(--paper). Same class of
      bug as --mono/--accent, just for background instead of font-family. 2026-09-07, see decisions.md. */

    /* layout */
    --pad:     clamp(20px, 4vw, 56px);

    /* motion */
    --ease:    cubic-bezier(.2, .7, .2, 1);
  }
}

@layer tokens {
  /* Remaining --client accents only support page-specific components that
     still read var(--client). The global site accent is --rosa / --accent. */
  body.proj-hpcem        { --client: #0096D6; }
  body.proj-droplove     { --client: #F5007B; }
  body.proj-setset       { --client: #9F00D9; }

  /* Tier-3 template demo accents — swap per real project when a template
     gets used for actual client work. Scoped to body class (not bare :root)
     because case-study.css, which defines these templates' shared sections,
     loads on every case-study-style page; an unscoped :root rule would leak
     across pages. */
  body.proj-tier3brand  { --client: #2A6DF4; }
  body.proj-tier3motion { --client: #E86A17; }
  body.proj-tier3web    { --client: #7A1FA2; }
}

@layer base {
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
  html {
    scroll-behavior: smooth;
    font-optical-sizing: auto;   /* Newsreader carries an opsz axis (loaded, now used) */
    text-size-adjust: 100%;
  }
  body {
    background: var(--paper);
    color: var(--ink);
    font-family: var(--body);
    font-size: var(--fs-16);
    line-height: var(--lh-body);
    text-wrap: pretty;
    hanging-punctuation: first allow-end last;   /* Safari — cleaner prose edges */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }
  ::selection { background: var(--rosa); color: var(--paper); }
  a { color: inherit; }
  a:focus-visible, button:focus-visible { outline: 2px solid var(--rosa); outline-offset: 3px; }
  section { border-bottom: 1px solid var(--line); }

  /* Headings balance their line breaks (short, few lines); body stays pretty. */
  h1, h2, h3, h4 { text-wrap: balance; }

  /* Display type — serif, title case, never uppercase-expanded.
     The unified --fs-d4 clamp is anchored at 380px, so it lands near the
     old 39–53px mobile figures on its own — the bespoke ≤800px override
     is no longer needed and has been removed. */
  h1 {
    font-family: var(--display);
    font-weight: var(--w-serif);
    font-size: var(--fs-d4);
    line-height: var(--lh-hero);
    letter-spacing: var(--tr-tight);
    text-transform: none;
    max-width: 24ch;
    font-variation-settings: "opsz" 72;   /* display optical cut on every hero title */
  }
  h3, h4 {
    font-family: var(--display);
    font-weight: var(--w-serif-strong);
    letter-spacing: var(--tr-snug);
    text-transform: none;
  }
  /* Section eyebrow headings (the left label column of every .block) —
     a quiet ink label; the accent no longer sets headings. */
  section > h2, .block h2, .collab-strip h2 {
    font-family: var(--body);
    font-weight: var(--w-semi);
    font-size: var(--fs-12);
    letter-spacing: var(--tr-caps);
    text-transform: uppercase;
    color: var(--mid);
  }

  /* True Newsreader italic for in-headline emphasis — real italic
     letterforms (not oblique), pinned to the display optical-size cut so a
     keyword set in <em> reads as intentional editorial contrast. */
  h1 em, h2 em, h3 em, h4 em, .hero h1 em {
    font-style: italic;
    font-family: var(--display);
    font-weight: inherit;
    font-variation-settings: "opsz" 72;
  }

  /* ── FIGURES ──────────────────────────────────────────────────────
     Editorial numerals: running prose gets oldstyle, proportional figures
     that sit *in* the line like a magazine (Geist falls back to lining if
     it lacks the axis — harmless). Data/UI overrides back to tabular
     lining with a slashed zero so columns align and 0/O never confuse. */
  body { font-variant-numeric: proportional-nums oldstyle-nums; }
  .mono, code, kbd, table td, table th,
  .label, .flag-board dd, .num, [class*="stat"] {
    font-variant-numeric: tabular-nums lining-nums slashed-zero;
    font-feature-settings: "zero" 1;
  }
}

@layer utilities {
  /* skip-link — hidden off-screen until keyboard-focused, lets a
     keyboard/screen-reader user jump straight past the repeated nav
     into <main id="main"> instead of tabbing through it on every page */
  .skip-link {
    position: absolute;
    top: -48px;
    left: 12px;
    z-index: 1000;
    padding: 10px 18px;
    background: var(--ink);
    color: var(--paper);
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    text-decoration: none;
    border-radius: 4px;
    transition: top .15s var(--ease);
  }
  .skip-link:focus { top: 12px; }

  /* label utility — mono demoted to figures/IDs; eyebrows, scope pills,
     meta labels and captions moved to Geist. One spec now, on tokens. */
  .label {
    font-family: var(--body);
    font-size: var(--fs-11);
    font-weight: var(--w-med);
    letter-spacing: var(--tr-caps);
    text-transform: uppercase;
    color: var(--mid);
  }

  /* eyebrow utility — the mono voice (hero eyebrow, back-links, screen IDs).
     One spec replaces the .12em / .07em / .06em split that made this role
     render three different ways across the old files. .persona-role
     (case-study.css) is this exact spec plus a color/margin override —
     composed here instead of re-declared, 2026-08-30. */
  .eyebrow, .persona-role {
    font-family: var(--mono);
    font-size: var(--fs-11);
    font-weight: var(--w-med);
    letter-spacing: var(--tr-caps-wide);
    text-transform: uppercase;
    color: var(--mid);
  }

  /* motion / reveal */
  @media (prefers-reduced-motion: no-preference) {
    .rise { opacity: 0; transform: translateY(14px); animation: rise .7s var(--ease) forwards; }
    .rise.d1 { animation-delay: .08s; }
    .rise.d2 { animation-delay: .16s; }
    .rise.d3 { animation-delay: .26s; }
    @keyframes rise { to { opacity: 1; transform: none; } }

    .rv, .cs-reveal { opacity: 0; transform: translateY(16px);
      transition: opacity .6s var(--ease), transform .6s var(--ease); }
    .rv.in, .cs-reveal.in { opacity: 1; transform: none; }
    .rv-stagger.in { transition-delay: var(--d, 0s); }
  }
}

@layer components {
  /* ─── NAV ──────────────────────────────────────────────── */
  nav {
    position: sticky; top: 0; z-index: 100;
    display: flex; align-items: center; justify-content: space-between;
    padding: 18px var(--pad);
    background: rgba(242,241,237,0.92);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--line);
  }
  .nav-name {
    font-family: var(--display);
    font-weight: var(--w-serif-strong);
    font-size: var(--fs-20);
    letter-spacing: var(--tr-snug);
    text-decoration: none;
    text-transform: none;
  }
  .nav-name span { color: var(--rosa); }
  .nav-links { display: flex; gap: 28px; list-style: none; }
  .nav-links a {
    position: relative;
    font-family: var(--body);
    font-size: var(--fs-13);
    font-weight: var(--w-med);
    letter-spacing: 0.01em;
    text-transform: none;
    color: var(--mid);
    text-decoration: none;
    transition: color .15s;
  }
  .nav-links a:hover, .nav-links a:focus-visible { color: var(--ink); }
  .nav-links a.is-active { color: var(--ink); font-weight: 600; }
  .nav-links a::after {
    content: ''; position: absolute; left: 0; bottom: -4px;
    width: 100%; height: 1.5px; background: var(--ink);
    transform: scaleX(0); transform-origin: left;
    transition: transform .22s var(--ease);
  }
  .nav-links a:hover::after, .nav-links a:focus-visible::after { transform: scaleX(1); }

  /* ─── CTA — canonical text-link action ─────────────────── */
  .cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 12px;
    width: fit-content;
    max-width: 100%;
    font-family: var(--body);
    font-size: var(--fs-11);
    font-weight: 600;
    font-style: normal;
    line-height: 1.3;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--ink);
    text-decoration: none;
    padding-bottom: 8px;
    border-bottom: 1.5px solid var(--rosa);
  }
  .cta span {
    color: var(--rosa);
    line-height: 1;
    transition: transform .25s var(--ease, ease);
  }
  .cta:hover span { transform: translateX(3px); }

  .full-back-cta {
    padding: 28px var(--pad) clamp(40px, 6vh, 64px);
    text-align: center;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
  }

  /* ─── NAV — hamburger toggle (mobile) ───────────────────── */
  .nav-toggle {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 32px; height: 32px;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
  }
  .nav-toggle span {
    display: block;
    width: 100%; height: 2px;
    background: var(--ink);
    transition: transform .25s var(--ease), opacity .2s;
  }
  nav.nav-open .nav-toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  nav.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
  nav.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

  @media (max-width: 760px) {
    .nav-toggle { display: flex; }
    .nav-links {
      position: absolute;
      top: 100%; left: 0; right: 0;
      flex-direction: column;
      align-items: flex-start;
      gap: 2px;
      padding: 8px var(--pad) 20px;
      margin: 0;
      background: var(--paper);
      border-bottom: 1px solid var(--line);
      display: none;
    }
    nav.nav-open .nav-links { display: flex; }
    .nav-links li { width: 100%; }
    .nav-links a { display: block; padding: 12px 0; }
    .nav-links a::after { display: none; }
  }

  /* ─── SECTION SCAFFOLD ───────────────────────────────────── */
  /* Section strip. Shell pages + case-study group strips share the same
     CTA-like Geist label voice. Case-study .sdiv/.section-divider use the
     same text treatment in css/screens.css with tighter local padding. */
  .sec-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 30px var(--pad) 27px;
    background: transparent;
    border-bottom: 1px solid var(--line);
  }
  .sec-head h2 {
    /* Type spec matches .cta (2026-09-07, Rod's request) — family/size/weight/
       line-height/letter-spacing only; color stays --rosa, not .cta's --ink. */
    font-family: var(--body);
    font-size: var(--fs-11);
    font-weight: 600;
    font-style: normal;
    line-height: 1.3;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--rosa); /* not var(--accent) — Relay/Meridian's .wf-embed locally
      redefines --accent for their own product-UI theming; --rosa is the single,
      never-locally-shadowed global accent token. See docs/decisions.md 2026-08-30. */
  }
  .sec-head .label {
    font-family: var(--mono);
    font-size: var(--fs-11);
    font-weight: var(--w-med);
    letter-spacing: var(--tr-caps-wide);
    text-transform: none;
    color: var(--mid);
    font-variant-numeric: tabular-nums;
    text-align: right;
  }

  /* ─── PLACEHOLDER — shared shape for .flag-media/.media-placeholder/
     .specimen-box: dashed --line border, --paper-2 fill, centered content.
     Each keeps its own aspect-ratio/padding/margins — only the genuinely
     identical properties live here. Two other "placeholder-shaped" rules
     were checked and deliberately NOT folded in: .hero-stage uses literal
     pre-WCAG-fix colors (not these tokens) preserved on purpose, and
     .storyboard-box/.application-box use a different border treatment
     (none, and bottom-only solid) that isn't actually the same component.
     See design-system-inventory.md and docs/decisions.md 2026-08-30. */
  .flag-media, .media-placeholder, .specimen-box {
    border: 1px dashed var(--line);
    background: var(--paper-2);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
  }

  /* ─── HAIRLINE GRID — shared shape for .flagships/.how/.principles ────
     Equal columns, border-left divider between items, collapse to one
     column with border-top under 900px. Same grid at three different
     column counts (2/3/3) — one shared rule instead of three copies.
     Column count is declared HERE too, not split off to pages.css/
     case-study.css: those live in @layer templates, which outranks this
     @layer components regardless of media-query match, so a templates-
     layer desktop column-count would have silently beaten this layer's
     mobile collapse at every width — caught in verification, 2026-08-30,
     see docs/decisions.md. Keeping both declarations in one layer is what
     makes the media query actually take effect. */
  .flagships, .how, .principles { display: grid; }
  .flagships { grid-template-columns: repeat(2, 1fr); }
  .how, .principles { grid-template-columns: repeat(3, 1fr); }
  .flag + .flag, .how-col + .how-col, .principle + .principle {
    border-left: 1px solid var(--line);
  }
  @media (max-width: 900px) {
    .flagships, .how, .principles { grid-template-columns: 1fr; }
    .flag + .flag, .how-col + .how-col, .principle + .principle {
      border-left: none;
      border-top: 1px solid var(--line);
    }
  }

  /* ─── FOOTER ─────────────────────────────────────────────── */
  footer {
    padding: clamp(56px, 9vh, 110px) var(--pad) 40px;
  }
  footer .big {
    position: relative;
    font-family: var(--display);
    font-weight: var(--w-serif);
    font-size: var(--fs-d3);
    line-height: var(--lh-solid);
    text-transform: none;
    letter-spacing: var(--tr-tight);
    text-decoration: none;
    display: inline-block;
    transition: color .2s;
  }
  footer .big::after {
    content: ''; position: absolute; left: 0; bottom: -6px;
    width: 100%; height: 4px; background: var(--rosa);
    transform: scaleX(0); transform-origin: left;
    transition: transform .3s var(--ease);
  }
  footer .big:hover,
  footer .big:focus-visible {
    color: var(--rosa);
    -webkit-text-fill-color: var(--rosa);
  }
  footer .big:hover::after,
  footer .big:focus-visible::after { transform: scaleX(1); }
  .foot-meta {
    margin-top: 48px;
    display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
  }
  .foot-meta a { text-decoration: none; }
  .foot-meta a:hover { color: var(--rosa); }
}

/* ─── migrated from revamp.css (Phase 4 completion) — deliberately UNLAYERED
   so it wins over the layered `.rv`/`.cs-reveal` opacity:0 initial state in
   @layer base above, without needing to match its specificity. ───
   B5 · reveal animations leaving content invisible — belt (CSS) and braces
   (js/site.js failsafe). If JS never runs, content is visible. */
.no-js .rv, .no-js .cs-reveal { opacity: 1 !important; transform: none !important; }
@media (prefers-reduced-motion: no-preference) {
  .rv, .cs-reveal { transition-delay: 0s; }
}

/* ═══════════════════════════════════════════════════════════════════════
   PAGE TRANSITIONS  ·  TRIAL — added 2026-08-18
   Cross-document View Transitions for page-to-page navigation.
   Pure CSS, progressive enhancement: unsupported browsers just hard-cut
   as before. Honors prefers-reduced-motion (whole block is gated).

   ░░ TO UNDO: delete everything from this banner to the END-PAGE-TRANSITIONS
   ░░ marker below. Nothing else in the codebase depends on it. ░░
   ═══════════════════════════════════════════════════════════════════════ */

/* Opt every same-origin navigation into a transition. Harmless no-op in
   browsers without support. */
@view-transition { navigation: auto; }

@media (prefers-reduced-motion: no-preference) {
  /* Default site-wide cross-fade + slight vertical drift. */
  ::view-transition-old(root) {
    animation: pt-fade-out .26s var(--ease, ease) both;
  }
  ::view-transition-new(root) {
    animation: pt-fade-in .34s var(--ease, ease) both;
  }
  @keyframes pt-fade-out { to   { opacity: 0; transform: translateY(-6px); } }
  @keyframes pt-fade-in  { from { opacity: 0; transform: translateY(8px);  } }
}
/* ═══════════ END-PAGE-TRANSITIONS ═══════════ */
