:root {
  --sidebar-w: 250px;
  /* Academic steel-blue + a sparing brass/gold accent — a palette grounded
     in "serious school administration tool" rather than generic SaaS
     blue-purple. Brand drives interactive elements (buttons, links,
     active states); accent is used sparingly for a couple of deliberate
     highlight moments (active nav indicator, stat icon rings) rather than
     wallpapered everywhere. */
  --brand: #2A5C8A;
  --brand-dark: #1D4568;
  --accent: #C89B3C;
  --accent-soft: #F7EFDC;
  --font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --ink: #171B24;
  --muted: #667085;
  --hairline: #E7EAEF;
  --sidebar-bg: #ffffff;
  --sidebar-border: #edeef1;
  --sidebar-hover: #f4f5f8;
  --sidebar-active-bg: #EEF3F8;
  --sidebar-active-fg: var(--brand);
  --radius-lg: 12px;
  --radius-md: 9px;
  --shadow-sm: 0 1px 2px rgba(23,27,36,.05);
  --shadow-md: 0 2px 6px rgba(23,27,36,.06), 0 10px 24px rgba(23,27,36,.05);
}
* { box-sizing: border-box; }
html, body {
  background: #ffffff;
  font-family: var(--font-family);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  font-size: 14px;
}
h1, h2, h3, h4, h5, h6 { font-weight: 650; letter-spacing: -0.015em; color: var(--ink); }

.app-shell { min-height: 100vh; background: #ffffff; }
.app-sidebar {
  width: var(--sidebar-w); background: var(--sidebar-bg); color: #4b5160; flex-shrink: 0;
  position: fixed; top: 0; bottom: 0; left: 0; overflow-y: auto; z-index: 1030; transition: transform .2s;
  border-right: 1px solid var(--sidebar-border);
}
.sidebar-brand { padding: 1.25rem 1.4rem; font-weight: 700; font-size: 1.08rem; color: var(--ink); border-bottom: 1px solid var(--sidebar-border); letter-spacing: -.01em; position: relative; }
.sidebar-brand::after { content: ""; position: absolute; left: 1.4rem; right: 1.4rem; bottom: -1px; height: 2px; background: linear-gradient(90deg, var(--brand), var(--accent)); border-radius: 2px; opacity: .55; }
.sidebar-brand i { color: var(--brand); margin-right: .5rem; }
.sidebar-nav { padding: .85rem .65rem; display: flex; flex-direction: column; gap: 1px; }
.sidebar-nav .nav-link { color: #565c6b; padding: .58rem .8rem; border-radius: var(--radius-md); font-size: .855rem; font-weight: 500; transition: background .15s ease, color .15s ease, padding-left .15s ease; display: flex; align-items: center; border-left: 2.5px solid transparent; }
.sidebar-nav .nav-link i { color: #9aa0ad; width: 18px; transition: color .15s ease; }
.sidebar-nav .nav-link:hover { background: var(--sidebar-hover); color: var(--ink); padding-left: .95rem; }
.sidebar-nav .nav-link.active { background: var(--sidebar-active-bg); color: var(--sidebar-active-fg); font-weight: 600; border-left-color: var(--accent); }
.sidebar-nav .nav-link.active i { color: var(--sidebar-active-fg); }

/* .app-sidebar is position:fixed — taken out of normal flow entirely, so
   it never actually participates in a flex layout here. .app-main used to
   rely on `flex: 1` (inside a flex .app-shell) *plus* a manual margin-left
   to make room for it — flex-grow sizing combined with an extra margin on
   top is exactly the kind of thing that renders inconsistently across
   browsers/zoom levels, and was the cause of the page's content
   stopping short of the actual browser width with blank space beside it
   (reported in production). Sizing .app-main with an explicit
   width: calc(100% - sidebar width) instead removes that ambiguity —
   deterministic in every browser, no flex involved. */
.app-main { margin-left: var(--sidebar-w); width: calc(100% - var(--sidebar-w)); display: flex; flex-direction: column; min-width: 0; background: #ffffff; }
.app-topbar {
  height: 62px; background: #ffffff; border-bottom: 1px solid var(--hairline); display: flex; align-items: center;
  gap: 1rem; padding: 0 1.5rem; position: sticky; top: 0; z-index: 1020;
}
.topbar-search { position: relative; width: 280px; }
.topbar-search i { position: absolute; left: 12px; top: 10px; color: #9ca3af; font-size: .78rem; }
.topbar-search input { width: 100%; padding: 7px 12px 7px 32px; border-radius: var(--radius-md); border: 1px solid var(--hairline); background: #fafbfc; font-size: .84rem; transition: border-color .15s ease, background .15s ease; }
.topbar-search input:focus { outline: none; border-color: var(--brand); background: #fff; }
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: .4rem; }
.btn-icon { border: none; background: transparent; color: #5b6472; width: 36px; height: 36px; border-radius: 50%; transition: background .15s ease, color .15s ease; }
.btn-icon:hover { background: #f2f4f7; color: var(--brand); }
.notif-dot { position: absolute; top: 7px; right: 7px; width: 7px; height: 7px; background: #e0505a; border-radius: 50%; border: 1.5px solid #fff; }
.avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--brand); color: #fff; display: flex; align-items: center; justify-content: center; font-size: .74rem; font-weight: 600; flex-shrink: 0; }
.profile-btn { border: none; background: transparent; border-radius: var(--radius-md); padding: .3rem .5rem; }
.profile-btn:hover { background: #f7f8fa; }

.app-content { padding: 1.75rem 2rem; background: #ffffff; }

.stat-card { background: #ffffff; border-radius: var(--radius-lg); padding: 1.1rem 1.3rem; box-shadow: var(--shadow-sm); border: 1px solid var(--hairline); transition: box-shadow .2s ease, transform .2s ease, border-color .2s ease; }
.stat-card:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); border-color: #dfe2e8; }
.stat-card .stat-icon { width: 42px; height: 42px; border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; font-size: 1.05rem; }
.stat-card .stat-value { font-size: 1.5rem; font-weight: 700; color: var(--ink); letter-spacing: -.01em; }
.card-elevated { background: #ffffff; border-radius: var(--radius-lg); border: 1px solid var(--hairline); box-shadow: var(--shadow-sm); }

/* ---- Colorful icon badges — soft-tinted rounded squares used for subject/
   chapter icons, stat cards, and anywhere a vivid, distinct visual marker
   helps scanning (inspired by modern SaaS/HR dashboard kits: pastel fill +
   saturated icon color, never a flat gray icon). Deliberately independent
   of --brand (which stays tenant-customizable) so these read as a fixed,
   colorful system regardless of a tenant's chosen brand color. ---- */
.icon-badge {
  width: 46px; height: 46px; border-radius: 13px; display: flex; align-items: center; justify-content: center;
  font-size: 1.15rem; flex-shrink: 0;
}
.icon-badge.icon-badge-sm { width: 34px; height: 34px; border-radius: 10px; font-size: .92rem; }
.icon-badge-indigo { background: #EEF0FF; color: #4F46E5; }
.icon-badge-sky    { background: #E6F4FE; color: #0284C7; }
.icon-badge-emerald{ background: #E5F8EE; color: #059669; }
.icon-badge-amber  { background: #FEF3E0; color: #B45309; }
.icon-badge-rose   { background: #FDE8EE; color: #E11D48; }
.icon-badge-violet { background: #F2E9FE; color: #7C3AED; }
.icon-badge-teal   { background: #E1F7F5; color: #0D9488; }
.icon-badge-orange { background: #FEEBDD; color: #EA580C; }
.icon-badge-pink   { background: #FDE7F3; color: #DB2777; }

/* Subject/chapter cards — a clean tile with a colorful icon badge, used on
   the Learning Hub. Hover lift matches .stat-card for a consistent feel. */
.tile-card { background: #fff; border-radius: var(--radius-lg); border: 1px solid var(--hairline); box-shadow: var(--shadow-sm); padding: 1.15rem; transition: box-shadow .2s ease, transform .2s ease, border-color .2s ease; }
.tile-card:hover { box-shadow: var(--shadow-md); transform: translateY(-3px); border-color: #dfe2e8; }
.tile-card .tile-title { font-weight: 700; color: var(--ink); font-size: .98rem; letter-spacing: -.01em; margin-top: .7rem; }
.tile-card .tile-meta { color: var(--muted); font-size: .78rem; }

/* Chapter-number badge — a small gradient "pill" instead of plain text,
   using the tenant brand color so it stays on-theme while the subject/
   icon badges above stay fixed-palette. */
.chapter-num-badge {
  display: inline-flex; align-items: center; justify-content: center; min-width: 34px; height: 34px; padding: 0 .5rem;
  border-radius: 10px; font-weight: 700; font-size: .8rem; color: #fff; flex-shrink: 0;
  background: linear-gradient(135deg, var(--brand), var(--brand-dark));
}

/* ---- Mobile / any plain (non-DataTables) wide table: let the card
   scroll horizontally instead of overflowing the viewport. DataTables-
   managed tables (.datatable, below) handle their own scrolling via
   scrollX instead — giving both the plain-table rule and DataTables their
   own overflow container would nest two scrollbars around the same
   content, so this one is deliberately scoped to exclude .dataTables_wrapper. ---- */
.card-elevated:has(> table):not(:has(> .dataTables_wrapper)), .card-elevated:has(> .table-responsive) { overflow-x: auto; }

/* ---- DataTables with scrollX: true wraps the actual table in its own
   .dataTables_scroll / .dataTables_scrollBody strip, separate from the
   search box and pagination controls above/below it — that inner strip
   is what should scroll, not the whole card, so the toolbar and
   pagination stay put while only the grid itself pans sideways. Width is
   still forced to 100% so the table starts by filling the full card
   rather than whatever narrower width DataTables measured it at. ---- */
/* ---- DataTables with scrollX: true wraps the actual table in its own
   .dataTables_scroll / .dataTables_scrollBody strip, separate from the
   search box and pagination controls above/below it — that inner strip
   is what should scroll, not the whole card, so the toolbar and
   pagination stay put while only the grid itself pans sideways. Only the
   outer .dataTables_wrapper is forced to 100% here — NOT the <table>
   itself: scrollX clones the header into a second table and keeps both
   in sync with precise inline pixel widths DataTables computes itself,
   and forcing those to 100% !important (as an earlier version of this
   rule did) fights that math and breaks the sync between header and
   body, which is what was causing the whole toolbar+table to render
   misaligned/offset rather than actually scrolling cleanly. ---- */
.dataTables_wrapper { width: 100% !important; }
.dataTables_scrollBody { border-bottom: 1px solid var(--hairline); }
@media (max-width: 767px) {
  .app-content { padding: 1rem 1rem; }
  .stat-card { padding: .9rem 1rem; }
  .stat-card .stat-value { font-size: 1.25rem; }
  h4 { font-size: 1.15rem; }
  .card-elevated:not(:has(> .dataTables_wrapper)) { overflow-x: auto; }
  .chat-wrap { flex-direction: column; height: calc(100vh - 130px); }
  .chat-contacts { width: 100%; max-height: 40%; border-right: none; border-bottom: 1px solid var(--hairline); }
}

/* ---- Tables — dense, clean, Razorpay-style grid ---- */
.table { font-size: .855rem; color: var(--ink); margin-bottom: 0; }
.table thead th { font-weight: 600; font-size: .74rem; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); border-bottom: 1px solid var(--hairline); background: #fafbfc; padding: .65rem .9rem; white-space: nowrap; }
.table tbody td { padding: .62rem .9rem; border-color: var(--hairline); vertical-align: middle; }
.table-hover tbody tr:hover { background: #f9fafb; }
.table a { color: var(--brand); text-decoration: none; font-weight: 500; }
.table a:hover { text-decoration: underline; }

/* ---- Soft pill status badges (Razorpay-inspired) — overrides Bootstrap's
   solid text-bg-* badge fills sitewide without touching every view. ---- */
.badge { font-weight: 550; font-size: .72rem; padding: .34em .68em; border-radius: 999px; letter-spacing: .01em; }
.badge.text-bg-success { background: #e6f6ec !important; color: #1a8245 !important; }
.badge.text-bg-danger  { background: #fdeced !important; color: #c53030 !important; }
.badge.text-bg-warning { background: #fef6e0 !important; color: #b7791f !important; }
.badge.text-bg-info    { background: #e7f1fd !important; color: #2563eb !important; }
.badge.text-bg-secondary { background: #f1f2f5 !important; color: #6b7280 !important; }
.badge.text-bg-light   { background: #f4f5f7 !important; color: #4b5160 !important; border: 1px solid var(--hairline); }

.btn { font-weight: 550; border-radius: var(--radius-md); font-size: .84rem; transition: background .15s ease, border-color .15s ease, box-shadow .15s ease, transform .1s ease; }
.btn:active { transform: scale(.98); }
.btn-primary { background: var(--brand); border-color: var(--brand); }
.btn-primary:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
.btn-outline-primary { color: var(--brand); border-color: var(--brand); }
.btn-outline-primary:hover { background: var(--brand); border-color: var(--brand); }
.btn-outline-secondary { color: #4b5160; border-color: #d7dbe2; }
.btn-sm { font-size: .78rem; padding: .32rem .7rem; }

.form-control, .form-select { font-size: .845rem; border-radius: var(--radius-md); border-color: #d7dbe2; transition: border-color .15s ease, box-shadow .15s ease; }
.form-control:focus, .form-select:focus { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(42,92,138,.14); }
.form-label { font-weight: 600; color: #374151; font-size: .82rem; }

/* ---- Visible keyboard focus, distinct from the mouse-hover states above ---- */
a:focus-visible, button:focus-visible, .btn:focus-visible, .nav-link:focus-visible {
  outline: 2px solid var(--brand); outline-offset: 2px;
}

/* ---- Unify Bootstrap's default toggle-switch blue with the brand palette ---- */
.form-check-input:checked { background-color: var(--brand); border-color: var(--brand); }
.form-check-input:focus { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(42,92,138,.15); }
.form-switch .form-check-input { width: 2.4em; }

/* ---- Consistent icon treatment: bare glyph buttons get a soft circular
   hover/press background so icons read as deliberate controls, not stray
   symbols floating in whitespace. A brief scale nudge on press gives
   direct feedback that the click registered. ---- */
.btn-icon { display: inline-flex; align-items: center; justify-content: center; transition: background .15s ease, color .15s ease, transform .1s ease; }
.btn-icon:active { transform: scale(.92); }
h4 i.fa-solid, h5 i.fa-solid { font-size: .85em; opacity: .9; }

/* ---- Filter pill row (nav-tabs used as segmented filter chips) ---- */
.nav-tabs { border-bottom: 1px solid var(--hairline); gap: .25rem; }
.nav-tabs .nav-link { border: none; border-radius: var(--radius-md); color: var(--muted); font-weight: 550; font-size: .82rem; padding: .45rem .9rem; transition: background .15s ease, color .15s ease; }
.nav-tabs .nav-link:hover { background: #f4f5f8; border: none; }
.nav-tabs .nav-link.active { background: #f1f2f5; color: var(--ink); border: none; }

/* ---- DataTables generated controls — align with the rest of the design ---- */
.dataTables_filter input { border-radius: var(--radius-md); border: 1px solid var(--hairline); font-size: .84rem; padding: .35rem .6rem; margin-left: .4rem; }
.dataTables_filter input:focus { outline: none; border-color: var(--brand); }
.dataTables_length select { border-radius: 6px; border: 1px solid var(--hairline); font-size: .82rem; padding: .2rem 1.6rem .2rem .5rem; min-width: 4.5rem; width: auto; -webkit-appearance: menulist; appearance: menulist; }
.dataTables_info, .dataTables_length label, .dataTables_filter label { color: var(--muted); font-size: .8rem; }
.dataTables_paginate .paginate_button { border-radius: 6px !important; font-size: .8rem; padding: .3rem .65rem !important; margin-left: .2rem; border: 1px solid transparent !important; transition: background .15s ease; }
.dataTables_paginate .paginate_button.current { background: var(--brand) !important; color: #fff !important; border-color: var(--brand) !important; }
.dataTables_paginate .paginate_button:hover:not(.current) { background: #f4f5f8 !important; border-color: var(--hairline) !important; }

[data-bs-theme="dark"] html, [data-bs-theme="dark"] body { background: #0f1420; color: #e2e8f0; }
[data-bs-theme="dark"] .app-shell, [data-bs-theme="dark"] .app-main, [data-bs-theme="dark"] .app-content { background: #0f1420; }
[data-bs-theme="dark"] .app-sidebar { background: #161c2c; border-color: #232a3d; }
[data-bs-theme="dark"] .sidebar-brand { color: #e2e8f0; border-color: #232a3d; }
[data-bs-theme="dark"] .sidebar-nav .nav-link { color: #9aa5b8; }
[data-bs-theme="dark"] .sidebar-nav .nav-link i { color: #6b7688; }
[data-bs-theme="dark"] .sidebar-nav .nav-link:hover { background: #1e2536; color: #fff; }
[data-bs-theme="dark"] .sidebar-nav .nav-link.active { background: #26314f; color: #8fb0ff; border-left-color: var(--accent); }
[data-bs-theme="dark"] .sidebar-nav .nav-link.active i { color: #8fb0ff; }
[data-bs-theme="dark"] .app-topbar, [data-bs-theme="dark"] .stat-card, [data-bs-theme="dark"] .card-elevated, [data-bs-theme="dark"] table { background: #161c2c !important; color: #e2e8f0; border-color: #232a3d !important; }
/* Stat-icon chips use inline pastel colors (e.g. style="background:#eef2ff")
   set per-page for light mode — those washed-out pastels read poorly
   against a dark background, so override the background uniformly here
   (the inline icon *color* stays, since those accent hues are vibrant
   enough to stay legible on a dark chip without needing per-file changes). */
[data-bs-theme="dark"] .stat-icon { background: #1e2536 !important; }
[data-bs-theme="dark"] .table thead th { background: #1b2233 !important; color: #9aa5b8; }
[data-bs-theme="dark"] .table-hover tbody tr:hover { background: #1b2233 !important; }
[data-bs-theme="dark"] .table td, [data-bs-theme="dark"] .table th { border-color: #232a3d !important; color: #e2e8f0; }
[data-bs-theme="dark"] h1, [data-bs-theme="dark"] h2, [data-bs-theme="dark"] h3, [data-bs-theme="dark"] h4, [data-bs-theme="dark"] h5, [data-bs-theme="dark"] h6 { color: #f1f5f9; }
[data-bs-theme="dark"] p, [data-bs-theme="dark"] label, [data-bs-theme="dark"] .form-label, [data-bs-theme="dark"] .form-check-label { color: #cbd5e1; }
[data-bs-theme="dark"] .text-muted { color: #7d879a !important; }
[data-bs-theme="dark"] a { color: #7fa3f2; }

/* Form controls */
[data-bs-theme="dark"] .form-control, [data-bs-theme="dark"] .form-select,
[data-bs-theme="dark"] .topbar-search input, [data-bs-theme="dark"] .dataTables_filter input,
[data-bs-theme="dark"] .dataTables_length select {
  background: #1b2233; border-color: #2a3247; color: #e2e8f0;
}
[data-bs-theme="dark"] .form-control::placeholder { color: #6b7688; }
[data-bs-theme="dark"] .form-control:disabled { background: #161c2c; color: #7d879a; }
[data-bs-theme="dark"] .form-control:focus, [data-bs-theme="dark"] .form-select:focus { background: #1b2233; color: #e2e8f0; border-color: var(--brand); }

/* Buttons */
[data-bs-theme="dark"] .btn-outline-secondary { color: #cbd5e1; border-color: #2a3247; }
[data-bs-theme="dark"] .btn-outline-secondary:hover { background: #232a3d; color: #fff; }
[data-bs-theme="dark"] .btn-icon { color: #9aa5b8; }
[data-bs-theme="dark"] .btn-icon:hover { background: #232a3d; }

/* Dropdown menus (filter checklists, profile menu, etc.) */
[data-bs-theme="dark"] .dropdown-menu { background: #1b2233; border-color: #2a3247; }
[data-bs-theme="dark"] .dropdown-item { color: #cbd5e1; }
[data-bs-theme="dark"] .dropdown-item:hover { background: #232a3d; color: #fff; }
[data-bs-theme="dark"] .dropdown-item-text { color: #7d879a; }
[data-bs-theme="dark"] .dropdown-divider { border-color: #2a3247; }

/* Modals */
[data-bs-theme="dark"] .modal-content { background: #161c2c; color: #e2e8f0; }
[data-bs-theme="dark"] .modal-header, [data-bs-theme="dark"] .modal-footer { border-color: #232a3d; }

/* Nav tabs (filter chips) */
[data-bs-theme="dark"] .nav-tabs { border-color: #232a3d; }
[data-bs-theme="dark"] .nav-tabs .nav-link { color: #9aa5b8; }
[data-bs-theme="dark"] .nav-tabs .nav-link:hover { background: #1e2536; }
[data-bs-theme="dark"] .nav-tabs .nav-link.active { background: #232a3d; color: #fff; }

/* Alerts */
[data-bs-theme="dark"] .alert-danger { background: #3a1d22; color: #fca5b1; border-color: #5a2530; }
[data-bs-theme="dark"] .alert-warning { background: #3a2f14; color: #fcd980; border-color: #5a4a20; }
[data-bs-theme="dark"] .alert-info { background: #122b3a; color: #93c9ec; border-color: #1c4258; }
[data-bs-theme="dark"] .alert-success { background: #123a24; color: #8fdba8; border-color: #1c5a36; }

/* DataTables pagination */
[data-bs-theme="dark"] .dataTables_paginate .paginate_button { color: #cbd5e1 !important; }
[data-bs-theme="dark"] .dataTables_paginate .paginate_button:hover:not(.current) { background: #232a3d !important; color: #fff !important; }
[data-bs-theme="dark"] .dataTables_paginate .paginate_button.disabled { color: #4b5563 !important; }

/* Chat */
[data-bs-theme="dark"] .chat-wrap { background: #161c2c; border-color: #232a3d; }
[data-bs-theme="dark"] .chat-contacts { background: #1b2233; border-color: #232a3d; }
[data-bs-theme="dark"] .chat-contact { border-color: #232a3d; }
[data-bs-theme="dark"] .chat-contact:hover, [data-bs-theme="dark"] .chat-contact.active { background: #232a3d; }
[data-bs-theme="dark"] .msg.theirs { background: #232a3d; color: #e2e8f0; }

/* ---- FullCalendar (Calendar pages) — a third-party widget with its own
   CSS, not dark-mode-aware by default, so it needs its own override block
   rather than inheriting from the app's generic dark-mode rules above. ---- */
[data-bs-theme="dark"] .fc { color: #e2e8f0; }
[data-bs-theme="dark"] .fc-toolbar-title { color: #f1f5f9; }
[data-bs-theme="dark"] .fc-button-primary { background: #232a3d !important; border-color: #2a3247 !important; color: #cbd5e1 !important; }
[data-bs-theme="dark"] .fc-button-primary:hover { background: #2a3247 !important; }
[data-bs-theme="dark"] .fc-button-primary:disabled { opacity: .5; }
[data-bs-theme="dark"] .fc-button-active { background: var(--brand) !important; border-color: var(--brand) !important; }
[data-bs-theme="dark"] .fc-col-header-cell { background: #1b2233; color: #9aa5b8; }
[data-bs-theme="dark"] .fc-daygrid-day, [data-bs-theme="dark"] .fc-scrollgrid, [data-bs-theme="dark"] .fc-theme-standard td, [data-bs-theme="dark"] .fc-theme-standard th { border-color: #232a3d !important; }
[data-bs-theme="dark"] .fc-daygrid-day-number { color: #cbd5e1; }
[data-bs-theme="dark"] .fc-day-today { background: rgba(42,92,138,.15) !important; }
[data-bs-theme="dark"] .fc-list-day-cushion { background: #1b2233 !important; }
[data-bs-theme="dark"] .fc-list-event:hover td { background: #232a3d !important; }
[data-bs-theme="dark"] .fc-list-event-title, [data-bs-theme="dark"] .fc-list-event-time { color: #e2e8f0; }
[data-bs-theme="dark"] .fc-list-empty { background: #161c2c; color: #7d879a; }

/* ---- Quill rich-text editor (Question Bank, Assignments) — its "snow"
   theme is light by default, and both usages in this app set an inline
   white background on the editor container for light mode, which would
   otherwise stay a jarring white box against the dark theme. ---- */
[data-bs-theme="dark"] .ql-toolbar { background: #1b2233 !important; border-color: #2a3247 !important; }
[data-bs-theme="dark"] .ql-container { background: #161c2c !important; border-color: #2a3247 !important; }
[data-bs-theme="dark"] .ql-editor { color: #e2e8f0; }
[data-bs-theme="dark"] .ql-editor.ql-blank::before { color: #6b7688; }
[data-bs-theme="dark"] .ql-snow .ql-stroke { stroke: #9aa5b8; }
[data-bs-theme="dark"] .ql-snow .ql-fill { fill: #9aa5b8; }
[data-bs-theme="dark"] .ql-snow .ql-picker { color: #9aa5b8; }
[data-bs-theme="dark"] .ql-snow .ql-picker-options { background: #1b2233; border-color: #2a3247 !important; }

.auth-body { min-height: 100vh; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #17263a, #2A5C8A 60%, #3d7ab0); font-family: var(--font-family); }
.auth-card { background: #fff; padding: 2.75rem; border-radius: 16px; width: 100%; max-width: 400px; box-shadow: 0 24px 48px rgba(23,27,36,.22); }
.auth-brand { font-size: 1.4rem; font-weight: 700; letter-spacing: -.01em; }
.auth-brand i { color: var(--brand); margin-right: .45rem; }

/* ---- Chat ---- */
.chat-wrap { display: flex; height: calc(100vh - 150px); border: 1px solid var(--hairline); border-radius: 10px; overflow: hidden; background: #fff; }
.chat-contacts { width: 280px; border-right: 1px solid var(--hairline); overflow-y: auto; background: #fbfbfc; }
.chat-contact { padding: .65rem .9rem; cursor: pointer; border-bottom: 1px solid var(--hairline); }
.chat-contact:hover, .chat-contact.active { background: #eef1fd; }
.chat-contact .min-w-0 { min-width: 0; }
.contact-avatar { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.contact-unread-badge { font-size: .68rem; min-width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; padding: 0 .35rem; }
.chat-body { flex: 1; display: flex; flex-direction: column; }
.chat-messages { flex: 1; overflow-y: auto; padding: 1.1rem; }
.msg-row { display: flex; align-items: flex-end; gap: .5rem; margin-bottom: .6rem; }
.msg-row.mine { flex-direction: row-reverse; }
.msg-avatar { width: 26px; height: 26px; border-radius: 50%; object-fit: cover; font-size: .62rem; flex-shrink: 0; }
.msg { max-width: 62%; padding: .55rem .85rem; border-radius: 14px; font-size: .855rem; }
.msg.mine { background: var(--brand); color: #fff; border-bottom-right-radius: 4px; }
.msg.theirs { background: #f1f3f7; border-bottom-left-radius: 4px; }
.msg-card { border: 1px solid rgba(0,0,0,.08); border-radius: 8px; padding: .4rem .65rem; margin-bottom: .3rem; font-size: .78rem; background: rgba(255,255,255,.18); }
a.msg-card { color: inherit; }
a.msg-card:hover { background: rgba(255,255,255,.3); }
.msg-timestamp { font-size: .68rem !important; }
.msg.mine .msg-timestamp { color: rgba(255,255,255,.75) !important; }

@media (max-width: 991px) {
  .app-sidebar { transform: translateX(-100%); }
  .app-sidebar.show { transform: translateX(0); }
  .app-main { margin-left: 0; width: 100%; }
}

/* Desktop sidebar show/hide via the same topbar icon used on mobile —
   previously the icon was hidden entirely above the 991px breakpoint (d-lg-none)
   and toggling only ever applied a mobile-only overlay class that had no
   effect at desktop widths, so there was no way to hide the sidebar in a
   full browser window at all. */
.app-sidebar, .app-main { transition: transform .2s ease, margin-left .2s ease, width .2s ease; }
@media (min-width: 992px) {
  html[data-sidebar="collapsed"] .app-sidebar { transform: translateX(-100%); }
  html[data-sidebar="collapsed"] .app-main { margin-left: 0; width: 100%; }
}

