/* Raydiohost - LIGHT theme.
   Two layout shapes, matching the desktop app's structure:
     .split  = master/detail (list left, editor right)   -> Hosts, Shows, Schedule
     .card   = boxed full-width sections                 -> Station, Configuration
   Structure is the intent; the desktop-specific controls are gone. */

/* ==========================================================================
   Palette: blue and white, soft and serene. Every token below is the theme -
   change these and the whole panel follows, which is why the hardcoded hexes
   that remain (the dark station calendar, the front page) are called out where
   they live rather than being duplicated here.
   ========================================================================== */
:root {
  --bg:        #eaf4fc;
  --panel:     #ffffff;
  --ink:       #1a4b8a;
  --ink-2:     #4a7bbf;
  --ink-3:     #6a9cdd;
  --line:      #d8e7f5;
  --line-2:    #c3daf0;
  --accent:    #3399ff;
  --accent-2:  #1a4b8a;
  --danger:    #c62828;
  --ok:        #1b7f3b;
  --radius:    14px;
  --shadow:    0 1px 2px rgba(26,75,138,.06), 0 8px 24px rgba(51,153,255,.07);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        "Helvetica Neue", Arial, sans-serif;
}

/* ---------- shell ---------- */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 20px; height: 56px;
  background: var(--panel); border-bottom: 1px solid var(--line);
}
.brand { font-size: 18px; font-weight: 700; letter-spacing: -.2px; }
.brand span { color: var(--accent); }
.brand.big { font-size: 26px; text-align: center; }
.who { font-size: 13px; color: var(--ink-2); display: flex; gap: 12px; align-items: center; }
.who .sub { color: var(--ink-3); }

.shell { display: flex; min-height: calc(100vh - 56px); }
.side {
  width: 162px; flex: 0 0 162px; padding: 14px 8px;
  background: var(--panel); border-right: 1px solid var(--line);
}
.tab {
  display: block; padding: 9px 12px; margin-bottom: 2px;
  border-radius: 8px; color: var(--ink-2); text-decoration: none; font-size: 14px;
}
.tab:hover { background: #f0f2f5; color: var(--ink); }
.tab.on { background: #eaf0fe; color: var(--accent-2); font-weight: 600; }

.content { flex: 1; padding: 26px 30px 60px; max-width: 1340px; }

/* ---------- headings ---------- */
h1 { font-size: 23px; margin: 0 0 4px; letter-spacing: -.3px; }
h2 { font-size: 17px; margin: 0 0 14px; }
h3 { font-size: 15px; margin: 0 0 6px; }
.lede { color: var(--ink-2); margin: 0; max-width: 62ch; }
.pagehead {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 20px; margin-bottom: 22px;
}
.quiet { color: var(--ink-3); font-size: 13px; }
.center { text-align: center; }
code {
  background: #eef1f5; padding: 1px 6px; border-radius: 5px;
  font: 13px/1.4 ui-monospace, Menlo, Consolas, monospace;
}

/* ---------- split: master / detail ---------- */
.split { display: grid; grid-template-columns: 300px 1fr; gap: 20px; align-items: start; }

.list {
  list-style: none; margin: 0; padding: 6px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow); min-height: 80px;
}
.list li {
  padding: 10px 12px; border-radius: 8px; cursor: pointer;
  border-bottom: 1px solid transparent;
}
.list li:hover { background: #f4f6f9; }
.list li.on { background: #eaf0fe; }
.list li .t { font-weight: 600; font-size: 14px; }
.list li .s { font-size: 12.5px; color: var(--ink-3); }
.list li.empty { color: var(--ink-3); cursor: default; font-size: 13.5px; }
.list li.empty:hover { background: none; }

.editor {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 20px 22px;
}

/* ---------- forms ---------- */
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
label { display: block; margin-bottom: 14px; font-size: 13px; color: var(--ink-2); font-weight: 600; }
input, select, textarea {
  display: block; width: 100%; margin-top: 5px; padding: 9px 11px;
  border: 1px solid var(--line-2); border-radius: 8px;
  font: inherit; font-weight: 400; color: var(--ink); background: #fff;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37,99,235,.13);
}
/* the free-text box behind "Other…" - tinted so it reads as the custom entry, not
   a second field someone forgot to fill in */
input.other { margin-top: 6px; border-style: dashed; background: #fbfdff; }
input.other::placeholder { color: var(--muted); }
.help { display: block; margin-top: 4px; font-size: 12px; color: var(--ink-3); font-weight: 400; }
.actions { display: flex; gap: 10px; margin-top: 20px; align-items: center; }

.btn {
  display: inline-block; padding: 9px 15px; border-radius: 8px;
  border: 1px solid var(--line-2); background: #fff; color: var(--ink);
  font: inherit; font-weight: 600; font-size: 14px; cursor: pointer; text-decoration: none;
}
.btn:hover { background: #f4f6f9; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { background: var(--accent-2); }
.btn.danger { color: var(--danger); border-color: #e9c2c2; margin-left: auto; }
.btn.danger:hover { background: #fdf1f1; }
.btn.wide { width: 100%; margin-top: 8px; }
.btn[disabled] { opacity: .55; cursor: default; }

.err {
  margin: 14px 0 0; padding: 10px 12px; border-radius: 8px;
  background: #fdf1f1; border: 1px solid #e9c2c2; color: var(--danger); font-size: 13.5px;
}

/* ---------- cards ---------- */
.card {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 18px 20px; margin-bottom: 16px;
}
.card p { margin: 0 0 8px; color: var(--ink-2); }
.card.callout { border-left: 3px solid var(--accent); }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; margin-bottom: 22px; }

.stat {
  display: block; padding: 16px 18px; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); text-decoration: none; color: var(--ink);
}
.stat:hover { border-color: var(--line-2); }
.stat .num { display: block; font-size: 26px; font-weight: 700; letter-spacing: -.5px; }
.stat .lbl { color: var(--ink-3); font-size: 13px; }

/* ---------- login / landing ---------- */
.loginwrap { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 30px; }
.loginbox {
  width: 100%; max-width: 380px; background: var(--panel);
  border: 1px solid var(--line); border-radius: 14px;
  box-shadow: var(--shadow); padding: 28px 26px;
}
.loginbox.wide { max-width: 680px; }
.loginbox .lede { text-align: center; margin: 6px 0 20px; }

/* ---------- toast ---------- */
.toast {
  position: fixed; right: 22px; bottom: 22px; padding: 11px 16px;
  background: var(--ink); color: #fff; border-radius: 9px;
  font-size: 14px; box-shadow: 0 6px 20px rgba(0,0,0,.18); z-index: 50;
}
.toast.bad { background: var(--danger); }

/* ---------- fieldsets, cast, days, misc ---------- */
.fieldset {
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px 16px 6px; margin: 0 0 16px;
}
.fieldset legend { font-size: 13px; font-weight: 600; color: var(--ink-2); padding: 0 6px; }

.radio {
  display: flex; gap: 9px; align-items: flex-start; font-weight: 400;
  color: var(--ink); margin-bottom: 10px; cursor: pointer;
}
.radio input { width: auto; margin: 3px 0 0; flex: 0 0 auto; }
.radio span { font-size: 13.5px; }

.cast { list-style: none; margin: 0 0 10px; padding: 0; }
.cast li {
  display: flex; align-items: center; gap: 10px; padding: 7px 10px;
  border: 1px solid var(--line); border-radius: 8px; margin-bottom: 6px; background: #fbfcfd;
}
.cast li.empty { border: none; background: none; color: var(--ink-3); font-size: 13.5px; }
.cast .ord {
  width: 22px; height: 22px; flex: 0 0 22px; border-radius: 50%;
  background: #eaf0fe; color: var(--accent-2); font-size: 12px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.cast .who-n { font-weight: 600; font-size: 13.5px; }
.cast .who-r { color: var(--ink-3); font-size: 12.5px; }
.cast .ctl { margin-left: auto; display: flex; gap: 4px; }
.mini {
  border: 1px solid var(--line-2); background: #fff; border-radius: 6px;
  width: 26px; height: 26px; cursor: pointer; font-size: 13px; line-height: 1; padding: 0;
}
.mini:hover { background: #f2f5f8; }
.mini[disabled] { opacity: .35; cursor: default; }
.mini.danger { color: var(--danger); border-color: #e9c2c2; }
.castadd { display: flex; gap: 8px; margin-bottom: 14px; }
.castadd select { margin-top: 0; }

.days { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.day {
  display: flex; align-items: center; gap: 5px; margin: 0; font-weight: 400;
  border: 1px solid var(--line-2); border-radius: 7px; padding: 6px 10px; cursor: pointer;
  font-size: 13px; background: #fff;
}
.day input { width: auto; margin: 0; }

.list.wide { margin-bottom: 18px; }
.list.wide li .s { font-size: 12.5px; }
.plain { margin: 6px 0 0; padding-left: 20px; color: var(--ink-2); font-size: 13.5px; }
.plain li { margin-bottom: 4px; }
.ok {
  margin: 14px 0 0; padding: 10px 12px; border-radius: 8px;
  background: #eefaf1; border: 1px solid #bfe6ca; color: var(--ok); font-size: 13.5px;
}
.nextdue { background: #fbfcfd; }
.nextdue p { margin: 0; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13.5px; }

.warn {
  margin: 0 0 12px; padding: 9px 12px; border-radius: 8px;
  background: #fff8e6; border: 1px solid #f0dca8; color: #7a5b00; font-size: 13px;
}
.cast li.clash { border-color: #f0dca8; background: #fffdf4; }

/* ---------- custom voice listbox (faces in the list) ---------- */
.vsel { position: relative; flex: 1 1 auto; min-width: 0; }
.vsel-btn {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 7px 10px; border: 1px solid var(--line); border-radius: var(--radius);
  background: #fff; font: inherit; font-size: 14px; color: var(--ink);
  cursor: pointer; margin-bottom: 0;
}
.vsel-btn:hover { border-color: #c3ccd8; }
.vsel-label { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vsel-btn .caret { color: var(--ink-3); font-size: 11px; }

.vsel-panel {
  position: absolute; z-index: 40; top: calc(100% + 4px); left: 0;
  width: min(430px, 92vw); max-height: 330px; overflow-y: auto;
  background: #fff; border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 12px 30px rgba(20, 30, 50, .16); padding: 6px;
}
.vgroup {
  display: flex; align-items: center; justify-content: space-between;
  padding: 7px 9px 5px; font-size: 11px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-3);
}
.vgroup span { font-weight: 600; opacity: .7; }
.vopt {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 6px 8px; border: 0; border-radius: 8px; background: transparent;
  font: inherit; text-align: left; cursor: pointer;
}
.vopt:hover { background: #f2f5f9; }
.vopt.on { background: #e8f0fe; }
.vopt-txt { display: flex; flex-direction: column; min-width: 0; }
.vopt .vn { font-size: 13.5px; color: var(--ink); font-weight: 600; }
.vopt .vs { font-size: 11.5px; color: var(--ink-3); overflow: hidden;
            text-overflow: ellipsis; white-space: nowrap; }

/* ---------- host photo box ---------- */
.photobox {
  display: flex; gap: 14px; align-items: flex-start;
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 14px; margin: 0 0 16px; background: #fbfcfe;
}
.face.big { width: 84px; height: 84px; border-radius: 12px; }
.photobox-body { min-width: 0; flex: 1 1 auto; }
.photobox-body .pt { font-size: 13px; font-weight: 700; color: var(--ink); }
.photobox-body .ps { font-size: 12.5px; color: var(--ink-3); margin: 3px 0 10px; }
/* visually hidden but still focusable/clickable - NOT display:none, which breaks
   programmatic .click() in some browsers and label forwarding entirely */
.vh {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.photobox-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.photobox-actions .btn { margin-bottom: 0; }
.face.ph { background: #eef1f5; border: 1px dashed var(--line); }

/* ---------- voice audition + persona draft ---------- */
.voicepick { display: flex; gap: 8px; align-items: flex-end; }
.voicepick select { margin-top: 0; }
.btn.hear { flex: 0 0 auto; margin-bottom: 0; white-space: nowrap; }

/* headshots: the voice's placeholder portrait, and the host's own once uploaded */
.face {
  width: 40px; height: 40px; border-radius: 50%; flex: 0 0 auto;
  background: #eef1f5; object-fit: cover; display: block;
}
.voicepick .face { margin-bottom: 0; }
li .face { margin-top: 2px; }
li .face.ph { border: 1px dashed var(--line); }
/* a voice placeholder is visually distinguished from a real host photo */
li .face.fallback { opacity: .5; }
li > .row { min-width: 0; }
.list li { display: flex; gap: 10px; align-items: flex-start; }
.btn.hear:disabled { opacity: .45; cursor: default; }
.draftrow { display: flex; align-items: center; gap: 10px; margin: -4px 0 12px; }
.draftrow .quiet { font-size: 12.5px; }

@media (max-width: 820px) {
  .split, .grid2, .grid4, .row2 { grid-template-columns: 1fr; }
  .side { display: none; }
  .content { padding: 18px; }
}

/* ---- shows: destination block + slot day picker -------------------------- */
.filters { display: flex; align-items: end; gap: 12px; }
.meta { color: var(--quiet, #888); font-size: 13px; margin: 2px 0 10px; }
.slotdays {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin: 10px 0; font-size: 13px;
}
.slotdays .day { display: inline-flex; align-items: center; gap: 4px; }

/* ---- episodes: the script editor -----------------------------------------
   A script is a list of lines, so it is laid out as a list, one row per line:
   number, who, how it is delivered, what they say. Editing text in place is the
   whole point of the screen, so the textarea gets the width. */
.scripthead, .scriptline {
  display: grid;
  grid-template-columns: 34px 150px 130px 1fr 34px;
  gap: 8px;
  align-items: start;
}
.scripthead { padding: 0 0 6px; font-size: 12px; }
.scriptline { padding: 6px 0; border-top: 1px solid var(--line, #2a2a2a); }
.scriptline .n { color: var(--quiet, #888); font-size: 12px; padding-top: 8px; }
.scriptline .tx { resize: vertical; min-height: 44px; width: 100%; }
.scriptline select { width: 100%; }
.btn.tiny { padding: 2px 8px; line-height: 1.2; }

/* ---- the tenant's own files, under "I will upload it myself" ------------- */
.files { list-style: none; margin: 8px 0 0; padding: 0; }
.files li {
  padding: 8px 10px; border: 1px solid var(--line, #2a2a2a); border-radius: 6px;
  margin-bottom: 6px; display: flex; flex-direction: column; gap: 4px;
}
.files li .t { font-weight: 600; }
.files li .s { color: var(--quiet, #888); font-size: 12px; }
.files li .btn { align-self: start; }

/* A shown-level alert (thin material) drawn small in the list, full in the editor. */
.warnline { color: var(--warn, #d9a600); }

@media (max-width: 820px) {
  .scripthead { display: none; }
  .scriptline { grid-template-columns: 28px 1fr; }
  .scriptline .sp, .scriptline .em, .scriptline .del { grid-column: 2; }
  .scriptline .tx { grid-column: 2; }
}


/* ---- the schedule calendar ------------------------------------------------
   Blocks are positioned absolutely inside a day column, so a slot's height on screen is
   its duration. The four states are colour PLUS a word on the block, because red-vs-green
   alone is not something everyone can read. */
.legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12px; color: var(--quiet, #888); }
.legend .sw { display: inline-block; width: 10px; height: 10px; border-radius: 3px;
  margin-right: 5px; vertical-align: middle; }
.sw.series  { background: #7fb2e5; }
.sw.oneoff  { background: #5fbf7f; }
.sw.pending { background: rgba(151, 116, 224, .25); border: 1px dashed #a98ce8; }
.sw.err     { background: #d9534f; }

.cal { border: 1px solid var(--line, #2a2a2a); border-radius: 8px; margin-top: 10px; }
.cal-top { display: flex; justify-content: space-between; gap: 12px; align-items: center;
  padding: 8px 10px; border-bottom: 1px solid var(--line, #2a2a2a); flex-wrap: wrap; }
.cal-tz { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.cal-tz label { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.cal-nav { display: flex; align-items: center; gap: 8px; font-size: 12px; }

.cal-grid { display: grid; grid-template-columns: 56px 1fr; }
.cal-rail { border-right: 1px solid var(--line, #2a2a2a); padding-top: 30px; }
.rail-h { position: relative; }
.rail-h span { position: absolute; right: 6px; top: -7px; font-size: 10px; color: var(--quiet, #888); }
.cal-cols { display: grid; grid-template-columns: repeat(7, 1fr); }
.cal-head { grid-column: 1 / -1; height: 30px; display: grid;
  grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--line, #2a2a2a); }
.cal-h { padding: 6px 8px; font-size: 11px; color: var(--quiet, #888);
  border-left: 1px solid var(--line, #2a2a2a); }
.cal-col { position: relative; border-left: 1px solid var(--line, #2a2a2a); }

.blk { position: absolute; left: 2px; right: 2px; border-radius: 4px; padding: 2px 5px;
  font-size: 10px; line-height: 1.25; overflow: hidden; cursor: pointer;
  border: 1px solid rgba(0, 0, 0, .25); color: #10151a; }
.blk b { display: block; font-size: 10.5px; font-weight: 600; }
.blk span { opacity: .8; }
.blk i { display: block; font-style: normal; font-size: 9.5px; }
.blk.series  { background: #7fb2e5; }
.blk.oneoff  { background: #5fbf7f; }
.blk.pending { background: rgba(151, 116, 224, .18); border: 1px dashed #a98ce8;
                 color: #ded2fb; }
.blk.err     { background: #d9534f; color: #fff; }
.blk:hover { filter: brightness(1.12); }

/* ---- the slot dialog ---- */
.modal { position: fixed; inset: 0; background: rgba(0, 0, 0, .5); display: grid;
  place-items: center; z-index: 50; padding: 16px; }
.modal-card { background: var(--bg, #16181c); border: 1px solid var(--line, #2a2a2a);
  border-radius: 10px; padding: 14px 16px; width: min(520px, 100%); max-height: 90vh;
  overflow: auto; }
.modal-card h2 { margin: 0 0 4px; font-size: 16px; }
.slotdays { display: flex; gap: 10px; flex-wrap: wrap; font-size: 12px; }
.slotdays .day { display: flex; align-items: center; gap: 4px; }
.btn.danger { border-color: #a33; color: #e88; }


/* ---- the slot dialog was drawing on load, and Cancel did nothing --------------
   The rule below is the whole fix for both: `.modal { display: grid }` outranked the
   `hidden` attribute, so the UA's [hidden] { display: none } never applied. Setting
   hidden from Javascript therefore looked like a dead button. */
.modal[hidden] { display: none; }

/* ---- shows on the left, the week on the right ---- */
.sched-wrap { display: flex; gap: 16px; align-items: flex-start; }
.sched-left { flex: 0 0 248px; max-width: 248px; }   /* narrower: the table
                rows fit in less, and the grid wants the room */
.sched-left h3 { margin: 0 0 4px; font-size: 13px; text-transform: uppercase;
                 letter-spacing: .04em; color: var(--quiet, #8a8f98); }
.sched-right { flex: 1 1 auto; min-width: 0; }
@media (max-width: 900px) { .sched-wrap { flex-direction: column; }
                            .sched-left { flex: 1 1 auto; max-width: none; width: 100%; } }

#cal-shows li.drag { cursor: grab; }
#cal-shows li.drag:hover { border-color: var(--accent, #4a90d9); }
#cal-shows li.drag:active { cursor: grabbing; }
#cal-shows li.drag .who-r { display: block; }
.cal-col { transition: background-color .08s linear; }
.cal-col.droptarget { background: rgba(74, 144, 217, .10); }


/* ---- Episodes: the list scrolls on its own ----------------------------------
   A show can have dozens of episodes; without a cap the list pushes the editor down the
   page and you scroll the whole document to find one. 62vh keeps the editor in view. */
#episode-list { max-height: 62vh; overflow-y: auto; overscroll-behavior: contain; }

/* Actions moved above the player, and smaller - they are a toolbar, not the subject. */
.actions.compact { margin: 10px 0 14px; gap: 6px; }
.actions.compact .btn { font-size: 12px; padding: 5px 10px; }

/* What a delete will take, spelled out in the dialog. */
.del-list { list-style: disc; margin: 6px 0 12px 20px; padding: 0; font-size: 13.5px; }
.del-list li { margin: 2px 0; }

/* ---- the grid gets a clock, a zoom and a resize grip ------------------------
   .cal-cols must be positioned so the now line can be placed against it, and the line is
   measured from the columns' own top so the day headers do not offset it. */
.cal-cols { position: relative; }
.cal-zoom label { font-size: 12px; color: var(--quiet, #8a8f98); }
.cal-zoom select { margin-left: 4px; }
.nowline { position: absolute; left: 0; right: 0; height: 0;
           border-top: 2px solid var(--err, #d9534f); z-index: 5; pointer-events: none; }
.blk-resize { position: absolute; left: 0; right: 0; bottom: 0; height: 7px;
              cursor: ns-resize; background: linear-gradient(transparent, rgba(0,0,0,.18)); }
.blk { position: absolute; overflow: hidden; }
.blk.conflict { outline: 2px dashed var(--err, #d9534f); outline-offset: -2px; }
.blk i { display: block; font-size: 10.5px; font-style: normal; opacity: .9; }

/* ---- the shows panel stays put and scrolls inside itself --------------------
   Before this, a tenant with a dozen shows had a left column taller than the viewport, so
   the calendar started below the fold and finding a show meant scrolling the whole page.
   Sticky keeps the header and the list in view; the list gets its own scrollbar so the
   panel's height is bounded no matter how many shows there are. */
.sched-left { position: sticky; top: 12px; align-self: flex-start; }
#cal-shows { max-height: calc(100vh - 250px); overflow-y: auto; overscroll-behavior: contain; }
@media (max-width: 900px) {
  /* Stacked layout: sticky would pin the list over the calendar, so drop it. */
  .sched-left { position: static; }
  #cal-shows { max-height: 40vh; }
}

/* ---- "mini" buttons actually are mini --------------------------------------
   `.mini` was on the markup but no rule ever defined it, so those buttons rendered at the
   full .btn size (14px, 9x15 padding) - which is why "this week" was too big for its own
   button and crowded the nav row. nowrap keeps a two-word label on one line. */
.btn.mini, button.mini { font-size: 12px; padding: 4px 9px; line-height: 1.25;
                         white-space: nowrap; }
/* The toolbar rows. The timezone line takes a full row to itself so the note can wrap, and
   the week nav is pinned to the right of the second row - it was being pushed past the card's
   right edge and clipped by the card's own overflow, which cut "this week" in half. */
.cal-tz { flex: 1 1 100%; }
.cal-zoom { flex: 0 0 auto; }
.cal-nav { flex-wrap: wrap; }

/* ---- the shows panel: search, stripes, and the clock ------------------------
   Alternating row backgrounds, borrowed from the LibreTime media table: with more than a
   handful of shows the stripes are what let the eye track one row across the panel. */
.cal-now { margin: 0 0 8px; font-size: 12px; color: var(--quiet, #8a8f98); }
.shows-search { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; }
.shows-search input[type="search"] { flex: 1 1 auto; min-width: 0; padding: 5px 8px;
  font: inherit; font-size: 12.5px; border: 1px solid var(--line, #d5d9e0);
  border-radius: 6px; background: #fff; color: inherit; }
.shows-search .quiet { flex: 0 0 auto; font-size: 11.5px; white-space: nowrap; }
#cal-shows { padding: 0; }
#cal-shows li { padding: 7px 9px; border-radius: 0;
                border-bottom: 1px solid rgba(0, 0, 0, .05); }
#cal-shows li:nth-child(odd) { background: rgba(0, 0, 0, .032); }
#cal-shows li:hover { background: #eaf0fe; }
#cal-shows li.empty { background: none; }

/* ---- how tall is a show row -------------------------------------------------
   .who-n and .who-r only had rules under .cast, so in the shows panel they fell back to
   unstyled 16px defaults - and .list li is a flex row, so the title and the two detail
   lines were being crammed side by side. Pinning the sizes here makes the row exactly
   three lines, which is what the panel's height cap is calculated against. */
#cal-shows li { display: block; padding: 7px 9px; }
#cal-shows .who-n { display: block; font-weight: 600; font-size: 13px; line-height: 1.3; }
#cal-shows .who-r { display: block; font-size: 11.5px; line-height: 1.35;
                    color: var(--quiet, #8a8f98); }

/* ---- the shows panel as a table ---------------------------------------------
   Three cells per row - badge, show, length - so the headings above sit over their own
   column. Smaller than the old stacked rows on purpose: this is a list you scan, and the
   whole point of the shortened panel is that the calendar wants the width more. */
.shows-head, #cal-shows li { display: grid; grid-template-columns: 19px 1fr 32px 34px;
  gap: 5px; align-items: start; }
/* The header bar, shaped after the airtime media table: a tinted strip with labels, a
   sort caret and a hairline between columns, so the list reads as a table. */
.shows-head { padding: 3px 9px; font-size: 9.5px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .03em; color: #6b7280;
  background: #f1f3f6; border-top: 1px solid #e4e6eb;
  border-bottom: 1px solid #d6dae1; }
.shows-head span { overflow: hidden; white-space: nowrap; }
.shows-head span + span { border-left: 1px solid #e4e6eb; padding-left: 4px; }
.shows-head span:last-child { text-align: right; }
#cal-shows .who-slots, #cal-shows .who-len { font-size: 11px; text-align: right;
  color: var(--quiet, #8a8f98); white-space: nowrap; font-variant-numeric: tabular-nums; }
#cal-shows .who-slots { color: #9aa1ad; }
.shows-head .caret { color: #b8bec8; font-size: 8px; }
.shows-head span.on, .shows-head span.on .caret { color: #39414f; }
.shows-head span[data-sort]:hover { color: #39414f; }
#cal-shows li { display: grid; padding: 5px 9px; }
#cal-shows li.empty { display: block; }
.kind { display: inline-block; width: 14px; height: 14px; border-radius: 3px;
  font-style: normal; font-size: 10px; line-height: 14px; text-align: center;
  color: #fff; cursor: help; }
.kind.series { background: #7fb2e5; }   /* the legend's own colours */
.kind.oneoff { background: #5fbf7f; }
#cal-shows .who-txt { min-width: 0; }
#cal-shows .who-n { display: block; font-weight: 600; font-size: 12.5px; line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#cal-shows .who-r { display: block; font-size: 11px; line-height: 1.3;
  color: var(--quiet, #8a8f98); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
#cal-shows .who-len { font-size: 11px; color: var(--quiet, #8a8f98); text-align: right;
  white-space: nowrap; }

/* ==== the calendar reads like a playout calendar =============================
   Approximated from the Airtime/AutoDJ week grid: a dark panel, a muted hour rail, saturated
   blocks carrying NEAR-BLACK text (bright fill + dark ink is what makes them scannable at a
   glance), and a bright now-line. Scoped to .cal and .cal-* so the rest of the page keeps its
   light theme - only the grid changes. */
.cal { background: #4a4a4a; border-color: #5e5e5e; overflow: hidden; }
.cal-top { border-bottom: 1px solid #5e5e5e; padding-bottom: 8px; }
.cal-tz label, .cal-zoom label, .cal-nav { color: #b8b8b8; }
.cal-top select { background: #565656; color: #eef2f7; border: 1px solid #666666;
  border-radius: 5px; padding: 3px 6px; font: inherit; font-size: 12px; }
.cal-top .btn { background: #565656; color: #e8eef5; border: 1px solid #666666; }
.cal-top .btn:hover { background: #616161; }

/* the hour rail and the day headers */
.cal-grid { background: #4a4a4a; }
/* The grid gets its own scrollbar and the page stops moving. The rail and the columns are
   siblings inside this box, so they scroll together and the hours stay lined up with the
   blocks; the day strip is sticky so you always know which day you are looking at. */
.cal-grid { max-height: calc(100vh - 340px); min-height: 280px; overflow-y: auto;
  overflow-x: hidden; overscroll-behavior: contain;
  /* align-items: start is the fix for "it will not scroll all the way down". With the
     default stretch, a grid container with a max-height sizes its implicit row to the
     BOX, so the 624px of hours inside the rail and the columns overflow their tracks and
     get clipped instead of becoming scrollable area - you could never reach 23:00. */
  align-items: start; align-content: start; }
.cal-head { position: sticky; top: 0; z-index: 3; }
.cal-rail { border-right-color: #5e5e5e; }
/* The hour numbers on the left are .rail-h span, NOT .cal-h - .cal-h is only the day
   headers. Recolouring .cal-h looked like it did nothing, because it did nothing to
   the rail: the base rule is `.rail-h span { color: var(--quiet) }`, a light-theme
   variable, which is why the times stayed mid-grey on the dark panel. */
.cal-rail .rail-h { border-bottom: 1px solid #5e5e5e; }
.cal-rail .rail-h span { color: #ece7dc; font-size: 10.5px; }
.cal-h { color: #ece7dc; border-bottom: 1px solid #585858; }
/* The day strip now goes DARKER than the panel rather than lighter. Lighter-than-the-body
   by one step (#545454 on #4a4a4a) was never going to read as a header - a header has to
   separate, and going down buys more separation than going up on a mid grey. */
.cal-head { background: #4e5b6e; border-bottom: 1px solid #5e5e5e;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .07) inset; }
.cal-head .cal-h { color: #ece7dc; border-bottom: 0; font-weight: 600; }
/* The date inside each day header ("Mon 28") is its own <span class="quiet">, and the
   base rule for .quiet is `color: var(--ink-3); font-size: 13px` - a LIGHT-THEME dark
   grey, and bigger than the header it sits in. On the dark panel that numeral was
   coming out dim and oversized. Same family, slightly quieter, correct size. */
.cal-head .cal-h .quiet { color: #ece7dc; font-size: 11px; opacity: .78; }
.cal-col { border-left-color: #585858; }
.cal-col.today { background: rgba(255, 255, 255, .05); }
.cal-col.droptarget { background: rgba(63, 143, 214, .18); }

/* the blocks: bright fill, dark ink */
.blk { color: #08131d; }
.blk b { color: inherit; }
.blk span, .blk i { color: inherit; opacity: .85; }
.blk.series { background: #1a4b8a; }
.blk.oneoff { background: #1f8a70; color: #06170c; }
.blk.pending { background: rgba(151, 116, 224, .18); border: 1px dashed #a98ce8;
                 color: #ded2fb; }
.blk.pending span, .blk.pending i { color: inherit; opacity: .9; }
.blk.err { background: #d9534f; color: #fff; }
.blk.err span, .blk.err i { color: inherit; }
.blk:hover { filter: brightness(1.15); }
.blk.conflict { outline-color: #ffb020; }
.blk-resize { background: linear-gradient(transparent, rgba(0, 0, 0, .18)); }

/* where now is */
.nowline { border-top: 2px solid #ff5a5f;
  box-shadow: 0 0 6px rgba(255, 90, 95, .55); }

/* the three places that name these colours - legend, table badges, blocks - stay one
   vocabulary, so the same fill means the same thing wherever it is seen. */
.sw.series, .kind.series { background: #1a4b8a; }
.sw.oneoff, .kind.oneoff { background: #1f8a70; }

/* ==== the schedule page fits the window, so only the grid scrolls =============
   The old rule guessed at the chrome height (100vh - 340px) and guessed low: the app header,
   page title, legend and calendar toolbar stack to roughly 485px, so the grid box ran off the
   bottom of the window and the page scrolled to reach the last hours - which is the one thing
   that was meant to stop happening. Rather than keep guessing a number, the page becomes a
   column of viewport height and the grid takes whatever is LEFT (flex: 1). Nothing scrolls
   except the hours inside the grid and the shows list.

   :has() keeps this to the schedule page; every other tab lays out as before. */
@media (min-width: 901px) {
  /* No magic number here any more: schedule.js measures the chrome above the grid and sets
     this height, so it fits the window at any size or resolution. The calc() is only the
     fallback for the moment before the script runs. */
  .content:has(.sched-wrap) { height: calc(100dvh - 100px); display: flex;
    flex-direction: column; overflow: hidden; padding-bottom: 14px; }
  .sched-wrap { flex: 1 1 auto; min-height: 0; align-items: stretch; }

  /* left: the panel fills the column and its list is the only thing that scrolls */
  /* align-self: stretch is what makes the box end flush with the calendar. An earlier rule set
     align-self: flex-start on this column (for the old sticky behaviour), which sizes it to its
     own CONTENT instead of to the row - so the tray's bottom stopped wherever the show list
     happened to end. Resetting position alone did not undo it. */
  .sched-left { position: static; align-self: stretch; display: flex; flex-direction: column;
    min-height: 0; max-height: 100%; height: 100%; }
  .sched-left #cal-shows { flex: 1 1 auto; min-height: 0; max-height: none; }

  /* right: the card fills the column, the toolbar keeps its height, the grid takes the rest */
  .sched-right { display: flex; flex-direction: column; min-height: 0; }
  .sched-right .cal { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
  .cal-grid { flex: 1 1 auto; min-height: 0; max-height: none; }
}

/* ==== the empty hours are dotted graph paper, and the scrollbar belongs to the panel ====
   Flat grey gave no sense of scale - you could not tell where an hour began unless a show
   happened to sit there. The dots land on the hour lines (--hourpx, set from HOUR_PX by the
   script, so they stay put when the Hour size changes) and every 26px across. */
/* (the dotted pattern lived here briefly - it belongs on the page, not the grid) */
.cal-col { background-image: none; }

/* A white scrollbar on a dark calendar is the one bright thing in the panel, which is why it
   reads as a stripe rather than part of the grid. */
.cal-grid { scrollbar-width: thin; scrollbar-color: #7a7a7a #565656; }
.cal-grid::-webkit-scrollbar { width: 10px; height: 10px; }
.cal-grid::-webkit-scrollbar-track { background: #565656; border-left: 1px solid #5e5e5e; }
.cal-grid::-webkit-scrollbar-thumb { background: #7a7a7a; border-radius: 6px;
  border: 2px solid #565656; }
.cal-grid::-webkit-scrollbar-thumb:hover { background: #8c8c8c; }

/* ==== the calendar's scrollbar ===============================================
   This is the one that was white and is now dark grey. It is the scrollbar INSIDE the calendar
   card - not the page, and not the empty hours. Pale light yellow, as asked, with a slightly
   deeper yellow thumb so it can still be found against its own track. */
.cal-grid { scrollbar-width: thin; scrollbar-color: #e3d9a4 #fffdf2; }
.cal-grid::-webkit-scrollbar { width: 12px; height: 12px; }
.cal-grid::-webkit-scrollbar-track { background: #fffdf2; border-left: 1px solid #ece5c8; }
.cal-grid::-webkit-scrollbar-thumb { background: #e3d9a4; border-radius: 6px;
  border: 3px solid #fffdf2; }
.cal-grid::-webkit-scrollbar-thumb:hover { background: #d9cd8e; }
.cal-grid::-webkit-scrollbar-corner { background: #fffdf2; }

/* ==== the toolbar above the grid =============================================
   It was inheriting the panel grey, so it read as part of the grid rather than as the controls
   sitting above it. Lighter than the grid (#5c5c5c on #4a4a4a) and clearly not black - the
   point is to separate the three bands: toolbar, then the dark day strip, then the work
   surface. The controls go DARKER than the bar they sit on, so they read as inset dials, and
   the labels come up a step because a mid grey label on a lighter bar loses contrast. */
/* The chrome above the grid is one slate family rather than two more greys. Three neutral
   greys stacked read as flat; a hue on the controls separates them from the work surface
   without adding weight, and it sits with the app's blue accents and the blue blocks. */
.cal-top { background: #5b6a80; padding: 9px 10px; border-bottom: 1px solid #64748c; }
.cal-tz label, .cal-zoom label, .cal-nav { color: #e2e8f0; }
.cal-top .help { color: #d9e1ec; }
.cal-top select { background: #48556b; border-color: #64748c; }
.cal-top .btn { background: #48556b; border-color: #64748c; }
.cal-top .btn:hover { background: #64748c; }

/* Each control stays on one line. "Times shown in" and "Hour size" were wrapping INSIDE their
   labels, so the dropdown dropped below the words - the label box was narrower than its text
   and the words broke. nowrap on the label keeps the words and the dropdown together. */
.cal-tz label, .cal-zoom label { white-space: nowrap; }

/* ==== the toolbar is laid out, not guessed ===================================
   Two faults, one cause. The bar was a wrapping FLEX row, so:
     - "Hour size" put its dropdown on the next line, because .cal-zoom's label was a plain
       inline label with no flex row of its own, so the select fell below the words;
     - "this week" ran past the card's right edge, because a wrapping flex row has no column to
       stop at - it just keeps pushing, and the card's overflow clipped the button.
   Four cells in a grid cannot do either: the nav sits in its own column and is pinned to the
   right edge, and each label is a flex row so its dropdown stays beside its words. */
/* The nav sits BESIDE the Hour size control, not pinned to the right edge. Pinned to the edge it
   ended up sheared by the card's own overflow - "this week" half cut off and the page looking
   like it ran off. Butted up to the left of its column there is slack all the way to the edge,
   so it cannot be clipped however the window is sized. */
.cal-top { display: grid; grid-template-columns: max-content 1fr;
  grid-template-areas: "tz tz" "zoom nav";
  gap: 8px 16px; align-items: center; }
.cal-tz { grid-area: tz; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.cal-zoom { grid-area: zoom; display: flex; align-items: center; }
/* margin-left MUST stay 0 here. An auto margin on a grid item beats justify-self: it eats the
   free space in the item's area and pins it right, which is why this kept snapping back to
   the far edge and getting sheared no matter what justify-self said. */
.cal-nav { grid-area: nav; justify-self: start; margin-left: 0; margin-right: 0;
  display: flex; align-items: center; gap: 8px; min-width: 0; }
.cal-tz label, .cal-zoom label { display: flex; align-items: center; gap: 6px;
  white-space: nowrap; }
#cal-tz-note { min-width: 0; overflow-wrap: anywhere; }

/* ==== a swatch is a swatch, an error box is an error box =====================
   The legend marks "problem" with <i class="sw err">, and .err is also the class for the red
   ERROR BOXES (margin-top 14px, padding 10px 12px). The swatch picked those up, so it rendered
   as a big red slab pushed below the legend line instead of a 10px square. This resets the box
   on any swatch inside the legend; the colour still comes from .sw.err. */
.legend .sw { display: inline-block; width: 10px; height: 10px; min-width: 0; padding: 0;
  margin: 0 5px 0 0; border: 0; border-radius: 3px; vertical-align: -1px; line-height: 0;
  font-size: 0; }
.legend .sw.series { background: #1a4b8a; }
.legend .sw.oneoff { background: #1f8a70; }
.legend .sw.pending { background: rgba(151, 116, 224, .25); border: 1px dashed #a98ce8; }
.legend .sw.err { background: #d9534f; border: 0; }

/* "this week" is the widest label in the nav and was set to the same padding as the bare
   arrows, so it came out cramped against them. Wider padding now - there is slack all the way
   to the card edge, so it costs nothing. */
#cal-today { padding: 6px 22px; min-width: 104px; font-size: 12.5px; font-weight: 600; }

/* ==== the shows tray =========================================================
   A bordered box, because the list is a container you pick a show OUT OF - the calendar columns
   are the drop targets, this is the source. It lifts while a drag is in flight so the drag has
   visible feedback at the place it started, not only where it might land. */
.shows-tray { border: 1px solid #d7dbe1; border-radius: 8px; background: #fff;
  overflow: hidden; display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
/* the title is the tray's header bar, so the box reads as a panel with a name */
.shows-tray > h3 { margin: 0; padding: 9px 12px; font-size: 12px; letter-spacing: .06em;
  background: #f6f7f9; border-bottom: 1px solid #e6e9ee; color: #5b6472; }
.shows-tray > .help { margin: 0; padding: 8px 12px 0; }
.shows-tray > .cal-now { margin: 0; padding: 6px 12px 0; }
.shows-tray .shows-search { margin: 0; padding: 8px 12px; }
.shows-tray #cal-shows { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.shows-tray.dragging { border-color: #4a90d9; box-shadow: 0 0 0 3px rgba(74, 144, 217, .18); }
.shows-tray.dragging .tray-hint { color: #4a90d9; }
.tray-hint { margin: 0; padding: 6px 10px; font-size: 11px; color: #8a8f98;
  border-top: 1px dashed #e4e7eb; text-align: right; }

/* ==== the two halves are ONE panel ==========================================
   They were two cards sitting near each other: a 16px gap, the calendar dropped 10px by its own
   margin-top, and two sets of rounded corners facing each other - so the eye read two boxes.
   Now there is one frame around both, no gap, the tops level, and the junction between them is
   a divider rather than a pair of corners. Nothing inside changed; only the join. */
.sched-wrap { gap: 0; border: 1px solid #c9ced6; border-radius: 10px; overflow: hidden;
  background: #fff; align-items: stretch; }
.shows-tray { border: 0; border-right: 1px solid #c9ced6; border-radius: 0; }
.sched-right .cal { border: 0; border-radius: 0; margin-top: 0; }

/* ==== today, in the day strip ================================================
   The lettering only - no rule under the cell, no extra furniture. Bright yellow, because it
   has to hold its own against the white day names either side of it and nothing else in this
   header is a warm colour, so it reads as a mark rather than a theme. */
.cal-head .cal-h.today { color: #ffd400; }
.cal-head .cal-h.today .quiet { color: #ffd400; opacity: 1; }

/* The clock under the page title is a status line, not a paragraph: it ticks, so it gets tabular
   figures (otherwise the numbers jitter as the seconds change width) and it stays quiet so it
   does not compete with the heading it sits under. */
.pagehead .cal-now { margin: 5px 0 0; font-size: 13px; color: var(--quiet, #8a8f98);
  font-variant-numeric: tabular-nums; }

/* The station clock under the heading: bold, with the show name in blue so the eye lands on
   WHAT is next rather than on the word "NEXT". */
.pagehead .cal-now { font-weight: 700; }
.pagehead .cal-now .nxt-who { color: #2f6fd0; }

/* The now-line carries a small "now" tag at its left end. A bare red rule across the grid reads
   as a strikethrough on whatever it crosses - which is exactly how it looked at 15:00, sitting
   on the dashed "This week Fantasy" blocks - so the line names itself. */
.nowline::before { content: 'now'; position: absolute; left: 3px; top: -8px; z-index: 5;
  background: #ff5a5f; color: #fff; font-size: 9px; line-height: 15px; padding: 0 5px;
  border-radius: 3px; letter-spacing: .04em; }

/* ==== the brand mark =======================================================
   On the sign-in panel and at the top of the left menu. Served as .webp: the PNG of the same
   artwork was 290 KB against 30 KB - a detailed 3D render is the case PNG is worst at, and this
   loads on every page. It is pre-rounded with transparent corners, so it sits on white without
   carrying a dark square with it. */
.brandmark { display: block; width: 176px; max-width: 100%; height: auto; margin: 2px auto 6px; }
.navmark { display: block; width: 100%; max-width: 122px; height: auto; margin: 2px 0 12px; }

/* Creem review: site footer + legal pages */
.sitefoot{max-width:1100px;margin:40px auto 24px;padding:16px;text-align:center;font-size:13px;opacity:.75}
.sitefoot a{color:inherit;text-decoration:none;border-bottom:1px dotted currentColor}
.legal h3{margin-top:20px}
.legal ul{margin:8px 0 10px 22px}
.legal li{margin:4px 0}
.legal code{padding:1px 5px;border-radius:4px;background:rgba(255,255,255,.08)}

/* ==== the paywall ==========================================================
   Same shell as the landing page, but it leads with what happened rather than what we
   sell, and the buttons are the whole point of the page. */
.paywall-h { margin: 0 0 6px; font-size: 21px; }
.loginbox .card p { margin: 6px 0 0; }
.loginbox .card .btn { margin-top: 12px; }

/* Cover + jingle block, in the show editor */
.mediagrid { display: grid; grid-template-columns: 132px 1fr; gap: 16px; align-items: start; }
.mediabox { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.medialabel { font-size: 12px; font-weight: 600; color: var(--ink-2, #4b5563); }
.mediabox img { width: 132px; height: 132px; border-radius: 8px; object-fit: cover;
  border: 1px solid var(--line, #d7dbe1); background: #f1f3f6; }
.mediabox audio { width: 100%; max-width: 340px; height: 34px; }
@media (max-width: 640px) { .mediagrid { grid-template-columns: 1fr; } }

/* ==========================================================================
   The front page. Its own palette, scoped to .mkt so none of it can reach the
   panel: the hero is dark (the artwork's own world) and the body below is the
   app's light, so the page opens loud and settles down to read.
   ========================================================================== */
.mkt { --ink: #14121c; --mut: #5c5870; --vio: #6d3bd6; --cy: #22d3ee; --acc: #ff6a3d;
  color: var(--ink); background: #fff; }
.mkt-bar { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 14px 22px; background: #14102a; }
.mkt-logo { display: flex; align-items: center; gap: 14px; text-decoration: none;
  color: #fff; font-size: 21px; letter-spacing: -.01em; }
/* At 34px the badge was mush - the android's face and headphone rims are the whole point of
   it, so it needs to be big enough to read as a face. */
.mkt-logo img { width: 56px; height: 56px; border-radius: 13px; }
.mkt-logo b { color: var(--cy); }
.mkt-hero { position: relative; background: #14102a; overflow: hidden; min-height: 420px;
  display: flex; align-items: center; }
.mkt-hero-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  object-position: 70% center; }
.mkt-hero::after { content: ''; position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(14,10,32,.96) 0%, rgba(14,10,32,.88) 38%,
    rgba(14,10,32,.35) 62%, rgba(20,16,42,.15) 100%); }
.mkt-hero-inner { position: relative; z-index: 1; max-width: 620px; padding: 54px 22px 60px; }
.mkt-kicker { margin: 0 0 12px; font-size: 12px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--cy); font-weight: 700; }
.mkt h1 { margin: 0 0 16px; font-size: 44px; line-height: 1.06; font-weight: 800;
  letter-spacing: -.025em; color: #fff; }
.mkt-sub { margin: 0 0 26px; font-size: 16px; line-height: 1.6; color: #cfc9e6; max-width: 540px; }
.mkt-cta { display: flex; gap: 12px; flex-wrap: wrap; }
.mkt-pill { display: inline-block; padding: 12px 22px; border-radius: 999px; font-weight: 700;
  font-size: 14.5px; text-decoration: none; border: 1px solid transparent; cursor: pointer;
  background: var(--acc); color: #fff; box-shadow: 0 6px 18px rgba(255,106,61,.32); }
.mkt-pill:hover { filter: brightness(1.06); }
.mkt-pill.ghost { background: transparent; color: #fff; border-color: rgba(255,255,255,.34);
  box-shadow: none; }
.mkt-pill.ghost:hover { border-color: #fff; }
.mkt-pill.widest { display: block; text-align: center; margin-top: 16px; }
.mkt-plan .mkt-pill.ghost { color: var(--vio); border-color: rgba(109,59,214,.4); }
.mkt-note { margin: 14px 0 0; font-size: 13px; color: #a79fc4; }
.mkt-note.center { text-align: center; color: var(--mut); margin-top: 18px; }
.mkt-sec { max-width: 1040px; margin: 0 auto; padding: 54px 22px; }
.mkt-label { margin: 0 0 18px; font-size: 12px; font-weight: 800; letter-spacing: .16em;
  text-transform: uppercase; color: var(--vio); }
/* How it works: a snapping rail of cards, each with its own artwork and the copy laid over
   the bottom third. The gradient is doing real work - it is the only reason white text is
   readable on four different pictures. */
.mkt-railwrap { position: relative; }
.mkt-rail { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory;
  padding: 2px 2px 10px; scrollbar-width: thin; }
/* Two cards at a time, and wider than tall: a card that is 2-up needs half the rail minus
   half the gap, and the square artwork is cropped to a band (biased upward so a subject's
   head is not the first thing cut). */
.mkt-card { position: relative; flex: 0 0 calc(50% - 8px); aspect-ratio: 16 / 10;
  border-radius: 18px; overflow: hidden; background: #14102a; scroll-snap-align: start; }
.mkt-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  object-position: 50% 38%; }
.mkt-card::after { content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10,7,24,.10) 0%, rgba(10,7,24,.45) 52%, rgba(10,7,24,.93) 100%); }
.mkt-card-in { position: relative; z-index: 2; height: 100%; padding: 16px 18px 20px;
  display: flex; flex-direction: column; justify-content: space-between; color: #fff; }
.mkt-cardnum { display: inline-flex; align-items: center; justify-content: center; width: 30px;
  height: 30px; border-radius: 50%; background: rgba(255,255,255,.16);
  border: 1px solid rgba(255,255,255,.3); font-weight: 800; font-size: 13px; }
.mkt-cardtext h3 { margin: 0 0 7px; font-size: 17px; letter-spacing: -.01em; }
.mkt-cardtext p { margin: 0; font-size: 13.5px; line-height: 1.55; color: rgba(255,255,255,.86); }
.mkt-railnav { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.mkt-arrow { width: 38px; height: 38px; border-radius: 50%; cursor: pointer; font-size: 20px;
  line-height: 1; color: var(--vio); background: #fff; border: 1px solid #ddd6f0; }
.mkt-arrow:hover { background: #f4f0ff; }
.mkt-railhint { font-size: 12.5px; color: var(--mut); }
@media (max-width: 700px) {
  /* below this, two cards are too narrow to read, so it becomes one card and a peek */
  .mkt-card { flex-basis: 82vw; }
}
.mkt-split { display: grid; grid-template-columns: 1fr 1fr; gap: 34px; align-items: center; }
.mkt-shot { position: relative; }
.mkt-shot img { display: block; width: 100%; height: 300px; object-fit: cover;
  object-position: 50% center; border-radius: 16px; box-shadow: 0 18px 40px rgba(20,16,42,.18); }
/* The player sits ON the picture, because it is a demonstration of the thing the picture
   claims: two hosts, two voices. */
.mkt-player { position: absolute; left: 12px; right: 12px; bottom: 12px; display: flex;
  align-items: center; gap: 12px; padding: 9px 13px; border-radius: 12px;
  background: rgba(12,8,28,.82); border: 1px solid rgba(255,255,255,.14);
  box-shadow: 0 10px 26px rgba(0,0,0,.35); }
.mkt-player-label { color: #fff; font-size: 11.5px; font-weight: 800; letter-spacing: .1em;
  text-transform: uppercase; white-space: nowrap; }
.mkt-player audio { flex: 1; min-width: 0; height: 34px; }
@media (max-width: 620px) { .mkt-player-label { display: none; } }
.mkt-caption { margin: 10px 0 0; font-size: 12px; color: var(--mut); }
.mkt-split-text h2 { margin: 0 0 14px; font-size: 27px; line-height: 1.2; letter-spacing: -.02em; }
.mkt-check { margin: 0; padding: 0; list-style: none; }
.mkt-check li { position: relative; padding-left: 26px; margin-bottom: 11px; font-size: 14.5px;
  line-height: 1.6; color: #3b3750; }
.mkt-check li::before { content: '✓'; position: absolute; left: 0; top: 0; color: var(--vio);
  font-weight: 800; }
.mkt-plans { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
.mkt-plan { position: relative; border: 1px solid #e6e2f2; border-radius: 18px; padding: 26px 24px; }
.mkt-plan.best { border-color: var(--vio); box-shadow: 0 16px 40px rgba(109,59,214,.16); }
.mkt-plan h3 { margin: 0 0 4px; font-size: 15px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--mut); }
.mkt-price { margin: 0 0 12px; font-size: 38px; font-weight: 800; letter-spacing: -.02em; }
.mkt-price span { font-size: 15px; font-weight: 500; color: var(--mut); letter-spacing: 0; }
.mkt-plan p { font-size: 14.5px; line-height: 1.6; color: var(--mut); }
.mkt-badge { position: absolute; top: -12px; right: 18px; background: var(--acc); color: #fff;
  font-size: 11px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  padding: 5px 11px; border-radius: 999px; }
.mkt-foot { background: #14102a; color: #b9b2d4; padding: 34px 22px; text-align: center;
  font-size: 13px; }
.mkt-foot p { margin: 5px 0; }
.mkt-foot code { color: var(--cy); background: rgba(255,255,255,.07); padding: 1px 6px;
  border-radius: 5px; }
.mkt-foot a { color: #fff; }
.mkt-h2 { margin: 0 0 22px; font-size: 27px; line-height: 1.22; letter-spacing: -.02em;
  max-width: 660px; }
.mkt-for { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.mkt-forcard { border: 1px solid #e6e2f2; border-radius: 16px; padding: 20px 18px; background: #fbfaff; }
.mkt-forcard h3 { margin: 0 0 8px; font-size: 15px; letter-spacing: -.01em; }
.mkt-forcard p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--mut); }
/* The closing statement before the footer. It LEADS with what the reader gets (their station
   stays theirs) rather than with a disclaimer - "one thing to be clear about" made the page
   sound like it had something to defend. */
.mkt-close { text-align: center; padding-bottom: 34px; }
.mkt-clearh { margin: 0 0 12px; font-size: 25px; letter-spacing: -.02em; }
.mkt-clear { max-width: 740px; margin: 0 auto; font-size: 16px; line-height: 1.6;
  color: var(--ink); }

@media (max-width: 900px) {
  .mkt-steps, .mkt-for { grid-template-columns: 1fr 1fr; }
  .mkt-split, .mkt-plans { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .mkt-for { grid-template-columns: 1fr; }
  .mkt h1 { font-size: 32px; }
  .mkt-hero-inner { padding: 40px 20px 46px; }
}

/* The per-episode bin in the list. Quiet by default so a list of episodes does not read as
   a list of hazards, red on hover so it is unmistakable when aimed at. */
.rowdel { float: right; margin-left: 8px; padding: 0 4px; line-height: 1.2; font-size: 13px;
  background: none; border: 0; border-radius: 6px; cursor: pointer; opacity: .45;
  filter: grayscale(1); }
.rowdel:hover { opacity: 1; filter: none; background: rgba(217,83,79,.12); }
.rowdel:focus-visible { opacity: 1; filter: none; outline: 2px solid #d9534f; }

/* ==========================================================================
   The dashboard's month calendar. Read-only: rendered from the same cadences
   and episodes the Schedule tab uses, and it carries none of that page's
   interaction. The colour vocabulary is deliberately identical.
   ========================================================================== */
.dashcal-card { padding-bottom: 14px; }
.dashcal-head { display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 12px; }
.dashcal-head h3 { margin: 0; }
.dashcal-head .quiet { font-size: 12.5px; max-width: 460px; }
.dashcal { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.dc-h { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px;
  font-size: 11px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: #6b7280; }
.dc-h span { padding: 0 2px 4px; }
.dc-d { min-height: 88px; border: 1px solid #e6e9ee; border-radius: 10px; padding: 5px 6px 6px;
  background: #fff; display: flex; flex-direction: column; gap: 3px; overflow: hidden; }
.dc-d.off { background: #fafbfc; border-color: #eef1f4; }
.dc-d.off .dc-n { color: #c3c9d2; }
/* Days that have gone by sit back a shade, so the month reads as "where am I" at a glance. */
.dc-d.past { background: #f7f8fa; }
.dc-d.past .dc-n { color: #9aa3ae; }
.dc-d.today { border-color: #ffd400; box-shadow: inset 0 0 0 1px #ffd400; }
.dc-n { font-size: 11.5px; font-weight: 700; color: #4b5563; }
.dc-b { display: block; font-size: 10.5px; line-height: 1.3; padding: 2px 5px; border-radius: 5px;
  color: #fff; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dc-b.auto { background: #1a4b8a; }
.dc-b.indv { background: #1f8a70; }
.dc-b.none { background: rgba(151,116,224,.18); border: 1px dashed #a98ce8; color: #4f3f78; }
.dc-b.bad  { background: #d9534f; }
/* Past vs upcoming is carried by FORM, not by hue: the hue is already saying what state the
   airing is in, and a tenant must be able to read both at once. Solid = still to come,
   outlined = already aired. Failures stay solid either way - a past failure is the one thing
   you should never have to hunt for. */
.dc-b.done { opacity: 1; background: transparent; border: 1px solid currentColor; }
.dc-b.auto.done { color: #2c6ba5; }
.dc-b.indv.done { color: #2f7a49; }
.dc-b.none.done { color: #6b5a9c; border-style: dashed; }
.dc-b.bad.done  { background: #d9534f; border-color: #d9534f; color: #fff; }
.dc-b.live { box-shadow: 0 0 0 2px #ffd400; }
.dashcal-key { margin: 12px 0 0; font-size: 12px; display: flex; align-items: center;
  gap: 8px; flex-wrap: wrap; }
.dashcal-key .dc-b { display: inline-block; }
@media (max-width: 760px) {
  .dashcal { gap: 4px; }
  .dc-d { min-height: 62px; }
  .dc-b { font-size: 9.5px; padding: 1px 3px; }
}

/* ==========================================================================
   The reference's two identifying moves.
   ========================================================================== */
/* A slow blue-to-white-to-blue wash behind the page. Fixed, so it reads as a
   lit room rather than as a stripe that scrolls past. Panels are opaque white,
   so this only ever shows in the gutters and between cards. */
body { background: linear-gradient(180deg, #e3f1fb 0%, #f5fbff 42%, #eaf4fc 100%);
  background-attachment: fixed; }

/* Pill buttons with a blue gradient and a top highlight, so they look pressed
   out of the page rather than drawn on it. */
.btn, button.btn { border-radius: 999px; }
.btn.primary {
  background: linear-gradient(180deg, #4a90e2 0%, #3399ff 100%);
  border: 1px solid transparent;
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.35), 0 6px 16px rgba(51,153,255,.28);
}
.btn.primary:hover { filter: brightness(1.05); }
.btn.danger { border-radius: 999px; }
.btn.mini { border-radius: 999px; }
/* Inputs pick up the theme without needing to be restyled individually. */
input[type=text], input[type=email], input[type=password], input[type=number], select, textarea {
  border-color: var(--line-2); border-radius: 10px; }
input[type=text]:focus, input[type=email]:focus, input[type=password]:focus,
input[type=number]:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(51,153,255,.18); }

/* The episodes tree. One folder per show; episodes nest under it, so a long history costs
   one row instead of a scroll. Folder drawn inline in the reference's soft light blue. */
.epgrp { list-style: none; }
.ephead { display: flex; align-items: center; gap: 7px; width: 100%; padding: 6px 6px;
  background: none; border: 0; border-radius: 8px; cursor: pointer; text-align: left;
  font: inherit; color: var(--ink); }
.ephead:hover { background: rgba(51,153,255,.08); }
.epf { width: 17px; height: 14px; flex: 0 0 auto; }
.epc { width: 11px; height: 11px; flex: 0 0 auto; color: var(--ink-3);
  transition: transform .14s ease; }
.epgrp.open > .ephead .epc { transform: rotate(90deg); }
.ept { flex: 1 1 auto; font-weight: 600; font-size: 13px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.epn { flex: 0 0 auto; font-size: 11px; font-weight: 700; color: var(--ink-2);
  background: #eef5fd; border-radius: 999px; padding: 1px 7px; }
/* The flat lists lay a row out as two slots - a title and a detail. An episode row inside
   the tree has no title (the folder carries it), so it inherited that layout and the detail
   was squeezed into the narrow slot, wrapping a character at a time. These rows are plain
   blocks and take the whole width, whatever the list around them does. */
.epgrp, .epkids > li { display: block; }

/* Everything in the tree is clamped to the column's width. The episode rows carry long
   status text (a failure message, for instance), and without this that text pushes the
   whole list sideways into a horizontal scrollbar instead of wrapping - which is what made
   the tree look like it was expanding to the right and getting cut off. */
.epgrp, .epkids, .epkids > li { width: 100%; max-width: 100%; min-width: 0;
  box-sizing: border-box; }
.epkids { display: none; list-style: none; margin: 2px 0 6px; padding: 0 0 0 18px;
  overflow: hidden; }
.epgrp.open > .epkids { display: block; }
/* Rows wrap rather than truncate: in a tree, a clipped sentence is worse than a tall row. */
.epkids .s { display: block; width: 100%; white-space: normal;
  overflow-wrap: break-word; font-size: 11.5px; line-height: 1.4; padding: 3px 0 2px; }
.epkids .rowdel { float: none; margin-left: 6px; vertical-align: middle; }

/* ==========================================================================
   The episodes tree, qualified by its container id on purpose. That list is
   .list, and .list li lays a row out as flex slots - so the tree's rows were
   inheriting a two-slot layout with no title slot to fill, which squeezed the
   detail column to about one character wide. Every rule here outranks it.
   ========================================================================== */
#episode-list .epgrp,
#episode-list .epkids,
#episode-list .epkids > li { display: block; width: auto; max-width: 100%; min-width: 0;
  box-sizing: border-box; }
#episode-list .epkids { padding: 0 0 0 18px; overflow: hidden; }
/* The row is flex again, but this time the TEXT is the flexible part (flex: 1 1 auto with
   min-width: 0). That is the whole difference from the layout that collapsed to one character
   wide: a flex child with no flex-grow shrinks to its minimum content width. */
#episode-list .epkids > li { display: flex; align-items: flex-start; gap: 7px;
  padding: 4px 7px; margin: 3px 0; border-radius: 7px; border-left: 0; }
#episode-list .epkids > li:hover { background: #f2f8ff; }
#episode-list .epkids > li.on { background: #eaf0fe; }
#episode-list .epkids .s { flex: 1 1 auto; min-width: 0; display: block; white-space: normal;
  overflow-wrap: break-word; color: var(--ink-3); font-size: 11.5px; line-height: 1.4; }
#episode-list .epkids .epi { flex: 0 0 auto; width: 14px; height: 14px; margin-top: 2px;
  color: var(--ink-3); }
#episode-list .epkids > li.on .epi { color: var(--accent); }
#episode-list .epkids .rowdel { float: none; margin-left: 6px; vertical-align: middle; }
#episode-list .ephead { display: flex; align-items: center; gap: 7px; }

/* ---------------------------------------------------------------------------------------
   Script blocks. One card per line, dragged by its handle.

   Deliberately NOT scoped to #ep-lines: while you drag, Sortable appends a clone to <body>,
   and a clone that loses its styling mid-drag is exactly the "I can't see it moving" problem.
   .scriptline exists only in the episode editor, so there is nothing else to hit.
   --------------------------------------------------------------------------------------- */
#ep-script .scripthead { display: none; }
/* Script blocks. Host and tone share one column, stacked, which hands the script the width the
   two side-by-side dropdowns were eating. The script gets the room it needs and carries a
   tighter, smaller face than the rest of the panel. Everything is placed explicitly: with a
   1fr track in the mix, auto-placement is how a row quietly ends up somewhere you did not plan. */
.scriptline { display: grid; gap: 8px 10px; align-items: start; padding: 8px 12px 8px 10px;
  grid-template-columns: 18px 24px minmax(96px, 128px) minmax(0, 1fr) 84px;
  background: var(--panel, #fff); border: 1px solid var(--line, #d8e7f5);
  border-radius: 11px; margin: 0 0 8px; }
.scriptline .grab { grid-column: 1; grid-row: 1; }
.scriptline .n    { grid-column: 2; grid-row: 1; }
.scriptline .sp   { grid-column: 3; grid-row: 1; }
.scriptline .em   { grid-column: 3; grid-row: 2; }
.scriptline .tx   { grid-column: 4; grid-row: 1 / span 2; }
.scriptline .grab { cursor: grab; color: #b9cbe0; font-size: 13px; line-height: 1; padding-top: 6px;
  user-select: none; touch-action: none; }
.scriptline .grab:hover { color: var(--accent, #3399ff); }
.scriptline .grab:active { cursor: grabbing; }
.scriptline .grab:focus-visible { outline: 2px solid var(--accent, #3399ff); outline-offset: 2px;
  border-radius: 4px; }
.scriptline .n { color: var(--quiet, #888); font-size: 11.5px; padding-top: 7px; }
.scriptline .sp, .scriptline .em { width: auto; }
.scriptline .tx { width: 100%; min-width: 0; resize: vertical; min-height: 82px;
  font-size: 12.5px; line-height: 1.4; padding: 5px 7px; }
.scriptline .sp, .scriptline .em { min-width: 0; }
.scriptline .mv { grid-column: 5; grid-row: 1 / span 2; justify-content: flex-end; }

/* the three states of a drag: the block you picked up, the hole it left, and the clone that
   follows your pointer */
.scriptline.blk-chosen { opacity: .45; }
.scriptline.blk-ghost { opacity: .3; background: rgba(51, 153, 255, .07); border-style: dashed;
  border-color: var(--accent, #3399ff); }
.blk-follow { background: var(--panel, #fff); border: 1px solid var(--accent, #3399ff);
  border-radius: 11px; padding: 8px 10px; box-shadow: 0 18px 42px rgba(26, 75, 138, .28);
  transform: rotate(.4deg); opacity: .97; cursor: grabbing; }
@media (max-width: 720px) {
  .scriptline { grid-template-columns: 18px 24px minmax(0, 1fr) 84px; }
  .scriptline .sp, .scriptline .em { grid-column: 3; grid-row: auto; }
  .scriptline .tx { grid-column: 3; grid-row: auto; }
  .scriptline.audio .tag { grid-column: 3; grid-row: auto; }
  .scriptline .sp, .scriptline .em { grid-column: 3; }
  .scriptline .tx { grid-column: 3; }
  .scriptline .mv { grid-column: 4; grid-row: 1; }
}


/* Insert buttons in the block's action cell, and the audio block itself. */
.scriptline .mv { display: inline-flex; gap: 3px; align-items: center; }
.scriptline .mv .btn.tiny { padding: 1px 5px; font-size: 11px; line-height: 1.2; }
.scriptline.audio { background: #f2f9ff; border-color: var(--accent, #3399ff); }
.scriptline.audio .tag { grid-column: 3 / span 2; grid-row: 1; display: inline-flex; align-items: center;
  gap: 8px; font-size: 13px; font-weight: 600; padding: 5px 9px; background: #fff;
  border: 1px solid var(--line, #d8e7f5); border-radius: 8px; width: max-content; }
.scriptline.audio .tag .dur { color: var(--quiet, #888); font-weight: 400; font-size: 12px; }
.scriptline.audio .tag .chg { color: var(--accent, #3399ff); font-weight: 600; font-size: 12px;
  cursor: pointer; }
.scriptline.audio .tag .chg:hover { text-decoration: underline; }

/* The audio picker: a tree on the left, the folder's files on the right. */
.mp-wrap { position: fixed; inset: 0; background: rgba(16, 40, 70, .45); z-index: 9000;
  display: flex; align-items: center; justify-content: center; padding: 24px; }
.mp { background: var(--panel, #fff); border-radius: 14px; width: min(940px, 100%);
  height: min(620px, 100%); display: flex; flex-direction: column; overflow: hidden;
  box-shadow: 0 24px 60px rgba(10, 30, 60, .35); }
.mp-head { display: flex; align-items: baseline; gap: 10px; padding: 14px 16px;
  border-bottom: 1px solid var(--line, #d8e7f5); }
.mp-head b { font-size: 15px; }
.mp-sub { color: var(--quiet, #888); font-size: 12px; }
.mp-head .x { margin-left: auto; border: 0; background: none; font-size: 20px; cursor: pointer;
  color: var(--quiet, #888); line-height: 1; }
.mp-body { flex: 1 1 auto; display: grid; grid-template-columns: 290px 1fr; min-height: 0; }
.mp-tree { border-right: 1px solid var(--line, #d8e7f5); overflow: auto; padding: 8px 0; }
.mp-node { display: flex; align-items: center; gap: 8px; padding: 6px 14px; cursor: pointer;
  font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mp-node:hover { background: #f2f8ff; }
.mp-node.on { background: #eaf5ff; font-weight: 600; }
.mp-node span { margin-left: auto; color: var(--quiet, #888); font-size: 11.5px; font-weight: 400; }
.mp-kind { font-style: normal; font-size: 10px; text-transform: uppercase; letter-spacing: .05em;
  color: #8a6d1f; background: #fff6da; border-radius: 4px; padding: 1px 4px; }
.mp-list { display: flex; flex-direction: column; min-height: 0; }
.mp-q { margin: 10px 12px 6px; padding: 7px 10px; border: 1px solid var(--line, #d8e7f5);
  border-radius: 8px; font: inherit; font-size: 13px; }
.mp-rows { overflow: auto; padding: 0 6px 10px; }
.mp-row { display: grid; grid-template-columns: 1fr 190px 54px; gap: 10px; padding: 7px 8px;
  border-radius: 8px; cursor: pointer; font-size: 13px; align-items: center; }
.mp-row:hover { background: #eaf5ff; }
.mp-row .a, .mp-row .l { color: var(--quiet, #888); font-size: 12px; }
.mp-row .l { text-align: right; }
.mp-none { color: var(--quiet, #888); font-size: 12.5px; padding: 8px 10px; }
.mp-ask { color: #8a5a00; }
.mp-foot { border-top: 1px solid var(--line, #d8e7f5); padding: 10px 16px; display: flex;
  gap: 16px; align-items: center; flex-wrap: wrap; }
.mp-rightsbox { flex: 1 1 340px; font-size: 12px; color: var(--ink, #1a4b8a); }
.mp-rightsbox label { display: flex; gap: 8px; align-items: flex-start; line-height: 1.45; }
.mp-ok { color: #2f6f4f; }
.mp-urlbox { display: flex; gap: 6px; align-items: center; }
.mp-url { width: 240px; padding: 6px 9px; border: 1px solid var(--line, #d8e7f5);
  border-radius: 8px; font: inherit; font-size: 12.5px; }
@media (max-width: 760px) { .mp-body { grid-template-columns: 1fr; } .mp-tree { max-height: 150px; } }

.mp-loading { padding: 22px 20px; font-size: 13px; color: var(--ink, #1a4b8a); line-height: 1.55; }
.mp-row.sel { background: #dceeff; box-shadow: inset 0 0 0 1px var(--accent, #3399ff); }

.prog.on { color: var(--accent, #3399ff); font-weight: 600; }
.prog.err { color: #c62828; font-weight: 600; }


/* A render in flight. The banner is loud on purpose; the editor goes visibly inert so nobody
   drags something they cannot save, and the buttons are disabled rather than left to fail. */
.lockbar { background: #eaf5ff; border: 1px solid var(--accent, #3399ff); color: #14507f;
  border-radius: 10px; padding: 9px 12px; font-size: 13px; font-weight: 600; margin: 0 0 10px; }
#ep-script.locked { opacity: .7; }
#ep-script.locked .scriptline { pointer-events: none; }
#ep-script.locked .grab { cursor: not-allowed; }
#ep-script.locked .tx, #ep-script.locked select { background: #f6f8fb; cursor: not-allowed; }
.btn[disabled], .btn.primary[disabled] { opacity: .45; cursor: not-allowed; box-shadow: none; }


/* The show list's own delete: a small x that appears on the row, so a show can be removed
   without opening it. Named .show-del, not .del, because .del already belongs to a script line. */
#show-list li .t { display: flex; align-items: baseline; gap: 8px; justify-content: space-between; }
#show-list li .t > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#show-list li .show-del { border: 0; background: none; color: var(--quiet, #888); font-size: 15px;
  line-height: 1; cursor: pointer; padding: 0 3px; border-radius: 6px; flex: 0 0 auto; }
#show-list li .show-del:hover { color: #c62828; background: rgba(198, 40, 40, .1); }
#show-list li .show-del:focus-visible { outline: 2px solid var(--accent, #3399ff); }


/* The shows list rows stack. `.list li` makes a row of its children - which is right for a list
   of short items and wrong here, where the title and the meta line belong one above the other.
   Qualified with #show-list so it wins against that rule outright rather than by source order. */
#show-list li { display: block; }
#show-list li .t { margin-bottom: 2px; }
#show-list li .s { display: block; }

#show-list li .show-del svg { display: block; }
#show-list li .show-del { padding: 2px 4px; }

/* [hidden] must actually hide. The attribute is only a hint: ANY display rule on the element
   beats it, so a label laid out with `display:block` stays fully visible while carrying
   hidden="". That has now cost this project two separate bugs - the modal, and the debate-style
   field on the host form - so it is fixed once, here, for every element that uses the attribute
   rather than patched per element as each one is discovered. */
[hidden] { display: none !important; }
