  /* Trade Calculator — phone-first.
     The device most likely to be in your hand when a stop needs sizing is an
     iPhone, so the layout below is built for a 390px column first and only
     spreads out when there is room. Everything that isn't a number you decide
     from is either folded away or gone. */
  :root {
    --bg: #0f1115;
    --panel: #171a21;
    --panel2: #1e222b;
    --border: #2a2f3a;
    --text: #e6e9ef;
    --muted: #8a92a3;
    --accent: #4c8dff;
    --green: #3ecf8e;
    --red: #ff5c6c;
    --amber: #ffb020;
    --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    --tap: 44px;              /* minimum comfortable touch target */
    --gap: 12px;
  }
  @media (prefers-color-scheme: light) {
    :root {
      --bg: #f4f6fa; --panel: #ffffff; --panel2: #eef1f6; --border: #d7dce4;
      --text: #1a1d24; --muted: #5b6472; --accent: #2f6fed;
      --green: #12a06a; --red: #d63a4a; --amber: #b57a00;
    }
  }
  * { box-sizing: border-box; }
  html { -webkit-text-size-adjust: 100%; }
  body {
    margin: 0; background: var(--bg); color: var(--text);
    font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    padding: calc(10px + env(safe-area-inset-top)) calc(12px + env(safe-area-inset-right))
             calc(16px + env(safe-area-inset-bottom)) calc(12px + env(safe-area-inset-left));
  }
  /* No 300ms tap delay, no grey flash on every button, no accidental text
     selection when a card is double-tapped. */
  button, summary, .seg, tbody tr { -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
  button, summary, label, th { -webkit-user-select: none; user-select: none; }
  .wrap { max-width: 860px; margin: 0 auto; }
  .hidden { display: none !important; }

  /* ---- header ---- */
  .topbar { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
  h1 { font-size: 17px; margin: 0; margin-right: auto; letter-spacing: -.01em; }
  .envhint:not(:empty) { display: block; margin: -6px 0 12px; }
  footer { color: var(--muted); font-size: 11px; margin-top: 14px; text-align: center; }

  /* ---- panels ---- */
  .panel { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 14px; margin-bottom: 12px; }
  .sub { color: var(--muted); font-size: 12px; margin-bottom: 12px; }

  /* A folded panel shows its headline number in the summary, so the common
     question ("what's my balance", "how am I doing in R") is answered without
     opening anything. */
  details.fold { padding: 0; }
  details.fold > summary,
  details.more > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 10px; }
  details.fold > summary::-webkit-details-marker,
  details.more > summary::-webkit-details-marker { display: none; }
  details.fold > summary { min-height: var(--tap); padding: 0 14px; font-size: 14px; }
  details.fold > summary::after,
  details.more > summary::after {
    content: ""; width: 7px; height: 7px; margin-left: auto; flex: none;
    border-right: 2px solid var(--muted); border-bottom: 2px solid var(--muted);
    transform: rotate(45deg) translate(-2px, -2px); transition: transform .15s;
  }
  details.fold[open] > summary::after,
  details.more[open] > summary::after { transform: rotate(-135deg); }
  details.fold[open] > summary { border-bottom: 1px solid var(--border); }
  /* The headline value sits between the title and the chevron: with the chevron
     also margin-left:auto, the free space splits between them and an empty value
     collapses cleanly to nothing. */
  .fold-v { color: var(--muted); font: 13px var(--mono); margin-left: auto; }
  .fold-body { padding: 14px; }
  details.more { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 10px; }
  details.more > summary { min-height: 32px; color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
  details.more > summary::after { margin-left: 8px; width: 6px; height: 6px; }
  details.more[open] > summary { margin-bottom: 10px; }

  /* ---- form ---- */
  /* One grid: exactly two columns on a phone — including a 320px SE, where an
     auto-fit track collapses to one and doubles the height of the form — and as
     many as fit above that. Anything needing the full line says .row-wide. */
  .form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); align-items: start; }
  @media (min-width: 641px) {
    .form { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
    /* The form is phone-shaped by design; on a wide screen it is capped rather
       than stretched, so a two-state Long/Short switch doesn't end up 800px wide. */
    .inputs .form, .inputs .seg.tabs { max-width: 620px; }
  }
  .form + .form, .mode-body .form { margin-top: var(--gap); }
  .row-wide { grid-column: 1 / -1; }
  .field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
  .field label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
  .hint { font-size: 11px; color: var(--muted); text-transform: none; letter-spacing: 0; font-weight: 400; }
  .ladder { grid-column: 1 / -1; margin-top: -6px; }
  /* value + its unit switch on one line */
  .inline { display: flex; gap: 8px; align-items: center; min-width: 0; }
  .inline > input { flex: 1 1 90px; min-width: 0; }

  input[type="text"], input[type="number"], input[type="password"], select {
    background: var(--panel2); border: 1px solid var(--border); color: var(--text);
    border-radius: 9px; padding: 0 12px; font: 16px var(--mono); width: 100%;
    height: var(--tap); -webkit-appearance: none; appearance: none;
  }
  select { padding-right: 30px; cursor: pointer;
    background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);
    background-position: right 15px center, right 10px center; background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; }
  input:focus, select:focus { outline: none; border-color: var(--accent); }
  input::placeholder { color: var(--muted); opacity: .7; }

  /* ---- segmented controls ---- */
  .seg { display: flex; width: 100%; border: 1px solid var(--border); border-radius: 9px; overflow: hidden; }
  .seg button {
    flex: 1; background: var(--panel2); color: var(--muted); border: none;
    min-height: var(--tap); padding: 0 10px; cursor: pointer; font: 13px/1 inherit; white-space: nowrap;
  }
  .seg button.on { background: var(--accent); color: #fff; }
  .seg.compact { width: auto; flex: none; }
  .seg.compact button { flex: none; padding: 0 12px; font-size: 12px; }
  /* A unit switch that belongs to the input above it: full width of that field,
     so the pair reads as one control rather than two. */
  .seg.units button { min-height: 38px; font-size: 12px; }
  .seg.side button.on.long { background: var(--green); color: #04150d; }
  .seg.side button.on.short { background: var(--red); color: #fff; }
  /* Mode tabs read as tabs, not as another blue control competing with Side. */
  .seg.tabs { width: auto; border: none; border-radius: 0; gap: 18px; margin-bottom: 14px; border-bottom: 1px solid var(--border); }
  .seg.tabs button {
    background: none; padding: 0 0 9px; min-height: 32px; font-size: 14px; color: var(--muted);
    border-bottom: 2px solid transparent; margin-bottom: -1px;
  }
  .seg.tabs button.on { background: none; color: var(--text); border-bottom-color: var(--accent); }
  .mode-body { display: none; }
  .mode-body.on { display: block; }

  /* ---- buttons ---- */
  button.act {
    background: var(--accent); color: #fff; border: none; border-radius: 9px;
    min-height: var(--tap); padding: 0 18px; cursor: pointer; font: 600 15px inherit; width: 100%;
  }
  button.act:disabled { opacity: .5; cursor: default; }
  button.act.danger { background: var(--red); }
  button.mini {
    background: var(--panel2); color: var(--text); border: 1px solid var(--border); border-radius: 8px;
    min-height: 36px; padding: 0 12px; cursor: pointer; font: 13px inherit;
  }
  button.mini.danger { color: var(--red); border-color: color-mix(in srgb, var(--red) 40%, transparent); }
  button.mini.trade { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
  /* Refresh is maintenance, not a decision — an icon beside the ticker rather
     than a full-width blue bar that outranks everything around it. */
  button.icon {
    flex: none; width: var(--tap); height: var(--tap); border-radius: 9px; cursor: pointer;
    background: var(--panel2); border: 1px solid var(--border); color: var(--muted); font-size: 17px;
  }
  button.icon:disabled { opacity: .45; }

  /* ---- result summary strip ---- */
  /* What the report is about, in two lines: the trade on the first, everything
     that is the same for every variant on the second. */
  .sum { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin-bottom: 12px; }
  .sum .pair { font: 16px var(--mono); }
  .sum .tag { font: 600 11px/1.7 inherit; letter-spacing: .06em; padding: 0 8px; border-radius: 20px; }
  .sum .tag.long { background: color-mix(in srgb, var(--green) 18%, transparent); color: var(--green); }
  .sum .tag.short { background: color-mix(in srgb, var(--red) 18%, transparent); color: var(--red); }
  .sum .meta { width: 100%; color: var(--muted); font: 11px/1.6 var(--mono); }
  .micro { color: var(--muted); font-size: 11px; margin-top: 8px; }

  /* ---- table of variants ---- */
  table { width: 100%; border-collapse: collapse; font: 13px var(--mono); }
  .tbl-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  th, td { text-align: right; padding: 8px; border-bottom: 1px solid var(--border); white-space: nowrap; }
  th { color: var(--muted); font-weight: 500; font-size: 11px; text-transform: uppercase; }
  th:first-child, td:first-child { text-align: left; }
  tr.bad td { color: var(--muted); }
  tr.bad td:first-child::before { content: "! "; color: var(--red); }
  tr.heavy td { background: color-mix(in srgb, var(--amber) 12%, transparent); }
  tr.pick td { background: color-mix(in srgb, var(--accent) 14%, transparent); }
  tbody tr { cursor: pointer; }
  tr.sel td { background: color-mix(in srgb, var(--green) 16%, transparent); }
  tr.sel td:first-child { box-shadow: inset 3px 0 0 var(--green); }
  .tbl-scroll th.act-col, .tbl-scroll td.act-col {
    position: sticky; right: 0; background: var(--panel);
    border-left: 1px solid var(--border); text-align: center; padding-left: 10px;
  }
  td.loss, .big.loss, td .loss, .val.loss { color: var(--red); }
  td.profit, .big.profit, td .profit, .val.profit { color: var(--green); }
  /* Neither a win nor a loss — a trade that ran unprotected, or a stop that
     moved. Worth catching the eye without claiming the money went the wrong way. */
  td.warn, .big.warn, td .warn, .val.warn { color: var(--amber); }

  /* ---- selected-variant card ---- */
  .rec { border-left: 3px solid var(--green); padding: 12px 14px; background: var(--panel2); border-radius: 0 10px 10px 0; margin-top: 14px; }
  .rec-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 2px; }
  .rec-name { font: 15px var(--mono); margin-right: auto; }
  .rec-why { color: var(--muted); font-size: 12px; margin: 0 0 10px; }
  .rec .big { font: 15px var(--mono); }
  .rec-tag { font: 11px inherit; color: var(--muted); background: transparent; border: 1px solid var(--border); border-radius: 999px; padding: 3px 10px; }
  .rec-tag.on { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
  button.rec-tag { cursor: pointer; min-height: 30px; }
  .kv { display: grid; grid-template-columns: auto 1fr; gap: 3px 14px; font: 13px var(--mono); align-items: baseline; }
  .kv .k { color: var(--muted); }
  .rec-actions { display: flex; gap: 10px; align-items: center; margin-top: 12px; flex-wrap: wrap; }

  /* ---- the same card, armed ---- */
  /* Arming does not open a second panel — it turns this card into the order
     ticket. So the rail stops meaning "the variant you are reading" and starts
     meaning "the exchange this fires at": red for production, amber for the
     testnet, the same code the page border and the environment switch use. */
  .rec.armed.test { border-left-color: var(--amber); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--amber) 35%, transparent); }
  .rec.armed.prod { border-left-color: var(--red); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--red) 45%, transparent); }
  /* Editable where it is already printed: leverage and the slippage cap are set
     in the rows that read them out, and the margin above re-figures as you type.
     16px because anything smaller makes iOS zoom the page on focus. */
  input.kv-in {
    width: 5.5ch; height: 34px; padding: 0 7px; text-align: right;
    font: 16px var(--mono); border-radius: 7px;
    background: var(--bg); border: 1px solid var(--accent);
    -moz-appearance: textfield;
  }
  /* A stepper inside a 5-character box leaves room for about one digit. */
  input.kv-in::-webkit-outer-spin-button,
  input.kv-in::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
  .arm { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
  /* One line for the things arithmetic can't carry: that this is now an order,
     and which account on which exchange it lands in. */
  .arm-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; font: 12px var(--mono); color: var(--muted); }
  .arm-bar b { color: var(--text); }
  .arm-go { display: flex; gap: 10px; align-items: center; }
  .arm-go .act { flex: 1; }

  /* ---- notes ---- */
  .note { margin-top: 10px; padding: 9px 12px; border-radius: 9px; font-size: 13px; }
  .note.warn { background: color-mix(in srgb, var(--amber) 15%, transparent); color: var(--text); border: 1px solid color-mix(in srgb, var(--amber) 40%, transparent); }
  .note.stop { background: color-mix(in srgb, var(--red) 15%, transparent); border: 1px solid color-mix(in srgb, var(--red) 45%, transparent); }
  .note.err { background: color-mix(in srgb, var(--red) 12%, transparent); border: 1px solid color-mix(in srgb, var(--red) 40%, transparent); }
  .note.ok { background: color-mix(in srgb, var(--green) 15%, transparent); border: 1px solid color-mix(in srgb, var(--green) 45%, transparent); }
  /* Standing conditions of the strategy — true on every trade, so they read as
     footnotes rather than as amber alarms that mean nothing after the tenth time. */
  .note.quiet { background: none; border: none; padding: 0; margin-top: 10px; color: var(--muted); font-size: 11px; line-height: 1.6; }

  /* ---- chart ---- */
  .chart-wrap { margin: 2px 0 10px; }
  .chart-wrap svg { width: 100%; height: auto; display: block; }
  .chart-tfs { display: flex; gap: 6px; margin-bottom: 8px; }
  .chart-tfs button {
    background: transparent; color: var(--muted); border: 1px solid var(--border);
    border-radius: 7px; min-height: 32px; padding: 0 11px; cursor: pointer; font: 11px var(--mono);
  }
  .chart-tfs button.on { background: var(--accent); border-color: var(--accent); color: #fff; }
  .chart-tfs .live-toggle { margin-left: auto; }
  .chart-tfs .live-toggle.on { background: transparent; border-color: var(--green); color: var(--green); }
  .chart-live { display: flex; align-items: baseline; gap: 8px; margin: 0 0 6px; font: 12px var(--mono); }
  .chart-live .lp-price { font-size: 24px; color: var(--text); transition: color .25s; }
  .chart-live .lp-price.up, .chart-live .lp-chg.up { color: var(--green); }
  .chart-live .lp-price.down, .chart-live .lp-chg.down { color: var(--red); }
  .chart-live .lp-lbl, .chart-live .lp-age { color: var(--muted); font-size: 11px; }
  .chart-live .lp-age.stale { color: var(--amber); }
  .chart-live .lp-status { margin-left: auto; color: var(--muted); font-size: 11px; }
  /* A healthy feed is a green dot, not a chip spelling out "live" next to a
     price that is visibly ticking. Only a degraded feed gets words. */
  .chart-live .lp-status.on { color: var(--green); }
  .chart-live .lp-status.err { color: var(--red); border: 1px solid var(--red); border-radius: 999px; padding: 1px 8px; }
  .chart-live .lp-status.warn { color: var(--amber); border: 1px solid var(--amber); border-radius: 999px; padding: 1px 8px; }
  /* Legend: the three lines you are reading (entry, selected stop, target) are
     always out; the other stops fold away, because eight dashed labels is more
     chart legend than chart. */
  .chart-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; font: 12px var(--mono); }
  .chart-legend .lg { display: inline-flex; align-items: center; gap: 6px; color: var(--text); }
  .chart-legend .lg.off { color: var(--muted); }
  .chart-legend .sw { width: 18px; height: 0; border-top-width: 2px; border-top-style: solid; display: inline-block; }
  .chart-legend .lg .px { color: var(--muted); }
  .legend-more { margin-top: 6px; }
  .legend-more > summary {
    list-style: none; cursor: pointer; color: var(--muted); font: 11px var(--mono);
    min-height: 32px; display: flex; align-items: center;
  }
  .legend-more > summary::-webkit-details-marker { display: none; }
  .legend-more[open] > summary { margin-bottom: 4px; }
  .legend-more .chart-legend { gap: 3px 14px; }

  /* ---- account / journal ---- */
  .acct-sub-h { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; margin: 16px 0 8px; }
  .fold-body > .acct-sub-h:first-child { margin-top: 0; }
  .stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 8px; }
  .stat { background: var(--panel2); border: 1px solid var(--border); border-radius: 9px; padding: 9px 11px; }
  .stat .lbl { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
  .stat .val { font: 15px var(--mono); margin-top: 3px; }
  .acct-actions { display: flex; gap: 8px; align-items: center; margin-top: 10px; flex-wrap: wrap; }
  .acct-check { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; white-space: nowrap; min-height: 38px; }
  .acct-check input { width: 20px; height: 20px; }
  .acct-h { font-size: 15px; margin: 0 0 4px; }
  /* The Balance heading carries how fresh the numbers under it are. Same
     convention as the chart's price readout: a working refresh is a green dot,
     and only a broken or stale one is worth words. */
  .acct-sub-h.row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
  .acct-live { font: 11px var(--mono); text-transform: none; letter-spacing: 0; color: var(--muted); }
  .acct-live.on { color: var(--green); }
  .acct-live.warn { color: var(--amber); }
  .acct-live.err { color: var(--red); }
  /* Folded shut, the summary line is the whole panel — so if the balance on it
     has stopped being re-read, that has to be visible without opening anything. */
  .fold-v .stale { color: var(--amber); }

  /* ---- receipt ---- */
  /* Not a ticket — the ticket is the card up in the report. This is what the
     exchange came back with, and it stays until dismissed. */
  #tradeResult:empty { display: none; }
  .receipt { border: 1px solid color-mix(in srgb, var(--green) 45%, transparent); }
  .receipt.aborted { border-color: color-mix(in srgb, var(--red) 55%, transparent); }
  .receipt-h { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
  .receipt-h h3 { margin: 0; font-size: 15px; margin-right: auto; }
  .receipt-grid { display: grid; grid-template-columns: auto 1fr; gap: 4px 14px; font: 13px var(--mono); align-items: baseline; }
  .receipt-grid .k { color: var(--muted); }
  .receipt-grid .big { font: 15px var(--mono); }

  /* ---- market environment ---- */
  /* Production is the dangerous one, so it — not the testnet — carries the loud
     styling: a red rail down the page, and a red rail plus a red pill on the card
     the moment it is armed. You should be able to tell which exchange you are on
     from the corner of your eye. */
  #envSeg button { font-size: 12px; min-height: 34px; padding: 0 12px; }
  #envSeg button.on[data-env="testnet"] { background: var(--amber); color: #241a00; }
  #envSeg button.on[data-env="production"] { background: var(--red); color: #fff; }
  body.env-production { border-top: 3px solid var(--red); }
  body.env-testnet { border-top: 3px solid var(--amber); }
  .env-tag { font: 600 10px/1.6 inherit; letter-spacing: .06em; padding: 1px 7px; border-radius: 20px; vertical-align: 2px; }
  .env-tag.testnet { background: color-mix(in srgb, var(--amber) 22%, transparent); color: var(--amber); border: 1px solid color-mix(in srgb, var(--amber) 50%, transparent); }
  .env-tag.prod { background: color-mix(in srgb, var(--red) 20%, transparent); color: var(--red); border: 1px solid color-mix(in srgb, var(--red) 55%, transparent); }

  /* ---- accounts & API keys ---- */
  .userbar {
    display: flex; align-items: center; gap: 8px 10px; flex-wrap: wrap;
    background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
    padding: 10px 12px; margin-bottom: 12px; font-size: 13px;
  }
  .userbar .hint { font-size: 11px; }
  .userbar-actions { margin-left: auto; display: flex; gap: 8px; }
  .keychip { font: 11px var(--mono); color: var(--muted); border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px; white-space: nowrap; }
  .keychip.on { color: var(--green); border-color: color-mix(in srgb, var(--green) 45%, transparent); }
  .keychip.admin { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
  .stack { display: flex; flex-direction: column; gap: 10px; }
  .keycards { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; margin-top: 10px; }
  .keycard { background: var(--panel2); border: 1px solid var(--border); border-radius: 10px; padding: 12px; }
  .keycard.prod { border-color: color-mix(in srgb, var(--red) 40%, transparent); }
  .keycard.test { border-color: color-mix(in srgb, var(--amber) 35%, transparent); }
  .keycard-h { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
  .keycard-h code { font: 11px var(--mono); color: var(--text); }
  .keycard-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
  .keycard-actions .act { width: auto; }

  /* ---- Touch ID / Face ID ---- */
  /* The unlock button is the primary way back in on a device that has been
     enrolled, so it sits above the password form and is styled quieter than a
     blue "act" only in that it carries the sensor glyph — it is still the
     action this panel expects. */
  button.act.passkey { background: var(--panel2); color: var(--text); border: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); }
  button.act.passkey::before { content: "☝ "; }
  /* "or your password": a rule with the alternative sitting in the gap. */
  .pk-or { display: flex; align-items: center; gap: 10px; color: var(--muted); font-size: 12px; margin: 12px 0; }
  .pk-or::before, .pk-or::after { content: ""; flex: 1; height: 1px; background: var(--border); }
  .pk-list { display: flex; flex-direction: column; gap: 8px; margin: 10px 0; }
  .pk-row {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    background: var(--panel2); border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px;
  }
  /* A device that can no longer open the vault is a repair job, not a warning
     about money — amber, and it says why in the line beneath its name. */
  .pk-row.stale { border-color: color-mix(in srgb, var(--amber) 45%, transparent); }
  .pk-what { display: flex; flex-direction: column; gap: 2px; margin-right: auto; min-width: 0; }
  .pk-what .hint { font-size: 11px; }
  .pk-actions { display: flex; gap: 8px; }

  /* ---- phones ---- */
  @media (max-width: 640px) {
    .userbar-actions { margin-left: 0; width: 100%; }
    .userbar-actions button { flex: 1; }
    .keycards { grid-template-columns: 1fr; }
    /* On a phone the enrolled-device row stacks: the name and its state on one
       line, the buttons full width underneath, same as every other control. */
    .pk-what { width: 100%; }
    .pk-actions { width: 100%; }
    .pk-actions button { flex: 1; }
    table { font-size: 12px; }
    th, td { padding: 8px 6px; }

    /* The variant table is the one thing on this page you actually decide from.
       Here each row becomes a card: name and its trade button on the top line,
       the numbers underneath in a labelled three-up grid, nothing beyond the
       right edge. It stays a <table> in the markup, so row selection, the
       recommended pick and the noise flags all keep working untouched. */
    .tbl-scroll.cards { overflow-x: visible; }
    .tbl-scroll.cards table, .tbl-scroll.cards tbody { display: block; }
    .tbl-scroll.cards thead { display: none; }
    .tbl-scroll.cards tbody tr {
      display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
      gap: 9px 10px; align-items: start;
      background: var(--panel2); border: 1px solid var(--border);
      border-radius: 10px; padding: 11px 12px; margin-bottom: 8px;
    }
    .tbl-scroll.cards td { display: block; border: none; padding: 0; text-align: left; white-space: normal; overflow-wrap: anywhere; }
    /* Each number carries its own column heading, since the header row is gone. */
    .tbl-scroll.cards td[data-k]::before {
      content: attr(data-k); display: block; margin-bottom: 2px;
      font: 10px/1.3 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      color: var(--muted); text-transform: uppercase; letter-spacing: .04em;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    .tbl-scroll.cards td:first-child { grid-column: 1 / span 2; grid-row: 1; font-size: 13px; }
    .tbl-scroll.cards td.act-col {
      grid-column: 3; grid-row: 1; position: static; text-align: right;
      background: none; border-left: none; padding-left: 0;
    }
    /* With no trade button the name only spans two of the three columns, and the
       first number back-fills the empty corner beside it — the stop ends up in
       the top right in header-sized type. Letting the name take the whole first
       row keeps the six figures a tidy 3×2 block either way. */
    .tbl-scroll.cards tbody tr:not(:has(.act-col)) td:first-child { grid-column: 1 / -1; }
    .tbl-scroll.cards td.act-col button { min-height: 36px; padding: 0 14px; }
    .tbl-scroll.cards tbody tr.pick td:first-child::before { content: "★ "; color: var(--accent); }
    .tbl-scroll.cards tbody tr.pick td, .tbl-scroll.cards tbody tr.sel td,
    .tbl-scroll.cards tbody tr.heavy td { background: none; }
    .tbl-scroll.cards tbody tr.pick { background: color-mix(in srgb, var(--accent) 12%, var(--panel2)); }
    .tbl-scroll.cards tbody tr.heavy { border-color: color-mix(in srgb, var(--amber) 45%, transparent); }
    .tbl-scroll.cards tbody tr.sel {
      background: color-mix(in srgb, var(--green) 14%, var(--panel2));
      border-color: color-mix(in srgb, var(--green) 50%, transparent);
      box-shadow: inset 3px 0 0 var(--green);
    }
    .tbl-scroll.cards tbody tr.sel td:first-child { box-shadow: none; }
    @media (max-width: 360px) {
      .tbl-scroll.cards td[data-k]::before { font-size: 9.5px; letter-spacing: .01em; }
      /* Half a 320px column is not much to fit three unit buttons into. */
      .seg.units button { font-size: 11px; padding: 0 4px; }
    }

    /* Pin the chart to the top of the screen while the card list beneath it
       scrolls, so a tap updates something you are already looking at instead of
       something you have to scroll back up to see. It stays pinned only within
       its own results panel, and the opaque background is what lets it paint
       over cards passing underneath. */
    #chartBox {
      position: sticky; top: 0; z-index: 5;
      background: var(--panel);
      margin: 0 -14px; padding: 0 14px 8px;
      border-bottom: 1px solid var(--border);
      box-shadow: 0 6px 10px -8px rgba(0, 0, 0, .5);
    }
    .legend-more .chart-legend { max-height: 120px; overflow-y: auto; }
  }

  @media (hover: hover) {
    button.mini:hover { border-color: var(--muted); }
    button.icon:hover { color: var(--text); border-color: var(--muted); }
    button.mini.trade:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
    button.mini.danger:hover { border-color: var(--red); }
    button.rec-tag:hover { color: var(--text); border-color: var(--muted); }
    .chart-tfs button:hover { color: var(--text); border-color: var(--muted); }
    .chart-tfs .live-toggle.on:hover { color: var(--green); border-color: var(--green); }
    tbody tr:hover td { background: color-mix(in srgb, var(--text) 6%, transparent); }
    .tbl-scroll.cards tbody tr:hover td { background: none; }
    details.fold > summary:hover, details.more > summary:hover { color: var(--accent); }
  }
