/* ============================================================
   Service Works Plus design tokens
   Source of truth: docs/notes/design-direction.md (approved 2026-06-12)
   Every page on this site imports this file first.
   ============================================================ */

/* ============================================================
   Self-hosted fonts (2026-07-22)
   Replaces the Google Fonts stylesheet, which cost a render-blocking
   round trip to fonts.googleapis.com before the font files could even be
   discovered on fonts.gstatic.com. Same 63 KB of woff2, now first-party,
   discovered during this stylesheet's parse, and one fewer blocking request.

   Latin subsets only, matching the unicode-range Google served. Both
   families are SIL Open Font License 1.1; see fonts/OFL-NOTICE.txt.

   Archivo ships as a single variable file covering 400 to 700, which is
   what the design direction asks for (weights 400/500/600/700, one file).
   ============================================================ */

@font-face {
  font-family: "Archivo";
  src: url("../fonts/archivo-var-latin.woff2") format("woff2-variations");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/ibm-plex-mono-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/ibm-plex-mono-500-latin.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  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;
}

/* Metric-matched fallback for the swap window.
   font-display: swap guarantees text is never invisible, but it also
   guarantees a reflow when Archivo arrives unless the fallback occupies the
   same space. These numbers are measured, not guessed: Archivo and Arial were
   rendered at 100px in canvas and compared, giving a width ratio of 99.34%,
   an ascent of 88 and a descent of 21 per 100px em. The overrides are divided
   by the size-adjust factor, per the standard fallback recipe.

   Caveat: this assumes the fallback resolves to Arial or Helvetica, which are
   metric-compatible. Android devices resolving to Roboto will differ, and the
   remaining shift there is small and unavoidable without shipping a second
   fallback set. Applies only to headings and body copy, where a shift is most
   visible; the mono face is used for small labels only and is left alone. */
@font-face {
  font-family: "Archivo Fallback";
  src: local("Arial"), local("Helvetica Neue"), local("Helvetica");
  size-adjust: 99.34%;
  ascent-override: 88.58%;
  descent-override: 21.14%;
  line-gap-override: 0%;
}

:root {
  /* ---- Color ---- */
  --ink: #1a1c1e;            /* headings/body on light; dark-band base */
  --surface-dark: #23262a;   /* panels inside dark bands */
  --paper: #f6f5f2;          /* page background */
  --surface: #ffffff;        /* cards on paper */
  --line: #ddd9d2;           /* hairline rules, photo frames */
  --line-dark: #2e3236;      /* hairlines on dark bands */
  --text-secondary: #5b6066; /* secondary text on light (AA on paper) */
  --text-inverse: #f3f2ef;   /* body text on dark bands */
  --accent: #e8842d;         /* logo orange: UI marks, dark-surface text. <=10% of viewport */
  --accent-deep: #a85410;    /* orange TEXT on light surfaces (AA). Never white on orange. */
  --success: #2e7d32;
  --error: #b3261e;

  /* ---- Type ---- */
  --font-sans: "Archivo", "Archivo Fallback", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", monospace;

  /* Scale: mobile -> desktop via clamp (design-direction.md §2) */
  --fs-display: clamp(2.5rem, 1.55rem + 4vw, 4rem);      /* 40 -> 64 */
  --fs-h1: clamp(2.25rem, 1.4rem + 3.6vw, 3.5rem);       /* 36 -> 56 */
  --fs-h2: clamp(1.75rem, 1.45rem + 1.3vw, 2.5rem);      /* 28 -> 40 */
  --fs-h3: clamp(1.25rem, 1.16rem + 0.4vw, 1.625rem);    /* 20 -> 26 */
  --fs-body-lg: clamp(1.125rem, 1.08rem + 0.2vw, 1.25rem);
  --fs-body: clamp(1rem, 0.97rem + 0.15vw, 1.125rem);
  --fs-label: clamp(0.8125rem, 0.8rem + 0.05vw, 0.875rem);
  --fs-caption: 0.8125rem;

  --lh-tight: 1.08;
  --lh-heading: 1.15;
  --lh-body: 1.6;

  /* ---- Space (8px base) ---- */
  --s-1: 4px;
  --s-2: 8px;
  --s-3: 12px;
  --s-4: 16px;
  --s-5: 24px;
  --s-6: 32px;
  --s-7: 48px;
  --s-8: 64px;
  --s-9: 96px;
  --s-10: 128px;

  /* Section rhythm: 64 mobile -> 96 desktop */
  --section-pad: clamp(var(--s-8), 5vw + 32px, var(--s-9));

  /* ---- Layout ---- */
  --container: 1120px;
  --gutter: clamp(24px, 4vw, 40px);

  /* ---- Shape & misc ---- */
  --radius: 2px;
  --radius-badge: 10px;        /* logo badge in the dark bands */
  --radius-panel: 6px;         /* frosted content panels, portfolio photo frames */
  --radius-panel-mobile: 12px; /* softer panel corners on phones */
  --photo-max: 480px;          /* HARD CEILING: photos never render wider (§5) */
  --tap-min: 44px;
  --transition: 180ms ease-out;

  /* Sticky header height. Used by scroll-padding-top and the mobile hero
     height calculation, so it must stay in sync with .site-header min-height. */
  --header-h: 72px;
  /* Mobile sticky CTA bar height:
     --s-3 top + --tap-min button + --s-3 bottom + 1px border-top = 69px.
     Must match .mobile-cta-bar in main.css, or page content is trapped
     underneath it. Labels in that bar are nowrap so it cannot grow silently. */
  --cta-bar-h: 69px;
}
