/* ===================================================================
   Jamez Timeline — global styles
   Palette: champagne gold, deep purple, ivory
   =================================================================== */
/* Brand fonts, self-hosted (FE-1). They used to load render-blocking from
   Google's CDN, and a venue captive portal that blocks it left the page blank
   until the request timed out: the same reason SortableJS is vendored in
   app.js. Latin subsets of the variable fonts (every weight in one file);
   anything outside Latin falls back to the system font in the stacks below.
   Inter and Manrope are SIL Open Font License. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/fonts/inter-latin-260c81a4759baf163c025001c4f27872.woff2?vsn=d") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url("/fonts/manrope-latin-938c6e8019b69313372c47dbb7a7c930.woff2?vsn=d") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* FE-3: the app is light. Without this, a phone in dark mode draws native
     date/time pickers with dark internals on our light page. */
  color-scheme: light;
  /* FE-11: one stacking scale. Toasts sit above modals so feedback for an
     action taken inside a modal is visible; the Day Mode alert pulse is on
     top of everything. Local stacking inside a component can still use 1. */
  --z-sticky: 9;
  --z-header: 10;
  --z-fab: 30;
  --z-sheet: 50;
  --z-drag-ghost: 90;
  --z-modal: 100;
  --z-toast: 200;
  --z-alert: 1000;
  --bg: #ffffff;
  --bg-soft: #faf7f1;
  --bg-panel: #f6f2ea;
  --ink: #1d142e;
  --ink-soft: #3b3050;
  --text: #262029;
  --muted: #6b6471;
  --border: #ece7dc;
  --border-strong: #d6ccb6;
  --gold: #e5cc9f;
  --gold-strong: #c9a961;
  --gold-deep: #a8862f;
  --gold-tint: rgba(201, 169, 97, 0.12);
  --gold-wash: rgba(201, 169, 97, 0.18);
  --black: #111111;
  --danger: #b03a3a;
  --success: #2f7d3c;
  /* A11Y-5: --warn is text on light surfaces and the delay banner's fill
     under white text; #915f0c clears 4.5:1 both ways (was 2.9:1). */
  --warn: #915f0c;
  /* Gold for *text* on light surfaces. The brand golds are for fills and
     borders: as text they measure 2.1 to 3.4:1. This is 5.0:1 or better on
     the page and panel backgrounds, and 4.54:1 on the #ece7dc hover fill. */
  --gold-text: #806419;

  /* Layered, warm-tinted elevation — softer than a single hard drop shadow. */
  --shadow-sm: 0 1px 2px rgba(29, 20, 46, 0.05), 0 1px 1px rgba(29, 20, 46, 0.03);
  --shadow-md: 0 4px 16px rgba(29, 20, 46, 0.07), 0 2px 6px rgba(29, 20, 46, 0.05);
  --shadow-lg: 0 18px 48px rgba(29, 20, 46, 0.16), 0 6px 16px rgba(29, 20, 46, 0.08);

  /* Rounder corners read as more contemporary. */
  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 18px;
  --radius-xl: 24px;
  --radius-pill: 999px;

  /* Fluid type scale — one modular ramp that breathes from phone to desktop. */
  --fs-display: clamp(1.9rem, 1.35rem + 2.6vw, 2.85rem);
  --fs-h1: clamp(1.5rem, 1.2rem + 1.5vw, 2rem);
  --fs-h2: clamp(1.25rem, 1.1rem + 0.8vw, 1.55rem);
  --fs-h3: clamp(1.02rem, 0.98rem + 0.3vw, 1.18rem);
  --fs-lg: 1.0625rem;
  --fs-base: 0.9375rem;
  --fs-sm: 0.8125rem;
  --fs-xs: 0.6875rem;

  /* Spacing rhythm for new/refreshed rules. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;

  --ring: 0 0 0 3px rgba(201, 169, 97, 0.4);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
html, body { margin: 0; padding: 0; }

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  color: var(--text);
  /* Warm ivory with a barely-there champagne wash from the top. */
  background:
    radial-gradient(1200px 480px at 50% -280px, var(--gold-tint), transparent 70%),
    var(--bg-soft);
  background-attachment: fixed;
  font-size: var(--fs-base);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Kill the grey flash on tap; we provide our own :active/:focus feedback. */
  -webkit-tap-highlight-color: transparent;
}

h1, h2, h3, h4, .brand, .brand-text {
  font-family: 'Manrope', 'Inter', -apple-system, sans-serif;
  color: var(--ink);
  font-weight: 700;
  letter-spacing: -0.018em;
  line-height: 1.15;
  text-wrap: balance;
}
h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }

a { color: var(--gold-text); text-decoration: none; }
a:hover { text-decoration: underline; }

input, button, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
.muted { color: var(--muted); }

/* Modern focus: a single champagne ring on keyboard focus only. */
:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--radius-sm);
}
a:focus-visible, button:focus-visible { border-radius: var(--radius-sm); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============ Header / brand ============ */
.site-header {
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: saturate(1.4) blur(12px);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--border);
  padding: 12px max(20px, env(safe-area-inset-right)) 12px max(20px, env(safe-area-inset-left));
  padding-top: calc(12px + env(safe-area-inset-top, 0px));
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  flex-wrap: wrap;
  gap: 12px;
}
.brand {
  font-size: 22px;
  letter-spacing: 0.02em;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
}
.brand-mark {
  display: inline-block;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--gold), var(--gold-strong));
  position: relative;
  flex-shrink: 0;
}
.brand-mark::after {
  content: ''; position: absolute; inset: 6px;
  border-radius: 50%;
  background: var(--ink);
}
.brand-sub {
  font-size: 12px;
  font-weight: 500;
  color: var(--muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-family: 'Inter', sans-serif;
}
.header-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

/* ----- Status indicators ----- */
.save-status {
  font-size: 12px;
  color: var(--muted);
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  background: var(--bg-soft);
  border-radius: 999px;
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
}
.save-status.is-saved { opacity: 1; }

.save-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); }
.save-status.is-error .save-dot { background: var(--danger); }
@keyframes pulse { 50% { opacity: 0.4; } }

.collaborators {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: 12px;
  color: var(--muted);
  padding: 4px 10px;
  background: var(--bg-soft);
  border-radius: 999px;
}
.collab-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--gold-strong);
  box-shadow: 0 0 0 2px #fff;
  margin-left: -3px;
}
.collab-count { margin-left: 8px; }

.drag-pill {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12px;
  color: var(--ink);
  padding: 4px 10px;
  background: rgba(229, 204, 159, 0.35);
  border: 1px solid var(--gold-strong);
  border-radius: 999px;
}
.drag-pill-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--gold-strong);
  animation: pulse 1s infinite;
}
.timeline.remote-drag-active {
  background: rgba(229, 204, 159, 0.06);
  border-radius: 8px;
  padding: 2px;
  transition: background 0.2s;
}

/* ----- Floating ghost of another user's dragged item ----- */
.remote-ghost {
  /* keep grid layout from the cloned block, but make it visually distinct */
  background: #fff !important;
  border: 2px solid var(--gold-strong) !important;
  border-left: 4px solid var(--gold-strong) !important;
  box-shadow: 0 12px 32px rgba(29, 20, 46, 0.25);
  opacity: 0.92;
  transition: top 0.05s linear, left 0.05s linear;
  transform: rotate(-0.5deg);
}
.remote-ghost-label {
  position: absolute;
  bottom: 100%;
  left: 0;
  margin-bottom: 6px;
  padding: 3px 10px;
  background: var(--ink);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  border-radius: 999px;
  white-space: nowrap;
  pointer-events: none;
}

.last-edit {
  font-size: 12px;
  color: var(--text);
  padding: 4px 10px;
  background: var(--bg-soft);
  border-radius: 999px;
  /* The editor label can be long ("DJ (name@example.com)"); cap it so it
     stops dominating the top bar. Full text is in the title tooltip. */
  max-width: 220px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.role-tag {
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
}

/* ============ Buttons ============ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 9px 15px;
  border-radius: var(--radius);
  border: 1px solid var(--border-strong);
  background: #fff;
  color: var(--ink);
  font-weight: 600;
  font-size: 13.5px;
  line-height: 1.2;
  box-shadow: var(--shadow-sm);
  transition: background 0.15s var(--ease), border-color 0.15s var(--ease),
              box-shadow 0.15s var(--ease), transform 0.08s var(--ease);
  text-decoration: none;
  white-space: nowrap;
}
.btn:hover { background: var(--bg-panel); border-color: var(--gold-strong); text-decoration: none; }
.btn:active { transform: translateY(1px); box-shadow: none; }
.btn-primary {
  background: linear-gradient(160deg, #ecd8ac, var(--gold-strong));
  border-color: var(--gold-strong);
  color: var(--ink);
}
.btn-primary:hover {
  background: linear-gradient(160deg, var(--gold-strong), var(--gold-deep));
  border-color: var(--gold-deep);
  color: var(--ink);
}
.btn-dark { background: var(--black); border-color: var(--black); color: #fff; }
.btn-dark:hover { background: #2a2236; border-color: #2a2236; color: #fff; }
.btn-danger { background: #fff; border-color: var(--danger); color: var(--danger); }
.btn-danger:hover { background: var(--danger); color: #fff; }
.btn-ghost {
  background: transparent;
  border: 1px dashed var(--border-strong);
  color: var(--muted);
  width: 100%;
  justify-content: center;
  padding: 14px;
}
.btn-ghost:hover { border-color: var(--gold-strong); color: var(--ink); background: var(--bg-panel); }

.btn-icon {
  background: transparent;
  border: none;
  padding: 4px;
  color: var(--muted);
  border-radius: 4px;
  font-size: 15px;
}
.btn-icon:hover { color: var(--ink); background: var(--bg-soft); }
.btn-icon.active { color: var(--ink); background: var(--gold); }

.btn-icon-text {
  background: transparent;
  border: none;
  padding: 4px 8px;
  color: var(--muted);
  border-radius: 6px;
  font-size: 12.5px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  text-decoration: none;
}
.btn-icon-text:hover { color: var(--ink); background: var(--bg-soft); text-decoration: none; }
.btn-icon-text.muted { color: var(--muted); }
.event-card-expired {
  display: inline-flex; align-items: center;
  padding: 6px 10px;
  font-size: var(--fs-sm);
  color: var(--muted);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-pill);
}
.share-expired {
  margin: 0 0 14px;
  padding: 10px 12px;
  font-size: var(--fs-sm);
  color: var(--ink-soft);
  background: var(--gold-tint);
  border: 1px solid var(--gold);
  border-radius: var(--radius-sm);
}
.btn-icon-text.danger { color: var(--danger); }
.btn-icon-text.danger:hover { background: #fde7e7; color: #7a1d1d; }

.btn-pill {
  display: inline-flex;
  align-items: center;
  padding: 8px 16px;
  border-radius: 999px;
  background: #fff;
  border: 1px solid var(--border-strong);
  color: var(--ink);
  font-weight: 600;
  font-size: 13px;
  text-decoration: none;
}

/* ============ Landing page ============ */
.landing {
  min-height: calc(100vh - 70px);
  min-height: calc(100dvh - 70px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
}
.landing-card {
  max-width: 480px;
  width: 100%;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 40px;
  box-shadow: var(--shadow-md);
  text-align: center;
}
.landing-card h1 { font-size: 28px; margin: 0 0 8px; }
.landing-card p { color: var(--muted); margin: 0 0 24px; }
.landing-form { display: flex; flex-direction: column; gap: 12px; }
.landing-fineprint { font-size: 12px; margin-top: 18px; }

.input {
  width: 100%;
  padding: 11px 13px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: #fff;
  font-size: 14px;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
  font-family: inherit;
}
.input:focus, .input:focus-visible {
  outline: none;
  border-color: var(--gold-strong);
  box-shadow: var(--ring);
}

/* ============ Dashboard ============ */
.dashboard {
  max-width: 1280px;
  margin: 0 auto;
  padding: 32px 28px 60px;
}
.dashboard-head { margin-bottom: 24px; }
.dashboard-head h1 { font-size: 28px; margin: 0; }
.dashboard-head p { margin: 6px 0 0; }

.event-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 16px;
}

/* Event hub — cards for Timeline + each form */
.hub-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 14px;
}
.hub-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 20px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  text-decoration: none;
  color: inherit;
  transition: transform 0.12s var(--ease), box-shadow 0.12s var(--ease), border-color 0.12s var(--ease);
}
.hub-card:hover {
  border-color: var(--gold-strong);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  text-decoration: none;
}
.hub-card-icon {
  font-size: 28px;
  width: 52px; height: 52px;
  flex-shrink: 0;
  background: var(--bg-soft);
  border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
}
.hub-card-body { flex: 1; min-width: 0; }
.hub-card-body h3 { font-size: var(--fs-h3); margin: 0 0 3px; color: var(--ink); }
.hub-card-body p { margin: 0; font-size: 13px; color: var(--muted); }
.hub-card-arrow { font-size: 22px; color: var(--muted); flex-shrink: 0; }
.hub-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 20px; }

/* Assigned-form card with DJ reorder/remove controls */
.hub-card-wrap { display: flex; align-items: stretch; gap: 8px; }
.hub-card-wrap .hub-card { flex: 1; min-width: 0; }
.hub-card-controls { display: flex; flex-direction: column; justify-content: center; gap: 4px; }

/* DJ "send a form" assignment picker on the hub */
/* Per-event guest tipping switch (DJ only). Sits below the form-assign row as
   an event setting, not a navigation card, so it is deliberately quieter than
   .hub-card and does not lift on hover. */
.hub-tips {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 16px;
  padding: 16px 20px;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.hub-tips-main { flex: 1; min-width: 200px; }
.hub-tips-main h3 { font-size: var(--fs-h3); margin: 0 0 3px; color: var(--ink); }
.hub-tips-main p { margin: 0; font-size: 13px; }
.hub-tips-toggle {
  flex-shrink: 0;
  padding: 10px 18px;
  min-height: 44px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: #fff;
  font-family: inherit;
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  transition: background 0.12s var(--ease), border-color 0.12s var(--ease), color 0.12s var(--ease);
}
.hub-tips-toggle.is-on { background: var(--gold); border-color: var(--gold-strong); color: #1d142e; }
.hub-tips-toggle.is-off { color: var(--muted); }
.hub-tips-toggle:disabled { opacity: 0.55; cursor: not-allowed; }

.hub-assign { margin-top: 16px; }
.hub-assign form { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.hub-assign label { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.hub-assign select { max-width: 320px; }
.hub-assign p { margin: 0; }
.hub-empty-forms { margin-top: 16px; }

/* Forms index (list of a DJ's saved forms) */
.dashboard-head.with-action { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.dashboard-head.with-action > div { min-width: 0; }
.form-list { display: flex; flex-direction: column; gap: 12px; }
.form-list-row {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px 18px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  box-shadow: var(--shadow-sm);
}
.form-list-main { min-width: 0; }
.form-list-main h3 { font-size: 16px; margin: 0 0 3px; color: var(--ink); }
.template-tag { display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--gold-text); background: var(--bg-soft); border: 1px solid var(--border); border-radius: 999px; padding: 1px 8px; margin-left: 6px; vertical-align: middle; }

/* Form tags (DJ-side library organization) */
.tag-filter { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.tag-row { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 8px; }
.tag-chip {
  font-size: 13px; font-weight: 600; color: var(--ink);
  background: #fff; border: 1px solid var(--border); border-radius: 999px;
  padding: 4px 12px; cursor: pointer; transition: all 0.12s;
}
.tag-chip:hover { border-color: var(--gold-strong); }
.tag-chip.active { background: var(--ink); color: #fff; border-color: var(--ink); }
.tag-chip.small { font-size: 11px; padding: 2px 9px; cursor: default; color: var(--muted); }
.tag-chip.small:hover { border-color: var(--border); }
.form-list-main p { margin: 0; font-size: 13px; }
.form-list-actions { display: flex; gap: 8px; flex-shrink: 0; }

/* Form builder (field editor) */
.builder-fields { display: flex; flex-direction: column; gap: 14px; margin-top: 18px; }
.builder-field {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px 18px;
  box-shadow: var(--shadow-sm);
}
.builder-field-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.builder-field-num { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.builder-field-move { display: flex; gap: 4px; }
.builder-field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.builder-field-required { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; margin-top: 10px; cursor: pointer; }
.builder-field-required input { width: auto; }
@media (max-width: 560px) { .builder-field-row { grid-template-columns: 1fr; } }

/* Builder: large question label (preview feel) */
.builder-label { font-size: 16px; font-weight: 600; margin-bottom: 12px; }
.builder-sub-label { display: block; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); margin: 12px 0 6px; }

/* Builder: dynamic option rows */
.builder-options { margin-top: 4px; }
.builder-option { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.builder-option .input { flex: 1; }
.opt-glyph { width: 20px; text-align: center; color: var(--muted); flex-shrink: 0; }
.btn-link { background: none; border: none; color: var(--gold-text); font-size: 13px; font-weight: 600; cursor: pointer; padding: 4px 0; }
.btn-link:hover { text-decoration: underline; }

/* Builder: conditional-visibility row */
.builder-condition { margin-top: 4px; }
.builder-condition-row { display: flex; gap: 8px; flex-wrap: wrap; }
.builder-condition-row .input { flex: 1; min-width: 120px; }

/* Builder: section divider element */
.builder-section { background: var(--bg-soft); border-style: dashed; }
.builder-section-title { font-size: 16px; font-weight: 700; }

/* Builder: add-element buttons */
.builder-add { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
/* Hidden first submit button so Enter re-parses instead of firing a real action */
.builder-enter-guard { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); border: 0; opacity: 0; }

/* Client form: section headers + radio/checkbox groups */
.form-section-title {
  font-size: 15px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--gold-text); margin: 22px 0 4px; padding-top: 14px;
  border-top: 1px solid var(--border);
}
.form-fill .form-section-title:first-child { border-top: none; padding-top: 0; margin-top: 0; }
.choice-list { display: flex; flex-direction: column; gap: 8px; }
.choice-option { display: flex; align-items: center; gap: 10px; font-size: 15px; cursor: pointer; }
.choice-option input { width: auto; margin: 0; flex-shrink: 0; }
.event-card {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  gap: 14px 16px;
  box-shadow: var(--shadow-sm);
  transition: transform 0.12s, box-shadow 0.12s, border-color 0.12s;
}
.event-card:hover {
  border-color: var(--gold-strong);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}
.event-card-icon {
  font-size: 36px;
  width: 56px; height: 56px;
  background: var(--bg-soft);
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.event-card-body { min-width: 0; }
.event-card-body h3 { font-size: 17px; margin: 0 0 4px; }
.event-card-body h3 a { color: var(--ink); }
.event-card-body h3 a:hover { text-decoration: none; color: var(--gold-text); }
.event-card-type { font-size: 12px; color: var(--muted); margin: 0 0 6px; text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; }
.event-card-meta { font-size: 13px; color: var(--muted); margin: 0; display: flex; gap: 6px; flex-wrap: wrap; }
.event-card-actions {
  grid-column: 1 / -1;
  border-top: 1px solid var(--border);
  padding-top: 12px;
  margin-top: 4px;
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.empty-state {
  padding: 40px 20px;
  text-align: center;
  color: var(--muted);
  border: 2px dashed var(--border-strong);
  border-radius: var(--radius);
  background: #fff;
}
.empty-state h3 { margin: 0 0 6px; font-size: 16px; color: var(--ink); }
.empty-state p { margin: 0 0 14px; font-size: 13px; }
.empty-state.large { padding: 80px 20px; }
.empty-state.large h3 { font-size: 22px; }

/* ============ Archived events ============ */
.archived-section { margin-top: 32px; border-top: 1px solid var(--border); padding-top: 16px; }
.archived-summary {
  cursor: pointer;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0;
}
.archived-summary::-webkit-details-marker { display: none; }
.archived-summary::before { content: "▸"; color: var(--muted); font-size: 12px; }
.archived-section[open] .archived-summary::before { content: "▾"; }
.archived-help { font-size: 12.5px; margin: 8px 0 12px; max-width: 60ch; }
.archived-list { display: flex; flex-direction: column; gap: 6px; }
.archived-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.archived-name { font-weight: 600; color: var(--ink); font-size: 14px; }
.archived-meta { font-size: 12.5px; margin-left: auto; }
.archived-row .btn-icon-text { flex-shrink: 0; }

/* ============ Modal ============ */
.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(29, 20, 46, 0.45);
  backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-modal);
  padding: 20px;
  /* FE-13: keep a modal's buttons above the home indicator. */
  padding-bottom: max(20px, env(safe-area-inset-bottom));
}
.modal {
  background: #fff;
  border-radius: var(--radius-xl);
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: var(--shadow-lg);
}
/* FE-6: a modal or the mobile library sheet scrolled past its end used to
   carry on into the page (iOS) or trigger pull-to-refresh (Android), which
   reloads and drops the LiveView socket mid-edit. */
.modal, .library.library-open { overscroll-behavior: contain; }
.modal-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 18px 24px;
  border-bottom: 1px solid var(--border);
}
.modal-head h2 { font-size: 20px; margin: 0; }
.modal-body { padding: 20px 24px; display: flex; flex-direction: column; gap: 16px; }
.modal-actions {
  display: flex; justify-content: flex-end; gap: 10px;
  padding-top: 4px;
}

.field { display: flex; flex-direction: column; gap: 6px; }
.field label, .field .field-label {
  font-size: 11px; font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.field-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; }
@media (max-width: 600px) { .field-row { grid-template-columns: 1fr; } }

.type-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 8px;
}
.type-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 12px 8px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  cursor: pointer;
  background: #fff;
  text-align: center;
  font-size: 12px;
  transition: all 0.12s;
}
.type-tile input { position: absolute; opacity: 0; }
.type-tile:has(input:checked) {
  border-color: var(--gold-strong);
  background: var(--bg-soft);
  box-shadow: 0 0 0 3px rgba(229, 204, 159, 0.25);
}
.type-icon { font-size: 22px; }
.type-name { font-weight: 600; color: var(--ink); }

/* ============ Editor toolbar ============ */
.toolbar {
  background: #fff;
  border-bottom: 1px solid var(--border);
  padding: 16px 28px;
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 0.9fr 0.9fr 1.4fr;
  gap: 12px;
  align-items: end;
}
.toolbar.readonly { display: flex; gap: 24px; font-size: 14px; padding: 14px 28px; color: var(--text); }
@media (max-width: 1200px) { .toolbar { grid-template-columns: 1fr 1fr 1fr; } }
@media (max-width: 720px)  { .toolbar { grid-template-columns: 1fr 1fr; } }
.field .input { padding: 8px 10px; font-size: 14px; }

/* ============ Workspace layout ============ */
.workspace {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 20px;
  padding: 20px 28px 60px;
  max-width: 1500px;
  margin: 0 auto;
}
/* When there's no library (vendor / read-only), the timeline takes the
   whole row instead of getting jammed into the 280px column. */
.workspace.workspace-full { grid-template-columns: 1fr; max-width: 1100px; }
@media (max-width: 960px) {
  .workspace { grid-template-columns: 1fr; padding: 16px; }
}

/* ============ Library (left panel) ============ */
.library {
  position: sticky;
  top: 78px;
  max-height: calc(100vh - 100px);
  overflow-y: auto;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 12px;
  box-shadow: var(--shadow-sm);
}
.library-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  padding: 8px 4px 6px;
}
.library-sub {
  font-size: 11.5px;
  color: var(--muted);
  padding: 0 4px 8px;
}
.category { margin-bottom: 2px; }
.preset-event {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  font: inherit;
  color: inherit;
  text-align: left;
  padding: 8px 12px;
  margin: 2px 0;
  border-radius: 6px;
  cursor: grab;
  font-size: 13.5px;
  background: var(--bg-soft);
  border: 1px solid transparent;
  transition: background 0.12s, border-color 0.12s;
}
.preset-event:hover { background: #fff; border-color: var(--gold-strong); }
.preset-event:active { cursor: grabbing; }
.preset-event:focus-visible { outline: none; box-shadow: var(--ring); background: #fff; }
.preset-event .duration { font-size: 14px; color: var(--gold-text); font-weight: 700; }
.preset-event.sortable-ghost { opacity: 0.4; }
.preset-event.sortable-drag { background: var(--gold); border-color: var(--gold-strong); box-shadow: var(--shadow-md); }

.template-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 4px;
  border-bottom: 1px solid var(--bg-soft);
  font-size: 13px;
}
.template-name { color: var(--ink); font-weight: 500; }
.template-actions { display: flex; gap: 4px; }

/* ============ Timeline (right panel) ============ */
.timeline-panel {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 22px;
  box-shadow: var(--shadow-sm);
  min-height: 400px;
}
.timeline-summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 14px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
  gap: 12px;
}
.summary-item { display: flex; flex-direction: column; }
.summary-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  font-weight: 600;
}
.summary-value {
  font-family: 'Manrope', sans-serif;
  font-size: 18px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.summary-value.warn { color: var(--warn); }
.summary-note { display: block; font-size: var(--fs-xs); color: var(--warn); }

.timeline {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 100px;
  position: relative;
  padding-left: 26px;
}
/* Signature: a continuous champagne spine linking every item — the product's
   core object (the timeline) made literal. The rail lives in the container's
   left gutter, and each block hangs a node dot on it, so the mobile two-row
   block reflow can't break the alignment. */
.timeline::before {
  content: "";
  position: absolute;
  left: 10px;
  top: 10px;
  bottom: 10px;
  width: 2px;
  border-radius: 2px;
  background: linear-gradient(var(--gold-strong), var(--gold-wash));
  pointer-events: none;
}
.block::before {
  content: "";
  position: absolute;
  left: -21px;
  top: 21px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid var(--gold-strong);
  box-shadow: 0 0 0 3px var(--bg-soft);
  z-index: 1;
}
.block.completed::before { background: var(--gold-strong); }
.block.skipped::before { border-color: var(--border-strong); box-shadow: 0 0 0 3px var(--bg-soft); }
.remote-ghost::before { display: none; }
@media (max-width: 640px) {
  .timeline { padding-left: 20px; }
  .timeline::before { left: 7px; }
  .block::before { left: -18px; top: 17px; }
}

.block {
  display: grid;
  /* handle | time | title | duration | move (editors) | actions */
  grid-template-columns: 24px 86px 1fr auto auto auto;
  align-items: center;
  gap: 10px;
  padding: 12px 12px 12px 6px;
  background: #fff;
  border: 1px solid var(--border);
  border-left: 4px solid var(--gold);
  border-radius: var(--radius);
  transition: box-shadow 0.15s, border-color 0.15s;
  position: relative;
}
.block:hover { box-shadow: var(--shadow-sm); }
.block.sortable-ghost { opacity: 0.3; }
.block.sortable-chosen { box-shadow: var(--shadow-md); }
.block.locked { background: var(--bg-soft); }
.block.locked .drag-handle { cursor: not-allowed; opacity: 0.4; }
.block.completed { opacity: 0.7; }
.block.completed .block-name { text-decoration: line-through; }
.block.skipped { opacity: 0.5; background: repeating-linear-gradient(135deg, #fff, #fff 8px, var(--bg-soft) 8px, var(--bg-soft) 16px); }

.block-form { display: contents; }
.block-main {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.block-icon {
  font-size: 18px;
  line-height: 1;
  width: 24px;
  text-align: center;
  flex-shrink: 0;
}

.drag-handle {
  cursor: grab;
  color: var(--muted);
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 18px;
  line-height: 1;
  user-select: none;
  /* Own the touch gesture on the handle so the drag doesn't fight page scroll
     or pop the iOS text-selection callout mid-drag. */
  touch-action: none;
  -webkit-touch-callout: none;
}
.drag-handle:active { cursor: grabbing; }
.block-time {
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-size: 15px;
}
.block-time .ampm { font-size: 11px; color: var(--muted); margin-left: 2px; font-weight: 600; }
.block-name {
  border: none;
  background: transparent;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--text);
  padding: 4px 4px;
  border-radius: 4px;
  width: 100%;
  min-width: 0;
}
.block-name.readonly { padding: 0; }
.block-name:hover { background: var(--bg-soft); }
.block-name:focus {
  outline: none;
  background: var(--bg-soft);
  box-shadow: inset 0 -2px 0 var(--gold-strong);
}
.duration-input {
  display: inline-flex; align-items: center; gap: 3px;
  background: var(--bg-soft);
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 4px 6px;
  justify-self: end;
}
.duration-input.readonly { background: transparent; }
.duration-input:focus-within { border-color: var(--gold-strong); background: #fff; }
.duration-input input {
  width: 36px;
  border: none;
  background: transparent;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-size: 13px;
  padding: 0;
}
.duration-input input:focus { outline: none; }
.duration-input .unit {
  font-size: 10px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.block-actions { display: flex; gap: 2px; justify-content: flex-end; }
/* A11Y-1: the keyboard's reorder. Quiet next to the drag handle. */
.block-move { display: flex; gap: 2px; }
.move-btn { font-size: 13px; padding: 4px 5px; }
.move-btn:disabled { opacity: 0.3; cursor: default; }
.move-btn:disabled:hover { background: transparent; color: var(--muted); }
.btn-icon:focus-visible { outline: none; box-shadow: var(--ring); }
.accordion-toggle .chevron {
  display: inline-block;
  font-size: 18px;
  line-height: 1;
  transition: transform 0.15s ease;
}
.accordion-toggle.open .chevron { transform: rotate(90deg); }
.block-locked-icon { font-size: 13px; color: var(--muted); }

/* ----- Item drawer ----- */
.item-drawer {
  grid-column: 1 / -1;
  margin-top: 10px;
  background: var(--bg-soft);
  border-radius: 10px;
  padding: 16px;
  border: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 14px;
}
/* UX-4: which fields a collapsed row is hiding. */
.item-flags { display: inline-flex; flex-shrink: 0; gap: 2px; font-size: 13px; line-height: 1; opacity: 0.85; }
/* UX-2: the vendor's text-only drawer (no inputs, never private notes). */
.item-drawer-readonly { display: grid; gap: 12px; }
.item-drawer-readonly .readonly-label {
  font-size: 11px; font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.item-drawer-readonly .readonly-value { margin: 2px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.readonly-intros { margin: 0; padding-left: 1.5em; line-height: 1.5; }
.readonly-intros li { overflow-wrap: anywhere; }
.readonly-intros li + li { margin-top: 2px; }
.drawer-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
@media (max-width: 800px) { .drawer-row { grid-template-columns: 1fr; } }
.drawer-actions { display: flex; gap: 8px; justify-content: flex-end; flex-wrap: wrap; }

/* Song autocomplete dropdown in the item drawer (iTunes-backed, like the guest
   request portal but light-themed to match the editor). */
.song-field { position: relative; }
.song-suggestions {
  display: flex;
  flex-direction: column;
  margin-top: 8px;
  max-height: 340px;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 6px;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.song-suggestion {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 8px;
  border: none;
  border-radius: var(--radius);
  background: transparent;
  text-align: left;
  cursor: pointer;
  /* reset UA button styling — the gray box / centered text without this */
  font: inherit;
  color: inherit;
  transition: background 0.1s var(--ease);
}
.song-suggestion + .song-suggestion { margin-top: 2px; }
.song-suggestion:hover,
.song-suggestion:focus-visible { background: var(--bg-soft); outline: none; }
.song-art {
  width: 48px;
  height: 48px;
  border-radius: 8px;
  flex-shrink: 0;
  object-fit: cover;
  box-shadow: var(--shadow-sm);
  background: var(--bg-panel);
}
.song-suggestion-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 1px;
}
.song-suggestion-title {
  font-weight: 600;
  font-size: 14px;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.song-suggestion-artist {
  font-size: 12.5px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Song *list* fields (must-play / do-not-play): saved entries stacked above a
   search box that appends. Shares .song-field positioning with the single-song
   input so the suggestions dropdown lands the same way. */
.song-list {
  list-style: none;
  margin: 0 0 8px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.song-list-entry {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg-soft);
  font-size: 14px;
}
.song-list-title { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.song-list-remove {
  flex: none;
  width: 22px; height: 22px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--muted);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
}
.song-list-remove:hover,
.song-list-remove:focus-visible { background: var(--line); color: var(--text); outline: none; }
.song-list-add { display: flex; gap: 8px; align-items: center; }
.song-list-add .input { flex: 1; min-width: 0; }
.song-list-add .btn { flex: none; }
/* Bulleted song lists wherever an answer is only read: the vendor's read-only
   view of a form, the print sheet, and Day Mode. A must-play list runs to dozens
   of titles; comma-joined into a paragraph it is unreadable. */
.detail-answer-list, .sheet-detail-list, .day-detail-list {
  margin: 2px 0 0;
  padding-left: 18px;
}
.detail-answer-list li, .sheet-detail-list li, .day-detail-list li { margin: 0 0 2px; }

.swatch-row { display: flex; flex-wrap: wrap; gap: 4px; }
.swatch {
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 2px solid transparent;
  cursor: pointer;
  padding: 0;
}
.swatch.active {
  border-color: var(--ink);
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px #fff inset;
}
.icon-swatch {
  width: 28px; height: 28px;
  border-radius: 6px;
  border: 1px solid transparent;
  background: #fff;
  cursor: pointer;
  font-size: 16px;
  display: inline-flex; align-items: center; justify-content: center;
}
.icon-swatch.active { border-color: var(--gold-strong); background: var(--gold); }

/* UX-1: the couple's form answers, collapsed above the timeline. */
.answers-panel {
  margin-bottom: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-soft);
}
.answers-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 44px;
  padding: 10px 14px;
  background: none;
  border: 0;
  font: inherit;
  font-weight: 600;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}
.answers-head:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--radius); }
.answers-head-main { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; min-width: 0; }
.answers-head-main .muted { font-weight: 400; font-size: var(--fs-sm); }
.answers-head .chevron { transition: transform 0.15s var(--ease); }
.answers-head .chevron.open { transform: rotate(90deg); }
.answers-body { padding: 0 14px 12px; }
.answers-form + .answers-form { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.answers-form-title { margin: 0 0 8px; font-size: var(--fs-sm); color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.answers-rows { display: grid; grid-template-columns: minmax(120px, 34%) 1fr; gap: 6px 14px; margin: 0; }
.answers-rows dt { color: var(--muted); font-size: var(--fs-sm); }
.answers-rows dd { margin: 0; overflow-wrap: anywhere; }
/* pre-wrap on the answer text only: on the <dd> it also keeps the template's
   indentation and pushes every answer down a few blank lines. */
.answers-value { white-space: pre-wrap; }
@media (max-width: 560px) {
  .answers-rows { grid-template-columns: 1fr; gap: 2px; }
  .answers-rows dd { margin-bottom: 8px; }
}

.event-notes {
  margin-top: 22px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.notes-label {
  display: block;
  font-size: 11px; font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-bottom: 6px;
}
.add-custom-wrap { margin-top: 12px; }

/* Client planning form (editor) */
.event-details {
  margin-top: 22px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}
.details-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.details-hint { font-size: 12px; color: var(--muted); }
.detail-field { margin-bottom: 14px; }
.detail-help { display: block; font-size: 12px; color: var(--muted); }
.detail-answer { margin: 0; white-space: pre-wrap; color: var(--text); }

/* Client form answers on the print sheet */
.sheet-detail { margin-bottom: 10px; break-inside: avoid; }
.sheet-detail strong { display: block; color: var(--ink); font-size: 13px; }
.sheet-detail p { margin: 2px 0 0; font-size: 13px; white-space: pre-wrap; }

/* ============ Day-of Mode ============ */
.day-page {
  min-height: 100vh;
  background: linear-gradient(180deg, #faf8f3 0%, #fff 240px);
  padding-bottom: 100px;
}
.day-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 16px;
  background: var(--ink);
  color: #fff;
  position: sticky; top: 0; z-index: var(--z-sticky);
}
.day-header .brand-mark { width: 28px; height: 28px; }
.day-header .btn-pill { background: rgba(255,255,255,0.12); border-color: transparent; color: #fff; }
.day-brand { display: flex; align-items: center; gap: 10px; min-width: 0; }
.day-event-name {
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  font-size: 15px;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 60vw;
}
.day-event-meta { font-size: 11px; color: rgba(255,255,255,0.7); }

.day-delay-banner {
  background: var(--warn);
  color: #fff;
  text-align: center;
  padding: 10px 16px;
  font-size: 14px;
  font-weight: 500;
}

.day-main {
  max-width: 720px;
  margin: 0 auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.day-label {
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
  padding: 4px 4px;
  margin-bottom: 6px;
  display: flex;
  justify-content: space-between;
}

.day-card {
  background: #fff;
  border: 1px solid var(--border);
  border-left: 5px solid var(--gold);
  border-radius: var(--radius-lg);
  padding: 18px;
  box-shadow: var(--shadow-sm);
}
.day-card-now {
  border-left-width: 6px;
  box-shadow: var(--shadow-md);
}
.day-card-time {
  font-family: 'Manrope', sans-serif;
  font-weight: 800;
  font-size: 28px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.day-card-time .ampm { font-size: 14px; color: var(--muted); margin-left: 4px; font-weight: 700; }
.day-card-title {
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  font-size: 22px;
  color: var(--ink);
  margin: 10px 0 4px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.day-card-icon { font-size: 28px; }
.day-card-desc { color: var(--muted); margin: 4px 0 0; }

.day-announce {
  margin-top: 14px;
  padding: 14px;
  background: var(--ink);
  color: #fff;
  border-radius: 10px;
}
.day-announce.subtle { background: var(--bg-soft); color: var(--ink); }
.day-announce-label {
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  opacity: 0.7;
  margin-bottom: 6px;
}
.day-announce-text { font-size: 17px; line-height: 1.5; margin: 0; }
/* The entrance script: same reading size as the announcement, one intro per
   numbered line. A long unbroken name wraps inside the card at 360px instead
   of widening the page. */
.day-intros-list { margin: 0; padding-left: 1.6em; font-size: 17px; line-height: 1.5; }
.day-intros-list li { overflow-wrap: anywhere; }
.day-intros-list li + li { margin-top: 6px; }
.day-intros-list li::marker { font-weight: 800; }

.day-notes {
  margin-top: 12px;
  padding: 12px;
  background: var(--bg-soft);
  border-radius: 10px;
  font-size: 14px;
}
.day-notes-label {
  font-size: 11px; font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--muted);
  margin-bottom: 4px;
}
.day-notes p { margin: 0; }

/* Per-item song, surfaced large on the Day Mode Now/Next card. Gold to pop off
   the dark card; the "subtle" variant on the Next card is quieter. */
.day-song {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-top: 12px;
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  font-size: 19px;
  color: var(--gold);
}
.day-song .day-song-title { min-width: 0; overflow-wrap: anywhere; }
.day-song.subtle { font-size: 15px; font-weight: 600; opacity: 0.82; }

/* Overrun banner — like the delay banner but red, since running past the venue
   hard stop is more urgent than merely running behind the plan. */
.day-overrun-banner { background: var(--danger); }

.day-actions {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 10px;
  margin-top: 16px;
}
.day-btn {
  padding: 18px;
  border-radius: 14px;
  border: 1px solid var(--border-strong);
  background: #fff;
  font-weight: 700;
  font-size: 16px;
  color: var(--ink);
  cursor: pointer;
  min-height: 60px;
  transition: transform 0.06s, background 0.12s;
}
.day-btn:active { transform: scale(0.98); }
.day-btn.primary { background: var(--ink); color: #fff; border-color: var(--ink); }
.day-btn.primary:hover { background: #2a2236; }
.day-btn.delay { background: var(--gold); border-color: var(--gold-strong); }
.day-btn.delay.subtle { background: #fff; color: var(--muted); }

.day-delays { margin-top: 14px; }
.day-delays-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-bottom: 8px;
}
.day-delay-buttons { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }

.day-list {
  margin-top: 12px;
  background: #fff;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  overflow: hidden;
}
.day-list-head {
  padding: 12px 16px;
  font-weight: 700;
  font-size: 13px;
  background: var(--bg-soft);
  border-bottom: 1px solid var(--border);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.day-list-row {
  display: grid;
  grid-template-columns: 80px 1fr 30px;
  gap: 10px;
  align-items: center;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.day-list-row:last-child { border-bottom: none; }
.day-list-row.is-current { background: var(--bg-soft); font-weight: 600; }
.day-list-row.completed { opacity: 0.55; text-decoration: line-through; }
.day-list-row.skipped { opacity: 0.45; }

/* Tapping a row jumps the Now card to it — receptions reorder constantly.
   The feedback colour is set per theme below; --bg-soft is a light token and
   Day Mode runs dark in a dark room. :hover is guarded to real pointers
   because touch browsers leave it stuck after a tap. */
.day-list-row.tappable { cursor: pointer; }
@media (hover: hover) {
  .day-list-row.tappable:hover { background: var(--bg-soft); }
}
.day-list-row.tappable:active { background: var(--bg-soft); }
/* The song under a row title: present but quieter than the title. */
.day-list-name .day-song {
  display: inline-block;
  margin-top: 2px;
  font-size: 13px;
  font-weight: 500;
  opacity: 0.7;
  overflow-wrap: anywhere;
}
.day-list-row.completed .day-song,
.day-list-row.skipped .day-song { text-decoration: none; }

/* Nothing to run through yet. */
.day-empty { padding: 28px 20px; text-align: center; }
.day-empty-title { font-size: 17px; font-weight: 700; margin-bottom: 6px; }
.day-empty-desc { font-size: 14px; opacity: 0.75; margin: 0 0 16px; line-height: 1.5; }
.day-list-time {
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  font-size: 13px;
}
.day-list-time .ampm { font-size: 10px; color: var(--muted); margin-left: 2px; }
.day-list-icon { margin-right: 8px; }
.day-list-status { text-align: right; color: var(--gold-strong); font-weight: 700; }

/* Client-form answers surfaced in Day Mode (dark). Reuses .day-list container. */
.day-details { margin-top: 12px; }
.day-detail { padding: 12px 16px; border-bottom: 1px solid #322a42; }
.day-detail:last-child { border-bottom: none; }
.day-detail-label {
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em;
  color: #a89eb0; margin-bottom: 4px;
}
.day-detail-value { margin: 0; white-space: pre-wrap; color: #e7e0d3; font-size: 14px; }

/* ---- Day Mode dark theme ----
   Day Mode is run one-handed in dark venues; a bright white screen blinds the
   DJ and the room. These overrides (same single-class specificity, later in the
   file) recolor the surface dark. The mic-script announce goes gold-on-dark so
   the thing to say out loud is the highest-contrast element on screen. */
.day-page { background: #16101f; color: #f2ede2; }
.day-header { background: #0f0a17; }
/* Keep the sticky header clear of the iPhone notch/status bar (viewport-fit=cover). */
.day-header { padding-top: calc(14px + env(safe-area-inset-top, 0px)); }
.day-header .btn-pill { background: rgba(255,255,255,0.14); color: #fff; }
.day-card { background: #211a30; border-color: #322a42; }
.day-card-now { box-shadow: 0 8px 28px rgba(0,0,0,0.45); }
.day-card-time, .day-card-title { color: #f4efe4; }
.day-card-time .ampm, .day-card-desc { color: #a89eb0; }
.day-label, .day-delays-label { color: #a89eb0; }
.day-announce { background: var(--gold); color: #1d142e; }
.day-announce.subtle { background: #2b2340; color: #f2ede2; }
.day-notes { background: #2b2340; color: #e7e0d3; }
.day-notes-label { color: #a89eb0; }
.day-btn { background: #2b2340; color: #f2ede2; border-color: #453a5c; }
.day-btn.primary { background: #f2ede2; color: #1d142e; border-color: #f2ede2; }
.day-btn.primary:hover { background: #fff; }
.day-btn.delay { background: var(--gold); color: #1d142e; border-color: var(--gold-strong); }
.day-btn.delay.subtle { background: #2b2340; color: #a89eb0; border-color: #453a5c; }
.day-list { background: #211a30; border-color: #322a42; }
.day-list-head { background: #2b2340; border-bottom-color: #322a42; color: #a89eb0; }
.day-list-row { border-bottom-color: #322a42; }
.day-list-row.is-current { background: #2b2340; }
@media (hover: hover) {
  .day-list-row.tappable:hover { background: #2b2340; }
}
.day-list-row.tappable:active { background: #2b2340; }
.day-list-time { color: #e7e0d3; }
.day-list-time .ampm { color: #a89eb0; }
.day-list-status { color: var(--gold); }

/* ---- Day Mode connection + undo bars ---- */
.day-offline-banner {
  display: none;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 16px;
  background: #7a1d1d;
  color: #fff;
  font-size: 13.5px;
  font-weight: 600;
  text-align: center;
}
/* app.js toggles body.ws-down when the LiveView socket drops after connecting. */
body.ws-down .day-offline-banner { display: flex; }

.day-undo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 14px;
  padding: 12px 16px;
  background: #2b2340;
  border: 1px solid #453a5c;
  border-radius: 12px;
  color: #f2ede2;
  font-size: 14px;
}
.day-undo-btn {
  flex-shrink: 0;
  padding: 10px 18px;
  border-radius: 10px;
  border: 1px solid var(--gold-strong);
  background: var(--gold);
  color: #1d142e;
  font-weight: 700;
  font-size: 14px;
  cursor: pointer;
  min-height: 44px;
}

/* ============ Day Mode: song-request queue ============ */
.day-head-actions { display: flex; align-items: center; gap: 8px; }
.req-count {
  display: inline-block;
  margin-left: 6px;
  min-width: 20px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--gold);
  color: #1d142e;
  font-weight: 800;
  font-size: 12px;
  text-align: center;
}
.day-requests {
  max-width: 720px;
  margin: 0 auto;
  padding: 16px;
}
.day-requests-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.day-requests-title { font-family: 'Manrope', sans-serif; font-weight: 800; font-size: 20px; }

/* Queue-pressure warning: the per-event cap turns guests away silently. */
.req-queue-warning {
  margin: 10px 0;
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.4;
  color: #f6e2b4;
  background: rgba(214, 160, 44, 0.16);
  border: 1px solid rgba(214, 160, 44, 0.45);
}
.req-queue-warning.full {
  color: #ffd9d4;
  background: rgba(198, 64, 48, 0.2);
  border-color: rgba(198, 64, 48, 0.55);
}
.req-pin-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  min-height: 34px;
  border-radius: 999px;
  border: 1px solid var(--gold-strong);
  background: #241c33;
  color: #f2ede2;
  font-size: 14px;
  cursor: pointer;
}
.req-pin-chip strong { color: var(--gold); letter-spacing: 0.08em; font-size: 14px; }
.req-peek-controls .req-pin-chip { font-size: 13px; }

/* Dark modal to match Day Mode (e.g. the booth-QR PIN dialog). */
.day-modal { background: #1c1528; border: 1px solid #322a42; color: #f2ede2; }
.day-modal .modal-head { border-bottom-color: #322a42; }
.day-modal .modal-head h2 { color: #f4efe4; }
.day-modal .btn-icon { color: #a89eb0; }
.day-modal .btn-icon:hover { color: #fff; background: #2b2340; }
.day-modal .muted { color: #a89eb0; }
.day-modal label { color: #cdbfe0; }
.day-modal .input { background: #211a30; border-color: #453a5c; color: #f2ede2; }
.day-modal .input::placeholder { color: #8a8098; }
.day-modal .input:focus { border-color: var(--gold-strong); box-shadow: none; }
.day-modal .btn { background: #2b2340; border-color: #453a5c; color: #f2ede2; }
.day-modal .btn:hover { background: #34294c; border-color: var(--gold-strong); }
.day-modal .btn-primary { background: var(--gold); border-color: var(--gold-strong); color: #1d142e; }
.day-modal .btn-primary:hover { background: var(--gold-strong); }
.day-modal .btn-danger { background: transparent; border-color: #6b2f3f; color: #ff9aa2; }
.day-modal .btn-danger:hover { background: #3a1c22; color: #ffb4b4; }
.day-requests-empty { color: #a89eb0; font-size: 14px; text-align: center; padding: 24px 12px; }
.day-requests-empty a { color: var(--gold); }
.day-requests-hint { color: #8a8098; font-size: 12.5px; text-align: center; margin-top: 10px; }
.day-requests-hint .hint-touch { display: none; }
.day-requests-hint .hint-pointer { display: inline; }
@media (hover: none), (pointer: coarse) {
  .day-requests-hint .hint-touch { display: inline; }
  .day-requests-hint .hint-pointer { display: none; }
}

.req-list { display: flex; flex-direction: column; gap: 8px; }
.req-card {
  display: flex; align-items: center; gap: 12px;
  padding: 12px; border-radius: 12px;
  background: #211a30; border: 1px solid #322a42;
  touch-action: pan-y;
}
.req-card.status-played { opacity: 0.55; }
.req-card.status-rejected { opacity: 0.4; }
.req-art { width: 52px; height: 52px; border-radius: 8px; flex-shrink: 0; object-fit: cover; }
.req-main { flex: 1; min-width: 0; }
.req-title { font-weight: 700; font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.req-artist { font-size: 13.5px; color: #a89eb0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.req-guest { font-size: 12.5px; color: #8a8098; margin-top: 2px; }
.req-note { font-size: 13px; color: #cdbfe0; font-style: italic; margin-top: 2px; }
.req-actions { display: flex; gap: 8px; flex-shrink: 0; }

/* Touch devices triage by swiping, so the ✓/✕ buttons are redundant there and
   cost real width on a phone card — width the song title needs, next to the
   very element you are meant to swipe.
   Visually hidden rather than `display: none`, deliberately: a screen reader
   intercepts swipe gestures, so its user would otherwise have no way at all to
   act on a request. They also come back on keyboard focus. */
@media (hover: none), (pointer: coarse) {
  .req-actions:not(:focus-within) {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
}
.req-btn {
  width: 46px; height: 46px; border-radius: 50%;
  border: 1px solid #453a5c; background: #2b2340;
  font-size: 18px; font-weight: 800; cursor: pointer;
}
.req-btn.play { background: #1c3a22; border-color: #2f6b3f; color: #7fdca0; }
.req-btn.reject { background: #3a1c22; border-color: #6b2f3f; color: #ff9aa2; }
.req-badge { flex-shrink: 0; font-size: 13px; font-weight: 700; color: #a89eb0; }
.req-badge.played { color: #7fdca0; }

/* ============ Guest song-request portal ============ */
.rq-page {
  min-height: 100vh;
  min-height: 100dvh;
  background: #16101f;
  color: #f2ede2;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: max(20px, env(safe-area-inset-top)) 16px max(40px, env(safe-area-inset-bottom));
}
.rq-card { width: 100%; max-width: 440px; padding-top: 24px; }
.rq-brand {
  font-family: 'Manrope', sans-serif;
  font-weight: 800;
  font-size: 22px;
  margin-bottom: 6px;
}
.rq-muted { color: #a89eb0; font-size: 14px; margin: 4px 0 16px; }
.rq-big { font-size: 26px; font-weight: 800; margin: 0 0 8px; font-family: 'Manrope', sans-serif; }
.rq-error { color: #ffb4b4; font-size: 14px; margin-top: 10px; }

.rq-input {
  width: 100%;
  padding: 14px 16px;
  font-size: 16px; /* no iOS zoom */
  border-radius: 12px;
  border: 1px solid #453a5c;
  background: #211a30;
  color: #f2ede2;
  font-family: inherit;
}
.rq-input::placeholder { color: #8a8098; }
.rq-input:focus { outline: none; border-color: var(--gold-strong); }

.rq-btn {
  width: 100%;
  margin-top: 12px;
  padding: 14px 18px;
  border-radius: 12px;
  border: 1px solid #453a5c;
  background: #2b2340;
  color: #f2ede2;
  font-weight: 700;
  font-size: 16px;
  min-height: 48px;
  cursor: pointer;
}
.rq-btn-primary { background: var(--gold); color: #1d142e; border-color: var(--gold-strong); }
.rq-pin-form { display: flex; gap: 8px; }
.rq-pin-form .rq-btn { width: auto; margin-top: 0; flex-shrink: 0; }
.rq-pin { text-align: center; letter-spacing: 0.2em; }

/* Guest tip button. Subordinate to "Send request" on purpose: a guest came to
   this page to request a song, and the tip is an afterthought they may ignore.
   Hence the separating rule, the outline treatment, and the auto width rather
   than the full-bleed .rq-btn. */
.rq-tip {
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid #332a47;
  text-align: center;
}
.rq-tip-btn {
  display: inline-block;
  padding: 12px 22px;
  min-height: 44px;
  border-radius: 999px;
  border: 1px solid var(--gold-strong);
  background: transparent;
  color: var(--gold);
  font-weight: 700;
  font-size: 15px;
  text-decoration: none;
}
.rq-tip-btn:hover { background: var(--gold); color: #1d142e; text-decoration: none; }
.rq-tip-note { margin: 8px 0 0; font-size: 12px; color: #8a8098; }

.rq-search { position: relative; margin-bottom: 8px; }
/* UX-9: visible while LiveView has the search form in flight. */
.rq-searching {
  display: none;
  position: absolute; right: 14px; top: 50%; transform: translateY(-50%);
  font-size: var(--fs-sm); color: var(--muted);
  pointer-events: none;
}
.rq-search.phx-change-loading .rq-searching,
.rq-search.is-searching .rq-searching { display: block; }
.rq-typed { margin-top: 6px; border-style: dashed; }
.rq-suggestions { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
.rq-suggestion {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid #322a42;
  background: #211a30;
  color: #f2ede2;
  text-align: left;
  cursor: pointer;
  min-height: 56px;
}
.rq-suggestion:active { background: #2b2340; }
.rq-suggestion-main { display: flex; flex-direction: column; min-width: 0; }
.rq-suggestion-title { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rq-suggestion-artist { font-size: 13px; color: #a89eb0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rq-art-sm { width: 44px; height: 44px; border-radius: 6px; flex-shrink: 0; object-fit: cover; }

.rq-selected {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border-radius: 12px;
  border: 1px solid var(--gold-strong);
  background: #241c33;
  margin-bottom: 12px;
}
.rq-art { width: 56px; height: 56px; border-radius: 8px; flex-shrink: 0; object-fit: cover; }
.rq-selected-main { flex: 1; min-width: 0; }
.rq-selected-title { font-weight: 700; font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rq-selected-artist { font-size: 14px; color: #a89eb0; }
.rq-x {
  flex-shrink: 0;
  background: transparent;
  border: none;
  color: #a89eb0;
  font-size: 18px;
  padding: 8px;
  min-width: 40px;
  min-height: 40px;
  cursor: pointer;
}
.rq-form { display: flex; flex-direction: column; gap: 10px; }
.rq-closed, .rq-sent { margin-top: 24px; }

/* ============ Print sheet ============ */
.print-body { background: #f7f5ef; padding: 40px 20px; }
.print-toolbar {
  max-width: 800px;
  margin: 0 auto 20px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.sheet {
  max-width: 800px;
  margin: 0 auto;
  background: #fff;
  padding: 56px 64px 72px;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
}
.sheet-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  border-bottom: 3px solid var(--ink);
  padding-bottom: 18px;
  margin-bottom: 28px;
}
.brand-text {
  font-family: 'Manrope', sans-serif;
  font-weight: 800;
  font-size: 22px;
  color: var(--ink);
  letter-spacing: 0.02em;
}
.sheet-contact { text-align: right; font-size: 12px; color: var(--muted); }
.sheet-title {
  font-family: 'Manrope', sans-serif;
  font-weight: 800;
  font-size: 30px;
  color: var(--ink);
  margin: 0 0 6px;
  letter-spacing: -0.01em;
}
.sheet-meta {
  display: flex; gap: 22px;
  color: var(--muted); font-size: 13.5px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}
.sheet-meta strong { color: var(--ink); font-weight: 600; }
.sheet-section-title {
  font-family: 'Manrope', sans-serif;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  border-bottom: 1px solid var(--ink);
  padding-bottom: 6px;
  margin: 28px 0 12px;
}
.sheet-notes-block {
  background: var(--bg-soft);
  padding: 14px 16px;
  border-radius: 8px;
  margin-bottom: 12px;
}
.sheet-notes-block p { margin: 0; font-size: 13.5px; }

.sheet-table { width: 100%; border-collapse: collapse; }
.sheet-table thead th {
  text-align: left;
  font-family: 'Manrope', sans-serif;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  padding: 8px 8px;
  border-bottom: 2px solid var(--ink);
  font-weight: 700;
}
.sheet-table tbody td { padding: 12px 8px; border-bottom: 1px solid var(--border); vertical-align: top; }
.sheet-table .col-time {
  font-family: 'Manrope', sans-serif; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; white-space: nowrap;
  width: 90px; font-size: 15px;
}
.sheet-table .col-time .ampm { font-size: 10.5px; color: var(--muted); margin-left: 3px; font-weight: 600; }
.sheet-table .col-name { font-size: 14px; color: var(--text); }
.sheet-table .col-name strong { font-weight: 600; color: var(--ink); margin-left: 4px; }
.sheet-table .col-name .row-desc { font-size: 12px; color: var(--muted); margin-top: 3px; font-style: italic; }
.sheet-table .col-name .row-song { font-size: 12px; color: var(--gold-text); margin-top: 3px; font-weight: 600; }
.sheet-table .col-name .row-locked { font-size: 10px; margin-left: 6px; }
.sheet-table .col-category {
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  white-space: nowrap;
}
.sheet-table .col-duration {
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-size: 12.5px;
  white-space: nowrap;
  width: 70px;
}
.sheet-table .empty { padding: 24px; text-align: center; color: var(--muted); font-style: italic; }

.sheet-announcement {
  border-left: 3px solid var(--gold);
  padding: 10px 14px;
  margin-bottom: 12px;
  background: var(--bg-soft);
  border-radius: 0 6px 6px 0;
  break-inside: avoid;
}
.ann-head { display: flex; justify-content: space-between; margin-bottom: 6px; font-size: 12px; color: var(--muted); font-weight: 600; }
.ann-time { font-family: 'Manrope', sans-serif; }
.ann-title { color: var(--ink); }
.ann-text { font-size: 14px; margin: 0; line-height: 1.55; }
.ann-intros { margin: 0; padding-left: 1.5em; font-size: 14px; line-height: 1.55; }
.ann-text + .ann-intros { margin-top: 8px; }
.ann-intros li { overflow-wrap: anywhere; }

.sheet-notes { margin-bottom: 12px; font-size: 13px; }
.sheet-notes strong { display: block; margin-bottom: 4px; color: var(--ink); }
.sheet-notes p { margin: 0; color: var(--muted); }

.sheet-footer {
  margin-top: 36px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  font-size: 11.5px;
  color: var(--muted);
}

.sheet-page-break { page-break-before: always; }

@media print {
  .print-body { background: #fff; padding: 0; }
  .print-toolbar { display: none; }
  .sheet { border: none; box-shadow: none; padding: 28px 32px; max-width: none; }
  .sheet-table tbody tr { page-break-inside: avoid; }
  .sheet-announcement { page-break-inside: avoid; }
}

/* ============ Auth forms + Settings ============ */
.form-error {
  background: #fdecec;
  color: var(--danger);
  border: 1px solid #f4cfcf;
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 13px;
  margin-bottom: 12px;
  text-align: left;
}
.landing-cta-row { display: flex; gap: 10px; margin-bottom: 6px; }

.settings-card {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 24px;
  box-shadow: var(--shadow-sm);
  max-width: 720px;
}
.settings-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 18px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 18px;
}
.settings-title {
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  font-size: 15px;
  color: var(--ink);
  margin-bottom: 4px;
}
.settings-help { font-size: 13px; margin: 4px 0 0; }
.settings-help code {
  background: var(--bg-soft);
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 12px;
}
.settings-actions { display: flex; gap: 10px; margin-top: 4px; }
/* Roomier action buttons to match the spacious settings cards. */
.settings-actions .btn { padding: 10px 18px; font-size: 14px; }

/* ============ Tabs (Settings) ============
   Pure-CSS radio tabs: the panel and its tab-button light up from the checked
   radio (which the server pre-checks per ?tab= so a form redirect lands back on
   the right tab). Radios are visually hidden but keyboard-focusable. */
.tabs { max-width: 760px; }
.tab-radio {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.tab-bar {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 22px;
  overflow-x: auto;
  scrollbar-width: none;
}
.tab-bar::-webkit-scrollbar { display: none; }
.tab-btn {
  padding: 10px 18px;
  cursor: pointer;
  font-weight: 600;
  font-size: 14px;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  white-space: nowrap;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}
.tab-btn:hover { color: var(--ink); background: var(--bg-panel); }
.tab-panel { display: none; }

#tab-profile:checked ~ .tab-bar label[for="tab-profile"],
#tab-booth:checked ~ .tab-bar label[for="tab-booth"],
#tab-templates:checked ~ .tab-bar label[for="tab-templates"],
#tab-admin:checked ~ .tab-bar label[for="tab-admin"] {
  color: var(--ink);
  border-bottom-color: var(--gold-strong);
}
#tab-profile:focus-visible ~ .tab-bar label[for="tab-profile"],
#tab-booth:focus-visible ~ .tab-bar label[for="tab-booth"],
#tab-templates:focus-visible ~ .tab-bar label[for="tab-templates"],
#tab-admin:focus-visible ~ .tab-bar label[for="tab-admin"] {
  box-shadow: var(--ring);
  border-radius: var(--radius-sm);
}
#tab-profile:checked ~ #panel-profile,
#tab-booth:checked ~ #panel-booth,
#tab-templates:checked ~ #panel-templates,
#tab-admin:checked ~ #panel-admin { display: block; }

.tab-panel .settings-card { margin-bottom: 16px; }
.tab-panel .settings-card:last-child { margin-bottom: 0; }

/* Inline template-rename form — a plain input + button on the row baseline
   (unlike .pw-form, which is a padded box inside the admin password details). */
.rename-form { display: flex; gap: 8px; align-items: center; margin: 0; }
.rename-form .input { max-width: 280px; }

.qr-block { display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }
.qr-image { flex-shrink: 0; width: 220px; height: 220px; background: #fff; border-radius: 12px; padding: 8px; border: 1px solid var(--border); }
.qr-image svg { display: block; width: 100%; height: 100%; }
.qr-meta { flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 10px; }

/* Toggle switch */
.toggle {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
}
.toggle input { position: absolute; opacity: 0; pointer-events: none; }
.toggle-track {
  width: 44px; height: 24px;
  background: var(--border-strong);
  border-radius: 999px;
  position: relative;
  transition: background 0.15s;
  flex-shrink: 0;
}
.toggle-thumb {
  width: 20px; height: 20px;
  background: #fff;
  border-radius: 50%;
  position: absolute;
  top: 2px; left: 2px;
  transition: transform 0.15s;
  box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
.toggle input:checked + .toggle-track { background: var(--gold-strong); }
.toggle input:checked + .toggle-track .toggle-thumb { transform: translateX(20px); }
.toggle-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}

/* ----- Flash ----- */
.phx-flash { position: fixed; top: 14px; right: 14px; z-index: var(--z-toast); }
.phx-flash > * {
  padding: 10px 16px;
  border-radius: 8px;
  background: var(--ink);
  color: #fff;
  font-size: 13px;
  margin-bottom: 6px;
  box-shadow: var(--shadow-md);
}

.flash {
  padding: 12px 16px;
  border-radius: 8px;
  font-size: 14px;
  margin-bottom: 14px;
  border: 1px solid var(--border);
}
.flash-info { background: var(--bg-soft); color: var(--ink); }
.flash-error { background: #fde7e7; color: #7a1d1d; border-color: #f3c2c2; }
/* Toasts in the fixed flash group are click-to-dismiss and slide in. */
.phx-flash > * { cursor: pointer; max-width: 340px; animation: flash-in 0.18s ease-out; }
@keyframes flash-in { from { opacity: 0; transform: translateY(-6px); } }

/* ----- Impersonation banner ----- */
.impersonation-banner {
  background: #2a1d4a;
  color: #fff;
  padding: 10px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 13px;
  flex-wrap: wrap;
}
.impersonation-banner strong { color: #ffd66b; }
.impersonation-stop {
  color: #fff;
  text-decoration: underline;
  font-weight: 600;
}

/* ----- Share modal (one "Share" button collapses the 3 link actions) -----
   The header used to carry Client/Vendor/Requests copy buttons + two floating
   re-issue icons — the bar's biggest space hog. They now live behind a single
   labeled "🔗 Share" button that opens this dialog (reusing .modal). */
.share-modal .modal-body { gap: 10px; }
.share-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-soft);
}
.share-row-info { margin-right: auto; min-width: 0; }
.share-row-name { font-weight: 700; color: var(--ink); font-size: 14px; }
.share-row-hint { font-size: 12px; color: var(--muted); margin-top: 2px; }
.share-row .btn { flex-shrink: 0; }
.share-revoke { flex-shrink: 0; color: var(--gold-deep); }
.share-revoke:hover { background: var(--bg-panel); }

/* Direct links — one row per destination inside the event (timeline, each
   assigned form), with a copy button per role. Tighter than the event-level
   rows above: there are more of them and each is a single line. */
.share-direct { margin-top: 18px; }
.share-direct-head {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.share-direct-hint { font-size: 12px; color: var(--muted); margin: 2px 0 10px; }
.share-row-direct { padding: 9px 14px; gap: 8px; }
.share-row-direct .share-row-name { font-weight: 600; }
.share-row-direct .btn { padding: 5px 12px; font-size: 12.5px; }
@media (max-width: 520px) {
  .share-row-direct { flex-wrap: wrap; }
  .share-row-direct .share-row-info { flex-basis: 100%; margin-bottom: 6px; }
}

/* ----- Users table (admin panel) ----- */
.users-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 10px;
  font-size: 14px;
}
.users-table th, .users-table td {
  padding: 10px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.users-table th {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  font-weight: 700;
}
.users-table tr:last-child td { border-bottom: none; }
.users-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  align-items: center;
}

.badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--bg-soft);
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 600;
  border: 1px solid var(--border);
  cursor: pointer;
  font-family: inherit;
}
.badge.badge-on {
  background: var(--gold);
  color: var(--ink);
  border-color: var(--gold-strong);
}

.btn-small {
  padding: 6px 10px;
  font-size: 12.5px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: #fff;
  cursor: pointer;
  font-family: inherit;
  color: var(--ink);
}
.btn-small.btn-primary { background: var(--gold-strong); border-color: var(--gold-strong); color: var(--ink); }
.btn-small.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }

.user-pwreset { display: inline-block; }
.user-pwreset > summary { list-style: none; }
.user-pwreset > summary::-webkit-details-marker { display: none; }
.user-pwreset[open] > summary { background: var(--bg-soft); }
.pw-form {
  display: flex;
  gap: 6px;
  align-items: center;
  margin-top: 6px;
  padding: 8px;
  background: var(--bg-soft);
  border-radius: 6px;
}
.pw-form .input { padding: 6px 10px; font-size: 13px; }

@media (max-width: 720px) {
  .users-table thead { display: none; }
  .users-table tr {
    display: block;
    padding: 12px 0;
    border-bottom: 1px solid var(--border);
  }
  .users-table td {
    display: block;
    padding: 4px 0;
    border: none;
  }
  .users-table td::before {
    content: attr(data-label);
    font-size: 11px;
    color: var(--muted);
    text-transform: uppercase;
    margin-right: 6px;
  }
}

/* Mobile-only UI elements — hidden by default on desktop. */
.meta-summary,
.library-fab,
.library-mobile-head { display: none; }

/* ============ Small tablets & landscape phones (sidebar → sheet) ============
   At ≤960px we hide the library sidebar so the timeline gets full width
   and surface it through the floating "+ Add item" FAB instead. This
   catches iPhone Pro Max in landscape (932) and iPad portrait sizes.
   Below 640px the existing mobile rules take over for header/meta/blocks. */
@media (max-width: 960px) {
  .workspace { grid-template-columns: 1fr; padding: 16px; gap: 14px; }

  .library { display: none; }
  .library.library-open {
    display: block;
    position: fixed;
    inset: 0;
    z-index: var(--z-sheet);
    max-height: none;
    border-radius: 0;
    border: none;
    overflow-y: auto;
    padding: 14px 14px 80px;
    background: #fff;
  }
  .library-mobile-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-bottom: 10px;
    margin-bottom: 6px;
    border-bottom: 1px solid var(--border);
    font-weight: 700;
    font-size: 15px;
  }
  .library.library-open > .library-title:first-of-type { display: none; }
  .library-fab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--gold);
    color: var(--ink);
    border: none;
    border-radius: 999px;
    padding: 12px 18px;
    font-weight: 700;
    box-shadow: var(--shadow-md);
    position: fixed;
    right: 16px;
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    z-index: var(--z-fab);
    cursor: pointer;
  }
}

/* ============ Short viewports — landscape phones ============
   Width-based rules can't reach landscape phones (≥640px wide) so we
   also key the header/meta collapse off viewport height. */
@media (max-height: 560px) {
  .site-header { padding: 6px 12px; gap: 8px; }
  .brand { font-size: 15px; gap: 8px; }
  .brand-mark { width: 24px; height: 24px; }
  .brand-mark::after { inset: 5px; }
  .brand-sub { display: none; }
  .header-actions { gap: 6px; }
  .header-actions .btn,
  .header-actions .btn-icon-text { padding: 5px 9px; font-size: 12.5px; }
  .save-status { padding: 3px 8px; font-size: 11px; }

  /* Editor header: one horizontal-scroll action row (see the max-width:640px
     block for the rationale) — doubly important with almost no vertical room. */
  .editor-page .site-header { position: static; }
  .editor-page .header-actions {
    flex: 1 1 100%;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .editor-page .header-actions::-webkit-scrollbar { display: none; }
  .editor-page .header-actions > * { flex-shrink: 0; }
  .editor-page .header-actions .save-status,
  .editor-page .header-actions .collaborators,
  .editor-page .header-actions .last-edit,
  .editor-page .header-actions .drag-pill { order: 2; }
  /* Collapse the action buttons to their icons so all four fit one phone row
     instead of overflowing/scrolling; labels stay for screen readers/desktop. */
  .editor-page .header-actions .btn .btn-label { display: none; }
  .editor-page .header-actions .btn {
    gap: 0;
    padding: 9px 11px;
    min-width: 42px;
    justify-content: center;
    font-size: 16px;
  }

  /* Collapse the meta toolbar into the sticky summary button. */
  .meta-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 8px 14px;
    background: #fff;
    border: none;
    border-bottom: 1px solid var(--border);
    cursor: pointer;
    text-align: left;
    font: inherit;
    color: var(--ink);
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
  }
  .meta-summary-main { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
  .meta-summary-main strong {
    font-size: 14px; font-weight: 700;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .meta-summary-sub {
    font-size: 11.5px; color: var(--muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .meta-chevron { font-size: 18px; line-height: 1; color: var(--muted); flex-shrink: 0; }

  .toolbar.collapsible { display: none; }
  .toolbar.collapsible.open {
    display: grid;
    grid-template-columns: 1fr 1fr;
    padding: 10px 14px;
    gap: 8px;
  }
  .toolbar.collapsible.readonly.open {
    display: flex; padding: 10px 14px; gap: 12px;
    flex-wrap: wrap; font-size: 13px;
  }

  /* Day-of mode — slim down so the current item stays above the fold. */
  .day-header { padding: 8px 12px; position: static; }
  .day-header .brand-mark { width: 22px; height: 22px; }
  .day-event-name { font-size: 13.5px; }
  .day-event-meta { font-size: 10.5px; }
  .day-main { padding: 12px; gap: 10px; }
  .day-card { padding: 12px 14px; }
  .day-card-time { font-size: 22px; }
  .day-actions { gap: 8px; margin-top: 10px; }
  .day-btn { padding: 12px; min-height: 48px; font-size: 14px; }
  .day-delays { margin-top: 10px; }
}

/* ============ Mobile ============ */
@media (max-width: 640px) {
  /* Header — trim padding, hide the subtitle (often a long email), shrink brand. */
  .site-header { padding: 10px 14px; gap: 8px; }
  .brand { font-size: 17px; gap: 8px; }
  .brand-mark { width: 26px; height: 26px; }
  .brand-mark::after { inset: 5px; }
  .brand-sub { display: none; }
  .header-actions { gap: 6px; }
  .header-actions .btn,
  .header-actions .btn-icon-text { padding: 6px 10px; font-size: 13px; }

  /* --- Editor header slimming ---
     The editor's action set (share links, Day Mode, Print, All Events) used to
     wrap into ~4 sticky rows and eat a third of the viewport, and the sticky
     header (z10) and sticky .meta-summary (z9) both pinned to top:0 so the
     compact summary hid behind the header. Fix both: let the full header
     scroll away (static) and promote .meta-summary to the sole sticky context
     bar; collapse the actions into one horizontal-scroll row with the status
     pills ordered last so the buttons lead. Scoped to .editor-page so other
     pages keep their sticky header. */
  .editor-page .site-header { position: static; }
  .editor-page .header-actions {
    flex: 1 1 100%;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 2px;
  }
  .editor-page .header-actions::-webkit-scrollbar { display: none; }
  .editor-page .header-actions > * { flex-shrink: 0; }
  .editor-page .header-actions .save-status,
  .editor-page .header-actions .collaborators,
  .editor-page .header-actions .last-edit,
  .editor-page .header-actions .drag-pill { order: 2; }
  /* Icon-only action buttons so all four fit one narrow (portrait) phone row;
     labels kept for desktop + aria-label for a11y. */
  .editor-page .header-actions .btn .btn-label { display: none; }
  .editor-page .header-actions .btn {
    gap: 0;
    padding: 9px 11px;
    min-width: 42px;
    justify-content: center;
    font-size: 16px;
  }

  /* Dashboard */
  .dashboard { padding: 20px 14px 40px; }
  .dashboard-head h1 { font-size: 22px; }
  .event-grid { grid-template-columns: 1fr; gap: 12px; }
  .event-card { padding: 14px; gap: 10px 12px; }
  .event-card-icon { width: 44px; height: 44px; font-size: 26px; border-radius: 10px; }
  .event-card-body h3 { font-size: 16px; }
  .event-card-actions { padding-top: 10px; gap: 4px; }
  .event-card-actions .btn-icon-text { padding: 8px 10px; font-size: 12.5px; }

  /* Collapsible event-meta bar: a compact summary that expands to the full
     toolbar form. Sticky to keep critical context visible while scrolling. */
  .meta-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 10px 14px;
    background: #fff;
    border: none;
    border-bottom: 1px solid var(--border);
    cursor: pointer;
    text-align: left;
    font: inherit;
    color: var(--ink);
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
  }
  .meta-summary-main { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
  .meta-summary-main strong { font-size: 15px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .meta-summary-sub { font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .meta-chevron { font-size: 20px; line-height: 1; color: var(--muted); flex-shrink: 0; }

  /* Toolbar is collapsed by default; revealed when .open is added. */
  .toolbar.collapsible { display: none; }
  .toolbar.collapsible.open { display: grid; grid-template-columns: 1fr; padding: 12px 14px; gap: 8px; }
  .toolbar.collapsible.readonly.open { display: flex; padding: 10px 14px; gap: 12px; flex-wrap: wrap; font-size: 13px; }

  /* Editor workspace */
  .workspace { padding: 12px; gap: 12px; }
  .timeline-panel { padding: 14px; border-radius: var(--radius); }
  .timeline-summary { gap: 8px; padding-bottom: 10px; margin-bottom: 10px; }
  .summary-value { font-size: 15px; }

  /* Library hides off-screen by default on phones; the floating "+ Add item"
     button opens it as a fullscreen sheet (`.library-open`). */
  .library { display: none; }
  /* The original `.library-title` heading is redundant once the sheet header
     is showing — hide it inside the mobile sheet to avoid duplication. */
  .library.library-open > .library-title:first-of-type { display: none; }

  /* Timeline blocks — re-flow into two rows:
       row 1:  handle | time | (spacer) | duration | actions
       row 2:  title (full width)                            */
  .block {
    grid-template-columns: 22px auto 1fr auto auto;
    column-gap: 6px;
    row-gap: 4px;
    padding: 10px 10px 10px 4px;
    min-width: 0;
  }
  .block > .drag-handle    { grid-column: 1; grid-row: 1; }
  .block > .block-time     { grid-column: 2; grid-row: 1; font-size: 14px; white-space: nowrap; }
  /* .duration-input and .block-main are nested inside .block-form
     (display:contents) in the editable view, so a direct-child combinator
     misses them and the name field loses its row-2 slot. Match by descendant
     — still hits the read-only view where they're direct children. */
  .block .duration-input { grid-column: 4; grid-row: 1; justify-self: end; }
  .block > .block-actions  { grid-column: 5; grid-row: 1; }
  .block .block-main       { grid-column: 1 / -1; grid-row: 2; min-width: 0; }
  /* Editors: the move buttons take the end of the title row, under the
     lock/expand pair, so row 1 is no wider than before they existed. */
  .block.editable .block-main { grid-column: 1 / 5; }
  .block > .block-move     { grid-column: 5; grid-row: 2; justify-self: end; }
  .block-name { font-size: 14px; }
  .block-actions .btn-icon { padding: 6px; font-size: 17px; }

  /* Drawer */
  .item-drawer { padding: 12px; margin-top: 8px; }
  .swatch-row { gap: 4px; }
  .drawer-actions { flex-wrap: wrap; }
  .drawer-actions .btn { padding: 8px 12px; font-size: 13px; }

  /* Modal */
  .modal-backdrop { padding: 12px 12px max(12px, env(safe-area-inset-bottom)); }
  .modal-head { padding: 14px 18px; }
  .modal-body { padding: 16px 18px; }

  /* Settings */
  .settings-card { padding: 18px; }
  .settings-row { flex-direction: column; gap: 10px; }
  .settings-actions { flex-wrap: wrap; }

  /* ---- Touch ergonomics ----
     16px on anything focusable stops iOS Safari from auto-zooming on focus;
     bump the small icon/swatch controls toward a 44px tap target. */
  .input,
  textarea.input,
  select.input,
  .block-name,
  .duration-input input { font-size: 16px; }
  .duration-input input { width: 44px; }

  .btn-icon { padding: 9px; min-width: 40px; min-height: 40px; }
  .block-actions .btn-icon { padding: 8px; font-size: 18px; min-width: 40px; min-height: 40px; }
  .block > .drag-handle { grid-column: 1; min-width: 40px; min-height: 40px; }
  .block { grid-template-columns: 40px auto 1fr auto auto; }
  .swatch { width: 32px; height: 32px; }
  .icon-swatch { width: 42px; height: 42px; font-size: 18px; }
}

/* A11Y-1 on phones: touch reorders by dragging, so the move buttons get out
   of the title's way there. Visually hidden, never display:none: a screen
   reader's swipe can't drag, so VoiceOver and TalkBack users still reach them,
   and they come back into view for anyone who focuses one (same pattern as
   Day Mode's request buttons). */
@media (max-width: 640px) and ((hover: none) or (pointer: coarse)) {
  .block > .block-move:not(:focus-within) {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
  .block.editable:not(:has(.block-move:focus-within)) .block-main { grid-column: 1 / -1; }
}

/* The dark surfaces keep their native controls (the PIN field, guest inputs)
   dark to match (FE-3). */
.day-page, .rq-page { color-scheme: dark; }

/* Push opt-in banner (dashboard) */
.push-banner {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 auto 18px;
  max-width: 1100px;
  padding: 12px 16px;
  background: var(--bg-panel);
  border: 1px solid rgba(168,134,47,0.25);
  border-radius: 10px;
}
.push-banner-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 13.5px;
}
.push-banner-text strong { color: var(--ink); }
.push-banner-text .muted { font-size: 12.5px; }
.push-banner-dismiss {
  background: transparent;
  border: 0;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
  padding: 4px 8px;
  cursor: pointer;
}
.push-banner-dismiss:hover { color: var(--ink); }
@media (max-width: 600px) {
  .push-banner { flex-wrap: wrap; }
  .push-banner-text { flex-basis: 100%; }
}

/* ---- Forms: required markers + template preview ---- */
/* Read a system template's questions without cloning it first. */
.template-preview-list {
  grid-column: 1 / -1;
  margin: 10px 0 0;
  padding: 12px 16px 12px 34px;
  border-top: 1px solid var(--border);
  font-size: 14px;
  line-height: 1.7;
}
.template-preview-list li.section {
  list-style: none;
  margin-left: -18px;
  font-weight: 700;
  opacity: 0.75;
}
.template-preview-list li.question { opacity: 0.9; }

/* The DJ marked this question required; say so rather than only enforcing it. */
.required-marker {
  margin-left: 3px;
  color: #c64030;
  font-weight: 700;
}

/* ==========================================================================
   Day Mode layout: the Now card must never leave the screen
   ==========================================================================
   The two things that used to fight the Now card for vertical inches don't any
   more. The action buttons are pinned to the bottom, and the request queue is a
   sheet that floats OVER the page instead of a section rendered above it.
   Everything past Next collapses behind a header.

   Sizes live in custom properties so the height tiers at the bottom of this
   block can retune the whole stack by changing two numbers. */
:root {
  /* --actionbar-h is the bar's real rendered height (button + padding +
     border); the page's bottom padding and the sheet/toast offsets are all
     measured off it, so it has to stay in step with the rules below. */
  --sheet-peek-h: 92px;
  --actionbar-h: 59px;
  --rail-w: 300px;
  --toast-top: calc(env(safe-area-inset-top, 0px) + 8px);
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* dvh, not vh: with a fixed bottom stack, vh counts mobile browser chrome that
   isn't there and the last row of content hides behind the sheet. */
.day-page {
  min-height: 100dvh;
  padding-bottom: calc(
    var(--actionbar-h) + var(--sheet-peek-h) + env(safe-area-inset-bottom, 0px) + 20px
  );
}

/* ---- compact header: name + the clock the schedule is measured against ---- */
.day-header { padding: 10px 16px; padding-top: calc(10px + env(safe-area-inset-top, 0px)); }
.day-brand { flex: 1; min-width: 0; }
.day-event-name { max-width: none; font-size: 16px; }
.day-clock {
  font-family: 'Manrope', sans-serif;
  font-weight: 800;
  font-size: 18px;
  color: #f4efe4;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.day-clock .ampm { font-size: 11px; color: rgba(255,255,255,0.65); margin-left: 3px; }
.day-head-actions { gap: 12px; }
.day-head-actions .btn-pill { padding: 8px 12px; min-height: 40px; display: inline-flex; align-items: center; gap: 4px; }

/* ---- collapsible headers (Next strip, Full schedule, form sections) ---- */
.day-chev {
  flex-shrink: 0;
  color: #a89eb0;
  font-weight: 800;
  transition: transform 160ms ease;
  display: inline-block;
}
.day-chev.is-open { transform: rotate(90deg); }

.day-strip { background: #211a30; border: 1px solid #322a42; border-radius: 14px; overflow: hidden; }
.day-strip-head {
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 52px; padding: 10px 14px;
  background: none; border: 0; cursor: pointer;
  color: #f2ede2; font: inherit; text-align: left;
}
.day-strip-label {
  flex-shrink: 0;
  font-size: 10px; font-weight: 800; letter-spacing: 0.08em;
  text-transform: uppercase; color: #a89eb0;
}
.day-strip-time { flex-shrink: 0; font-weight: 700; font-size: 14px; font-variant-numeric: tabular-nums; }
.day-strip-time .ampm { font-size: 10px; color: #a89eb0; margin-left: 2px; }
.day-strip-name {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 600; font-size: 15px;
}
.day-strip-icon { margin-right: 6px; }
.day-strip-eta { flex-shrink: 0; font-size: 12.5px; color: var(--gold); font-weight: 700; }
.day-strip-body { padding: 0 14px 14px; display: flex; flex-direction: column; gap: 10px; }
.day-strip-empty { margin: 0; color: #8a8098; font-size: 13.5px; }

.day-list-head {
  display: flex; align-items: center; gap: 10px;
  width: 100%; min-height: 52px; padding: 12px 16px;
  border: 0; cursor: pointer;
  font: inherit; text-align: left;
}
.day-list-head-main {
  font-size: 11px; font-weight: 800; letter-spacing: 0.08em;
  text-transform: uppercase; color: #a89eb0; flex-shrink: 0;
}
.day-list-head-sub {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12px; color: #8a8098; text-align: right;
}

/* ---- pinned action bar ---------------------------------------------------
   Sits above the sheet's peek row, not under it. A long set of notes on the
   Now card can no longer push Complete/Skip below the fold. */
.day-actionbar {
  position: fixed;
  left: 0; right: 0;
  bottom: calc(var(--sheet-peek-h) + env(safe-area-inset-bottom, 0px));
  z-index: var(--z-fab);
  padding: 8px 14px;
  background: rgba(22, 16, 31, 0.97);
  border-top: 1px solid #322a42;
  box-shadow: 0 -6px 20px rgba(0, 0, 0, 0.35);
}
@supports (backdrop-filter: blur(8px)) {
  .day-actionbar { background: rgba(22, 16, 31, 0.86); backdrop-filter: blur(10px); }
}
.day-actionbar-row { display: flex; gap: 8px; max-width: 720px; margin: 0 auto; }
/* ~25% shorter than the 52px they started at. They stay full-width thirds, so
   the horizontal target is still large; it is only the height that tightens. */
.day-actionbar-row .day-btn {
  flex: 1;
  margin-top: 0;
  min-height: 42px;
  padding: 8px 12px;
  font-size: 14.5px;
}
.day-actionbar .day-delay-toggle { flex: 0 0 72px; }
.day-actionbar .day-delays { max-width: 720px; margin: 0 auto 10px; }
/* Padding too, not just min-height: .day-btn's base 18px padding otherwise
   wins and the delay row renders ~18px taller than the row above it. */
.day-actionbar .day-delay-buttons .day-btn {
  min-height: 42px;
  margin-top: 0;
  padding: 8px 12px;
  font-size: 14.5px;
}

/* ---- the request sheet ---------------------------------------------------
   Fixed to the viewport, so opening it never moves the Now card. body classes
   (not element classes) drive the open state: LiveView's DOM patching never
   touches <body>, so a re-render can't fight the transform mid-drag. */
/* Full height always; the collapsed state is a translate, not a shorter box.
   This is what lets a drag track the finger — transform is compositor-driven
   and interruptible, where the max-height animation it replaced could neither
   follow a gesture nor run at 60fps. */
.req-sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: var(--z-sheet);
  height: calc(72dvh + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: #1c1528;
  border-top: 1px solid #453a5c;
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -10px 30px rgba(0, 0, 0, 0.5);
  overflow: hidden;
  transform: translateY(calc(100% - var(--sheet-peek-h) - env(safe-area-inset-bottom, 0px)));
  transition: transform 300ms cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: transform;
}
body.req-sheet-open .req-sheet { transform: translateY(0); }

/* The peek row keeps its box in BOTH states — the drag measures its travel from
   the rendered layout, so a row that disappears on open would make the sheet
   jump mid-gesture. Only its contents swap: the oldest-pending card collapsed,
   the queue's title open (where the card would just duplicate the list). */
body.req-sheet-open .req-sheet-peek .req-card { display: none; }
body.req-sheet-open .req-peek-resting { display: none; }
/* Open, this row is the queue's header: the count pill plus its controls. */
body.req-sheet-open .req-peek-controls { display: flex; }

.req-sheet-inner { display: flex; flex-direction: column; min-height: 0; height: 100%; }

.req-sheet-grip {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 26px; padding: 8px 0 2px;
  background: none; border: 0; cursor: grab;
  touch-action: none;
  flex-shrink: 0;
}
.req-sheet-grip:active { cursor: grabbing; }
/* The handle carries the queue's state while the sheet is closed. Slightly
   thicker than a plain grab bar so the colour actually reads across a dark
   booth; the button's own label says the same thing for anyone not going by
   colour. */
.req-grip-bar {
  display: block;
  width: 46px; height: 5px;
  border-radius: 999px;
  background: #453a5c;
  /* No transition on purpose. This is a status indicator, and a transition
     that a backgrounded tab freezes mid-fade leaves it showing the previous
     state — the DJ steps away to Serato, comes back, and reads "open" off a
     queue that is closed. Correctness beats the fade on a 5px bar. */
}
.req-grip-bar.requests-on { background: #8fe4ae; }
.req-grip-bar.requests-off { background: #ff9aa2; }

.req-sheet-peek {
  display: flex; align-items: center; gap: 10px;
  height: calc(var(--sheet-peek-h) - 26px);
  padding: 0 12px 6px;
  overflow: hidden;
}
/* Everything in the peek is sized off the tier budget, not off its content:
   the collapsed sheet has to cost a known number of pixels or the Now card
   loses them without anyone deciding to spend them. */
.req-sheet-peek .req-card-body { padding: 6px 10px; }
.req-sheet-peek .req-btn { width: 40px; height: 40px; font-size: 16px; }
.req-sheet-peek .req-title { font-size: 15px; }
.req-sheet-peek .req-note,
.req-sheet-peek .req-guest { display: none; }
.req-peek-count {
  flex-shrink: 0;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--gold);
  color: #1d142e;
  font-weight: 800;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.req-peek-count.is-full { background: #c64030; color: #ffe8e4; }
.req-peek-summary { display: none; font-size: 14px; font-weight: 600; color: #cdbfe0; }
.req-peek-resting { flex: 1; font-size: 13.5px; color: #8a8098; }

/* Collapsed the row is one request card, so the controls stay out of the way;
   open, they are the header and the queue starts immediately below. */
.req-peek-controls { display: none; align-items: center; gap: 8px; flex: 1; justify-content: flex-end; }

/* One button, one boolean: it says which state the queue is in, and tapping it
   changes that state. Colour carries the same fact for a glance mid-set. */
.req-open-toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  min-height: 34px;
  border-radius: 999px;
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}
.req-open-toggle.is-open {
  background: rgba(47, 107, 63, 0.24);
  border: 1px solid #2f6b3f;
  color: #8fe4ae;
}
.req-open-toggle.is-closed {
  background: rgba(107, 47, 63, 0.26);
  border: 1px solid #6b2f3f;
  color: #ff9aa2;
}
.req-open-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: currentColor; }
.req-sheet-peek { flex-shrink: 0; touch-action: none; }
.req-sheet-peek .req-card { flex: 1; min-width: 0; touch-action: none; }

.req-sheet-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  min-height: 0;
  padding: 12px 14px 14px;
  border-top: 1px solid #322a42;
  overscroll-behavior: contain;
}
.req-sheet-body .day-requests-empty { padding: 18px 12px; }

/* ---- new-request toast ---------------------------------------------------
   Lives on <body>, outside LiveView's tree. Two rules make it unable to get in
   the way, and both are load-bearing:
     - `position: fixed`, so it never occupies layout space or pushes anything.
     - `pointer-events: none` on the host AND every toast, so a tap lands on
       whatever is underneath. It can sit over the action bar and still cost
       the DJ nothing — mid-reception a toast that eats a "Complete" press is
       worse than no toast at all.
   Deliberately not the full-screen pulse: the DJ has to be able to tell "the
   next item is starting" apart from "someone wants to hear Mr Brightside". */
#req-toasts {
  position: fixed;
  top: var(--toast-top);
  left: 0; right: 0;
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 0 14px;
  pointer-events: none;
}
/* Sized to its content and centred, so it reads as a pill laid over the title
   rather than a bar that replaces the header. */
.req-toast {
  pointer-events: none;
  width: auto;
  max-width: min(520px, 100%);
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 9px 16px;
  border-radius: 999px;
  background: rgba(43, 35, 64, 0.98);
  border: 1px solid var(--gold-strong);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.6);
  color: #f2ede2;
  animation: req-toast-in 220ms cubic-bezier(0.22, 0.61, 0.36, 1);
}
.req-toast.is-leaving { animation: req-toast-out 200ms ease-in forwards; }
.req-toast-label {
  flex-shrink: 0;
  font-size: 12.5px;
  font-weight: 800;
  color: var(--gold);
  white-space: nowrap;
}
.req-toast-song {
  flex: 1;
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
@keyframes req-toast-in {
  from { opacity: 0; transform: translateY(-12px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes req-toast-out {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(-6px); }
}
/* The header sits in the main column, so the toast centres over that, not over
   the viewport including the rail. */
body.req-rail #req-toasts { right: var(--rail-w); }

/* ---- swipe reveal --------------------------------------------------------
   The labels sit behind .req-card-body, which is what SwipeList translates, so
   the direction is readable mid-swipe instead of something to memorise. */
.req-card {
  position: relative;
  display: block;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 12px;
  overflow: hidden;
  touch-action: pan-y;
}
.req-card-body {
  position: relative;
  z-index: 1;
  display: flex; align-items: center; gap: 12px;
  padding: 12px;
  background: #211a30;
  border: 1px solid #322a42;
  border-radius: 12px;
}
.req-reveal {
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
  display: flex; align-items: center;
  padding: 0 18px;
  font-size: 14px; font-weight: 800; letter-spacing: 0.04em;
  opacity: 0;
  transition: opacity 120ms ease;
}
.req-reveal-play { justify-content: flex-start; background: #1c3a22; color: #7fdca0; }
.req-reveal-pass { justify-content: flex-end; background: #3a1c22; color: #ff9aa2; }
.req-card.swiping-play .req-reveal-play { opacity: 1; }
.req-card.swiping-pass .req-reveal-pass { opacity: 1; }

/* ==========================================================================
   Height tiers — what earns the screen at each size
   ==========================================================================
   Measured on AVAILABLE viewport height, not device height: the same phone has
   ~90px more of it installed as a PWA, and the query picks that up on its own.
   A phone in landscape is ~400px tall, so it lands in Compact for free without
   an orientation query. */

/* Compact — SE-class with browser chrome, and any phone in landscape.
   The peek card is the first thing to go: at this height the Now card needs
   every pixel, so the sheet drops to a count-only strip and triage happens
   after a tap instead of in the peek. */
@media (max-height: 620px) {
  :root {
    --sheet-peek-h: 48px;
    --actionbar-h: 51px;
    --toast-top: calc(env(safe-area-inset-top, 0px) + 4px);
  }
  .req-sheet-peek { padding: 2px 14px 8px; }
  .req-sheet-peek .req-card { display: none; }
  .req-peek-summary { display: block; flex: 1; }
  .day-header { padding-top: calc(6px + env(safe-area-inset-top, 0px)); padding-bottom: 6px; }
  .day-event-name { font-size: 14px; }
  .day-clock { font-size: 16px; }
  .day-main { gap: 10px; padding: 10px 14px; }
  .day-strip-head, .day-list-head { min-height: 44px; padding-top: 8px; padding-bottom: 8px; }
  .day-actionbar { padding: 6px 14px; }
  .day-actionbar-row .day-btn { min-height: 38px; font-size: 14px; }
  .day-card-now { padding: 14px; }
  .req-sheet { height: calc(88dvh + env(safe-area-inset-bottom, 0px)); }
}

/* Roomy — Pro Max / Pixel Pro, or most phones once installed as a PWA.
   Enough height to carry the guest's dedication in the peek row and to leave
   the next item's cues open by default. */
@media (min-height: 801px) {
  :root { --sheet-peek-h: 118px; }
  .req-sheet-peek .req-note,
  .req-sheet-peek .req-guest { display: block; }
  .day-card-now { padding: 20px; }
}

/* ==========================================================================
   Tablet rail — same markup, different shape
   ==========================================================================
   Both dimensions are gated on purpose. Width alone would put the rail on a
   landscape phone (932px wide, 430px tall), where a full-height rail is
   actively wrong; the height half keeps that case on the sheet. Portrait iPad
   is ~820x1180 and lands here, which is the booth-tablet case. */
@media (min-width: 800px) and (min-height: 700px) {
  body.req-rail .day-page { padding-right: var(--rail-w); padding-bottom: calc(var(--actionbar-h) + 20px); }

  body.req-rail .req-sheet {
    top: 0; bottom: 0; right: 0; left: auto;
    width: var(--rail-w);
    max-height: none;
    border-radius: 0;
    border-top: 0;
    border-left: 1px solid #453a5c;
    box-shadow: -8px 0 24px rgba(0, 0, 0, 0.4);
    padding-bottom: 0;
    height: 100%;
    transform: none;
    transition: none;
  }
  body.req-rail .req-sheet-inner { max-height: none; height: 100%; }
  /* No peek state to be in: the queue itself is always on screen. The row
     survives as the rail's header though — it carries the count and the
     queue's controls, which have nowhere else to live here. */
  body.req-rail .req-sheet-grip { display: none; }
  body.req-rail .req-sheet-peek {
    display: flex;
    flex-wrap: wrap;
    height: auto;
    gap: 8px;
    padding: calc(14px + env(safe-area-inset-top, 0px)) 14px 10px;
    border-bottom: 1px solid #322a42;
  }
  body.req-rail .req-sheet-peek .req-card,
  body.req-rail .req-peek-resting { display: none; }
  body.req-rail .req-peek-controls { flex: 1 1 100%; justify-content: flex-start; }
  body.req-rail .req-sheet-body { flex: 1; border-top: 0; padding-top: 12px; }

  body.req-rail .day-actionbar { right: var(--rail-w); bottom: 0; }
}

@media (min-width: 1000px) and (min-height: 700px) {
  :root { --rail-w: 340px; }
}

/* The sheet slides; under reduced motion it just changes state. A drag still
   tracks the finger — that is direct manipulation, not decorative motion. */
@media (prefers-reduced-motion: reduce) {
  .req-sheet { transition: none; }
  .day-chev { transition: none; }
  /* The toast still appears — it is information, not decoration — it just
     stops sliding in. */
  .req-toast, .req-toast.is-leaving { animation: none; }
}

/* ---------- Export to a drive (DriveExportLive) ----------------------------
   A desktop page (it needs Chrome/Edge on a computer), but it must still not
   scroll sideways on a narrow window: long file paths wrap. */
.dx { max-width: 920px; }
.dx-panel {
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px 22px;
  margin-bottom: 20px;
}
.dx-panel h2 { font-size: var(--fs-h3); margin: 0 0 8px; }
.dx-panel p { margin: 0 0 12px; }
.dx-panel code, .dx-howto code { font-size: 0.92em; }
.dx-error {
  color: var(--danger);
  background: #fdf1f1;
  border: 1px solid #f0caca;
  border-radius: var(--radius);
  padding: 10px 14px;
}
.dx-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
.dx-toggle { margin: 4px 0 8px; }
.dx-toggle label, .dx-rb > label { display: inline-flex; gap: 8px; align-items: center; cursor: pointer; }
.dx-rb { margin: 4px 0 8px; }
.dx-rb-fields { margin: 10px 0 0 24px; max-width: 460px; }
.dx-rb-os { border: 0; padding: 0; margin: 0 0 10px; display: flex; flex-wrap: wrap; gap: 6px 16px; align-items: center; }
.dx-rb-os legend { float: left; margin-right: 6px; font-weight: 600; font-size: var(--fs-sm); }
.dx-rb-os label { display: inline-flex; gap: 6px; align-items: center; cursor: pointer; }
.dx-rb-label { display: block; font-weight: 600; font-size: var(--fs-sm); margin-bottom: 4px; }
.dx-hint { font-size: var(--fs-sm); margin: 6px 0 0; }

.dx-list { margin-bottom: 28px; }
.dx-list h2 {
  font-size: var(--fs-h3);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  margin: 0 0 10px;
}
.dx-count { font-size: var(--fs-sm); font-weight: 600; color: var(--muted); }
.dx-rows { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--border); }
.dx-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) auto;
  gap: 8px 14px;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.dx-song { min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; }
.dx-title { font-weight: 600; color: var(--ink); }
.dx-artist { color: var(--ink-soft); }
.dx-context { flex-basis: 100%; font-size: var(--fs-sm); color: var(--muted); }
.dx-choose { min-width: 0; }
.dx-choose .input { padding: 8px 10px; font-size: 13px; text-overflow: ellipsis; }
.dx-search { grid-column: 1 / -1; padding: 4px 0 6px; }
.dx-search .input { max-width: 420px; }
.dx-results { list-style: none; margin: 6px 0; padding: 0; }
.dx-results .btn-link { text-align: left; overflow-wrap: anywhere; }

/* Status is in the chip's words as well as its colour. */
.dx-chip {
  font-size: 11px; font-weight: 700; letter-spacing: 0.02em;
  padding: 2px 8px; border-radius: var(--radius-pill);
  border: 1px solid transparent; white-space: nowrap;
}
.dx-chip-found { background: #e8f3ea; color: var(--success); border-color: #c5e0ca; }
.dx-chip-chosen { background: var(--gold-tint); color: var(--gold-text); border-color: var(--gold); }
.dx-chip-check { background: #fbf1df; color: var(--warn); border-color: #ecd3a6; }
.dx-chip-missing { background: #fdf1f1; color: var(--danger); border-color: #f0caca; }
.dx-chip-remembered { background: #e8f3ea; color: var(--success); border-color: #c5e0ca; }
.dx-chip-declined { background: var(--bg-panel); color: var(--muted); border-color: var(--border-strong); }
.dx-gone { flex-basis: 100%; font-size: var(--fs-sm); font-weight: 600; color: var(--warn); }

.dx-files, .dx-howto { margin: 0 0 16px; padding-left: 20px; overflow-wrap: anywhere; }
.dx-files li.ok > span:first-child { color: var(--success); font-weight: 700; }
.dx-files li.failed > span:first-child { color: var(--danger); font-weight: 700; }
.dx-howto li { margin-bottom: 4px; }

@media (max-width: 700px) {
  .dx-row { grid-template-columns: minmax(0, 1fr); }
  .dx-panel { padding: 16px; }
}

/* Recent changes (EventChangesLive). */
.changes-day { margin-top: 18px; }
.changes-day-title { font-size: 13px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); margin: 0 0 8px; }
.changes-list { list-style: none; margin: 0; padding: 0; }
.change-entry { padding: 10px 0; border-bottom: 1px solid var(--line, rgba(0,0,0,0.08)); }
.change-line { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: baseline; }
.change-who { font-weight: 700; }
.change-what { flex: 1 1 200px; overflow-wrap: anywhere; }
.change-time { color: var(--muted); font-size: 13px; }
.change-more { margin-top: 4px; background: none; border: 0; padding: 0; color: var(--gold-text); text-decoration: underline; cursor: pointer; font: inherit; }
.change-full { margin: 6px 0 0; display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; }
.change-full dt { font-weight: 700; color: var(--muted); }
.change-full dd { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }

/* "Changed since you last looked" (ChangeComponents). */
.changed-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--gold); flex: none; margin: 0 4px; vertical-align: middle; }
.field-changed { margin: 2px 0 4px; font-size: 12px; font-weight: 600; color: var(--gold-text); }
