:root {
    --primary: #2563eb;
    --primary-dark: #1d4ed8;
    --danger: #dc2626;
    --success: #16a34a;
    --bg: #f5f7fa;
    --border: #e2e8f0;
    --text: #1e293b;
    --muted: #64748b;
}
* { box-sizing: border-box; }
body {
    margin: 0;
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    background: var(--bg);
    color: var(--text);
}
/* ---------------------------------------------------------------------
   App shell: a left sidebar (nav links) + a main area (top bar + page
   content) side by side. This replaces the old single horizontal navbar,
   which ran out of room once a role like admin had 10+ links in it.
   ------------------------------------------------------------------- */
.app-shell { display: flex; min-height: 100vh; }

/* ---------------------------------------------------------------------
   Portal Background Image (see Settings -> Portal Background Image): when
   a school uploads one, includes/header.php sets it as the --portal-bg
   CSS variable on .app-shell below, as a FIXED full-page photo (it stays
   in place while the sidebar/content scroll over it). When no photo is
   uploaded, --portal-bg is simply never set, so the "none" fallback here
   keeps the plain page background exactly like before.
   ------------------------------------------------------------------- */
.app-shell {
    background-image: var(--portal-bg, none);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    background-attachment: fixed;
}

.sidebar {
    width: 240px;
    flex-shrink: 0; /* never let the topbar/content squeeze the sidebar narrower */
    /* Translucent + blurred rather than solid white, so it reads as a
       frosted "glass" layer floating on top of the background photo above,
       instead of hiding it completely -- same idea used by sites like
       Cisco Networking Academy. Looks like plain near-white when there's
       no background photo set. */
    background: rgba(255, 255, 255, 0.82);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px); /* Safari still needs the -webkit- prefix for this property */
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    position: sticky;
    top: 0;
    height: 100vh;
    overflow-y: auto;
    z-index: 20;
}
.sidebar-brand {
    display: flex; align-items: center; gap: 0.65rem;
    font-weight: 700; font-size: 1.05rem;
    padding: 1.1rem 1.1rem 1rem;
    border-bottom: 1px solid var(--border);
}
.sidebar nav { display: flex; flex-direction: column; padding: 0.6rem 0.65rem 1.5rem; gap: 0.15rem; }
.sidebar nav a {
    display: flex; align-items: center; gap: 0.65rem;
    padding: 0.6rem 0.7rem;
    border-radius: 8px;
    color: var(--text);
    text-decoration: none;
    font-size: 0.92rem;
}
.sidebar nav a:hover { background: #eff6ff; color: var(--primary); }
.sidebar-section-label {
    font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em;
    color: var(--muted); font-weight: 700;
    margin: 1rem 0.7rem 0.35rem;
}
.sidebar-section-label:first-child { margin-top: 0.4rem; }

.main-area { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* Pushes the footer down to the bottom of the viewport even on short pages
   (e.g. Students/Classes/Teachers/Subjects with only a few rows). Without
   this, <main> only takes up as much height as its own content needs, so
   the footer right after it ends up sitting in the middle of the screen
   instead of at the bottom. Giving <main> the REST of .main-area's height
   (flex: 1 1 auto, since .main-area is itself a flex column filling the
   full-height sidebar's height) fixes that on every page that goes through
   this shared layout -- no per-page change needed. */
.main-area main { flex: 1 1 auto; }

.topbar {
    display: flex; align-items: center; justify-content: space-between;
    /* Same frosted-glass treatment as .sidebar above, so the topbar reads
       as part of the same floating layer rather than a mismatched solid
       strip. */
    background: rgba(255, 255, 255, 0.82);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--border);
    padding: 0.75rem 1.5rem;
    position: sticky; top: 0; z-index: 10;
}
.topbar-spacer { flex: 1; }

/* The ☰ button only ever appears on narrow screens -- see the media query
   near the bottom of this file, which is also where the sidebar itself
   switches from "always visible" to "hidden until opened". */
.sidebar-toggle {
    display: none;
    font-size: 1.3rem;
    background: none; border: none; cursor: pointer;
    color: var(--text);
    padding: 0.25rem 0.5rem;
}
.sidebar-backdrop {
    display: none;
    position: fixed; inset: 0;
    background: rgba(15, 23, 42, 0.4);
    z-index: 15;
}

.navbar-user { display: flex; align-items: center; gap: 0.75rem; font-size: 0.9rem; color: var(--muted); }
.navbar-user-link { display: flex; align-items: center; gap: 0.5rem; color: var(--muted); text-decoration: none; }
.navbar-user-link:hover { color: var(--primary); }
.btn-link { color: var(--primary); text-decoration: none; }

.school-logo { height: 40px; max-width: 190px; object-fit: contain; }
.navbar-icon-fallback { font-size: 2rem; line-height: 1; }
.nexus-mark { display: block; }
.nexus-mark-nav { width: 28px; height: 28px; }
.nexus-mark-portal { width: 56px; height: 56px; }
.nexus-mark-footer { width: 20px; height: 20px; vertical-align: middle; }
.nexus-wordmark { font-weight: 800; letter-spacing: -0.01em; }
.nexus-wordmark .accent { color: #f97316; }

/* The product motto ("Where schools connect.") gets its own elegant italic
   serif font (Playfair Display, loaded in header.php's <head>) so it reads
   like a proper tagline instead of blending into ordinary muted text. */
.motto {
    font-family: "Playfair Display", Georgia, serif;
    font-style: italic;
    letter-spacing: 0.01em;
}

.platform-support-line {
    text-align: center;
    font-size: 0.85rem;
    color: #cbd5e1;
    background: #172554; /* a shade darker than the footer just below it, so the two bands read as one cohesive dark section rather than a jarring light-to-dark jump */
    padding: 0.6rem 1rem;
    margin: 0;
}
.platform-support-line a { color: #fdba74; text-decoration: none; font-weight: 600; }

.avatar { border-radius: 50%; object-fit: cover; display: inline-block; vertical-align: middle; flex-shrink: 0; }
.avatar-fallback { display: inline-flex; align-items: center; justify-content: center; background: var(--primary); color: #fff; font-weight: 700; font-size: 0.75rem; }
.avatar-large { width: 120px; height: 120px; font-size: 2rem; }
.logo-preview { max-height: 80px; max-width: 240px; object-fit: contain; border: 1px solid var(--border); border-radius: 8px; padding: 0.5rem; background: #fff; }

.container { max-width: 1100px; margin: 0 auto; padding: 1.5rem; }

/* ---------------------------------------------------------------------
   Floats the page's own content in a translucent "glass" panel on top of
   the fixed background photo, instead of the photo showing straight
   through to the page content (which would make tables/forms hard to
   read). Scoped to `.app-shell .container` specifically -- NOT plain
   `.container` -- so pages shown before login (like portal.php), which
   also use the .container class but sit outside .app-shell, are
   completely unaffected and keep their normal plain look.
   ------------------------------------------------------------------- */
.app-shell .container {
    background: rgba(255, 255, 255, 0.85);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-radius: 12px;
    margin-top: 1.5rem;
    margin-bottom: 1.5rem;
    box-shadow: 0 4px 24px rgba(15,23,42,0.10);
}

h1 { margin-top: 0; }
.muted { color: var(--muted); }

.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; flex-wrap: wrap; gap: 0.5rem; }

.btn {
    display: inline-block;
    padding: 0.5rem 1rem;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: #fff;
    color: var(--text);
    text-decoration: none;
    cursor: pointer;
    font-size: 0.95rem;
}
.btn-primary { background: var(--primary); color: #fff; border-color: var(--primary); }
.btn-primary:hover { background: var(--primary-dark); }
.text-danger { color: var(--danger); }

.alert { padding: 0.75rem 1rem; border-radius: 6px; margin-bottom: 1rem; font-size: 0.95rem; }
.alert-success { background: #dcfce7; color: #166534; }
.alert-error { background: #fee2e2; color: #991b1b; }

.data-table { width: 100%; border-collapse: collapse; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
.data-table th, .data-table td { padding: 0.65rem 0.9rem; border-bottom: 1px solid var(--border); text-align: left; font-size: 0.92rem; }
.data-table th { background: #f1f5f9; font-weight: 600; }
.data-table tr:hover td { background: #f8fafc; }

.search-form { margin-bottom: 1rem; display: flex; gap: 0.5rem; }
.search-form input, .search-form select { padding: 0.45rem 0.6rem; border: 1px solid var(--border); border-radius: 6px; }

.form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; max-width: 700px; background: #fff; padding: 1.5rem; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
.form-grid label { display: flex; flex-direction: column; font-size: 0.9rem; gap: 0.3rem; color: var(--muted); }
.form-grid input, .form-grid select { padding: 0.5rem; border: 1px solid var(--border); border-radius: 6px; font-size: 0.95rem; color: var(--text); }
.form-actions { grid-column: 1 / -1; display: flex; gap: 0.75rem; margin-top: 0.5rem; }

.auth-box {
    max-width: 380px; width: 100%; margin: 4rem auto; background: #fff; padding: 2.25rem 2rem 2rem;
    border-radius: 14px; box-shadow: 0 4px 24px rgba(15,23,42,0.08);
    border-top: 4px solid var(--primary);
}
.auth-box form { display: flex; flex-direction: column; gap: 0.5rem; }
.auth-box label { font-size: 0.9rem; color: var(--muted); margin-top: 0.5rem; }
.auth-box input { padding: 0.6rem; border: 1px solid var(--border); border-radius: 6px; }
.auth-box button { margin-top: 1rem; }
.hint { font-size: 0.8rem; color: var(--muted); margin-top: 1rem; }

/* ---------------------------------------------------------------------
   Login page split-screen: an illustration on one side, the sign-in card
   on the other. login.php sets $fullBleedPage = true before requiring
   header.php so <main> has no max-width here -- see includes/header.php --
   letting this div genuinely span the full browser width edge to edge.
   ------------------------------------------------------------------- */
.auth-split { display: flex; min-height: 100vh; }
.auth-illustration-panel {
    flex: 1.1;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden;
}
.auth-illustration-panel img { width: 100%; height: 100%; object-fit: cover; display: block; }
.auth-form-panel {
    flex: 1; min-width: 340px;
    display: flex; align-items: center; justify-content: center;
    padding: 2rem 1.5rem;
    background: #fff;
    /* Without this, a tall page (like the multi-field signup form) can get
       vertically centered in a way that clips its own top off-screen with
       no way to scroll up to it -- a well-known flexbox quirk. Adding
       scroll here means: center it when it fits, but scroll normally the
       moment it doesn't. */
    overflow-y: auto;
}
/* Inside this panel the flex centering above already does the job, so the
   card's own default margin (used when it's NOT in a split-screen, like on
   first_time_setup.php and signup.php) would just add unwanted extra space. */
.auth-form-panel .auth-box { margin: 0; }

/* Below this width there's no room for both halves side by side, so the
   illustration is dropped entirely and the sign-in card just takes the
   full screen -- same idea as the sidebar collapsing on mobile. */
@media (max-width: 860px) {
    .auth-illustration-panel { display: none; }
    .auth-split { min-height: auto; }
    .auth-form-panel { min-width: 0; padding: 3rem 1.5rem; }
}

.auth-back-link {
    display: inline-flex; align-items: center; gap: 0.35rem;
    font-size: 0.8rem; color: var(--muted); text-decoration: none;
    margin-bottom: 1.25rem; font-weight: 600;
}
.auth-back-link:hover { color: var(--primary); }

.auth-hint-box {
    margin-top: 1.25rem;
    padding: 0.85rem 1rem;
    background: #eff6ff;
    border: 1px solid #bfdbfe;
    border-radius: 10px;
    font-size: 0.85rem;
    color: #1e3a8a;
    text-align: left;
}
.auth-hint-box a { color: #1d4ed8; font-weight: 700; }

.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 1rem; margin-top: 1.5rem; }
.stat-card { background: #fff; padding: 1.25rem; border-radius: 8px; text-align: center; box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
.stat-value { font-size: 1.8rem; font-weight: 700; color: var(--primary); }
.stat-label { color: var(--muted); font-size: 0.85rem; margin-top: 0.25rem; }

.detail-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.5rem 2rem; background: #fff; padding: 1.25rem; border-radius: 8px; margin-bottom: 1.5rem; }

/* A dark navy matching the login illustration's gradient (see
   assets/img/login-illustration.svg) -- ties the very bottom of every page
   back to the same brand color instead of fading into plain white/gray. */
.site-footer { text-align: center; color: #cbd5e1; font-size: 0.85rem; padding: 1.5rem; background: #1e3a8a; }
.footer-brand { display: inline-flex; align-items: center; gap: 0.4rem; margin-bottom: 0.4rem; color: #fff; font-size: 0.9rem; }
/* A soft glow behind the logo mark so its own blue tones don't disappear
   into the equally-blue footer background it now sits on. */
.nexus-mark-footer { background: rgba(255,255,255,0.18); border-radius: 50%; padding: 3px; box-sizing: content-box; }

/* ---------------------------------------------------------------------
   Welcome/portal-choice page (portal.php) background: this page is shown
   BEFORE anyone signs in, so it has no school to pull a photo from (that's
   what includes/header.php's --portal-bg does for logged-in pages, further
   up in this file) -- this is a fixed, hand-made gradient instead, built
   only from the app's own brand colors (var(--primary) blue + the orange
   accent used in the "Nexus SMS" wordmark), no external image. Opted into
   only by portal.php, via $bodyClass = 'portal-page'; in that file.
   ------------------------------------------------------------------- */
.portal-page {
    background:
        radial-gradient(circle at 15% 15%, rgba(37,99,235,0.16), transparent 45%),
        radial-gradient(circle at 85% 25%, rgba(249,115,22,0.14), transparent 40%),
        radial-gradient(circle at 50% 90%, rgba(37,99,235,0.12), transparent 50%),
        linear-gradient(160deg, #eef2ff 0%, var(--bg) 55%, #fff7ed 100%);
    background-attachment: fixed; /* the blobs stay put behind the card even if the page scrolls */
    min-height: 100vh;
}

.portal-wrap {
    max-width: 760px; margin: 3rem auto; text-align: center;
    background: #fff; border-radius: 16px; padding: 2.5rem 2rem 2.25rem;
    box-shadow: 0 4px 24px rgba(15,23,42,0.08);
    border-top: 4px solid var(--primary);
}
.portal-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; margin-top: 2rem; }
.portal-card {
    display: block;
    background: #fff;
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 2rem 1rem;
    text-decoration: none;
    color: var(--text);
    box-shadow: 0 1px 3px rgba(0,0,0,0.06);
    transition: transform 0.1s, box-shadow 0.1s;
}
.portal-card:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.1); border-color: var(--primary); }
.portal-icon { font-size: 2.2rem; margin-bottom: 0.5rem; }
.portal-title { font-weight: 700; margin-bottom: 0.25rem; }
.portal-desc { font-size: 0.85rem; color: var(--muted); }

.portal-secondary {
    margin-top: 2.25rem;
    padding-top: 1.75rem;
    border-top: 1px solid var(--border);
    display: flex;
    justify-content: center;
    gap: 3rem;
    flex-wrap: wrap;
}
.portal-secondary-group { display: flex; flex-direction: column; align-items: center; gap: 0.65rem; }
.portal-secondary-label { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); font-weight: 700; }
.pill-row { display: flex; gap: 0.6rem; flex-wrap: wrap; justify-content: center; }
.pill-link {
    display: inline-flex; align-items: center; gap: 0.4rem;
    padding: 0.5rem 1.1rem; border-radius: 999px;
    background: #f1f5f9; color: var(--text);
    text-decoration: none; font-size: 0.85rem; font-weight: 600;
    border: 1px solid transparent;
    transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.pill-link:hover { background: #e0e7ff; border-color: var(--primary); transform: translateY(-1px); }

.portal-footer-link { margin-top: 1.75rem; }
.portal-footer-link a { font-size: 0.78rem; color: var(--muted); text-decoration: none; }
.portal-footer-link a:hover { color: var(--primary); text-decoration: underline; }

.report-box { background: #fff; padding: 1.5rem; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); margin-bottom: 1.5rem; }
.report-header { display: flex; justify-content: space-between; align-items: flex-start; border-bottom: 2px solid var(--border); padding-bottom: 1rem; margin-bottom: 1rem; }
.badge { display: inline-block; padding: 0.15rem 0.55rem; border-radius: 999px; font-size: 0.78rem; font-weight: 600; }
.badge-paid { background: #dcfce7; color: #166534; }
.badge-partial { background: #fef9c3; color: #854d0e; }
.badge-unpaid { background: #fee2e2; color: #991b1b; }
.badge-overdue { background: #fee2e2; color: #991b1b; }
.badge-voided { background: #e5e7eb; color: #374151; }

.announcement-list { display: flex; flex-direction: column; gap: 1rem; }
.announcement-card { background: #fff; padding: 1.1rem 1.3rem; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
.announcement-card-header { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.announcement-card-header h3 { margin: 0 0 0.25rem; }
.announcement-meta { margin: 0 0 0.6rem; font-size: 0.82rem; }
.announcement-body { margin: 0; white-space: pre-wrap; }

.dashboard-widget { background: #fff; padding: 1.25rem 1.4rem; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); margin-top: 1.5rem; }
.dashboard-widget-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem; }
.dashboard-widget-header h2 { margin: 0; font-size: 1.1rem; }
.dashboard-widget-header a { font-size: 0.85rem; color: var(--primary); text-decoration: none; }
.dashboard-widget-item { padding: 0.4rem 0; border-top: 1px solid var(--border); font-size: 0.92rem; }
.dashboard-widget-item:first-of-type { border-top: none; }

@media (max-width: 640px) {
    .form-grid, .detail-grid { grid-template-columns: 1fr; }
    .portal-grid { grid-template-columns: 1fr; }
}

/* Below this width, the sidebar is treated as a slide-in panel rather than
   a permanent column: it's pinned off-screen to the left (translateX
   -100%) until JS (assets/js/app.js) adds the "sidebar-open" class, which
   slides it into view and dims the rest of the page behind it. */
@media (max-width: 900px) {
    .sidebar {
        position: fixed;
        left: 0; top: 0;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        box-shadow: 2px 0 12px rgba(0,0,0,0.15);
    }
    .sidebar.sidebar-open { transform: translateX(0); }
    .sidebar-backdrop.sidebar-open { display: block; }
    .sidebar-toggle { display: inline-block; }
}

@media print {
    .sidebar, .topbar, .sidebar-backdrop, .search-form, .page-header .btn, .no-print, .site-footer { display: none !important; }
    .app-shell { display: block; background: none !important; }
    .main-area { display: block; }
    body { background: #fff; }
    .report-box { box-shadow: none; border: none; padding: 0; }
    .container {
        max-width: 100%; padding: 0; margin: 0;
        background: none !important; backdrop-filter: none !important;
        box-shadow: none !important; border-radius: 0 !important;
    }
}
