/* ===========================================================================
   PAGE · /carly/free/  —  CARLY LAUNCH CAMPAIGN LANDING PAGE   (.cf-* family)
   ---------------------------------------------------------------------------
   Built 2026-08-05 for the Carly launch campaign (social + paid ads).
   Runs on layouts/base-w-lp.njk (stripped chrome), and opts into the two
   shared components rather than cloning either:
     sharedCSS: [ss-statcard, ss-integrations]   sharedJS: [ss-statcard]

   WHAT THIS SHEET OWNS: the split hero, the section rhythm, the step list,
   the caption scene, the offer block, the results tiers and the CTA contrast
   pair. Everything with an .ss-* class name is borrowed and must NOT be
   restyled here beyond grid gaps — those sheets are shared with three other
   pages and a "small tweak" here lands on all of them.

   Only --w-* tokens. No raw brand hex outside the .cz-light block, which is
   the canonical light-band declaration lifted verbatim from carly.css.
   =========================================================================== */

:root{
  /* Page-scoped asset tokens (D51 — image files are shared, the custom
     properties are declared per page because canonical ds7.css omits them).
     --w-img-av-keegan IS global in ds7.css; --w-img-av-jon is not. */
  --w-img-av-jon:url("/assets/images/w/av-jon.webp");
  --w-img-logo-google: url("/assets/images/w/logo-google.svg");
  --w-img-logo-highspot: url("/assets/images/w/logo-highspot.svg");
  --w-img-logo-outreach: url("/assets/images/w/logo-outreach.png");
  --w-img-logo-seismic: url("/assets/images/w/logo-seismic.svg");
  --w-img-logo-sixsense: url("/assets/images/w/logo-sixsense.svg");

  /* standardized rhythm token, same value the Carly solutions pages use */
  --w-section-head-gap:clamp(40px,4vw,56px);
}

html{overflow-x:clip}   /* the marquee track is wider than the viewport; clip keeps sticky working */

/* ===== per-section LIGHT band — canonical declaration, lifted verbatim from carly.css =====
   Re-declares the foundation light tokens in scope so a single section renders light inside
   the dark-default page and every --w-* component inside it flips. Pair with
   data-nav-surface="light" on the section. */
.cz-light{
  background:var(--w-bg);color:var(--w-text);
  --w-bg:#f5f5f5; --w-bg-deep:#ebebeb; --w-bg-elev:#fafafa;
  --w-card:#ffffff; --w-card-lo:#efefef; --w-card-hi:#ffffff;
  --w-text:var(--w-charcoal); --w-text-2:rgba(28,26,36,0.66); --w-text-3:rgba(28,26,36,0.62);
  --w-text-prose:#302d2e; --w-text-on-brand:#ffffff; --w-icon-ink:var(--w-charcoal);
  --w-line-soft:rgba(28,26,36,0.06); --w-line:rgba(28,26,36,0.10); --w-line-strong:rgba(28,26,36,0.16); --w-edge-top:rgba(255,255,255,0.9);
  --w-brand:var(--w-purple-ink); --w-brand-2:var(--w-purple); --w-brand-soft:rgba(152,135,244,0.10); --w-brand-line:rgba(152,135,244,0.28);
  --w-shadow-raise:0 8px 18px -8px rgba(28,26,36,0.07), inset 0 1px 0 rgba(255,255,255,0.9);
  --w-shadow-raise-soft:0 4px 10px -6px rgba(28,26,36,0.05), inset 0 1px 0 rgba(255,255,255,0.85);
  --w-shadow-recess:inset 0 1px 3px rgba(28,26,36,0.05), inset 0 -1px 0 rgba(255,255,255,0.8);
  --w-shadow-recess-deep:inset 0 2px 5px rgba(28,26,36,0.07), inset 0 -1px 0 rgba(255,255,255,0.7);
  --w-shadow-sm:0 1px 2px rgba(28,26,36,0.04); --w-shadow-md:0 4px 12px rgba(28,26,36,0.05); --w-shadow-lg:0 12px 28px rgba(28,26,36,0.07);
  --w-glow-brand:0 2px 8px rgba(28,26,36,0.05); --w-glow-brand-strong:0 6px 16px rgba(28,26,36,0.07);
  --w-glass-fill:rgba(255,255,255,0.66); --w-glass-fill-strong:rgba(255,255,255,0.86); --w-glass-tint:rgba(28,26,36,0.90);
  --w-glass-fill-soft:rgba(28,26,36,0.03); --w-glass-line:rgba(28,26,36,0.10); --w-glass-line-bright:rgba(28,26,36,0.16);
  --w-glass-rim-top:rgba(255,255,255,0.95); --w-glass-rim-bottom:rgba(28,26,36,0.05);
  --w-glass-blur:blur(18px) saturate(140%); --w-glass-blur-lg:blur(22px) saturate(145%);
  --w-glass-shadow:0 10px 24px rgba(28,26,36,0.06); --w-glass-shadow-soft:0 4px 12px rgba(28,26,36,0.05);
  --w-cta-fill:var(--w-glass-tint); --w-cta-text:#ffffff; --w-cta-glow:var(--w-shadow-md); --w-cta-glow-strong:var(--w-shadow-lg);
  --w-card-brand-wash:linear-gradient(160deg, rgba(28,26,36,0.06), rgba(28,26,36,0.015)); --w-card-brand-line:var(--w-line-strong);
  --w-tag-brand-bg:rgba(28,26,36,0.06); --w-tag-brand-fg:var(--w-text); --w-focus:rgba(28,26,36,0.55);
  --w-grad-surface:linear-gradient(180deg, #ffffff 0%, #f5f5f5 100%);
  --w-grad-surface-hi:linear-gradient(180deg, #ffffff 0%, #fafafa 100%);
  --w-grad-recess:linear-gradient(180deg, #ededed 0%, #e3e3e3 100%);
}
@media (prefers-reduced-transparency: reduce){
  .cz-light .w-glass,.cz-light .w-btn--glass,.cz-light .w-tag,.cz-light .w-card,.cz-light .w-cta-band{background:var(--w-card);border-color:var(--w-line)}
}

/* ===== SECTION RHYTHM =====
   Asymmetric (tight top, generous bottom) — the approved house pattern. Tightened ~12% versus
   the Carly solutions pages: a landing page is read in one scroll, and their spacing is tuned
   for a reader who arrived deliberately and is willing to browse. */
.w-section{padding-block:clamp(46px,2.8vw + 1rem,74px) clamp(66px,4vw + 1.5rem,106px)}
/* head→content gap is owned by the grids, not the head, so every section matches */
.w-section-head{margin-bottom:0}
.cf-pain__grid,.cf-sol__grid,.cf-tl,.cf-offer__grid,.cf-res__lead,.ss-int__band{
  margin-top:var(--w-section-head-gap)}

/* ============ §1 · HERO — light band · rotating video · one proof stat =====
   REBUILT 2026-08-05. Previously a dark two-column split (copy left, product
   plate right) with a three-figure stat spine.

   THE STRUCTURE, top to bottom:
     .cf-hero          the band. Fills the viewport at desktop heights.
       .cf-hero__stage the video stack + its two-layer light wash + grain
       .cf-hero__inner a flex COLUMN, which is the whole trick:
         .cf-hero__copy   grows and centres its own content optically
         .cf-hero__floor  margin-top:auto, so it sits on the fold line

   WHY A FLEX COLUMN AND NOT A GRID: the floor has to touch the bottom of the
   viewport when there is spare height, and sit immediately under the copy when
   there is not. `margin-top:auto` inside a column flexbox does exactly that
   with no media query and no measurement — the gap collapses to zero the moment
   the content is taller than the box.

   The band is .cz-light in the markup, so every --w-* token inside it resolves
   to the light set (that declaration lives at the top of this file). The rest
   of the page is unchanged: §2 stays light, §3 goes dark, and so on.
   ------------------------------------------------------------------------- */
.cf-hero{position:relative;overflow:hidden;isolation:isolate;
  background:var(--w-bg);
  padding-block:clamp(20px,3vh,44px) 0}

/* Fill the viewport ONLY when there is a viewport worth filling. Two conditions,
   both required: wide enough that the composition isn't cramped, and tall enough
   that the floor lands on the fold instead of shoving the copy off the top.
   100svh (small viewport height) not 100vh — on iOS 100vh is measured against
   the COLLAPSED browser chrome, so a 100vh hero is permanently ~90px taller than
   the visible area and the logo bar sits below the fold, which is the exact
   opposite of the intent. */
@media(min-width:1025px) and (min-height:720px){
  /* the sticky nav is in flow above this section, so its height comes off the fill */
  .cf-hero{min-height:calc(100svh - 68px);display:flex;flex-direction:column}
  .cf-hero__inner{flex:1;display:flex;flex-direction:column}
  .cf-hero__copy{flex:1;display:flex;flex-direction:column;align-items:center;
    justify-content:center;
    /* optical centre, not mathematical: a stack under a heading reads as centred
       when it sits slightly ABOVE the true middle. Without this the copy looks
       like it has sunk. */
    padding-bottom:clamp(6px,1.4vh,22px)}
  .cf-hero__floor{margin-top:auto}
}

/* SHORT DESKTOP VIEWPORTS. A 1440x900 laptop leaves 832px once the nav is out,
   and the full-scale stack does not fit — the logo bar fell below the fold,
   which defeats the whole reason it is in the hero. Rather than let it overflow,
   the composition steps DOWN a size: the headline, the numeral and the mark all
   shrink together so the proportions hold and the floor still lands on the fold.
   This is the same move as scaling a poster to its frame; it is not a mobile
   breakpoint and must stay paired with the fill query above. */
@media(min-width:1025px) and (max-height:900px){
  .cf-hero__mark{width:clamp(42px,3.6vw,54px);height:clamp(42px,3.6vw,54px)}
  .cf-hero__h-a{font-size:clamp(38px,4.4vw,58px)}
  .cf-hero__h-b{font-size:clamp(22px,2.5vw,35px)}
  .cf-hero__lead{font-size:var(--w-fs-body);max-width:64ch}
  .cf-stat__v{font-size:clamp(52px,5.4vw,76px)}
  .cf-hero__badge{margin-top:var(--w-s-3)}
}

/* ---- the stage: video + wash ------------------------------------------- */
.cf-hero__stage{position:absolute;inset:0;z-index:0;overflow:hidden;pointer-events:none}
.cf-hero__scenes{position:absolute;inset:0}
/* Cross-fade, not cut. 900ms is slower than the homepage's 700ms because this
   band is light: on a bright wash a fast swap reads as a flicker. */
.cf-hero__scene{position:absolute;inset:0;opacity:0;
  transition:opacity .9s var(--w-ease);will-change:opacity}
.cf-hero__scene.is-active{opacity:1}
/* A very slow ken-burns push on the ACTIVE clip only. The clips are static
   compositions; without this the hero freezes between rotations. Paused on the
   inactive scenes so three videos are not animating off-screen. */
.cf-hero__vid{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transform:scale(1.06);transition:transform 8s linear}
.cf-hero__scene.is-active .cf-hero__vid{transform:scale(1.12)}

/* THE WASH IS TWO LAYERS. One flat white veil at the opacity the copy needs
   turns the footage to milk — the reason to pay 5MB for video is that people
   can see the people in it.
   Layer 1 (tint) keeps colour alive: a warm brand vignette pulled to the edges,
   so the corners stay photographic while the centre opens up.
   Layer 2 (wash) is a GENTLE global ramp — weakest at the top, resolving to a
   flat --w-bg at the very bottom so the hero dissolves into §2's light band
   instead of ending on a visible edge. That bottom stop is what replaces the
   .w-panel-rise seam the dark hero used to get.

   TUNED DOWN 2026-08-05 after looking at it. The first pass ran the wash at
   .58 → .95 to guarantee legibility everywhere, which made the footage a rumour:
   you could tell there was a person behind it and nothing more. Paying 5MB for a
   video and then hiding it is the worst of both. Legibility is now bought
   LOCALLY — a soft halo behind the copy stack only (.cf-hero__copy::before) —
   so the frame stays photographic at the edges where no text sits. If you raise
   these stops again, raise the halo instead. */
.cf-hero__tint{position:absolute;inset:0;
  background:
    radial-gradient(120% 90% at 50% 8%, rgba(255,255,255,0) 0%, rgba(233,221,255,.22) 62%, rgba(216,199,255,.40) 100%),
    linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.06))}
.cf-hero__wash{position:absolute;inset:0;
  background:linear-gradient(180deg,
    rgba(245,245,245,.26) 0%,
    rgba(245,245,245,.44) 30%,
    rgba(245,245,245,.66) 60%,
    rgba(245,245,245,.88) 86%,
    var(--w-bg) 100%)}
/* the same grain the homepage hero uses — it stops a large flat wash from
   banding on 8-bit displays, which is very visible on a light gradient */
.cf-hero__grain{position:absolute;inset:0;mix-blend-mode:multiply;opacity:.22;
  background-repeat:repeat;background-size:120px 120px;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='cfg'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23cfg)'/%3E%3C/svg%3E")}

.cf-hero__inner{position:relative;z-index:1;width:100%}

/* ---- copy stack --------------------------------------------------------- */
.cf-hero__copy{position:relative;display:flex;flex-direction:column;align-items:center;
  text-align:center;padding-block:clamp(12px,2.4vh,34px)}
/* THE LOCAL HALO. This is what makes a light-on-video hero work: instead of
   veiling the whole frame to protect the text, veil only the ellipse the text
   occupies and let the corners stay photographic. Elliptical and generously
   feathered so it never reads as a plate — if you can see its edge it is too
   tight. Sits at z-index:-1 (the stack has isolation via .cf-hero), so it is
   over the video and under every word. */
.cf-hero__copy::before{content:"";position:absolute;z-index:-1;
  inset:-8% -14%;pointer-events:none;
  background:radial-gradient(56% 60% at 50% 46%,
    rgba(248,248,250,.94) 0%, rgba(248,248,250,.80) 40%,
    rgba(248,248,250,.42) 66%, transparent 82%)}
/* THE GOGGLES. .w-mark--visor is a transparent PNG with no plate — the one asset
   in the system that is unmistakably Carly at 20px, which is the size it gets
   seen at in a feed. It opens the page. The drop-shadow (not box-shadow) follows
   the alpha channel, so the mark floats instead of sitting in an invisible box. */
.cf-hero__mark{width:clamp(52px,5vw,72px);height:clamp(52px,5vw,72px);
  filter:drop-shadow(0 10px 22px rgba(111,95,224,.30));
  animation:cfMarkIn .9s var(--w-ease) both}
@keyframes cfMarkIn{from{opacity:0;transform:translateY(-8px) scale(.9)}to{opacity:1;transform:none}}

.cf-hero__badge{margin-top:var(--w-s-4)}

/* TWO-VOICE H1 (D70) — line A the assertion in heavy sans, line B the answer in
   Instrument Serif italic on the brand ramp. The face + size drop IS the beat.
   Do not flatten line B back to sans, and do NOT put .w-accent--hero on it: that
   modifier is the bright lavender ramp built for dark bands and it vanishes on
   white (see feedback_ds7_gradient_numeral_traps). */
.cf-hero__h{margin:var(--w-s-4) 0 0;letter-spacing:-.025em;font-weight:var(--w-fw-black);
  color:var(--w-text);max-width:22ch}
.cf-hero__h-a{display:block;font-size:clamp(40px,5.6vw,76px);line-height:1;letter-spacing:-.035em}
/* em-based so the beat tracks the responsive font-size at every breakpoint */
.cf-hero__h-b{display:block;margin-top:.34em;font-size:clamp(24px,3.1vw,44px);line-height:1.12}

.cf-hero__lead{margin:var(--w-s-5) 0 0;max-width:58ch;color:var(--w-text-2)}
.cf-hero__actions{margin-top:var(--w-s-6);display:flex;gap:var(--w-s-3);
  flex-wrap:wrap;justify-content:center}

/* the three cold-click objections, answered before the fold: cost, effort, time-to-value */
.cf-reduce{list-style:none;margin:var(--w-s-5) 0 0;padding:0;
  display:flex;flex-wrap:wrap;justify-content:center;gap:var(--w-s-3) var(--w-s-5)}
.cf-reduce li{display:inline-flex;align-items:center;gap:8px;
  font-size:var(--w-fs-xs);font-weight:var(--w-fw-medium);color:var(--w-text-2)}
.cf-reduce .w-icon{width:15px;height:15px;flex:none;color:var(--w-brand-2)}

/* ---- floor: the proof stat + the customers ------------------------------ */
.cf-hero__floor{display:flex;flex-direction:column;gap:clamp(14px,1.8vh,24px);
  padding-bottom:clamp(14px,2vh,26px)}

/* THE HERO STAT — one figure, at assertion scale.
   Layout is numeral-left / body-right so the number owns the entry point and the
   claim reads as its caption. The glass card exists because the stat sits over
   video: without a surface the copy fights whatever frame is playing behind it. */
.cf-stat{position:relative;display:flex;align-items:center;gap:clamp(18px,2.4vw,34px);
  padding:clamp(14px,1.7vw,22px) clamp(18px,2.2vw,30px);
  border-radius:var(--w-r-2xl);
  background:rgba(255,255,255,.72);border:1px solid var(--w-glass-line);
  -webkit-backdrop-filter:var(--w-glass-blur-lg);backdrop-filter:var(--w-glass-blur-lg);
  box-shadow:inset 0 1px 0 var(--w-glass-rim-top),var(--w-glass-shadow);
  overflow:hidden}
/* the bloom — blooms once as the numeral lands, then settles to a resting glow.
   It is BEHIND the content (z-index:0 + children lifted) and pointer-events:none. */
.cf-stat::after{content:"";position:absolute;inset:-1px;z-index:0;pointer-events:none;
  border-radius:inherit;opacity:0;
  /* wide and low: a 70%/.28 bloom anchored at 12% read as a lilac PANEL behind
     the numeral rather than light coming off it. Spread it past the card and
     drop the peak — a glow you can find the edge of is a shape, not a glow. */
  background:radial-gradient(170% 300% at -6% 50%, rgba(152,135,244,.16) 0%, rgba(152,135,244,.045) 34%, transparent 62%);
  transition:opacity 1.4s var(--w-ease)}
.cf-stat.is-lit::after{opacity:1}
.cf-stat>*{position:relative;z-index:1}

/* the numeral. Gradient-clipped, tabular so the count-up does not jitter the
   layout as digits change width. --ss-num-grad comes from the .cz-light block
   used by the shared stat cards, so this figure and §3/§4's numerals are the
   same ramp on the same band. */
.cf-stat__v{position:relative;margin:0;display:flex;align-items:baseline;gap:.04em;
  font-size:clamp(60px,7.4vw,104px);font-weight:var(--w-fw-black);
  letter-spacing:-.05em;line-height:.86;
  background:linear-gradient(135deg,var(--w-purple-ink) 0%,var(--w-purple) 100%);
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.cf-stat__n{font-variant-numeric:tabular-nums lining-nums;font:inherit}
.cf-stat__u{font-size:.44em;font-weight:var(--w-fw-bold);letter-spacing:-.02em}
/* THE SHEEN. A narrow white diagonal that crosses the numeral once, as it lands.
   It is a sibling, not a ::after on .cf-stat__v — that element is painted through
   a background-clip:text mask, and a positioned descendant of a text-clipped
   parent renders transparent with nothing behind it and vanishes entirely
   (feedback_ds7_gradient_numeral_traps). Keep it a sibling. */
.cf-stat__sheen{position:absolute;inset:-20% -60%;pointer-events:none;opacity:0;
  background:linear-gradient(105deg,transparent 38%,rgba(255,255,255,.92) 50%,transparent 62%);
  transform:translateX(-120%)}
.cf-stat.is-lit .cf-stat__sheen{animation:cfSheen 1.1s var(--w-ease) .85s 1 both}
@keyframes cfSheen{
  0%{opacity:0;transform:translateX(-120%)}
  18%{opacity:1}
  82%{opacity:1}
  100%{opacity:0;transform:translateX(120%)}
}

.cf-stat__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:10px}
.cf-stat__l{margin:0;font-size:clamp(15px,1.25vw,18px);line-height:1.45;color:var(--w-text);
  max-width:44ch}
.cf-stat__l b{font-weight:var(--w-fw-bold)}
/* THE TRACK gives the number a shape. A bare "66%" is an abstraction; a bar that
   stops two-thirds of the way across is a quantity you can see without reading.
   It fills in step with the count-up (same 1.5s, same ease). */
.cf-stat__track{height:6px;border-radius:999px;overflow:hidden;
  background:rgba(28,26,36,.08)}
.cf-stat__fill{display:block;height:100%;width:0;border-radius:inherit;
  background:linear-gradient(90deg,var(--w-purple-ink),var(--w-purple));
  transition:width 1.5s cubic-bezier(.16,1,.3,1)}
.cf-stat.is-lit .cf-stat__fill{width:66%}
.cf-stat__src{margin:0;font-size:var(--w-fs-xs);color:var(--w-text-3)}

/* TRUST MARQUEE — the floor's last element, so at desktop heights it lands on
   the fold line. Hairline above only; the section ends here. */
.cf-hero__trust{padding-top:clamp(12px,1.6vh,20px);border-top:1px solid var(--w-line)}
.cf-hero__trust .w-trust-label{margin-bottom:var(--w-s-3)}

/* ⚠️ THE MARQUEE-ON-LIGHT TRAP. ds7.css flattens marquee logos with
   `filter:brightness(0) invert(1)` — white silhouettes, correct on the dark
   default. The light correction is scoped to `:root[data-theme="light"]`, and
   this page's ROOT is still dark: only this SECTION is light, via .cz-light.
   So the foundation rule wins and every logo renders white on white — the strip
   goes blank with no error anywhere, which is exactly how it shipped in the
   first pass of this hero. The three rules below are the light correction,
   re-scoped to the band. Any .w-marquee inside a .cz-light section needs them.
   SPECIFICITY: (0,3,0) here vs ds7's (0,2,0), so these win. Do not shorten. */
.cf-hero__trust .w-marquee__item{filter:grayscale(1) brightness(0);opacity:.5}
.cf-hero__trust .w-marquee__lockup i{filter:grayscale(1) brightness(0);opacity:.5}
.cf-hero__trust .w-marquee__lockup b{color:rgba(28,26,36,.62)}

/* ---- hero responsive ---------------------------------------------------- */
@media(max-width:900px){
  /* the stat goes vertical: at this width a 104px numeral beside a 44ch claim
     leaves the claim about twelve characters wide. */
  .cf-stat{flex-direction:column;align-items:flex-start;gap:14px}
  .cf-stat__v{font-size:clamp(56px,15vw,80px)}
  .cf-stat__body{width:100%}
}
@media(max-width:520px){
  .cf-hero__actions{width:100%}
  .cf-hero__actions .w-btn{flex:1 1 100%;justify-content:center}
  .cf-reduce{gap:10px var(--w-s-4)}
}

/* NO VIDEO below 900px — the poster is the hero. Three clips total 5.0MB, and a
   5MB autoplay background on a phone on cellular is a bounce, not a design. The
   scenes are display:none so the browser never establishes a media element at
   all; carly-free.js also refuses to attach the deferred sources under this
   width, because CSS alone would not stop the network request. */
@media(max-width:900px){
  .cf-hero__scenes{display:none}
  .cf-hero__stage{background:url("/assets/images/w/carly-free/cf-hero-poster.webp") center/cover no-repeat}
}
@media(prefers-reduced-motion:reduce){
  /* first frame only, no rotation, no ken-burns, no bloom or sheen */
  .cf-hero__scene{transition:none}
  .cf-hero__vid{transform:none;transition:none}
  .cf-hero__mark{animation:none}
  .cf-stat__fill{transition:none}
  .cf-stat.is-lit .cf-stat__sheen{animation:none;opacity:0}
  .cf-stat::after{transition:none}
}

/* ---------------------------------------------------------------------------
   PRIMARY CTA COLOUR — page-local override of the DS7 default.
   THE PROBLEM IT FIXES: --w-cta-fill resolves to the brand gradient on dark
   bands and to `--w-glass-tint` (near-black glass) on light ones. That is a
   sound system default — a neutral button never fights a busy light surface —
   but it means the SAME action wore two different colours as the reader scrolled
   this page: purple in the hero-adjacent dark sections, black in the light ones.
   A launch page has one job and it should have one button.
   WHY BRAND AND NOT BLACK: black is premium and it is also anonymous — it is the
   button every SaaS site ships, and on a page whose entire purpose is to
   introduce a product by name, the CTA is free brand real estate. The colour
   research people cite here is mostly noise (contrast against surroundings beats
   hue every time), so the tie-break is ownership, not psychology.
   WHICH purple: the DEEP end of the ramp (purple-ink → purple), not the default
   brand ramp, which finishes on lavender and goes soft against a near-white
   band. White label on this ramp measures ~5.2:1 at the dark stop and ~3.6:1 at
   the light one, clearing AA-large comfortably at the 18px/600 the button uses.
   Scoped to .cf-shine, which is on every primary CTA on this page and nothing
   else — DS7's own button is untouched. */
.cf-shine.w-btn--primary{
  background:linear-gradient(135deg,var(--w-purple-ink) 0%,var(--w-purple) 100%);
  color:#fff;border-color:transparent;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.28),0 8px 22px -10px rgba(111,95,224,.62)}
.cf-shine.w-btn--primary .w-icon{color:#fff}

/* ============ CTA TREATMENT — .cf-shine / .cf-lift =========================
   Applied to every primary CTA on the page (.cf-shine) and every glass
   secondary (.cf-lift). Both are ADDITIVE classes on top of .w-btn, never a
   replacement for it — the foundation still owns fill, radius, focus ring and
   the light/dark token swap, so these keep working if DS7's button changes.

   .cf-shine has two states on purpose:
     RESTING — a slow sheen crosses every 4.5s. Enough to catch peripheral
       vision on a page the reader is scanning; slow enough that it never reads
       as a loading bar. This is the "begging to be clicked" behaviour.
     HOVER   — the sheen speeds up to 900ms and repeats, the button lifts 2px,
       the glow doubles, and the arrow slides. The hover has to out-reward the
       resting state or the interaction feels like nothing happened.
   The sheen lives on a ::before with overflow:hidden on the button; the label
   sits above it via a z-index on the direct children.
   --------------------------------------------------------------------------- */
.cf-shine{position:relative;overflow:hidden;isolation:isolate}
.cf-shine>*{position:relative;z-index:1}
.cf-shine::before{content:"";position:absolute;top:-50%;bottom:-50%;left:-45%;width:34%;
  z-index:0;pointer-events:none;
  /* .34 peak, not .55, and 34% wide, not 55%. The first pass was a white BLOCK
     crossing the button — obvious in any still frame and cheap-looking in
     motion. A sheen should register as light moving over a surface, which means
     it has to be narrow enough to read as a highlight. */
  background:linear-gradient(100deg,transparent 0%,rgba(255,255,255,.34) 50%,transparent 100%);
  transform:skewX(-18deg) translateX(0);
  animation:cfShine 4.5s var(--w-ease) infinite}
@keyframes cfShine{
  0%{transform:skewX(-18deg) translateX(0)}
  /* the sweep itself occupies the first ~18% of the cycle; the rest is the rest */
  16%{transform:skewX(-18deg) translateX(430%)}
  100%{transform:skewX(-18deg) translateX(430%)}
}
.cf-shine,.cf-lift{transition:transform var(--w-dur) var(--w-ease),
  box-shadow var(--w-dur) var(--w-ease),background var(--w-dur) var(--w-ease)}
.cf-shine .w-icon,.cf-lift .w-icon{transition:transform var(--w-dur) var(--w-ease)}

@media(hover:hover){
  .cf-shine:hover{transform:translateY(-2px);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.5),0 10px 26px -8px rgba(111,95,224,.55),var(--w-cta-glow-strong)}
  .cf-shine:hover::before{animation-duration:.9s}
  .cf-shine:hover .w-icon{transform:translateX(4px)}
  .cf-lift:hover{transform:translateY(-2px);box-shadow:var(--w-shadow-lg)}
  .cf-lift:hover .w-icon{transform:translateX(3px)}
}
/* keyboard users get the same reward as the mouse — the ring alone is the
   accessibility floor, not the interaction */
.cf-shine:focus-visible{transform:translateY(-2px)}
.cf-shine:focus-visible::before{animation-duration:.9s}
@media(prefers-reduced-motion:reduce){
  .cf-shine::before{animation:none;opacity:0}
  .cf-shine:hover,.cf-lift:hover,.cf-shine:focus-visible{transform:none}
  .cf-shine .w-icon,.cf-lift .w-icon{transition:none}
}

/* ============ §2 · GETTING STARTED — the setup timeline ===================
   Pattern-lifted from the "Implementation" timeline on 2.0's /how-it-works/
   (the .week-timeline family): a centre spine, rows alternating left and
   right, a dot ON the spine and an icon tile opposite the copy.

   TWO DELIBERATE DEPARTURES FROM 2.0:
   1. The [ Day 1 ] pill is a TIMER CHIP — clock glyph + the real duration of
      the step. A day label describes a calendar; a duration describes effort,
      and effort is the thing the reader is actually weighing.
   2. 2.0 gave each row its own accent (cyan / violet / lavender / pink) via
      :nth-child. DS7 runs ONE brand ramp, so rows are differentiated by their
      position along the spine gradient instead. Do NOT reintroduce per-row
      hues — every other DS7 page would then be the odd one out.

   The spine is a pseudo-element on the list, so it spans exactly the rows and
   cannot drift when a step is added or removed.
   ------------------------------------------------------------------------- */
.cf-tl{position:relative;list-style:none;margin:0;padding:0;
  max-width:940px;margin-inline:auto}
/* THE SPINE IS TWO LAYERS, and that is what makes it animate.
   Layer 1 (.cf-tl::before) is the unlit TRACK — a hairline that spans the whole
   list so the reader can see the shape of the sequence before they have scrolled
   it. Layer 2 is per-row (.cf-tl__item::before): each row owns the slice of
   spine beside it and draws it in with scaleY when the row reveals. The line
   therefore grows down the page under the reader rather than being there all
   along, which is the difference between a diagram and a progress bar.
   Per-row rather than one long fill because row heights differ — a single
   animated element would need its height measured in JS and re-measured on
   resize. Composed from `transform` only, so it never touches layout. */
.cf-tl::before{content:"";position:absolute;left:50%;top:0;bottom:0;width:2px;
  transform:translateX(-50%);border-radius:2px;
  background:rgba(28,26,36,.10)}
.cf-tl__item::before{content:"";position:absolute;left:50%;top:0;bottom:0;width:2px;
  transform:translateX(-50%) scaleY(0);transform-origin:50% 0;border-radius:2px;
  background:linear-gradient(180deg,var(--w-purple-ink),var(--w-purple));
  transition:transform .85s cubic-bezier(.16,1,.3,1)}
.cf-tl__item.is-visible::before{transform:translateX(-50%) scaleY(1)}
/* …and the first and last rows mask the stub above the first dot and below the
   last one, so the track BEGINS and ENDS on a dot. A fixed top/bottom inset
   cannot do this: row heights vary with their copy, so any hardcoded value is
   correct at one breakpoint and wrong at the rest. A track that overshoots its
   terminus reads as a dangling wire. */
.cf-tl__item:first-child::after,
.cf-tl__item--last::after{content:"";position:absolute;left:50%;width:4px;z-index:1;
  transform:translateX(-50%);background:var(--w-bg)}
.cf-tl__item:first-child::after{top:0;height:50%}
.cf-tl__item--last::after{bottom:0;height:50%}

.cf-tl__item{position:relative;display:flex;align-items:center;
  gap:clamp(28px,4vw,64px);padding-block:clamp(8px,1vw,14px)}
/* alternate sides. row-reverse rather than order:, so the DOM stays in reading
   order for a screen reader and for anyone who linearises the page. */
.cf-tl__item:nth-child(even){flex-direction:row-reverse}

/* ALIGNMENT — copy hugs the spine, it does not run away from it (Jeff).
   The rows alternate sides, so a single text-align is wrong for half of them:
   left-aligning a block that sits LEFT of the centre line throws its ragged
   edge out to the page margin and leaves a canyon down the middle. Each side
   now points INWARD — odd rows (copy on the left) are right-aligned, even rows
   (copy on the right) are left-aligned — so both columns terminate against the
   spine and the eye tracks a single vertical axis down the section instead of
   ping-ponging across a gap.
   The timer chip and the bullet checks have to follow the same rule or they
   pin themselves to the outside edge and undo it. */
.cf-tl__item:nth-child(odd) .cf-tl__body{text-align:right;align-items:flex-end}
.cf-tl__item:nth-child(odd) .cf-tl__time{align-self:flex-end}
.cf-tl__item:nth-child(odd) .cf-tl__pts li{flex-direction:row-reverse}
.cf-tl__item:nth-child(even) .cf-tl__body{text-align:left;align-items:flex-start}
.cf-tl__item:nth-child(even) .cf-tl__time{align-self:flex-start}
.cf-tl__item:nth-child(even) .cf-tl__pts li{flex-direction:row}
.cf-tl__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:8px}
/* BOTH columns stay 1fr. This is load-bearing: the spine is at left:50%, so the
   column boundary has to be at 50% too. Narrowing the visual column to give the
   copy more room (tried, reverted) pushes the copy column past the midpoint and
   the text runs straight over the spine and the dots. The inward pull is bought
   with text-align only — never with column widths. The flex `gap` is what keeps
   the copy clear of the dot. */
.cf-tl__visual{flex:1;min-width:0;display:flex;justify-content:center}

/* the dot sits ON the spine and is the same size at every breakpoint — it is the
   element that makes the track read as a sequence rather than a divider. */
/* THE DOT lands after its segment has drawn (.18s behind it) and overshoots
   slightly on the way in — a back-eased pop is what reads as "arrived" rather
   than "faded in". The ring is a second pseudo-element that expands once and
   dissolves, so the arrival has a beat instead of just a state change. */
.cf-tl__dot{position:absolute;left:50%;top:50%;z-index:2;
  width:17px;height:17px;border-radius:50%;
  background:var(--w-bg);border:3px solid rgba(28,26,36,.16);
  box-shadow:0 0 0 5px var(--w-bg);
  transform:translate(-50%,-50%) scale(.35);opacity:0;
  transition:transform .5s cubic-bezier(.34,1.56,.64,1) .18s,
             opacity .3s var(--w-ease) .18s,
             border-color .5s var(--w-ease) .18s,
             box-shadow .5s var(--w-ease) .18s}
.cf-tl__item.is-visible .cf-tl__dot{opacity:1;transform:translate(-50%,-50%) scale(1);
  border-color:var(--w-brand-2);
  box-shadow:0 0 0 5px var(--w-bg),0 0 0 9px rgba(152,135,244,.16)}
.cf-tl__dot::after{content:"";position:absolute;inset:-3px;border-radius:50%;
  border:2px solid var(--w-brand-2);opacity:0;transform:scale(1)}
.cf-tl__item.is-visible .cf-tl__dot::after{animation:cfPing 1.1s var(--w-ease) .34s 1 both}
@keyframes cfPing{
  0%{opacity:.55;transform:scale(1)}
  100%{opacity:0;transform:scale(2.6)}
}
/* the final row's dot is filled, not hollow — the sequence has a terminus */
.cf-tl__item.is-visible .cf-tl__dot--live{background:var(--w-grad-brand);border-color:var(--w-lavender)}

/* THE TIMER CHIP — this is the element that replaced 2.0's [ Day 1 ] pill.
   Mono face because it is a measurement, not a label. */
/* The chip, title and icon each arrive on their own delay AFTER the dot, so a
   row resolves as a short sequence — line, dot, label, name, icon — rather than
   four things appearing at once. The whole cascade is under 700ms; any longer
   and a fast scroller outruns it. */
.cf-tl__time{align-self:flex-start;display:inline-flex;align-items:center;gap:7px;
  padding:5px 12px 5px 10px;border-radius:var(--w-r-pill);
  background:var(--w-brand-soft);border:1px solid var(--w-brand-line);
  font-family:var(--w-font-mono);font-size:11.5px;font-weight:700;letter-spacing:.01em;
  color:var(--w-brand);white-space:nowrap}
.cf-tl__time .w-icon{width:13px;height:13px;flex:none}
/* the terminal row reads as an outcome, not a duration, so it takes the solid
   brand fill the last dot and the last icon tile also carry */
.cf-tl__time--live{background:var(--w-grad-brand);border-color:transparent;color:var(--w-text-on-brand)}

/* the title flashes brand as it lands, then settles to charcoal over 1.4s.
   A permanent brand-coloured heading would compete with the numerals in §3/§4;
   a flash marks the arrival and gives the colour back. */
.cf-tl__t{margin:2px 0 0;font-size:clamp(18px,1.5vw,22px);font-weight:var(--w-fw-bold);
  letter-spacing:var(--w-ls-tight);line-height:1.28;color:var(--w-text)}
.cf-tl__item.is-visible .cf-tl__t{animation:cfTitleLand 1.6s var(--w-ease) .32s 1 both}
@keyframes cfTitleLand{
  0%{color:var(--w-brand);text-shadow:0 0 18px rgba(152,135,244,.45)}
  100%{color:var(--w-text);text-shadow:none}
}
.cf-tl__p{margin:0;font-size:var(--w-fs-sm);line-height:var(--w-lh-normal);color:var(--w-text-2)}
.cf-tl__pts{list-style:none;margin:6px 0 0;padding:0;display:flex;flex-direction:column;gap:7px}
/* flex-start, not center: these wrap to two lines at narrow widths and a centred
   check floats to the middle of the block instead of marking its first line. */
.cf-tl__pts li{display:flex;align-items:flex-start;gap:8px;
  font-size:var(--w-fs-xs);line-height:1.5;color:var(--w-text-2)}
.cf-tl__pts .w-icon{width:14px;height:14px;flex:none;margin-top:3px;color:var(--w-brand-2)}

.cf-tl__ic{width:72px;height:72px;border-radius:var(--w-r-lg);flex:none;
  display:flex;align-items:center;justify-content:center;
  background:var(--w-brand-soft);border:1px solid var(--w-brand-line);
  transform:scale(.86);opacity:0;
  transition:transform .55s cubic-bezier(.34,1.56,.64,1) .3s,
             opacity .4s var(--w-ease) .3s,box-shadow .8s var(--w-ease) .3s}
.cf-tl__item.is-visible .cf-tl__ic{opacity:1;transform:none;
  box-shadow:0 10px 30px -10px rgba(111,95,224,.42)}
.cf-tl__ic .w-icon{width:32px;height:32px;color:var(--w-brand)}
.cf-tl__ic--live{background:var(--w-grad-brand);border-color:transparent}
.cf-tl__ic--live .w-icon{color:var(--w-text-on-brand)}

@media(max-width:820px){
  /* Spine moves to the far left and every row goes single-column. Keeping the
     centre spine on a phone leaves ~40% of each row empty on alternating sides,
     and the icon tile ends up bigger than the copy it labels. */
  .cf-tl::before{left:8px}
  .cf-tl__item,.cf-tl__item:nth-child(even){flex-direction:row;gap:20px;
    padding-left:34px;padding-block:14px}
  /* everything left-aligned: with one column there is no centre line to hug, and
     the inward rule from desktop would right-align half the rows against nothing */
  .cf-tl__item:nth-child(odd) .cf-tl__body,
  .cf-tl__item:nth-child(even) .cf-tl__body{text-align:left;align-items:flex-start}
  .cf-tl__item:nth-child(odd) .cf-tl__time,
  .cf-tl__item:nth-child(even) .cf-tl__time{align-self:flex-start}
  .cf-tl__item:nth-child(odd) .cf-tl__pts li,
  .cf-tl__item:nth-child(even) .cf-tl__pts li{flex-direction:row}
  /* the dot is pinned near the top of the row rather than centred, so it lines up
     with the timer chip — the two read as one label. The masks move with it. */
  .cf-tl__dot{left:8px;top:30px;transform:translate(-50%,0) scale(.35)}
  .cf-tl__item.is-visible .cf-tl__dot{transform:translate(-50%,0) scale(1)}
  .cf-tl__item::before{left:8px}
  .cf-tl__item:first-child::after,
  .cf-tl__item--last::after{left:8px}
  .cf-tl__item:first-child::after{height:30px}
  .cf-tl__item--last::after{top:30px;bottom:0;height:auto}
  /* the icon tile is decoration at this width and the copy needs the room */
  .cf-tl__visual{display:none}
}

/* ============ §2b · THE RACE — the playful close on Getting Started ========
   "You've got five minutes. I'll time you." + a traffic-light start + a live
   stopwatch. One borrowed feeling: being timed at something as a kid. It has to
   land in about four seconds and then get out of the way, which is why the
   lights resolve fast and the button is the last thing standing.

   PREMIUM, NOT NOVELTY — the line this walks:
     · the instrument is glass and charcoal, not a cartoon stopwatch
     · the digits are the DS7 mono face on a ghost layer, so it reads as a
       display rather than as text that happens to be counting
     · amber and green appear for well under a second each and are the only
       non-brand hues on the page
   If any of those three drift, this stops being a wink and becomes a gimmick.

   Ready / Set / Go are the one legitimate use of DS7's status tokens as
   colour: the traffic-light convention is semantic here, not decorative.
   --------------------------------------------------------------------------- */
.cf-race{margin-top:clamp(44px,4.6vw,72px);
  display:flex;flex-direction:column;align-items:center;text-align:center;
  gap:clamp(18px,2.2vw,28px);
  padding:clamp(30px,3.4vw,52px) clamp(22px,3vw,44px);
  border-radius:var(--w-r-2xl);
  background:var(--w-card);border:1px solid var(--w-line);
  box-shadow:var(--w-shadow-raise-soft);
  position:relative;overflow:hidden}
/* a soft brand floor so the block reads as a moment, not another card */
.cf-race::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(80% 120% at 50% 118%, rgba(152,135,244,.20) 0%, rgba(152,135,244,.05) 44%, transparent 72%)}
.cf-race>*{position:relative;z-index:1}

.cf-race__hook{margin:0;font-size:clamp(21px,2vw,28px);font-weight:var(--w-fw-bold);
  letter-spacing:var(--w-ls-tight);line-height:1.25;color:var(--w-text)}

/* ---- the lights --------------------------------------------------------- */
/* Each word arrives on its own delay off .is-go. They are inline-block so the
   scale on "Go." does not reflow its siblings — a transform on an inline
   element is ignored, which is the classic way this effect silently does
   nothing. */
.cf-race__lights{margin:0;display:flex;align-items:baseline;justify-content:center;
  gap:clamp(10px,1.6vw,22px);flex-wrap:wrap;
  font-weight:var(--w-fw-black);letter-spacing:-.03em;line-height:1}
.cf-race__l{display:inline-block;opacity:0;transform:translateY(6px) scale(.92);
  font-size:clamp(26px,3.4vw,46px);color:var(--w-text-3)}
.cf-race.is-go .cf-race__l{animation:cfLight .5s cubic-bezier(.34,1.56,.64,1) both}
.cf-race.is-go .cf-race__l--ready{animation-delay:.05s}
.cf-race.is-go .cf-race__l--set{animation-delay:.55s}
.cf-race.is-go .cf-race__l--go{animation-delay:1.05s;animation-duration:.62s}
@keyframes cfLight{to{opacity:1;transform:none}}
/* colour + weight land WITH the word, via a second animation on the same delay.
   Amber for caution, green for go — and "Go." keeps growing past the others so
   the eye finishes on it. */
.cf-race.is-go .cf-race__l--ready{color:var(--w-text)}
.cf-race.is-go .cf-race__l--set{color:var(--w-warning);text-shadow:0 0 26px rgba(251,191,36,.42)}
.cf-race.is-go .cf-race__l--go{color:var(--w-success);text-shadow:0 0 30px rgba(52,211,153,.48);
  font-size:clamp(34px,4.6vw,64px)}

/* ---- the instrument ----------------------------------------------------- */
.cf-watch{display:inline-flex}
.cf-watch__face{position:relative;display:inline-flex;align-items:center;justify-content:center;
  padding:clamp(12px,1.4vw,18px) clamp(20px,2.4vw,34px);
  border-radius:var(--w-r-lg);
  background:linear-gradient(168deg,#232130 0%,#15141c 100%);
  border:1px solid rgba(255,255,255,.10);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.14),inset 0 -2px 6px rgba(0,0,0,.5),
             0 18px 40px -18px rgba(28,26,36,.6)}
/* the glass dome — a single highlight across the top third. This is the whole
   difference between "dark rectangle" and "instrument". */
.cf-watch__face::after{content:"";position:absolute;inset:1px 1px 55% 1px;pointer-events:none;
  border-radius:calc(var(--w-r-lg) - 1px);
  background:linear-gradient(180deg,rgba(255,255,255,.10),rgba(255,255,255,0))}
.cf-watch__ghost,.cf-watch__t{
  font-family:var(--w-font-mono);font-weight:600;
  font-size:clamp(30px,3.6vw,52px);line-height:1;letter-spacing:.02em;
  font-variant-numeric:tabular-nums lining-nums}
/* THE GHOST: every segment lit at low opacity behind the live digits, the way a
   real backlit LCD reads. It is also what stops the housing from resizing as
   digits change width — the ghost is the widest possible value and the live
   layer is absolutely positioned over it. */
.cf-watch__ghost{color:rgba(233,221,255,.13)}
.cf-watch__t{position:absolute;inset:auto;left:50%;top:50%;transform:translate(-50%,-50%);
  background:linear-gradient(180deg,#e9ddff 0%,#c18cff 100%);
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;
  filter:drop-shadow(0 0 14px rgba(193,140,255,.45))}
/* running state: a slow breath on the glow so the display feels live even when
   the hundredths are moving too fast to track */
.cf-race.is-running .cf-watch__t{animation:cfWatchLive 1.8s ease-in-out infinite}
@keyframes cfWatchLive{
  0%,100%{filter:drop-shadow(0 0 14px rgba(193,140,255,.45))}
  50%{filter:drop-shadow(0 0 22px rgba(193,140,255,.7))}
}
/* stopped at 5:00.00 — the glow goes green and holds, so the end state reads as
   "time" rather than as a broken counter */
.cf-race.is-done .cf-watch__t{animation:none;
  background:linear-gradient(180deg,#b9f5df 0%,var(--w-success) 100%);
  -webkit-background-clip:text;background-clip:text;
  filter:drop-shadow(0 0 20px rgba(52,211,153,.55))}

/* ---- the ask ------------------------------------------------------------ */
/* Appears only after "Go." — the button is the finish line, so it cannot be
   sitting there during the countdown. Scale + rise so it arrives rather than
   fades. */
.cf-race__cta{opacity:0;transform:translateY(10px) scale(.96)}
.cf-race.is-go .cf-race__cta{animation:cfLight .55s cubic-bezier(.34,1.56,.64,1) 1.45s both}

@media(max-width:520px){
  .cf-race__lights{gap:10px}
  .cf-race__cta{width:100%;justify-content:center}
}
@media(prefers-reduced-motion:reduce){
  /* everything present, nothing moving: the words are already coloured by the
     .is-go rules above, the button is visible, the watch shows a static 0:00.00 */
  .cf-race .cf-race__l,.cf-race .cf-race__cta{opacity:1;transform:none;animation:none}
  .cf-race.is-running .cf-watch__t{animation:none}
  .cf-tl__item::before,.cf-tl__dot,.cf-tl__ic{transition:none}
  .cf-tl__item::before{transform:translateX(-50%) scaleY(1)}
  .cf-tl__dot{opacity:1;transform:translate(-50%,-50%) scale(1)}
  .cf-tl__ic{opacity:1;transform:none}
  .cf-tl__item.is-visible .cf-tl__dot::after,
  .cf-tl__item.is-visible .cf-tl__t{animation:none}
}

/* ============ §3/§4 · PAIN + SOLUTION GRIDS ===============================
   Grid gaps and breakpoints only. The CARD itself is .ss-sfc and lives in
   /assets/css/w/shared/ss-statcard.css — do not restyle it here. */
.cf-pain__grid,.cf-sol__grid{gap:clamp(16px,1.7vw,24px)}
/* .cf-card is the shell the shared component expects to be given: it supplies the surface,
   the radius and the padding, and .ss-sfc supplies everything inside it. */
.cf-card{padding-inline:clamp(20px,2.1vw,28px)}
@media(max-width:1024px){
  /* 3→2 leaves an orphan on the third card; at this width the cards are still readable at
     full width, and a 1-up stack keeps each numeral at hero scale. */
  .cf-pain__grid,.cf-sol__grid{grid-template-columns:1fr}
}
@media(min-width:1025px){
  .cf-pain__grid,.cf-sol__grid{grid-template-columns:repeat(3,1fr)}
}

/* ============ §5 · THE OFFER ============================================== */
/* align-items:stretch (the default), NOT start. The free card is the taller column, and with
   `start` the right column ended at the plan ladder and left a column-height void beside the
   card's CTA — on the one section whose job is to close, the eye reads that void as the end of
   the page. Stretch + space-between hangs the ladder off the bottom so both columns terminate
   on the same line. */
.cf-offer__grid{display:grid;grid-template-columns:minmax(0,.86fr) minmax(0,1.14fr);
  align-items:stretch;gap:clamp(20px,2.4vw,34px)}

.cf-free{position:relative;display:flex;flex-direction:column;gap:var(--w-s-4);
  padding:clamp(26px,2.6vw,36px) clamp(22px,2.2vw,30px)}
.cf-free__tag{align-self:flex-start}
.cf-free__price{margin:0;display:flex;flex-direction:column;gap:6px}
.cf-free__amt{font-size:clamp(52px,5.4vw,72px);font-weight:var(--w-fw-black);
  letter-spacing:-.045em;line-height:.9;width:max-content;
  background:var(--w-grad-brand);-webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent}
.cf-free__per{font-size:var(--w-fs-sm);color:var(--w-text-2)}
/* the caps table — a definition list because that is what it is */
.cf-free__caps{margin:0;display:flex;flex-direction:column;gap:0}
.cf-free__caps>div{display:flex;justify-content:space-between;align-items:baseline;gap:var(--w-s-4);
  padding:11px 0;border-bottom:1px solid var(--w-line)}
.cf-free__caps>div:first-child{border-top:1px solid var(--w-line)}
.cf-free__caps dt{margin:0;font-size:var(--w-fs-sm);color:var(--w-text-2)}
.cf-free__caps dd{margin:0;font-size:var(--w-fs-sm);font-weight:var(--w-fw-semi);color:var(--w-text);
  font-variant-numeric:tabular-nums;text-align:right}
.cf-free__cta{margin-top:var(--w-s-2)}
.cf-free__note{margin:0;font-size:var(--w-fs-xs);line-height:1.5;color:var(--w-text-3);text-align:center}


/* The panel grows to the height of the taller free card beside it; the list sits at
   the top and the ladder is pushed onto the floor by its own margin-top:auto. Slack
   therefore collects in ONE place — between the last bullet and the ladder — where it
   reads as breathing room instead of as a gap someone forgot to close. */
.cf-facts{display:flex;flex-direction:column;height:100%;
  padding:clamp(24px,2.5vw,34px) clamp(22px,2.2vw,30px);
  border-radius:var(--w-r-2xl);background:var(--w-glass-fill);border:1px solid var(--w-glass-line);
  -webkit-backdrop-filter:var(--w-glass-blur);backdrop-filter:var(--w-glass-blur);
  box-shadow:inset 0 1px 0 var(--w-glass-rim-top),var(--w-glass-shadow-soft)}
.cf-facts__t{margin:0 0 var(--w-s-5);font-size:clamp(17px,1.4vw,20px);font-weight:var(--w-fw-bold);
  letter-spacing:var(--w-ls-tight);color:var(--w-text)}
/* NOT justify-content:space-around, and NOT flex:1. Both were here to absorb the
   height difference against the taller free card, and both did it by pushing the
   four bullets apart — at desktop that opened ~40px of dead air between one-line
   items and the list stopped reading as a list. Slack now collects once, at the
   bottom of the panel, where it looks like padding instead of like a mistake. */
.cf-facts__list{list-style:none;margin:0;padding:0;
  display:flex;flex-direction:column;gap:var(--w-s-4)}
.cf-facts__list li{display:flex;align-items:flex-start;gap:11px;
  font-size:var(--w-fs-sm);line-height:var(--w-lh-normal);color:var(--w-text-2)}
.cf-facts__list .w-icon{width:17px;height:17px;flex:none;margin-top:2px;color:var(--w-brand-2)}
.cf-facts__list b{color:var(--w-text);font-weight:var(--w-fw-semi)}

/* Deliberately NOT a pricing table — a five-tier grid on a landing page invites comparison
   shopping, which is a different job for a different page. This is the ladder in one line so
   the reader knows its shape and stops asking. */
.cf-ladder{margin-top:auto;padding-top:clamp(20px,2.4vw,30px);
  display:flex;flex-wrap:wrap;gap:8px}
.cf-ladder__step{flex:1 1 auto;min-width:96px;display:flex;flex-direction:column;gap:3px;
  padding:12px 14px;border-radius:var(--w-r-md);
  background:var(--w-glass-fill-soft);border:1px solid var(--w-line)}
.cf-ladder__step b{font-size:var(--w-fs-sm);font-weight:var(--w-fw-bold);color:var(--w-text);
  font-variant-numeric:tabular-nums}
.cf-ladder__step i{font-style:normal;font-family:var(--w-font-mono);font-size:11px;color:var(--w-text-3)}
.cf-ladder__step.is-on{background:var(--w-brand-soft);border-color:var(--w-brand-line)}
.cf-ladder__step.is-on b{color:var(--w-brand-2)}

@media(max-width:900px){
  .cf-offer__grid{grid-template-columns:1fr}
}

/* ============ §6 · RESULTS ================================================ */
/* Two tiers on purpose. The named, attributable customers get the display numeral and the card;
   the unattributed ones sit a full tier quieter so the page never implies they are the same
   class of evidence. Do not level them up to "balance" the section. */
.cf-res__lead{display:grid;grid-template-columns:repeat(2,1fr);gap:clamp(16px,1.7vw,24px)}
.cf-quote{display:flex;flex-direction:column;gap:var(--w-s-3);
  padding:clamp(26px,2.6vw,34px) clamp(22px,2.2vw,30px)}
.cf-quote__q{margin:var(--w-s-2) 0 0;font-size:var(--w-fs-body);line-height:1.6;color:var(--w-text-2)}
.cf-quote__q::before{content:"\201C"}
.cf-quote__q::after{content:"\201D"}
.cf-quote__who{margin-top:auto;padding-top:var(--w-s-4);border-top:1px solid var(--w-line);
  display:flex;align-items:center;gap:12px}
.cf-quote__id{display:flex;flex-direction:column;gap:2px;min-width:0}
.cf-quote__id b{font-size:var(--w-fs-sm);font-weight:var(--w-fw-semi);color:var(--w-text)}
.cf-quote__id span{font-size:var(--w-fs-xs);color:var(--w-text-3)}

.cf-res__grid{margin-top:clamp(16px,1.7vw,24px);
  display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(16px,1.7vw,24px)}
.cf-mini{margin:0;display:flex;flex-direction:column;gap:10px;
  padding:var(--w-s-5) 0 0;border-top:1px solid var(--w-line)}
.cf-mini__m{align-self:flex-start;font-family:var(--w-font-mono);font-size:11.5px;font-weight:700;
  letter-spacing:.01em;color:var(--w-brand-2)}
.cf-mini blockquote{margin:0;font-size:var(--w-fs-sm);line-height:var(--w-lh-normal);color:var(--w-text-2)}
.cf-mini figcaption{font-size:var(--w-fs-xs);color:var(--w-text-3)}
.cf-mini figcaption b{color:var(--w-text-2);font-weight:var(--w-fw-semi)}
@media(max-width:820px){
  .cf-res__lead{grid-template-columns:1fr}
  .cf-res__grid{grid-template-columns:1fr}
}

/* ============ §7 · INTEGRATIONS ==========================================
   .ss-int__band and its full-colour light-band rules live in the shared
   ss-integrations.css. Only the tail CTA is page-local. */
.cf-int__cta{margin-top:clamp(24px,2.6vw,36px);display:flex;align-items:center;justify-content:center;
  flex-wrap:wrap;gap:var(--w-s-4)}
.cf-int__cta p{margin:0;font-size:var(--w-fs-sm);color:var(--w-text-2)}

/* ============ §8 · FINAL CTA ============================================== */
.cf-cta__notes{display:flex;flex-wrap:wrap;justify-content:center;gap:var(--w-s-3) var(--w-s-5)}
.cf-cta__notes span{display:inline-flex;align-items:center;gap:8px;
  font-size:var(--w-fs-xs);font-weight:var(--w-fw-medium);color:var(--w-text-2)}
.cf-cta__notes .w-icon{width:15px;height:15px;flex:none;color:var(--w-brand-2)}

/* The two figures only mean anything AGAINST each other, so they are set as a contrast pair
   rather than a sentence: same size, same weight, brand vs muted, with the GAP between them
   carrying the message. --ss-num-grad comes from the shared sheet via .ss-cta__stat and is
   band-corrected for light. */
.cf-cta__stat{margin-top:var(--w-s-3);display:flex;flex-direction:column;align-items:center;gap:10px}
.cf-cta__pair{display:flex;align-items:center;gap:clamp(16px,2.4vw,32px)}
.cf-cta__side{display:flex;flex-direction:column;align-items:center;gap:4px}
.cf-cta__v{font-size:clamp(34px,3.4vw,46px);font-weight:var(--w-fw-black);letter-spacing:-.04em;
  line-height:.95;color:var(--w-text-3)}
.cf-cta__side.is-on .cf-cta__v{width:max-content;background:var(--ss-num-grad,var(--w-grad-brand));
  -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.cf-cta__k{font-size:var(--w-fs-xs);color:var(--w-text-3);text-align:center}
.cf-cta__vs{font-family:var(--w-font-mono);font-size:12px;color:var(--w-text-3);opacity:.7}
.cf-cta__cap{margin:0;display:inline-flex;align-items:center;gap:6px;
  font-size:var(--w-fs-sm);color:var(--w-text-2)}

/* the source tooltip — a real <button> so it is keyboard-reachable, not a title attribute */
.cf-cite{appearance:none;border:0;padding:0;background:none;cursor:pointer;position:relative;
  width:15px;height:15px;flex:none;display:inline-flex;align-items:center;justify-content:center;
  border-radius:50%;border:1px solid var(--w-line-strong);
  font-family:var(--w-font-mono);font-size:9.5px;font-weight:700;color:var(--w-text-3);
  transition:color var(--w-dur) var(--w-ease),border-color var(--w-dur) var(--w-ease)}
.cf-cite:hover,.cf-cite:focus-visible{color:var(--w-brand-2);border-color:var(--w-brand-line)}
.cf-cite__tip{position:absolute;bottom:calc(100% + 9px);left:50%;transform:translateX(-50%);
  width:max-content;max-width:min(300px,72vw);padding:9px 12px;border-radius:var(--w-r-sm);
  background:var(--w-glass-tint);color:#fff;border:1px solid var(--w-glass-line);
  font-family:var(--w-font);font-size:11.5px;font-weight:400;line-height:1.45;letter-spacing:0;
  text-align:left;opacity:0;visibility:hidden;pointer-events:none;z-index:5;
  transition:opacity var(--w-dur) var(--w-ease),visibility var(--w-dur) var(--w-ease)}
.cf-cite:hover .cf-cite__tip,.cf-cite:focus-visible .cf-cite__tip{opacity:1;visibility:visible}

/* ---------------------------------------------------------------------------
   REDUCED MOTION — the shared sheets already neutralize their own transitions;
   this covers the page-local plate wash and step tiles.
   --------------------------------------------------------------------------- */
@media(prefers-reduced-motion:reduce){
  .cf-cite__tip{transition:none}
}
