/* Standalone dashboard + admin theme — cream/teal/coral palette matching
   the homepage and the non-technical streamer guide. Deliberately separate
   from extension/config/config.css: the extension's Config view (running
   inside Twitch's iframe) keeps the Twitch-purple look, since it's meant
   to feel native to Twitch's own chrome. This file re-themes the exact
   same class names dashboard-core.js already generates — no JS structure
   changes needed beyond the brand header in renderNav(). */

:root {
  --bg: #F6F3EA;
  --surface: #FFFFFF;
  --ink: #1B2E2B;
  --ink-soft: #4A5A56;
  --ink-faint: #7C8A85;
  --accent: #2F7A6E;
  --accent-deep: #1B5850;
  --coral: #C9613F;
  --coral-bg: #FBEAE2;
  --line: #DDD5C2;
  --pill-bg: #E8F2EF;
  --pill-ink: #1B5850;
  --danger: #C1432E;
  --danger-deep: #9A3423;
  /* Text on a filled accent / danger button. The accent is a dark teal in the light
     theme (white text, 5.1:1) but a light mint in the dark one, where white text
     was 1.8:1 and nearly unreadable, so there it is the page's own dark color. */
  --on-accent: #FFFFFF;
  --danger-btn: #C1432E;
  --danger-btn-hover: #9A3423;
  --shadow: 0 1px 2px rgba(27, 46, 43, 0.06), 0 12px 32px -16px rgba(27, 46, 43, 0.18);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #101E1B;
    --surface: #16302B;
    --ink: #F1EDDF;
    --ink-soft: #A9BBB6;
    --ink-faint: #6E8480;
    --accent: #6BD2BE;
    --accent-deep: #9AE6D6;
    --coral: #F0906D;
    --coral-bg: #2B211B;
    --line: #2A423C;
    --pill-bg: #1D3D37;
    --pill-ink: #9AE6D6;
    --danger: #E2604A;
    --danger-deep: #C1432E;
    --on-accent: #101E1B;
    /* --danger is the bright red used for error TEXT on a dark surface; a filled
       danger button keeps white text, so its fill stays the darker red (5.1:1). */
    --danger-btn: #C1432E;
    --danger-btn-hover: #9A3423;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 12px 32px -16px rgba(0, 0, 0, 0.55);
  }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  font-family: "Karla", "Segoe UI", system-ui, sans-serif;
  color: var(--ink);
}

#app {
  padding: 32px 24px 60px;
  box-sizing: border-box;
  max-width: 880px;
  margin: 0 auto;
}

.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 28px;
}

/* Shown only for an operator-minted impersonation session (see auth.
   mint_impersonation_token / dashboard-core.js's renderNav) — deliberately
   loud, since the whole point is that whoever's using this notices it's a
   temporary, operator-granted mod session and not their own Twitch login. */
.impersonation-banner {
  background: var(--coral-bg);
  color: var(--coral);
  border: 1px solid var(--coral);
  border-radius: 10px;
  padding: 10px 16px;
  margin: -18px 0 20px;
  font-weight: 600;
  font-size: 0.9rem;
  text-align: center;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600;
  font-size: 1.2rem;
  text-decoration: none;
  color: var(--ink);
}

.brand img {
  width: 32px;
  height: 32px;
  object-fit: contain;
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 22px;
  margin-bottom: 18px;
  box-shadow: var(--shadow);
}

.dashboard-nav {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

/* Tags a manually-seeded entry (admin_manual_* user id — see
   routers/admin.py's add_manual_entry) wherever it shows up, so it never
   reads as indistinguishable from a real viewer's entry. Dashed border on
   purpose — visually distinct from the solid Active/Passed pills. */
.manual-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px dashed var(--ink-faint);
  color: var(--ink-faint);
  margin-left: 6px;
}

/* Unlike .manual-tag (dashed/faint, signals "test data"), this is a real
   sale — a claim_lot's leftover copies sold off the normal draw — so it
   gets a solid pill like the rest of the app's real-data badges. */
.extra-claim-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--pill-bg);
  color: var(--pill-ink);
  margin-left: 6px;
}

/* Coral rather than the teal pill/extra-claim-tag use — ties to the same
   coral already used for winner-note-row's name, so "this person won"
   reads consistently wherever it shows up, and stays visually distinct
   from the teal "Extra Claim"/"Manual" tags. */
.winner-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--coral-bg);
  color: var(--coral);
  margin-left: 6px;
}

/* A viewer's first recorded claim win — led_gengar's first-time winners pay
   right away before running a tab. Solid accent so it reads as an action
   cue, distinct from the coral "Winner" pill beside it. */
.first-time-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--surface);
  margin-left: 6px;
}

.winner-row {
  background: var(--coral-bg);
}

.dashboard-nav button {
  background: transparent;
  color: var(--ink-soft);
  border: 1.5px solid var(--line);
  border-radius: 999px;
  padding: 8px 18px;
}

.dashboard-nav button:hover {
  /* The generic `button:hover` (further down, same specificity) fills a hovered button
     with --accent-deep, which is also this text color: the label vanished. A nav pill
     stays transparent and only its border and text change. */
  background: transparent;
  border-color: var(--accent);
  color: var(--accent-deep);
}

.dashboard-nav button.nav-active {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}

.dashboard-nav button.nav-active:hover {
  background: var(--accent-deep);
  border-color: var(--accent-deep);
}

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(16, 30, 27, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  box-sizing: border-box;
  z-index: 1000;
}

.modal {
  max-width: 480px;
  width: 100%;
  max-height: 90vh;
  overflow-y: auto;
}

h3, h4 {
  font-family: "Fraunces", Georgia, serif;
  font-weight: 600;
  margin: 0 0 10px;
}

.muted {
  color: var(--ink-soft);
  font-size: 14px;
  margin: 0 0 12px;
}

.btn-link {
  display: inline-block;
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  border-radius: 8px;
  padding: 10px 18px;
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  text-decoration: none;
}

.btn-link:hover {
  background: var(--accent-deep);
}

.error {
  color: var(--danger);
}

.command-hint {
  font-size: 13px;
  margin: -8px 0 12px;
}

.command-hint.ok {
  color: var(--accent);
}

.command-hint.taken {
  color: var(--danger);
}

form label {
  display: block;
  margin-bottom: 10px;
  font-size: 14px;
  color: var(--ink-soft);
}

form fieldset {
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 10px 12px 12px;
  margin: 0 0 12px;
}

form legend {
  padding: 0 4px;
  font-size: 12px;
  color: var(--ink-faint);
}

form label.radio {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
  font-size: 14px;
}

form label.radio input {
  display: inline;
  width: auto;
  margin: 0;
}

.hidden {
  display: none;
}

/* Generic typeahead dropdown (see dashboard-core.js's wireTypeahead) —
   anchored to whichever input it wraps. */
.typeahead-wrap {
  position: relative;
}

.typeahead-dropdown {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  z-index: 10;
  margin-top: 4px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--shadow);
  max-height: 200px;
  overflow-y: auto;
}

.typeahead-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 12px;
  border: none;
  background: none;
  font: inherit;
  color: var(--ink);
  cursor: pointer;
}

.typeahead-item:hover,
.typeahead-item:focus {
  background: var(--line);
}

label.toggle-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 14px;
  margin-bottom: 6px;
  font-size: 14px;
  cursor: pointer;
}

.toggle {
  position: relative;
  display: inline-block;
  flex: none;
  width: 38px;
  height: 22px;
}

.toggle input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.toggle input:disabled {
  cursor: default;
}

.toggle-track {
  position: absolute;
  inset: 0;
  background: var(--line);
  border-radius: 999px;
  transition: background 0.15s ease;
}

.toggle-track::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 18px;
  height: 18px;
  background: var(--surface);
  border-radius: 50%;
  box-shadow: var(--shadow);
  transition: transform 0.15s ease;
}

.toggle input:checked + .toggle-track {
  background: var(--accent);
}

.toggle input:checked + .toggle-track::before {
  transform: translateX(16px);
}

.toggle input:disabled + .toggle-track {
  opacity: 0.45;
}

form input,
form textarea {
  display: block;
  margin-top: 4px;
  width: 100%;
  box-sizing: border-box;
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 8px;
  padding: 10px;
  font-size: 14px;
  font-family: inherit;
}

form textarea {
  resize: vertical;
}

input.small {
  width: 120px;
  flex: none;
}

.credits-section {
  border-top: 1px solid var(--line);
  margin-top: 12px;
  padding-top: 12px;
}

.credits-section:first-of-type {
  border-top: none;
  margin-top: 0;
  padding-top: 0;
}

.credit-balance-modal select {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 10px;
  padding: 10px;
  font-size: 14px;
  font-family: "Karla", sans-serif;
  background: var(--bg);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
}

.credits-grants-list {
  margin-bottom: 8px;
}

/* Bare .bill-row has no vertical spacing of its own (fine stacked inside a
   .bill-person block elsewhere, which supplies its own padding/border) —
   here rows sit directly one after another with nothing else around them,
   so without this they visually run together, buttons and all. */
.credits-grants-list .bill-row {
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
}

.credits-grants-list .bill-row:last-child {
  border-bottom: none;
}

.actions {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}

button {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  border-radius: 8px;
  padding: 10px 18px;
  font-weight: 700;
  cursor: pointer;
  font-size: 14px;
  font-family: "Karla", sans-serif;
}

button:hover {
  background: var(--accent-deep);
}

button.small {
  padding: 6px 12px;
  font-size: 13px;
  background: var(--pill-bg);
  color: var(--pill-ink);
  font-weight: 600;
}

button.small:hover {
  background: var(--line);
}

button.danger {
  background: var(--danger-btn);
  color: #FFFFFF;
}

button.danger:hover {
  background: var(--danger-btn-hover);
}

button:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Per-viewer totals on the Lookup page — an itemized bill, not just a lump
   sum: each person's line items, their subtotal, then a grand total. */
.bill {
  margin-top: 14px;
  margin-bottom: 20px;
}

.bill-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
}

.bill-person {
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}

.bill-person-header {
  font-weight: 700;
  margin-bottom: 4px;
  align-items: center;
}

.bill-item {
  padding-left: 14px;
  font-size: 13px;
  color: var(--ink-soft);
}

.bill-item.paid {
  text-decoration: line-through;
  color: var(--ink-faint);
}

.bill-item.credit {
  font-style: italic;
}

.bill-item-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.bill-person-name-group {
  display: flex;
  gap: 12px;
}

.paid-toggle.paid {
  background: var(--accent);
  color: var(--surface);
}

.paid-toggle.paid:hover {
  background: var(--accent-deep);
}

/* Coral rather than Paid's accent teal — the two toggles track independent
   facts (see renderWinnerTotals), so they need to read as visually distinct
   at a glance, not like two instances of the same state. */
.messaged-toggle.messaged {
  background: var(--coral);
  color: var(--surface);
}

.messaged-toggle.messaged:hover {
  background: var(--danger-deep);
}

/* Giveaway winner rows only — never shown alongside Paid/Messaged (those
   are claim-billing-only, on a different page), so reusing --accent here
   doesn't create a visual collision. */
.presence-toggle.present {
  background: var(--accent);
  color: var(--surface);
}

.presence-toggle.present:hover {
  background: var(--accent-deep);
}

.winner-note-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  font-size: 14px;
}

.winner-note-row span {
  flex: none;
  min-width: 150px;
  color: var(--coral);
  font-weight: 700;
}

/* Overrides the rule above (two classes beats one class + a type selector)
   for the row's one shared "Saved" indicator (see renderGiveawayCard) —
   it's a plain flash message, not the winner-name label the base rule was
   written for. Reserves the same fixed width whether or not it's currently
   showing anything, so every row lines up regardless of which fields (if
   any) have been saved yet — the actual fix for the fields "dancing"
   around, not just this element's own styling. */
.winner-note-row .save-flash {
  min-width: 48px;
  color: var(--accent);
  font-weight: 400;
  text-align: right;
}

.winner-note-row input {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 14px;
  font-family: inherit;
}

.winner-note-row input.winner-price-input {
  flex: none;
  width: 90px;
}

/* wireTypeahead wraps its input in .typeahead-wrap when a claim_lot has
   pre-entered cards (see renderGiveawayCard) — the wrap becomes the actual
   flex child here, so it needs the flex:1 the plain input normally gets
   directly, or the item input would shrink to content width instead of
   filling the row. */
.winner-note-row .typeahead-wrap {
  flex: 1;
}

.price-edit-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0;
  font-size: 14px;
}

.price-edit-row span { color: var(--coral); font-weight: 700; }

.price-edit-row input {
  width: 90px;
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 14px;
  font-family: inherit;
}

/* Home's remote wheel controls (see dashboard-core.js's renderGiveawayCard)
   — a plain .actions row, just with the spin-duration input mixed in next
   to Spin specifically. */
.wheel-remote-actions {
  align-items: center;
}

.spin-seconds-input {
  width: 56px;
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 14px;
  font-family: inherit;
}

.item-note-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 8px 0;
  font-size: 14px;
}

.item-note-row span { color: var(--coral); font-weight: 700; flex: none; }

.item-note-row input {
  flex: 1;
  min-width: 0;
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 14px;
  font-family: inherit;
}

/* Admin panel: bot login health. */
.bot-banner {
  margin: 0 0 16px;
  padding: 12px 16px;
  border: 1px solid var(--coral);
  border-radius: 10px;
  background: var(--coral-bg);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.5;
}

/* One row per bot: status text left, its action button right (wrapping below
   on a narrow screen). Also used for each entry inside the banner. */
.bot-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
  flex-wrap: wrap;
  margin: 8px 0;
}

.bot-row-text { flex: 1 1 260px; min-width: 0; }
.bot-row-text p { margin: 0; }
.bot-banner .bot-row { margin: 0; }
.bot-banner .bot-row + .bot-row { margin-top: 10px; }

/* The compact button-styled link: same look as button.small (grey pill), with
   .primary for the green call-to-action. .btn-link itself is defined above. */
.btn-link.small {
  padding: 6px 12px;
  font-size: 13px;
  background: var(--pill-bg);
  color: var(--pill-ink);
  font-weight: 600;
  white-space: nowrap;
}

.btn-link.small:hover { background: var(--line); }

.btn-link.small.primary {
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 700;
}

.btn-link.small.primary:hover { background: var(--accent-deep); }

.bot-ok { color: var(--accent); font-weight: 600; }
.bot-bad { color: var(--coral); font-weight: 700; }
.bot-warn { font-weight: 600; }
.bot-detail { font-size: 12px; }

.save-flash {
  font-size: 12px;
  color: var(--accent);
  opacity: 0;
  transition: opacity 0.2s ease;
}

.save-flash-visible { opacity: 1; }

.purge-confirm-input {
  display: block;
  width: 100%;
  box-sizing: border-box;
  background: var(--bg);
  border: 1px solid var(--line);
  color: var(--ink);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 14px;
  margin: 12px 0;
  font-family: inherit;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

th, td {
  text-align: left;
  padding: 8px 6px;
  border-bottom: 1px solid var(--line);
}

/* renderHistoryTable pairs a summary row with a nested-winners row right
   below it — the border between them would read as a second, unrelated
   divider, so only the winners row (the real end of this giveaway's block)
   keeps one. */
.history-summary-row td {
  border-bottom: none;
  padding-bottom: 2px;
}

.history-winners-row td {
  padding-top: 0;
}

.history-winner-row {
  display: flex;
  gap: 12px;
  padding: 3px 0 3px 18px;
  font-size: 13px;
  color: var(--ink-soft);
}

.history-winner-name {
  flex: none;
  width: 200px;
  color: var(--ink);
  font-weight: 600;
}

.history-winner-item {
  flex: none;
  width: 220px;
}

th {
  color: var(--ink-faint);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
}

/* Mod View's toolbar row, and its Most claimed leaderboard modal (the modal
   itself reuses .modal-backdrop / .modal / .card from above). */
.mod-view-toolbar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}

.sale-day-label-row {
  text-align: right;
  margin-bottom: 6px;
}

.sale-day-label {
  font-size: 13px;
  color: var(--ink-soft);
}

.mod-view-toolbar select {
  padding: 6px 12px;
  font-size: 13px;
  font-weight: 600;
  font-family: "Karla", sans-serif;
  background: var(--pill-bg);
  color: var(--pill-ink);
  border: none;
  border-radius: 8px;
  cursor: pointer;
}

.top-claimed-sort {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

/* Scrolls inside the card on a narrow screen instead of widening the page. */
.top-claimed-scroll { overflow-x: auto; }

/* One row per card in the batch-claim record-entry form (see
   renderBatchClaimModal) — item grows, price stays a fixed comfortable
   width, remove button doesn't stretch. */
.batch-claim-row {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 8px;
}

.batch-claim-row input[name="item"] {
  flex: 1;
}

.batch-claim-row input[name="price"] {
  width: 100px;
  flex: none;
}

/* One row per pre-entered card in the Manage Cards modal (see
   renderManageCardsModal) — name grows, quantity stays a fixed comfortable
   width, assigned-count label and delete/add button don't stretch. */
.giveaway-card-row {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 8px;
}

.giveaway-card-row input:first-child {
  flex: 1;
}

.giveaway-card-row .card-qty-input {
  width: 70px;
  flex: none;
}

.giveaway-card-row .card-assigned-label {
  flex: none;
  white-space: nowrap;
}

.top-claimed-table th.num,
.top-claimed-table td.num { text-align: right; }

.top-claimed-table .top-claimed-first td {
  background: var(--pill-bg);
  color: var(--pill-ink);
  font-weight: 700;
}

.channel-option {
  display: block;
  width: 100%;
  text-align: left;
}

#channel-switch-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  max-width: 880px;
  margin: 0 auto;
  padding: 10px 24px;
  font-size: 13px;
  color: var(--ink-soft);
  border-bottom: 1px solid var(--line);
}

/* Who's here panel (see dashboard-core.js "Who's here"). Fixed to the corner,
   outside #app, so a page redraw never touches it. */
.mod-presence-panel {
  position: fixed;
  right: 16px;
  bottom: 16px;
  z-index: 50;
  width: 280px;
  max-width: calc(100vw - 32px);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow);
  font-size: 14px;
}

.mod-presence-toggle {
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 10px 14px;
  font: inherit;
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
}

.mod-presence-list {
  list-style: none;
  margin: 0;
  padding: 0 14px 10px;
}

.mod-presence-list li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 0;
  color: var(--ink-soft);
}

.mod-presence-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}

.mod-presence-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mod-presence-role {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--pill-bg);
  color: var(--pill-ink);
}

/* "Name is editing" — informational only, never blocks the card. */
.card:has(> .editing-tag) {
  position: relative;
  border-color: var(--coral);
}

.editing-tag {
  position: absolute;
  top: -11px;
  right: 18px;
  font-size: 12px;
  font-weight: 700;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--coral-bg);
  color: var(--coral);
  border: 1px solid var(--coral);
}

/* Mod notes — the chat-style log inside the Who's here panel. */
.mod-notes-title {
  padding: 8px 14px 4px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-faint);
}

.mod-notes-log {
  list-style: none;
  margin: 0;
  padding: 0 14px;
  max-height: 240px;
  overflow-y: auto;
}

.mod-notes-log li {
  padding: 4px 0;
}

.mod-notes-head {
  display: flex;
  gap: 8px;
  align-items: baseline;
}

.mod-notes-time {
  font-size: 11px;
  color: var(--ink-faint);
}

.mod-notes-text {
  color: var(--ink-soft);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.mod-notes-form {
  display: flex;
  gap: 6px;
  padding: 8px 14px 12px;
}

/* display:flex above would otherwise win over the hidden attribute. */
.mod-notes-form[hidden] {
  display: none;
}

.mod-notes-input {
  flex: 1;
  min-width: 0;
}

.mod-notes-error {
  padding: 0 14px 10px;
  font-size: 13px;
  color: var(--danger);
}

/* Shown instead of the note box while Mod View is looking back at an earlier
   sale day: the log is a record, not live. */
.mod-notes-readonly {
  margin: 0 14px 6px;
  padding: 8px 10px;
  border: 1px dashed var(--ink-faint);
  border-radius: 8px;
  font-size: 13px;
  color: var(--ink-soft);
}

.mod-notes-readonly .mod-notes-live-btn {
  display: block;
  margin-top: 6px;
}

/* A giveaway entry's ticket count (see weightTag): plain for x1, accent for a
   subscriber's boosted entry. */
.weight-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--ink-soft);
  margin-left: 6px;
}

.weight-tag-boosted {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--surface);
}

/* The Giveaways page's Edit modal holds a whole giveaway card (entries table
   and all), which needs more width than the small form modals. */
.edit-giveaway-modal .modal {
  max-width: 760px;
}

/* A pending duel request on a claim's card (see dashboard-core.js's
   renderDuelBox): the broadcaster accepts or dismisses it. */
.duel-box {
  background: var(--coral-bg);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
  margin: 12px 0;
}

.duel-box p {
  margin: 0 0 6px;
}

.duel-box .actions {
  margin-top: 8px;
}

.duel-headline {
  font-weight: 600;
}

/* One titled slot inside the Google Sheets card on Config (see dashboard-core.js's
   renderSheetSlot): claims sheet, then shipping sheet. */
.sheet-slot {
  border-top: 1px solid var(--line);
  margin-top: 16px;
  padding-top: 14px;
}

.sheet-slot-title {
  margin: 0 0 4px;
  font-size: 1rem;
}

/* A claim that was won with no price recorded anywhere (see dashboard-core.js's
   missingPricePill): shown on the bill, the card, and the Mod View notice. Amber, a
   to-do rather than an alarm. */
.missing-price-pill {
  display: inline-block;
  background: rgba(255, 180, 84, 0.18);
  color: #ffb454;
  border: 1px solid rgba(255, 180, 84, 0.55);
  border-radius: 999px;
  padding: 1px 9px;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  margin-left: 6px;
}

.missing-price-notice {
  background: var(--surface);
  border: 1px solid rgba(255, 180, 84, 0.55);
  border-radius: 10px;
  padding: 8px 12px;
  margin-bottom: 14px;
  line-height: 1.8;
}

.missing-price-notice .missing-price-pill {
  margin-left: 0;
}

.missing-price-notice .link-button {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  text-decoration: underline;
  cursor: pointer;
  font: inherit;
}

.bill-item.missing-price {
  background: rgba(255, 180, 84, 0.07);
}

.card.flash-highlight {
  outline: 2px solid #ffb454;
  transition: outline-color 1.4s;
}
