/* =====================================================================
   ShopifyDevd — custom.css
   Carries the bespoke styling that theme.json can't express:
   layout, animation, complex typography, hover states.
   Token reference: theme.json (var --wp--preset--*)
===================================================================== */

/* ---------- 0. Resets & base ---------- */
/* Theme tokens. Variable NAMES are kept stable across themes (so existing
   rules using `var(--ink)` for backgrounds and `var(--bone)` for text Just
   Work in both modes); only the COLOR VALUES swap.

   Accent rule: `--volt` is the graphic accent (button bg, dot, cursor) —
   identical in both modes. `--volt-text` is the readable accent for TEXT,
   which has to darken on cream or it becomes illegible. */

:root {
  /* DARK (default) */
  --ink:        #0A0A0A;
  --graphite:   #141414;
  --rule:       #262626;
  --mute:       #8A8A85;
  --bone:       #F2EEE3;
  --bone-soft:  #E8E3D6;
  --volt:       #D8FF3D;
  --volt-text:  #D8FF3D;  /* legible on dark, same as graphic volt */
  --ember:      #FF4D1F;
  --header-fade: rgba(10,10,10,0.85);

  /* STABLE across themes. Use for text/icons that sit on a volt background —
     it must stay dark in BOTH modes so the volt button stays readable.
     Don't use --ink for this; --ink swaps with theme. */
  --accent-fg:  #0A0A0A;

  --ease-expo:  cubic-bezier(0.16, 1, 0.3, 1);
  --ease-power: cubic-bezier(0.65, 0, 0.35, 1);
  --pad-x:      clamp(24px, 5vw, 120px);
}

:root[data-theme="light"] {
  /* LIGHT — warm cream palette, never pure white. */
  --ink:        #F2EEE3;  /* was bg-dark, now bg-cream */
  --graphite:   #E8E2D2;  /* slight surface elevation */
  --rule:       #D2CCBC;  /* warm gray border */
  --mute:       #6A6A65;  /* warm gray for secondary text */
  --bone:       #0A0A0A;  /* was text-cream, now text-ink */
  --bone-soft:  #2A2A28;  /* near-black for body */
  --volt:       #D8FF3D;  /* keep graphic volt — used on dark buttons / accents */
  --volt-text:  #4F7515;  /* darker olive — legible on cream, keeps "green" identity */
  --ember:      #C73914;  /* slightly darker ember for cream */
  --header-fade: rgba(242,238,227,0.92);
}

/* Smooth crossfade when the theme attribute flips. Limited to the properties
   that actually swap, to avoid stomping on hover/scroll transitions. */
body, .site-header, .site-footer, .section, .value-card, .work-item__visual,
.quotes__quote, .contact-form__input, .contact-form__field, .services__item,
.process__node, .site-footer__list a, .quotes__prev, .quotes__next,
.contact__badges li, .about__portrait, .site-header__brand-link, .cursor {
  transition: background-color 0.5s var(--ease-expo),
              color 0.5s var(--ease-expo),
              border-color 0.5s var(--ease-expo),
              fill 0.5s var(--ease-expo),
              stroke 0.5s var(--ease-expo);
}

* { -webkit-tap-highlight-color: transparent; }

/* Skip link — visually hidden until focused. Sits ABOVE the fixed header
   when active so keyboard users can jump past nav to <main id="main">. */
.skip-link {
  position: absolute;
  top: -100px;
  left: 16px;
  z-index: 10000;
  padding: 12px 20px;
  background: var(--volt);
  color: var(--accent-fg);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 600;
  text-decoration: none;
  border-radius: 6px;
  transition: top 0.2s var(--ease-expo);
}
.skip-link:focus {
  top: 16px;
  outline: 2px solid var(--accent-fg);
  outline-offset: 2px;
}

/* Improved focus rings everywhere — Lighthouse a11y check + keyboard usability.
   Only :focus-visible (so mouse clicks don't show a ring; keyboard does). */
:focus-visible {
  outline: 2px solid var(--volt);
  outline-offset: 3px;
  border-radius: 2px;
}
/* Suppress Webkit's outline on links/buttons that already paint a focus ring. */
.skip-link:focus, .skip-link:focus-visible { outline-offset: 2px; }

html {
  scroll-behavior: smooth;
  /* Fixed header is ~100px; nudge anchor scrolling so the target heading
     lands below the header instead of being hidden underneath it. */
  scroll-padding-top: 110px;
  background: var(--ink);
}
@media (max-width: 880px) {
  html { scroll-padding-top: 80px; }
}

body {
  background: var(--ink);
  color: var(--bone);
  font-family: 'Inter Tight', system-ui, sans-serif;
  font-feature-settings: 'ss01', 'cv11';
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

/* Lenis smooth scroll */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: clip; }

/* Typography polish */
em, .hero__em {
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-variation-settings: 'opsz' 144;
  letter-spacing: -0.02em;
}

.has-mono-font-family { letter-spacing: 0.06em; text-transform: uppercase; }

/* Block default overrides */
.wp-block-buttons { gap: 16px; }
.wp-block-button .wp-element-button {
  transition: background-color 0.4s var(--ease-expo), color 0.4s var(--ease-expo), transform 0.5s var(--ease-expo);
  will-change: transform;
}

/* Outline button */
.btn-pill.is-style-outline .wp-element-button,
.btn-pill .wp-element-button {
  border-radius: 999px;
}
.is-style-outline .wp-element-button {
  background: transparent;
  color: var(--bone);
  border: 1px solid var(--rule);
}
.is-style-outline .wp-element-button:hover {
  background: var(--bone);
  color: var(--ink);
  border-color: var(--bone);
}

/* Link-style button */
.btn-link .wp-element-button,
.is-style-link .wp-element-button {
  background: transparent !important;
  color: var(--bone) !important;
  padding: 14px 0 !important;
  border-radius: 0 !important;
  border-bottom: 1px solid var(--rule);
  letter-spacing: 0.06em;
}
.btn-link .wp-element-button:hover,
.is-style-link .wp-element-button:hover {
  border-bottom-color: var(--volt);
  color: var(--volt-text) !important;  /* readable on cream in light mode */
}

/* Selection — volt is stable, text on it must stay dark */
::selection { background: var(--volt); color: var(--accent-fg); }

/* ---------- 1. Header ---------- */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 80;
  background: linear-gradient(to bottom, var(--header-fade), transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding-left: var(--pad-x) !important;
  padding-right: var(--pad-x) !important;
}
.site-header__inner {
  max-width: none;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
.site-header__brand {
  display: inline-flex;
  margin: 0;
  line-height: 0;
  /* `color` becomes the bone-colored stroke source for the SVG via currentColor */
  color: var(--bone);
}
.site-header__brand-link {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: inherit;
  outline: none;
}
.site-header__brand-link:focus-visible {
  outline: 2px solid var(--volt);
  outline-offset: 4px;
  border-radius: 4px;
}
.site-header__logo {
  display: block;
  width: auto;
  height: 64px;
  overflow: visible;
  transition: transform 0.5s var(--ease-expo);
  will-change: transform;
}
/* On hover the tag swings back toward upright — like you've picked it up. */
.site-header__brand-link:hover .site-header__logo-tag {
  transform: rotate(0deg);
  transform-origin: 110px 65px;
  transition: transform 0.6s var(--ease-expo);
}
.site-header__logo-tag {
  transition: transform 0.6s var(--ease-expo);
  transform-origin: 110px 65px;
}
@media (max-width: 880px) {
  .site-header__logo { height: 56px; }
  /* Mobile header collapses to logo + hamburger only. The theme toggle and
     Book Call pill move into the slide-out drawer (same JS hooks, see
     parts/header.html). Cleaner header, more thumb room. */
  .site-header__actions .theme-toggle:not(.theme-toggle--in-drawer) { display: none; }
  .site-header .site-header__cta { display: none; }
}

.site-nav { gap: 32px; }
.site-nav a { text-decoration: none; transition: color 0.3s var(--ease-expo); }
.site-nav a:hover { color: var(--volt-text); }

@media (max-width: 880px) {
  .site-nav { display: none !important; }
}

/* ---------- Mobile nav (hamburger + slide-out drawer) ----------
   Hidden above 880px (desktop has the mega menu). At <= 880px the trigger
   appears in .site-header__actions and toggles the overlay below. */
.mobile-nav-trigger {
  display: none; /* shown via media query */
  width: 44px; /* WCAG 2.5.5 AAA touch target */
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--bone);
  cursor: pointer;
  align-items: center;
  justify-content: center;
  margin-left: 8px;
  transition: border-color 0.3s var(--ease-expo), background-color 0.3s var(--ease-expo);
  -webkit-tap-highlight-color: transparent;
}
.mobile-nav-trigger:hover { border-color: var(--volt); }
.mobile-nav-trigger__bars {
  display: inline-flex;
  flex-direction: column;
  gap: 4px;
  width: 18px;
}
.mobile-nav-trigger__bars > span {
  display: block;
  width: 100%;
  height: 2px;
  background: currentColor;
  border-radius: 1px;
  transition: transform 0.3s var(--ease-expo), opacity 0.2s linear;
}
.mobile-nav-trigger[aria-expanded="true"] .mobile-nav-trigger__bars > span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.mobile-nav-trigger[aria-expanded="true"] .mobile-nav-trigger__bars > span:nth-child(2) {
  opacity: 0;
}
.mobile-nav-trigger[aria-expanded="true"] .mobile-nav-trigger__bars > span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* The overlay itself sits outside the header in document order so its z-index
   stack is independent of the fixed header's blur. Hidden above 880px and
   when the JS hasn't been initialised yet (defensive). */
.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(8, 8, 8, 0.6);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: flex;
  justify-content: flex-end;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.3s var(--ease-expo), visibility 0.3s;
}
.mobile-nav[hidden] { display: none; }
.mobile-nav[data-open="true"] {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
.mobile-nav__panel {
  width: min(420px, 100%);
  height: 100%;
  background: var(--ink);
  display: flex;
  flex-direction: column;
  padding: 28px;
  transform: translateX(100%);
  transition: transform 0.4s var(--ease-expo);
  border-left: 1px solid var(--rule);
}
.mobile-nav[data-open="true"] .mobile-nav__panel {
  transform: translateX(0);
}
.mobile-nav__head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 32px;
}
.mobile-nav__brand {
  font-family: 'Caveat', 'Brush Script MT', cursive;
  font-size: 28px;
  text-decoration: none;
  color: var(--bone);
}
.mobile-nav__brand strong { font-weight: 600; }
.mobile-nav__brand em { color: var(--volt); font-style: normal; }
.mobile-nav__close {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--bone);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: border-color 0.3s var(--ease-expo);
}
.mobile-nav__close:hover { border-color: var(--volt); }
.mobile-nav__list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.mobile-nav__list a {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 18px 4px;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 28px;
  font-weight: 400;
  color: var(--bone);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  transition: color 0.3s var(--ease-expo), padding 0.3s var(--ease-expo);
  min-height: 44px;
}
.mobile-nav__list a:hover,
.mobile-nav__list a:focus-visible {
  color: var(--volt-text);
  padding-left: 8px;
}
.mobile-nav__list a span {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 14px;
  color: var(--mute);
}
.mobile-nav__foot {
  margin-top: auto;
  padding-top: 32px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.mobile-nav__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 16px 20px;
  background: var(--volt);
  color: var(--accent-fg);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  border-radius: 999px;
  text-decoration: none;
  min-height: 48px;
  transition: gap 0.3s var(--ease-expo);
}
.mobile-nav__cta:hover { gap: 14px; }
.mobile-nav__meta {
  margin: 0;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--mute);
  text-align: center;
}

/* Drawer-specific theme toggle: full-width settings row instead of a 44px
   circle (which doesn't read as a tappable item next to a labelled CTA).
   The icon-swap CSS above works unchanged because it keys off `[data-theme]`
   on <html>, not the toggle's class. */
.theme-toggle--in-drawer {
  width: 100%;
  height: auto;
  min-height: 48px;
  border-radius: 999px;
  border: 1px solid var(--rule);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 12px 18px;
  background: transparent;
  color: var(--bone);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.3s var(--ease-expo), background-color 0.3s var(--ease-expo);
}
.theme-toggle--in-drawer:hover { border-color: var(--volt); }
/* Override the absolute centring used by the circular header variant — in
   the drawer we want the icon inline with the text label. Both icons stack
   in the same place and CSS opacity swaps which one shows (controlled by
   `[data-theme]` on <html>, see rules above). */
.theme-toggle--in-drawer .theme-toggle__icon {
  position: static;
  inset: auto;
  margin: 0;
  width: 18px;
  height: 18px;
}
.theme-toggle--in-drawer .theme-toggle__icon--sun,
.theme-toggle--in-drawer .theme-toggle__icon--moon {
  /* Stack the two icons on top of each other so only the active one is
     visible (the other has opacity:0). Without this, both would render
     side-by-side and create a 2-icon row. */
  position: absolute;
  left: 18px;
  top: 50%;
  transform-origin: center;
  margin-top: -9px;
}
:root[data-theme="dark"]  .theme-toggle--in-drawer .theme-toggle__icon--moon { transform: rotate(-90deg) scale(0.6); margin-top: -9px; }
:root[data-theme="dark"]  .theme-toggle--in-drawer .theme-toggle__icon--sun  { transform: rotate(0) scale(1); margin-top: -9px; }
:root[data-theme="light"] .theme-toggle--in-drawer .theme-toggle__icon--sun  { transform: rotate(90deg) scale(0.6); margin-top: -9px; }
:root[data-theme="light"] .theme-toggle--in-drawer .theme-toggle__icon--moon { transform: rotate(0) scale(1); margin-top: -9px; }
.theme-toggle--in-drawer { padding-left: 46px; position: relative; }
.theme-toggle--in-drawer .theme-toggle__label { display: inline-block; }

/* Body scroll lock when the drawer is open — JS toggles .has-mobile-nav. */
body.has-mobile-nav { overflow: hidden; }

/* Mobile sticky CTA — single-tap "Book a call" button bottom-right.
   Hidden on desktop (the header already shows a Book Call pill). On mobile
   it slides in once the user scrolls past the hero section so it doesn't
   compete with the lede. The visit→form path becomes one tap, anywhere. */
.sticky-cta {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 90;
  display: none; /* shown via media query + .is-visible class */
  align-items: center;
  gap: 8px;
  padding: 14px 18px;
  background: var(--volt);
  color: var(--accent-fg);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
  border-radius: 999px;
  text-decoration: none;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(0, 0, 0, 0.1);
  min-height: 48px;
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.4s var(--ease-expo), transform 0.4s var(--ease-expo);
  pointer-events: none;
}
.sticky-cta.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.sticky-cta__arrow {
  font-size: 14px;
  transition: transform 0.3s var(--ease-expo);
}
.sticky-cta:hover .sticky-cta__arrow {
  transform: translateX(2px) translateY(-2px);
}
@media (max-width: 880px) {
  .sticky-cta { display: inline-flex; }
}
@media (prefers-reduced-motion: reduce) {
  .sticky-cta { transition: opacity 0.15s; }
}

@media (max-width: 880px) {
  .mobile-nav-trigger { display: inline-flex; }
}
@media (min-width: 881px) {
  .mobile-nav { display: none !important; }
}
@media (prefers-reduced-motion: reduce) {
  .mobile-nav, .mobile-nav__panel { transition: opacity 0.15s, visibility 0.15s; }
  .mobile-nav[data-open="true"] .mobile-nav__panel { transform: none; }
}

/* Theme toggle — sits between nav and CTA. Shows the icon for the mode
   you'd switch TO (sun in dark mode, moon in light mode). */
.site-header__actions {
  display: inline-flex;
  align-items: center;
}
.theme-toggle {
  /* 44×44 = WCAG 2.5.5 AAA target size. The internal icon stays 18px so
     visual size is unchanged; the hit area expands with the border-box. */
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--bone);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  transition: border-color 0.3s var(--ease-expo), color 0.3s, transform 0.4s var(--ease-expo);
}
.theme-toggle:hover {
  border-color: var(--volt);
  color: var(--volt-text);
  transform: rotate(15deg);
}
.theme-toggle:focus-visible {
  outline: 2px solid var(--volt);
  outline-offset: 4px;
}
.theme-toggle__icon {
  position: absolute;
  inset: 0;
  margin: auto;
  transition: opacity 0.4s var(--ease-expo), transform 0.4s var(--ease-expo);
}
/* Dark mode → show sun (click to go light). Hide moon. */
:root[data-theme="dark"]  .theme-toggle__icon--moon { opacity: 0; transform: rotate(-90deg) scale(0.6); }
:root[data-theme="dark"]  .theme-toggle__icon--sun  { opacity: 1; transform: rotate(0) scale(1); }
/* Light mode → show moon (click to go dark). Hide sun. */
:root[data-theme="light"] .theme-toggle__icon--sun  { opacity: 0; transform: rotate(90deg) scale(0.6); }
:root[data-theme="light"] .theme-toggle__icon--moon { opacity: 1; transform: rotate(0) scale(1); }

/* ---------- 2. Sections (shared) ---------- */
.site-main { padding-top: 0; }

/* Full-bleed sections: no container, fluid edge padding via --pad-x.
   All overrides use !important — both patterns' inline styles AND WordPress's
   auto-generated constrained-layout selectors (`.is-layout-constrained > *`)
   try to set max-width/margins, and we deliberately defeat both. */
.section {
  position: relative;
  max-width: none !important;
  width: 100% !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
  padding-left: var(--pad-x) !important;
  padding-right: var(--pad-x) !important;
}
.section__head {
  max-width: 1280px;
  margin-bottom: clamp(40px, 6vw, 96px);
  padding-left: 0 !important;
  padding-right: 0 !important;
}

/* Site footer also goes edge-to-edge with the same rhythm. */
.site-footer {
  padding-left: var(--pad-x) !important;
  padding-right: var(--pad-x) !important;
}
.section__eyebrow {
  margin: 0 0 24px;
  letter-spacing: 0.12em;
}
.section__title {
  margin: 0;
  max-width: 14ch;
}
.section__title em { display: inline; }

/* ---------- 3. Hero ---------- */
.section--hero {
  min-height: 100svh;
  padding-top: clamp(120px, 14vw, 200px) !important;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  position: relative;
  overflow: clip;
}
/* On mobile the 100svh hero + 120px top padding leaves a big empty band
   above the headline (content is justify-content: flex-end). Reduce both
   so the hero feels purpose-built rather than half-empty. */
@media (max-width: 768px) {
  .section--hero {
    min-height: 80svh;
    padding-top: 80px !important;
  }
}

.hero__marquee {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  pointer-events: none;
  z-index: 0;
  mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
}
.hero__marquee-track {
  display: flex;
  gap: 4vw;
  white-space: nowrap;
  font-family: 'Inter Tight', sans-serif;
  font-weight: 600;
  font-size: clamp(120px, 22vw, 360px);
  letter-spacing: -0.05em;
  color: transparent;
  /* Outline tint follows the text color (currentColor on bone => text@6%) */
  -webkit-text-stroke: 1px color-mix(in srgb, var(--bone) 8%, transparent);
  animation: marquee 60s linear infinite;
  will-change: transform;
}
.hero__marquee-track span { display: inline-block; padding: 0 1vw; }
@keyframes marquee {
  from { transform: translate3d(0,0,0); }
  to   { transform: translate3d(-50%,0,0); }
}

.hero__title {
  position: relative;
  z-index: 2;
  max-width: 18ch;
  margin: 24px 0 0;
  line-height: 0.88;
  /* Override the hero font-size cap so the title scales properly
     on ultrawide screens now that the section is full-bleed. */
  font-size: clamp(64px, 13vw, 280px) !important;
}

.hero__meta {
  position: relative;
  z-index: 2;
  margin-top: clamp(48px, 8vw, 120px) !important;
  border-top: 1px solid var(--rule);
  padding-top: 32px;
}

.hero__lede {
  margin: 0;
  max-width: 42ch;
  color: var(--bone-soft);
}

.hero__metric {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 16px;
}
.hero__metric-number {
  margin: 0;
  font-feature-settings: 'tnum';
  line-height: 0.9;
  font-weight: 500;
}
.hero__metric-label {
  margin: 0;
  letter-spacing: 0.1em;
  max-width: 32ch;
}

.hero__scroll {
  position: absolute;
  bottom: 32px;
  right: var(--pad-x);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  z-index: 2;
}
.hero__scroll-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.18em;
  color: var(--mute);
}
.hero__scroll-line {
  width: 1px;
  height: 56px;
  background: linear-gradient(to bottom, var(--bone), transparent);
  transform-origin: top;
  animation: scrollPulse 2.4s var(--ease-expo) infinite;
}
@keyframes scrollPulse {
  0%   { transform: scaleY(0); opacity: 0; }
  20%  { opacity: 1; }
  60%  { transform: scaleY(1); opacity: 1; }
  100% { transform: scaleY(1); opacity: 0; transform-origin: bottom; }
}

@media (max-width: 768px) {
  .hero__meta .wp-block-column { flex-basis: 100% !important; }
  .hero__scroll { display: none; }
}

/* ---------- 4. Value rail ----------
   This section keeps padding 0 so the rail bleeds off the right edge —
   that off-canvas peek is the cue that more content scrolls horizontally.
   The section__head gets the standard --pad-x re-applied so it aligns
   with the rail's first card. */
.section--value { padding-left: 0 !important; padding-right: 0 !important; }
.section--value .section__head {
  padding-left: var(--pad-x) !important;
  padding-right: var(--pad-x) !important;
  max-width: none;
}

.value-rail {
  position: relative;
  margin-top: clamp(40px, 6vw, 80px);
  overflow: hidden;
}
.value-rail__track {
  display: flex;
  gap: 24px;
  padding: 0 var(--pad-x) 32px;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.value-rail__track::-webkit-scrollbar { display: none; }

.value-card {
  flex: 0 0 min(520px, 80vw);
  scroll-snap-align: start;
  background: var(--graphite);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 40px 32px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-height: 440px;
  position: relative;
  transition: border-color 0.5s var(--ease-expo), background 0.5s var(--ease-expo);
}
.value-card:hover {
  border-color: var(--volt);
  /* Theme-aware: slightly different shade from --graphite in both modes.
     Was hard-coded #161616 which made the card unreadable in light mode. */
  background: var(--ink);
}
.value-card__num {
  font-family: 'Inter Tight', sans-serif;
  font-size: clamp(48px, 6vw, 88px);
  font-weight: 500;
  line-height: 1;
  color: var(--volt-text);
  letter-spacing: -0.04em;
}
.value-card__title {
  font-family: 'Inter Tight', sans-serif;
  font-size: clamp(28px, 2.4vw, 38px);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.025em;
  margin: 0;
}
.value-card__body {
  color: var(--bone-soft);
  margin: 0;
  font-size: 16px;
  line-height: 1.55;
}
.value-card__list {
  margin-top: auto;
  padding: 16px 0 0;
  list-style: none;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--mute);
  text-transform: uppercase;
}

.value-rail__progress {
  height: 1px;
  background: var(--rule);
  margin: 0 var(--pad-x);
}
.value-rail__progress-bar {
  display: block;
  height: 100%;
  width: 25%;
  background: var(--volt-text);  /* darker olive in light mode for visibility */
  transform-origin: left;
  transition: width 0.4s var(--ease-expo);
}

/* ---------- 5. Featured work — Spotlight + Marquee ----------
   Legacy stacked-card layout (.work-item, etc.) was archived to
   assets/css/legacy.css in 2.0.0. That file is NOT enqueued — copy
   rules back into this section if you need to revert. */
/* New home-page work showcase (replaces the legacy stacked .work-item list).
   ┌──────────────────────────────────────────────────────────┐
   │  (03) SELECTED WORK · 10 case studies                     │
   │  Recent builds. Real numbers.                             │
   │  A new spotlight every Wednesday. Hover any card to peek. │
   ├────────────────────────────┬─────────────────────────────┤
   │  SPOTLIGHT  EARTHMEAL  …    │   [ brand-color visual    ] │
   │  Title with em                  │   [ wordmark + logo       ] │
   │  Problem · Approach · Result    │   [ Hover to peek ↘       ] │
   │  View full case study ↗         │                              │
   └─────────────────────────────────┴──────────────────────────┘
   ▸▸▸  marquee row 1 (left → right) · 9 cards                  ▸▸▸
   ◂◂◂  marquee row 2 (right → left) · 9 cards (reverse order)  ◂◂◂

   The spotlight is resolved server-side by shopifydevd_get_spotlight_case().
   Marquee cards trigger the same .work-popup as the spotlight via
   data-popup-href (one popup rendered per case in a shared container —
   marquee duplicates for the seamless loop don't multiply popup HTML). */

.spotlight-head { margin-bottom: clamp(40px, 5vw, 64px); }
.spotlight-head__count { color: var(--bone); }
.spotlight-head__lede {
  margin: 18px 0 0;
  max-width: 56ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--bone-soft);
}

/* --- Spotlight --- */
.spotlight {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(24px, 3vw, 40px);
  align-items: stretch;
  margin-bottom: clamp(48px, 6vw, 80px);
}
.spotlight__text {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 2.4vw, 32px);
  padding: clamp(28px, 3.5vw, 44px);
  border-radius: 22px;
  background: linear-gradient(135deg, var(--brand-from, #15140f), var(--brand-to, #0a0a08));
  border: 1px solid var(--rule);
}
.spotlight__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 18px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(243, 239, 230, 0.55);
}
.spotlight__label {
  color: var(--brand-accent, var(--volt));
  font-weight: 600;
  border: 1px solid currentColor;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 10px;
}
.spotlight__client {
  color: #f3efe6;
  font-weight: 500;
}
.spotlight__title {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 400;
  font-size: clamp(34px, 4vw, 56px);
  line-height: 1.08;
  letter-spacing: -0.01em;
  margin: 0;
  color: #f3efe6;
}
.spotlight__title em {
  color: var(--brand-accent, var(--volt));
  font-style: italic;
}
.spotlight__par {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  margin: 0;
  padding-top: 22px;
  border-top: 1px solid rgba(243, 239, 230, 0.12);
}
.spotlight__par dt {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brand-accent, var(--volt));
  margin: 0 0 8px;
}
.spotlight__par dd {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: rgba(243, 239, 230, 0.85);
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.spotlight__cta {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: auto;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #0a0a0a;
  background: var(--brand-accent, var(--volt));
  padding: 14px 22px;
  border-radius: 999px;
  text-decoration: none;
  transition: gap 0.3s var(--ease-expo), transform 0.4s var(--ease-expo);
}
.spotlight__cta:hover { gap: 14px; transform: translateY(-2px); }

.spotlight__visual {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 22px;
  overflow: hidden;
  background: linear-gradient(135deg, var(--brand-from, #15140f), var(--brand-to, #0a0a08));
  border: 1px solid var(--rule);
  text-decoration: none;
  isolation: isolate;
  transition: transform 0.6s var(--ease-expo);
  min-height: 420px;
}
.spotlight__visual:hover { transform: scale(1.005); }
.spotlight__visual::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 30% 25%, rgba(255,255,255,0.07), transparent 60%);
  pointer-events: none;
}
.spotlight__wordmark {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(80px, 12vw, 180px);
  line-height: 1;
  color: rgba(243, 239, 230, 0.06);
  letter-spacing: -0.02em;
  user-select: none;
  pointer-events: none;
  white-space: nowrap;
}
.spotlight__visual-logo {
  position: relative;
  z-index: 1;
  max-width: 60%;
  max-height: 50%;
  width: auto;
  height: auto;
  object-fit: contain;
  filter: brightness(0) invert(1);
  opacity: 0.95;
  transition: transform 0.5s var(--ease-expo);
}
.spotlight__visual:hover .spotlight__visual-logo { transform: scale(1.04); }
.spotlight__peek-hint {
  position: absolute;
  bottom: 22px;
  right: 22px;
  z-index: 2;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(243, 239, 230, 0.5);
  border: 1px solid rgba(243, 239, 230, 0.18);
  padding: 6px 12px;
  border-radius: 999px;
  backdrop-filter: blur(6px);
}

/* --- Marquee (two rows, opposite directions) --- */
.marquee {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-top: clamp(32px, 4vw, 56px);
}
.marquee__row {
  position: relative;
  overflow: hidden;
  /* Soft fade at both edges so cards appear/disappear instead of clipping */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 80px, #000 calc(100% - 80px), transparent);
          mask-image: linear-gradient(90deg, transparent, #000 80px, #000 calc(100% - 80px), transparent);
}
.marquee__track {
  display: flex;
  width: max-content;
  animation-duration: 35s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
  will-change: transform;
}
/* Use per-card margin-right (NOT gap) so the duplicate-set boundary has the
   same spacing as internal gaps. With `gap`, translateX(-50%) drifts by half
   a gap each loop because the track has internal gaps but no trailing one;
   margin-right makes every card carry its own right-side spacing, which lets
   -50% land exactly on the start of the duplicate set. */
.marquee__track > .marquee-card { margin-right: 16px; }
.marquee__row--ltr .marquee__track { animation-name: marquee-ltr; }
.marquee__row--rtl .marquee__track { animation-name: marquee-rtl; }
.marquee__row:hover .marquee__track { animation-play-state: paused; }
@keyframes marquee-ltr {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@keyframes marquee-rtl {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}

.marquee-card {
  width: 280px;
  flex-shrink: 0;
  aspect-ratio: 1.42 / 1;
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 10px;
  border-radius: 16px;
  background: linear-gradient(135deg, var(--brand-from, #15140f), var(--brand-to, #0a0a08));
  border: 1px solid var(--rule);
  text-decoration: none;
  color: #f3efe6;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: transform 0.4s var(--ease-expo), border-color 0.4s var(--ease-expo);
}
.marquee-card::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 25% 15%, rgba(255,255,255,0.06), transparent 60%);
  pointer-events: none;
}
.marquee-card:hover {
  transform: translateY(-4px);
  border-color: var(--brand-accent, var(--volt));
}
.marquee-card.is-clone {
  /* The duplicate cards exist purely for the seamless loop. They're keyboard-
     and screen-reader-hidden via aria-hidden + tabindex="-1" in the markup. */
}
.marquee-card__top {
  display: flex;
  align-items: center;
  gap: 10px;
}
.marquee-card__logo-wrap {
  display: inline-flex;
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  background: rgba(255, 255, 255, 0.10);
  border-radius: 6px;
  padding: 5px;
  align-items: center;
  justify-content: center;
}
.marquee-card__logo {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  filter: brightness(0) invert(1);
  opacity: 0.92;
}
.marquee-card__client {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #f3efe6;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.marquee-card__blurb {
  margin: 0;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 15px;
  line-height: 1.3;
  color: rgba(243, 239, 230, 0.92);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.marquee-card__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.marquee-card__year { color: rgba(243, 239, 230, 0.55); }
.marquee-card__cta {
  color: var(--brand-accent, var(--volt));
  font-size: 13px;
}

/* --- Peek-arming progress bar
   Painted across the top of any .js-work-card while the user is hovering
   and the open-delay is still counting down. Gives the user a visible
   signal that the preview is about to open AND a chance to bail by moving
   off the card before it fires.

   The duration comes from `--peek-delay` set inline by JS (initWorkPopup),
   so any per-card override via `data-peek-delay` is honoured automatically.
   `transform-origin: left` + scaleX animation = no layout shift, runs on
   the compositor for a smooth fill.

   Sizing notes:
     - 3px tall (was 2px) so it reads on small marquee cards too
     - z-index: 5 so it paints above .marquee-card::after's radial gradient
     - box-shadow glow so the volt/brand-accent stays legible even on
       gradients close to the bar's hue
     - inset 12px L/R so the fill isn't visually clipped by border-radius:
       16px on the marquee cards (was hugging the rounded corners). */
.spotlight__visual,
.marquee-card {
  position: relative;
}
.spotlight__visual::before,
.marquee-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--brand-accent, var(--volt));
  box-shadow: 0 0 10px var(--brand-accent, var(--volt)),
              0 0 22px rgba(216, 255, 61, 0.35);
  transform: scaleX(0);
  transform-origin: left center;
  z-index: 5;
  pointer-events: none;
  opacity: 0;
  border-bottom-left-radius: 2px;
  border-bottom-right-radius: 2px;
}
/* Marquee cards have a smaller border-radius (16px) and live in a tighter
   surface — inset the bar slightly so the fill doesn't disappear into the
   rounded corners during the first ~50px of the animation. */
.marquee-card::before {
  top: 0;
  left: 12px;
  right: 12px;
  height: 3px;
}
.spotlight__visual.is-peek-loading::before,
.marquee-card.is-peek-loading::before {
  opacity: 1;
  animation: peek-arming var(--peek-delay, 800ms) linear forwards;
}
@keyframes peek-arming {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* When the popup actually opens, fade the bar out so it doesn't linger
   behind the modal. (JS removes the `is-peek-loading` class at open, so the
   ::before falls back to opacity:0.) */

/* --- "Peek ↗" cursor variant — appears when hovering hover-popup-enabled
       cards (.js-cursor-peek). Uses a separate is-peek class so the regular
       is-large hover scale doesn't compete with the peek visual. */
.cursor.is-peek {
  width: 88px;
  height: 88px;
  background: var(--volt);
  color: var(--accent-fg);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 600;
  mix-blend-mode: normal; /* override the default difference blend */
  box-shadow: 0 8px 24px rgba(216, 255, 61, 0.35);
}
.cursor.is-peek::before {
  content: 'Peek ↗';
}

/* --- Responsive --- */
@media (max-width: 1024px) {
  .spotlight { grid-template-columns: 1fr; }
  .spotlight__visual { min-height: 320px; aspect-ratio: 16 / 10; }
}
@media (max-width: 768px) {
  .spotlight__par { grid-template-columns: 1fr; gap: 16px; padding-top: 16px; }
  .spotlight__visual { min-height: 260px; }
  .spotlight-head__lede { font-size: 14px; }
  .spotlight__title { font-size: clamp(28px, 7vw, 36px); }
  .spotlight__peek-hint { display: none; }
  /* The decorative wordmark behind the logo — at 80px Fraunces italic
     "earthmeal" / "international design" / "the wander club" are wider
     than the 340-ish px card on a phone, so the right edge clipped. Drop
     the size and allow wrapping so any wordmark fits any card width. */
  .spotlight__wordmark {
    font-size: clamp(48px, 14vw, 96px);
    white-space: normal;
    word-break: break-word;
    text-align: center;
    padding: 0 16px;
  }

  /* Marquee on mobile: animation off, hide the second row + clone cards,
     and let the user scroll the surviving row natively with snap points.
     Battery-friendly, less DOM, and preserves the popup-on-tap experience. */
  .marquee__row--rtl { display: none; }
  .marquee__row {
    -webkit-mask-image: none;
            mask-image: none;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 6px;
  }
  .marquee__row::-webkit-scrollbar { display: none; }
  .marquee__track {
    animation: none !important;
    transform: none !important;
    width: max-content;
  }
  .marquee-card {
    width: 240px;
    padding: 16px;
    scroll-snap-align: start;
  }
  .marquee-card__blurb { font-size: 14px; }
  .marquee-card.is-clone { display: none; }
}

/* ---------- 6. Services ---------- */
.services {
  display: grid;
  grid-template-columns: minmax(280px, 1fr) 1.4fr;
  gap: clamp(24px, 5vw, 80px);
  margin-top: clamp(40px, 6vw, 80px);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  padding: clamp(24px, 4vw, 56px) 0;
}
.services__list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  position: sticky;
  top: 120px;
  align-self: start;
}
.services__item {
  display: flex;
  align-items: baseline;
  gap: 24px;
  padding: 16px 0 16px 20px;
  background: transparent;
  border: 0;
  border-left: 2px solid transparent;
  text-align: left;
  cursor: pointer;
  font-family: 'Inter Tight', sans-serif;
  color: var(--mute);
  transition: color 0.4s var(--ease-expo), border-color 0.4s var(--ease-expo);
  /* Prevent the tap-to-select-text behaviour on mobile that competes with
     the click handler — without this, tapping the title span sometimes
     selects the word instead of firing the toggle. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  /* Touch-action: manipulation kills the 300ms double-tap delay on
     legacy mobile browsers, so taps register instantly. */
  touch-action: manipulation;
}
.services__item:hover { color: var(--bone); }
.services__item.is-active {
  color: var(--bone);
  border-left-color: var(--volt);
}
.services__num {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--mute);
}
.services__name {
  font-size: clamp(20px, 1.7vw, 28px);
  font-weight: 500;
  letter-spacing: -0.015em;
}

.services__panels { position: relative; min-height: 320px; }
.services__panel {
  display: none;
  flex-direction: column;
  gap: 20px;
  animation: panelIn 0.5s var(--ease-expo);
}
.services__panel.is-active { display: flex; }
@keyframes panelIn {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}
.services__title {
  font-family: 'Inter Tight', sans-serif;
  font-size: clamp(32px, 4vw, 56px);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1;
  margin: 0;
}
.services__lede {
  margin: 0;
  max-width: 48ch;
  font-size: clamp(16px, 1.2vw, 18px);
  line-height: 1.55;
  color: var(--bone-soft);
}
.services__meta {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
  border-top: 1px solid var(--rule);
  padding-top: 24px;
  margin: 16px 0 0;
}
.services__meta > div { display: flex; flex-direction: column; gap: 6px; }
.services__meta dt {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mute);
  margin: 0;
}
.services__meta dd {
  font-size: 14px;
  line-height: 1.5;
  margin: 0;
  color: var(--bone);
}
.services__cta {
  align-self: flex-start;
  margin-top: 16px;
  background: var(--volt);
  color: var(--accent-fg);  /* stable dark — must stay readable on volt in both themes */
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 16px 28px;
  border-radius: 999px;
  text-decoration: none;
  transition: background 0.3s, color 0.3s;
}
/* Hover swaps to bone bg + ink text — both swap with theme so it stays
   coherent: cream button + dark text in dark mode, dark button + cream
   text in light mode. */
.services__cta:hover {
  background: var(--bone);
  color: var(--ink);
}

@media (max-width: 880px) {
  /* Mobile pattern: turn the desktop "tab list + sticky right-side panel"
     into a real accordion. Without this, tapping `06` at the top of the
     list silently swapped a panel rendered far below the whole list — the
     user couldn't see anything happen.

     The trick: make .services a 12-row grid (6 tabs + 6 panels) and
     `display: contents` the wrappers so the buttons and the panels act as
     direct grid children. Each tab/panel pair is then assigned to adjacent
     rows, so the active panel renders directly under its own tab. The
     existing `[hidden]` / `.is-active` state already collapses the others. */
  .services {
    grid-template-columns: 1fr;
    grid-template-rows: repeat(12, auto);
    gap: 0;
    border-top: none;
    border-bottom: none;
    padding: 0;
    margin-top: clamp(24px, 4vw, 40px);
  }
  .services__list,
  .services__panels {
    display: contents;
  }
  .services__list { position: static; }
  .services__meta { grid-template-columns: 1fr; gap: 12px; padding-top: 16px; margin-top: 8px; }
  .services__title { font-size: clamp(24px, 6vw, 32px); }
  .services__lede { font-size: 15px; }
  /* Stretch the CTA to the panel's content edges without adding padding
     on top of an explicit width (which was overflowing the right border).
     `box-sizing: border-box` defends against the same in any future override. */
  .services__cta {
    align-self: stretch;
    box-sizing: border-box;
    width: auto;
    justify-content: center;
    text-align: center;
  }

  /* Tab — full-width row with a chevron on the right that rotates when
     the panel below is open. Bottom border draws the row separator. */
  .services__item {
    grid-column: 1;
    border-left: 0;
    border-bottom: 1px solid var(--rule);
    padding: 18px 0;
    gap: 16px;
    align-items: center;
    min-height: 64px;
    position: relative;
  }
  .services__item.is-active { border-left-color: transparent; }
  .services__item::after {
    content: '';
    position: absolute;
    right: 4px;
    top: 50%;
    width: 12px;
    height: 12px;
    border-right: 2px solid var(--mute);
    border-bottom: 2px solid var(--mute);
    transform: translateY(-70%) rotate(45deg);
    transition: transform 0.3s var(--ease-expo), border-color 0.3s var(--ease-expo);
  }
  .services__item.is-active::after {
    transform: translateY(-30%) rotate(-135deg);
    border-color: var(--volt-text);
  }
  .services__num { color: var(--mute); }
  .services__name { flex: 1; padding-right: 24px; font-size: 18px; }

  /* Each panel takes the row directly under its corresponding tab. Inactive
     panels keep `display: none` (set elsewhere); active ones render flex.
     Even 24px padding on all four sides + a subtle inset background so the
     panel reads as a contained "drawer" beneath its header tab. The 12px
     top margin gives visible breathing room between the tab's bottom border
     and the drawer — without it the panel kissed the line and read as one
     squashed block. */
  .services__panel {
    grid-column: 1;
    padding: 24px;
    margin: 12px 0 16px;
    background: var(--graphite);
    border-radius: 12px;
    border-bottom: 1px solid var(--rule);
  }

  /* Pair tabs and panels into adjacent grid rows. */
  .services__item[data-target="0"]    { grid-row: 1; }
  .services__panel[data-panel="0"]     { grid-row: 2; }
  .services__item[data-target="1"]    { grid-row: 3; }
  .services__panel[data-panel="1"]     { grid-row: 4; }
  .services__item[data-target="2"]    { grid-row: 5; }
  .services__panel[data-panel="2"]     { grid-row: 6; }
  .services__item[data-target="3"]    { grid-row: 7; }
  .services__panel[data-panel="3"]     { grid-row: 8; }
  .services__item[data-target="4"]    { grid-row: 9; }
  .services__panel[data-panel="4"]     { grid-row: 10; }
  .services__item[data-target="5"]    { grid-row: 11; }
  .services__panel[data-panel="5"]     { grid-row: 12; }

  /* The min-height was sized for a desktop swap; on mobile each panel is
     its own block, so collapse the reservation. */
  .services__panels { min-height: 0; }
}

/* ---------- 7. Process ---------- */
.process {
  list-style: none;
  margin: clamp(40px, 6vw, 80px) 0 0;
  padding: 0;
  position: relative;
  display: flex;
  flex-direction: column;
}
.process__step {
  display: grid;
  grid-template-columns: 80px 1fr 80px;
  gap: 32px;
  align-items: center;
  padding: clamp(28px, 4vw, 56px) 0;
  border-top: 1px solid var(--rule);
  position: relative;
}
.process__step:last-of-type { border-bottom: 1px solid var(--rule); }
.process__num {
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  letter-spacing: 0.1em;
  color: var(--mute);
}
.process__body { display: flex; flex-direction: column; gap: 8px; max-width: 56ch; }
.process__title {
  font-family: 'Inter Tight', sans-serif;
  font-size: clamp(28px, 4.5vw, 64px);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1;
  margin: 0;
}
.process__copy {
  margin: 0;
  color: var(--bone-soft);
  font-size: clamp(15px, 1vw, 17px);
  line-height: 1.55;
  max-width: 52ch;
}
.process__when {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--mute);
  text-transform: uppercase;
  margin-top: 4px;
}
.process__step.is-active .process__title { color: var(--bone); }
.process__rail { display: none; }
.process__node { display: none; }  /* legacy node — replaced by hover popup */

/* Section title for the process pattern: let it expand to section__head's
   full width (1280px). The 14ch global cap was forcing 4-line wraps. */
.section--process .section__title { max-width: none; }

/* Hover popup — fills the empty right column with an illustration + bullet
   list of what the step actually covers. Discoverability cue: the icon is
   always faintly visible at 35% opacity, the list reveals on hover. */
.process__step {
  /* Re-flow the row: fixed numbers, flexible body, generous popup zone. */
  grid-template-columns: 80px minmax(0, 1fr) minmax(0, 460px);
  gap: clamp(20px, 3vw, 48px);
}
.process__popup {
  display: flex;
  align-items: center;
  gap: 24px;
  min-width: 0;
}
.process__popup-art {
  flex-shrink: 0;
  width: 64px;
  height: 64px;
  color: var(--volt-text);
  opacity: 0.32;
  transition: opacity 0.45s var(--ease-expo), transform 0.45s var(--ease-expo);
}
.process__popup-art svg { width: 100%; height: 100%; display: block; }
.process__popup-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.02em;
  line-height: 1.5;
  color: var(--mute);
  opacity: 0;
  transform: translateX(-12px);
  transition: opacity 0.45s var(--ease-expo), transform 0.45s var(--ease-expo);
  pointer-events: none;
  min-width: 0;
}
.process__popup-list li {
  position: relative;
  padding-left: 14px;
}
.process__popup-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 7px;
  height: 1px;
  background: var(--volt-text);
}
.process__step:hover .process__popup-art {
  opacity: 1;
  transform: rotate(-4deg);
}
.process__step:hover .process__popup-list {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
}

@media (max-width: 1024px) {
  .process__step { grid-template-columns: 80px 1fr 240px; }
  .process__popup-art { width: 56px; height: 56px; }
  .process__popup-list { font-size: 11px; }
}
@media (max-width: 768px) {
  .process__step { grid-template-columns: 56px 1fr; gap: 16px; padding: 22px 0; }
  .process__popup { display: none; }
  /* Force visually equal left/right padding on the process section.
     Without this, the section__title's natural wrap and the steps' grid
     columns each settle at slightly different positions — visually the
     right gutter reads bigger than the left. Pin both sides to the same
     value and override any inherited inline `padding-right` from the
     pattern's wp:group inline style. */
  .section--process {
    padding-left: 20px !important;
    padding-right: 20px !important;
  }
  /* Tighten the two-column max-widths inside the steps so body text wraps
     close to the section's right padding (no extra inner-right gutter). */
  .process__body { max-width: none; }
  .process__copy { max-width: none; }
  .process__title { font-size: clamp(24px, 6vw, 32px); }
}

/* ---------- 8. About ---------- */
.about__portrait {
  margin: 0;
  border: 1px solid var(--rule);
  background: var(--graphite);
  position: relative;
  filter: grayscale(1) contrast(1.05);
  transition: filter 0.6s var(--ease-expo);
}
.about__portrait:hover { filter: grayscale(0) contrast(1); }
.about__portrait svg { display: block; width: 100%; height: auto; }
/* New <img> portrait — same 4:5 portrait container, object-fit covers any
   aspect ratio variation in the source file. The grayscale filter on the
   parent `.about__portrait` rolls back to colour on hover (above). */
.about__portrait-img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}
.about__portrait-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 4 / 5;
  background: var(--graphite);
  color: var(--mute);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: center;
  border: 1px dashed var(--rule);
}
.about__portrait-caption {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  color: var(--mute);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 12px 16px;
  border-top: 1px solid var(--rule);
}
.about__title {
  margin: 0 0 24px;
  max-width: 18ch;
}
.about__body { margin: 0 0 16px; max-width: 56ch; color: var(--bone-soft); }
.about__body em {
  color: var(--bone);
}
.about__facts {
  margin: 32px 0 0;
  padding: 24px 0 0;
  border-top: 1px solid var(--rule);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px 32px;
}
.about__facts > div { display: flex; flex-direction: column; gap: 4px; }
.about__facts dt {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mute);
  margin: 0;
}
.about__facts dd {
  margin: 0;
  font-size: 15px;
  color: var(--bone);
}

@media (max-width: 880px) {
  /* Centre the portrait column under the headline. Auto margins on a
     flex-basis-1fr column do nothing; need the WP-block container to
     accept centring too. */
  .about__col-portrait {
    flex-basis: 100% !important;
    max-width: 320px;
    margin-left: auto !important;
    margin-right: auto !important;
  }
  .about__col-portrait .about__portrait { margin: 0 auto; }

  /* 6 facts in a 3×2 grid (was 1×6) — fills the empty right side instead
     of leaving a long blank stripe. `auto-fit` would let the cells stretch
     to fill the row when there are fewer than 6 items. */
  .about__facts {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px 16px;
  }
  .about__facts dd { font-size: 14px; line-height: 1.4; }
  .about__facts dt { font-size: 10px; }
}
@media (max-width: 480px) {
  /* Below ~480px, 3 columns starts cramping longer values like
     "IST · works with US/EU". Drop to 2×3 — still fills the right side. */
  .about__facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------- 9. Testimonials ---------- */
.section--testimonials { background: var(--ink); }

.quotes {
  position: relative;
  min-height: 60vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin-top: clamp(40px, 6vw, 64px);
}
.quotes__viewport {
  position: relative;
  min-height: 640px;  /* mobile-first: room for stacked photo + quote */
}
@media (min-width: 880px) {
  .quotes__viewport { min-height: 560px; }  /* desktop row layout, taller now (bigger photo) */
}
@media (min-width: 1600px) {
  .quotes__viewport { min-height: 660px; }  /* ultrawide: photo grows further */
}

/* ---------- Testimonial: Editorial Spread layout ----------
   Magazine-style pull quote: framed portrait on the left, oversized
   opening quote mark + italic Fraunces quote on the right, attribution
   underneath with a thin top border. Mobile-first — stacks to single
   column below 880px. */

.quotes__item {
  margin: 0;
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(32px, 5vw, 56px);
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.6s var(--ease-expo), transform 0.6s var(--ease-expo);
  pointer-events: none;
}
.quotes__item.is-active {
  position: relative;
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* Photo placeholder — gradient tile with big italic initials and a volt
   tag pill. Each testimonial gets its own gradient via a modifier class. */
.quotes__photo {
  position: relative;
  width: clamp(220px, 70vw, 320px);
  aspect-ratio: 4 / 5;
  align-self: flex-start;
  flex-shrink: 0;
  margin-bottom: 16px;  /* room for the tag pill that overhangs */
}
.quotes__photo-frame {
  position: absolute;
  inset: 0;
  border: 1px solid var(--rule);
  transition: transform 0.6s var(--ease-expo);
  /* Per-quote gradient via inline CSS vars set in the pattern.
     Falls back to a neutral graphite gradient if no vars are supplied. */
  background: linear-gradient(160deg, var(--brand-from, #2a2a2a), var(--brand-to, #0a0a0a));
}
.quotes__photo-initials {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-weight: 500;
  font-size: clamp(80px, 16vw, 220px);  /* scales with the larger photo at full bleed */
  letter-spacing: -0.04em;
  color: var(--bone);
  pointer-events: none;
}
.quotes__photo-tag {
  position: absolute;
  bottom: -16px;
  right: -12px;
  background: var(--volt);
  color: var(--accent-fg);
  padding: 8px 14px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.14em;
  border-radius: 999px;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(216,255,61,0.18);
  z-index: 2;
}

/* Real headshot — overlays the brand-color frame at full opacity, with a
   subtle inner edge so it reads as a deliberate portrait, not a stock photo
   slapped on. The frame's gradient still peeks through where photos have
   transparent / cropped edges. */
.quotes__photo-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;  /* prefer faces, which sit in the upper third */
  border: 1px solid var(--rule);
  /* Slight desaturation + warm tint so the bunch of disparate photos read
     as a coherent set, the way magazine pull-quote portraits feel curated.
     Released to full colour on hover so the human face becomes vivid as the
     quote is being read. */
  filter: grayscale(0.18) contrast(1.02) brightness(0.97);
  transition: filter 0.6s var(--ease-expo), transform 0.6s var(--ease-expo);
}
.quotes__item:hover .quotes__photo-img,
.quotes__item.is-active .quotes__photo-img {
  filter: grayscale(0) contrast(1) brightness(1);
}
/* When the photo is present, the gradient frame shifts to a soft outer
   shadow rather than a competing surface — keeps the focal point on the
   face. */
.quotes__photo.has-photo .quotes__photo-frame {
  opacity: 0.45;
}
.quotes__item.is-active .quotes__photo-frame {
  animation: photo-breathe 8s ease-in-out infinite;
}
.quotes__item:hover .quotes__photo-frame { transform: scale(1.012); }
@keyframes photo-breathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.008); }
}

.quotes__content {
  min-width: 0;
}

/* Oversized opening quote mark — sits above the quote, serves as a visual
   anchor and reduces the need for actual quote characters in the body. */
.quotes__mark {
  display: block;
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(72px, 9vw, 160px);
  line-height: 0.4;
  color: var(--volt-text);
  margin: 12px 0 20px;
  user-select: none;
}

.quotes__quote {
  font-family: 'Fraunces', serif;
  font-style: italic;
  font-weight: 400;
  font-variation-settings: 'opsz' 144;
  font-size: clamp(26px, 3.2vw, 64px);
  line-height: 1.16;
  letter-spacing: -0.015em;
  margin: 0 0 32px;
  max-width: 38ch;  /* readable upper bound for italic body */
  color: var(--bone);
}
.quotes__quote em {
  color: var(--volt-text);
  font-family: 'Fraunces', serif;
  font-style: italic;
}

.quotes__attr {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--mute);
  border-top: 1px solid var(--rule);
  padding-top: 16px;
  text-transform: uppercase;
}
.quotes__attr strong { color: var(--bone); font-weight: 500; }
.quotes__sep { padding: 0 12px; color: var(--rule); }

/* Desktop: full-bleed two-column grid — generous portrait + wide quote.
   Photo grows to ~36% of available width on ultrawide screens so the
   composition stays editorial instead of feeling cramped. */
@media (min-width: 880px) {
  .quotes__item {
    grid-template-columns: minmax(360px, 36vw) 1fr;
    gap: clamp(56px, 7vw, 140px);
    align-items: center;
  }
  .quotes__photo {
    width: 100%;
    margin-bottom: 0;
    max-width: 560px;  /* hard cap so portraits never become billboards */
  }
  .quotes__photo-tag {
    bottom: -16px;
    right: -16px;
    font-size: 11px;
    padding: 9px 16px;
  }
}

/* Ultrawide (≥1600px): bump portrait + quote a touch more so the section
   uses the full canvas the rest of the site already leans into. */
@media (min-width: 1600px) {
  .quotes__item {
    grid-template-columns: minmax(420px, 32vw) 1fr;
  }
  .quotes__photo { max-width: 620px; }
}

@media (prefers-reduced-motion: reduce) {
  .quotes__item.is-active .quotes__photo-frame { animation: none; }
}

.quotes__nav {
  display: flex;
  align-items: center;
  gap: 24px;
  margin-top: clamp(40px, 6vw, 80px);
  padding-top: 24px;
  border-top: 1px solid var(--rule);
}
.quotes__prev, .quotes__next {
  background: transparent;
  border: 1px solid var(--rule);
  color: var(--bone);
  width: 48px;
  height: 48px;
  border-radius: 50%;
  cursor: pointer;
  transition: background 0.3s, color 0.3s, border-color 0.3s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.quotes__prev:hover, .quotes__next:hover {
  background: var(--bone);
  color: var(--ink);
  border-color: var(--bone);
}
.quotes__counter {
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  letter-spacing: 0.1em;
  color: var(--mute);
}
.quotes__counter-sep { padding: 0 4px; }
.quotes__progress {
  flex: 1;
  height: 1px;
  background: var(--rule);
  position: relative;
  overflow: hidden;
}
.quotes__progress-bar {
  position: absolute;
  inset: 0 auto 0 0;
  width: 25%;
  background: var(--volt-text);  /* was --volt; volt washed out on cream */
  transition: width 0.5s var(--ease-expo);
}



/* ---------- 10. Contact ---------- */
.contact__title { margin: 0 0 24px; max-width: 14ch; }
.contact__lede { margin: 0; max-width: 48ch; color: var(--bone-soft); }
.contact__badges {
  list-style: none;
  margin: 32px 0 0;
  padding: 24px 0 0;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--mute);
}
.contact__badges li {
  padding: 8px 14px;
  border: 1px solid var(--rule);
  border-radius: 999px;
}

.contact-form { display: flex; flex-direction: column; gap: 8px; }
.contact-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 0; }
.contact-form__row .contact-form__field { border-right: 1px solid var(--rule); }
.contact-form__row .contact-form__field:last-child { border-right: 0; }

.contact-form__field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  border-bottom: 1px solid var(--rule);
  padding: 16px 0;
  position: relative;
  transition: border-color 0.3s var(--ease-expo);
}
.contact-form__field:focus-within { border-bottom-color: var(--volt); }
.contact-form__row .contact-form__field { padding-right: 16px; }
.contact-form__row .contact-form__field:last-child { padding-right: 0; padding-left: 16px; }
.contact-form__label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mute);
}
/* Auto-add a volt-yellow asterisk to labels of required fields. Uses :has()
   to walk from the wrapping <label class="contact-form__field"> down to the
   input/textarea/select that's flagged required, then targets the nested
   .contact-form__label span. Modern-evergreen-only — gracefully no-ops in
   the rare browser without :has() (the field still validates; only the
   visual marker is missing). */
.contact-form__field:has(input:required) > .contact-form__label::after,
.contact-form__field:has(textarea:required) > .contact-form__label::after,
.contact-form__field:has(select:required) > .contact-form__label::after {
  content: ' *';
  color: var(--volt-text);
  font-weight: 600;
  margin-left: 2px;
}
/* Subtle "(optional)" pill — smaller, less letter-spaced, fades into the
   label so the eye lands on the field name first. */
.contact-form__optional {
  font-family: 'JetBrains Mono', monospace;
  font-size: 9px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(138, 138, 133, 0.7);  /* --mute with extra fade */
  margin-left: 4px;
  font-weight: 400;
}
/* Native HTML5 invalid state — paint the underline ember-red AFTER the user
   has interacted with the field. `:user-invalid` (Safari/Firefox/Chrome 119+)
   only triggers post-blur or post-submit, so users don't see red the moment
   they start typing. Falls back to :invalid for older Chromium. */
.contact-form__field:has(input:user-invalid),
.contact-form__field:has(textarea:user-invalid),
.contact-form__field:has(input:invalid:not(:placeholder-shown):not(:focus)),
.contact-form__field:has(textarea:invalid:not(:placeholder-shown):not(:focus)) {
  border-bottom-color: var(--ember);
}

.contact-form__input {
  background: transparent;
  border: 0;
  color: var(--bone);
  font-family: 'Inter Tight', sans-serif;
  font-size: 18px;
  line-height: 1.4;
  padding: 4px 0;
  outline: none;
  width: 100%;
}
.contact-form__input::placeholder { color: var(--mute); }
.contact-form__input--area { resize: vertical; min-height: 100px; }

.contact-form__radios {
  border: 0;
  padding: 16px 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  border-bottom: 1px solid var(--rule);
}
.contact-form__radios legend { padding: 0; }
.contact-form__radios > label {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-right: 16px;
  cursor: pointer;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mute);
  transition: color 0.3s;
}
.contact-form__radios > label:hover,
.contact-form__radios > label:has(input:checked) { color: var(--bone); }
.contact-form__radios input[type="radio"] {
  appearance: none;
  width: 14px; height: 14px;
  border: 1px solid var(--rule);
  border-radius: 50%;
  position: relative;
  cursor: pointer;
  transition: border-color 0.3s;
}
.contact-form__radios input[type="radio"]:checked {
  border-color: var(--volt);
  background:
    radial-gradient(circle, var(--volt) 0 4px, transparent 5px);
}
.contact-form__radios > div {
  display: flex;
  flex-wrap: wrap;
}

.contact-form__actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  margin-top: 24px;
}
.contact-form__submit {
  background: var(--volt);
  color: var(--accent-fg);  /* stable dark on volt */
  border: 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 18px 32px;
  border-radius: 999px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  transition: background 0.3s, color 0.3s, transform 0.4s var(--ease-expo);
}
.contact-form__submit:hover {
  background: var(--bone);
  color: var(--ink);
}
.contact-form__alt {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--mute);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 4px;
  transition: color 0.3s, border-color 0.3s;
}
.contact-form__alt:hover { color: var(--volt-text); border-bottom-color: var(--volt); }

@media (max-width: 640px) {
  .contact-form__row { grid-template-columns: 1fr; }
  /* Match the `:last-child` selector specificity from line ~2062, otherwise
     the desktop `padding-left: 16px` on the last-child (the EMAIL field)
     wins on mobile too — pushing the "EMAIL" label and input 16px to the
     right of the NAME field's left edge. */
  .contact-form__row .contact-form__field,
  .contact-form__row .contact-form__field:last-child {
    border-right: 0;
    padding-left: 0;
    padding-right: 0;
  }
}

/* ---------- 11. Final CTA ---------- */
.section--final { text-align: left; }
.final-cta__title {
  font-size: clamp(56px, 14vw, 320px);
  line-height: 0.92;
  letter-spacing: -0.04em;
  margin: 0;
  max-width: 18ch;
  font-weight: 500;
}

/* ---------- 12. Footer ---------- */
.site-footer {
  margin-top: 0;
  position: relative;
  overflow: clip;
  /* Skip layout/paint while the footer is below the viewport. Saves
     work on initial load and during scroll until the user gets close.
     `contain-intrinsic-size` reserves space so the scrollbar doesn't
     jump when the section paints in. */
  content-visibility: auto;
  contain-intrinsic-size: 0 600px;
}
.site-footer__wordmark {
  font-family: 'Inter Tight', sans-serif;
  font-size: clamp(80px, 18vw, 280px);
  font-weight: 500;
  letter-spacing: -0.05em;
  line-height: 0.85;
  margin: 0;
  white-space: nowrap;
}
.site-footer__dot { color: var(--volt); }
.site-footer__rule {
  margin: 24px 0;
  border: 0;
  height: 1px;
  background: var(--rule);
}
.site-footer__cols { gap: clamp(20px, 4vw, 80px) !important; }
.site-footer__list { list-style: none; padding: 0; margin: 12px 0 0; display: flex; flex-direction: column; gap: 8px; }
.site-footer__list a {
  color: var(--bone);
  text-decoration: none;
  font-size: 15px;
  transition: color 0.3s;
}
.site-footer__list a:hover { color: var(--volt-text); }
.site-footer__meta { margin: 0; font-size: 11px; letter-spacing: 0.12em; color: var(--mute); }

/* Mobile footer: WP's wp:columns block stacks to a single column ≤ 781px,
   leaving the four lists (Index, Contact, Elsewhere, Legal) as a tall
   single column with a wide blank gutter on the right. Force a 2-column
   grid below 880 so the four lists become a tidy 2×2 instead. */
@media (max-width: 880px) {
  .site-footer__cols.wp-block-columns {
    display: grid !important;
    grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    gap: 28px 24px !important;
  }
  .site-footer__cols.wp-block-columns > .wp-block-column {
    flex-basis: auto !important;
    width: auto !important;
    min-width: 0;
  }
  .site-footer__cols h5 {
    margin: 0 0 4px;
    font-size: 11px;
    letter-spacing: 0.12em;
    color: var(--mute);
  }
  .site-footer__list { margin-top: 8px; gap: 6px; }
  .site-footer__list a { font-size: 14px; }
}

/* ---------- 13. Cursor & motion utility ---------- */
.cursor {
  position: fixed;
  top: 0; left: 0;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--volt);
  pointer-events: none;
  z-index: 1000;
  mix-blend-mode: difference;
  transform: translate3d(-50%, -50%, 0);
  transition: width 0.35s var(--ease-expo), height 0.35s var(--ease-expo), background 0.3s;
  will-change: transform;
}
.cursor.is-large { width: 56px; height: 56px; background: var(--bone); }
@media (hover: none), (max-width: 880px) { .cursor { display: none; } }

.js-magnetic { will-change: transform; }

/* Reveal */
.js-reveal { opacity: 0; transform: translateY(40px); transition: opacity 0.8s var(--ease-expo), transform 0.8s var(--ease-expo); }
.js-reveal.is-visible { opacity: 1; transform: translateY(0); }

/* ---------- 14. Light-mode overrides ----------
   These target elements where the patterns (or WP block markup) hardcoded
   hex values inline. We can't edit those without touching every pattern,
   so we re-route them through CSS variables here with !important. */

[data-theme="light"] .section__eyebrow,
[data-theme="light"] .hero__metric-label,
[data-theme="light"] .site-footer__meta {
  color: var(--mute) !important;
}

[data-theme="light"] .hero__metric-number {
  color: var(--volt-text) !important;
}

[data-theme="light"] .site-footer {
  background-color: var(--ink) !important;
  color: var(--bone) !important;
}

[data-theme="light"] .site-footer__rule {
  background-color: var(--rule) !important;
  color: var(--rule) !important;
}

/* Logo SVG: volt strokes/fills become the legible olive tone on cream.
   Presentation attributes (stroke="...", fill="...") have lower specificity
   than CSS, so this overrides without !important. */
[data-theme="light"] .site-header__logo [stroke="#D8FF3D"] { stroke: var(--volt-text); }
[data-theme="light"] .site-header__logo [fill="#D8FF3D"]   { fill:   var(--volt-text); }

/* Cursor blob — mix-blend-mode: difference handles the inversion already,
   but let's make the `is-large` state use the inverse of `--bone` for clarity. */
[data-theme="light"] .cursor.is-large { background: var(--bone); }

/* Selection re-colors automatically since `::selection { background: var(--volt) }` is
   already volt and ink text, and ink stays dark on volt — works in both modes. */

/* ---------- 15. Case study detail pages ----------
   Layout for /work/[slug]/ pages. Rhythm matches the homepage section
   system: full-bleed sections, fluid type, section__eyebrow on the left
   column, content on the right (~70%). */

.case-main { padding-top: clamp(80px, 10vw, 140px); }

.case__top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--mute);
  text-transform: uppercase;
  margin-bottom: clamp(40px, 6vw, 80px);
  padding-bottom: 16px;
  border-bottom: 1px solid var(--rule);
}
.case__crumb { color: var(--mute); text-decoration: none; transition: color 0.3s; display: inline-flex; gap: 8px; }
.case__crumb:hover { color: var(--volt-text); }
.case__index { color: var(--volt-text); }

.case__title {
  margin: 24px 0 28px;
  max-width: 22ch;
  font-size: clamp(48px, 9vw, 180px) !important;
  line-height: 0.92;
  letter-spacing: -0.04em;
}
.case__lede {
  margin: 0 0 clamp(40px, 5vw, 64px);
  max-width: 56ch;
  color: var(--bone-soft);
  font-size: clamp(18px, 1.4vw, 22px);
  line-height: 1.5;
}

.case__meta {
  margin: 0 0 clamp(40px, 6vw, 80px);
  padding: 24px 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px 32px;
}
.case__meta > div { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.case__meta dt {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mute);
  margin: 0;
}
.case__meta dd {
  margin: 0;
  font-family: 'Inter Tight', sans-serif;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--bone);
}
@media (min-width: 880px) {
  .case__meta { grid-template-columns: repeat(6, 1fr); }
}

.case__hero-img {
  margin: 0;
  border: 1px solid var(--rule);
  background: var(--graphite);
}
.case__hero-img img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  display: block;
}

/* `.case__current-only` block + its surrounding section (`.case--compare`
   on non-Bevilles studies) was deleted in 2.3.4 across the 7 case-study
   patterns that didn't use the before/after slider — the full homepage
   screenshot was making each case-study page ~2000 px taller than needed.
   The CSS for `.case__current-only` and `.case__current-img` was deleted
   along with the markup. Bevilles, International Design, and The Wander
   Club still render their before/after `.compare` component (preserved). */

.case__row { gap: clamp(24px, 4vw, 64px) !important; }
.case__h {
  margin: 0 0 24px !important;
  font-size: clamp(28px, 3.8vw, 64px) !important;
  line-height: 1.02;
  letter-spacing: -0.025em;
  max-width: 22ch;
}
.case__body {
  margin: 0 0 16px;
  color: var(--bone-soft);
  max-width: 56ch;
  line-height: 1.5;
}
.case__body em { color: var(--bone); }

.case__list {
  list-style: none;
  margin: 24px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.case__list li {
  position: relative;
  padding-left: 24px;
  color: var(--bone-soft);
  line-height: 1.5;
}
.case__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.7em;
  width: 12px;
  height: 1px;
  background: var(--volt-text);
}
.case__list li strong { color: var(--bone); font-weight: 500; }
.case--scope .case__list li::before { background: var(--mute); }

.case__metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(16px, 3vw, 40px);
  margin: 16px 0 32px;
  padding: 32px 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.case__metrics > div { display: flex; flex-direction: column; gap: 8px; }
.case__metrics dt {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mute);
  order: 2;
  margin: 0;
}
.case__metrics dd {
  font-family: 'Inter Tight', sans-serif;
  font-size: clamp(40px, 6vw, 88px);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--bone);
  margin: 0;
  font-feature-settings: 'tnum';
}
.case__metric-value { color: var(--volt-text); }
@media (max-width: 640px) {
  .case__metrics { grid-template-columns: 1fr; gap: 24px; padding: 24px 0; }
}

/* ---------- Before/After comparison slider ----------
   Drag the handle (or click anywhere) to wipe between two images.
   `--compare-pos` (default 50%) is the only thing JS touches; CSS does
   the rest via `clip-path: inset()` on the after image. Accessible —
   the handle is a real button with aria-valuenow + arrow-key support.

   `--compare-ratio` lets each case study set its own slider aspect ratio
   (e.g. 1080/6392 for full-homepage screenshots, 16/10 for hero shots).
   The `position: sticky` on the handle keeps it reachable on tall sliders. */
.compare {
  position: relative;
  aspect-ratio: var(--compare-ratio, 16 / 10);
  overflow: hidden;
  background: var(--graphite);
  border: 1px solid var(--rule);
  user-select: none;
  touch-action: pan-y;
  cursor: ew-resize;
  --compare-pos: 50%;
  max-width: 100%;
}

/* Inner wrapper structure (used by both modes):
   .compare__viewport is the visible region (fills .compare).
   .compare__inner holds the two images at their natural aspect.
   In default mode they're identical in size. In --full-page mode the
   viewport scrolls vertically while inner is taller. */
.compare__viewport {
  position: absolute;
  inset: 0;
  overflow: hidden;
  width: 100%;
  height: 100%;
}
.compare__inner {
  position: relative;
  width: 100%;
  height: 100%;
}

.compare__before,
.compare__after {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: auto;             /* render at natural aspect — no stretch, no whitespace pad */
  user-select: none;
  -webkit-user-drag: none;
  pointer-events: none;
}
/* Wrap for the After image. Fills the full inner area with graphite so when
   the After capture is shorter than the Before, the area below the After's
   natural end reads as "page ends here" instead of letting Before bleed
   through. The horizontal wipe (clip-path) is applied to this wrap. */
.compare__after-frame {
  position: absolute;
  inset: 0;
  background: var(--graphite);
  clip-path: inset(0 calc(100% - var(--compare-pos)) 0 0);
  pointer-events: none;
}

/* FULL-PAGE MODE: fixed display height, internal vertical scroll.
   Both images are positioned absolute inside .compare__inner, which has
   the natural aspect of the source images (e.g. 1080/6392 = very tall).
   .compare__viewport scrolls vertically, revealing different parts of
   both images in lockstep — they're siblings in the same container, so
   they scroll together by definition. The horizontal wipe (clip-path)
   is independent of vertical position. */
.compare--full-page {
  aspect-ratio: auto;
  height: clamp(480px, 75vh, 760px);
  max-width: 100%;
}
.compare--full-page .compare__viewport {
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  scroll-behavior: smooth;
  /* Allow vertical pan only — horizontal pan stays free for the drag-to-compare gesture */
  touch-action: pan-y;
  /* Subtle scrollbar styling */
  scrollbar-width: thin;
  scrollbar-color: var(--rule) transparent;
}
.compare--full-page .compare__viewport::-webkit-scrollbar { width: 6px; }
.compare--full-page .compare__viewport::-webkit-scrollbar-track { background: transparent; }
.compare--full-page .compare__viewport::-webkit-scrollbar-thumb { background: var(--rule); border-radius: 3px; }
.compare--full-page .compare__viewport:hover::-webkit-scrollbar-thumb { background: var(--mute); }
.compare--full-page .compare__inner {
  width: 100%;
  height: auto;
  aspect-ratio: var(--compare-ratio);
}
.compare__divider {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--compare-pos);
  transform: translateX(-50%);
  width: 2px;
  background: var(--bone);
  pointer-events: none;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.2);
  z-index: 2;
}
.compare__handle {
  position: absolute;
  top: 50%;
  left: var(--compare-pos);
  transform: translate(-50%, -50%);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--bone);
  border: 0;
  color: var(--ink);
  cursor: ew-resize;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 16px rgba(0,0,0,0.35);
  transition: box-shadow 0.3s, transform 0.2s;
  z-index: 3;
}
.compare__handle svg { width: 24px; height: 24px; }
.compare__handle:hover { box-shadow: 0 4px 22px rgba(0,0,0,0.45), 0 0 0 4px rgba(216,255,61,0.22); }
.compare__handle:active { transform: translate(-50%, -50%) scale(0.94); }
.compare__handle:focus-visible {
  outline: 2px solid var(--volt);
  outline-offset: 4px;
}
.compare__label {
  position: absolute;
  top: 16px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--bone);
  background: rgba(10,10,10,0.7);
  padding: 6px 10px;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  pointer-events: none;
  z-index: 4;  /* above the scrolling viewport in full-page mode */
}
.compare__label--before { left: 16px; }
.compare__label--after  { right: 16px; }

/* Placeholder used when the real "before" image hasn't been added yet.
   Replace with <img src="..."> when you have the Wayback screenshot. */
.compare__before--placeholder {
  pointer-events: none;
  background:
    repeating-linear-gradient(135deg, transparent 0 12px, rgba(255,255,255,0.02) 12px 24px),
    linear-gradient(160deg, #1a1a1a, #050505);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 32px;
  text-align: center;
  font-family: 'JetBrains Mono', monospace;
  color: var(--mute);
}
.compare__placeholder-label {
  font-size: 12px;
  letter-spacing: 0.18em;
  color: var(--volt-text);
}
.compare__placeholder-note {
  font-size: 11px;
  letter-spacing: 0.06em;
  line-height: 1.6;
  max-width: 36ch;
}

/* ---------- PageSpeed Insights block (case-study performance section) ----------
   Mobile + desktop scores side by side with Core Web Vitals beneath each. */
.case__psi {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
  margin: 24px 0 0;
  padding: 0;
}
@media (min-width: 720px) {
  .case__psi { grid-template-columns: repeat(2, 1fr); }
}
.case__psi-col {
  border: 1px solid var(--rule);
  background: var(--graphite);
  padding: 28px;
  border-radius: 4px;
}
.case__psi-col dt {
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mute);
  margin: 0 0 12px;
}
.case__psi-col dd { margin: 0; }
.case__psi-score {
  font-family: 'Inter Tight', sans-serif;
  font-size: clamp(56px, 7vw, 96px);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.04em;
  font-feature-settings: 'tnum';
}
.case__psi-score--good    { color: #22c55e; }
.case__psi-score--ok      { color: #eab308; }
.case__psi-score--poor    { color: #ef4444; }
.case__psi-score--unknown { color: var(--mute); }
.case__psi-out {
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  color: var(--mute);
  margin-left: 4px;
}
.case__psi-vitals {
  list-style: none;
  margin: 24px 0 0;
  padding: 16px 0 0;
  border-top: 1px solid var(--rule);
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px 16px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
}
.case__psi-vitals li {
  display: flex;
  justify-content: space-between;
  letter-spacing: 0.04em;
}
.case__psi-vitals li > span:first-child {
  color: var(--mute);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 10px;
  align-self: center;
}
.case__psi-vitals li > span:last-child { color: var(--bone); font-weight: 500; }
.case__psi-source {
  margin: 16px 0 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--mute);
}
.case__psi-source a { color: var(--bone); text-decoration: none; border-bottom: 1px solid var(--rule); }
.case__psi-source a:hover { color: var(--volt-text); border-bottom-color: var(--volt); }

/* "View live site" button after scope */
.case__live { margin-top: 24px; }
.case__live .wp-element-button {
  font-size: 12px !important;
  letter-spacing: 0.08em !important;
}


/* ---------- Work card brand logo (default state) ----------
   Each Featured Work card shows the brand's actual logo centred on a
   brand-color gradient. Hovering the card opens a popup (see below)
   with a scrollable preview of the live homepage. */
.work-card-logo {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(160deg, var(--brand-from, #1a1a1a), var(--brand-to, #070707));
  padding: 8% 12%;
  transition: filter 0.5s var(--ease-expo);
}
.work-card-logo__img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  /* Normalise every logo (raster + SVG, regardless of original colour) to a
     white silhouette on the brand-coloured gradient. brightness(0) flattens
     to pure black, then invert(1) flips to white — idempotent for already-
     white sources, and works for SVGs that use currentColor. */
  filter: brightness(0) invert(1);
  color: var(--bone);
  opacity: 0.92;
  transition: transform 0.5s var(--ease-expo);
}
.work-item__visual:hover .work-card-logo__img {
  transform: scale(1.04);
}

/* ---------- Hover preview popup ----------
   Fixed-position modal overlay that covers the viewport with a dim
   backdrop. Inside: a 720×580 frame containing the homepage screenshot
   that autoscrolls top→bottom→top continuously. When the user moves
   their wheel/scroll inside the popup, the autoscroll pauses and they
   take over (CSS scroll-snap on user interaction).

   Closes when the cursor leaves both the source card AND the popup
   itself — handled by JS in main.js (initWorkPopup). */
.work-popup {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(8, 8, 8, 0.78);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  z-index: 200;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s var(--ease-expo), visibility 0.3s;
  pointer-events: none;
}
.work-popup.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
.work-popup__frame {
  position: relative;
  width: min(720px, 92vw);
  height: min(580px, 78vh);
  background: var(--graphite);
  border: 1px solid var(--rule);
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 30px 80px -20px rgba(0,0,0,0.6);
  display: flex;
  flex-direction: column;
  transform: translateY(8px) scale(0.985);
  transition: transform 0.35s var(--ease-expo);
}
.work-popup.is-open .work-popup__frame { transform: translateY(0) scale(1); }

.work-popup__bar {
  flex: 0 0 auto;
  height: 32px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 14px;
  background: #0d0d0d;
  border-bottom: 1px solid var(--rule);
}
.work-popup__bar > span:not(.work-popup__url):not(.work-popup__hint) {
  width: 9px; height: 9px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
}
.work-popup__bar > span:nth-child(1) { background: #ff5f57; }
.work-popup__bar > span:nth-child(2) { background: #ffbd2e; }
.work-popup__bar > span:nth-child(3) { background: #28c840; }
.work-popup__url {
  flex: 1;
  margin: 0 0 0 14px;
  height: 18px;
  background: rgba(255, 255, 255, 0.06);
  border-radius: 9px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  line-height: 18px;
  padding: 0 12px;
  color: var(--mute);
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.work-popup__hint {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mute);
  margin-left: 12px;
}
.work-popup__viewport {
  flex: 1;
  position: relative;
  overflow: hidden;
}
.work-popup__viewport-scroll {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  /* Custom scrollbar so the popup doesn't reveal native chrome */
  scrollbar-width: thin;
  scrollbar-color: var(--rule) transparent;
}
.work-popup__viewport-scroll::-webkit-scrollbar { width: 6px; }
.work-popup__viewport-scroll::-webkit-scrollbar-track { background: transparent; }
.work-popup__viewport-scroll::-webkit-scrollbar-thumb { background: var(--rule); border-radius: 3px; }
.work-popup__viewport-scroll:hover::-webkit-scrollbar-thumb { background: var(--mute); }

.work-popup__shot {
  width: 100%;
  height: auto;
  display: block;
}
/* When .is-auto is on the wrapper (default), the inner img animates. JS
   removes .is-auto on first wheel/touch input so the user takes over. */
.work-popup__viewport-scroll.is-auto {
  overflow: hidden;
}
.work-popup__viewport-scroll.is-auto .work-popup__shot {
  animation: work-popup-scroll var(--popup-scroll-dur, 22s) ease-in-out infinite;
  will-change: transform;
}
@keyframes work-popup-scroll {
  0%, 5%    { transform: translateY(0); }
  48%, 52%  { transform: translateY(-82%); }
  95%, 100% { transform: translateY(0); }
}

/* --- Placeholder popup (when no screenshot exists for the case) ---
   Painted in the case's brand colors so it reads as an intentional preview
   card, not a broken state. Drops in when a case-study folder doesn't yet
   have any of: after.jpg / desktop.jpg / hero.jpg. Auto-upgrades to the
   scrolling screenshot the moment any of those files appears on disk. */
.work-popup__placeholder {
  width: 100%;
  height: 100%;
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: 28px;
  padding: 36px;
  background: linear-gradient(135deg, var(--brand-from, #15140f), var(--brand-to, #0a0a08));
  overflow: hidden;
  isolation: isolate;
}
.work-popup__placeholder::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 30% 25%, rgba(255, 255, 255, 0.08), transparent 60%);
  pointer-events: none;
}
.work-popup__placeholder-wordmark {
  position: relative;
  z-index: 1;
  align-self: center;
  font-family: 'Fraunces', Georgia, serif;
  font-style: italic;
  font-size: clamp(48px, 8vw, 96px);
  line-height: 1;
  color: rgba(243, 239, 230, 0.95);
  letter-spacing: -0.02em;
  word-break: break-word;
  text-align: left;
  user-select: none;
}
.work-popup__placeholder-body {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
}
.work-popup__placeholder-meta {
  margin: 0;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brand-accent, #D8FF3D);
}
.work-popup__placeholder-title {
  margin: 0;
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 400;
  font-size: clamp(20px, 2vw, 26px);
  line-height: 1.2;
  color: #f3efe6;
}
.work-popup__placeholder-title em {
  color: var(--brand-accent, #D8FF3D);
  font-style: italic;
}
.work-popup__placeholder-result {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: rgba(243, 239, 230, 0.78);
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.work-popup__placeholder-cta {
  margin-top: auto;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brand-accent, #D8FF3D);
  border-bottom: 1px solid currentColor;
  padding-bottom: 4px;
  align-self: flex-start;
}
@media (max-width: 720px) {
  .work-popup__placeholder { grid-template-columns: 1fr; padding: 24px; gap: 16px; }
  .work-popup__placeholder-wordmark { font-size: clamp(36px, 12vw, 56px); text-align: center; }
}

/* Mobile: no popup, no hover preview. Card stays clickable for navigation. */
@media (max-width: 880px), (hover: none) {
  .work-popup { display: none !important; }
}
@media (prefers-reduced-motion: reduce) {
  .work-popup__viewport-scroll.is-auto .work-popup__shot { animation: none; }
  .work-popup__frame { transition: opacity 0.2s; }
}

/* ---------- Device-stack (Featured Work card mockup) ----------
   Composite mockup showing the same homepage at desktop / tablet / mobile,
   each frame autoscrolling its full-page screenshot at staggered speeds.
   Used in the Featured Work cards on the homepage. CSS-only animation —
   no JS, GPU-accelerated transforms, pauses on `prefers-reduced-motion`. */
.device-stack {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 10;
  background: linear-gradient(160deg, #1a1a1a, #0a0a0a);
  overflow: hidden;
  pointer-events: none;
  border: 1px solid var(--rule);
  border-radius: 4px;
}
/* When the device-stack lives on a case-study detail page, give it some
   breathing room and remove the border so it sits cleanly in the flow. */
.case--devices .device-stack {
  margin-top: clamp(16px, 2vw, 32px);
  border: 0;
  background: linear-gradient(160deg, #131313, #050505);
}
@media (min-width: 1024px) {
  .case--devices .device-stack { aspect-ratio: 16 / 9; }
}

/* Desktop browser — back layer, biggest. */
.device-stack__desktop {
  position: absolute;
  top: 6%;
  left: 4%;
  width: 64%;
  aspect-ratio: 16 / 10;
  border-radius: 4px;
  overflow: hidden;
  background: #0a0a0a;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.55);
  border: 1px solid var(--rule);
  z-index: 1;
}
.device-stack__desktop-bar {
  height: 14px;
  background: #1a1a1a;
  display: flex;
  align-items: center;
  padding-left: 6px;
  gap: 4px;
  border-bottom: 1px solid #262626;
}
.device-stack__desktop-bar::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  background: #ff5f57;
  box-shadow: 8px 0 0 #ffbd2e, 16px 0 0 #28c840;
}
.device-stack__viewport {
  position: relative;
  width: 100%;
  height: calc(100% - 14px);
  overflow: hidden;
}
.device-stack__desktop .device-stack__shot {
  width: 100%;
  height: auto;
  display: block;
  animation: device-scroll 26s ease-in-out infinite;
  animation-delay: 0.2s;
}

/* Tablet — middle layer, partial overlap on right. */
.device-stack__tablet {
  position: absolute;
  bottom: 6%;
  right: 5%;
  width: 24%;
  aspect-ratio: 4 / 5.4;
  border-radius: 8px;
  overflow: hidden;
  background: #0a0a0a;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.6);
  border: 1px solid var(--rule);
  z-index: 2;
}
.device-stack__tablet > .device-stack__viewport { height: 100%; }
.device-stack__tablet .device-stack__shot {
  width: 100%;
  height: auto;
  display: block;
  animation: device-scroll 30s ease-in-out infinite;
  animation-delay: 1.5s;
}

/* Mobile — front layer, smallest, bottom-left. */
.device-stack__mobile {
  position: absolute;
  bottom: 4%;
  left: 8%;
  width: 13%;
  aspect-ratio: 9 / 19;
  border-radius: 12px;
  overflow: hidden;
  background: #0a0a0a;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.7);
  border: 1px solid var(--rule);
  z-index: 3;
}
.device-stack__mobile-notch {
  position: absolute;
  top: 4px;
  left: 50%;
  transform: translateX(-50%);
  width: 32%;
  height: 3px;
  background: #000;
  border-radius: 0 0 4px 4px;
  z-index: 1;
  pointer-events: none;
}
.device-stack__mobile > .device-stack__viewport {
  height: 100%;
  border-radius: 10px;
}
.device-stack__mobile .device-stack__shot {
  width: 100%;
  height: auto;
  display: block;
  animation: device-scroll 34s ease-in-out infinite;
  animation-delay: 3s;
}

/* Single keyframe — scrolls 85% of image height, pauses at top + bottom.
   Works for any image as long as natural height ≥ ~5× the visible viewport. */
@keyframes device-scroll {
  0%, 8%    { transform: translateY(0); }
  48%, 52%  { transform: translateY(-85%); }
  92%, 100% { transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .device-stack__desktop .device-stack__shot,
  .device-stack__tablet  .device-stack__shot,
  .device-stack__mobile  .device-stack__shot { animation: none; }
}

/* When a work-item visual contains a device-stack, hide the SVG fallback. */
.work-item__visual:has(.device-stack) .work-item__visual-inner > svg { display: none; }


/* ---------- Case study contact form ----------
   Renders on every case-study page via templates/case-study.html. Hidden
   PHP-rendered fields (`case_study_title`, `case_study_url`) auto-populate
   per page so the lead arrives with attribution. */
.case-contact { background: var(--graphite); }
.case-contact__layout {
  display: flex;
  flex-direction: column;            /* mobile-first: stacked */
  gap: clamp(32px, 5vw, 64px);
}
@media (min-width: 880px) {
  .case-contact__layout {
    flex-direction: row;
    gap: clamp(48px, 6vw, 96px);
    align-items: flex-start;
  }
  .case-contact__head { flex: 1 1 0; max-width: 44ch; }
  .case-contact__form { flex: 1.4 1 0; min-width: 0; }
}

.case-contact__title {
  margin: 24px 0 20px;
  font-family: 'Inter Tight', sans-serif;
  font-size: clamp(32px, 4vw, 56px);
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: -0.025em;
  max-width: 18ch;
}
.case-contact__lede {
  margin: 0;
  color: var(--bone-soft);
  font-size: clamp(16px, 1.1vw, 18px);
  line-height: 1.55;
  max-width: 48ch;
}

.case-contact__badges {
  list-style: none;
  margin: 24px 0 0;
  padding: 16px 0 0;
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--mute);
}
.case-contact__badges li {
  padding: 6px 12px;
  border: 1px solid var(--rule);
  border-radius: 999px;
}

/* The "Inquiry from [Page Title]" attribution — visible to the user, gives
   transparency about what's being sent (matches the hidden field value). */
.case-contact__ref {
  margin: 24px 0 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  color: var(--mute);
  text-transform: uppercase;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: baseline;
}
.case-contact__ref-value {
  color: var(--volt-text);
  font-weight: 500;
}

/* Honeypot — visually hidden but still in the DOM for bots to find. */
.case-contact__honey {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  pointer-events: none;
  opacity: 0;
}

/* Form reuses the .contact-form__* classes from the homepage lead-capture
   for consistent styling. The wrapper here just controls layout flow. */
.case-contact__form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  position: relative;
}

.case-contact__feedback {
  margin: 16px 0 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--mute);
  min-height: 1em;          /* prevents layout shift when message appears */
}
.case-contact__feedback.is-success { color: var(--volt-text); }
.case-contact__feedback.is-error   { color: var(--ember); }

/* ---------- Case study gallery ----------
   Used for "key pages" / supplementary screenshots inside a case study.
   Mobile-first: stacks. Tablet: 2-up. Desktop: 3-up (or however many fit).
   Each item is an image + figcaption with a number + label + tiny note. */
.case__gallery {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(24px, 4vw, 48px);
  margin: clamp(24px, 4vw, 48px) 0 0;
}
@media (min-width: 720px) {
  .case__gallery { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1100px) {
  .case__gallery { grid-template-columns: repeat(3, 1fr); }
}
.case__gallery-item {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}
.case__gallery-link {
  display: block;
  position: relative;
  overflow: hidden;
  background: var(--graphite);
  border: 1px solid var(--rule);
  aspect-ratio: 1080 / 675;
  transition: border-color 0.4s var(--ease-expo);
}
.case__gallery-link:hover {
  border-color: var(--volt);
}
.case__gallery-link img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  display: block;
  transition: transform 0.6s var(--ease-expo);
}
.case__gallery-link:hover img {
  transform: scale(1.02);
}
.case__gallery-link::after {
  /* "Visit ↗" hover hint */
  content: 'Visit live ↗';
  position: absolute;
  bottom: 12px;
  right: 12px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: var(--volt);
  color: var(--accent-fg);
  padding: 6px 10px;
  border-radius: 999px;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.35s var(--ease-expo), transform 0.35s var(--ease-expo);
  pointer-events: none;
}
.case__gallery-link:hover::after,
.case__gallery-link:focus-visible::after {
  opacity: 1;
  transform: translateY(0);
}
.case__gallery-link:focus-visible {
  outline: 2px solid var(--volt);
  outline-offset: 4px;
}
.case__gallery-item figcaption {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-left: 0;
}
.case__gallery-num {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  letter-spacing: 0.16em;
  color: var(--volt-text);
}
.case__gallery-label {
  font-family: 'Inter Tight', sans-serif;
  font-size: 16px;
  font-weight: 500;
  letter-spacing: -0.015em;
  color: var(--bone);
}
.case__gallery-note {
  font-size: 13px;
  line-height: 1.5;
  color: var(--mute);
  max-width: 44ch;
}

/* Sub-label above each compare slider (when case study has multiple). */
.case__sublabel {
  margin: 0 0 12px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.14em;
  color: var(--mute);
  text-transform: uppercase;
}

/* Section wrapper inside a case study */
.case__caption {
  margin: 16px 0 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--mute);
  text-transform: uppercase;
}

@media (prefers-reduced-motion: reduce) {
  .compare__handle { transition: none; }
}

.case-footer { max-width: none !important; padding-left: var(--pad-x); padding-right: var(--pad-x); }
.case-footer__row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 24px;
}
.case-footer__back {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--bone);
  text-decoration: none;
  transition: color 0.3s;
}
.case-footer__back:hover { color: var(--volt-text); }
.case-footer__back:hover .case-footer__back-arrow { transform: translateX(-4px); }
.case-footer__back-arrow { transition: transform 0.4s var(--ease-expo); }
.case-footer__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--volt);
  color: var(--accent-fg);
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 16px 28px;
  border-radius: 999px;
  text-decoration: none;
  transition: background 0.3s, color 0.3s;
}
.case-footer__cta:hover { background: var(--bone); color: var(--ink); }

/* ---------- 14. Header — primary nav + "My Work" mega menu ---------- */
/* Markup lives in patterns/megamenu.php · behavior in main.js (initMegaMenu).
   The original wp:navigation block was a single anchor row; we replaced it
   with an explicit <ul> so we can mount the panel as a child of the active
   <li>. The panel itself is positioned against the .site-header (which is
   position:fixed), so it spans the viewport directly under the header. */

.site-nav__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 32px;
}
.site-nav__list > li { display: inline-flex; align-items: center; }
.site-nav__list a,
.site-nav__list .site-nav__trigger {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 18px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bone);
  text-decoration: none;
  background: none;
  border: 0;
  padding: 6px 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: color 0.3s var(--ease-expo);
}
.site-nav__list a:hover,
.site-nav__list .site-nav__trigger:hover,
.site-nav__list .site-nav__trigger[aria-expanded="true"] {
  color: var(--volt-text);
}

/* The mega menu lives inside this <li>, but expands full-width by anchoring
   to the .site-header. We let position:static here so the absolute panel
   reads from the header instead of from the trigger. */
.site-nav__item--mega { position: static; }

.site-nav__trigger-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.3s var(--ease-expo);
  margin-top: 1px;
}
.site-nav__trigger[aria-expanded="true"] .site-nav__trigger-arrow {
  transform: rotate(180deg);
}

/* === Megamenu panel ===
   Hard-coded dark scheme matching layout-demo.html — the panel keeps the same
   visual identity in both light and dark theme modes (it's a menu overlay,
   not page chrome, so it shouldn't recolor when the rest of the site does).
   Local tokens — only used inside .megamenu, scoped with custom-property
   inheritance from this rule.
*/
.megamenu {
  /* Demo palette — hard-coded so the panel stays dark in both themes. */
  --mm-bg:          #15140f;  /* card surface */
  --mm-bg-hover:    #1c1b16;  /* row hover / active */
  --mm-bone:        #f3efe6;  /* primary text */
  --mm-bone-soft:   rgba(243, 239, 230, 0.78);
  --mm-muted:       #8a8a85;  /* secondary text */
  --mm-line:        rgba(243, 239, 230, 0.10);
  --mm-line-strong: rgba(243, 239, 230, 0.22);
  --mm-accent:      #D8FF3D;  /* matches --volt — stable across themes */

  position: absolute;
  top: 100%;
  left: var(--pad-x);
  right: var(--pad-x);
  margin-top: 8px;
  background: var(--mm-bg);
  border: 1px solid var(--mm-line);
  border-radius: 18px;
  overflow: hidden;
  z-index: 79; /* one below .site-header so the header's blur sits over it */
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 0.32s var(--ease-expo), transform 0.32s var(--ease-expo);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
}
.megamenu[hidden] { display: none; }
.megamenu[data-open="true"] {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.megamenu__inner {
  display: grid;
  grid-template-columns: 330px 1fr;
  min-height: 480px;
}

/* --- Left rail: brand list ---
   `padding-left: 12px` keeps the active accent indicator (border-left on the
   row) inset from the panel's rounded edge so the names don't kiss the
   container border. Right side stays flush against the rail divider.

   Height: 14 case studies × ~56px row = ~810px. The rail caps at 560px
   and scrolls — a visible scrollbar (always shown via opacity tricks
   below) signals there's more content. Reverted from a viewport-aware
   max-height after the fade-mask approach hid the scrollbar visually. */
.megamenu__list {
  list-style: none;
  margin: 0;
  /* Vertical padding 12px matches the demo. Left padding 8px keeps the
     active row's accent border-left from kissing the panel's rounded
     corner; right side stays flush against the rail divider.
     Right padding 10px reserves room for the scrollbar gutter so the
     last row's text doesn't sit under the scrollbar thumb. */
  padding: 12px 10px 12px 8px;
  border-right: 1px solid var(--mm-line);
  max-height: 560px;
  overflow-y: scroll; /* `scroll` (not `auto`) so the bar is always visible */
  scrollbar-gutter: stable;
  /* Firefox: persistent thin bar in the brand line color. */
  scrollbar-width: thin;
  scrollbar-color: var(--mm-line-strong) transparent;
}
/* WebKit / Blink: persistent visible scrollbar. */
.megamenu__list::-webkit-scrollbar {
  width: 8px;
}
.megamenu__list::-webkit-scrollbar-track {
  background: rgba(243, 239, 230, 0.04);
  border-radius: 999px;
  margin: 8px 0;
}
.megamenu__list::-webkit-scrollbar-thumb {
  background: var(--mm-line-strong);
  border-radius: 999px;
}
.megamenu__list::-webkit-scrollbar-thumb:hover {
  background: var(--mm-bone-soft);
}

.megamenu__list-item { display: block; }

.megamenu__list-link {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 18px;
  border-left: 3px solid transparent;
  text-decoration: none;
  color: var(--mm-bone);
  cursor: pointer;
  transition: background-color 0.2s var(--ease-expo), border-color 0.2s var(--ease-expo);
}
.megamenu__list-link:hover {
  background: var(--mm-bg-hover);
}
.megamenu__list-link.is-active,
.megamenu__list-link[aria-selected="true"] {
  background: var(--mm-bg-hover);
  border-left-color: var(--mm-accent);
}
.megamenu__list-link:focus-visible {
  outline: 2px solid var(--mm-accent);
  outline-offset: -2px;
}

/* Brand-color tile carrying the logo silhouette — same visual cue as the
   homepage cards, scaled down to a 38×38 row indicator (matches demo's
   layout-demo.html → Option 3). */
.megamenu__list-tile {
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--brand-from, #15140f), var(--brand-to, #0a0a08));
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 5px;
  overflow: hidden;
}
.megamenu__list-tile img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  filter: brightness(0) invert(1);
  opacity: 0.95;
}

/* Text fallback for brands that don't ship a logo.{svg,png,jpg} file —
   renders the first 1-2 chars of the wordmark inside the gradient tile so
   the row stays visually consistent. No filter/inversion needed since the
   text is already painted in --mm-bone. */
.megamenu__list-tile--text {
  padding: 0; /* monogram is already centered via flex */
}
.megamenu__list-tile-mono {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--mm-bone);
  line-height: 1;
  opacity: 0.95;
}

.megamenu__list-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.megamenu__list-name {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 15px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mm-bone);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.megamenu__list-meta {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 9px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mm-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- Right detail ---
   Single-column layout per the layout-demo Option 3 design:
     ┌──────────────────────────────────────┐
     │ 2024  [LOGO]  B2B REDESIGN           │  meta row (logo replaces wordmark text)
     │ Title with em                         │
     │ PROBLEM  │  APPROACH  │  RESULT       │  3-column dl
     │ ...      │  ...       │  ...          │
     │ READ FULL CASE ↗                      │
     │ ┌──────────────────────────────────┐ │
     │ │      live site hero strip        │ │  fills remaining vertical space
     │ └──────────────────────────────────┘ │
     └──────────────────────────────────────┘
   Each panel uses the brand-color gradient as its background — hovering a
   different brand in the sidebar swaps the panel and the colour with it. */
.megamenu__detail {
  /* No padding on the container — each panel handles its own padding so it
     can paint its brand-colour gradient flush against the sidebar's right
     edge (fixes the left-margin issue: content was double-padded before). */
  position: relative;
  display: flex;
  flex-direction: column;
}
.megamenu__panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding: 36px;
  background: linear-gradient(135deg, var(--brand-from, #15140f), var(--brand-to, #0a0a08));
  min-height: 480px;
  overflow: hidden;
}
.megamenu__panel[hidden] { display: none; }

/* --- Eyebrow row: year · LOGO (replaces client text) · project tag --- */
.megamenu__panel-meta {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(243, 239, 230, 0.6);
}
.megamenu__panel-year { color: rgba(243, 239, 230, 0.6); }
.megamenu__panel-tag  { color: rgba(243, 239, 230, 0.6); }

/* The client name sits between the year and the project tag, painted in the
   bone colour so it reads as the row's anchor (matches the demo's Option 3
   eyebrow exactly). */
.megamenu__panel-client {
  font-weight: 500;
  color: var(--mm-bone);
}

/* --- Title --- */
.megamenu__panel-title {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 400;
  font-size: 30px;
  line-height: 1.15;
  margin: 0;
  color: var(--mm-bone);
  max-width: 28ch;
}
.megamenu__panel-title em {
  /* Per-brand accent (Total Group → orange, Bevilles → volt, etc.) — falls
     back to the menu's universal accent if a panel doesn't supply one. */
  color: var(--brand-accent, var(--mm-accent));
  font-style: italic;
}

/* --- Problem / Approach / Result — 3-column dl --- */
.megamenu__panel-par {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  margin: 0;
}
.megamenu__panel-par > div { min-width: 0; }
.megamenu__panel-par dt {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 18px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brand-accent, var(--mm-accent));
  margin: 0 0 8px;
}
.megamenu__panel-par dd {
  margin: 0;
  font-size: 18px;
  line-height: 1.5;
  color: rgba(243, 239, 230, 0.85);
  /* Clamp to four lines so a longer Problem/Approach paragraph in the
     canonical case data doesn't push the hero strip off-screen. The full
     text lives on the case-study page. */
  display: -webkit-box;
  -webkit-line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* --- "Read full case ↗" CTA --- */
.megamenu__panel-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brand-accent, var(--mm-accent));
  border-bottom: 1px solid currentColor;
  padding-bottom: 4px;
  text-decoration: none;
  transition: gap 0.3s var(--ease-expo);
}
.megamenu__panel-cta:hover { gap: 12px; }

/* --- Hero strip — live site's hero section.
   `flex: 1` makes it consume whatever vertical space is left in the panel
   after the meta/title/PAR/CTA. `background-position: top center` keeps the
   hero band of the homepage in frame even when the strip ends up cropped to
   a wide cinematic ratio. */
.megamenu__panel-hero {
  display: block;
  flex: 1;
  min-height: 160px;
  margin-top: auto;
  background-color: rgba(0, 0, 0, 0.2);
  background-size: cover;
  background-position: top center;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  text-decoration: none;
  transition: transform 0.4s var(--ease-expo), border-color 0.3s var(--ease-expo);
}
.megamenu__panel-hero:hover {
  transform: translateY(-2px);
  border-color: rgba(255, 255, 255, 0.18);
}

.megamenu__foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 28px;
  border-top: 1px solid var(--mm-line);
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mm-muted);
}
.megamenu__foot a { color: var(--mm-accent); text-decoration: none; }
.megamenu__foot a:hover { color: var(--mm-bone); }

/* Responsive */
@media (max-width: 1100px) {
  .megamenu__inner { grid-template-columns: 240px 1fr; }
  .megamenu__panel { padding: 28px; gap: 18px; }
  .megamenu__panel-title { font-size: 26px; }
  .megamenu__panel-par { gap: 18px; }
  .megamenu__panel-par dd { -webkit-line-clamp: 3; }
  .megamenu__list-link { padding: 12px 16px; gap: 12px; }
  .megamenu__list-tile { width: 32px; height: 32px; flex-basis: 32px; }
}
@media (max-width: 880px) {
  /* Match the original .site-nav mobile rule — primary nav and the mega menu
     are hidden together; mobile uses the brand link + Book Call CTA. A future
     mobile drawer can be added without re-architecting the desktop nav. */
  .site-nav, .megamenu { display: none !important; }
}

/* Reduce motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .hero__marquee-track { animation: none; }
  .cursor { display: none; }
}
