:root{
  --paper:#f8f6f0; --white:#ffffff; --ink:#21242b; --ink-soft:#565a63;
  --line:#d8d5ca; --teal:#1f6f6b; --teal-deep:#175450; --teal-line:#cfdcd7;
  --sage:#e6ede8; --persimmon:#d4652a; --persimmon-deep:#b0491a; --danger:#b02a1a;
  --sans:'IBM Plex Sans',system-ui,-apple-system,'Segoe UI',Roboto,Arial,sans-serif;
  --mono:'IBM Plex Mono',ui-monospace,monospace;
  --display:'Libre Franklin',var(--sans);
}
*{box-sizing:border-box}
body{margin:0;background:var(--paper);color:var(--ink);font-family:var(--sans);line-height:1.5;-webkit-font-smoothing:antialiased}
a{color:var(--teal-deep)}

.wrap{max-width:560px;margin:0 auto;padding:20px 16px 64px}
.wrap.narrow{max-width:480px}
.wrap.wide{max-width:900px}

header.top{padding:20px 4px 8px}
header.top.center{text-align:center}
.eyebrow{font-family:var(--sans);color:var(--teal);font-weight:600;font-size:.75rem;letter-spacing:.06em;text-transform:uppercase;margin:0 0 10px}
h1{font-family:var(--display);font-size:1.8rem;font-weight:900;line-height:1.12;margin:0 0 10px;color:var(--teal-deep);letter-spacing:-.01em}
body.admin h1{font-family:var(--sans);font-weight:700}
.intro{color:var(--ink-soft);font-size:.98rem;margin:0}
.intro strong{color:var(--ink)}

.card{background:var(--white);border:1px solid var(--line);border-radius:14px;padding:20px 16px;margin-top:18px}
.card h2{font-size:1.15rem;font-weight:700;margin:0 0 4px;color:var(--teal-deep)}
.card .sub,.sub{color:var(--ink-soft);font-size:.9rem;margin:0 0 16px}
.card.center{text-align:center}

.field{margin-bottom:16px}
label{display:block;font-weight:600;font-size:.95rem;margin-bottom:6px}
.hint{font-weight:400;color:var(--ink-soft);font-size:.85rem;display:block;margin-top:2px}
input[type=text],input[type=email],input[type=tel],input[type=password],select,textarea{
  width:100%;font:inherit;font-size:1.05rem;color:var(--ink);
  padding:13px 14px;border:1.5px solid var(--line);border-radius:10px;background:#fff;min-height:50px;
}
select{appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%231f6f6b' viewBox='0 0 16 16'%3E%3Cpath d='M2 5l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 14px center;padding-right:40px}
input:focus,select:focus,textarea:focus{outline:3px solid var(--teal-line);border-color:var(--teal)}
textarea{min-height:88px;resize:vertical}
.row2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media(max-width:340px){.row2{grid-template-columns:1fr}}
.reveal{display:none;margin-top:8px}
.reveal.open{display:block}

.field.bad input,.field.bad select{border-color:var(--danger)}
.err{color:var(--danger);font-size:.85rem;margin:6px 0 0;font-weight:600}
.alert{background:#f9e9e5;border:1.5px solid var(--danger);color:var(--danger);border-radius:10px;padding:12px 14px;margin-top:16px;font-weight:600;font-size:.95rem}
.notice{background:var(--sage);border:1.5px solid var(--teal-line);color:var(--teal-deep);border-radius:10px;padding:12px 14px;margin-top:16px;font-weight:600;font-size:.95rem}

/* honeypot — visually gone, still in the DOM for bots */
.hp{position:absolute;left:-9999px;top:-9999px}

/* availability grid (checkbox-as-button, works without JS) */
.dayrow{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.dayname{flex:0 0 44px;font-family:var(--mono);font-weight:600;font-size:.8rem;color:var(--teal-deep);text-transform:uppercase}
.slots{display:flex;flex:1;gap:8px}
.slot{display:flex;flex:1;margin:0;font-weight:600}
.slot input{position:absolute;opacity:0;width:1px;height:1px}
.slot span{
  flex:1;min-height:48px;border:1.5px solid var(--line);border-radius:10px;background:#fff;
  font-size:.85rem;color:var(--ink-soft);cursor:pointer;
  display:flex;align-items:center;justify-content:center;gap:4px;padding:4px 2px;
  transition:background .12s,border-color .12s,color .12s;
}
.slot input:checked+span{background:var(--teal);border-color:var(--teal-deep);color:#fff}
.slot input:checked+span::before{content:"✓";font-weight:700}
.slot input:focus-visible+span{outline:3px solid var(--teal-line)}

.cta{
  display:block;width:100%;margin-top:20px;padding:16px;border:0;border-radius:12px;
  background:var(--persimmon);color:#fff;font:inherit;font-size:1.15rem;font-weight:700;cursor:pointer;
}
.cta:active{background:var(--persimmon-deep)}
.foot{color:var(--ink-soft);font-size:.85rem;text-align:center;margin-top:14px}

.thanks{text-align:center;padding:48px 8px}
.thanks .big{width:76px;height:76px;border-radius:50%;background:var(--teal);color:#fff;font-size:2.4rem;display:flex;align-items:center;justify-content:center;margin:0 auto 18px}
.thanks h2{font-family:var(--display);font-weight:900;font-size:1.6rem;color:var(--teal-deep);margin:0 0 8px}
body.admin .thanks h2{font-family:var(--sans);font-weight:700}
.thanks p{color:var(--ink-soft);max-width:36ch;margin:0 auto 10px}
.thanks .small{font-size:.9rem}

/* ---------- chooser ---------- */
.choose{display:flex;flex-direction:column;gap:14px;margin-top:22px}
.choice{display:block;background:#fff;border:1.5px solid var(--line);border-radius:14px;padding:18px 16px;text-decoration:none;color:var(--ink)}
.choice:active{border-color:var(--teal)}
.choice.primary{border-color:var(--teal-line);border-left:5px solid var(--persimmon)}
.choice-tag{display:inline-block;font-size:.72rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--teal);background:var(--sage);border-radius:999px;padding:3px 10px;margin-bottom:10px}
.choice.primary .choice-tag{color:var(--persimmon-deep);background:#f5e4d8}
.choice-title{display:block;font-family:var(--display);font-weight:900;font-size:1.35rem;color:var(--teal-deep);margin-bottom:6px}
.choice-desc{display:block;color:var(--ink-soft);font-size:.95rem;line-height:1.45}

.adminlink{text-align:center;margin-top:30px}

/* ---------- radio / checkbox rows ---------- */
.radio,.check{display:flex;gap:11px;align-items:flex-start;font-weight:600;margin:0 0 10px;cursor:pointer}
.radio:last-child,.check:last-child{margin-bottom:0}
.radio input,.check input{flex:0 0 auto;width:22px;height:22px;margin:1px 0 0;accent-color:var(--teal)}
.radio span,.check span{font-weight:600;line-height:1.4}
.radio .hint,.check .hint{display:block;font-weight:400}
.field.bad .radio span,.field.bad .check span{color:var(--ink)}
input[type=file]{width:100%;font:inherit;font-size:.95rem;padding:11px 12px;border:1.5px dashed var(--line);border-radius:10px;background:#fff}
input[type=date]{width:100%;font:inherit;font-size:1.05rem;padding:12px 14px;border:1.5px solid var(--line);border-radius:10px;background:#fff;min-height:50px}

.card.ack{border-color:var(--teal-line);background:var(--sage)}
.card.ack h2{color:var(--teal-deep)}
.card.ack.bad{border-color:var(--danger)}

/* ---------- cost callout ---------- */
.costcard{display:flex;gap:12px;align-items:flex-start;background:var(--sage);border:1.5px solid var(--teal-line);border-radius:12px;padding:14px 16px;margin-top:16px}
.costcard .costbadge{flex:0 0 auto;background:var(--teal);color:#fff;font-weight:800;font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;border-radius:999px;padding:5px 12px;margin-top:1px}
.costcard p{margin:0;color:var(--ink);font-size:.95rem;line-height:1.5}
.sched-where{margin:14px 2px 0;color:var(--ink-soft);font-size:.95rem;line-height:1.5}
.sched-where strong{color:var(--ink)}

/* ---------- class schedule ---------- */
.sched{margin-top:18px}
.sched-stats{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px}
.sched-stats .stat{background:var(--sage);color:var(--teal-deep);border-radius:999px;padding:6px 13px;font-size:.85rem;font-weight:600}
.sched-stats .stat strong{font-weight:800}
.month-sep{font-family:var(--mono);font-size:.72rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-soft);margin:20px 0 10px;display:flex;align-items:center;gap:10px}
.month-sep::after{content:"";flex:1;height:1px;background:var(--line)}
.sesh{display:flex;gap:12px;align-items:stretch;background:#fff;border:1px solid var(--line);border-radius:12px;padding:12px;margin-bottom:10px}
.sesh.long{border-left:4px solid var(--persimmon)}
.sesh.tentative{background:transparent;border-style:dashed}
.sesh-date{flex:0 0 56px;display:flex;flex-direction:column;align-items:center;justify-content:center;background:var(--sage);border-radius:10px;padding:8px 4px;color:var(--teal-deep);line-height:1}
.sesh.long .sesh-date{background:#f5e4d8;color:var(--persimmon-deep)}
.sesh.tentative .sesh-date{background:#eee}
.sesh-date .dow{font-size:.68rem;text-transform:uppercase;letter-spacing:.05em;font-weight:700;margin-bottom:3px}
.sesh-date .dnum{font-family:var(--display);font-size:1.6rem;font-weight:900}
.sesh-body{flex:1;display:flex;flex-direction:column;justify-content:center;gap:6px;min-width:0}
.sesh-content{margin:0;font-weight:600;font-size:.95rem;color:var(--ink)}
.sesh.tentative .sesh-content{color:var(--ink-soft);font-weight:600}
.sesh-hours{align-self:flex-start;font-family:var(--mono);font-size:.68rem;text-transform:uppercase;letter-spacing:.05em;font-weight:600;color:var(--teal-deep);background:var(--sage);border-radius:6px;padding:2px 8px}
.sesh.long .sesh-hours{background:#f5e4d8;color:var(--persimmon-deep)}
.sesh.tentative .sesh-hours{background:#eee;color:var(--ink-soft)}
.sesh.virtual{border-left:4px solid var(--teal)}
.sesh.virtual .sesh-date{background:#e3ebef;color:var(--teal-deep)}
.sesh.virtual .sesh-hours{background:#e3ebef;color:var(--teal-deep)}
.sesh-tag{display:inline-block;font-size:.62rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:#fff;background:var(--teal);border-radius:6px;padding:2px 7px;vertical-align:middle;margin-left:6px}
.sched-foot{color:var(--ink-soft);font-size:.85rem;margin:14px 2px 0;line-height:1.45}

/* ---------- admin ---------- */
.adminnav{background:var(--teal-deep);color:#fff}
.adminnav .wrap{max-width:900px;display:flex;align-items:center;gap:4px;padding:10px 16px;flex-wrap:wrap}
.adminnav .brand{font-weight:700;font-size:.95rem;margin-right:10px;color:#cfdcd7}
.adminnav a{color:#eaf2f0;text-decoration:none;padding:8px 10px;border-radius:8px;font-size:.95rem;font-weight:600}
.adminnav a.on,.adminnav a:hover{background:rgba(255,255,255,.14)}
.adminnav .logout{margin-left:auto}
.adminnav .logout button{background:none;border:1px solid rgba(255,255,255,.35);color:#eaf2f0;border-radius:8px;padding:7px 12px;font:inherit;font-size:.85rem;cursor:pointer}

.pagehead{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:20px 4px 0;flex-wrap:wrap}
.pagehead h1{margin:0;font-size:1.5rem}

.btn{display:inline-block;background:var(--teal);color:#fff;border:0;border-radius:10px;padding:11px 16px;font:inherit;font-weight:700;font-size:.95rem;cursor:pointer;text-decoration:none;text-align:center}
.btn:active{background:var(--teal-deep)}
.btn.small{padding:9px 14px;font-size:.85rem}
.btn.tiny{padding:7px 10px;font-size:.8rem;white-space:nowrap}
.btn.ghost{background:#fff;color:var(--teal-deep);border:1.5px solid var(--teal-line)}
.btn.danger{background:var(--danger);width:100%;margin-top:16px;padding:13px}

/* heatmap */
.heat{max-width:420px}
.heatrow{display:flex;gap:6px;margin-bottom:6px}
.heatrow.head span{background:none;border:none}
.hd{flex:0 0 44px;display:flex;align-items:center;font-family:var(--mono);font-weight:600;font-size:.8rem;text-transform:uppercase;color:var(--teal-deep)}
.heatrow.head span:first-child{flex:0 0 44px}
.hb{flex:1;text-align:center;font-family:var(--mono);font-size:.7rem;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft)}
.hc{flex:1;min-height:44px;border:1px solid var(--teal-line);border-radius:8px;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:1rem}

/* submissions table → cards on small screens */
.tablewrap{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:.92rem}
th{text-align:left;font-family:var(--mono);font-size:.7rem;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft);padding:8px 10px;border-bottom:2px solid var(--line)}
td{padding:10px;border-bottom:1px solid var(--line);vertical-align:top}
td.avail{max-width:220px;font-size:.85rem;color:var(--ink-soft)}
@media(max-width:700px){
  table,thead,tbody,tr,td{display:block}
  thead{display:none}
  tr{border:1px solid var(--line);border-radius:10px;margin-bottom:12px;padding:6px 0;background:#fff}
  td{border:0;padding:4px 14px;max-width:none}
  td::before{content:attr(data-l);font-family:var(--mono);font-size:.65rem;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft);display:block}
}

/* detail list */
/* 96px rather than 110px: the label column only has to hold "PRE-REGISTERED" on
   two lines, and the 14px it gives back is the difference between a full email
   address fitting on this page and being truncated. */
.detail{display:grid;grid-template-columns:96px 1fr;gap:8px 14px;margin:0}
/* The list can truncate an address, because there you are scanning for a person
   rather than reading their email. Here you are reading it, so instead of an
   ellipsis that hides the end for good, the address stays whole and swipes
   sideways. The scrollbar is hidden; a word cut mid-character is the cue. */
.detail .mail{font-size:.92rem;overflow-x:auto;text-overflow:clip;scrollbar-width:none}
.detail .mail::-webkit-scrollbar{display:none}
.detail dt{font-family:var(--mono);font-size:.75rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-soft);padding-top:2px}
/* min-width:0 because a grid item defaults to min-width:auto, which lets a long
   unbreakable value (an email address that has been told not to wrap) push the
   1fr track wider than the card instead of truncating inside it. */
.detail dd{margin:0;overflow-wrap:anywhere;min-width:0}
@media(max-width:420px){.detail{grid-template-columns:84px 1fr;gap:8px 10px}}

/* An email address is one unbreakable token to read, not prose: broken across
   two lines it stops looking like an address at all. So it never wraps, and a
   long one truncates instead - the link still opens the right mailbox, and the
   full address is in the title. Overrides overflow-wrap:anywhere on .detail dd. */
.mail{display:block;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;overflow-wrap:normal}

/* manage lists */
.addrow{display:flex;gap:8px}
.addrow input{flex:1}
.addrow.stacked{flex-wrap:wrap}
.addrow.stacked input{flex:1 1 180px}
.mlist{list-style:none;margin:0;padding:0}
.mlist li{display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--line);flex-wrap:wrap}
.mlist li:last-child{border-bottom:0}
.mlist li.off .renamerow input,.mlist li.off .who b{opacity:.45;text-decoration:line-through}
.renamerow{display:flex;gap:6px;flex:1;min-width:200px}
.renamerow input{min-height:42px;padding:8px 10px;font-size:.95rem}
.use{color:var(--ink-soft);font-size:.8rem;white-space:nowrap}
.who{flex:1;min-width:200px}
.who b{display:block}
.rolechip{display:inline-block;font-size:.7rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;border-radius:6px;padding:2px 7px;vertical-align:middle;margin-left:4px}
.rolechip.admin{background:var(--sage);color:var(--teal-deep)}
.rolechip.viewer{background:#f3ece6;color:var(--persimmon-deep)}
.addrow.stacked select{flex:1 1 120px;min-height:42px;padding:8px 32px 8px 10px;font-size:.95rem}

/* text-reminder page */
.groupbtns{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 18px}
.onebyone{display:flex;flex-wrap:wrap;gap:8px;margin:0}
#picklist td:first-child,#picklist th:first-child{width:36px}
#picklist input[type=checkbox]{width:22px;height:22px;min-height:0;accent-color:var(--teal)}
@media(max-width:700px){#picklist td:first-child,#picklist th:first-child{width:auto}}

/* bulk roster bar */
.bulkbar{position:sticky;bottom:0;display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  background:var(--teal-deep);border-radius:12px;padding:12px 14px;margin-top:16px;
  box-shadow:0 4px 18px rgba(0,0,0,.22)}
/* display:flex on a class beats the browser's own [hidden] rule, so the bar
   stayed on screen with nothing ticked - the exact "about to do something by
   accident" look it was written to avoid. Say it explicitly. */
.bulkbar[hidden]{display:none}
.bulkbar .bulkcount{color:#fff;font-weight:700;font-size:.9rem;margin-right:auto}
.bulkbar .btn.ghost{background:transparent;color:#eaf2f0;border-color:rgba(255,255,255,.45)}
.btn[disabled]{opacity:.45;cursor:not-allowed}
.bulkbar .btn.approve{background:var(--persimmon)}
.bulkbar .btn.approve:active{background:var(--persimmon-deep)}
.bulkbar .btn.approve[disabled]{background:var(--persimmon)}
#rosterlist td:first-child,#rosterlist th:first-child{width:36px}
#rosterlist input[type=checkbox]{width:22px;height:22px;min-height:0;accent-color:var(--teal)}
.detail dd.comments{white-space:pre-wrap;background:var(--sage);border-radius:8px;padding:10px 12px}

/* filter chips */
.filters{margin:0 0 14px}
.filterrow{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:8px}
.filterlabel{font-family:var(--mono);font-size:.65rem;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-soft);flex:0 0 100%}
.filterbtn{font:inherit;font-size:.82rem;font-weight:600;color:var(--teal-deep);background:#fff;
  border:1.5px solid var(--teal-line);border-radius:8px;padding:7px 12px;cursor:pointer;min-height:38px}
.filterbtn.on{background:var(--teal-deep);border-color:var(--teal-deep);color:#fff}
.filterfoot{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:0 0 12px}
.filtercount{margin:0;font-size:.82rem}
.filterfoot .filterbtn{margin-left:auto;padding:6px 11px;font-size:.78rem;min-height:34px}
.filterfoot .filterbtn[hidden]{display:none}
.empty{padding:14px 2px;margin:0}

/* Decision and roster state, as words. Weight and colour do the work a pill
   would have done, without a page of little coloured tablets to look past. */
.st-ok{color:var(--teal-deep);font-weight:600}
.st-warn{color:var(--persimmon-deep);font-weight:600}
.st-bad{color:var(--danger);font-weight:700}
.st-mute{color:var(--ink-soft)}

/* The pre-registration list on a phone. The generic table-to-card rule below
   stacks every column into its own labelled block, which for nine columns is a
   card you have to scroll past one person at a time. These fields are mostly
   two or three words, so they pair up: name and contact get the full width, the
   short stuff sits in two columns, and `order` puts the decision and the roster
   state directly under the name where they are what you came to check. */
@media(max-width:700px){
  #rosterlist td:first-child,#rosterlist th:first-child{width:auto}
  #rosterlist tr{display:grid;grid-template-columns:1fr 1fr;column-gap:12px;row-gap:6px;
    position:relative;padding:12px 12px 12px 44px;margin-bottom:10px}
  #rosterlist tr[hidden]{display:none}
  #rosterlist td{padding:0;min-width:0}
  #rosterlist td::before{line-height:1.25;margin-bottom:1px}
  #rosterlist .c-pick{position:absolute;left:12px;top:12px;order:0}
  #rosterlist .c-pick::before{content:none}
  #rosterlist .c-name{grid-column:1/-1;order:1;font-size:1.05rem;font-weight:700;line-height:1.25}
  #rosterlist .c-name::before{content:none}
  /* These two keep their labels. A pill could stand alone under the name; the
     bare words "Accepted" and "Registered" side by side cannot. */
  #rosterlist .c-status{order:2}
  #rosterlist .c-roster{order:3}
  #rosterlist .c-contact{grid-column:1/-1;order:4;font-size:.88rem}
  #rosterlist .c-contact::before{content:none}
  #rosterlist .c-dept{order:5}
  #rosterlist .c-level{order:6}
  #rosterlist .c-cpr{order:7}
  #rosterlist .c-when{order:8}
}
#rosterlist .c-contact .tel{display:block}
/* A never-wrapping email would otherwise size the whole column to the longest
   address on the list and push the roster and date columns off the right edge.
   Cap it here and let .mail truncate; the card layout above sets its own width. */
@media(min-width:701px){#rosterlist .c-contact{max-width:180px}}
