/* ===========================================================================
   Mai Laundry App — motion layer
   ---------------------------------------------------------------------------
   2026-09-12. Loaded AFTER style.css and additive only: it introduces new
   classes and never redefines an existing rule, so the base site still renders
   correctly if this file 404s or JS is disabled.

   Consumes the tokens already defined in style.css (--primary, --gold, --ease,
   --radius-card …). Defines no colours of its own beyond alpha overlays, so
   dark mode keeps working without a second dark block here.

   MOTION CONTRACT
   Every animated element must be readable with NO JavaScript and with reduced
   motion on. Start states that hide content (opacity:0) are therefore gated
   behind BOTH `.js` and `html:not(.reduce-motion)`. If GSAP fails to load,
   site.js adds `.motion-failed` to <html>, which force-reveals everything.
   =========================================================================== */

/* ── Smooth-scroll wrapper ────────────────────────────────────────────────
   ScrollSmoother requires this exact nesting. Without JS these are plain
   divs with no effect. */
#smooth-wrapper { }
#smooth-content { will-change: transform; }

/* Pinned sections must not inherit the body's overflow clip. */
.ml-pin-safe { overflow: visible; }

/* ═══ Reveal primitives ═══════════════════════════════════════════════════
   GSAP drives these by setting inline styles; the class only supplies the
   hidden START state. `.in-view` is NOT used here (that is the legacy
   IntersectionObserver system in style.css, still used by untouched
   sections). */

.js:not(.reduce-motion):not(.motion-failed) [data-anim] { opacity: 0; }
.js:not(.reduce-motion):not(.motion-failed) [data-anim="up"]    { transform: translateY(28px); }
.js:not(.reduce-motion):not(.motion-failed) [data-anim="down"]  { transform: translateY(-24px); }
.js:not(.reduce-motion):not(.motion-failed) [data-anim="left"]  { transform: translateX(-32px); }
.js:not(.reduce-motion):not(.motion-failed) [data-anim="right"] { transform: translateX(32px); }
.js:not(.reduce-motion):not(.motion-failed) [data-anim="scale"] { transform: scale(.94); }
.js:not(.reduce-motion):not(.motion-failed) [data-anim="blur"]  { filter: blur(10px); }

/* Hero entrance items and the split headline. These MUST be class-gated in CSS
   rather than set as inline styles: an inline `opacity:0` cannot be overridden
   by the reduce-motion / motion-failed safety nets below, which would leave the
   whole hero blank for reduced-motion users and whenever GSAP fails to load.
   (Caught by the visibility audit, 2026-09-12.) */
.js:not(.reduce-motion):not(.motion-failed) [data-hero-in] { opacity: 0; transform: translateY(18px); }
.js:not(.reduce-motion):not(.motion-failed) [data-split]   { opacity: 0; }

/* Split-text lines: the wrapper clips, the line slides up out of it. */
.split-line-wrap { overflow: hidden; display: block; }

/* ═══ Magnetic buttons ════════════════════════════════════════════════════ */
.magnetic { position: relative; display: inline-flex; will-change: transform; }
.magnetic > * { pointer-events: none; }

/* ═══ Gradient mesh background ════════════════════════════════════════════
   Replaces flat section fills on the premium sections. Pure CSS, GPU-cheap:
   three radial gradients on one layer, no blur filter (unlike the legacy
   .blob elements, which promote three 480px blurred layers permanently). */
.mesh {
  position: relative;
  isolation: isolate;
  background:
    radial-gradient(58% 68% at 12% 8%,  color-mix(in srgb, var(--primary) 22%, transparent) 0%, transparent 62%),
    radial-gradient(52% 62% at 88% 22%, color-mix(in srgb, var(--gold)    16%, transparent) 0%, transparent 60%),
    radial-gradient(72% 78% at 52% 108%, color-mix(in srgb, var(--primary-light) 20%, transparent) 0%, transparent 66%),
    var(--bg);
}
.mesh-dark {
  background:
    radial-gradient(60% 70% at 14% 6%,  color-mix(in srgb, var(--primary-light) 30%, transparent) 0%, transparent 62%),
    radial-gradient(54% 64% at 86% 26%, color-mix(in srgb, var(--gold)          20%, transparent) 0%, transparent 58%),
    radial-gradient(76% 80% at 50% 106%, color-mix(in srgb, var(--primary)      34%, transparent) 0%, transparent 68%),
    var(--primary-deepest);
  color: #fff;
}
/* Fallback for engines without color-mix: a plain tint, still on-brand. */
@supports not (background: color-mix(in srgb, red 10%, transparent)) {
  .mesh      { background: var(--bg); }
  .mesh-dark { background: var(--hero-gradient); color: #fff; }
}

/* Fine grain so large flat areas don't band on wide gamut displays. */
.grain::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  opacity: .035; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ═══ Audience switch (Home ⇄ Business) ═══════════════════════════════════ */
.aud-switch {
  display: inline-flex; gap: 4px; padding: 4px;
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  border-radius: var(--radius-pill);
  border: 1px solid var(--line);
}
.aud-switch a {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 16px; border-radius: var(--radius-pill);
  font: 600 .82rem/1 var(--font-display); letter-spacing: .01em;
  color: var(--muted); text-decoration: none;
  transition: color .25s var(--ease), background .25s var(--ease), box-shadow .25s var(--ease);
  white-space: nowrap;
}
.aud-switch a:hover { color: var(--ink); }
.aud-switch a[aria-current="page"] {
  background: var(--card); color: var(--primary); box-shadow: var(--shadow-sm);
}
.mesh-dark .aud-switch { background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.18); }
.mesh-dark .aud-switch a { color: rgba(255,255,255,.72); }
.mesh-dark .aud-switch a:hover { color: #fff; }
.mesh-dark .aud-switch a[aria-current="page"] { background: #fff; color: var(--primary-deepest); }

/* ═══ Marquee (trust strip) ═══════════════════════════════════════════════ */
.marquee { overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent); }
.marquee-track { display: flex; gap: 3rem; width: max-content; will-change: transform; }
.marquee-item {
  display: inline-flex; align-items: center; gap: .6rem;
  font: 600 .9rem/1 var(--font-display); color: var(--muted); white-space: nowrap;
}
.marquee-item svg { color: var(--gold); flex: none; }

/* ═══ Garment journey (scroll-scrubbed) ══════════════════════════════════ */
.journey { position: relative; }
.journey-rail {
  position: relative; height: 4px; border-radius: 999px;
  background: color-mix(in srgb, var(--primary) 16%, transparent);
  margin: 2.6rem 0 2rem;
}
.journey-fill {
  position: absolute; inset: 0 auto 0 0; width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--primary), var(--gold));
}
.journey-steps { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1rem; }
.journey-step { text-align: center; }
.journey-ico {
  width: 58px; height: 58px; margin: 0 auto .9rem;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--card); border: 2px solid var(--line);
  color: var(--hint);
  transition: color .4s var(--ease), border-color .4s var(--ease),
              background .4s var(--ease), transform .4s var(--ease), box-shadow .4s var(--ease);
}
.journey-step.active .journey-ico {
  color: #fff; border-color: transparent; transform: scale(1.1);
  background: linear-gradient(135deg, var(--primary), var(--primary-light));
  box-shadow: 0 10px 26px color-mix(in srgb, var(--primary) 34%, transparent);
}
.journey-step.done .journey-ico { color: var(--primary); border-color: var(--primary-soft); }
.journey-step h4 { font: 700 .95rem/1.25 var(--font-display); margin: 0 0 .3rem; color: var(--ink); }
.journey-step p  { font-size: .82rem; color: var(--muted); margin: 0; line-height: 1.5; }
@media (max-width: 820px) {
  .journey-steps { grid-template-columns: repeat(2, 1fr); gap: 1.6rem 1rem; }
  .journey-rail { display: none; }
}
@media (max-width: 460px) { .journey-steps { grid-template-columns: 1fr; } }

/* ═══ Stat counters ══════════════════════════════════════════════════════ */
.stat-xl { font: 800 clamp(2.4rem, 5.2vw, 3.6rem)/1 var(--font-display); letter-spacing: -.02em; }
.stat-xl .unit { font-size: .46em; margin-left: .12em; color: var(--gold); }

/* ═══ Commercial volume calculator ═══════════════════════════════════════ */
.calc {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius-card); padding: clamp(1.4rem, 3vw, 2rem);
  box-shadow: var(--shadow-md);
}
.calc-row { margin-bottom: 1.35rem; }
.calc-row:last-of-type { margin-bottom: 1.9rem; }
.calc-label {
  display: flex; justify-content: space-between; align-items: baseline;
  font: 600 .86rem/1 var(--font-display); color: var(--ink); margin-bottom: .7rem;
}
.calc-val { font: 800 1.05rem/1 var(--font-display); color: var(--primary); }
.calc input[type="range"] {
  -webkit-appearance: none; appearance: none; width: 100%; height: 6px;
  border-radius: 999px; background: var(--line); outline: none; cursor: pointer;
}
.calc input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 22px; height: 22px;
  border-radius: 50%; background: var(--primary); border: 3px solid var(--card);
  box-shadow: 0 2px 8px color-mix(in srgb, var(--primary) 42%, transparent);
  cursor: grab; transition: transform .18s var(--ease);
}
.calc input[type="range"]::-webkit-slider-thumb:active { transform: scale(1.16); cursor: grabbing; }
.calc input[type="range"]::-moz-range-thumb {
  width: 22px; height: 22px; border-radius: 50%; background: var(--primary);
  border: 3px solid var(--card); cursor: grab;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--primary) 42%, transparent);
}
.calc input[type="range"]:focus-visible { outline: 2px solid var(--primary); outline-offset: 4px; }
.calc-out {
  border-top: 1px dashed var(--line); padding-top: 1.4rem;
  display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;
}
.calc-out div span { display: block; font-size: .76rem; color: var(--muted); margin-bottom: .3rem; }
.calc-out div strong { font: 800 1.5rem/1 var(--font-display); color: var(--ink); }
.calc-note { font-size: .76rem; color: var(--hint); margin: 1.1rem 0 0; line-height: 1.6; }

/* ═══ Sector / proof cards ═══════════════════════════════════════════════ */
.tilt { transform-style: preserve-3d; will-change: transform; }
.tilt-inner { transform: translateZ(38px); }

.proof-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1.1rem; }
.proof {
  position: relative; overflow: hidden;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius-card); padding: 1.5rem;
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), border-color .4s var(--ease);
}
.proof:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); border-color: var(--primary-soft); }
.proof::before {
  content: ""; position: absolute; inset: 0 0 auto; height: 3px;
  background: linear-gradient(90deg, var(--primary), var(--gold));
  transform: scaleX(0); transform-origin: left; transition: transform .45s var(--ease);
}
.proof:hover::before { transform: scaleX(1); }
.proof h3 { font: 700 1.05rem/1.3 var(--font-display); margin: 0 0 .5rem; }
.proof p  { font-size: .88rem; color: var(--muted); margin: 0; line-height: 1.65; }
.proof-ico {
  width: 44px; height: 44px; border-radius: 12px; margin-bottom: 1rem;
  display: grid; place-items: center;
  background: var(--primary-pale); color: var(--primary);
}
.mesh-dark .proof { background: rgba(255,255,255,.07); border-color: rgba(255,255,255,.14); }
.mesh-dark .proof h3 { color: #fff; }
.mesh-dark .proof p  { color: rgba(255,255,255,.76); }
.mesh-dark .proof-ico { background: rgba(255,255,255,.12); color: var(--gold-light); }

/* ═══ Scroll progress bar ════════════════════════════════════════════════ */
.scroll-prog {
  position: fixed; top: 0; left: 0; height: 3px; width: 100%;
  transform: scaleX(0); transform-origin: left; z-index: 999;
  background: linear-gradient(90deg, var(--primary), var(--gold));
  pointer-events: none;
}

/* ═══ Section heading kicker ═════════════════════════════════════════════ */
.kicker {
  display: inline-flex; align-items: center; gap: .55rem;
  font: 700 .74rem/1 var(--font-display); letter-spacing: .14em; text-transform: uppercase;
  color: var(--primary); margin-bottom: 1rem;
}
.kicker::before { content: ""; width: 26px; height: 2px; background: var(--gold); border-radius: 2px; }
.mesh-dark .kicker { color: var(--gold-light); }

/* ═══ Reduced motion / no-JS safety net ══════════════════════════════════
   Belt and braces: even if a start-state class slipped through, force
   everything visible. */
@media (prefers-reduced-motion: reduce) {
  [data-anim], [data-hero-in], [data-split] { opacity: 1 !important; transform: none !important; filter: none !important; }
  .marquee-track { animation: none !important; transform: none !important; }
  .journey-fill { width: 100% !important; }
  .journey-step .journey-ico { transition: none !important; }
}
html.reduce-motion [data-anim],  html.reduce-motion [data-hero-in],  html.reduce-motion [data-split],
html.motion-failed [data-anim],  html.motion-failed [data-hero-in],  html.motion-failed [data-split],
html:not(.js) [data-anim],       html:not(.js) [data-hero-in],       html:not(.js) [data-split] {
  opacity: 1 !important; transform: none !important; filter: none !important;
}

/* ═══ Single-plan layout ══════════════════════════════════════════════════
   2026-09-12 — the Elite tier was removed from the site (not currently
   offered). Premium is now the only plan, so it is presented as ONE centred
   card rather than a lone item stranded in a 2-column grid. Its bullets split
   into two columns from 620px up so a six-item list doesn't read as a
   towering column. */
.plan-single { display: flex; justify-content: center; }
.plan-single .plan {
  max-width: 620px; width: 100%;
  padding: clamp(1.8rem, 4vw, 2.6rem);
}
@media (min-width: 620px) {
  .plan-single .plan ul {
    display: grid; grid-template-columns: 1fr 1fr;
    gap: .55rem 1.6rem; align-items: start;
  }
}

/* ═══ Section heading sweep ══════════════════════════════════════════════
   A gradient underline that draws itself in as the heading enters. Applied
   via [data-sweep]; harmless (just a static underline) without JS. */
[data-sweep] {
  /* inline-block so the underline hugs the WORDS, not the full column width.
     background-size carries an explicit 3px height — the tween animates the
     width only; animating the height flooded the heading with the gradient. */
  display: inline-block;
  background-image: linear-gradient(90deg, var(--primary), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 3px;
  padding-bottom: .16em;
}
/* The heading is a block-level h2; making it inline-block let the eyebrow sit
   BESIDE it. Keep the h2 a block and hug the words with an inner span-free
   trick instead: fit-content + auto margins. */
[data-sweep] { display: block; width: fit-content; max-width: 100%; }
.section-head.center [data-sweep] { margin-inline: auto; }

/* ═══ Custom cursor ═══════════════════════════════════════════════════════
   2026-09-12 — replaces the .cursor-dot/.cursor-ring pair in style.css, which
   is now inert (site.js no longer creates those elements).

   `mix-blend-mode: difference` is doing real work here: the dot inverts itself
   against whatever is behind it, so it stays visible on the white cards AND on
   the deep-purple hero without a per-section class list to maintain.

   Only ever created on a fine pointer with reduced motion off — see
   initCursor() in motion.js. The native cursor is untouched otherwise. */
.cur-dot, .cur-ring {
  position: fixed; top: 0; left: 0; z-index: 9999;
  pointer-events: none; opacity: 0;
  transition: opacity .3s var(--ease);
  margin-left: -4px; margin-top: -4px;
}
.cur-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: #fff; mix-blend-mode: difference;
}
.cur-ring {
  width: 38px; height: 38px; border-radius: 50%;
  margin-left: -19px; margin-top: -19px;
  border: 1.5px solid color-mix(in srgb, var(--primary) 55%, transparent);
  transition: opacity .3s var(--ease), width .3s var(--ease), height .3s var(--ease),
              margin .3s var(--ease), border-radius .3s var(--ease),
              background .3s var(--ease), border-color .3s var(--ease);
}
body.cur-on .cur-dot, body.cur-on .cur-ring { opacity: 1; }

/* Over an interactive element: ring grows and tints. */
body.cur-on.cur-hover .cur-ring {
  width: 54px; height: 54px; margin-left: -27px; margin-top: -27px;
  background: color-mix(in srgb, var(--primary) 10%, transparent);
  border-color: color-mix(in srgb, var(--primary) 75%, transparent);
}
/* Locked onto a compact target: squares off into a "focus" shape. */
body.cur-on.cur-snap .cur-ring {
  width: 62px; height: 62px; margin-left: -31px; margin-top: -31px;
  border-radius: 16px;
  border-color: var(--gold);
  background: color-mix(in srgb, var(--gold) 12%, transparent);
}
body.cur-on.cur-snap .cur-dot { opacity: .35; }
/* Press feedback. */
body.cur-on.cur-down .cur-ring { transform: scale(.86); }

/* Hide the native cursor ONLY while ours is actually drawn, and never over
   text inputs where the I-beam carries real meaning. */
body.cur-on, body.cur-on a, body.cur-on button,
body.cur-on .card, body.cur-on .proof, body.cur-on .faq-q { cursor: none; }
body.cur-on input, body.cur-on textarea, body.cur-on select { cursor: auto; }

/* Touch, coarse pointers and reduced motion never see it. */
@media (hover: none), (pointer: coarse), (prefers-reduced-motion: reduce) {
  .cur-dot, .cur-ring { display: none !important; }
  body, body a, body button, body .card, body .proof, body .faq-q { cursor: auto !important; }
}

/* ═══ Header fit ══════════════════════════════════════════════════════════
   .header-inner is a flex row. Every child defaults to flex-shrink:1, so when
   the Home/Business switch was added the browser CRUSHED children into each
   other rather than reflowing: the wordmark printed over "Services", and
   "Contact" printed over the switch at 1366-1920px.

   Fix: nothing in the header may shrink. .nav is given flex:none too, so when
   the row genuinely runs out of width the media queries below shed optional
   chrome (phone, then switch, then the whole nav to the burger) instead of
   letting neighbours collide. Overlap is verified geometrically at 14 widths
   from 390 to 1920 — see hdr2.mjs. */
.site-header .header-inner { gap: 18px; flex-wrap: nowrap; }
.site-header .brand,
.site-header .nav,
.site-header .header-actions,
.site-header .header-tel,
.site-header .aud-switch { flex: none; }
.site-header .brand-name,
.site-header .header-tel,
.site-header .nav a { white-space: nowrap; }
.site-header .header-actions { gap: 10px; }
/* The header row must never be wider than the viewport. .header-inner caps at
   --maxw (1180px) + 44px padding, so above ~1224px there is always slack; below
   it the brand + nav + actions have to fit in the real width. Allowing the row
   to wrap is wrong (it doubles the header height), so instead the SWITCH — the
   most expendable header item, and present in the drawer — is dropped for the
   whole band where the six-link retail nav does not leave room for it. */
@media (max-width: 1420px) { .site-header .aud-switch { display: none; } }

/* Shed in order of redundancy. The phone repeats in the drawer and footer, so
   it goes first. The switch is the only header cross-link between the two
   audiences, so it survives longest — and the drawer carries it once the
   burger takes over. */
@media (max-width: 1400px) { .site-header .nav { gap: clamp(.6rem, 1.3vw, 1.1rem); } }
@media (max-width: 1300px) { .site-header .header-tel { display: none; } }
/* style.css swaps the nav for the burger at 860px, but with nothing allowed to
   shrink the six-link retail nav + switch + CTA still overran the row between
   861 and ~980px. Hand over to the burger EARLIER (980px) so the inline nav is
   only ever shown at a width that genuinely fits it. Everything the header
   drops is present in the drawer. */
@media (max-width: 1180px) { .site-header .aud-switch { display: none; } }
@media (max-width: 980px) {
  .site-header .nav { display: none; }
  .site-header .burger { display: flex; }
}

/* In the drawer the switch is full-width and always visible. */
.drawer .aud-switch { display: inline-flex; width: 100%; }
.drawer .aud-switch a { flex: 1; justify-content: center; }

/* ═══ Horizontal reveals on narrow screens ═══════════════════════════════
   [data-anim="left"|"right"] start offset by 32px on the X axis. Inside a
   full-width grid on a phone that pushes the element past the viewport and
   creates horizontal scroll (caught at 390px on the retail sectors grid,
   2026-09-12). Below the desktop breakpoint, fall back to a vertical reveal —
   same gesture, no overflow. 1100px covers the tablet range where a 2-col
   grid still sits flush to the gutters. */
@media (max-width: 1220px) {
  .js:not(.reduce-motion):not(.motion-failed) [data-anim="left"],
  .js:not(.reduce-motion):not(.motion-failed) [data-anim="right"] {
    transform: translateY(24px);
  }
}

/* ═══ Sector tiles as links ═══════════════════════════════════════════════
   2026-09-12 — the retail Commercial block was condensed to a teaser and its
   sector tiles became anchors into business.html#sectors. They were <div>s,
   so they need the link defaults removed and a hover affordance added. */
a.sector { text-decoration: none; color: inherit; display: block; }
a.sector:hover {
  border-color: var(--primary-soft);
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}
a.sector { transition: transform .3s var(--ease), box-shadow .3s var(--ease), border-color .3s var(--ease); }
a.sector:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }

/* ═══════════════════════════════════════════════════════════════════════════
   ROYAL LAYER — 2026-10-01
   ---------------------------------------------------------------------------
   Owner-directed: lift both Retail and Commercial to the editorial register of
   the printed commercial prospectus. Three moves do the work:

     1. A SERIF DISPLAY FACE for headlines. The prospectus sets its headlines
        in a high-contrast serif with italic accent phrases; that single choice
        is most of what reads as "royal". Body copy stays Inter.
     2. REAL PHOTOGRAPHY, extracted from the prospectus (assets/img/photo/).
     3. DEEP NAVY + GOLD for the dark sections, replacing flat purple fills.

   Additive: new classes only. The existing purple/gold token system is
   untouched and still governs every component not opted in here. */

/* Cormorant Garamond was already being downloaded by index.html and never
   used by any rule (dead weight on the critical path). It is now the display
   face, so the request finally earns itself. */
:root {
  --font-royal: 'Cormorant Garamond', 'Times New Roman', Georgia, serif;
  --navy:        #0E2338;
  --navy-deep:   #081726;
  --navy-soft:   #16304A;
  --royal-gold:  #C8A24A;
  --royal-ivory: #F7F4ED;
}

/* ── ONE PALETTE ──────────────────────────────────────────────────────────
   2026-10-02 — the royal layer introduced navy+gold ALONGSIDE the original
   purple+gold, which left both pages visibly mixed: a navy hero above a purple
   calculator above a navy chemistry band above a purple footer, and a purple
   header over a navy page.

   Rather than hand-patching each section, the BRAND TOKENS themselves are
   repointed to the navy family. Every component that reads --primary* — header,
   footer, buttons, chips, borders, focus rings, the .mesh gradients, the Elite
   card — follows automatically and stays in step. The gold is unified on the
   prospectus value (#C8A24A), which is slightly deeper than the old #D4AF37 and
   reads as metal rather than yellow on a navy ground.

   Nothing structural changes: this is a palette repoint, not a rewrite. The
   original purple values are preserved in style.css and would be restored by
   deleting this block. */
:root {
  --primary:         #16304A;   /* was #6D3B9E */
  --primary-deep:    #0E2338;
  --primary-deepest: #081726;
  --primary-light:   #2C4F72;
  --primary-pale:    #EEF2F6;
  --primary-soft:    #C9D6E2;

  --gold:       #C8A24A;
  --gold-deep:  #A8842F;
  --gold-light: #E0C176;
  --gold-pale:  #F7F1E2;

  --bg:        #FAFBFC;
  --card:      #FFFFFF;
  --card-alt:  #F2F5F8;
  --line:      #E2E7EC;

  --ink:   #16202B;
  --muted: #5C6773;
  --hint:  #93A0AD;

  --hero-gradient: linear-gradient(135deg, #081726 0%, #16304A 55%, #2C4F72 100%);

  /* Elite/dark card tier moves to navy too. */
  --elite-bg:       #0E2338;
  --elite-bg-soft:  #1C3C5A;
  --elite-hairline: #2C4F72;
  --elite-ivory:    #F7F4ED;

  --shadow-sm: 0 1px 2px rgba(14,35,56,.06), 0 1px 3px rgba(14,35,56,.05);
  --shadow-md: 0 4px 16px rgba(14,35,56,.09), 0 1px 3px rgba(14,35,56,.06);
  --shadow-lg: 0 18px 44px rgba(14,35,56,.16), 0 4px 12px rgba(14,35,56,.08);
}

/* Dark mode: deep navy-charcoal, same family. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg:       #0A121C;
    --card:     #142231;
    --card-alt: #1B2D3F;
    --line:     #2A3F55;
    --ink:      #EDF2F7;
    --muted:    #A8B6C4;
    --hint:     #78899A;
    --primary:       #6E9BC8;
    --primary-light: #8FB4DA;
    --primary-pale:  #1B2D3F;
    --primary-soft:  #33506E;
    --gold-pale:     #332C16;
  }
}

/* ── Display headings ─────────────────────────────────────────────────────
   .royal turns any heading into the prospectus voice. The accent span is the
   italic phrase the prospectus uses to carry the emphasis. */
.royal {
  font-family: var(--font-royal);
  font-weight: 600;
  letter-spacing: -.012em;
  line-height: 1.08;
}
.royal em, .royal .accent {
  font-style: italic;
  font-weight: 500;
  color: var(--primary);
}
.mesh-dark .royal em, .mesh-dark .royal .accent,
.royal-dark .royal em, .royal-dark .royal .accent { color: var(--royal-gold); }

/* Hairline rule + letterspaced kicker, straight from the prospectus. */
.royal-kicker {
  display: flex; align-items: center; gap: .8rem;
  font: 600 .72rem/1 var(--font-body);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--primary); margin-bottom: 1.1rem;
}
.royal-kicker::before {
  content: ""; width: 34px; height: 2px; flex: none;
  background: var(--royal-gold); border-radius: 2px;
}
.royal-dark .royal-kicker, .mesh-dark .royal-kicker { color: var(--royal-gold); }

/* ── Deep navy section ────────────────────────────────────────────────── */
.royal-dark {
  position: relative; isolation: isolate;
  background:
    radial-gradient(62% 72% at 16% 4%, rgba(200,162,74,.10) 0%, transparent 60%),
    radial-gradient(70% 76% at 84% 96%, rgba(22,48,74,.85) 0%, transparent 64%),
    linear-gradient(160deg, var(--navy-deep) 0%, var(--navy) 55%, var(--navy-soft) 100%);
  color: var(--royal-ivory);
}
.royal-dark h1, .royal-dark h2, .royal-dark h3, .royal-dark h4 { color: #fff; }
.royal-dark p  { color: rgba(247,244,237,.82); }

/* ── Stat band (prospectus "By the numbers") ──────────────────────────── */
.stat-band {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  border-top: 1px solid rgba(255,255,255,.14);
  border-bottom: 1px solid rgba(255,255,255,.14);
}
.stat-band > div {
  padding: 1.7rem 1.3rem;
  border-right: 1px solid rgba(255,255,255,.1);
}
.stat-band > div:last-child { border-right: 0; }
.stat-band .n {
  font: 600 clamp(2rem, 3.6vw, 2.9rem)/1 var(--font-royal);
  color: #fff; display: block; margin-bottom: .55rem;
}
.stat-band .n sup, .stat-band .n .sfx {
  color: var(--royal-gold); font-size: .5em; vertical-align: super;
  margin-left: .06em; font-family: var(--font-body); font-weight: 700;
}
.stat-band .n .unit-sm {
  font-size: .42em; color: rgba(255,255,255,.72); margin-left: .25em;
  font-family: var(--font-body); font-weight: 500; letter-spacing: .01em;
}
.stat-band .l {
  font: 600 .68rem/1.5 var(--font-body);
  letter-spacing: .13em; text-transform: uppercase;
  color: rgba(247,244,237,.62);
}
@media (max-width: 620px) {
  .stat-band > div { border-right: 0; border-bottom: 1px solid rgba(255,255,255,.1); }
}

/* ── Photo card (process stage / sector) ──────────────────────────────── */
.pcard {
  display: grid; grid-template-columns: 148px 1fr;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 14px; overflow: hidden;
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), border-color .4s var(--ease);
}
.pcard:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: var(--primary-soft); }
.pcard figure { margin: 0; position: relative; background: var(--card-alt); }
.pcard img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pcard .step-badge {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--navy); color: #fff;
  font: 600 .78rem/1 var(--font-royal);
}
.pcard .body { padding: 1.15rem 1.3rem; }
.pcard .tag {
  font: 700 .64rem/1 var(--font-body); letter-spacing: .13em;
  text-transform: uppercase; color: var(--royal-gold); display: block; margin-bottom: .5rem;
}
.pcard h3 { font: 600 1.06rem/1.25 var(--font-royal); margin: 0 0 .45rem; color: var(--ink); }
.pcard p  { font-size: .85rem; line-height: 1.6; color: var(--muted); margin: 0; }
@media (max-width: 560px) {
  .pcard { grid-template-columns: 1fr; }
  .pcard figure { height: 170px; }
}

/* ── Full-bleed feature photo ─────────────────────────────────────────── */
.photo-feature {
  position: relative; border-radius: 18px; overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.photo-feature img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-feature .cap {
  position: absolute; left: 16px; bottom: 16px;
  display: inline-flex; align-items: center; gap: .55rem;
  padding: 9px 16px; border-radius: var(--radius-pill);
  background: rgba(14,35,56,.82); backdrop-filter: blur(10px);
  color: #fff; font: 600 .82rem/1 var(--font-body);
}
.photo-feature .cap::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%;
  background: var(--royal-gold); flex: none;
}

/* ── ISO / certification chips ────────────────────────────────────────── */
.cert-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: .9rem; }
.cert {
  border: 1px solid var(--line); border-left: 3px solid var(--royal-gold);
  border-radius: 10px; padding: 1rem 1.15rem; background: var(--card);
}
.cert strong { display: block; font: 600 1.18rem/1 var(--font-royal); color: var(--ink); margin-bottom: .35rem; }
.cert span { font: 600 .64rem/1.4 var(--font-body); letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.royal-dark .cert { background: rgba(255,255,255,.05); border-color: rgba(255,255,255,.14); border-left-color: var(--royal-gold); }
.royal-dark .cert strong { color: #fff; }
.royal-dark .cert span { color: rgba(247,244,237,.6); }

/* ── Closing pull-quote ───────────────────────────────────────────────── */
.pullquote {
  font: italic 500 clamp(1.15rem, 2.4vw, 1.65rem)/1.45 var(--font-royal);
  color: var(--ink); max-width: 46ch;
}
.royal-dark .pullquote { color: #fff; }
