/* BCM Portal styles */

/* Core palette (docs/app_spec.md "Design Notes > Colors"): warm, not
   institutional — friendly, modern, uncluttered.
     blue   #0062DC  buttons, links, accents
     yellow #FFDC2B  primary CTAs only (Register, Pay Now, Submit)
     navy   #00132A  footer and contrast areas, white text on top
     coral  #FF724C  used sparingly, wherever it needs a little spice
   White backgrounds throughout, warm grays for secondary text and borders.
   Everything references these variables, so a future dark mode only needs an
   alternate :root[data-theme=dark] block — and re-theming means editing this
   block, not hunting through the file. */
:root {
  --color-bg: #ffffff;
  --color-surface: #fcfaf7;   /* warm off-white for raised cards */
  --color-surface-sunk: #f7f4ef; /* subtle warm fill: table heads, wells */
  --color-text: #1a2430;
  --color-text-muted: #6f6a63;  /* warm gray */
  --color-border: #e9e4dc;      /* warm gray */
  --color-border-strong: #d8d1c6;
  --color-primary: #0062DC;     /* buttons, links, accents */
  --color-primary-dark: #004fb0;
  --color-primary-soft: #e6f0fd;
  --color-navy: #00132A;        /* footer + contrast areas */
  --color-cta: #FFDC2B;         /* primary CTAs only */
  --color-cta-hover: #f2cd12;
  --color-cta-text: #00132A;
  --color-spice: #FF724C;       /* a little warmth where it earns it */
  --color-spice-soft: #ffe9e2;
  --color-spice-text: #b3421d; /* the coral, darkened enough to read as text */
  --color-callout: #1F9D5C;      /* the friendly asides ("Questions? Call us…") */
  --color-callout-soft: #e9f6ef;
  --color-notes-bg: #eef9f0;     /* notes: very light green — buttons and bubbles */
  --color-notes-bg-hover: #e0f3e5;
  --color-notes-border: #d2ecd9;
  --color-notes-text: #0b5b2a;
  --color-accent: #0062DC;
  --color-accent-soft: #e6f0fd;
  --color-danger: #c0392b;
  --color-topbar-top: #00132A;
  --color-topbar-bottom: #00132A;
  --color-topbar-text: #d7e3f4;
  --radius: 12px;
  --radius-sm: 9px;
  --shadow-card: 0 1px 2px rgba(0, 19, 42, 0.05), 0 6px 18px rgba(0, 19, 42, 0.05);
  /* Semester Schedule reservation states (see docs/app_spec.md) */
  --res-paid-bg: #dbeafe;          /* confirmed, no balance — blue pastel */
  --res-balance-full-bg: #fdf3c8;  /* confirmed, full semester due — yellow pastel */
  --res-balance-half-bg: #e9dcf7;  /* confirmed, half semester due — purple pastel */
  --res-balance-custom-bg: #1e3a5f;/* confirmed, custom balance — dark blue */
  --res-hold-bg: #e4e6ea;          /* hold block (lunch, errand) — neutral grey */
  --res-class-ensemble-bg: #d9f0de;     /* Guitar Ensemble class — green pastel */
  --res-class-musicianship-bg: #fbe2ec; /* Musicianship Skills class — rose pastel */
  --res-substitute-bg: #fde4cc;    /* someone else is covering this week — pastel orange */
  /* Semester-wide date list: the left rule that marks each date's status */
  --sem-date-active-line: #2e9e63;   /* a class day — green */
  --sem-date-inactive-line: #7c4dbd; /* a break or holiday — purple */
  --font-display: system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
  --font-body: system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
  --topbar-height: 56px;
}

/* Reset and base styles */
* {
  box-sizing: border-box;
}

body {
  font-family: var(--font-body);
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* Family-facing pages (parent & student): faint grey instrument line art
   around the content — a strip down each margin plus a band across the top,
   so the drawings frame the page instead of hiding behind the centered
   cards. The side strips repeat down the page; each ends in deliberate
   empty space, and the 200px offset wraps that emptiness to the very top so
   the corners stay clear of the band. Cards and modals are solid surfaces,
   so anything the column does cover stays texture, never content. (The ?v=
   busts browser caches when the drawings change.) */
body.instrument-bg {
  background-image:
    url('/images/instruments-left.svg?v=2'),
    url('/images/instruments-right.svg?v=2'),
    url('/images/instruments-top.svg?v=2');
  background-repeat: repeat-y, repeat-y, no-repeat;
  background-position: left 200px, right 200px, center 66px;
  background-size: 240px 2400px, 240px 2400px, 1400px 190px;
}

@media (max-width: 700px) {
  body.instrument-bg {
    background-size: 130px 1300px, 130px 1300px, 760px 103px;
    background-position: left 130px, right 130px, center 62px;
  }
}

/* Titles and anything asking the user to do something use the display font */
h1, h2, h3, .page-title {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--color-navy);
}

/* The most important words of instruction text ("Enter your code.") are bold
   italic in the display font so they are easy to pick out. */
.prompt-em {
  font-family: var(--font-display);
  font-weight: 700;
  font-style: italic;
}

a {
  color: var(--color-primary);
}

a:hover {
  color: var(--color-primary-dark);
}

/* Keyboard focus stays visible everywhere — a warm ring, not a browser
   default that vanishes against the blue. */
:focus-visible {
  outline: 3px solid var(--color-spice);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ===== Impersonation bar (dev-only "login as") ===== */

.impersonation-bar {
  background: #C2410C;
  color: #fff;
  text-align: center;
  font-size: 13px;
  padding: 4px 12px;
}

.impersonation-bar form {
  display: inline;
}

.impersonation-return {
  background: none;
  border: none;
  color: #fff;
  text-decoration: underline;
  cursor: pointer;
  font: inherit;
  padding: 0;
}

/* ===== Top bar ===== */

.topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: var(--topbar-height);
  padding: 8px 16px;
  background: linear-gradient(180deg, var(--color-topbar-top), var(--color-topbar-bottom));
  color: var(--color-topbar-text);
}

.topbar-brand {
  color: #fff;
  text-decoration: none;
  font-weight: 700;
  font-size: 16px;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
}

/* The white treble-clef logo (Images/BCM-logo-white-transparent-cropped.png):
   tall mark, sized by height, only visible on dark backgrounds. */
.brand-logo {
  height: 36px;
  width: auto;
  margin-right: 10px;
  flex: none;
}

.topbar-nav {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  margin-left: auto;
}

.topbar-nav a {
  color: var(--color-topbar-text);
  text-decoration: none;
  font-size: 14px;
  padding: 8px 10px;
  border-radius: 8px;
}

.topbar-nav a:hover,
.topbar-nav a:focus {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

.topbar-nav a.active {
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font-weight: 600;
}

/* Items that open a submenu bar get a small caret */
.topbar-nav a[data-subnav-toggle]::after {
  content: ' \25BE';
  font-size: 10px;
  opacity: 0.7;
}

.topbar-nav a[data-subnav-toggle][aria-expanded="true"]::after {
  content: ' \25B4';
}

/* Semester selector (admin): compact select in the top bar */
.semester-select {
  margin-left: 6px;
}

.semester-select select {
  width: auto;
  padding: 5px 8px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  font-size: 13px;
}

.semester-select select option {
  color: var(--color-text);
}

.semester-select.mobile {
  margin: 8px 12px 12px;
}

.semester-select.mobile select {
  width: 100%;
  background: #fff;
  color: var(--color-text);
  border: 1px solid var(--color-border);
  padding: 8px;
}

/* Avatar + dropdown at the far right of the top bar */
.nav-avatar-wrap {
  position: relative;
  flex: none;
}

.nav-avatar-btn {
  background: transparent;
  border: 0;
  padding: 2px;
  cursor: pointer;
  border-radius: 50%;
  display: inline-flex;
}

.nav-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid rgba(255, 255, 255, 0.25);
  flex: none;
}

.nav-avatar-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.15);
  color: #fff;
  font-weight: 700;
  font-size: 13px;
}

.avatar-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  background: var(--color-surface);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  min-width: 180px;
  padding: 6px;
  z-index: 1300;
}

.avatar-menu a {
  display: block;
  padding: 8px 10px;
  border-radius: 8px;
  color: var(--color-text);
  text-decoration: none;
}

.avatar-menu a:hover,
.avatar-menu a:focus {
  background: var(--color-surface-sunk);
}

/* "Admin Actions" dropdown (edit-user page) — same look as the avatar menu */
.nav-admin-wrap {
  position: relative;
  display: inline-block;
}

.admin-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  background: var(--color-surface);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
  min-width: 200px;
  padding: 6px;
  z-index: 1300;
}

.admin-menu a {
  display: block;
  padding: 8px 10px;
  border-radius: 8px;
  color: var(--color-text);
  text-decoration: none;
  white-space: nowrap;
}

.admin-menu a:hover,
.admin-menu a:focus {
  background: var(--color-surface-sunk);
}

/* Hamburger (mobile only) */
.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 38px;
  height: 38px;
  padding: 9px;
  background: transparent;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  flex: none;
}

.nav-toggle:hover {
  background: rgba(255, 255, 255, 0.12);
}

.nav-toggle span {
  display: block;
  height: 2px;
  width: 100%;
  background: #fff;
  border-radius: 2px;
}

/* ===== Mobile nav panel =====
   Full-width panel in normal document flow directly under the header: it
   pushes the page content down (no overlay, matching the subnav philosophy).
   Hidden on desktop. */
.mobile-nav {
  display: none;
  flex-direction: column;
  background: var(--color-topbar-bottom);
  padding: 6px 0;
}

.mobile-nav a {
  color: var(--color-topbar-text);
  text-decoration: none;
  font-size: 15px;
  padding: 12px 16px;
}

.mobile-nav a:hover,
.mobile-nav a:focus {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

.mobile-nav a.active {
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font-weight: 600;
}

.mobile-nav-sub {
  display: flex;
  flex-direction: column;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  margin-top: 4px;
  padding-top: 4px;
}

.mobile-nav-sub a {
  padding-left: 32px;
  font-size: 14px;
}

/* ===== Contextual submenu bar =====
   A full-width bar between the header and the content, in normal flow — it
   pushes the content down rather than overlaying it (cub_scouts admin-bar
   mechanism, rendered persistently per section). */
.subnav {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
  padding: 6px 16px;
  background: #0a2340;
  color: var(--color-topbar-text);
}

.subnav a {
  color: var(--color-topbar-text);
  text-decoration: none;
  font-size: 13px;
  padding: 6px 10px;
  border-radius: 6px;
}

.subnav a:hover,
.subnav a:focus {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}

.subnav a.active {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  font-weight: 600;
}

/* ===== Main content column ===== */

main {
  width: 100%;
  max-width: 1100px;
  margin: 24px auto;
  padding: 0 16px;
  flex: 1;
}

/* Wide pages (the Semester Schedule grid) use the full viewport width */
body.page-wide main {
  max-width: none;
}

/* ===== Minimal layout (auth-adjacent pages) ===== */

body.minimal {
  background: var(--color-bg);
}

.minimal-header {
  background: var(--color-navy);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 200;
  font-size: 20px;
  padding: 16px 20px;
  display: flex;
  align-items: center;
  border-bottom: 3px solid var(--color-cta);
}

.minimal-content {
  max-width: 680px;
  margin: 0 auto;
  padding: 32px 16px;
  width: 100%;
  flex: 1;
}

/* Public pages get a touch more air between sections than admin screens. */
.minimal-content h1 {
  margin-bottom: 0.5em;
}

.minimal-content h3 {
  margin-top: 22px;
}

/* Grid */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 16px;
}

/* Typography */
h2 {
  margin: 8px 0 16px;
}

h3 {
  margin: 6px 0 10px;
}

.small {
  font-size: 12px;
  color: var(--color-text-muted);
}

.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

/* Forms */
.stack {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.stack label {
  display: block;
  margin: 8px 0;
}

.stack .actions {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-top: 8px;
}

label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-weight: 500;
}

label.inline {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
}

input,
textarea,
select {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: #fff;
  font-family: inherit;
  font-size: 15px;
  color: var(--color-text);
}

input::placeholder,
textarea::placeholder {
  color: #a9a29a;
}

input:focus,
textarea:focus,
select:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-soft);
}

input[type="checkbox"],
input[type="radio"] {
  width: auto;
  height: auto;
  padding: 0;
  border: 0;
  vertical-align: middle;
}

/* Buttons */
button,
/* The everyday button: a quiet outlined control, so the blue primary and the
   yellow CTA are the only things competing for the eye on a screen. */
.button {
  display: inline-block;
  background: #fff;
  color: var(--color-navy);
  border: 1px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: 8px 14px;
  font-family: inherit;
  font-size: 14px;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.button:hover {
  background: var(--color-surface-sunk);
  border-color: var(--color-text-muted);
  color: var(--color-navy);
}

button.primary,
.button.primary {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
  font-weight: 600;
}

button.primary:hover,
.button.primary:hover {
  background: var(--color-primary-dark);
  border-color: var(--color-primary-dark);
  color: #fff;
}

button.danger,
.button.danger {
  background: var(--color-danger);
  border-color: var(--color-danger);
  color: #fff;
}

/* Notes buttons: light green, so "where the notes live" reads at a glance
   on every schedule and lesson card. */
button.notes,
.button.notes {
  background: var(--color-notes-bg);
  border-color: var(--color-notes-border);
  color: var(--color-notes-text);
}

button.notes:hover,
.button.notes:hover {
  background: var(--color-notes-bg-hover);
  border-color: #b9e0c3;
  color: var(--color-notes-text);
}

button:disabled,
.button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.inline {
  display: inline;
}

.actions {
  display: flex;
  gap: 8px;
  align-items: center;
}

/* Modal footer: the destructive action sits alone on the left, well away
   from Cancel/Save which pair up on the right (Save last). */
.actions-split {
  justify-content: space-between;
}

.actions-split .actions-right {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-left: auto;
}

/* Circular "+" button (e.g. Add a person, top-right of a page head) */
.plus-btn {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--color-primary);
  color: #fff;
  border: 0;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 0 2px;
  box-shadow: 0 2px 6px rgba(0, 98, 220, 0.30);
}

.plus-btn:hover {
  background: var(--color-primary-dark);
}

/* Messages */
.flash {
  background: #e7f6ed;
  color: #0f5d2f;
  padding: 10px;
  border-radius: 8px;
}

.error {
  background: var(--color-spice-soft);
  color: #7a0000;
  padding: 10px;
  border-radius: 8px;
}

.announcement {
  background: #fff6e0;
  border: 1px solid #f5d79a;
  color: #7a4a00;
  padding: 10px;
  border-radius: 8px;
}

/* Tables */
.list {
  width: 100%;
  border-collapse: collapse;
}

.list th,
.list td {
  padding: 8px;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}

.list th {
  background: var(--color-surface-sunk);
  font-weight: 600;
}

.list tr:hover {
  background: var(--color-surface);
}

/* Account status indicators (admin users pages) */
.status-verified {
  color: #0a6e3d;
  font-weight: 500;
}

.status-pending {
  color: #b45309;
  font-weight: 500;
}

/* Inline choice groups (role/instrument checkboxes) */
.choice-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 14px;
}

/* Badges. The plain one ("Cancelled", "Missed", "Time moved") is a warm gray
   pill — visible as a label without competing with the row it annotates. */
.badge {
  display: inline-block;
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 12px;
  background: var(--color-surface-sunk);
  color: var(--color-text-muted);
}

.badge.success {
  background: #e6fbf0;
  color: #0b7042;
}

/* Auth pages. Light and breathable like the rest of the portal — the card
   floats on a warm off-white rather than on a slab of navy, so signing in
   feels like the same welcoming place as everything behind it. */
.auth {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: 24px 16px;
  background: var(--color-surface-sunk);
  color: var(--color-text);
}

.auth .card {
  width: 380px;
  max-width: 100%;
  background: var(--color-bg);
  border-radius: var(--radius);
  padding: 28px 24px;
}

.auth .card .logo {
  display: block;
  max-width: 120px;
  height: auto;
  margin: 0 auto 16px auto;
}

.auth .card .subtitle {
  text-align: center;
  color: #666;
  font-size: 14px;
  margin: 8px 0 24px 0;
  font-weight: 500;
}

/* Modal */
.modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  z-index: 1400;
}

.modal.hidden {
  display: none;
}

.modal-content {
  background: #fff;
  max-width: 520px;
  width: 100%;
  border-radius: 16px;
  padding: 16px;
  position: relative;
  max-height: 90vh;
  overflow-y: auto;
}

/* In-modal tabs (schedule add modal: student lesson vs hold block) */
.modal-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--color-border);
  margin: 12px 0 16px;
}

.modal-tab {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 8px 12px;
  margin-bottom: -1px;
  font: inherit;
  color: var(--color-text-muted);
  cursor: pointer;
}

.modal-tab.active {
  color: var(--color-accent);
  border-bottom-color: var(--color-accent);
  font-weight: 600;
}

.modal .close {
  position: absolute;
  right: 8px;
  top: 8px;
  background: var(--color-surface-sunk);
  color: var(--color-text);
  border-radius: 50%;
  width: 32px;
  height: 32px;
  line-height: 28px;
  font-size: 20px;
  border: 0;
  padding-top: 3px;
  padding-left: 10px;
}

/* Typeahead (combobox with a results list under the input) */
.typeahead-wrap {
  position: relative;
}

.typeahead-results {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  max-height: 200px;
  overflow: auto;
  z-index: 1500;
  display: none;
}

.typeahead-results .typeahead-option {
  padding: 8px 10px;
  cursor: pointer;
}

.typeahead-results .typeahead-option.highlight {
  background: var(--color-accent-soft);
}

/* Utility */
.hidden {
  display: none !important;
}

details summary {
  cursor: pointer;
  color: var(--color-primary);
}

.description {
  padding-bottom: 10px;
}

/* ===== Responsive: nav collapses behind the hamburger ===== */
@media (max-width: 768px) {
  .topbar-nav,
  .subnav {
    display: none;
  }

  .nav-toggle {
    display: inline-flex;
  }

  /* On phones the logo stands alone (the name would crowd the bar) */
  .brand-full {
    display: none;
  }

  .brand-logo {
    margin-right: 0;
  }

  .topbar {
    gap: 10px;
  }

  /* Avatar stays in the bar; push it to the right of the brand */
  .nav-avatar-wrap {
    margin-left: auto;
  }

  .mobile-nav.open {
    display: flex;
  }

  main {
    padding: 16px;
    margin: 0 auto;
  }

  .actions {
    flex-direction: column;
    align-items: stretch;
  }

  .grid {
    grid-template-columns: 1fr !important;
  }
}

/* ===== BCM: brand wordmark ===== */

.brand-name {
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* The logo is white-on-transparent: on light surfaces (the login card's
   wordmark) invert it to dark so it stays visible. */
body.auth .brand-logo {
  filter: invert(1);
  opacity: 0.85;
  height: 44px;
  vertical-align: middle;
}

/* ===== BCM: site footer (copyright + phone number on every page) ===== */

.site-footer {
  margin-top: 48px;
  background: var(--color-navy);
  color: #d7e3f4;
  padding: 22px 24px;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 24px;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  /* A thin coral rule where the page meets the footer — the one place the
     accent gets to run the full width. */
  border-top: 3px solid var(--color-spice);
}

.site-footer a {
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.35);
}

.site-footer a:hover {
  color: var(--color-cta);
  border-bottom-color: var(--color-cta);
}

.site-footer-name {
  font-weight: 600;
}

/* ===== BCM: gold CTA buttons (Pay Now, Confirm — primary actions only) ===== */

.btn-cta {
  display: inline-block;
  background: var(--color-cta);
  color: var(--color-cta-text);
  border: 0;
  border-radius: 999px;
  padding: 13px 28px;
  font-family: inherit;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  box-shadow: 0 2px 0 rgba(0, 19, 42, 0.12);
  transition: background 0.15s ease, transform 0.05s ease;
}

.btn-cta:hover {
  background: var(--color-cta-hover);
  color: var(--color-cta-text);
}

.btn-cta:active {
  transform: translateY(1px);
  box-shadow: none;
}

.btn-cta:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.btn-outline {
  display: inline-block;
  background: transparent;
  color: var(--color-primary);
  border: 2px solid var(--color-primary);
  border-radius: 999px;
  padding: 11px 26px;
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
}

.btn-outline:hover {
  background: var(--color-primary);
  color: #fff;
}

/* The phone number, said out loud: a real person is one call away. Shown on
   the login page and at the top of the registration wizard (docs/app_spec.md
   — "a visible phone number on every page"; the footer carries the rest).
   Green rather than the coral accent — these asides are an invitation, and
   the coral is doing louder work elsewhere (the focus ring, the footer rule). */
.contact-callout {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
  background: var(--color-callout-soft);
  border-left: 4px solid var(--color-callout);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 10px 14px;
  margin: 16px 0;
  font-size: 15px;
}

.contact-callout a {
  color: var(--color-navy);
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
}

.contact-callout a:hover {
  text-decoration: underline;
}

/* ===== BCM: lessons ===== */

.online-tag {
  color: var(--color-primary);
  font-weight: 600;
  white-space: nowrap;
}

.lesson-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  align-items: baseline;
  padding: 12px 0;
  border-bottom: 1px solid var(--color-border);
}

.lesson-row-time {
  font-weight: 600;
  min-width: 120px;
}

/* A parent's phone and email on the admin student page: the reason the page
   is opened, so they read at a glance and copy cleanly (plain text, not
   tel:/mailto: links). */
.contact-big {
  font-size: 1.2rem;
  font-weight: 600;
  margin-top: 2px;
}
.contact-big .contact-sep {
  color: var(--color-text-muted);
  padding: 0 4px;
  font-weight: 400;
}

.lesson-cancelled {
  text-decoration: line-through;
  color: var(--color-text-muted);
}

/* When the next lesson is: the one thing a parent opens the portal to check,
   so it carries weight on the child's card rather than hiding in fine print. */
.next-lesson {
  margin-top: 8px;
  font-weight: 700;
}

/* A child's outstanding balance on their card. Red only when the family has
   fallen behind the schedule they were asked to keep (Billing::
   isSemesterPaymentBehind) — a balance that is simply not due yet is not an
   alarm. */
.balance-due {
  font-weight: 600;
  text-decoration: none;
}

.balance-due:hover {
  text-decoration: underline;
}

.balance-behind,
.balance-behind:hover {
  color: var(--color-danger);
}

/* A hold block in the teacher's week list — their own time, not a lesson. */
.lesson-row.lesson-hold {
  color: var(--color-text-muted);
}

/* A lesson's notes: a short thread anyone on the lesson can add to, each
   entry signed and dated (LessonDetailUIManager). Each note renders as a
   chat-style speech bubble in the notes light green, tail at lower left. */
.lesson-notes {
  margin: 4px 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.lesson-note {
  position: relative;
  max-width: 92%;
  margin-left: 8px;
  padding: 8px 12px;
  background: var(--color-notes-bg);
  border: 1px solid var(--color-notes-border);
  border-radius: 12px;
  border-bottom-left-radius: 3px;
}

/* The bubble's tail: a bordered triangle (border color) with a fill triangle
   (bubble color) laid one pixel inside it. */
.lesson-note::before,
.lesson-note::after {
  content: '';
  position: absolute;
  width: 0;
  height: 0;
  border-style: solid;
}

.lesson-note::before {
  left: -8px;
  bottom: 4px;
  border-width: 0 9px 9px 0;
  border-color: transparent var(--color-notes-border) transparent transparent;
}

.lesson-note::after {
  left: -5px;
  bottom: 5px;
  border-width: 0 7px 7px 0;
  border-color: transparent var(--color-notes-bg) transparent transparent;
}

.lesson-note-by {
  font-size: 12px;
  color: var(--color-text-muted);
  margin-top: 4px;
}

.lesson-notes-empty {
  margin: 4px 0;
}

.lesson-note-form {
  margin-top: 8px;
}

.lesson-note-form textarea {
  width: 100%;
  min-height: 54px;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 8px;
  font: inherit;
}

.note-save-state {
  font-size: 12px;
  color: var(--color-text-muted);
}

/* The materials dropzone: drag a voice memo (or any file) onto the modal.
   The real file input is visually hidden but still the thing the form
   submits; the dropzone is its face. */
.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 18px 12px;
  text-align: center;
  cursor: pointer;
  border: 2px dashed var(--color-border-strong);
  border-radius: var(--radius-sm);
  background: var(--color-surface-sunk);
  transition: background 0.15s ease, border-color 0.15s ease;
}

.dropzone:hover,
.dropzone:focus-visible {
  border-color: var(--color-text-muted);
}

.dropzone.dragover {
  background: var(--color-notes-bg);
  border-color: var(--color-callout);
}

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

.visually-hidden-input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
}

/* ===== Edit resources modal =====
   One row per material already on the lesson, its Remove tickbox on the
   right. A ticked row strikes itself through so what the save is about to
   delete is obvious before the teacher commits to it. */
.resource-edit-list {
  display: flex;
  flex-direction: column;
  margin: 4px 0 8px;
}

.resource-edit-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 4px 12px;
  padding: 8px 0;
  border-bottom: 1px solid var(--color-border);
}

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

.resource-edit-title {
  overflow-wrap: anywhere;
}

.resource-remove {
  font-size: 13px;
  color: var(--color-danger);
  white-space: nowrap;
  cursor: pointer;
}

.resource-edit-row:has(input[name="remove[]"]:checked) .resource-edit-title {
  text-decoration: line-through;
  opacity: 0.55;
}

.resource-edit-row:has(input[name="remove[]"]:checked) .resource-remove {
  font-weight: 700;
}

/* The chosen mark colors its button: Present goes light green, Absent light
   red, so a glance down the day shows how it went. The buttons are disabled
   once chosen (the mark is made), but must not fade like an ordinary
   disabled button — the color IS the information. */
.attendance-btn.active[data-attended="1"] {
  background: var(--color-notes-bg);
  border-color: var(--color-notes-border);
  color: var(--color-notes-text);
}

.attendance-btn.active[data-attended="0"] {
  background: #fdeaea;
  border-color: #f0c4c0;
  color: #a33227;
}

.attendance-btn.active:disabled {
  opacity: 1;
  cursor: default;
}

/* Taking a present/absent mark back off — quieter than the two buttons it
   follows, since it undoes rather than answers. */
.attendance-unmark {
  color: var(--color-text-muted);
}

/* ===== BCM: dashboard cards ===== */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 16px;
  margin: 16px 0;
}

.card {
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 18px 20px;
  margin-bottom: 10px;
  box-shadow: var(--shadow-card);
}

.card h3 {
  margin: 0 0 8px;
}

.card .card-sub {
  color: var(--color-text-muted);
  font-size: 13px;
  margin-bottom: 8px;
}

/* Person chips (initials circle + name) */
.assignee {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.assignee-avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.unassigned {
  color: var(--color-text-muted);
}

/* ===== BCM: wizard step indicator ===== */

.wizard-steps {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin: 4px 0 22px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--color-border);
  font-size: 13px;
  color: var(--color-text-muted);
}

.wizard-step {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.wizard-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--color-surface-sunk);
  color: var(--color-text-muted);
  font-weight: 700;
  font-size: 12px;
}

.wizard-step.active {
  color: var(--color-navy);
  font-weight: 600;
}

.wizard-step.active .wizard-step-num {
  background: var(--color-primary);
  color: #fff;
}

.wizard-step.done .wizard-step-num {
  background: #dcf5e7;
  color: #0a6e3d;
}

/* Example CSV block on the import upload step */
.import-example {
  background: #f6f5f2;
  border: 1px solid var(--color-border);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 12px;
  overflow-x: auto;
  margin: 0 0 10px;
}

/* ===== Semester-wide date list (Admin > Calendar) ===== */
/* A month grid is mostly empty for a semester that meets once a week, so the
   dates are listed instead. The left rule carries the status: green = a class
   day, purple = a break or holiday. */
.sem-dates {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sem-date {
  border-left: 3px solid transparent;
  padding: 8px 0 8px 12px;
}

.sem-date + .sem-date {
  border-top: 1px solid var(--color-border);
}

.sem-date-active {
  border-left-color: var(--sem-date-active-line);
}

.sem-date-inactive {
  border-left-color: var(--sem-date-inactive-line);
  color: var(--color-text-muted);
}

.sem-date-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
}

.sem-date-time {
  margin-left: auto;
  font-size: 12px;
  color: var(--color-text-muted);
}

.sem-date-locations {
  font-size: 12px;
  color: var(--color-text-muted);
  margin-top: 2px;
  padding-left: 16px;
}

/* Which semester a row belongs to. Only rendered once the list spans more
   than one, so a date is never ambiguous. */
.sem-date-tag {
  font-size: 11px;
  color: var(--color-text-muted);
  background: var(--color-accent-soft);
  border-radius: 999px;
  padding: 1px 8px;
  white-space: nowrap;
}

/* "Showing lessons from: Fall 2026, Spring 2027" above the list. */
.timeline-note {
  margin: 0 0 8px;
  color: var(--color-text-muted);
}

/* A lesson the student didn't attend, on the personal calendars. */
.sem-date-missed .sem-date-head strong,
.sem-date-missed .sem-date-time {
  text-decoration: line-through;
  color: var(--color-text-muted);
}

/* A legend swatch shaped like the list's left rule. */
.swatch.swatch-line {
  width: 3px;
  border-radius: 2px;
}

.swatch-line.sem-date-active {
  background: var(--sem-date-active-line);
}

.swatch-line.sem-date-inactive {
  background: var(--sem-date-inactive-line);
}

/* List / Month view toggle on the admin calendar. */
.view-toggle .button.active {
  background: var(--color-primary);
  color: #fff;
  pointer-events: none;
}

/* Month view: every month of the semester at once, one per row. */
.cal-months {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  align-items: start;
}

.cal-month h3 {
  margin: 0 0 8px;
  text-align: center;
  font-size: 15px;
}

.cal-month-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}

.cal-dow {
  font-size: 11px;
  color: var(--color-text-muted);
  text-align: center;
}

.cal-day {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 64px;
  padding: 4px 3px;
  border-radius: 8px;
  font-size: 13px;
  color: var(--color-text-muted);
}

a.cal-day {
  color: #fff;
  font-weight: 600;
  text-decoration: none;
}

/* Title ("Week 1") and abbreviated locations inside a day cell. */
.cal-day-title,
.cal-day-locs {
  font-size: 10px;
  line-height: 1.25;
  text-align: center;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cal-day-title {
  font-weight: 400;
}

a.cal-day:hover,
a.cal-day:focus {
  filter: brightness(1.15);
  outline: 2px solid var(--color-primary);
  outline-offset: 1px;
}

.cal-day-active {
  background: var(--sem-date-active-line);
}

.cal-day-inactive {
  background: var(--sem-date-inactive-line);
}

/* ===== BCM: semester schedule grid ===== */

/* One stacked section per class day (Saturdays, then Tuesdays). */
.schedule-day + .schedule-day {
  margin-top: 28px;
}

.schedule-day-head {
  margin: 0 0 8px;
}

.schedule-scroll {
  overflow-x: auto;
  background: #fff;
  border: 1px solid var(--color-border);
  border-radius: 10px;
}

.schedule-grid {
  border-collapse: collapse;
  min-width: 100%;
}

.schedule-grid th,
.schedule-grid td {
  border: 1px solid var(--color-border);
  padding: 4px 6px;
  font-size: 12px;
}

.schedule-grid th.grid-loc {
  background: var(--color-navy);
  color: #fff;
  text-align: center;
  font-size: 13px;
}

.schedule-grid th.grid-teacher {
  background: #f0f4fa;
  color: var(--color-navy);
  min-width: 130px;
  text-align: center;
}

.schedule-grid th.grid-time {
  background: #f8f9fa;
  white-space: nowrap;
  font-weight: 600;
  text-align: right;
  width: 90px;
}

.grid-cell {
  height: 34px;
  cursor: pointer;
  vertical-align: top;
}

.grid-cell:hover {
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}

.grid-cell .cell-student {
  font-weight: 600;
  display: block;
}

.grid-cell .cell-status {
  font-size: 10px;
  color: var(--color-text-muted);
}

/* Reservation states (docs/app_spec.md color coding) */
.grid-cell.res-reach-out {
  background: #fff;
  color: var(--color-text-muted);
  font-style: italic;
}

.grid-cell.res-pending {
  background: #fff;
}

.grid-cell.res-paid {
  background: var(--res-paid-bg);
}

.grid-cell.res-balance-full {
  background: var(--res-balance-full-bg);
}

.grid-cell.res-balance-half {
  background: var(--res-balance-half-bg);
}

.grid-cell.res-balance-custom {
  background: var(--res-balance-custom-bg);
  color: #fff;
}

.grid-cell.res-balance-custom .cell-status {
  color: #cfe0f5;
}

/* One commitment inside a cell. A lone item is transparent so its <td>
   supplies the colour exactly as before; when a cell holds several, each
   item carries its own res-* background and they stack, growing the row. */
.cell-item {
  display: block;
  cursor: pointer;
}

.grid-cell.res-multi {
  background: repeating-linear-gradient(
    -45deg, #fdecec 0 6px, #fff5f5 6px 12px
  );
  padding: 2px;
}

.grid-cell.res-multi .cell-item {
  border-radius: 4px;
  padding: 2px 4px;
  margin-bottom: 2px;
}

.grid-cell.res-multi .cell-item:last-child {
  margin-bottom: 0;
}

/* Colours for stacked items mirror the single-cell states. */
.cell-item.res-reach-out { background: #fff; font-style: italic; }
.cell-item.res-pending { background: #fff; }
.cell-item.res-paid { background: var(--res-paid-bg); }
.cell-item.res-balance-full { background: var(--res-balance-full-bg); }
.cell-item.res-balance-half { background: var(--res-balance-half-bg); }
.cell-item.res-balance-custom { background: var(--res-balance-custom-bg); color: #fff; }
.cell-item.res-hold { background: var(--res-hold-bg); color: var(--color-text-muted); }
.cell-item.res-class-ensemble { background: var(--res-class-ensemble-bg); }
.cell-item.res-class-musicianship { background: var(--res-class-musicianship-bg); }

/* Hold blocks: the teacher's own time, no student, deliberately drab so it
   reads as "not bookable" rather than as another reservation state. */
.grid-cell.res-hold {
  background: var(--res-hold-bg);
  background-image: repeating-linear-gradient(
    -45deg, rgba(0, 0, 0, 0.04) 0 6px, transparent 6px 12px
  );
  color: var(--color-text-muted);
}

/* Paid group classes held in a slot (Guitar Ensemble, Musicianship Skills):
   their own colors, without the hold's drab hatching — this is teaching
   time, not the teacher's own. */
.grid-cell.res-class-ensemble { background: var(--res-class-ensemble-bg); }
.grid-cell.res-class-musicianship { background: var(--res-class-musicianship-bg); }

/* Condensed mode: narrower columns, short names, status by color only */
.schedule-grid.compact th,
.schedule-grid.compact td {
  padding: 2px 4px;
  font-size: 11px;
}

.schedule-grid.compact th.grid-teacher {
  min-width: 92px;
}

.schedule-grid.compact th.grid-time {
  width: 72px;
}

.schedule-grid.compact .cell-status {
  display: none;
}

.schedule-grid.compact .grid-cell {
  height: 28px;
}

/* Columns hidden by the pager */
.col-hidden {
  display: none;
}

/* The column pager above the grid (only shown when paging is needed) */
.schedule-pager {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 8px;
  flex-wrap: wrap;
}

.schedule-pager select {
  width: auto;
  flex: 1;
  min-width: 160px;
  max-width: 340px;
}

.schedule-pager-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--color-navy);
}

.grid-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  margin: 10px 0;
  font-size: 12px;
  align-items: center;
}

.grid-legend .swatch {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 4px;
  border: 1px solid var(--color-border);
  vertical-align: -2px;
  margin-right: 4px;
}

/* Simple responsive form grids (admin forms) */
.grid-2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 8px 16px;
}

.grid-3 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px 16px;
}

/* Read-only label/value pairs (My Profile) */
.detail-grid {
  display: grid;
  grid-template-columns: minmax(120px, 180px) 1fr;
  gap: 4px 16px;
  margin: 0 0 16px;
}

.detail-grid dt {
  color: var(--color-text-muted);
  font-size: 14px;
}

.detail-grid dd {
  margin: 0;
  overflow-wrap: anywhere;
}

.detail-grid dd.detail-empty {
  color: var(--color-text-muted);
}

/* ===== Lead status pills (Admin > Leads) ===== */

.status-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.lead-new { background: #fdecd3; color: #8a5a00; }
.lead-contacted { background: #e8effa; color: #2b5ea0; }
.lead-scheduled { background: #ece3f7; color: #5b3a8a; }
.lead-converted { background: #dcf5e7; color: #0a6e3d; }
.lead-declined { background: #eceae7; color: #6b6660; }

.lead-paid-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  background: #dcf5e7;
  color: #0a6e3d;
  white-space: nowrap;
}

/* The "+" separators between tuition and fee lines on the registration form */
.tuition-plus {
  margin: 6px 0;
  font-weight: 700;
  color: var(--color-text-muted);
}

/* The question a group of radios/checkboxes answers. Sits just under the
   section heading and reads as the prompt — .small (12px, muted) is for
   footnotes and caveats, not for something the user has to answer. */
.form-question {
  font-size: 17px;
  font-weight: 600;
  color: var(--color-navy);
  margin: 0 0 8px;
}

/* Checkbox/radio options one per line, for option sets whose labels are long
   enough that a wrapping row (.choice-grid) reads as a jumble. */
.choice-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* The asterisk marking a required field. */
.required {
  color: var(--color-danger);
  font-weight: 700;
}

/* A full sentence of instructions inside a <label>. Labels are 500-weight,
   which reads as bold once the text is longer than a field name — the
   selector is scoped to `label` so it outranks that rule for certain. Block
   + margin lifts the prose clear of the field it introduces instead of
   letting the two sit flush together. */
label .label-prose {
  display: block;
  font-weight: 400;
  margin-bottom: 8px;
}

/* A caveat riding along inside a question — smaller and muted (from .small),
   but not carrying the question's bold weight. */
.form-question .small {
  font-weight: 400;
}

/* ===== Registration checkout (step 6) ===== */

.checkout-table .checkout-total td {
  border-top: 2px solid var(--color-border);
}

/* "Secure" reassurance beside the Billing Information heading. */
.secure-badge {
  font-size: 12px;
  font-weight: 600;
  color: #0a6e3d;
  background: #dcf5e7;
  border-radius: 999px;
  padding: 3px 10px;
  margin-left: 8px;
  white-space: nowrap;
  vertical-align: middle;
}

/* Stripe Elements mount points — give the iframes room to breathe. */
#payment-element,
#address-element {
  margin: 6px 0 4px;
}

/* Options set in from the question they answer, so the choices read as a
   group belonging to it rather than as more body copy. */
.choice-indent {
  padding-left: 22px;
}

/* ===== Slot picker (lead conversion) =====
   The semester schedule shown inside a modal so an admin can see a teacher's
   week before choosing a time. Free cells invite a click; busy ones are
   visible but deliberately inert — seeing what is already there is the point. */
.modal-content.wide {
  max-width: min(1200px, 96vw);
}

.grid-cell.pickable {
  cursor: pointer;
}

.grid-cell.pickable:hover {
  background: var(--res-paid-bg);
}

.grid-cell.res-busy {
  background: var(--res-hold-bg);
  color: var(--color-text-muted);
  cursor: default;
}


/* ===== Schedule edit mode =====
   Off by default, so reading the schedule can never move anybody's lesson.
   Turned on, the boxes pick up a grab cursor and the empty cells light up as
   you drag over them. */
.edit-mode-bar {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-wrap: wrap;
  margin: 10px 0;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--res-balance-full-bg);
}

.schedule-edit-mode td.grid-cell[draggable="true"] {
  cursor: grab;
}

.schedule-edit-mode .cell-item[draggable="true"] {
  cursor: grab;
}

.schedule-edit-mode .cell-item.dragging {
  opacity: 0.4;
  cursor: grabbing;
}

/* Held while the server decides, so a refused move never looks like it worked. */
.schedule-edit-mode .cell-item.saving {
  opacity: 0.5;
  pointer-events: none;
}

.grid-cell.drop-target {
  outline: 2px dashed var(--color-primary, #0062DC);
  outline-offset: -2px;
  background: var(--res-paid-bg);
}

/* A week somebody else is covering. */
.grid-cell.res-substitute,
.cell-item.res-substitute {
  background: var(--res-substitute-bg);
}

/* A cancelled lesson on a family's or teacher's list: still there, plainly off. */
.sem-date-cancelled .sem-date-head strong,
.sem-date-cancelled .sem-date-time {
  text-decoration: line-through;
  color: var(--color-text-muted);
}
