/* ==========================================================================
   MiRV ELEMENTS — site.css  ·  "The Specimen Sheet"
   --------------------------------------------------------------------------
   The complete stylesheet. Loaded non-render-blocking from every page, with a
   <noscript> fallback so it still applies when JavaScript is disabled.

   Sections 1–8 duplicate assets/css/critical.css so this file works standalone
   (the <noscript> path has no inlined block to rely on). Change a token here,
   change it there too, then re-sync the inlined blocks.

   DIRECTION — luxury through engineering precision, not ornament. The visual
   vernacular is a technical specimen sheet: black, gold-stamped, monospace
   annotation, hairline rules, obsessive alignment. Three devices carry it:
   the annotation rail, the Citation Block, and ruled editorial rows.

   CONTENTS
     1.  Tokens          9.  Section furniture   17. Glossary
     2.  Reset & base    10. Editorial rows      18. Breadcrumbs
     3.  Focus/skip      11. Citation Block      19. Forms
     4.  Layout + rail   12. Stats               20. Map
     5.  Header          13. Process             21. Footer
     6.  Buttons         14. Panels & CTA        22. Mobile CTA
     7.  Hero            15. Tables              23. Motion
     8.  Navigation      16. Testimonials        24. Utilities
   ========================================================================== */

/* ==========================================================================
   1. TOKENS  (mirrors critical.css)
   ========================================================================== */
:root {
  --bg-void: #0a0a0b;
  --bg-raised: #111113;
  --bg-panel: #16161a;
  --bg-elevated: #1c1c21;

  /* Terracotta sampled from the "M" of MiRV in the logo. 3.99:1 on void —
     fills, borders and large text only. Labels on it must be --on-red. */
  --red-primary: #c74135;
  --red-deep: #8e2a21;
  --red-bright: #d6584a;
  --red-text: #e8776a; /* 6.9:1 — error text */
  --red-glow: rgba(199, 65, 53, 0.34);
  --on-red: #ffffff; /* 4.96:1 on --red-primary; --text-body is 4.37:1 and fails */

  --gold: #d4af37;
  --gold-dim: #c5a028;
  --gold-glow: rgba(212, 175, 55, 0.2);

  --text-body: #f5f0e8;
  --text-muted: #a8a29a;
  --text-faint: #8a857d;

  --line: rgba(245, 240, 232, 0.09);
  --line-strong: rgba(245, 240, 232, 0.16);
  --line-gold: rgba(212, 175, 55, 0.3);

  --font-display: "Bodoni Moda", "Didot", "Bodoni MT", "Times New Roman", serif;
  --font-body: "Jost", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas,
    monospace;

  --fs-mono: 0.6875rem;
  --fs-xs: 0.75rem;
  --fs-sm: 0.875rem;
  --fs-base: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --fs-lg: clamp(1.0625rem, 0.99rem + 0.35vw, 1.25rem);
  --fs-xl: clamp(1.25rem, 1.12rem + 0.6vw, 1.5rem);
  --fs-2xl: clamp(1.75rem, 1.4rem + 1.6vw, 2.5rem);
  --fs-3xl: clamp(2rem, 1.45rem + 2.6vw, 3.5rem);
  --fs-4xl: clamp(2.5rem, 1.7rem + 3.9vw, 4.5rem);
  --fs-hero: clamp(2.875rem, 1.5rem + 6.6vw, 7rem);

  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4rem;
  --sp-9: 6rem;

  --container: 82rem;
  --container-narrow: 48rem;
  --gutter: clamp(1.25rem, 4vw, 4rem);
  --section-y: clamp(4.5rem, 9vw, 9.5rem);
  --header-h: 5.25rem;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --dur-fast: 180ms;
  --dur: 260ms;
  --dur-slow: 700ms;

  --radius: 2px;
  --radius-lg: 3px;
}

/* ==========================================================================
   2. RESET & BASE
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
  /* `clip` not `hidden`: the off-canvas drawer is fixed at translateX(100%)
     and still extends scrollable overflow in Chromium. `hidden` would force
     overflow-y to auto and break the sticky header. */
  overflow-x: clip;
}

body {
  background: var(--bg-void);
  color: var(--text-body);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  font-weight: 300;
  line-height: 1.75;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

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

/* Display face is a Didone — barred below 1.75rem, where its hairlines
   optically vanish on near-black. Anything smaller uses the body face. */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.04;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h5, h6 {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}

p { text-wrap: pretty; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
ul, ol { padding: 0; list-style: none; }

/* .hero__lede and .text-muted are included here because a link inside either
   would otherwise inherit the muted body colour and be indistinguishable from
   plain text — a WCAG 1.4.1 failure, since colour alone would not even be
   carrying it. Any standalone paragraph outside .prose that contains a link
   should use .text-muted so it picks this up. */
.prose a, .rich-text a, .hero__lede a, .text-muted a {
  color: var(--gold);
  text-decoration: underline;
  text-decoration-color: var(--line-gold);
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
  transition: color var(--dur) var(--ease-soft), text-decoration-color var(--dur) var(--ease-soft);
}
.prose a:hover, .rich-text a:hover, .hero__lede a:hover, .text-muted a:hover { color: #f0d97a; text-decoration-color: var(--gold); }

code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  color: var(--gold);
}

/* ==========================================================================
   3. FOCUS & SKIP LINK
   ========================================================================== */
:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; border-radius: var(--radius); }

.skip-link {
  position: absolute; left: var(--sp-4); top: -100%; z-index: 200;
  display: inline-flex; align-items: center; min-height: 2.75rem;
  padding: var(--sp-3) var(--sp-5);
  background: var(--red-primary); color: var(--on-red);
  font-family: var(--font-mono); font-size: var(--fs-mono);
  letter-spacing: 0.12em; text-transform: uppercase;
  transition: top var(--dur) var(--ease-out);
}
.skip-link:focus { top: var(--sp-4); }

.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* Spam honeypot. display:none rather than .visually-hidden on purpose: that
   utility deliberately KEEPS content in the accessibility tree, which is the
   opposite of what a trap field needs, and hiding a focusable control behind
   aria-hidden is an ARIA violation. Bots parse the HTML and fill it anyway. */
.form__trap { display: none; }

/* ==========================================================================
   4. LAYOUT + THE ANNOTATION RAIL
   --------------------------------------------------------------------------
   The rail is the signature structural device. Its content is REAL TEXT in
   real elements — never CSS `content:`, which crawlers cannot read. It carries
   true information: the schema type each section emits, permitted crawlers,
   the section index.
   ========================================================================== */
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.container--narrow { max-width: var(--container-narrow); }

.section {
  position: relative;
  padding-block: var(--section-y);
  /* `clip` contains the oversized ghost type without creating a scroll
     container, so position:sticky inside the rail still works. */
  overflow: clip;
}
.section--raised { background: var(--bg-raised); }
.section--hairline { border-top: 1px solid var(--line); }

/* Oversized architectural type sitting behind content as a depth layer.
   aria-hidden in the markup; carries no meaning. */
.ghost-type {
  position: absolute; z-index: 0; pointer-events: none; user-select: none;
  font-family: var(--font-display);
  font-size: clamp(7rem, 20vw, 18rem);
  line-height: 0.76; letter-spacing: -0.06em;
  color: transparent;
  -webkit-text-stroke: 1px rgba(245, 240, 232, 0.05);
  white-space: nowrap;
}
.ghost-type--right { top: -0.1em; right: 0; }
.ghost-type--left { top: -0.1em; left: 0; }
@media (max-width: 900px) { .ghost-type { display: none; } }

/* ==========================================================================
   5. HEADER
   ========================================================================== */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(10, 10, 11, 0.86);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border-bottom: 1px solid var(--line);
}
.site-header__inner { display: flex; align-items: center; gap: var(--sp-5); min-height: var(--header-h); }

.brand { display: flex; align-items: center; margin-right: auto; padding-block: var(--sp-2); flex-shrink: 0; }

/* The complete logo artwork, used exactly as supplied. Sized by height with
   width:auto; the intrinsic width/height attributes reserve the box so the
   header never shifts as the image decodes. */
.brand__logo { height: 3.25rem; width: auto; flex-shrink: 0; transition: opacity var(--dur) var(--ease-soft); }
@media (min-width: 768px) { .brand__logo { height: 3.75rem; } }
.brand:hover .brand__logo { opacity: 0.85; }

/* ==========================================================================
   6. BUTTONS
   ========================================================================== */
.btn {
  --btn-bg: transparent; --btn-fg: var(--text-body); --btn-border: var(--line-strong);
  position: relative; display: inline-flex; align-items: center; justify-content: center; gap: 0.55rem;
  min-height: 3rem; padding: 0.85rem 1.6rem;
  background: var(--btn-bg); color: var(--btn-fg);
  border: 1px solid var(--btn-border); border-radius: var(--radius);
  font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase; text-align: center;
  cursor: pointer; overflow: hidden; isolation: isolate;
  transition: color var(--dur) var(--ease-soft), border-color var(--dur) var(--ease-soft),
    box-shadow var(--dur) var(--ease-soft), transform var(--dur) var(--ease-soft);
}
.btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--btn-sweep, transparent);
  transform: scaleX(0); transform-origin: left center;
  transition: transform var(--dur-slow) var(--ease-out);
}
.btn:hover::before, .btn:focus-visible::before { transform: scaleX(1); }
.btn:active { transform: translateY(1px); }

.btn--primary {
  --btn-bg: var(--red-primary); --btn-fg: var(--on-red); --btn-border: var(--red-primary);
  --btn-sweep: linear-gradient(90deg, var(--red-deep), var(--red-primary));
}
.btn--primary:hover, .btn--primary:focus-visible {
  border-color: var(--red-bright);
  box-shadow: 0 0 0 1px var(--red-glow), 0 14px 36px -14px var(--red-glow);
}
.btn--secondary { --btn-fg: var(--gold); --btn-border: var(--line-gold); --btn-sweep: var(--gold-glow); }
.btn--secondary:hover, .btn--secondary:focus-visible {
  --btn-fg: #f0d97a; border-color: var(--gold);
  box-shadow: 0 0 0 1px var(--gold-glow), 0 14px 36px -16px var(--gold-glow);
}
.btn--full { width: 100%; }

.link-arrow {
  display: inline-flex; align-items: center; gap: 0.55rem; min-height: 2.75rem;
  color: var(--gold);
  font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase;
  transition: color var(--dur) var(--ease-soft), gap var(--dur) var(--ease-soft);
}
.link-arrow::after { content: ""; width: 1.5rem; height: 1px; background: currentColor; transition: width var(--dur) var(--ease-out); }
.link-arrow:hover, .link-arrow:focus-visible { color: #f0d97a; gap: 0.75rem; }
.link-arrow:hover::after, .link-arrow:focus-visible::after { width: 2.5rem; }

/* ==========================================================================
   7. HERO
   ========================================================================== */
.hero { position: relative; isolation: isolate; overflow: hidden; padding-block: clamp(3.5rem, 8vw, 7rem) clamp(3rem, 7vw, 6rem); }
.hero--page { padding-block: clamp(3rem, 6vw, 5rem) clamp(2.5rem, 5vw, 4rem); }
.hero__bg {
  position: absolute; inset: -25% -12%; z-index: -2; pointer-events: none;
  background:
    radial-gradient(46rem 32rem at 14% 6%, rgba(142, 42, 33, 0.36), transparent 66%),
    radial-gradient(34rem 26rem at 92% 84%, rgba(212, 175, 55, 0.12), transparent 64%),
    radial-gradient(54rem 42rem at 62% 44%, rgba(199, 65, 53, 0.13), transparent 70%);
}
.hero__grain { position: absolute; inset: 0; z-index: -1; pointer-events: none; opacity: 0.55; background-image: radial-gradient(circle at 46% 42%, transparent 0, var(--bg-void) 76%); }

/* --------------------------------------------------------------------------
   Desktop hero visual
   --------------------------------------------------------------------------
   Hidden entirely below 1024px, and declared as a background image rather than
   an <img> so that mobile never downloads the 124KB file — a display:none
   <img> still fetches its src, a background on an unrendered element does not.

   Stacking inside .hero (which sets isolation: isolate):
     -3  hero__bg     ambient colour wash
     -2  hero__visual the render
     -1  hero__grain  vignette
     -1  ::after      the readability scrim, painted after the grain
      0  content
   -------------------------------------------------------------------------- */
.hero__visual { display: none; }

@media (min-width: 1024px) {
  .hero__bg { z-index: -3; }

  .hero__visual {
    display: block;
    position: absolute;
    z-index: -2;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    width: min(54vw, 860px);
    aspect-ratio: 921 / 1024;
    max-height: 118%;
    background-image: url("/assets/img/mirv-elements-hero.jpg");
    background-size: contain;
    background-position: right center;
    background-repeat: no-repeat;
    pointer-events: none;
  }

  /* The scrim. Three stacked gradients: fade the image out toward the text
     column, and soften its top and bottom into the page so the crop edges
     never read as a hard rectangle. Without this the headline would sit over
     the laptop screen and lose contrast. */
  .hero__visual::after {
    content: "";
    position: absolute;
    inset: 0;
    background:
      linear-gradient(90deg, var(--bg-void) 0%, rgba(10, 10, 11, 0.9) 20%, rgba(10, 10, 11, 0.4) 44%, rgba(10, 10, 11, 0) 70%),
      linear-gradient(180deg, var(--bg-void) 0%, rgba(10, 10, 11, 0) 22%),
      linear-gradient(0deg, var(--bg-void) 0%, rgba(10, 10, 11, 0) 24%);
  }

  /* The headline is ALLOWED to cross over the render — that overlap is the
     composition, and boxing the copy into the left half forced the h1 into
     four cramped lines. It only works because of the scrim above: by the time
     the text reaches the image it sits on the opaque end of that gradient
     rather than on the artwork.

     VERIFIED, not assumed. The hero was re-rendered with the copy hidden and
     every pixel inside the measured text boxes sampled for luminance against
     --text-body (#F5F0E8, L=0.878). Worst case of all of them:

       width   headline   lede      buttons
       1024    9.9:1      16.6:1    12.3:1
       1280    10.0:1     16.8:1    13.3:1
       1440    7.0:1      17.0:1    13.7:1     <- worst
       1920    16.6:1     17.1:1    17.2:1

     7:1 clears AA for NORMAL text, so it is not leaning on the large-text
     exemption the h1 would qualify for. If the hero image is ever replaced,
     re-run that sampling before trusting these widths — a lighter render
     could put the headline under 4.5:1 without anything here changing.

     The lede stays narrower on purpose: a long measure over a busy background
     is harder to read than one short display line, and it has no reason to
     reach that far. */
  .hero__content { max-width: 72%; }
  .hero__content .hero__title {
    max-width: 17ch;
    font-size: clamp(2.75rem, 5.4vw, 5.5rem);
  }
  .hero__content .hero__lede { max-width: 44ch; font-size: var(--fs-base); }
}

@media (min-width: 1280px) {
  .hero__content { max-width: 68%; }
  .hero__content .hero__lede { font-size: var(--fs-lg); }
}

/* --------------------------------------------------------------------------
   Interior-page hero schematic
   --------------------------------------------------------------------------
   The same job .hero__visual does on the homepage, in a different medium:
   inline SVG rather than a photograph, so it costs about 2KB of markup instead
   of a 124KB JPEG and stays sharp at any pixel density. Services, About, Work,
   FAQ and Contact each get their own composition.

   Desktop only. Below 1024px the copy needs the whole column and the drawing
   would be too small to read as anything.

   The blend is a MASK, not a dark scrim. A mask fades the artwork itself to
   nothing as it approaches the headline; a scrim would instead lay a grey veil
   over hairline geometry and turn it to mud. Where mask-image is unsupported
   the drawing simply shows unmasked, which is still fine, because every
   composition is weighted into the right third of its viewBox and the headline
   never reaches it.

   Duplicated into critical.css — see the note there for why.
   -------------------------------------------------------------------------- */
.hero__figure { display: none; }

@media (min-width: 1024px) {
  .hero__figure {
    display: block;
    position: absolute;
    z-index: -2;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    width: min(46vw, 34rem);
    aspect-ratio: 640 / 560;
    max-height: 116%;
    opacity: 0.92;
    pointer-events: none;
    -webkit-mask-image: linear-gradient(96deg, transparent 6%, rgba(0, 0, 0, 0.26) 30%, rgba(0, 0, 0, 0.72) 54%, #000 78%);
    mask-image: linear-gradient(96deg, transparent 6%, rgba(0, 0, 0, 0.26) 30%, rgba(0, 0, 0, 0.72) 54%, #000 78%);
  }
  /* See the note in critical.css: SVG's default fill is black, and the hero
     sits on a warm wash rather than flat void, so an unstyled shape would show
     as a black blob during first paint. Inherited none prevents that. */
  .hero__figure svg { display: block; width: 100%; height: 100%; fill: none; }

  /* Keep the copy clear of the drawing. */
  .hero--page .hero__body { max-width: 58%; }
  .hero--page .hero__body .hero__title { max-width: 16ch; }
  .hero--page .hero__body .hero__lede { max-width: 44ch; }
}

.eyebrow {
  display: flex; align-items: center; gap: 0.7rem;
  font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: 0.24em; text-transform: uppercase; color: var(--gold);
  margin-bottom: var(--sp-5);
}
.eyebrow::before { content: ""; width: 1.75rem; height: 1px; background: var(--line-gold); flex-shrink: 0; }

.hero__title { max-width: 15ch; font-size: var(--fs-hero); line-height: 0.94; letter-spacing: -0.035em; }
.hero__title em { font-style: italic; color: var(--gold); }
.hero--page .hero__title { font-size: var(--fs-4xl); max-width: 20ch; }
.hero__lede { max-width: 50ch; margin-top: var(--sp-5); color: var(--text-muted); font-size: var(--fs-lg); line-height: 1.7; }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-top: var(--sp-6); }

/* Cursor-follow glow — fine pointers on desktop only, positioned by script. */
.cursor-glow {
  position: fixed; top: 0; left: 0; z-index: 1;
  width: 34rem; height: 34rem; margin: -17rem 0 0 -17rem;
  pointer-events: none; opacity: 0;
  background: radial-gradient(circle, rgba(199, 65, 53, 0.09), transparent 62%);
  transition: opacity 600ms var(--ease-soft);
  will-change: transform;
}

/* ==========================================================================
   8. NAVIGATION
   ========================================================================== */
.nav-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.875rem; height: 2.875rem; margin-right: -0.5rem;
  background: none; border: 1px solid var(--line); border-radius: var(--radius); cursor: pointer;
  transition: border-color var(--dur) var(--ease-soft);
}
.nav-toggle:hover { border-color: var(--line-gold); }
.nav-toggle__bars, .nav-toggle__bars::before, .nav-toggle__bars::after {
  display: block; width: 1.125rem; height: 1.5px; background: var(--text-body);
  transition: transform var(--dur) var(--ease-out), opacity var(--dur-fast) var(--ease-soft);
}
.nav-toggle__bars::before, .nav-toggle__bars::after { content: ""; position: absolute; }
.nav-toggle__bars::before { transform: translateY(-0.35rem); }
.nav-toggle__bars::after { transform: translateY(0.35rem); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before { transform: rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after { transform: rotate(-45deg); }

.nav-backdrop {
  position: fixed; inset: 0; z-index: 98;
  background: rgba(10, 10, 11, 0.72); backdrop-filter: blur(3px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur) var(--ease-soft), visibility var(--dur) var(--ease-soft);
}
.nav-backdrop[data-open="true"] { opacity: 1; visibility: visible; }

.site-nav {
  position: fixed; inset-block: 0; right: 0; z-index: 99;
  width: min(23rem, 88vw);
  padding: calc(var(--header-h) + var(--sp-6)) var(--sp-6) var(--sp-7);
  background: var(--bg-raised); border-left: 1px solid var(--line);
  overflow-y: auto; overscroll-behavior: contain;
  transform: translateX(100%); visibility: hidden;
  transition: transform 380ms var(--ease-out), visibility 380ms var(--ease-out);
}
.site-nav[data-open="true"] { transform: translateX(0); visibility: visible; }
.site-nav__list { display: flex; flex-direction: column; gap: var(--sp-1); }
.site-nav__link {
  display: flex; align-items: center; min-height: 3.25rem; padding: var(--sp-2) 0;
  color: var(--text-muted);
  font-family: var(--font-display); font-size: var(--fs-xl); letter-spacing: 0;
  border-bottom: 1px solid var(--line);
  transition: color var(--dur) var(--ease-soft), padding-left var(--dur) var(--ease-out);
}
.site-nav__link:hover, .site-nav__link:focus-visible { color: var(--text-body); padding-left: var(--sp-2); }
.site-nav__link[aria-current="page"] { color: var(--gold); }
.site-nav__cta { margin-top: var(--sp-6); }

@media (min-width: 1024px) {
  .nav-backdrop { display: none; }
  .site-nav {
    position: static; display: flex; align-items: center; gap: var(--sp-6);
    width: auto; padding: 0; background: none; border: 0; overflow: visible;
    transform: none; visibility: visible; transition: none;
  }
  .site-nav__list { flex-direction: row; align-items: center; gap: var(--sp-6); }
  .site-nav__link {
    position: relative; min-height: 2.75rem; padding: 0;
    font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500;
    letter-spacing: 0.14em; text-transform: uppercase;
    border: 0;
  }
  .site-nav__link:hover, .site-nav__link:focus-visible { padding-left: 0; }
  .site-nav__link::after {
    content: ""; position: absolute; left: 0; bottom: 0.5rem; width: 100%; height: 1px;
    background: var(--red-primary); transform: scaleX(0); transform-origin: left center;
    transition: transform var(--dur) var(--ease-out);
  }
  .site-nav__link:hover::after, .site-nav__link:focus-visible::after, .site-nav__link[aria-current="page"]::after { transform: scaleX(1); }
  .site-nav__cta { margin-top: 0; }
}

/* ==========================================================================
   9. SECTION FURNITURE
   ========================================================================== */
.section__head { margin-bottom: var(--sp-8); }
.section__title { max-width: 20ch; font-size: var(--fs-3xl); }
.section__title em { font-style: italic; color: var(--gold); }
.section__lede { max-width: 56ch; margin-top: var(--sp-5); color: var(--text-muted); font-size: var(--fs-lg); }

.prose > * + * { margin-top: var(--sp-5); }
.prose p, .prose li { color: var(--text-muted); }
.prose h3 { margin-top: var(--sp-7); color: var(--text-body); font-size: var(--fs-2xl); }
/* h4 exists so a sub-topic inside a service (e.g. occasion websites under
   Website Development) can carry its own "What's included" without repeating
   an h3 and muddying the heading outline. */
.prose h4 { margin-top: var(--sp-6); color: var(--text-body); font-size: var(--fs-xl); }
/* .text-gold is a (0,1,0) utility and would lose to `.prose h3` (0,1,1),
   which sets the body colour. These pairings out-specify it. */
.prose h3.text-gold, .prose h4.text-gold { color: var(--gold); }
.prose strong { color: var(--text-body); font-weight: 500; }

.checklist { display: grid; gap: var(--sp-3); }
.checklist li { position: relative; padding-left: 1.9rem; color: var(--text-muted); }
.checklist li::before {
  content: ""; position: absolute; left: 0; top: 0.75em;
  width: 0.5rem; height: 0.5rem;
  border-top: 1px solid var(--gold); border-right: 1px solid var(--gold);
  transform: rotate(45deg);
}

/* ==========================================================================
   10. EDITORIAL ROWS
   --------------------------------------------------------------------------
   Services as a ruled specimen index rather than a card grid. Number, name,
   tier, one line. Cards were the templated answer.
   ========================================================================== */
.rows { border-top: 1px solid var(--line); }

.row-item {
  position: relative;
  display: grid;
  grid-template-columns: 2.75rem minmax(0, 1fr);
  gap: 0 var(--sp-4);
  align-items: baseline;
  padding-block: var(--sp-5);
  border-bottom: 1px solid var(--line);
  transition: background var(--dur) var(--ease-soft);
}
@media (min-width: 900px) {
  .row-item { grid-template-columns: 3.5rem minmax(0, 1.1fr) minmax(0, 1fr) auto; gap: 0 var(--sp-6); align-items: baseline; }
}

.row-item::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--gold); transform: scaleX(0); transform-origin: left center;
  transition: transform var(--dur-slow) var(--ease-out);
}
.row-item:hover::before, .row-item:focus-within::before { transform: scaleX(1); }

/* --red-text, not --red-primary. At 11px these are small text and need 4.5:1;
   the terracotta fill colour only reaches 3.8:1. Same hue family, AA-safe. */
.row-item__num { font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500; color: var(--red-text); letter-spacing: 0.08em; }
.row-item__name { font-family: var(--font-display); font-size: var(--fs-2xl); color: var(--text-body); line-height: 1.08; }
.row-item__desc { color: var(--text-muted); font-size: var(--fs-sm); line-height: 1.7; grid-column: 2 / -1; margin-top: var(--sp-2); }
.row-item__tier { font-family: var(--font-mono); font-size: var(--fs-mono); color: var(--text-faint); letter-spacing: 0.14em; text-transform: uppercase; grid-column: 2 / -1; margin-top: var(--sp-2); }

@media (min-width: 900px) {
  .row-item__desc { grid-column: 3; margin-top: 0; }
  .row-item__tier { grid-column: 4; margin-top: 0; text-align: right; }
}

/* Whole row clickable while the real link stays the keyboard target */
.row-item__link::after { content: ""; position: absolute; inset: 0; z-index: 1; }

/* ==========================================================================
   SERVICE CARDS
   --------------------------------------------------------------------------
   The homepage service grid. Four across on wide screens, degrading to three,
   two, then one. Each card is a single link target; the anchor's ::after
   covers the card so the whole tile is clickable while the anchor stays the
   keyboard focus target and the accessible name.
   ========================================================================== */
.svc-grid {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: 1fr;
}
@media (min-width: 560px) { .svc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .svc-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .svc-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.svc-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: var(--sp-5);
  min-height: 15rem;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  isolation: isolate;
  overflow: hidden;
  transition: transform var(--dur) var(--ease-out),
    border-color var(--dur) var(--ease-soft),
    background var(--dur) var(--ease-soft);
}

/* Gold wash, revealed on hover */
.svc-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(158deg, rgba(212, 175, 55, 0.08), transparent 58%);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-soft);
}
.svc-card:hover, .svc-card:focus-within {
  transform: translateY(-4px);
  border-color: var(--line-gold);
  background: var(--bg-elevated);
}
.svc-card:hover::before, .svc-card:focus-within::before { opacity: 1; }

.svc-card__icon {
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  flex-shrink: 0;
  border-radius: 50%;
  color: var(--gold);
  background: rgba(212, 175, 55, 0.09);
  border: 1px solid rgba(212, 175, 55, 0.18);
  transition: background var(--dur) var(--ease-soft), border-color var(--dur) var(--ease-soft);
}
.svc-card__icon svg { width: 1.375rem; height: 1.375rem; }
.svc-card:hover .svc-card__icon { background: rgba(212, 175, 55, 0.16); border-color: var(--line-gold); }

/* Bodoni normally has a 1.75rem floor on this site — below that its hairlines
   optically vanish on near-black. At card width the full service names need to
   sit smaller than that, so weight 500 thickens the strokes to compensate.
   This is the one sanctioned exception; do not copy it to lighter weights. */
.svc-card__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.2rem, 1.08rem + 0.4vw, 1.4rem);
  line-height: 1.18;
  letter-spacing: -0.01em;
  color: var(--text-body);
}
.svc-card__title a { display: inline; }
.svc-card__title a::after { content: ""; position: absolute; inset: 0; z-index: 1; }

.svc-card__text {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  line-height: 1.65;
  margin-top: auto;
}

/* ==========================================================================
   11. THE CITATION BLOCK — the signature
   --------------------------------------------------------------------------
   One self-contained factual sentence, framed as the passage a machine will
   lift. Simultaneously the visual signature and the GEO payload.
   ========================================================================== */
.citation {
  position: relative;
  padding: var(--sp-6) 0 var(--sp-6) var(--sp-6);
  border-left: 2px solid var(--gold);
  background: linear-gradient(90deg, rgba(212, 175, 55, 0.055), transparent 55%);
  max-width: 62rem;
}
.citation__meta {
  font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--text-muted);
}
.citation__quote {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  line-height: 1.32;
  color: var(--text-body);
  margin-top: var(--sp-4);
  font-weight: 400;
}
.citation__quote em { font-style: italic; color: var(--gold); }
.citation__source {
  display: block; margin-top: var(--sp-5);
  font-family: var(--font-mono); font-size: var(--fs-mono);
  letter-spacing: 0.06em; color: var(--text-faint); font-style: normal;
}

/* Pull-quote, the lighter cousin used inside prose */
.pull-quote {
  margin-block: var(--sp-6);
  padding-left: var(--sp-5);
  border-left: 2px solid var(--red-primary);
  color: var(--text-body);
  font-family: var(--font-display); font-size: var(--fs-xl);
  font-style: italic; line-height: 1.4;
}

/* ==========================================================================
   12. STATS
   ========================================================================== */
.stats { display: grid; gap: var(--sp-6); grid-template-columns: repeat(2, 1fr); }
@media (min-width: 768px) { .stats { grid-template-columns: repeat(4, 1fr); } }

.stat { padding-top: var(--sp-4); border-top: 1px solid var(--line-gold); }
.stat__value {
  display: block; color: var(--gold);
  font-family: var(--font-display); font-size: var(--fs-3xl);
  line-height: 1; font-variant-numeric: tabular-nums;
}
.stat__label { display: block; margin-top: var(--sp-3); color: var(--text-muted); font-size: var(--fs-sm); line-height: 1.55; }

.trust-bar {
  display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-6);
  align-items: center; padding-block: var(--sp-5);
  border-block: 1px solid var(--line);
}
.trust-bar__item {
  display: inline-flex; align-items: center; gap: 0.6rem;
  color: var(--text-faint);
  font-family: var(--font-mono); font-size: var(--fs-mono);
  letter-spacing: 0.16em; text-transform: uppercase;
}
.trust-bar__item::before { content: ""; width: 0.3rem; height: 0.3rem; background: var(--red-primary); transform: rotate(45deg); flex-shrink: 0; }

/* ==========================================================================
   13. PROCESS
   ========================================================================== */
.steps { display: grid; gap: var(--sp-6); }
@media (min-width: 768px) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1200px) { .steps--5 { grid-template-columns: repeat(5, 1fr); } }

.step { position: relative; padding-top: var(--sp-5); border-top: 1px solid var(--line); transition: border-color var(--dur) var(--ease-soft); }
.step:hover { border-color: var(--line-gold); }
.step__num { display: block; margin-bottom: var(--sp-3); color: var(--red-text); font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500; letter-spacing: 0.14em; }
.step__title { font-family: var(--font-display); font-size: var(--fs-xl); color: var(--text-body); letter-spacing: -0.01em; }
.step__text { margin-top: var(--sp-3); color: var(--text-muted); font-size: var(--fs-sm); line-height: 1.7; }

/* ==========================================================================
   14. PANELS & CTA BAND
   ========================================================================== */
.panel { position: relative; padding: var(--sp-6); background: var(--bg-panel); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; }
@media (min-width: 768px) { .panel { padding: var(--sp-7); } }
.panel--accent { border-color: var(--line-gold); background: linear-gradient(155deg, var(--bg-panel), rgba(142, 42, 33, 0.16) 140%); }
.panel__num { display: block; margin-bottom: var(--sp-4); color: var(--gold); font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; }
.panel__title { font-size: var(--fs-2xl); }
.panel__text { margin-top: var(--sp-4); color: var(--text-muted); }
.panel__text + .panel__text { margin-top: var(--sp-4); }

/* Plain responsive grid. The only remaining user is the testimonial layout,
   where .testimonial supplies its own surface treatment — this just arranges
   them. Not a card style. */
.card-grid { display: grid; gap: var(--sp-5); grid-template-columns: 1fr; }
@media (min-width: 640px) { .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) {
  .card-grid--3 { grid-template-columns: repeat(3, 1fr); }
  .card-grid--4 { grid-template-columns: repeat(4, 1fr); }
}

.split { display: grid; gap: var(--sp-7); align-items: start; }
@media (min-width: 1024px) {
  .split { grid-template-columns: 0.85fr 1.15fr; gap: var(--sp-8); }
  .split--reverse { grid-template-columns: 1.15fr 0.85fr; }

  /* Alternating services. The heading column moves to the right visually while
     staying FIRST in the DOM, so the h2 still precedes the prose it titles for
     screen readers, crawlers and a JS-disabled read. Only the paint order
     changes — which is exactly what `order` is for, and why this is not done
     by rearranging the markup.
     Below 1024px the grid is a single column and none of this applies: the
     heading sits above its prose, which is the only sensible phone layout. */
  .split--flip { grid-template-columns: 1.15fr 0.85fr; }
  .split--flip > :first-child { order: 2; text-align: right; }
  .split--flip > :last-child { order: 1; }

  /* The eyebrow's leading rule is a ::before, so row-reverse both moves the
     rule to the right of the label and packs the pair against the right edge
     (in row-reverse, flex-start IS the right edge). */
  .split--flip .eyebrow { flex-direction: row-reverse; }

  /* These carry their own max-width, so they need pushing rather than just
     text-align to sit flush right. */
  .split--flip .section__title,
  .split--flip .section__lede { margin-left: auto; }
}

.cta-band { position: relative; isolation: isolate; overflow: hidden; padding-block: clamp(4.5rem, 10vw, 8rem); text-align: center; border-top: 1px solid var(--line); }
.cta-band__bg {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(42rem 26rem at 50% 110%, rgba(199, 65, 53, 0.3), transparent 66%),
    radial-gradient(28rem 18rem at 12% -10%, rgba(212, 175, 55, 0.1), transparent 64%);
}
.cta-band__title { max-width: 18ch; margin-inline: auto; font-size: var(--fs-3xl); }
.cta-band__title em { font-style: italic; color: var(--gold); }
.cta-band__text { max-width: 52ch; margin: var(--sp-5) auto 0; color: var(--text-muted); font-size: var(--fs-lg); }
.cta-band__actions { display: flex; flex-wrap: wrap; gap: var(--sp-4); justify-content: center; margin-top: var(--sp-6); }
.cta-band__note { margin-top: var(--sp-5); color: var(--text-faint); font-family: var(--font-mono); font-size: var(--fs-mono); letter-spacing: 0.1em; }

/* ==========================================================================
   15. TABLES
   ========================================================================== */
.table-scroll { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-lg); -webkit-overflow-scrolling: touch; }
.table { width: 100%; min-width: 46rem; border-collapse: collapse; font-size: var(--fs-sm); }
.table caption { padding: var(--sp-4) var(--sp-5); color: var(--text-faint); font-family: var(--font-mono); font-size: var(--fs-mono); letter-spacing: 0.06em; text-align: left; border-bottom: 1px solid var(--line); }
.table th, .table td { padding: var(--sp-4) var(--sp-5); text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
.table thead th {
  position: sticky; top: 0; background: var(--bg-elevated); color: var(--gold);
  font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase; white-space: nowrap;
}
.table tbody th { color: var(--text-body); font-family: var(--font-body); font-weight: 500; letter-spacing: 0; }
.table td { color: var(--text-muted); }
.table tbody tr:last-child th, .table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background var(--dur) var(--ease-soft); }
.table tbody tr:hover { background: rgba(245, 240, 232, 0.025); }
.table__yes { color: var(--gold); font-family: var(--font-mono); font-size: var(--fs-mono); letter-spacing: 0.08em; text-transform: uppercase; }
.table__no { color: var(--text-faint); }

/* ==========================================================================
   16. FAQ / TESTIMONIALS / CASE STUDY
   ========================================================================== */
.faq-list { display: grid; gap: 0; border-top: 1px solid var(--line); }
.faq-item { border-bottom: 1px solid var(--line); }
/* Answers start COLLAPSED and open on click. <details> keeps the full answer
   text in the served HTML either way, so crawlers still read every word and
   the FAQPage schema stays valid — Google explicitly supports accordions for
   FAQ markup. No JavaScript is involved; this is native <details> behaviour,
   so it still works with scripting disabled. */
.faq-item summary {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-4);
  min-height: 3.5rem; padding-block: var(--sp-5);
  cursor: pointer; list-style: none;
  color: var(--text-body); font-family: var(--font-display); font-size: var(--fs-xl);
  line-height: 1.25; transition: color var(--dur) var(--ease-soft);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover { color: var(--gold); }
.faq-item__icon { position: relative; flex-shrink: 0; width: 1rem; height: 1rem; margin-top: 0.5em; }
.faq-item__icon::before, .faq-item__icon::after { content: ""; position: absolute; top: 50%; left: 0; width: 100%; height: 1px; background: var(--gold); transition: transform var(--dur) var(--ease-out); }
.faq-item__icon::after { transform: rotate(90deg); }
.faq-item[open] .faq-item__icon::after { transform: rotate(0deg); }
.faq-item__answer { padding-bottom: var(--sp-5); max-width: 68ch; }
.faq-item__answer p { color: var(--text-muted); }
.faq-item__answer p + p { margin-top: var(--sp-4); }

.notice { display: flex; gap: var(--sp-4); padding: var(--sp-5); background: var(--bg-panel); border: 1px solid var(--line-gold); border-left-width: 2px; border-radius: var(--radius-lg); }
.notice__icon { flex-shrink: 0; width: 1.5rem; height: 1.5rem; margin-top: 0.15rem; color: var(--gold); }
.notice__title { color: var(--text-body); font-family: var(--font-body); font-size: var(--fs-base); font-weight: 500; }
.notice__text { margin-top: var(--sp-2); color: var(--text-muted); font-size: var(--fs-sm); }

.testimonial { display: flex; flex-direction: column; gap: var(--sp-4); padding: var(--sp-6); background: var(--bg-panel); border: 1px solid var(--line); border-radius: var(--radius-lg); }
.testimonial--placeholder { border-style: dashed; border-color: var(--line-strong); background: transparent; }
.testimonial__mark { width: 1.75rem; height: 1.75rem; color: var(--red-primary); }
.testimonial__quote { color: var(--text-body); font-family: var(--font-display); font-size: var(--fs-xl); font-style: italic; line-height: 1.45; }
.testimonial--placeholder .testimonial__quote { color: var(--text-faint); }
.testimonial__cite { display: flex; align-items: center; gap: var(--sp-3); margin-top: auto; padding-top: var(--sp-4); border-top: 1px solid var(--line); font-style: normal; }
.testimonial__avatar { display: grid; place-items: center; width: 2.75rem; height: 2.75rem; flex-shrink: 0; border: 1px solid var(--line-strong); border-radius: 50%; color: var(--text-faint); font-size: var(--fs-sm); }
.testimonial__name { display: block; color: var(--text-body); font-size: var(--fs-sm); font-weight: 500; }
.testimonial--placeholder .testimonial__name { color: var(--text-faint); }
.testimonial__role { display: block; color: var(--text-faint); font-family: var(--font-mono); font-size: var(--fs-mono); }

.case-study { display: grid; gap: var(--sp-6); padding: var(--sp-6); background: var(--bg-panel); border: 1px solid var(--line); border-radius: var(--radius-lg); }
@media (min-width: 1024px) { .case-study { grid-template-columns: 1fr 1.4fr; gap: var(--sp-8); padding: var(--sp-8); } }
.case-study__tag { display: inline-block; padding: 0.35rem 0.75rem; border: 1px solid var(--line-gold); border-radius: var(--radius); color: var(--gold); font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500; letter-spacing: 0.16em; text-transform: uppercase; }
/* When the case study carries only its spec block — no prose column beside it —
   the 1fr/1.4fr grid would leave the right 58% empty. Go single column and lay
   the spec out in two, so it reads as a data sheet rather than a stranded list. */
@media (min-width: 1024px) { .case-study--solo { grid-template-columns: 1fr; } }
@media (min-width: 700px) {
  .case-study--solo .case-study__meta { grid-template-columns: 1fr 1fr; gap: var(--sp-5) var(--sp-8); }
}
.case-study__meta { display: grid; gap: var(--sp-4); margin-top: var(--sp-5); }
.case-study__meta dt { color: var(--text-faint); font-family: var(--font-mono); font-size: var(--fs-mono); letter-spacing: 0.16em; text-transform: uppercase; }
.case-study__meta dd { margin: var(--sp-1) 0 0; color: var(--text-body); font-size: var(--fs-sm); }

/* Marks unresolved placeholder copy so it cannot ship by accident */
.placeholder-flag {
  display: inline-block; padding: 0.1rem 0.5rem;
  background: rgba(199, 65, 53, 0.18); border: 1px dashed var(--red-text); border-radius: var(--radius);
  color: var(--red-text); font-family: var(--font-mono); font-size: 0.625rem;
  font-style: normal; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; vertical-align: middle;
}

/* ==========================================================================
   17. GLOSSARY
   ========================================================================== */
.glossary { display: grid; gap: 0; border-top: 1px solid var(--line); }
.glossary__row { display: grid; gap: var(--sp-2); padding-block: var(--sp-5); border-bottom: 1px solid var(--line); }
@media (min-width: 768px) { .glossary__row { grid-template-columns: 17rem 1fr; gap: var(--sp-6); } }
.glossary__term { color: var(--gold); font-family: var(--font-display); font-size: var(--fs-xl); line-height: 1.25; }
.glossary__def { margin: 0; color: var(--text-muted); max-width: 68ch; }

/* ==========================================================================
   18. BREADCRUMBS
   ========================================================================== */
/* Vertical padding is on the links, not the bar: that gives each one a 44px
   touch target without the breadcrumb strip becoming a thick band. */
.breadcrumbs { border-bottom: 1px solid var(--line); }
.breadcrumbs__list { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; font-family: var(--font-mono); font-size: var(--fs-mono); letter-spacing: 0.12em; text-transform: uppercase; }
.breadcrumbs__list li { display: flex; align-items: center; gap: 0.5rem; color: var(--text-faint); }
.breadcrumbs__list li + li::before { content: "/"; color: var(--line-strong); }
.breadcrumbs a,
.breadcrumbs [aria-current="page"] { display: inline-flex; align-items: center; min-height: 2.75rem; }
.breadcrumbs a { color: var(--text-muted); transition: color var(--dur) var(--ease-soft); }
.breadcrumbs a:hover { color: var(--gold); }
.breadcrumbs [aria-current="page"] { color: var(--text-body); }

/* ==========================================================================
   19. FORMS
   ========================================================================== */
.form { display: grid; gap: var(--sp-5); }
.form__row { display: grid; gap: var(--sp-5); }
@media (min-width: 768px) { .form__row--2 { grid-template-columns: repeat(2, 1fr); } }

.field { display: grid; gap: var(--sp-2); }
.field__label { color: var(--text-body); font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; }
.field__optional { color: var(--text-faint); }
.field__hint { color: var(--text-faint); font-size: var(--fs-xs); line-height: 1.55; }
.field__control {
  width: 100%; min-height: 3.25rem; padding: 0.85rem 1rem;
  background: var(--bg-panel); color: var(--text-body);
  border: 1px solid var(--line-strong); border-radius: var(--radius);
  font-size: var(--fs-base); appearance: none;
  transition: border-color var(--dur) var(--ease-soft), box-shadow var(--dur) var(--ease-soft), background var(--dur) var(--ease-soft);
}
textarea.field__control { min-height: 9.5rem; resize: vertical; line-height: 1.7; }
select.field__control {
  background-image: linear-gradient(45deg, transparent 50%, var(--text-muted) 50%), linear-gradient(135deg, var(--text-muted) 50%, transparent 50%);
  background-position: calc(100% - 1.25rem) 1.5rem, calc(100% - 0.85rem) 1.5rem;
  background-size: 0.4rem 0.4rem, 0.4rem 0.4rem; background-repeat: no-repeat;
  padding-right: 2.75rem; cursor: pointer;
}
.field__control::placeholder { color: var(--text-faint); }
.field__control:hover { border-color: var(--line-gold); }
.field__control:focus { outline: none; background: var(--bg-elevated); border-color: var(--gold); box-shadow: 0 0 0 3px var(--gold-glow); }
.field__control[aria-invalid="true"] { border-color: var(--red-text); }
.field__control[aria-invalid="true"]:focus { border-color: var(--red-text); box-shadow: 0 0 0 3px rgba(232, 119, 106, 0.22); }

.field__error { display: none; align-items: center; gap: 0.4rem; color: var(--red-text); font-size: var(--fs-sm); }
.field__error:not(:empty) { display: flex; }

.checkbox-grid { display: grid; gap: var(--sp-2); margin: 0; padding: 0; border: 0; }
@media (min-width: 640px) { .checkbox-grid { grid-template-columns: repeat(2, 1fr); } }
.checkbox {
  display: flex; align-items: center; gap: var(--sp-3);
  min-height: 3rem; padding: 0.6rem 0.9rem;
  background: var(--bg-panel); border: 1px solid var(--line); border-radius: var(--radius);
  cursor: pointer; font-size: var(--fs-sm); color: var(--text-muted);
  transition: border-color var(--dur) var(--ease-soft), color var(--dur) var(--ease-soft), background var(--dur) var(--ease-soft);
}
.checkbox:hover { border-color: var(--line-gold); color: var(--text-body); }
.checkbox input { width: 1.15rem; height: 1.15rem; flex-shrink: 0; margin: 0; accent-color: var(--red-primary); cursor: pointer; }
.checkbox:has(input:checked) { border-color: var(--line-gold); background: rgba(212, 175, 55, 0.06); color: var(--text-body); }
.checkbox:has(input:focus-visible) { outline: 2px solid var(--gold); outline-offset: 2px; }

.fieldset { margin: 0; padding: 0; border: 0; }
.fieldset__legend { padding: 0; margin-bottom: var(--sp-3); color: var(--text-body); font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; }

.form__status { display: none; padding: var(--sp-4); border-radius: var(--radius); font-size: var(--fs-sm); }
.form__status:not(:empty) { display: block; }
.form__status[data-state="error"] { background: rgba(199, 65, 53, 0.12); border: 1px solid var(--red-text); color: var(--red-text); }
.form__status[data-state="success"] { background: rgba(212, 175, 55, 0.08); border: 1px solid var(--line-gold); color: var(--gold); }

.contact-list { display: grid; gap: var(--sp-5); }
.contact-list dt { color: var(--text-faint); font-family: var(--font-mono); font-size: var(--fs-mono); letter-spacing: 0.16em; text-transform: uppercase; }
.contact-list dd { margin: var(--sp-2) 0 0; }
.contact-list a { display: inline-flex; align-items: center; min-height: 2.75rem; color: var(--text-body); font-size: var(--fs-lg); border-bottom: 1px solid var(--line-gold); transition: color var(--dur) var(--ease-soft), border-color var(--dur) var(--ease-soft); }
.contact-list a:hover { color: var(--gold); border-color: var(--gold); }

.hours { display: grid; gap: var(--sp-2); font-size: var(--fs-sm); }
.hours__row { display: flex; justify-content: space-between; gap: var(--sp-4); padding-block: var(--sp-2); border-bottom: 1px solid var(--line); color: var(--text-muted); }
.hours__row span:last-child { color: var(--text-body); font-family: var(--font-mono); font-size: var(--fs-mono); font-variant-numeric: tabular-nums; }

/* ==========================================================================
   20. MAP
   ========================================================================== */
.map { position: relative; aspect-ratio: 16 / 10; background: var(--bg-panel); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow: hidden; }
@media (min-width: 768px) { .map { aspect-ratio: 21 / 9; } }
.map iframe { width: 100%; height: 100%; border: 0; filter: grayscale(1) invert(0.92) contrast(0.85) hue-rotate(180deg); }
.map__consent { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: var(--sp-4); padding: var(--sp-6); text-align: center; background: var(--bg-panel); }
.map__consent p { max-width: 34ch; color: var(--text-muted); font-size: var(--fs-sm); }

/* ==========================================================================
   21. FOOTER
   ========================================================================== */
.site-footer { padding-block: var(--sp-9) var(--sp-6); background: var(--bg-raised); border-top: 1px solid var(--line); }
.site-footer__grid { display: grid; gap: var(--sp-7); }
@media (min-width: 768px) { .site-footer__grid { grid-template-columns: 1.6fr 1fr 1fr; } }
@media (min-width: 1024px) { .site-footer__grid { grid-template-columns: 1.8fr 1fr 1fr 1.2fr; gap: var(--sp-8); } }

.site-footer__logo-link { display: inline-block; transition: opacity var(--dur) var(--ease-soft); }
.site-footer__logo-link:hover { opacity: 0.82; }
.site-footer__logo { height: 6.5rem; width: auto; margin-bottom: var(--sp-5); }
.site-footer__blurb { max-width: 40ch; margin-top: var(--sp-4); color: var(--text-muted); font-size: var(--fs-sm); line-height: 1.75; }

.footer-head { margin-bottom: var(--sp-4); color: var(--gold); font-family: var(--font-mono); font-size: var(--fs-mono); font-weight: 500; letter-spacing: 0.2em; text-transform: uppercase; }
.footer-links { display: grid; gap: 0; }
.footer-links a, .footer-contact a { display: inline-flex; align-items: center; min-height: 2.75rem; color: var(--text-muted); font-size: var(--fs-sm); transition: color var(--dur) var(--ease-soft); }
.footer-links a:hover, .footer-contact a:hover { color: var(--gold); }
.footer-contact { display: grid; gap: var(--sp-1); font-size: var(--fs-sm); color: var(--text-muted); }
.footer-contact address { font-style: normal; line-height: 1.75; }

.site-footer__bottom {
  display: flex; flex-wrap: wrap; gap: var(--sp-3) var(--sp-5);
  align-items: center; justify-content: space-between;
  margin-top: var(--sp-8); padding-top: var(--sp-5); border-top: 1px solid var(--line);
  color: var(--text-faint); font-family: var(--font-mono); font-size: var(--fs-mono); letter-spacing: 0.05em;
}
.site-footer__legal { display: flex; flex-wrap: wrap; gap: var(--sp-4); }

/* ==========================================================================
   22. MOBILE STICKY CTA
   ========================================================================== */
.mobile-cta {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 90;
  display: flex; gap: var(--sp-3);
  padding: var(--sp-3) var(--gutter) calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
  background: rgba(10, 10, 11, 0.95);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px);
  border-top: 1px solid var(--line);
}
.mobile-cta .btn { flex: 1; padding-inline: 0.75rem; }
body { padding-bottom: 4.75rem; }
@media (min-width: 1024px) { .mobile-cta { display: none; } body { padding-bottom: 0; } }

/* ==========================================================================
   23. MOTION
   --------------------------------------------------------------------------
   Content is VISIBLE BY DEFAULT. The `.js` class is added to <html> by a tiny
   inline head script, and only then does anything opt into a hidden start
   state. JS off, JS failed, or no IntersectionObserver all land on fully
   readable static content.

   On the homepage GSAP drives the reveals; elsewhere motion.js does. Both
   write the same `.is-visible` class, so this CSS serves either.
   ========================================================================== */
/* Pure CSS, no JS dependency — motion.js only reveals `.reveal`, so a hero
   waiting on a script would never appear on the pages that script covers.
   motion-home.js cancels this and uses GSAP instead. */
.js .hero__reveal {
  opacity: 0;
  transform: translate3d(0, 1.25rem, 0);
  animation: hero-in 900ms var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 110ms + 100ms);
}
.js .hero__reveal.is-visible { opacity: 1; transform: none; }
@keyframes hero-in { to { opacity: 1; transform: none; } }

.js .reveal { opacity: 0; transform: translate3d(0, 1.75rem, 0); will-change: transform, opacity; }
.js .reveal.is-visible { opacity: 1; transform: none; will-change: auto; }

/* Transitions switch on only once the script confirms stylesheets have
   settled, so an element can never animate its way INTO hiding while the
   deferred stylesheet is still arriving. GSAP-driven pages set their own
   tweens and ignore these. */
.js.motion-ready .reveal { transition: opacity 800ms var(--ease-out), transform 800ms var(--ease-out); transition-delay: calc(var(--i, 0) * 90ms); }

.js .reveal--left { transform: translate3d(-2.75rem, 0, 0); }
.js .reveal--right { transform: translate3d(2.75rem, 0, 0); }
.js .reveal--down { transform: translate3d(0, -1.75rem, 0); }
.js .reveal--rise { transform: translate3d(0, 3.5rem, 0); }
.js .reveal--scale { transform: scale(0.94); }
.js.motion-ready .reveal--slow { transition-duration: 1100ms; }

/* --------------------------------------------------------------------------
   GRID CHILDREN NEVER OFFSET HORIZONTALLY. This is a hard rule, learned the
   expensive way.

   These used to alternate translate3d(-2rem, ...) / translate3d(2rem, ...) so
   staggered cards fanned in from opposite sides. It looked good when it worked.
   When it did not, it broke the page: .svc-grid columns sit 16px apart, so a
   2rem (32px) offset makes adjacent cards overlap by 48px, and the layout reads
   as genuinely broken rather than merely unanimated.

   It stopped working for two compounding reasons:

   1. These rules are gated on `.js` alone, so they apply on the HOME page too —
      which is driven by GSAP (motion-home.js), not by the CSS system that owns
      them. GSAP clears the offset by writing an inline transform; these rules
      expect it cleared by the .is-visible class. Two owners, one property.
   2. .svc-card carries `transition: transform` for its hover lift. So when the
      CSS start-state transform changed, it ANIMATED — while GSAP was writing a
      different inline transform every frame. The transition and the tween
      fought, and the transition could be left running indefinitely, parked on
      the start value.

   A vertical offset has neither failure mode: if motion stalls, cards look
   slightly low, which nobody notices. Keep it that way. If you want directional
   motion back, put it on elements that are NOT siblings in a grid track.
   -------------------------------------------------------------------------- */
.js [data-stagger] > .reveal { transform: translate3d(0, 1.25rem, 0); }
.js .split > .reveal { transform: translate3d(0, 0.75rem, 0); }
.js [data-stagger] > .reveal--rise, .js .split > .reveal--rise { transform: translate3d(0, 3.5rem, 0); }
.js [data-stagger] > .reveal.is-visible, .js .split > .reveal.is-visible { transform: none; }

/* Same rule for the explicit directional variants when they happen to be grid
   siblings — .compare and .evidence pair two figures per row with a gap far
   smaller than 2.75rem, so the horizontal form would overlap there too. */
.js .compare > .reveal, .js .evidence > .reveal, .js .shots > .reveal {
  transform: translate3d(0, 1.25rem, 0);
}
.js .compare > .reveal.is-visible,
.js .evidence > .reveal.is-visible,
.js .shots > .reveal.is-visible { transform: none; }

@media (max-width: 767px) {
  .js .reveal--left, .js .reveal--right { transform: translate3d(0, 1rem, 0); }
  .js [data-stagger] > .reveal, .js .split > .reveal { transform: translate3d(0, 1rem, 0); }
  .js [data-stagger] > .reveal.is-visible, .js .split > .reveal.is-visible { transform: none; }
}

.js .hero__bg { animation: drift 28s var(--ease-soft) infinite alternate; will-change: transform; }
@keyframes drift {
  from { transform: translate3d(-1.5%, -1%, 0) scale(1.02); }
  to { transform: translate3d(1.5%, 1.5%, 0) scale(1.06); }
}

@media (min-width: 1024px) { .js [data-parallax] { transform: translate3d(0, var(--py, 0px), 0); will-change: transform; } }

.page-veil { position: fixed; inset: 0; z-index: 999; pointer-events: none; background: var(--bg-void); opacity: 0; transition: opacity 240ms var(--ease-soft); }
.page-veil[data-active="true"] { opacity: 1; }

/* --------------------------------------------------------------------------
   The accessibility override. Everything above yields to this.

   It removes MOVEMENT — every translate, every scale, the parallax, the drift.
   It deliberately KEEPS a plain opacity cross-fade, because a fade has no
   direction and no velocity, so it does not trigger the vestibular responses
   this media query exists to protect against. Reduced motion means less
   movement, not content popping in abruptly.
   -------------------------------------------------------------------------- */
@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;
  }

  .js .reveal, .js .hero__reveal, .js [data-stagger] > .reveal,
  .js .split > .reveal, .js [data-parallax] { transform: none !important; }

  .js .hero__reveal { opacity: 1 !important; animation: none !important; }

  .js .reveal { opacity: 0; }
  .js.motion-ready .reveal { transition: opacity 400ms linear !important; transition-delay: 0s !important; }
  .js .reveal.is-visible, .js .hero__reveal.is-visible { opacity: 1; }

  .cursor-glow, .page-veil { display: none !important; }
}

@media (max-width: 1023px) {
  .cursor-glow { display: none; }
  .js [data-parallax] { transform: none !important; }
}
@media (hover: none), (pointer: coarse) { .cursor-glow { display: none; } }

/* ==========================================================================
   24. UTILITIES
   ========================================================================== */
.text-gold { color: var(--gold); }
.text-muted { color: var(--text-muted); }
.lede { font-size: var(--fs-lg); color: var(--text-muted); }
.mono { font-family: var(--font-mono); font-size: var(--fs-mono); letter-spacing: 0.12em; text-transform: uppercase; }
.mt-4 { margin-top: var(--sp-4); }
.mt-5 { margin-top: var(--sp-5); }
.mt-6 { margin-top: var(--sp-6); }
.mt-7 { margin-top: var(--sp-7); }
.mt-8 { margin-top: var(--sp-8); }
.stack > * + * { margin-top: var(--sp-4); }
.stack-lg > * + * { margin-top: var(--sp-6); }
.divider { height: 1px; border: 0; background: var(--line); }
.nav-open { overflow: hidden; }

/* ==========================================================================
   25. SERVICE DIAGRAMS
   Schematics for the Services page. Every <svg> here is aria-hidden and
   carries NO text of its own — all meaning lives in the HTML <figcaption>
   beneath it. That is deliberate: a crawler, a screen reader, or a browser
   with images disabled loses nothing by ignoring the graphic entirely, and
   we never have to worry about SVG text falling below the 11px floor when
   the viewBox scales down on a phone.
   The one exception is the combination ring, which needs node labels; it
   sits in a scroll container with a min-width so those labels stay legible.
   ========================================================================== */
.svc-figure { margin: var(--sp-6) 0 0; }
@media (min-width: 1024px) { .svc-figure { margin-top: var(--sp-7); } }

.svc-figure__frame {
  position: relative;
  padding: clamp(0.75rem, 2.5vw, 1.25rem);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background:
    linear-gradient(rgba(212, 175, 55, 0.03) 1px, transparent 1px) 0 0 / 100% 1.5rem,
    linear-gradient(90deg, rgba(212, 175, 55, 0.03) 1px, transparent 1px) 0 0 / 1.5rem 100%,
    linear-gradient(158deg, rgba(199, 65, 53, 0.08), rgba(10, 10, 11, 0) 62%);
}
/* Corner ticks — the specimen-sheet register marks. */
.svc-figure__frame::before,
.svc-figure__frame::after {
  content: ""; position: absolute; width: 10px; height: 10px; pointer-events: none;
  border-color: rgba(212, 175, 55, 0.5); border-style: solid; border-width: 0;
}
.svc-figure__frame::before { top: -1px; left: -1px; border-top-width: 1px; border-left-width: 1px; }
.svc-figure__frame::after { bottom: -1px; right: -1px; border-bottom-width: 1px; border-right-width: 1px; }

.svc-figure svg { display: block; width: 100%; height: auto; }

.svc-figure__cap {
  margin-top: var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  line-height: 1.6;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}
.svc-figure__num {
  color: var(--gold);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.svc-figure__num::after { content: " — "; color: var(--text-faint); }

/* --- diagram primitives ------------------------------------------------- */
.dg-l  { fill: none; stroke: rgba(245, 240, 232, 0.22); stroke-width: 1.25; }
.dg-lf { fill: none; stroke: rgba(245, 240, 232, 0.11); stroke-width: 1; }
.dg-g  { fill: none; stroke: var(--gold); stroke-width: 1.25; }
.dg-gd { fill: none; stroke: rgba(212, 175, 55, 0.55); stroke-width: 1.25; stroke-dasharray: 4 4; }
.dg-gf { fill: rgba(212, 175, 55, 0.14); stroke: none; }
.dg-gs { fill: var(--gold); }
.dg-r  { fill: var(--red-primary); stroke: none; }
.dg-rs { fill: rgba(199, 65, 53, 0.22); stroke: var(--red-primary); stroke-width: 1.25; }
.dg-b  { fill: rgba(245, 240, 232, 0.14); stroke: none; }
.dg-bb { fill: rgba(245, 240, 232, 0.07); stroke: none; }
.dg-fill-void { fill: var(--bg-void); stroke: none; }
.dg-ld { fill: none; stroke: rgba(245, 240, 232, 0.20); stroke-width: 1.25; stroke-dasharray: 4 4; }
.dg-band { fill: rgba(245, 240, 232, 0.05); stroke: rgba(245, 240, 232, 0.22); stroke-width: 1.25; }
.dg-band--out { fill: rgba(199, 65, 53, 0.26); stroke: var(--red-primary); stroke-width: 1.25; }
.dg-chord { fill: none; stroke: rgba(199, 65, 53, 0.42); stroke-width: 1.25; }

/* --- the combination ring ----------------------------------------------- */
.combo-figure { margin: 0 0 var(--sp-7); }
.combo-figure__scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.combo-figure__scroll svg { min-width: 30rem; max-width: 36rem; margin-inline: auto; }
.combo-figure .svc-figure__cap { text-align: center; }
.dg-label {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.1em;
  fill: var(--text-muted);
}
.dg-label--gold { fill: var(--gold); }

/* ==========================================================================
   26. WORK IMAGERY
   Screenshot galleries, before/after pairs, and search-result evidence.
   Every image here is real work. Slots waiting on a real file use
   .shot__frame--pending, which is visibly and deliberately marked — the same
   honesty convention as .placeholder-flag on the testimonials. It reserves its
   own height via aspect-ratio so dropping the real image in causes no shift.
   ========================================================================== */
.shots { display: grid; gap: var(--sp-5); }
@media (min-width: 680px) { .shots--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px) { .shots--3 { grid-template-columns: repeat(3, 1fr); } }

.shot { margin: 0; }
.shot__frame {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-raised);
}
.shot__frame img { display: block; width: 100%; height: auto; }

/* A hairline gold edge on hover, so the grid feels inspectable rather than flat. */
@media (hover: hover) {
  .shot__frame { transition: border-color 240ms var(--ease-out); }
  .shot:hover .shot__frame { border-color: var(--line-gold); }
}

.shot__frame--pending {
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 10;
  border-style: dashed;
  background:
    linear-gradient(158deg, rgba(199, 65, 53, 0.06), rgba(10, 10, 11, 0) 62%),
    var(--bg-raised);
}
.shot__pending {
  padding: var(--sp-5);
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  line-height: 1.7;
  letter-spacing: 0.06em;
  color: var(--text-faint);
}
.shot__pending strong { display: block; color: var(--red-text); letter-spacing: 0.12em; }

.shot__cap {
  margin-top: var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  line-height: 1.6;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}
.shot__num { color: var(--gold); letter-spacing: 0.12em; text-transform: uppercase; }
.shot__num::after { content: " — "; color: var(--text-faint); }

/* --- before / after ----------------------------------------------------- */
.compare { display: grid; gap: var(--sp-6); }
@media (min-width: 800px) { .compare { grid-template-columns: 1fr 1fr; gap: var(--sp-5); } }

.compare__label {
  display: inline-block;
  margin-bottom: var(--sp-3);
  padding: 0.25rem 0.65rem;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.compare__label--before { border: 1px solid var(--line-strong); color: var(--text-muted); }
.compare__label--after {
  border: 1px solid var(--line-gold);
  background: rgba(212, 175, 55, 0.08);
  color: var(--gold);
}

/* --- search / AI evidence ----------------------------------------------- */
.evidence { display: grid; gap: var(--sp-6); }
@media (min-width: 760px) { .evidence { grid-template-columns: repeat(2, 1fr); } }

.evidence__engine {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: var(--sp-3);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold);
}
.evidence__engine::before {
  content: "";
  width: 1.5rem; height: 1px;
  background: var(--line-gold);
  flex-shrink: 0;
}
.evidence__note {
  margin-top: var(--sp-3);
  font-size: var(--fs-sm);
  line-height: 1.65;
  color: var(--text-muted);
}
.evidence__note em { font-style: italic; color: var(--text-body); }

/* Capture date. Deliberately quieter than the caption it follows, but it is
   load-bearing evidence metadata, not decoration — so it stays real text at
   the 11px mono floor rather than shrinking further. */
.evidence__date {
  display: inline-block;
  margin-left: 0.35rem;
  padding: 0.1rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.08em;
  color: var(--text-faint);
  white-space: nowrap;
}

/* Labels the engine a before/after pair belongs to. An h4 so the outline stays
   h2 > h3 > h4 down this section rather than skipping a level. */
.evidence__group {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
}
.evidence__group::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line-gold);
}

@media print {
  .site-header, .mobile-cta, .cursor-glow, .page-veil, .nav-backdrop { display: none !important; }
  body { background: #fff; color: #000; padding-bottom: 0; }
}
