  /* base reset + body come from ds.css; the profile keeps extra bottom room */
  body { padding-bottom: 48px; }
            
    @media (max-width: 640px) {
          }
  .back-link {
    color: var(--text-mid);
    text-decoration: none;
    font-size:var(--t-body);
    letter-spacing: 0.04em;
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 4px 10px;
    transition: color 0.1s, border-color 0.1s;
  }
  .back-link:hover { color: var(--interactive); border-color: var(--interactive); }
  .main {
    max-width: 960px;
    margin: 0 auto;
    padding: 24px 16px 0;
    /* clip (not hidden) contains horizontal overflow without forcing overflow-y
       to auto — so the cards' vertical drop-shadows aren't clipped. */
    overflow-x: clip;
  }
  /*  .panel / .platform-badge / .spinner are shared — see ds.css  */
  /*  Profile tab group  */
  /* (profile tab system removed — header + ladder history + career archive are all
     always-visible now; the career archive uses .season-switch sub-tabs.) */
  .player-heading {
    font-size:var(--t-lead);
    color: var(--text);
    letter-spacing: 0.04em;
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 18px;
  }
  .stat-blocks {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 12px;
  }
  /* Combat section: single panel with dense 3-column grid */
  /* Flush titled section — no surrounding box, so COMBAT matches the MATCHUPS
     section visually (.mu-title). The stat tiles inside keep their own borders. */
  .combat-panel {
    margin-top: 12px;
  }
  .combat-panel-title {
    color: var(--text-mid);
    font-size:var(--t-label);
    letter-spacing: 0.12em;
    text-transform: uppercase;
    border-bottom: 1px solid var(--border);
    padding-bottom: 8px;
    margin-bottom: 10px;
  }
  /* COMBAT in three tiers (docs/ui-character/05). It used to be a 3x4 grid of
     identical bordered tiles - the canonical generated-dashboard shape, where
     equal weight on twelve numbers means the reader is told none of them. And
     its colour was a CSS default rather than a meaning: K/D and KILLS were
     green while green is defined site-wide as positive-SEMANTIC, so a raw
     DEATHS count sat one tile away in the same family. Now:
       .cb-figure  ONE number, at --t-figure, that characterises the player
       .cb-four    four supporting numbers at --t-lead
       .cb-rest    the remainder as a dense borderless list at --t-label
     Green appears only via .pos, which the renderer sets on a genuinely
     positive-semantic value (K/D above 1, a live streak). */
  .cb-lead { display: flex; align-items: flex-start; gap: 22px; flex-wrap: wrap; margin-bottom: 12px; }
  .cb-hero { flex-shrink: 0; min-width: 84px; }
  .cb-k { color: var(--text-low); font-size: var(--t-micro); letter-spacing: 0.1em;
          text-transform: uppercase; margin-bottom: 3px; white-space: nowrap; }
  .cb-figure { color: var(--text-hi); font-size: var(--t-figure); font-weight: 700;
               font-variant-numeric: tabular-nums; line-height: 1.1; }
  .cb-four { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
             gap: 12px 20px; flex: 1; min-width: 240px; }
  .cb-v { color: var(--text); font-size: var(--t-lead); font-weight: 600;
          font-variant-numeric: tabular-nums; line-height: 1.15; }
  .cb-figure.pos, .cb-v.pos, .cb-rest dd.pos { color: var(--green); }
  .cb-rest { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
             gap: 0 30px; border-top: 1px solid var(--border); padding-top: 4px; margin: 0; }
  .cb-rest > div { display: flex; align-items: baseline; justify-content: space-between;
                   gap: 14px; padding: 5px 0; border-bottom: 1px solid var(--bg-2);
                   font-size: var(--t-label); }
  .cb-rest dt { color: var(--text-mid); margin: 0; }
  .cb-rest dd { color: var(--text); margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }
  .cb-q { color: var(--text-low); }
  .cb-note { color: var(--text-mid); font-size: var(--t-label); line-height: 1.5;
             margin: 2px 0 10px; }
  .cb-rest.thin dd { opacity: .6; }
  @media (max-width: 640px) {
    .cb-four { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 16px; }
    .cb-rest { grid-template-columns: 1fr; gap: 0; }
  }
  /* Overview panel: dense grid replacing the old 3-card elo-blocks row */
  .overview-panel {
    background: var(--bg-1);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 12px 14px;
    margin-bottom: 12px;
  }
  .overview-panel-title {
    color: var(--interactive);
    font-size:var(--t-label);
    font-weight: bold;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 10px;
  }
  .overview-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
  }
  @media (max-width: 640px) {
    .overview-grid { grid-template-columns: repeat(2, 1fr); }
  }
  .stat-block {
    background: var(--bg-0);
    border: 1px solid var(--bg-2);
    border-radius: 5px;
    padding: 12px 14px;
  }
  .stat-block-title {
    color: var(--text-low);
    font-size:var(--t-micro);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    margin-bottom: 10px;
    border-bottom: 1px solid var(--bg-2);
    padding-bottom: 5px;
  }
  .stat-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 6px;
    gap: 8px;
  }
  .stat-row:last-child { margin-bottom: 0; }
  .stat-label {
    color: var(--text-mid);
    font-size:var(--t-label);
    white-space: nowrap;
  }
  .stat-val {
    color: var(--green);
    font-size:var(--t-lead);
    font-weight: bold;
    text-align: right;
  }
  .stat-val.dim { color: var(--text); font-weight: normal; }
  .player-avatar-block {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 12px;
    margin-top: 14px;
  }
  .steam-badge {
    display: inline-block;
    font-size:var(--t-micro);
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--text-mid);
    background: var(--bg-1);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 3px 8px;
    text-decoration: none;
    transition: color 0.15s, border-color 0.15s;
  }
  .steam-badge:hover { color: var(--text); border-color: var(--text-low); }
  .error { color: var(--red); padding: 10px 12px; font-size:var(--t-body); background: #1a0a0a; border: 1px solid var(--red); border-radius: 4px; margin-top: 8px; }
  #player-content { display: none; }

  /*  Player search  */
                
  /*  Event history table  */
  /* auto layout: data columns size to their content (no clipped values); only
     the first column (name/label) truncates, capped below. */
  table { width: 100%; table-layout: auto; border-collapse: collapse; }
  td, th { white-space: nowrap; }
  td:first-child { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .eh-table { width: 100%; border-collapse: collapse; }
  .eh-table thead th {
    color: var(--text-mid);
    text-align: left;
    padding: 5px 10px;
    font-size:var(--t-label);
    letter-spacing: 0.05em;
    border-bottom: 1px solid var(--bg-2);
  }
  .eh-table thead th.num, .eh-table tbody td.num { text-align: right; }
  /* SET numbers read right-aligned; DATE hugs the SET column from the left. */
  .eh-table thead th.eh-set,  .eh-table tbody td.eh-set  { text-align: right; white-space: nowrap; }
  .eh-table thead th.eh-date, .eh-table tbody td.eh-date { text-align: left; }
  .eh-table tbody td {
    padding: 7px 10px;
    border-bottom: 1px solid var(--bg-2);
    font-size:var(--t-body);
  }
  .eh-table tbody tr:last-child td { border-bottom: none; }
  .eh-table tbody tr:hover { background: var(--bg-hover); }
  .delta-pos { color: var(--green); }
  .delta-neg { color: var(--red); }
  .delta-zero { color: var(--text-mid); }
  .elo-neutral { color: var(--text); }
  .peak-star { color: var(--gold); font-size:var(--t-micro); }
  /*  Penalty overlay (docs/penalties, Phase 6) — muted, informational tone  */
  .trail-flag { color: var(--gold); font-size:var(--t-micro); }
  tr.trail-penalty { background: #0f1119; }
  tr.trail-penalty:hover { background: #0f1119; }
  tr.trail-penalty td { color: var(--text-mid); font-style: italic; border-top: 1px solid var(--bg-1); }
  tr.trail-penalty td.tp-reason { text-align: left; font-style: normal; letter-spacing: 0.02em; }
  .sd-penalties { margin-top: 10px; padding: 8px 10px; background: #0f1119; border: 1px solid var(--bg-2); border-radius: 5px; }
  .sdp-head { color: var(--gold); font-size:var(--t-label); letter-spacing: 0.04em; margin-bottom: 6px; }
  .sdp-row { color: var(--text-mid); font-size:var(--t-label); padding: 2px 0; }
  .sdp-delta { color: var(--text); font-weight: 600; }
  .sdp-reason { color: var(--text-mid); }

  /*  S2 ladder history: three equal chart cards (ELO + game placement + set placement)  */
  .lh-top { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-bottom: 14px; }
  /*  All-view: two equal placement cards (game + set), no per-season ELO chart  */
  .lh-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
  @media (max-width: 880px) { .lh-top, .lh-pair { grid-template-columns: 1fr; } }
  /* Per-season summary strip (set/game W-L, top3, avg place) — replaces the old
     S2/S1 stat tabs; one compact row at the top of each ladder-history season. */
  .lh-summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 14px; }
  @media (max-width: 600px) { .lh-summary { grid-template-columns: repeat(2, 1fr); } }
  /* Very narrow phones (≤380, e.g. 320px): stack the summary so its cells can't
     overflow the panel (docs/frontend-polish/04). 390px keeps the 2-col grid. */
  @media (max-width: 380px) { .lh-summary { grid-template-columns: 1fr; } }
  .lh-sum-cell { background: var(--bg-0); border: 1px solid var(--bg-2); border-radius: 6px; padding: 8px 11px; }
  .lh-sum-label { font-size:var(--t-micro); color: var(--text-mid); text-transform: uppercase; letter-spacing: 0.05em; }
  .lh-sum-val { font-size:var(--t-lead); font-weight: 700; color: var(--text-hi); margin-top: 3px; }
  .lh-sum-sub { font-size:var(--t-label); color: var(--text-mid); font-weight: 600; margin-left: 3px; }
  /* op.gg-style season switcher */
  .lad-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
  /*  ladder/archive switchers use the shared .seg segmented control — see ds.css  */
  .chart-card { background: var(--bg-0); border: 1px solid var(--bg-2); border-radius: 6px; padding: 12px 14px; min-width: 0; display: flex; flex-direction: column; }
  .cc-title { color: var(--text-mid); font-size:var(--t-micro); letter-spacing: 0.06em; margin-bottom: 10px; }
  /* ELO trend: both seasons share one rule so the card is identical S2/S1; the
     SVG fills the whole chart area (no letterboxing), axis labels are HTML overlays. */
  #elo-chart, #s1-elo-chart, #eu-pts-chart { flex: 1; min-height: 168px; position: relative; }
  #elo-chart svg, #s1-elo-chart svg, #eu-pts-chart svg { position: absolute; inset: 0; width: 100%; height: 100%; }
  .eu-elo-note { background: var(--bg-1); border: 1px solid var(--bg-2); border-left: 3px solid var(--green); border-radius: 6px; padding: 8px 12px; margin-bottom: 14px; font-size:var(--t-label); line-height: 1.45; color: var(--text-mid); }
  .eu-elo-note b { color: var(--text); }
  .elo-lab { position: absolute; right: 7px; font-size:var(--t-label); font-weight: 600; color: var(--text-mid); font-variant-numeric: tabular-nums; pointer-events: none; line-height: 1; background: rgba(11,14,20,0.72); padding: 1px 4px; border-radius: 3px; }
  .elo-lab.elo-max { top: 5px; color: var(--gold); }
  .elo-lab.elo-min { bottom: 5px; }
  /* ELO-chart hover crosshair + dot + value tooltip */
  .eg-cross { position: absolute; top: 0; bottom: 0; width: 1px; background: rgba(255,255,255,0.2); pointer-events: none; transform: translateX(-0.5px); }
  .eg-dot { position: absolute; width: 7px; height: 7px; border-radius: 50%; background: var(--text-hi); border: 2px solid var(--bg-0); transform: translate(-50%,-50%); pointer-events: none; box-shadow: 0 0 0 1px rgba(255,255,255,0.25); }
  .eg-tip { position: absolute; background: var(--bg-0); border: 1px solid var(--border); border-radius: 4px; padding: 3px 7px; font-size:var(--t-label); color: var(--text-hi); pointer-events: none; white-space: nowrap; z-index: 5; font-variant-numeric: tabular-nums; line-height: 1.3; }
  .eg-tip .eg-tip-lbl { color: var(--text-mid); margin-right: 5px; }
  .lh-stats { display: flex; gap: 14px; flex-wrap: wrap; font-size:var(--t-label); color: var(--text-mid); align-items: baseline; margin-top: 10px; }
  .lh-stats b { color: var(--green); font-weight: bold; }
  .lh-stats .pk { color: var(--gold); }
  .lh-toggle {
    margin-top: 10px; background: var(--bg-0); border: 1px solid var(--border); border-radius: 4px;
    color: var(--text-mid); font-family: 'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace; font-size:var(--t-label); letter-spacing: 0.06em;
    padding: 6px 12px; cursor: pointer; width: 100%;
  }
  .lh-toggle:hover { color: var(--interactive); border-color: var(--interactive); }
  /* Ladder history + career archive now live inside .main (one centered column),
     so they inherit its width and the shared .panel padding — no per-panel
     centering needed. Every top-level block (summary card, ladder, archive) is
     the same width and shares left/right edges.

     Subtle lift off the near-black background — a restrained drop shadow, no
     glassy blur; because the page bg (#0b0913) isn't pure black, the soft black
     shadow reads as a gentle vignette around each card. Blur is kept within the
     column's side gutter so overflow-x:clip doesn't cut it. player.css only
     loads on the profile page, so this stays scoped to profiles. */
  .panel, .player-sticky-header {
    box-shadow: 0 3px 14px rgba(0, 0, 0, 0.38);
  }
  .ca-pane { margin-top: 4px; }
  /* placement distribution bar chart */
  #place-dist, #set-place-dist, #s1-place-dist, #s1-set-place-dist, #all-place-dist, #all-set-place-dist { flex: 1; min-width: 0; margin: 0; }
  /* reserve the placement cards' height so the loading skeleton and the real bars
     occupy the same space — no layout shift when renderDist() paints. */
  #place-dist, #set-place-dist { min-height: 140px; }
  .pd-title { color: var(--text-mid); font-size:var(--t-micro); letter-spacing: 0.06em; margin-bottom: 8px; }
  .pd-rows { display: flex; flex-direction: column; gap: 4px; }
  .pd-row { display: flex; align-items: center; gap: 8px; font-size:var(--t-label); }
  .pd-lab { color: var(--text-mid); width: 28px; text-align: right; flex-shrink: 0; }
  .pd-bar { flex: 1; height: 12px; background: var(--bg-0); border-radius: 3px; overflow: hidden; }
  .pd-fill { display: block; height: 100%; border-radius: 3px; min-width: 2px; transition: width 0.3s; }
  .pd-n { color: var(--text-mid); width: 70px; flex-shrink: 0; }
  /* clickable set rows → per-game detail */
  tr.set-row { cursor: pointer; }
  tr.set-row:hover { background: var(--bg-hover); }
  /*  .caret (chevron) is shared — see ds.css  */
  tr.detail-row > td { padding: 0; border-bottom: 1px solid var(--bg-2); background: var(--bg-0); }
  .set-detail { padding: 10px 12px 14px; }
  .sd-title { color: var(--text-mid); font-size:var(--t-label); letter-spacing: 0.05em; margin-bottom: 8px; }
  .sd-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  table.sd-table { border-collapse: collapse; table-layout: auto; min-width: 100%; }
  table.sd-table th { color: var(--text-low); font-size:var(--t-micro); text-align: left; padding: 4px 9px; font-weight: normal; white-space: nowrap; }
  table.sd-table th.num, table.sd-table td.num, table.sd-table th.g, table.sd-table td.g { text-align: center; }
  table.sd-table td { padding: 5px 9px; font-size:var(--t-label); border-top: 1px solid var(--bg-1); white-space: nowrap; }
  table.sd-table td.pl { text-align: left; max-width: 150px; overflow: hidden; text-overflow: ellipsis; }
  .sd-table a { color: var(--text); text-decoration: none; }
  .sd-table a:hover { color: var(--interactive); }
  table.sd-table td.sd-pts { color: var(--gold); font-weight: 600; }
  .eh-table tbody td.eh-pts { color: var(--gold); font-weight: 600; }
  .sd-gwin { color: var(--green); }
  .sd-you td { background: rgba(74,222,128,0.09); }
  .sd-you td.pl a { color: var(--green); font-weight: bold; }
  .sd-rk { color: var(--text-low); width: 26px; text-align: right; }
  /* tiebreak tags (same look as the event finals board) */
  .sd-table .tag { font-size:var(--t-micro); padding: 1px 5px; border-radius: 3px; margin-left: 5px; white-space: nowrap; }
  .sd-table .tag.tb { color: var(--gold); border: 1px solid var(--gold); }
  .sd-table .tag.tie { color: var(--text-mid); border: 1px solid var(--text-mid); }
  /*  Matchups section  */
  .mu-panel { background: var(--bg-1); border: 1px solid var(--border); border-radius: 6px; padding: 16px; margin-bottom: 16px; }
  .mu-title  { color: var(--text-mid); font-size:var(--t-label); letter-spacing: 0.12em; text-transform: uppercase; border-bottom: 1px solid var(--border); padding-bottom: 8px; margin-bottom: 10px; }
  .mu-sub    { color: var(--text-mid); font-size:var(--t-label); letter-spacing: 0.05em; text-transform: uppercase; margin: 10px 0 6px; }
  .mu-table  { width: 100%; border-collapse: collapse; }
  .mu-table th { color: var(--text-mid); font-size:var(--t-label); letter-spacing: 0.05em; text-align: left; padding: 4px 8px; border-bottom: 1px solid var(--bg-2); }
  .mu-table th.num { text-align: right; }
  .mu-table td { padding: 6px 8px; border-bottom: 1px solid var(--bg-2); font-size:var(--t-body); }
  .mu-table tr:last-child td { border-bottom: none; }
  .mu-table tr:hover td { background: var(--bg-hover); }
  .mu-table td.num { text-align: right; color: var(--text-mid); }
  .mu-table td.wl  { text-align: right; }
  .mu-table td.wp  { text-align: right; color: var(--green); font-weight: bold; }
  .mu-table td.wp.neg { color: var(--red); }
  .mu-table a { color: var(--text); text-decoration: none; }
  .mu-table a:hover { color: var(--interactive); }

  @media (max-width: 640px) {
    .main { padding: 16px 10px 0; }
    .panel { padding: 12px; }
    .stat-blocks { grid-template-columns: 1fr 1fr; gap: 8px; }
    .stat-block { padding: 10px; }
    .stat-block-title { font-size:var(--t-micro); }
    .stat-val { font-size:var(--t-body); }
    .player-heading { font-size:var(--t-lead); }
            .back-link { display: none; }
    .eh-table tbody td, .eh-table thead th { padding: 6px 7px; font-size:var(--t-label); }
  }
  @media (max-width: 380px) {
    .stat-blocks { grid-template-columns: 1fr; }
  }
  /* Player summary — a bordered card sharing the panels' width, border, radius
     and fill, so the top of the profile is framed against the background
     instead of floating on it as loose text. (Was a flush sticky bar.) */
  .player-sticky-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 16px;
    background: var(--bg-1);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 16px;
    margin-bottom: 16px;
  }
  .sticky-player-name { font-size:var(--t-lead); font-weight: 700; color: var(--text-hi); }
  /* Season-standing badge (S2 top 1/10/25) — medal palette matches setPlaceCell. */
  .season-trophy {
    margin-left: 8px; padding: 1px 8px; border-radius: 4px;
    font-size:var(--t-label); font-weight: 600; vertical-align: middle;
    border: 1px solid var(--text-mid); color: var(--text-mid); background: transparent;
    white-space: nowrap;
  }
  .season-trophy.tier-top1  { border-color: var(--gold); color: var(--gold); }
  .season-trophy.tier-top10 { border-color: #b9c0c8; color: #b9c0c8; }
  .season-trophy.tier-top25 { border-color: #cd7f32; color: #cd7f32; }
  .sticky-player-aka { font-size:var(--t-label); color: var(--text-mid); margin-top: 2px; }
  .sticky-stat-chips { display: flex; gap: 18px; flex-wrap: wrap; align-items: flex-start; }
  /* Each stat is a centered column (label over value) with a shared min-width, so
     the row reads as even columns regardless of label/value length — no more short
     values floating to the right under wide labels. tabular-nums keeps digits aligned. */
  .sticky-chip { display: flex; flex-direction: column; align-items: center; min-width: 46px; }
  /* Phones (docs/frontend-polish/04): the chips row is a flex item with no
     width, so it grew to its single-row content (~366px) and clipped past the
     viewport — flex-wrap had no room to act. Give it the full header width and
     tighten spacing so the six chips wrap cleanly instead of overflowing. */
  @media (max-width: 600px) {
    .sticky-stat-chips { width: 100%; gap: 12px 14px; justify-content: flex-start; }
    .sticky-chip { min-width: 40px; }
    /* Let the avatar+name block shrink so a long "aka …" line wraps instead of
       forcing the header wider than a 320px viewport. */
    .player-sticky-header > div { min-width: 0; }
    .sticky-player-aka { overflow-wrap: anywhere; }
  }
  .sticky-chip-label { font-size:var(--t-micro); color: var(--text-mid); text-transform: uppercase; letter-spacing: 0.05em; white-space: nowrap; }
  .sticky-chip-value { font-size:var(--t-lead); font-weight: 700; color: var(--green); font-variant-numeric: tabular-nums; margin-top: 3px; line-height: 1; }
  /* The rating is the one figure with its own size site-wide (--t-figure,
     ds.css) - the same size it is set at on the ladder. */
  .chip-rating .sticky-chip-value { font-size: var(--t-figure); }

  /*  Staff panel (the Edit button). One grid for every row so labels,
      values and actions line up across Accounts, Tournaments and Aliases. */
  .staff-panel { margin: 8px 0 4px; padding: 2px 14px 12px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-1); font-size: var(--t-label); }
  /* The script toggles rows and buttons with the hidden attribute; .btn and
     .sp-row set display, which would otherwise win over the UA's [hidden]. */
  .staff-panel [hidden] { display: none !important; }
  .sp-v .dim { color: var(--text-mid); }
  .sp-sec { padding: 10px 0 4px; }
  .sp-sec + .sp-sec { border-top: 1px solid var(--border); }
  .sp-label { font-size: var(--t-micro); color: var(--text-mid); text-transform: uppercase; letter-spacing: .1em; margin-bottom: 6px; }
  .sp-row { display: grid; grid-template-columns: 76px minmax(0, 1fr) auto; gap: 6px 12px; align-items: center; min-height: 32px; }
  .sp-k { color: var(--text-mid); }
  .sp-v { color: var(--text-hi); overflow-wrap: anywhere; }
  .sp-v.dim { color: var(--text-mid); }
  .sp-v a { color: var(--interactive); text-decoration: none; }
  .sp-v a:hover { text-decoration: underline; }
  .sp-a { justify-self: end; display: flex; gap: 8px; }
  .sp-btn { padding: 4px 12px; font-weight: 600; }
  .sp-form { display: flex; gap: 8px; align-items: center; }
  .sp-form input, .sp-form select { flex: 1; min-width: 0; padding: 6px 9px; background: var(--bg-0); border: 1px solid var(--border); border-radius: 4px; color: var(--text-hi); font-family: inherit; font-size: var(--t-label); }
  .sp-form select { flex: 0 0 auto; }
  .sp-form input:focus, .sp-form select:focus { border-color: var(--interactive); outline: none; }
  .sp-row .sp-form { grid-column: 2 / 4; }
  .sp-hint { color: var(--text-mid); margin: 0 0 8px; }
  .sp-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
  .sp-chip { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-0); }
  .sp-chip .tag { color: var(--text-low); font-size: var(--t-micro); }
  .sp-chip .tag.ocr { color: var(--amber); }
  .sp-chip button { background: none; border: 0; color: var(--text-low); cursor: pointer; font-size: var(--t-body); padding: 0; line-height: 1; }
  .sp-chip button:hover { color: var(--red); }
  .sp-result { margin-top: 6px; }
  .sp-result:empty { display: none; }
  .sp-result.ok { color: var(--green); }
  .sp-result.err { color: var(--red); }
  .sp-result.busy { color: var(--text-mid); }
  @media (max-width: 600px) {
    .sp-row { grid-template-columns: 64px minmax(0, 1fr); }
    .sp-a, .sp-row .sp-form { grid-column: 2; justify-self: start; }
  }
