/* ==========================================================================
   AEWA LABS — Design System
   Dark canvas · signal accent · engineered grid
   ========================================================================== */

/* ---------- 1. Tokens ---------- */
/* Paper & proof. The page is a proof sheet: grey type on paper, struck in
   red pen. Single-theme by intent — the metaphor only works on paper, so
   there is no dark variant to swap to. */
:root {
  /* Surface */
  --ink:        #f7f5f0;   /* paper */
  --ink-2:      #edeae3;   /* paper, sunk: cards, footer, marquee */
  --ink-3:      #e5e1d9;   /* pressed / hovered */
  --ink-4:      #d9d5c9;

  /* Line */
  --line:        #16151a29;
  --line-2:      #16151a4d;
  --line-3:      #16151a80;

  /* Type */
  --text:        #16151a;
  --text-2:      #4a484f;
  --text-3:      #6a676e;

  /* Accent — the cut */
  --accent:      #c8331b;   /* the cut: marks, fills, strikes, large display */
  /* #d93a1e on paper measures 4.10:1, which fails AA for small text, so
     accent-coloured TYPE uses the darker ink instead. */
  --accent-ink:  #a82813;
  --accent-2:    #e2603f;
  --accent-dim:  rgba(200, 51, 27, 0.10);
  --accent-glow: rgba(200, 51, 27, 0.28);

  /* Wall tones — the generated mass, in paper greys */
  /* Three spot inks. The amber read as brown against paper and muddied the
     set; pink, blue and green are saturated enough to carry the whole system. */
  --spot-pink:   #ad1d7e;
  --spot-blue:   #2340c9;
  --spot-green:  #0d7f4c;

  /* Fonts */
  --f-display: 'Archivo', ui-sans-serif, system-ui, sans-serif;
  --f-body:    'Geist', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --f-mono:    'Geist Mono', ui-monospace, 'SFMono-Regular', monospace;

  /* Space scale */
  --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; --s-11: 160px;

  /* Layout */
  --wrap: 1240px;
  --wrap-narrow: 860px;
  --gutter: clamp(20px, 5vw, 56px);
  --nav-h: 48px;

  /* Motion */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur: 0.6s;

  --radius: 14px;
  --radius-lg: 22px;
}

/* ---------- 2. Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }

/* The `hidden` attribute is only a user-agent rule, so ANY author `display`
   beats it. `.form` is display:grid — so `form.hidden = true` did nothing:
   after a successful send the form stayed on screen, the button frozen on
   "Sending…", with "Got it." sitting directly beneath it. Make the attribute
   mean what it says. */
[hidden] { display: none !important; }
html {
  -webkit-text-size-adjust: 100%;
  /* No `scroll-behavior: smooth` here: it fights ScrollTrigger's pinned hero
     and mis-measures the pin on refresh. Anchor links are smoothed in JS
     instead, which ScrollTrigger can follow. */
  scroll-padding-top: calc(var(--nav-h) + 24px);
}
body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--f-body);
  font-size: 16px;
  line-height: 1.68;
  font-feature-settings: 'kern', 'liga', 'cv11';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* `clip`, not `hidden`: overflow:hidden on body makes it a scroll container
     and breaks pin measurement. `clip` contains the marquee just as well. */
  overflow-x: clip;
}
img, svg, video, canvas { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
::selection { background: var(--accent); color: #fff; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 3px;
}

/* ---------- 3. Texture layers ---------- */
/* Removed. The blueprint grid and the film grain were both dark-tech
   signifiers that fought the paper ground — and both were on the list of
   generated-design tells. Clean paper instead. */

/* ---------- 4. Layout ---------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
  position: relative;
  z-index: 2;
}
.wrap--narrow { max-width: var(--wrap-narrow); }

section { position: relative; z-index: 2; }
.section { padding-block: clamp(72px, 11vw, 150px); }
.section--tight { padding-block: clamp(56px, 7vw, 88px); }
.section--line { border-top: 1px solid var(--line); }

.grid { display: grid; gap: var(--s-6); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 980px) {
  .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 680px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}

/* Two-column: sticky heading + content */
.cols {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(32px, 6vw, 96px);
  align-items: start;
}
.cols__sticky { position: sticky; top: calc(var(--nav-h) + 40px); }
@media (max-width: 900px) {
  .cols { grid-template-columns: 1fr; }
  .cols__sticky { position: static; }
}

/* ---------- 5. Typography ---------- */
.eyebrow {
  font-family: var(--f-mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-ink);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 var(--s-5);
}
.eyebrow::before {
  content: '';
  width: 22px;
  height: 1px;
  background: var(--accent);
  opacity: 0.7;
}
.eyebrow--plain { color: var(--text-3); }
.eyebrow--plain::before { background: var(--text-3); }

h1, h2, h3, h4, .h1, .h2, .h3, .h4 {
  font-family: var(--f-display);
  font-weight: 600;
  /* Archivo is a variable face; 112 on the width axis is the slightly
     expanded cut, and its taller x-height needs more leading than a
     narrow grotesque would. */
  font-variation-settings: 'wdth' 112;
  line-height: 1.10;
  letter-spacing: -0.042em;
  margin: 0 0 var(--s-5);
  text-wrap: balance;
}
h1, .h1 { font-size: clamp(34px, 5.0vw, 58px); letter-spacing: -0.045em; }
h2, .h2 { font-size: clamp(25px, 3.1vw, 38px); }
h3, .h3 { font-size: clamp(19px, 1.9vw, 24px); letter-spacing: -0.028em; line-height: 1.2; }
h4, .h4 { font-size: 16.5px; letter-spacing: -0.012em; line-height: 1.35; }

p { margin: 0 0 var(--s-4); color: var(--text-2); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

.lead {
  font-size: clamp(16.5px, 1.4vw, 18.5px);
  line-height: 1.62;
  color: var(--text-2);
  max-width: 60ch;
}
.lead strong { color: var(--text); font-weight: 500; }

.small { font-size: 13.5px; color: var(--text-3); }
.mono { font-family: var(--f-mono); font-size: 13px; letter-spacing: 0.02em; }

.accent { color: var(--accent-ink); }
.dim { color: var(--text-3); }

/* Gradient text for key phrases */
.grad {
  background: linear-gradient(100deg, var(--text) 10%, var(--accent-2) 55%, var(--accent) 90%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---------- 6. Buttons ---------- */
.btn {
  --btn-bg: var(--accent);
  --btn-fg: #ffffff;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 13px 24px;
  border-radius: 100px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: 14.5px;
  font-weight: 500;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  isolation: isolate;
  transition: transform 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out);
  will-change: transform;
}
.btn::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(110deg, transparent 20%, rgba(255,255,255,0.30) 50%, transparent 80%);
  transform: translateX(-130%);
  transition: transform 0.75s var(--ease-out);
}
.btn:hover { box-shadow: 0 12px 40px -10px var(--accent-glow); }
.btn:hover::after { transform: translateX(130%); }
.btn:active { transform: scale(0.97); }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--text);
  border: 1px solid var(--line-2);
  backdrop-filter: blur(8px);
}
.btn--ghost:hover {
  border-color: var(--line-3);
  background: rgba(20,22,26,0.05);
  box-shadow: none;
}
.btn--sm { padding: 11px 20px; font-size: 14px; }

.btn__arrow { transition: transform 0.4s var(--ease-out); }
.btn:hover .btn__arrow { transform: translateX(4px); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  align-items: center;
}

/* Text link with animated underline */
.link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--text);
  font-weight: 500;
  font-size: 15px;
  position: relative;
  padding-bottom: 3px;
}
.link::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.45s var(--ease-out);
}
.link:hover::after { transform: scaleX(1); transform-origin: left; }
.link:hover { color: var(--accent-ink); }
.link svg, .link .btn__arrow { transition: transform 0.4s var(--ease-out); }
.link:hover .btn__arrow { transform: translateX(4px); }

/* ---------- 7. Navigation ---------- */
/* A wordmark and one link. The plate is always on rather than fading in on
   scroll, because the wall now starts directly beneath it and needs a clean
   edge to start against. */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: var(--nav-h);
  z-index: 100;
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--line);
  background-color: #f7f5f0db;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.nav__inner {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-6);
}

.logo {
  font-family: var(--f-display);
  font-variation-settings: 'wdth' 112;
  font-weight: 800;
  font-size: 15px;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  min-height: 40px;
}

.nav__links { display: flex; align-items: center; gap: var(--s-5); list-style: none; margin: 0; padding: 0; }
.navlink {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-2);
  transition: color 0.2s;
}
.navlink:hover { color: var(--text); }
.navlink:active { color: var(--accent); }
.navlink[aria-current='page'] { color: var(--accent-ink); }

/* ---------- 8. Hero ---------- */
.hero {
  position: relative;
  min-height: clamp(640px, 100svh, 1000px);
  display: flex;
  align-items: center;
  padding-top: calc(var(--nav-h) + 40px);
  padding-bottom: var(--s-8);
  overflow: hidden;
}
#field {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  opacity: 0;
  transition: opacity 1.6s ease 0.3s;
}
#field.is-ready { opacity: 1; }
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  /* The particle field needed a radial wash on the left to keep the headline
     legible. The wall lives ABOVE the headline instead, so that wash only
     erased half the mass — a plain vertical fade is what this composition
     actually needs. */
  background: linear-gradient(to bottom,
    transparent 0%, transparent 68%, rgba(244, 242, 237, 0.80) 84%, var(--ink) 96%);
}
.hero .wrap { z-index: 3; }
.hero__inner { max-width: 940px; }
.hero h1 { margin-bottom: var(--s-6); }
.hero .lead { max-width: 54ch; margin-bottom: var(--s-7); }

/* Scroll hint */
.scroll-hint {
  position: absolute;
  bottom: 34px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-family: var(--f-mono);
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-3);
}
.scroll-hint__line {
  width: 1px; height: 46px;
  background: linear-gradient(to bottom, var(--accent), transparent);
  animation: drop 2.4s var(--ease-in-out) infinite;
  transform-origin: top;
}
@keyframes drop {
  0%   { transform: scaleY(0); opacity: 0; }
  40%  { transform: scaleY(1); opacity: 1; }
  100% { transform: scaleY(1) translateY(46px); opacity: 0; }
}
@media (max-width: 760px) { .scroll-hint { display: none; } }

/* ---------- 9. Marquee proof strip ---------- */
.marquee {
  border-block: 1px solid var(--line);
  padding-block: 10px;
  overflow: hidden;
  position: relative;
  background: var(--ink-2);
  /* Fixed pixels, not percentages. At 8% the fade scaled with the screen,
     so a phone lost 31px from each end — and with the longest claim at
     306px on a 390px screen there was no position where it was fully
     legible. A fixed 16px fade costs a phone almost nothing and still
     softens the ends on a wide display. */
  mask-image: linear-gradient(to right, transparent, #000 16px,
                              #000 calc(100% - 16px), transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 16px,
                                      #000 calc(100% - 16px), transparent);
}
.marquee__track {
  display: flex;
  width: max-content;
  gap: var(--s-8);
  animation: slide 38s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
/* Four identical copies in the markup, so the travel is a quarter of the
   track. Two copies left a dead gap on any screen wider than the list
   itself once the strip was trimmed to six claims. */
@keyframes slide { to { transform: translateX(-25%); } }
.marquee__item {
  display: inline-flex;
  align-items: center;
  gap: var(--s-5);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-2);
  white-space: nowrap;
}
.marquee__item::after {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.65;
}

/* ---------- 10. Cards ---------- */
.card {
  position: relative;
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: clamp(24px, 3vw, 38px);
  overflow: hidden;
  transition: border-color 0.5s var(--ease-out), transform 0.5s var(--ease-out), background 0.5s;
  will-change: transform;
}
/* Cursor-following glow */
.card::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  background: radial-gradient(420px circle at var(--mx, 50%) var(--my, 0%), rgba(217,58,30,0.09), transparent 62%);
  opacity: 0;
  transition: opacity 0.5s;
  pointer-events: none;
}
.card:hover { border-color: var(--line-2); background: var(--ink-3); }
.card:hover::before { opacity: 1; }
.card h3 { margin-bottom: var(--s-3); }
.card p { font-size: 15.5px; }

.card__num {
  font-family: var(--f-mono);
  font-size: 11.5px;
  letter-spacing: 0.16em;
  color: var(--accent-ink);
  display: block;
  margin-bottom: var(--s-5);
}
.card__tags {
  font-family: var(--f-mono);
  font-size: 12px;
  color: var(--text-3);
  line-height: 1.8;
  margin-block: var(--s-5);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
}
.card__foot { margin-top: var(--s-5); }

/* Link card — whole card clickable */
.card--link { display: flex; flex-direction: column; }
.card--link .card__foot { margin-top: auto; padding-top: var(--s-5); }

/* Bordered feature list (no card chrome) */
/* No top rule: the pen underline beneath each heading is the only line these
   items carry. Two rules per item — a border above and a stroke below, both
   turning red on hover — read as a boxed-in row rather than a marked one. */
.feature { padding-top: 0; }
/* h3, not h4: these sit directly under the section h2, and jumping a
   level breaks heading navigation for screen readers. Sized to match
   what h4 looked like. */
.feature h3 {
  font-size: 16.5px;
  letter-spacing: -0.012em;
  line-height: 1.35;
  margin-bottom: 14px;
}
.feature p { font-size: 15.5px; margin: 0; }

/* ---------- 11. Process timeline ---------- */
.phase {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: clamp(20px, 4vw, 64px);
  padding-block: clamp(36px, 5vw, 64px);
  border-top: 1px solid var(--line);
  position: relative;
}
/* No closing border: the ink rule beneath is what closes this block.
   Both together read as two dividers doing one job. */
.phase:last-child { border-bottom: 0; }
.phase__meta { position: sticky; top: calc(var(--nav-h) + 40px); align-self: start; }
.phase__num {
  font-family: var(--f-display);
  font-size: clamp(32px, 4.2vw, 50px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.05em;
  color: transparent;
  -webkit-text-stroke: 1px var(--line-3);
  display: block;
  margin-bottom: var(--s-3);
  transition: -webkit-text-stroke-color 0.6s, color 0.6s;
}
.phase.is-active .phase__num { -webkit-text-stroke-color: var(--accent); }
.phase__when {
  font-family: var(--f-mono);
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
}
.phase__body h3 { margin-bottom: var(--s-4); }
.phase__deliver {
  margin-top: var(--s-5);
  padding: var(--s-4) var(--s-5);
  background: var(--ink-2);
  border-left: 2px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 15px;
}
.phase__deliver strong { color: var(--text); font-weight: 500; }
@media (max-width: 780px) {
  .phase { grid-template-columns: 1fr; }
  .phase__meta { position: static; display: flex; align-items: baseline; gap: var(--s-4); }
  .phase__num { margin-bottom: 0; font-size: 38px; }
}

/* ---------- 12. Lists ---------- */
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-3); }
.ticks li {
  position: relative;
  padding-left: 28px;
  color: var(--text-2);
  font-size: 16px;
}
.ticks li::before {
  content: '';
  position: absolute;
  left: 4px; top: 11px;
  width: 7px; height: 7px;
  border-radius: 2px;
  background: var(--accent);
  transform: rotate(45deg);
}
.ticks strong { color: var(--text); font-weight: 500; }

.numbered { list-style: none; margin: 0; padding: 0; counter-reset: n; display: grid; gap: var(--s-5); }
.numbered li { counter-increment: n; display: grid; grid-template-columns: 38px 1fr; gap: var(--s-4); align-items: start; }
.numbered li::before {
  content: counter(n, decimal-leading-zero);
  font-family: var(--f-mono);
  font-size: 12px;
  color: var(--accent-ink);
  padding-top: 5px;
}
.numbered strong { color: var(--text); font-weight: 500; display: block; margin-bottom: 2px; }

/* ---------- 13. Stats ---------- */
.stat { border-top: 1px solid var(--line); padding-top: var(--s-5); }
.stat__num {
  font-family: var(--f-display);
  font-size: clamp(30px, 3.6vw, 44px);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.045em;
  color: var(--text);
  display: block;
  margin-bottom: var(--s-2);
}
.stat__label { font-size: 14.5px; color: var(--text-3); }

/* ---------- 14. Table ---------- */
.table-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-lg); }
table { width: 100%; border-collapse: collapse; min-width: 640px; font-size: 15px; }
th, td { padding: 18px 22px; text-align: left; border-bottom: 1px solid var(--line); vertical-align: top; }
th {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
  font-weight: 500;
  background: var(--ink-2);
}
tbody tr { transition: background 0.3s; }
tbody tr:hover { background: rgba(20,22,26,0.03); }
tbody tr:last-child td { border-bottom: 0; }
td strong { color: var(--text); font-weight: 500; }
td { color: var(--text-2); }

/* ---------- 15. Accordion (FAQ) ---------- */
.acc { border-top: 1px solid var(--line); }
.acc__item { border-bottom: 1px solid var(--line); }
.acc__btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  padding: 24px 0;
  text-align: left;
  font-family: var(--f-display);
  font-size: clamp(16px, 1.6vw, 19px);
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text);
  transition: color 0.3s;
}
.acc__btn:hover { color: var(--accent-ink); }
.acc__icon {
  flex: none;
  width: 22px; height: 22px;
  position: relative;
}
.acc__icon::before, .acc__icon::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 13px; height: 1.5px;
  background: var(--accent);
  transform: translate(-50%, -50%);
  transition: transform 0.45s var(--ease-out);
}
.acc__icon::after { transform: translate(-50%, -50%) rotate(90deg); }
.acc__btn[aria-expanded='true'] .acc__icon::after { transform: translate(-50%, -50%) rotate(0deg); }
.acc__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.5s var(--ease-out);
}
.acc__panel > div { overflow: hidden; }
.acc__item.is-open .acc__panel { grid-template-rows: 1fr; }
.acc__panel p { padding-bottom: 26px; max-width: 66ch; font-size: 16px; }

/* ---------- 16. Forms ---------- */
.form { display: grid; gap: var(--s-5); }
.field { display: grid; gap: 9px; }
.field label {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-3);
}
.field label span { color: var(--accent-ink); }
.field input, .field textarea, .field select {
  width: 100%;
  padding: 15px 18px;
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 16px;
  color: var(--text);
  transition: border-color 0.3s, background 0.3s, box-shadow 0.3s;
  appearance: none;
}
.field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23666d7d' stroke-width='1.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 18px center;
  padding-right: 46px;
}
.field textarea { min-height: 150px; resize: vertical; line-height: 1.6; }
.field input::placeholder, .field textarea::placeholder { color: var(--text-3); }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--ink-3);
  box-shadow: 0 0 0 4px var(--accent-dim);
}
.field__row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4); }
@media (max-width: 620px) { .field__row { grid-template-columns: 1fr; } }
.form__note { font-size: 14px; color: var(--text-3); }

/* ---------- 17. CTA band ---------- */
.cta-band {
  position: relative;
  border-top: 1px solid var(--line);
  overflow: hidden;
  background:
    radial-gradient(80% 130% at 50% 108%, rgba(217,58,30,0.12), transparent 62%),
    var(--ink);
}
.cta-band .wrap { text-align: center; }
/* `ch` here resolved against the PARENT font-size, not the heading's, so
   this was a third of the width it looked like. `em` measures the
   heading itself and lands the line break where it belongs. */
.cta-band h2 { max-width: 19em; margin-inline: auto; }
.cta-band .lead { margin-inline: auto; margin-bottom: var(--s-7); max-width: 58ch; }
.cta-band .btn-row { justify-content: center; }

/* ---------- 18. Footer ---------- */
.footer {
  border-top: 1px solid var(--line);
  background: var(--ink-2);
  padding-block: var(--s-9) var(--s-6);
  position: relative;
  z-index: 2;
}
.footer__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-7);
  padding-bottom: var(--s-8);
}
@media (max-width: 760px) { .footer__grid { grid-template-columns: 1fr; } }
@media (max-width: 560px) { .footer__grid { grid-template-columns: 1fr; } }
.footer__title {
  font-family: var(--f-mono);
  font-size: 10.5px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: var(--s-5);
}
.footer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px; }
.footer__list a {
  font-size: 15px;
  color: var(--text-2);
  transition: color 0.25s, transform 0.25s;
  display: inline-block;
}
.footer__list a:hover { color: var(--accent-ink); transform: translateX(3px); }
.footer__tag { font-family: var(--f-mono); font-size: 12px; color: var(--accent-ink); letter-spacing: 0.05em; margin-top: var(--s-3); }
.footer__bar {
  /* No rule of its own: the ink rule above already divides this off. */
  padding-top: var(--s-5);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4) var(--s-6);
  align-items: center;
  justify-content: space-between;
  font-size: 13.5px;
  color: var(--text-3);
}
.footer__bar a:hover { color: var(--text-2); }
.footer__legal { display: flex; flex-wrap: wrap; gap: var(--s-5); }

/* Giant footer wordmark — outline only, but the outline carries the three
   inks. A CSS text-stroke cannot take a gradient, so this is SVG text with a
   gradient stroke and no fill. textLength pins it to the viewBox, so it sizes
   predictably whether or not the display face has loaded yet. */
.footer__mark {
  display: block;
  width: 100%;
  /* Nudged up ~6% to hold the same optical size now that the viewBox
     carries margin around the letters. */
  max-width: clamp(202px, 25vw, 318px);
  height: auto;
  overflow: visible;
  margin-block: var(--s-7) var(--s-5);
  user-select: none;
  text-align: center;
}

/* ---------- 19. Utility ---------- */
.tagpill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  border: 1px solid var(--line-2);
  border-radius: 100px;
  font-family: var(--f-mono);
  font-size: 11.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-2);
  background: rgba(20,22,26,0.025);
}
.tagpill__dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: #15803d;
  box-shadow: 0 0 10px rgba(21,128,61,0.35);
  animation: pulse 2.4s ease-in-out infinite;
}
.tbc {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 4px;
  background: rgba(217,58,30,0.10);
  border: 1px dashed rgba(217,58,30,0.5);
  font-family: var(--f-mono);
  font-size: 0.82em;
  color: var(--accent-ink);
}
.divider { height: 1px; background: var(--line); border: 0; margin: 0; }
.center { text-align: center; }
.mt-6 { margin-top: var(--s-6); }
.mt-7 { margin-top: var(--s-7); }
.mb-7 { margin-bottom: var(--s-7); }
.maxw { max-width: 62ch; }

.skip {
  position: absolute;
  left: -9999px;
  top: 12px;
  z-index: 200;
  padding: 12px 20px;
  background: var(--accent);
  color: #fff;
  border-radius: 8px;
}
.skip:focus { left: 12px; }

/* ---------- 20. Scroll-reveal primitives ---------- */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out);
}
[data-reveal].is-in { opacity: 1; transform: none; }

/* Stagger children */
.js [data-reveal-group] > * {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.85s var(--ease-out), transform 0.85s var(--ease-out);
}
[data-reveal-group].is-in > * { opacity: 1; transform: none; }
[data-reveal-group].is-in > *:nth-child(1) { transition-delay: 0.00s; }
[data-reveal-group].is-in > *:nth-child(2) { transition-delay: 0.07s; }
[data-reveal-group].is-in > *:nth-child(3) { transition-delay: 0.14s; }
[data-reveal-group].is-in > *:nth-child(4) { transition-delay: 0.21s; }
[data-reveal-group].is-in > *:nth-child(5) { transition-delay: 0.28s; }
[data-reveal-group].is-in > *:nth-child(6) { transition-delay: 0.35s; }
[data-reveal-group].is-in > *:nth-child(7) { transition-delay: 0.42s; }
[data-reveal-group].is-in > *:nth-child(8) { transition-delay: 0.49s; }

/* Line-by-line headline mask reveal */
.line-mask { display: block; overflow: hidden; }
.js .line-mask > span {
  display: block;
  transform: translateY(105%);
  transition: transform 1s var(--ease-out);
}
.is-in .line-mask > span,
.line-mask.is-in > span { transform: translateY(0); }
.line-mask:nth-child(2) > span { transition-delay: 0.09s; }
.line-mask:nth-child(3) > span { transition-delay: 0.18s; }

/* Page load fade */
/* No page-level fade at all. Two attempts at one both failed the same way:
   hiding the page and revealing it from a JS callback left it invisible when
   rAF never fired, and a CSS animation holds its `from` state when animations
   are frozen. Nothing that can fail may stand between a visitor and the page,
   so the page is simply never hidden. Sections still animate individually —
   those have a load-and-scroll safety net and cannot strand the whole site. */

/* ---------- 21. Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  body::after { animation: none; opacity: 0.02; }
  [data-reveal], [data-reveal-group] > * { opacity: 1 !important; transform: none !important; }
  .line-mask > span { transform: none !important; }
  .marquee__track { animation: none; }
  #field { display: none; }
  .page-fade { opacity: 1; }
}

/* ---------- 22. Refinements ---------- */
/* `ch` resolves against the PARENT font-size, which under-sizes display
   headings badly. Constrain measure in `em` on the heading itself. */
.lede { max-width: 13em; }
.lede--tight { max-width: 10em; }

/* Sticky column headings sit in a narrower track — step the scale down */
.cols__sticky h2 { font-size: clamp(23px, 2.5vw, 31px); }

/* Keep card meta rows aligned across a row of unequal cards */
.card--link .card__tags { margin-top: auto; }

/* Nav needs room for the wordmark + 5 links + CTA before collapsing */
@media (max-width: 1140px) and (min-width: 1081px) {
  .nav__link { padding-inline: 10px; font-size: 14px; }
}

/* A display h1 inside a narrow grid track must step down with the track,
   otherwise it wraps one word per line. */
.cols h1 { font-size: clamp(28px, 3.2vw, 40px); }
h1.lede  { max-width: 11em; }
.cols h1.lede { max-width: none; }

/* ---------- 23. Service block (landing-page layout) ---------- */
.svc {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(28px, 5vw, 80px);
  padding-block: clamp(40px, 5vw, 68px);
  border-top: 1px solid var(--line);
  align-items: start;
}
.svc:last-child { border-bottom: 0; }
.svc__head { position: sticky; top: calc(var(--nav-h) + 40px); }
.svc__head h3 { font-size: clamp(21px, 2.2vw, 27px); margin-bottom: var(--s-3); }
.svc__claim {
  color: var(--text);
  font-weight: 500;
  font-size: 17px;
  margin-bottom: var(--s-4);
}
.svc__head p { font-size: 16px; }
.svc__body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-6) var(--s-7);
}
.svc__col h4 { margin-bottom: 14px; }
.svc__col p { font-size: 15.5px; margin: 0; }
.svc__col {
  padding-top: 0;
}

@media (max-width: 900px) {
  .svc { grid-template-columns: 1fr; }
  .svc__head { position: static; }
}
@media (max-width: 620px) {
  .svc__body { grid-template-columns: 1fr; }
}

/* Scroll-spy state on anchor nav items */
.nav__link.is-current { color: var(--accent-ink); background: rgba(20,22,26,0.06); }

/* ---------- 24. Manifesto statement ---------- */
/* A thesis, not a feature grid: oversized claim, the argument in two
   columns beneath it, and the conclusion set apart in display type. */
.manifesto__h { font-size: clamp(28px, 3.9vw, 46px); max-width: 15em; }
.manifesto__body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 4vw, 72px);
  margin-top: var(--s-7);
  padding-top: var(--s-6);
  border-top: 1px solid var(--line);
}
@media (max-width: 760px) { .manifesto__body { grid-template-columns: 1fr; } }
.manifesto__close {
  margin-top: clamp(44px, 6vw, 88px);
  font-family: var(--f-display);
  font-weight: 500;
  font-size: clamp(19px, 2.2vw, 28px);
  line-height: 1.26;
  letter-spacing: -0.03em;
  color: var(--text);
  /* wide enough that each sentence holds its own line on desktop, so the
     explicit <br> is the only break the reader sees */
  max-width: 27em;
}
.manifesto__close em { font-style: normal; color: var(--accent); }

/* ---------- 25. Archivo width axis on the rest of the display role ---------- */
.logo,
.phase__num,
.footer__mark,
.manifesto__close,
.acc__btn,
.stat__num,
.svc__head h3 { font-variation-settings: 'wdth' 112; }

/* ---------- 26. The wall (hero) ---------- */
/* Content sits at the BOTTOM of the hero; the wall fills the space above it,
   so the mass of generated output is what you scroll down through. */
.hero {
  /* The original's composition: the headline occupies a flexible first row
     and sits at its foot, with the lead and the counter on a fixed row below.
     That is what leaves the top 58% clear for the wall. */
  display: grid;
  grid-template-rows: 1fr auto;
  align-items: initial;
  min-height: 100svh;
  padding-top: calc(var(--nav-h) + 24px);
  padding-bottom: var(--s-6);
}
.hero__stage { align-self: end; padding-bottom: 0; }
.hero__foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--s-5) var(--s-7);
  border-top: 1px solid var(--line);
  padding-top: var(--s-7);
  padding-bottom: var(--s-5);
}
.hero__foot .lead { margin: 0; max-width: 46ch; }
.wall {
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 74%;
  z-index: 0;
  display: grid;
  /* 8rem fits the longest entry (20 characters at 0.625rem mono) so no
     word is ever cut off; the right-edge fade is gone for the same reason. */
  /* Fluid, not stepped. A hard breakpoint made the column count jump — six
     columns at 760px, four at 768 — which is the sort of thing you only
     see when you drag a window across it. wall.js measures whatever track
     this produces and drops entries too long to fit. */
  /* 6rem floor left a 320px screen with two columns and a wall that read
     thin; 5rem gets three there and costs nothing above, since the tracks
     stretch to fill either way. */
  grid-template-columns: repeat(auto-fill, minmax(clamp(5rem, 9vw, 8rem), 1fr));
  align-content: start;
  gap: 3px 20px;
  overflow: hidden;
  padding: calc(var(--nav-h) + 12px) var(--gutter) 0;
  pointer-events: none;
  /* hold the words solid for longer before the fade takes them */
  mask-image: linear-gradient(180deg, #000 0%, #000 80%, transparent 100%);
}
@media (max-height: 560px) { .wall { height: 30%; } }

.frag {
  position: relative;
  display: block;
  overflow: hidden;
  font-family: var(--f-mono);
  font-size: 0.625rem;
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--fc, var(--text-3));
  opacity: 0.8;
  white-space: nowrap;
  transition: color 0.6s var(--ease-out), opacity 0.6s var(--ease-out);
}
.frag::after {
  content: '';
  position: absolute;
  top: 54%;
  left: -3%;
  right: -3%;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.45s var(--ease-out);
}
/* The original used opacity .24 — correct on a dark ground, invisible on
   paper, which left red strikes floating over nothing. Struck type stays
   legible; the strike is what marks it, not the fade. */
/* Cutting drains the COLOUR out. That is the whole argument: colour is what
   abundance looks like, and what is left after the cut is neutral. */
.frag.is-cut { color: var(--text-3); opacity: 0.24; }
.frag.is-cut::after { transform: scaleX(1); }

/* The turn, in the one accent on the page */
.hero__turn { display: block; color: var(--accent); }
.scramble { display: block; }

/* Counter — a real count of what is on screen, not an invented figure */
.hero__meter {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
  font-family: var(--f-mono);
  font-size: 11.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-3);
}
.hero__meter b { font-weight: 400; color: var(--text-2); font-variant-numeric: tabular-nums; }
#count-kept { color: var(--accent-ink); }

@media (prefers-reduced-motion: reduce) {
  .frag, .frag::after { transition: none !important; }
}

/* ---------- 27. Crop marks — the one thing kept ---------- */
/* Two L-shaped brackets that land on the headline at the end of the cut.
   The selection mark, not decoration: it is what "1 kept" points at. */
.crop { position: relative; display: block; width: fit-content; max-width: 100%; }
.crop::before,
.crop::after {
  content: '';
  position: absolute;
  width: 0.875rem;
  height: 0.875rem;
  border: 1.5px solid var(--accent);
  opacity: 0;
  transition: opacity 0.4s var(--ease-out);
  pointer-events: none;
}
.crop::before { top: -0.75rem;    left: -1.25rem;  border-bottom: 0; border-right: 0; }
.crop::after  { bottom: -0.75rem; right: -1.25rem; border-top: 0;    border-left: 0;  }
.crop.is-marked::before,
.crop.is-marked::after { opacity: 1; }

@media (max-width: 640px) {
  .crop::before { left: -0.5rem; top: -0.5rem; }
  .crop::after  { right: -0.5rem; bottom: -0.5rem; }
}
@media (prefers-reduced-motion: reduce) {
  .crop::before, .crop::after { transition: none; }
}

/* ---------- 28. Proof marks ----------
   Every effect below is the same gesture as the hero: a pen passing over the
   page. Nothing here is motion for its own sake. */

/* A. Section rules are DRAWN, not printed — a red stroke crosses the rule and
      then settles back into the page's own hairline. */
.section--line { position: relative; }
.section--line::before {
  content: '';
  position: absolute; top: -1px; left: 0; right: 0; height: 1px;
  background: var(--accent);
  transform: scaleX(0); transform-origin: left center;
  /* It used to draw in and then fade out, which just looked like a glitch.
     It stays now: every section opens on a line of the cut colour. */
  transition: transform 1.05s var(--ease-out);
  pointer-events: none;
}
.section--line.is-drawn::before { transform: scaleX(1); }

/* B. Struck copy: the page marks its own words the way the wall is marked. */
.strike { position: relative; white-space: nowrap; }
.strike::after {
  content: '';
  position: absolute; left: -2%; right: -2%; top: 56%; height: 2px;
  background: var(--accent);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 0.6s var(--ease-out) 0.3s;
}
.strike.is-struck::after { transform: scaleX(1); }

/* C. The process reads as a checklist: a phase you have passed stays marked. */
.phase__num { transition: -webkit-text-stroke-color 0.6s var(--ease-out), color 0.6s var(--ease-out); }
.phase.is-passed .phase__num { -webkit-text-stroke-color: var(--accent); color: var(--accent-dim); }

@media (prefers-reduced-motion: reduce) {
  .section--line::before { display: none; }
  .strike::after { transition: none; transform: scaleX(1); }
}

/* The counter is the one thing on screen for the whole opening: it is what
   the visitor watches drain while the wall is struck out. */
.hero__meter { margin: 0; }

/* ---------- 29. The margin ----------
   A marked-up proof carries a margin: a rule down the side, a folio number
   against each page, and paper that is not perfectly flat. That is what fills
   the space beside the text column here — not ornament borrowed from
   somewhere else. */

/* Paper tooth. Very low, and warm rather than neutral, so it reads as stock
   rather than as a filter laid over the page. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.5;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23p)' opacity='0.055'/%3E%3C/svg%3E");
}

/* Alternating stock. Two sections sit on a half-tone so the page has
   rhythm instead of one uninterrupted sheet. */
.section--tint { background: var(--ink-2); }

/* ---------- 30. Marking up ----------
   A proof is a thing someone HANDLED: highlighter dragged over the lines that
   matter, sheets lifted, a registration target in the corner, a colour bar
   along the edge. That is where the interest comes from here — not from a
   frosted panel, which belongs to a different material entirely. */

/* Sheets lift. Paper, not glass: a soft drop and a hairline edge, no blur. */
.card {
  transition: border-color 0.5s var(--ease-out), transform 0.45s var(--ease-out),
              box-shadow 0.45s var(--ease-out), background 0.5s;
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: 0 20px 44px -28px rgba(20, 22, 26, 0.30);
}

/* ---------- 31. Halftone, lamp, pen, frame ---------- */


/* PEN — a slightly wavy hand-drawn line draws under a heading on hover. */
.svc__col h4,
.feature h3 { position: relative; display: inline-block; }
.pen {
  position: absolute;
  left: -3px; bottom: -6px;
  width: calc(100% + 6px); height: 8px;
  overflow: visible;
  pointer-events: none;
}
.pen path { fill: none; stroke-width: 1.6; stroke-linecap: round; }
.pen .rest { stroke: var(--line-2); }
.pen .ink {
  stroke: var(--accent);
  stroke-dasharray: 200;
  stroke-dashoffset: 200;
  transition: stroke-dashoffset 0.5s var(--ease-out);
}
.svc__col:hover .pen .ink,
.feature:hover .pen .ink { stroke-dashoffset: 0; }

/* FRAME — crop marks at the four corners of each section, so every section
   reads as its own trimmed sheet. Set on the content column rather than the
   full-bleed section, so the marks land in the gutter beside the text. */
.section--line > .wrap--narrow::before {
  content: '';
  position: absolute;
  /* Only on the narrow, centred sections: there the marks sit well inside
     the page. On a full-width section they land against the screen edge,
     which reads as a browser artifact rather than a trim mark. */
  inset: calc(-1 * clamp(22px, 3vw, 40px)) calc(-1 * clamp(14px, 2vw, 28px));
  pointer-events: none;
  z-index: 1;
  background-repeat: no-repeat;
  background-position: top left, top right, bottom left, bottom right;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' fill='none' stroke='%23d93a1e' stroke-width='1.4'%3E%3Cpath d='M0.7 15V0.7H15'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' fill='none' stroke='%23d93a1e' stroke-width='1.4'%3E%3Cpath d='M0 0.7H14.3V15'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' fill='none' stroke='%23d93a1e' stroke-width='1.4'%3E%3Cpath d='M0.7 0V14.3H15'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' fill='none' stroke='%23d93a1e' stroke-width='1.4'%3E%3Cpath d='M0 14.3H14.3V0'/%3E%3C/svg%3E");
}
/* Below this the narrow column already fills the screen, so the marks would sit
   against the edge — and their negative inset pushed the page 14px wide, which
   is where the mobile horizontal scroll was coming from. */
@media (max-width: 960px) {
  .section--line > .wrap--narrow::before { content: none; }
}

@media (prefers-reduced-motion: reduce) {
  .pen .ink { transition: none; }
}

/* ---------- 32. Hero foot ---------- */
@media (max-width: 700px) {
  .hero__foot { flex-direction: column; align-items: flex-start; }
}

/* ---------- 33. Hero load-in ----------
   The reference's own entrance: a pure translate, no opacity. That matters —
   an animation that never runs leaves the text visible, just seated 18px low,
   rather than invisible. Nothing here can hide the headline. */
.js .load-in {
  animation: rise-in 0.8s var(--ease-out) both;
  animation-delay: var(--d, 0s);
}
@keyframes rise-in {
  from { transform: translateY(18px); }
  to   { transform: none; }
}
.scramble { font-variant-ligatures: none; }

@media (prefers-reduced-motion: reduce) {
  .js .load-in { animation: none; }
}

/* ---------- 34. Filling the sheet ----------
   Wide sections were mostly empty paper. Three devices, all from the same
   press vocabulary, and none of them touching the screen edge. */

/* No background dot fields. Both the matrix behind the column and the corner
   halftones were masked to fade out, which meant neither ever read as a
   complete thing — just a patch of dots stopping for no reason. A texture that
   cannot be seen whole is noise, so the paper stays clean and the colour
   carries the page instead. */

/* INK RULE — a thin gradient through the three inks, drawn in on entry.
   This is the page's recurring accent: a signal line, not a colour swatch. */
.rule-ink {
  width: 100%;
  height: 2px;
  border-radius: 2px;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 1.1s var(--ease-out);
  background: linear-gradient(90deg,
    var(--spot-pink), var(--spot-blue) 50%, var(--spot-green));
}
.rule-ink.is-drawn { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) { .rule-ink { transition: none; transform: scaleX(1); } }

/* SPOT INKS ON THE SERVICE BLOCKS — the colour from the hero carries into the
   biggest section instead of vanishing after the opening. */
.svc[data-ink='blue']  { --dink: var(--spot-blue); }
.svc[data-ink='green'] { --dink: var(--spot-green); }
.svc[data-ink='pink']  { --dink: var(--spot-pink); }
.svc .card__num { color: var(--dink, var(--accent-ink)); }
.svc .svc__claim { color: var(--dink, var(--text)); }
.svc .pen .ink { stroke: var(--dink, var(--accent)); }

.footer__mark text {
  font-family: var(--f-display);
  font-variation-settings: 'wdth' 112;
  font-weight: 700;
  letter-spacing: -0.06em;
}

/* ---------- 35. Colour trace ----------
   No crosshair, no lamp. A soft wash of ink under the pointer whose hue is
   taken from where you are across the page — pink at the left, blue through
   the middle, green at the right, the same run as the gradient rules. The
   palette follows you instead of an instrument tracking you. */
.trace {
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease;
  mix-blend-mode: multiply;
  /* 280px read as a lamp sweeping the page — too big to feel like a pointer
     and big enough to wash whole paragraphs. Tightened to something the size
     of a cursor's own halo, and a touch denser so the smaller area still
     carries the colour. */
  background: radial-gradient(130px circle at var(--cx, 50%) var(--cy, 50%),
    rgba(var(--trace-rgb, 35 64 201) / 0.16), transparent 70%);
}
.trace.is-on { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .trace { display: none; } }

/* ---------- 36. Inked top rule ----------
   Some dividers matter more than others: the one that opens a block earns the
   colour, the ones between repeated items stay as hairlines. Drawn on entry,
   and it replaces the element's own border rather than sitting next to it. */
.rule-top { position: relative; border-top-color: transparent !important; }
.rule-top::before {
  content: '';
  position: absolute;
  top: -1px; left: 0; right: 0;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg,
    var(--spot-pink), var(--spot-blue) 50%, var(--spot-green));
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 1.1s var(--ease-out);
  pointer-events: none;
}
.rule-top.is-drawn::before { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .rule-top::before { transition: none; transform: scaleX(1); }
}

/* ---------- 37. Footer top row ----------
   The brand block and the wordmark run parallel instead of stacked, so the
   space beside the wordmark is filled rather than left blank. */
.footer__top {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-7);
  flex-wrap: wrap;
  padding-bottom: var(--s-8);
}
/* The wordmark alone left the right half of the row empty above it; the
   contact details sit with it now, so the row reads as two columns. */
.footer__side {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--s-5);
  text-align: right;
  flex: none;
}
.footer__side .small { margin: 0; }
.footer__top .footer__mark { margin: 0; flex: none; }
@media (max-width: 760px) {
  .footer__top { flex-direction: column; align-items: flex-start; gap: var(--s-6); }
  .footer__side { align-items: flex-start; text-align: left; width: 100%; }
}

/* ---------- 38. Phone ----------
   Most of the traffic is a phone, so these are corrections, not afterthoughts. */
@media (max-width: 760px) {
  /* A 17px-tall link is not a tap target. Covers the footer and the contact
     page's own "Direct" list, which uses the same footer list styles. */
  .footer__side a,
  .footer__brand a:not(.logo),
  .footer__list a,
  .form__note a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  /* Small print at 13.5px is uncomfortable on a handset. */
  .small { font-size: 14px; }
}

@media (max-width: 760px) {
  /* Wide tracks stretched to ~165px each held a 120px word — lots of dead
     space and a wall that read as a list rather than a mass. Narrower tracks
     and a tighter gutter restore the density; wall.js drops the longest
     entries below this same width so nothing clips.

     760, not 560: at 561px the 8rem tracks dropped the wall to three columns
     spread across a 600px screen — sparser than the same wall on a phone,
     which is exactly backwards. Keep this number and wall.js's NARROW in
     step; they are the same breakpoint. */
  .wall { gap: 4px 12px; }
}

@media (max-width: 560px) {
  /* On a phone the headline starts at ~61% of the hero, so a 74% wall ran a
     hundred pixels of live type straight behind it. Stop the mass above the
     headline instead of relying on the mask to hide the collision. Phones
     only: on a tablet the hero is tall enough that 74% still clears. */
  .wall { height: 57%; }
}

/* ---------- 39. Form validation states ----------
   The form tells the truth now, so it needs somewhere to say so: a red edge
   on the field at fault, the reason under it, and a form-level line for
   anything that went wrong on the way out. */
.field.is-invalid input,
.field.is-invalid textarea,
.field.is-invalid select {
  border-color: var(--accent);
  background: var(--accent-dim);
}
.field__err {
  margin: 0;
  font-size: 13.5px;
  color: var(--accent-ink);
}
.form__alert {
  margin: 0;
  padding: 14px 18px;
  border: 1px solid var(--line-2);
  border-left: 2px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--ink-2);
  font-size: 14.5px;
  color: var(--text-2);
}
/* This address is the only route to us while the alert is showing, so it has
   to be thumb-sized. Padding with matching negative margin grows the hit area
   without reflowing the sentence it sits in. */
.form__alert a {
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  display: inline-block;
  padding-block: 12px;
  margin-block: -12px;
}

/* Honeypot. Off-screen rather than display:none — some bots skip fields they
   can tell are hidden, and this one is meant to be filled in. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---------- 40. Marquee on a phone ----------
   A 64px gap on a 390px screen meant one claim on screen at a time, usually
   caught mid-fade. Tighter spacing puts two in view and gives the reader
   something to land on. */
@media (max-width: 760px) {
  .marquee__track { gap: var(--s-6); }
  .marquee__item { font-size: 11.5px; letter-spacing: 0.1em; }
  .marquee__item::after { width: 4px; height: 4px; }
}

/* Uppercase mono labels at 11.5px are fine on a desktop at reading distance
   and mean on a phone. A half-point up costs nothing and the tracking keeps
   them reading as labels rather than body copy. */
@media (max-width: 760px) {
  .eyebrow { font-size: 12.5px; }
  .footer__title { font-size: 11.5px; }
  .card__num, .phase__when { font-size: 12.5px; }
}

/* The success state replaces a tall form inside the same card, so it needs a
   little room of its own rather than sitting flush at the top of the box. */
.form-done { padding-block: var(--s-5) var(--s-3); }
.form-done .h3 { margin-bottom: var(--s-3); }
