      .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: 40px;
        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;
      }
      .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(58px, 4.5vw, 74px) 1fr clamp(22px, 1.7vw, 30px);
        grid-template-rows: auto auto;
        gap: 1px;
        min-width: clamp(172px, 13vw, 248px);
        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;
      }
      .app-card > * { background: rgba(13, 13, 13, 0.88); transition: background 120ms; }
      .app-card:hover > * { background: rgba(197, 52, 0, 0.10); }
      .app-card.is-active > * { background: rgba(197, 52, 0, 0.14); }
      .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;
        padding: 6px 3px;
        color: var(--text);
        font-family: var(--display);
        font-size: clamp(9px, 0.72vw, 11px);
        font-weight: 700;
        letter-spacing: -0.02em;
        text-transform: uppercase;
        text-align: center;
        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: 38px;
        height: 38px;
        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: baseline;
        justify-content: space-between;
        gap: 12px;
        padding: 7px 12px;
      }
      .app-card__tagline {
        color: var(--text);
        font-family: var(--display);
        font-size: 11.5px;
        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: 11px;
        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;
      }

      /* ── 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);
        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);
      }
      #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__private {
        color: var(--orange);
        font-weight: 500;
      }
      /* 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;
        align-items: center;
        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 {
        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(240px, 19.5vw, 330px);
        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);
      }

      /* Leader SVG is part of the previous "ring around the sphere"
         layout. The column stack on the bottom-right doesn't have
         cards adjacent to the sphere, so leader polylines would draw
         long ugly diagonals across the canvas. Hidden globally; the
         <svg id="app-leaders"> stays in the DOM so the column layout
         JS doesn't need to know about it. */
      #app-leaders { display: none; }

      /* ── 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;
      }
