/* =========================================================================================
   WhaleRestocks Web Console — "harbor ledger"
   A light, professional operations console. Neutral paper surfaces, one deep marine-blue
   accent for everything interactive, green strictly for success/profit, quiet hairlines.
   ========================================================================================= */

:root {
  /* Two palettes, one sheet: everything reads from these tokens, and <html data-theme="dark">
     (stamped by a pre-paint script in <head> — base.html + login.html — so there is no flash)
     swaps the whole set below. `color-scheme` must always match the palette, or the browser
     paints the widgets IT draws (select popups, datalist suggestions, scrollbars, date pickers)
     in the OS scheme while the page shows the other one — which is why the filter dropdowns
     once opened as a black box on a dark-mode machine. */
  color-scheme: light;

  /* --- paper surfaces --- */
  --abyss:      #f7f8fa;   /* page floor (clean neutral) */
  --deep:       #fbfcfd;   /* app shell / rail */
  --surface:    #ffffff;   /* panels */
  --surface-2:  #f4f6f9;   /* raised / hover */
  --surface-3:  #eef1f5;   /* inputs / active */
  --line:       rgba(17, 27, 45, .10);
  --line-soft:  rgba(17, 27, 45, .06);
  --line-strong:rgba(17, 27, 45, .16);

  /* --- ink --- */
  --ink:        #17202e;
  --ink-dim:    #4e5b70;
  --ink-faint:  #8791a3;
  --ink-ghost:  #b4bdca;

  /* --- accent: deep marine blue — the ONE interactive color --- */
  --accent:      #2e5fd7;
  --accent-deep: #2349a8;
  --accent-glow: rgba(46, 95, 215, .20);
  --accent-dim:  rgba(46, 95, 215, .09);
  /* Fill for a hovered primary button. In light it is simply the deep accent; dark needs its own
     value because there --accent-deep flips BRIGHTER (it is the text variant), and white button
     text on a bright fill would wash out (2.3:1). */
  --accent-hover: var(--accent-deep);

  /* --- semantics (status only, never decoration) --- */
  --sonar:      #16935a;   /* success / live / cartable / profit */
  --sonar-deep: #0f7247;
  --sonar-glow: rgba(22, 147, 90, .20);
  --sonar-dim:  rgba(22, 147, 90, .10);

  --amber:      #b07a10;   /* warn / benched / checking / queued */
  --amber-glow: rgba(176, 122, 16, .18);
  --amber-dim:  rgba(176, 122, 16, .07);   /* quiet warn wash (banners, pills, tinted rows) */
  --coral:      #d23b4c;   /* danger / failed / banned / fraud */
  --coral-glow: rgba(210, 59, 76, .16);
  --coral-dim:  rgba(210, 59, 76, .06);    /* quiet danger wash */
  --tide:       var(--accent);   /* info / links fold into the accent */
  --tide-glow:  var(--accent-glow);

  /* legacy names still referenced by a few templates/JS (always with a fallback) — folding
     them into the real tokens makes those call sites theme-aware for free */
  --bad:        var(--coral);
  --warn:       var(--amber);
  --mint:       var(--sonar);
  --mint-glow:  var(--sonar-dim);
  --muted:      var(--ink-faint);   /* settings.html divider/chips; mirrors the .muted class */

  /* --- chrome: the handful of colors that are not ink-on-surface --- */
  --hud-bg:      rgba(255, 255, 255, .82);  /* translucent blurred bars (fleet strip, save bar) */
  --scroll-thumb:       #d7dbe2;
  --scroll-thumb-hover: #bdc4cf;
  --tip-ink:     #ffffff;                   /* text on the inverted (ink-colored) tooltips */
  --tip-warn:    #ffca6b;                   /* the amber that reads on those tooltips */
  --seat-stroke: #ffffff;                   /* seat/section separators on the seat maps */
  --seat-stroke-muted: rgba(255, 255, 255, .72);  /* sold/taken seats keep a quieter separator */
  --on-fill:     #ffffff;                   /* label ink over saturated amber/coral/accent fills */
  --halo:        rgba(255, 255, 255, .82);  /* paint-order stroke behind seat-map labels */
  --veil:        rgba(247, 248, 250, .72);  /* page-colored loading/closed overlay */
  --scrim:       rgba(20, 30, 45, .38);     /* behind the phone nav drawer */
  --backdrop:    rgba(26, 42, 56, .42);     /* behind modals */

  /* --- type --- */
  --f-display: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --f-body:    "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  --f-mono:    "IBM Plex Mono", ui-monospace, "JetBrains Mono", monospace;

  /* --- geometry --- */
  --rail-w: 232px;
  --radius: 10px;
  --radius-sm: 6px;
  --gap: 18px;
  --shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 6px 20px -10px rgba(16, 24, 40, .10);
  --shadow-glow: 0 0 0 1px var(--accent-dim), 0 6px 20px -10px rgba(16, 24, 40, .10);
}

/* =========================================================================================
   HARBOR AT NIGHT — the same ledger after dark.
   Not a grayscale flip: the surfaces stay in the marine family (blue-cast slate, page floor
   darkest, panels lifted above it), the ONE accent is the same marine blue brightened just
   enough to hold contrast, and the status colors keep their exact meanings. --accent-deep /
   --sonar-deep flip brighter rather than deeper — they are the *text* variants, and text
   must gain contrast against dark surfaces, not lose it.
   ========================================================================================= */
:root[data-theme="dark"] {
  color-scheme: dark;

  /* --- night surfaces --- */
  --abyss:      #0d1119;   /* page floor (deepest water) */
  --deep:       #10151e;   /* app shell / rail */
  --surface:    #151c28;   /* panels */
  --surface-2:  #1b2433;   /* raised / hover */
  --surface-3:  #222d3f;   /* inputs / active */
  --line:       rgba(164, 183, 215, .13);
  --line-soft:  rgba(164, 183, 215, .08);
  --line-strong:rgba(164, 183, 215, .22);

  /* --- ink --- */
  --ink:        #e7ecf5;
  --ink-dim:    #a8b3c7;
  --ink-faint:  #7b87a0;
  --ink-ghost:  #525e77;

  /* --- accent --- */
  --accent:      #5178e8;
  --accent-deep: #8aabf4;
  --accent-glow: rgba(81, 120, 232, .32);
  --accent-dim:  rgba(81, 120, 232, .15);
  --accent-hover: #4062c8;   /* deeper than --accent: hovered primary keeps white text legible */

  /* --- semantics --- */
  --sonar:      #2fc389;
  --sonar-deep: #62dcab;
  --sonar-glow: rgba(47, 195, 137, .30);
  --sonar-dim:  rgba(47, 195, 137, .13);

  --amber:      #dfa63d;
  --amber-glow: rgba(223, 166, 61, .28);
  --amber-dim:  rgba(223, 166, 61, .12);
  --coral:      #ee6b7c;
  --coral-glow: rgba(238, 107, 124, .28);
  --coral-dim:  rgba(238, 107, 124, .12);

  /* --- chrome --- */
  --hud-bg:      rgba(16, 21, 30, .82);
  --scroll-thumb:       #2e3a50;
  --scroll-thumb-hover: #3d4c68;
  --tip-ink:     #10151d;                  /* tooltips invert: light card, dark text */
  --tip-warn:    #7d5b0e;
  --seat-stroke: #0d1119;
  --seat-stroke-muted: rgba(13, 17, 25, .72);
  --on-fill:     #10151d;                  /* the dark fills are bright, so their label ink is dark */
  --halo:        rgba(13, 17, 25, .85);
  --veil:        rgba(13, 17, 25, .72);
  --scrim:       rgba(2, 5, 10, .55);
  --backdrop:    rgba(2, 5, 10, .60);
  --shadow: 0 1px 2px rgba(0, 0, 0, .40), 0 6px 20px -10px rgba(0, 0, 0, .55);
  --shadow-glow: 0 0 0 1px var(--accent-dim), 0 6px 20px -10px rgba(0, 0, 0, .55);
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--f-body);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
  background: var(--abyss);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-deep); }

svg.ico { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; flex: none; }

::selection { background: var(--accent-dim); color: var(--ink); }

/* scrollbars */
*::-webkit-scrollbar { width: 11px; height: 11px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--scroll-thumb); border-radius: 99px; border: 3px solid transparent; background-clip: padding-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--scroll-thumb-hover); background-clip: padding-box; }

/* =========================================================================================
   APP SHELL — fixed command rail + top fleet strip + content
   ========================================================================================= */
.shell { display: grid; grid-template-columns: var(--rail-w) 1fr; min-height: 100vh; }

/* ---- command rail (sidebar) ----
   Four fixed bands: brand, instance scope, scrolling grouped nav, foot. Only the nav scrolls,
   so the brand and the sign-out are always reachable no matter how many tabs exist. */
.rail {
  position: sticky; top: 0; align-self: start;
  height: 100vh; display: flex; flex-direction: column;
  background: var(--deep);
  border-right: 1px solid var(--line);
  padding: 0;
}

/* brand — mark sits in a tinted tile so it reads as a logo, not a stray glyph */
.rail__brand {
  display: flex; align-items: center; gap: 11px;
  padding: 16px 16px 15px;
  border-bottom: 1px solid var(--line-soft);
}
.rail__mark {
  width: 34px; height: 34px; flex: none; color: var(--accent);
  background: var(--accent-dim); border-radius: 9px; padding: 5px;
  stroke-width: 1.7;
}
.rail__title { font-family: var(--f-display); font-weight: 650; letter-spacing: -.1px; font-size: 14.5px; line-height: 1.1; min-width: 0; }
.rail__title small { display: block; font-family: var(--f-mono); font-weight: 400; font-size: 9px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--ink-faint); margin-top: 3px; }
.rail__close { display: none; }   /* phone-only dismiss; see the drawer block below */

/* instance switcher — a single control with a live status dot baked in */
.rail__instance { padding: 12px 14px; border-bottom: 1px solid var(--line-soft); }
.rail__instance label { display: block; font-family: var(--f-mono); font-size: 9px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 6px; }
.rail__pick {
  position: relative; display: flex; align-items: center;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-sm);
  transition: border-color .14s, box-shadow .14s;
}
.rail__pick:hover { border-color: var(--line-strong); }
.rail__pick:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }
.rail__pick.is-scoped { border-color: var(--accent-glow); background: var(--accent-dim); }
.rail__pickdot { width: 6px; height: 6px; border-radius: 99px; background: var(--ink-ghost); flex: none; margin-left: 10px; }
.rail__pickdot.on  { background: var(--sonar); box-shadow: 0 0 0 3px var(--sonar-dim); }
.rail__pickdot.off { background: var(--ink-ghost); }
.rail__pick select {
  flex: 1; min-width: 0; border: 0; background: none; box-shadow: none;
  padding: 7px 26px 7px 8px; font-size: 12px; color: var(--ink);
}
.rail__pick select:focus { outline: none; box-shadow: none; }

/* nav — the only scrolling band */
.rail__nav {
  flex: 1; overflow-y: auto; overscroll-behavior: contain;
  padding: 8px 9px 14px; display: flex; flex-direction: column; gap: 1px;
}
.rail__group {
  font-family: var(--f-mono); font-size: 8.5px; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--ink-ghost); padding: 0 11px; margin: 13px 0 5px;
}
.rail__nav > .rail__group:first-child { margin-top: 2px; }
.navlink {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 11px; border-radius: 7px;
  color: var(--ink-dim); font-weight: 500; font-size: 13px;
  position: relative; transition: background .14s, color .14s;
}
.navlink svg { width: 16px; height: 16px; flex: none; opacity: .7; transition: opacity .14s, color .14s; }
.navlink__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.navlink:hover { background: var(--surface-2); color: var(--ink); }
.navlink:hover svg { opacity: 1; }
.navlink.is-active {
  background: var(--accent-dim); color: var(--accent-deep); font-weight: 600;
}
.navlink.is-active svg { opacity: 1; color: var(--accent); }
.navlink.is-active::before {
  content: ""; position: absolute; left: -9px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 18px; border-radius: 0 99px 99px 0;
  background: var(--accent);
}
.navlink:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Live CART COUNT on the Carts link — a filled pill, distinct from .navlink__badge (which counts
   running jobs on every link) so the two numbers can sit side by side without reading as one.
   margin-left:auto lives here because this element comes first; the job badge then trails it. */
.navlink__count {
  margin-left: auto; flex: none; position: relative;
  font-family: var(--f-mono); font-size: 10px; font-variant-numeric: tabular-nums;
  min-width: 19px; text-align: center; padding: 1.5px 6px; border-radius: 99px;
  color: var(--ink-dim); background: var(--surface-3); border: 1px solid var(--line);
}
.navlink__count.live { color: var(--accent-deep); background: var(--accent-dim); border-color: var(--accent-dim); }
/* Unseen carts arrived since this browser last looked. Coral because it is the console's
   attention colour — and it is a dot, not a number, because "how many are new" is not the
   question; "is there something I haven't seen" is. */
.navlink__count.has-new::after {
  content: ""; position: absolute; top: -3px; right: -3px;
  width: 7px; height: 7px; border-radius: 99px;
  background: var(--coral); box-shadow: 0 0 0 2px var(--deep);
}
.navlink__count:not([hidden]) + .navlink__badge { margin-left: 6px; }

.navlink__badge { margin-left: auto; font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-faint); flex: none; }
.navlink__badge.live { color: var(--ink); }
.navlink__badge.live::before {
  content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--sonar); margin-right: 5px; vertical-align: 1px;
  animation: wr-badge-pulse 1.6s ease-in-out infinite;
}
@keyframes wr-badge-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }

.rail__foot { padding: 10px 14px; border-top: 1px solid var(--line-soft); display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rail__foot .ver { font-family: var(--f-mono); font-size: 10px; color: var(--ink-ghost); }
.rail__out {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12px; color: var(--ink-faint);
  padding: 5px 9px; border-radius: var(--radius-sm); transition: background .14s, color .14s;
}
.rail__out .ico { width: 14px; height: 14px; }
.rail__out:hover { color: var(--coral); background: var(--coral-glow); }

/* ---- main column ---- */
.main { min-width: 0; display: flex; flex-direction: column; }

/* top fleet-health strip — the old console title, now a HUD bar */
.fleet {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
  padding: 9px 22px;
  background: var(--hud-bg); backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line);
}
.fleet__title { font-family: var(--f-display); font-weight: 600; font-size: 13px; letter-spacing: .4px; margin-right: 8px; color: var(--ink); }
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 10px; border-radius: 99px;
  background: var(--surface); border: 1px solid var(--line);
  font-family: var(--f-mono); font-size: 11.5px; color: var(--ink-dim);
  white-space: nowrap;
}
.chip b { color: var(--ink); font-weight: 600; }
.chip .dot { width: 7px; height: 7px; border-radius: 99px; background: var(--ink-faint); flex: none; }
.chip.good .dot { background: var(--sonar); }
.chip.warn .dot { background: var(--amber); }
.chip.bad  .dot { background: var(--coral); }
.chip.good b { color: var(--sonar); }
.chip.warn b { color: var(--amber); }
.chip.bad  b { color: var(--coral); }
.fleet__spacer { flex: 1; }
.fleet__clock { font-family: var(--f-mono); font-size: 11.5px; color: var(--ink-faint); }

.content { padding: 26px 22px 60px; max-width: 1480px; width: 100%; }
/* A page rendered inside an in-page frame (base.html `embed`): no rail beside it, and the host
   modal already supplies the outer margin. Two classes, so it outranks the breakpoint paddings. */
.content.content--embed { padding: 16px 18px 28px; max-width: none; }

/* page header */
.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; margin-bottom: 22px; }
.page-head__l { min-width: 0; }
.eyebrow { font-family: var(--f-mono); font-size: 10.5px; letter-spacing: 2.4px; text-transform: uppercase; color: var(--accent-deep); margin-bottom: 7px; }
h1 { font-family: var(--f-display); font-weight: 700; font-size: 27px; letter-spacing: -.2px; margin: 0; line-height: 1.1; }
.page-head p { color: var(--ink-dim); margin: 7px 0 0; font-size: 13.5px; max-width: 70ch; }
/* `flex: 0 1 auto` + wrap, not `flex: none`: a header with four actions (Sales) otherwise refuses
   to shrink and pushes the whole document sideways in the band above the 880px stacking rule. */
.page-head__r { display: flex; gap: 10px; align-items: center; flex: 0 1 auto;
  flex-wrap: wrap; justify-content: flex-end; }

h2 { font-family: var(--f-display); font-weight: 700; font-size: 16px; letter-spacing: -.1px; margin: 0; }
h3 { font-family: var(--f-display); font-weight: 700; font-size: 13.5px; letter-spacing: 0; margin: 0; color: var(--ink); }

/* =========================================================================================
   PANELS / CARDS / STATS
   ========================================================================================= */
.panel {
  background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.panel__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 15px 18px; border-bottom: 1px solid var(--line-soft); }
.panel__head .sub { font-family: var(--f-mono); font-size: 11px; color: var(--ink-faint); }
/* "N running" on the Queue rail. Deliberately louder than the faint count beside it: that count is
   of queue-GATED events and stays high after everything is stopped, so this is the only figure on
   the tab that answers "is anything still joining?". */
.panel__head .sub.q-running { color: var(--amber); font-weight: 600; }
.panel__body { padding: 18px; }
.panel__body.flush { padding: 0; }

.grid { display: grid; gap: var(--gap); }
/* grid children default to min-width:auto, so unbreakable content (long paths, proxy
   strings) blows out the track and overflows the row — let every grid item shrink. */
.grid > * { min-width: 0; }
.grid.cols-2 { grid-template-columns: repeat(2, 1fr); }
.grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.grid.cols-4 { grid-template-columns: repeat(4, 1fr); }
.grid.cols-5 { grid-template-columns: repeat(5, 1fr); }
@media (max-width: 1100px) { .grid.cols-4 { grid-template-columns: repeat(2, 1fr); } .grid.cols-3 { grid-template-columns: repeat(2,1fr);} .grid.cols-5 { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 720px) { .grid.cols-2, .grid.cols-3, .grid.cols-4, .grid.cols-5 { grid-template-columns: 1fr; } }

/* stat card — big mono number, thin accent top rule */
.stat {
  position: relative; overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 16px 17px 15px;
  box-shadow: var(--shadow);
}
.stat::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px; background: linear-gradient(90deg, var(--accent), transparent 70%); opacity: .45; }
.stat.is-warn::before { background: linear-gradient(90deg, var(--amber), transparent 70%); }
.stat.is-bad::before  { background: linear-gradient(90deg, var(--coral), transparent 70%); }
.stat__label { font-family: var(--f-mono); font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--ink-faint); display: flex; align-items: center; gap: 7px; }
.stat__value { font-family: var(--f-mono); font-weight: 600; font-size: 30px; letter-spacing: -.5px; margin-top: 8px; line-height: 1; color: var(--ink); }
.stat__value .unit { font-size: 14px; color: var(--ink-faint); font-weight: 400; margin-left: 3px; }
.stat__sub { margin-top: 7px; font-size: 11.5px; color: var(--ink-dim); }
.stat.is-good .stat__value { color: var(--sonar); }
.stat.is-warn .stat__value { color: var(--amber); }
.stat.is-bad  .stat__value { color: var(--coral); }

/* =========================================================================================
   PILLS / BADGES / DOTS
   ========================================================================================= */
.pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2.5px 9px; border-radius: 99px;
  font-family: var(--f-mono); font-size: 11px; font-weight: 500; letter-spacing: .2px;
  border: 1px solid var(--line-strong); color: var(--ink-dim); background: var(--surface);
}
.pill .dot { width: 6px; height: 6px; border-radius: 99px; background: currentColor; }
.pill.good { color: var(--sonar-deep); border-color: var(--sonar-dim); background: var(--sonar-dim); }
.pill.warn { color: var(--amber); border-color: var(--amber-glow); background: var(--amber-dim); }
.pill.bad  { color: var(--coral); border-color: var(--coral-glow); background: var(--coral-dim); }
.pill.info { color: var(--accent-deep); border-color: var(--accent-dim); background: var(--accent-dim); }
.pill.idle { color: var(--ink-faint); }

/* dashboard per-engine pool gauges (tmpt + anon-jar buffers), live-updated */
.pool-cell { display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.pill.pool { padding: 2.5px 8px; gap: 5px; }
.pill.pool .ico { width: 13px; height: 13px; opacity: .85; }
.pill.pool b { color: inherit; font-weight: 600; font-variant-numeric: tabular-nums; }
.pill.pool .u { color: var(--ink-faint); font-weight: 400; letter-spacing: .3px; }

.pulse { position: relative; }
.pulse::after {
  content: ""; position: absolute; left: -3px; top: 50%; width: 6px; height: 6px;
  transform: translateY(-50%); border-radius: 99px; background: currentColor;
  animation: sonar-ping 1.8s ease-out infinite;
}
@keyframes sonar-ping {
  0%   { box-shadow: 0 0 0 0 currentColor; opacity: .7; }
  70%  { box-shadow: 0 0 0 9px transparent; opacity: 0; }
  100% { box-shadow: 0 0 0 0 transparent; opacity: 0; }
}

/* =========================================================================================
   BUTTONS
   ========================================================================================= */
.btn {
  display: inline-flex; align-items: center; gap: 8px; justify-content: center;
  font-family: var(--f-display); font-weight: 600; font-size: 13px; letter-spacing: .3px;
  padding: 8px 15px; border-radius: var(--radius-sm); cursor: pointer;
  background: var(--surface-2); color: var(--ink); border: 1px solid var(--line-strong);
  transition: background .14s, border-color .14s, transform .05s, box-shadow .14s;
  white-space: nowrap; text-decoration: none;
}
.btn:hover { background: var(--surface-3); border-color: var(--line-strong); }
.btn:active { transform: translateY(1px); }
.btn svg { width: 15px; height: 15px; }
.btn.primary {
  background: var(--accent);
  color: #ffffff; border-color: transparent; box-shadow: 0 1px 2px rgba(16, 24, 40, .10);
}
.btn.primary:hover { background: var(--accent-hover); }
.btn.danger { color: var(--coral); border-color: var(--coral-glow); }
.btn.danger:hover { background: var(--coral-dim); border-color: var(--coral); }
.btn.ghost { background: transparent; border-color: var(--line); }
.btn.ghost:hover { background: var(--surface); }
.btn.sm { padding: 5px 10px; font-size: 12px; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn-row { display: flex; gap: 9px; flex-wrap: wrap; }

/* =========================================================================================
   TABLES
   ========================================================================================= */
.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 13px; }
table.data th {
  text-align: left; font-family: var(--f-mono); font-weight: 500; font-size: 10px;
  letter-spacing: 1.4px; text-transform: uppercase; color: var(--ink-faint);
  padding: 11px 14px; border-bottom: 1px solid var(--line); white-space: nowrap;
}
table.data td { padding: 11px 14px; border-bottom: 1px solid var(--line-soft); color: var(--ink-dim); vertical-align: middle; }
table.data tr:last-child td { border-bottom: none; }
table.data tbody tr { transition: background .12s; }
table.data tbody tr:hover { background: var(--surface); }
table.data td.mono, table.data .mono { font-family: var(--f-mono); color: var(--ink); }
table.data td.num { font-family: var(--f-mono); text-align: right; }
table.data th.num { text-align: right; }
.t-primary { color: var(--ink); font-weight: 500; }

/* =========================================================================================
   FORMS
   ========================================================================================= */
label.field { display: block; margin-bottom: 14px; }
.field > span { display: block; font-family: var(--f-mono); font-size: 10.5px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 6px; }
input[type=text], input[type=password], input[type=number], input[type=search], input[type=url], select, textarea {
  width: 100%; font-family: var(--f-body); font-size: 13.5px; color: var(--ink);
  background: var(--surface-3); border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  padding: 9px 12px; transition: border-color .14s, box-shadow .14s; outline: none;
}
input[type=text].mono, input.mono, textarea.mono, select.mono { font-family: var(--f-mono); }
input:focus, select:focus, textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }
input::placeholder, textarea::placeholder { color: var(--ink-ghost); }
textarea { resize: vertical; min-height: 96px; line-height: 1.55; }
select { appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%2388a2b0' stroke-width='2'%3E%3Cpath d='M3 5l3 3 3-3'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 11px center; padding-right: 30px; }
/* Fleet table profile-assign dropdown: size to the selected profile name (not the narrow
   column's min-content) so it isn't clipped behind the arrow. Floor keeps short names usable. */
select[data-assign] { width: auto; min-width: 132px; max-width: 240px; }
.checkbox { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px; color: var(--ink-dim); }
.checkbox input { width: auto; accent-color: var(--accent); }
.help { font-size: 11.5px; color: var(--ink-faint); margin-top: 5px; }
.inline-form { display: flex; gap: 9px; align-items: flex-end; flex-wrap: wrap; }

/* =========================================================================================
   EMPTY STATE / MISC
   ========================================================================================= */
.empty { text-align: center; padding: 46px 20px; color: var(--ink-faint); }
.empty svg { width: 38px; height: 38px; opacity: .45; margin-bottom: 12px; color: var(--accent); }
.empty h3 { color: var(--ink-dim); margin-bottom: 5px; }
.muted { color: var(--ink-faint); }
.mono { font-family: var(--f-mono); }
.tnum { font-family: var(--f-mono); font-variant-numeric: tabular-nums; }
.right { text-align: right; }
.nowrap { white-space: nowrap; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 1px; }
hr.rule { border: none; border-top: 1px solid var(--line-soft); margin: 18px 0; }
.stack { display: flex; flex-direction: column; gap: var(--gap); }
.row { display: flex; gap: var(--gap); align-items: center; }
.banner { display: flex; align-items: center; gap: 11px; padding: 11px 15px; border-radius: var(--radius-sm); font-size: 13px; border: 1px solid var(--line-strong); background: var(--surface); margin-bottom: 18px; }
.banner.warn { border-color: var(--amber-glow); background: var(--amber-dim); color: var(--amber); }
.banner.bad { border-color: var(--coral-glow); background: var(--coral-dim); color: var(--coral); }
.banner svg { width: 17px; height: 17px; flex: none; }

/* secret mask */
.secret { font-family: var(--f-mono); color: var(--ink-faint); }
.reveal { cursor: pointer; border-bottom: 1px dotted var(--ink-ghost); }

/* =========================================================================================
   MODAL / DRAWER
   ========================================================================================= */
.modal-backdrop {
  position: fixed; inset: 0; z-index: 70; display: none;
  background: var(--backdrop); backdrop-filter: blur(3px);
  align-items: flex-start; justify-content: center; padding: 7vh 18px 18px;
}
.modal-backdrop.open { display: flex; }
.modal {
  width: 100%; max-width: 720px; max-height: 84vh; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius);
  box-shadow: var(--shadow); animation: rise .22s cubic-bezier(.2,.7,.3,1) both;
}
.modal.wide { max-width: 920px; }
.modal__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 20px; border-bottom: 1px solid var(--line-soft); }
.modal__head h2 { font-size: 16px; }
.modal__close { cursor: pointer; color: var(--ink-faint); background: none; border: none; padding: 4px; border-radius: 5px; }
.modal__close:hover { color: var(--ink); background: var(--surface-2); }
.modal__body { padding: 20px; overflow-y: auto; }
.modal__foot { display: flex; align-items: center; justify-content: flex-end; gap: 10px; padding: 14px 20px; border-top: 1px solid var(--line-soft); }
.steps { display: flex; gap: 8px; margin-bottom: 18px; }
.step { flex: 1; height: 3px; border-radius: 99px; background: var(--surface-3); }
.step.active { background: var(--accent); }
.step.done { background: var(--accent-deep); }
.pick-list { display: flex; flex-direction: column; gap: 8px; max-height: 46vh; overflow-y: auto; }
.pick {
  display: flex; align-items: center; gap: 12px; padding: 11px 13px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2);
  cursor: pointer; transition: border-color .12s, background .12s;
}
.pick:hover { border-color: var(--accent-glow); }
.pick.sel { border-color: var(--accent); background: var(--accent-dim); }
.pick input { accent-color: var(--accent); }
.pick__meta { min-width: 0; flex: 1; }
.pick__t { color: var(--ink); font-weight: 500; }
.pick__s { font-size: 11.5px; color: var(--ink-faint); font-family: var(--f-mono); margin-top: 2px; }
/* Live TM stock beside each date in the add-by-artist wizard. Fixed width so the numbers form
   a scannable right-hand column instead of ragging with the venue names beside them. */
.pick__avail { flex: 0 0 auto; text-align: right; min-width: 104px; }
.wiz-avail { font-family: var(--f-mono); font-size: 11.5px; white-space: nowrap; }
.wiz-avail.pending { color: var(--ink-faint); opacity: .65; }
.wiz-avail.ok { color: var(--sonar); }
.wiz-avail.out { color: var(--coral); }
.wiz-avail.unk { color: var(--ink-faint); }
.wiz-avail__sub { color: var(--ink-faint); font-size: 10.5px; }
.chips-edit { display: flex; flex-wrap: wrap; gap: 6px; }
.chip-toggle { cursor: pointer; user-select: none; padding: 4px 10px; border-radius: 99px; font-family: var(--f-mono); font-size: 11.5px; border: 1px solid var(--line-strong); color: var(--ink-dim); background: var(--surface-2); }
.chip-toggle.on { color: var(--accent-deep); border-color: var(--accent); background: var(--accent-dim); }
.spinner { width: 16px; height: 16px; border: 2px solid var(--line-strong); border-top-color: var(--accent); border-radius: 50%; animation: spin .7s linear infinite; display: inline-block; }
@keyframes spin { to { transform: rotate(360deg); } }

/* tiny inline controls used in data tables */
.toggle { cursor: pointer; display: inline-flex; align-items: center; gap: 6px; font-family: var(--f-mono); font-size: 11px; padding: 3px 9px; border-radius: 99px; border: 1px solid var(--line-strong); color: var(--ink-faint); background: var(--surface); }
.toggle.on { color: var(--accent-deep); border-color: var(--accent-glow); background: var(--accent-dim); }
.toggle .dot { width: 6px; height: 6px; border-radius: 99px; background: currentColor; }
.inp-mini { width: 64px; padding: 4px 7px; font-size: 12px; }
.sel-mini { padding: 4px 24px 4px 8px; font-size: 12px; }
.icon-btn { cursor: pointer; color: var(--ink-faint); background: none; border: 1px solid var(--line); border-radius: 5px; padding: 4px; display: inline-flex; }
.icon-btn:hover { color: var(--ink); border-color: var(--line-strong); background: var(--surface-2); }
.icon-btn.danger:hover { color: var(--coral); border-color: var(--coral-glow); }
.icon-btn.spin { color: var(--accent); pointer-events: none; }
.icon-btn.spin svg { animation: spin .7s linear infinite; }
.btn.busy { opacity: .7; pointer-events: none; }
.btn.busy svg { animation: spin .7s linear infinite; }

/* =========================================================================================
   TOASTS
   ========================================================================================= */
.toasts { position: fixed; right: 18px; bottom: 18px; z-index: 80; display: flex; flex-direction: column; gap: 10px; max-width: 360px; }
.toast {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 12px 14px; border-radius: var(--radius-sm); font-size: 13px;
  background: var(--surface-2); border: 1px solid var(--line-strong);
  box-shadow: var(--shadow); animation: toast-in .25s ease both;
}
.toast.good { border-left: 3px solid var(--sonar); }
.toast.warn { border-left: 3px solid var(--amber); }
.toast.bad  { border-left: 3px solid var(--coral); }
.toast.info { border-left: 3px solid var(--tide); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }

/* =========================================================================================
   LOGIN
   ========================================================================================= */
.gate { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.gate__card { width: 100%; max-width: 380px; }
.gate__brand { display: flex; flex-direction: column; align-items: center; gap: 14px; margin-bottom: 26px; text-align: center; }
.gate__mark { width: 58px; height: 58px; color: var(--accent); }
.gate__brand h1 { font-size: 22px; }
.gate__brand small { font-family: var(--f-mono); font-size: 10px; letter-spacing: 3px; text-transform: uppercase; color: var(--ink-faint); }
.gate .panel__body { padding: 24px; }
.gate .err { color: var(--coral); font-size: 13px; margin-bottom: 14px; text-align: center; }

/* staggered page-load reveal */
.reveal-in { animation: rise .5s cubic-bezier(.2,.7,.3,1) both; }
.reveal-in:nth-child(1) { animation-delay: .02s; }
.reveal-in:nth-child(2) { animation-delay: .07s; }
.reveal-in:nth-child(3) { animation-delay: .12s; }
.reveal-in:nth-child(4) { animation-delay: .17s; }
.reveal-in:nth-child(5) { animation-delay: .22s; }
@keyframes rise { from { opacity: 0; transform: translateY(12px); } }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }

/* responsive rail collapse */
@media (max-width: 880px) {
  .shell { grid-template-columns: 1fr; }
  .rail { position: fixed; left: 0; top: 0; width: var(--rail-w); transform: translateX(-100%); transition: transform .2s; z-index: 60; }
  .rail.open { transform: none; }
  .content { padding: 20px 14px 50px; }
}
.rail-toggle { display: none; }
@media (max-width: 880px) { .rail-toggle { display: inline-flex; } }

/* ---- shared event editor: the "Event" block (templates/_event_editor_modal.html, editor_full) ----
   Only the Carts tab renders this half — the Events tab already carries min qty / offer code / ACO /
   gates inline on its table row. A banded strip above the curation grid so the two halves read as
   "what this event IS" then "what it buys". */
.ee-block { border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
            background: var(--surface-2); padding: 12px 14px; margin-bottom: 18px; }
.ee-ident { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.ee-name { font-family: var(--f-display); font-weight: 700; font-size: 14px; color: var(--ink);
           min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }
.ee-sub { font-size: 11.5px; color: var(--ink-dim); min-width: 0; }
.ee-sub:empty { display: none; }
/* flex-start + a shared control band: the gate glyphs and link buttons are shorter than a text
   input, so bottom-alignment would drop their labels a line below "MIN QUANTITY" / "OFFER CODE".
   Every cell's label sits on one line and its control centres in the same 38px strip. */
.ee-controls { display: flex; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.ee-f { margin: 0; flex: 0 0 auto; }
.ee-f input { width: 120px; }
.ee-f--gates, .ee-f--links { flex: 0 0 auto; }
.ee-gates, .ee-links { display: flex; align-items: center; gap: 7px; min-height: 38px; flex-wrap: wrap; }
.ee-msg { font-size: 11px; color: var(--ink-faint); }
.ee-msg:empty { display: none; }
/* ACO armed while Monitor Mode is on is a pair that reads armed and never fires — amber, not green */
.toggle.is-moot { color: var(--amber); border-color: var(--amber-glow); background: var(--amber-dim); }
@media (max-width: 620px) {
  .ee-controls { gap: 12px; }
  .ee-f input { width: 100%; }
  .ee-f:not(.ee-f--gates):not(.ee-f--links) { flex: 1 1 140px; }
}

/* ---- curate & filter modal: two-column layout + interactive seat map ---- */
.cur-grid { display: grid; grid-template-columns: 300px 1fr; gap: 18px; }
@media (max-width: 760px) { .cur-grid { grid-template-columns: 1fr; } }
.cur-left { display: flex; flex-direction: column; gap: 14px; }
.cur-tabs { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.cur-tab { background: none; border: 1px solid var(--line-soft); color: var(--ink-dim);
           border-radius: 7px; padding: 4px 12px; cursor: pointer; font-size: 12px; }
.cur-tab.active { border-color: var(--accent); color: var(--accent-deep); }

.seatmap-wrap { width: 100%; max-height: 52vh; overflow: auto; position: relative;
                background: var(--surface-2); border: 1px solid var(--line-soft);
                border-radius: 10px; }
.seatmap { width: 100%; height: auto; display: block; }
.seatmap .seg { fill: var(--surface); stroke: var(--line-soft); stroke-width: 6;
                cursor: pointer; transition: fill .08s; }
.seatmap .seg:hover { fill: var(--ink-faint); }
.seatmap .seg.sel { fill: var(--accent); stroke: var(--accent); }
.seatmap .seg.ga { stroke: var(--amber); stroke-dasharray: 18 10; }
.seatmap .seg.ga.sel { fill: var(--amber); }
/* fitted in-section name labels: centered in each shape, size-capped so they never
   overflow it; white over our own selected/pending fill, quiet ink otherwise */
.seatmap .seg-name { fill: var(--ink-dim); text-anchor: middle; dominant-baseline: middle;
                     pointer-events: none; font-family: var(--f-mono); font-weight: 600; }
.seatmap .seg-name.on-fill { fill: var(--on-fill); }

.map-legend { margin-top: 8px; font-size: 11px; color: var(--ink-dim);
              display: flex; align-items: center; gap: 6px; }
.map-legend .lg { width: 12px; height: 12px; border-radius: 3px; display: inline-block;
                  background: var(--surface); border: 1px solid var(--line-soft); }
.map-legend .lg.sel { background: var(--accent); border-color: var(--accent); }
.map-legend .lg.ga { border-color: var(--amber); }
.map-status { padding: 24px; text-align: center; font-size: 13px; }

/* exclude-type chips reuse .chip-toggle but turn coral when active (excluded) */
.chip-toggle.danger.on { background: var(--coral); border-color: var(--coral); color: var(--on-fill); }

/* background venue art (the STAGE layer) composited under the interactive paths.
   When present, section polygons become a translucent highlight overlay so the art
   shows through; the art carries its own labels, so ours are hidden. */
.seatmap .seatmap-bg { pointer-events: none; }
.seatmap.has-bg .seg { fill: transparent; stroke: rgba(120,150,170,.35); stroke-width: 4; }
.seatmap.has-bg .seg:hover { fill: var(--accent); fill-opacity: .18; }
.seatmap.has-bg .seg.sel { fill: var(--accent); fill-opacity: .45; stroke: var(--accent); stroke-width: 8; }
.seatmap.has-bg .seg.ga { stroke: var(--amber); }
.seatmap.has-bg .seg.ga.sel { fill: var(--amber); fill-opacity: .45; stroke: var(--amber); }
/* over art, only label sections whose fill covers the art's own baked label */
.seatmap.has-bg .seg-name { display: none; }
.seatmap.has-bg .seg-name.show { display: block; }

/* quick section-group chips (Floor / 100s / 200s / TERRACE LEVEL / ...) */
.cur-groups { margin-bottom: 10px; }
.cur-groups__head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.cur-groups__lbl { font-size: 11px; color: var(--ink-dim); text-transform: uppercase; letter-spacing: .04em; margin-right: auto; }
/* cap the groups strip so a venue with many groups never shoves the map off-screen */
#secGroups { max-height: 92px; overflow-y: auto; padding-right: 2px; }
.chip-toggle.group { border-color: var(--accent); color: var(--ink-dim); }
.chip-toggle.group.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.chip-toggle.group.part { border-style: dashed; color: var(--ink); }
.chip-toggle.group .grp-n { opacity: .6; font-size: 10px; }

/* excluded-type chip showing the code + its human description (e.g. "PLAT1 Official Platinum") */
.chip-toggle .chip-sub { opacity: .7; font-size: 11px; font-weight: 400; }
.chip-toggle.danger.on .chip-sub { opacity: .9; }

/* section price tiers (curate modal): tier rows, the amber pending-tier build state, and
   the per-section price tag on chips / outline on the map */
.tier-list { display: flex; flex-direction: column; gap: 6px; margin: 2px 0 8px; }
.tier-row { display: flex; align-items: center; gap: 8px; padding: 6px 8px 6px 10px;
  border: 1px solid var(--line-soft); border-radius: 9px; background: var(--surface-2); font-size: 12px; }
.tier-row .tier-price { font-family: var(--f-mono); font-weight: 600; color: var(--accent-deep); white-space: nowrap; }
.tier-row .tier-secs { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; color: var(--ink-dim); }
.tier-row .icon-btn { flex: none; font-size: 13px; line-height: 1; }
.tier-editor { border: 1px dashed var(--amber); border-radius: 9px; padding: 10px;
  margin: 2px 0 8px; background: var(--amber-dim); }
.tier-editor__hint { font-size: 11px; color: var(--ink-dim); margin-bottom: 8px; }
.chip-toggle.pend { border-color: var(--amber); color: var(--amber); background: var(--amber-dim); box-shadow: inset 0 0 0 1px var(--amber); }
.chip-toggle .tier-tag { font-family: var(--f-mono); font-size: 10px; font-weight: 600; color: var(--accent-deep); margin-left: 5px; }
.chip-toggle.pend .tier-tag { color: var(--amber); }
.seatmap .seg.tiered { stroke: var(--accent-deep); stroke-width: 12; }
.seatmap .seg.pend { fill: var(--amber); fill-opacity: .6; stroke: var(--amber); }
.seatmap.has-bg .seg.tiered { stroke: var(--accent-deep); stroke-width: 8; }
.seatmap.has-bg .seg.pend { fill: var(--amber); fill-opacity: .5; stroke: var(--amber); stroke-width: 8; }
/* a map area that couldn't be reconciled to a manifest section — shown for context but
   not a clickable carting target */
.seatmap .seg.unmatched { opacity: .28; pointer-events: none; }

/* AutoPrice aggressiveness dial: one slider, live % readout, banded hint */
.ap-aggro { display: flex; align-items: center; gap: 10px; margin: 4px 0 10px; }
.ap-aggro input[type="range"] { flex: 1; accent-color: var(--accent); cursor: pointer; min-width: 0; }
.ap-aggro__end { font-size: 10px; color: var(--ink-faint); text-transform: uppercase;
  letter-spacing: .05em; white-space: nowrap; flex: none; }
.ap-aggro__val { font-weight: 700; font-size: 14px; color: var(--accent-deep);
  min-width: 46px; text-align: right; flex: none; }

/* hover price tooltip on the curate map: the hovered section's name + the price cap
   that applies to it (tier > event max), floating just above the cursor */
.map-tip { position: absolute; z-index: 6; pointer-events: none; background: var(--ink);
  color: var(--tip-ink); border-radius: 7px; padding: 6px 10px; line-height: 1.4;
  box-shadow: var(--shadow); white-space: nowrap; max-width: 240px; overflow: hidden; }
.map-tip[hidden] { display: none; }
.map-tip b { display: block; font-family: var(--f-mono); font-size: 11px; font-weight: 600;
  letter-spacing: .04em; opacity: .85; overflow: hidden; text-overflow: ellipsis; }
.map-tip__price { display: block; font-family: var(--f-mono); font-size: 12.5px; font-weight: 700; }
.map-tip__price.pend { color: var(--tip-warn); }
.map-tip__src { font-size: 9.5px; font-weight: 400; opacity: .6; letter-spacing: .06em;
  text-transform: uppercase; }

/* AutoPrice (events page): VS-link tag on rows, the review banner + flag pill, and the
   live status strip that narrates each TM/VividSeats fetch during a run */
.vs-tag { display: inline-flex; align-items: center; font-family: var(--f-mono); font-size: 9.5px;
  font-weight: 700; letter-spacing: .06em; padding: 2px 6px; border-radius: 5px;
  border: 1px solid var(--line-strong); color: var(--ink-faint); background: var(--surface);
  vertical-align: middle; cursor: default; }
.vs-tag.on { color: var(--sonar-deep); border-color: var(--sonar-dim); background: var(--sonar-dim);
             cursor: pointer; }
.vs-tag.on:hover { filter: brightness(.93); }
/* Login glyph: reuses .vs-tag / .vs-tag.on colours (green when ON), but is always clickable
   and holds a 12px line-icon instead of the 2-char VS text (svg.ico defaults to 18px). */
.vs-tag.login-tag { cursor: pointer; padding: 2px 5px; }
.vs-tag.login-tag .ico { width: 12px; height: 12px; }
/* Monitor-Mode glyph: the literal "M", same green-when-ON / white-when-OFF treatment as the
   login + queue tags. Fixed min-width so a one-character label still reads as a button. */
.vs-tag.monitor-tag { cursor: pointer; padding: 2px 5px; min-width: 18px; justify-content: center; }
/* Turbo glyph: the literal "T" (extra cold-snapshot polling), same treatment as "M". */
.vs-tag.turbo-tag { cursor: pointer; padding: 2px 5px; min-width: 18px; justify-content: center; }
/* Auto-Turbo: lit (Turbo is running) but only for the hub's after-restock window, not the T flag.
   The dashed darker border tells it apart from a T the operator switched on. */
.vs-tag.turbo-tag.on.auto { border-style: dashed; border-color: var(--sonar-deep); }
.pill.ap-flag { cursor: pointer; }
.pill.ap-flag:hover { filter: brightness(.94); }
/* Claude's price filters on an event (claude_event_svc.price_marks): "✦ 12 buy" / "✦ no buy" */
.pill.cp-flag { cursor: pointer; font-weight: 600; }
.pill.cp-flag:hover { filter: brightness(.94); }
/* …and the same note at the top of Curate & filter */
.cur-claude { margin: 0 0 14px; padding: 9px 14px; border: 1px solid var(--sonar-dim); border-left: 3px solid var(--sonar);
  border-radius: var(--radius-sm); background: var(--sonar-dim); color: var(--ink-dim); font-size: 12.5px; line-height: 1.45; }
.cur-claude b { color: var(--sonar-deep); }
.cur-claude.is-none { border-color: var(--amber-glow); border-left-color: var(--amber); background: var(--amber-dim); }
.cur-claude.is-none b { color: var(--amber); }
.cur-claude.is-failed { border-color: var(--coral-glow); border-left-color: var(--coral); background: var(--coral-dim); }
.cur-claude.is-failed b { color: var(--coral); }
.cur-claude__when { color: var(--ink-faint); font-size: 11.5px; }
.cur-claude__sum { margin-top: 4px; color: var(--ink-dim); }

/* =========================================================================================
   EVENTS TABLE — fixed geometry
   The complaint this solves: a long event title used to widen the Event column, which shoved
   every other cell sideways, and the Filters cell wrapped onto a second line whenever a row had
   a few extra pills — so two adjacent rows never lined up.

   The fix is structural, not cosmetic:
     · table-layout: fixed + <colgroup> widths  -> column x-positions are decided by the CSS,
       never by the content, so no row can move another row's controls.
     · both title lines clamp to ONE line with an ellipsis -> every name block is exactly 2 lines.
     · the pill strip is nowrap and scrolls inside its own column instead of wrapping.
   Result: identical row height and identical control positions for every event.
   ========================================================================================= */
/* min-width, with the .table-wrap scroller around it, is what keeps the ELASTIC column honest.
   The eight fixed columns come to ~920px; on a 1280-wide window the panel is ~990px, so without a
   floor the Event name gets whatever is left — which the ninth column (ACO (Cart Holds)) took down
   to ~50px, i.e. "A…". A fixed table does not refuse to shrink, it just crushes the one auto
   column. The floor gives the name ~180px and lets .table-wrap scroll the last few pixels instead,
   which is exactly what that wrapper's overflow-x is for. Above ~1300 nothing scrolls at all, and
   below 640 the phone card layout takes over and this rule stops applying. */
.ev-table { table-layout: fixed; width: 100%; min-width: 1100px; }
.ev-c-sel   { width: 38px; }
.ev-c-main  { width: auto; }        /* the only elastic column */
.ev-c-aco   { width: 78px; }
/* ACO (Cart Holds) — its own column beside ACO. Its header is the widest thing in it, and it is
   the ONE header allowed to wrap onto a second line (table.data th is nowrap): wrapping is what
   lets the column stay near its sibling's width instead of being sized by a 16-character label. */
.ev-c-acoh  { width: 88px; }
.ev-c-qty   { width: 86px; }
.ev-c-offer { width: 118px; }
.ev-c-flt   { width: 188px; }
.ev-c-gates { width: 160px; }
.ev-c-act   { width: 188px; }   /* 5 aligned buttons: sales, explore, refetch, curate, archive */

.ev-table td { vertical-align: middle; }
.ev-table th.ev-sel, .ev-table td.ev-sel { text-align: center; padding-left: 8px; padding-right: 8px; }

/* name block — two clamped lines, so row height never depends on the title */
.ev-main { min-width: 0; }
.ev-main .t-primary {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-weight: 550; line-height: 1.35;
}
.ev-title-link { display: block; text-decoration: none; }
.ev-title-link:hover { color: var(--accent); }
.ev-meta {
  font-size: 11px; line-height: 1.45;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ev-meta__hi { color: var(--ink-dim); }
.ev-claude { color: var(--accent-deep); font-weight: 600; cursor: help; }

/* controls sized to their columns so they can't spill */
.ev-aco .toggle, .ev-acoh .toggle { width: 100%; justify-content: center; }
.ev-table th.ev-acoh-h { white-space: normal; line-height: 1.25; padding-left: 8px; padding-right: 8px; }
.ev-qty .inp-mini { width: 100%; }
.ev-offer .inp-mini { width: 100%; }

/* pill strip — one line, scrolls in place, never wraps the row taller */
.ev-flt { min-width: 0; }
.filt-cell {
  display: flex; align-items: center; gap: 5px;
  flex-wrap: nowrap; overflow-x: auto; min-width: 0;
  scrollbar-width: none; -ms-overflow-style: none;
}
.filt-cell::-webkit-scrollbar { display: none; }
.filt-cell > * { flex: none; }
.ev-allsec { font-size: 11px; }

/* gates + actions — fixed lanes, so the glyphs are at the same x on every single row */
.ev-table td.ev-gates, .ev-table td.ev-act { padding-left: 8px; padding-right: 8px; }
.ev-gates { white-space: nowrap; }
.ev-gates > * { margin-right: 4px; vertical-align: middle; }
.ev-gates > *:last-child { margin-right: 0; }
.ev-act { white-space: nowrap; text-align: right; }
.ev-act > .icon-btn {
  width: 28px; height: 28px; margin-left: 5px; padding: 4px;
  align-items: center; justify-content: center; vertical-align: middle;
}
.ev-act > .icon-btn:first-child { margin-left: 0; }

.ev-pagination {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; border-top: 1px solid var(--line-soft); background: var(--surface);
}
.ev-pagination__actions { display: flex; align-items: center; gap: 10px; font-size: 11px; }

@media (min-width: 641px) and (max-width: 880px) {
  .ev-c-act { width: 248px; }
}

/* =========================================================================================
   EVENT SALES INTELLIGENCE — live Automatiq DataIQ lookup from each Events row
   ========================================================================================= */
.ev-sales-btn {
  min-width: 22px; justify-content: center;
  font-family: var(--f-mono); font-size: 10px; font-weight: 700; line-height: 14px;
  color: var(--accent-deep); border-color: var(--accent-glow); background: var(--accent-dim);
}
.ev-sales-btn:hover { color: var(--accent); border-color: var(--accent); }

.modal.wide.event-sales {
  max-width: min(1180px, calc(100vw - 36px)); max-height: 90vh;
  overflow: hidden;
}
.es-modal-head { align-items: flex-start; padding: 18px 22px 16px; }
.es-identity { min-width: 0; }
.es-kicker {
  display: block; margin-bottom: 4px;
  font-family: var(--f-mono); font-size: 9px; font-weight: 600; letter-spacing: 1.2px;
  text-transform: uppercase; color: var(--accent-deep);
}
.es-modal-head h2 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 18px; }
.es-meta { margin: 4px 0 0; color: var(--ink-faint); font-family: var(--f-mono); font-size: 10.5px; }
.es-modal-body { padding: 18px 22px 20px; }
.es-modal-foot { padding: 12px 22px; }
.es-live-note {
  display: inline-flex; align-items: center; gap: 7px; margin-right: auto;
  color: var(--ink-faint); font-size: 11px;
}
.es-live-note .dot { background: var(--sonar); box-shadow: 0 0 0 3px var(--sonar-dim); }

.es-match {
  min-height: 24px; display: flex; align-items: center; gap: 9px; margin-bottom: 13px;
  color: var(--ink-faint); font-size: 11px;
}
.es-match:empty { min-height: 0; margin: 0; }
.es-match-chip {
  flex: none; display: inline-flex; align-items: center; padding: 4px 8px;
  border: 1px solid var(--line); border-radius: 99px;
  font-family: var(--f-mono); font-size: 9px; font-weight: 600; letter-spacing: .3px;
}
.es-match-chip.is-exact { color: var(--sonar-deep); border-color: var(--sonar-glow); background: var(--sonar-dim); }
.es-match-chip.is-fallback { color: var(--amber); border-color: var(--amber-glow); background: var(--amber-dim); }
.es-match-copy { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.es-status {
  min-height: 94px; display: flex; align-items: center; justify-content: center;
  margin: 8px 0; padding: 20px; border: 1px dashed var(--line-strong); border-radius: var(--radius);
  background: var(--surface-2); color: var(--ink-dim); text-align: center; font-size: 13px;
}
.es-status[hidden] { display: none; }
.es-status.is-loading::before {
  content: ""; width: 15px; height: 15px; margin-right: 9px; border: 2px solid var(--line-strong);
  border-top-color: var(--accent); border-radius: 50%; animation: spin .7s linear infinite;
}
.es-status.is-error { color: var(--coral); border-color: var(--coral-glow); background: var(--coral-dim); }

.es-session-editor {
  max-width: 820px; margin: 0 auto 16px; padding: 15px 16px;
  border: 1px solid var(--accent-glow); border-radius: var(--radius);
  background: linear-gradient(135deg, var(--accent-dim), var(--surface-2));
  box-shadow: 0 10px 26px color-mix(in srgb, var(--accent) 7%, transparent);
}
.es-session-editor[hidden] { display: none; }
.es-session-editor__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  margin-bottom: 12px;
}
.es-session-editor__eyebrow {
  display: block; margin-bottom: 3px; color: var(--accent-deep);
  font-family: var(--f-mono); font-size: 8.5px; font-weight: 650;
  letter-spacing: .7px; text-transform: uppercase;
}
.es-session-editor__head h3 { margin: 0; color: var(--ink); font-size: 14px; }
.es-session-editor__status {
  flex: none; padding: 4px 8px; border: 1px solid var(--line); border-radius: 99px;
  background: var(--surface); color: var(--ink-faint); font-family: var(--f-mono); font-size: 9px;
}
.es-session-editor__status.is-ready {
  color: var(--sonar-deep); border-color: var(--sonar-glow); background: var(--sonar-dim);
}
.es-session-editor__status.is-managed {
  color: var(--amber); border-color: var(--amber-glow); background: var(--amber-dim);
}
.es-session-editor__form { display: flex; flex-direction: column; gap: 7px; }
.es-session-editor__form > label {
  color: var(--ink-faint); font-family: var(--f-mono); font-size: 9px;
  font-weight: 600; letter-spacing: .45px; text-transform: uppercase;
}
.es-session-editor__form textarea {
  width: 100%; min-height: 72px; resize: vertical; padding: 10px 11px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink); font-family: var(--f-mono);
  font-size: 10.5px; line-height: 1.5;
}
.es-session-editor__form textarea:focus {
  border-color: var(--accent); outline: 2px solid var(--accent-dim); outline-offset: 1px;
}
.es-session-editor__help { margin: 0; color: var(--ink-faint); font-size: 10px; line-height: 1.45; }
.es-session-editor__help code { color: var(--accent-deep); font-family: var(--f-mono); }
.es-session-editor__error { margin: 2px 0 0; color: var(--coral); font-size: 10.5px; }
.es-session-editor__error[hidden] { display: none; }
.es-session-editor__actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 3px; }

.es-resolution {
  max-width: 820px; margin: 4px auto; padding: 2px 0 10px;
}
.es-resolution[hidden] { display: none; }
.es-resolution__title { margin: 0; color: var(--ink); font-size: 15px; }
.es-resolution__title:focus { outline: none; }
.es-resolution__intro { margin: 5px 0 14px; color: var(--ink-faint); font-size: 11px; }
.es-candidates { display: flex; flex-direction: column; gap: 7px; }
.es-candidate {
  width: 100%; display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px 16px; padding: 11px 13px; cursor: pointer; text-align: left;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2);
  color: var(--ink); transition: border-color .12s, background .12s, transform .12s;
}
.es-candidate:hover { border-color: var(--accent-glow); background: var(--accent-dim); transform: translateY(-1px); }
.es-candidate:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.es-candidate__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
.es-candidate__meta { grid-column: 1; color: var(--ink-faint); font-size: 10px; }
.es-candidate__basis {
  grid-column: 2; grid-row: 1 / span 2; align-self: center; color: var(--accent-deep);
  font-family: var(--f-mono); font-size: 8.5px; font-weight: 600; letter-spacing: .25px;
}
.es-manual-search {
  display: grid; grid-template-columns: minmax(220px, 1fr) auto auto; align-items: end;
  gap: 10px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line-soft);
}
.es-manual-search__field { display: flex; flex-direction: column; gap: 5px; }
.es-manual-search__field > span {
  color: var(--ink-faint); font-family: var(--f-mono); font-size: 8.5px;
  font-weight: 600; letter-spacing: .5px; text-transform: uppercase;
}
.es-manual-search__field input { width: 100%; }
.es-manual-search__date { align-self: center; color: var(--ink-faint); font-family: var(--f-mono); font-size: 9px; }

.es-metrics { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; }
.es-metric {
  min-width: 0; display: flex; flex-direction: column; padding: 12px 13px 11px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2);
}
.es-metric__label {
  min-height: 24px; color: var(--ink-faint); font-family: var(--f-mono); font-size: 9px;
  font-weight: 600; letter-spacing: .65px; line-height: 1.3; text-transform: uppercase;
}
.es-metric__value {
  margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--ink); font-family: var(--f-mono); font-size: clamp(16px, 1.5vw, 21px);
  font-variant-numeric: tabular-nums; letter-spacing: -.55px;
}
.es-metric__note { margin-top: 4px; color: var(--ink-faint); font-size: 9.5px; }
.es-metric--windows .es-metric__label { min-height: 0; }
.es-sales-windows {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: 7px 0 0; padding: 0;
}
.es-sales-window {
  min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 2px;
  border-left: 1px solid var(--line-soft);
}
.es-sales-window:first-child { border-left: 0; }
.es-sales-window__period {
  color: var(--ink-faint); font-family: var(--f-mono); font-size: 8px;
  font-weight: 600; letter-spacing: .35px; text-transform: uppercase;
}
.es-sales-window__value {
  margin: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  color: var(--ink); font-family: var(--f-mono); font-size: 15px; font-weight: 700;
  font-variant-numeric: tabular-nums; line-height: 1.2;
}

.es-tabs {
  display: flex; gap: 3px; margin: 18px 0 14px; padding: 3px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--surface-2);
}
.es-tab {
  flex: 1; cursor: pointer; border: 0; border-radius: 5px; padding: 8px 12px;
  background: transparent; color: var(--ink-faint); font-family: var(--f-body); font-size: 11.5px;
  font-weight: 600; transition: color .12s, background .12s, box-shadow .12s;
}
.es-tab:hover { color: var(--ink); }
.es-tab.active { color: var(--accent-deep); background: var(--surface); box-shadow: 0 1px 3px var(--line); }
.es-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.es-tab-panel[hidden] { display: none; }

#eventSalesIntelligence { display: flex; flex-direction: column; gap: 14px; }
.es-intel-hero {
  display: grid; grid-template-columns: 174px minmax(0, 1fr); overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  box-shadow: inset 3px 0 0 var(--accent);
}
.es-intel-score {
  display: flex; flex-direction: column; justify-content: center; padding: 20px 22px;
  border-right: 1px solid var(--line-soft); background: var(--surface-2);
}
.es-intel-score__label, .es-intel-stat__label {
  color: var(--ink-faint); font-family: var(--f-mono); font-size: 8.5px; font-weight: 600;
  letter-spacing: .55px; text-transform: uppercase;
}
.es-intel-score__value {
  margin-top: 4px; color: var(--accent-deep); font-family: var(--f-mono); font-size: 35px;
  font-variant-numeric: tabular-nums; letter-spacing: -1.4px; line-height: 1;
}
.es-intel-score__scale { margin-top: 5px; color: var(--ink-faint); font-size: 9.5px; }
.es-intel-hero__copy { min-width: 0; padding: 18px 20px; }
.es-intel-hero__title { margin: 3px 0 2px; color: var(--ink); font-size: 19px; }
.es-intel-confidence { margin: 0; color: var(--accent-deep); font-family: var(--f-mono); font-size: 10px; font-weight: 600; }
.es-intel-hero__note { max-width: 720px; margin: 9px 0 0; color: var(--ink-dim); font-size: 11px; line-height: 1.5; }
.es-intel-stats { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 7px; }
.es-intel-stat {
  min-width: 0; display: flex; flex-direction: column; gap: 3px; padding: 10px 11px;
  border: 1px solid var(--line-soft); border-radius: var(--radius-sm); background: var(--surface-2);
}
.es-intel-stat__value {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink);
  font-family: var(--f-mono); font-size: 15px; font-variant-numeric: tabular-nums;
}
.es-intel-stat__note { color: var(--ink-faint); font-size: 8.5px; line-height: 1.3; }
.es-intel-block, .es-intel-table-card {
  min-width: 0; padding: 14px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
.es-intel-section-head { margin-bottom: 12px; }
.es-factor-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.es-factor {
  min-width: 0; padding: 12px; border: 1px solid var(--line-soft); border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.es-factor.is-unavailable { opacity: .72; }
.es-factor__head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.es-factor__label { color: var(--ink); font-size: 11.5px; font-weight: 700; }
.es-factor__score { color: var(--accent-deep); font-family: var(--f-mono); font-size: 9.5px; white-space: nowrap; }
.es-factor__meter { height: 4px; margin: 9px 0; overflow: hidden; border-radius: 99px; background: var(--surface-3); }
.es-factor__fill { display: block; height: 100%; border-radius: inherit; background: var(--accent); }
.es-factor__summary { min-height: 31px; margin: 0; color: var(--ink-dim); font-size: 10px; line-height: 1.45; }
.es-factor__weight { display: block; margin-top: 8px; color: var(--ink-faint); font-family: var(--f-mono); font-size: 8px; }
.es-factor__evidence { margin: 9px 0 0; padding: 8px 0 0 15px; border-top: 1px solid var(--line-soft); color: var(--ink-faint); font-size: 9px; line-height: 1.45; }
.es-signal-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; }
.es-signal-card { min-width: 0; padding: 13px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.es-signal-card.is-positive { border-left: 3px solid var(--sonar); }
.es-signal-card.is-risk { border-left: 3px solid var(--amber); }
.es-signal-card h3 { margin: 0 0 8px; color: var(--ink); font-size: 12px; }
.es-signal-list { margin: 0; padding-left: 16px; color: var(--ink-dim); font-size: 10px; line-height: 1.55; }
.es-signal-list li + li { margin-top: 4px; }
.es-signal-empty { margin: 0; color: var(--ink-faint); font-size: 10px; }
.es-intel-table-wrap { max-height: 380px; }
.es-intel-table { min-width: 1080px; }
.es-intel-table th.es-num { text-align: right; }
.es-intel-section strong, .es-intel-section span { display: block; }
.es-intel-section strong { color: var(--ink); }
.es-intel-section span { margin-top: 2px; color: var(--ink-faint); font-size: 8.5px; }
.es-intel-profit.is-positive { color: var(--sonar-deep); font-weight: 700; }
.es-intel-profit.is-negative { color: var(--coral); font-weight: 700; }
.es-intel-evidence strong, .es-intel-evidence span { display: block; }
.es-intel-evidence strong { color: var(--ink-dim); font-weight: 600; }
.es-intel-evidence span { margin-top: 2px; color: var(--ink-faint); font-size: 8.5px; }
.es-source-list { overflow: hidden; border: 1px solid var(--line-soft); border-radius: var(--radius-sm); }
.es-source {
  display: grid; grid-template-columns: minmax(150px, .8fr) 94px minmax(190px, 1fr) minmax(220px, 1.15fr);
  align-items: center; gap: 10px; min-height: 39px; padding: 7px 10px;
  border-top: 1px solid var(--line-soft); font-size: 9.5px;
}
.es-source:first-child { border-top: 0; }
.es-source__identity { min-width: 0; display: flex; align-items: center; gap: 7px; }
.es-source__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); font-size: 10.5px; }
.es-source__dot { width: 6px; height: 6px; flex: none; border-radius: 50%; background: var(--ink-faint); }
.es-source__dot.is-ready { background: var(--sonar); }
.es-source__dot.is-review { background: var(--amber); }
.es-source__status { color: var(--ink-faint); font-family: var(--f-mono); text-transform: uppercase; }
.es-source__detail { color: var(--ink-dim); }
.es-source__scope { color: var(--ink-faint); }
.es-intel-disclaimer {
  margin: 0; padding: 10px 12px; border-radius: var(--radius-sm); background: var(--surface-2);
  color: var(--ink-faint); font-size: 9.5px; line-height: 1.45; text-align: center;
}

.es-section-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 10px; }
.es-section-head h3 { margin: 0; color: var(--ink); font-size: 13px; line-height: 1.35; }
.es-section-head p { margin: 3px 0 0; color: var(--ink-faint); font-size: 10.5px; }
.es-count-chip {
  flex: none; padding: 4px 8px; border-radius: 99px; background: var(--surface-2);
  color: var(--ink-faint); font-family: var(--f-mono); font-size: 9.5px;
}

#eventSalesBreakdown { overflow-x: auto; }
.es-tree-head, .es-tree-row {
  min-width: 680px; display: grid; grid-template-columns: minmax(250px, 1fr) 92px 132px 112px;
  align-items: center; column-gap: 12px;
}
.es-tree-head {
  padding: 8px 12px; border: 1px solid var(--line); border-radius: 6px 6px 0 0;
  background: var(--surface-2); color: var(--ink-faint); font-family: var(--f-mono);
  font-size: 8.5px; font-weight: 600; letter-spacing: .55px; text-transform: uppercase;
}
.es-tree-head span:not(:first-child) { text-align: right; }
.es-tree-rows { min-width: 680px; border: 1px solid var(--line); border-top: 0; border-radius: 0 0 6px 6px; overflow: hidden; }
.es-tree-row { min-height: 37px; padding: 6px 12px; border-top: 1px solid var(--line-soft); font-size: 11.5px; }
.es-tree-rows > .es-tree-row:first-child,
.es-tree-rows > .es-tree-node:first-child > .es-tree-summary > .es-tree-row { border-top: 0; }
.es-tree-row:hover { background: var(--surface-2); }
.es-tree-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.es-depth-1 .es-tree-label { padding-left: 21px; }
.es-depth-2 .es-tree-label { padding-left: 42px; font-family: var(--f-mono); font-size: 10.5px; font-weight: 500; }
.es-tree-number { text-align: right; font-family: var(--f-mono); font-size: 10.5px; font-variant-numeric: tabular-nums; }
.es-tree-count { margin-left: 8px; color: var(--ink-faint); font-size: 9px; font-weight: 400; }
.es-tree-summary { display: block; cursor: pointer; list-style: none; }
.es-tree-summary::-webkit-details-marker { display: none; }
.es-tree-summary .es-tree-label::before {
  content: "›"; display: inline-block; width: 14px; margin-right: 2px; color: var(--ink-faint);
  font-family: var(--f-mono); font-size: 15px; line-height: 1; transition: transform .12s;
}
.es-tree-node[open] > .es-tree-summary .es-tree-label::before { transform: rotate(90deg); }
.es-tree-node[open] > .es-tree-summary > .es-tree-row { background: var(--accent-dim); }
.es-tree-branch { background: color-mix(in srgb, var(--surface-2) 55%, var(--surface)); }
.es-inline-load, .es-inline-error, .es-empty, .es-truncated {
  padding: 13px 15px; color: var(--ink-faint); font-size: 10.5px; text-align: center;
}
.es-inline-error { display: flex; align-items: center; justify-content: center; gap: 10px; color: var(--coral); }
.es-truncated { color: var(--amber); }

.es-chart-card, .es-market-card {
  min-width: 0; padding: 14px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface);
}
.es-chart-scroll { width: 100%; overflow-x: auto; overflow-y: hidden; }
.es-sales-chart { display: block; max-width: none; height: 232px; overflow: visible; }
.es-chart-grid { stroke: var(--line-soft); stroke-width: 1; }
.es-chart-axis-line { stroke: var(--line); stroke-width: 1; }
.es-chart-axis-tick, .es-chart-axis-title {
  fill: var(--ink-faint); font-family: var(--f-mono); font-size: 8.5px;
}
.es-chart-axis-title { font-size: 9px; font-weight: 600; letter-spacing: .25px; }
.es-chart-bar { fill: var(--accent-dim); stroke: var(--accent-glow); stroke-width: 1; }
.es-chart-line { stroke: var(--sonar); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.es-chart-dot { fill: var(--surface); stroke: var(--sonar); stroke-width: 2; }
.es-chart-label { fill: var(--ink-faint); font-family: var(--f-mono); font-size: 9px; }
.es-market-grid { display: grid; grid-template-columns: minmax(260px, .72fr) minmax(0, 1.45fr); gap: 10px; align-items: start; }
.es-exchanges { display: flex; flex-direction: column; gap: 11px; }
.es-exchange__line { display: flex; justify-content: space-between; gap: 10px; margin-bottom: 5px; font-size: 10.5px; }
.es-exchange__line strong { font-size: 11px; }
.es-exchange__track { height: 5px; overflow: hidden; border-radius: 99px; background: var(--surface-3); }
.es-exchange__fill { display: block; height: 100%; border-radius: inherit; background: var(--accent); }

.es-table-wrap { max-height: 300px; overflow: auto; margin-top: 12px; border: 1px solid var(--line); border-radius: 6px; }
.es-table { width: 100%; border-collapse: collapse; font-size: 10.5px; white-space: nowrap; }
.es-table th {
  position: sticky; top: 0; z-index: 1; padding: 7px 9px; background: var(--surface-2);
  border-bottom: 1px solid var(--line); color: var(--ink-faint); font-family: var(--f-mono);
  font-size: 8.5px; font-weight: 600; letter-spacing: .4px; text-align: left; text-transform: uppercase;
}
.es-table td { padding: 7px 9px; border-bottom: 1px solid var(--line-soft); color: var(--ink-dim); }
.es-table tbody tr:last-child td { border-bottom: 0; }
.es-table tbody tr:hover td { background: var(--surface-2); }
.es-table .es-num { text-align: right; font-family: var(--f-mono); font-variant-numeric: tabular-nums; }
.es-fetched { margin: 12px 2px 0; color: var(--ink-faint); font-family: var(--f-mono); font-size: 9px; text-align: right; }

@media (max-width: 900px) {
  .es-metrics { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .es-market-grid { grid-template-columns: 1fr; }
  .es-intel-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .es-factor-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .es-source { grid-template-columns: minmax(145px, .8fr) 86px minmax(0, 1.5fr); }
  .es-source__scope { grid-column: 3; }
}
@media (max-width: 640px) {
  .modal.wide.event-sales { max-width: 100%; max-height: 92vh; }
  .es-modal-head { padding: 18px 18px 13px; }
  .es-modal-body { padding: 14px 14px 18px; }
  .es-modal-foot { padding-left: 14px; padding-right: 14px; }
  .es-live-note { justify-content: center; margin: 2px 0 5px; }
  .es-session-editor { padding: 14px; }
  .es-session-editor__head { flex-direction: column; gap: 8px; }
  .es-session-editor__status { align-self: flex-start; }
  .es-session-editor__actions { flex-direction: column-reverse; }
  .es-session-editor__actions .btn { width: 100%; }
  .es-match { align-items: flex-start; flex-direction: column; }
  .es-match-copy { max-width: 100%; }
  .es-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .es-metric:last-child { grid-column: 1 / -1; }
  .es-metric__value { font-size: 18px; }
  .es-tabs { overflow-x: auto; }
  .es-tab { flex: none; min-width: 132px; }
  .es-intel-hero { grid-template-columns: 1fr; }
  .es-intel-score { border-right: 0; border-bottom: 1px solid var(--line-soft); }
  .es-intel-score__value { font-size: 29px; }
  .es-intel-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .es-factor-grid, .es-signal-grid { grid-template-columns: 1fr; }
  .es-source { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 9px; padding: 9px 10px; }
  .es-source__detail, .es-source__scope { grid-column: 1 / -1; }
  .es-candidate { grid-template-columns: 1fr; }
  .es-candidate__basis { grid-column: 1; grid-row: auto; }
  .es-manual-search { grid-template-columns: 1fr; }
  .es-manual-search__date { justify-self: start; }
  .es-sales-chart { height: 210px; }
}

/* --- panel head: two-row toolbar (six chips + sort + search will not share one line) --- */
.panel__head.ev-head { display: block; padding: 13px 16px 11px; }
.ev-head__r1 { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ev-head__r1 h2 { margin-right: auto; }
.ev-head__r2 {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--line-soft);
}
/* The ONLY select-all: it sits in the panel head rather than the <thead>, because the phone
   table->card layout clips a <thead> — which is what the old phone-only #selAllMob stand-in bar
   existed to work around. One control, every width, no stand-in to keep in sync. */
.ev-selall {
  display: inline-flex; align-items: center; gap: 8px; margin: 0; cursor: pointer;
  font-size: 12px; color: var(--ink-dim); white-space: nowrap;
}
.ev-selall input { margin: 0; }
.flt-chips__sep { width: 1px; height: 18px; background: var(--line); flex: none; }
.ap-review { display: flex; align-items: center; gap: 9px; margin: 0 0 14px; padding: 9px 14px;
  border: 1px solid var(--amber-glow); border-left: 3px solid var(--amber); border-radius: var(--radius-sm);
  background: var(--amber-dim); color: var(--ink-dim); font-size: 12.5px; }
.ap-review .ico { color: var(--amber); flex: none; }
.ap-review b { color: var(--amber); }
.ap-status { display: flex; align-items: center; gap: 10px; margin: 0 0 14px; padding: 9px 14px;
  border: 1px solid var(--line-soft); border-left: 3px solid var(--accent); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--ink-dim); font-size: 12.5px; }
.ap-status #apStatusStep { margin-left: auto; font-size: 11px; color: var(--ink-faint); }

/* events attention filters (chips beside the search box) */
.flt-chips { display: inline-flex; gap: 6px; align-items: center; }
.ev-head__r2 > .flt-chips {
  flex: 1 1 auto; min-width: 0; overflow-x: auto;
  scrollbar-width: none; -ms-overflow-style: none; padding-bottom: 2px;
}
.ev-head__r2 > .flt-chips::-webkit-scrollbar { display: none; }
.ev-head__r2 > .flt-chips .flt-chip { flex: none; }
.flt-chip { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px;
  padding: 4px 10px; border-radius: 999px; border: 1px solid var(--line-strong);
  background: var(--surface); color: var(--ink-dim); cursor: pointer; white-space: nowrap;
  transition: background .12s, color .12s, border-color .12s; }
.flt-chip .ico { width: 13px; height: 13px; }
.flt-chip:hover { background: var(--surface-2); color: var(--ink); }
.flt-chip.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.flt-chip.on .ico { color: #fff; }

/* Cards page filter bar — labelled rows of .flt-chip groups plus the narrowing dropdowns. Sits at
   the top of the Stored-cards panel body (not the summary), so clicking it never toggles the
   <details>. The chips reuse the Events page's .flt-chip so "ticked" looks identical on both. */
.cards-flt { display: flex; flex-direction: column; gap: 7px; padding: 10px 14px;
  border-bottom: 1px solid var(--line-soft); background: var(--surface); }
.cards-flt__row { display: flex; align-items: flex-start; gap: 9px; min-width: 0; }
.cards-flt__lbl { flex: none; width: 56px; padding-top: 5px; font-family: var(--f-mono);
  font-size: 10px; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); }
/* Chips WRAP here (the Events bar has three and lives on one line; this one has sixteen). */
.cards-flt .flt-chips { flex: 1 1 auto; flex-wrap: wrap; min-width: 0; }
.cards-flt .flt-chip { padding: 3px 9px; font-size: 11px; }
.cards-flt .flt-chip b.n { font-family: var(--f-mono); font-size: 10px; font-weight: 700; opacity: .7; }
/* A chip matching nothing right now is dimmed, never hidden: "0 declined" is an answer, and a bar
   whose chips appear and disappear between page loads can't be learned. Still clickable. */
.cards-flt .flt-chip.zero { opacity: .45; }
.cards-flt .flt-chip.on.zero { opacity: 1; }
.cards-flt__row--sel { flex-wrap: wrap; align-items: center; }
.cards-flt__row--sel select { flex: 0 1 186px; min-width: 0; padding-right: 26px;
  font-family: var(--f-mono); font-size: 12px; padding-top: 5px; padding-bottom: 5px; }
.cards-flt__row--sel select:disabled { opacity: .5; }
.cards-flt__row--sel .cbx { flex: 0 1 186px; min-width: 0; }
.cards-flt__row--sel .toggle { flex: none; cursor: pointer; }
.cards-flt__row--sel .toggle input { width: auto; accent-color: var(--accent); }
.cards-flt__row--sel .btn-mini { margin-left: auto; }

/* ---- .cbx — the narrowing combobox ------------------------------------------------------------
   Stands in for a <select> whose option list is unbounded: the bound-account one carries ~2,000
   distinct accounts, and a native popup that long is slow to open and impossible to scan. The
   button shows the current pick; the popup filters as you type and paints only the matches. Our own
   DOM, so it is styled here rather than by the OS, and it opens in one frame however big the pool
   gets (cards.js renders at most CBX_MAX rows). */
.cbx { position: relative; }
.cbx__btn { display: flex; align-items: center; gap: 6px; width: 100%; cursor: pointer;
  font-family: var(--f-mono); font-size: 12px; color: var(--ink); text-align: left;
  background: var(--surface-3); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); padding: 5px 8px; transition: border-color .14s, box-shadow .14s; }
.cbx__btn:hover { border-color: var(--line-strong); background: var(--surface-2); }
.cbx__btn:focus-visible { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }
.cbx__val { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cbx__n { flex: none; font-size: 10px; font-weight: 700; color: var(--ink-faint); }
.cbx__caret { flex: none; color: var(--ink-faint); font-size: 9px; line-height: 1; }
/* An active narrowing has to be visible without reading the label — same signal as a ticked chip. */
.cbx.on .cbx__btn { background: var(--accent); border-color: var(--accent); color: #fff; }
.cbx.on .cbx__n, .cbx.on .cbx__caret { color: rgba(255, 255, 255, .75); }
.cbx.is-empty .cbx__btn { opacity: .5; pointer-events: none; }
.cbx__pop { position: absolute; z-index: 40; top: calc(100% + 4px); left: 0; min-width: 100%;
  max-width: 340px; background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 10px 30px rgba(17, 27, 45, .14), 0 1px 2px rgba(16, 24, 40, .06);
  padding: 6px; display: flex; flex-direction: column; gap: 5px; }
.cbx__pop[hidden] { display: none; }
.cbx__q { font-family: var(--f-mono); font-size: 12px; padding: 5px 8px; }
.cbx__list { max-height: 260px; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; }
.cbx__opt { display: flex; align-items: center; gap: 8px; cursor: pointer; border: 0;
  background: none; text-align: left; font-family: var(--f-mono); font-size: 12px;
  color: var(--ink-dim); padding: 5px 7px; border-radius: 4px; width: 100%; }
.cbx__opt:hover, .cbx__opt.active { background: var(--surface-2); color: var(--ink); }
.cbx__opt.sel { color: var(--accent-deep); font-weight: 600; }
.cbx__opt .t { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cbx__opt .n { flex: none; font-size: 10px; color: var(--ink-faint); font-weight: 700; }
.cbx__none { padding: 7px; font-size: 11.5px; color: var(--ink-faint); }
/* "showing the first N of M" — a list that silently stops at 60 reads as "there are only 60". */
.cbx__more { padding: 5px 7px; font-size: 10.5px; color: var(--ink-faint); border-top: 1px solid var(--line-soft); }

/* ---- the windowed stored-cards table ----------------------------------------------------------
   cards.js paints only the rows scrolled into view, between two spacer rows that carry the height
   of everything above and below. That arithmetic needs every row to be the SAME height, which is
   what the fixed layout below buys: one line per cell, long values ellipsized with the full text in
   a title. (The row height is still measured from the live table rather than assumed here, so a
   later font/padding change corrects itself.) */
.cards-scroll { max-height: calc(100vh - 268px); min-height: 220px; overflow-y: auto;
  overscroll-behavior: contain; }
/* min-width is what `no-cards` promises on a phone: the table keeps its columns and the wrapper
   scrolls sideways, rather than squeezing ten columns into 360px. */
#cardsTable { table-layout: fixed; min-width: 940px; }
#cardsTable th, #cardsTable td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#cardsTable td { padding-top: 9px; padding-bottom: 9px; }
/* The header stays put while the rows stream under it — with 3,000 cards it is otherwise gone
   after the first flick, and the select-all checkbox with it. A collapsed border does not travel
   with a sticky cell, so the rule under the header is painted as an inset shadow instead. */
#cardsTable thead th { position: sticky; top: 0; z-index: 3; background: var(--surface);
  box-shadow: inset 0 -1px 0 var(--line); }
/* The spacers ARE the scroll height. They must never take a border, a hover tint or padding, or
   the table grows by 2px per render and the scrollbar walks. */
#cardsTable tr.cards-spacer td { padding: 0; border: 0; }
#cardsTable tbody tr.cards-spacer:hover { background: none; }
/* .inp-mini's own padding loses to the base `input[type=text]` rule on specificity, which made the
   linked-account box 38px tall and the whole row 57px. An id-scoped rule wins it back — worth ~12px
   a row, which is two more cards on screen. */
#cardsTable td .inp-mini { width: 100%; padding: 4px 7px; font-size: 12px; }
/* The action column holds three icon buttons in 7% of the table — tighten them so a narrow panel
   doesn't clip the delete. */
#cardsTable td.right { text-align: right; padding-left: 4px; padding-right: 8px; }
#cardsTable td.right .icon-btn { padding: 3px 4px; }
/* The status cell carries a pill AND a history chip; the bound-to cell an email AND a wallet pill.
   Both would wrap to a second line at a narrow panel width, and a taller row than the one that was
   measured is what makes a windowed table drift. Shrink the ornaments instead. */
#cardsTable td .pill { font-size: 10px; padding: 2px 7px; gap: 5px; }
#cardsTable td .pill .dot { width: 5px; height: 5px; }
#cardsTable td .q-chip { font-size: 10px; padding: 1px 5px; }
/* A history/expiry counter that means "the issuer said no" or "this is dead". */
.q-chip--bad { background: var(--coral-dim); border-color: var(--coral); color: var(--coral);
  font-weight: 700; }
/* Checkout-log error codes. A TM code (U103, U001, E101…) is Ticketmaster's own identifier; a
   WhaleRestocks label (BMP-BLOCK, NO-PROXY…) is OUR name for a failure TM described only in prose,
   or one that never reached TM. They must not look alike: reading 'NO-PROXY' as a TM code would
   send the operator hunting for a Ticketmaster error that does not exist. TM codes get the mono
   weight of a real identifier; ours are dimmer and dashed. */
.q-chip.code-tm { font-weight: 700; letter-spacing: .02em; }
.q-chip.code-ours { border-style: dashed; font-weight: 600; opacity: .92; }
/* The per-card log button is brighter when there IS a log to read. */
.icon-btn.has-log { color: var(--accent-deep); }
/* Log modal. Every cell is ONE line: the event name, the account email and TM's prose are all long
   enough to wrap a row to five lines each, which turns twenty attempts into a page nobody can scan.
   They clamp with an ellipsis instead and keep the full text in title= (the table scrolls
   horizontally inside its own wrapper, so nothing is unreachable). */
#cardLogBody .q-activity { margin: 0; }
#cardLogBody table.data td { vertical-align: middle; white-space: nowrap; }
#cardLogBody table.data th { white-space: nowrap; }
/* Event cell: the name on one line, the date / venue / seats under it. Two lines, both clamped, so
   every row stays the same height however long a tour name is. */
#cardLogBody .log-evcell { max-width: 230px; }
#cardLogBody .log-ev, #cardLogBody .log-ev__sub {
  display: block; max-width: 230px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#cardLogBody .log-ev__sub { font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-dim); }
/* Ticketmaster's own message is the primary evidence — give it the widest cell and let it take the
   remaining space rather than being the first thing pushed off the right edge. */
#cardLogBody .log-msg { max-width: 340px; min-width: 200px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
/* The log is a seven-column data table, not a form: at .modal.wide's 920px the message column — the
   whole point of the row — starts off-screen behind a horizontal scroll. Widen to fit it, still
   clamped to the viewport so it can never exceed the window (the phone rule below takes over at
   880px and makes every modal full-width anyway). */
#cardLogModal .modal.wide { max-width: min(1280px, calc(100vw - 48px)); }
/* An attempt where Ticketmaster never saw the card is context, not evidence about the card. */
#cardLogBody tr.log-unused > td { opacity: .62; }
#cardLogBody tr.log-unused .q-chip { opacity: 1; }

/* === shared cart/order card rows (used by the Carts + Orders pages) ======================= */
.card-rows{display:flex;flex-direction:column;gap:7px}
#cartGrid{display:flex;flex-direction:column;gap:7px}
.cart-row{padding:7px 13px;display:flex;flex-direction:column;gap:4px;line-height:1.2}
/* Orders live-filter: hide a card the search/window filter dropped (beats .cart-row's display:flex). */
.cart-row[hidden]{display:none}
/* Orders "showing N of M orders" count line under the toolbar. */
.orders-meta{margin:-2px 2px 12px;font-family:var(--f-mono);font-size:11.5px;color:var(--ink-dim)}
.cr-top{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.cr-id{min-width:0;flex:1 1 220px}
.cr-id h3{margin:0;font-size:13.5px;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cr-id .sub{margin-top:1px;display:flex;gap:6px;flex-wrap:wrap;align-items:center;font-size:10px;color:var(--ink-dim)}
.cr-facts{display:flex;gap:14px;flex:none;align-items:center}
.cr-status{display:flex;align-items:center;gap:8px;flex:none;margin-left:auto}
.ct-cell{min-width:0}
.ct-cell .k{font-size:8.5px;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-faint);font-family:var(--f-mono);line-height:1}
.ct-cell .v{font-size:12px;color:var(--ink);font-weight:600;margin-top:1px;font-variant-numeric:tabular-nums;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:130px;line-height:1.15}
.ct-cell .v.mono{font-family:var(--f-mono);font-weight:500}
.cr-bot{display:flex;align-items:center;gap:8px;flex-wrap:wrap;border-top:1px solid var(--line-soft);padding-top:6px}
.cr-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0;flex:1 1 auto;font-size:11.5px}
.cr-ttype{font-weight:600;color:var(--ink)}
.cr-ttype .desc{font-weight:400;color:var(--ink-dim)}
/* TM delivery method (Mobile / Will Call / e-ticket) on a cart row. Long descriptions truncate —
   the full text is on the element's title attribute. */
.cr-deliv{display:inline-flex;align-items:center;gap:4px;font-weight:600;color:var(--ink);
  min-width:0;max-width:320px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cr-deliv .desc{font-weight:400;color:var(--ink-dim)}
.cr-deliv.muted{font-weight:400;color:var(--ink-dim)}
.cr-deliv.blocked{color:var(--bad,#c0392b)}
.cr-deliv-check{cursor:pointer;background:none;border:0;padding:0;font:inherit}
.cr-deliv-check[disabled]{opacity:.6;cursor:default}
/* Action group. Always a <fieldset> so a blocked cart can disable every control natively; reset the
   browser's default fieldset chrome so it lays out exactly as the old plain container did. */
/* Single-row action bar: the fieldset shrinks (chips scroll) instead of wrapping into a tower
   of sparse lines — a card stays 3 rows tall however many card brands exist (2026-08-31). */
.cr-actset{display:flex;align-items:center;gap:7px;flex-wrap:nowrap;flex:1 1 auto;border:0;margin:0;padding:0;min-width:0}
.cr-actset>.btn{flex:none}
/* A delivery-blocked (will call) hold: shown like every other cart, but visibly inert. */
.cart-blocked{opacity:.72}
.cart-blocked .cr-actset{opacity:.55;pointer-events:none}
.cr-note{font-family:var(--f-mono);font-size:10.5px;color:var(--ink-dim);min-width:0;max-width:340px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cr-note:empty{display:none}
.cr-note.co-live{font-family:inherit;font-size:11.5px;color:var(--sonar-deep);white-space:normal;
  max-width:none;overflow:visible}
.cr-note.co-result{font-family:inherit;font-size:11.5px;white-space:normal;max-width:none;
  overflow:visible;line-height:1.35;color:var(--ink-dim)}
.cr-note.co-result.good{color:var(--sonar-deep)}
.cr-note.co-result.bad{color:var(--coral)}
.cr-note.co-result.warn{color:var(--amber)}
.cr-note.co-result.info{color:var(--tide)}
/* On the action row the note anchors bottom-LEFT and soaks up the slack (buttons stay right),
   truncating on one line — including the live/result variants, which are otherwise allowed to
   grow multi-line and would re-inflate the card height the move exists to remove. */
.cr-actions .cr-note{flex:1 1 auto;min-width:0;max-width:none;text-align:left;margin-right:auto}
.cr-actions .cr-note.co-live,.cr-actions .cr-note.co-result{
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:none;line-height:1.2}
.co-spin{display:inline-block;width:10px;height:10px;border:2px solid var(--line);
  border-top-color:var(--accent);border-radius:50%;animation:cospin .7s linear infinite;
  vertical-align:-1px;margin-right:6px}
@keyframes cospin{to{transform:rotate(360deg)}}
/* flex:0 1 auto + min-width:0 (NOT flex:none): the row must be allowed to SHRINK, or the tail
   buttons (Proxy, trash) slide off the card edge — the Proxy button's pinned-IP label made the
   row wider than the card (2026-08-31). nowrap keeps everything on ONE line: the actset inside
   shrinks by scrolling its brand chips, so the card never grows extra button rows. */
.cr-actions{display:flex;align-items:center;gap:7px;flex:1 1 auto;min-width:0;max-width:100%;
  margin-left:auto;flex-wrap:nowrap;justify-content:flex-end}
/* a pinned "Proxy: <host>" label must truncate, never widen the button past the card */
.cr-actions [data-checkoutproxy]{max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cr-cred{display:inline-flex;align-items:center;gap:5px;background:var(--deep);border:1px solid var(--line-soft);
  border-radius:var(--radius-sm);padding:2px 7px;min-width:0;max-width:220px}
.cr-cred>.ico{color:var(--ink-faint);flex:none;width:12px;height:12px}
.cr-cred .cv{font-family:var(--f-mono);font-size:11px;color:var(--ink);min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.brand-lead{font-size:9.5px;font-family:var(--f-mono);text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint)}
.brand-chips{display:inline-flex;align-items:center;gap:5px;flex-wrap:wrap}
/* Inside a cart card's action bar the chip set scrolls sideways instead of wrapping: with a
   dozen brands, wrapped chips were the main reason a card stood 6 rows tall. */
.cr-actset .brand-chips{flex:0 1 auto;min-width:64px;flex-wrap:nowrap;overflow-x:auto;
  overscroll-behavior-x:contain;scrollbar-width:thin;padding-bottom:1px}
.cr-actset .brand-chip{flex:none}
.brand-chip{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-family:var(--f-mono);font-weight:600;
  color:var(--ink-dim);border:1px solid var(--line);border-radius:999px;padding:2px 10px;background:var(--surface);
  cursor:pointer;transition:border-color .12s,background .12s,color .12s;user-select:none}
.brand-chip:hover{border-color:var(--accent);color:var(--accent-deep)}
.brand-chip.on{background:var(--accent-dim);border-color:var(--accent);color:var(--accent-deep)}
.brand-chip.on::before{content:"\2713";font-weight:700}
.ct-timer{display:inline-flex;align-items:center;gap:5px;font-family:var(--f-mono);font-size:11.5px;
  font-weight:600;padding:2px 8px;border-radius:999px;border:1px solid var(--line);
  background:var(--deep);color:var(--ink-dim);font-variant-numeric:tabular-nums;white-space:nowrap}
.ct-timer .ico{width:12px;height:12px}
.ct-timer.good{color:var(--sonar-deep);border-color:var(--sonar-glow);background:var(--sonar-dim)}
.ct-timer.warn{color:var(--amber);border-color:var(--amber-glow);background:var(--amber-glow)}
.ct-timer.bad{color:var(--coral);border-color:var(--coral-glow);background:var(--coral-glow);animation:ctpulse 1s ease-in-out infinite}
.ct-timer.expired{color:var(--ink-faint)}
@keyframes ctpulse{50%{opacity:.5}}
.ct-link{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-family:var(--f-mono);
  color:var(--tide);text-decoration:none;border:1px solid var(--line);border-radius:var(--radius-sm);
  padding:2px 8px;background:var(--surface);transition:border-color .15s,background .15s}
.ct-link:hover{border-color:var(--tide);background:var(--tide-glow)}
.ct-link .ico{width:12px;height:12px}
.ct-link.muted{color:var(--ink-ghost);border-style:dashed;cursor:default}
.ct-copy{flex:none;cursor:pointer;border:none;background:transparent;color:var(--ink-faint);
  padding:1px;border-radius:4px;display:inline-flex}
.ct-copy:hover{color:var(--accent);background:var(--accent-dim)}
.ct-copy .ico{width:12px;height:12px}
.cart-row .btn.sm{padding:5px 11px}
@media (max-width:760px){.cr-status{margin-left:0}.cr-actions{margin-left:0;width:100%}}

/* live event countdown (events page meta line) */
.countdown { font-family: var(--f-mono); font-size: 11px; color: var(--ink-faint); white-space: nowrap; }
.countdown.soon    { color: var(--amber); }                 /* < 24h */
.countdown.urgent  { color: var(--coral); font-weight: 600; } /* < 1h */
.countdown.started { color: var(--ink-faint); font-style: italic; }

/* =========================================================================================
   PURCHASES & SPEND — one-line ledger bar (Orders + Dashboard); window matrix collapsed
   behind the summary by default
   ========================================================================================= */
.spend summary { list-style: none; }
.spend summary::-webkit-details-marker { display: none; }
.spend__bar { display: flex; align-items: center; gap: 22px; padding: 11px 18px; cursor: pointer; user-select: none; }
.spend__title { display: inline-flex; align-items: center; gap: 9px; font-family: var(--f-display); font-weight: 700; font-size: 14px; color: var(--ink); flex: none; }
.spend__title .ico { width: 16px; height: 16px; color: var(--accent); }
.spend__cells { display: flex; align-items: center; gap: 36px; flex: 1; flex-wrap: wrap; min-width: 0; }
.spend__cell { display: flex; flex-direction: column; min-width: 0; }
.spend__label { font-family: var(--f-mono); font-size: 8.5px; letter-spacing: 1.3px; text-transform: uppercase; color: var(--ink-faint); }
.spend__num { font-family: var(--f-mono); font-weight: 600; font-size: 19px; letter-spacing: -.3px; color: var(--ink); margin-top: 2px; line-height: 1.1; }
.stat__sub.spend__sub { margin-top: 1px; font-size: 10px; color: var(--ink-faint); }
.spend__chev { display: inline-flex; align-items: center; gap: 8px; flex: none; font-size: 9.5px; letter-spacing: 1px; text-transform: uppercase; color: var(--ink-faint); }
.spend__chev .token-panel__chev { width: 14px; height: 14px; transition: transform .16s; transform: rotate(90deg); }
.spend[open] .spend__chev .token-panel__chev { transform: rotate(-90deg); }
.spend__body { border-top: 1px solid var(--line-soft); }
.spend__matrix th:not(:first-child),
.spend__matrix td:not(:first-child) { text-align: right; }
.spend__matrix td:first-child { color: var(--ink); font-weight: 500; }

/* =========================================================================================
   DASHBOARD — slim stat strip + engine-instance rows
   ========================================================================================= */
.statline { display: grid; grid-template-columns: repeat(9, minmax(0, 1fr)); gap: 10px; margin-bottom: var(--gap); }
@media (max-width: 1500px) { .statline { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (max-width: 1000px) { .statline { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 640px)  { .statline { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.stat.slim { padding: 10px 13px 9px; }
.stat.slim .stat__label { font-size: 8.5px; letter-spacing: 1.1px; gap: 5px; }
.stat.slim .stat__label .ico { width: 12px; height: 12px; }
.stat.slim .stat__value { font-size: 18px; margin-top: 5px; letter-spacing: -.3px; }
.stat.slim .stat__value .unit { font-size: 11px; margin-left: 2px; }
.stat.slim .stat__sub { margin-top: 3px; font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stat__off { font-size: 13px; }

.dash-split { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--gap); align-items: start; }
/* Grid children default to min-width:auto, so the engine panel grew to its widest row instead of
   to the column. On a phone that pushed each .eng out to ~550px in a 390px viewport and, because
   the page clips horizontal overflow, silently CUT OFF the per-engine Update/Restart/Stop buttons
   — they were unreachable, not just ugly. Same fix as `.grid > *`. */
.dash-split > * { min-width: 0; }
@media (max-width: 1100px) { .dash-split { grid-template-columns: minmax(0, 1fr); } }
@media (min-width: 881px) { .dash-split .panel__body.flush { max-height: 440px; overflow-y: auto; } }

.eng-tools { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.eng-tools__btns { display: inline-flex; gap: 8px; flex: none; }
.dash-split .panel__head h2 { flex: none; white-space: nowrap; }
.eng-rows { display: flex; flex-direction: column; }
.eng { padding: 10px 16px 11px; border-bottom: 1px solid var(--line-soft); }
.eng:last-child { border-bottom: none; }
.eng__top { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; min-width: 0; }
.eng__state { flex: none; min-width: 78px; justify-content: center; }
.eng__name { font-weight: 600; color: var(--ink); font-size: 13.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 190px; }
.eng__meta { font-size: 10.5px; color: var(--ink-faint); min-width: 0; flex: 0 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.eng__flag { font-size: 9.5px; padding: 1.5px 7px; flex: none; }
/* Deleted engines: ids blocked from re-registering. Collapsed by default -- it is a graveyard, not
   a working list, and only matters when re-adding a machine that was previously removed. */
.eng-tombs { border-top: 1px solid var(--line-soft); padding: 8px 16px 10px; }
.eng-tombs > summary { cursor: pointer; font-size: 11.5px; list-style: revert; }
.eng-tombs__rows { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.eng-tomb { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; min-width: 0; opacity: .78; }
.eng-tomb .pill { flex: none; font-size: 9.5px; padding: 1.5px 7px; }
.eng__spacer { flex: 1; }
.eng__seen { font-size: 10.5px; color: var(--ink-faint); flex: none; }
.eng__actions { display: inline-flex; gap: 6px; flex: none; }
.eng__actions .ico { width: 14px; height: 14px; }
.icon-btn.is-warn { color: var(--amber); border-color: var(--amber-glow); background: var(--amber-dim); }
.icon-btn.is-good { color: var(--sonar-deep); border-color: var(--sonar-dim); background: var(--sonar-dim); }
.eng__bot { display: flex; align-items: center; gap: 9px; margin-top: 8px; flex-wrap: wrap; }
.eng__bot select { width: auto; min-width: 128px; max-width: 200px; padding: 5px 26px 5px 9px; font-size: 12px; }
.eng__bot .monitor-host { flex: none; }
.eng__bot .monitor-host input { width: auto; accent-color: var(--accent); }
table.data.compact th { padding: 8px 12px; }
table.data.compact td { padding: 7.5px 12px; }

/* =========================================================================================
   PAYOUTS — period stepper, ledger hero, partner cards, expense form
   ========================================================================================= */
.periodbar { display: inline-flex; align-items: center; gap: 2px; padding: 3px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); }
.periodbar__nav { border: none; background: transparent; color: var(--ink-dim); width: 28px; height: 28px; border-radius: 5px; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; padding: 0; }
.periodbar__nav:hover { background: var(--surface); color: var(--ink); box-shadow: var(--shadow); }
.periodbar__nav .ico { width: 13px; height: 13px; }
.periodbar__nav.prev .ico { transform: rotate(180deg); }
.periodbar__label { min-width: 152px; text-align: center; font-family: var(--f-mono); font-weight: 600; font-size: 12.5px; color: var(--ink); }
.periodbar__custom { display: inline-flex; gap: 8px; align-items: center; }
.periodbar__custom[hidden] { display: none; }
.periodbar__custom .input { width: auto; padding: 6px 9px; font-size: 12.5px; }

.pay-partner .panel__head { padding: 12px 16px; }
.pay-partner .panel__body { padding: 6px 16px 12px; }
.pl-row { display: flex; justify-content: space-between; align-items: center; gap: 14px; padding: 7px 0; border-bottom: 1px solid var(--line-soft); font-size: 12.5px; color: var(--ink-dim); }
.pl-row:last-child { border-bottom: none; }
.pl-row .val { font-family: var(--f-mono); color: var(--ink); font-weight: 500; font-variant-numeric: tabular-nums; }

.exp-form { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; margin-bottom: 16px; }
.exp-f { display: block; margin: 0; }
.exp-f > span { display: block; font-family: var(--f-mono); font-size: 9px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 5px; }
.exp-f > span em { font-style: normal; text-transform: none; letter-spacing: 0; color: var(--ink-ghost); }
.exp-f .input { width: 100%; padding: 8px 11px; font-size: 13px; }
.exp-f--name { flex: 1 1 150px; min-width: 130px; }
.exp-f--descr { flex: 2 1 210px; min-width: 150px; }
.exp-f--amount { flex: 0 1 110px; }
.exp-f--type { flex: 0 1 132px; }
.exp-f--paidby { flex: 0 1 132px; }
.exp-f--date { flex: 0 1 150px; }
.exp-f--btns { display: flex; gap: 8px; flex: none; }
#expEndWrap[hidden] { display: none; }
table.data td.empty-row { text-align: center; color: var(--ink-faint); padding: 22px 14px; font-size: 12.5px; }

/* =========================================================================================
   SALES — resale ledger (hero P&L + sold-date window + sonar calendar)
   ========================================================================================= */
/* The toolbar owns a popover (the sold-date calendar) that has to paint over the ledger and the
   table below it, so it gets its own layer. 15 sits above page content (z-index auto) and below
   the sticky .fleet bar (20), which the popover should still scroll under. */
.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: var(--gap); position: relative; z-index: 15; }

.rangebar { position: relative; display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.rangebar__label { font-family: var(--f-mono); font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--ink-faint); margin-right: 2px; }
.rangebar .chip-toggle { display: inline-flex; align-items: center; gap: 6px; }
.rangebar .chip-toggle .ico { width: 12px; height: 12px; }

/* live search — grows between the view toggle and the date range */
.sales-search { display: flex; align-items: center; gap: 7px; flex: 1 1 220px; min-width: 150px;
  max-width: 400px; padding: 0 11px; border: 1px solid var(--line-strong); border-radius: 99px;
  background: var(--surface-2); }
.sales-search:focus-within { border-color: var(--accent); background: var(--surface); }
.sales-search .ico { width: 14px; height: 14px; color: var(--ink-faint); flex: none; }
.sales-search input { flex: 1; min-width: 0; width: auto; border: none; background: transparent;
  padding: 8px 0; font-size: 13px; color: var(--ink); outline: none; }
.sales-search input::placeholder { color: var(--ink-ghost); }
/* the pill's :focus-within border IS the focus mark; the console-wide input focus ring (declared
   later, same specificity) used to draw a second box inside it */
.sales-search input:focus, .sales-search input:focus-visible { outline: none; box-shadow: none; }
.sales-search input::-webkit-search-cancel-button { -webkit-appearance: none; display: none; }
.sales-search__x { border: none; background: none; cursor: pointer; color: var(--ink-faint);
  padding: 2px; display: inline-flex; align-items: center; }
.sales-search__x:hover { color: var(--ink); }
.sales-search__x .ico { width: 13px; height: 13px; }
/* the clear button is shown only once there is something to clear (its display above beats [hidden]) */
.sales-search__x[hidden] { display: none; }
/* the Events board's search: the same pill, still growing across the row like the plain box it replaced */
.sales-search.ev-search { flex: 1 1 260px; max-width: none; }

/* ---- ledger hero: the page's one loud element — profit for the selected window ---- */
.ledger { overflow: hidden; }
.ledger__grid { display: grid; grid-template-columns: minmax(300px, 1.15fr) 2fr; }
.ledger__hero {
  position: relative; padding: 24px 28px;
  border-right: 1px solid var(--line-soft);
  background: radial-gradient(130% 120% at 0% 0%, var(--accent-dim), transparent 62%);
}
.ledger__figure { font-family: var(--f-mono); font-weight: 600; font-size: clamp(32px, 3.6vw, 46px); letter-spacing: -1px; line-height: 1.05; margin-top: 10px; font-variant-numeric: tabular-nums; }
.ledger__figure.is-good { color: var(--sonar); }
.ledger__figure.is-bad  { color: var(--coral); }
.ledger__figure.is-warn { color: var(--amber); }
.ledger__figure.is-ink  { color: var(--ink); }
.ledger__sub { margin-top: 12px; font-family: var(--f-mono); font-size: 11.5px; color: var(--ink-dim); }
.ledger__sub b { color: var(--ink); font-weight: 600; }
.ledger__sub .is-good { color: var(--sonar-deep); }
.ledger__sub .is-warn { color: var(--amber); }
/* paid/pending refresh — a quiet pill sitting on the sub line beside the two figures it moves.
   Deliberately smaller and softer than a .btn: it belongs to the numbers, not to the page head. */
.ledger__refresh { display: inline-flex; align-items: center; gap: 5px; margin-left: 9px;
  padding: 2px 9px; border: 1px solid var(--line); border-radius: 99px; background: var(--surface-2);
  color: var(--ink-dim); font: inherit; font-size: 10.5px; line-height: 1.5; cursor: pointer;
  vertical-align: 1px; white-space: nowrap; }
.ledger__refresh:hover:not(:disabled) { color: var(--ink); border-color: var(--line-strong); }
.ledger__refresh:disabled { cursor: default; color: var(--ink-faint); }
.ledger__refresh.is-partial { color: var(--amber); border-color: var(--amber-glow); }
.ledger__refresh .ico { width: 11px; height: 11px; flex: none; }
.ledger__refresh .ico.spin { color: var(--accent); animation: spin .7s linear infinite; }
/* metric grid: column count comes from JS (cols-3 for 6 metrics, cols-2 for 2/4); hairlines
   between columns and rows only — the first column never doubles the hero's divider */
.ledger__metrics { display: grid; }
.ledger__metrics.cols-3 { grid-template-columns: repeat(3, 1fr); }
.ledger__metrics.cols-2 { grid-template-columns: repeat(2, 1fr); }
.ledger__m { padding: 18px 20px; border-left: 1px solid var(--line-soft); }
.ledger__metrics.cols-3 .ledger__m:nth-child(3n+1) { border-left: none; }
.ledger__metrics.cols-3 .ledger__m:nth-child(n+4) { border-top: 1px solid var(--line-soft); }
.ledger__metrics.cols-2 .ledger__m:nth-child(2n+1) { border-left: none; }
.ledger__metrics.cols-2 .ledger__m:nth-child(n+3) { border-top: 1px solid var(--line-soft); }
.ledger__m-label { font-family: var(--f-mono); font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--ink-faint); }
.ledger__m-value { font-family: var(--f-mono); font-weight: 600; font-size: 19px; color: var(--ink); margin-top: 6px; font-variant-numeric: tabular-nums; }
.ledger__m-value.is-good { color: var(--sonar); }
.ledger__m-value.is-bad  { color: var(--coral); }
@media (max-width: 980px) {
  .ledger__grid { grid-template-columns: 1fr; }
  .ledger__hero { border-right: none; border-bottom: 1px solid var(--line-soft); }
  .ledger__metrics.cols-3 { grid-template-columns: repeat(2, 1fr); }
  .ledger__metrics.cols-3 .ledger__m:nth-child(3n+1) { border-left: 1px solid var(--line-soft); }
  .ledger__metrics.cols-3 .ledger__m:nth-child(2n+1) { border-left: none; }
  .ledger__metrics.cols-3 .ledger__m:nth-child(n+3) { border-top: 1px solid var(--line-soft); }
}

/* ---- running balance: the all-time position, rendered into the same .ledger shell ---- */
/* the in-progress month sits on its own sub line with the counted/not-counted toggle inline */
.bal__current { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* month rows open that month in the period view below */
.bal__row { cursor: pointer; }
.bal__owed { font-variant-numeric: tabular-nums; }
.bal__owed.is-good { color: var(--sonar-deep); }
.bal__owed.is-bad  { color: var(--coral); }
.bal__total td { border-top: 1px solid var(--line-strong); background: var(--surface-2);
  color: var(--ink); font-weight: 600; }
table.data tbody tr.bal__total:hover { background: var(--surface-2); }  /* not a clickable row */

/* ---- token disclosure (rarely touched once saved) ---- */
.token-panel { margin-bottom: var(--gap); }
.token-panel summary { display: flex; align-items: center; gap: 9px; padding: 12px 18px; cursor: pointer; list-style: none; user-select: none; }
.token-panel summary::-webkit-details-marker { display: none; }
.token-panel summary .ico { width: 15px; height: 15px; color: var(--ink-faint); }
.token-panel__title { font-family: var(--f-display); font-weight: 600; font-size: 13px; color: var(--ink); }
.token-panel__chev { margin-left: auto; transition: transform .16s; transform: rotate(90deg); }
.token-panel[open] .token-panel__chev { transform: rotate(-90deg); }
.token-panel__body { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; border-top: 1px solid var(--line-soft); }
.token-panel__body input { flex: 1; min-width: 280px; width: auto; }

/* ---- account cell (Sales-page tabs): email + password, each copy-to-clipboard ---- */
.acct-cell { min-width: 150px; white-space: nowrap; }
.acct-line { display: flex; align-items: center; gap: 5px; max-width: 230px; }
.acct-line + .acct-line { margin-top: 3px; }
.acct-line > .ico { width: 12px; height: 12px; color: var(--ink-faint); flex: none; }
.acct-val { font-family: var(--f-mono); font-size: 11.5px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct-line .ct-copy { flex: none; }
.acct-line .ct-copy.ok { color: var(--sonar); }
.acct-line .ct-copy.ok .ico { color: var(--sonar); }

/* ---- Sales > Missing: per-row "Reset pw", stacked under the credentials it replaces ---- */
.rp-wrap { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin-top: 4px;
  max-width: 100%; }
.rp-btn { white-space: nowrap; flex: none; }
.rp-pill[hidden] { display: none; }
/* the status text can be a full reset error in one of the narrowest columns: ellipsize it and keep
   the whole thing in the pill's title */
.rp-pill { max-width: 100%; min-width: 0; overflow: hidden; }
.rp-pill .rp-pill-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- table note (unmatched-tickets warning under the sold table) ---- */
.sales-note { margin: 0 16px 12px; padding: 9px 12px; border-radius: var(--radius-sm); font-size: 12px;
  color: var(--amber); border: 1px solid var(--amber-glow); background: var(--amber-dim); }
.sales-note[hidden] { display: none; }

/* ---- P&L cell trimmings ---- */
.pnl-pct { font-size: 10.5px; opacity: .72; margin-left: 4px; }
.bundle-badge { font-family: var(--f-mono); font-size: 9.5px; letter-spacing: .4px; text-transform: uppercase;
  color: var(--accent-deep); background: var(--accent-dim); border: 1px solid var(--accent-dim);
  border-radius: 99px; padding: 1px 6px; margin-left: 6px; vertical-align: middle; }
/* backfilled = event details came from our own order, not Lysted (amber, to read as "our data") */
.bundle-badge.bf { color: var(--amber); background: var(--amber-dim); border-color: var(--amber-glow); }
/* cancelled = event cancelled & refunded — row stays visible but counts in NO number (coral) */
.bundle-badge.cx { color: var(--coral); background: var(--coral-dim); border-color: var(--coral-glow); }
/* edited = hand-corrected by the operator; the override is permanent and drives every number */
.bundle-badge.ed { color: var(--ink-dim); background: var(--surface-2); border-color: var(--line-soft); }
tr.is-cancelled td { opacity: .55; }
/* written off = booked as a $0 sale. Dimmed like a cancelled row, but struck through on the money
   columns so it never reads as a trade that simply went badly. */
tr.is-loss td { opacity: .62; }
tr.is-loss td.num { text-decoration: line-through; text-decoration-thickness: 1px; }
/* a Sec/Row/Seats value we filled from our own cart rather than Lysted */
.is-backfilled { border-bottom: 1px dotted var(--amber-glow); }
.act-cell { text-align: right; white-space: nowrap; }
.act-cell .icon-btn { font-size: 11px; line-height: 1; padding: 3px 5px; }
.act-cell .icon-btn + .icon-btn { margin-left: 1px; }
.icon-btn.warn:hover { color: var(--amber); border-color: var(--amber-glow); }

/* ---- Sales: the automatic-sync interval control (page header, beside Sync now) ----
   Reads as one control, not a stray form field: the "Auto" label and the <select> share a single
   bordered box with the same metrics as a .btn, so the header row keeps one baseline. The select
   itself is transparent and border-less inside it — the wrapper carries the chrome. */
.autosync { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  background: var(--surface-3); padding: 0 4px 0 10px; height: 34px; cursor: pointer; }
.autosync:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }
.autosync__lbl { display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--f-mono); font-size: 10px; letter-spacing: 1.1px; text-transform: uppercase;
  color: var(--ink-faint); }
.autosync__lbl .ico { width: 12px; height: 12px; }
/* `is-on` is set by sales.js whenever the timer is armed — the label lights up so "is this running
   on its own?" is answerable at a glance, without reading the dropdown. */
.autosync.is-on { border-color: var(--accent-glow); }
.autosync.is-on .autosync__lbl { color: var(--accent); }
.autosync__sel { width: auto; min-width: 76px; border: none; background-color: transparent;
  padding: 4px 26px 4px 2px; font-size: 12.5px; background-position: right 6px center; }
.autosync__sel:focus { border: none; box-shadow: none; }
@media (max-width: 880px) {
  /* the header becomes a 2-up grid — the control takes a whole cell like the buttons do */
  .autosync { width: 100%; justify-content: space-between; }
}

/* ---- Sales ledger table: fits the panel at every width, never scrolls sideways ----
   The four views run 13-15 columns. Rather than let the table set its own intrinsic width (which
   overflows .table-wrap and grows a horizontal scrollbar), it is table-layout:fixed and sales.js
   emits a <colgroup> whose percentages sum to 100 — so the table is exactly the panel width, at
   any viewport. Values that don't fit ellipsize and keep their full text in a title tooltip. */
#salesTable { table-layout: fixed; width: 100%; font-size: 12.5px; }
/* Tighter gutters than the generic .data table: with 15 columns every saved pixel goes into
   keeping a money figure whole rather than ellipsized. */
#salesTable th, #salesTable td {
  padding-left: 6px; padding-right: 6px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#salesTable th:first-child, #salesTable td:first-child { padding-left: 12px; }
/* The action / PO cells hold real controls, so they get their own tighter box — and they stay
   `overflow: hidden` like every other cell. A visible overflow here is what grew the wrapper's
   scrollWidth past the table (the buttons spilled out of the last column), which is exactly the
   horizontal scrollbar this layout exists to prevent. */
#salesTable td.act-cell, #salesTable th:last-child { padding-left: 4px; padding-right: 6px; }
#salesTable td.act-cell .icon-btn { padding: 2px 4px; }
/* Wrap instead of clip: when the column gets tight the buttons drop to a second line inside the
   cell — still fully clickable, and the cell still can't widen the table. */
#salesTable td.act-cell, #salesTable td.po-cell { white-space: normal; }
#salesTable td.po-cell .po-wrap { display: inline-flex; align-items: center; gap: 3px;
  flex-wrap: wrap; max-width: 100%; }
#salesTable td.po-cell .btn.sm { padding: 3px 7px; font-size: 10.5px; white-space: nowrap; }
/* the account cell stacks email + password, each ellipsizing inside the column */
#salesTable .acct-cell { min-width: 0; }
#salesTable .acct-line { max-width: 100%; }
/* …and, on Missing, a Reset pw control under them — same compact button metrics as the PO column,
   and the cell has to allow wrapping or the button + its status pill can't drop to a second line */
#salesTable td.acct-cell { white-space: normal; }
#salesTable td.acct-cell .btn.sm { padding: 3px 7px; font-size: 10.5px; white-space: nowrap; }
/* Note column (Missing tab). The whole cell is one button so the click target is the column, not a
   tiny icon — but it must READ as text, not as a control, so it carries no border or background
   until hover. Like every other cell it clips: the note ellipsizes and the title holds the rest. */
#salesTable td.note-cell { padding-left: 4px; padding-right: 4px; }
#salesTable .note-btn {
  display: flex; align-items: center; gap: 5px; width: 100%; max-width: 100%;
  padding: 3px 6px; border: 1px solid transparent; border-radius: 5px;
  background: none; color: var(--ink-dim); font: inherit; text-align: left; cursor: pointer;
  overflow: hidden;
}
#salesTable .note-btn:hover { border-color: var(--line); background: var(--surface-2); color: var(--ink); }
#salesTable .note-btn .note-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* An empty note is an invitation, not a value — quieter than the real notes it sits between, and
   the pencil says the cell is writable without spending width on a word. */
#salesTable .note-btn.is-empty { color: var(--ink-ghost); }
#salesTable .note-btn.is-empty .ico { width: 12px; height: 12px; }
#salesTable .note-btn.is-empty:hover { color: var(--ink-dim); }
/* the note modal's box is prose, so it gets more room than the one-line fields around it */
.note-area { min-height: 110px; }

/* the event cell holds a name plus badges — let the badges keep their size and the name give way */
#salesTable td .ev-name { display: inline-block; max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; vertical-align: bottom; }
/* compact pill: the status column is one of the narrowest, and a full-size pill (dot + 11px text
   + 14px gutters) is what made "COMPLETE" ellipsize. */
#salesTable td .pill { font-size: 9.5px; padding: 2px 6px; gap: 4px; }
#salesTable td .pill .dot { width: 4px; height: 4px; }
/* Below 1700px the P&L column can't hold "▼ $260.00 -100%" — drop the secondary ROI suffix so the
   MONEY is always whole. The full "amount · ROI" stays in the cell's title. */
@media (max-width: 1700px) { #salesTable .pnl-pct { display: none; } }

/* edit-row / edit-order modal: two columns of short fields, and JS hides the ones that don't
   apply to the row being edited (a sale has cost/payout/sold-to; an order has $ per ticket). */
.edit-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
.edit-grid .add-field[hidden] { display: none; }

/* ---- add-order modal ---- */
.add-help { font-size: 13px; color: var(--ink-dim); margin-bottom: 16px; line-height: 1.5; }
.add-field { display: block; margin-bottom: 14px; }
.add-field > span { display: block; font-family: var(--f-mono); font-size: 10px; letter-spacing: 1.4px;
  text-transform: uppercase; color: var(--ink-faint); margin-bottom: 6px; }
.add-field > span em { font-style: normal; text-transform: none; letter-spacing: 0; color: var(--ink-ghost); }
.add-field .input { width: 100%; }
.add-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.add-result { margin-top: 4px; padding: 10px 12px; border-radius: var(--radius-sm); font-size: 12.5px;
  border: 1px solid var(--line-soft); background: var(--surface-2); }
.add-result.is-good { color: var(--sonar-deep); border-color: var(--sonar-dim); background: var(--sonar-dim); }
.add-result.is-warn { color: var(--amber); border-color: var(--amber-glow); background: var(--amber-dim); }
.add-result[hidden] { display: none; }
.add-manual { margin-top: 18px; }
.add-manual__title { font-family: var(--f-mono); font-size: 10px; letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--ink-faint); margin-bottom: 8px; }
.add-manual__row { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-top: 1px solid var(--line-soft); font-size: 12.5px; }
.add-manual__row .mono { color: var(--ink); font-family: var(--f-mono); }
.add-manual__meta { color: var(--ink-faint); font-size: 11.5px; margin-right: auto; }

/* ---- cancelled-events modal ---- */
.cancel-list { max-height: 340px; overflow-y: auto; border: 1px solid var(--line-soft); border-radius: 8px; }
.cancel-row { display: flex; align-items: center; gap: 12px; padding: 9px 12px; border-top: 1px solid var(--line-soft); }
.cancel-row:first-child { border-top: 0; }
.cancel-row__info { min-width: 0; margin-right: auto; }
.cancel-row__name { font-size: 13px; color: var(--ink); }
.cancel-row__meta { font-size: 11.5px; color: var(--ink-faint); margin-top: 2px; }
.cancel-row.is-cancelled .cancel-row__name { text-decoration: line-through; opacity: .6; }
.cancel-row .btn { flex: none; white-space: nowrap; }
/* dimmed Orders card for a cancelled (refunded) order — visible, badged, counts for nothing */
.cart-row.is-cancelled .cr-top, .cart-row.is-cancelled .cr-bot { opacity: .55; }

/* ---- run rate: the window's profit carried out to a day / week / month / year average ---- */
.runrate { margin-top: var(--gap); overflow: hidden; }
.runrate__head {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  padding: 13px 20px; border-bottom: 1px solid var(--line-soft);
}
.runrate__title { font-family: var(--f-mono); font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--ink-faint); }
.runrate__basis { font-family: var(--f-mono); font-size: 11px; color: var(--ink-dim); }
.runrate__basis b { color: var(--ink); font-weight: 600; }
.runrate__grid { display: grid; grid-template-columns: repeat(4, 1fr); }
.runrate__c { padding: 16px 20px; border-left: 1px solid var(--line-soft); }
.runrate__c:first-child { border-left: none; }
.runrate__label { font-family: var(--f-mono); font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--ink-faint); }
.runrate__v { font-weight: 600; font-size: 22px; letter-spacing: -.3px; margin-top: 7px; }
.runrate__v.is-good { color: var(--sonar); }
.runrate__v.is-bad  { color: var(--coral); }
.runrate__sub { font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-faint); margin-top: 5px; }
@media (max-width: 880px) {
  .runrate__grid { grid-template-columns: repeat(2, 1fr); }
  .runrate__c:nth-child(2n+1) { border-left: none; }
  .runrate__c:nth-child(n+3) { border-top: 1px solid var(--line-soft); }
}

/* ---- sonar calendar popover (custom sold-date range: two clicks) ---- */
.cal {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60; width: 264px;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius);
  box-shadow: 0 12px 32px -12px rgba(16, 24, 40, .18); padding: 12px;
}
.cal__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.cal__title { font-family: var(--f-mono); font-size: 11.5px; font-weight: 600; letter-spacing: .6px; color: var(--ink); }
.cal__nav {
  width: 26px; height: 26px; border-radius: var(--radius-sm); border: 1px solid var(--line);
  background: var(--surface-2); color: var(--ink-dim); font-size: 14px; line-height: 1; cursor: pointer;
}
.cal__nav:hover { border-color: var(--accent-glow); color: var(--ink); }
.cal__dow { display: grid; grid-template-columns: repeat(7, 1fr); margin-bottom: 3px; }
.cal__dow span { text-align: center; font-family: var(--f-mono); font-size: 9px; letter-spacing: 1px; text-transform: uppercase; color: var(--ink-ghost); padding: 3px 0; }
.cal__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.cal__day {
  height: 30px; border: none; border-radius: var(--radius-sm); background: transparent;
  font-family: var(--f-mono); font-size: 11.5px; color: var(--ink-dim); cursor: pointer;
  font-variant-numeric: tabular-nums; padding: 0;
}
.cal__day:hover { background: var(--surface-3); color: var(--ink); }
.cal__day.is-out { color: var(--ink-ghost); }
.cal__day.is-off { opacity: .3; cursor: not-allowed; }
.cal__day.is-today { box-shadow: inset 0 0 0 1px var(--line-strong); }
.cal__day.is-in { background: var(--accent-dim); color: var(--accent-deep); border-radius: 0; }
.cal__day.is-start, .cal__day.is-end {
  background: var(--accent); color: #fff; font-weight: 600;
}
.cal__day.is-start { border-radius: var(--radius-sm) 0 0 var(--radius-sm); }
.cal__day.is-end { border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }
.cal__day.is-start.is-end { border-radius: var(--radius-sm); }
.cal__foot { margin-top: 9px; padding-top: 8px; border-top: 1px solid var(--line-soft); font-family: var(--f-mono); font-size: 10px; letter-spacing: .4px; color: var(--ink-faint); text-align: center; }
@media (max-width: 560px) { .cal { right: auto; left: 0; } }

/* =========================================================================================
   Seat map, shared by Restocks and Explorer
   ========================================================================================= */
  .sm-toolbar{display:flex;align-items:center;gap:8px;margin-bottom:6px;flex-wrap:wrap}
  .sm-btn{font-family:var(--f-mono);font-size:13px;font-weight:600;line-height:1;color:var(--ink-dim);
    border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface);padding:5px 11px;cursor:pointer}
  .sm-btn:hover{border-color:var(--sonar);color:var(--sonar-deep)}
  .sm-hint{font-size:11px;color:var(--ink-faint)}
  .sm-wrap{position:relative;width:100%;height:68vh;min-height:460px;overflow:hidden;
    border:1px solid var(--line);border-radius:var(--radius);background:var(--surface-2)}
  .sm-svg{width:100%;height:100%;display:block;cursor:grab;touch-action:none}
  .sm-svg.grabbing{cursor:grabbing}
  .sm-sec{fill:var(--surface-3);stroke:var(--line);stroke-width:6}
  .sm-seat{stroke:var(--seat-stroke);stroke-width:1.5}
  .sm-open{fill:var(--sonar)}
  .sm-taken{fill:var(--ink-ghost);opacity:.5}
  .sm-legend{display:inline-flex;align-items:center;gap:6px;margin-left:auto;font-size:12px;color:var(--ink-dim)}
  .sm-dot{width:10px;height:10px;border-radius:99px;display:inline-block;margin-left:8px}
  .sm-dot.sm-open{background:var(--sonar)}
  .sm-dot.sm-taken{background:var(--ink-ghost)}
  .sm-tip{position:absolute;z-index:5;pointer-events:none;background:var(--ink);color:var(--tip-ink);font-size:11.5px;
    line-height:1.4;padding:6px 9px;border-radius:6px;max-width:240px;box-shadow:var(--shadow);white-space:pre-line}
  .sm-tip[hidden]{display:none}

/* =========================================================================================
   MOBILE / PHONE  — comprehensive touch + small-screen treatment
   The console renders full-screen inside the WhaleRestocks iOS WebView (no browser chrome),
   so this layer owns: safe-area insets (notch / home indicator), 16px inputs (iOS zooms
   anything smaller on focus), >=44px tap targets, no page-level horizontal scroll (wide
   tables become stacked cards), bottom-sheet modals, and full-width toasts.
   ========================================================================================= */

/* --- safe-area insets: the sticky chrome must clear the notch / home indicator --- */
.fleet   { padding-top: max(9px, env(safe-area-inset-top)); padding-left: max(22px, env(safe-area-inset-left)); padding-right: max(22px, env(safe-area-inset-right)); }
.rail    { padding-top: env(safe-area-inset-top); }
.toasts  { bottom: max(18px, env(safe-area-inset-bottom)); right: max(18px, env(safe-area-inset-right)); }

/* Kill page-level horizontal scroll: nothing should push the body wider than the phone.
   Wide content (tables, code, maps) scrolls inside its OWN container, never the page. */
@media (max-width: 880px) {
  /* overflow-x: clip (not hidden) — clip does NOT become a scroll container, so it can't
     change the sticky-positioning context of the .fleet HUD the way `hidden` can. */
  html, body { max-width: 100%; overflow-x: clip; }
  .main { min-width: 0; max-width: 100%; overflow-x: clip; }
  .content { padding: 18px max(14px, env(safe-area-inset-left)) calc(60px + env(safe-area-inset-bottom)) max(14px, env(safe-area-inset-right)); }

  /* readable inputs: 16px prevents iOS focus-zoom; roomy padding = a real tap target */
  input[type=text], input[type=password], input[type=number], input[type=search],
  input[type=url], input[type=email], select, textarea { font-size: 16px; padding: 11px 13px; }
  .inp-mini { width: 72px; font-size: 16px; padding: 7px 9px; }
  .sel-mini { font-size: 16px; padding: 7px 26px 7px 10px; }

  /* >=44px tap targets across every interactive control */
  .btn { min-height: 44px; padding: 10px 16px; }
  .btn.sm { min-height: 40px; }
  .icon-btn { min-width: 40px; min-height: 40px; align-items: center; justify-content: center; }
  .toggle { min-height: 34px; padding: 6px 12px; }
  .checkbox input, .pick input, input[type=checkbox], input[type=radio] { width: 20px; height: 20px; }
  a.reveal, .ct-copy, .modal__close { min-width: 40px; min-height: 40px; }
  .ct-copy, .modal__close { display: inline-flex; align-items: center; justify-content: center; }

  /* fleet HUD: title + hamburger on one line, status chips scroll as one row below */
  .fleet { gap: 8px; padding-top: max(8px, env(safe-area-inset-top)); padding-bottom: 8px; }
  .fleet__title { margin-right: auto; }
  .fleet__clock { display: none; }              /* the phone shows its own clock */
  #fleetStrip {
    order: 3; flex: 0 0 100%; flex-wrap: nowrap; overflow-x: auto;
    -webkit-overflow-scrolling: touch; scrollbar-width: none; padding-bottom: 2px;
  }
  #fleetStrip::-webkit-scrollbar { display: none; }
  #fleetStrip .chip { flex: none; }

  /* page header stacks; actions become a full-width wrapping button row */
  .page-head { flex-direction: column; align-items: stretch; gap: 14px; margin-bottom: 18px; }
  .page-head__r { flex-wrap: wrap; }
  .page-head__r .btn { flex: 1 1 auto; }
  h1 { font-size: 22px; }
  .page-head p { font-size: 13px; }
  .toolbar { gap: 10px; }
  .btn-row .btn { flex: 1 1 auto; }
}

/* --- command-rail drawer: a tap-scrim behind the open rail closes it (added by console.js) --- */
.rail-scrim {
  position: fixed; inset: 0; z-index: 55; background: var(--scrim);
  backdrop-filter: blur(2px); opacity: 0; pointer-events: none; transition: opacity .2s;
}
.rail-scrim.show { opacity: 1; pointer-events: auto; }
@media (max-width: 880px) {
  .rail {
    width: min(86vw, 320px); box-shadow: 0 0 40px -8px rgba(16,24,40,.4);
    padding-bottom: env(safe-area-inset-bottom); background: var(--surface);
  }
  /* Roomier drawer: 44px rows, bigger glyphs, and a real dismiss in the brand bar. */
  .rail__brand { padding: 14px 14px 13px; }
  .rail__close {
    display: inline-flex; align-items: center; justify-content: center;
    margin-left: auto; flex: none;
    width: 40px; height: 40px; border-radius: 999px;
    border: 1px solid var(--line); background: var(--surface); color: var(--ink-faint);
    cursor: pointer; padding: 0;
  }
  .rail__close:active { background: var(--surface-2); }
  .rail__close .ico { width: 17px; height: 17px; }
  .rail__nav { padding: 6px 10px 18px; gap: 2px; }
  .rail__group { font-size: 9.5px; margin: 15px 0 6px; }
  .navlink { padding: 11px 12px; font-size: 15px; min-height: 44px; border-radius: 9px; }
  .navlink svg { width: 19px; height: 19px; }
  .navlink.is-active::before { left: -10px; height: 22px; }
  .navlink__badge { font-size: 12px; }
  .rail__instance { padding: 12px 14px; }
  .rail__pick select { font-size: 16px; padding: 10px 26px 10px 8px; }
  .rail__foot { padding: 12px 14px calc(12px + env(safe-area-inset-bottom)); }
  .rail__out { min-height: 40px; font-size: 13.5px; }
}

/* =========================================================================================
   MOBILE TABLES → STACKED CARDS
   Every data table becomes label/value cards at phone width so nothing scrolls sideways.
   console.js stamps each <td> with data-label from its column header. A table that must
   stay columnar can opt out with class "no-cards" (it then scrolls inside .table-wrap).
   ========================================================================================= */
@media (max-width: 640px) {
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

  table.data:not(.no-cards) { font-size: 14px; }
  table.data:not(.no-cards) thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  table.data:not(.no-cards),
  table.data:not(.no-cards) tbody,
  table.data:not(.no-cards) tr,
  table.data:not(.no-cards) td { display: block; width: auto; }
  table.data:not(.no-cards) tr {
    border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
    margin-bottom: 10px; padding: 2px 0; box-shadow: var(--shadow);
  }
  table.data:not(.no-cards) tbody tr:hover { background: var(--surface); }
  table.data:not(.no-cards) td {
    display: flex; align-items: center; justify-content: space-between; gap: 14px;
    padding: 9px 14px; border-bottom: 1px solid var(--line-soft);
    white-space: normal; text-align: right; min-height: 40px;
  }
  table.data:not(.no-cards) tr td:last-child { border-bottom: none; }
  table.data:not(.no-cards) td::before {
    content: attr(data-label); flex: none; text-align: left;
    font-family: var(--f-mono); font-size: 9.5px; letter-spacing: 1px; text-transform: uppercase;
    color: var(--ink-faint); font-weight: 500;
  }
  /* a cell with no header label (e.g. the row-actions column) spans full width, no gutter */
  table.data:not(.no-cards) td[data-label=""]::before,
  table.data:not(.no-cards) td:not([data-label])::before { content: none; }
  table.data:not(.no-cards) td[data-label=""],
  table.data:not(.no-cards) td:not([data-label]) { justify-content: flex-end; flex-wrap: wrap; }
  table.data:not(.no-cards) td.num { text-align: right; }
  /* let action buttons inside a card cell breathe */
  table.data:not(.no-cards) td .btn,
  table.data:not(.no-cards) td .btn.sm { min-height: 38px; }
}

/* =========================================================================================
   MOBILE MODALS → BOTTOM SHEETS
   Full-width, bottom-anchored, slide up. Body scrolls; header/footer pinned. Foot buttons
   go full-width so a thumb can hit them. Applies to every .modal-backdrop/.modal on the site.
   ========================================================================================= */
@media (max-width: 640px) {
  .modal-backdrop { align-items: flex-end; padding: 0; }
  .modal, .modal.wide {
    max-width: 100%; width: 100%; max-height: 92vh;
    border-radius: 18px 18px 0 0; border-bottom: none;
    animation: sheet-up .26s cubic-bezier(.2,.7,.3,1) both;
    padding-bottom: env(safe-area-inset-bottom);
  }
  .modal__head { padding: 16px 18px; position: sticky; top: 0; background: var(--surface); z-index: 2; border-radius: 18px 18px 0 0; }
  .modal__head::before { content: ""; position: absolute; top: 6px; left: 50%; transform: translateX(-50%); width: 38px; height: 4px; border-radius: 99px; background: var(--line-strong); }
  .modal__body { padding: 16px 18px; -webkit-overflow-scrolling: touch; }
  .modal__foot { flex-direction: column-reverse; align-items: stretch; gap: 8px; padding: 14px 18px calc(14px + env(safe-area-inset-bottom)); position: sticky; bottom: 0; background: var(--surface); }
  .modal__foot .btn { width: 100%; }
  @keyframes sheet-up { from { transform: translateY(100%); } }

  /* pickers: taller rows, bigger radios */
  .pick { padding: 13px; min-height: 52px; }
  .pick-list { max-height: 52vh; }

  /* curate / seat-map modal stacks; the map gets real height and pinch/scroll room */
  .cur-grid { grid-template-columns: 1fr; }
  .seatmap-wrap { max-height: 44vh; }
  .sm-wrap { height: 56vh; min-height: 320px; }
  .sm-toolbar { gap: 6px; }
  .sm-legend { margin-left: 0; }

  /* sold-date calendar popover becomes a centered sheet, not an off-screen dropdown */
  .cal { position: fixed; left: 12px; right: 12px; top: auto; bottom: calc(12px + env(safe-area-inset-bottom)); width: auto; }
  .cal__day { height: 40px; }
}

/* --- toasts: full-width along the bottom on phones so they never clip off-screen --- */
@media (max-width: 640px) {
  .toasts { left: max(12px, env(safe-area-inset-left)); right: max(12px, env(safe-area-inset-right)); max-width: none; }
  .toast { font-size: 14px; }
}

/* =========================================================================================
   MOBILE — per-page / per-component fixes (layered on the foundation above)
   ========================================================================================= */
@media (max-width: 880px) {
  /* Any panel/summary header with actions opposite its title wraps instead of overflowing.
     The action group (often an inline-styled classless div) drops to its own full-width row. */
  .panel__head { flex-wrap: wrap; }
  .panel__head > div:not(.sub), .panel__head > form, .panel__head > .row, .panel__head .btn-row { flex-wrap: wrap; }
  .panel__head > .row[style] { flex-wrap: wrap !important; }        /* override inline nowrap */
  summary.panel__head { flex-wrap: wrap; }

  /* big mono figures shrink so they never blow out a 1-col card */
  .stat__value { font-size: 25px; }
  .ledger__figure { font-size: clamp(30px, 9vw, 40px); }

  /* Dashboard "Update all / Restart all / …" and any fleet-wide action group: full-width row */
  .panel__head > div[style*="display:flex"] { width: 100%; justify-content: flex-start; }
}

@media (max-width: 640px) {
  /* --- Explorer keeps its dense reference/analytics tables columnar (contained scroller) --- */
  .xp-table-wrap { -webkit-overflow-scrolling: touch; }
  .xp-table-wrap table.data { display: table; width: 100%; font-size: 12px; }
  .xp-table-wrap table.data thead { display: table-header-group; position: static; width: auto; height: auto; overflow: visible; clip: auto; }
  .xp-table-wrap table.data tbody { display: table-row-group; }
  .xp-table-wrap table.data tr { display: table-row; margin: 0; padding: 0; border: 0; border-radius: 0; box-shadow: none; background: none; }
  .xp-table-wrap table.data td { display: table-cell; min-height: 0; text-align: left; white-space: nowrap; }
  .xp-table-wrap table.data td::before { content: none; }
  .xp-table-wrap table.data td.num { text-align: right; }

  /* --- Explorer header + seat-map color-mode segment: stack and scroll, don't overflow --- */
  .xp-map-head { flex-direction: column; align-items: stretch; gap: 10px; }
  .xp-segment { overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .xp-segment::-webkit-scrollbar { display: none; }
  .xp-segment button { flex: none; min-height: 40px; }
  .page-head__r.xp-controls, #xpControls { width: 100%; }
  .xp-input, #xpInput { width: 100%; }

  /* --- Carts / Orders: the 6-cell fact strip becomes a 3-up labelled mini-grid --- */
  .cr-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px 12px; width: 100%; }
  .cr-facts .ct-cell { min-width: 0; }
  .ct-cell .v { max-width: 100%; }
  .ct-cell .k { font-size: 9.5px; }
  .cr-top, .cr-bot { row-gap: 8px; }
  /* narrow screens go back to WRAPPING (the desktop bar is nowrap + chip-scroll): the
     full-width primary button below depends on it */
  .cr-actions { margin-left: 0; width: 100%; flex-wrap: wrap; }
  .cr-actset { flex-wrap: wrap; }
  .cr-actset .brand-chips { flex-wrap: wrap; overflow-x: visible; }
  .cr-actions [data-checkout], .cr-actions [data-pickacct] { flex: 1 1 100%; order: -1; }   /* primary action on top, full width */
  /* A BOUND cart keeps Pick/Random account alongside Run checkout (retry on a different account).
     Run checkout stays the full-width primary on top; the two ghost buttons then share the row
     below it instead of stacking into a three-button tower. `flex: 1 1 0` splits the line evenly
     whatever the gap is. */
  .cr-actions [data-checkout] ~ [data-pickacct],
  .cr-actions [data-checkout] ~ [data-randacct] { flex: 1 1 0; order: 0; min-width: 0; }
  .cr-cred { max-width: 100%; }
  .event-group-header { flex-wrap: wrap; }
  .egh-artist { max-width: 100%; }
  .egh-meta { min-width: 0; flex-shrink: 1; }

  /* --- Carts "Pick an account" rows stack instead of crushing the email --- */
  .pa-acct { flex-wrap: wrap; }
  .pa-acct .em { min-width: 0; flex: 1 1 100%; }
  .pa-acct .pa-note { min-width: 0; }
  .pa-acct .btn { flex: 1 1 100%; }

  /* --- Warm pool header row wraps; the flex spacer collapses so controls stay on screen --- */
  .row .fleet__spacer { display: none; }
  .wp-acct .em { min-width: 0; }

  /* --- Settings save bar: clear the home indicator, full-width buttons, drop the label --- */
  .savebar { padding-bottom: calc(14px + env(safe-area-inset-bottom)); }
  .savebar .muted.mono { display: none; }
  .savebar .btn-row { flex: 1; }
  .savebar .btn-row .btn { flex: 1; }

  /* --- Sales token field must not force page-width; view/range chips get real targets --- */
  .token-panel__body input { min-width: 0; }
  #salesViews .chip-toggle, #salesRange .chip-toggle, .rangebar .chip-toggle { min-height: 38px; }

  /* --- Logs: tab strips scroll horizontally as one row; taller tab targets --- */
  .tabs, .ilog-bar { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .tabs::-webkit-scrollbar, .ilog-bar::-webkit-scrollbar { display: none; }
  .tabs .tab, .ilog-bar .tab { flex: none; min-height: 40px; display: inline-flex; align-items: center; }
  /* card-ified log cells: let the message/reason columns wrap full width */
  table.data:not(.no-cards) td[style*="max-width"] { max-width: none !important; }

  /* --- Events: bulk bar + filter row wrap; curate chips are comfortable targets --- */
  #bulkBar { flex-wrap: wrap; gap: 8px; }
  #bulkBar .row { flex-wrap: wrap; }
  .chip-toggle, .flt-chip { min-height: 34px; }

  /* --- Login (its own template, does not extend base) — safe-area + no on-load zoom --- */
  .gate { min-height: 100dvh; padding: max(24px, env(safe-area-inset-top)) max(20px, env(safe-area-inset-right)) max(24px, env(safe-area-inset-bottom)) max(20px, env(safe-area-inset-left)); }
}

/* ── shared explorer visual language (moved verbatim from explorer.html; used by Explorer + Restocks) ── */
.xp-statrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(138px,1fr));gap:10px;margin:0 0 16px}
.xp-statrow .stat{padding:14px 14px 13px}
.xp-statrow .stat__value{font-size:24px;letter-spacing:-.25px}
/* Explorer embedded in the Queue tab's modal (base.html `embed`): the modal head already names the
   event, so the page gives the seat map the fold — a smaller title and one compact row of stats. */
[data-embed] .xp-page-head{align-items:center;margin-bottom:12px}
[data-embed] .xp-page-head .eyebrow{display:none}
[data-embed] .xp-page-head h1{font-size:18px;line-height:1.25}
[data-embed] .xp-statrow{grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:8px;margin-bottom:12px}
[data-embed] .xp-statrow .stat{padding:9px 10px 8px}
[data-embed] .xp-statrow .stat__label{letter-spacing:.6px;font-size:9.5px}
[data-embed] .xp-statrow .stat__value{font-size:17px;margin-top:5px}
.xp-flash{animation:xp-stat-flash .55s ease-out}
@keyframes xp-stat-flash{0%{background:var(--sonar-dim)}100%{background:transparent}}
.xp-map-panel{margin-bottom:16px}
.xp-head-tools{display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:flex-end}
.xp-segment{display:inline-flex;align-items:center;gap:2px;padding:2px;border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--surface-2)}
.xp-segment button{border:none;background:transparent;color:var(--ink-dim);font-family:var(--f-mono);font-size:10.5px;
  font-weight:600;padding:5px 8px;border-radius:5px;cursor:pointer}
.xp-segment button:hover{color:var(--ink)}
.xp-segment button.on{background:var(--surface);color:var(--sonar-deep);box-shadow:var(--shadow)}
.xp-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px}
.xp-grid>*{min-width:0}
@media (max-width:1100px){.xp-grid{grid-template-columns:1fr}}
.xp-panel-tall .panel__body{min-height:276px}
.xp-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.xp-filter{max-width:220px;font-size:12px;padding:7px 10px}
.xp-table-wrap{overflow:auto;max-height:330px}
.xp-sec-table tbody tr{cursor:pointer}
.xp-sec-table tbody tr.is-selected{background:var(--sonar-dim)}
.xp-sec-table th{cursor:pointer;user-select:none}
.xp-sec-table th.on{color:var(--sonar-deep)}
.xp-badge{display:inline-flex;align-items:center;max-width:100%;border:1px solid var(--line);border-radius:999px;
  padding:2px 7px;background:var(--surface-2);font-family:var(--f-mono);font-size:10.5px;color:var(--ink-dim)}
.xp-badge.good{border-color:var(--sonar-dim);background:var(--sonar-dim);color:var(--sonar-deep)}
.xp-badge.bad{border-color:var(--coral-glow);background:var(--coral-dim);color:var(--coral)}
.xp-trunc{display:block;max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.xp-trunc-wide{max-width:420px}
.xp-link{display:inline-block;margin-left:6px;font-family:var(--f-mono);font-size:10.5px;color:var(--sonar-deep);text-decoration:none}
.xp-link:hover{text-decoration:underline}
/* Two "this number isn't the whole story" markers, both Explorer-only: a price-ladder zone holding
   more than one price (the seat-level "PLAT" bucket above all), and a GA pool showing the last
   price seen before it sold out — GA prices live only in the push, so they vanish on sell-out. */
.xp-badge-spread{margin-left:6px;border-color:var(--sonar-dim);background:var(--sonar-dim);color:var(--sonar-deep)}
.xp-badge-stale{margin-left:6px;border-style:dashed}
.xp-row-stale td{opacity:.62}
/* "TM published no price for this section" — deliberately distinct from a bare "—", which on this
   tab means "we don't know" (catalog failed to load). */
.xp-na{font-family:var(--f-mono);font-size:10.5px;color:var(--ink-dim);font-style:italic}

/* ── mobile: dashboard engine rows / spend bar / payouts form ── */
@media (max-width: 880px) {
  .eng-tools { width: 100%; justify-content: flex-start; }
  .eng-tools__btns { flex-wrap: wrap; }
}
@media (max-width: 640px) {
  .spend__bar { flex-wrap: wrap; gap: 10px 12px; }
  .spend__title { flex: 1 1 auto; }
  .spend__chev { margin-left: auto; order: 2; }
  .spend__cells { order: 3; flex: 1 1 100%; justify-content: space-between; gap: 12px; }
  .spend__num { font-size: 17px; }
  .eng__name { max-width: 130px; }
  .eng__actions .icon-btn { min-width: 40px; min-height: 40px; }
  .periodbar__label { min-width: 112px; }
  .exp-f--name, .exp-f--descr, .exp-f--amount, .exp-f--type, .exp-f--paidby, .exp-f--date { flex: 1 1 46%; }
  .exp-f--btns { width: 100%; }
  .exp-f--btns .btn { flex: 1; }
}
.xp-table-wrap .num{font-variant-numeric:tabular-nums}
.xp-muted{color:var(--ink-faint)}
.xp-pctbar{position:relative;display:inline-flex;align-items:center;width:74px;height:16px;overflow:hidden;
  border:1px solid var(--line);border-radius:999px;background:var(--surface-3);font-family:var(--f-mono);
  font-size:10px;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums}
.xp-pctbar-fill{position:absolute;inset:0 auto 0 0;background:var(--sonar);opacity:.5}
.xp-pctbar b{position:relative;z-index:1;margin:0 auto;padding:0 4px}
.xp-footnote{font-size:11.5px;line-height:1.45;color:var(--ink-faint)}
.xp-price-timeline-body{display:flex;flex-direction:column;gap:10px}
.xp-pricing-headline{font-family:var(--f-mono);font-size:11.5px;color:var(--ink-dim);line-height:1.35}
.xp-pricing-headline b{color:var(--ink)}
.xp-price-chart-wrap{position:relative;border:1px solid var(--line-soft);border-radius:var(--radius-sm);
  background:linear-gradient(180deg,var(--surface),var(--surface-2));padding:8px 8px 6px}
.xp-price-svg{display:block;width:100%;height:150px;overflow:visible}
.xp-price-axis{font-family:var(--f-mono);font-size:10px;fill:var(--ink-faint)}
.xp-price-band{fill:var(--sonar-dim)}
.xp-price-line{fill:none;stroke:var(--sonar-deep);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round}
.xp-price-dot{fill:var(--surface);stroke:var(--ink);stroke-width:1.5}
.xp-price-caret{font-family:var(--f-mono);font-size:11px;font-weight:800;text-anchor:middle}
.xp-price-caret.is-up,.xp-price-change.is-up{color:var(--coral);fill:var(--coral)}
.xp-price-caret.is-down,.xp-price-change.is-down{color:var(--sonar-deep);fill:var(--sonar-deep)}
.xp-price-label{font-family:var(--f-mono);font-size:10px;fill:var(--ink);paint-order:stroke;stroke:var(--surface);stroke-width:4;stroke-linejoin:round}
.xp-price-tip{position:absolute;z-index:4;max-width:260px;pointer-events:none;border:1px solid var(--line);
  border-radius:var(--radius-sm);background:var(--surface);box-shadow:var(--shadow);padding:7px 9px;
  font-family:var(--f-mono);font-size:10.5px;line-height:1.45;color:var(--ink)}
.xp-price-tip[hidden]{display:none}
.xp-price-changes{display:flex;flex-direction:column;gap:6px;margin-top:2px}
.xp-price-change-row{display:flex;align-items:center;justify-content:space-between;gap:8px;
  border:1px solid var(--line-soft);border-radius:var(--radius-sm);background:var(--surface);padding:6px 8px;
  font-family:var(--f-mono);font-size:10.5px;color:var(--ink-dim)}
.xp-price-change-row b{font-weight:700;color:var(--ink)}
.xp-hist{min-height:156px;display:flex;align-items:flex-end;gap:4px;border-bottom:1px solid var(--line);padding:12px 4px 6px}
.xp-hcol{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:4px}
.xp-hval{font-family:var(--f-mono);font-size:9px;color:var(--ink-dim);line-height:1}
.xp-hbar{width:100%;max-width:34px;min-height:2px;border-radius:2px 2px 0 0;background:var(--sonar-dim);border-top:2px solid var(--sonar)}
.xp-hlbl{font-family:var(--f-mono);font-size:9px;color:var(--ink-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.xp-split{display:grid;grid-template-columns:1fr;gap:14px}
.xp-feed{display:flex;flex-direction:column;gap:7px;max-height:350px;overflow:auto;padding-right:2px}
.xp-feed-row{display:grid;grid-template-columns:72px minmax(0,1fr) auto;gap:10px;align-items:center;
  border:1px solid var(--line-soft);border-left:3px solid var(--line);border-radius:var(--radius-sm);
  background:var(--surface);padding:8px 10px}
.xp-feed-row.is-add{border-left-color:var(--sonar)}
.xp-feed-row.is-remove{border-left-color:var(--coral)}
.xp-feed-time{font-family:var(--f-mono);font-size:10.5px;color:var(--ink-faint)}
.xp-feed-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--ink)}
.xp-feed-meta{font-family:var(--f-mono);font-size:11px;color:var(--ink-dim);white-space:nowrap}
.xp-empty{padding:24px;text-align:center;color:var(--ink-faint);font-size:13px}

/* ============================ Restocks — bursts and whether we won the carts ============================
   One question per screen: when a restock burst hits, did we win the carts? Everything reads from the same
   six outcomes, always in this order and always these colors: won · beaten · preload · still open · too soon ·
   not in filters. Preload is a muted gold, not a violet: a violet reads as "open" blue to most colour-blind eyes. The won/beaten/open trio is checked for colour-blind separation in both themes (dataviz validator,
   2026-09-29); every bar also carries its numbers in text, so no reading depends on hue alone. */
:root{--rt-won:#0f7247;--rt-beaten:#e8707f;--rt-open:#6f8fd9;--rt-preload:#c39a2e;--rt-skip:var(--surface-3);
  --rt-pending:repeating-linear-gradient(135deg,var(--surface-3) 0 3px,var(--line-strong) 3px 5px)}
:root[data-theme="dark"]{--rt-won:#26a672;--rt-beaten:#b8475a;--rt-open:#6284e0;--rt-preload:#d9b04c}
.rt-bar .preload,.rt-key i.preload,.rt-out i.preload,.rt-track__b .preload{background:var(--rt-preload)}
.rt-chart .preload{fill:var(--rt-preload)}
.pill.preload{color:var(--ink-dim);border-color:var(--rt-preload);background:color-mix(in srgb,var(--rt-preload) 14%,transparent)}
.pill.preload .dot{background:var(--rt-preload)}
.rt-kind.is-preload{border-style:dashed;border-color:var(--rt-preload);background:color-mix(in srgb,var(--rt-preload) 10%,transparent)}
.why.rt-first{color:var(--sonar-deep)}

.rt-controls{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.rt-custom{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;color:var(--ink-faint)}
.rt-custom input{width:58px;padding:5px 7px;font-size:12px;font-family:var(--f-mono)}
.rt-custom input.on{border-color:var(--sonar);color:var(--sonar-deep)}
.rt-gaps{position:relative}
.rt-gaps>summary{list-style:none;cursor:pointer}
.rt-gaps>summary::-webkit-details-marker{display:none}
.rt-gaps__pop{position:absolute;right:0;top:calc(100% + 6px);z-index:30;width:300px;padding:14px 16px;
  background:var(--surface);border:1px solid var(--line-strong);border-radius:var(--radius);box-shadow:var(--shadow)}
.rt-gaps__pop h3{margin:0 0 4px}
.rt-gaps__pop p{margin:0 0 10px;font-size:11.5px;line-height:1.45;color:var(--ink-faint)}
.rt-gaps__pop .xp-segment{margin-bottom:12px}

/* the top: the last burst — the one figure this page leads with */
.rt-top{margin-bottom:16px}
.rt-hero{padding:18px 20px 16px}
.rt-hero__when{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:12.5px;color:var(--ink-dim)}
.rt-hero__when b{font-family:var(--f-mono);font-weight:600;color:var(--ink)}
.rt-live{width:8px;height:8px;border-radius:99px;background:var(--ink-ghost);flex:none}
.rt-live.is-live{background:var(--sonar);box-shadow:0 0 0 0 var(--sonar-glow);animation:rt-live 1.6s ease-out infinite}
@keyframes rt-live{0%{box-shadow:0 0 0 0 var(--sonar-glow)}70%{box-shadow:0 0 0 8px transparent}100%{box-shadow:0 0 0 0 transparent}}
.rt-hero__event{display:block;margin-top:9px;font-family:var(--f-display);font-weight:750;font-size:21px;line-height:1.2;
  letter-spacing:-.2px;color:var(--ink);text-decoration:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
a.rt-hero__event:hover{color:var(--accent-deep)}
.rt-hero__sub{margin-top:3px;font-size:12.5px;color:var(--ink-faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rt-hero__score{display:flex;align-items:flex-end;gap:14px;flex-wrap:wrap;margin:18px 0 10px}
.rt-hero__big{font-family:var(--f-display);font-weight:750;font-size:48px;line-height:.9;letter-spacing:-1.5px;color:var(--ink)}
.rt-hero__of{font-size:15px;color:var(--ink-dim);padding-bottom:3px}
.rt-hero__of b{color:var(--ink)}
.rt-hero__score .pill{margin-bottom:4px}
.rt-hero__none{margin:18px 0 6px;font-size:14px;color:var(--ink-dim)}
.rt-facts{display:flex;flex-wrap:wrap;gap:12px 30px;margin:14px 0 0;padding-top:13px;border-top:1px solid var(--line-soft)}
.rt-facts div{min-width:74px}
.rt-facts dt{font-size:11.5px;color:var(--ink-faint)}
.rt-facts dd{margin:3px 0 0;font-family:var(--f-mono);font-weight:600;font-size:14px;color:var(--ink);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.rt-facts dd small{font-weight:400;color:var(--ink-faint);font-size:11.5px}

/* the outcome bar: one segment per outcome, a 2px surface gap between them, numbers always beside it */
.rt-bar{display:flex;gap:2px;height:10px;min-width:48px;border-radius:5px;overflow:hidden;background:var(--surface)}
.rt-bar i{display:block;height:100%;min-width:3px}
.rt-bar .won{background:var(--rt-won)}
.rt-bar .beaten{background:var(--rt-beaten)}
.rt-bar .open{background:var(--rt-open)}
.rt-bar .pending{background:var(--rt-pending)}
.rt-bar .skipped{background:var(--rt-skip)}
.rt-bar.is-empty{background:var(--surface-3)}
.rt-bar--hero{height:18px;border-radius:7px}
.rt-legend{display:flex;flex-wrap:wrap;gap:6px 16px;font-size:12px;color:var(--ink-dim)}
.rt-key{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.rt-key i{width:11px;height:11px;border-radius:3px;display:inline-block;flex:none}
.rt-key i.won{background:var(--rt-won)}
.rt-key i.beaten{background:var(--rt-beaten)}
.rt-key i.open{background:var(--rt-open)}
.rt-key i.pending{background:var(--rt-pending)}
.rt-key i.skipped{background:var(--rt-skip);box-shadow:inset 0 0 0 1px var(--line-strong)}
.rt-key b{font-family:var(--f-mono);font-weight:600;color:var(--ink)}

/* the scoreboard: one ledger strip, hairlines between the cells — top row what restocked, bottom row how we did */
.rt-score{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:1px;background:var(--line-soft);
  border-radius:var(--radius);overflow:hidden}
@media (max-width:820px){.rt-score{grid-template-columns:repeat(2,minmax(0,1fr))}}
.rt-cell{background:var(--surface);padding:14px 16px 13px;min-width:0}
.rt-cell__label{display:flex;align-items:center;gap:7px;font-size:12px;color:var(--ink-dim)}
.rt-cell__label i{width:9px;height:9px;border-radius:3px;display:inline-block;flex:none}
.rt-cell__value{margin-top:6px;font-family:var(--f-display);font-weight:750;font-size:25px;letter-spacing:-.5px;line-height:1.05;color:var(--ink)}
.rt-cell__sub{margin-top:5px;font-size:11.5px;color:var(--ink-faint)}
.rt-score-panel{margin-bottom:16px}

/* over time */
.rt-chart-panel{margin-bottom:16px}
.rt-chart-panel .panel__head{flex-wrap:wrap}
.rt-chart{position:relative;padding:10px 16px 8px}
.rt-chart svg{display:block;width:100%;overflow:visible}
.rt-chart .ax{font-family:var(--f-mono);font-size:10px;fill:var(--ink-faint)}
.rt-chart .gl{stroke:var(--line-soft);stroke-width:1}
.rt-chart .base{stroke:var(--line);stroke-width:1}
.rt-chart .won{fill:var(--rt-won)}
.rt-chart .beaten{fill:var(--rt-beaten)}
.rt-chart .open{fill:var(--rt-open)}
.rt-chart .pending{fill:var(--ink-ghost)}
.rt-chart .skipped{fill:var(--surface-3)}
.rt-chart .hit{fill:transparent;cursor:crosshair}
.rt-chart .hit:hover,.rt-chart .hit:focus{fill:var(--accent-dim);outline:none}
.rt-tip{position:absolute;z-index:6;pointer-events:none;min-width:190px;max-width:260px;padding:9px 11px;
  background:var(--surface);border:1px solid var(--line-strong);border-radius:var(--radius-sm);box-shadow:var(--shadow);
  font-size:12px;line-height:1.5;color:var(--ink)}
.rt-tip[hidden]{display:none}
.rt-tip b{font-family:var(--f-mono)}
.rt-tip .rt-key{display:flex;justify-content:space-between;gap:12px}
.rt-tip__t{font-weight:650;margin-bottom:4px}
.rt-check{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--ink-dim);cursor:pointer;user-select:none}

/* tabs */
.rt-tabs{display:flex;align-items:center;gap:6px;margin:0 0 12px;flex-wrap:wrap}
.rt-tab{font-family:var(--f-display);font-size:13px;font-weight:650;color:var(--ink-dim);border:1px solid var(--line);
  border-radius:999px;padding:6px 15px;background:var(--surface);cursor:pointer}
.rt-tab:hover{color:var(--ink)}
.rt-tab.on{background:var(--accent-dim);border-color:var(--accent);color:var(--accent-deep)}
.rt-tab .n{font-family:var(--f-mono);font-weight:500;font-size:11px;color:var(--ink-faint);margin-left:4px}
.rt-pane{display:none}
.rt-pane.on{display:block}

/* the burst feed */
.rt-feed-tools{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:12px 16px;border-bottom:1px solid var(--line-soft)}
.rt-feed-tools .rt-search{flex:0 1 240px;min-width:150px;font-size:12.5px;padding:6px 10px}
.rt-feed-tools .rt-count{margin-left:auto;font-size:12px;color:var(--ink-faint)}
.rt-bursts{display:flex;flex-direction:column}
.rt-burst{border-bottom:1px solid var(--line-soft)}
.rt-burst:last-child{border-bottom:0}
.rt-burst__row{display:grid;align-items:center;gap:14px;width:100%;padding:11px 16px;background:none;border:0;
  text-align:left;color:inherit;font:inherit;cursor:pointer;
  grid-template-columns:86px minmax(0,1.5fr) 118px minmax(150px,1.25fr) 108px minmax(0,.9fr) 14px}
.rt-bursts--event .rt-burst__row{grid-template-columns:86px 118px minmax(170px,1.6fr) 108px 120px minmax(0,1fr) 14px}
.rt-burst__row:hover{background:var(--surface-2)}
.rt-burst__row:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.rt-burst.is-open>.rt-burst__row{background:var(--surface-2)}
.rt-burst.is-new>.rt-burst__row{animation:xp-stat-flash 1.2s ease-out}
.rt-when{min-width:0}
.rt-when b{display:block;font-family:var(--f-mono);font-weight:600;font-size:12.5px;color:var(--ink)}
.rt-when small{display:block;font-size:11px;color:var(--ink-faint);margin-top:1px}
.rt-ev{min-width:0}
.rt-ev b{display:block;font-weight:650;font-size:13.5px;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rt-ev small{display:block;font-size:11.5px;color:var(--ink-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px}
.rt-win{display:flex;flex-direction:column;gap:5px;min-width:0}
.rt-win__txt{font-size:12px;color:var(--ink-dim);white-space:nowrap}
.rt-win__txt b{font-family:var(--f-mono);color:var(--ink)}
.rt-qty{font-size:12px;color:var(--ink-dim);line-height:1.35}
.rt-qty b{font-family:var(--f-mono);font-weight:600;color:var(--ink)}
.rt-qty .rt-sep{display:none}
.rt-kinds{display:flex;flex-wrap:wrap;gap:4px;min-width:0}
.rt-kind{display:inline-flex;align-items:center;gap:4px;padding:1px 7px;border-radius:99px;border:1px solid var(--line);
  background:var(--surface);font-size:11px;color:var(--ink-dim);white-space:nowrap}
.rt-kind b{font-family:var(--f-mono);font-weight:600;color:var(--ink)}
.rt-kind.is-drop{border-color:var(--amber-glow);background:var(--amber-dim)}
.rt-chev{width:14px;height:14px;color:var(--ink-faint);transition:transform .15s}
.rt-burst.is-open .rt-chev{transform:rotate(90deg)}
.rt-verdict{justify-self:start;white-space:nowrap}
.rt-burst__detail{padding:6px 16px 16px;background:var(--surface-2);border-top:1px solid var(--line-soft)}
.rt-burst__facts{display:flex;flex-wrap:wrap;gap:6px 18px;padding:8px 0 10px;font-size:12px;color:var(--ink-dim)}
.rt-burst__facts b{font-family:var(--f-mono);color:var(--ink)}
.rt-more{display:block;width:100%;padding:11px;border:0;border-top:1px solid var(--line-soft);background:none;
  color:var(--accent-deep);font:inherit;font-size:12.5px;font-weight:600;cursor:pointer}
.rt-more:hover{background:var(--surface-2)}

/* tickets of one burst */
.rt-tix-wrap{max-height:460px;overflow:auto;border:1px solid var(--line-soft);border-radius:var(--radius-sm);background:var(--surface)}
.rt-tix-wrap:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.rt-tix{font-size:12.5px}
.rt-tix th{position:sticky;top:0;background:var(--surface);z-index:1}
.rt-tix td{vertical-align:top}
.rt-tix .seat{font-family:var(--f-mono);white-space:nowrap}
.rt-tix .why{font-size:11px;color:var(--ink-faint)}
.rt-cart{font-size:11.5px;color:var(--ink-dim);line-height:1.45}
.rt-cart b{font-family:var(--f-mono);font-weight:600;color:var(--ink)}
.rt-out{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;font-size:12px;color:var(--ink)}
.rt-out i{width:9px;height:9px;border-radius:3px;display:inline-block;flex:none}
.rt-out i.won{background:var(--rt-won)}
.rt-out i.beaten{background:var(--rt-beaten)}
.rt-out i.open{background:var(--rt-open)}
.rt-out i.pending{background:var(--rt-pending)}
.rt-out i.skipped{background:var(--rt-skip);box-shadow:inset 0 0 0 1px var(--line-strong)}
.rt-tix-tools{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 8px;font-size:12px;color:var(--ink-dim)}

/* events */
.rt-table-wrap{overflow:auto;max-height:640px}
.rt-events th{cursor:pointer;user-select:none;white-space:nowrap}
.rt-events th.on{color:var(--accent-deep)}
.rt-events td.num,.rt-events th.num{text-align:right;font-family:var(--f-mono);font-variant-numeric:tabular-nums}
.rt-events tbody tr{cursor:pointer}
.rt-events tbody tr:hover{background:var(--surface-2)}
.rt-events .rt-rate{display:flex;align-items:center;gap:8px;justify-content:flex-end}
.rt-events .rt-rate .rt-bar{width:84px;flex:none}
.rt-mode{display:inline-flex;align-items:center;padding:1px 7px;border-radius:99px;border:1px solid var(--line);
  font-size:11px;color:var(--ink-dim);white-space:nowrap;background:var(--surface)}

/* one event: its waves */
.rt-head-badges{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-top:9px}
.rt-wave{margin-bottom:14px;overflow:hidden}
.rt-wave__head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:14px 18px 10px}
.rt-wave__title{font-family:var(--f-display);font-weight:700;font-size:15px;color:var(--ink)}
.rt-wave__meta{font-size:12px;color:var(--ink-faint)}
.rt-phases{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;background:var(--line-soft);
  border-top:1px solid var(--line-soft);border-bottom:1px solid var(--line-soft)}
.rt-phase{background:var(--surface);padding:12px 18px 13px;min-width:0}
.rt-phase__label{font-size:12px;color:var(--ink-dim)}
.rt-phase__value{display:flex;align-items:baseline;gap:8px;margin:5px 0 8px;flex-wrap:wrap}
.rt-phase__value b{font-family:var(--f-display);font-weight:750;font-size:21px;letter-spacing:-.3px;color:var(--ink)}
.rt-phase__value span{font-size:12px;color:var(--ink-dim)}
.rt-track{position:relative;height:40px;margin:12px 18px 14px;border-bottom:1px solid var(--line)}
.rt-track__b{position:absolute;bottom:0;width:10px;display:flex;flex-direction:column-reverse;gap:1px;cursor:pointer}
.rt-track__b i{display:block;width:100%;border-radius:2px 2px 0 0}
.rt-track__b i+i{border-radius:2px 2px 0 0}
.rt-track__b .won{background:var(--rt-won)}
.rt-track__b .beaten{background:var(--rt-beaten)}
.rt-track__b .open{background:var(--rt-open)}
.rt-track__b .pending{background:var(--ink-ghost)}
.rt-track__b .skipped{background:var(--line-strong)}
.rt-track__ax{display:flex;justify-content:space-between;margin:-10px 18px 10px;font-family:var(--f-mono);font-size:10px;color:var(--ink-faint)}
.rt-note{font-size:12px;color:var(--ink-faint);line-height:1.5;margin:10px 2px 0}
.rt-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.rt-busy{font-size:12px;color:var(--ink-faint)}
.rt-stale{opacity:.6;transition:opacity .2s}

@media (max-width:900px){
  .rt-burst__row,.rt-bursts--event .rt-burst__row{grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;padding:12px 14px}
  .rt-burst__row>.rt-when{grid-column:1}
  .rt-burst__row>.rt-verdict{grid-column:2;grid-row:1;justify-self:end}
  .rt-burst__row>.rt-ev,.rt-burst__row>.rt-win,.rt-burst__row>.rt-qty,.rt-burst__row>.rt-kinds{grid-column:1 / -1}
  .rt-burst__row>.rt-chev,.rt-burst__row>.rt-dur{display:none}
  .rt-qty br{display:none}
  .rt-qty .rt-sep{display:inline}
  .rt-phases{grid-template-columns:1fr}
  .rt-hero__big{font-size:40px}
  .rt-controls{position:relative}
  .rt-gaps{position:static}
  .rt-gaps__pop{right:auto;left:0;width:min(300px,calc(100vw - 32px))}
}
@media (prefers-reduced-motion: reduce){.rt-live.is-live{animation:none}.rt-burst.is-new>.rt-burst__row{animation:none}}

/* the Market tab (the stored seat map, sections and prices) */
.rt-map{min-height:200px}
.price-chips{display:inline-flex;gap:6px;flex-wrap:wrap}
.price-chip{font-family:var(--f-mono);font-size:11px;font-weight:600;color:var(--ink-dim);
  border:1px solid var(--line);border-radius:999px;padding:2px 9px;background:var(--surface);cursor:pointer}
.price-chip.on{background:var(--sonar-dim);border-color:var(--sonar);color:var(--sonar-deep)}
.rke-back{color:var(--ink-faint);text-decoration:none;font-size:11px}
.rke-back:hover{color:var(--ink)}

/* ============================ Queue — queue-gated carting ============================
   Two views (queue.html / queue.js). THE BOARD answers "how is every queue doing?" at a glance:
   one lane per event, every running lane drawn on ONE shared log scale (front of the line at the
   left) with its best place, in-line count and movement beside it. THE EVENT VIEW answers the same
   question for one queue in full — COMMAND -> THE LINE -> HEALTH -> WHO JOINS -> ROSTER.

   Colour is load-bearing and follows the console's existing semantics exactly — green = through /
   live / the front of the line, blue = in line, amber = wants a look, coral = dead. Nothing here is
   decorative; if a colour appears, it is carrying a status.
   ==================================================================================== */
.vs-tag.queue-tag { cursor: pointer; padding: 2px 5px; }
.vs-tag.queue-tag .ico { width: 12px; height: 12px; }

/* ---- SHARED with the Cards tab (checkout-log chips) — not queue-only, don't fold these in ----
   nowrap: these are single tokens ("2✓ 3✗", "U103 8") and breaking one across two lines reads as
   two separate chips. */
.q-chip { font-family: var(--f-mono); font-size: 10px; padding: 2px 7px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-dim);
  white-space: nowrap; }
.q-chip--on { background: var(--sonar-dim); border-color: var(--sonar); color: var(--sonar-deep); font-weight: 700; }
.q-chip--warn { background: var(--amber-dim); border-color: var(--amber-glow); color: var(--amber); font-weight: 700; }
.q-activity { display: flex; flex-wrap: wrap; gap: 5px; margin: 4px 0 8px; }
.btn--xs { font-size: 10.5px; padding: 2px 8px; }

/* `[hidden]` is a UA rule, and ANY class below that sets `display` beats it — which is how a hidden
   panel stays on screen. These win over every display rule in this block, whatever its specificity. */
.q-board[hidden], .q-event[hidden], .q-ev[hidden], .q-group[hidden], .q-empty[hidden],
.q-board__none[hidden], .q-drawer[hidden], .q-dpane[hidden], .q-health[hidden], .q-more[hidden],
.q-tok[hidden], .q-filters[hidden], #q-accounts-view[hidden], #q-log-view[hidden],
.q-hdr__acts .btn[hidden], .q-engines-none[hidden], #q-engines-none[hidden] { display: none !important; }

/* ---- page header ---- */
.q-sub { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 14px; margin: 8px 0 0;
  font-size: 13px; color: var(--ink-dim); }
.q-sub b { font-family: var(--f-mono); font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
/* "N running" — the only figure on the tab that answers "is anything still joining?", so it is the
   one thing in this line that is loud: the queue-gated count beside it stays high when all is off. */
.q-sub__run { font-family: var(--f-mono); font-size: 12px; color: var(--ink-faint); }
.q-sub__run.is-live { color: var(--sonar-deep); font-weight: 600; }
.q-sub__run.is-live::before { content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 7px;
  border-radius: 99px; background: var(--sonar); vertical-align: 1px; animation: qpulse 2.6s ease-in-out infinite; }
.q-sub__sum { display: inline-flex; flex-wrap: wrap; gap: 4px 12px; }
.q-sub__sum span { white-space: nowrap; }
.q-sub__sum .t b, .q-sub__sum .w b { color: var(--sonar-deep); }
.q-head__r { align-items: center; }
.q-hchip { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; white-space: nowrap;
  min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  font-family: var(--f-mono); font-size: 11px; padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-dim);
  transition: border-color .14s, background .14s; }
.q-hchip:hover { border-color: var(--line-strong); color: var(--ink); }
.q-hchip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.q-hchip b { font-weight: 600; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.q-hchip .ico { width: 14px; height: 14px; }
.q-hchip__dot { width: 7px; height: 7px; border-radius: 99px; background: var(--ink-ghost); flex: none; }
.q-hchip--good .q-hchip__dot { background: var(--sonar); }
.q-hchip--bad { border-color: var(--coral-glow); background: var(--coral-dim); color: var(--coral); }
.q-hchip--bad b { color: var(--coral); }
.q-hchip--bad .q-hchip__dot { background: var(--coral); }
.q-hchip.is-warn { border-color: var(--amber-glow); background: var(--amber-dim); color: var(--amber); }

/* ---- the board's toolbar ---- */
.q-bar { display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap; margin-bottom: 12px; }
.q-bsearch { position: relative; flex: 0 1 300px; min-width: 190px; display: flex; align-items: center; }
.q-bsearch .ico { position: absolute; left: 11px; width: 15px; height: 15px; color: var(--ink-faint); pointer-events: none; }
.q-bsearch input[type=search] { padding: 8px 34px 8px 34px; border-radius: 999px; background: var(--surface);
  font-size: 13px; }
.q-bsearch kbd { position: absolute; right: 10px; font-family: var(--f-mono); font-size: 10px; color: var(--ink-ghost);
  border: 1px solid var(--line); border-radius: 4px; padding: 0 5px; line-height: 16px; pointer-events: none; }
.q-bsearch input:focus + kbd { display: none; }
.q-bfilters { display: flex; flex-wrap: wrap; gap: 5px; flex: 1 1 auto; }
.q-bf { font-family: var(--f-body); font-size: 12px; font-weight: 600; padding: 6px 12px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-dim); cursor: pointer;
  white-space: nowrap; }
.q-bf b { font-family: var(--f-mono); font-weight: 500; font-size: 11px; color: var(--ink-faint); margin-left: 3px;
  font-variant-numeric: tabular-nums; }
.q-bf:hover { border-color: var(--line-strong); color: var(--ink); }
.q-bf:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.q-bf.is-on { background: var(--accent-dim); border-color: var(--accent-glow); color: var(--accent-deep); }
.q-bf.is-on b { color: var(--accent-deep); }
.q-bf.is-zero:not(.is-on) { opacity: .5; }
.q-bf.is-alert b { color: var(--amber); font-weight: 700; }
.q-bsort { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; font-size: 12px; color: var(--ink-faint); }
.q-bsort select { width: auto; padding: 7px 30px 7px 12px; font-size: 12.5px; border-radius: 999px; background-color: var(--surface); }

/* ---- the lanes ----
   One grid for every running lane AND the group header above them, so the shared ruler, each lane's
   line and each figure column line up down the whole board. The container query (not a viewport
   media query) is what decides when a lane stacks: the board's own width is what the line needs. */
.q-evs { --q-id-w: 322px; --q-fig-w: 400px; --q-gap: 18px;
  container: qboard / inline-size; display: flex; flex-direction: column; gap: 8px; }
.q-group { display: grid; grid-template-columns: var(--q-id-w) minmax(0, 1fr) var(--q-fig-w);
  column-gap: var(--q-gap); align-items: end; padding: 14px 15px 2px; }
.q-group:first-child { padding-top: 2px; }
.q-group__label { font-size: 12px; font-weight: 700; color: var(--ink-dim); white-space: nowrap; }
.q-group__label b { font-family: var(--f-mono); font-weight: 500; color: var(--ink-faint); margin-left: 4px; }
.q-group__ruler { position: relative; height: 15px; font-family: var(--f-mono); font-size: 9.5px;
  color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.q-group__ruler i { position: absolute; bottom: 0; transform: translateX(-50%); font-style: normal; white-space: nowrap; }
.q-group__ruler i.is-front { transform: none; color: var(--sonar-deep); }
.q-group__ruler i.is-end { transform: translateX(-100%); }

/* ---- headers by presale time (2026-10-09) ----
   A header with no running lane has no ruler to line up with: one row, the board's full width. */
.q-group:not(.is-live) { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px; }
.q-group__toggle { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px 9px; min-width: 0;
  max-width: 100%; margin-left: -6px; padding: 4px 8px 4px 6px; border: 0; border-radius: 7px; background: none;
  font: inherit; color: inherit; text-align: left; cursor: pointer; }
.q-group__toggle:hover { background: var(--surface-3); }
.q-group__toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.q-group__chev { width: 13px; height: 13px; flex: none; color: var(--ink-faint); transform: rotate(90deg);
  transition: transform .15s; }
.q-group.is-closed .q-group__chev { transform: none; }
.q-group--live .q-group__label { color: var(--sonar-deep); }
.q-group--hidden .q-group__label { color: var(--ink-faint); }
.q-group__hint { font-size: 11.5px; color: var(--ink-ghost); }
.q-group--time .q-group__toggle { flex: 1 1 auto; }
.q-group__when { font-size: 12.5px; color: var(--ink); white-space: nowrap; }
.q-group__when b { font-weight: 700; }
.q-group__when small { margin-left: 7px; font-size: 11.5px; font-weight: 500; color: var(--ink-faint); }
.q-group__n { font-family: var(--f-mono); font-size: 11px; font-weight: 500; color: var(--ink-faint); }
.q-group__what { flex: 1 1 160px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12px; color: var(--ink-dim); }
/* Countdowns to a presale: accent, amber within the hour, red within five minutes. */
.q-clock[data-q-urg] { display: inline-block; padding: 2px 8px; border-radius: 999px; white-space: nowrap;
  font-family: var(--f-mono); font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--accent-deep); background: var(--accent-dim); }
.q-clock[data-q-urg="soon"] { color: var(--amber); background: var(--amber-dim); }
.q-clock[data-q-urg="now"] { color: var(--coral); background: var(--coral-dim); }

.q-ev { position: relative; display: grid; grid-template-columns: var(--q-id-w) minmax(0, 1fr) var(--q-fig-w);
  grid-template-areas: "id track figs" "acts track figs"; column-gap: var(--q-gap); row-gap: 8px;
  padding: 13px 15px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  box-shadow: var(--shadow); cursor: pointer; text-align: left;
  transition: border-color .14s, box-shadow .14s; }
.q-ev:hover { border-color: var(--line-strong); box-shadow: 0 1px 2px rgba(16, 24, 40, .05), 0 10px 26px -14px rgba(16, 24, 40, .22); }
/* An outline, not a box-shadow: a stopped lane sets box-shadow: none and used to lose its ring. */
.q-ev:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* The lane's left edge carries its state: live green, down coral, paused amber, stopped nothing. */
.q-ev::before { content: ""; position: absolute; left: -1px; top: 10px; bottom: 10px; width: 3px;
  border-radius: 0 3px 3px 0; background: transparent; }
.q-ev.is-armed::before { background: var(--sonar); }
.q-ev.is-paused::before { background: var(--amber); }
.q-ev.is-down::before { background: var(--coral); }

.q-ev__id { grid-area: id; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.q-ev__top { display: flex; align-items: center; gap: 8px; min-width: 0; }
.q-ev__dot { width: 8px; height: 8px; border-radius: 99px; background: var(--ink-ghost); flex: none; }
/* A running queue is the only thing on the board that breathes. One live signal, so it means something. */
.q-ev.is-armed .q-ev__dot { background: var(--sonar); animation: qpulse 2.6s ease-in-out infinite; }
.q-ev.is-paused .q-ev__dot { background: var(--amber); animation: none; }
.q-ev.is-down .q-ev__dot { background: var(--coral); animation: none; }
@keyframes qpulse { 0%, 100% { box-shadow: 0 0 0 0 var(--sonar-glow); } 55% { box-shadow: 0 0 0 5px transparent; } }
.q-ev__name { font-weight: 700; font-size: 14px; letter-spacing: -.1px; flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.q-ev__meta { display: block; font-size: 11.5px; color: var(--ink-faint); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.q-ev__nums { display: flex; flex-wrap: wrap; gap: 2px 10px; font-family: var(--f-mono); font-size: 10.5px;
  color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.q-ev__nums b { font-weight: 600; color: var(--ink-dim); }
.q-ev__nums .t b, .q-ev__nums .w, .q-ev__nums .w b { color: var(--sonar-deep); }
.q-ev__nums .f b { color: var(--coral); }
.q-ev__flags { display: flex; flex-wrap: wrap; gap: 4px; }
.q-ev__flags:empty { display: none; }
/* The lane's presale: its kind, and (outside its own start-time header) when + the countdown. The text
   gives way (an ellipsis) to a long sale name; the countdown beside it never shrinks. */
.q-ev__ps { display: flex; min-width: 0; font-size: 11.5px; color: var(--ink-dim); }
.q-ev__ps:empty { display: none; }
.q-ps { display: flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%; }
.q-ps__t { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.q-ps > .q-clock { flex: none; white-space: nowrap; }
.q-ps > .q-clock:not([data-q-urg])::before { content: "· "; }
.q-ps .q-clock[data-q-urg] { padding: 1px 6px; font-size: 10.5px; }
.q-ps.is-live { color: var(--sonar-deep); }
.q-ps.is-idle, .q-ps.is-idle b { color: var(--amber); }

.q-ev__acts { grid-area: acts; display: flex; flex-wrap: wrap; align-items: center; gap: 5px; align-self: end; }
/* Scoped under .q-ev__acts: a bare .q-ev__edit loses to `.btn.sm` (two classes). */
.q-ev__acts .btn { padding: 4px 9px; font-size: 11.5px; gap: 5px; }
.q-ev__acts .btn svg { width: 13px; height: 13px; }
.q-ev__acts .ev-sales-btn { font-size: 10px; }   /* keep the console-wide DataIQ look (mono, accent) */
.q-ev__acts .q-ev__pin { padding: 4px 6px; color: var(--ink-ghost); }
.q-ev__acts .q-ev__pin:hover { color: var(--amber); }
.q-ev.is-pinned .q-ev__pin { color: var(--amber); border-color: var(--amber-glow); background: var(--amber-dim); }
.q-ev.is-pinned .q-ev__pin svg { fill: currentColor; }
.q-ev__acts .q-ev__hide { padding: 4px 6px; color: var(--ink-ghost); }
.q-ev__acts .q-ev__hide[hidden] { display: none !important; }
.q-ev__acts .q-ev__hide:hover:not(:disabled) { color: var(--ink); }
.q-ev__acts .q-ev__hide:disabled { opacity: .35; cursor: not-allowed; }
.q-ev.is-hidden { opacity: .78; }
.q-ev.is-hidden .q-ev__hide { color: var(--accent-deep); border-color: var(--accent-glow); background: var(--accent-dim); }
.q-ev__acts .q-ev__go.is-stop { color: var(--ink-dim); }
.q-ev__acts .btn.ghost.q-ev__go.is-stop:hover { color: var(--coral); border-color: var(--coral-glow); background: var(--coral-dim); }
/* The lane is the click target for opening the event, so its hover must not read as the buttons'. */
.q-ev__acts .btn.ghost:not(.ev-sales-btn):hover { background: var(--surface-3); border-color: var(--line-strong); }

/* The line, drawn in the lane. Decade gridlines are a background: on this log scale every power of
   ten is the same width, so --q-dec (set by queue.js from the shared scale) is all it needs. */
.q-ev__track { grid-area: track; display: flex; flex-direction: column; justify-content: center; min-width: 0; }
.q-ev__track:empty { display: none; }
.q-tr__strip { position: relative; display: block; height: 36px; border-radius: 7px; overflow: hidden;
  border: 1px solid var(--line-soft);
  background:
    linear-gradient(90deg, var(--sonar-dim), transparent 14%),
    repeating-linear-gradient(90deg, var(--line-soft) 0 1px, transparent 1px calc(100% / var(--q-dec, 5))),
    var(--surface-2); }
.q-tr__strip i { position: absolute; top: 8px; bottom: 8px; width: 2px; margin-left: -1px; border-radius: 1px;
  background: var(--accent); opacity: .32; }
.q-tr__med { position: absolute; top: 4px; bottom: 4px; width: 0; margin-left: -.5px; text-decoration: none;
  border-left: 1px dashed var(--accent-deep); opacity: .55; }
.q-tr__best { position: absolute; top: 50%; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 99px;
  background: var(--sonar); border: 2px solid var(--surface); box-shadow: 0 0 0 3px var(--sonar-glow); }
/* The back of the fleet: a hollow ring, so front and back read as a pair. */
.q-tr__worst { position: absolute; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 99px;
  background: var(--surface); border: 2px solid var(--ink-faint); }
.q-tr__msg { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  padding: 0 12px; font-size: 11.5px; color: var(--ink-faint); text-align: center; }
.q-tr__ends { display: flex; justify-content: space-between; gap: 10px; margin-top: 5px; font-family: var(--f-mono);
  font-size: 10.5px; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.q-tr__ends b { font-weight: 600; color: var(--ink-dim); }
.q-tr__thr b { color: var(--sonar-deep); }
.q-tr__lob { text-align: right; }

/* Best place · In line · Moving. Hairline-separated tiles (1px grid gap over a soft line colour). */
.q-ev__figs { grid-area: figs; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px;
  align-self: center; background: var(--line-soft); border: 1px solid var(--line-soft); border-radius: 8px; overflow: hidden; }
.q-ev__figs:empty { display: none; }
.q-lf { display: flex; flex-direction: column; min-width: 0; padding: 7px 12px 8px; background: var(--surface); }
.q-lf__v { font-family: var(--f-mono); font-size: 18px; font-weight: 600; letter-spacing: -.5px; line-height: 1.15;
  font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--ink); }
.q-lf__v small { font-size: 10.5px; font-weight: 400; letter-spacing: 0; color: var(--ink-faint); margin-left: 4px; }
.q-lf__k { order: -1; margin-bottom: 2px; font-size: 10.5px; color: var(--ink-faint); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
/* Two lines before it is cut: Queue-it's own ETA text ("more than an hour") has to be readable. */
.q-lf__s { min-height: 1.35em; margin-top: 2px; font-size: 11px; line-height: 1.3; color: var(--ink-dim);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.q-lf--good .q-lf__v { color: var(--sonar-deep); }
.q-lf--warn .q-lf__v { color: var(--amber); }
.q-lf--idle .q-lf__v { color: var(--ink-ghost); }

/* A stopped event is a compact row: nothing is polling it, so there is no line to draw. */
.q-ev.is-stopped { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "id acts";
  align-items: center; padding: 10px 15px; box-shadow: none; background: var(--surface); }
.q-ev.is-stopped .q-ev__track, .q-ev.is-stopped .q-ev__figs { display: none; }
.q-ev.is-stopped .q-ev__acts { align-self: center; justify-content: flex-end; }
.q-ev.is-stopped .q-ev__name { font-size: 13.5px; font-weight: 600; }

/* The board's empty states. */
.q-empty { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px;
  padding: 46px 20px 50px; border: 1px dashed var(--line-strong); border-radius: var(--radius); background: var(--surface); }
.q-empty > .ico { width: 30px; height: 30px; color: var(--accent); }
.q-empty h3 { font-size: 15px; }
.q-empty p { max-width: 52ch; margin: 0 0 8px; font-size: 13px; color: var(--ink-dim); }
.q-board__none { margin: 18px 0 0; text-align: center; font-size: 13px; color: var(--ink-faint); }

@container qboard (max-width: 1000px) {
  .q-group { display: block; padding: 12px 4px 0; }
  .q-group__ruler { display: none; }
  .q-ev { grid-template-columns: minmax(0, 1fr); grid-template-areas: "id" "track" "figs" "acts"; }
  .q-ev.is-stopped { grid-template-columns: minmax(0, 1fr); grid-template-areas: "id" "acts"; }
  .q-ev__figs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .q-ev.is-stopped .q-ev__acts { justify-content: flex-start; }
}
@container qboard (max-width: 520px) {
  .q-ev { padding: 12px; }
  .q-ev__figs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .q-lf { padding: 7px 9px 8px; }
  .q-lf__v { font-size: 16px; }
}

/* ======================= the event view ======================= */
.q-event { display: flex; flex-direction: column; gap: 14px; container: qevent / inline-size; }
/* The queue switcher: back to the board, and every running / pinned queue one click away. */
.q-switch { display: flex; align-items: center; gap: 10px; min-width: 0; }
.q-back { display: inline-flex; align-items: center; gap: 6px; flex: none; cursor: pointer;
  font-size: 12.5px; font-weight: 600; padding: 6px 12px 6px 9px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-dim); }
.q-back:hover { color: var(--ink); border-color: var(--line-strong); }
.q-back:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.q-back .ico { width: 15px; height: 15px; }
.q-switch__list { display: flex; gap: 6px; min-width: 0; overflow-x: auto; scrollbar-width: none; padding: 2px; }
.q-switch__list::-webkit-scrollbar { display: none; }
.q-sw { display: inline-flex; align-items: center; gap: 7px; flex: none; max-width: 260px; cursor: pointer;
  padding: 5px 11px 5px 10px; border-radius: 999px; border: 1px solid var(--line); background: var(--surface);
  color: var(--ink-dim); font-size: 12px; }
.q-sw:hover { border-color: var(--line-strong); color: var(--ink); }
.q-sw:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.q-sw.is-on { border-color: var(--accent-glow); background: var(--accent-dim); color: var(--accent-deep); }
.q-sw__dot { width: 7px; height: 7px; border-radius: 99px; background: var(--ink-ghost); flex: none; }
.q-sw.is-armed .q-sw__dot { background: var(--sonar); }
.q-sw.is-down .q-sw__dot { background: var(--coral); }
.q-sw__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.q-sw__n { font-family: var(--f-mono); font-size: 11px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.q-sw__n small { font-size: 10px; color: var(--ink-faint); margin-left: 6px; }

/* COMMAND */
.q-hdr { display: flex; align-items: flex-start; gap: 16px 24px; flex-wrap: wrap; padding: 16px 18px; }
.q-hdr__main { flex: 1 1 340px; min-width: 0; }
.q-hdr__title { display: flex; align-items: center; gap: 10px; min-width: 0; }
.q-hdr__title h2 { font-size: 21px; letter-spacing: -.3px; line-height: 1.2; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.q-hdr__dot { width: 10px; height: 10px; border-radius: 99px; background: var(--ink-ghost); flex: none; }
.q-hdr.is-armed .q-hdr__dot { background: var(--sonar); animation: qpulse 2.6s ease-in-out infinite; }
.q-hdr.is-down .q-hdr__dot { background: var(--coral); animation: none; }
.q-hdr__meta { display: flex; align-items: center; gap: 6px 10px; flex-wrap: wrap; margin-top: 7px;
  font-size: 12.5px; color: var(--ink-faint); }
.q-hdr__meta a { color: var(--accent-deep); text-decoration: none; }
.q-hdr__meta a:hover { text-decoration: underline; }
.q-meta__where { color: var(--ink-dim); }
.q-hdr__side { display: flex; flex-direction: column; align-items: flex-end; gap: 9px; flex: 0 1 auto; }
.q-hdr__acts, .q-hdr__tools { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.q-hdr__tools .btn svg { width: 14px; height: 14px; }
.q-hdr__tools .ev-sales-btn { font-size: 10.5px; }
.btn.q-clear { color: var(--coral); border-color: var(--coral-glow); }
.btn.q-clear:hover { background: var(--coral-dim); border-color: var(--coral); }
/* Page freshness — how long since the browser last heard from the hub. Quiet until it is not. */
.q-fresh { display: block; margin-top: 6px; font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-ghost); }
.q-fresh:empty { display: none; }
.q-fresh.is-stale { color: var(--amber); font-weight: 700; }
/* The panels below still describe the event just left until the first reply for this one lands. */
.q-event.is-loading .q-grid, .q-event.is-loading .q-roster, .q-event.is-loading .q-health { opacity: .4; transition: opacity .2s; }

/* HEALTH — one sentence about whether anything needs a human */
.q-health { display: flex; align-items: center; gap: 10px; padding: 11px 16px; font-size: 13px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); }
.q-health .ico { width: 16px; height: 16px; flex: none; }
.q-health__txt { flex: 1 1 auto; min-width: 0; }
.q-health--ok { border-color: var(--sonar-glow); background: var(--sonar-dim); color: var(--sonar-deep); }
.q-health--warn { border-color: var(--amber-glow); background: var(--amber-dim); color: var(--amber); }
.q-health--bad { border-color: var(--coral-glow); background: var(--coral-dim); color: var(--coral); }

.q-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 14px; align-items: start; }
@container qevent (max-width: 900px) { .q-grid { grid-template-columns: minmax(0, 1fr); } }

/* THE LINE: the signature instrument. x is place in line, front on the LEFT. The bars are a density
   histogram of where the fleet is standing right now; the caps on either side hold the accounts that
   are OFF the scale — through it on the left, no number yet on the right. */
.q-line { padding: 15px 18px 0; }
.q-line__head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 11px; }
.q-line__title { font-size: 13px; font-weight: 700; color: var(--ink); }
.q-line__note { font-size: 11.5px; color: var(--ink-faint); }
.q-line__rig { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 9px; align-items: stretch; }
.q-cap { display: flex; flex-direction: column; align-items: center; justify-content: center; min-width: 70px;
  padding: 8px 11px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); }
.q-cap b { font-family: var(--f-mono); font-size: 19px; font-weight: 600; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--ink-dim); }
.q-cap span { font-size: 10.5px; color: var(--ink-faint); margin-top: 6px; text-align: center; }
.q-cap--through { border-color: var(--sonar-glow); background: var(--sonar-dim); }
.q-cap--through b { color: var(--sonar-deep); }
.q-cap.is-zero { opacity: .5; }
/* The floor tint is brightest at the front of the line — the left edge is the good end. */
.q-plot { position: relative; height: 112px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--accent-dim), transparent 55%); overflow: hidden; }
/* max-width matters at small N: without it, six accounts render as six slabs filling the panel,
   which reads as a wall rather than a short line. Capped, the bars stay ticks and the strip's
   LENGTH becomes a second honest reading — how many accounts are standing in the line at all. */
.q-plot__bars { position: absolute; left: 0; right: 0; top: 0; bottom: 18px;
  display: flex; align-items: flex-end; justify-content: flex-start; gap: 1px; padding: 10px 8px 0; }
.q-plot__bars i { flex: 1 1 0; min-width: 0; max-width: 9px; background: var(--accent);
  border-radius: 1.5px 1.5px 0 0; opacity: .78; }
.q-plot__axis { position: absolute; left: 0; right: 0; bottom: 0; height: 18px; display: flex;
  align-items: center; justify-content: space-between; gap: 8px; padding: 0 8px;
  border-top: 1px solid var(--line-soft); background: var(--surface);
  font-family: var(--f-mono); font-size: 9px; letter-spacing: .4px; color: var(--ink-faint);
  font-variant-numeric: tabular-nums; }
.q-plot__axis span { white-space: nowrap; }
.q-plot__empty { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 12px; color: var(--ink-faint); padding: 0 14px; text-align: center; }
@container qevent (max-width: 620px) {
  .q-line__rig { grid-template-columns: 1fr 1fr; }
  .q-line__rig > .q-plot { grid-column: 1 / -1; order: -1; }
  .q-cap { min-width: 0; }
}
/* Figures under the plot: hairline-separated by a 1px grid gap over a soft line colour. */
.q-figs { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 1px;
  background: var(--line-soft); margin-top: 15px; border-top: 1px solid var(--line-soft);
  border-radius: 0 0 var(--radius) var(--radius); overflow: hidden; }
.q-fig { background: var(--surface); padding: 11px 18px 13px; }
.q-fig__k { font-size: 11px; color: var(--ink-faint); }
.q-fig__v { font-family: var(--f-mono); font-size: 19px; font-weight: 600; letter-spacing: -.4px;
  line-height: 1.15; margin-top: 4px; font-variant-numeric: tabular-nums; }
.q-fig__v .u { font-size: 11px; color: var(--ink-faint); font-weight: 400; margin-left: 3px; letter-spacing: 0; }
.q-fig__s { font-size: 11px; color: var(--ink-dim); margin-top: 4px; }
.q-fig--good .q-fig__v { color: var(--sonar-deep); }
.q-fig--warn .q-fig__v { color: var(--amber); }
.q-fig--idle .q-fig__v { color: var(--ink-faint); }

/* WHO JOINS — frozen while the event runs, so it collapses out of the way then. */
.q-setup > summary { list-style: none; cursor: pointer; display: flex; align-items: center; flex-wrap: wrap;
  gap: 4px 10px; padding: 14px 16px; border-radius: var(--radius); }
.q-setup > summary::-webkit-details-marker { display: none; }
.q-setup > summary:hover { background: var(--surface-2); }
.q-setup > summary:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--accent-glow); }
.q-setup__t { display: inline-flex; align-items: center; gap: 7px; font-weight: 700; font-size: 13px; }
.q-setup__t .ico { width: 15px; height: 15px; color: var(--ink-faint); }
.q-setup__chev { margin-left: auto; color: var(--ink-faint); transition: transform .18s ease; }
.q-setup__chev .ico { width: 15px; height: 15px; }
.q-setup[open] .q-setup__chev { transform: rotate(90deg); }
.q-setup__sum { flex-basis: 100%; order: 3; font-family: var(--f-mono); font-size: 11px; color: var(--ink-faint);
  overflow-wrap: anywhere; }
.q-setup__body { display: flex; flex-direction: column; gap: 11px; padding: 12px 16px 16px; border-top: 1px solid var(--line-soft); }
.q-profile-list { display: flex; flex-wrap: wrap; gap: 7px; }
.q-profile { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; padding: 4px 10px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--surface); cursor: pointer; }
.q-profile:hover { border-color: var(--line-strong); }
.q-profile--all { align-self: flex-start; font-weight: 600; }
.q-race { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-dim); }
/* input.: the base rule is `input[type=number]{width:100%}` (0,1,1), so a bare class never wins
   and the race box stretched across the whole panel. */
input.q-race-input { width: 84px; padding: 6px 9px; font-size: 12.5px; }
.q-setup__note { margin: 0; font-size: 11.5px; color: var(--ink-faint); }
.q-locked { opacity: .5; }
.q-locked .q-profile { cursor: not-allowed; }

/* ROSTER */
.q-roster__head { display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap; padding: 12px 16px;
  border-bottom: 1px solid var(--line-soft); }
.q-search { flex: 1 1 220px; min-width: 160px; max-width: 360px; }
.q-roster .q-search { padding: 7px 12px; font-size: 13px; border-radius: 999px; background: var(--surface-2); }
.q-roster__count { margin-left: auto; font-family: var(--f-mono); font-size: 11px; color: var(--ink-faint); }
.q-filters { display: flex; gap: 5px; flex-wrap: wrap; padding: 10px 16px; border-bottom: 1px solid var(--line-soft); }
.q-filter { font-family: var(--f-body); font-size: 12px; font-weight: 600; padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-dim); cursor: pointer;
  white-space: nowrap; font-variant-numeric: tabular-nums; }
.q-filter b { font-family: var(--f-mono); font-size: 11px; font-weight: 500; color: var(--ink-faint); margin-left: 2px; }
.q-filter:hover { border-color: var(--line-strong); color: var(--ink); }
.q-filter:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.q-filter.is-on { background: var(--accent-dim); border-color: var(--accent-glow); color: var(--accent-deep); }
.q-filter.is-on b { color: var(--accent-deep); }
/* A filter matching nothing is dimmed, never hidden — "0 failed" is an answer, and a bar whose
   chips come and go between polls can't be learned. (Same rule as the Cards filter bar.) */
.q-filter.is-zero { opacity: .45; }
.q-filter.is-on.is-zero { opacity: 1; }
.q-tablewrap { overflow: auto; max-height: 66vh; }
.q-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12.5px; }
/* Sticky header: with hundreds of accounts you scroll far enough to forget which column is which. */
.q-table thead th { position: sticky; top: 0; z-index: 2; background: var(--surface); padding: 0;
  text-align: left; white-space: nowrap; border-bottom: 1px solid var(--line);
  font-size: 11px; font-weight: 600; color: var(--ink-faint); }
/* The sort control is a real <button> inside the <th> so it is focusable and announced as a control;
   aria-sort stays on the <th> where assistive tech expects it. */
.q-table th button { all: unset; box-sizing: border-box; display: flex; align-items: center; gap: 5px;
  width: 100%; padding: 10px 11px; cursor: pointer; font: inherit; color: inherit; }
.q-table th button:hover { color: var(--ink); background: var(--surface-2); }
.q-table th button:focus-visible { box-shadow: inset 0 0 0 2px var(--accent-glow); color: var(--ink); }
.q-table th.num button { justify-content: flex-end; }
/* The arrow always occupies its slot, so header text never shifts as you click between columns. */
.q-arw { font-size: 8px; opacity: 0; }
.q-table th.is-sorted { color: var(--accent-deep); }
.q-table th.is-sorted .q-arw { opacity: 1; }
/* Every cell is ONE line: a table of three hundred accounts at two heights cannot be scanned. Long
   values ellipsis inside their own cell instead. */
.q-table td { padding: 8px 11px; border-bottom: 1px solid var(--line-soft); vertical-align: middle; white-space: nowrap; }
.q-table td.prof { max-width: 140px; overflow: hidden; text-overflow: ellipsis; color: var(--ink-dim); }
/* The status line is the only unbounded string in the row (it carries Ticketmaster's own prose), so
   it is capped and ellipsised rather than allowed to set the table's width; the full text is one
   hover away in title=. */
.q-table td.st { max-width: 300px; width: 300px; }
.q-table tbody tr:hover td { background: var(--surface-2); }
.q-table td.num, .q-table th.num { text-align: right; }
.q-num { font-family: var(--f-mono); font-size: 11.5px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.q-num--ghost { color: var(--ink-ghost); }
.q-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; max-width: 270px; }
.q-who b { font-family: var(--f-mono); font-size: 11.5px; font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.q-who span { font-size: 10.5px; color: var(--ink-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Status: a dot carries the state, the words carry the detail. One line, always. */
.q-st { display: flex; align-items: center; gap: 7px; min-width: 0; }
.q-st__dot { width: 7px; height: 7px; border-radius: 99px; flex: none; background: var(--ink-ghost); }
.q-st__txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.q-st--through .q-st__dot { background: var(--sonar); }
.q-st--moving .q-st__dot { background: var(--accent); }
.q-st--attention .q-st__dot { background: var(--amber); }
.q-st--dead .q-st__dot { background: var(--coral); }
.q-st--attention .q-st__txt { color: var(--amber); }
.q-st--dead .q-st__txt { color: var(--coral); }
/* Purchased: the one row state that is an OUTCOME rather than a stage — a filled ring and the success
   colour, so "bought and gone" separates from "through and still racing" at a glance. */
.q-st--won .q-st__dot { background: var(--sonar); box-shadow: 0 0 0 3px var(--sonar-dim); }
.q-st--won .q-st__txt { color: var(--sonar-deep); font-weight: 500; }
/* Per-row travel: how far this account has come from the number it was given. */
.q-rail { display: flex; align-items: center; gap: 8px; min-width: 140px; }
.q-rail__t { position: relative; flex: 1 1 auto; height: 5px; border-radius: 99px; background: var(--surface-3); overflow: hidden; }
.q-rail__f { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 99px; background: var(--accent); }
.q-rail--done .q-rail__f { background: var(--sonar); }
.q-rail__n { font-family: var(--f-mono); font-size: 11.5px; font-variant-numeric: tabular-nums;
  white-space: nowrap; min-width: 64px; text-align: right; }
.q-more { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 12px;
  border-top: 1px solid var(--line-soft); font-size: 12px; color: var(--ink-faint); }
/* Actions column: the per-row Token / Release controls, PINNED to the right edge, so on a narrow
   window the one control anyone presses (Release) never scrolls out of reach. Opaque, and tracking
   the row hover, or the pinned cell stays pale over a highlighted row. */
.q-table td.q-acts { position: sticky; right: 0; z-index: 1; background: var(--surface);
  padding: 6px 11px 6px 6px; white-space: nowrap; text-align: right; }
.q-table tbody tr:hover td.q-acts { background: var(--surface-2); }
.q-table thead th:last-child { position: sticky; right: 0; z-index: 3; background: var(--surface); }
.q-acts .btn { padding-left: 8px; padding-right: 8px; }
.q-acts .btn + .btn { margin-left: 4px; }
/* The token control is an icon: it is on EVERY row. Its name lives in title + aria-label. */
.q-iconbtn { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 24px; padding: 0; }
.q-iconbtn .ico { width: 13px; height: 13px; }
/* The roster SHEDS COLUMNS rather than growing a horizontal scrollbar, in order of least use — each
   one is still in the payload, so widening the window brings it (and its sort header) back:
     ETA         Ticketmaster's own guess; the travel rail beside it already shows the position.
     Started at  a historical number; interesting once, not on every glance.
     Profile     nearly always the same value down the whole column, and it is searchable.
   Nothing that says whether an account is WORKING is ever dropped. The board is full width now (no
   event rail beside it), so these come in a good 300px later than they used to. */
@media (max-width: 1440px) {
  .q-table thead th:nth-child(6), .q-table tbody td:nth-child(6) { display: none; }   /* ETA */
}
@media (max-width: 1340px) {
  .q-table thead th:nth-child(4), .q-table tbody td:nth-child(4) { display: none; }   /* Started at */
  .q-table td.st { max-width: 260px; width: 260px; }
}
@media (max-width: 1240px) {
  .q-table thead th:nth-child(2), .q-table tbody td:nth-child(2) { display: none; }   /* Profile */
  .q-table td.st { max-width: 220px; width: 220px; }
  .q-who { max-width: 190px; }
}
@media (max-width: 1040px) {
  .q-table td.st { max-width: 170px; width: 170px; }
  .q-who { max-width: 150px; }
  .q-rail { min-width: 104px; }
}
/* Phone. Down to three things — who, where they are, and the controls. */
@media (max-width: 760px) {
  .q-table thead th:nth-child(3), .q-table tbody td:nth-child(3),
  .q-table thead th:nth-child(7), .q-table tbody td:nth-child(7) { display: none; }
  .q-table td, .q-table th button { padding-left: 8px; padding-right: 8px; }
  .q-rail { min-width: 70px; gap: 5px; }
  .q-rail__n { min-width: 44px; }
  /* A PIXEL cap, not 100%: inside an auto-layout table a percentage resolves against a cell sized by
     its own content, so the email would keep setting the column width and never ellipsise. */
  .q-who { max-width: 112px; }
  .q-who b { font-size: 11px; }
  .q-table td.q-acts { padding: 4px 6px 4px 4px; }
  .q-acts .btn { font-size: 10px; }
}

/* ---- Accounts | Log segmented control ---- */
.q-views { display: inline-flex; gap: 2px; padding: 2px; border: 1px solid var(--line);
  border-radius: 999px; background: var(--surface-2); }
.q-view { display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  font-size: 12px; font-weight: 600; padding: 5px 13px; border-radius: 999px;
  border: 1px solid transparent; background: transparent; color: var(--ink-dim); }
.q-view .ico { width: 13px; height: 13px; }
.q-view:hover { color: var(--ink); }
.q-view:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.q-view.is-on { background: var(--surface); border-color: var(--line-strong); color: var(--ink); }

/* ---- the log: what the queue did while nobody was watching ---- */
.q-log { list-style: none; margin: 0; padding: 0; max-height: 66vh; overflow: auto; }
.q-log__row { display: grid; grid-template-columns: 8px 52px minmax(0, 190px) minmax(0, 1fr);
  align-items: baseline; gap: 10px; padding: 8px 16px; border-bottom: 1px solid var(--line-soft); font-size: 12.5px; }
.q-log__row:hover { background: var(--surface-2); }
.q-log__dot { width: 6px; height: 6px; border-radius: 99px; background: var(--ink-ghost); align-self: center; }
.q-log__row--warn .q-log__dot { background: var(--amber); }
.q-log__row--error .q-log__dot { background: var(--coral); }
.q-log__t { font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-faint);
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.q-log__who { font-family: var(--f-mono); font-size: 11px; color: var(--ink-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.q-log__who i { font-style: normal; color: var(--ink-ghost); }
.q-log__msg { color: var(--ink); min-width: 0; }
.q-log__row--error .q-log__msg { color: var(--coral); }
.q-log__empty { padding: 34px 14px; text-align: center; color: var(--ink-faint); font-size: 12.5px; }
@media (max-width: 640px) {
  .q-log__row { grid-template-columns: 8px 52px minmax(0, 1fr); }
  .q-log__msg { grid-column: 2 / -1; }
}

/* ---- token inspection: one account, on demand ---- */
.q-tok { padding: 13px 16px; border-bottom: 1px solid var(--line-soft); background: var(--surface-2); }
.q-tok__head { display: flex; align-items: center; gap: 9px; margin-bottom: 8px; }
.q-tok__head b { font-family: var(--f-mono); font-size: 12px; flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; }
.q-tok__state { margin: 0 0 10px; font-size: 12px; }
.q-tok__state--good { color: var(--sonar-deep); }
.q-tok__state--warn { color: var(--amber); }
.q-tok__state--bad { color: var(--coral); }
.q-tok__state--idle { color: var(--ink-faint); }
.q-tok__f { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.q-tok__k { font-size: 11px; color: var(--ink-faint); flex: none; width: 126px; }
/* The value scrolls inside itself: a queueittoken is hundreds of characters. */
.q-tok__v { flex: 1 1 auto; min-width: 0; font-family: var(--f-mono); font-size: 11px;
  padding: 4px 8px; border: 1px solid var(--line); border-radius: 5px; background: var(--surface);
  color: var(--ink-dim); white-space: nowrap; overflow-x: auto; }
.q-tok__note { margin: 8px 0 0; font-size: 11.5px; color: var(--ink-faint); }
@media (max-width: 640px) {
  .q-tok__f { flex-wrap: wrap; }
  .q-tok__k { width: 100%; }
}

/* ======================= the settings drawer ======================= */
.q-drawer { position: fixed; inset: 0; z-index: 72; }
.q-drawer__scrim { position: absolute; inset: 0; background: var(--backdrop); backdrop-filter: blur(2px); }
.q-drawer__panel { position: absolute; top: 0; right: 0; bottom: 0; width: min(540px, 100vw);
  display: flex; flex-direction: column; background: var(--surface); border-left: 1px solid var(--line-strong);
  box-shadow: -18px 0 50px -28px rgba(16, 24, 40, .45); outline: none;
  animation: q-drawer-in .22s cubic-bezier(.2, .7, .3, 1) both; }
@keyframes q-drawer-in { from { transform: translateX(28px); opacity: 0; } }
.q-drawer__head { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 20px; border-bottom: 1px solid var(--line-soft); }
.q-drawer__head h2 { display: flex; align-items: center; gap: 8px; font-size: 16px; }
.q-drawer__head h2 .ico { width: 17px; height: 17px; color: var(--ink-faint); }
.q-drawer__tabs { display: flex; gap: 4px; padding: 10px 16px; border-bottom: 1px solid var(--line-soft); }
.q-dtab { cursor: pointer; font-size: 12.5px; font-weight: 600; padding: 6px 13px; border-radius: 999px;
  border: 1px solid transparent; background: transparent; color: var(--ink-dim); }
.q-dtab:hover { color: var(--ink); background: var(--surface-2); }
.q-dtab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.q-dtab.is-on { background: var(--accent-dim); border-color: var(--accent-glow); color: var(--accent-deep); }
.q-drawer__body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 16px 20px 24px; }
.q-dpane__intro { margin: 0 0 12px; font-size: 12px; line-height: 1.5; color: var(--ink-faint); }
.q-dpane__foot { position: sticky; bottom: -24px; display: flex; align-items: center; gap: 10px;
  margin: 14px -20px -24px; padding: 12px 20px 16px; border-top: 1px solid var(--line-soft); background: var(--surface); }
/* Queue settings: every [queue] key with its help text — a form rather than a checklist. */
.q-set__grp { border-top: 1px solid var(--line-soft); }
.q-set__grp > summary { list-style: none; cursor: pointer; padding: 10px 2px; font-size: 12px; font-weight: 700;
  color: var(--ink-dim); }
.q-set__grp > summary::-webkit-details-marker { display: none; }
.q-set__grp > summary:hover { color: var(--ink); }
.q-set__grp > summary b { color: var(--ink-ghost); font-weight: 500; font-family: var(--f-mono); }
.q-set__row { padding: 9px 2px 11px; border-top: 1px solid var(--line-soft); }
.q-set__k { display: block; font-family: var(--f-mono); font-size: 11.5px; font-weight: 600;
  color: var(--ink); margin-bottom: 5px; overflow-wrap: anywhere; }
.q-set__v input[type="text"], .q-set__v input[type="number"] { width: 100%; box-sizing: border-box;
  font-size: 12px; padding: 6px 9px; }
.q-set__bool { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; font-size: 12px;
  font-family: var(--f-mono); color: var(--ink-dim); }
/* The help text is long-form prose from settings.toml, so it wraps — clamped so one talkative key
   cannot push the Save button out of reach. */
.q-set__h { margin: 6px 0 0; font-size: 11.5px; line-height: 1.45; color: var(--ink-faint);
  white-space: normal; overflow-wrap: anywhere; max-height: 7em; overflow-y: auto; }
/* Engines */
.q-engine { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center;
  gap: 6px 9px; cursor: pointer; font-size: 12.5px; padding: 9px 9px; border: 1px solid var(--line-soft);
  border-left: 3px solid var(--line); border-radius: 7px; }
.q-engine + .q-engine { margin-top: 6px; }
.q-engine.is-converged { border-left-color: var(--sonar); background: var(--sonar-dim); }
.q-engine-name { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.q-engine-role { grid-column: 2 / -1; display: flex; flex-wrap: wrap; gap: 3px 10px;
  color: var(--ink-faint); font-family: var(--f-mono); font-size: 10px; line-height: 1.45; }
.q-engine-convergence { color: var(--amber); font-weight: 600; }
.q-engine.is-converged .q-engine-convergence { color: var(--sonar-deep); }
.q-engine-outcomes { flex-basis: 100%; }
/* Proxy pool */
.q-pool { display: flex; flex-direction: column; gap: 10px; }
.q-pool__state { display: flex; align-items: center; gap: 9px; margin: 0; font-size: 13px; }
.q-pool--good .q-hchip__dot { background: var(--sonar); }
.q-pool--bad .q-hchip__dot { background: var(--coral); }
.q-pool--bad .q-pool__state { color: var(--coral); }
.q-pool__nums { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 0; }
.q-pool__nums span { padding: 10px 12px; border: 1px solid var(--line-soft); border-radius: 8px;
  background: var(--surface-2); font-family: var(--f-mono); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.q-pool__bad { margin: 0; font-family: var(--f-mono); font-size: 11.5px; color: var(--coral); }

/* ---- add-events modal ---- */
.q-add-help { margin: 8px 0 14px; font-size: 12px; color: var(--ink-faint); }
.q-add-cb { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-dim); cursor: pointer; }
.q-add-cb input { flex: none; }
.q-add-result { margin-top: 12px; padding: 9px 11px; border-radius: var(--radius-sm);
  border: 1px solid var(--line); background: var(--surface-2); font-size: 12px; color: var(--ink-dim); }
.q-add-result[hidden] { display: none; }
.q-add-result.is-bad { border-color: var(--coral); background: var(--coral-dim); color: var(--coral); }

@media (max-width: 880px) {
  .q-bsearch input[type=search], .q-bsort select, input.q-race-input, .q-roster .q-search { font-size: 16px; }
  .q-bsort { margin-left: 0; }
  .q-bsearch { flex: 1 1 100%; }
  .q-hdr__side { align-items: stretch; width: 100%; }
  .q-hdr__acts, .q-hdr__tools { justify-content: flex-start; }
}
@media (prefers-reduced-motion: reduce) {
  .q-ev.is-armed .q-ev__dot, .q-hdr.is-armed .q-hdr__dot, .q-sub__run.is-live::before {
    animation: none; box-shadow: 0 0 0 3px var(--sonar-dim); }
  .q-setup__chev { transition: none; }
  .q-drawer__panel { animation: none; }
}

/* =========================================================================================
   Shared Explorer window (explorer_modal.js)
   The live Explorer page, framed, for up to 10 events at once as browser-style tabs
   (templates/_explorer_modal.html; the Carts tab's group headers and the Queue tab open it).
   Everything is scoped under .xpw (the window) and .xpw-dock (the minimized pill).
   The root is NOT a .modal-backdrop: generic "hide any clicked .modal-backdrop" handlers
   (carts.js) must never be able to hide a window whose frames hold live hub sessions, so it
   carries its own scrim. Stacking: above every .modal-backdrop (70), so a window restored from
   the dock is never under a modal opened meanwhile; the dock above the window; both under the
   toasts (80).
   ========================================================================================= */
.xpw {
  position: fixed; inset: 0; z-index: 74;
  display: flex; align-items: center; justify-content: center; padding: 3vh 14px;
}
/* [hidden] is a UA rule and loses to any display set here (the sheet's per-class opt-back-in). */
.xpw[hidden], .xpw-dock[hidden], .xpw__addbtn[hidden], .xpw__picker[hidden], .xpw__filter[hidden],
.xpw__picknote[hidden], .xpw__pickempty[hidden] { display: none; }
/* Minimized: nothing painted, nothing hit, but the LAYOUT stays, so every Explorer behind it keeps
   its size and its connection and comes back without a re-layout. Never display:none here — the
   framed Explorer lays its seat map out against its own size. (Inactive tabs get the same treatment,
   inline, from explorer_modal.js.) */
.xpw.is-min { visibility: hidden; pointer-events: none; }
.xpw__scrim { position: absolute; inset: 0; background: var(--backdrop); backdrop-filter: blur(3px); }
.xpw__dialog {
  position: relative; display: flex; flex-direction: column;
  width: min(1560px, calc(100vw - 28px)); height: 94vh; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--radius);
  box-shadow: var(--shadow); animation: rise .22s cubic-bezier(.2,.7,.3,1) both;
}
.xpw__dialog:focus { outline: none; }

/* ---- title bar: the viewed event, how many are live, minimize, close every Explorer ---- */
.xpw__head { display: flex; align-items: center; gap: 14px; padding: 9px 10px 9px 16px; }
.xpw__id { display: flex; align-items: center; gap: 10px; flex: 1 1 auto; min-width: 0; }
.xpw__glyph { display: inline-flex; flex: none; color: var(--accent); }
.xpw__glyph svg { width: 17px; height: 17px; }
.xpw__name { margin: 0; min-width: 0; font-family: var(--f-display); font-size: 15px; font-weight: 700;
  color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.xpw__meta { min-width: 0; font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.xpw__meta:empty { display: none; }
.xpw__tools { display: flex; align-items: center; gap: 2px; flex: none; }
.xpw__count { margin-right: 8px; padding: 2px 9px; border: 1px solid var(--line); border-radius: 99px;
  background: var(--surface-2); font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-dim);
  white-space: nowrap; font-variant-numeric: tabular-nums; cursor: help; }
.xpw__count:empty { display: none; }
/* At the cap the next open closes the tab viewed least recently: say so before it happens. */
.xpw__count.is-full { color: var(--amber); border-color: var(--amber-glow); background: var(--amber-dim); }
.xpw__btn { display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 32px; height: 32px; padding: 0; border: 0; border-radius: 7px; background: none;
  color: var(--ink-faint); cursor: pointer; transition: background .12s, color .12s; }
.xpw__btn svg { width: 17px; height: 17px; }
.xpw__btn:hover { color: var(--ink); background: var(--surface-2); }
.xpw__btn--close:hover { color: var(--coral); background: var(--coral-dim); }

/* ---- the tab strip: reads like a browser's — the viewed tab is raised onto the page below it ---- */
.xpw__strip { position: relative; z-index: 2; display: flex; align-items: flex-end; gap: 8px;
  padding: 6px 10px 0; background: var(--surface-2); border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line); }
/* margin-bottom:-1px lets the active tab sit ON the strip's bottom rule and paint over it, so the
   tab and the Explorer under it read as one sheet. An overflowing strip scrolls sideways (touch,
   trackpad, and a plain wheel via explorer_modal.js) with no scrollbar, like a browser's. */
.xpw__tabs { position: relative; display: flex; align-items: flex-end; gap: 2px; flex: 0 1 auto;
  min-width: 0; margin-bottom: -1px; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.xpw__tabs::-webkit-scrollbar { display: none; }
.xpw__tab { position: relative; display: flex; align-items: center; flex: 0 1 216px; min-width: 112px;
  height: 34px; border: 1px solid transparent; border-bottom: 0; border-radius: 8px 8px 0 0;
  color: var(--ink-dim); transition: background .12s, color .12s; }
.xpw__tab:hover { background: var(--surface-3); color: var(--ink); }
.xpw__tab.is-active { background: var(--abyss); border-color: var(--line); color: var(--ink);
  box-shadow: inset 0 2px 0 var(--accent); }
.xpw__tabsel { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; height: 100%;
  padding: 0 4px 0 12px; border: 0; border-radius: 8px 0 0 0; background: none; color: inherit;
  font-family: var(--f-display); font-size: 12.5px; font-weight: 600; text-align: left; cursor: pointer; }
.xpw__tabname { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.xpw__tab.is-down .xpw__tabname { color: var(--ink-faint); font-weight: 500; }
.xpw__tab.is-evicted .xpw__tabname { font-style: italic; }
.xpw__tabx { display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 20px; height: 20px; margin-right: 7px; padding: 0; border: 0; border-radius: 5px;
  background: none; color: var(--ink-faint); cursor: pointer; opacity: 0;
  transition: opacity .12s, background .12s, color .12s; }
.xpw__tabx svg { width: 13px; height: 13px; }
.xpw__tab:hover .xpw__tabx, .xpw__tab.is-active .xpw__tabx, .xpw__tabx:focus-visible { opacity: 1; }
.xpw__tabx:hover { color: var(--ink); background: var(--surface-3); }
@media (hover: none) { .xpw__tabx { opacity: 1; } }

/* live = sonar green, breathing gently; connecting = amber; closed / never connected = a ghost ring */
.xpw__dot, .xpw-dock__dot { flex: none; width: 7px; height: 7px; border-radius: 99px; background: var(--ink-ghost); }
.xpw__dot.is-live, .xpw-dock__dot.is-live { background: var(--sonar); animation: xpw-pulse 2.6s ease-in-out infinite; }
.xpw__dot.is-connecting, .xpw-dock__dot.is-connecting { background: var(--amber); }
.xpw__dot.is-closed, .xpw__dot.is-idle, .xpw-dock__dot.is-closed {
  background: transparent; box-shadow: inset 0 0 0 1.5px var(--ink-ghost); }
@keyframes xpw-pulse { 0%, 100% { box-shadow: 0 0 0 0 var(--sonar-glow); } 55% { box-shadow: 0 0 0 5px transparent; } }

/* ---- Add: another event's Explorer, from the list the page hands over (setSource) ---- */
.xpw__add { position: relative; flex: none; align-self: center; margin-bottom: 3px; }
.xpw__addbtn { display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 10px 0 7px;
  border: 1px dashed var(--line-strong); border-radius: 7px; background: none; color: var(--ink-dim);
  font-family: var(--f-display); font-size: 12px; font-weight: 600; cursor: pointer;
  transition: background .12s, border-color .12s, color .12s; }
.xpw__addbtn svg { width: 14px; height: 14px; }
.xpw__addbtn:hover, .xpw__addbtn[aria-expanded="true"] { border-style: solid; border-color: var(--accent-glow);
  background: var(--accent-dim); color: var(--accent-deep); }
.xpw__picker { position: absolute; top: calc(100% + 8px); left: 0; z-index: 5; width: 340px;
  max-width: calc(100vw - 40px); padding: 6px; background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: var(--radius); box-shadow: var(--shadow);
  animation: rise .16s cubic-bezier(.2,.7,.3,1) both; }
.xpw__pickhead { padding: 6px 8px 5px; font-family: var(--f-mono); font-size: 9.5px; letter-spacing: .8px;
  text-transform: uppercase; color: var(--ink-faint); }
.xpw__picknote { margin: 0 8px 6px; font-size: 11.5px; color: var(--amber); }
.xpw__filter { width: 100%; margin: 0 0 6px; padding: 6px 9px; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--surface-2); color: var(--ink);
  font-family: var(--f-body); font-size: 12.5px; }
.xpw__filter:focus { outline: none; border-color: var(--accent); }
.xpw__picklist { list-style: none; margin: 0; padding: 0; max-height: min(360px, 52vh); overflow-y: auto; }
.xpw__pick { display: flex; flex-direction: column; gap: 1px; width: 100%; padding: 7px 9px; border: 0;
  border-radius: var(--radius-sm); background: none; color: var(--ink); text-align: left; cursor: pointer; }
.xpw__pick:hover, .xpw__pick:focus-visible { outline: none; background: var(--accent-dim); }
.xpw__pickname { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.xpw__pickmeta { font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-faint);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.xpw__pickempty { margin: 6px 8px; font-size: 12px; color: var(--ink-faint); }

/* ---- the Explorers: every frame mounted and stacked; explorer_modal.js shows the viewed one ---- */
.xpw__body { position: relative; flex: 1 1 auto; min-height: 0; background: var(--abyss); }
.xpw__frame { position: absolute; inset: 0; display: block; width: 100%; height: 100%; border: 0;
  background: var(--abyss); }

/* keyboard focus is drawn INSIDE each control: the tab strip clips anything outside it */
.xpw__btn:focus-visible, .xpw__tabsel:focus-visible, .xpw__tabx:focus-visible, .xpw__addbtn:focus-visible,
.xpw-dock__open:focus-visible, .xpw-dock__close:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* ---- the dock: minimized, with every Explorer still live behind it ---- */
.xpw-dock { position: fixed; right: 18px; bottom: 18px; z-index: 75; display: inline-flex;
  align-items: stretch; overflow: hidden; background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: 99px; box-shadow: var(--shadow); animation: toast-in .25s ease both; }
.xpw-dock__open { display: inline-flex; align-items: center; gap: 9px; padding: 8px 13px 8px 15px;
  border: 0; border-radius: 99px 0 0 99px; background: none; color: var(--ink);
  font-family: var(--f-display); font-size: 12.5px; font-weight: 600; white-space: nowrap;
  cursor: pointer; transition: background .12s; }
.xpw-dock__open:hover { background: var(--surface-2); }
.xpw-dock__open b { font-family: var(--f-mono); font-weight: 600; font-variant-numeric: tabular-nums; }
.xpw-dock__dot { width: 8px; height: 8px; }
.xpw-dock__close { display: inline-flex; align-items: center; justify-content: center; width: 38px;
  padding: 0; border: 0; border-left: 1px solid var(--line); border-radius: 0 99px 99px 0;
  background: none; color: var(--ink-faint); cursor: pointer; transition: background .12s, color .12s; }
.xpw-dock__close svg { width: 15px; height: 15px; }
.xpw-dock__close:hover { color: var(--coral); background: var(--coral-dim); }
/* The dock sits where the toasts stack: while it shows (explorer_modal.js setDock) they stack just
   above it rather than covering it for seconds at a time. */
body.has-xpw-dock .toasts { bottom: calc(max(18px, env(safe-area-inset-bottom)) + 48px); }

/* Phone: the window IS the screen, the meta line goes (each tab's tooltip still carries it), and
   every control grows to a real tap target. */
@media (max-width: 640px) {
  .xpw { padding: 0; }
  .xpw__dialog { width: 100%; height: 100%; border: 0; border-radius: 0; }
  .xpw__meta { display: none; }
  .xpw__head { gap: 8px; padding: max(6px, env(safe-area-inset-top)) 6px 6px 12px; }
  .xpw__btn { width: 40px; height: 40px; }
  .xpw__tab { flex-basis: 156px; min-width: 104px; height: 40px; }
  .xpw__tabx { width: 28px; height: 28px; margin-right: 5px; }
  .xpw__addbtn { height: 34px; }
  .xpw-dock { right: max(12px, env(safe-area-inset-right)); bottom: max(12px, env(safe-area-inset-bottom)); }
  .xpw-dock__open { min-height: 44px; }
  .xpw-dock__close { width: 44px; }
  body.has-xpw-dock .toasts { bottom: calc(max(12px, env(safe-area-inset-bottom)) + 56px); }
}
@media (prefers-reduced-motion: reduce) {
  .xpw__dot.is-live, .xpw-dock__dot.is-live { animation: none; box-shadow: 0 0 0 3px var(--sonar-dim); }
  .xpw__dialog, .xpw__picker, .xpw-dock { animation: none; }
}

/* ---- Orders: PO Account (also rendered per-row in Sales > Missing) ---------------------- */
.po-wrap { display: inline-flex; align-items: center; gap: 8px; }
.po-btn { white-space: nowrap; }
.po-cell { white-space: nowrap; }
.po-pill[hidden] { display: none; }
.po-pill .po-pill-txt:empty { display: none; }
.po-curl { width: 100%; box-sizing: border-box; font-family: var(--f-mono); font-size: 12px;
  resize: vertical; border: 1px solid var(--line-strong); border-radius: 6px; padding: 10px;
  background: var(--surface-2); color: var(--ink); word-break: break-all; }
.po-field-label { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--ink-faint); margin: 10px 0 4px; }
.po-log-meta { font-family: var(--f-mono); font-size: 12px; color: var(--ink-faint); margin-bottom: 12px; }
.po-step { margin-bottom: 18px; }
.po-step-h { font-weight: 600; font-size: 13px; margin-bottom: 6px; color: var(--ink); }
.po-sub { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-faint);
  margin: 8px 0 4px; }
.po-pre { background: var(--surface-2); border: 1px solid var(--line-soft); border-radius: 6px;
  padding: 10px; overflow-x: auto; font-family: var(--f-mono); font-size: 11.5px;
  white-space: pre-wrap; word-break: break-word; max-height: 320px; overflow-y: auto; margin: 0; }
.po-note { color: var(--ink-faint); font-size: 12px; margin: 6px 0; }

/* =========================================================================================
   PROVISIONING PANEL — "Add a server" (top of Settings, moved off the Dashboard)
   ========================================================================================= */
.provision { margin-bottom: var(--gap); }
.provision__head { cursor: pointer; list-style: none; gap: 12px; align-items: center; }
.provision__head::-webkit-details-marker { display: none; }
.provision__icon {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 32px; height: 32px; border-radius: 8px;
  background: var(--accent-dim); color: var(--accent);
}
.provision__icon .ico { width: 17px; height: 17px; }
.provision__titles { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.provision__titles .sub { font-family: var(--f-body); font-size: 12.5px; color: var(--ink-dim); }
.provision__chev {
  flex: none; width: 16px; height: 16px; color: var(--ink-faint);
  transition: transform .18s ease;
}
.provision[open] .provision__chev { transform: rotate(90deg); }
.provision__head:hover .provision__chev { color: var(--ink); }

.cmd { margin-bottom: 14px; }
.cmd:last-of-type { margin-bottom: 0; }
.cmd__lbl {
  font-family: var(--f-mono); font-size: 9.5px; letter-spacing: 1.4px; text-transform: uppercase;
  color: var(--ink-faint); margin-bottom: 6px;
}
.cmd__row { display: flex; gap: 8px; align-items: stretch; }
.cmd__code {
  flex: 1; min-width: 0;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 10px 12px; font-size: 12px; line-height: 1.5; color: var(--ink);
  overflow-x: auto; white-space: pre;
}
.cmd__btn { flex: none; align-self: stretch; }

/* =========================================================================================
   MOBILE — EVENT ROWS AS REAL CARDS
   The generic table->card layer turns every <td> into a labelled full-width line, which for an
   event meant ~8 stacked lines and a pile of loose glyphs. These rules lay the same cells out on
   a small grid instead: identity on top, the three inputs as a labelled 3-up, the pill strip on
   its own line, and gates/actions on one final row. Every card gets the same shape.
   Selectors carry `table.data.ev-table` so they outrank the generic `table.data:not(.no-cards) td`.
   ========================================================================================= */
@media (max-width: 640px) {
  .ev-pagination { align-items: stretch; flex-direction: column; padding: 12px; }
  .ev-pagination__actions { justify-content: space-between; }

  table.data.ev-table { display: block; table-layout: auto; min-width: 0; }
  table.data.ev-table colgroup { display: none; }
  table.data.ev-table tbody { display: block; }

  /* The select checkbox is taken OUT of the grid and pinned to the card's top-left corner.
     Leaving it in the flow forced column 1 to the checkbox's ~20px, which then squashed the ACO
     toggle sharing that column. Out of flow, every control row gets its full width back. */
  /* Six columns, not three: the qty/offer row needs genuinely equal cells, and the ACO pair above
     it splits 2/4 so the longer "ACO (Cart Holds)" label keeps its own full-size touch target.
     Gates and actions each get their OWN full-width row. They used to share one row 50/50 (three
     gate tags | three action buttons, ~136px each), but the actions grew to five with Sales and
     Explorer. Every 6-column split is symmetric, so no reshuffle
     (2/4, shrinking the tags) buys the actions enough room; only a full-width row does, and that
     keeps the 40px touch targets instead of squeezing eight controls onto one line. */
  table.data.ev-table tbody tr {
    position: relative;
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    grid-template-areas:
      "main  main  main  main  main  main"
      "aco   aco   acoh  acoh  acoh  acoh"
      "qty   qty   qty   offer offer offer"
      "flt   flt   flt   flt   flt   flt"
      "gates gates gates gates gates gates"
      "act   act   act   act   act   act";
    gap: 11px 10px; align-items: center;
    padding: 13px 14px 13px 44px; margin-bottom: 10px;
  }
  table.data.ev-table td.ev-sel {
    position: absolute; left: 13px; top: 14px; width: auto; padding: 0;
  }
  table.data.ev-table tbody td {
    display: block; padding: 0; border-bottom: 0; min-height: 0;
    text-align: left; white-space: normal;
  }
  /* only the three inputs keep a caption; everything else is self-evident */
  table.data.ev-table tbody td::before { content: none; }
  table.data.ev-table tbody td.ev-aco::before,
  table.data.ev-table tbody td.ev-acoh::before,
  table.data.ev-table tbody td.ev-qty::before,
  table.data.ev-table tbody td.ev-offer::before {
    content: attr(data-label); display: block;
    font-family: var(--f-mono); font-size: 9px; letter-spacing: 1px; text-transform: uppercase;
    color: var(--ink-faint); font-weight: 500; margin-bottom: 5px; text-align: left;
  }

  table.data.ev-table td.ev-main  { grid-area: main; min-width: 0; }
  table.data.ev-table td.ev-aco   { grid-area: aco; }
  table.data.ev-table td.ev-acoh  { grid-area: acoh; }
  table.data.ev-table td.ev-qty   { grid-area: qty; }
  table.data.ev-table td.ev-offer { grid-area: offer; }
  table.data.ev-table td.ev-flt   { grid-area: flt; min-width: 0; }
  table.data.ev-table td.ev-gates { grid-area: gates; }
  table.data.ev-table td.ev-act   { grid-area: act; text-align: right; }

  /* the title may use two lines on a phone — but every card still clamps at the same 2 */
  .ev-main .t-primary {
    white-space: normal; overflow: hidden; text-overflow: ellipsis;
    display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical;
    font-size: 14px; line-height: 1.3;
  }
  .ev-meta { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2;
             -webkit-box-orient: vertical; font-size: 11.5px; margin-top: 3px; }

  .ev-aco .toggle, .ev-acoh .toggle { width: 100%; min-height: 38px; font-size: 12px; }
  .ev-qty .inp-mini, .ev-offer .inp-mini { width: 100%; font-size: 16px; padding: 9px 10px; }

  /* gates + actions: 40px targets, spaced apart, never a cluster of tiny glyphs */
  .ev-gates { display: flex; gap: 8px; }
  /* the literal-letter glyphs (M, T) carry a 18px min-width on desktop; on the phone they get the
     same 40px target as the icon glyphs so a thumb aimed at T cannot land on M */
  .ev-gates > .vs-tag.monitor-tag, .ev-gates > .vs-tag.turbo-tag { min-width: 40px; }
  .ev-gates > * {
    margin-right: 0; min-width: 40px; min-height: 38px;
    justify-content: center; border-radius: 8px; font-size: 11px;
  }
  .ev-gates .ico { width: 16px; height: 16px; }
  .ev-act { display: flex; gap: 8px; justify-content: flex-end; }
  .ev-act > .icon-btn {
    margin-left: 0; min-width: 40px; min-height: 38px;
    align-items: center; justify-content: center; border-radius: 8px;
  }
  .ev-act .ico { width: 16px; height: 16px; }

  .filt-cell { gap: 6px; padding-bottom: 2px; }
  .filt-cell .pill, .filt-cell .vs-tag { min-height: 24px; }

  /* ---- the chrome above the list ----
     This, not the cards, is what made the phone view unusable: 620px of header on an 844px
     screen left room for exactly ONE event. Seven action buttons stacked 2-up came to 200px,
     and a full-width sort select above a full-width search box came to another 119px.
     Both become single scrolling lines. */
  .ev-page-head { gap: 10px; margin-bottom: 12px; }
  .ev-page-head .page-head__r {
    display: flex; grid-template-columns: none;      /* drop the shared 2-up phone grid */
    flex-wrap: nowrap; gap: 7px; overflow-x: auto;
    scrollbar-width: none; -ms-overflow-style: none;
    /* MUST be flex-start. The desktop rule sets justify-content:flex-end, and in a horizontal
       scroll container that pushes the overflow off the LEFT edge, where scrollLeft cannot reach
       it — the first four buttons render at negative x and are simply unreachable. */
    justify-content: flex-start;
  }
  .ev-page-head .page-head__r::-webkit-scrollbar { display: none; }
  .ev-page-head .page-head__r form { display: contents; }
  .ev-page-head .page-head__r .btn {
    width: auto; flex: none; padding: 7px 11px; font-size: 12px; min-height: 36px;
  }
  /* "Add by artist" is the reason this page gets opened — it leads the row instead of sitting
     seven swipes to the right. */
  .ev-page-head .page-head__r .btn.primary { order: -1; grid-column: auto; }

  .panel__head.ev-head { padding: 10px 12px 9px; }
  /* Both rows carry `.panel__head.ev-head >` so they outrank the generic
     `.panel__head > div:not(.sub) { flex-wrap: wrap }` phone rule — without it the chips wrap
     onto a line of their own below the select-all and the toolbar grows ~20px. */
  .panel__head.ev-head > .ev-head__r1 { gap: 8px; flex-wrap: nowrap; }
  /* title, sort and search share ONE line: "Events" is already the page heading right above, so
     the h2 only has to carry the count. */
  .ev-head__r1 h2 { flex: none; margin-right: 0; font-size: 13px; white-space: nowrap; }
  /* "Events" is already the page heading two rows up, so the phone keeps only the number —
     ellipsising "Monitored events · 127" down to "Monitored eve…" hid the one useful part. */
  .ev-head__ttl { display: none; }
  .ev-head__r1 h2 .muted { color: var(--ink-dim); }

  /* six chips scroll on one line rather than stacking six deep */
  .panel__head.ev-head > .ev-head__r2 { flex-wrap: nowrap; gap: 8px; margin-top: 8px; padding-top: 8px; }
  /* width:auto, not the 100% the shared phone rule gives .flt-chips — at 100% it claims the whole
     line and pushes itself below the select-all it is supposed to sit beside. */
  .ev-head__r2 .flt-chips { width: auto; }
  .ev-head__r2 .flt-chips {
    flex: 1 1 auto; flex-wrap: nowrap; min-width: 0;
    overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
  }
  .ev-head__r2 .flt-chips::-webkit-scrollbar { display: none; }
  .ev-head__r2 .flt-chip { flex: none; }
  .ev-selall span { display: none; }        /* the box alone, with its title= — the label costs a third of the row */
  .ev-selall::after {
    content: "all"; font-family: var(--f-mono); font-size: 10px; color: var(--ink-faint);
  }
}

/* =========================================================================================
   MOBILE — ENGINE ROWS
   Same problem, same cure: the status/name/meta/seen/actions flex row used to wrap into a
   ragged pile with 24px tap targets. Give each part its own line and the actions real buttons.
   ========================================================================================= */
@media (max-width: 880px) {
  .eng { padding: 14px; }
  .eng__top { flex-wrap: wrap; row-gap: 9px; column-gap: 8px; }
  .eng__name { max-width: none; flex: 1 1 auto; min-width: 0; font-size: 14.5px; }
  .eng__state { min-width: 0; }
  .eng__meta { flex: 1 1 100%; order: 5; font-size: 11px; }
  .eng__spacer { display: none; }
  .eng__seen { order: 6; font-size: 11px; }
  .eng__actions { order: 7; margin-left: auto; gap: 8px; }
  .eng__actions .icon-btn {
    min-width: 42px; min-height: 38px;
    align-items: center; justify-content: center; border-radius: 8px;
  }
  .eng__actions .ico { width: 16px; height: 16px; }

  /* select and pool strip each take their own full-width row rather than competing for one */
  .eng__bot { margin-top: 11px; row-gap: 9px; }
  .eng__bot select { flex: 1 1 100%; width: 100%; max-width: none; min-width: 0; font-size: 16px; padding: 10px 30px 10px 11px; }
  /* pools scroll as one strip rather than wrapping into a block that shoves the row taller */
  .pool-cell {
    flex-wrap: nowrap; overflow-x: auto; width: 100%;
    scrollbar-width: none; -ms-overflow-style: none; padding-bottom: 2px;
  }
  .pool-cell::-webkit-scrollbar { display: none; }
  .pool-cell > .pill { flex: none; }

  /* fleet-wide buttons: even 2-up grid instead of a ragged wrap */
  .eng-tools { width: 100%; justify-content: flex-start; }
  .eng-tools__btns { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; width: 100%; }
  .eng-tools__btns .btn { width: 100%; justify-content: center; }
}

/* =========================================================================================
   POLISH PASS — desktop
   ========================================================================================= */

/* Centre the content column. It was max-width'd but left-aligned, so every screen wider than
   1480px left a growing dead gutter on the right and the page looked off-centre. */
.content { margin-left: auto; margin-right: auto; }

/* The stat strip was pinned to 9 columns while the dashboard renders 11 cards, so two always
   orphaned onto a ragged second row. auto-fit fills whatever row it is on, at any count — and
   118px is small enough that all 11 land on one row on a normal desktop. */
.statline { grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); }

/* panels: slightly softer head, and a head that sits flush when the body is a table */
.panel__head h2 { line-height: 1.25; }
/* Edge gutters so a flush table's first/last columns line up with the panel head above them.
   TABLE MODE ONLY — below 640px these tables are cards, where a stray padding-left on the first
   cell shunts the absolutely-positioned select checkbox on top of the event title. */
@media (min-width: 641px) {
  .panel__body.flush > .table-wrap > table.data > thead > tr > th:first-child,
  .panel__body.flush > .table-wrap > table.data > tbody > tr > td:first-child { padding-left: 18px; }
  .panel__body.flush > .table-wrap > table.data > thead > tr > th:last-child,
  .panel__body.flush > .table-wrap > table.data > tbody > tr > td:last-child { padding-right: 18px; }
}

/* table rows: a real hover tint (was var(--surface) = white on a white panel, i.e. invisible) */
table.data tbody tr:hover { background: var(--surface-2); }
table.data th {
  position: sticky; top: 0; z-index: 2;
  background: var(--surface);
}

/* empty states were 46px of dead vertical space in a panel that is often short */
.empty { padding: 34px 20px; }
.empty svg { width: 32px; height: 32px; margin-bottom: 9px; }
.empty p { margin: 0; font-size: 12.5px; }

/* buttons in a page header line up on one baseline and never squash their labels */
.page-head__r .btn { white-space: nowrap; }

/* focus visibility across the console (keyboard operators + a11y) */
.btn:focus-visible, .icon-btn:focus-visible, .toggle:focus-visible,
select:focus-visible, input:focus-visible, textarea:focus-visible,
.vs-tag:focus-visible, .flt-chip:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px;
}

/* =========================================================================================
   POLISH PASS — mobile
   ========================================================================================= */
@media (max-width: 880px) {
  /* Page-header actions: an even 2-up grid. `flex:1 1 auto` produced a ragged ladder where a
     lone long button (AutoPrice rules) took a whole row and the rest paired unevenly. */
  .page-head__r {
    display: grid; grid-template-columns: 1fr 1fr; gap: 8px; width: 100%;
  }
  .page-head__r > * { min-width: 0; }
  .page-head__r .btn { width: 100%; justify-content: center; flex: none; }
  .page-head__r form { display: contents; }          /* let a wrapped form's button join the grid */
  .page-head__r form .btn { width: 100%; }
  /* the primary action gets the full width, so the main CTA is never half a row */
  .page-head__r .btn.primary { grid-column: 1 / -1; }

  /* Panel heads stack: title line, then its controls as a full-width row. */
  .panel__head { flex-direction: column; align-items: stretch; gap: 10px; }
  .panel__head > .row { width: 100%; flex-wrap: wrap !important; }
  .panel__head .sub { align-self: flex-start; }

  /* Events toolbar inside the panel head: chips scroll on one line, sort + search SHARE one.
     They used to stack full-width (two lines, 80px) because the head was a single row with no
     line to spare. It is a two-row toolbar now, so they fit side by side — worth ~60px of the
     screen, which on a phone is most of an event card. */
  .flt-chips {
    display: flex; width: 100%; overflow-x: auto; flex-wrap: nowrap;
    scrollbar-width: none; -ms-overflow-style: none; padding-bottom: 2px;
  }
  .flt-chips::-webkit-scrollbar { display: none; }
  .flt-chips .flt-chip { flex: none; min-height: 38px; }
  #eventSort { width: 128px !important; flex: 0 0 128px !important; }
  #eventFilter { width: auto !important; flex: 1 1 auto !important; min-width: 0 !important; }
  /* title + sort + artist fill line 1 and the search takes a full line under them: with the artist menu's fixed
     210px beside them the search was squeezed to ~50px (the row overflowed the phone) — no room to type, or for
     its X. */
  .panel__head.ev-head > .ev-head__r1 { flex-wrap: wrap; }
  #eventArtist { width: auto !important; flex: 1 1 0 !important; min-width: 0; }
  .sales-search.ev-search { flex: 1 1 100%; min-width: 0; max-width: none; }
  /* the head's own chips sit on a row shared with the select-all, so they trade a little of the
     38px touch height for a shorter toolbar */
  .ev-head__r2 .flt-chip { min-height: 32px; }

  /* Cards filter bar: each labelled group becomes ONE horizontally-scrolling line rather than
     wrapping — sixteen wrapped chips on a phone push the table most of a screen down. Overrides
     the desktop wrap rule, which is more specific than the .flt-chips reset above. */
  .cards-flt { padding: 9px 12px; gap: 8px; }
  .cards-flt .flt-chips { flex-wrap: nowrap; overflow-x: auto; }
  .cards-flt__lbl { width: 44px; padding-top: 11px; font-size: 9.5px; }
  /* 2-up, not full-width: four stacked selects push the table most of a screen down, and these are
     narrowings the operator reaches for AFTER the chips. The label takes its own line so the pairs
     line up evenly — sharing the first line with it leaves one select stretched to 1.7x the rest. */
  .cards-flt__row--sel .cards-flt__lbl { flex: 1 1 100%; padding-top: 0; }
  .cards-flt__row--sel select,
  .cards-flt__row--sel .btn-mini { flex: 1 1 calc(50% - 5px); min-width: 0; min-height: 38px;
    margin-left: 0; width: auto; }

  /* Bulk-selection bar: label on top, actions as an even 2-up grid. */
  #bulkBar { flex-direction: column; align-items: stretch !important; gap: 10px; }
  #bulkBar > .row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  #bulkBar .btn { width: 100%; justify-content: center; }

  /* Sticky table headers are hidden in card mode; drop the sticky so it can't trap a z-index. */
  table.data th { position: static; }
}

@media (max-width: 640px) {
  /* Stat strip: 2-up on a phone reads far better than 1-up scrolling forever. */
  .statline { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .stat.slim { padding: 11px 12px 10px; }
  .stat.slim .stat__value { font-size: 20px; }

  /* Fleet HUD: tighter, and the title never wraps away from the hamburger. */
  .fleet__title { font-size: 12.5px; }
  .chip { font-size: 11px; padding: 4px 9px; }

  /* Page title + description tighten up so the first panel is nearer the fold. */
  h1 { font-size: 21px; }
  .page-head { gap: 12px; margin-bottom: 14px; }
  .panel__body { padding: 14px; }

  /* Provisioning command blocks: the copy button goes under the command, full width. */
  .cmd__row { flex-direction: column; }
  .cmd__btn { width: 100%; }
  .cmd__code { font-size: 11.5px; }
  .provision__head { gap: 10px; }
  .provision__titles .sub { font-size: 12px; }
}

/* =========================================================================================
   WORKBENCH — the shared pieces of the Orders / Sales / Warm Pool / Cards / Accounts tabs
   (2026-10-01 redesign, after the Live Sales + Inventory look): a hairline KPI strip, a segmented
   view switch, pill filter selects, two-line table cells and a "show more" bar. Page-only rules
   stay in each template's <style>.
   ========================================================================================= */

/* ---- KPI strip: one panel, hairlines between cells (the 1px gap shows the line colour through),
   so it wraps 6 -> 3 -> 2 by the panel's own width without a doubled border ---- */
.kpis-panel { overflow: hidden; margin-bottom: var(--gap); container-type: inline-size; }
.kpis { display: grid; grid-template-columns: repeat(var(--kpi-n, 6), minmax(0, 1fr)); gap: 1px; background: var(--line-soft); }
.kpi { background: var(--surface); padding: 15px 16px 13px; min-width: 0; }
.kpi--hero { background: radial-gradient(130% 120% at 0% 0%, var(--accent-dim), transparent 62%), var(--surface); }
.kpi__label { font-family: var(--f-mono); font-size: 10px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--ink-faint); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kpi__value { font-family: var(--f-mono); font-weight: 600; font-size: 19px; letter-spacing: -.4px; line-height: 1.1; margin-top: 8px; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.kpi--hero .kpi__value { font-size: 21px; }
.kpi__value.is-good { color: var(--sonar); }
.kpi__value.is-bad { color: var(--coral); }
.kpi__value.is-warn { color: var(--amber); }
.kpi__value .cents { font-size: .7em; opacity: .6; }
.kpi__sub { font-family: var(--f-mono); font-size: 10.5px; color: var(--ink-faint); margin-top: 7px; line-height: 1.5; }
.kpi__sub b { color: var(--ink-dim); font-weight: 600; }
.kpi__sub .is-bad { color: var(--coral); }
.kpi__sub .is-warn { color: var(--amber); }
.kpi__sub .is-good { color: var(--sonar-deep); }
.kpi.is-click { cursor: pointer; }
.kpi.is-click:hover { background-color: var(--surface-2); }
@container (max-width: 1120px) { .kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .kpis.kpis--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@container (max-width: 560px) {
  .kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .kpi { padding: 13px 13px 11px; }
}

/* ---- segmented view switch ---- */
.seg { display: inline-flex; align-items: center; gap: 2px; padding: 3px; border: 1px solid var(--line); border-radius: 99px; background: var(--surface-2); max-width: 100%; overflow-x: auto; scrollbar-width: none; }
.seg::-webkit-scrollbar { display: none; }
.seg__btn { flex: none; display: inline-flex; align-items: center; gap: 6px; border: 0; background: transparent; cursor: pointer;
  padding: 6px 14px; border-radius: 99px; font-family: var(--f-display); font-weight: 600; font-size: 12.5px; color: var(--ink-dim); white-space: nowrap; }
.seg__btn:hover { color: var(--ink); }
.seg__btn.on { background: var(--surface); color: var(--ink); box-shadow: 0 1px 2px rgba(16, 24, 40, .08), 0 0 0 1px var(--line); }
.seg__btn .n { font-family: var(--f-mono); font-weight: 500; font-size: 10.5px; color: var(--ink-faint); }
.seg__btn:focus-visible, .fsel:focus-visible, .chip-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- filter row: chips + pill selects; one row that wraps ---- */
.filters { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.filters .chip-toggle { display: inline-flex; align-items: center; gap: 5px; }
.filters .chip-toggle .n { font-weight: 600; }
.filters .chip-toggle .n:empty { display: none; }
.filters .chip-toggle .n.is-bad { color: var(--coral); }
.filters__sep { width: 1px; align-self: stretch; min-height: 20px; background: var(--line); margin: 0 2px; }
select.fsel { width: auto; max-width: 230px; padding: 6px 28px 6px 12px; font-family: var(--f-mono); font-size: 11.5px; border-radius: 99px;
  background-color: var(--surface-2); color: var(--ink-dim); background-position: right 10px center; }
select.fsel.on { border-color: var(--accent); color: var(--accent-deep); background-color: var(--accent-dim); }
.btn.link-btn { padding: 4px 8px; border: 0; background: none; color: var(--accent-deep); font-size: 12px; }
.btn.link-btn:hover { text-decoration: underline; background: none; }

/* ---- table cells with a main line and a quiet second line ---- */
table.data td .cm { color: var(--ink); font-weight: 500; }
table.data td .cs { display: block; margin-top: 3px; font-size: 11.5px; color: var(--ink-faint); line-height: 1.35; }
table.data td .cs.mono, table.data td .cm.mono { font-family: var(--f-mono); }
table.data.rows-click tbody tr { cursor: pointer; }
table.data.rows-click tbody tr:hover { background: var(--surface-2); }
.more-bar { display: flex; justify-content: center; align-items: center; gap: 12px; padding: 12px; border-top: 1px solid var(--line-soft); }
.more-bar[hidden] { display: none; }
.more-bar .muted { font-size: 12px; }
@keyframes wbFlash { from { background: var(--accent-dim); } to { background: transparent; } }
tr.wb-flash > td { animation: wbFlash 2.4s ease-out; }
.copy-chip { cursor: pointer; border-bottom: 1px dotted var(--ink-ghost); }
.copy-chip:hover { color: var(--accent-deep); border-bottom-color: var(--accent); }

/* ---- Accounts tab (overview + profile pages) ---- */
.acc-meter { display: inline-block; vertical-align: middle; width: 64px; height: 5px; margin-right: 8px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.acc-meter__fill { display: block; height: 100%; border-radius: 3px; background: var(--sonar); }
td.acc-detail { max-width: 340px; overflow: hidden; text-overflow: ellipsis; }
td.acc-proxy { max-width: 240px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc-more { justify-content: space-between; padding: 10px 16px; }
.acc-search { flex: 0 1 300px; }
td.acc-acts .btn.sm { padding: 4px 9px; font-size: 11.5px; }
.panel > summary.panel__head::-webkit-details-marker { display: none; }

/* =========================================================================================
   GEN LINKS modal (wallet_links.js)
   ========================================================================================= */
/* The unit is the ticket: its section / row / seat as labelled fields on the left, its two
   links on the right. One bar per order acts on every ticket at once. */
.gl-modal { max-width: 720px; }
.gl-modal .modal__body { padding: 16px 20px 20px; display: flex; flex-direction: column; gap: 14px; }
.gl-sub { margin-top: 3px; font-size: 12.5px; color: var(--ink-faint); }
.gl-empty { padding: 28px 0; text-align: center; font-size: 13px; color: var(--ink-faint); }

.gl-order { flex: none; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); overflow: hidden; }   /* flex: none: a scrolling body must never squeeze (and clip) a card */
.gl-order__head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 14px; background: var(--surface-2); border-bottom: 1px solid var(--line-soft);
}
.gl-order__id { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
.gl-order__no { font-family: var(--f-mono); font-weight: 600; font-size: 13.5px; letter-spacing: .02em; color: var(--ink); }
.gl-order__acct { font-size: 12px; color: var(--ink-faint); overflow-wrap: anywhere; }
.gl-order__count { font-size: 12px; color: var(--ink-dim); white-space: nowrap; }

.gl-bulk { display: flex; gap: 8px; flex-wrap: wrap; padding: 10px 14px; border-bottom: 1px solid var(--line-soft); }
.gl-bulk .btn { gap: 7px; }
.gl-bulk .btn.is-busy { opacity: 1; color: var(--accent-deep); border-color: var(--accent-glow); background: var(--accent-dim); }
.gl-bulk__copy { margin-left: auto; }

.gl-alert {
  display: flex; gap: 9px; align-items: flex-start; margin: 12px 14px 0; padding: 9px 11px;
  border-radius: var(--radius-sm); background: var(--amber-dim); border: 1px solid var(--amber-glow);
  font-size: 12.5px; line-height: 1.45; color: var(--ink);
}
.gl-alert .ico { width: 15px; height: 15px; flex: none; margin-top: 1px; color: var(--amber); }
.gl-alert b { display: block; font-weight: 600; color: var(--ink); }
.gl-alert span { color: var(--ink-dim); overflow-wrap: anywhere; }

.gl-tickets { list-style: none; margin: 0; padding: 2px 14px; }
.gl-ticket {
  display: grid; grid-template-columns: minmax(150px, 186px) minmax(0, 1fr); gap: 16px; align-items: center;
  padding: 13px 0; border-bottom: 1px solid var(--line-soft);
}
.gl-ticket:last-child { border-bottom: 0; }
.gl-tmeta { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12.5px; }

/* the seat, printed the way a ticket prints it */
.gl-seat { display: grid; grid-template-columns: repeat(3, minmax(0, auto)); justify-content: start; gap: 0 16px; }
.gl-seat span {
  display: block; margin-bottom: 2px; font-size: 10px; font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-faint);
}
.gl-seat b {
  display: block; font-size: 17px; line-height: 1.15; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
.gl-seat--all { grid-template-columns: 1fr; }
.gl-seat--all b { font-size: 13px; font-weight: 600; }

.gl-links { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.gl-link {
  display: grid; grid-template-columns: 148px minmax(0, 1fr) auto; align-items: center; gap: 10px;
  min-height: 32px;
}
.gl-link__name {
  display: flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 600; color: var(--ink-dim);
  white-space: nowrap; cursor: help;
}
.gl-link__name::before {             /* made / being made / not yet */
  content: ""; width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: transparent; box-shadow: inset 0 0 0 1.5px var(--ink-ghost);
}
.gl-link.is-done .gl-link__name::before { background: var(--sonar); box-shadow: 0 0 0 3px var(--sonar-dim); }
.gl-link.is-running .gl-link__name::before { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }
.gl-link__url {
  font-family: var(--f-mono); font-size: 12px; color: var(--accent-deep); text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gl-link__url:hover { text-decoration: underline; }
.gl-link__url.is-text { font-family: inherit; font-size: 12.5px; font-weight: 500; }
.gl-link__acts .btn.is-copied, .gl-bulk .btn.is-copied { color: var(--sonar-deep); border-color: var(--sonar-glow); background: var(--sonar-dim); }
.gl-link__state { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 12.5px; color: var(--ink-faint); }
.gl-link__state span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gl-link__state.is-running { color: var(--accent-deep); }
.gl-link__acts { display: flex; align-items: center; justify-content: flex-end; gap: 6px; }
.gl-link__acts .btn { gap: 6px; }
.gl-link__acts .btn .ico { width: 13px; height: 13px; }
.gl-link__acts .icon-btn .ico { width: 15px; height: 15px; }

.gl-spin {
  width: 11px; height: 11px; flex-shrink: 0; border-radius: 50%;
  border: 2px solid var(--accent-dim); border-top-color: var(--accent-deep); animation: glspin .8s linear infinite;
}
@keyframes glspin { to { transform: rotate(360deg); } }

@media (max-width: 640px) {
  .gl-modal .modal__body { padding: 12px 12px 16px; }
  .gl-ticket { grid-template-columns: 1fr; gap: 10px; }
  .gl-link { grid-template-columns: minmax(0, 1fr) auto; row-gap: 4px; }
  .gl-link__name { grid-column: 1 / -1; }
  .gl-bulk .btn { flex: 1 1 auto; }
  .gl-bulk__copy { margin-left: 0; }
}
@media (prefers-reduced-motion: reduce) { .gl-spin { animation-duration: 2.4s; } }

/* sweep / account-ticket listing inside the Gen Links modal */
.gl-sweep { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1px solid var(--line-soft); font-size: 12.5px; }
.gl-sweep__hint { color: var(--ink-faint); }
.gl-sweep--running { color: var(--accent-deep); }
.gl-sweep--error { color: var(--red); flex-wrap: wrap; }
.gl-sweep--error .ico { color: var(--amber); flex: none; }
.gl-sweep--loaded { flex-direction: column; align-items: stretch; gap: 0; padding: 0; }
.gl-sweep__bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 10px 14px; border-bottom: 1px solid var(--line-soft); }
.gl-sweep__bar > span:first-child { flex: 1; font-weight: 600; font-size: 12.5px; color: var(--ink-dim); }
.gl-sweep__event { border-bottom: 1px solid var(--line-soft); }
.gl-sweep__event:last-child { border-bottom: 0; }
.gl-sweep__ehead { padding: 8px 14px 4px; font-size: 12.5px; }
.gl-sweep__ehead b { color: var(--ink); }
.gl-sweep__meta { color: var(--ink-faint); font-weight: 400; font-size: 11.5px; }
.gl-sweep__tkt { display: flex; align-items: center; gap: 8px; padding: 5px 14px 5px 28px; cursor: pointer; font-size: 12.5px; }
.gl-sweep__tkt:hover { background: var(--surface-hover, rgba(0,0,0,.03)); }
.gl-sweep__tkt input[type="checkbox"] { flex: none; accent-color: var(--accent); }
.gl-sweep__seat { font-family: var(--f-mono); font-weight: 600; font-size: 12px; color: var(--ink); min-width: 80px; }
.gl-sweep__ttype { color: var(--ink-dim); }
.gl-sweep__oid { color: var(--ink-faint); font-family: var(--f-mono); font-size: 11.5px; }
.gl-sweep__st { margin-left: auto; font-size: 11.5px; font-weight: 600; white-space: nowrap; }
.gl-sweep__st.is-ready { color: var(--sonar-deep, #16a34a); }
.gl-sweep__st.is-warn { color: var(--amber, #d97706); }
.gl-sweep--done { color: var(--sonar-deep, #16a34a); }
.gl-sweep--done .ico { color: var(--sonar-deep, #16a34a); flex: none; }
.gl-sweep__bind { display: flex; align-items: center; gap: 8px; padding: 8px 14px; font-size: 12.5px; border-bottom: 1px solid var(--line-soft); }

.ls-glbtn { margin-top: 4px; }       /* Live Sales' row button */
