/* ═══════════════════════════════════════════════════════════════════════════
   PPC dashboard v2 — styles.css (the "looks" drawer).
   RELOCATED 1:1 from dashboard.html's <style> block (the 2026-07 file split —
   see Sales Dashboard/SPLIT-HANDOFF.md for the pattern and RULEBOOK Rule 6's
   split rule). Loaded in the same cascade position the inline block had:
   BEFORE /Shared Data/shell.css, so shell.css keeps winning ties exactly as
   it did on the single-file page.
   ═══════════════════════════════════════════════════════════════════════════ */
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f6fa; color: #2d3436; padding-bottom: 10px; }

  /* ── Sidebar ── */
  .sidebar { position: fixed; top: 0; left: 0; width: 150px; height: 100vh; background: #1a1f2e; color: #fff; display: flex; flex-direction: column; z-index: 100; }
  .sidebar .logo { padding: 14px 10px; border-bottom: 1px solid #2d3450; display: flex; align-items: center; gap: 8px; }
  .sidebar .logo svg { width: 28px; height: 28px; flex-shrink: 0; }
  .sidebar .logo span { font-size: 16px; font-weight: 800; font-style: italic; letter-spacing: 1.5px; color: #e8eaed; }
  .sidebar nav { flex: 1; padding: 12px 0; }
  .sidebar nav a { display: flex; align-items: center; gap: 10px; padding: 11px 18px; color: #8892a4; text-decoration: none; font-size: 13px; font-weight: 500; transition: all .15s; }
  .sidebar nav a:hover { background: #252b3d; color: #fff; }
  .sidebar nav a.active { background: #252b3d; color: #ff9900; border-left: 3px solid #ff9900; }
  .sidebar nav a .icon { width: 18px; text-align: center; font-size: 15px; }
  .sidebar .sidebar-footer { padding: 14px 14px; border-top: 1px solid #2d3450; font-size: 11px; color: #555e70; }

  /* ── Main ── */
  .main { margin-left: 150px; }

  /* ── Top bar ── */
  .topbar { background: #232f3e; color: #fff; padding: 14px 28px; display: flex; align-items: center; justify-content: space-between; position: sticky; top: 0; z-index: 50; }
  .topbar h1 { font-size: 18px; font-weight: 600; letter-spacing: .3px; }
  .topbar .subtitle { font-size: 12px; color: #a0aec0; margin-top: 2px; }
  .topbar > div:first-child { flex: 0 0 auto; white-space: nowrap; }

  /* ── Custom range ── */
  .custom-range { display: none; align-items: center; gap: 8px; }
  .custom-range.visible { display: flex; }
  .custom-range input[type="date"] { padding: 6px 10px; border: 1px solid #cbd5e0; border-radius: 6px; font-size: 13px; }

  /* ── "DON'T OPTIMIZE" — the topbar chip that appears only when a FETCH
     problem could make a suggestion wrong (owner 2026-08-06). It is not the
     settling pill's neighbour in meaning: that one says "still firming up",
     this one says "do not act". Clicking opens the full reason list. ── */
  .noopt-chip { display: inline-flex; align-items: center; gap: 6px; background: #b42318; color: #fff;
                border: none; border-radius: 999px; padding: 5px 13px; font: inherit; font-size: 12.5px;
                font-weight: 700; letter-spacing: .3px; cursor: pointer; white-space: nowrap; }
  .noopt-chip:hover { background: #911c13; }
  .noopt-why { position: absolute; top: calc(100% - 4px); right: 28px; z-index: 60; width: 520px; max-width: calc(100vw - 56px);
               background: #fff; color: #2d3436; border: 1px solid #f5b5b5; border-radius: 10px;
               box-shadow: 0 12px 32px rgba(0,0,0,.18); padding: 14px 16px; font-size: 12.5px; line-height: 1.55; }
  .noopt-why h4 { font-size: 13px; margin-bottom: 4px; color: #b42318; }
  .noopt-why .noopt-sub { color: #8a93a0; font-size: 11.5px; margin-bottom: 10px; }
  .noopt-item { display: flex; gap: 9px; padding: 7px 0; border-top: 1px solid #f2f4f7; }
  .noopt-item:first-of-type { border-top: none; }
  .noopt-mark { flex: 0 0 16px; font-weight: 700; }
  .noopt-on  { color: #b42318; }
  .noopt-off { color: #cbd5e0; }
  .noopt-item.noopt-quiet, .noopt-item.noopt-quiet b { color: #98a1b0; }
  .noopt-detail { color: #98a1b0; font-size: 11.5px; }
  .noopt-foot { margin-top: 10px; font-size: 11.5px; color: #8a93a0; }
  .noopt-foot a { color: #2e86de; text-decoration: underline; cursor: pointer; }

  /* ── Notices ── */
  .notice { margin: var(--cg-row, 14px) 28px 0; padding: 6px 12px; border-radius: 6px; font-size: 12px; line-height: 1.35; }
  .notice-warn { background: #fff3cd; border: 1px solid #ffe08a; border-left: 4px solid #f0b429; color: #7a5c00; }
  .notice-err  { background: #fde8e8; border: 1px solid #f5b5b5; border-left: 4px solid #e53e3e; color: #8a1c1c; white-space: pre-wrap; font-family: 'SF Mono','Consolas',monospace; font-size: 12px; }
  /* the stale-bids warning is a red notice but a SENTENCE, not a stack trace —
     it keeps the red, drops the monospace/pre-wrap the error notice uses */
  #bidHealthNotice { white-space: normal; font-family: inherit; font-size: 12.5px; line-height: 1.5; padding: 8px 12px; }
  .notice-dim { color: #b06a6a; font-weight: 400; }

  /* ── The attention pills — the to-do counts the rules produce. Until
     2026-09-05 a card at the top of the page (like Inventory's warnings
     banner); now one row under the topbar. Empty (display:none via :empty)
     until there is data. ── */
  /* ONE ROW UNDER THE TOPBAR (owner 2026-09-05). It was inside the topbar
     for a day: centred "in the middle of nowhere" on a wide screen, a third
     line on a laptop. Now a fixed place, one row, left edge on the gutter.
     Overflow stays visible: the breakdown panels hang from the pills. */
  .ppc-alerts { display: flex; flex-wrap: nowrap; align-items: center; gap: 6px; white-space: nowrap;
                padding: 10px var(--cg-gutter, 28px) 0; box-sizing: border-box; z-index: 40; }
  /* ^ z-index 40: under the topbar (50), over the sticky bars below (30) and
     the cards — so an open breakdown panel is never painted behind them */
  @media (max-width: 1100px) { .ppc-alerts { flex-wrap: wrap; row-gap: 6px; } }
  .ppc-alerts:empty { display: none; }
  .warn-pill, .warn-sub, .warn-allclear { white-space: nowrap; }
  .warn-pill-btn { display: inline-flex; align-items: center; gap: 6px; background: none; border: 2px solid transparent; border-radius: 8px; cursor: pointer; padding: 0; font: inherit; }
  .warn-pill-btn:hover .warn-pill { filter: brightness(.94); }
  /* the lit pill = the filter that is on (click again to clear) */
  .warn-pill-btn.warn-pill-on { border-color: #2563eb; }
  .warn-pill-wrap { position:relative; display:inline-flex; }
  .warn-pill.warn-vt-other { background:#e9edf2; color:#5b6472; }
  .warn-pill .vt-x { margin-left:4px; color:inherit; opacity:.7; }
  .warn-pill .vt-x:hover { opacity:1; }
  /* the breakdown panel under a header pill — the Colour logic card's look,
     hung from the pill instead of the table toolbar */
  .pill-panel { left:0; right:auto; top:calc(100% + 6px); width:600px; max-width:calc(100vw - 60px); text-align:left; white-space:normal; font-weight:400; }
  .pill-panel .vt-leg-gc { display:flex; flex-direction:column; gap:2px; }
  .pill-panel .vt-spend .vt-pct { color:#1a6ec0; margin-left:2px; }
  .pill-panel .vt-spend .vt-cnt { color:#8a93a0; font-weight:600; }
  /* the "all" row (owner 2026-09-05: "all should look differently … just a
     mild difference"): the group's own chip, bold capitals with a thin
     outline, and a faint line under the row */
  .pill-panel .vt-chip.vt-chip-all { font-weight:800; text-transform:uppercase; letter-spacing:.3px; box-shadow:inset 0 0 0 1px currentColor; }
  .pill-panel .vt-leg-it.vt-all { border-bottom:1px solid #eef2f7; border-radius:0; padding-bottom:7px; margin-bottom:3px; }
  /* A SUBSET of the rows above it, never a row to add on (owners 2026-09-08:
     each keyword under ONE action). "paused · negate still missing" counts
     keywords the pause colours have already counted; it only says how many of
     them are half-done. Indented and faded so the eye reads it as a note. */
  .pill-panel .vt-leg-it.vt-sub-row { margin-left:22px; opacity:.85; border-top:1px dashed #e6ebf2; border-radius:0; padding-top:6px; }
  .vt-chip-other { background:#e9edf2; color:#5b6472; }
  .warn-caret { color: #8a6100; font-size: 12px; }
  .warn-pill { font-size: 12.5px; font-weight: 700; padding: 2px 8px; border-radius: 6px; }
  .warn-pill.warn-red { background: #fde2e1; color: #b42318; }
  .warn-pill.warn-amber { background: #fbeec3; color: #8a6100; }
  .warn-pill.warn-soon { background: #dbeafe; color: #1d4ed8; }
  /* the strong-word list is the one piece of GOOD news on the row — it asks a
     manager to consider a word for the listing, it never stops anything */
  .warn-pill.warn-good { background: #dcf5e6; color: #1e7a45; }
  .warn-body { max-height: 260px; overflow-y: auto; padding: 4px 12px 10px; border-top: 1px solid #f0d2c0; }
  .warn-list { margin: 6px 0 0; padding-left: 20px; }
  .warn-li { font-size: 12px; line-height: 1.55; }
  .warn-li.warn-red { color: #7a271a; }
  .warn-li.warn-amber { color: #6b4a05; }
  .warn-li.warn-soon { color: #1e40af; }
  .warn-li.warn-good { color: #1e7a45; }
  .warn-dim { color: #98a1b0; font-weight: 400; }
  .warn-more { font-size: 11.5px; color: #9a7b5a; margin: 6px 0 0 20px; }
  .warn-allclear { font-size: 12.5px; font-weight: 700; color: #15803d; }
  .warn-sub { font-size: 11px; color: #9a7b5a; }
  /* not "still loading" — it failed, and the lists below are incomplete */
  .warn-sub.warn-sub-bad { color: #b02020; font-weight: 700; cursor: help; }
  /* "mark as done" ticks: the ✓ button on active lines, the muted handled state, undo */
  .warn-done-btn { margin-left: 6px; padding: 1px 8px; font: inherit; font-size: 11px; font-weight: 600; color: #15803d; background: #fff; border: 1px solid #bbe3c8; border-radius: 999px; cursor: pointer; vertical-align: 1px; }
  .warn-done-btn:hover { background: #f0fdf4; border-color: #15803d; }
  .warn-li-done { color: #98a1b0 !important; }
  .warn-li-done b { color: #7b8494; }
  .warn-done-note { font-size: 11px; color: #15803d; font-weight: 600; }
  .warn-undo { font-size: 11px; color: #2e86de; text-decoration: underline; cursor: pointer; }
  .warn-pill.warn-donepill { background: #e8f5ec; color: #15803d; }
  /* the "Update bid" test controls on bid-alert lines */
  .warn-bidctl { display: inline-flex; align-items: center; gap: 5px; margin-left: 8px; vertical-align: 1px; }
  .warn-bidctl input { width: 74px; padding: 2px 6px; font: inherit; font-size: 11.5px; border: 1px solid #d9c2ab; border-radius: 6px; background: #fff; }
  .warn-bid-btn { padding: 1px 9px; font: inherit; font-size: 11px; font-weight: 600; color: #2e86de; background: #fff; border: 1px solid #b9d4f0; border-radius: 999px; cursor: pointer; }
  .warn-bid-btn:hover { background: #f0f7ff; border-color: #2e86de; }
  .warn-bid-btn:disabled { opacity: .55; cursor: default; }
  .warn-bid-msg { font-size: 11px; font-weight: 600; }
  /* stands in for the Update box + button while the bid snapshot is stale */
  /* a line whose entity Amazon says was already changed elsewhere: it keeps
     its name, loses its suggestion, and explains itself in place */
  .warn-li-amzchg { color: #7a271a; }
  .warn-amzchg { color: #7a271a; }
  .warn-amzchg b { color: #b42318; }
  .warn-stalectl { margin-left: 8px; padding: 1px 9px; font-size: 11px; font-weight: 600; color: #b42318; background: #fff; border: 1px solid #f5b5b5; border-radius: 999px; white-space: nowrap; vertical-align: 1px; }
  /* "Worse performance" — the true-loss breakdown */
  .warn-worst-btn { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; background: #fff; border: 1px solid #f5b5b5; border-radius: 6px; padding: 3px 10px; font: inherit; font-size: 12px; font-weight: 700; color: #b42318; cursor: pointer; white-space: nowrap; }
  .warn-worst-btn:hover { background: #fef2f2; border-color: #b42318; }
  .warn-body-tall { max-height: 72vh; }
  .worst-head { font-size: 11.5px; color: #6b4a05; margin: 8px 0 4px; line-height: 1.5; }
  .worst-sec { margin-top: 10px; }
  .worst-sec-title { font-size: 12.5px; font-weight: 700; color: #7a271a; border-bottom: 1px solid #f0d2c0; padding-bottom: 3px; margin-bottom: 8px; }
  .worst-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 8px 18px; }
  .worst-win { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px; color: #8a6100; margin-bottom: 5px; }
  .worst-row { font-size: 12px; line-height: 1.7; }
  .worst-name { font-weight: 600; color: #2d3436; }
  .worst-loss { color: #b42318; cursor: pointer; border-bottom: 1px dotted #b42318; }
  .worst-miss { font-size: 10.5px; font-weight: 700; background: #fbeec3; color: #8a6100; border-radius: 6px; padding: 0 6px; white-space: nowrap; }
  .worst-sum { font-size: 11.5px; color: #6b4a05; border-top: 1px dashed #e2c9b6; margin-top: 5px; padding-top: 4px; line-height: 1.6; }
  .worst-note { font-size: 11.5px; color: #9a7b5a; }

  /* ── Filter section ── */
  .filters-bar { display: flex; align-items: flex-start; gap: 10px 16px; padding: 10px 28px; background: #fff; border-radius: 10px; margin: 0 28px var(--cg-row, 14px); box-shadow: 0 1px 3px rgba(0,0,0,.06); flex-wrap: wrap; z-index: 30; }   /* each block owns its BOTTOM gap only — the card above already spaced it */
  /* ^ z-index 30: the bar is position:sticky (hpin-card), which traps its
     dropdown panels in a new stacking context — without this the sticky table
     header (z-index 5/6) paints over the open dropdowns. 30 keeps dropdowns
     above the table but below the topbar (50). */
  .filter-group { display: flex; flex-direction: column; gap: 3px; }   /* compact filter rows (owner) */
  .filter-group > label { font-size: 11px; font-weight: 600; color: #636e72; text-transform: uppercase; letter-spacing: .5px; }
  .filter-chips { display: flex; flex-wrap: wrap; gap: 6px; }
  .filter-chip { padding: 4px 12px; border: 1px solid #cbd5e0; border-radius: 16px; font-size: 12px; cursor: pointer; user-select: none; transition: all .15s; background: #fff; }
  .filter-chip:hover { border-color: #ff9900; }
  .filter-chip.active { background: #ff9900; color: #fff; border-color: #ff9900; }

  /* ── Dropdown filters ── */
  .dropdown-filter-wrap { position: relative; }
  .dropdown-filter-btn { padding: 4px 14px; border: 1px solid #cbd5e0; border-radius: 16px; font-size: 12px; cursor: pointer; background: #fff; display: flex; align-items: center; gap: 6px; }
  .dropdown-filter-btn:hover { border-color: #ff9900; }
  .dropdown-panel { display: none; position: absolute; top: 100%; left: 0; margin-top: 4px; background: #fff; border: 1px solid #e2e8f0; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,.1); padding: 8px 0; z-index: 200; max-height: 340px; overflow-y: auto; min-width: 220px; }
  .dropdown-panel.open { display: block; }
  .dropdown-panel .dd-header { display: flex; justify-content: space-between; padding: 4px 12px 8px; border-bottom: 1px solid #edf2f7; }
  .dropdown-panel .dd-header a { font-size: 11px; color: #ff9900; cursor: pointer; text-decoration: none; }
  .dropdown-panel .dd-header a:hover { text-decoration: underline; }
  .dropdown-panel label { display: flex; align-items: center; gap: 8px; padding: 5px 12px; font-size: 12px; cursor: pointer; }
  .dropdown-panel label:hover { background: #f7fafc; }
  /* the Columns menu's group box + the members under it (owner 2026-09-05) */
  .dropdown-panel label.col-grp { border-top: 1px solid #eef2f7; margin-top: 4px; padding-top: 7px; }
  .dropdown-panel label.col-in-grp { padding-left: 30px; color: #4a5568; }
  .dropdown-panel input[type="checkbox"] { accent-color: #ff9900; }
  .count-badge { background: #ff9900; color: #fff; border-radius: 10px; padding: 0 7px; font-size: 11px; font-weight: 700; }
  /* A short line of guidance under a dropdown's Select all / Deselect all. */
  .dropdown-panel .dd-note { padding: 6px 12px 7px; font-size: 11px; line-height: 1.45; color: #718096; border-bottom: 1px solid #edf2f7; }
  /* ── A GROUP OF TICK BOXES WITH ONE MASTER OVER IT (owner 2026-09-04) ──
     The Type picker's 18 campaign types, split by ad type. The master is bold
     and its members are indented, so the eye reads the group before the rows;
     the "3/8" beside a heading answers "how much of this is on" without
     opening anything. Same behaviour as the Sales dashboard's Columns picker,
     which is where the owners asked for it from. */
  .dropdown-panel .dd-grp { border-top: 1px solid #edf2f7; }
  .dropdown-panel .dd-grp:first-child { border-top: 0; }
  .dropdown-panel .dd-grp-head { font-weight: 700; color: #2d3436; background: #fbfcfe; }
  .dropdown-panel .dd-grp-head:hover { background: #eef4fb; }
  .dropdown-panel .dd-grp-n { margin-left: auto; font-weight: 600; font-size: 10.5px; color: #8a93a0;
                              background: #fff; border: 1px solid #e2e8f0; border-radius: 9px; padding: 0 6px; }
  .dropdown-panel .dd-grp-body label { padding-left: 30px; }
  /* The LIST picker (owner 2026-08-27) — one list at a time, so radios, not
     tick boxes: two overlapping cohorts at once answers nothing. The panel is
     WIDER and TALLER than the other dropdowns because its rows carry three
     things (name, size, date) plus their own two controls, and a name like
     "2K kw raised for low impressions 27-8" must not wrap to read it. */
  #listDropdown { min-width: 380px; max-height: 460px; }
  .dropdown-panel .dd-row { display: flex; align-items: center; gap: 8px; padding: 5px 12px; font-size: 12.5px; color: #2d3436; cursor: pointer; }
  .dropdown-panel .dd-row:hover { background: #f5f8fc; }
  .dropdown-panel .dd-row input { accent-color: #ff9900; cursor: pointer; }
  .dropdown-panel .dd-sub { color: #98a1b0; font-size: 11px; }
  /* name + size/date on the left, its controls pinned right */
  .dropdown-panel .dd-row-list, .dropdown-panel .dd-row-gone { justify-content: space-between; }
  .dropdown-panel .dd-pick { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; cursor: pointer; }
  .dropdown-panel .dd-nm { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
  .dropdown-panel .dd-nm > .dd-sub { display: block; }
  .dropdown-panel .dd-acts { display: inline-flex; gap: 2px; flex: 0 0 auto; }
  /* The controls stay quiet until the row is hovered — a list of lists should
     read as names, not as a row of buttons. */
  .dropdown-panel .dd-act { padding: 2px 6px; border-radius: 5px; color: #98a1b0; cursor: pointer; font-size: 12px; opacity: 0; transition: opacity .12s; }
  .dropdown-panel .dd-row:hover .dd-act { opacity: 1; }
  .dropdown-panel .dd-act:hover { background: #eaf3fc; color: #2563eb; }
  .dropdown-panel .dd-act-del:hover { background: #fdecea; color: #b42318; }
  .dropdown-panel .dd-act-back { opacity: 1; color: #2563eb; font-size: 11.5px; font-weight: 600; }
  .dropdown-panel .dd-gone-h { margin-top: 4px; padding: 6px 12px 3px; border-top: 1px solid #edf2f7; font-size: 11px; font-weight: 700; color: #98a1b0; text-transform: uppercase; letter-spacing: .4px; }
  .dropdown-panel .dd-row-gone .dd-nm { color: #98a1b0; }
  /* …and the name of the list you are reading, on the table's count line. */
  .cnt-list { color: #b06000; font-weight: 700; }
  /* ── THE SHARED MARK IN THE CAMPAIGN TYPE FILTER (owner 2026-08-21) ──
     Same grey/orange chips the table puts beside a keyword, so the two places
     never disagree. Pushed to the right edge (margin-left:auto beats the
     .state-chip 6px) so the x/y figures line up in a column and the longest
     type name — "SB Product Collection ASIN" — still fits on one line. */
  #ctypeDropdown { min-width: 300px; }
  #ctypeDropdown label .state-chip { margin-left: auto; }

  /* ── KPI cards ── */
  /* The summary row: ONE row of 8, the shell's house cards (RULEBOOK Rule 6
     §2) in their SLIM one-line variant (.cg-kpis-slim, shell.css — owner
     2026-09-05: "much more compact vertically"). The page-local card padding /
     font sizes that used to sit here were dead under the shell and are gone. */
  .kpis { gap: 8px; padding: var(--cg-row, 14px) 28px; }
  /* "filtered products only" (ui.js renderKpis) — the card counts what the
     filter shows, the keyword table below counts whole keywords. */
  .kpi .sub .kpi-part { color: #b06000; cursor: help; border-bottom: 1px dotted #e0a060; }

  /* ── The two closed cards share ONE row (owner 2026-08-24: "tighten what's
     above the PPC table") ────────────────────────────────────────────────────
     "Breakdown by campaign" and "Charts" are two title lines while they are
     closed, and two title lines were costing the page two full rows plus two
     gaps — height the table underneath needs more than they do. Side by side
     they cost one. OPEN one and it takes the whole width back (.rowcard-wide,
     set by toggleCharts / toggleTrend in ui.js / tools.js), so a chart is never
     squeezed into half a page; the other card wraps to the line below it. */
  .cg-rowpair { display: flex; flex-wrap: wrap; gap: var(--cg-row, 14px); align-items: flex-start; }
  .cg-rowpair > .chart-card { flex: 1 1 calc(50% - (var(--cg-row, 14px) / 2)); min-width: 260px; margin: 0; }
  .cg-rowpair > .chart-card.rowcard-wide { flex-basis: 100%; }

  /* The number ranges inside the "Numbers" dropdown — label, then min – max.
     The panel itself, its header and its badge are the house dropdown already
     used for Models / Brands / Types / Columns; only these rows are new. */
  .dropdown-panel .dd-ranges { display: grid; grid-template-columns: auto auto; gap: 6px 10px; align-items: center; padding: 8px 12px 4px; }
  .dropdown-panel .dd-ranges > label { font-size: 11.5px; color: #4a5568; font-weight: 600; white-space: nowrap; }
  .dropdown-panel .dd-ranges > span { display: flex; align-items: center; gap: 5px; }
  .dropdown-panel .dd-ranges input { padding: 5px 8px; border: 1px solid #cbd5e0; border-radius: 6px; font-size: 13px; width: 68px; }
  .dropdown-panel .dd-ranges .dd-dash { color: #8a93a0; }

  /* ── Charts grid ── */
  .charts-grid { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr); gap: 20px; padding: 0 28px 22px; }
  /* Nested inside the collapsible "Breakdown by campaign" card (2026-08-12):
     the panels are that card's CONTENT, so they drop the card chrome — one box
     that unfolds, not a second box appearing underneath. The two-panel views
     (keyword / model) keep a hairline between them instead of two borders. */
  .cg-rowcard .charts-grid { padding: 14px 0 0; }
  html[data-shell="v2"] .cg-rowcard .charts-grid > .chart-card {
    border: 0; border-radius: 0; box-shadow: none; padding: 0; background: transparent;
  }
  html[data-shell="v2"] .cg-rowcard .charts-grid:not(.single) > .chart-card + .chart-card {
    border-left: 1px solid #e6e8ec; padding-left: 20px;
  }
  /* Campaign view: ONE full-width card (chart OR the comparison table). */
  /* minmax(0,1fr), NOT 1fr: 1fr's auto min-width lets the wide compare
     table inflate the column past the page, killing the card's own scrollbar. */
  .charts-grid.single { grid-template-columns: minmax(0,1fr); }
  /* ── Period-to-period campaign-type table (the campaign card's compare
     mode). Type names are the sticky first column; compact cells, cents
     rounded away, always-visible horizontal scrollbar (.table-scroll). ── */
  /* The compare table is its OWN scroll box (owner 2026-08-12): its height is
     draggable (the .pc-vsep bar under it, same UX as the big table's
     #tblResize), the header freezes at the top of THIS box — never the page,
     which is the bug that had it sliding down the screen — and the Total row
     pins to the bottom. `height` is set from JS (`--pc-h`), so the box opens at
     whatever shows the whole table and the user can grow or shrink it. */
  .pc-scroll { overflow-x: scroll; overflow-y: auto; scrollbar-width: auto; height: var(--pc-h, auto); }
  .pc-scroll::-webkit-scrollbar { height: 12px; }
  .pc-scroll::-webkit-scrollbar-thumb { background: #c5cdd8; border-radius: 6px; }
  .pc-scroll::-webkit-scrollbar-thumb:hover { background: #a8b3c2; }
  .pc-scroll::-webkit-scrollbar-track { background: #f1f3f7; }
  /* Natural column widths inside the horizontal scroll strip — the page-wide
     table rules (table-layout:fixed + ellipsis cells) would squeeze the 4
     sub-columns × 6 periods into unreadable "$…" stubs. */
  .pc-table { border-collapse: collapse; font-size: 11px; table-layout: auto; width: max-content; min-width: 100%; }
  /* Figures CENTRED, name column left — the house alignment (RULEBOOK Rule 6:
     "only the first name column is left, every figure is centred"). This table
     was right-ragged until 2026-08-12. */
  .pc-table th, .pc-table td { padding: 2px 7px; text-align: center; white-space: nowrap; overflow: visible; text-overflow: clip; max-width: none; border-bottom: 1px solid #edf2f7; vertical-align: middle; }
  /* Undo the page-wide data-table header look (dark, sticky, uppercase). */
  .pc-table thead th { background: var(--cg-th-bg); font-size: 10.5px; color: var(--cg-th-fg); font-weight: 600; text-transform: none; letter-spacing: 0; text-align: center; border-bottom: 2px solid var(--cg-th-line); z-index: auto; }
  /* THE HEADER FREEZES TO ITS OWN BOX, NOT THE PAGE (owner 2026-08-12, twice:
     first "the frozen header is being dragged down when scrolling", then "the
     header row should be frozen when scrolling down"). The original
     `position: static` never won anything: the shared shell re-applies sticky
     to any thead th inside a `.table-scroll` strip, and styles.css loads
     BEFORE shell.css, so it lost on both specificity and order. The page-wide
     `thead th { top: var(--topbar-h) }` then pinned BOTH header rows 66px down
     the SCREEN — they slid over the rows AND stacked on each other, hiding the
     period names. Pinning them to the scroll box (`top: 0`) is the same thing
     the big table does in `#tblArea.hcap`. Row 2 sits directly under row 1, so
     its offset is row 1's MEASURED height (`--pc-h1`, set in compare.js) —
     never a constant, because the period names wrap. Specificity is
     deliberately higher than the shell's rule. */
  html[data-shell="v2"] .pc-scroll .pc-table thead th { top: 0; bottom: auto; z-index: 3; }
  html[data-shell="v2"] .pc-scroll .pc-table thead tr:nth-child(2) th { top: var(--pc-h1, 24px); }
  html[data-shell="v2"] .pc-scroll .pc-table thead th.pc-name { left: 0; z-index: 5; }
  /* The Total row pins to the bottom edge, like the big table's TOTAL. Its
     border is drawn as a shadow — a collapsed border on a sticky cell stays
     behind (same quirk noted on the frozen name column). */
  .pc-scroll .pc-table tr.pc-total td { position: sticky; bottom: -1px; z-index: 2; box-shadow: 0 -2px 0 0 #cbd5e0; }
  .pc-scroll .pc-table tr.pc-total td.pc-name { z-index: 4; }
  /* The drag bar under the box — the house grip (.tbl-vsep), declared with it. */
  .pc-vsep { margin-top: 2px; }
  .pc-table tr:last-child td { border-bottom: none; }
  /* ALL TIME — the first column block. Its own background, so a reader can
     never mistake it for one of the equal-length windows beside it. */
  .pc-table .pc-alltime { background: #f4f7fc; }
  .pc-table thead th.pc-alltime { background: #eef3fa; }
  /* The bold TOTAL row that closes the table. */
  .pc-table tr.pc-total td { font-weight: 700; color: #2d3436; border-top: 2px solid var(--cg-total-line); background: var(--cg-total-bg); }
  .pc-table tr.pc-total td.pc-name { background: var(--cg-total-bg); }
  .pc-table tr.pc-total td.pc-alltime { background: #eef3fa; }
  .pc-dates { display: block; font-size: 10.5px; color: #98a1b0; font-weight: 400; }
  .pc-table th.pc-phead { text-align: center; padding-top: 4px; }
  .pc-table th.pc-sub { font-size: 10px; font-weight: 500; color: #98a1b0; padding-top: 2px; }
  .pc-table .pc-psep { border-left: 2px solid #e2e8f0; }
  /* The ACOS pills reuse the table's acos-* classes; tighten them to fit the short rows. */
  .pc-table td span[class*="cg-acos-"] { padding: 1px 5px; font-size: 10.5px; }
  /* The type-name column: sticky left with a visible edge, like the big table's frozen block. */
  .pc-table .pc-name { position: sticky; left: 0; z-index: 1; background: #fff; text-align: left; font-weight: 600; color: #2d3436; box-shadow: 3px 0 5px -2px rgba(45,55,72,0.16); padding: 4px 10px; }
  /* the frozen column's own white must not punch a hole in the header row */
  .pc-table thead th.pc-name { background: var(--cg-th-bg); color: var(--cg-th-fg); }
  /* edge as ::after, not border — sticky cells' collapsed borders don't travel (same quirk as the main table) */
  .pc-table .pc-name::after { content: ''; position: absolute; top: 0; bottom: 0; right: 0; width: 2px; background: #d5dbe3; pointer-events: none; }
  .pc-table td.pc-name { font-weight: 500; }
  .chart-card { background: #fff; border-radius: 10px; box-shadow: 0 1px 3px rgba(0,0,0,.06); padding: 20px; }
  .chart-card h3 { font-size: 16px; font-weight: 600; margin-bottom: 14px; color: #2d3436; }
  /* The campaign card's title row carries the mode button on the right. */
  #pieCard h3 { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; }
  .chart-card canvas { width: 100% !important; }
  .pie-card { display: flex; flex-direction: column; }
  /* Loading overlay shown over the campaign-type chart while a new period loads */
  .chart-loading { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #636e72; font-size: 13px; background: #fff; }

  /* ── Top-performers panel (right of the campaign-type chart) ── */
  .top-perf-card .tp-sub { font-size: 11.5px; color: #636e72; font-weight: 400; margin-left: 6px; }
  .top-perf-body { max-height: 440px; overflow-y: auto; margin: -2px -4px 0; }
  .top-perf-body table.tp-table { width: 100%; border-collapse: collapse; table-layout: auto; font-size: 12.5px; }
  .top-perf-body table.tp-table td { padding: 6px 8px; border: none; border-bottom: 1px solid #edf2f7; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: none; }
  .top-perf-body table.tp-table tr:last-child td { border-bottom: none; }
  .top-perf-body table.tp-table tr:hover td { background: rgba(255,153,0,0.06); }
  .tp-rank { width: 22px; text-align: right; color: #b0b8c0; font-weight: 700; font-variant-numeric: tabular-nums; }
  .tp-name { max-width: 0; width: 99%; }
  .tp-label { font-weight: 600; color: #2d3436; }
  .tp-ctx { color: #8a93a0; font-size: 11px; }
  .tp-rev { text-align: right; white-space: nowrap; color: #00875a; font-weight: 700; font-variant-numeric: tabular-nums; }
  .tp-pct { text-align: right; white-space: nowrap; color: #4a5568; width: 46px; font-variant-numeric: tabular-nums; }
  .tp-empty { color: #636e72; font-size: 13px; padding: 28px 4px; text-align: center; }

  /* ── Table ── */
  .table-wrap { padding: 0 28px 28px; }
  /* The table can be much wider than the screen; the PAGE scrolls sideways.
     The PAGE NEVER SCROLLS SIDEWAYS (RULEBOOK Rule 6, owner 2026-08-05):
     the table owns its own horizontal scroll, so the body is never stretched
     to the table's width. `body { min-width: max-content }` used to do that
     stretching — it is what let the browser's own bottom bar drag the whole
     dashboard (sidebar gap, cards, filters) out of frame to the left.
     The .hpin helpers below stay: they cost nothing now, and they keep each
     block on the visible page width (measured into --page-w). */
  body { max-width: 100%; }
  .hpin { position: sticky; left: var(--sidebar-w, 0px); width: var(--page-w, auto); box-sizing: border-box; }
  .hpin-card { position: sticky; left: calc(var(--sidebar-w, 0px) + 28px); width: calc(var(--page-w, 100vw) - 56px); box-sizing: border-box; }
  /* The header row freezes via position:sticky on the thead cells (below), pinned
     relative to the PAGE — so the whole page keeps scrolling as one and the charts
     above scroll away normally. We deliberately do NOT make this an inner scroll
     box (no overflow/ max-height): that created a second scrollbar that "trapped"
     the wheel over the table and left the upper content stuck on screen. */
  .table-card { background: #fff; border-radius: 10px; box-shadow: 0 1px 3px rgba(0,0,0,.06); position: relative; }
  /* THE TABLE OWNS ITS OWN SIDEWAYS SCROLL (owner 2026-08-05). Before this the
     wide table overflowed the PAGE, so the browser's own bottom scrollbar
     dragged the whole dashboard — summary cards, filters and all — sideways.
     Now only the table moves, and that bar belongs to the table. */
  #tblArea { overflow-x: auto; max-width: calc(var(--page-w, 100vw) - 56px); }
  #tblArea #dataTable th:nth-child(1), #tblArea #dataTable td:nth-child(1) { left: 0; }
  #tblArea #dataTable th:nth-child(2), #tblArea #dataTable td:nth-child(2) { left: 28px; }
  .table-card h2 { font-size: 17px; font-weight: 600; padding: 12px 20px 10px; border-bottom: 1px solid #edf2f7; display:flex; align-items:center; gap:12px; flex-wrap:wrap; z-index: 7; }
  /* THE COUNT RIDES THE TITLE LINE (owner 2026-08-24). It was a line of its own
     under the title — a whole row of page height for half a line of text. Its
     own size and colour travel with it, since inside the <h2> it would
     otherwise be read as part of the title. */
  .table-card h2 #tableCount { font-size: 12.5px; color: #4a5568; font-weight: 600; display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px; }
  .table-card h2 #tableCount:not(:empty)::before { content: '·'; color: #a0aab8; margin-right: 2px; }
  /* ^ z-index 7: the title bar is position:sticky (hpin-card), which traps the
     Colours legend card in its own stacking layer — without this the frozen
     table header (z-index 5/6) paints IN FRONT of the open card (owner
     screenshot 2026-08-10). 7 keeps the card above the header; the title and
     the header never overlap vertically, so nothing else changes. */
  table { border-collapse: collapse; font-size: 13px; width: 100%; table-layout: fixed; }
  /* Alignment/wrapping deliberately NOT set here — the house table standard in
     Shared Data/shell.css owns it for every page (headers wrap to ~2 lines and
     centre, figures centre, everything vertically centres). Only the PPC-
     specific bits (colours, padding, sticky offset) live here. */
  /* colours (background / label / underline) and the totals row below come from
     the shell's house table tokens — RULEBOOK Rule 6 §5a. */
  thead th { padding: 8px 6px; font-weight: 600; font-size: 11.5px; text-transform: uppercase; letter-spacing: .4px; overflow: hidden; position: sticky; top: var(--topbar-h, 66px); z-index: 5; }

  /* Frozen left columns: the row-select box + the identity column (campaign /
     keyword / model) stay pinned while the page scrolls sideways — phones too. */
  #dataTable th:nth-child(1), #dataTable td:nth-child(1) { position: sticky; left: calc(var(--sidebar-w, 150px) + 28px); }
  #dataTable th:nth-child(2), #dataTable td:nth-child(2) { position: sticky; left: calc(var(--sidebar-w, 150px) + 56px); }
  /* (The opaque gutter strip that used to hide cells sliding through the 28px
     gap is gone with the page's sideways scroll — nothing slides any more.) */
  /* Visible right EDGE on the frozen block, so it's clear where the freeze
     ends when the table scrolls sideways (2026-08-04). NOT a border: with
     border-collapse, a border on a position:sticky cell stays behind at the
     cell's original spot and scrolls away (browser quirk — the owner's bug
     report). An ::after strip is part of the cell, so it travels with it. */
  #dataTable th:nth-child(2), #dataTable td:nth-child(2) { box-shadow: 3px 0 5px -2px rgba(45,55,72,0.16); }
  #dataTable th:nth-child(2)::after, #dataTable td:nth-child(2)::after {
    content: ''; position: absolute; top: 0; bottom: 0; right: 0; width: 2px; background: #d5dbe3; pointer-events: none;
  }
  #dataTable tbody td:nth-child(-n+2) { background: #fff; z-index: 2; }
  #dataTable tr.lvl-1 td:nth-child(-n+2) { background: #f7fafc; }
  #dataTable tr.lvl-2 td:nth-child(-n+2) { background: #eef3f8; }
  #dataTable tr.lvl-3 td:nth-child(-n+2) { background: #e9eef5; }
  #dataTable tbody tr:hover td:nth-child(-n+2) { background: #fffaf0; }
  #dataTable thead th:nth-child(-n+2) { --cg-th-z: 21; }   /* corner cells above the rest of the header */
  thead th.sortable { cursor: pointer; user-select: none; }
  thead th.sortable:hover { color: #2563eb; }
  thead th .sort-arrow { font-size: 9px; margin-left: 2px; opacity: 0.45; color: #cbd5e0; white-space: nowrap; }
  thead th.sort-active .sort-arrow { opacity: 1; color: #2563eb; }

  /* ── Resizable columns (drag the separator on a header edge) ── */
  .col-resize-handle {
    position: absolute; right: 0; top: 0; bottom: 0; width: 5px;
    cursor: col-resize; user-select: none; z-index: 10;
    border-right: 2px solid rgba(255,255,255,0.45);
  }
  .col-resize-handle:hover, .col-resize-handle.active { background: #ff9900; border-right-color: #ff9900; }
  /* The drag guide line (commit-on-release column resize) */
  .col-resize-guide { position: fixed; top: 0; bottom: 0; width: 0; border-left: 2px solid #ff9900; z-index: 1200; pointer-events: none; }

  /* ── Resizable table height — same drag-bar UX as the Inventory dashboard's
     dividers. The bar sits under the table; drag it up to cap the table's
     height (it then scrolls inside its own box), drag it all the way down past
     the end of the table to let it grow full length again (the default). ── */
  /* .tbl-vsep and its pill are the HOUSE grip and live in
     Shared Data/shell.css (moved there 2026-08-18 when the Leads table took
     the same control) — never re-declare them here, or the two drift apart. */
  /* Height-capped mode: the box owns BOTH scrollbars, so the sticky offsets
     (frozen header + frozen left columns) move from the page to the box, and
     the box is capped to the visible page width so the page itself no longer
     scrolls sideways. */
  #tblArea.hcap { height: var(--tbl-h, 480px); overflow: auto; max-width: calc(var(--page-w, 100vw) - 56px); }
  #tblArea.hcap thead th { top: 0; }
  #tblArea.hcap #dataTable th:nth-child(1), #tblArea.hcap #dataTable td:nth-child(1) { left: 0; }
  #tblArea.hcap #dataTable th:nth-child(2), #tblArea.hcap #dataTable td:nth-child(2) { left: 28px; }
  /* One-screen AUTO-FIT default (owner request 2026-08-04): max-height instead
     of height, so a short table doesn't leave an empty hole in the pane. */
  #tblArea.hcap-auto { height: auto; max-height: var(--tbl-h, 480px); }
  /* The TOTAL row rides the pane's bottom edge — always in view while the
     rows scroll behind it (Amazon-console style). bottom:-1px + the dark
     under-strip (box-shadow) close the 1–2px sliver of the row behind that
     sub-pixel rounding let peek beneath the pinned totals (owner 2026-08-04). */
  #tblArea.hcap tbody tr.total-row td { position: sticky; bottom: -1px; z-index: 3; box-shadow: 0 3px 0 0 var(--cg-total-line); }
  #tblArea.hcap tbody tr.total-row td:nth-child(-n+2) { z-index: 4; }
  tbody td { padding: 7px 8px; border-top: 1px solid #edf2f7; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 260px; }
  tbody tr:hover { background: #fffaf0; }
  /* Totals: never crop the numbers (owner report 2026-08-04 — the big sums
     were ellipsized into "$57,386,…"). Slightly smaller font than before
     (was 14px) + no ellipsis; a number wider than its column paints over the
     row's own dark background instead of being cut. */
  tbody tr.total-row { font-weight: 700; font-size: 12px; }
  tbody tr.total-row td { padding: 10px 8px; overflow: visible; text-overflow: clip; }
  /* Figure/identity alignment comes from the house standard in shell.css —
     figures centre, identity (name) columns stay left. Do not re-declare it. */
  /* Tree level shading */
  tr.lvl-1 { background: #f7fafc; }
  tr.lvl-2 { background: #eef3f8; }
  tr.lvl-3 { background: #e9eef5; }
  tr.lvl-1 td, tr.lvl-2 td, tr.lvl-3 td { font-size: 12.5px; color: #2d3436; }
  .expand-icon { display: inline-block; width: 14px; font-size: 9px; color: #ff9900; transition: transform .15s; cursor: pointer; }
  .expand-icon.open { transform: rotate(90deg); }
  /* Copy-name chip on campaign names — appears on row hover, click = copy */
  /* The chip itself is the shell's (Shared Data/shell.css) since 2026-08-30,
     including the hover-reveal — this page opts in with data-cg-copy="hover"
     on its <html>. Only the ACCENT stays here, which Rule 6 §4 leaves to the
     page. */
  .copy-btn:hover { color: #ff9900; }
  .row-clickable { cursor: pointer; }

  .marketplace-badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
  .badge-us { background: #dfe6e9; color: #2d3436; }
  .badge-ca { background: #ffeaa7; color: #6c5ce7; }
  .text-green { color: #00b894; }
  .text-red { color: #d63031; }
  /* ACOS heat (higher = worse) */
  /* ACOS tints — the decision tree's OWN lines since 2026-08-09 (the old
     separate 25/35/100 scale is retired): deep green under the raise line,
     light green in the healthy band, orange up to the pause line, red above */
  /* The ACOS palette moved to Shared Data/shell.css on 2026-08-12 — ONE set of
     colours for this page and the Sales dashboard. Only the numbers are still
     per-page (⚙ Settings → Colour rules). Don't re-declare the hexes here. */
  /* The top ACOS KPI wears the same tier colours as the column, sized up
     to the card's value font (mirrors the Sales Net-Profit KPI badge). */
  .kpi .kpi-acos-badge { display: inline-block; padding: 0 9px; border-radius: 6px; }
  .match-badge { display:inline-block; padding:1px 7px; border-radius:4px; font-size:11px; font-weight:600; background:#edf2f7; color:#4a5568; }
  /* Negative-keyword marks: ⛔ badge on negated keyword rows, "⛔ N" count chip
     in the campaign rows' "Negative KW" column. neg-warn = negated but still spending. */
  .neg-badge { display:inline-block; padding:1px 6px; border-radius:4px; font-size:10.5px; font-weight:700; background:#fdecea; color:#c0392b; white-space:nowrap; }
  .neg-badge.neg-warn { background:#c0392b; color:#fff; }
  .neg-chip  { display:inline-block; padding:1px 7px; border-radius:9px; font-size:10.5px; font-weight:700; background:#fdecea; color:#c0392b; white-space:nowrap; cursor:pointer; }
  .neg-chip:hover { background:#fadbd8; }
  /* ── Negative-keywords modal (click a "⛔ N" chip) ── */
  .neg-modal-bg { position:fixed; inset:0; background:rgba(15,20,30,.45); z-index:3000; display:flex; align-items:center; justify-content:center; }
  .neg-modal { background:#fff; border-radius:12px; width:min(720px, 94%); max-height:88%; display:flex; flex-direction:column; box-shadow:0 12px 40px rgba(0,0,0,.25); overflow:hidden; }
  .nm-filters { display:flex; gap:6px; padding:10px 18px 0; flex-wrap:wrap; flex-shrink:0; }
  .nm-chip { border:1px solid #d7dbe2; background:#fff; border-radius:999px; padding:4px 11px; font-size:11.5px; font-weight:600; color:#5b6472; cursor:pointer; }
  .nm-chip:hover { border-color:#2563eb; color:#1d4ed8; }
  .nm-chip.active { background:#eaf1fe; border-color:#bcd3fa; color:#1d4ed8; }
  .neg-modal header { display:flex; align-items:flex-start; gap:10px; padding:14px 18px; border-bottom:1px solid #eef0f3; }
  .neg-modal .nm-title { font-size:14px; font-weight:700; color:#1a1d23; word-break:break-word; }
  .neg-modal .nm-sub { font-size:11.5px; color:#98a1b0; margin-top:2px; }
  .neg-modal .nm-x { margin-left:auto; border:0; background:#f2f4f7; border-radius:8px; width:28px; height:28px; font-size:14px; cursor:pointer; color:#5b6472; flex-shrink:0; }
  .neg-modal .nm-x:hover { background:#e6e8ec; color:#1a1d23; }
  .neg-modal .nm-body { overflow:auto; }
  .neg-modal table { width:100%; border-collapse:collapse; font-size:12.5px; }
  .neg-modal thead th { position:sticky; top:0; background:var(--cg-th-bg); text-align:left; padding:8px 14px; font-size:10.5px; text-transform:uppercase; letter-spacing:.04em; color:var(--cg-th-fg); border-bottom:1px solid var(--cg-th-line); }
  .neg-modal tbody td { padding:7px 14px; border-top:1px solid #f2f4f6; color:#1a1d23; }
  .neg-modal .nm-badge { display:inline-block; padding:1px 7px; border-radius:9px; font-size:10.5px; font-weight:700; white-space:nowrap; }
  .neg-modal .nm-exact { background:#fdecea; color:#c0392b; }
  .neg-modal .nm-phrase { background:#fef5e7; color:#9c6500; }
  .neg-modal .nm-scope { color:#5b6472; font-size:12px; }
  .neg-modal .nm-new { background:#fff6e8; color:#b06000; border:1px solid #f0d8b8; border-radius:4px; padding:1px 6px; font-size:10px; font-weight:700; cursor:help; }
  .neg-modal footer { display:flex; align-items:center; gap:10px; padding:12px 18px; border-top:1px solid #eef0f3; }
  .neg-modal .nm-note { font-size:11.5px; color:#98a1b0; }
  .neg-modal .nm-dl { margin-left:auto; background:#f2fbf5; color:#12894f; border:1px solid #cfe6d8; border-radius:9px; padding:7px 12px; font-size:12.5px; font-weight:600; cursor:pointer; white-space:nowrap; }
  .neg-modal .nm-dl:hover { background:#e7f7ee; }
  .neg-modal .nm-load { padding:26px; text-align:center; color:#98a1b0; font-size:12.5px; }
  .cell-tip.neg-host { border-bottom:none; margin-left:5px; }
  /* ── NEGATE card (rowtools.js, owner 2026-08-21) — the other half of
     "pause & negate". It borrows the negatives modal's shell above so the two
     read as one family; only the line list is its own. ── */
  .ng-modal { width:min(760px, 94%); }
  .ng-why { padding:10px 18px; font-size:12px; line-height:1.5; color:#5b6572; background:#fffdf6; border-bottom:1px solid #f3e8d0; }
  .ng-line { display:flex; align-items:center; gap:10px; padding:8px 18px; border-top:1px solid #f2f4f6; font-size:12.5px; }
  .ng-line.ng-pause { background:#fdf6f5; border-top:0; }
  .ng-line.ng-off { background:#fafbfc; color:#98a1b0; }
  .ng-line.ng-head { background:#f7f9fb; border-top:1px solid #e6eaee; font-weight:600; color:#5b6572; }
  /* The negate card's backdrop is z-index 3000; the rules overlay is 1500,
     so opened from inside the card it was painted BEHIND it — invisible,
     and the first click closed the card instead (2026-08-21 review). It is
     lifted above whenever it is opened from a card. */
  #negOverlay { z-index:3200; }
  /* the "is this diagram still true?" light (rowtools.js diagTruthMount) */
  .dg-truth { display:block; margin:0 0 12px; padding:9px 13px; border-radius:8px; font-size:12px; line-height:1.55; }
  .dg-dot { display:inline-block; width:9px; height:9px; border-radius:50%; margin-right:8px; vertical-align:1px; }
  .dg-ok { background:#f1f9f4; border:1px solid #cfe6d8; color:#1e6b3d; }
  .dg-ok .dg-dot { background:#2ea45f; box-shadow:0 0 0 3px rgba(46,164,95,.16); }
  .dg-bad { background:#fff6e8; border:1px solid #f0d8b8; color:#7a4a10; }
  .dg-bad .dg-dot { background:#e08a1e; box-shadow:0 0 0 3px rgba(224,138,30,.16); }
  .dg-unknown { background:#f7f9fb; border:1px solid #e2e6ea; color:#6b7580; }
  .dg-unknown .dg-dot { background:#b6bfc9; }
  .dg-when { color:#7c8c83; font-size:11px; }
  .dg-list { margin:6px 0 4px 18px; padding:0; }
  .dg-list li { margin:2px 0; }
  .dg-note { display:block; margin-top:4px; font-size:11px; color:#8a7250; }
  .dg-truth-host:empty { display:none; }
  /* no second margin-left:auto — the ✕ owns that one, or the two split the
     free space and neither lands where it should */
  .ng-help { align-self:center; margin-left:14px; font-size:11.5px; color:#1a6ec0; cursor:pointer; white-space:nowrap; }
  .ng-help:hover { text-decoration:underline; }
  /* the examples table in the negative-keyword logic window */
  /* the examples are the point of this window — they get the whole width,
     not a third of it (the 3-column grid squeezed every cell to "dog socks f…") */
  .fl-sec.fl-sec-wide { grid-column:1 / -1; }
  .ng-ex { width:100%; border-collapse:collapse; font-size:13px; margin:6px 0 10px; table-layout:fixed; }
  .ng-ex th:first-child, .ng-ex td:first-child { width:22%; }
  .ng-ex th:nth-child(2), .ng-ex td:nth-child(2) { width:14%; }
  .ng-ex th { text-align:left; font-size:10.5px; text-transform:uppercase; letter-spacing:.04em; color:#667085;
              padding:7px 10px; border-bottom:1px solid #e6e8ec; background:#fafbfc; }
  .ng-ex td { padding:9px 10px; border-top:1px solid #f2f4f6; vertical-align:top; line-height:1.55; }
  .ng-ex td:nth-child(3) { color:#a33a2c; }
  .ng-ex td:nth-child(4) { color:#1e7e34; }
  .ng-ex tr.ng-ex-warn td { background:#fffaf2; }
  .ng-ex-sub { display:block; color:#98a1b0; font-size:11px; margin-top:2px; }
  .ng-ex-note { background:#fff6e8; border-left:3px solid #e0a060; padding:8px 11px; border-radius:0 4px 4px 0; }
  .ng-tick { width:16px; flex-shrink:0; text-align:center; }
  .ng-tick input { accent-color:#ff9900; cursor:pointer; }
  .ng-nm { flex:1; min-width:0; }
  .ng-sub { display:block; font-size:11px; color:#98a1b0; margin-top:1px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .ng-tag { font-size:10px; font-weight:700; padding:1px 7px; border-radius:4px; white-space:nowrap; flex-shrink:0; }
  .ng-tag[title] { cursor:help; border-bottom-style:dotted; }
  .ng-phrase { background:#eef4fd; color:#1a5fb4; border:1px solid #cfe0f7; }
  .ng-exact { background:#f1f0fb; color:#5b46b8; border:1px solid #ddd8f4; }
  .ng-asin { background:#fdf0f6; color:#b8338a; border:1px solid #f6d7e8; }
  .ng-note { font-size:11px; color:#98a1b0; flex-shrink:0; max-width:46%; text-align:right; }
  .ng-ok { color:#1e7e34; font-weight:700; }
  .ng-fail { color:#c0392b; font-weight:700; }
  .ng-skip { color:#98a1b0; font-weight:700; }
  .ng-run { color:#1a6ec0; font-weight:700; }
  .ng-go { background:#c0392b; color:#fff; border:0; border-radius:9px; padding:8px 15px; font-size:12.5px; font-weight:700; cursor:pointer; }
  .ng-go:disabled { background:#e6b3ad; cursor:default; }
  .ng-cancel { background:#fff; border:1px solid #d7dbe2; border-radius:9px; padding:8px 13px; font-size:12.5px; cursor:pointer; color:#5b6472; }
  .ng-stop { color:#c0392b; font-weight:600; cursor:pointer; text-decoration:underline; }
  /* the row's own grey Negate button, beside the rules' red Go */
  /* Pause on a row the rules want CUT, not stopped — an extra door, so it wears
     the warning colour rather than the blue of a suggested action. */
  /* THE PAUSE COLUMN (owner 2026-08-26). Filled red, because everything in this
     column IS a recommendation — the button only appears where the rules ask
     for the stop. Colour means "the rules said so" here as everywhere else.
     (.nb-btn-stop keeps its outline for the base class the pill is built on.) */
  .nb-btn.nb-btn-stop { color:#b45309; border-color:#e6c98f; }
  .nb-btn.nb-btn-stop:hover { background:#fff7e8; border-color:#b45309; }
  .nb-btn.nb-btn-stop.nb-btn-stop-on { background:#b42318; border-color:#b42318; color:#fff; }
  .nb-btn.nb-btn-stop.nb-btn-stop-on:hover { background:#8f1d13; border-color:#8f1d13; }
  .nb-btn.nb-btn-neg { background:#f4f6f8; border:1px solid #d5dbe1; color:#3c4650; font-weight:600; }
  /* icon-only chip (the ⛔ beside Pause): square padding, no word to pad around */
  .nb-btn.nb-btn-icon { padding:1px 5px; font-size:12px; line-height:1.25; }
  .nb-btn.nb-btn-neg:hover { background:#e9edf1; color:#1a1d23; }
  .nb-btn.nb-btn-off { opacity:.45; cursor:default; }
  /* the ⋯ popup's negate line — its own class, never the pause's: a PAUSE row
     must not look like it offers pause twice (tests/run.mjs pins this) */
  .nb-man-neg { display:block; margin-top:7px; font-size:11.5px; color:#c0392b; cursor:pointer; font-weight:600; }
  .nb-man-neg:hover { text-decoration:underline; }
  /* Bid needs another look: ≥25 clicks since its last change (or ever) and the
     ACOS since is still ≥30 / ≥40 / ≥50% (same palette as budget pacing).
     Green = same evidence but ACOS ≤15% and bid under Amazon's suggested high
     (raise it). Purple = bid above the suggested high, regardless of clicks. */
  /* ── Colour-rules panel ── */
  /* ── Topbar ⚙ Settings drop-down (replaces the old filter-bar Rules slot) ── */
  .topbar-right { display:flex; align-items:center; gap:12px; flex:0 0 auto; white-space:nowrap; }
  .set-wrap { position:relative; }
  .set-btn { padding:6px 14px; border:none; border-radius:16px; background:#ff9900; color:#fff;
             font-size:12.5px; font-weight:600; cursor:pointer; font-family:inherit; white-space:nowrap; }
  .set-btn:hover { background:#e68a00; }
  .set-menu { display:none; position:absolute; right:0; top:calc(100% + 8px); background:#fff; color:#2d3436;
              border-radius:10px; box-shadow:0 10px 32px rgba(0,0,0,.28); min-width:250px; z-index:80;
              overflow:hidden; text-align:left; }
  .set-menu.open { display:block; }
  .set-item { padding:11px 16px; font-size:13px; font-weight:600; cursor:pointer; }
  .set-item + .set-item { border-top:1px solid #edf2f7; }
  .set-item:hover { background:#f4f7fb; }
  .set-item span { display:block; font-size:11px; color:#8a93a0; font-weight:400; margin-top:2px; line-height:1.4; }

  /* ── Optimization-rules windows: a wide card holding the flowchart drawn by
     optflow.js (2026-08-09 — the hand-positioned SVG is gone; the engine
     computes the drawing from the measured boxes, so lines cannot overlap and
     every branch label sits pinned on its own line). ── */
  .rules-card.opt-card { max-width:1580px; }
  /* The reserved / waiting-list settings windows: text cards, no diagram. */
  .rules-card.opt-slim { max-width: 820px; }
  .opt-slim .ot-note { font-size: 12.5px; }
  /* the asterisk notes in the reserved text windows (auto / audiences / next) */
  .ot-notes { margin: 14px 2px 0; border-top: 1px solid #edf2f7; padding-top: 10px; }
  .ot-note { font-size: 11.5px; color: #6b7684; line-height: 1.6; margin-bottom: 7px; }
  .ot-note b { color: #4a5568; }

  /* The flowchart engine's styles moved to Shared Data/shell.css with
     optflow.js itself (2026-08-14) — the Market page uses the same engine,
     and one look in two stylesheets is exactly the drift Rule 6 forbids. */
  /* the band tables: a compact GRID, not a <table> — the shared house-table
     default would stretch a real table to the full card width */
  .fl-grid { display:inline-grid; grid-template-columns:repeat(3, auto); gap:4px 12px; align-items:center; margin-top:4px; }
  .fl-gh { font-size:11px; font-weight:700; color:#4a5568; text-align:center; white-space:nowrap; }
  .fl-grid input { width:92px; }
  /* the Save row stays reachable while the tall card scrolls */
  .opt-card .rules-foot { position:sticky; bottom:-20px; background:#fff; margin:14px -4px 0;
                          padding:10px 4px 12px; border-top:1px solid #edf2f7; z-index:5; }
  @media (max-width: 1100px) { .fl-secs { grid-template-columns:1fr; } }
  .rules-overlay { display:none; position:fixed; inset:0; background:rgba(20,26,40,0.45); z-index:1500; align-items:flex-start; justify-content:center; padding:60px 16px 16px; }
  .rules-card { background:#fff; border-radius:12px; box-shadow:0 12px 40px rgba(0,0,0,.25); max-width:760px; width:100%; padding:20px 24px; font-size:13.5px; max-height:calc(100vh - 90px); overflow:auto; }
  .rules-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:6px; }
  .rules-head h3 { font-size:17px; }
  .rules-x { font-size:22px; color:#8a93a0; cursor:pointer; line-height:1; } .rules-x:hover { color:#e74c3c; }
  .rules-sec { border-top:1px solid #edf2f7; padding:12px 0 4px; }
  .rules-sec h4 { font-size:13px; text-transform:uppercase; letter-spacing:.4px; color:#4a5568; margin-bottom:8px; }
  .rules-ctx { font-weight:400; text-transform:none; letter-spacing:normal; color:#8a93a0; font-size:12px; }
  .rules-card input[type=number] { width:58px; padding:3px 6px; border:1px solid #cbd5e0; border-radius:5px; font-size:13px; text-align:center; font-weight:600; color:#1a6ec0; }
  .rules-def { display:flex; align-items:center; gap:10px; padding:4px 0; color:#2d3436; }
  .rules-def > span:last-child { white-space:nowrap; color:#4a5568; }
  .rules-hint { font-size:12px; color:#8a93a0; margin:2px 0 10px; line-height:1.5; }
  .rules-rule { display:grid; grid-template-columns:78px 1fr; align-items:center; gap:12px; padding:4px 0; }
  .rules-card .chip { display:inline-block; min-width:60px; text-align:center; }
  .rules-foot { display:flex; gap:10px; margin-top:14px; flex-wrap:wrap; }
  .rules-btn { padding:7px 16px; border:none; border-radius:6px; background:#ff9900; color:#fff; font-size:13px; font-weight:600; cursor:pointer; }
  .rules-btn:hover { background:#e68a00; }
  .rules-btn.secondary { background:#fff; color:#4a5568; border:1px solid #cbd5e0; }
  .rules-btn.secondary:hover { border-color:#ff9900; color:#ff9900; }
  .rules-btn:disabled { background:#e6ebf2; color:#8a93a0; cursor:not-allowed; }
  .rules-reload { margin-left:12px; font-size:12px; color:#4a5568; }
  .rules-reload a { color:#1a6ec0; font-weight:600; text-decoration:underline; cursor:pointer; }
  .rules-note { margin-top:10px; font-size:12px; color:#8a93a0; line-height:1.5; }

  /* ── VERDICT TINTS (owner 2026-08-09): a cell wears the rules' OWN verdict —
     colour = the action, shade = the branch that chose it. Written by
     PPC_VERDICTS / BUD_VERDICTS (tools.js), the same pass that fills the
     attention panel, so cell and pill can never disagree.
     Round-2 polish: a verdict washes the WHOLE CELL (square, edge to edge) so
     LOGIC colours are instantly distinguishable from the small rounded INFO
     pills (ACOS etc.); the value keeps a strong text colour. ── */
  .cell-tip.vt-raise        { color:#1e7d43; font-weight:600; }
  .cell-tip.vt-raise-noimp  { color:#256e63; font-weight:600; }   /* raise · no impressions — teal-green shade of the raise family */
  .cell-tip.vt-lower        { color:#7a4300; font-weight:600; }
  .cell-tip.vt-lower-thin   { color:#96621a; font-weight:600; }
  /* over the MAX BID — a cut for a reason that has nothing to do with how
     the keyword is performing, so it is the amber family (it IS a cut) but
     the coolest, most distinct member of it: a ceiling, not a verdict. */
  .cell-tip.vt-lower-overmax { color:#8a5a00; font-weight:700; }
  .cell-tip.vt-pause-150    { color:#8f1414; font-weight:700; }
  .cell-tip.vt-pause-nosale { color:#8f1414; font-weight:600; }
  .cell-tip.vt-pause-trial  { color:#8f1d1d; font-weight:600; }
  /* the two trial endings and the never-clicked pause are three rows on the
     panel, so three shades here — the cell wears its own row (2026-09-07) */
  .cell-tip.vt-pause-noneg  { color:#8f1d1d; font-weight:600; }
  .cell-tip.vt-pause-dead   { color:#7a1f1f; font-weight:600; }
  .cell-tip.vt-raise-retry  { color:#2b6e4f; font-weight:600; }
  .cell-tip.vt-check        { color:#8a6100; font-weight:600; }
  .cell-tip.vt-wait         { color:#5b6572; }
  /* cut until Amazon stopped showing it — a state, not a job */
  .cell-tip.vt-quiet        { color:#4a5560; }
  td:has(> .cell-tip.vt-raise)        { background:#dff3e7; }
  td:has(> .cell-tip.vt-raise-noimp)  { background:#dcf0ec; }
  td:has(> .cell-tip.vt-lower)        { background:#ffe3b8; }
  td:has(> .cell-tip.vt-lower-thin)   { background:#fff3da; }
  td:has(> .cell-tip.vt-lower-overmax){ background:#ffd9a0; box-shadow:inset 3px 0 0 #b3701a; }
  td:has(> .cell-tip.vt-pause-150)    { background:#f3b6b6; }
  td:has(> .cell-tip.vt-pause-nosale) { background:#f8d2d2; }
  td:has(> .cell-tip.vt-pause-trial)  { background:#fce7e7; }
  td:has(> .cell-tip.vt-pause-noneg)  { background:#fbdada; box-shadow:inset 0 0 0 1px #d98a8a; }
  td:has(> .cell-tip.vt-pause-dead)   { background:#f5dede; box-shadow:inset 3px 0 0 #b04a4a; }
  td:has(> .cell-tip.vt-raise-retry)  { background:#e2f1e8; box-shadow:inset 3px 0 0 #2b6e4f; }
  td:has(> .cell-tip.vt-check)        { background:#faeec9; }
  td:has(> .cell-tip.vt-wait)         { background:#edf1f6; }
  td:has(> .cell-tip.vt-quiet)        { background:#e6eaee; }
  /* the chip form of the same colours — the Colours dropdown, the Colour-rules
     window's examples, and the campaign view's roll-up chips */
  .vt-chip { display:inline-block; padding:2px 8px; border-radius:4px; font-size:10.5px; font-weight:600; white-space:nowrap; }
  /* the legend chips FILTER the table (owner 2026-08-10, one combined control) */
  /* paused — a state, not a verdict: quiet grey */
  .vt-chip-paused { background:#e2e6ea; color:#5b6472; }
  #vtLegCard [data-vt] { cursor:pointer; }
  #vtLegCard [data-vt]:hover { filter:brightness(.95); }
  #vtLegCard .vt-on { outline:2px solid #1a3f66; outline-offset:1px; }
  .vt-chip-none { background:#f1f4f8; color:#8a93a0; }
  .vt-chip-else { background:#fff; border:1px dashed #b7c0cc; color:#5b6572; }
  #vtLegBtn .vt-chip { pointer-events:none; }         /* clicks land on the button (opens the card) */
  .vt-x { margin-left:6px; cursor:pointer; font-weight:700; color:#8a93a0; }
  .vt-x:hover { color:#c62828; }
  .vt-chip-raise, .chip.vt-raise           { background:#c8ecd4; color:#1e7d43; }
  .vt-chip-raise-noimp                     { background:#cbe8e2; color:#256e63; }
  /* ONE LAST TRY — a raise, so green, with an edge-mark: a re-test, not a
     verdict on its ACOS (own row since 2026-09-07) */
  .vt-chip-raise-retry                     { background:#dcefe4; color:#2b6e4f; box-shadow:inset 3px 0 0 #2b6e4f; }
  .vt-chip-lower, .chip.vt-lower           { background:#ffce8a; color:#7a4300; }
  .vt-chip-lower-thin                      { background:#ffedd0; color:#96621a; }
  .vt-chip-pause, .chip.vt-pause-150       { background:#c62828; color:#fff; }
  .vt-chip-pause-nosale                    { background:#e57373; color:#4c0f0f; }
  .vt-chip-pause-trial                     { background:#f6cfcf; color:#8f1d1d; }
  /* The trial's other ending. Deliberately NOT in the red family: the three
     reds above all end in a negative, and this one is the door left open —
     the spending stops, the word is not blocked. Amber says "stopped, not
     condemned" without reading as one of the three. */
  /* the diagram draws PAUSE — DON'T NEGATE as a RED box (kind 'bad'): a
     pause is a stop, whatever happens to the negative. It was orange here
     until 2026-09-05, which made it read as a bid cut. */
  .vt-chip-pause-noneg                     { background:#fbdada; color:#8f1d1d; border:1px dashed #d98a8a; }
  /* shown past the dead line, never clicked — a negate that cost $0; the red
     family with an edge-mark, because no money was ever spent on it */
  .vt-chip-pause-dead                      { background:#f5dede; color:#7a1f1f; box-shadow:inset 3px 0 0 #b04a4a; }
  .vt-chip-check, .chip.vt-check           { background:#fbeec3; color:#8a6100; }
  /* the same yellow for a check that came from "no sale on this bid" — one
     shade lighter, so the two check rows read as two */
  .vt-chip-check-nosale                    { background:#fdf5da; color:#8a6100; }
  .vt-chip-wait-hold                       { background:#e9eef5; color:#5b6572; border:1px dashed #b9c2cc; }
  .vt-chip-none-thin                       { background:#f1f4f8; color:#8a93a0; border:1px dashed #c5ccd6; }
  .vt-chip-none-held                       { background:#eef4ee; color:#6b7f6f; }
  /* the same lower-the-bid family, one shade deeper: these rows ARE still a
     cut — the chip only isolates the ones already cut before. */
  /* the diagram draws the repeat offender as a YELLOW "check" box (THE CUT
     STILL HAPPENS — AND YOU ARE OFFERED A PAUSE), and the header pill wore
     yellow too; this chip was tan until 2026-09-05. Yellow with the orange
     left edge: a cut, that also asks you to look. */
  .vt-chip-lower-repeat, .chip.vt-lower-repeat { background:#fbeec3; color:#8a6100; box-shadow:inset 3px 0 0 #ffce8a; }
  /* the ceiling cut — same family, but carrying the left edge-mark the cell
     wears, so chip and cell are recognisably the same thing */
  .vt-chip-lower-overmax, .chip.vt-lower-overmax { background:#ffd9a0; color:#8a5a00; box-shadow:inset 3px 0 0 #b3701a; }
  /* cut until Amazon stopped showing it — a state, not a job, so it wears a
     quiet slate rather than an action colour */
  .vt-chip-quiet, .chip.vt-quiet           { background:#dfe4ea; color:#4a5560; border:1px dashed #b9c2cc; }
  .vt-chip-wait, .chip.vt-wait             { background:#e9eef5; color:#5b6572; }
  /* the windowed keyword table runs on a FIXED layout while pinned (no
     column jitter as the drawn slice changes); anything wider than its
     pinned column shows an ellipsis instead of stretching the column */
  .kw-virt td { overflow:hidden; }
  .kw-virt td.dim-cell { text-overflow:ellipsis; white-space:nowrap; }
  /* the Columns menu's preset row (Compact view / All columns) */
  .col-presets { display:flex; gap:6px; padding:4px 10px 8px; border-bottom:1px solid #eef2f7; margin-bottom:6px; }
  .col-presets button { flex:1; padding:4px 8px; font-size:11.5px; font-weight:600; background:#fff;
                        color:#4a5568; border:1px solid #cbd5e0; border-radius:5px; cursor:pointer; }
  .col-presets button:hover { border-color:#ff9900; color:#ff9900; }
  /* the campaign view's per-campaign verdict roll-up */
  .vt-camp { margin-left:8px; display:inline-flex; gap:4px; vertical-align:middle; }
  .vt-camp .vt-chip { font-size:10px; padding:1px 6px; }
  /* the seasonal tick. Marked = solid and always visible; unmarked = a faint
     "seasonal?" that only shows while the row is hovered, so a table of 300
     campaigns gains no clutter for a tick almost none of them wear. */
  .season-chip { font-size:10px; padding:1px 6px; border-radius:9px; cursor:pointer; white-space:nowrap;
                 border:1px dashed #cbd5e0; color:#8a93a0; background:#fff; opacity:0; transition:opacity .12s; }
  tr:hover .season-chip { opacity:1; }
  .season-chip:hover { border-color:#1a6ec0; color:#1a6ec0; }
  /* the ❄ that says a campaign IS seasonal — left of the name, where the
     column's ellipsis can never reach it */
  .season-mark { cursor:pointer; color:#1a6ec0; font-size:12px; }
  .season-mark:hover { color:#0d4f8f; }
  /* ── SPECIAL KEYWORDS (owner 2026-09-03) ──────────────────────────────────
     The same split as the ❄ above, and for the same reason: the STATE is a
     mark left of the name where the column's ellipsis can never reach it, the
     OFFER is a faint chip after the name that only appears on hover.
     🎯 = this keyword's own mark · 🚀 = it comes from its model's launch mark.
     .sp-idle = marked, but both special boxes are still blank, so nothing is
     actually judged differently yet — it is greyed rather than pretending. */
  /* ONE slot before the name holding the MARK or the OFFER — the pin star's
     rule, and for the pin star's reason (owner 2026-09-04: the offer used to be
     a chip AFTER the name and both name columns ellipsise, so on the Models
     view it was clipped off the row entirely and could not be found).
     `visibility`, never `display`: the slot keeps its width whether the offer
     is showing or not, so no name ever shifts under the cursor. */
  .sp-mark { cursor:pointer; font-size:12px; line-height:1; }
  .sp-mark:hover { filter:brightness(1.15); }
  tr .sp-mark { visibility:hidden; filter:grayscale(1); opacity:.4; }        /* the OFFER */
  tr:hover .sp-mark { visibility:visible; }
  tr .sp-mark.on { visibility:visible; filter:none; opacity:1; }             /* the MARK */
  /* marked while both boxes are empty: still clearly ON, but faded, and the
     hover says nothing is judged differently yet */
  tr .sp-mark.on.sp-idle { filter:grayscale(.7); opacity:.7; }
  /* the Colours dropdown card, next to Download Excel */
  /* ── ONE LINE PER COLOUR (owner 2026-08-23: "looks like a mess"). It used to
     be centred chips wrapping inside a 440px box: each chip, its hint and its
     figure stacked in a column, so a dozen colours became a staggered tower
     nobody could scan. Now it reads like a list — chip, what it means, what it
     is worth — three columns that line up down the card, and the whole ROW is
     the click target rather than the chip alone. ── */
  .vt-leg-card { position:absolute; right:0; top:calc(100% + 6px); z-index:600; background:#fff;
                 border:1px solid #dbe3ee; border-radius:10px; box-shadow:0 8px 28px rgba(20,30,50,.18);
                 padding:14px 16px; width:680px; max-height:78vh; overflow-y:auto;
                 text-align:left; font-weight:400; }
  .vt-leg-h { font-size:13px; font-weight:700; color:#1a3f66; margin-bottom:10px; }
  .vt-leg-sub { font-weight:400; color:#8a93a0; font-size:11.5px; }
  .vt-leg-clear { float:right; font-size:11.5px; font-weight:600; color:#1a6ec0; cursor:pointer; }
  .vt-leg-clear:hover { text-decoration:underline; }
  /* sectioned rows: a small grey group label, then roomy chips (owner
     2026-08-10 — "tiny packed colour squares, not separated to sections") */
  .vt-leg-g { display:flex; align-items:flex-start; gap:10px; padding:6px 0; border-top:1px solid #f1f4f8; }
  .vt-leg-gl { flex:0 0 46px; padding-top:7px; font-size:10px; font-weight:700; letter-spacing:.6px; text-transform:uppercase; color:#a3acb9; }
  .vt-leg-gc { display:flex; flex-direction:column; gap:2px; flex:1 1 auto; min-width:0; }
  .vt-leg-it { display:grid; grid-template-columns:184px 1fr auto; align-items:center; gap:12px;
               padding:4px 6px; border-radius:6px; cursor:pointer; }
  .vt-leg-it:hover { background:#f5f9fe; }
  .vt-leg-it.vt-on-row { background:#eaf4fd; box-shadow:inset 2px 0 0 #1a6ec0; }
  .vt-hint { font-size:11px; color:#8a93a0; line-height:1.3; white-space:normal; min-width:0; }
  .vt-spend { font-size:11px; font-weight:700; color:#4a5568; white-space:nowrap; text-align:right; }
  /* while the verdicts are still loading the figures are meaningless — dim
     them rather than print a column of dashes that reads as an empty account */
  .vt-leg-loading .vt-spend { opacity:.35; }
  /* the whole-list Update-all bar at the top of an opened suggestion list */
  .warn-bulk { display:flex; align-items:center; gap:10px; padding:6px 2px 2px; }
  .vt-leg-gc .vt-chip { font-size:11.5px; padding:4px 10px; border-radius:6px; justify-self:start; }
  .vt-leg-foot { font-size:11px; color:#8a93a0; border-top:1px solid #eef2f7; padding-top:8px; margin-top:6px; }
  /* Soft flag (striped): the gold-standard window is OK, but the newest
     critical clicks cross a bad tier — take a second look. */
  /* (the old bid tiers — bid-sig-30/40/50, the striped bid-soft-*, the purple
     bid-over-rec — were retired 2026-08-09 with the verdict tints above; the
     suggested-high comparison lives in the Bid hover now) */
  /* a labelled pill group on the topbar strip — the label opens its diagram. */
  /* a group = its label + its pills, one unbreakable unit; groups are parted
     by a thin line, never by a line break */
  .warn-grp { display:inline-flex; align-items:center; gap:6px; flex:0 0 auto; }
  .warn-grp + .warn-grp { border-left:1px solid #dfe3e8; padding-left:12px; margin-left:6px; }
  .warn-grp-lab { font-size:11px; font-weight:700; color:#5b6572; cursor:pointer; white-space:nowrap; margin-right:2px; }
  .warn-grp-lab:hover { color:#2563eb; text-decoration:underline; }
  .chg-info { cursor:help; border-bottom:1px dotted #b0b8c0; }
  /* ── One keyword, several products (ui.js kwModelCell, owner 2026-08-21) ──
     The Model cell of a keyword line that covers more than one product. The
     PART variant is the marked case: a Model/Brand filter matched only some of
     them, yet the line still shows all of them (one bid, one verdict), so it
     is tinted the same orange the page uses for "read this before you act". */
  .kw-multi { cursor:help; border-bottom:1px dotted #b0b8c0; color:#4a5462; }
  .kw-multi-part { color:#b06000; border-bottom-color:#e0a060; font-weight:600; background:#fff6e8; padding:0 3px; border-radius:3px; }
  .cnt-whole { color:#b06000; background:#fff6e8; border:1px solid #f0d8b8; border-radius:3px; padding:0 5px; margin-left:4px; cursor:help; font-weight:600; }

  /* ── Structured hover cards (Budget / Bid / Rec-bid cells) ──
     Replaces the browser's plain title= tooltip with a small dark panel of
     label→value rows. Shown by CSS :hover; positioned (fixed) by a delegated
     mouseover listener so it survives every table re-render. */
  /* Tips open on CLICK, not hover (RULEBOOK Rule 6) — cursor:pointer, and the
     card is shown by JS, never a CSS :hover rule. */
  .cell-tip { position:relative; cursor:pointer; border-bottom:1px dotted #b0b8c0; }
  /* body > .tip-box: shown cards are reparented to <body> (top stacking layer)
     so the sticky pinned bars (filters z30, topbar z50) can never cut them. */
  .cell-tip .tip-box, .head-tip .tip-box, body > .tip-box {
    display:none; position:fixed; z-index:1000; pointer-events:none;
    background:#232f3e; color:#e8eaed; font-size:11px; line-height:1.6; font-weight:400;
    padding:7px 11px; border-radius:6px; white-space:nowrap; text-align:left;
    box-shadow:0 4px 14px rgba(0,0,0,0.28);
  }
  /* Header variant: same card, but the host is a <th> (no dotted underline) and
     the body is a readable wrapped paragraph instead of nowrap rows. */
  .head-tip { cursor:pointer; }
  .tip-box .tip-text { display:block; white-space:normal; max-width:300px; font-weight:400; color:#dfe6ec; line-height:1.5; text-transform:none; letter-spacing:normal; text-align:left; }
  .tip-box .tip-head { display:block; color:#9aa7b2; font-size:10px; font-weight:600; text-transform:uppercase; letter-spacing:0.4px; margin-bottom:2px; }
  .tip-box .tip-row { display:flex; justify-content:space-between; gap:18px; }
  .tip-box .tip-row .l { color:#b8c4cf; }
  .tip-box .pct-ok { color:#7bd88f; } .tip-box .pct-hot { color:#ff8a8a; } .tip-box .pct-cold { color:#8ec4f8; }
  .tip-box .muted { color:#8b98a5; }
  /* The placement card (placement.js): the row of the figure that was clicked
     is a full-width band — bold text alone was not clear enough. In the app's
     own blue (#2563eb, the active chip/nav colour), soft on the dark card: the
     first version was solid amber and "too strong in the eye" (owner). The
     negative margins reach the card's 11px side padding so the band spans it. */
  .tip-box .tip-row.pl-mine { background:rgba(37,99,235,0.30); color:#fff; font-weight:700; margin:1px -11px; padding:1px 9px 1px 11px; border-left:2px solid #60a5fa; border-radius:3px; }
  .tip-box .tip-row.pl-mine .l { color:#fff; }
  /* The card's BOTTOM LINE — what the rules want done (owner 2026-08-20).
     It used to be a .tip-row: label pinned left, sentence pinned right, the
     whole thing on ONE nowrap line, so a 20-word verdict stretched the card
     across half the screen. It is now a block of its own — small label line,
     then the sentence in BOLD, wrapping inside a fixed width (~2 lines). */
  .tip-box .tip-verdict { display:block; max-width:340px; white-space:normal; font-weight:700;
                          line-height:1.45; margin-top:5px; color:#f2f6fa; }
  .tip-box .tip-verdict.muted { font-weight:600; color:#a4b2c0; }
  .tip-box .tip-vlab { display:block; color:#9aa7b2; font-size:10px; font-weight:600;
                       text-transform:uppercase; letter-spacing:0.4px; }
  /* a note inside a card that is a whole sentence: same wrapping treatment,
     so no explanation can stretch a card across the screen (House §11) */
  .tip-box .tip-note { display:block; max-width:340px; white-space:normal; line-height:1.45; margin-top:3px; }

  /* ── Column info note popup ── */
  /* colours from the shell's house table tokens (Rule 6 §5a) */
  .col-note-btn { display: inline-block; margin-left: 2px; width: 12px; height: 12px; line-height: 12px; font-size: 8px; font-weight: 700; text-align: center; vertical-align: middle; border-radius: 50%; cursor: pointer; font-style: italic; user-select: none; }

  @media (max-width: 900px) {
    .charts-grid { grid-template-columns: minmax(0,1fr); }
    .sidebar { width: 60px; } .sidebar .logo span { display: none; } .sidebar .logo { padding: 12px 10px; justify-content: center; }
    .sidebar nav a span:not(.icon) { display: none; }
    .main { margin-left: 60px; }
  }


  /* ── Frozen-column separators (2026-08-04): the table's collapsed borders do
     NOT travel with position:sticky cells, so the frozen columns' lines
     vanished the moment the table scrolled right. Inset shadows are painted by
     the cell itself and scroll with it — right edge + row line. ── */
  #dataTable th:nth-child(-n+2), #dataTable td:nth-child(-n+2) { box-shadow: inset -1px 0 0 #dfe4ea, inset 0 -1px 0 #edf2f7; }
  /* ── Entity on/off state (2026-08-04): chips + light-red tint ── */
  .state-chip { font-size: 9px; font-weight: 700; letter-spacing: .4px; border-radius: 4px; padding: 1px 5px; margin-left: 6px; vertical-align: 1px; white-space: nowrap; }
  .chip-paused { background: #fdeeec; color: #c0392b; border: 1px solid #f2c5bd; }
  .chip-archived { background: #f1f3f5; color: #6c757d; border: 1px solid #dee2e6; }
  .chip-enabled { background: #eef7f0; color: #1e7e34; border: 1px solid #cde8d4; }
  /* one keyword, several products (ui.js kwPartChipHtml). QUIET when you can
     see all of them, ORANGE when a filter hides some and the line therefore
     counts more than the cards at the top of the page. */
  .chip-multi { background: #f4f6f8; color: #78828f; border: 1px solid #e2e6ea; cursor: help; font-weight: 600; }
  .chip-part { background: #fff6e8; color: #b06000; border: 1px solid #f0d8b8; cursor: help; }
  tbody tr.row-off td { background: #fdf3f1; }
  tbody tr.row-off:hover td { background: #fbe9e6; }
  /* The frozen left cells set their own background by ID selector, which
     outranks the tint above — repeat it at ID strength so paused rows stay
     tinted across the frozen edge too. */
  #dataTable tbody tr.row-off td:nth-child(-n+2) { background: #fdf3f1; }
  #dataTable tbody tr.row-off:hover td:nth-child(-n+2) { background: #fbe9e6; }
  /* A SPECIAL keyword's row wore a faint violet (.row-sp) from 2026-09-03 to
     2026-09-07. Removed at the owners' word: the 🎯 / 🚀 mark on the row is
     the sign, and a background repeating it was noise. Nothing writes the
     class any more; do not bring it back as a "nice touch". */
  .silent-head td { background: #fafbfc; color: #4a5568; font-size: 12px; font-weight: 600; padding: 9px 12px; cursor: pointer; border-top: 2px solid #e2e8f0; }

  /* ══════════════════════════════════════════════════════════════════════
     THE "NEW BID" COLUMN (owner 2026-08-12) — the attention panel's
     suggestion, sitting next to the Bid it replaces, with its own Update
     and Done buttons. Deliberately quiet: the number is the loud part, the
     buttons are small outlines so a 250-row table doesn't turn into a wall
     of blue. Handled rows fade IN PLACE (.row-handled) — the To do / Done
     filter on the count line is what moves them out of the way, because a
     table that re-orders itself under the cursor is worse than one that
     stays still.
     ══════════════════════════════════════════════════════════════════════ */
  .nb-wrap { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
  /* THE PAUSE PILL STARTS ON THE SAME LINE IN EVERY ROW (owner 2026-08-26).
     The cell is a metric column, so the shell centres its contents — which
     meant a row WITH the ⛔ pushed its Pause left and a row without it (an SD
     target, which Amazon gives no negatives) sat further right, and the column
     read as ragged. This is a column of BUTTONS, not figures: the house
     centring is for numbers, and nothing here is one.
     Left is where the eye already is, coming from the keyword. */
  html[data-shell="v2"] #dataTable tbody td[data-col="pausekw"],
  html[data-shell="v2"] #dataTable tfoot td[data-col="pausekw"] { text-align: left; }
  #dataTable td[data-col="pausekw"] .nb-wrap { justify-content: flex-start; }
  .nb-val { font-weight: 700; font-size: 12px; padding: 1px 4px; border-radius: 4px; cursor: help; }
  /* a figure you may overrule: click it and it becomes the box below
     (owner 2026-08-20 — the panel at the top has always allowed this) */
  .nb-val.nb-edit { cursor: pointer; border-bottom: 1px dashed currentColor; }
  /* while the box is open the pill steps out of the way, so the input
     fits the same ~112px column the figure did */
  .nb-val.nb-editing { background: none; padding: 0; border-bottom: 0; }
  .nb-in { width: 46px; font: inherit; font-size: 11.5px; font-weight: 700; text-align: center;
           padding: 1px 2px; border: 1px solid #2e86de; border-radius: 4px; background: #fff; color: #1f2d3d; }
  .nb-in::-webkit-outer-spin-button, .nb-in::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
  .nb-in { -moz-appearance: textfield; appearance: textfield; }
  .nb-dir { font-size: 8px; margin-right: 2px; vertical-align: 1px; }
  .nb-up   { background: #c8ecd4; color: #1e7d43; }   /* same colours as the Bid tint / the colour chips */
  .nb-dn   { background: #ffce8a; color: #7a4300; }
  .nb-stop { background: #c62828; color: #fff; }
  .nb-chk  { background: #ffe9a8; color: #7a5c00; }
  .nb-btn { padding: 1px 6px; font: inherit; font-size: 10.5px; font-weight: 700; color: #2e86de;
            background: #fff; border: 1px solid #b9d4f0; border-radius: 999px; cursor: pointer; }
  .nb-btn:hover { background: #f0f7ff; border-color: #2e86de; }
  .nb-btn:disabled { opacity: .55; cursor: default; }
  .nb-btn-done { color: #5b6572; border-color: #d7dee8; }
  /* ── YOUR OWN CHANGE (owner 2026-08-20): grey, never coloured — colour is
     reserved for what the RULES asked for, so the two can never be confused. */
  /* a standing caveat in the header — quiet, hoverable, never a banner */
  .sub-caveat { color: #b08900; cursor: help; border-bottom: 1px dotted #d9c07a; }
  /* "N already paused, still waiting for their negative" — the Pause group's
     own footnote, so a count that includes stopped keywords says so. */
  .vt-leg-half { display:block; margin-top:5px; font-size:11px; line-height:1.4; color:#8a5a1a; cursor:pointer; }
  .vt-leg-half:hover { text-decoration: underline; }
  .nb-man { color: #98a1b0; font-size: 11.5px; border-bottom: 1px dashed #c9d0d9; cursor: pointer; }
  .nb-man:hover { color: #2e86de; border-bottom-color: #2e86de; }
  .nb-man-pop { position: fixed; z-index: 1200; background: #fff; border: 1px solid #dbe3ee; border-radius: 10px;
                box-shadow: 0 8px 24px rgba(20,30,50,.14); padding: 12px 13px; width: 252px; text-align: left; }
  .nb-man-h { font-size: 10px; text-transform: uppercase; letter-spacing: .5px; color: #98a1b0; margin-bottom: 8px; }
  .nb-man-said { background: #f7f9fc; border-radius: 6px; padding: 6px 8px; font-size: 11px; line-height: 1.45; color: #5b6572; margin-bottom: 9px; }
  .nb-man-r { display: flex; align-items: center; gap: 6px; }
  .nb-man-sym { color: #7a838f; font-size: 12px; font-weight: 700; }
  .nb-man-pop input { width: 70px; font: inherit; font-size: 12px; font-weight: 700; text-align: center;
                      padding: 3px; border: 1px solid #2e86de; border-radius: 5px; }
  .nb-man-btn { padding: 2px 11px; font: inherit; font-size: 11px; font-weight: 700; color: #2e86de;
                background: #fff; border: 1px solid #b9d4f0; border-radius: 999px; cursor: pointer; }
  .nb-man-btn:hover { background: #f0f7ff; }
  .nb-man-pause { display: block; margin-top: 10px; padding-top: 9px; border-top: 1px solid #f0f3f7;
                  color: #b02020; font-size: 12px; font-weight: 600; cursor: pointer; }
  .nb-man-pause:hover { text-decoration: underline; }
  .nb-man-why { color: #98a1b0; font-size: 11px; line-height: 1.45; margin-top: 9px; border-top: 1px solid #f0f3f7; padding-top: 8px; }
  .nb-btn-done:hover { background: #f4f6f9; border-color: #8a93a0; }
  /* the stale-snapshot stand-in: the number still reads, the push is withdrawn */
  .nb-stale { color: #b42318; font-weight: 700; cursor: help; }
  /* handled — grey, quiet, and reversible */
  .nb-done { color: #8a93a0; font-weight: 600; font-size: 12px; cursor: help; }
  .nb-undo { margin-left: 5px; color: #1a6ec0; cursor: pointer; font-weight: 700; }
  .nb-undo:hover { text-decoration: underline; }
  .nb-gone { color: #7a271a; font-size: 11px; font-weight: 600; cursor: help; }
  .nb-done { white-space: nowrap; }
  /* the whole row fades once its keyword is handled — the eye skips it, but
     it never moves, so nothing jumps while you work down the list */
  tbody tr.row-handled td { opacity: .42; }
  tbody tr.row-handled:hover td { opacity: .8; }
  #dataTable tbody tr.row-handled td:nth-child(-n+2) { opacity: .42; }
  #dataTable tbody tr.row-handled:hover td:nth-child(-n+2) { opacity: .8; }

  /* ── The To do / Done filter on the count line, under the table title.
     A SECOND filter that stacks on the colour one: the colour says WHICH
     job, this says WHETHER IT IS DONE. Counts are always counts within the
     colour currently picked. ── */
  .df-wrap { margin-left: 10px; padding-left: 10px; border-left: 1px solid #dfe4ea; cursor: help; }
  .df-chip { display: inline-block; margin-right: 5px; padding: 1px 8px; border-radius: 999px;
             font-size: 11.5px; font-weight: 600; color: #1a6ec0; background: #eef5fd;
             border: 1px solid #d3e4f7; cursor: pointer; }
  .df-chip:hover { background: #ddecfb; }
  .df-chip.df-on { background: #1a6ec0; border-color: #1a6ec0; color: #fff; }
  .df-chip.df-empty { color: #8a93a0; background: #f4f6f9; border-color: #e4e9f0; }
  .df-clear { font-size: 11.5px; font-weight: 600; color: #1e7d43; }

  /* ── The summary pills wear the TABLE'S OWN verdict colours (owner
     2026-08-12: "the top is a bit confusing" next to the bottom). Same
     action, same colour, wherever you are on the page — green raise ·
     orange lower · red pause · yellow a human checks — and the budget
     pills follow the Budget cell's tints for the same reason. The two
     lists with NO counterpart in the table (words for the listing,
     reactivate) stay blue on purpose, so a colour never means two things.
     Values copied from the .vt-chip-* set above; change them together. ── */
  .warn-pill.warn-vt-raise { background: #c8ecd4; color: #1e7d43; }
  .warn-pill.warn-vt-lower { background: #ffce8a; color: #7a4300; }
  .warn-pill.warn-vt-pause { background: #c62828; color: #fff; }
  .warn-pill.warn-vt-check { background: #ffe9a8; color: #7a5c00; }
  /* the opened lines below a pill — darker, readable on white */
  .warn-li.warn-vt-raise { color: #14532d; }
  .warn-li.warn-vt-lower { color: #7a4300; }
  .warn-li.warn-vt-pause { color: #7a271a; }
  .warn-li.warn-vt-check { color: #6b4a05; }
  /* the count line's "· N keywords / targets" — the figure the pills count */
  .cnt-kw { color: #1a6ec0; cursor: pointer; }
  /* ── PINS (rowtools.js): the ☆/★, the pinned tint, the ★ chip ── */
  .pin-star { color: #c9cfd8; cursor: pointer; font-size: 12px; }
  .pin-star:hover { color: #e6a817; }
  .pin-star.on { color: #e6a817; }
  tr .pin-star { visibility: hidden; }
  tr:hover .pin-star, tr .pin-star.on { visibility: visible; }
  tr.row-pinned td { background: #fffaf0; }
  #dataTable tbody tr.row-pinned td:nth-child(-n+2) { background: #fffaf0; }
  .pin-stub-note { color: #98a1b0; font-size: 11px; font-style: italic; }
  .pin-chip { margin-left: 10px; padding: 1px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600;
              color: #8a6100; background: #fff3d6; border: 1px solid #f0dfae; cursor: pointer; }
  .pin-chip.on { background: #e6a817; border-color: #e6a817; color: #fff; }
  /* the keyword PAUSED chip answers on click */
  .state-chip.chip-click { cursor: pointer; }
  .state-chip.chip-click:hover { filter: brightness(0.93); }
  /* the blank Action cell's quiet dash — the hover carries its reason */
  .nb-blank { color: #c6ccd4; cursor: help; }
  /* the greyed side-note in the count line's keyword reading */
  .cnt-dim { color: #98a1b0; font-weight: 400; }
  /* diagram figures that QUOTE an input — linked look, flash when they follow typing */
  .ot-echo { color: #1a6ec0; font-weight: 600; border-bottom: 1px dotted #9cc3e8; cursor: help; }
  .ot-flash { animation: otFlash 0.9s ease-out; }
  @keyframes otFlash { 0% { background: #ffe9a8; } 100% { background: transparent; } }

  /* The subset bulk button and its menu (owner 2026-08-12) moved to
     Shared Data/shell.css on 2026-08-25 — the Sales dashboard needed the same
     control, so the house version now lives in the shell (RULEBOOK Rule 6) and
     this page inherits it. Only the TICK menu, which is PPC's own, is below. */

  /* ── Ticks (owner 2026-08-12 redesign): the count line only ever says
     "N of M ticked", and only when the ticks deviate from the all-ticked
     default. The scopes live in the ▾ menu on the header box. */
  .tick-note { margin-left: 10px; padding-left: 10px; border-left: 1px solid #dfe4ea; color: #8a93a0; font-weight: 600; cursor: help; }
  .tick-caret { cursor: pointer; color: #98a1b0; font-size: 10px; padding: 1px 3px; border-radius: 4px; vertical-align: middle; }
  .tick-caret:hover { color: #1a6ec0; background: #eaf3fc; }
  #tickMenu { position: fixed; z-index: 500; background: #fff; border: 1px solid #d7dbe2; border-radius: 8px;
              box-shadow: 0 4px 14px rgba(0,0,0,.14); padding: 4px; font-size: 12px; font-weight: 500;
              text-transform: none; letter-spacing: normal; }
  .tick-mi { padding: 6px 12px; border-radius: 6px; cursor: pointer; color: #2d3436; white-space: nowrap; }
  .tick-mi:hover { background: #eaf3fc; color: #1a6ec0; }

/* ── The KW/ASIN diagram's SPECIAL KEYWORDS section (owner 2026-09-03) ──────
   `.fl-live` is a figure computed from the boxes as you type them, so nothing
   here is a second copy of the arithmetic to keep in step — specialAcosLines()
   and specialFairFigures() fill them, the same functions the judging calls.
   Since 2026-09-04 each box holds a % INCREASE, so it carries THREE live
   figures: the house number it is applied to, what that comes to, and the
   detail (the whole ACOS fan / the trial gate). */
 /* the unit after an input must never wrap away from it — "1 × the product"
   then a lone grey "price" on the next line was the first thing the render
   showed (2026-09-03, measured at the 367px section width). */
.fl-unit { white-space:nowrap; }
.fl-spnote { margin:10px 0 2px; padding:8px 12px; font-size:12px; line-height:1.6; color:#4a5568;
              background:#f7f4ff; border:1px solid #e4dcff; border-radius:8px; }
.fl-spnote .sp-mark { cursor:default; }
.fl-live { font-weight:700; color:#2d3436; }
.fl-live-bad { color:#c0392b; }
/* ONE bold answer per box — the figure the increase produces. The supporting
   detail beside it is live too, but a whole sentence in the same weight reads
   as nothing emphasised at all (seen only by rendering it, 2026-09-04). */
.fl-sec-sp #spLines, .fl-sec-sp #spTrialNow { font-weight:600; color:#5a6472; }
.fl-sec-sp #spLines.fl-live-bad, .fl-sec-sp #spTrialNow.fl-live-bad { color:#c0392b; font-weight:700; }
.fl-sec-sp .fl-def-off { opacity:.75; }
.fl-sec-sp .sp-mark { font-size:13px; }
/* the Bid card's SPECIAL block — its own heading, and the house figure each
   special one replaced, so the reader never has to go and look it up */
.tip-box .sp-tip-head { color:#7c3aed; }
.tip-box .sp-was { color:#a0aab8; font-weight:400; font-size:10.5px; white-space:nowrap; }
