/* ============================================================
   KORA — native rebuild v2 (matched to video reference)
   HTML/CSS/JS, no Framer. GSAP ScrollTrigger + Lenis.
   ============================================================ */

/* discrete static weights (matches the original's font delivery — not a
   single variable-axis file, which rendered mid-weights too heavy) */
@font-face { font-family: "Manrope"; src: url("../assets/fonts/manrope-latin-300-normal.woff2") format("woff2"); font-weight: 300; font-style: normal; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("../assets/fonts/manrope-latin-400-normal.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("../assets/fonts/manrope-latin-500-normal.woff2") format("woff2"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("../assets/fonts/manrope-latin-600-normal.woff2") format("woff2"); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("../assets/fonts/manrope-latin-700-normal.woff2") format("woff2"); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: "Manrope"; src: url("../assets/fonts/manrope-latin-800-normal.woff2") format("woff2"); font-weight: 800; font-style: normal; font-display: swap; }

/* Metric-matched fallback. font-display: swap means the browser paints in a
   fallback face first and reflows when Manrope arrives; that reflow used to be
   invisible on the homepage because the hero was still hidden behind the JS
   load animation. Now that the opening is CSS and the hero paints immediately,
   the swap became a visible layout shift (CLS 0.005 -> 0.033).

   The overrides make the fallback occupy the same space as Manrope, so the
   swap is a change of shape, not of geometry:
     size-adjust    Manrope is ~5% wider than Arial at the same px size
                    (measured: 2455.05 vs 2338.43 for a 100px sample string)
     ascent/descent Manrope's own hhea metrics, 2132/-600 on a 2000 upm,
                    divided by the size-adjust as the spec requires
   Three local() sources cover the three desktop platforms without a download:
   Arial (Windows), Helvetica (macOS), Liberation Sans (Linux, metrically
   identical to Arial). If none resolve the face is simply skipped and the
   stack falls through to ui-sans-serif as before. */
@font-face {
  font-family: "Manrope Fallback";
  src: local("Arial"), local("Helvetica"), local("Liberation Sans");
  size-adjust: 105%;
  ascent-override: 101.5%;
  descent-override: 28.6%;
  line-gap-override: 0%;
}

:root {
  /* Accent. Back to the original Kora green after the purple trials
     (#5F5DC3 / #8F8DFF / #A1A0FF). Relative luminance 0.44: small accent text
     on the dark sections lands at 7.2:1, dark text on an accent fill at 7.3:1,
     and cream on an accent fill at 2.15:1 — the one weak spot, inherited
     from the template as-is. No per-surface variants. */
  --green: #5dc39b;
  --green-soft: #a9dcc5;
  --cream: #fffffa;
  --paper: #fcfcfa;
  --beige: #f0f0e6;
  --beige-2: #f5f5e9; /* exact shell/panel tone from the original */
  --dark: #242424;
  --ink: #0d0d0d;
  --gray: #616161;
  --gray-2: #9a9a96;
  --gray-ink: #6f6f6b;   /* same hue, passes 4.5:1 on --beige-2 for small text */
  --line: #e6e6e2;
  --skeleton: #e7e7df; /* neutral stand-in while an image is still loading */
  --w75: rgba(255, 255, 250, 0.78);
  --w45: rgba(255, 255, 250, 0.45);

  --font: "Manrope", "Manrope Fallback", ui-sans-serif, system-ui, sans-serif;
  --container: min(100rem, 84vw);
  --card-w: min(120rem, 98.4vw);
  --edge: max(0.625rem, calc((100vw - var(--card-w)) / 2));
  /* hero stage frame — fixed px like the original */
  --stage-edge: 20px;
  --stage-r: 40px;
  --r: 1.5rem;
  --r-s: 0.875rem;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* sits between the section headline scale (--h-sec) and the big display
     scale (--h-mega): clearly larger than a section title, a step under the
     "Testimonials" display size. */
  --h-hero: clamp(2.9375rem, 4.4vw, 5.75rem);
  --h-sec: clamp(2.375rem, 3.4vw, 4.25rem);
  --h-mega: clamp(3.5rem, 5.6vw, 7.25rem);
  --h-mid: clamp(1.5rem, 2vw, 2.375rem);
  --h-card: clamp(1.3125rem, 1.5vw, 1.8125rem);

  /* Subpage scale. These four clamps and the section padding were written out
     verbatim in about/cases/contact/insight/insights.css, in fixed px. They are
     now named, and in rem, so the subpage scale rides the same fluid root as
     the home page instead of standing still while the home page grows. The two
     h2 scales that used to differ only in their floor (44 vs 40) are one. */
  --sec-pad: clamp(5rem, 8vw, 8.75rem);     /* section top/bottom rhythm */
  --h-page: clamp(3.5rem, 7.8vw, 7.5rem);   /* subpage hero H1 */
  --h-page-2: clamp(2.75rem, 4.2vw, 5rem);  /* subpage section H2 */
  --t-lead: clamp(1.25rem, 2vw, 1.875rem);  /* hero sub / intro lead */
  --t-lead-2: clamp(1.375rem, 2vw, 1.875rem); /* longer-form lead inside a card */
}

*, *::before, *::after { box-sizing: border-box; }

/* Root scale: 1rem = 16px at 1920w, grows proportionally on 2K/4K,
   shrinks on smaller screens (min 11px), fixed on mobile */
html { font-size: clamp(11px, 0.8333vw, 30px); }
/* Android Chrome "font boosting" inflates text in blocks it deems wide,
   which was blowing the phone hero up to one word per line and wrapping the
   CTA buttons — the layout is authored responsive, so boosting is noise. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
@media (max-width: 900px) { html { font-size: 14px; } :root { --stage-edge: 10px; --stage-r: 20px; } }

html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
body {
  margin: 0; font-family: var(--font);
  font-size: 1rem; line-height: 1.55; color: var(--dark);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
img { display: block; max-width: 100%; height: auto; }

/* Screen-reader-only: keeps a heading in the document outline without drawing it.
   Used where a section's visible title is styled type rather than a heading tag. */
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
a { color: inherit; text-decoration: none; }
button { font: inherit; background: none; border: 0; cursor: pointer; color: inherit; padding: 0; }
ul { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, p, figure, blockquote { margin: 0; }

/* ---------- line breaking ----------
   Display type must never drop a single word onto a line of its own — at
   these sizes a hanging last word reads as a layout bug, not as typography.
   balance is the tool that actually does it: this Chromium reports support
   for text-wrap: pretty but still breaks the orphan off (measured, not
   assumed), so pretty is not relied on anywhere.
   Scope is headings plus the few lead paragraphs set large enough for the
   same problem to show; body copy keeps its natural ragged edge. */
h1, h2, h3, h4,
.lead, .r-sub, .results-intro { text-wrap: balance; }

.container { width: var(--container); margin-inline: auto; }
.label { font-size: 0.8125rem; font-weight: 600; letter-spacing: -0.01em; }

/* two-tone headings */
.tt { color: var(--dark); }
.tt em { font-style: normal; color: var(--gray-2); }

/* kora logo lockup */
.logo { display: inline-flex; align-items: center; gap: 0.4375rem; font-weight: 700; letter-spacing: -0.03em; }
.logo .mark { width: 1.2em; height: 1.2em; color: var(--green); flex: none; }
.logo sup { font-size: 0.45em; font-weight: 600; letter-spacing: 0; transform: translateY(-0.2em); }

/* stars */
.stars { color: var(--green); font-size: 0.9375rem; letter-spacing: 0.125rem; }

/* ============ BUTTONS ============ */
.btn {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center; gap: 0.625rem;
  border-radius: 6.25rem; padding: 0.8125rem 1.5rem; min-height: 3.25rem;
  font-size: 1rem; font-weight: 600; letter-spacing: -0.02em;
  transition: transform 0.4s var(--ease-spring), color 0.25s ease 0.12s, background-color 0.01s linear 0s;
}
/* once the flood has covered the button, silently swap the real background
   to the fill colour — kills the dark antialiasing hairlines at the edges.
   On mouse-leave the swap is instant (while the fill still covers all). */
.btn:hover { transform: translateY(-0.125rem); transition: transform 0.4s var(--ease-spring), color 0.25s ease 0.12s, background-color 0.01s linear 0.38s; }
.btn--dark:hover, .btn--green:not(.btn--vc):hover { background-color: var(--cream); }
.btn--green { background: var(--green); color: var(--cream); }
.btn--dark { background: var(--dark); color: var(--cream); }
.btn--ghost { color: var(--cream); }
.btn--wide { width: 100%; border-radius: 0.875rem; padding: 1rem; }
.btn .dot { display: none; }

/* liquid fill: the dot expands into a blob that floods the button */
.btn .bt, .btn svg { position: relative; z-index: 2; }
/* the dot IS the flood: a circle that simply scales up until it covers
   the button (clipped by the pill's overflow) */
.btn .fill {
  position: absolute; z-index: 1; right: 1.125rem; top: 50%;
  width: 0.5rem; height: 0.5rem; margin-top: -0.25rem; border-radius: 50%;
  pointer-events: none;
}
/* the flood is a PRE-SIZED circle (not the dot scaled 340×): small GPU
   layer → never degrades to a snap. --flood is set per button by
   shared.js (≈2.3× button width) so the edge visibly sweeps across the
   whole button for the full 0.65s instead of covering it instantly */
.btn .fill::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: var(--flood, 30rem); height: var(--flood, 30rem); border-radius: 50%;
  background: inherit;
  transform: translate(-50%, -50%) scale(0);
  transition: transform 0.65s var(--ease);
}
.btn:hover .fill::before { transform: translate(-50%, -50%) scale(1); }
/* label flips: old line exits up with a tilt, new one rotates in from below.
   .bt is its own overflow mask so the waiting clone never peeks out */
.btn .bt { position: relative; display: inline-block; overflow: hidden; padding: 0.12em 0.2em; margin: -0.12em -0.2em; }
.btn .bt .t1 { display: inline-block; transform-origin: 100% 50%; transition: transform 0.45s var(--ease-spring); }
.btn .bt .t2 { position: absolute; inset: 0.12em 0.2em; transform-origin: 100% 50%; transform: translateY(170%) rotate(-16deg); transition: transform 0.45s var(--ease-spring); }
.btn:hover .bt .t1 { transform: translateY(-200%) rotate(10deg); }
.btn:hover .bt .t2 { transform: translateY(0) rotate(0); }
/* room for the dot on solid buttons so the label never collides with it */
.btn--green:not(.btn--wide), .btn--dark:not(.btn--wide) { padding-right: 2.75rem; }
/* small green dot re-appears on the flooded (cream) button */
.btn::after {
  content: ""; position: absolute; z-index: 2;
  right: 1.125rem; top: 50%; width: 0.5rem; height: 0.5rem;
  margin-top: -0.25rem; border-radius: 50%; background: var(--green);
  opacity: 0; transform: scale(0.4);
  transition: opacity 0.18s ease 0.2s, transform 0.35s var(--ease-spring) 0.2s;
  pointer-events: none;
}
.btn:hover::after { opacity: 1; transform: scale(1); }
/* ghost buttons: no flood — a green circle springs up behind the arrow */
.btn--ghost .fill { display: none; }
.btn--ghost::after {
  z-index: 1; /* under the arrow (svg sits at z-index 2) */
  right: calc(1.5rem + 8px - 0.775em);
  width: 1.55em; height: 1.55em; margin-top: -0.775em;
  opacity: 1; transform: scale(0);
  transition: transform 0.35s var(--ease-spring);
}
.btn--ghost:hover::after { transform: scale(1); }
.btn--ghost:hover { color: var(--cream); } /* text stays light, no flood */
.btn--dark .fill, .btn--green .fill { background: var(--cream); }
.btn--dark:hover, .btn--green:hover { color: var(--dark); }
.btn--ghost .fill { background: rgba(255,255,250,0.16); }
.plan-detail__top .btn:hover { color: var(--cream); }
.plan-detail__top .btn .fill { background: var(--dark); }

/* ============ NAV ============ */
/* fixed px — the original does not scale the nav on wide screens */
.nav { position: fixed; top: 30px; left: 30px; right: 30px; z-index: 100; display: flex; justify-content: space-between; align-items: center; pointer-events: none; }
/* auto-hide: shared.js flips .nav--away on scroll direction */
.nav { transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1); }
.nav--away { transform: translateY(calc(-100% - 62px)); }
@media (prefers-reduced-motion: reduce) { .nav { transition: none; } .nav--away { transform: none; } }
.nav__pill {
  pointer-events: auto;
  display: flex; align-items: center; gap: 0;
  height: 60px;
  background: var(--cream); border-radius: 30px;
  padding: 0 17px;
  box-shadow: 0 8px 30px rgba(13,13,13,0.08);
}
.nav__pill .logo { font-size: 21px; margin-right: 20px; }
/* Dima Golovenko: the green iD mark alone stands in for the wordmark */
.logo--dg .mark { width: auto; height: 1.6em; aspect-ratio: 1 / 1; color: var(--green); }
.nav__pill a.lnk { width: 113px; text-align: center; font-size: 15px; font-weight: 600; letter-spacing: -0.02em; padding: 7px 0; border-radius: 100px; transition: background 0.25s; }
/* hover bg is now the sliding green .nav-hpill (see transition.js) */
.nav__book {
  pointer-events: auto;
  display: flex; align-items: center;
  color: var(--cream); font-size: 15px; font-weight: 600;
  transition: opacity 0.4s, transform 0.4s;
}
/* dark pill: text + minus icon; the avatar overlaps its right edge */
.nav__book .bk-pill {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 10px;
  height: 54px;
  background: var(--dark); border-radius: 40px;
  padding: 0 46px 0 20px;
}
/* green pill sweeps in from the right on hover */
.nav__book .bk-fill {
  position: absolute; z-index: 0; top: 50%; right: 14px;
  width: 8px; height: 8px; margin-top: -4px; border-radius: 40px;
  background: var(--green); opacity: 0;
  transition: top 0.4s var(--ease-spring), right 0.4s var(--ease-spring),
              width 0.4s var(--ease-spring), height 0.4s var(--ease-spring),
              margin-top 0.4s var(--ease-spring), opacity 0.15s;
}
.nav__book:hover .bk-fill { top: -2px; right: -2px; width: calc(100% + 4px); height: calc(100% + 4px); margin-top: 0; opacity: 1; }
.nav__book .bk-pill > *:not(.bk-fill) { position: relative; z-index: 1; }
/* label flip (right anchor, like the buttons) */
.nav__book .bk-t { display: inline-block; overflow: hidden; padding: 0.12em 0.2em; margin: -0.12em -0.2em; }
.nav__book .bk-t .t1 { display: inline-block; transform-origin: 100% 50%; transition: transform 0.45s var(--ease-spring); }
.nav__book .bk-t .t2 { position: absolute; inset: 0.12em 0.2em; transform-origin: 100% 50%; transform: translateY(170%) rotate(-16deg); transition: transform 0.45s var(--ease-spring); }
.nav__book:hover .bk-t .t1 { transform: translateY(-200%) rotate(10deg); }
.nav__book:hover .bk-t .t2 { transform: translateY(0) rotate(0); }
/* minus → plus icon */
.nav__book .bk-ic {
  width: 22px; height: 22px; flex: none; border-radius: 50%;
  display: grid; place-items: center; position: relative;
  background: rgba(255,255,250,0.14); color: var(--cream);
  border: 1px solid rgba(255,255,250,0.4);
  transition: background 0.3s, color 0.3s, border-color 0.3s;
}
.nav__book .bk-ic svg { position: absolute; transition: opacity 0.25s, transform 0.4s var(--ease-spring); }
.nav__book .bk-ic .i-plus { opacity: 0; transform: rotate(-90deg); }
.nav__book:hover .bk-ic { background: var(--cream); color: var(--dark); border-color: var(--cream); }
.nav__book:hover .bk-ic .i-minus { opacity: 0; transform: rotate(90deg); }
.nav__book:hover .bk-ic .i-plus { opacity: 1; transform: rotate(0); }
/* avatar: a bigger circle overlapping the pill's right edge;
   rolls away on hover, "You" rolls in */
.nav__book .bk-ava { width: 62px; height: 62px; margin-left: -42px; z-index: 2; flex: none; border-radius: 50%; overflow: hidden; position: relative; background: #2c2c2a; }
.nav__book .bk-ava img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform 0.45s var(--ease-spring); }
/* full-square layer sliding inside the round mask — the circle itself never warps */
.nav__book .bk-ava .you {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: #2c2c2a; color: var(--cream); font-size: 13px; font-weight: 600;
  transform: translateY(-102%); transition: transform 0.45s var(--ease-spring);
}
/* static ring on the mask, stays put while layers roll */
.nav__book .bk-ava::after {
  content: ""; position: absolute; inset: 0; z-index: 3; border-radius: 50%;
  box-shadow: inset 0 0 0 1.5px rgba(255,255,250,0.35); pointer-events: none;
}
/* roll goes top → bottom: photo drops out, "You" falls in from above */
.nav__book:hover .bk-ava img { transform: translateY(102%); }
.nav__book:hover .bk-ava .you { transform: translateY(0); }
.nav__book.is-hidden { opacity: 0; transform: translateY(-0.5rem); pointer-events: none; }
@media (max-width: 900px) {
  .nav { top: 14px; left: 14px; right: 14px; }
  .nav--away { transform: translateY(calc(-100% - 30px)); }
  .nav__pill { height: 48px; }
  .nav__pill a.lnk { display: none; }
  .nav__pill .logo--dg { margin-right: 0; }
  .nav__book { height: 44px; }
  .nav__book .bk-pill { height: 44px; padding: 0 38px 0 16px; }
  .nav__book .bk-ava { width: 50px; height: 50px; margin-left: -34px; }
}

/* ============ INTRO PIN ============ */
.intro { position: relative; height: 330vh; background: var(--paper); }
/* the pin is scroll distance, not content: on a phone 330vh of thumb-swiping
   for one statement reads as a stuck page, so the morph runs its whole
   timeline in ~2 screens instead of ~3.3. */
@media (max-width: 760px) { .intro { height: 220vh; } }
.intro__stick { position: sticky; top: 0; height: 100svh; overflow: clip; }


/* stage = the morphing image card */
.stage {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: calc(100% - 2 * var(--stage-edge)); height: calc(100svh - 2 * var(--stage-edge));
  border-radius: var(--stage-r); overflow: clip;
}
.stage__media { position: absolute; inset: 0; }
/* an image that fills its frame — used by the hero stage, the case
   mini-cards and the contact background */
.stage__media img, .case-mini__img img, .contact-sec__bg img { width: 100%; height: 100%; object-fit: cover; }
/* Kept for a quick swap back to the flat canvas: add stage__media--grad to
   #stageMedia and drop the <img>. */
.stage__media--grad { background: linear-gradient(180deg, #0f3a86 0%, #12459b 42%, #1560cd 100%); }
/* the hero photo reads better flipped — the tree sits away from the headline */
#stageMedia img { transform: scaleX(-1); }
/* permanent darkening of the hero photo (deepens on scroll via JS) */
.stage__dim { position: absolute; inset: 0; background: rgba(13,13,13,0.48); }
/* film grain over the hero media */
.stage__grain {
  position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: 0.55;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.14 0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 20rem;
}

/* hero content (inside stage) */
.hero-ui { position: absolute; inset: 0; z-index: 2; color: var(--cream); display: flex; flex-direction: column; justify-content: flex-end; }
/* keep every load/scroll-animated hero element on a permanent GPU layer:
   without this, tween start/end promotes/demotes the layer and the text
   antialiasing flips for a frame — reads as random flicker on Windows */
.nav, .hero-ui, .hero-ui__txt h1, .hero-ui__txt .sub, .hero-ui__cta,
.hero-ui__foot, .case-mini, .statement { will-change: transform, opacity; }
/* NOTE: no will-change on .btn .fill — pre-rasterizing the tiny 8px dot
   makes the scale(340) flood snap instead of animating on some GPUs */
/* The +5rem is a deliberate 80px drop from the original Kora position: the
   block sat too close to the nav pill. It rides on the existing clamp rather
   than replacing it, so the viewport-height behaviour is untouched, and being
   rem it eases off on narrow screens where the root shrinks (80 → 55 → 70px). */
.hero-ui__txt { position: absolute; left: clamp(28px, 3.4vw, 64px); top: calc(clamp(6.25rem, 13svh, 10rem) + 5rem); max-width: 74rem; }
.hero-ui__txt h1 { font-size: var(--h-hero); font-weight: 600; letter-spacing: -0.03em; line-height: 1.12; }
/* The hero is composed by hand: the <br> puts one sentence per line, and
   above ~1100px that is exactly the two-line block it should be — balancing
   there only re-splits it into three. So the hero opts out of the site-wide
   balance while it is wide.
   Below 1100px the authored break stops helping: each sentence wraps on its
   own and strands its closing word ("understand.", "convert.") on a line by
   itself. Dropping the break lets all six words reflow together, and there
   balance is what distributes them. */
.hero-ui__txt h1 { text-wrap: wrap; }
@media (max-width: 1100px) {
  .hero-ui__txt h1 { text-wrap: balance; }
  .hero-ui__txt h1 br { display: none; }
}
.hero-ui__txt .sub { margin-top: 1.375rem; font-size: clamp(0.9375rem, 1.1vw, 1.1875rem); font-weight: 500; max-width: 34rem; line-height: 1.45; }
.hero-ui__cta { display: flex; align-items: center; gap: 1.125rem; margin-top: 1.875rem; }
.hero-ui__cta .arr { opacity: 0.9; }
.hero-ui__foot {
  position: relative; padding: 0 clamp(28px, 3.4vw, 64px) 48px;
  display: flex; flex-direction: column; gap: 1.5rem;
  align-items: flex-start;
}
.trusted { display: flex; align-items: center; gap: 0.75rem; }
.trusted__avatars { display: flex; }
.trusted__avatars img { width: 1.875rem; height: 1.875rem; border-radius: 50%; border: 0.125rem solid rgba(255,255,250,0.7); object-fit: cover; }
.trusted__avatars img + img { margin-left: -0.5625rem; }
.trusted .cap { font-size: 0.8125rem; font-weight: 600; }
.trusted .stars { display: block; margin-bottom: 0.125rem; }

/* logo marquee — narrow, left-aligned strip (not full width, as in the original).
   Sits alone in the bottom-left foot of the hero: it replaced the
   "Trusted by 50+ companies" avatar row that used to sit above it. The width
   cap keeps the strip clear of the floating case card on the right, and the
   viewport clamp stops it spilling past the gutter on phones. */
.marquee { overflow: hidden; width: min(557px, 70%); max-width: calc(100vw - 2 * clamp(28px, 3.4vw, 64px)); align-self: flex-start; mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent); }
.marquee__track { display: flex; gap: 3rem; width: max-content; animation: marquee 26s linear infinite; align-items: center; }
@keyframes marquee { from { transform: translateX(-50%); } to { transform: translateX(0); } }
.marquee .lg { color: rgba(255,255,250,0.85); font-size: 1.375rem; white-space: nowrap; }
/* real client/employer logos riding in the same strip: normalized to a flat
   cream silhouette on the dark hero, and to a dark one on light-bg strips */
.marquee .lgi { height: 1.5rem; width: auto; flex: none; filter: brightness(0) invert(1); opacity: 0.85; }
.marquee--page .lgi, .ab-mq .lgi { filter: brightness(0); opacity: 0.55; }
/* the Nokia wordmark is set much larger on its canvas than the others —
   one size step down brings its optical weight in line with the strip */
.marquee .lgi[src*="nokia"] { height: 1.05rem; }
.marquee .lgi[src*="onepagecrm"], .marquee .lgi[src*="halo"] { height: 1.8rem; }
.marquee .lgi[src*="nyra"] { height: 1.6rem; }
.marquee .lgi[src*="adwa"] { height: 1.1rem; }
.marquee .lgi[src*="upwork"] { height: 1.55rem; }
.lg--1 { font-weight: 300; letter-spacing: 0.25em; text-transform: uppercase; font-size: 1.125rem !important; }
.lg--2 { font-weight: 800; letter-spacing: -0.02em; }
.lg--3 { font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; }
.lg--4 { font-family: Georgia, serif; font-style: italic; font-weight: 400; }
.lg--5 { font-weight: 600; }

/* case mini card (bottom right) — beige shell, photo left, white inner column.
   Fixed px: the original keeps this card the same size on any screen. */
.case-mini {
  position: absolute; right: 56px; bottom: 56px;
  display: flex; background: var(--beige-2); color: var(--dark);
  border-radius: 30px; padding: 10px; gap: 10px; width: 405px;
  box-shadow: 0 24px 50px rgba(13,13,13,0.14);
}
.case-mini__img { position: relative; width: 137px; min-height: 176px; border-radius: 20px; overflow: hidden; flex: none; }
.case-mini__img .cl { position: absolute; inset: auto 0 10px 0; color: var(--cream); font-size: 12px; font-weight: 700; text-align: center; }
.case-mini__body { display: flex; flex-direction: column; width: 241px; background: var(--cream); border-radius: 20px; overflow: hidden; }
.case-mini__body .chip { align-self: flex-start; margin: 20px 20px 0; background: var(--dark); color: var(--cream); font-size: 13px; font-weight: 600; line-height: 1.3; border-radius: 30px; padding: 5px 9px; }
.case-mini__body .t { margin: 10px 10px 12px 18px; font-size: 13px; font-weight: 600; letter-spacing: -0.045em; line-height: 1.5; }
.case-mini__metric { display: flex; align-items: center; gap: 10px; margin-top: auto; padding: 10px 15px 10px 20px; border-top: 1px solid var(--line); }
.case-mini__metric b { font-size: 30px; font-weight: 600; letter-spacing: -0.03em; }
.case-mini__metric span { font-size: 13px; color: var(--gray); font-weight: 600; line-height: 1.3; }
.case-mini__metric .go {
  margin-left: auto; width: 40px; height: 40px; flex: none; aspect-ratio: 1;
  border-radius: 50%; border: 1px solid var(--line); display: grid; place-items: center;
  color: var(--dark); position: relative; overflow: hidden;
}
/* same language as .btn: a green circle floods out from the middle, and the
   arrow leaves to the right while its clone flies in from the left */
.case-mini__metric .go .go__fill {
  position: absolute; z-index: 0; left: 50%; top: 50%;
  width: 100%; height: 100%; border-radius: 50%; background: var(--green);
  transform: translate(-50%, -50%) scale(0);
  transition: transform 0.5s var(--ease);
}
.case-mini:hover .go .go__fill { transform: translate(-50%, -50%) scale(1); }
/* color: inherit is load-bearing — .case-mini__metric span paints every span
   in the row grey, and this wrapper is a span, so without it the arrows keep
   the metric's grey instead of following the circle from dark to cream. */
.case-mini__metric .go .go__arrows { position: relative; z-index: 1; display: block; width: 15px; height: 15px; color: inherit; }
.case-mini__metric .go .go__arrows svg { position: absolute; inset: 0; display: block; transition: transform 0.45s var(--ease-spring); }
/* the incoming arrow is cream from the first frame: it only ever appears on
   the green flood, so it never has to wait for the colour transition */
.case-mini__metric .go .go__arrows .a2 { transform: translateX(-160%); color: var(--cream); }
.case-mini:hover .go .go__arrows svg { transform: translateX(160%); }
.case-mini:hover .go .go__arrows .a2 { transform: translateX(0); }
/* On phones the original keeps the case card, stacked full-width under the
   hero copy. Absolute pinning collided with the copy on shorter screens, so
   the phone hero becomes ONE flex column — copy, card, marquee — and the
   card physically cannot overlap anything: it takes its place in the flow,
   margin-top:auto soaks up whatever height the screen has to spare. The copy
   drops its absolute position for the same reason. On screens shorter than
   700px there is no spare height at all and the card bows out. */
@media (max-width: 760px) {
  .case-mini { display: none; }
  .hero-ui { justify-content: flex-start; }
  .hero-ui__txt { position: static; margin: clamp(4.5rem, 10svh, 7rem) 20px 0; }
  /* one full step below --h-hero's floor: at phone measure the full-size
     heading ran to five lines, and the CTA pair must hold one row. */
  .hero-ui__txt h1 { font-size: 2.375rem; }
  .hero-ui__cta { flex-wrap: nowrap; gap: 0.875rem; }
  .hero-ui__cta .btn { white-space: nowrap; padding-inline: 1.125rem; }
  /* order: copy → marquee → case card at the very bottom (as asked) */
  .hero-ui__foot { order: 1; margin-top: auto; }
}
@media (max-width: 760px) and (min-height: 700px) {
  .case-mini {
    display: flex; position: static; order: 2;
    margin: 0.875rem 16px 14px; width: auto; padding: 8px; gap: 8px;
  }
  .case-mini__img { width: 108px; min-height: 150px; }
  .case-mini__body { width: auto; flex: 1; }
}
/* sub-380 phones: the body column is narrow enough that the metric text
   wraps deep and the card grows past what the hero column can spare —
   everything inside steps down one size so the marquee keeps its footing. */
@media (max-width: 380px) {
  .case-mini__img { width: 92px; min-height: 128px; }
  .case-mini__body .chip { margin: 12px 12px 0; font-size: 12px; }
  .case-mini__body .t { margin: 8px 10px 10px 12px; font-size: 12px; }
  .case-mini__metric { padding: 8px 12px 8px 14px; }
  .case-mini__metric b { font-size: 22px; }
}

/* statement (over blurred stage) */
.statement {
  position: absolute; inset: 0; z-index: 3; display: grid; place-items: center;
  text-align: center; padding-inline: 6vw; opacity: 0; pointer-events: none;
}
/* The <br> in the copy is what guarantees the two sentences never share a line;
   the measure only has to be wide enough not to break a sentence in half on top
   of that. 26em is deliberately generous — the current copy never reaches it at
   any width, so it costs nothing here, and it means longer statement copy can be
   dropped in later without re-tuning this number. text-wrap: balance evens the
   halves out whenever a sentence does have to wrap on narrow screens. */
.statement p { font-size: clamp(1.875rem, 3.3vw, 3.875rem); font-weight: 600; letter-spacing: -0.03em; line-height: 1.18; color: var(--cream); max-width: 26em; text-wrap: balance; }
.statement .w { opacity: 0; display: inline-block; }

/* ============ COMPARISON ============ */
/* pulled up by 60svh: the section's own white bg rides over the pinned
   intro (covers the statement) — no separate curtain element needed */
/* full-viewport overlap: the intro stays PINNED until the compare has
   covered the whole screen, so no released statement strip at the top */
.compare { position: relative; z-index: 5; height: 340vh; margin-top: -100svh; background: var(--paper); }
.compare__stick { position: sticky; top: 0; height: 100svh; overflow: clip; display: grid; place-items: center; }
.compare__title { position: absolute; inset: 0; display: grid; place-items: center; text-align: center; z-index: 1; }
.compare__title .l1, .compare__title .l2 { display: block; font-size: var(--h-sec); font-weight: 600; letter-spacing: -0.03em; line-height: 1.15; color: var(--gray-2); }
/* the <b> is a COLOUR emphasis only — it inherits the 600 of the surrounding
   line instead of setting its own weight. A different weight on top of the
   colour change read as two typefaces sharing a sentence, and at this size the
   500 was optically thinner than the grey it sat next to, so the emphasised
   half looked lighter than the unemphasised one. */
.compare__title .l1 b { font-weight: inherit; color: var(--dark); }
.compare__cards { position: absolute; inset: 0; z-index: 2; }
.comp-card {
  position: absolute; left: 50%; top: 50%;
  width: min(29.6875rem, 44vw); height: min(31.25rem, 82svh);
  border-radius: 1.25rem; padding: clamp(1.25rem, 2vw, 2.25rem);
  display: flex; flex-direction: column;
}
.comp-card .label { color: var(--gray-2); margin-bottom: 0.625rem; }
.comp-card .logo { font-size: 1.0625rem; }
.comp-card h3 { font-size: var(--h-mid); font-weight: 600; letter-spacing: -0.03em; line-height: 1.2; margin-top: 1.375rem; }
.comp-card ul { margin-top: auto; display: flex; flex-direction: column; gap: 0.875rem; }
.comp-card li { display: flex; align-items: center; gap: 0.625rem; font-size: 0.875rem; font-weight: 600; letter-spacing: -0.01em; }
.comp-card li .ic { width: 1.375rem; height: 1.375rem; border-radius: 50%; flex: none; display: grid; place-items: center; }
/* The card is a FIXED height (it has to be — both cards are absolutely centred
   and animate as one stack), and the list is bottom-aligned via margin-top:auto,
   so anything the content can't fit spills past the rounded corner instead of
   scrolling. With five bullets that only bites where the bullets wrap to two
   lines AND the viewport is short — a phone in the 640px-tall class — so the
   list tightens there rather than everywhere. Desktop spacing is left alone
   because it still fits. */
@media (max-height: 700px) {
  .comp-card ul { gap: 0.5rem; }
  .comp-card li { font-size: 0.8125rem; }
}
/* On a phone every bullet wraps to two lines, so the same card that has ~300px
   of slack on desktop has almost none here — the shortened height would spill
   the list past the rounded corner. Below 560px it keeps the original one. */
@media (max-width: 560px) {
  .comp-card { height: min(40.625rem, 84svh); }
}
.comp-card--before { background: var(--beige-2); border: 1px solid var(--line); color: var(--dark); z-index: 2; }
.comp-card--after { z-index: 1; }
.comp-card--before li .ic { background: var(--dark); color: var(--cream); font-size: 0.625rem; }
.comp-card--after { background: var(--green); color: var(--cream); }
.comp-card--after .label { color: rgba(255,255,250,0.8); }
.comp-card--after li .ic { background: var(--cream); color: var(--green); font-size: 0.6875rem; }
/* ---------- comparison: static stack on phones ---------- */
/* The desktop section is a 340vh scroll morph: both cards absolutely centred
   and fanned apart by JS. At phone widths min(29.6875rem, 44vw) leaves a
   ~170px card and the fan has nowhere to go, so — like the original template —
   the phone layout is the plain document: title, Before, After, in normal
   flow. The JS timeline is only created above 760px (main.js); the !importants
   below also neutralise inline styles left by a mid-session resize. */
@media (max-width: 760px) {
  .compare { height: auto; margin-top: 0; padding: 4rem 0 0.5rem; }
  .compare__stick { position: static; height: auto; overflow: visible; display: block; padding-inline: 20px; }
  .compare__title { position: static; display: block; margin-bottom: 1.875rem; }
  .compare__title .l1, .compare__title .l2 { transform: none !important; opacity: 1 !important; }
  .compare__cards { position: static; }
  .comp-card {
    position: static; width: 100%; height: auto; min-height: 0;
    transform: none !important; opacity: 1 !important; filter: none !important;
  }
  .comp-card + .comp-card { margin-top: 0.875rem; }
  .comp-card ul { margin-top: 1.75rem; }
  .comp-card--before > *, .comp-card--after li { opacity: 1 !important; transform: none !important; }
}

/* ============ SERVICES ============ */
.services { background: var(--paper); padding: clamp(4.375rem, 7vw, 7.5rem) 0 0; }
.services h2.mega { font-size: var(--h-mega); font-weight: 600; letter-spacing: -0.04em; line-height: 0.95; }
.services .intro-p { font-size: clamp(1.1875rem, 1.6vw, 1.6875rem); font-weight: 500; letter-spacing: -0.02em; line-height: 1.4; max-width: 40rem; margin-top: 2.125rem; }
.services .intro-p em { font-style: normal; color: var(--green); }
.services .note { font-size: 0.75rem; color: var(--gray-2); margin-top: 0.875rem; }

/* horizontal bar chart */
.chart { position: relative; margin-top: clamp(1.875rem, 3vw, 3.375rem); padding-top: 2.375rem; padding-bottom: 2.125rem; border-bottom: 1px solid var(--line); }
/* dashed vertical gridlines behind the bars, one per axis tick */
.chart__grid { position: absolute; inset: 0 0 2.375rem 0; pointer-events: none; }
.chart__grid span { position: absolute; top: 0; bottom: 0; width: 0; border-left: 1px dashed rgba(36, 36, 36, 0.16); }
.chart__grid span:nth-child(1) { left: 0.55%; }
.chart__grid span:nth-child(2) { left: 12.87%; }
.chart__grid span:nth-child(3) { left: 25.2%; }
.chart__grid span:nth-child(4) { left: 37.52%; }
.chart__grid span:nth-child(5) { left: 49.84%; }
.chart__grid span:nth-child(6) { left: 62.16%; }
.chart__grid span:nth-child(7) { left: 74.48%; }
.chart__grid span:nth-child(8) { left: 86.81%; }
.chart__grid span:nth-child(9) { left: 99.13%; }
.chart__row { position: relative; height: 3.125rem; margin-bottom: 0.75rem; }
.chart__row i {
  position: absolute; inset: 0 auto 0 0; border-radius: 0.9375rem;
  display: flex; align-items: center; justify-content: space-between;
  padding-inline: 0.9375rem; font-size: 0.8125rem; font-weight: 600; letter-spacing: -0.025em; font-style: normal;
  transform-origin: left; white-space: nowrap; overflow: hidden;
}
/* widths are the values themselves, measured on the same rail as the axis:
   0.55% is the 0 gridline and 99.13% is the 1.6% one, so a bar of value v
   ends at 0.55 + v * (99.13-0.55)/1.6. */
.chart__row--redesigned i { width: 91.74%; background: var(--green); color: var(--cream); }
.chart__row--original i { width: 53.54%; background: #e6e6e6; color: var(--dark); }
/* axis labels sit under their gridlines (left-aligned, like the original) */
.chart__axis { position: relative; height: 1.4rem; margin-top: 0.5625rem; font-size: 0.8125rem; font-weight: 600; letter-spacing: -0.025em; color: var(--dark); }
.chart__axis span { position: absolute; top: 0; }
.chart__axis span:nth-child(1) { left: calc(0.55% - 8px); }
.chart__axis span:nth-child(2) { left: calc(12.87% - 8px); }
.chart__axis span:nth-child(3) { left: calc(25.2% - 8px); }
.chart__axis span:nth-child(4) { left: calc(37.52% - 8px); }
.chart__axis span:nth-child(5) { left: calc(49.84% - 8px); }
.chart__axis span:nth-child(6) { left: calc(62.16% - 8px); }
.chart__axis span:nth-child(7) { left: calc(74.48% - 8px); }
.chart__axis span:nth-child(8) { left: calc(86.81% - 8px); }
.chart__axis span:nth-child(9) { left: calc(99.13% - 8px); }

/* Narrow screens. Two things stop fitting at once, both caused by the copy
   being longer than the money figures it replaced:
   - the grey bar is only ~53% wide and "Original 0.86% avg conversion" clips
     out of it below ~440px, so the unit drops away and the bar reads
     "Original  0.86%" — the axis is already in %, so nothing is lost;
   - nine axis labels of "0.2%" sit closer together than eight of "2M" did,
     so the axis type steps down to keep a readable gap and to stop the last
     label hanging as far past the right edge. */
@media (max-width: 480px) {
  .chart__row i .u { display: none; }
  .chart__axis { font-size: 0.6875rem; }
}


/* service cards — beige shell (10px padding) holding: white info card +
   green pill button on the left, full-height photo on the right */
/* gap = (viewport left below a settled card) + ~22svh dwell, so after a card
   lands there is a stretch of scroll before the next one starts covering it */
.svc-stack {
  margin-top: clamp(2.5rem, 4vw, 4.375rem); display: grid;
  /* gap = the strip of viewport left below a settled card + an 18svh dwell,
     so a card that has landed sits alone and perfectly still for a stretch
     before the next one climbs into view and starts covering it */
  gap: calc((100svh - min(680px, 78svh)) / 2 + 18svh);
}
.svc-card {
  position: sticky; top: calc((100svh - min(680px, 78svh)) / 2);
  background: var(--beige-2); border-radius: 30px;
  padding: 10px;
  display: grid; grid-template-columns: 1fr 1fr; column-gap: 10px; overflow: hidden;
  min-height: min(680px, 78svh);
}
@media (max-width: 860px) {
  /* static, not sticky: with the single-column card taller than the viewport,
     stacking meant the next card started covering this one before its lower
     half had ever been on screen. The phone column just scrolls. */
  .svc-card { grid-template-columns: 1fr; row-gap: 10px; min-height: 0; position: static; }
  .svc-stack { gap: 1.625rem; }
  .svc-card__media .glass-quote { display: none; }
}
.svc-card__info { display: flex; flex-direction: column; gap: 10px; }
.svc-card__box { background: var(--cream); border-radius: 30px; padding: clamp(24px, 2.6vw, 50px); flex: 1; display: flex; flex-direction: column; }
.svc-card__top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.375rem; }
/* beige pill with the icon in a white circle inside-left (matches original) */
.svc-card__top .lbl {
  display: inline-flex; align-items: center; gap: 0.5rem;
  background: var(--beige-2); border-radius: 6.25rem; padding: 2px 11px 2px 2px;
  font-size: 0.8125rem; font-weight: 600; letter-spacing: -0.025em;
}
.svc-card__top .lbl svg { color: var(--dark); flex: none; }
.svc-card__top .lbl .ico {
  width: 25px; height: 25px; border-radius: 50%; background: var(--cream);
  display: grid; place-items: center; flex: none;
}
.svc-card__top .lbl .pt { padding: 0; background: none; border-radius: 0; }
.svc-card__top .num { font-size: 1.25rem; font-weight: 600; letter-spacing: -0.02em; color: var(--dark); }
.svc-card h3 { font-size: clamp(1.375rem, 1.6vw, 1.875rem); font-weight: 600; letter-spacing: -0.04em; line-height: 1.3; max-width: 30rem; }
.svc-card .desc { color: var(--gray); font-size: 0.9062rem; margin-top: 0.875rem; max-width: 25rem; }
.svc-card .offer-label { margin-top: auto; padding-top: 1.875rem; font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.03em; }
.svc-card .chips { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.875rem; }
.svc-card .chips li { background: var(--beige-2); border-radius: 0.9375rem; padding: 0.1875rem 0.5625rem; font-size: 0.8125rem; font-weight: 600; letter-spacing: -0.025em; color: var(--dark); }
.svc-card .btn--wide { margin-top: 0; height: 3.5rem; padding: 0; border-radius: 100px; }
.svc-card__media { position: relative; margin: 0; border-radius: 22px; overflow: hidden; min-height: 20rem; }
.svc-card__media > img, .svc-card__media > video, .case__img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* The poster is a still of frame 0, so there is no empty box before playback.
   Default framing is centred — the motion-design clip is composed on its centre
   line, so cover crops evenly off both sides and nothing important is lost. */
.svc-card__vid { display: block; background: var(--skeleton); }
/* card 01 only: that clip is 4:3 landscape in a portrait slot, so cover crops
   ~17% off each side; pushing the focal point to 78% keeps the phone whole
   instead of shaving its right edge, and the branch still fills the left half. */
.svc-card__vid--phone { object-position: 78% 50%; }
/* On the stacked phone layout the original template puts each service's image
   ABOVE its text card, as its own rounded block. order:-1 restores that (the
   DOM keeps info first for desktop), and every media box takes a 4:3 ratio
   instead of the 20rem strip: the Nomi shot is natively 4:3 (phone is 84% of
   frame height, a ~2.5:1 strip would slice it), and the clips crop evenly. */
@media (max-width: 860px) {
  .svc-card__media { order: -1; min-height: 0; aspect-ratio: 4 / 3; }
}
.glass-quote {
  position: absolute; right: 1.25rem; bottom: 1.25rem; max-width: 18.75rem;
  background: rgba(30,30,28,0.38); backdrop-filter: blur(0.875rem);
  border: 1px solid rgba(255,255,250,0.16); border-radius: 1.25rem;
  padding: 1rem 1.125rem; color: var(--cream);
}
.glass-quote p { font-size: 0.8438rem; font-weight: 600; letter-spacing: -0.01em; line-height: 1.45; }
.glass-quote .who { display: flex; align-items: center; gap: 0.625rem; margin-top: 0.75rem; }
.glass-quote .who img { width: 1.875rem; height: 1.875rem; border-radius: 50%; object-fit: cover; }
.glass-quote .who .n { font-size: 0.7812rem; font-weight: 700; }
.glass-quote .who .r { font-size: 0.6875rem; color: var(--w75); }

/* ============ HOW WE WORK ============ */
.how { background: var(--paper); padding: var(--sec-pad) 0; }
.how h2 { font-size: var(--h-sec); font-weight: 600; letter-spacing: -0.03em; line-height: 1.12; max-width: 15em; }
.how .r-sub { color: var(--gray); font-size: 0.9375rem; margin-top: 1.125rem; max-width: 20rem; }

/* horizontal accordion — beige wrap around cream cards (matched to original:
   wrap #f5f5e9 r40 pad/gap 10; cards #fffffa r30 pad 45, head 17px) */
.phases {
  display: flex; gap: 0.625rem; margin-top: clamp(1.875rem, 3vw, 3.125rem);
  background: var(--beige-2); border-radius: 2.5rem; padding: 0.625rem;
}
@media (max-width: 760px) { .phases { flex-direction: column; } }
.phase {
  flex: 1; min-height: 22.5rem; border-radius: 1.875rem; cursor: pointer;
  background: var(--cream); border: 0;
  padding: clamp(1.5rem, 2.3vw, 2.8125rem); position: relative; overflow: hidden;
  transition: flex 0.65s var(--ease), background 0.5s, color 0.5s;
  display: flex; flex-direction: column;
}
.phase .head { display: flex; justify-content: space-between; align-items: center; font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.03em; color: var(--dark); }
.phase:not(.is-open) .head { justify-content: center; }
.phase .head b { font-weight: 600; }
.phase .dots { display: flex; gap: 0.25rem; align-items: center; }
.phase .dots i { width: 0.375rem; height: 0.375rem; border-radius: 50%; background: rgba(255, 255, 250, 0.75); }
.phase .dots i.on { background: var(--green); }
.phase .body { margin-top: auto; opacity: 0; transform: translateY(0.625rem); transition: opacity 0.4s, transform 0.5s; }
.phase .body .nm { display: flex; align-items: center; gap: 0.625rem; font-size: 1.25rem; font-weight: 500; letter-spacing: -0.03em; }
.phase .body p { font-size: 0.9375rem; font-weight: 600; margin-top: 0.75rem; line-height: 1.5; letter-spacing: -0.03em; color: rgba(255, 255, 255, 0.75); max-width: 22.5rem; }
.phase.is-open { flex: 3; background: var(--dark); color: var(--cream); }
.phase.is-open .head { color: var(--cream); }
.phase.is-open .head b { color: rgba(255, 255, 250, 0.55); }
.phase.is-open .body { opacity: 1; transform: none; transition-delay: 0.15s; }
/* stacked phone accordion: a closed phase is a slim bar (its head only), not a
   22.5rem blank. The min-height only makes sense for the horizontal desktop
   accordion where closed cards are narrow columns; the body has to leave the
   layout entirely because at opacity 0 it still holds its height. This block
   sits after the base rules on purpose — .phase{min-height:0} has the same
   specificity as the base .phase and must win by order. */
@media (max-width: 760px) {
  .phase { min-height: 0; }
  .phase:not(.is-open) { padding-block: 1.375rem; }
  .phase:not(.is-open) .body { display: none; }
  .phase.is-open { min-height: 20rem; }
}

/* video card */
.how__video { position: relative; border-radius: 1.25rem; overflow: hidden; margin-top: 0.875rem; }
.how__video img { width: 100%; aspect-ratio: 1480 / 700; object-fit: cover; }
/* the self-hosted showreel is 16:9 — the card takes the clip's own ratio so
   nothing is cropped and no letterbox bars appear when it starts playing */
.how__video--file img { aspect-ratio: 16 / 9; }
.how__video video { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 2; display: block; background: #000; }
/* self-starting and silent: no play affordance to offer */
.how__video--file .play { display: none; }
.how__video .lg { position: absolute; top: 1.5rem; left: 1.625rem; color: var(--cream); font-size: 1.1875rem; }
.how__video .play {
  position: absolute; inset: 0; margin: auto; width: 4.25rem; height: 4.25rem; border-radius: 50%;
  background: rgba(13,13,13,0.45); backdrop-filter: blur(0.375rem); color: var(--cream);
  display: grid; place-items: center; transition: transform 0.3s var(--ease);
  border: 1px solid rgba(255,255,250,0.25);
}
.how__video .play:hover { transform: scale(1.1); }
/* click-to-play: the poster stays a plain image until asked for, then the
   player is dropped on top of it. The card keeps its own 1480/700 ratio so
   nothing below it shifts when the video starts; the wider-than-16:9 gap is
   let through to black rather than resizing the page. */
.how__video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; z-index: 2; }
.how__video .lg, .how__video .play { transition: opacity 0.3s var(--ease), transform 0.3s var(--ease); }
.how__video.is-playing { cursor: default; background: #000; }
/* !important: the appear system leaves an inline opacity:1 on these, which a
   plain rule can't outrank */
.how__video.is-playing .lg, .how__video.is-playing .play { opacity: 0 !important; pointer-events: none; }
.how__video.is-playing:hover img { transform: none; }

/* tagline + dark strip */
.how__tagline {
  font-size: var(--h-mid); font-weight: 600; letter-spacing: -0.03em; line-height: 1.25;
  margin-top: clamp(3.125rem, 5vw, 5rem);
  /* aligned with the narrowed pillars card below */
  width: min(92.5rem, 100%); margin-inline: auto;
}
.how__tagline > * { max-width: 22em; }
.pillars {
  width: min(92.5rem, 100%); margin-inline: auto;
  background: var(--dark); color: var(--cream); border-radius: 1.125rem;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.875rem;
  padding: clamp(1.5rem, 2.4vw, 2.5rem); margin-top: 1.875rem;
}
@media (max-width: 760px) { .pillars { grid-template-columns: 1fr; } }
.pillars .p svg { color: var(--cream); opacity: 0.9; }
.pillars .p p { font-size: 0.8125rem; color: var(--w75); margin-top: 0.875rem; line-height: 1.6; }
.pillars .p p b { color: var(--cream); }

/* ============ WORK STACK (clipped case panels) ============ */
/* Each panel is a window. The .wcard__fixed layer inside is counter-translated
   by main.js so it holds still in the viewport while the panel scrolls past —
   so the composition is progressively cut off by the panel edge and the next
   case takes over. clip-path keeps the blurred, scaled backdrop inside. */
.wstack { background: var(--paper); padding: 0; position: relative; z-index: 4; }

/* The frame lives on the rail, not on the panels. --rail-rest / --rail-r-rest
   are the resting values; JS scrubs the live --rail-inset up from 0 and clips
   the WHOLE rail to the viewport band, so the three cases are one continuous
   surface with exactly four rounded corners — no seam can ever show up in the
   shape, because the shape does not know where the panels meet. */
.wstack__rail {
  --rail-rest: 20px; --rail-r-rest: 40px; --rail-inset: 0px;
  background: #181818;
}

.wcard {
  position: relative; display: block; height: 100svh;
  background: #181818; color: var(--cream);
  /* overflow: hidden is what makes the panel a window: it cuts off the
     counter-translated content layer inside. The rounded frame is applied to
     the rail above, so the panel itself stays a plain rectangle. */
  isolation: isolate; overflow: hidden;
}
.wcard__bg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0; filter: blur(12px); transform: scale(1.08);
}
.wcard__tint { position: absolute; inset: 0; z-index: 1; background: rgba(11,11,11,0.42); }

.wcard__fixed { position: absolute; inset: 0; z-index: 2; pointer-events: none; will-change: transform; }

.wcard__marq { position: absolute; inset: 0; display: flex; align-items: center; overflow: hidden; }
.wcard__track { display: flex; width: max-content; animation: wmarq 26s linear infinite; }
.wcard__title {
  display: inline-flex; align-items: center; white-space: nowrap;
  font-size: clamp(4.5rem, 11vw, 12.5rem); font-weight: 700;
  letter-spacing: -0.045em; line-height: 0.9; color: rgba(255,255,250,0.30);
}
.wcard__title .dot { font-style: normal; font-size: 0.34em; padding: 0 0.42em; opacity: 0.75; }
@keyframes wmarq { to { transform: translateX(-50%); } }

.wcard__stage {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  justify-content: space-between; align-items: stretch;
  /* add the shape inset on top of the normal padding, so the meta rows keep
     the same breathing room inside the visible card at any point of the morph */
  padding: calc(var(--rail-inset) + clamp(1.5rem, 2.6vw, 2.75rem)) 0;
}
.wcard__row {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem;
  font-size: 0.75rem; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase;
  color: rgba(255,255,250,0.72);
}
.wcard__row > span:nth-child(2) { text-align: center; }
.wcard__row > span:nth-child(3) { text-align: right; }
.wcard__go { color: var(--cream); }
.wcard__go i { font-style: normal; display: inline-block; transition: transform 0.35s var(--ease-spring); }
.wcard:hover .wcard__go i { transform: translate(0.15rem, -0.15rem); }

/* the window is a fixed 16:9 frame that fits inside whatever vertical room the
   panel leaves. the outer box just claims that room; .wcard__frame is the frame
   itself. it has to be a plain element, not the <img> — a replaced element's
   intrinsic width wins over `height: 100%` and silently breaks the ratio. */
.wcard__window {
  position: relative;
  margin: clamp(2.25rem, 4.4vw, 5rem) auto;
  flex: 1 1 0%; min-height: 0; width: 92%;
  display: grid; place-items: center;
}
.wcard__frame {
  display: block; position: relative; overflow: hidden;
  width: 100%; height: auto;
  aspect-ratio: 16 / 9;
  border-radius: clamp(0.5rem, 0.9vw, 1rem);
  background: rgba(255,255,250,0.05);
  box-shadow: 0 2rem 4.5rem rgba(0,0,0,0.45);
}
/* past ~1.75 the panel runs out of height before it runs out of width, so
   flip which axis drives the size. the crossover sits below 16/9 because the
   panel's padding and the two meta rows eat vertical room the viewport has. */
@media (min-aspect-ratio: 7 / 4) {
  .wcard__frame { width: auto; height: 100%; }
}
.wcard__window img { width: 100%; height: 100%; object-fit: cover; display: block; }

@media (max-width: 900px) {
  .wstack__rail { --rail-rest: 10px; --rail-r-rest: 20px; }
  .wcard__row { font-size: 0.625rem; letter-spacing: 0.05em; }
  .wcard__row > span:nth-child(3) { display: none; }
  .wcard__row { grid-template-columns: 1fr auto; }
}
@media (prefers-reduced-motion: reduce) {
  .wcard__track { animation: none; }
  .wcard__go i { transition: none; }
}

/* ============ TEAM ============ */
/* full-bleed section on the paper background */
[hidden] { display: none !important; }
.team-sec, .pricing-sec, .contact-sec { padding: 0 var(--edge); background: var(--paper); }
.team-sec__card { background: var(--green); border-radius: var(--r); padding: clamp(3.125rem, 5vw, 6.25rem) 0; }
.team-sec .in { width: min(100rem, 88%); margin-inline: auto; }
.team-sec .logo { color: var(--cream); font-size: 1.0625rem; }
.team-sec h2 { font-size: var(--h-sec); font-weight: 600; letter-spacing: -0.03em; line-height: 1.1; color: var(--cream); margin-top: 1.125rem; }
.team-sec h2 em { font-style: normal; color: rgba(255,255,250,0.55); }
.team-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 3.75rem; margin-top: clamp(1.875rem, 3vw, 3.5rem); }
@media (max-width: 860px) { .team-grid { grid-template-columns: 1fr; } }
.team-row {
  display: flex; align-items: center; gap: 1rem;
  padding: 0.875rem 0; border-bottom: 1px solid rgba(13,13,13,0.12);
}
.team-row img { width: 2.875rem; height: 2.875rem; border-radius: 50%; object-fit: cover; }
.team-row .n { color: var(--cream); font-size: 1.0312rem; font-weight: 600; letter-spacing: -0.01em; }
.team-row .r { color: rgba(13,13,13,0.6); font-size: 0.8125rem; font-weight: 600; margin-top: 1px; }
.team-row .num { margin-left: auto; color: rgba(13,13,13,0.45); font-size: 0.75rem; font-weight: 700; }
.team-row .plus {
  width: 1.875rem; height: 1.875rem; border-radius: 50%; border: 1px solid rgba(13,13,13,0.25);
  display: grid; place-items: center; color: var(--dark); font-size: 1rem; font-weight: 400;
  transition: 0.3s; flex: none;
}
.team-row:hover .plus { background: var(--dark); color: var(--cream); border-color: var(--dark); }
.team-hire {
  margin-top: clamp(2.25rem, 4vw, 3.75rem);
  display: grid; grid-template-columns: 1.15fr 0.85fr; gap: 2.5rem; align-items: center;
}
@media (max-width: 860px) { .team-hire { grid-template-columns: 1fr; } }
.team-hire img { width: 100%; border-radius: 1.125rem; aspect-ratio: 16/9; object-fit: cover; }
.team-hire__txt h3 { color: var(--cream); font-size: var(--h-mid); font-weight: 600; letter-spacing: -0.03em; line-height: 1.15; }
.team-hire__txt p { color: rgba(13,13,13,0.65); font-weight: 600; font-size: 0.9062rem; margin-top: 0.875rem; max-width: 21.25rem; }
.team-hire__txt .btn { margin-top: 1.5rem; }

/* ============ TESTIMONIALS ============ */
.testi { background: var(--paper); padding: var(--sec-pad) 0; }
.testi__feat { position: relative; border-radius: var(--r); overflow: hidden; color: var(--cream); }
.testi__feat > img { width: 100%; aspect-ratio: 1480 / 760; object-fit: cover; min-height: 30rem; filter: saturate(0.85) contrast(0.94) brightness(0.95); }
/* same darkening + film grain treatment as the hero stage */
.testi__feat::before {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: rgba(13, 13, 13, 0.48); pointer-events: none;
}
.testi__feat::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: 0.55;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.14 0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 20rem;
}
.testi__feat .big-t, .testi__feat .glass-quote, .testi__feat .rate { z-index: 2; }
.testi__feat .big-t {
  position: absolute; top: clamp(1.25rem, 4vw, 4.375rem); left: clamp(1.25rem, 3vw, 2.75rem);
  font-size: var(--h-mega); font-weight: 500; letter-spacing: -0.04em; line-height: 0.9;
}
.testi__feat .glass-quote { left: clamp(1.25rem, 3vw, 2.75rem); right: auto; bottom: clamp(1.25rem, 3vw, 2.75rem); top: auto; max-width: 22.5rem; padding: 1.375rem; }
.testi__feat .glass-quote .q { font-size: 1.1875rem; font-weight: 600; line-height: 1.4; }
.testi__feat .glass-quote .small { font-size: 0.7812rem; color: var(--w75); margin-top: 0.875rem; line-height: 1.5; }
.testi__feat .rate { position: absolute; right: clamp(1.25rem, 3vw, 3.125rem); bottom: clamp(1.25rem, 3vw, 2.75rem); text-align: right; }
.testi__feat .rate b { font-size: clamp(2.5rem, 4vw, 4.5rem); font-weight: 500; letter-spacing: -0.03em; }
.testi__feat .rate b span { font-size: 0.4em; color: var(--w75); }
.testi__feat .rate .cap { font-size: 0.75rem; color: var(--w75); }
/* phone: the quote takes the full card width with even 16px gutters (it used
   to run its desktop max-width into the right edge), and the rating drops
   into the cleared strip underneath it. */
@media (max-width: 560px) {
  .testi__feat > img { min-height: 34rem; }
  .testi__feat .glass-quote { left: 16px; right: 16px; max-width: none; bottom: 6rem; }
  .testi__feat .rate { right: 16px; bottom: 1.25rem; }
}

/* testimonial accordion cards */
/* beige shell around the row, exactly like the services stack and the phase
   accordion: 10px of padding and gap, cream cards inside, one big radius. */
.t-cards {
  display: flex; gap: 0.625rem; margin-top: 1rem;
  background: var(--beige-2); border-radius: 2rem; padding: 0.625rem;
}
.t-cards.no-anim, .t-cards.no-anim * { transition: none !important; } /* for height measurement */
@media (max-width: 860px) { .t-cards { flex-direction: column; } }
.t-card {
  flex: 1; background: var(--cream); border: 0; border-radius: 1.5rem;
  padding: 1.5rem; cursor: pointer; overflow: hidden; position: relative;
  transition: flex 0.6s var(--ease), background 0.4s;
  min-height: 15rem; display: flex; flex-direction: column;
}
.t-card .top { display: flex; justify-content: space-between; align-items: center; }
.t-card .x { color: var(--gray-2); font-size: 1.375rem; font-weight: 300; line-height: 1; transition: transform 0.35s var(--ease), color 0.25s; }
.t-card:hover .x { color: var(--green); }
.t-card .qq { display: block; quotes: none; margin-top: 1rem; font-size: 0.9375rem; font-weight: 600; letter-spacing: -0.01em; line-height: 1.5; color: var(--gray-2); transition: color 0.4s; }
.t-card .who { display: flex; align-items: center; gap: 0.625rem; margin-top: auto; padding-top: 1.125rem; }
.t-card .who img { width: 2.125rem; height: 2.125rem; border-radius: 50%; object-fit: cover; }
/* person chip: name + role. Same three lines in the testimonial cards,
   the CTA band and the footer. */
.t-card .who .n, .cta-band .who .n, .footer .fwho .n { font-size: 0.8438rem; font-weight: 700; }
.t-card .who .r, .cta-band .who .r, .footer .fwho .r { font-size: 0.75rem; color: var(--gray); }
.t-card .sig { margin-left: auto; font-family: "Segoe Script", cursive; font-size: 1.1875rem; color: var(--dark); opacity: 0; transition: opacity 0.4s; }
.t-card.is-open { flex: 2.1; background: var(--cream); }
.t-card.is-open .qq { color: var(--dark); font-size: 1.125rem; }
.t-card.is-open .sig { opacity: 1; }
.t-card.is-open .x { transform: rotate(45deg); }

/* stats counters */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2.5rem; margin-top: clamp(3.125rem, 5vw, 5rem); }
@media (max-width: 860px) { .stats { grid-template-columns: 1fr 1fr; } }
.stat { border-top: 1px solid var(--line); padding-top: 1.25rem; position: relative; }
.stat svg { position: absolute; right: 0; top: 1.25rem; color: var(--dark); opacity: 0.7; }
.stat .num { font-size: clamp(2.25rem, 3.4vw, 3.75rem); font-weight: 500; letter-spacing: -0.03em; }
.stat .num .sfx, .case__nums .num .sfx { color: var(--green); font-size: 0.55em; font-weight: 600; }
.stat .d { color: var(--gray); font-size: 0.8125rem; margin-top: 0.625rem; max-width: 12.5rem; line-height: 1.5; }

/* CTA band */
.cta-band { display: grid; grid-template-columns: 0.8fr 1.4fr auto; gap: 2.5rem; align-items: center; margin-top: clamp(3.125rem, 5vw, 5.625rem); }
@media (max-width: 860px) { .cta-band { grid-template-columns: 1fr; } }
.cta-band .logo { font-size: 1.0625rem; }
.cta-band .small { font-size: 0.7812rem; color: var(--gray); margin-top: 0.625rem; max-width: 13.75rem; }
.cta-band .mid p { font-size: clamp(1.1875rem, 1.7vw, 1.75rem); font-weight: 500; letter-spacing: -0.02em; line-height: 1.35; }
.cta-band .mid .g { color: var(--gray-2); }
.cta-band .who { display: flex; align-items: center; gap: 0.75rem; margin-top: 1.125rem; }
.cta-band .who img, .footer .fwho img { width: 2.5rem; height: 2.5rem; border-radius: 50%; object-fit: cover; }
.cta-band .btn { padding: 1.375rem 3.75rem; font-size: 1rem; border-radius: 1rem; }

/* ============ CASE STUDY ============ */
.case { background: var(--paper); padding-bottom: var(--sec-pad); }
/* two equal columns on the standard gutter */
.case__grid, .insights__grid, .cform .row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0.875rem; }
@media (max-width: 860px) { .case__grid { grid-template-columns: 1fr; } }
.case__left { display: flex; flex-direction: column; gap: 0.875rem; }
.panel { background: var(--cream); border: 1px solid var(--line); border-radius: 1.125rem; padding: clamp(1.25rem, 2vw, 2rem); }
.case .date, .faq__foot .t { font-size: 0.8125rem; color: var(--gray); font-weight: 600; }
.case h3 { font-size: var(--h-mid); font-weight: 600; letter-spacing: -0.03em; line-height: 1.25; margin-top: 0.875rem; }
.case__meta { margin-top: 1.375rem; }
/* pill label left, value in a second left-aligned column (matches original) */
.case__meta li { display: grid; grid-template-columns: 1fr 1.5fr; align-items: center; padding: 0.625rem 0; font-size: 0.8125rem; }
.case__meta .k { justify-self: start; display: inline-flex; align-items: center; gap: 0.5rem; background: var(--beige-2); border-radius: 100px; padding: 0.4375rem 0.8125rem; color: var(--dark); font-weight: 600; }
.case__meta .v { color: var(--dark); font-weight: 600; }
.case__nums { display: grid; grid-template-columns: 1fr 1fr; gap: 1.875rem; }
.case__nums .cell { position: relative; }
.case__nums .cell .mi {
  position: absolute; right: 0; top: 0; width: 2.25rem; height: 2.25rem;
  border: 1px solid var(--line); border-radius: 50%;
  display: grid; place-items: center; color: var(--dark); background: var(--paper);
}
.case__nums .num { font-size: clamp(2.25rem, 3vw, 3.375rem); font-weight: 500; letter-spacing: -0.03em; }
.case__nums .d { color: var(--gray); font-size: 0.7812rem; margin-top: 0.5rem; }
.case__right { display: flex; flex-direction: column; gap: 0.875rem; }
.case__svc { display: grid; grid-template-columns: 1fr 1fr; gap: 1.25rem; }
@media (max-width: 560px) { .case__svc { grid-template-columns: 1fr; } }
.case__svc .h { font-size: 0.8125rem; color: var(--gray); font-weight: 600; margin-bottom: 0.75rem; }
/* Filled beige pills, no outline — the same treatment the featured card on
   cases.html already uses (.feat__side .chips). The old outlined 8px-radius
   chip was the odd one out on the site; matching them keeps the case block
   consistent wherever it appears. The dark "+N" counter stays as is. */
.case__svc .chips { display: flex; flex-wrap: wrap; gap: 0.4375rem; }
.case__svc .chips li { background: var(--beige-2); border-radius: 6.25rem; padding: 0.3125rem 0.75rem; font-size: 0.8125rem; font-weight: 600; letter-spacing: -0.01em; color: var(--dark); }
.case__svc .chips li.dk { background: var(--dark); color: var(--cream); }
.case__svc .q { font-size: 0.8438rem; font-weight: 600; line-height: 1.5; }
.case__svc .who { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.625rem; font-size: 0.7812rem; color: var(--gray); }
.case__svc .who img { width: 1.625rem; height: 1.625rem; border-radius: 50%; object-fit: cover; }
.case__img { position: relative; border-radius: 1.125rem; overflow: hidden; flex: 1; min-height: 17.5rem; }
.case__img .cl { position: absolute; inset: 0; display: grid; place-items: center; color: var(--cream); font-size: 1.625rem; font-weight: 700; letter-spacing: -0.02em; }
.case .btn--wide { margin-top: 0; }
/* full-pill case buttons: the pair swaps into each other — green floods to
   dark, dark floods to green (shared by index + cases) */
.btn--vc { height: 3.5rem; padding: 0; border-radius: 40px; }
.btn--vc.btn--green .fill { background: var(--dark); }
.btn--vc.btn--green:hover { color: var(--cream); background-color: var(--dark); }
/* .fill is both the resting dot and the seed of the flood (::before inherits
   its colour), so this one line makes the dot green AND the flood green */
.btn--vc.btn--dark .fill { background: var(--green); }
.btn--vc.btn--dark:hover { color: var(--cream); background-color: var(--green); }
/* the small dot that springs back after the flood is green by default —
   invisible on a green button, so it turns cream here */
.btn--vc.btn--dark::after { background: var(--cream); }
/* homepage case section: single beige wrap, borderless cream cards (matched
   to the original / cases-page .feat) */
.case__grid { background: var(--beige-2); border-radius: 40px; padding: 10px; gap: 10px; }
.case .panel { border: 0; border-radius: 30px; }
.case__img { border-radius: 30px; }

/* ============ PRICING ============ */
.pricing-sec__card { background: var(--dark); border-radius: var(--r); padding: clamp(3.125rem, 5vw, 6.25rem) 0; color: var(--cream); }
.pricing-sec .in { width: min(100rem, 88%); margin-inline: auto; }
.pricing-sec__head { display: flex; justify-content: space-between; align-items: flex-end; gap: 1.875rem; flex-wrap: wrap; }
.pricing-sec h2 { font-size: var(--h-sec); font-weight: 600; letter-spacing: -0.03em; line-height: 1.1; color: var(--cream); max-width: 9em; }
.pricing-sec h2 em { font-style: normal; color: var(--w45); }
.pricing-sec .trusted .cap { color: var(--w75); }
.pricing__grid { display: grid; grid-template-columns: 0.9fr 1.5fr; gap: 2.5rem; margin-top: clamp(2.25rem, 4vw, 3.75rem); align-items: start; }
@media (max-width: 860px) { .pricing__grid { grid-template-columns: 1fr; } }
.plan-list .plan-row {
  width: 100%; text-align: left;
  border: 1px solid rgba(255,255,250,0.14); border-radius: 0.875rem;
  padding: 1.125rem 1.25rem; margin-bottom: 0.625rem;
  display: flex; align-items: center; gap: 0.875rem;
  transition: background 0.3s, border-color 0.3s;
}
.plan-list .plan-row .ic { width: 1.25rem; color: var(--w75); }
.plan-list .plan-row .nm { font-size: 1rem; font-weight: 600; }
.plan-list .plan-row .pr { font-size: 0.7812rem; color: var(--w45); margin-top: 0.125rem; }
.plan-list .plan-row .pop { margin-left: auto; background: var(--green); color: var(--dark); font-size: 0.6875rem; font-weight: 700; border-radius: 6.25rem; padding: 0.25rem 0.625rem;
  /* "Most common" is two words where the template had one, and on a phone
     the pill broke across two lines and pushed the row taller than its
     neighbours. Keeping the pill whole lets the label beside it wrap
     instead, which costs nothing. */
  white-space: nowrap; }
.plan-list .plan-row .radio { margin-left: auto; width: 1.125rem; height: 1.125rem; border-radius: 50%; border: 0.0938rem solid rgba(255,255,250,0.4); }
.plan-list .plan-row .pop + .radio { margin-left: 0.75rem; }
.plan-list .plan-row.is-on { background: rgba(255,255,250,0.07); border-color: rgba(255,255,250,0.3); }
.plan-list .plan-row.is-on .radio { border-color: var(--green); background: radial-gradient(circle, var(--green) 45%, transparent 50%); }
/* Narrow phones. "Most common" is a two-word pill where the template had the
   one-word "Popular", and "Ongoing, month to month" is a longer sub-label than
   "Starts at $8500/mo" — together they left the middle row so little width that
   it wrapped to three lines and stood a head taller than the two rows around
   it, which reads as a broken list rather than a longer label. Tightening the
   row's own padding and gap first (that space is free), then stepping the pill
   and sub-label down, keeps all three rows the same height down to 360px and
   holds the middle one to two lines at 320px. */
@media (max-width: 400px) {
  .plan-list .plan-row { padding: 1.125rem 0.875rem; gap: 0.625rem; }
  .plan-list .plan-row .pop { font-size: 0.625rem; padding: 0.1875rem 0.4375rem; }
  .plan-list .plan-row .pr { font-size: 0.6875rem; }
}
.pricing__note { color: var(--w75); font-size: clamp(1rem, 1.3vw, 1.3125rem); font-weight: 500; margin-top: 2.125rem; max-width: 20rem; line-height: 1.45; }
.pricing__note em { font-style: normal; color: var(--green); }
.plan-detail { background: rgba(255,255,250,0.05); border: 1px solid rgba(255,255,250,0.12); border-radius: 1.125rem; padding: clamp(1.375rem, 2.2vw, 2.375rem); }
.plan-detail__top { display: flex; justify-content: space-between; align-items: center; gap: 1.25rem; flex-wrap: wrap; }
.plan-detail__top .price { font-size: clamp(2.125rem, 3vw, 3.375rem); font-weight: 500; letter-spacing: -0.03em; }
/* A model name is read, not scanned at a glance the way "$2500" was, so it
   steps down from the price size. At the old size "Monthly Retainer" pushed
   the button onto a second line at every desktop width. */
.plan-detail__top .price--name { font-size: clamp(1.5rem, 2.2vw, 2.25rem); }
.plan-detail .feats-label { margin-top: 1.625rem; font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--w45); }
.plan-detail .feats-label + .feats { margin-top: 0.875rem; }
.plan-detail__top .btn { background: var(--cream); color: var(--dark); padding: 0.8125rem 2.875rem; }
.plan-detail .desc { color: var(--w75); font-size: 0.9062rem; margin-top: 1.125rem; max-width: 26.25rem; }
.plan-detail .feats { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem 1.5rem; margin-top: 1.625rem; }
@media (max-width: 560px) { .plan-detail .feats { grid-template-columns: 1fr; } }
.plan-detail .feats li { display: flex; align-items: center; gap: 0.625rem; font-size: 0.875rem; font-weight: 600; }
.plan-detail .feats li .ck { width: 1.25rem; height: 1.25rem; border-radius: 50%; background: var(--green); color: var(--dark); display: grid; place-items: center; font-size: 0.625rem; flex: none; }

/* ============ FAQ ============ */
.faq { background: var(--paper); padding: var(--sec-pad) 0; text-align: center; }
.faq h2 { font-size: var(--h-mega); font-weight: 600; letter-spacing: -0.04em; }
.faq__panel { width: min(51.25rem, 92vw); margin: clamp(1.875rem, 3vw, 3.125rem) auto 0; background: var(--beige-2); border: 1px solid var(--line); border-radius: 1.25rem; padding: clamp(1.125rem, 2vw, 1.875rem); text-align: left; }
.faq__tabs { display: flex; justify-content: center; gap: 0.375rem; flex-wrap: wrap; }
.faq__tabs button { border-radius: 6.25rem; padding: 0.5rem 1.125rem; font-size: 0.8125rem; font-weight: 600; letter-spacing: -0.025em; color: var(--gray); transition: 0.25s; }
.faq__tabs button.is-active { background: var(--green); color: var(--cream); }
.faq__tabs button:not(.is-active):hover { background: var(--cream); color: var(--dark); }
.faq__list { margin-top: 1.125rem; }
.faq-item { background: var(--cream); border: 1px solid var(--line); border-radius: 0.75rem; margin-bottom: 0.5rem; }
.faq-item summary { list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 1.25rem; padding: 1.125rem 1.375rem; font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.03em; cursor: pointer; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary .x { color: var(--gray-2); font-size: 1.375rem; font-weight: 300; transition: transform 0.35s var(--ease); flex: none; line-height: 1; }
.faq-item[open] summary .x { transform: rotate(45deg); }
.faq-item.is-closing summary .x { transform: rotate(0deg); }
.faq-item .a { color: var(--gray); font-weight: 600; padding: 0 1.375rem 1.25rem; font-size: 0.9375rem; letter-spacing: -0.03em; line-height: 1.5; text-align: left; }
.faq__foot { display: flex; align-items: center; justify-content: space-between; gap: 1.25rem; margin-top: 1.125rem; padding: 0.625rem 0.75rem; flex-wrap: wrap; }
.faq__foot .avs { display: flex; }
.faq__foot .avs img { width: 2.5rem; height: 2.5rem; border-radius: 50%; border: 0.125rem solid var(--beige-2); object-fit: cover; }
.faq__foot .avs img + img { margin-left: -0.625rem; }
.faq__mail { display: inline-flex; align-items: center; gap: 0.625rem; font-size: 1.5625rem; font-weight: 600; letter-spacing: -0.03em; cursor: pointer; }
.faq__mail .ic { width: 1.375rem; height: 1.375rem; border-radius: 50%; background: var(--green); color: var(--cream); display: grid; place-items: center; font-size: 0.6875rem; }

/* ============ INSIGHTS ============ */
.insights { background: var(--paper); padding-bottom: var(--sec-pad); }
.insights__wrap { display: grid; grid-template-columns: 0.9fr 1.5fr; gap: clamp(1.875rem, 5vw, 6.875rem); align-items: stretch; }
@media (max-width: 860px) { .insights__wrap { grid-template-columns: 1fr; } }
.insights__left { display: flex; flex-direction: column; align-items: flex-start; }
.insights__left h2 { font-size: var(--h-sec); font-weight: 600; letter-spacing: -0.03em; }
.insights__left p { color: var(--gray); font-size: 0.9375rem; margin-top: 1rem; max-width: 20rem; }
.insights__left .btn { margin-top: auto; }
@media (max-width: 860px) { .insights__left .btn { margin-top: 24px; margin-bottom: 24px; } }
@media (max-width: 560px) { .insights__grid { grid-template-columns: 1fr; } }
.ins-card { position: relative; border-radius: 1.125rem; overflow: hidden; aspect-ratio: 3 / 4; display: flex; }
.ins-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform 0.8s var(--ease); }
.ins-card:hover img { transform: scale(1.04); }
.ins-card::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(13,13,13,0.08) 40%, rgba(13,13,13,0.6)); }
.ins-card .chip {
  position: absolute; z-index: 2; top: 0.875rem; left: 0.875rem;
  display: inline-flex; align-items: center; gap: 0.4375rem;
  background: var(--cream); color: var(--dark);
  border-radius: 6.25rem; padding: 0.4375rem 0.8125rem; font-size: 0.75rem; font-weight: 700;
}
.ins-card .txt { position: relative; z-index: 2; margin-top: auto; padding: 1.25rem; color: var(--cream); width: 100%; }
.ins-card .meta { font-size: 0.7188rem; font-weight: 600; color: var(--w75); }
.ins-card .t { display: block; font-size: clamp(1.125rem, 1.5vw, 1.5rem); font-weight: 500; letter-spacing: -0.02em; line-height: 1.3; margin-top: 0.5rem; }

/* ============ CONTACT ============ */
.contact-sec__card { position: relative; border-radius: var(--r); overflow: hidden; padding: clamp(1.625rem, 3vw, 4.375rem) 0; }
.contact-sec__bg { position: absolute; inset: 0; }
/* same treatment as the hero stage: flat 34% dim + film grain, so the cream
   text and the glass form sit on the photo the way they do up top */
.contact-sec__bg::after { content: ""; position: absolute; inset: 0; background: rgba(13,13,13,0.48); }
.contact-sec__bg::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: 0.55;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.14 0'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 20rem;
}
.contact-sec .in { position: relative; z-index: 2; width: min(100rem, 88%); margin-inline: auto; display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.875rem, 4vw, 5.625rem); }
@media (max-width: 860px) { .contact-sec .in { grid-template-columns: 1fr; } }
.contact-sec h2 { color: var(--cream); font-size: var(--h-sec); font-weight: 600; letter-spacing: -0.03em; line-height: 1.1; max-width: 8em; }
.contact-sec .feats { margin-top: 1.875rem; display: flex; flex-direction: column; gap: 0.875rem; }
.contact-sec .feats li { display: flex; align-items: center; gap: 0.75rem; color: var(--cream); font-weight: 600; font-size: 0.9375rem; letter-spacing: -0.03em; }
/* the ✦ chips read as decoration next to three short lines — the list holds
   on its own, so the markers are dropped and the text keeps the left edge */
.contact-sec .feats li .ic { display: none; }
.contact-sec .feats li .ic { width: 1.625rem; height: 1.625rem; border-radius: 0.5rem; background: rgba(255,255,250,0.15); backdrop-filter: blur(0.25rem); display: grid; place-items: center; font-size: 0.75rem; flex: none; }
.contact-sec .q { margin-top: auto; padding-top: 3.75rem; color: var(--cream); max-width: 23.75rem; }
.contact-sec .q .lbl { color: var(--green-soft); font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; }
.contact-sec .q p { font-size: 1.5625rem; font-weight: 600; letter-spacing: -0.03em; line-height: 1.35; margin-top: 0.625rem; }
.contact-sec .q .who { display: flex; align-items: center; gap: 0.625rem; margin-top: 1rem; font-size: 0.8125rem; color: var(--w75); }
.contact-sec .q .who img { width: 2rem; height: 2rem; border-radius: 50%; object-fit: cover; }
.cform {
  align-self: start; /* hug the content instead of stretching to the column */
  /* glass panel matched to the original: rgba(227,227,227,.45) + blur(10) */
  background: rgba(227, 227, 227, 0.45);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border: 1px solid rgba(255,255,250,0.5);
  color: var(--dark); border-radius: 1.875rem; padding: clamp(1.25rem, 2vw, 2.125rem);
}
.cform .logo { font-size: 1rem; }
.cform .lead { font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.01em; margin-top: 0.875rem; line-height: 1.4; }
.cform .lead em { font-style: normal; color: var(--gray); }
@media (max-width: 560px) { .cform .row2 { grid-template-columns: 1fr; } }
.cform label { display: block; font-size: 0.8125rem; font-weight: 600; letter-spacing: -0.025em; margin: 1rem 0 0.375rem; }
.cform input[type="text"], .cform input[type="email"], .cform textarea {
  width: 100%; border: 1px solid rgba(30,30,28,0.15); background: rgba(255,255,250,0.6);
  border-radius: 0.625rem; font: inherit; font-size: 0.875rem; padding: 0.6875rem 0.8125rem; outline: none;
}
.cform input:focus, .cform textarea:focus { border-color: var(--dark); }
.cform .chips { display: flex; flex-wrap: wrap; gap: 0.4375rem; }
.cform .chips button {
  display: inline-flex; align-items: center; gap: 0.4375rem;
  border: 1px solid rgba(30,30,28,0.15); background: rgba(255,255,250,0.5);
  border-radius: 6.25rem; padding: 0.5rem 0.8125rem; font-size: 0.7812rem; font-weight: 600; transition: 0.2s;
}
.cform .chips button .rb { width: 0.8125rem; height: 0.8125rem; border-radius: 50%; border: 0.0938rem solid rgba(30,30,28,0.3); }
.cform .chips button.is-on { background: var(--dark); color: var(--cream); border-color: var(--dark); }
.cform .chips button.is-on .rb { border-color: var(--green); background: radial-gradient(circle, var(--green) 45%, transparent 50%); }
.cform textarea { min-height: 5.25rem; resize: vertical; }
.cform .terms { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8125rem; letter-spacing: -0.025em; color: var(--gray); margin-top: 1rem; }
.cform .foot { display: flex; justify-content: space-between; align-items: center; gap: 1rem; margin-top: 1.125rem; }
.cform .foot .note { font-size: 0.8125rem; letter-spacing: -0.025em; color: var(--gray); max-width: 12.5rem; line-height: 1.5; }
.contact-stats { display: flex; gap: 3.75rem; justify-content: center; margin-top: clamp(1.875rem, 3vw, 3.75rem); position: relative; z-index: 2; color: var(--cream); flex-wrap: wrap; }
.contact-stats .cell { display: flex; align-items: baseline; gap: 0.75rem; }
.contact-stats .num { font-size: clamp(2.25rem, 3.4vw, 3.75rem); font-weight: 600; letter-spacing: -0.04em; }
.contact-stats .num .sfx { color: var(--green-soft); font-size: 0.55em; }
.contact-stats .d { font-size: 0.8125rem; letter-spacing: -0.025em; font-weight: 600; color: var(--w75); max-width: 8.125rem; line-height: 1.5; }

/* ============ FOOTER (green arc rises & fills the bg) ============ */
.footer {
  position: relative; z-index: 2;
  background: transparent;
  /* same frame as the hero stage: 20px sides and bottom */
  padding: clamp(3.75rem, 7vw, 7.5rem) var(--stage-edge) var(--stage-edge);
  margin-top: clamp(3.75rem, 6vw, 6.875rem);
}
/* clips the huge circle so it can't extend the page below the footer,
   while still letting it rise up to 100svh above the footer top */
.footer__arcWrap {
  position: absolute; z-index: 0;
  left: 0; right: 0; top: -100svh; bottom: 0;
  overflow: hidden;
  pointer-events: none;
}
.footer__arc {
  position: absolute; z-index: 0;
  left: 50%; top: calc(100svh - 46svh);
  width: max(160vw, 1400px); aspect-ratio: 1; height: auto;
  transform: translateX(-50%);
  border-radius: 50%;
  background: var(--green);
  will-change: transform;
  pointer-events: none;
}
.footer__card { position: relative; z-index: 1; }
.footer__card { background: var(--beige-2); border-radius: var(--stage-r); overflow: hidden; padding: clamp(1.875rem, 4vw, 4.375rem) clamp(1.25rem, 3vw, 3.75rem) 0; }
.footer__grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.875rem, 5vw, 6.875rem); }
@media (max-width: 860px) { .footer__grid { grid-template-columns: 1fr; } }
.footer .logo { font-size: 1.125rem; }
.footer .addr { font-size: 0.7812rem; color: var(--gray); margin-top: 0.625rem; line-height: 1.5; }
.footer h3 { font-size: var(--h-mid); font-weight: 600; letter-spacing: -0.03em; line-height: 1.2; margin-top: 1.875rem; }
.footer .nl { display: flex; gap: 0; margin-top: 1.375rem; max-width: 26.25rem; border: 1px solid var(--line); background: var(--cream); border-radius: 6.25rem; padding: 0.3125rem; }
.footer .nl input { flex: 1; border: 0; background: none; font: inherit; font-size: 0.875rem; padding: 0.5rem 0.875rem; outline: none; }
.footer .nl .btn { padding: 0.625rem 1.25rem; font-size: 0.875rem; min-height: 0; }
.footer .agree { display: flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; color: var(--gray); margin-top: 0.75rem; }
/* --gray-2 is a display-type accent and stays as designed; in the footer the same
   token lands on 12px text over --beige-2, where it measures 2.57:1. --gray-ink is
   the same hue at 4.55:1, scoped to the small footer copy only. */
.footer .h { font-size: 0.75rem; color: var(--gray-ink); font-weight: 700; margin: 2.125rem 0 0.75rem; }
.footer .socials { display: flex; gap: 0.625rem; }
.footer .socials a { width: 2.125rem; height: 2.125rem; border-radius: 50%; border: 1px solid rgba(30,30,28,0.18); display: grid; place-items: center; transition: 0.25s; }
.footer .socials a:hover { background: var(--dark); color: var(--cream); }
/* the newsletter block became a single CTA: give the button the same rhythm
   the form had, so the Socials heading below keeps its distance */
.footer__grid > div > .btn--green { margin-top: 1.375rem; }
.footer .legal { display: flex; gap: 1.375rem; font-size: 0.8125rem; font-weight: 600; }
.footer .tagline { font-size: clamp(1.1875rem, 1.7vw, 1.6875rem); font-weight: 500; letter-spacing: -0.02em; line-height: 1.35; }
.footer .tagline em { font-style: normal; color: var(--gray-ink); }
.footer .fwho { display: flex; align-items: center; gap: 0.75rem; margin-top: 1.25rem; }
.footer .tel { font-size: 0.875rem; font-weight: 600; color: var(--gray); margin-top: 1.625rem; }
.footer .mail { display: inline-flex; align-items: center; gap: 0.625rem; font-size: clamp(1.1875rem, 1.6vw, 1.625rem); font-weight: 600; letter-spacing: -0.02em; margin-top: 0.5rem; cursor: pointer; }
.footer .mail .ic { width: 1.625rem; height: 1.625rem; border-radius: 50%; background: var(--green); color: var(--cream); display: grid; place-items: center; font-size: 0.75rem; }
.footer .fnav { margin-top: 1.25rem; }
.footer .fnav li { padding: 0.375rem 0; }
.footer .fnav a { font-size: clamp(1.1875rem, 1.6vw, 1.5625rem); font-weight: 600; letter-spacing: -0.02em; }
.footer .fnav a::before { content: "• "; color: var(--dark); }
.footer .fnav a:hover { color: var(--green); }
.footer__giant { margin-top: clamp(1.25rem, 3vw, 3.125rem); overflow: hidden; line-height: 0.72; text-align: center; position: relative; }
.footer__giant span { display: inline-block; text-transform: uppercase; font-size: clamp(3.25rem, 15.5vw, 19rem); /* full-bleed like the original kora: the word ("PIXELHOMIE" = 5.38em in caps) spans ~97vw and is cropped by the card edge */ font-weight: 600; letter-spacing: -0.04em; color: var(--green); transform: translateY(0.14em); }
/* copyright floats bottom-right; the giant wordmark is cropped by the card edge */
.footer__copy { position: absolute; right: clamp(1.25rem, 3vw, 3.75rem); bottom: 1.25rem; font-size: 0.7188rem; color: var(--gray); }

/* ============ HOVER STATES ============ */
.btn:active { transform: translateY(0) scale(0.98); }
.case-mini { transition: box-shadow 0.35s; }
.case-mini:hover { box-shadow: 0 1.875rem 3.75rem rgba(13,13,13,0.24); }
/* photo blurs + darkens, logo drifts to center, arrow goes green */
.case-mini__img img { transition: filter 0.5s var(--ease), transform 0.5s var(--ease); }
.case-mini:hover .case-mini__img img { filter: blur(9px) brightness(0.75); transform: scale(1.06); }
/* transform (compositor) instead of animating `bottom` (layout) — the
   label drift was visibly janky because layout ran every frame */
.case-mini__img .cl { transition: transform 0.55s var(--ease-spring); }
.case-mini:hover .case-mini__img .cl { transform: translateY(-71px); }
/* the circle itself only shifts colour/border — the green arrives via .go__fill */
.case-mini:hover .go { color: var(--cream); border-color: var(--green); }
.case-mini .go { transition: color 0.3s ease 0.12s, border-color 0.3s; }
.team-row { cursor: pointer; }
.team-row img { transition: transform 0.35s var(--ease); }
.team-row:hover img { transform: scale(1.35); }
.team-row .n, .team-row .r { transition: transform 0.35s var(--ease); display: inline-block; }
.plan-list .plan-row:hover { border-color: rgba(255,255,250,0.45); }
.faq-item summary:hover .x { color: var(--green); }
.faq__mail:hover .ic { transform: rotate(90deg); }
.faq__mail .ic { transition: transform 0.35s var(--ease); }
.footer .fnav a { transition: padding 0.3s var(--ease), color 0.3s; }
.footer .fnav a:hover { padding-left: 0.5rem; }
.footer .mail:hover .ic { transform: rotate(90deg); }
.footer .mail .ic { transition: transform 0.35s var(--ease); }
.ins-card .txt .meta, .ins-card .txt .t { transition: transform 0.5s var(--ease); }
.ins-card:hover .txt .t { transform: translateY(-0.25rem); }
.how__video { cursor: pointer; }
.how__video img { transition: transform 0.9s var(--ease); }
.how__video:hover img { transform: scale(1.03); }
.t-card:not(.is-open):hover { background: var(--beige-2); }
.phase:not(.is-open):hover { background: var(--beige); }

/* ============ APPEAR ============ */
[data-appear] { opacity: 0; transform: translateY(1.875rem); }
.no-js [data-appear], [data-appear].is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  [data-appear] { opacity: 1 !important; transform: none !important; }
  .marquee__track { animation: none; }
}

/* ---------- category chip on image (insights cards, shared) ---------- */
.cat-chip {
  position: absolute; z-index: 3; top: 24px; left: 24px;
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--dark); color: var(--cream);
  border-radius: 100px; padding: 2px 12px 2px 2px;
  font-size: 12px; font-weight: 600; white-space: nowrap;
}
.cat-chip .ico {
  width: 25px; height: 25px; border-radius: 50%;
  background: var(--cream); color: var(--dark);
  display: grid; place-items: center; flex: none;
}

/* ---------- page transition curtain (green, arced edges) ---------- */
.pt-curtain { position: fixed; inset: 0; z-index: 300; pointer-events: none; }
.pt-curtain svg { width: 100%; height: 100%; display: block; }

/* ---------- nav hover: sliding green pill + page blur ---------- */
.nav-hpill {
  position: absolute; left: 0; top: 0; height: 37px; width: 0;
  background: var(--green); border-radius: 100px;
  opacity: 0; z-index: 0;
  transition: transform 0.35s var(--ease), width 0.35s var(--ease), opacity 0.25s ease;
}
.nav__pill { position: relative; }
.nav__pill .logo, .nav__pill .lnk { position: relative; z-index: 1; }
.nav__pill .lnk { transition: color 0.25s ease; }
.nav__pill .lnk.is-hov { color: var(--cream); }
main { transition: filter 0.45s ease; }
html.nav-blur main { filter: blur(12px) saturate(0.55) brightness(0.78); }
@media (prefers-reduced-motion: reduce) { html.nav-blur main { filter: none; } }

/* while a page-transition entry is pending, any early paint must be green,
   not white (class is set by an inline <head> script before first paint) */
html.pt-in, html.pt-in body { background: var(--green) !important; }

/* services head pins behind the incoming cards and shrinks as they ride over */
.svc-head { position: sticky; top: -240px; z-index: 0; }
.svc-stack { position: relative; z-index: 2; }

/* late-loading images fade in (class added/removed by shared.js) */
img.img-fade { opacity: 0; transition: opacity 0.6s ease; }
img.img-fade.img-in { opacity: 1; }
/* While an image loads a neutral skeleton stands in for it. WHERE that
   skeleton is painted is what decides whether it looks right — shared.js
   measures and picks one of two homes:
   · the image FILLS its container -> the container takes it, which also
     hides the container's own (often dark) background and kills the black
     flash. Overlay gradients (::before/::after scrims) are muted too: over
     a light skeleton they read as a black card.
   · the image sits NEXT TO other content (avatar + name, photo + caption)
     -> the image itself takes it. A skeleton on the container would light
     up the text beside it, and a square container behind a round avatar
     would show its corners — which is exactly the bug this replaced. */
.img-loading { background-color: var(--skeleton) !important; }
.img-loading::before, .img-loading::after { opacity: 0 !important; }
img.img-skeleton { background-color: var(--skeleton); }

/* word spans produced by the deep appear cascade (shared.js) */
.aw { display: inline-block; }

/* ============================================================================
   HOMEPAGE LOAD ANIMATION — pure CSS.

   This used to be a GSAP timeline in main.js, which meant the first screen
   could not paint until gsap + ScrollTrigger + lenis + shared.js + main.js
   (~198 KB) had downloaded and parsed: LCP sat around 3.9 s. The opening is
   now driven entirely by CSS keyframes that start the moment the stylesheet
   is parsed, so the hero paints on its own schedule and JS only takes over
   afterwards to hand the stage to the scroll timeline.

   The html.preload class is set by an inline <head> script (only when
   prefers-reduced-motion is off AND this is not a page-transition arrival),
   so it is present before first paint. main.js removes it on takeover —
   which cancels every animation below and lets each element rest at its
   natural, already-final state. That is why no keyframe needs a `to` that
   restates a value: `both` fill holds the end state until the class drops.

   Absolute schedule (delays are measured from stylesheet parse; these mirror
   the old GSAP timeline exactly, which had a 0.12 s lead-in):
     0.12  stage pops from scale(0)                      0.60  back.out(1.6)
     0.67  stage unfolds card → full bleed               0.95  power3.inOut
     1.12  hero UI fades in                              0.60  power2.out
     1.22  h1 words rise, stagger 0.05                   0.70  back.out(1.7)
     1.42  .sub then .hero-ui__cta, stagger 0.09         0.80  back.out(1.7)
     1.81  foot + case-mini lift                         0.70  back.out(1.6)
     1.81  foot + case-mini fade/unblur                  0.95  power2.inOut
     2.21  nav drops in                                  0.60  power2.out
   total 2.81 s — main.js waits this out before initIntroScroll().        */

/* ease translations from GSAP's names */
:root {
  --e-back: cubic-bezier(0.34, 1.56, 0.64, 1);   /* back.out(1.6 / 1.7) */
  --e-p3io: cubic-bezier(0.65, 0, 0.35, 1);      /* power3.inOut        */
  --e-p2o:  cubic-bezier(0.33, 1, 0.68, 1);      /* power2.out          */
  --e-p2io: cubic-bezier(0.65, 0, 0.35, 1);      /* power2.inOut        */
}

/* the card springs out of nothing. The translate repeats .stage's own
   centring: a transform declaration replaces it wholesale, it does not
   add to it. */
@keyframes koraStagePop {
  from { transform: translate(-50%, -50%) scale(0); }
  to   { transform: translate(-50%, -50%) scale(1); }
}
/* ...then unfolds into the full-bleed stage. The end values are literally
   .stage's own declarations, so the element lands exactly where the
   stylesheet would have put it and nothing shifts when the class drops. */
@keyframes koraStageUnfold {
  from { width: min(18.75rem, 30vw); height: min(13.75rem, 28svh); border-radius: 1.125rem; }
  to   { width: calc(100% - 2 * var(--stage-edge)); height: calc(100svh - 2 * var(--stage-edge));
         border-radius: var(--stage-r); }
}
@keyframes koraFade { from { opacity: 0; } to { opacity: 1; } }
/* blur(10px) is the same start value the scroll-appear system uses in
   shared.js — the hero was the only block that faded in sharp, which read
   as a different animation language from the rest of the page. */
@keyframes koraRise34 {
  from { transform: translateY(34px); opacity: 0; filter: blur(10px); }
  to   { transform: none; opacity: 1; filter: blur(0px); }
}
/* foot + case-mini split motion from fade: back.out on opacity finishes the
   fade in the first ~0.25 s and reads as an abrupt pop, so the spring stays
   on the movement and the fade gets its own longer, gentler curve. Two
   keyframes, two durations, same start time. */
@keyframes koraLift24 { from { transform: translateY(24px); } to { transform: none; } }
@keyframes koraFadeBlur { from { opacity: 0; filter: blur(10px); } to { opacity: 1; filter: blur(0px); } }
@keyframes koraNavIn {
  from { opacity: 0; transform: translateY(-14px); }
  to   { opacity: 1; transform: none; }
}

html.preload #stage {
  animation: koraStagePop 0.6s var(--e-back) 0.12s both,
             koraStageUnfold 0.95s var(--e-p3io) 0.67s both;
}
html.preload .hero-ui { animation: koraFade 0.6s var(--e-p2o) 1.12s both; }

/* nth-of-type, not nth-child: the <h1> contains a <br> between the two
   lines, and nth-child would count it and shift every delay after it. */
html.preload .hero-ui__txt h1 .aw { animation: koraRise34 0.7s var(--e-back) both; }
html.preload .hero-ui__txt h1 .aw:nth-of-type(1) { animation-delay: 1.22s; }
html.preload .hero-ui__txt h1 .aw:nth-of-type(2) { animation-delay: 1.27s; }
html.preload .hero-ui__txt h1 .aw:nth-of-type(3) { animation-delay: 1.32s; }
html.preload .hero-ui__txt h1 .aw:nth-of-type(4) { animation-delay: 1.37s; }
html.preload .hero-ui__txt h1 .aw:nth-of-type(5) { animation-delay: 1.42s; }
html.preload .hero-ui__txt h1 .aw:nth-of-type(6) { animation-delay: 1.47s; }

html.preload .hero-ui__txt .sub { animation: koraRise34 0.8s var(--e-back) 1.42s both; }
html.preload .hero-ui__cta     { animation: koraRise34 0.8s var(--e-back) 1.51s both; }

html.preload .hero-ui__foot,
html.preload .case-mini {
  animation: koraLift24 0.7s var(--e-back) 1.81s both,
             koraFadeBlur 0.95s var(--e-p2io) 1.81s both;
}
html.preload .nav { animation: koraNavIn 0.6s var(--e-p2o) 2.21s both; }

/* ============ KEYBOARD FOCUS ============
   Mouse clicks stay outline-free; Tab shows a green ring. */
a:focus-visible, button:focus-visible, input:focus-visible,
textarea:focus-visible, select:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 3px;
  border-radius: 4px;
}


/* ---------- case covers: wordmark on a bright product shot ---------- */
/* the Kora covers were dark stock photos, so a plain cream wordmark read fine.
   the Nomi cover is a bright mockup, so the mark now sits in a frosted pill.
   the pill is what makes it readable over the phone screen, so it stays
   centred on the cover the way the original wordmark was. */
.case__img .cl {
  inset: auto 0 1.25rem 0;
  display: block;
  width: -moz-fit-content;
  width: fit-content;
  margin-inline: auto;
  font-size: 1rem;
  padding: 0.5rem 0.9375rem;
  border-radius: 999px;
  background: rgba(36, 36, 36, 0.55);
  -webkit-backdrop-filter: blur(0.5rem);
  backdrop-filter: blur(0.5rem);
}
.case-mini__img .cl {
  /* centred without a transform: the hover state animates translateY on this
     same element, so left:50%/translateX would fight it. auto margins inside a
     left:0/right:0 box centre a fit-content absolute element just as well. */
  inset: auto 0 10px 0;
  width: -moz-fit-content;
  width: fit-content;
  margin-inline: auto;
  text-align: center;
  padding: 4px 9px;
  border-radius: 999px;
  background: rgba(36, 36, 36, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
