/* ==========================================================================
   TOKENS
   One place for the template's values. Change one here and every component
   that uses it follows. Values that change with the screen are set again in
   the media queries at the end of this section (same name, the later wins).
   Names follow the homepage comparison's token set (inventory.md, section 5).
   ========================================================================== */
:root {
  /* Colour and greys */
  --colour-ink: #09090B;                              /* text on light, the dark sections, the hero button */
  --colour-muted: #09090B99;                          /* 60% ink: secondary text on light */
  --colour-quiet: #767676;                            /* the pinned section's blocks that are not current (4.54:1 on white) */
  --colour-white: #FFFFFF;
  --colour-ground-hero: #F6F5F3;                      /* the hero, and the header bar until it has sampled the page */
  --colour-placeholder: #FAFAF9;                      /* behind a frame or avatar until its image loads */
  --colour-tile: #E8E6E1;                             /* behind a hero strip tile until its image loads */
  --colour-pill: #F7F7F5;                             /* a logo pill outside the hero (the hero's own are transparent) */
  --colour-hairline: #09090B14;                       /* 8% ink: the proof avatar's ring */
  --colour-on-dark: #FFFFFF;                          /* headings on the dark sections */
  --colour-on-dark-body: #FFFFFFCC;                   /* 80% white: body text on dark */
  --colour-on-dark-link: rgba(255, 255, 255, 0.65);   /* footer links */
  --colour-on-dark-label: rgba(255, 255, 255, 0.5);   /* the FAQ label, footer labels and meta */
  --colour-on-dark-rule: rgba(255, 255, 255, 0.12);   /* the footer's one hairline */
  /* site-wide names that system.css and announce.js read: keep them */
  --white: #FFFFFF;
  --text-white: #FFFFFF;
  --text-primary: #09090B;
  --font: var(--type-family);

  /* Type: Inter Tight, 400 to read, 500 for buttons and names */
  --type-family: 'Inter Tight', 'Geist', system-ui, sans-serif;
  --type-display: clamp(40px, 5.8vw, 100px);                       /* the hero headline from 768 px */
  --type-display-phone: clamp(35px, 11vw, 48px);                   /* the hero headline on phones (variant a) */
  --type-display-2: clamp(40px, calc(11.75px + 3.63vw), 72px);     /* the booking heading */
  --type-stat: 36px;                                               /* the stat figures from 1025 px: a companion to the 28 px quote (1.29x) */
  --type-title: clamp(26px, min(8.4vw, calc(28.3px + 0.95vw)), 38px);   /* block titles and section headings */
  --type-title-track: -0.022em;                                    /* their tracking, tighter as they grow */
  --type-quote: 28px;                                              /* the proof quote from 1025 px */
  --type-item: 18px;                                               /* list items, step titles, FAQ questions */
  --type-body: 16px;                                               /* descriptions, FAQ answers */
  --type-caption: 15px;                                            /* stat labels */
  --type-ui: 14px;                                                 /* button text, names, footer links */
  --type-small: 13px;                                              /* the hero's small line, numerals, header parts, meta */
  --type-label: 11px;                                              /* footer column labels */

  /* Space */
  --space-section-desktop: 80px;   /* above and below every section, so 160 px between sections from 1025 px */
  --space-section-tablet: 64px;    /* 128 px between sections at tablet */
  --space-section-phone: 48px;     /* 96 px between sections on phones */
  --space-title-desktop: 48px;     /* a section heading to its content */
  --space-title-tablet: 32px;      /* the same below 1024 px */
  --space-title-body: 16px;        /* a block title to its description (grows with the title, below) */
  --space-group: 32px;             /* between groups inside a block */
  --space-columns: 48px;           /* between text columns */
  --space-list: 14px;              /* between list rows */
  --space-button-note: 10px;       /* the hero button to its small line */
  --space-figure-label: 6px;       /* a stat figure to its label (about 15 to 17 px from the figure's baseline to the label's capitals) */
  --space-frame-gap: 80px;         /* the pinned section's text column to its frame */

  /* Container: below the hero, one centred column from 1024 px (the viewport less max(48 px, 8vw) a side, never wider
     than 1240 px); the page's own gutters below 1024 px */
  --gutter-desktop: 48px;
  --gutter-tablet: 32px;
  --gutter-phone: 20px;
  --container-side: 8vw;
  --container-cap: 1240px;
  --container-pad: max(var(--gutter-desktop), var(--container-side), calc((100% - var(--container-cap)) / 2));

  /* Radius */
  --radius: 8px;          /* frames, images, cards, the calendar panel */
  --radius-tile: 6px;     /* hero strip tiles */
  --radius-small: 4px;    /* the booking card's button */
  --radius-pill: 999px;

  /* Motion: one easing to enter (on load only), one to travel (the pinned section) */
  --ease-enter: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-travel: cubic-bezier(0.65, 0, 0.35, 1);
  --duration-state: 0.2s;   /* colour and underline changes */
}

/* The pinned frame's size and place (Delivers), worked out in CSS. Pinned (1024 px and wider, and wider than tall): the
   creative is centred in the viewport and as large as the booking card allows, 16 px clear above the card (74 px tall,
   24 px from the bottom on desktop): a margin of 108 px above and below, and where that alone leaves under 16 px (a
   frame at its height cap) the frame sits up to 6 px above centre (--wwd-lift), so a 1440x900 frame loses 5 px of width
   rather than 14 (padding QA, fault 2: it sat 7 px over the card); the top margin still clears the 68 px header bar
   when it shows (the indicator sits inside the frame, so it costs no height). Its height tops out at 80% of the
   viewport. Its width is the smallest of: that height's 4:5 width, 58% of the container, what leaves the text column
   380 px (or the widest title's width from 1280 px, --title-w) beside the frame gap, and 1080 px; so it never starves
   the text. The viewport height is the small viewport (svh, so the toolbar on a tablet never pushes it low; vh where
   svh is unknown), and centring uses the same, so it never jumps as the toolbar shows and hides. cqw is the section's
   own width. 1440x900: 544x680. Taller than wide (an iPad upright) it stacks instead. */
:root {
  --cr-vh: 100vh;
  --cr-m: 108px;
  --cr-h0: clamp(320px, calc(var(--cr-vh) - 2 * var(--cr-m)), min(calc(var(--cr-vh) * 0.8), 1350px));
  --title-w: 0px;
  --cr-w: min(calc(var(--cr-h0) * 0.8), calc(100cqw * 0.58), calc(100cqw - var(--space-frame-gap) - max(380px, var(--title-w))), 1080px);
  --cr-h: calc(var(--cr-w) * 1.25);
  --wwd-lift: clamp(0px, calc(114px - (var(--cr-vh) - var(--cr-h)) / 2), 6px);
  --cr-top: calc((var(--cr-vh) - var(--cr-h)) / 2 - var(--wwd-lift));
}
@supports (height: 100svh) {
  :root { --cr-vh: 100svh; }
}
@supports (width: round(1.5px, 1px)) {
  /* where the browser can round: the frame's width a multiple of 4 px and its height exactly 1.25 times that, so it
     is exactly 4:5 in whole pixels (rounding the two apart left 1180x820 at 484x602), its edges on whole device
     pixels at 1x, 1.5x and 2x (a frame on a fraction of a device pixel showed a 1 px seam down its right edge at 1440
     on a retina screen), its top in whole pixels; the script also nudges its left edge onto a whole device pixel, as
     the container's 8vw gutter is often fractional. The height-cap term rounds down, so the height never passes the
     cap and the 16 px over the card holds */
  :root {
    --cr-w: min(round(min(calc(100cqw * 0.58), calc(100cqw - var(--space-frame-gap) - max(380px, var(--title-w))), 1080px), 4px), round(down, calc(var(--cr-h0) * 0.8), 4px));
    --cr-h: calc(var(--cr-w) * 1.25);
    --cr-top: round(calc((var(--cr-vh) - var(--cr-h)) / 2 - var(--wwd-lift)), 1px);
  }
}
@media (min-width: 1280px) {
  :root { --title-w: 440px; }
}

/* Motion options the script reads (lander.js reads these names; a page can set its own in its <style>). Between blocks
   the frame pushes up (--lp-block-move on --lp-block-ease, through --lp-block-distance of the frame); within a block
   brands travel sideways (--lp-user-slide). Holds: logos --lp-hold-logo, applications --lp-hold-photo, the first brand's
   first showing --wwd-first-hold, an ad visitor's own brand --lp-lead-hold. The guide strips scroll one page per
   --lp-doc-page and change brand at each page (--lp-doc-cut: page) or on a fixed beat (a time, e.g. 3300ms). */
:root {
  --lp-block-move: 800ms;
  --lp-block-ease: var(--ease-travel);   /* the push, and the sideways travel within a block */
  --lp-block-distance: 100%;   /* of the frame; the two images overlap by 1 px while they move */
  --lp-hold-logo: 2000ms;   /* block 1 */
  --lp-hold-photo: 3300ms;  /* block 2 */
  --lp-lead-hold: 4800ms;
  --wwd-first-hold: 3000ms; /* the first brand's first showing, Clad unless an ad visitor (Charlie: "make sure clad is visible in block 1 so it starts with that") */
  --lp-user-slide: 450ms;   /* the sideways travel within a block: autoplay, a click on a segment or the frame, an arrow key */
  --lp-doc-page: 5s;
  --lp-doc-cut: page;
}

/* Text selection in a client's colour: the first one here, the rest from the page's brand list (lander-data), which
   lander.js steps through on each new selection */
:root { --sel-bg: #84DAFFFC; --sel-ink: var(--colour-ink); }

/* Responsive steps of the tokens above (type audit, 12 Nov). Titles 40 px from 1024, 44 px at 1280 growing to 48 px at
   1440, then to 52 px at 1728 and up (capped there so the frame keeps its full width where the container caps at
   1240 px); on phones about 32 px (27 px at 320 to 38 px; under 380 px 8.4vw, so they stay at least 8% under the
   closing heading). Tracking tightens as they grow (-0.022em to -0.031em). Descriptions 16 px, 17 px
   from 1280; list items 18 px, 19 px from 1024, 20 px from 1440. The title to description gap grows with the title,
   16, 18 then 20 px. Display 2: 40 px at 769, 48.9 at 1024, 64 at 1440, 72 from 1660; min(9.2vw, 40px) to 768. Stat
   figures about 1.3 times the quote beside them (Charlie, 13 Nov: "they feel quite big and just cumbersome"): 36 px from
   1025 (quote 28), 26 px from 769 to 1024 (quote 20), 24 px on phones (quote 18). */
@media (max-width: 1024px) {
  :root { --type-stat: 26px; }
}
@media (max-width: 768px) {
  :root { --type-display-2: min(9.2vw, 40px); --type-stat: 24px; }   /* the closing heading and the stat figures on phones */
}
@media (min-width: 1024px) {
  :root { --type-title: 40px; --type-title-track: -0.025em; --type-item: 19px; --space-title-body: 18px; }
}
@media (min-width: 1280px) {
  :root { --type-title: clamp(44px, calc(44px + (100vw - 1280px) * 0.025), 48px); --type-title-track: -0.028em; --type-body: 17px; --title-w: max(440px, calc(var(--type-title) * 8.4)); }
}
@media (min-width: 1440px) {
  :root { --type-title: clamp(48px, calc(48px + (100vw - 1440px) * 0.01389), 52px); --type-title-track: -0.03em; --type-item: 20px; --space-title-body: 20px; }
}
@media (min-width: 1728px) {
  :root { --type-title-track: -0.031em; }
}

/* ==========================================================================
   BASE. Reset, the page grounds, the custom cursor (mouse only), text selection in a client's colour, and the page's two
   layers: the white content (main.page-content) over the dark booking section, FAQ and footer (.footer-reveal).
   ========================================================================== */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  overflow-x: hidden;
  cursor: none;
  /* Overscroll: browsers paint the rubber band with the html background
     COLOUR only (images ignored). Dark hero at the top + dark footer at
     the bottom = light top, dark bottom. */
  background-color: var(--colour-ground-hero);
}
.cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--colour-ink);
  pointer-events: none;
  z-index: 10002;
  transform: translate(-50%, -50%);
  transition: width 0.3s cubic-bezier(0.25, 0.1, 0.25, 1),
              height 0.3s cubic-bezier(0.25, 0.1, 0.25, 1),
              border-radius 0.3s cubic-bezier(0.25, 0.1, 0.25, 1),
              background 0.3s ease,
              box-shadow 0.3s ease,
              backdrop-filter 0.3s ease,
              -webkit-backdrop-filter 0.3s ease,
              opacity 0.15s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  will-change: transform;
  opacity: 0;
  overflow: hidden;
}
.cursor.visible { opacity: 1; }
.cursor-text {
  font-family: var(--type-family);
  font-family: 'Geist Mono', monospace;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--colour-white);
  opacity: 0;
  transform: scale(0.5);
  transition: opacity 0.3s ease 0.05s, transform 0.3s cubic-bezier(0.25, 0.1, 0.25, 1) 0.05s;
  white-space: nowrap;
  user-select: none;
}
.cursor.active {
  width: auto;
  padding: 0 12px;
  height: 28px;
  border-radius: var(--radius-small);
  background: rgba(0, 0, 0, 0.45);
  box-shadow: none;
  backdrop-filter: blur(40px);
  -webkit-backdrop-filter: blur(40px);
}
.cursor.active .cursor-text {
  opacity: 1;
  transform: scale(1);
}
.cursor.on-dark:not(.active) {
  background: var(--colour-white);
}
.cursor.link-hover,
.cursor.on-dark.link-hover {
    
  width: 20px;
  height: 20px;
}
/* Ensure cursor: none on all elements */
* { cursor: none !important; }
@media (hover: none), (pointer: coarse) {
  /* Hide custom cursor on touch devices */
  .cursor { display: none !important; }
  *, html { cursor: auto !important; }
}
body {
  font-family: var(--type-family);
  color: var(--colour-ink);
  background: var(--colour-ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis: none;
}
a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }
/* (No scroll-in entrances, Charlie's rule, 12 Nov: no fade-ups, only the work moves. How it works, the proof row
   and the FAQ used to rise 64 px over 1 s as they came into view; they are simply there now. The hero's one entrance
   on load and the pinned section's motion stay.) */
.page-content {
  position: relative;
  z-index: 1;
  background: var(--colour-white);
  border-radius: 0 0 8px 8px;
  overflow: hidden;
  overflow: clip; /* as on the homepage: clips without becoming a scroll container, so position: sticky works inside */
}
.footer-reveal {
  position: relative;
  z-index: 0;
}
@media (max-width: 768px) {
  /* Remove sticky reveal on mobile, keep CTA visible */
  .footer-reveal {
    position: relative;
  }
  .page-content {
    border-radius: 0;
    overflow: visible;
  }
}
.lp-vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* Selection in a client's colour (Charlie, 12 Nov: "a fun highlight colour"): each new selection takes the next
   brand in the page's order, Clad Laser Blue #84DAFF, Reversa Olive #B1BB98, Datagram Orange #FF5C00, Kedalion Gold
   #FCCA04, Hemi Electric Orange #FF4600 (hexes from their guides' colour pages), with ink #09090B on all five (5.8:1
   and up). Form fields keep the system selection; the Cal.com frame is its own page and untouched. */
:not(input):not(textarea)::selection { background-color: var(--sel-bg); color: var(--sel-ink); }
:not(input):not(textarea)::-moz-selection { background-color: var(--sel-bg); color: var(--sel-ink); }

/* ==========================================================================
   SHARED TYPE. Block titles and the "How it works" heading are one style; descriptions and list items share two sizes.
   Sizes come from the type tokens.
   ========================================================================== */
/* Headings below the hero: the block titles carry the delivers section on their own and the proof row explains
   itself (both keep a visually hidden h2 for their name); "How it works" keeps a heading, set exactly like the block
   titles, 48 px from its steps (32 px below 1024). One headline size below the hero. One space between sections,
   content to content: 160 px on desktop, 128 px on tablet, 96 px on mobile (the proof row's bottom is trimmed by the
   dark section's own top padding, 64 + 24, 56 + 24, 48 + 24).
   Type scale (Charlie, 12 Nov: the block headlines "a little bit bigger ... a bit more drama", then the copy with
   them). Titles 40 px from 1024, 44 px at 1280 growing to 48 px at 1440, then to 52 px at 1728 and up (capped
   there so the frame keeps its full width where the container caps at 1240 px: the frame wins over 4 px of type);
   on phones about 32 px (27 px at 320 to 38 px with the width; under 380 px 8.4vw, so they stay at least 8% under the
   closing heading, whose 9.2vw can't grow without wrapping the heading); tracking tightening as they grow (-0.022em to -0.031em, the hero's
   way), line-height 1.05; always one line from 1024 (the text column is kept at least 8.4 title sizes wide, the
   widest title, "The logo and identity", being 8.34). The copy: descriptions 16 px, 17 px from 1280 (muted,
   line-height 1.45); list items 18 px, 19 px from 1024, 20 px from 1440 (line-height 1.3), numerals still 13 px
   and muted, on the item's baseline; "How it works" step titles and descriptions on the same two sizes. The title
   to description gap grows with the title, 16, 18 then 20 px. */
.lp-section-title, .wwd-q .offering-title { font-size: var(--type-title); font-weight: 400; letter-spacing: var(--type-title-track); line-height: 1.05; color: var(--colour-ink); }
.wwd-q .offering-desc, .how-it-works .hiw-step-desc { font-size: var(--type-body); line-height: 1.45; }
.wwd-q .offering-list-item, .how-it-works .hiw-step-title { font-size: var(--type-item); line-height: 1.3; }

/* ==========================================================================
   HEADER (required). Wordmark on the left; on the right the sprint availability and the next free call, written by
   lander.js only once it has real data. Hides while scrolling down, comes back on scroll up as a bar in the colour of
   the section under it (lander.js sets --nav-bar). The Book a call link (.nav-cta) is hidden at every width.
   ========================================================================== */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: 22px;
  padding-inline: 24px;
  transition: padding 0.3s;
  width: 100%;
}
.nav-inner {
  display: flex;
  align-items: center;
  gap: 32px;
  position: relative;
  padding: 10px 24px;
  border-radius: var(--radius-small);
  background: rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  transition: background 0.4s, box-shadow 0.4s, border-radius 0.25s, backdrop-filter 0.4s, -webkit-backdrop-filter 0.4s;
}
/* Logo floats free - no pill. Out-ranks system.css's !important over-dark glass. */
html .nav .nav-inner,
html .nav.scrolled .nav-inner,
html .nav.nav-over-dark .nav-inner {
  background: none !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
.nav-logo svg { height: 12px; width: auto; }
.nav-logo svg path { fill: var(--colour-ink); transition: fill 0.4s; }
.nav-cta {
  display: flex;
  background: var(--colour-ink);
  border-radius: var(--radius-small);
  padding: 10px 20px;
  transition: background 0.4s, opacity 0.15s;
}
.nav-cta:hover { opacity: 0.85; }
.nav-cta span {
  font-size: var(--type-ui);
  line-height: 18px;
  color: var(--colour-white);
  font-weight: 500;
  transition: color 0.4s;
}
.nav.scrolled .nav-inner {
  background: rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: 0px 2px 8px #0000000A;
}
.nav.scrolled .nav-logo svg path { fill: var(--colour-ink); }
.nav.scrolled .nav-cta { background: var(--colour-ink); }
.nav.scrolled .nav-cta span { color: var(--colour-white); }
/* Dark-mode nav when over a dark section (booking / footer) */
.nav.nav-over-dark .nav-inner {
  background: rgba(18, 18, 20, 0.55);
  box-shadow: none;
}
.nav.nav-over-dark .nav-logo svg path { fill: var(--colour-white); }
.nav.nav-over-dark .nav-cta { background: var(--colour-white); }
.nav.nav-over-dark .nav-cta span { color: var(--colour-ink); }
@media (max-width: 768px) {
  .nav .nav-cta { display: none; }
  /* one clock on mobile, like the reference */
  .nav-clocks { display: flex; margin-right: 0; }
  .nav-clocks .nav-clock:nth-child(2), .nav-clocks .nav-clock:nth-child(3) { display: none; }
}
@media (min-width: 769px) {
  .nav .nav-cta { display: none; }
  .nav-clocks { margin-right: 0; }
}
@media (min-width: 769px) and (max-width: 1024px) {
  .nav-clocks { display: flex; }
}
/* ── Nav clocks ── */
.nav-clocks { display: flex; gap: 20px; margin-left: auto; margin-right: 24px; }
.nav-clock { font-size: var(--type-small); color: var(--colour-muted); display: inline-flex; align-items: center; gap: 4px; }
.nav-clock-label { display: block; overflow: hidden; height: 16px; transition: width 0.28s cubic-bezier(0.22, 1, 0.36, 1); }
.nav-clock strong { font-weight: 500; color: var(--colour-ink); font-variant-numeric: tabular-nums; }
.nav.nav-over-dark .nav-clock { color: rgba(255,255,255,0.55); }
.nav.nav-over-dark .nav-clock strong { color: var(--colour-white); }
@media (max-width: 1024px) {
  .nav-clocks { display: none; }
  .nav {
    padding-block: 14px;
    padding-inline: 8px;
  }
  .nav-inner {
    padding: 0;
  }
}
@media (max-width: 768px) {
  .nav {
    padding-block: 16px;
    padding-inline: var(--gutter-phone);
  }
  .nav-inner {
    padding: 0;
  }
  .nav-cta { display: flex; }
  /* No scrolled/contained state on mobile */
  .nav-inner,
  .nav.scrolled .nav-inner {
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
  }
  .nav.scrolled .nav-logo svg path { fill: var(--colour-ink); }
  .nav.nav-over-dark .nav-logo svg path { fill: var(--colour-white); }
  .nav.nav-over-dark.scrolled .nav-logo svg path { fill: var(--colour-white); }
  .nav.nav-over-light .nav-logo svg path { fill: var(--colour-ink); }
  .nav.nav-over-light.scrolled .nav-logo svg path { fill: var(--colour-ink); }
}
/* Header bar: always the exact colour of the section under it (the hero's #F6F5F3 until the script has sampled) */
html .nav {
  background-color: var(--nav-bar, var(--colour-ground-hero));
  transition: padding 0.3s, transform 0.35s var(--ease-enter);
}
html .nav.nav-hidden { transform: translateY(-100%); }
@media (min-width: 1025px) {
  html .nav.scrolled { padding-block: 14px; }
}
@media (min-width: 768px) and (max-width: 1024px) {
  .nav { padding-inline: var(--gutter-tablet); }
}
/* Header, right side: availability and the next call in the clocks' type (muted label, ink value); both link to the
   booking section (they look alike, so neither is a dead tap). Shown from 769 px (both parts fit beside the wordmark at 1024); hidden on phones as the
   clocks were. */
.nav-clocks { gap: 24px; }
.nav-clocks .nav-clock-label { height: auto; overflow: visible; }
a.nav-clock { text-decoration: none; }
a.nav-clock strong { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: transparent; transition: text-decoration-color var(--duration-state) ease; }
a.nav-clock:hover strong, a.nav-clock:focus-visible strong { text-decoration-color: currentColor; }
@media (min-width: 769px) and (max-width: 1024px) {
  .nav-clocks { display: flex; }
  .nav-clocks { margin-right: 0; }
}

/* ==========================================================================
   BOOKING CARD (optional, floating). Bottom right from 769 px, a bar along the bottom on phones. lander.js slides it
   in after 200 px and out while the booking calendar is in view; below 1024 px it waits for the cookie choice.
   ========================================================================== */
/* ── Notification booking card (Haptic-style) ── */
.notif-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}
.notif-card {
  position: fixed;
  top: 76px;
  right: 24px;
  z-index: 90;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  width: 384px;
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border-radius: var(--radius);
  border: 1px solid rgba(9, 9, 11, 0.08);
  box-shadow: 0 8px 30px rgba(9, 9, 11, 0.10);
  opacity: 0;
  transform: translateY(-12px);
  pointer-events: none;
  transition: opacity 0.5s var(--ease-enter), transform 0.5s var(--ease-enter);
}
.notif-card.show { opacity: 1; transform: translateY(0); pointer-events: auto; }
.notif-text { flex: 1 1 auto; min-width: 0; }
.notif-title { font-size: var(--type-ui); font-weight: 500; color: var(--colour-ink); line-height: 18px; }
.notif-sub { font-size: var(--type-small); color: rgba(9, 9, 11, 0.55); line-height: 17px; }
.notif-action {
  flex-shrink: 0;
  width: 80px;
  text-align: center;
  font-size: var(--type-small);
  font-weight: 500;
  color: var(--colour-white);
  background: var(--colour-ink);
  border-radius: var(--radius-small);
  padding: 9px 0;
  cursor: pointer;
  transition: opacity 0.15s;
}
.notif-action:hover { opacity: 0.85; }
@media (max-width: 768px) {
  /* Mobile: bottom-pinned booking bar (Haptic pattern), replaces nav CTA */
  .notif-card {
    top: auto;
    bottom: calc(12px + env(safe-area-inset-bottom));
    left: 12px;
    right: 12px;
    width: auto;
    transform: translateY(12px);
  }
  .notif-card.show { transform: translateY(0); }
}
/* Booking card (Charlie, 12 Nov): slides up into place once the visitor has scrolled into the hero, slides out
   downwards while the booking calendar reaches its place and again back at the very top (script at the end of the page);
   those are the only two places it is absent. Up: from below the viewport edge (its own height plus its bottom
   margin), 450 ms, cubic-bezier(0.22, 1, 0.36, 1); out: 300 ms ease-in; reduced motion: a short fade, no slide.
   Solid white with a hairline and a soft shadow, so it reads as the same deliberate card over white, the warm grey
   hero and the #09090B sections (the old 82% white went pale grey over dark). From 769 px it sits bottom right,
   24 px from both edges, ignoring the container; mobile keeps the full-width bar. Below 1024 px it waits for the
   cookie choice (html.consent-open) before its first appearance. */
.notif-card {
  --notif-out: calc(100% + 24px);
  z-index: 101;
  background: var(--colour-white);
  border: 1px solid rgba(9, 9, 11, 0.10);
  box-shadow: 0 8px 30px rgba(9, 9, 11, 0.14);
  opacity: 0;
  transform: translateY(var(--notif-out));
  transition: transform 0.3s cubic-bezier(0.4, 0, 1, 1), opacity 0.3s cubic-bezier(0.4, 0, 1, 1);
}
.notif-card.show { opacity: 1; transform: translateY(0); transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.45s cubic-bezier(0.22, 1, 0.36, 1); }
@media (max-width: 768px) {
  .notif-card { --notif-out: calc(100% + 12px + env(safe-area-inset-bottom)); }
  html.consent-open .notif-card { opacity: 0; transform: translateY(var(--notif-out)); pointer-events: none; }
}
@media (min-width: 769px) {
  .notif-card { top: auto; bottom: 24px; right: 24px; padding-block: 10px; }
}
@media (min-width: 769px) and (max-width: 1023.98px) {
  html.consent-open .notif-card { opacity: 0; transform: translateY(var(--notif-out)); pointer-events: none; }
}
.notif-title { text-wrap: balance; }
@media (max-width: 374.98px) {
  /* never one word on its own line on the narrowest phones */
  .notif-action { width: 64px; }
}
@media (hover: none) {
  /* under 375 px the button gives the 13 px sub-line 16 px more room, so it wraps as it did at 12 px and the card keeps its height */
  .notif-action:hover { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  /* no sticky 85% grey after a tap (the cookie button sits where the card lands) */
  .notif-card, html.consent-open .notif-card { transform: none; transition: opacity 0.15s linear; }
  .notif-card.show { transform: none; transition: opacity 0.15s linear; }
}
.notif-sub { color: var(--colour-muted); }
@media (max-width: 768px) {
  /* Padding QA fixes (14-viewport padding QA, 12 Nov; fault numbers from its report).
   1 + 12, phone booking bar: 16 px from the screen's edges (the cookie sheet's inset), and the footer's bottom padding
   grows to match so its last line clears the bar by 16 px or more; under 380 px the bar's title and sub-line wrap, so
   the footer leaves more. From 452 px the bar stops growing at 420 px and sits bottom right. */
  .notif-card { left: max(16px, calc(100% - 436px)); right: 16px; bottom: calc(16px + env(safe-area-inset-bottom)); --notif-out: calc(100% + 16px + env(safe-area-inset-bottom)); }
}

/* ==========================================================================
   HERO (required). Group 1, the ask: the headline, the button and one small line. Group 2, the proof: the logo row
   tight on the drifting strip of work. Optional: an eyebrow (.bs-hero-eyebrow) and a sub-line (.bs-hero-subline), for
   the SEO pages. The only entrance on the page plays here, once, on load (headline words, then the button and logos).
   ========================================================================== */
.bs-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 180px;
  padding-bottom: 80px;
  padding-inline: var(--gutter-desktop);
  gap: 24px;
  background: var(--colour-ground-hero);
}
.bs-hero-eyebrow {
  opacity: 0;
  transform: translateY(20px);
  animation: heroFadeUp 0.8s var(--ease-enter) 0.1s forwards;
}
.bs-hero-eyebrow span {
  font-size: var(--type-small);
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 16px;
  color: var(--colour-muted);
}
.bs-hero-headline {
  font-size: 72px;
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--colour-ink);
  text-align: center;
  max-width: 1000px;
  text-wrap: balance;
}
.bs-hero-headline .hw {
  display: inline-block;
  opacity: 0;
  transform: translateY(26px);
  animation: heroFadeUp 0.7s var(--ease-enter) forwards;
}
.bs-hero-headline .hw.hw-muted { color: rgba(9, 9, 11, 0.45); }
.bs-hero-subline {
  font-size: 17px;
  font-weight: 400;
  line-height: 28px;
  color: var(--colour-muted);
  text-align: center;
  max-width: 440px;
  opacity: 0;
  transform: translateY(16px);
  animation: heroFadeUp 0.8s var(--ease-enter) 0.4s forwards;
}
@keyframes heroFadeUp {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.logo-ticker {
  display: flex;
  align-items: center;
  padding: 48px 0 32px;
  gap: 10px;
  overflow: hidden;
  position: relative;
  z-index: 1;
  background: var(--colour-white);
}
.logo-ticker-track {
  display: flex;
  gap: 10px;
  flex-shrink: 0;
  animation: ticker 40s linear infinite;
}
@keyframes ticker {
  to { transform: translateX(calc(-100% - 10px)); }
}
.logo-pill {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 72px;
  padding: 0 40px;
  background: var(--colour-pill);
  border-radius: var(--radius-small);
  flex-shrink: 0;
}
.logo-pill img {
  height: 24px;
  width: auto;
  opacity: 0.7;
}
.logo-pill.logo-icon img { height: 32px; }
/* Ticker inside the hero: bare logos, no pill containers */
.bs-hero .logo-ticker {
  width: 100%;
  max-width: 1000px;
  margin-inline: auto;
  background: transparent;
  padding: 8px 0 16px;
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 12%, #000 88%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 12%, #000 88%, transparent 100%);
  opacity: 0;
  transform: translateY(16px);
  animation: heroFadeUp 0.8s var(--ease-enter) 0.6s forwards;
}
.bs-hero .logo-pill {
  background: transparent;
  height: 44px;
  padding: 0 30px;
}
.bs-hero .logo-pill img { opacity: 0.55; }
.hero-cta-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin-top: 5px;
  opacity: 0;
  transform: translateY(16px);
  animation: heroFadeUp 0.8s var(--ease-enter) 0.5s forwards;
}
.hero-cta-btn {
  display: flex;
  background: var(--colour-ink);
  border-radius: var(--radius-small);
  padding: 10px 20px;
  border: none;
  cursor: pointer;
  text-decoration: none;
  transition: opacity 0.15s;
}
.hero-cta-btn:hover {
  opacity: 0.85;
}
.hero-cta-btn span {
  font-family: var(--type-family);
  font-size: var(--type-ui);
  font-weight: 500;
  line-height: 18px;
  color: var(--colour-white);
}
/* Ambient glow: canvas mirrors video frames, blurred, bleeding past the media box */
.bs-hero { position: relative; }
@media (max-width: 1024px) {
  .bs-hero {
    padding-top: 166px;
    padding-bottom: 64px;
    padding-inline: var(--gutter-tablet);
    gap: 20px;
  }
  .bs-hero-headline {
    font-size: 48px;
    line-height: 1.1;
    max-width: 500px;
  }
  .bs-hero-subline {
    font-size: 16px;
    max-width: 400px;
  }
}
@media (max-width: 768px) {
  .bs-hero {
    padding-top: 112px;
    padding-bottom: 48px;
    padding-inline: var(--gutter-phone);
    gap: 20px;
  }
  .bs-hero-headline {
    font-size: 36px;
    line-height: 1.1;
    max-width: 350px;
  }
  .bs-hero-subline {
    font-size: 15px;
    line-height: 22px;
    max-width: 320px;
  }
}
/* ── Hero strip (jobs.html), edge to edge under the logo row ── */
.bs-hero .c-strip {
  --h: 380px;
  --gap: 12px;
  align-self: stretch;
  margin-inline: calc(-1 * var(--gutter-desktop));
  overflow: hidden;
}
.c-track { display: flex; gap: var(--gap); width: max-content; will-change: transform; }
.c-set { display: flex; gap: var(--gap); }
.c-card {
  flex: 0 0 auto;
  height: var(--h);
  aspect-ratio: var(--r);
  border-radius: var(--radius-tile);
  overflow: hidden;
  background: var(--colour-tile);
}
.c-card img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Hero button: one line at every width, at least 44 px tall, with one muted line 10 px under it (the eyebrow's
   13 px muted style), centred */
.hero-cta-group { gap: var(--space-button-note); }
.hero-cta-btn { min-height: 44px; align-items: center; justify-content: center; }
.hero-cta-btn span { white-space: nowrap; }
.hero-cta-note { font-size: var(--type-small); font-weight: 400; letter-spacing: 0.02em; line-height: 16px; color: var(--colour-muted); text-align: center; }
@media (min-width: 1025px) {
  /* 48 px from the header to the eyebrow, 40 px from the logo row to the strip */
  .bs-hero { padding-top: 132px; }
}
@media (min-width: 769px) and (max-width: 1024px) {
  .bs-hero { padding-top: 116px; }
}
@media (max-width: 1024px) {
  .bs-hero .c-strip { --h: 340px; --gap: 10px; margin-inline: calc(-1 * var(--gutter-tablet)); }
}
@media (max-width: 768px) {
  .bs-hero { padding-top: 100px; }
  .bs-hero .c-strip { --h: 240px; --gap: 8px; margin-inline: calc(-1 * var(--gutter-phone)); }
}
.bs-hero { padding-bottom: 80px; }
@media (max-width: 1024px) {
  .bs-hero { padding-bottom: 64px; }
}
@media (max-width: 768px) {
  .bs-hero { padding-bottom: 48px; }
}
@media (min-width: 1025px) {
  .bs-hero .c-strip { margin-top: clamp(16px, calc(50vh - 370px), 96px); }
}
/* Hero headline (Charlie, 12 Nov: "the jobs page, just black text, is a bit cooler, maybe a little bit bigger"): both lines
   in the primary black, one step under the jobs headline (jobs: clamp(44px, 6.6vw, 104px), weight 400, -0.05em, line
   height 0.98; -0.045em and 1.02 from 768 px down, 37 px on phones): 5.8vw up to 88 px with the jobs tracking and line
   height, clamp(32px, 9.4vw, 44px) on phones. The copy's two lines stay two lines; on a phone where a line cannot fit,
   the break gives way and the words balance over three (script under the hero). No eyebrow on the ad landers, so the
   headline sits 64 px under the header on desktop (48 px on phones), and the rest of the hero keeps the jobs page's
   rhythm: 32 px to the sub-copy (one size up, 18 px, as on jobs), 32 px to the button. */
.bs-hero-headline { font-size: clamp(40px, 5.8vw, 88px); letter-spacing: -0.05em; line-height: 0.98; max-width: 1240px; }
.bs-hero-headline .hw.hw-muted { color: inherit; }
.bs-hero-headline + .bs-hero-subline { margin-top: 8px; }
.bs-hero .hero-cta-group { margin-top: 8px; }
@media (min-width: 1025px) {
  .bs-hero { padding-top: 148px; }
  .bs-hero-subline { font-size: 18px; line-height: 27px; max-width: 560px; }
}
@media (min-width: 769px) and (max-width: 1024px) {
  .bs-hero { padding-top: 128px; }
  .bs-hero-headline { max-width: none; }
}
@media (max-width: 768px) {
  .bs-hero { padding-top: 112px; }
  .bs-hero-headline { font-size: clamp(32px, 9.4vw, 44px); letter-spacing: -0.045em; line-height: 1.02; max-width: none; }
}
/* No sub-copy on the ad lander: the headline sits where the jobs page sets its own (92 px under the header on desktop,
   176 px from the top) and goes straight to the button, 40 px apart on desktop and 32 px below 1025 px, so the space
   reads as the headline's own margin rather than a missing paragraph */
.bs-hero-headline + .hero-cta-group { margin-top: 12px; }
@media (min-width: 1025px) {
  /* 20 px hero gap + 12 below 1025 px */
  .bs-hero { padding-top: 176px; }
  .bs-hero-headline + .hero-cta-group { margin-top: 16px; }
}
@media (min-width: 768px) {
  /* Hero device fixes (hero QA of 22 sizes, 12 Nov). The headline's top stays where it is; the cap rises to 100 px so it
   keeps its share of the screen from 1728 px; the header's side gutter matches the hero's 32 px from 768 to 1024 px; a
   phone on its side starts the hero at 88 px; 768 px (iPad mini upright) takes the tablet hero, not the phone one; the
   phone logo row packs tighter (16 px a logo, the row at 80%) so two to three whole logos sit clear of the fades; from
   1440 px the button is 48 px tall with 15 px text. */
  .bs-hero-headline { font-size: var(--type-display); }
}
@media (min-width: 768px) and (max-width: 768.98px) {
  .bs-hero { padding-top: 128px; padding-bottom: 64px; padding-inline: var(--gutter-tablet); }
  .bs-hero-headline { font-size: var(--type-display); letter-spacing: -0.05em; line-height: 0.98; }
  .bs-hero .c-strip { --h: 340px; --gap: 10px; margin-inline: calc(-1 * var(--gutter-tablet)); }
}
@media (max-height: 500px) and (orientation: landscape) {
  .bs-hero { padding-top: 88px; }
}
@media (max-width: 767.98px) {
  .bs-hero .logo-pill { padding: 0 16px; }
  .bs-hero .logo-ticker-track { zoom: 0.8; }
}
@media (min-width: 1440px) {
  .bs-hero .hero-cta-btn { min-height: 48px; }
  .bs-hero .hero-cta-btn span { font-size: 15px; }
}
/* Phone headline, four lines by phrase ("A brand identity / in two weeks. / Designed by / senior people."), two
   variants one attribute apart (data-phone-headline on the hero): a) larger type, 30 / 56 / 56 px from the headline
   to the button, the small line to the logos, the logos to the strip; b) smaller type with today's tighter gaps, so
   more of the work strip shows in the first screen. Above 767 px the phrase breaks give way to the two sentences. */
.bs-hero-headline .hb-m { display: none; }
@media (max-width: 767.98px) {
  .bs-hero-headline .hb-m { display: inline; }
  .bs-hero[data-phone-headline="a"] .bs-hero-headline { font-size: var(--type-display-phone); }
  .bs-hero[data-phone-headline="a"] .logo-ticker { margin-top: 20px; }
  .bs-hero[data-phone-headline="a"] .c-strip { margin-top: 12px; }
  .bs-hero[data-phone-headline="b"] .bs-hero-headline { font-size: clamp(32px, 9.6vw, 42px); }
  .bs-hero[data-phone-headline="b"] .logo-ticker { margin-top: 4px; }
  .bs-hero[data-phone-headline="b"] .c-strip { margin-top: 0; }
}
/* Hero in two groups (Charlie, 12 Nov: "should the headline and CTA be kind of centred with the logo ticker above the
   images?"). Group 1, the ask (headline, button, its line), sits optically centred between the header and the logo row,
   lifted by 5% of that space; group 2, the proof, is the logo row tight on the work strip (logo ink to image top
   36 px). The strip keeps today's share of the first screen at 1280x720 to 1440x900: its top lands at 48.3vh + 215 px
   (the hero's min-height), and on taller screens it comes up a little rather than leave a hole; group 1 takes the
   space above. Tablets and phones keep their flow with the same grouping: a larger gap after the button's line, the
   logos tight on the strip. */
.hero-ask { display: contents; }
@media (min-width: 1025px) {
  .bs-hero { padding-top: 84px; row-gap: 0; min-height: calc(48.3vh + 675px); }
  .hero-ask { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 24px; flex: 1 0 auto; padding-bottom: 5.5vh; }
  .bs-hero .logo-ticker { padding-bottom: 2px; }
  .bs-hero .c-strip { margin-top: 24px; }
}
@media (min-width: 768px) and (max-width: 1024px) {
  .bs-hero .logo-ticker { margin-top: 26px; padding-bottom: 8px; }
}
@media (max-width: 767.98px) {
  .bs-hero .logo-ticker { padding-bottom: 8px; }
  .bs-hero[data-phone-headline="a"] .logo-ticker { margin-top: 20px; }
  .bs-hero[data-phone-headline="a"] .c-strip { margin-top: 0; }
  .bs-hero[data-phone-headline="b"] .logo-ticker { margin-top: 8px; }
  .bs-hero[data-phone-headline="b"] .c-strip { margin-top: -4px; }
}
/* A tile with a video (data-video, the Kedalion rock loop here): the video lies over the tile's still, the same size and
   crop, and takes no pointer */
.bs-hero .c-card[data-video] { position: relative; }
.bs-hero .c-card[data-video] video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  /* Reduced motion: the logo row stands still (one copy, centred, its edges still fading), as the work strip does */
  .bs-hero .logo-ticker { justify-content: center; }
  .bs-hero .logo-ticker-track { animation: none; }
  .bs-hero .logo-ticker-track[aria-hidden="true"] { display: none; }
}

/* ==========================================================================
   DELIVERS, THE PINNED SECTION (optional). Three text blocks on the left; one 4:5 frame pinned on the right whose
   picture changes with the block beside it (a push) and brand by brand inside a block (a sideways slide), with a
   segment row of one pill per brand. Below 1024 px, or when the screen is taller than wide, each frame stacks above
   its text. Motion in lander.js; the frames' markup is generated by scripts/brands/build_brands.py.
   ========================================================================== */
.what-we-do {
  display: flex;
  flex-direction: column;
  padding-block: 120px;
  padding-inline: var(--gutter-desktop);
  gap: 64px;
  background: var(--colour-white);
  position: relative;
  z-index: 1;
}
.offering-intro {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.offering-title {
  font-size: 36px;
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--colour-ink);
}
.offering-desc {
  font-size: 15px;
  font-weight: 400;
  line-height: 1.6;
  color: var(--colour-muted);
}
.offering-details {
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 1 1 0%;
  justify-content: flex-end;
}
.offering-list {
  display: flex;
  flex-direction: column;
}
.offering-list-item {
  display: flex;
  align-items: center;
  height: 56px;
  border-bottom: 1px solid #E4E4E7;
  font-size: 18px;
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 24px;
  color: var(--colour-ink);
  white-space: nowrap;
}
.offering-list-item { gap: 16px; }
.offering-list-num {
  font-size: var(--type-small);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  color: var(--colour-muted);
  flex-shrink: 0;
  width: 24px;
}
.offering-list-item:last-child {
  border-bottom: none;
}
@media (max-width: 1024px) {
  .what-we-do {
    padding-block: 80px;
    padding-inline: var(--gutter-tablet);
    gap: 40px;
  }
  .offering-title {
    font-size: 28px;
  }
  .offering-list-item {
    font-size: 15px;
    height: 48px;
  }
}
@media (max-width: 768px) {
  .what-we-do {
    padding-inline: var(--gutter-phone);
  }
}
.wwd-q-grid { display: grid; grid-template-columns: minmax(0, 1fr) var(--cr-w); column-gap: var(--space-frame-gap); }
.wwd-q-cell { min-height: var(--cr-h); display: flex; flex-direction: column; justify-content: center; }
.wwd-q-text { display: flex; flex-direction: column; gap: var(--space-group); }
.wwd-q .offering-desc, .wwd-q .offering-list { max-width: 420px; }
@media (min-width: 1024px) and (max-width: 1727.98px) and (min-aspect-ratio: 1001/1000) {
  /* Laptops, 1024 to 1727 wide (padding QA, fault 3, approved by Charlie 12 Nov): the frame sits at its height cap
   here, so the text column is wide and a balanced two-line description left 255 to 380 px of empty band before
   the frame. From 1024 the description runs a 28em measure (first lines 57 to 65 characters, the second three
   words or more; 29em would leave "at kickoff." on its own), never a word on its own (text-wrap: pretty in place
   of the site's balance, so the first line stays long): at the column's full width it ran 72 to 83 characters over
   a 10 to 18 character tail (coordinator, 12 Nov). The title, list and left edge unchanged. At 1728 and up (text
   beside a capped container) the 420 px balanced measure stays. */
  .wwd-q .offering-desc { max-width: 28em; text-wrap: pretty; }
}
.wwd-q .offering-intro { gap: var(--space-title-body); }
.wwd-q .offering-details { flex: none; justify-content: flex-start; }
/* production's numbered rows (13 px muted numerals in a 24 px column, 16 px to the item, on its baseline) without
   the hairlines */
.wwd-q .offering-list { gap: var(--space-list); }
.wwd-q .offering-list-item { height: auto; border-bottom: none; white-space: normal; align-items: baseline; }
.wwd-q-panel { position: sticky; top: var(--cr-top); width: var(--cr-w); height: var(--cr-h); margin-top: calc(-1 * var(--wwd-lift)); }
/* starts lifted too, so it is already pinned, 16 px over the card, when block 1 is centred to read */
.wwd-q-img {
  position: absolute;
  inset: 0;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--colour-placeholder);
  opacity: 0;
}
.wwd-q-img img { width: 100%; height: 100%; object-fit: cover; }
/* Brand guidelines in parallel (Charlie, 12 Nov): one strip per brand, every strip the same five 16:9 pages in the
   same order (cover, logo, colour, typography, application) at the same size, gap and margins, on the site black,
   side margins and gaps 2.2% of the frame. One endless column with an even rhythm (Charlie, 12 Nov: no "big gap"
   at the loop): every page has the one gap above it and nothing below, so the last page of a cycle meets the next
   cover across exactly the gap between any two pages. The script sets the gap and the page height in whole pixels
   (--lp-doc-gap, --lp-doc-ph, from the frame's width), so a cycle is a whole number of pixels and the wrap never
   opens or closes by a fraction. The strips sit side by side in the frame's rail, inside one track, and that track
   is the only thing that moves vertically (one animation, one transform), so every strip is always at the same
   offset: the set travels sideways as one slide to the next brand while the document keeps scrolling up, Clad's
   colour page meeting Reversa's at the same height. Each strip has the ground behind it. Two copies of the pages per
   strip, the second exactly one cycle below the first, so translateY(-50%) is one cycle and loops with no jump.
   Speed is set per page (--lp-doc-page). Changes (--lp-doc-cut): "page" as each page reaches the top margin, where
   the frame sits as it does at rest, a page whole in view; a time (3300ms) on that beat. It scrolls only while its
   block is the active one and the frame is on screen, from the covers each time; reduced motion shows the first
   brand's covers, still. */
.wwd-q-doc { background: var(--colour-ink); container-type: inline-size; }
.wwd-q-doc .doc-track { position: relative; will-change: transform; animation: lpDocScroll var(--lp-doc-dur, 50s) linear infinite paused; }
.wwd-q-doc .doc-strip { flex: 0 0 100%; width: 100%; display: flex; flex-direction: column; padding-inline: 2.2cqw; background: var(--colour-ink); }
.wwd-q-doc .doc-strip img { width: 100%; height: var(--lp-doc-ph, auto); aspect-ratio: 16 / 9; object-fit: fill; margin-top: var(--lp-doc-gap, 2.2cqw); flex: none; }
.wwd-q-doc.is-playing .doc-track { animation-play-state: running; }
@keyframes lpDocScroll { to { transform: translateY(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .wwd-q-doc .doc-track { animation: none; }
}
/* the frame on screen, and the one leaving while a push runs */
.wwd-q-img.is-prev { opacity: 1; z-index: 1; }
.wwd-q-img.is-active { opacity: 1; z-index: 2; }
@media (min-width: 1024px) and (min-aspect-ratio: 1001/1000) {
  /* the block the creative belongs to is in production's colours; the others are set in one quieter grey, #767676
   (4.54:1 on white), title, sub-copy, numerals and items alike, changing over 200 ms (no movement) */
  .wwd-q-text .offering-title, .wwd-q-text .offering-desc, .wwd-q-text .offering-list-item, .wwd-q-text .offering-list-num { transition: color var(--duration-state) ease; }
  .wwd-q-cell:not(.is-current) .wwd-q-text .offering-title, .wwd-q-cell:not(.is-current) .wwd-q-text .offering-desc,
  .wwd-q-cell:not(.is-current) .wwd-q-text .offering-list-item, .wwd-q-cell:not(.is-current) .wwd-q-text .offering-list-num { color: var(--colour-quiet); }
}
@media (prefers-reduced-motion: reduce) {
  .wwd-q-text .offering-title, .wwd-q-text .offering-desc, .wwd-q-text .offering-list-item, .wwd-q-text .offering-list-num { transition: none; }
}
@media not all and (min-width: 1024px) and (min-aspect-ratio: 1001/1000) {
  /* Stacked (whenever not pinned: this query is the exact complement of the pinned one, the same string the script
   reads, so the two never disagree; at an aspect between 1.000 and 1.001 the CSS pinned while the script stacked):
   each frame above its text, as wide as the container but never taller than 78% of the small viewport (a phone on
   its side, an iPad upright) nor wider than 675 px, so its 1080 px images are never upscaled more than 1.25x on a
   2x screen (an iPad Pro 13 upright showed them at 852 px, 1.58x), its left edge on the text's (the container's) edge, as the text is set left (padding QA, fault 8: centred, it
   sat 44.5 px inside the text at 768 and 9.8 px at 820); the segment row inside its bottom edge, 10 px in from
   either side of the frame. */
  .wwd-q-grid { display: flex; flex-direction: column; --st-w: min(100%, calc(var(--cr-vh) * 0.78 * 0.8), 675px); }
  .wwd-q-cells, .wwd-q-media, .wwd-q-panel, .wwd-q-mask { display: contents; }
  .wwd-q-img, .wwd-q-img.is-prev, .wwd-q-img.is-active {
    position: relative;
    inset: auto;
    width: var(--st-w);
    align-self: flex-start;
    aspect-ratio: 4 / 5;
    opacity: 1;
    z-index: auto;
    transition: none;
  }
  .wwd-q-cell { min-height: 0; padding: 32px 0 64px; }
  .wwd-q-cell:last-child { padding-bottom: 0; }
  .wwd-q-text { max-width: none; }
  .wwd-q-img:nth-child(1) { order: 1; }
  .wwd-q-ind[data-b="0"] { order: 2; }
  .wwd-q-cell:nth-child(1) { order: 3; }
  .wwd-q-img:nth-child(2) { order: 4; }
  .wwd-q-ind[data-b="1"] { order: 5; }
  .wwd-q-cell:nth-child(2) { order: 6; }
  .wwd-q-img:nth-child(3) { order: 7; }
  .wwd-q-ind[data-b="2"] { order: 8; }
  .wwd-q-cell:nth-child(3) { order: 9; }
}
/* Motion (Charlie, 12 Nov). Between blocks the creative pushes: the next block travels up from below through the
   full height of the frame while the last one leaves at the top, masked by the frame (reversed when scrolling back
   up), carrying the same brand; the guide pushes as one piece. Within a block the brands travel sideways, quicker
   than the push (Charlie: they "should swipe from right to left and swipe from left to right ... but it could be
   quicker than the up and down one"): 450 ms on the push's easing, the next brand coming in from the right (from
   the last back to the first too, never a rewind), an earlier one from the left. Autoplay, a click and an arrow
   key make the same travel. Logos move on every 2 s (Charlie: "could be a bit quicker"), applications every 3.3 s,
   the guides once a page, the whole set of strips travelling as one slide while they keep scrolling up; each hold
   counts from the moment the travel lands. After a push the brand gets a full hold, its timer starting when the
   push lands. An ad visitor's own brand holds 4.8 s on its first showing. Reduced motion: an instant cut. */
.wwd-q-img.is-moving { will-change: transform; }
/* the push: both frames on their own layers while the script moves them */
/* Each frame is a native horizontal scroll-snap rail, one slide per brand at the frame's full width (a clone of
   the last before the first and of the first after the last, for the endless list): fingers and trackpads move it
   with the system's own momentum and snap, one brand per flick (snap-stop always); the page's vertical scroll
   passes through; the browser's back and forward swipe stays out (overscroll contain); no scrollbar. */
.wwd-q-rail { position: absolute; inset: 0; display: flex; overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory; overscroll-behavior-x: contain; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.wwd-q-rail::-webkit-scrollbar { display: none; }
.wwd-q-rail > * { flex: 0 0 100%; width: 100%; height: 100%; scroll-snap-align: start; scroll-snap-stop: always; }
.wwd-q-doc .wwd-q-rail { position: relative; inset: auto; align-items: flex-start; }
.wwd-q-doc .wwd-q-rail > * { height: auto; }
/* Hemi's logo tile is white on the white page: an inside hairline in a soft grey on that slide alone (and its
   clone), on the frame's 8 px radius, so it travels with the slide and never shows on a neighbour (Charlie: "put
   an extremely subtle outline around hemi soft grey just soft so its there"); not on its jacket or its guide */
.wwd-q-img[data-kind="logo"] .wwd-q-rail > [data-client="hemi"] { border-radius: var(--radius); outline: 1px solid rgba(9, 9, 11, 0.08); outline-offset: -1px; }
@media (min-width: 1024px) and (min-aspect-ratio: 1001/1000) {
  /* the mask: on desktop the pinned frame clips at the 8 px radius (and clip-path, which WebKit needs to keep the
   corners round over a moving layer) with the frames square inside it, so two frames meeting mid-push show no
   rounded notch; stacked frames below 1024 px clip themselves */
  .wwd-q-mask { position: absolute; inset: 0; clip-path: inset(0 round var(--radius)); }
  .wwd-q-img { border-radius: 0; }
}
@media not all and (min-width: 1024px) and (min-aspect-ratio: 1001/1000) {
  .wwd-q-img { clip-path: inset(0 round var(--radius)); }
}
/* Controls (Charlie, 12 Nov): a click or tap on the frame shows the next brand, a sideways swipe the next or the
   previous one, the arrow keys too; the page still scrolls through it (pan-y). On the frame, the stories pattern
   (Charlie: "follow better precedents, reels ... more subtle and elegant"; "the bar should be at the bottom"): along
   the bottom, 10 px in, one 2 px pill
   per brand sharing the width, 3 px apart, no outline or box; a track of white at 35% and a white fill growing
   from the left at a steady rate over the hold, the brands before the current one full, the ones after it track
   only; the state changes in an instant, nothing un-fills. A barely-there shadow on each white pill keeps it
   legible without a scrim; where white cannot read, that pill takes the ink pair instead, pill by pill (data-tone
   on each image: one letter per pill for the stretch of image under it; on the guides, the tone of the page band
   passing under each pill, from data-tones on each page, held while a gap between pages passes, so a coloured
   swatch never tints it the way a difference blend did). The row sits above the images, stays still while they
   push beneath it and is clipped by the frame's radius; each pill is a button that jumps to its brand, its hit
   area 44 px tall, reaching up into the frame. No brand name: the work says whose it is. */
.wwd-q-img { cursor: pointer; }
.wwd-q-img:focus-visible { outline: 2px solid var(--colour-ink); outline-offset: -2px; }
.wwd-q-ind { position: absolute; left: 10px; right: 10px; bottom: 10px; z-index: 10; display: flex; align-items: flex-end; gap: 3px; height: 2px; }
.wwd-q-tick { position: relative; flex: 1 1 0; align-self: flex-end; height: 44px; min-width: 0; padding: 0; border: 0; background: none; cursor: pointer; }
/* each pill's tap target reaches halfway across the 3 px gaps to its neighbours and, at the ends, out to the
   frame's edges, so the targets tile the frame's width without overlapping (a phone on its side had 40 px pills:
   now 43.4 px for the middle three and 51.9 px for the end ones at 667x375, 45.3 and 53.8 px at 844x390; five
   middle-sized targets of 44 px do not fit a 214 px row, so they share it equally); the pills look the same */
.wwd-q-tick::before { content: ''; position: absolute; top: 0; bottom: 0; left: -1.5px; right: -1.5px; }
.wwd-q-tick:first-child::before { left: -10px; }
.wwd-q-tick:nth-last-child(2)::before { right: -10px; }
.wwd-q-tick { color: var(--colour-white); }
.wwd-q-tick i { position: absolute; left: 0; right: 0; bottom: 0; height: 2px; border-radius: 1px; background: rgba(255, 255, 255, 0.35); overflow: hidden; box-shadow: 0 0 1px rgba(0, 0, 0, 0.28); }
.wwd-q-tick.is-done i { background: var(--colour-white); }
.wwd-q-tick.is-on i::after { content: ''; position: absolute; inset: 0; border-radius: 1px; background: var(--colour-white); transform-origin: left; transform: scaleX(var(--wwd-p, 1)); }
.wwd-q-tick.is-lt { color: var(--colour-ink); }
.wwd-q-tick.is-lt i { background: rgba(9, 9, 11, 0.18); box-shadow: none; }
.wwd-q-tick.is-lt.is-done i, .wwd-q-tick.is-lt.is-on i::after { background: rgba(9, 9, 11, 0.8); }
.wwd-q-ind::before { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 44px; }
.wwd-q-ind, .wwd-q-ind::before { cursor: pointer; }
/* the gaps belong to the row, so the pointer never drops out between pills */
.wwd-q-tick:focus-visible { outline: none; }
.wwd-q-tick:focus-visible i { outline: 2px solid currentColor; outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  /* Hover (mouse and trackpad only; Charlie, 12 Nov: "puffs out ... like how Apple does", then "a little bit clunky"):
   one continuous magnification that follows the pointer like the Dock. The script sets each pill's thickness every
   frame from a cosine falloff of its distance to the pointer (zero at 1.2 pills away), 2 px at rest to 5 px right
   under it, eased toward that each frame (21% of the way rising, 17% relaxing: about 200 ms in, 260 ms out, no
   overshoot), so the swell travels along the row as one wave. Widths and gaps never change; each pill grows from its
   centre line and stays a pill; its track brightens with it (35% to 55% white, 18% to 28% ink). A press dips the
   pill under the pointer by 1 px. Written as --wwd-h and --wwd-a on each pill. Reduced motion: the hovered pill
   is 4 px and nothing moves. */
  .wwd-q-tick i { bottom: 1px; height: var(--wwd-h, 2px); border-radius: var(--radius-pill); transform: translateY(50%); }
  .wwd-q-tick.is-on i::after { border-radius: var(--radius-pill); }
  .wwd-q-tick:not(.is-done) i { background: rgba(255, 255, 255, var(--wwd-a, 0.35)); }
  .wwd-q-tick.is-lt:not(.is-done) i { background: rgba(9, 9, 11, calc(var(--wwd-a, 0.35) * 0.514)); }
}
/* Press and hold (stories): holding the frame or the row pauses everything, letting go carries on; so a hold never
   selects text, drags an image or opens the iOS callout or a context menu */
.wwd-q-img, .wwd-q-ind { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.wwd-q-img img { -webkit-user-drag: none; }
.wwd-q-doc.is-held .doc-track, .wwd-q-doc.is-playing.is-held .doc-track { animation-play-state: paused; }
/* Pause / Play: out of sight until it has keyboard focus, then a small pill at the row's right end */
.wwd-q-play { position: absolute; right: 0; bottom: 10px; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.wwd-q-play:focus-visible { width: auto; height: auto; margin: 0; padding: 4px 10px; clip: auto; overflow: visible; border-radius: var(--radius-pill); background: rgba(9, 9, 11, 0.78); color: var(--colour-white); font-family: inherit; font-size: 12px; line-height: 16px; font-weight: 500; outline: 2px solid var(--colour-white); outline-offset: 1px; }
@media (min-width: 1024px) and (min-aspect-ratio: 1001/1000) {
  .wwd-q-mask .wwd-q-ind:not(.is-current) { visibility: hidden; }
}
@media not all and (min-width: 1024px) and (min-aspect-ratio: 1001/1000) {
  .wwd-q-ind { position: relative; left: auto; right: auto; bottom: auto; align-self: flex-start; width: calc(var(--st-w) - 20px); margin: -12px 0 10px 10px; }
}
@media (max-width: 1023.98px) and (min-aspect-ratio: 1001/1000) and (max-height: 540px) {
  /* A phone on its side (under 1024 px, wider than tall, under 540 px tall): each frame beside its text, two
   columns, the frame 78% of the small viewport tall and centred on its row, the text centred on it; the segment
   row 10 px inside the frame's bottom and sides, also where the text runs taller than the frame (centred with the
   frame, its top margin the frame's height less 22 px, so it ends 10 px above the frame's bottom) */
  .wwd-q-grid { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 40px; row-gap: 56px; align-items: center; }
  .wwd-q-img:nth-child(1), .wwd-q-ind[data-b="0"] { grid-area: 1 / 1; }
  .wwd-q-cell:nth-child(1) { grid-area: 1 / 2; }
  .wwd-q-img:nth-child(2), .wwd-q-ind[data-b="1"] { grid-area: 2 / 1; }
  .wwd-q-cell:nth-child(2) { grid-area: 2 / 2; }
  .wwd-q-img:nth-child(3), .wwd-q-ind[data-b="2"] { grid-area: 3 / 1; }
  .wwd-q-cell:nth-child(3) { grid-area: 3 / 2; }
  .wwd-q-img, .wwd-q-img.is-prev, .wwd-q-img.is-active { width: calc(var(--cr-vh) * 0.78 * 0.8); align-self: center; }
  .wwd-q-ind { align-self: center; width: calc(var(--cr-vh) * 0.78 * 0.8 - 20px); margin: calc(var(--cr-vh) * 0.78 - 22px) 0 0 10px; }
  .wwd-q-cell, .wwd-q-cell:last-child { padding: 0; }
}
/* the numerals' column grows with the text (24 px at 13 px), so they keep their column at any text size */
.wwd-q .offering-list-num { width: 1.85em; }

/* ==========================================================================
   HOW IT WORKS (optional). One heading and three steps; three columns from 1024 px.
   ========================================================================== */
.how-it-works {
  display: flex;
  flex-direction: column;
  padding-block: 80px;
  padding-inline: var(--gutter-desktop);
  gap: 48px;
  position: relative;
  z-index: 1;
  background: var(--colour-white);
}
.hiw-steps {
  display: flex;
  gap: 48px;
}
.hiw-step {
  display: flex;
  flex-direction: column;
  flex: 1 1 0%;
  gap: 12px;
}
.hiw-step-number {
  font-size: var(--type-small);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  line-height: 20px;
  color: var(--colour-muted);
}
.hiw-step-title {
  font-size: 20px;
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 26px;
  color: var(--colour-ink);
}
.hiw-step-desc {
  font-size: 15px;
  font-weight: 400;
  line-height: 24px;
  color: var(--colour-muted);
}
@media (max-width: 1024px) {
  .how-it-works {
    padding-block: 64px;
    padding-inline: var(--gutter-tablet);
    gap: 32px;
  }
  .hiw-steps {
    flex-direction: column;
    gap: 32px;
  }
  .hiw-step-title {
    font-size: 18px;
    line-height: 22px;
  }
  .hiw-step-desc {
    font-size: var(--type-ui);
    line-height: 20px;
  }
}
@media (max-width: 768px) {
  .how-it-works {
    padding-block: 48px;
    padding-inline: var(--gutter-phone);
    gap: 24px;
  }
  .hiw-step-desc {
    font-size: var(--type-ui);
    line-height: 22px;
  }
}
.how-it-works { gap: var(--space-title-desktop); }
@media (max-width: 1023.98px) {
  .how-it-works { gap: var(--space-title-tablet); }
}
@media (min-width: 1024px) {
  /* ── How it works, proof, the dark booking section and the FAQ on the same container ──
   No rules: the section headings replace the labels and their rules, and the rules between the two stats go. */
  .hiw-steps { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-columns); }
}

/* ==========================================================================
   PROOF (optional). A quote across two columns and two stats in the third; below 1024 px the stats sit under the quote.
   lander.js counts the figures up once and swaps the quote and stats for some ad visitors (lander-data).
   ========================================================================== */
.proof {
  display: flex;
  flex-direction: column;
  padding-block: 80px 96px;
  padding-inline: var(--gutter-desktop);
  position: relative;
  z-index: 1;
  background: var(--colour-white);
}
.proof-content {
  display: flex;
  align-items: flex-start;
  gap: 176px;
}
.proof-testimonial {
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  width: 520px;
  gap: 24px;
}
.proof-quote-mark {
  font-size: 32px;
  font-weight: 400;
  line-height: 1;
  color: var(--colour-ink);
}
.proof-quote-text {
  font-size: 24px;
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.4;
  color: var(--colour-ink);
}
.proof-author {
  display: flex;
  align-items: center;
  gap: 12px;
}
.proof-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--colour-placeholder);
  border: 1px solid var(--colour-hairline);
  flex-shrink: 0;
  overflow: hidden;
}
.proof-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.proof-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.proof-name {
  font-size: var(--type-ui);
  font-weight: 500;
  line-height: 18px;
  color: var(--colour-ink);
}
.proof-role {
  font-size: var(--type-small);
  font-weight: 400;
  line-height: 16px;
  color: var(--colour-muted);
}
.proof-stats {
  display: flex;
  flex-direction: column;
  flex: 1 1 0%;
}
.proof-stat {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-block: 32px;
  border-bottom: 1px solid var(--colour-hairline);
}
/* Stat figures (Charlie, 13 Nov: "they feel quite big and just cumbersome"): a companion to the quote, not a second
   headline, about 1.3 times its size (--type-stat: 36, 26, 24 px). Weight 400 like every figure on the page, tracking
   with the quote's, tight leading. While the figure counts up (lander.js adds .is-counting) its digits are tabular, as
   the step and list numbers, so nothing jitters: every digit is one width and the suffix only moves on when a digit is
   added. The landed figure is proportional, so "10" and "100,000" keep their natural spacing. */
.proof-stat-number {
  font-size: var(--type-stat);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--colour-ink);
}
.proof-stat-number.is-counting { font-variant-numeric: tabular-nums; }
.proof-stat-label {
  font-size: var(--type-caption);
  font-weight: 400;
  line-height: 1.5;
  color: var(--colour-muted);
}
@media (max-width: 1024px) {
  .proof {
    padding-block: 64px 72px;
    padding-inline: var(--gutter-tablet);
  }
  .proof-content {
    flex-direction: column;
    gap: 48px;
  }
  .proof-testimonial {
    width: 100%;
  }
  .proof-quote-text {
    font-size: 20px;
  }
  .proof-stats {
    display: flex;
    flex-direction: row;
    gap: 48px;
  }
  .proof-stat {
    flex: 1 1 0%;
    padding-block: 24px;
  }
}
@media (max-width: 768px) {
  .proof {
    padding-block: 48px 56px;
    padding-inline: var(--gutter-phone);
  }
  .proof-content {
    gap: 32px;
  }
  .proof-quote-text {
    font-size: 18px;
  }
  .proof-stats {
    flex-direction: column;
    gap: 0;
  }
}
/* Proof, on the "How it works" grid (Charlie, 12 Nov: the stats on the grid line on the right, more room for the
   testimonial). From 1024 px three equal columns with the steps' gap: the quote and its author across columns 1 and
   2 from the container's left edge (opening mark hung in the margin, so the first line starts on the edge), both
   stats stacked in column 3, their left edge on the "Ship" step's line. Each stat reads as one unit, its label
   --space-figure-label under the figure; the two stats sit clearly further apart than that (32 px from 1025, 22 px at
   1024, 24 px on phones), so the column ends level with or above the author row on the default quote. The first
   figure's cap top is level with the quote's first-line cap top: the stats' margin is the quote's cap top in its
   first line less the figure's (0.1363 of its size at line-height 1, Inter Tight), rounded to a whole pixel. Below
   1024 px, where the steps stack, the stats sit under the quote (side by side at tablet, stacked on phones, where they
   sit a little further from the author than from each other). Labels stay 15 px muted. */
.proof-testimonial { position: relative; }
.proof-quote-mark { position: absolute; top: 0; left: 0; transform: translateX(-100%); font-size: 24px; line-height: 1.4; }
.proof-content { align-items: start; }
.proof-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-columns); }
.proof-stat { padding-block: 0; border-bottom: none; gap: var(--space-figure-label); }
.proof-testimonial { max-width: 480px; }
@media (min-width: 1024px) {
  .proof-content { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--space-columns); row-gap: 0; align-items: start; }
  .proof-testimonial { grid-column: 1 / 3; width: auto; max-width: none; }
  /* at 1024 the quote is 20 px on 28 px lines (cap top 6.73 px down), the figure 26 px: 3 px */
  .proof-stats { grid-column: 3; display: flex; flex-direction: column; gap: 22px; margin-top: round(calc(6.73px - 0.1363 * var(--type-stat)), 1px); }
}
@media (max-width: 1023.98px) {
  .proof-content { align-items: stretch; }
}
@media (min-width: 1025px) {
  /* The quote one size up from 1025 px (24 to 28 px, its mark with it), so the two-sentence default fills columns 1 and 2
   beside the two stacked stats instead of stopping short of them (Charlie, 12 Nov) */
  .proof-quote-text, .proof-quote-mark { font-size: var(--type-quote); line-height: 1.25; }
  .proof-quote-text { letter-spacing: -0.02em; }
  /* the quote 28 px on 35 px lines (cap top 7.32 px down), the figure 36 px: 2 px */
  .proof-stats { gap: var(--space-group); margin-top: round(calc(7.32px - 0.1363 * var(--type-stat)), 1px); }
}
@media (max-width: 1024px) {
  /* set as display, not paragraph (type audit, 12 Nov: the homepage's 28 px setting); the mark keeps the text's leading so it stays on the first line */
  .proof-quote-mark { font-size: 20px; }
}
@media (max-width: 768px) {
  .proof-quote-mark { font-size: 18px; }
  /* stacked under the author: 40 px from the author row (the content's 32 px gap and 8 px), 24 px between the two */
  .proof-stats { grid-template-columns: minmax(0, 1fr); row-gap: 24px; margin-top: 8px; }
}
@media (max-width: 1023.98px) {
  /* Proof below 1024 px: the gutters are too narrow to hang the opening quote mark in, so it sets inline at the start
   of the quote (the quote's own first character, same size and colour) and the whole quote sits inside the gutter;
   from 1024 px it hangs in the container margin (absolute, so it never adds width or scroll) */
  .proof-quote-mark { display: none; }
  .proof-quote-text::before { content: "\201C"; }
}
/* the "+" box grows with its glyph at large text (32 px as before at normal size) */
.proof-stat-number { overflow-wrap: anywhere; }
/* 24 px gap + 16 */
/* Proof quote lines near equal length (Charlie, 12 Nov: "the line break needs to be balanced better") */
.proof-quote-text { text-wrap: balance; }
.proof-quote-text .nw { white-space: nowrap; }
@media (max-width: 767.98px) {
  .proof-quote-text .qb { display: none; }
}

/* ==========================================================================
   BOOKING (required). The dark section: a heading, one line and the inline Cal.com calendar, which lander.js starts
   loading 2,500 px ahead or on any press of a #book link. A quiet panel holds the calendar's height until it has drawn.
   ========================================================================== */
.footer-cta {
  background: var(--colour-ink);
  display: flex;
  padding-block: 64px 8px;
  padding-inline: var(--gutter-desktop);
  position: relative;
}
.footer-cta > * { position: relative; z-index: 1; }
/* Static, consistent lift behind the calendar - fades out well before the section edges */
.footer-cta::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(58% 44% at 50% 48%, rgba(255, 255, 255, 0.09), transparent 72%);
}
.footer-cta-inner {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 40px;
  width: 100%;
}
.footer-cta-text {
  max-width: 720px;
  align-self: center;
  text-align: center;
  padding-block: 24px 16px;
}
.footer-cta-text {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.footer-cta-heading {
  font-size: var(--type-display-2);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.02;
  color: var(--colour-on-dark);
}
.footer-cta-subline {
  font-size: 17px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--colour-on-dark-body);
  margin-bottom: 16px;
}
.footer-cta-microcopy {
  font-size: 17px;
  font-weight: 400;
  line-height: 1.5;
  color: var(--colour-on-dark-body);
}
.footer-cta-calendar {
  flex: 0 0 auto;
  width: 100%;
  min-width: 0;
  background: transparent;
}
.footer-cta-calendar #cal-inline {
  width: 100%;
  min-height: 620px;
}
/* Loading state: shows until Cal injects its iframe, then :empty stops matching */
.footer-cta-calendar #cal-inline:empty {
  display: flex;
  align-items: center;
  justify-content: center;
}
.footer-cta-calendar #cal-inline:empty::before {
  content: "Loading calendar\2026";
  font-size: 15px;
  color: rgba(255, 255, 255, 0.4);
}
@media (min-width: 769px) {
  /* Force the embed iframe tall enough that the full day of slots is visible
   with no internal scrolling. Cal fills whatever height it is given. */
  .footer-cta-calendar #cal-inline iframe { min-height: 900px; }
}
@media (min-width: 1150px) {
  .footer-cta-calendar #cal-inline iframe { min-height: 620px; }
}
@media (max-width: 1024px) {
  .footer-cta {
    padding-block: 56px 8px;
    padding-inline: var(--gutter-tablet);
  }
  .footer-cta-subline {
    font-size: 16px;
    margin-bottom: 8px;
  }
}
@media (max-width: 768px) {
  .footer-cta {
    padding-block: 48px 8px;
    padding-inline: var(--gutter-phone);
  }
  .footer-cta-inner {
    flex-direction: column;
    align-items: flex-start;
    gap: 32px;
  }
  /* Stop the text block stretching to match the calendar height (column flex) */
  .footer-cta-text { flex: 0 0 auto; width: 100%; }
  .footer-cta-calendar { flex: 0 0 auto; width: 100%; }
  .footer-cta-calendar #cal-inline { height: auto; }
}
.footer-cta-text { padding-top: 0; }
/* the email address breaks rather than run past a 360 px screen at large text */
/* Booking calendar: until Cal.com reports it has drawn, a quiet panel holds its place (the size it lands at on
   phones), with one muted line in it, so the section never looks empty on arrival */
.footer-cta-calendar #cal-inline { position: relative; }
.footer-cta-calendar #cal-inline:empty::before { content: none; }
.footer-cta-calendar #cal-inline:not(.cal-ready) { border-radius: var(--radius); background: rgba(255, 255, 255, 0.04); }
.footer-cta-calendar #cal-inline:not(.cal-ready)::after { content: "Loading calendar\2026"; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); font-size: 15px; color: rgba(255, 255, 255, 0.6); pointer-events: none; white-space: nowrap; }
/* ...and the box keeps the height Cal.com's calendar settles at, before and after it draws, so nothing moves when it
   does (final run, 12 Nov: on a phone the box went 900 to 736 to 1,072 px and the calendar jumped 300 px, CLS 0.22).
   Measured settled heights (Cal's stacked layout, below a 768 px wide frame): 1,026 at 320, 1,028 at 360, 1,041 at
   375, 1,054 at 390, 1,072 at 412, 1,088 at 430, 1,128 at 500, 1,214 at 600, 1,295 at 700, 1,333 at 768, 1,378 at
   820, 1,387 at 831; from 832 its two-column layout, held at 900 by the frame's own min-height; 620 from 1,150. The
   frame sits at the top of the box (Cal's own element is a wrapping flex box that centred the frame while it grew,
   so it climbed as it drew). A month with six weeks runs one row taller and grows the box below the fold. */
.footer-cta-calendar #cal-inline cal-inline { align-content: flex-start; align-items: flex-start; }
@media (max-width: 430px) {
  .footer-cta-calendar #cal-inline { min-height: max(1026px, calc(719px + 85.7vw)); }
}
@media (min-width: 430.02px) and (max-width: 767.98px) {
  .footer-cta-calendar #cal-inline { min-height: max(1088px, calc(704px + 84.5vw)); }
}
@media (min-width: 768px) and (max-width: 831.98px) {
  .footer-cta-calendar #cal-inline { min-height: calc(684px + 84.5vw); }
}
@media (min-width: 832px) and (max-width: 1149.98px) {
  .footer-cta-calendar #cal-inline { min-height: 900px; }
}

/* ==========================================================================
   FAQ (optional). Plain rows on the dark section, no cards: a question, its answer opening under it (the row's own
   onclick toggles .open).
   ========================================================================== */
.eyebrow {
  font-size: 20px;
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 24px;
  color: var(--colour-muted);
}
.faq {
  background: var(--colour-ink);
  display: flex;
  flex-direction: column;
  padding-block: 40px 96px;
  padding-inline: var(--gutter-desktop);
  gap: 48px;
  position: relative;
  z-index: 1;
}
.faq-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 16px;
  width: 100%;
  max-width: 1040px;
  margin-inline: auto;
}
.faq-header-top {
  display: flex;
  justify-content: center;
}
.faq .eyebrow { color: rgba(255, 255, 255, 0.45); }
.faq-list {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 1040px;
  margin-inline: auto;
}
/* FAQ rows are plain rows on the dark section (Charlie's rule, 12 Nov: no tinted or outlined cards; they were 5%
   white cards with an 8 px radius): no fill, no radius, the text on the container's edges, rows apart by spacing.
   --faq-row is each row's space above and below its text (the tap target, at least 44 px tall); the list gives it
   back at its top and bottom so the section's spacing is still measured text to text. */
.faq { --faq-row: 20px; }
.faq-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--faq-row) 0;
  cursor: pointer;
}
.faq-question {
  font-size: var(--type-item);
  font-weight: 400;
  letter-spacing: -0.01em;
  line-height: 1.3;
  color: var(--colour-white);
}
.faq-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  font-size: 32px;
  font-weight: 200;
  line-height: 1;
  color: var(--colour-white);
  transition: transform 0.2s;
}
.faq-answer {
  display: none;
  padding: 0 0 var(--faq-row);
}
.faq-answer p {
  font-size: var(--type-body);
  font-weight: 400;
  line-height: 1.5;
  color: var(--colour-on-dark-body);
  max-width: 30em;
}
.faq-item.open + .faq-answer { display: block; }
.faq-item.open .faq-icon { transform: rotate(45deg); }
@media (max-width: 1024px) {
  .faq {
    padding-block: 32px 64px;
    padding-inline: var(--gutter-tablet);
    gap: 32px;
  }
  .faq { --faq-row: 18px; }
}
@media (max-width: 768px) {
  .faq {
    padding-block: 40px 48px;
    padding-inline: var(--gutter-phone);
    gap: 24px;
  }
  .faq-icon {
    width: 26px;
    height: 26px;
    font-size: 26px;
  }
}
@media (min-width: 1024px) {
  .faq-header, .faq-list { max-width: none; }
}
/* Contrast (12 Nov sweep, both landers). Links in the dark FAQ answers took system.css's light-section link colour
   (#09090B on the dark panel, 1.1:1, also on production): they now take the answer text's own light colour with a
   55% white underline, and turn full white with a solid underline on hover and keyboard focus. Muted greys under 4.5:1 move to the
   page's next existing step: the FAQ label and the footer column labels to 50% white, the booking card's sub-line
   to the page's muted grey. */
.faq .faq-answer a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: rgba(255, 255, 255, 0.55); transition: color var(--duration-state) ease, text-decoration-color var(--duration-state) ease; }
.faq .faq-answer a:hover, .faq .faq-answer a:focus-visible { color: var(--colour-white); text-decoration-color: var(--colour-white); }
.faq .eyebrow { color: var(--colour-on-dark-label); }
/* FAQ questions never end on a single word at phone widths (responsive sweep, 360 px) */
.faq-question { text-wrap: balance; }
/* Large text (200% text zoom, and 375 px at normal size): the FAQ question keeps the "+" icon's room on its right in
   em, so the two never touch at any text size; on phones the footer columns take at least 5.5em each, so a long name
   ("Awwwards") at large text moves the column to its own row instead of running 9 px past the screen. */
.faq-question { padding-right: 0.75em; }
.faq-icon { width: max(32px, 1em); height: max(32px, 1em); }
/* 10 (plain rows, 12 Nov), the list hands back its first row's space above and its last row's space below, so the FAQ
   label to the first question and the last question to the footer are measured text to text like every other pair */
.faq-list { margin-block: calc(-1 * var(--faq-row)); }
/* 11, every width: the "+" box (32 px) never props up a one-line row, so a row's height is its text plus --faq-row
   above and below and one- and two-line questions keep the same inset (on phones the two-line ones are common) */
.faq-icon { margin-block: -7px; }

/* ==========================================================================
   FOOTER (required). Wordmark, three link columns, one hairline, the meta row.
   ========================================================================== */
.footer {
  background: var(--colour-ink);
  display: flex;
  flex-direction: column;
  padding-block: 80px 32px;
  padding-inline: var(--gutter-desktop);
}
.footer-main {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 80px;
  padding-bottom: 64px;
}
.footer-logo {
  flex-shrink: 0;
  display: inline-block;
}
.footer-logo svg {
  height: 21px;
  width: auto;
  display: block;
}
.footer-cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, auto));
  gap: 64px;
}
.footer-col {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}
.footer-col-label {
  font-size: var(--type-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  line-height: 16px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.4);
  margin-bottom: 4px;
}
.footer-col a {
  font-size: var(--type-ui);
  font-weight: 400;
  line-height: 20px;
  color: var(--colour-on-dark-link);
  text-decoration: none;
  transition: color var(--duration-state) ease, text-decoration-color var(--duration-state) ease;
}
.footer-col a:hover {
  color: var(--colour-white);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.footer-divider {
  width: 100%;
  height: 1px;
  background: var(--colour-on-dark-rule);
}
.footer-meta-link {
  color: rgba(255, 255, 255, 0.4);
  text-decoration: none;
  transition: color 0.2s, text-decoration 0.2s;
}
.footer-meta-link:hover { color: var(--colour-white); text-decoration: underline; text-underline-offset: 3px; }
.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-top: 24px;
}
.footer-meta {
  font-size: var(--type-small);
  font-weight: 400;
  line-height: 16px;
  color: var(--colour-on-dark-label);
}
@media (max-width: 1024px) {
  .footer {
    padding-block: 64px 28px;
    padding-inline: var(--gutter-tablet);
  }
  .footer-main {
    flex-direction: column;
    gap: 48px;
    padding-bottom: 48px;
  }
  .footer-cols {
    grid-template-columns: repeat(2, 1fr);
    gap: 40px 32px;
  }
  .footer-logo svg { height: 19px; }
}
@media (max-width: 768px) {
  .footer {
    padding-block: 48px 24px;
    padding-inline: var(--gutter-phone);
  }
  .footer-main {
    gap: 40px;
    padding-bottom: 40px;
  }
  .footer-cols {
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: 32px 20px;
    width: 100%;
  }
  .footer-logo svg { height: 17px; }
  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    padding-top: 20px;
  }
}
@media (min-width: 769px) {
  .footer { padding-bottom: 130px; }
  /* the footer's last row clears the card (24 + 74 + 32) */
}
@media (max-width: 768px) {
  /* Mobile: the footer's last line clears the booking bar pinned to the bottom of the screen */
  .footer { padding-bottom: calc(112px + env(safe-area-inset-bottom)); }
}
.footer-col-label { color: var(--colour-on-dark-label); }
@media (max-width: 768px) {
  /* at 200% text a figure like 100,000+ breaks inside its column rather than spill */
  .footer-cols { grid-template-columns: repeat(auto-fit, minmax(max(96px, 5.5em), 1fr)); }
}
.footer-meta-link { overflow-wrap: anywhere; }
@media (max-width: 768px) {
  .footer { padding-bottom: calc(116px + env(safe-area-inset-bottom)); }
}
@media (max-width: 379.98px) {
  .footer { padding-bottom: calc(154px + env(safe-area-inset-bottom)); }
}
@media (min-width: 769px) and (max-width: 1024px) {
  /* 7 and 9, tablet 769 to 1024 px: the footer's three columns across the full width, and the header's right side on
   the logo's 32 px */
  .footer-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); width: 100%; }
}

/* ==========================================================================
   COOKIE DIALOG. consent.js draws it; these rules only place it: bottom left on desktop, a sheet on phones.
   ========================================================================== */
body > .pow-consent { background: rgba(9, 9, 11, 0.96); }
@media (min-width: 769px) {
  body > .pow-consent { left: 24px; right: auto; transform: translateY(8px); }
  body > .pow-consent.is-visible { transform: translateY(0); }
}

/* ==========================================================================
   ACROSS SECTIONS. One container and one spacing between sections, set after the components so it wins over their
   first values: 160 px between sections from 1025 px, 128 px at tablet, 96 px on phones (half above and half below
   each), and one centred column from 1024 px (--container-pad).
   ========================================================================== */
.what-we-do.wwd-q, .proof { container-type: inline-size; }
@media (min-width: 1024px) {
  /* ── One container, delivers to FAQ ── */
  .what-we-do.wwd-q, .how-it-works, .proof, .footer-cta, .faq {
    padding-inline: var(--container-pad);
  }
}
.what-we-do.wwd-q, .how-it-works { padding-block: var(--space-section-desktop); }
.proof { padding-block: 80px 72px; }
@media (max-width: 1024px) {
  .what-we-do.wwd-q, .how-it-works { padding-block: var(--space-section-tablet); }
  .proof { padding-block: 64px 48px; }
}
@media (max-width: 768px) {
  .what-we-do.wwd-q, .how-it-works { padding-block: var(--space-section-phone); }
  .proof { padding-block: 48px 24px; }
}
@media (min-width: 1024px) {
  /* side gutter and cap: the delivers section's own rule, so the edges match exactly (coordinator, 12 Nov) */
  .how-it-works, .proof, .footer-cta, .faq, .footer { padding-inline: var(--container-pad); }
}
.proof { padding-block: var(--space-section-desktop); }
.footer-cta { padding-block: var(--space-section-desktop); }
.faq { padding-block: var(--space-section-desktop); }
.footer { padding-top: var(--space-section-desktop); }
@media (max-width: 1024px) {
  .proof, .footer-cta, .faq { padding-block: var(--space-section-tablet); }
  .footer { padding-top: var(--space-section-tablet); }
}
@media (max-width: 768px) {
  .proof, .footer-cta, .faq { padding-block: var(--space-section-phone); }
  .footer { padding-top: var(--space-section-phone); }
}
@media (min-width: 768px) and (max-width: 768.98px) {
  /* 4, 768 px (iPad mini upright): the sections below the hero take the tablet system the hero already uses, 32 px gutters
   and 128 px between sections, as at 820 */
  .what-we-do.wwd-q, .how-it-works, .proof, .footer-cta, .faq, .footer { padding-inline: var(--gutter-tablet); }
  .what-we-do.wwd-q, .how-it-works, .proof, .footer-cta, .faq { padding-block: var(--space-section-tablet); }
  .footer { padding-top: var(--space-section-tablet); }
}

/* ==========================================================================
   TOUCH. Small links and buttons get a 44 px hit area without changing how they look.
   ========================================================================== */
@media (pointer: coarse) {
  /* Touch: small links and buttons get a 44 px hit area without changing how they look */
  .nav-logo, .notif-action, .footer-logo, .footer-col a, .footer-meta-link, a.nav-clock, body > .pow-consent button, body > .pow-consent a { position: relative; }
  .nav-logo::after, .notif-action::after, .footer-logo::after, .footer-col a::after, .footer-meta-link::after, a.nav-clock::after,
  body > .pow-consent button::after, body > .pow-consent a::after {
    content: ''; position: absolute; left: 50%; top: 50%; width: max(100%, 44px); height: 44px; transform: translate(-50%, -50%);
  }
}
