/* JSKAdvisory redesign
   Palette is derived from the JSK brand navy (#1D2B88), black, white and grey (#69727D). */

:root {
  --ink: #060A24;        /* page background, navy-black */
  --deep: #0C1236;       /* cards */
  --raised: #121A4A;
  --navy: #1D2B88;       /* JSK brand */
  --navy-hi: #2738A8;
  --signal: #6E7FFF;     /* brand tint for accents on dark */
  --signal-hi: #9AA6FF;
  --mist: #A9B0CF;       /* secondary text */
  --text: #E6E9F7;
  --paper: #FFFFFF;
  --slate: #69727D;      /* JSK grey */
  --amber: #E9B872;      /* warning state only */
  --line: rgba(169, 176, 207, .14);
  --line-2: rgba(169, 176, 207, .26);

  --r-lg: 24px;
  --r-md: 18px;
  --r-sm: 12px;
  --gutter: clamp(16px, 3vw, 32px);
  --font-display: "Poppins", system-ui, sans-serif;
  --font-body: "Inter", system-ui, sans-serif;
  --ease: cubic-bezier(.2, .8, .2, 1);

  color-scheme: dark;
  interpolate-size: allow-keywords;
}

/* ---------- Base ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }
html { scroll-padding-top: 96px; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
/* Lenis smooth scrolling (main.js) takes over from the CSS smooth scroll once it loads */
html.lenis, html.lenis body { height: auto; }
html.lenis { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
body {
  background: var(--ink);
  color: var(--text);
  font: 400 16px/1.6 var(--font-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}
img, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }
ul, ol { list-style: none; }
h1, h2, h3 { font-family: var(--font-display); color: #fff; font-weight: 400; text-wrap: balance; }
h2 { font-size: clamp(2rem, 4.2vw, 3.4rem); line-height: 1.04; letter-spacing: -.045em; }
h3 { line-height: 1.15; letter-spacing: -.025em; }
p { text-wrap: pretty; }

svg { fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
/* Images (and links wrapping one) can't be dragged off the page; main.js covers browsers without this property */
img, a:has(img) { -webkit-user-drag: none; }

:focus-visible { outline: 2px solid var(--signal-hi); outline-offset: 3px; border-radius: 6px; }
.btn:focus-visible, .icon-btn:focus-visible { border-radius: 999px; }

.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip {
  position: fixed; top: 12px; left: 12px; z-index: 100;
  padding: 10px 16px; border-radius: 999px; background: #fff; color: var(--ink);
  transform: translateY(-200%);
}
.skip:focus { transform: none; }

.wrap { width: min(1280px, 100% - 2 * var(--gutter)); margin-inline: auto; }
.section { padding-block: clamp(88px, 11vw, 152px); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 48px; padding: 0 22px; border-radius: 999px;
  font: 500 15px/1 var(--font-body); white-space: nowrap; cursor: pointer;
  border: 1px solid transparent;
  transition: background-color .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease), translate .2s var(--ease), scale .16s var(--ease);
}
/* Hover is kept plain: the fill eases one shade deeper and the button lifts a pixel, nothing more. The white button
   turns the blue of the comparison table's check circles instead, with white text. */
@media (hover: hover) {
  .btn:hover { translate: 0 -1px; background-color: var(--btn-hover); }
  .btn--light:hover { color: #fff; }
}
.btn svg { width: 16px; height: 16px; }
.btn--sm { height: 40px; padding: 0 16px; font-size: 14px; }
.btn--light { background: #fff; color: var(--ink); --btn-hover: var(--signal); }
.btn--primary { background: var(--navy); color: #fff; border-color: rgba(110, 127, 255, .55); --btn-hover: var(--navy-hi); }
.btn--ghost { background: transparent; color: #fff; border-color: rgba(255, 255, 255, .28); --btn-hover: rgba(255, 255, 255, .06); }
.btn--ghost:hover { border-color: rgba(255, 255, 255, .6); }
/* Pressing any control shrinks it to 97% for as long as it's held */
@media (prefers-reduced-motion: no-preference) {
  :is(.btn, .icon-btn, .nav-cta, .nav-toggle, .chain__arrow, .speak__close, .footer .socials a):active { scale: .97; }
  .media-play:active .play { scale: .97; }
}

.section-head { display: grid; gap: 18px; justify-items: start; max-width: 760px; margin-bottom: clamp(40px, 5vw, 64px); }
.section-head p { color: var(--mist); font-size: 17px; max-width: 56ch; }
.section-head--center { margin-inline: auto; text-align: center; justify-items: center; }

/* ---------- Logo ---------- */
.logo { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-display); color: #fff; }
.logo__mark {
  display: inline-grid; place-items: center;
  padding: 5px 7px 4px; border-radius: 6px;
  background: var(--navy); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .2);
  font-weight: 600; font-size: 15px; line-height: 1; letter-spacing: .02em;
}
.logo__word { font-weight: 500; font-size: 17px; letter-spacing: -.02em; }
.logo--sm .logo__mark { font-size: 13px; }
.logo--sm .logo__word { font-size: 15px; }

/* ---------- Header ----------
   Full-width bar with a hairline. Transparent over the hero, hides while scrolling down,
   comes back with a solid navy-black backing when scrolling up. */
.site-header {
  --bar-h: 66px;
  position: fixed; inset: 0 0 auto; z-index: 50; height: var(--bar-h);
  border-bottom: 1px solid var(--line-2);
  transition: translate .45s var(--ease), opacity .45s var(--ease);
}
.site-header::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: rgba(6, 10, 36, .9);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  opacity: 0; transition: opacity .35s;
}
.site-header.is-solid::before, .site-header.is-open::before { opacity: 1; }
.site-header.is-hidden { translate: 0 calc(-100% - 10px); opacity: 0; }
.site-header__inner {
  width: min(1280px, 100% - 2 * var(--gutter)); height: 100%; margin-inline: auto;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 24px;
}
.site-header__inner > .logo { justify-self: start; }

/* Text roll: the word slides up and a pure white copy rolls in from below */
.roll { display: block; overflow: hidden; line-height: 1.5; }
.roll > span { display: block; text-shadow: 0 1.5em 0 #fff; transition: translate .5s var(--ease); }
a:hover > .roll > span, a:focus-visible > .roll > span { translate: 0 -1.5em; }

.nav { display: flex; gap: 16px; }
.nav a {
  position: relative; display: flex; align-items: center; height: 42px; padding: 0 12px;
  font-size: 16px; letter-spacing: -.02em; color: #fff;
  transition: filter .35s var(--ease);
}
/* On hover the white word glows: a tight white halo with a wider, faint blue one behind it. It's a filter on the link,
   outside the roll's clipping box, so the glow isn't cut off at the edges of the word. */
.nav a:is(:hover, :focus-visible) {
  filter: drop-shadow(0 0 5px rgba(255, 255, 255, .6)) drop-shadow(0 0 14px rgba(154, 166, 255, .5));
}
.nav a:focus-visible { outline-offset: 0; }

.nav-cta {
  justify-self: end; display: inline-flex; align-items: center; height: 42px; padding: 0 16px;
  border-radius: 8px; background: rgba(255, 255, 255, .1);
  font-size: 14px; font-weight: 500; letter-spacing: -.01em; color: #fff;
  transition: background-color .25s, scale .16s var(--ease);
}
.nav-cta:hover { background: rgba(255, 255, 255, .16); }
.nav-cta:focus-visible { border-radius: 8px; }

.nav-toggle {
  display: none; justify-self: end; width: 40px; height: 40px; border-radius: 8px;
  border: 0; background: rgba(255, 255, 255, .1); cursor: pointer;
  place-content: center; gap: 5px; transition: scale .16s var(--ease);
}
.nav-toggle:focus-visible { border-radius: 8px; }
.nav-toggle__bar { display: block; width: 22px; height: 1.5px; background: #fff; border-radius: 2px; transition: transform .35s var(--ease), opacity .2s; }
/* Child 1 is the screen-reader label, so the bars are children 2-4 */
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(4) { transform: translateY(-6.5px) rotate(-45deg); }

/* Open, the menu takes the rest of the screen under the bar, so bar and menu together fill the phone's full height
   (100% here is the bar's own height; dvh follows the browser toolbar as it shows and hides). The page behind is
   locked while it's open (main.js). */
.mobile-nav {
  position: absolute; top: 100%; left: 0; right: 0;
  height: calc(100vh - 100%); height: calc(100dvh - 100%);
  display: grid; align-content: start; padding: 4px var(--gutter) 24px;
  background: rgba(6, 10, 36, .96);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  overflow-y: auto; overscroll-behavior: contain;
}
html.nav-locked { overflow: hidden; scrollbar-gutter: stable; }
.mobile-nav[hidden] { display: none; }
.mobile-nav a:not(.btn) { padding: 16px 0; font: 400 1.4rem var(--font-display); letter-spacing: -.02em; color: #fff; border-bottom: 1px solid var(--line); }
.mobile-nav .btn { margin-top: 20px; border-radius: 8px; }
/* Opens in 220ms, growing out of the menu button (its centre, top right) from 95%, with its rows arriving 30ms apart;
   closes back into the button in 180ms (main.js holds it open for that long) */
@media (prefers-reduced-motion: no-preference) {
  .mobile-nav { transform-origin: calc(100% - var(--gutter) - 20px) calc(var(--bar-h) / -2); }
  .mobile-nav:not([hidden]) { animation: pop-in .22s var(--ease) both; }
  .mobile-nav:not([hidden]) > * { animation: menu-row .3s var(--ease) both; animation-delay: calc(40ms + var(--i, 0) * 30ms); }
  .mobile-nav.is-closing { animation: pop-out .18s cubic-bezier(.4, 0, 1, 1) both; pointer-events: none; }
  .mobile-nav.is-closing > * { animation: none; }
}
@keyframes pop-in { from { opacity: 0; scale: .95; } }
@keyframes pop-out { to { opacity: 0; scale: .95; } }
@keyframes menu-row { from { opacity: 0; translate: 0 -6px; } }

/* ---------- Hero ---------- */
/* Video frame + logo band together fill the first screen, so the logos sit above the fold */
.hero { display: flex; flex-direction: column; min-height: 100svh; }
.hero__frame {
  position: relative; isolation: isolate; overflow: hidden;
  flex: 1 0 auto; min-height: 480px; /* low enough that the logo band still fits on a 680px-tall laptop screen; the copy sets the real height */
  display: grid; align-content: end;
  padding: 116px var(--gutter) clamp(20px, 3vw, 40px);
  background: var(--ink);
}
.hero__video {
  position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 45%;
}
.hero__shade {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(6, 10, 36, .6) 0%, rgba(6, 10, 36, 0) 22%, rgba(6, 10, 36, 0) 40%, rgba(6, 10, 36, .72) 72%, rgba(6, 10, 36, .96) 100%),
    linear-gradient(90deg, rgba(6, 10, 36, .72) 0%, rgba(6, 10, 36, .42) 38%, rgba(6, 10, 36, 0) 66%),
    rgba(12, 18, 54, .22);
}
/* Same column as .wrap, so the hero copy lines up with the logo and every section below */
.hero__bottom { width: min(1280px, 100%); margin-inline: auto; }
.hero__lede { max-width: 44ch; margin-bottom: 22px; font-size: 17px; color: var(--text); }
.hero__title {
  max-width: 1000px;
  font-weight: 600; text-transform: uppercase;
  font-size: clamp(2.05rem, 5vw, 4.6rem); line-height: .98; letter-spacing: -.045em;
}

/* Speak with John card */
.speak {
  display: grid; grid-template-columns: 56px 1fr; align-items: center; gap: 14px;
  padding: 14px; border-radius: var(--r-md);
  background: rgba(9, 14, 44, .74);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  backdrop-filter: blur(16px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, .12);
}
.speak__photo {
  width: 56px; height: 56px; border-radius: 12px;
  /* John's studio headshot (240px square: three times the size it shows at), zoomed slightly so his face fills the tile */
  background: var(--navy) url("images/john-headshot.jpg") no-repeat;
  background-size: 135%;
  background-position: 52% 18%;
}
.speak__text { display: grid; gap: 2px; }
.speak__name { font: 500 17px/1.2 var(--font-display); color: #fff; letter-spacing: -.01em; }
.speak__role { font-size: 12.5px; color: var(--mist); }
.speak__btn { grid-column: 1 / -1; width: 100%; }

/* Floating banner: fixed bottom right, under the header (z-index 50). main.js adds .is-shown 8s after the visitor
   starts scrolling, and removes it while the contact section, FAQ card or footer is on screen. While hidden it is
   also invisible to screen readers and the keyboard. */
.speak--float {
  position: fixed; right: var(--gutter); bottom: var(--gutter); z-index: 40;
  width: 340px;
  background: rgba(9, 14, 44, .9);
  box-shadow: 0 24px 60px -18px rgba(0, 0, 0, .75);
  visibility: hidden; opacity: 0; translate: 0 16px; scale: .95; transform-origin: 100% 100%;
  /* leaving: 20% quicker than arriving */
  transition: opacity .32s var(--ease), translate .48s var(--ease), scale .48s var(--ease), visibility 0s linear .48s;
}
.speak--float.is-shown {
  visibility: visible; opacity: 1; translate: 0 0; scale: 1;
  transition: opacity .4s var(--ease), translate .6s var(--ease), scale .6s var(--ease), visibility 0s;
}
.speak--float .speak__text { padding-right: 30px; }
.speak__close {
  position: absolute; top: 8px; right: 8px; width: 32px; height: 32px; display: grid; place-items: center;
  padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--mist); cursor: pointer;
  transition: background-color .2s var(--ease), color .2s var(--ease), scale .16s var(--ease);
}
.speak__close:hover { background: rgba(255, 255, 255, .1); color: #fff; }
.speak__close svg { width: 16px; height: 16px; }

/* Load sequence */
@media (prefers-reduced-motion: no-preference) {
  .hero__video { animation: settle 2.2s var(--ease) both; }
  .hero__lede, .hero__title {
    animation: rise .9s var(--ease) both; animation-delay: var(--d, 0s);
  }
  .hero__lede { --d: .26s; }
  .hero__title { --d: .34s; }
}
@keyframes rise { from { opacity: 0; transform: translateY(16px); } }
@keyframes settle { from { transform: scale(1.06); } }

/* ---------- Clients ---------- */
.clients { padding: 30px 0; background: var(--paper); color: var(--slate); }
.marquee {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.marquee__track { display: flex; width: max-content; animation: marquee 48s linear infinite; }
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__set { display: flex; align-items: center; gap: 72px; padding-right: 72px; }
.marquee img { height: 40px; width: auto; max-width: 150px; object-fit: contain; filter: grayscale(1); opacity: .78; transition: filter .35s var(--ease), opacity .35s var(--ease); }
/* Logos return to their own colours on hover (the strip also pauses, so the logo stays under the pointer) */
@media (hover: hover) {
  .marquee img:hover { filter: none; opacity: 1; }
}
@keyframes marquee { to { transform: translateX(-50%); } }

/* ---------- Services ---------- */
.services__grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(32px, 5vw, 80px); align-items: start; }
/* The intro rides at the vertical centre of the screen, level with the card in focus (main.js keeps --intro-h current) */
.services__intro { position: sticky; top: max(96px, calc(50vh - var(--intro-h, 320px) / 2)); display: grid; gap: 20px; justify-items: start; }
.services__intro p { max-width: 46ch; color: var(--mist); font-size: 17px; }
.services__intro .btn { margin-top: 8px; }
.services__cards { position: relative; display: grid; gap: 40px; } /* positioned so each card's offsetTop is measured from here (main.js) */
.svc {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); gap: 24px;
  min-height: 340px; padding: 24px;
  background: var(--deep); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.svc__body { display: flex; flex-direction: column; gap: 14px; padding: 8px 4px; }
.svc h3 { font-size: clamp(1.45rem, 2.1vw, 1.85rem); }
.svc__body > p { color: var(--mist); }
/* What's included: a checked list, one item per row, divided by hairlines */
.svc__tags { display: grid; margin-top: auto; padding-top: 10px; font-size: 14px; line-height: 1.35; color: var(--text); }
.svc__tags li { display: flex; align-items: center; gap: 12px; padding: 11px 0; border-top: 1px solid var(--line); }
.svc__tags li::before {
  content: ""; flex: none; width: 20px; height: 20px; border-radius: 50%;
  background: rgba(110, 127, 255, .16) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239AA6FF' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / 12px no-repeat;
}
.svc__visual {
  position: relative; overflow: hidden; min-height: 280px;
  border-radius: var(--r-md); border: 1px solid var(--line);
  background: linear-gradient(160deg, #18236F 0%, #0A1034 100%);
}

/* website mock */
.svc__visual--site { padding: 28px 0 0 28px; }
.mock-browser { height: 100%; overflow: hidden; border-radius: 10px 0 0 0; background: #fff; box-shadow: 0 24px 50px -20px rgba(0, 0, 0, .6); }
.mock-browser__bar { display: flex; align-items: center; gap: 6px; padding: 10px 12px; background: #F5F6FA; border-bottom: 1px solid #EAEAEA; }
.mock-browser__bar i { width: 8px; height: 8px; border-radius: 50%; background: #D5D9E6; }
.mock-browser__bar span { margin-left: 8px; padding: 3px 10px; border: 1px solid #EAEAEA; border-radius: 6px; background: #fff; font: 11.5px var(--font-body); color: var(--slate); }
.mock-browser__page { padding: 22px; }
.mb-hero { display: grid; justify-items: start; gap: 10px; padding-bottom: 20px; }
.mb-hero b { display: block; width: 85%; height: 12px; border-radius: 4px; background: var(--navy); }
.mb-hero b.mb-short { width: 55%; background: #C9CEE6; }
.mb-cta { margin-top: 6px; padding: 7px 12px; border-radius: 999px; background: var(--navy); color: #fff; font: 500 11px/1 var(--font-body); }
.mb-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.mb-row i { height: 46px; border-radius: 6px; background: #EEF0F8; }
.mock-float {
  position: absolute; right: 16px; bottom: 16px; width: 150px; padding: 12px;
  display: grid; gap: 6px; border-radius: 12px;
  background: rgba(9, 14, 44, .92); border: 1px solid rgba(255, 255, 255, .14);
}
.mock-float span { font-size: 11.5px; color: var(--mist); }
.mock-float svg { width: 100%; height: 36px; stroke: var(--signal-hi); stroke-width: 2; }
.mock-float path { vector-effect: non-scaling-stroke; }

/* Before/after slider (services card). --pos is the handle's distance from the left edge:
   100% shows only Before, 0% only After. Registered so it can animate smoothly. */
@property --pos { syntax: "<percentage>"; inherits: true; initial-value: 50%; }
.svc__visual--maps { --pos: 50%; background: #0A1034; }
.ba__layer { position: absolute; inset: 0; }
/* Anchored to the top so the stats strip (date, average ranking, top-3 placements) stays readable */
.ba__layer img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
.svc__visual--maps .ba__layer figcaption { top: auto; bottom: 10px; }
.ba__layer--after { clip-path: inset(0 0 0 var(--pos)); }
.svc__visual--maps .ba__layer--after figcaption { left: auto; right: 10px; }
.ba__handle { position: absolute; top: 0; bottom: 0; left: var(--pos); width: 2px; margin-left: -1px; background: #fff; box-shadow: 0 0 10px rgba(6, 10, 36, .45); pointer-events: none; }
.ba__handle::after {
  content: ""; position: absolute; top: 50%; left: 50%; width: 34px; height: 34px; translate: -50% -50%; border-radius: 50%;
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231D2B88' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 7-5 5 5 5M15 7l5 5-5 5'/%3E%3C/svg%3E") center / 18px no-repeat;
  box-shadow: 0 4px 14px rgba(6, 10, 36, .4);
}
.svc__visual figcaption {
  position: absolute; top: 10px; left: 10px; padding: 4px 9px; border-radius: 999px;
  background: rgba(6, 10, 36, .82); color: #fff; font-size: 11.5px;
}

/* funnel */
.svc__visual--funnel { display: grid; align-content: center; gap: 18px; padding: 24px; }
.funnel__cap { font-size: 12px; color: var(--mist); }
.funnel__row { display: grid; grid-template-columns: 1fr auto; gap: 8px 12px; font-size: 13.5px; color: #fff; }
.funnel__row em { font: normal 400 12px var(--font-body); color: var(--signal-hi); }
.funnel__row em.is-gap { color: var(--amber); }
.funnel__bar { grid-column: 1 / -1; position: relative; height: 8px; border-radius: 99px; background: rgba(255, 255, 255, .08); }
.funnel__bar i { position: absolute; inset: 0 auto 0 0; width: var(--w); border-radius: inherit; background: var(--signal); }
.funnel__bar s { position: absolute; top: -4px; bottom: -4px; left: var(--t); width: 2px; border-radius: 2px; background: #fff; }

/* chat */
.svc__visual--chat { display: flex; flex-direction: column; justify-content: center; gap: 10px; padding: 20px; }
.bubble { max-width: 88%; padding: 10px 14px; border-radius: 14px; font-size: 13.5px; line-height: 1.45; color: #fff; }
.bubble--agent { align-self: flex-start; background: var(--navy); border: 1px solid rgba(255, 255, 255, .12); border-bottom-left-radius: 4px; }
.bubble--user { align-self: flex-end; background: rgba(255, 255, 255, .1); border-bottom-right-radius: 4px; }
.chat__done { display: flex; align-items: center; gap: 8px; margin-top: 4px; font-size: 12.5px; color: var(--signal-hi); }
.chat__done svg { width: 16px; height: 16px; }

/* Illustration loops. main.js adds .is-live while a card is on screen (and only when motion is allowed);
   without it every illustration shows its finished state. Each loop tells its card's story, then resets. */
.mb-cta { position: relative; }
.mb-cursor { position: absolute; left: 62%; top: 55%; width: 18px; height: 18px; fill: #fff; stroke: var(--ink); stroke-width: 1.4; stroke-linejoin: round; opacity: 0; pointer-events: none; }
.mock-float path { fill: none; }
@media (prefers-reduced-motion: no-preference) {
  /* Site: a visitor's cursor glides to "Book a consultation", clicks, and the enquiries line climbs */
  .svc__visual--site.is-live .mb-cursor { animation: svc-cursor 7s var(--ease) infinite; }
  .svc__visual--site.is-live .mb-cta { animation: svc-click 7s infinite; }
  .svc__visual--site.is-live .mock-float path { stroke-dasharray: 400; animation: svc-draw 7s cubic-bezier(.45, 0, .2, 1) infinite; }
  .svc__visual--site.is-live .mock-float { animation: svc-bob 7s ease-in-out infinite; }

  /* Maps: the card opens on the whole Before grid, the slider sweeps across to After, holds, and sweeps back.
     (With reduced motion the slider simply rests in the middle.) */
  .svc__visual--maps { --pos: 100%; }
  .svc__visual--maps:not(.is-live) .ba__handle { opacity: 0; }
  .svc__visual--maps.is-live { animation: ba-sweep 8s cubic-bezier(.65, 0, .35, 1) infinite; }
  .svc__visual--maps.is-live .ba__handle { animation: ba-handle 8s infinite; }
  /* the knob stretches 12% along its path at full speed and is round again whenever it stops */
  .svc__visual--maps.is-live .ba__handle::after { animation: ba-knob 8s cubic-bezier(.65, 0, .35, 1) infinite; }

  /* Funnel: each bar fills to this month's actual against its fixed target line, then the status appears */
  .svc__visual--funnel.is-live .funnel__bar i { transform-origin: left; animation: svc-fill 6s var(--ease) infinite; }
  .svc__visual--funnel.is-live .funnel__row em { animation: svc-status 6s infinite; }
  .svc__visual--funnel.is-live .funnel__row:nth-of-type(2) :is(i, em) { animation-delay: .25s; }
  .svc__visual--funnel.is-live .funnel__row:nth-of-type(3) :is(i, em) { animation-delay: .5s; }

  /* Chat: the conversation plays out message by message and ends booked */
  .svc__visual--chat.is-live > :nth-child(1) { animation: svc-msg1 7s var(--ease) infinite; }
  .svc__visual--chat.is-live > :nth-child(2) { animation: svc-msg2 7s var(--ease) infinite; }
  .svc__visual--chat.is-live > :nth-child(3) { animation: svc-msg3 7s var(--ease) infinite; }
  .svc__visual--chat.is-live > :nth-child(4) { animation: svc-msg4 7s var(--ease) infinite; }
  /* the tick pulses once as the booking lands, to confirm it */
  .svc__visual--chat.is-live .chat__done svg { border-radius: 50%; animation: svc-pulse 7s infinite; }

  /* Cards arrive as they're scrolled to: the card rises and settles, its illustration opens out from the centre,
     then the copy follows line by line. main.js adds .can-reveal to <html>, and .is-in to each card once. */
  .can-reveal .svc {
    opacity: 0; translate: 0 80px; scale: .96;
    transition: opacity .8s var(--ease), translate 1.2s cubic-bezier(.16, 1, .3, 1), scale 1.2s cubic-bezier(.16, 1, .3, 1);
  }
  .can-reveal .svc__visual {
    clip-path: inset(10% 10% 10% 10% round var(--r-md));
    transition: clip-path 1.3s cubic-bezier(.16, 1, .3, 1) .12s;
  }
  .can-reveal .svc__body > * {
    opacity: 0; translate: 0 20px;
    transition: opacity .7s var(--ease), translate .9s cubic-bezier(.16, 1, .3, 1);
    transition-delay: calc(.22s + var(--i, 0) * .08s);
  }
  .can-reveal .svc__body > :nth-child(2) { --i: 1; }
  .can-reveal .svc__body > :nth-child(3) { --i: 2; }
  .can-reveal .svc__body > :nth-child(4) { --i: 3; }
  .can-reveal .svc.is-in { opacity: 1; translate: 0 0; scale: 1; }
  .can-reveal .svc.is-in .svc__visual { clip-path: inset(0 0 0 0 round var(--r-md)); }
  .can-reveal .svc.is-in .svc__body > * { opacity: 1; translate: 0 0; }

  /* List rows (credentials, articles, FAQ) arrive 30ms apart as their list is scrolled to. main.js numbers the rows. */
  .can-reveal [data-stagger]:not(.is-in) > * { opacity: 0; }
  .can-reveal [data-stagger].is-in > * { animation: row-in .55s var(--ease) both; animation-delay: calc(var(--i, 0) * 30ms); }

  /* About: the portrait is unmasked from the bottom up, then its details settle in turn: the name, then the video */
  .can-reveal .about__portrait { transition: clip-path 1.1s cubic-bezier(.16, 1, .3, 1); }
  .can-reveal .about__visual:not(.is-in) .about__portrait { clip-path: inset(100% 0 0 0 round var(--r-lg)); }
  .can-reveal .about__visual.is-in .about__portrait { clip-path: inset(0 0 0 0 round var(--r-lg)); }
  .can-reveal .about__visual:not(.is-in) :is(.about__caption > *, .about__media) { opacity: 0; }
  .can-reveal .about__visual.is-in .about__caption > * { animation: row-in .6s var(--ease) both; animation-delay: calc(.4s + var(--i, 0) * 60ms); }
  .can-reveal .about__caption > span { --i: 1; }
  .can-reveal .about__visual.is-in .about__media { animation: row-in .7s var(--ease) .56s both; }

  /* Focus: main.js sets --f on each card from 1 (its centre is on the screen's centre line, level with the intro) to 0 (a
     whole card away). The card in focus is full size and brightness with a soft signal edge; its neighbours sit
     back, smaller and dimmer, and come forward as they're scrolled to. It uses transform and filter, so it layers
     on top of the reveal above (opacity, translate, scale) without either cancelling the other. */
  .svc-focus .svc {
    transform: scale(calc(.94 + .06 * var(--f, 1)));
    filter: brightness(calc(.42 + .58 * var(--f, 1))) saturate(calc(.55 + .45 * var(--f, 1)));
    border-color: color-mix(in srgb, var(--signal) calc(var(--f, 1) * 32%), var(--line));
    box-shadow: 0 40px 100px -50px rgb(110 127 255 / calc(var(--f, 1) * .5));
    will-change: transform, filter;
  }
}
@keyframes row-in { from { opacity: 0; translate: 0 12px; } }
@keyframes svc-cursor {
  0%, 4% { opacity: 0; translate: 70px 56px; }
  10% { opacity: 1; }
  30% { translate: 0 0; scale: 1; }
  33% { scale: .82; }
  37%, 70% { opacity: 1; translate: 0 0; scale: 1; }
  80%, 100% { opacity: 0; translate: 0 0; }
}
@keyframes svc-click {
  0%, 32% { box-shadow: 0 0 0 0 rgba(29, 43, 136, .45); }
  48%, 100% { box-shadow: 0 0 0 12px rgba(29, 43, 136, 0); }
}
@keyframes svc-draw {
  0%, 34% { stroke-dashoffset: 400; opacity: 1; }
  66%, 86% { stroke-dashoffset: 0; opacity: 1; }
  95% { stroke-dashoffset: 0; opacity: 0; }
  100% { stroke-dashoffset: 400; opacity: 0; }
}
@keyframes svc-bob { 0%, 100% { translate: 0 0; } 50% { translate: 0 -6px; } }
@keyframes ba-sweep {
  0%, 12% { --pos: 100%; }
  45%, 62% { --pos: 0%; }
  95%, 100% { --pos: 100%; }
}
@keyframes ba-knob {
  0%, 12% { scale: 1 1; }
  28.5% { scale: 1.12 .96; }
  45%, 62% { scale: 1 1; }
  78.5% { scale: 1.12 .96; }
  95%, 100% { scale: 1 1; }
}
@keyframes svc-pulse {
  0%, 44% { scale: 1; box-shadow: 0 0 0 0 rgba(154, 166, 255, .55); }
  48% { scale: 1.2; }
  53% { scale: 1; }
  62%, 100% { scale: 1; box-shadow: 0 0 0 10px rgba(154, 166, 255, 0); }
}
/* The handle fades out while it rests against either edge, so its knob is never left half cut off */
@keyframes ba-handle {
  0%, 8% { opacity: 0; }
  14%, 42% { opacity: 1; }
  48%, 58% { opacity: 0; }
  64%, 92% { opacity: 1; }
  98%, 100% { opacity: 0; }
}
@keyframes svc-fill {
  0%, 6% { scale: 0 1; opacity: 1; }
  36%, 86% { scale: 1 1; opacity: 1; }
  95% { scale: 1 1; opacity: 0; }
  100% { scale: 0 1; opacity: 0; }
}
@keyframes svc-status {
  0%, 30% { opacity: 0; }
  38%, 86% { opacity: 1; }
  95%, 100% { opacity: 0; }
}
/* Messages land about 0.9s apart, then the finished conversation holds for 3s before the loop restarts */
@keyframes svc-msg1 { 0%, 2% { opacity: 0; translate: 0 8px; } 7%, 88% { opacity: 1; translate: 0 0; } 95%, 100% { opacity: 0; } }
@keyframes svc-msg2 { 0%, 14% { opacity: 0; translate: 0 8px; } 19%, 88% { opacity: 1; translate: 0 0; } 95%, 100% { opacity: 0; } }
@keyframes svc-msg3 { 0%, 27% { opacity: 0; translate: 0 8px; } 32%, 88% { opacity: 1; translate: 0 0; } 95%, 100% { opacity: 0; } }
@keyframes svc-msg4 { 0%, 40% { opacity: 0; translate: 0 8px; } 45%, 88% { opacity: 1; translate: 0 0; } 95%, 100% { opacity: 0; } }

/* stats */
.stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  margin-top: clamp(72px, 9vw, 128px);
  border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden;
}
.stat { display: flex; flex-direction: column; gap: 14px; padding: 28px 28px 26px; border-right: 1px solid var(--line); }
.stat:last-child { border-right: 0; }
.stat__num {
  order: -1;
  font: 300 clamp(2.6rem, 5vw, 4.5rem)/1 var(--font-display); letter-spacing: -.05em; color: #fff;
  font-variant-numeric: tabular-nums;
}
.stat__unit { margin: 0 .04em; font-size: .6em; letter-spacing: -.02em; color: var(--mist); }
.stat__label { font-size: 12.5px; line-height: 1.5; color: var(--mist); }

/* ---------- Comparison ----------
   JSK's column is one card (the wrap's ::before) that sits behind the table and runs past it at the top and down
   into the booking button. A flat blue tint inside a lit blue border that glows softly at its edge; the fill
   itself stays flat. A point of light travels round the border (::after), and while motion is off it rests on
   the top-right corner. The other two columns stay plain and quieter. */
@property --shine { syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.compare-wrap { --label-w: 22%; --us-w: 32%; position: relative; isolation: isolate; }
.compare-wrap::before, .compare-wrap::after {
  content: ""; position: absolute; z-index: -1; top: -18px; bottom: 0; left: var(--label-w); width: var(--us-w);
  border-radius: var(--r-lg); pointer-events: none;
}
.compare-wrap::before {
  background: rgba(110, 127, 255, .07);
  box-shadow:
    inset 0 0 0 1px rgba(110, 127, 255, .34),
    inset 0 0 24px -10px rgba(110, 127, 255, .4),
    0 0 30px -8px rgba(110, 127, 255, .42);
}
/* The shine: a conic sweep (a short fading tail, then a white head) cut down to a 1.5px ring by the mask */
.compare-wrap::after {
  --shine: 55deg;
  padding: 1.5px;
  background: conic-gradient(from var(--shine), transparent 0 290deg, rgba(154, 166, 255, .5) 335deg, #fff 354deg, transparent 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
}
@keyframes compare-shine { to { --shine: 415deg; } }
/* main.js adds .is-live while the table is on screen, so the shine only runs when it can be seen */
@media (prefers-reduced-motion: no-preference) {
  .compare-wrap.is-live::after { animation: compare-shine 6s linear infinite; }
}
.compare { width: 100%; table-layout: fixed; border-collapse: separate; border-spacing: 0; font-size: 15.5px; line-height: 1.5; }
.compare__label-col { width: var(--label-w); }
.compare__us-col { width: var(--us-w); }
.compare th, .compare td { padding: 26px 28px; text-align: left; vertical-align: top; border-bottom: 1px solid var(--line); }
.compare thead th, .compare thead td { padding-block: 22px 26px; vertical-align: middle; }
.compare thead th { font: 500 15px/1.3 var(--font-display); letter-spacing: -.01em; color: var(--text); }
.compare tbody th { padding-left: 0; font: 400 17px/1.4 var(--font-display); letter-spacing: -.015em; color: #fff; }
.compare td { color: var(--mist); }
/* Inside the card the row lines stop short of its edges */
.compare .is-us {
  border-bottom-color: transparent; color: #fff;
  background: linear-gradient(rgba(255, 255, 255, .13), rgba(255, 255, 255, .13)) 50% 100% / calc(100% - 56px) 1px no-repeat;
}
.compare tbody .is-us { font-weight: 500; font-size: 16px; }
.compare .logo__mark { background: #fff; color: var(--navy); box-shadow: none; }
.cell { display: flex; align-items: flex-start; gap: 12px; }
.cell svg { flex: none; width: 22px; height: 22px; margin-top: 1px; padding: 4px; border-radius: 50%; background: var(--signal); color: #fff; stroke-width: 2.6; }
.compare__foot { margin-left: var(--label-w); width: var(--us-w); padding: 28px 28px 30px; }
.compare__foot .btn { width: 100%; }

/* ---------- Results: the two highlights, side by side ---------- */
.wins__head {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: end;
  gap: 20px clamp(32px, 5vw, 80px); margin-bottom: clamp(40px, 5vw, 64px);
}
.wins__head p { justify-self: end; max-width: 44ch; color: var(--mist); font-size: 17px; }
.wins { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
.win {
  --pad: 10px;
  display: flex; flex-direction: column; padding: var(--pad);
  background: var(--deep); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.win__media { height: auto; aspect-ratio: 16 / 9; border-radius: calc(var(--r-lg) - var(--pad)); }
.win__media video { width: 100%; height: 100%; object-fit: cover; background: #04061A; }
.win__body { display: flex; flex: 1; flex-direction: column; padding: clamp(22px, 2.4vw, 32px) clamp(14px, 1.8vw, 24px) clamp(14px, 1.6vw, 20px); }
.win__who { font-size: 13.5px; color: var(--signal-hi); }
.win__result { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 4px 16px; margin-top: 12px; }
.win__fig { font: 300 clamp(3.6rem, 6.6vw, 6.25rem)/.8 var(--font-display); letter-spacing: -.06em; color: #fff; }
.win__label { max-width: 9ch; font: 400 clamp(1.05rem, 1.4vw, 1.3rem)/1.2 var(--font-display); letter-spacing: -.015em; color: var(--text); }

/* The first 30 days as a row of ticks; the lit ones run up to the day the result landed (--n on the card).
   One mask cuts both layers into ticks: the dim row underneath and the lit run on top. */
.win__days { display: grid; gap: 10px; margin-top: auto; padding-top: clamp(28px, 3.4vw, 44px); }
.win__mark { width: calc(var(--n) / 30 * 100%); min-width: max-content; text-align: right; font-size: 13.5px; font-weight: 500; color: #fff; }
.win__track {
  --gap: 3px;
  position: relative; display: block; height: 28px; background: rgba(169, 176, 207, .14);
  -webkit-mask: repeating-linear-gradient(90deg, #000 0 calc(100% / 30 - var(--gap)), transparent 0 calc(100% / 30));
  mask: repeating-linear-gradient(90deg, #000 0 calc(100% / 30 - var(--gap)), transparent 0 calc(100% / 30));
}
.win__track::after { content: ""; position: absolute; inset: 0 auto 0 0; width: calc(var(--n) / 30 * 100%); background: var(--signal); }
.win__axis { display: flex; justify-content: space-between; font-size: 12px; color: var(--mist); }
/* main.js adds .can-fill when motion is allowed: the lit run then steps in one day at a time as the strip
   scrolls into view, so the four-day result lands well before the one-month one */
@media (prefers-reduced-motion: no-preference) {
  .wins.can-fill .win__track::after { transition: width calc(var(--n) * 50ms) steps(var(--n), end) .2s; }
  .wins.can-fill .win__mark { transition: opacity .4s var(--ease) calc(.2s + var(--n) * 50ms), translate .4s var(--ease) calc(.2s + var(--n) * 50ms); }
  .wins.can-fill .win:not(.is-in) .win__track::after { width: 0; }
  .wins.can-fill .win:not(.is-in) .win__mark { opacity: 0; translate: 0 6px; }
}
.wins__foot { display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 14px 24px; margin-top: clamp(32px, 4vw, 48px); }
.wins__foot p { color: var(--mist); }

/* click-to-play media */
.media-play { position: relative; display: block; width: 100%; height: 100%; padding: 0; border: 0; background: #0A1034; cursor: pointer; overflow: hidden; }
.media-play img { width: 100%; height: 100%; object-fit: cover; }
.play {
  position: absolute; top: 50%; left: 50%; translate: -50% -50%;
  width: 72px; height: 72px; border-radius: 50%; display: grid; place-items: center;
  background: #fff; color: var(--navy);
  box-shadow: 0 12px 40px -8px rgba(0, 0, 0, .55);
  transition: scale .25s var(--ease);
}
.play svg { width: 26px; height: 26px; margin-left: 3px; }
.media-play:hover .play { scale: 1.07; }
.media-play:focus-visible { outline-offset: -4px; border-radius: inherit; }

/* ---------- About ---------- */
.about__grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(32px, 5vw, 80px); align-items: start; }
/* Desktop: John's portrait, cropped head to waist at 4:5, with the intro video set into its lower right corner and
   hanging past its edge, so the video covers his arm rather than his face. The pair sits level with the middle of the
   story and scrolls with the page. The padding leaves room for the overhang (the video is 62% wide at 16:9, and 45% of
   it hangs below: 62% x 9/16 x .45 = 15.7% of the width). */
.about__visual { position: relative; align-self: center; padding-bottom: 15.7%; }
.about__portrait { position: relative; width: 80%; aspect-ratio: 4 / 5; margin: 0; overflow: hidden; border-radius: var(--r-lg); background: #ECEEF2; }
/* The photo is drawn at 110% of the frame's width (165% of its width tall), so there's room for it to drift inside the
   frame (main.js). At rest it sits 5% up, its position halfway through the drift; the drift never reaches his hair. */
.about__portrait img { position: absolute; top: -5%; left: -5%; width: 110%; max-width: none; height: auto; }
/* The bottom runs into the page's ink, so his navy suit fades into the dark instead of stopping at a white edge */
.about__portrait::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(0deg, rgba(6, 10, 36, .95) 0%, rgba(6, 10, 36, .55) 18%, rgba(6, 10, 36, 0) 40%);
}
/* 16:9, the video's own shape, so the whole frame shows with nothing cropped. The ink ring cuts it out of the portrait. */
.about__media {
  position: absolute; right: 0; bottom: 0; width: 62%; height: auto; aspect-ratio: 16 / 9;
  border-radius: var(--r-md); box-shadow: 0 0 0 6px var(--ink), 0 30px 60px -24px rgba(0, 0, 0, .8);
}
.about__media .play { width: 60px; height: 60px; }
.about__media .play svg { width: 22px; height: 22px; }
.about__media .preview__hint { top: 12px; right: 12px; }
/* Short laptop screens: a square crop keeps the pinned pair inside the window */
@media (min-width: 901px) and (max-height: 820px) {
  .about__portrait { aspect-ratio: 1; }
}

/* Hover preview: a muted loop plays under a darker top edge, with its progress along the bottom edge.
   main.js adds the iframe on first hover (fine pointers only), .is-hovering while the pointer is over it and
   .is-previewing once it's actually playing. YouTube pauses a player the browser reports as not fully visible,
   so the frame is fully opaque for the whole hover and every layer above it lets the pointer through. */
.about__media::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(6, 10, 36, .9) 0%, rgba(6, 10, 36, .5) 14%, rgba(6, 10, 36, 0) 36%);
}
.preview__frame {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0;
  pointer-events: none; opacity: 0; transition: opacity .25s var(--ease);
}
.is-hovering .preview__frame { opacity: 1; }
/* The about and results players are 80px taller than their 16:9 frames at both ends. YouTube letterboxes the video
   in the middle at exactly the frame's size (so it lines up with the thumbnail) and draws its title bar and buttons
   along the player's own edges, out in the overhang the frame clips. */
:is(.about__media, .win__media) .preview__frame { inset: -80px 0 auto; height: calc(100% + 160px); }
:is(.about__media, .win__media) .play, .preview__hint, .preview__bar { z-index: 2; pointer-events: none; }
:is(.about__media, .win__media) .play { transition: scale .25s var(--ease), opacity .3s var(--ease); }
:is(.about__media, .win__media).is-previewing .play { opacity: 0; scale: .85; }
.preview__hint {
  position: absolute; top: 16px; right: 16px; display: flex; align-items: center; gap: 8px;
  padding: 7px 12px 7px 10px; border-radius: 999px;
  background: rgba(6, 10, 36, .82); color: #fff; font-size: 12.5px;
  opacity: 0; translate: 0 -6px; scale: .95; transform-origin: 100% 0;
  transition: opacity .24s var(--ease), translate .24s var(--ease), scale .24s var(--ease);
}
.preview__hint svg { width: 16px; height: 16px; }
.preview__bar {
  position: absolute; left: 0; right: 0; bottom: 0; height: 4px;
  background: rgba(255, 255, 255, .18); opacity: 0; transition: opacity .3s var(--ease);
}
.preview__bar i { display: block; height: 100%; background: var(--signal-hi); transform-origin: left; scale: 0 1; }
.is-previewing :is(.preview__hint, .preview__bar) { opacity: 1; translate: 0 0; }
.is-previewing .preview__hint { scale: 1; transition-duration: .3s; }
/* Name, bottom left on the dark fade, clear of the video */
.about__caption {
  position: absolute; z-index: 1; left: clamp(16px, 2vw, 24px); bottom: clamp(16px, 2vw, 22px);
  display: grid; gap: 2px; max-width: 40%;
}
.about__caption strong { font: 500 clamp(1.05rem, 1.4vw, 1.25rem)/1.2 var(--font-display); letter-spacing: -.02em; color: #fff; }
.about__caption span { font-size: 13px; color: rgba(255, 255, 255, .78); }
.about__body { display: grid; gap: 20px; justify-items: start; }
.about__body > p { max-width: 60ch; color: var(--mist); font-size: 17px; }
.creds { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; width: 100%; margin-top: 16px; }
.creds__title { margin-bottom: 8px; font-size: 12.5px; font-weight: 400; color: var(--mist); }
.creds li { display: grid; gap: 2px; padding: 14px 0; border-top: 1px solid var(--line); }
.creds strong { font: 500 15.5px var(--font-display); color: #fff; }
.creds li span { font-size: 14.5px; line-height: 1.5; color: var(--mist); }

/* ---------- Testimonials ---------- */
.voices { overflow-x: clip; }
.voices__head { display: grid; gap: 16px; justify-items: center; text-align: center; margin-bottom: clamp(40px, 4.5vw, 64px); }
.voices__head p { max-width: 48ch; font-size: 17px; color: var(--mist); }
.icon-btn {
  width: 48px; height: 48px; border-radius: 50%; display: grid; place-items: center;
  border: 1px solid var(--line-2); background: transparent; color: #fff; cursor: pointer;
  transition: background-color .2s, border-color .2s, scale .16s var(--ease);
}
.icon-btn:hover { background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .45); }
.icon-btn svg { width: 20px; height: 20px; }

/* Testimonial chain. The client in focus opens into a wide white card: the result, quote and who said it on the left,
   the video on the right. The others wait either side as white-framed portraits, smaller towards the edges.
   main.js gives each card its place (data-pos, -3 to 3, where the 3s are parked just off stage) and marks the one in
   focus .is-active; every size and offset below comes from these variables, so a change of focus is one transition
   of width, height and position. The copy column keeps a fixed width while its card grows or shrinks, so it never
   reflows mid-move; --th is the tallest copy block, measured by main.js, and the cards grow to fit it. */
.chain {
  --pad: 8px; --g: 20px; --dur: .9s; --ease-chain: cubic-bezier(.76, 0, .24, 1);
  --w0: min(880px, 60vw); --h0: max(540px, var(--th, 0px)); --tw: calc(var(--w0) * .5);
  --w1: 176px; --w2: 92px; --w3: 56px;
  --h1: calc(var(--h0) * .74); --h2: calc(var(--h0) * .52); --h3: calc(var(--h0) * .34);
}
/* Without JS: the cards in a row that scrolls sideways */
.chain__stage {
  display: flex; gap: var(--g); overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none;
  padding: 0 max(var(--gutter), (100% - var(--w0)) / 2) 40px;
}
.chain__stage::-webkit-scrollbar { display: none; }
.chain__item {
  position: relative; flex: none; width: var(--w0); height: var(--h0); scroll-snap-align: center;
  overflow: hidden; border-radius: var(--r-lg); background: #fff;
  box-shadow: 0 44px 80px -48px rgba(6, 10, 36, .5);
}
.chain.is-ready .chain__stage { display: block; position: relative; height: var(--h0); padding: 0; overflow: visible; touch-action: pan-y; }
.chain.is-ready .chain__item {
  position: absolute; z-index: 1; top: 50%; left: 50%; width: var(--w); height: var(--h);
  translate: calc(var(--x) - 50%) -50%; cursor: pointer;
  transition: width var(--dur) var(--ease-chain), height var(--dur) var(--ease-chain), translate var(--dur) var(--ease-chain),
    opacity .6s var(--ease), visibility 0s;
}
.chain.is-ready .chain__item.is-active { z-index: 2; cursor: auto; }
/* a card moving from one side of the focus to the other travels behind every other card */
.chain.is-ready .chain__item.is-crossing { z-index: 0; }
.chain__item[data-pos="0"] { --w: var(--w0); --h: var(--h0); --x: 0px; }
.chain__item[data-pos="1"] { --w: var(--w1); --h: var(--h1); --x: calc(var(--w0) / 2 + var(--g) + var(--w1) / 2); }
.chain__item[data-pos="2"] { --w: var(--w2); --h: var(--h2); --x: calc(var(--w0) / 2 + 2 * var(--g) + var(--w1) + var(--w2) / 2); }
.chain__item[data-pos="3"] { --w: var(--w3); --h: var(--h3); --x: calc(var(--w0) / 2 + 3 * var(--g) + var(--w1) + var(--w2) + var(--w3) / 2); }
.chain__item[data-pos="-1"] { --w: var(--w1); --h: var(--h1); --x: calc(-1 * (var(--w0) / 2 + var(--g) + var(--w1) / 2)); }
.chain__item[data-pos="-2"] { --w: var(--w2); --h: var(--h2); --x: calc(-1 * (var(--w0) / 2 + 2 * var(--g) + var(--w1) + var(--w2) / 2)); }
.chain__item[data-pos="-3"] { --w: var(--w3); --h: var(--h3); --x: calc(-1 * (var(--w0) / 2 + 3 * var(--g) + var(--w1) + var(--w2) + var(--w3) / 2)); }
.chain.is-ready .chain__item:is([data-pos="3"], [data-pos="-3"]) {
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: width var(--dur) var(--ease-chain), height var(--dur) var(--ease-chain), translate var(--dur) var(--ease-chain),
    opacity .5s var(--ease), visibility 0s var(--dur);
}
/* first placement and window resizes jump straight to the new layout */
.chain.is-instant :is(.chain__item, .chain__photo, .chain__text, .chain__text > div > *) { transition: none !important; }

/* The copy column */
.chain__text {
  position: absolute; top: 0; left: 0; width: var(--tw); height: var(--h0);
  padding: clamp(30px, 3.2vw, 48px); color: var(--text);
  transition: opacity .15s linear .35s, visibility 0s;
}
.chain__text > div { display: flex; flex-direction: column; min-height: 100%; }
.chain.is-measuring .chain__text { height: auto; }
.chain.is-measuring .chain__text > div { min-height: 0; }
.chain__result { display: grid; gap: 12px; color: var(--ink); }
.chain__stat { font: 300 clamp(4rem, 5.4vw, 5.5rem)/.85 var(--font-display); letter-spacing: -.055em; }
.chain__unit { margin-left: .04em; font-size: .56em; letter-spacing: -.02em; color: var(--signal); }
.chain__label { max-width: 20ch; font-size: clamp(1.1rem, 1.35vw, 1.25rem); font-weight: 400; line-height: 1.3; letter-spacing: -.01em; color: var(--text); }
.chain__text blockquote { max-width: 30ch; margin-top: auto; padding-top: 32px; font-size: clamp(17px, 1.4vw, 20px); line-height: 1.5; letter-spacing: -.005em; color: var(--ink); }
.chain__who { display: grid; gap: 3px; margin-top: 24px; padding-left: 14px; border-left: 2px solid var(--navy); line-height: 1.3; }
.chain__who strong { font: 500 15.5px var(--font-display); color: var(--ink); }
.chain__who span { font-size: 14px; color: var(--mist); }
/* On coming into focus the copy slides in from the left and fades up, line by line, as the card finishes opening */
.chain__text > div > * {
  --at: calc(.4s + var(--i, 0) * 70ms);
  transition: translate 1.1s cubic-bezier(.16, 1, .3, 1) var(--at), opacity .8s var(--ease) var(--at);
}
.chain__text > div > :nth-child(2) { --i: 1; }
.chain__text > div > :nth-child(3) { --i: 2; }
.chain__text > div > blockquote { transition-delay: .5s; }
.chain__text > div > .chain__who { transition-delay: .6s; }
.chain.is-ready .chain__item:not(.is-active) .chain__text { opacity: 0; visibility: hidden; transition: opacity .2s var(--ease), visibility 0s .2s; }
.chain.is-ready .chain__item:not(.is-active) .chain__text > div > * { opacity: 0; translate: -32px 0; transition: translate 0s .2s, opacity .2s var(--ease); }

/* The video: a portrait crop of the frame, filling the card's white frame when it waits at the side */
.chain .chain__photo {
  position: absolute; top: var(--pad); right: var(--pad); bottom: var(--pad); left: var(--tw); width: auto; height: auto;
  border-radius: calc(var(--r-lg) - var(--pad));
  transition: left var(--dur) var(--ease-chain), bottom var(--dur) var(--ease-chain);
}
.chain.is-ready .chain__item:not(.is-active) .chain__photo { left: var(--pad); bottom: var(--pad); }
/* thumbnail and player overhang the frame, a little at the top (YouTube's title bar) and more at the bottom, where
   these videos have captions burned in */
.chain__photo img { position: absolute; top: -12%; left: 0; width: 100%; height: 138%; object-fit: cover; transition: scale .9s cubic-bezier(.16, 1, .3, 1); }
.chain__photo .preview__frame { inset: auto; top: -12%; left: 50%; width: auto; height: 138%; aspect-ratio: 16 / 9; translate: -50% 0; }
.chain__photo .preview__bar { z-index: 3; }
.chain__photo::after {
  content: ""; position: absolute; inset: auto 0 0; z-index: 1; height: 45%; pointer-events: none;
  background: linear-gradient(0deg, rgba(6, 10, 36, .5), rgba(6, 10, 36, 0));
  transition: opacity .5s var(--ease);
}
.chain__watch {
  position: absolute; left: 14px; bottom: 14px; z-index: 2; pointer-events: none;
  display: flex; align-items: center; gap: 10px; padding: 5px 16px 5px 5px; border-radius: 999px;
  background: rgba(6, 10, 36, .45); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18);
  color: #fff; font-size: 14px; line-height: 1; white-space: nowrap;
  transition: opacity .4s var(--ease) .55s;
}
.chain__watch > span { display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: #fff; color: var(--navy); transition: scale .25s var(--ease); }
.chain__watch svg { width: 14px; height: 14px; margin-left: 2px; }
.chain__photo:hover .chain__watch > span { scale: 1.08; }
/* the dark fade along the bottom stays on every card; only the button waits for focus */
.chain.is-ready .chain__item:not(.is-active) .chain__watch { opacity: 0; transition: opacity .2s var(--ease); }
.chain.is-ready .chain__item:not(.is-active):hover .chain__photo img { scale: 1.06; }

/* Dots: the one in focus stretches into a pill that fills while it waits for the next card */
.chain__controls { display: flex; justify-content: center; align-items: center; gap: 12px; margin-top: clamp(32px, 3.4vw, 48px); }
.chain:not(.is-ready) .chain__controls { display: none; }
.chain__dots { display: flex; align-items: center; }
.chain__dot { display: grid; place-items: center; height: 36px; padding: 0 5px; border: 0; background: none; cursor: pointer; }
.chain__dot i {
  position: relative; display: block; width: 8px; height: 8px; overflow: hidden; border-radius: 99px;
  background: rgba(6, 10, 36, .16); transition: width .6s var(--ease-chain), background-color .25s;
}
.chain__dot:hover i { background: rgba(6, 10, 36, .32); }
.chain__dot.is-active i { width: 44px; background: rgba(29, 43, 136, .16); }
.chain__dot i::after { content: ""; position: absolute; inset: 0; border-radius: inherit; background: var(--navy); transform-origin: left; scale: 0 1; }
.chain__dot.is-active i::after { scale: 1 1; }
.chain.is-auto .chain__dot.is-active i::after { animation: chain-dwell 6s linear forwards; }
.chain.is-auto.is-held .chain__dot.is-active i::after { animation-play-state: paused; }
@keyframes chain-dwell { from { scale: 0 1; } to { scale: 1 1; } }
.chain__dot:focus-visible { outline: 2px solid var(--navy); outline-offset: -4px; border-radius: 99px; }
/* Previous and next arrows either side of the dots */
.chain__arrow {
  display: grid; place-items: center; width: 36px; height: 36px; border-radius: 50%;
  border: 1px solid var(--line-2); background: transparent; color: var(--ink); cursor: pointer;
  transition: background-color .2s, border-color .2s, scale .16s var(--ease);
}
.chain__arrow:hover { background: rgba(6, 10, 36, .05); border-color: rgba(6, 10, 36, .45); }
.chain__arrow:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.chain__arrow svg { width: 16px; height: 16px; transition: translate .25s var(--ease); }
.chain__arrow[data-chain-prev]:hover svg { translate: -2px 0; }
.chain__arrow[data-chain-next]:hover svg { translate: 2px 0; }

/* ---------- Articles ---------- */
.articles__head { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; max-width: none; }
.articles__head h2 { max-width: 16ch; }
/* One article across the full width, its title on the photo under a dark fade; the next three as compact rows */
.articles__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
.article { position: relative; isolation: isolate; overflow: hidden; }
.article img { width: 100%; height: 100%; object-fit: cover; transition: scale .8s var(--ease); }
.article h3 { transition: color .2s; }
.article__meta { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--mist); }
.article__meta span::before { content: ""; display: inline-block; width: 3px; height: 3px; margin-right: 10px; border-radius: 50%; background: currentColor; vertical-align: middle; }
.article:focus-visible { outline-offset: 4px; border-radius: var(--r-lg); }

.article--feature {
  grid-column: 1 / -1; display: flex; flex-direction: column; justify-content: space-between; align-items: flex-start; gap: 24px;
  min-height: clamp(380px, 38vw, 540px); padding: clamp(18px, 2.2vw, 30px);
  border-radius: var(--r-lg); background: var(--deep);
}
.article--feature .article__img { position: absolute; inset: 0; z-index: -2; object-position: 50% 60%; }
.article--feature::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(0deg, rgba(6, 10, 36, .94) 0%, rgba(6, 10, 36, .6) 30%, rgba(6, 10, 36, 0) 62%);
}
.article__tag { padding: 6px 11px; border-radius: 8px; background: #fff; color: var(--ink); font-size: 12.5px; font-weight: 500; line-height: 1.2; }
.article--feature .article__body { display: grid; gap: 14px; }
.article--feature .article__meta { color: rgba(255, 255, 255, .86); }
.article--feature h3 { max-width: 26ch; font-size: clamp(1.5rem, 2.6vw, 2.4rem); line-height: 1.1; letter-spacing: -.035em; }
.article--feature:hover .article__img { scale: 1.04; }

.article--row {
  display: grid; grid-template-columns: clamp(84px, 7.6vw, 112px) minmax(0, 1fr); align-items: center; gap: 16px;
  padding: 8px 18px 8px 8px; border-radius: var(--r-md); background: var(--deep); border: 1px solid var(--line);
  transition: background-color .2s, border-color .2s;
}
.article--row:focus-visible { border-radius: var(--r-md); }
.article__thumb { display: block; overflow: hidden; aspect-ratio: 1; border-radius: var(--r-sm); background: var(--raised); }
.article--row .article__body { display: grid; gap: 8px; }
.article--row h3 {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
  font-size: 16px; line-height: 1.3; letter-spacing: -.015em;
}
.article--row:hover { background: var(--raised); border-color: var(--line-2); }
.article--row:hover h3 { color: var(--signal-hi); }
.article--row:hover img { scale: 1.06; }

/* ---------- Light band (testimonials only) ----------
   A pale sheet, inset from the screen edges with rounded corners, so the page changes key once on the way down.
   It swaps the text and line colours; the video cards inside stay dark. */
.band-light {
  --text: #2B3050; --mist: #596080; --line: rgba(6, 10, 36, .1); --line-2: rgba(6, 10, 36, .2);
  margin-inline: clamp(8px, 1vw, 16px); border-radius: clamp(28px, 3vw, 44px); overflow: clip;
  background: #EEF0F9; color: var(--text); color-scheme: light;
}
.band-light h2 { color: var(--ink); }
.band-light .icon-btn { color: var(--ink); }
.band-light .icon-btn:hover { background: rgba(6, 10, 36, .05); border-color: rgba(6, 10, 36, .45); }
.band-light .btn--ghost { color: var(--ink); border-color: rgba(6, 10, 36, .22); }
.band-light .btn--ghost { --btn-hover: rgba(6, 10, 36, .05); }
.band-light .btn--ghost:hover { border-color: rgba(6, 10, 36, .5); }
.band-light :is(.btn, .icon-btn):focus-visible { outline-color: var(--navy); }

/* ---------- FAQ ---------- */
.faq__grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(32px, 5vw, 80px); align-items: start; }
.faq__side { position: sticky; top: 120px; display: grid; gap: 20px; justify-items: start; }
.speak--panel { width: min(360px, 100%); margin-top: 16px; background: var(--deep); border-color: var(--line); -webkit-backdrop-filter: none; backdrop-filter: none; }
.faq__list { border-top: 1px solid var(--line); }
.qa { border-bottom: 1px solid var(--line); }
.qa summary {
  display: flex; justify-content: space-between; align-items: center; gap: 24px;
  padding: 24px 0; list-style: none; cursor: pointer;
  font: 400 clamp(1.1rem, 1.6vw, 1.3rem)/1.3 var(--font-display); color: #fff; letter-spacing: -.01em;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary:focus-visible { outline-offset: 6px; }
.qa__icon {
  position: relative; flex: none; width: 36px; height: 36px; border-radius: 50%;
  border: 1px solid var(--line-2);
  transition: background-color .3s, border-color .3s;
}
/* A plus drawn as two bars: opening fades the upright bar out through a blur as it shrinks, leaving a minus */
.qa__icon::before, .qa__icon::after {
  content: ""; position: absolute; inset: 0; width: 11px; height: 1.5px; margin: auto;
  border-radius: 2px; background: currentColor;
  transition: opacity .2s var(--ease), filter .2s var(--ease), scale .25s var(--ease);
}
.qa__icon::after { rotate: 90deg; }
.qa[open] .qa__icon { background: var(--navy); border-color: var(--navy); }
.qa[open] .qa__icon::after { opacity: 0; filter: blur(2px); scale: .2 1; }
.qa__a p { max-width: 62ch; padding: 0 56px 26px 0; color: var(--mist); }
.qa__a a { color: var(--signal-hi); text-decoration: underline; text-underline-offset: 3px; }
.qa::details-content { block-size: 0; overflow: clip; transition: block-size .25s var(--ease), content-visibility .25s allow-discrete; }
.qa[open]::details-content { block-size: auto; }

/* ---------- CTA ---------- */
/* Full-bleed photo whose top dissolves into the page ink (and whose foot dissolves into the footer),
   so the FAQ, this section and the footer read as one continuous scroll. Copy sits centred in the open sky. */
/* The photo (2000x1116) is pinned to the bottom of the frame at full width, so the skyline keeps the same
   relationship to the content at every width: tower tops sit 25.8% of the frame width above the photo's foot.
   Pushed down 22% (12.3%W), the photo rises behind the lower part of the booking card: its sky glows either side
   of the card, the tallest towers tuck just under its bottom edge, the bridge arches beside it, and the Opera House
   and harbour show underneath, fading into the footer. Percent padding resolves against width, which is what makes this hold. */
.cta__frame {
  position: relative; isolation: isolate; overflow: hidden;
  display: grid; place-items: start center; text-align: center;
  padding: clamp(120px, 11vw, 190px) var(--gutter) calc(9% + 40px);
}
.cta__img {
  position: absolute; z-index: -2; left: 0; bottom: 0;
  width: 100%; max-width: none; height: auto; aspect-ratio: 2000 / 1116; object-fit: cover;
  transform: translateY(22%);
  /* Its top edge fades out so the photo starts invisibly inside the ink (behind the card) */
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 22%);
          mask-image: linear-gradient(180deg, transparent 0%, #000 22%);
}
.cta__shade {
  position: absolute; inset: 0; z-index: -1;
  /* Heavy ink wash as on forma24: the photo reads as atmosphere, not detail, so the edges melt into the sections around it */
  background:
    radial-gradient(ellipse 55% 40% at 50% 36%, rgba(6, 10, 36, .4), rgba(6, 10, 36, 0) 70%),
    linear-gradient(180deg, var(--ink) 0%, rgba(6, 10, 36, .9) 16%, rgba(6, 10, 36, .6) 40%, rgba(6, 10, 36, .36) 64%, rgba(6, 10, 36, .46) calc(100% - var(--cta-fade, 110px)), var(--ink) 100%);
}
/* Copy centred in the sky, JSK's booking calendar beneath it, so the call is booked without leaving the page.
   The card is 1040px wide because the widget only switches to its three-column layout (details, month, times)
   from about 1000px; narrower, it stacks those parts and grows to roughly 1,000px tall. */
.cta__content { width: min(1040px, 100%); display: grid; justify-items: center; gap: clamp(48px, 5vw, 72px); }
.cta__copy { display: grid; gap: 22px; justify-items: center; max-width: 820px; }
.cta h2 { font-size: clamp(2.2rem, 5vw, 4.25rem); line-height: 1.02; }
.cta__copy > p { max-width: 48ch; font-size: 18px; color: var(--text); }
.cta__copy .btn { margin-top: 8px; }
.cta__booking {
  position: relative; width: 100%; min-height: 699px; /* the trimmed widget's height at full width, so the card doesn't jump */
  overflow: hidden; border-radius: var(--r-lg); background: #fff; text-align: left;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .14), 0 60px 120px -40px rgba(0, 0, 0, .9);
}
.cta__booking.is-ready { min-height: 0; }
.cta__cal { display: block; width: 100%; height: 787px; border: 0; }
/* In its wide layout the widget opens with an empty 64px header strip and a 24px footer strip, each behind a hairline;
   pulling the frame over them lets the card start at "Select Date & Time" (the back arrow lives in the left column).
   The stacked layout has no strip (its logo sits at the top), so this is keyed to the card's own width. */
.cta__booking { container-type: inline-size; }
@container (min-width: 1000px) { .cta__cal { margin: -64px 0 -24px; } }
.cta__loading {
  position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: 14px;
  padding: 24px; text-align: center; font-size: 15px; color: #4a5070;
}
.cta__loading a { color: var(--navy); font-size: 14px; text-decoration: underline; text-underline-offset: 3px; }
.cta__spinner {
  width: 28px; height: 28px; border-radius: 50%;
  border: 3px solid rgba(29, 43, 136, .15); border-top-color: var(--navy);
  animation: cta-spin .9s linear infinite;
}
@keyframes cta-spin { to { rotate: 360deg; } }
.cta__booking.is-ready .cta__loading { display: none; }

/* ---------- Footer ---------- */
.footer { padding: clamp(40px, 5vw, 72px) 0 32px; }
.footer__grid { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 40px; }
.footer__brand p { max-width: 32ch; margin-top: 18px; color: var(--mist); }
.footer .socials { display: flex; gap: 10px; margin-top: 22px; }
.footer .socials a {
  display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%;
  border: 1px solid var(--line-2); color: var(--text);
  transition: background-color .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease), scale .16s var(--ease);
}
.footer .socials svg { width: 17px; height: 17px; }
.footer .socials a:hover { background: var(--navy); border-color: var(--navy); color: #fff; }
.footer .socials a:focus-visible { outline-offset: 3px; }
.footer__title { margin-bottom: 14px; font-size: 12.5px; font-weight: 400; color: var(--mist); }
.footer ul { display: grid; gap: 10px; font-size: 15px; }
.footer ul a { color: var(--text); transition: color .2s; }
.footer ul a:hover { color: #fff; text-decoration: underline; text-underline-offset: 3px; }
/* Copyright on the left, legal links on the right of the same line */
.footer__base { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 12px 32px; margin-top: 64px; padding-top: 24px; border-top: 1px solid var(--line); }
.footer__base p { font-size: 12.5px; color: var(--mist); }
.footer .footer__legal { display: flex; flex-wrap: wrap; gap: 8px 24px; font-size: 12.5px; }
.footer .footer__legal a { color: var(--mist); }

/* ---------- Video modal ---------- */
.video-modal { width: min(1100px, calc(100vw - 32px)); max-width: none; margin: auto; padding: 0; border: 0; background: transparent; overflow: visible; color: #fff; }
.video-modal::backdrop { background: rgba(3, 5, 18, .86); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.video-modal__frame { position: relative; aspect-ratio: 16 / 9; overflow: hidden; border-radius: var(--r-md); background: #000; }
/* The clicked thumbnail's picture, carried into the player (main.js); the player fades in over it once loaded */
.video-modal__poster { position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: cover; }
.video-modal__frame :is(iframe, video) { position: relative; display: block; width: 100%; height: 100%; border: 0; background: #000; transition: opacity .3s var(--ease); }
.video-modal__close { position: absolute; top: -60px; right: 0; background: rgba(255, 255, 255, .08); }

/* ---------- Responsive ---------- */
@media (max-width: 1180px) {
  .chain { --g: 14px; --w0: min(760px, 70vw); --h0: max(480px, var(--th, 0px)); --tw: calc(var(--w0) * .52);
    --w1: clamp(64px, (100vw - var(--w0)) / 3.2, 140px); --w2: calc(var(--w1) * .5); --w3: calc(var(--w1) * .3); }
  .svc { grid-template-columns: 1fr; }
  .svc__visual { min-height: 260px; }
  /* Full-width card: keep the map roughly square so most of the ranking grid stays in view */
  .svc__visual--maps { min-height: 0; aspect-ratio: 1 / 1; max-height: 520px; }
}

@media (max-width: 900px) {
  .chain { --pad: 6px; --g: 10px; --w0: min(520px, 100vw - 2 * var(--gutter) - 56px); --ph: min(300px, var(--w0) * .74);
    --h0: calc(var(--ph) + var(--pad) + var(--th, 340px)); --tw: var(--w0);
    --w1: clamp(20px, (100vw - var(--w0)) / 4, 96px); --w2: calc(var(--w1) * .55); --w3: calc(var(--w1) * .3);
    --h1: calc(var(--h0) * .78); --h2: calc(var(--h0) * .6); --h3: calc(var(--h0) * .44); }
  .chain__item { border-radius: 20px; }
  .chain .chain__photo { left: var(--pad); bottom: var(--th, 340px); border-radius: 15px; }
  .chain__text { top: auto; bottom: 0; height: var(--th, 340px); padding: 22px 22px 24px; }
  .chain__stat { font-size: clamp(3rem, 12vw, 3.75rem); }
  .chain__text blockquote { padding-top: 20px; font-size: 15.5px; }
  .chain__who { margin-top: 18px; }
  .chain__watch { left: 10px; bottom: 10px; font-size: 13px; }
  .chain__watch > span { width: 30px; height: 30px; }
  .site-header { --bar-h: 64px; }
  .site-header__inner { grid-template-columns: 1fr auto; gap: 10px; }
  .nav, .nav-cta { display: none; }
  .nav-toggle { display: grid; }

  .hero__frame { padding-top: 104px; }

  .services__grid, .about__grid, .faq__grid { grid-template-columns: 1fr; }
  .services__intro, .faq__side { position: static; }
  /* Single column: the heading stays on top and the "Speak with John" panel drops below the last question */
  .faq__side { display: contents; }
  .faq .speak--panel { order: 1; margin-top: 8px; }
  /* One column: no portrait, and the video goes back to a full-width 16:9 block */
  .about__visual { position: static; padding-bottom: 0; }
  .about__portrait { display: none; }
  .about__media { position: relative; width: 100%; border-radius: var(--r-lg); border: 1px solid var(--line); box-shadow: none; }
  .about__media .play { width: 72px; height: 72px; }
  .about__media .play svg { width: 26px; height: 26px; }
  /* Comparison: each row becomes a block, with JSK's answer on its own tinted, softly lit panel and the two alternatives
     listed under it (the travelling shine stays on the desktop card; five of them at once would be too busy) */
  .compare-wrap::before, .compare-wrap::after { display: none; }
  .compare, .compare tbody, .compare tr, .compare th, .compare td { display: block; width: auto; }
  .compare colgroup { display: none; }
  .compare thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .compare tbody tr { padding: 24px 0 22px; border-bottom: 1px solid var(--line); }
  .compare tbody tr:first-child { border-top: 1px solid var(--line); }
  .compare tbody th, .compare tbody td { padding: 0; border: 0; }
  .compare tbody th { margin-bottom: 12px; font-size: 18px; }
  .compare tbody .is-us {
    margin-bottom: 10px; padding: 14px 18px 16px; border-radius: var(--r-md);
    background: rgba(110, 127, 255, .07);
    box-shadow: inset 0 0 0 1px rgba(110, 127, 255, .34), 0 0 22px -8px rgba(110, 127, 255, .42);
  }
  .compare tbody .is-us::before { content: attr(data-label); display: block; margin-bottom: 8px; font: 500 12.5px/1 var(--font-body); color: var(--signal-hi); }
  .compare tbody td:not(.is-us) { display: grid; grid-template-columns: 76px 1fr; gap: 12px; padding: 5px 18px; font-size: 15px; }
  .compare tbody td:not(.is-us)::before { content: attr(data-label); color: #7D84A6; }
  .compare__foot { width: auto; margin: 28px 0 0; padding: 0; }

  .stats { grid-template-columns: 1fr 1fr; }
  .stat:nth-child(2) { border-right: 0; }
  .stat:nth-child(-n + 2) { border-bottom: 1px solid var(--line); }

  .wins__head { grid-template-columns: 1fr; }
  .wins__head p { justify-self: start; }
  .wins { grid-template-columns: minmax(0, 1fr); max-width: 680px; margin-inline: auto; }

  /* Tablet and down: the three rows stack under the wide article */
  .articles__grid { grid-template-columns: minmax(0, 1fr); }

  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__brand { grid-column: 1 / -1; }
}

@media (max-width: 560px) {
  .win { --pad: 6px; }
  .win__track { --gap: 2px; height: 24px; }
  .wins__foot { flex-direction: column; }
  /* only the nearest neighbours fit beside the card in focus */
  .chain.is-ready .chain__item:is([data-pos="2"], [data-pos="-2"]) { opacity: 0; visibility: hidden; pointer-events: none; }
  .hero__frame { min-height: 0; padding: 92px var(--gutter) 18px; gap: 22px; }
  /* Shorten the video so the Opera House sits above the headline instead of behind it, then fade its lower edge into the ink */
  .hero__video {
    height: calc(100% - 340px); object-position: 56% 50%;
    -webkit-mask-image: linear-gradient(180deg, #000 72%, transparent 100%);
            mask-image: linear-gradient(180deg, #000 72%, transparent 100%);
  }
  .hero__lede { font-size: 15.5px; margin-bottom: 16px; }

  .marquee__set { gap: 48px; padding-right: 48px; }
  .marquee img { height: 32px; }

  .svc { padding: 14px; }
  .svc__body { padding: 8px 6px 4px; }
  .svc__visual--site { padding: 20px 0 0 20px; }
  .stat { padding: 20px 18px; }

  /* Phones: the banner becomes one slim bar along the bottom: photo, name, a shorter button, close */
  .speak--float {
    left: 12px; right: 12px; bottom: 12px; width: auto;
    grid-template-columns: 40px minmax(0, 1fr) auto auto; gap: 10px; padding: 10px;
  }
  .speak--float .speak__photo { width: 40px; height: 40px; border-radius: 10px; }
  .speak--float .speak__text { padding-right: 0; }
  .speak--float .speak__name { font-size: 15px; }
  .speak--float .speak__role { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .speak--float .speak__btn { grid-column: auto; width: auto; padding-inline: 14px; }
  .speak--float .speak__btn-extra { display: none; }
  .speak--float .speak__close { position: static; width: 28px; height: 28px; }

  .band-light { margin-inline: 0; border-radius: 28px; }
  .articles__head { flex-direction: column; align-items: flex-start; }
  .article--feature { min-height: 420px; }
  .article--feature h3 { font-size: 1.45rem; }
  .article--row { gap: 14px; padding-right: 14px; }
  .creds { grid-template-columns: 1fr; gap: 8px; }
  .qa__a p { padding-right: 0; }

  /* Phones: photo at double width, shifted so the Opera House and CBD fill the screen.
     Towers sit 51.6%W above its foot; pushed down 28% (31.2%W), so 20.4%W + 28px clears the card. */
  .cta__frame { padding: 96px var(--gutter) calc(20.4% + 28px); }
  .cta__img { width: 200%; left: -48%; transform: translateY(28%); }
  .cta__shade { --cta-fade: 36px; } /* the city is only ~75px tall here, so fade just its waterline into the footer */
  .footer__grid { grid-template-columns: 1fr; }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .marquee__track { width: auto; animation: none; justify-content: center; }
  .marquee__set { flex-wrap: wrap; justify-content: center; row-gap: 24px; padding: 0 24px; }
  .marquee__set[aria-hidden="true"] { display: none; }
}
