/* ══════════════════════════════════════════════════════════════════════════
   Living Knowledge Base animation
   ══════════════════════════════════════════════════════════════════════════

   Team updates rotate in, drop into the Knowledge Base, and the new context
   fans out through Operations and Customer Success to the specialised leaf
   nodes. Pure CSS — no JavaScript drives any part of it.

   Moved here out of static-pages/home/body.css so the homepage's "Living
   Knowledge Base" section and the hero of the knowledge base product page can
   share one copy. That mattered as soon as there were two: the homepage
   section links straight to that page, so the two are the same claim in two
   places, and a visitor following the link should not arrive at a different
   drawing of it.

   Why a separate file rather than shared.css. shared.css is enqueued on every
   page of the site (functions.php loads it for the site-wide CTA), so anything
   put there is downloaded everywhere. This is ~18KB of animation used by two
   pages, so it is loaded by those two pages through the `styles` array in
   their deps.json and by nobody else.

   Selectors are unscoped, exactly as they were in home/body.css — this was a
   verbatim move, so the homepage's rendering is unchanged by construction.
   That is safe only because the file is loaded by the two pages that opt into
   it; it is not, and must not become, a site-wide stylesheet.

   Markup lives in each page's body.html. The avatar images are referenced by
   absolute path under static-pages/home/avatars/, which resolves from any
   page.
   ══════════════════════════════════════════════════════════════════════════ */

        /* Funnel animation */
        .funnel {
            position: relative;
            aspect-ratio: 420 / 560;
            font-family: var(--bodyfontfamily, system-ui, sans-serif);
        }
        .funnel__layer {
            position: absolute; inset: 0;
            width: 100%; height: 100%;
            pointer-events: none;
        }
        .funnel__spout {
            transform-origin: 210px 340px;
            animation: funnelSpoutStretch 3s steps(1, end) infinite;
        }
        .funnel__head,
        .funnel__head-back {
            animation: funnelHeadLift 3s steps(1, end) infinite;
        }
        @keyframes funnelSpoutStretch {
            0%, 78%, 98%, 100% { transform: scaleY(1); }
            82%                { transform: scaleY(1.18); }
            86%                { transform: scaleY(0.82); }
            90%                { transform: scaleY(1.10); }
            94%                { transform: scaleY(0.94); }
        }
        @keyframes funnelHeadLift {
            0%, 78%, 98%, 100% { transform: translateY(0); }
            82%                { transform: translateY(-16px); }
            86%                { transform: translateY(16px); }
            90%                { transform: translateY(-9px); }
            94%                { transform: translateY(5px); }
        }
        .funnel__layer--back  { z-index: 0; }
        .funnel__layer--front { z-index: 2; }
        .funnel__factory {
            position: relative;
            z-index: 2;
        }
        .funnel__card {
            position: absolute;
            left: 50%;
            top: 0;
            width: 62%;
            background: #F5F5F7;
            border: 1px solid rgba(15,23,42,.06);
            border-radius: 18px;
            box-shadow: 0 10px 24px rgba(15,23,42,.08), 0 2px 4px rgba(15,23,42,.04);
            padding: 12px 14px;
            display: flex; flex-direction: column; gap: 10px;
            transform-origin: 50% 50%;
            animation: funnelArc 18s cubic-bezier(.4, 0, .2, 1) infinite;
            animation-delay: var(--d, 0s);
            will-change: transform, opacity;
            z-index: 1;
        }
        .funnel__title {
            font-size: 15px; font-weight: 700; color: #0F172A;
            letter-spacing: -0.01em; line-height: 1.1;
        }
        .funnel__row {
            display: flex; align-items: center; gap: 14px;
        }
        .funnel__portrait {
            position: relative;
            width: 64px; height: 64px; flex-shrink: 0;
        }
        .funnel__avatar {
            width: 64px; height: 64px; border-radius: 50%;
            object-fit: cover; object-position: 50% 15%;
            background: #E2E8F0;
            border: 2px solid #fff;
            box-shadow: 0 0 0 1px rgba(15,23,42,.08), 0 4px 10px rgba(15,23,42,.12);
        }
        .funnel__badge {
            position: absolute;
            right: -4px; bottom: -2px;
            width: 28px; height: 28px; border-radius: 50%;
            display: flex; align-items: center; justify-content: center;
            color: #fff; font-size: 15px;
            border: 2px solid #F5F5F7;
            box-shadow: 0 2px 6px rgba(15,23,42,.2);
        }
        .funnel__badge--mic   { background: #20796F; }
        .funnel__badge--gh    { background: #24292F; }
        .funnel__badge--slack { background: #fff; }
        .funnel__badge--memo  { background: #F59E0B; }
        .funnel__badge--pdf   { background: #DC2626; }
        .funnel__badge--gmail { background: #fff; }
        .funnel__info {
            flex: 1; min-width: 0;
            display: flex; flex-direction: column; gap: 3px;
        }
        .funnel__name {
            font-size: 14px; font-weight: 700; color: #0F172A;
            line-height: 1.15;
            white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
        }
        .funnel__role {
            font-size: 11.5px; color: #64748B;
            line-height: 1.15; font-weight: 500;
            white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
            margin-bottom: 4px;
        }
        .funnel__skeleton {
            display: flex; flex-direction: column; gap: 5px;
        }
        .funnel__skeleton span {
            height: 10px; border-radius: 5px;
            background: linear-gradient(90deg, #DCE3EB 0%, #EDF1F5 50%, #DCE3EB 100%);
            background-size: 200% 100%;
            animation: funnelSkel 2.2s ease-in-out infinite;
        }
        .funnel__skeleton span:last-child {
            height: 8px;
            background: linear-gradient(90deg, #E6ECF1 0%, #F1F5F9 50%, #E6ECF1 100%);
            background-size: 200% 100%;
        }
        @keyframes funnelSkel {
            0%   { background-position: 100% 0; }
            100% { background-position: -100% 0; }
        }

        @keyframes funnelArc {
            0%   { transform: translate(calc(-50% + var(--sx, 0%)), 0%) rotate(0deg)             scale(1);  opacity: 1; }
            11%  { transform: translate(calc(-50% + var(--sx, 0%)), 0%) rotate(0deg)             scale(1);  opacity: 1; }
            15%  { transform: translate(-50%, 105%)                     rotate(var(--rot, 0deg)) scale(.5); opacity: 1; }
            17%  { transform: translate(-50%, 125%)                     rotate(var(--rot, 0deg)) scale(.3); opacity: 0; }
            100% { transform: translate(-50%, 125%)                     rotate(var(--rot, 0deg)) scale(.3); opacity: 0; }
        }

        .funnel__chip {
            transform-box: fill-box;
            transform-origin: center;
            animation: funnelChipPulse 3s steps(1, end) infinite;
        }
        @keyframes funnelChipPulse {
            0%, 78%, 98%, 100% { transform: scale(1)    rotate(0deg); }
            82%                { transform: scale(1.12) rotate(-5deg); }
            86%                { transform: scale(0.92) rotate(4deg); }
            90%                { transform: scale(1.08) rotate(-3deg); }
            94%                { transform: scale(0.98) rotate(1deg); }
        }
        .funnel__chip-die {
            animation: funnelChipDie 3s steps(1, end) infinite;
        }
        @keyframes funnelChipDie {
            0%, 78%, 98%, 100% { fill: transparent; }
            82%                { fill: #FFD66E; }
            86%                { fill: #38BDF8; }
            90%                { fill: #FFD66E; }
            94%                { fill: #FFFFFF; }
        }
        .funnel__chip-dot {
            transform-box: fill-box;
            transform-origin: center;
            animation: funnelChipDot 3s steps(1, end) infinite;
        }
        @keyframes funnelChipDot {
            0%, 78%, 98%, 100% { opacity: 1; transform: scale(1); }
            82%                { opacity: 0; transform: scale(.3); }
            86%                { opacity: 1; transform: scale(1.4); }
            90%                { opacity: 0; transform: scale(.3); }
            94%                { opacity: 1; transform: scale(1.2); }
        }
        .funnel__chip-ring {
            transform-box: fill-box;
            transform-origin: center;
            opacity: 0;
            animation: funnelChipRing 3s ease-out infinite;
        }
        @keyframes funnelChipRing {
            0%, 78%, 98%, 100% { transform: scale(.6); opacity: 0; }
            80%                { transform: scale(.6); opacity: .9; }
            96%                { transform: scale(3.2); opacity: 0; }
        }
        .funnel__chip-signal {
            transform-box: fill-box;
            transform-origin: center;
            filter: drop-shadow(0 0 2px #7DD3FC) drop-shadow(0 0 4px #38BDF8);
            opacity: 0;
        }
        .funnel__chip-signal--in {
            animation: funnelChipSignalIn .7s linear infinite;
        }
        @keyframes funnelChipSignalIn {
            0%        { transform: translateY(0);    opacity: 1; }
            85%       { transform: translateY(36px); opacity: 1; }
            100%      { transform: translateY(36px); opacity: 0; }
        }
        .funnel__chip-signal--out {
            animation: funnelChipSignalOut .7s linear infinite;
        }
        @keyframes funnelChipSignalOut {
            0%        { transform: translateY(0);    opacity: 1; }
            85%       { transform: translateY(20px); opacity: 1; }
            100%      { transform: translateY(20px); opacity: 0; }
        }

        .funnel__cpu {
            position: absolute;
            left: 50%; bottom: calc(11% + 23px);
            transform: translateX(-50%);
            display: flex; flex-direction: column; align-items: center;
        }
        .funnel__library {
            width: 210px; height: 160px;
            display: block;
            filter: drop-shadow(0 6px 10px rgba(15,23,42,.18));
        }
        .funnel__cpu-label {
            font-size: 11px; font-weight: 700; color: #0F172A;
            letter-spacing: .02em;
        }
        @keyframes funnelCpuJiggle {
            0%, 100%   { transform: translateY(0)   rotate(0); }
            28%        { transform: translateY(-3px) rotate(-4deg); }
            34%        { transform: translateY(3px)  rotate(3deg); }
            42%        { transform: translateY(0)    rotate(-2deg); }
            52%        { transform: translateY(0)    rotate(0); }
        }

        /* ----- Knowledge-base graphic (replaces the building+funnel for "Living Knowledge Base") -----
           The same 6 .funnel__card elements still rotate in and drop down — they take the place of
           the "INGEST" panel that the reference image puts above the network. They land in the
           Knowledge Hub primary node. From there the pulse propagates outward:
              card → KH (always, every 3s) → relevant primary (Ops/CS) → relevant leaf node.
           Card-to-leaf mapping (drives which paths/nodes pulse at which moment in the 18s loop):
              card1 Voice Update      lands 15%      → Ops → SOPs
              card2 PR Merged         lands 31.67%   → KH-leaf Engineering Wiki  (no second primary)
              card3 Slack Conv        lands 48.33%   → KH-leaf Marketing Assets  (no second primary)
              card4 Voice Memo        lands 65%      → Ops → Compliance
              card5 PDF Proposal      lands 81.67%   → CS → Client Accounts
              card6 Email Thread      lands 98.33%   → CS → Customer Support
        */
        /* Container widens and lengthens vs the original 420/560 to fit the hub triangle plus a
           ring of leaf nodes around each primary, like the reference graphic. Design grid is
           480×560 — every left/top % below is derived from that grid. The three primaries form a
           tight equilateral triangle of side 120, sitting low in the canvas so the upper portion
           is reserved for the rotating cards to drop into. */
        .funnel.kb-stage { aspect-ratio: 480 / 560; max-width: 480px; }

        /* Default frame: behaves like a transparent passthrough — the stage fills it up to the
           480px max-width set above. The frame only becomes load-bearing on small screens, where
           it locks the visual size and the stage is scaled down to fit. */
        .kb-scale-frame { width: 100%; max-width: 480px; position: relative; }

        /* Small-screen handling. Below 600px the stage is locked at its 480px design width so its
           internal proportions stay correct, and the whole element is shrunk visually with
           transform: scale(). The frame's aspect-ratio sets the layout footprint to the *visible*
           scaled size; the stage is absolutely positioned inside so its 480×560 design-size box
           doesn't extend the column height or leave dead space below the animation.

           Two steps, both driven purely by --kb-frame-width (the scale below is its only consumer):
             • Step 1 — larger phones (451–599px): cap at 380px so the animation doesn't read as tiny
               in the full-width stacked column.
             • Step 2 — very small phones (≤450px): drop back to 280px so a ~330px device still keeps
               ~25px of side padding. */
        @media (max-width: 599px) {
            .kb-scale-frame {
                --kb-frame-width: min(380px, calc(100vw - 50px));
                width: var(--kb-frame-width);
                aspect-ratio: 480 / 560;
                margin: 0 auto;
            }
            .kb-scale-frame .funnel.kb-stage {
                position: absolute;
                top: 0; left: 0;
                width: 480px;
                max-width: none;
                height: 560px;
                aspect-ratio: auto;
                transform-origin: top left;
                transform: scale(calc(var(--kb-frame-width) / 480px));
            }
        }
        /* Step 2 override — only the frame width changes; width/aspect-ratio/scale above all read
           the var, so they recompute to the smaller size. */
        @media (max-width: 450px) {
            .kb-scale-frame {
                --kb-frame-width: min(280px, calc(100vw - 50px));
            }
        }

        .kb-paths {
            position: absolute; inset: 0;
            width: 100%; height: 100%;
            pointer-events: none;
            z-index: 0;
        }
        .kb-path {
            fill: none;
            stroke: #64748B;
            stroke-width: 1.6;
            stroke-linecap: round;
            stroke-dasharray: 4 6;
            opacity: .45;
            animation: kbPathFlow 1.4s linear infinite;
        }
        @keyframes kbPathFlow {
            from { stroke-dashoffset: 0; }
            to   { stroke-dashoffset: -22; }
        }
        /* Per-path activation. Each path has a constant gentle dash flow plus an 18s outer loop that
           brightens it at the trigger moments associated with that route's card(s). */
        .kb-path--kh-ops      { animation: kbPathFlow 1.4s linear infinite, kbPathPulse_Ops    18s linear infinite; }
        .kb-path--kh-cs       { animation: kbPathFlow 1.4s linear infinite, kbPathPulse_Cs     18s linear infinite; }
        .kb-path--ops-cs      { /* steady — sibling-primary link, never directly activated */ }
        .kb-path--kh-eng      { animation: kbPathFlow 1.4s linear infinite, kbPathPulse_Eng    18s linear infinite; }
        .kb-path--kh-mkt      { animation: kbPathFlow 1.4s linear infinite, kbPathPulse_Mkt    18s linear infinite; }
        .kb-path--ops-sop     { animation: kbPathFlow 1.4s linear infinite, kbPathPulse_Sop    18s linear infinite; }
        .kb-path--ops-hr      { animation: kbPathFlow 1.4s linear infinite, kbPathPulse_Hr     18s linear infinite; }
        .kb-path--cs-supp     { animation: kbPathFlow 1.4s linear infinite, kbPathPulse_Supp   18s linear infinite; }
        .kb-path--cs-client   { animation: kbPathFlow 1.4s linear infinite, kbPathPulse_Client 18s linear infinite; }

        /* Cascade timings — when a card lands at time T, the pulse travels through the network in
           sequence rather than all at once:
              T          KH peaks (3s sub-loop, every card landing)
              T + 0.5%   Path KH→primary (or KH→leaf for direct routes) brightens
              T + 1%     Primary (Ops/CS) peaks; OR for KH-direct routes, the leaf peaks here
              T + 1.5%   Path primary→leaf brightens (two-hop routes only)
              T + 2%     Leaf peaks (two-hop routes only)
           1% of an 18s loop ≈ 180ms, so each cascade step is clearly distinguishable to the eye. */
        @keyframes kbPathPulse_Ops    { /* shared by cards 1 (15%) and 4 (65%); brightens at +0.5% */
            0%, 15%, 17%, 65%, 67%, 100%       { stroke: #64748B; opacity: .45; stroke-width: 1.6; }
            15.5%, 65.5%                        { stroke: #38BDF8; opacity: 1;   stroke-width: 2.4; }
            16.5%, 66.5%                        { stroke: #7DD3FC; opacity: .8;  stroke-width: 2;   }
        }
        @keyframes kbPathPulse_Cs     { /* shared by cards 5 (81.67%) and 6 (98.33%); brightens at +0.5% */
            0%, 81.67%, 83.67%, 98.33%, 100%    { stroke: #64748B; opacity: .45; stroke-width: 1.6; }
            82.17%, 98.83%                      { stroke: #38BDF8; opacity: 1;   stroke-width: 2.4; }
            83%, 99.5%                          { stroke: #7DD3FC; opacity: .8;  stroke-width: 2;   }
        }
        @keyframes kbPathPulse_Eng    { /* card 2 KH→leaf direct; brightens at 32.17% (+0.5%) */
            0%, 31.67%, 33.67%, 100%   { stroke: #64748B; opacity: .45; stroke-width: 1.6; }
            32.17%                      { stroke: #38BDF8; opacity: 1;   stroke-width: 2.4; }
            33%                         { stroke: #7DD3FC; opacity: .8;  stroke-width: 2;   }
        }
        @keyframes kbPathPulse_Mkt    { /* card 3 KH→leaf direct; brightens at 48.83% (+0.5%) */
            0%, 48.33%, 50.33%, 100%   { stroke: #64748B; opacity: .45; stroke-width: 1.6; }
            48.83%                      { stroke: #38BDF8; opacity: 1;   stroke-width: 2.4; }
            49.67%                      { stroke: #7DD3FC; opacity: .8;  stroke-width: 2;   }
        }
        @keyframes kbPathPulse_Sop    { /* card 4 Ops→leaf; brightens at 66.5% (+1.5% after KH peak) */
            0%, 66%, 68%, 100%         { stroke: #64748B; opacity: .45; stroke-width: 1.6; }
            66.5%                       { stroke: #38BDF8; opacity: 1;   stroke-width: 2.4; }
            67.33%                      { stroke: #7DD3FC; opacity: .8;  stroke-width: 2;   }
        }
        @keyframes kbPathPulse_Hr     { /* card 1 Ops→leaf; brightens at 16.5% (+1.5% after KH peak) */
            0%, 16%, 18%, 100%         { stroke: #64748B; opacity: .45; stroke-width: 1.6; }
            16.5%                       { stroke: #38BDF8; opacity: 1;   stroke-width: 2.4; }
            17.33%                      { stroke: #7DD3FC; opacity: .8;  stroke-width: 2;   }
        }
        @keyframes kbPathPulse_Supp   { /* card 6 CS→leaf; brightens at 99.83% (+1.5% after KH peak) */
            0%, 99.33%, 100%           { stroke: #64748B; opacity: .45; stroke-width: 1.6; }
            99.83%                      { stroke: #38BDF8; opacity: 1;   stroke-width: 2.4; }
        }
        @keyframes kbPathPulse_Client { /* card 5 CS→leaf; brightens at 83.17% (+1.5% after KH peak) */
            0%, 82.67%, 84.67%, 100%   { stroke: #64748B; opacity: .45; stroke-width: 1.6; }
            83.17%                      { stroke: #38BDF8; opacity: 1;   stroke-width: 2.4; }
            84%                         { stroke: #7DD3FC; opacity: .8;  stroke-width: 2;   }
        }

        /* Nodes — primary (large filled circle, white text) + secondary (small light-teal circle
           with external label). Both are HTML elements absolutely positioned over the path SVG.
           Position is derived from a 420×620 design grid: left/top % = (cx_px - r_px)/420 (or /620). */
        .kb-node {
            position: absolute;
            border-radius: 50%;
            display: flex; flex-direction: column;
            align-items: center; justify-content: center;
            text-align: center;
            transform-origin: center;
            will-change: transform;
            z-index: 2;
        }
        .kb-pri {
            width: 21%;            /* 88px @ 420 container */
            aspect-ratio: 1 / 1;
            border: 3px solid #fff;
            box-shadow: 0 6px 16px rgba(15,23,42,.18), 0 2px 4px rgba(15,23,42,.08);
            color: #fff;
            padding: 6px;
        }
        .kb-pri__icon  { font-size: 17px; line-height: 1; margin-bottom: 2px; }
        .kb-pri__label { font-size: 9px; font-weight: 800; line-height: 1.05; letter-spacing: .01em; }

        /* All three primaries are the same size (r=46 → width 19.17% on the 480 grid) on an
           equilateral triangle of side 120. The triangle sits low so cards have ~150px of clean
           drop-zone above the topmost node before they hit Knowledge Hub. */
        .kb-pri--kh  { width: 14.58%; background: #19877D; left: 42.71%; top: 34.82%; animation: kbPulseKH 3s steps(1, end) infinite; }              /* brand primary teal — cx 240 cy 230 */
        .kb-pri--ops { width: 14.58%; background: #287FAB; left: 30.21%; top: 53.39%; animation: kbPulseOps 18s linear infinite; }                   /* brand secondary blue — cx 180 cy 334 */
        .kb-pri--cs  { width: 14.58%; background: #F8C26C; color: #4A4A4A; left: 55.21%; top: 53.39%; animation: kbPulseCs 18s linear infinite; }    /* brand accent gold (dark-grey text for contrast) — cx 300 cy 334 */

        /* Knowledge Hub pulses on every card landing. With 6 cards every 3s, a 3s loop pulses on
           each landing identically — same trick the original funnelChip used. */
        @keyframes kbPulseKH {
            0%, 88%, 100% { transform: scale(1);    box-shadow: 0 6px 16px rgba(15,23,42,.18), 0 2px 4px rgba(15,23,42,.08); }
            90%           { transform: scale(1.10); box-shadow: 0 8px 24px rgba(25,135,125,.55), 0 0 0 4px rgba(25,135,125,.22); }
            93%           { transform: scale(.97);  box-shadow: 0 6px 18px rgba(25,135,125,.32), 0 0 0 2px rgba(25,135,125,.14); }
            96%           { transform: scale(1.04); box-shadow: 0 6px 16px rgba(15,23,42,.18); }
        }
        /* Operations pulses for cards 1 and 4 — at T+1% (16% and 66%) so it follows the KH peak. */
        @keyframes kbPulseOps {
            0%, 15.5%, 17.5%, 65.5%, 67.5%, 100% { transform: scale(1);    box-shadow: 0 6px 16px rgba(15,23,42,.18); }
            16%,    66%                           { transform: scale(1.10); box-shadow: 0 8px 24px rgba(40,127,171,.55), 0 0 0 4px rgba(40,127,171,.22); }
            17%,    67%                           { transform: scale(1.03); }
        }
        /* Customer Success pulses for cards 5 and 6 — at T+1% (82.67% and 99.33%). Card 6's CS peak
           sits late in the loop; it decays naturally back to rest as the loop wraps. */
        @keyframes kbPulseCs {
            0%, 82.17%, 84.17%, 98.83%, 100%       { transform: scale(1);    box-shadow: 0 6px 16px rgba(15,23,42,.18); }
            82.67%, 99.33%                         { transform: scale(1.10); box-shadow: 0 8px 24px rgba(248,194,108,.65), 0 0 0 4px rgba(248,194,108,.30); }
            83.67%                                  { transform: scale(1.03); }
        }

        /* Secondary leaf node — small light-teal circle with external label below. */
        .kb-sec {
            width: 7.08%;           /* 34px @ 480 container */
            aspect-ratio: 1 / 1;
            background: #D4ECE8;
            border: 1.5px solid #20796F;
            color: #0F4A43;
            box-shadow: 0 2px 6px rgba(15,23,42,.10);
        }
        .kb-sec__icon  { font-size: 13px; line-height: 1; }
        .kb-sec__label {
            position: absolute;
            top: 100%; left: 50%;
            transform: translateX(-50%);
            margin-top: 4px;
            font-size: 9.5px; font-weight: 700;
            color: #0F172A; line-height: 1.05;
            white-space: nowrap;
            letter-spacing: .01em;
        }
        /* Two-line override for slightly longer labels (kept narrow with a fixed width) */
        .kb-sec__label--wrap { white-space: normal; width: 78px; }
        /* HR Policies + Meeting Notes sit side-by-side near the centre under the triangle, so their
           labels need to be narrower to keep a visible gap between them. */
        .kb-sec--hr .kb-sec__label, .kb-sec--meeting .kb-sec__label { width: 48px; }

        /* Positions on the 480×700 grid. r=22 for all secondaries.
           left % = (cx - r)/480 *100,  top % = (cy - r)/700 *100. Each cluster halos its primary
           outward — KH leaves wrap above and to its sides, Ops leaves arc around its lower-left,
           CS leaves arc around its lower-right. */
        /* All positions on the 480×560 grid. r=22 for secondaries → width 9.17%.
           KH halo (4) — Marketing/Engineering far sides at KH's mid level, Sales/Product
           below KH between it and Ops/CS. */
        .kb-sec--mkt      { left: 11.04%;    top: 32.68%; animation: kbPulseSec_Mkt    18s linear infinite; } /* card3, cx 70  cy 200 */
        .kb-sec--sales    { left: 21.46%; top: 44.29%; }                                                   /* steady, cx 120 cy 265 */
        .kb-sec--eng      { left: 81.88%; top: 32.68%; animation: kbPulseSec_Eng    18s linear infinite; } /* card2, cx 410 cy 200 */
        .kb-sec--prod     { left: 71.46%; top: 44.29%; }                                                   /* steady, cx 360 cy 265 */
        /* Ops halo (5) — Analytics upper-left, SOPs left, Compliance lower-left, Contracts
           south (pulled in), HR Policies inner-right between Ops and the centre. */
        .kb-sec--analytics { left: 4.79%;  top: 45.18%; }                                                  /* steady, cx 40  cy 270 */
        .kb-sec--sop      { left: 4.79%;  top: 61.25%; animation: kbPulseSec_Sop    18s linear infinite; } /* card4, cx 40  cy 360 */
        .kb-sec--comp     { left: 13.12%; top: 75.54%; }                                                   /* steady, cx 80  cy 440 */
        .kb-sec--contracts { left: 31.87%; top: 79.11%; }                                                  /* steady, cx 170 cy 460 (was 485 — pulled up 25) */
        .kb-sec--hr       { left: 41.25%; top: 67.5%; animation: kbPulseSec_Hr     18s linear infinite; } /* card1, cx 215 cy 395 (pulled toward centre + up to clear Contracts) */
        /* CS halo (5) — mirror of Ops on the right. */
        .kb-sec--roadmap  { left: 88.12%; top: 45.18%; }                                                   /* steady, cx 440 cy 270 */
        .kb-sec--supp     { left: 88.12%; top: 61.25%; animation: kbPulseSec_Supp   18s linear infinite; } /* card6, cx 440 cy 360 */
        .kb-sec--client   { left: 79.79%; top: 75.54%; animation: kbPulseSec_Client 18s linear infinite; } /* card5, cx 400 cy 440 */
        .kb-sec--onboard  { left: 61.04%;    top: 79.11%; }                                                   /* steady, cx 310 cy 460 (was 485 — pulled up 25) */
        .kb-sec--meeting  { left: 51.67%; top: 67.5%; }                                                   /* steady, cx 265 cy 395 (mirror of HR — toward centre + up) */

        /* Per-secondary pulse keyframes. The leaf's own background and icon colour STAY at their
           steady styling at all times (light teal background, dark teal icon) so the icon remains
           legible — receiving is signalled with scale + a coloured outer glow only. The glow
           colour matches the owning primary (teal for KH leaves, blue for Ops, orange for CS). */
        /* Leaf peak times (cascade tail end):
              KH-direct cards (2, 3): T_card + 1%
              Two-hop cards (1, 4, 5, 6): T_card + 2%
           Card 6's leaf wraps the loop — its peak lands at 0.33% (was 100.33% before wrap). */
        @keyframes kbPulseSec_Mkt    { /* card 3 KH-direct, peak at 49.33% (T+1%) */
            0%, 48.83%, 51.33%, 100% { transform: scale(1);    box-shadow: 0 2px 6px rgba(15,23,42,.10); }
            49.33%                    { transform: scale(1.18); box-shadow: 0 0 0 4px rgba(32,121,111,.35), 0 4px 16px rgba(32,121,111,.55); }
            50.5%                     { transform: scale(1.06); box-shadow: 0 0 0 2px rgba(32,121,111,.18), 0 2px 10px rgba(32,121,111,.30); }
        }
        @keyframes kbPulseSec_Eng    { /* card 2 KH-direct, peak at 32.67% (T+1%) */
            0%, 32.17%, 34.67%, 100% { transform: scale(1);    box-shadow: 0 2px 6px rgba(15,23,42,.10); }
            32.67%                    { transform: scale(1.18); box-shadow: 0 0 0 4px rgba(32,121,111,.35), 0 4px 16px rgba(32,121,111,.55); }
            33.83%                    { transform: scale(1.06); box-shadow: 0 0 0 2px rgba(32,121,111,.18), 0 2px 10px rgba(32,121,111,.30); }
        }
        @keyframes kbPulseSec_Sop    { /* card 4 via Ops, peak at 67% (T+2%) */
            0%, 66.5%, 69%, 100%     { transform: scale(1);    box-shadow: 0 2px 6px rgba(15,23,42,.10); }
            67%                       { transform: scale(1.18); box-shadow: 0 0 0 4px rgba(37,99,235,.35),  0 4px 16px rgba(37,99,235,.55); }
            68.17%                    { transform: scale(1.06); box-shadow: 0 0 0 2px rgba(37,99,235,.18),  0 2px 10px rgba(37,99,235,.30); }
        }
        @keyframes kbPulseSec_Hr     { /* card 1 via Ops, peak at 17% (T+2%) */
            0%, 16.5%, 19%, 100%     { transform: scale(1);    box-shadow: 0 2px 6px rgba(15,23,42,.10); }
            17%                       { transform: scale(1.18); box-shadow: 0 0 0 4px rgba(37,99,235,.35),  0 4px 16px rgba(37,99,235,.55); }
            18.17%                    { transform: scale(1.06); box-shadow: 0 0 0 2px rgba(37,99,235,.18),  0 2px 10px rgba(37,99,235,.30); }
        }
        @keyframes kbPulseSec_Supp   { /* card 6 via CS, peak wraps to 0.33% (was 100.33%) */
            0%, 1.5%, 99.83%, 100%  { transform: scale(1);    box-shadow: 0 2px 6px rgba(15,23,42,.10); }
            0.33%                    { transform: scale(1.18); box-shadow: 0 0 0 4px rgba(234,88,12,.35), 0 4px 16px rgba(234,88,12,.55); }
            1%                       { transform: scale(1.06); box-shadow: 0 0 0 2px rgba(234,88,12,.18), 0 2px 10px rgba(234,88,12,.30); }
        }
        @keyframes kbPulseSec_Client { /* card 5 via CS, peak at 83.67% (T+2%) */
            0%, 83.17%, 85.67%, 100% { transform: scale(1);    box-shadow: 0 2px 6px rgba(15,23,42,.10); }
            83.67%                    { transform: scale(1.18); box-shadow: 0 0 0 4px rgba(234,88,12,.35), 0 4px 16px rgba(234,88,12,.55); }
            84.83%                    { transform: scale(1.06); box-shadow: 0 0 0 2px rgba(234,88,12,.18), 0 2px 10px rgba(234,88,12,.30); }
        }

        /* Cards drop in front of the leaves and behind the Knowledge Hub primary so they appear
           absorbed by KH on landing. */
        .funnel.kb-stage .funnel__card { z-index: 3; }
        .funnel.kb-stage .kb-pri--kh { z-index: 4; }
