/* ============================================================
   motion.css  —  advanced motion layer for usa.weblystudio.com
   Additive only. Everything degrades to the static page when JS
   or motion is unavailable (gating lives on html.js-motion).
   ============================================================ */

/* ---------- GPU hints (kept tight to avoid memory bloat) ---------- */
.scroll-rail-fill { will-change: transform; }

/* ---------- Lenis smooth-scroll helper styles ---------- */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }

/* ============================================================
   1. SCROLL PROGRESS RAIL  (intro loader removed in Batch 8 for instant first paint)
   ============================================================ */
.scroll-rail { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 1200; pointer-events: none; }
.scroll-rail-fill { height: 100%; width: 100%; transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--accent), var(--gold)); }

/* ============================================================
   3. CUSTOM CURSOR  (desktop / fine-pointer only; JS adds .has-cursor)
   ============================================================ */
.mcursor, .mcursor-ring { position: fixed; top: 0; left: 0; z-index: 9000; pointer-events: none;
  border-radius: 50%; transform: translate(-50%, -50%); opacity: 0; transition: opacity .3s ease; }
.mcursor { width: 7px; height: 7px; background: var(--accent); }
.mcursor-ring { width: 34px; height: 34px; border: 1.5px solid rgba(196,93,62,.5);
  transition: width .25s var(--easing-default), height .25s var(--easing-default), background .25s ease, opacity .3s ease; }
body.has-cursor { cursor: none; }
body.has-cursor a, body.has-cursor button, body.has-cursor .btn, body.has-cursor summary, body.has-cursor [role="button"] { cursor: none; }
body.has-cursor .mcursor, body.has-cursor .mcursor-ring { opacity: 1; }
body.has-cursor.cursor-hot .mcursor-ring { width: 56px; height: 56px; background: rgba(196,93,62,.08); border-color: rgba(196,93,62,.7); }

/* ============================================================
   4. HERO AURORA  (animated canvas behind hero copy)
   ============================================================ */
.aurora-canvas { position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: 0; transition: opacity 1.4s ease; }
.aurora-canvas.on { opacity: 1; }
/* dark bands host the aurora behind their own content */
#agencies, .book { position: relative; }
#agencies > .ctn, #book .book-inner { position: relative; z-index: 1; }

/* hero calendar floats in 3D toward the cursor */
.hero-cal { perspective: 1300px; }
.hero-cal-card { transition: transform .45s var(--easing-default); transform-style: preserve-3d; }

/* highlight spans sweep their wash on (orange/yellow) */
html.js-motion .hl-orange, html.js-motion .hl-yellow { background-size: 0 100%; background-repeat: no-repeat; transition: background-size .7s var(--easing-default); }
html.js-motion .hl-orange.swept { background-size: 100% 100%; }
html.js-motion .hl-yellow.swept { background-size: 100% 100%; }

/* ============================================================
   5. CARD TILT + CURSOR SPOTLIGHT  (services / roles)
   ============================================================ */
.svc-card, .role-card { transform-style: preserve-3d; transition: transform .35s var(--easing-default), box-shadow .35s ease; }
.svc-card::after, .role-card::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; opacity: 0;
  background: radial-gradient(240px circle at var(--mx, 50%) var(--my, 50%), rgba(196,93,62,.12), transparent 62%);
  transition: opacity .3s ease; pointer-events: none;
}
.svc-card.lit::after, .role-card.lit::after { opacity: 1; }

/* ============================================================
   6. MAGNETIC BUTTONS
   ============================================================ */
.btn.magnetic { transition: transform .3s var(--easing-spring), background var(--duration-fast), box-shadow var(--duration-normal); will-change: transform; }

/* ============================================================
   7. HOW-IT-WORKS pinned stepper progress line
   ============================================================ */
.steps-line { position: absolute; left: 0; top: 0; height: 3px; width: 0;
  background: linear-gradient(90deg, var(--accent), var(--gold)); border-radius: 3px; }

/* ============================================================
   10. VELOCITY MARQUEE — giant statement band
   ============================================================ */
.vmarquee { overflow: hidden; padding: clamp(26px, 6vw, 60px) 0; background: var(--white); border-top: 1px solid var(--bg-3); border-bottom: 1px solid var(--bg-3); }
.vmarquee-track { display: flex; align-items: center; white-space: nowrap; width: max-content; will-change: transform; }
.vmarquee-track span { font-family: var(--serif); font-weight: 400; font-size: clamp(38px, 11vw, 148px); line-height: .95; letter-spacing: -.02em; padding: 0 .16em; color: var(--ink); }
.vmarquee .vm-dot { color: var(--accent); }
/* marquee stays visible under reduced motion; motion.js sets its auto-drift to 0
   so it only reacts to your scroll (user-initiated), never moves on its own. */

/* ============================================================
   11. SCROLL STORY — pinned full-screen statement sequence
   ============================================================ */
.hstory { position: relative; background: var(--ink); color: #fff; overflow: hidden; }
.hstory-stage { position: relative; }
.hstory-slide { position: relative; min-height: 78vh; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 8vh 6vw; }
.hstory-slide h2 { font-family: var(--serif); font-weight: 400; font-size: clamp(40px, 8.6vw, 124px); line-height: 1.02; letter-spacing: -.02em; margin: 0; color: #fff; max-width: 18ch; }
.hstory .grad { background: linear-gradient(100deg, #E8A24B 0%, #F5C97A 100%); -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent; }
.hs-final .btn { margin-top: 32px; }
/* pinned crossfade mode (desktop, added by JS): stack the slides on top of each other */
.hstory.is-story .hstory-stage { height: 100vh; }
.hstory.is-story .hstory-slide { position: absolute; inset: 0; min-height: 0; padding: 0 6vw; will-change: transform, opacity, filter; }
@media (prefers-reduced-motion: reduce) { .hstory-slide { min-height: 58vh; } }

/* ============================================================
   11B. VSTORY — native-scroll cinematic statements (no pin, perfectly organic)
   ============================================================ */
.vstory { background: var(--ink); color: #fff; }
.vstory-panel { min-height: 80vh; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 6vh 8vw; }
.vstory-panel h2 { font-family: var(--serif); font-weight: 400; font-size: clamp(40px, 8.4vw, 120px); line-height: 1.03; letter-spacing: -.02em; margin: 0; color: #fff; max-width: 16ch; }
.vstory .grad { background: linear-gradient(100deg, #E8A24B 0%, #F5C97A 100%); -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent; }
.vstory-final .btn { margin-top: 30px; }
html.js-motion .vstory-panel { opacity: 0; transform: translateY(48px) scale(.965); filter: blur(10px); transition: opacity .8s var(--easing-default), transform .9s var(--easing-spring), filter .8s var(--easing-default); }
html.js-motion .vstory-panel.seen { opacity: 1; transform: none; filter: blur(0); }
@media (prefers-reduced-motion: reduce) { .vstory-panel { min-height: 60vh; } }

/* ============================================================
   11C. CONVEYOR — native-scroll statements fade in from bottom, out at top (NO pin)
   ============================================================ */
.conveyor { background: var(--ink); color: #fff; }
.conveyor-panel { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 4vh 8vw; will-change: opacity, transform; }
.conveyor-panel h2 { font-family: var(--serif); font-weight: 400; font-size: clamp(40px, 8.4vw, 124px); line-height: 1.03; letter-spacing: -.02em; margin: 0; color: #fff; max-width: 16ch; }
.conveyor .grad { background: linear-gradient(100deg, #E8A24B 0%, #F5C97A 100%); -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent; }
.conveyor-final .btn { margin-top: 30px; }
@media (max-width: 768px) { .conveyor-panel { min-height: 86vh; } }
@media (prefers-reduced-motion: reduce) { .conveyor-panel { min-height: 60vh; opacity: 1 !important; filter: none !important; transform: none !important; } }

/* ============================================================
   11D. STICK — RELIABLE pinned scroll-story via position:sticky (NO ScrollTrigger).
   Flows visibly by default; JS adds .stick-on to engage the sticky pin.
   modes: vertical conveyor (fade in from bottom, out at top) | horizontal slide
   ============================================================ */
.stick { position: relative; background: var(--ink); color: #fff; }
.stick-slide { position: relative; min-height: 86vh; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 4vh 8vw; }
.stick-slide h2 { font-family: var(--serif); font-weight: 400; font-size: clamp(40px, 8.4vw, 124px); line-height: 1.03; letter-spacing: -.02em; margin: 0; max-width: 18ch; color: #fff; }
.stick .grad { background: linear-gradient(100deg, #E8A24B 0%, #F5C97A 100%); -webkit-background-clip: text; background-clip: text; color: transparent; -webkit-text-fill-color: transparent; }
.stick-final .btn { margin-top: 30px; }
.stick.stick-on .stick-stage { position: sticky; top: 0; height: 100vh; overflow: hidden; }
.stick.stick-on .stick-slide { position: absolute; inset: 0; min-height: 0; will-change: opacity, transform; }
/* The .stick giant-text spectacle is scroll-driven (you control it), so it runs under
   reduced motion too — driven per-frame by JS, not CSS transitions. If JS never loads,
   the head safety-net drops js-motion and base .stick-slide styles show the statements
   stacked and fully visible. Fallback only applies when JS is absent: */
@media (prefers-reduced-motion: reduce) {
  html:not(.js-motion) .stick.stick-on .stick-slide { position: relative; inset: auto; min-height: 60vh; opacity: 1 !important; transform: none !important; filter: none !important; }
}

/* ============================================================
   13. FAQ CHOREOGRAPHED ACCORDION
   ============================================================ */
.faq-item .faq-body { overflow: hidden; }
.faq-item .faq-chev { transition: transform .35s var(--easing-default); }
.faq-item.is-open .faq-chev { transform: rotate(180deg); }
.faq-item.is-open > summary { color: var(--accent); }

/* (Batch 5: removed block 14 TESTIMONIAL/CASE hover rules — #testimonials was replaced by #trust and
   #results was removed, so .testi-* / .case-* matched no DOM.) */

/* ============================================================
   15. SECTION DRAMA (invisible-ink, stat pops, pricing landing)
   ============================================================ */
/* agencies "they never see us" resolves out of near-invisibility on scroll */
html.js-motion #agencies .sub strong { opacity: .2; transition: opacity 1.1s var(--easing-default); }
html.js-motion #agencies .sub strong.lit { opacity: 1; }
/* stat figures arrive like evidence */
html.js-motion #stats .stat-figure { transform: scale(.84); opacity: .7; transition: transform .7s var(--easing-spring), opacity .6s ease; }
html.js-motion #stats .stat-figure.popped { transform: scale(1); opacity: 1; }
/* the "1/3rd" headline lands */
html.js-motion #pricing .pricing-headline { transform: scale(1.12); filter: blur(6px); transition: transform .85s var(--easing-spring), filter .7s var(--easing-default); }
html.js-motion #pricing .pricing-headline.landed { transform: scale(1); filter: blur(0); }

/* #guarantees — cards drop from above and seat */
html.js-motion #guarantees .g-card { transform: translateY(-30px) rotate(-1.5deg); transition: transform .7s var(--easing-spring); }
html.js-motion #guarantees .g-card:nth-child(even) { transform: translateY(-30px) rotate(1.5deg); }
html.js-motion #guarantees .g-card.seated { transform: none; }

/* Batch 4: removed dead #offer task-typewriter (.role-card.claimed) and #how step-light-up
   (.step-card / .lit-step) rules — their JS modules + matching DOM are gone. Deck role-tasks
   visibility now lives in block 26; #how is the .how-split number-column layout (block 28). */

/* #agencies — redaction bars wipe off the card copy (text is always real DOM; bars are js-motion-gated so removal reveals all) */
html.js-motion #agencies .agency-card p { position: relative; }
html.js-motion #agencies .agency-card p::after { content: ''; position: absolute; inset: -2px -6px; background: #0e0e1a; border-radius: 3px; transform-origin: right center; transition: transform .6s var(--easing-default); }
html.js-motion #agencies .agency-card.declassified p::after { transform: scaleX(0); }

/* #pricing — counterweight tip (your side floats up, local-hire side sinks) */
html.js-motion #pricing .pricing-compare .pc-webly { transform: translateY(22px); transition: transform .85s var(--easing-spring); }
html.js-motion #pricing .pricing-compare .pc-local { transform: translateY(-10px); transition: transform .85s var(--easing-spring); }
html.js-motion #pricing .pricing-compare.tipped .pc-webly { transform: translateY(-10px); }
html.js-motion #pricing .pricing-compare.tipped .pc-local { transform: translateY(22px); }

/* (#who audience-card motion removed in Batch 8 with the #who section) */

/* ============================================================
   17. CARD WALLS DEAL IN (services/roles/who/why/guarantees/results)
   transform-only so a missed reveal degrades to "slightly offset but visible"
   ============================================================ */
html.js-motion .deal-card { transform: translateY(50px) scale(.97); transition: transform .6s var(--easing-default); }
html.js-motion .deal-card.dealt { transform: none; }

/* ============================================================
   16. MORE SECTION DRAMA (why viz, eor, drivers, guarantees)
   ============================================================ */
/* why vetting funnel bars grow (decorative viz) */
html.js-motion #why .funnel-bar { transform: scaleX(0); transform-origin: left center; transition: transform .8s var(--easing-default); }
html.js-motion #why .funnel-bar.grown { transform: scaleX(1); }
/* eor checklist slides in (transform-only so content is visible even if a reveal is missed) */
html.js-motion #eor .eor-list li { transform: translateX(-18px); opacity: .55; transition: transform .6s var(--easing-default), opacity .5s ease; }
html.js-motion #eor .eor-list li.seen { transform: none; opacity: 1; }
/* ============================================================
   20. #possible — PINNED: title holds, ONE driver card centered at a time.
   The whole section pins (position:sticky stage, like .stick). Inside, the
   head (label+title+sub+dots) holds while the 4 driver cards crossfade one-
   at-a-time (in-from-right / out-to-left) => exactly one sharp card centered,
   never an empty column or a faded card in a void. Shared rAF loop => iOS-safe.
   No JS / no .poss-on => cards fall back to normal stacked flow, fully visible.
   ============================================================ */
.poss-cards { position: relative; }
.poss-dots { display: flex; gap: 8px; margin-top: 22px; }
.poss-dots span { width: 22px; height: 4px; border-radius: 4px; background: rgba(27,27,47,.14); transition: background .3s ease; }
.poss-dots span.on { background: var(--accent); }
html.js-motion #possible.poss-on { padding: 0; }
html.js-motion #possible.poss-on .poss-pin { position: sticky; top: 0; height: 100vh; overflow: hidden; display: flex; align-items: stretch; }
html.js-motion #possible.poss-on .poss-inner { height: 100%; width: 100%; }
html.js-motion #possible.poss-on .poss-cards .driver { position: absolute; left: 0; right: 0; top: 50%; max-width: 600px; margin: 0 auto; transform: translateY(-50%); will-change: transform, opacity; }

@media (min-width: 920px) {
  #possible .poss-inner { display: grid; grid-template-columns: 0.82fr 1.18fr; gap: 56px; align-items: center; }
  #possible .poss-cards { height: 100%; }
  #possible .poss-cards .driver { padding: 38px 36px; }
  #possible .poss-cards .driver-fig { font-size: clamp(56px, 7vw, 86px); margin-bottom: 14px; }
  #possible .poss-cards .driver h3 { font-size: var(--text-2xl); margin-bottom: 10px; }
  #possible .poss-cards .driver p { font-size: var(--text-base); }
}
@media (max-width: 919px) {
  #possible .poss-inner { display: flex; flex-direction: column; }
  #possible .poss-head { flex: 0 0 auto; padding-top: clamp(70px, 9vh, 96px); } /* clear the fixed nav so the heading isn't cut when pinned on mobile */
  #possible .poss-head .title { font-size: clamp(26px, 6.6vw, 38px); }
  #possible .poss-head .sub { font-size: var(--text-sm); }
  html.js-motion #possible.poss-on .poss-cards { flex: 1 1 auto; }
  .poss-dots { margin-top: 14px; }
}
html:not(.js-motion) #possible .poss-cards { display: flex; flex-direction: column; gap: 16px; margin-top: 24px; }
/* Short / landscape viewports (< 600px tall): a pinned head + a centered card can't both
   fit in 100vh, so don't pin — fall back to a plain stacked, fully-visible list. */
@media (max-height: 600px) {
  html.js-motion #possible.poss-on { height: auto !important; padding: var(--space-20) 0; }
  html.js-motion #possible.poss-on .poss-pin { position: static; height: auto; overflow: visible; display: block; }
  html.js-motion #possible.poss-on .poss-inner { display: block; height: auto; }
  html.js-motion #possible.poss-on .poss-cards { position: static; display: flex; flex-direction: column; gap: 16px; margin-top: 22px; height: auto; }
  html.js-motion #possible.poss-on .poss-cards .driver { position: relative; top: auto; left: auto; right: auto; transform: none !important; opacity: 1 !important; filter: none !important; margin: 0 auto; }
  #possible .poss-dots { display: none; }
}
/* guarantees risk-free callout lands (scale-only, visible if stuck) */
html.js-motion #guarantees .risk-free-callout { transform: scale(.93); transition: transform .8s var(--easing-spring); }
html.js-motion #guarantees .risk-free-callout.landed { transform: scale(1); }

/* ============================================================
   19. READ-ALONG TEXT FILL (words brighten as they cross a read-line)
   JS scrubs per-UNIT opacity inline on the .rw / .rword children. The un-scrubbed DEFAULT below is
   opacity:1, so any unit the loop never writes shows solid (and if the script never runs the text
   never even splits, so it stays full). The inline scrub still wins whenever JS runs, since an inline
   style beats this rule. NOTE: the parent `.readalong{opacity:1}` alone canNOT rescue child units —
   child opacity composes independently — which is why the per-child default below exists.
   ============================================================ */
html.js-motion .readalong { opacity: 1 !important; transform: none !important; filter: none !important; }
html.js-motion .readalong .rw, html.js-motion .readalong .rword { opacity: 1; }
/* no transition on .rw: the JS soft-front already eases the fill; a CSS opacity transition would
   double-lag it ~100ms behind the scroll and blur the crisp moving edge (Batch 4: "gap smaller"). */
html.js-motion .readalong .rw { display: inline; }
/* char-fill: each WORD is an inline-block so it never breaks mid-word at a line wrap, while its
   characters (the .rw spans inside) fill one by one. */
html.js-motion .readalong .rword { display: inline-block; }
/* every read-along heading is a block <h2>; assert it so the inline-block .rword units always
   wrap + centre, even if a future change sets a .title to inline/flex */
html.js-motion .title.readalong { display: block; }

/* ============================================================
   8. MOBILE / TOUCH  —  lighten
   ============================================================ */
@media (hover: none), (pointer: coarse), (max-width: 768px) {
  .mcursor, .mcursor-ring { display: none !important; }
  body.has-cursor { cursor: auto; }
  .hero-cal-card { transform: none !important; }
}

/* ============================================================
   9. REDUCED MOTION  —  hard off switch
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .scroll-rail, .mcursor, .mcursor-ring, .aurora-canvas { display: none !important; }
  .hero-cal-card, .svc-card, .role-card { transition: none !important; transform: none !important; }
  html.js-motion .hero-h1 { opacity: 1 !important; transform: none !important; }
  html.js-motion .hl-orange, html.js-motion .hl-yellow { background-size: 100% 100% !important; }
}

/* ============================================================
   21. #offer — "two ways to work with us": BIG CENTERED statements that fill
   character-by-character on scroll (tresmares/Santander), then cards magnet-snap in.
   ============================================================ */
#offer .label { text-align: center; }
#offer > .ctn > .title { text-align: center; max-width: 16ch; margin-left: auto; margin-right: auto; font-size: clamp(40px, 7vw, 86px); line-height: 1.04; }
#offer > .ctn > .sub { text-align: center; max-width: 60ch; margin-left: auto; margin-right: auto; }
.offer-group { margin-top: var(--space-20); }
.offer-group + .offer-group { margin-top: var(--space-24); }
.offer-tag { display: block; max-width: 22ch; margin: 0 auto; padding: 0; background: none !important; box-shadow: none !important; border-radius: 0; font-family: var(--serif); font-weight: 400; font-size: clamp(28px, 4.6vw, 50px); line-height: 1.06; letter-spacing: -.01em; text-transform: none; }
.offer-tag-a { color: var(--accent); }
.offer-tag-b { color: var(--ink); }
.hl-spec { color: #C45D3E; }
.offer-group-line { margin: 16px auto 0; max-width: 54ch; text-align: center; color: var(--ink-3); font-size: var(--text-lg); line-height: 1.55; }
.offer-group .services-grid, .offer-group .roles-grid { margin-top: var(--space-12); }

/* ============================================================
   22. VELOCITY MARQUEE — grab to read (pointer/touch drag scrub)
   touch-action:pan-y lets vertical swipes still scroll the page.
   ============================================================ */
.vmarquee { touch-action: pan-y; }
.vm-draggable { cursor: grab; }
.vm-draggable.vm-grabbing { cursor: grabbing; }
.vm-draggable.vm-grabbing, .vm-draggable.vm-grabbing .vmarquee-track { user-select: none; -webkit-user-select: none; }
.vm-draggable .vmarquee-track span { -webkit-user-drag: none; }

/* (#possible pinned card cycle now lives in block 20 above) */
/* (Batch 4: removed the dead #offer MAGNET-SNAP block — the DECK module [block 26] now owns
   #offer card entrance and no .magnet-card class is added anymore.) */

/* ============================================================
   25. SPOTLIGHT HEADINGS — bigger + centered on the feature sections
   (#offer already centered in block 21; #fit intro + #pricing join it).
   The rest of the page keeps its left-aligned rhythm. Paragraphs in these
   sections drop the read-along and just rise in slow + centered.
   ============================================================ */
.fit-reel .fit-intro .title, #pricing > .ctn > .title {
  text-align: center; margin-left: auto; margin-right: auto;
  font-size: clamp(40px, 6.6vw, 82px); line-height: 1.04; max-width: 18ch;
}
.fit-reel .fit-intro .label, #pricing > .ctn > .label { text-align: center; }
.fit-reel .fit-intro, #pricing > .ctn > .label, #pricing > .ctn > .title, #pricing > .ctn > .sub { text-align: center; }
.fit-reel .fit-intro .sub, #pricing > .ctn > .sub { margin-left: auto; margin-right: auto; max-width: 60ch; }
/* paragraphs: slower, gentler rise (overrides the default .anim 800ms) */
html.js-motion #offer > .ctn > .sub.anim,
html.js-motion .fit-reel .fit-intro .sub.anim,
html.js-motion #pricing > .ctn > .sub.anim { transition-duration: 1150ms; }
html.js-motion #offer > .ctn > .sub.anim:not(.on),
html.js-motion .fit-reel .fit-intro .sub.anim:not(.on),
html.js-motion #pricing > .ctn > .sub.anim:not(.on) { transform: translateY(42px); }

/* ============================================================
   26. #offer DECK — each group pins; cards pile up one at a time into an
   accumulating deck (newest at the front/centre, older peeking behind/above),
   then release to the next group. JS adds .deck-on to engage the pin and
   drives the cards per-frame via the shared rAF loop (iOS-safe). Without
   .deck-on (no-JS / reduced motion / very short viewport) the cards fall back
   to the normal services-/roles-grid, fully visible.
   ============================================================ */
#offer .deck-head { text-align: center; margin: 0 auto; }
#offer .deck-head .offer-tag { font-size: clamp(30px, 5vw, 58px); }
#offer .deck-stage { margin-top: var(--space-12); }

html.js-motion #offer .deck-group.deck-on .deck-track { position: relative; }
html.js-motion #offer .deck-group.deck-on .deck-pin {
  position: sticky; top: 0; height: 100vh; overflow: hidden;
  display: flex; flex-direction: column; justify-content: flex-start;
}
html.js-motion #offer .deck-group.deck-on .deck-head { flex: 0 0 auto; padding-top: clamp(70px, 8vh, 100px); } /* clear the fixed nav (~62-74px) so the heading isn't cut under it when pinned */
html.js-motion #offer .deck-group.deck-on .deck-stage {
  position: relative; flex: 1 1 auto; display: block; margin: 0; min-height: 0;
  overflow: hidden;                       /* clips the waiting cards parked below so the opaque stack shows no bleed */
}
html.js-motion #offer .deck-group.deck-on .deck-card {
  position: absolute; left: 50%; top: 50%; margin: 0;
  width: min(660px, 90vw); opacity: 0;
  /* uniform min box + vertical centring so the receded cards' top edges line up into a clean
     stacked-deck lip rather than a ragged pile (the cards have different natural heights). */
  min-height: clamp(300px, 44vh, 440px);
  display: flex; flex-direction: column; justify-content: center;
  transform: translate(-50%, -50%);       /* will-change is toggled per-card in JS so it isn't held on all 13 cards for the page's lifetime */
  transition: none !important;            /* per-frame JS drives it; no CSS lag */
  padding: clamp(30px, 4vw, 48px) clamp(28px, 3.4vw, 44px);
  border-radius: 28px;                    /* big premium card (solutionwagon-style, Webly branding) */
  background:
    radial-gradient(130% 90% at 100% 0%, rgba(212,168,83,.16), transparent 55%),
    linear-gradient(158deg, #ffffff 0%, var(--bg-2) 100%);
  border: 1px solid rgba(196,93,62,.14);
  box-shadow: 0 22px 55px rgba(27,27,47,.16), 0 4px 12px rgba(27,27,47,.07);
}
html.js-motion #offer .deck-group.deck-on .deck-card h3 { font-size: clamp(24px, 3vw, 36px); margin-bottom: 14px; }
html.js-motion #offer .deck-group.deck-on .deck-card .role-top h3 { font-size: clamp(22px, 2.5vw, 30px); margin-bottom: 0; }
html.js-motion #offer .deck-group.deck-on .deck-card .svc-icon,
html.js-motion #offer .deck-group.deck-on .deck-card .spec-card-icon { transform: scale(1.1); transform-origin: left center; margin-bottom: 18px; }
html.js-motion #offer .deck-group.deck-on .deck-card:hover { transform: translate(-50%, -50%); } /* inline JS transform wins anyway */
html.js-motion #offer .deck-group.deck-on .deck-card p { font-size: clamp(15px, 1.7vw, 18px); }
html.js-motion #offer .deck-group.deck-on .deck-card .role-desc { font-size: clamp(15px, 1.7vw, 17px); }
/* ORANGE "book a call" FINALE card that lands on top of each deck (Samar: a screaming book-the-call CTA) */
#offer .deck-cta { background: linear-gradient(155deg, var(--accent) 0%, var(--accent-2) 100%); border-color: transparent; color: #fff; text-align: center; }
#offer .deck-cta h3 { color: #fff; }
#offer .deck-cta p { color: rgba(255,255,255,.92); }
.deck-cta-btn { display: inline-flex; align-items: center; gap: 9px; margin-top: 20px; padding: 14px 30px; border-radius: 100px; background: #fff; color: var(--accent); font-weight: 700; font-size: var(--text-base); text-decoration: none; box-shadow: 0 10px 26px rgba(0,0,0,.20); transition: transform .25s var(--easing-default), box-shadow .25s; }
.deck-cta-btn svg { transition: transform .25s var(--easing-default); }
@media (hover: hover) and (pointer: fine) { .deck-cta-btn:hover { transform: translateY(-2px); box-shadow: 0 14px 34px rgba(0,0,0,.30); } .deck-cta-btn:hover svg { transform: translateX(3px); } }
/* engaged deck: beat the light deck-card gradient + centre the CTA content */
html.js-motion #offer .deck-group.deck-on .deck-card.deck-cta { background: linear-gradient(155deg, var(--accent) 0%, var(--accent-2) 100%); border-color: rgba(255,255,255,.2); align-items: center; text-align: center; }
html.js-motion #offer .deck-group.deck-on .deck-card.deck-cta h3 { color: #fff; font-size: clamp(24px, 3.2vw, 36px); margin-bottom: 12px; max-width: 18ch; }
html.js-motion #offer .deck-group.deck-on .deck-card.deck-cta p { color: rgba(255,255,255,.92); font-size: clamp(15px, 1.7vw, 18px); max-width: 36ch; margin: 0 auto; }
/* role tasks stay visible inside the deck (the old typewriter module is gone) */
html.js-motion #offer .deck-card .role-tasks li { opacity: 1; transform: none; }
@media (max-width: 600px), (max-height: 760px) {
  /* tighten so a big card still fits the pinned viewport on small / short screens (covers the
     641-760px-tall band the deck still engages in) */
  html.js-motion #offer .deck-group.deck-on .deck-card { padding: 22px 20px; min-height: 0; }
  html.js-motion #offer .deck-group.deck-on .deck-card .role-output { display: none; }
}
/* Deck + reel un-pin on short viewports (e.g. a landscape phone reached by rotate/resize AFTER load,
   where the JS one-time short guard no longer re-fires). Mirrors the #possible escape hatch. !important
   is required because the rAF loops keep writing inline opacity/transform. The DECK escape is at 640px to
   match its JS engage gate (innerHeight >= 640) so there is no engaged-but-not-escaped band; the fit reel
   engages at 560 and is escaped at 600 (escape >= engage, no gap). */
@media (max-height: 640px) {
  html.js-motion #offer .deck-group.deck-on .deck-track { position: static; height: auto !important; }
  html.js-motion #offer .deck-group.deck-on .deck-pin { position: static; height: auto; overflow: visible; display: block; }
  html.js-motion #offer .deck-group.deck-on .deck-stage { position: static; display: grid; }
  html.js-motion #offer .deck-group.deck-on .deck-card { position: relative; left: auto; top: auto; min-height: 0; transform: none !important; opacity: 1 !important; filter: none !important; }
}
@media (max-height: 600px) {
  html.js-motion .fit-reel.fit-on .fit-track { position: static; height: auto !important; }
  html.js-motion .fit-reel.fit-on .fit-pin { position: static; height: auto; overflow: visible; display: block; }
  html.js-motion .fit-reel.fit-on .fit-stage { position: static; display: flex; flex-direction: column; gap: 16px; height: auto; max-width: 780px; margin: 28px auto 0; }
  html.js-motion .fit-reel.fit-on .fit-stmt { position: relative; left: auto; top: auto; width: auto; transform: none !important; opacity: 1 !important; filter: none !important; font-size: clamp(22px, 3vw, 32px); }
}

/* ============================================================
   27. #fit REEL — pinned; each "is this you?" line flies in from the right,
   holds dead-centre big, slides out to the left, one at a time. JS adds
   .fit-on. Fallback (no .fit-on) = a clean centred list, fully visible.
   ============================================================ */
.fit-stage { list-style: none; margin: 28px auto 0; padding: 0; max-width: 780px; display: flex; flex-direction: column; gap: 16px; }
.fit-stmt {
  font-family: var(--serif); font-weight: 400; color: var(--ink);
  font-size: clamp(22px, 3vw, 32px); line-height: 1.2; letter-spacing: -.01em; text-align: center;
}
html.js-motion .fit-reel.fit-on .fit-track { position: relative; }
html.js-motion .fit-reel.fit-on .fit-pin {
  position: sticky; top: 0; height: 100vh; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
}
html.js-motion .fit-reel.fit-on .fit-stage { position: relative; width: 100%; max-width: none; height: 100%; display: block; margin: 0; }
html.js-motion .fit-reel.fit-on .fit-stmt {
  position: absolute; left: 50%; top: 50%; margin: 0;
  width: min(940px, 88vw); opacity: 0;
  transform: translate(-50%, -50%); will-change: transform, opacity; transition: none !important;
  font-size: clamp(30px, 5.4vw, 70px); line-height: 1.1;
}

/* ============================================================
   28. #how — tresmares split: sticky left text + two right number columns
   that scroll at different speeds (col 1 slow, col 2 fast). JS translates the
   columns per-frame (desktop only); no-JS / mobile = a clean static two-up.
   ============================================================ */
.how-split .how-left .title { max-width: 14ch; line-height: 1.06; }
.how-split .how-left .sub { max-width: 42ch; margin-top: 18px; }
.how-link {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 28px;
  /* --accent-2 (#A84B30) not --accent: small/normal-size text needs 4.5:1 AA on white; accent #C45D3E is 4.2:1 */
  font-family: var(--sans); font-weight: 600; color: var(--accent-2); text-decoration: none;
  border-bottom: 1.5px solid currentColor; padding-bottom: 3px;
  transition: gap .3s var(--easing-default);
}
.how-link svg { transition: transform .3s var(--easing-default); }
.how-link:hover { gap: 12px; } .how-link:hover svg { transform: translateX(3px); }

.how-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0; margin-top: 36px; }
.how-col { display: flex; flex-direction: column; }
html.js-motion .how-col { will-change: transform; }
.num-cell { border-top: 1px solid rgba(27,27,47,.12); padding: clamp(18px, 2.4vw, 32px) clamp(12px, 1.6vw, 22px); }
.how-col-slow .num-cell:first-child, .how-col-fast .num-cell:first-child { border-top: none; }
.num-fig { display: block; font-family: var(--serif); font-weight: 400; color: var(--accent); font-size: clamp(44px, 6.6vw, 92px); line-height: .92; letter-spacing: -.02em; }
.num-fig i { font-style: normal; font-size: .34em; color: var(--accent-2); margin-left: .05em; letter-spacing: 0; }
.num-cap { margin-top: 10px; font-family: var(--sans); font-size: clamp(15px, 1.5vw, 18px); font-weight: 600; color: var(--ink); line-height: 1.25; }
.num-sub { margin-top: 8px; font-size: var(--text-sm); color: var(--ink-3); line-height: 1.55; max-width: 34ch; }
@media (max-width: 899px) {
  /* phones: don't squeeze the two very-different columns into half-width each. Stack the 4 steps
     (number + caption + paragraph) full-width, then the 5 proof stats below as a compact 2-up strip. */
  .how-cols { grid-template-columns: 1fr; gap: 0; margin-top: 28px; }
  .how-col-fast { margin-top: 8px; display: grid; grid-template-columns: 1fr 1fr; gap: 0; }
  .how-col-fast .num-cell:nth-child(-n+2) { border-top: none; }
  .how-col-fast .num-cell:nth-child(even) { border-left: 1px solid rgba(27,27,47,.12); }
  .how-col-fast .num-fig { font-size: clamp(36px, 12vw, 60px); }
  .how-col-fast .num-cap { max-width: none; }
}
@media (min-width: 900px) {
  .how-split .how-grid { display: grid; grid-template-columns: 0.82fr 1.18fr; gap: clamp(40px, 5vw, 84px); align-items: start; }
  html.js-motion .how-split .how-left { position: sticky; top: 16vh; }
  .how-cols { margin-top: 0; }
  .how-col-slow .num-cell { border-right: 1px solid rgba(27,27,47,.12); padding-right: clamp(22px, 2.4vw, 40px); }
  .how-col-fast { margin-top: 16vh; }   /* staggered down, like the reference */
  .how-col-fast .num-cell { padding-left: clamp(22px, 2.4vw, 40px); }
}

/* ============================================================
   29. #trust — PINNED social proof. The giant word "TRUST" fills accent left->right while the real
   review cards slide right->left (JS adds .trust-on + drives the rail/word per-frame). Fallback
   (no .trust-on: no-JS / reduced motion / short viewport) = a static readable grid of reviews with
   the word solid white. The reviews are real DOM (a <ul> of <li> figures) so SEO/SR get them either way.
   ============================================================ */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

/* NO overflow:hidden here — an overflow!=visible ancestor breaks the child .trust-pin position:sticky.
   Clipping of the giant word + rail is done on .trust-pin itself (which overflow:hidden is fine on). */
.trust { background: var(--ink); color: #fff; position: relative; }
.trust-eyebrow { text-align: center; color: var(--gold); font-size: var(--text-xs); font-weight: 700; letter-spacing: .16em; text-transform: uppercase; margin: 0 0 12px; }
.trust-word { font-family: var(--sans); font-weight: 800; text-align: center; letter-spacing: -.03em; line-height: .9; margin: 0; color: #fff; }
.trust-rail { list-style: none; margin: 0; padding: 0; }
.trust-card { list-style: none; }
.trust-card figure { margin: 0; background: #232339; border: 1px solid rgba(255,255,255,.10); border-radius: 20px; padding: clamp(26px, 2.8vw, 36px); display: flex; flex-direction: column; gap: 14px; height: 100%; box-shadow: 0 12px 30px rgba(0,0,0,.26); }
.trust-stars { color: var(--gold); font-size: 17px; letter-spacing: 3px; line-height: 1; }
.trust-quote { margin: 0; font-family: var(--sans); font-weight: 400; font-size: clamp(15px, 1.45vw, 17px); line-height: 1.6; color: rgba(255,255,255,.88); }
.trust-who { display: flex; flex-direction: column; gap: 2px; margin-top: auto; }
.trust-name { font-weight: 700; color: #fff; font-size: var(--text-base); }
.trust-co { font-size: var(--text-sm); color: var(--gold); }

/* static / fallback layout (no .trust-on) */
.trust .trust-pin { padding: clamp(56px, 8vw, 96px) 28px; }
.trust-word { font-size: clamp(64px, 16vw, 190px); margin-bottom: clamp(28px, 4vw, 48px); }
.trust-rail { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; max-width: var(--max); margin: 0 auto; }

/* engaged pin */
html.js-motion .trust.trust-on .trust-track { position: relative; }
html.js-motion .trust.trust-on .trust-pin {
  position: sticky; top: 0; height: 100vh; overflow: hidden; padding: 0;
  display: flex; flex-direction: column; justify-content: center;
}
html.js-motion .trust.trust-on .trust-eyebrow { position: absolute; top: clamp(70px, 9vh, 104px); left: 0; right: 0; z-index: 3; margin: 0; } /* clear the fixed nav so the eyebrow is visible when pinned */
html.js-motion .trust.trust-on .trust-word {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 1;
  width: max-content; max-width: 100vw;   /* shrink-wrap to the glyphs so the gradient stop maps 1:1 to the letters (fill stays in sync with the reviews, not the full viewport) */
  font-size: clamp(84px, 26vw, 380px); margin: 0; white-space: nowrap; pointer-events: none;
  color: transparent; -webkit-text-fill-color: transparent;
  -webkit-background-clip: text; background-clip: text;
  background-image: linear-gradient(90deg, var(--accent) 0%, rgba(255,255,255,.95) 0%); /* JS moves the stop L->R */
}
html.js-motion .trust.trust-on .trust-rail {
  position: relative; z-index: 2; display: flex; flex-wrap: nowrap; align-items: center;
  gap: clamp(18px, 2vw, 30px); width: max-content; padding: 0 10vw; will-change: transform;
}
html.js-motion .trust.trust-on .trust-card { flex: 0 0 auto; width: min(440px, 86vw); }
/* #trust un-pin on short viewports (e.g. rotate-to-landscape after load) — mirrors the deck/#possible
   escape. The rAF loop keeps writing inline transform + the word's gradient, so reset with !important and
   force the word back to solid white. */
@media (max-height: 600px) {
  html.js-motion .trust.trust-on .trust-track { position: static; height: auto !important; }
  html.js-motion .trust.trust-on .trust-pin { position: static; height: auto; overflow: visible; padding: clamp(40px, 8vw, 72px) 28px; display: block; }
  html.js-motion .trust.trust-on .trust-eyebrow { position: static; }
  html.js-motion .trust.trust-on .trust-word {
    position: static; transform: none; width: auto; max-width: none;
    font-size: clamp(56px, 14vw, 150px); margin-bottom: clamp(24px, 4vw, 40px);
    color: #fff !important; -webkit-text-fill-color: #fff !important; background-image: none !important;
  }
  html.js-motion .trust.trust-on .trust-rail {
    transform: none !important; display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    width: auto; padding: 0; gap: 18px; max-width: var(--max); margin: 0 auto;
  }
  html.js-motion .trust.trust-on .trust-card { width: auto; }
}

/* ============================================================
   30. MOBILE SCROLL CUE — a clickable DOWN-ARROW button (by JS, touch-only) shown while a pinned section is
   mid-experience; hides when done. Tapping it advances the section by one item. Only tappable while shown.
   ============================================================ */
.scroll-cue {
  position: fixed; left: 50%; bottom: 88px; transform: translateX(-50%);
  z-index: 70; pointer-events: none; opacity: 0; transition: opacity .45s ease, transform .15s ease;
  width: 50px; height: 50px; border: none; padding: 0; border-radius: 50%; cursor: pointer; font: inherit;
  display: flex; align-items: center; justify-content: center;
  background: rgba(27,27,47,.66); color: #fff;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  box-shadow: 0 6px 20px rgba(0,0,0,.28);
}
.scroll-cue.on { opacity: .94; pointer-events: auto; }   /* only clickable while shown */
.scroll-cue:active { transform: translateX(-50%) scale(.9); }
.scroll-cue .cue-ic { display: block; animation: cueDown 1.4s var(--easing-default) infinite; } /* always points DOWN */
@keyframes cueDown { 0%, 100% { transform: translateY(-3px); } 50% { transform: translateY(4px); } }
@media (prefers-reduced-motion: reduce) { .scroll-cue .cue-ic { animation: none !important; } }
