/* The boot screen and the shell are toggled with the "hidden" attribute, but
   both carry a class that sets "display". An author rule beats the UA's
   "[hidden] { display: none }", so without this the boot screen stayed on the
   page after loading and the dashboard appeared below it — you had to scroll
   past a spinner to reach your own data. */
[hidden] { display: none !important; }

/**
 * Styling for the signed-in half of the site: the login page and the host
 * dashboard.
 *
 * Loaded AFTER styles.css and reuses its custom properties (--bg, --primary,
 * --surface …), so the dashboard can never drift from the marketing site's
 * palette — there is one definition of brand blue, in styles.css.
 */

/* ------------------------------------------------------------------- shared */

.btn-block { width: 100%; justify-content: center; }
.btn-sm { padding: 8px 14px; font-size: 0.86rem; }
.btn-ghost {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text);
}
.btn-ghost:hover { border-color: var(--primary); color: var(--primary-2); }

.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.field > span { font-size: 0.82rem; color: var(--text-muted); font-weight: 500; }
.field input,
.field textarea {
  width: 100%;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.95rem;
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.field input:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgb(46 144 250 / 0.18);
}
.field input:disabled,
.field textarea:disabled { opacity: 0.55; cursor: not-allowed; }
.field textarea { resize: vertical; }

.field-with-button { position: relative; display: block; }
.field-with-button input { padding-right: 68px; }
.reveal-toggle {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: 0;
  color: var(--text-muted);
  font: inherit;
  font-size: 0.8rem;
  cursor: pointer;
  padding: 6px 8px;
}
.reveal-toggle:hover { color: var(--primary-2); }

.form-error {
  background: rgb(220 60 70 / 0.12);
  border: 1px solid rgb(220 60 70 / 0.35);
  color: #ff9ca4;
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-size: 0.88rem;
  margin: 0 0 16px;
}

/* A button that can be busy. The spinner sits inside so the width doesn't jump
   between states — a resizing submit button under the cursor is how you get a
   double submit. */
.spinner {
  width: 16px;
  height: 16px;
  border: 2px solid rgb(255 255 255 / 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  display: none;
  animation: spin 0.7s linear infinite;
}
.spinner-lg { width: 28px; height: 28px; border-width: 3px; display: block; }
.is-busy .spinner { display: inline-block; }
.is-busy .btn-label { display: none; }
@keyframes spin { to { transform: rotate(360deg); } }

/* -------------------------------------------------------------------- login */

.auth-body {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
  background:
    radial-gradient(900px 500px at 50% -10%, rgb(46 144 250 / 0.16), transparent 70%),
    var(--bg);
}
.auth-shell { width: 100%; max-width: 420px; }
.auth-back {
  display: inline-block;
  margin-bottom: 18px;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.88rem;
}
.auth-back:hover { color: var(--primary-2); }

.auth-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 32px 28px 26px;
  animation: rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes rise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

/* The bare mark, no tile. A gradient square behind it made it look like an app
   icon pasted onto the page rather than the brand itself, and the cuts had to
   be painted in the tile's colour to survive — which only worked while the tile
   was there. */
.auth-mark {
  display: grid;
  place-items: center;
  justify-content: start;
  margin-bottom: 18px;
}
.auth-card h1 { font-family: var(--font-head); font-size: 1.6rem; margin: 0 0 4px; }
.auth-sub { color: var(--text-muted); margin: 0 0 24px; font-size: 0.94rem; }
.auth-note { font-size: 0.86rem; color: var(--text-muted); margin: 18px 0 0; line-height: 1.6; }
.auth-note a { color: var(--primary-2); }
.auth-note-faint { color: var(--text-faint); margin-top: 8px; }
.auth-footnote {
  text-align: center;
  color: var(--text-faint);
  font-size: 0.82rem;
  margin: 20px 0 0;
  line-height: 1.6;
}

/* ---------------------------------------------------------------- dashboard */

.dash-body { background: var(--bg); min-height: 100vh; }

.dash-boot {
  min-height: 100vh;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 14px;
  color: var(--text-muted);
}

.dash-top {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 14px 24px;
  background: rgb(10 14 26 / 0.85);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}
.dash-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--text);
  text-decoration: none;
  font-family: var(--font-head);
  font-weight: 700;
}
.dash-brand b { color: var(--primary); font-weight: 700; }

.dash-nav { display: flex; gap: 4px; margin-left: 12px; }
.dash-nav-item {
  background: none;
  border: 0;
  color: var(--text-muted);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  padding: 8px 14px;
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.18s ease, background 0.18s ease;
}
.dash-nav-item:hover { color: var(--text); }
.dash-nav-item.is-active { color: var(--primary-2); background: rgb(46 144 250 / 0.12); }

.dash-user { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.dash-email { color: var(--text-faint); font-size: 0.84rem; }

/* 900px was sized for a page of lists, where a long measure is hard to read.
   The home page is tiles and a rail, which simply left a laptop half empty. */
.dash-main { max-width: 1200px; margin: 0 auto; padding: 32px 28px 80px; }
.view { animation: rise 0.35s cubic-bezier(0.22, 1, 0.36, 1) both; }
.view h1 { font-family: var(--font-head); font-size: 1.7rem; margin: 0 0 4px; }
.view-sub { color: var(--text-muted); margin: 0 0 24px; }
.view-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.view-loading { display: grid; place-items: center; padding: 60px 0; }
.view-loading .spinner { display: block; width: 24px; height: 24px; }

.back-link {
  background: none;
  border: 0;
  color: var(--text-muted);
  font: inherit;
  font-size: 0.86rem;
  padding: 0 0 14px;
  cursor: pointer;
}
.back-link:hover { color: var(--primary-2); }

.stat-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin-bottom: 24px; }
.stat {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.stat span:last-child { color: var(--text-muted); font-size: 0.82rem; }
.stat-n { font-family: var(--font-head); font-size: 1.6rem; font-weight: 700; }

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 20px;
}
.card-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.card-head h2 { font-family: var(--font-head); font-size: 1rem; margin: 0; }
.card-head:empty { display: none; }

.row-list { list-style: none; margin: 0; padding: 0; }
.row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 12px;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.16s ease, transform 0.16s ease;
}
.row:hover { background: var(--surface-alt); transform: translateX(2px); }
.row + .row { border-top: 1px solid var(--border); border-radius: 0; }
.row-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.row-title { font-weight: 600; }
.row-sub { color: var(--text-muted); font-size: 0.84rem; }

.pill {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: 999px;
  white-space: nowrap;
}
.pill-ok { background: rgb(31 174 110 / 0.16); color: #58d6a0; }
.pill-warn { background: rgb(232 163 61 / 0.16); color: #e8a33d; }
.pill-danger { background: rgb(220 60 70 / 0.16); color: #ff8f98; }
.pill-muted { background: var(--surface-alt); color: var(--text-muted); }

.empty { padding: 26px 4px; text-align: center; color: var(--text-muted); }
.empty-hint { color: var(--text-faint); font-size: 0.86rem; margin-top: 4px; }
.note { color: var(--text-faint); font-size: 0.84rem; line-height: 1.6; }

.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }
.field-wide { grid-column: 1 / -1; }
.form-actions { grid-column: 1 / -1; display: flex; justify-content: flex-end; }

.table-wrap { overflow-x: auto; }
.table { width: 100%; border-collapse: collapse; font-size: 0.88rem; }
.table th {
  text-align: left;
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
}
.table td { padding: 10px; border-bottom: 1px solid var(--border); }
.mono { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 0.82rem; color: var(--text-muted); }

.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 20px);
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 11px 20px;
  font-size: 0.88rem;
  opacity: 0;
  transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  z-index: 60;
}
.toast.is-in { opacity: 1; transform: translate(-50%, 0); }
.toast-danger { border-color: rgb(220 60 70 / 0.5); color: #ff9ca4; }

@media (max-width: 720px) {
  .dash-top { flex-wrap: wrap; gap: 12px; padding: 12px 16px; }
  .dash-nav { order: 3; width: 100%; margin: 0; overflow-x: auto; }
  .dash-email { display: none; }
  .dash-main { padding: 24px 16px 60px; }
  .stat-row { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
}

/* Everything that moves here is decoration. Someone who asked the OS to stop
   animations gets the same dashboard, still. */
@media (prefers-reduced-motion: reduce) {
  .view, .auth-card { animation: none; }
  .row:hover { transform: none; }
  .toast { transition: opacity 0.01s; }
  .spinner { animation-duration: 2s; }
}


.boot-error { max-width: 380px; text-align: center; }
.boot-error h1 { font-family: var(--font-head); font-size: 1.2rem; margin: 0 0 8px; color: var(--text); }
.boot-error p { color: var(--text-muted); margin: 0 0 18px; }
.boot-actions { display: flex; gap: 10px; justify-content: center; }

/* ── charts ───────────────────────────────────────────────────────────── */
.charts { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
.chart-wide { grid-column: 1 / -1; }
.chart-block h3 { font-size: 0.9rem; margin: 0 0 2px; font-family: var(--font-head); }
.chart-note { color: var(--text-faint); font-size: 0.8rem; margin: 0 0 10px; }
.chart { width: 100%; height: auto; display: block; overflow: visible; }
.chart-grid { stroke: var(--border); stroke-width: 1; }
.chart-axis { fill: var(--text-faint); font-size: 10px; }
.chart-value { fill: var(--text); font-size: 12px; font-weight: 700; }
.chart-centre { fill: var(--text); font-size: 22px; font-weight: 700; }
.chart-empty { fill: var(--text-faint); font-size: 12px; }
.chart-line { stroke: var(--primary); stroke-width: 2.5; fill: none; stroke-linejoin: round; stroke-linecap: round; }
.chart-area { fill: rgb(46 144 250 / 0.14); stroke: none; }
.chart-dot { fill: var(--primary); stroke: var(--surface); stroke-width: 2; }

.donut-row { display: flex; align-items: center; gap: 16px; }
.chart-donut { max-width: 160px; flex: none; }
.legend { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; font-size: 0.82rem; min-width: 0; }
.legend li { display: flex; align-items: center; gap: 8px; }
.legend-dot { width: 9px; height: 9px; border-radius: 3px; flex: none; }
.legend-label { color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.legend-value { margin-left: auto; font-weight: 700; }

/* ── interact ─────────────────────────────────────────────────────────── */
.interact { display: grid; gap: 26px; }
.interact h3 { font-size: 0.9rem; margin: 0 0 10px; font-family: var(--font-head); }
.interact-form { display: grid; gap: 10px; margin-bottom: 16px; }
.interact-form textarea,
.answer-row input {
  width: 100%;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
  resize: vertical;
}
.interact-form textarea:focus,
.answer-row input:focus { outline: none; border-color: var(--primary); }
.interact-form .btn { justify-self: start; }
.check { display: flex; align-items: center; gap: 8px; color: var(--text-muted); font-size: 0.85rem; }
.check input { width: 15px; height: 15px; accent-color: var(--primary); }

.feed-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.feed-list li { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 12px; }
.feed-list p { margin: 0; font-size: 0.9rem; line-height: 1.55; }
.feed-list .meta { display: block; margin-top: 6px; color: var(--text-faint); font-size: 0.78rem; }
.answer { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); display: grid; gap: 6px; justify-items: start; }
.answer-row { display: flex; gap: 8px; margin-top: 10px; }
.answer-row input { flex: 1; }

.polls { display: grid; gap: 18px; }
.poll { background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 14px; }
.poll-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 2px; }
.poll .meta { color: var(--text-faint); font-size: 0.78rem; }
.poll-options { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 10px; }
.poll-row { display: flex; justify-content: space-between; gap: 12px; font-size: 0.86rem; margin-bottom: 5px; }
.poll-n { color: var(--text-muted); white-space: nowrap; }
.poll-bar { height: 7px; border-radius: 999px; background: var(--surface-alt); overflow: hidden; }
.poll-bar i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--primary), var(--cyan)); transition: width 0.5s cubic-bezier(0.22, 1, 0.36, 1); }

@media (max-width: 720px) {
  .charts { grid-template-columns: 1fr; }
  .donut-row { flex-direction: column; align-items: flex-start; }
}
@media (prefers-reduced-motion: reduce) {
  .poll-bar i { transition: none; }
}

/* ── chart scrubbing ──────────────────────────────────────────────────── */
.chart-surface { cursor: crosshair; touch-action: none; }
.chart-crosshair { stroke: var(--primary); stroke-width: 1; stroke-dasharray: 3 3; opacity: 0.8; }
.chart-scrub-dot { fill: var(--primary); stroke: var(--surface); stroke-width: 2; }
.chart-scrub-box { fill: var(--surface-alt); stroke: var(--border); }
.chart-scrub-label { fill: var(--text); font-size: 11px; font-weight: 600; }
.chart-scrub { transition: opacity 0.15s ease; pointer-events: none; }

/* ── expandable lists ─────────────────────────────────────────────────── */
.list-toggle { margin-top: 12px; width: 100%; justify-content: center; }

/* ── new poll ─────────────────────────────────────────────────────────── */
.poll-new { margin-bottom: 16px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--bg); }
.poll-new summary { padding: 11px 14px; cursor: pointer; font-size: 0.88rem; font-weight: 600; color: var(--primary-2); }
.poll-new[open] summary { border-bottom: 1px solid var(--border); }
.poll-form { padding: 14px; }
.poll-form input[type='text'] {
  width: 100%;
  padding: 9px 11px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 0.88rem;
}
.poll-form input[type='text']:focus { outline: none; border-color: var(--primary); }
.poll-inputs { display: grid; gap: 8px; }
.poll-form-actions { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }

@media (prefers-reduced-motion: reduce) { .chart-scrub { transition: none; } }

/* ── donut selection ──────────────────────────────────────────────────── */
.chart-donut { max-width: 240px; }
.donut-slice { cursor: pointer; transition: opacity 0.2s ease, transform 0.2s ease; transform-origin: center; }
.donut-slice.is-dim { opacity: 0.28; }
.donut-slice.is-on { transform: scale(1.035); }
.legend li { transition: opacity 0.2s ease; }
.legend li.is-dim { opacity: 0.35; }
.legend li.is-on .legend-label { color: var(--text); font-weight: 600; }

/* The check-in bars carried the same font sizes as a full-width chart and read
   as oversized next to the other two. Constrained and scaled down instead. */
.chart-bars { max-width: 420px; }
.chart-bars .chart-value { font-size: 11px; }
.chart-bars .chart-axis { font-size: 9px; }

/* ── expandable lists ─────────────────────────────────────────────────── */
/* Once expanded the toggle sticks to the bottom of the viewport, so collapsing
   a 300-row table doesn't mean scrolling to the end to find the button. */
.list-toggle.is-expanded {
  position: sticky;
  bottom: 12px;
  z-index: 3;
  background: var(--surface-alt);
  border-color: var(--primary);
  box-shadow: 0 10px 26px -12px rgb(0 0 0 / 0.9);
}

/* Both chart cells stretch to the taller of the two, so the shorter one can
   push its own filler to the bottom instead of leaving a hole under itself. */
.chart-block { display: flex; flex-direction: column; }
.mini-stats {
  list-style: none;
  margin: auto 0 0;
  padding: 12px 0 0;
  display: grid;
  gap: 8px;
  border-top: 1px solid var(--border);
  font-size: 0.85rem;
}
.mini-stats li { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.mini-stats span { color: var(--text-muted); }
.mini-stats b { font-size: 1rem; font-variant-numeric: tabular-nums; }
.mini-stats .is-good { color: #1FAE6E; }

/* A second question under the check-in bars, so the cell is not a quarter
   empty. White like every other heading — grey read as a caption belonging to
   the chart above it rather than as the title of the one below.
   
   Written as `.chart-block h3.chart-sub`, not `.chart-sub`: `.chart-block h3`
   above sets `margin: 0 0 2px`, and a class-plus-element selector outranks a
   bare class, so every margin set here was silently discarded. */
.chart-block h3.chart-sub {
  font-size: 0.9rem;
  margin: 23px 0 2px;
  font-family: var(--font-head);
  color: var(--text);
}

/* ---------------------------------------------------------------- payouts */
/* The money card on an event page. Numbers line up in a column, so they use
   tabular figures — proportional digits make two amounts of the same magnitude
   look different lengths, which is exactly the wrong signal on a fee table. */

.payout-table {
  display: flex;
  flex-direction: column;
  margin-bottom: 0.75rem;
}

.payout-line {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.45rem 0;
  font-size: 0.92rem;
  color: rgba(232, 236, 245, 0.72);
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.payout-line:last-child {
  border-bottom: 0;
}

.payout-line.is-strong {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  margin-top: 0.35rem;
  padding-top: 0.7rem;
  font-size: 1.02rem;
  font-weight: 700;
  color: #fff;
}

.payout-value {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.payout-refunds {
  margin: 0.75rem 0 0.25rem;
}

.payout-refunds > summary {
  cursor: pointer;
  color: #2e90fa;
  font-size: 0.9rem;
  font-weight: 600;
  padding: 0.35rem 0;
}

.payout-tickets {
  display: flex;
  flex-direction: column;
  margin-top: 0.5rem;
}

.payout-ticket {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.payout-ticket-meta {
  display: block;
  font-size: 0.78rem;
  color: rgba(232, 236, 245, 0.5);
  margin-top: 0.15rem;
}

.note-ok {
  color: #35c98b;
}

.note-danger {
  color: #f26d6d;
}

/* Highlight purchase — the day stepper and its running total. */
.highlight-body { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
.highlight-picker { display: flex; align-items: center; gap: 14px; }
.highlight-picker .btn { min-width: 44px; font-size: 1.1rem; line-height: 1; }
.highlight-days { font-size: 1.15rem; min-width: 76px; text-align: center; color: var(--text); }
.highlight-total-row { margin: 0; }
.highlight-total { color: var(--text-muted); font-size: 0.9rem; }
.highlight-body .btn-primary { align-self: flex-start; }

/* ------------------------------------------------------------ event wizard */
/* The dashboard's own create-event flow. Same six steps as the app's wizard,
   and the same two building blocks it was rebuilt around: a segmented control
   for a genuine either/or, a switch for a default and a deviation from it. */

.view-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.view-head h1 { margin: 0; }

.wiz { max-width: 640px; margin: 0 auto; }
.wiz-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
.wiz-head h1 { font-family: var(--font-head); font-size: 1.4rem; margin: 0; }

.wiz-progress { margin-bottom: 20px; }
.wiz-progress-track {
  height: 4px;
  border-radius: 999px;
  background: var(--surface-alt);
  overflow: hidden;
}
.wiz-progress-fill {
  height: 100%;
  background: var(--primary);
  border-radius: 999px;
  transition: width 0.25s ease;
}
.wiz-progress-label {
  display: block;
  margin-top: 8px;
  font-size: 0.8rem;
  color: var(--text-muted);
}

.wiz-body { display: flex; flex-direction: column; gap: 16px; }

.wiz-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px;
}
.wiz-card .field:last-child { margin-bottom: 0; }
.wiz-card-title {
  font-family: var(--font-head);
  font-size: 0.95rem;
  margin: 0 0 14px;
}

.wiz-hint {
  display: block;
  color: var(--text-faint);
  font-size: 0.78rem;
  line-height: 1.5;
}

/* Segmented control — one row, the chosen half filled. */
.wiz-seg {
  display: flex;
  gap: 3px;
  padding: 3px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.wiz-seg-btn {
  flex: 1;
  padding: 9px 12px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 0.84rem;
  font-weight: 600;
  cursor: pointer;
}
.wiz-seg-btn:hover { color: var(--text); }
.wiz-seg-btn.is-on { background: var(--primary); color: #fff; }

/* Switch row. The checkbox stays in the DOM and keeps the keyboard and screen
   reader behaviour; the track beside it is what you see. */
.wiz-switch {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 0;
  cursor: pointer;
}
.wiz-switch + .wiz-switch { border-top: 1px solid var(--border); }
.wiz-switch-text { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.wiz-switch-label { font-size: 0.9rem; font-weight: 600; color: var(--text); }
.wiz-switch-desc { font-size: 0.78rem; line-height: 1.5; color: var(--text-muted); }
.wiz-switch-input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
}
.wiz-switch-track {
  position: relative;
  flex: none;
  width: 44px;
  height: 26px;
  border-radius: 999px;
  background: var(--border);
  transition: background 0.18s ease;
}
.wiz-switch-track::after {
  content: '';
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.18s ease;
}
.wiz-switch-input:checked ~ .wiz-switch-track { background: var(--primary); }
.wiz-switch-input:checked ~ .wiz-switch-track::after { transform: translateX(18px); }
.wiz-switch-input:focus-visible ~ .wiz-switch-track { outline: 2px solid var(--primary-2); outline-offset: 2px; }

/* Category buttons. */
.wiz-types { display: flex; flex-wrap: wrap; gap: 8px; }
.wiz-type {
  padding: 9px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-alt);
  color: var(--text-muted);
  font: inherit;
  font-size: 0.84rem;
  font-weight: 600;
  cursor: pointer;
}
.wiz-type:hover { color: var(--text); }
/* The chosen category's own colour is set inline from constants/events.ts, and
   an inline style outranks this rule — so these are the fallback for the moment
   before it is applied, not a second opinion about what colour it should be. */
.wiz-type.is-on { background: var(--primary); border-color: var(--primary); color: #fff; }

/* Banner, at the ratio the feed and the event page use. */
.wiz-banner-frame {
  aspect-ratio: 16 / 9;
  width: 100%;
  margin-bottom: 14px;
  border-radius: var(--radius-sm);
  background: var(--surface-alt);
  overflow: hidden;
}
.wiz-banner-img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wiz-banner-empty {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
  font-size: 0.82rem;
}
.wiz-file { font-size: 0.84rem; color: var(--text-muted); }

/* Committee list. */
.wiz-member {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  cursor: pointer;
}
.wiz-member + .wiz-member { border-top: 1px solid var(--border); }
.wiz-member-name { flex: 1; font-size: 0.9rem; color: var(--text); }
.wiz-member-roles { font-size: 0.76rem; color: var(--text-faint); }
.wiz-check { width: 18px; height: 18px; accent-color: var(--primary); }

/* Review lines. The label column is fixed so the values line up down the card
   instead of starting somewhere different on every row. */
.wiz-line { display: flex; align-items: flex-start; gap: 16px; padding: 5px 0; }
.wiz-line-label { width: 132px; flex: none; font-size: 0.8rem; line-height: 1.45; color: var(--text-faint); }
.wiz-line-value { flex: 1; font-size: 0.86rem; line-height: 1.45; color: var(--text); }
.wiz-line-value.is-empty { color: var(--text-faint); font-style: italic; }

.wiz-review-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0;
  margin-bottom: 10px;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.wiz-review-head .wiz-card-title { margin: 0; }
.wiz-review-edit { color: var(--primary-2); font-size: 0.82rem; font-weight: 600; }

.wiz-foot {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 22px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

@media (max-width: 560px) {
  .wiz-line { flex-direction: column; gap: 2px; }
  .wiz-line-label { width: auto; }
}

/* ---------------------------------------------- selects, dates and times */
/* `.field` styled inputs and textareas and stopped there, so every <select> on
   the dashboard fell back to the browser's own control: white, system font,
   nothing to do with the page around it. A date or time input had the same
   problem one layer down — the field itself inherited nothing, and the picker
   that drops out of it is painted by the browser from `color-scheme`, which
   defaults to light. Declaring it dark is what makes the calendar and the clock
   match the site, and it keeps the native behaviour that matters most here:
   you can still type the date instead of hunting for it. */

.field select {
  width: 100%;
  padding: 12px 38px 12px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background-color: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.95rem;
  cursor: pointer;
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
  /* The browser's own arrow is drawn in its own palette, so it is replaced
     rather than tolerated. */
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a94a6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px 16px;
}
.field select:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgb(46 144 250 / 0.18);
}
/* The dropdown list itself is an OS menu; only its colours can be influenced. */
.field select option { background: var(--surface); color: var(--text); }

.field input[type='date'],
.field input[type='time'],
.field input[type='number'] { color-scheme: dark; }

/* File input: the button half is a browser control, so it gets the same
   treatment as a small ghost button rather than being left as-is. */
.wiz-file { color: var(--text-muted); }
.wiz-file::file-selector-button {
  margin-right: 12px;
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-alt);
  color: var(--text);
  font: inherit;
  font-size: 0.84rem;
  font-weight: 600;
  cursor: pointer;
}
.wiz-file::file-selector-button:hover { border-color: var(--primary); color: var(--primary-2); }

/* One ticket add-on. */
.wiz-addon {
  padding: 14px;
  margin-bottom: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
}
.wiz-addon .field:last-of-type { margin-bottom: 10px; }

/* --------------------------------------------------- date and time pickers */
/* Drawn rather than borrowed from the browser — see assets/js/pickers.js for
   why none of dd/mm/yyyy, "no typing" and 24-hour time can be asked of a
   native date or time input. */

.wiz-picker { position: relative; }
.wiz-picker-button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.95rem;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.wiz-picker-button:hover { border-color: var(--primary); }
.wiz-picker-button:focus-visible {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgb(46 144 250 / 0.18);
}
.wiz-picker-placeholder { color: var(--text-faint); }
.wiz-picker-icon { opacity: 0.6; font-size: 0.9rem; }

.wiz-cal {
  position: absolute;
  z-index: 20;
  top: calc(100% + 6px);
  left: 0;
  width: 280px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  box-shadow: 0 18px 40px rgb(0 0 0 / 0.45);
}
.wiz-cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.wiz-cal-title { font-size: 0.88rem; font-weight: 600; color: var(--text); }
.wiz-cal-nav {
  width: 28px;
  height: 28px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-alt);
  color: var(--text);
  font: inherit;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.wiz-cal-nav:hover { border-color: var(--primary); color: var(--primary-2); }
.wiz-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.wiz-cal-weekday {
  text-align: center;
  padding: 4px 0;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-faint);
}
.wiz-cal-pad { display: block; }
.wiz-cal-day {
  padding: 7px 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 0.82rem;
  cursor: pointer;
}
.wiz-cal-day:hover:not(.is-off) { background: var(--surface-alt); }
.wiz-cal-day.is-on { background: var(--primary); color: #fff; font-weight: 700; }
/* A past day is shown, not hidden: the month still has to read like a month. */
.wiz-cal-day.is-off { color: var(--text-faint); opacity: 0.4; cursor: not-allowed; }

.wiz-time { display: flex; align-items: center; gap: 8px; }
.wiz-time-part {
  flex: 1;
  padding: 12px 34px 12px 14px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background-color: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.95rem;
  cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a94a6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 15px 15px;
}
.wiz-time-part:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgb(46 144 250 / 0.18);
}
.wiz-time-part option { background: var(--surface); color: var(--text); }
.wiz-time-colon { color: var(--text-muted); font-weight: 700; }

/* The organiser's own row: ticked, and not a choice. */
.wiz-member.is-fixed { cursor: default; }
.wiz-member.is-fixed .wiz-member-name { color: var(--text-muted); }
.wiz-member .wiz-check:disabled { opacity: 0.65; cursor: default; }

/* ------------------------------------------------------------- home widgets */
/* Four tiles and a rail, instead of three counters above a collapsed list. The
   tiles are buttons, not cards with a link in them: the whole surface is the
   target, which is what people try first anyway. */

.home-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}
.home-head h1 { margin: 0 0 4px; }
.home-head .view-sub { margin: 0; }

.scope { display: flex; align-items: center; gap: 8px; flex: none; }
.scope > span { font-size: 0.78rem; color: var(--text-faint); }
.scope-select {
  padding: 8px 32px 8px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background-color: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 0.86rem;
  font-weight: 600;
  cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238a94a6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 15px 15px;
}
.scope-select:focus { outline: none; border-color: var(--primary); }
.scope-select option { background: var(--surface); color: var(--text); }

.home-grid { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); gap: 20px; align-items: start; }
.tile-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; }

.tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 190px;
  padding: 24px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.18s ease, transform 0.18s ease, background 0.18s ease;
}
.tile:hover { border-color: var(--primary); transform: translateY(-2px); }
.tile:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgb(46 144 250 / 0.18); }
.tile-title {
  font-family: var(--font-head);
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text-muted);
}
.tile-value { display: flex; align-items: baseline; gap: 7px; margin-top: auto; }
.tile-value strong {
  font-family: var(--font-head);
  font-size: 2.6rem;
  font-weight: 800;
  line-height: 1;
  color: var(--text);
}
.tile-unit { font-size: 0.82rem; color: var(--text-muted); }
.tile-sub { font-size: 0.82rem; line-height: 1.5; color: var(--text-faint); }

/* A thin accent per tile, so the four are told apart at a glance without
   needing four icons. */
.tile-community { border-top: 2px solid #2e90fa; }
.tile-interact { border-top: 2px solid #1fae6e; }
.tile-past { border-top: 2px solid #a24be0; }
.tile-finances { border-top: 2px solid #e8a33d; }

.rail {
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}
.rail-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.rail-head h2 { font-family: var(--font-head); font-size: 0.95rem; margin: 0; }

.view-actions { display: flex; gap: 10px; margin-bottom: 16px; }
.money { font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text); }

@media (max-width: 900px) {
  .home-grid { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .tile-grid { grid-template-columns: 1fr; }
  .home-head { flex-direction: column; align-items: stretch; }
}

/* ------------------------------------------- interact, members and the rail */

/* A question and its answer field stack; the row's default is side by side. */
.row.row-stack { flex-direction: column; align-items: stretch; gap: 10px; }
.answer-row { display: flex; gap: 8px; }
.answer-row input {
  flex: 1;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
}
.answer-row input:focus { outline: none; border-color: var(--primary); }

.member-search {
  width: 100%;
  margin-bottom: 12px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
}
.member-search:focus { outline: none; border-color: var(--primary); }

/* The rail holds every active event, so it gets its own scroll rather than
   stretching the page past the tiles beside it.

   `overflow-x: hidden` is not belt-and-braces: `overflow-y: auto` alone makes
   the box scrollable in BOTH directions, and two things in here are wider than
   the column — a long event name, and the 2px nudge each row takes on hover.
   So a horizontal bar appeared under a list that had nothing to scroll to
   sideways. The names are truncated here rather than everywhere, because this
   is the only place a row is this narrow. */
.rail .row-list { max-height: 520px; overflow-y: auto; overflow-x: hidden; }
.rail .row-title,
.rail .row-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rail .list-toggle { width: 100%; margin-top: 10px; }

/* Saving a community's details: the button and what became of it. */
.save-row { display: flex; align-items: center; gap: 12px; margin-top: 4px; }
.save-note { font-size: 0.84rem; color: var(--text-muted); }
.save-note.is-ok { color: #1fae6e; }
.save-note.is-bad { color: #f87171; }

/* Accept / decline on a join request, and the notify checkbox on the forms. */
.decide-row { display: flex; gap: 8px; flex: none; }
.notify-row { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; cursor: pointer; }
.notify-row span { font-size: 0.88rem; color: var(--text); }

/* A community's two panels sit side by side above its member list, so they are
   wider and shorter than the home page's four — they are doors to a form, not
   numbers to read, so there is nothing in them that wants height. */
.tile-grid-wide { grid-template-columns: 1fr 1fr; margin-bottom: 20px; }
.tile-grid-wide .tile { min-height: 0; }
.tile-grid-wide .tile-value strong { font-size: 1.2rem; }
.tile-posting { border-top: 2px solid #3ec9ea; }
.tile-details { border-top: 2px solid #9aa7b0; }
@media (max-width: 760px) { .tile-grid-wide { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------------ dialogs */
/* Replaces the browser's confirm() and prompt() — see assets/js/dialog.js. */

.dlg-backdrop {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgb(5 8 16 / 0.62);
  backdrop-filter: blur(3px);
  animation: dlg-fade 0.14s ease-out;
}
.dlg {
  width: 100%;
  max-width: 440px;
  padding: 22px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: 0 24px 60px rgb(0 0 0 / 0.5);
  animation: dlg-rise 0.16s ease-out;
}
.dlg-title { font-family: var(--font-head); font-size: 1.05rem; margin: 0 0 10px; }
.dlg-text { margin: 0 0 10px; font-size: 0.9rem; line-height: 1.55; color: var(--text-muted); }
.dlg-input {
  width: 100%;
  margin: 4px 0 6px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
  resize: vertical;
}
.dlg-input:focus { outline: none; border-color: var(--primary); }
.dlg-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }

/* Destructive confirmations. The class was already in use on "Cancel event"
   and simply had no rule, so that button looked like any other. */
.btn-danger {
  background: #e5484d;
  border: 1px solid #e5484d;
  color: #fff;
}
.btn-danger:hover { background: #d13b40; border-color: #d13b40; }

@keyframes dlg-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes dlg-rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ------------------------------------------------------- community calendar */

.cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.cal-title { font-family: var(--font-head); font-size: 0.95rem; font-weight: 600; }
.cal-nav {
  width: 30px;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface-alt);
  color: var(--text);
  font: inherit;
  font-size: 1.05rem;
  line-height: 1;
  cursor: pointer;
}
.cal-nav:hover { border-color: var(--primary); color: var(--primary-2); }

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 4px;
}
.cal-weekday { padding: 2px 6px; font-size: 0.72rem; font-weight: 600; color: var(--text-faint); }
.cal-cell {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-height: 84px;
  padding: 6px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  min-width: 0;
}
.cal-cell.is-pad { border: 0; background: transparent; }
.cal-cell.is-past { opacity: 0.55; }
.cal-cell.is-today { border-color: var(--primary); }
.cal-day { font-size: 0.75rem; font-weight: 600; color: var(--text-muted); }
.cal-cell.is-today .cal-day { color: var(--primary-2); }

/* One event in a day: a coloured edge in its category colour, and its name cut
   to fit — the full name is on hover, and a click opens the event. */
.cal-chip {
  display: block;
  width: 100%;
  padding: 2px 6px;
  border: 0;
  border-left: 3px solid var(--chip);
  border-radius: 4px;
  background: color-mix(in srgb, var(--chip) 16%, transparent);
  color: var(--text);
  font: inherit;
  font-size: 0.72rem;
  text-align: left;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
}
.cal-chip:hover { background: color-mix(in srgb, var(--chip) 30%, transparent); }
.cal-chip.is-cancelled { text-decoration: line-through; opacity: 0.6; }
.cal-more { font-size: 0.68rem; color: var(--text-faint); padding-left: 2px; }

@media (max-width: 640px) {
  .cal-cell { min-height: 56px; padding: 4px; }
  .cal-chip { font-size: 0; height: 6px; padding: 0; border-left-width: 0; background: var(--chip); }
  .cal-more { display: none; }
}

/* ── Environment label: only the test dashboard shows it ─────────────────── */
.env-label {
  position: fixed;
  right: 12px;
  bottom: 12px;
  z-index: 1000;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  pointer-events: none;
}
