/* =========================================================================
   College Connect — Monochrome frosted glass (white / grey / charcoal only)
   Visible frosted panels over a soft grey wash. Re-skin via :root.
   ========================================================================= */

/* =========================================================================
   FONTS — self-hosted (was Google Fonts). Variable woff2 in web/fonts/,
   subset by unicode-range exactly as Google serves them, so the latin-ext
   file is fetched only when a glyph actually needs it (the common English
   path loads just the two "latin" files). font-display:swap paints text
   immediately in the fallback, then swaps. Self-hosting removes a render-
   blocking third-party request and lets these cache immutably on our edge.
   ========================================================================= */
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('fonts/jakarta.latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Plus Jakarta Sans';
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url('fonts/jakarta.latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('fonts/fraunces.latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url('fonts/fraunces.latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Fraunces';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/fraunces-italic.latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Fraunces';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url('fonts/fraunces-italic.latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  /* =========================================================================
     College Connect design tokens — espresso · gilt · ivory.
     Editorial-luxury: deep roasted browns, ivory paper, scarce precious gold.
     ========================================================================= */

  /* ---- Brand: espresso is the workhorse for primary actions ---- */
  --accent: #6a4126;
  --accent-2: #4a2c18;            /* deeper espresso — gradient feet, hovers */
  --accent-3: #855536;            /* lighter espresso — gradient heads */
  --accent-soft: rgba(106, 65, 38, 0.09);
  --accent-ring: rgba(106, 65, 38, 0.28);

  /* ---- Gilt: the "money" accent. Used scarcely — a hairline, an active
     indicator, one key number. Never as a broad fill. ---- */
  --gold: #b88a3e;
  --gold-2: #d8b061;
  --gold-soft: rgba(184, 138, 62, 0.14);
  --gold-line: rgba(184, 138, 62, 0.38);   /* thin gilt hairline / frame */

  /* ---- Status — leaf green / coral red (tuned a touch deeper for contrast) -- */
  --ok: #5a8233;
  --ok-soft: rgba(95, 138, 55, 0.14);
  --fault: #bd433a;
  --fault-soft: rgba(194, 70, 59, 0.11);
  --danger: #b94038;
  --danger-soft: rgba(190, 68, 57, 0.11);
  --warn: #9c6b1a;
  --warn-soft: rgba(199, 154, 62, 0.16);

  /* ---- Ink — secondary/tertiary darkened to clear AA on ivory ---- */
  --text: #271b10;
  --text-1: #271b10;
  --text-2: #50402f;             /* secondary text (was #6b594c) */
  --muted: #6f5d4c;              /* tertiary / labels (was #9b897a) */
  --faint: #a99a87;              /* decorative only — placeholders, caret arrows */

  /* ---- Warm frosted (ivory) glass ---- */
  --glass: rgba(255, 252, 245, 0.58);
  --glass-2: rgba(255, 252, 245, 0.72);
  --glass-3: rgba(255, 251, 244, 0.90);
  --card: rgba(255, 253, 248, 0.66);
  --stroke: rgba(255, 255, 255, 0.80);
  --hairline: rgba(74, 50, 30, 0.10);
  --hairline-2: rgba(74, 50, 30, 0.16);
  --selection: rgba(106, 65, 38, 0.16);

  /* ---- Radius ladder: one consistent set (20 / 14 / 10) ---- */
  --radius: 20px;
  --radius-sm: 14px;
  --radius-xs: 10px;

  /* ---- Elevation: 3 diffuse levels (resting / raised / overlay).
     Soft, large, low-opacity — diffuse light reads as luxury. ---- */
  --shadow-sm: 0 1px 2px rgba(58, 38, 22, 0.05), 0 6px 16px rgba(58, 38, 22, 0.06);
  --shadow: 0 2px 6px rgba(58, 38, 22, 0.05), 0 16px 38px rgba(58, 38, 22, 0.09);
  --shadow-lg: 0 4px 12px rgba(58, 38, 22, 0.06), 0 30px 70px rgba(58, 38, 22, 0.13);
  --shadow-gold: 0 6px 18px rgba(120, 86, 30, 0.16);

  --blur: 22px;

  /* ---- Spacing: strict 8px system (with a 4px half-step) ---- */
  --space-1: 4px;  --space-2: 8px;   --space-3: 12px;  --space-4: 16px;
  --space-5: 24px; --space-6: 32px;  --space-7: 48px;  --space-8: 64px;
  --space: 8px;                  /* legacy alias */

  /* ---- Type scale: ~1.2 modular, rem-anchored to a 16px root ---- */
  --fs-eyebrow: 0.6875rem;       /* 11 */
  --fs-xs: 0.75rem;              /* 12 */
  --fs-sm: 0.8125rem;            /* 13 */
  --fs-base: 0.875rem;           /* 14 */
  --fs-md: 1rem;                 /* 16 */
  --fs-lg: 1.1875rem;            /* 19 */
  --fs-xl: 1.5rem;               /* 24 */
  --fs-2xl: 1.875rem;            /* 30 */
  --fs-3xl: 2.25rem;             /* 36 */
  --tracking-eyebrow: 0.12em;

  /* ---- Motion: one duration, one signature easing ---- */
  --dur: 180ms;
  --ease: cubic-bezier(.2, .7, .2, 1);

  --font: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-display: "Fraunces", "Plus Jakarta Sans", Georgia, serif;

  /* =========================================================================
     THEME LAYER — everything below is overridable per palette via
     [data-theme="…"] (see the THEMES block near the end of this file). These
     are the ESPRESSO (default) values, so :root alone renders the original
     warm look unchanged. js/theme.js sets data-theme on <html> before paint.
     ========================================================================= */

  /* Surface fills — the inner tints layered on glass panels (tiles, inputs,
     chips, hovers). Tokenised so DARK themes can dial white-on-dark right down
     (a 0.55 white that lifts a light panel would blow out a dark one). White
     sheen ON coloured elements — buttons, bed bars — stays literal, not these. */
  --fill-1: rgba(255,255,255,.45);     /* weakest: option-ish / faint panels  */
  --fill-2: rgba(255,255,255,.55);     /* standard surface (most common)      */
  --fill-3: rgba(255,255,255,.74);     /* raised (card hovers)                */
  --fill-strong: rgba(255,255,255,.95); /* hover / active / selected          */
  --inset-hi: rgba(255,255,255,.85);   /* top inset highlight on frosted glass */
  --on-fill: #fff;                     /* text/icon on accent & status FILLS.
     White on dark/mid fills (light themes); the dark themes flip this to a near
     -black ink because their accents are bright (white-on-cyan would be illegible). */
  --opt-bg: #fffdf8;                   /* native <option> list (needs solid)   */
  --ink-wash: rgba(28,30,45,0.04);     /* faint ink wash (bed chips)           */
  --ink-wash-2: rgba(28,30,45,0.08);   /* stronger ink wash (× close buttons)  */
  --gilt-ring: rgba(216,176,97,0.28);  /* the gold inner-ring sheen            */
  --scrollbar: rgba(106,65,38,0.20);
  --scrollbar-h: rgba(106,65,38,0.34);
  --overlay: rgba(44,30,18,0.32);      /* modal / mobile-drawer scrim          */
  --island-bg: #f8f3e8;                /* opaque island panels (opt out of blur) */
  --skel-base: rgba(106,65,38,0.08);
  --skel-sweep: rgba(255,252,245,0.55);

  /* Backdrop — the page wash + drifting blobs + paper grain. */
  --body-bg: #efe6d6;
  --bg-grad:
    radial-gradient(1100px 820px at 14% -5%, #fdf8ee 0%, transparent 58%),
    radial-gradient(900px 700px at 100% 0%, #f5ecdc 0%, transparent 55%),
    linear-gradient(168deg, #fbf5ec 0%, #f2e9da 60%, #ece0cd 100%);
  --blob-1: #f6e6d2; --blob-2: #eedcba; --blob-3: #fbf0df; --blob-4: #f1ddcf;
  --grain-opacity: 0.022;
  --grain-blend: multiply;

  /* Login hero gradient (scarce gilt + espresso wash). */
  --brand-grad:
    radial-gradient(420px 320px at 80% 10%, rgba(216,176,97,0.20) 0%, transparent 60%),
    linear-gradient(160deg, rgba(106,65,38,0.13) 0%, rgba(184,138,62,0.16) 100%);

  /* Bed status (blue=empty · red=full · amber=reserved) stays literal: it's
     saturated solid fills with white text, so it reads on any backdrop. */

  /* Select dropdown caret (stroke colour baked in per theme = --muted). */
  --caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%236f5d4c' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><path d='M4 6l4 4 4-4'/></svg>");
}

* { box-sizing: border-box; margin: 0; padding: 0; }
/* Generic show/hide hook for JS classList toggles (print chooser, the Add-rooms
   Custom section, …). !important so it wins over any display rule. */
.hidden { display: none !important; }
html, body { height: 100%; overflow: hidden; }
body {
  font-family: var(--font);
  color: var(--text);
  background: var(--body-bg);
  -webkit-font-smoothing: antialiased;
  user-select: none;
}

/* ---- Warm ivory backdrop with soft cream/gold shapes for richness -------- */
.bg {
  position: fixed; inset: 0; z-index: 0; overflow: hidden;
  /* Calmer surface: two soft ivory washes + a quiet diagonal. Gold removed from
     the backdrop so the gilt stays scarce and precious in the UI itself. */
  background: var(--bg-grad);
}
/* Fine paper grain overlay — tactile printed-stationery richness, dialed back. */
.bg::after {
  content: ""; position: absolute; inset: -50%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  opacity: var(--grain-opacity); pointer-events: none; mix-blend-mode: var(--grain-blend);
}
/* Drifting light — quieter and slower, so content sits on a still surface. */
.blob { position: absolute; border-radius: 50%; filter: blur(92px); animation: drift 54s ease-in-out infinite; }
.blob-1 { width: 460px; height: 460px; background: var(--blob-1); opacity: 0.34; top: -130px; left: -70px; }
.blob-2 { width: 400px; height: 400px; background: var(--blob-2); opacity: 0.24; top: 4%; right: -110px; animation-delay: -14s; }
.blob-3 { width: 480px; height: 480px; background: var(--blob-3); opacity: 0.40; bottom: -200px; left: 26%; animation-delay: -28s; }
.blob-4 { width: 320px; height: 320px; background: var(--blob-4); opacity: 0.22; bottom: -120px; right: 12%; animation-delay: -7s; }
@keyframes drift {
  0%, 100% { transform: translate(0, 0); }
  50% { transform: translate(22px, 16px); }
}

#root { position: relative; z-index: 1; height: 100vh; }

/* ---- Glass utility ------------------------------------------------------ */
.glass {
  background: var(--glass);
  backdrop-filter: blur(var(--blur)) saturate(120%);
  -webkit-backdrop-filter: blur(var(--blur)) saturate(120%);
  border: 1px solid var(--stroke);
  box-shadow: var(--shadow), inset 0 1px 0 var(--inset-hi);
}

::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 8px;
  border: 3px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-h); background-clip: content-box; }
* { scrollbar-color: var(--scrollbar) transparent; }

/* =========================================================================
   TYPOGRAPHY — Fraunces display serif for headings; gilt optical sizing
   ========================================================================= */
.login-brand h1, .login-form h2, .page-head h1, .side-brand .t1,
.stat .num, .modal h3, .detail h3, .camp-head .nm,
.profile-row .nm, .counter .big, .fc-num, h3.island-title, .co-year-title {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 600;
  letter-spacing: -0.2px;
}
.page-head h1, .login-brand h1 { font-weight: 600; letter-spacing: -0.4px; }
.stat .num, .counter .big, .fc-num { font-weight: 600; letter-spacing: -0.5px; }

/* =========================================================================
   LOGIN
   ========================================================================= */
.login { height: 100vh; display: grid; place-items: center; padding: 24px;
  overflow-y: auto; }   /* scroll if the card is taller than the viewport */
.login-card {
  width: 860px; max-width: 96vw; border-radius: var(--radius);
  display: grid; grid-template-columns: 1fr 1fr; overflow: hidden;
}
.login-brand {
  padding: 48px 44px; position: relative;
  background: var(--brand-grad);
  border-right: 1px solid var(--gold-line);
  display: flex; flex-direction: column; justify-content: center;
}
.login-brand .lead { font-family: var(--font-display); font-style: italic; font-weight: 500; }
.login-form { padding: 48px 44px; display: flex; flex-direction: column; justify-content: center; }
.brand-badge {
  width: 132px; height: 132px; border-radius: 28px; display: grid; place-items: center;
  background: #fff; color: #fff; margin-bottom: 26px;
  box-shadow: var(--shadow), inset 0 0 0 1px var(--gold-line);
  overflow: hidden; padding: 10px;
}
.brand-logo { width: 100%; height: 100%; object-fit: contain; display: block; }
.login-brand h1 { font-size: 31px; font-weight: 600; letter-spacing: -0.5px; }
.login-brand .lead { color: var(--text-2); font-size: 15px; margin-top: 8px; font-weight: 500; }
.login-brand p { color: var(--muted); font-size: 13px; margin-top: 16px; line-height: 1.6; }

.eyebrow { font-size: 11px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--muted); }
.login-form h2 { font-size: 22px; font-weight: 700; margin: 6px 0 26px; letter-spacing: -0.3px; }

/* =========================================================================
   FORM CONTROLS
   ========================================================================= */
label.field { display: block; font-size: 12px; font-weight: 600; color: var(--text-2); margin: 14px 0 6px; }
.input, .select, textarea.input {
  width: 100%; height: 44px; padding: 0 14px; color: var(--text); font-family: var(--font);
  font-size: 14px; border-radius: var(--radius-xs); outline: none;
  background: var(--fill-2); border: 1px solid var(--hairline-2);
  transition: border-color .15s, box-shadow .15s, background .15s;
}
textarea.input { height: 78px; padding: 12px 14px; resize: none; line-height: 1.5; }
.input::placeholder { color: var(--faint); }
.input:focus, .select:focus, textarea.input:focus {
  border-color: var(--accent); background: var(--fill-strong);
  box-shadow: 0 0 0 4px var(--accent-soft);
}
.select { appearance: none; cursor: pointer;
  background-image: var(--caret);
  background-repeat: no-repeat; background-position: right 14px center; padding-right: 38px; }
.select option { background: var(--opt-bg); color: var(--text); }

.error-msg { color: var(--fault); font-size: 12.5px; min-height: 18px; margin: 10px 0 4px; }

.infobox { margin-top: 24px; padding: 14px 16px; border-radius: var(--radius-xs);
  background: var(--fill-1); border: 1px solid var(--hairline); display: flex; gap: 10px;
  color: var(--muted); font-size: 12px; line-height: 1.7; }
.infobox svg { flex: none; margin-top: 1px; color: var(--faint); }
.infobox b { color: var(--text-2); }

/* =========================================================================
   BUTTONS  (charcoal solid for actions, grey ghost for secondary)
   ========================================================================= */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; padding: 0 18px; border-radius: var(--radius-xs); border: 1px solid transparent;
  font-family: var(--font); font-size: 13.5px; font-weight: 700; cursor: pointer;
  transition: transform .08s, filter .15s, background .15s, border-color .15s; white-space: nowrap;
}
.btn { letter-spacing: .2px; }
.btn:active { transform: translateY(1px); }
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-ring); }
.btn svg { width: 16px; height: 16px; }
.btn-primary { color: var(--on-fill);
  background: linear-gradient(180deg, var(--accent-3) 0%, var(--accent) 100%);
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255,255,255,.18),
              inset 0 0 0 1px var(--gilt-ring); }
.btn-primary:hover { transform: translateY(-1px);
  background: linear-gradient(180deg, var(--accent) 0%, var(--accent-2) 100%);
  box-shadow: var(--shadow), inset 0 1px 0 rgba(255,255,255,.20),
              inset 0 0 0 1px var(--gilt-ring); }
.btn-primary:active { transform: translateY(0); }
.btn-danger { color: var(--on-fill); background: var(--danger); box-shadow: var(--shadow-sm); }
.btn-danger:hover { filter: brightness(1.06); }
.btn-success { color: var(--on-fill); background: var(--ok); box-shadow: var(--shadow-sm); }
.btn-success:hover { filter: brightness(1.06); }
.btn-block { width: 100%; }
/* Prominent full-width action buttons inside the student detail modal. */
.btn-det { height: 50px; font-size: 14.5px; margin-top: 12px; }
.btn-det svg { width: 18px; height: 18px; }

/* Admin password-change audit log (modal list). */
.pwlog { margin-top: 6px; max-height: 56vh; overflow: auto; display: flex;
  flex-direction: column; gap: 2px; }
.pwlog-row { display: flex; align-items: center; gap: 12px; padding: 9px 4px;
  border-bottom: 1px solid var(--hairline); }
.pwlog-row:last-child { border-bottom: none; }
.pwlog-row .nm { font-size: 13.5px; font-weight: 700; color: var(--text); }
.pwlog-row .sub { font-size: 12px; margin-top: 2px; }
.btn-ghost { color: var(--text); background: var(--fill-2); border-color: var(--hairline-2); }
.btn-ghost:hover { background: var(--fill-strong); }
.btn-danger-ghost { color: var(--text); background: var(--fill-2); border-color: var(--hairline-2);
  height: 34px; padding: 0 12px; font-size: 12.5px; }
.btn-danger-ghost:hover { background: var(--fill-strong); border-color: var(--accent); }

/* =========================================================================
   APP SHELL
   ========================================================================= */
.app { display: grid; grid-template-columns: 248px 1fr; height: 100vh; padding: 16px; gap: 16px; }

.sidebar { border-radius: var(--radius); padding: 20px 14px; display: flex; flex-direction: column; }
.side-brand { display: flex; align-items: center; gap: 13px; padding: 6px 8px 18px; }
.side-brand .badge { width: 56px; height: 56px; border-radius: 15px; display: grid; place-items: center;
  background: #fff; color: #fff; box-shadow: var(--shadow-sm), inset 0 0 0 1px var(--gold-line);
  overflow: hidden; flex: none; padding: 5px; }
.side-brand .t1 { font-size: 19px; font-weight: 800; letter-spacing: -0.3px; line-height: 1.15; }
.side-brand .t2 { font-size: 11.5px; color: var(--muted); margin-top: 1px; }
.side-section { font-size: 10.5px; font-weight: 800; letter-spacing: 1.8px; color: var(--text-2);
  text-transform: uppercase; padding: 14px 12px 8px; }

.nav-item { display: flex; align-items: center; gap: 12px; padding: 11px 12px; border-radius: var(--radius-xs);
  color: var(--text-2); font-size: 14px; font-weight: 500; cursor: pointer; position: relative;
  transition: background .15s, color .15s; margin-bottom: 4px; }
.nav-item svg { width: 19px; height: 19px; opacity: .75; }
.nav-item:hover { background: var(--fill-2); color: var(--text); }
.nav-item.active { background: var(--fill-strong); color: var(--text); font-weight: 700; box-shadow: var(--shadow-sm); }
.nav-item.active svg { color: var(--accent); opacity: 1; }
.nav-item.active::before { content: ""; position: absolute; left: -14px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 22px; border-radius: 4px;
  background: linear-gradient(180deg, var(--gold-2), var(--accent)); }

.side-foot { margin-top: auto; }
.user-card { display: flex; align-items: center; gap: 12px; padding: 12px; border-radius: var(--radius-xs);
  background: var(--fill-2); border: 1px solid var(--hairline); margin-bottom: 12px; }
.avatar { width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; flex: none;
  background: linear-gradient(155deg, var(--accent-3), var(--accent-2)); color: var(--on-fill);
  font-weight: 700; font-size: 13px; font-family: var(--font-display);
  box-shadow: inset 0 0 0 1px var(--gilt-ring), var(--shadow-sm); }
.user-card .nm { font-size: 13px; font-weight: 700; }
.user-card .rl { font-size: 11px; color: var(--muted); }

.main { border-radius: var(--radius); padding: 28px 30px; overflow: auto;
  overscroll-behavior-y: contain; }
.page-head { margin-bottom: 24px; }
.page-head h1 { font-size: 30px; line-height: 1.12; }
.page-head .sub { color: var(--text-2); font-size: 14px; margin-top: 5px; }

/* ---- Stat cards --------------------------------------------------------- */
.stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 22px; }
.stat { border-radius: var(--radius-sm); padding: 18px 20px; display: flex; align-items: center; gap: 16px; }
.stat .chip { width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center; flex: none;
  background: var(--accent-soft); color: var(--accent); }
.stat .num { font-size: 27px; font-weight: 800; letter-spacing: -0.5px; line-height: 1; }
.stat .lbl { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .5px; margin-top: 6px; }
.chip-accent { background: var(--accent-soft); color: var(--accent); }
.chip-ok { background: var(--ok-soft); color: var(--ok); }
.chip-danger { background: var(--danger-soft); color: var(--danger); }
.chip-warn { background: var(--warn-soft); color: var(--warn); }
/* Gilt icon medallions — only the accent-coloured chips, so status chips
   (.chip-ok / .chip-danger / .chip-warn) keep their own colours. */
.stat .chip.chip-accent, .mod-tile .chip, .camp-head .chip,
.counter .chip, .chip-sm {
  background: linear-gradient(155deg, var(--gold-soft) 0%, var(--accent-soft) 72%);
  box-shadow: inset 0 0 0 1px var(--gold-line); color: var(--accent); }

/* ---- AC layout ---------------------------------------------------------- */
.ac-toolbar { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; }
.ac-toolbar .select { width: 170px; height: 40px; }
.legend { margin-left: auto; display: flex; gap: 16px; }
.legend span { display: inline-flex; align-items: center; gap: 7px; color: var(--muted); font-size: 12px; }
.legend .dot { width: 9px; height: 9px; border-radius: 50%; }

.ac-body { display: grid; grid-template-columns: 1fr 360px; gap: 18px; align-items: start; }
.grid-card { border-radius: var(--radius-sm); padding: 16px; max-height: calc(100vh - 320px); overflow: auto; }
.floor-title { font-size: 14px; font-weight: 700; color: var(--text-2); margin: 14px 4px 10px; }
.floor-title:first-child { margin-top: 4px; }
.tiles { display: flex; flex-wrap: wrap; gap: 10px; }

.tile { width: 120px; border-radius: var(--radius-xs); padding: 12px 13px; cursor: pointer;
  background: var(--fill-2); border: 1px solid var(--hairline);
  transition: transform .12s, background .15s, border-color .15s, box-shadow .15s; }
.tile:hover { transform: translateY(-2px); background: var(--fill-strong); box-shadow: var(--shadow-sm); }
.tile .row { display: flex; align-items: center; gap: 8px; }
.tile .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.tile .no { font-size: 16px; font-weight: 800; letter-spacing: -0.3px; }
.tile .st { font-size: 11px; color: var(--text-2); margin-top: 6px; line-height: 1.3; }
.tile.fault { background: var(--fault-soft); border-color: var(--hairline-2); }
.tile.fault .st { color: var(--danger); font-weight: 600; }
.tile.selected { border-color: var(--accent); background: var(--fill-strong);
  box-shadow: 0 0 0 1px var(--accent-ring); }
.dot-ok { background: var(--ok); }
.dot-fault { background: var(--fault); }

/* ---- Detail panel ------------------------------------------------------- */
.detail { border-radius: var(--radius-sm); padding: 22px; max-height: calc(100vh - 320px); overflow: auto; }
.detail h3 { font-size: 20px; font-weight: 800; letter-spacing: -0.3px; }
.detail .meta { color: var(--muted); font-size: 12px; margin-top: 2px; }
.divider { height: 1px; background: var(--hairline); margin: 18px 0; }

.pill { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 999px;
  font-size: 11.5px; font-weight: 700; }
.pill svg { width: 13px; height: 13px; }
.pill-ok { background: var(--ok-soft); color: var(--ok); }
.pill-danger { background: var(--danger-soft); color: var(--danger); }
.pill-warn { background: var(--warn-soft); color: var(--warn); }
.pill-accent { background: var(--accent-soft); color: var(--accent); }

.counter { display: flex; align-items: center; gap: 14px; padding: 14px 16px; border-radius: var(--radius-xs);
  background: var(--fill-2); border: 1px solid var(--hairline); }
.counter .chip { width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center; flex: none;
  background: var(--accent-soft); color: var(--accent); }
.counter .big { font-size: 20px; font-weight: 800; }
.counter .cap { font-size: 11px; color: var(--muted); }
.problemcounts { margin-top: 12px; }
.problemcounts .pc { display: flex; justify-content: space-between; font-size: 12px; padding: 4px 0; color: var(--text-2); }
.problemcounts .pc b { color: var(--text); }

.detail h4 { font-size: 15px; font-weight: 700; margin-bottom: 4px; }
.hist { background: var(--fill-2); border: 1px solid var(--hairline); border-radius: var(--radius-xs);
  padding: 12px 14px; margin-top: 8px; }
.hist .top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.hist .pr { font-size: 13px; font-weight: 700; }
.hist .notes { font-size: 12px; color: var(--text-2); margin-top: 6px; line-height: 1.5; }
.hist .by { font-size: 11px; color: var(--muted); margin-top: 6px; line-height: 1.6; }

/* ---- Empty state -------------------------------------------------------- */
.empty { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 50px 20px; }
.empty .ec { width: 62px; height: 62px; border-radius: 18px; display: grid; place-items: center;
  background: var(--fill-2); border: 1px solid var(--hairline); color: var(--muted); margin-bottom: 14px; }
.empty h4 { font-size: 16px; font-weight: 700; }
.empty p { font-size: 12.5px; color: var(--muted); margin-top: 4px; line-height: 1.5; }

/* ---- Home module cards -------------------------------------------------- */
.mod-grid { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 6px; }
.mod-tile { width: 190px; border-radius: var(--radius-sm); padding: 20px; cursor: pointer;
  background: var(--fill-2); border: 1px solid var(--hairline);
  transition: transform .12s, background .15s, box-shadow .15s; }
.mod-tile:hover { transform: translateY(-2px); background: var(--fill-strong); box-shadow: var(--shadow-sm); }
.mod-tile .chip { width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent); margin-bottom: 14px; }
.mod-tile .nm { font-size: 14px; font-weight: 700; }
.mod-tile .go { font-size: 12px; color: var(--muted); margin-top: 2px; }

/* ---- Dashboard: role-aware quick view ---------------------------------- */
.dash-stats { display: flex; flex-wrap: wrap; gap: 16px; margin-bottom: 20px; }
.dash-stats .stat { flex: 1 1 210px; }
.stat.clickable { cursor: pointer; transition: transform .12s, box-shadow .15s; }
.stat.clickable:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.dash-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(322px, 1fr));
  gap: 16px; align-items: start; }
.dash-card { border-radius: var(--radius-sm); padding: 18px 20px; cursor: pointer;
  transition: transform .12s, box-shadow .15s; }
.dash-card:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.dash-head { display: flex; align-items: center; gap: 12px; margin-bottom: 15px; }
.dash-ic { width: 42px; height: 42px; border-radius: 12px; display: grid; place-items: center; flex: none; }
.dash-ht { min-width: 0; }
.dash-title { font-size: 15px; font-weight: 800; letter-spacing: -0.2px; }
.dash-sub { font-size: 12px; color: var(--muted); margin-top: 1px; }
.dash-arrow { margin-left: auto; color: var(--faint); display: grid; place-items: center; flex: none;
  transition: color .15s, transform .15s; }
.dash-card:hover .dash-arrow { color: var(--accent); transform: translateX(2px); }
.dash-list { display: flex; flex-direction: column; gap: 12px; }
.dash-line { font-size: 13px; }
.dash-line.simple { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.dl-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 7px; }
.dl-name { font-weight: 700; color: var(--text); }
.dl-meta { font-size: 12px; color: var(--text-2); white-space: nowrap; }
.dl-meta b { color: var(--text); font-weight: 800; }
.bar { height: 7px; border-radius: 999px; background: var(--hairline); overflow: hidden; }
.bar i { display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--gold-2), var(--accent)); transition: width .4s ease; }

/* ---- Users -------------------------------------------------------------- */
.users-body { display: grid; grid-template-columns: 1fr 340px; gap: 18px; align-items: start; }
.panel { border-radius: var(--radius-sm); padding: 22px; }
.acct { display: flex; align-items: center; gap: 14px; padding: 12px 14px; border-radius: var(--radius-xs);
  background: var(--fill-2); border: 1px solid var(--hairline); margin-bottom: 10px; }
.acct .nm { font-size: 14px; font-weight: 700; }
.acct .sub { font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.acct .spacer { margin-left: auto; }

/* Manual highlight flag (Students list rows + detail badge/button). The row
   carries an inline --flag colour (the picked swatch); fall back to --warn so
   anything without an explicit colour keeps the original amber. */
.acct.flagged { border-color: var(--flag, var(--warn));
  box-shadow: inset 3px 0 0 var(--flag, var(--warn));
  background: color-mix(in srgb, var(--flag, var(--warn)) 10%, transparent); }
.acct.clickable.flagged:hover {
  background: color-mix(in srgb, var(--flag, var(--warn)) 16%, transparent);
  border-color: var(--flag, var(--warn)); }
.flag-dot { display: inline-flex; vertical-align: -2px; color: var(--flag, var(--warn)); }
.tag-flag { display: inline-block; font-size: 0.7em; font-weight: 800; letter-spacing: .04em;
  text-transform: uppercase; color: var(--warn); background: var(--warn-soft);
  padding: 2px 7px; border-radius: 999px; vertical-align: middle; }
.btn-warn-ghost { color: var(--warn); background: var(--warn-soft); border-color: transparent; }
.btn-warn-ghost:hover { background: var(--warn-soft); border-color: var(--warn); }

/* Highlight-colour picker (Students + Beds detail modals): a label and a row of
   colour swatches; --sw is each swatch's colour. */
.flag-picker { display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 12px; padding: 10px 12px; border: 1px solid var(--line);
  border-radius: 12px; background: var(--surface-2, transparent); }
.flag-picker-lbl { display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 700; color: var(--muted); }
.flag-swatches { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.flag-sw { width: 24px; height: 24px; border-radius: 999px; cursor: pointer;
  background: var(--sw, var(--line)); border: 2px solid transparent;
  box-shadow: 0 0 0 1px var(--line) inset; padding: 0; transition: transform .08s ease;
  display: inline-flex; align-items: center; justify-content: center; }
.flag-sw:hover { transform: scale(1.12); }
.flag-sw.on { border-color: var(--text); box-shadow: 0 0 0 2px var(--sw) inset; }
.flag-sw:disabled { opacity: .5; cursor: default; transform: none; }
.flag-sw.flag-clear { background: transparent; color: var(--muted);
  box-shadow: 0 0 0 1px var(--line) inset; }
.flag-sw.flag-clear:hover { color: var(--danger, #ef4444); }
.flag-sw.hidden { display: none; }

/* ===================== Exams module ===================== */
.ex-filters { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; }
.ex-list-head { display: flex; align-items: center; justify-content: space-between;
  margin: 18px 0 10px; }
.ex-h3 { font-size: 20px; font-weight: 800; letter-spacing: -.01em; margin: 0; }

.ex-card { border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px;
  background: var(--surface-2, transparent); margin-bottom: 6px; }
.ex-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.ex-card-t { font-size: 13px; font-weight: 800; }
.ex-subchips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 10px; }
.ex-subchip { display: inline-flex; align-items: center; gap: 4px; font-size: 12px;
  padding: 3px 9px; border-radius: 999px; border: 1px solid var(--line);
  background: var(--surface, transparent); }
.ex-subchip b { font-weight: 800; color: var(--muted); }

/* Exam list rows reuse .acct; the type badge leads each row. */
.ex-type { flex: none; min-width: 78px; text-align: center; font-size: 10.5px;
  font-weight: 800; text-transform: uppercase; letter-spacing: .05em;
  padding: 5px 8px; border-radius: 8px; color: var(--text);
  background: color-mix(in srgb, var(--accent, #888) 16%, transparent); }
.ex-type-weekend    { background: color-mix(in srgb, #3b82f6 18%, transparent); color: #1e40af; }
.ex-type-weekly     { background: color-mix(in srgb, #3b82f6 18%, transparent); color: #1e40af; }
.ex-type-cumulative { background: color-mix(in srgb, #a855f7 18%, transparent); color: #6b21a8; }
.ex-type-part_test  { background: color-mix(in srgb, #16a34a 18%, transparent); color: #14532d; }
/* Section header above each exam-type group in the list. */
.ex-group-label { font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted); margin: 14px 2px 6px; }
.ex-group-label:first-child { margin-top: 4px; }

/* Each exam type renders as a self-contained series card, so empty and filled
   series read as the same uniform block (no ragged spacing between them). */
.ex-series { border: 1px solid var(--hairline); border-radius: 14px;
  background: var(--fill-1, transparent); padding: 4px 14px 12px; margin-bottom: 14px; }
.ex-series-head { display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 12px 2px 10px; border-bottom: 1px solid var(--hairline);
  margin-bottom: 12px; }
.ex-series-title { font-size: 13px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted); margin: 0; }
.ex-series-empty { font-size: 12.5px; color: var(--faint); padding: 2px 2px 4px; }
.ex-series .acct:last-child { margin-bottom: 2px; }
/* "Viewing: <campus>" line on the marks grid — which campus(es) are on screen. */
.ex-viewing { display: inline-flex; align-items: center; gap: 7px; margin-top: 10px;
  padding: 6px 13px; border-radius: 999px; font-size: 14px; font-weight: 600;
  background: color-mix(in srgb, var(--accent, #3b82f6) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent, #3b82f6) 32%, transparent);
  color: var(--text); }
.ex-viewing b { font-weight: 800; }
.ex-viewing svg { width: 16px; height: 16px; opacity: .85; }
.ex-viewing .muted { font-weight: 500; font-size: 12.5px; }

/* Campus filter in the marks-grid top bar (only when the exam spans >1 campus). */
.ex-campus-filter { margin-left: auto; }

/* Variant dropdown on the marks grid (linked-course A/C filter). */
.ex-variant { margin-top: 8px; max-width: 260px; font-size: 12.5px; padding: 5px 8px; }

/* Course-link modal (Courses screen → "Link courses for exams"). */
.cl-seclabel { display: flex; align-items: center; gap: 8px; font-size: 11px;
  font-weight: 800; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted); margin: 14px 0 4px; }
.cl-seclabel:first-child { margin-top: 2px; }
.cl-seclabel button { margin-left: auto; text-transform: none; letter-spacing: 0;
  font-weight: 600; }
.cl-row { display: flex; align-items: center; gap: 10px; padding: 8px 0;
  border-bottom: 1px solid var(--line); }
.cl-row:last-child { border-bottom: 0; }
.cl-row > div { flex: 1; }
.cl-custom-wrap { border-top: 1px solid var(--line); margin-top: 14px; padding-top: 10px; }
.cl-names { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 14px;
  margin-top: 8px; max-height: 220px; overflow: auto; }
.cl-check { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
  cursor: pointer; }

/* Field rows in the exam editor modal. */
.fld { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; }
.fld > span { font-size: 12px; font-weight: 700; color: var(--muted); }
.fld-row { display: flex; gap: 12px; }
.fld-row .fld { flex: 1; }
.modal-title { font-size: 16px; font-weight: 800; margin: 0 0 14px; }
.btn-icon { width: 38px; padding: 0; flex: none; }

.ex-subrows { display: flex; flex-direction: column; gap: 8px; }
.ex-subrow { display: flex; gap: 8px; align-items: center; }
.ex-subrow .ex-sub-name { flex: 1; }
.ex-subrow .ex-sub-max { width: 84px; flex: none; }
/* Per-exam editor: subject NAME is fixed (from the group); only max is editable. */
.ex-subrow-fixed .ex-sub-fixedname { flex: 1; font-size: 13px; font-weight: 600;
  padding: 7px 2px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Group subjects editor (Courses screen): names only. */
.gs-subrows { display: flex; flex-direction: column; gap: 8px; }
.gs-subrow { display: flex; gap: 8px; align-items: center; }
.gs-subrow .gs-name { flex: 1; }

.ex-camp-checks { display: flex; flex-wrap: wrap; gap: 10px; }
.ex-camp-check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px;
  padding: 6px 10px; border: 1px solid var(--line); border-radius: 10px; cursor: pointer; }

/* Marks grid — a full page (not a modal) so the grid gets real width. */
.ex-page { max-width: 1180px; margin: 0 auto; }
.ex-page-card { border: 1px solid var(--line); border-radius: 18px; padding: 20px 22px; }
.ex-grid-head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 12px; }
.ex-summary { display: flex; gap: 14px; }
.ex-summary > div { text-align: center; }
.ex-summary b { display: block; font-size: 17px; font-weight: 800; }
.ex-summary span { font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--muted); }
.ex-grid-wrap { overflow: auto; max-height: 66vh; border: 1px solid var(--line);
  border-radius: 12px; }
.ex-grid { border-collapse: separate; border-spacing: 0; width: 100%; font-size: 12.5px; }
.ex-grid th, .ex-grid td { padding: 8px 10px; border-bottom: 1px solid var(--line);
  white-space: nowrap; }
.ex-grid thead th { position: sticky; top: 0; z-index: 2; background: var(--surface);
  font-size: 11px; text-transform: uppercase; letter-spacing: .03em; color: var(--muted); }
.ex-grid .ex-num { text-align: center; }
.ex-grid .ex-cat { text-align: center; color: var(--muted); white-space: nowrap; }
.ex-grid .ex-stick { position: sticky; left: 0; z-index: 1; background: var(--surface);
  text-align: left; min-width: 150px; }
.ex-grid thead .ex-stick { z-index: 3; }
.ex-grid th.ex-sortable { cursor: pointer; user-select: none; }
.ex-grid th.ex-sortable:hover { color: var(--text); }
.ex-sortarrow { font-size: 8.5px; margin-left: 3px; }
.ex-max { font-size: 9.5px; color: var(--muted); margin-left: 2px; }
.ex-sname { font-weight: 700; }
.ex-scampus { font-size: 10.5px; color: var(--muted); }
.ex-markwrap { display: inline-flex; flex-direction: column; align-items: center; gap: 2px; }
.ex-mark { width: 58px; height: 30px; text-align: center; border: 1px solid var(--line);
  border-radius: 8px; background: var(--surface); color: var(--text); font-size: 12.5px; }
.ex-mark:disabled { opacity: .45; }
.ex-subrank { font-size: 9.5px; font-weight: 700; color: var(--muted); min-height: 12px; line-height: 12px; }
.ex-total { font-weight: 800; }
/* Derived BIO column (Botany + Zoology) — computed, not editable */
.ex-bio { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.ex-bioval { font-weight: 700; font-size: 12.5px; min-height: 30px; display: inline-flex; align-items: center; }
.ex-mrow.is-absent { opacity: .6; }

/* Marks import modal (sheet picker + preview) */
.imp-sheets { display: flex; flex-direction: column; gap: 8px; margin: 6px 0 4px; max-height: 44vh; overflow: auto; }
.imp-sheet { display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; border: 1px solid var(--line);
  border-radius: 10px; cursor: pointer; }
.imp-sheet:hover { background: var(--surface); }
.imp-sheet input { margin-top: 3px; }
.imp-sub { display: block; font-size: 12px; color: var(--muted); }
.imp-prev { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 2px; }
.imp-line { display: flex; gap: 10px; font-size: 13px; }
.imp-line span { color: var(--muted); min-width: 72px; }
.imp-stats { display: flex; gap: 10px; margin: 2px 0; }
.imp-stats > div { flex: 1; text-align: center; padding: 8px; border: 1px solid var(--line); border-radius: 10px; }
.imp-stats b { display: block; font-size: 18px; font-weight: 800; }
.imp-stats span { font-size: 10.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.imp-note { font-size: 12px; color: var(--muted); background: var(--surface); border-radius: 8px; padding: 8px 10px; }
.imp-note.imp-warn { color: #7f1d1d; background: color-mix(in srgb, #ef4444 12%, transparent); }
.ex-status { display: flex; align-items: center; gap: 8px; }
.ex-abs { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; color: var(--muted); }

/* Status / pass-fail tags (shared by the grid and the student Exams tab) */
.ex-tag { display: inline-block; font-size: 10px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .04em; padding: 3px 8px; border-radius: 999px; }
.ex-tag-pass    { color: #14532d; background: color-mix(in srgb, #16a34a 18%, transparent); }
.ex-tag-fail    { color: #7f1d1d; background: color-mix(in srgb, #ef4444 18%, transparent); }
.ex-tag-absent  { color: #7f1d1d; background: color-mix(in srgb, #ef4444 14%, transparent); }
.ex-tag-pending { color: var(--muted); background: color-mix(in srgb, var(--muted) 14%, transparent); }

/* Profile | Exams tab strip inside the student modal */
.modal-tabs { display: flex; gap: 4px; margin: 4px 0 14px; padding: 4px;
  background: color-mix(in srgb, var(--muted) 8%, transparent); border-radius: 12px; }
.mtab { flex: 1; height: 34px; border: 0; background: transparent; cursor: pointer;
  font-size: 12.5px; font-weight: 700; color: var(--muted); border-radius: 9px; }
.mtab.on { background: var(--surface); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,.08); }

/* Full-screen student detail (replaces the old modal island) */
.stud-detail { max-width: 960px; margin: 0 auto; }
.stud-bar { margin-bottom: 12px; }
.stud-back svg { transform: rotate(180deg); }
.stud-card { border: 1px solid var(--line); border-radius: 18px; padding: 22px 26px; }
.stud-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }
.stud-actions .btn { height: 40px; padding: 0 18px; }
/* Read-only profile fields in two columns so the page doesn't feel empty. */
.kvlist.kv-2col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 30px; row-gap: 0; }
@media (max-width: 620px) { .kvlist.kv-2col { grid-template-columns: 1fr; } }

/* Student Exams tab cards */
.stex-card { border: 1px solid var(--line); border-radius: 12px; padding: 11px 13px;
  margin-bottom: 8px; }
.stex-top { display: flex; align-items: center; gap: 10px; }
.stex-title { font-weight: 700; font-size: 13px; }
.stex-meta { font-size: 11px; color: var(--muted); margin-top: 2px; }
.stex-score { font-weight: 800; font-size: 13px; }
.stex-subs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.stex-absent { border-color: color-mix(in srgb, #ef4444 35%, var(--line)); }

/* Date-of-joining: a Date/Note segmented toggle above the input (the field can
   hold a real date or a free-text note). */
.doj-wrap { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
.doj-toggle { display: inline-flex; align-self: flex-start; border: 1px solid var(--hairline-2);
  border-radius: 8px; overflow: hidden; background: var(--fill-2); }
.doj-mode { padding: 4px 13px; font-size: 12px; font-weight: 700; color: var(--muted);
  background: transparent; border: none; cursor: pointer; }
.doj-mode.on { background: var(--accent); color: #fff; }

/* Shared student page pieces: the profile ISLAND + the MARKS panel. The admin
   detail shows them as TABS (Details | Marks & performance), each full width;
   the parent portal renders the same pieces in its own shell. */
.stud-detail { max-width: 1200px; }
.stud-detail .stud-card { max-width: 960px; margin: 0 auto; }
.stud-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.stud-tab { display: inline-flex; align-items: center; gap: 8px; padding: 10px 18px;
  border-radius: 999px; border: 1px solid var(--line); background: transparent;
  font: inherit; font-size: 13.5px; font-weight: 700; color: var(--muted); cursor: pointer; }
.stud-tab.on { background: var(--accent); border-color: var(--accent); color: #fff; }
/* The Details tab: the island centres as a roomy card, its fields flowing
   into two columns on wide screens (the footer blocks stay full width). */
.stud-detwrap .stud-island { max-width: 780px; margin: 0 auto; }
@media (min-width: 700px) {
  .stud-detwrap .kvlist { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 36px; }
  .stud-detwrap .kvlist .kv:nth-last-child(-n+2) { border-bottom: none; }
}
.stud-island { border: 1px solid var(--line); border-radius: 18px; padding: 20px 22px; }
.stud-main { border: 1px solid var(--line); border-radius: 18px; padding: 20px 22px;
  min-height: 420px; }
.stud-main-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.stud-main-head h3 { margin: 0; font-size: 16px; }
.stud-main-head svg { color: var(--faint); }

/* Exam-type tabs on the marks panel (one per series the course sits) */
.stex-tabs { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.stex-tab { display: inline-flex; align-items: center; gap: 7px; padding: 8px 15px;
  border-radius: 999px; border: 1px solid var(--line); background: transparent;
  font: inherit; font-size: 13px; font-weight: 700; color: var(--muted); cursor: pointer; }
.stex-tab .cnt { font-size: 11px; font-weight: 800; padding: 1px 7px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); }
.stex-tab.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.stex-tab.on .cnt { background: rgba(255, 255, 255, .22); color: #fff; }

/* Marks summary strip above the exam cards */
.stex-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 8px; margin-bottom: 14px; }
.stex-stat { border: 1px solid var(--line); border-radius: 12px; padding: 10px 8px;
  text-align: center; background: var(--fill-2); }
.stex-stat .v { font-weight: 800; font-size: 16px; }
.stex-stat .l { font-size: 10.5px; color: var(--muted); margin-top: 2px;
  text-transform: uppercase; letter-spacing: .04em; }

/* Parent-login block at the end of the admin island */
.pl-sec { border-top: 1px solid var(--hairline-2); margin-top: 14px; padding-top: 12px; }
.pl-head { display: flex; align-items: center; gap: 6px; font-size: 12px;
  font-weight: 700; color: var(--text-2); }
.pl-head svg { color: var(--faint); }
.pl-status { font-size: 11.5px; margin: 6px 0 8px; }
.pl-cred { display: flex; justify-content: space-between; gap: 10px; align-items: center;
  border: 1px solid var(--line); border-radius: 10px; padding: 8px 12px;
  margin-top: 8px; font-size: 13px; }
.pl-cred span { color: var(--muted); }
.pl-cred b { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; user-select: all; }

/* Login screen: the Staff / Student segmented toggle */
.login-mode { display: flex; border: 1px solid var(--hairline-2); border-radius: 10px;
  overflow: hidden; background: var(--fill-2); margin-bottom: 18px; }
.lmode { flex: 1; padding: 9px 0; font-size: 13px; font-weight: 700; color: var(--muted);
  background: transparent; border: none; cursor: pointer; }
.lmode.on { background: var(--accent); color: #fff; }

/* Parent portal: its own shell reusing the staff shell's classes (.app /
   .sidebar / .main), so only the page content needs styling — Home is the
   performance overview (counts strip + recent exams), the profile view
   centers the island, a series page is one full-width card. */
.parent-home .stud-island { max-width: 640px; margin: 0 auto; }
.parent-series { min-height: calc(100vh - 160px); }
.pser-h { font-size: 11.5px; font-weight: 800; letter-spacing: .5px; text-transform: uppercase;
  color: var(--muted); margin: 20px 0 8px; }

/* =========================================================================
   TOASTS
   ========================================================================= */
#toasts { position: fixed; bottom: 26px; left: 50%; transform: translateX(-50%); z-index: 50;
  display: flex; flex-direction: column; gap: 10px; align-items: center; }
.toast { display: flex; align-items: center; gap: 10px; padding: 12px 18px; border-radius: 12px;
  background: var(--glass-3); backdrop-filter: blur(16px); border: 1px solid var(--stroke);
  box-shadow: var(--shadow); color: var(--text); font-size: 13px; font-weight: 600;
  animation: toastIn .25s ease, toastOut .3s ease forwards; animation-delay: 0s, 2.4s; }
.toast svg { width: 16px; height: 16px; color: var(--accent); }
@keyframes toastIn { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
@keyframes toastOut { to { opacity: 0; transform: translateY(14px); } }

.fade-in { animation: fadeIn .25s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }


/* Account / role list rows lift like the other cards. */
.acct { transition: border-color .15s, box-shadow .15s, transform .12s, background .15s; }
.acct:hover { border-color: var(--gold-line); box-shadow: var(--shadow-sm); background: var(--fill-3); }

/* =========================================================================
   CAMPUSES + FLOOR PLAN + MODALS
   ========================================================================= */
.iconbtn { width: 34px; height: 34px; flex: none; display: grid; place-items: center;
  border-radius: 9px; border: 1px solid var(--hairline); background: var(--fill-2);
  color: var(--text-2); cursor: pointer; transition: background .15s, color .15s, border-color .15s; }
.iconbtn:hover { background: var(--fill-strong); color: var(--text); border-color: var(--hairline-2); }
.iconbtn svg { width: 16px; height: 16px; }
.iconbtn.sm { width: 30px; height: 30px; }
.iconbtn.sm svg { width: 15px; height: 15px; }
.iconbtn.xs { width: 26px; height: 26px; margin-left: 6px; }
.iconbtn.xs svg { width: 13px; height: 13px; }
/* "on" = this course is taught at ≥1 campus (Courses screen offering button) */
.iconbtn.on { color: var(--accent); border-color: var(--accent-ring); background: var(--accent-soft); }
/* Course → campuses picker (which campuses teach a global course) */
.cc-picks { display: flex; flex-direction: column; gap: 2px; max-height: 320px; overflow: auto; }
.cc-pick { display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: 9px; cursor: pointer; }
.cc-pick:hover { background: var(--fill); }
.cc-pick input { width: 16px; height: 16px; accent-color: var(--accent); flex: none; }
.btn-xs { height: 32px; padding: 0 12px; font-size: 12px; }

/* ---- Campus cards ---- */
.camp { border-radius: var(--radius-sm); padding: 20px; margin-bottom: 16px; }
.camp-head { display: flex; align-items: center; gap: 14px; }
.camp-head .chip { width: 44px; height: 44px; border-radius: 12px; display: grid; place-items: center; flex: none;
  background: var(--accent-soft); color: var(--accent); }
.camp-head .nm { font-size: 16px; font-weight: 800; letter-spacing: -0.2px; }
.camp-head .counts { font-size: 12px; color: var(--muted); margin-top: 2px; }
.pchips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.pchip { display: inline-flex; align-items: center; gap: 8px; padding: 6px 8px 6px 12px; border-radius: 999px;
  background: var(--accent-soft); color: var(--text); font-size: 12.5px; font-weight: 600; }
.pchip .x, .bedchip .x { display: grid; place-items: center; width: 18px; height: 18px; border-radius: 50%;
  border: none; background: var(--ink-wash-2); color: var(--text-2); cursor: pointer; }
.pchip .x:hover, .bedchip .x:hover { background: var(--accent); color: var(--on-fill); }
.assign-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* ---- Campus tabs (floor plan) ---- */
.camp-tabs { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
.ctab { padding: 9px 16px; border-radius: 999px; border: 1px solid var(--hairline-2);
  background: var(--fill-2); color: var(--text-2); font-size: 13px; font-weight: 600;
  font-family: var(--font); cursor: pointer; transition: all .15s; }
.ctab:hover { background: var(--fill-strong); color: var(--text); }
.ctab.active { background: linear-gradient(180deg, var(--accent-3), var(--accent)); color: var(--on-fill);
  border-color: var(--accent); box-shadow: var(--shadow-sm), inset 0 0 0 1px var(--gilt-ring); }

/* ---- Floor plan toolbar ---- */
.fp-toolbar { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; flex-wrap: wrap; }
.fp-hint { font-size: 12px; color: var(--muted); }

/* ---- Floor cards ---- */
.floor { border-radius: var(--radius-sm); padding: 14px 16px; margin-bottom: 14px; }
.floor-head { display: flex; align-items: center; gap: 12px; }
.chev { width: 28px; height: 28px; flex: none; display: grid; place-items: center; border: none;
  background: transparent; color: var(--muted); cursor: pointer; transition: transform .18s; }
.chev.open { transform: rotate(90deg); }
.chip-sm { width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center; flex: none;
  background: var(--accent-soft); color: var(--accent); }
.fname { font-size: 15px; font-weight: 700; }
.sub2 { font-size: 11.5px; color: var(--muted); margin-top: 1px; }

/* ---- Blocks (optional A/B/C layer inside a floor) ---- */
.blockwrap { display: flex; flex-direction: column; gap: 12px; margin-top: 14px; }
.blockwrap.hidden { display: none; }
.block { border: 1px solid var(--hairline); border-radius: var(--radius-sm);
  background: var(--fill-1); padding: 10px 12px; }
.block-head { display: flex; align-items: center; gap: 10px; }
.block-badge { width: 30px; height: 30px; border-radius: 9px; display: grid; place-items: center;
  flex: none; font-weight: 800; font-family: var(--font-display); font-size: 13px; color: var(--accent);
  background: linear-gradient(155deg, var(--gold-soft), var(--accent-soft));
  box-shadow: inset 0 0 0 1px var(--gold-line); }
.bname { font-size: 14px; font-weight: 800; }
.block-rooms { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: 10px; margin-top: 10px; }
.block-rooms.hidden { display: none; }
.chev.sm { width: 24px; height: 24px; }
.chev.sm svg { width: 14px; height: 14px; }

/* ---- Beds island: per-block grouping ---- */
.bedblock { margin-bottom: 18px; }
.bedblock:last-child { margin-bottom: 0; }
.bedblock-head { display: flex; align-items: center; gap: 8px; font-weight: 800; font-size: 14px;
  margin-bottom: 10px; color: var(--text); }
.bedblock-head svg { color: var(--accent); flex: none; }
.bedblock-sub { margin-left: auto; font-size: 12px; font-weight: 600; color: var(--muted); }

.rooms { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 12px;
  margin-top: 14px; }
.rooms.hidden { display: none; }
.room { border-radius: var(--radius-xs); padding: 12px 14px;
  background: var(--fill-2); border: 1px solid var(--hairline); }
.room-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* AC pill + add/rename/delete buttons travel together so they wrap as one unit
   (the wide "Non-AC" pill no longer shifts the + button onto a different row). */
.room-ctrls { display: flex; align-items: center; gap: 6px; margin-left: auto; flex: none; }
.rname { font-size: 13.5px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Beds sit side-by-side and wrap, so a room with many beds stays compact
   instead of one tall column. Chips keep their natural width (names stay full). */
.beds { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 12px; }
.bedchip { display: inline-flex; align-items: center; gap: 6px; padding: 5px 7px 5px 9px; border-radius: 8px;
  background: var(--ink-wash); border: 1px solid var(--hairline); font-size: 11.5px; font-weight: 600;
  color: var(--text-2); white-space: nowrap; }
.bedchip svg { color: var(--muted); flex: none; }

/* ---- Modal ---- */
.modal-overlay { position: fixed; inset: 0; z-index: 100; background: var(--overlay);
  backdrop-filter: blur(4px); display: grid; place-items: center; animation: fadeIn .15s ease; }
/* Default modal sizes to its content. Big "islands" opt in via .island / .floor-island. */
.modal { width: 480px; max-width: 92vw; max-height: 88vh; border-radius: var(--radius-sm);
  padding: 24px 26px; background: var(--glass-3);
  display: flex; flex-direction: column; overflow: auto; }
.modal h3 { font-size: 18px; font-weight: 800; letter-spacing: -0.2px; }
.modal-msg { font-size: 13px; color: var(--text-2); line-height: 1.55; margin-top: 8px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: auto;
  padding-top: 18px; flex: none; }
.modal-actions .btn { height: 40px; padding: 0 18px; }

/* ---- AC/non-AC segmented control (modal) ---- */
.seg { display: flex; gap: 8px; }
.seg-btn { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; border-radius: var(--radius-xs); border: 1px solid var(--hairline-2);
  background: var(--fill-2); color: var(--text-2); font-family: var(--font);
  font-size: 13px; font-weight: 600; cursor: pointer; transition: all .15s; }
.seg-btn svg { width: 15px; height: 15px; }
.seg-btn:hover { background: var(--fill-strong); }
.seg-btn.active { background: linear-gradient(180deg, var(--accent-3), var(--accent)); color: var(--on-fill);
  border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--gilt-ring); }

/* ---- AC pill on floor rows ---- */
.acpill { padding: 5px 11px; border-radius: 999px; font-size: 11px; font-weight: 700;
  font-family: var(--font); cursor: pointer; border: 1px solid var(--hairline-2);
  transition: all .15s; letter-spacing: .3px; white-space: nowrap; flex: none; }
.acpill.on { background: var(--accent); color: var(--on-fill); border-color: var(--accent); }
.acpill.off { background: var(--fill-2); color: var(--muted); }
.acpill:hover { filter: brightness(1.05); border-color: var(--accent); }

/* ---- Back button ---- */
.backbtn { display: inline-flex; align-items: center; gap: 6px; margin-bottom: 14px;
  padding: 8px 14px 8px 10px; border-radius: 999px; border: 1px solid var(--hairline-2);
  background: var(--fill-2); color: var(--text-2); font-family: var(--font);
  font-size: 12.5px; font-weight: 600; cursor: pointer; transition: all .15s; }
.backbtn:hover { background: var(--fill-strong); color: var(--text); }
.backbtn svg { width: 16px; height: 16px; transform: rotate(180deg); }

/* ---- Grouped account list (admin User Management) ---- */
.grp-head { display: flex; align-items: center; gap: 8px; margin: 18px 2px 10px;
  color: var(--text-2); font-size: 11px; font-weight: 700; letter-spacing: 1.2px;
  text-transform: uppercase; }
.grp-head:first-child { margin-top: 2px; }
.grp-head svg { width: 14px; height: 14px; color: var(--muted); }
.grp-count { margin-left: auto; padding: 2px 9px; border-radius: 999px; letter-spacing: 0;
  background: var(--accent-soft); color: var(--text-2); font-size: 11px; font-weight: 700; }

/* ---- Roles & permissions screen ---- */
.acct .chip { width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center;
  flex: none; background: var(--accent-soft); color: var(--accent); }
.acct .chip svg { width: 18px; height: 18px; }
.modgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 8px 0 4px; }
.modcheck { display: flex; align-items: center; gap: 7px; padding: 9px 11px; cursor: pointer;
  border: 1px solid var(--hairline); border-radius: 12px; font-size: 13px; font-weight: 600;
  color: var(--text-2); background: var(--card); user-select: none; }
.modcheck:hover { border-color: var(--accent); }
.modcheck input { accent-color: var(--accent); width: 15px; height: 15px; flex: none; }
.modcheck svg { width: 15px; height: 15px; color: var(--muted); flex: none; }
.modcheck:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); color: var(--text-1); }
.modgrid #erMods, .modal .modgrid { grid-template-columns: 1fr 1fr; }

/* ---- "Reported / resolved by" lines in the AC complaint detail ---- */
.wholine { display: flex; align-items: center; gap: 6px; font-size: 12px;
  color: var(--text-2); margin: 2px 0; }
.wholine svg { width: 13px; height: 13px; flex: none; color: var(--muted); }
.wholine b { color: var(--text); font-weight: 700; }
.wholine-sub { color: var(--muted); font-size: 11px; padding-left: 19px; }
.hist .by { margin-top: 6px; display: flex; flex-direction: column; gap: 2px; }

/* ---- Role pill on each account + the role picker ---- */
.rolepill { display: inline-flex; align-items: center; gap: 5px; height: 30px;
  padding: 0 10px; border-radius: 999px; font-size: 12px; font-weight: 700;
  font-family: var(--font); color: var(--accent); background: var(--accent-soft);
  border: 1px solid transparent; cursor: pointer; white-space: nowrap;
  transition: border-color .15s, background .15s; }
.rolepill svg { width: 12px; height: 12px; }
.rolepill:not(.static):hover { border-color: var(--accent-ring); }
.rolepill.static { cursor: default; color: var(--text-2); background: var(--hairline); }
.roleopts { display: flex; flex-direction: column; gap: 8px; margin: 10px 0 4px; }
.roleopt { display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 11px 13px; border-radius: 12px; border: 1px solid var(--hairline);
  background: var(--card); font-family: var(--font); font-size: 14px; font-weight: 600;
  color: var(--text); cursor: pointer; transition: border-color .15s, background .15s; }
.roleopt:hover { border-color: var(--accent); background: var(--accent-soft); }
.roleopt.current { border-color: var(--accent-ring); background: var(--accent-soft); }
/* A student who already has a bed: visible in the picker but not selectable. */
.roleopt.taken { opacity: .55; cursor: default; }
.roleopt.taken:hover { border-color: var(--hairline); background: var(--card); }
.roleopt svg { width: 15px; height: 15px; color: var(--muted); flex: none; }

/* "Show all students" override toggle in the bed-assign picker */
.pick-all { display: flex; align-items: center; gap: 8px; margin: -2px 0 10px;
  font-size: 12.5px; font-weight: 600; color: var(--text); cursor: pointer;
  user-select: none; }
.pick-all input { accent-color: var(--accent); width: 15px; height: 15px;
  cursor: pointer; flex: none; }
.pick-all .muted { font-weight: 500; }

/* Locked role field (e.g. Administrator) — no dropdown caret */
.select.no-arrow { background-image: none; padding-right: 14px; cursor: default; }

/* ---- Off/View/Edit permission rows in the Roles screen ---- */
.permrow { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px;
  padding: 8px 0; border-bottom: 1px solid var(--hairline); }
.permrow:last-child { border-bottom: none; }
.permname { display: flex; align-items: center; gap: 7px; font-size: 13px;
  font-weight: 600; color: var(--text); flex: 1; min-width: 0; }
.permname svg { width: 15px; height: 15px; color: var(--muted); flex: none; }
.seg-perm { gap: 4px; flex: none; }
.seg-b { height: 28px; padding: 0 11px; border-radius: 8px; cursor: pointer;
  font-family: var(--font); font-size: 12px; font-weight: 700; color: var(--text-2);
  background: var(--fill-2); border: 1px solid var(--hairline-2);
  transition: background .12s, color .12s, border-color .12s; }
.seg-b:not(.active):hover:not(:disabled) { background: var(--fill-strong); }
.seg-b.active { background: var(--accent); color: var(--on-fill); border-color: var(--accent); }
.seg-b.active:hover:not(:disabled) { background: var(--accent-2); }
.seg-b:disabled { opacity: .55; cursor: default; }
/* Invisible spacer that keeps Off/View/Edit columns aligned on rows (e.g.
   Accounts) that have no Edit option. */
.seg-b.seg-ph { visibility: hidden; pointer-events: none; }

/* ---- Password field with show/hide eye ---- */
.pw-wrap { position: relative; }
.pw-wrap .input { padding-right: 44px; }
.pw-toggle { position: absolute; top: 0; right: 0; height: 44px; width: 42px;
  display: grid; place-items: center; background: none; border: none; cursor: pointer;
  color: var(--muted); border-radius: var(--radius-xs); }
.pw-toggle:hover { color: var(--text-2); }
.pw-toggle svg { width: 16px; height: 16px; }

/* ---- Inline button spinner (login etc.) ---- */
.spinner { display: inline-block; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid rgba(255,255,255,.45); border-top-color: var(--on-fill);
  animation: spin 0.7s linear infinite; vertical-align: -3px; margin-right: 4px; }
@keyframes spin { to { transform: rotate(360deg); } }
.btn:disabled { opacity: 0.85; cursor: default; }

/* ---- Clickable profile card + profile modal ---- */
.user-card { display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 8px 10px; margin-bottom: 10px; border-radius: var(--radius-xs);
  background: var(--fill-1); border: 1px solid var(--hairline);
  cursor: pointer; font-family: var(--font); transition: border-color .15s, background .15s; }
.user-card:hover { border-color: var(--accent-ring); background: var(--fill-3); }
.user-card .nm { font-size: 13.5px; font-weight: 700; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-card .rl { font-size: 11.5px; color: var(--muted); }
.user-card .uc-go { margin-left: auto; color: var(--faint); display: grid; place-items: center; }
.profile-row { display: flex; align-items: center; gap: 13px; margin: 4px 0 6px; }
.profile-row .avatar.lg { width: 52px; height: 52px; font-size: 18px; flex: none; }
.profile-row .nm { font-size: 16px; font-weight: 700; }
.profile-row .rl { font-size: 12.5px; color: var(--text-2); }

/* ---- Profile details (key/value rows) ---- */
.kvlist { display: flex; flex-direction: column; gap: 0; margin-top: 4px; }
.kv { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 2px; border-bottom: 1px solid var(--hairline); font-size: 13.5px; }
.kv:last-child { border-bottom: none; }
.kv .k { color: var(--muted); font-weight: 600; }
.kv .v { color: var(--text); font-weight: 700; text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Inline-editable phone box inside the student detail kv list. */
.kv .phone-edit { width: 58%; max-width: 220px; margin: -4px 0; text-align: right;
  font-weight: 700; padding: 6px 9px; }
/* Edit-mode rows in the student profile: each value becomes an input/select. */
.kv-edit { align-items: center; }
.kv-edit .kv-in { width: 60%; max-width: 240px; margin: -4px 0; padding: 7px 10px;
  font-weight: 700; }
.kv-edit input.kv-in { text-align: right; }
/* "(dropped)" tag next to a struck-out admission. */
.tag-dropped { color: var(--fault); font-weight: 700; font-size: 0.82em; }

/* Beds "Can see occupants" sub-toggle in the Roles permission rows. */
.bed-occ { display: flex; align-items: center; gap: 7px; width: 100%;
  margin: 8px 0 2px; font-size: 12px; font-weight: 600; color: var(--text-2);
  cursor: pointer; }
.bed-occ input { width: 15px; height: 15px; accent-color: var(--accent, #6b4329);
  cursor: pointer; }
.bed-occ.hidden { display: none; }

/* Students filter row: Campus / Year / Group / Course… dropdowns + a live count. */
.filter-row { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end;
  margin: 0 0 14px; }
.filter-count { margin-left: auto; align-self: center; color: var(--muted);
  font-size: 12.5px; font-weight: 700; white-space: nowrap; }

/* Custom multi-select dropdown (replaces the native <select> so the menu looks
   identical on macOS and Windows). Trigger = a styled button; .msel-pop = an
   absolutely-positioned popover of checkbox rows. */
.msel { position: relative; display: flex; flex-direction: column; gap: 4px;
  font-size: 11.5px; font-weight: 700; color: var(--text-2); }
.msel-label { padding-left: 2px; }
.msel-trigger { display: flex; align-items: center; gap: 8px;
  min-width: 170px; height: 44px; padding: 0 12px; cursor: pointer;
  font-family: var(--font); font-size: 14px; font-weight: 600; color: var(--text);
  text-align: left; border-radius: var(--radius-xs);
  background: var(--fill-2); border: 1px solid var(--hairline-2);
  transition: border-color .15s, box-shadow .15s, background .15s; }
.msel-trigger:hover { background: var(--fill-strong); }
.msel-text { flex: 1; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.msel:not(.has-val) .msel-text { color: var(--muted); }
.msel-trigger > svg { flex: none; color: var(--faint); transition: transform .18s; }
.msel.open .msel-trigger { border-color: var(--accent);
  background: var(--fill-strong); box-shadow: 0 0 0 4px var(--accent-soft); }
.msel.open .msel-trigger > svg { transform: rotate(180deg); }

.msel-pop { position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  min-width: 100%; max-width: 280px; max-height: 320px; overflow-y: auto;
  display: none; flex-direction: column; gap: 2px; padding: 6px;
  border-radius: var(--radius-xs); background: var(--opt-bg);
  border: 1px solid var(--hairline-2); box-shadow: var(--shadow-lg); }
.msel.open .msel-pop { display: flex; }
.msel-opt { display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 9px; border: none; border-radius: 7px; background: none;
  cursor: pointer; font-family: var(--font); font-size: 13px; font-weight: 600;
  color: var(--text); text-align: left; }
.msel-opt:hover { background: var(--fill-1); }
.msel-check { flex: none; display: inline-flex; align-items: center;
  justify-content: center; width: 17px; height: 17px; border-radius: 5px;
  color: #fff; background: transparent; border: 1.5px solid var(--hairline-2); }
.msel-single .msel-check { border-radius: 50%; }
.msel-check > svg { opacity: 0; }
.msel-opt.on .msel-check { background: var(--accent); border-color: var(--accent); }
.msel-opt.on .msel-check > svg { opacity: 1; }
.msel-empty { padding: 10px 9px; color: var(--muted); font-size: 12.5px; font-weight: 600; }

@media (max-width: 700px) {
  .msel { flex: 1 1 100%; }
  .msel-trigger { min-width: 0; width: 100%; }
  .msel-pop { max-width: none; right: 0; }
  .filter-count { margin-left: 0; }
}

/* Register form: one field per row, stacked vertically. */
.reg-form .reg-fields { display: flex; flex-direction: column; gap: 2px;
  max-height: 60vh; overflow: auto; padding-right: 2px; }
.reg-form .field-row { display: flex; flex-direction: column; }
.reg-form .field-row .field { margin: 10px 0 5px; }
.reg-form select.input { width: 100%; }

/* =========================================================================
   MOBILE / RESPONSIVE
   ========================================================================= */
/* Mobile-only chrome is hidden on desktop. */
.topbar { display: none; }
.scrim { display: none; }

@media (max-width: 960px) {
  /* Never let anything cause sideways scrolling on small screens. */
  html, body, #root { overflow-x: hidden; max-width: 100%; }

  /* 16px inputs stop iOS Safari from auto-zooming (and shifting) on focus. */
  .input, .select, textarea.input { font-size: 16px; }

  /* ---- Login: stack the panels, compact brand, and SCROLL ----
     Body has overflow:hidden globally, so the login owns its own scroll here;
     align-items:start (not center/stretch) keeps the top reachable when the
     card is taller than the screen. */
  .login { padding: 0; display: block; height: 100dvh; overflow-y: auto;
    -webkit-overflow-scrolling: touch; }
  .login-card { grid-template-columns: 1fr; width: 100%; max-width: 100%;
    border-radius: 0; min-height: 100dvh; }
  .login-brand { padding: 30px 22px 6px; border-right: none; text-align: center; align-items: center; }
  .login-brand .brand-badge { width: 88px; height: 88px; margin-bottom: 14px; }
  .login-brand p { display: none; }
  .login-form { padding: 20px 22px 34px; }

  /* ---- App shell becomes a top bar + slide-in drawer ---- */
  .app { display: flex; flex-direction: column; height: 100dvh; padding: 0; gap: 0; }
  .topbar { display: flex; align-items: center; gap: 11px; flex: none; height: 56px;
    padding: 0 10px; border-radius: 0; position: relative; z-index: 30; }
  .hamburger { width: 42px; height: 42px; border: none; background: none; cursor: pointer;
    color: var(--text); display: grid; place-items: center; border-radius: 10px; }
  .hamburger:active { background: var(--accent-soft); }
  .tb-logo { width: 30px; height: 30px; object-fit: contain; }
  .tb-title { font-size: 16px; font-weight: 800; letter-spacing: -0.2px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  .sidebar { position: fixed; top: 0; left: 0; bottom: 0; width: 272px; max-width: 84vw;
    border-radius: 0; z-index: 50; transform: translateX(-100%);
    transition: transform .22s ease; overflow-y: auto; }
  .sidebar.open { transform: translateX(0); box-shadow: var(--shadow); }
  .scrim { display: block; position: fixed; inset: 0; z-index: 40;
    background: var(--overlay); opacity: 0; pointer-events: none; transition: opacity .22s; }
  .scrim.show { opacity: 1; pointer-events: auto; }

  .main { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden;
    border-radius: 0; padding: 16px 14px; }

  /* ---- Stack every two/three-column layout (full width) ---- */
  .stats { grid-template-columns: 1fr; gap: 12px; }
  .ac-body, .users-body { grid-template-columns: 1fr; gap: 14px; }
  .modgrid, .modal .modgrid, .modgrid #erMods { grid-template-columns: 1fr; }
  .mod-grid > * { flex: 1 1 100%; }
  .bedgrid { grid-template-columns: 1fr 1fr; gap: 8px; }   /* 2-up, scales with screen */

  /* Campus tabs: scroll sideways instead of overflowing the page. */
  .camp-tabs { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .camp-tabs .ctab { flex: none; }

  .page-head h1 { font-size: 22px; }
  .page-head { margin-bottom: 18px; }
  .panel { padding: 16px; }
  .modal { width: 96vw; max-width: 96vw; max-height: 92vh; }
  .tile { width: 100%; }
  .tiles { gap: 8px; }

  /* ---- List rows (accounts, roles, campus principals): drop the role pill +
     action buttons onto their own line so the right side never clips. The
     .spacer becomes a full-width flex break. ---- */
  .acct { flex-wrap: wrap; column-gap: 10px; row-gap: 10px; padding: 12px 14px; }
  .acct > .spacer { flex-basis: 100%; height: 0; margin: 0; }
  .acct > .rolepill { margin-left: 0; }
  .acct .nm, .acct .sub { white-space: normal; overflow-wrap: anywhere; }

  /* ---- Campus cards: let the header actions wrap instead of overflowing. ---- */
  .camp-head { flex-wrap: wrap; row-gap: 10px; }

  /* ---- Detail / AC panels: full-width action buttons read better on phones. ---- */
  .detail .btn, .detail .pill { max-width: 100%; }
}

@media (max-width: 460px) {
  .bedgrid { grid-template-columns: 1fr; }   /* one bed card per row on phones */
}

/* ---- Beds (admissions) ---- */
.bedroom { padding: 4px 6px 10px; }
.bedroom-head { display: flex; align-items: center; gap: 7px; font-size: 13px;
  font-weight: 700; color: var(--text-2); margin: 8px 2px; }
.bedroom-head svg { width: 14px; height: 14px; color: var(--muted); }
.bedgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; }
.bedcard { border: 1px solid var(--hairline-2); border-radius: var(--radius-xs);
  padding: 12px 13px; background: var(--fill-2); }
.bedcard.filled { background: var(--ok-soft); cursor: pointer; }
.bedcard.filled:hover { border-color: var(--ok); }
.bc-top { display: flex; align-items: center; gap: 7px; font-size: 12px; color: var(--text-2); }
.bc-top svg { width: 14px; height: 14px; color: var(--muted); }
.bc-name { font-weight: 700; }
.bc-student { font-size: 14px; font-weight: 800; margin-top: 8px; color: var(--text); }
.bc-meta { font-size: 12px; color: var(--text-2); margin-top: 2px; }
.bc-by { font-size: 11px; color: var(--muted); margin-top: 6px; display: flex; align-items: center; gap: 4px; }
.bc-by svg { width: 11px; height: 11px; }
.btn-xs { height: 30px; padding: 0 11px; font-size: 12px; }
.btn-xs svg { width: 13px; height: 13px; }

/* ---- Students toolbar + search + pending-assign banner ---- */
.toolbar-row { display: flex; gap: 12px; align-items: center; margin-bottom: 14px; flex-wrap: wrap; }
.searchbar { display: flex; align-items: center; gap: 8px; flex: none; min-width: 220px;
  background: var(--fill-2); border: 1px solid var(--hairline-2);
  border-radius: var(--radius-xs); padding: 0 12px; }
.toolbar-row .searchbar { flex: 1; }   /* grow horizontally only in the toolbar */
.searchbar svg { width: 16px; height: 16px; color: var(--muted); flex: none; }
.searchbar .input { border: none; background: none; height: 42px; padding: 0; flex: 1; }
.searchbar .input:focus { box-shadow: none; }
.searchbar .seg { flex: none; gap: 4px; }
.banner-pending { display: flex; align-items: center; gap: 9px; margin-bottom: 14px;
  padding: 11px 14px; border-radius: var(--radius-xs); font-size: 13px;
  background: var(--accent-soft); border: 1px solid var(--accent-ring); color: var(--text); }
.banner-pending svg { width: 16px; height: 16px; color: var(--accent); flex: none; }
@media (max-width: 960px) { .toolbar-row { flex-direction: column; align-items: stretch; }
  .toolbar-row .btn { width: 100%; } }

/* ---- AC report rank badge ---- */
.roleopt .rank { width: 22px; height: 22px; border-radius: 50%; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent); font-size: 12px; font-weight: 800; flex: none; }

/* ---- Clickable list rows (students) ---- */
.acct.clickable { cursor: pointer; border-radius: var(--radius-xs); transition: background .12s; }
.acct.clickable:hover { background: var(--fill-2); }
.acct .uc-go { color: var(--faint); display: grid; place-items: center; margin-left: 4px; }

/* ---- Large "island" modal (e.g. choose-a-student) ---- */
.modal.island { width: 75vw; max-width: 75vw; height: 80vh; display: flex; flex-direction: column; }
@media (max-width: 960px) { .modal.island { width: 96vw; max-width: 96vw; height: 88vh; } }
/* The big islands hold long SCROLLING lists. Content scrolled inside a
   backdrop-filter fails to rasterize (rows blank out mid-scroll, worst in
   Safari), so these two opt OUT of the glass blur — opaque stand-in for the
   glass tint over the page background — and the overlay behind them drops
   its own 4px backdrop blur for the same reason. */
.modal.island, .modal.floor-island {
  background: var(--island-bg);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.modal-overlay:has(.modal.island, .modal.floor-island) {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* ---- Beds: compact floor list ---- */
.floorlist { display: flex; flex-direction: column; gap: 10px; }
.floorcard { display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  padding: 16px 18px; border-radius: var(--radius-sm); border: 1px solid var(--hairline);
  background: var(--glass); cursor: pointer; font-family: var(--font);
  transition: border-color .15s, background .15s, transform .08s; }
.floorcard:hover { border-color: var(--accent-ring); }
.floorcard:active { transform: translateY(1px); }
.floorcard.allfull { background: var(--danger-soft); border-color: var(--danger); }
.fc-icon { width: 44px; height: 44px; border-radius: 12px; display: grid; place-items: center;
  flex: none; background: var(--accent-soft); color: var(--accent); }
.fc-name { font-size: 16px; font-weight: 800; letter-spacing: -0.2px; }
.fc-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.fc-sub .okc { color: var(--ok); } .fc-sub .badc { color: var(--danger); }
.fc-sub .resc { color: var(--warn); }
.floorcard .uc-go { margin-left: auto; color: var(--faint); display: grid; place-items: center; }

/* ---- Beds: floor island (90% × 90%) ---- */
.modal.floor-island { width: 90vw; max-width: 90vw; height: 90vh; }
.island-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
  flex: none; margin-bottom: 12px; }
.island-head-right { display: flex; align-items: center; gap: 14px; }
.legend { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.bedrows { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; gap: 8px; }
.bedrow { display: flex; align-items: center; gap: 14px; padding: 10px 12px;
  border-radius: var(--radius-xs); border: 1px solid var(--hairline); background: var(--fill-1); }
.bedrow.allfull { background: var(--danger-soft); border-color: var(--danger); }
.bedrow-room { width: 130px; flex: none; display: flex; align-items: center; gap: 7px;
  font-weight: 700; font-size: 13px; color: var(--text); }
.bedrow-room svg { width: 15px; height: 15px; color: var(--muted); flex: none; }
.bedrow-beds { display: flex; flex-wrap: wrap; gap: 8px; flex: 1; }
.bed-dot { width: 46px; height: 46px; border-radius: 11px; display: grid; place-items: center;
  cursor: pointer; font-size: 12px; font-weight: 800; color: #fff; border: 1px solid transparent;
  transition: transform .08s, filter .12s; }
.bed-dot:hover { transform: translateY(-1px); filter: brightness(1.08); }
.bed-dot.full { background: #be4338; }             /* red = filled (literal, like the bed bars) */
.bed-dot.empty { background: #2f6fb3; }            /* blue = empty */
.bed-dot.mini { width: 14px; height: 14px; border-radius: 4px; cursor: default; }

/* ---- Bed detail header (red when filled) ---- */
.bd-head { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
.bd-badge { width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center;
  flex: none; background: #2f6fb3; color: #fff; }
.bd-head.filled .bd-badge { background: var(--danger); }
.bd-head.reserved .bd-badge { background: #cf8f23; }
/* Reservation summary inside the bed-detail modal. */
.resvbox { display: flex; gap: 10px; align-items: flex-start; margin-top: 10px; padding: 12px 14px;
  border-radius: 12px; background: var(--warn-soft); color: var(--warn); }
.resvbox svg { width: 16px; height: 16px; flex: none; margin-top: 1px; }
.resv-t { font-weight: 700; font-size: 13px; }
.resv-note { font-size: 12.5px; margin-top: 2px; color: var(--text); }

@media (max-width: 960px) {
  .modal.floor-island { width: 96vw; max-width: 96vw; height: 92vh; padding: 16px 14px; }
  .bedrow { flex-direction: column; align-items: stretch; gap: 8px; }
  .bedrow-room { width: auto; }
  /* Single column on phones; box keeps inside its block (no horizontal overflow). */
  .roombox-grid { grid-template-columns: 1fr; gap: 10px; }
  .roombox { padding: 11px; }
}

/* ---- AC report: expandable repair-reason rows ---- */
.rep-row { border-bottom: 1px solid var(--hairline); }
.rep-row:last-child { border-bottom: none; }
.rep-head { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
  padding: 11px 2px; background: none; border: none; cursor: pointer;
  font-family: var(--font); font-size: 14px; font-weight: 600; color: var(--text); }
.rep-head b { font-weight: 800; }
.rep-chev { display: grid; place-items: center; color: var(--muted); transition: transform .15s; }
.rep-row.open .rep-chev { transform: rotate(90deg); }
.rep-body { padding-bottom: 8px; }
.rep-reason { display: flex; align-items: flex-start; gap: 8px; padding: 6px 0 6px 22px;
  font-size: 13px; color: var(--text-2); }
.rep-reason svg { width: 12px; height: 12px; color: var(--muted); flex: none; margin-top: 2px; }
.rep-text { flex: 1; min-width: 0; }
.rep-date { margin-left: auto; font-size: 11.5px; color: var(--muted); flex: none; white-space: nowrap; }

/* ---- Compact modal (e.g. empty bed detail) ---- */
.modal.compact { width: 460px; max-width: 92vw; height: auto; max-height: 86vh; }

/* ---- Export preview (shown before an .xlsx is downloaded) ---- */
.modal.xp-modal { width: 880px; max-width: 94vw; max-height: 88vh; }
.xp-head { flex: none; }
.xp-sub { font-size: 12px; margin-top: 3px; word-break: break-word; }
.xp-body { flex: 1; min-height: 0; overflow: auto; margin-top: 14px; }
.xp-sheet + .xp-sheet { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--hairline); }
.xp-title { font-size: 14px; font-weight: 800; color: var(--text); margin-bottom: 6px; }
.xp-metas { margin-bottom: 10px; }
.xp-meta { font-size: 11.5px; font-weight: 600; color: var(--muted); line-height: 1.55; }
.xp-tablewrap { overflow: auto; border: 1px solid var(--hairline-2);
  border-radius: var(--radius-xs); background: var(--fill-1); }
.xp-table { border-collapse: collapse; width: 100%; font-size: 12px; }
.xp-table th, .xp-table td { text-align: left; padding: 7px 11px; white-space: nowrap;
  border-bottom: 1px solid var(--hairline); }
.xp-table th { position: sticky; top: 0; z-index: 1; font-weight: 700; color: var(--text-2);
  background: var(--fill-strong); border-bottom: 1px solid var(--hairline-2); }
.xp-table td { color: var(--text); }
.xp-table tbody tr:last-child td { border-bottom: none; }
.xp-table tbody tr:hover td { background: var(--fill-1); }
.xp-more { font-size: 11.5px; font-weight: 600; color: var(--muted); margin-top: 8px; padding-left: 2px; }
.xp-empty { font-size: 12.5px; color: var(--muted); padding: 14px 2px; }
@media (max-width: 700px) {
  .xp-table th, .xp-table td { padding: 6px 8px; }
}

/* ---- Beds floor island: room boxes with horizontal bed bars ---- */
/* The beds island is a flex column: fixed header, scrolling body. */
#floorBody { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.bedscroll { flex: 1; min-height: 0; overflow: auto; }
/* ---- Activity Log (admin audit trail) ---- */
.loglist { padding: 4px 6px; }
.logrow { display: flex; align-items: center; gap: 12px; padding: 12px 12px;
  border-bottom: 1px solid var(--hairline); }
.logrow:last-child { border-bottom: none; }
.log-ic { width: 34px; height: 34px; flex: none; border-radius: 10px; display: grid;
  place-items: center; background: var(--accent-soft); color: var(--accent); }
.log-main { flex: 1; min-width: 0; }
.log-act { font-size: 14px; color: var(--text); overflow-wrap: anywhere; }
.log-detail { font-size: 13px; color: var(--text-2); margin-top: 2px; overflow-wrap: anywhere; }
.log-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.log-del { flex: none; color: var(--danger); }
.log-when { flex: none; font-size: 12px; color: var(--muted); white-space: nowrap; }
@media (max-width: 820px) {
  .logrow { flex-wrap: wrap; }
  .log-when { width: 100%; margin-left: 46px; }
}

/* ---- Pull-to-refresh (phone / installed app) ---- */
#ptr { position: fixed; top: 0; left: 50%; transform: translateX(-50%) translateY(0);
  z-index: 4000; width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center; background: var(--glass-3);
  border: 1px solid var(--hairline); box-shadow: 0 6px 18px rgba(60,40,24,.18);
  color: var(--accent); opacity: 0; pointer-events: none;
  transition: opacity .15s ease; }
#ptr.show { opacity: 1; }
#ptr .ptr-spin { display: grid; place-items: center; transition: transform .15s ease; }
#ptr.ready .ptr-spin { transform: rotate(180deg); }
/* transition:none so the .15s transform transition doesn't fight the spin. */
#ptr.reload .ptr-spin { animation: ptr-rot .8s linear infinite; transition: none; }
@keyframes ptr-rot { from { transform: rotate(0); } to { transform: rotate(360deg); } }

/* Campus-wide bed availability, shown above the floor list on the Beds tab. */
.beds-summary { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin-bottom: 14px; padding: 12px 16px; border-radius: var(--radius-sm);
  border: 1px solid var(--hairline); background: var(--fill-1); }
.beds-summary .bs-num { font-size: 15px; color: var(--text-2); }
.beds-summary .bs-num b { font-size: 22px; font-weight: 800; color: var(--accent); margin-right: 4px; }
.beds-summary .bs-sub { font-size: 12.5px; color: var(--muted); margin-left: auto; }

/* Block / Room dropdowns inside the floor island (mainly for phones). */
.bedfilter { flex: none; display: flex; flex-wrap: wrap; gap: 10px 14px; margin-bottom: 12px; }
.bedfilter-f { display: flex; flex-direction: column; gap: 4px; flex: 1 1 160px; min-width: 0; }
.bedfilter-f > span { font-size: 11px; font-weight: 700; letter-spacing: .3px;
  text-transform: uppercase; color: var(--muted); }
.bedsel { height: 40px; }
.roombox-grid { display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(264px, 100%), 1fr)); gap: 14px; align-content: start; }
.roombox { border: 1px solid var(--hairline); border-radius: var(--radius-sm); padding: 14px;
  background: var(--fill-1); }
.roombox.allfull { background: var(--danger-soft); border-color: var(--danger); }
.roombox-head { display: flex; align-items: center; gap: 7px; font-weight: 800; font-size: 14px; margin-bottom: 10px; }
.roombox-head svg { width: 15px; height: 15px; color: var(--muted); flex: none; }
.roombox-beds { display: flex; flex-direction: column; gap: 8px; }
/* flex-direction:row is explicit on purpose: the state class is `.empty`, which
   collides with the global .empty empty-state component (flex-direction:column).
   Stating row here keeps empty and filled beds on one identical horizontal line. */
.bedbar { display: flex; flex-direction: row; align-items: center; gap: 11px; width: 100%;
  text-align: left;
  height: 56px; flex: none; padding: 0 13px 0 10px; border-radius: 12px; border: 1px solid transparent;
  cursor: pointer; color: #fff; font-family: var(--font); font-weight: 700; font-size: 13px;
  flex-wrap: nowrap; overflow: hidden; box-sizing: border-box; position: relative;
  transition: transform .14s ease, box-shadow .14s ease, filter .14s ease; }
/* blue = empty, red = filled — subtle vertical gradient + inset highlight gives
   the flat bars depth without leaving the warm palette. */
.bedbar.empty { background: linear-gradient(180deg, #3f7cbe 0%, #2f6fb3 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.20), 0 2px 7px rgba(47,111,179,.24); }
.bedbar.full { background: linear-gradient(180deg, #cf564b 0%, #be4338 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.18), 0 2px 7px rgba(194,70,59,.24); }
/* amber = reserved: a held slot (locked, but no student assigned yet). */
.bedbar.reserved { background: linear-gradient(180deg, #d99a3e 0%, #c8862a 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.20), 0 2px 7px rgba(176,120,40,.26); }
.bedbar:hover { transform: translateY(-1px); filter: brightness(1.05);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.22), 0 7px 16px rgba(60,40,24,.20); }
.bedbar:active { transform: translateY(0); filter: brightness(.98); }
.bb-ic { display: grid; place-items: center; width: 30px; height: 30px; flex: none;
  border-radius: 9px; background: rgba(255,255,255,.18); }
.bb-ic svg { width: 16px; height: 16px; }
/* Bed name is the identifier — always show it in full (it's short). */
.bb-name { flex: none; font-weight: 800; letter-spacing: .1px; white-space: nowrap; }
/* Occupant name is secondary — it shrinks/ellipsizes when space is tight. */
.bb-who { flex: 0 1 auto; min-width: 0; margin-left: auto; font-weight: 600; font-size: 12px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; background: rgba(255,255,255,.17);
  padding: 4px 10px; border-radius: 999px; }
.bb-tag { flex: none; margin-left: auto; font-size: 10.5px; font-weight: 800; letter-spacing: .5px;
  text-transform: uppercase; background: rgba(255,255,255,.16); color: rgba(255,255,255,.95);
  padding: 4px 10px; border-radius: 999px; }
.swatch { width: 13px; height: 13px; border-radius: 4px; display: inline-block; }
.swatch.empty { background: #2f6fb3; } .swatch.full { background: #be4338; }

/* ---- Floor plan: bed kind badge + room AC ---- */
.kindbadge { font-size: 10px; font-weight: 700; padding: 1px 7px; border-radius: 6px;
  background: var(--hairline); color: var(--text-2); border: none; cursor: pointer; margin-left: 4px;
  font-family: var(--font); }
.kindbadge.twin { background: var(--gold-soft); color: var(--warn); }
button.kindbadge:hover { filter: brightness(0.97); }

/* ---- Beds island: twin bunk grouping + AC marker ---- */
.twinunit { display: flex; flex-direction: column; gap: 6px; padding: 6px;
  border: 2px dashed var(--accent-ring); border-radius: 16px;
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--inset-hi); }
.acdot { margin-left: auto; font-size: 12px; font-weight: 800; color: var(--accent);
  background: var(--accent-soft); padding: 4px 11px; border-radius: 999px; letter-spacing: .3px; }

/* ---- Centered login form (no demo box): centred headings, even full-width fields ---- */
.login-form { text-align: center; }
.login-form .field { text-align: left; }
.login-form .infobox { text-align: left; }

/* ---- Floor island legend dots (fixed small circles) ---- */
.legend { display: inline-flex; align-items: center; gap: 6px; }
.legend .dot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; flex: none; }
.legend .dot.blue { background: #2f6fb3; }
.legend .dot.red { background: #be4338; }
.legend .dot.amber { background: #cf8f23; }

/* ---- Activity Log: filter tabs + failed-login entries ---- */
.log-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.log-tab {
  padding: 7px 14px; border-radius: 999px; cursor: pointer; font: inherit;
  font-size: 13px; font-weight: 600; color: var(--accent-2);
  border: 1px solid var(--hairline-2); background: var(--fill-2);
}
.log-tab:hover { background: var(--fill-strong); }
.log-tab.active { background: var(--accent); border-color: var(--accent); color: var(--on-fill); }
.log-tab-n { margin-left: 5px; opacity: 0.6; font-weight: 500; }
.log-tab.active .log-tab-n { opacity: 0.85; }
.logrow.log-fail .log-ic { color: var(--danger); background: var(--danger-soft); }

/* =========================================================================
   LUXURY REFINEMENT LAYER — loaded last; overrides by source order so the
   existing rules stay intact. Typography, numerals, focus, selection, motion.
   ========================================================================= */

/* Warm text selection. */
::selection { background: var(--selection); color: var(--text); }
::-moz-selection { background: var(--selection); color: var(--text); }

/* An elegant, visible focus ring on interactive elements that lack a bespoke
   one (icon buttons, tabs, segmented controls, cards-as-buttons, links). The
   more-specific .input:focus / .btn:focus-visible rules still win where set. */
a:focus-visible, button:focus-visible, select:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--accent-ring), 0 0 0 4.5px var(--gold-line);
}

/* Display headings: let SIZE + AIR carry hierarchy, not heavy weight. Fraunces
   settles to 500–600 with tighter tracking and line-height. */
.login-brand h1, .page-head h1 {
  font-weight: 500; letter-spacing: -0.6px; line-height: 1.06;
}
.login-form h2, .modal h3, .detail h3, .camp-head .nm,
.fc-name, h3.island-title, .side-brand .t1 {
  font-weight: 600; letter-spacing: -0.3px;
}

/* Numerals align in columns everywhere figures appear. */
.stat .num, .counter .big, .fc-num, .grp-count, .dl-meta b, .dl-meta,
.beds-summary .bs-num b, .tile .no, .bed-dot, .filter-count, .log-when,
.log-tab-n, .kv .v, .bc-student, .bc-meta, .pwlog-row .sub {
  font-variant-numeric: tabular-nums lining-nums;
}
.stat .num, .counter .big, .fc-num { font-weight: 600; }

/* Eyebrows / section labels: one muted ink, one consistent tracking. */
.eyebrow, .side-section, .grp-head { letter-spacing: var(--tracking-eyebrow); color: var(--muted); }

/* Editorial-italic voice for empty states + leads (the cheapest "premium" tell). */
.empty h4 { font-family: var(--font-display); font-weight: 500; letter-spacing: -0.2px; }
.empty p { font-style: italic; }
.login-brand .lead { letter-spacing: -0.1px; }

/* Comfortable measure on prose. */
.login-brand p, .infobox { max-width: 64ch; }

/* The hero login card floats on the deepest, softest light. */
.login-card { box-shadow: var(--shadow-lg); }

/* Keep the gilt active indicator slim + precious (pure gold, not espresso). */
.nav-item.active::before {
  width: 2.5px; height: 20px;
  background: linear-gradient(180deg, var(--gold-2), var(--gold));
}

/* Graceful fallback where backdrop-filter is unsupported: solid ivory panels. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass, .modal, .toast, .topbar { background: var(--glass-3); }
}

/* Respect reduced-motion globally — one quiet, optional flourish at most. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important; scroll-behavior: auto !important;
  }
  .blob { animation: none; }
}

/* =========================================================================
   PHASE 2 — login hero details + skeleton loaders
   ========================================================================= */

/* Login brand panel: a scarce gilt eyebrow, a hairline rule, a secure footer —
   the quiet cues of a private reception desk. Gold lives here, on the hero. */
.brand-eyebrow {
  font-family: var(--font); font-size: var(--fs-eyebrow); font-weight: 700;
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
  color: var(--gold); margin-bottom: 10px;
}
.brand-rule {
  width: 64px; height: 1px; margin: 18px 0; border: none;
  background: linear-gradient(90deg, var(--gold-line), transparent);
}
.login-foot {
  display: flex; align-items: center; gap: 8px; margin-top: 22px;
  padding-top: 16px; border-top: 1px solid var(--hairline);
  font-size: var(--fs-xs); color: var(--muted);
}
.login-foot svg { width: 14px; height: 14px; color: var(--gold); flex: none; }
@media (max-width: 960px) {
  .brand-rule { margin: 12px auto; }       /* centered with the stacked brand */
  .login-foot { justify-content: center; }
}

/* Skeleton loaders — shimmering ivory blocks that mirror the real layout, so
   the page never flashes raw "Loading…" text. */
.skel { position: relative; overflow: hidden;
  background: var(--skel-base); border-radius: 7px; }
.skel::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, var(--skel-sweep), transparent);
  animation: shimmer 1.5s var(--ease) infinite;
}
@keyframes shimmer { 100% { transform: translateX(100%); } }
.skel-stat { display: flex; align-items: center; gap: 16px; }
.skel-chip { width: 46px; height: 46px; border-radius: 12px; flex: none; }
.skel-bd { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.skel-ln { height: 12px; border-radius: 6px; width: 100%; }
.skel-ln.sm { height: 10px; }
.skel-ln.w30 { width: 30%; } .skel-ln.w40 { width: 40%; } .skel-ln.w50 { width: 50%; }
.skel-ln.w60 { width: 60%; } .skel-ln.w70 { width: 70%; } .skel-ln.w80 { width: 80%; }
.skel-rows { padding: 6px; }
.skel-row { display: flex; align-items: center; gap: 14px; padding: 12px 8px;
  border-bottom: 1px solid var(--hairline); }
.skel-row:last-child { border-bottom: none; }

/* =========================================================================
   PHASE 3 — mobile: modals/islands fit the dynamic viewport + spacing polish
   ========================================================================= */

/* Toasts clear the home indicator on phones (env = 0 on desktop, so no change). */
#toasts { bottom: max(26px, calc(env(safe-area-inset-bottom) + 14px)); }

@media (max-width: 960px) {
  /* THE FIX for clipped islands: dvh tracks the visible area as Safari's address
     and tool bars show/hide, so modals never get cut off top or bottom. The
     overlay can also scroll, and safe-area padding clears notches. */
  .modal-overlay {
    place-items: center; overflow-y: auto; -webkit-overflow-scrolling: touch;
    padding: max(12px, env(safe-area-inset-top)) 8px max(12px, env(safe-area-inset-bottom));
  }
  .modal { max-height: calc(100dvh - 24px); }
  .modal.island, .modal.floor-island {
    width: 96vw; max-width: 96vw;
    height: calc(100dvh - 24px); max-height: calc(100dvh - 24px); padding: 16px 14px;
  }
  .modal.compact { height: auto; }

  /* A little more air so the phone layout reads considered, not cramped, and the
     content clears the home indicator. */
  .main { padding: 18px 16px calc(20px + env(safe-area-inset-bottom)); }
  .page-head { margin-bottom: 16px; }
  .panel { padding: 16px 14px; }
  .modal-actions .btn { flex: 1; }       /* full, tappable modal buttons */
  .nav-item { padding: 13px 12px; }      /* bigger touch targets in the drawer */
  .topbar { border-bottom: 1px solid var(--hairline); }
  .side-brand { padding-top: max(10px, env(safe-area-inset-top)); }
}

/* Mobile topbar: match the desktop brand exactly — a Fraunces wordmark and a
   rounded white logo badge with a gilt hairline (not the bare image). */
@media (max-width: 960px) {
  .tb-title { font-family: var(--font-display); font-weight: 600; letter-spacing: -0.3px; }
  .tb-logo {
    width: 36px; height: 36px; padding: 4px; background: #fff;
    border-radius: 9px; object-fit: contain; flex: none;
    box-shadow: inset 0 0 0 1px var(--gold-line), var(--shadow-sm);
  }
}

/* ---- Global finish: crisp type, palette-matched form controls, clean taps ---- */
:root { accent-color: var(--accent); }
body {
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  -webkit-tap-highlight-color: transparent;
}

/* Floor plan: never force a room column wider than its container, so rooms can't
   spill out of blocks and blocks out of floors. min(340px, 100%) collapses to a
   single full-width column when space is tight (mobile, nested padding). */
.rooms, .block-rooms {
  grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr));
}
@media (max-width: 960px) {
  .rooms, .block-rooms { gap: 8px; }
  .floor { padding: 12px; }
  .block { padding: 10px; }
  .room { padding: 12px; }
  .beds { gap: 6px; }
}

/* ====================================================================== */
/* Room types · CLASS blocks · classrooms · AC tickets (2026-06 update)    */
/* ====================================================================== */

/* Generic green accent for "free / available" counts (Floors + Beds tabs). */
.okc { color: var(--ok); }

/* Floor plan: the "Add block / Add CLASS block" button row. */
.fp-addrow { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }

/* CLASS block: a tinted badge + a classroom card with no beds. */
.block-badge.class { width: auto; min-width: 30px; padding: 0 9px; font-size: 10px; letter-spacing: .4px;
  background: linear-gradient(155deg, var(--accent-soft), var(--gold-soft));
  box-shadow: inset 0 0 0 1px var(--accent-ring); color: var(--accent); }
.room-class .chip-sm { color: var(--accent); }

/* Room-type badge on a hostel room header. */
.typebadge { font-size: 10px; font-weight: 700; padding: 2px 8px; border-radius: 6px;
  background: var(--accent-soft); color: var(--accent); white-space: nowrap; }

/* "Add rooms" room-type selector. */
.typegrid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.typeopt { display: flex; flex-direction: column; gap: 2px; align-items: flex-start;
  padding: 10px 12px; border-radius: 10px; border: 1px solid var(--hairline);
  background: var(--fill-2); cursor: pointer; text-align: left; }
.typeopt:hover { border-color: var(--accent-ring); }
.typeopt.active { border-color: var(--accent); background: var(--fill-strong);
  box-shadow: 0 0 0 3px var(--accent-soft); }
.topt-label { font-size: 13px; font-weight: 700; color: var(--text); }
.topt-sub { font-size: 11px; color: var(--muted); }

/* AC complaint tickets (one card per open complaint). */
.ticket { border: 1px solid var(--hairline); border-radius: 10px; padding: 10px 12px;
  margin-bottom: 8px; background: var(--fill-1); }
.ticket-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ticket-notes { font-size: 12px; color: var(--text-2); margin: 6px 0; }

/* =========================================================================
   THEMES — admin-selectable palettes. Each block only re-points the design
   tokens defined in :root; every component reads those tokens, so the whole
   app re-skins from here. js/theme.js sets <html data-theme="…"> before paint
   and the value is global (stored server-side, delivered via bootstrap()).
   :root[data-theme] outspecifies :root, so order vs. the base doesn't matter.
   ESPRESSO is the bare :root (no block needed). Print is unaffected — it
   resets to black-on-white with !important and its own literal colours.
   ========================================================================= */

/* ---- COBALT GLASS — cool, crisp, institutional (light) ------------------ */
:root[data-theme="cobalt"] {
  --accent: #2563eb; --accent-2: #1e40af; --accent-3: #3b82f6;
  --accent-soft: rgba(37,99,235,0.09); --accent-ring: rgba(37,99,235,0.30);
  --gold: #2563eb; --gold-2: #60a5fa; --gold-soft: rgba(37,99,235,0.12); --gold-line: rgba(37,99,235,0.34);
  --gilt-ring: rgba(96,165,250,0.30);
  --ok: #16a34a; --ok-soft: rgba(22,163,74,0.13);
  --fault: #dc2626; --fault-soft: rgba(220,38,38,0.10);
  --danger: #dc2626; --danger-soft: rgba(220,38,38,0.10);
  --warn: #b45309; --warn-soft: rgba(217,119,6,0.15);
  --text: #0f1b2d; --text-1: #0f1b2d; --text-2: #33425a; --muted: #5b6b82; --faint: #9aa7ba;
  --glass: rgba(255,255,255,0.58); --glass-2: rgba(255,255,255,0.72); --glass-3: rgba(255,255,255,0.92);
  --card: rgba(255,255,255,0.66); --stroke: rgba(255,255,255,0.85);
  --hairline: rgba(15,27,45,0.09); --hairline-2: rgba(15,27,45,0.15); --selection: rgba(37,99,235,0.16);
  --shadow-sm: 0 1px 2px rgba(15,30,60,0.05), 0 6px 16px rgba(15,30,60,0.07);
  --shadow: 0 2px 6px rgba(15,30,60,0.06), 0 16px 38px rgba(15,30,60,0.10);
  --shadow-lg: 0 4px 12px rgba(15,30,60,0.07), 0 30px 70px rgba(15,30,60,0.14);
  --shadow-gold: 0 6px 18px rgba(37,99,235,0.18);
  --opt-bg: #ffffff;
  --ink-wash: rgba(15,27,45,0.05); --ink-wash-2: rgba(15,27,45,0.09);
  --scrollbar: rgba(37,99,235,0.22); --scrollbar-h: rgba(37,99,235,0.40);
  --overlay: rgba(13,22,40,0.34); --island-bg: #eef3fb;
  --skel-base: rgba(37,99,235,0.08); --skel-sweep: rgba(255,255,255,0.60);
  --body-bg: #eaf0f8;
  --bg-grad:
    radial-gradient(1100px 820px at 14% -5%, #fbfdff 0%, transparent 58%),
    radial-gradient(900px 700px at 100% 0%, #e3edfb 0%, transparent 55%),
    linear-gradient(168deg, #f4f8fe 0%, #e8f0fb 60%, #dde8f7 100%);
  --blob-1: #d6e6fb; --blob-2: #c7dbf6; --blob-3: #e3eefc; --blob-4: #d0e0f7;
  --brand-grad:
    radial-gradient(420px 320px at 80% 10%, rgba(96,165,250,0.22) 0%, transparent 60%),
    linear-gradient(160deg, rgba(37,99,235,0.13) 0%, rgba(59,130,246,0.16) 100%);
  --caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%235b6b82' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><path d='M4 6l4 4 4-4'/></svg>");
}

/* ---- BOTANIC — fresh, organic, green (light) ---------------------------- */
:root[data-theme="botanic"] {
  --accent: #0f766e; --accent-2: #0b554f; --accent-3: #15a394;
  --accent-soft: rgba(15,118,110,0.10); --accent-ring: rgba(15,118,110,0.30);
  --gold: #0f766e; --gold-2: #3cbfae; --gold-soft: rgba(15,118,110,0.12); --gold-line: rgba(15,118,110,0.34);
  --gilt-ring: rgba(60,191,174,0.30);
  --ok: #4d7c0f; --ok-soft: rgba(77,124,15,0.14);
  --fault: #c2410c; --fault-soft: rgba(194,65,12,0.11);
  --danger: #b91c1c; --danger-soft: rgba(185,28,28,0.10);
  --warn: #a16207; --warn-soft: rgba(161,98,7,0.15);
  --text: #14241b; --text-1: #14241b; --text-2: #33473b; --muted: #5e7163; --faint: #9aab9e;
  --glass: rgba(250,253,249,0.58); --glass-2: rgba(250,253,249,0.72); --glass-3: rgba(249,253,248,0.92);
  --card: rgba(250,253,249,0.66); --stroke: rgba(255,255,255,0.82);
  --hairline: rgba(20,40,30,0.10); --hairline-2: rgba(20,40,30,0.16); --selection: rgba(15,118,110,0.16);
  --shadow-sm: 0 1px 2px rgba(20,45,32,0.05), 0 6px 16px rgba(20,45,32,0.07);
  --shadow: 0 2px 6px rgba(20,45,32,0.05), 0 16px 38px rgba(20,45,32,0.10);
  --shadow-lg: 0 4px 12px rgba(20,45,32,0.06), 0 30px 70px rgba(20,45,32,0.14);
  --shadow-gold: 0 6px 18px rgba(15,118,110,0.16);
  --opt-bg: #f7fbf6;
  --ink-wash: rgba(20,40,30,0.05); --ink-wash-2: rgba(20,40,30,0.09);
  --scrollbar: rgba(15,118,110,0.22); --scrollbar-h: rgba(15,118,110,0.38);
  --overlay: rgba(16,34,26,0.34); --island-bg: #eef4ec;
  --skel-base: rgba(15,118,110,0.08); --skel-sweep: rgba(255,255,255,0.55);
  --body-bg: #e7efe6;
  --bg-grad:
    radial-gradient(1100px 820px at 14% -5%, #f7fcf5 0%, transparent 58%),
    radial-gradient(900px 700px at 100% 0%, #e4f0e2 0%, transparent 55%),
    linear-gradient(168deg, #f2f8f0 0%, #e8f1e6 60%, #dde9da 100%);
  --blob-1: #d8ead2; --blob-2: #c8e0c5; --blob-3: #e6f1e1; --blob-4: #d2e6cf;
  --brand-grad:
    radial-gradient(420px 320px at 80% 10%, rgba(60,191,174,0.20) 0%, transparent 60%),
    linear-gradient(160deg, rgba(15,118,110,0.14) 0%, rgba(21,163,148,0.16) 100%);
  --caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%235e7163' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><path d='M4 6l4 4 4-4'/></svg>");
}

/* ---- MIDNIGHT — deep blue-black, electric cyan (dark) ------------------- */
:root[data-theme="midnight"] {
  --accent: #22d3ee; --accent-2: #0891b2; --accent-3: #67e8f9;
  --accent-soft: rgba(34,211,238,0.12); --accent-ring: rgba(34,211,238,0.40);
  --gold: #38bdf8; --gold-2: #7dd3fc; --gold-soft: rgba(56,189,248,0.16); --gold-line: rgba(56,189,248,0.42);
  --gilt-ring: rgba(125,211,252,0.26);
  --ok: #34d399; --ok-soft: rgba(52,211,153,0.16);
  --fault: #f87171; --fault-soft: rgba(248,113,113,0.16);
  --danger: #f87171; --danger-soft: rgba(248,113,113,0.16);
  --warn: #fbbf24; --warn-soft: rgba(251,191,36,0.16);
  --text: #e8edf7; --text-1: #f1f5fc; --text-2: #aebbd0; --muted: #8493ad; --faint: #5d6a83;
  --glass: rgba(255,255,255,0.06); --glass-2: rgba(255,255,255,0.08); --glass-3: #161d2e;
  --card: rgba(255,255,255,0.05); --stroke: rgba(255,255,255,0.10);
  --hairline: rgba(255,255,255,0.09); --hairline-2: rgba(255,255,255,0.15); --selection: rgba(34,211,238,0.28);
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.40), 0 6px 16px rgba(0,0,0,0.45);
  --shadow: 0 2px 6px rgba(0,0,0,0.45), 0 16px 38px rgba(0,0,0,0.55);
  --shadow-lg: 0 4px 12px rgba(0,0,0,0.50), 0 30px 70px rgba(0,0,0,0.60);
  --shadow-gold: 0 6px 22px rgba(34,211,238,0.22);
  --fill-1: rgba(255,255,255,.03); --fill-2: rgba(255,255,255,.055);
  --fill-3: rgba(255,255,255,.10); --fill-strong: rgba(255,255,255,.14);
  --inset-hi: rgba(255,255,255,.06);
  --on-fill: #04131c;                  /* dark ink on the bright cyan/status fills */
  --opt-bg: #161d2e;
  --ink-wash: rgba(255,255,255,0.05); --ink-wash-2: rgba(255,255,255,0.10);
  --scrollbar: rgba(255,255,255,0.16); --scrollbar-h: rgba(255,255,255,0.30);
  --overlay: rgba(3,6,14,0.62); --island-bg: #11182a;
  --skel-base: rgba(255,255,255,0.06); --skel-sweep: rgba(255,255,255,0.10);
  --body-bg: #0a0e1a;
  --bg-grad:
    radial-gradient(1100px 820px at 14% -5%, #101a30 0%, transparent 58%),
    radial-gradient(900px 700px at 100% 0%, #0c1424 0%, transparent 55%),
    linear-gradient(168deg, #0b1120 0%, #0a0e1a 60%, #080b14 100%);
  --blob-1: #0e7490; --blob-2: #1e3a8a; --blob-3: #155e75; --blob-4: #0c4a6e;
  --grain-opacity: 0.05; --grain-blend: overlay;
  --brand-grad:
    radial-gradient(420px 320px at 80% 10%, rgba(34,211,238,0.18) 0%, transparent 60%),
    linear-gradient(160deg, rgba(14,116,144,0.30) 0%, rgba(8,47,73,0.42) 100%);
  --caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%238493ad' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><path d='M4 6l4 4 4-4'/></svg>");
}

/* ---- INDIGO NOIR — charcoal-violet, scarce amber (dark) ----------------- */
:root[data-theme="indigo"] {
  --accent: #818cf8; --accent-2: #6366f1; --accent-3: #a5b4fc;
  --accent-soft: rgba(129,140,248,0.13); --accent-ring: rgba(129,140,248,0.40);
  --gold: #e0b15a; --gold-2: #f0cd86; --gold-soft: rgba(224,177,90,0.16); --gold-line: rgba(224,177,90,0.42);
  --gilt-ring: rgba(224,177,90,0.30);
  --ok: #4ade80; --ok-soft: rgba(74,222,128,0.15);
  --fault: #fb7185; --fault-soft: rgba(251,113,133,0.16);
  --danger: #fb7185; --danger-soft: rgba(251,113,133,0.16);
  --warn: #fbbf24; --warn-soft: rgba(251,191,36,0.15);
  --text: #ece9f5; --text-1: #f4f1fb; --text-2: #b7b0cf; --muted: #8e86a8; --faint: #655d7e;
  --glass: rgba(255,255,255,0.06); --glass-2: rgba(255,255,255,0.08); --glass-3: #1b1828;
  --card: rgba(255,255,255,0.05); --stroke: rgba(255,255,255,0.10);
  --hairline: rgba(255,255,255,0.09); --hairline-2: rgba(255,255,255,0.15); --selection: rgba(129,140,248,0.30);
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.45), 0 6px 16px rgba(0,0,0,0.50);
  --shadow: 0 2px 6px rgba(0,0,0,0.50), 0 16px 38px rgba(0,0,0,0.60);
  --shadow-lg: 0 4px 12px rgba(0,0,0,0.55), 0 30px 70px rgba(0,0,0,0.65);
  --shadow-gold: 0 6px 22px rgba(224,177,90,0.20);
  --fill-1: rgba(255,255,255,.03); --fill-2: rgba(255,255,255,.055);
  --fill-3: rgba(255,255,255,.10); --fill-strong: rgba(255,255,255,.14);
  --inset-hi: rgba(255,255,255,.06);
  --on-fill: #150f24;                  /* dark ink on the bright periwinkle/status fills */
  --opt-bg: #1b1828;
  --ink-wash: rgba(255,255,255,0.05); --ink-wash-2: rgba(255,255,255,0.10);
  --scrollbar: rgba(255,255,255,0.16); --scrollbar-h: rgba(255,255,255,0.30);
  --overlay: rgba(6,4,12,0.64); --island-bg: #161324;
  --skel-base: rgba(255,255,255,0.06); --skel-sweep: rgba(255,255,255,0.10);
  --body-bg: #0f0d17;
  --bg-grad:
    radial-gradient(1100px 820px at 14% -5%, #1a1630 0%, transparent 58%),
    radial-gradient(900px 700px at 100% 0%, #15122a 0%, transparent 55%),
    linear-gradient(168deg, #131022 0%, #0f0d17 60%, #0b0912 100%);
  --blob-1: #4338ca; --blob-2: #6d28d9; --blob-3: #3730a3; --blob-4: #5b21b6;
  --grain-opacity: 0.05; --grain-blend: overlay;
  --brand-grad:
    radial-gradient(420px 320px at 80% 10%, rgba(224,177,90,0.16) 0%, transparent 60%),
    linear-gradient(160deg, rgba(99,102,241,0.30) 0%, rgba(67,56,202,0.40) 100%);
  --caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%238e86a8' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><path d='M4 6l4 4 4-4'/></svg>");
}

/* ---- MONOCHROME — pure black & white, white background (light) ---------- */
:root[data-theme="mono"] {
  --accent: #111111; --accent-2: #000000; --accent-3: #333333;
  --accent-soft: rgba(0,0,0,0.06); --accent-ring: rgba(0,0,0,0.32);
  --gold: #1a1a1a; --gold-2: #444444; --gold-soft: rgba(0,0,0,0.08); --gold-line: rgba(0,0,0,0.30);
  --gilt-ring: rgba(0,0,0,0.20);
  --ok: #1a1a1a; --ok-soft: rgba(0,0,0,0.07);
  --fault: #000000; --fault-soft: rgba(0,0,0,0.07);
  --danger: #000000; --danger-soft: rgba(0,0,0,0.07);
  --warn: #333333; --warn-soft: rgba(0,0,0,0.09);
  --text: #0a0a0a; --text-1: #0a0a0a; --text-2: #3a3a3a; --muted: #666666; --faint: #9b9b9b;
  --glass: rgba(255,255,255,0.58); --glass-2: rgba(255,255,255,0.74); --glass-3: rgba(255,255,255,0.94);
  --card: rgba(255,255,255,0.70); --stroke: rgba(255,255,255,0.92);
  --hairline: rgba(0,0,0,0.10); --hairline-2: rgba(0,0,0,0.17); --selection: rgba(0,0,0,0.14);
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.05), 0 6px 16px rgba(0,0,0,0.06);
  --shadow: 0 2px 6px rgba(0,0,0,0.06), 0 16px 38px rgba(0,0,0,0.10);
  --shadow-lg: 0 4px 12px rgba(0,0,0,0.07), 0 30px 70px rgba(0,0,0,0.14);
  --shadow-gold: 0 6px 18px rgba(0,0,0,0.14);
  --opt-bg: #ffffff;
  --ink-wash: rgba(0,0,0,0.04); --ink-wash-2: rgba(0,0,0,0.08);
  --scrollbar: rgba(0,0,0,0.22); --scrollbar-h: rgba(0,0,0,0.42);
  --overlay: rgba(0,0,0,0.42); --island-bg: #f4f4f4;
  --skel-base: rgba(0,0,0,0.07); --skel-sweep: rgba(255,255,255,0.62);
  --body-bg: #ffffff;
  --bg-grad:
    radial-gradient(1100px 820px at 14% -5%, #ffffff 0%, transparent 58%),
    radial-gradient(900px 700px at 100% 0%, #f6f6f6 0%, transparent 55%),
    linear-gradient(168deg, #ffffff 0%, #fafafa 60%, #f1f1f1 100%);
  --blob-1: #efefef; --blob-2: #e6e6e6; --blob-3: #f5f5f5; --blob-4: #ececec;
  --grain-opacity: 0.015;
  --brand-grad:
    radial-gradient(420px 320px at 80% 10%, rgba(0,0,0,0.05) 0%, transparent 60%),
    linear-gradient(160deg, rgba(0,0,0,0.07) 0%, rgba(0,0,0,0.11) 100%);
  --caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%23666666' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'><path d='M4 6l4 4 4-4'/></svg>");
}

/* =========================================================================
   THEME PICKER — admin-only control rendered in the profile modal. Styled
   from tokens, so it looks right in every palette it can switch to.
   ========================================================================= */
.theme-grid { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 2px; }
.theme-card { display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 10px 12px; border-radius: var(--radius-xs); cursor: pointer; color: var(--text);
  border: 1px solid var(--hairline); background: var(--fill-2); font-family: var(--font);
  transition: border-color .15s, background .15s, transform .08s; }
.theme-card:hover { border-color: var(--accent-ring); background: var(--fill-strong); }
.theme-card:active { transform: translateY(1px); }
.theme-card.active { border-color: var(--accent); background: var(--accent-soft); }
.tc-sw { display: inline-flex; flex: none; border-radius: 7px; overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--hairline-2); }
.tc-sw .ts { width: 16px; height: 30px; display: block; }
.tc-meta { display: flex; flex-direction: column; min-width: 0; }
.tc-name { font-size: 13.5px; font-weight: 700; }
.tc-sub { font-size: 11.5px; color: var(--muted); }
.tc-check { margin-left: auto; flex: none; color: var(--accent); opacity: 0;
  display: grid; place-items: center; transition: opacity .15s; }
.theme-card.active .tc-check { opacity: 1; }

/* ---- Courses screen ----
   Year (section) → Group (card) → Course (row). The year heading is the one
   confident element; everything below it stays quiet and disciplined. */
.co-wrap { display: flex; flex-direction: column; gap: 30px; padding-top: 18px; }
.co-year { display: flex; flex-direction: column; gap: 12px; }

/* Year section header: serif title + student total, edit actions to the right. */
.co-year-head-row { display: flex; align-items: baseline; gap: 12px;
  padding-bottom: 10px; border-bottom: 1px solid var(--hairline); }
.co-year-title { font-size: 22px; line-height: 1.1; }
.co-year-total { font-size: 12.5px; font-weight: 600; color: var(--muted); }
.co-year-actions { display: flex; align-items: center; gap: 4px; margin-left: auto; }
.co-year-note { font-size: 12.5px; color: var(--muted); margin: -4px 0 2px; }

/* Group card */
.co-group { padding: 14px 16px; }
.co-grp-head { display: flex; align-items: center; gap: 9px; margin-bottom: 8px;
  padding-bottom: 8px; border-bottom: 1px solid var(--hairline); }
.co-grp-name { font-size: 14px; font-weight: 700; }
.co-grp-count { font-size: 13px; font-weight: 800; color: var(--muted);
  background: var(--fill-2); border-radius: 20px; padding: 2px 11px; flex: none;
  font-variant-numeric: tabular-nums; }
.co-grp-actions { display: flex; align-items: center; gap: 2px; margin-left: auto; }

/* Course rows */
.co-courses { display: flex; flex-direction: column; gap: 2px; }
.co-course-row { display: flex; align-items: center; gap: 10px; padding: 6px 4px;
  border-radius: 8px; }
.co-course-row:hover { background: var(--fill-strong); }
.co-course-row.has-camps { align-items: flex-start; padding-top: 7px; padding-bottom: 7px; }
.co-course-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.co-course-camps { display: flex; flex-wrap: wrap; gap: 4px; }
.co-camp-chip { font-size: 10.5px; font-weight: 600; color: var(--muted);
  background: var(--fill-2); border-radius: 5px; padding: 1px 6px; white-space: nowrap; }
.co-camp-chip.none { color: var(--muted); background: transparent; padding-left: 0;
  font-style: italic; font-weight: 500; }
.co-course-name { font-size: 13.5px; font-weight: 600; min-width: 0; flex: 1; }
.co-course-count { font-size: 15.5px; font-weight: 800; color: var(--accent);
  background: var(--accent-soft); border-radius: 20px; padding: 3px 12px; flex: none;
  min-width: 34px; text-align: center; line-height: 1.15; letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums; box-shadow: inset 0 0 0 1px var(--accent-ring); }
.co-course-count.empty { color: var(--muted); background: var(--fill-2); box-shadow: none; }
.co-course-actions { display: flex; gap: 2px; flex: none; }

.co-empty { font-size: 12.5px; color: var(--muted); padding: 2px 2px 6px; }
.co-empty.sm { padding: 4px 4px 2px; }
.co-del:hover { color: var(--danger); }
.co-add-bar { display: flex; gap: 8px; justify-content: flex-start; padding-top: 6px; }
.btn-sm { height: 32px; padding: 0 12px; font-size: 12.5px; gap: 6px; }
.btn-sm svg { width: 14px; height: 14px; }
@media (max-width: 640px) {
  .co-year-head-row { flex-wrap: wrap; }
  .co-year-actions { margin-left: 0; width: 100%; }
  .co-course-name { font-size: 13px; }
  .co-course-actions { gap: 0; }
}

/* ---- Public-demo notice (demo fork only) -------------------------------- */
.demo-ribbon {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 2000;
  padding: 6px 14px; text-align: center;
  font-size: 12px; line-height: 1.4; letter-spacing: .01em;
  background: rgba(20, 16, 12, .88); color: #f5eee6;
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  border-top: 1px solid rgba(255, 255, 255, .14);
}
.demo-ribbon b { font-weight: 700; }
.demo-creds {
  margin-top: 10px; padding: 8px 10px; border-radius: 10px;
  font-size: 12.5px; line-height: 1.5;
  background: rgba(0, 0, 0, .06); border: 1px dashed rgba(0, 0, 0, .25);
}
.demo-creds code {
  font-size: 12px; padding: 1px 5px; border-radius: 6px;
  background: rgba(0, 0, 0, .08);
}
