/* ==========================================================================
   BASE — reset, typography, layout primitives.
   Contains no literal colours, fonts, radii or shadows. Only tokens.
   ========================================================================== */

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

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--size-body);
  line-height: var(--leading-body);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

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

a { color: inherit; }

h1 { font-size: var(--size-h1); }
h2 { font-size: var(--size-h2); }
h3 { font-size: var(--size-h3); }

h1, h2, h3, h4 {
  margin: 0;
  color: var(--heading);
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  line-height: var(--leading-heading);
  text-wrap: balance;
}

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

::selection { background: var(--accent); color: var(--accent-on); }

:focus-visible {
  outline: 2px solid var(--accent-text);
  outline-offset: 2px;
}


/* ---------------------------------------------------------------- LAYOUT */

/* Three wrappers on every block, header and footer included:

     <section class="section">            vertical rhythm
       <div class="padding-global">       keeps content off the viewport edge
         <div class="container">          caps + centres; the ONLY max-width

   At 1440px: .padding-global pads 72px, .container runs 80 → 1360, content
   sits 100 → 1340. --frame-x lands on 80 either side of the ~1422px cap. */

.padding-global { padding-inline: var(--pad-x); }

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);   /* sets the content inset from the column edge */
}

.section {
  position: relative;              /* anchors anything positioned inside it */
  padding-block: var(--section-pad);
}

/* Frame colours. Declared on the elements that draw them so they resolve
   against whatever theme and band the element sits in. */
.section, .footer, .divider { --frame-line: var(--line); --mark: var(--ink); }
.section--inverse { --frame-line: color-mix(in srgb, var(--ink-inverse) 16%, transparent); }

/* Rails (1px verticals at the content-column edges) were removed on request,
   24 Sep. The gutter stays: it still sets the content's inset. To restore,
   draw them with .section/.footer ::before/::after at left/right: var(--frame-x). */

/* Section boundary: full-width hairline, a 6px square where it crosses a rail.
   Place <div class="divider" aria-hidden="true"></div> between sections. */
.divider, .footer__crossing {
  position: relative; z-index: 2; pointer-events: none;
}
.divider { height: 1px; background: var(--frame-line); }
.footer__crossing { position: absolute; top: -0.5px; left: 0; right: 0; height: 0; }  /* centred on the border-top */
.divider::before, .divider::after,
.footer__crossing::before, .footer__crossing::after {
  content: ''; position: absolute; top: 0; width: 6px; height: 6px; background: var(--mark);
}
.divider::before, .footer__crossing::before { left:  calc(var(--frame-x) + 0.5px); transform: translate(-50%, -50%); }
.divider::after,  .footer__crossing::after  { right: calc(var(--frame-x) + 0.5px); transform: translate(50%, -50%); }
.divider::before, .divider::after { top: 0.5px; }

/* The footer's boundary squares come from .footer__crossing, a real element,
   so its pseudo-elements stay free. */
.footer { position: relative; padding-top: 40px; border-top: var(--border-w) solid var(--frame-line); }

/* Giveback: meet the column edge instead of sitting --gutter inside it.
   Never bleed with 100vw — vw includes the scrollbar. */
.bleed { margin-inline: calc(-1 * var(--bleed)); width: calc(100% + 2 * var(--bleed)); }

/* The one breakpoint that matters. The gutter goes too — on a phone it only
   costs measure; --bleed goes to 0 in tokens.css at the same width. */
@media (max-width: 991px) {
  .footer__crossing, .divider::before, .divider::after { display: none; }
  .container { padding-inline: 0; }
}

/* Band rhythm. Two inverse sections must never touch — alternate these. */
.section--ground  { background: var(--ground); }
.section--band    { background: var(--ground-2); }
.section--inverse {
  background: var(--ground-inverse);
  color: var(--ink-inverse);
}
.section--inverse h1, .section--inverse h2, .section--inverse h3 { color: var(--ink-inverse); }

/* Section heading: headline left, lede right, bottom-aligned. */
.section-head {
  display: grid;
  grid-template-columns: 1.35fr 0.65fr;
  gap: var(--space-9);
  align-items: end;
  margin-bottom: var(--space-8);
}
.section-head h2 { font-size: var(--size-h2); letter-spacing: var(--display-tracking); }
.section-head p  { color: var(--ink-muted); font-size: var(--size-body); }
.section--inverse .section-head p { color: var(--ink-inverse-muted); }

@media (max-width: 860px) {
  .section-head { grid-template-columns: 1fr; gap: var(--space-4); }
}


/* ---------------------------------------------------------------- TEXT */

.label {
  font-family: var(--font-label);
  font-size: var(--size-label);
  font-weight: var(--label-weight);
  letter-spacing: var(--label-tracking);
  text-transform: var(--label-transform);
  color: var(--ink-muted);
}
.section--inverse .label { color: var(--ink-inverse-muted); }

.display {
  font-size: var(--size-display);
  letter-spacing: var(--display-tracking);
  line-height: var(--leading-display);
}

.lede { font-size: var(--size-body-lg); color: var(--ink-muted); }
.small { font-size: var(--size-small); }
/* Body paragraphs are 16px (29 Sep): a paragraph or text link set .small
   inside a section reads at body size; .small stays small elsewhere. */
.section p.small, .section a.small { font-size: var(--size-body); }
.mono { font-family: var(--font-mono); }

/* Emphasis in a headline: a drawn band, never a change of face or slant. */
.mark {
  background: linear-gradient(var(--accent-wash), var(--accent-wash)) 0 0.30em / 100% 0.84em no-repeat;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
  padding-inline: 0.06em 0.1em;
  mix-blend-mode: multiply;
}

/* Anything not yet written or not yet cleared. Deliberately conspicuous:
   comps get screenshotted. */
.todo {
  background: repeating-linear-gradient(
    -45deg, transparent, transparent 5px,
    color-mix(in srgb, var(--risk) 14%, transparent) 5px,
    color-mix(in srgb, var(--risk) 14%, transparent) 10px);
  outline: 1px dashed var(--risk);
  color: var(--risk);
  font-family: var(--font-label);
  font-size: var(--size-label);
  letter-spacing: var(--label-tracking);
  text-transform: uppercase;
  padding: 2px 6px;
  display: inline-block;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}


/* ==========================================================================
   RASTER TEXT
   --------------------------------------------------------------------------
   Rebuilds the FK Raster effect — letterforms rendered as a halftone dot grid —
   without licensing a foundry face. A dot pattern is painted behind the glyphs
   and clipped to them, so the text stays live: selectable, searchable, and read
   correctly by assistive technology.

   DISPLAY SIZES ONLY. The dot grid eats perceived contrast, so anything under
   about 40px turns to mush. There is a guard below that switches it off.
   ========================================================================== */

.raster { color: var(--heading); }

@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .raster {
    background-image: radial-gradient(var(--heading) 40%, transparent 44%);
    background-size: var(--raster-cell) var(--raster-cell);
    background-position: 0 0;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }

  /* The "blended" variant: solid at the start, dissolving into the raster.
     Two layers — a hard-stopped wipe over the dot grid. */
  .raster--blend {
    background-image:
      linear-gradient(95deg, var(--heading) 0 22%, transparent 62%),
      radial-gradient(var(--heading) 40%, transparent 44%);
    background-size: 100% 100%, var(--raster-cell) var(--raster-cell);
  }

  /* Below display size the effect stops being legible, so it stops being applied. */
  @media (max-width: 640px) {
    .raster, .raster--blend {
      background-image: none;
      -webkit-background-clip: border-box;
      background-clip: border-box;
      color: var(--heading);
    }
  }
}

/* A display line set in the stylized serif. */
.serif { font-family: var(--font-serif); font-weight: 400; }

/* Icons: Lucide, from the assets/icons/lucide.svg sprite
   (<svg class="icon"><use href="assets/icons/lucide.svg#name"/></svg>).
   The sprite carries no stroke attributes, so this rule owns them: current
   text colour, and square caps with mitred joins to match the boxy controls.
   --icon-size / --icon-stroke tune one use without a new class. */
.icon {
  flex: none;
  display: inline-block;
  width: var(--icon-size, 1em);
  height: var(--icon-size, 1em);
  vertical-align: -0.125em;
  fill: none;
  stroke: currentColor;
  stroke-width: var(--icon-stroke, 1.75);
  stroke-linecap: square;
  stroke-linejoin: miter;
  overflow: visible;
}
