      .dashboard-root {
        font-family: var(--mono), 'JetBrains Mono', Menlo, Consolas, monospace;
        opacity: 0;
        transition: opacity 520ms cubic-bezier(.2, .7, .2, 1);
      }
      .dashboard-root.is-ready {
        opacity: 1;
      }
      .dashboard-root::before {
        content: "";
        position: fixed;
        inset: 0;
        background: var(--bg);
        z-index: -1;
      }
      /* Pin the Three.js canvas to the viewport so it covers any area outside
         the panels, no matter how the window is resized. */
      .dashboard-canvas-host {
        position: fixed;
        inset: 0;
        z-index: 0;
      }
      .dashboard-canvas-host > canvas {
        position: absolute;
        inset: 0;
        display: block;
      }

      /* ── Pool state panel (left dossier) ────────────────────── */
      #pool-stats {
        position: fixed;
        top: 86px;
        bottom: 24px;
        left: 24px;
        /* Width scales with viewport so the panel takes the same
           PROPORTION of screen real estate on a 14" Mac as on a 27"
           display — narrower in absolute px on smaller screens. */
        width: clamp(258px, 21.2vw, 312px);
        background: rgba(13,13,13,0.88);
        border: 1px solid var(--line);
        border-radius: 5px;
        color: var(--text);
        font-family: var(--mono), 'JetBrains Mono', Menlo, Consolas, monospace;
        font-size: 11px;
        display: flex;
        flex-direction: column;
        z-index: 10;
        /* Content stack (header, hero, metrics, ERC20 list, activities,
           stats grid) is taller than most viewports — let it scroll inside
           the panel instead of spilling past the bottom border. */
        overflow-y: auto;
        scrollbar-width: thin;
        scrollbar-color: var(--line) transparent;
      }
      #pool-stats::-webkit-scrollbar { width: 6px; }
      #pool-stats::-webkit-scrollbar-thumb { background: var(--line); }
      #pool-stats__head {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 10px 14px;
        border-bottom: 1px solid var(--line);
        text-transform: uppercase;
        letter-spacing: 0.2em;
        font-size: 10px;
        color: var(--dim);
      }
      #pool-stats__head h3 {
        margin: 0;
        font-size: 10px;
        font-weight: 500;
        letter-spacing: 0.2em;
        color: var(--dim);
      }
      #pool-stats__sub {
        padding: 8px 14px 10px;
        font-size: 9px;
        color: var(--faint);
        letter-spacing: 0.14em;
        text-transform: uppercase;
        border-bottom: 1px dashed rgba(250,250,250,0.05);
      }

      /* Featured TVL hero block — no corner decorations, just clean type. */
      .frame {
        padding: 18px 14px;
        margin: 0 14px;
        border-bottom: 1px dashed rgba(250,250,250,0.05);
      }
      .frame__label {
        font-size: 9px;
        letter-spacing: 0.3em;
        text-transform: uppercase;
        color: var(--dim);
        font-weight: 500;
      }
      .frame__value {
        margin-top: 8px;
        font-size: 32px;
        font-weight: 800;
        font-family: var(--display);
        font-variant-numeric: tabular-nums;
        letter-spacing: -0.025em;
        line-height: 1.0;
        text-transform: uppercase;
        background: linear-gradient(178deg, #fffdf1 0%, #f4ece8 50%, #ffcdb6 100%);
        -webkit-background-clip: text;
        background-clip: text;
        -webkit-text-fill-color: transparent;
        color: transparent;
      }
      /* TVL value + chart button on one line. */
      .frame__row {
        display: flex;
        align-items: center;
        gap: 10px;
      }
      .tvl-chart-btn {
        margin-top: 8px;
        width: 26px;
        height: 26px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: rgba(13, 13, 13, 0.88);
        border: 1px solid var(--line);
        border-radius: 4px;
        color: var(--dim);
        cursor: pointer;
        padding: 0;
        transition: color 120ms, border-color 120ms;
        flex-shrink: 0;
      }
      .tvl-chart-btn:hover {
        color: var(--orange);
        border-color: rgba(197, 52, 0, 0.55);
      }

      /* ── TVL-over-time modal ─────────────────────────────────── */
      .tvl-modal {
        position: fixed;
        inset: 0;
        z-index: 90;
        display: none;
      }
      .tvl-modal.is-open { display: block; }
      /* Same backdrop treatment as the Use section's app slide-out
         (live-apps.jsx): 55% black + 4px blur, .22s fade — the pool
         panel visibly blurs behind it. */
      .tvl-modal__backdrop {
        position: absolute;
        inset: 0;
        background: rgba(0, 0, 0, 0.55);
        backdrop-filter: blur(4px);
        -webkit-backdrop-filter: blur(4px);
      }
      .tvl-modal.is-open .tvl-modal__backdrop {
        animation: tvl-fade-in 220ms ease-out;
      }
      /* The pool tab NEVER blurs: while the chart drawer is open the
         panel is lifted above the backdrop (and above the drawer, so
         the slide-out genuinely emerges from behind the tab). Class
         toggled on <body> by tvlchart.js. */
      body.tvl-chart-open #pool-stats {
        z-index: 95;
      }
      @keyframes tvl-fade-in {
        from { opacity: 0; }
        to   { opacity: 1; }
      }
      /* Drawer extending from the pool tab, separated by a small
         gutter; the clip reveal still grows it rightward from the
         tab's side. Header geometry mirrors the tab so the hairlines
         stay level across the gap. */
      .tvl-modal__panel {
        position: absolute;
        left: calc(24px + clamp(258px, 21.2vw, 312px) + 14px);
        top: 86px;
        width: min(500px, calc(100vw - 24px - clamp(258px, 21.2vw, 312px) - 62px));
        background: rgba(13, 13, 13, 0.97);
        border: 1px solid var(--line);
        border-radius: 6px;
        padding: 0 0 10px;
        box-shadow: 0 32px 80px -24px rgba(0, 0, 0, 0.9);
        font-family: var(--mono), 'JetBrains Mono', Menlo, Consolas, monospace;
      }
      /* Same duration/easing as the Use section's app panel, but the
         reveal is a left-to-right clip (drawer being pulled out of the
         tab) rather than a translate — the chart never passes under or
         over the tab, it extends from its edge. */
      .tvl-modal.is-open .tvl-modal__panel {
        animation: tvl-extend 320ms cubic-bezier(.2, .7, .2, 1);
      }
      @keyframes tvl-extend {
        from { clip-path: inset(0 100% 0 0); }
        to   { clip-path: inset(0 0 0 0); }
      }
      /* Closing: the drawer retracts back into the tab (reverse clip)
         while the backdrop fades — mirrors the Use-section close. The
         is-closing rules are declared after is-open so they win while
         both classes are present during the retract. */
      .tvl-modal.is-closing .tvl-modal__panel {
        animation: tvl-retract 280ms cubic-bezier(.4, 0, .8, .4) forwards;
      }
      @keyframes tvl-retract {
        from { clip-path: inset(0 0 0 0); }
        to   { clip-path: inset(0 100% 0 0); }
      }
      .tvl-modal.is-closing .tvl-modal__backdrop {
        animation: tvl-fade-out 260ms ease-in forwards;
      }
      @keyframes tvl-fade-out {
        from { opacity: 1; }
        to   { opacity: 0; }
      }
      /* Mirrors #pool-stats__head exactly (same paddings, type, and
         hairline) so the underline runs as ONE continuous line from the
         tab into the drawer, and the seam border stays aligned. */
      .tvl-modal__head {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 14px;
        padding: 10px 14px;
        border-bottom: 1px solid var(--line);
        text-transform: uppercase;
        letter-spacing: 0.2em;
        font-size: 10px;
        color: var(--dim);
      }
      .tvl-modal__title {
        font-family: var(--display);
        font-size: 10px;
        font-weight: 500;
        letter-spacing: 0.2em;
        color: var(--dim);
        text-transform: uppercase;
        margin: 0;
        line-height: inherit;
      }
      .tvl-modal__ranges { display: flex; gap: 4px; }
      /* Standalone pills row between the header and the chart. */
      .tvl-modal__ranges--bar { padding: 10px 14px 0; }
      /* Same treatment as the tx-log VIEW >> button (.tx__btn). */
      .tvl-modal__range {
        display: inline-block;
        padding: 3px 8px;
        background: transparent;
        border: 1px solid #3a3a44;
        border-radius: 0;
        color: var(--text);
        font-size: 10px;
        letter-spacing: 0.16em;
        text-transform: uppercase;
        font-family: inherit;
        white-space: nowrap;
        cursor: pointer;
        outline: none;
        transition: color 120ms, border-color 120ms;
      }
      .tvl-modal__range:hover,
      .tvl-modal__range.is-active {
        border-color: var(--orange);
        color: var(--orange);
      }
      .tvl-modal__close {
        background: transparent;
        border: none;
        color: var(--dim);
        /* Compact so the header keeps exactly #pool-stats__head's
           height — the hairlines must meet at the same y. */
        font-size: 10px;
        line-height: 1;
        cursor: pointer;
        padding: 0;
      }
      .tvl-modal__close:hover { color: var(--text); }
      .tvl-modal__meta {
        display: flex;
        align-items: baseline;
        gap: 12px;
        padding: 14px 16px 4px;
      }
      .tvl-modal__now {
        font-family: var(--display);
        font-size: 26px;
        font-weight: 800;
        letter-spacing: -0.02em;
        color: var(--text);
      }
      .tvl-modal__delta { font-size: 10px; letter-spacing: 0.08em; }
      .tvl-modal__delta.up { color: #7fbf7f; }
      .tvl-modal__delta.down { color: var(--orange); }
      .tvl-modal__chart { padding: 14px 16px 0; }
      .tvl-modal__svg { width: 100%; height: 220px; display: block; }
      .tvl-modal__axis {
        display: flex;
        justify-content: space-between;
        font-size: 9px;
        letter-spacing: 0.12em;
        color: var(--faint);
        text-transform: uppercase;
        padding: 6px 2px 0;
      }
      .tvl-modal__empty {
        height: 220px;
        display: grid;
        place-items: center;
        color: var(--faint);
        font-size: 11px;
        letter-spacing: 0.14em;
        text-transform: uppercase;
      }
      .tvl-modal__foot {
        padding: 10px 16px 4px;
        font-size: 9px;
        letter-spacing: 0.12em;
        color: var(--faint);
        text-transform: uppercase;
      }

      .frame__hint {
        margin-top: 6px;
        font-size: 9px;
        letter-spacing: 0.2em;
        color: var(--faint);
        text-transform: uppercase;
      }

      .metrics {
        padding: 0 14px 14px;
        display: flex;
        flex-direction: column;
      }
      .metric {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        padding: 9px 0;
        border-bottom: 1px dashed rgba(250,250,250,0.05);
      }
      .metric:last-child { border-bottom: none; }
      .metric__label {
        font-size: 10px;
        letter-spacing: 0.14em;
        color: var(--faint);
        text-transform: uppercase;
      }
      .metric__label::before {
        content: '» ';
        color: var(--ghost);
        margin-right: 2px;
      }
      .metric__value {
        color: var(--text);
        font-variant-numeric: tabular-nums;
        font-size: 14px;
        font-weight: 500;
      }

      .erc20-section__head {
        margin-top: 8px;
        padding: 10px 0;
        font-size: 10px;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        color: var(--faint);
        border-bottom: 1px dashed rgba(250,250,250,0.05);
      }
      .erc20-section__head::before {
        content: '» ';
        color: var(--ghost);
        margin-right: 2px;
      }

      .erc20-list {
        display: flex;
        flex-direction: column;
        padding: 6px 0 4px;
        max-height: 180px;
        overflow-y: auto;
        scrollbar-width: thin;
        scrollbar-color: var(--line) transparent;
      }
      .erc20-list::-webkit-scrollbar { width: 4px; }
      .erc20-list::-webkit-scrollbar-thumb { background: var(--line); }

      /* 2 × 2 stats grid below the ERC20 list. */
      .pool-stats-grid {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 1px;
        background: var(--line);
        margin: 10px -14px 0;
        border-top: 1px solid var(--line);
        border-bottom: 1px solid var(--line);
      }
      .stat-cell {
        background: rgba(13,13,13,0.88);
        padding: 9px 12px;
      }
      .stat-cell__label {
        font-size: 9px;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        color: var(--faint);
        margin-bottom: 4px;
      }
      .stat-cell--wide {
        grid-column: 1 / -1;
      }
      .pool-stats-grid__title {
        margin-top: 14px;
        padding: 10px 0 6px;
        font-size: 10px;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        color: var(--faint);
        border-bottom: 1px dashed rgba(250,250,250,0.05);
      }
      .pool-stats-grid__title::before {
        content: '» ';
        color: var(--ghost);
        margin-right: 2px;
      }
      .stat-cell__value {
        font-size: 14px;
        font-weight: 500;
        font-variant-numeric: tabular-nums;
        background: linear-gradient(
          90deg,
          #d6531c,
          #c53400,
          #d6531c,
          #a02a00,
          #c53400,
          #d6531c
        );
        background-size: 300% 100%;
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
        -webkit-text-fill-color: transparent;
        animation: defi-glow 5s linear infinite;
        filter: drop-shadow(0 0 4px var(--green-glow));
      }

      .erc20-row {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 4px 0;
      }
      .erc20-row__id {
        display: flex;
        align-items: center;
        gap: 8px;
      }
      .erc20-row__icon {
        width: 18px;
        height: 18px;
        border-radius: 50%;
        background: var(--bg);
        object-fit: cover;
      }
      .erc20-row__icon--blank {
        background: rgba(250,250,250,0.05);
        border: 1px dashed var(--line);
        border-radius: 50%;
      }
      .erc20-row__sym {
        color: var(--text);
        font-size: 11px;
        font-weight: 500;
      }
      .erc20-row__val {
        color: var(--text);
        font-size: 11px;
        font-variant-numeric: tabular-nums;
      }
      .erc20-row__val--unpriced { color: var(--faint); font-style: italic; }

      /* Most frequent activities — sortable list. Deposit/withdrawal rows are
         live (30D from /agg/window-ops); the rest are mock placeholders until
         the server can attribute DeFi-routed activity by type. */
      .activities-section__head {
        margin-top: 14px;
        padding: 10px 0 6px;
        font-size: 10px;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        color: var(--faint);
        border-bottom: 1px dashed rgba(250,250,250,0.05);
        display: flex;
        justify-content: space-between;
        align-items: baseline;
      }
      .activities-section__head::before {
        content: '» ';
        color: var(--ghost);
        margin-right: 2px;
      }
      .activities-section__head-title { flex: 1; }
      .activities-section__head-window {
        color: var(--ghost);
        font-size: 9px;
        letter-spacing: 0.18em;
      }
      .activities-list {
        display: flex;
        flex-direction: column;
        gap: 5px;
        padding: 6px 0 2px;
      }
      .activity-row {
        display: grid;
        grid-template-columns: 96px 1fr 56px;
        gap: 8px;
        align-items: center;
        font-size: 11px;
      }
      .activity-row__name {
        color: var(--text);
        font-weight: 500;
        white-space: nowrap;
      }
      .activity-row__bar {
        height: 4px;
        background: rgba(250,250,250,0.05);
        position: relative;
        overflow: hidden;
      }
      .activity-row__bar-fill {
        position: absolute;
        inset: 0 auto 0 0;
        background: linear-gradient(
          90deg,
          #d6531c, #c53400, #d6531c, #a02a00, #c53400, #d6531c
        );
        background-size: 300% 100%;
        animation: defi-glow 5s linear infinite;
      }
      .activity-row__count {
        color: var(--text);
        font-variant-numeric: tabular-nums;
        text-align: right;
      }

      /* ── Floating app cards orbiting the sphere ─────────────────────
         Each app is fixed-positioned at one of the central area's four
         corners (between #pool-stats on the left and #tx-log on the
         right). A small SVG layer underneath (#app-leaders) draws a
         line from each card to the sphere silhouette. JS recomputes
         the line endpoints on resize + camera scale change. */
      /* Card is a 3-column × 2-row grid. The 1px gap shows through as
         dividing lines between cells because the card has a var(--line)
         background and each cell has its own dark background on top.
         The chevron column spans both rows so the V sits centered
         vertically next to the whole card body. */
      .app-card {
        position: fixed;
        z-index: 10;
        display: grid;
        /* Columns scale slightly on small screens so the card body
           doesn't crowd the sphere. Same proportional treatment as
           the side panels — keeps the constellation legible on a 14"
           Mac and on a 27" display. */
        grid-template-columns: clamp(76px, 6vw, 108px) 1fr;
        grid-template-rows: auto auto;
        gap: 1px;
        /* Explicit width (not min-width): cards must never stretch to
           fill the gutter — they're compact tiles pinned around the
           sphere. The ring-layout JS reads this rendered width when
           computing each card's bearing offset. */
        width: clamp(290px, 22vw, 420px);
        background: var(--line);
        border: 1px solid var(--line);
        border-radius: 5px;
        text-decoration: none;
        color: inherit;
        font-family: var(--mono), 'JetBrains Mono', Menlo, Consolas, monospace;
        font-size: clamp(8px, 0.58vw, 10px);
        overflow: hidden;
        transition: border-color 120ms;
        /* Depth over the sphere, without touching the card's own look:
           the cells were already 12% translucent, so blurring whatever
           passes behind them (wireframe, spikes, stars) makes the card
           read as a pane floating in front of the scene. No shadows,
           no color changes — the card UI is exactly as before. */
        backdrop-filter: blur(16px);
        -webkit-backdrop-filter: blur(16px);
      }
      .app-card > * { background: rgba(13, 13, 13, 0.88); }
      /* Very light grey wash over the whole card on hover. */
      .app-card::after {
        content: '';
        position: absolute;
        inset: 0;
        background: rgba(250, 250, 250, 0.05);
        opacity: 0;
        transition: opacity 120ms;
        pointer-events: none;
      }
      .app-card:hover::after { opacity: 1; }
      .app-card.is-active > * { background: rgba(197, 52, 0, 0.14); }
      /* Mini app cards (Opus / ForgeYields / ArcX / Ekubo) — same
         structure as the main four, scaled down. */
      .app-card--mini {
        width: clamp(180px, 13.5vw, 250px);
        grid-template-columns: clamp(58px, 4.6vw, 84px) 1fr clamp(14px, 1.1vw, 18px);
      }
      .app-card--mini .app-card__name { font-size: 9px; padding: 5px 6px; }
      .app-card--mini .app-card__head { padding: 5px 9px; }
      .app-card--mini .app-card__tagline { font-size: 9px; }
      .app-card--mini .app-card__metric-label { font-size: 8px; }
      .app-card--mini .app-card__logo { width: 22px; height: 22px; }
      .app-card--mini .app-card__vol-key { font-size: 8px; }
      .app-card--mini .app-card__vol-val { font-size: 9px; }
      .app-card.is-active { border-color: rgba(197, 52, 0, 0.55); }
      .app-card[data-position="nw"] { top: clamp(72px, 6vw, 96px); left: clamp(340px, 27vw, 460px); }
      .app-card[data-position="ne"] { top: clamp(72px, 6vw, 96px); right: clamp(364px, 29vw, 480px); }
      .app-card[data-position="sw"] { bottom: clamp(60px, 5vw, 96px); left: clamp(340px, 27vw, 460px); }
      .app-card[data-position="se"] { bottom: clamp(60px, 5vw, 96px); right: clamp(364px, 29vw, 480px); }

      /* 'coming soon' placeholder cards — identical grid scaffolding to
         the real .app-card, just every dimension scaled down. The logo
         image is heavily blurred so the source image is unrecognizable
         (intentionally vague — 'a logo will go here'). No hover/active
         color treatment since these aren't interactive. */
      .app-card--placeholder {
        grid-template-columns: clamp(30px, 2.3vw, 46px) 1fr clamp(14px, 1.1vw, 22px);
        min-width: clamp(100px, 8vw, 162px);
        font-size: clamp(6px, 0.42vw, 7.5px);
        cursor: default;
      }
      .app-card--placeholder:hover > * { background: rgba(13, 13, 13, 0.88); }
      .app-card--placeholder .app-card__name {
        font-size: 9px;
        padding: 4px 6px;
        color: #c8c4d8;
      }
      .app-card--placeholder .app-card__head {
        padding: 4px 8px;
        gap: 6px;
      }
      .app-card--placeholder .app-card__tagline {
        font-size: 8.5px;
        font-weight: 400;
        color: var(--text);
      }
      .app-card--placeholder .app-card__metric-label {
        font-size: 7.5px;
      }
      .app-card--placeholder .app-card__logo-wrap {
        padding: 5px;
      }
      .app-card--placeholder .app-card__logo {
        width: 28px;
        height: 28px;
        border-radius: 50%;
        background-image: none;
        /* Light blur so the two-tone disk reads as a soft halo without
           leaking past the logo cell. */
        filter: blur(3px);
        opacity: 0.95;
      }
      /* Per-placeholder color pair — each is a soft radial gradient so
         the blur smears two colors into a single blurry halo. */
      .app-card--placeholder[data-app="placeholder1"] .app-card__logo {
        /* light red + black */
        background: radial-gradient(circle at 35% 35%, #ff8a8a 0%, #ff4d4d 45%, var(--bg) 100%);
      }
      .app-card--placeholder[data-app="placeholder2"] .app-card__logo {
        /* purple + white */
        background: radial-gradient(circle at 35% 35%, #ffffff 0%, #c79be0 45%, #6f3aa0 100%);
      }
      .app-card--placeholder[data-app="placeholder3"] .app-card__logo {
        /* green + white */
        background: radial-gradient(circle at 35% 35%, #ffffff 0%, #88e58c 45%, #2fa343 100%);
      }
      .app-card--placeholder[data-app="placeholder4"] .app-card__logo {
        /* amber + black — south slot, completing the four-color set. */
        background: radial-gradient(circle at 35% 35%, #ffd07a 0%, #e0860d 45%, var(--bg) 100%);
      }
      .app-card--placeholder .app-card__values {
        padding: 5px 8px;
        gap: 1px;
      }
      .app-card--placeholder .app-card__vol-key {
        font-size: 8px;
      }
      .app-card--placeholder .app-card__vol-val {
        font-size: 9px;
        color: var(--faint);
      }
      .app-card--placeholder .app-card__chevron-wrap {
        opacity: 0.4;
      }
      .app-card--placeholder .app-card__chevron {
        font-size: 10px;
      }

      /* Top-left cell: app name. */
      .app-card__name {
        grid-column: 1;
        grid-row: 1;
        /* Same type size as the tagline and flex-centered on the same
           row, so e.g. ENDUR sits level with "Staking & LSTs". */
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 7px 8px;
        color: var(--text);
        font-family: var(--display);
        font-size: 10px;
        font-weight: 700;
        letter-spacing: -0.02em;
        text-transform: uppercase;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      /* Bottom-left cell: logo, centered. */
      .app-card__logo-wrap {
        grid-column: 1;
        grid-row: 2;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 10px;
      }
      .app-card__logo {
        width: 30px;
        height: 30px;
        border-radius: 50%;
        object-fit: cover;
        background: var(--bg);
      }

      /* Top-middle cell: tagline + metric label (vol. 30D). */
      .app-card__head {
        grid-column: 2;
        grid-row: 1;
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        padding: 7px 12px;
      }
      .app-card__tagline {
        color: var(--text);
        font-family: var(--display);
        font-size: 10px;
        font-weight: 600;
        letter-spacing: -0.005em;
      }
      .app-card__metric-label {
        color: var(--faint);
        font-size: 9px;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        white-space: nowrap;
      }

      /* Bottom-middle cell: public + private value rows, right-aligned. */
      .app-card__values {
        grid-column: 2;
        grid-row: 2;
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: 3px;
        padding: 8px 12px;
      }
      .app-card__row {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 10px;
        line-height: 1.2;
      }
      .app-card__vol-key {
        color: var(--faint);
        font-size: 11px;
        letter-spacing: 0.04em;
      }
      .app-card__vol-val {
        color: var(--text);
        font-size: 10px;
        font-weight: 500;
        font-variant-numeric: tabular-nums;
        text-align: right;
      }
      /* Multicolor glowing private volume — same palette as the spike
         bars on the sphere, so the row visually echoes the activity. */
      .app-card__vol-pri {
        background: linear-gradient(
          90deg,
          #d6531c,
          #c53400,
          #d6531c,
          #a02a00,
          #c53400,
          #d6531c
        );
        background-size: 300% 100%;
        -webkit-background-clip: text;
        background-clip: text;
        color: transparent;
        -webkit-text-fill-color: transparent;
        animation: defi-glow 5s linear infinite;
        filter: drop-shadow(0 0 4px rgba(197, 52, 0, 0.55));
      }
      @keyframes defi-glow {
        0% { background-position: 0% 50%; }
        100% { background-position: 100% 50%; }
      }

      /* Right column: chevron, centered vertically, spans both rows. */
      .app-card__chevron-wrap {
        grid-column: 3;
        grid-row: 1 / span 2;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      .app-card__chevron {
        color: var(--faint);
        font-size: 14px;
        line-height: 1;
        transition: transform 180ms, color 180ms;
      }
      .app-card.is-active .app-card__chevron {
        transform: rotate(180deg);
        color: var(--orange);
      }

      /* Leader-line SVG layer — sits between the sphere canvas (z:0)
         and the cards/panels (z:10). Pointer-events off so it never
         intercepts clicks. */
      #app-leaders {
        position: fixed;
        inset: 0;
        width: 100vw;
        height: 100vh;
        z-index: 5;
        pointer-events: none;
        /* Leader lines parked for now (2026-06-10, per direction) —
           drawing machinery stays live in appdropdown.js; delete this
           one line to bring them back. */
        display: none;
      }

      /* ── Uptime panel (bottom, left of the tx log) ─────────── */
      /* 90-day uptime bar chart styling. The chart and percentage
         live in the tx-log footer (see #tx-log__foot below); these
         per-bar rules just define the segment colors the JS sets. */
      .uptime-bar {
        flex: 1;
        height: 100%;
        background: #1ec97a;          /* ok */
      }
      .uptime-bar--deg { background: #ffc83b; }   /* degraded */
      .uptime-bar--inc { background: var(--orange); }   /* incident — ember */
      .uptime-bar--unk { background: var(--line); }   /* unknown — no data */


      /* ── Terminal-styled live transactions ──────────────────────
         Narrower than pool-stats: tx-cards are 1-line metrics so
         they read fine at 320px and the sphere gets more breathing
         room on the right. */
      #tx-log {
        position: fixed;
        top: 86px;
        right: 24px;
        bottom: 24px;
        /* Same responsive width treatment as #pool-stats — keeps the
           central area for the sphere proportional across screen sizes. */
        width: clamp(240px, 19.5vw, 294px);
        background: rgba(13,13,13,0.88);
        border: 1px solid var(--line);
        border-radius: 5px;
        color: var(--text);
        /* Same stack as #pool-stats so the two panel headers match. */
        font-family: var(--mono), 'JetBrains Mono', Menlo, Consolas, monospace;
        font-size: 11px;
        line-height: 1.55;
        display: flex;
        flex-direction: column;
        z-index: 10;
        pointer-events: auto;
      }
      #tx-log__head {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 10px 14px;
        border-bottom: 1px solid var(--line);
        text-transform: uppercase;
        letter-spacing: 0.2em;
        font-size: 10px;
        color: var(--dim);
      }
      /* Match #pool-stats__head h3 exactly: the site stylesheet puts all
         h3s in the display face (Unison Pro stand-in), which the POOL
         STATE title inherits — this span needs the same treatment. */
      #tx-log__head > span:first-child {
        font-family: var(--display);
        font-weight: 500;
        font-size: 10px;
        letter-spacing: 0.2em;
        line-height: 1.0;
        color: var(--dim);
      }
      #tx-log__head .live {
        color: var(--orange);
        display: inline-flex;
        align-items: center;
        gap: 6px;
      }
      #tx-log__head .live::before {
        content: '';
        width: 6px;
        height: 6px;
        background: var(--orange);
        animation: tx-blink 1.1s steps(1) infinite;
      }
      @keyframes tx-blink {
        0%, 50% { opacity: 1; }
        51%, 100% { opacity: 0.2; }
      }
      #tx-log__list {
        flex: 1;
        min-height: 0;
        overflow-y: auto;
        padding: 8px 0;
        display: flex;
        flex-direction: column;
        scrollbar-width: thin;
        scrollbar-color: var(--line) transparent;
      }
      #tx-log__list::-webkit-scrollbar { width: 6px; }
      #tx-log__list::-webkit-scrollbar-thumb { background: var(--line); }

      /* Anchor items to the bottom of the list when content is shorter
         than the container — pushes the first item down via auto-margin. */
      #tx-log__list > .tx:first-child { margin-top: auto; }

      .tx {
        padding: 8px 14px;
        border-top: 1px dashed rgba(250,250,250,0.05);
      }
      .tx:first-child { border-top: none; }

      .tx__head {
        display: flex;
        justify-content: space-between;
        font-size: 10px;
        letter-spacing: 0.15em;
        text-transform: uppercase;
        color: var(--dim);
      }
      /* Both DEPOSIT and WITHDRAWAL labels read as quiet grey — the live
         spike on the sphere is what carries the action; the row label is
         just a classifier. */
      .tx__kind,
      .tx__kind--deposit {
        color: #8a8a98;
      }
      .tx__amount {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        gap: 8px;
        margin: 2px 0;
        color: var(--text);
        font-size: 13px;
        font-weight: 500;
        font-variant-numeric: tabular-nums;
      }
      .tx__amount__left {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .tx__amount em {
        font-style: normal;
        color: var(--dim);
        font-weight: 400;
        flex-shrink: 0;
      }
      .tx__hash {
        color: var(--faint);
        font-size: 10px;
        word-break: break-all;
      }
      .tx__token-icon {
        width: 13px;
        height: 13px;
        border-radius: 50%;
        vertical-align: middle;
        margin-right: 4px;
        margin-left: 2px;
        background: var(--bg);
        object-fit: cover;
        position: relative;
        top: -1px;
      }
      .tx__line {
        color: var(--dim);
        font-size: 10px;
        line-height: 1.55;
      }
      .tx__line + .tx__line { margin-top: 1px; }
      .tx__line .label,
      .tx__hash .label {
        color: var(--faint);
        text-transform: uppercase;
        letter-spacing: 0.12em;
        font-size: 9px;
        margin-right: 8px;
      }
      .tx__defi-name {
        color: var(--text);
        font-weight: 500;
        letter-spacing: 0.04em;
      }
      .tx__arrow { color: var(--dim); margin: 0 2px; }
      .tx__private {
        color: var(--orange);
        font-weight: 500;
      }
      /* Publicly visible on-chain party (depositor addr, withdrawal
         to_addr / AVNU infra) — neutral tone so the orange [shielded]
         slots read as the special ones. */
      .tx__public {
        color: var(--dim);
        font-weight: 500;
        letter-spacing: 0.04em;
      }
      /* Inline TO row with the VIEW >> button on the right. Sharp-edged
         terminal button → Voyager; bottom-aligns with the "TO [PRIVATE]" line. */
      .tx__line--with-action {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 8px;
      }
      .tx__btn {
        display: inline-block;
        padding: 3px 8px;
        background: transparent;
        border: 1px solid #3a3a44;
        color: var(--text);
        text-decoration: none;
        font-size: 10px;
        letter-spacing: 0.16em;
        text-transform: uppercase;
        font-family: inherit;
        white-space: nowrap;
        transition: color 120ms, border-color 120ms;
      }
      .tx__btn:hover {
        border-color: var(--orange);
        color: var(--orange);
      }
      /* Footer hosts the 90-day indexer uptime panel:
           ┌──────────────────────────────────────────┐
           │ Uptime · 90D                             │  ← label
           │ [▮▮▮ ... ▮▮▮]                  99.93%   │  ← chart + pct
           │ 90D ago                       Today      │  ← tick markers
           └──────────────────────────────────────────┘
         The chart + percentage stay horizontally aligned in the
         middle row; the ticks sit under the chart only, not under
         the percentage. */
      #tx-log__foot {
        padding: 10px 14px;
        border-top: 1px solid var(--line);
        display: flex;
        flex-direction: column;
        gap: 6px;
      }
      .tx-log__foot-label {
        font-size: 9px;
        letter-spacing: 0.18em;
        text-transform: uppercase;
        color: var(--dim);
      }
      .tx-log__foot-row {
        display: flex;
        /* Top-align so the pct can center against the BAR CHART's 24px
           band (not chart + tick labels, which dragged it lower). */
        align-items: flex-start;
        gap: 12px;
      }
      .tx-log__foot-col {
        flex: 1;
        display: flex;
        flex-direction: column;
        gap: 4px;
        min-width: 0;
      }
      .tx-log__foot-chart {
        display: flex;
        align-items: flex-end;
        gap: 1px;
        height: 24px;
      }
      .tx-log__foot-ticks {
        display: flex;
        justify-content: space-between;
        font-size: 8px;
        letter-spacing: 0.16em;
        text-transform: uppercase;
        color: var(--faint);
      }
      .tx-log__foot-pct {
        /* Same 24px band as .tx-log__foot-chart, content centered, so
           the 100% sits level with the uptime bars. */
        height: 24px;
        display: flex;
        align-items: center;
        font-size: 14px;
        font-weight: 300;
        color: var(--text);
        font-variant-numeric: tabular-nums;
        letter-spacing: 0;
        line-height: 1;
      }
      .tx-log__foot-pct sup {
        font-size: 9px;
        color: var(--dim);
        margin-left: 1px;
        font-weight: 300;
      }

      /* App-card info overlay — appears anchored to a clicked card,
         covering the sphere area with a translucent backdrop. Each
         overlay is fixed-positioned by data-position so it shares
         its card's anchor corner; the inner grid-rows transition
         slides it open along the card's outward axis (down for top
         cards, up for bottom cards).
         JS injects this element per app on load. */
      .app-card-info {
        position: fixed;
        z-index: 20;
        width: clamp(290px, 22vw, 420px);
        display: grid;
        grid-template-rows: 0fr;
        transition: grid-template-rows 110ms ease-out;
      }
      /* Vesu has the longest detailed metric stack — give its popup more room. */
      .app-card-info[data-app-info="vesu"] {
        width: clamp(300px, 24.5vw, 420px);
      }
      .app-card-info.is-open { grid-template-rows: 1fr; }
      .app-card-info[data-position="nw"] { top: 138px;    left: 396px; }
      .app-card-info[data-position="ne"] { top: 138px;    right: 436px; }
      .app-card-info[data-position="sw"] { bottom: 138px; left: 396px; }
      .app-card-info[data-position="se"] { bottom: 138px; right: 436px; }
      .app-card-info__inner {
        overflow: hidden;
        min-height: 0;
        /* Same base color as the .app-card cells (rgba(13, 13, 13, …))
           but with lower alpha so the overlay reads as a more
           transparent extension of the card, not a separate dark-blue
           layer. Border matches the cards' var(--line) too. */
        background: rgba(13, 13, 13, 0.42);
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        border: 1px solid var(--line);
        border-radius: 5px;
        color: var(--text);
        font-family: var(--mono);
        font-size: 11px;
        letter-spacing: 0.04em;
        /* Content fades in slightly behind the row open so it doesn't
           visibly squash mid-animation. */
        opacity: 0;
        transition: opacity 90ms ease-out 30ms;
      }
      .app-card-info.is-open .app-card-info__inner { opacity: 1; }
      /* Inner padding only when actually open; collapsed state must
         keep height exactly 0 so the leader line stays clean. */
      .app-card-info__pad { padding: 14px; }
      .app-card-info__what {
        margin: 0 0 10px;
        font-size: 11.5px;
        line-height: 1.5;
        color: #c8c4d8;
      }
      .app-card-info__metrics {
        display: grid;
        grid-template-columns: 1fr 1fr;
        gap: 1px;
        background: rgba(250,250,250,0.05);
        margin-bottom: 12px;
      }
      /* Endur shows three stacked APY rows instead of the standard
         2-cell metric grid (STRK / strkBTC / BTC staking yields). */
      .app-card-info__metrics--list { grid-template-columns: 1fr; }
      .app-card-info__metric--row {
        display: flex;
        align-items: baseline;
        justify-content: space-between;
        gap: 12px;
        padding: 7px 10px;
      }
      .app-card-info__metric--row .app-card-info__metric-label {
        font-size: 11px;
        color: var(--text);
        letter-spacing: 0;
        text-transform: none;
      }
      .app-card-info__metric--row .app-card-info__metric-value {
        margin-top: 0;
        font-size: 13px;
        line-height: 1;
      }
      .app-card-info__metric {
        background: var(--bg);
        padding: 7px 9px;
      }
      .app-card-info__metric-label {
        font-size: 9px;
        letter-spacing: 0.16em;
        text-transform: uppercase;
        color: var(--faint);
      }
      .app-card-info__metric-value {
        margin-top: 2px;
        font-size: 14px;
        color: var(--text);
        font-weight: 300;
        font-variant-numeric: tabular-nums;
      }
      .app-card-info__pv {
        display: flex;
        flex-direction: column;
        gap: 10px;
        margin-bottom: 12px;
      }
      .app-card-info__pv-section { display: block; }
      .app-card-info__pv-head {
        font-size: 9px;
        letter-spacing: 0.18em;
        text-transform: uppercase;
        margin-bottom: 4px;
      }
      .app-card-info__pv-section--publicly .app-card-info__pv-head { color: var(--orange); }
      .app-card-info__pv-section--privately .app-card-info__pv-head { color: #a02a00; }
      .app-card-info__pv-list {
        list-style: none;
        margin: 0;
        padding: 0;
        display: flex;
        flex-direction: column;
        gap: 3px;
        font-size: 11px;
        color: #c8c4d8;
        line-height: 1.4;
      }
      .app-card-info__pv-list li::before { content: '· '; color: var(--ghost); }
      /* Footer: social icons on the left, 'open APP >>' on the right. */
      .app-card-info__foot {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        margin-top: 18px;
      }
      .app-card-info__icons {
        display: flex;
        gap: 10px;
      }
      .app-card-info__icon {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        color: var(--faint);
        text-decoration: none;
        line-height: 0;
        transition: color 120ms;
      }
      .app-card-info__icon:hover { color: var(--orange); }
      /* Matches the .tx__btn (VIEW >>) styling on the live tx log so
         buttons feel consistent across the dashboard. */
      .app-card-info__open-btn {
        display: inline-block;
        padding: 4px 10px;
        background: transparent;
        border: 1px solid #3a3a44;
        color: var(--text);
        text-decoration: none;
        font-size: 10px;
        letter-spacing: 0.16em;
        text-transform: uppercase;
        font-family: inherit;
        white-space: nowrap;
        transition: color 120ms, border-color 120ms;
      }
      .app-card-info__open-btn:hover {
        color: var(--orange);
        border-color: var(--orange);
      }

      /* ── COMING SOON treatments ────────────────────────────────────
         Two surfaces flagged with data-status="coming-soon":
           1. .app-card  — the four live app tiles around the sphere
              (Vesu / AVNU / Endur / Troves). DeFi privacy isn't live
              yet, so the cards are dimmed + a soft orange COMING SOON
              ribbon pinned to the top-right corner. Click is preserved
              so the dropdown still opens; only the visual state changes.
           2. .stat-cell — the pool stats grid cells for DeFi-related
              numbers (private transfers, lending, borrowing, swapped,
              staking). Same coming-soon ribbon, smaller, plus the
              value is dimmed so it doesn't read as a real live figure. */
      .app-card[data-status="coming-soon"] {
        position: relative;
        opacity: 0.62;
        filter: saturate(0.55);
      }
      .app-card[data-status="coming-soon"] > * {
        background: rgba(13, 13, 13, 0.92);
      }
      .app-card[data-status="coming-soon"]:hover {
        opacity: 0.78;
      }
      .app-card[data-status="coming-soon"]:hover > * {
        background: rgba(13, 13, 13, 0.92);
      }
      .app-card[data-status="coming-soon"]::after {
        content: "COMING SOON";
        position: absolute;
        top: 0;
        right: 0;
        z-index: 3;
        padding: 4px 9px;
        font-family: var(--mono, monospace);
        font-size: 8.5px;
        letter-spacing: 0.22em;
        text-transform: uppercase;
        color: var(--orange, #e86a2d);
        background: rgba(10, 10, 10, 0.82);
        border: 1px solid rgba(197, 52, 0, 0.45);
        border-top: none;
        border-right: none;
        border-bottom-left-radius: 4px;
        pointer-events: none;
        white-space: nowrap;
      }

      /* Coming-soon DeFi stat cells: no corner badge — instead replace
         the numeric value with italic "coming soon" text sitting in the
         exact spot the dollar value would occupy. The original digits
         are still in the DOM (poolstats.js writes into them on each
         metrics tick) so we just hide them with font-size: 0 and paint
         the placeholder via ::after. */
      .stat-cell[data-status="coming-soon"] .stat-cell__value {
        font-size: 0;
        line-height: 1;
        animation: none;
        filter: none;
        background: none;
        -webkit-text-fill-color: initial;
        color: transparent;
      }
      .stat-cell[data-status="coming-soon"] .stat-cell__value::after {
        content: "coming soon";
        display: inline-block;
        font-family: var(--mono, monospace);
        font-style: italic;
        font-size: 13px;
        font-weight: 400;
        letter-spacing: 0.04em;
        text-transform: none;
        color: var(--dim, #8a8595);
        -webkit-text-fill-color: var(--dim, #8a8595);
        background: none;
      }

      /* ── Mobile (≤760px) ───────────────────────────────────────
         The two dossier panels are position:fixed and sized to the
         viewport on desktop, which overlaps and clips them on phones.
         On mobile we drop them out of fixed positioning and stack them
         vertically as full-width scrollable cards, flowing over the
         Three.js globe (which stays pinned as the background). */
      @media (max-width: 760px) {
        .dashboard-root {
          position: relative;
          z-index: 1;
          display: flex;
          flex-direction: column;
          gap: 14px;
          /* clear the fixed site nav up top + breathing room at the bottom */
          padding: 78px 12px calc(32px + env(safe-area-inset-bottom, 0px));
          min-height: 100vh;
          box-sizing: border-box;
        }
        /* Mobile: hide the 3D sphere — its OrbitControls (on the canvas) hijack
           thumb-scroll (the user rotates the globe instead of scrolling). Kept
           sized (visibility, not display) so init.js doesn't choke on a 0-size
           canvas; pointer-events:none lets touches pass through to scroll. The
           static page background (.dashboard-root::before) shows through. */
        .dashboard-canvas-host { visibility: hidden !important; pointer-events: none !important; }

        #pool-stats,
        #tx-log {
          position: relative;
          inset: auto;
          top: auto; right: auto; bottom: auto; left: auto;
          width: 100%;
          max-width: 480px;
          margin: 0 auto;
        }
        /* pool-state is mostly static content — let it grow with the page */
        #pool-stats {
          height: auto;
          max-height: none;
          overflow: visible;
        }
        /* the live tx feed can be long — cap its height so the page scroll
           stays usable while the feed keeps its own internal scroll */
        #tx-log {
          height: 60vh;
          min-height: 320px;
        }
      }

      /* ── DATA section: dashboard slides up, charts slide in from below ───
         The dashboard is a fixed full-viewport 3D scene with no document
         scroll. On "Go to data", the whole dashboard view (.dashboard-stage)
         slides UP by one viewport while #data-section slides UP from below in
         lockstep — together they read as a single scroll-down. datasection.js
         toggles body.data-open (drives the stage) + #data-section.is-open. */

      /* Wrapping the dashboard layers in a transformed stage moves the sphere,
         panels, app cards and leader lines as ONE unit. The transform also
         makes this the containing block for its fixed children, but at
         translateY(0) the stage fills the viewport, so their positions (incl.
         the JS-set app-card left/top) are unchanged at rest. */
      .dashboard-stage {
        position: fixed;
        inset: 0;
        transform: translateY(0);
        transition: transform 760ms cubic-bezier(.2, .7, .2, 1);
        will-change: transform;
      }
      body.data-open .dashboard-stage { transform: translateY(-100%); }

      .go-to-data {
        position: fixed;
        left: 50%;
        bottom: 22px;
        transform: translateX(-50%);
        z-index: 20;
        display: inline-flex;
        align-items: center;
        gap: 8px;
        padding: 9px 16px;
        background: rgba(13, 13, 13, 0.88);
        border: 1px solid var(--line);
        border-radius: 5px;
        color: var(--text);
        font-family: var(--mono), 'JetBrains Mono', Menlo, Consolas, monospace;
        font-size: 11px;
        letter-spacing: 0.16em;
        text-transform: uppercase;
        cursor: pointer;
        transition: color 140ms, border-color 140ms, opacity 360ms,
                    transform 360ms cubic-bezier(.2, .7, .2, 1);
      }
      .go-to-data:hover { color: var(--orange); border-color: var(--orange); }
      .go-to-data svg { transition: transform 200ms; }
      .go-to-data:hover svg { transform: translateY(2px); }
      /* The button rides the stage up; just fade it as the slide begins
         (no transform override here — that would fight the stage transform
         it inherits from its ancestor). */
      body.data-open .go-to-data {
        opacity: 0;
        pointer-events: none;
      }

      #data-section {
        position: fixed;
        inset: 0;
        z-index: 60;
        background: var(--bg);
        transform: translateY(100%);
        transition: transform 760ms cubic-bezier(.2, .7, .2, 1);
        display: flex;
        flex-direction: column;
        overflow-y: auto;
        font-family: var(--mono), 'JetBrains Mono', Menlo, Consolas, monospace;
      }
      #data-section.is-open { transform: translateY(0); }

      /* Back button is centered (mirroring the centered Go-to-data button
         at the bottom of the dashboard); the title is pinned left so it
         doesn't pull the button off-centre. */
      .data-section__head {
        position: relative;
        flex: 0 0 auto;
        display: flex;
        justify-content: center;
        align-items: center;
        padding: 18px 24px;
        border-bottom: 1px solid var(--line);
      }
      /* Visual twin of .go-to-data so the pair reads as one scroll control:
         centered pill at the bottom (Go to data ↓) / top (↑ Back). */
      .data-section__back {
        display: inline-flex;
        align-items: center;
        gap: 8px;
        padding: 9px 16px;
        background: rgba(13, 13, 13, 0.88);
        border: 1px solid var(--line);
        border-radius: 5px;
        color: var(--text);
        font-family: var(--mono), 'JetBrains Mono', Menlo, Consolas, monospace;
        font-size: 11px;
        letter-spacing: 0.16em;
        text-transform: uppercase;
        cursor: pointer;
        transition: color 140ms, border-color 140ms;
      }
      .data-section__back:hover { border-color: var(--orange); color: var(--orange); }
      .data-section__back svg { transition: transform 200ms; }
      .data-section__back:hover svg { transform: translateY(-2px); }
      .data-section__title {
        position: absolute;
        left: 24px;
        top: 50%;
        transform: translateY(-50%);
        font-family: var(--display);
        font-size: 11px;
        font-weight: 500;
        letter-spacing: 0.24em;
        text-transform: uppercase;
        color: var(--dim);
      }
      /* On narrow screens the centered pill needs the full width — drop the
         left-pinned title so they can't collide. */
      @media (max-width: 600px) {
        .data-section__title { display: none; }
      }

      .data-section__grid {
        flex: 0 0 auto;
        display: grid;
        grid-template-columns: 1fr 1fr;
        /* Two rows fill the viewport (the 2×2 fits a 14" screen); the 3rd row
           — the 5th chart — sits just below the fold, so the top of it peeks
           to invite a scroll. ~140px ≈ header + paddings + inter-row gap. */
        grid-auto-rows: calc((100vh - 140px) / 2);
        gap: 16px;
        padding: 18px 24px 40px;
      }
      @media (max-width: 860px) {
        /* Single column: charts stack and the section scrolls. Each row gets a
           fixed, readable height in dvh (so the mobile URL bar collapsing can't
           squash the plots) instead of the desktop "half the viewport" math.
           Tighter gutters hand width back to the plot area. */
        .data-section__grid {
          grid-template-columns: 1fr;
          grid-template-rows: none;
          grid-auto-rows: clamp(240px, 45dvh, 320px);
          gap: 12px;
          padding: 14px 12px 32px;
        }
        /* A desktop full-width chart is just a normal cell in one column. */
        .data-chart--wide { grid-column: auto; }
      }
      @media (max-width: 480px) {
        /* Phones: trim chrome so the plot dominates the cell, and give the
           nav pills a thumb-sized tap target. */
        .data-chart { padding: 12px 10px 12px; }
        .data-chart__label { font-size: 11px; letter-spacing: 0.12em; margin-bottom: 10px; }
        .data-shielded__tip { min-width: 158px; padding: 9px 10px; font-size: 11px; }
        .data-section__head { padding: 14px; }
        .data-section__back, .go-to-data { padding: 12px 18px; }
      }
      /* Full-width chart — spans both grid columns (e.g. Private Actions). */
      .data-chart--wide { grid-column: 1 / -1; }
      .data-chart {
        min-width: 0;
        min-height: 0;
        display: flex;
        flex-direction: column;
        background: rgba(13, 13, 13, 0.6);
        border: 1px solid var(--line);
        border-radius: 6px;
        padding: 16px 18px 18px;
      }
      .data-chart__label {
        display: flex;
        align-items: baseline;
        gap: 10px;
        margin-bottom: 14px;
        font-family: var(--display);
        font-size: 12px;
        font-weight: 600;
        letter-spacing: 0.18em;
        text-transform: uppercase;
        color: var(--text);
      }
      .data-chart__unit {
        font-family: var(--mono), monospace;
        font-size: 9px;
        font-weight: 400;
        letter-spacing: 0.1em;
        text-transform: none;
        color: var(--faint);
      }
      .data-chart__canvas { width: 100%; flex: 1 1 auto; min-height: 0; }
      .data-chart__empty {
        height: 100%;
        min-height: 0;
        display: grid;
        place-items: center;
        color: var(--faint);
        font-size: 11px;
        letter-spacing: 0.14em;
        text-transform: uppercase;
      }
      /* Legend for the Volume stacked-bars chart — color key per category. */
      .data-volume-legend {
        display: flex;
        flex-wrap: wrap;
        gap: 4px 12px;
        margin-bottom: 12px;
        font-size: 9px;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: var(--faint);
      }
      .data-volume-legend span { display: inline-flex; align-items: center; gap: 5px; }
      .data-volume-legend i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }
      /* "coming soon" protocols in the routed-volume legend — dimmed + tag. */
      .data-volume-legend .legend-soon { opacity: 0.45; }
      .data-volume-legend .legend-soon i { background: #3a3a44; }
      .data-volume-legend .legend-soon em {
        font-style: normal; margin-left: 4px; font-size: 8px;
        letter-spacing: 0.1em; text-transform: uppercase; color: var(--orange);
      }

      /* Hover tooltip: date + per-token rows + total, mirroring the reference. */
      .data-shielded__tip {
        position: absolute;
        z-index: 5;
        min-width: 196px;
        padding: 10px 12px;
        background: rgba(10, 10, 12, 0.96);
        border: 1px solid var(--line);
        border-radius: 6px;
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
        pointer-events: none;
        font-size: 12px;
      }
      .data-shielded__tip[hidden] { display: none; }
      .data-shielded__tip-date {
        margin-bottom: 8px;
        font-family: var(--mono), 'JetBrains Mono', Menlo, Consolas, monospace;
        font-size: 12px;
        font-weight: 600;
        color: #fff;
      }
      .data-shielded__tip-row,
      .data-shielded__tip-total {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 18px;
        padding: 2px 0;
        color: rgba(255, 255, 255, 0.7);
      }
      .data-shielded__tip-row span { display: inline-flex; align-items: center; gap: 7px; }
      .data-shielded__tip-row i { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
      .data-shielded__tip-row b { color: rgba(255, 255, 255, 0.92); font-variant-numeric: tabular-nums; font-weight: 500; }
      .data-shielded__tip-total {
        margin-top: 6px;
        padding-top: 8px;
        border-top: 1px solid var(--line);
        color: #fff;
      }
      .data-shielded__tip-total b { font-variant-numeric: tabular-nums; }
      .data-shielded__bars > div { cursor: crosshair; }
