/* =====================================================================
   Sidebar shell, tab strips, page furniture.

   Loaded AFTER app.css and adds to it rather than replacing anything.
   Tokens all come from app.css -- nothing new is defined here, so the
   palette stays in one place.
   ===================================================================== */

/* =====================================================================
   THE SCROLLBAR IS WHY A CENTRED LAYOUT MOVES BETWEEN TABS.

   A tab with enough content to scroll gets a vertical scrollbar; a shorter
   one does not. Anything centred with margin auto then shifts sideways by
   the scrollbar's width as it appears and disappears — which reads as "the
   widths change on every tab" however fixed the grid columns underneath
   are. Fixing the columns does not help, because the columns were never
   the problem.

   Reserving the gutter permanently costs a few pixels and removes the
   movement. overflow-y: scroll is the older way to the same end, kept for
   browsers without scrollbar-gutter.
   ===================================================================== */

html {
  scrollbar-gutter: stable;
}

@supports not (scrollbar-gutter: stable) {
  html { overflow-y: scroll; }
}

/* --- shell -------------------------------------------------------- */

.shell {
  display: grid;
  grid-template-columns: 15rem 1fr;
  min-height: 100vh;
  min-height: 100dvh;
}

.sidebar {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding: 1.25rem 1rem;
  background: var(--panel);
  border-right: 1px solid var(--border);
}

.sidebar .brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--text);
}

.sidebar .mon-sm { width: 1.75rem; height: 1.75rem; flex: none; }

.sidebar .wordmark {
  font-size: 0.85rem;
  letter-spacing: 0.03em;
  line-height: 1.2;
  color: var(--gold);
}

.sidenav {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.sidenav a {
  padding: 0.55rem 0.7rem;
  border-radius: var(--radius);
  border-left: 2px solid transparent;
  color: var(--muted);
  font-size: 0.9rem;
  text-decoration: none;
}

.sidenav a:hover {
  background: var(--panel-alt);
  color: var(--text);
}

/* The current page is marked by the accent edge rather than a fill, so a
   long nav does not turn into a row of competing blocks. */
.sidenav a[aria-current="page"] {
  background: var(--panel-alt);
  border-left-color: var(--gold);
  color: var(--text);
}

.sidefoot {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
  font-size: 0.78rem;
}

.sidefoot .who { color: var(--faint); }
.sidefoot a    { color: var(--muted); text-decoration: none; }
.sidefoot a:hover { color: var(--text); }

.main {
  padding: 1.75rem 2rem 4rem;
  max-width: 68rem;
}

/* --- page furniture ----------------------------------------------- */

.back {
  display: inline-block;
  margin-bottom: 0.75rem;
  font-size: 0.82rem;
  color: var(--muted);
  text-decoration: none;
}

.back:hover { color: var(--gold); }

.page-title {
  margin: 0 0 1.25rem;
  font-size: 1.35rem;
  font-weight: 500;
  letter-spacing: 0.01em;
}

/* --- tabs ---------------------------------------------------------- */
/*
   Real links to real URLs. The underline marks the current one, which is
   the convention people already know from every other admin tool.
*/

.tabs {
  display: flex;
  gap: 0.25rem;
  margin: 0 0 1.5rem;
  border-bottom: 1px solid var(--border);
  /* overflow-x alone makes overflow-y compute to auto, which renders a
     vertical scrollbar inside a 40px strip. Both have to be stated. */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.tabs::-webkit-scrollbar { display: none; }

.tabs a {
  padding: 0.55rem 0.9rem;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  color: var(--muted);
  font-size: 0.88rem;
  text-decoration: none;
  white-space: nowrap;
}

.tabs a:hover { color: var(--text); }

.tabs a[aria-current="page"] {
  border-bottom-color: var(--gold);
  color: var(--text);
}

/* --- day groups on the calendar ------------------------------------ */

.day {
  margin-bottom: 1.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  overflow: hidden;
}

.day-head {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  padding: 0.7rem 1rem;
  background: var(--panel-alt);
  border-bottom: 1px solid var(--border);
  font-size: 0.88rem;
}

.day-head .date { color: var(--gold); }
.day-head .rest { color: var(--muted); font-size: 0.8rem; }

.day-closed .day-head { background: var(--danger-bg); }
.day-closed .day-head .date { color: var(--text); }

.session {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  padding: 0.65rem 1rem;
  border-bottom: 1px solid var(--border);
  font-size: 0.9rem;
}

.session:last-child { border-bottom: 0; }

.session .time {
  flex: none;
  width: 9.5rem;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-size: 0.85rem;
}

.session .what { flex: 1; }
.session .who  { color: var(--faint); font-size: 0.8rem; }

.session .count {
  flex: none;
  font-variant-numeric: tabular-nums;
  font-size: 0.82rem;
  color: var(--muted);
}

/* Blocked mat time is not a class. Muted and struck through so it reads as
   "unavailable" at a glance rather than as something with a roster. */
.session-block .what { color: var(--muted); font-style: italic; }
.session-cancelled .what { text-decoration: line-through; color: var(--faint); }

/* --- small pieces --------------------------------------------------- */

.pill {
  display: inline-block;
  padding: 0.08rem 0.45rem;
  border-radius: 1rem;
  border: 1px solid var(--border);
  font-size: 0.7rem;
  color: var(--muted);
  vertical-align: middle;
}

.pill-warn { border-color: rgba(180, 60, 60, 0.4); color: var(--danger); }
.pill-ok   { border-color: rgba(74, 143, 92, 0.4);  color: var(--ok); }

.toolbar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 1.1rem;
  flex-wrap: wrap;
}

.empty {
  padding: 2rem 1rem;
  text-align: center;
  color: var(--faint);
  font-size: 0.88rem;
}

.field-row {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}

.field-row .field { flex: 1 1 10rem; margin-bottom: 1.1rem; }

/* --- narrow screens ------------------------------------------------- */
/*
   The sidebar becomes a horizontal strip rather than disappearing behind a
   hamburger. Six items fit across a phone, and a menu you have to open is
   a menu you forget is there.
*/

@media (max-width: 45rem) {
  .shell { grid-template-columns: 1fr; }

  .sidebar {
    flex-direction: row;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 0.75rem;
    border-right: 0;
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
  }

  .sidebar .wordmark { display: none; }

  .sidenav { flex-direction: row; }

  .sidenav a {
    border-left: 0;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    padding: 0.4rem 0.55rem;
  }

  .sidenav a[aria-current="page"] {
    border-left: 0;
    border-bottom-color: var(--gold);
  }

  .sidefoot {
    margin-top: 0;
    margin-left: auto;
    flex-direction: row;
    align-items: center;
    padding-top: 0;
    border-top: 0;
  }

  .sidefoot .who { display: none; }

  .main { padding: 1.25rem 1rem 3rem; }

  .session { flex-wrap: wrap; }
  .session .time { width: 100%; }
}


/* =====================================================================
   Calendar grid  --  FullCalendar 7.

   VERSION 7 HAS NO STABLE CLASS NAMES. They are generated (.fc-classic-n5m)
   and change between releases, so nothing below targets one. Styling is done
   two ways only:

     1. overriding the --fc-classic-* custom properties the theme exposes
     2. our own sb-* classes, attached by our hooks in calendar.js

   Anything written against an .fc-* selector will break silently on the next
   update. Do not add one.
   ===================================================================== */

#calendar {
  /* Map the theme onto the school palette. Dark mode is already on via
     data-color-scheme, so these override its dark values, not the light. */
  --fc-classic-background:        transparent;
  --fc-classic-foreground:        var(--text);
  --fc-classic-faint:             rgba(255, 255, 255, 0.03);
  --fc-classic-faint-foreground:  var(--faint);
  --fc-classic-muted:             rgba(255, 255, 255, 0.06);
  --fc-classic-muted-foreground:  var(--muted);
  --fc-classic-strong:            rgba(255, 255, 255, 0.10);

  --fc-classic-border:            var(--border);
  --fc-classic-strong-border:     var(--gold-dim);

  --fc-classic-primary:           var(--gold);
  --fc-classic-primary-foreground:#0d0d0d;

  /* SET EXPLICITLY, NOT DERIVED.
     
     palette.css declares these on :root as var(--fc-classic-primary). A
     custom property is substituted where it is *declared*, so :root resolved
     them to the literal #3788d8 and inherited that down — overriding
     --fc-classic-primary here arrived too late to change anything, which is
     why the events stayed FullCalendar blue through several rounds of
     supposedly-correct overrides.
     
     Anything palette.css derives from another variable has to be restated
     here rather than assumed to follow. */
  --fc-classic-event:             transparent;
  --fc-classic-event-contrast:    var(--text);
  --fc-classic-background-event:  var(--gold-dim);

  --fc-classic-button:            var(--panel);
  --fc-classic-button-border:     var(--border);
  --fc-classic-button-strong:     var(--panel-alt);
  --fc-classic-button-strong-border: var(--gold-dim);
  --fc-classic-button-foreground: var(--text);
  --fc-classic-button-outline:    rgba(212, 175, 106, 0.5);

  --fc-classic-today:             rgba(212, 175, 106, 0.08);
  --fc-classic-now:               var(--danger);
  --fc-classic-highlight:         rgba(212, 175, 106, 0.12);

  --fc-event-color:               transparent;
  --fc-event-contrast-color:      var(--text);

  font-size: 0.88rem;
}

/* --- our own classes, attached in calendar.js ------------------------ */

.sb-day     { position: relative; min-height: 8rem; }
.sb-dayhead { position: relative; }

/* Past days recede rather than vanish. You still need to read them. */
.sb-day-past { background: rgba(0, 0, 0, 0.22); }

/* --- event cards ---------------------------------------------------- */

.ev {
  /* Fills the day cell. This is the card — everything FullCalendar wraps
     around it is scaffolding, and three earlier attempts styled the
     scaffolding instead, which is why a blue bar kept showing beside it. */
  display: block;
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--border);
  border-left: 3px solid var(--gold-dim);
  border-radius: var(--radius);
  background: var(--panel);
  padding: 0.45rem 0.55rem;
  margin-bottom: 0.3rem;
  white-space: normal;
  cursor: pointer;
}

.ev-time  { font-size: 0.72rem; color: var(--faint); font-variant-numeric: tabular-nums; }
.ev-title { font-size: 0.83rem; color: var(--text); line-height: 1.3; }
.ev-who   { font-size: 0.72rem; color: var(--muted); margin-top: 0.15rem; }
.ev-count { font-size: 0.72rem; color: var(--muted); margin-top: 0.25rem; font-variant-numeric: tabular-nums; }
.ev-flag  { font-size: 0.7rem;  color: var(--danger); margin-top: 0.2rem; }

.ev-past      { opacity: 0.45; cursor: default; }
.ev-block     { background: var(--panel-alt); }
.ev-block .ev-title     { color: var(--muted); font-style: italic; }
.ev-cancelled .ev-title { text-decoration: line-through; color: var(--faint); }

.ev-book {
  display: block;
  margin-top: 0.45rem;
  padding: 0.28rem 0;
  border: 1px solid var(--gold-dim);
  border-radius: var(--radius);
  text-align: center;
  font-size: 0.74rem;
  color: var(--gold);
  text-decoration: none;
}

.ev-book:hover { background: rgba(212, 175, 106, 0.1); }

/* --- hover affordances ----------------------------------------------- */
/*
   Shown on hover AND on keyboard focus. A hover-only control cannot be
   reached without a mouse, which would make closing a day impossible from
   the keyboard.
*/

.day-add {
  display: block;
  width: calc(100% - 0.5rem);
  margin: 0.25rem;
  padding: 0.3rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--faint);
  font: inherit;
  font-size: 0.74rem;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s;
}

.sb-day:hover .day-add,
.day-add:focus-visible { opacity: 1; }

.day-add:hover { border-color: var(--gold-dim); color: var(--gold); }

.day-menu {
  position: absolute;
  top: 0.15rem;
  right: 0.15rem;
  border: 0;
  background: transparent;
  color: var(--faint);
  font-size: 0.95rem;
  line-height: 1;
  padding: 0.15rem 0.3rem;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s;
}

.sb-dayhead:hover .day-menu,
.day-menu:focus-visible { opacity: 1; }

.day-menu:hover { color: var(--gold); }

/* --- dialogs ---------------------------------------------------------- */

.modal {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 3rem 1rem;
  overflow-y: auto;
  background: rgba(0, 0, 0, 0.65);
}

.modal[hidden] { display: none; }

body.modal-open { overflow: hidden; }

.modal-panel {
  width: 100%;
  max-width: 34rem;
  padding: 1.25rem 1.4rem 1.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
}

.modal-sm { max-width: 26rem; }

.modal-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.25rem;
}

.modal-head h2 { margin: 0; font-size: 1.05rem; font-weight: 500; }

.modal-x {
  margin-left: auto;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
}

.modal-x:hover { color: var(--text); }

.modal-sub { margin: 0 0 1.1rem; font-size: 0.82rem; color: var(--gold); }

.modal-foot {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}

.check { display: flex; align-items: center; gap: 0.5rem; font-size: 0.88rem; }
.check input { width: auto; }

/* --- field types app.css does not cover ------------------------------- */
/*
   app.css styles text, email, number and date inputs. A time input was
   never in that list, so the two in the Add session dialog fall back to the
   browser's light default and sit white on a dark panel.
*/

.field input[type="time"],
.field input[type="datetime-local"] {
  width: 100%;
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-alt);
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
}

.field input[type="time"]:focus,
.field input[type="datetime-local"]:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold-dim);
}

/* The little clock and calendar buttons are black-on-black otherwise. */
.field input[type="time"]::-webkit-calendar-picker-indicator,
.field input[type="date"]::-webkit-calendar-picker-indicator,
.field input[type="datetime-local"]::-webkit-calendar-picker-indicator {
  filter: invert(0.75);
  cursor: pointer;
}

/* --- second-level tabs ------------------------------------------------ */

.tabs-sub { margin-top: -1rem; border-bottom: 0; }
.tabs-sub a { font-size: 0.82rem; padding: 0.4rem 0.7rem; }

/* --- Google address lookup -------------------------------------------- */
/*
   gmp-place-autocomplete is a web component with its own shadow DOM, so its
   internals cannot be styled from here. Only the outer box is ours. It sits
   above the real address fields as a helper, and if the script never loads
   the element is removed and the plain fields remain.
*/

gmp-place-autocomplete {
  display: block;
  width: 100%;
  margin-bottom: 0.5rem;
  border-radius: var(--radius);
  color-scheme: dark;
}

/* Catch-all so a field type nobody listed does not fall back to the
   browser's light default, which is how the phone and time inputs ended up
   white on a dark panel. */
.field input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]),
.field select,
.field textarea {
  width: 100%;
  padding: 0.55rem 0.65rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-alt);
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
  border-color: var(--gold-dim);
}

/* --- file drop zone ---------------------------------------------------- */
/*
   A label wrapping a hidden file input. Clicking anywhere opens the picker
   with no JavaScript; the drag handling is an enhancement on top.
*/

.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 9rem;
  margin-bottom: 1.1rem;
  padding: 1.5rem;
  border: 2px dashed var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel-alt);
  color: var(--muted);
  text-align: center;
  font-size: 0.9rem;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}

.dropzone:hover,
.dropzone:focus-within { border-color: var(--gold-dim); }

.dropzone.is-over {
  border-color: var(--gold);
  background: rgba(212, 175, 106, 0.06);
}

.dropzone.has-file { border-style: solid; border-color: var(--ok); }

.dropzone-text strong { color: var(--text); font-weight: 500; }

/* Off-screen rather than display:none. A display:none form control cannot
   be focused, and a browser will refuse to submit a form containing one it
   needs to complain about — silently. This keeps it reachable by keyboard
   and submittable. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.dropzone-name {
  font-size: 0.82rem;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}

/* --- rendered agreement text ------------------------------------------ */
/*
   A scrolling panel holding a legal document. Comfortable line length and
   real spacing, because somebody is expected to read this before signing
   rather than scroll past it.
*/

.doc-body {
  max-height: 24rem;
  overflow-y: auto;
  padding: 1.25rem 1.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-alt);
  font-size: 0.88rem;
  line-height: 1.6;
  color: var(--muted);
}

.doc-body-short { max-height: none; }

.doc-body h2,
.doc-body h3,
.doc-body h4,
.doc-body h5 {
  margin: 1.4rem 0 0.5rem;
  color: var(--text);
  font-weight: 500;
  line-height: 1.3;
}

.doc-body h2 { font-size: 1.02rem; }
.doc-body h3 { font-size: 0.95rem; }
.doc-body h4,
.doc-body h5 { font-size: 0.9rem; }

.doc-body > :first-child { margin-top: 0; }

.doc-body p  { margin: 0 0 0.85rem; }
.doc-body strong { color: var(--text); font-weight: 600; }

.doc-body ul,
.doc-body ol { margin: 0 0 0.85rem 1.1rem; padding: 0; }
.doc-body li { margin-bottom: 0.35rem; }

.doc-body hr {
  margin: 1.5rem 0;
  border: 0;
  border-top: 1px solid var(--border);
}

.doc-body blockquote {
  margin: 0 0 0.85rem;
  padding: 0.6rem 0.9rem;
  border-left: 2px solid var(--gold-dim);
  background: rgba(212, 175, 106, 0.05);
}

/* Placeholders that were filled in. Marked so a signer can see which parts
   are about them specifically rather than boilerplate. */
.doc-body code {
  padding: 0.05rem 0.3rem;
  border-radius: 3px;
  background: rgba(212, 175, 106, 0.12);
  color: var(--gold);
  font-family: inherit;
  font-size: 0.95em;
}

/* =====================================================================
   Member portal.

   Its own shell, its own classes. Everything here is prefixed m- so it
   cannot collide with the staff side, and so a change to one never
   quietly alters the other.

   No inline styles in the portal templates. That was what made the first
   version look hand-assembled.
   ===================================================================== */

.mshell {
  max-width: 44rem;
  margin: 0 auto;
  padding: 0 1rem 4rem;
}

/* --- header ----------------------------------------------------------- */

.mhead {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1.25rem 0 1rem;
  border-bottom: 1px solid var(--border);
}

.mbrand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--gold);
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  text-decoration: none;
}

.mbrand .mon-sm { width: 1.6rem; height: 1.6rem; }

.mout {
  margin-left: auto;
  color: var(--muted);
  font-size: 0.82rem;
  text-decoration: none;
}

.mout:hover { color: var(--text); }

/* --- tabs ------------------------------------------------------------- */

.mtabs {
  display: flex;
  gap: 0.2rem;
  margin-bottom: 1.75rem;
  border-bottom: 1px solid var(--border);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.mtabs::-webkit-scrollbar { display: none; }

.mtabs a {
  padding: 0.7rem 0.9rem;
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  color: var(--muted);
  font-size: 0.9rem;
  text-decoration: none;
  white-space: nowrap;
}

.mtabs a:hover { color: var(--text); }

.mtabs a[aria-current="page"] {
  border-bottom-color: var(--gold);
  color: var(--text);
}

/* --- person switcher --------------------------------------------------- */

.mswitch {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 1.25rem;
  font-size: 0.85rem;
}

.mswitch-label { color: var(--faint); font-size: 0.78rem; }

.mswitch a {
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 1rem;
  color: var(--muted);
  text-decoration: none;
}

.mswitch a:hover { color: var(--text); border-color: var(--gold-dim); }

.mswitch a.is-current {
  border-color: var(--gold);
  background: rgba(212, 175, 106, 0.1);
  color: var(--gold);
}

/* --- headings and text -------------------------------------------------- */

.mtitle {
  margin: 0 0 1.25rem;
  font-size: 1.35rem;
  font-weight: 500;
}

.mh2 {
  margin: 0 0 0.85rem;
  font-size: 1rem;
  font-weight: 500;
  color: var(--text);
}

.mmuted { color: var(--muted); font-size: 0.9rem; margin: 0; }

.mhint {
  margin: 0.85rem 0 0;
  color: var(--faint);
  font-size: 0.8rem;
  line-height: 1.5;
}

.mfoot {
  margin-top: 2.5rem;
  color: var(--faint);
  font-size: 0.8rem;
  line-height: 1.6;
}

.mnote {
  padding: 0.9rem 1.1rem;
  margin-bottom: 1.5rem;
  border: 1px solid var(--border);
  border-left: 2px solid var(--gold-dim);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.6;
}

.mnote strong { color: var(--text); }

/* --- summary cards ------------------------------------------------------ */

.mcards {
  display: grid;
  /* Fixed count, not auto-fit. Three cards on one tab and two on another
     must not produce different card widths — the layout moving as you
     change tabs is what makes a page feel unstable. */
  grid-template-columns: repeat(3, 1fr);
  gap: 0.85rem;
  margin-bottom: 1.75rem;
}

@media (max-width: 36rem) {
  .mcards { grid-template-columns: 1fr; }
}

.mcard {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 1rem 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
}

.mcard-attention { border-color: var(--gold-dim); }

.mcard-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--faint);
}

.mcard-value { font-size: 1.02rem; color: var(--text); line-height: 1.3; }
.mcard-note  { font-size: 0.8rem; color: var(--muted); }

.mcard-link {
  margin-top: 0.6rem;
  font-size: 0.8rem;
  color: var(--gold);
  text-decoration: none;
}

.mcard-link:hover { text-decoration: underline; }

/* --- panels -------------------------------------------------------------- */

.mpanel {
  padding: 1.25rem 1.4rem;
  margin-bottom: 1.25rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
}

/* A floor, so a tab holding one line is not half the height of one holding
   a table and the content below does not jump as you switch. */
.mpanel { min-height: 7rem; }

.mpanel-attention { border-color: var(--gold-dim); }
.mpanel-quiet     { opacity: 0.6; }

/* --- definition lists ---------------------------------------------------- */

.mdl {
  display: grid;
  /* Fixed, not sized to content. A label column that fits "Date of birth"
     on one tab and "Rate" on another is a different width on each, and the
     page shifts as you move between them. */
  grid-template-columns: 8.5rem 1fr;
  gap: 0.5rem 1.25rem;
  margin: 0;
  font-size: 0.9rem;
}

.mdl dt { color: var(--faint); }
.mdl dd { margin: 0; color: var(--text); }

.mlist { margin: 0; padding-left: 1.1rem; font-size: 0.9rem; color: var(--text); }
.mlist li { margin-bottom: 0.3rem; }

/* --- tables --------------------------------------------------------------- */

.mtable { width: 100%; border-collapse: collapse; font-size: 0.88rem; }

.mtable th {
  padding: 0 0 0.5rem;
  border-bottom: 1px solid var(--border);
  color: var(--faint);
  font-weight: 400;
  font-size: 0.78rem;
  text-align: left;
}

.mtable td {
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--border);
  color: var(--muted);
}

.mtable td:first-child { color: var(--text); }
.mtable tr:last-child td { border-bottom: 0; }

/* --- schedule -------------------------------------------------------------- */

.mday { margin-bottom: 1.5rem; }

.mday-head {
  margin: 0 0 0.5rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
  color: var(--gold);
  font-size: 0.9rem;
  font-weight: 500;
}

.mday-closed .mday-head { color: var(--muted); }

.msession {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.4rem 0;
  font-size: 0.88rem;
  flex-wrap: wrap;
}

.msession-time {
  flex: none;
  width: 5.5rem;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  font-size: 0.82rem;
}

.msession-title { color: var(--text); }
.msession-who   { color: var(--faint); font-size: 0.8rem; }

.msession.is-cancelled .msession-title {
  text-decoration: line-through;
  color: var(--faint);
}

/* --- coming soon ------------------------------------------------------------ */
/*
   Stated rather than hidden. An empty section reads as broken; a sentence
   saying what is not built yet reads as progress.
*/

.msoon {
  padding: 1.1rem 1.3rem;
  margin-top: 1.75rem;
  border: 1px dashed var(--border);
  border-radius: var(--radius-lg);
  color: var(--faint);
  font-size: 0.85rem;
  line-height: 1.6;
}

.msoon .mh2 { color: var(--muted); font-size: 0.9rem; }
.msoon p    { margin: 0 0 0.6rem; }
.msoon strong { color: var(--muted); }

/* --- pills ------------------------------------------------------------------- */

.mpill {
  display: inline-block;
  padding: 0.08rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 1rem;
  color: var(--muted);
  font-size: 0.7rem;
  vertical-align: middle;
}

@media (max-width: 30rem) {
  .mdl { grid-template-columns: 1fr; gap: 0.15rem 0; }
  .mdl dt { margin-top: 0.6rem; }
  .msession-time { width: 100%; }
}

/* =====================================================================
   Kiosk.

   Read from a metre away by somebody in a uniform with a bag on their
   shoulder. Everything is large, there is one field, and nothing on the
   screen says anything about anybody who is not standing at it.
   ===================================================================== */

.kiosk {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: 2rem 1.5rem;
  text-align: center;
}

.kiosk-title { margin: 0 0 0.25rem; font-size: 1.8rem; font-weight: 500; }
.kiosk-sub   { margin: 0 0 2.5rem; color: var(--muted); font-size: 1rem; }

.kiosk-form { width: 100%; max-width: 20rem; }

.kiosk-label {
  display: block;
  margin-bottom: 0.6rem;
  color: var(--faint);
  font-size: 0.9rem;
}

.kiosk-code {
  width: 100%;
  padding: 1rem;
  border: 2px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  color: var(--text);
  font-size: 2.2rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.35em;
  text-align: center;
  font-family: inherit;
}

.kiosk-code:focus {
  outline: none;
  border-color: var(--gold);
}

.kiosk-go {
  width: 100%;
  margin-top: 1rem;
  padding: 1rem;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--gold);
  color: #0d0d0d;
  font: inherit;
  font-size: 1.1rem;
  cursor: pointer;
}

.kiosk-note {
  max-width: 24rem;
  margin: 2rem 0 0;
  color: var(--faint);
  font-size: 0.82rem;
  line-height: 1.6;
}

/* --- the answer ------------------------------------------------------- */

.kiosk-result {
  width: 100%;
  max-width: 26rem;
  padding: 1.75rem;
  margin-bottom: 2.5rem;
  border-radius: var(--radius-lg);
}

.kiosk-result h1 { margin: 0 0 0.35rem; font-size: 2rem; font-weight: 500; }
.kiosk-result p  { margin: 0; font-size: 0.95rem; }

.kiosk-ok {
  border: 1px solid rgba(74, 143, 92, 0.5);
  background: rgba(74, 143, 92, 0.12);
}

.kiosk-warn {
  border: 1px solid rgba(180, 60, 60, 0.5);
  background: rgba(180, 60, 60, 0.1);
}

/* --- the way out -------------------------------------------------------- */
/*
   Small, at the bottom, closed by default. A lock on a screen rather than a
   security boundary — the device's own kiosk mode is what actually holds a
   tablet to one app.
*/

.kiosk-exit {
  margin-top: auto;
  padding-top: 2rem;
  color: var(--faint);
  font-size: 0.8rem;
}

.kiosk-exit summary { cursor: pointer; opacity: 0.4; }
.kiosk-exit summary:hover { opacity: 1; }

.kiosk-exit form {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin-top: 0.75rem;
}

.kiosk-pin {
  width: 6rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-alt);
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
  text-align: center;
}

.kiosk-pinerr { color: var(--danger); }

/* --- kiosk keypad ------------------------------------------------------ */

.kiosk-display {
  margin: 0 0 1.5rem;
  font-size: 2.4rem;
  letter-spacing: 0.4em;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  min-height: 3rem;
}

.kpad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
  width: 100%;
  max-width: 18rem;
  margin: 0 auto;
}

.kkey {
  aspect-ratio: 1;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: var(--panel);
  color: var(--text);
  font: inherit;
  font-size: 1.6rem;
  cursor: pointer;
  transition: background 0.08s;
}

.kkey:active { background: var(--panel-alt); }
.kkey-quiet  { color: var(--muted); font-size: 1.3rem; }

.kkey-go {
  background: var(--gold);
  border-color: var(--gold);
  color: #0d0d0d;
}

.kkey-go:disabled {
  background: var(--panel);
  border-color: var(--border);
  color: var(--faint);
  cursor: default;
}

/* --- confirmation screen ------------------------------------------------ */

.kconfirm {
  display: grid;
  grid-template-columns: 15rem 1fr;
  min-height: 100vh;
  min-height: 100dvh;
}

.kconfirm-who {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 2rem 1.5rem;
  background: var(--panel-alt);
  border-right: 1px solid var(--border);
  text-align: center;
}

.kconfirm-back {
  align-self: flex-start;
  color: var(--muted);
  font-size: 0.85rem;
  text-decoration: none;
}

.kavatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 5rem;
  height: 5rem;
  margin: 2rem 0 1rem;
  border-radius: 50%;
  background: var(--gold);
  color: #0d0d0d;
  font-size: 1.6rem;
  letter-spacing: 0.02em;
}

.kconfirm-who h1 { margin: 0; font-size: 1.15rem; font-weight: 500; line-height: 1.3; }

.kconfirm-main { padding: 2rem 2.25rem 3rem; max-width: 38rem; }

.kconfirm-h {
  margin: 0 0 0.85rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--faint);
  font-weight: 500;
}

/* --- picking classes ----------------------------------------------------- */

.kpicks { display: flex; flex-direction: column; gap: 0.6rem; margin-bottom: 2.25rem; }

.kpick {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  cursor: pointer;
  font-size: 1rem;
}

.kpick:has(input:checked) {
  border-color: var(--gold);
  background: rgba(212, 175, 106, 0.08);
}

.kpick input { width: 1.2rem; height: 1.2rem; accent-color: var(--gold); }
.kpick-time  { color: var(--muted); font-variant-numeric: tabular-nums; min-width: 5rem; }
.kpick-title { color: var(--text); }

/* --- the attestation ------------------------------------------------------ */

.kattest {
  padding: 1.25rem 1.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--muted);
}

.kattest p { margin: 0 0 0.85rem; }
.kattest p:last-child { margin-bottom: 0; }
.kattest strong { color: var(--text); }
.kattest-quiet { color: var(--faint); font-size: 0.82rem; }

.kattest-tick {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin: 1.25rem 0 1.75rem;
  font-size: 1rem;
  color: var(--text);
  cursor: pointer;
}

.kattest-tick input { width: 1.3rem; height: 1.3rem; accent-color: var(--gold); }

.kconfirm-go {
  width: 100%;
  padding: 1.1rem;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--gold);
  color: #0d0d0d;
  font: inherit;
  font-size: 1.1rem;
  cursor: pointer;
}

@media (max-width: 40rem) {
  .kconfirm { grid-template-columns: 1fr; }
  .kconfirm-who {
    flex-direction: row;
    align-items: center;
    gap: 1rem;
    padding: 1rem 1.25rem;
    border-right: 0;
    border-bottom: 1px solid var(--border);
    text-align: left;
  }
  .kavatar { width: 3rem; height: 3rem; margin: 0; font-size: 1.05rem; }
  .kconfirm-back { align-self: center; margin-left: auto; order: 3; }
  .kconfirm-main { padding: 1.5rem 1.25rem 3rem; }
}

/* =====================================================================
   Record pages — a subject in a fixed column, tabs beside it.

   EVERY WIDTH HERE IS FIXED. Sizing a label column to its content means it
   changes between tabs, and the whole page shifts as you move around it.
   That was the complaint, and it is the rule for everything below.
   ===================================================================== */

/* A record page uses the full width available. The reading-width cap that
   suits a list makes the pane beside a 17rem sidebar uncomfortably narrow. */
.main:has(.record) { max-width: 82rem; }

.record {
  display: grid;
  grid-template-columns: 17rem minmax(0, 1fr);
  gap: 1.75rem;
  align-items: start;
  max-width: 68rem;
}

.record-side {
  position: sticky;
  top: 1.5rem;
  padding: 1.25rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
}

.record-main { min-width: 0; }

/* --- sidebar contents --------------------------------------------------- */

.rs-back {
  display: inline-block;
  margin-bottom: 1rem;
  color: var(--muted);
  font-size: 0.8rem;
  text-decoration: none;
}

.rs-back:hover { color: var(--gold); }

.rs-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 4.5rem;
  height: 4.5rem;
  margin: 0 auto 0.85rem;
  border-radius: 50%;
  background: var(--panel-alt);
  border: 1px solid var(--gold-dim);
  color: var(--gold);
  font-size: 1.35rem;
  letter-spacing: 0.02em;
}

.rs-name {
  margin: 0 0 0.5rem;
  font-size: 1.1rem;
  font-weight: 500;
  line-height: 1.3;
  text-align: center;
}

.rs-status {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.3rem;
  margin: 0 0 1rem;
}

.rs-tag {
  padding: 0.1rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 1rem;
  color: var(--muted);
  font-size: 0.7rem;
}

.rs-tag-on { border-color: var(--gold-dim); color: var(--gold); }

/* --- the code ------------------------------------------------------------ */

.rs-code {
  padding: 0.7rem;
  margin-bottom: 1rem;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  text-align: center;
}

.rs-code-value {
  display: block;
  font-size: 1.5rem;
  letter-spacing: 0.22em;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.rs-code-label {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.7rem;
  color: var(--faint);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* --- quick actions -------------------------------------------------------- */
/*
   Fixed three-column grid rather than flex, so a person with no email does
   not produce differently sized buttons from one who has both.
*/

.rs-actions {
  display: grid;
  /* Call and Email. Anything reached once per member belongs in a panel
     with room to explain itself, not among the quick actions. */
  grid-template-columns: repeat(2, 1fr);
  gap: 0.4rem;
  margin-bottom: 1.25rem;
}

.rs-action {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
  padding: 0.5rem 0.2rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--muted);
  font-size: 0.7rem;
  text-decoration: none;
}

.rs-action:hover { border-color: var(--gold-dim); color: var(--gold); }
.rs-action-icon { font-size: 1rem; line-height: 1; }

/* --- the detail list ------------------------------------------------------- */

.rs-dl {
  display: grid;
  grid-template-columns: 4.5rem 1fr;   /* fixed. see note at the top. */
  gap: 0.45rem 0.6rem;
  margin: 0 0 1rem;
  font-size: 0.82rem;
}

.rs-dl dt { color: var(--faint); }
.rs-dl dd { margin: 0; color: var(--text); min-width: 0; }

.rs-wrap  { overflow-wrap: anywhere; }
.rs-quiet { color: var(--faint); }

.rs-block {
  padding-top: 0.9rem;
  margin-top: 0.9rem;
  border-top: 1px solid var(--border);
}

.rs-block-warn { border-top-color: rgba(180, 60, 60, 0.4); }

.rs-h {
  margin: 0 0 0.5rem;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--faint);
  font-weight: 500;
}

.rs-line { margin: 0 0 0.6rem; font-size: 0.82rem; line-height: 1.45; }
.rs-line:last-child { margin-bottom: 0; }

@media (max-width: 52rem) {
  .record { grid-template-columns: 1fr; }
  .record-side { position: static; }
}


/* --- sidebar additions --------------------------------------------------- */

.rs-since {
  margin: 0 0 0.75rem;
  text-align: center;
  font-size: 0.75rem;
  color: var(--faint);
  line-height: 1.5;
}

.rs-edit { display: block; text-align: center; margin-bottom: 1rem; }

/* A form wrapper must not become a grid item of its own, or the button
   inside it lays out differently from the two anchors beside it. */
.rs-action-form { display: contents; }

/* The button inherits nothing from a UA stylesheet: without this it renders
   as a white box beside two dark anchors. */
button.rs-action {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  color: var(--muted);
  font: inherit;
  font-size: 0.7rem;
  cursor: pointer;
  width: 100%;
}

button.rs-action:hover { border-color: var(--gold-dim); color: var(--gold); }

.rs-action.is-off {
  opacity: 0.3;
  cursor: default;
  pointer-events: none;
}

.rs-small {
  display: inline-block;
  margin-top: 0.3rem;
  font-size: 0.78rem;
  color: var(--gold);
  text-decoration: none;
}

.rs-small:hover { text-decoration: underline; }

/* --- notes ---------------------------------------------------------------- */

.note-item {
  padding: 0.9rem 0;
  border-bottom: 1px solid var(--border);
}

.note-item:last-child { border-bottom: 0; padding-bottom: 0; }
.note-item.is-pinned  { border-left: 2px solid var(--gold-dim); padding-left: 0.9rem; }
.note-imported        { opacity: 0.65; }

.note-head {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.35rem;
}

.note-author { font-size: 0.85rem; color: var(--text); }
.note-when   { font-size: 0.78rem; color: var(--faint); }

.note-body {
  margin: 0 0 0.5rem;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--muted);
}

.note-actions { display: flex; gap: 0.9rem; }

.note-btn {
  padding: 0;
  border: 0;
  background: none;
  color: var(--faint);
  font: inherit;
  font-size: 0.76rem;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.note-btn:hover { color: var(--gold); }

/* --- membership cards ------------------------------------------------------ */

.ms-card {
  padding: 1rem 1.1rem;
  margin-bottom: 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-alt);
}

.ms-card:last-child { margin-bottom: 0; }
.ms-card.is-ended   { opacity: 0.55; }

.ms-head {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin-bottom: 0.75rem;
}

.ms-head h3 { margin: 0; font-size: 1rem; font-weight: 500; }

/* Fixed columns: a membership with a shorter plan name must not lay out
   differently from one beside it. */
.ms-dl {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem 1rem;
  margin: 0;
}

.ms-dl dt {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--faint);
  margin-bottom: 0.15rem;
}

.ms-dl dd { margin: 0; font-size: 0.88rem; color: var(--text); }

@media (max-width: 38rem) {
  .ms-dl { grid-template-columns: repeat(2, 1fr); }
}

/* --- editing a membership ------------------------------------------------ */

.ms-editlink { margin: 0.85rem 0 0; }

.ms-edit {
  padding-top: 1rem;
  margin-top: 0.85rem;
  border-top: 1px solid var(--border);
}

/* Fixed columns, so the form does not reflow as values change length. */
.ms-edit-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem 1rem;
  margin-bottom: 0.5rem;
}

.ms-edit-grid .field { margin: 0; }

@media (max-width: 42rem) {
  .ms-edit-grid { grid-template-columns: repeat(2, 1fr); }
}

/* A panel holding something that will happen unless somebody intervenes. */
.panel-attention { border-color: var(--gold-dim); }

/* A count beside a tab label. Fixed minimum width so tabs do not shift as
   numbers change. */
.tab-count {
  display: inline-block;
  min-width: 1.4rem;
  padding: 0.05rem 0.35rem;
  margin-left: 0.3rem;
  border-radius: 1rem;
  background: var(--panel-alt);
  color: var(--muted);
  font-size: 0.72rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* --- calendar cards ------------------------------------------------------ */
/*
   FullCalendar wraps our .ev card in several elements. A card cannot fill a
   cell if anything between it and the cell is narrower, so the whole chain
   stretches — and none of them paints, because .ev is the surface.

   The theme's own class names are obfuscated, which is why guessing at
   selectors failed repeatedly. --fc-event-color is the documented way to
   stop it painting its default blue.
*/

#calendar {
  --fc-event-color:          transparent;
  --fc-event-contrast-color: var(--text);
}

/* --- kiosk: three columns ------------------------------------------------ */
/*
   Today's classes, the keypad, and who just checked in — all at once. The
   screen stands alone by the door, and the questions it answers without
   being asked are: what is on, am I early, did my tap register.
*/

.kmain {
  display: grid;
  grid-template-columns: 16rem 1fr 14rem;   /* fixed sides, keypad takes the rest */
  gap: 1px;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--border);
}

.kcol {
  padding: 1.5rem 1.25rem;
  background: var(--bg);
}

.kcol-pad {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.kcol-h {
  margin: 0 0 0.25rem;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--faint);
  font-weight: 500;
}

.kdate { margin: 0 0 1.25rem; color: var(--muted); font-size: 0.88rem; }
.kquiet { color: var(--faint); font-size: 0.85rem; margin: 0; }

/* --- today's classes ------------------------------------------------------ */

.kclass {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.88rem;
}

.kclass:last-child { border-bottom: 0; }
.kclass-time { color: var(--muted); font-variant-numeric: tabular-nums; min-width: 4.5rem; }
.kclass-name { color: var(--text); }

.kclass-tag {
  padding: 0.05rem 0.4rem;
  border-radius: 1rem;
  font-size: 0.68rem;
  border: 1px solid var(--border);
  color: var(--faint);
}

.kclass-now .kclass-tag { border-color: var(--gold-dim); color: var(--gold); }
.kclass-now .kclass-name { color: var(--gold); }
.kclass-done { opacity: 0.4; }
.kclass-off  { opacity: 0.5; text-decoration: line-through; }

/* --- recent check-ins ------------------------------------------------------ */

.krecent {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.88rem;
}

.krecent:last-of-type { border-bottom: 0; }
.krecent-name { color: var(--text); }
.krecent-time { color: var(--faint); font-size: 0.78rem; font-variant-numeric: tabular-nums; }

.kiosk-exit-note { margin-top: 2rem; font-size: 0.75rem; opacity: 0.35; }
.kiosk-exit-note a { color: var(--muted); text-decoration: none; }
.kiosk-exit-note a:hover { opacity: 1; color: var(--gold); }

/* --- account alerts on the confirm screen ---------------------------------- */

.kalerts { margin-bottom: 1.75rem; }

.kalert {
  padding: 0.85rem 1rem;
  margin-bottom: 0.5rem;
  border-radius: var(--radius);
  font-size: 0.92rem;
  line-height: 1.5;
}

.kalert-warn {
  border: 1px solid rgba(180, 60, 60, 0.5);
  background: rgba(180, 60, 60, 0.1);
  color: var(--text);
}

.kalert-note {
  border: 1px solid var(--gold-dim);
  background: rgba(212, 175, 106, 0.08);
  color: var(--text);
}

/* A narrow tablet drops the side columns below the keypad rather than
   squeezing three columns into nothing. */
@media (max-width: 56rem) {
  .kmain { grid-template-columns: 1fr; min-height: 0; }
  .kcol-pad { order: -1; padding: 2rem 1.25rem; }
}

/* --- portal: signed-in devices -------------------------------------------- */

.mdevice {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--border);
  font-size: 0.9rem;
}

.mdevice:last-of-type { border-bottom: 0; }
.mdevice-name { color: var(--text); }
.mdevice-when { color: var(--faint); font-size: 0.8rem; white-space: nowrap; }

/* The staff route off the member sign-in page. Readable: it is the only way
   staff reach their own sign-in, and a 30%-opacity link is not a way. */
.msignin-staff {
  margin: 2.5rem 0 0;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
  text-align: center;
  font-size: 0.88rem;
  color: var(--muted);
}

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

/* --- compressed days ------------------------------------------------------ */
/*
   The school runs two days a week. A seven-column grid gives five of them to
   nothing, which leaves the two that matter narrow and hard to read —  but
   hiding the other five entirely makes the week jump from Sunday to Saturday
   and you lose your place in the month.
   
   So they stay, as thin strips. The date is still there; there is simply no
   room for anything else, and nothing else is there anyway.
   
   Driven by classes calendar.js puts on the container from the class blocks,
   so a Wednesday class appearing widens Wednesday without touching this file.
*/


/* --- calendar columns ----------------------------------------------------- */
/*
   FullCalendar 7 hashes its own class names, so .fc-day-mon, .fc-daygrid-event
   and the rest do not exist in this build — they are version 6 names. Several
   rounds of CSS written against them did nothing at all, which the vendored
   VERSION.txt warns about in as many words.

   Two supported routes: override the --fc-classic-* variables, or attach our
   own classes through the *ClassNames hooks. These use the second, which is
   why everything here carries an sb- prefix.

   CLOSED DAYS ARE COMPRESSED, NOT HIDDEN. Removing them makes a week jump
   from Sunday to Saturday and you lose your place in the month. As narrow
   strips they still read — Mon 14, Tue 15 — while the two days that matter
   take the room.
*/

#calendar .sb-col-quiet {
  /* Wide enough for "Mon 14" and a little air, and the same for all five. */
  width: 4.5rem;
  max-width: 4.5rem;
  min-width: 4.5rem;
  background: rgba(0, 0, 0, 0.28);
  overflow: hidden;
}

#calendar .sb-col-quiet,
#calendar .sb-col-quiet * {
  font-size: 0.72rem;
  color: var(--faint);
}

/* Nothing is ever scheduled in one, so nothing needs room. */
#calendar .sb-col-quiet .ev,
#calendar .sb-col-quiet .sb-add { display: none; }

/* With five columns compressed the two open ones are wide. Enough height
   that a card reads as a card rather than a strip. */
#calendar .sb-col-open { min-height: 7rem; }

/* --- the trial check-in code ---------------------------------------------- */
/*
   Shown on the confirmation and emailed. A visitor who types it at the kiosk
   is recorded as having turned up, which is what lets a no-show be arithmetic
   rather than something somebody remembers to mark.
*/

.checkin-code-panel {
  padding: 1.25rem;
  margin-bottom: 1.75rem;
  border: 1px solid var(--gold-dim);
  border-radius: var(--radius-lg);
  background: rgba(212, 175, 106, 0.06);
}

.checkin-code-value {
  display: block;
  font-size: 2rem;
  letter-spacing: 0.3em;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}

.checkin-code-label {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--faint);
}

.checkin-code-note {
  margin: 0.85rem 0 0;
  font-size: 0.85rem;
  color: var(--muted);
  line-height: 1.5;
}

/* =====================================================================
   The trial form.

   The one page a stranger sees first, reached from an advert. Everything
   here is about it not reading as work: one step at a time, large targets,
   and no field visible before it is needed.

   Without script every step shows and the form still submits — which is
   why the hiding lives in a class the script adds rather than in the
   markup.
   ===================================================================== */

.trial-shell {
  max-width: 34rem;
  margin: 2rem auto;
  padding: 0 1rem 3rem;
}

.trial-form {
  padding: 1.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel);
}

.tstep-h {
  margin: 0 0 0.35rem;
  font-size: 1.35rem;
  font-weight: 500;
}

.tstep-lead {
  margin: 0 0 1.5rem;
  color: var(--muted);
  font-size: 0.92rem;
  line-height: 1.55;
}

/* --- step one: the three paths ------------------------------------------- */

.tchoices { display: grid; gap: 0.6rem; }

.tchoice {
  display: block;
  width: 100%;
  padding: 1.1rem 1.25rem;
  text-align: left;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--panel-alt);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: border-color 0.12s;
}

.tchoice:hover { border-color: var(--gold-dim); }

.tchoice-title { display: block; font-size: 1.02rem; }

.tchoice-note {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.82rem;
  color: var(--faint);
}

/* --- picking a time ------------------------------------------------------- */

.tdays { margin-bottom: 1.5rem; }

.tday { margin-bottom: 1.25rem; }

.tday-h {
  margin: 0 0 0.5rem;
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--faint);
  font-weight: 500;
}

/* [hidden] LOSES TO AN EXPLICIT display.
   
   The browser's built-in rule is [hidden] { display: none }, which an element
   rule setting display: flex overrides — so the script could set hidden all
   it liked and the slot stayed on screen. Any element the script hides needs
   its own hidden rule if it also sets display. */
.tslot[hidden],
.tday[hidden],
.tstep[hidden],
.tnone[hidden] { display: none !important; }

.tslot {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.8rem 1rem;
  margin-bottom: 0.4rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-alt);
  cursor: pointer;
  font-size: 0.95rem;
}

.tslot:has(input:checked) {
  border-color: var(--gold);
  background: rgba(212, 175, 106, 0.09);
}

.tslot input { width: 1.15rem; height: 1.15rem; accent-color: var(--gold); }
.tslot-time  { min-width: 5.5rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.tslot-title { flex: 1; }

/* Honest scarcity: shown only when it is true, which is the only way it
   keeps working. */
.tslot-last {
  font-size: 0.72rem;
  color: var(--gold);
  white-space: nowrap;
}

.tnone { color: var(--muted); font-size: 0.9rem; }
.tnone a { color: var(--gold); }

/* --- navigation ----------------------------------------------------------- */

.tnav {
  display: flex;
  gap: 0.5rem;
  margin-top: 1.75rem;
}

.tnav .btn-primary { flex: 1; }

.tprivacy {
  margin: 1.25rem 0 0;
  text-align: center;
  font-size: 0.78rem;
  color: var(--faint);
}

.tprivacy a { color: var(--muted); }

/* The child-only steps and fields, hidden until that path is taken. Only
   once the script has taken over — without it, everything shows. */
.trial-form.is-stepped:not(.is-child) .tchild-only { display: none; }

/* A way out, from every public page. Somebody who changed their mind should
   not have to use the browser's back button to find the school again. */
.tback-site {
  max-width: 34rem;
  margin: 1.5rem auto 0;
  text-align: center;
  font-size: 0.82rem;
}

.tback-site a { color: var(--muted); text-decoration: none; }
.tback-site a:hover { color: var(--gold); }

/* Step dots on the trial form. Where you are, how far there is to go, and a
   way back to a step you have already answered. */
.tdots {
  display: flex;
  justify-content: center;
  gap: 0.45rem;
  list-style: none;
  margin: 0 0 1rem;
  padding: 0;
}

/* The marker belongs to the li, not the ol, so list-style above does not
   reach it — the numbers kept rendering beside the dots. Setting it here,
   and display: block, removes the marker box entirely. */
.tdots li {
  list-style: none;
  display: block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--border);
  transition: background 0.15s, transform 0.15s;
}

.tdots li.is-done { background: var(--gold-dim); }

.tdots li.is-here {
  background: var(--gold);
  transform: scale(1.35);
}

.tdots li[hidden] { display: none; }

/* --- the dashboard -------------------------------------------------------- */
/*
   What is on next, who is coming who has never been here, and who is owed a
   reply. Every row is something somebody can act on — a name to click, a
   time to be somewhere, a gap to close.
*/

.dash-h {
  margin: 0 0 1.5rem;
  font-size: 1.5rem;
  font-weight: 400;
}

.dash-row {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin: 0;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--border);
}

.dash-row:last-child { border-bottom: 0; }

.dash-time {
  min-width: 5rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* A visitor, and whether they are ready to walk in. */
.dash-trial {
  display: grid;
  grid-template-columns: 8rem 1fr auto;
  gap: 0.75rem;
  align-items: baseline;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--border);
}

.dash-trial:last-child { border-bottom: 0; }

.dash-trial-when { font-variant-numeric: tabular-nums; }
.dash-trial-when span { margin-left: 0.4rem; font-size: 0.85rem; }

.dash-trial-who .muted { font-size: 0.85rem; }

.dash-note {
  font-size: 0.82rem;
  font-style: italic;
  color: var(--muted);
}

.dash-trial-ready {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
  justify-content: flex-end;
}

@media (max-width: 40rem) {
  .dash-trial { grid-template-columns: 1fr; gap: 0.3rem; }
  .dash-trial-ready { justify-content: flex-start; }
}

/* The delete override. Folded away, because it is the answer to a rule the
   system has just given a good reason for — but present, because a rule with
   no way past it eventually traps somebody. */
.rs-override {
  margin-top: 0.75rem;
}

.rs-override > summary {
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--muted);
  list-style: none;
}

.rs-override > summary::-webkit-details-marker { display: none; }

.rs-override > summary::before {
  content: '▸ ';
  color: var(--faint);
}

.rs-override[open] > summary::before { content: '▾ '; }
.rs-override > summary:hover { color: var(--text); }

/* A quiet notice in the record sidebar: something that needs attention but
   is not an error, like a guardianship that has outlived a birthday. */
.rs-notice {
  margin: 0 0 1rem;
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--gold-dim);
  border-radius: var(--radius);
  background: rgba(212, 175, 106, 0.06);
}

.rs-notice p {
  margin: 0 0 0.6rem;
  font-size: 0.82rem;
  line-height: 1.45;
  color: var(--muted);
}

/* Type DELETE to confirm. One deliberate act, at the moment of doing it. */
.rs-delete-confirm {
  display: block;
  margin: 0.75rem 0;
  font-size: 0.82rem;
  color: var(--muted);
}

.rs-delete-confirm input {
  display: block;
  width: 9rem;
  margin-top: 0.3rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--panel-alt);
  color: var(--text);
  font: inherit;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.rs-delete-confirm input:focus {
  outline: none;
  border-color: var(--danger);
}

/* Per-document actions in the portal's paperwork list. */
.mdoc-actions {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  white-space: nowrap;
}

.mdoc-actions form { display: inline; }

.mdoc-actions button {
  padding: 0;
  border: 0;
  background: none;
  color: var(--gold);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}

.mdoc-actions button:hover { text-decoration: underline; }
