/* ====== /products/* ======
   One stylesheet for the six product pages (2026-09-21, built section by
   section from the Sales frame 428:4719). Loads after home.css. */

.prod-cyan { color: var(--c-accent-highlight); }
.prod-pink { color: var(--c-accent-pink); }
.prod-sand { color: var(--c-accent-sand); }   /* the problem: warm against cyan, so the polarity survives greyscale */
.prod-eyebrow { font-family: var(--font-secondary); font-size: var(--t-p3); letter-spacing: var(--ls-cta); text-transform: uppercase; color: var(--c-accent-cyan); }
.prod-eyebrow span { margin-inline: 4px; color: var(--c-text-muted); }

/* ── 1 · Hero: copy left, the radar right ─────────────────────────── */
.prod-hero {
    min-height: 0; align-items: center;
    padding-block: var(--space-15);
    /* TEST 2026-09-22: Home's hero ground (the canvas's diagonal #15001B → #2C003E) in place of the frame's vertical Background/gradient 1 */
    background: linear-gradient(104deg, var(--primary-900) 0%, var(--primary-800) 46%, var(--primary-600) 100%);
}
.prod-hero__inner { gap: var(--space-10); }
.prod-hero__copy { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-5); }
.prod-hero__body { max-width: 640px; font-size: var(--t-p1); color: var(--c-text-muted); }   /* P1 18px, not the 16px body default: it is the second thing read on the page (2026-10-02) */

/* the radar */
.radar { position: relative; width: min(100%, 420px); margin-inline: auto; }
.radar svg {
    width: 100%; height: auto; border-radius: 50%;
    /* the frame's glow: 60px/8px at .13 and a wide 120px/24px halo */
    box-shadow: 0 0 120px 24px rgba(173, 239, 242, .04), 0 0 60px 8px rgba(173, 239, 242, .13);
}
.radar__grid { opacity: .55; }
.radar__sweep { transform-origin: 0 0; animation: radar-sweep 6s linear infinite; }
@keyframes radar-sweep { to { transform: rotate(360deg); } }
/* each contact flashes as the sweep reaches its bearing, then fades over the
   rest of the revolution: same 6s clock, phase = bearing / 360             */
.radar__contact { fill: #ADEFF2; opacity: .18; animation: radar-blip 6s linear calc(var(--at) / 360 * 6s - 6s) infinite; }
@keyframes radar-blip {
    0%   { opacity: 1; filter: drop-shadow(0 0 6px #ADEFF2); }
    12%  { opacity: .9; }
    100% { opacity: .18; filter: none; }
}

/* ── 2 · The problem: copy left, "what gets logged" right ─────────── */
.prod-problem { background: var(--neutral-black); overflow: hidden; }   /* the bars run the band's full height and no further */
.prod-problem__grid { display: flex; flex-direction: column; gap: var(--space-8); }
.prod-problem__copy { display: flex; flex-direction: column; gap: var(--space-4); }
/* the frame: the right half sits between two soft cyan bars (31px, blurred 50) */
/* the frame, both tiers: the "logged" block sits between two soft cyan bars —
   the bars are the box. Mobile (483:6836): the block is 339px tall under the
   heading with 18px bars at its edges; desktop: the right half of the band
   with 31px bars at x=624 and x=1349 (rendered at the column's edges).     */
.prod-logged {
    position: relative; display: flex; flex-direction: column; justify-content: center; gap: var(--space-4);
    padding: var(--space-6) 43px;   /* stacked: as tall as its three lines (the frame's 339 only beside the copy) */
    container-type: inline-size;    /* the ticker sizes its type to the width it has */
    /* the frame puts the bars at the 402 frame's edges, i.e. the container's
       padding: bleed exactly that on each side (100vw would count a scrollbar) */
    margin-inline: calc(var(--page-gutter) * -1);
    overflow: hidden;
}
.prod-logged::before, .prod-logged::after {
    content: ''; position: absolute; top: 0; bottom: 0; width: 18px; pointer-events: none;
    background: var(--c-accent-band); filter: blur(22px); opacity: .6;
}
.prod-logged::before { left: 0; }
.prod-logged::after  { right: 0; }
.prod-logged__label, .prod-logged__note { font-size: var(--t-p1); color: #FFF7FB; }
.prod-logged__note { color: rgba(255, 247, 251, .75); }
/* the ticker: a one-line window; the list steps up one line per beat, holding
   between steps; the last item repeats the first so the wrap is invisible */
.ticker { height: 1.25em; overflow: hidden; font-size: min(var(--t-h3), 6.3cqi); line-height: 1.25; font-weight: var(--fw-medium); }   /* H3, or smaller when the longest status (15.5em) would not fit: cqi is the block's content width */
.ticker__list { display: flex; flex-direction: column; animation: ticker-step calc(var(--n) * 1.8s) infinite; }
.ticker__list li { height: 1.25em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@keyframes ticker-step {   /* 5 steps: hold, then move, for each line; the keyframes are generated for n = 5 */
    0%, 16%    { transform: translateY(0); }
    20%, 36%   { transform: translateY(-1.25em); }
    40%, 56%   { transform: translateY(-2.5em); }
    60%, 76%   { transform: translateY(-3.75em); }
    80%, 96%   { transform: translateY(-5em); }
    100%       { transform: translateY(-6.25em); }
}

/* ── 3 · What didn't fit: the glass bar of struck phrases, GONE, the questions ── */
.prod-missing { background: linear-gradient(180deg, var(--primary-500) 0%, #0A000D 100%); }   /* the frame's gradient */
.prod-missing__label { font-size: var(--t-h4); line-height: var(--lh-heading); color: var(--c-accent-cyan); margin-bottom: var(--space-4); }
.prod-missing__label--ask { margin-top: var(--space-10); }
/* the bar: frosted white, the four phrases divided by a dot-and-line, GONE at the end */
.prod-gone {
    display: flex; flex-direction: column; gap: var(--space-4);
    padding: var(--space-6);
    border: 2px solid rgba(255, 255, 255, .29); border-radius: 20px; overflow: visible;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .22) 0%, rgba(255, 255, 255, .06) 35%, rgba(255, 255, 255, 0) 60%, rgba(0, 0, 0, .10) 100%),
        radial-gradient(ellipse 60% 60% at 10% 0%, rgba(255, 255, 255, .18) 0%, rgba(255, 255, 255, 0) 60%),
        rgba(255, 255, 255, .28);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .6), inset 0 -1px 0 rgba(0, 0, 0, .25), 0 16px 40px rgba(0, 0, 0, .35), 0 0 60px rgba(171, 235, 240, .12);
}
.prod-gone.is-visible .prod-gone__word { text-shadow: 0 0 18px rgba(171, 235, 240, .7); }   /* GONE glows when it lands */
.prod-gone__list { display: flex; flex-direction: column; gap: 0; }
.prod-gone__list li { position: relative; padding-block: var(--space-4); font-size: var(--t-p1); color: var(--grey-400); }
/* stacked (mobile frame 551:969): a hairline between phrases running the card's
   full width, with a dot at its left end on the card's edge                  */
.prod-gone__list li + li::before { content: ''; position: absolute; left: calc(var(--space-6) * -1); right: calc(var(--space-6) * -1); top: 0; height: 2px; background: linear-gradient(90deg, #FFFFFF 0%, rgba(89, 72, 94, 1) 100%); }
.prod-gone__list li + li::after  { content: ''; position: absolute; left: calc(var(--space-6) * -1 - 5px); top: -4px; width: 10px; height: 10px; border-radius: 50%; background: #FFFFFF; }
/* the strike draws through each phrase in turn, once the bar is on screen: a
   real line-through, revealed left to right by a copy of the text clipped
   over the plain one.
   display: block is load-bearing. The overlay is positioned inset: 0, and on
   an inline span that resolves to the union of its line boxes, so a phrase
   that wraps got a second copy of the whole string laid over it. As a block
   the overlay matches the box and the strike follows every wrapped line.
   The span also used to carry white-space: nowrap here with normal only at
   1024+, which is backwards: the longest audit phrase then ran off the right
   edge on a phone. Fixed 2026-09-30.                                       */
.prod-strike { position: relative; display: block; }
.prod-strike::after {
    content: attr(data-text); position: absolute; inset: 0; color: inherit;
    text-decoration: line-through; text-decoration-thickness: 2px; text-decoration-color: var(--grey-400);
    clip-path: inset(0 100% 0 0);
    transition: clip-path .5s cubic-bezier(.2, .7, .2, 1) calc(.4s + var(--i) * .35s);
}
.prod-gone.is-visible .prod-strike::after { clip-path: inset(0 0 0 0); }
.prod-gone__word { align-self: flex-start; margin-top: var(--space-4); font-size: var(--t-h3); line-height: var(--lh-heading); font-weight: var(--fw-medium); letter-spacing: .06em; text-transform: uppercase; color: var(--c-accent-cyan); opacity: 0; transform: translateX(-8px); transition: opacity .5s ease 2.1s, transform .5s ease 2.1s; }
.prod-gone.is-visible .prod-gone__word { opacity: 1; transform: none; }   /* lands after the last strike */
/* the H2 ticker (component 101) */
/* below 1024 the questions wrap, so the window is two lines tall (2.5em) and
   every item is held to that height; the step is 2.5em. From 1024 one line. */
.ticker--h2 { height: 2.5em; font-size: var(--t-h2); line-height: 1.25; font-weight: var(--fw-regular); }
.ticker--h2 .ticker__list li { height: 2.5em; white-space: normal; text-overflow: clip; }
.ticker__list--4 { animation: ticker-step-4 calc(4 * 2.2s) infinite; }
@keyframes ticker-step-4 {
    0%, 20%    { transform: translateY(0); }
    25%, 45%   { transform: translateY(calc(var(--row, 2.5em) * -1)); }
    50%, 70%   { transform: translateY(calc(var(--row, 2.5em) * -2)); }
    75%, 95%   { transform: translateY(calc(var(--row, 2.5em) * -3)); }
    100%       { transform: translateY(calc(var(--row, 2.5em) * -4)); }
}

/* ── 4 · One call. Four reads. — the tabs ─────────────────────────── */
.prod-reads { background: var(--c-primary-dark); }
.prod-reads__head { display: flex; flex-direction: column; gap: var(--space-6); }
.prod-reads__copy { display: flex; flex-direction: column; gap: var(--space-4); }
.prod-reads__copy p { max-width: 585px; }
/* Figma component 88: a P3 pill — outlined by default, white when selected */
.prod-tabs { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.prod-tab {
    padding: 8px 16px; border-radius: 24px;
    /* semibold in both states (Akshay, 2026-10-01: the selected pill was hard to read).
       Galano ships a real 600 face, so nothing is synthesised.                 */
    font-size: var(--t-p3); font-weight: var(--fw-semibold); line-height: var(--lh-body); color: var(--c-neutral-gray);
    border: 1px solid var(--primary-400);
    background: transparent;
    transition: background-color .25s ease, color .25s ease, border-color .25s ease, box-shadow .25s ease;
}
.prod-tab:hover { border-color: var(--c-accent-cyan); color: var(--c-text); }
/* Weight alone could not fix this one: --c-accent-mauve (#906E9F) on white is
   4.27:1, and 14px text needs 4.5:1 for AA. --c-primary-light (#5B3367) is the
   same purple family a few steps deeper and measures 9.9:1, so the pill keeps
   its colour and becomes legible. The resting pill was never the problem:
   #D8D8D8 on the section's ground is 14.1:1.                                  */
.prod-tab[aria-selected="true"] { background: #FFFFFF; border-color: #FFFFFF; color: var(--c-primary-light); box-shadow: var(--gloss-edge), 0 0 18px rgba(255, 255, 255, .18); }
/* the panels: one visible, cross-fading; content per tab comes in later passes */
.prod-panels { position: relative; margin-top: var(--space-10); min-height: 200px; }
.prod-panel { opacity: 0; transform: translateY(10px); transition: opacity .3s ease, transform .3s ease; }
.prod-panel.is-active { opacity: 1; transform: none; }

/* ── 5 · A thousand calls is a profile ────────────────────────────── */
.prod-scale { background: linear-gradient(180deg, var(--primary-500) 0%, var(--primary-800) 100%); --plines: 5; }   /* the frame's Background/gradient 1; 5 point lines on the swipe cards (322–342 wide: two points wrap). Below 1024 only — from 1024 the tiles share one grid and size themselves, see the subgrid block */
.prod-scale__copy { display: flex; flex-direction: column; gap: var(--space-4); }
.prod-scale__copy h2 { max-width: none; }              /* full width, wraps with the screen (2026-09-22) */
.prod-scale__copy p { max-width: none; font-size: var(--t-p1); }
/* the tiles (Figma component 85). Rest: grey glass, 281 tall, rounded top only,
   content at the foot. Hover: grows to 340 (upward — the row is bottom-aligned)
   onto the cyan→purple gradient. Every tile shares one internal grid with fixed
   rows so names, subs and points sit level across the row at rest.          */
.prod-tiles { margin-top: var(--space-10); }
.prod-tiles__row {
    display: flex; gap: var(--space-5); align-items: flex-end;
    overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none;
    margin-inline: calc(var(--page-gutter) * -1); padding-inline: var(--page-gutter); scroll-padding-inline: var(--page-gutter);
}
.prod-tiles__row::-webkit-scrollbar { display: none; }
.prod-tiles__dots { color: var(--c-text); }
.ptile {
    position: relative; isolation: isolate;
    flex: 0 0 auto; width: min(342px, calc(100vw - var(--page-gutter) - var(--space-5) - 28px)); scroll-snap-align: start;
    /* The swipe row below 1024: rows reserved in LINES, not px, so they hold at
       every tile width — name 2 · sub 2 · points --plines. From 1024 the tiles
       subgrid their rows off the shared row grid instead and this is overridden. */
    display: grid; grid-template-rows: auto 2.9em minmax(calc(var(--plines) * 1.4em + 8px), auto); align-content: end; gap: var(--space-3);   /* minmax: a narrow phone that wraps one more line grows the tile instead of spilling past its foot */
    min-height: 281px; padding: var(--space-6);
    color: var(--c-text);
}
/* the surface is its own layer so growing it never changes the tile's box: the
   row, the siblings and the section below stay exactly where they are     */
.ptile::before {
    content: ''; position: absolute; inset: 0; z-index: -1; border-radius: 16px 16px 0 0;
    background: var(--gloss-sheen), rgba(80, 80, 80, .2);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18);
    transition: top .35s cubic-bezier(.2, .7, .2, 1), background-color .35s ease, box-shadow .35s ease;
}
.ptile::after {                                        /* the lit surface, faded in over the grey one */
    content: ''; position: absolute; inset: 0; z-index: -1; border-radius: 16px 16px 0 0;
    /* The frame's gradient 2 exactly: cyan to the purple wash over the whole tile.
       Ending it early (it used to stop at 55%) left a steep ramp meeting a flat
       field, and that join read as a hairline across the tile. Running it to the
       foot removes the join; the type follows the surface instead — see below. */
    background: var(--gloss-sheen), linear-gradient(180deg, var(--c-accent-cyan) 0%, rgba(94, 55, 110, .3) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 0 40px rgba(171, 235, 240, .25);
    opacity: 0;
    transition: top .35s cubic-bezier(.2, .7, .2, 1), opacity .35s ease;
}
.ptile__name { align-self: end; min-height: 2.2em; display: flex; align-items: flex-end; font-size: clamp(26px, 1.6vw + 12px, 36px); line-height: 1.1; font-weight: var(--fw-regular); }   /* two lines reserved; 36 at 1440 (the frame), 28 at 1024 */
.ptile__sub { align-self: start; font-size: var(--t-p2); color: rgba(255, 249, 245, .85); }
/* Lit, the surface runs pale cyan at the top to deep purple at the foot, so one ink
   cannot serve the whole tile: cream on the name measures 2.4:1, dark on the bullets
   2.4:1. The type follows the surface — name and sub-line go dark where the ground is
   pale (7.1:1 and 5.0:1), the bullets stay cream on the dark foot (7.1:1).        */
.ptile__name, .ptile__sub { transition: color .35s ease; }
.ptile__points { align-self: start; display: flex; flex-direction: column; gap: 4px; padding-left: 1.1em; list-style: disc; font-size: var(--t-p2); color: rgba(255, 249, 245, .85); }
.ptile__points li::marker { color: var(--c-accent-cyan); }
/* the lit state: the cyan→purple surface (the frame's Background/gradient 2), the
   type staying white as in the frame (dark type was unreadable on the purple foot).
   Hover only where hover exists: on a phone a tapped tile would otherwise stay
   "hovered" after the swipe and light up beside the current one. The 59px growth
   (281 → 340, upward, on the surface only) is a desktop-row move; the swipe row
   below 1024 lights the current tile without growing it, so nothing above the
   row has to hold space for it.                                             */
@media (hover: hover) {
    .ptile:hover::after, .ptile:focus-within::after { opacity: 1; }
    .ptile:hover .ptile__name, .ptile:focus-within .ptile__name { color: var(--primary-500); }
    .ptile:hover .ptile__sub,  .ptile:focus-within .ptile__sub  { color: rgba(50, 0, 65, .85); }
}
@media (hover: hover) and (min-width: 1024px) {
    .ptile:hover::before, .ptile:focus-within::before, .ptile:hover::after, .ptile:focus-within::after { top: -32px; }   /* the frame grows 59; 32 keeps the move and halves the headroom the row must hold */
}
/* in carousel mode (below 1024) the current tile is lit */
@media (max-width: 1023px) {
    .ptile.is-current::after { opacity: 1; }
    .ptile.is-current .ptile__name { color: var(--primary-500); }
    .ptile.is-current .ptile__sub  { color: rgba(50, 0, 65, .85); }
}
/* …and only one tile is ever lit: with a mouse over another tile, the current one gives the light up */
@media (hover: hover) and (max-width: 1023px) {
    .prod-tiles__row:hover .ptile.is-current:not(:hover)::after { opacity: 0; }
    .prod-tiles__row:hover .ptile.is-current:not(:hover) .ptile__name { color: var(--c-text); }
    .prod-tiles__row:hover .ptile.is-current:not(:hover) .ptile__sub  { color: rgba(255, 249, 245, .85); }
}

/* ── 6 · Outcomes: the frame — four L-shaped hairlines on the dark ground, a
   lighter lit band across the lower part of the section that the tiles sit
   into (the frame's 207px cyan ellipse, blurred, under a purple plate).    */
.prod-outcomes { position: relative; overflow: hidden; background: var(--c-primary-dark); --lines: 3; --dots-block: 32px; }
/* the lit band. The frame: a blurred cyan ellipse low in the section with a flat
   dark rectangle laid over its lower half, so the light spreads UPWARD behind the
   tile names and stops on a hard edge just under them; the lines of text below sit
   on the plain ground. --otile-foot is that edge, measured from the tile's bottom
   line: the bottom padding, the reserved text lines, and 6px of air.          */
.prod-outcomes { --otile-foot: calc(var(--space-6) + var(--lines) * 22.4px + 6px); }
.prod-outcomes::before, .prod-outcomes::after { content: ''; position: absolute; left: 0; right: 0; pointer-events: none; }
.prod-outcomes::before { bottom: calc(var(--space-15) + var(--dots-block) + var(--otile-foot)); height: 300px; background: linear-gradient(0deg, rgba(171, 235, 240, .2) 0%, rgba(171, 235, 240, .11) 40%, rgba(171, 235, 240, 0) 100%); }
.prod-outcomes::after  { top: calc(100% - var(--space-15) - var(--dots-block) - var(--otile-foot)); bottom: 0; background: var(--c-primary-dark); }
.prod-outcomes .container { position: relative; z-index: 1; }   /* above the band and its mask */
.prod-outcomes .prod-tiles { margin-top: var(--space-8); }
.prod-tiles--audiences .prod-tiles__row { padding-top: 8px; }   /* no upward growth here — only the lift's 4px */
.prod-outcomes .prod-tiles__row { padding-top: 8px; }   /* the dots sit 3.5px above the line */
.otile {
    position: relative; flex: 0 0 auto; width: min(300px, calc(100vw - var(--page-gutter) - var(--space-5) - 28px)); scroll-snap-align: start;
    display: grid; grid-template-rows: 1fr auto; align-items: end; gap: var(--space-3);
    min-height: 263px; padding: var(--space-6) var(--space-3) var(--space-6) var(--space-4);   /* the frame: 26px from the text to the line */
    background: none;
    transition: transform .3s ease;
}
/* the L: a dot, a hairline down the left edge, a true 16px quarter-circle into the
   bottom edge (the frame's SVG has a hand-drawn wobble in that corner — smoothed) */
.otile::before { content: ''; position: absolute; left: 3px; top: 7px; right: 0; bottom: 2px; border-left: 1px solid rgba(255, 255, 255, .85); border-bottom: 1px solid rgba(255, 255, 255, .85); border-bottom-left-radius: 16px; transition: border-color .3s ease; pointer-events: none; }
.otile::after  { content: ''; position: absolute; left: 0; top: 0; width: 7px; height: 7px; border-radius: 50%; background: #FFFFFF; transition: background-color .3s ease, filter .3s ease; }
.otile__name { align-self: end; font-size: clamp(24px, 1.2vw + 12px, 36px); line-height: 1.35; font-weight: var(--fw-regular); }
.otile__text { align-self: start; min-height: calc(var(--lines) * 1.4em); font-size: var(--t-p2); color: var(--c-text); }   /* lines reserved (the frame: text at a fixed y), so the names above sit level */
.otile:hover, .otile.is-current { transform: none; }
.otile:hover::before, .otile.is-current::before { border-color: var(--c-accent-cyan); }
.otile:hover::after, .otile.is-current::after { background: var(--c-accent-cyan); filter: drop-shadow(0 0 5px rgba(171, 235, 240, 1)); }

/* ── 7 · Who it's for: four tiles (Figma component 78) ─────────────── */
.prod-audiences { background: var(--c-primary-dark); }
.atile {
    position: relative; isolation: isolate; flex: 0 0 auto; width: min(300px, calc(100vw - var(--page-gutter) - var(--space-5) - 28px)); scroll-snap-align: start;
    display: grid; grid-template-rows: auto 3.1em; align-content: end; gap: var(--space-3);
    min-height: 335px; padding: var(--space-6);
    color: var(--c-text);
}
.atile::before, .atile::after { content: ''; position: absolute; inset: 0; z-index: -1; border-radius: 16px; }
.atile::before {
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .09) 0%, rgba(255, 255, 255, .03) 30%, rgba(255, 255, 255, 0) 55%, rgba(0, 0, 0, .2) 100%),
        radial-gradient(ellipse 70% 50% at 15% 0%, rgba(255, 255, 255, .08) 0%, rgba(255, 255, 255, 0) 60%),
        rgba(80, 80, 80, .2);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), inset 0 -1px 0 rgba(0, 0, 0, .3), 0 16px 40px rgba(0, 0, 0, .35);
}
.atile::after  { background: var(--gloss-sheen), linear-gradient(180deg, rgba(220, 104, 255, .4) 0%, rgba(0, 0, 0, .4) 100%); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 0 40px rgba(232, 182, 240, .25); opacity: 0; transition: opacity .35s ease; }
.atile.is-current::after { opacity: 1; }   /* carousel mode: the current tile (products.js sets it only below 1024) */
/* hover only where hover exists (a tapped tile would otherwise stay lit beside the current one) */
@media (hover: hover) {
    .atile:hover::after, .atile:focus-within::after { opacity: 1; }
    .js .atile.is-visible:hover, .js .atile.is-visible:focus-within { transform: translateY(-4px); transition-duration: .3s; }   /* outranks the reveal's transform: none */
}
/* …and one lit tile at a time: with a mouse over another tile, the current one gives the light up */
@media (hover: hover) and (max-width: 1023px) {
    .prod-tiles__row:hover .atile.is-current:not(:hover)::after { opacity: 0; }
}
.atile__shine { position: absolute; inset: 0; z-index: 0; border-radius: inherit; overflow: hidden; pointer-events: none; }   /* clips its own reflection so the tile's shadows stay unclipped */
.atile__shine::before { content: ""; position: absolute; inset: -40% -60%; background: linear-gradient(115deg, rgba(255, 255, 255, 0) 40%, rgba(255, 255, 255, .12) 50%, rgba(255, 255, 255, 0) 60%); transform: translateX(-60%); }   /* the reflection: once, on the way in */
@media (hover: hover) { .atile:hover .atile__shine::before { transform: translateX(60%); transition: transform .9s ease; } }
.atile > .atile__name, .atile > .atile__text { position: relative; z-index: 1; }
/* the motifs (like Why Voice's science cards): one small drawing per audience,
   top-right, animating only while the tile is on screen                      */
.atile__art { position: absolute; top: var(--space-6); right: var(--space-6); left: var(--space-6); z-index: 1; display: flex; justify-content: center; }   /* centred (2026-09-22) */
.atile__art svg { width: min(200px, 100%); height: auto; overflow: visible; }
.atile__art [class^="art-"] { transform-box: fill-box; transform-origin: center; }
/* risk: the read pulses where the line turns */
.atile--risk.is-visible .art-ring { animation: art-pulse 2.6s ease-out infinite; }
.atile--risk.is-visible .art-dot  { animation: art-glow 2.6s ease-out infinite; }
.atile--risk.is-visible .art-slip { animation: art-slip 2.6s ease-in-out infinite; }
@keyframes art-pulse { 0% { transform: scale(.4); opacity: 1; } 70%, 100% { transform: scale(2.2); opacity: 0; } }
@keyframes art-glow  { 0%, 100% { filter: none; } 15% { filter: drop-shadow(0 0 6px #ABEBF0); } }
@keyframes art-slip  { 0%, 100% { stroke-dashoffset: 0; } 50% { stroke-dashoffset: -7; } }
/* coach: the playhead rewinds the recording to the moment (x≈106), the moment's bars light,
   the pin drops and the note opens above it; one 6s clock                    */
.atile--coach .art-pin, .atile--coach .art-note { opacity: 0; }
.atile--coach.is-visible .art-play   { animation: art-rewind 6s ease-in-out infinite; }
.atile--coach.is-visible .art-moment { animation: art-moment 6s ease-out infinite; }
.atile--coach.is-visible .art-pin    { animation: art-pin 6s ease-out infinite; }
.atile--coach.is-visible .art-note   { animation: art-note 6s ease-out infinite; }
@keyframes art-rewind { 0%, 8% { transform: translateX(0); opacity: 1; } 34%, 88% { transform: translateX(-90px); opacity: 1; } 94%, 100% { transform: translateX(-90px); opacity: 0; } }
@keyframes art-moment { 0%, 32% { fill: #FFF9F5; fill-opacity: .38; } 38%, 88% { fill: #ABEBF0; fill-opacity: 1; } 94%, 100% { fill: #FFF9F5; fill-opacity: .38; } }
@keyframes art-pin    { 0%, 36% { opacity: 0; transform: translateY(-8px); } 42%, 88% { opacity: 1; transform: translateY(0); } 94%, 100% { opacity: 0; } }
@keyframes art-note   { 0%, 44% { opacity: 0; transform: translateY(4px); } 50%, 88% { opacity: 1; transform: translateY(0); } 94%, 100% { opacity: 0; } }
/* forecast: the signal line draws through the stages to its end point, holds, and redraws */
.atile--forecast .art-signal { stroke-dasharray: 1; stroke-dashoffset: 1; }
.atile--forecast .art-end { opacity: 0; }
.atile--forecast.is-visible .art-signal { animation: art-draw 5s ease-in-out infinite; }
.atile--forecast.is-visible .art-end { animation: art-end 5s ease-in-out infinite; }
@keyframes art-draw { 0% { stroke-dashoffset: 1; } 35%, 85% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 1; } }
@keyframes art-end  { 0%, 30% { opacity: 0; } 38%, 85% { opacity: 1; filter: drop-shadow(0 0 6px #ABEBF0); } 100% { opacity: 0; } }
/* renewal: the account travels the timeline; the ring fires as it passes the signal, long before the marker */
.atile--renewal .art-ring { opacity: 0; }
.atile--renewal.is-visible .art-mover { animation: art-travel 5s linear infinite; }
.atile--renewal.is-visible .art-ring  { animation: art-catch 5s ease-out infinite; }
@keyframes art-travel { 0% { transform: translateX(0); opacity: 0; } 6% { opacity: 1; } 94% { transform: translateX(170px); opacity: 1; } 100% { transform: translateX(170px); opacity: 0; } }
@keyframes art-catch  { 0%, 58% { transform: scale(.4); opacity: 0; } 60% { opacity: 1; } 85%, 100% { transform: scale(2.4); opacity: 0; } }
.atile__name { min-height: 2.2em; display: flex; align-items: flex-end; font-size: clamp(26px, 1.6vw + 12px, 36px); line-height: 1.1; font-weight: var(--fw-regular); }
.atile__text { font-size: var(--t-p2); color: rgba(255, 249, 245, .85); }

/* ── 8 · Compliance: three purple tiles; a swipe row below 1024 ───────── */
.prod-compliance { background: linear-gradient(180deg, var(--primary-500) 0%, var(--c-primary-purple) 45%, var(--primary-800) 100%); }   /* the frame's #2E003B, lit at the top and settling toward the CTA band below (added 2026-09-22) */
.ctile {
    position: relative; flex: 0 0 auto; width: min(300px, calc(100vw - var(--page-gutter) - var(--space-5) - 28px)); scroll-snap-align: start;
    min-height: 310px;   /* 258 in the frame; taller to house the motif above the copy */
    container-type: inline-size;   /* the name sizes down to stay on one line: 'Glass box, not black box' is 11.9em, so ≤ 8.1cqi (a little under, for rounding); never under 24 (then it wraps into its reserved second line) */
    display: grid; grid-template-rows: auto 2.5em 4.3em; align-content: end; gap: var(--space-3);   /* name 2 lines reserved · text 3 lines: level across the row */
    padding: var(--space-6);
    border-radius: 16px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .14) 0%, rgba(255, 255, 255, .04) 30%, rgba(255, 255, 255, 0) 55%, rgba(0, 0, 0, .16) 100%),
        radial-gradient(ellipse 70% 50% at 15% 0%, rgba(171, 235, 240, .14) 0%, rgba(171, 235, 240, 0) 60%),
        var(--primary-400);   /* the frame's #5E376E under the site's sheen, corner light and darkened foot */
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .35), inset 0 -1px 0 rgba(0, 0, 0, .35), 0 16px 40px rgba(0, 0, 0, .35);
}
.prod-tiles--compliance .prod-tiles__row { padding-top: 8px; }   /* the lift's 4px only */
@media (max-width: 1023px) { .ctile.is-current { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 -1px 0 rgba(0, 0, 0, .35), 0 24px 48px rgba(0, 0, 0, .4), var(--gloss-glow); } }   /* swipe row: the current tile glows */
/* the motifs, top-right (the §7 device). These run whenever the tile is drawn:
   swipe row and desktop row alike (three small drawings) */
.ctile__art { position: absolute; top: var(--space-6); right: var(--space-6); left: var(--space-6); display: flex; justify-content: center; }   /* centred (2026-09-22) */
.ctile__art svg { width: min(200px, 100%); height: auto; overflow: visible; }
.ctile__art [class^="art-"] { transform-box: fill-box; transform-origin: center; }
/* on-premise: a patrol light circles the wall; the calls drift inside and never cross it */
.art-patrol { stroke-dasharray: .12 .88; stroke-dashoffset: 0; animation: art-patrol 6s linear infinite; }
@keyframes art-patrol { to { stroke-dashoffset: -1; } }
.art-call--1 { animation: art-call-1 7s ease-in-out infinite alternate; }
.art-call--2 { animation: art-call-2 6s ease-in-out infinite alternate; }
.art-call--3 { animation: art-call-3 8s ease-in-out infinite alternate; }
@keyframes art-call-1 { 0% { transform: translate(0, 0); } 35% { transform: translate(40px, 22px); } 70% { transform: translate(6px, 26px); } 100% { transform: translate(46px, -6px); } }
@keyframes art-call-2 { 0% { transform: translate(0, 0); } 40% { transform: translate(-28px, -24px); } 100% { transform: translate(26px, -30px); } }
@keyframes art-call-3 { 0% { transform: translate(0, 0); } 30% { transform: translate(-46px, 18px); } 65% { transform: translate(-10px, -18px); } 100% { transform: translate(4px, 20px); } }
/* glass box: the read lights, the trace runs to the second, the second lights, the trace runs on and the sentence lights */
.art-trace { stroke-dasharray: .18 1.82; stroke-dashoffset: .18; animation: art-trace 4.5s linear infinite; }   /* gap longer than the path: one segment only, no second one entering at the box while the first lands */
.art-read { animation: art-lit 4.5s ease-in-out infinite; }
.art-second { opacity: .35; animation: art-second 4.5s ease-in-out infinite; }
.art-sentence { animation: art-sentence 4.5s ease-in-out infinite; }
@keyframes art-trace    { 0%, 10% { stroke-dashoffset: .18; } 75%, 100% { stroke-dashoffset: -1; } }   /* linear: the same speed along the box, the dive to the second and the run to the sentence */
@keyframes art-lit      { 0%, 100% { filter: none; } 8%, 20% { filter: drop-shadow(0 0 6px #ABEBF0); } }
@keyframes art-second   { 0%, 40% { opacity: .35; filter: none; } 48%, 90% { opacity: 1; filter: drop-shadow(0 0 5px #ABEBF0); } 100% { opacity: .35; } }
@keyframes art-sentence { 0%, 68% { fill: #FFF9F5; fill-opacity: .3; } 76%, 92% { fill: #ABEBF0; fill-opacity: 1; } 100% { fill: #FFF9F5; fill-opacity: .3; } }
/* deterministic: the playhead replays row one, two, three; the read lands at the same point on each; the line and the ticks confirm it */
.art-head { animation: art-head 7s linear infinite; }
.art-land, .art-same, .art-ticks path { opacity: 0; }
/* one 7s clock for everything (no delays: a delayed loop would carry row three's
   landing into the next replay); the head reaches x=100 at 17 / 45.6 / 74.1% */
.art-land { animation: art-land-0 7s ease-out infinite; } .art-land[style*="--k: 1"] { animation-name: art-land-1; } .art-land[style*="--k: 2"] { animation-name: art-land-2; }
.art-ticks path { animation: art-tick-0 7s ease-out infinite; } .art-ticks path[style*="--k: 1"] { animation-name: art-tick-1; } .art-ticks path[style*="--k: 2"] { animation-name: art-tick-2; }
.art-same { animation: art-same 7s ease-out infinite; }
.art-row { animation: art-row-0 7s ease-out infinite; } .art-row[style*="--k: 1"] { animation-name: art-row-1; } .art-row[style*="--k: 2"] { animation-name: art-row-2; }
@keyframes art-land-1 { 0%, 45.6% { opacity: 0; transform: scale(.4); } 47.6% { opacity: 1; transform: scale(1.4); } 50.6%, 90% { opacity: 1; transform: scale(1); } 96%, 100% { opacity: 0; } }
@keyframes art-land-2 { 0%, 74.1% { opacity: 0; transform: scale(.4); } 76.1% { opacity: 1; transform: scale(1.4); } 79.1%, 90% { opacity: 1; transform: scale(1); } 96%, 100% { opacity: 0; } }
@keyframes art-tick-1 { 0%, 54.5% { opacity: 0; } 57%, 90% { opacity: 1; } 96%, 100% { opacity: 0; } }
@keyframes art-tick-2 { 0%, 83% { opacity: 0; } 85.5%, 90% { opacity: 1; } 96%, 100% { opacity: 0; } }
@keyframes art-row-1 { 0%, 28.6% { stroke-opacity: .35; } 32%, 52% { stroke-opacity: .8; } 58%, 100% { stroke-opacity: .35; } }
@keyframes art-row-2 { 0%, 57.1% { stroke-opacity: .35; } 61%, 81% { stroke-opacity: .8; } 87%, 100% { stroke-opacity: .35; } }
@keyframes art-head { 0% { transform: translate(0, 0); opacity: 1; } 26% { transform: translate(146px, 0); opacity: 1; } 28.5% { transform: translate(146px, 0); opacity: 0; }
                      28.6% { transform: translate(0, 18px); opacity: 0; } 30% { opacity: 1; } 54.5% { transform: translate(146px, 18px); opacity: 1; } 57% { transform: translate(146px, 18px); opacity: 0; }
                      57.1% { transform: translate(0, 36px); opacity: 0; } 58.5% { opacity: 1; } 83% { transform: translate(146px, 36px); opacity: 1; } 85.5%, 100% { transform: translate(146px, 36px); opacity: 0; } }
@keyframes art-land-0 { 0%, 17% { opacity: 0; transform: scale(.4); } 19% { opacity: 1; transform: scale(1.4); } 22%, 90% { opacity: 1; transform: scale(1); } 96%, 100% { opacity: 0; } }
@keyframes art-tick-0 { 0%, 26% { opacity: 0; } 28.5%, 90% { opacity: 1; } 96%, 100% { opacity: 0; } }
@keyframes art-same { 0%, 84% { opacity: 0; } 87%, 95% { opacity: 1; } 100% { opacity: 0; } }
@keyframes art-row-0 { 0% { stroke-opacity: .35; } 4%, 24% { stroke-opacity: .8; } 30%, 100% { stroke-opacity: .35; } }
.ctile__name { grid-row: 2; align-self: end; font-size: max(24px, min(var(--t-h3), 8.1cqi)); line-height: var(--lh-heading); font-weight: var(--fw-medium); color: var(--c-accent-cyan); }
.ctile__text { grid-row: 3; align-self: start; font-size: var(--t-p2); color: var(--c-accent-cyan); }

/* ── Desktop ──────────────────────────────────────────────────────── */
@media (min-width: 1024px) {
    .prod-hero { min-height: 693px; }
    .prod-hero__inner { flex-direction: row; align-items: center; justify-content: space-between; gap: var(--space-10); }
    .prod-hero__copy { flex: 1 1 0; min-width: 0; max-width: 668px; }                    /* the frame's 668 at 1440; narrower below */
    .prod-hero h1 { max-width: 14ch; }   /* capped only beside the visual; stacked, the headline runs the full width */
    .radar { flex: 0 0 clamp(340px, 34vw, 480px); width: clamp(340px, 34vw, 480px); margin: 0; }   /* 480 at 1440, 348 at 1024 */

    .prod-problem { padding-block: 0; }
    .prod-problem__grid { flex-direction: row; align-items: stretch; gap: 0; min-height: 339px; }
    .prod-problem__copy { flex: 0 0 50%; justify-content: center; padding-block: var(--space-15); padding-right: var(--space-10); }
    .prod-problem__copy h2 { max-width: 14ch; }   /* capped only beside the logged block; stacked, it runs full width */
    .prod-logged { flex: 1; min-height: 339px; gap: var(--space-10); padding: var(--space-15) 43px var(--space-15) 96px; margin-inline: 0; }   /* the frame: label 60 above the ticker, note 40 below; 96 in from the left bar, 43 from the right */
    .prod-logged::before, .prod-logged::after { width: 31px; }

    .prod-gone { flex-direction: row; align-items: stretch; justify-content: space-between; gap: var(--space-6); padding: 0 var(--space-8) 0 0; }
    .prod-gone__list { flex-direction: row; flex: 1 1 0; min-width: 0; gap: 0; }
    /* each phrase is a cell: it wraps to two lines when the bar is narrow (1024–1300),
       so GONE always has its room; the divider is the cell's left edge, running the
       bar's full height with the dot sitting on the top edge                      */
    .prod-gone__list li { flex: 1 1 0; min-width: 0; display: flex; align-items: center; padding: var(--space-8) var(--space-5); }
    .prod-gone__list li:first-child { padding-left: var(--space-8); }

    /* in the row the divider is vertical: the cell's left edge, dot on the bar's top edge */
    .prod-gone__list li + li::before { left: 0; right: auto; top: 0; bottom: 0; width: 2px; height: auto; background: linear-gradient(180deg, #FFFFFF 0%, rgba(89, 72, 94, 1) 100%); }
    .prod-gone__list li + li::after  { left: -4px; top: -5px; }
    .prod-gone__word { flex: 0 0 auto; align-self: center; margin-top: 0; }
    .ticker--h2 { height: 1.25em; --row: 1.25em; }
    .ticker--h2 .ticker__list li { height: 1.25em; white-space: nowrap; }

    .prod-tiles__row { display: flex; overflow: visible; margin-inline: 0; padding-inline: 0; scroll-snap-type: none; gap: var(--space-5); padding-top: 32px; }   /* room for the hover growth */   /* 20 between the profile tiles (40 wrapped 'Competitive position' and the first sub line at 1440) */
    /* The three profile tiles share one grid, so name, sub-line and bullets sit on
       the same tracks whatever the copy wraps to. Replaces a reserved line count
       (--plines) that had to be re-guessed per page and per breakpoint, and was
       wrong in four bands by 2026-10-06. The swipe row below 1024 still uses it. */
    .prod-scale .prod-tiles__row {
        display: grid; grid-template-columns: repeat(3, 1fr);
        grid-template-rows: minmax(0, 1fr) auto minmax(2.9em, auto) auto;   /* slack, then name / sub / bullets; the sub keeps its 2-line reserve so the gap above the bullets is unchanged */
        column-gap: var(--space-5); row-gap: var(--space-3); align-items: stretch;
        min-height: calc(281px + 32px);   /* the frame's 281 resting tile plus the 32 of padding-top the hover growth needs: min-height is border-box, so the headroom has to be added back */
    }
    .prod-scale .ptile { grid-row: 1 / span 4; grid-template-rows: subgrid; row-gap: var(--space-3); }   /* a subgrid uses its OWN gutters, so the row gap is restated */
    .prod-scale .ptile__name   { grid-row: 2; }   /* explicit: auto-placement would put the sub above the name */
    .prod-scale .ptile__sub    { grid-row: 3; }
    .prod-scale .ptile__points { grid-row: 4; }
    .prod-scale { padding-bottom: 0; }   /* the frame: the three tiles stand on the section's bottom edge (row mode only) */
    .prod-tiles__row--4 { gap: var(--space-5); }
    .ptile, .otile, .atile, .ctile { flex: 1 1 0; width: auto; min-width: 0; }
    .prod-outcomes { --dots-block: 0px; }
    .prod-outcomes .prod-tiles__row { gap: var(--space-10); justify-content: space-between; }
    .otile { flex: 0 1 300px; }   /* the frame: 300 wide, 40 apart, spread across the 1320 */
    .prod-tiles__dots { display: none; }
    /* the frame staggers the audience tiles: 2nd and 4th sit 125px lower, and
       two open-U connectors (the frame's SVG) join 1→2 above the row's foot
       and 3→4 below it. In the frame the tiles are 300 wide with 40 gaps
       (1320 = 4×300 + 3×40); the connector spans a tile's left edge to the
       next tile's right edge minus a margin (343 wide, 257 tall).            */
    .prod-tiles__row--4 .atile:nth-child(even) { margin-top: 125px; }
    .prod-tiles__row--4:has(.atile) { align-items: flex-start; }
    .prod-tiles--audiences { position: relative; isolation: isolate; }
    /* frame coordinates (section 1440 wide, tiles 300 wide at x=60/400/740/1080,
       y=256 for 1 and 3, y=467 for 2 and 4, all 335 tall): connectors 340×256 at
       (210,591) and (890,591) — i.e. starting a third of the way into tile 1 (3),
       dropping from the tile's FOOT, along under tile 2 (4), up its right edge.
       The row here starts at the container's left (x=60 → 0) and is 1320 wide. */
    /* the frame's four connector instances: two at y=591 (below tiles 1→2 and
       3→4) and two flipped at y=211 above them (the frame's 8162/8163 at (550,211)
       and (890,591)). The rendered frame shows: 1→2 rising ABOVE the row from
       tile 1's third to tile 2's right edge; 3→4 dropping BELOW. Reproduced as
       one shape and its vertical mirror.                                   */
    /* the staggered arrangement kept (no connectors, 2026-09-22); the row's
       own spacing: the usual gap under the copy, and the section's padding below
       the two lower tiles                                                  */
    .prod-tiles--audiences { margin-top: var(--space-10); }

    /* compliance: a plain 3-up row from 1024 (the swipe row is below 1024) */
    .prod-tiles__row--3 { gap: var(--space-5); }
    .ctile { transition: transform .3s ease, box-shadow .3s ease; }
    .js .ctile.is-visible:hover { transform: translateY(-4px); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 -1px 0 rgba(0, 0, 0, .35), 0 24px 48px rgba(0, 0, 0, .4), var(--gloss-glow); }

    .prod-reads__head { flex-direction: row; align-items: flex-end; justify-content: space-between; gap: var(--space-10); }   /* the frame: copy left, tabs right, bottom-aligned */
    .prod-reads__copy { flex: 0 1 585px; }
    .prod-tabs { flex: 0 0 auto; flex-wrap: nowrap; }
}

/* outcomes: the reserved text lines follow the tile width (the longest line — Consistent performance — sets it):
   300 wide on phones and from 1440 → 3 lines; 245–299 (1200–1439) → 4; 205–244 (1024–1199) → 5 */
@media (min-width: 1024px) and (max-width: 1199px) { .prod-outcomes { --lines: 5; } }
@media (min-width: 1200px) and (max-width: 1439px) { .prod-outcomes { --lines: 4; } }

/* ── AVI_Collections ──────────────────────────────────────────────────── */

/* 1 · hero: the frame's render as a full-bleed ground, the copy low-left (the
   frame puts it at y=387 of 774). The image is the designer's 1258×676 raster,
   covering; a 768 cut on phones. TODO: a live visual in a later pass.        */
.prod-hero--collections { position: relative; overflow: hidden; align-items: flex-end; background: var(--primary-900); }
.prod-hero__bg { position: absolute; inset: 0; z-index: 0; }
.prod-hero__bg img { width: 100%; height: 100%; object-fit: cover; object-position: 60% 50%; display: block; }
.prod-hero--collections::before { content: ''; position: absolute; inset: 0; z-index: 0; background: linear-gradient(180deg, rgba(21, 0, 27, 0) 30%, rgba(21, 0, 27, .82) 62%, rgba(21, 0, 27, .95) 100%); }   /* the copy's footing over the chrome */
.prod-hero--collections::after { content: ''; position: absolute; inset: 0; z-index: 0; background: linear-gradient(90deg, rgba(21, 0, 27, .9) 0%, rgba(21, 0, 27, .55) 34%, rgba(21, 0, 27, 0) 62%); }   /* a scrim down the copy's side: the render's ribbons run bright right through it */
/* phones: the frame's own crop (483:7173) — a portrait slice with the ring high,
   the copy on the dark ground under it, as in the mobile frame                */
@media (max-width: 767px) {
    /* the crop sits on top in a band of its own, tall enough to hold the whole ring at
       any phone width (the crop is 469×752 and the ring ends at ~40% of it, so 0.72 of
       the viewport width clears it with room to spare); the copy follows on the solid
       ground beneath. No viewport-height maths: a short phone scrolls a little rather
       than squeezing the image away — which is what a height-driven hero did.      */
    .prod-hero--collections { display: flex; flex-direction: column; align-items: stretch; min-height: 0; padding-top: 0; padding-bottom: 0; }
    .prod-hero--collections .prod-hero__bg { position: relative; inset: auto; flex: 0 0 auto; height: clamp(260px, 72vw, 420px); overflow: hidden; }
    .prod-hero--collections .prod-hero__bg img { height: 100%; object-fit: cover; object-position: 50% 4%; }
    .prod-hero--collections .prod-hero__bg::after { content: ''; position: absolute; inset: auto 0 -1px 0; height: 110px; background: linear-gradient(180deg, rgba(21, 0, 27, 0) 0%, rgba(21, 0, 27, .75) 55%, var(--primary-900) 100%); }
    .prod-hero--collections::before, .prod-hero--collections::after { background: none; }
    .prod-hero--collections .prod-hero__inner { flex: 0 0 auto; padding-top: var(--space-5); padding-bottom: var(--space-10); }
}
/* tablets: the frame has no cut for this tier. The landscape render is squeezed into a
   short band here, which puts the copy on the bright chrome — so the hero keeps a
   height and the ground is pulled darker under the copy.                        */
@media (min-width: 768px) and (max-width: 1023px) {
    .prod-hero--collections { min-height: 560px; }
    .prod-hero--collections .prod-hero__bg img { object-position: 42% 22%; }
    .prod-hero--collections::before { background: linear-gradient(180deg, rgba(21, 0, 27, .1) 0%, rgba(21, 0, 27, .35) 30%, rgba(21, 0, 27, .88) 66%, rgba(21, 0, 27, .96) 100%); }
    .prod-hero--collections::after { background: linear-gradient(90deg, rgba(21, 0, 27, .75) 0%, rgba(21, 0, 27, .3) 45%, rgba(21, 0, 27, 0) 80%); }
}
.prod-hero--collections .prod-hero__inner { position: relative; z-index: 1; }
.prod-hero--collections .prod-hero__copy { max-width: none; }
.prod-hero--collections h1 { max-width: 36ch; }   /* the frame: two lines across the 1320 */

/* 4 · the read a normal audit can't reveal: one sentence, two readings. The frame:
   a blurred purple→cyan band across the middle, the words half dark, the voice half
   a frosted white wash; H3 above and below. Stacked below 768.                  */
.prod-audit { position: relative; overflow: hidden; background: var(--c-surface-1); }
.prod-audit .container { position: relative; z-index: 1; }
/* the band sits behind the two columns and is centred on THEM, not on the section:
   Callback has no closing line under the split, so a section-centred band drifted off
   the wash and left the glow above it and a bare edge below (2026-09-24) */
.prod-audit__band { position: absolute; z-index: -1; top: 50%; left: 50%; width: 100vw; height: 220px; transform: translate(-50%, -50%); background: linear-gradient(90deg, var(--primary-800) 0%, var(--primary-300) 56%, var(--c-accent-cyan) 100%); filter: blur(25px); opacity: .9; }
.prod-audit__title, .prod-audit__close { text-align: left; font-size: var(--t-h3); line-height: var(--lh-heading); font-weight: var(--fw-medium); }   /* stacked: left, with the rest of the page; the frame's centring returns at 768 */
.prod-audit__split { position: relative; display: grid; grid-template-columns: 1fr; margin-block: var(--space-8); }
/* stacked, both blocks sit on the container's own left edge, with everything else
   on the page; the two-column rules below give them their insets back */
.prod-audit__words, .prod-audit__voice { display: flex; flex-direction: column; gap: var(--space-4); padding-block: var(--space-8); padding-inline: 0; }
.prod-audit__words { text-align: left; }
/* The frame's wash (602:1426) is a 720x223 rectangle running from the centre to
   the FRAME's right edge, sitting exactly over the blurred band so its edges melt
   into the band's own blur. Ours stopped at the container gutter and took its
   height from the copy, which turned it into a floating box. Same fill, the band's
   geometry: it bleeds past the container and the section clips it. The bleed has
   to be on the element itself, not a pseudo — the reveal's clip-path clips to this
   box, and would cut anything a pseudo painted outside it.                    */
.prod-audit__voice {
    position: relative; text-align: left;
    background: rgba(253, 253, 253, .25);
    backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
    /* stacked, it is a full-width band: pulled out to the viewport edges and given
       the gutter back, so its copy lands on the container's left edge like the
       words above it (2026-09-24) */
    margin-inline: calc(var(--page-gutter) * -1);
    padding-inline: var(--page-gutter);
}
.prod-audit__label { font-size: var(--t-p1); color: var(--c-text); }
.prod-audit__line { font-size: var(--t-h4); line-height: var(--lh-heading); color: var(--c-text); }
.prod-audit__voice .prod-audit__line { color: var(--primary-500); }   /* the frame: #320041 on the light wash */
.prod-audit__verdict { font-size: var(--t-p1); color: var(--c-text); }
/* the sequence on reveal: words → the light crosses → the voice line → its verdict */
.js .prod-audit__split .prod-audit__words > * { opacity: 0; transform: translateY(8px); transition: opacity .6s ease, transform .6s ease; }
.js .prod-audit__split .prod-audit__voice { clip-path: inset(0 100% 0 0); transition: clip-path 1s cubic-bezier(.2, .7, .2, 1) .7s; }
.js .prod-audit__split .prod-audit__voice > * { opacity: 0; transform: translateY(8px); transition: opacity .6s ease, transform .6s ease; }
.js .prod-audit__split.is-visible .prod-audit__words > * { opacity: 1; transform: none; }
.js .prod-audit__split.is-visible .prod-audit__words > :nth-child(2) { transition-delay: .15s; }
.js .prod-audit__split.is-visible .prod-audit__words > :nth-child(3) { transition-delay: .3s; }
.js .prod-audit__split.is-visible .prod-audit__voice { clip-path: inset(0 0 0 0); }
.js .prod-audit__split.is-visible .prod-audit__voice > * { opacity: 1; transform: none; transition-delay: 1.3s; }
.js .prod-audit__split.is-visible .prod-audit__voice > :nth-child(2) { transition-delay: 1.5s; }
.js .prod-audit__split.is-visible .prod-audit__voice > :nth-child(3) { transition-delay: 2s; }
@media (min-width: 768px) {
    .prod-audit__title, .prod-audit__close { text-align: center; }   /* the frame centres them over the two columns */
    .prod-audit__split { grid-template-columns: 1fr 1fr; }
    .prod-audit__words { text-align: right; align-items: flex-end; padding-right: var(--space-10); }
    /* half the frame out to its right edge, at the band's own height */
    .prod-audit__words { justify-content: center; }
    .prod-audit__voice {
        justify-content: center; height: 220px; padding-block: 0;
        margin-left: 0; margin-right: -50vw;
        padding-left: var(--space-10); padding-right: 50vw;   /* the padding gives the bleed back, so the copy still wraps inside the column */
    }
    .js .prod-audit__split .prod-audit__voice { clip-path: inset(0 100% 0 0); }
}
@media (min-width: 1024px) {
    .prod-hero--collections { min-height: 774px; padding-bottom: 80px; }
    .prod-audit__band, .prod-audit__voice { height: 223px; }
}

/* 2 · the problem (Collections): the frame's ground runs black → surface-1 left to right; the
   copy sits bottom-aligned beside a glass card (white 15%, a 1px white→pink→cyan
   stroke, radius 16) listing the four dispositions. One is white, three grey; the
   white one steps down the list — the agent picking a box.                    */
.prod-problem--collections { background: linear-gradient(90deg, var(--neutral-black) 0%, var(--c-surface-1) 100%); }
.prod-box { position: relative; display: flex; flex-direction: column; gap: var(--space-6); padding: 44px 34px; border-radius: 16px; background: rgba(255, 255, 255, .15); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); box-shadow: 0 16px 40px rgba(0, 0, 0, .3); }
.prod-box::before { content: ''; position: absolute; inset: 0; border-radius: inherit; padding: 1px; background: linear-gradient(180deg, #FFFFFF 0%, var(--c-accent-pink) 50%, var(--c-accent-cyan) 100%); -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; pointer-events: none; }   /* the gradient hairline */
.prod-box__label { font-size: var(--t-p1); color: #FFF7FB; }
.prod-box__note { font-size: var(--t-p1); color: var(--teal-50); }
.prod-box__list { display: flex; flex-direction: column; font-size: var(--t-h3); line-height: 1.2; font-weight: var(--fw-medium); }
.prod-box__list li { color: var(--grey-700); animation: box-pick calc(var(--n) * 1.8s) ease-in-out calc((var(--i) - var(--n)) * 1.8s) infinite; }   /* negative delays: every line starts mid-cycle, so only one is white from the first frame */
@keyframes box-pick { 0%, 20% { color: #FFFFFF; text-shadow: 0 0 14px rgba(255, 255, 255, .35); } 25%, 100% { color: var(--grey-700); text-shadow: none; } }
@media (min-width: 1024px) {
    .prod-problem--collections .prod-problem__grid { align-items: flex-end; gap: var(--space-10); min-height: 469px; padding-block: var(--space-15); }
    .prod-problem--collections .prod-problem__copy { flex: 0 1 602px; padding: 0; justify-content: flex-end; }
    .prod-problem--collections .prod-problem__copy h2 { max-width: none; }
    .prod-box { flex: 0 1 678px; min-height: 345px; }
}

/* 7 · outcomes (Collections): copy left, four tiles in a 2×2 right, over the frame's wave under a
   cyan wash (the raster is the designer's; the sparkle badge cropped off its foot).
   Tiles (component 115): dark, radius 16, copy low; on hover the type turns teal, a
   white sheen rises from the foot and the tile throws a wide soft glow.            */
.prod-recover { position: relative; overflow: hidden; background: var(--c-primary-dark); }
.prod-recover__bg { position: absolute; inset: 0; z-index: 0; }
.prod-recover__bg img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 60%; display: block; }
.prod-recover::before { content: ''; position: absolute; inset: 0; z-index: 0; background: rgba(171, 235, 240, .1); }
.prod-recover__grid { position: relative; z-index: 1; display: flex; flex-direction: column; gap: var(--space-8); }
.prod-recover__copy { display: flex; flex-direction: column; gap: var(--space-4); }
.prod-recover__copy p { font-size: var(--t-p1); }   /* P1, as the other section bodies (the frame has P2) */
.prod-tiles--recover { margin-top: 0; }
.prod-tiles--recover .prod-tiles__row { padding-top: 8px; align-items: stretch; }   /* swipe row: every tile as tall as the tallest, whatever its copy wraps to */
.rtile {
    position: relative; isolation: isolate; flex: 0 0 auto; width: min(300px, calc(100vw - var(--page-gutter) - var(--space-5) - 28px)); scroll-snap-align: start;
    display: grid; grid-template-rows: 1fr auto auto; align-content: end; gap: var(--space-2);
    min-height: 187px; padding: var(--space-8); overflow: hidden;
    border-radius: 16px;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .1) 0%, rgba(255, 255, 255, .03) 30%, rgba(255, 255, 255, 0) 55%, rgba(0, 0, 0, .25) 100%),
        radial-gradient(ellipse 70% 50% at 15% 0%, rgba(255, 255, 255, .09) 0%, rgba(255, 255, 255, 0) 60%),
        var(--primary-900);   /* the frame's #15001B under the site's sheen, corner light and darkened foot */
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), inset 0 -1px 0 rgba(0, 0, 0, .35), 0 16px 40px rgba(0, 0, 0, .3);
    color: var(--c-text); transition: color .35s ease, box-shadow .35s ease, transform .3s ease;
}
.rtile::before, .wtile::before { content: ''; position: absolute; inset: -40% -60%; z-index: -1; pointer-events: none; background: linear-gradient(115deg, rgba(255, 255, 255, 0) 40%, rgba(255, 255, 255, .12) 50%, rgba(255, 255, 255, 0) 60%); transform: translateX(-60%); }   /* the reflection: once, on the way in */
.rtile::after { content: ''; position: absolute; inset: 0; z-index: -2; border-radius: inherit; background: linear-gradient(180deg, rgba(217, 217, 217, 0) 0%, rgba(255, 255, 255, .5) 100%); opacity: 0; transition: opacity .35s ease; }
.rtile__name { grid-row: 2; font-size: var(--t-h4); line-height: var(--lh-heading); font-weight: var(--fw-regular); }
.rtile__text { grid-row: 3; font-size: var(--t-p2); }
.rtile .prod-cyan { color: var(--c-accent-highlight); }   /* the stat stays lit at rest; on hover the whole tile turns teal and it merges */
.rtile.is-current .prod-cyan, .rtile:hover .prod-cyan { color: inherit; }
.rtile.is-current { color: var(--c-accent-highlight); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 4px 100px 20px rgba(255, 255, 255, .1); }
.rtile.is-current::after { opacity: 1; }
@media (hover: hover) {
    .rtile:hover { color: var(--c-accent-highlight); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 4px 100px 20px rgba(255, 255, 255, .1); }
    .rtile:hover::after { opacity: 1; }
    .rtile:hover::before, .wtile:hover::before { transform: translateX(60%); transition: transform .9s ease; }
    .js .rtile.is-visible:hover { transform: translateY(-4px); transition-duration: .3s; }
}
@media (hover: hover) and (max-width: 1023px) {
    .prod-tiles__row:hover .rtile.is-current:not(:hover) { color: var(--c-text); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12), 0 16px 40px rgba(0, 0, 0, .3); }
    .prod-tiles__row:hover .rtile.is-current:not(:hover)::after { opacity: 0; }
}
@media (min-width: 1024px) {
    .prod-recover__grid { flex-direction: row; align-items: flex-end; justify-content: space-between; gap: var(--space-10); }
    .prod-recover__copy { flex: 0 0 378px; }
    .prod-tiles--recover { flex: 0 1 902px; }
    .prod-tiles--recover .prod-tiles__row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-5); padding-top: 8px; }
    .rtile { width: auto; }
}

/* 8 · who it's for (Collections): H2 left and body right, then a 2×2 of alternating widths
   (components 111/112: 778 and 522 of the 1320): dark with a hairline; a pink→black
   gradient on hover. A radial white glow sits behind the middle of the grid.      */
.prod-owners { position: relative; overflow: hidden; background: var(--c-primary-dark); }
.prod-owners::before { content: ''; position: absolute; left: 50%; bottom: 0; width: min(1100px, 100%); height: 480px; transform: translateX(-50%); background: radial-gradient(ellipse 50% 50% at 50% 55%, rgba(255, 255, 255, .7) 0%, rgba(192, 240, 244, .22) 42%, rgba(171, 235, 240, 0) 70%); filter: blur(50px); pointer-events: none; }
.prod-owners .container { position: relative; }
.prod-owners__head { display: flex; flex-direction: column; gap: var(--space-4); }
.prod-owners__head h2 { max-width: none; }
.prod-owners__head p { font-size: var(--t-p1); }   /* P1, as the other section bodies */
.prod-tiles--owners .prod-tiles__row { padding-top: 8px; align-items: stretch; }   /* swipe row: every tile as tall as the tallest */
.wtile {
    position: relative; isolation: isolate; flex: 0 0 auto; width: min(300px, calc(100vw - var(--page-gutter) - var(--space-5) - 28px)); scroll-snap-align: start;
    display: grid; grid-template-rows: 1fr auto auto; align-content: end; gap: var(--space-2);
    min-height: 175px; padding: var(--space-8); overflow: hidden;
    border-radius: 16px; border: 1px solid rgba(89, 89, 89, .8);
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .1) 0%, rgba(255, 255, 255, .03) 30%, rgba(255, 255, 255, 0) 55%, rgba(0, 0, 0, .22) 100%),
        radial-gradient(ellipse 70% 50% at 15% 0%, rgba(255, 255, 255, .09) 0%, rgba(255, 255, 255, 0) 60%),
        var(--primary-800);   /* the frame's #1C0024 under the sheen, corner light and darkened foot */
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .2), inset 0 -1px 0 rgba(0, 0, 0, .35), 0 16px 40px rgba(0, 0, 0, .3);
    color: var(--c-text); transition: transform .3s ease, border-color .35s ease;
}
/* Lit: a pink wash entering from the top-left and fading out by about two thirds,
   so the foot of the tile is the tile's own resting ground rather than a second
   black. It is a tint over that ground, not a cover: solid pink at the corner put
   white type on a pale field (2.6:1) and the heading strained to read; at .38 over
   #1C0024 the same corner is 9:1 (2026-09-24). Sales' §7 tiles are .atile
   and are not touched by this.                                                  */
.wtile::after {
    content: ''; position: absolute; inset: 0; z-index: -2; border-radius: inherit;
    background: linear-gradient(132deg, rgba(232, 182, 240, .38) 0%, rgba(232, 182, 240, .14) 36%, rgba(232, 182, 240, 0) 70%);
    opacity: 0; transition: opacity .35s ease;
}
.wtile__name { grid-row: 2; font-size: clamp(26px, 1.6vw + 12px, 36px); line-height: 1.1; font-weight: var(--fw-regular); }
.wtile__text { grid-row: 3; font-size: var(--t-p2); max-width: 400px; }
.wtile.is-current { border-color: rgba(232, 182, 240, .5); }
.wtile.is-current::after { opacity: 1; }
@media (hover: hover) {
    .wtile:hover { border-color: rgba(232, 182, 240, .5); }
    .wtile:hover::after { opacity: 1; }
    .js .wtile.is-visible:hover { transform: translateY(-4px); transition-duration: .3s; }
}
@media (hover: hover) and (max-width: 1023px) {
    .prod-tiles__row:hover .wtile.is-current:not(:hover) { border-color: rgba(89, 89, 89, .8); }
    .prod-tiles__row:hover .wtile.is-current:not(:hover)::after { opacity: 0; }
}
@media (min-width: 1024px) {
    .prod-tiles--owners .prod-tiles__row { display: grid; grid-template-columns: 41fr 18fr 41fr; gap: var(--space-5); padding-top: 8px; }   /* 778 : 522 both ways round */
    .wtile { width: auto; }
    .wtile:nth-child(1) { grid-column: 1 / 3; }
    .wtile:nth-child(2) { grid-column: 3; }
    .wtile:nth-child(3) { grid-column: 1; }
    .wtile:nth-child(4) { grid-column: 2 / 4; }
}

/* ── Collections · 5 · the reads as a stepped list (Figma 657:581) ──────
   From 1024: the list left, one panel on the stage right; the open step shows its
   lead and its rule fills over the step's time, then the next opens. Below 1024 the
   mobile frame (740:1745) opens every step, each with its own panel and no timer.  */
.prod-steps { background: var(--c-primary-dark); }
.prod-steps__copy { display: flex; flex-direction: column; gap: var(--space-4); }
.prod-steps__copy p { max-width: 90ch; font-size: var(--t-p1); }
.prod-steps:not(.prod-steps--tabs) .prod-steps__copy p { max-width: none; }   /* alone on its row: full width, unlike Sales where it sits beside the pills (2026-10-03) */
.prod-steps__grid { margin-top: var(--space-10); }
.prod-steps__list { display: flex; flex-direction: column; gap: var(--space-4); }
.pstep { display: flex; flex-direction: column; gap: var(--space-4); }
.pstep__name { font-size: var(--t-h3); line-height: var(--lh-heading); font-weight: var(--fw-medium); color: var(--c-text); text-align: left; }
.pstep__lead { font-size: var(--t-p2); color: var(--c-text); }
.pstep__rule { position: relative; height: 2px; border-radius: 2px; background: rgba(235, 230, 236, .22); }   /* the frame: a 2px rule under every step */
.pstep__fill { position: absolute; inset: 0 auto 0 0; width: 0; border-radius: inherit; background: var(--grey-50); box-shadow: 0 0 8px rgba(235, 230, 236, .45); }
@keyframes step-fill { from { width: 0; } to { width: 100%; } }
/* the panel the visuals live in: the frame's 619×437 card, a purple glow at its foot
   and a cyan sheen across its top-right corner                                    */
.pview__panel {
    position: relative; display: grid; place-items: center; overflow: hidden;
    aspect-ratio: 619 / 437; width: 100%; border-radius: 16px;
    background:
        linear-gradient(132deg, rgba(0, 0, 0, 0) 62%, rgba(171, 235, 240, .22) 88%, rgba(171, 235, 240, .34) 100%),   /* the frame's cyan sheen off the top-right corner */
        linear-gradient(275deg, rgba(0, 0, 0, 0) 86%, rgba(94, 55, 110, .75) 100%),                                   /* and its purple glow at the foot */
        var(--primary-900);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .14), 0 20px 50px rgba(0, 0, 0, .35);
}
.pview__hold { font-family: var(--font-secondary); font-size: var(--t-p3); letter-spacing: var(--ls-cta); text-transform: uppercase; color: rgba(171, 235, 240, .5); }
.prod-steps__stage { display: none; }

/* below 1024: every step open, its own panel under it, no timer */
@media (max-width: 1023px) {
    .prod-steps__list { gap: var(--space-8); }
    .pstep__fill { display: none; }
}

@media (min-width: 1024px) {
    .prod-steps__grid { display: flex; align-items: stretch; justify-content: space-between; gap: var(--space-10); }
    .prod-steps__list { flex: 0 1 666px; gap: 0; padding-top: var(--space-8); }
    .prod-steps__stage { display: block; position: relative; flex: 0 1 619px; aspect-ratio: 619 / 437; }   /* its own ratio sets the row's height; stretch keeps it level with the list when the list is taller */
    .prod-steps__stage .pview.is-active { height: 100%; }
    .prod-steps__stage .pview__panel { height: 100%; aspect-ratio: auto; }
    .pstep { gap: 0; }
    .pstep__view { display: none; }                       /* the stage shows it instead */
    .pstep__name { padding-block: var(--space-4); cursor: pointer; transition: color .3s ease; }
    .pstep__name:hover { color: var(--c-accent-cyan); }
    .pstep:not(.is-open) .pstep__name { color: rgba(255, 249, 245, .8); }
    .pstep__lead { max-height: 0; margin: 0; opacity: 0; overflow: hidden; transition: max-height .45s ease, opacity .35s ease, margin .45s ease; }
    .pstep.is-open .pstep__lead { max-height: 8em; margin-bottom: var(--space-5); opacity: 1; }
    .pstep.is-open .pstep__fill { animation: step-fill 6s linear paused forwards; }   /* products.js runs and pauses it; when it ends the next step opens */
    .pview { position: absolute; inset: 0; opacity: 0; transform: translateY(8px); transition: opacity .45s ease, transform .45s ease; pointer-events: none; }
    .pview.is-active { position: relative; opacity: 1; transform: none; pointer-events: auto; }
}

/* ── Collections · 5 · visual 1: the Opportunity Timeline (Figma 752:2183) ──
   A HUD frame (a cyan bar on each side) around the four openings the call gave, each
   stamped with its grade. The grade reads three ways — glyph, word and colour — so it
   survives greyscale.
   The settled state IS the CSS: the run below only plays once, the first time the
   panel is seen (products.js adds .is-run), so a reader who arrives late still sees
   the finished panel and nothing loops in the corner of their eye.
   ONE root size (.tl's font-size) scales everything; the rest is in em.          */
.pview__panel { container-type: inline-size; }
/* below 1024 the panel takes the height its visual needs — the frame's 619×437 ratio
   leaves a cavern at these widths, where the panel runs nearly full-bleed          */
@media (max-width: 1023px) {
    .pview__panel { aspect-ratio: auto; min-height: 220px; }
    .pview__panel > [data-tl] { position: relative; inset: auto; width: 100%; }   /* every visual, not just the first. width: the panel is a centring grid, so an in-flow child would otherwise shrink to its content */
}
.tl {
    position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; gap: 1em;
    padding: 2em 1.9em;
    font-size: clamp(9px, 2.6cqi, 17px);
}
.tl__frame { position: absolute; inset: 1.1em .9em; border: 1px solid rgba(171, 235, 240, .5); border-radius: 1em; background: rgba(171, 235, 240, .03); }
.tl__bar { position: absolute; top: 38%; bottom: 38%; width: .34em; border-radius: 2px; background: var(--c-accent-cyan); box-shadow: 0 0 10px rgba(171, 235, 240, .7); }
.tl__bar--l { left: .72em; }
.tl__bar--r { right: .72em; }
.tl__grid { position: relative; display: grid; grid-template-columns: 1fr 1fr; gap: .75em; }   /* the cards hug their copy; both cards in a row share its height */
.tl__card {
    position: relative; overflow: hidden;
    display: grid; grid-template-columns: 1fr auto; grid-template-rows: auto auto auto; align-content: start; align-items: center; gap: .1em .7em;
    padding: .85em 1em; border-radius: .55em;
    border: 1px solid rgba(171, 235, 240, .32); background: rgba(171, 235, 240, .045);
}
.tl__time  { grid-column: 1; font-family: var(--font-secondary); font-size: 1.1em; line-height: 1.5; color: rgba(255, 249, 245, .7); }
.tl__name  { grid-column: 1; font-size: 1.32em; line-height: 1.2; color: var(--c-accent-cyan); }
.tl__grade { grid-column: 1; display: inline-flex; align-items: center; gap: .4em; margin-top: .25em; font-family: var(--font-secondary); font-size: 1.05em; letter-spacing: .06em; text-transform: uppercase; }
.tl__glyph { width: 1.1em; height: 1.1em; flex: none; }
.tl__glyph path, .tl__glyph circle { fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.tl__glyph .tl__glyph-fill { fill: currentColor; stroke: none; }
.tl__card--missed   .tl__grade { color: var(--accent-neon-red); }
.tl__card--partial  .tl__grade { color: var(--accent-desert-sand); }
.tl__card--captured .tl__grade { color: var(--teal-500); }
.tl__spark { grid-column: 2; grid-row: 1 / -1; align-self: center; display: flex; align-items: flex-end; gap: .22em; height: 2.4em; }
.tl__spark i { display: block; width: .26em; height: calc(2.4em * var(--h) / 100); border-radius: .13em; background: var(--c-accent-cyan); opacity: .45; transform-origin: bottom; }
.tl__legend { display: flex; justify-content: center; gap: 1.5em; font-family: var(--font-secondary); font-size: .95em; letter-spacing: .06em; color: rgba(255, 249, 245, .65); }
.tl__key { display: inline-flex; align-items: center; gap: .45em; }
.tl__dot { width: .5em; height: .5em; border-radius: 50%; background: currentColor; }
.tl__key--missed   .tl__dot { background: var(--accent-neon-red); }
.tl__key--partial  .tl__dot { background: var(--accent-desert-sand); }
.tl__key--captured .tl__dot { background: var(--teal-500); }

/* the run — once, on first sight: the frame comes up, the four openings land in turn
   and each grade stamps, the legend follows. ~2.4s in total.                      */
.tl.is-run .tl__frame  { animation: tl-frame 1s ease-out both; }
.tl.is-run .tl__bar    { animation: tl-bar .7s ease-out both .15s; }
.tl.is-run .tl__card   { animation: tl-card .7s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.25s + var(--k, 0) * .22s); }
.tl.is-run .tl__grade  { animation: tl-stamp .5s ease-out both; animation-delay: calc(.6s + var(--k, 0) * .22s); }
.tl.is-run .tl__spark i { animation: tl-spark .5s ease-in-out both; animation-delay: calc(.5s + var(--k, 0) * .22s + var(--b) * .04s); }
.tl.is-run .tl__legend { animation: tl-legend .6s ease-out both 1.5s; }
@keyframes tl-frame  { from { opacity: 0; transform: scale(.985); } to { opacity: 1; transform: none; } }
@keyframes tl-bar    { from { opacity: 0; transform: scaleY(.3); } to { opacity: 1; transform: none; } }
@keyframes tl-card   { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes tl-stamp  { 0% { opacity: 0; } 55% { opacity: 1; filter: drop-shadow(0 0 6px currentColor); } 100% { opacity: 1; filter: none; } }
@keyframes tl-spark  { from { transform: scaleY(.25); opacity: .2; } to { transform: scaleY(1); opacity: .45; } }
@keyframes tl-legend { from { opacity: 0; } to { opacity: 1; } }
/* a narrow panel: tighter frame and padding, so the cards and legend still sit inside */
@container (max-width: 430px) {
    .tl { padding: 1.4em 1.2em 1.6em; gap: .7em; }
    .tl__frame { inset: .7em .6em; }
    .tl__grid { gap: .55em; }
    .tl__card { padding: .7em .8em; }
    .tl__spark { height: 1.9em; }
}

/* ── Collections · 5 · visual 2: the Capture Rate gauge (Figma 657:535) ──
   The same rules as visual 1: one clamped root size, everything in em, the SVG keeps
   its own shape (no stretching), and the run plays once on first sight — the arc
   sweeps to the share the agent took, the number counts up with it (products.js).  */
.cr {
    position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .7em;
    padding: 1.6em;
    font-size: clamp(9px, 2.6cqi, 17px);
}
.cr__dial { position: relative; width: 100%; max-width: 34em; }   /* the frame's gauge fills the panel. width+max-width, not min(): as a flex item in the stacked column min() left it shrink-to-fit and it fell back to the SVG's intrinsic 300px */
.cr__svg { display: block; width: 100%; height: auto; overflow: visible; }
.cr__body { fill: rgba(94, 55, 110, .38); stroke: rgba(171, 235, 240, .3); stroke-width: 1.2; }
.cr__ticks line { stroke: rgba(171, 235, 240, .45); stroke-width: 1.4; }
.cr__ticks .cr__tick--long { stroke: rgba(171, 235, 240, .8); stroke-width: 2; }
.cr__track { fill: none; stroke: rgba(255, 249, 245, .14); stroke-width: 11; stroke-linecap: round; }
.cr__arc   { fill: none; stroke: var(--c-accent-highlight); stroke-width: 11;   /* the sweep itself is driven by products.js (data-sweep), so the arc and the number move together */   /* a flat colour, not a gradient: the visual renders twice per step (stage + stacked list), and a duplicate gradient id resolved to the hidden copy, so the arc vanished on desktop */ stroke-linecap: round; filter: drop-shadow(0 0 6px rgba(171, 235, 240, .55)); stroke-dasharray: 100; stroke-dashoffset: calc(100 - var(--v)); }
.cr__value { position: absolute; left: 0; right: 0; bottom: 31%; text-align: center; font-family: var(--font-secondary); font-size: 3.6em; line-height: 1; color: var(--c-accent-highlight); text-shadow: 0 0 18px rgba(152, 235, 239, .45); }
.cr__caption { position: absolute; left: 0; right: 0; bottom: 19%; text-align: center; font-family: var(--font-secondary); font-size: 1.05em; letter-spacing: .06em; color: rgba(255, 249, 245, .8); }   /* inside the dial, under the number, as the frame has it */
/* the run */
.cr.is-run .cr__body    { animation: cr-body .7s ease-out both; }
.cr.is-run .cr__ticks line { animation: cr-tick .5s ease-out both; animation-delay: calc(.15s + var(--i, 0) * .01s); }
.cr.is-run .cr__track   { animation: cr-fade .6s ease-out both .2s; }
.cr.is-run .cr__value   { animation: cr-value .6s ease-out both .3s; }
.cr.is-run .cr__caption { animation: cr-fade .6s ease-out both 1.2s; }
@keyframes cr-body  { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes cr-tick  { from { opacity: 0; } to { opacity: 1; } }
@keyframes cr-fade  { from { opacity: 0; } to { opacity: 1; } }
@keyframes cr-value { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: none; } }
@container (max-width: 430px) {
    .cr { padding: 1.2em; }
    .cr__value { font-size: 3em; }
    .cr__caption { font-size: .95em; }
}

/* ── Collections · 5 · visual 3: the Opportunity Outcome readout (Figma 657:625) ──
   A screen inside the panel: the title, then three label → value lines joined by a
   trace, the second it slipped in a lit display. Same rules as the others — one
   clamped root size, everything in em, and the run plays once on first sight.    */
.oo {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.4em;
    font-size: clamp(11px, 2.6cqi, 17px);   /* a higher floor than the other two: this panel is all type */
}
.oo__screen {
    position: relative; width: 100%; max-width: 32em;
    display: flex; flex-direction: column; gap: 1.1em;
    padding: 1.5em 2em; border-radius: 1em;
    border: 1px solid rgba(171, 235, 240, .45);
    background:
        repeating-linear-gradient(180deg, rgba(171, 235, 240, .05) 0 1px, rgba(171, 235, 240, 0) 1px 4px),   /* the screen's scan lines */
        linear-gradient(160deg, rgba(94, 55, 110, .5), rgba(21, 0, 27, .9));
    box-shadow: inset 0 0 30px rgba(171, 235, 240, .12), 0 16px 40px rgba(0, 0, 0, .35);
}
.oo__bar { position: absolute; top: 22%; bottom: 22%; width: .3em; border-radius: 2px; background: var(--c-accent-cyan); box-shadow: 0 0 10px rgba(171, 235, 240, .7); }
.oo__bar--l { left: -.15em; }
.oo__bar--r { right: -.15em; }
.oo__title { font-family: var(--font-secondary); font-size: 2.1em; line-height: 1.1; font-weight: var(--fw-semibold); letter-spacing: .04em; text-align: center; color: var(--c-accent-highlight); text-shadow: 0 0 14px rgba(152, 235, 239, .6); }
.oo__rows { display: flex; flex-direction: column; gap: .9em; }
.oo__row { display: flex; align-items: center; gap: .7em; }
.oo__label { font-family: var(--font-secondary); font-size: 1.15em; color: rgba(255, 249, 245, .9); }
.oo__trace { flex: 1; height: 1px; background: linear-gradient(90deg, rgba(171, 235, 240, .7), rgba(171, 235, 240, .35)); position: relative; transform-origin: left; }
.oo__trace::before, .oo__trace::after { content: ''; position: absolute; top: -1.5px; width: 4px; height: 4px; border-radius: 50%; background: var(--c-accent-cyan); }
.oo__trace::before { left: 0; }
.oo__trace::after  { right: 0; }
.oo__value { font-family: var(--font-secondary); font-size: 1.15em; color: var(--c-accent-highlight); }
.oo__value--alarm { letter-spacing: .08em; text-transform: uppercase; color: var(--accent-neon-red); text-shadow: 0 0 12px rgba(255, 82, 82, .45); }
.oo__value--clock { display: inline-flex; align-items: center; gap: .5em; padding: .25em .6em; border-radius: .4em; border: 1px solid rgba(171, 235, 240, .5); background: rgba(171, 235, 240, .08); font-size: 1.5em; letter-spacing: .06em; box-shadow: inset 0 0 14px rgba(171, 235, 240, .2); }
.oo__live { width: .42em; height: .42em; border-radius: 50%; background: currentColor; box-shadow: 0 0 .5em currentColor; }   /* the moment is marked, not illustrated: the frame's satellite glyph read as a scribble at this size */
/* the run: the screen powers up, each line is traced in turn, the time lands last */
.oo.is-run .oo__screen { animation: oo-screen .6s ease-out both; }
.oo.is-run .oo__bar    { animation: oo-fade .5s ease-out both .2s; }
.oo.is-run .oo__title  { animation: oo-title .9s ease-out both .15s; }
.oo.is-run .oo__label  { animation: oo-fade .4s ease-out both; animation-delay: calc(.5s + var(--k, 0) * .35s); }
.oo.is-run .oo__trace  { animation: oo-trace .5s ease-out both; animation-delay: calc(.6s + var(--k, 0) * .35s); }
.oo.is-run .oo__value  { animation: oo-value .45s ease-out both; animation-delay: calc(.9s + var(--k, 0) * .35s); }
@keyframes oo-screen { from { opacity: 0; transform: scale(.985); } to { opacity: 1; transform: none; } }
@keyframes oo-fade   { from { opacity: 0; } to { opacity: 1; } }
@keyframes oo-title  { 0% { opacity: 0; } 30% { opacity: 1; } 42% { opacity: .35; } 55%, 100% { opacity: 1; } }   /* a screen coming up */
@keyframes oo-trace  { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes oo-value  { from { opacity: 0; transform: translateX(.4em); } to { opacity: 1; transform: none; } }
@container (max-width: 430px) {
    .oo { padding: 1em; }
    .oo__screen { padding: 1.1em 1.2em; gap: .8em; }
    .oo__title { font-size: 1.7em; }
    .oo__label, .oo__value { font-size: 1.1em; }
    .oo__value--clock { font-size: 1.3em; }
}

/* ── Collections · 5 · visual 4: Engagement (Figma 657:669) ────────────
   Four reads, each a segmented meter. The band sets the row's colour — 33 and under
   red, 34-66 amber, above 66 green — and the number is always there, so the read
   never rests on colour alone. Same rules as the others; runs once on first sight. */
.en {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.4em;
    font-size: clamp(10px, 2.6cqi, 17px);
}
.en__screen {
    position: relative; width: 100%; max-width: 32em;
    padding: 1.4em 1.8em; border-radius: 1em;
    border: 1px solid rgba(171, 235, 240, .4);
    background:
        repeating-linear-gradient(180deg, rgba(171, 235, 240, .05) 0 1px, rgba(171, 235, 240, 0) 1px 4px),
        linear-gradient(160deg, rgba(94, 55, 110, .4), rgba(21, 0, 27, .9));
    box-shadow: inset 0 0 30px rgba(171, 235, 240, .1), 0 16px 40px rgba(0, 0, 0, .35);
}
.en__bar { position: absolute; top: 24%; bottom: 24%; width: .3em; border-radius: 2px; background: var(--c-accent-cyan); box-shadow: 0 0 10px rgba(171, 235, 240, .7); }
.en__bar--l { left: -.15em; }
.en__bar--r { right: -.15em; }
.en__rows { display: flex; flex-direction: column; gap: .85em; }
.en__row { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: .8em; --en: var(--c-accent-cyan); }
.en__row--low  { --en: var(--accent-neon-red); }
.en__row--mid  { --en: var(--accent-desert-sand); }
.en__row--high { --en: #5FE3A1; }
.en__row--flat { --en: var(--c-accent-cyan); }   /* a reading, not a grade: no band colours (the callback vitals) */   /* a mint green: the palette has no green, and the pale cyan used for 'Captured' does not read as one (red / amber / green bands) */
.en__label { font-family: var(--font-secondary); font-size: 1.05em; letter-spacing: .06em; text-transform: uppercase; color: rgba(255, 249, 245, .85); }
.en__track { display: flex; gap: .22em; }
.en__track i { display: block; width: .5em; height: 1.2em; border-radius: .12em; border: 1px solid rgba(171, 235, 240, .3); background: rgba(171, 235, 240, .06); }
.en__track i.is-on { border-color: var(--en); background: var(--en); box-shadow: 0 0 .5em color-mix(in srgb, var(--en) 60%, transparent); }
.en__pct { min-width: 3.2em; text-align: right; font-family: var(--font-secondary); font-size: 1.25em; color: var(--en); }
/* the run */
.en.is-run .en__screen { animation: oo-screen .6s ease-out both; }
.en.is-run .en__bar    { animation: oo-fade .5s ease-out both .2s; }
.en.is-run .en__label, .en.is-run .en__pct { animation: en-line .5s ease-out both; animation-delay: calc(.3s + var(--k, 0) * .2s); }
.en.is-run .en__track i { animation: en-cell .3s ease-out both; animation-delay: calc(.4s + var(--k, 0) * .2s + var(--i, 0) * .045s); }
@keyframes en-line { from { opacity: 0; transform: translateY(.3em); } to { opacity: 1; transform: none; } }
@keyframes en-cell { from { opacity: 0; transform: scaleY(.3); } to { opacity: 1; transform: none; } }
@container (max-width: 430px) {
    .en { padding: 1em; }
    .en__screen { padding: 1.1em 1.1em; }
    .en__rows { gap: .6em; }
    .en__row { gap: .5em; }
    .en__label { font-size: .95em; }
    .en__track i { width: .38em; height: 1em; }
    .en__pct { font-size: 1.1em; min-width: 2.8em; }
}

/* ── Sales · 4 · the four reads: tabs, each holding a stepped list ──────
   The frames (448:5199 and the three after it): the copy and the pills in one row,
   then the open tab's steps on the left with its visual on the stage. Below 1024 the
   pills scroll sideways and the open tab's steps all stand open — one read at a time
   on a phone, rather than fourteen panels in a single scroll.                    */
.prod-steps--tabs .prod-steps__head { display: flex; flex-direction: column; gap: var(--space-6); }
.prod-steps--tabs .prod-steps__copy { display: flex; flex-direction: column; gap: var(--space-4); }
.prod-steps--tabs .prod-steps__copy p { font-size: var(--t-p1); }
.prod-steps--tabs .prod-panels { margin-top: var(--space-8); min-height: 0; }
.prod-steps--tabs .prod-steps__grid { margin-top: 0; }
.pstep__tag { display: block; margin-top: .2em; font-family: var(--font-secondary); font-size: var(--t-p3); letter-spacing: var(--ls-cta); text-transform: uppercase; color: rgba(171, 235, 240, .7); }
/* the pills scroll sideways on a phone rather than wrapping into a block */
@media (max-width: 1023px) {
    .prod-steps--tabs .prod-tabs { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-inline: calc(var(--page-gutter) * -1); padding-inline: var(--page-gutter); }
    .prod-steps--tabs .prod-tabs::-webkit-scrollbar { display: none; }
    .prod-steps--tabs .prod-tab { flex: 0 0 auto; }
}
@media (min-width: 1024px) {
    .prod-steps--tabs .prod-steps__head { flex-direction: row; align-items: flex-end; justify-content: space-between; gap: var(--space-10); }
    .prod-steps--tabs .prod-steps__copy { flex: 0 1 620px; }
    .prod-steps--tabs .prod-steps__copy p { max-width: 60ch; }   /* capped only beside the pills */
    .prod-steps--tabs .prod-tabs { flex: 0 0 auto; flex-wrap: nowrap; }
}

/* ── Sales · 4 · The Deal's visuals ─────────────────────────────────────
   Same rules as Collections': one clamped root size per visual, everything in em, the run
   plays once on first sight (products.js adds .is-run), numbers count from the same
   rAF pass. The screen chrome and the meter rows are the ones Engagement already
   defines — these reuse them rather than restating them.                        */

/* Deal Health Score: the number, then the five signals banded by value */
.dh {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.4em;
    font-size: clamp(10px, 2.6cqi, 17px);
}
.dh__screen {
    position: relative; width: 100%; max-width: 32em; padding: 1.3em 1.7em; border-radius: 1em;
    border: 1px solid rgba(171, 235, 240, .4);
    background:
        repeating-linear-gradient(180deg, rgba(171, 235, 240, .05) 0 1px, rgba(171, 235, 240, 0) 1px 4px),
        linear-gradient(160deg, rgba(94, 55, 110, .4), rgba(21, 0, 27, .9));
    box-shadow: inset 0 0 30px rgba(171, 235, 240, .1), 0 16px 40px rgba(0, 0, 0, .35);
}
.dh__head { display: flex; align-items: baseline; justify-content: space-between; gap: 1em; margin-bottom: 1em; padding-bottom: .7em; border-bottom: 1px solid rgba(171, 235, 240, .2); }
.dh__title { font-family: var(--font-secondary); font-size: 1.05em; letter-spacing: .06em; text-transform: uppercase; color: rgba(255, 249, 245, .85); }
.dh__score { font-family: var(--font-secondary); font-size: 2.4em; line-height: 1; color: var(--c-accent-highlight); text-shadow: 0 0 16px rgba(152, 235, 239, .45); }
.dh__of { font-size: .45em; color: rgba(255, 249, 245, .6); }
.dh__rows { gap: .7em; }
.dh.is-run .dh__screen { animation: oo-screen .6s ease-out both; }
.dh.is-run .oo__bar    { animation: oo-fade .5s ease-out both .2s; }
.dh.is-run .dh__head   { animation: en-line .5s ease-out both .25s; }
.dh.is-run .en__label, .dh.is-run .en__pct { animation: en-line .5s ease-out both; animation-delay: calc(.45s + var(--k, 0) * .18s); }
.dh.is-run .en__track i { animation: en-cell .3s ease-out both; animation-delay: calc(.5s + var(--k, 0) * .18s + var(--i, 0) * .04s); }

/* Turning Points: the call's spine, the seconds it moved marked either side */
.tp {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.4em;
    font-size: clamp(10px, 2.6cqi, 17px);
}
.tp__screen { position: relative; width: 100%; max-width: 32em; padding: 1.3em 1.5em; }
.tp__spine { position: absolute; left: 4.85em; transform: translateX(-50%);   /* on the marks: 3.4em of timestamp + .6em gap + half of the 1.7em mark */ top: .6em; bottom: 2.6em; width: 2px; border-radius: 2px; margin-left: 1.5em; background: linear-gradient(180deg, rgba(171, 235, 240, .1), rgba(171, 235, 240, .65), rgba(171, 235, 240, .1)); }
.tp__list { display: flex; flex-direction: column; gap: .85em; }
.tp__item { position: relative; display: grid; grid-template-columns: 3.4em 1.7em 1fr; align-items: center; gap: .6em; --tp: var(--teal-500); }
.tp__item--down { --tp: var(--accent-neon-red); }
.tp__at { font-family: var(--font-secondary); font-size: 1.05em; color: rgba(255, 249, 245, .7); text-align: right; }
.tp__mark { display: grid; place-items: center; width: 1.7em; height: 1.7em; border-radius: 50%; border: 1px solid var(--tp); background: var(--c-primary-dark); box-shadow: 0 0 .6em color-mix(in srgb, var(--tp) 45%, transparent); }
.tp__mark svg { width: .85em; height: .85em; fill: var(--tp); }
.tp__text { font-size: 1.15em; color: var(--c-text); }
.tp__move { grid-column: 3; font-family: var(--font-secondary); font-size: .9em; letter-spacing: .05em; text-transform: uppercase; color: var(--tp); }
.tp__note { margin-top: 1em; font-family: var(--font-secondary); font-size: .95em; letter-spacing: .05em; color: rgba(255, 249, 245, .6); }
.tp.is-run .tp__spine { animation: tp-spine .7s ease-out both; transform-origin: top; }
.tp.is-run .tp__item  { animation: tp-item .5s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.3s + var(--k, 0) * .22s); }
.tp.is-run .tp__mark  { animation: tp-mark .45s ease-out both; animation-delay: calc(.4s + var(--k, 0) * .22s); }
.tp.is-run .tp__note  { animation: oo-fade .5s ease-out both 1.3s; }
@keyframes tp-spine { from { transform: scaleY(0); } to { transform: none; } }
@keyframes tp-item  { from { opacity: 0; transform: translateX(.6em); } to { opacity: 1; transform: none; } }
@keyframes tp-mark  { 0% { transform: scale(.3); } 60% { transform: scale(1.15); } 100% { transform: none; } }

/* VTC: one bar per call segment, the low ones the tells */
.vt {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.3em;
    font-size: clamp(10px, 2.4cqi, 16px);
}
.vt__screen { position: relative; width: 100%; max-width: 34em; }
.vt__legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.2em; margin-bottom: .9em; font-family: var(--font-secondary); font-size: .9em; letter-spacing: .05em; color: rgba(255, 249, 245, .65); }
.vt__key { display: inline-flex; align-items: center; gap: .45em; }
.vt__key--high .tl__dot { background: var(--teal-500); }
.vt__key--mid  .tl__dot { background: var(--accent-desert-sand); }
.vt__key--low  .tl__dot { background: var(--accent-neon-red); }
.vt__plot { position: relative; padding-bottom: .5em; border-bottom: 1px solid rgba(171, 235, 240, .3); }
.vt__grid { position: absolute; inset: 0 0 .5em; background: repeating-linear-gradient(180deg, rgba(171, 235, 240, .12) 0 1px, rgba(171, 235, 240, 0) 1px 25%); }
.vt__bars { position: relative; display: flex; align-items: flex-end; justify-content: space-between; gap: .35em; height: 10em; }
.vt__bar { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; gap: .3em; height: 100%; --vt: var(--teal-500); }
.vt__bar--mid { --vt: var(--accent-desert-sand); }
.vt__bar--low { --vt: var(--accent-neon-red); }
.vt__val  { font-family: var(--font-secondary); font-size: .85em; color: var(--vt); }
.vt__stem { display: block; width: 100%; height: calc(100% * var(--v) - 1.6em); border-radius: .2em .2em 0 0; background: linear-gradient(180deg, var(--vt), color-mix(in srgb, var(--vt) 35%, transparent)); box-shadow: 0 0 .6em color-mix(in srgb, var(--vt) 40%, transparent); transform-origin: bottom; }
.vt__note { margin-top: .7em; text-align: center; font-family: var(--font-secondary); font-size: .9em; letter-spacing: .05em; color: rgba(255, 249, 245, .6); }
.vt.is-run .vt__legend { animation: oo-fade .5s ease-out both .1s; }
.vt.is-run .vt__stem   { animation: vt-stem .5s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.25s + var(--k, 0) * .055s); }
.vt.is-run .vt__val    { animation: oo-fade .4s ease-out both; animation-delay: calc(.45s + var(--k, 0) * .055s); }
.vt.is-run .vt__note   { animation: oo-fade .5s ease-out both 1.1s; }
@keyframes vt-stem { from { transform: scaleY(0); } to { transform: none; } }
@container (max-width: 430px) {
    .dh__screen, .tp__screen { padding: 1.1em 1.1em; }
    .dh__score { font-size: 2em; }
    .tp__item { grid-template-columns: 3em 1.5em 1fr; }
    .tp__text { font-size: 1.05em; }
    .vt__bars { height: 8em; gap: .25em; }
    .vt__val { font-size: .85em; }
    .vt__legend { gap: .8em; font-size: .8em; }
}

/* ── Sales · 4 · The Agent's visuals ────────────────────────────────────
   Selling skills as nine banded bars, the persona as the readout plus the talk/listen
   split, coaching as the gap → fix → the line that triggered it. Same rules again.  */

/* Selling Skills */
.sk {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.2em;
    font-size: clamp(9px, 2.3cqi, 15px);
}
.sk__screen {
    position: relative; width: 100%; max-width: 34em; padding: 1.2em 1.5em; border-radius: 1em;
    border: 1px solid rgba(171, 235, 240, .35);
    background:
        repeating-linear-gradient(180deg, rgba(171, 235, 240, .05) 0 1px, rgba(171, 235, 240, 0) 1px 4px),
        linear-gradient(160deg, rgba(94, 55, 110, .38), rgba(21, 0, 27, .9));
    box-shadow: inset 0 0 30px rgba(171, 235, 240, .1), 0 16px 40px rgba(0, 0, 0, .35);
}
.sk__legend { display: flex; flex-wrap: wrap; gap: .9em; margin-bottom: .9em; font-family: var(--font-secondary); font-size: .9em; letter-spacing: .05em; color: rgba(255, 249, 245, .65); }
.sk__key { display: inline-flex; align-items: center; gap: .4em; }
.sk__key--high .tl__dot { background: #5FE3A1; }
.sk__key--good .tl__dot { background: #43AE86; }
.sk__key--mid  .tl__dot { background: var(--accent-desert-sand); }
.sk__key--low  .tl__dot { background: var(--accent-neon-red); }
.sk__rows { display: flex; flex-direction: column; gap: .45em; }
.sk__row { display: grid; grid-template-columns: 11.5em 1fr 2.2em; align-items: center; gap: .7em; --sk: #5FE3A1; }   /* one ladder, brightest at the top: mint, deep mint, amber, red */
.sk__row--good { --sk: #43AE86; }
.sk__row--mid  { --sk: var(--accent-desert-sand); }
.sk__row--low  { --sk: var(--accent-neon-red); }
.sk__label { font-size: 1.05em; color: rgba(255, 249, 245, .9); }
.sk__track { position: relative; height: .75em; border-radius: .4em; background: rgba(171, 235, 240, .1); overflow: hidden; }
.sk__fill  { position: absolute; inset: 0 auto 0 0; width: calc(var(--v) * 1%); border-radius: inherit; background: linear-gradient(90deg, color-mix(in srgb, var(--sk) 55%, transparent), var(--sk)); box-shadow: 0 0 .5em color-mix(in srgb, var(--sk) 45%, transparent); transform-origin: left; }
.sk__val { font-family: var(--font-secondary); font-size: 1.05em; text-align: right; color: var(--sk); }
.sk.is-run .sk__screen { animation: oo-screen .6s ease-out both; }
.sk.is-run .sk__legend { animation: oo-fade .5s ease-out both .2s; }
.sk.is-run .sk__label, .sk.is-run .sk__val { animation: en-line .45s ease-out both; animation-delay: calc(.3s + var(--k, 0) * .09s); }
.sk.is-run .sk__fill { animation: sk-fill .6s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.35s + var(--k, 0) * .09s); }
@keyframes sk-fill { from { transform: scaleX(0); } to { transform: none; } }

/* Sales Persona: the readout, plus the talk/listen split drawn */
.ps {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.4em;
    font-size: clamp(11px, 2.6cqi, 17px);
}
.ps__screen { width: 100%; max-width: 32em; }
.ps__split { margin-top: 1.2em; padding-top: 1em; border-top: 1px solid rgba(171, 235, 240, .22); }
.ps__bar { display: flex; height: .9em; border-radius: .45em; overflow: hidden; background: rgba(171, 235, 240, .1); }
.ps__talk   { width: calc(var(--talk) * 1%); background: linear-gradient(90deg, var(--c-accent-pink), rgba(232, 182, 240, .5)); transform-origin: left; }
.ps__listen { flex: 1; background: linear-gradient(90deg, rgba(171, 235, 240, .45), var(--c-accent-cyan)); }
.ps__keys { display: flex; justify-content: space-between; margin-top: .5em; font-family: var(--font-secondary); font-size: 1em; }
.ps__key--talk   { color: var(--c-accent-pink); }
.ps__key--listen { color: var(--c-accent-cyan); }
.ps__note { margin-top: .5em; font-size: .95em; color: rgba(255, 249, 245, .65); }
.ps.is-run .oo__screen { animation: oo-screen .6s ease-out both; }
.ps.is-run .oo__bar    { animation: oo-fade .5s ease-out both .2s; }
.ps.is-run .oo__label  { animation: oo-fade .4s ease-out both; animation-delay: calc(.35s + var(--k, 0) * .28s); }
.ps.is-run .oo__trace  { animation: oo-trace .5s ease-out both; animation-delay: calc(.45s + var(--k, 0) * .28s); }
.ps.is-run .oo__value  { animation: oo-value .45s ease-out both; animation-delay: calc(.7s + var(--k, 0) * .28s); }
.ps.is-run .ps__talk   { animation: sk-fill .7s cubic-bezier(.2, .7, .2, 1) both 1.3s; }
.ps.is-run .ps__keys, .ps.is-run .ps__note { animation: oo-fade .5s ease-out both 1.6s; }

/* Coaching: the gap, the fix, the line that triggered it */
.co {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.3em;
    font-size: clamp(10px, 2.5cqi, 16px);
}
.co__cards { display: flex; flex-direction: column; gap: .9em; width: 100%; max-width: 33em; }
.co__card { padding: 1em 1.2em; border-radius: .8em; border: 1px solid rgba(171, 235, 240, .3); background: linear-gradient(160deg, rgba(94, 55, 110, .35), rgba(21, 0, 27, .85)); box-shadow: 0 12px 30px rgba(0, 0, 0, .3); }
.co__gap { display: flex; align-items: center; gap: .5em; font-family: var(--font-secondary); font-size: 1.1em; letter-spacing: .05em; text-transform: uppercase; color: var(--accent-desert-sand); }
.co__flag { width: .5em; height: .5em; border-radius: 50%; background: currentColor; box-shadow: 0 0 .6em currentColor; }
.co__fix { margin-top: .45em; font-size: 1.05em; color: var(--c-text); }
.co__quote { margin-top: .7em; padding-left: .8em; border-left: 2px solid rgba(171, 235, 240, .45); }
.co__quote p { font-size: 1.05em; font-style: italic; color: var(--c-accent-highlight); }
.co__quote cite { display: block; margin-top: .25em; font-family: var(--font-secondary); font-size: .9em; font-style: normal; letter-spacing: .05em; color: rgba(255, 249, 245, .6); }
.co.is-run .co__card { animation: tp-item .55s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.2s + var(--k, 0) * .28s); }
.co.is-run .co__quote { animation: oo-fade .5s ease-out both; animation-delay: calc(.55s + var(--k, 0) * .28s); }

@container (max-width: 430px) {
    .sk__screen { padding: 1em 1.1em; }
    .sk__row { grid-template-columns: 9.5em 1fr 2em; gap: .5em; }
    .sk__legend { gap: .6em; font-size: .8em; }
    .ps__screen { max-width: none; }
    .co__card { padding: .85em .95em; }
}

/* ── Sales · 4 · The Customer's visuals ─────────────────────────────────
   The needs as a numbered list, the objection as said → meant with how hard it was
   held, readiness as the verdict and what earned it. The customer persona reuses the
   readout with no split to draw. Same rules again.                              */

/* Primary needs */
.nd {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.4em;
    font-size: clamp(10px, 2.5cqi, 16px);
}
.nd__list { display: flex; flex-direction: column; gap: .7em; width: 100%; max-width: 32em; }
.nd__item { display: grid; grid-template-columns: 2.6em 1fr; align-items: center; gap: .8em; padding: .8em 1em; border-radius: .7em; border: 1px solid rgba(171, 235, 240, .28); background: linear-gradient(160deg, rgba(94, 55, 110, .32), rgba(21, 0, 27, .8)); }
.nd__no { font-family: var(--font-secondary); font-size: 1.2em; color: var(--c-accent-highlight); text-shadow: 0 0 10px rgba(152, 235, 239, .4); }
.nd__text { font-size: 1.05em; line-height: 1.35; color: var(--c-text); }
.nd.is-run .nd__item { animation: tp-item .5s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.15s + var(--k, 0) * .16s); }

/* Objection map */
.ob {
    position: absolute; inset: 0; display: grid; place-items: center; align-content: center; gap: 1.1em; padding: 1.4em;
    font-size: clamp(10px, 2.5cqi, 16px);
}
.ob__pair { display: grid; grid-template-columns: 1fr auto 1fr; align-items: stretch; gap: .9em; width: 100%; max-width: 33em; }
.ob__side { padding: .9em 1em; border-radius: .7em; border: 1px solid rgba(171, 235, 240, .3); background: linear-gradient(160deg, rgba(94, 55, 110, .3), rgba(21, 0, 27, .82)); }
.ob__side--meant { border-color: rgba(232, 182, 240, .45); box-shadow: 0 0 22px rgba(232, 182, 240, .12); }
.ob__label { font-family: var(--font-secondary); font-size: .9em; letter-spacing: .05em; text-transform: uppercase; color: rgba(255, 249, 245, .6); }
.ob__quote { margin-top: .4em; font-size: 1.1em; line-height: 1.35; font-style: italic; color: var(--c-accent-highlight); }
.ob__side--meant .ob__quote { color: var(--c-accent-pink); }
.ob__arrow { align-self: center; }
.ob__arrow svg { width: 2.6em; height: 1em; fill: none; stroke: var(--c-accent-cyan); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.ob__strength { display: flex; flex-wrap: wrap; align-items: center; gap: .5em; width: 100%; max-width: 33em; font-family: var(--font-secondary); font-size: .95em; letter-spacing: .04em; color: rgba(255, 249, 245, .6); }
.ob__slabel { text-transform: uppercase; }
.ob__sval { color: var(--accent-neon-red); text-transform: uppercase; }
.ob__bars { display: inline-flex; gap: .2em; }
.ob__bars i { display: block; width: .45em; height: 1em; border-radius: .1em; background: var(--accent-neon-red); box-shadow: 0 0 .4em rgba(255, 82, 82, .5); }
.ob__snote { flex: 1 1 100%; color: rgba(255, 249, 245, .5); }
.ob.is-run .ob__side  { animation: tp-item .5s cubic-bezier(.2, .7, .2, 1) both; }
.ob.is-run .ob__side--meant { animation-delay: .45s; }
.ob.is-run .ob__arrow { animation: oo-fade .4s ease-out both .35s; }
.ob.is-run .ob__strength { animation: oo-fade .5s ease-out both .8s; }

/* Buying readiness */
.br {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.4em;
    font-size: clamp(11px, 2.6cqi, 17px);
}
.br__screen {
    position: relative; width: 100%; max-width: 30em; padding: 1.4em 1.8em; border-radius: 1em; text-align: center;
    border: 1px solid rgba(171, 235, 240, .4);
    background:
        repeating-linear-gradient(180deg, rgba(171, 235, 240, .05) 0 1px, rgba(171, 235, 240, 0) 1px 4px),
        linear-gradient(160deg, rgba(94, 55, 110, .42), rgba(21, 0, 27, .9));
    box-shadow: inset 0 0 30px rgba(171, 235, 240, .12), 0 16px 40px rgba(0, 0, 0, .35);
}
.br__verdict { font-family: var(--font-secondary); font-size: 1.9em; line-height: 1.15; font-weight: var(--fw-semibold); letter-spacing: .03em; color: #5FE3A1; text-shadow: 0 0 16px rgba(95, 227, 161, .45); }
.br__signals { display: flex; flex-direction: column; align-items: center; gap: .55em; margin-top: 1em; padding-top: .9em; border-top: 1px solid rgba(171, 235, 240, .22); }
.br__signal { display: inline-flex; align-items: center; gap: .5em; font-size: 1.05em; color: var(--c-text); }
.br__signal .tl__glyph { width: 1.05em; height: 1.05em; color: #5FE3A1; }
.br.is-run .br__screen { animation: oo-screen .6s ease-out both; }
.br.is-run .oo__bar    { animation: oo-fade .5s ease-out both .2s; }
.br.is-run .br__verdict { animation: oo-title .9s ease-out both .2s; }
.br.is-run .br__signal { animation: en-line .45s ease-out both; animation-delay: calc(.7s + var(--k, 0) * .18s); }

@container (max-width: 430px) {
    .nd__item { grid-template-columns: 2.2em 1fr; padding: .7em .8em; }
    .ob__pair { grid-template-columns: 1fr; }
    .ob__arrow { justify-self: center; transform: rotate(90deg); }
    .br__screen { padding: 1.1em 1.1em; }
    .br__verdict { font-size: 1.55em; }
}

/* ── Sales · 4 · The Competition's visuals ──────────────────────────────
   The field as two columns, price sensitivity as a three-stop scale with the read
   pinned on it, the win strategy as ranked moves. Same rules again.             */

/* Competitive read */
.cs {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.4em;
    font-size: clamp(10px, 2.5cqi, 16px);
}
.cs__cols { display: grid; grid-template-columns: 1fr 1fr; gap: .9em; width: 100%; max-width: 34em; }
.cs__col { padding: 1em 1.1em; border-radius: .8em; border: 1px solid rgba(171, 235, 240, .28); background: linear-gradient(160deg, rgba(94, 55, 110, .32), rgba(21, 0, 27, .85)); --cs: #5FE3A1; }
.cs__col--exposed { --cs: var(--accent-neon-red); border-color: rgba(255, 82, 82, .35); }
.cs__label { font-family: var(--font-secondary); font-size: .95em; letter-spacing: .05em; text-transform: uppercase; color: var(--cs); }
.cs__list { display: flex; flex-direction: column; gap: .55em; margin-top: .8em; }
.cs__list li { display: grid; grid-template-columns: 1.15em 1fr; align-items: start; gap: .5em; font-size: 1.02em; line-height: 1.35; color: var(--c-text); }
.cs__list .tl__glyph { width: 1.15em; height: 1.15em; margin-top: .1em; color: var(--cs); }
.cs.is-run .cs__col { animation: tp-item .55s cubic-bezier(.2, .7, .2, 1) both; }
.cs.is-run .cs__col--exposed { animation-delay: .25s; }
.cs.is-run .cs__list li { animation: en-line .45s ease-out both; animation-delay: calc(.4s + var(--k, 0) * .12s); }

/* Price sensitivity */
.pc {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.4em;
    font-size: clamp(11px, 2.6cqi, 17px);
}
.pc__screen {
    position: relative; width: 100%; max-width: 30em; padding: 1.5em 2em 1.7em; border-radius: 1em;
    border: 1px solid rgba(171, 235, 240, .4);
    background:
        repeating-linear-gradient(180deg, rgba(171, 235, 240, .05) 0 1px, rgba(171, 235, 240, 0) 1px 4px),
        linear-gradient(160deg, rgba(94, 55, 110, .42), rgba(21, 0, 27, .9));
    box-shadow: inset 0 0 30px rgba(171, 235, 240, .12), 0 16px 40px rgba(0, 0, 0, .35);
}
.pc__title { font-family: var(--font-secondary); font-size: 1em; letter-spacing: .06em; text-transform: uppercase; text-align: center; color: rgba(255, 249, 245, .75); }
.pc__scale { position: relative; margin-top: 1.6em; }
.pc__track { display: block; height: .55em; border-radius: .3em; background: linear-gradient(90deg, #5FE3A1, var(--accent-desert-sand), var(--accent-neon-red)); opacity: .75; }
.pc__pin {
    position: absolute; top: -.45em; left: calc((var(--at) + .5) / var(--stops) * 100%); transform: translateX(-50%);
    width: 1.4em; height: 1.4em; border-radius: 50%; border: 2px solid var(--accent-neon-red);
    background: var(--c-primary-dark); box-shadow: 0 0 .8em rgba(255, 82, 82, .6);
}
.pc__stops { display: grid; grid-template-columns: repeat(var(--stops), 1fr); margin-top: .7em; font-family: var(--font-secondary); font-size: .95em; letter-spacing: .05em; text-transform: uppercase; color: rgba(255, 249, 245, .55); text-align: center; }
.pc__stop.is-at { color: var(--accent-neon-red); }
.pc.is-run .pc__screen { animation: oo-screen .6s ease-out both; }
.pc.is-run .oo__bar    { animation: oo-fade .5s ease-out both .2s; }
.pc.is-run .pc__title  { animation: oo-fade .5s ease-out both .2s; }
.pc.is-run .pc__track  { animation: sk-fill .7s cubic-bezier(.2, .7, .2, 1) both .3s; transform-origin: left; }
.pc.is-run .pc__pin    { animation: pc-pin .5s cubic-bezier(.2, .7, .2, 1) both .9s; }
.pc.is-run .pc__stop   { animation: oo-fade .4s ease-out both; animation-delay: calc(.5s + var(--k, 0) * .1s); }
@keyframes pc-pin { from { opacity: 0; transform: translateX(-50%) translateY(-.5em) scale(.5); } to { opacity: 1; transform: translateX(-50%); } }

/* Win strategy */
.mv {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.3em;
    font-size: clamp(10px, 2.5cqi, 16px);
}
.mv__list { display: flex; flex-direction: column; gap: .85em; width: 100%; max-width: 33em; }
.mv__move { position: relative; padding: 1em 1.2em 1em 1.4em; border-radius: .8em; border: 1px solid rgba(171, 235, 240, .3); background: linear-gradient(160deg, rgba(94, 55, 110, .34), rgba(21, 0, 27, .85)); }
.mv__move::before { content: ''; position: absolute; left: 0; top: 1em; bottom: 1em; width: 3px; border-radius: 0 3px 3px 0; background: var(--c-accent-cyan); box-shadow: 0 0 .6em rgba(171, 235, 240, .5); }
.mv__head { display: flex; flex-wrap: wrap; align-items: center; gap: .6em; }
.mv__rank { font-family: var(--font-secondary); font-size: 1.05em; letter-spacing: .05em; text-transform: uppercase; color: var(--c-accent-highlight); }
.mv__impact { padding: .12em .6em; border-radius: 999px; border: 1px solid rgba(95, 227, 161, .5); font-family: var(--font-secondary); font-size: .85em; letter-spacing: .04em; text-transform: uppercase; color: #5FE3A1; }
.mv__text { margin-top: .5em; font-size: 1.05em; line-height: 1.4; color: var(--c-text); }
.mv__kind { margin-top: .5em; font-family: var(--font-secondary); font-size: .9em; letter-spacing: .05em; text-transform: uppercase; color: rgba(255, 249, 245, .55); }
.mv.is-run .mv__move { animation: tp-item .55s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.2s + var(--k, 0) * .28s); }
.mv.is-run .mv__move::before { animation: tp-spine .5s ease-out both; animation-delay: calc(.35s + var(--k, 0) * .28s); transform-origin: top; }

@container (max-width: 430px) {
    .cs__cols { grid-template-columns: 1fr; }
    .cs__col { padding: .85em .95em; }
    .pc__screen { padding: 1.2em 1.2em 1.4em; }
    .mv__move { padding: .85em 1em .85em 1.2em; }
}

/* ── AVI_Callback Engine ────────────────────────────────────────────────
   §1 the found card among six, §2 and §5 the same queue twice: as the dialer hands
   it over and as the engine ranks it. The queue is the page's argument, so it is
   drawn as the reference has it — rows as cards, the buried lead marked — not as
   the frame's plain table.                                                      */

/* 1 · hero: the copy right, the call cards left. Same ground as every product hero */
.prod-hero--callback { background: linear-gradient(104deg, var(--primary-900) 0%, var(--primary-800) 46%, var(--primary-600) 100%); }
.cbcards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); width: 100%; }
.cbcard {
    display: flex; flex-direction: column; justify-content: space-between; gap: var(--space-5);
    min-height: 7.5em; padding: var(--space-4); border-radius: 12px;
    border: 1px solid rgba(171, 235, 240, .16);
    background: var(--gloss-sheen), rgba(80, 80, 80, .18);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12), 0 12px 30px rgba(0, 0, 0, .3);
    font-size: var(--t-p3); color: rgba(255, 249, 245, .65);
}
.cbcard__decision b { display: inline-block; margin-top: .2em; font-weight: var(--fw-regular); color: rgba(255, 249, 245, .8); }
.cbcard--found {
    border-color: var(--c-accent-cyan); color: var(--primary-900);
    background: var(--gloss-sheen), var(--accent-ice-blue);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 0 40px rgba(171, 235, 240, .35);
}
.cbcard--found .cbcard__decision b { color: var(--primary-900); font-weight: var(--fw-semibold); }
.js .cbcards.is-visible .cbcard--found { animation: cb-found 3.2s ease-in-out .4s infinite; }   /* a heartbeat, not a single flash (2026-09-23): the one worth calling keeps signalling */
@keyframes cb-found {
    0%, 100% { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 0 26px rgba(171, 235, 240, .28); }
    12%      { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 0 60px rgba(171, 235, 240, .75); }
    24%      { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 0 30px rgba(171, 235, 240, .35); }
    34%      { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 0 52px rgba(171, 235, 240, .6); }
    48%      { box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 0 26px rgba(171, 235, 240, .28); }
}

/* 2 and 5 · the queue. The frame runs a purple→cyan band behind each; ours keeps
   that direction but stays dark enough for the table to read on it.            */
.prod-queue--clock { background: linear-gradient(90deg, var(--neutral-black) 0%, var(--c-surface-1) 100%); }   /* the Collections problem ground: the dialer's queue is the old system, so it does not get the brand's colours (2026-09-23) */
.prod-queue--ranked { background: linear-gradient(100deg, var(--primary-800) 0%, var(--primary-500) 45%, rgba(94, 55, 110, .95) 100%); }
.prod-queue__grid { display: flex; flex-direction: column; gap: var(--space-8); }
.prod-queue__copy { display: flex; flex-direction: column; gap: var(--space-4); }
.cq {
    padding: var(--space-5) var(--space-6); border-radius: 16px;
    border: 1px solid rgba(171, 235, 240, .25);
    background: rgba(21, 0, 27, .55); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    box-shadow: 0 18px 44px rgba(0, 0, 0, .35);
}
/* the dialer's queue reads in the system's own greys; only the buried lead is ours */
.prod-queue--clock .cq { border-color: rgba(168, 168, 168, .3); background: rgba(0, 0, 0, .45); }
.prod-queue--clock .cq__title { color: var(--grey-700); }
.prod-queue--clock .cq__row { border-color: rgba(168, 168, 168, .18); }
.cq__top { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-4); font-family: var(--font-secondary); font-size: var(--t-p3); letter-spacing: var(--ls-cta); text-transform: uppercase; }
.cq__title { color: var(--c-accent-cyan); }
.cq__sort  { color: rgba(255, 249, 245, .55); }
.cq--ranked .cq__sort { color: var(--teal-500); }
.cq__rows { display: flex; flex-direction: column; gap: 6px; }
.cq__row {
    display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-3);
    padding: 10px var(--space-4); border-radius: 8px;
    border: 1px solid rgba(171, 235, 240, .14); background: rgba(255, 255, 255, .02);
    font-family: var(--font-secondary); font-size: var(--t-p3); color: rgba(255, 249, 245, .75);
}
.cq__at, .cq__rank { color: rgba(255, 249, 245, .55); }
.cq__rank { min-width: 1.8em; text-align: right; }
.cq__lead { color: rgba(255, 249, 245, .85); }
.cq__score { font-size: var(--t-p2); color: var(--c-text); }
.cq__state { color: rgba(255, 249, 245, .5); }
.cq__prio { padding: .1em .55em; border-radius: 999px; font-size: calc(var(--t-p3) - 1px); letter-spacing: .04em; border: 1px solid currentColor; }
.cq__prio--p1 { color: var(--c-accent-pink); }
.cq__prio--p2 { color: var(--accent-desert-sand); }
.cq__prio--p3 { color: rgba(255, 249, 245, .45); }
.cq__tag { grid-column: 1 / -1; font-family: var(--font-primary); font-size: var(--t-p3); color: var(--teal-500); }
.cq__row.is-hot  { border-color: rgba(152, 235, 239, .55); background: rgba(152, 235, 239, .1); color: var(--c-text); box-shadow: 0 0 22px rgba(152, 235, 239, .14); }
.cq__row.is-hot .cq__at, .cq__row.is-hot .cq__rank, .cq__row.is-hot .cq__lead, .cq__row.is-hot .cq__state { color: var(--c-accent-highlight); }
.cq__row.is-warm { border-color: rgba(152, 235, 239, .3); background: rgba(152, 235, 239, .05); }
.cq__row.is-cold { opacity: .55; }
.cq__gap { display: flex; justify-content: center; gap: .5em; padding: 6px 0; }
.cq__gap span { width: 3px; height: 3px; border-radius: 50%; background: rgba(255, 249, 245, .35); }
.cq__note { margin-top: var(--space-4); font-size: var(--t-p2); color: rgba(255, 249, 245, .6); }
.cq--ranked .cq__note { color: var(--teal-500); }
/* Every row was its own grid container, so each one sized its own tracks from its
   own contents and the columns never lined up down the list — and the rows that
   carry no state cell shifted their score and priority right (2026-09-24).
   One grid for the whole list; the rows borrow its columns with subgrid, so all
   five line up however wide the contents are. */
.cq--ranked .cq__rows { display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto auto; row-gap: 6px; column-gap: var(--space-3); }
.cq--ranked .cq__row  { grid-column: 1 / -1; grid-template-columns: subgrid; }
.cq--ranked .cq__gap  { grid-column: 1 / -1; }
.cq--ranked .cq__score { text-align: right; }   /* the digits line up too */
/* The re-sort (products.js): the list arrives in lead-number order with the ranks
   and the elision blank, then sorts itself by score and they fade in — the
   section's own sentence, drawn. The server always renders the sorted order, so
   no-JS and Reduce Motion get the truth and nothing here applies to them. */
.cq--ranked .cq__rank, .cq--ranked .cq__gap { transition: opacity .55s ease .25s; }
.cq--ranked.is-unsorted .cq__rank, .cq--ranked.is-unsorted .cq__gap { opacity: 0; transition-delay: 0s; }
/* the rows land in order, as a queue being read */
.js [data-reveal].is-visible .cq__row { animation: tp-item .45s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.15s + var(--k, 0) * .09s); }

/* 3 · the log against the voice: the Collections split, with its body line above */
.prod-audit__body { max-width: 60ch; margin-top: var(--space-4); text-align: left; }   /* stacked: left, as above */
@media (min-width: 768px) { .prod-audit__body { margin-inline: auto; text-align: center; } }

@media (min-width: 1024px) {
    .prod-hero--callback .prod-hero__inner { flex-direction: row-reverse; align-items: center; gap: var(--space-16); }
    .prod-hero--callback .cbcards { flex: 0 0 clamp(300px, 32vw, 420px); grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .prod-hero--callback .prod-hero__copy { flex: 1 1 0; min-width: 0; max-width: 706px; }
    .prod-queue__grid { flex-direction: row; align-items: center; justify-content: space-between; gap: var(--space-10); }
    .prod-queue__copy { flex: 0 1 460px; }
    .prod-queue__copy h2 { max-width: 20ch; }   /* capped only beside the queue */
    .prod-queue__grid > :last-child { flex: 0 1 640px; }
}
/* 7 · the particle band is much busier than Collections' wave, so the copy gets a scrim
   rather than a wash, and the band sits low behind the tiles                   */
.prod-recover--callback::before { background: none; }
.prod-recover--callback::after { content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none; background: linear-gradient(90deg, rgba(21, 0, 27, .94) 0%, rgba(21, 0, 27, .78) 42%, rgba(21, 0, 27, .5) 100%); }   /* ::after, not ::before: a pseudo-element paints under the element's own children, so a scrim on ::before ended up beneath the picture */
.prod-recover--callback .prod-recover__bg img { object-position: 50% 70%; opacity: .8; }

/* ── Callback · 4 · the verdict's three visuals ─────────────────────────
   The score on its arc with the priority it lands in, the vitals as the Engagement
   meters (already defined), and the next step as two cards: the priority to dial by
   and the angle to try. Same rules as every other visual.                       */

/* Lead Score */
.ls {
    position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .35em;
    padding: 1.3em;
    font-size: clamp(10px, 2.6cqi, 17px);
}
.ls__dial { position: relative; width: 100%; max-width: 26em; }
.ls__dial .cr__svg { display: block; width: 100%; height: auto; overflow: visible; }
.ls__arc { stroke: var(--c-accent-highlight); }
.ls__value { position: absolute; left: 0; right: 0; bottom: 26%; text-align: center; font-family: var(--font-secondary); font-size: 3.4em; line-height: 1; color: var(--c-accent-highlight); text-shadow: 0 0 18px rgba(152, 235, 239, .45); }
.ls__of { position: absolute; left: 0; right: 0; bottom: 14%; text-align: center; font-family: var(--font-secondary); font-size: .95em; letter-spacing: .06em; text-transform: uppercase; color: rgba(255, 249, 245, .6); }
.ls__plabel { font-family: var(--font-secondary); font-size: .95em; letter-spacing: .08em; text-transform: uppercase; color: rgba(255, 249, 245, .6); }
.ls__prios { display: flex; gap: .5em; }
.ls__prio {
    display: grid; place-items: center; min-width: 2.6em; padding: .3em .6em; border-radius: .4em;
    border: 1px solid rgba(171, 235, 240, .3); background: rgba(171, 235, 240, .06);
    font-family: var(--font-secondary); font-size: 1.05em; color: rgba(255, 249, 245, .7);
}
.ls__prio.is-at { border-color: var(--c-accent-cyan); background: var(--accent-ice-blue); color: var(--primary-900); box-shadow: 0 0 20px rgba(171, 235, 240, .45); }
.ls__caption { margin-top: .3em; font-family: var(--font-secondary); font-size: .95em; letter-spacing: .04em; color: rgba(255, 249, 245, .65); }
.ls.is-run .cr__body, .ls.is-run .cr__track { animation: cr-body .7s ease-out both; }
.ls.is-run .ls__value, .ls.is-run .ls__of { animation: cr-value .6s ease-out both .3s; }
.ls.is-run .ls__plabel { animation: oo-fade .5s ease-out both .9s; }
.ls.is-run .ls__prio { animation: en-line .45s ease-out both; animation-delay: calc(1s + var(--k, 0) * .12s); }
.ls.is-run .ls__caption { animation: oo-fade .5s ease-out both 1.5s; }

/* Next Step */
.ns {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.3em;
    font-size: clamp(10px, 2.5cqi, 16px);
}
.ns__cols { display: grid; grid-template-columns: 1fr 1fr; gap: .9em; width: 100%; max-width: 33em; }
.ns__col { padding: 1em 1.1em; border-radius: .8em; border: 1px solid rgba(171, 235, 240, .28); background: linear-gradient(160deg, rgba(94, 55, 110, .34), rgba(21, 0, 27, .85)); --ns: var(--accent-desert-sand); }
.ns__col--act { --ns: var(--c-accent-cyan); border-color: rgba(171, 235, 240, .45); box-shadow: 0 0 24px rgba(171, 235, 240, .12); }
.ns__label { font-family: var(--font-secondary); font-size: .9em; letter-spacing: .06em; text-transform: uppercase; color: rgba(255, 249, 245, .6); }
.ns__big { margin-top: .35em; font-size: 1.5em; line-height: 1.2; color: var(--ns); text-shadow: 0 0 14px color-mix(in srgb, var(--ns) 35%, transparent); }
.ns__text { margin-top: .5em; font-size: 1em; line-height: 1.4; color: rgba(255, 249, 245, .8); }
.ns.is-run .ns__col { animation: tp-item .55s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.2s + var(--k, 0) * .28s); }
.ns.is-run .ns__big { animation: oo-value .5s ease-out both; animation-delay: calc(.5s + var(--k, 0) * .28s); }

@container (max-width: 430px) {
    .ls__value { font-size: 2.9em; }
    .ns__cols { grid-template-columns: 1fr; }
    .ns__col { padding: .85em .95em; }
}

/* ── AVI_Audit ──────────────────────────────────────────────────────────
   §1 the frame's render beside the copy, §2 the day's calls as cells (three lit out
   of a hundred), §3 the struck phrases on the Sales device, §4 the rubric's three
   visuals, §5 the defects table on the callback queue's panel.                  */

/* 1 · hero */
.prod-hero--audit { background: linear-gradient(104deg, var(--primary-900) 0%, var(--primary-800) 46%, var(--primary-600) 100%); }
/* Stacked, the render is the card it has always been, below the copy: the picture
   is a section-level child now (it has to be, to reach the section's edges at
   1024+), so the section stacks and the card treatment lives on the picture.
   Measured identical to the pre-change mobile hero.                           */
.prod-hero--audit { flex-direction: column; }
.prod-hero__art { order: 2; display: block; width: auto; margin: var(--space-10) var(--page-gutter) 0; border-radius: 16px; overflow: hidden; box-shadow: 0 20px 50px rgba(0, 0, 0, .4); }
.prod-hero__art img { display: block; width: 100%; height: auto; }

/* 2 · the day's calls, as cells. Three audited, one of the unheard hiding a defect */
/* Stacked, the field is a block of its own under the copy rather than a layer
   behind it. Below 1024 the copy runs the full width, so the overlay collided
   with it: a lit cell sat on the headline at 768 and the flagged one hid
   behind the word AUDITED at 500, the one cell the note points at. Full
   bleed and in flow, every cell is legible. The overlay comes back at 1024+,
   where the H2 is capped at 24ch and the field has the right half to itself. */
.prod-cells { position: relative; overflow: hidden; display: flex; flex-direction: column; background: linear-gradient(90deg, var(--neutral-black) 0%, var(--c-surface-1) 100%); }
.prod-cells__field { order: 2; display: flex; flex-direction: column; gap: 1px; background: rgba(171, 235, 240, .18); pointer-events: none; }
/* A continuous field, not a row of chips. Figma's cells share one hairline
   between them; giving every cell its own 1px border put two borders plus a
   gap between neighbours, about 3px of seam, and the wall became a chart of
   discrete objects — the wrong metaphor for "a hundred calls nobody played
   back". So the separator lives on the ROW as a background showing through a
   1px gap, and the cells carry no border at all. */
.prod-cells__row { display: flex; gap: 1px; background: rgba(171, 235, 240, .18); }
.prod-cells__cell { flex: 1; height: 34px; background: rgba(171, 235, 240, .05); }
.prod-cells__cell.is-audited { background: var(--accent-ice-blue); box-shadow: 0 0 18px rgba(171, 235, 240, .5); }
.prod-cells__cell.is-flagged { background: rgba(232, 182, 240, .22); }
.js .prod-cells .prod-cells__cell.is-audited { animation: cells-lit 4s ease-in-out infinite; animation-delay: calc(var(--c, 0) * .05s); }
@keyframes cells-lit { 0%, 100% { box-shadow: 0 0 14px rgba(171, 235, 240, .4); } 50% { box-shadow: 0 0 26px rgba(171, 235, 240, .75); } }
.prod-cells__copy { position: relative; display: flex; flex-direction: column; gap: var(--space-4); padding-block: var(--space-10); }
.prod-cells__legend { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); font-family: var(--font-secondary); font-size: var(--t-p3); letter-spacing: var(--ls-cta); text-transform: uppercase; color: rgba(255, 249, 245, .6); }
.prod-cells__title { color: var(--c-accent-cyan); }
.prod-cells__key { display: inline-flex; align-items: center; gap: .5em; }
.prod-cells__key i { width: 10px; height: 10px; border-radius: 2px; border: 1px solid rgba(171, 235, 240, .25); background: rgba(171, 235, 240, .05); }
.prod-cells__key i.is-audited { border-color: var(--c-accent-cyan); background: var(--accent-ice-blue); }
.prod-cells__note { font-size: var(--t-p1); color: var(--c-text); }
/* Stacked there is nothing to dim selectively, but the field still needs
   knocking back or the wall of ninety-seven reads as bright as the three that
   were audited. A flat scrim does it; the lit cells carry z-index and stay
   above it. At 1024+ this becomes the left-to-right gradient that clears the
   copy. */
.prod-cells::after { content: ''; position: absolute; inset: 0; background: rgba(0, 0, 0, .45); pointer-events: none; }
/* NO z-index on the field, deliberately. It used to carry z-index: 0, which
   creates a stacking context and trapped the audited cells' z-index: 2 inside
   it — the scrim then painted over them and they rendered at 79% of
   #ABEBF0, a muted teal. The comment below claimed they read through; they did
   not. Measured and fixed 2026-09-30. Leave the field unpositioned in the
   z-axis and the cells reach the top on their own. */
.prod-cells__cell.is-audited, .prod-cells__cell.is-flagged { position: relative; z-index: 2; }   /* the audited ones read through the scrim; that is the point */
.prod-cells .container { position: relative; z-index: 3; }

/* 3 · five phrases will not sit in one row, so this page's bar wraps to two, and the
   dividers become cell borders rather than full-height rules                     */
@media (min-width: 1024px) {
    .prod-missing--audit .prod-gone { align-items: center; }
    .prod-missing--audit .prod-gone__list { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; }
    .prod-missing--audit .prod-gone__list li { padding: var(--space-5) var(--space-5); border-left: 1px solid rgba(255, 255, 255, .12); }
    .prod-missing--audit .prod-gone__list li:nth-child(3n + 1) { border-left: 0; padding-left: var(--space-8); }
    .prod-missing--audit .prod-gone__list li:nth-child(n + 4) { border-top: 1px solid rgba(255, 255, 255, .12); }
    /* Row 2 holds only items 4 and 5, so the third column is free. Item 5 takes
       it: at ~33 characters a cell it would otherwise wrap, and the line carries
       a contrast — the agent who NEEDED coaching against the one who GOT picked
       — that no shorter version survives. Four short phrases and one that lands
       harder reads better than five of one weight. */
    .prod-missing--audit .prod-gone__list li:nth-child(5) { grid-column: 2 / span 2; }
    .prod-missing--audit .prod-gone__list li + li::before, .prod-missing--audit .prod-gone__list li + li::after { display: none; }
}
/* 3 · the closing line under the struck phrases */
.prod-missing--audit .prod-missing__close { margin-top: var(--space-8); font-size: var(--t-h3); line-height: var(--lh-heading); font-weight: var(--fw-medium); }

/* 4 · the scorecard */
.sc {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.3em;
    font-size: clamp(10px, 2.5cqi, 16px);
}
.sc__grid { display: grid; grid-template-columns: 1fr 1fr; gap: .8em; width: 100%; max-width: 32em; }
.sc__stat { display: flex; flex-direction: column; align-items: center; gap: .25em; padding: .9em 1em; border-radius: .7em; border: 1px solid rgba(171, 235, 240, .3); background: linear-gradient(160deg, rgba(94, 55, 110, .3), rgba(21, 0, 27, .85)); --sc: var(--c-accent-highlight); }
.sc__stat--good { --sc: #5FE3A1; border-color: rgba(95, 227, 161, .4); }
.sc__stat--warn { --sc: var(--accent-desert-sand); border-color: rgba(230, 210, 181, .4); }
.sc__label { font-family: var(--font-secondary); font-size: .85em; letter-spacing: .07em; text-transform: uppercase; color: rgba(255, 249, 245, .6); }
.sc__value { font-family: var(--font-secondary); font-size: 1.9em; line-height: 1.1; color: var(--sc); text-shadow: 0 0 14px color-mix(in srgb, var(--sc) 35%, transparent); }
.sc.is-run .sc__stat { animation: tp-item .5s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.15s + var(--k, 0) * .09s); }
.sc.is-run .sc__value { animation: oo-value .5s ease-out both; animation-delay: calc(.35s + var(--k, 0) * .09s); }

/* 4 · the rubric */
.ru {
    position: absolute; inset: 0; display: grid; place-items: center; padding: 1.1em;
    font-size: clamp(9px, 2.2cqi, 14px);
}
.ru__list { display: grid; grid-template-columns: 1fr; gap: .3em; width: 100%; max-width: 34em; }
.ru__check { display: grid; grid-template-columns: 5.4em 1fr; align-items: baseline; gap: .2em .7em; padding: .5em .8em; border-radius: .5em; border: 1px solid rgba(171, 235, 240, .16); background: rgba(171, 235, 240, .03); --ru: #5FE3A1; }
.ru__check--defect { --ru: var(--accent-neon-red); border-color: rgba(255, 82, 82, .35); background: rgba(255, 82, 82, .06); }
.ru__state { display: inline-flex; align-items: center; gap: .35em; font-family: var(--font-secondary); font-size: .95em; letter-spacing: .05em; text-transform: uppercase; color: var(--ru); }
.ru__state .tl__glyph { width: .95em; height: .95em; }
.ru__name { font-size: 1.05em; color: var(--c-text); }
.ru__note { grid-column: 2; font-size: .95em; color: rgba(255, 249, 245, .6); }
.ru.is-run .ru__check { animation: en-line .4s ease-out both; animation-delay: calc(.12s + var(--k, 0) * .07s); }
/* nine checks will not stand in one column inside the panel: two from 480px across */
@container (min-width: 480px) {
    .ru { font-size: clamp(9px, 1.9cqi, 13px); }
    .ru__list { grid-template-columns: 1fr 1fr; gap: .3em .5em; max-width: none; }
}

/* 4 · the issues surfaced */
.is {
    position: absolute; inset: 0; display: grid; place-items: center; align-content: center; gap: .8em; padding: 1.3em;
    font-size: clamp(10px, 2.4cqi, 15px);
}
.is__list { display: flex; flex-direction: column; gap: .7em; width: 100%; max-width: 33em; }
.is__item { padding: .85em 1em; border-radius: .7em; border: 1px solid rgba(255, 82, 82, .35); background: linear-gradient(160deg, rgba(94, 55, 110, .3), rgba(21, 0, 27, .85)); }
.is__tag { display: flex; align-items: center; gap: .5em; font-family: var(--font-secondary); font-size: .9em; letter-spacing: .06em; text-transform: uppercase; color: var(--accent-neon-red); }
.is__text { margin-top: .4em; font-size: 1.1em; line-height: 1.35; color: var(--c-text); }
.is__where { margin-top: .35em; font-family: var(--font-secondary); font-size: .9em; letter-spacing: .04em; color: rgba(255, 249, 245, .6); }
.is__summary { width: 100%; max-width: 33em; padding: .85em 1em; border-radius: .7em; border: 1px solid rgba(171, 235, 240, .3); background: rgba(171, 235, 240, .05); }
.is__slabel { font-family: var(--font-secondary); font-size: .9em; letter-spacing: .06em; text-transform: uppercase; color: var(--c-accent-cyan); }
.is__stext { margin-top: .35em; font-size: 1em; line-height: 1.4; color: rgba(255, 249, 245, .85); }
.is.is-run .is__item { animation: tp-item .5s cubic-bezier(.2, .7, .2, 1) both; animation-delay: calc(.15s + var(--k, 0) * .22s); }
.is.is-run .is__summary { animation: oo-fade .5s ease-out both .8s; }

/* 5 · the defects table shares the queue's panel */
.cq--table .cq__row { grid-template-columns: 1fr 4.5em 3em 9.5em; gap: var(--space-3); }
.cq__row--head { border: 0; background: none; font-size: var(--t-p3); letter-spacing: var(--ls-cta); text-transform: uppercase; color: rgba(255, 249, 245, .45); padding-block: 2px; }
.cq__count { text-align: right; color: var(--c-text); }
.cq__trend { display: inline-flex; justify-content: center; }
.cq__trend svg { width: 1em; height: 1em; fill: currentColor; stroke: currentColor; stroke-width: 1.4; }
.cq__row--up   .cq__trend { color: #5FE3A1; }
.cq__row--down .cq__trend { color: var(--accent-neon-red); }
.cq__row--flat .cq__trend { color: var(--accent-desert-sand); }
.cq__action { color: rgba(255, 249, 245, .7); }
.cq--table .cq__row--down .cq__action { color: var(--accent-desert-sand); }

/* 6 · outcomes on this page have no raster: a plain ground, tiles numbered */
/* 6 · Outcomes. Audit does NOT use .prod-recover: frame 817:4165 puts the copy
   across the top and the four tiles in one row, each led by a 48px numeral.
   The other product pages keep .prod-recover with its background photo; Audit
   has no photo, so the frame gives it a gradient and five blurred glows.      */
.prod-numbered { position: relative; overflow: hidden; background: linear-gradient(90deg, var(--neutral-black) 0%, var(--c-surface-1) 100%); }
/* the frame's glows: two large white (top-left and bottom-right), a small
   white, a cyan and a lavender. All blurred 50 with a wide spread, so they
   read as light in the ground rather than as shapes.                         */
.prod-numbered::before {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background:
        radial-gradient(26% 74% at  1% -3%, rgba(253, 253, 253, .20) 0%, rgba(253, 253, 253, 0) 70%),
        radial-gradient(26% 62% at 93% 78%, rgba(253, 253, 253, .20) 0%, rgba(253, 253, 253, 0) 70%),
        radial-gradient(14% 34% at 28% 33%, rgba(253, 253, 253, .14) 0%, rgba(253, 253, 253, 0) 70%),
        radial-gradient(14% 34% at 68% 40%, rgba(171, 235, 240, .28) 0%, rgba(171, 235, 240, 0) 70%),
        radial-gradient(13% 32% at  5% 76%, rgba(232, 182, 240, .30) 0%, rgba(232, 182, 240, 0) 70%);
}
.prod-numbered .container { position: relative; z-index: 1; }
/* Stacked at every width, matching Collections' section 8 (.prod-owners__head): the
   frame splits H2 left and body right, but the head reads better as one column
   and is now the same shape in both places.                                   */
.prod-numbered__copy { display: flex; flex-direction: column; gap: var(--space-4); }
.prod-numbered__copy h2 { max-width: none; }
.prod-numbered__copy p  { font-size: var(--t-p1); }
.prod-numbered .prod-tiles { margin-top: var(--space-10); }

/* The tile. min-height rather than the frame's fixed 305: the numeral sits at
   the top and margin-top: auto drops the name and text to the foot, which is
   what makes the gap between them the composition. Fixing the height instead
   would clip the longest text in a narrow tile.                              */
.ntile {
    position: relative; isolation: isolate; flex: 0 0 auto; scroll-snap-align: start;
    width: min(300px, calc(100vw - var(--page-gutter) - var(--space-5) - 28px));
    min-height: 305px; padding: var(--space-5); overflow: hidden;
    display: flex; flex-direction: column; gap: var(--space-2);
    border-radius: 16px; background: rgba(255, 255, 255, .12);
    transition: background .35s ease, transform .3s ease;
}
.ntile__no   { font-size: var(--t-h2); line-height: var(--lh-heading); transition: opacity .3s ease; }
.ntile__name { margin-top: auto; font-size: var(--t-h4); line-height: var(--lh-heading); font-weight: var(--fw-regular); }
.ntile__text { font-size: var(--t-p2); }
/* the pair bleeds off the top and right edges; the tile's overflow clips it */
.ntile__chev { position: absolute; top: -19px; right: -9px; width: 207px; height: 149px; opacity: 0; filter: blur(2px); pointer-events: none; transition: opacity .35s ease; }
/* the lit state (component 850:4542): the numeral gives way to the chevrons.
   #5B3367 is --primary-400 exactly. The frame's lavender is within 19 of
   --accent-soft-lavender, and its amber has no token, so the warm point-glow
   is --accent-desert-sand: the warm-against-cool reading survives and the
   generated palette stays untouched.                                         */
.ntile.is-current, .ntile:hover {
    background:
        radial-gradient(52% 50% at  3%   9%, rgba(232, 182, 240, .35) 0%, rgba(232, 182, 240, 0) 70%),
        radial-gradient(34% 34% at 98% 100%, rgba(230, 210, 181, .30) 0%, rgba(230, 210, 181, 0) 70%),
        linear-gradient(180deg, var(--c-primary-dark) 0%, var(--c-primary-light) 100%);
}
.ntile.is-current .ntile__no,   .ntile:hover .ntile__no   { opacity: 0; }
.ntile.is-current .ntile__chev, .ntile:hover .ntile__chev { opacity: 1; }
@media (hover: hover) {
    .js .ntile.is-visible:hover { transform: translateY(-4px); transition-duration: .3s; }
}
/* below 1024 the carousel lights the current tile; hovering the row hands that
   over to the pointer, as it does for the other tile rows                     */
@media (hover: hover) and (max-width: 1023px) {
    .prod-tiles__row:hover .ntile.is-current:not(:hover) { background: rgba(255, 255, 255, .12); }
    .prod-tiles__row:hover .ntile.is-current:not(:hover) .ntile__no   { opacity: 1; }
    .prod-tiles__row:hover .ntile.is-current:not(:hover) .ntile__chev { opacity: 0; }
}

/* 7 · Who it's for. Audit does NOT use .prod-owners either: frame 832:4431 puts
   four 300x190 tiles in one row with the wave behind them, where Collections and
   Callback run 778/522 twice on a radial glow. Both layouts stay — .prod-owners
   and .wtile are still those two pages' section.                             */
.prod-roles { position: relative; overflow: hidden; background: var(--c-primary-dark); }
.prod-roles .container { position: relative; }
/* stacked at every width, as section 6 above and Collections' section 8 */
.prod-roles__head { display: flex; flex-direction: column; gap: var(--space-4); }
.prod-roles__head h2 { max-width: none; }
.prod-roles__head p { font-size: var(--t-p1); }   /* P1, as the frame and the other section bodies */
.prod-tiles--roles { position: relative; }
/* The wave keeps its own width and is cropped by the section, rather than being
   squashed to fit: a 1467-wide wave compressed to a phone is a zigzag. Centred
   on the tile row, so it crosses the tiles wherever the row lands.           */
.prod-roles__wave {
    position: absolute; left: 50%; top: 50%; pointer-events: none;
    width: max(1606px, 112vw); max-width: none; height: 358px; transform: translate(-50%, -50%);
}
/* max-width: none, or base.css's img, svg { max-width: 100% } caps the wave at
   the row's width. And no z-index on it: the tiles are positioned and come
   later in the source, so they paint over it on their own. A negative z-index
   here escaped to the root — neither .prod-roles nor the row makes a stacking
   context — and the wave went behind the section's own background.           */

.role-tile {
    position: relative; isolation: isolate; flex: 0 0 auto; scroll-snap-align: start;
    width: min(300px, calc(100vw - var(--page-gutter) - var(--space-5) - 28px));
    min-height: 190px; padding: var(--space-6); overflow: hidden;
    display: flex; flex-direction: column; gap: var(--space-2);
    border-radius: 16px; border: 1px solid rgba(232, 182, 240, .45);
    background: rgba(255, 255, 255, .12);
    transition: background .35s ease, border-color .35s ease, transform .3s ease;
}
/* clamped, not the frame's flat 36: at 1024 the tile is about 204 wide and a
   flat 36 puts the longest name on three lines, past the 190                 */
.role-tile__name { font-size: clamp(26px, 1.6vw + 12px, 36px); line-height: 1.1; font-weight: var(--fw-regular); color: var(--c-accent-cyan); }
.role-tile__text { font-size: var(--t-p2); }
/* The frame draws the hairline at full #E8B6F0. At 45% instead: four tiles at
   full strength, plus the pink H2 accent and the wave's pink half, put the
   section at 43% pink pixels against 2% cyan, and the cyan names stopped
   leading. The hue and the outline both survive the reduction.               */
/* the lit state (822:4401): the fill carries it and the outline goes          */
.role-tile.is-current, .role-tile:hover { background: rgba(171, 235, 240, .2); border-color: transparent; }
@media (hover: hover) {
    .js .role-tile.is-visible:hover { transform: translateY(-4px); transition-duration: .3s; }
}
@media (hover: hover) and (max-width: 1023px) {
    .prod-tiles__row:hover .role-tile.is-current:not(:hover) { background: rgba(255, 255, 255, .12); border-color: rgba(232, 182, 240, .45); }
}

@media (max-width: 1023px) {
    .cq--table .cq__row { grid-template-columns: 1fr 3.5em 2.5em; }
    .cq--table .cq__action { grid-column: 1 / -1; color: rgba(255, 249, 245, .55); }
    .cq__row--head { display: none; }
}
@media (min-width: 1024px) {
    .prod-hero--audit .prod-hero__inner { flex-direction: row; align-items: center; gap: var(--space-10); }
    /* 720, not 668: at 668 the headline ran to six lines and hyphenated
       ninety-/seven; 720 is where it falls to the frame's four. Scoped to this
       page, so the other three product heroes keep 668.                      */
    .prod-hero--audit .prod-hero__copy { flex: 0 1 720px; max-width: 720px; }
    /* off the flow and onto the section's right edge. .hero already carries
       position: relative and overflow: hidden, so the bleed is clipped.       */
    .prod-hero--audit { flex-direction: row; --art-w: calc(100% - var(--page-gutter) - 720px); }
    .prod-hero--audit .prod-hero__art {
        position: absolute; inset: 0 0 0 auto; order: 0; z-index: 0;
        width: var(--art-w); margin: 0; border-radius: 0; box-shadow: none;
        /* the band crops the asset's own transparent left third away, which left a
           ruled vertical edge down the middle of the hero. The mask puts the
           dissolve back, and unlike the asset's alpha it holds at every band
           width — at 1024 the band is a quarter of what it is at 1440.        */
        -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 26%);
                mask-image: linear-gradient(90deg, transparent 0, #000 26%);
    }
    .prod-hero--audit .prod-hero__art img { width: 100%; height: 100%; object-fit: cover; object-position: 100% 38%; }
    .prod-hero--audit .prod-hero__inner { position: relative; z-index: 1; }
    /* the field goes back behind the copy, and the scrim dims it where the words are */
    .prod-cells { display: block; }
    .prod-cells__field { position: absolute; inset: 0; order: 0; justify-content: space-between; gap: 0; padding-block: var(--space-6); background: none; }
    .prod-cells::after { background: linear-gradient(90deg, rgba(0, 0, 0, .9) 0%, rgba(0, 0, 0, .72) 42%, rgba(0, 0, 0, .12) 100%); }
    .prod-cells__copy { padding-block: var(--space-16); }
    .prod-cells__copy h2 { max-width: 24ch; }   /* capped only where the field shows beside it */
    .prod-cells__cell { height: 46px; }
    /* the frame's single row, all the way down to 1024. 4x300 + 3x40 is 1320,
       which is the container at 1440 exactly; below that the tiles shrink
       rather than wrap. At 1024 each is about 204 wide and the names go to two
       lines, which reads tighter but keeps the composition. A 2x2 was tried
       here and is worse: at 506 wide the tile is a landscape box with a void
       in the middle, because the gap between numeral and name IS the design. */
    .prod-numbered .prod-tiles__row { gap: var(--space-10); }
    .ntile { flex: 1 1 0; width: auto; min-width: 0; }
    /* the frame: four across, 4x300 + 3x40 = 1320 at 1440. align-items: stretch
       because the base row is flex-end: the longest name wraps to a third line
       around 1024 and the other three then hang off its foot.                */
    .prod-roles .prod-tiles__row { gap: var(--space-10); align-items: stretch; }
    .role-tile { flex: 1 1 0; width: auto; min-width: 0; }
}

/* ── Fine print under an outcome section ──────────────────────────────
   Every reads section shows figures that look like real output, so each
   one carries one line saying they are examples and that accuracy on real
   calls follows the recording. Styled like the certifications fine print
   on Home: P3, muted, and dimmed again — fine print that shouts reads as
   a warning, fine print that sits still reads as candour.
   (RK, 2026-10-09; see V2-DESIGN-DEVIATIONS.)                          */
.prod-fine {
    margin-top: var(--space-8);
    max-width: var(--measure);
    font-size: var(--t-p3);
    line-height: var(--lh-body);
    color: var(--c-text-muted);
    opacity: .75;
}
