/*
 * Student Hub design system.
 * Layered on top of Bootstrap 5 (loaded before this file) — Bootstrap
 * supplies component structure and JS behavior; these rules give the
 * app its own light, professional visual identity and are the single
 * source of truth for color/type/spacing used across every module.
 *
 * All color pairs below were checked against WCAG 2.2 AA contrast
 * thresholds (4.5:1 text, 3:1 UI-component boundaries) before use.
 */

:root {
    /* Color — indigo/purple primary accent (app-wide, per the SaaS
       design reference). Chosen as a Tailwind-indigo-600-equivalent
       pair: white text on --sh-primary, and --sh-primary text on
       --sh-primary-light, both comfortably clear WCAG AA (4.5:1+). */
    --sh-primary: #4F46E5;
    --sh-primary-hover: #4338CA;
    --sh-primary-light: #EEF0FF;
    --sh-secondary: #5B6472;

    /* Sidebar — dark navy shell, independent of the content-area
       tokens above so the sidebar can be dark while every card/table/
       form elsewhere stays on the existing light palette. */
    --sh-sidebar-bg: #111827;
    --sh-sidebar-bg-hover: #1F2937;
    --sh-sidebar-text: #CBD5E1;
    --sh-sidebar-text-muted: #94A3B8;
    --sh-sidebar-border: #1F2937;
    --sh-sidebar-active-bg: rgba(99, 102, 241, 0.16);
    --sh-sidebar-active-text: #C7D2FE;
    --sh-sidebar-active-border: #818CF8;

    --sh-success: #1E6B3C;
    --sh-success-bg: #E6F4EA;
    --sh-danger: #B3261E;
    --sh-danger-bg: #FBEAE9;
    --sh-warning-text: #664D03;
    --sh-warning-bg: #FFF3CD;
    --sh-info: #1C5E8A;
    --sh-info-bg: #E6F1F8;

    --sh-bg: #F5F7FA;
    --sh-surface: #FFFFFF;
    --sh-border: #8792A2;
    --sh-border-subtle: #E2E5EA;
    --sh-text: #1A202C;
    --sh-text-muted: #5B6472;

    /* Typography */
    --sh-font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    --sh-fs-xs: 0.75rem;
    --sh-fs-sm: 0.875rem;
    --sh-fs-base: 1rem;
    --sh-fs-lg: 1.125rem;
    --sh-fs-xl: 1.375rem;
    --sh-fs-2xl: 1.75rem;
    --sh-fs-3xl: 2.25rem;

    /* Spacing (4px grid) */
    --sh-space-1: 0.25rem;
    --sh-space-2: 0.5rem;
    --sh-space-3: 0.75rem;
    --sh-space-4: 1rem;
    --sh-space-5: 1.5rem;
    --sh-space-6: 2rem;
    --sh-space-8: 3rem;

    /* Shape */
    --sh-radius-sm: 6px;
    --sh-radius-md: 10px;
    --sh-radius-lg: 14px;
    --sh-shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.08);
    --sh-shadow-md: 0 4px 12px rgba(16, 24, 40, 0.10);

    /* Layout: fixed so sticky elements (table headers) can dock exactly
       below the topbar instead of guessing its rendered height. */
    --sh-topbar-height: 68px;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    font-family: var(--sh-font-sans);
    font-size: var(--sh-fs-base);
    color: var(--sh-text);
    background-color: var(--sh-bg);
    line-height: 1.5;
}

h1, h2, h3, h4, h5, h6 {
    font-weight: 600;
    line-height: 1.25;
    color: var(--sh-text);
}

h1 { font-size: var(--sh-fs-3xl); }
h2 { font-size: var(--sh-fs-2xl); }
h3 { font-size: var(--sh-fs-xl); }

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

/* Visible, consistent focus indicator on every interactive element */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 3px solid var(--sh-primary);
    outline-offset: 2px;
}

/* Skip-to-main-content link */
.skip-link {
    position: absolute;
    top: -100px;
    left: var(--sh-space-3);
    z-index: 2000;
    padding: var(--sh-space-2) var(--sh-space-4);
    background: var(--sh-primary);
    color: #fff;
    border-radius: var(--sh-radius-sm);
    text-decoration: none;
}

.skip-link:focus {
    top: var(--sh-space-3);
}

/* Buttons */
.btn {
    border-radius: var(--sh-radius-sm);
    font-weight: 500;
    min-height: 2.5rem;
    padding-inline: var(--sh-space-4);
}

.btn-primary {
    --bs-btn-bg: var(--sh-primary);
    --bs-btn-border-color: var(--sh-primary);
    --bs-btn-hover-bg: var(--sh-primary-hover);
    --bs-btn-hover-border-color: var(--sh-primary-hover);
    --bs-btn-active-bg: var(--sh-primary-hover);
    --bs-btn-active-border-color: var(--sh-primary-hover);
    --bs-btn-disabled-bg: var(--sh-primary);
    --bs-btn-disabled-border-color: var(--sh-primary);
}

.btn-outline-secondary {
    --bs-btn-color: var(--sh-secondary);
    --bs-btn-border-color: var(--sh-border);
    --bs-btn-hover-bg: var(--sh-secondary);
    --bs-btn-hover-border-color: var(--sh-secondary);
}

/* Danger button skin — reserved for destructive actions (Delete, Reset
   Password, etc.), same token-driven override pattern as primary/
   outline-secondary above so all three read as one system. */
.btn-danger {
    --bs-btn-bg: var(--sh-danger);
    --bs-btn-border-color: var(--sh-danger);
    --bs-btn-hover-bg: #8f1e18;
    --bs-btn-hover-border-color: #8f1e18;
    --bs-btn-active-bg: #8f1e18;
    --bs-btn-active-border-color: #8f1e18;
}

.btn-outline-danger {
    --bs-btn-color: var(--sh-danger);
    --bs-btn-border-color: var(--sh-danger);
    --bs-btn-hover-bg: var(--sh-danger);
    --bs-btn-hover-border-color: var(--sh-danger);
}

/* Forms */
.form-label {
    font-weight: 500;
    margin-bottom: var(--sh-space-1);
}

.form-control,
.form-select {
    border-color: var(--sh-border);
    border-radius: var(--sh-radius-sm);
    min-height: 2.5rem;
}

.form-control:focus,
.form-select:focus {
    border-color: var(--sh-primary);
    box-shadow: 0 0 0 3px var(--sh-primary-light);
}

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

/* Password field with a show/hide toggle: the input gets right-padding
   so its own text never runs under the button, which sits on top of it
   as a plain icon control (no border/background) so it doesn't read as
   a second, separate input. */
.password-field {
    position: relative;
}

.password-field .form-control {
    padding-right: 2.75rem;
}

.password-toggle {
    position: absolute;
    top: 0;
    right: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 100%;
    min-height: 2.5rem;
    background: none;
    border: none;
    color: var(--sh-text-muted);
    font-size: var(--sh-fs-lg);
}

.password-toggle:hover {
    color: var(--sh-text);
}

/* File uploads: a lightly tinted, clearly-clickable "Choose file"
   button on the native input — no drag-and-drop widget or JS, just a
   cleaner skin on the browser's own file picker control so it reads
   as an intentional upload area rather than default OS chrome. */
.form-control[type="file"] {
    padding: var(--sh-space-2) var(--sh-space-3);
}

.form-control[type="file"]::file-selector-button {
    margin-inline-end: var(--sh-space-3);
    padding: var(--sh-space-2) var(--sh-space-3);
    border: 1px solid var(--sh-border);
    border-radius: var(--sh-radius-sm);
    background-color: var(--sh-primary-light);
    color: var(--sh-primary);
    font-weight: 500;
    transition: background-color 0.15s ease;
}

.form-control[type="file"]:hover::file-selector-button {
    background-color: var(--sh-primary);
    color: #fff;
}

.is-invalid ~ .invalid-feedback,
.invalid-feedback {
    color: var(--sh-danger);
    font-weight: 500;
}

/* Cards */
.card {
    border: 1px solid var(--sh-border-subtle);
    border-radius: var(--sh-radius-md);
    box-shadow: var(--sh-shadow-sm);
    /* A bit more breathing room than Bootstrap's 1rem default, on
       every card/card-header/card-body/card-footer app-wide. */
    --bs-card-spacer-y: 1.25rem;
    --bs-card-spacer-x: 1.25rem;
}

/* Grid gutters: loosens the two gutter classes used everywhere in
   this app for card grids (KPI rows, section-card rows, etc.) —
   Bootstrap's own g-3/g-4 gutters are fixed values unrelated to the
   --sh-space-* tokens, so this is the one place that needs to
   override them directly rather than through a variable. */
.row.g-3 { --bs-gutter-x: 1.25rem; --bs-gutter-y: 1.25rem; }
.row.g-4 { --bs-gutter-x: 1.75rem; --bs-gutter-y: 1.75rem; }

.card-header {
    background-color: var(--sh-surface);
    border-bottom: 1px solid var(--sh-border-subtle);
    font-weight: 600;
}

/* Reports menu: whole-card links (not just an icon or a small "Open"
   button) — a visible hover/focus treatment makes them read as
   interactive, and the color change is paired with the existing
   shadow-lift, never color alone. */
.report-menu-card {
    color: inherit;
    transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

.report-menu-card:hover,
.report-menu-card:focus-visible {
    box-shadow: var(--sh-shadow-md);
    border-color: var(--sh-primary);
}

.report-menu-card h2 {
    color: var(--sh-primary);
}

/* Danger Zone: a plain card whose header is tinted to read as
   "destructive actions live here" without needing red text on every
   line inside it — the same restrained color-as-accent approach as
   .dashboard-section-card's colored top border. */
.danger-zone > .card-header {
    background-color: var(--sh-danger-bg);
    color: var(--sh-danger);
    border-bottom-color: var(--sh-danger);
}

/* Student photo thumbnail on the Room Details page */
.room-student-photo {
    width: 56px;
    height: 56px;
    border-radius: var(--sh-radius-md);
    object-fit: cover;
    flex-shrink: 0;
}

.room-student-photo--placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--sh-bg);
    border: 1px solid var(--sh-border-subtle);
    color: var(--sh-text-muted);
    font-size: var(--sh-fs-xl);
}

/* ID proof front/back thumbnail (Student View and Edit pages) */
.id-proof-thumb {
    display: block;
    max-width: 220px;
    max-height: 140px;
    width: auto;
    height: auto;
    object-fit: contain;
    border: 1px solid var(--sh-border-subtle);
    border-radius: var(--sh-radius-md);
    background-color: var(--sh-bg);
}

/* Room picker preview (Add/Edit Student) */
.room-picker-summary {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--sh-space-1) var(--sh-space-3);
    padding: var(--sh-space-3);
    background: var(--sh-bg);
    border: 1px solid var(--sh-border-subtle);
    border-radius: var(--sh-radius-sm);
    font-size: var(--sh-fs-sm);
}

.room-picker-summary dt {
    font-weight: 600;
    color: var(--sh-text-muted);
}

.room-picker-summary dd {
    margin: 0;
}

/* Tables */
.table {
    --bs-table-border-color: var(--sh-border-subtle);
}

.table thead th {
    font-size: var(--sh-fs-sm);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--sh-text-muted);
    background-color: var(--sh-bg);
    border-bottom: 2px solid var(--sh-border-subtle);
}

/*
 * Wide list tables (Students, Payments): give the first identity
 * column (name) enough room that typical 2-3 word values sit on one
 * line, while narrower fixed-format columns (mobile, room, dates,
 * currency, status, actions) stay compact via .text-nowrap / explicit
 * widths below. .students-table-scroll / .payments-table-scroll still
 * provide horizontal scroll as the fallback for anything that
 * genuinely doesn't fit (e.g. small phones).
 *
 * The first column is also frozen (sticky left) so it stays visible
 * while scrolling horizontally through the rest of the row, and the
 * header row is frozen (sticky top) so column labels stay visible
 * while scrolling down through many rows. Both are pure CSS
 * positioning — DOM order and semantics (scope="col", reading order)
 * are untouched, so this doesn't affect screen readers.
 *
 * IMPORTANT — why the header sticks to *this wrapper*, not the page:
 * the original approach set only overflow-x: auto on Bootstrap's
 * .table-responsive and left overflow-y at its "visible" default,
 * intending the header to dock below the topbar as the whole PAGE
 * scrolled. Per the CSS Overflow spec, a non-"visible" value on one
 * axis with "visible" left on the other silently promotes the other
 * to "auto" — so this wrapper became an (invisible, no scrollbar
 * ever appeared) vertical scroll container too, which hijacked it as
 * the containing block for "position: sticky; top: <topbar height>"
 * on the header cells. Result: the header cells rendered permanently
 * offset by that many pixels *from the wrapper's own top edge* —
 * not "once you scroll" — overlapping the first couple of data rows
 * at all times. (Trying to opt back out with overflow-y: clip doesn't
 * work either: the spec downgrades a lone "clip" paired with "auto"
 * on the other axis to "hidden", which is still a valid sticky
 * containing block.) Both were confirmed via getBoundingClientRect()
 * against the live page, not guessed — see the Students-table fix
 * this pattern originated from.
 *
 * The fix embraces the promotion instead of fighting it: each wrapper
 * is an intentional, bounded-height scroll container for BOTH axes,
 * so "top: 0" on the header means exactly what it says — stuck to
 * this box's own top edge — with no dependency on an unrelated
 * ancestor's height. This is also the standard "frozen header +
 * frozen column" table pattern, reused as-is for Payments so it never
 * has to rediscover the same bug.
 */
.students-table-scroll,
.payments-table-scroll,
.electricity-table-scroll,
.complaints-table-scroll,
.reports-table-scroll,
.audit-table-scroll,
.rooms-table-scroll,
.room-types-table-scroll,
.admins-table-scroll {
    overflow: auto;
    max-height: min(65vh, 560px);
    scroll-behavior: auto;
    overflow-anchor: none;
}

.students-table td,
.payments-table td,
.electricity-table td,
.complaints-table td,
.reports-table td,
.audit-table td,
.rooms-table td,
.room-types-table td,
.admins-table td {
    vertical-align: middle;
}

/* Row hover: a subtle background tint on every data table's rows —
   applied globally via the shared .table class so every module gets
   it automatically, no per-table opt-in needed. The frozen identity
   column (below) gets the same tint on hover so it doesn't look like
   a different, un-hovered row underneath it. */
.table tbody tr:hover > * {
    background-color: var(--sh-bg);
}

/* Students table: when a room has more than one student, each column
   stacks that room's students as separate entries inside the same
   <td> — so the whole room is still one <tr>, with every student's own
   value (and, in the Actions column, their own View/Edit/Checkout
   links) lined up entry-for-entry across columns. */
.students-table .stacked-list {
    display: flex;
    flex-direction: column;
    gap: var(--sh-space-2);
}

.students-table .stacked-item {
    display: flex;
    align-items: center;
    min-height: 1.75rem;
}

.students-table .stacked-list .stacked-item:not(:last-child) {
    padding-bottom: var(--sh-space-2);
    border-bottom: 1px solid var(--sh-border-subtle);
}

.students-table .col-actions .stacked-item {
    flex-wrap: wrap;
    gap: var(--sh-space-1);
}

.students-table thead th,
.payments-table thead th,
.electricity-table thead th,
.complaints-table thead th,
.reports-table thead th,
.audit-table thead th,
.rooms-table thead th,
.room-types-table thead th,
.admins-table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
}

.students-table .col-student-name,
.payments-table .col-student-name,
.electricity-table .col-student-name,
.complaints-table .col-student-name,
.reports-table .col-student-name,
.audit-table .col-student-name,
.rooms-table .col-student-name,
.room-types-table .col-student-name,
.admins-table .col-student-name {
    min-width: 10rem;
    max-width: 18rem;
    position: sticky;
    left: 0;
    z-index: 1;
    background-color: var(--sh-surface);
    box-shadow: 1px 0 0 var(--sh-border-subtle);
}

.students-table thead th.col-student-name,
.payments-table thead th.col-student-name,
.electricity-table thead th.col-student-name,
.complaints-table thead th.col-student-name,
.reports-table thead th.col-student-name,
.audit-table thead th.col-student-name,
.rooms-table thead th.col-student-name,
.room-types-table thead th.col-student-name,
.admins-table thead th.col-student-name {
    z-index: 3;
    background-color: var(--sh-bg);
}

/* Desktop column-width tightening: fixed-format columns don't need
   more room than their content ever actually uses, so give the extra
   space back before falling to horizontal scroll. */
@media (min-width: 992px) {
    .students-table .col-actions,
    .payments-table .col-actions,
    .electricity-table .col-actions,
    .complaints-table .col-actions,
    .audit-table .col-actions,
    .rooms-table .col-actions,
    .room-types-table .col-actions,
    .admins-table .col-actions {
        white-space: nowrap;
    }

    .students-table .col-actions .btn,
    .payments-table .col-actions .btn,
    .electricity-table .col-actions .btn,
    .complaints-table .col-actions .btn,
    .audit-table .col-actions .btn,
    .rooms-table .col-actions .btn,
    .room-types-table .col-actions .btn,
    .admins-table .col-actions .btn {
        padding-inline: var(--sh-space-2);
    }
}

/* Stat cards (Payments ledger summary): plain numbers, never the only
   signal of meaning — each is paired with a text label above it. */
.stat-card-label {
    font-size: var(--sh-fs-sm);
    color: var(--sh-text-muted);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.stat-card-value {
    font-size: var(--sh-fs-2xl);
    font-weight: 700;
    color: var(--sh-text);
    white-space: nowrap;
}

/* At narrow widths two stat cards per row leave too little room for a
   ₹2xl-size currency value to stay on one line without this — shrink
   the number rather than let it wrap mid-value (e.g. "₹50,750.0" /
   "0" split across two lines). */
@media (max-width: 420px) {
    .stat-card-value {
        font-size: var(--sh-fs-xl);
    }
}

/* Printable receipt: kept inside the normal app shell on-screen
   (so navigation/back/print controls work normally) but the shell
   chrome disappears for the printed page via the existing @media
   print rule in app.css; .no-print hides the on-screen-only action
   buttons that would otherwise print as unusable ink. */
.no-print {
    display: flex;
}

@media print {
    .no-print {
        display: none !important;
    }

    .receipt-card {
        border: none;
        box-shadow: none;
    }

    /* Reports: the bounded-height scroll region (.students-table-scroll
       and friends) is exactly right on screen, but printing only what's
       currently scrolled into view would silently cut off a long
       report — browsers don't reliably re-expand a scrolled, fixed-
       height container to show its full content on the printed page.
       Drop the height cap and sticky positioning for print only, so
       every row prints, not just the last scroll position. */
    .reports-table-scroll {
        max-height: none;
        overflow: visible;
    }

    .reports-table thead th,
    .reports-table .col-student-name {
        position: static;
        box-shadow: none;
    }
}

/* Badges — always pair color with an icon or text, never color alone */
.badge {
    font-weight: 600;
    font-size: var(--sh-fs-xs);
    padding: 0.35em 0.65em;
    border-radius: var(--sh-radius-sm);
}

.badge-success { color: var(--sh-success); background-color: var(--sh-success-bg); }
.badge-danger  { color: var(--sh-danger);  background-color: var(--sh-danger-bg); }
.badge-warning { color: var(--sh-warning-text); background-color: var(--sh-warning-bg); }
.badge-info    { color: var(--sh-info);    background-color: var(--sh-info-bg); }

/* Alerts */
.alert {
    border-radius: var(--sh-radius-md);
    border: 1px solid transparent;
}

.alert-success { color: var(--sh-success); background-color: var(--sh-success-bg); border-color: var(--sh-success); }
.alert-danger  { color: var(--sh-danger);  background-color: var(--sh-danger-bg);  border-color: var(--sh-danger); }

/* Touch targets */
.btn, .form-control, .form-select, .app-nav-list a {
    min-height: 44px;
}

/* Breadcrumbs: reuses Bootstrap's shipped .breadcrumb component,
   restyled with the app's own tokens so it reads as part of the same
   system rather than default Bootstrap chrome. */
.breadcrumb {
    margin-bottom: var(--sh-space-3);
    font-size: var(--sh-fs-sm);
}

.breadcrumb-item a {
    color: var(--sh-text-muted);
    text-decoration: none;
}

.breadcrumb-item a:hover,
.breadcrumb-item a:focus-visible {
    color: var(--sh-primary);
    text-decoration: underline;
}

.breadcrumb-item.active {
    color: var(--sh-text);
    font-weight: 500;
}

/*
 * Narrow single-column form wrappers: three fixed widths cover every
 * form/detail card in the app (previously each page hardcoded its own
 * `style="max-width: ...px"`). Applied alongside the existing `card`
 * class, e.g. `class="card form-panel"`.
 */
.form-panel-sm { max-width: 560px; }
.form-panel     { max-width: 640px; }
.form-panel-lg  { max-width: 720px; }

/*
 * Narrow number inputs (meter readings, unit rates): replaces
 * one-off `style="min-width: ...rem"` on a handful of Electricity/
 * Payments form fields with the same three sizes they already used.
 */
.input-narrow-sm { min-width: 6rem; }
.input-narrow-md { min-width: 7rem; }
.input-narrow-lg { min-width: 8rem; }

/* Larger student photo (Student Profile header) — same
   modifier pattern as .room-student-photo--placeholder. */
.room-student-photo--lg {
    width: 88px;
    height: 88px;
}

.room-student-photo--lg.room-student-photo--placeholder {
    font-size: 2rem;
}
