/* ==========================================================================
   Fonts (self-hosted, latin subsets only)
   Anton is display; Libre Franklin is a variable font covering 400-800.
   ========================================================================== */
@font-face {
  font-family: 'Anton';
  src: url('fonts/Anton-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Libre Franklin';
  src: url('fonts/LibreFranklin-Variable.woff2') format('woff2');
  font-weight: 400 800;
  font-style: normal;
  font-display: swap;
}

/* ==========================================================================
   Design tokens
   ========================================================================== */
:root {
  --bg:        #0a0a0a;
  --panel:     #111;
  --panel-2:   #161616;
  --panel-3:   #232323;
  --red:       #dc1e1e;
  --cream:     #e9e9e6;
  --muted-1:   #c9c9c4;
  --muted-2:   #b8b8b4;
  --muted-3:   #a8a8a4;
  --muted-4:   #8a8a86;
  --border-15: rgba(233, 233, 230, .15);
  --border-25: rgba(233, 233, 230, .25);
  --border-3:  rgba(233, 233, 230, .3);
  --border-4:  rgba(233, 233, 230, .4);

  --font-display: 'Anton', Impact, sans-serif;
  --font-body:    'Libre Franklin', -apple-system, BlinkMacSystemFont, 'Segoe UI',
                  Roboto, sans-serif;
}

/* ==========================================================================
   Base
   ========================================================================== */
* { box-sizing: border-box; }

/* Plain black on <html> so mobile overscroll/bounce reveals more wall, not the
   browser's default white. */
html { background: var(--bg); }

body {
  margin: 0;
  min-height: 100vh;
  /* Plain black wall - the ridge texture is applied *inside* the ticket frame
     below, so the poster reads as a printed sheet hung on a matte black wall
     rather than the whole page sharing one texture. */
  background: var(--bg);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Admin.html doesn't use the ticket frame (per design 7c). It needs its own
   top-level padding and centered text so the cards inside sit correctly. */
body.page-body {
  padding: 24px 16px 48px;
  text-align: center;
}

button { font-family: inherit; }
input, textarea { font-family: inherit; }

/* ==========================================================================
   Ticket frame + tape corners
   Wraps the poster-style screens (voting, gate, results). Admin stays
   frameless. The soft red radial glow at the top of the frame comes from the
   background gradient below.
   ========================================================================== */
.ticket-frame {
  position: relative;
  margin: 14px;
  padding: 56px 22px 30px;
  border: 2px solid var(--border-3);
  border-radius: 2px;
  min-height: calc(100vh - 28px);
  /* Two stacked backgrounds inside the frame: the red radial glow on top of
     the faint horizontal ridge texture. The ridge lives here (not on body)
     so the poster reads as a printed sheet distinct from the black wall
     around it. */
  background:
    radial-gradient(ellipse at 50% 0%, rgba(220, 30, 30, .22), transparent 58%),
    repeating-linear-gradient(0deg, var(--bg) 0 3px, var(--panel) 3px 6px);
}
.ticket-frame::before,
.ticket-frame::after {
  content: '';
  position: absolute;
  top: -12px;
  width: 44px;
  height: 18px;
  background: rgba(233, 233, 230, .28);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .3);
  z-index: 4;
}
.ticket-frame::before { left: 26px;  transform: rotate(-8deg); }
.ticket-frame::after  { right: 26px; transform: rotate(8deg); }

/* ==========================================================================
   Reusable primitives - pill badge, title, tagline, description, buttons,
   inputs, cards, section labels, dividers, starburst.
   ========================================================================== */

/* "One Night Only" / "Live Now" / "Live Results" chip above the title. */
.pill-badge {
  display: table;
  margin: 0 auto 14px;
  padding: 3px 10px;
  background: var(--cream);
  color: var(--red);
  border-radius: 2px;
  font-family: var(--font-body);
  font-weight: 800;
  font-size: 11px;
  letter-spacing: .3em;
  text-transform: uppercase;
}

/* Big poster headline. Use `.vs` on the middle word for the red accent. */
.poster-title {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 40px;
  line-height: .92;
  letter-spacing: .01em;
  color: var(--cream);
  text-align: center;
  text-transform: uppercase;
}
.poster-title .vs { color: var(--red); }

/* Red uppercase byline between title and description paragraph. */
.tagline {
  margin: 8px 0 20px;
  color: var(--red);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: .08em;
  text-align: center;
  text-transform: uppercase;
}

/* Long-form paragraph under the tagline. */
.poster-desc {
  margin: 0 0 24px;
  color: var(--muted-2);
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.55;
  text-align: center;
}

/* Big dashed-bordered action buttons: red primary, dark secondary. */
.dashed-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  padding: 18px;
  border: 2px dashed var(--cream);
  border-radius: 4px;
  color: var(--cream);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform .08s ease;
}
.dashed-btn:active   { transform: scale(.98); }
.dashed-btn:disabled { opacity: .4; cursor: not-allowed; }
.dashed-btn.red      { background: var(--red); }
.dashed-btn.dark     { background: var(--panel-3); }

.btn-stack {
  display: flex;
  flex-direction: column;
  gap: 11px;
}

/* Solid-red action button - no dashed border. Used in modals (Continue button
   on the photo-required interstitial) and anywhere the design shows a filled
   red CTA without the poster-style dashed frame. */
.solid-btn {
  display: block;
  width: 100%;
  padding: 16px;
  border: none;
  border-radius: 4px;
  color: var(--cream);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform .08s ease;
}
.solid-btn:active   { transform: scale(.98); }
.solid-btn:disabled { opacity: .4; cursor: not-allowed; }
.solid-btn.red      { background: var(--red); }
.solid-btn.dark     { background: var(--panel-3); }

/* "You have 4 of 5 votes left." - .count highlights the fraction. */
.votes-remaining {
  margin: 18px 0 6px;
  color: var(--muted-4);
  font-size: 12px;
  text-align: center;
  min-height: 18px;
}
.votes-remaining .count { color: var(--red); font-weight: 700; }

/* "✓ Vote counted for Houseband!" - also carries the vote-flow status
   messages (uploading, saving, etc.). See setStatus() in vote.js for the
   kind classes it applies. */
.vote-confirmation {
  margin: 0 0 20px;
  min-height: 18px;
  color: var(--muted-1);
  font-size: 12px;
  font-weight: 600;
  text-align: center;
}
.vote-confirmation.info    { color: var(--muted-1); font-weight: 500; }
.vote-confirmation.success { color: var(--muted-1); font-weight: 600; }
.vote-confirmation.error   { color: #ff9a9a; font-weight: 600; }

/* Uppercase micro-label used above sections and inputs. */
.section-label {
  margin-bottom: 11px;
  color: var(--red);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: .2em;
  text-transform: uppercase;
}

/* Horizontal dashed rule separating major sections within a card. */
.section-divider {
  margin-top: 6px;
  padding-top: 18px;
  border-top: 2px dashed var(--border-25);
}

/* Rotated red "Vote Now" badge sticking out from the right edge of the ticket
   frame, tilted counter-clockwise so it looks slapped-on. Placed a bit below
   the top corner so the tape-strip corners stay clean. */
.starburst {
  position: absolute;
  top: 96px;
  right: -6px;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 58px;
  height: 58px;
  border: 2px dashed var(--cream);
  border-radius: 50%;
  background: var(--red);
  transform: rotate(-15deg);
}
.starburst span {
  color: var(--cream);
  font-family: var(--font-display);
  font-size: 11px;
  line-height: 1.15;
  text-align: center;
  text-transform: uppercase;
}
.starburst[hidden] { display: none; }

/* ==========================================================================
   Photo feed grid
   Each tile starts as a striped placeholder with a "generating..." label. When
   feed.js's loadThumbnail resolves the 400x400 derivative from the resize-images
   extension, the placeholder is hidden and the image fades in. On persistent
   failure (retries exhausted, or an old photo without derivatives) the tile stays
   as the plain striped placeholder without the label.
   ========================================================================== */
.feed-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}

.feed-tile {
  position: relative;
  aspect-ratio: 1;
  border: 2px dashed rgba(233, 233, 230, .2);
  border-radius: 4px;
  background: repeating-linear-gradient(
    135deg, var(--panel-2) 0 6px, #1c1c1c 6px 12px
  );
  overflow: hidden;
  cursor: default;
}
.feed-tile.is-loaded { cursor: pointer; }

.feed-tile.is-loading::after {
  content: 'generating…';
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #7a7a76;
  font-family: ui-monospace, Menlo, monospace;
  font-size: 8.5px;
  letter-spacing: .02em;
}

.feed-photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .25s ease;
}
.feed-tile.is-loaded .feed-photo { opacity: 1; }

.feed-empty {
  grid-column: 1 / -1;
  padding: 20px 0;
  border: 2px dashed var(--border-15);
  border-radius: 4px;
  color: var(--muted-4);
  font-size: 12px;
  text-align: center;
}

/* ==========================================================================
   Poster-page links (e.g. "View live results →", "← Back to voting")
   ========================================================================== */
a.results-link {
  display: block;
  margin: 6px 0 18px;
  color: var(--muted-4);
  font-size: 12.5px;
  font-weight: 600;
  text-align: center;
  text-decoration: none;
}
a.results-link:hover { color: var(--cream); }

/* ==========================================================================
   Status message (gate + shared)
   Used by gate.js's #gate-status. Vote-flow status uses .vote-confirmation
   above; this is for the gate-specific states.
   ========================================================================== */
.status {
  margin-top: 16px;
  min-height: 20px;
  font-size: 13px;
  text-align: center;
}
.status.info    { color: var(--muted-3); }
.status.success { color: #7be07b; }
.status.error   { color: #ff9a9a; }

/* Hidden-attribute overrides. A plain #id selector would outrank the browser's
   default [hidden] { display: none } rule, so anything given display via a
   normal selector needs an explicit hidden override to actually hide when
   the attribute is set. Same class of bug guarded against elsewhere. */
.starburst[hidden],
#gate-screen[hidden],
#voting-content[hidden],
#results-content[hidden],
#admin-login[hidden],
#admin-panel[hidden] { display: none; }

/* ==========================================================================
   Results-page score bars - design 7a
   Team label + Anton count on the label row; a slim filled track below.
   results.js toggles .leader on whichever row is winning; the leader gets a
   red count + red bar fill, the trailing team gets muted grey. Ties: both
   muted.
   ========================================================================== */
.score-bars {
  margin: 0 0 20px;
}
.score-row + .score-row { margin-top: 16px; }

.score-label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 6px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 14px;
  color: var(--cream);
  text-transform: uppercase;
  letter-spacing: .04em;
}

.score-count {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--muted-1);
  transition: color .4s ease;
}
.score-row.leader .score-count { color: var(--red); }

.score-track {
  height: 16px;
  border: 1px solid var(--border-15);
  border-radius: 3px;
  background: var(--panel-3);
  overflow: hidden;
}

.score-fill {
  height: 100%;
  background: #5c5c58;
  transition: width .4s ease, background .4s ease;
}
.score-row.leader .score-fill { background: var(--red); }

/* ==========================================================================
   Lightbox - designs 9a (viewing) and 9b (delete confirm)
   Vertical stack: top bar (delete left, save+close right) -> stage with the
   photo + round prev/next side buttons -> Anton red counter at the bottom.
   The confirm dialog is a card absolutely positioned over the stage; opening
   it dims the underlying photo.
   ========================================================================== */
.lightbox-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  flex-direction: column;
  padding: 44px 16px 24px;
  background: #050505;
}
.lightbox-overlay.open { display: flex; }

.lightbox-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 0 4px 10px;
}
.lightbox-topbar-right {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}

/* Round dashed buttons in the top row. */
.lightbox-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  color: var(--cream);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
}
.lightbox-btn.delete {
  border: 2px dashed var(--red);
  background: rgba(220, 30, 30, .15);
}
.lightbox-btn.delete[hidden] { display: none; }
.lightbox-btn.close,
.lightbox-btn.save {
  border: 2px dashed var(--border-4);
  background: rgba(255, 255, 255, .06);
}
.lightbox-btn:disabled { opacity: .5; cursor: default; }

/* Photo stage - the image fills what's left, prev/next float over the sides. */
.lightbox-stage {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: none;
  overflow: hidden;
}
.lightbox-img {
  max-width: 100%;
  max-height: 100%;
  border: 2px dashed rgba(233, 233, 230, .2);
  border-radius: 6px;
  object-fit: contain;
  touch-action: none;
  user-select: none;
  -webkit-user-drag: none;
  will-change: transform, filter;
  transition: filter .2s ease;
}
.lightbox-img.dimmed { filter: brightness(.4); }

.lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid rgba(233, 233, 230, .3);
  border-radius: 50%;
  background: rgba(0, 0, 0, .5);
  color: var(--cream);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
}
.lightbox-nav.prev { left: 4px; }
.lightbox-nav.next { right: 4px; }

.lightbox-counter {
  padding-top: 16px;
  color: var(--red);
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: .08em;
  text-align: center;
}

/* Confirmation dialog overlaid on the stage - design 9b. */
.lightbox-confirm {
  position: absolute;
  inset: 0;
  z-index: 1002;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
}
.lightbox-confirm[hidden] { display: none; }
.lightbox-confirm-card {
  width: 100%;
  max-width: 340px;
  padding: 24px 20px;
  border: 2px dashed var(--red);
  border-radius: 8px;
  background: #151515;
  box-shadow: 0 20px 50px rgba(0, 0, 0, .5);
  text-align: center;
}
.lightbox-confirm-desc {
  margin: 0 0 20px;
  color: var(--cream);
  font-size: 13px;
  line-height: 1.6;
}
.lightbox-confirm-actions {
  display: flex;
  gap: 10px;
}
.lightbox-confirm-actions button {
  flex: 1;
  padding: 13px;
  border-radius: 4px;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: pointer;
}
.lightbox-confirm-cancel {
  border: 2px dashed var(--border-4);
  background: transparent;
  color: var(--cream);
}
.lightbox-confirm-delete {
  border: none;
  background: var(--red);
  color: var(--cream);
}

/* ==========================================================================
   Modals (photo-required interstitial) - design 8b
   Dashed cream border on a dark card, red Anton heading, muted description,
   solid red CTA + underlined text link. The overlay blurs the underlying
   voting page so the poster peeks through behind the dialog.
   ========================================================================== */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 900;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: rgba(0, 0, 0, .55);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}
.modal-overlay:not([hidden]) { display: flex; }

.modal-box {
  width: 100%;
  max-width: 360px;
  padding: 26px 22px;
  border: 2px dashed var(--cream);
  border-radius: 8px;
  background: #151515;
  box-shadow: 0 20px 50px rgba(0, 0, 0, .5);
  text-align: center;
}

.modal-heading {
  margin: 0 0 14px;
  color: var(--red);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 22px;
  letter-spacing: .02em;
  text-transform: uppercase;
}

.modal-desc {
  margin: 0 0 22px;
  color: var(--muted-1);
  font-size: 13px;
  line-height: 1.6;
}

.modal-cancel {
  display: block;
  margin: 14px auto 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--muted-4);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}

/* ==========================================================================
   Admin panel - design 7c
   Ordered card layout: header row, "At a glance" stat tiles, Event controls,
   Setup & access, Activity log, Danger zone. Deliberately no ticket frame -
   this is the operational surface, not a poster.
   ========================================================================== */

.admin-body {
  padding: 24px 14px 40px;
  text-align: left;
}

.admin-shell {
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
}

/* Login screen (before signing in) - single centered card. */
.admin-login {
  background: radial-gradient(
    ellipse at 50% 0%, rgba(220, 30, 30, .16), transparent 55%
  );
  padding: 40px 22px 30px;
  border: 2px dashed var(--border-25);
  border-radius: 8px;
  text-align: center;
}
.admin-login .admin-title { margin-bottom: 12px; }
.admin-login-desc {
  margin: 0 0 22px;
  color: var(--muted-3);
  font-size: 12.5px;
  line-height: 1.55;
}

/* Signed-in header row. */
.admin-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 0 4px 14px;
  border-bottom: 2px dashed var(--border-25);
}
.admin-header-left  { text-align: left; }
.admin-header-right { text-align: right; }

.admin-title {
  margin: 0 0 4px;
  color: var(--cream);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 28px;
  letter-spacing: .01em;
  text-transform: uppercase;
  line-height: 1;
}

.back-link {
  color: var(--muted-4);
  font-family: var(--font-body);
  font-size: 11px;
  text-decoration: none;
}
.back-link:hover { color: var(--cream); }

.admin-email {
  margin-bottom: 6px;
  color: var(--muted-4);
  font-family: var(--font-body);
  font-size: 10.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  word-break: break-all;
}

/* Small outlined "Sign out" button. */
.ghost-btn {
  padding: 6px 10px;
  border: 1px solid var(--border-35);
  border-radius: 4px;
  background: transparent;
  color: var(--cream);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: uppercase;
  cursor: pointer;
}
.ghost-btn:hover { background: rgba(233, 233, 230, .06); }

/* A card in the admin panel (dashed cream border). */
.admin-card {
  padding: 16px;
  border: 2px dashed var(--border-25);
  border-radius: 8px;
}
.admin-card.danger { border-color: var(--red); margin-top: 6px; }

.admin-card-header { margin-bottom: 10px; }
.admin-card-subtitle {
  margin-top: 2px;
  color: var(--muted-4);
  font-size: 11px;
}
.admin-card-desc {
  margin: 0 0 12px;
  color: var(--muted-3);
  font-size: 12px;
  line-height: 1.5;
}

/* Stats grid - solid subtle borders on the tiles rather than dashed. Four
   dashed tiles crammed side-by-side read as one big cross-hatch on a phone;
   solid outlines here let the numbers and micro-labels breathe. */
.stats-panel {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  width: 100%;
  margin: 0;
}
.stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 12px 4px;
  border: 1px solid var(--border-3);
  border-radius: 6px;
  text-align: center;
}
.stat-value {
  color: var(--cream);
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1;
}
.stat-value.red { color: var(--red); }
.stat-label {
  margin-top: 4px;
  color: var(--muted-3);
  font-family: var(--font-body);
  font-size: 9.5px;
  text-transform: uppercase;
}

/* Venue form fields. */
.venue-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 8px;
}
.venue-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: left;
}
.venue-field > span {
  color: var(--muted-4);
  font-family: var(--font-body);
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.venue-field-radius { margin-bottom: 12px; }
.venue-field .text-input {
  padding: 9px;
  font-size: 11.5px;
}

/* Leaflet map container. A solid subtle border rather than dashed, because
   dashing this inside the Event Controls card (which is itself dashed) reads
   as visual noise - two nested dashed lines a hair apart. Solid keeps the
   frame legible without competing with the card. */
.venue-map {
  width: 100%;
  aspect-ratio: 16 / 9;
  min-height: 180px;
  margin: 0 0 14px;
  border: 1px solid var(--border-15);
  border-radius: 6px;
  overflow: hidden;
}
.leaflet-container { background: var(--panel-2); }

.venue-current {
  margin: 0 0 12px;
  color: var(--muted-4);
  font-size: 11px;
  text-align: left;
}

.venue-btn-row {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}
.venue-btn-row.venue-btn-row-primary { margin-bottom: 0; }
.venue-btn-row .dashed-btn,
.venue-btn-row .solid-btn {
  flex: 1;
  padding: 12px 6px;
  font-size: 11px;
  letter-spacing: .04em;
}

/* Downgrade interior "dashed" buttons inside admin cards to a subtle solid
   outline. The outer card is already dashed cream; nesting another dashed
   line inside it (only ~16px away) reads as busy noise on a phone. The
   poster-style voting buttons on index.html keep their loud dashed cream
   borders - those *are* the hero elements of their screen, not an interior
   detail of a card. */
.admin-card .dashed-btn {
  border-style: solid;
  border-width: 1px;
  border-color: var(--border-3);
}

/* ==========================================================================
   Preview mode callout - sits at the bottom of Event Controls.
   Turns bright red when active so admins can't forget to switch it off.
   ========================================================================== */
.preview-callout {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px solid var(--border-3);
  border-radius: 6px;
  transition: border-color .2s ease, background .2s ease;
}
.preview-callout.is-active {
  border-color: var(--red);
  background: rgba(220, 30, 30, .08);
}

.preview-toggle {
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  user-select: none;
}
.preview-toggle input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* iOS-style switch. Track shifts to red when the checkbox is checked. */
.preview-toggle-track {
  position: relative;
  flex: 0 0 auto;
  width: 40px;
  height: 22px;
  border-radius: 12px;
  background: var(--panel-3);
  border: 1px solid var(--border-3);
  transition: background .15s ease, border-color .15s ease;
}
.preview-toggle-thumb {
  position: absolute;
  top: 1px;
  left: 1px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--cream);
  transition: transform .15s ease;
}
.preview-toggle input:checked ~ .preview-toggle-track {
  background: var(--red);
  border-color: var(--red);
}
.preview-toggle input:checked ~ .preview-toggle-track .preview-toggle-thumb {
  transform: translateX(18px);
}
.preview-toggle input:focus-visible ~ .preview-toggle-track {
  outline: 2px solid var(--cream);
  outline-offset: 2px;
}

.preview-toggle-label {
  color: var(--cream);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.preview-callout.is-active .preview-toggle-label { color: var(--red); }

.preview-desc {
  margin: 10px 0 0;
  color: var(--muted-3);
  font-size: 11px;
  line-height: 1.5;
  text-align: left;
}

/* Invite form (email + Add button on the same row). */
.invite-form {
  display: flex;
  gap: 8px;
  max-width: none;
  margin: 0;
}
.invite-form .text-input {
  flex: 1;
  min-width: 0;
  padding: 10px;
  font-size: 11.5px;
}
.invite-add-btn {
  flex: 0 0 auto;
  width: auto;
  padding: 0 14px;
  font-size: 11.5px;
}
.invite-message-box {
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: none;
  margin: 10px 0 0;
}
.invite-message-text {
  width: 100%;
  resize: vertical;
  font-family: inherit;
  line-height: 1.4;
}

/* Reused text input in the admin cards. Cleaner form than the legacy style. */
.text-input {
  padding: 10px;
  border: 1px solid var(--border-25);
  border-radius: 4px;
  background: var(--panel-2);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 12px;
  min-width: 0;
}
.text-input:focus {
  outline: none;
  border-color: var(--red);
}

/* Activity log entries. */
.admin-log-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 280px;
  overflow-y: auto;
}
.admin-log-entry {
  padding-left: 10px;
  border-left: 2px solid var(--border-25);
  text-align: left;
}
.admin-log-meta {
  color: var(--muted-4);
  font-size: 10px;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.admin-log-body {
  margin-top: 2px;
  color: var(--muted-3);
  font-size: 11px;
  line-height: 1.35;
  word-break: break-word;
}
.admin-log-empty {
  padding: 10px 0;
  border-left: none;
  color: var(--muted-4);
  font-size: 11px;
  text-align: center;
  list-style: none;
}
