/*
 * Dark Theme (opt-in color mode)
 * -----------------------------------------------------------------------
 * Every rule in this file is scoped under `body.theme-dark` (or the more
 * specific `body.theme-material.theme-dark`) so that it is strictly
 * additive: with those classes absent (the default "Light" mode) nothing
 * here applies and the app renders pixel-identical to before this file
 * existed.
 *
 * This is an INDEPENDENT axis from the Modern/Material style switcher
 * (material-theme.css, scoped under body.theme-material). A user can land
 * on any of the 4 combinations:
 *   - Modern  + Light   (default, unaffected by either theme file)
 *   - Modern  + Dark    -> covered by the base `body.theme-dark` rules
 *                          below, layered on top of style.css/sidenav.css
 *   - Material+ Light   (default Material look, unaffected by this file)
 *   - Material+ Dark    -> `body.theme-dark` rules apply first, then the
 *                          `body.theme-material.theme-dark` section further
 *                          down overrides the Material design-token
 *                          variables (--md-*) so every Material component
 *                          that already reads those variables picks up
 *                          dark surfaces/borders/shadows for free.
 *
 * Do NOT edit style.css / sidenav.css / color.css / material-theme.css to
 * add dark-mode rules - add them here instead.
 */

/* =========================================================================
   MODERN + DARK  (body.theme-dark, Material class absent)
   Keeps Modern's soft/rounded aesthetic (rounded corners, gentle shadows)
   but swaps the light palette for a dark one.
   ========================================================================= */

body.theme-dark {
    --dk-bg: #14161f;
    --dk-surface: #1e2230;
    --dk-surface-alt: #262b3a;
    --dk-border: #333a4d;
    --dk-border-strong: #454c62;

    --dk-text: #e6e8ee;
    --dk-text-secondary: #c1c5d1;
    --dk-text-muted: #9aa0b2;

    --dk-shadow: rgba(0, 0, 0, .45);

    /* Lighter tint of the brand primary, used only where the color sits as
       FOREGROUND text/icons directly on a dark surface (outline buttons,
       .text-primary, links) - #5d60ef read as text-on-dark falls under the
       ~4.5:1 AA threshold for normal text, this tint clears it comfortably.
       Solid fills (btn-primary, active nav, badges) keep using the
       unmodified --bs-primary since white-on-#5d60ef is already high
       contrast and shouldn't shift between light/dark mode. */
    --dk-primary-text: #9799ff;

    background-color: var(--dk-bg);
    color: var(--dk-text);
}

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

body.theme-dark .app-wrapper {
    background: var(--dk-bg);
}

body.theme-dark .app-main,
body.theme-dark main.app-content {
    background: var(--dk-bg);
    color: var(--dk-text);
}

body.theme-dark .sidebar {
    background: var(--dk-surface);
    border-right-color: var(--dk-border);
}

body.theme-dark .sidebar-menu li a {
    color: var(--dk-text-muted);
}

body.theme-dark .sidebar-menu li.active a,
body.theme-dark .sidebar-menu li a:hover {
    background: var(--bs-primary);
    color: #fff;
}

body.theme-dark .offcanvas {
    background: var(--dk-surface);
    color: var(--dk-text);
}

body.theme-dark .offcanvas-header {
    border-bottom-color: var(--dk-border);
}

body.theme-dark .offcanvas .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

body.theme-dark .topnav {
    background: var(--dk-surface);
    border-bottom-color: var(--dk-border);
}

body.theme-dark .topnav-left h6 {
    color: var(--dk-text) !important;
}

body.theme-dark .topnav-right > .dropdown > a {
    color: var(--dk-text);
}

body.theme-dark .topnav-right img.rounded-circle {
    border: 1px solid var(--dk-border-strong);
}

/* ---- Text utilities (unmodified Bootstrap defaults are unreadable on a
   dark surface, so give the ones used across the app a dark-aware value) ---- */

body.theme-dark .text-muted,
body.theme-dark .text-secondary {
    color: var(--dk-text-muted) !important;
}

body.theme-dark .text-primary {
    color: var(--dk-primary-text) !important;
}

body.theme-dark .text-danger {
    color: #ff6b7a !important;
}

body.theme-dark small {
    color: inherit;
}

/* =========================================================================
   Buttons
   ========================================================================= */

body.theme-dark .btn {
    color: var(--dk-text);
}

/* .btn-light keeps Bootstrap's light background in every theme (used ~8
   places app-wide: users list row-menu toggle, subjects/attendance/chat
   action buttons, editor toolbar, etc.) - the blanket .btn rule above
   forces its icon/text to dark mode's near-white color regardless,
   producing a near-invisible near-white-on-light-gray button (confirmed
   live via headless browser: computed color rgb(230,232,238) on background
   rgb(248,249,250) for the users-list row-menu button). Same specificity
   as the .btn rule above (one extra class each), so this must stay after
   it in source order to win. */
body.theme-dark .btn-light {
    color: #000;
}

body.theme-dark .btn-primary {
    color: #fff;
}

body.theme-dark .btn-outline-primary {
    background: transparent;
    color: var(--dk-primary-text);
    border-color: var(--dk-primary-text);
}

body.theme-dark .btn-outline-primary:hover,
body.theme-dark .btn-outline-primary:focus,
body.theme-dark .btn-outline-primary:active {
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
    color: #fff;
}

body.theme-dark .btn-outline-secondary {
    background: transparent;
    color: var(--dk-text-secondary);
    border-color: var(--dk-border-strong);
}

body.theme-dark .btn-outline-secondary:hover,
body.theme-dark .btn-outline-secondary:focus,
body.theme-dark .btn-outline-secondary:active {
    background-color: var(--dk-surface-alt);
    border-color: var(--dk-border-strong);
    color: var(--dk-text);
}

body.theme-dark .btn-danger {
    color: #fff;
}

body.theme-dark .ui-btn-group .btn:not(.active) {
    background: var(--dk-surface-alt);
    color: var(--dk-primary-text);
}

body.theme-dark .ui-btn-group .btn:not(.active):hover {
    background: rgba(93, 96, 239, .25);
}

body.theme-dark .ui-btn-group .btn.active {
    color: #fff;
}

/* =========================================================================
   Cards / surfaces
   ========================================================================= */

body.theme-dark .card,
body.theme-dark .exam-timer,
body.theme-dark .attendance-date-btn,
body.theme-dark .cover-card,
body.theme-dark .users-page,
body.theme-dark .article-card,
body.theme-dark .bg-soft,
body.theme-dark .feed-card,
body.theme-dark .dashboard-card {
    background-color: var(--dk-surface);
    color: var(--dk-text);
}

body.theme-dark .card,
body.theme-dark .exam-timer,
body.theme-dark .feed-card {
    border-color: var(--dk-border);
    box-shadow: 0 10px 25px var(--dk-shadow);
}

/* .post-card:hover's lift (dashboard.css) uses a light-mode-tuned shadow
   rgba that would barely read against a dark surface - intensify from the
   same --dk-shadow token .feed-card already uses above instead. */
body.theme-dark .post-card:hover {
    box-shadow: 0 14px 32px var(--dk-shadow);
}

/* .info-card's visible surface is a full-bleed photo (.info-img,
   position:absolute over the card), not the themed --dk-surface fill
   underneath it - .info-title/.info-sub overlaid on that photo must stay
   at their original light-mode dark color regardless of theme, or they
   inherit dark mode's light body text color and become illegible on the
   light photo (confirmed by rendering - "Teachers"/"Students" titles were
   invisible). */
body.theme-dark .info-card {
    box-shadow: 0 10px 30px var(--dk-shadow);
}

body.theme-dark .info-title {
    color: #1f2937;
}

/* .section-subject-title (sections/subjects/index.blade.php's subject
   cards) is the OPPOSITE situation from .info-title above, despite looking
   like the same kind of card title - this one sits in a plain, non-
   overlapping .card-body below the image, which the body.theme-dark .card
   rule further up already gives a themed background + var(--dk-text). Its
   own light-mode color: #1f2937 in style.css (a directly-declared value on
   the element) otherwise wins over that inherited color regardless of
   theme, rendering as dark-gray-on-dark-surface - confirmed invisible by
   the user. Explicit override here restores the inherited card text color
   in dark mode. */
body.theme-dark .section-subject-title {
    color: var(--dk-text);
}

/* .subject-growth-avatar (sections/partials/subject-growth-avatar.blade.php)
   - unlike .info-title/.custom-badge above, this sits inside the card BODY
   (plain surface, not an overlay on a still-light photo), so it needs a
   real dark-mode background/text swap rather than staying light on
   purpose. */
body.theme-dark .subject-growth-avatar {
    background: var(--dk-surface-alt);
}

body.theme-dark .subject-growth-avatar:hover,
body.theme-dark .subject-growth-avatar:focus-visible {
    background: var(--dk-border);
}

/* Kept white/light on purpose, unlike the badge/label around it - this is
   character illustration art, not a UI surface, and character mascot art
   generally reads best on a single consistent neutral backdrop regardless
   of app theme (same reason a profile photo frame doesn't usually invert
   in dark mode) rather than switching to a dark frame that might clash if
   the source PNGs turn out not to have transparent backgrounds. */
body.theme-dark .subject-growth-avatar-img {
    border-color: rgba(255, 255, 255, 0.08);
}

body.theme-dark .subject-growth-avatar-label {
    color: var(--dk-text);
}

body.theme-dark .subject-growth-avatar-track {
    background: rgba(255, 255, 255, 0.12);
}

/* .avatar-character-option (users/profiles/index.blade.php growth avatar
   picker) - same reasoning as .subject-growth-avatar above. */
body.theme-dark .avatar-character-option {
    border-color: var(--dk-border);
    background: var(--dk-surface-alt);
}

body.theme-dark .avatar-character-option:hover,
body.theme-dark .avatar-character-option:focus-visible,
body.theme-dark .avatar-character-option.active {
    border-color: var(--bs-primary);
    background: var(--dk-border);
}

body.theme-dark .avatar-character-option img {
    border-color: rgba(255, 255, 255, 0.08);
}

body.theme-dark .avatar-character-option span {
    color: var(--dk-text);
}

/* .plant-growth-badge (sections/partials/plant-growth-avatar.blade.php) -
   same reasoning as .subject-growth-avatar above (sits in the card body,
   not overlaying a photo, so needs a real background/text swap). Its SVG
   icon needs no override at all - currentColor already follows this
   badge's own `color: var(--bs-primary)`, and --bs-primary/--bs-primary-
   hover aren't redefined in dark mode. */
body.theme-dark .plant-growth-badge {
    background: var(--dk-surface-alt);
}

body.theme-dark .plant-growth-badge-icon {
    background: rgba(255, 255, 255, 0.08);
}

body.theme-dark .plant-growth-badge-label {
    color: var(--dk-text);
}

body.theme-dark .plant-growth-badge-track {
    background: rgba(255, 255, 255, 0.12);
}

/* Profile page's cover .card (see the body.profile-page .card radius fix
   in dashboard.css) pulls its .card-body up over the yellow cover photo
   via a negative margin. At >=768px (Bootstrap md, where the avatar and
   name switch to d-md-flex side-by-side) the centered flex row still
   overlaps the still-light banner, so the name needs to stay dark there.
   Below md the avatar/name stack vertically and the name renders well
   below the banner, on the plain dark card surface - forcing dark text
   there made it invisible (near-black on near-black), so this override
   is scoped to md+ only and mobile inherits the normal light .card text. */
@media (min-width: 768px) {
    body.theme-dark.profile-page .card-body h3 {
        color: #1f2937;
    }
}

/* .dashboard-card carries its own background-image banner (see
   dashboard.css) rather than a flat surface fill - dark mode only needs to
   darken its border/overlay, not override the background entirely. */
body.theme-dark .dashboard-card {
    border: 1px solid var(--dk-border);
    box-shadow: 0 10px 25px var(--dk-shadow);
}

/* .custom-badge is only ever used inside .dashboard-card, sitting on its
   fixed light-yellow banner image (not a themed dark surface) - giving it
   dark mode's light text color made it invisible against that still-light
   banner (confirmed by screenshot: "From <city>" / "Followed by N Users"
   text unreadable). It keeps dashboard.css's light-mode-appropriate colors
   in dark mode too, same reasoning as the .dashboard-card fix above. */

/* dashboard.css defines several classes with hardcoded gray/dark text
   colors (#111, #374151, #6b7280) that have no fixed background of their
   own - they sit directly on the themed .feed-card surface, so in dark
   mode the ambient background goes dark while this text stayed hardcoded
   dark too. Confirmed by real-device screenshot: post author names
   (.user-name-link) were nearly invisible; the same shape of bug applies
   to the post/reaction action buttons, small in-card icons, and the poll
   box's own fixed light background. */
body.theme-dark .user-name-link {
    color: var(--dk-text);
}

body.theme-dark .post-actions button,
body.theme-dark .feed-actions button,
body.theme-dark .reaction-btn {
    color: var(--dk-text-secondary);
}

body.theme-dark .post-actions button:hover,
body.theme-dark .feed-actions button:hover,
body.theme-dark .reaction-btn:hover,
body.theme-dark .poll-option-box:hover {
    background: var(--dk-surface-alt);
}

/* Active reaction colors (dashboard.css) need to win over the generic
   `body.theme-dark .reaction-btn` gray-text rule directly above (same
   specificity tier, later-in-cascade-file wins otherwise) - re-declared
   here at matching `body.theme-dark` specificity rather than relying on
   dashboard.css's un-scoped rule to survive the cascade. Colors themselves
   are already saturated/vivid brand tones that read fine unchanged against
   a dark surface, same reasoning as reaction emoji/other fixed-hue UI. */
body.theme-dark .reaction-btn[data-selected="like"] {
    color: #1877f2;
}
body.theme-dark .reaction-btn[data-selected="love"] {
    color: #f33e58;
}
body.theme-dark .reaction-btn[data-selected="care"],
body.theme-dark .reaction-btn[data-selected="haha"],
body.theme-dark .reaction-btn[data-selected="wow"],
body.theme-dark .reaction-btn[data-selected="sad"] {
    color: #f7b125;
}
body.theme-dark .reaction-btn[data-selected="angry"] {
    color: #e9710f;
}

/* Reaction count summary (dashboard.css's .reaction-total-count/
   .reaction-stack-icon) - same light-gray-text/fixed-white-ring situation
   as elsewhere in this file. */
body.theme-dark .reaction-total-count {
    color: var(--dk-text-muted);
}
body.theme-dark .reaction-stack-icon {
    background: var(--dk-surface);
    box-shadow: 0 0 0 1px var(--dk-surface);
}

body.theme-dark .feed-card i {
    color: var(--dk-text-muted);
}

body.theme-dark .poll-box {
    background: var(--dk-surface-alt);
}

/* .multi-img-tile (dashboard.css - multi-photo post composer preview grid)
   has the same fixed-light-background situation as .poll-box above (it
   sits inside the themed-dark #post-modal .modal-content), plus its
   ".multi-img-add-more" sibling is a bordered dashed pill whose border/
   text color needs the same lighter-tint treatment as .btn-outline-primary
   above (foreground color directly on a dark surface, not a solid fill). */
body.theme-dark .multi-img-tile {
    background: var(--dk-surface-alt);
}

/* .feed-image-gallery-tile (dashboard.css - read-only feed gallery grid)
   has the same fixed-light-background situation as .multi-img-tile above. */
body.theme-dark .feed-image-gallery-tile {
    background: var(--dk-surface-alt);
}

body.theme-dark .multi-img-add-more {
    color: var(--dk-primary-text);
    border-color: var(--dk-primary-text);
}

body.theme-dark .multi-img-add-more:hover {
    background: rgba(151, 153, 255, 0.12);
}

/* .progress's track is a hardcoded light gray (#e5e7eb/#e4e6eb in
   dashboard.css) with no dark-aware value of its own - against the poll
   box's now-dark background it stayed a pale bar sitting on top of a dark
   surface instead of reading as a recessed track. */
body.theme-dark .progress {
    background-color: var(--dk-border);
}

/* .voted-label's hardcoded #16a34a is legible on either surface, but only
   just clears ~4.3:1 against --dk-surface-alt (below the 4.5:1 AA target
   for its 11px text) - bump it to the same brighter green already used
   elsewhere in this app for "success/online" states (~6.2:1 on dark). */
body.theme-dark .voted-label {
    color: #22c55e;
}

/* .reaction-box (the emoji picker popover that appears above the Like
   button) is a hardcoded white pill with no dark-aware value - unlike the
   post/reaction buttons it sits detached from any themed surface, so it
   floated as a solid white box against the dark feed. */
body.theme-dark .reaction-box {
    background: var(--dk-surface);
    box-shadow: 0 5px 15px var(--dk-shadow);
}

/* .shared-post-card has its own hardcoded light background (#f9fafb),
   separate from the ambient .feed-card it sits inside - the shared post's
   author name/description text inherits dark mode's light --dk-text color
   from that ambient .feed-card, which was then landing on this still-light
   nested background: light-on-light, illegible. */
body.theme-dark .shared-post-card {
    background: var(--dk-surface-alt);
    border-color: var(--dk-border);
}

body.theme-dark .shared-post-card:hover {
    background: var(--dk-border);
}

/* .event-item.blue/.green/.yellow (dashboard's "Upcoming Events" widget)
   keep their fixed light pastel backgrounds (#e0e7ff/#dcfce7/#fef3c7) in
   every mode - same reasoning as .info-title/.custom-badge above - but
   their title/detail text has no color of its own, so it was inheriting
   the ambient .feed-card's dark-mode --dk-text (near-white), landing
   light-on-light and effectively invisible. */
body.theme-dark .event-item {
    color: #1f2937;
}

body.theme-dark .event-item small {
    color: #4b5563;
}

/* Bootstrap's .shadow/.shadow-sm/.shadow-lg utilities compile with
   !important and are used directly on several cards app-wide (e.g. the
   login/register/reset auth cards use .shadow-lg) - without this, those
   elements keep Bootstrap's light-mode-tuned shadow color even in dark
   mode, which reads as a pale halo against a dark surface. Re-tint them
   with the same --dk-shadow used for .card/.feed-card above, at roughly
   matching blur/spread per utility size. */
body.theme-dark .shadow {
    box-shadow: 0 .5rem 1rem var(--dk-shadow) !important;
}

body.theme-dark .shadow-sm {
    box-shadow: 0 .125rem .25rem var(--dk-shadow) !important;
}

body.theme-dark .shadow-lg {
    box-shadow: 0 1rem 3rem var(--dk-shadow) !important;
}

/* Bootstrap's .bg-light utility (also !important) is used ~43 times across
   the app for recessed card rows (user list items, online-users rows,
   birthday-celebrant rows, etc.) - confirmed by real phone screenshots
   that without this, dark mode leaves it at Bootstrap's light gray while
   the text inside inherits dark mode's light text color from its
   ancestor .card/.feed-card - light text on a light row, illegible.
   .badge.bg-light already had its own override above; this covers every
   other use of the utility. */
body.theme-dark .bg-light {
    background-color: var(--dk-surface-alt) !important;
}

/* Both of these sit directly on a .bg-light row/card and use a hardcoded
   white "cutout" border (light-mode-only design: separates the element
   from an arbitrary avatar-image/status-color behind it) - without this,
   the white border stays hardcoded while .bg-light above correctly turns
   dark, so it reads as a bright, unintended ring/box. Match the border to
   the same dark surface .bg-light now resolves to, so it keeps blending
   with its row instead of standing out. */
body.theme-dark .online-status-dot,
body.theme-dark .profile-avatar-preview {
    border-color: var(--dk-surface-alt) !important;
}

/* Same photo-backdrop reasoning as .info-title above - stays at its
   original light-mode color (style.css's own #6b7280), not the dark-mode
   muted token. */
body.theme-dark .info-sub {
    color: #6b7280;
}

body.theme-dark .cover-card {
    box-shadow: 0 10px 25px var(--dk-shadow);
}

body.theme-dark .attendance-date-btn {
    background: var(--dk-surface-alt);
}

body.theme-dark .attendance-date-btn .time {
    color: var(--dk-text-muted);
}

body.theme-dark .attendance-date-btn:hover {
    background: var(--bs-primary);
}

body.theme-dark .attendance-date-btn:hover .date,
body.theme-dark .attendance-date-btn:hover .time {
    color: #fff;
}

body.theme-dark .exam-timer .timer-title {
    color: var(--dk-text-secondary);
}

body.theme-dark .timer-box {
    background: var(--dk-surface-alt);
    border-color: var(--dk-border);
}

body.theme-dark .timer-box span {
    color: var(--dk-text-muted);
}

/* =========================================================================
   Forms
   ========================================================================= */

body.theme-dark .form-control,
body.theme-dark .form-select,
body.theme-dark .ui-search input {
    background-color: var(--dk-surface-alt);
    border-color: var(--dk-border-strong);
    color: var(--dk-text);
}

body.theme-dark .form-control:focus,
body.theme-dark .form-select:focus,
body.theme-dark .ui-search input:focus {
    background-color: var(--dk-surface-alt);
    border-color: var(--bs-primary);
    color: var(--dk-text);
    box-shadow: 0 0 0 .2rem rgba(93, 96, 239, .25);
}

body.theme-dark .form-control::placeholder,
body.theme-dark .ui-search input::placeholder {
    color: var(--dk-text-muted);
    opacity: 1;
}

/* Bootstrap's .form-text (help text under an input, e.g. lesson-modal's
   "A lesson is a named group of topics...") is never restyled by
   Bootstrap for dark backgrounds - stays its light-mode #6c757d, which
   reads as near-invisible against the dark .bg-light surface these
   usually sit on. Generic Bootstrap utility used across many forms, not
   just this one modal, so fixed globally rather than per-page. */
body.theme-dark .form-text {
    color: var(--dk-text-muted);
}

body.theme-dark .ui-search i {
    color: var(--dk-text-muted);
}

/* Bootstrap's <select> caret / native color-scheme so options render on a
   dark surface instead of forcing white-on-white in some browsers. */
body.theme-dark .form-select {
    color-scheme: dark;
}

body.theme-dark .form-check-input {
    background-color: var(--dk-surface-alt);
    border-color: var(--dk-border-strong);
}

body.theme-dark .form-check-input:checked {
    background-color: var(--bs-primary);
    border-color: var(--bs-primary);
}

/* Bootstrap's switch "knob" is drawn as a background-image SVG circle
   baked with a fixed fill color (rgba(0,0,0,.25) unchecked / #fff
   checked) rather than a themeable CSS color - that dark, low-opacity
   circle on the already-dark --dk-surface-alt track above is nearly
   invisible (confirmed by rendering), so swap the unchecked/focus knob
   to a light circle here. The checked state's white knob already reads
   fine against the --bs-primary track set above and needs no change. */
body.theme-dark .form-switch .form-check-input {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba(255,255,255,0.55)'/%3e%3c/svg%3e");
}

body.theme-dark .form-switch .form-check-input:focus {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='rgba(255,255,255,0.85)'/%3e%3c/svg%3e");
}

/* =========================================================================
   Exam question page (subjects/assessments/view.blade.php, scoped under
   .assessment-question-list-page) - .exam-header-card/.exam-question-card
   already pick up the dark .card background/border/shadow rules above (they
   both carry the .card class); only the hardcoded text/surface colors set
   in question.css need overriding here.
   ========================================================================= */

body.theme-dark .exam-instruction-label {
    color: var(--dk-text-muted);
}

body.theme-dark .exam-instruction-text,
body.theme-dark .exam-question-text {
    color: var(--dk-text);
}

body.theme-dark .basic-radio-div {
    background: var(--dk-surface-alt);
    border-color: var(--dk-border-strong);
}

body.theme-dark .basic-radio-div:hover {
    border-color: var(--bs-primary);
    background: var(--dk-surface);
}

body.theme-dark .basic-radio-div:has(.basic-radio:checked) {
    border-color: var(--bs-primary);
    background: var(--dk-surface);
    box-shadow: 0 0 0 1px var(--bs-primary) inset;
}

body.theme-dark .basic-span {
    color: var(--dk-text);
}

body.theme-dark .basic-radio {
    border-color: var(--dk-primary-text);
}

body.theme-dark .basic-radio:checked::after {
    background-color: var(--dk-primary-text);
}

body.theme-dark .correct-answer-hint {
    color: var(--dk-primary-text) !important;
}

/* Bootstrap's .table cells paint their own background-color regardless of
   an ancestor's background (same confirmed bug shape as .scale-table and
   .ui-table elsewhere in this file), so the surface token has to be set on
   the wrapper, the table, and every <th>/<td> individually. */
body.theme-dark .matching-table-wrap,
body.theme-dark .matching-table-wrap table,
body.theme-dark .matching-table-wrap thead th,
body.theme-dark .matching-table-wrap tbody td {
    background-color: var(--dk-surface-alt) !important;
    border-color: var(--dk-border) !important;
}

body.theme-dark .matching-table-wrap thead th {
    color: var(--dk-text-secondary) !important;
}

body.theme-dark .matching-table-wrap tbody td {
    color: var(--dk-text) !important;
}

/* Answer-builder tables (multiple choice / matching authoring) - same
   underline-input treatment as #table-scale below, scoped under
   .matching-table-wrap instead so it doesn't reach #table-scale itself. */
body.theme-dark .matching-table-wrap .form-control.border-only-bottom {
    background: transparent;
    border-bottom-color: var(--dk-border-strong);
    color: var(--dk-text) !important;
    -webkit-text-fill-color: var(--dk-text) !important;
}

body.theme-dark .matching-table-wrap .form-control.border-only-bottom::placeholder {
    color: var(--dk-text-muted) !important;
    -webkit-text-fill-color: var(--dk-text-muted) !important;
    opacity: 1;
}

/* =========================================================================
   Subject form (resources/views/subjects/form.blade.php) - image dropzone
   + grading scale table, both added in style.css.
   ========================================================================= */

body.theme-dark .scale-section-title {
    color: var(--dk-text) !important;
}

body.theme-dark .subject-image-frame {
    background: var(--dk-surface-alt);
}

body.theme-dark .subject-image-empty {
    background: var(--dk-surface-alt);
    border-color: var(--dk-border-strong);
    color: var(--dk-text-muted);
}

/* .scale-table-wrapper sits on the already-dark-themed .bg-light panel
   (see the app-wide body.theme-dark .bg-light rule above) - give it its own
   inset surface so the "table on a card" layering still reads the same as
   in light mode instead of flattening to one flat panel. Uses the same
   --dk-surface-alt token every other "surface on a surface" component in
   this app uses (.poll-box, .multi-img-tile, etc.) rather than true black -
   pure #000 here read as a jarring stripe against the surrounding navy
   card, out of step with the rest of the dark theme's palette.
   Bootstrap's .table cells paint their own background-color:
   var(--bs-table-bg) (defaults to #fff) regardless of an ancestor's
   background - the same confirmed bug shape as .ui-table tbody td
   elsewhere in this file - so the token has to be set on the wrapper, the
   table, and every <th>/<td> individually, or the cells paint themselves
   white on top of it. */
body.theme-dark .scale-table-wrapper,
body.theme-dark #table-scale,
body.theme-dark .scale-table thead th,
body.theme-dark .scale-table tbody td,
body.theme-dark .scale-table tbody tr {
    background-color: var(--dk-surface-alt) !important;
}

/* Belt-and-suspenders: Bootstrap 5.3 paints table cells via
   `.table > :not(caption) > * > * { background-color: var(--bs-table-bg); }`
   (defaults to #fff) rather than a plain background-color rule with no
   variable indirection - overriding the token itself at the table level
   is the mechanism Bootstrap's own theming actually expects, so it covers
   any cell state (hover, striping) the direct background-color rules
   above don't happen to catch. */
body.theme-dark #table-scale {
    --bs-table-bg: var(--dk-surface-alt);
    --bs-table-color: var(--dk-text);
    --bs-table-accent-bg: transparent;
}

body.theme-dark .scale-table thead th {
    color: var(--dk-text-secondary) !important;
    border-bottom-color: var(--dk-border);
}

body.theme-dark .scale-table tbody td {
    border-bottom-color: var(--dk-border);
}

body.theme-dark #table-scale .form-control.border-only-bottom {
    background: transparent;
    border-bottom-color: var(--dk-border-strong);
    color: var(--dk-text) !important;
    -webkit-text-fill-color: var(--dk-text) !important;
    -webkit-appearance: none;
    opacity: 1 !important;
}

body.theme-dark #table-scale .form-control.border-only-bottom:focus {
    border-bottom-color: var(--bs-primary);
    color: var(--dk-text) !important;
    -webkit-text-fill-color: var(--dk-text) !important;
}

body.theme-dark #table-scale .form-control.border-only-bottom::placeholder {
    color: var(--dk-text-muted) !important;
    -webkit-text-fill-color: var(--dk-text-muted) !important;
}

/* readonly "Attendance" row specifically - matches the same belt-and-
   suspenders technique already proven necessary for this exact widget in
   light mode (see style.css: plain `color` alone wasn't enough there,
   needed -webkit-text-fill-color + opacity too, likely Chromium's
   readonly-input UA styling fighting back). Max specificity + !important
   on every channel so nothing upstream (base rule, Material-theme combo)
   can leave it dim. */
body.theme-dark #table-scale .form-control.border-only-bottom[readonly] {
    color: var(--dk-text) !important;
    -webkit-text-fill-color: var(--dk-text) !important;
    opacity: 1 !important;
    font-weight: 700;
}

/* =========================================================================
   Settings: School Year Management table (settings/form.blade.php) - same
   fix shape as #table-scale above (direct background-color on every
   wrapper/row/cell, plus the --bs-table-* variable override, since
   Bootstrap paints cell backgrounds via var(--bs-table-bg) which
   otherwise stays white regardless of the .bg-light ancestor's dark
   background), scoped to this table's own #id since it was never covered
   by the #table-scale-specific rules above.
   ========================================================================= */

body.theme-dark #table-schoolyear,
body.theme-dark #table-schoolyear tbody tr,
body.theme-dark #table-schoolyear tbody td,
body.theme-dark #table-schoolyear thead th {
    background-color: var(--dk-surface-alt) !important;
}

/* Belt-and-suspenders #2: Bootstrap 5.3 actually paints every cell via
   `.table > :not(caption) > * > * { background-color: var(--bs-table-bg);
   box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg); }` - matching
   that exact selector shape here (rather than only the tbody/thead rule
   above) guarantees this wins regardless of which half of Bootstrap's own
   rule (the background-color or the inset box-shadow) ends up deciding
   the visible color, including the checkbox column's <td> which carries
   no .form-control of its own to catch it otherwise. */
body.theme-dark #table-schoolyear > :not(caption) > * > * {
    background-color: var(--dk-surface-alt) !important;
    color: var(--dk-text);
}

body.theme-dark #table-schoolyear {
    --bs-table-bg: var(--dk-surface-alt);
    --bs-table-color: var(--dk-text);
    --bs-table-accent-bg: transparent;
    --bs-table-hover-bg: var(--dk-surface);
}

body.theme-dark #table-schoolyear thead th {
    color: var(--dk-text-secondary) !important;
    border-bottom-color: var(--dk-border);
}

body.theme-dark #table-schoolyear tbody td {
    border-bottom-color: var(--dk-border);
}

body.theme-dark #table-schoolyear .form-control.border-only-bottom {
    background: transparent !important;
    border-bottom-color: var(--dk-border-strong);
    color: var(--dk-text) !important;
    -webkit-text-fill-color: var(--dk-text) !important;
    -webkit-appearance: none;
    opacity: 1 !important;
}

/* input[type=date]'s native Chromium widget (calendar icon + its own
   internal paint layer) ignores a plain background-color override unless
   the browser is told the surrounding UI is dark - without this the date
   fields alone can stay a native light/white widget even once every other
   cell/input above is correctly dark. */
body.theme-dark #table-schoolyear input[type="date"].form-control.border-only-bottom {
    color-scheme: dark;
}

body.theme-dark #table-schoolyear .form-control.border-only-bottom:focus {
    border-bottom-color: var(--bs-primary);
    color: var(--dk-text) !important;
    -webkit-text-fill-color: var(--dk-text) !important;
}

body.theme-dark #table-schoolyear .form-control.border-only-bottom::placeholder {
    color: var(--dk-text-muted) !important;
    -webkit-text-fill-color: var(--dk-text-muted) !important;
}

/* =========================================================================
   Permissions matrix (settings/nav-links, settings/permission-links) -
   role column header icons + the permission-links module group-header
   rows, both new markup layered on top of .ui-table above.
   ========================================================================= */

body.theme-dark .ui-role-head i {
    color: var(--bs-primary);
}

/* Higher-specificity selector (adds .ui-matrix-table) needed here to beat
   the ".ui-table tbody td { color: var(--dk-text) }" rule above, which
   would otherwise win on specificity and silently keep the group-header
   text in the default (non-brand) text color. .ui-permission-group-header
   (the role-detail pages' per-group mini-card header, styled identically in
   light mode - see style.css) doesn't sit inside .ui-table, so no such
   specificity fight there; folded into the same rule regardless for one
   shared dark-mode definition. */
body.theme-dark .ui-matrix-table .ui-matrix-group-row td,
body.theme-dark .ui-matrix-table .ui-matrix-group-row:hover td,
body.theme-dark .ui-permission-group-header {
    background-color: var(--dk-surface-alt);
    color: #b9bbfa;
    border-bottom-color: var(--dk-border);
}

/* =========================================================================
   Dropdowns
   ========================================================================= */

body.theme-dark .dropdown-menu {
    background-color: var(--dk-surface);
    border-color: var(--dk-border);
    box-shadow: 0 10px 30px var(--dk-shadow);
}

body.theme-dark .dropdown-item {
    color: var(--dk-text-secondary);
}

body.theme-dark .dropdown-item:hover,
body.theme-dark .dropdown-item:focus {
    background-color: var(--dk-surface-alt);
    color: var(--dk-text);
}

body.theme-dark .dropdown-item.active,
body.theme-dark .dropdown-item:active {
    background-color: var(--bs-primary);
    color: #fff;
}

body.theme-dark .dropdown-item.text-danger {
    color: #ff6b7a !important;
}

body.theme-dark .dropdown-item.text-danger:hover {
    background-color: rgba(255, 107, 122, .12);
}

body.theme-dark .dropdown-divider {
    border-color: var(--dk-border);
}

body.theme-dark .theme-switcher .theme-option.active {
    background-color: rgba(93, 96, 239, .22);
    color: var(--dk-primary-text);
}

/* =========================================================================
   Badges
   ========================================================================= */

body.theme-dark .badge.bg-light {
    background-color: var(--dk-surface-alt) !important;
    color: var(--dk-text) !important;
}

body.theme-dark .badge.bg-secondary {
    color: #fff;
}

/* Bootstrap's .bg-*-subtle utilities compile to fixed light pastel colors
   (CSS custom properties like --bs-success-bg-subtle) regardless of
   color-scheme, so badges like settings/nav-links|permission-links's roles-
   list "Full access"/"All" pills (.badge.bg-success-subtle /
   .bg-primary-subtle) and users/list.blade.php's status pill
   (.bg-danger-subtle) would otherwise render as a near-white block on a dark
   surface. Dim each to a translucent tint of the same hue instead, matching
   the --dk-surface-alt-on-dark language already used by .badge.bg-light
   above (confirmed low-contrast by rendering before this fix). */
body.theme-dark .badge.bg-success-subtle {
    background-color: rgba(25, 135, 84, .2) !important;
    color: #4ade80 !important;
}

body.theme-dark .badge.bg-primary-subtle {
    background-color: rgba(93, 96, 239, .25) !important;
    color: var(--dk-primary-text) !important;
}

body.theme-dark .badge.bg-danger-subtle {
    background-color: rgba(220, 53, 69, .2) !important;
    color: #ff6b7a !important;
}

/* Same fix, .bg-secondary-subtle variant - used by the Topics list's
   "Unpublished" pill (subjects/lessons/topics/partials/topic-meta.blade.php). */
body.theme-dark .badge.bg-secondary-subtle {
    background-color: rgba(108, 117, 125, .25) !important;
    color: #c9ccd1 !important;
}

/* =========================================================================
   Alerts (e.g. the role-detail "In use" banner on settings/nav-links|
   permission-links/role.blade.php, and users/list.blade.php's empty state)
   ========================================================================= */

body.theme-dark .alert-light {
    background-color: var(--dk-surface-alt);
    border-color: var(--dk-border);
    color: var(--dk-text);
}

/* =========================================================================
   Modals
   ========================================================================= */

body.theme-dark .modal-content {
    background-color: var(--dk-surface);
    color: var(--dk-text);
    border-color: var(--dk-border);
}

body.theme-dark .modal-header,
body.theme-dark .modal-footer {
    border-color: var(--dk-border);
}

body.theme-dark .modal-header .btn-close {
    filter: invert(1) grayscale(100%) brightness(200%);
}

/* =========================================================================
   SweetAlert2 popups (alert.js) - same treatment as .modal-content above;
   uses the base --dk-surface/--dk-text tokens so it also reads correctly
   in the Material+Dark combo (material-theme.css layers its own
   radius/shadow on top via body.theme-material .swal2-popup).
   ========================================================================= */

body.theme-dark .swal2-popup {
    background: var(--dk-surface);
    color: var(--dk-text);
}

body.theme-dark .swal-subtitle {
    color: var(--dk-text-secondary);
}

/* .reactors-tab (dashboard.css - reactors-modal.blade.php) has the same
   hardcoded gray-on-white text/hover as the other custom action buttons in
   this file - same fix as .reaction-btn above. .reactor-emoji-badge is a
   small solid-white circle (like .status-badge-inline's border) that needs
   a dark-aware background so it doesn't look like a stray white dot. */
body.theme-dark .reactors-tab {
    color: var(--dk-text-secondary);
}

body.theme-dark .reactors-tab:hover {
    background: var(--dk-surface-alt);
}

body.theme-dark .reactor-emoji-badge {
    background: var(--dk-surface);
    border-color: var(--dk-surface);
}

/* =========================================================================
   .ui-table (used across list/index pages app-wide)
   ========================================================================= */

body.theme-dark .ui-table {
    background: var(--dk-surface);
}

body.theme-dark .ui-table thead th {
    background-color: var(--dk-surface-alt);
    color: var(--dk-text-secondary);
    border-bottom-color: var(--dk-border);
}

body.theme-dark .ui-table tbody td {
    /* Bootstrap's .table cells paint background-color: var(--bs-table-bg),
       which defaults to #fff and was never overridden here - so every
       .ui-table row body-wide was rendering near-invisible light text on a
       white cell background in dark mode (only caption-less border/hover
       colors were themed). Confirmed by rendering (getComputedStyle showed
       td background-color: rgb(255, 255, 255) here before this fix), same
       shape of bug as the other fixes in this file. */
    background-color: var(--dk-surface);
    color: var(--dk-text);
    border-bottom-color: var(--dk-border);
}

body.theme-dark .ui-table tbody tr:hover {
    background-color: var(--dk-surface-alt);
}

/* .topic-list-item (subjects/lessons/partials/topic-list.blade.php) - same
   shape as the .ui-table tbody tr:hover fix above, mirrored for the
   button.topic-list-item:hover rule in style.css. */
body.theme-dark button.topic-list-item:hover,
body.theme-dark button.topic-list-item:focus {
    background-color: var(--dk-surface-alt);
}

body.theme-dark .ui-table-empty {
    color: var(--dk-text-muted);
}

/* =========================================================================
   Class Grades matrix (.grade-table, sections/students/grade.blade.php) -
   the sticky first column and the two summary rows both paint an explicit
   light background in style.css (#ffffff/#f8f9fb/#f9fafb/#f4f6ff), which is
   more specific than the generic .ui-table tbody td dark-mode fix above (it
   targets :first-child / .grade-row-total / .grade-row-average), so it wins
   the cascade and would otherwise show light cells in an otherwise-dark
   table. Same --dk-surface/--dk-surface-alt tokens as the rest of
   .ui-table, so these cells blend in rather than standing out.
   ========================================================================= */

body.theme-dark .grade-table thead th:first-child,
body.theme-dark .grade-table tbody td:first-child {
    background-color: var(--dk-surface);
    box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.4);
}

body.theme-dark .grade-table thead th:first-child {
    background-color: var(--dk-surface-alt);
}

body.theme-dark .grade-table tbody tr:hover td:first-child {
    background-color: var(--dk-surface-alt);
}

body.theme-dark .grade-table tbody tr.grade-row-total td,
body.theme-dark .grade-table tbody tr.grade-row-average td {
    background-color: var(--dk-surface-alt);
}

/* =========================================================================
   Class Attendance matrix (.attendance-table,
   sections/subjects/attendances/index.blade.php) - unlike .grade-table
   above, the header row itself is sticky here too (many student rows to
   scroll through, not just many date columns), so style.css has to paint an
   explicit opaque background on every header cell (not just :first-child)
   to keep rows from showing through as they scroll underneath it. That
   explicit light background needs the same dark-mode override treatment. */

body.theme-dark .attendance-table thead th {
    background-color: var(--dk-surface-alt);
}

body.theme-dark .attendance-table thead th:first-child,
body.theme-dark .attendance-table tbody td:first-child {
    background-color: var(--dk-surface);
    box-shadow: 2px 0 4px -2px rgba(0, 0, 0, 0.4);
}

body.theme-dark .attendance-table thead th:first-child {
    background-color: var(--dk-surface-alt);
}

body.theme-dark .attendance-table tbody tr:hover td:first-child {
    background-color: var(--dk-surface-alt);
}

body.theme-dark .attendance-table thead th:nth-last-child(-n + 2),
body.theme-dark .attendance-table tbody td:nth-last-child(-n + 2) {
    background-color: var(--dk-surface-alt);
}

/* =========================================================================
   Class Schedule widget (.cd-schedule, styled in schedule.css - the
   CodyHouse "Schedule Table" component embedded in
   sections/schedules/index.blade.php and schedules/index.blade.php). The
   widget's text color already follows dark mode for free via `color:
   inherit` in schedule.css, so only the light gridline/border color (used
   for the desktop timeline hour-lines and the per-day column borders)
   needs an explicit override here - everything else (event cards) keeps
   its own subject-driven background color regardless of theme.
   ========================================================================= */

body.theme-dark .cd-schedule {
    --schedule-border: var(--dk-border);
}

body.theme-dark .cd-schedule .no-schedule {
    color: var(--dk-text-muted);
}

/* login/register/reset render the PathBuilder wordmark as a single raster
   image (logo.webp) with the "PathBuilder for Schools" text baked in at a
   fixed dark color, sized for a light card background. On a dark card that
   text becomes nearly invisible (confirmed by rendering - only the
   colored icon glyph stays legible). Can't recolor pixels inside a raster
   image with CSS, so give it a light backdrop patch instead, scoped to
   this specific logo via its alt text so it can't accidentally match the
   different sidebar logo image. */
body.theme-dark img[alt="PathBuilder School logo"] {
    background: #fff;
    border-radius: 12px;
    padding: 8px;
}

/* Every view falls back to the same /assets/images/user.webp icon when a
   user has no uploaded photo (topnav, dashboard feed, online users list,
   users list/form, section share dialogs, articles, ...). That icon is a
   dark silhouette, tuned for a light avatar circle - on a dark surface it
   blends in and disappears, same shape of bug as the other fixes in this
   file. Tried swapping to a pre-made "white-user.png" via `content: url()`
   first, but that asset turned out to be near-invisible itself (very
   light/low-contrast on transparent, confirmed by opening the file) - so
   instead this recolors the original icon with the same invert+grayscale
   filter already used above for .btn-close/no-image.png, which reliably
   turns its dark strokes light regardless of the source asset. Matching on
   the `src` attribute (rather than editing every view or adding JS) means
   it also covers any avatar swapped to this fallback at runtime via
   onerror, and any future view that follows the same convention. */
body.theme-dark img[src$="/assets/images/user.webp"] {
    filter: invert(1) grayscale(100%) brightness(160%);
}

/* Every post image (.feed-image) that 404s falls back, via each view's
   onerror="this.src='/assets/images/no-image.png'", to this placeholder -
   a near-white/pale-cyan graphic with a muted gray-teal icon, tuned for a
   light page. Unlike .feed-card itself (which is themed), this is a raster
   image with its own baked-in pale background, so no background-color
   override can fix it - it renders as a large near-white box no matter
   what surface it sits on. Same invert+grayscale trick already used above
   for .btn-close neutralizes its color and flips light<->dark, turning the
   pale backdrop dark and the icon light instead of leaving a blank-looking
   white panel in the feed. */
body.theme-dark img[src$="/assets/images/no-image.png"] {
    filter: invert(1) grayscale(100%);
    background-color: var(--dk-surface-alt);
}

/* =========================================================================
   Authoring Tool editor (layouts/editor.blade.php, styled in editor.css) -
   reused in 4 places: subjects/lessons/topics/create-modal.blade.php,
   subjects/assessments/view.blade.php (essay answers), libraries/view.blade.php
   and articles/form.blade.php - so this fix benefits all four. editor.css
   hardcodes a white .authoring-editor surface, a light-grey #f8f9fa
   toolbar and an #e9ecef hover, none of which had any dark-mode entry
   before this (confirmed zero "editor" references previously in this
   file), leaving a stark light panel inside an otherwise dark modal/page.
   Toolbar buttons themselves already ride the app-wide
   body.theme-dark .btn-light rule above, so only the surfaces below need
   their own override. */
body.theme-dark .authoring-editor {
    background-color: var(--dk-surface) !important;
    border-color: var(--dk-border) !important;
}

body.theme-dark .editor-toolbar {
    background: var(--dk-surface-alt);
    border-color: var(--dk-border) !important;
}

body.theme-dark .editor-toolbar .btn:hover {
    background-color: var(--dk-border);
}

body.theme-dark .editor-content {
    color: var(--dk-text);
}

@media (max-width: 575.98px) {
    body.theme-dark .editor-toolbar-group {
        border-bottom-color: var(--dk-border);
    }
}

/* =========================================================================
   MATERIAL + DARK  (body.theme-material.theme-dark)
   material-theme.css builds every Material component off of a shared set
   of --md-* design-token variables declared on `body.theme-material`.
   Re-declaring those same variables here - under the more specific
   `body.theme-material.theme-dark` selector - is enough to make every
   Material surface/border/text-on-surface pick up dark values without
   duplicating each component rule; only the few things that need a
   genuinely different treatment on dark (borders needing to read lighter,
   elevation shadows needing more contrast against an already-dark
   surface) get an explicit rule below.
   ========================================================================= */

body.theme-material.theme-dark {
    --md-primary: var(--bs-primary, #5d60ef);
    --md-primary-dark: #4547c9;
    /* white-on-filled-primary stays high contrast in both modes - the
       Material top app bar/active nav/filled buttons don't need to change. */
    --md-on-primary: #ffffff;
    --md-primary-tint: rgba(93, 96, 239, .22);
    --md-on-primary-tint: #b8baff;

    --md-surface: var(--dk-surface);
    --md-surface-alt: var(--dk-surface-alt);
    --md-on-surface: var(--dk-text);
    --md-on-surface-variant: var(--dk-text-muted);

    /* Material leans on visible 1px borders more than Modern does, so give
       them extra lightness/contrast against the dark surface rather than
       reusing Modern's slightly dimmer --dk-border. */
    --md-border: #454c62;
    --md-border-strong: #59617c;

    --md-error: #ff6b7a;
    --md-error-tint: rgba(255, 107, 122, .15);

    /* Elevation shadows read as depth cues against a LIGHT surface in the
       original Material spec; on a dark surface a same-toned shadow all
       but disappears, so darken/strengthen them instead of trying to
       fully replicate Material's dark-theme surface-tint elevation system. */
    --md-elevation-1: 0 1px 2px 0 rgba(0, 0, 0, .55), 0 1px 3px 1px rgba(0, 0, 0, .35);
    --md-elevation-2: 0 1px 2px 0 rgba(0, 0, 0, .55), 0 2px 6px 2px rgba(0, 0, 0, .35);
    --md-elevation-4: 0 2px 3px 0 rgba(0, 0, 0, .55), 0 6px 10px 4px rgba(0, 0, 0, .35);
    --md-elevation-8: 0 4px 4px 0 rgba(0, 0, 0, .55), 0 8px 12px 6px rgba(0, 0, 0, .35);
    --md-elevation-16: 0 8px 10px -5px rgba(0, 0, 0, .5), 0 16px 24px 2px rgba(0, 0, 0, .45), 0 6px 30px 5px rgba(0, 0, 0, .4);

    background-color: var(--dk-bg);
}

body.theme-material.theme-dark .app-wrapper {
    background: var(--dk-bg);
}

/* Material's sidebar nav rows use --md-on-surface-variant for idle text and
   a solid --md-primary fill for the active row - both already flip to dark
   values via the variable overrides above, no extra rule needed. */

body.theme-material.theme-dark .topnav > .btn:hover,
body.theme-material.theme-dark .topnav > .btn:focus {
    background-color: rgba(255, 255, 255, .12);
}

/* =========================================================================
   Assessment Score page - .question-block correct/incorrect tint
   (sections/subjects/assessments/score.blade.php). Light-mode uses pale
   green/red tints on a white card; dark mode swaps to a low-opacity tint
   over the themed dark surface instead of the light-mode hex values (which
   would render as a near-white block on a dark page).
   ========================================================================= */

body.theme-dark .question-block {
    border-color: var(--dk-border);
    background-color: var(--dk-surface);
}

body.theme-dark .question-block-correct {
    border-color: #2f9e5c;
    background-color: rgba(47, 158, 92, 0.12);
}

body.theme-dark .question-block-incorrect {
    border-color: #dc3545;
    background-color: rgba(220, 53, 69, 0.12);
}

/* =========================================================================
   Calendar (calendars/index.blade.php) - the FullCalendar widget had zero
   dark-mode coverage: .calendar-wrapper is a hardcoded white card
   (calendar.css) and several .fc-* rules there set explicit light-mode hex
   colors, so in dark mode this rendered as a bright white box in the
   middle of an otherwise dark page. Two layers here: the specific classes
   calendar.css already customizes get dark counterparts below, and
   FullCalendar's own un-customized chrome (day-cell backgrounds, header
   row, borders) is retargeted via its official --fc-* theming variables,
   scoped to .calendar-wrapper so it doesn't leak into anything else.
   ========================================================================= */

body.theme-dark .calendar-wrapper {
    background: var(--dk-surface-alt);

    --fc-page-bg-color: var(--dk-surface-alt);
    --fc-neutral-bg-color: var(--dk-surface);
    --fc-border-color: var(--dk-border);
    --fc-list-event-hover-bg-color: var(--dk-surface);
    --fc-today-bg-color: rgba(93, 96, 239, .15);
    --fc-button-text-color: var(--dk-text);
    --fc-button-bg-color: var(--dk-surface);
    --fc-button-border-color: var(--dk-border);
    --fc-button-hover-bg-color: var(--dk-border);
    --fc-button-hover-border-color: var(--dk-border-strong);
    --fc-button-active-bg-color: var(--bs-primary);
    --fc-button-active-border-color: var(--bs-primary);
}

body.theme-dark .fc .fc-toolbar-title {
    color: var(--dk-text);
}

body.theme-dark .fc .fc-button {
    background: var(--dk-surface);
    color: var(--dk-primary-text);
}

body.theme-dark .fc .fc-button-primary:not(:disabled).fc-button-active {
    background: var(--bs-primary);
    color: #fff;
}

body.theme-dark .fc .fc-daygrid-day-number {
    color: var(--dk-text-secondary);
}

body.theme-dark .fc .fc-day-today {
    background: rgba(93, 96, 239, .15) !important;
}

/* =========================================================================
   Chat module (chats/index.blade.php) - chat.css hardcodes every surface,
   border, and text color as light-mode-only hex (white panels, #e9ecef
   borders, #6c757d/#9aa1a9 muted text) with zero dark-mode counterpart
   anywhere, so the whole two-column messaging UI rendered as a bright
   white block regardless of theme. Mapped onto the same --dk-* tokens
   every other module in this file uses.
   ========================================================================= */

body.theme-dark .chat-list-container,
body.theme-dark .chat-box {
    background: var(--dk-surface-alt);
    border-color: var(--dk-border);
}

body.theme-dark .chat-list-header,
body.theme-dark .chat-header,
body.theme-dark .chat-input {
    border-color: var(--dk-border);
}

body.theme-dark .chat-input {
    background: var(--dk-surface-alt);
}

body.theme-dark .chat-item {
    border-bottom-color: var(--dk-border);
}

body.theme-dark .chat-item:hover,
body.theme-dark .chat-item.active {
    background: var(--dk-surface);
}

body.theme-dark .chat-name {
    color: var(--dk-text);
}

body.theme-dark .chat-preview {
    color: var(--dk-text-muted);
}

body.theme-dark .chat-time {
    color: var(--dk-text-muted);
}

body.theme-dark .chat-item.unread {
    background: rgba(93, 96, 239, .12);
}

body.theme-dark .chat-item.unread .chat-name,
body.theme-dark .chat-item.unread .chat-preview {
    color: var(--dk-text);
}

body.theme-dark .chat-body {
    background: var(--dk-surface);
}

body.theme-dark .empty-chat {
    color: var(--dk-text-muted);
}

/* .message.sent keeps its own solid gradient + white text unchanged -
   only .received (a pale light-blue bubble in light mode) and the audio
   bubble need a dark counterpart, since a light tint on a dark page reads
   as an unintended bright block same as everywhere else in this file. */
body.theme-dark .message.received,
body.theme-dark .audio-msg {
    background: var(--dk-surface-alt);
    color: var(--dk-text);
}

body.theme-dark .tag-container {
    background: var(--dk-surface-alt);
    border-color: var(--dk-border);
}

body.theme-dark .tag-container input {
    background: transparent;
    color: var(--dk-text);
}

body.theme-dark .chat-list-header .btn {
    background: var(--dk-surface);
    color: var(--dk-text);
}

body.theme-dark .chat-list-header .btn:hover {
    background: var(--dk-border);
}

body.theme-dark .attachment-preview {
    background: var(--dk-surface);
    color: var(--dk-text);
}

body.theme-dark .message.received .message-file-doc {
    background: rgba(255, 255, 255, .06);
    color: var(--dk-text);
}
