@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,600;0,700;1,400&family=Jost:wght@300;400;500;600;700;800&family=Inter:wght@400;500;600;700;800&display=swap');

/* ─── Reset ─────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* overflow-x: clip (not hidden) — hidden with overflow-y unset forces
   overflow-y to compute as auto, turning body into an accidental scroll
   container that breaks position:sticky on its children (navbar, tab
   bars, etc.), since html — not body — is the element that actually
   scrolls. clip has no such pairing quirk. */
html, body { max-width: 100%; overflow-x: clip; }
/* Always reserve space for the vertical scrollbar, whether or not the
   current page actually needs one — without this, switching from a short
   page (no scrollbar) to a tall one (has a scrollbar) shifts all content,
   including the navbar, sideways by the scrollbar's width. That's the
   navbar "moving left" between tabs. */
html { scrollbar-gutter: stable; overflow-y: scroll; }


/* ─── Design Tokens ─────────────────────────────────────────────────────────── */
:root {
  /* Brand */
  --primary:       #c47c05;
  --primary-dark:  #9a6004;
  --primary-light: #fef5e0;
  --primary-muted: #f4c560;
  /* Text sitting directly on a var(--primary) fill -- live default (today's
     exact value), recomputed per-palette by applyAppearancePalette() via
     accentTextFor() so a light-accent preset doesn't end up with invisible
     white-on-near-white text. */
  --on-primary:    #E6DDC6;

  /* Semantic */
  --success:       #059669;
  --success-light: #d1fae5;
  --danger:        #dc2626;
  --danger-light:  #fee2e2;
  --warning:       #d97706;
  --warning-light: #fef3c7;
  --secondary:     #d97706;

  /* Neutral */
  --text:          #0f172a;
  --text-muted:    #7a5018;
  --text-subtle:   #a0722a;
  --border:        #e2e8f0;
  --bg:            #f8fafc;
  --bg-hover:      #f1f5f9;
  --white:         #ffffff;
  --card-bg:       #ffffff;

  /* Nav */
  --nav-bg:        #0f172a;
  --nav-h:         60px;

  /* Table/grid column headers -- their own tokens (not hardcoded to --bg/
     --text-subtle) so Academy Profile > Appearance can recolor just the
     header strip independently of the page background. Default value is a
     live reference to --bg/--text-subtle (var() resolves lazily at use
     time), so a academy that never opens Appearance sees today's exact
     look, light or dark, with zero extra CSS needed. */
  --th-bg:         var(--bg);
  --th-text:       var(--text-subtle);

  /* Decorative page-background glows (body{}, below) -- same "live default,
     JS overrides on demand" pattern as --th-bg/--th-text above. Values here
     are today's exact hardcoded blob colors so nothing changes until a
     academy actually opens Appearance; applyAppearancePalette() (utils.js)
     then recomputes these from the chosen palette's own primary/pageBg so
     the background visibly follows the pick instead of staying fixed. */
  --bg-glow-1: rgba(196,124,5,.28);
  --bg-glow-2: rgba(43,122,117,.22);
  --bg-tint:   rgba(248,250,252,.5);

  /* Scrollbars */
  --scrollbar-track: rgba(196,124,5,.08);
  --scrollbar-thumb:       var(--primary-muted);
  --scrollbar-thumb-hover: var(--primary);

  /* Radii */
  --radius:        10px;
  --radius-sm:     6px;
  --radius-lg:     16px;
  --radius-pill:   999px;

  /* Shadows */
  --shadow-sm:  0 1px 2px rgba(0,0,0,.05);
  --shadow:     0 1px 3px rgba(0,0,0,.08), 0 1px 2px rgba(0,0,0,.06);
  --shadow-md:  0 4px 12px rgba(0,0,0,.08), 0 2px 4px rgba(0,0,0,.05);
  --shadow-lg:  0 12px 40px rgba(0,0,0,.12), 0 4px 12px rgba(0,0,0,.08);

  --transition: 180ms ease;
}

/* Full dark-token set, app-wide (not page-scoped like the earlier pilot) —
   most components (inputs, .stat-card, buttons, badges) already reference
   these variables rather than hardcoded colors, so they adapt automatically.
   Only a couple of components below (.card, .table-wrap) hardcode a "light
   glass" look regardless of theme and need explicit dark overrides too. */
:root[data-theme="dark"] {
  --primary:       #e0a020;
  --primary-dark:  #c47c05;
  --primary-light: rgba(224,160,32,.14);
  --primary-muted: #f4c560;
  --on-primary:    #E6DDC6;
  --success-light: rgba(5,150,105,.18);
  --danger-light:  rgba(220,38,38,.18);
  --warning-light: rgba(217,119,6,.18);
  --text:          #E6DDC6;
  --text-muted:    #b9a483;
  --text-subtle:   #8f7c5c;
  --border:        rgba(255,255,255,.1);
  --bg:            #14110c;
  --bg-hover:      #1c1811;
  --white:         #1a160f;
  --card-bg:       #1a160f;
  --bg-glow-1: rgba(224,160,32,.28);
  --bg-glow-2: rgba(43,122,117,.11);
  --bg-glow-3: rgba(220,20,60,.11);
  --bg-base:   #0d0b08;
  --shadow-sm:  0 1px 2px rgba(0,0,0,.3);
  --shadow:     0 1px 3px rgba(0,0,0,.35), 0 1px 2px rgba(0,0,0,.3);
  --shadow-md:  0 4px 12px rgba(0,0,0,.35), 0 2px 4px rgba(0,0,0,.3);
  --shadow-lg:  0 12px 40px rgba(0,0,0,.45), 0 4px 12px rgba(0,0,0,.35);

  /* Dark bg needs a lighter (not darker) track to read as a track at all;
     the thumb drops to primary-dark since primary/-muted are too close in
     value to the lighter track to show contrast here. */
  --scrollbar-track: rgba(255,255,255,.07);
  --scrollbar-thumb:       var(--primary-dark);
  --scrollbar-thumb-hover: var(--primary);
}

/* ─── Scrollbars ─────────────────────────────────────────────────────────────── */
/* Thin, on-brand scrollbars everywhere (page scroll, tables, filter strips,
   modals, roster grids, …) instead of each OS's default chrome. Firefox via
   scrollbar-width/-color, everyone else via ::-webkit-scrollbar*. The
   transparent border + background-clip:padding-box trick insets the thumb
   inside the track so it reads as a slim floating pill, not a bar that
   fills the full gutter. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track);
}
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: var(--scrollbar-track); border-radius: var(--radius-pill); }
*::-webkit-scrollbar-thumb {
  background-color: var(--scrollbar-thumb);
  border-radius: var(--radius-pill);
  border: 2px solid transparent;
  background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover { background-color: var(--scrollbar-thumb-hover); }
*::-webkit-scrollbar-corner { background: transparent; }

/* ─── Base ───────────────────────────────────────────────────────────────────── */
/* Background is two soft color glows painted directly as part of body's own
   `background` property — deliberately NOT pseudo-elements this time. A
   pseudo-element's visibility depends on z-index/stacking-context rules that
   went wrong twice in a row here; a plain background layer has no such
   failure mode; it is always painted, always behind body's children, no
   stacking context required. background-attachment:fixed keeps it visible
   while scrolling on long pages — the earlier concern about `fixed` was
   about a large bitmap photo specifically, not a cheap computed gradient
   like this one, so that tradeoff doesn't apply here.

   Light theme only, the two glows also slowly drift (bgDrift below) so the
   page doesn't sit dead still — the photo and flat tint layers stay put
   (animating those too would look janky on a full-viewport fixed image, and
   nobody's eye is on the corners anyway). That's why this is split into
   separate background-image/-position/-size properties instead of the
   single `background` shorthand: a shorthand bakes each layer's position
   into its own radial-gradient()/url() term, which isn't animatable, but
   background-position accepts one value per layer and can be keyframed. */
body {
  font-family: 'Jost', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background-image:
    radial-gradient(circle at center, var(--bg-glow-1), transparent 60%),
    radial-gradient(circle at center, var(--bg-glow-2), transparent 60%),
    linear-gradient(var(--bg-tint), var(--bg-tint));
  background-position: 100% 0%, 0% 100%, center;
  background-size: auto, auto, auto;
  background-color: var(--bg);
  background-repeat: no-repeat;
  background-attachment: fixed;
  animation: bgDrift 16s ease-in-out infinite alternate;
  color: var(--text);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
}
@keyframes bgDrift {
  0%   { background-position: 100% 0%, 0% 100%, center; }
  100% { background-position: 65% 35%, 35% 65%, center; }
}
@media (prefers-reduced-motion: reduce) {
  body { animation: none; }
}
/* The bottom-left glow used to be all teal-green at .22 opacity -- now split
   into two layered glows at the same spot, teal and crimson each at half
   that opacity, so the corner reads as a green/crimson blend instead of
   solid green. Top-right amber glow is untouched. */
:root[data-theme="dark"] body {
  background:
    radial-gradient(circle at 96% 2%, var(--bg-glow-1), transparent 45%),
    radial-gradient(circle at 2% 96%, var(--bg-glow-2), transparent 45%),
    radial-gradient(circle at 2% 96%, var(--bg-glow-3), transparent 45%),
    var(--bg-base);
  background-repeat: no-repeat;
  background-attachment: fixed;
  animation: none;
}

/* ─── Navbar ─────────────────────────────────────────────────────────────────── */
.navbar {
  background: #0f172a;
  height: var(--nav-h);
  padding: 0 1.5rem;
  display: flex;
  align-items: center;
  position: sticky;
  top: 0;
  z-index: 200;
  box-shadow: 0 1px 0 rgba(255,255,255,.07), var(--shadow-md);
  gap: 1rem;
}

/* Shows by default (the wheel favicon, sized/bordered per-page) - a real
   logo, not blank text-only. applyBranding() swaps the src to the academy's
   own uploaded logo when one exists (utils.js). */
.nav-logo-img { display: block; }

.navbar-brand {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: 1.05rem;
  font-weight: 700;
  color: #E6DDC6;
  text-decoration: none;
  letter-spacing: -.01em;
  flex-shrink: 1;
  /* Not 0 -- the logo img next to this text has flex-shrink:0 (its own
     fixed 34px size never shrinks), but this container's own overflow:
     hidden crops it visually once the container gets squeezed below that,
     which is exactly what a long translated nav-link row does in Tamil.
     A floor here means the "Learn" text gives up space first instead. */
  min-width: 40px;
  max-width: 38%;
  overflow: hidden;
}

.navbar-brand-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.navbar-links {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: .15rem;
  list-style: none;
  margin-left: .5rem;
  flex: 1;
}

.navbar-links li { display: contents; }

.navbar-links a {
  color: rgba(255,255,255,.7);
  text-decoration: none;
  padding: .38rem .72rem;
  border-radius: var(--radius-sm);
  font-size: .85rem;
  font-weight: 500;
  transition: background var(--transition), color var(--transition);
  white-space: nowrap;
}

.navbar-links a:hover        { background: rgba(255,255,255,.1);  color: #E6DDC6; }
.navbar-links a.active       {
  background: rgba(255,255,255,.15); color: #E6DDC6; font-weight: 600;
  box-shadow: inset 0 -2px 0 0 var(--primary);
}
.navbar-links a.nav-logout   { color: rgba(255,255,255,.5); margin-left: auto; }   /* tabs start at the left; only Logout (and the theme toggle after it) sit at the right */
.navbar-links a.nav-logout:hover { background: rgba(220,38,38,.25); color: #fca5a5; }

/* Dark/light toggle — lives in the navbar, deliberately the last element so
   it sits at the extreme right regardless of how many nav links a page has. */
.theme-toggle {
  width: 32px; height: 32px; border-radius: 50%; border: 1.5px solid rgba(255,255,255,.18);
  background: transparent; display: flex; align-items: center; justify-content: center;
  cursor: pointer; color: rgba(255,255,255,.65); transition: background .2s ease, color .2s ease;
  flex-shrink: 0; margin-left: .5rem;
}
.theme-toggle:hover { background: rgba(255,255,255,.1); color: var(--primary-muted); }
.theme-toggle svg { width: 16px; height: 16px; }
.theme-toggle .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }

/* Language switcher — same icon-button treatment as .theme-toggle, sits
   right next to it. font-family here (not globally) since the dropdown is
   the one place multiple Indic scripts render side by side; system fonts on
   Android/iOS/Windows/Mac all ship Devanagari/Tamil/Telugu/Kannada/
   Gurmukhi/Gujarati/Bengali coverage already, so no webfont needed. */
.lang-switch { position: relative; margin-left: .5rem; }
/* Groups the theme toggle + language switcher into one row instead of two
   stacked nav items -- matters most in the mobile hamburger sidebar, where
   .navbar-links li becomes a full-width block and these two small icon
   buttons would otherwise each eat a whole row of their own. */
.nav-utility-row { display: flex; align-items: center; gap: .5rem; }
.lang-switch-btn { margin-left: 0; font-weight: 700; font-size: .8rem; }
.lang-switch-dropdown {
  display: none; position: absolute; top: calc(100% + 6px); right: 0; z-index: 300;
  background: var(--white); border: 1.5px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); padding: .4rem; min-width: 150px;
  font-family: "Noto Sans", "Noto Sans Devanagari", "Noto Sans Tamil", "Noto Sans Telugu",
    "Noto Sans Kannada", "Noto Sans Gurmukhi", "Noto Sans Gujarati", "Noto Sans Bengali", sans-serif;
}
.lang-switch-dropdown.open { display: block; }
.lang-option {
  display: block; width: 100%; text-align: left; padding: .5rem .65rem; font-size: .88rem;
  background: none; border: none; border-radius: var(--radius-sm); color: var(--text);
  cursor: pointer; transition: background .12s;
}

/* Non-English compact-UI trim -- Tamil/Bengali/Gujarati/Kannada/Punjabi/
   Telugu especially run visibly longer than the English source string for
   the same short label (button text, badge, nav item, table header), and
   every one of those was sized/nowrap-tuned against English string lengths
   only. A small across-the-board reduction on just the tight, single-line
   UI chrome (never body copy/paragraphs, which can wrap freely) buys enough
   room that translated labels fit instead of clipping or forcing an
   unwanted line-wrap inside a pill-shaped button. html[lang] is set by
   i18n.js's initI18n() on every page once a language is chosen. */
html:not([lang="en"]) .btn,
html:not([lang="en"]) .badge,
html:not([lang="en"]) .navbar-links a,
html:not([lang="en"]) .lp-nav .actions .btn,
html:not([lang="en"]) .tab-btn,
html:not([lang="en"]) .chart-toggle-btn,
html:not([lang="en"]) .status-pill,
html:not([lang="en"]) .mp-month,
html:not([lang="en"]) th,
html:not([lang="en"]) .stat-label,
html:not([lang="en"]) .dcr-label,
html:not([lang="en"]) .data-card-meta {
  font-size: .9em;
}
/* Tamil's conjunct/ligature-heavy script still ran noticeably wider than
   the other seven languages even after the .9em trim above -- same selector
   list, one step smaller. Placed right after so equal-specificity + source
   order lets this win over the general rule for Tamil specifically. */
html[lang="ta"] .btn,
html[lang="ta"] .badge,
html[lang="ta"] .navbar-links a,
html[lang="ta"] .lp-nav .actions .btn,
html[lang="ta"] .tab-btn,
html[lang="ta"] .chart-toggle-btn,
html[lang="ta"] .status-pill,
html[lang="ta"] .mp-month,
html[lang="ta"] th,
html[lang="ta"] .stat-label,
html[lang="ta"] .dcr-label,
html[lang="ta"] .data-card-meta {
  font-size: .82em;
}
/* Nav links specifically need to go smaller still -- a full row of Tamil
   labels at .82em was still wide enough to squeeze the logo (see
   .navbar-brand's min-width comment) out of the space it needs. */
html[lang="ta"] .navbar-links a {
  font-size: .7em;
}
.lang-option:hover { background: var(--primary-light); color: var(--primary); }
.lang-option.active { background: var(--primary); color: var(--on-primary); font-weight: 700; }
:root[data-theme="dark"] .lang-switch-dropdown { background: #1a1108; border-color: rgba(255,255,255,.14); }

/* Hamburger button */
.nav-hamburger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  margin-left: auto;
  padding: .5rem;
  background: none;
  border: 1px solid rgba(255,255,255,.15);
  border-radius: var(--radius-sm);
  cursor: pointer;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  transition: border-color var(--transition);
}
.nav-hamburger:hover { border-color: rgba(255,255,255,.35); }
.nav-hamburger span {
  display: block;
  width: 18px;
  height: 2px;
  background: rgba(255,255,255,.85);
  border-radius: 2px;
  margin: 0 auto;
  transition: transform var(--transition), opacity var(--transition);
}

/* Mobile overlay */
.nav-overlay {
  display: none;
  position: fixed;
  inset: var(--nav-h) 0 0 0;
  background: rgba(0,0,0,.45);
  z-index: 190;
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

@media (max-width: 768px) {
  .nav-hamburger { display: flex; }

  .navbar-links {
    position: fixed;
    top: var(--nav-h);
    right: 0;
    bottom: 0;
    width: min(270px, 82vw);
    flex-direction: column;
    align-items: stretch;
    /* Desktop's justify-content:flex-end (right-aligns a single row) is
       still in effect here otherwise -- in a *column* flex container that
       packs overflowing content against the BOTTOM instead of the top, so
       once there are enough tabs to overflow the tray, the top items render
       above the visible box (negative offset) and are permanently
       unreachable: scrollHeight itself comes out equal to clientHeight,
       i.e. no scroller at all, not just a hidden one. */
    justify-content: flex-start;
    gap: .2rem;
    margin: 0;
    padding: 1rem .75rem 1.5rem;
    background: var(--nav-bg);
    border-left: 1px solid rgba(255,255,255,.08);
    transform: translateX(100%);
    transition: transform .28s cubic-bezier(.4,0,.2,1);
    overflow-y: auto;
    /* app.html renders this <ul> with only its 2 hardcoded items (Logout,
       theme/lang row) first, then inserts all the real route links
       (Dashboard, Students, ...) at the very TOP once the signed-in role
       is known (renderNavLinks()'s insertAdjacentHTML('afterbegin', ...)).
       Chrome's default scroll anchoring reacts to content appearing above
       an already-visible node by silently bumping scrollTop to keep that
       node pinned in place -- which shoves the newly-inserted top links
       out of view the instant they're added, well before the user has
       scrolled anything themselves. Not a "preserve reading position"
       case worth keeping; this is a one-time mount-time fill-in, so
       anchoring here only ever hides content. */
    overflow-anchor: none;
    z-index: 200;
  }

  .navbar-links li { display: block; }
  .navbar-links a  { display: block; padding: .75rem 1rem; border-radius: var(--radius); font-size: .9rem; }
  .navbar-links a.nav-logout { margin-left: 0; margin-top: .5rem; }
  .navbar-links .nav-utility-row { padding: .5rem 1rem; }

  .navbar.open .navbar-links          { transform: translateX(0); }
  .navbar.open .nav-overlay           { display: block; }
  .navbar.open .nav-hamburger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .navbar.open .nav-hamburger span:nth-child(2) { opacity: 0; transform: scaleX(0); }
  .navbar.open .nav-hamburger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
}

/* ─── Layout ─────────────────────────────────────────────────────────────────── */
.page-container {
  max-width: 1100px;
  margin: 1.75rem auto;
  padding: 0 1.25rem;
  min-width: 0;
}

h1, h2, h3, h4, h5, h6,
.page-title, .card-title, .navbar-brand, .stat-value, .data-card-title {
  font-family: 'Cormorant Garamond', serif;
}

.page-title {
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: -.02em;
  margin-bottom: 1.25rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  flex-wrap: wrap;
}
.page-title-actions { display: flex; gap: .5rem; flex-wrap: wrap; }

/* ─── Cards ──────────────────────────────────────────────────────────────────── */
.card {
  background: rgba(255,255,255,.45);
  border-radius: var(--radius-lg);
  border: 2px solid var(--border);
  box-shadow:
    inset 0 1px 0 rgba(255,220,120,.55),
    inset 1px 0 0 rgba(255,210,100,.3),
    inset 0 -1px 0 rgba(100,55,5,.14),
    inset -1px 0 0 rgba(100,55,5,.1),
    0 0 0 1px rgba(196,124,5,.06),
    0 0 20px -4px rgba(196,124,5,.28),
    0 6px 16px rgba(100,55,5,.14);
  padding: 1.35rem 1.5rem;
  margin-bottom: 1rem;
}
:root[data-theme="dark"] .card {
  background: rgba(255,255,255,.035);
  border-color: rgba(255,255,255,.08);
  box-shadow: 0 1px 2px rgba(0,0,0,.3);
}

.card-title {
  font-size: .95rem;
  font-weight: 700;
  letter-spacing: -.01em;
  margin-bottom: 1rem;
  padding-bottom: .6rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: .5rem;
}

/* ─── Stat Cards ─────────────────────────────────────────────────────────────── */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(175px, 1fr));
  gap: 1rem;
  margin-bottom: 1.25rem;
}

.stat-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  border: 1px solid var(--border);
  padding: 1.1rem 1.25rem;
  position: relative;
  overflow: hidden;
  transition: box-shadow var(--transition), transform var(--transition);
}

.stat-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}

.stat-card.primary::before   { background: var(--primary); }
.stat-card.success::before   { background: var(--success); }
.stat-card.warning::before   { background: var(--warning); }
.stat-card.danger::before    { background: var(--danger); }

/* Keep left-border for backward compat */
.stat-card.primary   { border-left: 4px solid var(--primary); }
.stat-card.success   { border-left: 4px solid var(--success); }
.stat-card.warning   { border-left: 4px solid var(--warning); }
.stat-card.danger    { border-left: 4px solid var(--danger); }

.stat-label { font-size: .72rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .06em; font-weight: 600; }
.stat-value { font-size: 1.65rem; font-weight: 800; margin-top: .2rem; letter-spacing: -.02em; line-height: 1.2; }
.stat-sub   { font-size: .78rem; color: var(--text-muted); margin-top: .25rem; }

/* Dashboard metric cards */
.metric-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  padding: 1.15rem 1.35rem;
  display: flex;
  flex-direction: column;
  gap: .2rem;
  transition: box-shadow var(--transition);
}
.metric-card:hover { box-shadow: var(--shadow-md); }
.metric-card .m-label  { font-size: .72rem; color: var(--text-muted); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }
.metric-card .m-value  { font-size: 1.6rem; font-weight: 800; letter-spacing: -.025em; line-height: 1.2; margin-top: .15rem; }
.metric-card .m-prev   { font-size: .78rem; color: var(--text-muted); }
.metric-card .m-change { font-size: .9rem; font-weight: 700; margin-top: .1rem; display: flex; align-items: center; gap: .25rem; }
.m-change.up   { color: var(--success); }
.m-change.down { color: var(--danger); }
.m-change.flat { color: var(--text-subtle); }

.fin-primary { border-left: 4px solid var(--primary); }
.fin-prev    { border-left: 4px solid var(--primary-muted); }
.ops-enroll  { border-left: 4px solid #6366f1; }
.ops-instr   { border-left: 4px solid #0891b2; }
.ops-att     { border-left: 4px solid #7c3aed; }

/* Dashboard section titles */
.section-title {
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-subtle);
  margin: 1.75rem 0 .75rem;
  display: flex;
  align-items: center;
  gap: .75rem;
}
.section-title::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--border);
}

/* ─── Bar Chart ──────────────────────────────────────────────────────────────── */
.chart-wrap {
  background: rgba(255,255,255,.45);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  box-shadow:
    inset 0 1px 0 rgba(255,220,120,.55),
    inset 1px 0 0 rgba(255,210,100,.3),
    inset 0 -1px 0 rgba(100,55,5,.14),
    inset -1px 0 0 rgba(100,55,5,.1),
    0 2px 8px rgba(100,55,5,.08);
  padding: 1.35rem 1.5rem;
  margin-bottom: 1rem;
}
.chart-title { font-size: .95rem; font-weight: 700; margin-bottom: 1.1rem; letter-spacing: -.01em; }
.bar-chart {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: 140px;
  border-bottom: 2px solid var(--border);
  overflow-x: auto;
  padding-bottom: 4px;
  scrollbar-width: thin;
}
.bar-group { display: flex; flex-direction: column; align-items: center; gap: 4px; flex: 1; min-width: 48px; }
.bars      { display: flex; align-items: flex-end; gap: 3px; height: 120px; }
.bar {
  width: 18px;
  border-radius: 4px 4px 0 0;
  min-height: 4px;
  transition: height .4s cubic-bezier(.4,0,.2,1);
}
.bar.current  { background: var(--primary); }
.bar.previous { background: var(--primary-muted); }
.bar-lbl { font-size: .68rem; color: var(--text-subtle); text-align: center; white-space: nowrap; }
.chart-legend { display: flex; gap: 1rem; margin-top: .85rem; font-size: .8rem; color: var(--text-muted); }
.legend-dot { width: 10px; height: 10px; border-radius: 3px; display: inline-block; margin-right: 4px; vertical-align: middle; }

/* ─── Tables ─────────────────────────────────────────────────────────────────── */
.table-wrap {
  overflow-x: auto;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: rgba(255,255,255,.45);
  box-shadow:
    inset 0 1px 0 rgba(255,220,120,.55),
    inset 1px 0 0 rgba(255,210,100,.3),
    inset 0 -1px 0 rgba(100,55,5,.14),
    inset -1px 0 0 rgba(100,55,5,.1),
    0 2px 8px rgba(100,55,5,.08);
}
:root[data-theme="dark"] .table-wrap {
  background: rgba(255,255,255,.025);
  border-color: rgba(255,255,255,.08);
  box-shadow: 0 1px 2px rgba(0,0,0,.3);
}
table { width: 100%; border-collapse: collapse; background: transparent; }
thead th {
  text-align: left;
  padding: .65rem 1rem;
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  font-weight: 700;
  color: var(--th-text);
  background: var(--th-bg);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
td {
  padding: .8rem 1rem;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  font-size: .9rem;
}
tr:last-child td    { border-bottom: none; }
tbody tr:nth-child(even) td { background: rgba(15,23,42,.025); }
tbody tr:hover td   { background: rgba(196,124,5,.07); }
:root[data-theme="dark"] tbody tr:nth-child(even) td { background: rgba(255,255,255,.03); }
:root[data-theme="dark"] tbody tr:hover td { background: rgba(224,160,32,.09); }
.td-muted   { color: var(--text-muted); font-size: .85rem; }
.td-amount  { font-variant-numeric: tabular-nums; font-weight: 600; font-size: .9rem; text-align: right; }
th.th-amount { text-align: right; }

/* ─── Buttons ────────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: .5rem 1rem;
  border-radius: var(--radius-sm);
  border: none;
  cursor: pointer;
  font-family: inherit;
  font-size: .875rem;
  font-weight: 500;
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  letter-spacing: -.005em;
  transition: transform 180ms ease, box-shadow 180ms ease, background 180ms ease, filter 180ms ease;
  will-change: transform, box-shadow;
}

.btn:hover  { transform: translateY(-2px); }
.btn:active { transform: translateY(1px) scale(.96); filter: brightness(.9); transition: transform 80ms ease, filter 80ms ease; }
.btn:disabled { opacity: .45; cursor: not-allowed; pointer-events: none; transform: none !important; }

/* Primary → black */
.btn-primary {
  background: #0f172a;
  color: #f1f5f9;
  box-shadow: 0 2px 6px rgba(0,0,0,.35), 0 1px 2px rgba(0,0,0,.2);
}
.btn-primary:hover {
  background: #1e293b;
  box-shadow: 0 8px 24px rgba(0,0,0,.45), 0 3px 8px rgba(0,0,0,.25);
}
/* Its near-black fill is nearly the same tone as the dark theme's card
   background — same camouflage problem .btn-outline had, same amber-glow fix. */
:root[data-theme="dark"] .btn-primary {
  box-shadow: 0 0 0 1px rgba(224,160,32,.3), 0 0 16px -2px var(--primary), 0 2px 6px rgba(0,0,0,.35);
}
:root[data-theme="dark"] .btn-primary:hover {
  box-shadow: 0 0 0 1px rgba(224,160,32,.45), 0 0 26px -2px var(--primary), 0 3px 8px rgba(0,0,0,.25);
}

/* Success → stays green (semantic) */
.btn-success {
  background: var(--success);
  color: #E6DDC6;
  box-shadow: 0 2px 6px rgba(5,150,105,.3), 0 1px 2px rgba(0,0,0,.15);
}
.btn-success:hover {
  box-shadow: 0 8px 22px rgba(5,150,105,.4), 0 3px 8px rgba(0,0,0,.15);
}

/* Extra-emphasis variant (e.g. Record Payment) — same darkest-green fill +
   off-white text as .badge-success/.alert-success/.toast-success, not a
   separate shade. */
.btn-success-dark {
  background: #133000;
  color: #E6DDC6;
  box-shadow: 0 2px 6px rgba(5,150,105,.3), 0 1px 2px rgba(0,0,0,.15);
}
.btn-success-dark:hover {
  background: #1c4400;
  box-shadow: 0 8px 22px rgba(5,150,105,.4), 0 3px 8px rgba(0,0,0,.15);
}
/* Same camouflage problem .btn-primary's near-black fill has against the
   dark theme's card background (see comment above it) -- same glow-ring fix,
   green instead of amber. */
:root[data-theme="dark"] .btn-success-dark {
  box-shadow: 0 0 0 1px rgba(5,150,105,.35), 0 0 16px -2px var(--success), 0 2px 6px rgba(0,0,0,.35);
}
:root[data-theme="dark"] .btn-success-dark:hover {
  box-shadow: 0 0 0 1px rgba(5,150,105,.5), 0 0 26px -2px var(--success), 0 3px 8px rgba(0,0,0,.25);
}

/* Danger → stays red (semantic), but a darker fill than --danger itself
   (that variable also drives .alert-danger/.badge-danger text and stays as
   the brighter shade there) -- same darkest-fill + off-white text pattern
   as .btn-success-dark above, red instead of green. */
.btn-danger {
  background: #6b1414;
  color: #E6DDC6;
  box-shadow: 0 2px 6px rgba(220,38,38,.3), 0 1px 2px rgba(0,0,0,.15);
}
.btn-danger:hover {
  background: #841919;
  box-shadow: 0 8px 22px rgba(220,38,38,.4), 0 3px 8px rgba(0,0,0,.15);
}
/* Same camouflage problem .btn-primary/.btn-success-dark's dark fills have
   against the dark theme's card background -- same glow-ring fix, red. */
:root[data-theme="dark"] .btn-danger {
  box-shadow: 0 0 0 1px rgba(220,38,38,.35), 0 0 16px -2px var(--danger), 0 2px 6px rgba(0,0,0,.35);
}
:root[data-theme="dark"] .btn-danger:hover {
  box-shadow: 0 0 0 1px rgba(220,38,38,.5), 0 0 26px -2px var(--danger), 0 3px 8px rgba(0,0,0,.25);
}

/* Warning */
.btn-warning {
  background: var(--warning);
  color: #E6DDC6;
  box-shadow: 0 2px 6px rgba(217,119,6,.3), 0 1px 2px rgba(0,0,0,.15);
}
.btn-warning:hover {
  box-shadow: 0 8px 22px rgba(217,119,6,.4), 0 3px 8px rgba(0,0,0,.15);
}

/* Outline */
/* Border/shadow tinted warm amber instead of flat gray/black — echoes the
   gold accent already used for labels/text-muted everywhere on the page,
   so buttons stop looking like a mismatched neutral-gray afterthought next
   to them. Dark mode's own override two rules down replaces both
   properties outright, so this is light-mode-only in effect. */
.btn-outline {
  background: var(--white);
  border: 2px solid rgba(196,124,5,.35);
  color: var(--text);
  box-shadow: 0 0 10px -3px rgba(196,124,5,.3), 0 1px 3px rgba(100,55,5,.09), 0 1px 2px rgba(100,55,5,.05);
}
.btn-outline:hover {
  background: var(--bg-hover);
  border-color: rgba(196,124,5,.6);
  box-shadow: 0 0 16px -2px rgba(196,124,5,.4), 0 6px 18px rgba(100,55,5,.14), 0 2px 6px rgba(100,55,5,.08);
}
/* Both background and border resolve to near-black in dark mode (var(--white)
   is the dark surface color there, var(--border) is barely-visible white at
   10% opacity) — on a dark card/table, an outline button all but disappears.
   A warm amber glow (matching the dashboard's existing glow language on
   .metric-card/.chart-wrap) keeps it readable instead of just camouflaged. */
:root[data-theme="dark"] .btn-outline {
  border-color: rgba(224,160,32,.4);
  box-shadow: 0 0 0 1px rgba(224,160,32,.08), 0 0 10px -3px var(--primary);
}
:root[data-theme="dark"] .btn-outline:hover {
  border-color: var(--primary);
  box-shadow: 0 0 0 1px rgba(224,160,32,.15), 0 0 18px -2px var(--primary);
}

.btn-sm   { padding: .3rem .65rem; font-size: .8rem; border-radius: var(--radius-sm); }
.btn-lg   { padding: .8rem 1.75rem; font-size: 1rem; border-radius: var(--radius); }
/* True circle everywhere, regardless of sibling button height — every
   .btn-icon in the app is the WhatsApp button, sitting in a flex row next
   to taller text buttons (Profile, Deactivate, …). The row's default
   align-items:stretch was stretching it tall, turning the circle oval;
   align-self:center opts this one item out of that stretch. Fixed
   width+height (not padding-driven sizing) plus a raised/embossed shadow
   for a "3D" look instead of the flat outline every other .btn-outline
   gets. !important because :root[data-theme="dark"] .btn-outline's own
   box-shadow below is more specific and would otherwise win the cascade. */
.btn-icon {
  padding: 0; width: 2.2rem; height: 2.2rem; border-radius: 50%;
  flex-shrink: 0; align-self: center;
  box-shadow:
    0 3px 6px rgba(0,0,0,.18), 0 1px 2px rgba(0,0,0,.12), 0 0 8px -3px rgba(37,211,102,.4),
    inset 0 1px 1px rgba(255,255,255,.6), inset 0 -2px 2px rgba(0,0,0,.06) !important;
}
/* Chromium quirk: inside an inline-flex button, the SVG child's WIDTH (only
   the width, not height) gets shrunk by the flex algorithm to a sliver
   (~6px) even with plenty of room in the container — flex-shrink:0
   confirmed via isolated testing to be the actual fix. This, not icon
   size, was why the WhatsApp glyph kept rendering as an unrecognizable dot
   no matter how many times width/height got bumped. */
.btn-icon svg { flex-shrink: 0; }
.btn-icon:hover {
  transform: translateY(-1px);
  box-shadow:
    0 5px 10px rgba(0,0,0,.2), 0 2px 4px rgba(0,0,0,.14), 0 0 12px -2px rgba(37,211,102,.55),
    inset 0 1px 1px rgba(255,255,255,.6), inset 0 -2px 2px rgba(0,0,0,.06) !important;
}
.btn-icon:active {
  transform: translateY(0);
  box-shadow: 0 1px 2px rgba(0,0,0,.18), inset 0 2px 3px rgba(0,0,0,.12) !important;
}
:root[data-theme="dark"] .btn-icon {
  box-shadow:
    0 3px 8px rgba(0,0,0,.4), 0 0 10px -2px rgba(37,211,102,.35),
    inset 0 1px 1px rgba(255,255,255,.08), inset 0 -2px 3px rgba(0,0,0,.35) !important;
}
:root[data-theme="dark"] .btn-icon:hover {
  box-shadow:
    0 5px 12px rgba(0,0,0,.45), 0 0 16px -1px rgba(37,211,102,.5),
    inset 0 1px 1px rgba(255,255,255,.1), inset 0 -2px 3px rgba(0,0,0,.35) !important;
}

/* Every checkbox/radio in the app was the bare browser default — tiny and OS
   blue instead of the app's amber accent. accent-color re-themes the native
   check/dot without rebuilding it from scratch; size bumped to match. */
input[type="checkbox"],
input[type="radio"] {
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--primary);
  cursor: pointer;
}

/* ─── Toggle switch ──────────────────────────────────────────────────────────── */
/* A real checkbox underneath (visually hidden, not display:none, so it stays
   keyboard/screen-reader accessible) styled as an on/off switch via a
   ~sibling track+thumb. Usage:
   <label class="toggle-switch">
     <input type="checkbox" id="...">
     <span class="toggle-track"></span><span class="toggle-thumb"></span>
   </label>
   No JS changes needed anywhere already reading/writing that input's
   .checked -- this only changes how it looks. */
.toggle-switch { position: relative; display: inline-block; width: 44px; height: 24px; flex-shrink: 0; vertical-align: middle; }
.toggle-switch input {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0;
  opacity: 0; cursor: pointer; z-index: 1;
}
.toggle-switch .toggle-track {
  position: absolute; inset: 0; background: var(--border); border-radius: 999px;
  transition: background var(--transition);
}
.toggle-switch .toggle-thumb {
  position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3); transition: transform var(--transition);
}
.toggle-switch input:checked ~ .toggle-track { background: var(--primary); }
.toggle-switch input:checked ~ .toggle-thumb { transform: translateX(20px); }
.toggle-switch input:focus-visible ~ .toggle-track { box-shadow: 0 0 0 3px rgba(224,160,32,.35); }

/* ─── Forms ──────────────────────────────────────────────────────────────────── */
.form-group  { margin-bottom: 1.1rem; }
.form-row    { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.form-row-3  { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; }

label {
  display: block;
  font-size: .82rem;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: .35rem;
  letter-spacing: .01em;
}

input[type="text"],
input[type="number"],
input[type="tel"],
input[type="email"],
input[type="password"],
input[type="date"],
input[type="datetime-local"],
input[type="search"],
input[type="time"],
input[type="url"],
input[type="month"],
select,
textarea {
  width: 100%;
  padding: .58rem .85rem;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: .9rem;
  font-family: inherit;
  color: var(--text);
  background: var(--white);
  transition: border-color var(--transition), box-shadow var(--transition);
  appearance: none;
}

select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23c47c05' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .85rem center;
  padding-right: 2.25rem;
}

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(196,124,5,.15);
}

input::placeholder, textarea::placeholder { color: var(--text-subtle); }
.form-hint  { font-size: .78rem; color: var(--text-muted); margin-top: .3rem; }
.form-error { font-size: .78rem; color: var(--danger); margin-top: .3rem; font-weight: 500; }

/* ── TomSelect dropdown theme ──────────────────────────────────────────────
   Every page using TomSelect (via the CDN <link>/<script> pair) needs this
   to match the app's own inputs instead of the library's bare default look.
   All theme-var-driven, so light/dark adapt automatically — no separate
   dark-mode block needed here.
   !important on the visual properties is load-bearing, not decoration: the
   TomSelect CDN's own stylesheet is a <link> tag too, and on every page that
   uses it, it's declared AFTER main.css's <link> in <head> — so at equal
   specificity its bundled defaults (white background, near-black text)
   silently win the cascade and this whole block does nothing. Confirmed by
   loading the real CDN CSS (not a test stub) and inspecting computed style:
   .ts-dropdown resolved to TomSelect's own color, not var(--text). Refusing
   to depend on every page getting <link> order right forever. */
/* display:flex + the child-input rules below stop the control from growing
   taller the moment it's opened. TomSelect renders its filter <input> as a
   plain block-level child rather than replacing the shown text inline, so
   without this the input's own height stacks below the existing content
   instead of sharing the same line — confirmed by measuring .ts-control's
   box before/after opening (38.5px -> 56.5px) with the real library loaded. */
.ts-wrapper.single .ts-control { display: flex !important; align-items: center; border: 1.5px solid var(--border) !important; border-radius: var(--radius-sm); font-size: .9rem; font-family: inherit; padding: .58rem .85rem; background: var(--white) !important; color: var(--text) !important; box-shadow: none; cursor: pointer; }
/* A single-select box is always one line (long labels get an ellipsis). Wrapping onto a second line
   while focused made the box shrink on blur, shifting the controls below it between mouse-down and
   mouse-up so the first click on e.g. Save was lost. */
.ts-wrapper.single .ts-control > .item { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; max-width: 100%; }
.ts-wrapper.single .ts-control > input { flex: 1; min-width: 0; height: auto !important; min-height: 0 !important; padding: 0 !important; margin: 0 !important; line-height: normal !important; font-size: inherit !important; }
/* Text typed into any TomSelect box: the library's own dark-grey input
   colour was invisible on dark surfaces. */
.ts-wrapper .ts-control > input,
.ts-wrapper.single.input-active .ts-control > input { color: var(--text) !important; -webkit-text-fill-color: var(--text) !important; background: transparent !important; }
.ts-wrapper.multi .ts-control { border: 1.5px solid var(--border) !important; border-radius: var(--radius-sm); background: var(--white) !important; color: var(--text) !important; font-size: .9rem; font-family: inherit; padding: .4rem .6rem; box-shadow: none; }
.ts-wrapper.multi.focus .ts-control { border-color: var(--primary) !important; }
.ts-wrapper.multi .ts-control > div.item { background: rgba(224,160,32,.14); border: 1px solid rgba(224,160,32,.45); color: var(--text); border-radius: 999px; }
.ts-wrapper.multi .ts-control > div.item .remove { color: var(--text-muted); border-left-color: rgba(224,160,32,.45); }
.ts-wrapper.single.focus .ts-control { border-color: var(--primary) !important; box-shadow: 0 0 0 3px rgba(37,99,235,.12); }
.ts-wrapper.single.input-active .ts-control { border-color: var(--primary) !important; background: var(--white) !important; color: var(--text) !important; }
.ts-dropdown { border: 1.5px solid var(--border) !important; border-radius: var(--radius-sm); box-shadow: var(--shadow-lg); font-size: .9rem; font-family: inherit; background: var(--white) !important; color: var(--text) !important; margin-top: 4px; overflow: hidden; }
.ts-dropdown .ts-dropdown-content { max-height: 240px; }
/* File picker (initFilePicker in utils.js) and a fallback so no native "Choose file" box ever looks raw */
.fp-box { border: 1.5px dashed var(--border); border-radius: var(--radius); padding: .8rem; display: flex; flex-wrap: wrap; align-items: center; gap: .6rem .9rem; background: var(--bg); transition: border-color .15s, background .15s; }
.fp-box.drag { border-color: var(--primary); background: var(--primary-light); }
.fp-add { display: inline-flex; align-items: center; gap: .45rem; }
.fp-hint { font-size: .78rem; color: var(--text-muted); }
.fp-thumbs { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: .6rem; }
.fp-thumbs:empty { display: none; }
.fp-thumb { position: relative; width: 92px; font-size: .68rem; color: var(--text-muted); }
.fp-thumb img { width: 92px; height: 70px; object-fit: cover; border-radius: var(--radius-sm); border: 1px solid var(--border); display: block; }
.fp-thumb span { display: block; margin-top: .2rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fp-x { position: absolute; top: -6px; right: -6px; width: 20px; height: 20px; border-radius: 50%; border: none; background: var(--danger); color: #fff; font-size: .9rem; line-height: 1; cursor: pointer; padding: 0; appearance: none; }
input[type="file"]::file-selector-button { border: 1.5px solid var(--border); border-radius: var(--radius-sm); background: var(--white); color: var(--text); font: inherit; font-size: .85rem; font-weight: 600; padding: .45rem .9rem; margin-right: .7rem; cursor: pointer; }
input[type="file"]::file-selector-button:hover { border-color: var(--primary); color: var(--primary); }
/* Photo zoom pop-up (utils.js) */
.pz-overlay { position: fixed; inset: 0; background: rgba(15, 23, 42, .6); display: flex; align-items: center; justify-content: center; z-index: 900; padding: 1rem; cursor: zoom-out; }
.pz-card { position: relative; background: var(--white); padding: .6rem; border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); cursor: default; }
.pz-card img { display: block; width: min(380px, 78vw); height: min(380px, 70vh); object-fit: contain; border-radius: var(--radius); background: var(--bg); }
.pz-x { position: absolute; top: -12px; right: -12px; width: 30px; height: 30px; border-radius: 50%; border: none; background: var(--text); color: var(--white); font-size: 1.2rem; line-height: 1; cursor: pointer; padding: 0; appearance: none; }
img.student-photo, #ro-photo-img, #form-photo-img { cursor: zoom-in; }
/* A student's name that opens their profile (studentLink in utils.js) */
.student-name-link { color: inherit; text-decoration: none; font-weight: inherit; }
.student-name-link:hover { color: var(--primary); text-decoration: underline; }
/* Row "Actions ▾" menu (see actionsCell in utils.js) */
.act-wrap { display: inline-block; }
.act-menu { position: fixed; z-index: 500; min-width: 200px; background: var(--white); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-lg); padding: .3rem; display: flex; flex-direction: column; }
.act-menu button { display: flex; align-items: center; gap: .65rem; width: 100%; text-align: left; background: none; border: none; padding: .55rem .75rem; border-radius: var(--radius-sm); font: inherit; font-size: .88rem; font-weight: 500; color: var(--text); cursor: pointer; appearance: none; }
.act-menu button:hover { background: var(--primary-light); color: var(--primary); }
.act-menu button.danger { color: var(--danger); }
.act-menu button.danger:hover { background: var(--danger-light); color: var(--danger); }
.act-menu button svg { width: 16px; height: 16px; flex-shrink: 0; }
/* Group headings inside a dropdown (e.g. expense categories): a label, not a pickable row. */
.ts-dropdown .optgroup-header { padding: .5rem 1rem .3rem; font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--text-muted) !important; background: var(--bg); cursor: default; }
.ts-dropdown .optgroup:not(:first-child) { border-top: 1px solid var(--border); }
/* Small inline "+ Add ..." links next to a field label. */
.manage-link { color: var(--primary); font-weight: 600; text-decoration: none; }
.manage-link:hover { text-decoration: underline; }
/* A list attached to <body> (see styledSelect in utils.js) must sit above the sticky nav. */
body > .ts-dropdown { z-index: 1000; }
.ts-dropdown .option { padding: .6rem 1rem; cursor: pointer; color: var(--text) !important; }
.ts-dropdown .option.active { background: var(--primary-light) !important; color: var(--primary) !important; }
.ts-dropdown .option:hover  { background: var(--primary-light) !important; color: var(--primary) !important; }
.ts-dropdown .option.selected { background: var(--primary-light) !important; color: var(--primary) !important; font-weight: 600; }
.ts-dropdown input.ts-search { border: none; border-bottom: 1.5px solid var(--border) !important; border-radius: 0; padding: .55rem 1rem; font-size: .875rem; font-family: inherit; background: var(--bg) !important; color: var(--text) !important; width: 100%; outline: none; }
.ts-dropdown input.ts-search:focus { background: var(--bg) !important; }
.ts-dropdown .no-results { padding: .75rem 1rem; color: var(--text-muted) !important; font-size: .875rem; }
.ts-wrapper .clear-button { color: var(--text-muted); }

/* ── Card list — phone alternative to a wide table ─────────────────────────
   A table with 5+ columns just doesn't fit a phone screen; scrolling it
   sideways inside .table-wrap works but is a bad experience. Pages that
   provide a card alternative render BOTH a `.table-wrap.has-mobile-cards`
   and a sibling `.data-cards` from the same data — this media query is the
   only thing that decides which is visible, so it reflows instantly on
   resize/rotation with no re-render. Add has-mobile-cards only to a
   .table-wrap that actually has a .data-cards sibling — plain .table-wrap
   elsewhere (tables that already fit fine on a phone) are unaffected. */
.data-cards { display: none; }
@media (max-width: 640px) {
  .table-wrap.has-mobile-cards, .table-scroll.has-mobile-cards { display: none; }
  .data-cards { display: flex; flex-direction: column; gap: .75rem; }
}
/* Light mode only — a warm-tinted glass edge echoing .card's bevel instead
   of a flat white box with a plain gray border. Dark mode is re-pinned
   right after to its exact prior values (var(--card-bg)/var(--border)/
   var(--shadow-sm)), unchanged. */
.data-card {
  background: rgba(255,255,255,.55);
  border: 2px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1rem;
  box-shadow:
    inset 0 1px 0 rgba(255,220,120,.5),
    0 0 16px -4px rgba(196,124,5,.25),
    0 4px 10px rgba(100,55,5,.1);
}
:root[data-theme="dark"] .data-card {
  background: var(--card-bg);
  border-color: var(--border);
  box-shadow: var(--shadow-sm);
}
.data-card-header { display: flex; align-items: center; justify-content: space-between; gap: .5rem; margin-bottom: .65rem; padding-bottom: .65rem; border-bottom: 1px solid var(--border); }
.data-card-identity { display: flex; align-items: center; gap: .65rem; min-width: 0; }
.data-card-title { font-weight: 700; font-size: .95rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.data-card-meta { font-size: .85rem; color: var(--text-muted); flex-shrink: 0; text-align: right; }
.data-card-body { display: flex; flex-direction: column; }
.data-card-row { display: flex; justify-content: space-between; align-items: center; gap: .75rem; font-size: .85rem; padding: .35rem 0; border-bottom: 1px solid var(--border); }
.data-card-row:last-child { border-bottom: none; }
.data-card-row .dcr-label { color: var(--text-muted); flex-shrink: 0; }
.data-card-row .dcr-value { text-align: right; }
/* All 4 buttons (Copy Link, Availability, WhatsApp, Remove) sit in one row,
   each sized to its own content -- Remove and WhatsApp are both .btn-icon
   (compact circles) specifically so a labeled Remove doesn't blow the row's
   width budget. flex-wrap stays on as a fallback for genuinely tiny
   screens, but at normal phone widths this fits without wrapping. */
.data-card-actions { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .75rem; }
.data-card-actions .btn-icon { flex: 0 0 auto; }

/* Date input tweaks */
input[type="date"]::-webkit-calendar-picker-indicator {
  cursor: pointer;
  opacity: .55;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-size: 14px;
}
input[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: 1; }
input[type="date"]::-webkit-datetime-edit-fields-wrapper { padding: 0; }
input[type="date"]::-webkit-datetime-edit { padding: 0; color: var(--text); }
input[type="date"]::-webkit-datetime-edit-year-field,
input[type="date"]::-webkit-datetime-edit-month-field,
input[type="date"]::-webkit-datetime-edit-day-field { color: var(--text); }
input[type="date"]:invalid::-webkit-datetime-edit { color: var(--text-subtle); }

/* ── Shared date / date-time picker (see shared/js/datepicker.js) ─────────
   Native <input type="date"/"datetime-local"> stays the real value store
   (nothing else on a page changes), but its own popup/segment highlighting
   is unstylable OS chrome. On mouse/desktop it's hidden and driven from this
   custom calendar instead; on touch the native input is left visible so
   phones keep their familiar sliding picker. */
.dt-field { position: relative; }
.dt-display {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; padding: .58rem .85rem;
  border: 1.5px solid var(--border); border-radius: var(--radius-sm);
  background: var(--white); color: var(--text);
  font-size: .9rem; font-family: inherit; cursor: pointer;
  transition: border-color var(--transition);
}
.dt-display:hover { border-color: var(--primary-muted); }
.dt-type {
  display: none; position: absolute; left: 2px; top: 2px; z-index: 2;
  border: none; outline: none; border-radius: var(--radius-sm); background: var(--white); color: var(--text);
  padding: 0 .85rem; font: inherit; font-size: .9rem;
}
.dt-type.on { display: block; }
.dt-display:focus-within { border-color: var(--primary); }
.dt-display svg { color: var(--text-muted); flex-shrink: 0; margin-left: .5rem; }
.dt-dropdown {
  display: none; position: absolute; top: calc(100% + 6px); left: 0; z-index: 50;
  background: var(--white); border: 1.5px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  padding: 1rem; width: 270px;
}
.dt-dropdown.open { display: block; }
.dt-cal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: .6rem; }
.dt-cal-title {
  font-weight: 700; font-size: .92rem; color: var(--text);
  background: none; border: none; cursor: pointer; font-family: inherit;
  padding: .2rem .5rem; border-radius: var(--radius-sm); transition: background .12s;
}
.dt-cal-title:hover { background: var(--bg-hover); }
.dt-nav-btn {
  width: 26px; height: 26px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: none; cursor: pointer; font-size: .95rem; color: var(--text);
  display: flex; align-items: center; justify-content: center;
  transition: background .12s;
}
.dt-nav-btn:hover { background: var(--bg-hover); }
.dt-weekdays {
  display: grid; grid-template-columns: repeat(7, 1fr);
  font-size: .68rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--text-muted); text-align: center; padding-bottom: .3rem;
}
.dt-days { display: grid; grid-template-columns: repeat(7, 1fr); gap: .15rem; }
.dt-day {
  aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
  border-radius: 50%; font-size: .82rem; cursor: pointer; color: var(--text);
  transition: background .12s, color .12s;
}
.dt-day:hover { background: var(--primary-light); color: var(--primary); }
.dt-day.selected { background: var(--primary); color: var(--on-primary); font-weight: 700; }
.dt-day.today:not(.selected) { border: 1.5px solid var(--primary-muted); }
.dt-day.other-month { color: var(--text-subtle); opacity: .45; cursor: default; }
.dt-day.other-month:hover { background: none; color: var(--text-subtle); }
.dt-day.disabled { color: var(--text-subtle); opacity: .35; cursor: not-allowed; }
.dt-day.disabled:hover { background: none; color: var(--text-subtle); }

/* Month/year zoom grids — click the header title to reach these, so a
   birthdate decades back doesn't need dozens of prev-month clicks. */
.dt-months, .dt-years { display: grid; grid-template-columns: repeat(3, 1fr); gap: .3rem; }
.dt-month, .dt-year {
  display: flex; align-items: center; justify-content: center;
  padding: .55rem 0; border-radius: var(--radius-sm); font-size: .82rem; cursor: pointer; color: var(--text);
  transition: background .12s, color .12s;
}
.dt-month:hover, .dt-year:hover { background: var(--primary-light); color: var(--primary); }
.dt-month.selected, .dt-year.selected { background: var(--primary); color: var(--on-primary); font-weight: 700; }
.dt-year.other-decade { color: var(--text-subtle); opacity: .45; }
.dt-year.other-decade:hover { background: none; color: var(--text-subtle); }
.dt-month.disabled, .dt-year.disabled { color: var(--text-subtle); opacity: .35; cursor: not-allowed; }
.dt-month.disabled:hover, .dt-year.disabled:hover { background: none; color: var(--text-subtle); }
.dt-time-row {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  margin-top: .85rem; padding-top: .85rem; border-top: 1.5px solid var(--border);
}
.dt-dropdown.dt-dropdown-time-only { width: auto; }
.dt-dropdown-time-only .dt-time-row { margin-top: 0; padding-top: 0; border-top: none; }
.dt-time-group { display: flex; flex-direction: column; align-items: center; gap: .15rem; }
.dt-time-step {
  background: none; border: none; cursor: pointer; color: var(--text-muted);
  font-size: .7rem; line-height: 1; padding: .3rem; min-width: 1.8rem; min-height: 1.8rem;
  display: flex; align-items: center; justify-content: center; transition: color .12s;
}
.dt-time-step:hover { color: var(--primary); }
/* .dt-time-row prefix: the global input[type="text"] rule (padding .58rem
   .85rem, width 100%) is more specific than a lone class and was squeezing
   the digit area to nothing -- boxes showed blank on desktop. */
.dt-time-row .dt-time-val {
  width: 2.7rem; max-width: 2.7rem; box-sizing: border-box; text-align: center; border: 1.5px solid var(--border); border-radius: var(--radius-sm);
  padding: .3rem 0; font-size: .95rem; font-weight: 700; color: var(--text);
  background: var(--white); font-family: inherit; cursor: text;
  transition: border-color var(--transition);
}
.dt-time-val:focus { outline: none; border-color: var(--primary); }
.dt-time-colon { font-weight: 700; font-size: 1.05rem; color: var(--text-muted); }
.dt-ampm { display: flex; flex-direction: column; gap: .2rem; margin-left: .3rem; }
.dt-ampm-btn {
  padding: .22rem .5rem; font-size: .68rem; font-weight: 700; font-family: inherit;
  border: 1.5px solid var(--border); border-radius: var(--radius-sm);
  background: var(--white); color: var(--text-muted); cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.dt-ampm-btn.active { background: var(--primary); color: var(--on-primary); border-color: var(--primary); }
.dt-actions { display: flex; margin-top: .85rem; }

/* Slider fallback for hour/minute, alongside (not instead of) the up/down
   step buttons above -- dragging is a lot faster than repeated taps once
   you're more than a couple steps away from the current value, especially
   on a touchscreen where each tap is a bigger, slower gesture than a mouse
   click. Coarse-pointer-only: a mouse already has the step buttons plus
   direct typing-adjacent precision, a slider there would just be clutter. */
.dt-time-slider-row { display: none; }
@media (pointer: coarse) {
  .dt-time-step { font-size: .85rem; min-width: 2.3rem; min-height: 2.3rem; }
  .dt-time-slider-row {
    display: flex; flex-direction: column; gap: .6rem;
    margin-top: .75rem; padding-top: .75rem; border-top: 1.5px solid var(--border);
  }
  .dt-time-slider-item { display: flex; align-items: center; gap: .6rem; }
  .dt-time-slider-label { font-size: .72rem; font-weight: 700; color: var(--text-muted); width: 3.2rem; flex-shrink: 0; }
  .dt-time-slider {
    flex: 1; height: 2rem; appearance: none; background: transparent; cursor: pointer;
  }
  .dt-time-slider::-webkit-slider-runnable-track {
    height: 6px; border-radius: 999px; background: var(--border);
  }
  .dt-time-slider::-webkit-slider-thumb {
    appearance: none; width: 24px; height: 24px; margin-top: -9px;
    border-radius: 50%; background: var(--primary); border: 3px solid var(--white);
    box-shadow: var(--shadow-sm);
  }
  .dt-time-slider::-moz-range-track { height: 6px; border-radius: 999px; background: var(--border); }
  .dt-time-slider::-moz-range-thumb {
    width: 24px; height: 24px; border-radius: 50%; background: var(--primary);
    border: 3px solid var(--white); box-shadow: var(--shadow-sm);
  }
}

/* Plain <input type="range"> sliders (e.g. Academy Profile's default session
   count) otherwise render with the browser's native blue accent -- retheme
   track+thumb to match the site's gold accent, same colors as
   .dt-time-slider above and the gold scrollbar thumb. */
input[type="range"] {
  appearance: none; -webkit-appearance: none; width: 100%; height: 1.4rem;
  background: transparent; cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track { height: 6px; border-radius: 999px; background: var(--border); }
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 20px; height: 20px; margin-top: -7px;
  border-radius: 50%; background: var(--primary); border: 3px solid var(--white); box-shadow: var(--shadow-sm);
}
input[type="range"]::-moz-range-track { height: 6px; border-radius: 999px; background: var(--border); }
input[type="range"]::-moz-range-thumb {
  width: 20px; height: 20px; border-radius: 50%; background: var(--primary);
  border: 3px solid var(--white); box-shadow: var(--shadow-sm);
}

/* Scrollable table block */
.table-scroll { overflow-y: auto; overflow-x: auto; border-radius: var(--radius); border: 1px solid var(--border); background: var(--white); box-shadow: var(--shadow-sm); }
.table-scroll table { width: 100%; border-collapse: collapse; background: var(--white); }

/* Width constraints */
input[type="tel"]    { max-width: 210px; }
input[type="date"]   { max-width: 185px; }
input[type="number"] { max-width: 180px; }

.field-sm   { max-width: 160px !important; }
.field-md   { max-width: 320px !important; }
.field-full { max-width: 100% !important; }

/* ─── Badges ─────────────────────────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: .18rem .6rem;
  border-radius: var(--radius-pill);
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
}
/* Success/danger capsules are hardcoded, not theme-variable — the same
   darkest-green/darkest-red fill with off-white text in both light and dark
   theme, matching .alert-success/.alert-danger and .toast-success/-danger. */
.badge-success { background: #133000; color: #E6DDC6; }
.badge-danger  { background: #6f0000; color: #E6DDC6; }
.badge-warning { background: var(--warning-light); color: var(--warning); }
.badge-primary { background: var(--primary-light); color: var(--primary); }
.badge-muted   { background: var(--bg-hover); color: var(--text-muted); }

/* text-align:center matters here specifically -- a long translated status
   word (some languages run well past what the pill's padding was sized
   for) wraps to two lines rather than overflowing, and without this that
   second line reads left-aligned inside an otherwise-centered pill shape. */
.badge-active   { background: #133000; color: #E6DDC6; font-size: .7rem; padding: .18rem .6rem; border-radius: var(--radius-pill); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; display: inline-flex; align-items: center; justify-content: center; text-align: center; }
.badge-inactive { background: #6f0000; color: #E6DDC6; font-size: .7rem; padding: .18rem .6rem; border-radius: var(--radius-pill); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; display: inline-flex; align-items: center; justify-content: center; text-align: center; }

/* ─── Filters Bar ────────────────────────────────────────────────────────────── */
.filters {
  display: flex;
  gap: .75rem;
  align-items: flex-end;
  flex-wrap: wrap;
  background: rgba(255,255,255,.45);
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  box-shadow:
    inset 0 1px 0 rgba(255,220,120,.55),
    inset 1px 0 0 rgba(255,210,100,.3),
    inset 0 -1px 0 rgba(100,55,5,.14),
    inset -1px 0 0 rgba(100,55,5,.1),
    0 2px 8px rgba(100,55,5,.08);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
}
:root[data-theme="dark"] .filters {
  background: rgba(255,255,255,.035);
  border-color: rgba(255,255,255,.08);
  box-shadow: 0 1px 2px rgba(0,0,0,.3);
}
.filter-group { display: flex; flex-direction: column; gap: .25rem; min-width: 130px; max-width: 100%; }
.filter-group label { font-size: .75rem; font-weight: 600; color: var(--text-subtle); margin: 0; letter-spacing: .04em; text-transform: uppercase; }

/* ─── Signature Pad ──────────────────────────────────────────────────────────── */
.sig-wrap {
  border: 2px dashed var(--border);
  border-radius: var(--radius);
  /* Off-white (not stark white) in both themes -- a signature pad needs a
     light surface for the amber ink stroke to read against, but "light"
     doesn't have to mean the one pure-white surface the rest of the app
     deliberately avoids. Same cream as .badge-primary/.btn-success-dark's
     text color, used here as a fill instead. */
  background: #E6DDC6;
  position: relative;
  display: inline-block;
  transition: border-color var(--transition);
}
.sig-wrap:focus-within { border-color: var(--primary); }
.sig-canvas {
  display: block;
  touch-action: none;
  cursor: crosshair;
  border-radius: calc(var(--radius) - 2px);
}
.sig-hint {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-subtle);
  font-size: .85rem;
  pointer-events: none;
  gap: .4rem;
}
.sig-clear { position: absolute; top: 8px; right: 8px; }

/* ─── Alerts ─────────────────────────────────────────────────────────────────── */
.alert {
  padding: .85rem 1.1rem;
  border-radius: var(--radius);
  font-size: .875rem;
  margin-bottom: 1rem;
  border-left: 3px solid transparent;
  line-height: 1.5;
}
.alert-info    { background: var(--primary-light); color: var(--primary-dark); border-color: var(--primary); }
/* Solid darkest-shade fill + off-white text, same treatment as
   .toast-success/.toast-danger and .btn-success-dark -- unlike alert-info/
   -warning below, this pairing doesn't need a light/dark theme override
   since it's already dark enough to hold its own text color either way. */
.alert-success { background: #133000; color: #E6DDC6; border-color: var(--success); }
.alert-danger  { background: #6f0000; color: #E6DDC6; border-color: var(--danger); }
.alert-warning { background: var(--warning-light); color: #92400e; border-color: var(--warning); }
:root[data-theme="dark"] .alert-warning { color: #fcd34d; }

/* ─── Photo ──────────────────────────────────────────────────────────────────── */
.student-photo {
  width: 90px; height: 90px;
  border-radius: var(--radius);
  object-fit: cover;
  border: 2px solid var(--border);
  background: var(--bg);
}
.academy-logo, .academy-logo-placeholder {
  width: 90px; height: 90px;
  border-radius: var(--radius);
  border: 2px solid var(--border);
  background: var(--white);
}
.academy-logo { object-fit: contain; padding: .4rem; }
.academy-logo-placeholder {
  display: flex; align-items: center; justify-content: center;
  color: var(--text-subtle); font-size: 2rem;
}
.student-photo-placeholder {
  width: 90px; height: 90px;
  border-radius: var(--radius);
  border: 2px solid var(--border);
  background: var(--bg-hover);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-subtle);
  font-size: 2rem;
}

/* ─── Letterhead (attendance/profile/receipt print views) ──────────────────── */
.letterhead {
  display: flex; align-items: center; gap: .85rem;
  padding-bottom: .85rem; margin-bottom: 1rem;
  border-bottom: 2px solid var(--border);
}
.letterhead-logo { width: 52px; height: 52px; object-fit: contain; border-radius: var(--radius-sm); flex-shrink: 0; }
.letterhead-name { font-size: 1.15rem; font-weight: 800; letter-spacing: -.01em; }
.letterhead-contact { font-size: .8rem; color: var(--text-muted); margin-top: .15rem; }
@media print {
  .letterhead { border-bottom-color: #000; }
  .letterhead-name { color: #000; }
  .letterhead-contact { color: #333; }
}

/* ─── Loading & Empty ────────────────────────────────────────────────────────── */
.loading {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3rem 1rem;
  color: var(--text-muted);
  font-size: .9rem;
  gap: .75rem;
}
.spinner {
  width: 20px; height: 20px;
  border: 2.5px solid var(--border);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin .7s linear infinite;
  flex-shrink: 0;
}
@keyframes spin { to { transform: rotate(360deg); } }

.empty-state {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--text-muted);
}
.empty-state h3 { font-size: 1rem; margin-bottom: .35rem; color: var(--text); font-weight: 600; }
.empty-state p  { font-size: .875rem; }

/* ─── Toast ──────────────────────────────────────────────────────────────────── */
#toast-container {
  position: fixed;
  bottom: 1.5rem;
  right: 1rem;
  left: 1rem;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: .5rem;
  pointer-events: none;
}
#toast-container .toast { pointer-events: auto; }
.toast {
  background: var(--nav-bg);
  color: #E6DDC6;
  padding: .8rem 1.25rem;
  border-radius: var(--radius);
  font-size: .875rem;
  font-weight: 500;
  max-width: 300px;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transform: translateY(8px) scale(.97);
  transition: opacity .2s, transform .2s;
  border-left: 3px solid rgba(255,255,255,.3);
}
.toast.show           { opacity: 1; transform: none; }
.toast.toast-success  { background: #133000; border-color: var(--success); }
.toast.toast-danger   { background: #6f0000; border-color: var(--danger); }
.toast.toast-warning  { background: #78350f; border-color: var(--warning); }

/* ─── Login Page ─────────────────────────────────────────────────────────────── */
.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  background: radial-gradient(1200px 640px at 18% 8%, rgba(196,124,5,.38), transparent 62%), radial-gradient(900px 600px at 90% 90%, rgba(43,122,117,.25), transparent 60%), #0d0b08;
  padding: 18vh 5% 2vh 1.5rem;
}
.login-page::before {
  content: '';
  position: fixed;
  inset: 0;
  background:
    linear-gradient(to right, rgba(0,0,0,.05) 0%, rgba(0,0,0,.0) 45%, rgba(5,3,1,.68) 100%);
  z-index: 0;
}
@media(max-width:640px){
  .login-page {
    justify-content: center;
    padding: 1rem;
    padding-bottom: 6vh;
    background-position: 35% center;
  }
  .login-page::before {
    background: rgba(5,3,1,.6);
  }
  .role-card .label {
    font-size: .62rem !important;
    letter-spacing: .04em !important;
  }
}
/* Warm cream tint (not stark white) + a soft amber glow ring, so this reads
   as this app's own card sitting over the photo instead of a generic flat
   white box dropped on top of it -- same warm-gold language as the rest of
   the app's glowing borders, just dialed down since it sits over a busy
   photo, not a plain card grid. */
.login-card {
  position: relative;
  z-index: 1;
  background: rgba(255,252,246,.94);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-radius: var(--radius-lg);
  box-shadow:
    0 24px 70px rgba(0,0,0,.4),
    0 0 0 1px rgba(224,160,32,.22),
    0 0 42px -14px rgba(224,160,32,.4);
  padding: 2.5rem 2.25rem;
  width: 100%;
  max-width: 420px;
  border: 1px solid rgba(224,160,32,.3);
}
.login-logo { text-align: center; margin-bottom: 2rem; }
.login-logo h1 {
  font-size: 1.35rem;
  font-weight: 800;
  color: var(--text);
  letter-spacing: -.02em;
}
.login-logo p { font-size: .875rem; color: var(--text-muted); margin-top: .35rem; }

.tab-group {
  display: flex;
  border-bottom: 2px solid var(--border);
  margin-bottom: 1.5rem;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  overflow: hidden;
}
.tab-btn {
  flex: 1;
  padding: .65rem;
  background: none;
  border: none;
  cursor: pointer;
  font-family: inherit;
  font-size: .875rem;
  font-weight: 500;
  color: var(--text-muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: color var(--transition), border-color var(--transition);
}
.tab-btn.active { color: var(--primary); border-bottom-color: var(--primary); font-weight: 700; }

.otp-row { display: flex; gap: .5rem; align-items: flex-end; }
.otp-row input { flex: 1; }

/* Confirm screen */
.confirm-photo {
  width: 100px; height: 100px; border-radius: 50%;
  object-fit: cover; border: 3px solid var(--primary-muted);
  display: block; margin: 0 auto 1rem;
}
.confirm-placeholder {
  width: 100px; height: 100px; border-radius: 50%;
  background: var(--bg); border: 3px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  font-size: 2.5rem; margin: 0 auto 1rem;
}
.confirm-name { text-align: center; font-size: 1.15rem; font-weight: 700; margin-bottom: .2rem; }
.confirm-role { text-align: center; font-size: .85rem; color: var(--text-muted); margin-bottom: 1.5rem; text-transform: capitalize; }

/* ─── Student Sign Page ──────────────────────────────────────────────────────── */
.sign-page { max-width: 500px; margin: 2rem auto; padding: 0 1.25rem; }
.sign-card {
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  border: 1px solid var(--border);
  padding: 1.75rem;
}
.sign-date {
  font-size: 1rem;
  font-weight: 600;
  text-align: center;
  color: var(--text-muted);
  margin-bottom: 1.5rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--border);
}
.success-card { text-align: center; padding: 2.5rem 1.5rem; }
.success-icon { font-size: 3rem; margin-bottom: .75rem; }

/* ─── Coachs split layout ────────────────────────────────────────────────── */
.coachs-layout {
  display: grid;
  /* Was 230px -- fine for "Add Coach" in English, too narrow for the
     same label in Tamil/other longer translations, which wrapped the
     card-title mid-word instead of fitting on one or two clean lines. */
  grid-template-columns: 280px 1fr;
  gap: 1.25rem;
  align-items: start;
}
.coach-form-card  { position: sticky; top: calc(var(--nav-h) + 1rem); }
.coach-grid-inner { max-height: calc(100vh - 200px); overflow-y: auto; }
.search-bar { display: flex; gap: .5rem; margin-bottom: 1rem; }
.search-bar input { flex: 1; }
.td-actions { display: flex; gap: .4rem; justify-content: flex-end; flex-wrap: wrap; }


/* ─── Print ──────────────────────────────────────────────────────────────────── */
.print-only { display: none; }
@media print {
  body { background: #fff !important; font-size: 12px; }
  .navbar, .no-print, .btn, button { display: none !important; }
  .print-only { display: block !important; }
  .card  { box-shadow: none !important; border: 1px solid #ddd !important; margin-bottom: .5rem; }
  .table-wrap { box-shadow: none !important; border: 1px solid #ddd !important; }
  .page-container { margin: 0; padding: 0; max-width: 100%; }
  th, td { padding: .35rem .6rem; }
  .print-header {
    text-align: center;
    margin-bottom: 1rem;
    padding-bottom: .75rem;
    border-bottom: 2px solid #000;
  }
  .print-header h1 { font-size: 1.2rem; font-weight: 700; }
  .print-header p  { font-size: .85rem; color: #555; }
}

/* ─── Responsive ─────────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
  .coachs-layout { grid-template-columns: 1fr; }
  .coach-form-card { position: static; }
  .coach-grid-inner { max-height: none; }
}

@media (max-width: 640px) {
  .page-container { margin: 1.25rem auto; padding: 0 1rem; }
  .form-row, .form-row-3 { grid-template-columns: 1fr; }
  .stat-grid { grid-template-columns: 1fr 1fr; }
  .page-title { font-size: 1.2rem; }
  th, td { padding: .6rem .75rem; }
  .card { padding: 1rem 1.1rem; }
  .login-card { padding: 2rem 1.5rem; }

  /* On mobile, constrained inputs can go full width */
  input[type="tel"]    { max-width: 100%; }
  input[type="date"]   { max-width: 100%; }
  input[type="number"] { max-width: 100%; }

  /* THE "page zooms/pans out of place the moment I tap anything" bug —
     iOS Safari auto-zooms the whole page in when a focused input's
     font-size is under 16px, then leaves it zoomed/pannable afterwards
     ("dancing", pulling the page to a corner). Every input/select/textarea
     in the app was sized at .9rem (14.4px) or smaller. !important because
     several contexts (TomSelect's .ts-control, date inputs, etc.) set
     their own smaller font-size more specifically than this rule.
     Excludes the date-picker's small readonly hour/minute steppers —
     readonly inputs never take a keyboard and can't trigger this zoom, so
     forcing them to 16px would just make that compact widget look oversized
     for no benefit. */
  input:not([type="checkbox"]):not([type="radio"]):not([readonly]),
  select,
  textarea {
    font-size: 16px !important;
  }
  /* TomSelect's own search inputs (mark-student/mark-coach pickers etc.)
     set font-size: inherit !important at equal specificity to the rule
     above — spelled out explicitly here instead of relying on source-order
     tie-breaking, since that's what was still triggering the iOS zoom/
     "dancing" on pages like Mark Attendance. */
  .ts-wrapper.single .ts-control > input,
  .ts-dropdown input.ts-search {
    font-size: 16px !important;
  }
}

@media (max-width: 400px) {
  .stat-grid { grid-template-columns: 1fr; }
  .btn { font-size: .82rem; padding: .45rem .85rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   "Azure Clean" look -- active only when utils.js's _applyPaletteObject() sets
   <html data-look="clean"> (the 'azure' appearance preset; every other preset
   and Custom Colors clear it, so nothing above changes for them).

   The palette supplies the colours (--primary, --text, --border, ...). This
   block supplies the look those colours cannot: a flat white/grey page instead
   of the photo + glow background, plain hairline-bordered cards instead of the
   warm glass bevel, blue buttons instead of near-black, a slate-navy nav, soft
   tinted status badges, and a sans-serif (Inter) instead of the serif headings.
   Kept in one place, last in the file, so it wins ties with the rules above and
   is easy to delete. Every fill/text pairing here is >=4.5:1 (white on #1a6fe3
   is 4.8:1; the dark-mode equivalents use light text on tinted fills).
   ═══════════════════════════════════════════════════════════════════════════ */
:root[data-look="clean"] {
  --nav-bg: #17212b;
  --text-subtle: #6b7587;
  --bg-hover: #eef2f8;
  --success: #15803d;  --success-light: #e3f5ea;
  --danger: #c62828;   --danger-light: #fdeaea;
  --warning: #b45309;  --warning-light: #fdf1dd;
  --clean-btn: #1a6fe3;  --clean-btn-hover: #1558b8;
  --clean-ring: rgba(26,111,227,.18);
  --shadow-sm: 0 1px 2px rgba(16,24,40,.05);
  --shadow:    0 1px 3px rgba(16,24,40,.08), 0 1px 2px rgba(16,24,40,.04);
  --shadow-md: 0 4px 12px rgba(16,24,40,.08), 0 2px 4px rgba(16,24,40,.04);
  --shadow-lg: 0 12px 32px rgba(16,24,40,.14), 0 4px 10px rgba(16,24,40,.06);
  --radius: 10px;
  --radius-lg: 12px;
  --scrollbar-track: transparent;
  --scrollbar-thumb: #c3cbd8;
  --scrollbar-thumb-hover: var(--primary);
}
:root[data-look="clean"][data-theme="dark"] {
  --nav-bg: #131b23;
  --text-subtle: #8190a6;
  --bg-hover: #222d39;
  --success: #4ade80;  --success-light: rgba(74,222,128,.14);
  --danger: #f87171;   --danger-light: rgba(248,113,113,.14);
  --warning: #fbbf24;  --warning-light: rgba(251,191,36,.14);
  --clean-ring: rgba(77,155,255,.3);
  --shadow-sm: 0 1px 2px rgba(0,0,0,.3);
  --shadow:    0 1px 3px rgba(0,0,0,.35), 0 1px 2px rgba(0,0,0,.3);
  --shadow-md: 0 4px 12px rgba(0,0,0,.35), 0 2px 4px rgba(0,0,0,.3);
  --shadow-lg: 0 12px 32px rgba(0,0,0,.5), 0 4px 10px rgba(0,0,0,.35);
  --scrollbar-thumb: #3a4656;
}

/* Flat page + sans-serif type */
:root[data-look="clean"] body,
:root[data-look="clean"][data-theme="dark"] body {
  background: var(--bg);
  animation: none;
  font-family: 'Inter', 'Jost', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-weight: 400;
}
:root[data-look="clean"] h1, :root[data-look="clean"] h2, :root[data-look="clean"] h3,
:root[data-look="clean"] h4, :root[data-look="clean"] h5, :root[data-look="clean"] h6,
:root[data-look="clean"] .page-title, :root[data-look="clean"] .card-title,
:root[data-look="clean"] .navbar-brand, :root[data-look="clean"] .stat-value,
:root[data-look="clean"] .data-card-title {
  font-family: 'Inter', 'Jost', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
:root[data-look="clean"] .page-title { font-weight: 700; letter-spacing: -.02em; }
:root[data-look="clean"] .card-title { font-weight: 600; }

/* Slate-navy nav, white text, blue active marker */
:root[data-look="clean"] .navbar { background: color-mix(in srgb, var(--primary) 80%, #fff); box-shadow: 0 2px 8px rgba(16,24,40,.14); }
:root[data-look="clean"] .navbar-brand { color: #fff; }
:root[data-look="clean"] .navbar-links a { color: #fff; }
:root[data-look="clean"] .navbar-links a:hover { background: rgba(255,255,255,.16); color: #fff; }
:root[data-look="clean"] .navbar-links a.active { background: #fff; color: var(--primary); font-weight: 700; box-shadow: none; }
:root[data-look="clean"] .navbar-links a.nav-logout { color: #fff; }
:root[data-look="clean"] .navbar-links summary { color: #fff; }
:root[data-look="clean"] .navbar-links summary:hover { background: rgba(255,255,255,.16); color: #fff; }
:root[data-look="clean"] .nav-group.has-active > details > summary { background: #fff; color: var(--primary); font-weight: 700; box-shadow: none; }
:root[data-look="clean"] .nav-group-menu { background: color-mix(in srgb, var(--primary) 80%, #fff); border-color: rgba(255,255,255,.3); }
:root[data-look="clean"] .theme-toggle:hover { color: #fff; }
:root[data-look="clean"] .toast { color: #fff; }

/* Plain bordered surfaces */
:root[data-look="clean"] .card,
:root[data-look="clean"] .chart-wrap,
:root[data-look="clean"] .filters,
:root[data-look="clean"] .table-wrap,
:root[data-look="clean"] .data-card,
:root[data-look="clean"] .metric-card,
:root[data-look="clean"] .stat-card {
  background: var(--card-bg) !important;
  border: 1px solid var(--border) !important;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm) !important;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
:root[data-look="clean"] .metric-card:hover { box-shadow: var(--shadow-md) !important; }

/* Tables: white rows, hairline separators, soft blue hover */
:root[data-look="clean"] tbody tr:nth-child(even) td,
:root[data-look="clean"][data-theme="dark"] tbody tr:nth-child(even) td { background: transparent; }
:root[data-look="clean"] tbody tr:hover td,
:root[data-look="clean"][data-theme="dark"] tbody tr:hover td { background: var(--primary-light); }
:root[data-look="clean"] .month-row.selected td { background: var(--primary-light); }

/* Buttons: one bright blue, white text, no glow rings */
:root[data-look="clean"] .btn-primary { background: var(--clean-btn); color: #fff; box-shadow: 0 1px 2px rgba(26,111,227,.35); }
:root[data-look="clean"] .btn-primary:hover { background: var(--clean-btn-hover); box-shadow: 0 6px 16px rgba(26,111,227,.35); }
:root[data-look="clean"] .btn-success { background: #15803d; color: #fff; box-shadow: 0 1px 2px rgba(21,128,61,.3); }
:root[data-look="clean"] .btn-success:hover { box-shadow: 0 6px 16px rgba(21,128,61,.35); }
:root[data-look="clean"] .btn-success-dark { background: #15803d; color: #fff; box-shadow: 0 1px 2px rgba(21,128,61,.3); }
:root[data-look="clean"] .btn-success-dark:hover { background: #116632; box-shadow: 0 6px 16px rgba(21,128,61,.35); }
:root[data-look="clean"] .btn-danger { background: #c62828; color: #fff; box-shadow: 0 1px 2px rgba(198,40,40,.3); }
:root[data-look="clean"] .btn-danger:hover { background: #a61f1f; box-shadow: 0 6px 16px rgba(198,40,40,.35); }
:root[data-look="clean"] .btn-warning { background: #b45309; color: #fff; box-shadow: 0 1px 2px rgba(180,83,9,.3); }
:root[data-look="clean"] .btn-warning:hover { background: #92400e; box-shadow: 0 6px 16px rgba(180,83,9,.35); }
:root[data-look="clean"] .btn-outline { background: var(--white); border: 1.5px solid #cfd6e2; color: var(--text); box-shadow: none; }
:root[data-look="clean"] .btn-outline:hover { background: var(--primary-light); border-color: var(--primary); color: var(--primary); box-shadow: none; }
:root[data-look="clean"][data-theme="dark"] .btn-outline { border-color: rgba(255,255,255,.2); }
:root[data-look="clean"][data-theme="dark"] .btn-outline:hover { border-color: var(--primary); }
:root[data-look="clean"] .btn:hover { transform: translateY(-1px); }

/* Focus rings and selection chips in blue instead of amber */
:root[data-look="clean"] input:focus, :root[data-look="clean"] select:focus, :root[data-look="clean"] textarea:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--clean-ring); }
:root[data-look="clean"] .toggle-switch input:focus-visible ~ .toggle-track { box-shadow: 0 0 0 3px var(--clean-ring); }
:root[data-look="clean"] .ts-wrapper.multi .ts-control > div.item,
:root[data-look="clean"] #mark-form-card .ts-wrapper.multi .ts-control > div.item,
:root[data-look="clean"] .slot-chip { background: var(--primary-light); border: 1px solid var(--primary-muted); color: var(--text); }
:root[data-look="clean"] .ts-wrapper.multi .ts-control > div.item .remove,
:root[data-look="clean"] #mark-form-card .ts-wrapper.multi .ts-control > div.item .remove { border-left-color: var(--primary-muted); }
:root[data-look="clean"] #mark-form-card .ts-wrapper.multi.focus .ts-control { box-shadow: 0 0 0 3px var(--clean-ring); }
:root[data-look="clean"] .instr-day { background: var(--card-bg); border-color: var(--border); }
:root[data-look="clean"] .instr-day-header { background: var(--bg); }
:root[data-look="clean"] .profile-section summary:hover,
:root[data-look="clean"] .notif-block-header:hover { background: var(--primary-light); }

/* Status badges and alerts: soft tint + strong text instead of solid dark fills */
:root[data-look="clean"] .badge-success, :root[data-look="clean"] .badge-active { background: #dcf3e5; color: #0b5b34; }
:root[data-look="clean"] .badge-danger,  :root[data-look="clean"] .badge-inactive { background: #fde3e3; color: #9b1c1c; }
:root[data-look="clean"][data-theme="dark"] .badge-success, :root[data-look="clean"][data-theme="dark"] .badge-active { background: rgba(74,222,128,.16); color: #86efac; }
:root[data-look="clean"][data-theme="dark"] .badge-danger,  :root[data-look="clean"][data-theme="dark"] .badge-inactive { background: rgba(248,113,113,.16); color: #fca5a5; }
:root[data-look="clean"] .alert-success { background: #e6f5ec; color: #0b5b34; }
:root[data-look="clean"] .alert-danger  { background: #fdeaea; color: #9b1c1c; }
:root[data-look="clean"] .alert-warning { color: #92400e; }
:root[data-look="clean"][data-theme="dark"] .alert-success { background: rgba(74,222,128,.14); color: #86efac; }
:root[data-look="clean"][data-theme="dark"] .alert-danger  { background: rgba(248,113,113,.14); color: #fca5a5; }
:root[data-look="clean"][data-theme="dark"] .alert-warning { color: #fcd34d; }

/* Signature pad: cool off-white instead of cream */
:root[data-look="clean"] .sig-wrap { background: #f8fafc; }

/* ─── Printed documents (invoice, receipts) — see shared/js/printdocs.js ─────────────────────────────── */
.pd { --pd-tint: color-mix(in srgb, var(--pd-accent) 9%, #fff); --pd-ink: #0f172a; --pd-muted: #64748b; --pd-line: #e2e8f0;
  font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif; color: var(--pd-ink); font-size: 12.5px; line-height: 1.5;
  position: relative; padding: 4px 2px; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.pd * { box-sizing: border-box; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.pd-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; padding-bottom: 14px; border-bottom: 3px solid var(--pd-accent); }
.pd-brand { display: flex; align-items: center; gap: 14px; min-width: 0; }
.pd-logo { width: 58px; height: 58px; object-fit: contain; border-radius: 10px; flex-shrink: 0; }
.pd-academy { font-size: 20px; font-weight: 800; letter-spacing: -.01em; line-height: 1.15; }
.pd-contact { font-size: 10.5px; color: var(--pd-muted); margin-top: 4px; max-width: 360px; line-height: 1.45; }
.pd-dot { margin: 0 5px; opacity: .6; }
.pd-doc { text-align: right; flex-shrink: 0; }
.pd-doc-title { font-size: 26px; font-weight: 800; letter-spacing: .14em; color: var(--pd-accent); line-height: 1; }
.pd-doc-no { font-size: 12.5px; font-weight: 700; margin-top: 7px; letter-spacing: .02em; }
.pd-pill { display: inline-block; margin-top: 8px; padding: 3px 13px; border-radius: 999px; font-size: 10px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; background: #e2e8f0; color: #475569; }
.pd-pill.paid { background: #dcfce7; color: #166534; }
.pd-pill.part { background: #fef3c7; color: #92400e; }
.pd-pill.unpaid { background: #fee2e2; color: #991b1b; }
.pd-pill.cancelled { background: #e2e8f0; color: #475569; text-decoration: line-through; }
.pd-info { display: flex; justify-content: space-between; align-items: flex-start; gap: 28px; margin: 18px 0 16px; }
.pd-box { flex: 1; min-width: 0; }
.pd-label { font-size: 9px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: #94a3b8; margin-bottom: 5px; }
.pd-name { font-size: 15px; font-weight: 700; line-height: 1.3; }
.pd-sub { font-size: 11px; color: #475569; margin-top: 2px; }
.pd-meta { min-width: 220px; background: var(--pd-tint); border-radius: 10px; padding: 8px 14px; }
.pd-meta-row { display: flex; justify-content: space-between; gap: 18px; padding: 3px 0; font-size: 11.5px; }
.pd-meta-row span { color: var(--pd-muted); }
.pd-table { width: 100%; border-collapse: collapse; margin-top: 4px; }
.pd-table thead th { background: var(--pd-tint); color: var(--pd-accent); font-size: 9.5px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; text-align: left; padding: 9px 12px; }
.pd-table th.r, .pd-table td.r { text-align: right; }
.pd-table th.n, .pd-table td.n { width: 36px; color: #94a3b8; }
.pd-table tbody td { padding: 10px 12px; border-bottom: 1px solid var(--pd-line); font-size: 12.5px; vertical-align: top; }
.pd-table tbody tr:last-child td { border-bottom-color: #cbd5e1; }
.pd-small tbody td, .pd-small thead th { padding: 6px 12px; font-size: 11.5px; }
.pd-small thead th { font-size: 9px; }
.pd-more { text-align: center; color: #94a3b8; font-size: 10.5px; }
.pd-totals { margin: 14px 0 0 auto; width: 46%; min-width: 250px; }
.pd-total-row { display: flex; justify-content: space-between; padding: 6px 12px; font-size: 12.5px; }
.pd-total-row span { color: var(--pd-muted); }
.pd-balance { display: flex; justify-content: space-between; align-items: center; margin-top: 6px; padding: 11px 14px; border-radius: 9px; background: var(--pd-accent); color: #fff; font-size: 14px; font-weight: 800; }
.pd-balance span { letter-spacing: .04em; }
.pd-balance.ok { background: #15803d; }
.pd-balance.void { background: #64748b; }
.pd-section { margin-top: 16px; font-size: 9px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: #94a3b8; }
.pd-notes { margin-top: 18px; background: #f8fafc; border-left: 3px solid var(--pd-accent); border-radius: 6px; padding: 10px 14px; font-size: 11.5px; color: #334155; }
.pd-sign { margin-top: 30px; display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; }
.pd-thanks { font-size: 11px; color: var(--pd-muted); font-style: italic; }
.pd-signer { text-align: center; min-width: 190px; }
.pd-sig-img { height: 46px; object-fit: contain; display: block; margin: 0 auto 2px; }
.pd-sig-gap { height: 46px; }
.pd-signer-line { border-top: 1px solid #94a3b8; padding-top: 5px; display: flex; flex-direction: column; font-size: 11px; }
.pd-signer-line span { color: var(--pd-muted); font-size: 10px; }
.pd-foot { margin-top: 22px; padding-top: 10px; border-top: 1px solid var(--pd-line); font-size: 9.5px; color: #94a3b8; text-align: center; }
.pd-watermark { position: absolute; left: 50%; top: 42%; transform: translate(-50%, -50%) rotate(-24deg); font-size: 92px; font-weight: 900; letter-spacing: .1em; color: rgba(185, 28, 28, .09); pointer-events: none; white-space: nowrap; }
/* receipts: two compact copies per sheet */
.pd.compact { font-size: 11.5px; padding-top: 14px; }
.pd.compact .pd-head { padding-bottom: 7px; border-bottom-width: 2.5px; }
.pd.compact .pd-logo { width: 44px; height: 44px; }
.pd.compact .pd-academy { font-size: 17px; }
.pd.compact .pd-doc-title { font-size: 19px; letter-spacing: .12em; }
.pd.compact .pd-info { margin: 8px 0 6px; }
.pd.compact .pd-name { font-size: 13.5px; }
.pd.compact .pd-meta { padding: 6px 12px; min-width: 200px; }
.pd.compact .pd-sign { margin-top: 4px; }
.pd.compact .pd-sig-img, .pd.compact .pd-sig-gap { height: 24px; }
.pd.compact .pd-small tbody td, .pd.compact .pd-small thead th { padding: 4px 10px; }
.pd.compact .pd-section { margin-top: 10px; }
.pd.compact .pd-stats { margin-top: 8px; }
.pd.compact .pd-stats > div { padding: 5px 10px; }
.pd.compact .pd-upi { margin-top: 6px; padding-top: 5px; }
.pd.compact .pd-upi img { width: 42px; height: 42px; }
.pd.compact .pd-amount { padding: 8px 14px; }
.pd.compact .pd-amount-fig { font-size: 22px; }
.pd-copytag { position: absolute; top: 0; right: 2px; font-size: 8px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase; color: #94a3b8; }
.pd-amount { display: flex; justify-content: space-between; align-items: center; gap: 16px; background: var(--pd-tint); border: 1.5px solid var(--pd-accent); border-radius: 10px; padding: 10px 16px; margin: 4px 0 6px; }
.pd-amount-words { font-size: 11px; color: #334155; font-weight: 600; max-width: 330px; }
.pd-amount-fig { font-size: 26px; font-weight: 800; color: var(--pd-accent); letter-spacing: -.01em; white-space: nowrap; }
.pd-stats { display: flex; gap: 10px; margin-top: 12px; }
.pd-stats > div { flex: 1; background: #f8fafc; border: 1px solid var(--pd-line); border-radius: 8px; padding: 7px 12px; display: flex; flex-direction: column; }
.pd-stats span { font-size: 9px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: #94a3b8; }
.pd-stats strong { font-size: 14px; font-weight: 800; }
.pd-stats .due { background: #fef2f2; border-color: #fecaca; } .pd-stats .due strong { color: #b91c1c; }
.pd-stats .ok { background: #f0fdf4; border-color: #bbf7d0; } .pd-stats .ok strong { color: #15803d; }
.pd-cut { position: relative; border-top: 1.5px dashed #b6bfcc; margin: 12px 0; }
.pd-cut span { position: absolute; left: 50%; top: -7px; transform: translateX(-50%); background: #fff; padding: 0 8px; font-size: 8px; letter-spacing: .16em; text-transform: uppercase; color: #94a3b8; }
.pd-sheet .pd { page-break-inside: avoid; }
.pd-upi { display: flex; align-items: center; gap: 12px; margin-top: 12px; padding-top: 10px; border-top: 1px dashed #cbd5e1; font-size: 10.5px; }
.pd-upi strong { display: block; font-size: 11px; }
.pd-upi span { color: var(--pd-muted); }
.pd-sumrow { display: flex; justify-content: space-between; align-items: flex-start; gap: 24px; margin-top: 14px; }
.pd-sumrow .pd-totals { margin: 0 0 0 auto; }
.pd-pay { display: flex; align-items: center; gap: 14px; border: 1.5px solid var(--pd-line); border-radius: 12px; padding: 10px 14px 10px 10px; background: #fff; }
.pd-pay img { width: 92px; height: 92px; display: block; }
.pd-pay strong { display: block; font-size: 17px; font-weight: 800; color: var(--pd-accent); line-height: 1.2; }
.pd-pay span { display: block; font-size: 10.5px; color: var(--pd-muted); margin-top: 2px; }

/* ─── Page header (admin shell): one hero block, then a floating tabs bar ─────────────────────────── */
.hero { position: relative; overflow: hidden; color: #fff; padding: 1.15rem 1.75rem 3.3rem;
  background: linear-gradient(118deg, #0b1224 0%, #16233f 55%, #1d3158 100%); }
:root[data-look="clean"] .hero { background: linear-gradient(118deg, color-mix(in srgb, var(--primary) 58%, #000) 0%, var(--primary) 50%, color-mix(in srgb, var(--primary) 66%, #fff) 100%); }
.hero::before { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 96px; background: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 120' preserveAspectRatio='none'%3E%3Cpath fill='%23ffffff' fill-opacity='.10' d='M0 60 C 240 120 480 0 720 50 S 1200 110 1440 40 L1440 120 L0 120Z'/%3E%3Cpath fill='%23ffffff' fill-opacity='.07' d='M0 85 C 300 20 560 120 860 70 S 1260 30 1440 80 L1440 120 L0 120Z'/%3E%3C/svg%3E") bottom / 100% 100% no-repeat; pointer-events: none; }
.hero::after { content: ''; position: absolute; right: -90px; top: -130px; width: 380px; height: 380px; border-radius: 50%; background: radial-gradient(circle, rgba(255,255,255,.18), rgba(255,255,255,0) 68%); pointer-events: none; }
.hero-in { position: relative; z-index: 1; display: flex; align-items: center; gap: 1.25rem; }
.hero-menu { display: none; }
.hero-logo-link { display: block; line-height: 0; flex-shrink: 0; }
.hero-logo { width: 92px; height: 92px; object-fit: cover; border-radius: 50%; background: #fff; border: 3px solid rgba(255,255,255,.92); box-shadow: 0 8px 22px rgba(0,0,0,.28); }
.hero-id { min-width: 0; flex: 0 1 auto; max-width: 34%; }
.hero-id h1 { margin: 0; font-size: 1.95rem; font-weight: 800; letter-spacing: -.012em; line-height: 1.12; color: #fff; text-shadow: 0 2px 10px rgba(0,0,0,.22);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.hero-tag { margin-top: .35rem; font-size: .98rem; font-style: italic; font-weight: 500; letter-spacing: .01em; color: rgba(255,255,255,.88); line-height: 1.35; }
.hero-tag:empty { display: none; }
.hero-banner { flex: 1 1 0; min-width: 0; display: flex; justify-content: center; }
.hero-banner .brand-banner { width: 100%; max-width: 580px; height: 96px; border-radius: 18px; background-size: cover; background-position: center; border: 2px solid rgba(255,255,255,.6); box-shadow: 0 10px 26px rgba(0,0,0,.3); }
.hero-right { margin-left: auto; display: flex; align-items: center; gap: 1.2rem; flex-shrink: 0; }
.hero-clock { text-align: right; line-height: 1.2; }
#brand-time { font-size: 1.65rem; font-weight: 800; letter-spacing: .03em; font-variant-numeric: tabular-nums; color: #fff; text-shadow: 0 2px 8px rgba(0,0,0,.2); }
#brand-date { font-size: .86rem; color: rgba(255,255,255,.86); margin-top: .15rem; }
.hero-tools { display: flex; align-items: center; gap: .55rem; }
.hero .theme-toggle { width: 42px; height: 42px; margin-left: 0; color: #fff; background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.38); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }
.hero .theme-toggle:hover { background: rgba(255,255,255,.28); color: #fff; }
.hero .lang-switch { margin-left: 0; }

/* the tabs: a white floating bar that overlaps the hero's lower edge */
:root .navbar.shell-nav { margin: -2rem 1.5rem 0; height: 58px; padding: 0 .6rem; border: none; border-radius: 18px; top: .6rem;
  background: var(--white); box-shadow: 0 12px 32px rgba(15,23,42,.16), 0 0 0 1px var(--border); gap: .5rem; }
:root .navbar.shell-nav .navbar-brand, :root .navbar.shell-nav .nav-hamburger { display: none; }
:root .navbar.shell-nav .navbar-links { justify-content: flex-start; gap: .15rem; }
:root .navbar.shell-nav .navbar-links a, :root .navbar.shell-nav .navbar-links summary { color: var(--text-muted); font-weight: 600; font-size: .9rem; padding: .55rem 1rem; border-radius: 12px; background: transparent; box-shadow: none; }
:root .navbar.shell-nav .navbar-links a:hover, :root .navbar.shell-nav .navbar-links summary:hover { background: var(--bg-hover); color: var(--text); }
:root .navbar.shell-nav .navbar-links a.active, :root .navbar.shell-nav .nav-group.has-active > details > summary { background: var(--primary); color: var(--on-primary, #fff); font-weight: 700; box-shadow: 0 4px 12px color-mix(in srgb, var(--primary) 40%, transparent); }
:root .navbar.shell-nav .navbar-links a.nav-logout { margin-left: auto; color: var(--danger); }
:root .navbar.shell-nav .navbar-links a.nav-logout:hover { background: var(--danger-light); color: var(--danger); }
:root .navbar.shell-nav .nav-group-menu { background: var(--white); border: 1px solid var(--border); box-shadow: var(--shadow-lg); }
@media (max-width: 768px) {
  .hero { padding: .8rem 1rem 2.4rem; }
  .hero-in { gap: .7rem; }
  .hero-menu { display: flex; flex-direction: column; justify-content: center; gap: 4px; width: 40px; height: 40px; flex-shrink: 0; padding: 0 10px; border-radius: 12px; cursor: pointer; background: rgba(255,255,255,.16); border: 1px solid rgba(255,255,255,.38); }
  .hero-menu span { display: block; height: 2px; background: #fff; border-radius: 2px; }
  .hero-logo { width: 50px; height: 50px; border-width: 2px; }
  .hero-id { max-width: none; flex: 1 1 auto; }
  .hero-id h1 { font-size: .98rem; -webkit-line-clamp: 2; }
  .hero-tag { font-size: .74rem; margin-top: .1rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .hero-banner, #brand-date { display: none; }
  /* the clock sits in the hero's lower-right corner so the academy name keeps its room */
  .hero-clock { position: absolute; right: 1rem; bottom: -1.65rem; }
  #brand-time { font-size: .78rem; font-weight: 700; color: #fff; text-shadow: 0 1px 4px rgba(0,0,0,.35); }
  .hero-right { gap: .5rem; }
  .hero .theme-toggle { width: 34px; height: 34px; }
  .hero::before { height: 60px; }
  /* the tabs bar disappears; its list opens as the side menu from the button in the hero */
  :root .navbar.shell-nav { margin: 0; height: 0; padding: 0; top: 0; box-shadow: none; background: transparent; border-radius: 0; }
  :root .navbar.shell-nav .navbar-links { top: 0; background: var(--white); }
  :root .navbar.shell-nav .navbar-links a.nav-logout { margin-left: 0; }
  .nav-overlay { inset: 0; }
  .reminder-strip { top: 0 !important; }
}
@media (max-width: 1100px) and (min-width: 769px) { .hero-banner { display: none; } .hero-id { max-width: 48%; } }
@media print { .hero { display: none !important; } }
/* Academy Profile > Branding: logo and banner side by side */
.brand-block { display: grid; grid-template-columns: minmax(180px, 260px) 1fr; gap: 1.5rem; margin-bottom: 1rem; align-items: start; }
@media (max-width: 760px) { .brand-block { grid-template-columns: 1fr; } }
.brand-col > label { display: block; margin-bottom: .45rem; }
.banner-preview { height: 96px; border: 1.5px dashed var(--border); border-radius: var(--radius); background: var(--bg); display: flex; align-items: center; justify-content: center; color: var(--text-muted); font-size: .85rem; overflow: hidden; }
.banner-preview img { width: 100%; height: 100%; object-fit: cover; }

/* Placeholder-style entries of a styled dropdown (the empty "Select ..." option): light, like any input's helper text,
   and gone the moment the box is focused so the cursor and what is typed stay readable. An empty entry still holds one
   line, so the box keeps its normal height. */
.ts-wrapper.single .ts-control > .item[data-value=""] { color: var(--text-subtle) !important; }
.ts-wrapper.single .ts-control > .item[data-value=""]:empty::before { content: "\200b"; }
.ts-wrapper.single.input-active .ts-control > .item[data-value=""],
.ts-wrapper.single.focus .ts-control > .item[data-value=""] { display: none !important; }
.ts-wrapper.single.input-active .ts-control > input { min-width: 4ch; }

/* A label with a Masters / Fee Items link keeps label and link on one line, so neighbouring fields stay level. */
.form-group > label:has(.manage-link) { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .1rem .5rem; white-space: normal; }
.form-group > label:has(.manage-link) .manage-link { margin-left: 0 !important; flex: none; }

/* ─── Inviting fields ─────────────────────────────────────────────────────────
   Three things read differently on every form: the label (dark, firm), the hint inside an empty field (pale,
   regular weight) and what the person types (full colour, a touch heavier). The field itself is softly tinted,
   lifts on hover, and turns white with a coloured ring while it is being filled, its label lighting up too. */
:root { --field-bg: color-mix(in srgb, var(--primary) 4%, var(--white)); --field-border: color-mix(in srgb, var(--text) 16%, transparent); --hint: color-mix(in srgb, var(--text) 38%, transparent); }
label { color: var(--text); font-size: .8rem; font-weight: 650; letter-spacing: .015em; transition: color var(--transition); }
.form-group:focus-within > label { color: var(--primary); }
input[type="text"], input[type="number"], input[type="tel"], input[type="email"], input[type="password"], input[type="date"],
input[type="datetime-local"], input[type="search"], input[type="time"], input[type="url"], input[type="month"], select, textarea {
  background: var(--field-bg); border-color: var(--field-border); font-weight: 500; padding: .66rem .95rem;
  transition: border-color var(--transition), box-shadow var(--transition), background var(--transition);
}
input:hover:not(:focus):not(:disabled), select:hover:not(:focus), textarea:hover:not(:focus) { border-color: color-mix(in srgb, var(--primary) 55%, var(--field-border)); }
input:focus, select:focus, textarea:focus { background: var(--white); border-width: 1.5px; }
input::placeholder, textarea::placeholder { color: var(--hint); font-weight: 400; opacity: 1; }
input:disabled, textarea:disabled { background: color-mix(in srgb, var(--text) 5%, var(--white)); color: var(--text-muted); }
.form-hint { color: var(--text-muted); font-size: .76rem; opacity: .85; }
.ts-wrapper.single .ts-control, .ts-wrapper.multi .ts-control { background: var(--field-bg) !important; border-color: var(--field-border) !important; font-weight: 500; padding-top: .66rem; padding-bottom: .66rem; }
.ts-wrapper.single:hover:not(.focus) .ts-control, .ts-wrapper.multi:hover:not(.focus) .ts-control { border-color: color-mix(in srgb, var(--primary) 55%, var(--field-border)) !important; }
.ts-wrapper.single.focus .ts-control, .ts-wrapper.multi.focus .ts-control, .ts-wrapper.single.input-active .ts-control { background: var(--white) !important; border-color: var(--primary) !important; box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 20%, transparent); }
.ts-wrapper .ts-control > input::placeholder { color: var(--hint) !important; font-weight: 400; }
.ts-wrapper.single .ts-control > .item[data-value=""] { color: var(--hint) !important; font-weight: 400; }
/* Chrome paints an input's placeholder with -webkit-text-fill-color, which the typed-text rule above sets dark. */
.ts-wrapper .ts-control > input::placeholder { -webkit-text-fill-color: var(--hint) !important; }
label .opt { font-weight: 400; color: var(--text-muted); font-size: .72rem; letter-spacing: 0; }

/* ─── Section tiles (Notifications, Academy Profile) ───────────────────────────
   One calm tile per section instead of a stack of bars: a single-colour line icon in the theme colour, the
   title with its count, a short description and an arrow. Opening a tile shows that section on its own, with a
   way back. Search at the top narrows the tiles by keyword. */
.tile-search { position: relative; margin-bottom: 1rem; }
.tile-search input { padding-left: 2.5rem; }
.tile-search svg { position: absolute; left: .85rem; top: 50%; transform: translateY(-50%); width: 17px; height: 17px; color: var(--text-muted); pointer-events: none; }
.tile-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .9rem; }
@media (max-width: 760px) { .tile-grid { grid-template-columns: 1fr; } }
.tile { display: flex; align-items: center; gap: 1rem; width: 100%; text-align: left; font: inherit; color: var(--text);
  padding: 1rem 1.1rem; border: 1px solid var(--border); border-radius: 14px; background: #fbf8f3; cursor: pointer;
  box-shadow: 0 1px 2px rgba(15,23,42,.04); transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease; appearance: none; }
:root[data-theme="dark"] .tile { background: var(--card-bg); }
.tile:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); box-shadow: 0 6px 18px rgba(15,23,42,.08); transform: translateY(-1px); }
.tile:focus-visible { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 22%, transparent); }
.tile-icon { flex: none; width: 46px; height: 46px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--primary) 12%, transparent); color: var(--primary); }
.tile-icon svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.tile-text { flex: 1; min-width: 0; }
.tile-title { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; font-weight: 700; font-size: .95rem; line-height: 1.25; }
.tile-title .badge, .tile-title .badge-danger, .tile-title .badge-primary { background: color-mix(in srgb, var(--primary) 14%, transparent) !important; color: var(--primary) !important; border: none !important; }
.tile-desc { margin-top: .2rem; font-size: .8rem; color: var(--text-muted); line-height: 1.4; }
.tile-arrow { flex: none; width: 18px; height: 18px; color: var(--primary); }
.tile-arrow svg { width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.tile-empty { padding: 1.5rem 0; text-align: center; color: var(--text-muted); font-size: .9rem; }
.tile-back { display: inline-flex; align-items: center; gap: .35rem; margin: 0 0 .9rem; padding: .4rem .8rem .4rem .55rem; font: inherit; font-weight: 600; font-size: .85rem;
  color: var(--primary); background: transparent; border: 1px solid transparent; border-radius: 999px; cursor: pointer; appearance: none; }
.tile-back:hover { background: color-mix(in srgb, var(--primary) 10%, transparent); }
.tile-back svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.tile-detail-head { display: flex; align-items: center; gap: .8rem; margin-bottom: 1rem; }
.tile-detail-head h2 { margin: 0; font-size: 1.15rem; font-weight: 800; }
.tile-detail-head .tile-desc { margin-top: .1rem; }
.pager { display: flex; align-items: center; justify-content: space-between; gap: .75rem; margin-top: .9rem; font-size: .84rem; color: var(--text-muted); }
.pager-btns { display: flex; gap: .4rem; }

/* ─── Phones: nothing may be wider than the screen ────────────────────────────
   A grid column written as 1fr cannot shrink below its content, so one long email or one nowrap line stretched
   the whole page and cut the cards off on the right. Columns now shrink, and long words wrap. */
.coachs-layout > *, .rm-layout > *, .help-grid > *, .svc-layout > *, .ex-layout > *, .invoices-layout > *,
.form-row > *, .form-row-3 > * { min-width: 0; }
.card { max-width: 100%; }
@media (max-width: 900px) {
  .page-container .coachs-layout, .page-container .rm-layout, .page-container .help-grid, .page-container .svc-layout, .page-container .ex-layout, .page-container .invoices-layout { grid-template-columns: minmax(0, 1fr); }
}
.data-card-row .dcr-value, .data-card-title, .data-card-meta { min-width: 0; overflow-wrap: anywhere; }
.data-card-row .dcr-value { text-align: right; }
.data-card-row { gap: .75rem; }
.data-card .badge-active, .data-card .badge-inactive, .data-card .badge { white-space: normal; text-align: center; }
.rm-seg { flex-wrap: wrap; max-width: 100%; }
@media (max-width: 760px) { .page-container .ex-split { grid-template-columns: minmax(0, 1fr); } .ex-chart-box { max-width: 100%; } }
.ts-wrapper { max-width: 100%; min-width: 0; }
.ex-chart-box { max-width: 100%; min-width: 0; overflow: hidden; }
.ex-chart-box canvas { max-width: 100% !important; }
@media (max-width: 480px) { .sa-filters { grid-template-columns: minmax(0, 1fr) !important; } .sa-filters > * { min-width: 0; } }
.ex-bar-head { flex-wrap: wrap; gap: .1rem .6rem; min-width: 0; }
.ex-bar-head .nm { min-width: 0; overflow-wrap: anywhere; }

/* Side-by-side fields in a narrow card shrink instead of pushing the second one out of view. */
.svc-two > *, .ex-two > *, .two-col > *, .form-row > *, .form-row-3 > * { min-width: 0; }
.svc-two select, .svc-two .ts-wrapper, .ex-two .ts-wrapper, .two-col .ts-wrapper { max-width: 100%; }

/* ─── Modal (every popup form: add, edit, confirm, report) ──────────────────── */
.modal-overlay {
  display: none; position: fixed; inset: 0; background: rgba(0,0,0,.45);
  z-index: 800; align-items: center; justify-content: center;
  padding: 1rem; backdrop-filter: blur(2px);
}
.modal-overlay.open { display: flex; }
.modal-box {
  background: var(--card-bg); color: var(--text); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  border: 1px solid var(--border); width: 100%; max-width: 520px;
  padding: 1.5rem; position: relative; max-height: 92vh; overflow-y: auto;
}
.modal-title { font-size: 1.05rem; font-weight: 700; margin-bottom: .8rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.modal-close { background: none; border: none; margin: 0; padding: .2rem .5rem; font: inherit; font-size: 1.4rem; line-height: 1; cursor: pointer; color: var(--text-muted); appearance: none; -webkit-appearance: none; }
.modal-close:hover { color: var(--text); }
@media (max-width: 560px) { .modal-box { padding: 1.1rem; max-height: 96vh; } .modal-overlay { padding: .5rem; align-items: flex-end; } }
.modal-actions .btn { min-width: 90px; }
.opt { font-weight: 400; color: var(--text-muted); font-size: .85em; }
/* the chips and small helpers screens share */
.chip { display: inline-block; padding: .12rem .5rem; border-radius: 99px; background: var(--bg-hover); font-size: .74rem; margin: 0 .2rem .2rem 0; }

/* ═══ Forms v2: raised, glowing fields (after Clinically), compact, phone first ═══════════════════════════════════
   Fields look like small physical objects: lifted off the page by an outer shadow, with a soft crease inside the top edge.
   Focus lights them up (amber glow + a one-pixel lift). Everything is sized for a thumb first. */
:root {
  --field-bg: #fbf8f3;
  --field-edge: color-mix(in srgb, var(--primary-dark) 24%, transparent);
  --field-shadow: 0 5px 12px -4px rgba(100, 55, 5, .16), inset 0 2px 3px rgba(100, 55, 5, .12), inset 0 -1px 0 rgba(255, 255, 255, .95);
  --field-glow: 0 0 0 4px color-mix(in srgb, var(--primary) 24%, transparent), 0 0 20px color-mix(in srgb, var(--primary) 30%, transparent);
}
:root[data-theme="dark"] {
  --field-bg: var(--bg-hover);
  --field-edge: rgba(255, 235, 205, .16);
  --field-shadow: 0 5px 12px -4px rgba(0, 0, 0, .5), inset 0 2px 4px rgba(0, 0, 0, .4), inset 0 -1px 0 rgba(255, 255, 255, .06);
}

input[type="text"], input[type="number"], input[type="tel"], input[type="email"], input[type="password"], input[type="date"],
input[type="datetime-local"], input[type="search"], input[type="time"], input[type="url"], input[type="month"], select, textarea,
.dt-display, .ts-wrapper.single .ts-control, .ts-wrapper.multi .ts-control {
  background-color: var(--field-bg) !important;
  border: 1px solid var(--field-edge) !important;
  border-radius: 11px !important;
  box-shadow: var(--field-shadow) !important;
  min-height: 2.45rem;
  padding: .5rem .8rem;
  font-size: .9rem;
  transition: box-shadow .16s ease, border-color .16s ease, transform .16s ease;
}
textarea { min-height: 4.6rem; }
input:hover:not(:focus), select:hover:not(:focus), textarea:hover:not(:focus), .dt-display:hover, .ts-wrapper:not(.focus) .ts-control:hover { border-color: var(--primary-muted) !important; }
input:focus, select:focus, textarea:focus, .dt-display:focus-visible, .dt-field:focus-within .dt-display, .ts-wrapper.focus .ts-control {
  outline: none;
  border-color: var(--primary) !important;
  box-shadow: var(--field-shadow), var(--field-glow) !important;
  transform: translateY(-1px);
}
@media (prefers-reduced-motion: reduce) { input, select, textarea, .dt-display, .ts-control { transition: none !important; transform: none !important; } }
.dt-display { display: flex; align-items: center; justify-content: space-between; text-align: left; }
.dt-display-text:empty::before { content: 'Pick'; color: var(--text-subtle); }
.dt-display svg { color: var(--primary); }
/* The search box inside a styled dropdown shows no second frame, and a chosen value is plain text, not a boxed chip. */
.ts-wrapper.single .ts-control > .item { background: none !important; border: 0 !important; box-shadow: none !important; padding: 0 !important; color: var(--text); font-weight: 500; }
.ts-wrapper.single .ts-control { padding-right: 2rem !important; }
.ts-wrapper.multi .ts-control { padding: .3rem .5rem !important; gap: .25rem; }

/* The grid: every field in a form is a cell, and cells re-flow with the room there is. */
.form-wrap { container-type: inline-size; width: 100%; }
.form-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); grid-auto-flow: row dense; gap: .75rem .7rem; align-items: end; }
.form-grid > .form-group { margin: 0; min-width: 0; }
.form-grid .fg-full, .form-grid .fg-wide { grid-column: span 6; }
.form-grid .fg-short, .form-grid .fg-sel { grid-column: span 3; }
@container (min-width: 440px) {
  .form-grid .fg-wide, .form-grid .fg-sel { grid-column: span 3; }
  .form-grid .fg-short { grid-column: span 2; }
}
.form-grid label { margin-bottom: .25rem; font-size: .78rem; }
.form-grid .form-hint { margin-top: .2rem; }

/* Day chips: all seven days on show; a tap presses a day in (amber, sunk), another tap lifts it back out. */
.daychips { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: .35rem; }
.daychip {
  appearance: none; -webkit-appearance: none; margin: 0; font: inherit; font-size: .8rem; font-weight: 600; cursor: pointer;
  padding: .55rem 0; border-radius: 11px; color: var(--text-muted); background: var(--field-bg);
  border: 1px solid var(--field-edge);
  box-shadow: 0 4px 9px -3px color-mix(in srgb, var(--primary-dark) 30%, transparent), inset 0 1px 0 rgba(255, 255, 255, .9);
  transition: transform .12s ease, box-shadow .12s ease, background .12s ease, color .12s ease;
}
.daychip:hover { border-color: var(--primary-muted); color: var(--text); }
.daychip[aria-pressed="true"] {
  color: var(--on-primary, #fff); border-color: var(--primary-dark);
  background: linear-gradient(160deg, color-mix(in srgb, var(--primary) 82%, #fff), var(--primary) 55%, var(--primary-dark));
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, .35), 0 0 14px color-mix(in srgb, var(--primary) 45%, transparent);
  transform: translateY(1px);
}
.daychip:focus-visible { outline: none; box-shadow: var(--field-glow); }

/* Date and time panel: floats over the form. On a phone it is a bottom sheet. */
.dt-dropdown { position: fixed !important; z-index: 1200 !important; width: 290px; max-width: calc(100vw - 16px); }
@media (max-width: 640px) {
  .dt-dropdown.open {
    top: auto !important; left: 0 !important; right: 0; bottom: 0; width: auto; max-width: none;
    border-radius: 20px 20px 0 0; padding: 1.1rem 1.1rem calc(1.1rem + env(safe-area-inset-bottom));
    box-shadow: 0 0 0 100vmax rgba(15, 23, 42, .4), 0 -10px 30px rgba(0, 0, 0, .25);
  }
  .dt-dropdown .dt-days { gap: .25rem; }
  .dt-day { min-height: 2.5rem; }
}
.dt-day.selected, .dt-month.selected, .dt-year.selected { background: linear-gradient(160deg, color-mix(in srgb, var(--primary) 82%, #fff), var(--primary)); box-shadow: 0 0 12px color-mix(in srgb, var(--primary) 45%, transparent); }

/* Buttons are as wide as their words, never a long bar. */
.btn { width: auto; }
.modal-actions { justify-content: flex-end; }
.modal-box { max-width: min(640px, 100%); }
@media (max-width: 560px) { .modal-actions .btn { min-width: 0; padding-left: 1.2rem; padding-right: 1.2rem; } }

/* Search + filters: a tidy grid, filters side by side instead of one per line. */
.filters { display: grid !important; grid-template-columns: repeat(auto-fit, minmax(126px, 1fr)); gap: .6rem .7rem !important; align-items: end; }
.filters .filter-group { min-width: 0 !important; flex: none !important; }
.filters .filter-group:has([data-q]) { grid-column: 1 / -1; }
@media (min-width: 720px) { .filters .filter-group:has([data-q]) { grid-column: span 2; } }
.filters > :is(button, a, .btn) { justify-self: start; }
.filters .filter-group label { font-size: .7rem; margin-bottom: .2rem; }

/* Phones: tables keep each column as wide as its content and scroll sideways, rather than squeezing words onto four lines. */
@media (max-width: 640px) {
  .table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .data-table { width: max-content; min-width: 100%; }
  .data-table th, .data-table td { padding: .55rem .7rem; white-space: nowrap; }
  .data-table td { max-width: 18rem; overflow: hidden; text-overflow: ellipsis; }
}
.seg-btns { background: var(--field-bg); box-shadow: var(--field-shadow); border-color: var(--field-edge) !important; }
.seg-btns button.on { box-shadow: inset 0 2px 4px rgba(0,0,0,.28); }

/* Hand-built forms (a card or dialog with fields placed straight inside): same packing as formHTML, two or more fields to a row. */
:is(.card, .modal-body, .page-container > form, form):has(> .form-group + .form-group) {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 148px), 1fr)); grid-auto-flow: row dense; gap: .75rem .7rem; align-items: start;
}
:is(.card, .modal-body, form):has(> .form-group + .form-group) > :not(.form-group) { grid-column: 1 / -1; }
:is(.card, .modal-body, form):has(> .form-group + .form-group) > .form-group { margin: 0; min-width: 0; }
:is(.card, .modal-body, form):has(> .form-group + .form-group) > .form-group:is(:has(textarea), :has(.daychips), :has(.ts-wrapper.multi), :has(input[type="checkbox"]), :has(.form-hint), :has(.btn)) { grid-column: 1 / -1; }
.form-two, .form-row, .form-row-3 {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 148px), 1fr)); grid-auto-flow: row dense; gap: .75rem .7rem; align-items: start; margin-bottom: .9rem;
}
.form-two > .form-group, .form-row > .form-group, .form-row-3 > .form-group { margin: 0; min-width: 0; }
.form-two > .form-group:is(:has(textarea), :has(.daychips), :has(.ts-wrapper.multi), :has(input[type="checkbox"]), :has(.form-hint)) { grid-column: 1 / -1; }
@media (max-width: 479px) { .filters { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; } }
.filters > :is(button, .btn) { min-width: 0; }
.form-two > .form-wrap, .form-row > .form-wrap, .form-row-3 > .form-wrap { grid-column: 1 / -1; }

/* ═══ Theme engine (see shared/js/theme.js) ═════════════════════════════════════════════════════════════════════
   Only active once an owner or admin has saved a look: theme.js then sets html[data-tm] plus the variables and
   data-t* switches below. Nothing here touches an academy that has not chosen a look. */
:root[data-tm] { font-size: var(--fs, 16px); }
:root[data-tm] body { font-family: var(--font-body); font-size: 1rem; font-weight: 400; background-color: var(--bg); background-image: none; animation: none; color: var(--text); }
:root[data-tm] :is(h1, h2, h3, h4, .page-title, .card-title, .navbar-brand, .stat-value, .data-card-title, .modal-title, .hero h1) { font-family: var(--font-head); letter-spacing: -.01em; }
:root[data-tm] :is(input, select, textarea, button) { font-family: var(--font-body); }

/* page background */
:root[data-tm][data-tg="soft"] body { background-image: linear-gradient(180deg, color-mix(in srgb, var(--primary) 9%, var(--bg)) 0, var(--bg) 460px); background-repeat: no-repeat; background-attachment: scroll; }
:root[data-tm][data-tg="aurora"] body {
  background-image: radial-gradient(60rem 38rem at 100% -8%, color-mix(in srgb, var(--primary) 26%, transparent), transparent 62%),
                    radial-gradient(52rem 34rem at -6% 40%, color-mix(in srgb, var(--secondary) 20%, transparent), transparent 64%),
                    radial-gradient(46rem 30rem at 70% 110%, color-mix(in srgb, var(--primary) 16%, transparent), transparent 66%);
  background-attachment: fixed; background-repeat: no-repeat;
}
:root[data-tm][data-tg="dots"] body { background-image: radial-gradient(color-mix(in srgb, var(--text) 16%, transparent) 1.3px, transparent 1.6px); background-size: 20px 20px; background-attachment: scroll; }
:root[data-tm][data-tg="grid"] body {
  background-image: linear-gradient(color-mix(in srgb, var(--text) 9%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--text) 9%, transparent) 1px, transparent 1px);
  background-size: 28px 28px; background-attachment: scroll;
}

/* banner */
:root[data-tm] .hero { background: linear-gradient(118deg, var(--banner-1), var(--banner-2)); }
:root[data-tm][data-tn="solid"] .hero { background: var(--banner-1); }
:root[data-tm][data-tn="solid"] .hero::before, :root[data-tm][data-tn="solid"] .hero::after { display: none; }
/* banner text: white on a dark banner, near-black on a light one (the yellow Bold Block banner) */
:root[data-tm] .hero :is(h1, .hero-tag, #academy-title, #brand-tagline) { color: var(--on-banner, #fff); }

/* navigation bar */
:root[data-tm] .navbar { background: var(--card-bg); border: 1px solid var(--border); box-shadow: 0 8px 22px -10px color-mix(in srgb, var(--text) 35%, transparent); }
:root[data-tm] :is(.navbar-brand, .navbar-links a, .navbar-links summary) { color: var(--text-muted); }
:root[data-tm] :is(.navbar-links a, .navbar-links summary):hover { background: var(--primary-light); color: var(--primary); }
:root[data-tm] :is(.navbar-links a.active, .nav-group.has-active > details > summary) { background: var(--btn-bg); color: var(--btn-fg); box-shadow: 0 6px 14px -6px var(--btn-bg); }
:root[data-tm] .nav-group-menu { background: var(--card-bg); border-color: var(--border); }
:root[data-tm] .navbar-links a.nav-logout { color: var(--danger); }
:root[data-tm] :is(.navbar-links a, .navbar-links summary) { border-radius: var(--btn-radius, 10px); }

/* cards */
:root[data-tm] :is(.card, .chart-wrap, .filters, .table-wrap, .data-card, .metric-card, .stat-card, .modal-box, .dt-dropdown) {
  background: var(--card-bg); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: none; color: var(--text);
}
:root[data-tm][data-tc="flat"] :is(.card, .chart-wrap, .table-wrap, .data-card, .metric-card, .stat-card) { border-color: transparent; background: color-mix(in srgb, var(--card-bg) 82%, var(--bg)); }
:root[data-tm][data-tc="raised"] :is(.card, .chart-wrap, .table-wrap, .data-card, .metric-card, .stat-card) { box-shadow: 0 14px 30px -14px color-mix(in srgb, var(--text) 38%, transparent), 0 2px 5px color-mix(in srgb, var(--text) 8%, transparent); }
:root[data-tm][data-tc="glass"] :is(.card, .chart-wrap, .table-wrap, .data-card, .metric-card, .stat-card, .filters) {
  background: color-mix(in srgb, var(--card-bg) 58%, transparent); -webkit-backdrop-filter: blur(16px) saturate(1.5); backdrop-filter: blur(16px) saturate(1.5);
  border: 1px solid color-mix(in srgb, #fff 55%, transparent); box-shadow: 0 16px 36px -16px color-mix(in srgb, var(--text) 40%, transparent);
}
:root[data-tm][data-tc="brutal"] :is(.card, .chart-wrap, .table-wrap, .data-card, .metric-card, .stat-card, .modal-box) { border: 2px solid var(--border); box-shadow: 5px 5px 0 var(--border); }
:root[data-tm][data-tc="brutal"] .modal-box { box-shadow: 8px 8px 0 var(--border); }
:root[data-tm] .filters { background: color-mix(in srgb, var(--card-bg) 70%, var(--bg)); box-shadow: none; }
:root[data-tm] :is(thead th, .data-table th) { background: var(--th-bg); color: var(--th-text); }
:root[data-tm] tbody tr:hover td { background: var(--primary-light); }

/* buttons */
:root[data-tm] .btn { border-radius: var(--btn-radius); }
:root[data-tm] :is(.btn-primary, .btn-success-dark) {
  background: var(--btn-bg); color: var(--btn-fg); border: var(--btn-bw) solid var(--btn-bd);
  box-shadow: 0 8px 18px -8px color-mix(in srgb, var(--btn-bg) 80%, transparent);
}
:root[data-tm] .btn-primary:hover { background: color-mix(in srgb, var(--btn-bg) 90%, #000); box-shadow: 0 12px 24px -8px color-mix(in srgb, var(--btn-bg) 85%, transparent); }
:root[data-tm][data-tb="gradient"] .btn-primary { background: linear-gradient(135deg, var(--btn-bg), color-mix(in srgb, var(--btn-bg) 52%, var(--secondary))); }
:root[data-tm][data-tb="gradient"] .btn-primary:hover { background: linear-gradient(135deg, color-mix(in srgb, var(--btn-bg) 92%, #fff), color-mix(in srgb, var(--btn-bg) 45%, var(--secondary))); }
:root[data-tm][data-tb="outline"] .btn-primary { background: transparent; color: var(--btn-bg); border: max(var(--btn-bw), 2px) solid var(--btn-bg); box-shadow: 0 0 16px -6px var(--btn-bg); }
:root[data-tm][data-tb="outline"] .btn-primary:hover { background: var(--btn-bg); color: var(--btn-fg); }
:root[data-tm][data-tb="soft"] .btn-primary { background: color-mix(in srgb, var(--btn-bg) 15%, var(--card-bg)); color: var(--btn-bg); box-shadow: none; border-color: transparent; font-weight: 600; }
:root[data-tm][data-tb="soft"] .btn-primary:hover { background: color-mix(in srgb, var(--btn-bg) 26%, var(--card-bg)); }
:root[data-tm][data-tb="raised"] .btn-primary {
  background: linear-gradient(180deg, color-mix(in srgb, var(--btn-bg) 84%, #fff), var(--btn-bg));
  box-shadow: 0 5px 0 color-mix(in srgb, var(--btn-bg) 62%, #000), 0 12px 18px -6px color-mix(in srgb, var(--btn-bg) 60%, transparent), inset 0 1px 0 rgba(255,255,255,.4);
  transform: translateY(-2px);
}
:root[data-tm][data-tb="raised"] .btn-primary:active { transform: translateY(3px); box-shadow: 0 1px 0 color-mix(in srgb, var(--btn-bg) 62%, #000); }
:root[data-tm][data-tb="brutal"] .btn-primary { border: 2px solid var(--btn-bd); box-shadow: 4px 4px 0 var(--btn-bd); }
:root[data-tm][data-tb="brutal"] .btn-primary:hover { transform: translate(-1px, -1px); box-shadow: 6px 6px 0 var(--btn-bd); background: var(--btn-bg); }
:root[data-tm][data-tb="brutal"] .btn-primary:active { transform: translate(3px, 3px); box-shadow: 1px 1px 0 var(--btn-bd); }
:root[data-tm] .btn-outline { background: transparent; color: var(--text); border: max(var(--btn-bw), 1.5px) solid var(--border); box-shadow: none; }
:root[data-tm] .btn-outline:hover { border-color: var(--btn-bg); color: var(--btn-bg); background: var(--primary-light); }
:root[data-tm][data-tb="brutal"] .btn-outline { border: 2px solid var(--btn-bd); box-shadow: 3px 3px 0 var(--btn-bd); }

/* fields */
:root[data-tm] :is(input[type="text"], input[type="number"], input[type="tel"], input[type="email"], input[type="password"], input[type="date"], input[type="search"], input[type="time"], input[type="url"], select, textarea, .dt-display, .ts-wrapper.single .ts-control, .ts-wrapper.multi .ts-control) {
  background-color: var(--field-bg) !important; color: var(--text); border-color: var(--field-edge) !important; border-radius: var(--radius-sm) !important;
}
:root[data-tm] :is(input, select, textarea):focus, :root[data-tm] .dt-field:focus-within .dt-display, :root[data-tm] .ts-wrapper.focus .ts-control {
  border-color: var(--primary) !important; box-shadow: var(--field-shadow), 0 0 0 4px var(--theme-ring), 0 0 20px var(--theme-ring) !important;
}
:root[data-tm][data-tf="flat"] :is(input[type="text"], input[type="number"], input[type="tel"], input[type="email"], input[type="password"], input[type="date"], input[type="search"], input[type="time"], input[type="url"], select, textarea, .dt-display, .ts-wrapper.single .ts-control, .ts-wrapper.multi .ts-control) { box-shadow: none !important; }
:root[data-tm][data-tf="line"] :is(input[type="text"], input[type="number"], input[type="tel"], input[type="email"], input[type="password"], input[type="date"], input[type="search"], input[type="time"], input[type="url"], select, textarea, .dt-display, .ts-wrapper.single .ts-control, .ts-wrapper.multi .ts-control) {
  background-color: transparent !important; box-shadow: none !important; border-width: 0 0 2px 0 !important; border-radius: 0 !important; padding-left: .1rem;
}
:root[data-tm] .daychip { border-radius: var(--radius-sm); }
:root[data-tm] .daychip[aria-pressed="true"] { background: var(--btn-bg); color: var(--btn-fg); border-color: var(--btn-bd); }
:root[data-tm][data-tb="brutal"] .daychip[aria-pressed="true"] { box-shadow: 3px 3px 0 var(--btn-bd); transform: none; }
:root[data-tm] .tab-btn.active { color: var(--primary); border-color: var(--primary); }
:root[data-tm] :is(.badge, .chip) { border-radius: var(--btn-radius); }
