  /* Shared system — same as scan-result page */
  :root {
    --bg:       #03051a;
    --bg-elev:  #080c28;
    --bg-elev2: #0e1336;
    --line:     #1a2046;
    --line-2:   #232a55;
    --text:     #e8eaf2;
    --text-dim: #7e84a8;
    --text-faint:#4e527a;
    --accent:    #a8a8e0;
    --accent-dim:#5e5fa8;
    --good:      #6dc794;
    --warn:      #e3c87a;
    --bad:       #e08070;
    --good-dim:  rgba(109,199,148,0.18);
    /* Classification identity colors (2026-07-21). One
       dedicated token per category — bundled red, cabaled amber-gold
       (its own color, distinct from generic warn straw-yellow), organic
       blue by decree (2026-07-16: a green verdict reads as a buy
       signal). --good stays green for generic positives. */
    --cls-bundled: #e08070;
    --cls-cabaled: #dc9e47;
    --cls-organic: #6ea8ff;
    --organic:   var(--cls-organic); /* legacy alias — new code uses --cls-organic */
    --organic-dim: rgba(110,168,255,0.18);
    --warn-dim:  rgba(227,200,122,0.18);
    --bad-dim:   rgba(224,128,112,0.18);
    --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
    --sans: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
    --pad-x: 56px;
    --col-max: 1480px;
  }
  *, *::before, *::after { box-sizing: border-box; }
  html, body { margin: 0; padding: 0; background: var(--bg); color: var(--text); font-family: var(--sans); font-size: 14px; line-height: 1.5; -webkit-font-smoothing: antialiased; }
  body { min-height: 100vh; }
  a { color: inherit; text-decoration: none; }
  ::selection { background: rgba(168,168,224,0.3); color: var(--text); }

  body::before {
    content: ""; position: fixed; inset: 0; pointer-events: none; z-index: 0;
    background:
      radial-gradient(1200px 600px at 80% -10%, rgba(168,168,224,0.06), transparent 60%),
      radial-gradient(900px 500px at -10% 100%, rgba(168,168,224,0.04), transparent 60%);
  }
  #app { position: relative; z-index: 1; }

  .container { max-width: var(--col-max); margin: 0 auto; padding: 0 var(--pad-x); }
  .uplabel { font-family: var(--mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-dim); }
  .uplabel-faint { font-family: var(--mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-faint); }
  .num { font-family: var(--sans); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
  .num-tab { font-family: var(--sans); font-variant-numeric: tabular-nums; letter-spacing: -0.005em; }
  .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
  .text-dim { color: var(--text-dim); }
  .text-faint { color: var(--text-faint); }
  .row-between { display: flex; justify-content: space-between; align-items: baseline; }

  /* Topbar — a generous brand header. No border, no sticky. Logo sits big
     and centered in the vertical space above the search. Nav links float
     top-right. */
  .topbar {
    position: relative;
    min-height: 132px;
    display: flex; align-items: center; justify-content: center;
    padding: 32px var(--pad-x) 24px;
  }
  /* Logo centred, nav right — but as grid columns, not as an absolutely
     positioned nav floating over a centred logo. Out of flow the nav reserved
     no width, and between roughly 900px and 1150px it landed straight on top
     of the logo (measured); columns shrink and shuffle instead of colliding.
     Markup order is nav-then-brand, so the columns are assigned explicitly. */
  .topbar .row {
    width: 100%; max-width: var(--col-max); margin: 0 auto; position: relative;
    display: grid; grid-template-columns: 1fr auto 1fr;
    align-items: center; column-gap: 24px;
  }
  .brand {
    display: flex; align-items: baseline; gap: 12px;
    justify-content: center;
    grid-column: 2; justify-self: center;
  }
  .brand-mark {
    font-family: var(--mono);
    font-size: 32px;
    letter-spacing: 0.02em;
    color: var(--text);
    line-height: 1;
    font-weight: 500;
  }
  .brand-mark .brand-underscore {
    color: var(--accent);
    animation: search-caret-blink 1.05s steps(2, end) infinite;
  }
  .brand-dot {
    width: 10px; height: 10px; border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 16px var(--accent);
    transform: translateY(-2px);
  }
  .topbar-nav {
    grid-column: 3; justify-self: end;
    display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px 24px;
    color: var(--text-dim); min-width: 0;
  }
  .topbar-nav a { font-family: var(--mono); font-size: 12px; letter-spacing: 0.04em; white-space: nowrap; }
  .topbar-nav a:hover { color: var(--text); }

  /* Narrow windows: side by side stops fitting, so the header stacks — logo
     first, links centred underneath. Every link stays on screen and nothing
     pushes the page wider than the viewport. */
  @media (max-width: 900px) {
    .topbar { min-height: 0; padding: 26px var(--pad-x) 18px; }
    .topbar .row {
      display: flex; flex-direction: column-reverse; align-items: center; gap: 16px;
    }
    .topbar-nav { justify-content: center; gap: 12px 18px; max-width: 100%; }
  }
  @media (max-width: 640px) {
    .topbar { padding: 22px 20px 16px; }
  }

  /* Page wrap */
  .page-wrap { padding: 0; }

  /* Search row — input-scaled, no border, subtle tinted region. A blinking
     caret signals "type here"; the [ enter ↵ ] hint at the right shows how
     to submit. Tint lifts on hover/focus. */
  .search-row {
    max-width: var(--col-max);
    margin: 0 auto;
    padding: 24px var(--pad-x) 28px;
  }
  .search-region {
    display: flex; align-items: center; gap: 12px;
    padding: 14px 18px;
    background: rgba(168, 168, 224, 0.025);
    transition: background 0.2s;
  }
  /* The label wraps only caret+input so the paste/scan buttons beside it
     don't inherit label activation (a tap on "paste" must not also focus
     the field and pop the keyboard). */
  .search-field {
    display: flex; align-items: center; gap: 12px;
    flex: 1 1 auto; min-width: 0;
    cursor: text;
  }
  .search-region:hover { background: rgba(168, 168, 224, 0.05); }
  .search-region.focused { background: rgba(168, 168, 224, 0.08); }
  .search-region.errored { background: rgba(224, 128, 112, 0.08); }

  .search-caret {
    color: var(--accent);
    font-family: var(--mono);
    font-size: 15px;
    line-height: 1;
    margin-right: -8px;
    animation: search-caret-blink 1.05s steps(2, end) infinite;
    pointer-events: none;
  }
  @keyframes search-caret-blink {
    0%, 49% { opacity: 1; }
    50%, 100% { opacity: 0; }
  }

  .search-input {
    background: transparent; border: 0; outline: none;
    color: var(--text);
    font-family: var(--mono);
    font-size: 15px;
    letter-spacing: 0;
    flex: 1 1 auto;
    padding: 0;
    line-height: 1.3;
    min-width: 0;
    caret-color: var(--accent);
  }
  .search-input::placeholder {
    color: var(--text-faint);
    font-family: var(--mono);
    font-weight: 400;
  }

  .search-hint {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.06em;
    color: var(--text-faint);
    flex: 0 0 auto;
    line-height: 1;
    transition: color 0.15s;
    white-space: nowrap;
    user-select: none;
  }
  .search-hint .kbd-glyph {
    color: var(--text-dim);
    margin: 0 1px;
  }
  .search-region.focused .search-hint,
  .search-hint.ready { color: var(--accent); }
  .search-region.focused .search-hint .kbd-glyph,
  .search-hint.ready .kbd-glyph { color: var(--accent); }
  .search-region.errored .search-hint { color: var(--bad); }

  /* Tap buttons for touch layouts — hidden on desktop, where the enter-key
     hint stays the affordance. */
  .search-actions { display: none; flex: 0 0 auto; align-items: center; gap: 8px; }
  .search-btn {
    font-family: var(--mono);
    font-size: 13px;
    letter-spacing: 0.04em;
    color: var(--accent);
    background: rgba(110, 168, 255, 0.08);
    border: 1px solid rgba(110, 168, 255, 0.28);
    border-radius: 2px;
    padding: 9px 16px;
    min-height: 40px;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s, border-color 0.15s;
  }
  .search-btn:active { background: rgba(110, 168, 255, 0.18); }
  .search-btn-go { background: rgba(110, 168, 255, 0.14); border-color: rgba(110, 168, 255, 0.45); }

  @media (max-width: 720px) {
    .search-row { padding-top: 40px; }
    .search-region { padding: 10px 10px 10px 14px; }
    /* 16px is the iOS floor: anything smaller makes Safari force-zoom the
       page when the field is focused. */
    .search-input { font-size: 16px; }
    .search-actions { display: flex; }
    /* The enter-key hint is a keyboard affordance — meaningless on touch.
       Errors still surface through it. */
    .search-hint { display: none; }
    .search-hint.has-error { display: block; white-space: normal; font-size: 10px; max-width: 34vw; }
  }

  /* Filter strip */
  .filter-strip {
    padding: 22px var(--pad-x) 16px;
    max-width: var(--col-max); margin: 0 auto;
    display: flex; align-items: center;
    flex-wrap: wrap; gap: 16px;
  }
  .filter-strip-left {
    display: flex; align-items: center; gap: 32px;
    flex-wrap: wrap;
  }
  .filter-strip-right { margin-left: auto; display: flex; align-items: center; gap: 16px; }

  /* Filter chips — no boxes, no pills. Reads as inline editorial controls:
     muted label, value in body color, caret. Engaged state lifts the value
     to accent. Hover underlines the value subtly. */
  .filter-chip { position: relative; }
  .filter-chip-trigger {
    background: transparent;
    border: 0;
    padding: 8px 0;
    height: auto;
    display: inline-flex; align-items: baseline; gap: 10px;
    cursor: pointer;
    color: var(--text-dim);
    transition: color 0.15s;
  }
  .filter-chip-trigger > svg { align-self: center; color: var(--text-faint); transition: color 0.15s; }
  .filter-chip-trigger:hover { color: var(--text); }
  .filter-chip-trigger:hover .filter-chip-value { box-shadow: inset 0 -1px 0 var(--accent-dim); }
  .filter-chip.open .filter-chip-trigger { color: var(--text); }
  .filter-chip.open .filter-chip-trigger > svg { color: var(--accent); }
  .filter-chip.engaged .filter-chip-trigger { color: var(--text); }
  .filter-chip.engaged .filter-chip-value { color: var(--accent); box-shadow: inset 0 -1px 0 var(--accent-dim); }

  .filter-chip-label {
    font-family: var(--mono);
    font-size: 10.5px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-faint);
  }
  .filter-chip-value {
    font-family: var(--sans); font-weight: 500;
    font-size: 13px;
    color: inherit;
    letter-spacing: -0.005em;
    padding-bottom: 1px;
    transition: box-shadow 0.15s, color 0.15s;
  }
  .filter-menu {
    position: absolute; top: calc(100% + 4px); left: 0;
    min-width: 140px;
    background: var(--bg-elev);
    border: 1px solid var(--line);
    z-index: 30;
    padding: 4px 0;
    box-shadow: 0 12px 32px rgba(0,0,0,0.6);
  }
  .filter-opt {
    background: transparent; border: 0;
    width: 100%;
    text-align: left;
    padding: 7px 14px;
    color: var(--text-dim);
    font: 500 12px var(--sans);
    letter-spacing: -0.005em;
    cursor: pointer;
    white-space: nowrap;
  }
  .filter-opt:hover { background: rgba(168,168,224,0.06); color: var(--text); }
  .filter-opt.active { color: var(--accent); background: rgba(168,168,224,0.04); }

  .filter-clear {
    background: transparent; border: 0;
    color: var(--text-faint);
    font: 500 11px var(--mono);
    letter-spacing: 0.06em;
    cursor: pointer;
    padding: 6px 10px;
    transition: color 0.15s;
  }
  .filter-clear:hover { color: var(--accent); }

  /* View toggle — text + small icon, underline-active. No border. */
  .view-toggle {
    display: inline-flex;
    gap: 22px;
  }
  .vt-btn {
    background: transparent; border: 0;
    padding: 6px 0 7px;
    color: var(--text-faint);
    font: 500 11px var(--mono);
    letter-spacing: 0.1em; text-transform: uppercase;
    display: inline-flex; align-items: center; gap: 8px;
    cursor: pointer;
    border-bottom: 1px solid transparent;
    transition: color 0.15s, border-color 0.15s;
  }
  .vt-btn:hover { color: var(--text); }
  .vt-btn.active { color: var(--text); border-bottom-color: var(--accent); }
  .vt-btn svg { color: inherit; }

  /* Table */
  .table-area {
    padding: 24px var(--pad-x) 0;
    max-width: var(--col-max); margin: 0 auto;
    overflow-x: auto;
  }
  table.pt { width: 100%; border-collapse: collapse; min-width: 880px; }
  table.pt thead th {
    text-align: left;
    font: 500 11px var(--mono);
    color: var(--text-dim);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 14px 12px 14px 0;
    font-weight: 500;
    border-bottom: 1px solid var(--line);
    user-select: none;
    position: relative;
  }
  table.pt thead th:last-child { padding-right: 0; }
  table.pt thead th.sortable { cursor: pointer; transition: color 0.15s; }
  table.pt thead th.sortable:hover { color: var(--text); }
  table.pt thead th.sortable.active { color: var(--text); }
  table.pt thead th.right, table.pt td.right { text-align: right; padding-right: 0; padding-left: 24px; }
  table.pt thead th.right { padding-right: 0; }
  table.pt thead th.left { text-align: left; }

  table.pt tbody td {
    padding: 14px 12px 14px 0;
    font-size: 13px;
    border-bottom: 1px solid var(--line);
    vertical-align: middle;
    transition: background 0.15s;
  }
  table.pt tbody td:last-child { padding-right: 0; }
  table.pt tbody tr.row { cursor: pointer; }
  /* Pinned site token (owner 2026-08-07; reworked 2026-08-12: "more subtle,
     flowing, no fill"). No cell borders and NO interior tint — the frame is
     a hairline ring drawn by the .pin-flow overlay (rendered by ProjectRow
     when p.pinned): a masked 1px ring in the organic blue at low alpha,
     with a soft light drifting left-to-right along it. The overlay
     positions against the ROW (position:relative on the tr); pointer-events
     none, cosmetic-only. Hover stays the ordinary row hover. */
  table.pt tbody tr.row-pinned td:first-child { position: relative; }
  /* The ring must not fight the table's hairlines (owner 2026-08-12): the
     thead underline and the pinned row's own cell borders would cross its
     corners, so both go transparent (color only — the 1px stays, no
     reflow). The ring itself is the separation. */
  table.pt:has(tbody tr.row-pinned) thead th { border-bottom-color: transparent; }
  table.pt tbody tr.row-pinned td { border-bottom-color: transparent; }
  .pin-flow {
    position: absolute;
    /* Extends 12px past the row on both sides ("too close to logo and
       chart end") — safe: .table-area keeps >=16px lateral padding at
       every breakpoint, so the overhang never creates scroll overflow. */
    left: -12px;
    top: 0;
    /* width/height are set to the ROW's box (+24px width) at runtime
       (PinFlow's ResizeObserver) — a positioned <tr> is not a containing
       block in Chrome, so the first cell anchors the overlay instead. */
    border-radius: 8px;
    padding: 1px; /* ring thickness */
    pointer-events: none;
    background: rgba(110, 168, 255, 0.16);
    /* One ring mask on the parent clips BOTH sweep sheets below to the
       hairline, so the pseudos stay simple full-box gradients. */
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    mask-composite: exclude;
    overflow: hidden;
  }
  /* Two independent lights, same glint, co-prime periods (7.5s and 11s):
     their phase drifts continuously, so the pattern never repeats the
     same way — lone passes, staggered pairs, occasional crossings — and
     a pass happens roughly every 4-5s (owner 2026-08-12: "more often,
     different patterns, exact same effect"). */
  .pin-flow::before,
  .pin-flow::after {
    content: "";
    position: absolute;
    inset: 0;
  }
  /* FOUR lights, two per sheet, all the same glint (owner 2026-08-12:
     "more lights, more patterns"). Each sheet carries a bright narrow
     band and a faint wide one on repeating tiles; the keyframes move the
     two layers different whole numbers of tiles per cycle (whole numbers,
     or the loop seam snaps), so within one sheet the pair beats against
     itself, and the two sheets run opposite directions on 36s vs 44s —
     the full choreography only realigns every ~6.5 minutes.
     Cadence: ~5s, 12s, 11s and 22s per light — something is usually
     moving, rarely the same thing twice. */
  .pin-flow::before {
    background:
      linear-gradient(
          100deg,
          transparent 38%,
          rgba(110, 168, 255, 0.42) 50%,
          transparent 62%
        )
        200% 0 / 300% 100% repeat-x,
      linear-gradient(
          95deg,
          transparent 30%,
          rgba(110, 168, 255, 0.2) 50%,
          transparent 70%
        )
        40% 0 / 500% 100% repeat-x;
    animation: pin-flow-weave 36s linear infinite;
  }
  .pin-flow::after {
    /* Return pair: opposite direction, opposite slant, softer. */
    background:
      linear-gradient(
          80deg,
          transparent 36%,
          rgba(110, 168, 255, 0.3) 50%,
          transparent 64%
        )
        -100% 0 / 300% 100% repeat-x,
      linear-gradient(
          85deg,
          transparent 28%,
          rgba(110, 168, 255, 0.15) 50%,
          transparent 72%
        )
        -60% 0 / 500% 100% repeat-x;
    animation: pin-flow-weave-back 44s linear infinite;
    animation-delay: 3s;
  }
  /* Tile math: with tile widths 300%/500%, one full tile of travel is a
     position delta of 150%/125% respectively — the deltas below are 7 and
     3 whole tiles (before) and 4 and 2 (after), so every layer loops
     seamlessly. Decreasing position = light travels left-to-right. */
  @keyframes pin-flow-weave {
    0% { background-position: 200% 0, 40% 0; }
    100% { background-position: -850% 0, -335% 0; }
  }
  @keyframes pin-flow-weave-back {
    0% { background-position: -100% 0, -60% 0; }
    100% { background-position: 500% 0, 190% 0; }
  }
  @media (prefers-reduced-motion: reduce) {
    .pin-flow::before,
    .pin-flow::after {
      animation: none;
      background: none;
    }
  }
  table.pt tbody tr.row:hover td { background: rgba(168,168,224,0.04); }

  /* Project cell */
  .proj-cell { display: flex; align-items: center; gap: 12px; padding-right: 12px; }
  .proj-launcher {
    display: inline-flex; align-items: center; justify-content: center;
    width: 22px; height: 22px;
    color: var(--text-dim);
    flex: 0 0 22px;
    transition: color 0.15s;
  }
  .row:hover .proj-launcher { color: var(--accent); }
  .proj-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .proj-name {
    font: 500 14px var(--sans);
    color: var(--text);
    letter-spacing: -0.005em;
    line-height: 1.2;
    white-space: nowrap;
  }
  .proj-ticker {
    font: 500 11px var(--mono);
    color: var(--text-dim);
    letter-spacing: 0.04em;
    line-height: 1.2;
  }

  /* Chain glyph */
  .chain-glyph {
    color: var(--text-dim);
    display: inline-flex;
    transition: color 0.15s;
  }
  .row:hover .chain-glyph { color: var(--text); }

  /* Verdict mark — left block has the dot prefix, then a stacked column with
     the verdict word on top and the timestamp directly below it, centered
     under the word (so "36M AGO"'s center sits under the center of "Organic"
     regardless of which word it is). The score sits to the right of that
     block, vertically centered between the verdict line and the timestamp
     line. */
  .verdict-stack {
    display: flex; flex-direction: column;
    gap: 6px;
    align-items: flex-start;
    min-height: 56px;
    justify-content: center;
  }
  .col-verdict { min-height: 56px; vertical-align: middle; }
  .verdict-mark {
    display: inline-flex; align-items: center;
    gap: 14px;
    cursor: default;
    transition: opacity 0.15s;
  }
  .verdict-mark .vm-row {
    display: inline-flex; align-items: flex-start; gap: 8px;
  }
  .verdict-mark .vm-dot {
    width: 6px; height: 6px; border-radius: 50%;
    flex: 0 0 6px;
    margin-top: 4px;
    box-shadow: 0 0 8px currentColor;
  }
  .verdict-mark .vm-label-stack {
    display: flex; flex-direction: column;
    align-items: center;
    gap: 6px;
    line-height: 1;
  }
  .verdict-mark .vm-label {
    font: 500 13px var(--sans);
    letter-spacing: 0.01em;
    line-height: 1;
  }
  .verdict-mark .vm-freshness {
    font: 500 10.5px var(--mono);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-dim);
    line-height: 1;
    white-space: nowrap;
  }
  .verdict-mark .vm-score {
    font: 500 16px var(--sans);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
    line-height: 1;
  }
  .freshness {
    font: 500 10.5px var(--mono);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-dim);
    line-height: 1;
    white-space: nowrap;
  }
  .scan-link {
    background: transparent; border: 0;
    color: var(--accent);
    font: 500 11px var(--mono);
    letter-spacing: 0.06em; text-transform: uppercase;
    cursor: pointer;
    padding: 4px 0;
    transition: color 0.15s;
  }
  .scan-link:hover { color: var(--text); }

  /* Rescan spinner */
  .rescan-spinner {
    display: inline-flex; align-items: center; gap: 8px;
    color: var(--text-dim);
    font: 500 11px var(--mono); letter-spacing: 0.06em; text-transform: uppercase;
  }
  .spin { animation: spin 1s linear infinite; transform-origin: center; }
  @keyframes spin { from { transform: rotate(0); } to { transform: rotate(360deg); } }

  /* Mini spark cell — fixed width so column doesn't shift */
  .col-chart { width: 110px; }
  .mini-spark { display: inline-block; }

  /* Sort arrow */
  .sort-arrow { color: var(--accent); display: inline-flex; }

  /* Interval picker (Δ column header) */
  th.interval-header {
    text-align: right;
    padding-right: 0;
    padding-left: 24px;
    position: relative;
  }
  th.interval-header.active .interval-sort { color: var(--text); }
  .interval-sort { color: inherit; }
  .interval-trigger {
    background: transparent;
    border: 0;
    color: var(--text);
    padding: 4px 8px 5px;
    margin: 0 -4px;
    font: 500 11px var(--mono);
    letter-spacing: 0.1em;
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
    border-bottom: 1px solid var(--accent-dim);
    transition: color 0.15s, border-color 0.15s, background 0.15s;
  }
  .interval-trigger:hover {
    border-bottom-color: var(--accent);
    background: rgba(168,168,224,0.08);
  }
  .interval-trigger.open {
    border-bottom-color: var(--accent);
    color: var(--accent);
    background: rgba(168,168,224,0.08);
  }
  .interval-trigger svg { color: var(--accent); transition: transform 0.15s; }
  .interval-trigger:hover svg { transform: translateY(1px); }
  .interval-trigger.open svg { transform: rotate(180deg); }
  .interval-menu {
    position: absolute; top: calc(100% + 4px); right: 0;
    background: var(--bg-elev);
    border: 1px solid var(--line-2);
    z-index: 30;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    box-shadow: 0 12px 32px rgba(0,0,0,0.6);
  }
  .interval-opt {
    background: transparent; border: 0;
    padding: 8px 14px;
    color: var(--text-dim);
    font: 500 11px var(--mono);
    letter-spacing: 0.1em;
    cursor: pointer;
    min-width: 54px;
    transition: background 0.15s, color 0.15s;
  }
  .interval-opt:hover { background: rgba(168,168,224,0.06); color: var(--text); }
  .interval-opt.active { color: var(--accent); background: rgba(168,168,224,0.08); }

  /* Empty state */
  .table-empty {
    padding: 100px 0;
    display: flex; flex-direction: column; align-items: center; gap: 12px;
    color: var(--text-faint);
    max-width: var(--col-max);
    margin: 24px auto 0;
    border-top: 1px solid var(--line);
  }
  .te-glyph { font: 300 40px var(--sans); color: var(--text-faint); letter-spacing: 0; }
  .te-msg {
    font: 500 11px var(--mono); letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--text-faint);
  }
  .te-action {
    background: transparent; border: 0;
    color: var(--accent);
    font: 500 11px var(--mono);
    letter-spacing: 0.1em; text-transform: uppercase;
    cursor: pointer;
    transition: color 0.15s;
  }
  .te-action:hover { color: var(--text); }

  /* Verdict tooltip */
  .v-tooltip {
    background: var(--bg);
    border: 1px solid var(--line);
    padding: 12px 14px;
    box-shadow: 0 14px 36px rgba(0,0,0,0.65);
    min-width: 240px;
  }
  .vt-head {
    display: flex; align-items: baseline; gap: 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--line);
  }
  .vt-class {
    font: 500 13px var(--sans);
    letter-spacing: -0.005em;
  }
  .vt-score {
    font: 500 18px var(--sans);
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
    color: var(--text);
    margin-left: auto;
  }
  .vt-of { font-size: 11px; color: var(--text-faint); }
  .vt-rows { display: grid; grid-template-columns: 1fr; gap: 6px; padding: 10px 0 4px; }
  .vt-row {
    display: grid;
    grid-template-columns: 8px 1fr auto;
    align-items: baseline;
    gap: 10px;
  }
  .vt-dot { width: 6px; height: 6px; border-radius: 50%; align-self: center; }
  .vt-dot.good { background: var(--good); }
  .vt-dot.warn { background: var(--warn); }
  .vt-dot.bad  { background: var(--bad); }
  .vt-lbl { font: 500 10px var(--mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-dim); }
  .vt-val { font: 500 12px var(--sans); font-variant-numeric: tabular-nums; color: var(--text); }
  .vt-foot {
    font: 500 9.5px var(--mono); letter-spacing: 0.1em; text-transform: uppercase;
    color: var(--text-faint); padding-top: 8px; border-top: 1px solid var(--line); margin-top: 6px;
  }

  /* Footer row */
  .ft-row {
    padding: 24px var(--pad-x) 64px;
    max-width: var(--col-max); margin: 0 auto;
    display: flex; justify-content: space-between; align-items: baseline;
    color: var(--text-faint);
    font: 500 10.5px var(--mono); letter-spacing: 0.08em; text-transform: uppercase;
  }
  .ft-meta .ft-num { color: var(--text); font-variant-numeric: tabular-nums; }

  /* Responsive column collapse — priority order: TXNS → VOLUME → AGE.
     Verdict, MCAP, HOLDERS, Δ, Chart must always remain visible. */
  @media (max-width: 1280px) {
    table.pt thead th.col-txns, table.pt tbody td.col-txns { display: none; }
  }
  @media (max-width: 1100px) {
    table.pt thead th.col-volume, table.pt tbody td.col-volume { display: none; }
  }
  @media (max-width: 960px) {
    table.pt thead th.col-age, table.pt tbody td.col-age { display: none; }
    table.pt { min-width: 0; }
  }
  .site-footer { text-align: center; padding: 26px 16px 30px; font-size: 12px; color: var(--text-faint); letter-spacing: 0.04em; position: relative; z-index: 1; }
  .site-footer a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
  .site-footer a:hover { color: var(--text); }

  /* ── Compare view ──────────────────────────────────────────────────────
     Landing "Compare" toggle — a picker (watchlist quick-add + paste an
     address) above a row of per-token cards. Cards, not a literal <table>:
     a real row-aligned table has no good pure-CSS path to a stacked mobile
     layout, and this feature is explicitly judged at ~375px (see the
     640px flex-direction flip below, same breakpoint analysis.css uses to
     collapse its grids to 1 column). */
  .compare-view {
    padding: 24px var(--pad-x) 8px;
    max-width: var(--col-max); margin: 0 auto;
  }
  .cmp-picker {
    padding: 16px 20px;
    background: rgba(168, 168, 224, 0.025);
    margin-bottom: 20px;
  }
  .cmp-picker-row { display: flex; gap: 10px; align-items: center; }
  .cmp-picker-input {
    flex: 1 1 auto; min-width: 0;
    background: transparent; border: 0; border-bottom: 1px solid var(--line-2);
    color: var(--text); font-family: var(--mono); font-size: 13px;
    padding: 8px 2px; outline: none; transition: border-color 0.15s;
  }
  .cmp-picker-input::placeholder { color: var(--text-faint); }
  .cmp-picker-input:focus { border-bottom-color: var(--accent); }
  .cmp-picker-add {
    flex: 0 0 auto;
    background: transparent; border: 1px solid var(--line-2);
    color: var(--text-dim); font: 500 11px var(--mono); letter-spacing: 0.08em; text-transform: uppercase;
    padding: 8px 14px; cursor: pointer;
    transition: color 0.15s, border-color 0.15s, opacity 0.15s;
  }
  .cmp-picker-add:hover:not(:disabled) { color: var(--text); border-color: var(--accent-dim); }
  .cmp-picker-add:disabled { opacity: 0.35; cursor: default; }
  .cmp-picker-err { color: var(--bad); font: 500 11px var(--mono); letter-spacing: 0.02em; margin-top: 8px; }
  .cmp-picker-watchlist { margin-top: 14px; display: flex; flex-direction: column; gap: 8px; }
  .cmp-picker-chips { display: flex; flex-wrap: wrap; gap: 8px; }
  .cmp-chip {
    display: inline-flex; align-items: center; gap: 6px;
    background: transparent; border: 1px solid var(--line-2);
    color: var(--text-dim); font: 500 12px var(--sans);
    padding: 5px 10px 5px 6px; cursor: pointer;
    transition: color 0.15s, border-color 0.15s, opacity 0.15s;
  }
  .cmp-chip:hover:not(:disabled) { color: var(--text); border-color: var(--accent-dim); }
  .cmp-chip.added { opacity: 0.4; cursor: default; }
  .cmp-chip:disabled { cursor: default; }
  .cmp-chip-plus { color: var(--accent); font-weight: 600; }
  .cmp-hint { padding: 0 2px 16px; }

  .cmp-grid { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 16px; }
  .cmp-card {
    flex: 1 1 230px; min-width: 230px; max-width: 300px;
    background: rgba(168, 168, 224, 0.02);
    border: 1px solid var(--line);
    padding: 18px;
    display: flex; flex-direction: column; gap: 12px;
  }
  .cmp-card-head { display: flex; align-items: center; gap: 10px; }
  .cmp-card-remove {
    flex: 0 0 auto; margin-left: auto;
    background: transparent; border: 0;
    color: var(--text-faint); font-size: 13px; line-height: 1;
    padding: 4px; cursor: pointer; transition: color 0.15s;
  }
  .cmp-card-remove:hover { color: var(--bad); }
  .cmp-card-missing-body { display: flex; flex-direction: column; gap: 10px; padding-top: 2px; }

  .cmp-card-score {
    font: 500 30px var(--sans); font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em; line-height: 1;
    padding: 4px 6px; margin: 0 -6px; width: fit-content;
    transition: background 0.15s;
  }
  .cmp-card-score.worst { background: var(--bad-dim); }
  .cmp-card-score-of { font-size: 13px; color: var(--text-faint); margin-left: 2px; }

  .cmp-card-verdict-row { display: flex; align-items: center; gap: 8px; }
  .cmp-card-label { font: 500 13px var(--sans); letter-spacing: -0.005em; }
  .cmp-card-tier {
    font: 600 9px var(--mono); letter-spacing: 0.08em;
    color: var(--text-dim); border: 1px solid var(--line-2);
    padding: 2px 5px;
  }
  .cmp-card-band { font-size: 11.5px; line-height: 1.4; }

  .cmp-card-stats { display: flex; gap: 20px; padding: 10px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
  .cmp-card-stat { display: flex; flex-direction: column; gap: 3px; }

  .cmp-card-signals { display: flex; flex-direction: column; gap: 8px; }
  .cmp-sig-row {
    display: grid; grid-template-columns: 8px 1fr auto;
    align-items: center; gap: 8px;
    padding: 3px 4px; margin: 0 -4px;
    transition: background 0.15s;
  }
  .cmp-sig-row.worst { background: var(--bad-dim); }
  .cmp-sig-label { font: 500 10px var(--mono); letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-dim); }
  .cmp-sig-value { font: 500 12px var(--sans); font-variant-numeric: tabular-nums; color: var(--text); text-align: right; white-space: nowrap; }
  .vt-dot.nodata { background: var(--text-faint); opacity: 0.45; }

  .cmp-card-fresh { padding-top: 2px; }

  @media (max-width: 640px) {
    .compare-view { padding-top: 16px; }
    .cmp-picker { padding: 14px; }
    .cmp-picker-row { flex-wrap: wrap; }
    .cmp-grid { flex-direction: column; }
    .cmp-card { min-width: 0; max-width: none; }
  }
