/* ===========================================================================
   How it works — page-specific styles.
   Loaded AFTER tokens.css and shell.css, so scoped overrides here win on
   source order. Shared shell (nav, footer, buttons, .frame, .cm-h, .sec-label)
   belongs in shell.css, not here.
   =========================================================================== */
/* How-it-works hero: LIGHT gradient + dark three.js particle-wave field (Figma 410-12158) */
.hiw-hero{position:relative;height:76vh;min-height:620px;   /* 85vh -> 76vh with the hero CTA removed (Tony/Chad 08-11): the next section peeking above the fold is now the scroll cue */overflow:hidden;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  background:linear-gradient(120deg, var(--soft) 0%, var(--panel) 40%, var(--surface) 66%)}
.hiw-hero-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:0;display:block;transform:translateY(32%)}   /* drop the wave field so its crests sit BELOW the sub-text (was 26%: when the hero shrank to 76vh on 08-11 the crests started lapping the paragraph — 32% restores the clearance) */
/* edge fade: dissolves the dark particle field into the light page at the borders + bottom */
.hiw-hero-vignette{position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(to right, var(--surface) 0%, rgba(241,243,255,0) 12%),
    linear-gradient(to left, var(--surface) 0%, rgba(241,243,255,0) 12%),
    linear-gradient(to bottom, rgba(241,243,255,0) 66%, rgba(241,243,255,.55) 86%, var(--surface) 100%)}
.hiw-hero-inner{position:relative;z-index:2;text-align:center;padding:168px 24px 0;max-width:780px}
/* Phones: push the wave field further down. It only started rendering on small screens on
   2026-08-06, and at the desktop 26% offset its first drawn pixel landed at 441px from the hero
   top while the "See the Engine" button sits at 446-490 — the field ran straight through it.
   38% clears the button by ~32px. Percent, not px, so it tracks the hero height.
   900 matches the SMALL threshold in hero-field.js; keep the two in step. */
@media (max-width:900px){
  .hiw-hero-canvas{transform:translateY(38%)}
  /* The vignette's bottom wash starts at 66% and is 55% opaque by 86%. That is fine on desktop
     where the field sits high, but on phones the field is pushed to 38% and its first pixels
     land around 537px of a 680px hero — inside the wash, which whitened it to almost nothing.
     Start the fade at 88% here so only the very bottom edge blends into the page. */
  .hiw-hero-vignette{background:
    linear-gradient(to right, var(--surface) 0%, rgba(241,243,255,0) 12%),
    linear-gradient(to left, var(--surface) 0%, rgba(241,243,255,0) 12%),
    linear-gradient(to bottom, rgba(241,243,255,0) 88%, var(--surface) 100%)}
}   /* extra top padding so the headline clears the nav with air */
.hiw-hero-inner h1{font-family:var(--display);font-weight:500;font-size:clamp(40px,7vw,68px);line-height:1.05;color:var(--ink);margin:0}
.hiw-hero-inner h1 .accent{color:var(--action)}
.hiw-sub{margin:24px auto 0;max-width:440px;font-family:var(--sans);font-weight:300;font-size:16px;line-height:24px;color:var(--ink)}
/* light page: override the shared dark body bg so the top overscroll (rubber-band) reads light, not dark navy */
/* nav + hero go dark over the light background (scoped to this page) */
/* scrolled nav on the LIGHT page: a light, opaque-enough frosted bar so it reads consistently over
   both the light upper sections and the dark lower ones — and keep the dark-ink content (don't flip to white) */
/* the floating Menu shortcut reads dark over the light hero */

/* ============================================================================
   CAMPAIGN MODEL — pinned scroll-story below the hero (id="how-it-works")
   Phase 1 (Signal identification) -> Phase 2 (Revenue Campaign Execution)
   -> Phase 3 (Continuous optimization), gated by scroll. Reuses img/shared/onprofit-orb.webp,
   the .ava-glow gradient, the 1728px frame, tokens, and the .cat-eyebrow type.
   Layout classes are new; nothing shell is redeclared. Drive: campaign-model.js
   ========================================================================== */
.cm{position:relative;background:var(--surface)}
.cm-track{position:relative}                                    /* auto-play: one full-screen block, no pin (JS starts it on scroll-in) */
.cm-sticky{position:relative;height:100vh;min-height:720px;overflow:hidden;display:flex;flex-direction:column;
  justify-content:center;padding:48px 0}
.cm-frame{width:100%;max-width:1408px;margin:0 auto;padding:0 24px;box-sizing:border-box} /* standard content grid (matches .frame: 1408 + 24px → 1360) so section 01 aligns with sections 02-05 */

.cm-head{max-width:720px}
/* context modifier: on near-white surfaces the eyebrow needs a darker blue for contrast (base type unchanged) */
.on-light .cat-eyebrow{color:var(--action)}
/* .cm-h lives in shell.css (single source). The byte-identical copy that used to sit here
   also OUTRANKED shell's media queries — it loads later — which is why this heading stayed
   40px on phones while every other section scaled down. Removed 2026-08-06. */
.cm-sub{font-family:var(--sans);font-weight:300;font-size:16px;line-height:24px;color:var(--deep);margin:16px 0 0;max-width:640px}

/* three stage pills — style locked to Figma 536-24788 (Geist Medium 14/26, ink text,
   1px #B3C6F9 border, square corners, no fill, 8x16 padding). Gating = opacity only. */
.cm-stages{display:flex;gap:16px;margin:32px 0 0}
.cm-stage-pill{flex:0 0 auto;display:flex;align-items:center;justify-content:center;gap:10px;padding:8px 16px;
  border:1px solid var(--soft);background:transparent;font-family:var(--sans);font-weight:400;
  font-size:14px;line-height:26px;color:var(--ink);white-space:nowrap;transition:opacity .5s ease}
.cm-stage-pill .n{flex:none}
.cm-stage-pill[data-lit="1"]{opacity:1}
.cm-stage-pill[data-lit="0"]{opacity:.4}
/* redistribute the 3 columns within the same full-width row: middle narrower, sides wider.
   Labels align to their outer edge (p1 left over the dots, p3 right over the loop block) so the
   graphic underneath doesn't shift. */
/* Stage-pill widths (Figma 630:28001): blocks 1 + 3 are fixed 262px; block 2 (Campaign Execution)
   flexes to fill the wide middle so it sits over the graphic. Change the 262px here to resize 1 + 3. */
.cm-stages .cm-p1{flex:0 0 262px}   /* Revenue identification — fixed 262px */
.cm-stages .cm-p2{flex:1 1 0}       /* Revenue Campaign Execution — fills the rest (widest) */
.cm-stages .cm-p3{flex:0 0 262px}   /* Continuous optimization — fixed 262px */

/* the graphic board — fixed reference size, scaled to fit the frame (keeps connectors pixel-accurate) */
.cm-board-wrap{position:relative;margin-top:8px;height:560px}
.cm-board{position:absolute;top:0;left:50%;width:1240px;height:560px;margin-left:-620px;transform-origin:top center}
.cm-board *{box-sizing:border-box}

/* market particle field (the "market"; Ava captures them) — reuses the homepage idea */
.cm-particles{position:absolute;left:-260px;top:0;width:1600px;height:470px;pointer-events:none;z-index:0}   /* extends 260px left of the board so the opportunity list can align under the Phase 1 pill on wide viewports */
/* SVG connector layer sits under the boxes */
.cm-svg{position:absolute;inset:0;width:1240px;height:470px;overflow:visible;pointer-events:none;z-index:4   /* above .cm-ava (2) and .cm-deal (3): the dashed connectors were passing BEHIND the orb glow */}
.cm-svg-front{z-index:3}   /* Signal/Context -> Ava lines above the orb (z-index:2) so they read as feeding Ava */
.cm-svg .feed{fill:none;stroke:var(--canvas);stroke-width:1.5;stroke-dasharray:1.5 3;stroke-linecap:round;opacity:0;transition:opacity .3s ease}   /* dotted style (Figma 530-24472); starts hidden so it never flashes before JS */
/* Ava -> outcome connectors (Figma 536-24753): short dashed soft-blue line + filled dot at the box */
.cm-svg .out{fill:none;stroke:var(--canvas);stroke-width:1.5;stroke-dasharray:2 2;opacity:0}
.cm-svg .out-dot{fill:var(--dot);stroke:none;opacity:0}
.cm-svg .coll{fill:var(--dot);stroke:none;opacity:0;transition:opacity .3s ease}/* feedback-loop arrows (Figma 530-24502 style): solid soft-blue, rounded corners */
.cm-svg .arw{fill:none;stroke:var(--canvas);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;opacity:0;transition:opacity .3s ease}
/* ==== ARROW STYLE (2026-07-28) — REVERT: delete these three rules + the <defs> in the connector SVG ====
   Figma 674:2389 draws the feedback arrows as a filled shape with a gradient along their length and a solid
   triangular head, not a flat mid-blue stroke. Gradient runs from #B3C6F9 at the head to #E1E8FA at the tail. */
.cm-svg #cm-in{stroke:url(#arwGradIn)}
.cm-svg #cm-out{stroke:url(#arwGradOut)}
.cm-svg .arw-head{fill:var(--soft);stroke:none}
/* ==== end arrow style ==== */
.cm-svg .pulse{fill:none;stroke:var(--action);stroke-width:2.5;stroke-linecap:round}

/* stage groups dim until their phase is active */
.cm-g{transition:opacity .55s ease, filter .55s ease}
.cm-drops{display:none}     /* mobile only — desktop draws these in .cm-svg */
.cm-connect{display:none}   /* mobile only — the desktop board draws its connectors in .cm-svg */
.cm-g[data-lit="0"]{opacity:.32;filter:grayscale(.5)}
.cm-g[data-lit="1"]{opacity:1;filter:none}

/* far-left customer-journey scan dots */
/* Revenue identification — the 5 opportunities the intelligence layer finds (Figma 605-35908).
   Each row's particles condense to form it one at a time, then its navy dot pulses and emits. */
/* Matched to the Signal/Context lists (2026-08-13, Victoria): same 4px eyebrow gap as
   .cm-list h4 and the same 300-weight 14/20 text as .cm-list li, so both sides of the board
   read as one type system. The row lost its old 48px box, so cm-opps' top moved 180 -> 201
   (off the 4-grid ON PURPOSE) to keep the emitter dot's centre on the trunk at y 235:
   199 + eyebrow 20 + gap 6 + half the 20px row = 235. Gap is 6 not 4 because the right
   side's h4->li box distance MEASURES 6.0 (4px margin + leading) — matched to the pixel. */
.cm-opps{position:absolute;left:20px;top:199px;width:238px;z-index:3}
.cm-opps-eyebrow{font-family:var(--sans);font-weight:400;font-size:12px;line-height:20px;letter-spacing:1px;
  text-transform:uppercase;color:var(--action);margin-bottom:6px;white-space:nowrap}
.cm-opp{position:relative;display:flex;align-items:center;justify-content:space-between;height:20px;
  opacity:0;transition:opacity .28s ease}   /* border-bottom removed 2026-08-06 */
.cm-opp.on{opacity:1}   /* the solid word takes over the instant the dots land */
.cm-opp-label{font-family:var(--sans);font-weight:300;font-size:14px;line-height:20px;color:var(--ink);white-space:nowrap}
.cm-opp-dot{flex:none;width:9px;height:9px;border-radius:50%;background:var(--dot);opacity:0;transform:scale(.4);transition:opacity .3s ease, transform .3s ease}
.cm-opp.lit .cm-opp-dot{opacity:1;transform:scale(1)}   /* the emitter dot appears once the row is formed */
/* .sent = this row's bullet has LEFT for the merge point. Hidden with no transition so the SVG traveller,
   which spawns on the exact same coordinates in the same frame, reads as the same dot leaving rather than a copy.
   Removing .sent falls back to the .3s transition above, so it fades back in softly for the next loop. */
.cm-opp.sent .cm-opp-dot{opacity:0;transition:none}
.cm-opp-dot.pulse{animation:cmOppPulse .6s ease-out}
@keyframes cmOppPulse{0%{transform:scale(1);box-shadow:0 0 0 0 rgba(36,69,157,.35)}45%{transform:scale(1.8);box-shadow:0 0 0 6px rgba(36,69,157,.16)}100%{transform:scale(1);box-shadow:0 0 0 0 rgba(36,69,157,0)}}

/* SIGNAL / CONTEXT chips + their lists */
/* Signal / Context chip — style locked to Figma 536-24722: dashed 1px #B3C6F9, 4px radius,
   12px padding, transparent, centred icon + Geist Medium 12/26 1px-tracked uppercase ink label */
.cm-chip{position:absolute;z-index:3;display:flex;align-items:center;justify-content:center;gap:8px;width:136px;height:36px;padding:0 14px;
  background:transparent;border:1px dashed var(--soft);border-radius:4px;font-family:var(--sans);font-weight:500;
  font-size:12px;line-height:26px;letter-spacing:1px;text-transform:uppercase;color:var(--ink);
  opacity:0;transition:opacity .55s ease}
.cm-chip.show{opacity:1}
.cm-chip.punch{animation:cmPunch .5s cubic-bezier(.34,1.56,.64,1)}   /* pops bigger for a beat when the pulse lands (a "hit") */
@keyframes cmPunch{0%{transform:scale(1)}30%{transform:scale(1.16)}100%{transform:scale(1)}}
.cm-chip svg{width:16px;height:16px;stroke:var(--ink)}
.cm-chip svg.cm-ic-doc{width:19px;height:14px;stroke:none;fill:var(--ink)}   /* Context icon (Figma 486-4584): filled document, own aspect */
.cm-list{position:absolute;z-index:3;width:184px;font-family:var(--sans)}
.cm-list h4{margin:0 0 4px;font-weight:400;font-size:14px;line-height:20px;color:var(--action);opacity:0;transition:opacity .55s ease}
.cm-list h4.show{opacity:1}
.cm-list ul{list-style:none;margin:0;padding:0}
.cm-list li{font-weight:300;font-size:14px;line-height:20px;color:var(--ink);opacity:0;transform:translateX(-6px);transition:opacity .4s ease, transform .4s ease}
.cm-list li.on{opacity:1;transform:none}
.cm-list li.ping{animation:cmPing .7s ease-out}   /* a signal mote just landed -> the item it informs brightens for a beat */
@keyframes cmPing{0%{color:var(--ink)}25%{color:var(--action)}100%{color:var(--ink)}}   /* text-shadow glow removed 2026-08-13 (Victoria): the item still flashes blue when a mote lands, without the halo behind the words */
/* one running line: "Who to contact: paywall hit, seat added, product activity".
   The list items stay as real elements so the per-item ping animation still has a target. */
.cm-list h4{display:block}   /* the label sits on its own line; its 8px margin-bottom only
   takes effect as a block, which is what opens the gap to the items below */
.cm-list ul,.cm-list li{display:inline}   /* the items themselves still flow as one comma-joined line */
.cm-list li::before{content:", ";color:var(--ink)}
.cm-list li:first-child::before{content:""}   /* no leading space now that it starts the line */
/* ==== LEFT-COLUMN ALIGNMENT (2026-07-28) — REVERT: delete data-align="figma" from #cmBoard and this block ====
   Moves Signal/Context from x=270 to x=218 so they line up with the left edge of the "2. Revenue Campaign
   Execution" pill, which also pulls the feed arrows clear of Ava's glow disc (60px of arrow now sits outside
   it, was 8px). The opportunity column and the converge bracket move with it — see FIGMA_ALIGN in
   campaign-model.js, which reads the same data-align attribute. Removing the attribute restores everything. */
[data-align="figma"] .cm-chip{left:218px !important}
[data-align="figma"] .cm-list{left:218px !important}
/* ==== end left-column alignment ==== */

/* Ava orb + glow (reused from homepage) */
/* Ava composition — Figma 530-24619: orb floating on a stack of glow layers
   (blue underglow #7C98F8 blur, solid #F1F3FF halo, blurred #527EFF mid-glow) */
.cm-ava{position:absolute;left:595px;top:235px;width:188px;height:188px;margin:-94px 0 0 -94px;z-index:2}
.cm-ava-glow{position:absolute;inset:0;opacity:0;transform:scale(.6);transition:opacity .8s ease, transform .8s ease}
.cm-ava-glow.on{opacity:1;transform:scale(1)}
.cm-ava-glow>*{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);pointer-events:none}
/* underglow — Figma 530:24611: #7C98F8 pill, 407x176, blur(42px), opacity .6, centred 7px above the orb.
   Kept as a gradient rather than a real filter:blur() so it renders once and doesn't re-rasterize on every
   scroll frame (the parent scales on reveal). To match the blur's PROFILE the gradient holds a plateau at
   full alpha out to 58% and only then falls off, instead of fading from the centre — a 42px blur on a solid
   pill leaves the core opaque. Sized 520x224 = the Figma 407x176 scaled by 240/188 (our orb is 240, Figma's 188). */
/* Sized to the Figma pill INCLUDING its blur bleed, not to the pill alone: 407x176 with blur(42) reads out to
   245x130 from centre, x1.2766 (our orb 240 vs Figma 188) = 628x332. It stays SHORTER than the 463 halo on
   purpose, so blue only shows as two lobes left and right and never floods above or below — that containment
   is what keeps the halo edge readable. (880x760 flooded it; 520x225 clipped the bleed and read as a sliver.)
   Stops are matched to a measured scan of the Figma render: alpha .43 where the halo edge falls (74% of the
   radius) so the step there is ~50 units, close to Figma's 44, instead of the 54 that read as a hard circle.
   2026-07-28: SCALE = FIGMA 1:1. Proven by the stage pills (Figma 262 = ours 262) and by Figma's "Graphic"
   frame (674:2329) being 1360 wide = our .frame content width. An earlier pass wrongly derived 0.82 by
   comparing our 1240 board to Figma's 1512 PAGE frame; the badge match (88x0.82=72) was a coincidence and
   the badges are simply undersized. Orb 188, halo 362, mid 456x368, under 492x260 — all Figma values.
   OLD 2026-07-28 note: The whole graphic is built at 1240/1512 = 0.82 of the Figma frame
   (674:2036 "Desktop - Chosen one", 1512 wide) — the channel bubbles prove it: Figma 88 x 0.82 = our 72.
   The orb alone had been built at 240 when 188 x 0.82 = 156, i.e. 1.28x too big, and every glow tweak before
   this was compensating for that. Orb 240->156, halo 356->296, mid 448x364->372x304, under 484x256->404x212.
   halo:orb is back to Figma's 1.93, and the clearances land at 31px left / 38px right, against Figma's
   30 / 34 at this scale. Do not resize one layer alone: they all derive from the 0.82 board scale. */
.cm-ava-under{width:492px;height:260px;margin-top:-8px;border-radius:50%;
  background:radial-gradient(closest-side, rgba(124,152,248,.58) 0%, rgba(124,152,248,.54) 45%, rgba(124,152,248,.43) 74%, rgba(124,152,248,0) 100%);
  opacity:1}
/* halo = a SOLID #F1F3FF disc. It must stay OPAQUE: the whole effect is that it punches a pale disc out of the
   blue field behind it, and that boundary IS the contrast (a soft arc, bluer outside / paler inside).
   Lowering its opacity lets blue bleed through and flattens the edge — tried .45, it kills the effect. */
.cm-ava-halo{width:362px;height:362px;opacity:1}
.cm-ava-mid{width:456px;height:368px}
/* rim glow: the orb PNG has clean circular alpha (transparent corners), so drop-shadow hugs its edge exactly.
   A tight shadow + a wide one = the concentrated edge light that makes the sphere read as lit, which a diffuse
   field behind it can't do on its own. Not in Figma; this is the "more than the file" part. */
.cm-ava-img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;opacity:0;transform:scale(.72);
  filter:drop-shadow(0 0 14px rgba(58,111,255,.6)) drop-shadow(0 0 52px rgba(58,111,255,.5));
  transition:opacity .7s ease, transform .7s cubic-bezier(.2,.9,.3,1.2)}
.cm-ava-img.on{opacity:1;transform:scale(1)}
.cm-ava.pulse-run .cm-ava-glow.on{animation:cmGlow 3.2s ease-in-out infinite}
@keyframes cmGlow{0%,100%{opacity:.8}50%{opacity:1}}

/* orbiting channel badges */
/* channel bubble — style from Figma 486-4452: translucent surface-tinted frosted glass circle */
/* coords are relative to .cm-ava (they were re-based from .cm-board on 2026-08-06 when the
   badges were nested inside the orb, so they straddle it at ANY size incl. mobile) */
.cm-badges{position:absolute;inset:0;pointer-events:none}
.cm-badge{position:absolute;width:72px;height:72px;border-radius:50%;
  background:rgba(206,217,252,.38);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);   /* frosted glass over the orb (Figma 530-24624) */
  border:1px solid rgba(255,255,255,.5);display:flex;align-items:center;justify-content:center;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.45), 0 8px 22px rgba(36, 69, 157,.10);z-index:3;opacity:0;transform:scale(.4);transition:opacity .5s ease, transform .5s ease}
.cm-badge.on{opacity:1;transform:scale(1)}
/* heartbeat when the pulse reaches Ava — reinforces she's a multimodal agent (a lub-dub double thump, staggered across the 3 channels) */
.cm-badge.beat{animation:cmBeat .9s ease-out}
.cm-badge.b2.beat{animation-delay:.08s}
.cm-badge.b3.beat{animation-delay:.16s}
@keyframes cmBeat{0%{transform:scale(1)}14%{transform:scale(1.18)}28%{transform:scale(1)}42%{transform:scale(1.12)}56%,100%{transform:scale(1)}}
.cm-badge svg{width:30px;height:30px;fill:var(--white)}
.cm-badge.b1{left:-8px;top:-25px}   /* on the same circle as b2/b3: its centre sat 164 from the orb centre against their 104-109, so it floated clear of the sphere instead of straddling it */    /* phone: straddles the orb's upper-left edge (Figma 530-24618) */
.cm-badge.b2{left:148px;top:-3px}   /* text: straddles the right edge */
.cm-badge.b3{left:-28px;top:117px}   /* email: straddles the lower-left edge */

/* center caption under the orb */
.cm-cap{position:absolute;left:385px;top:400px;width:420px;text-align:center;z-index:3;font-family:var(--sans);opacity:0;transition:opacity .5s ease}
/* Ava caption — style from Figma 530-24493: Geist Medium 18/28 (title ink + subtitle action),
   Geist Regular 14/23 ink for the detail, 16px gap, centred */
.cm-cap .t{display:block;font-family:var(--sans);font-weight:500;font-size:18px;line-height:28px;color:var(--ink)}
.cm-cap .s{display:block;font-family:var(--sans);font-weight:400;font-size:18px;line-height:28px;color:var(--action)}
.cm-cap .d{display:block;font-family:var(--sans);font-weight:300;font-size:14px;line-height:20px;color:var(--ink);margin-top:16px}

/* WORKS THE DEAL outcomes */
.cm-deal{position:absolute;left:782px;top:150px;width:240px;z-index:3;font-family:var(--sans)}
/* Works the deal + outcome boxes — style from Figma 541-25074: Geist Regular 12/26 1px-tracked
   uppercase ink label; filled #E1E8FA square boxes, 8x16 padding, centred check + Geist 14/26 ink */
.cm-deal .cm-deal-h{margin:0 0 8px 44px;font-weight:400;font-size:12px;line-height:26px;letter-spacing:1px;text-transform:uppercase;color:var(--ink);text-align:center;opacity:0;transition:opacity .5s ease}
.cm-out-row{display:flex;align-items:center;justify-content:center;gap:9px;height:40px;padding:0 12px;margin:0 0 4px 44px;white-space:nowrap;border-radius:var(--radius-sm);
  background:var(--panel);font-weight:400;font-size:14px;line-height:26px;color:var(--ink);
  opacity:0;transform:translateY(8px);transition:opacity .45s ease, transform .45s ease}
.cm-out-row.on{opacity:1;transform:none}
.cm-out-row svg{width:16px;height:16px;stroke:var(--ink);flex:none}

/* Stage 3 — self-improving */
.cm-loop{position:absolute;left:1120px;top:190px;width:150px;z-index:3;font-family:var(--sans);opacity:0;transition:opacity .5s ease}
.cm-loop-ic{width:22px;height:22px;color:var(--canvas);margin-bottom:14px}   /* Figma cycle icon 536-24746, fill #7C98F8 */
.cm-loop-ic svg{width:100%;height:100%;fill:currentColor}@keyframes cmSpin{from{transform:rotate(0)}to{transform:rotate(360deg)}}
.cm-loop p{margin:0;font-family:var(--sans);font-weight:300;font-size:14px;line-height:20px;color:var(--ink)}   /* Figma 530-24500: Geist 14/20 ink, "A self-improving system" = Medium */
.cm-loop p strong{font-weight:500}

/* ========================= HOW-IT-WORKS content sections (below the campaign model) =========================
   Reuse .cat-eyebrow / .cm-h / .cm-sub type + the 1728px frame + tokens. All spacing on a 4px grid. */
.hiw-sec{position:relative;z-index:1}
/* page frame comes from the shared .frame in shell.css (1408 + 24px) */
.hiw-head{max-width:calc(50% - 48px)}   /* heading + sub live in the left column only (matches the 1fr 1fr grid column) */
/* S1 — the agent · Figma 815:16549 -------------------------------------
   A light dotted field with two 704 panels that tile the 1408 frame exactly
   (704+704) but sit at DIFFERENT heights: the light one 110px above the dark
   one. That offset is the whole composition, so it is kept literally on
   desktop and dropped the moment the panels stack. */
.hiw-agent{position:relative;overflow:hidden;background:var(--surface)}
/* the dot field is the Figma pattern verbatim: a 14x14 rounded square (rx 3)
   in a 41.44 tile at 50% opacity, painted at a 6.216px repeat. The footer has
   its own sparser 10px radial-dot texture — deliberately a different density,
   not the same thing re-skinned. */
.hiw-agent::before{content:none}   /* v3: the band moved to .hiw-agent-shot::before so it tracks the video, not the section */
.hiw-agent-in{position:relative;padding-top:120px;padding-bottom:128px}
/* ---- REBUILT 2026-08-13 (Figma 926-18267): copy top-left, demo video as the hero ---------
   The dark ink panel, its rule, and the two-column copy split are gone. Figma's text block
   starts at x=77 on a 1512 page — which IS the frame's content edge (76), so the copy simply
   sits at the frame edge. Video: 1216x620 (the mp4's own 1.96:1), right-aligned to the frame.
   Figma shows it bleeding ~23px past the content edge; not measured deliberately (Victoria:
   "finding the creative direction"), so it rides the grid instead. -------------------------- */
/* v3 of the section (2026-08-13, Victoria's Figma iteration): heading + lead CENTRED above
   the demo, the demo CENTRED, and the remaining copy moves BELOW it as a left-aligned block
   with a vertical rule. */
.hiw-agent-copy{position:relative;z-index:1;text-align:center}
.hiw-agent-copy h2{margin:0 auto 32px;max-width:602px;
  font-family:var(--display);font-weight:500;font-size:40px;line-height:48px;color:var(--ink)}
.hiw-agent-copy .lead{margin:0 auto;max-width:568px;
  font-family:var(--sans);font-weight:400;font-size:16px;line-height:24px;color:var(--deep)}
.hiw-agent-after{position:relative;z-index:1;margin-top:192px;max-width:678px;
  border-left:1px solid var(--soft);padding-left:44px}   /* text lands at Figma's x=122: frame edge + rule + 44 */
.hiw-agent-after h3{margin:0 0 8px;font-family:var(--sans);font-weight:500;font-size:20px;line-height:24px;color:var(--deep)}   /* Geist Medium 20/24 (Figma), tight to its paragraph */
.hiw-agent-after p{margin:0 0 24px;font-family:var(--sans);font-weight:400;font-size:16px;line-height:24px;color:var(--deep)}
.hiw-agent-after p:last-child{margin-bottom:0}
.hiw-agent-shot{position:relative;width:1216px;max-width:100%;margin:72px auto 0}   /* centred; 72 gap from the lead (Figma 929-18563) */
/* the dot band rides WITH the video (Figma: starts ~30% into it, runs 112px past its bottom),
   full-bleed across the viewport; the copy below sits on clean surface. Same tile as before. */
.hiw-agent-shot::before{content:"";position:absolute;top:30%;bottom:-112px;left:50%;width:100vw;transform:translateX(-50%);pointer-events:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 41.44 41.44'%3E%3Crect width='14' height='14' rx='3' fill='%233A6FFF' fill-opacity='.5'/%3E%3C/svg%3E");
  background-size:6.216px 6.216px}

/* the video's cast shadow — same blurred ellipse as before, retuned to the big frame:
   centred under the bottom edge, sized to the 1216 width */
.hiw-agent-glow{position:absolute;left:50%;bottom:-16px;width:62%;height:96px;
  transform:translateX(-50%);border-radius:50%;background:rgba(124,152,248,.5);filter:blur(32px);
  z-index:0;pointer-events:none}
.hiw-agent-shot video{position:relative;z-index:1;display:block;width:100%;height:auto;border-radius:var(--radius-sm)}
@media (max-width:1024px){
  .hiw-agent-copy h2{font-size:28px;line-height:34px}   /* same step as .panel-content .shift-h on the homepage */
}
@media (max-width:900px){
  .hiw-agent-in{padding-top:96px;padding-bottom:96px}
  .hiw-agent-shot{margin-top:48px}   /* stacked: the demo still leads with a clear beat below the copy */
}/* 03 — the team: light head, then the blue canvas begins behind the cards */
.hiw-team{padding:160px 0 40px;background:var(--surface);position:relative;z-index:2}   /* light; lifted above the blue canvas so the cards straddle the wave */
.hiw-teamhead-title{max-width:calc(50% - 48px)}                      /* eyebrow + headline span the left half */
.hiw-teamhead-cols{margin-top:16px;max-width:calc(50% - 48px)}   /* supporting paragraph in the left column only (matches the title width) */
.hiw-teamhead-cols .cm-sub{max-width:none;margin:0}
@media (max-width:1024px){ .hiw-teamhead-title,.hiw-teamhead-cols,.hiw-head{max-width:none} }
@media (max-width:900px){ .hiw-team{padding-top:120px} }
.hiw-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:24px;margin-top:56px;position:relative;z-index:2;margin-bottom:-360px}   /* 24px gaps; cards straddle the wave — bottom overlaps the blue canvas */
.hiw-card{padding:36px 24px 40px;display:flex;flex-direction:column;background:var(--white);border-radius:var(--radius-md)}
.hiw-card h3{order:2;font-family:var(--sans);font-weight:400;font-size:24px;line-height:30px;color:var(--deep);margin:0 0 12px}   /* 24/30 matches .hiw-step h3 on this page */
.hiw-card-ico{order:1;margin:0 0 48px;min-height:180px;display:flex;align-items:center;justify-content:center}   /* first now, so no top margin. min-height keeps all four titles level whatever each graphic measures */
.hiw-card-ico .spiro-svg{width:176px;height:176px;display:block;animation:spiro-spin 52s linear infinite}   /* generated in hiw-shapes.js; slow continuous rotation */
@keyframes spiro-spin{to{transform:rotate(360deg)}}
/* The Figma graphic is one filled path of dots, not a stroke, so it cannot be "drawn" with
   stroke-dashoffset. A diagonal mask swept across it gives the same read: the contour appears
   from the bottom-left corner outward, along the shape's own diagonal. */
.hiw-card-fig img{display:block;
  -webkit-mask-image:linear-gradient(160deg,#000 0 35%,transparent 62%);
          mask-image:linear-gradient(160deg,#000 0 35%,transparent 62%);
  -webkit-mask-size:300% 300%;        mask-size:300% 300%;
  -webkit-mask-position:100% 100%;    mask-position:100% 100%}
.hiw-card.in .hiw-card-fig img{
  -webkit-transition:-webkit-mask-position 1.4s ease .25s;
          transition:mask-position 1.4s ease .25s;
  -webkit-mask-position:0% 0%;        mask-position:0% 0%}
/* Idle motion once the sweep has drawn them in: the whole graphic breathes, scaling between .93
   and 1.07 about its centre. Alternating so it eases back instead of resetting with a jump.
   Each card runs a different duration so they never pulse in unison. */
@keyframes hiwFigDrift{
  from{transform:scale(.93)}
  to  {transform:scale(1.07)}
}
.hiw-card.in .hiw-card-fig img{animation:hiwFigDrift 4.5s ease-in-out 1.6s infinite alternate}
.hiw-cards .hiw-card:nth-child(2).in .hiw-card-fig img{animation-duration:5.5s;animation-delay:2.4s}   /* third to start */
.hiw-cards .hiw-card:nth-child(3).in .hiw-card-fig img{animation-duration:5s;animation-delay:2s}      /* second to start */
.hiw-cards .hiw-card:nth-child(4).in .hiw-card-fig img{animation-duration:6s;animation-delay:2.8s}    /* last */

@media (prefers-reduced-motion:reduce){
  .hiw-card-fig img{-webkit-mask-image:none;mask-image:none;transition:none;animation:none}
  .hiw-card.in .hiw-card-fig img{animation:none}
}
/* the 4 boxes disclose on their own stagger (reveal + shell.css .reveal) */
.hiw-cards .hiw-card:nth-child(2){transition-delay:.08s}   /* the graphic sweep picks this up too */
.hiw-cards .hiw-card:nth-child(3){transition-delay:.16s}
.hiw-cards .hiw-card:nth-child(4){transition-delay:.24s}
.hiw-steps .hiw-step:nth-child(2){transition-delay:.08s}
.hiw-steps .hiw-step:nth-child(3){transition-delay:.16s}
.hiw-card .cm-sub{order:3;margin:0;max-width:none}   /* reuse the body type (.cm-sub); card adds layout only */
/* ---- team cards: 4-up → 2-up (tablet) → 1-up (mobile). The 4-up grid ran off screen below ~1100px.
       margin-bottom shrinks with the column count: cards get shorter as they widen, so the straddle
       over the wave has to shrink too or the last card ends up almost entirely on the dark. ---- */
@media (max-width:1180px){
  /* 1180 not 1024: below this the 4-up gives ~245px cards and the 28px headings wrap to three lines.
     1180 also covers the 11" iPad in landscape. */
  .hiw-cards{grid-template-columns:repeat(2,1fr);margin-bottom:-300px}   /* -300 keeps the straddle at 58-75% of the card across 360-1180, matching the ~71% the 4-up has at desktop */
  .hiw-cards .hiw-card:nth-child(3){transition-delay:0s}
  .hiw-cards .hiw-card:nth-child(4){transition-delay:.08s}
}
@media (max-width:640px){
  .hiw-cards{grid-template-columns:1fr}
  .hiw-cards .hiw-card:nth-child(2),
  .hiw-cards .hiw-card:nth-child(3),
  .hiw-cards .hiw-card:nth-child(4){transition-delay:0s}   /* stacked: each card reveals on its own scroll-in, no row stagger */
}
/* ---- lower (dark) sections 3-5 + footer float on one gradient ---- */
.hiw-lower{position:relative;z-index:1;margin-top:-4px;padding-top:440px;overflow-x:clip;   /* margin-top:-4px overlaps the team section to kill the subpixel seam at the boundary; overflow-x:clip stops the section-05 glow widening the page */
  background:radial-gradient(ellipse 92.7% 36.9% at 67% 46.3%,
    var(--deep) 3.9%, #19306C 57.7%, #010510 100%) var(--void)}
/* S3 — what it takes (live in weeks) + FIRST/THEN/ONGOING columns.
   Moved ABOVE the team section 2026-08-11 (Tony: product -> promise -> how the team
   delivers it) and restyled for the light region — headings/labels inherit the light-page
   ink instead of the old dark-canvas white/soft overrides. */
.hiw-weeks{padding:120px 0 0;background:var(--surface)}   /* 120 top after the agent canvas; bottom air comes from .hiw-team's own 160px top padding */
@media (max-width:900px){ .hiw-lower{padding-top:360px} }   /* 440 clears the desktop -360 card overhang into the dark canvas; mobile only overhangs -300 */
.hiw-steps{display:grid;grid-template-columns:repeat(3,1fr);gap:48px;margin-top:72px}
.hiw-step{border-top:1px solid var(--soft);padding-top:24px}
.hiw-step .lbl{display:block;font-family:var(--sans);font-weight:500;font-size:12px;line-height:26px;text-transform:uppercase;color:var(--deep);margin-bottom:4px}
.hiw-step h3{font-family:var(--sans);font-weight:400;font-size:24px;line-height:30px;color:var(--ink);margin:0 0 28px}
.hiw-step .cm-sub{margin:0;max-width:none}   /* reuse the body type (.cm-sub); --soft comes from the .hiw-weeks override */
/* S5 — the new alternative: a solid --ink box floating on the blue wave (Figma 630:27921) */
.hiw-alt{position:relative;padding:96px 0;text-align:center}
.hiw-alt-box{position:relative;background:var(--ink);border-radius:var(--radius-sm);padding:112px 128px 96px}   /* solid box on the wave (no z-index → the glow ::before drops fully BEHIND this opaque box, not onto its face) */
/* soft blue sphere of light behind the box (Figma ellipse 630:23703) — pure CSS radial glow, no image.
   sits behind the opaque box so only the halo bleeds out, backlighting it against the dark wave */
.hiw-alt-box::before{content:"";position:absolute;z-index:-1;pointer-events:none;
  left:50%;top:50%;transform:translate(-50%,-50%);
  width:calc(100% + 560px);height:calc(100% + 560px);border-radius:50%;
  background:radial-gradient(ellipse closest-side at center,
    rgba(120,162,255,.98) 0%, rgba(103,146,255,.88) 14%, rgba(66,122,255,.7) 34%,
    rgba(58,111,255,.46) 46%, rgba(58,111,255,.26) 56%, rgba(58,111,255,.14) 66%,
    rgba(58,111,255,.07) 76%, rgba(58,111,255,.03) 86%, rgba(58,111,255,.01) 94%,
    rgba(58,111,255,0) 100%)}
.hiw-alt-inner{max-width:680px;margin:0 auto;display:flex;flex-direction:column;align-items:center;gap:48px}
.hiw-alt-titlegroup{display:flex;flex-direction:column;align-items:center;gap:12px;width:100%}
.hiw-alt h2{font-family:var(--display);font-weight:500;font-size:40px;line-height:44px;color:var(--white);margin:0;max-width:680px}
.hiw-alt .lead{font-family:var(--sans);font-weight:300;font-size:16px;line-height:24px;color:var(--soft);margin:0;max-width:680px}
.hiw-alt-emph{margin:0}
.hiw-alt-emph svg{width:32px;height:32px;stroke:var(--surface);fill:none;margin-bottom:8px}
.hiw-alt-emph p{font-family:var(--sans);font-weight:400;font-size:20px;line-height:32px;color:var(--surface);margin:0}   /* 20/32, the site's standard 20px pairing */
@media(max-width:640px){
  .hiw-alt{padding:56px 0}
  .hiw-alt-box{padding:56px 24px}
  .hiw-alt-inner{gap:32px}
  .hiw-alt h2{font-size:30px;line-height:1.12}
}

/* ---- mobile: drop the pin, stack, play each block on scroll-in ---- */
@media (max-width:900px){
  .cm-track{height:auto}
  .cm-sticky{position:static;height:auto;min-height:0;padding:72px 0;display:block}
  .cm-board-wrap{height:auto;margin-top:32px}
  .cm-board{position:static;width:100%;margin:0;height:auto;transform:none!important;display:flex;flex-direction:column;gap:28px}
  .cm-svg,.cm-particles{display:none}
  .cm-chip,.cm-list,.cm-ava,.cm-cap,.cm-deal,.cm-loop,.cm-opps{position:static;width:auto}
  .cm-opp{opacity:1;transform:none}
  .cm-opp.on .cm-opp-dot,.cm-opp.lit .cm-opp-dot{opacity:1;transform:none}
  /* .cm-ava must stay POSITIONED. The line above sets the stacked blocks to position:static, but
     .cm-ava's children (.cm-ava-glow and .cm-ava-img) are absolute/inset:0, so a static parent sent
     them up to .cm-board for their containing block and the orb rendered ~400px wide over the section. */
  .cm-ava{position:relative;left:auto;top:auto;width:116px;height:116px;margin:24px auto 0}   /* left/top MUST be reset: the desktop rule sets left:595px;top:235px, which position:static made inert but position:relative re-applies as an offset */
  /* the glow layers carry desktop pixel sizes (463-640px) and are centre-translated, so they spill
     past the 220px box on a phone. Scaled to sit inside the mobile column. */
  .cm-ava-under{width:304px;height:160px;margin-top:-4px}   /* desktop 404x212 scaled to clear the 312px column at a 360px viewport */
  .cm-ava-halo{width:288px;height:288px}
  .cm-ava-mid{width:320px;height:260px}

  .cm-stages{flex-direction:column}
  .cm-stages .cm-p1,.cm-stages .cm-p2,.cm-stages .cm-p3{flex:0 0 auto}   /* drop the fixed 262px so pills stack full-width on mobile */
  .cm-stages .cm-p2{justify-content:center}

  /* ---- Stacked, interleaved with the stage pills (2026-08-06) -----------------------
     The pills live in .cm-stages and their content in .cm-board > .cm-g, i.e. different
     parents, so `order` alone cannot interleave them. display:contents dissolves those
     wrappers so every block becomes a direct flex item of .cm-frame, which can then put
     each pill directly above the content it labels.
     The desktop scroll choreography is skipped here: it drives a pinned board that does
     not exist once this is static, so everything is forced to its final state instead of
     waiting for a reveal that will not come. */
  .cm-frame{display:flex;flex-direction:column;gap:16px}
  .cm-stages,.cm-board-wrap,.cm-board,.cm-g{display:contents}
  .cm-head{order:0;margin-bottom:24px}
  .cm-stages .cm-p1{order:1}
  .cm-opps{order:2;text-align:center}

  /* the bracket joining stage 1 to stage 2. Borders, not an SVG: it is three straight dashed
     lines, so a box with dashed left/right/bottom plus one dashed drop draws it exactly,
     scales with the column, and costs no extra request. */
  .cm-connect{display:block;order:3;position:relative;height:56px;margin:0}   /* no margin: the flex column already supplies a 24px gap, so the bracket sits exactly 24px under the label */
  .cm-connect::before{content:"";position:absolute;left:18%;right:18%;top:0;height:26px;
    border-left:1px dashed var(--soft);border-right:1px dashed var(--soft);border-bottom:1px dashed var(--soft)}
  .cm-connect::after{content:"";position:absolute;left:50%;top:26px;height:26px;
    border-left:1px dashed var(--soft)}
  .cm-opp{justify-content:center;height:auto}   /* the rule under "Sales Assisted PLG" is a desktop device; centred and rule-less on phones. height:auto too — the 48px row is a desktop measure and left ~22px of dead space under the label, which is what made the bracket read as detached. */
  .cm-opps-eyebrow{margin-bottom:8px}   /* was 12: tuck the eyebrow onto its label */
  .cm-opp-dot{display:none}                            /* its emitter dot belongs to the desktop trunk graphic */
  .cm-stages .cm-p2{order:4}
  .cm-badges{order:6}
  .cm-ava{order:7}
  .cm-cap{order:8}

  /* the three dashed drops from Ava into the outcomes. Same technique as .cm-connect: straight
     dashed lines are borders, so no SVG and no extra request. The dot is a ::after on each. */
  .cm-out-row,.cm-deal .cm-deal-h{margin-left:0}   /* the desktop connector lane does not exist here */
  .cm-drops{display:flex;order:9;justify-content:center;gap:64px;height:32px;margin:0}   /* height 32, was 72. margin 0 so the 16px column gap is the only spacing above AND below */
  .cm-drops span{position:relative;width:0;border-left:1px dashed var(--soft)}
  .cm-drops span::after{content:"";position:absolute;left:-4px;bottom:-4px;width:8px;height:8px;
    border-radius:50%;background:var(--canvas)}
  .cm-deal{order:10}
  /* second bracket: gathers the three outcomes back into one line and hands off to stage 3.
     Identical shape to .cm-connect above, so it is the same class with only its order changed:
     one dashed rule with the ends rising into the outcomes box and a drop into stage 3. */
  .cm-connect-b{order:10}
  .cm-stages .cm-p3{order:11}
  /* stage 3 puts its cycle icon and its sentence on one line here rather than stacked: the
     22px icon on the left, the copy beside it, the pair centred like the rest of the column. */
  .cm-loop{order:12;display:flex;align-items:center;justify-content:center;gap:20px;text-align:left}
  .cm-loop-ic{flex:none;margin-bottom:0}   /* the 14px gap below it is the stacked desktop measure */

  /* SIGNAL and CONTEXT sit side by side, as in the mobile design */
  .cm-signals{order:5;display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:start}
  .cm-pair{display:flex;flex-direction:column;gap:16px}   /* 16, was 8: the chip needs to breathe away from the label under it */
  .cm-chip{width:100%}
  .cm-list{width:auto}

  /* the three bubbles straddle the orb (nested inside .cm-ava), scaled to the mobile size:
     the orb is 176 here against 188 on desktop, and the badges 56 against 72 — the same 0.78
     ratio, so they sit on the same points of its edge. */
  .cm-ava{width:176px;height:176px}
  .cm-badges{display:block}
  .cm-badge{display:flex;width:56px;height:56px;opacity:1 !important;transform:none !important}
  .cm-badge.b1{left:7px;top:-7px}   /* same correction at mobile scale: was 125 from centre against b2/b3 at 81-86 */
  .cm-badge.b2{left:133px;top:15px}
  .cm-badge.b3{left:-5px;top:108px}

  /* everything the scroll sequence would have revealed, shown outright.
     !important because campaign-model.js writes inline opacity for the desktop sequence. */
  .cm-cap,.cm-loop,.cm-chip,.cm-list h4,.cm-list li,.cm-ava-glow,.cm-ava-img,
  .cm-deal .cm-deal-h,.cm-out-row,.cm-opp{opacity:1 !important;transform:none !important}
  .cm-cap{position:static;width:auto;text-align:center}
  .cm-loop{position:static;width:auto}
}

/* ---- mobile overrides that must outrank the base rules above, so they sit at the end ---- */
@media (max-width:900px){
  .hiw-card h3,
  .hiw-step h3{font-size:20px;line-height:32px}   /* 20/32 is the site's existing 20px pairing; 24 competed with the section heading */
  .hiw-steps{grid-template-columns:1fr;gap:40px;margin-top:80px}   /* stacked: 3-up gives ~14 characters a line on a phone. 80 so the first rule clears the copy above it */
  .hiw-steps .hiw-step:nth-child(2),
  .hiw-steps .hiw-step:nth-child(3){transition-delay:0s}          /* each reveals on its own scroll-in */
}

/* the closer sat almost directly on the dark alt box above it (Victoria, 2026-08-13) */
.closer{padding-top:184px}
