/* ============================================================================
   Landing page only (index.html). Everything shared with the other seven
   pages lives in site.css.
   ========================================================================= */

/* Decorative layers (the wash's blurred ::after, the mascot parked off-stage
   before placement) reach past the viewport on purpose; clip the page so none
   of them ever conjures a horizontal scrollbar. clip, not hidden: hidden
   would turn the page into a scroll container and break position: sticky.
   On the ROOT element, not body: Chromium does not propagate a body clip to
   the viewport, so on body it looked applied and clipped nothing. */
html { overflow-x: clip; }

/* ------------------------------------------------------------------- hero */

/* No overflow clip and no bottom rule: the gradient canvas deliberately runs
   past the hero's bottom edge and behind the statement below it. */
.hero {
    position: relative;
    height: 100vh;
    min-height: 700px;
}
.hero-bg { position: absolute; inset: 0; }

/* The hero ground is the paper itself. The violet wash that used to live
   here moved out on request: the colour in this hero now comes from the
   mascot's gradient and nothing else, so the lockup is the only saturated
   thing on the screen. The ag-drift keyframes survive below because the
   pricing band still drifts on them. */

@keyframes ag-drift-a {
    from { transform: translate3d(-3%, 0, 0) scale(1.02); }
    to   { transform: translate3d(3%, -3%, 0) scale(1.10); }
}
@keyframes ag-drift-b {
    from { transform: translate3d(4%, 2%, 0) scale(1.08) rotate(-2deg); }
    to   { transform: translate3d(-4%, -2%, 0) scale(1.0) rotate(2deg); }
}

/* The hero column: a small kicker, the agent's name at display scale, then the
   description and the CTAs — all stacked against the left gutter. Gaps are set
   per-element rather than with one flex `gap`, because the kicker belongs
   tight to the name while the paragraph needs air beneath it. */
.hero-foot {
    position: absolute;
    left: var(--gutter);
    right: var(--gutter);
    /* A touch below dead centre, which opens the gap under the corner labels
       without crowding the CTA against the bottom of the hero. */
    top: 54%;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

/* Aimee stands above the end of the wordmark and can be picked up and
   thrown. Absolutely positioned INSIDE the hero, which is already a
   positioning context: where she lands is her state, and she scrolls away
   with the hero rather than following the reader down the page. The walls
   she bounces off are the hero's box, for the same reason.

   Only this 72px body catches pointer events (the canvas below turns them
   off again), so her overflow margin never swallows a click meant for the
   page. */
.ag-hero-mascot {
    position: absolute;
    left: 0;
    top: 0;
    z-index: 140;
    /* One number sizes her. The canvas overscan and the JS collision radius
       are both derived from it, so a layout can make her bigger without any
       of the three drifting apart. */
    --ag-aimee: 72px;
    width: var(--ag-aimee);
    height: var(--ag-aimee);
    /* Laid out from the start and merely transparent, rather than display:
       none: the canvas has to have a real measured size when the renderer
       sizes its backing store, or it falls back to a guess. */
    opacity: 0;
    pointer-events: auto;
    cursor: grab;
    touch-action: none;
    will-change: transform;
    transition: opacity .5s ease;
}
.ag-hero-mascot.is-on { opacity: 1; }
.ag-hero-mascot.is-held { cursor: grabbing; }
.ag-hero-mascot svg,
.ag-hero-mascot canvas {
    width: 100%;
    height: 100%;
    display: block;
    overflow: visible;
    /* The idle float lives on the canvas because JS rewrites the wrapper's
       transform every frame to place her; on the same element the bob would
       be overwritten before it ever painted. */
    animation: acm-float 3.4s ease-in-out infinite;
}
@keyframes acm-float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-4px); }
}
/* The 3D canvas deliberately overflows the 72px body box: a press squishes
   her up to 1.4x on one axis and travelling drags a tail out behind her, and
   without this margin either would clip at the canvas edge. The shader's
   orthographic span is widened by exactly the same ratio, so her resting size
   is unchanged. The size is spelled out rather than left to inset + auto: a
   canvas is a replaced element, so auto resolves to its backing-store width
   and the insets are quietly ignored, which once put her 35px off her own
   position. */
.ag-hero-mascot canvas {
    position: absolute;
    left: calc(var(--ag-aimee) * -0.29167);
    top: calc(var(--ag-aimee) * -0.29167);
    width: calc(var(--ag-aimee) * 1.58333);
    height: calc(var(--ag-aimee) * 1.58333);
    /* The margin is for her bulges, not for hit-testing: grabbing happens on
       the 72px body above. */
    pointer-events: none;
}
/* Her own clock, independent of the pointer: a double-blink every few
   seconds, scaled around each bar's own centre. */
.ag-hero-mascot .acm-blink {
    transform-box: fill-box;
    transform-origin: 50% 50%;
    animation: acm-blink 4.6s ease-in-out infinite;
}
@keyframes acm-blink {
    0%, 6%, 12%, 100% { transform: scaleY(1); }
    3%, 9%            { transform: scaleY(0.08); }
}
@media (prefers-reduced-motion: reduce) {
    .ag-hero-mascot .acm-blink,
    .ag-hero-mascot svg,
    .ag-hero-mascot canvas { animation: none; }
}

/* --- the opening (hero-intro.js) ---
   A false-colour field over the whole hero on which ink dots gather into
   Aimee; it cools to transparent and reveals the paper and the violet ink.
   Sits after the ink canvas and before the copy, so the DOM word paints on
   top of it the way the wordmark does in the reference film. */
.ag-intro-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}
/* Nothing but the field while the opening plays: the nav is held back and
   fades in with the paper. */
body.ag-intro-live #nav { opacity: 0; pointer-events: none; }
#nav { transition: opacity .6s ease; }
/* The word waits, then fades in beside the formed mark (2.2s). Once the
   hand-off fires, ag-word-distort hides the DOM copy as usual. */
body.ag-intro .hero-word-type { opacity: 0; }
body.ag-intro.ag-intro-word .hero-word-type { opacity: 1; transition: opacity .55s ease; }
body.ag-intro .hero-word.is-typed .hero-mascot { opacity: 0; }

@media (prefers-reduced-motion: reduce) { .ag-intro-canvas { display: none; } }

/* --- minimal hero (ag-hero-min on <body>) ---
   For now the hero is ONLY the wordmark, centred on the paper with the ink:
   no mascot, no lede, no CTAs, no corner labels, no scroll cue. The nav is
   held off-screen too and drops in once the visitor has scrolled (site.js
   clears nav-held past half a viewport). Everything is hidden by mode class
   rather than removed, so switching back is one attribute. */
/* The inline SVG mascot slot stays off for good: the throwable 3D Aimee
   (hero-distort-init) holds that place in the lockup now. */
.hero-word .hero-mascot { display: none; }
.hero-word.is-typing,
.hero-word.is-typed { transform: none; }
body.ag-hero-min .hero-lede,
body.ag-hero-min .hero-actions,
body.ag-hero-min .hero-note,
body.ag-hero-min .hero-labels,
body.ag-hero-min .hero-scroll { display: none; }
/* Without the mascot there is no reserved slot to compensate for, so the
   centre-then-slide shift must not run: it would park the word off-axis. */
body.ag-hero-min .hero-word.is-typing,
body.ag-hero-min .hero-word.is-typed { transform: none; }
/* The word alone sits dead centre rather than a touch below it. */
body.ag-hero-min .hero-foot { top: 50%; }

/* The name IS the logo: mascot first, then AGENTIDOO in caps — the same
   lockup as the brand mark, just at display scale. Darker Grotesque SemiBold,
   self-hosted; falls back to the site face if the woff2 is pulled. */
.hero-word {
    /* Positioned so it is ALWAYS the containing block for the distortion
       canvas inside it. Without this the canvas anchors to .hero-foot most of
       the time but to .hero-word while the typing transform is live, and the
       coordinates set during one regime mean something else under the other:
       the word ends up drawn a mascot's width off to the left. */
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.05em;
    margin: 0;
    font-family: 'Darker Grotesque', 'Archivo', system-ui, sans-serif;
    font-size: clamp(48px, 10.4vw, 175px);
    font-weight: 600;
    letter-spacing: 0.005em;
    line-height: 1;
    text-transform: uppercase;
    color: var(--ink);
}
/* The typed span: fixing the line box's height keeps the row from collapsing
   in the beat before the first letter lands. */
.hero-word-type { display: inline-block; min-height: 1em; white-space: nowrap; }

/* The shader's copy of the wordmark. It sits exactly over the DOM text with
   a margin of slack for displaced pixels, and only takes over once the name is
   written: until then the DOM text is the visible one, so a missing WebGL
   context or a blocked module simply leaves the page as it already was. */
.hero-word-canvas {
    position: absolute;
    display: none;
    pointer-events: none;
}
/* Two gates: the fluid background shows from the moment the sim runs
   (ag-fluid-bg), while the canvas only takes over the WORD once typing has
   finished (ag-word-distort, via the shader's own show-word switch). */
body.ag-fluid-bg .hero-word-canvas,
body.ag-word-distort .hero-word-canvas { display: block; }
/* Hidden, not removed: it stays the thing that defines the row's width, the
   accessible text, and the box the canvas measures itself against. */
body.ag-word-distort .hero-word-type { visibility: hidden; }

/* The mascot leads the lockup at cap height, exactly as in the logo. Sized in
   `em`, so it tracks the display size at every breakpoint. Its slot is laid
   out from the start, it only becomes visible when it arrives, so the word
   never shifts sideways when it appears. */
.hero-mascot {
    flex: 0 0 auto;
    cursor: pointer;
    width: 1.42em;
    /* The glass svg is a square box with the blob at ~55% of it, and the blob
       does not sit centred inside that box. The negative margins pull the
       padding back in on all four sides, so the row's height is driven by the
       text rather than by the oversized canvas.

       Top and bottom are deliberately lopsided by 0.162em: `align-items:
       center` centres the BOX, which left the blob riding 0.16em above the
       caps. Shifting the box down inside its own margin box (the two values
       still sum to -0.6em, so the row height is untouched) puts the blob's
       centre on the cap band's centre, which is how the mascot sits in the
       brand logo artwork: measured off it at 0.004 cap-heights from dead
       centre, so this reproduces the lockup rather than approximating it. */
    margin: -0.118em -0.26em -0.482em -0.28em;
    line-height: 0;
}

/* Poke her and she hops. The jump lives on the <svg> because the wrapper is
   already carrying the entrance animation and the inner group is carrying the
   idle float — three separate elements, three separate animations, no
   clobbering. site.js drops the class on animationend so it can fire again on
   the next click. */
.hero-mascot .mascot-glass { transform-origin: 50% 92%; }
.hero-mascot.is-jumping .mascot-glass {
    /* `linear` on purpose: every segment below carries its own easing. One
       global curve was what made this read as a jolt, because it eased the
       fall the same way it eased the rise, so she decelerated into the
       ground instead of accelerating into it. */
    animation: ag-mascot-jump 1.05s linear;
}
@keyframes ag-mascot-jump {
    /* Anticipation: a slow crouch, easing IN so the weight gathers. */
    0%   { transform: translateY(0) scale(1, 1);
           animation-timing-function: cubic-bezier(0.36, 0, 0.66, 0.5); }
    16%  { transform: translateY(3.5%) scale(1.07, 0.93);
           animation-timing-function: cubic-bezier(0.12, 0.7, 0.4, 1); }
    /* Push-off: fastest part of the whole move, stretching as she leaves. */
    30%  { transform: translateY(-15%) scale(0.94, 1.07);
           animation-timing-function: cubic-bezier(0.25, 0.5, 0.35, 1); }
    /* Apex: nearly still, shape back to normal. The long, flat top is what
       makes a jump feel weightless rather than twitchy. */
    46%  { transform: translateY(-30%) scale(0.99, 1.01);
           animation-timing-function: cubic-bezier(0.5, 0, 0.9, 0.45); }
    /* Fall: eases IN, so she picks up speed on the way down. */
    68%  { transform: translateY(-13%) scale(1, 1);
           animation-timing-function: cubic-bezier(0.5, 0, 0.85, 0.6); }
    /* Landing squash, then two decaying settles instead of one hard stop. */
    80%  { transform: translateY(0) scale(1.06, 0.94);
           animation-timing-function: cubic-bezier(0.2, 0.8, 0.4, 1); }
    88%  { transform: translateY(-4%) scale(0.985, 1.015);
           animation-timing-function: cubic-bezier(0.45, 0, 0.55, 1); }
    95%  { transform: translateY(0) scale(1.015, 0.985);
           animation-timing-function: cubic-bezier(0.3, 0.7, 0.4, 1); }
    100% { transform: translateY(0) scale(1, 1); }
}
@media (prefers-reduced-motion: reduce) {
    .hero-mascot.is-jumping .mascot-glass { animation: none; }
}
.hero-mascot img,
.hero-mascot .mascot-glass { display: block; width: 100%; height: auto; }

/* --- the typed reveal ---
   site.js adds .is-typing at once (so no-JS and reduced-motion keep the full
   lockup with zero flash), empties the span, types the name and then swaps
   .is-typing for .is-typed, which pops the mascot in. */
/* site.js ramps the lockup's opacity from near-nothing to full across the
   keystrokes, so the name fades up as it is written. The opacity transition
   smooths the steps between one letter and the next; the transform one is
   what slides the word aside when the mascot takes her slot. */
.hero-word.is-typing,
.hero-word.is-typed {
    transition: opacity 0.28s linear,
                transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}

/* The mascot's slot is reserved in the flex row from the start, which parks
   the word half a slot right of centre. While it is empty, pull the whole row
   back by that half so the NAME is what reads centred; dropping the shift on
   .is-typed slides the word right into the finished lockup, exactly as she
   walks in. 0.465em = half of (1.42em box - 0.54em negative margins + 0.05em
   gap), so it tracks the display size. */
.hero-word.is-typing { transform: translateX(-0.465em); }
.hero-word.is-typed { transform: none; }

.hero-word.is-typing .hero-word-type::after {
    content: '';
    display: inline-block;
    width: 0.05em;
    height: 0.62em;
    margin-left: 0.06em;
    background: var(--ink);
    animation: ag-caret 1.1s steps(2, jump-none) infinite;
}
@keyframes ag-caret { 0% { opacity: 1; } 100% { opacity: 0; } }
/* The mascot waits offstage to the left of the lockup and walks in once the
   name is finished. Its slot is laid out from the start, so the word never
   shifts sideways when it arrives. */
/* She rolls in from the left of the lockup once the name is written: tipped
   over at the start and turning upright as she travels, landing at rest just
   as she reaches her slot. The rotation resolves a beat before the slide does,
   so the last of the movement is a settle rather than a spin. */
.hero-word.is-typing .hero-mascot {
    opacity: 0;
    transform: translateX(-1.4em) rotate(-115deg);
}
.hero-word.is-typed .hero-mascot {
    animation: ag-mascot-in 1.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes ag-mascot-in {
    from { opacity: 0; transform: translateX(-1.4em) rotate(-115deg); }
    55%  { opacity: 1; }
    82%  { transform: translateX(-0.1em) rotate(-4deg); }
    to   { opacity: 1; transform: none; }
}

/* --- the staggered rise ---
   site.js adds .is-staged to the hero synchronously (so no-JS and
   reduced-motion never see a hidden hero), then lifts each row in turn once
   the lockup is assembled: lede, CTAs, fine print, corner labels, scroll cue.
   Only `opacity` and `transform` animate, so every step stays on the
   compositor.

   This block was lost once already, taken out with the metaball CSS around
   it, and nothing failed loudly: the classes still went on, they just styled
   nothing, so the whole hero simply appeared at once. If the rise ever stops
   working again, check that this rule still exists before looking at the JS. */
.hero.is-staged .ag-rise {
    opacity: 0;
    transform: translateY(20px);
}
.hero .ag-rise.is-in {
    opacity: 1;
    transform: none;
    transition: opacity 0.5s ease, transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

.hero-lede {
    margin-top: clamp(24px, 3vw, 48px);
    margin-inline: auto;
    max-width: 46ch;
    font-size: clamp(16px, 1.3vw, 19px);
    line-height: 1.5;
    color: var(--ink);
}

.hero-actions {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 32px;
}
.hero-note { margin-top: 16px; font-size: 12.5px; color: var(--ink); }

/* Paired micro-labels across the top of the hero, above the wave band. */
.hero-labels {
    position: absolute;
    left: var(--gutter);
    right: var(--gutter);
    top: calc(var(--nav-h) + 28px);
}

/* Scroll cue, bottom-right, clear of the centred headline column. */
.hero-scroll {
    position: absolute;
    right: var(--gutter);
    bottom: 9vh;
    text-decoration: none;
}

/* -------------------------------------------------------------- statement */

/* position+z-index so this paints ABOVE the hero canvas overlapping it — a
   later sibling in normal flow otherwise renders beneath a positioned one,
   and the gradient would cover the copy. */
.statement {
    position: relative;
    z-index: 1;
    padding: 140px var(--gutter) 150px;
}
/* The showcase runs this at display scale — the paragraph IS the section, so
   it is sized like a headline rather than like body copy. */
.statement p {
    max-width: 1320px;
    font-size: clamp(28px, 4.1vw, 70px);
    font-weight: 400;
    letter-spacing: -0.04em;
    line-height: 1.06;
    text-wrap: pretty;
}
/* The statement types itself in when it scrolls up (site.js). Characters are
   only made transparent, never removed, so the paragraph keeps its finished
   line breaks and nothing reflows while it fills. The caret is absolutely
   positioned for the same reason: an inline one would widen its line. */
.statement p.is-typing .ag-ch { opacity: 0; }
.statement p.is-typing .ag-ch.is-on { opacity: 1; }
.statement p .ag-ch { position: relative; }
.statement p.is-typing .ag-ch.has-caret::after {
    content: '';
    position: absolute;
    left: 100%;
    bottom: 0.1em;
    width: 0.05em;
    height: 0.62em;
    margin-left: 0.06em;
    background: currentColor;
    animation: ag-caret 1.1s steps(2, jump-none) infinite;
}
/* The frosted panels wait for the typing to reach them, so the section does
   not sit there showing two empty dark boxes. */
.statement p.is-typing .mark {
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}
.statement p.is-typing .mark.is-on {
    background: rgba(18, 16, 22, .82);
    backdrop-filter: blur(14px) saturate(1.6);
    -webkit-backdrop-filter: blur(14px) saturate(1.6);
}

/* Frosted violet behind the two pulled-out words rather than a solid fill, so
   the hero gradient bleeding down into this section shows through them. The
   tint has to stay opaque enough to hold white text — below about .5 alpha the
   words start disappearing into the pale parts of the gradient. */
.mark {
    background: rgba(18, 16, 22, .82);
    backdrop-filter: blur(14px) saturate(1.6);
    -webkit-backdrop-filter: blur(14px) saturate(1.6);
    color: #fff;
    padding: 0 .18em;
}

/* ----------------------------------------------------------- bleed panels */

/* The layout language for #demo and #features, after Motto's Parasail case
   study: no cards, no page gutter. Each block is a full-bleed field of flat
   colour with the artwork floating centred inside it, and 2-up rows meet on a
   hard edge with no gap so the two colours abut directly.

   --bleed is the thin breathing margin Motto keeps at the viewport edge; it is
   NOT the section gutter, which these blocks deliberately ignore. */
.demo, #features {
    --bleed: 12px;
    --panel-pad: clamp(24px, 2.6vw, 44px);
}

.bleed-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 24px;
    flex-wrap: wrap;
    padding: 96px var(--gutter) 40px;
}
/* The features head stacks instead: eyebrow, then the headline and its lede
   side by side underneath. */
.bleed-head--stack { display: block; }
.bleed-head--stack h2 {
    margin-top: 28px;
    max-width: 15ch;
    font-size: clamp(34px, 5vw, 76px);
    letter-spacing: -0.035em;
    line-height: 1;
}
.bleed-head--stack p {
    margin-top: 20px;
    max-width: 46ch;
    font-size: 17px;
    line-height: 1.55;
    color: var(--ink-2);
}

.demo-status { display: inline-flex; align-items: center; gap: 10px; font-size: 14px; color: var(--ink-3); }
.demo-live { display: inline-flex; align-items: center; gap: 6px; color: var(--ok); font-weight: 500; }
.demo-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ok); }

/* Two fields touching. Zero gap is the point — a gutter here turns the pair
   back into cards. */
.split {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0;
    margin: 0 var(--bleed) var(--bleed);
}
/* Puts the media field on the right without reordering the DOM, so the copy
   still follows its own clip for a screen reader. */
.split--rev > :first-child { order: 2; }

.panel {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: stretch;
    margin: 0;
    padding: var(--panel-pad);
    overflow: hidden;
}
/* Only the copy half needs a floor — without one it would collapse shorter
   than the clip beside it and the row would lose its edge. */
.panel--copy { min-height: clamp(300px, 34vw, 520px); }
.panel--wide { margin: 0 var(--bleed) var(--bleed); }
/* Every field is white. The tinted rotation (violet / bone / ink) left a wide
   margin of flat colour around each screenshot, and on the dark fields the
   clips — which carry their own pale wash — read as bright rectangles pasted
   on black. White lets the artwork's own background run into the page. */
.panel { background: var(--paper-pure); }

.panel > img,
.panel > video {
    display: block;
    width: 100%;
    margin: 0;
    border-radius: 6px;
}

/* Motto's micro-label. In flow above the artwork rather than absolutely
   pinned: pinned, it sat underneath the media on any panel whose artwork is
   wider than the padding inset — which is every wide panel. */
.panel-tag {
    align-self: flex-start;
    margin-bottom: 24px;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-3);
}

/* The four stills carry their point in the caption, so it is set as display
   type on the same scale as a #features row headline rather than as grey
   supporting text — otherwise the demo section reads as four unlabelled
   screenshots with footnotes. */
.panel figcaption {
    margin-top: 28px;
    max-width: 20ch;
    font-size: clamp(21px, 1.8vw, 30px);
    font-weight: 400;
    letter-spacing: -0.025em;
    line-height: 1.12;
    color: var(--ink);
}

/* The copy half of a #features row. */
.panel--copy { justify-content: center; padding: var(--panel-pad); }
.panel--copy h3 {
    max-width: 16ch;
    font-size: clamp(26px, 2.9vw, 46px);
    letter-spacing: -0.03em;
    line-height: 1.05;
}
.panel--copy p {
    margin-top: 20px;
    max-width: 42ch;
    font-size: 16.5px;
    line-height: 1.6;
    color: var(--ink-2);
}

/* Hover: the artwork itself lifts inside its field. The field never moves, so
   nothing reflows and the hard edges between panels stay put. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
    .panel > img,
    .panel > video {
        transition: transform .4s cubic-bezier(.2,.7,.3,1);
        will-change: transform;
    }
    .panel:hover > img,
    .panel:hover > video { transform: translateY(-8px) scale(1.012); }
}

/* ---------------------------------------------------------------- collage */

/* The Odoo-module collage: official module icons scattered around the centred
   copy, each drifting vertically at its own pace as the page scrolls. The
   drift itself is written by site.js into --shift; everything here is static
   placement, so the layout is honest with JS disabled — tiles simply hold
   their resting spots. */
.modules-collage {
    position: relative;
    padding: 40px 0;
    overflow: hidden;
}
.collage-stage {
    position: relative;
    height: clamp(680px, 100vh, 940px);
}

/* The tiles drift past the section's edges as you scroll. Masked rather than
   clipped, so they dissolve into the page instead of being sliced off by the
   overflow. The copy is deliberately OUTSIDE this layer — a mask on the whole
   stage would fade the headline too. */
.collage-field {
    position: absolute;
    inset: 0;
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 9%, #000 91%, transparent 100%);
    mask-image: linear-gradient(180deg, transparent 0%, #000 9%, #000 91%, transparent 100%);
}

.collage-copy {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    /* No horizontal padding: the box is centred and the nowrap headline sets
       its width, so a gutter here just inflates the box ~170px past the text
       and pushes the surrounding tiles further out than they look. */
    text-align: center;
}
/* One line. nowrap plus a vw-scaled size rather than a max-width: at 3.4vw
   the string is about 0.48em x 33 characters, so it clears the gutters at
   every desktop width and never breaks to two. Mobile releases the nowrap. */
.collage-copy h2 {
    white-space: nowrap;
    font-size: clamp(26px, 3.4vw, 54px);
    letter-spacing: -0.03em;
    line-height: 1.02;
}
.collage-copy p {
    margin: 16px auto 0;
    max-width: 560px;
    font-size: 16px;
    line-height: 1.6;
    color: var(--ink-2);
}

/* Placement from per-tile custom properties; the scroll drift rides in
   --shift so it composes with the centring translate instead of replacing
   it (the transform-vs-rotate lesson from the orbit, same trap). */
.collage-item {
    position: absolute;
    left: calc(var(--x) * 1%);
    top: calc(var(--y) * 1%);
    width: calc(var(--s) * 1px);
    height: calc(var(--s) * 1px);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 22%;
    background: var(--paper-pure);
    box-shadow: 0 10px 30px rgba(18, 16, 22, .10);
    transform: translate(-50%, -50%) translateY(var(--shift, 0px));
    will-change: transform;
    /* Reveal state, driven by .is-visible on the section. */
    opacity: 0;
    scale: .8;
    transition: opacity .5s ease, scale .5s cubic-bezier(.2,.7,.3,1);
    transition-delay: var(--delay, 0s);
}
.modules-collage.is-visible .collage-item { opacity: 1; scale: 1; }
.collage-item img {
    width: 62%;
    height: 62%;
    display: block;
    pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
    .collage-item { transform: translate(-50%, -50%); transition: none; opacity: 1; scale: 1; }
}

@media (max-width: 860px) {
    .collage-stage { height: 660px; }
    /* No room for one line at this width, and the vw-scaled size bottoms out
       at its 26px floor on a phone — set the mobile sizes directly and let the
       box run wider. */
    .collage-copy { padding: 0 18px; width: 100%; }
    .collage-copy h2 { white-space: normal; font-size: 34px; line-height: 1.06; }
    /* Full box width: at 34ch this wrapped to four lines inside a 354px box,
       making the copy six lines tall and forcing the tile bands out to the
       section edges. Three lines buys back ~28px on each side. */
    .collage-copy p { margin-top: 14px; max-width: none; font-size: 16px; }
    /* Smaller tiles so eighteen of them breathe at 390px; --s is a plain
       number, so scaling stays one multiplication. --ym repacks each tile
       into a band above or below the copy, which spans nearly the whole
       width here — the desktop clear-window around the centre is gone. */
    .collage-item {
        top: calc(var(--ym, var(--y)) * 1%);
        width: calc(var(--s) * 0.52px);
        height: calc(var(--s) * 0.52px);
    }
}

}

/* -------------------------------------------------------------- how it works */

.how-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 40px;
    margin-top: 56px;
    flex-wrap: wrap;
}
.how-head h2 { font-size: clamp(32px, 3.6vw, 56px); letter-spacing: -0.03em; line-height: 1; }
.how-head p { max-width: 360px; font-size: 17px; line-height: 1.55; color: var(--ink-2); }
.how-steps { margin-top: 72px; }
.how-steps .num { font-size: 14px; font-weight: 600; color: var(--accent); letter-spacing: 0.1em; }
.how-steps h3 { margin-top: 20px; font-size: clamp(28px, 2.6vw, 44px); letter-spacing: -0.02em; }
.how-steps p { margin-top: 16px; font-size: 16px; line-height: 1.55; color: var(--ink-2); }

/* The pricing band bleeds its background upward, so the default 96px of
   section padding put the abo cards almost straight under the last step.
   This is the breathing room between the two. */
#how { padding-bottom: 200px; }

/* ---------------------------------------------------------------- pricing */

/* Light, like every other section. It used to be a dark violet band with white
   copy; the gradient behind it now carries the section, so the type is ink and
   the cards are frosted the same way the header is. */
.pricing {
    position: relative;
    padding: 120px var(--gutter);
}

/* Bleeds past the section top and bottom so the colour runs under the
   neighbouring sections instead of stopping on their edges, and fades out at
   both ends. Every .section is lifted into the positioned layer (site.css) so
   their copy still paints above this. */
.pricing-bg {
    position: absolute;
    inset: -16% 0;
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 14%, #000 86%, transparent 100%);
    mask-image: linear-gradient(180deg, transparent 0%, #000 14%, #000 86%, transparent 100%);
}
/* The hero's living ink, brought behind the pricing band. It inherits the
   mask above, so it fades out at both ends exactly like the wash it replaces.
   Held back to a tint: this one sits behind three cards of body copy, where
   the hero's version has nothing to compete with. */
.pricing-fluid {
    position: absolute;
    left: 0;
    top: 0;
    display: none;
    opacity: .72;
}
body.ag-pricing-fluid .pricing-fluid { display: block; }
body.ag-pricing-fluid .pricing-wash { display: none; }

/* The pricing band's colour, same construction as the hero wash but calmer:
   this one sits behind three cards of body copy, so it stays a tint rather
   than a field. Two layers is enough at this scale. */
.pricing-wash {
    position: absolute;
    inset: 0;
    pointer-events: none;
    filter: blur(46px) saturate(1.3);
    background:
        radial-gradient(40% 60% at 20% 40%, rgba(113, 99, 158, .62) 0%, rgba(113, 99, 158, 0) 70%),
        radial-gradient(44% 58% at 74% 60%, rgba(128, 116, 173, .56) 0%, rgba(128, 116, 173, 0) 72%),
        radial-gradient(30% 44% at 52% 30%, rgba(248, 246, 252, .85) 0%, rgba(248, 246, 252, 0) 74%);
    animation: ag-drift-a 30s ease-in-out infinite alternate;
}
.pricing-wash::after {
    content: '';
    position: absolute;
    inset: -12%;
    background:
        radial-gradient(34% 48% at 62% 24%, rgba(93, 81, 132, .48) 0%, rgba(93, 81, 132, 0) 74%),
        radial-gradient(30% 42% at 30% 78%, rgba(163, 150, 214, .44) 0%, rgba(163, 150, 214, 0) 76%);
    animation: ag-drift-b 38s ease-in-out infinite alternate;
}
@media (prefers-reduced-motion: reduce) {
    .pricing-wash, .pricing-wash::after { animation: none; }
}

.pricing-head {
    position: relative;
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 40px;
    padding-bottom: 64px;
    flex-wrap: wrap;
}
.pricing-head h2 { margin-top: 40px; font-size: clamp(32px, 3.6vw, 56px); letter-spacing: -0.03em; line-height: 1; }
.pricing-head p { max-width: 380px; font-size: 16px; line-height: 1.6; color: var(--ink-2); }

.pricing-cards { position: relative; display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; }

/* Frosted, borderless — the gradient behind shows through. */
.plan {
    position: relative;
    border-radius: var(--r-card);
    padding: 40px 36px 44px;
    background: rgba(255,255,255,.46);
    backdrop-filter: blur(20px) saturate(1.7);
    -webkit-backdrop-filter: blur(20px) saturate(1.7);
    box-shadow: 0 14px 40px rgba(18,16,22,.10);
    display: flex;
    flex-direction: column;
}
.plan--featured { background: rgba(255,255,255,.66); }
.plan-inner { display: flex; flex-direction: column; flex: 1; }
.plan-top { display: flex; justify-content: space-between; align-items: center; }
.plan-name { font-size: 14px; font-weight: 600; letter-spacing: 0.1em; }
.plan-tag { font-size: 12px; font-weight: 600; background: var(--ink); color: #fff; padding: 4px 12px; border-radius: var(--r-pill); }
.plan-tag--outline { background: none; border: 1px solid var(--ink); color: var(--ink); }
.plan-blurb { margin-top: 14px; font-size: 13.5px; line-height: 1.5; color: var(--ink-3); }
.plan-price { margin-top: 24px; font-size: 52px; font-weight: 500; letter-spacing: -0.03em; }
.plan-price small { font-size: 16px; font-weight: 400; letter-spacing: 0; }
.plan-credits { margin-top: 6px; font-size: 14px; font-weight: 600; }
.plan-meta { margin-top: 4px; font-size: 12.5px; color: var(--ink-3); }
.plan ul { margin: 24px 0 28px; padding: 0; list-style: none; font-size: 14.5px; line-height: 2.1; color: var(--ink-2); }
.plan li.off { color: var(--ink-3); }
.plan .btn { margin-top: auto; align-self: flex-start; padding: 12px 28px; font-size: 15px; }

.pricing-notes { position: relative; display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin-top: 48px; }
.pricing-note {
    background: rgba(255,255,255,.42);
    backdrop-filter: blur(20px) saturate(1.7);
    -webkit-backdrop-filter: blur(20px) saturate(1.7);
    border-radius: var(--r-frame);
    padding: 24px;
}
.pricing-note b { display: block; font-size: 15px; font-weight: 600; }
.pricing-note p { margin-top: 10px; font-size: 14px; line-height: 1.6; color: var(--ink-2); }
.pricing-fine { position: relative; margin-top: 40px; text-align: center; font-size: 13px; color: var(--ink-3); }

/* --------------------------------------------------------------- responsive */

@media (max-width: 1080px) {
    .pricing-cards, .pricing-notes { grid-template-columns: 1fr; }
}

@media (max-width: 860px) {
    #how { padding-bottom: 130px; }

    /* Splits stack. The order swap is unset too, or the reversed rows would
       put the copy above its own clip on half the page. */
    .split { grid-template-columns: 1fr; }
    .split--rev > :first-child { order: 0; }
    .bleed-head { padding: 64px var(--gutter) 24px; }
    .panel { min-height: 0; padding: 30px 22px; }
    /* The tag would sit on top of the artwork in a short panel, so it takes a
       row of its own rather than being pinned. */
    .panel-tag { margin-bottom: 18px; }
    /* 16:9 at 342px wide is a 192px strip and the composer inside it becomes
       unreadable. Taller crop, anchored on the middle of the frame where the
       conversation is. */
    .panel--media video { aspect-ratio: 4 / 3; object-fit: cover; object-position: center; }
    .panel figcaption { margin-top: 18px; }
    .panel--copy { padding: 34px 22px 44px; }

    /* The hero is content-height on a phone, so .hero-bg has to stay in flow
       for its children to give it that height. The gradient is therefore
       absolute against .hero and fills it, with the copy sitting on top —
       rather than the old layout, which put the gradient in a 200px band
       ABOVE the text instead of behind it. */
    .hero { height: auto; min-height: 0; padding: calc(var(--nav-h) + 28px) 0 64px; }
    .hero-bg { position: static; }
    /* The same band as on desktop, but the phone hero is a shorter box, so it
       needs proportionally more of it to still read as colour behind the
       lockup rather than a stripe. */
    /* Into the positioned layer so they paint above the absolute canvas;
       they are later in DOM order, so no z-index arms race. */
    .hero-labels, .hero-foot { position: relative; z-index: 1; }
    .hero-foot { top: auto; left: auto; right: auto; transform: none; padding: 0 var(--gutter); }
    /* Side by side the two labels do not fit 390px — the right-hand one wraps
       to three lines and runs into the gutter. Stacked and left-aligned. */
    .hero-labels {
        top: auto;
        left: auto;
        right: auto;
        flex-direction: column;
        align-items: flex-start;
        margin: 0 0 28px;
        padding: 0 var(--gutter);
        gap: 6px;
        font-size: 10.5px;
    }
    .hero-labels > :last-child { text-align: left; }
    /* Full-width CTAs read as one clear stack rather than two ragged pills. */
    /* Bigger and lifted clear of the word on a phone, where the display type
       is clamped to its floor and the mascot would otherwise crowd the "e". */
    .hero-word { font-size: clamp(38px, 9.5vw, 175px); }
    .hero-actions { align-self: stretch; }
    .hero-actions .btn { flex: 1 1 100%; justify-content: center; }
    /* The scroll cue is a desktop affordance — on a phone the next section is
       already a thumb-flick away, and it would collide with the CTA stack. */
    .hero-scroll { display: none; }
    .statement { padding: 72px var(--gutter); }
    .pricing { padding: 72px var(--gutter); }
    /* Reaches further past the section on a phone, where the stacked cards
       make it tall and a 16% bleed barely shows. Kept to 0 horizontally —
       widening it past the viewport would reintroduce a horizontal scroll,
       since this section no longer clips its overflow. */
    .pricing-bg {
        inset: -26% 0;
        -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 10%, #000 90%, transparent 100%);
        mask-image: linear-gradient(180deg, transparent 0%, #000 10%, #000 90%, transparent 100%);
    }
}

/* ============================================================================
   Below the hero: the page after cohere.com/de (2026-09), section for
   section, in Agentidoo's palette. Measured from the reference at 1440:
   40px gutters, 1360px inner width, sections 80px / 144px deep, one weight
   (400) for every heading, tight tracking, 16px/1.4 body, pill buttons
   53px tall, tiles at 12px radius, cards at 22px. The hero above stays
   ours. The old below-hero blocks further up in this file are superseded
   by this block and no longer referenced from index.html.
   ========================================================================= */

:root {
    --c-ink: #17171C;
    --c-text: #212121;
    --c-muted: #6B6B70;
    --c-rule: #E5E5E8;
    --c-card: #F4F2F8;          /* the reference's warm off-white, tinted our way */
    --c-dark: #1B1B1B;
    --c-white: #ffffff;
}

/* --- type ---------------------------------------------------------------- */
.c-h2 { font-size: 48px; font-weight: 400; letter-spacing: -0.01em; line-height: 1.2; color: var(--c-text); }
.c-h2--sm { font-size: 32px; letter-spacing: -0.01em; line-height: 1.2; }
.c-h3 { font-size: 24px; font-weight: 400; letter-spacing: -0.005em; line-height: 1.3; color: var(--c-text); }
.c-p  { font-size: 16px; line-height: 1.4; color: var(--c-text); }
.c-p--lead { font-size: 18px; line-height: 1.45; }
.c-eyebrow { font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--c-muted); }
.c-link { display: inline-flex; align-items: center; gap: 8px; font-size: 16px; color: var(--c-text); text-decoration: none; padding: 8px 0; }
.c-link:hover { text-decoration: underline; text-underline-offset: 4px; }
.c-link .arr { transition: transform .2s ease; }
.c-link:hover .arr { transform: translateX(3px); }

/* --- buttons ------------------------------------------------------------- */
.c-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    padding: 12px 24px; border-radius: 9999px; border: 2px solid transparent;
    background: var(--c-ink); color: #fff; font-size: 16px; line-height: 24px; font-weight: 400;
    text-decoration: none; transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.c-btn:hover { background: #2E2E35; }
.c-btn--light { background: #fff; color: var(--c-ink); }
.c-btn--light:hover { background: #ECEAF3; }
/* The popular plan's CTA carries the brand gradient rather than the plain
   white fill the other two use, so the recommended tier is the only
   saturated thing in the band. Hover slides the same gradient. */
.c-plan--hot .c-btn--light {
    background-image: var(--ag-grad); background-color: transparent; color: #fff;
    background-size: 190% 190%; background-position: 0% 0%;
    transition: background-position .55s cubic-bezier(.32,.72,0,1), box-shadow .35s ease;
}
.c-plan--hot .c-btn--light:hover {
    background-image: var(--ag-grad); background-color: transparent; color: #fff;
    background-position: 100% 100%;
    box-shadow: 0 14px 30px -14px rgba(139,93,193,.6);
}
.c-btn--ghost { background: transparent; color: inherit; border-color: transparent; padding-left: 0; padding-right: 0; }
.c-btn--ghost:hover { background: transparent; text-decoration: underline; text-underline-offset: 4px; }

/* --- layout -------------------------------------------------------------- */
.c-section { position: relative; z-index: 1; padding: 80px var(--gutter); }
.c-section--tight { padding-top: 40px; padding-bottom: 40px; }
.c-section--deep  { padding-bottom: 144px; }
.c-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 40px; margin-bottom: 40px; }
.c-head .c-h2 { max-width: 560px; }

/* --- media pair: one wide tile, one tall, 899:441 at 560 high ------------- */
.c-media { padding-top: 0; }
.c-media-grid { display: grid; grid-template-columns: 899fr 441fr; gap: 24px; }
.c-tile { position: relative; overflow: hidden; border-radius: 12px; background: var(--c-card); }
.c-tile--wide { aspect-ratio: 899 / 560; }
.c-tile--tall { aspect-ratio: 441 / 560; }
.c-tile > video, .c-tile > img.c-tile-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.c-tile-mascot { position: absolute; left: 50%; top: 46%; width: 42%; transform: translate(-50%, -50%); filter: drop-shadow(0 30px 60px rgba(60, 40, 120, .25)); }
.c-tile-label {
    position: absolute; left: 24px; bottom: 24px; display: inline-flex; align-items: center; gap: 10px;
    padding: 10px 16px; border-radius: 9999px; background: rgba(255,255,255,.72); backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px); color: var(--c-ink); font-size: 14px;
}
.c-tile-label i { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }

/* --- three value columns, line-art icons --------------------------------- */

/* --- full-bleed product bands: copy left, UI cropped off the right edge --- */
.c-band {
    position: relative; overflow: hidden; color: #fff;
    min-height: min(900px, 100vh); padding: 160px var(--gutter) 0;
}
.c-band--dark {
    background:
        linear-gradient(180deg, rgba(27,27,27,.78) 0%, rgba(27,27,27,.92) 70%, #1B1B1B 100%),
        url('/assets/media/field-still.jpg') center / cover no-repeat;
    background-color: var(--c-dark);
}
.c-band--blue {
    background:
        radial-gradient(120% 90% at 20% 10%, rgba(139, 93, 193, .55) 0%, rgba(139, 93, 193, 0) 60%),
        linear-gradient(160deg, #2B3FBF 0%, #4C4FB8 45%, #1C1A3A 100%);
}
.c-band-copy { position: relative; z-index: 2; max-width: 460px; }
.c-band-copy .c-h2 { color: #fff; }
.c-band-copy .c-p { color: rgba(255,255,255,.86); margin-top: 20px; max-width: 420px; }
.c-band-copy .c-actions { display: flex; align-items: center; gap: 24px; margin-top: 36px; }
.c-band-copy .c-btn--ghost { color: #fff; }
/* The product, seen in part. Anchored to the right edge, taller than the
   band, so it is cut at the right and at the bottom the way the reference
   cuts its screenshots. */
.c-band-ui {
    position: absolute; left: 50%; top: 120px; width: max(780px, 58vw); height: auto;
    border-radius: 12px 0 0 0; box-shadow: 0 40px 120px rgba(0,0,0,.45);
    display: block;
}
.c-band--blue .c-band-ui { top: 190px; left: 52%; }
/* the chat is a wide 16:10 capture; larger than the home screen so it too
   runs off the bottom of the band instead of ending inside it */
.c-band--dark .c-band-ui { left: 38%; top: 90px; width: max(1240px, 108vw); }

/* --- carousel of 420x420 cards with video -------------------------------- */
.c-carousel { padding-top: 144px; padding-bottom: 80px; overflow: hidden; }
.c-car-nav { display: flex; gap: 20px; }
.c-car-nav button {
    width: 40px; height: 40px; border-radius: 50%; border: 0; background: transparent; color: var(--c-ink);
    font-size: 22px; line-height: 1; cursor: pointer; display: grid; place-items: center;
}
.c-car-nav button:disabled { color: #C8C8CE; cursor: default; }
.c-track {
    display: flex; gap: 24px; overflow-x: auto; scroll-snap-type: x mandatory;
    scrollbar-width: none; padding-right: var(--gutter);
    margin-right: calc(-1 * var(--gutter));   /* the row runs off the right edge */
}
.c-track::-webkit-scrollbar { display: none; }
.c-card {
    position: relative; flex: 0 0 420px; width: 420px; height: 420px; border-radius: 22px; overflow: hidden;
    background: var(--c-card); scroll-snap-align: start; text-decoration: none; color: inherit;
}
.c-card img, .c-card video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block;
    transition: transform .7s cubic-bezier(.2,.7,.2,1); }
/* Hover: the picture inside grows, the frame stays put, so the row never
   reflows and the neighbours do not jump. The shadow deepens with it. */
.c-card { transition: box-shadow .45s ease; }
.c-card:hover img, .c-card:hover video { transform: scale(1.06); }
.c-card:hover { box-shadow: 0 30px 70px rgba(40,24,90,.18); }
.c-card-label { position: absolute; left: 24px; top: 24px; z-index: 2; font-size: 20px; color: #fff; text-shadow: 0 1px 14px rgba(0,0,0,.45); }
.c-card-label--dark { color: var(--c-ink); text-shadow: none; }
.c-car-caps { display: grid; grid-template-columns: repeat(4, 420px); gap: 24px; margin-top: 16px; }
.c-car-caps p { font-size: 15px; color: var(--c-muted); }
.c-progress { position: relative; width: 380px; height: 2px; margin: 32px auto 0; background: var(--c-rule); border-radius: 2px; }
.c-progress i { position: absolute; left: 0; top: 0; height: 100%; width: 25%; border-radius: 2px; background: linear-gradient(90deg, #8B5DC1, #6F9BFF); transition: left .3s ease; }

/* --- capabilities: media card left, exclusive accordion right ------------ */
.c-caps { padding-top: 80px; padding-bottom: 144px; }
.c-caps .c-h2 { text-align: center; margin-bottom: 64px; }
.c-caps-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 96px; align-items: start; }
.c-caps-media { position: relative; border-radius: 22px; overflow: hidden; background: var(--c-card); aspect-ratio: 1 / 1; }
.c-caps-media img, .c-caps-media video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; opacity: 0; transform: scale(1.02); transition: opacity .45s ease, transform .6s cubic-bezier(.2,.7,.2,1); }
.c-caps-media img.is-on, .c-caps-media video.is-on { opacity: 1; transform: none; }
.c-acc details { border-top: 1px solid var(--c-rule); }
.c-acc details:last-child { border-bottom: 1px solid var(--c-rule); }
.c-acc summary {
    list-style: none; cursor: pointer; padding: 20px 0; font-size: 20px; color: var(--c-text);
    display: flex; align-items: center; justify-content: space-between;
}
.c-acc summary::-webkit-details-marker { display: none; }
.c-acc details[open] { position: relative; }
.c-acc details[open]::before {
    content: ''; position: absolute; left: 0; right: 0; top: -1px; height: 2px;
    background: linear-gradient(90deg, #8B5DC1 0%, #B07FF0 50%, #6F9BFF 100%);
}
.c-acc details[open] summary { padding-bottom: 8px; }
.c-acc-body { padding: 0 0 28px; }
.c-acc-body .c-p { max-width: 460px; }
.c-acc-body ul { list-style: none; margin: 20px 0 0; padding: 0; display: grid; gap: 10px; }
.c-acc-body li { display: flex; gap: 10px; align-items: flex-start; font-size: 15px; line-height: 1.45; color: var(--c-text); }
.c-acc-body li svg { flex: none; width: 18px; height: 18px; margin-top: 2px; }
.c-acc-body .c-link { margin-top: 20px; }

/* The three value columns lead with a Streamline glyph at text scale, in the
   accent, replacing the earlier abstract line drawings. */

/* --- pricing, in the card language --------------------------------------- */
.c-pricing { padding-top: 80px; padding-bottom: 80px; }
.c-pricing .c-head p { max-width: 460px; }
.c-plans { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.c-plan { position: relative; border-radius: 22px; background: var(--c-card); padding: 32px; display: flex; flex-direction: column; min-height: 520px; }
.c-plan--hot { background: var(--c-ink); color: #fff; }
.c-plan--hot .c-p, .c-plan--hot .c-plan-list li { color: rgba(255,255,255,.86); }
.c-plan-name { font-size: 12px; letter-spacing: .1em; text-transform: uppercase; color: inherit; opacity: .8; display: flex; align-items: center; gap: 10px; }
.c-plan-tag { font-size: 11px; letter-spacing: .06em; padding: 3px 8px; border-radius: 9999px; background: #8B5DC1; color: #fff; text-transform: uppercase; }
.c-plan .c-p { margin-top: 12px; }
.c-plan-price { margin-top: 28px; font-size: 48px; font-weight: 400; letter-spacing: -0.02em; line-height: 1; }
.c-plan-price small { font-size: 16px; letter-spacing: 0; opacity: .7; }
.c-plan-credits { margin-top: 10px; font-size: 16px; }
.c-plan-meta { font-size: 13px; color: var(--c-muted); margin-top: 4px; }
.c-plan--hot .c-plan-meta { color: rgba(255,255,255,.6); }
.c-plan-list { list-style: none; margin: 24px 0 0; padding: 24px 0 0; border-top: 1px solid rgba(0,0,0,.08); display: grid; gap: 10px; }
.c-plan--hot .c-plan-list { border-top-color: rgba(255,255,255,.14); }
.c-plan-list li { font-size: 15px; line-height: 1.4; display: flex; gap: 10px; }
.c-plan-list li::before { content: ''; flex: none; width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .5; margin-top: 7px; }
.c-plan .c-btn { margin-top: auto; align-self: flex-start; }
.c-plan .c-btn { margin-top: 28px; }
.c-plan-foot { display: flex; flex-direction: column; margin-top: auto; }
.c-pricing-fine { margin-top: 24px; font-size: 13px; color: var(--c-muted); }
.c-pricing-notes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 40px; margin-top: 64px; }
.c-pricing-notes h4 { font-size: 16px; font-weight: 400; margin: 0 0 8px; }
.c-pricing-notes p { font-size: 15px; line-height: 1.45; color: var(--c-muted); }

/* --- faq, as a ruled list ------------------------------------------------ */
.c-faq { padding-top: 80px; padding-bottom: 144px; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.45fr); gap: 64px; align-items: start; }
.c-faq .c-head { margin-bottom: 0; position: sticky; top: 96px; }
.c-faq-list { max-width: none; }
.c-faq-list details { border-top: 1px solid var(--c-rule); }
.c-faq-list details:last-child { border-bottom: 1px solid var(--c-rule); }
.c-faq-list summary { list-style: none; cursor: pointer; padding: 24px 0; font-size: 20px; color: var(--c-text); display: flex; justify-content: space-between; align-items: center; gap: 24px; }
.c-faq-list summary::-webkit-details-marker { display: none; }
.c-faq-list summary .sign { flex: none; width: 24px; height: 24px; display: grid; place-items: center; font-size: 22px; line-height: 1; transition: transform .2s ease; }
.c-faq-list details[open] summary .sign { transform: rotate(45deg); }
.c-faq-list details p { padding: 0 0 24px; max-width: 720px; font-size: 16px; line-height: 1.5; color: var(--c-text); }

/* The answer opens instead of appearing. A <details> has nothing to animate
   until its content box is addressable, so the height is interpolated on
   ::details-content, with `interpolate-size` to make `auto` a value the
   transition can reach and `allow-discrete` to keep the box alive on the way
   out. Where a browser has neither, the answer simply appears, as before. */
.c-faq-list { interpolate-size: allow-keywords; }

.c-faq-list details::details-content {
    block-size: 0;
    overflow: clip;
    opacity: 0;
    transition:
        block-size .34s cubic-bezier(.22, 1, .36, 1),
        content-visibility .34s allow-discrete,
        opacity .26s ease;
}

.c-faq-list details[open]::details-content {
    block-size: auto;
    opacity: 1;
}

/* the text settles down into the space the box just made */
.c-faq-list details p { transform: translateY(-6px); transition: transform .34s cubic-bezier(.22, 1, .36, 1); }
.c-faq-list details[open] p { transform: none; }

/* the plus turns into a cross with a little overshoot */
.c-faq-list summary .sign { transition: transform .34s cubic-bezier(.34, 1.4, .64, 1), color .2s ease; }
.c-faq-list summary:hover .sign { color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
    .c-faq-list details::details-content,
    .c-faq-list details p,
    .c-faq-list summary .sign { transition-duration: .01ms; }
}

/* --- the closing band, on the field ------------------------------------- */
.c-cta {
    position: relative; overflow: hidden; min-height: 420px; display: grid; place-items: center; text-align: center;
    padding: 96px var(--gutter); color: var(--c-ink);
    background: #FAFAFB;
}
.c-cta > div { position: relative; }
.c-cta .c-h2 { font-size: 60px; color: var(--c-ink); letter-spacing: -0.02em; line-height: 1; }
.c-cta .c-btn { margin-top: 32px; }
/* The same water as the hero, behind a band. Hidden until the solver has a
   context, so a machine without WebGL2 sees plain paper and nothing broken. */
.c-pricing { position: relative; overflow: hidden; }
.band-fluid { position: absolute; inset: 0; width: 100%; height: 100%; display: none; pointer-events: none; }
.has-ink > .band-fluid { display: block; }
.c-pricing > *:not(.band-fluid) { position: relative; }

/* --- footer, dark, five columns ----------------------------------------- */
.c-foot { background: #171717; color: #fff; padding: 64px var(--gutter) 32px; }
.c-foot-grid { display: grid; grid-template-columns: 1fr repeat(4, 160px); gap: 24px; }
/* The footer carries the same lockup as the header, in white: the mascot is
   knocked to white with a filter (its gradient would fight the dark ground)
   and the wordmark is the header's own type. logo/white.svg in the repo is an
   older chevron mark and is not used. */
.brand-lockup--white { color: #fff; font-size: 24px; }
.brand-lockup--white img { filter: brightness(0) invert(1); }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.c-foot h4 { margin: 0 0 14px; font-size: 12px; font-weight: 400; color: #9A9AA0; letter-spacing: .02em; }
.c-foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.c-foot li a { color: #fff; text-decoration: none; font-size: 14px; }
.c-foot li a:hover { text-decoration: underline; text-underline-offset: 3px; }
.c-foot-bot { display: flex; justify-content: space-between; align-items: center; gap: 24px; margin-top: 72px; font-size: 12px; color: #9A9AA0; }
.c-foot-bot a { color: #9A9AA0; text-decoration: none; margin-left: 18px; }
.c-foot-bot a:hover { text-decoration: underline; }
.c-social { display: flex; gap: 18px; }
.c-social a { color: #fff; font-size: 13px; text-decoration: none; margin: 0; }

/* --- responsive ---------------------------------------------------------- */
@media (max-width: 1100px) {
    .c-cols { grid-template-columns: 1fr; gap: 48px; }
    .c-caps-grid { grid-template-columns: 1fr; gap: 48px; }
    .c-plans { grid-template-columns: 1fr; }
    .c-pricing-notes { grid-template-columns: 1fr; gap: 24px; }
    .c-foot-grid { grid-template-columns: 1fr 1fr; }
    .c-band { min-height: 0; padding-top: 96px; }
    .c-band-ui { position: relative; left: 0; top: 0; width: 100%; margin-top: 48px; border-radius: 12px 12px 0 0; }
    .c-band--blue .c-band-ui, .c-band--dark .c-band-ui { left: 0; top: 0; width: 100%; }
    /* Narrow: the UI is cropped on the RIGHT rather than shrunk to a thumbnail,
       so what remains is still legible. */
    .c-band-ui { max-width: none; }
    /* the sidebar is cropped away, the chat is what remains */
    .c-band--dark .c-band-ui { width: 220%; margin-left: -62%; }
    /* the welcome screen is centred, so cut both sides */
    .c-band--blue .c-band-ui { width: 170%; margin-left: -35%; }
}
@media (max-width: 760px) {
    .c-faq { grid-template-columns: 1fr; gap: 24px; }
    .c-faq .c-head { position: static; }
    .c-h2 { font-size: 36px; }
    .c-cta .c-h2 { font-size: 40px; }
    .c-media-grid { grid-template-columns: 1fr; }
    .c-tile--tall { aspect-ratio: 4 / 3; }
    /* The hero film is framed for a wide tile; on a phone the tile is square
       and the film is scaled up so the card fills it. */
    .c-tile--wide { aspect-ratio: 1 / 1; }
    .c-tile--wide > video { transform: scale(1.12); transform-origin: 50% 50%; }
    .c-col svg { width: 64px; height: 80px; }
    .c-col .c-col-icn { width: 40px; height: 40px; }
    .c-cols { gap: 40px; }
    .c-values, .c-caps { padding-bottom: 96px; }
    .c-carousel { padding-top: 96px; }
    .c-band { padding-top: 72px; }
    .c-head { flex-direction: column; align-items: flex-start; gap: 20px; }
    .c-card { flex-basis: 300px; width: 300px; height: 300px; }
    .c-car-caps { display: none; }
    .c-foot-grid { grid-template-columns: 1fr; }
    .c-foot-bot { flex-direction: column; align-items: flex-start; }
}

/* --- photographic hero ground (?glass) ---
   The glass render is busy where the copy sits, so a soft veil is laid over
   it, centred on the column the text occupies. Radial rather than a flat
   scrim: the image keeps its life at the edges, which is the half worth
   looking at, and only loses contrast directly under the words. */
body.ag-glass-bg .hero-bg::after {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(50% 40% at 50% 52%,
        rgba(255,255,255,.46) 0%, rgba(255,255,255,.24) 48%, rgba(255,255,255,0) 78%);
}
/* The copy sits ABOVE the veil. Everything in the hero relies on DOM order
   for painting, and a pseudo-element on the parent paints after every child,
   so the veil greyed out the very words it was meant to make readable. */
body.ag-glass-bg .hero-foot,
body.ag-glass-bg .hero-labels,
body.ag-glass-bg .hero-scroll { z-index: 2; }
body.ag-glass-bg.ag-glass-plain .hero-bg::after { display: none; }

/* --- contour-wave hero ground (?waves) ---
   The canvas is the ground, so the fluid's own tint is switched off and the
   copy is lifted above it the same way the glass ground needed. */
.ag-wave-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
body.ag-wave-bg .hero-word-canvas { opacity: 0; }
/* The canvas painted the wordmark as well as the ink, so hiding it took the
   name with it. The DOM copy comes back instead. */
body.ag-wave-bg .hero-word-type { opacity: 1; }
body.ag-wave-bg .hero-foot,
body.ag-wave-bg .hero-labels,
body.ag-wave-bg .hero-scroll { z-index: 2; }

/* --- hero 2: the opening delivers Aimee, the copy assembles around her ---
   Enabled by ?hero2. The claim carries the promise at display size and the
   wordmark steps back to the nav, where a logo belongs: the largest type on
   the page should say what the product does, not what it is called.
   Everything here is scoped to the mode class, so the current hero is
   untouched. */
.hero-claim, .hero-slot { display: none; }
/* ag-no-mascot (set on <body> in index.html): the start screen without
   Aimee. Her slot, her still mark and the 3D body stay off in every hero
   mode; the copy column keeps its place. */
body.ag-no-mascot .hero-slot, body.ag-no-mascot .hero-slot-mark, body.ag-no-mascot .ag-hero-mascot { display: none !important; }
/* The opening lockup belongs to the opening alone. Without body.ag-intro it
   must never render (a later rule had let its word leak into the corner). */
body:not(.ag-intro) .ag-lockup, body.ag-no-mascot .ag-lockup { display: none !important; }

body.ag-hero2 .hero-foot {
    top: 50%; left: var(--gutter); right: auto;
    width: min(620px, 46vw); transform: translateY(-50%);
    text-align: left; align-items: flex-start;
}
body.ag-hero2 .hero-word { display: none; }
body.ag-hero2 .hero-claim {
    display: block; margin: 0 0 22px;
    font-family: 'Darker Grotesque', Archivo, system-ui, sans-serif;
    font-size: clamp(52px, 6.2vw, 88px); line-height: .96; letter-spacing: -0.03em;
    font-weight: 500; color: var(--ink);
}
body.ag-hero2 .hero-claim span { display: block; }
body.ag-hero2 .hero-lede { margin: 0 0 26px; text-align: left; max-width: 30em; }
body.ag-hero2 .hero-actions { justify-content: flex-start; }
body.ag-hero2 .hero-note { display: block; }

/* Her place: the right column. The slot is never painted, it only tells the
   opening where to form her and the mesh where home is, so one number moves
   both and they can never disagree. */
/* She is the only thing in the right column, so she carries it. */
body.ag-hero2 .ag-hero-mascot { --ag-aimee: 216px; }
@media (max-width: 860px) { body.ag-hero2 .ag-hero-mascot { --ag-aimee: 132px; } }
body.ag-hero2 .hero-slot {
    display: block; position: absolute;
    left: 68%; top: 48%; width: 1px; height: 1px;
}
/* Her still mark, for anyone the 3D body never reaches: the renderer is
   deliberately not started without a fine pointer (nothing to react to), and
   on those machines the right column was simply empty. Hidden the moment the
   real body mounts, so the two are never both on screen. */
.hero-slot-mark {
    position: absolute; left: 50%; top: 50%;
    /* Sized here, not inherited, and max-width released: the slot is a 1px
       anchor and the global img { max-width: 100% } clamped her to exactly
       that one pixel. */
    width: 216px; height: auto; max-width: none;
    transform: translate(-50%, -50%);
    /* The float carries the centring with it. acm-float writes a plain
       translateY, and a keyframe replaces the whole transform rather than
       adding to it, so borrowing it dropped her centring and parked her a
       half-width right of the anchor. Same trap the mascot documents. */
    animation: ag-slot-float 3.4s ease-in-out infinite;
}
@keyframes ag-slot-float {
    0%, 100% { transform: translate(-50%, -50%); }
    50%      { transform: translate(-50%, calc(-50% - 5px)); }
}
@media (prefers-reduced-motion: reduce) { .hero-slot-mark { animation: none; } }
body.ag-fluid-bg .hero-slot-mark { display: none; }

/* Each line of the claim arrives on its own, after she has landed. */
body.ag-hero2 .hero-claim span { opacity: 0; transform: translateY(16px); }
body.ag-hero2 .hero-claim.is-in span {
    opacity: 1; transform: none;
    transition: opacity .5s ease, transform .6s cubic-bezier(.22,1,.36,1);
}
body.ag-hero2 .hero-claim.is-in span:nth-child(2) { transition-delay: .09s; }
body.ag-hero2 .hero-claim.is-in span:nth-child(3) { transition-delay: .18s; }
body.ag-hero2 .hero-lede,
body.ag-hero2 .hero-actions,
body.ag-hero2 .hero-note { opacity: 0; transform: translateY(16px); }
body.ag-hero2 .hero-lede.is-in,
body.ag-hero2 .hero-actions.is-in,
body.ag-hero2 .hero-note.is-in {
    opacity: 1; transform: none;
    transition: opacity .5s ease, transform .6s cubic-bezier(.22,1,.36,1);
}

@media (max-width: 860px) {
    /* The phone rules above turn the hero into a normal stacked column
       (position: static, transform: none). This layout must follow them
       rather than fight them: the desktop centring would otherwise pull the
       claim back out of the flow and drop it on top of the labels. */
    body.ag-hero2 .hero-foot {
        position: relative; top: auto; left: auto; right: auto;
        width: auto; transform: none; padding: 0 var(--gutter);
    }
    /* Order on a phone: labels, then Aimee, then the claim and the rest. */
    body.ag-hero2 .hero-labels { margin-bottom: 18px; }
    body.ag-hero2 .hero-slot { position: absolute; left: 50%; top: 210px; }
    body.ag-hero2 .ag-hero-mascot { --ag-aimee: 118px; }
    body.ag-hero2 .hero-slot-mark { width: 118px; }
    body.ag-hero2 .hero-claim { margin: 132px 0 18px; font-size: clamp(40px, 11vw, 64px); }
    body.ag-hero2 .hero-lede { margin-bottom: 22px; }
}

/* --- ag-hero3: the split hero -------------------------------------------
   Copy on paper to the left of a hairline seam at 48%; to the right, a field of
   the questions people ask, as real text. Built on ag-hero2's left column, so
   only what differs is stated here. No mascot in this layout (see
   ag-no-mascot); the ink keeps the paper half alive. */
body.ag-hero3 .hero-labels, body.ag-hero3 .hero-scroll, body.ag-hero3 .hero-note { display: none; }
body.ag-hero3 .hero-foot {
    /* Centred on the field: the copy is the only thing on the hero now. */
    left: 50%; right: auto; transform: translate(-50%, -50%);
    width: min(860px, calc(100vw - 2 * var(--gutter)));
    text-align: center; align-items: center;
}
body.ag-hero3 .hero-claim {
    font-family: 'Archivo', system-ui, sans-serif;
    font-size: clamp(44px, 4.9vw, 72px); line-height: .98; letter-spacing: -0.042em;
    font-weight: 600; margin: 20px 0 22px;
}
body.ag-hero3 .hero-eyebrow {
    display: inline-flex; align-items: center; gap: 8px; border-radius: 999px; padding: 6px 13px;
    font-size: 11px; text-transform: uppercase; letter-spacing: .2em; font-weight: 500; color: #495057;
    background: rgba(18,16,22,.035); border: 1px solid rgba(18,16,22,.07);
}
body.ag-hero3 .hero-eyebrow i { width: 5px; height: 5px; border-radius: 50%; background: var(--mk-primary, #71639E); display: block; }
body.ag-hero3 .hero-lede { font-size: 19.5px; line-height: 1.5; color: #495057; margin: 0 auto 22px; max-width: 30em; text-align: center; }
/* Centred hero: the three claims sit in one row, not a stacked list. */
body.ag-hero3 .hero-ticks { list-style: none; margin: 0 0 30px; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 12px 28px; }
body.ag-hero3 .hero-ticks li { display: flex; gap: 13px; align-items: center; font-size: 16px; color: #495057; }
/* Same glyph and same 18px box as .c-acc-body li svg, so the two lists
   match. Ink, not the accent: the violet is spoken for by the pills.  */
body.ag-hero3 .hero-ticks li svg {
    flex: none; width: 18px; height: 18px;
    color: var(--ink);
}
/* The field. Sits after the ink canvas in the DOM and under the copy's
   z-index, so it covers the ink on its half and nothing else. */
body.ag-hero3 .hero-split {
    position: absolute; right: 0; top: 0; bottom: 0; width: 52%;
    background: #F4F2F7; border-left: 1px solid rgba(18,16,22,.07);
    overflow: hidden; pointer-events: none;
}
/* As its own band between the statement and the capabilities: full width,
   three rows, hairlines top and bottom instead of the seam. */
body.ag-hero3 .hero-split--band {
    position: relative; right: auto; top: auto; bottom: auto; width: 100%; height: 392px;
    border-left: 0; border-top: 1px solid rgba(18,16,22,.07); border-bottom: 1px solid rgba(18,16,22,.07);
}
/* In the band the label is a section eyebrow on the gutter, above the rows,
   instead of a chip floating over the last row. */
body.ag-hero3 .hero-split--band .hero-pills-label { left: var(--gutter); right: auto; top: 22px; bottom: auto; background: transparent; border: 0; padding: 0; backdrop-filter: none; }
body.ag-hero3 .hero-split--band .hero-pills { inset: 56px -6% 0 auto; }
body.ag-hero3 .c-requests { position: relative; z-index: 1; }
/* The box the rows are clipped to. No edge fade: the pills end at the seam
   line itself, which is also what a hovered one does. */
body.ag-hero3 .hero-pills-clip { position: absolute; inset: 0; overflow: hidden; }
body.ag-hero3 .hero-pills {
    --pill-gap: 20px;
    /* Wider than any field, anchored to the field's right edge, so the rows'
       tracks always start well left of the seam (they overflow leftwards). */
    /* Taller than the field on both ends, so the first and last rows are cut
       by the hero's edges rather than floating inside them. */
    /* No vertical overhang any more (the rows must not touch the edges); the
       right one stays, so the marquee still runs off the viewport. */
    position: absolute; inset: 0 -6% 0 auto; width: max(1200px, 200%);
    /* The rows sit close together and the block is centred, so there is clear
       air above the first row and below the last instead of both being cut
       by the hero's edges. */
    display: flex; flex-direction: column; justify-content: center; align-items: stretch; gap: 22px;
}
/* No paint containment here: it clipped the hovered pill's lift and shadow
   at the row's own box. The field's overflow already does the clipping the
   marquee needs. */
body.ag-hero3 .hero-pill-row { position: relative; width: 100%; flex: 0 0 auto; }
/* The track holds four identical sets and is moved from one set in to two
   sets in: with T = 4S + 3g that is from -(T/4 + g/4) to -(T/2 + g/2), which
   is exactly one set plus one gap, so the wrap lands on identical pixels.
   Sitting between the first and third set keeps both edges covered in either
   direction. */
body.ag-hero3 .hero-pill-track {
    display: flex; gap: var(--pill-gap); white-space: nowrap; width: max-content;
    animation: ag-pill-marquee var(--dur, 50s) linear infinite;
    animation-delay: var(--phase, 0s);
    /* Its own compositing layer, moved in 3D space: the browser then slides
       a finished bitmap instead of re-rasterising text every frame, which is
       the difference between a drift and a crawl. */
    will-change: transform; backface-visibility: hidden; transform: translate3d(0,0,0);
}
body.ag-hero3 .hero-pill-row:nth-child(even) .hero-pill-track { animation-direction: reverse; }
body.ag-hero3 .hero-split.is-paused .hero-pill-track { animation-play-state: paused; }
@keyframes ag-pill-marquee {
    from { transform: translate3d(calc(-25% - var(--pill-gap) / 4), 0, 0); }
    to   { transform: translate3d(calc(-50% - var(--pill-gap) / 2), 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
    body.ag-hero3 .hero-pill-track { animation: none; transform: translate3d(calc(-25% - var(--pill-gap) / 4), 0, 0); }
}
body.ag-hero3 .hero-pill {
    border-radius: 999px; padding: 20px 34px; font-size: 31px; letter-spacing: -.02em; line-height: 1.2;
    /* Transparent rather than removed, so dropping the visible border does
       not shift every pill by two pixels. */
    color: #BBB6C6; background: rgba(18,16,22,.045); border: 1px solid transparent;
    /* The field is click-through; only the pills take the pointer, for the
       hover below. Colour and lift ease on a spring-like curve, never linear. */
    pointer-events: auto; cursor: default;
    transition: color .38s cubic-bezier(.32,.72,0,1), background-color .38s cubic-bezier(.32,.72,0,1),
                border-color .38s cubic-bezier(.32,.72,0,1), transform .5s cubic-bezier(.32,.72,0,1),
                box-shadow .5s cubic-bezier(.32,.72,0,1);
}
body.ag-hero3 .hero-pill.is-on { color: #8B83A1; background: rgba(113,99,158,.11); }
/* Hover: the pill turns Odoo violet (the theme's primary, violet as the
   fallback) and lifts; its row holds still so a moving pill can be read.
   Driven by .is-hot from site.js rather than :hover, because the field clips
   at the seam: a pill straddling an edge would highlight as a cut-off shape.
   site.js only marks pills that are fully inside the field. */
body.ag-hero3 .hero-pill.is-hot {
    color: #fff;
    background: var(--mk-primary, #71639E);
    transform: translateY(-3px) scale(1.025);
    box-shadow: 0 22px 44px -20px rgba(113,99,158,.6);
    /* Above its neighbours, so the lift is never overlapped by the next pill. */
    position: relative; z-index: 1;
}
body.ag-hero3 .hero-pill-row.is-hot-row .hero-pill-track { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) { body.ag-hero3 .hero-pill.is-hot { transform: none; } }
body.ag-hero3 .hero-pills-label {
    position: absolute; right: 40px; bottom: 44px;
    font-size: 11px; letter-spacing: .2em; text-transform: uppercase; color: #8B83A1;
    /* Sits on top of the moving rows, so it carries its own paper. */
    padding: 7px 12px; border-radius: 999px; background: rgba(250,250,251,.92);
    border: 1px solid rgba(18,16,22,.07); backdrop-filter: blur(6px);
}
/* Eyebrow and ticks join the copy's entrance. */
body.ag-hero3 .hero-eyebrow, body.ag-hero3 .hero-ticks { opacity: 0; transform: translateY(16px); }
body.ag-hero3 .hero-eyebrow.is-in, body.ag-hero3 .hero-ticks.is-in {
    opacity: 1; transform: none;
    transition: opacity .5s ease, transform .6s cubic-bezier(.22,1,.36,1);
}
body.ag-hero3 .hero-claim.is-in span:nth-child(2) { transition-delay: .09s; }
/* How many rows fit depends on the hero's height, not its width: eight rows
   plus their gaps are 786px, so a 720px-tall window pushed them past both
   edges and the air above and below went negative. Drop rows as the window
   gets flatter. Rows are hidden, not removed, so the markup stays one list.
   These sit before the phone block below, which overrides them with 5. */
@media (max-height: 860px) { body.ag-hero3 .hero-pill-row:nth-child(n+8) { display: none; } }
@media (max-height: 780px) { body.ag-hero3 .hero-pill-row:nth-child(n+7) { display: none; } }
@media (max-height: 660px) { body.ag-hero3 .hero-pill-row:nth-child(n+6) { display: none; } }

@media (max-width: 860px) {
    /* Phone: the copy first, the field below it as a band. */
    /* The desktop centring transform must not survive onto the phone, where the
       hero is a normal stacked column. */
    body.ag-hero3 .hero-foot { width: auto; left: auto; right: auto; transform: none; text-align: center; align-items: center; }
    body.ag-hero3 .hero-claim { margin: 14px 0 16px; font-size: clamp(34px, 9.4vw, 44px); }
    body.ag-hero3 .hero-split {
        position: relative; right: auto; top: auto; bottom: auto; width: auto; height: 380px;
        margin-top: 32px; border-top: 1px solid rgba(18,16,22,.07);
    }
    /* Five rows only: eight would not fit the band with air left at either
       end. Hidden rather than removed, so the markup stays one list. */
    body.ag-hero3 .hero-pill-row:nth-child(n+6) { display: none; }
    body.ag-hero3 .hero-pills { --pill-gap: 12px; inset: 0 -30% 0 auto; width: max(900px, 200%); gap: 14px; }
    body.ag-hero3 .hero-pill { padding: 12px 20px; font-size: 18px; }
    body.ag-hero3 .hero-pills-label { right: 24px; bottom: 18px; }
}

/* --- header: brand on the gutter, links and CTA in one dark pill ------------
   The bar itself is transparent; the pill carries the chrome. Start free keeps
   the brand gradient (.btn--primary), Sign in is a plain white link. */
/* Desktop only: below 860px the original burger layout owns the header and
   these pill rules must not reach the phone (they forced the links and the
   CTA visible there and pushed the burger off-screen). */
@media (min-width: 861px) {
    body.ag-hero3 #nav { background: transparent; border-bottom: 0; backdrop-filter: none; -webkit-backdrop-filter: none; justify-content: space-between; }
    body.ag-hero3 #nav.is-solid { background: transparent; border-bottom-color: transparent; }
    body.ag-hero3 .nav-pill {
        /* Thinner, and set down from the top edge rather than centred in the
           bar: 20px of air above, 44px tall. */
        position: absolute; left: 50%; top: 20px; transform: translateX(-50%);
        display: flex; align-items: center; gap: 6px;
        padding: 4px 4px 4px 14px; border-radius: 999px;
        background: #121016; color: #fff;
        box-shadow: 0 18px 44px -20px rgba(18,16,22,.55), inset 0 1px 0 rgba(255,255,255,.06);
    }
    /* The brand inside the pill: mascot in its own colours, wordmark in white,
       a hairline between it and the links. */
    body.ag-hero3 .nav-pill .nav-logo { display: block; margin: 0; padding-right: 14px; margin-right: 6px; border-right: 1px solid rgba(255,255,255,.14); line-height: 0; }
    body.ag-hero3 .nav-pill .brand-lockup { color: #fff; font-size: 22px; }
    body.ag-hero3 .nav-pill .nav-links { display: flex; gap: 2px; margin: 0; padding: 0; list-style: none; }
    body.ag-hero3 .nav-pill .nav-links a { display: inline-block; padding: 8px 11px; border-radius: 999px; color: rgba(255,255,255,.86); font-size: 13.5px; text-decoration: none; transition: background .2s ease, color .2s ease; }
    body.ag-hero3 .nav-pill .btn--sm { padding: 8px 14px; font-size: 13px; }
    body.ag-hero3 .nav-pill .nav-links a:hover { background: rgba(255,255,255,.08); color: #fff; }
    body.ag-hero3 .nav-pill .nav-cta { display: flex; align-items: center; gap: 4px; }
    body.ag-hero3 .nav-pill #nav-signin { background: transparent; border-color: transparent; color: rgba(255,255,255,.86); backdrop-filter: none; }
    body.ag-hero3 .nav-pill #nav-signin:hover { background: rgba(255,255,255,.08); color: #fff; }
}

@media (max-width: 860px) {
    body.ag-hero3 .hero-ticks { flex-direction: column; align-items: center; gap: 10px; }
    /* A claim that wraps keeps its glyph at the start of its own first line
       instead of drifting to the column's edge. */
    body.ag-hero3 .hero-ticks li { text-align: left; align-items: flex-start; max-width: 30ch; }
    body.ag-hero3 .hero-ticks li svg { margin-top: 3px; }
    body.ag-hero3 .hero-split--band { height: 262px; }
    body.ag-hero3 .hero-split--band .hero-pills { inset: 44px -30% 0 auto; }
    /* The wrapper dissolves so the links and the CTA are direct children of
       #nav again and the existing burger-menu rules lay them out. */
    body.ag-hero3 .nav-pill { display: contents; }
}
