/* ==========================================================================
   OM Consulting & Media
   Fourth pass. Pass 3's warm editorial direction holds (plum darks, blush
   paper, generous radii, Bodoni italic as the one accent voice) but the
   surface stops looking template-built:

   - Cards are mostly gone. Sections are ruled, not boxed. A hairline and
     real negative space does the job a border-plus-shadow was doing.
   - Shadow is rationed. It survives only where something genuinely floats
     (the hero portrait, the tags pinned over photography). Nothing else.
   - Hover moves ONE cheap property at a time. Shadows live on pseudo layers
     and cross-fade with opacity, so nothing repaints a blur on every frame.
   - No layout properties are ever transitioned. That was the choppiness.
   ========================================================================== */

:root {
  /* Brand */
  --magenta:      #B4009A;
  --magenta-deep: #8E0079;
  --magenta-lit:  #EE3AAC;
  --magenta-soft: #F7DCEF;
  --magenta-mist: #FBEDF6;

  /* Brand-owned dark. Plum, so the dark bands still read as OM. */
  --plum:      #16000F;
  --plum-2:    #250520;
  --plum-3:    #3A0B32;

  --ink:    #1A0E17;
  --ink-2:  #4B3D46;
  --ink-3:  #7A6C75;
  --ink-4:  #A4959E;

  /* Surface */
  --paper:   #FFFFFF;
  --blush:   #FBF4F8;
  --blush-2: #F6EAF1;
  --line:    #EDDFE7;
  --line-2:  #F4EAEF;

  /* Right / wrong. Used only in the "Why OM" comparison: a warm red for the
     usual way, a clean green for the OM way. */
  --good:      #1FB673;
  --good-lit:  #34D98A;
  --bad:       #E5484D;

  /* On plum */
  --on-dark:      rgba(255, 255, 255, 0.74);
  --on-dark-dim:  rgba(255, 255, 255, 0.5);
  --on-dark-line: rgba(255, 255, 255, 0.14);

  /* Type */
  --display: "Archivo", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --sans:    "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --accent:  "Bodoni Moda", Georgia, "Times New Roman", serif;

  /* Layout */
  --wrap: 1240px;
  --gutter: clamp(1.25rem, 5vw, 4rem);
  /* The hero pulls itself up under the sticky header by exactly this, so the
     two must not drift apart. */
  --header-h: 86px;

  --r-xs:   10px;
  --r:      18px;
  --r-lg:   28px;
  --r-xl:   38px;
  --r-pill: 999px;

  /* Depth. Rationed. Only things that genuinely float get one, and the tint
     is plum rather than neutral grey so it reads warm. */
  --lift-1: 0 2px 8px -4px rgba(22, 0, 15, 0.07);
  --lift-2: 0 10px 26px -22px rgba(22, 0, 15, 0.2);
  --lift-3: 0 22px 56px -44px rgba(90, 0, 76, 0.26);

  /* Motion.
     --t     colour, opacity, borders.
     --t-mv  transform.
     The two are deliberately close together now. They used to be 0.28s and
     0.5s on an expo-out curve, which front-loads almost all of its travel in
     the first fifth of the duration: the colour snapped, the movement kept
     going, and every hover read as a flick rather than a glide. Both are
     longer, the gap between them is smaller, and the curve eases in as well
     as out so nothing starts at full speed.

     --expo is the old curve, kept for the scroll reveal, where arriving fast
     and settling slowly is exactly what is wanted.

     Nothing else gets transitioned. Width, padding and box-shadow all force
     work on every frame, which is what made the old hovers stutter. */
  --ease: cubic-bezier(0.33, 0.62, 0.24, 1);
  --soft: cubic-bezier(0.4, 0, 0.2, 1);
  --expo: cubic-bezier(0.22, 1, 0.36, 1);
  --t:    0.42s;
  --t-mv: 0.52s;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 96px;
}

body {
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--ink-2);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, picture, svg { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }

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

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ==========================================================================
   Typography
   ========================================================================== */
h1, h2, h3, h4 {
  font-family: var(--display);
  color: var(--ink);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.03em;
}

h2 { font-size: clamp(2.1rem, 4.6vw, 3.5rem); }
h3 {
  font-size: clamp(1.3rem, 1.9vw, 1.6rem);
  line-height: 1.2;
  letter-spacing: -0.022em;
  font-weight: 600;
}

p { text-wrap: pretty; }

.lede {
  font-size: clamp(1.08rem, 1.35vw, 1.22rem);
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 36rem;
}
.lede--wide { max-width: 44rem; }

/* Accent words inside a heading. Kept in the display sans at heading weight so
   they read cleanly and only the magenta colour marks them out — the italic
   serif version was hard to read at a glance. */
.accent {
  font-family: var(--display);
  font-style: normal;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--magenta);
}
.section--dark .accent { color: var(--magenta-lit); }

/* Eyebrow. Now a soft pill rather than bare tracked caps. */
.label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--magenta);
  background: var(--magenta-mist);
  border-radius: var(--r-pill);
  padding: 0.42rem 0.9rem;
}
.label::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: currentColor;
}
.label--ink  { color: var(--ink-3); background: var(--blush-2); }
.label--dark { color: var(--magenta-lit); background: rgba(238, 58, 172, 0.14); }

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

section { position: relative; }

.section { padding-block: clamp(4rem, 7.5vw, 7rem); }
.section--blush { background: var(--blush); }

/* Dark band. Plum with a faint magenta lift in one corner so it is not a
   flat rectangle of black. */
.section--dark {
  background: var(--plum);
  color: var(--on-dark);
  background-image:
    radial-gradient(120% 90% at 100% 0%, rgba(180, 0, 154, 0.30) 0%, rgba(180, 0, 154, 0) 55%),
    radial-gradient(90% 70% at 0% 100%, rgba(238, 58, 172, 0.12) 0%, rgba(238, 58, 172, 0) 60%);
}
.section--dark h2, .section--dark h3, .section--dark h4 { color: #fff; }
/* The lede's default ink is invisible on plum. Declared here so no page has to
   carry an inline colour to fix it. */
.section--dark .lede, .page-hero .lede { color: var(--on-dark); }

/* Photo-backed band. A dark section whose backdrop is a real photograph from
   the work rather than another rectangle of brand colour. The image is
   pushed well under a plum wash so type stays at full contrast and the shot
   reads as texture, not as a slideshow you have to look at. */
.section--photo { background-color: var(--plum); overflow: hidden; }
.section--photo > .wrap { position: relative; z-index: 2; }
.section--photo::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--photo);
  background-size: cover;
  background-position: var(--photo-pos, center);
  opacity: 0.3;
  filter: grayscale(0.55) contrast(1.05);
}
.section--photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(200deg, rgba(22, 0, 15, 0.72) 0%, rgba(22, 0, 15, 0.93) 62%),
    radial-gradient(100% 90% at 100% 0%, rgba(180, 0, 154, 0.42) 0%, rgba(180, 0, 154, 0) 58%);
}
/* On a phone the backdrop is cover-cropped to a tall band, so it zooms into
   whatever the middle of the frame happens to be: signage, price tickets, a
   projected slide. Dropped further here so it reads as texture rather than as
   a photograph competing with the copy on top of it. */
@media (max-width: 700px) {
  .section--photo::before { opacity: 0.17; }
}

/* Rounded band. Lets a coloured section sit in the page like a slab instead
   of a hard edge-to-edge box. */
.band-round { border-radius: var(--r-xl); margin-inline: clamp(0px, 2vw, 1.5rem); }

.section-head { margin-bottom: clamp(2.25rem, 4vw, 3.5rem); }
.section-head h2 { max-width: 20ch; }
.section-head .label + h2 { margin-top: 1.1rem; }
.section-head .lede { margin-top: 1.3rem; }

.section-head--split {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: clamp(1.75rem, 4vw, 4rem);
  align-items: end;
}
.section-head--split .lede { margin-top: 0; max-width: 30rem; }

/* ---------- Buttons ----------
   The fill is a pseudo-element that wipes up from the bottom, not a
   background-color swap, so the colour change reads as a deliberate move
   rather than a flicker. Labels are wrapped in .btn__label so they sit above
   that layer without needing negative z-index tricks. */
.btn {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 1.02rem 1.5rem 1.02rem 1.75rem;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-family: var(--display);
  font-size: 0.84rem;
  font-weight: 600;
  letter-spacing: 0.045em;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  transition: color var(--t) var(--soft), border-color var(--t) var(--soft),
              background-color var(--t) var(--soft);
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  transform: translateY(100%);
  transition: transform var(--t-mv) var(--ease);
}
.btn:hover::before, .btn:focus-visible::before { transform: translateY(0); }
.btn__label { position: relative; }

/* The arrow rides in its own disc. On hover the disc inverts and the arrow
   travels, which is the whole reason the padding is asymmetric. */
.btn__arrow {
  position: relative;
  display: grid;
  place-items: center;
  width: 26px; height: 26px;
  margin-right: -0.35rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  transition: background-color var(--t) var(--soft);
}
.btn__arrow svg { transition: transform var(--t-mv) var(--ease); }
.btn:hover .btn__arrow svg { transform: translateX(3px); }
.btn svg { flex-shrink: 0; }
.btn:active { transform: translateY(1px); }

/* Primary: magenta, inverting to white with a magenta hairline. */
.btn--primary { background: var(--magenta); color: #fff; }
.btn--primary::before { background: #fff; }
.btn--primary:hover, .btn--primary:focus-visible {
  color: var(--magenta);
  border-color: var(--magenta);
}
.btn--primary:hover .btn__arrow { background: var(--magenta); color: #fff; }

.btn--ghost { border-color: var(--line); color: var(--ink); background: #fff; }
.btn--ghost::before { background: var(--ink); }
.btn--ghost:hover, .btn--ghost:focus-visible { color: #fff; border-color: var(--ink); }
.btn--ghost .btn__arrow { background: var(--blush-2); }
.btn--ghost:hover .btn__arrow { background: rgba(255, 255, 255, 0.18); }

/* On plum: white, inverting to magenta. */
.btn--light { background: #fff; color: var(--plum); }
.btn--light::before { background: var(--magenta); }
.btn--light:hover, .btn--light:focus-visible { color: #fff; }
.btn--light .btn__arrow { background: var(--magenta-mist); }
.btn--light:hover .btn__arrow { background: rgba(255, 255, 255, 0.22); }

.btn--outline-light { border-color: var(--on-dark-line); color: #fff; }
.btn--outline-light::before { background: rgba(255, 255, 255, 0.1); }
.btn--outline-light:hover { border-color: rgba(255, 255, 255, 0.5); }

.btn--sm { padding: 0.72rem 1rem 0.72rem 1.3rem; font-size: 0.76rem; }
.btn--sm .btn__arrow { width: 22px; height: 22px; }
.btn--lg { padding: 1.15rem 1.65rem 1.15rem 1.95rem; font-size: 0.9rem; }
.btn-row { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem; }

/* Text link with a rule that wipes in */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  color: var(--magenta);
  padding-bottom: 0.3rem;
  position: relative;
}
.link-arrow::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t) var(--ease);
}
.link-arrow:hover::after { transform: scaleX(1); }
.link-arrow svg { transition: transform var(--t) var(--ease); }
.link-arrow:hover svg { transform: translateX(4px); }

/* ---------- Media wrapper ----------
   Anything photographic goes in one of these so the corners, the crop and
   the slow hover push are consistent everywhere. */
.media {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--blush-2);
}
.media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 1.1s var(--soft);
}
.media:hover img { transform: scale(1.045); }

/* Stars. One shape, reused by the review band and the hero chip. */
.stars { display: inline-flex; gap: 0.15rem; color: var(--magenta); }
.stars svg { width: 15px; height: 15px; flex-shrink: 0; fill: currentColor; }
.stars--lit { color: var(--magenta-lit); }

/* ==========================================================================
   Header
   ========================================================================== */
.header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: saturate(170%) blur(16px);
  -webkit-backdrop-filter: saturate(170%) blur(16px);
  border-bottom: none;
  transition: border-color var(--t) var(--soft), box-shadow var(--t) var(--soft),
              background-color var(--t) var(--soft);
}
.header.is-stuck {
  border-bottom: 1px solid var(--line-2);
  box-shadow: 0 10px 30px -24px rgba(22, 0, 15, 0.5);
}

/* On a page that opens with a dark media hero the bar sits on the photograph
   rather than above it: no fill, inverted logo, white links. As soon as it
   sticks it becomes the normal light bar again. */
.header--over:not(.is-stuck) {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
/* Over the dark hero the logo swaps to a variant where only the black script
   and "& MEDIA" are knocked out to white, while the pink OM mark stays pink.
   Once the header sticks and becomes the light bar, the normal dark logo
   returns. Both images are stacked so the swap is instant with no reflow. */
.header--over:not(.is-stuck) .brand__logo--dark { opacity: 0; }
.header--over:not(.is-stuck) .brand__logo--light { opacity: 1; }
.header--over:not(.is-stuck) .nav a { color: rgba(255, 255, 255, 0.95); }
.header--over:not(.is-stuck) .nav a:hover { color: #fff; }
.header--over:not(.is-stuck) .nav a::after { background: var(--magenta-lit); }
/* The CTA keeps its magenta fill over the hero video. An outlined version
   disappeared into the footage, and it is the one thing on the bar that has to
   read as a button from across the room. */
.header--over:not(.is-stuck) .header__actions .btn--primary {
  background: var(--magenta);
  color: #fff;
  border-color: var(--magenta);
  box-shadow: 0 14px 30px -18px rgba(22, 0, 15, 0.9);
}
.header--over:not(.is-stuck) .header__actions .btn--primary::before { background: #fff; }
.header--over:not(.is-stuck) .header__phone { color: #fff; }
.header--over:not(.is-stuck) .header__phone svg { color: var(--magenta-lit); }
.header--over:not(.is-stuck) .header__phone:hover {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
}
/* Over the hero the toggle is a softer, more transparent pill. */
.header--over:not(.is-stuck) .burger {
  background: rgba(22, 0, 15, 0.32);
  border-color: rgba(255, 255, 255, 0.22);
}

/* Three tracks, with the nav in the middle one. `space-between` used to push
   the links left of centre because the right-hand group is wider than the
   logo; equal outer tracks fix that properly at any width. */
.header__inner {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1.5rem;
  height: var(--header-h);
}
.header__actions { justify-self: end; }

.brand { display: grid; align-items: center; flex-shrink: 0; }
/* Both logo variants occupy the same grid cell; only opacity changes. */
.brand__logo {
  grid-area: 1 / 1;
  height: 54px; width: auto;
  transition: transform var(--t) var(--ease), opacity var(--t) var(--soft);
}
.brand__logo--light { opacity: 0; }
.brand:hover .brand__logo { transform: scale(1.03); }

.nav { display: flex; align-items: center; gap: 2rem; }
.nav a {
  font-family: var(--display);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--ink);
  position: relative;
  padding-block: 0.4rem;
  transition: color var(--t) var(--soft);
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 2px;
  border-radius: 2px;
  background: var(--magenta);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t) var(--ease);
}
.nav a:hover { color: var(--magenta); }
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }
.nav a[aria-current="page"] { color: var(--ink); }

.header__actions { display: flex; align-items: center; gap: 0.9rem; }
.header__phone {
  font-family: var(--display);
  font-size: 0.86rem;
  font-weight: 600;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.9rem;
  border-radius: var(--r-pill);
  transition: color var(--t) var(--soft), background-color var(--t) var(--soft);
}
.header__phone:hover { color: var(--magenta); background: var(--magenta-mist); }
.header__phone svg { color: var(--magenta); }

/* Mobile toggle */
.burger {
  display: none;
  width: 46px; height: 46px;
  align-items: center;
  justify-content: center;
  background: rgba(22, 0, 15, 0.36);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--r-pill);
  cursor: pointer;
  box-shadow: 0 6px 18px -12px rgba(22, 0, 15, 0.5);
  transition: background-color var(--t) var(--soft), border-color var(--t) var(--soft),
              box-shadow var(--t) var(--soft);
}
.burger:hover { background: var(--magenta); border-color: var(--magenta); }
.burger span {
  display: block;
  position: relative;
  width: 18px; height: 2px;
  border-radius: 2px;
  background: #fff;
  transition: background var(--t) var(--soft);
}
.burger span::before, .burger span::after {
  content: "";
  position: absolute; left: 0;
  width: 18px; height: 2px;
  border-radius: 2px;
  background: #fff;
  transition: transform var(--t) var(--ease);
}
.burger span::before { top: -6px; }
.burger span::after  { top: 6px; }
.burger[aria-expanded="true"] span { background: transparent; }
.burger[aria-expanded="true"] span::before { transform: translateY(6px) rotate(45deg); }
.burger[aria-expanded="true"] span::after  { transform: translateY(-6px) rotate(-45deg); }

/* ---------- Mobile menu overlay ----------
   A full-screen overlay that sits at the top level, above the header, rather
   than an accordion pushing the page down. A scrim fades in; a panel slides in
   from the right. It is display:none by default (via [hidden]) and switched on
   with .is-open, so nothing on the panel is focusable until it opens. */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 90;
}
.mobile-menu[hidden] { display: none; }

.mobile-menu__scrim {
  position: absolute;
  inset: 0;
  background: rgba(16, 6, 14, 0.55);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity var(--t) var(--soft);
}
.mobile-menu.is-open .mobile-menu__scrim { opacity: 1; }

.mobile-menu__panel {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: min(20rem, 84vw);
  display: flex;
  flex-direction: column;
  padding: 1.15rem 1.5rem 2rem;
  color: var(--ink-2);
  background:
    radial-gradient(ellipse at 0% 65%, rgba(224, 60, 168, 0.12) 0%, rgba(224, 60, 168, 0) 58%),
    radial-gradient(ellipse at 100% 0%, rgba(110, 145, 220, 0.09) 0%, rgba(110, 145, 220, 0) 58%),
    #fdfbfc;
  box-shadow: -30px 0 80px -20px rgba(22, 0, 15, 0.18);
  transform: translateX(100%);
  transition: transform var(--t-mv) var(--ease);
  overflow-y: auto;
}
.mobile-menu.is-open .mobile-menu__panel { transform: none; }
@media (prefers-reduced-motion: reduce) {
  .mobile-menu__panel { transition: none; }
}

.mobile-menu__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.5rem;
  padding-bottom: 1.15rem;
  border-bottom: 1px solid var(--line);
}
/* The dark artwork dies on plum, so the drawer runs the knocked-out variant
   the header already uses over the hero. Both are in the markup, stacked. */
.mobile-menu__logo { height: 44px; width: auto; }
.mobile-menu__close {
  flex-shrink: 0;
  width: 42px; height: 42px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--blush-2);
  color: var(--ink-2);
  cursor: pointer;
  transition: border-color var(--t) var(--soft), color var(--t) var(--soft),
              background-color var(--t) var(--soft);
}
.mobile-menu__close:hover { border-color: var(--magenta); color: #fff; background: var(--magenta); }

.mobile-menu__links { display: flex; flex-direction: column; }
/* Each row carries its own number in the display face, the way the "start
   here" options do, and a chevron on the right so the list reads as navigation
   rather than five words on rules. */
.mobile-menu__links a {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 1.05rem 0;
  font-family: var(--display);
  font-size: 1.15rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
  border-bottom: 1px solid var(--line);
  /* Colour only. The old hover indented the row with padding-left, which
     relaid out the whole drawer on every frame; translating the row instead
     would have dragged its rule off the left edge with it, so the movement
     lives on the chevron below. */
  transition: color var(--t) var(--soft);
  counter-increment: navitem;
}
.mobile-menu__links { counter-reset: navitem; }
.mobile-menu__links a::before {
  content: "0" counter(navitem);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--magenta);
  opacity: 0.75;
}
.mobile-menu__links a::after {
  content: "";
  margin-left: auto;
  width: 7px; height: 7px;
  border-right: 1.6px solid currentColor;
  border-top: 1.6px solid currentColor;
  transform: rotate(45deg);
  opacity: 0.45;
  transition: transform var(--t) var(--ease), opacity var(--t) var(--soft);
}
.mobile-menu__links a:hover,
.mobile-menu__links a[aria-current="page"] { color: var(--magenta); }
.mobile-menu__links a[aria-current="page"]::before { opacity: 1; }
.mobile-menu__links a:hover::after,
.mobile-menu__links a:active::after {
  transform: translateX(3px) rotate(45deg);
  opacity: 0.95;
}

/* The number is a centred line over the CTA rather than a left-aligned
   afterthought, so the foot of the drawer reads as one block. */
.mobile-menu__foot {
  margin-top: auto;
  padding-top: 1.75rem;
  text-align: center;
}
.mobile-menu__phone {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  margin-bottom: 1.1rem;
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
}
.mobile-menu__phone svg { color: var(--magenta); }
.mobile-menu__foot .btn { width: 100%; }

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background: var(--plum);
  color: #fff;
  /* Pulled up under the sticky header so the photo runs edge to edge behind
     it, then padded back out so the copy still clears it. */
  margin-top: calc(-1 * var(--header-h));
  padding-top: var(--header-h);
  min-height: min(92vh, 900px);
  display: flex;
}

/* ---------- Layer 1: the photograph ---------- */
/* overflow, because the image is scaled up for the drift and would otherwise
   bleed past this box, outside the scrim, wherever the box is not the hero.
   scaleX(-1) mirrors the photo so the group faces inward toward the headline. */
.hero__media { position: absolute; inset: 0; z-index: 0; overflow: hidden; transform: scaleX(-1); }
.hero__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* A fixed zoom crops the top of the frame so Amanda (far right after the
     mirror) sits more centred in the section, while the section keeps its
     height. No drift animation — the photograph is still. */
  object-position: 64% 46%;
  transform: scale(1.14);
  /* Graded rather than left raw: desaturated a touch and pushed down so the
     plum and magenta layers above have something to sit into. */
  filter: grayscale(0.14) contrast(1.05) saturate(1) brightness(1.12);
}

/* Video variant. The clip is already flipped in the source (Amanda reads
   right, in the lighter zone; the client sits left under the scrim), so it is
   NOT mirrored here. Graded down a touch so the busy retail behind them sits
   back into the brand plum rather than competing. */
.hero__media--video { transform: none; }
.hero__video {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 54% 38%;
  filter: grayscale(0.26) contrast(1.05) saturate(0.92) brightness(0.94);
}

/* ---------- Layer 2: grading and legibility ---------- */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    /* under the sticky header */
    linear-gradient(180deg, rgba(22, 0, 15, 0.45) 0%, rgba(22, 0, 15, 0) 20%),
    /* a plum veil pulled over the centre */
    radial-gradient(46% 62% at 41% 24%, rgba(22, 0, 15, 0.38) 0%, rgba(22, 0, 15, 0.12) 46%, rgba(22, 0, 15, 0) 72%),
    /* carries the left column */
    linear-gradient(97deg,
      rgba(22, 0, 15, 0.62) 0%,
      rgba(22, 0, 15, 0.52) 32%,
      rgba(22, 0, 15, 0.26) 58%,
      rgba(22, 0, 15, 0.06) 80%,
      rgba(22, 0, 15, 0.10) 100%),
    /* lands the bottom edge on solid plum so the ticker joins on cleanly */
    linear-gradient(0deg, var(--plum) 0%, rgba(22, 0, 15, 0.7) 12%, rgba(22, 0, 15, 0) 46%);
}

/* ---------- Layer 3: the shapes. All decorative, all low opacity. ---------- */
.hero__shapes { position: absolute; inset: 0; z-index: 2; overflow: hidden; }
.hero__shapes > span { position: absolute; display: block; }

/* A magenta wash raked across the frame. This is what stops the photo
   reading as a grey stock shot and makes it feel brand-owned. */
.hero__wash {
  inset: 0;
  background:
    /* the raked band, now carried further across the frame */
    linear-gradient(115deg, rgba(180, 0, 154, 0.35) 0%, rgba(180, 0, 154, 0.18) 40%, rgba(180, 0, 154, 0.06) 60%, rgba(180, 0, 154, 0) 76%),
    /* a bloom pulled in from the top-left over the middle, sat over the tall
       figure so he reads back into the brand colour rather than competing */
    radial-gradient(68% 66% at 42% 8%, rgba(238, 58, 172, 0.18) 0%, rgba(238, 58, 172, 0) 60%);
  mix-blend-mode: screen;
  opacity: 0.22;
}

.hero__rules { display: none; }
.hero__ring  { display: none; }

@media (max-width: 620px) {
  .hero__glow { opacity: 0.3; }
  .hero__wash { opacity: 0.10; }
}

/* Soft magenta bloom low-left, sitting behind the CTA row. */
.hero__glow {
  width: min(760px, 70vw);
  aspect-ratio: 1;
  left: -18%;
  bottom: -34%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(238, 58, 172, 0.16) 0%, rgba(238, 58, 172, 0) 66%);
}

/* ---------- Layer 4: grain ---------- */
.hero__grain {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  opacity: 0.32;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.35'/%3E%3C/svg%3E");
}

/* ---------- The content ---------- */
.hero__inner {
  position: relative;
  z-index: 4;
  align-self: stretch;
  /* As the flex child of .hero, allow it to shrink to the viewport instead of
     being floored at its content width (which overflows on narrow phones). */
  min-width: 0;
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 0.56fr) minmax(0, 0.44fr);
  grid-template-areas: "copy card";
  align-content: stretch;
  align-items: center;
  gap: clamp(1.5rem, 3vw, 2.25rem);
  padding-block: clamp(3.5rem, 6vw, 5rem) clamp(2.5rem, 4vw, 3.5rem);
}
.hero__copy { grid-area: copy; max-width: 40rem; }

/* One quiet line above the lockup, not a row of competing pills. The old
   hero stacked a location pill, a rating chip, an award tag and a second
   rating chip around a headline, and the CTA lost every time. */
.hero__meta {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-bottom: clamp(1.5rem, 2.4vw, 2.1rem);
  font-family: var(--display);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.88);
}
.hero__meta::before {
  content: "";
  width: 34px; height: 1px;
  background: var(--magenta-lit);
  flex-shrink: 0;
}

/* ---------- The lockup ---------- */
.lockup {
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  line-height: 0.9;
  letter-spacing: -0.04em;
  color: #fff;
  font-size: clamp(2.8rem, 7vw, 6.1rem);
  text-shadow: 0 2px 30px rgba(22, 0, 15, 0.35);
}
.lockup__line { display: block; position: relative; width: fit-content; }

.lockup__strike {
  color: #fff;
  font-weight: 600;
  font-size: 0.42em;
  letter-spacing: -0.02em;
  margin-bottom: 0.3em;
}

.lockup__hit { color: var(--magenta-lit); }

.hero__lede {
  margin-top: clamp(1.4rem, 2.4vw, 1.95rem);
  max-width: 33rem;
  color: rgba(255, 255, 255, 0.94);
}
.hero__lede .accent { color: var(--magenta-lit); }
.hero .btn-row { margin-top: clamp(1.85rem, 3vw, 2.4rem); }

.link-arrow--light { color: #fff; }
.link-arrow--light:hover { color: var(--magenta-lit); }

/* ---------- The floating card ----------
   Glass rather than a white panel, so the photograph still reads through it.
   This is the only element allowed to sit on top of the people. */
.hero__card {
  grid-area: card;
  align-self: end;
  justify-self: end;
  width: min(21rem, 100%);
  padding: 1rem 1.15rem;
  border-radius: var(--r-lg);
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(22, 0, 15, 0.34);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  box-shadow: 0 30px 70px -50px rgba(0, 0, 0, 0.9);
  transition: transform var(--t-mv) var(--ease), border-color var(--t) var(--soft);
}
.hero__card:hover {
  transform: translateY(-4px);
  border-color: rgba(238, 58, 172, 0.45);
}
.hero__card-head { display: flex; align-items: center; gap: 0.85rem; }
/* Let the text column shrink so the credential line wraps inside the card
   instead of running off the edge. */
.hero__card-head > div { min-width: 0; }
.hero__card-head img {
  width: 54px; height: 54px;
  flex-shrink: 0;
  border-radius: 50%;
  object-fit: cover;
  object-position: center 14%;
  border: 1px solid rgba(255, 255, 255, 0.28);
}
.hero__card-head strong {
  display: block;
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: #fff;
}
.hero__card-head span {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.76rem;
  line-height: 1.35;
  color: var(--on-dark-dim);
}
/* The one credential, sat under the name as a compact line rather than a
   separate ruled block, so the card stays short. */
.hero__card-head span.hero__card-cred {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.35rem;
  font-family: var(--display);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: rgba(255, 255, 255, 0.85);
  line-height: 1.3;
  white-space: nowrap;
}
.hero__card-head span.hero__card-cred svg { flex-shrink: 0; color: var(--magenta-lit); }
.hero__card-award {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  margin: 1rem 0 0;
  padding-top: 0.95rem;
  border-top: 1px solid var(--on-dark-line);
  font-size: 0.7rem;
  line-height: 1.4;
  color: var(--on-dark-dim);
}
.hero__card-award svg { flex-shrink: 0; color: var(--magenta-lit); margin-top: 1px; }
.hero__card-award strong {
  display: block;
  font-family: var(--display);
  font-size: 0.78rem;
  font-weight: 600;
  color: #fff;
  margin-bottom: 0.15rem;
}

/* ---------- Proof rail ----------
   Same four facts, set as a ruled row on the photograph: figures on a
   hairline, nothing boxed. */
.hero__proof {
  grid-area: proof;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1.25rem, 3vw, 2.75rem);
  margin-top: clamp(1rem, 3vw, 2.25rem);
  padding-top: clamp(1.5rem, 2.6vw, 2.1rem);
  border-top: 1px solid var(--on-dark-line);
}
.hero__proof > div { position: relative; }
.hero__proof > div + div { padding-left: clamp(1.25rem, 3vw, 2.75rem); }
.hero__proof > div + div::before {
  content: "";
  position: absolute;
  left: 0; top: 0.2rem; bottom: 0.2rem;
  width: 1px;
  background: var(--on-dark-line);
}
.hero__proof dt {
  font-family: var(--display);
  font-size: clamp(1.35rem, 2vw, 1.8rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  color: #fff;
  line-height: 1;
}
.hero__proof dd {
  font-size: 0.82rem;
  color: var(--on-dark-dim);
  margin: 0.65rem 0 0;
  line-height: 1.45;
  max-width: 15rem;
}

/* ---------- Hero responsive ---------- */
@media (max-width: 1040px) {
  .hero__inner {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "copy" "card";
    align-items: start;
  }
  .hero__card { width: min(24rem, 100%); }
}
@media (max-width: 720px) {
  .hero { min-height: 86vh; }

  /* Full-bleed on phones: the frame is zoomed hard onto Amanda so she rises
     out of the space to the right of the copy, and a plum-to-transparent
     wash raked in from the top-left carries the type while sinking the rest
     of the group back into the brand colour. */
  .hero__media,
  .hero__scrim { inset: 0; height: auto; }
  .hero__media img {
    /* Anchored to the bottom edge so the group is always shown in full and
       any excess only crops off the empty ceiling at the top. */
    object-position: 24% 100%;
    transform: scale(1.32);
    /* Scale from the bottom edge so zooming only crops the empty ceiling at
       the top and the group is always shown in full from the bottom up. */
    transform-origin: center bottom;
    /* Lifted a touch on phones so Amanda reads clearly through the grade. */
    filter: grayscale(0.06) contrast(1.02) saturate(1.05) brightness(1.3);
  }
  /* The landscape clip sits as a top band rather than covering the full tall
     hero. Cover then scales against this shorter height, so it zooms far less
     and shows more of the scene; the plum below carries the copy and hides the
     band's lower edge. */
  .hero__media--video { inset: 0 0 auto 0; height: 56vh; }
  .hero__video {
    object-position: 52% 30%;
    filter: grayscale(0.05) contrast(1.02) saturate(1.06) brightness(1.16);
  }
  .hero__scrim {
    background:
      /* A stronger, darker plum-into-magenta rake in from the left edge, and
         cleared by a third of the way across. It carries the meta line and the
         lockup instead of the flat pink veil that used to sit over the whole
         frame and just made the footage look washed. */
      linear-gradient(90deg,
        rgba(22, 0, 15, 0.90) 0%,
        rgba(22, 0, 15, 0.60) 22%,
        rgba(22, 0, 15, 0) 50%),
      /* The clip is cut off at 56vh inside an 86vh hero, so the fade has to be
         fully solid before 65% or the straight edge shows. Extra stops through
         the middle so it ramps rather than steps. */
      linear-gradient(180deg,
        rgba(22, 0, 15, 0) 22%,
        rgba(22, 0, 15, 0.18) 34%,
        rgba(22, 0, 15, 0.42) 43%,
        rgba(22, 0, 15, 0.66) 50%,
        rgba(22, 0, 15, 0.85) 56%,
        rgba(22, 0, 15, 0.96) 61%,
        var(--plum) 66%);
  }
  /* The full-frame magenta veil goes on phones. It sat over the whole clip as
     a flat pink haze; the raked edge in the scrim above does the brand colour
     now, from the left, where the type is. */
  .hero__wash { opacity: 0; }
  /* Belt and braces on the clip's own bottom edge: the band fades itself out
     before the scrim has to hide it, so there is no hard line to catch even
     mid-transition. */
  .hero__media--video {
    -webkit-mask-image: linear-gradient(180deg, #000 62%, rgba(0, 0, 0, 0) 99%);
            mask-image: linear-gradient(180deg, #000 62%, rgba(0, 0, 0, 0) 99%);
  }
  /* Both lines of type over the footage go near-white. Dimmed grey read as
     unfinished against a busy frame. */
  .hero__meta { color: rgba(255, 255, 255, 0.94); }
  .hero__lede { color: #fff; }
  /* Smaller subtext, capped at two lines. */
  .hero__lede {
    font-size: 0.92rem;
    line-height: 1.42;
    margin-top: 1rem;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .hero__inner {
    padding-top: calc(var(--header-h) + 2.25rem);
    padding-bottom: 2.75rem;
    align-content: end;
    align-items: end;
  }

  /* The meta line wraps to two at this width, so the rule hangs off the
     first line rather than floating between them. */
  .hero__meta { align-items: flex-start; }
  .hero__meta::before { width: 24px; margin-top: 0.52rem; }
  /* `.hero__shapes > span` sets these to block, so match that specificity. */
  .hero__shapes > .hero__rules,
  .hero__shapes > .hero__ring--sm { display: none; }
  .hero__proof {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.4rem 1.25rem;
  }
  .hero__proof > div + div { padding-left: 0; }
  .hero__proof > div + div::before { display: none; }
  .hero__proof > div:nth-child(n + 3) {
    padding-top: 1.4rem;
    border-top: 1px solid var(--on-dark-line);
  }
}

/* ==========================================================================
   Ticker
   A slow marquee of the sectors. Gives the page movement without another grid.
   ========================================================================== */
.ticker {
  background:
    radial-gradient(ellipse at 0% 55%, rgba(224, 60, 168, 0.16) 0%, rgba(224, 60, 168, 0) 52%),
    radial-gradient(ellipse at 100% 0%, rgba(110, 145, 220, 0.11) 0%, rgba(110, 145, 220, 0) 52%),
    #fdfbfc;
  color: var(--ink);
  padding-block: 1.05rem;
  overflow: hidden;
  box-shadow: 0 1px 0 rgba(22, 0, 15, 0.08), 0 3px 10px rgba(22, 0, 15, 0.05);
}
.ticker__track {
  display: flex;
  width: max-content;
  animation: ticker 42s linear infinite;
}
.ticker:hover .ticker__track { animation-play-state: paused; }
.ticker__group {
  display: flex;
  align-items: center;
  gap: 2.75rem;
  padding-right: 2.75rem;
  list-style: none;
  margin: 0;
}
.ticker__group li {
  display: flex;
  align-items: center;
  gap: 2.75rem;
  font-family: var(--display);
  font-size: 0.98rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
}
.ticker__group li::after {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--magenta-lit);
}
@keyframes ticker { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .ticker__track { animation: none; }
}

/* ==========================================================================
   Partner band
   ========================================================================== */
/* ==========================================================================
   Partner band
   Real logos rather than names in pills. The four marks fight badly in their
   own colours (Seven red, Chamber purple, Women on the Move hot pink), so
   they sit desaturated by default and come up in full colour on hover. That
   is the only way a strip of unrelated brands reads as one row.
   ========================================================================== */
/* The band now runs on the plum, matching the reviews band, so the page
   alternates light and dark the whole way down. That means the four marks
   cannot sit in their own colours: they are dark artwork and would vanish.
   They are knocked out to white instead, which as a side effect finally makes
   Seven red, Chamber purple and Women on the Move pink read as one row. */
.partners {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(2.25rem, 3.8vw, 3.25rem);
  background: var(--plum);
}
.partners__bg { position: absolute; inset: 0; z-index: -1; }
/* The wash. Same raked angle as the hero so the two feel cut from one thing. */
.partners__wash {
  position: absolute;
  inset: -40% -10%;
  background:
    radial-gradient(44% 130% at 4% 55%, rgba(180, 0, 154, 0.42) 0%, rgba(180, 0, 154, 0) 72%),
    radial-gradient(40% 120% at 97% 35%, rgba(238, 58, 172, 0.24) 0%, rgba(238, 58, 172, 0) 74%);
}
/* Hairline verticals on the brand grid, faded out top and bottom. */
.partners__rules {
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(
    90deg,
    rgba(255, 255, 255, 0.08) 0 1px,
    transparent 1px calc(100% / 6)
  );
  background-size: 100% 100%;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 30%, #000 70%, transparent);
          mask-image: linear-gradient(180deg, transparent, #000 30%, #000 70%, transparent);
}
.partners__inner {
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 4rem);
  flex-wrap: wrap;
}
.partners__label {
  font-family: var(--display);
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--magenta-lit);
  flex-shrink: 0;
  max-width: 7rem;
  line-height: 1.5;
}
.partners__list {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
}
/* Each mark sits on its own white chip rather than being knocked out to a flat
   white silhouette. That lets the logos keep their real colours (Seven red,
   Ripple's brushstroke, the Chamber magenta, Women on the Move's badge) and
   still read as one clean row on the plum. The chip looks finished at rest and
   only lifts, brightens and grows a touch on hover. */
.partners__list li {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.9rem 1.35rem;
  border-radius: var(--r);
  background: rgba(255, 255, 255, 0.94);
  border: 1px solid rgba(255, 255, 255, 0.6);
  box-shadow: 0 14px 34px -24px rgba(0, 0, 0, 0.75);
  transition: transform var(--t-mv) var(--ease),
              background-color var(--t) var(--soft);
}
/* The deeper shadow the lift needs rides on its own layer and cross-fades on
   opacity, so hovering four chips at once never asks for four blur repaints.
   The layer sits over the chip but only ever paints its outer shadow, so it
   cannot cover the logo underneath and needs no z-index games. */
.partners__list li::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: 0 26px 50px -22px rgba(0, 0, 0, 0.55);
  opacity: 0;
  transition: opacity var(--t) var(--soft);
}
.partners__list li:hover {
  background: #fff;
  transform: translateY(-5px) scale(1.05);
}
.partners__list li:hover::after { opacity: 1; }
.partners__list img {
  height: clamp(34px, 3.7vw, 46px);
  width: auto;
  transition: transform var(--t-mv) var(--ease), filter var(--t) var(--soft);
}
.partners__list li:hover img { transform: scale(1.06); filter: saturate(1.12) brightness(1.05); }
/* Stacked and circular lockups carry their name inside the mark, so they need
   more height than the wide ones to stay legible at the same optical weight. */
.partners__list img[data-tall] { height: clamp(44px, 4.6vw, 58px); }

/* ==========================================================================
   Proof
   The homepage band that replaced the invented Google reviews. Four checkable
   facts on a blush ground, ruled rather than boxed, so it reads as a record
   rather than as four more marketing tiles. The .grev review card below is
   untouched and ready for the day real testimonials arrive.
   ========================================================================== */
.proof { background: var(--blush); }
.proof__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0 clamp(1.5rem, 3vw, 2.75rem);
}
.proof__item {
  position: relative;
  padding: clamp(1.4rem, 2.4vw, 1.9rem) 0 clamp(1.5rem, 2.6vw, 2rem);
  border-top: 1px solid var(--line);
}
/* Same wipe the capability cells use, so the two grids behave identically. */
.proof__item::after {
  content: "";
  position: absolute;
  top: -1px; left: 0;
  width: 100%; height: 2px;
  background: var(--magenta);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.65s var(--ease);
}
.proof__item:hover::after { transform: scaleX(1); }
.proof__ico {
  display: inline-grid;
  place-items: center;
  width: 40px; height: 40px;
  margin-bottom: 0.85rem;
  border-radius: 50%;
  background: #fff;
  color: var(--magenta);
  box-shadow: inset 0 0 0 1px var(--line);
  transition: background-color var(--t) var(--soft), color var(--t) var(--soft);
}
.proof__item:hover .proof__ico { background: var(--magenta); color: #fff; }
.proof__item h3 {
  font-size: clamp(1rem, 1.35vw, 1.12rem);
  line-height: 1.25;
  margin-bottom: 0.45rem;
}
.proof__item p { font-size: 0.91rem; line-height: 1.5; color: var(--ink-3); }
.proof__note {
  margin-top: clamp(1.5rem, 2.6vw, 2.25rem);
  padding-top: clamp(1.25rem, 2vw, 1.6rem);
  border-top: 1px solid var(--line);
  max-width: 46rem;
  font-size: 0.92rem;
  color: var(--ink-4);
}
@media (max-width: 1080px) { .proof__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .proof__grid { grid-template-columns: 1fr; } }

/* ==========================================================================
   Reviews
   ========================================================================== */
.reviews__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
  margin-bottom: clamp(2rem, 3.5vw, 3rem);
}
.reviews__score {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding-left: 1.5rem;
  border-left: 1px solid var(--on-dark-line);
}
.reviews__score strong {
  font-family: var(--display);
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: #fff;
  line-height: 1;
}
.reviews__score .stars { display: inline-flex; }
.reviews__score div span { font-size: 0.8rem; color: var(--on-dark-dim); display: block; }

/* Google-style review cards, ported from the Charlton Tyres treatment: white
   card, initial avatar, name and time, the Google mark top-right, gold stars.
   They sit on the dark photo section so the white pops. */
.grev-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.25rem, 2.4vw, 1.75rem);
}
.grev {
  background: #ffffff;
  border: 1px solid rgba(255, 255, 255, 0.9);
  border-radius: 14px;
  padding: 1.4rem 1.5rem 1.55rem;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  box-shadow: 0 24px 50px -34px rgba(0, 0, 0, 0.7);
}
.grev__head { display: flex; align-items: center; gap: 0.8rem; }
.grev__avatar {
  width: 44px; height: 44px;
  flex: none;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.05rem;
  color: #fff;
}
.grev__who { min-width: 0; flex: 1; }
.grev__name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.98rem;
  letter-spacing: -0.01em;
  color: var(--ink);
  line-height: 1.15;
  margin: 0;
}
.grev__time { font-size: 0.8rem; color: var(--ink-4); margin: 0.15rem 0 0; }
.grev__g { width: 20px; height: 20px; flex: none; align-self: flex-start; }
.grev__stars { display: inline-flex; gap: 2px; }
.grev__stars svg { width: 16px; height: 16px; fill: #FBBC04; }
.grev__text { font-size: 0.94rem; color: var(--ink-2); line-height: 1.55; margin: 0; }

@media (max-width: 860px) {
  .grev-grid { grid-template-columns: 1fr; max-width: 34rem; margin-inline: auto; }
}

/* ==========================================================================
   Services
   Six capabilities covering the whole life of an account. They used to be six
   bordered, rounded, pastel-iconed cards each carrying a four-line paragraph,
   which is the exact shape a reader has been trained to skim. They are ruled
   cells now, in line with the rest of the page: a hairline on top that goes
   magenta on hover, one line of copy, and a drawn glyph doing the explaining.
   ========================================================================== */
.caps__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 clamp(1.75rem, 4vw, 3.25rem);
}
.cap {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.55rem;
  padding: clamp(1.5rem, 2.4vw, 1.9rem) 0 clamp(1.6rem, 2.6vw, 2.1rem);
  border-top: 1px solid var(--line);
}
/* The magenta wipe rides on top of the hairline rather than replacing it, so
   the rule never changes width or position, only what colour covers it. */
.cap::after {
  content: "";
  position: absolute;
  top: -1px; left: 0;
  width: 100%; height: 2px;
  background: var(--magenta);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.65s var(--ease);
}
.cap:hover::after { transform: scaleX(1); }

/* ---------- The glyphs ----------
   Each is a small line drawing that animates its own idea: rings tuning into
   alignment, a calendar filling itself in, a shutter sweeping, a funnel
   dripping, a chart drawing itself. Long durations and small amplitudes on
   purpose. Six busy loops in a grid would be noise, not motion design. */
.cap__gfx {
  display: block;
  margin-bottom: 0.5rem;
  color: var(--magenta);
}
.gfx { display: block; width: 46px; height: 46px; overflow: visible; }
.gfx * {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform-box: fill-box;
  transform-origin: center;
}
/* Anything filled has to say so after that blanket rule. */
.gfx__core, .gfx__rec, .gfx__drop, .gfx__typ, .gfx__peak, .gfx__cell {
  fill: currentColor;
  stroke: none;
}
.gfx__frame, .gfx__axis { opacity: 0.42; }
.gfx__axis { stroke-width: 1.6; }

/* 01 Setup — two arcs turning until the centre locks. */
.gfx__ring { opacity: 0.55; }
.gfx__ring--a { animation: gfx-spin 9s linear infinite; }
.gfx__ring--b { animation: gfx-spin 6s linear infinite reverse; }
.gfx__core { animation: gfx-lock 3.6s var(--soft) infinite; }
@keyframes gfx-spin { to { transform: rotate(360deg); } }
@keyframes gfx-lock {
  0%, 62%   { transform: scale(0.7); opacity: 0.5; }
  74%       { transform: scale(1);   opacity: 1; }
  92%, 100% { transform: scale(0.7); opacity: 0.5; }
}

/* 02 Presence — a month filling itself in. */
.gfx__cell { opacity: 0.2; animation: gfx-fill 5.4s var(--soft) infinite; }
.gfx__cell--2 { animation-delay: 0.22s; }
.gfx__cell--3 { animation-delay: 0.44s; }
.gfx__cell--4 { animation-delay: 0.66s; }
.gfx__cell--5 { animation-delay: 0.88s; }
.gfx__cell--6 { animation-delay: 1.1s; }
@keyframes gfx-fill {
  0%, 6%    { opacity: 0.2; }
  16%, 62%  { opacity: 1; }
  76%, 100% { opacity: 0.2; }
}

/* 03 Production — the lens breathes, the record light pulses, a scan runs. */
.gfx__lens { animation: gfx-lens 3.4s var(--soft) infinite; }
.gfx__rec { animation: gfx-rec 1.9s var(--soft) infinite; }
.gfx__scan { opacity: 0.5; animation: gfx-scan 3.4s linear infinite; }
@keyframes gfx-lens {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(2px); }
}
@keyframes gfx-rec {
  0%, 100% { transform: scale(0.78); opacity: 0.45; }
  45%      { transform: scale(1);    opacity: 1; }
}
@keyframes gfx-scan {
  0%       { stroke-dashoffset: 22; }
  55%,100% { stroke-dashoffset: -100; }
}

/* 04 Pipeline — leads going in the top and coming out qualified. */
.gfx__drop { opacity: 0; animation: gfx-drop 2.8s var(--soft) infinite; }
.gfx__drop--2 { animation-delay: 0.35s; }
.gfx__drop--3 { animation-delay: 0.7s; }
@keyframes gfx-drop {
  0%       { transform: translate(0, 0) scale(1); opacity: 0; }
  12%      { opacity: 0.9; }
  55%      { transform: translate(0, 18px) scale(0.8); opacity: 0.9; }
  /* Only the middle of the three makes it out the bottom. That is the point
     of a funnel, so the other two translate sideways and fade. */
  85%,100% { transform: translate(0, 30px) scale(0.55); opacity: 0; }
}
.gfx__drop--1 { animation-name: gfx-drop-off; }
.gfx__drop--3 { animation-name: gfx-drop-off; }
@keyframes gfx-drop-off {
  0%       { transform: translate(0, 0); opacity: 0; }
  12%      { opacity: 0.8; }
  50%      { transform: translate(0, 12px); opacity: 0.8; }
  78%,100% { transform: translate(0, 16px); opacity: 0; }
}

/* 05 Communication — a reply being typed, not a static bubble. */
.gfx__typ { opacity: 0.28; animation: gfx-type 1.5s var(--soft) infinite; }
.gfx__typ--2 { animation-delay: 0.18s; }
.gfx__typ--3 { animation-delay: 0.36s; }
@keyframes gfx-type {
  0%, 70%, 100% { transform: translateY(0);    opacity: 0.28; }
  30%           { transform: translateY(-3px); opacity: 1; }
}

/* 06 Growth — the line draws itself, then the arrow and the peak land. */
.gfx__trend { animation: gfx-draw 4.6s var(--ease) infinite; }
.gfx__tip { opacity: 0; animation: gfx-late 4.6s var(--soft) infinite; }
.gfx__peak { opacity: 0; animation: gfx-late 4.6s var(--soft) infinite; }
@keyframes gfx-draw {
  0%        { stroke-dashoffset: 100; }
  42%, 82%  { stroke-dashoffset: 0; }
  100%      { stroke-dashoffset: 100; }
}
@keyframes gfx-late {
  0%, 40%   { opacity: 0; transform: scale(0.7); }
  52%, 82%  { opacity: 1; transform: scale(1); }
  92%, 100% { opacity: 0; transform: scale(0.7); }
}

/* Nothing here carries meaning that the copy does not already carry, so all
   of it stops dead rather than degrading. */
@media (prefers-reduced-motion: reduce) {
  .gfx * { animation: none !important; }
  .gfx__cell, .gfx__typ, .gfx__core, .gfx__rec { opacity: 1; }
  .gfx__drop { opacity: 0.8; }
  .gfx__trend { stroke-dashoffset: 0; }
  .gfx__tip, .gfx__peak { opacity: 1; }
}

.cap__role {
  font-family: var(--display);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--magenta);
}
.cap h3 {
  font-size: clamp(1.15rem, 1.7vw, 1.32rem);
  letter-spacing: -0.02em;
  max-width: 18ch;
  transition: color var(--t) var(--soft);
}
.cap:hover h3 { color: var(--magenta); }
.cap p { color: var(--ink-2); font-size: 0.94rem; max-width: 32ch; }

/* The line that ties the six back to the one-contact promise. */
.caps__foot {
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
  padding-top: clamp(1.35rem, 2.2vw, 1.75rem);
  border-top: 1px solid var(--line);
  max-width: 48rem;
  color: var(--ink-3);
  font-size: 0.98rem;
}


/* ==========================================================================
   Feature (on the ground)
   ========================================================================== */
.feature__grid {
  display: grid;
  grid-template-columns: 1.02fr 0.98fr;
  gap: clamp(2.25rem, 6vw, 5.5rem);
  align-items: center;
}

/* ---------- The photo pair ----------
   These two were previously matched thumbnails side by side, which wasted
   both of them: the on-location shoot is the strongest image on the site and
   it was the size of a stamp. Now one leads at full height and the second
   overlaps it from below, cut out of the paper by a blush-coloured border. */
/* The lead runs the full width of its column and the inset overlaps its
   bottom-right corner, so both images finish on the same vertical line as the
   column itself. The old version padded the stack on the right, which pushed
   the inset out past the lead and left the pair sitting at an angle to every
   other edge on the page. */
.feature__stack {
  position: relative;
  max-width: 30rem;
  padding-bottom: clamp(2.75rem, 6vw, 4.5rem);
}
.feature__lead {
  width: 100%;
  aspect-ratio: 4 / 5;
  border-radius: var(--r-xl);
}
/* The border is the band's own background colour, so the inset reads as cut
   out of the section rather than framed. It moved with the band to plum. */
.feature__inset {
  position: absolute;
  right: 0;
  bottom: 0;
  width: min(56%, 17rem);
  aspect-ratio: 4 / 3;
  border: clamp(7px, 0.9vw, 12px) solid var(--plum);
  border-radius: calc(var(--r-lg) + 8px);
  box-shadow: 0 26px 60px -34px rgba(0, 0, 0, 0.8);
}

/* Tag pinned into the lead image rather than floating between the two. */
/* Higher specificity than `.feature p` above, which was overriding the tag's
   ink colour with the band's on-dark white and leaving it white-on-white. */
.feature .feature__tag {
  position: absolute;
  left: clamp(0.9rem, 2vw, 1.4rem);
  top: clamp(0.9rem, 2vw, 1.4rem);
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.6rem 1.05rem;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  font-family: var(--display);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
.feature__tag svg { color: var(--magenta); }

.feature h2 { margin-bottom: 1.35rem; }
.feature .label { margin-bottom: 1.1rem; }
.feature p + p { margin-top: 1rem; }
/* The band runs on plum now, so the type inverts with it. */
.feature p { color: var(--on-dark); }
.feature .lede { color: rgba(255, 255, 255, 0.9); }
.feature strong { color: #fff; font-weight: 600; }

.feature__points {
  list-style: none;
  padding: 0;
  margin-top: 1.85rem;
  display: grid;
  gap: 0.65rem;
}
.feature__points li {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  font-size: 0.95rem;
  color: var(--on-dark);
}
.feature__points li::before {
  content: "";
  flex-shrink: 0;
  width: 18px; height: 18px;
  margin-top: 0.2rem;
  border-radius: 50%;
  background: var(--magenta)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
    center / 11px 11px no-repeat;
}
/* ==========================================================================
   Case studies — the work cards
   Five near-identical text slabs, each carrying two columns of prose and a
   three-up outcome strip, ran nearly 3000px down the homepage and said the
   same shape five times. They are cards now, and every card answers the same
   four questions in the same order, each one captioned: WHO it was for, WHAT
   WAS WRONG, WHAT WE DID as three chips, and WHAT CHANGED as two figures.

   No photography. The band across the top used to carry a real frame from
   OM's own work under a plum wash, which looked well and did two bad things:
   it read as a photograph of that client, and it pushed the only information
   anyone wanted down the card. It is an identity strip now. The long
   write-ups still exist on the case studies page, one tap down, inside
   .work__detail.
   ========================================================================== */
.works {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 1.8vw, 1.5rem);
}
/* The specialty case leads at double width and lays out landscape, so the set
   never reads as five identical tiles. */
.works > .work--lead { grid-column: span 2; }

/* Where the cards can be expanded (the case studies page) they size to their
   own content instead of stretching to the row. Stretching is what a tidy
   static grid wants, but the moment one card opens, every sibling in its row
   grows with it and shows a hole where the copy ran out. The lead still fills
   its row so the landscape card never floats short. */
.works--open { align-items: start; }
.works--open > .work--lead { align-self: stretch; }

.work {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--line);
  /* Transform only. The lift is a pseudo layer that cross-fades underneath,
     so hovering a card never asks the browser to repaint a blur, which is the
     rule the rest of this stylesheet follows. */
  transition: transform var(--t-mv) var(--ease);
}
/* The ring is an inset shadow on a pseudo layer, so it is not clipped by the
   card's own overflow and it cross-fades on opacity rather than repainting a
   shadow. Nothing else moves but the card itself. */
.work::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1.5px var(--magenta-soft);
  opacity: 0;
  transition: opacity var(--t) var(--soft);
}
.work:hover { transform: translateY(-3px); }
.work:hover::after { opacity: 1; }
.work[hidden] { display: none; }

/* ---------- The header band ----------
   This used to be a photograph: a real frame from OM's own work under a plum
   wash. It looked handsome and told you nothing, and worse, a photo sitting
   above a case study reads as a photo OF that client, which none of them
   were. The band is now a plain identity strip. Sector on the left, because
   that is the only thing a reader is scanning for, the sector glyph and the
   index on the right. No image, no crop, no ambiguity. */
.work__head {
  position: relative;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: clamp(0.9rem, 1.8vw, 1.15rem) clamp(1.15rem, 2.2vw, 1.6rem);
  background: var(--magenta-mist);
  border-bottom: 1px solid var(--line);
}
.work__id {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
}

/* The ghost index, set at the end of the strip. */
.work__num {
  margin-left: auto;
  font-family: var(--display);
  font-size: clamp(1.6rem, 2.4vw, 2rem);
  font-weight: 800;
  letter-spacing: -0.06em;
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px var(--magenta-soft);
  transition: -webkit-text-stroke-color var(--t) var(--soft);
}
.work:hover .work__num { -webkit-text-stroke-color: var(--magenta-lit); }

/* The sector, which is the first thing anyone needs from one of these. */
.work__who {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--display);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--magenta-deep);
}
.work__who::before {
  content: "";
  flex-shrink: 0;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--magenta);
}
/* One card is the specialty. It says so, once. */
.work__flag {
  font-family: var(--display);
  font-size: 0.58rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #fff;
  background: var(--magenta);
  padding: 0.3rem 0.6rem;
  border-radius: var(--r-pill);
}

/* ---------- The glyph ----------
   Same family as the services grid: a small line drawing that animates its
   own idea. It sits in the header strip now, magenta on white rather than
   white on plum, and the blur behind it is gone with the photograph. */
.work__gfx {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  border-radius: 50%;
  color: var(--magenta);
  background: var(--paper);
  box-shadow: inset 0 0 0 1px var(--magenta-soft);
  transition: background-color var(--t) var(--soft), color var(--t) var(--soft);
}
.work:hover .work__gfx { background: var(--magenta); color: #fff; }
.wgfx { display: block; width: 22px; height: 22px; overflow: visible; }
.wgfx * {
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  transform-box: fill-box;
  transform-origin: center;
}
.wgfx__soft { opacity: 0.4; }
.wgfx__dot { fill: currentColor; stroke: none; }

/* 01 NDIS — the shield holds, the tick draws itself inside it. */
.wgfx__tick { stroke-width: 2.2; animation: wg-tick 4.4s var(--ease) infinite; }
@keyframes wg-tick {
  0%       { stroke-dashoffset: 100; }
  28%, 78% { stroke-dashoffset: 0; }
  96%,100% { stroke-dashoffset: 100; }
}
/* 02 Wellness — a drop lands and the rings go out. */
.wgfx__ring { opacity: 0; animation: wg-ring 3.6s var(--soft) infinite; }
.wgfx__ring--2 { animation-delay: 0.5s; }
.wgfx__ring--3 { animation-delay: 1s; }
@keyframes wg-ring {
  0%       { transform: scale(0.35); opacity: 0; }
  22%      { opacity: 0.75; }
  70%,100% { transform: scale(1.25); opacity: 0; }
}
/* 03 Print and office — the handset, and the call actually connecting. */
.wgfx__wave { opacity: 0; animation: wg-wave 2.6s var(--soft) infinite; }
.wgfx__wave--2 { animation-delay: 0.28s; }
.wgfx__wave--3 { animation-delay: 0.56s; }
@keyframes wg-wave {
  0%, 100% { opacity: 0; }
  30%, 62% { opacity: 0.9; }
}
/* 04 Finance — four quarters coming round, one at a time. */
.wgfx__q { opacity: 0.22; animation: wg-q 6s steps(1, end) infinite; }
.wgfx__q--2 { animation-delay: 1.5s; }
.wgfx__q--3 { animation-delay: 3s; }
.wgfx__q--4 { animation-delay: 4.5s; }
@keyframes wg-q {
  0%, 24%   { opacity: 1; }
  25%, 100% { opacity: 0.22; }
}
/* 05 Beauty — the frame refreshes on a loop. */
.wgfx__spin { animation: wg-spin 5.5s var(--ease) infinite; }
@keyframes wg-spin {
  0%, 55%   { transform: rotate(0deg); }
  78%, 100% { transform: rotate(180deg); }
}
.wgfx__spark { animation: wg-spark 5.5s var(--soft) infinite; }
@keyframes wg-spark {
  0%, 60%   { opacity: 0.3; transform: scale(0.8); }
  76%, 92%  { opacity: 1;   transform: scale(1); }
  100%      { opacity: 0.3; transform: scale(0.8); }
}
@media (prefers-reduced-motion: reduce) {
  .wgfx * { animation: none !important; }
  .wgfx__tick { stroke-dashoffset: 0; }
  .wgfx__ring, .wgfx__wave { opacity: 0.5; }
  .wgfx__q { opacity: 1; }
}

/* ---------- The body ---------- */
.work__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 0.75rem;
  padding: clamp(1.15rem, 2.2vw, 1.6rem) clamp(1.15rem, 2.2vw, 1.6rem) clamp(1.1rem, 2vw, 1.4rem);
}
.work__body h3 {
  font-size: clamp(1.12rem, 1.55vw, 1.32rem);
  letter-spacing: -0.025em;
  line-height: 1.18;
  max-width: 22ch;
  transition: color var(--t) var(--soft);
}
.work:hover .work__body h3 { color: var(--magenta); }
.work__line {
  font-size: 0.93rem;
  line-height: 1.5;
  color: var(--ink-3);
  max-width: 44ch;
}

/* ---------- The two labelled rows ----------
   The old card ran a headline, an unlabelled sentence and three unlabelled
   chips, and left the reader to work out which was the problem and which was
   the work. Both are captioned now, so the same three facts land in the same
   order on every card: who, what was wrong, what we did. */
.work__rows {
  display: grid;
  gap: 1rem;
  margin-top: 0.1rem;
}
.work__row { display: grid; gap: 0.4rem; }
.work__row .work__k { margin: 0; }

/* What we did, as three chips rather than three sentences. */
.work__did {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding: 0;
  margin: 0;
}
.work__did li {
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--magenta-deep);
  background: var(--magenta-mist);
  border-radius: var(--r-pill);
  padding: 0.34rem 0.7rem;
}

/* ---------- What changed, as two figures ----------
   This replaces the single italicised outcome line, which was the vaguest
   thing on the card. Two measures per case, sat on their own rule at the foot
   so the eye can run straight down the column and read nothing but results.

   The values are deliberately the kind of thing that can be said out loud on
   a call: cadence, cover, standards held. There are no revenue figures or
   percentage lifts here, for the same reason the disclaimer on the case
   studies page gives. When Amanda has a client's permission for a real
   number, it drops straight into a <dt> and the caption underneath it. */
.work__stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.9rem clamp(0.9rem, 1.8vw, 1.4rem);
  /* auto pins the figures to the foot of the card, so the second line of every
     column in a row lands on the same baseline however long the copy above it
     runs. */
  margin: auto 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.work__stat { min-width: 0; }
.work__stat dt {
  font-family: var(--display);
  font-size: clamp(1.02rem, 1.5vw, 1.22rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--magenta);
}
.work__stat dd {
  margin: 0.3rem 0 0;
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--ink-3);
}
/* The second figure gets a hairline between it and the first, which is enough
   separation without a box around either. */
.work__stat + .work__stat {
  padding-left: clamp(0.9rem, 1.8vw, 1.4rem);
  border-left: 1px solid var(--line);
}

/* ---------- The lead card, wide ----------
   Without the photograph there is no second column to fill, so the lead runs
   the same single column as its siblings, just larger and with more air. Two
   columns of copy were tried here first and left a hole: the card has to
   match the height of the one beside it, and splitting the copy in half
   halves the height it fills. */
@media (min-width: 861px) {
  .work--lead .work__body { padding: clamp(1.6rem, 2.8vw, 2.3rem); gap: 1.1rem; }
  .work--lead .work__body h3 { font-size: clamp(1.4rem, 2.2vw, 1.85rem); max-width: 24ch; }
  .work--lead .work__line { font-size: 1rem; max-width: 52ch; }
  .work--lead .work__rows { gap: 1.35rem; }
  .work--lead .work__did li { font-size: 0.76rem; padding: 0.4rem 0.8rem; }
  .work--lead .work__stats { max-width: 40rem; }
  .work--lead .work__stat dt { font-size: clamp(1.2rem, 1.8vw, 1.45rem); }
  .work--lead .work__stat dd { font-size: 0.85rem; }
}

/* ---------- The expander (case studies page) ----------
   The full write-up, one tap down. Animating grid-template-rows rather than
   height means the panel never needs a measured pixel value, and the closed
   state is genuinely zero so nothing is reachable while it is shut. */
.work__more {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex: none;
  gap: 1rem;
  width: 100%;
  margin-top: 0.9rem;
  padding: 0.75rem 0 0;
  border: 0;
  border-top: 1px solid var(--line);
  background: none;
  cursor: pointer;
  font-family: var(--display);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  transition: color var(--t) var(--soft);
}
.work__more:hover { color: var(--magenta); }
.work__more-sign {
  position: relative;
  flex-shrink: 0;
  width: 26px; height: 26px;
  border-radius: 50%;
  border: 1px solid var(--line);
  transition: background-color var(--t) var(--soft), border-color var(--t) var(--soft);
}
.work__more-sign::before,
.work__more-sign::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 10px; height: 1.6px;
  border-radius: 2px;
  background: currentColor;
  transform: translate(-50%, -50%);
  transition: transform var(--t) var(--ease), background-color var(--t) var(--soft);
}
.work__more-sign::after { transform: translate(-50%, -50%) rotate(90deg); }
.work__more:hover .work__more-sign { border-color: var(--magenta); }
.work__more[aria-expanded="true"] .work__more-sign {
  background: var(--magenta);
  border-color: var(--magenta);
  color: #fff;
}
.work__more[aria-expanded="true"] .work__more-sign::after { transform: translate(-50%, -50%) rotate(0deg); }

/* The panel animates its own height in pixels, set by the script from the
   content's scrollHeight and handed back to `auto` once the transition ends.
   The tidier 0fr-to-1fr grid trick was tried first and does not survive here:
   inside this flex column the fr track resolves against no free space, so the
   panel stays at zero for the whole transition and only ever snaps open.
   `flex: none` matters too, or the panel is just a shrinkable flex item that
   collapses again the moment it is given a height. */
.work__detail {
  height: 0;
  overflow: hidden;
  flex: none;
  transition: height var(--t-mv) var(--ease);
}
.work__detail > div { min-height: 0; }

.work__k {
  font-family: var(--display);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin: 1.1rem 0 0.5rem;
}
.work__brief { font-size: 0.93rem; line-height: 1.55; color: var(--ink-2); }
.work__list { list-style: none; display: grid; gap: 0.5rem; padding: 0; }
.work__list li {
  position: relative;
  padding-left: 1.3rem;
  font-size: 0.93rem;
  line-height: 1.5;
  color: var(--ink-2);
}
.work__list li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.52em;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--magenta-lit);
  box-shadow: 0 0 0 3px var(--magenta-mist);
}
.work__still {
  margin-top: 1rem;
  padding: 0.8rem 1rem;
  border-radius: var(--r-xs);
  background: var(--magenta-mist);
  font-size: 0.89rem;
  line-height: 1.5;
  color: var(--ink-2);
}
.work__still b {
  display: block;
  font-family: var(--display);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--magenta);
  margin-bottom: 0.25rem;
}
/* The highlighter, kept from the long write-ups. */
.work .hl {
  font-weight: 600;
  color: var(--magenta-deep);
  background: linear-gradient(180deg, transparent 62%, var(--magenta-soft) 62%);
}

@media (max-width: 1080px) {
  .works { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .works > .work--lead { grid-column: span 2; }
}
@media (max-width: 700px) {
  .works { grid-template-columns: 1fr; }
  .works > .work--lead { grid-column: auto; }
}
/* Two figures side by side get about twelve characters each on a narrow
   phone, which is not enough for the captions. They stack, and the divider
   moves from the side to the top. */
@media (max-width: 400px) {
  .work__stats { grid-template-columns: 1fr; gap: 0.7rem; }
  .work__stat + .work__stat {
    padding: 0.7rem 0 0;
    border-left: 0;
    border-top: 1px solid var(--line);
  }
}

.cases__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  flex-wrap: wrap;
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
  padding-top: clamp(1.5rem, 2.5vw, 2rem);
  border-top: 1px solid var(--line);
}
.cases__foot p { color: var(--ink-3); max-width: 40rem; font-size: 0.96rem; }


/* ==========================================================================
   About
   ========================================================================== */
.about__grid {
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: clamp(2.25rem, 5vw, 4.5rem);
  align-items: center;
}
.about__media { position: relative; }
.about__media .media {
  aspect-ratio: 4 / 5;
  border-radius: var(--r-xl);
  box-shadow: var(--lift-3);
}
/* The source is already cropped to this frame, head to hips, so the box
   needs no offset. */
.about__media .media img { object-position: center 20%; }
.about__caption {
  position: absolute;
  left: clamp(0.9rem, 2vw, 1.35rem);
  bottom: clamp(0.9rem, 2vw, 1.35rem);
  padding: 0.6rem 1.05rem;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, 0.93);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  font-size: 0.78rem;
  font-family: var(--display);
  font-weight: 600;
  color: var(--ink);
  box-shadow: var(--lift-2);
}

.about h2 { margin-bottom: 1.4rem; }
.about .label { margin-bottom: 1.1rem; }
.about__body p { color: var(--ink-2); }
.about__body p + p { margin-top: 1.05rem; }
.about strong { color: var(--ink); font-weight: 600; }

/* Set as a pull quote, not parked in a pink panel. The tint made Amanda's
   own words read as another UI component. */
.about__quote {
  position: relative;
  margin-top: clamp(2rem, 3.5vw, 2.75rem);
  padding-left: 1.6rem;
  font-family: var(--display);
  font-style: normal;
  font-weight: 600;
  letter-spacing: -0.01em;
  font-size: clamp(1.25rem, 2vw, 1.6rem);
  line-height: 1.4;
  color: var(--ink);
}
/* A rule, not a giant curly quote glyph. Bodoni's quote mark renders as two
   specks at this size and reads as a rendering fault. */
.about__quote::before {
  content: "";
  position: absolute;
  top: 0.3rem; left: 0;
  width: 2px; height: calc(100% - 0.6rem);
  border-radius: 2px;
  background: var(--magenta);
}
.about__sign {
  margin-top: 1.1rem;
  font-family: var(--display);
  font-size: 0.76rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-4);
}

/* ==========================================================================
   Why OM — the comparison
   Replaced four numbered claims on hairlines, none of which a competitor
   could not also claim. Each row is its own two-column grid rather than two
   independent columns, so hovering anywhere on a row lights both halves and
   the pair reads as one statement. The right-hand cells carry a continuous
   magenta tint so the OM side still reads as a single panel down the table.
   ========================================================================== */
.vs .section-head { margin-bottom: clamp(2rem, 3.5vw, 3rem); }
.vs .section-head h2 { max-width: 22ch; }
.vs .section-head .lede { color: var(--on-dark); max-width: 46ch; }

.vs__table { display: grid; }

.vs__head, .vs__row { display: grid; grid-template-columns: 1fr 1fr; }

.vs__head-cell {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0;
  padding: 0.9rem clamp(0.9rem, 2vw, 1.5rem);
  font-family: var(--display);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.vs__head-cell--x { color: var(--on-dark-dim); }
.vs__head-cell--o { color: #fff; background: rgba(31, 182, 115, 0.14); }

.vs__mark {
  display: grid;
  place-items: center;
  width: 24px; height: 24px;
  border-radius: 50%;
}
.vs__mark svg { width: 13px; height: 13px; }
.vs__mark--x { background: rgba(229, 72, 77, 0.16); color: #FF9C9E; box-shadow: inset 0 0 0 1px rgba(229, 72, 77, 0.4); }
.vs__mark--o { background: var(--good); color: #fff; box-shadow: 0 6px 16px -8px rgba(31, 182, 115, 0.9); }

.vs__cell {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  margin: 0;
  padding: clamp(1rem, 1.8vw, 1.35rem) clamp(0.9rem, 2vw, 1.5rem);
  border-top: 1px solid var(--on-dark-line);
  font-size: 0.97rem;
  line-height: 1.55;
  transition: color var(--t) var(--soft), background-color var(--t) var(--soft);
}
/* The left-hand option stays the quieter of the two even on hover. The point
   of every row is the right-hand side. */
.vs__cell--x { color: var(--on-dark-dim); }
/* The OM column reads as one continuous green-tinted panel down the table, with
   a hairline down its leading edge so it lifts off the plum as the "right" side. */
.vs__cell--o {
  color: #fff;
  background: rgba(31, 182, 115, 0.12);
  box-shadow: inset 3px 0 0 rgba(31, 182, 115, 0.55);
}
.vs__row:last-child .vs__cell { border-bottom: 1px solid var(--on-dark-line); }

.vs__ico {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 20px; height: 20px;
  margin-top: 0.15rem;
  border-radius: 50%;
  transition: background-color var(--t) var(--soft), transform var(--t-mv) var(--ease);
}
.vs__ico svg { width: 11px; height: 11px; }
.vs__cell--x .vs__ico { background: rgba(229, 72, 77, 0.16); color: #FF9C9E; }
.vs__cell--o .vs__ico { background: var(--good); color: #fff; box-shadow: 0 6px 16px -9px rgba(31, 182, 115, 0.9); }

.vs__row:hover .vs__cell--x { color: var(--on-dark); }
.vs__row:hover .vs__cell--o { background: rgba(31, 182, 115, 0.2); }
.vs__row:hover .vs__cell--o .vs__ico { background: var(--good-lit); transform: scale(1.14); }

/* ---------- The table arriving ----------
   The whole block used to fade in as one slab, which for a five-row argument
   meant the reader got all five at once and read none of them. Each row is its
   own .reveal now, seventy milliseconds apart, and the tick on the OM side
   draws itself rather than appearing already ticked. The row is the unit of
   meaning, so the row is the unit of motion. */
.vs__cell--o .vs__ico svg path {
  stroke-dasharray: 30;
  stroke-dashoffset: 30;
  transition: stroke-dashoffset 0.55s var(--ease) 0.25s;
}
.vs__row.is-in .vs__cell--o .vs__ico svg path { stroke-dashoffset: 0; }
/* The cross is the state being argued against: it is there from the start. */
.vs__cell--x .vs__ico svg path { stroke-dashoffset: 0; }

@media (prefers-reduced-motion: reduce) {
  .vs__cell--o .vs__ico svg path { stroke-dashoffset: 0; transition: none; }
}

@media (max-width: 760px) {
  /* Two narrow columns turn both sides into word soup. Stacked, each row is
     the claim and then the answer, read downward. Previously the OM half kept
     its filled green panel while the X half sat bare, so the column alternated
     empty / filled and looked uneven. Each row is now one bordered card: the X
     line on top, a hairline, then the OM line, both padded the same. */
  .vs__head { display: none; }
  .vs__table { display: grid; gap: 0.85rem; }
  .vs__row {
    grid-template-columns: 1fr;
    margin: 0;
    border: 1px solid var(--on-dark-line);
    border-radius: var(--r-lg);
    overflow: hidden;
    background: rgba(255, 255, 255, 0.03);
  }
  .vs__cell { border-top: 0; padding: 0.95rem 1.1rem; }
  .vs__cell--x { border-bottom: 1px solid var(--on-dark-line); }
  /* Keep a soft green tint on the OM half, but drop the inset edge bar so the
     two halves read as one card rather than a floating panel. */
  .vs__cell--o { background: rgba(31, 182, 115, 0.09); box-shadow: none; }
  .vs__row:last-child .vs__cell { border-bottom: 0; }
  .vs__row:last-child .vs__cell--x { border-bottom: 1px solid var(--on-dark-line); }
}

/* ==========================================================================
   Start here — the interactive CTA band
   The question is the same one it always asked, and picking an answer still
   retargets the button at the enquiry wizard. What changed is everything
   underneath it. It used to be a full-bleed magenta gradient with a white
   lattice raked across it and a translucent card floating on top: three
   competing decorative layers, a box inside a box, and the one section on the
   site that did not look like the rest of it.

   It is now a light slab inset into the page: blush ground, a hairline, and a
   soft magenta bloom in the top corner. The photograph that used to back it
   is gone. Cropping a wide frame into a short band gave a different sliver of
   image at every width, and it dropped a second dark section directly under
   the dark one above it, so the page ended on two heavy bands in a row. The
   paper margin around the slab still does the separating, and the closing ask
   now reads as an open invitation rather than a shutter coming down.

   The markup is identical on every page, so the whole change lives here:
   .start__bg is the slab, .start__wash is the bloom and .start__rules is a
   hairline grid over it. Nothing in the HTML had to move.
   ========================================================================== */
.start {
  position: relative;
  isolation: isolate;
  color: var(--ink-2);
  background: transparent;
  /* The slab carries its own padding, so the section only has to make room
     for it. Extra clearance top and bottom so the slab reads as a clear inset
     box with space around it, not flush with the section edges. */
  padding-block: clamp(4rem, 8vw, 7rem);
}
.start h2 {
  color: var(--ink);
  font-size: clamp(2.1rem, 4.4vw, 3.4rem);
  max-width: 15ch;
  margin-top: 1.1rem;
}
.start .accent { color: var(--magenta); }
.start .label--dark { color: var(--magenta); background: var(--magenta-mist); }
.start .label--dark::before { background: currentColor; }

/* ---------- The slab ---------- */
/* Sized and centred exactly like .wrap, so the slab's edges land on the same
   vertical lines as every heading on the page rather than floating at some
   width of their own. */
.start__bg {
  position: absolute;
  top: 0; bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: min(100% - var(--gutter), var(--wrap));
  z-index: -1;
  overflow: hidden;
  border-radius: var(--r-xl);
  background-color: var(--blush);
  box-shadow: inset 0 0 0 1px var(--line), var(--lift-3);
}
/* The bloom: two soft magenta washes, one in each corner the eye lands on.
   This is where the cropped photograph used to be. */
.start__wash {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(80% 90% at 100% 0%, rgba(238, 58, 172, 0.16) 0%, rgba(238, 58, 172, 0) 62%),
    radial-gradient(70% 80% at 0% 100%, rgba(180, 0, 154, 0.09) 0%, rgba(180, 0, 154, 0) 60%);
}
/* The rules: a faint grid, the one bit of texture on the slab. Same hairline
   colour as every other rule on the site, so it reads as paper rather than as
   a pattern laid over it. */
.start__rules {
  position: absolute;
  inset: 0;
  opacity: 0.55;
  background-image:
    linear-gradient(var(--line-2) 1px, transparent 1px),
    linear-gradient(90deg, var(--line-2) 1px, transparent 1px);
  background-size: 68px 68px;
  -webkit-mask-image: radial-gradient(120% 100% at 50% 0%, #000 0%, transparent 78%);
          mask-image: radial-gradient(120% 100% at 50% 0%, #000 0%, transparent 78%);
}

/* The content sits straight on the slab now. The translucent card it used to
   sit inside was a second border around a section that already had one. */
.start__inner {
  max-width: 68rem;
  /* Trim the vertical padding so the slab reads as a compact box; the section's
     own padding-block supplies the white space around it. */
  padding: clamp(1.4rem, 2.6vw, 2.1rem) clamp(1.5rem, 3.5vw, 3rem);
}

/* Wizard chrome above the heading: a "one question" counter and a near-full
   progress bar, echoing the "Step 01 of 05" + bar at the top of the form. */
.start__head { position: relative; margin: 0; }
.start__head::before {
  content: "One question · 30-second start";
  display: block;
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 0.9rem;
}
.start__head::after {
  content: "";
  display: block;
  height: 3px;
  width: min(18rem, 100%);
  margin-top: clamp(1.1rem, 2vw, 1.5rem);
  border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--magenta) 0 84%, var(--line) 84% 100%);
}

.start__picks {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.65rem;
  margin: 0;
}
.pick {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.95rem;
  padding: 1.05rem 3.4rem 1.05rem 1.2rem;
  text-align: left;
  cursor: pointer;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  transition:
    background-color var(--t) var(--soft),
    border-color var(--t) var(--soft),
    color var(--t) var(--soft),
    transform var(--t-mv) var(--ease);
}
.pick:hover { background: var(--magenta-mist); border-color: var(--magenta-soft); }
.pick:focus-visible { outline: 2px solid var(--magenta); outline-offset: 3px; }
.pick__n {
  flex-shrink: 0;
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--ink-4);
  transition: color var(--t) var(--soft);
}
.pick__t {
  font-family: var(--display);
  font-size: clamp(0.98rem, 1.25vw, 1.08rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.25;
}
/* The tick sits where the wizard's does: an empty ring that fills magenta with
   a white check on selection. */
.pick::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 1.15rem;
  transform: translateY(-50%);
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: transparent
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='%23a8018f' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
    center / 0 0 no-repeat;
  transition: border-color var(--t) var(--soft), background-color var(--t) var(--soft),
              background-size var(--t) var(--ease);
}
/* On a light slab the chosen answer inverts the other way: solid magenta, the
   only saturated block in the band, so which one is live is never in
   question. The tick disc goes white and keeps the magenta check it always
   had. */
.pick.is-on {
  background: var(--magenta);
  border-color: var(--magenta);
  color: #fff;
  box-shadow: 0 20px 40px -26px rgba(180, 0, 154, 0.7);
}
.pick.is-on .pick__n { color: rgba(255, 255, 255, 0.72); }
.pick.is-on::after {
  border-color: #fff;
  background-color: #fff;
  background-size: 13px 13px;
}

.start__note {
  margin: clamp(1.4rem, 2.4vw, 1.8rem) 0 0;
  max-width: 42ch;
  font-size: 1.02rem;
  line-height: 1.6;
  color: var(--ink-2);
}
.start__go { margin-top: clamp(1.5rem, 2.6vw, 2rem); }
/* The two buttons keep their markup on all ten pages, so they are restyled
   for paper here rather than reclassed in ten files. Light becomes the
   magenta primary, outline-light becomes the ink outline. */
.start .btn--light { background: var(--magenta); color: #fff; }
.start .btn--light::before { background: var(--plum); }
.start .btn--light .btn__arrow { background: rgba(255, 255, 255, 0.2); }
.start .btn--light:hover .btn__arrow { background: rgba(255, 255, 255, 0.24); }
.start .btn--outline-light { border-color: var(--line); color: var(--ink); background: var(--paper); }
.start .btn--outline-light::before { background: var(--ink); }
.start .btn--outline-light:hover,
.start .btn--outline-light:focus-visible { color: #fff; border-color: var(--ink); }

/* Landscape: the ask on the left, the option list down the right. */
@media (min-width: 861px) {
  .start__inner {
    display: grid;
    grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
    grid-template-areas:
      "head  picks"
      "note  picks"
      "go    picks";
    column-gap: clamp(2rem, 4.5vw, 3.75rem);
    align-items: start;
  }
  .start__head  { grid-area: head; }
  .start__note  { grid-area: note; }
  .start__go    { grid-area: go; align-self: end; }
  .start__picks { grid-area: picks; align-self: stretch; }
  /* Pin the progress bar to the foot of the heading block. */
  .start h2 { margin-bottom: 0; }
}

/* Stacked, the progress bar lands hard against the top of the first option and
   its unfilled tail reads as a stray rule floating over the box. It only ever
   made sense as chrome under the heading in the landscape layout. */
@media (max-width: 860px) {
  .start__head::after { display: none; }
  .start h2 { margin-bottom: clamp(1.4rem, 4vw, 1.9rem); }
}

@media (max-width: 520px) {
  .pick { gap: 0.8rem; padding: 0.95rem 3.1rem 0.95rem 1.1rem; }
}
@media (prefers-reduced-motion: reduce) {
  .pick, .pick.is-on { transform: none; }
  .pick.is-on::after { animation: none; }
}

/* ==========================================================================
   Contact page
   ========================================================================== */
.page-hero {
  background: var(--plum);
  color: var(--on-dark);
  padding-block: clamp(3rem, 6vw, 4.5rem) clamp(2.5rem, 4vw, 3.5rem);
  background-image:
    radial-gradient(110% 90% at 100% 0%, rgba(180, 0, 154, 0.32) 0%, rgba(180, 0, 154, 0) 58%);
}
.page-hero__top {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(1.75rem, 4vw, 4rem);
  align-items: end;
  padding-bottom: clamp(2.25rem, 4vw, 3rem);
}
.page-hero h1 {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 0.98;
  color: #fff;
  font-size: clamp(2.4rem, 5.8vw, 4.6rem);
  margin-top: 1.25rem;
}
.page-hero .lede { color: var(--on-dark); margin-bottom: 0.35rem; }

/* Four ruled columns on the plum, not four translucent boxes. */
.page-hero__rail {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1.25rem, 3vw, 2.75rem);
}
.rail-item {
  position: relative;
  padding-top: clamp(1.15rem, 2vw, 1.5rem);
  border-top: 1px solid var(--on-dark-line);
  transition: transform var(--t-mv) var(--ease);
}
.rail-item::after {
  content: "";
  position: absolute;
  top: -1px; left: 0;
  width: 100%; height: 1px;
  background: var(--magenta-lit);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.65s var(--ease);
}
a.rail-item:hover::after { transform: scaleX(1); }
a.rail-item:hover { transform: translateY(-3px); }
.rail-item__label {
  display: block;
  font-family: var(--display);
  font-size: 0.66rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--magenta-lit);
  margin-bottom: 0.5rem;
}
.rail-item__value {
  display: block;
  font-family: var(--display);
  font-size: 0.98rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: #fff;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.rail-item__value small {
  display: block;
  font-family: var(--sans);
  font-size: 0.78rem;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--on-dark-dim);
  margin-top: 0.3rem;
}

.contact__grid {
  display: grid;
  grid-template-columns: 0.72fr 1.28fr;
  gap: clamp(2.5rem, 5vw, 4.5rem);
  align-items: start;
}

.next-steps h3 {
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-4);
  margin-bottom: 1.35rem;
}
.next-steps ol { list-style: none; margin: 0; padding: 0; counter-reset: step; }
.next-steps li {
  counter-increment: step;
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.94rem;
  color: var(--ink-2);
  display: grid;
  grid-template-columns: 1.9rem 1fr;
  gap: 0.6rem;
}
.next-steps li:first-child { border-top: 1px solid var(--line); }
.next-steps li::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--accent);
  font-style: italic;
  font-size: 1.05rem;
  color: var(--magenta);
  line-height: 1.5;
}

/* A pull quote, set as one. The tinted rounded panel made it read as another
   component rather than as Amanda talking. */
.aside-quote {
  position: relative;
  margin: clamp(2rem, 3.5vw, 2.75rem) 0 0;
  padding-left: 1.5rem;
}
.aside-quote::before {
  content: "";
  position: absolute;
  left: 0; top: 0.35rem; bottom: 2.5rem;
  width: 2px;
  border-radius: 2px;
  background: var(--magenta);
}
.aside-quote blockquote {
  font-family: var(--accent);
  font-style: italic;
  font-size: clamp(1.15rem, 1.7vw, 1.4rem);
  line-height: 1.4;
  color: var(--ink);
}
.aside-quote figcaption {
  margin-top: 1rem;
  font-family: var(--display);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-4);
}

.location-note {
  margin-top: 1.85rem;
  font-size: 0.82rem;
  color: var(--ink-4);
}
.location-note a { color: var(--magenta); }

/* ---------- Fields ---------- */
.field { display: flex; flex-direction: column; gap: 0.45rem; }
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.field label {
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.field label .req { color: var(--magenta); }

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.9rem 1.05rem;
  border: 1px solid var(--line);
  border-radius: var(--r-xs);
  background: var(--blush);
  font-size: 0.96rem;
  color: var(--ink);
  transition: border-color var(--t) var(--soft), background-color var(--t) var(--soft),
              box-shadow var(--t) var(--soft);
}
.field textarea { resize: vertical; min-height: 140px; line-height: 1.55; }
.field select { appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%237A6C75' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  padding-right: 2.5rem;
}
.field input::placeholder, .field textarea::placeholder { color: var(--ink-4); }

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--magenta);
  background: var(--paper);
  box-shadow: 0 0 0 4px var(--magenta-mist);
}
.field[data-invalid="true"] input,
.field[data-invalid="true"] select,
.field[data-invalid="true"] textarea { border-color: #C62222; }

.field__error { font-size: 0.78rem; color: #C62222; display: none; }
.field[data-invalid="true"] .field__error { display: block; }

/* Spam honeypot, visually removed but not display:none */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-status {
  display: none;
  margin-top: 1.25rem;
  padding: 0.95rem 1.15rem;
  border-radius: var(--r-xs);
  font-size: 0.92rem;
}
.form-status.is-visible { display: block; }
.form-status.is-error { background: #FDECEC; color: #A81C1C; }

.is-submitting { opacity: 0.6; pointer-events: none; }

/* ==========================================================================
   Enquiry wizard
   One question per screen. The panel is the single card left on the site and
   it earns it: it is a distinct surface you are working inside, not a box
   drawn around some text.
   ========================================================================== */
.wizard {
  padding: clamp(1.6rem, 3.2vw, 2.6rem);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper);
}

.wiz__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1.15rem;
}
.wiz__counter {
  font-family: var(--display);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-4);
  white-space: nowrap;
}
.wiz__counter b { color: var(--ink); }

.wiz__progress {
  height: 3px;
  border-radius: var(--r-pill);
  background: var(--line-2);
  overflow: hidden;
  margin-bottom: clamp(1.75rem, 3vw, 2.5rem);
}
/* Scaled rather than widened, so advancing a step never triggers layout. */
.wiz__bar {
  display: block;
  height: 100%;
  width: 100%;
  border-radius: inherit;
  background: var(--magenta);
  transform: scaleX(0.2);
  transform-origin: left;
  transition: transform 0.6s var(--ease);
}

.wiz__body { position: relative; }
.wiz__step { display: none; border: 0; padding: 0; margin: 0; min-width: 0; }
.wiz__step.is-active { display: block; animation: wiz-in 0.42s var(--ease); }
@keyframes wiz-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .wiz__step.is-active { animation: none; }
}

.wiz__q { display: block; margin-bottom: 1.6rem; padding: 0; }
.wiz__q-num {
  display: block;
  font-family: var(--display);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--magenta);
  margin-bottom: 0.85rem;
}
.wiz__q-title {
  display: block;
  font-family: var(--display);
  font-size: clamp(1.5rem, 2.8vw, 2.05rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--ink);
}
.wiz__q-sub {
  display: block;
  margin-top: 0.7rem;
  color: var(--ink-3);
  font-size: 0.94rem;
  line-height: 1.55;
}

/* ---------- Options ---------- */
.wiz__options { display: grid; grid-template-columns: 1fr 1fr; gap: 0.7rem; }
.wiz__options--stack { grid-template-columns: 1fr; }

.wiz__opt { display: block; cursor: pointer; }
.wiz__opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.wiz__box {
  position: relative;
  display: block;
  height: 100%;
  padding: 1.05rem 3.1rem 1.05rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--blush);
  transition: border-color var(--t) var(--soft), background-color var(--t) var(--soft);
}
.wiz__box--compact { padding-block: 0.95rem; }
.wiz__opt:hover .wiz__box { border-color: var(--magenta-soft); background: var(--magenta-mist); }
.wiz__opt-label {
  display: block;
  font-family: var(--display);
  font-size: 0.98rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.wiz__opt-desc {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.85rem;
  line-height: 1.45;
  color: var(--ink-3);
}
.wiz__tick {
  position: absolute;
  top: 50%;
  right: 1.1rem;
  transform: translateY(-50%);
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: #fff
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
    center / 0 0 no-repeat;
  transition: border-color var(--t) var(--soft), background-color var(--t) var(--soft),
              background-size var(--t) var(--ease);
}
.wiz__opt input:checked + .wiz__box {
  border-color: var(--magenta);
  background: var(--magenta-mist);
}
.wiz__opt input:checked + .wiz__box .wiz__tick {
  border-color: var(--magenta);
  background-color: var(--magenta);
  background-size: 12px 12px;
}
.wiz__opt input:focus-visible + .wiz__box {
  border-color: var(--magenta);
  outline: 2px solid var(--magenta);
  outline-offset: 3px;
}

/* ---------- Text steps ---------- */
.wiz__row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
.wiz__step .field[data-invalid="true"] input,
.wiz__step .field[data-invalid="true"] textarea { border-color: #C62222; }

.wiz__err {
  display: none;
  margin-top: 1.1rem;
  font-size: 0.86rem;
  color: #C62222;
}
.wiz__step.show-error .wiz__err { display: block; }

/* ---------- Controls ---------- */
.wiz__foot {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: clamp(1.75rem, 3vw, 2.25rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--line-2);
}
.wiz__back {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  background: none;
  border: 0;
  padding: 0.5rem 0;
  cursor: pointer;
  font-family: var(--display);
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--ink-3);
  transition: color var(--t) var(--soft);
}
.wiz__back:hover { color: var(--magenta); }
.wiz__back svg { transition: transform var(--t-mv) var(--ease); }
.wiz__back:hover svg { transform: translateX(-3px); }
.wiz__hint {
  margin-left: auto;
  font-size: 0.8rem;
  color: var(--ink-4);
}
.wiz__next, .wiz__submit { flex-shrink: 0; }
/* The .btn display rule outranks the UA [hidden] rule, so restore it. */
.btn[hidden], .wiz__back[hidden], .wiz__foot[hidden], .wiz__done[hidden] { display: none; }

/* ---------- Done ---------- */
.wiz__done { text-align: center; padding: clamp(1rem, 3vw, 2rem) 0 0.5rem; }
/* Focused programmatically so screen readers land on it. It is a status
   region, not a control, so it should not draw a focus ring around itself. */
.wiz__done:focus, .wiz__done:focus-visible { outline: none; }
.wiz__done-mark {
  width: 56px; height: 56px;
  margin: 0 auto 1.5rem;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--magenta);
  color: #fff;
  animation: wiz-pop 0.55s cubic-bezier(0.2, 1.2, 0.4, 1);
}
@keyframes wiz-pop {
  from { transform: scale(0.5); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .wiz__done-mark { animation: none; }
}
.wiz__done h2 { font-size: clamp(1.5rem, 2.6vw, 2.1rem); margin-bottom: 0.85rem; }
.wiz__done > p {
  max-width: 27rem;
  margin: 0 auto;
  color: var(--ink-2);
}
.wiz__done a:not(.btn) { color: var(--magenta); }
.wiz__done-call { margin-top: 2rem; }
.wiz__done-call .btn__label,
.wiz__done-call .btn__arrow { color: #fff; }
.wiz__done-lines {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 2rem;
}
.wiz__done-lines a {
  flex: 1 1 12rem;
  padding: 0.95rem 1.15rem;
  border-radius: var(--r);
  background: var(--blush);
  color: var(--ink);
  text-align: left;
  transition: background-color var(--t) var(--soft);
}
.wiz__done-lines a:hover { background: var(--magenta-mist); }
.wiz__done-lines small {
  display: block;
  font-family: var(--display);
  font-size: 0.66rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 0.3rem;
}
.wiz__done-lines b {
  font-family: var(--display);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  overflow-wrap: anywhere;
}

/* ==========================================================================
   Footer
   ========================================================================== */
.footer {
  background: var(--blush);
  padding-block: clamp(3rem, 5vw, 4.25rem) 2rem;
}
/* Four columns since the service pages landed: brand, explore, what we do,
   contact. The brand column keeps the extra width. */
.footer__grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1.1fr 1fr;
  gap: clamp(2rem, 4vw, 3.5rem);
}
.footer__brand img { height: 62px; width: auto; margin-bottom: 1.25rem; }
.footer__tagline {
  font-family: var(--accent);
  font-style: italic;
  font-size: 1.15rem;
  color: var(--magenta);
  margin-bottom: 0.9rem;
}
.footer__brand p { font-size: 0.92rem; color: var(--ink-3); max-width: 24rem; }

.footer h4 {
  font-family: var(--display);
  font-size: 0.7rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink-4);
  margin-bottom: 1.25rem;
}
.footer ul { list-style: none; padding: 0; display: grid; gap: 0.7rem; }
/* Was animating padding-left, which relaid out the column on every frame and
   dragged the neighbouring links with it. Transform moves the same distance
   for free and touches nothing else. */
.footer li a, .footer address a {
  display: inline-block;
  font-size: 0.94rem;
  color: var(--ink-2);
  transition: color var(--t) var(--soft), transform var(--t-mv) var(--ease);
}
.footer li a:hover, .footer address a:hover {
  color: var(--magenta);
  transform: translateX(4px);
}
.footer address { font-style: normal; display: grid; gap: 0.7rem; font-size: 0.94rem; }

.footer__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: clamp(2.5rem, 4vw, 3.5rem);
  padding-top: 1.6rem;
  border-top: 1px solid var(--line);
  font-size: 0.83rem;
  color: var(--ink-4);
}
.footer__credit { color: var(--ink-4); }
.footer__credit a {
  color: var(--ink-3, var(--ink-4));
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color var(--t) var(--soft), border-color var(--t) var(--soft);
}
.footer__credit a:hover { color: var(--magenta); border-bottom-color: currentColor; }

.footer__social { display: flex; gap: 0.6rem; }
.footer__social a {
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border: 1px solid var(--line);
  border-radius: 50%;
  color: var(--ink-2);
  background: #fff;
  transition: background-color var(--t) var(--soft), color var(--t) var(--soft),
              border-color var(--t) var(--soft), transform var(--t-mv) var(--ease);
}
.footer__social a:hover {
  border-color: var(--magenta);
  background: var(--magenta);
  color: #fff;
  transform: translateY(-3px);
}
.footer__social a:hover svg { transform: none; }

/* ==========================================================================
   Scroll reveal
   ========================================================================== */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.75s var(--soft), transform 0.85s var(--expo);
}
.reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

/* Skip link */
.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background: var(--plum);
  color: #fff;
}
.skip:focus { left: 0; }

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 1080px) {
  /* The vertical dividers only make sense in a single row. Once the stats
     wrap, each tile carries its own rule instead. */
  .hero__proof { grid-template-columns: repeat(2, 1fr); gap: 0; border-top: 0; }
  .hero__proof > div,
  .hero__proof > div + div {
    padding: 1.35rem 0;
    border-top: 1px solid var(--line);
  }
  .hero__proof > div:nth-child(even) { padding-left: clamp(1.25rem, 4vw, 2.5rem); }
  .hero__proof > div + div::before { content: none; }

  .page-hero__rail { grid-template-columns: repeat(2, 1fr); }
  .footer__grid { grid-template-columns: repeat(3, 1fr); }
  .footer__brand { grid-column: 1 / -1; }

  /* Six across three is too tight here, but two still reads as a set. */
  .caps__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  /* Flex keeps the mark hard-left and the burger hard-right at every width,
     rather than relying on an empty middle grid track. */
  .header__inner { display: flex; justify-content: space-between; gap: 1rem; }
  .nav, .header__phone, .header__actions > .btn { display: none; }
  .header__actions { justify-self: auto; gap: 0.5rem; }
  .burger { display: flex; }
  html { scroll-padding-top: 86px; }

  /* "Working alongside" sits on its own line, the four marks share one row. */
  .partners__inner { flex-direction: column; align-items: flex-start; gap: 1.1rem; }
  .partners__label { max-width: none; }
  .partners__list {
    width: 100%;
    flex-wrap: nowrap;
    justify-content: space-between;
    gap: 1rem;
  }
  .partners__list li { padding: 0.75rem 1rem; }
  .partners__list img { height: 30px; }
  .partners__list img[data-tall] { height: 40px; }

  .section-head--split { grid-template-columns: 1fr; align-items: start; gap: 1.25rem; }
  .page-hero__top { grid-template-columns: 1fr; gap: 1.25rem; align-items: start; }
  .footer__grid { grid-template-columns: repeat(2, 1fr); }

  /* .onset__grid collapses too, but its base rule is declared further down
     the file than this query, so the override has to live at the very bottom
     with the rest of the on-set block. See the note there. */
  /* Stacked single-column left the small glyph alone on a wide row with a big
     empty gap beside it. Lay each card out as glyph-left, copy-right so the
     text fills the width and the set reads tighter. */
  .caps__grid { grid-template-columns: 1fr; }
  /* The glyph used to hold its own column all the way down the card, which
     left every heading and paragraph indented and a channel of dead space
     running down the right. It now shares the top row with the role label and
     the copy below runs the full width of the column. */
  .cap {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: 0.85rem;
    row-gap: 0.45rem;
    align-items: center;
    padding: clamp(1.15rem, 4vw, 1.5rem) 0;
  }
  .cap__gfx { grid-column: 1; grid-row: 1; margin: 0; }
  .cap__role { grid-column: 2; grid-row: 1; }
  .cap h3,
  .cap > p:not(.cap__role) { grid-column: 1 / -1; max-width: none; }
  .feature__grid { grid-template-columns: 1fr; }
  .feature__media { order: -1; }
  .feature__stack { max-width: 30rem; }

  .about__grid { grid-template-columns: 1fr; }
  .about__media { max-width: 25rem; }

  .contact__grid { grid-template-columns: 1fr; }
  .contact__aside { order: 2; }
}

@media (max-width: 620px) {
  body { font-size: 1rem; }
  /* The mobile drawer already carries the CTA, so the header keeps just the mark. */
  .header__actions > .btn { display: none; }

  .hero__proof { grid-template-columns: 1fr; }
  .hero__proof > div:nth-child(even) { padding-left: 0; }

  .page-hero__rail { grid-template-columns: 1fr; }

  /* The overlap needs room to breathe. Below this it just crowds. */
  .feature__stack { padding: 0; }
  .feature__inset {
    position: static;
    width: 100%;
    aspect-ratio: 16 / 10;
    border: 0;
    border-radius: var(--r-lg);
    margin-top: 0.85rem;
    box-shadow: none;
  }

  .footer__grid { grid-template-columns: 1fr; }
  .footer__bottom { flex-direction: column; align-items: flex-start; }
  /* Keep all four marks on one line even on the narrowest phones. */
  .partners__list { gap: 0.5rem; }
  .partners__list li { padding: 0.6rem 0.7rem; border-radius: var(--r-xs); }
  .partners__list img { height: 24px; }
  .partners__list img[data-tall] { height: 34px; }

  .btn-row .btn { flex: 1 1 100%; }
  .band-round { border-radius: var(--r-lg); margin-inline: 0; }

  .caps__grid { padding-inline: 0.65rem; }

  .wiz__options { grid-template-columns: 1fr; }
  .wiz__row { grid-template-columns: 1fr; }
  .wiz__foot { flex-wrap: wrap; }
  .wiz__hint { order: 3; width: 100%; margin-left: 0; }
  .wiz__next, .wiz__submit { flex: 1; }
  .cases__foot .btn { width: 100%; }
}

/* ===================== On set / reels ===================== */
.onset__grid {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  /* Stretch, not centre, so the copy column runs the full height of the reels
     beside it and the diagram fills that space rather than floating low. */
  align-items: stretch;
}
/* The copy is a flex column: the intro sits at the top, then the flow diagram
   grows to take up whatever height is left, centring itself in it. That is what
   lines the bottom of the left column up with the bottom of the two reels. */
.onset__copy { display: flex; flex-direction: column; }
/* Dialled down from the page's default h2 scale. At laptop widths the full
   size ran to three lines and, with the lede under it, pushed the bottom of
   this column well past the bottom of the two reels beside it. Two lines and
   a slightly tighter lede land the two columns level. */
.onset__copy h2 {
  margin: 0.9rem 0 1rem;
  max-width: 19ch;
  font-size: clamp(1.9rem, 3vw, 2.65rem);
}
.onset__copy .lede { max-width: 42ch; font-size: 1rem; line-height: 1.55; }

/* ---------- The flow graphic ----------
   The model, drawn. This replaced three paragraphs and a two-item stat row
   that all said the same thing in words. A brief goes in on the left, OM
   carries it, four specialist lines come out the right, and a pulse runs the
   whole route on a loop.

   The pulses are a second copy of each path with a short dash sliding along
   it. pathLength="100" normalises every path to 100 units, so one set of
   keyframes drives lines of completely different lengths — without it each
   curve would need its own dash maths. */
.flow {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin: clamp(1.6rem, 3vw, 2.2rem) 0 0;
  padding-top: clamp(1.6rem, 3vw, 2.4rem);
  border-top: 1px solid var(--line);
}
.flow__svg { display: block; width: 100%; height: auto; max-width: 35rem; }

.flow__chip { fill: none; stroke: rgba(180, 0, 154, 0.3); stroke-width: 1.3; }
.flow__chip-t {
  fill: var(--magenta);
  font-family: var(--display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-anchor: middle;
}

/* A magenta-tinted hairline rather than the grey rule colour. At this weight
   grey read as a wireframe someone forgot to style. */
.flow__wire { fill: none; stroke: rgba(180, 0, 154, 0.26); stroke-width: 1.5; }
.flow__pulse {
  fill: none;
  stroke: var(--magenta);
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-dasharray: 9 100;
  opacity: 0;
}

.flow__halo { fill: var(--magenta); stroke: none; opacity: 0.07; }
.flow__hub { fill: var(--magenta); stroke: none; }
.flow__hub-t {
  fill: #fff;
  font-family: var(--display);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  text-anchor: middle;
}
.flow__ping {
  fill: none;
  stroke: var(--magenta);
  stroke-width: 1.4;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}

.flow__node { fill: var(--magenta); stroke: none; opacity: 0.3; transform-box: fill-box; transform-origin: center; }
.flow__out {
  fill: var(--ink-2);
  font-family: var(--sans);
  font-size: 13.5px;
  opacity: 0.5;
}

/* One 3.4s cycle drives everything. The brief crosses in the first fifth, the
   hub pings, then the four branches fire a beat apart. */
.flow__pulse--in { animation: flow-in 3.4s linear infinite; }
.flow__ping      { animation: flow-ping 3.4s var(--soft) infinite; }

.flow__pulse--o1, .flow__pulse--o2,
.flow__pulse--o3, .flow__pulse--o4 { animation: flow-out 3.4s linear infinite; }
.flow__node--o1, .flow__node--o2,
.flow__node--o3, .flow__node--o4 { animation: flow-node 3.4s var(--soft) infinite; }
.flow__out--o1, .flow__out--o2,
.flow__out--o3, .flow__out--o4 { animation: flow-lit 3.4s var(--soft) infinite; }

.flow__pulse--o2, .flow__node--o2, .flow__out--o2 { animation-delay: 0.09s; }
.flow__pulse--o3, .flow__node--o3, .flow__out--o3 { animation-delay: 0.18s; }
.flow__pulse--o4, .flow__node--o4, .flow__out--o4 { animation-delay: 0.27s; }

@keyframes flow-in {
  0%        { stroke-dashoffset: 9;    opacity: 0; }
  5%        { opacity: 1; }
  20%       { stroke-dashoffset: -100; opacity: 1; }
  24%, 100% { stroke-dashoffset: -100; opacity: 0; }
}
@keyframes flow-ping {
  0%, 19%   { transform: scale(0.8);  opacity: 0; }
  27%       { opacity: 0.5; }
  48%, 100% { transform: scale(1.16); opacity: 0; }
}
@keyframes flow-out {
  0%, 26%   { stroke-dashoffset: 9;    opacity: 0; }
  31%       { opacity: 1; }
  56%       { stroke-dashoffset: -100; opacity: 1; }
  60%, 100% { stroke-dashoffset: -100; opacity: 0; }
}
@keyframes flow-node {
  0%, 53%   { transform: scale(1);    opacity: 0.3; }
  61%       { transform: scale(1.45); opacity: 1; }
  86%, 100% { transform: scale(1);    opacity: 0.3; }
}
@keyframes flow-lit {
  0%, 53%   { opacity: 0.5; }
  61%, 82%  { opacity: 1; }
  96%, 100% { opacity: 0.5; }
}

@media (prefers-reduced-motion: reduce) {
  .flow__pulse, .flow__ping { animation: none; opacity: 0; }
  .flow__node { animation: none; opacity: 1; }
  .flow__out  { animation: none; opacity: 1; }
}

.flow figcaption {
  margin-top: 1.15rem;
  font-size: 0.9rem;
  color: var(--ink-3);
  max-width: 40ch;
}

.reels__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.8rem, 1.6vw, 1.2rem);
}

.reel {
  position: relative;
  display: block;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--ink);
  cursor: pointer;
  aspect-ratio: 9 / 16;
  isolation: isolate;
  /* The tile clips its own contents, so a cross-fading shadow layer would be
     cut off inside it. It carries the shadow at rest instead and the hover is
     transform only, the same deal the rest of the page makes. */
  box-shadow: 0 22px 44px -28px rgba(26, 14, 23, 0.55);
  transition: transform var(--t) var(--ease);
}
.reel:hover { transform: translateY(-4px); }
.reel:focus-visible { outline: 2px solid var(--magenta); outline-offset: 3px; }

.reel img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.7s var(--ease), opacity var(--t) var(--soft);
}
.reel:hover img { transform: scale(1.05); opacity: 0.92; }

.reel::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(20, 8, 17, 0.78) 0%, rgba(20, 8, 17, 0.12) 42%, rgba(20, 8, 17, 0) 68%);
  z-index: 1;
}

.reel__play {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  padding-left: 3px;
  border-radius: 50%;
  color: var(--magenta);
  background: rgba(255, 255, 255, 0.94);
  box-shadow: 0 10px 30px -8px rgba(20, 8, 17, 0.6);
  transition: transform var(--t) var(--ease), background-color var(--t) var(--soft), color var(--t) var(--soft);
}
.reel:hover .reel__play { transform: translate(-50%, -50%) scale(1.08); background: var(--magenta); color: #fff; }

.reel__tag {
  position: absolute;
  top: 0.9rem;
  left: 0.9rem;
  z-index: 2;
  font-family: var(--display);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #fff;
  padding: 0.34rem 0.6rem;
  border-radius: 999px;
  background: rgba(180, 0, 154, 0.85);
  backdrop-filter: blur(4px);
}

.reel__cap {
  position: absolute;
  left: 1rem;
  right: 1rem;
  bottom: 1rem;
  z-index: 2;
  font-size: 0.86rem;
  line-height: 1.35;
  color: rgba(255, 255, 255, 0.94);
  text-align: left;
  text-wrap: balance;
}

/* ---- reel lightbox ---- */
.rbox {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 2.5rem);
}
.rbox[hidden] { display: none; }

.rbox__scrim {
  position: absolute;
  inset: 0;
  background: rgba(16, 6, 14, 0.82);
  backdrop-filter: blur(6px);
  animation: rbox-fade 0.25s var(--ease);
}
@keyframes rbox-fade { from { opacity: 0; } to { opacity: 1; } }

.rbox__panel {
  position: relative;
  width: min(420px, 100%);
  animation: rbox-rise 0.3s var(--ease);
}
@keyframes rbox-rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }

.rbox__name {
  display: block;
  margin-bottom: 0.75rem;
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
  text-align: center;
}

.rbox__stage {
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #000;
  box-shadow: 0 30px 70px -30px rgba(0, 0, 0, 0.8);
}
.rbox__stage iframe {
  display: block;
  width: 100%;
  height: min(78vh, 720px);
  border: 0;
  background: #fff;
}

.rbox__x {
  position: absolute;
  top: -3rem;
  right: 0;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  font-size: 1.7rem;
  line-height: 1;
  color: #fff;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 50%;
  cursor: pointer;
  transition: background-color var(--t) var(--soft);
}
.rbox__x:hover { background: rgba(255, 255, 255, 0.24); }

@media (max-width: 560px) {
  .reels__grid { gap: 0.8rem; }
  .reel__cap { font-size: 0.78rem; }
  .reel__play { width: 52px; height: 52px; }
  .rbox__x { top: auto; bottom: -3.2rem; right: 50%; transform: translateX(50%); }
}

/* ---------- On set, responsive ----------
   This whole block was appended after the site's responsive section, so the
   two-column .onset__grid was outranking the stacking rule up there by source
   order alone and the section stayed in two cramped columns on a phone. The
   override belongs here, below the base rule, not up with the others.
   Anything else added to the trailing block needs its own query down here
   for the same reason. */
@media (max-width: 900px) {
  .onset__grid { grid-template-columns: 1fr; gap: 2.25rem; align-items: start; }
  .onset__copy h2 { max-width: 20ch; }
  .flow__svg { max-width: 30rem; }
}

/* ==========================================================================
   INTERIOR PAGES
   The services hub, the six service pages, case studies and about.

   Everything here follows the rules the homepage already set: ruled rather
   than boxed, shadow only on things that genuinely float, and only colour,
   opacity and transform ever transitioned. The motion is drawn in SVG and
   CSS, no library, and all of it stops dead under prefers-reduced-motion.

   NOTE ON SOURCE ORDER: this block sits after the site's responsive section,
   so a base rule here outranks a matching rule in the breakpoints above by
   source order alone. Every breakpoint these components need lives at the
   BOTTOM of this block, not up there. Same trap as the on-set block.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Page hero, media variant
   The contact page's plum hero, with a photograph pushed a long way under it
   so the band reads as a place rather than a coloured rectangle. Type sits at
   full contrast because the scrim, not the image opacity, does the work.
   -------------------------------------------------------------------------- */
.page-hero { position: relative; isolation: isolate; overflow: hidden; }
.page-hero > .wrap { position: relative; z-index: 3; }

.page-hero--media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: var(--photo);
  background-size: cover;
  background-position: var(--photo-pos, center);
  filter: grayscale(0.34) contrast(1.06) brightness(1.06);
  transform: scale(1.05);
}
/* The wedge carries the left column at full contrast and then clears, so the
   photograph is actually visible on the right rather than being a texture
   nobody can make out. */
.page-hero--media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(100deg,
      rgba(22, 0, 15, 0.95) 0%,
      rgba(22, 0, 15, 0.91) 34%,
      rgba(22, 0, 15, 0.8) 58%,
      rgba(22, 0, 15, 0.72) 82%,
      rgba(22, 0, 15, 0.76) 100%),
    linear-gradient(0deg, var(--plum) 0%, rgba(22, 0, 15, 0.5) 14%, rgba(22, 0, 15, 0) 48%),
    linear-gradient(180deg, rgba(22, 0, 15, 0.5) 0%, rgba(22, 0, 15, 0) 26%),
    radial-gradient(78% 88% at 96% 2%, rgba(238, 58, 172, 0.34) 0%, rgba(238, 58, 172, 0) 62%);
}
/* A hero carrying a drawn graphic in its right-hand column needs the photo
   pushed further back, or the two fight. */
.page-hero--media:has(.page-hero__art)::before { opacity: 0.42; }

/* On phones the faded background photo reads as murk behind the heading rather
   than as imagery. Drop it and let the header sit on the clean plum (same as
   the home/contact heroes), keeping only the drawn art where a page has one. */
@media (max-width: 760px) {
  .page-hero--media::before,
  .page-hero--media::after { display: none; }
}

/* The same raked magenta wash and hairline verticals the home hero uses, so
   an interior header is recognisably cut from the same thing. */
.page-hero__fx { position: absolute; inset: 0; z-index: 2; overflow: hidden; pointer-events: none; }
.page-hero__fx > span { position: absolute; display: block; }
.page-hero__wash {
  inset: 0;
  background: linear-gradient(115deg,
    rgba(180, 0, 154, 0.5) 0%, rgba(180, 0, 154, 0.26) 42%, rgba(180, 0, 154, 0) 72%);
  mix-blend-mode: screen;
  opacity: 0.4;
}
.page-hero__rules {
  inset: 0;
  background: repeating-linear-gradient(90deg,
    rgba(255, 255, 255, 0.07) 0 1px, transparent 1px 16.666%);
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 40%, #000 100%);
          mask-image: linear-gradient(90deg, transparent 0%, #000 40%, #000 100%);
}
.page-hero__ring {
  width: clamp(300px, 34vw, 520px);
  aspect-ratio: 1;
  right: -8%;
  top: -34%;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 50%;
  animation: heroFloat 20s var(--soft) infinite alternate;
}
@media (prefers-reduced-motion: reduce) {
  .page-hero__ring { animation: none; }
}

/* ---------- Breadcrumbs ---------- */
.crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: clamp(1.25rem, 2.4vw, 1.85rem);
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--on-dark-dim);
}
.crumbs a { color: rgba(255, 255, 255, 0.72); transition: color var(--t) var(--soft); }
.crumbs a:hover { color: var(--magenta-lit); }
.crumbs span[aria-current] { color: #fff; }
.crumbs li { list-style: none; display: flex; align-items: center; gap: 0.5rem; }
.crumbs ol { display: contents; margin: 0; padding: 0; }
.crumbs li + li::before {
  content: "";
  width: 14px;
  height: 1px;
  background: rgba(255, 255, 255, 0.28);
}

/* ---------- Hero split: copy on the left, a drawn graphic on the right ---------- */
.page-hero__split {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
  padding-bottom: clamp(2.25rem, 4vw, 3rem);
}
.page-hero__split .lede { color: var(--on-dark); margin-top: 1.35rem; }
.page-hero__split h1 { margin-top: 1.1rem; font-size: clamp(2.2rem, 4.8vw, 3.9rem); }
.page-hero .btn-row { margin-top: clamp(1.6rem, 2.6vw, 2.1rem); }

/* --------------------------------------------------------------------------
   2. The art system
   One vocabulary shared by every service page: hairline wires, magenta nodes,
   a dash travelling a path, translucent plates. Each page then draws its own
   idea out of those primitives rather than getting a stock icon.
   -------------------------------------------------------------------------- */
.art {
  display: block;
  width: 100%;
  max-width: 30rem;
  margin-inline: auto;
  overflow: visible;
}
.art__wire { fill: none; stroke: rgba(255, 255, 255, 0.2); stroke-width: 1.4; }
.art__wire--soft { stroke: rgba(255, 255, 255, 0.11); }
.art__pulse {
  fill: none;
  stroke: var(--magenta-lit);
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-dasharray: 10 100;
  opacity: 0;
}
.art__plate {
  fill: rgba(255, 255, 255, 0.05);
  stroke: rgba(255, 255, 255, 0.16);
  stroke-width: 1;
}
.art__node { fill: var(--magenta-lit); stroke: none; transform-box: fill-box; transform-origin: center; }
.art__ring { fill: none; stroke: rgba(255, 255, 255, 0.22); stroke-width: 1.3; transform-box: fill-box; transform-origin: center; }
.art__t {
  fill: rgba(255, 255, 255, 0.6);
  font-family: var(--display);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.13em;
}
.art__t--mid { text-anchor: middle; }
.art__lbl {
  fill: rgba(255, 255, 255, 0.82);
  font-family: var(--sans);
  font-size: 12.5px;
}
/* The one line that draws itself. Kept off .art__pulse because that carries a
   short travelling dash, and this is the whole path being revealed. */
.art__trend {
  fill: none;
  stroke: var(--magenta-lit);
  stroke-width: 2.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* A filled cell, for the grids that need one after .art__plate's outline. */
.a-day { fill: rgba(255, 255, 255, 0.1); stroke: none; }
.a-day--p { fill: var(--magenta-lit); }

/* ---------- 01 Foundations: four satellites locking onto one target ---------- */
/* .art__ring already sets fill-box and a centred origin, so the orbit turns
   about its own centre without the SVG's geometry being restated in CSS. */
.art--found .a-orbit { animation: a-orbit 16s linear infinite; }
.art--found .a-orbit--r { animation-duration: 22s; animation-direction: reverse; }
.art--found .a-sat { animation: a-lock 4.2s var(--soft) infinite; }
.art--found .a-sat--2 { animation-delay: 0.5s; }
.art--found .a-sat--3 { animation-delay: 1s; }
.art--found .a-sat--4 { animation-delay: 1.5s; }
.art--found .a-core { animation: a-core 4.2s var(--soft) infinite; }
.art--found .a-tick { opacity: 0; animation: a-tick 4.2s var(--soft) infinite; }
.art--found .a-tick--2 { animation-delay: 0.32s; }
.art--found .a-tick--3 { animation-delay: 0.64s; }
@keyframes a-orbit { to { transform: rotate(360deg); } }
@keyframes a-lock {
  0%, 100% { transform: scale(0.7); opacity: 0.45; }
  55%, 80% { transform: scale(1);   opacity: 1; }
}
@keyframes a-core {
  0%, 44%   { transform: scale(0.86); opacity: 0.55; }
  62%, 88%  { transform: scale(1);    opacity: 1; }
  100%      { transform: scale(0.86); opacity: 0.55; }
}
@keyframes a-tick {
  0%, 30%   { opacity: 0; }
  44%, 88%  { opacity: 1; }
  100%      { opacity: 0; }
}

/* ---------- 02 Social: a month filling itself, week by week ---------- */
.art--social .a-day { animation: a-day 7s var(--soft) infinite; }
.art--social .a-day--2 { animation-delay: 0.5s; }
.art--social .a-day--3 { animation-delay: 1s; }
.art--social .a-day--4 { animation-delay: 1.5s; }
.art--social .a-day--5 { animation-delay: 2s; }
.art--social .a-day--6 { animation-delay: 2.5s; }
.art--social .a-day--7 { animation-delay: 3s; }
.art--social .a-day--8 { animation-delay: 3.5s; }
.art--social .a-sweep { animation: a-sweep 7s var(--soft) infinite; }
@keyframes a-day {
  0%, 4%    { opacity: 0.25; }
  12%, 74%  { opacity: 1; }
  86%, 100% { opacity: 0.25; }
}
@keyframes a-sweep {
  0%        { transform: translateY(0); opacity: 0; }
  6%        { opacity: 0.75; }
  62%       { transform: translateY(78px); opacity: 0.75; }
  72%, 100% { transform: translateY(78px); opacity: 0; }
}

/* ---------- 03 Production: a playhead crossing a strip of frames ---------- */
.art--prod .a-frame { animation: a-frame 6s var(--soft) infinite; }
.art--prod .a-frame--2 { animation-delay: 0.75s; }
.art--prod .a-frame--3 { animation-delay: 1.5s; }
.art--prod .a-frame--4 { animation-delay: 2.25s; }
.art--prod .a-head { animation: a-head 6s linear infinite; }
.art--prod .a-rec { animation: a-rec 2s var(--soft) infinite; }
@keyframes a-frame {
  0%, 6%    { opacity: 0.28; }
  14%, 52%  { opacity: 1; }
  64%, 100% { opacity: 0.28; }
}
@keyframes a-head {
  0%        { transform: translateX(0); opacity: 0; }
  4%        { opacity: 1; }
  84%       { transform: translateX(238px); opacity: 1; }
  92%, 100% { transform: translateX(238px); opacity: 0; }
}
@keyframes a-rec {
  0%, 100% { opacity: 0.4; transform: scale(0.8); }
  46%      { opacity: 1;   transform: scale(1); }
}

/* ---------- 04 Pipeline: names in, one booked conversation out ---------- */
.art--pipe .a-lead { opacity: 0; animation: a-lead 4.4s var(--soft) infinite; }
.art--pipe .a-lead--2 { animation-delay: 0.55s; }
.art--pipe .a-lead--3 { animation-delay: 1.1s; }
.art--pipe .a-lead--4 { animation-delay: 1.65s; }
/* A group, so it needs its own box and origin before it can be scaled: an SVG
   <g> defaults to rotating and scaling about the user-space origin. */
.art--pipe .a-out {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: a-out 4.4s var(--soft) infinite;
}
.art--pipe .a-wall { animation: a-wall 4.4s var(--soft) infinite; }
@keyframes a-lead {
  0%        { transform: translateY(0);    opacity: 0; }
  10%       { opacity: 0.95; }
  46%       { transform: translateY(52px); opacity: 0.95; }
  62%, 100% { transform: translateY(66px); opacity: 0; }
}
@keyframes a-out {
  0%, 48%   { opacity: 0; transform: translateY(0) scale(0.7); }
  62%, 88%  { opacity: 1; transform: translateY(0) scale(1); }
  100%      { opacity: 0; transform: translateY(0) scale(0.7); }
}
@keyframes a-wall {
  0%, 44%   { opacity: 0.35; }
  58%, 86%  { opacity: 1; }
  100%      { opacity: 0.35; }
}

/* ---------- 05 Communication: a question in, an answer back the same day ---------- */
.art--talk .a-in  { opacity: 0; animation: a-msg 5.2s var(--soft) infinite; }
.art--talk .a-out2 { opacity: 0; animation: a-msg 5.2s var(--soft) infinite 1.3s; }
.art--talk .a-in2 { opacity: 0; animation: a-msg 5.2s var(--soft) infinite 2.6s; }
.art--talk .a-dot { animation: a-dot 1.4s var(--soft) infinite; }
.art--talk .a-dot--2 { animation-delay: 0.16s; }
.art--talk .a-dot--3 { animation-delay: 0.32s; }
.art--talk .a-clock { animation: a-clock 5.2s linear infinite; transform-box: fill-box; transform-origin: 50% 100%; }
@keyframes a-msg {
  0%        { opacity: 0; transform: translateY(9px); }
  8%, 70%   { opacity: 1; transform: translateY(0); }
  84%, 100% { opacity: 0; transform: translateY(0); }
}
@keyframes a-dot {
  0%, 66%, 100% { transform: translateY(0);    opacity: 0.32; }
  30%           { transform: translateY(-3px); opacity: 1; }
}
@keyframes a-clock { to { transform: rotate(360deg); } }

/* ---------- 06 Growth: the line drawn, then the flags planted ---------- */
.art--grow .a-line { animation: a-draw 6.4s var(--ease) infinite; }
.art--grow .a-bar { transform-box: fill-box; transform-origin: center bottom; animation: a-bar 6.4s var(--ease) infinite; }
.art--grow .a-bar--2 { animation-delay: 0.16s; }
.art--grow .a-bar--3 { animation-delay: 0.32s; }
.art--grow .a-bar--4 { animation-delay: 0.48s; }
.art--grow .a-bar--5 { animation-delay: 0.64s; }
.art--grow .a-flag { opacity: 0; animation: a-flag 6.4s var(--soft) infinite; }
.art--grow .a-flag--2 { animation-delay: 0.5s; }
.art--grow .a-flag--3 { animation-delay: 1s; }
@keyframes a-draw {
  0%        { stroke-dashoffset: 100; }
  38%, 82%  { stroke-dashoffset: 0; }
  100%      { stroke-dashoffset: 100; }
}
@keyframes a-bar {
  0%, 8%    { transform: scaleY(0.16); opacity: 0.4; }
  30%, 80%  { transform: scaleY(1);    opacity: 1; }
  96%, 100% { transform: scaleY(0.16); opacity: 0.4; }
}
@keyframes a-flag {
  0%, 34%   { opacity: 0; transform: translateY(6px); }
  46%, 82%  { opacity: 1; transform: translateY(0); }
  94%, 100% { opacity: 0; transform: translateY(6px); }
}

/* Nothing in the art carries meaning the copy does not already carry, so all
   of it stops rather than degrading to something slower. */
@media (prefers-reduced-motion: reduce) {
  .art * { animation: none !important; }
  .art .art__pulse { opacity: 0; }
  .art .a-sat, .art .a-core, .art .a-tick, .art .a-day,
  .art .a-frame, .art .a-lead, .art .a-out, .art .a-wall,
  .art .a-in, .art .a-in2, .art .a-out2, .art .a-flag, .art .a-bar { opacity: 1; }
  .art .a-sweep, .art .a-head { opacity: 0; }
  .art .a-line { stroke-dashoffset: 0; }
  .art .a-bar { transform: none; }
}

/* --------------------------------------------------------------------------
   3. Service index
   The six services as full-width ruled rows, in the same language as the
   case-study index: number, drawn glyph, name, one line, arrow. A tint
   cross-fades in behind on hover rather than the row growing a border.
   -------------------------------------------------------------------------- */
.sindex { display: grid; border-top: 1px solid var(--line); }

.sindex__row {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: 3.5rem 3.25rem minmax(0, 1fr) minmax(0, 1.05fr) 2.75rem;
  align-items: center;
  gap: clamp(0.75rem, 2vw, 1.75rem);
  padding: clamp(1.35rem, 2.4vw, 1.85rem) clamp(0.75rem, 1.6vw, 1.25rem);
  border-bottom: 1px solid var(--line);
  transition: transform var(--t-mv) var(--ease);
}
/* The tint is a pseudo layer so hover cross-fades opacity rather than
   repainting a background on every frame. */
.sindex__row::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg, var(--magenta-mist) 0%, rgba(251, 237, 246, 0) 78%);
  opacity: 0;
  transition: opacity var(--t) var(--soft);
}
.sindex__row::after {
  content: "";
  position: absolute;
  left: 0; bottom: -1px;
  width: 100%; height: 2px;
  background: var(--magenta);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.65s var(--ease);
}
.sindex__row:hover::before { opacity: 1; }
.sindex__row:hover::after  { transform: scaleX(1); }
.sindex__row:hover { transform: translateX(4px); }

.sindex__n {
  font-family: var(--display);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--ink-4);
  transition: color var(--t) var(--soft);
}
.sindex__row:hover .sindex__n { color: var(--magenta); }
.sindex__gfx { color: var(--magenta); }
.sindex__gfx .gfx { width: 38px; height: 38px; }
.sindex__ttl {
  font-family: var(--display);
  font-size: clamp(1.15rem, 1.9vw, 1.45rem);
  font-weight: 600;
  letter-spacing: -0.024em;
  color: var(--ink);
  line-height: 1.15;
  transition: color var(--t) var(--soft);
}
.sindex__row:hover .sindex__ttl { color: var(--magenta); }
.sindex__ttl small {
  display: block;
  margin-top: 0.3rem;
  font-family: var(--display);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--magenta);
}
.sindex__say { color: var(--ink-2); font-size: 0.95rem; margin: 0; }
.sindex__go {
  justify-self: end;
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  border-radius: 50%;
  border: 1px solid var(--line);
  color: var(--ink-3);
  transition: background-color var(--t) var(--soft), color var(--t) var(--soft),
              border-color var(--t) var(--soft), transform var(--t-mv) var(--ease);
}
.sindex__row:hover .sindex__go {
  background: var(--magenta);
  border-color: var(--magenta);
  color: #fff;
  transform: translateX(3px);
}

/* --------------------------------------------------------------------------
   4. The arc
   The life of an account, drawn along one rail. Built in HTML rather than
   SVG so it can turn from a horizontal rail into a vertical one on a phone
   without redrawing any geometry. A magenta glow travels the rail and each
   node lights as it passes.
   -------------------------------------------------------------------------- */
.arc {
  position: relative;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(0.75rem, 1.8vw, 1.5rem);
  list-style: none;
  margin: clamp(2rem, 4vw, 3rem) 0 0;
  padding: 0;
}
/* The rail itself, plus the travelling light on top of it. */
.arc::before,
.arc::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  top: 7px;
  height: 1px;
}
.arc::before { background: var(--on-dark-line); }
.arc::after {
  background: linear-gradient(90deg,
    rgba(238, 58, 172, 0) 0%,
    rgba(238, 58, 172, 0.95) 46%,
    rgba(238, 58, 172, 0) 100%);
  width: 34%;
  right: auto;
  animation: arc-run 7s var(--soft) infinite;
}
@keyframes arc-run {
  0%   { transform: translateX(-40%); opacity: 0; }
  8%   { opacity: 1; }
  88%  { transform: translateX(310%); opacity: 1; }
  100% { transform: translateX(330%); opacity: 0; }
}
/* The same travelling light down a vertical rail, used once the arc stacks. */
@keyframes arc-run-v {
  0%   { transform: translateY(-30%); opacity: 0; }
  8%   { opacity: 1; }
  88%  { transform: translateY(420%); opacity: 1; }
  100% { transform: translateY(450%); opacity: 0; }
}

.arc__step { position: relative; padding-top: 2.1rem; }
.arc__step::before {
  content: "";
  position: absolute;
  top: 1px;
  left: 0;
  width: 13px; height: 13px;
  border-radius: 50%;
  background: var(--plum);
  border: 1px solid rgba(255, 255, 255, 0.28);
  transition: background-color var(--t) var(--soft), border-color var(--t) var(--soft);
}
.arc__step::after {
  content: "";
  position: absolute;
  top: 4px;
  left: 3px;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--magenta-lit);
  opacity: 0;
  animation: arc-lit 7s var(--soft) infinite;
}
.arc__step:nth-child(2)::after { animation-delay: 0.72s; }
.arc__step:nth-child(3)::after { animation-delay: 1.44s; }
.arc__step:nth-child(4)::after { animation-delay: 2.16s; }
.arc__step:nth-child(5)::after { animation-delay: 2.88s; }
.arc__step:nth-child(6)::after { animation-delay: 3.6s; }
@keyframes arc-lit {
  0%, 4%    { opacity: 0; transform: scale(0.5); }
  12%, 40%  { opacity: 1; transform: scale(1); }
  56%, 100% { opacity: 0; transform: scale(0.5); }
}
/* The eyebrow is a <p>, and .arc__step p sets the body colour and size for
   this block. A single class would lose to it on specificity, which is how
   these labels ended up grey at body size. Same trap as .stage__k, .roles__k
   and .tl__yr below. */
.arc__step .arc__k {
  font-family: var(--display);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--magenta-lit);
  margin-bottom: 0.45rem;
}
.arc__step h3 { font-size: 1.02rem; letter-spacing: -0.02em; margin-bottom: 0.45rem; }
.arc__step p { font-size: 0.88rem; line-height: 1.5; color: var(--on-dark-dim); margin: 0; }

@media (prefers-reduced-motion: reduce) {
  .arc::after { animation: none; opacity: 0; }
  .arc__step::after { animation: none; opacity: 1; }
}

/* --------------------------------------------------------------------------
   5. Stage rail
   How a single service actually runs, week by week. Vertical at every width:
   a hairline down the left with the progress drawn on top of it, and each
   step's marker filling as the line reaches it.
   -------------------------------------------------------------------------- */
.stage { position: relative; list-style: none; margin: 0; padding: 0 0 0 clamp(2.1rem, 4vw, 2.75rem); }
.stage::before,
.stage::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 0.55rem;
  bottom: 1.5rem;
  width: 1px;
}
.stage::before { background: var(--line); }
/* The drawn line. scaleY on a pseudo layer, so the growth costs one transform
   rather than animating a height. */
.stage::after {
  background: var(--magenta);
  transform-origin: top;
  transform: scaleY(0);
  animation: stage-draw 4.5s var(--ease) infinite;
}
@keyframes stage-draw {
  0%        { transform: scaleY(0); opacity: 0.9; }
  56%, 82%  { transform: scaleY(1); opacity: 0.9; }
  96%, 100% { transform: scaleY(1); opacity: 0; }
}

.stage__step { position: relative; padding-bottom: clamp(1.6rem, 3vw, 2.25rem); }
.stage__step:last-child { padding-bottom: 0; }
.stage__step::before {
  content: "";
  position: absolute;
  left: calc(-1 * clamp(2.1rem, 4vw, 2.75rem));
  top: 0.5rem;
  width: 13px; height: 13px;
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--line);
}
.stage__step::after {
  content: "";
  position: absolute;
  left: calc(-1 * clamp(2.1rem, 4vw, 2.75rem) + 3px);
  top: calc(0.5rem + 3px);
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--magenta);
  transform: scale(0);
  animation: stage-dot 4.5s var(--ease) infinite;
}
.stage__step:nth-child(2)::after { animation-delay: 0.34s; }
.stage__step:nth-child(3)::after { animation-delay: 0.68s; }
.stage__step:nth-child(4)::after { animation-delay: 1.02s; }
.stage__step:nth-child(5)::after { animation-delay: 1.36s; }
@keyframes stage-dot {
  0%, 6%    { transform: scale(0); }
  16%, 82%  { transform: scale(1); }
  96%, 100% { transform: scale(0); }
}
.stage__step .stage__k {
  font-family: var(--display);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--magenta);
  margin-bottom: 0.4rem;
}
.stage__step h3 { font-size: clamp(1.05rem, 1.6vw, 1.22rem); margin-bottom: 0.45rem; }
.stage__step p { font-size: 0.95rem; color: var(--ink-2); margin: 0; max-width: 46ch; }

/* On the plum the rail inverts. */
.section--dark .stage::before { background: var(--on-dark-line); }
.section--dark .stage::after { background: var(--magenta-lit); }
.section--dark .stage__step::before { background: var(--plum); border-color: rgba(255, 255, 255, 0.28); }
.section--dark .stage__step::after { background: var(--magenta-lit); }
.section--dark .stage__step .stage__k { color: var(--magenta-lit); }
.section--dark .stage__step p { color: var(--on-dark); }

@media (prefers-reduced-motion: reduce) {
  .stage::after { animation: none; transform: scaleY(1); opacity: 0.35; }
  .stage__step::after { animation: none; transform: scale(1); }
}

/* --------------------------------------------------------------------------
   6. Included list
   What you actually get, as two ruled columns. Ticked, never boxed.
   -------------------------------------------------------------------------- */
.incl {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 clamp(1.75rem, 4vw, 3.5rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
/* A grid, not a flex row of inline text. Run as one inline sentence the bold
   lead-in wraps mid-phrase and the sentence restarts on the next line at a
   random indent, which reads as a broken table. The label gets its own line
   and the sentence sits under it. */
.incl li {
  display: grid;
  grid-template-columns: 19px minmax(0, 1fr);
  gap: 0.25rem 0.8rem;
  padding: clamp(0.9rem, 1.6vw, 1.15rem) 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.94rem;
  line-height: 1.55;
  color: var(--ink-3);
}
/* Everything except the tick sits in the second track, stacked. Without this
   the description would auto-place into column one on the next row. */
.incl li > * { grid-column: 2; }
.incl li strong {
  display: block;
  font-family: var(--display);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  line-height: 1.25;
}
.incl li::before {
  content: "";
  grid-row: 1;
  grid-column: 1;
  width: 19px; height: 19px;
  margin-top: 0.16rem;
  border-radius: 50%;
  background: var(--magenta-mist)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 24 24' fill='none' stroke='%23B4009A' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
    center / 11px 11px no-repeat;
  transition: background-color var(--t) var(--soft);
}
.incl li strong { color: var(--ink); font-weight: 600; }
.section--dark .incl li { color: var(--on-dark); border-bottom-color: var(--on-dark-line); }
.section--dark .incl li strong { color: #fff; }
.section--dark .incl li::before {
  background-color: rgba(238, 58, 172, 0.18);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 24 24' fill='none' stroke='%23EE3AAC' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}

/* What we deliberately do not do. Same rhythm, a rule instead of a tick, so
   the honest half of the page does not read as a warning box. */
.excl { list-style: none; margin: 0; padding: 0; }
.excl li {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--line-2);
  font-size: 0.94rem;
  color: var(--ink-3);
}
.excl li::before {
  content: "";
  flex-shrink: 0;
  width: 19px; height: 19px;
  margin-top: 0.2rem;
  border-radius: 50%;
  background: var(--blush-2);
  box-shadow: inset 0 0 0 1px var(--line);
  position: relative;
}
.excl li span { display: block; }
.excl--dark li { color: var(--on-dark-dim); border-bottom-color: var(--on-dark-line); }
.excl--dark li::before { background: rgba(255, 255, 255, 0.06); box-shadow: inset 0 0 0 1px var(--on-dark-line); }

/* --------------------------------------------------------------------------
   7. Media slot
   An honest placeholder. It is branded rather than a grey box with a cross
   through it, it says exactly what photograph belongs there, and a slow
   magenta sweep keeps it from reading as a broken image. Swap the whole
   element for a <div class="media"> when the real shot lands.
   -------------------------------------------------------------------------- */
.slot {
  position: relative;
  overflow: hidden;
  display: grid;
  place-items: center;
  text-align: center;
  padding: clamp(1.75rem, 4vw, 2.75rem);
  border-radius: var(--r-lg);
  background: var(--blush);
  box-shadow: inset 0 0 0 1px var(--line);
  aspect-ratio: var(--slot-ratio, 4 / 3);
}
.slot::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(90deg, rgba(180, 0, 154, 0.07) 0 1px, transparent 1px),
    linear-gradient(0deg,  rgba(180, 0, 154, 0.07) 0 1px, transparent 1px);
  background-size: 46px 46px;
  -webkit-mask-image: radial-gradient(100% 100% at 50% 50%, #000 0%, transparent 76%);
          mask-image: radial-gradient(100% 100% at 50% 50%, #000 0%, transparent 76%);
}
/* The sweep. One transform on a skewed band, nothing else moves. */
.slot::after {
  content: "";
  position: absolute;
  top: -30%;
  bottom: -30%;
  left: -35%;
  width: 32%;
  background: linear-gradient(90deg,
    rgba(238, 58, 172, 0) 0%, rgba(238, 58, 172, 0.16) 50%, rgba(238, 58, 172, 0) 100%);
  transform: skewX(-14deg);
  animation: slot-sweep 5.5s var(--soft) infinite;
}
@keyframes slot-sweep {
  0%       { transform: translateX(0) skewX(-14deg); }
  62%,100% { transform: translateX(430%) skewX(-14deg); }
}
.slot__inner { position: relative; z-index: 1; max-width: 26rem; }
.slot__ico {
  display: inline-grid;
  place-items: center;
  width: 46px; height: 46px;
  margin-bottom: 0.9rem;
  border-radius: 50%;
  background: #fff;
  color: var(--magenta);
  box-shadow: inset 0 0 0 1px var(--line);
}
.slot__k {
  font-family: var(--display);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--magenta);
  margin-bottom: 0.5rem;
}
.slot__ttl {
  font-family: var(--display);
  font-size: clamp(1.02rem, 1.6vw, 1.2rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin-bottom: 0.45rem;
}
.slot__note { font-size: 0.88rem; line-height: 1.5; color: var(--ink-3); margin: 0; }

/* On the plum. */
.slot--dark { background: rgba(255, 255, 255, 0.035); box-shadow: inset 0 0 0 1px var(--on-dark-line); }
.slot--dark::before {
  background-image:
    linear-gradient(90deg, rgba(255, 255, 255, 0.06) 0 1px, transparent 1px),
    linear-gradient(0deg,  rgba(255, 255, 255, 0.06) 0 1px, transparent 1px);
}
.slot--dark .slot__ico { background: rgba(255, 255, 255, 0.08); color: var(--magenta-lit); box-shadow: inset 0 0 0 1px var(--on-dark-line); }
.slot--dark .slot__k { color: var(--magenta-lit); }
.slot--dark .slot__ttl { color: #fff; }
.slot--dark .slot__note { color: var(--on-dark-dim); }

@media (prefers-reduced-motion: reduce) {
  .slot::after { animation: none; opacity: 0; }
}

/* --------------------------------------------------------------------------
   7c. A real photograph in a media slot
   The "How it runs" band on every service page used to end in a branded
   placeholder asking Amanda for a shot. There were already six usable
   photographs in the library, so each page now carries the one that matches
   what the page is describing, with a caption that says what is happening in
   it rather than what is missing.
   -------------------------------------------------------------------------- */
.shot { margin: 0; }
.shot .media { border-radius: var(--r-lg); box-shadow: var(--lift-2); }
.shot__cap {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  margin-top: 0.9rem;
  font-size: 0.86rem;
  line-height: 1.45;
  color: var(--ink-3);
  max-width: 34ch;
}
.shot__cap svg { flex-shrink: 0; margin-top: 0.2rem; color: var(--magenta); }
.section--dark .shot__cap { color: var(--on-dark-dim); }

/* --------------------------------------------------------------------------
   7b. The scope device
   Replaced the "Awaiting artwork / one page from a real scope" placeholder in
   the Included band on every service page. There is no redacted scope document
   to publish, so this draws the thing instead: the lines of the scope tick
   themselves off in sequence, the total settles on one invoice, and the sign-
   off rule draws itself underneath. Same idiom as the device in each service
   hero, so it reads as part of the set rather than as a patch over a gap.
   -------------------------------------------------------------------------- */
.scope {
  position: relative;
  overflow: hidden;
  padding: clamp(1.25rem, 2.6vw, 1.75rem);
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, 0.045);
  box-shadow: inset 0 0 0 1px var(--on-dark-line);
}
/* The same faint lattice the dark bands use, faded out through a mask so it
   never reads as a table someone forgot to style. */
.scope::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(90deg, rgba(255, 255, 255, 0.05) 0 1px, transparent 1px),
    linear-gradient(0deg,  rgba(255, 255, 255, 0.05) 0 1px, transparent 1px);
  background-size: 44px 44px;
  -webkit-mask-image: radial-gradient(110% 110% at 78% 6%, #000 0%, transparent 78%);
          mask-image: radial-gradient(110% 110% at 78% 6%, #000 0%, transparent 78%);
}
.scope > * { position: relative; }

.scope__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 0.9rem;
  margin-bottom: 0.4rem;
  border-bottom: 1px solid var(--on-dark-line);
  font-family: var(--display);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}
.scope__badge {
  letter-spacing: 0.1em;
  color: #fff;
  background: var(--magenta);
  padding: 0.32rem 0.6rem;
  border-radius: var(--r-pill);
}

.scope__lines { list-style: none; padding: 0; margin: 0; }
.scope__lines li {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.72rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  font-size: 0.92rem;
  color: rgba(255, 255, 255, 0.5);
  transition: color var(--t) var(--soft);
  animation: scope-lit 7s var(--soft) infinite;
}
.scope__lines li:nth-child(2) { animation-delay: 0.5s; }
.scope__lines li:nth-child(3) { animation-delay: 1s; }
.scope__lines li:nth-child(4) { animation-delay: 1.5s; }
@keyframes scope-lit {
  0%, 6%    { color: rgba(255, 255, 255, 0.5); }
  14%, 72%  { color: rgba(255, 255, 255, 0.92); }
  84%, 100% { color: rgba(255, 255, 255, 0.5); }
}

/* The tick fills rather than appearing. Border, background and the mark are
   three cheap properties on one 20px disc. */
.scope__tick {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 20px; height: 20px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.28);
  background: transparent
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='11' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
    center / 0 0 no-repeat;
  animation: scope-tick 7s var(--soft) infinite;
}
.scope__lines li:nth-child(2) .scope__tick { animation-delay: 0.5s; }
.scope__lines li:nth-child(3) .scope__tick { animation-delay: 1s; }
.scope__lines li:nth-child(4) .scope__tick { animation-delay: 1.5s; }
@keyframes scope-tick {
  0%, 6%    { background-color: transparent;    border-color: rgba(255, 255, 255, 0.28); background-size: 0 0; }
  14%, 72%  { background-color: var(--magenta); border-color: var(--magenta);            background-size: 11px 11px; }
  84%, 100% { background-color: transparent;    border-color: rgba(255, 255, 255, 0.28); background-size: 0 0; }
}

.scope__foot {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  padding-top: 1.1rem;
}
.scope__foot p {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.45);
  max-width: 18ch;
}
/* The sign-off. A rule that draws itself left to right once the ticks are in. */
.scope__sig {
  flex-shrink: 0;
  width: 7rem; height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--magenta-lit), rgba(238, 58, 172, 0.2));
  transform-origin: left;
  animation: scope-sign 7s var(--ease) infinite;
}
@keyframes scope-sign {
  0%, 24%   { transform: scaleX(0); }
  40%, 74%  { transform: scaleX(1); }
  86%, 100% { transform: scaleX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .scope__lines li, .scope__tick, .scope__sig { animation: none; }
  .scope__lines li { color: rgba(255, 255, 255, 0.9); }
  .scope__tick { background-color: var(--magenta); border-color: var(--magenta); background-size: 11px 11px; }
  .scope__sig { transform: scaleX(1); }
}

/* Service feature icon panel — used on service pages in place of placeholder photos */
.svc-feat {
  border-radius: var(--r-lg);
  background: linear-gradient(145deg, var(--plum-2) 0%, var(--plum-3) 100%);
  display: grid;
  place-items: center;
  aspect-ratio: 4 / 3;
  position: relative;
  overflow: hidden;
}
.svc-feat::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(90deg, rgba(255, 255, 255, 0.04) 0 1px, transparent 1px),
    linear-gradient(0deg,  rgba(255, 255, 255, 0.04) 0 1px, transparent 1px);
  background-size: 46px 46px;
  -webkit-mask-image: radial-gradient(100% 100% at 50% 50%, #000 0%, transparent 80%);
          mask-image: radial-gradient(100% 100% at 50% 50%, #000 0%, transparent 80%);
}
.svc-feat__ico {
  position: relative;
  display: grid;
  place-items: center;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: rgba(180, 0, 154, 0.18);
  box-shadow: inset 0 0 0 1px rgba(238, 58, 172, 0.3), 0 0 64px rgba(180, 0, 154, 0.35);
  color: var(--magenta-lit);
}

/* --------------------------------------------------------------------------
   8. FAQ
   Native <details>, ruled. The marker is a plus that turns into a minus, and
   the panel fades rather than animating its own height.
   -------------------------------------------------------------------------- */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: clamp(1.15rem, 2.2vw, 1.5rem) 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--display);
  font-size: clamp(1rem, 1.5vw, 1.15rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  transition: color var(--t) var(--soft);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--magenta); }
.faq__sign {
  position: relative;
  flex-shrink: 0;
  width: 30px; height: 30px;
  border-radius: 50%;
  border: 1px solid var(--line);
  transition: background-color var(--t) var(--soft), border-color var(--t) var(--soft);
}
.faq__sign::before,
.faq__sign::after {
  content: "";
  position: absolute;
  top: 50%; left: 50%;
  width: 11px; height: 1.6px;
  border-radius: 2px;
  background: var(--ink-2);
  transform: translate(-50%, -50%);
  transition: transform var(--t) var(--ease), background-color var(--t) var(--soft);
}
.faq__sign::after { transform: translate(-50%, -50%) rotate(90deg); }
.faq summary:hover .faq__sign { border-color: var(--magenta); }
.faq details[open] .faq__sign { background: var(--magenta); border-color: var(--magenta); }
.faq details[open] .faq__sign::before,
.faq details[open] .faq__sign::after { background: #fff; }
.faq details[open] .faq__sign::after { transform: translate(-50%, -50%) rotate(0deg); }
.faq__a {
  padding: 0 0 clamp(1.15rem, 2.2vw, 1.5rem);
  max-width: 60ch;
  font-size: 0.98rem;
  color: var(--ink-2);
  animation: faq-in 0.35s var(--ease);
}
.faq__a p + p { margin-top: 0.8rem; }
@keyframes faq-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .faq__a { animation: none; }
}

/* --------------------------------------------------------------------------
   9. Pager
   Previous and next service, as two ruled cells rather than two buttons.
   -------------------------------------------------------------------------- */
.pager {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1rem, 3vw, 2.5rem);
  border-top: 1px solid var(--line);
}
.pager__side {
  position: relative;
  padding: clamp(1.35rem, 2.4vw, 1.85rem) 0;
  transition: transform var(--t-mv) var(--ease);
}
.pager__side--next { text-align: right; }
.pager__side::after {
  content: "";
  position: absolute;
  top: -1px; left: 0;
  width: 100%; height: 2px;
  background: var(--magenta);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.6s var(--ease);
}
.pager__side--next::after { transform-origin: right; }
.pager__side:hover::after { transform: scaleX(1); }
.pager__side--prev:hover { transform: translateX(-4px); }
.pager__side--next:hover { transform: translateX(4px); }
.pager__k {
  display: block;
  font-family: var(--display);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-4);
  margin-bottom: 0.55rem;
}
.pager__t {
  display: block;
  font-family: var(--display);
  font-size: clamp(1.1rem, 1.8vw, 1.35rem);
  font-weight: 600;
  letter-spacing: -0.025em;
  color: var(--ink);
  transition: color var(--t) var(--soft);
}
.pager__side:hover .pager__t { color: var(--magenta); }
.pager__side--empty { opacity: 0.45; pointer-events: none; }

/* --------------------------------------------------------------------------
   10. Sector filter
   Chips that filter the case-study run. Buttons, not a select, because there
   are only six and they double as a summary of who OM works with.
   -------------------------------------------------------------------------- */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: clamp(1.75rem, 3vw, 2.5rem);
}
.filters__btn {
  padding: 0.62rem 1.1rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--line);
  background: #fff;
  cursor: pointer;
  font-family: var(--display);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--ink-2);
  transition: color var(--t) var(--soft), border-color var(--t) var(--soft),
              background-color var(--t) var(--soft), transform var(--t-mv) var(--ease);
}
.filters__btn:hover { border-color: var(--magenta); color: var(--magenta); }
.filters__btn[aria-pressed="true"] {
  background: var(--magenta);
  border-color: var(--magenta);
  color: #fff;
  transform: translateY(-2px);
}
/* Filtering hides rows outright rather than reordering, so nothing animates
   into a gap that is about to close. */
.cstudy[hidden] { display: none; }

/* ---------- Deep case study ----------
   The homepage panel carrying one more layer: the line that is still true
   about the sector once the engagement is running. */
.cstudy__note {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  margin-top: clamp(1.1rem, 2vw, 1.5rem);
  padding: clamp(0.9rem, 1.6vw, 1.15rem) clamp(1rem, 1.8vw, 1.3rem);
  border-radius: var(--r-xs);
  background: var(--blush);
  box-shadow: inset 0 0 0 1px var(--line-2);
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--ink-2);
}
.cstudy__note b {
  font-family: var(--display);
  font-size: 0.63rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--magenta);
  white-space: nowrap;
  padding-top: 0.22rem;
  flex-shrink: 0;
}

/* A quiet, honest note about what these write-ups do and do not claim. */
.disclaim {
  display: flex;
  align-items: flex-start;
  gap: 0.9rem;
  margin-top: clamp(2rem, 3.5vw, 2.75rem);
  padding-top: clamp(1.35rem, 2.2vw, 1.75rem);
  border-top: 1px solid var(--line);
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--ink-3);
  max-width: 58rem;
}
.disclaim svg { flex-shrink: 0; color: var(--magenta); margin-top: 0.2rem; }

/* --------------------------------------------------------------------------
   11. Timeline (about)
   Five years, drawn. Reuses the stage rail's language at a bigger size, with
   the year set in the display face rather than in a numbered disc.
   -------------------------------------------------------------------------- */
.tl { position: relative; list-style: none; margin: 0; padding: 0; }
.tl__row {
  position: relative;
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr);
  gap: clamp(1.25rem, 3vw, 2.5rem);
  padding: clamp(1.5rem, 2.6vw, 2rem) 0;
  border-top: 1px solid var(--line);
  transition: transform var(--t-mv) var(--ease);
}
.tl__row:last-child { border-bottom: 1px solid var(--line); }
.tl__row::after {
  content: "";
  position: absolute;
  top: -1px; left: 0;
  width: 100%; height: 2px;
  background: var(--magenta);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.7s var(--ease);
}
.tl__row:hover::after { transform: scaleX(1); }
/* .tl__row p sets the body size for the right-hand column, and would otherwise
   win against a single class on equal specificity. */
.tl__row .tl__yr {
  font-family: var(--display);
  font-size: clamp(1.05rem, 1.9vw, 1.32rem);
  font-weight: 700;
  letter-spacing: -0.025em;
  color: var(--magenta);
  line-height: 1.1;
}
.tl__yr small {
  display: block;
  margin-top: 0.45rem;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-4);
}
.tl__row h3 { font-size: clamp(1.1rem, 1.8vw, 1.35rem); margin-bottom: 0.55rem; }
.tl__row p { font-size: 0.96rem; color: var(--ink-2); margin: 0; max-width: 52ch; }

/* --------------------------------------------------------------------------
   12. Roles
   The specialist network, named by what they do rather than by who they are.
   Ruled cells, one glyph each, same shape as the homepage capabilities.
   -------------------------------------------------------------------------- */
.roles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 clamp(1.75rem, 4vw, 3.25rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
.roles li {
  padding: clamp(1.35rem, 2.4vw, 1.75rem) 0;
  border-top: 1px solid var(--on-dark-line);
}
.roles h3 { font-size: 1.05rem; margin-bottom: 0.4rem; }
.roles p { font-size: 0.9rem; color: var(--on-dark-dim); margin: 0; }
.roles li .roles__k {
  font-family: var(--display);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--magenta-lit);
  margin-bottom: 0.5rem;
}

/* --------------------------------------------------------------------------
   13. Pull band
   One sentence, big, on the plum. Used where a section needs a breath rather
   than another grid.
   -------------------------------------------------------------------------- */
.pull { padding-block: clamp(3rem, 6vw, 5rem); }
.pull blockquote {
  position: relative;
  max-width: 30ch;
  padding-left: clamp(1.25rem, 2.5vw, 2rem);
  font-family: var(--display);
  font-size: clamp(1.5rem, 3.4vw, 2.6rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.18;
  color: #fff;
}
.pull blockquote::before {
  content: "";
  position: absolute;
  left: 0; top: 0.35rem; bottom: 0.35rem;
  width: 3px;
  border-radius: 3px;
  background: var(--magenta-lit);
}
.pull figcaption {
  margin-top: 1.35rem;
  padding-left: clamp(1.25rem, 2.5vw, 2rem);
  font-family: var(--display);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--on-dark-dim);
}

/* --------------------------------------------------------------------------
   14. Who it's for
   A ruled two-column split: a good fit on one side, an honest not-yet on the
   other. Shares the comparison band's logic without repeating its table.
   -------------------------------------------------------------------------- */
.fit {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.75rem, 4vw, 3.5rem);
}
.fit__col h3 {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding-bottom: 1rem;
  margin-bottom: 0.35rem;
  border-bottom: 1px solid var(--line);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.fit__mark {
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
}
.fit__mark svg { width: 12px; height: 12px; }
.fit__mark--y { background: var(--magenta); color: #fff; }
.fit__mark--n { background: var(--blush-2); color: var(--ink-4); box-shadow: inset 0 0 0 1px var(--line); }
.fit__col ul { list-style: none; margin: 0; padding: 0; }
.fit__col li {
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--line-2);
  font-size: 0.96rem;
  color: var(--ink-2);
}
.fit__col--n li { color: var(--ink-3); }

/* Sector chips, used under a service page's fit section. */
.tags { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1.5rem; }
.tags span {
  padding: 0.5rem 0.95rem;
  border-radius: var(--r-pill);
  background: var(--blush-2);
  font-family: var(--display);
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--ink-2);
  transition: background-color var(--t) var(--soft), color var(--t) var(--soft);
}
.tags span:hover { background: var(--magenta-mist); color: var(--magenta); }

/* --------------------------------------------------------------------------
   15. Split section
   The workhorse two-column layout these pages use for copy beside a piece of
   media. Declared once so every interior page keeps the same measure.
   -------------------------------------------------------------------------- */
.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
.split--wide-l { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
.split--wide-r { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); }
.split--top { align-items: start; }
.split__body p + p { margin-top: 1rem; }
.split__body h2 { margin-bottom: 1.3rem; }
.split__body .label { margin-bottom: 1.1rem; }
.section--dark .split__body p { color: var(--on-dark); }
.section--dark .split__body strong { color: #fff; }
.split__body strong { color: var(--ink); font-weight: 600; }

/* A figure caption under a piece of media, set as a credit line. */
.credit {
  margin-top: 0.9rem;
  font-size: 0.82rem;
  color: var(--ink-4);
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
}
.credit svg { flex-shrink: 0; color: var(--magenta); margin-top: 0.15rem; }
.section--dark .credit { color: var(--on-dark-dim); }

/* --------------------------------------------------------------------------
   16. Interior pages, responsive
   Every breakpoint the components above need. They live here, at the bottom
   of the block, because a query up in the site's responsive section would be
   outranked by the base rules above it.
   -------------------------------------------------------------------------- */
@media (max-width: 1080px) {
  .arc { grid-template-columns: repeat(3, minmax(0, 1fr)); row-gap: 2rem; }
  /* The travelling light only reads along one continuous rail. Once the arc
     wraps to two rows the rail is a lie, so both go. */
  .arc::before, .arc::after { display: none; }
  .arc__step { padding-top: 1.75rem; }
  .roles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  /* A raked wedge on a narrow viewport covers the whole width, which leaves
     the header as flat plum with an invisible photograph behind it. Vertical
     instead: the photo reads in the top band under the breadcrumb, then
     lands on solid plum before the headline starts. Same trick the home hero
     uses on a phone. */
  .page-hero--media::before { filter: grayscale(0.28) contrast(1.05) brightness(1.15); }
  .page-hero--media::after {
    background:
      linear-gradient(180deg,
        rgba(22, 0, 15, 0.44) 0%,
        rgba(22, 0, 15, 0.6) 18%,
        rgba(22, 0, 15, 0.9) 34%,
        var(--plum) 46%),
      radial-gradient(90% 70% at 96% 0%, rgba(238, 58, 172, 0.3) 0%, rgba(238, 58, 172, 0) 62%);
  }
  .page-hero--media:has(.page-hero__art)::before { opacity: 1; }

  .page-hero__split { grid-template-columns: 1fr; gap: 2.25rem; }
  .page-hero__art { order: -1; max-width: 26rem; }
  .split,
  .split--wide-l,
  .split--wide-r { grid-template-columns: 1fr; gap: 2.25rem; }
  /* Stacked, a 4:5 portrait at full column width becomes the loudest thing on
     the page and pushes the copy below the fold. Capped and centred instead. */
  .split__media {
    order: -1;
    width: 100%;
    max-width: 26rem;
    margin-inline: auto;
  }
  .split--flip .split__media { order: 0; }

  .sindex__row {
    grid-template-columns: 2.5rem minmax(0, 1fr) 2.25rem;
    grid-template-areas:
      "n   gfx  go"
      "ttl ttl  ttl"
      "say say  say";
    align-items: center;
    row-gap: 0.55rem;
    padding-inline: 0;
  }
  .sindex__n   { grid-area: n; }
  .sindex__gfx { grid-area: gfx; justify-self: start; }
  .sindex__ttl { grid-area: ttl; }
  .sindex__say { grid-area: say; }
  .sindex__go  { grid-area: go; }
  .sindex__gfx .gfx { width: 30px; height: 30px; }
  .sindex__row:hover { transform: none; }

  .fit { grid-template-columns: 1fr; gap: 2rem; }
  .incl { grid-template-columns: 1fr; }
  .tl__row { grid-template-columns: 1fr; gap: 0.75rem; }
  .tl__yr { display: flex; align-items: baseline; gap: 0.75rem; }
  .tl__yr small { margin-top: 0; }
}

@media (max-width: 620px) {
  /* One column, so the rail can come back, turned on its side. The dots hang
     off it on the left and the copy is indented past them, which is the same
     drawing the desktop version makes, read downward. */
  .arc {
    grid-template-columns: 1fr;
    row-gap: 1.5rem;
    padding-left: 1.9rem;
  }
  .arc::before {
    display: block;
    top: 6px;
    bottom: 0.6rem;
    left: 6px;
    right: auto;
    width: 1px;
    height: auto;
  }
  .arc::after {
    display: block;
    top: 6px;
    left: 6px;
    right: auto;
    width: 1px;
    height: 22%;
    background: linear-gradient(180deg,
      rgba(238, 58, 172, 0) 0%,
      rgba(238, 58, 172, 0.95) 46%,
      rgba(238, 58, 172, 0) 100%);
    animation-name: arc-run-v;
  }
  .arc__step { padding-top: 0; }
  .arc__step::before { top: 0.35rem; left: -1.9rem; }
  .arc__step::after  { top: calc(0.35rem + 3px); left: calc(-1.9rem + 3px); }

  .roles { grid-template-columns: 1fr; }
  .pager { grid-template-columns: 1fr; gap: 0; }
  .pager__side--next { text-align: left; }
  .pager__side--next::after { transform-origin: left; }
  .pager__side + .pager__side { border-top: 1px solid var(--line); }
  .pager__side:hover { transform: none; }
  .cstudy__note { flex-direction: column; gap: 0.35rem; }
  .cstudy__note b { padding-top: 0; }
  .crumbs { font-size: 0.66rem; }
  .slot { aspect-ratio: var(--slot-ratio-sm, 4 / 3); padding: 1.5rem 1.25rem; }
  .filters { gap: 0.4rem; }
  .filters__btn { padding: 0.5rem 0.85rem; font-size: 0.74rem; }
}
