/* ============================================================
   v2.css: the 2026 rework design, loaded on every page

   Loaded AFTER styles.css, which still supplies everything shared:
   reset, skip link, language toggle, accessibility toolbar and its
   colour themes, WhatsApp float, form, before/after slider, quotes
   marquee, footer, lightbox. This file only adds the new sections
   and re-points the palette. The homepage sections come first; the
   work pages, legal pages and 404 are near the end.

   PALETTE
   The dark look is NOT written as literals on components. It is the
   existing token set (--cream, --ink, --paper ...) re-pointed at dark
   values, the same trick .band-dark uses, so every reused component
   (form, slider, quotes, footer) goes dark with no per-component
   rules. And it applies only while no accessibility colour theme is
   on: those themes define the same tokens on :root, and this block
   steps aside for them, so "high contrast" still means high contrast.

   The v2-only tokens (--v2-*) default to plain theme tokens, so under
   a colour theme the headings, the pink button and the testimonial
   accents all fall back to the theme's own colours.

   NO GRADIENTS. The template's gradient headings and gradient button
   were taken out on purpose (Sept 2026, owner's call: they read as
   generic AI styling). Colour is flat: light headings, one pink for
   actions. The only gradients left are functional fades (the bottom of
   the hero portrait, the edges of the marquee rows), not decoration.
   ============================================================ */

:root.v2 {
  --v2-bg:        var(--cream);
  --v2-fg:        var(--ink);
  --v2-fg-soft:   var(--ink-soft);
  --v2-light-bg:  var(--paper);
  --v2-light-fg:  var(--ink);
  --v2-light-line: var(--tan-soft);
  --v2-head:      var(--ink);
  --v2-cta-bg:    var(--gold-deep);
  --v2-cta-hover: var(--gold-hover);
  --v2-cta-fg:    var(--paper);
  --v2-ghost-hover: var(--tan-soft);
  --v2-desc-opacity: 1;
  --v2-svc-band: var(--tan-soft);     /* services row highlight */
  /* Testimonials. Neutral here, so a colour theme gets plain cards. */
  --v2-quote-line: var(--tan-soft);
  --v2-acc-title: var(--ink);

  --v2-ease: cubic-bezier(.25, .1, .25, 1);
  --v2-pad:  1.5rem;                 /* px-6 */
  --v2-title: clamp(3rem, 12vw, 160px);
  --vh: 100vh;
}
/* svh, where it exists, so mobile browser chrome sliding away does not
   resize anything mid-scroll. */
@supports (height: 100svh) { :root.v2 { --vh: 100svh; } }
@media (min-width: 768px) { :root.v2 { --v2-pad: 2.5rem; } }   /* md:px-10 */

:root.v2:not(.a11y-contrast):not(.a11y-invert):not(.a11y-yellow):not(.a11y-mono):not(.a11y-sepia) {
  color-scheme: dark;

  /* Existing tokens, re-pointed. Contrast on #0C0C0C: --ink 15.3:1,
     --ink-soft 7.9:1, --gold-deep 8.1:1. On --paper (#151515) all stay
     above 7:1. */
  --cream: #0C0C0C; --cream-deep: #0C0C0C; --paper: #151515;
  --ink: #D7E2EA;   --ink-soft: #9BA7B0;
  --gold: #E59BDD;  --gold-deep: #E59BDD; --gold-hover: #F2C2EC;
  --tan: #4A4E52;   --tan-soft: #2A2D30;
  --danger: #FF8A80;
  --on-media: #FFFFFF;
  --veil-rgb: 0 0 0; --handle-ring-rgb: 0 0 0; --backdrop-rgb: 0 0 0;
  --espresso: #0C0C0C; --espresso-2: #151515;
  --on-dark: #D7E2EA; --on-dark-soft: #9BA7B0; --gold-on-dark: #E59BDD; --line-on-dark: #2A2D30;

  --v2-fg:        #D7E2EA;
  --v2-light-bg:  #FFFFFF;
  --v2-light-fg:  #0C0C0C;
  --v2-light-line: rgb(12 12 12 / .15);
  --v2-head:      #D7E2EA;
  /* The site's pink: the same #E59BDD as the stat numbers and links
     (--gold-deep in this palette). It is light, so the label is dark:
     #0C0C0C on it is 9.9:1 (white would be 2.1:1). */
  --v2-cta-bg:    var(--gold-deep);
  --v2-cta-hover: var(--gold-hover);
  --v2-cta-fg:    #0C0C0C;
  --v2-ghost-hover: rgb(215 226 234 / .1);
  /* 0.6 of #0C0C0C on white is #6D6D6D, 5.2:1. Under a colour theme the
     description drops the fade and takes the theme's own text colour. */
  --v2-desc-opacity: .6;
  /* The site's pink as the services row highlight: #0C0C0C text on it is
     9.9:1, so the row stays fully readable while lit. */
  --v2-svc-band: #E59BDD;
  /* Testimonials: the site's one pink only (purple and orange were tried
     and clashed with it). Title in the pink, 9.9:1; card borders in the
     same pink at 40%, so the cards read as a set without shouting. */
  --v2-quote-line: rgb(229 155 221 / .4);
  --v2-acc-title: #E59BDD;
}

/* ─── Base ───────────────────────────────────────────────────── */
html.v2, .v2 body { background: var(--v2-bg); }
.v2 body {
  font-family: Kanit, Heebo, system-ui, sans-serif;
  color: var(--v2-fg);
  /* clip, not hidden: hidden makes body a scroll container, which breaks
     position: sticky on the work cards. */
  overflow-x: clip;
}
/* styles.css puts Fredoka on these. Kanit/Heebo everywhere here. */
.v2 :is(h1, h2, h3, .btn, .stat dd, .case__name, .quote blockquote) {
  font-family: Kanit, Heebo, system-ui, sans-serif;
}
/* The logo is black on transparent: white on the dark page. Under a colour
   theme it keeps its own black, since several of those grounds are light. */
:root.v2:not(.a11y-contrast):not(.a11y-invert):not(.a11y-yellow):not(.a11y-mono):not(.a11y-sepia) :is(.foot__brand, .h-nav__brand) img {
  filter: invert(1);
}

.h-head { color: var(--v2-head); }

.h-title {
  margin: 0;
  font-size: var(--v2-title);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -.025em;
  text-transform: uppercase;
  text-align: center;
  text-wrap: balance;
}
.h-title--ink { color: var(--v2-light-fg); }
/* The reused sections have sentence-length titles, which at 160px would
   run to four lines. Same treatment, smaller cap. */
.v2 .h-title--sm {
  font-size: clamp(2.5rem, 7vw, 96px);
  line-height: 1.05;
  margin-bottom: clamp(1rem, 2vw, 1.5rem);
}

/* ─── Buttons ────────────────────────────────────────────────── */
.h-cta {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .75rem 2rem;
  font-size: .75rem; font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; text-decoration: none;
  /* One line at normal sizes; at enlarged text the label may wrap rather
     than push the button past the screen edge. */
  max-width: 100%; text-align: center;
  color: var(--v2-cta-fg);
  background: var(--v2-cta-bg);
  border-radius: 999px;
  transition: transform .2s var(--v2-ease), background-color .2s var(--v2-ease);
}
@media (min-width: 640px) { .h-cta { padding: .875rem 2.5rem; font-size: .875rem; } }
@media (min-width: 768px) { .h-cta { padding: 1rem 3rem; font-size: 1rem; } }
@media (hover: hover) and (pointer: fine) {
  .h-cta:hover { transform: translateY(-2px); background: var(--v2-cta-hover); }
}
.h-cta:focus-visible { outline: 2px solid var(--v2-fg); outline-offset: 3px; }

/* The form's send button and the reused .btn--accent: the same flat pink. */
.v2 .btn--accent {
  --btn-bg: var(--v2-cta-bg); --btn-bd: var(--v2-cta-bg); --btn-fg: var(--v2-cta-fg);
  box-shadow: none;
  text-transform: uppercase; letter-spacing: .1em;
}
@media (hover: hover) and (pointer: fine) {
  .v2 .btn--accent:hover { --btn-bg: var(--v2-cta-hover); --btn-bd: var(--v2-cta-hover); box-shadow: none; }
}

.h-ghost {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .75rem 2rem;
  font-size: .875rem; font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; text-decoration: none;
  color: var(--v2-fg);
  border: 2px solid var(--v2-fg); border-radius: 999px;
  transition: background-color .2s var(--v2-ease);
}
@media (min-width: 640px) { .h-ghost { padding: .875rem 2.5rem; font-size: 1rem; } }
@media (hover: hover) and (pointer: fine) { .h-ghost:hover { background: var(--v2-ghost-hover); } }

/* ─── Nav ────────────────────────────────────────────────────── */
/* In the page flow, not laid over the hero: with the toolbar's text size
   raised the header wraps to more rows, and an overlaid header then sat on
   top of the name. In flow, the hero simply starts below it. */
.h-nav {
  position: relative; z-index: 30;
  padding: max(1.5rem, env(safe-area-inset-top, 0px)) var(--v2-pad) 0;
}
@media (min-width: 768px) { .h-nav { padding-top: 2rem; } }
/* Logo at the inline start (top right in Hebrew), the four links grouped in
   the middle, the language toggle at the far end. */
/* flex-wrap: at normal sizes everything fits one row (down to 320px), but
   with the toolbar's text size raised the links would push the page wider
   than the screen (WCAG 1.4.4/1.4.10); wrapping onto a second row keeps it. */
.h-nav__bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .5rem; }
/* 44px tap targets for the logo and the links: the text stays the same
   size, the hit area grows around it. */
.h-nav__brand { display: grid; place-items: center; flex: none; min-width: 44px; min-height: 44px; line-height: 0; }
.h-nav__brand img { width: 40px; height: auto; }
@media (min-width: 1024px) { .h-nav__brand img { width: 64px; } }
.h-nav__brand:focus-visible { border-radius: 50%; }
.h-nav__links { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; column-gap: clamp(.6rem, 3.2vw, 2.75rem); }
.h-nav__links a {
  color: var(--v2-fg); text-decoration: none;
  font-size: .8125rem; font-weight: 500;
  letter-spacing: .03em; text-transform: uppercase;
  white-space: nowrap;               /* "צרו קשר" stays one line */
  display: inline-flex; align-items: center; min-height: 44px;
  transition: opacity .2s var(--v2-ease);
}
/* The narrowest phones (320-359px): logo, four links and the toggle only
   just fit in one row, so everything steps down a notch. */
@media (max-width: 359px) {
  .h-nav__brand img { width: 34px; }
  .h-nav__links { gap: .45rem; }
  .h-nav__links a { font-size: .75rem; letter-spacing: 0; }
}
@media (min-width: 768px)  { .h-nav__brand img { width: 56px; } .h-nav__bar { gap: .75rem; } }
@media (min-width: 768px)  { .h-nav__links a { font-size: 1.125rem; letter-spacing: .05em; } }
@media (min-width: 1024px) { .h-nav__links a { font-size: 1.4rem; } }
@media (hover: hover) and (pointer: fine) { .h-nav__links a:hover { opacity: .7; } }
.v2 .h-nav .lang { color: var(--v2-fg); border-color: var(--tan); }

/* ─── Hero ───────────────────────────────────────────────────── */
/* Sized by its content, not the viewport: the name, then the portrait pulled
   up into the name's lower half, with the tagline bar laid over the
   portrait's faded foot. --title-fs is the name's font-size; v2.js writes
   the fitted value, the vw figures below are the no-JS starting point. */
.h-hero {
  --title-fs: 14vw;
  position: relative;
  display: flex; flex-direction: column;
  /* Both axes: on touch screens the portrait trails the scroll (v2.js), and
     this makes it sink behind the hero's bottom edge instead of sliding over
     the image strip below. */
  overflow: clip;
}

/* Gap below the header. Tuned so the name sits exactly where it did when the
   header was overlaid (80 / 72 / 68 / 84px from the top at 375 / 640 / 768 /
   1024+); on desktop the name's own line box tucks slightly under the logo. */
.h-hero__head { overflow: hidden; margin-top: .75rem; padding-inline: var(--v2-pad); }
@media (min-width: 640px)  { .h-hero__head { margin-top: .25rem; } }
@media (min-width: 768px)  { .h-hero__head { margin-top: -1.375rem; } }
@media (min-width: 1024px) { .h-hero__head { margin-top: -.375rem; } }

.h-hero__title {
  margin: 0; width: 100%;
  font-weight: 900; line-height: 1; letter-spacing: -.025em;
  text-transform: uppercase; white-space: nowrap; text-align: center;
  /* No-JS starting point, tuned to the Hebrew line. v2.js then fits the
     exact width in either language. */
  font-size: var(--title-fs);
}
:root[lang="en"] .h-hero { --title-fs: 12.5vw; }
/* inline-block so its width is the text's own width, which fitTitle reads.
   The padding keeps Heebo's black-weight descenders inside the clip box. */
.h-hero__fit { display: inline-block; padding-block: .02em .08em; }

/* The portrait: her illustrated cut-out (1140x1380, transparent), at the
   template's width steps. It sits in the flow under the name and is pulled
   up by just over half the name's height, so the top of her head lands on
   the lower half of the letters and covers them (z-index above the name).
   The height cap keeps name + figure inside one screen: a short laptop gets
   a smaller figure rather than a hero taller than the viewport. */
.h-hero__portrait {
  --pw: min(calc(100vw - 1rem), 480px);
  --ar: .8261;                       /* the image's own width / height */
  position: relative; z-index: 10;
  align-self: center;
  margin-top: calc(var(--title-fs) * -.55);
  /* v2.js scales it from the feet on touch screens (scroll parallax). */
  transform-origin: 50% 100%;
  width: min(var(--pw), calc((var(--vh) - 5rem - var(--title-fs) * .5) * var(--ar)));
}
@media (min-width: 640px)  { .h-hero__portrait { --pw: 360px; } }
@media (min-width: 768px)  { .h-hero__portrait { --pw: 440px; } }
@media (min-width: 1024px) { .h-hero__portrait { --pw: 520px; } }

/* Any [data-magnet] element (v2.js): slow ease back out, quicker follow. */
[data-magnet] { will-change: transform; transition: transform .6s ease-in-out; }
[data-magnet].is-active { transition: transform .3s ease-out; }
/* The coat is cut off flat at the bottom of the image. Fading the lowest
   quarter out melts that edge into the page, keeps the tagline and button
   (which sit over it) legible, and hides the gap the magnet opens under the
   figure when it lifts toward the cursor. */
.h-cutout img {
  width: 100%; height: auto;
  -webkit-mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 70%, transparent 100%);
}

/* From 640px up the bar is laid over the bottom of the portrait, which the
   mask above fades out. On a phone the figure spans nearly the full width,
   so the tagline would sit on the coat; there it follows the figure instead,
   tucked slightly into its faded foot. */
.h-hero__bar {
  position: relative; z-index: 20; margin-top: -2.5rem;
  /* wrap: at enlarged text sizes the button drops to its own line instead of
     being pushed off the edge. */
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 1rem;
  padding: 0 var(--v2-pad) 1.75rem;
  /* The WhatsApp and accessibility buttons are fixed in this corner
     (48px + 1rem inset); keep the tagline out from under them. */
  padding-inline-start: max(var(--v2-pad), 4.75rem);
}
@media (min-width: 640px) {
  .h-hero__bar { position: absolute; inset-inline: 0; bottom: 0; margin-top: 0; padding-bottom: 2rem; }
}
@media (min-width: 768px) { .h-hero__bar { padding-bottom: 2.5rem; } }

.h-hero__sub {
  margin: 0;
  max-width: 160px;
  color: var(--v2-fg);
  font-size: clamp(.8rem, 1.4vw, 1.5rem);
  font-weight: 300; line-height: 1.375;
  letter-spacing: .025em; text-transform: uppercase;
}
@media (min-width: 640px)  { .h-hero__sub { max-width: 180px; } }
@media (min-width: 768px)  { .h-hero__sub { max-width: 210px; } }
@media (min-width: 1024px) { .h-hero__sub { max-width: 260px; } }

/* Page-load entrance. Pure CSS, so nothing above the fold waits on JS or
   can be left invisible by a script that failed. `both` holds the start
   frame through each delay. */
@keyframes v2-in {
  from { opacity: 0; transform: translate(var(--fx, 0), var(--fy, 30px)); }
  to   { opacity: 1; transform: none; }
}
.fx-in { animation: v2-in .7s var(--v2-ease) both; }
.fx-in--nav      { --fy: -20px; animation-delay: 0s; }
.fx-in--title    { --fy: 40px;  animation-delay: .15s; }
.fx-in--sub      { --fy: 20px;  animation-delay: .35s; }
.fx-in--cta      { --fy: 20px;  animation-delay: .5s; }
.fx-in--portrait { --fy: 30px;  animation-delay: .6s; }

/* ─── Marquee ────────────────────────────────────────────────── */
.h-marquee {
  --mh: clamp(190px, 22vw, 300px);
  display: flex; flex-direction: column; gap: .75rem;
  padding: 6rem 0 2.5rem;
  overflow: hidden;
}
@media (min-width: 640px) { .h-marquee { padding-top: 8rem; } }
@media (min-width: 768px) { .h-marquee { padding-top: 10rem; } }
/* Forced ltr so each track anchors its LEFT edge and the translate maths is
   the same in both languages. */
.h-marquee__row { direction: ltr; }
.h-marquee__track { display: flex; gap: .75rem; width: max-content; will-change: transform; }
/* One height, each photo's own width (from its width/height attributes),
   so portrait, landscape and tall phone shots all show whole. */
.h-marquee img {
  flex: none; height: var(--mh); width: auto;
  object-fit: cover; border-radius: 1rem; background: #151515;
}

/* ─── About ──────────────────────────────────────────────────── */
.h-about {
  position: relative;
  min-height: 100vh; min-height: 100svh;
  display: flex; align-items: center; justify-content: center;
  padding: 5rem 1.25rem;
  overflow: clip;
}
@media (min-width: 640px) { .h-about { padding-inline: 2rem; } }
@media (min-width: 768px) { .h-about { padding-inline: 2.5rem; } }

.h-about__deco {
  position: absolute; z-index: 0;
  width: auto;                        /* width follows each photo's own shape */
  border-radius: 1rem;
  box-shadow: 0 20px 50px rgb(0 0 0 / .5);
  /* The fade-in moves `transform`, so the tilt lives on `rotate`. */
}
@media (min-width: 640px)  { .h-about__deco { border-radius: 1.25rem; } }
@media (min-width: 768px)  { .h-about__deco { border-radius: 1.5rem; } }
/* Desktop: as big as the space allows, sized by HEIGHT so tall and wide
   photos read as one set. Three caps, smallest wins:
   - 40vh, so the two photos on one side never meet (4% + 8% insets + 2x40%);
   - the room beside the ~560px text column, less the inset and a margin,
     so the widest photo (about-05, ~0.86 wide-to-tall) never reaches the
     text even tilted;
   - 420px on very large screens.
   From 1280px only: below that the side room is too narrow, and the photos
   move into bands above and below the text instead (see below). */
@media (min-width: 1280px) {
  .h-about__deco {
    width: auto; border-radius: 1.75rem;
    height: min(40vh, calc((100vw - 560px) / 2 - 4vw - 1rem), 420px);
  }
}
.h-about__deco--tl { top: 4%;    left: 1%;  rotate: -8deg; }
.h-about__deco--bl { bottom: 8%; left: 3%;  rotate: 6deg; }
.h-about__deco--tr { top: 4%;    right: 1%; rotate: 7deg; }
.h-about__deco--br { bottom: 8%; right: 3%; rotate: -6deg; }
@media (min-width: 640px) {
  .h-about__deco--tl { left: 2%; }  .h-about__deco--bl { left: 6%; }
  .h-about__deco--tr { right: 2%; } .h-about__deco--br { right: 6%; }
}
@media (min-width: 768px) {
  .h-about__deco--tl { left: 4%; }  .h-about__deco--bl { left: 4%; }
  .h-about__deco--tr { right: 4%; } .h-about__deco--br { right: 4%; }
}
/* Below 1280px there is no room beside the text, so the photos get their own
   bands above and below it instead: the section's padding reserves each band,
   and the photos are sized by HEIGHT so tall and wide ones read as one set.
   Offsets are fixed rem, not %, so a taller section (English, 200% text)
   can never push a photo into the text. Each padding = offset + photo height
   + the extra height the tilt adds + a gap. */
@media (max-width: 1279px) {
  .h-about { --deco-t: 230px; --deco-b: 190px; padding-top: 18rem; padding-bottom: 15rem; }
  .h-about__deco--tl, .h-about__deco--tr { height: var(--deco-t); top: 1.25rem; }
  /* In from the edge far enough that the tilted corner is not clipped. */
  .h-about__deco--tl { left: 5%; }  .h-about__deco--tr { right: 5%; }
  .h-about__deco--bl, .h-about__deco--br { height: var(--deco-b); top: auto; bottom: 1.5rem; }
}
/* The narrowest phones (under 360px): one notch smaller, or the two bottom
   photos meet. */
@media (max-width: 359px) {
  .h-about { --deco-t: 190px; --deco-b: 150px; padding-top: 15.5rem; padding-bottom: 12.5rem; }
}
@media (min-width: 640px) and (max-width: 1279px) {
  .h-about { --deco-t: 300px; --deco-b: 250px; padding-top: 22.5rem; padding-bottom: 20rem; }
  .h-about__deco--tl, .h-about__deco--tr { top: 1.5rem; }
  .h-about__deco--bl, .h-about__deco--br { bottom: 2rem; }
}

.h-about__inner {
  position: relative; z-index: 1;
  display: flex; flex-direction: column; align-items: center;
  gap: 4rem;
}
@media (min-width: 640px) { .h-about__inner { gap: 5rem; } }
@media (min-width: 768px) { .h-about__inner { gap: 6rem; } }
.h-about__text { display: flex; flex-direction: column; align-items: center; gap: 2.5rem; }
@media (min-width: 640px) { .h-about__text { gap: 3.5rem; } }
@media (min-width: 768px) { .h-about__text { gap: 4rem; } }

.h-about__p {
  margin: 0; max-width: 560px;
  color: var(--v2-fg);
  font-size: clamp(1rem, 2vw, 1.35rem); font-weight: 500; line-height: 1.625;
  text-align: center;
}

/* Scroll reveal. The per-character copy is built by v2.js; each character
   carries --i, the paragraph carries --n and a live --p (0..1). Opacity is
   computed here, so a scroll frame writes ONE custom property, not 360
   inline styles. Char i ramps 0.2 -> 1 while --p crosses i/n .. (i+1)/n. */
.rv { display: block; }
.rv__w { display: inline-block; white-space: nowrap; }
.rv__c { opacity: clamp(.2, calc(.2 + (var(--p, 1) * var(--n, 1) - var(--i, 0)) * .8), 1); }

/* ─── Services ───────────────────────────────────────────────── */
.h-services {
  background: var(--v2-light-bg); color: var(--v2-light-fg);
  border-radius: 40px 40px 0 0;
  padding: 5rem 1.25rem;
}
@media (min-width: 640px) { .h-services { border-radius: 50px 50px 0 0; padding: 6rem 2rem; } }
@media (min-width: 768px) { .h-services { border-radius: 60px 60px 0 0; padding: 8rem 2.5rem; } }
.h-services .h-title { margin-bottom: 4rem; }
@media (min-width: 640px) { .h-services .h-title { margin-bottom: 5rem; } }
@media (min-width: 768px) { .h-services .h-title { margin-bottom: 7rem; } }
.h-services :focus-visible { outline-color: var(--v2-light-fg); }

.svc { list-style: none; margin: 0 auto; padding: 0; max-width: 64rem; }
.svc__item {
  position: relative; isolation: isolate;
  display: flex; align-items: center; gap: 1.5rem;
  padding: 2rem clamp(.75rem, 2vw, 2rem);
  border-top: 1px solid var(--v2-light-line);
}
.svc__item:last-child { border-bottom: 1px solid var(--v2-light-line); }
@media (min-width: 640px) { .svc__item { padding-block: 2.5rem; gap: 2.5rem; } }
@media (min-width: 768px) { .svc__item { padding-block: 3rem; gap: 3.5rem; } }
.svc__num {
  flex: none;
  font-size: clamp(3rem, 10vw, 140px); font-weight: 900; line-height: 1;
  letter-spacing: -.03em;
  color: var(--v2-light-fg);
  font-variant-numeric: tabular-nums;
  transition: color .7s var(--v2-ease), transform .45s var(--v2-ease);
}
.svc__body { min-width: 0; }
.svc__name {
  margin: 0 0 .5rem;
  font-size: clamp(1rem, 2.2vw, 2.1rem); font-weight: 500; line-height: 1.2;
  text-transform: uppercase;
}
.svc__desc {
  margin: 0; max-width: 42rem;
  font-size: clamp(.85rem, 1.6vw, 1.25rem); font-weight: 300; line-height: 1.625;
  opacity: var(--v2-desc-opacity);
}

/* Outlined numbers that fill in solid as their row scrolls into view.
   v2.js adds .svc--outline only when motion is allowed, and .is-filled per
   row, so with no JS or reduced motion the numbers are simply solid. */
.svc--outline .svc__item:not(.is-filled) .svc__num {
  color: transparent;
  -webkit-text-stroke: 1.5px var(--v2-light-fg);
}
@media (min-width: 768px) {
  .svc--outline .svc__item:not(.is-filled) .svc__num { -webkit-text-stroke-width: 2px; }
}

/* Rows light up: a solid pink band sweeps in from the reading start and the
   number nudges toward the text. Hover with a mouse; on touch screens v2.js
   lights (.is-lit) the one row nearest the middle of the screen. */
.svc__item::before {
  content: ""; position: absolute; inset: .4rem 0; z-index: -1;
  border-radius: 24px;
  background: var(--v2-svc-band);
  transform: scaleX(0);
  transform-origin: calc(50% + 50% * var(--flip)) 50%;   /* inline start */
  transition: transform .45s var(--v2-ease);
}
.svc__item.is-lit::before { transform: scaleX(1); }
.svc__item.is-lit .svc__num { transform: translateX(calc(-.5rem * var(--flip))); }
/* :hover only where there is a real hovering pointer. Touch browsers apply
   :hover on tap and iOS keeps it until you tap elsewhere, which left the
   first row touched stuck pink on phones. */
@media (hover: hover) and (pointer: fine) {
  .svc__item:hover::before { transform: scaleX(1); }
  .svc__item:hover .svc__num { transform: translateX(calc(-.5rem * var(--flip))); }
}

/* ─── Work: stacking cards ───────────────────────────────────── */
/* Follows the about section on the same dark ground, so it needs no
   rounded lip of its own; the white services section after it has one. */
.h-work { position: relative; padding: 3rem 1.25rem 2rem; }
@media (min-width: 640px) { .h-work { padding-inline: 2rem; } }
@media (min-width: 768px) { .h-work { padding: 4rem 2.5rem 3rem; } }
.h-work > .h-title { margin-bottom: 3rem; }
@media (min-width: 768px) { .h-work > .h-title { margin-bottom: 4rem; } }

/* The SLOT is what sticks, not the card: sticky only holds within the
   parent, so it has to be a direct child of the full-height list for the
   cards to pile up on each other. Each sits 28px lower than the last so
   the edges of the earlier cards stay visible.

   Every slot, the last included, is tall enough to scroll its card all
   the way to its stacked spot. (The last one used to be only as tall as
   its card, so the list ended the moment card 03 arrived and the whole
   stack scrolled off with 03 still short of its place.) Each slot is 28px
   shorter than the one before, which lines all their bottoms up, so the
   three cards let go at the same moment and leave as one stack instead of
   01 sliding out from under the others first. The ::after spacer is a
   short hold with all three stacked before they go. */
.stack { max-width: 1400px; margin-inline: auto; }
.stack__slot {
  --stick: 6rem;
  --room: 70;                        /* scroll room per card, in vh */
  position: sticky; top: calc(var(--stick) + var(--i, 0) * 28px);
  height: calc(var(--room) * 1vh + (2 - var(--i, 0)) * 28px);
  height: calc(var(--room) * 1svh + (2 - var(--i, 0)) * 28px);
}
.stack__slot:nth-child(2) { --i: 1; }
.stack__slot:nth-child(3) { --i: 2; }
.stack::after { content: ""; display: block; height: 10vh; }
/* Phone cards are short (~430px), so a desktop-sized room left a ~430px
   empty band after the stack left. 70vh still clears the tallest phone
   card; bigger screens get the full 85vh and a longer hold. */
@media (min-width: 768px) {
  .stack__slot { --room: 85; }
  .stack::after { height: 20vh; }
}
@media (min-width: 768px) { .stack__slot { --stick: 8rem; } }

.pcard {
  transform-origin: top center;
  background: var(--v2-bg);
  border: 2px solid var(--v2-fg);
  border-radius: 40px;
  padding: 1rem;
  will-change: transform;
}
@media (min-width: 640px) { .pcard { border-radius: 50px; padding: 1.5rem; } }
@media (min-width: 768px) { .pcard { border-radius: 60px; padding: 2rem; } }

.pcard__head {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: .5rem 1.25rem;
  padding-inline: .5rem;
  margin-bottom: 1rem;
}
@media (min-width: 768px) { .pcard__head { gap: .75rem 2rem; margin-bottom: 1.5rem; } }
.pcard__num {
  flex: none;
  font-size: clamp(3rem, min(10vw, 15vh), 140px); font-weight: 900; line-height: .9;
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
}
.pcard__meta { flex: 1 1 10rem; min-width: 0; }
.pcard__cat {
  margin: 0 0 .15rem;
  color: var(--v2-fg-soft);
  font-size: clamp(.75rem, 1.1vw, 1rem); letter-spacing: .1em; text-transform: uppercase;
}
.pcard__name {
  margin: 0; color: var(--v2-fg);
  font-size: clamp(1.15rem, 2.4vw, 2.2rem); font-weight: 500; line-height: 1.15;
  text-transform: uppercase;
}
@media (max-width: 639px) { .pcard__head .h-ghost { width: 100%; } }

/* Every card's media area is the SAME size, or a shorter card stacked on a
   taller one would leave the one underneath poking out below it. The area
   (.pcard__media) is full width at the widest set's aspect, capped by the
   height the stuck card can spare (--reserve covers the rest of the card).
   Inside it, each card's row of clips (.pcard__row) is scaled to fit whole
   and centred: tiles are sized by flex-grow = the clip's own aspect
   (16/9 = 1.7778, 9/16 = .5625) and the row's --ratio is their sum, so
   nothing is cropped. Container query units need Safari 16 / Chrome 105;
   older browsers get a full-width row, which is still uncropped. */
.pcard__media {
  --reserve: 26rem;
  --box: 1.125;                      /* widest set on phones: two reels */
  container-type: size;
  width: 100%;
  aspect-ratio: var(--box);
  max-height: calc(var(--vh) - var(--reserve));
  display: grid; place-items: center;
}
.pcard__row {
  display: flex; gap: .75rem;
  width: 100%;
  width: min(100cqw, 100cqh * var(--ratio));
  aspect-ratio: var(--ratio);
}
.tile {
  flex: 1 1 0; min-width: 0; margin: 0;
  overflow: hidden; background: #151515;
  border-radius: 28px;
}
@media (min-width: 640px) { .tile { border-radius: 40px; } }
@media (min-width: 1024px) { .tile { border-radius: 50px; } }
.tile--h { flex-grow: 1.7778; }
.tile--v { flex-grow: .5625; }
.tile video { width: 100%; height: 100%; object-fit: cover; }

/* Speaker button on clips with sound (added by app.js). Inset grows
   with the tile's corner radius so it never sits in the curve. Pink
   when the clip is audible, the site's one accent. */
.tile { position: relative; }
.tile__sound {
  position: absolute; inset-block-end: 12px; inset-inline-end: 12px;
  width: 44px; height: 44px; padding: 0;
  display: grid; place-items: center;
  border: 0; border-radius: 999px; cursor: pointer;
  background: rgba(12, 12, 12, .6); color: #fff;
  transition: background-color .2s, color .2s;
}
.tile__sound svg {
  width: 22px; height: 22px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
.tile__sound svg path:first-child { fill: currentColor; }
.tile__sound:hover { background: rgba(12, 12, 12, .8); }
.tile__sound[aria-pressed="true"] { background: #E59BDD; color: #0C0C0C; }
.tile__sound:focus-visible { outline: 3px solid #E59BDD; outline-offset: 3px; }
@media (min-width: 640px) { .tile__sound { inset-block-end: 18px; inset-inline-end: 18px; } }
@media (min-width: 1024px) { .tile__sound { inset-block-end: 22px; inset-inline-end: 22px; } }

/* < 640: the first clip or two. 640+: the --md clips join. */
.tile--md { display: none; }
.pcard__media--three { --ratio: 1.125; }   /* 2 reels */
.pcard__media--wide  { --ratio: 1.7778; }  /* 1 landscape */
.pcard__media--two   { --ratio: 1.125; }   /* 2 reels */
@media (min-width: 640px) {
  .tile--md { display: block; }
  .pcard__media { --box: 1.6875; }          /* widest set: three reels */
  .pcard__media--three { --ratio: 1.6875; } /* 3 reels */
  .pcard__media--wide  { --ratio: 2.3403; } /* landscape + reel */
}

/* Desktop: the number, title and button move into a column beside the
   clips, which get the card's full height. */
@media (min-width: 1024px) {
  .pcard {
    display: grid; grid-template-columns: minmax(15rem, 22rem) 1fr;
    align-items: stretch; gap: 2rem;
  }
  .pcard__head {
    flex-direction: column; flex-wrap: nowrap; align-items: flex-start;
    margin-bottom: 0; padding-block: .5rem;
  }
  .pcard__meta { flex: none; }
  .pcard__head .h-ghost { margin-top: auto; }
  .pcard__media { --reserve: 17rem; }
}

/* ─── Reused sections, re-seated on the dark page ────────────── */
/* Whatever follows the white services section rises over its foot with a
   rounded dark lip: the treatment the work section had when it came
   straight after services. */
.v2 .h-services + .section {
  position: relative; z-index: 1;
  background: var(--v2-bg);
  border-radius: 40px 40px 0 0;
  margin-top: -2.5rem;
}
@media (min-width: 640px) { .v2 .h-services + .section { border-radius: 50px 50px 0 0; margin-top: -3rem; } }
@media (min-width: 768px) { .v2 .h-services + .section { border-radius: 60px 60px 0 0; margin-top: -3.5rem; } }
.v2 .section { padding-block: clamp(5rem, 9vw, 8rem); }
/* The contact title shares its row with the form, so it gets half the
   width; at the full --sm size it broke into five lines. */
.v2 .contact .h-title--sm { font-size: clamp(2.25rem, 4.6vw, 64px); text-align: start; }
.v2 .results .section__lead,
.v2 .voices .section__title { text-align: center; margin-inline: auto; }
.v2 .results .section__lead { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.v2 .voices .section__title { margin-bottom: clamp(2.5rem, 5vw, 4rem); }
.v2 .case { border-radius: 32px; }
/* ─── Testimonials ───────────────────────────────────────────── */
/* Pink title, pink-edged cards: the same pink as the buttons and stats. */
.v2 .voices .section__title { color: var(--v2-acc-title); }
.v2 .quote {
  border-radius: 24px;
  border: 1px solid var(--v2-quote-line);
  background: var(--paper);
}
.v2 .form { border-radius: 32px; }
.v2 .foot { border-top-color: var(--tan-soft); }

/* ─── Other pages: shared header ─────────────────────────────── */
/* In the flow rather than laid over a full-screen hero. */
.h-nav--page { position: relative; }

/* ─── Work pages (business / events / abroad) ────────────────── */
.v2 .page-hero { padding-block: clamp(1.5rem, 4vw, 3rem) clamp(3rem, 6vw, 5rem); }
.v2 .page-hero__title {
  font-size: clamp(2.5rem, 6vw, 88px); font-weight: 900; line-height: 1.02;
  letter-spacing: -.025em; text-transform: uppercase;
  margin-bottom: clamp(1rem, 2vw, 1.5rem);
}
.v2 .page-hero__text { font-weight: 300; line-height: 1.6; }
.v2 .page-hero__media .reel {
  border-radius: clamp(1.75rem, 3vw, 2.5rem);
  border: 0;
  box-shadow: 0 30px 80px rgb(0 0 0 / .55);
}
.v2 .back { text-transform: uppercase; letter-spacing: .05em; font-size: .85rem; }

/* One ground colour top to bottom, as on the homepage: the old site's
   banding (.band-paper) would read here as a slightly-off grey strip. */
.v2 .band-paper { background: none; }
.v2 #videos { padding-block: clamp(3rem, 7vw, 6rem); }
.v2 #videos .section__title,
.v2 #videos .section__lead { text-align: center; margin-inline: auto; }
.v2 .ytcard {
  border: 0; border-radius: clamp(1.25rem, 2.5vw, 2rem);
  background: #151515;
  box-shadow: 0 16px 40px rgb(0 0 0 / .45);
}
@media (hover: hover) and (pointer: fine) {
  .v2 .ytcard:hover { box-shadow: 0 24px 56px rgb(0 0 0 / .6); }
}
/* The play button takes the CTA pink, so the one colourful thing on a card
   is the thing to press. */
.v2 .ytcard__play {
  width: 58px; height: 58px; border: 0;
  background: var(--v2-cta-bg);
  box-shadow: 0 6px 20px rgb(0 0 0 / .45);
}
.v2 .ytcard__play svg { fill: var(--v2-cta-fg); }
@media (hover: hover) and (pointer: fine) {
  .v2 .ytcard:hover .ytcard__play { background: var(--v2-cta-hover); }
}

/* Closing band: the work cards' outlined, heavily rounded frame. */
.v2 .cta-band { background: none; padding-block: clamp(1rem, 3vw, 2rem) clamp(5rem, 9vw, 8rem); }
.v2 .cta-band__inner {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 1.75rem;
  border: 2px solid var(--v2-fg);
  border-radius: 40px;
  padding: clamp(2.5rem, 6vw, 4.5rem) clamp(1.25rem, 5vw, 4rem);
}
@media (min-width: 640px) { .v2 .cta-band__inner { border-radius: 50px; } }
@media (min-width: 768px) { .v2 .cta-band__inner { border-radius: 60px; } }
.v2 .cta-band h2 {
  max-width: 20ch; margin-inline: auto;
  font-size: clamp(2rem, 5vw, 64px); font-weight: 900; line-height: 1.05;
  letter-spacing: -.02em; text-wrap: balance;
  color: var(--v2-head);
}
.v2 .cta-band p { margin-inline: auto; font-weight: 300; }

/* ─── Legal pages and 404 ─────────────────────────────────────── */
.v2 .legal { padding-block: clamp(1.5rem, 4vw, 3rem) clamp(5rem, 10vw, 8rem); }
.v2 .legal .page-hero__title { font-size: clamp(2.5rem, 7vw, 96px); }
.v2 .legal__body { font-weight: 300; }
.v2 .legal__body a { color: var(--gold-deep); }
.v2 .legal__body strong { color: var(--v2-fg); font-weight: 500; }
.v2 .legal .hero__actions { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; }

/* ─── Scroll fade-ins ────────────────────────────────────────── */
/* Only armed once v2.js has run and confirmed motion is allowed (it adds
   .fx-on), so with no JS nothing is ever hidden. v2.js marks whatever is
   already on screen as .is-in BEFORE arming, so nothing visible blinks. */
.fx-on [data-fade] {
  transition:
    opacity var(--dur, .7s) var(--v2-ease) var(--delay, 0s),
    transform var(--dur, .7s) var(--v2-ease) var(--delay, 0s);
}
.fx-on [data-fade]:not(.is-in) {
  opacity: 0;
  transform: translate(var(--fx, 0), var(--fy, 30px));
}

/* ─── Stillness ──────────────────────────────────────────────── */
/* Reduced motion, from the OS or from the toolbar's "stop animations".
   v2.js also stops the scroll-driven pieces; these cover the CSS side. */
@media (prefers-reduced-motion: reduce) {
  .fx-in { animation: none; }
  [data-magnet], .h-cta { transition: none; }
  .svc__num, .svc__item::before { transition: none; }
}
:root.a11y-motion-off .fx-in { animation: none; }
:root.a11y-motion-off [data-magnet],
:root.a11y-motion-off .h-cta { transition: none; }
:root.a11y-motion-off .rv__c { opacity: 1; }
/* Pseudo-elements can't go inside :is(), hence the separate ::before line. */
:root.a11y-motion-off .svc__num,
:root.a11y-motion-off .svc__item::before { transition: none; }

/* ─── Landscape phones ───────────────────────────────────────── */
/* 740x360: no height for the portrait under the name, or for a sticky card
   stack. The portrait is dropped, the tagline bar goes back into the flow
   under the name, and the cards simply scroll. */
@media (orientation: landscape) and (max-height: 520px) {
  .h-hero__portrait { display: none; }
  .h-hero__bar { position: relative; margin-top: 2rem; }
  .stack__slot { position: static; height: auto; margin-bottom: 1.5rem; }
  .stack::after { display: none; }
  .pcard__media { max-height: none; }
}
