/* ==========================================================================
   MONTSERRAT, SELF-HOSTED (14 Oct 2026)
   Served from /fonts on this site instead of Google Fonts, so no visitor's IP
   address goes to Google before they have consented to anything (the Google
   Fonts IP-transfer issue under EU law). One variable file covers every
   weight from 100 to 900. SIL Open Font License: /fonts/OFL.txt.
   ========================================================================== */
@font-face{
  font-family:'Montserrat'; font-style:normal; font-weight:100 900; font-display:swap;
  src:url(/fonts/montserrat-latin-wght-normal.woff2) format('woff2-variations'), url(/fonts/montserrat-latin-wght-normal.woff2) format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Montserrat'; font-style:normal; font-weight:100 900; font-display:swap;
  src:url(/fonts/montserrat-latin-ext-wght-normal.woff2) format('woff2-variations'), url(/fonts/montserrat-latin-ext-wght-normal.woff2) format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* Monsta Media Mayfair — enhancement layer (additive, brand-aligned) */
/* Loads after each page's inline styles. Pure enhancement: 3D card tilt,
   hero WebGL aura, magnetic buttons, subtle parallax + mobile safeguards.
   Everything degrades cleanly on touch / reduced-motion. */

/* ---------- smooth anchor scrolling ---------- */
@media (prefers-reduced-motion: no-preference){
  html:focus-within{scroll-behavior:smooth}
}

/* ---------- 3D cursor-tilt cards (generalises the dental .ttile feel) ---------- */
.t3d{
  position:relative;
  isolation:isolate;
  transform-style:preserve-3d;
  transition:transform .35s cubic-bezier(.2,.7,.2,1), box-shadow .35s ease, border-color .3s ease;
  will-change:transform;
}
.t3d > .t3d-glow{
  position:absolute; inset:0; z-index:-1;
  border-radius:inherit; pointer-events:none;
  opacity:0; transition:opacity .3s ease;
  background:radial-gradient(220px circle at var(--mx,50%) var(--my,50%), rgba(236,0,140,.22), transparent 60%);
}
.t3d.tilting{ box-shadow:0 30px 60px -30px rgba(236,0,140,.35), 0 10px 30px -18px rgba(0,0,0,.5); }
.t3d.tilting > .t3d-glow{ opacity:1; }
/* darker cards get a slightly stronger glow */
.tile.dark.t3d > .t3d-glow, .ltile.dark.t3d > .t3d-glow, .network .nc.t3d > .t3d-glow{
  background:radial-gradient(240px circle at var(--mx,50%) var(--my,50%), rgba(236,0,140,.30), transparent 62%);
}

/* ---------- hero WebGL aura (behind the mascot) ---------- */
.hx-fig{ position:relative; }
.hx-canvas{
  position:absolute; left:-8%; top:-8%; width:116%; height:116%;
  z-index:0; pointer-events:none; opacity:0;
  transition:opacity 1.4s ease; mix-blend-mode:screen;
}
.hx-canvas.on{ opacity:1; }
.hx-fig .hx-gor{ position:relative; z-index:1; }

/* ---------- micro-interaction: primary buttons ---------- */
.btn:not(.navbtn){ will-change:transform; }

/* ---------- reveal safety: never leave content hidden ---------- */
.reveal{ } /* base owned by page; kit only adds motion where safe */

/* ---------- mobile fitment safeguards ---------- */
@media (max-width:760px){
  .hx-canvas{ display:none !important; }
  img, video, canvas, iframe, svg{ max-width:100%; }
}
@media (max-width:560px){
  .wrap{ overflow-wrap:break-word; }
  /* numbered eyebrows (e.g. "03  Why automotive businesses choose us")
     were vertically-centring the number against wrapped multi-line text and
     over-tracking on narrow screens — align to first line + tighten spacing. */
  .eyebrow{ align-items:flex-start; letter-spacing:.12em; }
  .eyebrow .num{ flex:0 0 auto; line-height:inherit; }
  /* keep long display headings from ever overflowing the viewport */
  h1, h2, .big{ overflow-wrap:break-word; }
}

/* ---------- honour reduced motion ---------- */
@media (prefers-reduced-motion: reduce){
  .t3d{ transition:none !important; transform:none !important; }
  .t3d > .t3d-glow{ display:none !important; }
  .hx-canvas{ display:none !important; }
}

/* ---------- touch devices: no tilt/hover transforms ---------- */
@media (hover:none), (pointer:coarse){
  .t3d{ transform:none !important; }
  .t3d > .t3d-glow{ display:none !important; }
}

/* ---------- track-record stats: clean, full-width, no empty cells ---------- */
.stats.cols3 .lead{ color:#ff6ab8; margin-bottom:14px; }
.stats.cols3 .phead{ color:#fff; font-weight:900; letter-spacing:-.02em;
  font-size:clamp(24px,3.6vw,40px); line-height:1.05; margin:0 0 36px; max-width:22ch; }
.stats.cols3 .grid{ grid-template-columns:repeat(3,1fr); gap:32px 44px; }
@media (max-width:760px){ .stats.cols3 .grid{ grid-template-columns:1fr; gap:28px; }
  .stats.cols3 .phead{ margin-bottom:28px; } }

/* ---------- FAQ closing card: fills the last row + adds a CTA (no void) ---------- */
.ans .a.wide{ grid-column:1 / -1; display:grid; grid-template-columns:1.6fr auto;
  gap:28px; align-items:center; }
.ans .a.wide .wtext{ min-width:0; }
.ans .a.wide .wcta{ white-space:nowrap; }
@media (max-width:640px){ .ans .a.wide{ grid-template-columns:1fr; gap:18px; justify-items:start; } }

/* ---------- reusable enhanced feature section (dental-style, brand-pink) ---------- */
.wsect{ position:relative; overflow:hidden; color:#fff; padding:92px 0;
  background:radial-gradient(46% 60% at 88% 4%, rgba(236,0,140,.18), transparent 60%), var(--ink); }
.wsect .head-row h2{ color:#fff; max-width:16ch; }
.wsect .head-row p{ color:#b9b9c4; max-width:40ch; }
.wgrid{ position:relative; display:grid; grid-template-columns:repeat(3,1fr); gap:18px; margin-top:34px; }
.wtile{ position:relative; isolation:isolate; border-radius:20px; padding:28px 26px 26px;
  background:linear-gradient(180deg,#17171c,#121216);
  border:1px solid rgba(255,255,255,.08);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.04);
  transition:transform .25s cubic-bezier(.2,.7,.2,1), border-color .3s, box-shadow .3s; }
/* `.js` guard added 16 Sep 26. Without it these six feature cards were set to
   opacity 0 unconditionally, so on the two pages that use them — /websites and
   /automotive-marketing-agency — the whole band was invisible to anyone with
   JavaScript off or blocked, and to any crawler that does not execute it.
   Every other reveal on the site is already written this way. */
.js .wtile.reveal{ opacity:0; transform:translateY(18px); transition:opacity .6s ease, transform .6s cubic-bezier(.2,.7,.2,1); }
.js .wtile.reveal.in{ opacity:1; transform:none; transition-delay:calc(var(--i,0) * 80ms); }
/* soft static corner accent so cards look designed even without hover (esp. touch) */
.wtile::before{ content:""; position:absolute; inset:0; z-index:-1; border-radius:20px; pointer-events:none;
  background:radial-gradient(150px 120px at 30px 30px, rgba(236,0,140,.10), transparent 72%); opacity:.85; }
/* cursor-follow glow (desktop) */
.wtile .glow{ position:absolute; inset:0; z-index:-1; border-radius:20px; opacity:0; transition:opacity .3s; pointer-events:none;
  background:radial-gradient(240px circle at var(--mx,50%) var(--my,50%), rgba(236,0,140,.22), transparent 62%); }
/* animated gradient border ring */
.wtile .ring{ position:absolute; inset:-1px; z-index:-1; border-radius:21px; padding:1px; opacity:0; transition:opacity .35s; pointer-events:none;
  background:conic-gradient(from var(--a,0deg), transparent 55%, #ff6ab8, var(--pink), transparent);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite:xor; mask-composite:exclude; }
.wtile:hover{ border-color:rgba(236,0,140,.4); box-shadow:0 26px 60px -34px rgba(236,0,140,.55), inset 0 1px 0 rgba(255,255,255,.05); }
.wtile:hover .glow, .wtile:hover .ring{ opacity:1; }
/* icon tile — self-contained, sits cleanly inside the padding */
.wtile .ic{ position:relative; width:48px; height:48px; border-radius:14px; margin:0 0 18px;
  display:flex; align-items:center; justify-content:center;
  background:linear-gradient(155deg, rgba(236,0,140,.26), rgba(236,0,140,.06));
  border:1px solid rgba(236,0,140,.30);
  box-shadow:0 8px 20px -10px rgba(236,0,140,.55), inset 0 1px 0 rgba(255,255,255,.14);
  transition:transform .3s ease, box-shadow .3s ease; }
.wtile:hover .ic{ transform:translateY(-2px) scale(1.05); box-shadow:0 14px 28px -10px rgba(236,0,140,.75), inset 0 1px 0 rgba(255,255,255,.2); }
.wtile .ic svg{ width:22px; height:22px; display:block; }
.wtile .tg{ font-weight:800; font-size:10.5px; letter-spacing:.15em; text-transform:uppercase; color:#ff6ab8; margin:0 0 8px; }
.wtile h3{ font-size:20px; font-weight:800; letter-spacing:-.01em; color:#fff; margin:0; }
.wtile p{ font-size:14px; line-height:1.55; color:#b9b9c4; margin-top:9px; font-weight:400; }
/* touch / no-hover: keep a subtle living accent since JS tilt+glow are disabled */
@media (hover:none){ .wtile .ring{ opacity:.45; } .wtile .glow{ opacity:.3; } .wtile:active{ border-color:rgba(236,0,140,.4); } }
.wbanner{ grid-column:1 / -1; position:relative; overflow:hidden; border-radius:20px; padding:28px 30px;
  background:linear-gradient(120deg, var(--pink), #a3006a); display:flex; align-items:center; gap:22px;
  flex-wrap:wrap; justify-content:space-between; box-shadow:0 24px 60px -32px rgba(236,0,140,.7); }
.wbanner .shine{ position:absolute; top:0; left:-40%; width:34%; height:100%; pointer-events:none;
  background:linear-gradient(120deg, transparent, rgba(255,255,255,.30), transparent); transform:skewX(-18deg); animation:wshine 5s ease-in-out infinite; }
@keyframes wshine{ 0%,62%{ left:-40%; } 100%{ left:132%; } }
.wbanner .bl{ display:flex; align-items:center; gap:16px; max-width:58ch; position:relative; }
.wbanner .bic{ width:48px; height:48px; border-radius:13px; background:rgba(255,255,255,.18); display:flex; align-items:center; justify-content:center; flex:0 0 48px; }
.wbanner .bic svg{ width:22px; height:22px; display:block; }
.wbanner h3{ color:#fff; font-size:20px; font-weight:800; margin:0; }
.wbanner p{ color:#ffdbef; font-size:14px; margin-top:4px; font-weight:400; }
.wbanner .pills{ display:flex; gap:8px; flex-wrap:wrap; position:relative; }
.wbanner .pills span{ background:rgba(255,255,255,.16); color:#fff; font-weight:700; font-size:12px; padding:7px 13px; border-radius:30px; white-space:nowrap; }
@media (max-width:820px){ .wgrid{ grid-template-columns:1fr 1fr; } }
@media (max-width:600px){ .wgrid{ grid-template-columns:1fr; } .wbanner{ flex-direction:column; align-items:flex-start; } }
@media (prefers-reduced-motion:reduce){ .wbanner .shine{ display:none; } .wtile{ transition:border-color .3s; } }

/* ---------- splitrow ("Built for automotive/clinics"): kill mobile dead-space ---------- */
/* Page CSS has an unconditional `.splitrow{grid-template-columns:1fr 1fr}` that overrides its
   own mobile rule, so it stays 2-col on phones and the short image floats in a tall column.
   Force 1-col below 900px and make the image a full-width banner that fills cleanly. */
@media (max-width:900px){
  .splitrow{ grid-template-columns:1fr !important; gap:24px; align-items:start; }
  .splitrow .txt{ order:2; }
  .splitrow .duo, .splitrow > figure{ width:100%; margin:0; aspect-ratio:16 / 9 !important; max-height:300px; }
  .splitrow .duo img, .splitrow > figure img{ width:100%; height:100%; object-fit:cover; display:block; }
}


/* ---- work strip (reused from homepage: manual scroll, category tags) ---- */
.workstrip{background:var(--ink);color:#fff;padding:70px 0;overflow:hidden}
.workstrip .ws-head{display:flex;justify-content:space-between;align-items:flex-end;gap:24px;flex-wrap:wrap;margin-bottom:26px}
.workstrip .ws-head h2{font-size:clamp(24px,3.4vw,40px);max-width:20ch;color:#fff;letter-spacing:-.02em}
.workstrip .ws-head .eyebrow{color:var(--pink);margin-bottom:12px}
.workstrip .ws-link{display:inline-flex;align-items:center;gap:9px;font-weight:800;font-size:14px;color:#fff;border-bottom:2px solid var(--pink);padding-bottom:3px;transition:gap .2s ease,color .2s ease;white-space:nowrap}
.workstrip .ws-link:hover{gap:14px;color:var(--pink)}
.workstrip .ws-row{display:flex;gap:14px;overflow-x:auto;overflow-y:hidden;overscroll-behavior-y:auto;scroll-snap-type:x proximity;padding-bottom:8px;-webkit-overflow-scrolling:touch;cursor:grab}
.workstrip .ws-row.drag{cursor:grabbing}
.workstrip .ws-row::-webkit-scrollbar{height:0}
.workstrip .wf{position:relative;flex:0 0 auto;height:clamp(200px,26vw,262px);border-radius:14px;overflow:hidden;scroll-snap-align:start;background:#15151a}
.workstrip .wf img{height:100%;width:auto;display:block;filter:saturate(.72) contrast(1.03) brightness(.94);transition:transform .9s cubic-bezier(.2,.7,.2,1),filter .6s ease;user-select:none;-webkit-user-drag:none}
.workstrip .wf:hover img{filter:none;transform:scale(1.05)}
.workstrip .wf video{height:100%;width:auto;display:block;filter:saturate(.72) contrast(1.03) brightness(.94);transition:transform .9s cubic-bezier(.2,.7,.2,1),filter .6s ease;user-select:none;-webkit-user-drag:none;background:#15151a}
.workstrip .wf:hover video{filter:none;transform:scale(1.05)}
.workstrip .wf::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 55%,rgba(8,8,10,.5));pointer-events:none}
.workstrip .wf .tag{position:absolute;left:12px;bottom:11px;z-index:1;font-weight:800;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:#fff;opacity:0;transform:translateY(6px);transition:.4s}
.workstrip .wf:hover .tag{opacity:1;transform:none}

/* ---- booking calendar fallback (only injected when the embed is blocked) ---- */
.calfall{padding:46px 22px;text-align:center;color:#141418}
.calfall strong{display:block;font-size:clamp(18px,2.4vw,24px);letter-spacing:-.01em;margin-bottom:10px}
.calfall p{color:#5b5b66;max-width:46ch;margin:0 auto 18px;font-size:15px;line-height:1.55}
.calfall .btn{margin:2px auto 14px}
.calfall-alt{margin-top:4px}
.calfall-alt a{font-weight:700;text-decoration:underline;color:#141418}
.calfall-alt a:hover{color:var(--pink,#EC008C)}

/* ---- Party Pixel marquee band (work + automotive) ---- */
.ppxm{background:radial-gradient(720px 340px at 88% -8%,rgba(236,0,140,.10),transparent 60%),var(--ink)}
.ppxm .ppx-sub2{color:#b9b9c3;max-width:56ch;margin-top:12px;font-size:15.5px;line-height:1.6}
.ppxm .mqwin{position:relative;overflow:hidden;margin-top:36px}
.ppxm .mqwin::before,.ppxm .mqwin::after{content:"";position:absolute;top:0;bottom:0;width:min(11vw,130px);z-index:2;pointer-events:none}
.ppxm .mqwin::before{left:0;background:linear-gradient(90deg,var(--ink),transparent)}
.ppxm .mqwin::after{right:0;background:linear-gradient(270deg,var(--ink),transparent)}
.ppxm .mq{display:flex;width:max-content}
.ppxm .mqt{display:flex;gap:14px;padding-right:14px;animation:ppxmscroll 75s linear infinite}
.ppxm .mqwin:hover .mqt,.ppxm .mqwin:focus-within .mqt{animation-play-state:paused}
.ppxm .wf{height:clamp(230px,28vw,330px)}
@keyframes ppxmscroll{from{transform:translateX(0)}to{transform:translateX(-100%)}}
.ppxm .ppxm-foot{display:flex;justify-content:space-between;align-items:center;gap:14px 22px;flex-wrap:wrap;margin-top:28px;color:#8f8f9b;font-size:13px;font-weight:600}
.ppxm .ppxm-foot a{color:#fff;font-weight:800;border-bottom:2px solid var(--pink);padding-bottom:2px;transition:color .2s ease}
.ppxm .ppxm-foot a:hover{color:var(--pink)}
.ppxm .ppxm-chips{display:flex;flex-wrap:wrap;gap:10px 26px;color:#d9d9e0;font-size:13px;font-weight:700;letter-spacing:.02em}
.ppxm .ppxm-chips i{font-style:normal;color:var(--pink);margin-right:8px}
@media (prefers-reduced-motion:reduce){.ppxm .mqt{animation:none}.ppxm .mqwin{overflow-x:auto;overflow-y:hidden;overscroll-behavior-y:auto;-webkit-overflow-scrolling:touch}.ppxm .mq{width:auto}.ppxm .mqt[aria-hidden]{display:none}}

/* ==========================================================================
   SHARED DESIGN LANGUAGE  ·  "the spine"                     (added 28 Jul 26)
   --------------------------------------------------------------------------
   Derived from the trust band and applied site-wide so the fourteen pages
   read as one piece of work rather than fourteen separate builds.

   BRAND DISCIPLINE — no new hues are introduced below. Every colour here is
   already in use across the site, and each has one job:

     var(--pink)  #EC008C   primary pink            — on dark
     --pink-lt    #ff6ab8   the established tint    — on dark (50 uses already)
     --pink-dp    #c70b78   the deep, contrast-safe — on light (75 uses already)

   Loading order matters: this file comes after every page's inline <style>,
   so these rules win at equal specificity without needing !important.
   Everything degrades to the existing design where unsupported.
   ========================================================================== */
:root{ --pink-lt:#ff6ab8; --pink-dp:#c70b78; }

/* --------------------------------------------------------------------------
   1 · THE EYEBROW RULE
   The landing page already led every eyebrow with a short pink rule; the
   other thirteen pages did not. currentColor makes it correct in every
   context automatically — deep pink on light bands, tint on dark ones —
   so 82 eyebrows unify without a single per-section override.
   -------------------------------------------------------------------------- */
.eyebrow::before{ content:""; width:22px; height:2px; border-radius:2px;
  background:currentColor; opacity:.85; flex:none; }
/* eyebrows carrying a numeral: pull it in so rule + number + label read as
   one unit rather than three separate marks */
.eyebrow .num{ margin-left:-3px; }
@media (max-width:560px){ .eyebrow::before{ width:16px; margin-top:.55em; } }
/* The rule marks a SECTION, never a card. .quote .by is the one other
   section-level label on the site, so it takes the rule; card micro-labels
   (.tile .tg, .wtile .tg, .pftag) deliberately stay plain — if every label
   carried the mark it would stop meaning anything. */
.quote .by{ display:inline-flex; align-items:center; gap:10px; }
.quote .by::before{ content:""; width:22px; height:2px; border-radius:2px;
  background:currentColor; opacity:.85; flex:none; }

/* --------------------------------------------------------------------------
   2 · THE FIELD
   Every ink-backed band gets the same two layers: an off-centre pink glow
   and a 72px grid faded out through a radial mask. Barely visible alone —
   its job is to stop dark sections reading as flat black rectangles and to
   make them recognisably part of one system.
   -------------------------------------------------------------------------- */
.stats, .cta-final, .network, .mkt{ position:relative; overflow:hidden; }
.stats > .wrap, .cta-final > .wrap, .network > .wrap, .mkt > .wrap{ position:relative; z-index:2; }
.stats::before, .cta-final::before, .network::before, .mkt::before{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:
    radial-gradient(70% 90% at 50% -18%, rgba(236,0,140,.17), transparent 62%),
    radial-gradient(56% 70% at 4% 106%, rgba(236,0,140,.08), transparent 62%); }
.stats::after, .cta-final::after, .network::after, .mkt::after{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none; opacity:.45;
  background-image:
    linear-gradient(rgba(255,255,255,.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px);
  background-size:72px 72px;
  -webkit-mask-image:radial-gradient(72% 100% at 50% 40%, #000, transparent 76%);
          mask-image:radial-gradient(72% 100% at 50% 40%, #000, transparent 76%); }
/* .cta-final already carries a giant .ghostword; it sits later in the DOM and
   so still paints above the field. Nothing to do but leave it alone. */
/* the pink statement band gets the same grid in white, so it belongs to the
   family rather than sitting between two fielded ink bands as a flat slab */
.quote{ position:relative; overflow:hidden; }
.quote > .wrap{ position:relative; z-index:2; }
.quote::after{ content:""; position:absolute; inset:0; z-index:0; pointer-events:none; opacity:.5;
  background-image:
    linear-gradient(rgba(255,255,255,.10) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.10) 1px, transparent 1px);
  background-size:72px 72px;
  -webkit-mask-image:radial-gradient(70% 100% at 50% 40%, #000, transparent 74%);
          mask-image:radial-gradient(70% 100% at 50% 40%, #000, transparent 74%); }

/* --------------------------------------------------------------------------
   3 · THE SPINE — the trust band itself
   One lit hairline sweeping left to right, a node dropping in above each
   figure, and a glyph beneath that means what the figure means: ten ticks
   for the decade, seven day-blocks with a marker stepping across for the
   weekly report, a field of dots for the client count. No new claims — the
   glyphs carry shape, not numbers.
   Desktop reads as a single instrument; below 860px the spine is dropped
   and the cells stack left-aligned, which is far easier to scan on a phone.
   -------------------------------------------------------------------------- */
.stats.spine .lead{ display:flex; flex-direction:column; align-items:center;
  text-align:center; gap:9px; margin-bottom:50px; }
.stats.spine .lead .hd{ display:inline-flex; align-items:center; gap:16px; }
/* rules flanking the label — the horizontal echo of the spine below it */
.stats.spine .lead .hd::before, .stats.spine .lead .hd::after{
  content:""; width:clamp(18px,5vw,54px); height:1px; flex:none;
  background:linear-gradient(90deg, transparent, rgba(236,0,140,.85)); }
.stats.spine .lead .hd::after{ background:linear-gradient(270deg, transparent, rgba(236,0,140,.85)); }
/* #8a8a96 rather than the darker --muted: at 11px on ink the muted grey only
   reached ~3.3:1, under the 4.5:1 needed for small text. */
.stats.spine .lead .src{ margin:0; color:#8a8a96; font-weight:600; font-size:11px;
  letter-spacing:.06em; text-transform:none; }

.sgrid{ position:relative; display:grid; grid-template-columns:repeat(3,1fr);
  gap:26px; padding-top:46px; }
.sgrid::before{ content:""; position:absolute; left:0; right:0; top:0; height:1px;
  background:rgba(255,255,255,.13); }
.sgrid::after{ content:""; position:absolute; left:0; top:0; height:1px; width:0;
  background:linear-gradient(90deg, transparent, var(--pink) 12%, var(--pink) 88%, transparent);
  box-shadow:0 0 14px rgba(236,0,140,.8);
  transition:width 1.5s cubic-bezier(.2,.8,.2,1) .15s; }
.sgrid.in::after{ width:100%; }
.scell{ position:relative; text-align:center; padding:0 10px; }
.scell::before{ content:""; position:absolute; left:50%; top:-46px;
  transform:translate(-50%,-50%) scale(0); width:13px; height:13px; border-radius:50%;
  background:var(--pink);
  box-shadow:0 0 0 5px rgba(236,0,140,.16), 0 0 22px rgba(236,0,140,.85);
  transition:transform .5s cubic-bezier(.2,1.5,.4,1); }
.sgrid.in .scell::before{ transform:translate(-50%,-50%) scale(1); }
.sgrid.in .scell:nth-child(2)::before{ transition-delay:.5s; }
.sgrid.in .scell:nth-child(3)::before{ transition-delay:.85s; }
.scell .n{ font-size:clamp(40px,5.2vw,64px); font-weight:900; letter-spacing:-.035em;
  line-height:.95; color:var(--pink); }
.scell .l{ margin:12px auto 0; color:#c7c7d0; font-size:14px; font-weight:500; max-width:24ch; }
.scell .gl{ margin-top:22px; display:flex; justify-content:center; }

/* glyph — ten ticks */
.gTick{ display:flex; align-items:flex-end; gap:7px; height:30px; }
.gTick i{ display:block; width:4px; height:30px; border-radius:2px; background:var(--pink);
  opacity:.30; transform-origin:bottom; transform:scaleY(.28);
  transition:transform .55s cubic-bezier(.2,.8,.2,1), opacity .55s ease; }
.sgrid.in .gTick i{ transform:scaleY(1); opacity:.9; }
.sgrid.in .gTick i:nth-child(1){transition-delay:.05s} .sgrid.in .gTick i:nth-child(2){transition-delay:.11s}
.sgrid.in .gTick i:nth-child(3){transition-delay:.17s} .sgrid.in .gTick i:nth-child(4){transition-delay:.23s}
.sgrid.in .gTick i:nth-child(5){transition-delay:.29s} .sgrid.in .gTick i:nth-child(6){transition-delay:.35s}
.sgrid.in .gTick i:nth-child(7){transition-delay:.41s} .sgrid.in .gTick i:nth-child(8){transition-delay:.47s}
.sgrid.in .gTick i:nth-child(9){transition-delay:.53s} .sgrid.in .gTick i:nth-child(10){transition-delay:.59s}

/* glyph — a seven-day cadence, one marker stepping across */
.gWeek{ display:flex; align-items:flex-end; gap:6px; height:30px; }
.gWeek i{ display:block; width:16px; height:9px; border-radius:3px;
  background:rgba(236,0,140,.30); box-shadow:inset 0 0 0 1px rgba(236,0,140,.22);
  position:relative; overflow:hidden; }
.gWeek i::after{ content:""; position:absolute; inset:0; background:var(--pink);
  transform:translateX(-101%); }
.sgrid.in .gWeek i::after{ animation:mmwk 5.6s linear infinite; }
.sgrid.in .gWeek i:nth-child(2)::after{animation-delay:.8s} .sgrid.in .gWeek i:nth-child(3)::after{animation-delay:1.6s}
.sgrid.in .gWeek i:nth-child(4)::after{animation-delay:2.4s} .sgrid.in .gWeek i:nth-child(5)::after{animation-delay:3.2s}
.sgrid.in .gWeek i:nth-child(6)::after{animation-delay:4s}   .sgrid.in .gWeek i:nth-child(7)::after{animation-delay:4.8s}
@keyframes mmwk{ 0%{transform:translateX(-101%)} 10%,26%{transform:translateX(0)} 40%,100%{transform:translateX(101%)} }

/* glyph — a field of dots, wiped in with an animated mask so 100 dots need
   no per-dot delay rules. Falls back to simply visible without mask support. */
.gDots{ display:grid; grid-template-columns:repeat(20,5px); gap:4px; width:max-content;
  -webkit-mask-image:linear-gradient(90deg,#000,#000); mask-image:linear-gradient(90deg,#000,#000);
  -webkit-mask-repeat:no-repeat; mask-repeat:no-repeat;
  -webkit-mask-size:0% 100%; mask-size:0% 100%;
  transition:-webkit-mask-size 1.1s cubic-bezier(.2,.8,.2,1) .25s,
                     mask-size 1.1s cubic-bezier(.2,.8,.2,1) .25s; }
.sgrid.in .gDots{ -webkit-mask-size:100% 100%; mask-size:100% 100%; }
.gDots i{ display:block; width:5px; height:5px; border-radius:50%; background:var(--pink); opacity:.7; }

/* --------------------------------------------------------------------------
   THE SPINE ROTATES  (≤860px)
   An earlier version simply dropped the spine on phones and stacked plain
   ruled cells, which lost everything that gave the band its weight. A phone
   has one long axis and it is vertical — so the same rule, the same lit
   sweep and the same glowing nodes run DOWN the left instead of across the
   top. Same instrument, turned ninety degrees.
   -------------------------------------------------------------------------- */
@media (max-width:860px){
  .stats.spine .lead{ align-items:flex-start; text-align:left; margin-bottom:34px; gap:7px; }
  /* leading rule only — matches the eyebrow language everywhere else */
  .stats.spine .lead .hd::after{ display:none; }
  .stats.spine .lead .hd::before{ width:26px;
    background:linear-gradient(270deg, transparent, rgba(236,0,140,.85)); }
  /* indent the attribution past the rule so it aligns with the label above
     it rather than with the rule (26px rule + 16px gap) */
  .stats.spine .lead .src{ padding-left:42px; }

  .sgrid{ position:relative; grid-template-columns:1fr; gap:0; padding-top:0; border-top:0; }
  /* the unlit track */
  .sgrid::before{ content:""; position:absolute; left:6px; right:auto; top:10px; bottom:14px;
    width:1px; height:auto; background:rgba(255,255,255,.13); }
  /* the lit sweep — top to bottom now, and it must reset the desktop width */
  .sgrid::after{ content:""; position:absolute; left:6px; right:auto; top:10px;
    width:1px; height:0;
    background:linear-gradient(180deg, transparent, var(--pink) 9%, var(--pink) 91%, transparent);
    box-shadow:0 0 14px rgba(236,0,140,.8);
    transition:height 1.7s cubic-bezier(.2,.8,.2,1) .15s; }
  .sgrid.in::after{ width:1px; height:calc(100% - 24px); }

  .scell{ text-align:left; padding:20px 0 30px 32px; border-bottom:0; }
  .scell:last-child{ padding-bottom:4px; }
  /* node sits ON the rule, level with the middle of its figure */
  .scell::before{ left:6px; top:44px; width:13px; height:13px;
    transform:translate(-50%,-50%) scale(0); }
  .sgrid.in .scell::before{ transform:translate(-50%,-50%) scale(1); }
  /* the figures carry the impact on a small screen, so they run larger
     relative to the viewport than the desktop clamp allows */
  .scell .n{ font-size:clamp(44px,12.5vw,58px); }
  .scell .l{ margin-left:0; font-size:14.5px; }
  /* stacked, so the glyphs no longer share a 30px baseline band — without
     this the 9px week blocks leave 21px of dead space above them */
  .scell .gl{ justify-content:flex-start; margin-top:18px; }
  .gWeek{ height:auto; }
}

/* --------------------------------------------------------------------------
   4 · THE FIGURES
   Flat brand pink, no gradient (Albert, 28 Jul 26: "make trust strip same
   colour as brand pink"). A gradient reads as a second treatment sitting
   next to the brand colour rather than as the brand colour itself, so the
   figures use #EC008C exactly — the same pink as the spine, the nodes and
   every glyph in the band.
   .tile.dark .big is deliberately NOT included: those numerals were white
   by design and tinting them was over-reach on my part.
   -------------------------------------------------------------------------- */
.scell .n{ color:var(--pink); }

/* --------------------------------------------------------------------------
   5 · THE FOCUS RING
   One ring, brand pink, everywhere — keyboard users get the same considered
   treatment as everyone else, and it stops browsers drawing three different
   default outlines across the site.
   -------------------------------------------------------------------------- */
:focus-visible{ outline:2px solid var(--pink-lt); outline-offset:3px; border-radius:3px; }
.book :focus-visible, .tests :focus-visible{ outline-color:var(--pink-dp); }

/* --------------------------------------------------------------------------
   6 · THE LINK
   Footer and nav links shared no hover treatment. A rule that wipes in from
   the left gives every link on the site the same small, deliberate response.
   -------------------------------------------------------------------------- */
footer .fcol a, .fbot a{ position:relative; display:inline-block; }
footer .fcol a{ display:block; }
footer .fcol a::after, .fbot a::after{ content:""; position:absolute; left:0; right:0;
  bottom:1px; height:1px; background:var(--pink); transform:scaleX(0);
  transform-origin:left; transition:transform .3s cubic-bezier(.2,.8,.2,1); }
footer .fcol a:hover::after, .fbot a:hover::after,
footer .fcol a:focus-visible::after, .fbot a:focus-visible::after{ transform:scaleX(1); }

/* --------------------------------------------------------------------------
   REDUCED MOTION
   The inline reveal script adds .in to every .reveal immediately when motion
   is reduced, so the end states above already apply — only the movement is cut.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion:reduce){
  .sgrid::after, .scell::before, .gTick i, .gDots,
  footer .fcol a::after, .fbot a::after{ transition:none; }
  .sgrid.in .gWeek i::after{ animation:none; transform:translateX(0); opacity:.55; }
}

/* ==========================================================================
   7 · THE AD-CREATIVE GALLERY                                (moved 28 Jul 26)
   --------------------------------------------------------------------------
   Was duplicated in three page <style> blocks and absent from the five pages
   that needed it most — including the landing page our Meta ads point at.
   One definition here now serves every page; adding the gallery to a new page
   is markup only.

   It is a drag-scrollable strip rather than a grid on purpose: creatives are
   portrait and vary in ratio, so a row that keeps each one's own crop shows
   the work honestly. enhance.js picks up [data-drag] for pointer dragging and
   wheel pass-through.
   ========================================================================== */
.crshow{ position:relative; overflow:hidden; color:#fff; padding:74px 0 30px;
  background:radial-gradient(70% 90% at 85% -10%, rgba(236,0,140,.25), transparent 55%), var(--ink); }
.crshow .head{ display:flex; justify-content:space-between; align-items:flex-end;
  gap:28px; flex-wrap:wrap; margin-bottom:8px; }
.crshow h2{ font-size:clamp(26px,3.6vw,42px); max-width:18ch; }
.crshow .head p{ color:#c7c7d0; font-weight:400; font-size:15.5px; max-width:52ch; margin-top:12px; }
.crshow .head .btn{ flex:none; margin-bottom:4px; }
/* the strip bleeds past .wrap so the row runs to the viewport edge, while the
   first card still lines up with the heading above it */
.crstrip{ --ah:clamp(240px,24vw,330px); display:flex; gap:14px;
  overflow-x:auto; overflow-y:hidden; overscroll-behavior-x:contain;
  padding:22px max(24px, calc((100vw - 1180px)/2)) 30px;
  scroll-snap-type:x proximity; cursor:grab; }
.crstrip.drag{ cursor:grabbing; }
.crstrip::-webkit-scrollbar{ height:9px; }
.crstrip::-webkit-scrollbar-track{ background:rgba(255,255,255,.08); border-radius:8px; }
.crstrip::-webkit-scrollbar-thumb{ background:rgba(255,255,255,.25); border-radius:8px; }
.crstrip::-webkit-scrollbar-thumb:hover{ background:rgba(236,0,140,.6); }
.crcard{ flex:0 0 auto; height:var(--ah); border-radius:14px; overflow:hidden;
  border:1px solid rgba(255,255,255,.14); background:#15151a;
  box-shadow:0 26px 54px -30px rgba(0,0,0,.6); scroll-snap-align:start;
  transition:transform .22s ease, border-color .22s ease; }
.crcard img{ height:100%; width:auto; display:block; }
.crcard:hover{ transform:translateY(-4px); border-color:rgba(236,0,140,.55); }
.crshow .foot{ color:#9a9aa6; font-size:12px; max-width:70ch; padding:0 24px;
  margin:0 auto; text-align:center; }
@media (max-width:760px){ .crstrip{ --ah:230px; gap:11px; } .crcard{ transition:none; } }
@media (max-width:560px){ .crshow{ padding:56px 0 22px; } .crstrip{ --ah:205px; } }
/* on the landing page the gallery sits among .lpsec bands — match their rhythm */
.lp .crshow{ padding:88px 0 34px; }

/* ==========================================================================
   8 · THE NETWORK BAND                                     (aligned 28 Jul 26)
   --------------------------------------------------------------------------
   Three corrections, all of them consistency rather than invention.

   (a) THE SEAM. The band was painted with its own wash,
       `radial-gradient(60% 100% at 50% 0%, #2a0a1d, #0d0d11)`. #2a0a1d is
       brand-hue but heavily blacked-off, and as a large flat field it read
       purple next to the pure --ink of the trust band directly above it —
       leaving a visible horizontal seam between two sections that should
       have felt like one surface. It now uses --ink like every other dark
       band and lets THE FIELD (motif 2) supply the pink, so the two bands
       meet invisibly.

   (b) THE CARDS. websites.html already carried a more considered variant of
       this exact component (`.network.sys .nc`): a soft vertical fill, a lift
       on hover and a pink border on approach. The plain `.nc` on the other
       three pages never got it. Rather than design something new, the better
       version that already existed is promoted to the base — so one component
       now looks the same everywhere it appears.

   (c) THE ICONS. Flat pink blocks were the heaviest, least-finished mark on
       the page. They stay brand pink — pink IS the brand — but pick up the
       depth the rest of the site's icon tiles already have: a gradient, an
       inner highlight and a soft cast glow.
   ========================================================================== */
.network{ background:var(--ink); padding:84px 0; }
.network .lead2{ color:#c7c7d0; }
.network .grid{ margin-top:38px; }

.network .nc{
  background:linear-gradient(180deg, rgba(255,255,255,.055), rgba(255,255,255,.02));
  border:1px solid rgba(255,255,255,.10);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.04);
  transition:transform .25s cubic-bezier(.2,.7,.2,1), border-color .3s ease, box-shadow .3s ease; }
.network .nc:hover{
  transform:translateY(-3px);
  border-color:rgba(236,0,140,.45);
  box-shadow:0 24px 50px -30px rgba(236,0,140,.40), inset 0 1px 0 rgba(255,255,255,.06); }

.network .nc .ni{
  background:linear-gradient(155deg, #ff4fae, var(--pink) 62%);
  box-shadow:0 10px 24px -12px rgba(236,0,140,.75), inset 0 1px 0 rgba(255,255,255,.28);
  transition:transform .3s ease, box-shadow .3s ease; }
.network .nc:hover .ni{
  transform:translateY(-1px) scale(1.04);
  box-shadow:0 14px 28px -12px rgba(236,0,140,.9), inset 0 1px 0 rgba(255,255,255,.34); }

/* touch: no hover to reveal the treatment, so the resting state carries it */
@media (hover:none){
  .network .nc{ transform:none !important; }
  .network .nc .ni{ transform:none !important; }
}
@media (prefers-reduced-motion:reduce){
  .network .nc, .network .nc .ni{ transition:none; }
}

/* ==========================================================================
   9 · CLOSING THE GAPS                                     (aligned 28 Jul 26)
   --------------------------------------------------------------------------
   Audit of every dark band on the site found four sections still painting
   themselves outside the palette, and three more sitting on flat black while
   their neighbours carried THE FIELD.

   TWO OFF-PALETTE MAROONS ARE NOW GONE FROM THE CODEBASE ENTIRELY:
     #2a0a1d  (.network, .moat)          -> rgba(236,0,140,.16) over --ink
     #3a0c25  (.ctaband, plain .hero)    -> rgba(236,0,140,.20/.22) over --ink
   Both were brand-hue but blacked-off so far that at section scale they read
   mauve against pure --ink. Only .ctaband (404 page) and .network were live;
   .moat, .vsl and the plain .hero rule were already dead CSS. They were
   rewritten in place anyway, so reusing any of those classes later cannot
   reintroduce the colour.

   THE REMAINING FLAT BANDS join the family below. .marq is deliberately left
   alone — it is a thin ticker, not a section, and a field would only muddy it.
   ========================================================================== */
.craft{ position:relative; overflow:hidden; }
.craft > .wrap{ position:relative; z-index:2; }
.craft::before{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:
    radial-gradient(70% 90% at 50% -18%, rgba(236,0,140,.17), transparent 62%),
    radial-gradient(56% 70% at 4% 106%, rgba(236,0,140,.08), transparent 62%); }
.craft::after{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none; opacity:.45;
  background-image:
    linear-gradient(rgba(255,255,255,.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.045) 1px, transparent 1px);
  background-size:72px 72px;
  -webkit-mask-image:radial-gradient(72% 100% at 50% 40%, #000, transparent 76%);
          mask-image:radial-gradient(72% 100% at 50% 40%, #000, transparent 76%); }

/* the work strip takes the glow but NOT the grid — it is wall-to-wall imagery,
   so a grid behind it is invisible work and only costs paint time */
.workstrip{ position:relative; }
.workstrip > .wrap{ position:relative; z-index:2; }
.workstrip::before{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:radial-gradient(64% 86% at 50% -14%, rgba(236,0,140,.13), transparent 62%); }

/* craft cards pick up the same approach behaviour as every other dark card */
.craft .ci{ transition:transform .25s cubic-bezier(.2,.7,.2,1), border-color .3s ease, box-shadow .3s ease; }
.craft .ci:hover{ transform:translateY(-3px); border-color:rgba(236,0,140,.45);
  box-shadow:0 24px 50px -30px rgba(236,0,140,.40); }
@media (hover:none){ .craft .ci{ transform:none !important; } }
@media (prefers-reduced-motion:reduce){ .craft .ci{ transition:none; } }

/* --------------------------------------------------------------------------
   The mascot on 404 / terms / privacy / cookies was rendering 860x120 —
   squashed to a seventh of its height, aspect 7.17 against a natural 0.99.
   `.camasc` sets height:120px, but the <img> also carries width="860", which
   the browser applies as a CSS presentation hint; with neither dimension
   auto, the image simply stretches to fill both. Same failure mode as the
   landing-page video earlier: a width/height ATTRIBUTE is a style hint, not
   just intrinsic-ratio metadata, so any CSS that fixes one axis must free
   the other.
   -------------------------------------------------------------------------- */
.camasc{ width:auto; }

/* --------------------------------------------------------------------------
   Section rail — shared scroll aid (was duplicated inline on three pages).
   Built by enhance.js from `section[data-nav]`; desktop only, and only when a
   page has enough stops to be worth it. Dots sit clear of content, label on
   hover, pink when the section is in view.
   -------------------------------------------------------------------------- */
.lprail{position:fixed;right:20px;top:50%;transform:translateY(-50%);z-index:100;display:none;flex-direction:column;gap:2px;padding:10px 8px;border-radius:100px;background:rgba(10,10,12,.34);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid rgba(255,255,255,.09);opacity:0;transition:opacity .5s ease}
.lprail.on{opacity:1}
.lprail a{position:relative;display:block;width:24px;height:24px;text-decoration:none}
.lprail a::after{content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:6px;height:6px;border-radius:50%;background:rgba(255,255,255,.30);transition:background .3s ease,transform .35s cubic-bezier(.2,.8,.2,1),box-shadow .35s ease}
.lprail a:hover::after{background:rgba(255,255,255,.65);transform:translate(-50%,-50%) scale(1.25)}
.lprail a.on::after{background:var(--pink);transform:translate(-50%,-50%) scale(1.5);box-shadow:0 0 0 4px rgba(236,0,140,.18)}
.lprail a span{position:absolute;right:28px;top:50%;transform:translateY(-50%) translateX(6px);white-space:nowrap;font-size:11px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;color:#fff;background:rgba(10,10,12,.86);border:1px solid rgba(255,255,255,.12);padding:6px 11px;border-radius:100px;opacity:0;pointer-events:none;transition:opacity .28s ease,transform .28s cubic-bezier(.2,.8,.2,1)}
.lprail a:hover span,.lprail a:focus-visible span{opacity:1;transform:translateY(-50%) translateX(0)}
.lprail a:focus-visible::after{background:var(--pink)}
@media(min-width:1240px){.lprail{display:flex}}
@media(prefers-reduced-motion:reduce){.lprail{transition:none}}

/* Section index inside the mobile menu — same source of truth, no extra chrome. */
nav .links .navsec{display:none;margin:10px 0 2px;padding-top:12px;border-top:1px solid rgba(255,255,255,.10);font-size:10px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.42)}
nav .links a.navjump{display:none;font-weight:600;font-size:13.5px;opacity:.78;letter-spacing:.01em}
@media(max-width:900px){nav .links .navsec{display:block}nav .links a.navjump{display:block;padding:9px 0}}
/* Light-section variant of the rail — same shape, inverted contrast. */
.lprail.light{background:rgba(255,255,255,.62);border-color:rgba(10,10,12,.10);box-shadow:0 6px 20px rgba(10,10,12,.07)}
.lprail.light a::after{background:rgba(10,10,12,.26)}
.lprail.light a:hover::after{background:rgba(10,10,12,.55)}
.lprail.light a.on::after{background:var(--pink)}

/* --------------------------------------------------------------------------
   WhatsApp alternative in the booking section — sits beside the written
   enquiry option, on the same row where that option is a button and on its
   own line where it is a sentence. Quiet outline by default; WhatsApp green
   arrives only on hover/focus, so the brand pink still leads the section.
   Every booking section on the site is on a light background, so one tone.
   -------------------------------------------------------------------------- */
.altcta{display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:wrap;margin-top:20px}
.altcta .btn{margin-top:0}
.psub + .altcta{margin-top:-18px}
.wabtn{display:inline-flex;align-items:center;gap:9px;font-weight:700;font-size:13.5px;line-height:1;padding:13px 19px;border-radius:40px;border:1px solid rgba(15,15,18,.16);background:#fff;color:#0f0f12;text-decoration:none;transition:border-color .18s ease,background .18s ease,color .18s ease,box-shadow .18s ease}
.wabtn svg{flex:none;opacity:.6;transition:opacity .18s ease}
.wabtn:hover,.wabtn:focus-visible{border-color:rgba(37,211,102,.78);background:rgba(37,211,102,.06);color:#0b6b38;box-shadow:0 10px 24px -16px rgba(37,211,102,.9)}
.wabtn:hover svg,.wabtn:focus-visible svg{opacity:1}
@media(max-width:560px){.altcta{gap:8px}.wabtn{width:100%;justify-content:center;padding:15px 19px}}

/* Quiet utility link in the footer's fine-print row — present so the team can
   reach a campaign landing page, not a wayfinding link for visitors. It only
   recedes; it is never hidden. Full contrast on hover and keyboard focus, and
   no display, size or off-screen tricks that would read as a cloaked link. */
footer .fbot a.fquiet{color:rgba(255,255,255,.42);font-weight:500}
footer .fbot a.fquiet:hover,footer .fbot a.fquiet:focus-visible{color:#cfcfd8}

/* ==========================================================================
   10 · THE MOTION SYSTEM                                    (added 16 Sep 26)
   --------------------------------------------------------------------------
   Albert, 16 Sep 2026: "enhance ui with high focus on journey experience and
   conversion … subtle elegant high level animations which are strategically
   displayed and not cluttered … intense focus on mobile … same high visual
   impact as on the desktop … speed is also very important."

   Three rules govern everything below.

   1. ONE VOCABULARY. Every element on the site enters the same way: it rises,
      it comes forward in Z, it settles. One easing curve (--mm-ease), one
      distance, one duration. Fourteen pages then read as one hand.
   2. COMPOSITED ONLY. transform and opacity, nothing else. No width, height,
      top, left, filter or box-shadow is ever animated on scroll, so the
      compositor carries the work and the main thread stays free for the
      first paint. This is what makes the mobile build feel expensive rather
      than heavy.
   3. NOTHING MOVES THAT ISN'T SAYING SOMETHING. Motion marks a section
      arriving, a figure counting, a strip having more to show. Decoration
      that carries no information was left out on purpose.

   Everything here is scoped to `html.mmx`, a class enhance.js sets once it is
   running. No JS, no motion, and the page renders exactly as it does today.
   ========================================================================== */
:root{
  --mm-ease:cubic-bezier(.16,1,.3,1);   /* the settle */
  --mm-ease-out:cubic-bezier(.22,.7,.2,1);
  --mm-rise:26px;
  --mm-dur:.78s;
}

/* --------------------------------------------------------------------------
   10.1 · THE REVEAL, WITH DEPTH
   The site already reveals on scroll: opacity plus translateY(26px). The move
   was flat — the card slid up a plane. It now also comes FORWARD, rotating a
   few degrees out of the page around its bottom edge under a shared
   perspective. Same distance, same duration, but the eye reads it as an
   object arriving rather than a rectangle sliding, and that difference is
   most of the perceived quality jump on a phone where there is no hover to
   carry the craft.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion:no-preference){
  html.mmx .js .reveal,
  html.mmx .reveal{
    opacity:0;
    transform:translate3d(0,var(--mm-rise),0) scale(.986);
    transition:opacity .62s var(--mm-ease-out), transform var(--mm-dur) var(--mm-ease);
  }
  html.mmx .js .reveal.in,
  html.mmx .reveal.in{ opacity:1; transform:none; }
  /* Deliberately NO will-change here. A long page carries sixty reveals; hinting
     all of them at once promotes sixty layers and costs more memory on a phone
     than it saves in paint. transform + opacity transitions are promoted for
     their duration anyway. */

  /* Cards inside a grid get the Z rotation. Text blocks deliberately do not:
     rotating a paragraph makes its baselines shimmer on low-DPI screens. */
  /* The perspective lives in each card's own transform, not on the grid.
     A `perspective` on the container establishes a 3D rendering context that
     persists for the life of the page — every child stays promoted to its own
     compositor layer long after the animation is over, which cost about 9fps
     of scrolling on the pages with the most cards. Written this way the 3D
     context exists only while the card is actually moving: `transform:none`
     at rest means no context, no layer, no cost. At six degrees the
     difference in vanishing point is not visible. */
  html.mmx .mm-persp > .reveal{
    transform:perspective(1500px) translate3d(0,var(--mm-rise),0) rotateX(6deg) scale(.985);
    transform-origin:50% 100%;
  }
  html.mmx .mm-persp > .reveal.in{ transform:none; }

  /* Stagger. JS numbers the children of every grid it recognises; the delay
     is capped so a twelve-card grid never leaves the reader waiting. */
  html.mmx .reveal[style*="transition-delay"]{ /* strips set their own */ }
  html.mmx .mm-stagger > .reveal{ transition-delay:calc(var(--mm-i,0) * 62ms); }
}

/* --------------------------------------------------------------------------
   10.2 · THE HEADING RISE
   Section headings lift word by word out of their own line. It reads as
   typesetting rather than animation, and it is the one flourish that is worth
   spending on every page because a heading is the first thing read.

   The words are wrapped by JS only when motion is allowed, and the original
   markup is restored the moment the animation finishes, so nothing about the
   document that a crawler or a screen reader sees is changed for longer than
   three quarters of a second.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion:no-preference){
  html.mmx .mmw{
    display:inline-block;
    opacity:0;
    transform:translate3d(0,.42em,0);
    transition:opacity .5s var(--mm-ease-out), transform .72s var(--mm-ease);
    transition-delay:calc(var(--mm-w,0) * 34ms);
  }
  html.mmx .mmrise.in .mmw{ opacity:1; transform:none; }

  /* The pink bar behind the second line of every hero headline is the brand's
     own mark. It now wipes in from the left under the words rather than being
     there from the first frame. Scoped to `.mmrise`, which JS only sets on a
     heading it has actually split and removes once the run is over, so a
     heading that was skipped is never left without its highlight. */
  html.mmx h1.mmrise .hl, html.mmx .hl.mmhl{ background-repeat:no-repeat; background-size:0% 100%; }
  html.mmx h1.mmrise.in .hl, html.mmx .hl.mmhl.in{
    background-size:100% 100%;
    transition:background-size .85s var(--mm-ease) .3s;
  }
}

/* --------------------------------------------------------------------------
   10.3 · THE EYEBROW DRAWS ITS RULE
   Motif 1 gave every section the same 22px pink rule. It now draws in from
   nothing as the section arrives — the smallest possible motion, on the mark
   that already says "a section starts here".
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion:no-preference){
  html.mmx .reveal .eyebrow::before,
  html.mmx .eyebrow.reveal::before{
    transform:scaleX(0); transform-origin:left center;
    transition:transform .6s var(--mm-ease) .12s;
  }
  html.mmx .reveal.in .eyebrow::before,
  html.mmx .eyebrow.reveal.in::before{ transform:scaleX(1); }
}

/* ==========================================================================
   11 · THE STAGE  —  the grid motif, extruded
   --------------------------------------------------------------------------
   Motif 2 put a 72px grid behind every dark band. In the hero that same grid
   is laid flat and run into the distance under the mascot, so the figure is
   standing on the site's own design language rather than floating on a
   gradient. It is the one piece of real 3D on the page and it is built from
   two gradients and a transform: no canvas, no library, no image.
   ========================================================================== */
.heroX .hx-fig, .lphero .lpfig{ position:relative; }
/* the stage is anchored to the mascot, not to the figure column, so the detail
   card that sits under it on the clinic and automotive heroes is never covered */
html.mmx .mm-fig3d{ position:relative; display:flex; justify-content:center; width:100%; }

html.mmx .mm-stage{
  position:absolute; left:50%; bottom:-4%; z-index:0;
  width:210%; height:86%; min-height:150px;
  transform:translateX(-50%) perspective(460px) rotateX(66deg);
  transform-origin:50% 100%;
  pointer-events:none;
  overflow:hidden;
  -webkit-mask-image:radial-gradient(60% 78% at 50% 100%, #000 5%, transparent 78%);
          mask-image:radial-gradient(60% 78% at 50% 100%, #000 5%, transparent 78%);
  opacity:0; transition:opacity 1.2s ease .2s;
}
/* The grid lives on an inner layer twice the height, moved with transform.
   Animating `background-position` instead repaints the whole plane on every
   frame for as long as the hero is on screen; a transform is handed to the
   compositor and costs nothing per frame. */
html.mmx .mm-stage::before{
  content:""; position:absolute; left:0; top:0; width:100%; height:200%;
  background-image:
    linear-gradient(rgba(236,0,140,.42) 1px, transparent 1px),
    linear-gradient(90deg, rgba(236,0,140,.30) 1px, transparent 1px);
  background-size:74px 74px;
}
html.mmx .mm-stage.on{ opacity:1; }
html.mmx .mm-stage.mm-hold, html.mmx .mm-stage.mm-hold::before{ animation-play-state:paused; }
@media (prefers-reduced-motion:no-preference){
  html.mmx .mm-stage::before{ animation:mmStage 9s linear infinite; }
  /* and the plane draws itself out from the horizon once, on arrival */
  html.mmx .mm-stage.on{ animation:mmStageIn 1.5s var(--mm-ease) both; }
}
@keyframes mmStage{ from{ transform:translate3d(0,-50%,0); } to{ transform:translate3d(0,0,0); } }
@keyframes mmStageIn{
  from{ transform:translateX(-50%) perspective(460px) rotateX(66deg) scale(.55); opacity:0; }
  to  { transform:translateX(-50%) perspective(460px) rotateX(66deg) scale(1);   opacity:1; }
}

/* The light pool the figure stands in. The grid says "this is our surface";
   the pool says "the figure is ON it" — without one the other reads as a
   pattern behind a cut-out. Two layers, one idea.
   Deliberately NOT applied to the mascot itself: that image is the LCP
   element on a phone, and an element that starts at opacity 0 does not count
   as painted, so animating it in would post a slower Largest Contentful Paint
   for a purely decorative gain. It only floats, which transform can do
   without touching when the pixel first lands. */
html.mmx .mm-fig3d::after{
  content:""; position:absolute; left:50%; bottom:-3%; z-index:0;
  width:78%; height:16%; min-height:34px; transform:translateX(-50%);
  border-radius:50%; pointer-events:none;
  background:radial-gradient(closest-side, rgba(236,0,140,.55), rgba(236,0,140,.16) 55%, transparent 75%);
  filter:blur(6px);
  opacity:0; transition:opacity 1.1s ease .45s;
}
html.mmx .mm-fig3d.on::after{ opacity:1; }

/* the figure itself breathes, very slightly, and casts its glow forward */
@media (prefers-reduced-motion:no-preference){
  /* index / clinic / automotive only. The landing page mascot already carries
     its own `lpbreathe`, deliberately switched off below 900px — leave it. */
  .heroX .hx-gor{ animation:mmFloat 7.5s ease-in-out infinite; }
}
@keyframes mmFloat{ 0%,100%{ transform:translate3d(0,0,0); } 50%{ transform:translate3d(0,-9px,0); } }

/* ==========================================================================
   12 · DEPTH ON SCROLL  —  what replaces hover on a phone
   --------------------------------------------------------------------------
   Desktop has had cursor-tilt cards since the first enhancement pass. A phone
   has no cursor, so the same depth is driven by the only input a phone
   actually has: the scroll position. Where the browser supports scroll-driven
   animations these run entirely off the main thread, which is the only way to
   put this much motion on a mid-range Android without dropping frames.
   Everywhere else it simply does not run, and the card is the card.
   ========================================================================== */
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){

    /* NOTE ON THE STRIPS. A scroll-linked lean was built here first: each
       frame rotating on Y as it crossed the scrollport. It was removed after
       looking at it. The strips hold the client photography and the ad
       creative — the product itself — and rotating a photograph in
       perspective distorts the thing the reader came to judge, while
       overriding the hover zoom that already earns its place on desktop.
       Motion that costs the work its own presentation is not an enhancement.
       The strips keep their fade, their rail and their snap; the frames stay
       rectangular and honest.

       The hero stage recedes as the hero leaves, which is depth applied to
       something decorative by definition. */
    html.mmx .mm-stage.on{
      animation:mmStageIn 1.5s var(--mm-ease) both, mmStageOut linear both;
      animation-timeline:auto, view();
      animation-range:normal, exit 0% exit 100%;
    }
    @keyframes mmStageOut{
      from{ opacity:1; }
      to  { opacity:.15; }
    }

    /* Dark-band glow gains a touch of life as its section passes. One
       property, opacity, on a layer that is already painted.
       Desktop only: on a phone this is an opacity change on a full-width
       radial-gradient layer every frame, and the phone's frame budget is
       better spent on the content scrolling over it. The glow is still there,
       it simply holds still. */
    @media (min-width:901px){
    .stats::before, .cta-final::before,
    .network::before, .craft::before{
      animation:mmGlow linear both;
      animation-timeline:view();
      animation-range:entry 0% exit 100%;
    }
    }
    @keyframes mmGlow{ 0%{opacity:.35} 50%{opacity:1} 100%{opacity:.35} }

    /* NOTE: no scroll-progress bar is added here. Every page already ships
       `.scrollprog`, a 3px fixed bar at the top of the viewport. A second
       progress indicator would be the exact kind of element that carries no
       information the reader does not already have. */
  }
}

/* ==========================================================================
   13 · THE STRIPS ON A PHONE
   --------------------------------------------------------------------------
   The photo and ad-creative strips are the proof on this site: they are the
   work. On a phone they were 200–230px tall, which put roughly one and a bit
   frames on screen and made the best asset on the page the quietest thing on
   it. They are now sized to the viewport, so a phone shows one frame properly
   plus the edge of the next — the standard signal that a row continues.

   Three affordances come with that, and each one is answering a question the
   reader actually has:
     · a fade at whichever edge has content beyond it  ("there is more")
     · a hairline progress rail under the row          ("how much more")
     · scroll-snap, so a flick lands on a frame        ("I am in control")
   The fade is driven by --mL/--mR, which enhance.js sets from scrollLeft, so
   at rest the first frame is never dimmed for no reason.
   ========================================================================== */
@media (max-width:900px){
.workstrip .ws-row,
.crstrip,
.lprow,
.tests .grid{
  -webkit-mask-image:linear-gradient(90deg,
    transparent 0, #000 var(--mL,0px),
    #000 calc(100% - var(--mR,0px)), transparent 100%);
          mask-image:linear-gradient(90deg,
    transparent 0, #000 var(--mL,0px),
    #000 calc(100% - var(--mR,0px)), transparent 100%);
  /* No transition on mask-image. A mask is rasterised, not interpolated on the
     compositor, so animating it repaints the whole strip every frame — it cost
     about 10fps across the image-heavy pages on a 4x-throttled CPU. The values
     move in single pixels as you scroll, so stepping them reads as smooth.

     Phone only. A mask forces the whole strip into its own compositing pass,
     and on desktop the affordance is already there: a visible scrollbar on the
     creative strip, a grab cursor and drag on the photo strips, and a pointer
     that can simply hover past the edge. Paying for it twice made no sense. */
}
}

/* the rail: 2px, the width of the strip, filled to the scroll position */
html.mmx .mm-rail{
  position:relative; height:2px; border-radius:2px;
  background:rgba(255,255,255,.12);
  margin:16px auto 0; width:min(150px,38%);
  overflow:hidden;
}
/* A strip that turns out not to scroll hides its rail with visibility, never
   display: the 18px stays reserved, so nothing on the page moves when images
   finish loading and the measurement changes. Layout shift is a cost the
   reader pays for a decoration, which is never a trade worth making. */
html.mmx .mm-rail.off{ visibility:hidden; }
html.mmx .mm-rail.light{ background:rgba(10,10,12,.12); }
html.mmx .mm-rail i{
  position:absolute; left:0; top:0; bottom:0; border-radius:2px;
  width:var(--rw,30%); transform:translateX(var(--rx,0%));
  background:var(--pink);
  transition:transform .12s linear;
}
@media (min-width:901px){ html.mmx .mm-rail{ display:none; } }

/* Scroll-snap aligns a card's start edge with the SNAPPORT edge, which ignores
   the strip's own left padding — so at rest the browser quietly scrolled each
   strip 24px and the first card sat flush against the screen edge instead of
   lining up under its heading. scroll-padding is what snapping reads. */
.crstrip{ scroll-padding-left:max(24px, calc((100vw - 1180px)/2)); }
.workstrip .ws-row, .craftrow, .tests .grid{ scroll-padding-left:24px; }

@media (max-width:900px){
  /* one frame, properly, plus the edge of the next.
     The row also breaks its 24px gutter and runs to both screen edges: on a
     phone that is the difference between a photograph and a thumbnail, and it
     is what puts the next frame on screen so the strip reads as a strip. The
     first frame still lines up under the heading. */
  .workstrip .ws-row{
    scroll-snap-type:x proximity;
    margin-left:-24px; margin-right:-24px;
    padding-left:24px; padding-right:24px;
  }
  .workstrip .wf{ height:min(70vw,300px); border-radius:16px; }
  .ppxm .wf{ height:min(66vw,290px); }
  .crstrip{ --ah:min(72vw,310px); gap:12px; }
  .crcard{
    border-radius:16px;
    /* A 54px-blur drop shadow under every card in a 34-card strip is a large
       blurred raster per card, and on the ink background it is invisible
       anyway. The border already separates the card from the band. */
    box-shadow:none;
  }
  /* The muted-until-hover treatment cannot fire without a hover, so on touch
     it only ever subtracts: every frame of the client's photography shown
     desaturated, with no way to see it otherwise. Dropping the filter outright
     also drops a filtered raster per image, which is the single cheapest
     rendering saving available on these pages. The work shows at full strength
     and costs less to draw. */
  .workstrip .wf img,
  .workstrip .wf video{ filter:none; }
  /* the category label is a hover affordance on desktop; on touch it would
     never appear at all, so it rests visible and quiet instead */
  .workstrip .wf .tag{ opacity:.92; transform:none; }
}

/* --------------------------------------------------------------------------
   13.1 · THE CRAFT ROW
   Below 900px `.craftrow` becomes a horizontal snap row of 74%-wide cards.
   The next card was being sliced mid-sentence with a hard edge, which reads
   as a layout fault rather than as a row that continues. Widened to 82% and
   given the same edge fade as every other strip.
   -------------------------------------------------------------------------- */
@media (max-width:900px){
  .craftrow{
    scroll-snap-type:x proximity;
    gap:14px; padding-bottom:10px;
    -webkit-mask-image:linear-gradient(90deg, transparent 0, #000 var(--mL,0px), #000 calc(100% - var(--mR,0px)), transparent 100%);
            mask-image:linear-gradient(90deg, transparent 0, #000 var(--mL,0px), #000 calc(100% - var(--mR,0px)), transparent 100%);
  }
  .craftrow .ci{ flex:0 0 82%; }
}

/* ==========================================================================
   14 · THE PHONE BUILD
   --------------------------------------------------------------------------
   Everything in this block exists because it was measured on a 390×844
   viewport, not because it looked plausible in a stylesheet.
   ========================================================================== */
@media (max-width:900px){

  /* 14.1 · THE HERO.
     The mascot ran to roughly 360px before the first word of the headline,
     which put the primary call to action level with the fold on a 667px
     phone. The figure keeps its presence — it is the brand — but it is now
     sized against the viewport rather than a fixed pixel box, and the space
     around it is tightened, so the headline, the promise and both buttons
     land inside the first screen on every phone down to an iPhone SE. */
  .heroX{ padding:26px 0 40px; }
  .heroX .wrap{ gap:14px; }
  .heroX .hx-gor{ max-width:min(52vw,250px); }
  .heroX .hx-text .eyebrow{ margin-bottom:14px; }
  .heroX .sub{ margin-top:16px; }
  .heroX .cta{ margin-top:22px; }
  .heroX .hx-trust{ margin-top:20px; }
  /* the three trust marks read as one row of three, not a ragged wrap */
  .heroX .hx-trust{ gap:8px 16px; }
}
@media (max-width:640px){
  .heroX .hx-gor{ max-width:min(50vw,215px); }
  .heroX{ padding:20px 0 36px; }
}
/* very short phones (SE, mini) — the figure yields first, never the message */
@media (max-width:900px) and (max-height:700px){
  .heroX .hx-gor{ max-width:min(40vw,175px); }
  .heroX{ padding:16px 0 32px; }
}

@media (max-width:900px){
  /* 14.2 · TAP TARGETS.
     Measured, not guessed: every link, button and <summary> on the page was
     sized at 390px and anything under 44px in either axis is listed here.
     Nothing moves visually — the type and the rule stay exactly where they
     were, the hit area grows around them. */
  .workstrip .ws-link{ padding:13px 0 11px; }
  footer .fcol a{ padding:10px 0; }
  .fbot a{ display:inline-block; padding:13px 0; }
  nav .logo, .lpbrand{ padding:12px 0; }
  .lpfoot a{ display:inline-block; padding:12px 0; }
  .lpfoot .wrap span:last-child{ display:flex; gap:6px 20px; flex-wrap:wrap; }
  .ppxm .ppxm-foot a, .ppx .ppx-foot a{ display:inline-block; padding:12px 0; }
  summary{ padding-top:9px; padding-bottom:9px; }
  /* the three social links sit on one row, so height is all they can gain */
  footer .fcol a[href*="instagram"], footer .fcol a[href*="linkedin"],
  footer .fcol a[href*="facebook"]{ padding:12px 0; }
  /* Arrows on the site-preview carousel. `html` prefix because several pages
     carry a second <style> block in the BODY, which loses on specificity but
     wins on source order against a stylesheet linked in the head. One extra
     element in the selector settles it without !important. */
  html .crm-nav{ width:44px; height:44px; }
  /* the menu button is the one control every phone visitor uses */
  html .burger{ min-width:44px; min-height:44px; }
  /* the cookie banner: declining must be as easy to hit as accepting */
  .cbtn{ min-height:44px; }

  /* 14.3 · THE STICKY BAR.
     It sat 16px from the bottom edge on every device, which on any iPhone
     with a home indicator puts it under the gesture bar. It now clears the
     safe area, and it slides out of the way rather than covering the booking
     calendar it is pointing at — a button that scrolls you to something you
     are already looking at is noise. */
  .sticky{
    bottom:calc(14px + env(safe-area-inset-bottom,0px));
    transition:transform .38s var(--mm-ease), opacity .3s ease;
  }
  html.mmx .sticky.mm-away{
    transform:translate3d(0,calc(100% + 26px),0); opacity:0; pointer-events:none;
  }
  .sticky a{
    box-shadow:0 16px 34px -14px rgba(236,0,140,.75), inset 0 1px 0 rgba(255,255,255,.26);
  }

  /* 14.4 · THE MOBILE MENU.
     A plain dropdown. The links now arrive in sequence when it opens, which
     costs nothing and makes the one piece of chrome everybody touches feel
     built rather than defaulted. */
  /* The panel was 96% opaque over a 16px backdrop blur. Four percent of a
     bright hero is not nothing: the headline, the mascot and the hero buttons
     all hazed through the menu, which is the one piece of chrome that has to
     be legible instantly. A diff of the open menu against the same shot with
     the page hidden put 809,836 pixels out by more than 20. It is opaque now,
     and the backdrop filter is gone with it — once nothing shows through, a
     blur of what is behind costs a compositing pass every frame for a result
     nobody can see.

     max-height keeps the panel inside the viewport. On a 568px phone the menu
     is taller than the screen, so the last links sat below the fold with no
     way to reach them; now the panel scrolls itself. */
  nav .links{
    background:#0c0c10;
    box-shadow:0 26px 50px -30px rgba(0,0,0,.9);
    max-height:calc(100dvh - 68px);
    overflow-y:auto;
    overscroll-behavior:contain;
  }
}
@media (max-width:900px) and (prefers-reduced-motion:no-preference){
  html.mmx nav .links.open > a{ animation:mmNav .42s var(--mm-ease) both; }
  html.mmx nav .links.open > a:nth-child(1){animation-delay:.02s}
  html.mmx nav .links.open > a:nth-child(2){animation-delay:.05s}
  html.mmx nav .links.open > a:nth-child(3){animation-delay:.08s}
  html.mmx nav .links.open > a:nth-child(4){animation-delay:.11s}
  html.mmx nav .links.open > a:nth-child(5){animation-delay:.14s}
  html.mmx nav .links.open > a:nth-child(6){animation-delay:.17s}
  html.mmx nav .links.open > a:nth-child(7){animation-delay:.20s}
  html.mmx nav .links.open > a:nth-child(8){animation-delay:.23s}
  @keyframes mmNav{ from{ opacity:0; transform:translate3d(0,-8px,0); } to{ opacity:1; transform:none; } }
}

/* 14.5 · TESTIMONIALS.
   Three identical white cards stacked down a phone is roughly 900px of the
   same rectangle. They become a snap row: one testimonial at a time, read
   properly, with the next one showing at the edge. Every word stays in the
   document — this is presentation, not truncation. */
@media (max-width:760px){
  .tests .grid{
    display:flex; grid-template-columns:none;
    overflow-x:auto; overflow-y:hidden; overscroll-behavior-y:auto;
    scroll-snap-type:x proximity; gap:12px;
    padding-bottom:6px; margin-left:-24px; margin-right:-24px;
    padding-left:24px; padding-right:24px;
    -webkit-overflow-scrolling:touch; scrollbar-width:none;
  }
  .tests .grid::-webkit-scrollbar{ height:0; }
  .tests .tcard{
    flex:0 0 84%; scroll-snap-align:start; min-width:0;
  }
  /* a wide closing card in the same row would break the rhythm */
  .tests .grid > .tcard.wide{ flex:0 0 92%; }
}

/* 14.6 · THE LOGO ROW.
   Four marks wrapped 3 + 1, which reads as one mark left over. Two rows of
   two is deliberate at any width where four will not fit on one line. */
@media (max-width:560px){
  .plogos{
    display:grid; grid-template-columns:1fr 1fr; gap:16px 10px;
    justify-items:center; max-width:330px; margin-left:auto; margin-right:auto;
  }
}

/* 14.7 · CHIPS.
   A pill whose label wraps onto a second line stops looking like a pill.
   Below 560px the long ones sit as full-width rows instead, which is also
   easier to read. */
@media (max-width:560px){
  .chips span, .bpills span{ max-width:100%; }
}

/* ==========================================================================
   15 · SURFACE  —  one light source, one lift
   --------------------------------------------------------------------------
   The site had three or four different card treatments. They now share the
   same physics: light from above, a 1px inner highlight on the top edge, and
   the same lift on approach. Nothing is recoloured; the palette is untouched.
   ========================================================================== */
.btn:not(.line){
  box-shadow:0 14px 30px -16px rgba(236,0,140,.7), inset 0 1px 0 rgba(255,255,255,.24);
}
.btn:not(.line):hover{
  box-shadow:0 18px 38px -16px rgba(236,0,140,.85), inset 0 1px 0 rgba(255,255,255,.3);
}
.btn:active{ transform:translateY(1px) scale(.988); }

/* touch devices get a real press state, since they get no hover */
@media (hover:none){
  .tests .tcard:active, .network .nc:active,
  .craft .ci:active, .wtile:active,
  .crcard:active, .workstrip .wf:active{
    transform:scale(.988); transition:transform .12s ease;
  }
}

/* ==========================================================================
   16 · REDUCED MOTION
   Every animation added above is switched off here, and every end state is
   restored, so the page is complete and static. This block is the contract:
   nothing in the motion system is load-bearing for content.
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  html.mmx .mm-stage, html.mmx .mm-stage::before, html.mmx .mm-stage.on{ animation:none; }
  .heroX .hx-gor{ animation:none; }
  html.mmx .mmw{ opacity:1; transform:none; transition:none; }
  html.mmx .reveal, html.mmx .js .reveal{ opacity:1; transform:none; transition:none; }
  html.mmx .reveal .eyebrow::before{ transform:none; transition:none; }
  .sticky{ transition:none; }
  html.mmx nav .links.open > a{ animation:none; }
  html.mmx .mm-rail i{ transition:none; }
}

/* ==========================================================================
   17 · THE PHONE'S OWN RHYTHM                               (added 16 Sep 26)
   --------------------------------------------------------------------------
   Every band on the site carried its desktop vertical padding straight down
   to a 390px screen: 84px above and below a section that is 340px wide. On a
   desktop that is composure; on a phone it is dead space between things the
   reader is trying to connect, and it pushed the homepage to roughly nineteen
   screens of scrolling before the booking section.

   The scale below is proportional, not flat — the hierarchy between a major
   band and a minor one is preserved, everything is simply set at a phone's
   scale. Measured effect on the homepage: about 900px removed with no content
   touched, and the page reads tighter rather than thinner.
   ========================================================================== */
@media (max-width:760px){
  .stats, .network, .tests,
  .quote, .book, .lpbook{ padding-top:58px; padding-bottom:58px; }
  .cta-final{ padding-top:64px; padding-bottom:64px; }
  .lpsec, .wsect{ padding-top:56px; padding-bottom:56px; }
  .workstrip, .ppxm{ padding-top:52px; padding-bottom:52px; }
  .craft{ padding-top:50px; padding-bottom:50px; }
  .sect, .statement{ padding-top:46px; padding-bottom:46px; }
  .crshow{ padding-top:48px; padding-bottom:18px; }
  .lpend{ padding-top:52px; padding-bottom:52px; }
  /* the gap between a heading block and the content it introduces closes too */
  .ws-head{ margin-bottom:20px; }
}

/* --------------------------------------------------------------------------
   17.1 · THE FOOTER
   One column on a phone made the footer a thousand pixels tall — longer than
   several of the sections above it, and the last thing anyone sees. The two
   link columns sit side by side; the brand column keeps the full width. Same
   links, same order, roughly half the height.
   -------------------------------------------------------------------------- */
@media (max-width:760px){
  footer .fgrid{
    grid-template-columns:1fr 1fr; gap:22px 20px; padding:28px 24px 8px;
  }
  footer .fgrid > .fcol:first-child{ grid-column:1 / -1; }
  footer .fcol a{ padding:10px 0; font-size:13px; }
  /* the three social links share one row, so height is all they can gain */
  footer .fcol a[href*="instagram"], footer .fcol a[href*="linkedin"],
  footer .fcol a[href*="facebook"]{ padding:12px 0; }
}

/* --------------------------------------------------------------------------
   17.2 · PILLS THAT WRAP
   A pill is a pill because its label fits on one line. Where a label is long
   enough to wrap on a phone the row becomes a stack of full-width rows, which
   is what the label needed in the first place.
   -------------------------------------------------------------------------- */
@media (max-width:560px){
  .pillrow{ gap:8px; }
  .pillrow span{ width:100%; text-align:left; }
}

/* --------------------------------------------------------------------------
   17.3 · CAPTION ROWS UNDER THE SITE SHOTS  (/work)
   Title and "Explore the build" shared a row; when the title wrapped, the
   link stayed pinned to the first line and the pair stopped reading as one
   caption. On a phone the link drops beneath the title it belongs to.
   -------------------------------------------------------------------------- */
@media (max-width:640px){
  .sitesx .sx-cap, .sitesx figcaption{
    display:block;
  }
  .sitesx figcaption a, .sitesx .sx-cap a{
    display:inline-block; margin-top:6px;
  }
}

/* ==========================================================================
   18 · THE FLAGSHIP CARD                                    (rebuilt 16 Sep 26)
   --------------------------------------------------------------------------
   This is the first block under the hero, which makes it the most valuable
   space on the site. It held a list of three services: Google Ads, Meta Ads,
   Content. Four hundred pixels below it sits "One partner for the whole
   journey", a six-card menu that already contains Paid ads (Google and Meta)
   and Content we shoot. Two service lists back to back, the second one better
   than the first. No amount of rewriting fixes a section that repeats the one
   under it, which is why three passes of copy on it never landed.

   So the job changed. The menu below answers "what do you offer". This block
   now answers the question a reader actually has first, which is "why would
   yours work" — with the one thing here that a competitor cannot copy onto
   their own site, and three terms of engagement that are only sayable if they
   are true. Seven elements became four, and the card has a focal point again.

   Structurally it is the same hairline ledger as the booking panel (section
   19), in its dark form. One pattern, two tones.
   ========================================================================== */
/* The two columns are close in height now, so they simply centre against each
   other. The row/span scheme here dated from a much taller ledger and a much
   shorter text column; with the heading at display scale it left an empty
   implicit row across the bottom of the card about 130px deep. */
.flagship{ align-items:center; }
.flagship .inner{ grid-column:1; grid-row:1; align-self:center; }
.flagship .fledger{ grid-column:2; grid-row:1; align-self:center; }

.flagship .fgo{ display:flex; align-items:center; gap:14px 22px; flex-wrap:wrap; margin-top:26px; position:relative; }
.flagship .fgo-alt{
  position:relative; display:inline-flex; align-items:center; gap:8px;
  font-weight:800; font-size:14px; color:#fff; padding:4px 0; transition:color .2s ease;
}
.flagship .fgo-alt span{ transition:transform .25s var(--mm-ease,cubic-bezier(.16,1,.3,1)); }
.flagship .fgo-alt::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:2px;
  background:var(--pink); transform:scaleX(1); transform-origin:left;
  transition:transform .3s var(--mm-ease,cubic-bezier(.16,1,.3,1));
}
.flagship .fgo-alt:hover span, .flagship .fgo-alt:focus-visible span{ transform:translateX(4px); }
.flagship .fgo-alt:hover, .flagship .fgo-alt:focus-visible{ color:var(--pink-lt,#ff6ab8); }

/* the ledger: three terms, hairline separated, the brand diamond as the mark */
.flagship .fledger{
  border:1px solid rgba(255,255,255,.13); border-radius:18px; overflow:hidden;
  background:rgba(255,255,255,.03);
}
.flagship .fl{ padding:18px 20px; border-bottom:1px solid rgba(255,255,255,.10); }
.flagship .fl:last-child{ border-bottom:0; }
.flagship .fl b{
  display:flex; align-items:flex-start; gap:10px;
  font-size:15.5px; font-weight:800; color:#fff; letter-spacing:-.01em; line-height:1.3;
}
.flagship .fl b::before{
  content:"\25C6"; color:var(--pink); font-size:9px; line-height:1.9; flex:none;
}
.flagship .fl em{
  display:block; font-style:normal; margin:5px 0 0 19px;
  font-size:14px; line-height:1.55; color:#b9b9c4; font-weight:400;
}

@media (max-width:900px){
  .flagship .inner, .flagship .fledger{ grid-column:auto; grid-row:auto; }
  .flagship .fgo{ margin-top:6px; }
  .flagship .fgo-alt{ padding:12px 0; }
  .flagship .fl{ padding:16px 17px; }
}

/* ==========================================================================
   20 · ICON WEIGHT                                        (normalised 16 Sep 26)
   --------------------------------------------------------------------------
   Every line icon on the site is already drawn on the same 24-unit grid with
   round caps and round joins. What was not consistent was how heavy each one
   LOOKS, because stroke-width was set per icon while the rendered size varied
   from 13px to 26px. Optical weight is the product of the two, and it ranged
   from 1.46 to 2.17 device pixels:

       .pfflow   14px x 2.5  = 1.46      .ni       20px x 2    = 1.67
       .ws-link  16px x 2.4  = 1.60      .ic       22px x 2    = 1.83
       .dot      13px x 3    = 1.63      .crm-nav  20px x 2.4  = 2.00
       .pi       21px x 1.9  = 1.66      .lpshield 26px x 2    = 2.17

   Two icons the same size looked like different weights, and the arrows read
   noticeably lighter than the ticks beside them. Everything is now set to the
   same 1.7 device pixels, solving stroke-width = 1.7 x 24 / rendered size.
   A presentation attribute loses to a stylesheet, so this corrects all 105
   icons without touching a single path.

   The brand marks are deliberately excluded: Google, Meta, LinkedIn, TikTok
   and WhatsApp are filled logos drawn to their owners' specifications and are
   not ours to restyle.
   ========================================================================== */
.dot svg      { stroke-width:3.14; }   /* 13px */
.pfflow svg   { stroke-width:2.91; }   /* 14px */
.ws-link svg  { stroke-width:2.55; }   /* 16px */
.ni svg,
.crm-nav svg  { stroke-width:2.04; }   /* 20px */
.pi svg       { stroke-width:1.94; }   /* 21px */
.ic svg,
.bic svg      { stroke-width:1.85; }   /* 22px */
.lpshield svg { stroke-width:1.57; }   /* 26px */

/* `.ic` is used by two components at two sizes, and inside one of them the
   icons were not even the same size as each other. Size is pinned first, then
   the weight that lands on 1.7 at that size. Consistent size is the more
   visible half of "consistent icons". */
.tsect .ic svg{ width:20px; height:20px; stroke-width:2.04; }   /* 20px */

/* ==========================================================================
   19 · WHAT A PROPOSAL INVOLVES                          (rebuilt 16 Sep 26)
   --------------------------------------------------------------------------
   A three-field "leave your email" box shipped here first and was wrong, for a
   reason that matters more than the layout: a proposal from this business is
   researched and costed, and it is not something to hand to anyone who types
   an address. Stripping the ask down cheapened the thing being asked for.

   So the friction goes back in, and it is made to earn its place. The reader
   is told what the extra two minutes buys them — a call that starts already
   informed, and a proposal written around their business rather than a
   template. That is the actual conversion lever on a considered purchase:
   not fewer fields, but less uncertainty about what happens next.

   Register matters as much as the structure here. [[monsta-pricing-rule]]
   records ten rejected attempts at the money sentence on the landing page, and
   the two that read worst were the ones centred on Monsta's selectivity —
   "there is no rate card", "the smallest quarter we take on". Nothing below
   says what we accept or screen for. It says what the reader gets and what it
   costs them in time.

   Built as the ledger panel the landing page already uses (.lproles, .lpuse,
   .lpterm): one bordered panel, hairline rows, label on its own line with a
   short line beneath. Reusing that shape is what keeps the site one piece of
   work rather than a collection of good ideas.
   ========================================================================== */
.nextup{
  max-width:720px; margin:30px auto 0; text-align:left;
  border:1px solid var(--line,#e7e7ec); border-radius:20px;
  background:#fff; overflow:hidden;
}
/* The booking band centres its own intro paragraph with a max-width and auto
   margins. Every <p> inside this panel inherited that and sat centred in a
   left-aligned ledger, which is the kind of near-miss that reads as careless
   without being obviously wrong. Reset it once, here. */
/* `.book .head p` (0,2,1) sets max-width:48ch and auto margins on every
   paragraph in the band, so the panel's own lines sat centred inside a
   left-aligned ledger. Matched on specificity rather than reached for
   !important. */
.book .head .nextup p, .book .head .nextup em,
.book .head .nextup li, .book .head .nextup b,
.nextup .nu-lead, .nextup .nu-steps em{
  max-width:none; margin-left:0; margin-right:0;
}
.nextup .nu-lead{
  margin:0; padding:16px 22px; font-size:11.5px; font-weight:800;
  letter-spacing:.14em; text-transform:uppercase; color:#0f0f12;
  border-bottom:1px solid var(--line,#e7e7ec);
  display:flex; align-items:center; justify-content:flex-start; gap:10px;
  text-align:left;   /* the band above is centred; a ledger is not */
}
/* the brand diamond marks a panel header, exactly as it does on the LP */
.nextup .nu-lead::before{
  content:"\25C6"; color:var(--pink-dp,#c70b78); font-size:9px; line-height:1;
}
.nextup .nu-steps{ list-style:none; margin:0; padding:0; }
.nextup .nu-steps li{
  display:flex; gap:16px; align-items:flex-start;
  padding:18px 22px; border-bottom:1px solid var(--line,#e7e7ec);
}
.nextup .nu-n{
  flex:0 0 auto; font-size:12px; font-weight:900; letter-spacing:.06em;
  color:var(--pink-dp,#c70b78); padding-top:2px; min-width:22px;
}
.nextup .nu-steps b{
  display:block; font-size:15.5px; font-weight:800; color:#0f0f12; letter-spacing:-.01em;
}
.nextup .nu-steps em{
  display:block; font-style:normal; margin-top:4px;
  font-size:14px; line-height:1.55; color:#5b5b66; font-weight:400;
}
.nextup .nu-go{
  display:flex; align-items:center; gap:14px 18px; flex-wrap:wrap;
  padding:20px 22px; background:var(--mist,#f5f5f7);
}
.nextup .nu-go .btn{ margin:0; }
.nextup .nu-or{ font-size:13.5px; color:#6a6a76; font-weight:600; }
/* three routes, one row: answer the questions, pick a time, or message */
.nextup .nu-go .wabtn{ margin-left:auto; }
@media (max-width:860px){ .nextup .nu-go .wabtn{ margin-left:0; } }

.book .altcta{ margin-top:18px; }

@media (max-width:720px){
  .nextup{ margin-top:24px; border-radius:18px; }
  .nextup .nu-lead{ padding:14px 18px; }
  .nextup .nu-steps li{ padding:16px 18px; gap:13px; }
  .nextup .nu-go{ padding:18px; }
  .nextup .nu-go .btn{ width:100%; justify-content:center; }
  .nextup .nu-or{ width:100%; text-align:center; }
  .nextup .nu-go .wabtn{ width:100%; justify-content:center; }
}

/* ==========================================================================
   20 · ICON TILES: ONE TREATMENT                          (aligned 16 Sep 26)
   --------------------------------------------------------------------------
   The site has three components that put a brand-pink tile behind a small
   mark: `.ni` on the network cards, `.ic` on the feature tiles, and `.pi` on
   the flagship rows. `.ni` and `.ic` already carried depth — a gradient, an
   inner highlight on the top edge and a soft cast glow. `.pi` was a flat pink
   square, which is the cheapest-looking element on the highest-value section
   of the homepage. It now gets the same treatment.

   The gradient also corrects a fourth pink. `.ni` was mixing to `#ff4fae`,
   which is not one of the three the palette allows. It is now `--pink-lt`
   (#ff6ab8), the established tint, so every icon tile on the site mixes the
   same two brand values.
   ========================================================================== */
.network .nc .ni,
.flagship .prow .pi{
  background:linear-gradient(155deg, var(--pink-lt,#ff6ab8), var(--pink) 62%);
  box-shadow:0 10px 24px -12px rgba(236,0,140,.75), inset 0 1px 0 rgba(255,255,255,.28);
}
.flagship .prow .pi{ transition:transform .3s ease, box-shadow .3s ease; }
.flagship .prow{ transition:transform .25s cubic-bezier(.2,.7,.2,1), border-color .3s ease, background .3s ease; }
.flagship .prow:hover{
  transform:translateY(-2px);
  border-color:rgba(236,0,140,.38);
  background:rgba(255,255,255,.07);
}
.flagship .prow:hover .pi{
  transform:translateY(-1px) scale(1.04);
  box-shadow:0 14px 28px -12px rgba(236,0,140,.9), inset 0 1px 0 rgba(255,255,255,.34);
}
@media (hover:none){
  .flagship .prow, .flagship .prow .pi{ transform:none !important; }
}
@media (prefers-reduced-motion:reduce){
  .flagship .prow, .flagship .prow .pi{ transition:none; }
}

/* the skip control on an optional question: present, never louder than the
   answer it is offering to bypass */
.eqnav .eqskip{
  background:none; border:0; cursor:pointer; font:inherit;
  font-weight:700; font-size:13.5px; color:#6a6a76;
  padding:12px 14px; border-radius:30px; transition:color .18s ease, background .18s ease;
}
.eqnav .eqskip:hover, .eqnav .eqskip:focus-visible{ color:#0f0f12; background:rgba(10,10,12,.05); }

/* The pink bar under the second line of a headline is the site's signature
   mark, defined on `.heroX` and the landing pages but never on `.lg-hero`
   (/work). Same values, so the mark is identical wherever a hero uses it. */
.lg-hero h1 .hl, .eqhero h1 .hl{
  background:linear-gradient(180deg, transparent 58%, rgba(236,0,140,.6) 58%);
  padding:0 .04em;
}

/* ============================================================
   21 · A HEADING THAT IS A LINK
   Several section headings are a single inline link. Inline text sets its own
   box from the font, so the tap target came out 25px tall — a finger is about
   44px, and a miss on a heading link reads as the site ignoring you.
   Padding makes the box the right height and an equal negative margin gives
   the space straight back to the line, so the target grows and nothing on the
   page moves. Touch only: a mouse already hits 25px without thinking.
   ============================================================ */
@media (hover:none) and (pointer:coarse){
  h2 > a:only-child, h3 > a:only-child{
    display:inline-block;
    padding-top:10px; padding-bottom:10px;
    margin-top:-10px; margin-bottom:-10px;
  }
}

/* ============================================================
   22 · THE FLAGSHIP, AT THE SCALE ITS POSITION DESERVES
   This card is the second thing on the homepage and the first argument the
   site makes, and it was set at the same size as a mid-page feature block —
   a 24px heading on a phone, directly under a 34px hero. Position and
   typographic weight disagreed, so the reader's eye went straight past it to
   the photography below.

   It now opens at display scale with the signature pink bar under the second
   line, which is the hero's own device and the reason the two read as one
   thought rather than two sections. The 72px grid behind every dark band on
   this site is laid into the card as well, masked away from the text and
   fading out before it reaches the ledger, so the surface has material to it
   without competing with a word.

   Prefixed `html ` throughout: several pages carry a second <style> in the
   BODY that wins on source order against this file at equal specificity.
   ============================================================ */
html .flagship{ padding:46px 44px; border-radius:28px; }

html .flagship h2{
  font-size:clamp(30px,4.3vw,50px);
  line-height:1.04;
  letter-spacing:-.022em;
  margin:15px 0 17px;
  text-wrap:balance;
}
html .flagship h2 .hl{
  background:linear-gradient(180deg, transparent 58%, rgba(236,0,140,.6) 58%);
  padding:0 .04em;
}
html .flagship p{
  font-size:16.5px; line-height:1.62; color:#dcdce4; max-width:40ch;
}

/* the surface. Two hairline gradients, no image, no extra request. */
html .flagship::after{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background-image:
    linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px);
  background-size:72px 72px;
  -webkit-mask-image:radial-gradient(118% 108% at 100% 0%, #000 6%, transparent 60%);
  mask-image:radial-gradient(118% 108% at 100% 0%, #000 6%, transparent 60%);
}
html .flagship .inner, html .flagship .fledger,
html .flagship .platforms{ position:relative; z-index:1; }

/* -- the stage rows -------------------------------------------------------
   Four rows, one per stage of the path the heading names, on the icon-tile
   component this card was originally built with. Type is set against the
   heading rather than left at the old 15/13, because at display scale the
   rows read as a caption otherwise. The text sits in its own wrapper so the
   tile stays a fixed flex item and the two lines stack against it. */
html .flagship .platforms{ gap:10px; }
html .flagship .prow{ padding:14px 16px; align-items:flex-start; gap:13px; }
html .flagship .prow .pi{ width:38px; height:38px; flex:0 0 38px; border-radius:11px; margin-top:1px; }
html .flagship .prow .pt{ min-width:0; }
html .flagship .prow b{ font-size:15.5px; line-height:1.25; display:block; }
html .flagship .prow em{ font-size:13.5px; line-height:1.45; color:#c2c2cd; margin-top:3px; }

@media (max-width:900px){
  html .flagship .platforms{ gap:9px; }
  html .flagship .prow{ padding:13px 14px; gap:12px; }
  html .flagship .prow .pi{ width:34px; height:34px; flex:0 0 34px; border-radius:10px; }
  html .flagship .prow b{ font-size:15px; }
  html .flagship .prow em{ font-size:13px; }
}

/* A phone gets the same presence at its own scale: the heading still opens
   bigger than anything below it, and the padding comes in so the ledger keeps
   its full width. */
@media (max-width:900px){
  html .flagship{ padding:32px 24px; border-radius:24px; }
  html .flagship h2{ font-size:clamp(29px,8.4vw,40px); margin:13px 0 15px; line-height:1.17; }
  html .flagship p{ font-size:16px; max-width:none; }

  /* The marked phrase fits one line on a laptop and two on a phone. At the
     desktop's 1.04 leading the two bars meet and read as one solid slab, so a
     phone gets looser leading to separate them and a thinner bar to keep the
     mark light. `box-decoration-break: clone` is what gives the second line
     its own padded end instead of a bar sheared off mid-word. */
  html .flagship h2 .hl{
    background:linear-gradient(180deg, transparent 72%, rgba(236,0,140,.72) 72%);
    padding:0 .06em;
    -webkit-box-decoration-break:clone; box-decoration-break:clone;
  }
}

/* ============================================================
   23 · THE SEAM BETWEEN SECTIONS
   Eighteen pages are built from bands that alternate ink, mist and white, and
   every boundary between them was a straight cut. Two things went wrong with
   that. Where the tone changed, the page read as stacked blocks rather than one
   composed document. Where it did not change — the FAQ and the booking panel
   are both mist, the stats band and the network band are both ink — two
   sections merged into a single slab several thousand pixels deep with nothing
   to say one had ended.

   So every band now opens with a seam, in its own tone:

     · an ink band takes a fine light hairline and a soft bloom of brand pink
       bleeding a short way down from it, so arriving at a dark section feels
       lit rather than cut;
     · a light band takes a single hairline, invisible where it meets ink and
       exactly enough where it meets more light.

   Both are inset box-shadows. Nothing here is a pseudo-element, so no existing
   ::before or ::after is disturbed; nothing occupies space, so no layout moves;
   and both paint once with the background rather than on every frame.

   Heroes are excluded on purpose: a seam marks a join, and nothing joins above
   the first section on a page. The two bands that continue /work's hero
   (.casewrap, .reelsvid) are excluded for the same reason — they are one block
   with it, and a line there would break a run that is meant to be continuous.
   ============================================================ */
.workstrip, .crshow, .crsx, .wsect, .craft, .network, .stats.spine, .tsect,
.cta-final, .mkt, .lpsec.ink, .lpvid, .lpvals, .lpend{
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.085),
    inset 0 44px 56px -56px rgba(236,0,140,.55);
}

.book, .lpbook, .sect.mist, .lpsec.mist, .sitesx,
.sect.crmshow, .sect.pfolio, .tests{
  box-shadow: inset 0 1px 0 rgba(15,15,18,.07);
}

/* The pink statement band is the one section that is neither: it is a full
   stop in the middle of the page, and a seam on it would soften exactly the
   abruptness it exists for. */

/* ============================================================
   24 · ONE HERO SCALE
   `.heroX` is one component used on three pages, and it was carrying two
   completely different type scales: the homepage capped at 70px, clinic and
   automotive at 86px. The bigger number was not the bigger hero. Both of those
   headlines are written as two lines with an explicit <br>, and at 86px in a
   666px column each of those lines wrapped again — so the hero rendered as
   four lines occupying 38% of a 900px viewport, and 24% of an iPhone SE.
   The page's most important sentence was also its least composed.

   One clamp now governs all three, chosen by measurement rather than taste:
   at 64px the homepage still sets on two lines and the two longer headlines
   set on three, at 21% of the viewport instead of 38%. The mobile scale is
   unified in the same way and lands within a pixel or two of where each page
   already was, so nothing regresses on the 80% of traffic that is on a phone.

   `text-wrap: balance` was on the homepage alone; it is what stops a
   three-line headline ending on a single orphaned word, so all three have it.
   ============================================================ */
@media (min-width:901px){
  html .heroX h1{ font-size:clamp(40px,5.2vw,64px); }
}
@media (max-width:900px){
  html .heroX h1{ font-size:clamp(29px,9.2vw,52px); }
}
html .heroX h1{ text-wrap:balance; }

/* ============================================================
   25 · ONE LABEL SCALE
   Three components do the same job on this site — name the section above its
   heading — and each was set to its own size and tracking: `.eyebrow` at
   12px/.12em, `.tagf` in the flagship card at 11.5px/.14em, `.plabel` above
   the platform row at 11.5px/.14em and a lighter weight. Nobody reads a
   letter-spacing value, but they feel three near-misses as a site that was
   assembled rather than designed.

   All three now share the eyebrow's scale. `.tagf` also takes the leading pink
   rule, because it labels a section like any other; `.plabel` does not, because
   it is a caption sitting centred under a heading rather than a section label,
   and the rule marks sections.
   ============================================================ */
html .tagf{
  display:inline-flex; align-items:center; gap:10px;
  font-size:12px; letter-spacing:.12em; font-weight:800;
}
html .tagf::before{
  content:""; width:22px; height:2px; border-radius:2px;
  background:currentColor; opacity:.85; flex:none;
}
@media (max-width:560px){ html .tagf::before{ width:16px; } }

html .plabel{ font-size:12px; letter-spacing:.12em; font-weight:800; }

/* ============================================================
   26 · THE PROOF SHOULD LOOK LIKE PROOF
   Four white cards on a white band, separated from the page by a single
   hairline: the one section carrying third-party evidence was the flattest
   thing on the site, and on a phone — where these become a swipe row — an
   outline on white gives almost nothing to grab onto.

   The cards take the mist fill used for panels everywhere else, so they read
   as objects rather than outlines, and a quotation mark in brand pink sits at
   the shoulder of each one, which says what the card is before a word of it is
   read. Both are additions to an existing component; the markup, the stars and
   the attributions are untouched.

   The band itself stays white on purpose. Making it mist would have put it
   against the mist band that follows and cost the page a tonal change it uses
   to pace itself.
   ============================================================ */
html .tests .tcard{
  background:#f6f6f9;
  border-color:rgba(15,15,18,.085);
  position:relative;
  isolation:isolate;
}
html .tests .tcard::after{
  content:"\201D";
  position:absolute; right:16px; top:34px;
  font-family:Georgia, 'Times New Roman', serif;
  font-size:92px; line-height:0; font-weight:700;
  color:rgba(236,0,140,.13);
  pointer-events:none; z-index:-1;
}
html .tests .q{ font-size:16.5px; line-height:1.58; }

@media (max-width:760px){
  html .tests .tcard::after{ font-size:74px; right:13px; top:30px; }
}

/* ============================================================
   27 · THE CRAFT ROW FILLS ITS ROW
   `.craftrow` was declared `repeat(5, 1fr)` — five columns, hard-coded to the
   number of cards that happened to be there when it was written. The homepage
   now carries four, so the fifth track sat empty and the whole row stopped
   about 70% of the way across the section, which is what reads as a band of
   dead space down the right-hand side. The cards were also squeezed into
   ~190px each, so a sentence broke across five or six lines and the shortest
   card carried half a card of blank below it.

   `auto-fit` collapses the tracks that have nothing in them and shares the
   width between the rest, so the row fills whatever it is given: four cards on
   the homepage, five on /marketing-agency-london, and any number later,
   without a second rule. At 1180px that is roughly 290px a card rather than
   190px, which takes two lines out of every one of them.

   The mobile rule is untouched: below 760px `.craftrow` is a flex scroll strip
   and `grid-template-columns` is inert there.
   ============================================================ */
html .craftrow{
  grid-template-columns:repeat(auto-fit, minmax(210px, 1fr));
  gap:16px;
}

/* ==========================================================================
   THE ENQUIRY FLOW (.brief)  ·  14 Oct 2026
   Details first, five questions, then call or email. Built by /brief.js and
   mounted in every #book band (and on /enquiry), where the booking calendar
   used to sit open. The calendar now loads inside the card only when the
   visitor chooses it.
   Made from parts the site already owns, not new ones: the pink pill chips
   from the old /enquiry form, the .nextup ledger numerals, the brand diamond,
   the lit pink rule from the trust spine (here it is the progress bar along
   the card's top edge). Three pinks only.
   ========================================================================== */
.brief{ max-width:820px; margin:26px auto 0; text-align:left; }
.bf-card{
  position:relative; background:#fff; border:1px solid var(--line,#e7e7ec);
  border-radius:24px; overflow:hidden;
  box-shadow:0 30px 70px -34px rgba(0,0,0,.40);
}
.bf-rule{ position:absolute; top:0; left:0; right:0; height:3px; background:rgba(15,15,18,.06); z-index:2; }
.bf-rule i{
  display:block; height:100%; width:0; border-radius:0 3px 3px 0;
  background:var(--pink,#EC008C); box-shadow:0 0 12px rgba(236,0,140,.55);
  transition:width .5s cubic-bezier(.2,.7,.2,1);
}
.bf-top{
  display:flex; align-items:center; justify-content:space-between; gap:10px 20px; flex-wrap:wrap;
  padding:22px 30px 18px; border-bottom:1px solid var(--line,#e7e7ec);
}
.bf-stages{ list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:6px 22px; }
.bf-stages li{
  display:flex; align-items:center; gap:8px; margin:0;
  font-size:11.5px; font-weight:800; letter-spacing:.13em; text-transform:uppercase; color:#9a9aa6;
}
.bf-stages .bf-n{ font-size:11.5px; font-weight:900; letter-spacing:.06em; color:#b9b9c4; min-width:16px; }
.bf-stages li.on{ color:#0f0f12; }
.bf-stages li.on .bf-n{ color:var(--pink-dp,#c70b78); }
.bf-stages li.ok{ color:#6a6a76; }
.bf-stages li.ok .bf-n{ font-size:0; }
.bf-stages li.ok .bf-n::before{ content:"\2713"; font-size:12.5px; color:var(--pink-dp,#c70b78); }
.bf-count{ margin:0; font-size:12.5px; font-weight:700; color:#6a6a76; }

.bf-body{ padding:28px 30px 30px; }
.bf-h{ font-size:clamp(21px,2.6vw,27px); line-height:1.15; letter-spacing:-.02em; font-weight:900; margin:0; color:#0f0f12; }
.bf-h:focus{ outline:none; }
.bf-hint{ color:#6a6a76; font-size:14.5px; line-height:1.55; font-weight:500; margin:8px 0 0; max-width:60ch; }
.bf-hint b{ color:#0f0f12; font-weight:700; word-break:break-all; }

.bf-grid{ display:grid; grid-template-columns:1fr 1fr; gap:14px 16px; margin-top:22px; }
.bf-grid.bf-one{ grid-template-columns:1fr; max-width:560px; }
.bf-f{ min-width:0; }
.bf-f label{ display:block; font-weight:800; font-size:13px; letter-spacing:.02em; margin-bottom:7px; color:#0f0f12; }
.bf-f label em{ font-style:normal; font-weight:600; font-size:12px; color:#6a6a76; }
.bf-f input, .bf-f textarea{
  display:block; width:100%; min-height:50px; padding:13px 15px;
  border:1.5px solid var(--line,#e7e7ec); border-radius:14px; background:#fff; color:#0f0f12;
  font:inherit; font-size:16px;           /* 16px stops iOS zooming into the field */
  transition:border-color .15s ease, box-shadow .15s ease;
}
.bf-f input::placeholder, .bf-f textarea::placeholder{ color:#9a9aa6; }
.bf-f input:hover, .bf-f textarea:hover{ border-color:#c7c7d0; }
.bf-f input:focus, .bf-f textarea:focus{ outline:none; border-color:var(--pink,#EC008C); box-shadow:0 0 0 3px rgba(236,0,140,.14); }
.bf-f input[aria-invalid="true"]{ border-color:var(--pink-dp,#c70b78); background:#fff8fc; }
.bf-f textarea{ min-height:108px; resize:vertical; }
.bf-hp{ position:absolute!important; left:-9999px!important; width:1px; height:1px; opacity:0; }

.bf-chips{ display:flex; flex-wrap:wrap; gap:10px; margin-top:20px; }
.bf-chips button{
  border:1.5px solid var(--line,#e7e7ec); background:#fff; color:#0f0f12; cursor:pointer;
  border-radius:32px; padding:12px 18px; min-height:46px;
  font:inherit; font-weight:700; font-size:14px; line-height:1.25;
  transition:border-color .14s ease, background .14s ease, color .14s ease, transform .14s ease, box-shadow .14s ease;
}
.bf-chips button:hover{ border-color:var(--pink,#EC008C); }
.bf-chips button[aria-pressed="true"]{
  background:var(--pink,#EC008C); border-color:var(--pink,#EC008C); color:#fff;
  transform:translateY(-1px); box-shadow:0 10px 22px -14px rgba(236,0,140,.85);
}

.bf-nav{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-top:26px; }
.bf-nav .btn{ margin:0 0 0 auto; }
.bf-nav .btn[disabled]{ opacity:.6; cursor:progress; transform:none; box-shadow:none; }
.bf-back{
  background:none; border:0; padding:12px 2px; cursor:pointer;
  font:inherit; font-weight:800; font-size:14px; color:#6a6a76;
}
.bf-back:hover{ color:#0f0f12; }
.bf-err{
  margin:16px 0 0; padding:11px 14px; border-radius:12px;
  background:#fdeef6; border:1px solid rgba(236,0,140,.35);
  color:var(--pink-dp,#c70b78); font-weight:700; font-size:13.5px; line-height:1.45;
}
.bf-err[hidden]{ display:none; }
.bf-note{ margin:18px 0 0; font-size:12.5px; line-height:1.6; color:#6a6a76; max-width:62ch; }
.bf-note a{ color:#0f0f12; text-decoration:underline; text-underline-offset:2px; }

/* call or email: two doors, same weight */
.bf-routes{ display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-top:22px; }
.bf-route{
  display:flex; align-items:center; gap:16px; width:100%; padding:20px; text-align:left; cursor:pointer;
  border:1.5px solid var(--line,#e7e7ec); border-radius:18px; background:#fff; color:#0f0f12; font:inherit;
  transition:border-color .18s ease, transform .22s cubic-bezier(.2,.7,.2,1), box-shadow .22s ease;
}
.bf-route:hover, .bf-route:focus-visible{ border-color:var(--pink,#EC008C); transform:translateY(-2px); box-shadow:0 18px 36px -22px rgba(236,0,140,.6); }
.bf-ico{
  flex:none; width:46px; height:46px; border-radius:14px; display:grid; place-items:center;
  background:rgba(236,0,140,.08); color:var(--pink-dp,#c70b78); transition:background .18s ease, color .18s ease;
}
.bf-route:hover .bf-ico, .bf-route:focus-visible .bf-ico{ background:var(--pink,#EC008C); color:#fff; }
.bf-rt{ flex:1; min-width:0; }
.bf-rt b{ display:block; font-size:16.5px; font-weight:800; letter-spacing:-.01em; }
.bf-rt em{ display:block; margin-top:3px; font-style:normal; font-size:13.5px; line-height:1.5; color:#6a6a76; font-weight:500; }
.bf-arr{ flex:none; color:var(--pink-dp,#c70b78); font-weight:900; transition:transform .2s ease; }
.bf-route:hover .bf-arr{ transform:translateX(3px); }

/* the calendar, inside the card (rebuilt 14 Oct, evening)
   The card widens for this step so the calendar lays out side by side on a
   laptop (date, times and summary in one view). It sits on a "stage": the
   site's field motif (pink glow + fading grid) in its light form, so the
   calendar's own white card reads as placed, not pasted. A placeholder in
   the calendar's shape holds the space and shimmers until it is ready. */
.brief{ transition:max-width .55s cubic-bezier(.2,.7,.2,1); }
.brief.bf-wide{ max-width:1160px; }
.bf-resume{
  display:inline-flex; align-items:center; gap:9px; margin:0 0 16px; padding:6px 14px 6px 6px;
  border-radius:30px; background:rgba(236,0,140,.07); color:#3a3a44; font-size:13px; font-weight:600; line-height:1.4;
}
.bf-resume span{ flex:none; width:22px; height:22px; border-radius:50%; display:grid; place-items:center; background:var(--pink,#EC008C); color:#fff; font-size:11px; font-weight:900; }
.bf-calhead{ display:flex; align-items:flex-end; justify-content:space-between; gap:18px 32px; flex-wrap:wrap; }
.bf-calintro{ flex:1 1 360px; min-width:0; }
.bf-how{ list-style:none; margin:0; padding:0 0 3px; display:flex; align-items:center; flex:none; }
.bf-how li{ display:flex; align-items:center; gap:8px; margin:0; font-size:12.5px; font-weight:700; color:#8a8a96; white-space:nowrap; }
.bf-how li + li::before{ content:""; flex:none; width:24px; height:1.5px; margin:0 10px; background:var(--line,#e7e7ec); }
.bf-how b{
  flex:none; width:24px; height:24px; border-radius:50%; display:grid; place-items:center;
  border:1.5px solid var(--line,#e7e7ec); background:#fff; color:#9a9aa6; font-size:11.5px; font-weight:900;
}
.bf-how li.on{ color:#0f0f12; }
.bf-how li.on b{ background:var(--pink,#EC008C); border-color:var(--pink,#EC008C); color:#fff; box-shadow:0 6px 14px -6px rgba(236,0,140,.85); }

.bf-stage{
  position:relative; margin:22px -30px 0; padding:0 16px 10px; overflow:hidden;
  border-top:1px solid var(--line,#e7e7ec); border-bottom:1px solid var(--line,#e7e7ec);
  background:radial-gradient(60% 90% at 50% 0%, rgba(236,0,140,.075), transparent 72%), #f7f7f9;
}
.bf-stage::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background-image:linear-gradient(rgba(15,15,18,.04) 1px, transparent 1px), linear-gradient(90deg, rgba(15,15,18,.04) 1px, transparent 1px);
  background-size:48px 48px;
  -webkit-mask-image:radial-gradient(70% 70% at 50% 25%, #000, transparent); mask-image:radial-gradient(70% 70% at 50% 25%, #000, transparent);
}
.bf-frame{ position:relative; z-index:1; min-height:690px; }
.bf-frame iframe{ position:relative; z-index:2; display:block; width:100%; height:700px; border:0; background:transparent; opacity:0; transition:opacity .45s ease; }
.bf-frame.bf-live{ min-height:0; }
.bf-frame.bf-live iframe{ opacity:1; }
.bf-frame .calfall{ position:relative; z-index:2; margin:24px 0 14px; background:#fff; border:1px solid var(--line,#e7e7ec); border-radius:16px; }
.bf-sr{ position:absolute!important; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; margin:0; }

.bf-skel{ position:absolute; inset:0; z-index:1; padding:64px 0 16px; transition:opacity .35s ease; }
.bf-frame.bf-live .bf-skel{ opacity:0; visibility:hidden; transition:opacity .35s ease, visibility 0s .35s; }
.bf-sk-card{
  position:relative; display:grid; grid-template-columns:31% 1fr 25%; height:600px; overflow:hidden;
  background:#fff; border:1px solid rgba(16,24,40,.1); border-radius:8px;
}
.bf-sk-card::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(100deg, transparent 35%, rgba(255,255,255,.8) 50%, transparent 65%);
  background-size:260% 100%; animation:bfShimmer 1.5s linear infinite;
}
@keyframes bfShimmer{ from{ background-position:130% 0; } to{ background-position:-30% 0; } }
.bf-sk-side{ display:flex; flex-direction:column; gap:14px; padding:28px 24px; border-right:1px solid rgba(16,24,40,.08); }
.bf-sk-cal{ padding:28px 24px; }
.bf-sk-days{ display:grid; grid-template-columns:repeat(7, 1fr); gap:20px 8px; margin-top:30px; }
.bf-sk-days i{ display:block; justify-self:center; width:30px; height:30px; border-radius:50%; background:#f1f1f4; }
.bf-sk-days i.on{ background:rgba(236,0,140,.28); }
.bf-sk-slots{ display:flex; flex-direction:column; gap:14px; padding:70px 22px 22px 0; }
.bf-sk-slots i{ display:block; height:44px; border-radius:6px; border:1.5px solid rgba(236,0,140,.22); }
.bf-sk-l{ display:block; height:12px; border-radius:6px; background:#ececf0; }
.bf-sk-l.w40{ width:40%; } .bf-sk-l.w60{ width:60%; } .bf-sk-l.w80{ width:80%; }
.bf-sk-logo{ display:block; width:58px; height:58px; margin-bottom:8px; border-radius:50%; background:#f1f1f4; }
@media (max-width:1099px){
  .bf-skel{ padding-top:16px; }
  .bf-sk-card{ grid-template-columns:1fr; grid-template-rows:auto 1fr; height:640px; }
  .bf-sk-side{ border-right:0; border-bottom:1px solid rgba(16,24,40,.08); padding:22px; }
  .bf-sk-slots{ display:none; }
}

.bf-agenda{ margin-top:22px; }
.bf-label{ margin:0 0 10px; font-size:11.5px; font-weight:800; letter-spacing:.13em; text-transform:uppercase; color:#9a9aa6; }
.bf-agenda ul{ list-style:none; margin:0; padding:0; display:grid; grid-template-columns:repeat(auto-fit, minmax(230px, 1fr)); gap:10px 26px; }
.bf-agenda li{ position:relative; margin:0; padding:0 0 0 20px; font-size:14px; line-height:1.5; color:#3a3a44; }
.bf-agenda li::before{ content:"\25C6"; position:absolute; left:1px; top:5px; font-size:9px; line-height:1; color:var(--pink-dp,#c70b78); }

.bf-calfoot{ display:flex; align-items:center; justify-content:space-between; gap:8px 16px; flex-wrap:wrap; margin-top:20px; padding-top:12px; border-top:1px solid var(--line,#e7e7ec); }
.bf-calalt{ font-size:13px; color:#9a9aa6; }
.bf-calalt a{ font-weight:600; color:#6a6a76; text-decoration:underline; text-underline-offset:2px; }
.bf-calalt a:hover{ color:#0f0f12; }
.bf-slow .bf-calalt a[data-cal-direct]{ color:var(--pink-dp,#c70b78); font-weight:800; }

/* sent */
.bf-tick{
  width:56px; height:56px; border-radius:50%; display:grid; place-items:center; margin-bottom:16px;
  background:var(--pink,#EC008C); color:#fff; font-size:26px; font-weight:900;
  box-shadow:0 14px 30px -14px rgba(236,0,140,.85);
}
.bf-prep{ list-style:none; margin:18px 0 0; padding:0; border-top:1px solid var(--line,#e7e7ec); max-width:640px; }
.bf-prep li{ position:relative; margin:0; padding:12px 0 12px 24px; border-bottom:1px solid var(--line,#e7e7ec); font-size:14.5px; line-height:1.5; color:#3a3a44; }
.bf-prep li::before{ content:"\25C6"; position:absolute; left:2px; top:14px; font-size:9px; line-height:1; color:var(--pink-dp,#c70b78); }
.bf-alt{ margin:20px 0 0; font-size:14.5px; color:#3a3a44; }
.bf-link{
  background:none; border:0; padding:6px 0; cursor:pointer; font:inherit; font-weight:800;
  color:var(--pink-dp,#c70b78); text-decoration:underline; text-underline-offset:3px;
}

/* booked: the card's last screen, in the flow or on /thank-you */
.bf-seal{ position:relative; width:64px; height:64px; margin:0 0 18px; }
.bf-seal span{
  position:absolute; inset:0; border-radius:50%; display:grid; place-items:center;
  background:var(--pink,#EC008C); color:#fff; font-size:28px; font-weight:900;
  box-shadow:0 16px 34px -14px rgba(236,0,140,.9);
  animation:bfSeal .6s cubic-bezier(.2,1.5,.4,1) both;
}
.bf-seal::before{
  content:""; position:absolute; inset:-9px; border-radius:50%; border:2px solid rgba(236,0,140,.4);
  animation:bfRing 1.3s .2s ease-out both;
}
@keyframes bfSeal{ from{ opacity:0; transform:scale(.4); } to{ opacity:1; transform:none; } }
@keyframes bfRing{ from{ opacity:1; transform:scale(.62); } to{ opacity:0; transform:scale(1.4); } }
.bf-booked .bf-err a{ color:inherit; text-decoration:underline; }
.bf-bgrid{ display:grid; grid-template-columns:1.2fr 1fr; gap:20px 22px; margin-top:24px; align-items:start; }
.bf-agenda.bf-agenda-col{ margin-top:0; }
.bf-agenda-col ul{ grid-template-columns:1fr; gap:0; border-top:1px solid var(--line,#e7e7ec); }
.bf-agenda-col li{ padding:12px 0 12px 22px; border-bottom:1px solid var(--line,#e7e7ec); font-size:14.5px; }
.bf-agenda-col li::before{ top:17px; }
.bf-wait{
  position:relative; overflow:hidden; padding:18px 18px 8px; border-radius:18px; color:#fff;
  background:radial-gradient(90% 120% at 100% 0%, rgba(236,0,140,.30), transparent 60%), var(--ink,#0a0a0c);
  box-shadow:0 24px 50px -30px rgba(10,10,12,.7);
}
.bf-wait .bf-label{ color:#9a9aa6; }
.bf-wl{
  display:grid; grid-template-columns:1fr auto; align-items:center; gap:1px 12px; padding:12px 2px;
  border-top:1px solid rgba(255,255,255,.09); color:#fff; text-decoration:none;
}
.bf-wait .bf-label + .bf-wl{ border-top:0; }
.bf-wl b{ font-size:14.5px; font-weight:800; letter-spacing:-.005em; transition:color .15s ease; }
.bf-wl em{ grid-column:1; font-style:normal; font-size:12.5px; line-height:1.4; color:#b9b9c4; }
.bf-wl span{ grid-column:2; grid-row:1 / span 2; color:var(--pink-lt,#ff6ab8); font-weight:900; transition:transform .2s ease; }
.bf-wl:hover b, .bf-wl:focus-visible b{ color:var(--pink-lt,#ff6ab8); }
.bf-wl:hover span, .bf-wl:focus-visible span{ transform:translateX(3px); }
.bf-again{ margin-top:18px; }
@media (prefers-reduced-motion: reduce){
  .brief{ transition:none; }
  .bf-seal span, .bf-seal::before, .bf-sk-card::after{ animation:none; }
  .bf-seal::before{ opacity:0; }
  .bf-frame iframe{ transition:none; }
}

.bf-foot{ padding:0 30px 18px; text-align:right; }
.bf-foot[hidden]{ display:none; }
.bf-reset{ background:none; border:0; padding:8px 0; cursor:pointer; font:inherit; font-size:12.5px; font-weight:600; color:#9a9aa6; text-decoration:underline; text-underline-offset:2px; }
.bf-reset:hover{ color:#3a3a44; }

/* before brief.js runs (or if it cannot): the calendar is one click away */
.bf-nojs{ padding:32px 28px; text-align:center; }
.bf-nojs h3{ font-size:22px; font-weight:900; letter-spacing:-.02em; }
.bf-nojs p{ margin:8px auto 18px; color:#6a6a76; font-size:15px; max-width:44ch; }

.bf-step{ animation:bfIn .32s cubic-bezier(.2,.7,.2,1); }
@keyframes bfIn{ from{ opacity:0; transform:translateY(8px); } to{ opacity:1; transform:none; } }
@media (prefers-reduced-motion: reduce){
  .bf-step{ animation:none; }
  .bf-rule i, .bf-route, .bf-chips button{ transition:none; }
}

/* the row above the card: WhatsApp stays exactly as it was, with a lead-in */
.altcta .alt-lead, .nextup .nu-or.alt-lead{ font-size:13.5px; font-weight:600; color:#6a6a76; }

@media (max-width:640px){
  .brief{ margin-top:22px; }
  .bf-card{ border-radius:20px; }
  .bf-top{ padding:18px 18px 14px; }
  .bf-stages{ gap:6px 14px; }
  .bf-stages li:not(.on) .bf-l{ display:none; }
  .bf-body{ padding:22px 18px 24px; }
  .bf-grid{ grid-template-columns:1fr; }
  .bf-routes{ grid-template-columns:1fr; }
  .bf-route{ padding:16px; gap:14px; }
  .bf-chips button{ flex:1 1 calc(50% - 5px); }
  .bf-nav .btn{ flex:1; justify-content:center; }
  .bf-stage{ margin:18px -18px 0; padding:0 8px 8px; }
  .bf-frame{ min-height:600px; }
  .bf-skel{ padding-top:8px; }
  .bf-calhead{ gap:14px; }
  .bf-how{ width:100%; flex-wrap:wrap; justify-content:space-between; gap:8px 10px; padding:0; }
  .bf-how li{ font-size:11px; gap:5px; }
  .bf-how li + li::before{ display:none; }
  .bf-how b{ width:20px; height:20px; font-size:10.5px; }
  .bf-bgrid{ grid-template-columns:1fr; }
  .bf-calfoot{ flex-direction:column; align-items:flex-start; }
  .bf-foot{ padding:0 18px 16px; }
  .altcta .alt-lead{ width:100%; text-align:center; }
}

/* ==========================================================================
   COOKIE CHOICES (.cookie.ck)  ·  14 Oct 2026
   Built by /consent.js. "No thanks" and "Allow all" sit side by side on the
   first layer, the same size. Since 14 Oct, 21:21 (Albert's call, made
   knowing the ICO and EDPB view that a weaker-looking refuse button is a
   nudge), "No thanks" is grey and lighter weight. To go back to identical
   buttons, delete the [data-ck="reject"] rules below.
   ========================================================================== */
/* Rebuilt 14 Oct, late evening: a slim toast, not a wall. One line on what
   a yes is for, two equal buttons, "Choose" in the sentence. Bottom left on
   a laptop (about 720 x 64px), a low strip on a phone (about 110px). It
   arrives after the first scroll, tap or key, so the page is seen first. */
.cookie.ck{
  display:none; flex-direction:column; flex-wrap:nowrap; align-items:stretch; justify-content:flex-start; gap:0; padding:0;
  left:20px; right:auto; bottom:20px; width:min(720px, calc(100vw - 40px)); max-width:none; margin:0;
  max-height:calc(100vh - 40px); overflow:auto; overscroll-behavior:contain;
  border:1px solid rgba(255,255,255,.10); border-radius:16px;
  background:#0d0d11; color:#fff;
  box-shadow:0 18px 44px -18px rgba(0,0,0,.7), 0 0 0 1px rgba(236,0,140,.10);
  transition:opacity .4s ease, transform .45s cubic-bezier(.2,.8,.2,1), visibility 0s;
}
.cookie.ck.on{ display:flex; }
.cookie.ck.ck-wait{ opacity:0; visibility:hidden; transform:translateY(14px); pointer-events:none; transition:none; }
.ck-main{ display:flex; align-items:center; gap:12px 18px; padding:12px 12px 12px 18px; }
.cookie.ck .cmsg{ flex:1 1 auto; min-width:0; margin:0; max-width:none; color:#b9b9c4; font-size:13px; line-height:1.5; }
.cookie.ck .cmsg b{ color:#fff; font-weight:800; margin-right:2px; }
.cookie.ck .cmsg b::before{
  content:""; display:inline-block; width:7px; height:7px; margin:0 8px 1px 0; border-radius:50%;
  background:var(--pink,#EC008C); box-shadow:0 0 10px rgba(236,0,140,.8); vertical-align:middle;
}
.cookie.ck .cmsg a, .cookie.ck .ck-more{
  color:#fff; font:inherit; font-weight:700; text-decoration:underline; text-decoration-color:rgba(255,255,255,.35); text-underline-offset:3px;
}
.cookie.ck .ck-more{ background:none; border:0; padding:0; margin:0; cursor:pointer; }
.cookie.ck .cmsg a:hover, .cookie.ck .ck-more:hover{ text-decoration-color:var(--pink-lt,#ff6ab8); }
.cookie.ck .cbtns{ flex:none; display:flex; gap:8px; }
.cookie.ck .cbtn{
  width:112px; min-height:40px; padding:9px 12px; border-radius:30px; cursor:pointer;
  font-family:inherit; font-weight:800; font-size:13.5px; line-height:1.2; white-space:nowrap;
  color:#fff; background:var(--pink,#EC008C); border:0;
  transition:background .15s ease, transform .15s ease;
}
.cookie.ck .cbtn:hover{ background:var(--pink-dp,#c70b78); }
.cookie.ck .cbtn[data-ck="reject"]{ background:#2b2b33; color:#d9d9e2; font-weight:600; }
.cookie.ck .cbtn[data-ck="reject"]:hover{ background:#36363f; color:#fff; }
.cookie.ck .cbtn:active{ transform:scale(.97); }
.cookie.ck .cbtn:focus-visible, .cookie.ck .ck-more:focus-visible, .cookie.ck .cmsg a:focus-visible{ outline:2px solid var(--pink-lt,#ff6ab8); outline-offset:2px; border-radius:6px; }
/* the finer choice opens above the toast */
.ck-prefs{ order:-1; padding:6px 18px 4px; border-bottom:1px solid rgba(255,255,255,.08); }
.ck-prefs[hidden]{ display:none; }
.ck-row{ display:flex; align-items:center; justify-content:space-between; gap:16px; padding:10px 0; border-bottom:1px solid rgba(255,255,255,.07); }
.ck-prefs .ck-row:last-of-type{ border-bottom:0; }
label.ck-row{ cursor:pointer; }
.ck-row b{ display:block; color:#fff; font-size:13px; font-weight:800; }
.ck-row span{ display:block; color:#9a9aa6; font-size:12px; line-height:1.45; margin-top:1px; }
.ck-row .ck-on{ flex:none; margin:0; color:var(--pink-lt,#ff6ab8); font-size:11.5px; font-weight:800; white-space:nowrap; }
.ck-row input[type="checkbox"]{
  -webkit-appearance:none; appearance:none; flex:none; position:relative; cursor:pointer;
  width:42px; height:24px; margin:0; border-radius:20px; background:#3a3a44; transition:background .18s ease;
}
.ck-row input[type="checkbox"]::after{
  content:""; position:absolute; top:3px; left:3px; width:18px; height:18px; border-radius:50%;
  background:#fff; transition:transform .18s ease;
}
.ck-row input[type="checkbox"]:checked{ background:var(--pink,#EC008C); }
.ck-row input[type="checkbox"]:checked::after{ transform:translateX(18px); }
.ck-row input[type="checkbox"]:focus-visible{ outline:2px solid var(--pink-lt,#ff6ab8); outline-offset:2px; }
.ck-save{ display:flex; justify-content:flex-end; padding:8px 0 10px; }
.cookie.ck .ck-save .cbtn{ width:auto; padding:9px 20px; }
@media (max-width:640px){
  /* phones: a low strip, the sentence above the two buttons */
  .cookie.ck{ left:8px; right:8px; width:auto; bottom:calc(8px + env(safe-area-inset-bottom, 0px)); border-radius:14px; max-height:calc(100vh - 16px); }
  .ck-main{ flex-direction:column; align-items:stretch; gap:10px; padding:12px 12px 12px; }
  .cookie.ck .cmsg{ font-size:12.5px; line-height:1.45; padding:0 2px; }
  .cookie.ck .ck-undo{ display:none; }
  .cookie.ck .cbtns{ display:grid; grid-template-columns:1fr 1fr; }
  .cookie.ck .cbtn{ width:auto; min-height:42px; }
  .ck-prefs{ padding:4px 14px 2px; }
  .cookie.ck .ck-save .cbtn{ width:100%; }
}
@media (prefers-reduced-motion: reduce){
  .cookie.ck{ transition:none; }
  .cookie.ck.ck-wait{ transform:none; }
  .cookie.ck .cbtn{ transition:none; }
}
/* the settings button on /cookies */
.ck-open-btn{ margin-top:12px; }
/* the privacy request form on /privacy */
.pvform{ margin-top:14px; padding:22px; border:1px solid var(--line,#e7e7ec); border-radius:18px; background:#fafafb; }
.pvform .bf-grid{ margin-top:4px; }
.pvform select{ display:block; width:100%; min-height:50px; padding:12px 14px; border:1.5px solid var(--line,#e7e7ec); border-radius:14px; background:#fff; font:inherit; font-size:16px; color:#0f0f12; }
.pvform .pv-ok{ margin:14px 0 0; font-weight:700; color:#0b6b38; }
.pvform .pv-ok:focus{ outline:none; }
.pvform .btn{ margin-top:16px; }
/* legal pages: the cookie tables */
.legal .tblwrap{ overflow-x:auto; -webkit-overflow-scrolling:touch; margin-top:10px; }
.legal table{ width:100%; min-width:520px; border-collapse:collapse; font-size:13.5px; }
.legal th, .legal td{ text-align:left; vertical-align:top; padding:9px 12px 9px 0; border-bottom:1px solid var(--line,#e7e7ec); color:#3a3a44; }
.legal th{ font-weight:800; color:#0f0f12; font-size:12px; letter-spacing:.04em; }
.legal td:first-child{ font-weight:700; color:#0f0f12; white-space:nowrap; }
.legal .ck-open-btn{ font-family:inherit; }
/* The flow sits under the band's centred heading block; nothing from
   `.book .head p` (centred, 48ch, auto margins) may reach inside the card. */
.book .brief, .lpbook .brief{ text-align:left; }
.book .brief p, .lpbook .brief p{ max-width:none; margin-left:0; margin-right:0; }
.book .brief .bf-hint, .lpbook .brief .bf-hint{ max-width:60ch; margin-top:8px; color:#6a6a76; font-weight:500; }
.book .brief .bf-note, .lpbook .brief .bf-note{ max-width:62ch; margin-top:18px; color:#6a6a76; }
.book .brief .bf-count, .lpbook .brief .bf-count{ margin:0; color:#6a6a76; }
.book .brief .bf-err, .lpbook .brief .bf-err{ margin-top:16px; color:var(--pink-dp,#c70b78); }
.book .brief .bf-nojs p{ margin:8px auto 18px; max-width:44ch; }
/* the "send it another way" screen: the same two doors, as links */
a.bf-route{ text-decoration:none; }
a.bf-route:hover .bf-rt b, a.bf-route:focus-visible .bf-rt b{ color:#0f0f12; }
.bf-rescue .bf-ico svg{ display:block; }
.bf-rescue .bf-note a{ color:#0f0f12; text-decoration:underline; text-underline-offset:2px; }
.bf-retry[disabled]{ opacity:.6; cursor:progress; }

/* ==========================================================================
   GET IN TOUCH, IN EVERY FOOTER  ·  14 Oct 2026
   Albert: "when someone wants to contact us they are never left without an
   option to get in touch easily". WhatsApp, a phone number, an email address
   (written in by brief.js, so it is never in the page for scrapers; it falls
   back to /enquiry without JavaScript) and the booking card, on all pages.
   The email address is shown in full with a Copy button, because an "email
   us" link does nothing on a computer with no mail app set up.
   ========================================================================== */
@media (min-width:761px){
  footer .fgrid{ grid-template-columns:1.35fr .95fr .9fr .9fr; }
}
footer .fcontact a[data-mm-mail]{ margin-bottom:0; }
.fmail{ display:flex; align-items:center; flex-wrap:wrap; gap:4px 8px; margin:0 0 6px; font-size:12px; color:#9a9aa6; word-break:break-all; }
.fmail span{ user-select:all; }
.mm-copy{
  background:none; border:1px solid rgba(255,255,255,.22); border-radius:20px; cursor:pointer;
  padding:3px 10px; min-height:26px; font:inherit; font-size:11.5px; font-weight:700; color:#cfcfd8; word-break:normal;
}
.mm-copy:hover, .mm-copy:focus-visible{ border-color:var(--pink-lt,#ff6ab8); color:#fff; }
.mm-copy.done{ border-color:var(--pink,#EC008C); color:var(--pink-lt,#ff6ab8); }
@media (max-width:760px){
  /* the way to reach us sits right under the brand, full width, two across */
  footer .fgrid > .fcontact{ grid-column:1 / -1; display:grid; grid-template-columns:1fr 1fr; column-gap:20px; }
  footer .fgrid > .fcontact b, footer .fgrid > .fcontact .fmail{ grid-column:1 / -1; }
  /* two rows of two (WhatsApp, Call / Book a call, Email us), then the address */
  footer .fcontact a[href^="https://wa.me"]{ order:1; }
  footer .fcontact a[href^="tel:"]{ order:2; }
  footer .fcontact a[href$="#book"]{ order:3; }
  footer .fcontact a[data-mm-mail]{ order:4; }
  footer .fcontact .fmail{ order:5; }
}
/* the landing pages' slim footer gets the same four ways in */
.lpfoot .lpcontact{ display:flex; flex-wrap:wrap; align-items:center; gap:8px 20px; width:100%; padding-bottom:16px; margin-bottom:4px; border-bottom:1px solid rgba(255,255,255,.08); }
.lpfoot .lpcontact b{ color:#fff; font-size:11.5px; letter-spacing:.16em; text-transform:uppercase; font-weight:800; }
.lpfoot .lpcontact a{ margin-left:0; font-weight:700; }
.lpfoot .lpcontact .fmail{ order:9; width:100%; margin:2px 0 0; }
@media (max-width:640px){
  .lpfoot .lpcontact{ display:grid; grid-template-columns:1fr 1fr; gap:4px 20px; }
  .lpfoot .lpcontact b, .lpfoot .lpcontact .fmail{ grid-column:1 / -1; }
  .lpfoot .lpcontact b{ margin-bottom:6px; }
  .lpfoot .lpcontact a{ padding:9px 0; }
  .lpfoot .lpcontact a[href^="https://wa.me"]{ order:1; } .lpfoot .lpcontact a[href^="tel:"]{ order:2; }
  .lpfoot .lpcontact a[href$="#book"]{ order:3; } .lpfoot .lpcontact a[data-mm-mail]{ order:4; }
}
/* a written-out address beside any "email us" fallback inside the card */
.bf-mailline{ margin:12px 0 0; font-size:13px; color:#6a6a76; display:flex; align-items:center; flex-wrap:wrap; gap:6px 10px; }
.bf-mailline b{ color:#0f0f12; font-weight:700; user-select:all; word-break:break-all; }
.bf-mailline .mm-copy, .pvform .mm-copy{ border-color:var(--line,#e7e7ec); color:#3a3a44; }
.bf-mailline .mm-copy:hover, .pvform .mm-copy:hover{ border-color:var(--pink,#EC008C); color:#0f0f12; }
