:root {
  /* Premium-feel stack. Manrope for headings/hero (modern, slightly rounded),
     Inter as the UI workhorse (crisp numbers, pairs with Manrope), Playfair
     Display italic as the occasional serif accent. */
  --font-ui: "Inter", "Segoe UI", "Trebuchet MS", Arial, sans-serif;
  --font-display: "Manrope", "Inter", "Segoe UI Semibold", "Trebuchet MS", Arial, sans-serif;
  --font-fancy: "Playfair Display", "Georgia", "Times New Roman", serif;
  --poke-blue: #1d4ed8;
  --poke-red: #dc2626;
  --poke-gold: #fbbf24;
  --header-ink: #f8fafc;
}

body {
  margin: 0;
  background: linear-gradient(180deg, #0b1220 0%, #0f172a 45%, #111827 100%);
  color: #e2e8f0;
  font-family: var(--font-ui);
  position: relative;
  min-height: 100vh;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /*
   * Flex column on body so .app-footer can `margin-top: auto` to the
   * actual bottom of the page (not float in the middle of the
   * viewport on short pages like the payment screen or empty orders
   * list). Reported May 15: "can u put the crafture co on the bottom
   * of the page not the middle?" — short pages have lots of empty
   * space below content, so without flex+auto-margin the footer sat
   * directly under the content card, which on a 1080p screen reads
   * as "the middle." This pins it to the bottom edge.
   *
   * Children of body still flow normally in document order. Fixed
   * and absolute positioning continue to work — flex preserves the
   * containing-block contract for them.
   */
  display: flex;
  flex-direction: column;
}

#pokemonBackdrop {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  overflow: hidden;
}

#pokemonBackdrop::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(2, 6, 23, 0.35) 0%, rgba(2, 6, 23, 0.28) 48%, rgba(2, 6, 23, 0.4) 100%);
}

#pokemonBackdrop::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Neutral brand-family washes (was pokeball red/yellow tints). */
  background:
    radial-gradient(circle at 15% 12%, rgba(0, 212, 255, 0.1), transparent 42%),
    radial-gradient(circle at 83% 22%, rgba(0, 119, 255, 0.12), transparent 42%),
    radial-gradient(circle at 58% 78%, rgba(56, 189, 248, 0.08), transparent 40%);
}


body.modal-open {
  overflow: hidden;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 22px;
  padding-bottom: 92px;
  position: relative;
  z-index: 2;
}

.brand-header {
  display: flex;
  align-items: center;
  gap: 14px;
}

h1,
h2 {
  font-family: var(--font-display);
  letter-spacing: -0.015em;
  font-weight: 700;
}
h2 {
  font-size: 1.15rem;
  color: #f1f5f9;
}

.brand-logo {
  width: 64px;
  height: 64px;
  object-fit: contain;
  border-radius: 8px;
  border: 1px solid #374151;
  background: #0b1220;
  padding: 4px;
}

.brand-logo-fallback {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #e5e7eb;
  font-weight: 800;
  font-size: 24px;
}

/* ── Pokémon-style brand header ─────────────────────────────────────
   Classic Pokémon logo look: chunky yellow wordmark with a blue outline
   and a drop shadow. The -webkit-text-stroke draws the outer blue ring;
   the gradient on the text gives it that gold-to-yellow shine. */
.pokemon-brand {
  gap: 18px;
  padding: 6px 0 10px;
}

.pokemon-brand .brand-logo {
  width: 72px;
  height: 72px;
  filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.5));
}

.brand-title-wrap {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* Brand-neutral login wordmark (class names are legacy — the styling is
   not): the TEXT comes from brand.json via data-brand-name; the look must
   suit any shop's name, so no themed lettering or outlines. */
.poke-title {
  font-family: "Manrope", "Inter", sans-serif;
  margin: 0;
  line-height: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.poke-title-text {
  font-size: 2.2rem;
  font-weight: 800;
  letter-spacing: 0.5px;
  color: #f8fafc;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
}

.poke-title-sub {
  font-family: "Manrope", "Inter", sans-serif;
  font-weight: 700;
  font-size: 0.8rem;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: #38bdf8;
  margin-top: 2px;
}

.poke-tagline {
  font-style: italic;
  color: #cbd5e1;
  margin-top: 6px;
  font-size: 0.85rem;
}

@media (max-width: 680px) {
  .poke-title-text { font-size: 1.8rem; letter-spacing: 1px; }
  .poke-title-sub { font-size: 0.75rem; letter-spacing: 2px; }
  .pokemon-brand .brand-logo { width: 56px; height: 56px; }
}

.hint {
  color: #94a3b8;
  margin-top: 0;
}

/* Login-panel safety tip: stack the English and Spanish translations
   so shippers/streamers working in either language can read it without
   one version looking like an afterthought. */
.login-tip {
  display: block;
  margin-top: 8px;
  line-height: 1.5;
}
.login-tip-lang {
  display: block;
  padding: 4px 0;
}
.login-tip-es {
  color: #7dd3fc;
  border-top: 1px dashed rgba(148, 163, 184, 0.25);
  margin-top: 4px;
}
.login-tip-es strong { color: #bae6fd; }

/* ─── User bar (top-right: "admin  admin  ★ master") ───────────────── */
#currentUser {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
}
#currentUser strong {
  color: #e2e8f0;
  font-weight: 700;
}
.user-bar-alias {
  color: #64748b;
  font-size: 12px;
  font-weight: 400;
}
.user-bar-role {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 600;
  text-transform: lowercase;
  letter-spacing: 0.01em;
  background: rgba(148, 163, 184, 0.18);
  color: #cbd5e1;
  border: 1px solid rgba(148, 163, 184, 0.35);
}
.user-bar-role-admin      { background: rgba(220, 38, 38, 0.18); color: #fca5a5; border-color: rgba(220, 38, 38, 0.4); }
.user-bar-role-tech       { background: rgba(79, 70, 229, 0.22); color: #c7d2fe; border-color: rgba(79, 70, 229, 0.45); }
.user-bar-role-management { background: rgba(217, 119, 6, 0.2);  color: #fed7aa; border-color: rgba(217, 119, 6, 0.45); }
.user-bar-role-closer     { background: rgba(5, 150, 105, 0.2);  color: #6ee7b7; border-color: rgba(5, 150, 105, 0.45); }
.user-bar-role-streamer   { background: rgba(244, 114, 182, 0.2); color: #f9a8d4; border-color: rgba(244, 114, 182, 0.45); }
.user-bar-role-shipper    { background: rgba(59, 130, 246, 0.2); color: #93c5fd; border-color: rgba(59, 130, 246, 0.45); }
.user-bar-master {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 700;
  background: linear-gradient(90deg, rgba(251, 191, 36, 0.22), rgba(245, 158, 11, 0.18));
  color: #fde68a;
  border: 1px solid rgba(251, 191, 36, 0.55);
}

/* Row-level Active / Inactive / Jorge Pulled dropdown. Background color
   tells the operator at-a-glance what state a product is in without
   having to read the text. Colors are strong-opaque (not tinted) so
   the text has enough contrast both when the pill is closed AND when
   the dropdown is open — browsers otherwise render <option> on the
   OS's default background, which turned our light-on-light tints into
   near-invisible labels on Windows. */
select.row-active-select {
  padding: 3px 6px;
  border-radius: 4px;
  border: 1px solid #475569;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  color: #0f172a;
}
select.row-active-select option {
  /* Force option styling so the open dropdown isn't rendered with OS
     defaults. Dark text on a clean light background reads everywhere. */
  background: #f8fafc;
  color: #0f172a;
  font-weight: 600;
}
select.row-active-select.row-active-active {
  background: #16a34a;
  color: #f0fdf4;
  border-color: #166534;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}
select.row-active-select.row-active-inactive {
  background: #475569;
  color: #f1f5f9;
  border-color: #334155;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}
select.row-active-select.row-active-jp {
  background: #d97706;
  color: #fff7ed;
  border-color: #92400e;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
}

/* ── Active Inventory Value modal ───────────────────────────────── */
.inv-value-summary-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 10px;
  margin-top: 8px;
}
.inv-value-stat {
  background: #1f2937;
  border: 1px solid #334155;
  border-radius: 6px;
  padding: 10px 14px;
  text-align: center;
}
.inv-value-stat .inv-value-label {
  color: #94a3b8;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
  margin-bottom: 4px;
}
.inv-value-stat .inv-value-val {
  color: #e5e7eb;
  font-size: 22px;
  font-weight: 800;
  font-family: ui-monospace, Menlo, Consolas, monospace;
}
.inv-value-stat-stream {
  background: rgba(5, 150, 105, 0.12);
  border-color: rgba(5, 150, 105, 0.45);
}
.inv-value-stat-stream .inv-value-val {
  color: #6ee7b7;
}
.inv-value-stat-tcg {
  background: rgba(79, 70, 229, 0.15);
  border-color: rgba(79, 70, 229, 0.45);
}
.inv-value-stat-tcg .inv-value-val {
  color: #c7d2fe;
}
#invValueListContainer table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
#invValueListContainer th,
#invValueListContainer td {
  padding: 6px 8px;
  border-bottom: 1px solid #334155;
}
#invValueListContainer th {
  position: sticky;
  top: 0;
  background: #0f172a;
  text-align: left;
  font-size: 11px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: #94a3b8;
  z-index: 1;
}
#invValueListContainer tbody tr:hover {
  background: rgba(148, 163, 184, 0.07);
}
#invValueListContainer .iv-val-stream { color: #6ee7b7; font-weight: 600; text-align: right; font-family: ui-monospace, Menlo, Consolas, monospace; }
#invValueListContainer .iv-val-tcg    { color: #c7d2fe; font-weight: 600; text-align: right; font-family: ui-monospace, Menlo, Consolas, monospace; }
#invValueListContainer .iv-qty        { text-align: right; font-family: ui-monospace, Menlo, Consolas, monospace; }
#invValueListContainer .iv-thumb      { width: 36px; height: 36px; object-fit: contain; background: #1c1917; border: 1px solid #475569; border-radius: 3px; }

/* ── TikTok Orders CSV Import ─────────────────────────────────────── */
.import-orders-drop-zone {
  border: 2px dashed rgba(139, 92, 246, 0.45);
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.05), rgba(139, 92, 246, 0.05));
  border-radius: 14px;
  padding: 42px 20px;
  text-align: center;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.import-orders-drop-zone:hover,
.import-orders-drop-zone.drag-over {
  border-color: #8b5cf6;
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.12), rgba(139, 92, 246, 0.12));
}
.import-orders-dz-icon {
  font-size: 2.4rem;
  margin-bottom: 6px;
}
.import-orders-dz-title {
  font-family: "Manrope", "Inter", system-ui, sans-serif;
  font-weight: 700;
  color: #e2e8f0;
  font-size: 1rem;
}
.import-orders-dz-sub {
  color: #94a3b8;
  font-size: 0.85rem;
  margin-top: 2px;
}
.import-result-card {
  background: #0f172a;
  border: 1px solid rgba(99, 102, 241, 0.35);
  border-radius: 10px;
  padding: 14px 16px;
}
.import-result-card h4 {
  margin: 0 0 10px;
  color: #c7d2fe;
  font-family: "Manrope", "Inter", system-ui, sans-serif;
}
.import-result-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px 12px;
  margin-bottom: 8px;
}
.import-result-stat {
  background: #111827;
  border: 1px solid #334155;
  border-radius: 6px;
  padding: 8px 10px;
}
.import-result-stat .ir-label {
  color: #94a3b8;
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
  margin-bottom: 2px;
}
.import-result-stat .ir-val {
  color: #e2e8f0;
  font-size: 1.15rem;
  font-weight: 800;
  font-family: ui-monospace, Menlo, Consolas, monospace;
}
.import-result-stat.ir-inserted .ir-val { color: #6ee7b7; }
.import-result-stat.ir-updated  .ir-val { color: #c7d2fe; }
.import-result-stat.ir-noop     .ir-val { color: #94a3b8; }
.import-result-stat.ir-preapp   .ir-val { color: #fde68a; }

/* Clickable flag pill — used in the Inventory Value toolbar for the
   "N items missing a TCG price" warning. Click to isolate the flagged
   rows; click again (or the ✕ clear pip) to restore the full list. */
.flag-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid rgba(245, 158, 11, 0.55);
  background: rgba(245, 158, 11, 0.12);
  color: #fde68a;
  font-size: 12px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 9999px;
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.flag-pill:hover {
  background: rgba(245, 158, 11, 0.22);
  border-color: rgba(245, 158, 11, 0.75);
  color: #fef3c7;
}
.flag-pill-active {
  background: rgba(245, 158, 11, 0.35);
  border-color: #f59e0b;
  color: #1c1917;
}
.flag-pill-active:hover {
  background: rgba(245, 158, 11, 0.45);
  color: #0b1220;
}
.flag-pill-clear {
  background: rgba(0, 0, 0, 0.22);
  padding: 1px 6px;
  border-radius: 9999px;
  font-size: 10px;
  font-weight: 700;
}

/* Screen layout: make the Inventory Value modal a full-height flex
   column so the summary cards + filter row stay pinned at the top and
   ONLY the inner list scrolls. The default .modal-panel rule at the
   bottom of this file sets max-height + overflow:auto on the whole
   panel, which — combined with the old inner max-height:60vh — was
   creating a double-scroll that chopped off the last few rows. */
#inventoryValueModal .modal-panel {
  display: flex;
  flex-direction: column;
  /* Leave some breathing room above + below so the modal doesn't hug
     the viewport edges. 80px ≈ the 48px top padding the .modal sets
     + a bit at the bottom so the last row is visibly inside the panel. */
  max-height: calc(100vh - 80px);
  overflow: hidden;
  padding-bottom: 12px;
}
#inventoryValueModal .modal-panel > * {
  flex-shrink: 0;
}
#inventoryValueModal .modal-panel #invValueListContainer {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
  overflow: auto;
}

/* Same double-scroll fix for the Low-on-Floor modal — same pattern. */
#lowFloorModal .modal-panel {
  display: flex;
  flex-direction: column;
  max-height: calc(100vh - 80px);
  overflow: hidden;
  padding-bottom: 12px;
}
#lowFloorModal .modal-panel > * {
  flex-shrink: 0;
}
#lowFloorModal .modal-panel #lowFloorListContainer {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
  overflow: auto;
}

@media print {
  #inventoryValueModal .no-print,
  #inventoryValueModal button,
  #inventoryValueModal select,
  #inventoryValueModal input[type="search"] { display: none !important; }
  #inventoryValueModal { position: static; background: #fff !important; color: #000 !important; }
  #inventoryValueModal .modal-panel { max-width: 100% !important; box-shadow: none !important; border: none !important; max-height: none !important; display: block !important; overflow: visible !important; }
  #invValueListContainer { max-height: none !important; overflow: visible !important; }
}

/* ─── Password field with eye-toggle ──────────────────────────────────
   Wrap a <input type="password"> + a <button class="pw-toggle"> in
   a .pw-wrap so the eye icon sits INSIDE the input on the right.
   Default is inline-flex (for toolbars, table cells). When the wrapper
   lives inside a .form-row (column flex layout) it stretches to full
   width so the input fills the row the same way it did before. */
.pw-wrap {
  position: relative;
  display: inline-flex;
  align-items: stretch;
  vertical-align: middle;
  max-width: 100%;
}
.form-row > .pw-wrap,
.pw-wrap.pw-wrap-block {
  display: flex;
  width: 100%;
}
.pw-wrap > input {
  flex: 1 1 auto;
  min-width: 0;
  padding-right: 36px;
  box-sizing: border-box;
}
.pw-toggle {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  border: none;
  background: transparent;
  color: #94a3b8;
  cursor: pointer;
  font-size: 15px;
  padding: 2px 6px;
  line-height: 1;
  border-radius: 4px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
}
.pw-toggle:hover {
  color: #e5e7eb;
  background: rgba(148, 163, 184, 0.15);
}
.pw-toggle:focus-visible {
  outline: 2px solid rgba(59, 130, 246, 0.55);
  outline-offset: 1px;
}
.pw-toggle.pw-revealed {
  color: #fbbf24;
}

/* Post-set "tell the user their password" reveal card. Shows up
   directly under the user row in the admin table after create or
   reset, stays visible until dismissed or 90s elapses. */
.pw-reveal-card {
  margin: 6px 0;
  padding: 10px 12px;
  background: #422006;
  border: 1px solid #f59e0b;
  border-radius: 6px;
  color: #fde68a;
  font-size: 13px;
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}
.pw-reveal-card .pw-reveal-label {
  color: #fbbf24;
  font-weight: 700;
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.04em;
}
.pw-reveal-card .pw-reveal-user {
  font-family: ui-monospace, Menlo, Consolas, monospace;
  color: #fde68a;
}
.pw-reveal-card .pw-reveal-value {
  font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  background: #1c1917;
  padding: 4px 10px;
  border: 1px dashed #f59e0b;
  border-radius: 4px;
  user-select: all;
}
.pw-reveal-card button {
  font-size: 11px;
  padding: 3px 10px;
}
.pw-reveal-card .pw-reveal-hide-hint {
  font-size: 11px;
  color: #fbbf24;
  margin-left: auto;
}

.toolbar {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
  align-items: center;
  flex-wrap: wrap;
  padding: 10px;
  border: 1px solid #334155;
  border-radius: 10px;
  background: #111c2f;
}

.user-avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid #475569;
  background: #0b1220;
}

.inline-user {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  vertical-align: middle;
}

.inline-user-avatar {
  width: var(--avatar-size, 20px);
  height: var(--avatar-size, 20px);
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid #475569;
  background: #0b1220;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.inline-user-fallback {
  color: #e2e8f0;
  font-weight: 700;
  font-size: calc(var(--avatar-size, 20px) * 0.45);
}

.inline-user-label {
  font-weight: 600;
}

body.streamer-simple [data-streamer-simple-hide="true"] {
  display: none !important;
}
body.streamer-simple [data-streamer-simple-show="true"] {
  display: flex !important;
}

body.streamer-simple .simple-primary-buttons button {
  font-size: 16px;
  padding: 10px 14px;
}

body.streamer-simple #sessionOwnerLabel {
  display: none;
}

input,
button {
  font-size: 14px;
  padding: 8px 10px;
  border-radius: 6px;
  border: 1px solid #475569;
}

input,
select {
  background: #1f2937;
  color: #f8fafc;
}

input:focus,
select:focus {
  outline: 2px solid #60a5fa;
  outline-offset: 1px;
  border-color: #60a5fa;
}

button {
  background: #2563eb;
  color: #fff;
  cursor: pointer;
  border-color: #3b82f6;
  font-weight: 600;
}

button.secondary {
  background: #334155;
  border-color: #475569;
}

button.danger {
  background: #7f1d1d;
  border-color: #ef4444;
  color: #fee2e2;
}

button:hover {
  filter: brightness(1.08);
}

table {
  width: 100%;
  border-collapse: collapse;
  background: #182235;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 6px 20px rgba(2, 6, 23, 0.35);
}

th,
td {
  border: 1px solid #334155;
  padding: 8px;
  text-align: left;
}

th {
  background: linear-gradient(180deg, #1e293b 0%, #0f172a 100%);
  color: var(--header-ink);
  font-family: var(--font-display);
  letter-spacing: 0.2px;
}

th.sortable {
  cursor: pointer;
  user-select: none;
}

#productsTable thead th {
  color: var(--header-ink);
  font-weight: 800;
  text-shadow: none;
  border-top: 1px solid rgba(251, 191, 36, 0.45);
  border-bottom: 2px solid rgba(251, 191, 36, 0.5);
  background:
    linear-gradient(180deg, rgba(30, 64, 175, 0.55) 0%, rgba(15, 23, 42, 0.95) 100%),
    linear-gradient(90deg, rgba(220, 38, 38, 0.3) 0%, rgba(29, 78, 216, 0.32) 100%);
}

#productsTable {
  overflow: visible;
}

#productsTable thead th.sortable:hover {
  background:
    linear-gradient(180deg, rgba(37, 99, 235, 0.65) 0%, rgba(15, 23, 42, 0.96) 100%),
    linear-gradient(90deg, rgba(239, 68, 68, 0.35) 0%, rgba(59, 130, 246, 0.4) 100%);
  color: #ffffff;
}

#productsTable thead th.sortable:active {
  transform: translateY(1px);
}

tbody tr:nth-child(odd) {
  background: #1b273a;
}

tbody tr:nth-child(even) {
  background: #172234;
}

#productsTable tbody tr.category-separator td {
  border-top: 3px solid #ef4444 !important;
}

.editor {
  margin-top: 20px;
  background: linear-gradient(180deg, #1b273a 0%, #172235 100%);
  border: 1px solid #334155;
  border-radius: 12px;
  padding: 16px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
}

.editor h2 {
  margin-top: 0;
  margin-bottom: 12px;
  color: #f8fafc;
  border-bottom: 1px solid #334155;
  padding-bottom: 8px;
}

.hidden {
  display: none !important;
}

/* Pre-auth gate — hide everything except login/brand-header until authed.
   Applied to body; cleared once currentUser is populated.

   Belt-and-suspenders: the targeted .auth-gated class handles the originally-
   identified panels (catalog, stream builder, etc.), AND a catch-all rule
   hides every direct-child <section> of the app container except #loginPanel.
   This means any new admin/management panel added later is AUTOMATICALLY
   hidden when logged out — no need to remember a class. Critical for the
   shared-computer case: after logout the shipper sees ONLY the login form,
   nothing underneath, no matter what panel was open before. */
body.pre-auth .auth-gated {
  display: none !important;
}
body.pre-auth main.container > section:not(#loginPanel) {
  display: none !important;
}

/* Generic panel collapse — applied by makePanelCollapsible().
   Toggles a class on the <section>; the toggle-button stays visible,
   everything else inside the section hides. No DOM restructuring. */
section.panel-collapsed > *:not(.panel-toggle-btn) {
  display: none !important;
}
.panel-toggle-btn {
  margin-bottom: 8px;
}
/* Tools-menu "hide this section entirely" — separate from collapse so the
   two states can coexist (a section can be visible+collapsed, or hidden). */
section.panel-hidden-by-tools {
  display: none !important;
}

/* Tools menu dropdown (⚙ Sections) */
.tools-menu {
  position: relative;
  display: inline-block;
}
.tools-menu summary {
  display: inline-block;
  cursor: pointer;
  list-style: none;
  padding: 4px 10px;
  border-radius: 4px;
}
.tools-menu summary::-webkit-details-marker { display: none; }
.tools-menu[open] summary { background: rgba(148, 163, 184, 0.12); }
.tools-menu-dropdown {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 4px;
  min-width: 260px;
  max-height: 400px;
  overflow-y: auto;
  background: #0f172a;
  border: 1px solid #334155;
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
  padding: 8px;
  z-index: 100;
}
.tools-menu-header {
  font-size: 0.7rem;
  color: #94a3b8;
  padding: 4px 8px 8px;
  border-bottom: 1px solid #334155;
  margin-bottom: 4px;
}
.tools-menu-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  cursor: pointer;
  border-radius: 4px;
  font-size: 0.85rem;
}
.tools-menu-item:hover { background: rgba(148, 163, 184, 0.08); }
.tools-menu-item input { margin: 0; }

/* Feedback inbox — list items rendered by loadFeedback(). */
.feedback-item {
  border: 1px solid #334155;
  border-left-width: 4px;
  border-radius: 4px;
  padding: 10px 12px;
  margin-bottom: 8px;
  background: #0f172a;
}
.feedback-item.cat-suggestion { border-left-color: #3b82f6; }
.feedback-item.cat-bug        { border-left-color: #dc2626; }
.feedback-item.cat-issue      { border-left-color: #f59e0b; }
.feedback-item.cat-fix        { border-left-color: #14b8a6; }
.feedback-item.status-resolved { opacity: 0.6; }
.feedback-item-head {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 6px;
  font-size: 0.8rem;
  color: #94a3b8;
}
.feedback-item-cat {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: 0.7rem;
  padding: 2px 6px;
  border-radius: 3px;
  background: rgba(148, 163, 184, 0.15);
}
.feedback-item-msg {
  color: #f1f5f9;
  white-space: pre-wrap;
  margin: 6px 0;
}
.feedback-item-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 8px;
}

/* Audit log table */
.audit-log-table { width: 100%; border-collapse: collapse; font-size: 0.82rem; }
.audit-log-table th, .audit-log-table td { padding: 6px 8px; border-bottom: 1px solid #1f2937; vertical-align: top; text-align: left; }
.audit-log-table th { font-size: 0.7rem; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.05em; background: rgba(30, 41, 59, 0.4); }
.audit-row.audit-flagged { background: rgba(220, 38, 38, 0.08); }
.audit-row.audit-flagged td { border-bottom-color: rgba(220, 38, 38, 0.3); }
.audit-flag { color: #fca5a5; font-weight: 600; font-size: 0.75rem; margin-bottom: 4px; }
.audit-when { white-space: nowrap; color: #94a3b8; font-size: 0.75rem; }
.audit-action { font-family: ui-monospace, monospace; font-size: 0.75rem; padding: 1px 6px; border-radius: 3px; background: rgba(148, 163, 184, 0.15); }
.audit-action.a-login-success { background: rgba(16, 185, 129, 0.18); color: #6ee7b7; }
.audit-action.a-login-failed, .audit-action.a-login-rate_limited { background: rgba(220, 38, 38, 0.18); color: #fca5a5; }
.audit-action.a-access-denied_401, .audit-action.a-access-denied_403 { background: rgba(245, 158, 11, 0.18); color: #fde68a; }
.audit-action.a-user-role_changed { background: rgba(167, 139, 250, 0.2); color: #ddd6fe; }
.audit-action.a-product-deleted, .audit-action.a-user-deleted { background: rgba(220, 38, 38, 0.18); color: #fca5a5; }
.audit-details-json { font-family: ui-monospace, monospace; font-size: 0.72rem; color: #cbd5e1; word-break: break-word; max-width: 420px; }
.audit-ua { font-size: 0.65rem; margin-top: 2px; max-width: 420px; }
.audit-log-table code { font-size: 0.75rem; }

/* Per-user audit summary — shown above the table when a user is
   selected in the dropdown. Quick-glance security card: last login,
   last failure, last action, recent failure counts, top action types. */
.audit-user-summary {
  margin: 10px 0 14px;
  padding: 12px 14px;
  border: 1px solid #1f2937;
  border-radius: 8px;
  background: rgba(15, 23, 42, 0.6);
  font-size: 0.85rem;
}
.audit-user-summary.loading,
.audit-user-summary.err {
  font-style: italic;
  color: #94a3b8;
}
.audit-user-summary-head {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid #1f2937;
}
.audit-user-summary-head strong {
  font-size: 1rem;
  font-family: ui-monospace, monospace;
}
.audit-user-summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px 16px;
  margin-bottom: 10px;
}
.audit-user-summary-grid > div {
  font-size: 0.78rem;
  line-height: 1.5;
}
.audit-user-summary-grid .audit-warn {
  background: rgba(220, 38, 38, 0.08);
  border-radius: 4px;
  padding: 4px 6px;
}
.audit-user-summary-grid .hint {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.audit-user-summary-actions {
  font-size: 0.75rem;
  padding-top: 6px;
  border-top: 1px solid #1f2937;
}

/* Idle-timeout warning banner — appears 1 min before auto-logout so an
   admin who stepped away for coffee can click "I'm still here" to cancel. */
.idle-warn-banner {
  position: fixed;
  top: 12px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9999;
  background: #78350f;
  border: 1px solid #f59e0b;
  color: #fef3c7;
  padding: 10px 16px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 0.9rem;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
  animation: idleWarnPulse 1.5s ease-in-out infinite;
}
@keyframes idleWarnPulse {
  0%, 100% { box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5), 0 0 0 0 rgba(245, 158, 11, 0.5); }
  50%      { box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5), 0 0 0 8px rgba(245, 158, 11, 0); }
}

/* Go-Live nudge: shown to a streamer who is prepping but hasn't clicked
   Start Stream yet. Steady banner (prep runs long — flashing would be
   maddening); only the Start Stream button softly pulses. Mirrors the
   .idle-warn-banner layout, in red to read as "you should be LIVE". */
/* Unmissable full-width "you're not live" bar. Pinned across the top, large
   print, pulsing — it covers the header on purpose and only clears once the
   streamer clicks Start Stream (records stream_live_at). */
.go-live-nudge {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  transform: none;
  z-index: 100000;
  background: #b91c1c;
  border: none;
  border-bottom: 4px solid #fca5a5;
  color: #fff;
  padding: 16px 20px;
  border-radius: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  flex-wrap: wrap;
  max-width: 100vw;
  box-shadow: 0 6px 28px rgba(0, 0, 0, 0.6);
  font-size: 1.35rem;
  font-weight: 800;
  text-align: center;
  animation: goLiveBarPulse 1.15s ease-in-out infinite;
}
.go-live-nudge button {
  font-size: 1.2rem;
  font-weight: 800;
  padding: 12px 26px;
  background: #fff;
  color: #b91c1c;
  border: 0;
  border-radius: 10px;
  cursor: pointer;
  white-space: nowrap;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);
}
.go-live-nudge button:hover { background: #fee2e2; }
@keyframes goLiveBarPulse {
  0%, 100% { background: #b91c1c; }
  50%      { background: #ef4444; }
}
.sb-btn-start.go-live-glow {
  animation: goLivePulse 1.4s ease-in-out infinite;
}
@keyframes goLivePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.6); }
  50%      { box-shadow: 0 0 0 8px rgba(239, 68, 68, 0); }
}

/* Stale/reused-session warning banner — shown when a loaded session carries
   prior-stream data (old start, leftover GMV, already ended). Offset below the
   go-live nudge so the two never overlap. */
.stale-session-banner {
  position: fixed;
  top: 64px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9998;
  background: #7f1d1d;
  border: 2px solid #ef4444;
  color: #fee2e2;
  padding: 10px 16px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 92vw;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
  font-size: 0.9rem;
}

.form-row {
  display: flex;
  flex-direction: column;
  margin-bottom: 12px;
  gap: 4px;
}

.form-row label {
  font-weight: 700;
  color: #cbd5e1;
}

.editing-product {
  margin-bottom: 12px;
  color: #93c5fd;
}

.editor-actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.edit-links-info {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.edit-link-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 8px;
  background: rgba(30, 41, 59, 0.55);
  border: 1px solid rgba(59, 130, 246, 0.18);
  border-radius: 6px;
}
.edit-link-row-main {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.edit-link-row code {
  font-size: 0.9em;
}
.edit-link-attribution {
  font-size: 0.72rem;
  color: #94a3b8;
  font-style: italic;
}
.edit-link-attribution:empty {
  display: none;
}

/* ── Panel shared base ───────────────────────────────────────────────────── */
#userAdminPanel,
#assignmentGeneratorPanel,
#assignmentQueuePanel,
#streamBuilderPanel,
#productChangeLogPanel {
  border-color: rgba(59, 130, 246, 0.35);
  background: linear-gradient(160deg, #0f1e35 0%, #0b1525 55%, #0a1120 100%);
  box-shadow: 0 8px 28px rgba(2, 6, 23, 0.45), inset 0 0 0 1px rgba(59, 130, 246, 0.12);
}

/* ── Panel h2 shared ─────────────────────────────────────────────────────── */
#userAdminPanel h2,
#assignmentGeneratorPanel h2,
#assignmentQueuePanel h2,
#streamBuilderPanel h2,
#productChangeLogPanel h2 {
  font-family: var(--font-display);
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: 0.35px;
  color: #f8fafc;
  border-bottom: 2px solid rgba(251, 191, 36, 0.45);
  padding-bottom: 10px;
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Golden accent line before each h2 */
#userAdminPanel h2::before,
#assignmentGeneratorPanel h2::before,
#assignmentQueuePanel h2::before,
#streamBuilderPanel h2::before,
#productChangeLogPanel h2::before {
  content: "";
  display: inline-block;
  width: 4px;
  height: 1.1em;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--poke-gold) 0%, var(--poke-red) 100%);
  flex-shrink: 0;
}

/* ── Assigned Game Queue — dark red accent ───────────────────────────────── */
#assignmentQueuePanel {
  border-color: rgba(185, 28, 28, 0.5);
  background: linear-gradient(160deg, #1a0c10 0%, #130810 55%, #0c060d 100%);
  box-shadow: inset 0 0 0 1px rgba(239, 68, 68, 0.18), 0 8px 28px rgba(0, 0, 0, 0.4);
}

#assignmentQueuePanel h2 {
  color: #fecaca;
  border-bottom-color: rgba(239, 68, 68, 0.5);
}

#assignmentQueuePanel h2::before {
  background: linear-gradient(180deg, #ef4444 0%, #7f1d1d 100%);
}

#assignmentQueuePanel #assignmentQueueList {
  border: 1px solid rgba(185, 28, 28, 0.45);
  border-radius: 8px;
  padding: 8px 10px;
  background: rgba(17, 7, 10, 0.6);
}

#assignmentQueuePanel .session-list-item {
  border-bottom-color: rgba(185, 28, 28, 0.4);
}

/* ── Hint text ───────────────────────────────────────────────────────────── */
#userAdminPanel .hint,
#assignmentGeneratorPanel .hint,
#assignmentQueuePanel .hint,
#streamBuilderPanel .hint,
#productChangeLogPanel .hint {
  color: #cbd5e1;
  font-weight: 500;
}

/* ── Form labels ─────────────────────────────────────────────────────────── */
#userAdminPanel .form-row label,
#assignmentGeneratorPanel .form-row label,
#assignmentQueuePanel .form-row label,
#streamBuilderPanel .form-row label,
#productChangeLogPanel .form-row label {
  color: #bfdbfe;
  font-weight: 700;
}

/* ── Inputs / selects ────────────────────────────────────────────────────── */
#userAdminPanel input,
#userAdminPanel select,
#assignmentGeneratorPanel input,
#assignmentGeneratorPanel select,
#assignmentQueuePanel input,
#assignmentQueuePanel select,
#streamBuilderPanel input,
#streamBuilderPanel select,
#productChangeLogPanel input,
#productChangeLogPanel select {
  background: #0f172a;
  border-color: #334155;
  color: #f8fafc;
  font-weight: 600;
}

/* ── Assignment Generator action buttons ─────────────────────────────────── */
#assignmentGeneratorPanel .editor-actions button,
#assignmentGeneratorPanel .toolbar button {
  font-weight: 700;
}

#assignmentGeneratorPanel #agCreateButton {
  background: linear-gradient(135deg, #dc2626 0%, #991b1b 100%);
  border-color: #ef4444;
}

#assignmentGeneratorPanel #agPreviewButton,
#assignmentGeneratorPanel #agPublishButton {
  background: #1e3a5f;
  border-color: #2563eb;
}

#changeLogExplorer {
  margin-top: 10px;
}

#changeLogDateTabs,
#changeLogCategoryTabs {
  gap: 6px;
  flex-wrap: wrap;
}

#changeLogDateTabs button.active-filter,
#changeLogCategoryTabs button.active-filter {
  background: #b91c1c;
  border-color: #ef4444;
}

.change-log-entries {
  margin-top: 10px;
  display: grid;
  gap: 8px;
}

.change-log-card {
  border: 1px solid #374151;
  border-radius: 8px;
  padding: 10px;
  background: #0f172a;
}

.change-log-card-top {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  align-items: center;
}

.change-log-chip {
  display: inline-block;
  border: 1px solid #475569;
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 0.75rem;
  color: #fecaca;
  background: #3f0d12;
}

.change-log-time {
  color: #cbd5e1;
  font-size: 0.8rem;
}

.change-log-main {
  margin-top: 6px;
  color: #f8fafc;
  font-weight: 700;
}

.change-log-meta {
  margin-top: 4px;
  color: #bfdbfe;
  font-size: 0.9rem;
}

.change-log-reason {
  margin-top: 4px;
  color: #e2e8f0;
}

.dims-status-badge {
  display: inline-block;
  margin-top: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 800;
  border: 1px solid transparent;
}

.dims-status-verified {
  color: #dcfce7;
  background: #166534;
  border-color: #22c55e;
}

.dims-status-unverified {
  color: #fee2e2;
  background: #7f1d1d;
  border-color: #ef4444;
}

.dims-status-pending {
  color: #fef3c7;
  background: #854d0e;
  border-color: #f59e0b;
}

#addItemImagePullStatus {
  margin-top: 6px;
  padding: 6px 8px;
  border-radius: 6px;
  border: 1px solid #334155;
  font-weight: 700;
}

#addItemImagePullStatus.asset-status-ok {
  color: #dcfce7;
  background: #14532d;
  border-color: #22c55e;
}

#addItemImagePullStatus.asset-status-warn {
  color: #fee2e2;
  background: #7f1d1d;
  border-color: #ef4444;
}

/*
 * Amber info banner for "image hasn't been uploaded to disk yet but
 * everything else is fine" (May 15 2026). Previously the create
 * dialog showed a scary red error when the catalog tried to preview
 * the image right after create, before the operator had a chance to
 * drop the JPG into assets/products/. The product record itself is
 * 100% fine — only the file is missing. Owner: "when no image needs
 * to create a placeholder not error out".
 */
#addItemImagePullStatus.asset-status-info {
  color: #fef3c7;
  background: #78350f;
  border-color: #f59e0b;
}

.asset-preview-thumb {
  margin-top: 6px;
  width: 72px;
  height: 72px;
  object-fit: cover;
  border: 1px solid #334155;
  border-radius: 6px;
  background: #0f172a;
}

.status {
  margin-top: 14px;
  min-height: 20px;
  color: #d1d5db;
}

.image-thumb {
  width: 84px;
  height: 84px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid #4b5563;
  background: #0b1220;
  cursor: zoom-in;
  position: relative;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  z-index: 1;
}

.image-thumb:hover {
  transform: scale(3);
  /* Anchor zoom to the LEFT edge of the thumbnail. The image lives in
     the leftmost column of catalog / slab tables, so the rest of the
     row is to the RIGHT -- zoom expands into that empty space.
     Previous "right center" anchored the zoom from the right edge
     which pushed the enlarged image off-screen to the LEFT for any
     thumbnail in the first column (May 20 2026 operator screenshot
     showed the Arcanine thumbnail zooming partially off the left edge). */
  transform-origin: left center;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.55);
  z-index: 25;
}

/* Slab thumbnails render larger than sealed (84x84) so the user can visually
   verify the graded card matches the slab at a glance without opening the
   lightbox. Hover-zoom still kicks in for a full-size preview. */
.image-thumb-slab {
  width: 140px;
  height: 140px;
}

/* eBay side panel inside the price-history chart modal. Cross-checks the
   TCG market price against currently-listed eBay asks. Free Browse API —
   no approval needed — so the panel renders whenever EBAY_APP_ID +
   EBAY_CERT_ID are set on the server. */
.ebay-panel .ebay-panel-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 8px;
}

.ebay-panel-stats {
  display: flex;
  gap: 20px;
  padding: 8px 12px;
  background: #0f172a;
  border-radius: 6px;
  margin-bottom: 10px;
  font-size: 0.95rem;
}

.ebay-panel-stats .ebay-stat-label {
  color: #94a3b8;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-right: 4px;
}

.ebay-listing-row {
  display: flex;
  gap: 10px;
  align-items: center;
  padding: 6px 8px;
  border: 1px solid #334155;
  border-radius: 6px;
  margin-top: 6px;
  text-decoration: none;
  color: #e2e8f0;
}

.ebay-listing-row:hover {
  background: #1e293b;
  border-color: #475569;
}

.ebay-listing-thumb {
  width: 48px;
  height: 48px;
  object-fit: cover;
  border-radius: 4px;
  background: #1e293b;
  flex-shrink: 0;
}

.ebay-listing-thumb--empty {
  display: inline-block;
}

.ebay-listing-body {
  flex: 1;
  min-width: 0;
}

.ebay-listing-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.88rem;
}

.ebay-listing-meta {
  color: #94a3b8;
  font-size: 0.82rem;
  margin-top: 2px;
}

.ebay-listing-cond {
  margin-left: 8px;
  padding: 1px 6px;
  background: #334155;
  border-radius: 3px;
  font-size: 0.72rem;
}

/* Catalog type tabs: Sealed Products vs Slabs. Slabs live in the same
   products table server-side, but the UI keeps them in isolated views so
   900+ sealed rows never mix with the slab list. */
/* Sealed / Slabs sub-tabs. Styled as premium pills, matching the
   visual weight of the Orders launcher so the catalog view switch
   reads as a first-class control rather than generic browser chrome. */
.catalog-type-tabs {
  display: flex;
  gap: 8px;
  margin: 10px 0 14px;
  padding: 4px;
  background: rgba(15, 23, 42, 0.6);
  border: 1px solid #1e293b;
  border-radius: 999px;
  width: fit-content;
}

.catalog-type-tab {
  background: transparent;
  color: #94a3b8;
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 8px 22px;
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.02em;
  transition: color 0.15s ease, background 0.15s ease, transform 0.05s ease,
    box-shadow 0.15s ease, filter 0.15s ease;
}

.catalog-type-tab:hover:not(.catalog-type-tab-active) {
  color: #f1f5f9;
  background: rgba(100, 116, 139, 0.18);
}

.catalog-type-tab:active:not(.catalog-type-tab-active) {
  transform: translateY(1px);
}

.catalog-type-tab-active {
  font-family: var(--font-fancy);
  font-style: italic;
  font-weight: 700;
  font-size: 1rem;
  letter-spacing: 0.03em;
  color: #1a1207;
  background: linear-gradient(135deg, #f5c451 0%, #d4a017 50%, #b5850b 100%);
  border-color: #a67c04;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.35);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
}

.catalog-type-tab-active:hover {
  filter: brightness(1.08);
}

.catalog-type-tab-active:focus-visible {
  outline: 2px solid #f5c451;
  outline-offset: 2px;
}

#currentUser {
  color: #bfdbfe;
  font-weight: 700;
}

.specs-text {
  color: #cbd5e1;
  font-size: 12px;
}

/* ── Stream Session Builder redesign ──────────────────────── */
.sb-control-card {
  background: #0f172a;
  border: 1px solid #1e293b;
  border-radius: 12px;
  padding: 16px 18px;
  margin-bottom: 12px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.sb-session-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.sb-meta-chip {
  font-size: 0.75rem;
  font-weight: 600;
  color: #64748b;
  background: #1e293b;
  padding: 3px 10px;
  border-radius: 20px;
  letter-spacing: 0.02em;
}

.sb-primary-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px;
}

.sb-input-group {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.sb-input-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: #64748b;
}

.sb-input {
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 8px;
  color: #f1f5f9;
  padding: 7px 10px;
  font-size: 0.875rem;
  min-width: 130px;
  transition: border-color 0.15s;
}

.sb-input:focus {
  border-color: #6366f1;
  outline: none;
}

.sb-path-input {
  min-width: 280px;
  font-size: 0.8rem;
}

.sb-stream-actions {
  display: flex;
  gap: 8px;
  align-self: flex-end;
}

.sb-btn-start {
  padding: 8px 20px;
  border-radius: 8px;
  font-size: 0.875rem;
  font-weight: 700;
  background: linear-gradient(135deg, #16a34a, #15803d);
  color: #fff;
  border: none;
  cursor: pointer;
  transition: opacity 0.15s;
}

.sb-btn-start:hover { opacity: 0.85; }

.sb-btn-end {
  padding: 8px 20px;
  border-radius: 8px;
  font-size: 0.875rem;
  font-weight: 700;
  background: linear-gradient(135deg, #dc2626, #991b1b);
  color: #fff;
  border: none;
  cursor: pointer;
  transition: opacity 0.15s;
}

.sb-btn-end:hover { opacity: 0.85; }

.sb-admin-row,
.sb-streamer-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  padding: 12px 14px;
  background: #0a1120;
  border: 1px solid #1e293b;
  border-radius: 10px;
}

.sb-select {
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 8px;
  color: #f1f5f9;
  padding: 7px 10px;
  font-size: 0.82rem;
}

.sb-btn-admin {
  display: inline-flex;
  align-items: center;
  gap: 6px;                         /* breathing room between icon + label */
  padding: 6px 14px;
  border-radius: 7px;
  font-size: 0.8rem;
  font-weight: 600;
  background: #1e293b;
  color: #cbd5e1;
  border: 1px solid #334155;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, transform 0.12s;
}
.sb-btn-admin:active { transform: translateY(1px); }

/* Cartoony Pokemon-TCG icon style — used on every button in the
   Stream Session Builder toolbar. SVG <symbol>s are defined once at
   the top of the body; each button references one via <use href>.
   Drop-shadow gives them that "sticker on cardboard" pop. */
.sb-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.45));
  transition: transform 0.12s ease;
}
.sb-btn-admin:hover .sb-icon,
.sb-btn-danger:hover .sb-icon { transform: scale(1.08) rotate(-3deg); }
.sb-btn-danger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.sb-btn-admin:hover {
  background: #334155;
  color: #f1f5f9;
}

/* Save button — green-accent variant with inline SVG. Modernized from
   the floppy-disk emoji ("Save" → "Save now" since auto-save covers
   the steady-state case; this button is for impatient saves). */
.sb-btn-save {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: linear-gradient(180deg, #16a34a, #15803d);
  color: #ecfdf5;
  border-color: rgba(34, 197, 94, 0.55);
  font-weight: 700;
}
.sb-btn-save:hover {
  background: linear-gradient(180deg, #22c55e, #16a34a);
  color: #fff;
}
.sb-btn-save svg {
  flex: 0 0 auto;
  opacity: 0.92;
}

/* Auto-save hint — small dim text next to the Save button so the
   streamer knows the manual button is optional. Stays compact. */
.sb-autosave-hint {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.72rem;
  color: #64748b;
  letter-spacing: 0.04em;
  font-style: italic;
}
.sb-autosave-hint::before {
  content: "";
  width: 6px; height: 6px; border-radius: 50%;
  background: #22c55e;
  box-shadow: 0 0 6px rgba(34, 197, 94, 0.55);
  animation: sbAutosavePulse 2.4s ease-in-out infinite;
}
@keyframes sbAutosavePulse {
  0%, 100% { opacity: 0.55; transform: scale(1); }
  50%      { opacity: 1.0;  transform: scale(1.25); }
}
@media (prefers-reduced-motion: reduce) {
  .sb-autosave-hint::before { animation: none; opacity: 0.85; }
}

/* TikTok per-room template selector — sits next to the Export button so
   the streamer can switch between TCG (no warehouse column) and Evo
   (with warehouse column G) without leaving the session panel. */
.sb-template-select {
  padding: 6px 10px;
  border-radius: 7px;
  font-size: 0.78rem;
  font-weight: 600;
  background: #0f172a;
  color: #cbd5e1;
  border: 1px solid #334155;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.sb-template-select:hover { background: #1e293b; color: #f1f5f9; }
.sb-template-select:focus { outline: 2px solid #3b82f6; outline-offset: 1px; }

.sb-btn-danger {
  padding: 6px 14px;
  border-radius: 7px;
  font-size: 0.8rem;
  font-weight: 600;
  background: #450a0a;
  color: #fca5a5;
  border: 1px solid #7f1d1d;
  cursor: pointer;
  transition: background 0.15s;
}

.sb-btn-danger:hover { background: #7f1d1d; }

.sb-time-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: #0f172a;
  border: 1px solid #1e293b;
  border-radius: 8px;
  margin-bottom: 14px;
  font-size: 0.8rem;
}

.sb-time-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #334155;
  flex-shrink: 0;
}

.sb-time-label {
  color: #64748b;
  font-weight: 600;
}

.sb-time-sep {
  color: #1e293b;
  font-weight: 700;
}

/* Tabs */
.sb-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 0;
  border-bottom: 2px solid #1e293b;
  padding-bottom: 0;
}

.sb-tab {
  padding: 8px 20px;
  border-radius: 8px 8px 0 0;
  font-size: 0.82rem;
  font-weight: 600;
  background: transparent;
  color: #64748b;
  border: 1px solid transparent;
  border-bottom: none;
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
  position: relative;
  bottom: -2px;
}

.sb-tab:hover {
  color: #cbd5e1;
  background: #1e293b44;
}

.sb-tab-active {
  color: #f1f5f9;
  background: #1e293b;
  border-color: #334155;
  border-bottom-color: #1e293b;
}

/* Table */
.sb-table-wrap {
  overflow-x: auto;
  border: 1px solid #1e293b;
  border-top: none;
  border-radius: 0 0 10px 10px;
  margin-bottom: 16px;
}

.sb-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.84rem;
}

.sb-table thead tr {
  background: #0f172a;
}

.sb-table th {
  padding: 10px 12px;
  text-align: left;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: #64748b;
  border-bottom: 1px solid #1e293b;
  white-space: nowrap;
}

.sb-table tbody tr {
  border-bottom: 1px solid #1e293b;
  transition: background 0.1s;
}

.sb-table tbody tr:hover {
  background: #1e293b55;
}

.sb-table tbody tr:last-child {
  border-bottom: none;
}

.sb-table td {
  padding: 9px 12px;
  color: #cbd5e1;
}

/* Stat cards */
.sb-stat-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  gap: 10px;
  margin-top: 16px;
}

.sb-stat-card {
  background: #0f172a;
  border: 1px solid #1e293b;
  border-radius: 10px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  transition: border-color 0.15s;
}

.sb-stat-card:hover { border-color: #334155; }

.sb-card-cost {
  border-color: #7f1d1d44;
  background: linear-gradient(135deg, #0f172a 60%, #2d0a0a22);
}

.sb-card-profit {
  border-color: #14532d44;
  background: linear-gradient(135deg, #0f172a 60%, #052e1622);
}

.sb-stat-label {
  font-size: 0.67rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #64748b;
}

.sb-stat-value {
  font-size: 1.1rem;
  font-weight: 700;
  color: #f1f5f9;
  line-height: 1;
}

.sb-card-cost .sb-stat-value { color: #f87171; }
.sb-card-profit .sb-stat-value { color: #4ade80; }

.sb-giveaway-total {
  font-size: 0.85rem;
  font-weight: 600;
  color: #94a3b8;
  margin-top: 10px;
  padding: 8px 12px;
  background: #0f172a;
  border-radius: 8px;
  border: 1px solid #1e293b;
}

/* Remove old session-summary & cost-profit-stack if still referenced */
.session-summary { display: none; }
.cost-profit-stack { display: none; }

.rolling-show-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 850;
  display: flex;
  gap: 14px;
  align-items: center;
  flex-wrap: wrap;
  padding: 10px 16px;
  border-top: 1px solid #334155;
  background: rgba(15, 23, 42, 0.96);
  color: #dbeafe;
  font-weight: 700;
}

/* When a modal is open, hide the rolling stream-stats bar entirely.
   Without this, its fixed footprint crowds the bottom of the viewport
   and the modal's last row feels "stuck" against an invisible shelf,
   even though the modal's z-index puts the panel on top. */
body.modal-open .rolling-show-bar {
  display: none !important;
}

.rolling-timer {
  font-family: "Courier New", Courier, monospace;
  font-size: 1.05rem;
  font-weight: 800;
  color: #fbbf24;
  letter-spacing: 1px;
  min-width: 68px;
}
.rolling-timer:empty { display: none; }

.rolling-commission {
  font-weight: 800;
  color: #a78bfa;
  font-size: 0.95rem;
  letter-spacing: 0.3px;
}

#sessionTable input[type="number"] {
  width: 90px;
}

.catalog-add-qty {
  width: 70px;
}

/* ± stepper around the qty input — explicit buttons replace the native
   number-input spinners, which were unreliable across browsers/touch and
   the user reported them as "dead." */
.catalog-qty-stepper {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid #374151;
  border-radius: 6px;
  overflow: hidden;
  background: #1f2937;
}
.catalog-qty-stepper .catalog-qty-step {
  background: #374151;
  color: #f3f4f6;
  border: 0;
  padding: 0 10px;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  font-weight: 600;
  min-width: 28px;
}
.catalog-qty-stepper .catalog-qty-step:hover {
  background: #4b5563;
}
.catalog-qty-stepper .catalog-qty-step:active {
  background: #6366f1;
}
.catalog-qty-stepper .catalog-add-qty {
  width: 48px;
  border: 0;
  border-radius: 0;
  text-align: center;
  background: transparent;
  color: #f3f4f6;
  -moz-appearance: textfield; /* Firefox: hide native spinner */
}
.catalog-qty-stepper .catalog-add-qty::-webkit-inner-spin-button,
.catalog-qty-stepper .catalog-add-qty::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.actions-cell {
  white-space: nowrap;
}

/* Inline stock ± stepper for admin/tech roles. Click + / − fires
   PATCH /api/products/:id/stock with a quick-adjust reason. The display
   number flashes briefly on optimistic update. */
.stock-cell-mgr { white-space: nowrap; }
.stock-stepper {
  display: inline-flex;
  align-items: stretch;
  border: 1px solid #374151;
  border-radius: 6px;
  overflow: hidden;
  background: #1f2937;
}
.stock-stepper .stock-step {
  background: #374151;
  color: #f3f4f6;
  border: 0;
  padding: 0 8px;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  font-weight: 600;
  min-width: 24px;
}
.stock-stepper .stock-step:hover:not([disabled]) { background: #4b5563; }
.stock-stepper .stock-step:active:not([disabled]) { background: #6366f1; }
.stock-stepper .stock-step[disabled] { opacity: 0.45; cursor: wait; }
.stock-stepper .stock-qty-display {
  min-width: 36px;
  padding: 4px 6px;
  text-align: center;
  font-weight: 700;
  background: transparent;
  color: #f3f4f6;
}
.stock-stepper .stock-qty-display.stock-flash {
  color: #fbbf24;
  transition: color 200ms;
}

#sessionListPanel {
  margin-bottom: 10px;
  border: 1px solid #374151;
  border-radius: 6px;
  padding: 8px;
  background: #111827;
}

.session-list-item {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: center;
  border-bottom: 1px solid #374151;
  padding: 6px 0;
}

.session-list-item:last-child {
  border-bottom: none;
}

.rule-chip {
  display: inline-block;
  border: 1px solid #334155;
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 12px;
  margin-right: 6px;
  color: #cbd5e1;
}

.warn-text {
  color: #fca5a5;
  font-weight: 600;
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;
}

.lightbox.hidden {
  display: none !important;
}

.lightbox-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.75);
}

.lightbox-content {
  position: relative;
  z-index: 2;
  max-width: min(92vw, 1200px);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.lightbox-image {
  max-width: 100%;
  max-height: calc(90vh - 44px);
  border-radius: 8px;
  border: 1px solid #374151;
  background: #0b1220;
}

.lightbox-close {
  align-self: flex-end;
}

.modal {
  position: fixed;
  inset: 0;
  z-index: 950;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 48px;
}

.modal.hidden {
  display: none !important;
}

.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
}

.modal-panel {
  position: relative;
  z-index: 2;
  width: min(92vw, 640px);
  max-height: calc(100vh - 90px);
  overflow: auto;
  margin-top: 0;
}

/* TCG Pricing */
.tcg-price-cell {
  color: #67e8f9;
  font-weight: 600;
  white-space: nowrap;
}
/* Tiny re-pull (↻) button shown next to an already-priced TCG cell so a
   single suspicious price can be refreshed without a full bulk refresh.
   Muted by default, brightens on hover so it doesn't clutter the table. */
.tcg-reprice-btn {
  background: transparent;
  border: 0;
  color: #67e8f9;
  opacity: 0.35;
  cursor: pointer;
  font-size: 0.95em;
  padding: 0 2px;
  line-height: 1;
  vertical-align: baseline;
}
.tcg-reprice-btn:hover { opacity: 1; }
.tcg-reprice-btn:disabled { opacity: 0.6; cursor: default; }

/* Stale-TCG-price flag — amber marker next to a stored price older than the
   staleness window (default 48h). Signals "re-pull before pricing a buy". */
.tcg-stale {
  display: inline-block;
  margin-left: 4px;
  padding: 0 4px;
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 700;
  white-space: nowrap;
  color: #b45309;
  background: #fef3c7;
  border: 1px solid #f59e0b;
  cursor: help;
}

.tcg-adjusted-cell {
  color: #a78bfa;
  font-weight: 600;
  white-space: nowrap;
}

.tcg-unlinked {
  color: #64748b;
}

.tcg-link-btn {
  font-size: 0.75rem;
  padding: 2px 8px;
}

.tcg-link-result-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 0;
  border-bottom: 1px solid #1e293b;
}

.tcg-link-result-row:last-child {
  border-bottom: none;
}

#addItemTcgSearchResults {
  margin-top: 8px;
  border: 1px solid #1e293b;
  border-radius: 8px;
  padding: 8px 10px;
  max-height: 220px;
  overflow: auto;
  background: #0b1220;
}

#addItemTcgSelect {
  width: 100%;
  margin-top: 8px;
  border: 1px solid #1e293b;
  border-radius: 8px;
  background: #0b1220;
  color: #e5e7eb;
  padding: 8px;
}

#tcgSearchTable {
  width: 100%;
}

#tcgLinkPanel {
  width: min(92vw, 720px);
}

/* --- Assignment schedule / expiry --- */
.assignment-scheduled-badge {
  display: inline-block;
  background: #1e3a5f;
  color: #93c5fd;
  border: 1px solid #2563eb;
  border-radius: 5px;
  padding: 1px 8px;
  font-size: 0.78rem;
  font-weight: 600;
  vertical-align: middle;
  margin-left: 4px;
}

.assignment-expired-badge {
  display: inline-block;
  background: #450a0a;
  color: #fca5a5;
  border: 1px solid #dc2626;
  border-radius: 5px;
  padding: 1px 8px;
  font-size: 0.78rem;
  font-weight: 700;
  vertical-align: middle;
  margin-left: 4px;
}

.assignment-expired {
  opacity: 0.7;
  border-left: 3px solid #dc2626;
}

.assignment-status-expired {
  color: #f87171;
}

/* --- Pagination --- */
.pagination-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 4px;
  flex-wrap: wrap;
}

.pagination-info {
  color: #94a3b8;
  font-size: 0.85rem;
  margin-right: 6px;
}

.pagination-controls {
  display: flex;
  gap: 5px;
  flex-wrap: wrap;
  align-items: center;
}

.pagination-btn {
  min-width: 36px;
  padding: 4px 10px;
  font-size: 0.85rem;
  border-radius: 6px;
  cursor: pointer;
}

.pagination-btn.pagination-active {
  background: linear-gradient(135deg, #3b82f6, #6366f1);
  color: #fff;
  border: none;
  font-weight: 700;
  cursor: default;
}

.pagination-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.pagination-ellipsis {
  color: #64748b;
  padding: 0 4px;
  line-height: 2;
}

/* Page size selector in toolbar */
.page-size-label {
  display: flex;
  align-items: center;
  gap: 5px;
  color: #94a3b8;
  font-size: 0.85rem;
  white-space: nowrap;
}

.page-size-label select {
  padding: 4px 8px;
  border-radius: 6px;
  background: #1e293b;
  border: 1px solid #334155;
  color: #e5e7eb;
  font-size: 0.85rem;
}

.report-download-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}

.report-dl-btn {
  font-size: 0.82rem;
  padding: 5px 12px;
  border-radius: 6px;
}

/* ── Stream Analytics ─────────────────────────────────────── */
.analytics-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
  padding-bottom: 12px;
  border-bottom: 1px solid #1e293b;
}

.analytics-header h3 {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 700;
  color: #e2e8f0;
  letter-spacing: 0.03em;
}

/* ── Product Change Log filter bar + load-more ─────────────────────── */
.change-log-filter-bar {
  padding: 14px 16px !important;
  background:
    linear-gradient(135deg, rgba(99, 102, 241, 0.05) 0%, rgba(15, 23, 42, 0.92) 60%, rgba(139, 92, 246, 0.04) 100%),
    #0f172a !important;
  border: 1px solid rgba(99, 102, 241, 0.22) !important;
  border-radius: 12px !important;
  margin-bottom: 12px !important;
}
.change-log-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.change-log-field-label {
  font-family: "Inter", system-ui, sans-serif;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #94a3b8;
}
.change-log-filter-bar input[type="text"],
.change-log-filter-bar input[type="date"] {
  background: linear-gradient(180deg, #1e293b 0%, #192235 100%);
  border: 1px solid rgba(71, 85, 105, 0.6);
  border-radius: 8px;
  color: #e2e8f0;
  padding: 7px 10px;
  font-family: "Inter", system-ui, sans-serif;
  font-size: 0.88rem;
  color-scheme: dark;
  transition: border-color 0.18s, box-shadow 0.18s;
}
.change-log-filter-bar input:focus {
  border-color: #8b5cf6;
  outline: none;
  box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.18);
}
.change-log-range-btn {
  font-size: 0.78rem !important;
  padding: 6px 10px !important;
  border-radius: 6px !important;
  min-width: 42px;
}
.change-log-range-btn.active {
  background: linear-gradient(135deg, #6366f1, #8b5cf6) !important;
  color: #fff !important;
  border-color: rgba(139, 92, 246, 0.6) !important;
}
.change-log-meta {
  font-size: 0.78rem;
  color: #94a3b8;
  margin-left: auto;
  font-family: "Inter", system-ui, sans-serif;
}
.change-log-load-more {
  display: flex;
  justify-content: center;
  padding: 14px 0 6px;
}
.change-log-load-more.hidden { display: none; }
.change-log-load-more button {
  padding: 8px 18px;
  font-weight: 600;
  background: linear-gradient(135deg, rgba(99, 102, 241, 0.22), rgba(139, 92, 246, 0.18));
  border: 1px solid rgba(139, 92, 246, 0.45);
  color: #c7d2fe;
  border-radius: 8px;
}
.change-log-load-more button:hover {
  filter: brightness(1.15);
  box-shadow: 0 0 12px rgba(139, 92, 246, 0.35);
}
.change-log-load-more button[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
}

/* ── Analytics filter bar — premium lift ───────────────────────────── */
.analytics-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 14px;
  margin-bottom: 24px;
  padding: 18px 20px;
  background:
    linear-gradient(135deg, rgba(99, 102, 241, 0.04) 0%, rgba(15, 23, 42, 0.9) 60%, rgba(139, 92, 246, 0.04) 100%),
    #0f172a;
  border: 1px solid rgba(99, 102, 241, 0.22);
  border-radius: 14px;
  box-shadow:
    0 1px 0 rgba(148, 163, 184, 0.05) inset,
    0 8px 24px -12px rgba(15, 23, 42, 0.7);
}

.analytics-filter-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.analytics-filter-label {
  font-family: "Inter", system-ui, sans-serif;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: #94a3b8;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.analytics-filter-label::before {
  font-size: 0.82rem;
  opacity: 0.85;
}
.analytics-filter-group:nth-child(1) .analytics-filter-label::before { content: "📅"; }
.analytics-filter-group:nth-child(2) .analytics-filter-label::before { content: "📅"; }
.analytics-filter-group:nth-child(3) .analytics-filter-label::before { content: "👤"; }
.analytics-filter-group:nth-child(4) .analytics-filter-label::before { content: "🎥"; }

/* Inline subtitle next to Creator/Streamer to disambiguate them at a
   glance — used to require a tooltip hover to know the difference. */
.analytics-filter-sub {
  font-size: 0.62rem;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0.02em;
  color: rgba(148, 163, 184, 0.65);
  font-style: italic;
  margin-left: 4px;
}

.analytics-filter-input {
  background: linear-gradient(180deg, #1e293b 0%, #192235 100%);
  border: 1px solid rgba(71, 85, 105, 0.6);
  border-radius: 9px;
  color: #e2e8f0;
  padding: 9px 12px;
  font-family: "Inter", system-ui, sans-serif;
  font-size: 0.9rem;
  font-weight: 500;
  min-width: 150px;
  transition: border-color 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
  color-scheme: dark;
}
.analytics-filter-input::placeholder {
  color: #64748b;
  font-weight: 400;
}
.analytics-filter-input:hover {
  border-color: rgba(99, 102, 241, 0.4);
  background: linear-gradient(180deg, #1f2a40 0%, #1a2339 100%);
}
.analytics-filter-input:focus {
  border-color: #8b5cf6;
  outline: none;
  background: #1b2538;
  box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.18);
}

/* Better-looking native date picker icon on dark theme. Webkit's
   default calendar glyph is black — color-scheme:dark above flips
   most of that, and this makes the click target bigger + more
   discoverable on hover. */
.analytics-filter-input[type="date"]::-webkit-calendar-picker-indicator {
  filter: invert(0.6) brightness(1.4);
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 0.15s;
}
.analytics-filter-input[type="date"]:hover::-webkit-calendar-picker-indicator,
.analytics-filter-input[type="date"]:focus::-webkit-calendar-picker-indicator {
  opacity: 1;
}

.analytics-load-btn {
  padding: 10px 22px;
  border-radius: 9px;
  font-family: "Manrope", "Inter", system-ui, sans-serif;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 55%, #a855f7 100%);
  color: #fff;
  border: 1px solid rgba(139, 92, 246, 0.55);
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.15s ease, filter 0.15s ease;
  align-self: flex-end;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.14) inset,
    0 6px 20px -8px rgba(139, 92, 246, 0.55);
}

.analytics-load-btn:hover {
  filter: brightness(1.08);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.18) inset,
    0 10px 24px -8px rgba(139, 92, 246, 0.75);
}

.analytics-load-btn:active {
  transform: translateY(1px);
}

/* Stat cards */
.analytics-stat-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 20px;
}

.analytics-stat-card {
  background: #0f172a;
  border: 1px solid #1e293b;
  border-radius: 12px;
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  transition: border-color 0.15s;
  flex: 1 1 120px;
  min-width: 110px;
  max-width: 180px;
}

.analytics-stat-card:hover {
  border-color: #334155;
}

.analytics-card-gmv {
  border-color: #1d4ed8;
  background: linear-gradient(135deg, #0f172a 60%, #1e3a5f33);
}

.analytics-card-profit {
  border-color: #15803d;
  background: linear-gradient(135deg, #0f172a 60%, #14532d33);
}

.analytics-stat-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #64748b;
}

.analytics-stat-value {
  font-size: 1.35rem;
  font-weight: 700;
  color: #f1f5f9;
  line-height: 1;
}

.analytics-card-gmv .analytics-stat-value {
  color: #60a5fa;
}

.analytics-card-profit .analytics-stat-value {
  color: #4ade80;
}

/* Table */
.analytics-table-wrap {
  overflow-x: auto;
  border-radius: 10px;
  border: 1px solid #1e293b;
}

/* Top scrollbar shim — a small div above the analytics table whose
   horizontal overflow mirrors the table-wrap's. JS keeps the two
   scroll positions in lock-step so dragging EITHER scrollbar moves
   the table. Eliminates the "I have to scroll the whole page down
   just to grab the bottom scrollbar" friction. */
.analytics-top-scroll-shim {
  overflow-x: auto;
  overflow-y: hidden;
  height: 16px;
  margin-bottom: 4px;
  border-radius: 8px;
  border: 1px solid #1e293b;
  background: #0a1124;
  /* Firefox-only — keeps the scrollbar visible when there's overflow */
  scrollbar-width: thin;
}
.analytics-top-scroll-shim::-webkit-scrollbar {
  height: 12px;
}
.analytics-top-scroll-shim::-webkit-scrollbar-track {
  background: #0a1124;
}
.analytics-top-scroll-shim::-webkit-scrollbar-thumb {
  background: #334155;
  border-radius: 6px;
}
.analytics-top-scroll-shim::-webkit-scrollbar-thumb:hover {
  background: #475569;
}
.analytics-top-scroll-shim > div {
  /* JS sets this to the table's scrollWidth on every load so the
     shim has the same scrollable extent as the table. Height kept
     tiny so the shim is just a scrollbar — no visual content. */
  height: 1px;
}

.analytics-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.82rem;
  min-width: 900px;
}

.analytics-table thead tr {
  background: #0f172a;
}

.analytics-table th {
  padding: 10px 12px;
  text-align: left;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: #64748b;
  border-bottom: 1px solid #1e293b;
  white-space: nowrap;
}

.analytics-table tbody tr {
  border-bottom: 1px solid #1e293b;
  transition: background 0.1s;
}

.analytics-table tbody tr:hover {
  background: #1e293b55;
}

.analytics-table tbody tr:last-child {
  border-bottom: none;
}

.analytics-table td {
  padding: 9px 12px;
  color: #cbd5e1;
  white-space: nowrap;
}

/* Inline ✏ edit buttons on session-builder stat cards (Total Cost,
   Giveaway Cost). Admin-only — hidden for streamers via the
   data-streamer-simple-hide hook on the buttons themselves. The
   button sits inline with the stat label so it doesn't intrude on
   the value display. */
.sb-stat-edit-btn {
  background: rgba(34, 197, 94, 0.18);
  color: #bbf7d0;
  border: 1px solid rgba(34, 197, 94, 0.45);
  border-radius: 6px;
  font-size: 0.68rem;
  padding: 1px 5px;
  margin-left: 6px;
  cursor: pointer;
  line-height: 1.1;
  transition: filter 0.12s, transform 0.12s;
}
.sb-stat-edit-btn:hover {
  filter: brightness(1.1);
  transform: translateY(-1px);
}

.analytics-profit-pos {
  color: #4ade80 !important;
  font-weight: 600;
}

.analytics-profit-neg {
  color: #f87171 !important;
  font-weight: 600;
}

/* Sticky Date + Streamer columns on the analytics sessions table.
   The table is much wider than the viewport (15 columns) and the
   horizontal scrollbar lives at the bottom of the table, so to see
   who a -$5,577 profit row belongs to, the owner had to either
   scroll the page all the way down to grab the scrollbar OR scroll
   right and lose the streamer column off the left. Pinning the
   first two cells of every row to the viewport's left edge keeps
   the streamer + date visible no matter how far right you scroll.
   Reported May 13: "I should be able to scroll to the left, not
   have to go to the bottom to scroll to the left, to see who is
   the -5577.40 — or make it spread better so I can see everything
   as I need."
   Fixed pixel widths on cols 1 and 2 so the left-offset on col 2
   stays predictable. The 95+110 split matches typical content
   width: dates like "5/13/2026" fit comfortably in 95px and
   streamer handles ("sushi", "dr-chop") fit in 110px. */
/* IMPORTANT: scoped to #analyticsTable, NOT .analytics-table. The
   session-detail modal's Hit/Floor/Giveaway tables share the
   .analytics-table class but have a totally different schema (6
   columns, column 2 is a long product Name). Applying the 110px
   max-width sticky rule there mangled the name column into
   overlapping the category cell. Reported May 14: "now they are
   jumbled over each other." Keeping the sticky behavior tied to
   the specific id avoids that regression. */
#analyticsTable th:nth-child(1),
#analyticsTable td:nth-child(1) {
  position: sticky;
  left: 0;
  z-index: 1;
  min-width: 95px;
  max-width: 95px;
  background: #0a1124;
}
#analyticsTable th:nth-child(2),
#analyticsTable td:nth-child(2) {
  position: sticky;
  left: 95px;
  z-index: 1;
  min-width: 110px;
  max-width: 110px;
  background: #0a1124;
  box-shadow: 1px 0 0 #1e293b;
}
#analyticsTable thead th:nth-child(1),
#analyticsTable thead th:nth-child(2) {
  z-index: 2;
  background: #0f172a;
}
#analyticsTable tbody tr:hover td:nth-child(1),
#analyticsTable tbody tr:hover td:nth-child(2) {
  background: #16223e;
}

/* ── Shipper clock panel (bilingual) ───────────────────────────────────── */
.hclock-wrap {
  max-width: 560px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.hclock-hero {
  text-align: center;
  padding: 28px 20px 20px;
  background: linear-gradient(135deg, #0f172a, #1e293b);
  border: 1px solid #334155;
  border-radius: 18px;
}

.hclock-greeting {
  font-size: 0.82rem;
  color: #64748b;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 4px;
}

.hclock-name {
  font-size: 1.6rem;
  font-weight: 800;
  color: #f1f5f9;
  margin-bottom: 12px;
  letter-spacing: 0.01em;
}

.hclock-time {
  font-size: 2.8rem;
  font-weight: 700;
  color: #fff;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  line-height: 1;
}

.hclock-date {
  font-size: 0.9rem;
  color: #94a3b8;
  margin-top: 6px;
  text-transform: capitalize;
}

.hclock-status-card {
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 16px;
  padding: 28px 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.hclock-status-label {
  font-size: 1.15rem;
  font-weight: 700;
  text-align: center;
}
.hclock-in  { color: #4ade80; }
.hclock-out { color: #f87171; }

.hclock-elapsed {
  font-size: 0.88rem;
  color: #94a3b8;
  font-variant-numeric: tabular-nums;
  min-height: 1.2em;
  text-align: center;
}

.hclock-btn {
  width: 260px;
  padding: 16px 0;
  font-size: 1.15rem;
  font-weight: 800;
  border: none;
  border-radius: 12px;
  cursor: pointer;
  letter-spacing: 0.03em;
  transition: opacity 0.15s, transform 0.1s;
}
.hclock-btn-in  { background: linear-gradient(135deg, #22c55e, #15803d); color: #fff; box-shadow: 0 4px 18px #22c55e40; }
.hclock-btn-out { background: linear-gradient(135deg, #ef4444, #b91c1c); color: #fff; box-shadow: 0 4px 18px #ef444440; }
.hclock-btn:hover  { opacity: 0.88; transform: translateY(-2px); }
.hclock-btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; box-shadow: none; }

.hclock-punches {
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 14px;
  padding: 20px;
}

.hclock-punches-title {
  font-size: 0.78rem;
  color: #64748b;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 12px;
}

.hclock-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.hclock-table th {
  color: #64748b;
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 0 10px 8px;
  text-align: left;
  font-weight: 600;
}
.hclock-table td {
  padding: 8px 10px;
  border-top: 1px solid #0f172a;
  color: #cbd5e1;
}
.hclock-active-cell { color: #4ade80; font-weight: 600; }
.hclock-empty { color: #475569; padding: 12px 0; text-align: center; }

.hclock-total {
  margin-top: 12px;
  font-size: 0.9rem;
  color: #94a3b8;
  text-align: right;
}
.hclock-total strong { color: #f1f5f9; }

/* ── Hours Dashboard (management) — Premium ──────────────────────────── */
#hoursDashboardPanel {
  background:
    radial-gradient(circle at 0% 0%, rgba(99, 102, 241, 0.08) 0%, transparent 45%),
    radial-gradient(circle at 100% 100%, rgba(168, 85, 247, 0.06) 0%, transparent 45%),
    linear-gradient(160deg, #0d1117 0%, #0f172a 60%, #1a1040 100%);
  border: 1px solid rgba(99, 102, 241, 0.25);
  border-radius: 20px;
  padding: 28px 28px 32px;
  box-shadow: 0 20px 60px -30px rgba(99, 102, 241, 0.4);
}

.hd-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 26px;
  gap: 12px;
  flex-wrap: wrap;
  padding-bottom: 22px;
  border-bottom: 1px solid rgba(99, 102, 241, 0.18);
}
.hd-title {
  font-family: "Manrope", "Inter", system-ui, sans-serif;
  font-size: 1.6rem;
  font-weight: 800;
  background: linear-gradient(90deg, #a5b4fc, #818cf8, #c4b5fd);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  margin: 0 0 6px;
  letter-spacing: -0.02em;
}
.hd-subtitle {
  font-family: "Inter", system-ui, sans-serif;
  font-size: 0.88rem;
  /* Was #475569 — effectively invisible on the dark panel. Bumped to
     slate-300 with a touch of weight so the "Filter and review..." hint
     actually reads. */
  color: #cbd5e1;
  font-weight: 500;
  margin: 0;
  letter-spacing: 0.01em;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.hd-subtitle::before {
  content: "⏱";
  opacity: 0.85;
}
.hd-refresh-btn {
  background: transparent;
  border: 1px solid #334155;
  color: #6366f1;
  border-radius: 10px;
  padding: 9px 18px;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
  white-space: nowrap;
  letter-spacing: 0.02em;
}
.hd-refresh-btn:hover {
  background: #6366f118;
  border-color: #6366f1;
  color: #a5b4fc;
  box-shadow: 0 0 12px #6366f130;
}
.hd-print-btn {
  background: linear-gradient(135deg, #4f46e5, #7c3aed);
  border: none;
  color: #fff;
  border-radius: 10px;
  padding: 9px 18px;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.2s;
  white-space: nowrap;
  letter-spacing: 0.02em;
  box-shadow: 0 2px 12px #4f46e540;
}
.hd-print-btn:hover { opacity: 0.88; transform: translateY(-1px); box-shadow: 0 4px 18px #4f46e560; }

/* Range pills */
.hd-range-pills {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 16px;
  background: #0f172a;
  border: 1px solid #1e293b;
  border-radius: 12px;
  padding: 5px;
  width: fit-content;
}
.hd-pill {
  padding: 7px 20px;
  border-radius: 8px;
  font-size: 0.82rem;
  font-weight: 700;
  border: none;
  background: transparent;
  color: #475569;
  cursor: pointer;
  transition: all 0.18s;
  letter-spacing: 0.03em;
}
.hd-pill:hover { color: #94a3b8; background: #1e293b; }
.hd-pill-active {
  background: linear-gradient(135deg, #6366f1, #7c3aed);
  color: #fff;
  box-shadow: 0 3px 14px #6366f150;
}

/* Custom date row */
.hd-custom-dates {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
  padding: 12px 16px;
  background: #0f172a;
  border: 1px solid #1e293b;
  border-radius: 10px;
  width: fit-content;
}
.hd-custom-dates.hidden { display: none; }
.hd-date-input {
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 7px;
  padding: 7px 12px;
  color: #f1f5f9;
  font-size: 0.86rem;
}
.hd-date-input:focus { outline: none; border-color: #6366f1; }
.hd-date-sep { color: #334155; font-size: 1.1rem; }

/* Worker filter */
.hd-filter-row {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 24px;
}
.hd-filter-label {
  font-size: 0.75rem;
  color: #475569;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space: nowrap;
  font-weight: 700;
}
.hd-filter-select {
  background: #0f172a;
  border: 1px solid #1e293b;
  border-radius: 9px;
  padding: 8px 14px;
  color: #f1f5f9;
  font-size: 0.88rem;
  min-width: 200px;
  transition: border-color 0.15s;
}
.hd-filter-select:focus { outline: none; border-color: #6366f1; }

/* Stat cards */
.hd-stat-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
  margin-bottom: 24px;
}
.hd-stat-card {
  position: relative;
  background: linear-gradient(135deg, #0f172a, #1a1040);
  border: 1px solid #1e293b;
  border-radius: 16px;
  padding: 22px 20px 18px;
  text-align: center;
  overflow: hidden;
  transition: border-color 0.2s, transform 0.15s;
}
.hd-stat-card::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, #6366f1, #a855f7);
  border-radius: 16px 16px 0 0;
}
.hd-stat-card:hover { border-color: #334155; transform: translateY(-2px); }
.hd-stat-label {
  font-size: 0.7rem;
  color: #475569;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 10px;
  font-weight: 700;
}
.hd-stat-value {
  font-size: 1.9rem;
  font-weight: 900;
  color: #f1f5f9;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* Worker chips — section header */
.hd-worker-chips-header {
  font-size: 0.72rem;
  color: #334155;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
  margin-bottom: 12px;
}

/* Worker chips */
.hd-worker-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 24px;
}
.hd-worker-chip {
  position: relative;
  background: linear-gradient(135deg, #0f172a, #1e1b4b);
  border: 1px solid #312e81;
  border-radius: 14px;
  padding: 14px 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 120px;
  transition: border-color 0.2s, transform 0.15s;
}
.hd-worker-chip:hover { border-color: #6366f1; transform: translateY(-2px); }
.hd-chip-name {
  font-size: 0.75rem;
  color: #94a3b8;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}
.hd-chip-hours {
  font-size: 1.5rem;
  font-weight: 900;
  background: linear-gradient(135deg, #a5b4fc, #c4b5fd);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

/* Worker chip with overtime — orange accent border so the eye lands on
   anyone who went past 8/day or 40/week. */
.hd-worker-chip-has-ot { border-color: #d97706; }
.hd-worker-chip-has-ot:hover { border-color: #fb923c; }
.hd-chip-ot {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 10px;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.hd-chip-ot-daily {
  background: rgba(251, 146, 60, 0.18);
  color: #fb923c;
  border: 1px solid rgba(251, 146, 60, 0.4);
}
.hd-chip-ot-weekly {
  background: rgba(250, 204, 21, 0.16);
  color: #facc15;
  border: 1px solid rgba(250, 204, 21, 0.4);
}

/* Stat-card variant for OT — orange accent so the totals are scannable. */
.hd-stat-card-ot { border-color: rgba(251, 146, 60, 0.4); }
.hd-stat-card-ot .hd-stat-value {
  background: linear-gradient(135deg, #fbbf24, #fb923c);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* Shipper output (#505 questionnaire) — blue accent, matching the 📦
   badge already shown on session rows. */
.hd-stat-card-output { border-color: rgba(37, 99, 235, 0.45); }
.hd-stat-card-output .hd-stat-value {
  background: linear-gradient(135deg, #60a5fa, #93c5fd);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* Lives/carts badge on a worker chip. */
.hd-chip-output {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 10px;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
  background: rgba(37, 99, 235, 0.16);
  color: #60a5fa;
  border: 1px solid rgba(37, 99, 235, 0.4);
}

/* Shipper Output section — per-platform tally chips. */
.hd-output-section {
  margin: 0 0 24px;
  padding: 16px 18px;
  border: 1px solid rgba(37, 99, 235, 0.32);
  border-radius: 12px;
  background: rgba(37, 99, 235, 0.05);
}
.hd-output-title {
  font-size: 1rem;
  font-weight: 800;
  color: #60a5fa;
  margin: 0 0 6px;
  letter-spacing: 0.02em;
}
.hd-output-sub {
  font-size: 0.82rem;
  color: #94a3b8;
  margin: 0 0 12px;
  line-height: 1.45;
}
.hd-output-sub strong { color: #cbd5e1; }
.hd-output-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.hd-output-chip {
  background: linear-gradient(135deg, #0f172a, #172554);
  border: 1px solid #1e40af;
  border-radius: 14px;
  padding: 14px 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 120px;
  transition: border-color 0.2s, transform 0.15s;
}
.hd-output-chip:hover { border-color: #3b82f6; transform: translateY(-2px); }
.hd-output-lives {
  font-size: 1.5rem;
  font-weight: 900;
  background: linear-gradient(135deg, #60a5fa, #93c5fd);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.hd-output-shifts {
  font-size: 0.7rem;
  color: #64748b;
  font-weight: 700;
  letter-spacing: 0.05em;
}

/* Overage Detail section — per-day rows where the worker went over 8h. */
.hd-overage-section {
  margin-top: 22px;
  padding: 16px 18px;
  border: 1px solid rgba(251, 146, 60, 0.28);
  border-radius: 12px;
  background: rgba(251, 146, 60, 0.04);
}
.hd-overage-title {
  font-size: 1rem;
  font-weight: 800;
  color: #fb923c;
  margin: 0 0 6px;
  letter-spacing: 0.02em;
}
.hd-overage-sub {
  font-size: 0.82rem;
  color: #94a3b8;
  margin: 0 0 12px;
  line-height: 1.45;
}
.hd-overage-sub strong { color: #cbd5e1; }
.hd-td-overage {
  color: #fb923c;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Records table */
.hd-table-wrap {
  overflow-x: auto;
  border-radius: 14px;
  border: 1px solid #1e293b;
  background: #0a0f1a;
}
.hd-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.87rem;
  min-width: 580px;
}
.hd-table thead tr {
  border-bottom: 1px solid #1e293b;
}
.hd-table th {
  background: #0d1117;
  color: #334155;
  padding: 13px 16px;
  text-align: left;
  font-weight: 700;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  white-space: nowrap;
}
.hd-table td {
  padding: 12px 16px;
  border-bottom: 1px solid #0f172a;
  color: #94a3b8;
  white-space: nowrap;
}
.hd-table tbody tr { transition: background 0.12s; }
.hd-table tbody tr:hover { background: #1e293b40; }
.hd-table tbody tr:last-child td { border-bottom: none; }
.hd-td-worker {
  font-weight: 800;
  color: #e2e8f0;
  font-size: 0.9rem;
}
/* Higher specificity than `.hd-table td` (0,1,1) so white-space:normal wins —
   otherwise the td's nowrap kept long notes on one line, overflowing under the
   Edit button (operator: "notes can't be seen correctly"). Wrap + cap width. */
.hd-table td.hd-td-notes {
  color: #cbd5e1;
  font-size: 0.8rem;
  white-space: normal;
  word-break: break-word;
  overflow-wrap: anywhere;
  max-width: 340px;
  min-width: 200px;
  line-height: 1.4;
}
.hd-active-row {
  color: #4ade80;
  font-weight: 700;
  font-size: 0.82rem;
}
.hd-empty {
  color: #1e293b;
  padding: 32px;
  text-align: center;
  font-size: 0.9rem;
  letter-spacing: 0.05em;
}
/* ── Required field indicator & input error ──────────────────────────── */
.required-star {
  color: #f87171;
  font-weight: 800;
}
.input-error-highlight {
  outline: 2px solid #f87171 !important;
  box-shadow: 0 0 0 3px rgba(248,113,113,0.3) !important;
  animation: input-shake 0.3s ease;
}
@keyframes input-shake {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}

/* ── Low stock badge ──────────────────────────────────────────────────── */
.low-stock-badge {
  display: inline-block;
  background: #f59e0b;
  color: #1e293b;
  font-size: 0.65rem;
  font-weight: 800;
  padding: 1px 5px;
  border-radius: 4px;
  margin-left: 4px;
  vertical-align: middle;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.low-stock-filter-label {
  font-size: 0.82rem;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 4px;
  color: #fbbf24;
  font-weight: 600;
}

/* ── Restock log ──────────────────────────────────────────────────────── */
.restock-log-section {
  margin-top: 14px;
  font-size: 0.82rem;
  color: #94a3b8;
}
.restock-log-section summary { cursor: pointer; font-weight: 600; color: #dbeafe; }

/* ── Bulk action bar ──────────────────────────────────────────────────── */
.bulk-action-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 8px;
  margin-bottom: 10px;
  font-size: 0.85rem;
  color: #dbeafe;
}
.bulk-action-bar.hidden { display: none; }

/* ── Announcements ────────────────────────────────────────────────────── */
.announcements-panel {
  background: linear-gradient(135deg, #1e3a5f 0%, #0f172a 100%);
  border: 1px solid #334155;
  border-radius: 10px;
  padding: 14px 18px;
  margin-bottom: 14px;
}
.announcements-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}
.announcements-header h3 { margin: 0; color: #fbbf24; }
.announcement-item {
  padding: 8px 0;
  border-bottom: 1px solid #1e293b;
}

/* ── Announcement-panel tabs (Announcements / Upcoming Events) ──────── */
/* Inline tab bar at the top of the panel — same gradient backdrop as the
   panel itself, sits flush with the rounded corners. The active tab pulls
   the same amber as the announcements header so the user's eye stays on a
   single accent color across both tabs. */
.ap-tabs {
  display: flex;
  gap: 4px;
  margin-bottom: 10px;
  border-bottom: 1px solid #334155;
}
.ap-tab {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  color: #94a3b8;
  font-size: 0.9rem;
  font-weight: 600;
  padding: 6px 12px;
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.ap-tab:hover { color: #e2e8f0; }
.ap-tab.active {
  color: #fbbf24;
  border-bottom-color: #fbbf24;
}
.ap-tab-badge {
  background: #fbbf24;
  color: #0f172a;
  border-radius: 999px;
  padding: 0 7px;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.4;
}
.ap-tab-panel.hidden { display: none; }

/* ── Upcoming Events ──────────────────────────────────────────────────── */
/* Event cards stack with a slim left-border accent colored by event type
   so the user can scan the list and pick out "the auction" or "the
   comic con" without reading every title. The badge uses the same color
   palette for cohesion. */
.event-card {
  position: relative;
  background: rgba(15, 23, 42, 0.5);
  border: 1px solid #1e293b;
  border-left-width: 4px;
  border-radius: 6px;
  padding: 10px 12px;
  margin-bottom: 8px;
}
.event-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}
.event-title { color: #f8fafc; font-size: 1rem; }
.event-badge {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 4px;
  background: #334155;
  color: #e2e8f0;
}
.event-badge-card_show   { background: #1e3a8a; color: #bfdbfe; }
.event-badge-tcg_event   { background: #5b21b6; color: #ddd6fe; }
.event-badge-comic_con   { background: #831843; color: #fbcfe8; }
.event-badge-auction     { background: #78350f; color: #fed7aa; }
.event-badge-store_event { background: #064e3b; color: #a7f3d0; }
.event-badge-other       { background: #334155; color: #cbd5e1; }
.event-card[data-event-id] { border-left-color: #475569; }
.event-card:has(.event-badge-card_show)   { border-left-color: #3b82f6; }
.event-card:has(.event-badge-tcg_event)   { border-left-color: #a78bfa; }
.event-card:has(.event-badge-comic_con)   { border-left-color: #f472b6; }
.event-card:has(.event-badge-auction)     { border-left-color: #fb923c; }
.event-card:has(.event-badge-store_event) { border-left-color: #34d399; }

.event-meta { color: #cbd5e1; font-size: 0.85rem; margin-bottom: 2px; }
.event-venue { color: #e2e8f0; font-size: 0.85rem; }
.event-address { font-size: 0.78rem; margin-top: 2px; }
.event-extras { display: flex; gap: 10px; align-items: center; margin-top: 4px; }
.event-fee {
  background: #1e293b;
  color: #fde68a;
  font-size: 0.75rem;
  padding: 2px 8px;
  border-radius: 4px;
}
.event-url { color: #93c5fd; font-size: 0.8rem; text-decoration: none; }
.event-url:hover { text-decoration: underline; }
.event-desc {
  margin: 6px 0 0;
  color: #e2e8f0;
  font-size: 0.85rem;
  line-height: 1.4;
  white-space: pre-wrap;
}
.event-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px dashed #1e293b;
}
.event-admin {
  margin-left: auto;
  display: inline-flex;
  gap: 4px;
}
.event-admin button {
  font-size: 0.7rem;
  padding: 2px 8px;
}

/* Comment thread expands inline under each event. Keep it tight and
   visually distinct from the parent card so the user reads it as a
   sub-feed, not a continuation of the event metadata. */
.event-thread {
  margin-top: 8px;
  padding: 8px;
  background: rgba(15, 23, 42, 0.7);
  border: 1px solid #1e293b;
  border-radius: 4px;
}
.event-thread.hidden { display: none; }
.event-thread-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }
.event-comment {
  padding: 6px 8px;
  background: #1e293b;
  border-radius: 4px;
}
.event-comment-head {
  display: flex;
  gap: 8px;
  align-items: center;
  font-size: 0.75rem;
}
.event-comment-head strong { color: #fde68a; }
.event-comment-head .hint { color: #94a3b8; }
.event-comment-head button { margin-left: auto; }
.event-comment-body {
  color: #e2e8f0;
  font-size: 0.85rem;
  margin-top: 3px;
  white-space: pre-wrap;
  word-wrap: break-word;
}
.event-thread-compose {
  display: flex;
  gap: 6px;
}
.event-thread-compose input {
  flex: 1;
  font-size: 0.85rem;
  padding: 4px 8px;
}
.event-thread-compose button {
  font-size: 0.8rem;
  padding: 4px 12px;
}

.link-btn {
  background: transparent;
  border: none;
  color: #93c5fd;
  cursor: pointer;
  font-size: 0.8rem;
  padding: 2px 4px;
}
.link-btn:hover { text-decoration: underline; }
.link-btn.danger { color: #fca5a5; }

/* ── Assignment comments ──────────────────────────────────────────────── */
.assignment-comments-wrap {
  width: 100%;
  font-size: 0.78rem;
  margin-top: 4px;
}
.assignment-comment {
  padding: 3px 0;
  border-bottom: 1px solid #1e293b;
  color: #cbd5e1;
}
.assignment-countdown {
  font-weight: 700;
  font-size: 0.78rem;
}

/* ── Shipper week summary ─────────────────────────────────────────────── */
.hclock-week-wrap { margin-bottom: 12px; }
.hclock-week-card {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
  border: 1px solid #334155;
  border-radius: 10px;
}
.hclock-week-num {
  font-size: 1.6rem;
  font-weight: 800;
  color: #60a5fa;
}
.hclock-week-label {
  font-size: 0.82rem;
  color: #94a3b8;
}
/* Failure state for the week card. The panel must always SAY something —
   blanking it made an expired session look like missing hours. */
.hclock-week-card-msg {
  flex-wrap: wrap;
  font-size: 0.85rem;
  color: #fbbf24;
  border-color: #78350f;
}

/* Shipper weekly detail breakdown */
.hclock-week-detail-wrap { margin-bottom: 12px; }
.hclock-week-detail-card {
  background: linear-gradient(180deg, #1b273a 0%, #172235 100%);
  border: 1px solid #334155;
  border-radius: 12px;
  padding: 14px 18px;
}
.hclock-week-detail-title {
  font-size: 0.78rem;
  font-weight: 700;
  color: #94a3b8;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 10px;
}

/* Shipper hours history (week/month/year navigation) */
.hclock-history-wrap {
  background: linear-gradient(180deg, #1b273a 0%, #172235 100%);
  border: 1px solid #334155;
  border-radius: 12px;
  padding: 14px 18px;
  margin-bottom: 12px;
}
.hclock-history-header { margin-bottom: 10px; }
.hclock-history-title {
  font-size: 0.86rem;
  font-weight: 700;
  color: #cbd5e1;
}
.hclock-history-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.hclock-history-pills {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.hclock-history-pill {
  background: #0f172a;
  border: 1px solid #334155;
  color: #94a3b8;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 6px 12px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.hclock-history-pill:hover {
  background: #1e293b;
  color: #cbd5e1;
}
.hclock-history-pill-active {
  background: #2563eb;
  border-color: #3b82f6;
  color: #f8fafc;
}
.hclock-history-pill-active:hover {
  background: #2563eb;
  color: #f8fafc;
}
.hclock-history-nav {
  display: flex;
  align-items: center;
  gap: 8px;
}
.hclock-history-nav-btn {
  background: #0f172a;
  border: 1px solid #334155;
  color: #cbd5e1;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.9rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.hclock-history-nav-btn:hover:not(:disabled) {
  background: #1e293b;
  border-color: #475569;
}
.hclock-history-nav-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.hclock-history-label {
  font-size: 0.86rem;
  font-weight: 600;
  color: #cbd5e1;
  min-width: 180px;
  text-align: center;
}
.hclock-history-body { min-height: 80px; }
.hclock-history-summary {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  padding: 10px 12px;
  background: #0f172a;
  border: 1px solid #1e293b;
  border-radius: 10px;
  margin-bottom: 12px;
}
.hclock-history-num-big {
  font-size: 1.4rem;
  font-weight: 800;
  color: #60a5fa;
}
.hclock-history-label-sm {
  font-size: 0.78rem;
  color: #94a3b8;
  margin-left: 4px;
}
.hclock-history-num { text-align: right; font-variant-numeric: tabular-nums; }
.hclock-history-loading,
.hclock-history-error,
.hclock-history-empty {
  text-align: center;
  font-size: 0.84rem;
  color: #64748b;
  padding: 18px 0;
}
.hclock-history-error { color: #f87171; }

/* TikTok template status badge */
.tiktok-badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 8px;
  white-space: nowrap;
}
.tiktok-badge-ok {
  background: rgba(74,222,128,0.15);
  color: #4ade80;
  border: 1px solid #4ade80;
}
.tiktok-badge-warn {
  background: rgba(250,204,21,0.15);
  color: #facc15;
  border: 1px solid #facc15;
}

/* ── Analytics tabs ───────────────────────────────────────────────────── */
.analytics-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 12px;
}
.analytics-tab {
  padding: 6px 16px;
  border-radius: 6px 6px 0 0;
  border: 1px solid #334155;
  border-bottom: none;
  background: #0f172a;
  color: #94a3b8;
  font-weight: 600;
  cursor: pointer;
  font-size: 0.82rem;
}
.analytics-tab.active {
  background: #1e293b;
  color: #dbeafe;
  border-color: #60a5fa;
}

/* ── Assignment generator health & tolerance ──────────────────────────── */
.ag-health-card {
  background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
  border: 1px solid #334155;
  border-radius: 10px;
  padding: 14px 18px;
  margin-bottom: 14px;
}
.ag-health-grid {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
}
.ag-health-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.ag-health-num {
  font-size: 1.5rem;
  font-weight: 800;
  color: #60a5fa;
}
.ag-health-label {
  font-size: 0.78rem;
  color: #94a3b8;
}
.ag-health-low {
  margin-top: 10px;
  color: #fbbf24;
  font-size: 0.82rem;
}
.ag-health-low summary { cursor: pointer; font-weight: 600; }
.ag-health-table {
  width: 100%;
  margin-top: 6px;
  border-collapse: collapse;
  font-size: 0.78rem;
  color: #cbd5e1;
}
.ag-health-table th { text-align: left; color: #94a3b8; padding: 3px 6px; border-bottom: 1px solid #334155; }
.ag-health-table td { padding: 3px 6px; }

.ag-tolerance-warning {
  background: #7f1d1d;
  color: #fca5a5;
  border: 1px solid #dc2626;
  border-radius: 6px;
  padding: 8px 12px;
  margin-bottom: 8px;
  font-weight: 700;
  font-size: 0.88rem;
}
/* ── Catalog / Hours collapse toggles ───────────────────────────────────────── */
/* When a collapsible .editor section is collapsed, strip the card look so the
   toggle button is the only visible element — identical to the catalog toggle. */
.editor.editor-collapsed {
  background: transparent;
  border: none;
  box-shadow: none;
  padding: 0;
  margin-top: 10px;
}

@keyframes collapseGlow {
  0%   { box-shadow: 0 0 0px 0px rgba(99,102,241,0); border-color: #334155; }
  50%  { box-shadow: 0 0 10px 2px rgba(99,102,241,0.45); border-color: #6366f1; }
  100% { box-shadow: 0 0 0px 0px rgba(99,102,241,0); border-color: #334155; }
}

.catalog-collapse-toggle { margin: 10px 0 0; }

.catalog-toggle-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  background: linear-gradient(90deg, #13111c 0%, #0f172a 100%);
  border: 1.5px solid #334155;
  border-bottom: none;
  border-radius: 10px 10px 0 0;
  padding: 13px 20px;
  color: #e2e8f0;
  font-size: 0.92rem;
  font-weight: 800;
  cursor: pointer;
  text-align: left;
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
  letter-spacing: 0.03em;
}
.catalog-toggle-btn:hover {
  background: linear-gradient(90deg, #1e1b35 0%, #1e293b 100%);
  border-color: #6366f1;
  box-shadow: 0 0 12px 2px rgba(99,102,241,0.3);
}

/* Collapsed state: strong visual signal */
.catalog-toggle-btn[aria-expanded="false"] {
  border-radius: 10px;
  border: 1.5px solid #6366f1;
  background: linear-gradient(90deg, #1a1535 0%, #0f172a 100%);
  box-shadow: 0 0 0 0 rgba(99,102,241,0);
  animation: collapseGlow 2.5s ease-in-out infinite;
}
.catalog-toggle-btn[aria-expanded="false"]:hover {
  animation: none;
  box-shadow: 0 0 16px 4px rgba(99,102,241,0.5);
}

.catalog-toggle-icon {
  font-size: 0.85rem;
  color: #818cf8;
  transition: transform 0.2s;
  flex-shrink: 0;
}
.catalog-toggle-btn[aria-expanded="false"] .catalog-toggle-icon {
  color: #a5b4fc;
}

.catalog-toggle-count {
  font-size: 0.78rem;
  color: #64748b;
  font-weight: 500;
  margin-left: 2px;
}

/* Collapse buttons that live inside an .editor panel (hours, commissions, builder, change-log) */
.hd-collapse-btn {
  border-radius: 10px 10px 0 0;
  border: 1.5px solid #334155;
  border-bottom: none;
  margin-bottom: 0;
  width: 100%;
}
.hd-collapse-btn[aria-expanded="false"] {
  border-radius: 10px;
  border: 1.5px solid #6366f1;
  background: linear-gradient(90deg, #1a1535 0%, #0f172a 100%);
  animation: collapseGlow 2.5s ease-in-out infinite;
}
.hd-collapse-btn[aria-expanded="false"]:hover {
  animation: none;
  box-shadow: 0 0 16px 4px rgba(99,102,241,0.5);
}
.hd-collapse-subtitle {
  font-weight: 500;
  /* Was #94a3b8 at 78% size — washed out next to the bold title.
     Raise contrast + add a separator bar so it reads as a secondary
     line instead of low-priority noise. */
  color: #cbd5e1;
  font-size: 0.82rem;
  letter-spacing: 0.01em;
  padding-left: 10px;
  border-left: 1px solid rgba(148, 163, 184, 0.35);
  margin-left: 6px;
}

/* Bump the headline text inside the collapse button to Manrope so the
   "Hours Dashboard" title lines up with the hero + h2 premium lift. */
.catalog-toggle-btn,
.hd-collapse-btn {
  font-family: "Manrope", "Inter", system-ui, sans-serif;
  font-size: 0.98rem;
  letter-spacing: -0.01em;
}

/* ── Analytics clickable rows ────────────────────────────────────────────── */
.analytics-row-clickable { cursor: pointer; transition: background 0.12s; }
.analytics-row-clickable:hover { background: #1e293b !important; }
.analytics-session-link { color: #818cf8; font-weight: 600; }
.analytics-detail-hint { font-size: 0.7rem; opacity: 0.6; }

/* ── Session Detail Modal ─────────────────────────────────────────────────── */
.sd-panel {
  max-width: 960px;
  width: 95vw;
  /* border-box so the 24px padding + border count INSIDE max-height.
     Content-box + 90vh let the panel bottom hang ~26-100px below the
     viewport (worse the more the display is zoomed): the last rows and
     the end of the scrollbar were unreachable — operator 2026-07-13
     "I can't scroll down, I have to zoom out". 100vh - 64px = the
     .modal's 48px top padding + 16px bottom clearance. */
  box-sizing: border-box;
  max-height: calc(100vh - 64px);
  overflow-y: auto;
  padding: 24px 28px;
}
.sd-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 14px;
  gap: 12px;
  flex-wrap: wrap;
}
.sd-title { margin: 0; font-size: 1.3rem; color: #e2e8f0; }
.sd-meta {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  font-size: 0.8rem;
  color: #94a3b8;
  margin-top: 4px;
}
.sd-status-chip {
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 8px;
  padding: 1px 8px;
  font-size: 0.7rem;
  color: #4ade80;
  font-weight: 700;
  text-transform: uppercase;
}
.sd-stat-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}
.sd-stat {
  flex: 1 1 90px;
  min-width: 85px;
  background: #0f172a;
  border: 1px solid #1e293b;
  border-radius: 10px;
  padding: 10px 12px;
  text-align: center;
}
.sd-stat-label { font-size: 0.6rem; color: #64748b; text-transform: uppercase; letter-spacing: .07em; font-weight: 700; margin-bottom: 3px; }
.sd-stat-val { font-size: 1.05rem; font-weight: 900; color: #e2e8f0; }
.sd-val-gmv { color: #4ade80; }
.sd-stat-profit .sd-stat-val { color: #4ade80; }
.sd-stat-loss .sd-stat-val { color: #f87171; }
.sd-comm-strip {
  display: flex;
  align-items: center;
  gap: 14px;
  background: #1e1433;
  border: 1px solid #a78bfa44;
  border-radius: 10px;
  padding: 10px 16px;
  margin-bottom: 12px;
  font-size: 0.88rem;
  color: #c4b5fd;
  font-weight: 600;
}
.sd-comm-amount { font-size: 1.1rem; font-weight: 900; color: #a78bfa; }
.sd-notes {
  background: #1e293b;
  border-left: 3px solid #4f46e5;
  padding: 8px 14px;
  border-radius: 0 8px 8px 0;
  font-size: 0.82rem;
  color: #94a3b8;
  margin-bottom: 12px;
}
.sd-section-title {
  font-size: 0.75rem;
  font-weight: 700;
  color: #94a3b8;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 6px;
}
.sd-table { font-size: 0.8rem; }

/* ── Commission UI ──────────────────────────────────────────────────────── */
.comm-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 12px;
  flex-wrap: wrap;
  gap: 8px;
}
.comm-title { margin: 0 0 2px; color: #a78bfa; }
.comm-subtitle { margin: 0; }

/* Summary chips per worker */
.comm-worker-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 20px;
  padding: 4px 14px;
  font-size: 0.8rem;
}
.comm-worker-name { font-weight: 700; color: #e2e8f0; }
.comm-worker-earned { color: #a78bfa; }
.comm-worker-owed { color: #94a3b8; }
.comm-owed-positive { color: #f87171; font-weight: 700; }

/* Table row states */
.comm-row-paid td { opacity: 0.6; }
.comm-row-owed td { opacity: 1; }
.comm-amount { font-weight: 700; color: #a78bfa; }

/* Badges */
.comm-badge-paid {
  display: inline-block;
  background: rgba(74,222,128,0.15);
  color: #4ade80;
  border: 1px solid #4ade80;
  border-radius: 10px;
  padding: 1px 8px;
  font-size: 0.72rem;
  font-weight: 700;
}
.comm-badge-owed {
  display: inline-block;
  background: rgba(248,113,113,0.15);
  color: #f87171;
  border: 1px solid #f87171;
  border-radius: 10px;
  padding: 1px 8px;
  font-size: 0.72rem;
  font-weight: 700;
}

/* Streamer: My Commission section */
/* Auto-logout countdown banner — shown after End Stream click.
   Pinned to the top-right so it's visible regardless of scroll
   position but doesn't cover the main UI. Fade-out at logout
   moment for a soft visual handoff. */
.auto-logout-banner {
  position: fixed;
  top: 16px; right: 16px;
  z-index: 9999;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 12px 18px;
  border-radius: 12px;
  background: linear-gradient(135deg, rgba(127, 29, 29, 0.95), rgba(69, 10, 10, 0.95));
  border: 1px solid rgba(248, 113, 113, 0.5);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(248, 113, 113, 0.18);
  color: #fef2f2;
  font-family: "Bebas Neue", "Manrope", system-ui, sans-serif;
  letter-spacing: 0.04em;
  pointer-events: none;
  animation: autoLogoutPulse 2.4s ease-in-out infinite;
  transition: opacity 0.6s ease;
}
@keyframes autoLogoutPulse {
  0%, 100% { box-shadow: 0 12px 36px rgba(0, 0, 0, 0.55), 0 0 0 0 rgba(248, 113, 113, 0.5); }
  50%      { box-shadow: 0 12px 36px rgba(0, 0, 0, 0.55), 0 0 0 8px rgba(248, 113, 113, 0); }
}
.auto-logout-banner-fading { opacity: 0.5; animation: none; }
.auto-logout-icon { font-size: 1.4rem; flex: 0 0 auto; }
.auto-logout-text { display: flex; flex-direction: column; gap: 2px; }
.auto-logout-clock { font-size: 1.2rem; color: #fee2e2; font-variant-numeric: tabular-nums; }
.auto-logout-sub { font-size: 0.7rem; color: #fca5a5; letter-spacing: 0.06em; text-transform: uppercase; }

/* End-Stream success banner — pinned top-center so the streamer
   actually SEES that End Stream worked, instead of squinting at the
   bottom status bar. Sits alongside the auto-logout banner (top-right),
   not on top of it. Auto-fades after a few seconds — purely a confirm,
   not actionable. */
.end-stream-confirm-banner {
  position: fixed;
  top: 16px; left: 50%;
  transform: translateX(-50%);
  z-index: 9998;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 14px 22px;
  border-radius: 12px;
  background: linear-gradient(135deg, rgba(20, 83, 45, 0.96), rgba(6, 78, 59, 0.96));
  border: 1px solid rgba(74, 222, 128, 0.55);
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(74, 222, 128, 0.22);
  color: #ecfdf5;
  font-family: "Bebas Neue", "Manrope", system-ui, sans-serif;
  letter-spacing: 0.04em;
  pointer-events: none;
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.end-stream-confirm-banner-fading { opacity: 0; transform: translateX(-50%) translateY(-12px); }
.end-stream-confirm-icon { font-size: 1.5rem; flex: 0 0 auto; }
.end-stream-confirm-text { display: flex; flex-direction: column; gap: 2px; }
.end-stream-confirm-title { font-size: 1.05rem; color: #d1fae5; }
.end-stream-confirm-sub { font-size: 0.72rem; color: #86efac; letter-spacing: 0.06em; text-transform: uppercase; }

/* My Stats — period picker. Sits at the top of the streamer's stats
   panel so they can drill into a specific month / quarter / YTD
   instead of always seeing all-time aggregates. The native <input
   type="month"> is the fine-grained control; the quick-pick buttons
   are common-case shortcuts. The display span echoes the resolved
   period back so the streamer can confirm what they're looking at. */
.my-stats-period {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 10px 12px;
  background: linear-gradient(180deg, rgba(30, 41, 59, 0.7), rgba(15, 23, 42, 0.85));
  border: 1px solid rgba(148, 163, 184, 0.2);
  border-radius: 10px;
  margin: 8px 0 14px;
}
.my-stats-period-label {
  font-family: "Bebas Neue", "Manrope", system-ui, sans-serif;
  font-size: 0.95rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #cbd5e1;
}
.my-stats-month {
  background: #0f172a;
  color: #e2e8f0;
  border: 1px solid #334155;
  border-radius: 6px;
  padding: 5px 10px;
  font-size: 0.85rem;
  font-family: inherit;
  color-scheme: dark;
}
.my-stats-quickpicks { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.my-stats-qp {
  background: #1e293b;
  color: #cbd5e1;
  border: 1px solid #334155;
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.12s, color 0.12s, border-color 0.12s;
}
.my-stats-qp:hover { background: #334155; color: #f1f5f9; }
.my-stats-qp.active {
  background: linear-gradient(135deg, #4f46e5, #6366f1);
  color: #fff;
  border-color: transparent;
}
.my-stats-period-display {
  margin-left: auto;
  font-family: "Bebas Neue", "Manrope", system-ui, sans-serif;
  font-size: 0.92rem;
  letter-spacing: 0.08em;
  color: #fbbf24;
  text-shadow: 0 1px 4px rgba(251, 191, 36, 0.15);
}
.my-stats-scope-hint {
  font-size: 0.72rem;
  color: #64748b;
  font-weight: 400;
  letter-spacing: 0.04em;
  margin-left: 6px;
}

/* My Stats — side-by-side period comparison table (week / month /
   year / all-time). Lets streamers see trends at a glance instead
   of having to flip the picker between periods. */
.my-stats-compare {
  margin: 8px 0 14px;
  overflow-x: auto;
}
.my-stats-compare table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
  background: linear-gradient(180deg, rgba(30, 41, 59, 0.45), rgba(15, 23, 42, 0.6));
  border: 1px solid rgba(148, 163, 184, 0.18);
  border-radius: 10px;
  overflow: hidden;
}
.my-stats-compare th,
.my-stats-compare td {
  padding: 8px 12px;
  text-align: right;
  border-bottom: 1px solid rgba(51, 65, 85, 0.4);
}
.my-stats-compare th:first-child,
.my-stats-compare td:first-child {
  text-align: left;
  color: #94a3b8;
  font-weight: 600;
  font-family: "Bebas Neue", "Manrope", system-ui, sans-serif;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 0.78rem;
}
.my-stats-compare thead th {
  font-family: "Bebas Neue", "Manrope", system-ui, sans-serif;
  font-size: 0.82rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #cbd5e1;
  background: rgba(15, 23, 42, 0.6);
}
.my-stats-compare tbody td {
  color: #e2e8f0;
  font-variant-numeric: tabular-nums;
}
.my-stats-compare tbody tr:hover { background: rgba(99, 102, 241, 0.08); }
.my-stats-compare tbody tr:last-child td { border-bottom: 0; }
.my-stats-compare-num { font-weight: 700; }
.my-stats-compare-money { color: #86efac; }
.my-stats-compare-earn { color: #fbbf24; }

.commission-streamer-summary { margin: 8px 0; }
.comm-my-chips {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}
.comm-my-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  background: #1e293b;
  border: 1px solid #334155;
  border-radius: 10px;
  padding: 10px 20px;
  min-width: 100px;
}
.comm-chip-num { font-size: 1.3rem; font-weight: 900; color: #a78bfa; }
.comm-chip-label { font-size: 0.72rem; color: #94a3b8; margin-top: 2px; }
.comm-chip-paid .comm-chip-num { color: #4ade80; }
.comm-chip-owed .comm-chip-num { color: #f87171; }

.comm-history-table { width: 100%; border-collapse: collapse; font-size: 0.82rem; margin-top: 8px; }
.comm-history-table th { text-align: left; color: #94a3b8; padding: 4px 8px; border-bottom: 1px solid #334155; }
.comm-history-table td { padding: 4px 8px; border-bottom: 1px solid #1e293b; }

/* ─── Commission Payment Modal ───────────────────────────────────────── */
.comm-pay-panel {
  max-width: 440px;
  padding: 28px 32px;
}
.comm-pay-title {
  font-size: 1.15rem;
  font-weight: 800;
  color: #a78bfa;
  margin: 0 0 12px;
}
.comm-pay-summary {
  background: rgba(167,139,250,0.1);
  border: 1px solid rgba(167,139,250,0.3);
  border-radius: 8px;
  padding: 8px 12px;
  color: #c4b5fd;
  font-size: 0.85rem;
  margin-bottom: 16px;
}
.comm-pay-select,
.comm-pay-input {
  width: 100%;
  padding: 8px 10px;
  background: #1c1c2e;
  border: 1px solid #3a3a5c;
  border-radius: 6px;
  color: #e2e8f0;
  font-size: 0.88rem;
}
.comm-pay-select:focus,
.comm-pay-input:focus {
  outline: none;
  border-color: #a78bfa;
}
.required-star { color: #f87171; }

/* Payment method chip in table */
.comm-pay-method-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: rgba(167,139,250,0.12);
  color: #c4b5fd;
  border: 1px solid rgba(167,139,250,0.3);
  border-radius: 8px;
  padding: 1px 7px;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}
.comm-pay-ref {
  color: #94a3b8;
  font-weight: 400;
}

/* Payment Log panel */
.comm-pay-log-section {
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid #2e2e4a;
}
.comm-pay-log-title {
  font-size: 0.95rem;
  font-weight: 700;
  color: #a78bfa;
  margin: 0 0 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.comm-pay-log-table th {
  font-size: 0.72rem;
  background: rgba(167,139,250,0.07);
  color: #a78bfa;
}

/* ─────────────────────────────────────────────────────────────────────── */

/* ─── Barcode scanner UI ─────────────────────────────────────────────── */
#scanBadge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  background: linear-gradient(90deg, rgba(74,222,128,0.18), rgba(34,197,94,0.12));
  border: 1px solid rgba(74,222,128,0.55);
  color: #bbf7d0;
  margin-left: 8px;
  cursor: pointer;
  user-select: none;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
#scanBadge.off {
  background: rgba(71,85,105,0.25);
  border-color: rgba(148,163,184,0.35);
  color: #94a3b8;
}
#scanBadge.active {
  box-shadow: 0 0 0 2px rgba(74,222,128,0.25), 0 0 16px rgba(74,222,128,0.35);
}
#scanBadge .scan-badge-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #22c55e;
  box-shadow: 0 0 6px rgba(34,197,94,0.7);
}
#scanBadge.off .scan-badge-dot { background: #64748b; box-shadow: none; }
#scanBadge .scan-badge-ctx { text-transform: uppercase; }
#scanBadge .scan-badge-last {
  font-weight: 500;
  color: rgba(240,253,244,0.85);
  font-size: 0.78rem;
  margin-left: 6px;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@keyframes gg-scan-row-flash {
  0%   { background: rgba(74,222,128,0.45); }
  60%  { background: rgba(74,222,128,0.15); }
  100% { background: transparent; }
}
tr.scan-flash {
  animation: gg-scan-row-flash 1.1s ease-out;
}

/* Scanner panel: renders as a popover floating near the Scan badge, not an inline section. */
#scannerPanel {
  position: fixed;
  top: 68px;
  right: 20px;
  width: min(92vw, 520px);
  max-height: min(78vh, 560px);
  overflow-y: auto;
  z-index: 9500;
  background: rgba(15, 23, 42, 0.98);
  border: 1px solid rgba(74, 222, 128, 0.55);
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6), 0 0 0 4px rgba(74, 222, 128, 0.08);
  border-radius: 12px;
  padding: 16px 18px;
  animation: gg-scan-pop 0.14s ease-out;
}
@keyframes gg-scan-pop {
  from { opacity: 0; transform: translateY(-6px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
#scannerPanel .scan-mode-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin: 10px 0;
}
#scannerPanel .scan-mode-chip {
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid rgba(148,163,184,0.35);
  background: rgba(30,41,59,0.6);
  color: #cbd5e1;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.85rem;
  transition: all 0.15s ease;
}
#scannerPanel .scan-mode-chip:hover {
  border-color: rgba(74,222,128,0.6);
  color: #bbf7d0;
}
#scannerPanel .scan-mode-chip.active {
  background: linear-gradient(90deg, rgba(74,222,128,0.22), rgba(34,197,94,0.14));
  border-color: rgba(74,222,128,0.7);
  color: #bbf7d0;
  box-shadow: 0 0 0 2px rgba(74,222,128,0.2);
}
#scanReceivingLog {
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid rgba(148,163,184,0.18);
  border-radius: 8px;
  padding: 8px 12px;
  background: rgba(15,23,42,0.4);
  font-family: ui-monospace, "Cascadia Mono", Menlo, monospace;
  font-size: 0.82rem;
}
#scanReceivingLog .scan-log-row {
  padding: 4px 0;
  border-bottom: 1px dashed rgba(148,163,184,0.12);
  color: #cbd5e1;
  display: flex;
  gap: 10px;
}
#scanReceivingLog .scan-log-row:last-child { border-bottom: none; }
#scanReceivingLog .scan-log-row.err { color: #fca5a5; }
#scanReceivingLog .scan-log-row .scan-log-time { color: #94a3b8; min-width: 70px; }
#scanReceivingLog .scan-log-row .scan-log-pid { color: #a78bfa; min-width: 70px; }

/* Link-UPC modal specifics */
#linkUpcModal .modal-panel { max-width: 560px; }
#linkUpcModal .link-upc-code {
  font-family: ui-monospace, "Cascadia Mono", Menlo, monospace;
  font-size: 1.25rem;
  padding: 8px 12px;
  background: rgba(15,23,42,0.6);
  border: 1px solid rgba(148,163,184,0.25);
  border-radius: 6px;
  letter-spacing: 0.05em;
}
#linkUpcSearchResults {
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid rgba(148,163,184,0.15);
  border-radius: 6px;
  margin-top: 8px;
}
#linkUpcSearchResults .link-upc-result {
  padding: 8px 12px;
  cursor: pointer;
  border-bottom: 1px solid rgba(148,163,184,0.1);
  display: flex;
  align-items: center;
  gap: 10px;
}
.link-upc-thumb {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid #4b5563;
  background: #0b1220;
  flex-shrink: 0;
}
.link-upc-thumb--empty {
  display: inline-block;
}
.link-upc-info {
  min-width: 0;
}
#linkUpcSearchResults .link-upc-result:hover { background: rgba(74,222,128,0.08); }
#linkUpcSearchResults .link-upc-result.selected { background: rgba(74,222,128,0.18); }

/* Scan picker modal (shared-UPC disambiguation) */
.scan-picker-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 60vh;
  overflow-y: auto;
  margin: 12px 0;
}
.scan-picker-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid #374151;
  border-radius: 6px;
  background: #0b1220;
  color: inherit;
  cursor: pointer;
  text-align: left;
}
.scan-picker-row:hover { background: rgba(74,222,128,0.10); border-color: #4ade80; }
.scan-picker-thumb {
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 4px;
  border: 1px solid #4b5563;
  background: #0b1220;
  flex-shrink: 0;
}
.scan-picker-thumb--empty { display: inline-block; }
.scan-picker-meta { min-width: 0; flex: 1; }
.scan-picker-name { font-weight: 600; font-size: 0.95rem; }
.scan-picker-sub { font-size: 0.8rem; color: #94a3b8; margin-top: 2px; }

/* Link-UPC modal — section headers separate local catalog matches from
   TCGPlayer "add new" suggestions so the user knows what each row does. */
.link-upc-section-label {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #93c5fd;
  margin: 10px 0 4px;
  padding: 4px 8px;
  border-left: 3px solid #3b82f6;
  background: rgba(59, 130, 246, 0.08);
}
.link-upc-result.link-upc-tcg {
  border-left: 3px solid #b45309;
}
.link-upc-tcg-qty-label {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.75rem;
  color: #cbd5e1;
  white-space: nowrap;
}
.link-upc-tcg-qty-label span {
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.link-upc-tcg-qty {
  width: 60px;
  padding: 3px 6px;
  font-size: 0.85rem;
  text-align: center;
}
.link-upc-tcg-add {
  font-size: 0.8rem;
  padding: 4px 10px;
  white-space: nowrap;
}

/* Inline confirm form — expands in place of the Add+Link button, showing
   the pre-filled dimensions from /api/products/suggest-dimensions. */
.link-upc-confirm {
  flex: 1 1 100%;
  margin-top: 8px;
  padding: 10px 12px;
  background: rgba(180, 83, 9, 0.08);
  border: 1px solid rgba(180, 83, 9, 0.3);
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.link-upc-confirm-note {
  font-size: 0.8rem;
  color: #fcd34d;
  line-height: 1.4;
}
.link-upc-confirm-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 6px;
}
.link-upc-confirm-fields label {
  display: flex;
  flex-direction: column;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #94a3b8;
  gap: 2px;
}
.link-upc-confirm-fields input {
  padding: 4px 8px;
  font-size: 0.9rem;
  font-weight: normal;
  letter-spacing: normal;
  text-transform: none;
  color: #f1f5f9;
}
.link-upc-confirm-actions {
  display: flex;
  gap: 8px;
}
.link-upc-confirm-ok {
  background: #059669;
  color: white;
  font-weight: 600;
}

/* TCG link search — region badge (e.g. "Japan", "Korean") on non-English
   results so they're visually distinct when linking. */
.tcg-region-badge {
  display: inline-block;
  padding: 1px 6px;
  margin-left: 4px;
  border-radius: 4px;
  font-size: 0.7rem;
  font-weight: 600;
  background: #b45309;
  color: #fff7ed;
  vertical-align: middle;
  letter-spacing: 0.02em;
}

/* Orders launcher — premium gold gradient pill to stand apart from other chrome. */
.launcher-premium {
  font-family: var(--font-fancy);
  font-style: italic;
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.03em;
  color: #1a1207;
  background: linear-gradient(135deg, #f5c451 0%, #d4a017 50%, #b5850b 100%);
  border: 1px solid #a67c04;
  border-radius: 999px;
  padding: 6px 18px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.35);
  cursor: pointer;
  transition: filter 0.15s ease, transform 0.05s ease, box-shadow 0.15s ease;
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
}
.launcher-premium:hover:not(:disabled) {
  filter: brightness(1.08);
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.4);
}
.launcher-premium:active:not(:disabled) {
  transform: translateY(1px);
  filter: brightness(0.96);
}
.launcher-premium:focus-visible {
  outline: 2px solid #f5c451;
  outline-offset: 2px;
}

/* ═══════════════════════════════════════════════════════════════════
   Streamer Room Scheduler — premium trainer-card aesthetic
   Per-room colors mirror Pokémon energy types so each room reads as
   its own "type" the audience already groks. Avatars are the focal
   point at 64px (cells) / 96px (modal) / 48px (persistent card).
   ═══════════════════════════════════════════════════════════════════ */
:root {
  --room-ebay-main-bg:    linear-gradient(135deg, #1e40af 0%, #3b82f6 100%);
  --room-ebay-main-solid: #3b82f6;
  --room-ebay-main-glow:  0 0 20px rgba(59, 130, 246, 0.45);

  --room-sports-bg:       linear-gradient(135deg, #166534 0%, #22c55e 100%);
  --room-sports-solid:    #22c55e;
  --room-sports-glow:     0 0 20px rgba(34, 197, 94, 0.45);

  --room-tiktok-tcg-bg:   linear-gradient(135deg, #be185d 0%, #ec4899 100%);
  --room-tiktok-tcg-solid:#ec4899;
  --room-tiktok-tcg-glow: 0 0 20px rgba(236, 72, 153, 0.45);

  --room-tiktok-evo-bg:   linear-gradient(135deg, #7e22ce 0%, #a855f7 100%);
  --room-tiktok-evo-solid:#a855f7;
  --room-tiktok-evo-glow: 0 0 20px rgba(168, 85, 247, 0.45);

  --room-ebay-back-bg:    linear-gradient(135deg, #475569 0%, #94a3b8 100%);
  --room-ebay-back-solid: #94a3b8;
  --room-ebay-back-glow:  0 0 20px rgba(148, 163, 184, 0.40);
}

.scheduler-panel { padding: 18px 20px; }
.scheduler-head {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 14px;
  margin-bottom: 14px;
}
.scheduler-week-nav {
  display: inline-flex; align-items: center; gap: 12px;
  background: linear-gradient(180deg, #0f172a, #1e293b);
  border: 1px solid #334155;
  border-radius: 12px;
  padding: 8px 14px;
  font-family: "Bebas Neue", "Manrope", system-ui, sans-serif;
  font-size: 1.05rem;
  letter-spacing: 0.04em;
}
.scheduler-week-nav button {
  background: transparent; border: 0; color: #cbd5e1; cursor: pointer;
  font-size: 1.2rem; padding: 0 6px;
}
.scheduler-week-nav button:hover { color: #f5c451; }
.scheduler-mode-toggle {
  display: inline-flex; gap: 0;
  background: rgba(15, 23, 42, 0.5);
  border: 1px solid #334155;
  border-radius: 999px;
  padding: 4px;
}
.scheduler-mode-toggle button {
  background: transparent; border: 0; color: #94a3b8;
  padding: 6px 14px; cursor: pointer;
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em;
  border-radius: 999px;
  transition: background 0.18s, color 0.18s;
}
.scheduler-mode-toggle button.active {
  background: linear-gradient(135deg, #4f46e5, #6366f1);
  color: #fff;
  box-shadow: 0 4px 12px rgba(99, 102, 241, 0.4);
}
/* Edit-mode toggle gets distinct active colors so the operator can see
 * at a glance which mode they're in — and what the consequence is.
 * Orange = "This week only" (treat as a warning that changes here
 * don't persist). Green = "Recurring" (success, the change repeats
 * every week). The matching banner below the grid uses the same
 * color family for instant reinforcement. Reported 2026-05-22:
 * operator set shifts thinking they were recurring but was actually
 * in override mode; the changes "disappeared" next week. */
.scheduler-mode-toggle--main button.mode-override.active {
  background: linear-gradient(135deg, #ea580c, #f97316);
  box-shadow: 0 4px 12px rgba(249, 115, 22, 0.4);
}
.scheduler-mode-toggle--main button.mode-template.active {
  background: linear-gradient(135deg, #15803d, #22c55e);
  box-shadow: 0 4px 12px rgba(34, 197, 94, 0.4);
}

/* Mode-explainer banner. Sits between the toolbar row and the grid.
 * Spells out in plain language what each mode does so the operator
 * never has to guess. JS swaps the class + text on toggle click. */
.scheduler-mode-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 14px;
  margin: 10px 0;
  border-radius: 8px;
  font-size: 0.85rem;
  line-height: 1.45;
  border: 1px solid;
}
.scheduler-mode-banner strong { font-weight: 700; }
.scheduler-mode-banner--override {
  background: rgba(249, 115, 22, 0.10);
  border-color: rgba(249, 115, 22, 0.45);
  color: #fde7cf;
}
.scheduler-mode-banner--template {
  background: rgba(34, 197, 94, 0.10);
  border-color: rgba(34, 197, 94, 0.45);
  color: #d6f7e0;
}

.scheduler-grid {
  display: grid;
  /* Default: rooms-rows orientation = 1 corner + 7 day columns. */
  grid-template-columns: 140px repeat(7, minmax(140px, 1fr));
  gap: 8px;
  background: rgba(15, 23, 42, 0.4);
  border: 1px solid #1e293b;
  border-radius: 14px;
  padding: 12px;
  overflow-x: auto;
}
/* Days-rows orientation: 1 corner + N room columns. The number of
   columns adapts to the SCHED_ROOMS list — currently 5 rooms in
   production, so 6 cols total. Using auto-fit with minmax so it
   responds gracefully if a room is ever added or removed. */
.scheduler-grid[data-orientation="days-rows"] {
  grid-template-columns: 110px repeat(5, minmax(160px, 1fr));
}
/* Day-label cell when it sits in the LEFT column (days-rows mode). */
.scheduler-day-header.is-row {
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: left;
  border-bottom: none;
  border-right: 2px solid rgba(148, 163, 184, 0.18);
  padding: 16px 12px;
}
.scheduler-day-header.is-row.is-today::after {
  display: none; /* the underline animation doesn't fit a left-side label */
}
.scheduler-day-header.is-row.is-today {
  border-right-color: #fbbf24;
  box-shadow: inset 4px 0 0 #fbbf24;
}
/* Room label when it sits as a TOP-row header (days-rows mode). */
.scheduler-room-label.is-header {
  justify-content: center;
  text-align: center;
  border-left: none;
  border-bottom: 4px solid var(--room-color, #94a3b8);
  border-radius: 10px 10px 0 0;
  padding: 10px;
}
.scheduler-day-header {
  font-family: "Bebas Neue", "Manrope", sans-serif;
  font-size: 1rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: #cbd5e1;
  text-align: center;
  padding: 10px 4px 8px;
  border-bottom: 2px solid rgba(148, 163, 184, 0.18);
  position: relative;
}
.scheduler-day-header.is-today { color: #fbbf24; text-shadow: 0 0 14px rgba(251, 191, 36, 0.55); }
.scheduler-day-header.is-today::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px;
  background: linear-gradient(90deg, transparent, #fbbf24, transparent);
}
.scheduler-day-header .dh-date { display: block; font-size: 0.72rem; color: #64748b; letter-spacing: 0.06em; margin-top: 2px; }

.scheduler-room-label {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 10px;
  border-radius: 10px;
  background: rgba(15, 23, 42, 0.7);
  border-left: 4px solid var(--room-color, #94a3b8);
  font-family: "Bangers", "Bebas Neue", system-ui, sans-serif;
  font-size: 1.15rem;
  letter-spacing: 0.08em;
  color: #f1f5f9;
}
.scheduler-room-label[data-room="ebay_main"]   { --room-color: var(--room-ebay-main-solid); }
.scheduler-room-label[data-room="sports"]      { --room-color: var(--room-sports-solid); }
.scheduler-room-label[data-room="tiktok_tcg"]  { --room-color: var(--room-tiktok-tcg-solid); }
.scheduler-room-label[data-room="tiktok_evo"]  { --room-color: var(--room-tiktok-evo-solid); }
.scheduler-room-label[data-room="ebay_back"]   { --room-color: var(--room-ebay-back-solid); }
.scheduler-room-label .rl-dot {
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--room-color);
  box-shadow: 0 0 10px var(--room-color);
}

.trainer-slot {
  position: relative;
  min-height: 150px;
  border-radius: 12px;
  padding: 12px 10px 10px;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  gap: 6px;
  cursor: default;
  transition: transform 0.16s ease, box-shadow 0.18s ease;
  isolation: isolate;
  overflow: hidden;
}
.trainer-slot.is-clickable { cursor: pointer; }
.trainer-slot.is-clickable:hover { transform: translateY(-2px) scale(1.02); box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45); }
.trainer-slot::before {
  content: ""; position: absolute; inset: 0;
  background: var(--slot-bg, linear-gradient(135deg, #1e293b, #334155));
  opacity: 0.92; z-index: -2;
}
.trainer-slot::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10), inset 0 0 0 1px rgba(0, 0, 0, 0.20);
  pointer-events: none; z-index: -1;
}
.trainer-slot[data-room="ebay_main"]   { --slot-bg: var(--room-ebay-main-bg);   --slot-glow: var(--room-ebay-main-glow); }
.trainer-slot[data-room="sports"]      { --slot-bg: var(--room-sports-bg);      --slot-glow: var(--room-sports-glow); }
.trainer-slot[data-room="tiktok_tcg"]  { --slot-bg: var(--room-tiktok-tcg-bg);  --slot-glow: var(--room-tiktok-tcg-glow); }
.trainer-slot[data-room="tiktok_evo"]  { --slot-bg: var(--room-tiktok-evo-bg);  --slot-glow: var(--room-tiktok-evo-glow); }
.trainer-slot[data-room="ebay_back"]   { --slot-bg: var(--room-ebay-back-bg);   --slot-glow: var(--room-ebay-back-glow); }

.trainer-slot-avatar {
  width: 64px; height: 64px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.6);
  background: rgba(0, 0, 0, 0.25);
  object-fit: cover;
  box-shadow: var(--slot-glow);
  flex-shrink: 0;
}
.trainer-slot-avatar.fallback {
  display: flex; align-items: center; justify-content: center;
  font-family: "Bebas Neue", sans-serif; font-size: 1.6rem; letter-spacing: 0.04em;
  color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.trainer-slot-name {
  font-family: "Russo One", "Manrope", system-ui, sans-serif;
  font-size: 0.85rem; font-weight: 600;
  color: #fff; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.65);
  text-align: center; max-width: 100%;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.trainer-slot-time {
  font-family: "Bebas Neue", "Manrope", sans-serif;
  font-size: 0.85rem; letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.92);
  text-align: center; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.trainer-slot.is-override { border: 2px dashed rgba(251, 191, 36, 0.7); }
.trainer-slot-edited-pill {
  position: absolute; top: 6px; right: 6px;
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.08em;
  background: rgba(251, 191, 36, 0.22); color: #fbbf24;
  padding: 2px 6px; border-radius: 999px;
  border: 1px solid rgba(251, 191, 36, 0.4);
}
.trainer-slot.is-now-live { animation: trainerSlotLivePulse 2.4s ease-in-out infinite; }
.trainer-slot-live-pill {
  position: absolute; top: 6px; left: 6px;
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.08em;
  background: rgba(34, 197, 94, 0.28); color: #4ade80;
  padding: 2px 6px; border-radius: 999px;
  border: 1px solid rgba(74, 222, 128, 0.55);
  display: inline-flex; align-items: center; gap: 4px;
}
.trainer-slot-live-pill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: #4ade80; box-shadow: 0 0 8px #4ade80; }
/* ENDED pill — sits in the same top-left slot as LIVE but greyed
   out. Used when the streamer has closed their session for that
   shift so the next streamer can see the previous slot wrapped
   cleanly. Mutually exclusive with LIVE (backend only sets
   is_session_ended when is_actually_live is false). */
.trainer-slot-ended-pill {
  position: absolute; top: 6px; left: 6px;
  font-size: 0.6rem; font-weight: 800; letter-spacing: 0.08em;
  background: rgba(100, 116, 139, 0.28); color: #cbd5e1;
  padding: 2px 6px; border-radius: 999px;
  border: 1px solid rgba(148, 163, 184, 0.45);
}
.trainer-slot.is-session-ended {
  /* Subtle dim so an ended shift doesn't compete with active ones */
  filter: saturate(0.65) brightness(0.85);
}
@keyframes trainerSlotLivePulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.4), var(--slot-glow); }
  50%      { box-shadow: 0 0 0 8px rgba(74, 222, 128, 0.0), var(--slot-glow); }
}
.trainer-slot.has-conflict { box-shadow: 0 0 0 2px rgba(248, 113, 113, 0.7), var(--slot-glow); }

.trainer-slot-open {
  min-height: 150px; border-radius: 12px;
  border: 2px dashed rgba(148, 163, 184, 0.3);
  background: repeating-linear-gradient(45deg, rgba(148, 163, 184, 0.04) 0 8px, rgba(148, 163, 184, 0.0) 8px 16px);
  display: flex; align-items: center; justify-content: center;
  font-family: "Bebas Neue", sans-serif;
  font-size: 0.9rem; letter-spacing: 0.18em;
  color: rgba(148, 163, 184, 0.5);
  cursor: default;
  transition: border-color 0.18s, color 0.18s;
}
.trainer-slot-open[data-room="ebay_main"]   { border-color: rgba(59, 130, 246, 0.4); }
.trainer-slot-open[data-room="sports"]      { border-color: rgba(34, 197, 94, 0.4); }
.trainer-slot-open[data-room="tiktok_tcg"]  { border-color: rgba(236, 72, 153, 0.4); }
.trainer-slot-open[data-room="tiktok_evo"]  { border-color: rgba(168, 85, 247, 0.4); }
.trainer-slot-open[data-room="ebay_back"]   { border-color: rgba(148, 163, 184, 0.4); }
.trainer-slot-open.is-clickable { cursor: pointer; }
.trainer-slot-open.is-clickable:hover { color: #f5c451; border-color: #f5c451; }

/* Single grid-cell wrapper. Each schedule cell — whether it's
   empty (OPEN), has 1 shift, has 3 stacked shifts, or has stacks +
   "+ Add another" — gets wrapped in exactly ONE .sched-cell div
   so the CSS grid only counts ONE child per (row, column) and
   subsequent columns stay aligned. Without this, multi-shift cells
   broke layout downstream (room labels and OPEN cells appearing in
   the wrong columns). Reported May 15: "the tabs for the rooms are
   off — this is insane." */
.sched-cell {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

/* Overnight shift badge — shows on shifts whose end_time <=
   start_time (cross-midnight). Sits in the same top-right area as
   EDITED so an overnight + edited shift still shows both. */
.trainer-slot-overnight-pill {
  position: absolute; bottom: 6px; right: 6px;
  font-size: 0.58rem; font-weight: 800; letter-spacing: 0.05em;
  background: rgba(167, 139, 250, 0.28); color: #c4b5fd;
  padding: 2px 6px; border-radius: 999px;
  border: 1px solid rgba(167, 139, 250, 0.55);
}
.trainer-slot.is-overnight {
  /* Subtle moonlit accent to reinforce that this slot bleeds into
     tomorrow. Doesn't compete with the LIVE / ENDED pulses. */
  background-image: linear-gradient(
    180deg,
    transparent 60%,
    rgba(167, 139, 250, 0.06) 100%
  );
}

/* "+ Add another" ghost target rendered below existing shifts when
   admin clicks a non-empty cell. Compact dashed pill so it doesn't
   visually outweigh the actual shift cards above it. Reported
   May 14: "how do i schedule multiple people for the same day". */
.trainer-slot-add-another {
  margin-top: 6px;
  padding: 4px 8px;
  border: 1px dashed rgba(148, 163, 184, 0.4);
  border-radius: 6px;
  font-family: "Russo One", sans-serif;
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  color: rgba(148, 163, 184, 0.75);
  text-align: center;
  background: rgba(148, 163, 184, 0.04);
  transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.trainer-slot-add-another.is-clickable { cursor: pointer; }
.trainer-slot-add-another.is-clickable:hover {
  color: #f5c451;
  border-color: #f5c451;
  background: rgba(245, 196, 81, 0.08);
}

.scheduler-edit-modal {
  background: linear-gradient(180deg, #0f172a, #1e293b);
  border: 1px solid #334155;
  border-radius: 18px;
  padding: 26px 28px;
  color: #f1f5f9;
  min-width: 380px; max-width: 480px;
}
.scheduler-edit-modal h3 {
  font-family: "Bangers", sans-serif;
  font-size: 1.5rem; letter-spacing: 0.06em;
  margin-bottom: 14px; color: #fbbf24;
}
.scheduler-edit-modal label {
  display: block; font-size: 0.7rem; font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: #94a3b8;
  margin: 12px 0 4px;
}
.scheduler-edit-modal input,
.scheduler-edit-modal select {
  width: 100%; padding: 9px 12px;
  background: rgba(15, 23, 42, 0.6);
  border: 1px solid #334155; border-radius: 8px;
  color: #f1f5f9; font-family: inherit; font-size: 0.9rem;
}
.scheduler-edit-modal .modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; }
.scheduler-edit-modal .modal-actions button {
  padding: 8px 16px; border-radius: 8px; font-weight: 700; font-size: 0.82rem;
  border: 1px solid #334155; background: #1e293b; color: #cbd5e1; cursor: pointer;
}
.scheduler-edit-modal .modal-actions button.primary {
  background: linear-gradient(135deg, #4f46e5, #6366f1);
  color: #fff; border-color: transparent;
}
.scheduler-edit-modal .modal-actions button.danger {
  background: rgba(248, 113, 113, 0.18); color: #fca5a5;
  border-color: rgba(248, 113, 113, 0.4);
}

/* The <dialog> element must be dark IN ITS OWN RIGHT. The inner card's
   gradient used to receive a box-shadow string in its color slot
   (--popup-room-color got the room GLOW), which invalidated the whole
   background — and the browser's default WHITE dialog was what streamers
   saw at login (Aug 2026: "SO BRIGHT"). Dialog + backdrop stay dark even
   if a per-room variable ever goes invalid again. */
/* Inline SVG icons on the stream control buttons (replaced the old
   emoji glyphs Aug 2026). currentColor inherits the button text color. */
.sb-ico {
  vertical-align: -2px;
  margin-right: 7px;
}

dialog.streamer-popup-dialog {
  background: #0f172a;
  border: none;
  border-radius: 22px;
  padding: 0;
}
dialog.streamer-popup-dialog::backdrop {
  background: rgba(2, 6, 23, 0.72);
}
.streamer-popup {
  background:
    radial-gradient(ellipse at top, var(--popup-room-tint, rgba(99, 102, 241, 0.25)) 0%, rgba(15, 23, 42, 0.95) 65%),
    linear-gradient(180deg, #0f172a, #1e293b);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 22px; padding: 32px 36px;
  color: #f1f5f9;
  min-width: 420px; max-width: 540px;
  position: relative; backdrop-filter: blur(8px);
}
.streamer-popup-date {
  font-family: "Bebas Neue", sans-serif;
  font-size: 0.95rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: #94a3b8; text-align: center;
  position: relative; margin-bottom: 18px;
}
.streamer-popup-date::before, .streamer-popup-date::after { content: "╲╲╲"; opacity: 0.35; margin: 0 8px; }
.streamer-popup-avatar {
  width: 96px; height: 96px;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.7);
  margin: 0 auto; display: block;
  object-fit: cover;
  box-shadow: var(--popup-glow, 0 0 30px rgba(99, 102, 241, 0.5));
  animation: popupAvatarBob 2.4s ease-in-out infinite;
}
.streamer-popup-avatar.fallback {
  display: flex; align-items: center; justify-content: center;
  font-family: "Bebas Neue", sans-serif; font-size: 2.4rem;
  background: rgba(0, 0, 0, 0.3); color: #fff;
}
@keyframes popupAvatarBob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-4px); }
}
.streamer-popup-name {
  font-family: "Bangers", sans-serif;
  font-size: 2rem; letter-spacing: 0.06em;
  text-align: center; color: #fff;
  margin: 16px 0 4px;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.7);
}
.streamer-popup-name-rule {
  width: 80px; height: 2px;
  background: linear-gradient(90deg, transparent, #fbbf24, transparent);
  margin: 0 auto 18px;
}
.streamer-popup-assignment { text-align: center; margin: 14px 0 10px; }
.streamer-popup-assignment .label {
  font-family: "Russo One", sans-serif;
  font-size: 0.82rem; letter-spacing: 0.16em;
  color: #94a3b8; display: block; margin-bottom: 6px;
}
.streamer-popup-room-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 16px; border-radius: 999px;
  background: var(--popup-room-bg, linear-gradient(135deg, #4f46e5, #6366f1));
  font-family: "Russo One", sans-serif;
  font-size: 0.95rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: #fff; box-shadow: var(--popup-room-glow, 0 0 18px rgba(99, 102, 241, 0.45));
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}
.streamer-popup-room-pill .dot { width: 8px; height: 8px; border-radius: 50%; background: #fff; }
.streamer-popup-time {
  font-family: "Bebas Neue", sans-serif;
  font-size: 2rem; letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  text-align: center; margin-top: 8px; color: #fff;
}
.streamer-popup-time .arrow { color: #fbbf24; margin: 0 12px; }
.streamer-popup-time .next-day { font-size: 0.6em; color: #94a3b8; margin-left: 6px; }
.streamer-popup-section-rule {
  display: flex; align-items: center; gap: 10px;
  margin: 20px 0 12px;
  font-family: "Russo One", sans-serif;
  font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: #64748b;
}
.streamer-popup-section-rule::before, .streamer-popup-section-rule::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(148, 163, 184, 0.3), transparent);
}
.streamer-popup-week-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
.streamer-popup-week-row {
  display: grid; grid-template-columns: 60px 1fr auto;
  align-items: center; gap: 10px;
  padding: 6px 10px; border-radius: 8px; font-size: 0.85rem;
}
.streamer-popup-week-row.is-today {
  background: rgba(251, 191, 36, 0.10);
  border-left: 3px solid #fbbf24; padding-left: 7px;
}
.streamer-popup-week-row .day { font-family: "Bebas Neue", sans-serif; letter-spacing: 0.1em; color: #cbd5e1; }
.streamer-popup-week-row .room-mini-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; border-radius: 999px;
  font-size: 0.72rem;
  font-family: "Russo One", sans-serif;
  letter-spacing: 0.05em;
}
.streamer-popup-week-row .time { font-family: "Bebas Neue", sans-serif; font-variant-numeric: tabular-nums; color: #cbd5e1; letter-spacing: 0.04em; }
.streamer-popup-week-row.is-off .room-mini-pill,
.streamer-popup-week-row.is-off .time { color: #475569; font-style: italic; }
.streamer-popup-week-row.is-today .today-tag {
  font-size: 0.65rem; color: #fbbf24; font-weight: 800; letter-spacing: 0.08em;
  margin-left: 6px;
}
/* Before / After me strip on the daily streamer popup. Shows who's
   handing off the room TO me and who's taking it FROM me later, so
   I have names to say hi to and clean up for. Reported May 13: "we
   need to see who is before and who is after and have reminders to
   be considerate of people after you so START ON TIME AND CLEAN UP
   AFTER YOURSELF." */
.streamer-popup-neighbors {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 14px;
  padding: 10px 6px;
}
.streamer-popup-neighbor {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: rgba(99, 102, 241, 0.06);
  border: 1px solid rgba(99, 102, 241, 0.18);
  border-radius: 10px;
  min-height: 64px;
}
.streamer-popup-neighbor.is-empty {
  background: rgba(148, 163, 184, 0.04);
  border-color: rgba(148, 163, 184, 0.12);
  justify-content: center;
}
.streamer-popup-neighbor-label {
  font-family: "Russo One", sans-serif;
  font-size: 0.6rem;
  letter-spacing: 0.15em;
  color: #94a3b8;
  text-transform: uppercase;
  position: absolute;
  margin-top: -28px;
}
.streamer-popup-neighbor-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid rgba(99, 102, 241, 0.4);
}
.streamer-popup-neighbor-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.streamer-popup-neighbor-name {
  font-family: "Russo One", sans-serif;
  font-size: 0.88rem;
  color: #e2e8f0;
  letter-spacing: 0.03em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.streamer-popup-neighbor-time {
  font-family: "Bebas Neue", sans-serif;
  font-variant-numeric: tabular-nums;
  font-size: 0.8rem;
  color: #94a3b8;
  letter-spacing: 0.04em;
}
.streamer-popup-neighbor-empty {
  font-style: italic;
  color: #64748b;
  font-size: 0.8rem;
}
.streamer-popup-neighbor-arrow {
  font-family: "Russo One", sans-serif;
  font-size: 1.4rem;
  color: #fbbf24;
  text-align: center;
}
/* Courtesy reminder banner under the neighbors strip. Loud yellow
   border + "START ON TIME" treatment so a streamer who's about to
   click "Let's go!" can't miss it. */
.streamer-popup-courtesy {
  margin-top: 14px;
  padding: 10px 14px;
  background: linear-gradient(90deg, rgba(251, 191, 36, 0.10), rgba(251, 191, 36, 0.05));
  border-left: 3px solid #fbbf24;
  border-radius: 6px;
  font-size: 0.82rem;
  color: #fef3c7;
  line-height: 1.55;
}
.streamer-popup-courtesy strong {
  color: #fbbf24;
  font-family: "Russo One", sans-serif;
  letter-spacing: 0.05em;
  font-weight: 700;
}
.streamer-popup-courtesy span:nth-of-type(2) {
  /* The "START ON TIME" middle span gets extra emphasis. */
  font-family: "Russo One", sans-serif;
  color: #fbbf24;
  letter-spacing: 0.05em;
}

/* Read-only week viewer dialog — opens when a streamer clicks their
   schedule card. Same data as the admin grid; no edit affordances.
   Reported May 13: "also they need to be able to click the calendar
   and see who is scheduled." */
.streamer-week-viewer-dialog {
  border: 1px solid #1e293b;
  border-radius: 14px;
  background: #0a0f1f;
  color: #e2e8f0;
  padding: 0;
  max-width: 1280px;
  width: 96vw;
  max-height: 92vh;
}
.streamer-week-viewer-dialog::backdrop {
  background: rgba(2, 6, 23, 0.72);
}
.streamer-week-viewer {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 22px 24px;
  max-height: 92vh;
  overflow: hidden;
}
.streamer-week-viewer-header h2 {
  margin: 0 0 10px;
  font-family: "Russo One", sans-serif;
  font-size: 1.1rem;
  letter-spacing: 0.05em;
  color: #fbbf24;
}
.streamer-week-viewer-nav {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.streamer-week-viewer-label {
  font-family: "Bebas Neue", sans-serif;
  letter-spacing: 0.08em;
  color: #cbd5e1;
  font-size: 0.95rem;
  margin-left: 8px;
}
.streamer-week-viewer-grid {
  overflow: auto;
  max-height: calc(92vh - 160px);
}
.streamer-week-viewer-loading {
  padding: 40px 20px;
  text-align: center;
  color: #94a3b8;
  font-style: italic;
}
.streamer-week-viewer-hint {
  margin: 0;
  font-size: 0.78rem;
  color: #64748b;
  font-style: italic;
}
/* Force read-only feel: kill the hover-lift on slot cards inside the
   viewer so streamers don't get the "this looks clickable" affordance
   the admin grid uses. */
.streamer-week-viewer-grid .trainer-slot.is-clickable { cursor: default; }
.streamer-week-viewer-grid .trainer-slot.is-clickable:hover {
  transform: none;
  box-shadow: none;
}
.streamer-week-viewer-grid .trainer-slot-open.is-clickable { cursor: default; }
/* Hide the + Add another affordance in the read-only streamer week
   viewer — that's an admin-edit action and shouldn't show through
   to streamers even though canEditSchedule is checked at render
   time (the renderer is shared, so a defensive CSS hide closes the
   loop in case role state drifts mid-session). */
.streamer-week-viewer-grid .trainer-slot-add-another { display: none; }

/* Clickable streamer schedule card — affordance so the user knows
   the card opens the week viewer. */
.streamer-schedule-card[role="button"]:hover {
  filter: brightness(1.08);
  transform: translateY(-1px);
  transition: transform 0.12s, filter 0.12s;
}

.streamer-popup-actions { display: flex; justify-content: center; margin-top: 22px; }
.streamer-popup-go {
  padding: 12px 32px; border-radius: 12px;
  background: linear-gradient(135deg, #4f46e5, #6366f1);
  color: #fff; border: 0;
  font-family: "Russo One", sans-serif; font-size: 0.95rem;
  letter-spacing: 0.06em; cursor: pointer;
  box-shadow: 0 8px 24px rgba(99, 102, 241, 0.45);
  transition: transform 0.12s, filter 0.18s;
}
.streamer-popup-go:hover { transform: translateY(-2px); filter: brightness(1.1); }

.streamer-schedule-card {
  display: grid; grid-template-columns: 56px 1fr auto;
  align-items: center; gap: 14px;
  background: linear-gradient(180deg, #0f172a, #1e293b);
  border: 1px solid #334155;
  border-radius: 14px;
  padding: 12px 16px 12px 14px;
  color: #f1f5f9;
  margin-bottom: 14px;
  position: relative; overflow: hidden;
}
.streamer-schedule-card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: var(--card-room-bar, linear-gradient(90deg, #4f46e5, #6366f1));
}
.streamer-schedule-card-avatar {
  width: 48px; height: 48px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.55);
  background: rgba(0, 0, 0, 0.3);
  object-fit: cover;
  box-shadow: var(--card-room-glow, 0 0 14px rgba(99, 102, 241, 0.4));
}
.streamer-schedule-card-avatar.fallback {
  display: flex; align-items: center; justify-content: center;
  font-family: "Bebas Neue", sans-serif; font-size: 1.2rem; color: #fff;
}
.streamer-schedule-card-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.streamer-schedule-card-top {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-family: "Bebas Neue", sans-serif;
  font-size: 1.1rem; letter-spacing: 0.06em; color: #fff;
}
.streamer-schedule-card-top .pill {
  padding: 2px 10px; border-radius: 999px;
  font-family: "Russo One", sans-serif; font-size: 0.7rem;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.streamer-schedule-card-top .live-pill {
  background: rgba(34, 197, 94, 0.22); color: #4ade80;
  border: 1px solid rgba(74, 222, 128, 0.55);
}
.streamer-schedule-card-bottom { font-size: 0.78rem; color: #94a3b8; }

@media (prefers-reduced-motion: reduce) {
  .streamer-popup-avatar { animation: none !important; }
  .trainer-slot.is-now-live { animation: none !important; }
  .trainer-slot.is-clickable:hover { transform: none !important; }
}

/* ── Rollo label picker modal ──────────────────────────────────────────
 * Modal lives at #printLabelsModal. Lets the eBay room operator pick
 * which session items get printed (and how many of each) to the Rollo
 * 2x1 in thermal printer, plus toggle which fields appear on each label
 * (name + optionally ID / category / series / cost / barcode).
 *
 * Visual style mirrors the existing Stream Detail / Edit Item modals
 * (.editor.modal-panel) so it feels native in the same flow.
 */
.pl-panel { max-width: 720px; width: 90%; padding: 22px 26px; }
.pl-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 14px; margin-bottom: 14px;
}
.pl-title { margin: 0; font-size: 1.25rem; }
.pl-subtitle { font-size: 0.8rem; color: var(--muted, #94a3b8); margin-top: 4px; }

.pl-toggle-row {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 8px;
  padding: 12px 14px;
  margin-bottom: 14px;
}
.pl-section-title {
  font-size: 0.85rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--muted, #94a3b8);
  margin-bottom: 10px;
  display: flex; align-items: center; gap: 12px;
}
.pl-master-toggle { display: inline-flex; align-items: center; gap: 6px; font-weight: 400; font-size: 0.78rem; text-transform: none; letter-spacing: 0; }
.pl-toggle-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 6px 16px;
}
.pl-toggle-grid label { display: inline-flex; align-items: center; gap: 6px; font-size: 0.85rem; cursor: pointer; }
.pl-toggle-grid label.pl-toggle-disabled { cursor: not-allowed; opacity: 0.7; }
.pl-toggle-grid label .hint { font-size: 0.72rem; color: var(--muted, #94a3b8); }

.pl-items-section { margin-bottom: 14px; }
.pl-items-section.hidden { display: none; }
.pl-item-list { display: flex; flex-direction: column; gap: 6px; }
.pl-item-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 8px 10px; border-radius: 6px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.06);
}
.pl-row-check { display: inline-flex; align-items: center; gap: 8px; font-size: 0.88rem; cursor: pointer; flex: 1; min-width: 0; }
.pl-row-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-row-pid { color: var(--muted, #94a3b8); font-family: ui-monospace, monospace; font-size: 0.78rem; }
.pl-row-qty { display: inline-flex; align-items: center; gap: 6px; font-size: 0.8rem; color: var(--muted, #94a3b8); }
.pl-row-qty input[type="number"] {
  width: 64px; padding: 3px 6px; font-size: 0.85rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--text, #e5e7eb);
  border-radius: 4px;
}
.pl-empty { padding: 8px 4px; font-style: italic; }

.pl-footer {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.pl-total { font-size: 0.95rem; }
.pl-total strong { font-size: 1.15rem; color: var(--accent, #60a5fa); }
.pl-actions { display: flex; gap: 8px; }

/* Per-row quick-print 🏷 button on Stream Detail item tables. */
.sd-quick-label-btn {
  margin-left: 8px;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--text, #e5e7eb);
  border-radius: 4px;
  padding: 1px 6px;
  font-size: 0.85rem;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 0.15s ease, border-color 0.15s ease;
}
.sd-quick-label-btn:hover {
  opacity: 1;
  border-color: rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.05);
}

/*
 * App copyright footer (May 15 2026).
 *
 * Legal owner of the software is Crafture LLC. The DISPLAY brand
 * (currently GG Hobby) is a white-label default and will swap per
 * deployment per CLAUDE.md — but the copyright holder of the
 * underlying program is always Crafture LLC and does not change
 * regardless of which operator runs this instance. Like Microsoft
 * Office resold under a partner brand still carries "© Microsoft."
 *
 * Year was specified explicitly by the owner ("2025"). Update later
 * to a range ("2025–2026") once the year rolls over enough to matter
 * — single-year copyright is fine and standard.
 */
.app-footer {
  /* margin-top: auto pushes the footer to the bottom of the flex
   * column on body. On short pages this means the footer hugs the
   * viewport bottom; on long pages it sits naturally after content.
   *
   * position: relative + z-index: 2 is REQUIRED because #pokemonBackdrop
   * is position:fixed inset:0 z-index:1 and covers the full viewport
   * with the gradient + silhouettes. Without our own stacking context
   * the footer renders UNDERNEATH the backdrop and you just see the
   * gradient where the footer should be. Reported May 15 (multiple
   * times): "STILL NOT THERE." Mirrors what .container already does
   * to escape the backdrop. */
  position: relative;
  z-index: 2;
  margin-top: auto;
  margin-left: 0;
  margin-right: 0;
  margin-bottom: 0;
  padding: 16px;
  text-align: center;
  font-size: 0.8rem;
  /* Bumped contrast from 0.45 → 0.7 — at 0.45 the footer is legible
   * against the solid gradient but disappears against the busy
   * silhouette regions of the backdrop. 0.7 stays subtle without
   * vanishing. */
  color: rgba(229, 231, 235, 0.7);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(2, 6, 23, 0.5);
  width: 100%;
  letter-spacing: 0.02em;
}

/*
 * Footer clearance for the fixed rolling-stream-stats bar that sits
 * at viewport bottom with z-index 850. Reported May 15: "dont see
 * the crafture llc footer here" — without clearance the rolling bar
 * covers the copyright entirely. Scoped via :has() so other pages
 * (order flow, auction-control, etc.) that don't have a rolling bar
 * keep their footer flush at the viewport bottom. :has() is
 * supported by every browser the app already targets (Chrome 105+,
 * Firefox 121+, Safari 15.4+).
 */
body:has(.rolling-show-bar) .app-footer {
  margin-bottom: 64px;
}

.app-footer a {
  color: inherit;
  text-decoration: none;
}

/*
 * Header-bar action links (May 18 2026). Replaces the emoji set
 * (📱 ✨ 🔥 📊 💬) that rendered inconsistently across OSes / browsers
 * and clashed with the dark theme. Owner: "these icons look like
 * shit". The SVGs live in the <defs> sprite block in index.html and
 * inherit color from the link's currentColor, so they pick up the
 * .secondary button color without per-icon styling.
 */
.hd-link {
  /* Style anchors as full pill-buttons matching button.secondary
   * (dark background, white text, rounded). Without this override,
   * .secondary on an <a> picked up only border + base color, so the
   * Scan/AI Intake/Chase/Stats/Chat links read as bright blue
   * floating text -- not pill buttons. Owner v4: "make them like
   * the other [Feedback button] please". Now Feedback and these
   * 5 links share the same visual class. */
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  line-height: 1;
  padding: 8px 10px;
  border-radius: 6px;
  border: 1px solid #475569;
  background: #334155;
  color: #f8fafc;
  font-size: 14px;
  font-weight: 600;
}
.hd-link:hover {
  filter: brightness(1.15);
}
.hd-link:visited,
.hd-link:active {
  color: #f8fafc;
}

/* Catalog-toolbar links that are <a> (so target=_blank works) styled to
   match the sibling button.secondary buttons (Weight Audit, Low on Floor,
   Add Item…). The bare `.secondary` rule selects `button.secondary` only, so
   an `a.secondary` picks up none of the pill-button look and renders as a
   stripped link — underlined, and purple once visited.

   Keyed to a CLASS, not to individual ids. It was originally written for
   #dimsAuditLink alone, so every toolbar link added afterwards silently
   missed out: Price Log (Jul 2026) and MSRP Audit (Jul 2026) both shipped
   rendering as bare purple underlined text next to real buttons. Any future
   toolbar link just needs `class="secondary toolbar-link"`.
   May 20 2026: 'they all have good buttons and the dims look sub par'.
   Jul 27 2026: 'look at these tabs they are not good'. */
.toolbar-link,
.toolbar-link:link,
.toolbar-link:visited,
.toolbar-link:hover,
.toolbar-link:active {
  font-size: 14px;
  font-weight: 600;
  padding: 8px 10px;
  border-radius: 6px;
  border: 1px solid #475569;
  background: #334155;
  color: #fff;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  line-height: 1;
}
.toolbar-link:hover {
  filter: brightness(1.08);
}
.hd-icon {
  /* v3: 20px solid-filled icons (Heroicons solid variants). Outline
   * style v2 read as thin/spindly next to the Logout button. Solid
   * fill gives the icons real visual weight that matches the header
   * text and the chunky Logout button. fill=currentColor on the
   * symbol means each link's color drives the icon, same hover
   * tint behavior as before. */
  width: 20px;
  height: 20px;
  flex: 0 0 auto;
  vertical-align: middle;
  pointer-events: none;
}


/*
 * Deploy health badge in the top header. Three states:
 *   green  = HEAD == origin/main, last deploy ok
 *   yellow = behind (deploy pending) or no poll logged yet
 *   red    = last deploy failed
 * Reported May 19 2026: 'i need a way to make sure it is doing the
 * job intended' after multiple silent auto-pull failures.
 */
#deployHealthBadge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.deploy-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #6b7280;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.05);
}
.deploy-dot-green  { background: #22c55e; box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.25); }
.deploy-dot-yellow { background: #fbbf24; box-shadow: 0 0 0 2px rgba(251, 191, 36, 0.25); }
.deploy-dot-red    { background: #ef4444; box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.25); animation: deployPulse 1.5s ease-in-out infinite; }
@keyframes deployPulse {
  0%, 100% { box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.25); }
  50%      { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0.45); }
}

.deploy-popover {
  position: fixed;
  top: 70px;
  right: 16px;
  width: 360px;
  max-width: calc(100vw - 32px);
  background: #0f172a;
  border: 1px solid #334155;
  border-radius: 8px;
  padding: 14px 16px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
  z-index: 2000;
  font-size: 0.82rem;
  color: #e2e8f0;
  line-height: 1.5;
}
.deploy-popover h4 {
  margin: 0 0 8px;
  font-size: 0.95rem;
  display: flex;
  align-items: center;
  gap: 6px;
}
.deploy-popover dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 12px;
  margin: 0;
}
.deploy-popover dt { color: #94a3b8; font-weight: 600; }
.deploy-popover dd { margin: 0; word-break: break-all; }
.deploy-popover .deploy-summary {
  margin: 6px 0 12px;
  padding: 8px 10px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.04);
  font-size: 0.85rem;
}
.deploy-popover code {
  font-family: Consolas, Menlo, monospace;
  font-size: 0.78rem;
  background: rgba(255, 255, 255, 0.06);
  padding: 1px 5px;
  border-radius: 3px;
}

/* ── Wheel Image Library ──────────────────────────────────────────────
   Standalone page (web/wheel-library.html) that shows every active
   product as a 500x500 letterboxed PNG tile. Streamers drag tiles
   straight onto OBS Pro Live Studio's wheel slots, or click the save
   icon to download. Light theme on a white background so the
   letterbox-white image padding is invisible — every tile reads as
   one continuous square. */
.wheel-lib-body {
  margin: 0;
  font-family: "Manrope", system-ui, -apple-system, sans-serif;
  background: #f8fafc;
  color: #0f172a;
}
.wheel-lib-topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 20px;
  background: #ffffff;
  border-bottom: 1px solid #e2e8f0;
  position: sticky;
  top: 0;
  z-index: 50;
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.05);
}
.wheel-lib-brand {
  display: flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: #0f172a;
  font-weight: 700;
  font-size: 1.1rem;
  white-space: nowrap;
}
.wheel-lib-brand-icon { font-size: 1.4rem; }
.wheel-lib-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  flex-wrap: wrap;
}
.wheel-lib-actions input[type="search"] {
  flex: 1;
  min-width: 200px;
  padding: 8px 12px;
  border: 1px solid #cbd5e1;
  border-radius: 8px;
  font-size: 0.95rem;
  background: #ffffff;
  color: #0f172a;
}
.wheel-lib-actions select {
  padding: 8px 12px;
  border: 1px solid #cbd5e1;
  border-radius: 8px;
  background: #ffffff;
  color: #0f172a;
  font-size: 0.9rem;
}
.wheel-lib-btn {
  padding: 8px 14px;
  border-radius: 8px;
  border: 1px solid #1d4ed8;
  background: #1d4ed8;
  color: #ffffff;
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.wheel-lib-btn:hover { background: #1e40af; }
.wheel-lib-btn:disabled { opacity: 0.55; cursor: wait; }
.wheel-lib-btn-secondary {
  background: #ffffff;
  color: #1d4ed8;
}
.wheel-lib-btn-secondary:hover { background: #eff6ff; }

.wheel-lib-main {
  padding: 20px;
  max-width: 1600px;
  margin: 0 auto;
}
.wheel-lib-status {
  margin: 0 0 16px 0;
  padding: 8px 12px;
  border-radius: 6px;
  background: #e0f2fe;
  color: #075985;
  border-left: 4px solid #0ea5e9;
  font-size: 0.88rem;
}
.wheel-lib-status-error {
  background: #fee2e2;
  color: #991b1b;
  border-left-color: #dc2626;
}
.wheel-lib-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 14px;
}
.wheel-lib-empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 40px;
  color: #64748b;
  font-style: italic;
}
.wheel-lib-tile {
  margin: 0;
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 10px;
  overflow: hidden;
  cursor: grab;
  transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
  position: relative;
  display: flex;
  flex-direction: column;
}
.wheel-lib-tile:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(15, 23, 42, 0.12);
  border-color: #1d4ed8;
}
.wheel-lib-tile:active { cursor: grabbing; }
.wheel-lib-tile img {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  background: #ffffff; /* matches letterbox so the join is seamless */
  pointer-events: none; /* let drag fire on <figure>, not on <img> */
}
.wheel-lib-tile figcaption {
  padding: 8px 10px;
  border-top: 1px solid #f1f5f9;
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: #ffffff;
}
.wheel-lib-pid {
  font-family: Consolas, Menlo, monospace;
  font-size: 0.78rem;
  color: #1d4ed8;
  font-weight: 700;
}
.wheel-lib-name {
  font-size: 0.82rem;
  color: #334155;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wheel-lib-save-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid #cbd5e1;
  background: rgba(255, 255, 255, 0.92);
  cursor: pointer;
  font-size: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.12s ease, background 0.12s ease;
}
.wheel-lib-tile:hover .wheel-lib-save-btn { opacity: 1; }
.wheel-lib-save-btn:hover { background: #ffffff; }

/* ── Game badge — catalog Name cell, non-Pokémon rows only ─────────────── */
.game-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  border-radius: 10px;
  font-size: 0.72rem;
  font-weight: 600;
  vertical-align: middle;
  background: #334155;
  color: #e2e8f0;
  white-space: nowrap;
}
.game-badge-sports   { background: #14532d; color: #dcfce7; }
.game-badge-onepiece { background: #7c2d12; color: #ffedd5; }
.game-badge-mtg      { background: #3b0764; color: #f3e8ff; }
.game-badge-yugioh   { background: #713f12; color: #fef9c3; }
.game-badge-lorcana  { background: #164e63; color: #cffafe; }

/* ── Rooms & channels editor (rc-editor) ─────────────────────────────────
   The tables mix plain text, inputs, selects, and checkboxes per row; the
   app's global input sizing made every cell sit at a different height
   (operator, Sep 1: "all over the place and off centered"). One consistent
   control height + middle alignment fixes the grid; Kind gets badge pills
   because grey-on-grey text was unreadable. */
.rc-editor td, .rc-editor th { vertical-align: middle; }
.rc-editor tbody td { padding: 4px 6px; }
.rc-editor td input[type="text"],
.rc-editor td input[type="number"],
.rc-editor td select {
  margin: 0;
  height: 30px;
  padding: 3px 8px;
  box-sizing: border-box;
  font-size: 0.82rem;
}
.rc-editor td input[type="color"] { margin: 0; height: 26px; width: 34px; padding: 1px; vertical-align: middle; }
.rc-editor td input[type="checkbox"] { margin: 0; width: 16px; height: 16px; vertical-align: middle; }
.rc-editor td code { display: inline-block; padding: 2px 0; }
.rc-kind {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid transparent;
}
.rc-kind-live        { background: #0e749033; color: #67e8f9; border-color: #0e749077; }
.rc-kind-pos         { background: #16653433; color: #86efac; border-color: #16653477; }
.rc-kind-marketplace { background: #6d28d933; color: #d8b4fe; border-color: #6d28d977; }
.rc-kind-web         { background: #1d4ed833; color: #93c5fd; border-color: #1d4ed877; }
