/**
 * Solid System — theme stylesheet.
 *
 * The files in assets/css/tokens/ are copied BYTE-FOR-BYTE from the design bundle and
 * are never edited — that is what guarantees no brand value drifts during the port.
 * Anything this site needs to change about them is overridden here, deliberately and
 * in the open, with a comment saying why.
 *
 * Ported from styles/globals.css in the Next.js reference implementation. Where a rule
 * differs from that file, the difference is a WordPress fact and is commented as one.
 */

/* ── Font binding — self-hosted families into the token names ─────────────── */

:root {
  /**
   * theme.json declares the @font-face rules from assets/fonts/ and WordPress prints
   * them. The token names still resolve to real families here, so a component that
   * reads --font-display keeps working whether it is rendered by a block, a pattern
   * or the editor canvas.
   *
   * SUBSTITUTION, carried from the design system: 4.2 names Archivo, Söhne or Neue
   * Haas Grotesk Display. Archivo is the one with an open licence. If Söhne is
   * licensed later (7.1 lists "licensed web fonts, perpetual" as a procurement item),
   * swap the @font-face src in theme.json and the family name here — nothing else
   * reads a family name.
   */
  --font-display: Archivo, "Helvetica Neue", arial, sans-serif;
  --font-body: "IBM Plex Sans", "Helvetica Neue", arial, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, menlo, monospace;

  /**
   * ACCESSIBILITY OVERRIDE — pending TEXT only. See ADR-0012.
   *
   * --ss-pending is #8A8F98, which scores 3.25:1 on white and 3.06:1 on paper. WCAG 2.1
   * AA requires 4.5:1 for normal text, and the brief mandates AA (5, criterion 7) as
   * firmly as it mandates the palette. The two genuinely conflict.
   *
   * This darkens only the SEMANTIC ALIAS used for text — to 4.99:1 on white and 4.70:1
   * on paper. The base token --ss-pending is untouched and still drives borders and
   * rules, where the 3:1 minimum applies and the original value passes.
   *
   * The design intent survives: a held figure still reads as clearly muted against
   * --ss-steel (6.00:1), and is still nowhere near blue. Flagged for the design system
   * to confirm — docs/OPEN-ITEMS.md.
   */

  /* stylelint-disable-next-line color-no-hex -- defines a token, does not consume one */
  --text-pending: #6a7079;
}

/* ── Reset ────────────────────────────────────────────────────────────────── */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

body {
  margin: 0;
  background: var(--surface-base);
  color: var(--text-body);
  font-family: var(--font-body);
  font-size: var(--type-body-size);
  line-height: var(--type-body-line);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizelegibility;
}

/**
 * WordPress emits its own heading margins through global styles. Zeroing them here
 * keeps the 8px rhythm owned by --block-gap and the spacing scale, which is what
 * theme.json exposes to editors — two competing margin systems would let a page look
 * right in the editor and wrong on the front end.
 */
h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-display);
  color: var(--text-heading);
  margin: 0;
  text-wrap: pretty;
}

h1 {
  font-size: var(--type-h1-size);
  line-height: var(--type-h1-line);
}

h2 {
  font-size: var(--type-h2-size);
  line-height: var(--type-h2-line);
}

h3 {
  font-size: var(--type-h3-size);
  line-height: var(--type-h3-line);
}

h4 {
  font-size: var(--type-h4-size);
  line-height: var(--type-h4-line);
}

p {
  margin: 0;
  max-width: var(--measure-prose);
}

img,
svg,
video {
  max-width: 100%;
  height: auto;
}

a {
  color: var(--ss-blue);
  text-decoration: none;
}

/* Links gain a 1px underline on hover — colour change, never an opacity fade. */
a:hover {
  color: var(--ss-blue-hover);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

/**
 * A link sitting inside a block of text is underlined at rest, not only on hover.
 *
 * WCAG 2.1 AA (1.4.1, Use of Colour) requires a non-colour cue where a link is
 * surrounded by body text, and --ss-blue against --ss-ink measures 2.87:1 — below the
 * 3:1 that would let colour alone carry it. The design system's hover-only underline
 * still applies to standalone links: navigation, buttons and card links, where position
 * and context already identify them.
 */
p a,
li a,
dd a,
figcaption a,
address a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

/* ── Focus — 2px blue outline, 2px offset, on every interactive element ───── */

:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

/* ── Layout primitives ────────────────────────────────────────────────────── */

.container {
  max-width: var(--layout-max);
  margin-inline: auto;
  padding-inline: var(--layout-gutter);
}

.section {
  padding-block: var(--section-pad-y);
}

/* Alternating section background. Depth is a 1px rule and a paper ground, nothing else. */
.section--paper {
  background: var(--surface-section);
  border-top: var(--hairline);
  border-bottom: var(--hairline);
}

.prose {
  max-width: var(--measure-prose);
}

/**
 * WordPress alignment classes, bound to the same layout tokens so a block pattern and
 * a hand-written template produce the same measure. theme.json's contentSize is the
 * prose measure and wideSize the 1440px maximum; these two rules are what make that
 * real for .alignwide / .alignfull inside a constrained group.
 */
.wp-site-blocks > .alignfull,
.wp-block-group.alignfull {
  margin-inline: 0;
  max-width: none;
}

.wp-block-group.alignwide {
  max-width: var(--layout-max);
  margin-inline: auto;
}

/* ── The typographic signature ────────────────────────────────────────────── */

/**
 * Detail references (D.02), material designations (C140, Z200, Z275) and values
 * (λ 0.138, U 0.43) are ALWAYS mono, letter-spaced +0.02em. Across a site built on
 * nine numbered details this repetition is the brand's fingerprint — the design system
 * calls it "more recognisable than the logo at page scale".
 */
.data {
  font-family: var(--font-mono);
  font-size: var(--type-data-size);
  line-height: var(--type-data-line);
  letter-spacing: var(--tracking-mono);
  color: var(--text-data);
  font-variant-numeric: tabular-nums;
}

.eyebrow {
  font-family: var(--font-mono);
  font-size: var(--type-eyebrow-size);
  line-height: var(--type-eyebrow-line);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--text-secondary);
}

/* Key figures — 66%, U 0.21 — set at 72px in Archivo. */
.figure {
  font-family: var(--font-display);
  font-size: var(--type-figure-size);
  line-height: var(--type-figure-line);
  font-weight: var(--weight-bold);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.caption {
  font-family: var(--font-mono);
  font-size: var(--type-caption-size);
  line-height: var(--type-caption-line);
  letter-spacing: var(--tracking-mono);
  color: var(--text-caption);
}

/* ── Motion — page entry only, once, 12px over 320ms ──────────────────────── */

.enter {
  animation: enter-up var(--motion-enter-duration) var(--ease-standard) both;
}

@keyframes enter-up {
  from {
    opacity: 0;
    transform: translateY(var(--motion-enter-offset));
  }

  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .enter {
    animation: none;
  }
}

/* ── Accessibility ────────────────────────────────────────────────────────── */

.visually-hidden,

/* WordPress core and many plugins emit .screen-reader-text; give it the same treatment
   rather than letting a second, subtly different clip rule into the page. */
.screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: 100;
  padding: var(--space-3) var(--space-5);
  background: var(--surface-base);
  border: var(--hairline);
  transform: translateY(-200%);
}

.skip-link:focus {
  transform: none;
}

/**
 * The admin bar is fixed at the top for logged-in editors and overlaps a sticky
 * header. Only ever visible to staff, but it makes the site editor's preview lie
 * about where the header sits.
 */
body.admin-bar .ss-header--sticky {
  top: 32px;
}

@media (width <= 782px) {
  body.admin-bar .ss-header--sticky {
    top: 46px;
  }
}

/* ── Responsive — 360 / 768 / 1024 / 1440 / 1920 (criterion 1) ────────────── */

@media (width <= 1024px) {
  :root {
    --layout-gutter: var(--space-7);
    --section-pad-y: var(--space-10);
    --type-h1-size: 44px;
    --type-h1-line: 48px;
    --type-h2-size: 32px;
    --type-h2-line: 38px;
    --type-figure-size: 56px;
    --type-figure-line: 56px;
  }
}

@media (width <= 768px) {
  :root {
    --layout-gutter: var(--layout-gutter-mobile);
    --section-pad-y: var(--space-9);
    --type-h1-size: 34px;
    --type-h1-line: 39px;
    --type-h2-size: 26px;
    --type-h2-line: 32px;
    --type-h3-size: 21px;
    --type-h3-line: 28px;
    --type-body-size: 17px;
    --type-body-line: 27px;
    --type-figure-size: 48px;
    --type-figure-line: 48px;
  }

  /* The sticky mobile contact bar is the only fixed element on small screens. */
  body {
    padding-bottom: 56px;
  }
}

/**
 * Grid and flex children default to min-width: auto, which lets a wide table force its
 * column open and scroll the whole page sideways at 360px. That defect shipped once —
 * see STATUS.md, "Page scrolled sideways at 360px". The scroll wrapper only works if
 * the track is allowed to shrink.
 */
.wp-block-group > *,
.wp-block-columns > .wp-block-column {
  min-width: 0;
}
