/* ============================================================================
   mediaPro International UK — landing page
   Dark-first by necessity, not taste: #FF8100 only reaches WCAG AA on black
   (8.34:1). See PROJECT-PLAN.md §5.1.
   ========================================================================= */

/* ── Tokens ──────────────────────────────────────────────────────────────── */
:root {
  /* Brand — immutable, per the manual. No fifth hue. */
  --mp-orange: #ff8100;
  --mp-grey:   #969798;
  --mp-white:  #ffffff;
  --mp-black:  #000000;

  /* Surfaces: tonal steps of brand black */
  --surface-0: #000000;
  --surface-1: #0a0a0a;
  --surface-2: #141414;
  --surface-3: #1e1e1e;

  --line-subtle: rgba(255, 255, 255, 0.10);
  --line-strong: rgba(255, 255, 255, 0.20);

  --text-primary:   #ffffff;
  --text-secondary: #969798;
  --text-accent:    #ff8100;

  --font-brand: Arial, "Helvetica Neue", Helvetica, sans-serif;

  --shell-max: 1320px;
  --shell-pad: clamp(20px, 5vw, 64px);

  --section-y: clamp(72px, 10vw, 148px);

  /* Motion */
  --e: cubic-bezier(0.16, 1, 0.3, 1);
  --t-fast: 180ms;
  --t-mid: 320ms;

  /* Pixel curtain. main.js parses these to schedule its own teardown, so they
     have to stay plain millisecond values — no seconds, no calc(). */
  --curtain-sweep: 500ms;       /* first tile to last */
  --curtain-pop: 90ms;          /* one tile's own fade */
  --curtain-content-out: 140ms; /* panel contents clearing before the sweep back */
  /* When the last tile has finished. Everything else in the menu waits for it. */
  --curtain-total: calc(var(--curtain-sweep) + var(--curtain-pop));
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  font-family: var(--font-brand);
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--text-primary);
  background: var(--surface-0);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
ul, ol { list-style: none; padding: 0; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
address { font-style: normal; }

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

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

.skip-link {
  position: absolute; left: 50%; top: 0; transform: translate(-50%, -120%);
  z-index: 200; padding: 12px 20px;
  background: var(--mp-orange); color: var(--mp-black); font-weight: bold;
  transition: transform var(--t-fast) var(--e);
}
.skip-link:focus { transform: translate(-50%, 0); }

/* ── Type ────────────────────────────────────────────────────────────────── */
.h2 {
  font-size: clamp(2rem, 4.5vw, 3.5rem);
  font-weight: bold;
  letter-spacing: -0.02em;
  line-height: 1.05;
}

.lead {
  font-size: clamp(1.125rem, 1.6vw, 1.375rem);
  line-height: 1.6;
  max-width: 60ch;
}

p { max-width: 68ch; }

/* The brand's own signature: wide-tracked uppercase micro-type. */
.micro-label {
  font-size: 0.75rem;
  font-weight: bold;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--text-accent);
}

/* ── Layout ──────────────────────────────────────────────────────────────── */
.shell {
  width: 100%;
  max-width: var(--shell-max);
  margin-inline: auto;
  padding-inline: var(--shell-pad);
}

.section { padding-block: var(--section-y); }
.section--alt { background: var(--surface-1); }

.section__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px 48px;
  margin-bottom: clamp(40px, 5vw, 72px);
  padding-bottom: 28px;
  border-bottom: 1px solid var(--line-subtle);
}
.section__head .micro-label { margin-bottom: 14px; }
.section__head--centred { justify-content: center; text-align: center; }
/* Just the micro-label, no rule under it — used where the head no longer
   carries an h2 (see the About page's How We Work section) and the border
   plus its padding would sit under one short line looking like a stray
   underline rather than a section divider. */
.section__head--no-rule { padding-bottom: 0; border-bottom: 0; }

/* A heading set to hold on a single line, fitted to the width it is given.
   "Turning Ambitious Ideas Into Extraordinary Experiences" measures ~25.6em
   of advance in the brand stack, so the size that exactly fills the
   container is width / 25.6 — 3.85cqi leaves slack for font fallbacks. The
   cap is dead at the current 1320px shell and only bites if the shell ever
   grows.

   Below ~730px of container that fitted size drops under 28px, too small for
   a section head, so the query simply stops applying and it wraps normally. */
.section__head--fit { container-type: inline-size; }

@container (min-width: 730px) {
  .section__head--fit .h2 {
    white-space: nowrap;
    font-size: min(3.5rem, 3.85cqi);
  }
}
.section__note { color: var(--text-secondary); max-width: 42ch; }

/* Caps the label+heading column so a long heading (e.g. the Products &
   Services one) wraps within its own width instead of claiming the full
   row and pushing .section__note onto a line of its own below it. Short
   headings elsewhere never approach this width, so they're unaffected. */
.section__head-copy { max-width: 700px; }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 28px;
  font-size: 0.9375rem;
  font-weight: bold;
  letter-spacing: 0.02em;
  white-space: nowrap;
  border: 1px solid transparent;
  transition: background var(--t-fast) var(--e),
              color var(--t-fast) var(--e),
              border-color var(--t-fast) var(--e),
              transform var(--t-fast) var(--e);
}
.btn:active { transform: translateY(1px); }

/* Orange takes BLACK text. White-on-orange is 2.52:1 and fails AA. */
.btn--primary { background: var(--mp-orange); color: var(--mp-black); }
.btn--primary:hover { background: #ffa040; }

.btn--ghost { border-color: var(--line-strong); color: var(--mp-white); }
.btn--ghost:hover { border-color: var(--mp-white); background: rgba(255, 255, 255, 0.06); }

.btn--sm { padding: 11px 20px; font-size: 0.8125rem; }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: bold;
  font-size: 0.9375rem;
  color: var(--mp-white);
  padding-bottom: 4px;
  border-bottom: 1px solid var(--line-strong);
  transition: color var(--t-fast) var(--e), border-color var(--t-fast) var(--e);
}
.link-arrow span { transition: transform var(--t-mid) var(--e); }
.link-arrow:hover { color: var(--mp-orange); border-color: var(--mp-orange); }
.link-arrow:hover span { transform: translateX(5px); }
.link-arrow--sm { font-size: 0.8125rem; border: 0; padding: 0; }

/* ── Placeholder markers ─────────────────────────────────────────────────── */
/* Deliberately visible. Nothing fake should ship by accident. */
.ph {
  position: relative;
  display: grid;
  place-content: center;
  gap: 6px;
  text-align: center;
  background:
    repeating-linear-gradient(45deg,
      rgba(255, 129, 0, 0.06) 0 10px,
      transparent 10px 20px),
    var(--surface-2);
  border: 1px dashed rgba(255, 129, 0, 0.45);
}
.ph--16x9 { aspect-ratio: 16 / 9; }
.ph--logo { aspect-ratio: 5 / 2; }
.ph__tag {
  font-size: 0.6875rem;
  font-weight: bold;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mp-orange);
}
.ph__meta { font-size: 0.75rem; color: var(--text-secondary); }

.ph-tag {
  display: inline-block;
  font-size: 0.625rem;
  font-weight: bold;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mp-orange);
  border: 1px solid rgba(255, 129, 0, 0.5);
  padding: 3px 8px;
}
.ph-tag--corner { position: absolute; top: 12px; right: 12px; background: rgba(0, 0, 0, 0.72); }

/* ── Header ──────────────────────────────────────────────────────────────── */
.site-header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
}
/* Scrim keeps the logo legible over any video frame. Swaps out for the
   scrolled background below the instant the threshold is crossed — no
   opacity transition here, deliberately: on this element specifically it
   never resolves (confirmed by testing, not just theory), leaving the scrim
   stuck visible over the blurred layer instead of handing off to it. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.75), transparent);
  pointer-events: none;
}
.site-header.is-scrolled::before { opacity: 0; }

/* The scrolled background, on its own layer so it can be masked without
   fading the logo/nav sitting on top of it (site-header__inner's z-index
   keeps them above this). Half-transparent alone would let whatever's
   scrolling underneath show straight through the nav text, so it's blurred
   for legibility — and masked so it thins out and disappears before the
   header's own bottom edge, a soft vignette rather than the bar just
   stopping dead. The solid portion has to clear the CTA button, the tallest
   thing in the row (~50px, padding included) — at the 76px scrolled height
   that's ~83% down, so the fade doesn't start until 84%, comfortably below
   the logo and Contact button rather than dissolving through them. */
.site-header::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: rgb(0 0 0 / 50%);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  mask-image: linear-gradient(to bottom, black 0%, black 84%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, black 0%, black 84%, transparent 100%);
}
.site-header.is-scrolled::after { opacity: 1; }

/* Breaks out of the shell on the same inset as the hero headline, so the logo
   and the line below it share one left edge. Sits above both the scrim and
   the scrolled background — position:relative alone wouldn't guarantee that;
   it's the z-index that does. */
.site-header__inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  height: 96px;
  max-width: none;
  padding-inline: clamp(20px, 3.4vw, 48px);
  transition: height var(--t-mid) var(--e);
}
.site-header.is-scrolled .site-header__inner { height: 76px; }

.site-header__logo img { width: auto; height: 42px; transition: height var(--t-mid) var(--e); }
.site-header.is-scrolled .site-header__logo img { height: 36px; }

.site-nav { display: none; }
.site-nav__list { display: flex; align-items: center; gap: clamp(16px, 2vw, 30px); }
.site-nav__link {
  position: relative;
  /* Never break a label across lines — the row is sized to hold them whole. */
  white-space: nowrap;
  font-size: 0.8125rem;
  font-weight: bold;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-secondary);
  padding-block: 6px;
  transition: color var(--t-fast) var(--e);
}
.site-nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--mp-orange);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 240ms var(--e);
}
.site-nav__link:hover { color: var(--mp-white); }
.site-nav__link:hover::after { transform: scaleX(1); }

.site-header__actions { display: flex; align-items: center; gap: 14px; }

/* The CTA is present at every width, and phones only offer 280–374px of
   shell. Below 480px the row goes compact: smaller mark, tighter gaps and
   less padding on the button. The old rule also collapsed the label from
   "Request a Quote" to "Quote" to save 90-odd px; "Contact" is short enough
   that it no longer has to. */
@media (max-width: 479px) {
  .site-header__inner { gap: 16px; }
  .site-header__actions { gap: 10px; }
  .site-header__logo img { height: 34px; }
  .site-header .btn--sm { padding: 10px 14px; }
  /* The 16px label overruns the 320px floor: 123.6px of logo, 16px gap, 91.8px
     of button, 10px gap and the 44px toggle come to 285.4px against 280px of
     shell. 14px type on 12px of padding brings it to 273.7px, 6.3px in hand,
     and still a size up from the 13px this label used to sit at. Measured in
     the browser, not estimated — re-measure if the label changes. */
  .site-header__cta { font-size: 0.875rem; padding-inline: 12px; }
  /* The region switcher only ever shares this row with the toggle while the
     menu is open (body.is-locked) — the closed-state math above, and its
     6.3px of spare room, is untouched by this. Shrinking the switcher's own
     tap target here buys back some of the room a third icon costs; if it
     still doesn't fit on the narrowest phones, wrapping to a second line
     beats clipping. */
  .lang-switch__toggle { width: 36px; height: 36px; }
  .lang-switch__toggle svg { width: 18px; height: 18px; }
  body.is-locked .site-header__actions { flex-wrap: wrap; justify-content: flex-end; row-gap: 8px; }
  body.is-locked .site-header__inner { height: auto; min-height: 96px; }
}

/* Colour discipline: over the hero the orange belongs to "Elevate." alone, so
   the header button stays ghosted. Once the hero is gone it takes the orange
   and becomes the only accent in view. */
.site-header:not(.is-scrolled) .site-header__actions .btn--primary {
  background: transparent;
  color: var(--mp-white);
  border-color: var(--line-strong);
}
.site-header:not(.is-scrolled) .site-header__actions .btn--primary:hover {
  border-color: var(--mp-white);
  background: rgba(255, 255, 255, 0.06);
}

/* Softer than the rest of the geometry, which sits at 2px, but well short of
   a pill — the header is the one place a rounded box reads as a control. The
   label overrides .btn--sm: at 13px it read as a caption next to the nav, and
   the CTA has to out-weigh the links rather than match them. .btn--sm's own
   11px of block padding, stacked on that bigger label, read as bulky next to
   the 44px toggle/lang-switch controls either side of it — trimmed down so
   it lands close to their height instead of towering over them. Horizontal
   padding is untouched, so it doesn't also narrow. align-items:center on
   site-header__actions keeps it vertically centered regardless of height. */
.site-header__cta { border-radius: 8px; font-size: 1rem; padding-block: 7px; }

/* ── Region switcher ─────────────────────────────────────────────────────── */
/* Only ever visible while the mobile menu is open — body.is-locked is the
   exact signal setMenu() already sets on open/close, so no new JS state is
   needed just to show or hide this. A native <details>, not a custom
   dropdown: opening and closing need no JS at all this way — see
   templates/partials/header.html. */
.lang-switch { display: none; position: relative; }
body.is-locked .lang-switch { display: block; }

/* Above 1024px the switcher shares the header with the visible top nav (the
   drawer becomes a right-hand panel rather than covering the page — see
   templates/partials/header.html). .site-header__inner lays logo/nav/actions
   out with justify-content:space-between, so growing .site-header__actions
   by the switcher's width reshuffles both gaps and drags the nav links left
   when the menu opens. Taking the switcher out of flow keeps
   .site-header__actions the same size whether the menu is open or closed —
   the nav never moves — and positions it to land exactly where it would
   have sat in flow, so nothing visibly changes but the nav's stillness. */
@media (min-width: 1024px) {
  .site-header__actions { position: relative; }
  body.is-locked .lang-switch {
    position: absolute;
    top: 50%;
    right: 100%;
    transform: translateY(-50%);
    margin-right: 14px;
  }
}

.lang-switch__toggle {
  display: grid;
  place-content: center;
  width: 44px;
  height: 44px;
  color: var(--mp-white);
  cursor: pointer;
  list-style: none;
}
.lang-switch__toggle::-webkit-details-marker { display: none; }

.lang-switch__menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 20;
  display: flex;
  gap: 8px;
  padding: 10px;
  background: var(--surface-2);
  border: 1px solid var(--line-subtle);
}
.lang-switch__option {
  display: block;
  width: 28px;
  height: 19px;
  overflow: hidden;
  outline-offset: 2px;
  transition: transform var(--t-fast) var(--e);
}
.lang-switch__option:hover { transform: scale(1.08); }
.lang-switch__option svg { display: block; width: 100%; height: 100%; }

.menu-toggle { display: grid; place-content: center; width: 44px; height: 44px; }
.menu-toggle__bars { display: block; width: 26px; }
.menu-toggle__bars i {
  display: block;
  height: 2px;
  background: var(--mp-white);
  transition: transform var(--t-mid) var(--e), opacity var(--t-fast) var(--e);
}
.menu-toggle__bars i + i { margin-top: 7px; }
.menu-toggle[aria-expanded="true"] .menu-toggle__bars i:first-child { transform: translateY(4.5px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] .menu-toggle__bars i:last-child { transform: translateY(-4.5px) rotate(-45deg); }

/* ── Mobile menu ─────────────────────────────────────────────────────────── */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 99;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 40px;
  padding: 120px var(--shell-pad) 48px;
  background: var(--surface-0);
  overflow-y: auto;
}
.mobile-menu[hidden] { display: none; }
.mobile-menu__nav li {
  border-bottom: 1px solid var(--line-subtle);
  opacity: 0;
  transform: translateY(14px);
  animation: menu-in 460ms var(--e) forwards;
  /* --menu-delay holds the links back until the pixel curtain has landed. */
  animation-delay: calc(var(--menu-delay, 0ms) + 60ms * var(--i));
}
.mobile-menu__nav a {
  display: block;
  padding: 18px 0;
  font-size: clamp(1.5rem, 6vw, 2rem);
  font-weight: bold;
  letter-spacing: -0.02em;
}

/* The curtain paints the panel background instead, so the panel itself goes
   transparent — but only once JS has actually built the tiles. Without script,
   or under reduced motion, the flat background above stays. */
.mobile-menu.is-curtained { background: transparent; --menu-delay: var(--curtain-total); }

/* Closing runs in two beats: the contents fade, then the tiles sweep back out
   underneath them. Without the first beat the links would be left hanging over
   the page as their background dissolves away. */
.mobile-menu.is-closing { pointer-events: none; }
.mobile-menu.is-closing .mobile-menu__nav {
  opacity: 0;
  transition: opacity var(--curtain-content-out) var(--e);
}

/* From here the panel stops covering the page and becomes a right-hand drawer.
   A true 25% is too narrow for "Explore mediaPro UK" to sit on one line once
   padding is taken off, so it floors at 340px — a quarter at 1360px and wider,
   wider than a quarter below that. The rest of the page stays visible, so the
   panel needs an edge and a scrim to sit against. */
@media (min-width: 1024px) {
  .mobile-menu {
    inset: 0 0 0 auto;
    width: max(25%, 340px);
    padding: 120px clamp(28px, 2.6vw, 40px) 48px;
    border-left: 1px solid var(--line-subtle);
  }
  .mobile-menu__nav a { font-size: 1.375rem; }
  /* Dim the page behind it — also the click target that closes the panel. */
  .mobile-menu::before {
    content: "";
    position: fixed;
    inset: 0 max(25%, 340px) 0 0;
    background: rgba(0, 0, 0, 0.6);
    /* Paced to the sweep, not faster. Dimming the page ahead of the tiles reads
       as the backdrop arriving before the effect has finished. Linear, not --e:
       that ease-out is so front-loaded it hits 83% opacity a quarter of the way
       in, which is the same problem the matched duration was meant to fix. The
       tiles fill at a roughly even rate, so the scrim has to as well. */
    animation: scrim-in var(--curtain-total) linear both;
  }
  /* Cancelling the animation snaps opacity back to 1, which is exactly the
     value the transition then needs to leave from. The delay holds it there
     while the contents clear, so it lifts in step with the tiles. */
  .mobile-menu.is-closing::before {
    animation: none;
    opacity: 0;
    transition: opacity var(--curtain-total) linear var(--curtain-content-out);
  }
}

@keyframes menu-in { to { opacity: 1; transform: none; } }
@keyframes scrim-in { from { opacity: 0; } to { opacity: 1; } }

/* ── Pixel curtain ───────────────────────────────────────────────────────── */
/* The menu's background rebuilt as a grid of squares that pop on in a
   wavefront. Tiles are absolutely placed and sized by JS; everything that
   varies per tile arrives as an inline style, so all this has to describe is
   the pop itself. Sits under the panel (z-index 99) and the header (100). */
.pixel-curtain {
  position: fixed;
  inset: 0;
  z-index: 98;
  pointer-events: none;
}
.pixel-curtain[hidden] { display: none; }
.pixel-curtain i {
  position: absolute;
  display: block;
  background: var(--surface-0);
  opacity: 0;
  /* Near-instant per tile. A slower ramp reads as a fade; the hard pop is what
     makes the sweep read as pixels. The sweep itself lives in the delays. */
  transition: opacity var(--curtain-pop) linear;
  transition-delay: var(--d, 0ms);
}
.pixel-curtain.is-open i { opacity: 1; }

/* Mirrors the drawer's own footprint above 1024px. Has to come after the base
   rule above, not up in the panel's media query — same specificity, so this
   only wins on source order. */
@media (min-width: 1024px) {
  .pixel-curtain { inset: 0 0 0 auto; width: max(25%, 340px); }
}

body.is-locked { overflow: hidden; }

/* ── Hero ────────────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  /* svh, not vh — avoids the mobile browser-chrome jump. */
  min-height: 100svh;
  padding-top: 140px;
  overflow: hidden;
  isolation: isolate;
}

.hero__media { position: absolute; inset: 0; z-index: -2; background: var(--mp-black); }
.hero__poster,
.hero__video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
/* Video fades up over the poster — literally a lighting cue. */
.hero__video { opacity: 0; transition: opacity 1200ms ease-out; }
.hero__video.is-ready { opacity: 1; }

/* Top and bottom only — no left-hand fade, so the footage reads clean across
   the full width. The bottom carries the headline; the top is the shorter of
   the two and exists purely so the nav clears contrast over lit footage
   (1.63:1 without it, against a 4.5 minimum). */
.hero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(0, 0, 0, 0.88) 0%, rgba(0, 0, 0, 0.6) 9%, rgba(0, 0, 0, 0.2) 16%, transparent 24%),
    linear-gradient(to top, rgba(0, 0, 0, 0.95) 0%, rgba(0, 0, 0, 0.55) 22%, rgba(0, 0, 0, 0.2) 42%, transparent 62%);
}

/* Breaks out of the shell: the line sits nearer the left edge than the header
   does, which is the twincampro placement. */
.hero__inner {
  position: relative;
  max-width: none;
  padding-inline: clamp(20px, 3.4vw, 48px);
  padding-bottom: clamp(24px, 3vw, 40px);
}

/* One line, low and hard left. Two bounds, both load-bearing: 7.1vw is what
   keeps the sentence (11.75em at this tracking) on one line at any width, and
   4rem is the desktop cap. Rewording the sentence means re-measuring. */
.hero__title {
  font-size: min(7.1vw, 4rem);
  font-weight: bold;
  letter-spacing: -0.03em;
  line-height: 1;
  white-space: nowrap;
  margin-bottom: 0;
}
/* Each word lifts and lights on hover — the only motion in the hero. The glow
   is two stacked shadows: a tight one to thicken the edge, a wide soft one to
   read as spill behind the glyphs. */
.hero__title .word {
  display: inline-block;
  transition: transform 280ms var(--e), text-shadow 280ms var(--e);
}
.hero__title .word:hover {
  transform: translateY(-0.09em);
  text-shadow:
    0 0 0.12em rgba(255, 255, 255, 0.45),
    0 0 0.55em rgba(255, 255, 255, 0.35);
}
.hero__title .word--accent { color: var(--mp-orange); }
.hero__title .word--accent:hover {
  text-shadow:
    0 0 0.12em rgba(255, 129, 0, 0.55),
    0 0 0.6em rgba(255, 129, 0, 0.45);
}

/* A gradient twice the width of the word, clipped to the glyphs and slid
   leftward — the shimmer-text effect. It runs on hover only, as a second layer
   on the existing glow. `Elevate.` uses the same sweep in orange, further
   down, so the accent survives the clip.
   Guarded by @supports because `color: transparent` without a working clip
   renders the words invisible rather than merely unshimmered. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .hero__title .word--shimmer {
    /* The gradient is clipped to the glyphs at rest too, but the opaque text
       covers it, so nothing shows until :hover turns the fill transparent.
       Painting it up front means no first-frame flash. */
    background-image: linear-gradient(
      90deg,
      var(--mp-white) 0%,
      rgba(255, 255, 255, 0.35) 50%,
      var(--mp-white) 100%
    );
    background-size: 200% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    /* line-height is 1, so the tail of `g` hangs outside the box the gradient
       is painted in and would be clipped away with the fill transparent. The
       padding grows that box; the negative margin puts the line box back. */
    padding-bottom: 0.24em;
    margin-bottom: -0.24em;
    /* text-shadow paints behind transparent glyphs and smears through them, so
       the hover glow swaps it for drop-shadow, which reads the clipped
       gradient's own alpha. Same colours, same 280ms as before. */
    transition: transform 280ms var(--e), filter 280ms var(--e);
  }
  .hero__title .word--shimmer:hover {
    color: transparent;
    animation: hero-shimmer 2.5s linear infinite;
    text-shadow: none;
    filter:
      drop-shadow(0 0 0.12em rgba(255, 255, 255, 0.45))
      drop-shadow(0 0 0.55em rgba(255, 255, 255, 0.35));
  }

  /* Same sweep, brand palette: the band dips the orange rather than the white,
     so all three words dim and recover together. The glow moves to drop-shadow
     for the same reason it did above — text-shadow smears through the clip. */
  .hero__title .word--shimmer.word--accent {
    background-image: linear-gradient(
      90deg,
      var(--mp-orange) 0%,
      rgba(255, 129, 0, 0.35) 50%,
      var(--mp-orange) 100%
    );
  }
  .hero__title .word--shimmer.word--accent:hover {
    text-shadow: none;
    filter:
      drop-shadow(0 0 0.12em rgba(255, 129, 0, 0.55))
      drop-shadow(0 0 0.6em rgba(255, 129, 0, 0.45));
  }
}

@keyframes hero-shimmer {
  from { background-position: 200% center; }
  to   { background-position: -200% center; }
}

/* Right-aligned rather than centred — the bottom-right corner the removed
   video toggle used to occupy — and taller than before, plus a dark backdrop
   behind it: against a busy, bright video frame a thin outline alone read as
   barely there. */
.hero__cue {
  position: absolute;
  right: clamp(20px, 3.4vw, 48px);
  bottom: clamp(24px, 3vw, 40px);
  z-index: 2;
  width: 20px; height: 46px;
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(6px);
  display: none;
}
.hero__cue span {
  position: absolute;
  left: 50%; top: 8px;
  width: 2px; height: 6px;
  background: var(--mp-orange);
  transform: translateX(-50%);
  animation: cue 1.9s var(--e) infinite;
}
@keyframes cue {
  0%, 18% { opacity: 0; transform: translate(-50%, 0); }
  40% { opacity: 1; }
  75%, 100% { opacity: 0; transform: translate(-50%, 18px); }
}

/* ── Explore mediaPro UK ─────────────────────────────────────────────────── */
.explore__grid { display: grid; gap: clamp(36px, 5vw, 72px); }
.explore__copy > * + * { margin-top: 20px; }
.explore__copy .micro-label + .h2 { margin-top: 16px; }
.explore__copy p { color: var(--text-secondary); }
.explore__copy .lead { color: var(--text-primary); }

.explore__media { position: relative; }
.explore__media > img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.explore__gallery-link { margin-top: 20px; }
/* Hairline orange rule as a framing device rather than a border. */
.explore__media::after {
  content: "";
  position: absolute;
  left: 0; bottom: -1px;
  width: 84px; height: 3px;
  background: var(--mp-orange);
}

.stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  margin-top: clamp(48px, 6vw, 88px);
  background: var(--line-subtle);
  border-block: 1px solid var(--line-subtle);
}
.stat {
  position: relative;
  display: grid;
  gap: 8px;
  align-content: start;
  padding: clamp(24px, 3vw, 38px) clamp(18px, 2vw, 28px);
  background: var(--surface-0);
}
.stat__value {
  font-size: clamp(2.25rem, 5vw, 3.5rem);
  font-weight: bold;
  letter-spacing: -0.03em;
  line-height: 1;
}
.stat__label {
  font-size: 0.8125rem;
  color: var(--text-secondary);
  line-height: 1.45;
}
.stat .ph-tag { position: absolute; top: 12px; right: 12px; }

/* ── Cards ───────────────────────────────────────────────────────────────── */
.cards { display: grid; gap: clamp(18px, 2.2vw, 28px); }
.card {
  position: relative;
  background: var(--surface-2);
  border: 1px solid var(--line-subtle);
  transition: background var(--t-mid) var(--e),
              border-color var(--t-mid) var(--e),
              transform var(--t-mid) var(--e);
}
.card:hover { background: var(--surface-3); border-color: var(--line-strong); transform: translateY(-3px); }

/* Projects */
.project__media { overflow: hidden; }
.project__media img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; transition: transform 620ms var(--e); }
.project:hover .project__media img { transform: scale(1.045); }
.project__body { padding: clamp(20px, 2.2vw, 30px); display: grid; gap: 12px; }
.project__title { font-size: clamp(1.1875rem, 1.7vw, 1.4375rem); font-weight: bold; letter-spacing: -0.01em; line-height: 1.2; text-align: center; }
.project__meta {
  font-size: 0.6875rem;
  font-weight: bold;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mp-orange);
  text-align: center;
}
.project__summary { font-size: 0.9375rem; color: var(--text-secondary); text-align: center; }

/* Every chip the same width so five disciplines read as a tidy 3 + 2 grid and
   a lone "Video" is the same size as the rest. */
.project .tags li { flex: 0 0 6.25rem; text-align: center; padding-inline: 4px; }

.tags { display: flex; flex-wrap: wrap; justify-content: center; gap: 7px; margin-top: 4px; }
.tags li {
  font-size: 0.6875rem;
  font-weight: bold;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-secondary);
  padding: 5px 10px;
  border: 1px solid var(--line-subtle);
}

/* Services */
.svc { padding: clamp(24px, 2.4vw, 32px); }
/* The grid lives on the link, not .svc itself — same split as
   .project/.project__link. A display:contents anchor would leave the
   gaps between icon/name/summary/caps un-clickable (gaps belong to
   whichever element owns the grid); owning it here instead means the
   full card interior, gaps included, is part of the link's own box. */
.svc__link { display: grid; gap: 14px; align-content: start; height: 100%; }
.svc__icon { color: var(--mp-orange); width: 44px; height: 44px; justify-self: center; }
.svc__name { font-size: 1.25rem; font-weight: bold; letter-spacing: -0.01em; text-align: center; }
/* min-height reserves 4 lines regardless of how long each service's own
   summary happens to be, so .svc__caps below starts at the same height on
   every card in the row — a shorter summary otherwise left that card's
   divider and list noticeably higher than its neighbours'. 4 rather than 3:
   at this card's actual rendered width the copy wraps more than its
   character count suggests, and 3 clipped two of the five summaries. */
.svc__summary { font-size: 0.9375rem; line-height: 1.5; min-height: 6em; color: var(--text-secondary); text-align: center; }
.svc__caps { display: grid; gap: 7px; margin-top: 4px; padding-top: 16px; border-top: 1px solid var(--line-subtle); }
/* Summaries and capability lists are held back until the service pages
   return (see SERVICE_PAGES_ENABLED). Each card is then just icon and name,
   so both step up to carry the card on their own. */
.cards--svc-bare .svc { padding-block: clamp(36px, 4vw, 60px); }
.cards--svc-bare .svc__link { gap: 22px; align-content: center; }
.cards--svc-bare .svc__icon { width: 88px; height: 88px; }
.cards--svc-bare .svc__name { font-size: 1.5rem; }
.svc__caps li { font-size: 0.8125rem; color: var(--text-secondary); text-align: center; position: relative; }

/* Clients */
/* Fixed column counts, not auto-fill: ten logos must fill whole rows rather
   than leaving a ragged half-empty band. */
.logo-wall {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--line-subtle);
  border: 1px solid var(--line-subtle);
}
.logo-wall__item {
  display: grid;
  place-items: center;
  padding: clamp(20px, 2.4vw, 32px);
  background: var(--surface-1);
  transition: background var(--t-mid) var(--e);
}
.logo-wall__item:hover { background: var(--surface-2); }
.logo-wall__item img {
  max-height: 46px;
  width: auto;
  filter: grayscale(1) brightness(2);
  opacity: 0.55;
  transition: opacity var(--t-mid) var(--e), filter var(--t-mid) var(--e);
}
.logo-wall__item:hover img { opacity: 1; filter: none; }
.logo-wall__item .ph { width: 100%; }

/* Insights */
.insight__link { display: grid; gap: 12px; padding: clamp(22px, 2.4vw, 32px); height: 100%; align-content: start; }
.insight__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 0.6875rem;
  font-weight: bold;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.insight__cat { color: var(--mp-orange); }
.insight__title { font-size: clamp(1.125rem, 1.6vw, 1.375rem); font-weight: bold; letter-spacing: -0.01em; line-height: 1.25; }
.insight__excerpt { font-size: 0.9375rem; color: var(--text-secondary); }
.insight__link .link-arrow--sm { margin-top: 6px; color: var(--text-secondary); }
.insight:hover .link-arrow--sm { color: var(--mp-orange); }

/* ── Global presence ─────────────────────────────────────────────────────── */
/* Was surface-0, but with Clients gone this sits next to another black
   section — stepped up one so the tonal alternation survives. */
.section--global { background: var(--surface-1); }

/* Copy (list) stacked above the map below 1024px, side by side above it —
   same split as .explore__grid, which this otherwise mirrors. The header
   sits above this grid instead of inside .global__copy (its own
   .section__head, full shell width — see the section markup), specifically
   so the list starts right at the top of .global__copy with nothing above
   it: that is what lines its first row (UAE) up with the map's own top
   edge below, via align-items: start at the breakpoints further down. */
.global__grid { display: grid; gap: clamp(32px, 4.5vw, 64px); }

.global__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}
.global__country {
  flex: 1;
  padding-block: 10px;
  border: 0;
  background: none;
  font: inherit;
  font-weight: bold;
  text-align: left;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color var(--t-fast) var(--e);
}
.global__country:hover,
.global__country:focus-visible,
.global__country.is-current { color: var(--mp-white); }

/* Sits on its own row, shown only while that row is active — by a plain
   :hover/:focus-within (no JS needed for this part at all) and, so a hover
   started on the map keeps this in sync too, by the same is-current class
   show()/hide() already put on .global__country. visibility rather than
   opacity: an invisible-but-still-opacity-0 link would still sit in the
   tab order on every row at once, which is worse than not being reachable
   until its own row is actually current. */
.global__detail-link {
  flex-shrink: 0;
  font-size: 0.8125rem;
  font-weight: bold;
  color: var(--mp-orange);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--t-fast) var(--e);
}
.global__row:hover .global__detail-link,
.global__row:focus-within .global__detail-link,
.global__country.is-current ~ .global__detail-link {
  visibility: visible;
  opacity: 1;
}

/* ── World map ───────────────────────────────────────────────────────────── */
/* Drawn once by tools/build_world_map.py into a template partial, so the page
   ships flat SVG — no map library, nothing fetched at runtime. */
.worldmap {
  position: relative;
  /* No standalone cap here any more — .global__grid's own map column does
     that job now (see the 1024px/1240px breakpoints below). Cropping the
     Americas already keeps the frame squarer than a full world map, which
     is what made a cap worth having in the first place. */
  width: 100%;
}
.wm__svg { display: block; width: 100%; height: auto; }

/* The backdrop sits barely above the page so the twelve carry the colour. */
.wm__land { fill: var(--surface-2); }
.wm__mark,
.wm__dot {
  fill: var(--mp-orange);
  transition: fill var(--t-fast) var(--e);
}
/* Dimming is driven by a class rather than :hover on the container, so that
   crossing the ocean does not knock the whole map back — only landing on a
   country does. */
.worldmap.is-focused .wm__mark,
.worldmap.is-focused .wm__dot { fill: rgba(255, 129, 0, 0.4); }
/* The lit shape is marked by the same code that fills the tooltip, not by
   :hover — a tap fires pointerover without ever entering the hover state, and
   this way the highlight and the label can never disagree. */
.worldmap.is-focused .wm__mark.is-active,
.worldmap.is-focused .wm__dot.is-active { fill: var(--mp-orange); }

/* Qatar, Bahrain and Singapore are dots rather than shapes — too small to
   register at 110m, two of them absent from the data altogether. The ring
   keeps a 4.5px dot legible against land of a similar value. */
.wm__dot { stroke: var(--surface-0); stroke-width: 1.5; }

.worldmap__tip {
  position: absolute;
  z-index: 2;
  display: grid;
  gap: 2px;
  padding: 10px 14px;
  background: var(--surface-0);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  /* Both left and top are real edge coordinates set in JS — placed beside
     the shape (right by default, left if that would run off the map), not
     centred on it, so the label never sits on top of the country it
     describes. No transform needed to compensate. */
  pointer-events: none;
  /* Addresses are long, so the label wraps inside a fixed measure rather than
     stretching the map. */
  max-width: 270px;
  text-align: left;
}

.worldmap__tip[hidden] { display: none; }
.worldmap__tip-name {
  font-size: 0.8125rem;
  font-weight: bold;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--mp-white);
}
.worldmap__tip-body { display: grid; gap: 10px; }
.worldmap__tip-office { display: grid; gap: 1px; }
/* Countries with several offices get a rule between them, so three addresses
   do not read as one run-on block. */
.worldmap__tip-office + .worldmap__tip-office {
  padding-top: 9px;
  border-top: 1px solid var(--line-subtle);
}
.worldmap__tip-city {
  font-size: 0.8125rem;
  font-weight: bold;
  color: var(--mp-white);
}
.worldmap__tip-address {
  font-size: 0.75rem;
  line-height: 1.4;
  color: var(--text-secondary);
}
.worldmap__tip-phone {
  margin-top: 3px;
  font-size: 0.8125rem;
  color: var(--mp-orange);
  font-variant-numeric: tabular-nums;
}

/* The grid carries the same detail the map shows on hover, so the section
   reads the same without a pointer. */

/* ── Socials ─────────────────────────────────────────────────────────────── */
.socials { display: grid; gap: clamp(16px, 2vw, 24px); }
.social {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas: "icon name go" "icon handle go";
  align-items: center;
  column-gap: 18px;
  padding: clamp(22px, 2.4vw, 30px);
  background: var(--surface-2);
  border: 1px solid var(--line-subtle);
  transition: background var(--t-mid) var(--e), border-color var(--t-mid) var(--e);
}
.social:hover { background: var(--surface-3); border-color: var(--line-strong); }
.social__icon { grid-area: icon; display: grid; place-items: center; width: 46px; height: 46px; border: 1px solid var(--line-subtle); color: var(--mp-white); }
.social__name { grid-area: name; font-weight: bold; letter-spacing: -0.01em; }
.social__handle { grid-area: handle; font-size: 0.8125rem; color: var(--text-secondary); }
.social__go { grid-area: go; color: var(--text-secondary); transition: transform var(--t-mid) var(--e), color var(--t-mid) var(--e); }
.social:hover .social__go { transform: translateX(5px); color: var(--mp-orange); }

/* ── Interior pages ──────────────────────────────────────────────────────── */
/* The header is fixed and the landing page only gets away with it because the
   hero sits underneath. Every other page has to clear it. */
.section--page { padding-top: calc(var(--section-y) + 90px); }

.crumbs { margin-bottom: clamp(24px, 3vw, 40px); }
.crumbs__list {
  /* An ol, so it carries semantics for assistive tech. The reset clears the
     numbering — see the ul, ol rule there. */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 0.75rem;
  font-weight: bold;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.crumbs__list li + li::before { content: "/"; margin-right: 8px; opacity: 0.5; }
.crumbs__list a { color: var(--text-secondary); transition: color var(--t-fast) var(--e); }
.crumbs__list a:hover { color: var(--mp-white); }
.crumbs__list [aria-current] { color: var(--mp-orange); }

/* ── Category tiles ──────────────────────────────────────────────────────── */
/* Six of them, so three across makes two clean rows rather than an orphan. */
.tiles { display: grid; gap: clamp(18px, 2.4vw, 32px); }
.tile { display: grid; gap: 12px; }
.tile__media {
  display: block;
  overflow: hidden;
  border-radius: 10px;
  border: 1px solid var(--line-subtle);
}
.tile__media img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform 620ms var(--e);
}
.tile:hover .tile__media img { transform: scale(1.045); }
.tile:hover .tile__media { border-color: var(--line-strong); }
.tile__name {
  font-size: clamp(1.125rem, 1.7vw, 1.375rem);
  font-weight: bold;
  letter-spacing: -0.01em;
  color: var(--mp-white);
  transition: color var(--t-fast) var(--e);
}
.tile:hover .tile__name { color: var(--mp-orange); }

/* The listing cards are anchors wrapping spans, unlike the landing page where
   the same classes sit on divs. These make the spans behave as blocks; a div
   is already block, so the landing page is unaffected. */
.project__link { display: grid; grid-template-rows: auto 1fr; height: 100%; }
.project__media,
.project__body,
.project__title,
.project__meta,
.project__summary { display: block; }
.project__body { display: grid; }

.empty {
  padding: clamp(28px, 4vw, 48px);
  border: 1px dashed var(--line-strong);
  color: var(--text-secondary);
  display: grid;
  gap: 14px;
  justify-items: start;
}

/* ── One project ─────────────────────────────────────────────────────────── */
/* No cap here — full width until the 600px breakpoint gives .work__grid its
   sidebar, where this is capped to match that grid's own flexible column
   exactly (see the media query below). Before that, .work__grid is a single
   stacked column too, so there is no sidebar for a cap to align against. */
.work__head { margin-bottom: clamp(24px, 3vw, 40px); }
/* .lead's own sitewide max-width:60ch would otherwise cap this narrower
   than .work__head's box. Left ragged rather than justified: unlike
   .work__body p below, this stands alone with no sidebar for its right
   edge to line up against, so there's nothing to gain by forcing lines to
   reach it — and hyphens: auto was splitting ordinary words (e.g.
   "fra-grance", "im-mersive") to do so. */
.work__head .lead { max-width: none; }
.work__media {
  overflow: hidden;
  border-radius: 10px;
  margin-bottom: clamp(28px, 3.6vw, 52px);
}
.work__media img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.work__grid { display: grid; gap: clamp(24px, 3vw, 48px); }
/* No max-width here, and it overrides the global `p { max-width: 68ch }`
   below on its own paragraphs too: that cap is sized for prose standing
   alone, and next to the facts sidebar it stopped the text well short of
   the track's actual width, leaving a wide dead gap before the sidebar. */
.work__body { display: grid; gap: 1em; }
/* Justified rather than ragged-right: a left-aligned line only reaches this
   box's edge by chance of where its words happen to break, which next to
   the facts sidebar reads as a gap rather than a second column. hyphens
   softens justify's usual cost (uneven word-spacing) by letting a long word
   break instead of stretching the gaps around it. */
.work__body p { max-width: none; text-align: justify; hyphens: auto; }
.work__body .quiet { color: var(--text-secondary); }

.facts { display: grid; gap: 0; border-top: 1px solid var(--line-subtle); }
.facts__row {
  display: grid;
  grid-template-columns: 8rem 1fr;
  gap: 12px;
  padding-block: 12px;
  border-bottom: 1px solid var(--line-subtle);
  font-size: 0.875rem;
}
.facts__row dt {
  font-size: 0.6875rem;
  font-weight: bold;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.facts__row dd { margin: 0; color: var(--mp-white); }
.facts__row dd a { color: var(--mp-orange); }
.work__facts .tags { margin-top: 18px; }

/* Project gallery: the same .carousel component the homepage's social posts
   use (see "Social carousels" below), one full-width photo at a time rather
   than the static grid this replaced. */
.carousel--gallery { margin-block: clamp(32px, 4vw, 56px); }
/* Gallery as the page header: sits where the cover image used to. */
.carousel--lead { margin-top: 0; margin-bottom: clamp(28px, 3.6vw, 52px); }

/* Service detail page: the "Our Brands" strip below the write-up. Reuses
   .logo-wall as-is (built for the homepage trust wall but never wired up
   there — see CONTENT-NEEDED.md) rather than styling a second grid. */
.service-brands { margin-block: clamp(32px, 4vw, 56px); }
.service-brands h2 { color: var(--mp-orange); }
.gallery-figure img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 8px;
}
.gallery-figure figcaption {
  margin-top: 8px;
  font-size: 0.75rem;
  color: var(--text-secondary);
}

/* ── About ───────────────────────────────────────────────────────────────── */
/* This page carries no photography by design: the growth story is told in
   type, so none of it waits on a shoot. Everything below is rules, numerals
   and measure — the same devices the rest of the site already uses. */
.story__head { max-width: 68ch; }
.story__head .micro-label + .h2 { margin-top: 16px; }
.story__head .h2 + .lead { margin-top: clamp(20px, 2.4vw, 28px); }

.story__body { display: grid; gap: 1.1em; margin-top: clamp(28px, 3vw, 40px); }
.story__body p { color: var(--text-secondary); }

/* Timeline: rows, not a rail. The date is a left-hand column once there is
   room for one and stacks above its entry when there is not — a vertical rail
   would need a gutter the narrow layout cannot spare. */
/* No border-top: .section__head already rules off directly above, and a second
   line below it read as an empty first row. */
.timeline { display: grid; }
.timeline__step {
  display: grid;
  gap: 10px;
  padding-block: clamp(26px, 3.4vw, 44px);
  border-bottom: 1px solid var(--line-subtle);
}
.timeline__when {
  font-size: 0.6875rem;
  font-weight: bold;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mp-orange);
}
.timeline__what { display: grid; gap: 12px; }
.timeline__title {
  font-size: clamp(1.1875rem, 1.8vw, 1.5rem);
  font-weight: bold;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.timeline__what p { font-size: 0.9375rem; color: var(--text-secondary); }

/* Dual advantage. Hairline-separated panels rather than .card: these two are a
   single argument split in half, and the card lift would read as two choices. */
.duo {
  display: grid;
  gap: 1px;
  background: var(--line-subtle);
  border: 1px solid var(--line-subtle);
}
.duo__panel {
  display: grid;
  gap: 14px;
  align-content: start;
  padding: clamp(26px, 3.4vw, 48px);
  background: var(--surface-0);
  transition: background var(--t-mid) var(--e);
}
.duo__panel:hover { background: var(--surface-2); }
.duo__title {
  font-size: clamp(1.25rem, 2vw, 1.625rem);
  font-weight: bold;
  letter-spacing: -0.015em;
  line-height: 1.15;
}
.duo__copy { color: var(--text-secondary); }

/* Pillars */
.pillars { display: grid; gap: clamp(26px, 3vw, 40px); }
/* Was up in .section__head, level with the "How we work" label — moved
   below the pillar copy instead, so it reads as a call to action after the
   case for it rather than a header ornament before it. */
.pillars__cta { margin-top: clamp(28px, 3.4vw, 48px); }
.pillar {
  display: grid;
  gap: 12px;
  align-content: start;
  padding-top: 20px;
  border-top: 1px solid var(--line-strong);
}
.pillar__title {
  font-size: clamp(1.0625rem, 1.5vw, 1.25rem);
  font-weight: bold;
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.pillar__copy { font-size: 0.9375rem; color: var(--text-secondary); }

/* Both numerals take the orange micro-type the project meta already uses, so
   the page has one counting device rather than two. */
.duo__index,
.pillar__index {
  font-size: 0.6875rem;
  font-weight: bold;
  letter-spacing: 0.18em;
  color: var(--mp-orange);
}

/* Close */
.pullquote {
  margin: 0 0 clamp(48px, 6vw, 88px);
  padding-left: clamp(18px, 2.4vw, 32px);
  border-left: 2px solid var(--mp-orange);
}
.pullquote p {
  font-size: clamp(1.375rem, 3vw, 2.125rem);
  font-weight: bold;
  letter-spacing: -0.02em;
  line-height: 1.25;
  /* Wide enough to sit against the .h2 below it rather than ragging short of
     it — a display measure, not a reading one. */
  max-width: 34ch;
}

.closer { display: grid; gap: 20px; justify-items: start; }
.closer p { color: var(--text-secondary); }
.closer__actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px; }

/* ── Social carousels ────────────────────────────────────────────────────── */
/* One post visible per account, the rest reached with the buttons or a swipe.
   Showing a single card is what lets the three accounts stay on one row: a
   third of the shell is a comfortable width for one card, and hopeless for a
   rail of several. */
.carousel { position: relative; margin-top: clamp(14px, 1.6vw, 20px); }

/* The track is the scroll container. Everything the carousel does is native:
   snap points, momentum, keyboard scrolling. The buttons are an addition, not
   the mechanism, so this still works with JS off. */
.carousel__track {
  display: grid;
  grid-auto-flow: column;
  /* Exactly the width of the track, so a card can never be left half-read at
     the edge and the scroll step is always one whole post. */
  grid-auto-columns: 100%;
  gap: clamp(10px, 1.2vw, 16px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* No scrollbar: position is shown by the dots below, Instagram-style. */
  scrollbar-width: none;
}
.carousel__track::-webkit-scrollbar { display: none; }
/* The ring is drawn inside the box. Padding the scroller to make room for an
   outset ring instead left its resting scrollLeft at 4 rather than 0, which is
   enough to stop the "at the start" test in main.js ever being true. */
.carousel__track:focus-visible { outline: 2px solid var(--mp-orange); outline-offset: -2px; }
.carousel__item { scroll-snap-align: start; }

.post {
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr auto;
  height: 100%;
  background: var(--surface-2);
  border: 1px solid var(--line-subtle);
  transition: border-color var(--t-mid) var(--e), background var(--t-mid) var(--e);
}
.post:hover { border-color: var(--line-strong); background: var(--surface-0); }
.post__media { display: block; aspect-ratio: 16 / 9; overflow: hidden; }
.post__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.post__caption {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  padding: 14px 14px 0;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--mp-white);
}
.post__date {
  padding: 8px 14px 14px;
  font-size: 0.75rem;
  color: var(--text-secondary);
}

/* Added by JS, so they never appear as dead controls. */
.carousel__btn {
  position: absolute;
  top: calc(50% - 20px);
  z-index: 2;
  display: grid;
  place-content: center;
  width: 40px; height: 40px;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.72);
  border: 1px solid var(--line-strong);
  color: var(--mp-white);
  transition: opacity var(--t-fast) var(--e), border-color var(--t-fast) var(--e);
}
.carousel__btn:hover { border-color: var(--mp-orange); color: var(--mp-orange); }
.carousel__btn--prev { left: -8px; }
.carousel__btn--next { right: -8px; }
/* Disabled rather than removed, so the track does not shift when it runs out. */
.carousel__btn[disabled] { opacity: 0; pointer-events: none; }

/* Position dots, added by JS (so they never show without the script). One per
   slide, the current one lit, like a multi-photo Instagram post. */
.carousel__dots {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: 12px;
}
.carousel__dot {
  width: 6px; height: 6px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  cursor: pointer;
  transition: background var(--t-fast) var(--e), transform var(--t-fast) var(--e);
}
/* A 24px hit area around the 6px dot, for thumbs. */
.carousel__dot { position: relative; }
.carousel__dot::after { content: ""; position: absolute; inset: -9px; }
.carousel__dot:hover { background: rgba(255, 255, 255, 0.6); }
.carousel__dot[aria-current="true"] { background: var(--mp-orange); transform: scale(1.25); }

/* ── Footer ──────────────────────────────────────────────────────────────── */
.site-footer { background: var(--surface-0); border-top: 1px solid var(--line-subtle); }

/* The scrolling band. Track holds two identical copies, so shifting by exactly
   -50% lands back on an identical frame — seamless, no JS, no clone maths. */
/* Sits under everything else in the footer and runs without stopping — it is
   a watermark rather than a control, so hovering it does nothing. */
.marquee {
  padding-block: clamp(20px, 3vw, 36px);
  border-top: 1px solid var(--line-subtle);
}
.marquee__viewport { overflow: hidden; }
.marquee__track {
  display: flex;
  width: max-content;
  animation: marquee 60s linear infinite;
  will-change: transform;
}
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.marquee__copy {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2vw, 32px);
  padding-right: clamp(16px, 2vw, 32px);
  /* Tops out at 150px, the size the band runs at on twincampro.com. */
  font-size: clamp(3rem, 10vw, 9.375rem);
  font-weight: bold;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  line-height: 1.1;
  white-space: nowrap;
}
/* Solid fill at a whisper rather than an outline. The reference sits at 10%
   dark-on-white, which lands 8% off its background; white at 8% on black is
   the same distance, and happens to be exactly --surface-2. */
.marquee__word,
.marquee__sep { color: rgba(255, 255, 255, 0.08); }
.marquee__sep { font-size: 0.34em; }

.site-footer__grid {
  display: grid;
  gap: clamp(36px, 4vw, 56px);
  /* Asymmetric on purpose: .site-footer__legal below already carries its own
     24px of top padding, so the full clamp(48-80px) on this end alone put
     ~113px of dead space under whichever column runs longest (currently the
     brand column, since PM_logo_Web_White.zip's badge made it the tallest)
     before the copyright line. The top keeps its original spacing from the
     section above. */
  padding-block: clamp(48px, 6vw, 80px) clamp(28px, 3vw, 40px);
}
/* Logo, blurb and the social row read as one signature block, so they're
   centred as a unit rather than left-hung like the link columns beside them. */
.site-footer__col--brand { text-align: center; }
/* Block-level like every other img on the site (the site-wide img reset), so
   text-align on the column does nothing for it — needs its own centering. */
.site-footer__logo { width: auto; height: 40px; margin-bottom: 22px; margin-inline: auto; }
/* max-width caps the box narrower than the column on anything but the
   tightest mobile widths — without the auto margins, text-align alone would
   centre the wrapped lines inside a box still hugging the column's left
   edge. */
.site-footer__blurb { font-size: 0.9375rem; color: var(--text-secondary); max-width: 34ch; margin-inline: auto; }
.site-footer__socials { display: flex; justify-content: center; gap: 10px; margin-top: 24px; }
.site-footer__socials a {
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  border: 1px solid var(--line-subtle);
  color: var(--text-secondary);
  transition: color var(--t-fast) var(--e), border-color var(--t-fast) var(--e);
}
.site-footer__socials a:hover { color: var(--mp-white); border-color: var(--line-strong); }

/* Now leads the "Get in touch" column rather than closing the brand one, so
   the spacing points down to the heading below it instead of up to the
   socials row it used to sit under. */
.site-footer__plasa { display: inline-block; margin-bottom: 20px; transition: opacity var(--t-fast) var(--e); }
.site-footer__plasa img { display: block; width: 72px; height: auto; }
.site-footer__plasa:hover { opacity: 0.75; }

.site-footer__col .micro-label { color: var(--text-secondary); margin-bottom: 18px; }
.site-footer__links { display: grid; gap: 11px; }
.site-footer__links a { font-size: 0.9375rem; color: var(--text-secondary); transition: color var(--t-fast) var(--e); }
.site-footer__links a:hover { color: var(--mp-white); }
.site-footer__address { font-size: 0.9375rem; color: var(--text-secondary); line-height: 1.8; margin-bottom: 22px; }
.site-footer__address a:hover { color: var(--mp-white); }

.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  justify-content: space-between;
  padding-block: 24px;
  border-top: 1px solid var(--line-subtle);
  font-size: 0.8125rem;
  color: var(--text-secondary);
}

/* ── Contact page ────────────────────────────────────────────────────────── */
.contact__grid { display: grid; gap: clamp(40px, 5vw, 64px); }
.contact__info { display: grid; gap: 24px; align-content: start; }

.contact-form__notice {
  padding: 24px;
  margin-bottom: 28px;
  background: var(--surface-2);
  border: 1px solid var(--line-subtle);
}
.contact-form__notice--rate-limited { border-color: var(--mp-orange); }

/* ── Forms (PROJECT-PLAN.md §5.10) ──────────────────────────────────────── */
.form-field { display: grid; gap: 8px; margin-bottom: 22px; }
.form-field__label { font-size: 0.8125rem; font-weight: bold; letter-spacing: 0.02em; }
.form-field__input {
  height: 56px;
  padding: 0 16px;
  background: var(--surface-2);
  border: 1px solid var(--line-subtle);
  border-radius: 0;
  color: var(--text-primary);
  font: inherit;
}
.form-field__input:focus-visible {
  outline: 2px solid var(--mp-orange);
  outline-offset: 2px;
  border-color: var(--mp-orange);
}
.form-field__input[aria-invalid="true"] { border-color: var(--mp-orange); }
textarea.form-field__input { height: auto; min-height: 168px; padding: 16px; resize: vertical; }
.form-field__error { font-size: 0.875rem; color: var(--mp-orange); }
/* CSS-hidden, not display:none or type="hidden" — see forms.py's comment on
   company_website. */
.form-field--honeypot { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* ── Office grid ─────────────────────────────────────────────────────────── */
/* Hairline-separated cells, same technique as .duo: one continuous fact
   table reads better here than a set of separately-hovering .card tiles. */
.office-grid {
  display: grid;
  gap: 1px;
  background: var(--line-subtle);
  border: 1px solid var(--line-subtle);
  margin-top: clamp(32px, 4vw, 48px);
}
.office-grid__item {
  padding: clamp(20px, 2.2vw, 28px);
  background: var(--surface-0);
  display: grid;
  gap: 12px;
  align-content: start;
}
.office-grid__country {
  font-size: 0.8125rem;
  font-weight: bold;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mp-orange);
}
.office-grid__office { display: grid; gap: 4px; font-size: 0.9375rem; color: var(--text-secondary); }
.office-grid__office a { color: var(--text-secondary); transition: color var(--t-fast) var(--e); }
.office-grid__office a:hover { color: var(--mp-white); }
.office-grid__city { color: var(--text-primary); font-weight: bold; }
.office-grid__status { font-size: 0.9375rem; color: var(--text-secondary); }

/* Inline links inside prose — the privacy policy body and the contact page's
   footer note below it. Nothing else on the site links from inside a
   sentence, so unlike .office-grid__office a (a clearly-labelled phone
   number in a structured address block) these need an underline: colour
   alone would not mark them as clickable. */
.story__body a,
.section__note a {
  color: var(--mp-white);
  text-decoration: underline;
  text-underline-offset: 2px;
  transition: color var(--t-fast) var(--e);
}
.story__body a:hover,
.section__note a:hover { color: var(--mp-orange); }

.contact__privacy-note { margin-top: clamp(32px, 4vw, 48px); }

/* ── Coverflow carousel ──────────────────────────────────────────────────── */
/* Real Motion+ parameters (paywalled component), reimplemented here in
   vanilla JS/CSS — see
   docs/superpowers/specs/2026-08-28-coverflow-gallery-design.md for where
   the numbers come from. */
.coverflow {
  position: relative;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 15%, #000 85%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 15%, #000 85%, transparent);
}
.coverflow__track {
  position: relative;
  height: 0;
  /* Reserves height for the tallest absolutely-positioned item: width caps
     at 90% of the track (below), photos are 4:3, so 0.9 × 0.75 = 67.5% of
     the track's own width. Retune if either the width cap or the photo
     aspect ratio changes — the JS's cardWidth formula must match exactly. */
  padding-bottom: 67.5%;
  perspective: 1200px;
  touch-action: pan-y;
}
.coverflow__item {
  position: absolute;
  top: 0; left: 50%;
  width: min(540px, 90%);
}
.coverflow__item img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.coverflow__link { display: block; transition: transform var(--t-mid) var(--e), opacity var(--t-mid) var(--e); }
.coverflow__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 20px;
}
.coverflow__btn {
  display: grid;
  place-items: center;
  width: 36px; height: 36px;
  border: 1px solid var(--line-subtle);
  color: var(--mp-white);
  transition: border-color var(--t-fast) var(--e), opacity var(--t-fast) var(--e);
}
.coverflow__btn:hover { border-color: var(--line-strong); }
.coverflow__btn[disabled] { opacity: 0.3; pointer-events: none; }
.coverflow__dots { display: flex; gap: 8px; }
.coverflow__dot {
  width: 7px; height: 7px;
  border: 1px solid var(--line-strong);
  background: transparent;
  padding: 0;
  transition: background var(--t-fast) var(--e), border-color var(--t-fast) var(--e);
}
.coverflow__dot.is-current { background: var(--mp-orange); border-color: var(--mp-orange); }

/* ── Reveal on scroll ────────────────────────────────────────────────────── */
[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 700ms var(--e) var(--d, 0ms),
              transform 700ms var(--e) var(--d, 0ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }

/* The hero headline is deliberately not in this system — it is present from
   first paint and never animates in. See .hero__title for its hover state. */

/* ── Breakpoints ─────────────────────────────────────────────────────────── */
@media (min-width: 600px) {
  .stats { grid-template-columns: repeat(4, 1fr); }
  .logo-wall { grid-template-columns: repeat(3, 1fr); }
  .cards--3 { grid-template-columns: repeat(2, 1fr); }
  /* Each block of text gets its own fixed slot, so titles, locations,
     summaries and chips start at the same height on every card in a row.
     Only from here up: on a single column the spare space would be dead air.
     The title is top-aligned in its slot; the meta, summary and chips too. */
  .project__body { grid-template-rows: auto auto auto auto; align-content: start; padding-top: clamp(14px, 1.5vw, 20px); }
  .project__title { min-height: 3.2em; display: grid; align-items: center; padding: 0 0 12px; border-bottom: 1px solid var(--line-strong); }
  .project__meta { min-height: 3.2em; }
  .project__summary { min-height: calc(7 * 1lh); }
  .project .tags { min-height: 5.6rem; align-content: flex-start; margin-top: 0; padding-top: 14px; border-top: 1px solid var(--line-strong); }
  .socials { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .tiles { grid-template-columns: repeat(2, 1fr); }
  .work__grid { grid-template-columns: minmax(0, 1fr) 20rem; }
  /* Matches .work__grid's own flexible column exactly, so the title and
     lead paragraph above it share the same right edge as the body text
     and stop well short of the facts sidebar it sits beside below. */
  .work__head { max-width: calc(100% - 20rem - clamp(24px, 3vw, 48px)); }
  .social { grid-template-columns: auto 1fr; grid-template-areas: "icon go" "name name" "handle handle"; row-gap: 4px; }
  .social__icon { margin-bottom: 14px; }
  .social__go { justify-self: end; align-self: start; }
  .office-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 760px) {
  .cards--5 { grid-template-columns: repeat(3, 1fr); }
  .duo { grid-template-columns: repeat(2, 1fr); }
  .pillars { grid-template-columns: repeat(2, 1fr); }
  /* The date becomes a column. Fixed, not auto: a ragged left edge down the
     timeline is the one thing this layout cannot afford. */
  .timeline__step {
    grid-template-columns: 11rem minmax(0, 1fr);
    column-gap: clamp(24px, 3vw, 48px);
  }
  .site-footer__grid { grid-template-columns: repeat(2, 1fr); }
  .hero__cue { display: block; }
}

@media (max-width: 759px) {
  /* Stacked, the first pillar's rule lands just under .section__head's own and
     the two read as one doubled line. The head's rule is the top edge here —
     the same reason .timeline carries no border-top. */
  .pillar:first-child { border-top: 0; padding-top: 0; }

  /* Full-bleed 100svh made sense on a landscape screen; on a tall, narrow
     phone viewport it forced object-fit:cover to crop most of the video's
     width to fill that height, zooming in far tighter than the footage was
     shot for. Square gives cover a shape close to the source framing, so it
     crops top/bottom modestly instead of losing most of the sides. */
  .hero { aspect-ratio: 1 / 1; min-height: auto; }

  /* Stacked one-column-under-another, the four footer sections plus legal
     plus the marquee made for a very long scroll. Explore and Services are
     both just short link lists, so they pair up two-across instead of
     stacking — the biggest single cut, since it's the height of the taller
     of the two (5 items) rather than both added together (9). Brand and Get
     in touch stay full width: the brand column carries the logo/blurb/social
     row, and Get in touch carries the address block and CTA, neither of
     which suits a half-width column. */
  .site-footer__grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 32px 24px;
    padding-block: 40px 24px;
  }
  .site-footer__col--brand,
  .site-footer__grid > .site-footer__col:last-child { grid-column: 1 / -1; }
  /* Explore would sit alone in a half column once Services is gone. */
  .site-footer__grid--no-services > .site-footer__col:nth-child(2) { grid-column: 1 / -1; }

  /* Tighter internal spacing throughout — each of these was sized for a
     column with room to breathe next to three siblings; stacked/paired on
     mobile they just add up to extra scroll. */
  .site-footer__logo { margin-bottom: 16px; }
  .site-footer__socials { margin-top: 16px; }
  .site-footer__plasa { margin-bottom: 16px; }
  .site-footer__col .micro-label { margin-bottom: 12px; }
  .site-footer__address { margin-bottom: 16px; }

  /* The marquee's font floor (3rem/48px) was sized to still read as a bold
     statement band on a wide screen; on a 400px-ish viewport that's most of
     the available width per letter, so it's a big block of vertical space
     for very little of the phrase to show per frame. Drop the floor and the
     band's own padding so it reads as a closing flourish, not another
     section. */
  .marquee { padding-block: 14px; }
  .marquee__copy { font-size: clamp(2rem, 13vw, 9.375rem); }
}

@media (min-width: 1024px) {
  /* End-aligned rather than center: .explore__copy runs several paragraphs
     deeper than the carousel + Gallery link, so centering left "Gallery"
     stranded above "See what we do" instead of level with it. Bottom-
     aligning the columns lands both link-arrows on the same row. */
  .explore__grid { grid-template-columns: 1fr 1fr; align-items: end; }
  .timeline__step { grid-template-columns: 14rem minmax(0, 1fr); }
  .cards--3 { grid-template-columns: repeat(3, 1fr); }
  .project__summary { min-height: calc(9 * 1lh); }
  .tiles { grid-template-columns: repeat(3, 1fr); }
  /* Exactly four tiles: three columns would strand the fourth alone on a
     second row, so lay them out 2 × 2 and centre the block on the page. */
  .tiles:has(> li:nth-child(4):last-child) { grid-template-columns: repeat(2, 1fr); max-width: 56rem; margin-inline: auto; }
  .logo-wall { grid-template-columns: repeat(5, 1fr); }
  .site-footer__grid { grid-template-columns: 1.6fr 1fr 1fr 1.3fr; }
  .site-footer__grid--no-services { grid-template-columns: 1.6fr 1fr 1.3fr; }
  .hero__inner { padding-bottom: clamp(32px, 3.4vw, 48px); }
  .office-grid { grid-template-columns: repeat(3, 1fr); }
  .contact__grid { grid-template-columns: 1fr 1.15fr; }
  /* The list column is capped, not a fraction — it's short words, one per
     line, so it never needs more than this to read comfortably. Every
     extra pixel the row has goes to the map (1fr) instead of being split
     proportionally, which is what actually makes the map bigger as the
     section gets more room, rather than both growing together. */
  .global__grid { grid-template-columns: minmax(240px, 320px) 1fr; align-items: start; }
}

/* The horizontal nav needs room for its longest label without wrapping. With
   the current three items — About is drawer-only — it fits the 1024px shell;
   six measured ~1046px and needed 1200px. Restoring Clients and Insights, or
   putting About back in the bar, means checking this again. */
@media (min-width: 1024px) {
  .site-nav { display: block; }
  /* The burger and the CTA are both present at every width — the burger sits
     beside the nav rather than replacing it. */
}

@media (min-width: 1240px) {
  .explore__grid { grid-template-columns: 1fr 1.1fr; gap: 88px; }
  /* Five across only once each card can hold a readable measure. */
  .cards--5 { grid-template-columns: repeat(5, 1fr); }
  .global__grid { grid-template-columns: minmax(240px, 320px) 1fr; gap: 88px; }
}

/* ── Reduced motion ──────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  [data-reveal] { opacity: 1; transform: none; }
  /* Keep the glow, drop the lift — the colour change carries the affordance. */
  .hero__title .word:hover { transform: none; }
  /* The blanket animation kill above would freeze the sweep at whatever
     background-position it reached, leaving the word dimmed for as long as it
     is hovered. Drop the gradient and keep the glow — the same trade the rule
     above makes. The :hover selector is needed to outrank the hover rule. */
  .hero__title .word--shimmer,
  .hero__title .word--shimmer:hover {
    background-image: none;
    color: var(--mp-white);
    animation: none;
  }
  .hero__title .word--shimmer.word--accent,
  .hero__title .word--shimmer.word--accent:hover { color: var(--mp-orange); }
  .hero__video { opacity: 1; }
  .marquee__track { animation: none; }
  .hero__cue span { animation: none; opacity: 1; }
}
