/* ═══════════════════════════════════════════════════════════════════════════
   303 Analytics — the only stylesheet.

   Derived from the Modernist design system
   (design/_ds/modernist-b6be1359-.../styles.css) and the design reference
   (design/303 Analytics Site v2.dc.html). Only the tokens and component
   classes this page actually uses are carried over.

   Design rules that are non-negotiable here, per the handoff README:
     · border-radius is 0 everywhere
     · rules are 2px solid, never hairlines
     · no shadows — nothing floats
     · spruce #14483f is the only accent; gold appears exactly once
     · labels are flush left, including inside buttons
   ═══════════════════════════════════════════════════════════════════════ */

/* — fonts —————————————————————————————————————————————————————————————————
   Archivo variable (400–900) self-hosted. One file covers both roles the
   design uses: 400 body and 800 display. */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 900;
  font-stretch: 100%;
  font-display: swap;
  src: url('fonts/archivo-var-latin.woff2') format('woff2');
  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: 'Archivo';
  font-style: normal;
  font-weight: 400 900;
  font-stretch: 100%;
  font-display: swap;
  src: url('fonts/archivo-var-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* — tokens ————————————————————————————————————————————————————————————————
   The accent ramp is baked static. In the design file these were injected at
   runtime by applyAccent() as color-mix(in oklab, …); the design system's own
   stylesheet ships a red accent, so without this the page renders red. The
   hex values below are those color-mix results computed exactly. */
:root {
  --color-bg: #f3f2f2;
  --color-text: #201e1d;
  --color-ink: #201e1d;              /* header + footer bars, submit button */
  --color-divider: rgba(32, 30, 29, 0.4);
  /* The logo's secondary gold, nudged four steps darker. At the design's
     #c47f1f this clears only 2.94:1 on the light ground, just under the
     3.0 large-text floor; #c07d1f reaches 3.03 and is indistinguishable.
     The logo files keep the original gold: the lockup on this page uses
     #e0a44a on the ink bar at 7.57:1, and brand marks are exempt from
     contrast requirements regardless. */
  --color-gold: #c07d1f;             /* used on exactly one element */

  --color-accent: #14483f;           /* deep spruce — matches the logo */
  --color-accent-200: #c9d4d1;       /* link hover on spruce */
  --color-accent-400: #75908a;
  --color-accent-600: #0e3932;       /* pressed */
  --color-accent-700: #082923;       /* accent text at paragraph size */

  --font-heading: 'Archivo', system-ui, sans-serif;
  --font-body: 'Archivo', system-ui, sans-serif;
  --font-heading-weight: 800;

  --radius: 0;

  /* The single measurement that holds the whole page on one vertical
     alignment. Used as left/right padding on every full-width section. */
  --gutter: clamp(20px, 5vw, 64px);
  --rule: 2px solid var(--color-divider);
}

/* — base ——————————————————————————————————————————————————————————————— */
*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: clamp(16px, 1.1vw, 18px);
  line-height: 1.55;
  font-weight: 400;
  min-height: 100vh;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  margin: 0;
}

/* Every paragraph in the design carried an explicit margin. Zero the base and
   let the classes below state their own, so nothing inherits a UA default. */
p { margin: 0; }

img { display: block; max-width: 100%; }

a { color: var(--color-accent); text-underline-offset: 3px; }
a:hover { color: var(--color-accent-700); }

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* Sections that run as a spruce field: type goes white, and so does the focus
   ring — the accent-colored ring from the design system would be invisible
   against its own background. */
/* Text links only. Without :not(.btn) these win on specificity (0,1,1 beats
   .btn-hero's 0,1,0) and repaint the hero button's label white on its own
   white background, making it vanish. */
.on-accent a:not(.btn) { color: #fff; }
.on-accent a:not(.btn):hover { color: var(--color-accent-200); }
.on-accent :focus-visible { outline-color: #fff; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* — shared type roles —————————————————————————————————————————————————— */
.kicker {
  font-size: clamp(10px, 1.4vw, 12px);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin: 0 0 16px;
}
.kicker--muted { opacity: 0.55; }
.kicker--accent { color: var(--color-accent-700); }

/* Kickers on the spruce fields track wider and sit at 85% rather than 55% —
   the looser tracking is what makes them read as poster chrome. */
.kicker--field {
  letter-spacing: 0.18em;
  opacity: 0.85;
}

.section-title {
  font-size: clamp(30px, 4.6vw, 48px);
  letter-spacing: -0.03em;
}

/* Display-weight line in the accent, used to close a block. */
.callout {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: clamp(19px, 2.1vw, 24px);
  color: var(--color-accent);
  margin: 0;
}

/* — buttons ———————————————————————————————————————————————————————————————
   Labels are flush left: a button wider than its label starts the text at the
   left padding edge, never centered. That is a system rule, not a preference. */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  cursor: pointer;
  text-decoration: none;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  line-height: 1.2;
  border: 1px solid transparent;
  border-radius: var(--radius);
}
.btn:disabled { opacity: 0.45; cursor: not-allowed; }

.btn-hero {
  background: #fff;
  color: var(--color-accent);
  font-size: clamp(15px, 1.3vw, 17px);
  padding: 16px 24px;
  white-space: nowrap;
}
.btn-hero:hover { background: var(--color-accent-200); color: var(--color-accent-700); }
.btn-hero:active { background: var(--color-accent-400); color: #fff; }

.btn-submit {
  background: var(--color-ink);
  color: #fff;
  font-size: 16px;
  min-height: 48px;          /* mobile touch-target floor — do not reduce */
  padding: 14px 24px;
  align-self: flex-start;
}
.btn-submit:hover:not(:disabled) { background: #000; }
.btn-submit:active:not(:disabled) { background: var(--color-accent-700); }

/* — header ————————————————————————————————————————————————————————————— */
.site-header {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: clamp(20px, 2.6vw, 30px) var(--gutter);
  background: var(--color-ink);
  color: var(--color-bg);
}
.site-header__logo-link {
  margin-right: auto;
  display: flex;
  align-items: center;
  line-height: 0;
}
.site-header__logo {
  height: clamp(56px, 7.5vw, 86px);
  width: auto;
}

/* — hero ——————————————————————————————————————————————————————————————— */
.hero {
  background: var(--color-accent);
  color: #fff;
  padding: clamp(44px, 7vw, 80px) var(--gutter) clamp(40px, 6vw, 72px);
}
.hero .kicker { margin-bottom: clamp(20px, 3.5vw, 36px); }

.hero__title {
  font-size: clamp(38px, 8.4vw, 104px);
  line-height: 0.92;
  letter-spacing: -0.04em;
  /* 14ch is what forces the 3–4 line poster break. Keep it. */
  max-width: 14ch;
}

.hero__foot {
  display: flex;
  gap: clamp(24px, 4vw, 56px);
  margin-top: clamp(28px, 4.5vw, 52px);
  align-items: flex-end;
  flex-wrap: wrap;
}
.hero__lede {
  margin: 0;
  font-size: clamp(17px, 1.6vw, 20px);
  line-height: 1.45;
  max-width: 52ch;
}

/* — banded grids ——————————————————————————————————————————————————————————
   How the rules are drawn, and why it is done this way:

   Each cell carries its own border-top and border-left. The grid is pulled
   left by 2px inside a wrapper that clips overflow, so the leftmost cell's
   left border is cut off. The wrapper is pulled out by the cell padding
   (20px each side) so content still lands on the page gutter.

   The two obvious alternatives both fail. A gap-based grid over a colored
   parent leaves visible colored blocks when the grid wraps to fewer columns.
   A border-right approach leaves a stray rule hanging at the band's right
   edge. Per-cell leading borders inside a clipping wrapper is correct at
   every column count, including fully stacked. Do not simplify this. */
.band {
  overflow: hidden;
  margin: 0 -20px;
  border-bottom: var(--rule);
}
.band__grid {
  display: grid;
  margin-left: -2px;
}
.band__cell {
  border-top: var(--rule);
  border-left: var(--rule);
}

.band-section { padding: 0 var(--gutter); }

/* stat band — four cells */
/* The `min(…, 100%)` guard on every auto-fit track below is a correctness fix,
   not a design change. A bare minmax(330px, 1fr) cannot fit a 320px viewport:
   the column stays 330px wide, which pushed the document to 350px (horizontal
   scroll) and clipped 8px into the service cells' content. min() lets the track
   collapse to the container at narrow widths and is inert above ~370px, so the
   design's column behavior is untouched everywhere it was verified. */
.stats__grid { grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr)); }
.stats__cell { padding: clamp(24px, 3vw, 32px) 20px clamp(26px, 3vw, 34px); }
.stat__number {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: clamp(30px, 3.4vw, 38px);
  letter-spacing: -0.03em;
}
.stat__unit { font-size: 0.55em; }
.stat__number--gold { color: var(--color-gold); }
.stat__note {
  margin: 10px 0 0;
  font-size: 15px;
  opacity: 0.75;
}

/* — services ——————————————————————————————————————————————————————————— */
.services { padding: clamp(44px, 6vw, 72px) var(--gutter); }
.services__title {
  max-width: 26ch;
  margin: 0 0 clamp(28px, 4vw, 44px);
}
.services__grid { grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr)); }
.services__cell { padding: clamp(26px, 3vw, 34px) 20px clamp(28px, 3vw, 36px); }
.services__cell-kicker {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin: 0 0 14px;
}
.services__cell h3 {
  font-size: clamp(23px, 2.7vw, 30px);
  margin: 0 0 16px;
}
.services__cell p:not(.services__cell-kicker) { opacity: 0.8; }
.services__cell__body { margin: 0 0 12px; }
/* The AI cell runs 16px under its body copy, not 12px — it is setting up the
   display-weight closing line rather than another paragraph. */
.services__cell__body--wide { margin: 0 0 16px; }
.services__cell p:last-child { margin-bottom: 0; }
.services__cell .callout { opacity: 1; }

/* — process ———————————————————————————————————————————————————————————— */
.process { padding: 0 var(--gutter) clamp(44px, 6vw, 72px); }
.process__title { margin: 0 0 clamp(24px, 3.4vw, 36px); }
.process__list { border-top: var(--rule); }
.step {
  display: grid;
  grid-template-columns: clamp(72px, 9vw, 120px) minmax(180px, 240px) 1fr;
  gap: clamp(16px, 2.5vw, 32px);
  padding: clamp(20px, 2.4vw, 26px) 0;
  border-bottom: var(--rule);
  align-items: baseline;
}
.step__number {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: clamp(28px, 3.6vw, 40px);
  color: var(--color-accent);
  letter-spacing: -0.03em;
}
.step h4 { font-size: clamp(19px, 2.2vw, 24px); }
.step p { margin: 0; opacity: 0.8; }

/* — about —————————————————————————————————————————————————————————————— */
.about {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: clamp(28px, 4vw, 48px);
  padding: 0 var(--gutter) clamp(44px, 6vw, 72px);
  align-items: start;
}
/* Photography prints in pure black and white in this system. Never tint or
   colorize imagery — the filter stays even if the source file is already B&W. */
.grayscale { filter: grayscale(1) contrast(1.08); }
.about__portrait {
  width: 100%;
  aspect-ratio: 4 / 5;
  max-height: 520px;
  /* The design states both `aspect-ratio: 4/5` and `max-height: 520px`, but
     those conflict above 416px of width: max-height wins, the box turns
     landscape, and object-fit crops the portrait to fill it — 34% of the photo
     height gone at 1440px, 52% at 1920px, taking the top of the head with it.
     The placeholder in the design file was empty, so this never showed.
     Capping the width at the height limit's 4:5 partner (520 x 4/5) lets both
     stated constraints hold at once and shows the whole frame. */
  max-width: calc(520px * 4 / 5);
}
.about__portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Until the portrait file lands, the text column is the grid's only child.
   Cap its measure so it doesn't run the full page width on a wide viewport.
   This rule stops applying by itself once the portrait is added. */
.about > :only-child { max-width: 68ch; }

.about__title { margin: 0 0 22px; }
.about__body { margin: 0 0 14px; opacity: 0.85; }
.about__body--last { margin: 0 0 20px; }
.about__quote {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: clamp(19px, 2.1vw, 24px);
  line-height: 1.2;
  letter-spacing: -0.02em;
  border-top: var(--rule);
  padding-top: 20px;
}

/* — contact ———————————————————————————————————————————————————————————— */
.contact {
  background: var(--color-accent);
  color: #fff;
  padding: clamp(44px, 6vw, 72px) var(--gutter);
}
.contact__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr));
  gap: clamp(32px, 4.5vw, 56px);
  align-items: start;
}
.contact .kicker { margin-bottom: 20px; }
.contact__title {
  font-size: clamp(32px, 5vw, 52px);
  line-height: 0.98;
  letter-spacing: -0.035em;
  margin: 0 0 22px;
}
.contact__lede {
  margin: 0;
  font-size: clamp(16px, 1.5vw, 18px);
  max-width: 44ch;
}
.contact__links { margin: 24px 0 0; font-size: 16px; }

/* — form ——————————————————————————————————————————————————————————————— */
.form { display: flex; flex-direction: column; gap: 16px; }
.form__row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
  gap: 16px;
}
.field > label {
  display: block;
  color: #fff;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 5px;
}
.input {
  width: 100%;
  min-height: 48px;          /* mobile touch-target floor — do not reduce */
  padding: 6px 10px;
  font: inherit;
  font-size: 16px;           /* 16px also stops iOS zooming the field on focus */
  color: var(--color-text);
  caret-color: var(--color-accent);
  background: #fff;
  border: 1px solid #fff;
  border-radius: var(--radius);
}
textarea.input { min-height: 120px; resize: vertical; }

/* Error state in the system's voice: ink text over a 2px rule. Explicitly not
   a red alert pill — red is not in this palette and the radius is 0. */
.field--invalid .input { border-color: var(--color-ink); border-width: 2px; }
.field__error {
  display: none;
  margin: 6px 0 0;
  padding-top: 6px;
  border-top: 2px solid #fff;
  font-size: 13px;
  color: #fff;
}
.field--invalid .field__error { display: block; }

.form__status {
  margin: 0;
  font-size: 14px;
  line-height: 1.4;
}
.form__status:empty { display: none; }
.form__status--error {
  padding-top: 10px;
  border-top: 2px solid #fff;
}

/* — footer ————————————————————————————————————————————————————————————— */
.site-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 22px var(--gutter);
  background: var(--color-ink);
  color: var(--color-bg);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.site-footer__logo {
  height: 32px;
  width: auto;
  margin-right: auto;
}

/* — the only two breakpoints in the design ————————————————————————————————
   Everything else scales continuously through clamp() and auto-fit. */
@media (max-width: 820px) {
  /* The step number becomes a hanging marker with title and copy stacked
     beside it in column 2. */
  .step {
    grid-template-columns: 64px 1fr;
    row-gap: 6px;
  }
  .step h4 { grid-column: 2; }
  .step p { grid-column: 2; }

  .hero__foot {
    flex-direction: column;
    align-items: stretch;
  }
  .hero__foot .btn { align-self: flex-start; }
}
