:root{
  /* Celebrate Ameri'kana — sampled from the festival logo.
     The logo lives on a dark ground, so cream/green/orange are used at full
     strength only on navy. The -ink variants are darkened for text on white
     (>=4.5:1); using the raw brand colours as light-mode text fails contrast. */
  --navy:#1b242c;
  --cream:#dfeaaf;
  --green:#4bb689;
  --orange:#ed561f;
  --green-ink:#368463;      /* 4.53:1 on white */
  --orange-ink:#d44511;     /* 4.51:1 on white */
  --brand:var(--green-ink);
  --on-shift:#cfe8dc;        /* green = available / working */
  --on-shift-line:#7bbfa0;
  --off-shift:#1b242c;       /* blacked out = not on shift */
  --brand-deep:#2b6b50;
  --charcoal:#58595b;
  --ink:#21242b;
  --muted:#6b7280;
  --paper:#ffffff;
  --bg:#f6f5f2;
  --line:#e7e4de;
  --confirmed:#1f7a52;
  --confirmed-bg:#e8f3ec;
  --pending:#b9821a;
  --pending-bg:#fbf2df;
  --researching:#0891b2;
  --researching-bg:#e0f2f7;
  --checking:#2563eb;
  --checking-bg:#e7effe;
  --proposed:#475569;
  --proposed-bg:#eceff2;
  --pendingconf:#0f766e;
  --pendingconf-bg:#dcefec;
  --unavailable:#64748b;
  --unavailable-bg:#eef1f5;
  --overbudget:#c2410c;
  --overbudget-bg:#fbe9df;
  --house:#6b7280;
  --house-bg:#eeeeec;
  --stage-main:#d44511;
  --stage-main-bg:#fbe9df;
  --stage-comm:#6d7e21;
  --stage-comm-bg:#f2f5e2;
  --shadow:0 1px 2px rgba(33,36,43,.06),0 8px 24px rgba(33,36,43,.06);
  --radius:14px;
  --font:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
}
*{box-sizing:border-box;}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--font);
  -webkit-font-smoothing:antialiased;line-height:1.5;}
a{color:var(--brand-deep);text-decoration:none;}
a:hover{text-decoration:underline;}
button{font-family:inherit;}

header.app{background:var(--paper);border-bottom:1px solid var(--line);}
.brandbar{max-width:1120px;margin:0 auto;padding:18px 24px;
  display:flex;align-items:center;justify-content:space-between;gap:20px;}
/* The wordmark is cream-on-dark artwork — it needs its own navy plate to sit
   on, exactly as it does on the poster. Straight onto white it is 1.27:1. */
.amerikana-mark{display:inline-flex;align-items:center;gap:9px;text-decoration:none;
  background:var(--navy);border-radius:10px;padding:8px 14px;}
.amerikana-mark .cel{font-size:10px;font-weight:800;letter-spacing:.18em;
  text-transform:uppercase;color:var(--green);line-height:1;}
.amerikana-mark img{height:22px;width:auto;display:block;}
@media(max-width:560px){
  .amerikana-mark{padding:6px 10px;gap:7px;flex:0 0 auto;}
  .amerikana-mark .cel{display:none;}
  .amerikana-mark img{height:19px;}
  .brandbar{padding:12px 14px;gap:10px;}
  /* "Coordinated by" is the first thing to go — the mark still says who made
     it, and the header must not push the page sideways. */
  .ym-block .by{display:none;}
  .ym-logo{height:16px;}
  nav.tabs{padding:0 14px;}
}
/* min-width:0 so the credit block can actually shrink — as a flex item it
   defaults to min-content, and the 136px logo pushed the header to 418px in a
   390px viewport. */
.ym-block{display:flex;align-items:center;gap:9px;color:var(--charcoal);
  min-width:0;flex-shrink:1;}
.ym-block .by{font-size:11px;text-transform:uppercase;letter-spacing:.14em;color:var(--muted);
  white-space:nowrap;}
.ym-logo{height:20px;width:auto;max-width:100%;display:block;}
.ym-logo path,.ym-logo polygon{fill:var(--charcoal);}

.titlewrap{max-width:1120px;margin:0 auto;padding:26px 24px 0;
  display:flex;align-items:flex-end;justify-content:space-between;gap:20px;flex-wrap:wrap;}
.kicker{color:var(--brand);font-weight:700;font-size:12.5px;letter-spacing:.16em;
  text-transform:uppercase;margin:0 0 6px;}
h1.page{font-size:30px;margin:0 0 4px;letter-spacing:-.4px;}
.sub{color:var(--muted);font-size:15px;margin:0;}
.title-actions{display:flex;gap:10px;align-items:center;}

.banner{background:var(--confirmed-bg);color:var(--confirmed);font-size:13px;font-weight:600;
  text-align:center;padding:8px 16px;}

/* The tab row is wider than a phone (7 tabs vs 390px). It scrolls INSIDE
   itself — letting the page scroll sideways instead drags the header and the
   whole grid with it, which is what crew hit on their phones on show day. */
nav.tabs{max-width:1120px;margin:22px auto 0;padding:0 24px;
  display:flex;gap:4px;border-bottom:1px solid var(--line);
  overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;}
nav.tabs::-webkit-scrollbar{display:none;}
nav.tabs a{flex:0 0 auto;white-space:nowrap;}
nav.tabs a{font-size:15px;font-weight:600;color:var(--muted);
  padding:12px 16px;border-bottom:3px solid transparent;margin-bottom:-1px;text-decoration:none;}
nav.tabs a:hover{color:var(--ink);text-decoration:none;}
nav.tabs a.active{color:var(--brand);border-bottom-color:var(--brand);}

main{max-width:1120px;margin:0 auto;padding:30px 24px 60px;}

.pill{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:700;
  padding:4px 10px;border-radius:999px;letter-spacing:.02em;white-space:nowrap;}
.pill.confirmed{background:var(--confirmed-bg);color:var(--confirmed);}
.pill.pending{background:var(--pending-bg);color:var(--pending);}
.pill.researching{background:var(--researching-bg);color:var(--researching);}
.pill.checking{background:var(--checking-bg);color:var(--checking);}
.pill.proposed{background:var(--proposed-bg);color:var(--proposed);}
.pill.pendingconf{background:var(--pendingconf-bg);color:var(--pendingconf);}
.pill.unavailable{background:var(--unavailable-bg);color:var(--unavailable);}
.pill.house{background:var(--house-bg);color:var(--house);}
.dot{width:7px;height:7px;border-radius:50%;background:currentColor;}
/* Status marker over an artist photo */
.photo-badge{position:absolute;top:10px;left:10px;z-index:2;
  box-shadow:0 1px 4px rgba(0,0,0,.28);border:1px solid rgba(255,255,255,.55);}

.chips{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 24px;}
.chip{background:var(--paper);border:1px solid var(--line);border-radius:999px;
  padding:8px 14px;font-size:13px;font-weight:600;color:var(--charcoal);box-shadow:var(--shadow);}
.chip b{color:var(--ink);}

.days{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;align-items:start;}
.day h2{font-size:13px;text-transform:uppercase;letter-spacing:.12em;color:var(--charcoal);
  margin:0 0 12px;padding-bottom:8px;border-bottom:2px solid var(--line);}
.day h2 span{color:var(--muted);font-weight:600;letter-spacing:0;text-transform:none;}
.evt{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px;margin-bottom:14px;box-shadow:var(--shadow);}
.evt .time{font-size:12px;font-weight:700;color:var(--brand);letter-spacing:.02em;}
.evt .name{font-size:16px;font-weight:700;margin:3px 0 2px;}
.evt .room{font-size:12.5px;color:var(--muted);margin:0 0 10px;}
.evt .acts{border-top:1px dashed var(--line);padding-top:10px;display:flex;
  flex-direction:column;gap:9px;}
/* Scoped to the schedule card. Unscoped, this also hit the <th class="act"> /
   <td class="act"> cells on /inputs and blockified them, collapsing all nine act
   columns into one stack. Flex children are blockified anyway, so this is only
   here to keep the intent explicit. */
.evt .act{display:block;}
.act-head{display:flex;align-items:flex-start;justify-content:space-between;gap:8px;}
.act .who{font-size:14px;font-weight:600;}
.act .meta{font-size:12px;color:var(--muted);margin-top:1px;}
.act.tbd .who{color:var(--muted);font-style:italic;font-weight:500;}
.act .pill{margin-top:7px;}
.act .right{display:flex;align-items:center;gap:8px;flex-shrink:0;}
.editbtn{appearance:none;border:1px solid var(--line);background:var(--paper);color:var(--muted);
  border-radius:8px;width:26px;height:26px;cursor:pointer;font-size:13px;line-height:1;
  display:none;align-items:center;justify-content:center;}
.editbtn:hover{color:var(--ink);border-color:var(--charcoal);}
.staff .editbtn{display:inline-flex;}
.addact{display:none;margin-top:10px;font-size:12.5px;font-weight:600;color:var(--brand-deep);
  background:none;border:0;cursor:pointer;padding:0;}
.staff .addact{display:inline-block;}

.artist-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:20px;}
.artist{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);
  overflow:hidden;box-shadow:var(--shadow);display:flex;flex-direction:column;}
.photo{aspect-ratio:16/9;background:linear-gradient(135deg,#ececea,#dedbd4);
  display:flex;align-items:center;justify-content:center;position:relative;
  background-size:cover;background-position:center;}
.photo .mono{font-size:40px;font-weight:900;color:#bdb8ad;letter-spacing:-1px;}
.photo .ph-note{position:absolute;bottom:8px;right:10px;font-size:10.5px;
  color:#9a958a;letter-spacing:.06em;text-transform:uppercase;}
.artist .body{padding:18px;display:flex;flex-direction:column;gap:8px;flex:1;}
.artist .aname{font-size:19px;font-weight:800;margin:0;letter-spacing:-.2px;}
.artist .role{font-size:13px;color:var(--brand-deep);font-weight:600;margin:0;}
.artist .bio{font-size:13.5px;color:#41454d;margin:2px 0 0;}
.artist .foot{margin-top:auto;display:flex;align-items:center;justify-content:space-between;
  gap:10px;padding-top:12px;border-top:1px solid var(--line);}
.artist .slot{font-size:12px;color:var(--muted);}
.artist .slot b{color:var(--ink);}
.afee{font-weight:800;color:var(--ink);font-size:15px;}
.afee.tbd{font-weight:600;font-style:italic;color:var(--muted);font-size:13px;}
.aslot{display:block;font-size:12px;color:var(--muted);margin-top:2px;}
.links{display:flex;gap:14px;font-size:13px;font-weight:600;}

.stat{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);
  padding:16px 18px;box-shadow:var(--shadow);}
.stat .lbl{font-size:11.5px;text-transform:uppercase;letter-spacing:.1em;color:var(--muted);}
.stat .val{font-size:24px;font-weight:800;margin-top:4px;letter-spacing:-.5px;}
.stat .val.red{color:var(--brand);}
.stat .val.green{color:var(--confirmed);}
.stat .val.set{cursor:pointer;}
.stat .val.set:hover{color:var(--brand-deep);}
table.budget{width:100%;border-collapse:collapse;background:var(--paper);
  border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);}
table.budget th{text-align:left;font-size:11.5px;text-transform:uppercase;letter-spacing:.08em;
  color:var(--muted);padding:13px 18px;border-bottom:1px solid var(--line);background:#fafaf8;}
table.budget td{padding:14px 18px;border-bottom:1px solid var(--line);font-size:14px;vertical-align:top;}
table.budget tr:last-child td{border-bottom:0;}
table.budget .ev{font-weight:600;}
table.budget .day{font-size:12px;color:var(--muted);font-weight:500;}
table.budget .fee{font-weight:700;text-align:right;white-space:nowrap;}
table.budget .fee.tbd{color:var(--muted);font-weight:500;font-style:italic;}
tr.total td{background:#fafaf8;font-weight:800;font-size:15px;}
tr.total .fee{color:var(--brand);}
.note{font-size:12.5px;color:var(--muted);margin:16px 2px 0;}

/* Run of Show */
.ros-legend{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 6px;}
.ros-legend .tag{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:700;
  padding:3px 9px;border-radius:999px;letter-spacing:.02em;white-space:nowrap;}
.tag .dot{width:6px;height:6px;border-radius:50%;background:currentColor;}
.tag.loadin{background:var(--pending-bg);color:var(--pending);}
.tag.check{background:var(--checking-bg);color:var(--checking);}
.tag.call{background:var(--pendingconf-bg);color:var(--pendingconf);}
.tag.perf{background:var(--confirmed-bg);color:var(--confirmed);}
.tag.prog{background:var(--proposed-bg);color:var(--proposed);}
.tag.break{background:var(--house-bg);color:var(--house);}
.tag.strike{background:var(--overbudget-bg);color:var(--overbudget);}
/* Stage-view toggle */
.viewbar{display:flex;align-items:center;gap:12px;margin:0 0 16px;flex-wrap:wrap;}
.seg{display:inline-flex;border:1px solid var(--line);border-radius:999px;overflow:hidden;background:var(--paper);}
.seg button{appearance:none;border:0;background:none;font-family:inherit;font-size:12.5px;font-weight:600;
  color:var(--muted);padding:7px 15px;cursor:pointer;}
.seg button.on{background:var(--brand);color:#fff;}
.viewnote{font-size:11.5px;color:var(--muted);}

.ros-day{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);margin:0 0 20px;overflow:hidden;}
.ros-day .day-head{padding:16px 20px;border-bottom:1px solid var(--line);
  display:flex;align-items:flex-start;justify-content:space-between;gap:12px;}
.ros-day .day-head h2{font-size:15px;margin:0;letter-spacing:-.2px;}
.ros-day .day-head .dmeta{font-size:12px;color:var(--muted);margin:3px 0 0;}
.ros-day .day-head .dmeta b{color:var(--brand-deep);font-weight:700;}
.ros-day .addros{display:none;flex-shrink:0;font-size:12.5px;padding:6px 12px;}
.staff .ros-day .addros{display:inline-block;}

/* Dead-simple list: time · phase · what. Red is the only accent, only on the music. */
.ros-list .row{display:flex;align-items:baseline;padding:10px 20px;border-bottom:1px solid var(--line);}
.ros-list .row:last-child{border-bottom:0;}
.ros-list .row .t{width:80px;flex:none;font-size:13px;font-weight:700;color:var(--charcoal);
  font-variant-numeric:tabular-nums;}
.ros-list .row .ph{width:104px;flex:none;font-size:10.5px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:#9a958a;}
.ros-list .row .d .ti{font-size:14px;color:var(--ink);}
.ros-list .row .d .ti b{font-weight:700;}
.ros-list .row .d .sub{font-size:12px;color:var(--muted);margin-top:2px;}
.ros-list .row.perf{background:var(--stage-main-bg);}
.ros-list .row.perf .t,.ros-list .row.perf .ph,
.ros-list .row.perf .d .ti,.ros-list .row.perf .d .ti b{color:var(--orange-ink);}

/* Stage view hides call & arrival rows (data stays for artist advances). */
#ros-wrap.stage-only .row[data-phase="call"],
#ros-wrap.stage-only .row[data-phase="arrival"]{display:none;}

.staff .ros-list .row.editable{cursor:pointer;}
.staff .ros-list .row.editable:hover{background:#f4f2ee;}
.staff .ros-list .row.perf.editable:hover{background:#f7ded1;}
.field .hintlbl{text-transform:none;letter-spacing:0;font-weight:500;color:var(--muted);}

/* --- Amerikana ROS tab: Amerikana official show-caller rundowns (read-only) --- */
#amerikana-wrap[hidden]{display:none;}
.amerikana-note{font-size:12px;color:var(--muted);margin:0 0 16px;line-height:1.5;}
.amerikana-note b{color:var(--charcoal);font-weight:700;}
.uday-label{font-size:12.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--charcoal);margin:4px 2px 12px;}
.uevent .day-head{display:block;}
.uevent .day-head h2{font-size:14px;}
.uevent .day-head .dmeta b{color:var(--brand-deep);}
.utable-wrap{overflow-x:auto;}
.utable{width:100%;border-collapse:collapse;font-size:12.5px;}
.utable th{text-align:left;font-size:9.5px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;
  color:var(--muted);padding:7px 12px;border-bottom:1px solid var(--line);background:#faf9f7;white-space:nowrap;}
.utable td{padding:8px 12px;border-bottom:1px solid var(--line);vertical-align:top;}
.utable tbody tr:last-child td{border-bottom:0;}
.utable .unum{width:26px;color:#9a958a;font-variant-numeric:tabular-nums;font-size:11px;}
.utable .ubegin,.utable .udur,.utable .uend{width:78px;white-space:nowrap;
  font-variant-numeric:tabular-nums;color:var(--charcoal);font-size:11.5px;}
.utable .unotes{width:130px;color:var(--muted);font-size:11px;}
.utable .uti{font-weight:600;color:var(--ink);line-height:1.3;}
.utable .usub{font-size:11px;color:var(--muted);margin-top:3px;white-space:pre-line;line-height:1.4;}
.utable tr.usection td{background:var(--charcoal);color:#fff;font-size:9.5px;font-weight:800;
  letter-spacing:.14em;text-transform:uppercase;padding:4px 12px;}
.utable tr.music{background:#fdf5f4;}
.utable tr.music .uti,.utable tr.music .ubegin,
.utable tr.music .udur,.utable tr.music .uend{color:var(--brand-deep);}

/* --- Advance tracker (staff only): artists down, advance steps across --- */
.adv-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;
  flex-wrap:wrap;margin:0 0 16px;}
.legend{display:flex;gap:16px;flex-wrap:wrap;font-size:12px;color:var(--muted);}
.legend span{display:inline-flex;align-items:center;gap:7px;}
/* Scoped to .legend: /staffing has its own .key, a text label, and an unscoped
   20x20 box here crushed it into an overlapping stack. Same trap as .act. */
.legend .key{width:20px;height:20px;border-radius:6px;border:1px solid var(--line);background:var(--paper);}
.legend .key.done{background:var(--confirmed-bg);border-color:#bfdccb;}
.legend .key.wait{background:var(--pending-bg);border-color:#e8d5a8;}
.legend .key.na{background:var(--house-bg);border-color:#dcdad4;}
.progress{font-size:12.5px;color:var(--muted);font-variant-numeric:tabular-nums;}
.progress b{color:var(--ink);font-weight:800;}

.adv-wrap{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);overflow-x:auto;}
table.adv{width:100%;border-collapse:collapse;}
table.adv th{font-size:10.5px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--muted);padding:12px 10px;background:#faf9f7;border-bottom:1px solid var(--line);
  text-align:center;}
table.adv th.who{text-align:left;padding-left:20px;min-width:250px;position:sticky;left:0;
  background:#faf9f7;z-index:2;}
table.adv th.noteh{text-align:left;padding-left:14px;}
table.adv td{padding:10px;border-bottom:1px solid var(--line);text-align:center;vertical-align:middle;}
table.adv td.who{text-align:left;padding-left:20px;position:sticky;left:0;background:var(--paper);z-index:1;}
table.adv tbody tr:last-child td{border-bottom:0;}
table.adv tbody tr:hover td,table.adv tbody tr:hover td.who{background:#fbfaf8;}
table.adv tr.daybreak td,table.adv tr.daybreak td.who{background:var(--charcoal);color:#fff;
  font-size:9.5px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;
  padding:5px 20px;text-align:left;}
.pname{appearance:none;border:0;background:none;padding:0;cursor:pointer;text-align:left;
  font-family:inherit;display:block;}
.pname .aname{display:block;font-size:14.5px;font-weight:700;letter-spacing:-.1px;color:var(--ink);}
.pname .arole{display:block;font-size:11.5px;color:var(--muted);margin-top:1px;}
.pname:hover .aname{color:var(--brand-deep);}
.guest{font-size:9.5px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--charcoal);background:var(--house-bg);border-radius:999px;padding:1px 7px;
  margin-left:6px;vertical-align:1px;}
.cell{appearance:none;font-family:inherit;cursor:pointer;width:34px;height:34px;border-radius:9px;
  border:1px solid var(--line);background:var(--paper);color:#cdc8be;font-size:14px;font-weight:800;
  display:inline-flex;align-items:center;justify-content:center;}
.cell:hover{border-color:var(--charcoal);}
.cell:focus-visible{outline:2px solid var(--brand);outline-offset:2px;}
.cell[data-s="done"]{background:var(--confirmed-bg);border-color:#bfdccb;color:var(--confirmed);}
.cell[data-s="wait"]{background:var(--pending-bg);border-color:#e8d5a8;color:var(--pending);}
.cell[data-s="na"]{background:var(--house-bg);border-color:#dcdad4;color:var(--house);}
td.note{text-align:left;min-width:190px;}
td.note .n{font-size:12px;color:var(--muted);cursor:text;padding:4px 6px;border-radius:7px;
  border:1px dashed transparent;min-height:24px;}
td.note .n:hover{border-color:var(--line);}
td.note .n:focus{outline:0;border-color:var(--charcoal);border-style:solid;background:#fff;}
td.note .n:empty::before{content:"add note";color:#c9c4ba;font-style:italic;}
.adv-foot{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:16px 2px 0;}

footer.app{border-top:1px solid var(--line);margin-top:30px;}
.footrow{max-width:1120px;margin:0 auto;padding:18px 24px;display:flex;
  align-items:center;justify-content:space-between;color:var(--muted);font-size:12.5px;}
.ver{font-variant-numeric:tabular-nums;}
.footrow a{color:var(--muted);}

/* Buttons */
.btn{appearance:none;border:1px solid var(--line);background:var(--paper);color:var(--ink);
  border-radius:9px;padding:8px 14px;font-size:13.5px;font-weight:600;cursor:pointer;}
.btn:hover{border-color:var(--charcoal);}
.btn.primary{background:var(--brand);border-color:var(--brand);color:#fff;}
.btn.primary:hover{background:var(--brand-deep);border-color:var(--brand-deep);}
.btn.danger{color:var(--brand-deep);border-color:#eccfcb;}

/* Modal */
.modal-bg{position:fixed;inset:0;background:rgba(33,36,43,.45);display:none;
  align-items:flex-start;justify-content:center;padding:40px 16px;z-index:50;overflow:auto;}
.modal-bg.open{display:flex;}
.modal{background:var(--paper);border-radius:var(--radius);width:100%;max-width:560px;
  box-shadow:0 24px 60px rgba(0,0,0,.25);}
.modal h3{margin:0;padding:20px 22px;border-bottom:1px solid var(--line);font-size:17px;}
.modal .form{padding:18px 22px;display:grid;gap:14px;}
.modal .row2{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
.field label{display:block;font-size:12px;font-weight:600;color:var(--muted);
  text-transform:uppercase;letter-spacing:.05em;margin-bottom:5px;}
.field input,.field select,.field textarea{width:100%;border:1px solid var(--line);border-radius:9px;
  padding:9px 11px;font-size:14px;font-family:inherit;color:var(--ink);background:#fff;}
.field textarea{min-height:70px;resize:vertical;}
.field.check{display:flex;align-items:center;gap:8px;}
.field.check input{width:auto;}
.field.check label{margin:0;text-transform:none;letter-spacing:0;font-size:13.5px;color:var(--ink);}
.modal .actions{display:flex;justify-content:space-between;align-items:center;
  padding:16px 22px;border-top:1px solid var(--line);}
.modal .actions .right{display:flex;gap:10px;}

/* Login */
.login-wrap{min-height:70vh;display:flex;align-items:center;justify-content:center;padding:24px;}
.login-card{background:var(--paper);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);width:100%;max-width:380px;padding:30px;text-align:center;}
.login-card .emblem{background:var(--navy);border-radius:14px;padding:20px 22px;
  display:block;margin:0 0 20px;}
.login-card .emblem img{width:100%;max-width:250px;height:auto;display:block;margin:0 auto;}
.login-card p{color:var(--muted);font-size:14px;margin:0 0 22px;}
.login-card input{width:100%;border:1px solid var(--line);border-radius:10px;
  padding:12px 14px;font-size:15px;margin-bottom:12px;}
.login-card .btn.primary{width:100%;padding:12px;}
.login-card .err{color:var(--brand);font-size:13px;margin:0 0 14px;font-weight:600;}

@media(max-width:860px){
  .days,.artist-grid{grid-template-columns:1fr;}
    .modal .row2{grid-template-columns:1fr;}
}


/* Stage badges + stage filter (two stages, one day) */
.stagepill{display:inline-block;font-size:10px;font-weight:700;letter-spacing:.07em;
  text-transform:uppercase;padding:2px 7px;border-radius:999px;vertical-align:2px;
  background:var(--stage-main-bg);color:var(--stage-main);}
.stagepill.comm{background:var(--stage-comm-bg);color:var(--stage-comm);}
#ros-wrap.only-main .row[data-stage="Community Stage"],
#ros-wrap.only-comm .row[data-stage="Main Stage"]{display:none;}

/* Phones — crew run the day off these. Time stays left, phase label moves
   above the activity so the detail line gets the full width. */
@media(max-width:560px){
  .viewbar{gap:8px;}
  .seg button{padding:7px 11px;font-size:12px;}
  .viewnote{font-size:11.5px;}
  .ros-day .day-head{padding:13px 14px;}
  .ros-list .row{flex-wrap:wrap;padding:11px 14px;column-gap:10px;}
  .ros-list .row .t{width:64px;font-size:14px;}
  .ros-list .row .ph{width:auto;order:3;font-size:9.5px;margin:3px 0 0 74px;}
  .ros-list .row .d{flex:1 1 calc(100% - 74px);min-width:0;}
  .ros-list .row .d .ti{font-size:15px;line-height:1.35;}
  .ros-list .row .d .sub{font-size:12.5px;}
}

/* --- Crew ------------------------------------------------------------------
   Two teams work a staggered rotation; the chips key A/B consistently across
   the coverage grid, the by-person view and the shift blocks. */
.crewnote-doc{font-size:13px;color:var(--muted);font-style:italic;margin:0 0 16px;}
.teamchip{display:inline-block;min-width:20px;text-align:center;font-size:10px;
  font-weight:800;letter-spacing:.06em;padding:2px 7px;border-radius:999px;margin-right:6px;}
.teamchip.teamA{background:var(--stage-main-bg);color:var(--stage-main);}
.teamchip.teamB{background:var(--stage-comm-bg);color:var(--stage-comm);}
.shiftchip{display:inline-block;font-size:11.5px;font-weight:600;padding:3px 9px;
  border-radius:999px;margin:0 6px 4px 0;}
.shiftchip.teamA{background:var(--stage-main-bg);color:var(--stage-main);}
.shiftchip.teamB{background:var(--stage-comm-bg);color:var(--stage-comm);}
.phours{flex:0 0 110px;text-align:right;font-size:12px;color:var(--muted);font-weight:600;}

/* Crew rows layered onto the run of show — quiet by default, never red, and
   hidden until the toggle asks for them. */
.ros-list .row.crewrow{display:none;background:var(--bg);}
#ros-wrap.show-crew .ros-list .row.crewrow{display:flex;}
.ros-list .row.crewrow .t,.ros-list .row.crewrow .ph{color:var(--muted);}
.ros-list .row.crewrow .d .ti{color:var(--charcoal);font-size:13.5px;}
.ros-list .row.crewrow .d .ti b{color:var(--ink);}

/* Phones — crew run the day off these. This block sat empty, which is why the
   staffing grid looked handled and never was: 639px of Time + Main Stage +
   Community Stage + Site + On against a 390px screen, and a time column that
   computed to `static`, so scrolling right to a person left every shift cell
   belonging to no visible minute.

   The person columns ARE the content, so they keep scrolling. The stage/site
   narration is not, so it goes. Time freezes at the left edge — same treatment
   as the CH column on /inputs, and the same reason. */
@media(max-width:560px){
  .staffgrid .gstage,.staffgrid .gsite{display:none;}
  .staffgrid .gtime{position:sticky;left:0;z-index:2;background:var(--paper);
    width:56px;padding:0 6px;
    /* border-collapse drops borders on sticky cells; draw the edge instead. */
    box-shadow:1px 0 0 var(--line);}
  .staffgrid thead th.gtime{z-index:4;}
  /* The band and uncovered rows already paint .gtime and win on specificity,
     so the frozen column keeps its striping instead of going flat white. */
  .staffgrid .gtime.h{font-size:11.5px;}
  .staffgrid .gtime.hh{font-size:10px;}
  .staffgrid .gtime.q{font-size:9.5px;}
  .staffgrid thead th{font-size:9.5px;}
  .viewbar .key{margin-right:10px;font-size:11px;}
  /* 44px columns fit a desk, not a phone — 36 keeps four people on screen next
     to the frozen time column. */
  .staffgrid .gperson,.staffgrid .gcell{width:36px;}
  .staffgrid .gcell .cpk{font-size:7.5px;}
}

/* Crew list — one row per person: name, phone, their shifts, hours. */
.crewlist .crewrow{display:flex;align-items:center;gap:14px;padding:12px 20px;
  border-bottom:1px solid var(--line);}
.crewlist .crewrow:last-child{border-bottom:0;}
.crewlist .cname{flex:0 0 165px;cursor:pointer;}
.crewlist .cname:hover .nm{color:var(--brand);}
.crewlist .cname .nm{display:block;font-size:15px;font-weight:700;color:var(--ink);}
.crewlist .cname .rl{display:block;font-size:11.5px;color:var(--muted);margin-top:1px;}
.crewlist .cphone{flex:0 0 132px;}
.crewlist .tel{font-size:14px;font-weight:600;color:var(--brand);white-space:nowrap;}
.crewlist .nophone{font-size:12px;color:var(--muted);font-style:italic;}
.crewlist .cshifts{flex:1 1 auto;display:flex;flex-wrap:wrap;gap:6px;}
.crewlist .chours{flex:0 0 74px;text-align:right;font-size:12.5px;font-weight:600;
  color:var(--muted);}
button.shiftchip{border:0;font-family:inherit;cursor:pointer;}
button.shiftchip:hover{filter:brightness(.95);}
.shiftchip.addchip{background:transparent;border:1px dashed var(--line);color:var(--muted);}
.shiftchip.addchip:hover{border-color:var(--brand);color:var(--brand);}

@media(max-width:560px){
  .crewlist .crewrow{flex-wrap:wrap;gap:8px 12px;padding:12px 14px;}
  .crewlist .cname{flex:1 1 auto;}
  .crewlist .cphone{flex:0 0 auto;}
  .crewlist .chours{flex:0 0 auto;order:3;}
  .crewlist .cshifts{flex:1 1 100%;}
}
.crewlist .listdivider{padding:9px 20px;font-size:11px;font-weight:800;
  letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
  background:var(--bg);border-bottom:1px solid var(--line);}
.crewlist .cshirt{flex:0 0 56px;text-align:center;}
.crewlist .sz{display:inline-block;font-size:11.5px;font-weight:800;padding:3px 9px;
  border-radius:999px;background:var(--stage-comm-bg);color:var(--stage-comm);}
.crewlist .nosz{font-size:11.5px;color:var(--muted);font-style:italic;}
.crewlist .editfield{appearance:none;border:0;background:none;font-family:inherit;
  cursor:pointer;padding:0;}
.crewlist .cphone .editfield{font-size:10.5px;font-weight:700;color:var(--muted);
  text-transform:uppercase;letter-spacing:.08em;margin-left:8px;}
.crewlist .cphone .editfield:hover{color:var(--brand);}
.crewlist .nophone.editfield{font-size:12px;font-style:normal;color:var(--brand);
  margin-left:0;text-transform:none;letter-spacing:0;font-weight:600;}
.crewlist .szbtn{display:inline-block;}
.crewlist .szbtn:hover .sz{filter:brightness(.93);}
.crewlist .szbtn:hover .nosz{color:var(--brand);}
.crewlist .chours{flex:0 0 118px;}
.crewlist .chours .hrs{display:block;}
.crewlist .paybtn{display:block;text-align:right;width:100%;margin-top:2px;}
.crewlist .pay{font-size:13px;font-weight:800;color:var(--ink);}
.crewlist .rate{display:block;font-size:10.5px;color:var(--muted);font-weight:600;}
.crewlist .paybtn:hover .pay{color:var(--brand);}

/* --- Staffing grid ---------------------------------------------------------
   One colour only: green means available/working. Everything else is
   structural — ruled columns, hatching for a break, and a shaded row with a
   left bar where nobody is rostered. Team tints and the red gap state are
   gone; nine colour-coded columns read as a quilt. */
.gridscroll{overflow-x:auto;-webkit-overflow-scrolling:touch;}
.staffgrid{border-collapse:collapse;width:100%;font-size:12px;}
.staffgrid th,.staffgrid td{border-bottom:1px solid var(--line);padding:0;}
.staffgrid thead th{position:sticky;top:0;background:var(--paper);z-index:2;
  padding:8px 6px;font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;
  color:var(--muted);border-bottom:2px solid var(--charcoal);vertical-align:bottom;}
.staffgrid .ghours th{border-bottom:1px solid var(--line);padding:2px 6px 6px;}
.staffgrid .gw{font-size:10px;font-weight:700;color:var(--charcoal);}

/* Ruled columns — the readability fix. Every person column is separated, and
   the three left-hand columns are walled off from the grid itself. */
.staffgrid th.gperson,.staffgrid td.gcell{border-left:1px solid var(--line);}
.staffgrid th.gcount,.staffgrid td.gcount{border-left:2px solid var(--charcoal);
  border-right:2px solid var(--charcoal);}
.staffgrid th.gstage,.staffgrid td.gstage,
.staffgrid th.gsite,.staffgrid td.gsite{border-left:1px solid var(--charcoal);}

/* Time is labelled on EVERY row, weighted by significance — the hour reads
   first, the half next, the quarters recede. A sparse time column was the
   thing making this hard to follow. */
.staffgrid .gtime{width:72px;padding:0 8px;white-space:nowrap;text-align:right;
  font-variant-numeric:tabular-nums;}
.staffgrid .gtime.h{font-size:12px;font-weight:800;color:var(--ink);}
.staffgrid .gtime.hh{font-size:10.5px;font-weight:600;color:var(--charcoal);}
.staffgrid .gtime.q{font-size:10px;font-weight:500;color:#a8afb8;}
/* Widths are capped, not just floored. With only a min-width the table's auto
   layout handed every surplus pixel to Site — the emptiest column on the page
   — and squeezed the crew columns that are the actual point of the view. */
.staffgrid .gstage{min-width:150px;max-width:180px;width:180px;padding:3px 9px;}
.staffgrid .gsite{min-width:104px;max-width:130px;width:118px;padding:3px 8px;}
.staffgrid .gstage .ev,.staffgrid .gsite .ev{display:block;font-size:11.5px;
  color:var(--ink);line-height:1.35;}
.staffgrid .gstage .ev.perf{font-weight:700;}
.staffgrid .gsite .ev{color:var(--muted);font-size:11px;}
.staffgrid thead th.gstage,.staffgrid thead th.gsite{text-align:left;}
.staffgrid .gcount{width:36px;text-align:center;font-weight:800;color:var(--ink);}
.staffgrid .gcount.zero{color:var(--muted);}
.staffgrid .gperson{width:44px;}
.staffgrid .gperson span{display:block;font-size:10px;line-height:1.1;}

.staffgrid .gcell{width:44px;height:15px;cursor:pointer;position:relative;}
.staffgrid .gcell.on{background:var(--on-shift);}
/* A rostered hour with a position reads as that position's colour; a rostered
   hour without one stays plain green, which is what "still to assign" looks
   like at a glance. */
.staffgrid .gcell.on.pgreen{background:#bfe0cd;}
.staffgrid .gcell.on.pcommunity{background:#efd9b8;}
.staffgrid .gcell.on.pmain{background:#c9d4e4;}
.staffgrid .gcell .cpk{position:absolute;top:1px;left:0;right:0;font-size:8px;
  font-weight:800;letter-spacing:.03em;line-height:1;color:var(--ink);
  text-align:center;pointer-events:none;}
.staffgrid .gcell.off .cpk{color:#8b939e;}
.staffgrid .gcell.break{background:repeating-linear-gradient(45deg,transparent,
  transparent 3px,#d8dce2 3px,#d8dce2 4px);}
/* Blacked out, not blank. White read as "no data"; solid dark makes the green
   working blocks the only thing the eye lands on. */
.staffgrid .gcell.off{background:var(--off-shift);}
.staffgrid tbody tr.uncovered .gcell.off{background:var(--off-shift);}
.staffgrid .gcell.sstart{box-shadow:inset 0 2px 0 var(--on-shift-line);}

/* Row rules: every 15 minutes light, every hour heavy, so the eye can travel
   sideways without losing its place. */
.staffgrid tbody tr td{border-bottom:1px solid #eef0f2;}
.staffgrid tbody tr.halfline td{border-bottom-color:#dcdfe4;}
.staffgrid tbody tr.hourline td{border-top:2px solid var(--charcoal);border-bottom-color:#dcdfe4;}
/* Alternating hour band, on the reading columns only — banding the shift grid
   too would fight with the green. */
.staffgrid tbody tr.band .gtime,
.staffgrid tbody tr.band .gstage,
.staffgrid tbody tr.band .gsite,
.staffgrid tbody tr.band .gcount{background:#f4f5f7;}

/* A moment with nobody rostered. No red — a heavy left marker and the empty
   headcount are enough, and they survive being printed or screenshotted. */
.staffgrid tbody tr.uncovered td{background:#eceef1;}
.staffgrid tbody tr.uncovered .gtime{box-shadow:inset 3px 0 0 var(--ink);}
.staffgrid tbody tr.uncovered .ev{font-weight:700;}

.viewbar .key{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--muted);
  margin-right:14px;}
.kbox{width:14px;height:14px;border-radius:3px;border:1px solid var(--line);
  display:inline-block;flex:0 0 auto;}
.kbox.on{background:var(--on-shift);}
.kbox.brk{background:repeating-linear-gradient(45deg,transparent,transparent 3px,
  #d8dce2 3px,#d8dce2 4px);}
.kbox.off{background:var(--off-shift);border-color:var(--off-shift);}
.kbox.pgreen{background:#bfe0cd;}
.kbox.pcommunity{background:#efd9b8;}
.kbox.pmain{background:#c9d4e4;}
.kbox.gap{background:#eceef1;box-shadow:inset 3px 0 0 var(--ink);}

/* --- Positions: green room / community / main, chosen per hour -------------
   Set by tapping a slot on the grid itself (staffing.js). The picker is a
   modal with 44px targets because this is done one-handed, walking, and a miss
   sends someone to the wrong stage. */
.postpick{display:flex;flex-direction:column;gap:8px;margin:14px 0 4px;}
.postpick .pbtn{appearance:none;border:1px solid var(--line);border-radius:10px;
  background:var(--paper);font-family:inherit;font-size:14px;font-weight:700;
  color:var(--ink);min-height:48px;padding:0 16px;cursor:pointer;text-align:left;}
.postpick .pbtn.on{color:var(--paper);border-color:transparent;}
.postpick .pbtn.pgreen.on{background:var(--brand-deep);}
.postpick .pbtn.pcommunity.on{background:#8a5a1f;}
.postpick .pbtn.pmain.on{background:var(--navy);}
.postpick .pbtn.pperf.on{background:var(--off-shift);}
.postpick .pbtn.pclear{color:var(--muted);font-weight:600;}


/* --- My shift: one person's own day ---------------------------------------
   The staffing grid is 27 columns on a 390px phone. At load-in a student only
   needs their own row, so this is the same data as one big readable list. */
.whopick{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;padding:16px 20px;}
.whobtn{display:flex;flex-direction:column;justify-content:center;gap:2px;
  min-height:64px;padding:12px 14px;border:1px solid var(--line);border-radius:12px;
  background:var(--paper);font-size:15px;font-weight:700;color:var(--ink);
  text-decoration:none;box-shadow:var(--shadow);}
.whobtn:hover{border-color:var(--brand);text-decoration:none;}
.whobtn span{font-size:11.5px;font-weight:600;color:var(--muted);}

/* Clock in / out. Native time inputs on purpose — the phone's own wheel beats
   anything hand-rolled, and this gets used tired, at the end of a long day. */
.clocklist{display:flex;flex-direction:column;}
.clockrow{display:flex;align-items:flex-end;gap:12px;padding:11px 20px;
  border-bottom:1px solid var(--line);}
.clockrow.saving{opacity:.55;}
.clockrow.bad input{border-color:var(--overbudget);}
.clockrow label{display:flex;flex-direction:column;gap:3px;font-size:10.5px;
  font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);}
.clockrow input[type=time]{font-family:inherit;font-size:16px;font-weight:700;
  color:var(--ink);border:1px solid var(--line);border-radius:9px;padding:9px 10px;
  background:var(--paper);min-height:44px;}
.clockrow .clen{margin-left:auto;font-size:13px;font-weight:700;color:var(--muted);
  font-variant-numeric:tabular-nums;padding-bottom:11px;}
/* The gap between two shifts, named. A paid meal break has to be visible or
   the total looks like the app cannot add up. */
.clockgap{padding:7px 20px;font-size:11.5px;font-weight:700;letter-spacing:.04em;
  color:var(--muted);border-bottom:1px solid var(--line);background:var(--bg);}
.clockgap.paid{color:var(--green-ink);}
.clockgap[hidden]{display:none;}
.clockfoot{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  padding:14px 20px;border-top:1px solid var(--line);background:var(--bg);
  font-size:13px;color:var(--muted);flex-wrap:wrap;}
.clockfoot b{font-size:17px;color:var(--ink);font-variant-numeric:tabular-nums;}
.clockpay{display:flex;align-items:baseline;gap:7px;}
.clockrate{font-size:11.5px;}

.mylist{display:flex;flex-direction:column;}
.myblock{display:flex;gap:14px;padding:13px 20px;border-bottom:1px solid var(--line);
  border-left:4px solid transparent;}
.myblock:last-child{border-bottom:0;}
.myblock.on{background:var(--on-shift);border-left-color:var(--on-shift-line);}
.myblock.on.pgreen{background:#bfe0cd;border-left-color:var(--brand-deep);}
.myblock.on.pcommunity{background:#efd9b8;border-left-color:#8a5a1f;}
.myblock.on.pmain{background:#c9d4e4;border-left-color:var(--navy);}
.myblock.brk{background:repeating-linear-gradient(45deg,transparent,transparent 5px,
  #eceef1 5px,#eceef1 7px);}
/* Off and performing are the blacked-out state from the grid, so the two
   surfaces read the same. */
.myblock.perf,.myblock:not(.on):not(.brk){background:var(--off-shift);}
.myblock.perf .mylabel,.myblock:not(.on):not(.brk) .mylabel{color:#fff;}
.myblock.perf .mytime b,.myblock:not(.on):not(.brk) .mytime b,
.myblock.perf .mytime span,.myblock:not(.on):not(.brk) .mytime span,
.myblock.perf .mylen,.myblock:not(.on):not(.brk) .mylen{color:#aeb6c0;}
.myblock.perf .myevents,.myblock:not(.on):not(.brk) .myevents{color:#8b939e;}
.mytime{flex:0 0 78px;display:flex;flex-direction:column;line-height:1.25;
  font-variant-numeric:tabular-nums;}
.mytime b{font-size:14.5px;color:var(--ink);}
.mytime span{font-size:11.5px;color:var(--muted);}
.mywhat{min-width:0;}
.mylabel{display:block;font-size:14.5px;font-weight:700;color:var(--ink);}
.mylen{font-size:11.5px;color:var(--muted);}
.myevents{margin:7px 0 0;padding:0 0 0 16px;font-size:12.5px;color:var(--charcoal);
  line-height:1.45;}

/* --- Input lists -----------------------------------------------------------
   The source is a matrix: a channel per row, an act per column. Kept that way
   because at the desk the question is "who needs channel 24", which is a
   column scan, not a lookup. */
.inputgrid{border-collapse:collapse;width:100%;font-size:12px;}
.inputgrid th,.inputgrid td{border:1px solid var(--line);padding:4px 7px;
  white-space:nowrap;}
.inputgrid thead th{position:sticky;top:0;background:var(--paper);z-index:2;
  font-size:10px;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);
  border-bottom:2px solid var(--charcoal);text-align:left;vertical-align:bottom;}
.inputgrid thead th.act{border-left:1px solid var(--charcoal);}
.inputgrid thead th.act span{display:block;font-size:11px;line-height:1.15;
  max-width:88px;white-space:normal;}
/* Frozen channel column, the way the source sheet freezes its left panes. Once
   you scroll right to find an act, the channel number has to stay on screen or
   a mark belongs to no row. border-collapse drops borders on sticky cells, so
   the right edge is drawn with a shadow instead. */
.inputgrid .ch{width:34px;text-align:center;font-weight:800;color:var(--ink);
  position:sticky;left:0;background:var(--paper);z-index:1;
  box-shadow:1px 0 0 var(--line);}
.inputgrid thead th.ch{z-index:3;}
.inputgrid tbody tr:hover td.ch{background:#f4f5f7;}
.inputgrid .snake{color:var(--muted);font-size:11px;}
.inputgrid .cat{color:var(--muted);font-size:11px;}
.inputgrid .inst{font-weight:600;color:var(--ink);}
.inputgrid .mic,.inputgrid .stand,.inputgrid .loc{font-size:11.5px;color:var(--charcoal);}
.inputgrid .note{font-size:11px;color:var(--muted);}
.inputgrid td.act{width:48px;text-align:center;font-size:12px;color:var(--muted);
  border-left:1px solid var(--charcoal);}
.inputgrid td.act.hit{background:var(--on-shift);color:var(--ink);font-weight:700;}
.inputgrid td.act.wide{font-size:10.5px;white-space:normal;line-height:1.15;}
.inputgrid tbody tr:hover td{background:#f4f5f7;}
.inputgrid tbody tr:hover td.act.hit{background:#bcddcc;}
.inputgrid tr.spare td{color:#b3b9c1;}
.inputgrid .sparelbl{font-style:italic;color:#b3b9c1;}
.seg .segl{font-size:12.5px;font-weight:600;padding:8px 15px;color:var(--muted);
  text-decoration:none;display:inline-block;}
.seg .segl.on{background:var(--brand);color:#fff;}
.seg .segl:hover{text-decoration:none;}
