/* OmniSentient — How It Works
   Three-step audit-trail explainer that immediately follows the hero.
   Static, visual-first, reuses existing .page-section / .steps-grid /
   .step-card tokens defined in index.html's extra_head. */

/* ── Section header ─────────────────────────────────────────────────── */
.how-it-works .text-center {
    max-width: 56rem;
    margin: 0 auto clamp(8px, 1vw, 16px);
    text-align: center;
}

.how-it-works .how-bridge {
    font-size: clamp(0.95rem, 0.82rem + 0.35vw, 1.12rem);
    line-height: 1.6;
    color: var(--text-muted);
    max-width: 56ch;
    margin: clamp(10px, 1.2vw, 18px) auto 0;
}

/* ── Grid layout ────────────────────────────────────────────────────── */
.how-it-works .how-steps {
    list-style: none;
    padding: 0;
    margin: clamp(32px, 4vw, 56px) 0 0;
}

.how-it-works .how-card {
    display: flex;
    flex-direction: column;
}

.how-it-works .how-card .step-number { margin-bottom: 16px; }
.how-it-works .how-card .step-title  { margin: 0; }
.how-it-works .how-card .step-desc {
    margin: 8px 0 0;
    min-height: 4.5em;
}

/* ── Color-coded step labels ────────────────────────────────────────── */
.step-card--detect .step-number  { color: #f97316; }
.step-card--explain .step-number { color: #22d3ee; }
.step-card--remediate .step-number { color: #22c55e; }

/* ── Status dots ────────────────────────────────────────────────────── */
.sv-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    display: inline-block;
    flex-shrink: 0;
}
.sv-dot--red    { background: #ef4444; box-shadow: 0 0 6px #ef4444; }
.sv-dot--orange { background: #f97316; box-shadow: 0 0 6px #f97316; }
.sv-dot--cyan   { background: #22d3ee; box-shadow: 0 0 6px #22d3ee; }
.sv-dot--green  { background: #22c55e; box-shadow: 0 0 6px #22c55e; }

/* ── Per-step visual stubs (static representations) ─────────────────── */
.how-stub {
    margin-top: auto;
    padding: 14px 16px;
    border-radius: 8px;
    background: rgba(2, 6, 23, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.06);
    font-family: var(--font-mono);
    font-size: clamp(0.7rem, 0.62rem + 0.15vw, 0.78rem);
    line-height: 1.6;
    color: var(--text-muted);
}

/* ── DETECT — terminal log ──────────────────────────────────────────── */
.how-stub-terminal .how-stub-line {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.how-stub-terminal .how-stub-line.is-fail {
    color: #ef4444;
    font-weight: 600;
}
.how-stub-terminal .is-frame {
    color: #fef08a;
    padding-left: 8px;
    border-left: 2px solid #ef4444;
    margin-top: 6px;
}
.how-stub-alert {
    color: #f97316;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid rgba(255, 255, 255, 0.05);
    font-size: 0.72rem;
}

/* ── EXPLAIN — analysis card rows ───────────────────────────────────── */
.how-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px 0;
}
.how-row + .how-row {
    border-top: 1px solid rgba(255, 255, 255, 0.04);
}
.how-label {
    color: #64748b;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.how-value {
    color: var(--text-strong);
    font-weight: 600;
    text-align: right;
    font-size: 0.75rem;
}
.how-value--high { color: #f97316; }
.how-value--cyan { color: #22d3ee; }

/* ── REMEDIATE — PR preview ─────────────────────────────────────────── */
.how-stub-pr-header {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 10px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    margin-bottom: 10px;
}
.how-stub-pr-badge {
    font-weight: 700;
    color: #22c55e;
    background: rgba(34, 197, 94, 0.12);
    border: 1px solid rgba(34, 197, 94, 0.30);
    padding: 2px 8px;
    border-radius: 20px;
    font-size: 0.65rem;
    letter-spacing: 0.02em;
    white-space: nowrap;
    flex-shrink: 0;
}
.how-stub-pr-meta {
    font-size: 0.7rem;
    color: var(--text-strong);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.how-stub-diff {
    padding: 6px 8px;
    border-radius: 4px;
    background: rgba(0, 0, 0, 0.3);
    border: 1px solid rgba(255, 255, 255, 0.04);
}
.how-stub-diff-line {
    padding: 2px 6px;
    border-radius: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.how-stub-diff-line.is-del { color: #fca5a5; background: rgba(239, 68, 68, 0.08); }
.how-stub-diff-line.is-add { color: #86efac; background: rgba(34, 197, 94, 0.10); }

.how-stub-pr-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 10px;
    padding-top: 8px;
    border-top: 1px solid rgba(255, 255, 255, 0.04);
}
.how-stub-pr-footer .how-stub-pr-meta {
    font-weight: 400;
    color: #64748b;
    font-size: 0.65rem;
}
.how-stub-pr-approve {
    font-size: 0.65rem;
    font-weight: 700;
    padding: 3px 10px;
    border-radius: 4px;
    background: rgba(34, 197, 94, 0.18);
    color: #22c55e;
    border: 1px solid rgba(34, 197, 94, 0.3);
    letter-spacing: 0.02em;
    white-space: nowrap;
}

/* ─────────────────────────────────────────────────────────────────────
   Gamma-style split layout (v4 — refined)
   Left: visual placeholder (image slot, full column height).
   Right: left-aligned header + vertical stack of 3 step cards.
   Cards have subtle filled surface + depth; icons sit in filled pentagons
   colour-matched to each step.
   ───────────────────────────────────────────────────────────────────── */
:root {
    --how-shield-fill: rgba(255, 255, 255, 0.04);
    --how-shield-stroke: rgba(255, 255, 255, 0.12);
}

.how-split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
    gap: clamp(40px, 5.5vw, 96px);
    /* Both columns share a true vertical centre so the header lines up
       against the visual's geometric middle, not its top edge. */
    align-items: center;
}

/* ── LEFT: image slot (placeholder until user adds an illustration) ── */
.how-visual {
    display: flex;
    justify-content: center;
    align-items: center;
}

.how-visual-placeholder {
    width: 100%;
    max-width: 520px;
    aspect-ratio: 4 / 5;
    border: 1px dashed rgba(255, 255, 255, 0.10);
    border-radius: 20px;
    /* Layered atmospheric depth — small foreground blobs + a single
       wider, fainter background wash so the slot reads as 3D space
       (foreground vs background), not a single-plane blur. */
    background:
        radial-gradient(ellipse 60% 40% at 28% 28%, rgba(124, 58, 237, 0.12), transparent 55%),
        radial-gradient(ellipse 55% 40% at 72% 72%, rgba(6, 182, 212, 0.09), transparent 55%),
        radial-gradient(ellipse 40% 30% at 50% 50%, rgba(244, 63, 94, 0.05), transparent 60%),
        radial-gradient(ellipse 120% 90% at 50% 50%, rgba(124, 58, 237, 0.04), transparent 75%),
        rgba(255, 255, 255, 0.015);
}

/* ── RIGHT: header + step list (everything left-aligned) ─────────────── */
.how-right-column {
    display: flex;
    flex-direction: column;
    /* More breathing room between header and step list */
    gap: clamp(32px, 3.8vw, 56px);
}

.how-header {
    display: flex;
    flex-direction: column;
    gap: 12px;
    text-align: left;
}

.how-header .section-label {
    margin: 0;
    text-align: left;
}

.how-title {
    /* Editorial weight (500) + softer kerning (-0.018 → -0.01) so phrases
       like "Pull Request" breathe instead of looking crammed. Plus
       text-wrap: balance for a clean two-line split. */
    font-size: var(--fs-h2);
    font-weight: 500;
    color: var(--text-strong);
    line-height: 1.22;
    letter-spacing: -0.01em;
    margin: 0;
    max-width: 22ch;
    text-wrap: balance;
}

.how-header .section-label {
    /* Wider tracking on the eyebrow caps for a more institutional feel */
    letter-spacing: 0.16em;
}

.how-bridge {
    font-size: clamp(0.96rem, 0.86rem + 0.28vw, 1.08rem);
    line-height: 1.6;
    /* Brighter — was 0.62, now 0.72 for better readability without losing
       hierarchy against the title */
    color: rgba(255, 255, 255, 0.72);
    margin: 0;
    max-width: 44ch;
}

/* ── Vertical step list (ol/li) ─────────────────────────────────────── */
.how-steps-v3 {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    /* 24px — slightly more vertical rhythm for a premium SaaS feel */
    gap: 24px;
    position: relative;
}

/* No flow line — the numbered labels (01/02/03) already establish the
   sequence; a dashed connector was adding visual noise without adding
   information. Card-to-card vertical rhythm carries the flow on its own. */

/* ── Step card — proper component with depth, not just an outlined div ── */
.how-step-row {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: 60px 1fr;
    gap: 20px;
    align-items: center;
    padding: 20px 24px 20px 20px;
    /* Restrained surface — single soft gradient over a faint base. Matte
       glass, not glossy. */
    background:
        linear-gradient(180deg, rgba(255, 255, 255, 0.028), rgba(255, 255, 255, 0.008)),
        rgba(10, 10, 31, 0.35);
    border: 1px solid rgba(255, 255, 255, 0.07);
    border-radius: 14px;
    /* Two-layer shadow: 1px hairline ring for edge definition (cards no
       longer feel "cut out" of the section) + soft drop for grounding. */
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.035),
        0 8px 24px rgba(0, 0, 0, 0.22);
    transition:
        background 220ms ease,
        border-color 220ms ease,
        transform 220ms ease,
        box-shadow 220ms ease;
}

.how-step-row:hover {
    background:
        linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.015)),
        rgba(10, 10, 31, 0.45);
    border-color: rgba(255, 255, 255, 0.12);
    transform: translateY(-2px);
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.06),
        0 14px 32px -10px rgba(0, 0, 0, 0.5);
}

/* Per-step accent — softer stroke (0.20 → 0.12) so the shield no longer
   reads as an outlined badge. Fill stays at the higher density (0.18) so
   the icon container clearly belongs with its step's colour theme. */
.how-card--detect    { --how-shield-fill: rgba(249, 115, 22, 0.18); --how-shield-stroke: rgba(253, 186, 116, 0.12); }
.how-card--explain   { --how-shield-fill: rgba(34, 211, 238, 0.18); --how-shield-stroke: rgba(103, 232, 249, 0.12); }
.how-card--remediate { --how-shield-fill: rgba(34, 197, 94, 0.18);  --how-shield-stroke: rgba(134, 239, 172, 0.12); }

/* ── Shield-shaped pentagon icon container ─────────────────────────── */
.how-shield {
    position: relative;
    width: 60px;
    height: 64px;
    flex-shrink: 0;
    /* Soft shadow + -2px nudge: optically aligns the shield centre with
       the title baseline (icons rendered geometrically always feel a
       touch low against text — designers shift them up to compensate). */
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.18));
    transform: translateY(-2px);
}

.how-shield svg {
    width: 100%;
    height: 100%;
    display: block;
    transition: filter 220ms ease;
}

.how-shield-icon {
    position: absolute;
    /* Pentagon body centre is at y=39 in the 64px box. Top:14 lands the
       flex centre at y=(14+64)/2 = 39 → exact body centroid. */
    inset: 14px 0 0 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    line-height: 1;
    color: rgba(255, 255, 255, 0.7);
    transition: color 220ms ease;
    pointer-events: none;
}

.how-card--detect    .how-shield-icon { color: #fdba74; }
.how-card--explain   .how-shield-icon { color: #67e8f9; }
.how-card--remediate .how-shield-icon { color: #86efac; }

/* ── Step content (title + description) ────────────────────────────── */
.how-step-content {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.how-step-title {
    font-size: var(--fs-h3);
    font-weight: 600;
    color: var(--text-strong);
    line-height: 1.3;
    margin: 0;
    letter-spacing: -0.008em;
}

.how-step-desc {
    font-size: var(--fs-body);
    /* Looser leading for premium readability */
    line-height: 1.65;
    color: rgba(255, 255, 255, 0.58);
    margin: 0;
}

/* ── Responsive ─────────────────────────────────────────────────────── */
@media (max-width: 1024px) {
    .how-split {
        grid-template-columns: 1fr;
        gap: 56px;
    }
    .how-visual-placeholder { max-width: 480px; aspect-ratio: 16 / 10; }
    .how-right-column { justify-content: flex-start; }
}

@media (max-width: 520px) {
    .how-step-row {
        grid-template-columns: 52px 1fr;
        gap: 14px;
        padding: 16px;
    }
    .how-shield { width: 52px; height: 56px; }
    .how-shield-icon { inset: 12px 0 0 0; font-size: 1.35rem; }
}

/* ── Section exit — closing statement + CTA ─────────────────────────── */
.how-exit {
    margin-top: clamp(48px, 5vw, 80px);
    text-align: center;
}

.how-exit-headline {
    font-size: clamp(1.2rem, 0.95rem + 0.8vw, 1.7rem);
    font-weight: 700;
    color: var(--text-strong);
    letter-spacing: -0.015em;
    line-height: 1.25;
    margin: 0;
    max-width: 32ch;
    margin-left: auto;
    margin-right: auto;
}

.how-exit-sub {
    font-size: clamp(0.95rem, 0.85rem + 0.3vw, 1.1rem);
    color: var(--text-muted);
    line-height: 1.5;
    max-width: 48ch;
    margin: 12px auto 0;
}

.how-exit-actions {
    margin-top: clamp(20px, 2.2vw, 28px);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
}

.how-exit-cta {
    padding: clamp(11px, 1vw, 16px) clamp(22px, 2.4vw, 38px);
    font-size: clamp(0.9rem, 0.7rem + 0.25vw, 1.05rem);
}

.how-exit-microcopy {
    font-size: 0.78rem;
    color: var(--text-muted);
    margin: 0;
    letter-spacing: 0.01em;
    opacity: 0.85;
}

/* ── Proof strip ────────────────────────────────────────────────────── */
.how-proof-strip {
    margin-top: clamp(36px, 4vw, 56px);
    padding-top: clamp(24px, 2.6vw, 32px);
    border-top: 1px solid var(--border-subtle);
    display: flex;
    justify-content: center;
    gap: clamp(20px, 3vw, 48px);
    flex-wrap: wrap;
}

.how-proof-item {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-size: 0.85rem;
    color: var(--text-muted);
    text-decoration: none;
    transition: color 0.2s ease;
    letter-spacing: 0.01em;
}

.how-proof-item:hover,
.how-proof-item:focus-visible {
    color: var(--text-strong);
}

.how-proof-item i {
    font-size: 0.85rem;
    color: #c4b5fd;
    width: 14px;
    text-align: center;
}

.how-proof-arrow {
    opacity: 0.5;
    transition: transform 0.2s ease, opacity 0.2s ease;
    display: inline-block;
}

.how-proof-item:hover .how-proof-arrow,
.how-proof-item:focus-visible .how-proof-arrow {
    opacity: 1;
    transform: translateX(3px);
}

/* ── Responsive ─────────────────────────────────────────────────────── */
@media (max-width: 880px) {
    .how-it-works .how-steps {
        grid-template-columns: 1fr;
    }
    .how-it-works .how-card .step-desc { min-height: 0; }
}

@media (max-width: 720px) {
    .how-proof-strip {
        flex-direction: column;
        gap: 14px;
        align-items: center;
    }
}

/* ─────────────────────────────────────────────────────────────────────
   HOW IT WORKS — LEFT VISUAL · cinematic 3-phase loop
   State machine in landing-how-loop.js drives data-phase attribute on
   .how-loop. Each phase block reads [data-phase="..."] and toggles
   visibility / animations via opacity + transform (GPU-cheap).
   ───────────────────────────────────────────────────────────────────── */
.how-loop {
    position: relative;
    width: 100%;
    max-width: 520px;
    aspect-ratio: 4 / 5;
    border-radius: 20px;
    overflow: hidden;
    background:
        radial-gradient(ellipse 120% 90% at 50% 50%, rgba(124, 58, 237, 0.06), transparent 75%),
        rgba(8, 10, 24, 0.65);
    /* 2px border + outline (2px outer at 4px offset).
       Phase rules set border-color / outline-color / box-shadow halo.
       Sanity-tested with magenta — pipeline confirmed working. */
    border: 2px solid rgba(255, 255, 255, 0.08);
    outline: 2px solid transparent;
    outline-offset: 4px;
    will-change: transform;
    transition: outline-color 800ms cubic-bezier(0.4, 0, 0.2, 1),
                border-color  800ms cubic-bezier(0.4, 0, 0.2, 1);
}

.how-loop-particles {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.how-loop-svg {
    position: relative;
    width: 100%;
    height: 100%;
    display: block;
    z-index: 1;
}

/* ── Background grid — uniform across phases ──────────────────────── */
.how-loop-grid {
    opacity: 0.7;
    transition: opacity 600ms ease;
}

/* ── Caption ──────────────────────────────────────────────────────── */
.how-loop-caption {
    position: absolute;
    /* Lifted 22px → 44px so it's solidly inside the visible area, never
       clipped at the box edge. */
    bottom: 44px;
    left: 0;
    right: 0;
    text-align: center;
    z-index: 4;                                /* above ::after vignette */
    pointer-events: none;
}

.how-loop-caption-title {
    display: inline-block;
    font-family: var(--font-mono, ui-monospace, monospace);
    /* Bumped 0.72 → 0.82rem for readability — still mono micro-type feel */
    font-size: 0.82rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    color: #f9fafb;
    padding: 8px 18px;
    border-radius: 6px;
    /* Denser pill bg + thicker border so caption clearly sits on top of
       whatever phase visuals are happening behind it. */
    background: rgba(8, 10, 22, 0.85);
    border: 1px solid rgba(255, 255, 255, 0.14);
    min-height: 1em;
    transition: color 280ms ease, border-color 280ms ease;
}

.how-loop-caption-sub {
    margin-top: 8px;
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 0.65rem;
    color: rgba(255, 255, 255, 0.45);
    letter-spacing: 0.06em;
    transition: color 280ms ease;
}

[data-phase="detect"]    .how-loop-caption-title { color: #ff7a7a; border-color: rgba(255, 59, 59, 0.30); }
[data-phase="explain"]   .how-loop-caption-title { color: #67e8f9; border-color: rgba(45, 212, 191, 0.30); }
[data-phase="remediate"] .how-loop-caption-title { color: #86efac; border-color: rgba(34, 197, 94, 0.35); }

/* ── PHASE 1: DETECT — heartbeat pulse + chromatic flicker ─────────── */
@keyframes howHeartbeat {
    0%, 100% { transform: scale(1); opacity: 0.85; }
    20%      { transform: scale(1.18); opacity: 1; }
    35%      { transform: scale(0.95); opacity: 0.7; }
    50%      { transform: scale(1.10); opacity: 0.95; }
}
@keyframes howPulseRing {
    0%   { transform: scale(1);   opacity: 0.7; }
    100% { transform: scale(2.6); opacity: 0; }
}
@keyframes howCompress {
    0%, 100% { transform: scale(1); opacity: 0.6; }
    50%      { transform: scale(1.04); opacity: 0.9; }
}

.how-loop-core--red {
    opacity: 0;
    transform-origin: 200px 240px;
    transition: opacity 350ms ease;
}
.how-loop-core--green {
    opacity: 0;
    transform-origin: 200px 240px;
    transition: opacity 350ms ease;
}

[data-phase="detect"] .how-loop-core--red {
    opacity: 1;
    animation: howHeartbeat 1.1s ease-in-out infinite;
}
[data-phase="detect"] .how-loop-pulse-outer {
    /* Desync: different duration + curve + negative phase offset
       so the ring never re-syncs visibly against the 1.4s heartbeat. */
    animation: howPulseRing 1.52s cubic-bezier(0.22, 1, 0.36, 1) infinite;
    animation-delay: -0.3s;
    transform-origin: 200px 240px;
}
[data-phase="detect"] .how-loop-compress {
    animation: howCompress 1.2s ease-in-out infinite;
    transform-origin: 200px 240px;
}

/* ── PHASE 2: EXPLAIN — scanning sweep + hex fragments visible ────── */
.how-loop-scan,
.how-loop-streams,
.how-loop-hex {
    opacity: 0;
    transition: opacity 350ms ease;
}

@keyframes howScanRotate {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

[data-phase="explain"] .how-loop-scan,
[data-phase="explain"] .how-loop-streams {
    opacity: 1;
}
[data-phase="explain"] .how-loop-hex { opacity: 1; }
[data-phase="explain"] .how-loop-scan-sweep {
    transform-origin: 200px 240px;
    animation: howScanRotate 2.4s linear infinite;
}
[data-phase="explain"] .how-loop-streams line {
    stroke-dasharray: 6 8;
    animation: howStreamFlow 1.4s linear infinite;
}
@keyframes howStreamFlow {
    from { stroke-dashoffset: 0;  }
    to   { stroke-dashoffset: -28; }
}

/* ── PHASE 3: REMEDIATE — green core + shockwave + grid pulse ────── */
@keyframes howGreenOvershoot {
    0%   { transform: scale(0.6); opacity: 0; }
    50%  { transform: scale(1.20); opacity: 1; }
    100% { transform: scale(1.00); opacity: 1; }
}
@keyframes howShockwave {
    0%   { r: 40;  opacity: 0.85; stroke-width: 3; }
    100% { r: 180; opacity: 0;    stroke-width: 1; }
}
@keyframes howGridFlash {
    0%, 100% { opacity: 0.7; }
    20%      { opacity: 1; }
}

[data-phase="remediate"] .how-loop-core--green {
    opacity: 1;
    transform-origin: 200px 240px;
    animation: howGreenOvershoot 700ms cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
[data-phase="remediate"] .how-loop-shockwave {
    animation: howShockwave 900ms ease-out forwards;
}
[data-phase="remediate"] .how-loop-grid {
    animation: howGridFlash 1s ease-in-out forwards;
}

/* ── Reduced motion — single static "remediate" frame ─────────────── */
@media (prefers-reduced-motion: reduce) {
    .how-loop * {
        animation: none !important;
        transition: none !important;
    }
    .how-loop-core--green { opacity: 1; }
}

/* ── Responsive — tighter on smaller screens ──────────────────────── */
@media (max-width: 720px) {
    .how-loop {
        max-width: 420px;
        aspect-ratio: 1 / 1;
    }
    .how-loop-caption-title { font-size: 0.68rem; }
}

/* ─────────────────────────────────────────────────────────────────────
   HOW IT WORKS LOOP · v2 polish — controlled imperfection + bridges
   Overrides + additions to the v1 loop styles defined above.
   ───────────────────────────────────────────────────────────────────── */

/* ── Background drift — slow gradient pan for ambient motion ──────── */
@keyframes howBgDrift {
    0%   { background-position: 0% 0%,   0% 0%; }
    50%  { background-position: 100% 50%, 50% 100%; }
    100% { background-position: 0% 0%,   0% 0%; }
}
.how-loop {
    background:
        radial-gradient(ellipse 120% 90% at 50% 50%, rgba(124, 58, 237, 0.05), transparent 70%),
        radial-gradient(ellipse 80% 60% at 30% 70%, rgba(45, 212, 191, 0.03), transparent 75%),
        rgba(8, 10, 22, 0.94);                          /* dense panel — solid, not glass */
    background-size: 220% 220%, 180% 180%, 100% 100%;
    animation: howBgDrift 24s ease-in-out infinite;
    will-change: transform;
    /* ── ENCLOSURE WEIGHT — base grounding for all phases ──────────────
       Layered drop shadow gives mass: lower offset = sits in space,
       wider blur = heavier feel. White-bezel rim creates bg separation
       without colour. These are CONSTANT across phases; phase shadows
       below only add subtle colour tinting on top. */
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.035),           /* outer bezel rim */
        0 24px 56px -20px rgba(0, 0, 0, 0.60),          /* deep ground shadow */
        0 8px 16px -8px rgba(0, 0, 0, 0.35);            /* near gravity shadow */
}

/* ── PHASE 1: DETECT — uneven heartbeat (asymmetric keyframes) ────── */
@keyframes howHeartbeat {
    /* Irregular rhythm: quick double-tap then pause */
    0%   { transform: translate3d(0, 0, 0) scale(1.00); opacity: 0.85; }
    8%   { transform: translate3d(0.5px, -0.5px, 0) scale(1.22); opacity: 1; }
    14%  { transform: translate3d(0, 0, 0) scale(0.94); opacity: 0.72; }
    22%  { transform: translate3d(-0.5px, 0.3px, 0) scale(1.15); opacity: 0.96; }
    32%  { transform: translate3d(0, 0, 0) scale(1.00); opacity: 0.88; }
    100% { transform: translate3d(0, 0, 0) scale(1.00); opacity: 0.85; }
}
[data-phase="detect"] .how-loop-core--red {
    opacity: 1;
    transform-origin: 200px 240px;
    animation: howHeartbeat 1.4s ease-in-out infinite;
}

/* ── Glitch ticks — flicker briefly + asymmetrically ──────────────── */
@keyframes howGlitch1 {
    0%, 100% { opacity: 0; }
    5%       { opacity: 0.9; }
    8%       { opacity: 0; }
    52%      { opacity: 0.7; }
    54%      { opacity: 0; }
}
@keyframes howGlitch2 {
    0%, 100% { opacity: 0; }
    18%      { opacity: 0.8; }
    21%      { opacity: 0; }
    68%      { opacity: 0.5; }
    71%      { opacity: 0; }
}
@keyframes howGlitch3 {
    0%, 100% { opacity: 0; }
    36%      { opacity: 0.85; }
    40%      { opacity: 0; }
    82%      { opacity: 0.6; }
    85%      { opacity: 0; }
}
[data-phase="detect"] .how-loop-glitch { opacity: 1; }
[data-phase="detect"] .how-loop-glitch-line-1 { animation: howGlitch1 2.1s linear infinite; }
[data-phase="detect"] .how-loop-glitch-line-2 { animation: howGlitch2 1.7s linear infinite; }
[data-phase="detect"] .how-loop-glitch-line-3 { animation: howGlitch3 2.4s linear infinite; }

/* ── BRIDGE 1: inward pull before fragmentation (180ms) ───────────── */
@keyframes howInwardPull {
    0%   { transform: scale(1.00); opacity: 1; }
    100% { transform: scale(0.4); opacity: 0; }
}
[data-phase="bridge-1"] .how-loop-core--red {
    transform-origin: 200px 240px;
    animation: howInwardPull 180ms cubic-bezier(0.7, 0, 0.84, 0) forwards;
    opacity: 1;
}
[data-phase="bridge-1"] .how-loop-glitch { opacity: 0; }

/* ── PHASE 2: EXPLAIN — staggered streams + radar with falloff trail */
[data-phase="explain"] .how-loop-streams line,
[data-phase="bridge-2"] .how-loop-streams line { opacity: 1; }

/* Stagger each stream line's flow timing — break the synced look */
[data-phase="explain"] .how-loop-streams line:nth-child(1) { animation: howStreamFlow 1.4s linear infinite; }
[data-phase="explain"] .how-loop-streams line:nth-child(2) { animation: howStreamFlow 1.7s linear infinite 0.2s; }
[data-phase="explain"] .how-loop-streams line:nth-child(3) { animation: howStreamFlow 1.9s linear infinite 0.45s; }
[data-phase="explain"] .how-loop-streams line:nth-child(4) { animation: howStreamFlow 1.5s linear infinite 0.7s; }

/* Radar sweep — opacity falloff trail (additional path follows behind) */
[data-phase="explain"] .how-loop-scan-sweep {
    transform-origin: 200px 240px;
    animation: howScanRotate 2.4s linear infinite;
    filter: drop-shadow(0 0 6px rgba(45, 212, 191, 0.35));
}

/* ── BRIDGE 2: tension hold (150ms) — freeze + slight dim ─────────── */
@keyframes howTensionHold {
    0%, 100% { opacity: 0.7; filter: brightness(1); }
    50%      { opacity: 0.85; filter: brightness(0.85); }
}
[data-phase="bridge-2"] .how-loop-scan,
[data-phase="bridge-2"] .how-loop-streams,
[data-phase="bridge-2"] .how-loop-hex {
    opacity: 1;
    animation: howTensionHold 150ms ease-in-out;
}

/* ── PHASE 3: REMEDIATE — aggressive collapse + dual blurred shockwave */
@keyframes howGreenOvershoot {
    /* Brightness/saturate spike at 35% (≈180ms peak window). saturate
       prevents the over-bright frame from going washed-white. */
    0%   { transform: scale(0.4);  opacity: 0; filter: brightness(0.6)  saturate(1.0); }
    35%  { transform: scale(1.35); opacity: 1; filter: brightness(1.4)  saturate(1.1); }
    45%  { transform: scale(1.30); opacity: 1; filter: brightness(1.3)  saturate(1.08); }
    70%  { transform: scale(0.92); opacity: 1; filter: brightness(1.0)  saturate(1.0); }
    100% { transform: scale(1.00); opacity: 1; filter: brightness(1.0)  saturate(1.0); }
}
/* After overshoot ends — micro settle so mass feels physical, not snapped */
@keyframes howGreenSettle {
    0%   { transform: scale(1.00); }
    60%  { transform: scale(0.985); }
    100% { transform: scale(1.00); }
}
[data-phase="remediate"] .how-loop-core--green {
    opacity: 1;
    transform-origin: 200px 240px;
    /* Chain: aggressive overshoot, then mass-settle micro-bounce */
    animation:
        howGreenOvershoot 520ms cubic-bezier(0.34, 1.8, 0.64, 1) forwards,
        howGreenSettle    600ms ease-out 520ms forwards;
}

/* Energy swirl — rotating dashed ring inside green core */
@keyframes howEnergySwirl {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
[data-phase="remediate"] .how-loop-energy-swirl {
    opacity: 0.85;
    transform-origin: 200px 240px;
    animation: howEnergySwirl 1.8s linear infinite;
}

/* Primary shockwave — fast initial expansion, tight decay (impact feel) */
@keyframes howShockwave1 {
    0%   { r: 40;  opacity: 0;    stroke-width: 3; }
    10%  { r: 62;  opacity: 1;    stroke-width: 3; }
    60%  { r: 140; opacity: 0.2;  stroke-width: 1.5; }
    100% { r: 220; opacity: 0;    stroke-width: 0.5; }
}
[data-phase="remediate"] .how-loop-shockwave--1 {
    animation: howShockwave1 900ms cubic-bezier(0.1, 0.85, 0.25, 1) forwards;
    filter: blur(0.6px);
}

/* Secondary echo shockwave — ghostlier, delayed, thinner */
@keyframes howShockwave2 {
    0%   { r: 40;  opacity: 0;    stroke-width: 1; }
    15%  { r: 52;  opacity: 0.35; stroke-width: 1; }
    100% { r: 240; opacity: 0;    stroke-width: 0.5; }
}
[data-phase="remediate"] .how-loop-shockwave--2 {
    animation: howShockwave2 1100ms cubic-bezier(0.1, 0.85, 0.25, 1) 200ms forwards;
    filter: blur(2px);
}

/* Grid flash — accentuated for hero moment */
@keyframes howGridFlash {
    0%, 100% { opacity: 0.7; }
    15%      { opacity: 1; }
    35%      { opacity: 0.85; }
}
[data-phase="remediate"] .how-loop-grid {
    animation: howGridFlash 900ms ease-in-out forwards;
}

/* Scene-wide reactive pulse — whole SVG dips slightly (synced with shockwave).
   Applied to .how-loop-svg, not .how-loop, to avoid clashing with the JS
   transform on .how-loop (parallax drift + breathing). */
@keyframes howScenePulse {
    0%   { transform: scale(1.000); }
    30%  { transform: scale(0.978); }
    100% { transform: scale(1.000); }
}
[data-phase="remediate"] .how-loop-svg {
    transform-origin: 50% 50%;
    animation: howScenePulse 900ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* ── Reduced motion override — kill all animations, static remediate */
@media (prefers-reduced-motion: reduce) {
    .how-loop,
    .how-loop * {
        animation: none !important;
        transition: none !important;
    }
    .how-loop { background: rgba(8, 10, 24, 0.7); }
    .how-loop-core--green { opacity: 1; }
}

/* ─────────────────────────────────────────────────────────────────────
   HOW-LOOP · REACTIVE SURFACE SYSTEM (v3)
   The container itself behaves like a system surface — phase-tinted
   ambient glow, edge depth/bezel highlight, border response, and
   subtle per-phase character motion. All driven by [data-phase].

   Layer model (z-order):
       ::before  z=0  ambient glow (phase-coloured radial wash)
       canvas    z=1  particle field
       svg/cap   z=2  core, scans, captions
       ::after   z=3  vignette + bezel highlight overlay

   No clash with JS — JS controls .how-loop transform (drift + breathing);
   CSS surface effects use ::before / ::after / .how-loop-svg only.
   ───────────────────────────────────────────────────────────────────── */

/* ── Surface layer 1: ambient glow (under everything) ───────────────── */
.how-loop::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 0;
    /* Phase-coloured radial — re-tints via phase selectors below */
    background: radial-gradient(
        ellipse 80% 60% at 50% 45%,
        rgba(124, 58, 237, 0.05),
        transparent 70%
    );
    opacity: 0.6;
    transition: background 600ms cubic-bezier(0.4, 0, 0.2, 1),
                opacity    600ms ease;
}

/* ── Surface layer 4: bezel highlight + vignette (over everything) ────
   This layer carries the "thickness" illusion of the enclosure:
   bright 1px line at top = light catching a bevel, dark 1px at bottom
   = gravity/weight, deep inset vignette = energy pushed inward (the
   container is HOLDING something, not displaying it). */
.how-loop::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 3;
    box-shadow:
        /* Inner edge highlight — 1px line just inside the border. Bumped
           0.05 → 0.09 so the "thick / physical enclosure" reads visibly. */
        inset 0 0 0 1px rgba(255, 255, 255, 0.09),
        inset 0 1px 0 rgba(255, 255, 255, 0.10),     /* top bevel highlight */
        inset 0 -1px 0 rgba(0, 0, 0, 0.40),          /* bottom weight */
        inset 0 0 120px rgba(0, 0, 0, 0.45);         /* inward vignette */
    transition: box-shadow 800ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* Stack children: canvas behind SVG, both above ambient glow */
.how-loop > .how-loop-particles { position: absolute; z-index: 1; }
.how-loop > .how-loop-svg       { position: relative; z-index: 2; }
.how-loop > .how-loop-caption   { position: absolute; z-index: 2; }

/* ── PHASE: DETECT — Option B: ONE crisp line + ONE soft halo ─────── */
[data-phase="detect"] .how-loop {
    outline: 3px solid rgba(255, 60, 60, 1) !important;
    outline-offset: 0 !important;
    box-shadow:
        0 0 24px rgba(255, 60, 60, 0.25),           /* single soft halo */
        0 20px 40px -12px rgba(0, 0, 0, 0.50) !important;  /* subtle drop shadow */
}
[data-phase="detect"] .how-loop::before {
    opacity: 1;
    background: radial-gradient(
        ellipse 80% 60% at 38% 42%,                     /* off-centre = unstable */
        rgba(255, 59, 59, 0.12),
        rgba(124, 58, 237, 0.04) 40%,
        transparent 70%
    );
}
[data-phase="detect"] .how-loop::after {
    box-shadow:
        inset 0 1px 0 rgba(255, 120, 120, 0.05),
        inset 0 -1px 0 rgba(0, 0, 0, 0.30),
        inset 0 0 100px rgba(40, 0, 0, 0.40);
}

/* ── BRIDGE-1: warming transition (red → cyan) ───────────────────────── */
[data-phase="bridge-1"] .how-loop {
    border-color: rgba(180, 100, 100, 0.14);
    box-shadow: 0 8px 32px -8px rgba(150, 70, 70, 0.08);
}
[data-phase="bridge-1"] .how-loop::before {
    opacity: 0.85;
    background: radial-gradient(
        ellipse 70% 50% at 50% 45%,
        rgba(180, 100, 100, 0.08),
        transparent 70%
    );
}

/* ── PHASE: EXPLAIN — Option B: ONE crisp line + ONE soft halo ────── */
[data-phase="explain"] .how-loop {
    outline: 3px solid rgba(45, 212, 191, 1) !important;
    outline-offset: 0 !important;
    box-shadow:
        0 0 24px rgba(45, 212, 191, 0.25),
        0 20px 40px -12px rgba(0, 0, 0, 0.50) !important;
}
[data-phase="explain"] .how-loop::before {
    opacity: 1;
    background: radial-gradient(
        ellipse 90% 70% at 58% 50%,                     /* right-biased = directional */
        rgba(45, 212, 191, 0.09),
        rgba(103, 232, 249, 0.04) 45%,
        transparent 75%
    );
}
[data-phase="explain"] .how-loop::after {
    box-shadow:
        inset 0 1px 0 rgba(103, 232, 249, 0.06),
        inset 0 -1px 0 rgba(0, 0, 0, 0.30),
        inset 0 0 110px rgba(0, 20, 30, 0.40);
}

/* ── BRIDGE-2: tension hold (cyan → green) ───────────────────────────── */
[data-phase="bridge-2"] .how-loop {
    border-color: rgba(103, 232, 249, 0.12);
    box-shadow: 0 8px 32px -8px rgba(80, 150, 150, 0.08);
}
[data-phase="bridge-2"] .how-loop::before {
    opacity: 0.85;
    background: radial-gradient(
        ellipse 70% 50% at 50% 50%,
        rgba(80, 150, 150, 0.06),
        transparent 70%
    );
}

/* ── PHASE: REMEDIATE — Option B: ONE crisp line + ONE soft halo ──── */
[data-phase="remediate"] .how-loop {
    outline: 3px solid rgba(34, 197, 94, 1) !important;
    outline-offset: 0 !important;
    box-shadow:
        0 0 24px rgba(34, 197, 94, 0.25),
        0 20px 40px -12px rgba(0, 0, 0, 0.50) !important;
}
[data-phase="remediate"] .how-loop::before {
    opacity: 1;
    /* Tighter falloff — ambient stays inside, doesn't reach the edge.
       Was 90% 70% / 40% / 75%; now 70% 55% / 32% / 60% so the wash dies
       well before the boundary — creates inside-vs-edge contrast. */
    background: radial-gradient(
        ellipse 70% 55% at 50% 50%,
        rgba(34, 197, 94, 0.16),
        rgba(45, 212, 191, 0.05) 32%,
        transparent 60%
    );
}
[data-phase="remediate"] .how-loop::after {
    /* CONTAINMENT seal — inner ring is the visible "energy lock", tighter
       inward vignette pushes glow toward the centre (energy held inside,
       not radiating outward). Crucially: bottom shadow strengthens to
       give the enclosure visible "weight" at the base. */
    box-shadow:
        inset 0 0 0 1px rgba(134, 239, 172, 0.35),     /* containment seal ring */
        inset 0 1px 0 rgba(255, 255, 255, 0.06),       /* top bevel light catch */
        inset 0 -1px 0 rgba(0, 0, 0, 0.50),            /* heavy bottom weight */
        inset 0 0 140px rgba(0, 0, 0, 0.55);           /* deep inward vignette */
}

/* ─────────────────────────────────────────────────────────────────────
   Compress ring — DETECT only
   Static SVG element with stroke baked in markup; must explicitly hide
   in non-detect phases (was leaking into explain/remediate as a faint
   red circle, polluting the "system stable" final frame).
   ───────────────────────────────────────────────────────────────────── */
.how-loop-compress {
    opacity: 0;
    transition: opacity 600ms ease;
}
[data-phase="detect"] .how-loop-compress {
    opacity: 1;
}

/* ─────────────────────────────────────────────────────────────────────
   Per-phase character motion on .how-loop-svg
   (not .how-loop — JS already drives .how-loop transform).
   Subtle, never noisy.
   ───────────────────────────────────────────────────────────────────── */

/* Detect — softer, more occasional shudder (every 5s, ±0.2px max) */
@keyframes howSurfaceShudder {
    0%, 97%, 100% { transform: translateX(0); }
    98%           { transform: translateX(-0.2px); }
    99%           { transform: translateX(0.2px); }
}
[data-phase="detect"] .how-loop-svg {
    will-change: transform;
    animation: howSurfaceShudder 5s linear infinite;
}

/* Explain — barely perceptible analytical sway (rotation oscillation) */
@keyframes howSurfaceAnalyze {
    0%   { transform: rotate(-0.15deg); }
    100% { transform: rotate(0.15deg); }
}
[data-phase="explain"] .how-loop-svg {
    will-change: transform;
    animation: howSurfaceAnalyze 6s ease-in-out infinite alternate;
    transform-origin: 50% 50%;
}

/* Remediate already uses howScenePulse (defined earlier) — keep that */

/* ─────────────────────────────────────────────────────────────────────
   v3 INTENSITY LAYER · 5 surgical moves for "dangerous intelligent system"
   1. Glitch burst (Detect) — JS toggles .is-glitching for 100ms
   2. Lock moment (bridge-2) — brightness drops to 0.85, snap back on remediate
   3. Energy compression — handled in JS particle physics (expand → collapse)
   4. Silent impact cue — contrast bump + grid flash spike on green peak
   5. Edge reaction sync — container micro-compresses with shockwave
   ───────────────────────────────────────────────────────────────────── */

/* (1) GLITCH BURST — 100ms shake on .how-loop-svg when .how-loop has
       .is-glitching class. Applied to SVG to avoid clashing with the JS
       transform on .how-loop itself. */
@keyframes howGlitchBurst {
    0%   { transform: translate3d(0, 0, 0); }
    20%  { transform: translate3d(0.9px, -0.5px, 0); }
    40%  { transform: translate3d(-0.7px, 0.4px, 0); }
    60%  { transform: translate3d(0.5px, 0.6px, 0); }
    80%  { transform: translate3d(-0.4px, -0.4px, 0); }
    100% { transform: translate3d(0, 0, 0); }
}
.how-loop.is-glitching .how-loop-svg {
    animation: howGlitchBurst 100ms steps(5) 1;
}

/* (2) LOCK MOMENT — brightness drop on bridge-2 (tension hold) before
       the remediate snap. The transition into remediate then snaps the
       brightness back to 1, which creates the "AI caught it" beat. */
[data-phase="bridge-2"] .how-loop {
    filter: brightness(0.85);
    transition: filter 60ms ease-in;
}
[data-phase="remediate"] .how-loop {
    filter: brightness(1);
    transition: filter 80ms ease-out;
}

/* (4) SILENT IMPACT CUE — extra contrast spike in the brightness peak
       window of the green overshoot (32-38% of 520ms). The eye registers
       this as an "impact" without it being a flash. Augments the existing
       howGreenOvershoot keyframe via a second short-duration animation. */
@keyframes howImpactContrast {
    /* Production tuning — felt without being aggressive. */
    0%   { filter: contrast(1)    saturate(1); }
    35%  { filter: contrast(1.22) saturate(1.12); }
    60%  { filter: contrast(1.06) saturate(1.03); }
    100% { filter: contrast(1)    saturate(1); }
}
[data-phase="remediate"] .how-loop-svg {
    /* Chain: existing scene-pulse from earlier block + impact contrast.
       Both target .how-loop-svg — multiple animations compose. */
    animation:
        howScenePulse      900ms cubic-bezier(0.16, 1, 0.3, 1),
        howImpactContrast  320ms ease-out;
}

/* (5) EDGE REACTION SYNC — container itself micro-compresses on remediate
       entry, synced with the primary shockwave. Briefly overrides the JS
       transform on .how-loop for ~900ms; JS resumes drift after. */
@keyframes howContainerReact {
    /* Production tuning — visible compression without being jarring. */
    0%   { transform: scale(1); }
    18%  { transform: scale(0.978); }
    40%  { transform: scale(0.990); }
    100% { transform: scale(1); }
}
[data-phase="remediate"] .how-loop {
    animation: howContainerReact 900ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* Brief grid intensity flash on green core peak — already had howGridFlash,
   bump the leading edge so the impact frame stands out (5% keyframe). */
@keyframes howGridImpactFlash {
    0%   { opacity: 0.7; }
    3%   { opacity: 1; }                     /* earlier impact frame */
    15%  { opacity: 0.88; }
    100% { opacity: 0.7; }
}
[data-phase="remediate"] .how-loop-grid {
    animation: howGridImpactFlash 900ms ease-out forwards;
}

/* ─────────────────────────────────────────────────────────────────────
   CONTEXT LAYER · "Don't add motion — add context"
   1. Data echo  — faint log fragments drifting in background (all phases)
   2. Edge pulse — corner dots blinking slowly (all phases, alive edges)
   3. Right cards reactive — sync with active phase
   4. Caption micro-status dots — handled by JS dotsCycleTimer
   ───────────────────────────────────────────────────────────────────── */

/* (1) DATA ECHO — ambient background telemetry.
   Matched to the radar cyan family (#2dd4bf) so it reads as part of the
   same system, not random text. Slight blur for "telemetry, not UI" feel.
   Opacity range 0.13-0.20 — visible against dark bg, never dominating. */
.how-data-echo text {
    fill: rgba(45, 212, 191, 0.20);
    letter-spacing: 0.04em;
    filter: blur(0.4px);
}
@keyframes howEchoDrift1 {
    0%, 100% { transform: translate(0, 0);     opacity: 0.75; }
    50%      { transform: translate(3px, -2px); opacity: 1; }
}
@keyframes howEchoDrift2 {
    0%, 100% { transform: translate(0, 0);     opacity: 0.70; }
    50%      { transform: translate(-2px, 2px); opacity: 0.95; }
}
@keyframes howEchoDrift3 {
    0%, 100% { transform: translate(0, 0);     opacity: 0.65; }
    50%      { transform: translate(2px, 1px);  opacity: 0.90; }
}
@keyframes howEchoDrift4 {
    0%, 100% { transform: translate(0, 0);      opacity: 0.78; }
    50%      { transform: translate(-3px, -1px); opacity: 1; }
}
.how-data-echo-1 { animation: howEchoDrift1 14s ease-in-out infinite; transform-origin: 42px 98px; }
.how-data-echo-2 { animation: howEchoDrift2 17s ease-in-out infinite; transform-origin: 262px 118px; }
.how-data-echo-3 { animation: howEchoDrift3 19s ease-in-out infinite; transform-origin: 48px 392px; }
.how-data-echo-4 { animation: howEchoDrift4 15s ease-in-out infinite; transform-origin: 278px 408px; }

/* (2) EDGE PULSE — corner dots, irregular pulse rhythm per corner. */
.how-edge-pulse circle {
    fill: rgba(255, 255, 255, 0.45);
}
@keyframes howEdgePulse {
    0%, 100% { opacity: 0.20; r: 1.2; }
    50%      { opacity: 0.65; r: 1.8; }
}
.how-edge-pulse-1 { animation: howEdgePulse 3.2s ease-in-out infinite; animation-delay: 0s; }
.how-edge-pulse-2 { animation: howEdgePulse 4.1s ease-in-out infinite; animation-delay: 0.8s; }
.how-edge-pulse-3 { animation: howEdgePulse 3.7s ease-in-out infinite; animation-delay: 1.6s; }
.how-edge-pulse-4 { animation: howEdgePulse 4.5s ease-in-out infinite; animation-delay: 0.4s; }

/* (3) RIGHT CARDS REACTIVE — section gets data-active-phase from JS.
       Matching card highlights subtly: brighter bg, tinted border, glow on
       the icon. No glow leak — kept inside the card. */
.how-it-works[data-active-phase] .how-step-row {
    transition:
        background 500ms cubic-bezier(0.4, 0, 0.2, 1),
        border-color 500ms cubic-bezier(0.4, 0, 0.2, 1),
        box-shadow 500ms cubic-bezier(0.4, 0, 0.2, 1);
}

.how-it-works[data-active-phase="detect"] .how-card--detect {
    background: linear-gradient(180deg, rgba(255, 99, 99, 0.04), rgba(17, 24, 39, 0.20));
    border-color: rgba(255, 99, 99, 0.20);
    box-shadow: inset 0 0 0 1px rgba(255, 99, 99, 0.08);
}
.how-it-works[data-active-phase="detect"] .how-card--detect .how-shield-icon {
    color: #ff8a8a;
    filter: drop-shadow(0 0 8px rgba(255, 99, 99, 0.35));
}

.how-it-works[data-active-phase="explain"] .how-card--explain {
    background: linear-gradient(180deg, rgba(103, 232, 249, 0.04), rgba(17, 24, 39, 0.20));
    border-color: rgba(103, 232, 249, 0.22);
    box-shadow: inset 0 0 0 1px rgba(103, 232, 249, 0.08);
}
.how-it-works[data-active-phase="explain"] .how-card--explain .how-shield-icon {
    color: #7ee5f0;
    filter: drop-shadow(0 0 8px rgba(103, 232, 249, 0.35));
}

.how-it-works[data-active-phase="remediate"] .how-card--remediate {
    background: linear-gradient(180deg, rgba(134, 239, 172, 0.05), rgba(17, 24, 39, 0.20));
    border-color: rgba(134, 239, 172, 0.28);
    box-shadow: inset 0 0 0 1px rgba(134, 239, 172, 0.12);
}
.how-it-works[data-active-phase="remediate"] .how-card--remediate .how-shield-icon {
    color: #9ef4b7;
    filter: drop-shadow(0 0 9px rgba(134, 239, 172, 0.45));
}

/* Reduced motion — kill the context drifts but keep state highlights */
@media (prefers-reduced-motion: reduce) {
    .how-data-echo text,
    .how-edge-pulse circle {
        animation: none !important;
    }
}
