/* ============================================================
   stage.css - the beats, their background, and the reading scrim

   STRUCTURE
     .stage-bg   fixed CSS gradient field, behind everything
     #scene      fixed canvas for the price chart, above it
     .beat       a tall section; its frame pins for one viewport
     .beat-frame sticky 12-column grid, one viewport tall
     .beat-copy  the words, placed in a different corner each beat
     .sec::before the scrim that keeps the read sections legible

   There is no 3D behind the beats any more. A parameter surface used
   to fly past here and it never read as anything but decorative
   terrain, so it was replaced by .stage-bg - three very large, very
   soft colour fields drifting on a dark base. The only WebGL left on
   the page is the candlestick chart, which starts at .page-body.

   NO-JS / NO-WEBGL
   Beats are readable without any script: `is-live` is an enhancement
   applied once the page has decided the beat is on screen, and the
   data-scene="off" block below un-pins them into ordinary sections.
   ============================================================ */

/* ── The background the beats sit on ────────────────────────
   The blobs move with transform only - no background-position and no
   animated filter - so the whole thing composites on the GPU and costs
   essentially nothing while the page is being read. */
body {
    background: var(--bg-base, #0a0f1e);
}

.stage-bg {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    overflow: hidden;
    background:
        radial-gradient(120% 80% at 50% -10%, #182757 0%, transparent 60%),
        linear-gradient(180deg, #0a0f1e 0%, #0e1630 52%, #0a0f1e 100%);
}

.stage-bg span {
    position: absolute;
    display: block;
    border-radius: 50%;
    /* A blur this wide on a shape this size has no visible edge at any
       zoom, which is the entire point. */
    filter: blur(110px);
    opacity: 0.5;
    will-change: transform;
}

/* One cool, one deep, one warm. The warm field is the only heat on the
   first screen and is deliberately the smallest and faintest of the
   three: enough that the page is not pure blue, not enough to read as a
   second brand colour. */
.stage-bg span:nth-child(1) {
    width: 62vw; height: 62vw;
    right: -12vw; top: -18vw;
    background: radial-gradient(circle, rgba(111, 141, 216, 0.55), transparent 70%);
    animation: bg-drift-a 34s var(--ease-in-out, ease-in-out) infinite alternate;
}
.stage-bg span:nth-child(2) {
    width: 70vw; height: 70vw;
    left: -22vw; bottom: -26vw;
    background: radial-gradient(circle, rgba(30, 48, 110, 0.65), transparent 70%);
    animation: bg-drift-b 44s var(--ease-in-out, ease-in-out) infinite alternate;
}
.stage-bg span:nth-child(3) {
    width: 34vw; height: 34vw;
    right: 16vw; bottom: 2vw;
    background: radial-gradient(circle, rgba(201, 169, 98, 0.10), transparent 70%);
    animation: bg-drift-c 52s var(--ease-in-out, ease-in-out) infinite alternate;
}

@keyframes bg-drift-a {
    from { transform: translate3d(0, 0, 0) scale(1); }
    to   { transform: translate3d(-6vw, 7vh, 0) scale(1.12); }
}
@keyframes bg-drift-b {
    from { transform: translate3d(0, 0, 0) scale(1); }
    to   { transform: translate3d(8vw, -6vh, 0) scale(1.08); }
}
@keyframes bg-drift-c {
    from { transform: translate3d(0, 0, 0) scale(1); }
    to   { transform: translate3d(-9vw, -4vh, 0) scale(1.18); }
}

/* ── The canvas ─────────────────────────────────────────────
   Fixed and transparent. It only has anything in it from .page-body
   downward; over the beats it draws nothing and .stage-bg shows. */
#scene {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 0;
    pointer-events: none;
    opacity: 0;
    transition: opacity 900ms var(--ease-out, ease);
}
#scene[data-ready="true"] { opacity: 1; }

/* Everything that is not the canvas sits above it. */
#header, main, footer, .page-body { position: relative; z-index: 1; }

/* The blobs and the chart both bleed past the viewport; neither should
   ever give the document a horizontal scrollbar. */
main, .page-body { overflow-x: clip; }

/* ── A beat ─────────────────────────────────────────────────
   Tall enough that its frame pins for about one viewport before the
   next one arrives. */
.beat {
    position: relative;
    /* A short hold, not a long one.

       170vh was right when a 3D camera was flying through these screens
       and needed scroll distance to travel across: the pin bought the
       move its runway. There is no camera here any more - the background
       is a static CSS gradient - so those extra 70vh bought nothing, and
       scrolling through them changed nothing on screen. It read as the
       page being stuck.

       118vh gives each beat one screen plus a brief hold, which is long
       enough for the copy to land and short enough that a scroll always
       does something. */
    min-height: 118vh;
    /* global.css carries a bare `section { padding: var(--space-section)
       var(--space-inner) }`, and a beat IS a section - so every one of
       them was picking up 96px of top padding that nothing here reset.

       That pushed the sticky frame's natural position down to y=169, so
       a frame 100svh tall ended 169px BELOW the fold. Its middle row
       centred at about 620 instead of 450, and the hero's copy and panel
       sat in the bottom half of the screen under a large empty band.
       The frame owns its own padding; the section must have none. */
    padding: 0;
}

.beat-frame {
    position: sticky;
    top: var(--nav-h, 4.5rem);
    height: calc(100svh - var(--nav-h, 4.5rem));
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    /* One row. The four-beat version placed copy in a different corner
       of a three-row grid each time, and a block taller than its row
       slid under the nav (beat 2's title was off the top of the screen
       at 1440x900). Centring every beat on the same axis means the only
       way copy can leave the frame is by being taller than the frame. */
    grid-template-rows: 1fr;
    /* Content sits in the TOP half of the frame, because the chart occupies a
       band across the bottom of the viewport (js/scene.js). Centring it put
       every headline straight over the candles. */
    align-items: start;
    padding: clamp(2rem, 6vh, 4.5rem) clamp(1.25rem, 4vw, 3.5rem) clamp(1.5rem, 4vh, 3rem);
    gap: 0 clamp(1rem, 2vw, 2rem);
}

/* Top-row copy still wants more air than a plain gutter, or it reads as
   pinned to the nav's underside rather than placed near the top. */


.beat-copy {
    position: relative;
    display: grid;
    justify-items: start;
    gap: clamp(0.85rem, 1.7vw, 1.35rem);
    align-self: start;
}

/* The halo. A blurred ellipse rather than a panel: a filled box with an
   edge would read as a card pasted on the background, and the point of
   moving the copy around is that it belongs to the space.

   The size is stated rather than left to farthest-corner. With default
   sizing the transparent stop sat outside the element box on the long
   axis, so the halo cut off at a hard vertical line. */
.beat-copy::before {
    /* No plate. With the chart confined to a band across the bottom, the
       copy never sits over a candle, so the scrim behind it had nothing to
       do except read as a dark rounded box on a wide screen. Legibility if
       the two ever do meet - a very short viewport - is handled by the text
       shadow below, which costs nothing and shows nothing. */
    content: none;
}

/* Two placements. The copy takes the left six columns or the right six;
   the aside takes the other side. Alternating them is what moves the eye
   from beat to beat - the vertical hop was never doing that work. */
[data-side="left"]  .beat-copy { grid-column: 1 / 7; }
[data-side="right"] .beat-copy { grid-column: 7 / 13; }

/* Copy in a right-hand column is set ragged-left, or its short last
   line floats away from the column it belongs to. */
[data-side="right"] .beat-copy { justify-items: start; text-align: left; }

.beat-title { max-width: 16ch; margin: 0; }
.beat-body  { max-width: 46ch; margin: 0; }
.beat-note {
    font-family: var(--font-body);
    font-size: var(--step--1);
    line-height: 1.65;
    color: var(--text-quiet, #8592b0);
    max-width: 44ch;
    margin: 0.35rem 0 0;
    padding-top: 0.9rem;
    border-top: 1px solid var(--border, rgba(255, 255, 255, 0.08));
    width: 100%;
}
.beat-cta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-top: 0.4rem;
}

/* Entry. An enhancement only: without JS nothing gets `is-live`, and
   the data-scene="off" block below shows everything anyway. */
body[data-scene="on"] .beat-copy > * {
    opacity: 0;
    transform: translateY(16px);
    transition: opacity 1050ms var(--ease-in-out, ease-in-out),
                transform 1050ms var(--ease-in-out, ease-in-out);
}
body[data-scene="on"] .beat.is-live .beat-copy > * {
    opacity: 1;
    transform: none;
    transition: opacity 640ms var(--ease-out, ease),
                transform 640ms var(--ease-out, ease);
}
body[data-scene="on"] .beat.is-live .beat-copy > :nth-child(2) { transition-delay: 65ms; }
body[data-scene="on"] .beat.is-live .beat-copy > :nth-child(3) { transition-delay: 130ms; }
body[data-scene="on"] .beat.is-live .beat-copy > :nth-child(4) { transition-delay: 195ms; }

/* ── The page below the beats ───────────────────────────────
   Read and clicked, not looked at. The chart keeps running behind it,
   so each section lays a scrim over the canvas. */
.sec { position: relative; }
.sec::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    /* Not opaque: the chart stays the ground the page sits on. But it
       has to be quiet enough that a candle never runs through a line of
       body copy. */
    background: rgba(10, 15, 30, 0.90);
}

/* The join. The first section under the last beat ramps from clear to
   the reading scrim over its own height, so the beats hand over to the
   page instead of being cut off at a line. */
.sec-open::before {
    background: linear-gradient(180deg,
        rgba(10, 15, 30, 0)    0%,
        rgba(10, 15, 30, 0.34) 30%,
        rgba(10, 15, 30, 0.74) 64%,
        rgba(10, 15, 30, 0.93) 100%);
}

/* #faq keeps its own max-width because the sticky-aside grid IS its
   layout, so its scrim gets the bleed instead of its box. */
#faq::before { inset-inline: calc(50% - 50vw); }

/* ── The close ──────────────────────────────────────────────
   The mirror of .sec-open: this one ramps back out, so the last thing
   on the page is the chart rather than a flat panel with a footer under
   it. The copy sits in the top half where the scrim is still working;
   the bottom half is left clear for the candles.

   Full bleed like #faq's: the section's box stops at the shell, and a
   scrim that stops with it leaves a vertical step down the right-hand
   side where the chart is suddenly un-scrimmed. */
.sec-close::before {
    inset-inline: calc(50% - 50vw);
    /* Barely different from the sections above it. The chart used to be
       dimmed everywhere and then revealed here, which made the footer the
       brightest thing on the page - exactly backwards. */
    /* The closing section is the one place the chart IS the subject, so it
       clears more than a reading section does - but it starts from the same
       0.86 as everything above, so the page brightens gently into it rather
       than switching on at the footer. */
    background: linear-gradient(180deg,
        rgba(10, 15, 30, 0.88) 0%,
        rgba(10, 15, 30, 0.70) 34%,
        rgba(10, 15, 30, 0.34) 62%,
        rgba(10, 15, 30, 0.22) 100%);
}

/* ── Scene off ──────────────────────────────────────────────
   No WebGL, or the chart failed to load. The beats stop reserving two
   screens each and become ordinary stacked sections. The background is
   pure CSS and is completely unaffected. */
body[data-scene="off"] .beat { min-height: 0; }
body[data-scene="off"] .beat-frame {
    position: static;
    height: auto;
    display: block;
    padding-block: clamp(3rem, 8vw, 5.5rem);
}
body[data-scene="off"] .beat-copy,
body[data-scene="off"] [data-side="right"] .beat-copy {
    justify-items: start;
    text-align: left;
    max-width: 46rem;
}
body[data-scene="off"] .beat-copy::before { display: none; }
body[data-scene="off"] .beat-cards { display: none; }
body[data-scene="off"] .sec::before { background: var(--bg-base, #0a0f1e); }

/* ── Reduced motion ─────────────────────────────────────────
   Colour is the point; the drift is only atmosphere. The chart renders
   one frame per scroll settle and never loops. */
@media (prefers-reduced-motion: reduce) {
    .stage-bg span { animation: none; }
    #scene[data-ready="true"] { opacity: 0.85; transition: none; }
    body[data-scene="static"] .beat-copy > *,
    body[data-scene="static"] .beat-cards li { opacity: 1; transform: none; }
}

/* ── Narrow ─────────────────────────────────────────────────
   Below the two-column point there is no room for copy beside anything,
   so every beat takes the full width and the cards go: three glass
   panels stacked over a headline is a worse opening than none, and the
   same three facts are in the sections below. */
@media (max-width: 900px) {
    .beat { min-height: 106vh; }
    .beat-frame {
        grid-template-rows: auto 1fr auto;
        padding-inline: clamp(1.25rem, 5vw, 2rem);
    }
    /* [data-side] on the selector, or the desktop six-column placement
       (0,1,1) outranks a bare .beat-copy (0,1,0) and the phone keeps a
       half-width column. */
    [data-side] .beat-copy,
    [data-side="right"] .beat-copy {
        grid-column: 1 / -1;
        justify-items: start;
        text-align: left;
    }
    .beat-cards { display: none; }
    .beat-title { max-width: 100%; }
    .beat-body { max-width: 100%; }
}


/* ════════════════════════════════════════════════════════════
   THE PANEL
   One component for every beat's supporting content.

   Before this there were four different things: glass cards with
   their own radius, a figure with its own border, two bare lists with
   hairline rules. Four treatments across four screens reads as four
   unfinished ideas rather than one system, which is what made them
   look thrown together.

   The rules it follows, everywhere:
     - one container: same surface, border, radius, padding
     - a label at the top, set small, quiet and letterspaced
     - rows are label-left / value-right, divided by hairlines
     - figures are tabular and negatively tracked; words are not
     - the accent appears at most once per panel
   ════════════════════════════════════════════════════════════ */

.beat-aside {
    align-self: start;
    margin: 0;
    /* Wide enough for a label and a value without the two colliding,
       narrow enough that it never competes with the headline. */
    inline-size: min(100%, 23rem);
}
.panel-lg { inline-size: min(100%, 25rem); }
.panel-row { inline-size: min(100%, 46rem); }

/* Every aside gets the FULL height of the frame and centres in it.

   They used to be pinned to a single row - beat 2's was `grid-area: 3 /
   8 / 4 / 13` with align-self: end, and row 3 is 0.9fr of the frame.
   The block is taller than that row, so anchoring its bottom edge to
   the bottom of a short row pushed the rest of it off the bottom of the
   screen. Spanning all three rows and centring means the only way one
   can leave the viewport is by being taller than the viewport. */
[data-side="left"]  .beat-aside { grid-column: 8 / 13; justify-self: start; }
[data-side="right"] .beat-aside { grid-column: 1 / 6;  justify-self: end; }

/* No container. The boxed version read as a settings dialog parked on
   the artwork - a bordered rectangle with a shaded fill and rows inside
   is the shape of a form, and four of them across four screens looked
   like leftover UI rather than like part of the page.

   What replaces it is typographic: a short accent rule, a label, and
   rows on hairlines, with nothing drawn around any of it. The copy
   beside it has no box either, so the two now read as one composition
   rather than as a headline next to a widget. */
.panel {
    position: relative;
    padding-top: 1.15rem;
}

/* The rule. Short, the accent colour, and it DRAWS rather than fades -
   which is the entrance, not decoration. */
.panel::before {
    content: '';
    position: absolute;
    inset-block-start: 0;
    inset-inline-start: 0;
    width: 2.6rem;
    height: 2px;
    background: var(--gold, #c9a962);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform 1000ms var(--ease-in-out, ease-in-out);
}
body[data-scene="on"] .beat.is-live .panel::before {
    transform: scaleX(1);
    transition: transform 760ms var(--ease-out, ease);
}

.panel-label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0 0 1.1rem;
    font-family: var(--font-body);
    font-weight: 600;
    font-size: 0.72rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-quiet, #8592b0);
}
.panel-tag {
    padding: 0.12rem 0.5rem;
    border-radius: var(--radius-pill, 999px);
    background: rgba(138, 164, 232, 0.13);
    color: var(--accent-warm, #8aa4e8);
    font-size: 0.66rem;
    letter-spacing: 0.09em;
}

/* ── Rows ───────────────────────────────────────────────────
   Label left, value right, hairline between, nothing around. The last
   row carries no rule so the block ends on air. */
.panel-rows { display: grid; margin: 0; }
.panel-rows > div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 1.5rem;
    padding: 0.7rem 0;
    /* Faded at both ends. A hairline that stops dead draws a corner; one
       that fades reads as a division. */
    border-bottom: 0;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.10) 8%,
                rgba(255, 255, 255, 0.10) 92%, transparent) bottom / 100% 1px no-repeat;
}
.panel-rows > div:last-child { background: none; }
.panel-rows dt {
    font-family: var(--font-body);
    font-size: 0.85rem;
    color: var(--text-quiet, #8592b0);
}
.panel-rows dd {
    margin: 0;
    font-family: var(--font-body);
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--text-primary, #eef1f8);
    text-align: right;
}
/* Figures take the mono face and tabular figures. Words do not: setting
   "every close" in a monospace is the tell of a table that does not
   know what it is holding. */
.panel-rows dd.num {
    font-family: var(--font-num);
    font-variant-numeric: tabular-nums;
    font-size: 1.35rem;
    font-weight: 500;
    letter-spacing: -0.025em;
}
.panel-rows-tight > div { padding: 0.5rem 0; }

/* Stacked, for rows whose value is a sentence - side by side they wrap
   into a ragged column. */
.panel-rows-stack > div { display: grid; gap: 0.2rem; padding: 0.8rem 0; }
.panel-rows-stack dt {
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--text-primary, #eef1f8);
}
.panel-rows-stack dd {
    font-size: 0.85rem;
    font-weight: 400;
    line-height: 1.55;
    color: var(--text-muted, #a3adc4);
    text-align: left;
}

.panel-rule {
    height: 0;
    margin: 1.2rem 0;
    border: 0;
    border-top: 1px solid rgba(255, 255, 255, 0.09);
}

/* ── The example message ────────────────────────────────────
   The one thing here that keeps a surface, because it is depicting a
   message and a message is an object. Even so it is a sheet rather than
   a dialog: no full border, one soft edge, and the accent rule of the
   block runs down its left side instead of across its top. */
.panel-lg .msg-sheet {
    position: relative;
    padding: 1rem 1.1rem 1rem 1.25rem;
    /* No hard rule down the side and no cut corner. The edge is a gradient
       that fades out top and bottom, and the surface fades away to nothing
       on the right, so the block sits ON the page rather than being a
       rectangle pasted over it. */
    border: 0;
    border-radius: var(--radius-md, 8px);
    background:
        linear-gradient(180deg, transparent, rgba(138, 164, 232, 0.55) 18%,
                        rgba(138, 164, 232, 0.55) 82%, transparent) left / 2px 100% no-repeat,
        linear-gradient(105deg, rgba(255, 255, 255, 0.055) 0%,
                        rgba(255, 255, 255, 0.02) 45%, rgba(255, 255, 255, 0) 90%);
}
/* A soft halo instead of a border: it reads as a lit surface, not a box. */
.panel-lg .msg-sheet::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05),
                0 18px 40px -28px rgba(0, 0, 0, 0.9);
}
.msg-head {
    display: flex;
    align-items: baseline;
    gap: 0.55rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.msg-tkr {
    font-family: var(--font-num);
    font-size: 1.15rem;
    font-weight: 500;
    letter-spacing: -0.02em;
    color: var(--text-primary, #eef1f8);
}
.msg-strat { font-size: 0.82rem; color: var(--text-quiet, #8592b0); }
.msg-act {
    margin-inline-start: auto;
    padding: 0.16rem 0.6rem;
    border-radius: var(--radius-pill, 999px);
    background: rgba(45, 190, 140, 0.14);
    color: #2dbe8c;
    font-size: 0.76rem;
    font-weight: 600;
}
.msg-btns { display: flex; gap: 0.5rem; margin-top: 1rem; }
.msg-btns span {
    flex: 1;
    text-align: center;
    padding: 0.5rem 0;
    border-radius: var(--radius-sm, 5px);
    border: 1px solid rgba(255, 255, 255, 0.14);
    font-size: 0.84rem;
    font-weight: 600;
    color: var(--text-muted, #a3adc4);
}
.msg-btns .msg-add {
    background: var(--accent-blue, #8aa4e8);
    border-color: transparent;
    /* Near-black on this blue, not white: white is about 3:1 here. */
    color: #070b16;
}

/* ── Figures in a row (beat 3) ──────────────────────────────
   Three readings on one line, divided by hairlines, no container. */
.panel-row { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; }
.panel-row .fig {
    display: grid;
    gap: 0.35rem;
    justify-items: center;
    text-align: center;
    padding-inline: clamp(0.75rem, 2vw, 1.75rem);
    border-inline-start: 1px solid rgba(255, 255, 255, 0.09);
}
.panel-row .fig:first-child { border-inline-start: 0; }
.fig-v {
    font-size: clamp(1.3rem, 2.5vw, 1.8rem);
    font-weight: 500;
    letter-spacing: -0.03em;
    line-height: 1.05;
    color: var(--text-primary, #eef1f8);
    white-space: nowrap;
}
.fig-k {
    font-size: 0.8rem;
    line-height: 1.4;
    color: var(--text-quiet, #8592b0);
    /* One line each. A caption that wraps under one figure and not the
       next makes a row of readings look ragged. */
    white-space: nowrap;
}
/* The pair we run is the point of the reading, so it is the one thing
   that takes the accent. */
.fig-mark .fig-v { color: var(--accent-blue, #8aa4e8); }

/* ── Entry ──────────────────────────────────────────────────
   With the copy, not after it.

   And a settle rather than a slide: the block resolves out of a blur as
   it rises a few pixels, which reads as something coming into focus
   instead of something being pushed on from off-screen. The accent rule
   draws across at the same time (see .panel::before above), so the
   entrance has a stroke in it rather than being one uniform fade.

   Rows carry a small stagger of their own - 40ms apart, capped - which
   is enough to give the block a direction without turning it into a
   list assembling itself. */
/* The base state is also the EXIT state, so its timing is what a beat
   leaving looks like. Leaving is given half again as long as arriving
   and a softer curve: an entrance wants to land, but something on its
   way out should just recede. It was using the same 700ms expo-out in
   both directions, which snapped it off the screen. */
body[data-scene="on"] .beat-aside {
    opacity: 0;
    transform: translateY(14px);
    filter: blur(9px);
    transition: opacity 1150ms var(--ease-in-out, ease-in-out),
                transform 1150ms var(--ease-in-out, ease-in-out),
                filter 1150ms var(--ease-in-out, ease-in-out);
}
body[data-scene="on"] .beat.is-live .beat-aside {
    opacity: 1;
    transform: none;
    filter: blur(0);
    transition: opacity 700ms var(--ease-out, ease),
                transform 700ms var(--ease-out, ease),
                filter 700ms var(--ease-out, ease);
}
body[data-scene="on"] .panel-rows > div,
body[data-scene="on"] .panel-row .fig {
    opacity: 0;
    /* No stagger on the way out - leaving one row at a time reads as the
       block coming apart rather than as it receding. */
    transition: opacity 900ms var(--ease-in-out, ease-in-out) 0ms;
}
body[data-scene="on"] .beat.is-live .panel-rows > div,
body[data-scene="on"] .beat.is-live .panel-row .fig {
    opacity: 1;
    transition: opacity 560ms var(--ease-out, ease);
}
body[data-scene="on"] .beat.is-live .panel-rows > div:nth-child(2),
body[data-scene="on"] .beat.is-live .panel-row .fig:nth-child(2) { transition-delay: 40ms; }
body[data-scene="on"] .beat.is-live .panel-rows > div:nth-child(3),
body[data-scene="on"] .beat.is-live .panel-row .fig:nth-child(3) { transition-delay: 80ms; }
body[data-scene="on"] .beat.is-live .panel-rows > div:nth-child(n+4) { transition-delay: 120ms; }

/* Below the two-column point a panel under a headline is just more to
   scroll past, and every fact in them is repeated in the sections
   below. */
@media (max-width: 900px) {
    .beat-aside { display: none; }
}
@media (prefers-reduced-motion: reduce) {
    body[data-scene="static"] .beat-aside { opacity: 1; transform: none; }
}

/* The one row in "Who does what" that is the visitor's job. Separated by
   a heavier rule and given the accent, so the three-over-one shape is
   legible before the words are. */
.panel-rows .row-you {
    /* ONE rule, not two. The row above still carried its own border-bottom
       while this one drew a border-top over a 0.35rem gap, so the divider
       read as a double line. The preceding row's border is dropped below and
       this heavier rule is the only one. */
    margin-top: 0;
    border-top: 0;
    padding-top: 0.95rem;
    background: linear-gradient(90deg, transparent, rgba(201, 169, 98, 0.45) 8%,
                rgba(201, 169, 98, 0.45) 92%, transparent) top / 100% 1px no-repeat;
}
.panel-rows > div:has(+ .row-you) { background: none; }
.panel-rows .row-you dt { color: var(--text-muted, #a3adc4); }
.panel-rows .row-you dd { color: var(--gold, #c9a962); font-weight: 600; }

/* Beat 3's fourth column is the lowest-friction next step on the page,
   so it is a link rather than a reading. */
.fig-link {
    color: var(--accent-blue, #8aa4e8);
    text-decoration: none;
    border-bottom: 1px solid rgba(138, 164, 232, 0.4);
    transition: border-color var(--dur-fast, 160ms) var(--ease-out, ease);
}
.fig-link:hover { border-bottom-color: var(--accent-blue, #8aa4e8); }
.fig-link:focus-visible { outline: 2px solid var(--accent-blue, #8aa4e8); outline-offset: 3px; }

/* The opening panel's lead line. Larger than a row and set in the body
   face, because it is a sentence rather than a reading - this is the
   first panel on the site and it states the company before it diagrams
   it. Sits above the rule that divides it from the rows. */
.panel-lead {
    margin: 0 0 1.15rem;
    padding-bottom: 1.15rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.09);
    font-family: var(--font-body);
    font-size: 1.02rem;
    font-weight: 500;
    line-height: 1.5;
    color: var(--text-primary, #eef1f8);
    max-width: 24ch;
}

/* Beat 3's readings are words now rather than figures, so they lose the
   tabular treatment and the tight tracking that belong to numbers. */
.panel-row .fig-v:not(.num) {
    font-family: var(--font-display);
    font-size: clamp(1.05rem, 1.9vw, 1.35rem);
    letter-spacing: var(--tracking-display);
}


/* ── Ledger additions ──────────────────────────────────────── */
.beat-eyebrow {
    font-family: var(--font-body);
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent-warm, #8d99b8);
    margin: 0 0 0.25rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
}
.beat-eyebrow::before {
    content: '';
    width: 2.2rem; height: 1px;
    background: var(--gold, #c9a962);
}
/* Titles in the serif read larger than Geist did at the same size, so
   the hero steps down one notch and lets the italic word carry it. */
/* A notch smaller than it was. The chart band starts below the tallest
   beat, so every point of headline is a point taken off the chart - and at
   the old size the band was thin enough that the price read as flat. */
#hero .beat-title { font-size: clamp(2.2rem, 1.6rem + 3vw, 4.4rem); line-height: 1.02; }
.beat .display-lg { font-size: var(--step-4); }
.beat .display-md { font-size: var(--step-3); }
.beat-body { font-size: var(--step-0); }
.beat-title em { font-style: italic; color: var(--accent, #8aa4e8); }
/* The panel rule and the "you" row are brass now via the token swap;
   the message sheet's action chip stays green because it depicts a buy. */
.msg-btns .msg-add { background: var(--accent, #8aa4e8); color: var(--accent-ink, #0a0f1e); }

/* The aside gets the same halo as the copy now that the chart runs
   behind the beats: rows on hairlines over candles were legible but
   busy, and the two blocks should sit in the same kind of space. */
.beat-aside { position: relative; }
.beat-aside::before { content: none; }

/* The insurance the plates used to be. Invisible against the page and
   enough to keep a headline readable if a short viewport ever pushes the
   chart band up under it. */
.beat-copy, .beat-aside {
    text-shadow: 0 1px 16px rgba(10, 15, 30, 0.85), 0 0 3px rgba(10, 15, 30, 0.6);
}
