/* ==========================================================================
   Red 4 Digital — design system
   --------------------------------------------------------------------------
   Light and open by default, with white and warm off-white alternating band by
   band so the page is easy to scan on the way down.

   Four colours only — red, gold, black, white. Black appears in exactly one
   place: the hero, where it works as a translucent veil over the photograph
   rather than a flat fill. Nothing else on the site is dark. The bands that
   need to stand apart from white — the opportunity section, the closing call
   to action, the footer — use the light end of the gold scale with normal
   dark text, so the page stays open the whole way down.

   Red carries action; gold carries emphasis and numbers. The research behind
   this rebuild found the entire AI-consultancy category sitting in corporate
   blue, so the red is a deliberate differentiator, not decoration.
   ========================================================================== */

:root {
  /* Brand */
  --red: #c41e25;
  --red-dark: #a3161c;
  --red-tint: #fdf2f2;
  --gold: #b08420;
  --gold-bright: #d9ad3f;
  --gold-tint: #fbf6e9;

  /* A full gold scale, dark end first. Black is now reserved for the hero
     alone; every other dark band and the footer are built from these, so the
     page reads as one warm family rather than as black with gold on top.
     The deep end is a true bronze — dark enough for white text at AA, warm
     enough that it never reads as grey. */
  /* The light scale, used for every gold band and the footer. */
  --gold-100: #faf4e4;
  --gold-150: #f6eee0;
  --gold-200: #f1e5c4;

  /* Sampled straight off the R4 mark — the gold in the logo itself. Reserved
     for the closing call to action, which is the one band that should stop
     you, so it is the one band that carries the full-strength colour. */
  --gold-logo: #a37f4a;
  --gold-logo-lift: #b08d5e;
  --gold-logo-deep: #957240;
  /* On that gold, text has to go almost black to clear 4.5:1. A mid brown
     fails outright, so the deep band gets its own muted colour. */
  --on-gold-deep: #241d10;
  --gold-300: #e7d5a6;
  --gold-600: #8f6a15;
  --gold-700: #6f5211;

  /* Lines and muted text on the light gold bands. Both are mixed from the gold
     rather than from neutral grey, which reads as dirt against a warm ground. */
  /* Lines and muted text on the light gold bands. Both are mixed from the gold
     rather than from neutral grey, which reads as dirt against a warm ground. */
  --on-gold-line: #e8dcbc;
  --on-gold-muted: #6b6250;

  /* Typefaces. Declared as tokens so the whole site can be re-set from one
     place — the Schibsted Grotesk trial overrides these two and nothing else. */
  --font-body: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-display: "Space Grotesk", Inter, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Neutrals, all mixed toward the brand black rather than pure grey */
  --ink: #0b0b0c;
  --ink-soft: #1b1b1f;
  --text: #17171b;
  --text-muted: #5c5c66;
  --text-faint: #8a8a93;
  --line: #e5e3df;
  --line-strong: #d2cfc9;
  --paper: #ffffff;
  --paper-alt: #f7f6f3;
  --paper-warm: #f2efe9;

  /* On dark */
  --on-dark: #ffffff;
  --on-dark-muted: #a9a9b2;
  --on-dark-line: rgba(255, 255, 255, 0.14);

  --wrap: 1240px;
  --wrap-narrow: 820px;
  --radius: 4px;
  --radius-lg: 8px;

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --shadow-card: 0 1px 2px rgba(11, 11, 12, 0.04), 0 8px 24px rgba(11, 11, 12, 0.06);
  --shadow-float: 0 4px 12px rgba(11, 11, 12, 0.08), 0 24px 64px rgba(11, 11, 12, 0.18);
}

/* ── Reset ───────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

body {
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.65;
  color: var(--text);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
ul, ol { list-style: none; padding: 0; }

:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ink); color: #fff; padding: 12px 20px;
}
.skip-link:focus { left: 0; }

/* ── Typography ──────────────────────────────────────────────────────────── */
h1, h2, h3, h4, h5 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.025em;
  color: var(--ink);
  text-wrap: balance;
}

h1 { font-size: clamp(2.4rem, 5.6vw, 4.1rem); letter-spacing: -0.035em; }
h2 { font-size: clamp(1.9rem, 3.8vw, 2.9rem); }
h3 { font-size: clamp(1.2rem, 2vw, 1.45rem); }
h4 { font-size: 1.05rem; }

h1 em, h2 em, h3 em {
  font-style: normal;
  color: var(--red);
}

p { text-wrap: pretty; }

.lead {
  font-size: clamp(1.05rem, 1.5vw, 1.22rem);
  line-height: 1.7;
  color: var(--text-muted);
  max-width: 62ch;
}

/* The small uppercase label that opens most sections. */
.eyebrow {
  display: inline-flex; align-items: baseline; gap: 0;
  /* Bitcount Single is a pixel-grid face — the type equivalent of the dot field
     behind the hero, which is why the eyebrow wears it and nothing else does.
     Two adjustments come with it: it is drawn on a coarse grid so it needs more
     size than Space Grotesk did to stay legible, and its glyphs already carry
     air, so the old 0.15em tracking read as gaps between letters rather than a
     label. Space Grotesk stays as the fallback so a failed font load changes
     the texture and not the layout. */
  font-family: "Bitcount Single", "Space Grotesk", sans-serif;
  font-size: 0.9rem; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  /* Gold, and specifically --gold-600. The eyebrow is 0.9rem, which is small
     text, so it needs 4.5:1 against white. Measured: --gold-bright is 2.10 and
     --gold-logo 3.69, so both fail; --gold-600 is 4.95 and is the lightest of
     the set that passes. --gold-700 passes at 7.26 but reads brown rather than
     gold. The dark bands keep --gold-300 below, which is 13.55 on #0b0b0c. */
  color: var(--gold-600);
  margin-bottom: 18px;
}
.on-dark .eyebrow { color: var(--gold-300); }

/* A blinking underscore after every eyebrow, in place of the 26px rule that
   used to sit before it. step-end rather than a fade: a cursor blinks on and
   off, it does not pulse, and an eased opacity reads as a glow. 1.06s is the
   rate a terminal uses. It takes its colour from the text, so it follows the
   red-to-gold switch on the dark bands with no second rule. */
.eyebrow::after {
  /* A literal underscore. It sits on the baseline, which is why the eyebrow
     aligns its flex items to baseline rather than centre — with align-items
     centred the glyph floats above the text it is supposed to trail. */
  content: "_";
  margin-left: 0.12em;
  animation: r4-caret 1.06s step-end infinite;
}
@keyframes r4-caret { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }
/* Held steady rather than removed: the caret is part of the wordmark's look,
   and a visitor asking for less motion still wants the design. */
@media (prefers-reduced-motion: reduce) {
  .eyebrow::after { animation: none; opacity: 0.55; }
}

/* ── Layout ──────────────────────────────────────────────────────────────── */
.wrap { width: min(100% - 44px, var(--wrap)); margin-inline: auto; }
.wrap-narrow { width: min(100% - 44px, var(--wrap-narrow)); margin-inline: auto; }

.band { padding-block: clamp(64px, 8vw, 118px); }
.band--alt { background: var(--paper-alt); }
.band--warm { background: var(--paper-warm); }
.band--tight { padding-block: clamp(44px, 5vw, 72px); }

/* The gold bands are light — a warm cream, not a dark fill. A slow diagonal
   gradient across the light end of the scale keeps a full-width band from
   going flat, and hairline borders stop it bleeding into the white either
   side. Text stays the normal dark. */
.band--gold {
  background: linear-gradient(168deg, var(--gold-100) 0%, var(--gold-150) 55%, var(--gold-200) 100%);
  color: var(--text);
  border-block: 1px solid var(--on-gold-line);
}
.band--gold .lead, .band--gold p { color: var(--on-gold-muted); }

/* Full-strength logo gold. Used once, on the closing call to action. */
.band--gold-deep {
  background: linear-gradient(168deg, var(--gold-logo-lift) 0%, var(--gold-logo) 55%, var(--gold-logo-deep) 100%);
  color: var(--ink);
  border-block: 1px solid rgba(0, 0, 0, 0.12);
}
.band--gold-deep .lead, .band--gold-deep p { color: var(--on-gold-deep); }
/* Red on gold sits at 1.9:1 and vanishes. White carries the button instead and
   keeps the red where it still reads — in the label. */
.band--gold-deep .btn--primary { background: #fff; color: var(--red); }
.band--gold-deep .btn--primary:hover { background: var(--ink); color: #fff; }
.band--gold-deep .link-arrow { color: var(--ink); }

/* Kept for the hero, the only dark ground left on the site. */
.on-dark { color: var(--on-dark); }
.on-dark h1, .on-dark h2, .on-dark h3, .on-dark h4 { color: var(--on-dark); }
.on-dark .lead, .on-dark p { color: var(--on-dark-muted); }

.section-head { max-width: 760px; margin-bottom: clamp(38px, 5vw, 62px); }
.section-head h2 + .lead { margin-top: 18px; }
/* Centred variant. The auto margins are needed twice over: once on the block,
   which is narrower than the wrap it sits in, and again on its children —
   .lead carries its own 62ch cap, so without this it centres its text inside a
   box still sitting flush against the left edge. */
.section-head--centre { margin-inline: auto; text-align: center; }
.section-head--centre > * { margin-inline: auto; }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 11px 20px;
  font-family: var(--font-display);
  /* Uppercase with open tracking, the way code23 sets its buttons — 0.875rem at
     0.12em, which is their 0.105rem tracking expressed as a ratio so it holds
     at any size. The size drops from 0.95rem to pay for the extra width: caps
     plus 0.12em runs roughly a third wider than the sentence case it replaces.
     Font follows --font-display, so these turn to Geist Mono with the headings
     rather than needing their own switch. */
  font-size: 0.875rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.12em;
  border: 1px solid transparent; border-radius: var(--radius);
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease),
              border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.btn svg { width: 17px; height: 17px; flex: none; transition: transform 0.25s var(--ease); }
.btn:hover svg { transform: translateX(3px); }

.btn--primary { background: var(--red); color: #fff; }
.btn--primary:hover { background: var(--red-dark); }

.btn--dark { background: var(--ink); color: #fff; }
.btn--dark:hover { background: var(--ink-soft); }

.btn--gold { background: var(--gold); color: #fff; }
.btn--gold:hover { background: #96701a; }

.btn--line { background: transparent; border-color: var(--line-strong); color: var(--ink); }
.btn--line:hover { border-color: var(--ink); background: var(--ink); color: #fff; }

/* The hero is dark but is not marked .on-dark — the white offer card lives
   inside it and must keep its light styling. Buttons are called out directly. */
.on-dark .btn--line,
.hero .btn--line { border-color: var(--on-dark-line); color: #fff; }
.on-dark .btn--line:hover,
.hero .btn--line:hover { background: #fff; color: var(--ink); border-color: #fff; }

.btn--block { width: 100%; justify-content: center; }
.btn--lg { padding: 14px 26px; font-size: 0.92rem; }

/* Inline text link with an arrow */
.link-arrow {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-display);
  font-weight: 600; font-size: 0.92rem;
  color: var(--red);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s var(--ease), gap 0.2s var(--ease);
}
.link-arrow:hover { border-color: currentColor; gap: 11px; }
.link-arrow svg { width: 15px; height: 15px; }

/* ── Header ──────────────────────────────────────────────────────────────── */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: saturate(180%) blur(14px);
}

/* The brand rule. Long red, a short gold centred on the screen, then long
   black. Sits on the sticky header rather than the hero, so it is under the
   bar on every page and stays there while scrolling — it also serves as the
   header's bottom edge, which is why there is no separate border. */
.site-header::after {
  content: "";
  position: absolute; left: 0; right: 0; bottom: 0;
  height: 3px;
  background: linear-gradient(90deg,
    var(--red) 0%, var(--red) 45%,
    var(--gold) 45%, var(--gold) 55%,
    var(--ink) 55%, var(--ink) 100%);
}
/* The bar sizes itself from the logo rather than pinning a height, which is
   what previously capped the logo at 64px: anything taller overflowed a fixed
   76px. min-height keeps the old bar height as the floor, so a small logo
   changes nothing and a large one is accommodated instead of clipped. */
.header-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 28px; min-height: max(76px, calc(var(--logo-h, 56px) + 24px));
}
/* The logo sits on a small live tile rather than flat white. The anchor becomes
   the positioning context; the field is inset slightly wider than the mark so
   the texture reads as a ground it stands on rather than a box drawn round it.
   The tile is painted white explicitly — the header is a translucent white, so
   inheriting it would let the page scroll through the dots. */
.header-logo { position: relative; display: inline-flex; align-items: center; }
/* No background here on purpose — it comes from the Halftone screen, inline, and
   defaults to transparent. It was pinned to #fff when the tile was built,
   because the header is a translucent white and a transparent tile lets the page
   scroll THROUGH the dots. That turned out to be the wanted effect rather than
   the bug it was guarded against: the mark reads as sitting on the page instead
   of in a box. Set the field to #fff to get the solid tile back. */
.header-logo-field {
  position: absolute; inset: -7px -10px; z-index: 0;
  border-radius: 3px; overflow: hidden; pointer-events: none;
}
.header-logo-field canvas { display: block; width: 100%; height: 100%; }
/* Above the field, and the mark's own transparency is the point — the dots
   show through the gaps in the 4 rather than being masked by it. */
.header-logo img { position: relative; z-index: 1; height: var(--logo-h, 56px); width: auto; }

.nav-main { display: flex; align-items: center; gap: 4px; }
.nav-main a {
  /* Uppercase in the display face, matching the buttons. Size drops 0.94 to
     0.78rem and the horizontal padding tightens, because caps at 0.1em run
     wide and the header has a nowrap CTA and a phone number to fit beside
     them. */
  padding: 9px 11px; border-radius: var(--radius);
  font-family: var(--font-display);
  font-size: 0.78rem; font-weight: 600; color: var(--text);
  text-transform: uppercase; letter-spacing: 0.1em;
  transition: background 0.18s var(--ease), color 0.18s var(--ease);
}
.nav-main a:hover { background: var(--paper-alt); color: var(--ink); }
.nav-main a[aria-current="page"] { color: var(--red); font-weight: 600; }

.header-right { display: flex; align-items: center; gap: 14px; }
.header-phone {
  font-family: var(--font-display); font-weight: 600;
  font-size: 0.92rem; color: var(--ink); white-space: nowrap;
}
.header-phone:hover { color: var(--red); }

.nav-toggle {
  display: none; background: none; border: 1px solid var(--line-strong);
  border-radius: var(--radius); padding: 9px; cursor: pointer;
}
.nav-toggle svg { width: 20px; height: 20px; }

@media (max-width: 1040px) {
  .nav-main, .header-phone { display: none; }
  .nav-toggle { display: block; }
}

/* Mobile drawer */
.nav-drawer {
  position: fixed; inset: 76px 0 0; z-index: 99;
  background: var(--paper);
  padding: 28px 22px 40px;
  overflow-y: auto;
  transform: translateY(-8px);
  opacity: 0; visibility: hidden;
  transition: opacity 0.24s var(--ease), transform 0.24s var(--ease), visibility 0.24s;
}
.nav-drawer.open { opacity: 1; visibility: visible; transform: none; }
.nav-drawer a {
  display: block; padding: 15px 0;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: 1.22rem; font-weight: 600;
}
.nav-drawer .btn { margin-top: 26px; }

/* ── Hero ────────────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  background: var(--ink);
  color: var(--on-dark);
  overflow: hidden;
  isolation: isolate;
}
.hero::after {
  /* The black is a translucent veil rather than a wash over a faded picture:
     the image runs at full strength underneath and this controls how much
     shows through. Heaviest on the left where the headline sits, lifting
     across to the right so the photograph reads around the offer card.
     The lightest stop is still 0.40, which keeps white text on the right-hand
     side of the band above AA. */
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(100deg,
    rgba(11, 11, 12, 0.93) 0%,
    rgba(11, 11, 12, 0.88) 32%,
    rgba(11, 11, 12, 0.66) 62%,
    rgba(11, 11, 12, 0.40) 100%);
}
.hero-bg {
  position: absolute; inset: 0; z-index: -2;
  background: var(--ink);
}
.hero-bg img {
  width: 100%; height: 100%; object-fit: cover;
  /* Favours the right of the frame, where the software on screen actually is. */
  object-position: 60% center;
}



.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(min(340px, 100%), 0.85fr);
  gap: clamp(36px, 5vw, 72px);
  align-items: center;
  padding-block: clamp(64px, 8vw, 108px);
}
/* The dot field fills the whole hero, sitting between the flat ground and the
   veil so the ::after gradient still controls how strongly it reads behind the
   headline. z-index -2 is the photograph's old layer, so nothing else moves. */
.hero-field { position: absolute; inset: 0; z-index: -2; pointer-events: none; }
.hero-field canvas { display: block; width: 100%; height: 100%; }
/* With the audit card gone the copy has the row to itself. */
.hero-grid--wide { grid-template-columns: minmax(0, 1fr); }
.hero-grid--wide .hero-copy { max-width: 44rem; }

/* The footer mark is drawn rather than placed, so the canvas has to be given the
   size the img used to take from its own intrinsic dimensions. */
.r4-mark[data-halftone] { width: var(--mark-h, 96px); height: var(--mark-h, 96px); }
.r4-mark[data-halftone] canvas { display: block; width: 100%; height: 100%; }

.hero-copy h1 { color: #fff; margin-bottom: 24px; }
.hero-copy h1 em { color: var(--gold-bright); }
.hero-copy .lead { color: var(--on-dark-muted); font-size: clamp(1.05rem, 1.4vw, 1.18rem); }
.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 34px; }

/* The white offer card, floated over the dark band. */
.offer-card {
  background: #fff;
  color: var(--text);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-float);
  padding: clamp(26px, 3vw, 36px);
  border-top: 4px solid var(--red);
}
.offer-card .eyebrow { color: var(--red); margin-bottom: 12px; }
.offer-card h2 {
  font-size: clamp(1.3rem, 1.9vw, 1.6rem);
  color: var(--ink);
  margin-bottom: 16px;
}
.offer-price {
  display: flex; align-items: baseline; gap: 10px;
  padding-bottom: 18px; margin-bottom: 18px;
  border-bottom: 1px solid var(--line);
}
.offer-price .amount {
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 3.4vw, 2.9rem); font-weight: 700;
  letter-spacing: -0.03em; color: var(--ink); line-height: 1;
}
.offer-price .note { font-size: 0.88rem; color: var(--text-muted); }
.offer-card p { font-size: 0.96rem; color: var(--text-muted); margin-bottom: 18px; }

.offer-guarantee {
  display: flex; gap: 11px; align-items: flex-start;
  background: var(--gold-tint);
  border-left: 3px solid var(--gold);
  padding: 14px 16px; margin-bottom: 20px;
  border-radius: 0 var(--radius) var(--radius) 0;
}
.offer-guarantee svg { width: 18px; height: 18px; color: var(--gold); flex: none; margin-top: 2px; }
.offer-guarantee strong {
  font-size: 0.93rem; font-weight: 600; color: var(--ink); line-height: 1.5;
}
.offer-foot {
  font-size: 0.83rem; color: var(--text-faint);
  margin: 14px 0 0; text-align: center;
}

/* Trust bar under the hero */
/* The column count comes from how many items are actually switched on, so
   turning one off splits the rest equally rather than leaving a gap where it
   used to be. Both counts are emitted by the template — CSS cannot do the
   arithmetic inside repeat(). */
.trust-bar {
  border-top: 1px solid var(--on-dark-line);
  display: grid;
  grid-template-columns: repeat(var(--trust-cols, 4), minmax(0, 1fr));
}
.trust-item { padding: 26px 26px 30px; }
.trust-item + .trust-item { border-left: 1px solid var(--on-dark-line); }
.trust-item .value {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 2.1vw, 1.75rem); font-weight: 700;
  letter-spacing: -0.02em; color: var(--gold-bright); margin-bottom: 7px;
}
.trust-item .label { font-size: 0.88rem; color: var(--on-dark-muted); line-height: 1.5; }

@media (max-width: 960px) {
  .hero-grid { grid-template-columns: 1fr; }
  .trust-bar { grid-template-columns: repeat(var(--trust-cols-sm, 2), minmax(0, 1fr)); }
  /* At two columns every odd item starts a row, whatever the total. */
  .trust-item:nth-child(odd) { border-left: none; }
  .trust-item:nth-child(n+3) { border-top: 1px solid var(--on-dark-line); }
}
@media (max-width: 560px) {
  .trust-bar { grid-template-columns: 1fr; }
  .trust-item + .trust-item { border-left: none; border-top: 1px solid var(--on-dark-line); }
}

/* ── Cards & grids ───────────────────────────────────────────────────────── */
/* Explicit column counts rather than auto-fit. auto-fit decides the count from
   available width, which orphaned the fourth service card into a row of its
   own at desktop widths — four items in a three-column grid. Fixed counts with
   named breakpoints keep every grid balanced at every size. */
.grid { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1000px) {
  .grid--3, .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
}
.grid > * { background: var(--paper); padding: clamp(26px, 2.8vw, 38px); }
.band--alt .grid > * { background: var(--paper-alt); }

/* Numbered service card — the 01/02/03 pattern */
.svc-card { display: flex; flex-direction: column; position: relative; transition: background 0.25s var(--ease); }
.svc-card:hover { background: var(--red-tint); }
.svc-num {
  font-family: var(--font-display);
  font-size: 0.82rem; font-weight: 700; letter-spacing: 0.1em;
  color: var(--red); margin-bottom: 16px;
}
.svc-card h3 { margin-bottom: 12px; }
.svc-card p { color: var(--text-muted); font-size: 0.97rem; margin-bottom: 20px; flex: 1; }

/* Promise / feature tiles */
.tile h3 { margin-bottom: 12px; display: flex; align-items: center; gap: 11px; }
.tile h3::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%;
  background: var(--gold); flex: none;
}
.tile p { color: var(--text-muted); font-size: 0.97rem; }

/* Stat tiles */
.stat .value {
  display: block; font-family: var(--font-display);
  font-size: clamp(1.9rem, 3.4vw, 2.7rem); font-weight: 700;
  letter-spacing: -0.03em; color: var(--gold); line-height: 1; margin-bottom: 14px;
}
/* Deepened on the light ground: the mid gold cleared 3:1 against bronze but
   not against cream. These are large display figures, so 3:1 is the bar. */
.band--gold .stat .value { color: var(--gold-600); }
.stat p { font-size: 0.95rem; color: var(--text-muted); }
.band--gold .stat p { color: var(--on-gold-muted); }
.band--gold .grid { background: var(--on-gold-line); border-color: var(--on-gold-line); }
.band--gold .grid > * { background: rgba(255, 255, 255, 0.62); }

/* ── AI model strip ──────────────────────────────────────────────────────── */
.models { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; background: var(--line); border-block: 1px solid var(--line); }
@media (max-width: 1000px) { .models { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .models { grid-template-columns: 1fr; } }
.model { background: var(--paper); padding: 30px 28px; }
.model-name {
  display: flex; align-items: baseline; gap: 9px; margin-bottom: 12px;
}
.model-name strong {
  font-family: var(--font-display); font-size: 1.15rem;
  font-weight: 700; letter-spacing: -0.02em; color: var(--ink);
}
.model-name span { font-size: 0.8rem; color: var(--text-faint); }
.model p { font-size: 0.9rem; color: var(--text-muted); line-height: 1.6; }
/* The vendor mark sits where the red/gold rule used to, so the card keeps its
   rhythm. Uploaded icons are painted through a mask rather than shown directly
   — that way any SVG comes out in gold regardless of its own colours. */
.model-mark {
  display: block; width: 27px; height: 27px; margin-bottom: 16px;
  color: var(--gold); flex: none;
}
.model-mark--upload {
  background: currentColor;
  -webkit-mask: var(--mark) center / contain no-repeat;
  mask: var(--mark) center / contain no-repeat;
}

/* ── Split comparison (the opportunity band) ─────────────────────────────── */
.split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px; background: var(--on-gold-line); border: 1px solid var(--on-gold-line); border-radius: var(--radius-lg); overflow: hidden; }
@media (max-width: 820px) { .split { grid-template-columns: 1fr; } }
.split-side { background: rgba(255, 255, 255, 0.62); padding: clamp(26px, 3vw, 40px); }
.split-side--win { background: linear-gradient(160deg, rgba(196, 30, 37, 0.07), rgba(255, 255, 255, 0.62) 70%); }
.split-side h3 {
  font-family: var(--font-display); font-size: 1.15rem;
  margin-bottom: 20px; color: var(--ink);
}
.split-side--lose h3 { color: var(--text-muted); }
.split-side li {
  padding: 12px 0 12px 28px; position: relative;
  border-top: 1px solid var(--on-gold-line);
  color: var(--on-gold-muted); font-size: 0.96rem; line-height: 1.6;
}
.split-side li:first-child { border-top: none; }
.split-side li::before {
  position: absolute; left: 0; top: 12px; font-weight: 700; font-size: 1rem;
}
.split-side--lose li::before { content: "↓"; color: #a89a7c; }
.split-side--win li::before { content: "↑"; color: var(--red); }
.split-side--win li { color: var(--text); }

.punch { margin-top: clamp(40px, 5vw, 66px); max-width: 900px; }
.punch p:first-child {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.7vw, 2rem); line-height: 1.35;
  letter-spacing: -0.02em; color: var(--ink); font-weight: 500; margin-bottom: 16px;
}
.punch p + p { color: var(--on-gold-muted); max-width: 62ch; }

/* ── Proof ───────────────────────────────────────────────────────────────── */
.client-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; }
@media (max-width: 900px) { .client-list { grid-template-columns: 1fr; } }
.client { background: var(--paper); padding: clamp(24px, 2.6vw, 34px); }
.client h3 { font-size: 1.08rem; margin-bottom: 10px; }
.client h3::after {
  content: ""; display: block; width: 30px; height: 2px;
  background: var(--gold); margin-top: 12px;
}
.client p { font-size: 0.93rem; color: var(--text-muted); }

.product-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: 22px; margin-top: 22px; }
.product {
  border: 1px solid var(--line); border-radius: var(--radius-lg);
  overflow: hidden; background: var(--paper);
  transition: box-shadow 0.25s var(--ease), transform 0.25s var(--ease);
}
.product:hover { box-shadow: var(--shadow-card); transform: translateY(-2px); }
.product-img { aspect-ratio: 16 / 10; overflow: hidden; background: var(--paper-warm); }
.product-img img { width: 100%; height: 100%; object-fit: cover; }
.product-body { padding: 22px 24px 26px; }
.product-body h3 { font-size: 1.08rem; margin-bottom: 8px; display: flex; align-items: center; gap: 8px; }
.product-body h3 svg { width: 15px; height: 15px; color: var(--text-faint); }
.product-body p { font-size: 0.93rem; color: var(--text-muted); }

/* ── Tech stack chips ────────────────────────────────────────────────────── */
.chips { display: flex; flex-wrap: wrap; gap: 9px; }
.chip {
  padding: 9px 16px; border: 1px solid var(--line-strong);
  border-radius: 100px; font-size: 0.88rem; font-weight: 500;
  color: var(--text-muted); background: var(--paper);
}
.band--gold .chip { border-color: var(--on-gold-line); color: var(--on-gold-muted); background: rgba(255, 255, 255, 0.6); }
.on-dark .chip { border-color: var(--on-dark-line); color: var(--on-dark-muted); background: transparent; }

/* ── Closing CTA ─────────────────────────────────────────────────────────── */
.cta-band { text-align: center; }
.cta-band h2 { margin-bottom: 18px; }
.cta-band .lead { margin-inline: auto; }
.cta-actions { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; align-items: center; margin-top: 32px; }
.cta-band .link-arrow { color: var(--red); }

/* ── Footer ──────────────────────────────────────────────────────────────── */
.site-footer {
  /* Geist Mono across the whole footer and the strip below it — pinned, not
     following --font-display, so the footer keeps this face whatever the
     heading trials are set to. Everything inside inherits, so a block added
     later matches without needing its own rule. Lower case here on purpose:
     the uppercase treatment is for the top nav and buttons, and a footer full
     of capitals reads as shouting rather than as structure. */
  font-family: var(--font-mono);
  background: linear-gradient(180deg, var(--gold-150) 0%, var(--gold-200) 100%);
  color: var(--on-gold-muted);
  border-top: 1px solid var(--on-gold-line);
  padding-top: clamp(52px, 6vw, 80px);
}
/* Explicit column counts. The previous rule combined a 240px minimum first
   column with auto-fit 150px columns, giving the grid an 840px floor it could
   not shrink below — which pushed every page 71px wider than a phone screen. */
.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) repeat(4, minmax(0, 1fr));
  gap: clamp(28px, 3vw, 48px);
  padding-bottom: 48px;
}
@media (max-width: 1000px) {
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-brand { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .footer-grid { grid-template-columns: 1fr; gap: 28px; }
}
.footer-brand img { height: var(--logo-footer-h, 40px); width: auto; margin-bottom: 18px; }
/* Prose, so the body face — same reasoning as the column items. The footer's
   mono is for labels: headings, the closing strip, the "Why Red 4?" band. */
.footer-brand p { font-family: var(--font-body); font-size: 0.92rem; line-height: 1.7; max-width: 38ch; }
/* Social row. Sits under the brand blurb rather than in a column of its own, so
   an unclaimed account leaving a gap never shows as an empty column heading. */
.footer-social {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin-top: 20px; padding: 0; list-style: none;
}
.footer-social a {
  display: grid; place-items: center;
  width: 38px; height: 38px; border-radius: 50%;
  border: 1px solid var(--on-gold-line);
  color: var(--ink); text-decoration: none;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.footer-social a:hover, .footer-social a:focus-visible {
  background: var(--red); border-color: var(--red); color: #fff;
}
.footer-social svg { display: block; }

.footer-col h5 {
  font-family: var(--font-mono); font-size: 0.78rem;
  font-weight: 600; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--ink); margin-bottom: 16px;
}
/* Same treatment as the top nav, a touch tighter: these are lists of links, so
   they read as a set rather than as sentences. Slightly less tracking than the
   header because there are more of them stacked. */
/* The COLUMN HEADINGS stay in Geist Mono uppercase — they are labels, and they
   are what makes the footer read as a set. The ITEMS under them are not labels,
   they are readable lines like "AI, Systems & Security Audit", so they take the
   body face in sentence case, matching the prose in the charity strip. Mono at
   0.76rem with tracking made a five-word service name hard work. */
.footer-col li {
  margin-bottom: 10px; line-height: 1.6;
  font-family: var(--font-body);
  font-size: 0.95rem; font-weight: 400;
  letter-spacing: 0;
}
.footer-col a:hover { color: var(--red); }

/* Newsletter sign-up. Lives in the brand column under the social row, so it is
   on every page without needing a band of its own. */
.footer-sub { margin-top: 28px; max-width: 38ch; }
.footer-sub h5 {
  font-family: var(--font-mono); font-size: 0.78rem;
  font-weight: 600; letter-spacing: 0.13em; text-transform: uppercase;
  color: var(--ink); margin-bottom: 8px;
}
.footer-sub p { font-size: 0.86rem; line-height: 1.6; margin-bottom: 12px; }
.footer-sub-row { display: flex; gap: 8px; flex-wrap: wrap; }
.footer-sub input[type="email"] {
  flex: 1 1 180px; min-width: 0;
  padding: 10px 12px; font: inherit; font-size: 0.9rem;
  color: var(--ink); background: #fff;
  border: 1px solid var(--on-gold-line); border-radius: 4px;
}
.footer-sub input[type="email"]:focus-visible {
  outline: 2px solid var(--red); outline-offset: 1px;
}
.footer-sub button {
  padding: 10px 18px; font: inherit; font-size: 0.9rem; font-weight: 600;
  color: #fff; background: var(--red);
  border: 1px solid var(--red); border-radius: 4px; cursor: pointer;
}
.footer-sub button:hover { filter: brightness(1.08); }

/* Turnstile, in interaction-only mode. It renders nothing at all for the great
   majority of visitors, so the container must not reserve space or leave a gap
   under the field in the ordinary case — margin only once it has content. */
.footer-sub-cf:not(:empty) { margin-top: 12px; }
.footer-sub-note {
  margin-top: 10px; font-size: 0.8rem; opacity: 0.75;
}

/* Off-screen but still focusable by assistive tech, and still submitted — which
   is what the honeypot needs. */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Black band. The one place besides the hero where the site goes dark, and it
   earns it: this is the memorial note, not a marketing one. */
.footer-four {
  background: var(--ink); color: var(--on-dark);
  padding-block: 40px;
}
.footer-four-inner {
  display: grid;
  grid-template-columns: minmax(0, 220px) minmax(0, 1fr) auto;
  gap: clamp(20px, 3vw, 44px); align-items: start;
}

/* The memorial clock. Deliberately quiet — it sits at the edge of the band and
   is never the first thing read. */
.munich { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 10px; }
.munich-clock { width: 62px; height: auto; color: var(--gold-300); opacity: 0.55; }
.munich figcaption {
  font-family: var(--font-mono);
  font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--on-dark-muted); opacity: 0.8; white-space: nowrap;
}
.footer-four p { color: var(--on-dark-muted); }
/* The R4 monogram sits with the heading it belongs to — the Eddie Colman
   note is the one place on the site where the mark carries actual meaning. */
/* The monogram now sits alone in the first column: the heading moved across to
   sit directly on top of the copy it introduces, which is where a heading
   belongs and how every other section of the site is set. The mark stays here
   as the column's anchor rather than following the heading, so the band keeps
   its three-part rhythm. */
.footer-four-head { display: flex; flex-direction: column; align-items: flex-start; }
/* The word under the dissolving 4. Sized by script to the mark's own width —
   this only says what face it wears and how far below it sits. Bitcount Single
   is the eyebrow's face, and the caret it ends on is the eyebrow's caret. */
.r4-mark-word {
  display: block; margin-top: 0.4rem; line-height: 1; white-space: nowrap;
  font-family: "Bitcount Single", "Space Grotesk", sans-serif;
  /* Weight is set inline from the Credit setting; this is only the fallback
     for a page rendered before that field existed. */
  font-weight: 400; letter-spacing: 0.06em; text-transform: uppercase;
}
/* Explicit gap, because the global reset zeroes every margin. */
.footer-four-body { display: flex; flex-direction: column; gap: 12px; }
/* Plain on white — both halves of the monogram read as drawn, so it needs no
   tile behind it. */
.r4-mark { flex: none; display: inline-flex; }
.r4-mark img { width: var(--mark-h, 96px); height: var(--mark-h, 96px); display: block; }
.footer-four h5 {
  font-family: var(--font-mono); font-size: 0.78rem;
  font-weight: 600; letter-spacing: 0.13em; text-transform: uppercase; color: var(--gold-300);
}
.footer-four p { font-size: 0.89rem; line-height: 1.7; max-width: 74ch; }

/* Red closing strip — the last step down the page. A thin white rule separates
   it from the black band above, so the two solid colours never touch. */
.footer-bottom {
  background: var(--red);
  border-top: 3px solid #fff;
  color: rgba(255, 255, 255, 0.88);
  padding-block: 22px;
  font-family: var(--font-mono);
  font-size: 0.8rem; letter-spacing: 0.01em;
}
.footer-bottom-inner {
  display: flex; flex-wrap: wrap; gap: 12px 28px; justify-content: space-between;
}
.footer-bottom a:hover { color: #fff; text-decoration: underline; }

@media (max-width: 980px) {
  .footer-four-inner { grid-template-columns: minmax(0, 200px) minmax(0, 1fr); }
  .munich { grid-column: 1 / -1; flex-direction: row; align-items: center; gap: 14px; }
}
@media (max-width: 700px) {
  .footer-four-inner { grid-template-columns: 1fr; }
}

/* ── Reveal on scroll ─────────────────────────────────────────────────────
   Gated behind the .js class, which the inline script sets before first paint.
   Without it every .reveal stays fully visible — so a JS error, a blocked
   script or a text-only browser can never leave the page blank below the fold.
   The content is in the HTML either way; only the animation is conditional. */
.js .reveal { opacity: 0; transform: translateY(14px); transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); }
.js .reveal.visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; transition: none; }
}

/* ── Page hero (every page except the homepage) ───────────────────────────── */
/* Light, not dark. The black hero is the homepage's alone; inner pages open on
   paper so the run down the site stays open. */
.page-hero {
  background: linear-gradient(180deg, var(--paper) 0%, var(--paper-alt) 100%);
  border-bottom: 1px solid var(--line);
  padding-block: clamp(48px, 6vw, 86px);
}
.page-hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(min(320px, 100%), 0.8fr);
  gap: clamp(32px, 4vw, 64px);
  align-items: start;
}
.page-hero h1 { margin-bottom: 20px; }
.page-hero .lead { margin-bottom: 4px; }
.page-hero .hero-actions { margin-top: 30px; }
@media (max-width: 900px) {
  .page-hero-inner { grid-template-columns: 1fr; }
}

/* The priced offer card, reused from the homepage hero on a light ground. */
.price-card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-top: 4px solid var(--red);
  border-radius: var(--radius-lg);
  padding: clamp(24px, 2.6vw, 32px);
  box-shadow: var(--shadow-card);
}
.price-card .eyebrow { margin-bottom: 10px; }
.price-card p { font-size: 0.96rem; color: var(--text-muted); margin-bottom: 18px; }

/* ── Numbered process ────────────────────────────────────────────────────── */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr));
  gap: 1px;
  background: var(--on-gold-line);
  border: 1px solid var(--on-gold-line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  counter-reset: step;
}
.step { background: rgba(255, 255, 255, 0.62); padding: clamp(24px, 2.6vw, 34px); }
.step-label {
  display: inline-block;
  font-family: var(--font-display);
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--red); margin-bottom: 14px;
}
.step h3 { font-size: 1.1rem; margin-bottom: 10px; }
.step p { font-size: 0.95rem; color: var(--on-gold-muted); }

/* ── In scope / out of scope ─────────────────────────────────────────────── */
/* The single most trust-building block on a fixed-price page: it answers the
   question every buyer is actually asking — what exactly do I get. */
.scope { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); gap: clamp(24px, 3vw, 48px); }
.scope-head {
  display: flex; align-items: center; gap: 10px;
  font-size: 1.05rem; padding-bottom: 14px; margin-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.scope-head::before {
  content: ""; width: 20px; height: 20px; border-radius: 50%; flex: none;
  background: var(--red);
}
.scope-head--out::before { background: var(--text-faint); }
.scope li {
  position: relative; padding: 12px 0 12px 30px;
  border-bottom: 1px solid var(--line);
  font-size: 0.97rem; color: var(--text);
}
.scope li::before {
  content: "✓"; position: absolute; left: 2px; top: 12px;
  color: var(--red); font-weight: 700;
}
.scope-out li { color: var(--text-muted); }
.scope-out li::before { content: "—"; color: var(--text-faint); }

.stat-note { margin-top: 20px; font-size: 0.85rem; color: var(--text-faint); }

/* ── FAQ ─────────────────────────────────────────────────────────────────── */
.faq { border-top: 1px solid var(--line); max-width: 900px; }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item summary {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 20px 0; cursor: pointer; list-style: none;
  font-family: var(--font-display);
  font-size: 1.05rem; font-weight: 600; color: var(--ink);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--red); }
.faq-icon {
  position: relative; width: 16px; height: 16px; flex: none;
}
.faq-icon::before, .faq-icon::after {
  content: ""; position: absolute; background: var(--red);
  transition: transform 0.25s var(--ease);
}
.faq-icon::before { left: 0; top: 7px; width: 16px; height: 2px; }
.faq-icon::after { left: 7px; top: 0; width: 2px; height: 16px; }
.faq-item[open] .faq-icon::after { transform: scaleY(0); }
.faq-body { padding: 0 0 22px; max-width: 72ch; }
.faq-body p { color: var(--text-muted); }

/* ── About: founder ──────────────────────────────────────────────────────── */
.founder { display: grid; grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr); gap: clamp(32px, 4vw, 64px); align-items: start; }
.founder-photo { margin: 0; }
.founder-photo img {
  width: 100%; border-radius: var(--radius-lg);
  background: var(--paper-warm); object-fit: cover;
}
.founder-photo figcaption {
  margin-top: 12px; font-size: 0.84rem; color: var(--text-faint);
  font-family: var(--font-display); letter-spacing: 0.04em;
}
.founder-text h2 { margin-bottom: 22px; }
.founder-text p { color: var(--text-muted); margin-bottom: 18px; max-width: 66ch; }
.founder-text p strong { color: var(--ink); font-weight: 600; }
@media (max-width: 860px) { .founder { grid-template-columns: 1fr; } }

/* ── About: the Eddie Colman band ────────────────────────────────────────── */
.band--eddie { background: var(--ink); color: var(--on-dark); padding-block: clamp(56px, 7vw, 96px); }
.band--eddie h2 { color: #fff; }
.band--eddie p { color: var(--on-dark-muted); margin-bottom: 16px; max-width: 62ch; }
.band--eddie .eyebrow { color: var(--gold-300); }
.eddie { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: clamp(28px, 4vw, 56px); align-items: center; }
.eddie-mark img { width: var(--mark-about-h, 110px); height: var(--mark-about-h, 110px); }
.munich--large .munich-clock { width: 92px; }
@media (max-width: 900px) {
  .eddie { grid-template-columns: auto minmax(0, 1fr); }
  .munich--large { grid-column: 1 / -1; flex-direction: row; gap: 16px; }
}
@media (max-width: 560px) {
  .eddie { grid-template-columns: 1fr; }
  .eddie-mark img { width: 84px; height: 84px; }
}

/* ── Contact ─────────────────────────────────────────────────────────────── */
.contact-details { margin-top: 34px; border-top: 1px solid var(--line); }
.contact-details li {
  display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 16px;
  padding: 14px 0; border-bottom: 1px solid var(--line);
  font-size: 0.96rem; color: var(--text-muted);
}
.contact-label {
  font-family: var(--font-display); font-size: 0.74rem;
  font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-faint); padding-top: 3px;
}
.contact-details a { color: var(--ink); border-bottom: 1px solid var(--line-strong); }
.contact-details a:hover { color: var(--red); border-color: var(--red); }
@media (max-width: 480px) { .contact-details li { grid-template-columns: 1fr; gap: 4px; } }

.form-card {
  background: var(--paper); border: 1px solid var(--line);
  border-top: 4px solid var(--red); border-radius: var(--radius-lg);
  padding: clamp(24px, 2.8vw, 36px); box-shadow: var(--shadow-card);
}
.form-card h2 { font-size: 1.4rem; margin-bottom: 8px; }
.form-intro { font-size: 0.94rem; color: var(--text-muted); margin-bottom: 24px; }

.field { margin-bottom: 16px; }
.field-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
@media (max-width: 520px) { .field-row { grid-template-columns: 1fr; } }
.field label {
  display: block; margin-bottom: 6px;
  font-size: 0.85rem; font-weight: 500; color: var(--text);
}
.req { color: var(--red); }
.field input, .field select, .field textarea {
  width: 100%; padding: 12px 14px;
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  background: var(--paper); font-size: 0.97rem;
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--red);
  box-shadow: 0 0 0 3px rgba(196, 30, 37, 0.12);
}
.field textarea { resize: vertical; min-height: 120px; }

/* Honeypot. Off-screen rather than display:none — some bots skip hidden
   fields, and this one exists precisely to be filled in. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-status { margin-top: 14px; font-size: 0.92rem; min-height: 1.2em; }
.form-status.is-error { color: var(--red); }
.form-status.is-ok { color: #1c7a3e; font-weight: 500; }
.form-small { margin-top: 14px; font-size: 0.8rem; color: var(--text-faint); line-height: 1.6; }

/* ── Legal documents ─────────────────────────────────────────────────────── */
.legal-updated { margin-top: 10px; font-size: 0.9rem; color: var(--text-faint); }
.legal-doc h2 {
  font-size: 1.3rem; margin: 40px 0 14px;
  padding-top: 24px; border-top: 1px solid var(--line);
}
.legal-doc h2:first-of-type { border-top: none; padding-top: 0; margin-top: 0; }
.legal-doc p { color: var(--text-muted); margin-bottom: 16px; }
.legal-doc ul { margin: 0 0 18px; }
.legal-doc li {
  position: relative; padding: 6px 0 6px 22px; color: var(--text-muted);
}
.legal-doc li::before {
  content: ""; position: absolute; left: 2px; top: 15px;
  width: 6px; height: 6px; border-radius: 50%; background: var(--gold);
}
.legal-doc a { color: var(--red); border-bottom: 1px solid currentColor; }

/* ── Insights ────────────────────────────────────────────────────────────── */
.post-date {
  display: block; margin-top: auto; padding-top: 14px;
  font-size: 0.83rem; color: var(--text-faint);
}
.post-meta {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 22px; font-size: 0.88rem; color: var(--text-faint);
}
.post-flag {
  padding: 3px 10px; border-radius: 100px;
  background: var(--gold-tint); color: var(--gold-600);
  font-size: 0.78rem; font-weight: 600;
}
.post-hero-img { margin-top: -20px; }
.post-hero-img img { width: 100%; border-radius: var(--radius-lg); }

.post-body { font-size: 1.06rem; line-height: 1.75; }
.post-body > p { color: var(--text-muted); margin-bottom: 22px; }
.post-body > h2 { font-size: clamp(1.4rem, 2.4vw, 1.8rem); margin: 42px 0 16px; }
.post-body > h3 { margin: 32px 0 12px; }
.post-body ul, .post-body ol { margin: 0 0 22px; }
.post-body li {
  position: relative; padding: 6px 0 6px 24px; color: var(--text-muted);
}
.post-body li::before {
  content: ""; position: absolute; left: 2px; top: 16px;
  width: 6px; height: 6px; border-radius: 50%; background: var(--gold);
}
.post-body a { color: var(--red); border-bottom: 1px solid currentColor; }
.post-body blockquote {
  margin: 28px 0; padding: 4px 0 4px 22px;
  border-left: 3px solid var(--gold);
  font-size: 1.12rem; color: var(--ink);
}
.post-body img { border-radius: var(--radius); margin: 24px 0; }
.post-source {
  margin-top: 36px; padding-top: 20px; border-top: 1px solid var(--line);
  font-size: 0.9rem; color: var(--text-faint);
}
.post-source a { color: var(--red); }

/* ── Cookie consent ──────────────────────────────────────────────────────── */
/* Bottom-left rather than a full-width bar: it stays out of the way of the
   hero's call to action, which is the thing the page exists to get clicked. */
.consent {
  position: fixed; z-index: 200;
  left: 16px; bottom: 16px; width: min(100% - 32px, 420px);
  background: var(--paper);
  border: 1px solid var(--line);
  border-top: 3px solid var(--red);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-float);
  padding: 20px 22px;
}
.consent[hidden] { display: none; }
.consent p { font-size: 0.9rem; line-height: 1.6; color: var(--text-muted); margin-bottom: 16px; }
.consent a { color: var(--red); border-bottom: 1px solid currentColor; }
.consent-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.consent-actions .btn { padding: 10px 18px; font-size: 0.9rem; }

/* The full call to action wraps to two lines on a phone and pushes the header
   out of shape; below 620px it swaps to a short form rather than disappearing,
   because it is the main conversion route on the site. */
.nav-cta { white-space: nowrap; }
.nav-cta-short { display: none; }
/* The short label arrives at 900px rather than 620px: "BOOK THE AUDIT — £995"
   set in caps at 0.12em is about a third wider than it was in sentence case,
   and the header CTA is nowrap, so it runs into the nav well before the phone
   breakpoint it used to rely on. */
@media (max-width: 900px) {
  .nav-cta-full { display: none; }
  .nav-cta-short { display: inline; }
}

@media (max-width: 620px) {
  .nav-cta { padding: 11px 16px; font-size: 0.88rem; }
  /* Same floor-and-grow rule as above, matched to the 0.82 phone scale below. */
  .header-inner { gap: 12px; min-height: max(68px, calc(var(--logo-h, 56px) * 0.82 + 20px)); }
  .header-logo img { height: calc(var(--logo-h, 56px) * 0.82); }
}

/* Turnstile only renders anything on the rare occasion it needs a human, so
   this collapses to nothing on almost every visit rather than leaving a gap. */
.form-turnstile:not(:empty) { margin-bottom: 16px; }

/* ── Town pages ──────────────────────────────────────────────────────────── */

/* The local-market prose. Measured rather than full width — this is the section
   people actually read, so it gets a comfortable line length. */
.prose { max-width: 68ch; }
.prose p { font-size: 1.02rem; line-height: 1.75; color: var(--text-muted); }
.prose p + p { margin-top: 18px; }

/* A worked example. Same card language as .svc-card, but the outcome line is
   the point — it is what turns a description into a claim. */
.scenario {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 26px 26px 22px;
}
.scenario h3 { font-size: 1.05rem; margin-bottom: 10px; }
.scenario p { font-size: 0.93rem; color: var(--text-muted); line-height: 1.65; }
.scenario-outcome {
  display: flex; align-items: flex-start; gap: 9px;
  margin-top: 16px; padding-top: 15px; border-top: 1px solid var(--line);
  font-weight: 600; color: var(--ink);
}
.scenario-outcome svg { width: 17px; height: 17px; flex: none; margin-top: 3px; color: var(--red); }

.local-proof { text-align: center; }
.local-proof h2 { margin-bottom: 14px; }
.local-proof p { color: var(--text-muted); line-height: 1.7; }

.areas-block { text-align: center; }
.areas-block h2 { font-size: clamp(1.15rem, 1.8vw, 1.4rem); margin-bottom: 20px; }
.areas-list {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 10px;
  list-style: none; padding: 0; margin: 0 0 18px;
}
.areas-list li {
  font-size: 0.85rem; color: var(--text-muted);
  border: 1px solid var(--line); border-radius: 100px; padding: 5px 13px;
  background: var(--paper);
}
.areas-note { font-size: 0.88rem; color: var(--text-faint); max-width: 60ch; margin: 0 auto; }

/* Towns with a page sit in the same list as towns without one, so a linked
   entry has to be visibly clickable at rest — the existing rule only changes
   colour on hover, which a reader never discovers. */
.footer-col a { text-decoration: none; }
.footer-col ul a { border-bottom: 1px solid currentColor; }

/* ── The charity strip on the homepage ───────────────────────────────────────
   A strip, not a band: one line of copy and a button side by side. The whole
   point of the homepage rewrite was to stop it arguing several cases at once,
   so this earns its place by staying to about forty words and one link. */
.give-strip { background: var(--gold-100); border-block: 1px solid var(--line); }
.give {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(24px, 4vw, 56px); align-items: center;
}
.give h2 { font-size: clamp(1.3rem, 2vw, 1.65rem); margin-bottom: 10px; }
.give p { color: var(--text-muted); max-width: 62ch; }
.give .btn { white-space: nowrap; }
@media (max-width: 780px) {
  .give { grid-template-columns: 1fr; }
  .give .btn { white-space: normal; justify-self: start; }
}

/* ── Where the charity queue is ──────────────────────────────────────────────
   Deliberately loud, because it is the one line on that page that goes out of
   date, and a stale queue is the fastest way to lose a charity's trust. */
.queue-status {
  margin: 0 0 clamp(28px, 4vw, 44px);
  padding: 14px 18px; border-left: 3px solid var(--red);
  background: rgba(255, 255, 255, 0.6); border-radius: var(--radius-lg);
  font-size: 0.97rem; color: var(--text);
}
.queue-status strong { color: var(--ink); }

/* A BLACK HEADER.
   One class on the bar, and everything inside it flips: the ground, the nav,
   the phone, the button and the hairline under it. The logo is chosen in the
   layout rather than here — a black bar takes the dissolving 4 and a white one
   the field, which is the way round each reads, and is the same rule the client
   credits apply to themselves.

   Written as overrides of the light header rather than as a second header, so
   anything added to the light one is inherited and only its colour has to be
   answered here. */
.site-header.is-dark { background: rgba(11, 11, 12, 0.92); }
/* The same hairline as the light header, with the third band flipped: red,
   gold, then WHITE rather than ink — an ink band on an ink bar is invisible,
   so the line looked two-thirds the width it should be. Same stops, so the two
   headers read as one design in two colourways. */
.site-header.is-dark::after {
  background: linear-gradient(90deg,
    var(--red) 0%, var(--red) 45%,
    var(--gold) 45%, var(--gold) 55%,
    #FDFAF7 55%, #FDFAF7 100%);
}
.site-header.is-dark .nav-main a { color: rgba(253, 250, 247, 0.82); }
.site-header.is-dark .nav-main a[aria-current="page"] { color: #fff; }
/* Hover has to go DARK on the black bar, which looks backwards until you
   remember what `.nav-main a:hover` does: it paints a light --paper-alt pill
   behind the link. The dark-header rule used to lift hover and current-page to
   #fff together, so hovering an item put near-white text on a near-white pill
   and the label disappeared under the cursor — the one state where you are
   certainly looking at it. Only the current-page colour belongs at #fff; it
   sits on the bar itself with no pill behind it.

   Declared after the aria-current rule deliberately. The two selectors have
   identical specificity, so source order is what decides the current page's
   own hover, and the pill means dark has to win. */
.site-header.is-dark .nav-main a:hover { color: var(--ink); }
.site-header.is-dark .header-phone,
.site-header.is-dark .header-right a:not(.btn) { color: rgba(253, 250, 247, 0.82); }
.site-header.is-dark .header-right a:not(.btn):hover { color: #fff; }
.site-header.is-dark .nav-toggle { color: #fff; }
.site-header.is-dark .nav-toggle span { background: #fff; }
/* The mark on a dark bar: brand red is drawn for white paper and goes muddy
   here, the same allowance the footer credit makes. */
.site-header.is-dark .r4-mark { --r4-red: #d2373d; }
.site-header.is-dark .r4-px rect { fill: #d2373d; }

/* A LOGO INSIDE A PAGE SECTION.
   Height comes from the section's own setting via --section-logo-h; nothing
   here fixes a size, because a mark that punctuates one band shouts in the
   next. Centred and given room above the heading it introduces. */
.section-logo {
  display: flex; justify-content: center;
  margin: 0 auto clamp(1.2rem, 2.5vw, 2rem);
  height: var(--section-logo-h, 72px);
}
.section-logo img,
.section-logo .r4-mark,
.section-logo .header-logo-field { height: 100%; width: auto; display: block; }
.section-logo .r4-mark[data-halftone],
.section-logo .header-logo-field[data-halftone] {
  width: var(--section-logo-h, 72px); height: var(--section-logo-h, 72px);
}
.section-logo canvas { width: 100%; height: 100%; display: block; }
/* The field is a tile with the mark sitting on it, so the two stack. */
.section-logo--field { position: relative; }
.section-logo--field img { position: absolute; inset: 0; margin: auto; height: 78%; width: auto; }
/* Brand red is drawn for white paper; the dark bands need it lifted, the same
   allowance the footer credit and the dark header make. */
.band--gold-deep .section-logo .r4-mark, .cta-band .section-logo .r4-mark { --r4-red: #d2373d; }

/* ── Case study pull quote ───────────────────────────────────────────────── */
/* Only ever holds something a client actually said, so it is allowed to take
   the full width of the narrow wrap and be the loudest thing on the page. The
   gold band it sits on already carries the section colour, so the quote takes a
   rule rather than a second background. */
.pull-quote { margin: 0; padding: 4px 0 4px 26px; border-left: 3px solid var(--gold-600); }
.pull-quote p {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2.4vw, 1.7rem);
  line-height: 1.4; letter-spacing: -0.015em; color: var(--on-gold);
}
.pull-quote cite {
  display: block; margin-top: 18px; font-style: normal;
  font-size: 0.9rem; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--on-gold-muted);
}
