/* ════════════════════════════════════════════════════════════════════════════
   LIQUID GLASS — the app's visual identity, native app only
   ────────────────────────────────────────────────────────────────────────────
   Every screen in the app shares one iridescent field with frosted surfaces
   floating on it. Loaded by every page (portals, login, registration) and gated
   on html.iris-glass, which college-brand.js sets at parse time from <head> —
   before <body> exists, so the first paint is already glass with no flash of the
   flat theme. Web visitors never get the class and are completely untouched.

   The leverage: every page here is already token-driven (`background: var(--card-bg)`
   or `var(--card)`, `var(--border)`, `var(--shadow)`, `var(--radius)`), so
   re-pointing those tokens converts whole pages at once. Only the blur, the field,
   and the specular rim are genuinely new. Selectors are all .iris-glass-prefixed,
   so they out-specify each page's own rules regardless of load order.
   ════════════════════════════════════════════════════════════════════════════ */

.iris-glass { background-color: #AFC3F2; }              /* canvas fallback */

/* ── The field ───────────────────────────────────────────────────────────────
   A fixed pseudo-layer rather than background-attachment:fixed — that combination
   janks badly in a WebView next to backdrop-filter, whereas this is one cheap
   composited layer that never repaints on scroll. */
.iris-glass body {
  background: none !important;
  min-height: 100vh;
}
.iris-glass body::before {
  content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-color: #AFC3F2;
  background-image:
    radial-gradient(at 14% 12%, #6EC3F7 0px, transparent 55%),
    radial-gradient(at 88%  6%, #C9A0F0 0px, transparent 55%),
    radial-gradient(at  6% 58%, #F49AC8 0px, transparent 52%),
    radial-gradient(at 94% 46%, #8FA8F5 0px, transparent 55%),
    radial-gradient(at 46% 86%, #F7B7D3 0px, transparent 55%),
    radial-gradient(at 82% 96%, #7CC6F5 0px, transparent 52%);
}

/* ── Shared token re-point ───────────────────────────────────────────────────
   --card-bg is the portals' surface token; --card is the registration forms'.
   Setting both here converts every page that reads either. */
.iris-glass body {
  --card-bg: rgba(255, 255, 255, 0.42);
  --card:    rgba(255, 255, 255, 0.42);
  --border:  rgba(255, 255, 255, 0.58);
  --shadow:  0 8px 30px rgba(30, 41, 90, 0.10);
  --radius:  18px;
  --text:       #212838;    /* darkened: now sits on colour, not on near-white */
  --text-light: #55607A;
  --bg: transparent;
  color: var(--text);
}

/* ── Frosted surfaces ────────────────────────────────────────────────────────
   Blur goes ONLY on top-level surfaces. Nesting backdrop-filter inside
   backdrop-filter compounds the cost and muddies the result, so inner elements
   (table rows, list items, form groups) take a translucent fill and read the blur
   from the surface they sit in. */
.iris-glass .card,
.iris-glass .stat-card,
.iris-glass .top-header,
.iris-glass .sidebar,
.iris-glass .modal-content,
.iris-glass .bottom-nav,
.iris-glass .iris-sheet,
.iris-glass .login-card,
.iris-glass .login-modal,
.iris-glass .feature-pill {
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  backdrop-filter: blur(16px) saturate(180%);
  background: var(--card-bg);
  border: 1px solid var(--border);
  box-shadow: 0 8px 30px rgba(30, 41, 90, 0.10),
              inset 0 1px 0 rgba(255, 255, 255, 0.75);   /* lit top edge */
  border-radius: var(--radius);
}

/* ── SIGNATURE: the light catching the rim ───────────────────────────────────
   Real glass doesn't glow evenly; it picks up a bright glint where the edge
   turns. Corner-confined and sat behind the content, so it never washes text. */
.iris-glass .card,
.iris-glass .stat-card,
.iris-glass .login-card { position: relative; }
.iris-glass .card::after,
.iris-glass .stat-card::after,
.iris-glass .login-card::after {
  content: ''; position: absolute; inset: 0; z-index: 0;
  border-radius: inherit; pointer-events: none;
  background:
    radial-gradient(90px 44px at 5% -2%,   rgba(255,255,255,0.90), transparent 72%),
    radial-gradient(70px 36px at 99% 101%, rgba(255,255,255,0.65), transparent 72%);
}
.iris-glass .card > *,
.iris-glass .stat-card > *,
.iris-glass .login-card > * { position: relative; z-index: 1; }

/* Edge-to-edge safe area. targetSdk 36 (Android 16) enforces edge-to-edge on
   Android 15+, so the WebView draws under the status bar — the sticky top header
   would otherwise sit beneath the clock/battery. Pad it down by the inset. App-only
   (this file is gated on .iris-glass), so browser/web is untouched. */
.iris-glass .top-header {
  padding-top: calc(14px + env(safe-area-inset-top, 0px));
}

/* ── Top-right cluster (profile chip + bell) ─────────────────────────────────
   .profile-chip hardcodes #F0F4F4 rather than reading --card-bg, so the token
   re-point above skipped it and it stayed an opaque slab in a frosted header.
   Both sit INSIDE .top-header, which is already blurred — so they take a
   translucent fill and read that blur, rather than stacking a second one.
   The avatar and the notification badge stay solid: they're accents. */
.iris-glass .profile-chip {
  background: rgba(255, 255, 255, 0.34);
  border: 1px solid var(--border);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.iris-glass .notif-btn {
  background: rgba(255, 255, 255, 0.34);
  border: 1px solid var(--border);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.iris-glass .notif-btn i { color: var(--text); }

/* ── Modal scrims ────────────────────────────────────────────────────────────
   Same story as the More sheet: the scrim was the problem, not the panel. The
   login modal is already glass (white @42% + blur 16) — but floating it on
   ink @50% left it nothing to show through but black, so it read as a flat white
   slab. Both scrims drop to a hint of shade, and their blur goes: the panel does
   its own frosting, and stacking a second backdrop-filter underneath only costs
   frames and muddies what shows through. */
.iris-glass .modal-overlay,          /* login page */
.iris-glass .modal {                 /* portals (shared.css) */
  background: rgba(15, 23, 42, 0.12);
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
/* Near-opaque #F9FAFB @80% reads as a solid bar across the top of a frosted panel. */
.iris-glass .modal-header {
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.22) 0%, transparent 100%);
}

/* ── The More sheet: see the page you came from ──────────────────────────────
   The sheet opens over whatever you were reading, and the point of a half sheet
   is that you never lose your place. The heavy scrim (ink @42%) was doing more to
   hide the page than the sheet itself, so it drops to a hint of shade — enough to
   push the page back a layer, not enough to blank it. The sheet's own fill thins
   too; the blur behind it is what keeps the labels legible, so that stays. The
   tiles keep a stronger fill than the sheet, because their text has to carry over
   whatever colour happens to sit behind them. */
.iris-glass .iris-sheet-backdrop {
  background: rgba(15, 23, 42, 0.12);
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.iris-glass .iris-sheet { background: rgba(255, 255, 255, 0.26); }
.iris-glass .iris-sheet-item { background: rgba(255, 255, 255, 0.40); }

/* ── Role switcher dropdown ──────────────────────────────────────────────────
   A popover, not a panel: it floats free over live page content, so it can't take
   the card fill (42%) the way surfaces sitting on the field do — the dashboard read
   straight through it. It needs a heavier fill AND its own blur, because there's no
   blurred parent behind it to borrow from once it extends past the header. */
.iris-glass #roleSwitcherDropdown {
  background: rgba(255, 255, 255, 0.78);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  backdrop-filter: blur(18px) saturate(180%);
  border: 1px solid var(--border);
  box-shadow: 0 10px 34px rgba(30, 41, 90, 0.22);
}
.iris-glass .role-switch-item { color: var(--text); }
.iris-glass .role-switch-item:active { background: rgba(255, 255, 255, 0.55); }

/* ── Inner surfaces: translucent only, never a second blur ───────────────── */
.iris-glass .card-header    { background: rgba(255, 255, 255, 0.18); border-bottom-color: var(--border); }
.iris-glass .data-table tr  { background: rgba(255, 255, 255, 0.30); border-color: rgba(255,255,255,0.5); }
.iris-glass input,
.iris-glass select,
.iris-glass textarea {
  background: rgba(255, 255, 255, 0.46); border-color: var(--border); color: var(--text);
}
.iris-glass .btn-outline {
  background: rgba(255, 255, 255, 0.38); border-color: var(--border); color: var(--text);
}

/* ── Accents stay opaque ─────────────────────────────────────────────────────
   A status badge or a primary action has to read at a glance; frosting them
   would cost the very contrast they exist for. The colour tiles are solid for
   the same reason. */
.iris-glass .btn-primary,
.iris-glass .badge-pill,
.iris-glass .bn-item.active { -webkit-backdrop-filter: none; backdrop-filter: none; }

/* ── Scroll bars ─────────────────────────────────────────────────────────────
   Matches the picker. The WebView's default overlay bar is transient and all but
   invisible against the field, so long lists gave no hint they continued below.
   Covers the viewport and the inner scrollers (the More sheet's grid, scrolling
   tab strips, any overflow area). Stays an overlay, so it costs no layout width
   and shifts nothing. */
.iris-glass { scrollbar-width: thin; scrollbar-color: rgba(33, 40, 56, 0.32) transparent; }
.iris-glass::-webkit-scrollbar,
.iris-glass body::-webkit-scrollbar,
.iris-glass .iris-sheet-body::-webkit-scrollbar,
.iris-glass .tabs::-webkit-scrollbar,
.iris-glass .table-wrap::-webkit-scrollbar,
.iris-glass .modal-content::-webkit-scrollbar { width: 6px; height: 6px; }

.iris-glass::-webkit-scrollbar-track,
.iris-glass body::-webkit-scrollbar-track,
.iris-glass .iris-sheet-body::-webkit-scrollbar-track,
.iris-glass .tabs::-webkit-scrollbar-track,
.iris-glass .table-wrap::-webkit-scrollbar-track,
.iris-glass .modal-content::-webkit-scrollbar-track { background: transparent; }

.iris-glass::-webkit-scrollbar-thumb,
.iris-glass body::-webkit-scrollbar-thumb,
.iris-glass .iris-sheet-body::-webkit-scrollbar-thumb,
.iris-glass .tabs::-webkit-scrollbar-thumb,
.iris-glass .table-wrap::-webkit-scrollbar-thumb,
.iris-glass .modal-content::-webkit-scrollbar-thumb {
  background: rgba(33, 40, 56, 0.30);
  border-radius: 99px;
}
.iris-glass::-webkit-scrollbar-thumb:active,
.iris-glass body::-webkit-scrollbar-thumb:active,
.iris-glass .iris-sheet-body::-webkit-scrollbar-thumb:active {
  background: rgba(33, 40, 56, 0.48);
}

/* ── Login page ──────────────────────────────────────────────────────────────
   Its own design system (Playfair/DM Sans, split panel) rather than the portal
   tokens, so its surfaces are named here. The left panel carries the college's
   campus photo — left alone, since that's the college's own identity, not chrome
   for us to frost over. */
.iris-glass .right-panel { background: transparent; }
.iris-glass .right-footer { background: transparent; }
.iris-glass .login-cards { gap: 14px; }
/* The footer greys were picked for a white page; on the field they all but vanish. */
.iris-glass .right-footer p { color: rgba(33, 40, 56, 0.66); }
.iris-glass .copyright { color: rgba(33, 40, 56, 0.50); }

/* ── Registration forms ──────────────────────────────────────────────────────
   Token-driven like the portals (--card / --border / --shadow / --radius), so
   the re-point above already converts them; these are the leftovers that hardcode. */
.iris-glass .container { background: transparent; }
.iris-glass .section-title { border-bottom-color: var(--border); }
.iris-glass .doc-item { background: rgba(255, 255, 255, 0.30); border-color: var(--border); }
.iris-glass .checkbox-wrapper { background: rgba(255, 255, 255, 0.26); }
