@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&family=JetBrains+Mono:wght@500;600&display=swap');

:root{
  /* --- "TFAdmin Design System" foundations — copied exactly from the
     Claude Design reference (design_handoff_admin_shell), not approximated. --- */
  --surface-0:#f7f7f5; --surface-1:#ffffff; --surface-2:#fbfbf9;
  --text-primary:#16181d; --text-secondary:#5c6068; --text-muted:#93979f;
  --border:#e7e7e3; --border-strong:#d2d2cc;
  --accent:#1b5fa8; --accent-bg:#eaf2fb;
  --danger:#a32020; --danger-bg:#fdeded;
  --success:#0d6b52; --success-bg:#e6f6f0;
  --warning:#8a5308; --warning-bg:#fdf2e0;
  --info:#5c6068; --info-bg:#f0f0ee;
  --normal:#2E9E4F; --utility:#E07B1A;
  --radius:10px; --radius-lg:14px; --radius-pill:999px;
  --shadow-sm:0 1px 2px rgba(20,20,25,.05);
  --shadow-md:0 2px 10px rgba(20,20,25,.06);

  /* --- Sidebar "Navy" tone (the reference's default of its 3 tweakable
     sidebar tones) — kept as its own token namespace, separate from the
     login screen's --tf-navy-* tokens below, so restyling the sidebar can
     never change the login screen's look. --- */
  --tf-side-bg:#0b1220; --tf-side-active:#132038; --tf-side-border:#22375c;
  --tf-side-text:#e4e5ea; --tf-side-muted:#8b8e99;

  /* --- Login screen tokens ONLY — do not repoint sidebar/nav rules at
     these; add to --tf-side-* above instead. --- */
  --tf-navy-950:#15161a; --tf-navy-900:#1c1e23; --tf-navy-800:#25272e;
  --tf-navy-border:#34363f; --tf-navy-text:#e4e5ea; --tf-navy-muted:#8b8e99;
  --tf-iri:#0e7a86; --tf-cri:#E07B1A;

  --font-display:'Manrope',sans-serif;
  --font-body:'Manrope',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
}
html[data-theme="dark"]{
  --surface-0:#0a0f1e; --surface-1:#141b2c; --surface-2:#1a2338;
  --text-primary:#e7ecf6; --text-secondary:#a3aec4; --text-muted:#77839c;
  --border:#242f49; --border-strong:#34405e;
  --accent:#7aa8e0; --accent-bg:#182746;
  --danger:#e79a9a; --danger-bg:#3a1e1e;
  --success:#7ecfae; --success-bg:#123227;
  --warning:#e3bd82; --warning-bg:#392a10;
  --info:#a3aec4; --info-bg:#1c2438;
  --shadow-sm:0 1px 2px rgba(0,0,0,.3);
  --shadow-md:0 2px 12px rgba(0,0,0,.35);
  /* Dark theme's sidebar stays a frosted glass panel over the page halo
     (unrelated to the Navy/Onyx/Slate tone, which only swaps the LIGHT
     theme's solid sidebar fill per the reference) — --tf-side-active/
     border stay constant across themes. */
  --tf-side-bg:rgba(15,23,48,.55);
  /* Login screen tokens ONLY — frozen, do not reuse for sidebar/nav. */
  --tf-navy-950:#070b16; --tf-navy-900:#0f1730; --tf-navy-800:#182746;
  --tf-navy-border:#2a3a5c; --tf-navy-text:#e4e5ea; --tf-navy-muted:#8b8e99;
}

*{ box-sizing:border-box; }
html,body{ height:100%; }
body{ margin:0; background:var(--surface-0); color:var(--text-primary);
  font-family:var(--font-body); -webkit-font-smoothing:antialiased; letter-spacing:-0.005em; }

/* Dark mode only: the same halo glow as the login screen, carried through
   into the app so it doesn't feel like a different product once you sign in. */
html[data-theme="dark"] body{
  background:radial-gradient(ellipse 1400px 900px at 55% -10%, #14213f 0%, #0a0f1e 50%, #05070c 100%);
  background-attachment:fixed;
}

/* Themed scrollbars — the OS-default scrollbar (light gray track/thumb)
   reads as a bug against the dark theme's near-black surfaces, so it's
   restyled to match the surface tokens in both themes rather than left to
   the browser default. */
*{ scrollbar-width:thin; scrollbar-color:var(--border-strong) transparent; }
*::-webkit-scrollbar{ width:10px; height:10px; }
*::-webkit-scrollbar-track{ background:transparent; }
*::-webkit-scrollbar-thumb{ background-color:var(--border-strong); border-radius:999px; }
*::-webkit-scrollbar-thumb:hover{ background-color:var(--text-muted); }
*::-webkit-scrollbar-corner{ background:transparent; }
/* The page-level scrollbar specifically sits over body's
   background-attachment:fixed gradient in dark mode — a transparent track
   doesn't reliably composite over that (the OS paints scrollbars in their
   own layer, and a "what's behind me" lookup against a fixed-attachment
   gradient is exactly the case that tends to fall back to an opaque
   default instead), showing up as a mismatched strip the full height of
   the track. Nested scroll containers (the TOC, dropdowns) sit on
   ordinary solid surface colors and don't have this problem, so only the
   page-level (html) scrollbar gets an explicit solid match here. */
html[data-theme="dark"]{ scrollbar-color:var(--border-strong) #05070c; }
html[data-theme="dark"]::-webkit-scrollbar-track{ background:#05070c; }

button, select, input{ font-family:inherit; }
a{ color:inherit; }

/* ============ App shell ============ */
.app{ display:flex; min-height:100vh; }

/* ---------- Sidebar (Navy tone, per the design reference) ---------- */
.sidebar{ width:264px; flex:0 0 264px; background:var(--tf-side-bg);
  color:var(--tf-side-text); display:flex; flex-direction:column;
  border-right:1px solid var(--tf-side-border); position:sticky; top:0; height:100vh; z-index:30; }

/* Dark mode: glass panel over the body's halo instead of a flat black
   slab — the glow shows through rather than stopping at the sidebar edge. */
html[data-theme="dark"] .sidebar{
  background:var(--tf-side-bg); backdrop-filter:blur(20px); -webkit-backdrop-filter:blur(20px);
  border-right:1px solid rgba(255,255,255,.06);
}

.brand{ display:flex; align-items:center; gap:10px; padding:24px 18px 20px; }
.brand-logo{ height:42px; width:auto; display:block; }

.sidebar-divider{ height:1px; background:var(--tf-side-border); margin:2px 18px 14px; }

/* Person / identity strip (the sketch's boxed name card) */
.identity{ margin:0 14px 14px; padding:12px 12px 12px 13px; border:1px solid var(--tf-side-border);
  border-left:3px solid var(--accent); border-radius:8px; background:var(--tf-side-active); }
.identity-clickable{ cursor:pointer; transition:background .12s; }
.identity-clickable:hover{ background:var(--tf-side-active); }
.identity-row{ display:flex; align-items:center; gap:10px; }
.identity-avatar{ width:34px; height:34px; border-radius:50%; background:var(--accent);
  display:flex; align-items:center; justify-content:center;
  font-family:var(--font-mono); font-size:13px; font-weight:600; color:#fff; flex:0 0 auto; }
.identity-name{ font-size:13px; font-weight:600; color:#fff; line-height:1.25; }
.identity-course{ font-size:10.5px; color:var(--tf-side-muted); margin-top:1px; }
.identity-badge{ margin-top:9px; display:flex; flex-wrap:wrap; align-items:center; gap:5px; }

/* Flight-strip style nav */
.nav{ flex:1; overflow-y:auto; padding:2px 14px 10px; display:flex; flex-direction:column; gap:6px; }
.nav-section-label{ font-size:9.5px; text-transform:uppercase; letter-spacing:0.09em; color:var(--tf-side-muted);
  margin:12px 2px 2px; }
/* Nav items: icon + label, clean and minimal (no acronym codes) */
.nav-strip{ position:relative; display:flex; align-items:center; gap:11px;
  padding:10px 12px; border-radius:9px; border:1px solid transparent; cursor:pointer;
  background:transparent; text-align:left; width:100%; transition:background .12s, border-color .12s; }
.nav-strip:hover{ background:var(--tf-side-active); }
.nav-strip.active{ background:var(--tf-side-active); border-color:transparent; }
.nav-strip-icon{ flex:0 0 auto; width:19px; height:19px; display:flex; align-items:center; justify-content:center;
  color:var(--tf-side-muted); transition:color .12s; }
.nav-strip-icon svg{ width:18px; height:18px; }
.nav-strip.active .nav-strip-icon{ color:var(--accent); }
.nav-strip-label{ font-size:13.5px; font-weight:500; color:var(--tf-side-muted); flex:1; }
.nav-strip.active .nav-strip-label{ color:#fff; font-weight:600; }
.nav-strip-count{ font-family:var(--font-mono); font-size:10.5px; font-weight:600; color:#fff;
  background:var(--danger); padding:1px 6px; border-radius:9px; min-width:16px; text-align:center; flex:0 0 auto; }

/* Nav groups (e.g. "Course", "Training") — expandable parents with sub-items */
.nav-group-chevron{ flex:0 0 auto; font-size:13px; color:var(--tf-side-muted); transition:transform .15s; }
.nav-group-chevron.open{ transform:rotate(90deg); }
.nav-group-children{ max-height:0; overflow:hidden; display:flex; flex-direction:column; gap:6px;
  transition:max-height .18s ease; }
.nav-group-children.open{ padding-top:6px; }
.nav-strip-sub{ padding-left:38px; }
.nav-strip-sub .nav-strip-icon{ width:16px; height:16px; }
.nav-strip-sub .nav-strip-icon svg{ width:15px; height:15px; }
.nav-strip-sub .nav-strip-label{ font-size:12.5px; }

.sidebar.collapsed .nav-group-chevron{ display:none; }
.sidebar.collapsed .nav-group-children{ display:none; }

.sidebar-footer{ padding:12px 14px 18px; border-top:1px solid var(--tf-side-border); }
.logout-btn{ width:100%; display:flex; align-items:center; justify-content:space-between; gap:8px;
  background:transparent; border:1px solid transparent; color:var(--tf-side-muted);
  padding:9px 12px; border-radius:9px; font-size:14px; font-weight:500; cursor:pointer; }
.logout-btn:hover{ background:var(--tf-side-active); color:var(--tf-side-text); }

/* ---------- Main column ---------- */
.main{ flex:1; min-width:0; display:flex; flex-direction:column; }

/* Transparent, title-less topbar — icons only, right-aligned, per the
   design reference (no eyebrow/title block, no background/border). */
/* background is the page bg, not literally transparent — sticky content
   (e.g. Wiki's long-form text) scrolls directly underneath this bar, and a
   truly transparent background let that text show through as a ghosting
   artifact right at the top edge. Matching the page bg keeps the "no
   visible bar" look in the normal case (nothing to scroll under it yet)
   while actually occluding content once there is. */
.topbar{ position:sticky; top:0; z-index:20; background:var(--surface-0);
  padding:16px 28px; display:flex; align-items:center; justify-content:flex-end; gap:8px; flex-wrap:wrap; }
.topbar-right{ display:flex; align-items:center; gap:8px; }
/* System-wide search — centered in whatever space is left of the icon
   cluster, so it reads as its own thing rather than crowding the icons. */
.topbar-search-wrap{ flex:1; display:flex; justify-content:center; min-width:0; }
.global-search{ position:relative; width:100%; max-width:440px; }
.global-search-bar{ display:flex; align-items:center; gap:8px; width:100%; background:var(--surface-1);
  border:1px solid var(--border); border-radius:999px; padding:9px 16px; box-shadow:var(--shadow-sm); }
.global-search-bar svg{ flex:0 0 auto; color:var(--text-muted); }
.global-search-bar input{ flex:1; min-width:0; border:none; background:none; font:inherit; font-size:13.5px;
  color:var(--text-primary); outline:none; }
.global-search-results{ position:absolute; top:calc(100% + 6px); left:0; right:0; max-height:420px; overflow-y:auto;
  background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius-lg); box-shadow:var(--shadow-md);
  padding:8px; z-index:30; text-align:left; }
.global-search-group + .global-search-group{ margin-top:6px; padding-top:6px; border-top:1px solid var(--border); }
.global-search-group-label{ font-size:10.5px; text-transform:uppercase; letter-spacing:.06em; color:var(--text-muted);
  font-weight:700; margin:4px 8px; }
.global-search-item{ display:flex; flex-direction:column; align-items:flex-start; gap:1px; width:100%;
  padding:7px 10px; border-radius:9px; border:none; background:none; cursor:pointer; text-align:left; }
.global-search-item:hover{ background:var(--surface-2); }
.global-search-item-title{ font-size:13px; font-weight:600; color:var(--text-primary); }
.global-search-item-sub{ font-size:11px; color:var(--text-muted); }
.global-search-empty{ padding:14px; text-align:center; font-size:12.5px; color:var(--text-muted); }
@media (max-width: 860px){ .topbar-search-wrap{ display:none; } }
#topbar-role-badge-wrap{ display:flex; align-items:center; gap:5px; }

.icon-btn{ background:var(--surface-1); border:1px solid var(--border); color:var(--text-secondary);
  width:36px; height:36px; border-radius:8px; display:flex; align-items:center; justify-content:center; cursor:pointer; font-size:15px; }
.icon-btn:hover{ border-color:var(--border-strong); color:var(--text-primary); }
.icon-btn.active{ background:var(--accent-bg); border-color:var(--accent); color:var(--accent); }
.icon-btn.sm{ width:22px; height:22px; border-radius:6px; font-size:13px; flex:0 0 auto; }

/* ============ Notification bell (topbar) ============ */
.notif-bell-wrap{ position:relative; }
.notif-bell-badge{ position:absolute; top:-4px; right:-4px; min-width:16px; height:16px; padding:0 3px;
  border-radius:9px; background:var(--danger); color:#fff; font-size:9.5px; font-weight:700;
  font-family:var(--font-mono); display:flex; align-items:center; justify-content:center; line-height:1; }
.notif-dropdown{ position:absolute; top:calc(100% + 8px); right:0; width:320px; max-height:420px; overflow-y:auto;
  background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius-lg);
  box-shadow:var(--shadow-md); z-index:50; }
.notif-dropdown-head{ display:flex; align-items:center; justify-content:space-between; padding:12px 14px;
  border-bottom:1px solid var(--border); font-size:12.5px; font-weight:700; position:sticky; top:0; background:var(--surface-1); }
.notif-mark-all{ background:none; border:none; color:var(--accent); font-size:11px; font-weight:600; cursor:pointer; padding:0; }
.notif-item{ padding:10px 14px; border-bottom:1px solid var(--border); cursor:pointer; }
.notif-item:last-child{ border-bottom:none; }
.notif-item:hover{ background:var(--surface-2); }
.notif-item.unread{ background:var(--accent-bg); }
.notif-item-text{ font-size:12.5px; color:var(--text-primary); }
.notif-item-time{ font-size:10.5px; color:var(--text-muted); margin-top:2px; }

/* ============ Personal / Account page ============
   Copied from the design reference's Account screen: one card (max-width
   520px), 84px avatar with a hover-reveal camera+"CHANGE" overlay
   (opacity 0→1, scale .88→1, 0.25s cubic-bezier(.2,.8,.2,1)), Email/
   Username rows, then a Password row bordered off above. */
.account-card{ max-width:520px; padding:28px; display:flex; flex-direction:column; gap:22px; }
.account-header{ display:flex; align-items:center; gap:20px; }
.personal-avatar-wrap{ position:relative; flex:0 0 auto; display:block; border-radius:50%; cursor:pointer; }
.personal-avatar{ width:84px; height:84px; font-size:24px;
  background:var(--accent); border-color:transparent; color:#fff; }
.personal-avatar-overlay{ position:absolute; inset:0; border-radius:50%; background:rgba(10,12,18,0);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px;
  opacity:0; transform:scale(.88); cursor:pointer;
  transition:opacity .25s cubic-bezier(.2,.8,.2,1), transform .25s cubic-bezier(.2,.8,.2,1), background .25s cubic-bezier(.2,.8,.2,1); }
.account-avatar-change-label{ font-size:9.5px; color:#fff; font-family:var(--font-mono); letter-spacing:.04em; }
.personal-avatar-wrap:hover .personal-avatar-overlay{ opacity:1; transform:scale(1); background:rgba(10,12,18,.6); }
.account-name{ font-family:var(--font-display); font-weight:700; font-size:18px; color:var(--text-primary); }
.account-role{ font-family:var(--font-mono); font-size:11.5px; color:var(--text-muted); text-transform:uppercase; letter-spacing:.05em; margin-top:4px; }
.account-section{ display:flex; flex-direction:column; gap:14px; padding-top:20px; border-top:1px solid var(--border); }
.account-security-row{ flex-direction:row; align-items:center; justify-content:space-between; }
.account-field-label{ font-size:11.5px; color:var(--text-secondary); margin-bottom:5px; }
.account-field-value{ font-size:13.5px; color:var(--text-primary); }
.account-field-value.mono{ font-family:var(--font-mono); font-size:13px; }
.account-field-title{ font-size:13.5px; font-weight:600; color:var(--text-primary); }
.account-field-sub{ font-size:12px; color:var(--text-muted); margin-top:2px; }

@media (max-width:560px){
  .account-header{ flex-direction:column; align-items:flex-start; text-align:left; }
  .account-security-row{ flex-direction:column; align-items:flex-start; gap:10px; }
}

/* ============ Settings — module toggle switch ============ */
.toggle-switch{ position:relative; display:inline-block; width:40px; height:22px; flex:0 0 auto; cursor:pointer; }
.toggle-switch input{ position:absolute; opacity:0; width:100%; height:100%; margin:0; cursor:pointer; }
.toggle-switch-track{ position:absolute; inset:0; background:var(--surface-2); border:1px solid var(--border-strong);
  border-radius:11px; transition:background .15s, border-color .15s; }
.toggle-switch-track::after{ content:''; position:absolute; top:2px; left:2px; width:16px; height:16px; border-radius:50%;
  background:#fff; box-shadow:var(--shadow-sm); transition:transform .15s; }
.toggle-switch input:checked + .toggle-switch-track{ background:var(--accent); border-color:var(--accent); }
.toggle-switch input:checked + .toggle-switch-track::after{ transform:translateX(18px); }
.toggle-switch input:focus-visible + .toggle-switch-track{ outline:2px solid var(--accent); outline-offset:2px; }

.viewport{ flex:1; padding:24px 26px 60px; }
.page{ display:none; max-width:1180px; margin:0 auto; }
.page#page-reservations{ max-width:none; }
.page.active{ display:block; animation:fade .25s ease; }
@keyframes fade{ from{ opacity:0; transform:translateY(4px); } to{ opacity:1; transform:none; } }

/* Slide-in used only for real page-to-page navigation (sidebar nav clicks)
   — deliberately NOT applied to in-place content swaps like Wiki folder/
   document navigation, which re-render far more often and would otherwise
   feel like a constant "refresh". */
@keyframes tf-slide-in{ from{ opacity:0; transform:translateX(16px); } to{ opacity:1; transform:translateX(0); } }
.page.active{ animation:tf-slide-in .32s cubic-bezier(.22,.61,.36,1); }
@media (prefers-reduced-motion: reduce){
  .page.active{ animation:none; }
}

/* ============ Reusable UI ============ */
/* Badges — copied exactly from the "TFAdmin Design System" reference's
   badgeStyle(): mono, uppercase, 8px radius (not a pill). */
.badge{ display:inline-flex; align-items:center; gap:5px; font-family:var(--font-mono); font-size:11px;
  font-weight:600; letter-spacing:0.04em; text-transform:uppercase; padding:4px 10px; border-radius:8px; white-space:nowrap; }
.badge.accent{ background:var(--accent-bg); color:var(--accent); }
.badge.success{ background:var(--success-bg); color:var(--success); }
.badge.warning{ background:var(--warning-bg); color:var(--warning); }
.badge.danger{ background:var(--danger-bg); color:var(--danger); }
.badge.info{ background:var(--info-bg); color:var(--info); }
.badge.cri{ background:#fdf1e6; color:var(--tf-cri); }
.badge.iri{ background:#e5f4f5; color:var(--tf-iri); }
.badge.master{ background:#f1e6fd; color:#7a2fc9; }
html[data-theme="dark"] .badge.cri{ background:#3a2410; }
html[data-theme="dark"] .badge.iri{ background:#0f2c2f; }
html[data-theme="dark"] .badge.master{ background:#2c1a3f; color:#c79bf0; }

.grid{ display:grid; gap:16px; }
.grid.cols-4{ grid-template-columns:repeat(4,1fr); }
.grid.cols-3{ grid-template-columns:repeat(3,1fr); }
.grid.cols-2{ grid-template-columns:repeat(2,1fr); }
@media (max-width:980px){ .grid.cols-4{ grid-template-columns:repeat(2,1fr);} .grid.cols-3{ grid-template-columns:repeat(2,1fr);} }
@media (max-width:640px){ .grid.cols-4,.grid.cols-3,.grid.cols-2{ grid-template-columns:1fr; } }

/* Fleet status cards — content (tail, gauge, two buttons) tops out around
   200px wide, so a fixed 3-up grid left a lot of dead air on either side.
   auto-fill sizes columns to the content instead of stretching to fill. */
.fleet-cards-grid{ display:grid; gap:16px; grid-template-columns:repeat(auto-fill, minmax(200px, 220px));
  justify-content:start; }
@media (max-width:640px){ .fleet-cards-grid{ grid-template-columns:repeat(auto-fill, minmax(160px, 1fr)); } }

.card{ background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius-lg);
  padding:18px; box-shadow:var(--shadow-sm); }
.card h3{ margin:0 0 4px; font-family:var(--font-display); font-size:14px; font-weight:700; }
.stat-card .stat-label{ font-size:11px; text-transform:uppercase; letter-spacing:0.06em; color:var(--text-muted); margin:0 0 8px; }
.stat-card .stat-value{ font-family:var(--font-display); font-size:26px; font-weight:700; line-height:1; }
.stat-card .stat-sub{ font-size:12px; color:var(--text-secondary); margin-top:6px; }

/* Reserves the AOG status line's height on every fleet card, AOG or not,
   so the gauge and action buttons stay aligned across a row of cards. */
.fleet-status-line{ font-size:12px; line-height:1.4; min-height:16.8px; margin:0 0 4px; }

.section-title{ font-family:var(--font-display); font-size:15px; font-weight:700; margin:26px 0 12px; display:flex;
  align-items:center; justify-content:space-between; }
.section-title:first-child{ margin-top:0; }

/* Unified segmented tab style — copied exactly from the "TFAdmin Design
   System" reference's settings/course-sub-tab pattern: a muted track, each
   tab going to a surface1 "pill" with accent text (not a filled accent
   background) when active. Used for course page tabs and, via
   .res-view-toggle below, the Reservations Day/Week/Month switch — one tab
   pattern app-wide instead of the old underline-vs-pill split. */
.course-tabbar{ display:inline-flex; gap:2px; background:var(--surface-2); border:1px solid var(--border);
  border-radius:11px; padding:4px; margin-bottom:20px; }
.course-tab{ padding:8px 18px; font-size:13px; font-weight:600; color:var(--text-secondary);
  background:none; border:none; border-radius:8px; cursor:pointer; transition:background .12s, color .12s; }
.course-tab:hover{ color:var(--text-primary); }
.course-tab.active{ background:var(--surface-1); color:var(--accent); box-shadow:var(--shadow-sm); }

/* ============ Course hub (unified landing panel, replaces the old
   Sections/Users/Question bank/Results tab bar) ============ */
.course-hub-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); gap:14px; }
.course-hub-card{ background:var(--surface-1); border:1px solid var(--border); border-radius:18px;
  padding:24px 16px; display:flex; flex-direction:column; align-items:center; gap:10px; text-align:center;
  cursor:pointer; box-shadow:var(--shadow-sm); transition:transform .15s cubic-bezier(.2,.8,.2,1), box-shadow .15s, border-color .15s; }
.course-hub-card:hover{ transform:translateY(-3px) scale(1.02); box-shadow:var(--shadow-md); border-color:var(--accent); }
.course-hub-card:active{ transform:translateY(-1px) scale(1); }
.course-hub-card-icon{ width:26px; height:26px; display:flex; align-items:center; justify-content:center; color:var(--text-secondary); transition:color .15s; }
.course-hub-card-icon svg{ width:26px; height:26px; }
.course-hub-card:hover .course-hub-card-icon{ color:var(--accent); }
.course-hub-card-label{ font-size:13.5px; font-weight:600; color:var(--text-primary); }
/* ============ Course Wiki (folder/document tree: rounded-card browsing + GitBook-style reader) ============ */
/* Folder browsing — full width, same rounded-card grid as the course hub. */
.wiki-browse{ max-width:1000px; }
.wiki-search-bar{ position:relative; display:flex; align-items:center; margin:14px 0 18px; max-width:420px; }
.wiki-search-bar svg{ position:absolute; left:12px; color:var(--text-muted); pointer-events:none; }
.wiki-search-bar input{ width:100%; padding:9px 12px 9px 34px; border-radius:9px; border:1px solid var(--border);
  background:var(--surface-1); color:var(--text-primary); font-size:13px; box-shadow:var(--shadow-sm); }
.wiki-search-bar input:focus{ outline:none; border-color:var(--accent); }
.wiki-grid-actions{ display:flex; gap:8px; margin-bottom:16px; }
.wiki-new-btn{ display:flex; align-items:center; gap:6px; padding:8px 12px; border-radius:8px;
  border:1px dashed var(--border-strong); background:transparent; color:var(--text-secondary); font-size:12.5px; font-weight:600; cursor:pointer; }
.wiki-new-btn:hover{ color:var(--accent); border-color:var(--accent); background:var(--accent-bg); }
.wiki-node-card{ position:relative; cursor:pointer; }
.wiki-node-delete{ position:absolute; top:8px; right:8px; width:24px; height:24px; border-radius:7px; border:1px solid var(--border);
  background:var(--surface-1); color:var(--text-muted); display:flex; align-items:center; justify-content:center;
  cursor:pointer; opacity:0; transition:opacity .12s, color .12s, border-color .12s; }
.wiki-node-card:hover .wiki-node-delete{ opacity:1; }
.wiki-node-delete:hover{ color:var(--danger); border-color:var(--danger); }
.wiki-search-results{ display:flex; flex-direction:column; gap:1px; background:var(--surface-1); border:1px solid var(--border);
  border-radius:var(--radius-lg); overflow:hidden; box-shadow:var(--shadow-sm); }
.wiki-search-result{ display:flex; align-items:center; gap:10px; padding:12px 14px; border:none; border-bottom:1px solid var(--border);
  background:transparent; color:inherit; text-align:left; cursor:pointer; }
.wiki-search-result:last-child{ border-bottom:none; }
.wiki-search-result:hover{ background:var(--surface-2); }
.wiki-search-result-icon{ flex:0 0 auto; color:var(--text-secondary); }
.wiki-search-result-title{ display:block; font-size:13.5px; font-weight:600; color:var(--text-primary); }
.wiki-search-result-path{ display:block; font-size:11.5px; color:var(--text-muted); margin-top:2px; }

/* Document reader — content + "On this page" TOC, no left sidebar (folder
   browsing above replaces what a persistent tree used to do). The
   breadcrumb+title live in their own sticky header ABOVE this grid (see
   .wiki-doc-sticky) so the TOC's top edge lines up with the content
   column's top edge — both are grid siblings starting at the same row. */
/* Collapsing the TOC hands its freed-up width to the content column, which
   is the point (a wider reading column once you don't need the names
   showing) — but snapping straight from 230px to 56px reflowed every line
   of text instantly, which read as a jarring "shift" rather than an
   intentional resize. Transitioning the track width turns the same reflow
   into something that visibly happens TO the page instead of just
   happening. */
.wiki-doc-shell{ display:grid; grid-template-columns:230px minmax(0,1fr); gap:22px; align-items:start; margin:0 -2px;
  transition:grid-template-columns .22s ease; }
.wiki-doc-main{ min-width:0; }
/* The negative top margin cancels .viewport's own 24px top padding so this
   element's box starts flush right under the topbar — exactly matching its
   sticky `top` offset. Without it, the element's natural flow position sat
   lower than its stuck position, so the first bit of scrolling visibly
   dragged it upward before it locked in place. The padding-top puts that
   same 24px of breathing room back inside the box. top:72px is the
   topbar's real measured height (16px padding + the search bar's ~40px,
   which is taller than the icon buttons) — 68px was a guess that undershot
   by 4px, leaving a small residual drift every time. */
.wiki-doc-sticky{ position:sticky; top:72px; z-index:16; background:var(--surface-0);
  margin:-24px -2px 0; padding:24px 2px 4px; }
html[data-theme="dark"] .wiki-doc-sticky, html[data-theme="dark"] .topbar{
  /* Matches body's dark-mode gradient instead of a flat fallback color — a
     flat color here reads as a visible, mismatched box against the
     gradient. background-attachment:fixed is NOT optional here, despite
     the repaint cost: a radial-gradient's percentage position (55% -10%)
     is resolved against the element's OWN box, not the viewport — body's
     copy of this gradient and a plain (non-fixed) copy on a ~200px-tall
     sticky header resolve "55% -10%" against completely different
     dimensions, so they can never actually line up, fixed or not. Without
     :fixed here this rendered as a visibly distinct rectangle the instant
     anything nearby repainted (confirmed via DevTools element inspection:
     hovering unrelated content elsewhere on the page was enough to expose
     the seam). The repaint-hotspot concern that motivated removing it
     stands, but correctness comes first — the fix for the cost is
     reducing how often nearby elements repaint (done: no hover transition
     on .wiki-part-block, no per-block position:sticky pencils), not
     breaking this element's own background math. */
  background:radial-gradient(ellipse 1400px 900px at 55% -10%, #14213f 0%, #0a0f1e 50%, #05070c 100%);
  background-attachment:fixed;
}
/* Windows-Explorer-style address bar: rounded pill segments chained with
   chevron arrows, first segment carries a folder icon. */
.wiki-breadcrumb{ display:flex; align-items:center; gap:2px; font-size:12.5px; color:var(--text-muted);
  margin-bottom:16px; background:var(--surface-1); border:1px solid var(--border); border-radius:999px;
  padding:5px 6px; width:fit-content; max-width:100%; overflow-x:auto; }
.wiki-crumb-seg{ display:flex; align-items:center; gap:6px; padding:5px 12px; border-radius:999px; white-space:nowrap; }
.wiki-crumb-seg svg{ flex:0 0 auto; width:13px; height:13px; opacity:.75; }
.wiki-breadcrumb > svg{ flex:0 0 auto; width:10px; height:10px; color:var(--text-muted); opacity:.6; margin:0 1px; }
.wiki-crumb-link{ background:none; border:none; font:inherit; font-size:12.5px; color:var(--text-muted); cursor:pointer; }
.wiki-crumb-link:hover{ color:var(--accent); background:var(--accent-bg); }
.wiki-crumb-current{ color:var(--text-primary); font-weight:700; background:var(--surface-2); }
.wiki-empty{ text-align:center; padding:60px 20px; color:var(--text-muted); background:var(--surface-1);
  border:1px solid var(--border); border-radius:var(--radius-lg); }
.wiki-page-header{ position:relative; padding-bottom:16px; margin-bottom:18px; border-bottom:1px solid var(--border); }
/* Same padding/border box as .wiki-title-edit-inline below, kept invisible
   here (transparent border, no background) — so the title sits at the
   exact same x/y position whether or not you can edit it. Without this,
   toggling edit mode swapped an <h1> with zero padding for an <input> with
   4px/8px padding, visibly shifting the title (and everything using it as
   a layout reference) a few pixels right.
   The 8px horizontal padding itself, though, offset the title's TEXT to
   the right of the breadcrumb/body copy below it, which have no such
   inset — margin-left cancels exactly that padding so the rendered glyphs
   land flush with the rest of the column, while the box (and therefore the
   edit-mode match above) keeps its padding untouched. */
.wiki-page-title{ font-family:var(--font-display); font-size:26px; font-weight:800; margin:0 0 10px -8px;
  padding:4px 8px; border:1px solid transparent; }
.wiki-page-meta{ display:flex; align-items:center; gap:7px; font-size:12px; color:var(--text-muted); }
.wiki-page-meta .person-avatar{ width:20px; height:20px; font-size:9px; }
.wiki-meta-sep{ opacity:.6; }
/* Find-in-page — sits in the same row as the author/updated meta, pushed to
   the far right of it. Searches only the rendered reading view. */
.wiki-find-bar{ display:flex; align-items:center; gap:5px; margin-left:auto; background:var(--surface-1);
  border:1px solid var(--border); border-radius:999px; padding:4px 5px 4px 10px; }
.wiki-find-bar svg{ flex:0 0 auto; opacity:.6; }
.wiki-find-bar input{ border:none; background:none; font:inherit; font-size:12px; color:var(--text-primary);
  width:120px; outline:none; }
.wiki-find-count{ font-size:11px; color:var(--text-muted); white-space:nowrap; min-width:28px; }
.wiki-find-nav{ display:flex; align-items:center; justify-content:center; width:20px; height:20px; padding:0;
  border-radius:6px; border:none; background:transparent; color:var(--text-secondary); cursor:pointer; }
.wiki-find-nav:hover{ background:var(--surface-2); color:var(--text-primary); }
mark.wiki-find-hit{ background:var(--warning-bg); color:inherit; border-radius:2px; padding:0 1px; }
mark.wiki-find-hit.current{ background:var(--accent); color:#fff; }
/* Renaming a document is just typing into its own title, in place — no
   separate "edit page" step for that either. */
/* letter-spacing:inherit is load-bearing, not decorative — form elements
   don't reliably inherit letter-spacing the way headings do even with an
   otherwise-identical font-family/size/weight (verified: without it, the
   rendered text measured ~4px narrower than the same string in the <h1>,
   confirmed via pixel analysis of a screen recording — invisible to
   getBoundingClientRect, since the CONTAINER box was identical; only the
   glyphs inside it were subtly different). */
.wiki-title-edit-inline{ display:block; width:100%; font-family:var(--font-display); font-size:26px; font-weight:800;
  letter-spacing:inherit;
  margin:0 0 10px -8px; padding:4px 8px; border-radius:8px; border:1px solid transparent; background:transparent; color:var(--text-primary); }
.wiki-title-edit-inline:hover{ border-color:var(--border); background:var(--surface-1); }
.wiki-title-edit-inline:focus{ outline:none; border-color:var(--accent); background:var(--surface-1); }

/* Each "# Part" chunk of the document renders on its own; in edit mode a
   pencil appears (on hover) right by its heading — click it and just that
   chunk swaps for a textarea in place. Nothing else on the page moves. */
/* The border/padding/margin below are unconditional — applied to every
   block for every viewer (students included), all the time, not just
   while hovering or while .wiki-editing is present. That was the actual
   bug behind two rounds of "content shifts/widens when I enter edit mode":
   scoping this box model to .wiki-editing meant editors-with-editing-on
   had a genuinely different content width than everyone else, so toggling
   edit mode really did reflow the whole document a few px wider each time.
   Baking the same reserved space into .wiki-part-block itself, always,
   means the box model is identical in every state — only :hover's
   border-color/background (scoped to .wiki-editing so students don't get
   an interactive-looking highlight on content they can't act on) actually
   changes. Rounded on all four corners to match every other rounded panel
   in this app. padding-top/bottom give the heading/text inside some
   breathing room from the highlight's own edges instead of running flush
   against them. */
/* No transition — animating background-color here means every mouse
   movement over content repaints this element on every frame while it's
   mid-hover. That's cheap on its own, but it sits near two elements using
   background-attachment:fixed (.topbar, .wiki-doc-sticky), and fixed
   backgrounds are a known Chromium repaint hotspot; frequent nearby
   repaints made pre-existing display-level gradient banding (an 8-bit
   panel struggling to render a smooth dark radial gradient) far more
   noticeable/flickery than it was before this hover feature existed.
   Instant on/off avoids that without removing the gradient entirely. */
/* Horizontal margin is 0 on both sides, deliberately, even though that
   means the border-left sits flush with the container's edge instead of
   poking 3px out past it the way earlier versions tried for. This app is
   box-sizing:border-box everywhere, and for a width:auto border-box block,
   a negative margin doesn't get absorbed/cancelled by the opposite side's
   padding the way it would under content-box — each side's negative
   margin independently pushes that edge outward by its own amount. With
   asymmetric margins (-15px left, -12px right, chosen to "look right"
   without the arithmetic actually being checked) that meant the block's
   right edge rendered 12px past its own container's right edge — reported
   as the highlight visibly overshooting the header above it. Zero
   horizontal margin cannot have this bug: the border-box is pinned exactly
   to the container's width no matter what padding/border values it has.
   Vertical margin still cancels padding-top/bottom exactly (needed so the
   block doesn't take up more vertical space than before and push
   everything below it down — verified empirically, this direction doesn't
   have the border-box asymmetry problem margin-left/right did). */
.wiki-part-block{ position:relative; border-left:3px solid transparent; border-radius:var(--radius-lg);
  padding:10px 12px; margin:-10px 0 -10px 0; }
.wiki-editing .wiki-part-block:hover{ border-left-color:var(--accent); background:var(--accent-bg); }
/* Spans the block's full height so the sticky button inside has room to
   travel — see the comment on renderWikiPartBlock() in app.js. */
/* position:absolute, not position:sticky — sticky was tried so the pencil
   would track the visible portion of a very tall block (a table can run
   thousands of px) instead of sitting at the block's true, possibly
   off-screen, vertical midpoint. It worked, but it meant every block on a
   long page — dozens of them, all at once, not just the hovered one — had
   its own simultaneously-active sticky element, even while invisible.
   Reported result: thin stray vertical line artifacts scattered through
   the page, reproducible in multiple browsers, that a full audit of every
   border/outline/shadow/pseudo-element in the area couldn't explain —
   consistent with a GPU-compositing seam issue from that many concurrent
   sticky layers rather than an actual CSS rule. Traded back to simple
   center-of-block positioning; the pencil can once again land off-screen
   on an extremely long chunk, which is a much smaller problem than
   rendering artifacts across the page. */
/* position:sticky, tracking the visible portion of the block instead of
   its true (possibly off-screen) vertical midpoint — restored after ruling
   it out as the cause of the stray-line artifact reported earlier; that
   turned out to be .wiki-doc-sticky's background-attachment, fixed
   separately. */
.wiki-part-edit-rail{ position:absolute; top:0; bottom:0; right:-14px; width:28px; pointer-events:none; }
.wiki-part-edit-btn{ position:sticky; top:calc(50vh - 14px); width:28px; height:28px; border-radius:8px;
  border:1px solid var(--border); background:var(--surface-1); color:var(--text-secondary); display:flex; align-items:center;
  justify-content:center; cursor:pointer; opacity:0; transition:opacity .12s, color .12s, border-color .12s; box-shadow:var(--shadow-sm);
  pointer-events:auto; }
.wiki-part-block:hover .wiki-part-edit-btn{ opacity:1; }
.wiki-part-edit-btn:hover{ color:var(--accent); border-color:var(--accent); }
.wiki-blank-note-block{ color:var(--text-muted); font-style:italic; padding:20px 0; display:flex; align-items:center; gap:10px; }

/* Draft/publish banner — sits under the document header whenever a doc has
   unpublished changes; editing mode (viewingDraft) gets a stronger tint. */
.wiki-draft-banner{ display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap;
  padding:11px 16px; margin:0 0 18px; border-radius:var(--radius-lg); border:1px solid var(--warning);
  background:var(--warning-bg); color:var(--text-primary); font-size:13px; }
.wiki-draft-banner-editing{ border-color:var(--accent); background:var(--accent-bg); }
.wiki-draft-banner-actions{ display:flex; gap:8px; flex:0 0 auto; }

.wiki-drafts-card{ position:relative; border-style:dashed; border-color:var(--border-strong); }
.wiki-drafts-count-badge{ position:absolute; top:10px; right:10px; min-width:18px; height:18px; padding:0 5px;
  border-radius:999px; background:var(--accent); color:var(--accent-contrast, #fff); font-size:10.5px; font-weight:700;
  display:flex; align-items:center; justify-content:center; }
.wiki-draft-card-path{ display:block; font-size:11px; color:var(--text-muted); margin-top:2px; }

.wiki-part-editing{ margin:0 0 8px; }
/* The editor is a contenteditable div carrying the same .wiki-md typography
   as the reading view — it IS the page, just editable, not a separate
   monospace textbox. It used to also get a full border + solid background +
   outer glow, which made clicking to edit feel like the content jumped into
   a completely different, boxed-off component. Now it uses the exact same
   padding/margin/border-radius as .wiki-part-block's own hover state (only
   the bottom padding gets extra room, for the Save/Cancel row below) — so
   the specific item you clicked into renders at the same position and
   width it already had a second ago, instead of visibly resizing the
   instant you start editing it. */
/* width:auto (the block-level default), not width:100% — a 100%-width box
   is pinned to exactly its container's width regardless of margin, so the
   negative margins here would just shift it sideways without growing it.
   .wiki-part-block relies on the opposite behavior (auto-width grows to
   compensate for negative margins, which is what actually produces the
   "3px further left in editing" cosmetic without also making it 27px
   narrower) — this has to match that exactly or the same item changes
   width the moment you click into it. */
.wiki-editor{ width:auto; min-height:120px; padding:10px 12px 22px; margin:-10px 0 0 0; border-radius:var(--radius-lg);
  border-left:3px solid var(--accent); background:var(--accent-bg); }
.wiki-editor:focus{ outline:none; }
.wiki-editor h2:first-child, .wiki-editor h3:first-child, .wiki-editor h4:first-child, .wiki-editor p:first-child{ margin-top:0; }
.wiki-part-editor-actions{ display:flex; align-items:center; gap:8px; margin-top:10px; }
.wiki-delete-link{ display:inline-flex; align-items:center; gap:6px; background:none; border:none; padding:0;
  font-size:12.5px; color:var(--danger); cursor:pointer; opacity:.85; }
.wiki-delete-link:hover{ opacity:1; text-decoration:underline; }
.wiki-add-part-btn{ display:flex; align-items:center; gap:6px; margin-top:18px; padding:10px 14px; border-radius:9px;
  border:1px dashed var(--border-strong); background:transparent; color:var(--text-secondary); font-size:12.5px; font-weight:600; cursor:pointer; }
.wiki-add-part-btn:hover{ color:var(--accent); border-color:var(--accent); background:var(--accent-bg); }

/* Vertical formatting rail — fixed to the right edge of the viewport,
   shown only while a part is actively being edited. Same icon language and
   button styling as everywhere else, just stacked instead of a horizontal
   bar, so it doesn't compete with the (unchanged) reading layout. */
.wiki-vtoolbar{ position:fixed; top:50%; right:22px; transform:translateY(-50%) translateX(0); z-index:40; display:flex; flex-direction:column;
  align-items:center; gap:5px; background:var(--surface-1); border:1px solid var(--border); border-radius:16px;
  padding:12px 9px; box-shadow:var(--shadow-md);
  animation:wiki-vtoolbar-in .15s ease-out;
  transition:opacity .12s ease, transform .12s ease; }
@keyframes wiki-vtoolbar-in{ from{ opacity:0; transform:translateY(-50%) translateX(14px); } to{ opacity:1; transform:translateY(-50%) translateX(0); } }
/* Toggled by JS right before the toolbar is torn down (wikiCloseToolbarThen
   in app.js, WIKI_VTOOLBAR_EXIT_MS must match this transition's duration)
   — CSS alone can't animate an element's removal, so the state change is
   delayed just long enough for this transition to play first. */
.wiki-vtoolbar.wiki-vtoolbar-leaving{ opacity:0; transform:translateY(-50%) translateX(14px); }
.wiki-vtoolbar-sep{ height:1px; width:26px; margin:4px 0; background:var(--border); }
.wiki-tool-btn{ display:flex; align-items:center; justify-content:center; width:40px; height:40px; padding:0; border-radius:10px;
  border:1px solid transparent; background:transparent; color:var(--text-secondary); cursor:pointer; }
.wiki-tool-btn svg{ width:19px; height:19px; }
.wiki-tool-btn:hover{ background:var(--surface-2); color:var(--text-primary); }
.wiki-tool-btn-text{ font-size:14px; font-weight:700; font-family:var(--font-mono); }
.wiki-tool-callout.info:hover{ color:var(--accent); background:var(--accent-bg); }
.wiki-tool-callout.tip:hover{ color:var(--success); background:var(--success-bg); }
.wiki-tool-callout.warning:hover{ color:var(--warning); background:var(--warning-bg); }
@media (max-width: 1180px){ .wiki-vtoolbar{ display:none; } }

/* Table insert — Word/Excel-style hover grid, pinned to the left of the
   vertical toolbar (which is position:fixed, so it's the containing block). */
.wiki-table-picker{ position:absolute; right:100%; top:50%; transform:translateY(-50%); margin-right:8px;
  background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius-lg); padding:10px;
  box-shadow:var(--shadow-md); z-index:41; }
.wiki-tpick-label{ font-size:11px; color:var(--text-muted); text-align:center; margin-bottom:7px; }
.wiki-tpick-grid{ display:grid; gap:3px; }
.wiki-tpick-cell{ width:14px; height:14px; border-radius:2px; border:1px solid var(--border); background:var(--surface-2); cursor:pointer; }
.wiki-tpick-cell.on{ background:var(--accent); border-color:var(--accent); }

/* Rendered Markdown */
.wiki-md{ font-size:17px; line-height:1.75; color:var(--text-primary); }
/* scroll-margin-top used to be a hardcoded 20px — nowhere near the sticky
   breadcrumb+title header's real height (~190-210px depending on whether
   the draft banner is showing). Clicking a TOC link scrolled the target
   heading to y=0, which sat almost entirely UNDER that opaque sticky header
   — so "Part 7" visually looked like it landed on 7.3, whatever heading
   happened to fall just past the header's bottom edge. --wiki-scroll-offset
   is set on #wiki-page-content in afterWikiRender(), measured fresh off the
   actual header height every render, same idea as the TOC's own sticky
   `top` fix. */
.wiki-md h2{ font-family:var(--font-display); font-size:23px; font-weight:800; margin:64px 0 16px;
  scroll-margin-top:var(--wiki-scroll-offset, 110px); }
/* :first-of-type, not :first-child — in edit mode each part-block's h2 is
   preceded by a .wiki-part-edit-btn sibling, which made :first-child stop
   matching and let the normal top margin back in, visibly dropping the
   whole document lower the moment edit mode turned on. :first-of-type
   ignores the button (different tag) and keeps matching either way. */
.wiki-md h2:first-of-type{ margin-top:0; }
.wiki-md h3{ font-family:var(--font-display); font-size:18.5px; font-weight:700; margin:34px 0 10px;
  scroll-margin-top:var(--wiki-scroll-offset, 110px); }
.wiki-heading-num{ color:var(--text-muted); font-weight:700; margin-right:7px; }
.wiki-md h4{ font-size:16px; font-weight:700; margin:18px 0 7px; color:var(--text-secondary); }
.wiki-md p{ margin:0 0 16px; color:var(--text-secondary); }
.wiki-md strong{ color:var(--text-primary); font-weight:700; }
.wiki-md a{ color:var(--accent); text-decoration:underline; text-underline-offset:2px; }
.wiki-md img{ max-width:100%; border-radius:var(--radius); border:1px solid var(--border); display:block; margin:0 0 16px; }
.wiki-md code{ font-family:var(--font-mono); font-size:14.5px; background:var(--surface-2); border:1px solid var(--border);
  border-radius:4px; padding:1px 5px; }
.wiki-md .wiki-list{ margin:0 0 16px; padding-left:24px; color:var(--text-secondary); display:flex; flex-direction:column; gap:6px; }
.wiki-md .wiki-hr{ border:none; border-top:1px solid var(--border); margin:22px 0; }
.wiki-code{ background:var(--surface-2); border:1px solid var(--border); border-radius:var(--radius); padding:14px 16px;
  overflow-x:auto; margin:0 0 16px; }
.wiki-code code{ font-family:var(--font-mono); font-size:14.5px; background:none; border:none; padding:0; white-space:pre; }
.wiki-blockquote{ border-left:3px solid var(--border-strong); padding:2px 0 2px 14px; margin:0 0 16px; color:var(--text-muted); }
.wiki-blockquote p{ margin:0 0 6px; color:inherit; }
.wiki-table-wrap{ overflow-x:auto; margin:0 0 16px; border:1px solid var(--border); border-radius:var(--radius-lg);
  box-shadow:var(--shadow-sm); }
/* Table cells are transparent by default, so a hovered/highlighted
   .wiki-part-block's accent tint used to show straight through every cell
   while each row's border-bottom stayed exactly as dark as it always was
   — reading as a much harsher set of stripes than intended (worse in some
   browsers than others, depending on how they anti-alias a 1px border
   against a tinted vs plain background). Fixed by giving the table its
   own opaque background ONLY while that ancestor is actually hovered —
   scoped this way (rather than an unconditional background on
   .wiki-table-wrap, tried first) so a table looks exactly like it always
   did outside of that hover state, with no permanent visible "card" edge
   against the page background the rest of the time. */
.wiki-editing .wiki-part-block:hover .wiki-table-wrap{ background:var(--surface-0); }
.wiki-table{ width:100%; border-collapse:separate; border-spacing:0; font-size:15px; }
.wiki-table th{ text-align:left; background:var(--surface-2); font-weight:700; padding:10px 14px; border-bottom:1px solid var(--border); }
.wiki-table td{ padding:10px 14px; border-bottom:1px solid var(--border); color:var(--text-secondary); }
.wiki-table tr:last-child td{ border-bottom:none; }
.wiki-table th:first-child{ border-top-left-radius:var(--radius-lg); }
.wiki-table th:last-child{ border-top-right-radius:var(--radius-lg); }
.wiki-table tbody tr:hover td{ background:var(--surface-1); }
.wiki-blank-note{ color:var(--text-muted); font-style:italic; }

.wiki-callout{ display:flex; gap:10px; padding:12px 14px; border-radius:var(--radius); border:1px solid; margin:0 0 16px; }
.wiki-callout-icon{ flex:0 0 auto; margin-top:1px; }
.wiki-callout-label{ font-weight:700; margin:0 0 2px; }
.wiki-callout p{ margin:0; color:inherit; }
.wiki-callout-info{ background:var(--accent-bg); border-color:var(--accent); color:var(--accent); }
.wiki-callout-tip{ background:var(--success-bg); border-color:var(--success); color:var(--success); }
.wiki-callout-warning{ background:var(--warning-bg); border-color:var(--warning); color:var(--warning); }
.wiki-callout-danger{ background:var(--danger-bg); border-color:var(--danger); color:var(--danger); }
.wiki-callout p, .wiki-callout strong{ color:var(--text-primary); }

.wiki-toc{ position:sticky; top:162px; font-size:12.5px; max-height:calc(100vh - 184px); overflow-y:auto; padding-right:4px; }
.wiki-toc-header{ display:flex; align-items:center; justify-content:space-between; gap:8px; margin:0 0 14px; }
.wiki-toc-title{ font-size:10.5px; text-transform:uppercase; letter-spacing:0.06em; color:var(--text-muted); margin:0; font-weight:700; }
.wiki-toc-narrow-btn{ display:flex; align-items:center; justify-content:center; flex:0 0 auto; width:20px; height:20px;
  padding:0; border:1px solid var(--border); border-radius:5px; background:none; color:var(--text-muted); cursor:pointer; }
.wiki-toc-narrow-btn:hover{ color:var(--text-primary); border-color:var(--border-strong); }
/* Each Part + its subparts is its own group so they can get real breathing
   room from the NEXT Part, and so the group's subpart list can collapse as
   one unit (wikiToggleTocPart in app.js) without disturbing anything
   above or below it. */
.wiki-toc-group{ margin-bottom:22px; }
.wiki-toc-group:last-child{ margin-bottom:0; }
.wiki-toc-part-row{ display:flex; align-items:center; gap:2px; }
.wiki-toc-chevron-btn{ display:flex; align-items:center; justify-content:center; flex:0 0 auto; width:16px; height:16px;
  padding:0; border:none; background:none; color:var(--text-muted); cursor:pointer; border-radius:4px; }
.wiki-toc-chevron-btn svg{ transition:transform .12s ease; }
.wiki-toc-chevron-btn.expanded svg{ transform:rotate(90deg); }
.wiki-toc-chevron-btn:hover{ color:var(--text-primary); background:var(--surface-2); }
.wiki-toc-chevron-spacer{ width:16px; flex:0 0 auto; }
/* margin-left starts from the chevron button's own width (16px) + the
   .wiki-toc-part-row gap (2px) = 18px, same offset that keeps subpart
   links under the Part text rather than to its left — plus the Part
   link's own 3px accent border and a few more px of clearance, so the
   subpart ticks sit clearly to the RIGHT of that vertical line instead of
   sharing its column (they used to start exactly where the border did,
   reading as one merged mark instead of two separate elements). */
.wiki-toc-subs{ margin-top:2px; margin-left:36px; }
.wiki-toc-link{ display:block; padding:5px 0 5px 12px; border-left:2px solid var(--border); color:var(--text-muted);
  text-decoration:none; margin-bottom:1px; transition:color .12s, border-color .12s; }
.wiki-toc-link:hover{ color:var(--text-primary); }
.wiki-toc-link.active{ color:var(--accent); border-left-color:var(--accent); font-weight:600; }
/* Parts (H2 — the manual's own PART 0-9 + Annexes) read as the main
   structure: bolder, uppercase, a stronger border. Subsections (H3) stay
   light and indented underneath. */
.wiki-toc-link.wiki-toc-part{ flex:1 1 auto; min-width:0; font-size:12.5px; font-weight:800; text-transform:uppercase;
  letter-spacing:0.03em; color:var(--text-primary); border-left-width:3px; border-left-color:var(--border-strong); }
.wiki-toc-link.wiki-toc-part.active{ border-left-color:var(--accent); }
/* A continuous vertical rail down the whole subpart list read as too heavy
   a structural element for what's just a handful of list items — this is a
   short angled tick per item instead (a small dash, not a connector), each
   one independent of its neighbours, echoing a hand-marked checklist rather
   than a tree diagram. */
.wiki-toc-link.wiki-toc-sub{ position:relative; padding-left:14px; font-size:12px; border-left:none; margin-bottom:0; }
.wiki-toc-link.wiki-toc-sub::before{ content:''; position:absolute; left:1px; top:50%; width:2px; height:11px;
  background:var(--border-strong); border-radius:1px; transform:translateY(-50%) rotate(25deg); transition:background-color .12s; }
.wiki-toc-link.wiki-toc-sub:hover::before{ background:var(--text-secondary); }
.wiki-toc-link.wiki-toc-sub.active::before{ background:var(--accent); }

/* Narrow mode — the whole TOC column shrinks and shows numbers only
   (Part index, or "index.n" for a subpart), no names; hover/title
   attribute still carries the full text. wikiToggleTocNarrow() in app.js
   toggles wikiState.tocNarrow and re-runs afterWikiRender(), which swaps
   in this markup and adds .wiki-doc-shell-toc-narrow to shrink the grid
   column to match. */
.wiki-doc-shell-toc-narrow{ grid-template-columns:56px minmax(0,1fr); }
.wiki-toc-narrow .wiki-toc-header{ justify-content:center; }
.wiki-toc-narrow .wiki-toc-group{ margin-bottom:10px; }
.wiki-toc-narrow-num{ display:flex; align-items:center; justify-content:center; width:100%; padding:6px 2px;
  border-left:none; border-radius:6px; text-align:center; font-weight:700; }
.wiki-toc-narrow-num.wiki-toc-part{ background:var(--surface-2); margin-bottom:2px; }
.wiki-toc-narrow-num.wiki-toc-sub{ font-size:10.5px; color:var(--text-muted); padding:4px 2px; }
.wiki-toc-narrow-num.active{ background:var(--accent-bg); color:var(--accent); }

@media (max-width: 860px){
  .wiki-doc-shell{ grid-template-columns:minmax(0,1fr); }
  .wiki-toc{ display:none; }
}

.btn{ display:inline-flex; align-items:center; gap:6px; border-radius:8px; padding:9px 14px; font-size:13px;
  font-weight:600; cursor:pointer; border:1px solid var(--border-strong); background:var(--surface-1); color:var(--text-primary); }
.btn:hover{ background:var(--surface-2); }
.btn.primary{ background:var(--accent); border-color:var(--accent); color:#fff; }
.btn.primary:hover{ filter:brightness(1.06); }
.btn.ghost{ border-color:transparent; background:transparent; }
.btn.sm{ padding:6px 10px; font-size:12px; }

.progress{ height:6px; border-radius:4px; background:var(--surface-2); border:1px solid var(--border); overflow:hidden; }
.progress > span{ display:block; height:100%; background:var(--accent); border-radius:4px; }

table.tf-table{ width:100%; border-collapse:collapse; font-size:13px; }
.tf-table th{ text-align:left; font-size:10.5px; text-transform:uppercase; letter-spacing:0.05em; color:var(--text-muted);
  border-bottom:1px solid var(--border); padding:8px 10px; font-weight:600; }
.tf-table td{ padding:10px 10px; border-bottom:1px solid var(--border); vertical-align:middle; }
.tf-table tr:last-child td{ border-bottom:none; }
.tf-table tr:hover td{ background:var(--surface-2); }
.table-wrap{ background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius-lg);
  overflow:hidden; box-shadow:var(--shadow-sm); }
.table-wrap .table-scroll{ overflow-x:auto; }

.module-card{ background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius-lg);
  padding:16px 18px; box-shadow:var(--shadow-sm); }
.module-head{ display:flex; align-items:baseline; justify-content:space-between; gap:10px; margin-bottom:2px; }
.module-head h4{ margin:0; font-size:14.5px; font-weight:700; }
.module-code{ font-family:var(--font-mono); font-size:10.5px; color:var(--text-muted); }
.cbt-list{ margin-top:12px; display:flex; flex-direction:column; gap:1px; border-top:1px solid var(--border); }
.cbt-item{ display:flex; align-items:center; gap:10px; padding:10px 2px; border-bottom:1px solid var(--border); }
.cbt-icon{ width:28px; height:28px; border-radius:6px; background:var(--surface-2); border:1px solid var(--border);
  display:flex; align-items:center; justify-content:center; font-size:13px; flex:0 0 auto; }
.cbt-name{ font-size:13px; font-weight:500; flex:1; }
.cbt-meta{ font-size:11.5px; color:var(--text-muted); }

.empty-state{ text-align:center; padding:50px 20px; color:var(--text-muted); }

/* ============ Course Users tab: list/card view toggle ============ */
.view-toggle{ display:inline-flex; gap:2px; background:var(--surface-2); border:1px solid var(--border); border-radius:9px; padding:4px; }
.view-toggle-btn{ width:26px; height:24px; border:none; background:transparent; border-radius:7px; cursor:pointer;
  color:var(--text-secondary); font-size:13px; display:flex; align-items:center; justify-content:center; }
.view-toggle-btn.active{ background:var(--surface-1); color:var(--accent); box-shadow:var(--shadow-sm); }
.user-card-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(140px, 1fr)); gap:12px; }
.user-card{ display:flex; flex-direction:column; align-items:center; text-align:center; gap:4px;
  background:var(--surface-1); border:1px solid var(--border); border-radius:16px; padding:16px 10px; }
.user-card .person-avatar{ width:44px; height:44px; font-size:15px; }
.user-card-name{ font-size:13px; font-weight:600; margin-top:4px; }
.user-card-role{ font-size:11px; color:var(--text-muted); }
@media (max-width:640px){ .user-card-grid{ grid-template-columns:repeat(auto-fill, minmax(110px, 1fr)); } }

/* ============ CBT activity cards (Moodle-style topic/activity list) ============ */
.cbt-secondary-links{ display:flex; gap:8px; justify-content:flex-end; margin:0 0 14px; }
.cbt-topic{ background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius-lg);
  overflow:hidden; box-shadow:var(--shadow-sm); }
.cbt-topic-head{ display:flex; align-items:center; justify-content:space-between; gap:10px;
  padding:14px 16px; background:var(--surface-2); border-bottom:1px solid var(--border); }
.cbt-topic-head h4{ margin:0; font-size:15px; font-weight:700; }
.cbt-activities{ display:flex; flex-direction:column; }
.cbt-activity{ display:flex; align-items:center; gap:12px; padding:13px 16px; border-bottom:1px solid var(--border); }
.cbt-activity:last-child{ border-bottom:none; }
.cbt-activity-icon{ width:36px; height:36px; border-radius:8px; flex:0 0 auto; background:var(--surface-2);
  display:flex; align-items:center; justify-content:center; font-size:16px; }
.cbt-activity-title{ font-size:13.5px; font-weight:600; }
.cbt-activity-sub{ font-size:11.5px; color:var(--text-muted); margin-top:2px; }
.cbt-activity-action{ flex:0 0 auto; }

/* Presentation viewer modal */
.viewer-modal .modal-card{ max-width:min(880px, 92vw); width:880px; }
.viewer-frame-wrap{ margin-top:12px; border:1px solid var(--border); border-radius:var(--radius-md); overflow:hidden; background:var(--surface-2); }
.viewer-frame-wrap img{ display:block; max-width:100%; max-height:70vh; margin:0 auto; }
.viewer-frame-wrap iframe{ display:block; width:100%; height:70vh; border:0; }

/* Course group chat (Course > Overview, theory side) — flat forum-post
   rows, no card/bubbles; a left accent rule marks your own posts. */
.chat-thread{ display:flex; flex-direction:column; max-height:360px; overflow-y:auto;
  border-top:1px solid var(--border); margin-bottom:16px; }
.chat-row{ padding:10px 2px 10px 12px; border-bottom:1px solid var(--border); border-left:2px solid transparent; }
.chat-row.mine{ border-left-color:var(--accent); background:var(--surface-2); }
.chat-msg-head{ display:flex; align-items:center; gap:6px; font-size:11px; margin-bottom:3px; }
.chat-msg-time{ color:var(--text-muted); font-size:10px; margin-left:auto; }
.chat-msg-text{ font-size:13px; white-space:pre-wrap; word-break:break-word; }
.chat-input-row{ display:flex; gap:8px; }
.chat-input-row input{ flex:1; padding:9px 12px; border-radius:8px; border:1px solid var(--border-strong);
  background:var(--surface-1); color:var(--text-primary); font-family:inherit; font-size:13px; }

/* ATPL Integrated Course programme (Course > Overview, student side) */
.programme-list{ display:flex; flex-direction:column; gap:1px; }
.programme-phase{ padding:12px 2px; border-bottom:1px solid var(--border); opacity:.55; }
.programme-phase:last-child{ border-bottom:none; }
.programme-phase.done{ opacity:.8; }
.programme-phase.current{ opacity:1; }
.programme-phase-head{ display:flex; align-items:flex-start; gap:12px; }
.programme-phase-code{ flex:0 0 auto; width:34px; height:34px; border-radius:8px; display:flex; align-items:center;
  justify-content:center; font-family:var(--font-mono); font-size:11.5px; font-weight:700;
  background:var(--surface-2); border:1px solid var(--border); color:var(--text-muted); }
.programme-phase.current .programme-phase-code{ background:var(--accent-bg); border-color:var(--accent); color:var(--accent); }
.programme-phase.done .programme-phase-code{ background:var(--success-bg); border-color:var(--success); color:var(--success); }
.programme-phase-titles{ flex:1; }
.programme-phase-titles h4{ margin:0; font-size:13.5px; font-weight:700; }
.programme-phase-items{ margin:8px 0 0 46px; padding:0; list-style:none; display:flex; flex-wrap:wrap; gap:6px 10px; }
.programme-phase-items li{ font-size:11.5px; color:var(--text-secondary); position:relative; padding-left:11px; }
.programme-phase-items li::before{ content:''; position:absolute; left:0; top:6px; width:4px; height:4px;
  border-radius:50%; background:var(--text-muted); }
.empty-state .ic{ font-size:28px; margin-bottom:8px; }

.iff-frame-wrap{ border:1px solid var(--border); border-radius:var(--radius-lg); overflow:hidden;
  box-shadow:var(--shadow-sm); background:var(--surface-1); }
.iff-frame-wrap iframe{ width:100%; height:calc(100vh - 210px); min-height:640px; border:0; display:block; }
.iff-note{ display:flex; gap:10px; align-items:flex-start; background:var(--accent-bg); color:var(--accent);
  border-radius:var(--radius); padding:12px 14px; font-size:12.5px; margin-bottom:14px; }

.person-cell{ display:flex; align-items:center; gap:9px; }
.person-avatar{ width:26px; height:26px; border-radius:50%; background:var(--surface-2); border:1px solid var(--border);
  display:flex; align-items:center; justify-content:center; font-family:var(--font-mono); font-size:10px; font-weight:600; }

.mobile-topbar{ display:none; }
.sidebar-scrim{ display:none; }

@media (max-width:880px){
  .sidebar{ position:fixed; left:0; top:0; transform:translateX(-100%); transition:transform .2s ease; box-shadow:var(--shadow-md); }
  .sidebar.open{ transform:translateX(0); }
  .sidebar-scrim.open{ display:block; position:fixed; inset:0; background:rgba(10,14,25,.45); z-index:29; }
  .mobile-topbar{ display:flex; align-items:center; gap:10px; padding:12px 16px; border-bottom:1px solid var(--border);
    background:var(--surface-1); position:sticky; top:0; z-index:15; }
  .mobile-topbar strong{ font-family:var(--font-display); font-size:14px; }
  .topbar{ padding:12px 16px; }
  .viewport{ padding:16px 16px 50px; }
}

/* ============ Login screen ============ */
.login-screen{ min-height:100vh; display:flex; align-items:center; justify-content:center;
  background:radial-gradient(circle at 50% 35%, #14213f 0%, #0a0f1e 45%, #05070c 100%); padding:24px; }
.login-card{ width:100%; max-width:380px; background:var(--tf-navy-900); border:1px solid var(--tf-navy-border);
  border-radius:var(--radius-lg); padding:30px 28px 26px; box-shadow:0 20px 60px rgba(0,0,0,.5); }
.login-logo{ height:34px; width:auto; display:block; margin:0 auto 18px; }
.login-sub{ text-align:center; color:var(--tf-navy-muted); font-size:12.5px; margin:0 0 20px; letter-spacing:0.02em; }
.login-label{ display:block; font-size:11px; color:var(--tf-navy-text); margin-bottom:12px; }
.login-label input{ display:block; width:100%; margin-top:5px; background:var(--tf-navy-800); border:1px solid var(--tf-navy-border);
  color:#fff; border-radius:7px; padding:9px 11px; font-size:13.5px; }
.login-label input::placeholder{ color:var(--tf-navy-muted); }
.login-error{ color:#f0a0a0; font-size:12px; margin:4px 0 0; }
.login-screen .btn.primary{ background:#3d7fe0; border-color:#3d7fe0; }
.login-screen .btn.primary:hover{ background:#4d8ce6; border-color:#4d8ce6; }
.login-demo{ margin-top:22px; padding-top:18px; border-top:1px solid var(--tf-navy-border); }
.login-demo-title{ font-size:11px; color:var(--tf-navy-muted); margin:0 0 10px; }
.login-demo-title .stat-sub{ color:var(--tf-navy-muted); font-size:10.5px; }
.login-demo-grid{ display:grid; grid-template-columns:1fr 1fr; gap:6px; max-height:220px; overflow-y:auto; }
.demo-account{ text-align:left; background:var(--tf-navy-800); border:1px solid var(--tf-navy-border); border-radius:7px;
  padding:7px 9px; cursor:pointer; display:flex; flex-direction:column; gap:1px; }
.demo-account:hover{ border-color:#1b5fa8; }
.demo-account-name{ font-size:11.5px; font-weight:600; color:#fff; }
.demo-account-role{ font-size:9.5px; color:var(--tf-navy-muted); }

/* ============ Forms ============ */
.form-grid{ display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-top:10px; }
.form-grid label{ font-size:11.5px; color:var(--text-secondary); display:flex; flex-direction:column; gap:5px; }
.form-grid input, .form-grid select, .form-grid textarea{
  font-size:13px; padding:8px 10px; border-radius:7px; border:1px solid var(--border-strong);
  background:var(--surface-1); color:var(--text-primary); font-family:inherit; resize:vertical; }
.form-grid input:disabled, .form-grid select:disabled, .form-grid textarea:disabled{ opacity:0.6; }
@media (max-width:640px){ .form-grid{ grid-template-columns:1fr; } }

/* ============ Stage progress track ============ */
.stage-track{ display:flex; align-items:flex-start; gap:4px; margin-top:10px; }
.stage-step{ flex:1; text-align:center; }
.stage-dot{ width:26px; height:26px; border-radius:50%; margin:0 auto 6px; display:flex; align-items:center; justify-content:center;
  font-size:11px; font-weight:700; font-family:var(--font-mono); border:2px solid var(--border-strong); color:var(--text-muted); background:var(--surface-1); }
.stage-step.done .stage-dot{ background:var(--success); border-color:var(--success); color:#fff; }
.stage-step.current .stage-dot{ background:var(--accent); border-color:var(--accent); color:#fff; }
.stage-name{ font-size:10px; color:var(--text-muted); line-height:1.25; }
.stage-step.current .stage-name{ color:var(--text-primary); font-weight:600; }

/* ============ Hours bars ============ */
.hours-list{ display:flex; flex-direction:column; gap:9px; margin-top:8px; }
.hours-row{ display:grid; grid-template-columns:64px 1fr 46px; align-items:center; gap:10px; }
.hours-label{ font-size:11.5px; color:var(--text-secondary); }
.hours-val{ font-family:var(--font-mono); font-size:11px; text-align:right; color:var(--text-muted); }

/* ============ Tabs row (IFF instructor) ============ */
.tabs-row{ display:flex; gap:8px; margin-bottom:14px; flex-wrap:wrap; }

/* ============ Modal ============ */
.modal-backdrop{ position:fixed; inset:0; background:rgba(10,14,25,.5); z-index:50; display:flex; align-items:center; justify-content:center; padding:20px; }
.modal-card{ background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius-lg); padding:22px;
  max-width:420px; width:100%; box-shadow:var(--shadow-md); position:relative; }
.modal-close-x{ position:absolute; top:12px; right:12px; width:30px; height:30px; border-radius:50%;
  border:none; background:transparent; color:var(--text-muted); font-size:20px; line-height:1; cursor:pointer;
  display:flex; align-items:center; justify-content:center; }
.modal-close-x:hover{ background:var(--surface-2); color:var(--text-primary); }
.modal-card h3{ margin:0; font-family:var(--font-display); font-size:15px; }

/* ============ Logbook (FCL.050) ============ */
.logbook-table{ font-size:11px; white-space:nowrap; }
.logbook-table th, .logbook-table td{ padding:6px 8px; text-align:center; }
.logbook-table td:nth-child(21), .logbook-table th:last-child{ text-align:left; white-space:normal; min-width:160px; }
.logbook-table .totals-row td{ font-weight:700; background:var(--surface-2); }
.mono{ font-family:var(--font-mono); }

/* ============ Reservations calendar ============ */
.res-toolbar{ display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap; margin-bottom:18px; }
.res-toolbar-left{ display:flex; gap:8px; }
.res-toolbar-center{ display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.res-toolbar-center input[type="date"]{ padding:7px 10px; border-radius:8px; border:1px solid var(--border-strong);
  background:var(--surface-1); color:var(--text-primary); font-size:13px; }
.res-view-toggle{ display:inline-flex; gap:2px; background:var(--surface-2); border:1px solid var(--border);
  border-radius:9px; padding:4px; margin-left:6px; }
.res-view-toggle button{ padding:7px 14px; font-size:12.5px; font-weight:600; border:none; background:none;
  border-radius:7px; color:var(--text-secondary); cursor:pointer; transition:background .12s, color .12s; }
.res-view-toggle button.active{ background:var(--surface-1); color:var(--accent); box-shadow:var(--shadow-sm); }
.res-toolbar-right{ margin-left:auto; display:flex; align-items:center; }

.res-grid-section{ background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius-lg);
  overflow:hidden; box-shadow:var(--shadow-sm); }
.res-section-title{ font-family:var(--font-display); font-weight:700; font-size:13px; padding:12px 16px;
  border-bottom:1px solid var(--border); background:var(--surface-2); }

.res-hour-row{ display:flex; border-bottom:1px solid var(--border); background:var(--surface-2); }
.res-row-label{ flex:0 0 150px; padding:8px 12px; display:flex; flex-direction:column; justify-content:center; gap:3px;
  border-right:1px solid var(--border); font-size:11px; color:var(--text-muted); }
.res-row-label strong{ font-size:12.5px; color:var(--text-primary); font-weight:650; }
.res-hours{ flex:1; display:flex; }
.res-hour-cell{ flex:1; text-align:center; font-size:10.5px; color:var(--text-muted); padding:8px 2px;
  font-family:var(--font-mono); border-left:1px solid var(--border); }
.res-hour-cell:first-child{ border-left:none; }

.res-rows{ display:flex; flex-direction:column; position:relative; }
.res-row{ display:flex; border-bottom:1px solid var(--border); min-height:78px; }
.res-row:last-child{ border-bottom:none; }
.res-row-track{ flex:1; position:relative; }
.res-gridlines{ position:absolute; inset:0; display:flex; }
.res-grid-cell{ flex:1; border-left:1px solid var(--border); }
.res-grid-cell:first-child{ border-left:none; }

.res-block{ position:absolute; top:6px; bottom:6px; background:var(--success); color:#fff; border-radius:7px;
  padding:6px 9px; font-size:11.5px; line-height:1.45; overflow:hidden; box-shadow:var(--shadow-sm);
  border:1px solid rgba(255,255,255,.25); text-align:center; display:flex; flex-direction:column; justify-content:center; }
.res-block-purpose{ opacity:.85; font-weight:400; }
.res-block-mine{ outline:2px solid var(--accent); outline-offset:-2px; }
.res-block-tail-only{ font-size:14px; font-weight:700; letter-spacing:.02em; }
.res-block-unavailable{ background:repeating-linear-gradient(135deg, var(--danger), var(--danger) 8px, #a3202033 8px, #a3202033 16px);
  color:#fff; font-weight:600; display:flex; align-items:center; justify-content:center; text-align:center; }
html[data-theme="dark"] .res-block-unavailable{ background:repeating-linear-gradient(135deg, var(--danger), var(--danger) 8px, #33181833 8px, #33181833 16px); }
.res-block-aog{ background:repeating-linear-gradient(135deg, var(--danger), var(--danger) 8px, #a3202033 8px, #a3202033 16px);
  color:#fff; font-weight:600; display:flex; align-items:center; justify-content:center; text-align:center; border-color:rgba(255,255,255,.35); }
html[data-theme="dark"] .res-block-aog{ background:repeating-linear-gradient(135deg, var(--danger), var(--danger) 8px, #33181833 8px, #33181833 16px); }
.res-block-aog.res-drag-invalid{ filter:brightness(1.3); }

.res-row-track-editable{ cursor:copy; }
.res-block-editable{ cursor:grab; }
.res-block-editable.res-block-locked{ cursor:pointer; }
.res-block-editable:hover{ filter:brightness(1.12); outline:2px solid rgba(255,255,255,.5); outline-offset:-2px; }
.res-block-editable:active{ cursor:grabbing; }
.res-block-clickable{ cursor:pointer; }
.res-block-clickable:hover{ filter:brightness(1.12); outline:2px solid rgba(255,255,255,.5); outline-offset:-2px; }
.res-block-dragging{ opacity:0.4; }

@media (max-width:880px){
  .res-row-label{ flex-basis:100px; }
  .res-hour-cell{ font-size:9px; }
}

/* ============ CBTA flight reports ============ */
.cbta-chip{ background:var(--surface-2); border:1px solid var(--border); border-radius:var(--radius);
  padding:10px 12px; display:flex; flex-direction:column; gap:2px; }
.cbta-chip.low{ background:var(--warning-bg); border-color:transparent; }
.cbta-chip-code{ font-family:var(--font-mono); font-size:10.5px; font-weight:700; color:var(--text-muted); letter-spacing:.03em; }
.cbta-chip.low .cbta-chip-code{ color:var(--warning); }
.cbta-chip-score{ font-family:var(--font-display); font-size:17px; font-weight:700; }
.cbta-chip-avg{ font-family:var(--font-mono); font-size:11px; font-weight:400; color:var(--text-muted); margin-left:4px; }

.folder-list-native{ display:flex; flex-direction:column; gap:8px; }
.mission-row{ background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius);
  padding:13px 16px; display:flex; justify-content:space-between; align-items:center; gap:12px; cursor:pointer;
  transition:box-shadow .15s, border-color .15s; }
.mission-row:hover{ box-shadow:var(--shadow-md); border-color:var(--border-strong); }
.mission-row-title{ margin:0; font-size:13.5px; font-weight:650; }
.mission-row-right{ display:flex; align-items:center; gap:12px; flex:0 0 auto; }

.cbta-task-section{ background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius);
  overflow:hidden; margin-bottom:10px; }
.cbta-task-header{ background:var(--surface-2); font-size:11px; font-weight:700; text-transform:uppercase;
  letter-spacing:.05em; padding:8px 14px; color:var(--text-secondary); }
.cbta-task-row{ display:flex; justify-content:space-between; gap:10px; padding:8px 14px; font-size:12.5px;
  border-top:1px solid var(--border); }
.cbta-task-row:first-of-type{ border-top:none; }

.cbta-comp-block{ background:var(--surface-1); border:1px solid var(--border); border-radius:var(--radius-lg);
  padding:16px 18px; margin-bottom:12px; }
.cbta-comp-head{ display:flex; align-items:center; gap:12px; }
.cbta-comp-dot{ flex:0 0 auto; width:32px; height:32px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  font-family:var(--font-display); font-weight:700; font-size:14px; border:2px solid var(--success); color:var(--success); }
.cbta-comp-dot.low{ border-color:var(--warning); color:var(--warning); }
.cbta-comp-dot-input{ flex:0 0 auto; width:44px; height:36px; border-radius:10px; text-align:center;
  font-family:var(--font-display); font-weight:700; font-size:15px; border:2px solid var(--success); color:var(--success);
  background:var(--surface-1); padding:0; }
.cbta-comp-dot-input.low{ border-color:var(--warning); color:var(--warning); }
.cbta-comp-code{ margin:0; font-size:13px; font-weight:700; letter-spacing:.02em; }
.cbta-comp-note{ font-size:12px; color:var(--warning); font-style:italic; margin:8px 0 4px; }

.cbta-banner{ margin-top:20px; text-align:center; font-family:var(--font-display); font-weight:700; font-size:14px;
  letter-spacing:.03em; padding:14px; border-radius:var(--radius-lg); color:#fff; }
.cbta-banner.success{ background:var(--success); }
.cbta-banner.warning{ background:var(--warning); }

/* ============ Donut charts (student dashboard) ============ */
.donut-row{ display:flex; gap:22px; flex-wrap:wrap; margin-top:10px; }
.donut-block{ flex:1 1 140px; min-width:140px; text-align:center; }
.donut-block svg{ display:block; margin:0 auto; }
.donut-seg{ transition:stroke-dashoffset 1.1s cubic-bezier(.3,0,.15,1); }
.donut-title{ font-size:12px; font-weight:600; color:var(--text-secondary); margin:8px 0 10px; }
.donut-legend{ display:flex; flex-direction:column; gap:5px; text-align:left; }
.donut-legend-row{ display:flex; align-items:center; gap:7px; font-size:11.5px; }
.donut-legend-dot{ width:8px; height:8px; border-radius:50%; flex:0 0 auto; }
.donut-legend-label{ flex:1; color:var(--text-secondary); }
.donut-legend-val{ font-family:var(--font-mono); font-size:10.5px; font-weight:600; white-space:nowrap; }

/* ============ Custom mouse-drag (reservations) ============ */
/* Invalid drag/resize target: red and more transparent, restored on drop by re-render */
.res-block.res-drag-invalid{ background:var(--danger) !important; opacity:0.55; }

/* Resize handles — invisible hit-areas at each edge with a hover-animated grip */
.res-resize-handle{ position:absolute; top:0; bottom:0; width:10px; cursor:ew-resize; z-index:5; }
.res-resize-left{ left:0; }
.res-resize-right{ right:0; }
.res-resize-handle::after{ content:''; position:absolute; top:50%; left:50%; width:3px; height:55%;
  background:rgba(255,255,255,.95); border-radius:2px; transform:translate(-50%,-50%) scaleY(.25); opacity:0;
  transition:opacity .15s ease, transform .15s ease; }
.res-block:hover .res-resize-handle::after{ opacity:.45; transform:translate(-50%,-50%) scaleY(.7); }
.res-resize-handle:hover::after{ opacity:1 !important; transform:translate(-50%,-50%) scaleY(1) !important; }

/* ============ Conflict indicator ============ */
.res-block-conflict{ outline:2px solid var(--danger); outline-offset:-2px; }
.res-conflict-icon{ display:block; font-size:12px; margin-bottom:2px; }

/* ============ Aircraft capability tags (read-only display) ============
   IFR/AUPRT-style approval tags, shown on Reservations and Fleet status.
   Standby (grey) is set deliberately from Fleet status' Edit modal — see
   openFleetEditModal in app.js — not by clicking the badge itself, to
   avoid accidentally changing an aircraft's operational state. */
.res-row-tags{ display:flex; flex-wrap:wrap; gap:4px; }
.tag-badge{ display:inline-flex; align-items:center; font-family:var(--font-mono); font-size:9px; font-weight:700;
  letter-spacing:.03em; padding:2px 6px; border-radius:5px; background:var(--accent-bg); color:var(--accent);
  border:1px solid transparent; }
.tag-badge.standby{ background:var(--surface-2); color:var(--text-muted); border-color:var(--border-strong); }

/* ============ AOG quick-toggle (reservations row label) ============ */
.res-aog-toggle{ align-self:flex-start; font-family:var(--font-mono); font-size:9px; font-weight:700;
  letter-spacing:.03em; padding:2px 7px; border-radius:5px; border:1px solid var(--border-strong);
  background:var(--surface-1); color:var(--text-muted); cursor:pointer; }
.res-aog-toggle:hover{ border-color:var(--danger); color:var(--danger); }
.res-aog-toggle.active{ background:var(--danger-bg); color:var(--danger); border-color:transparent; }

/* ============ Gauge chart (Fleet Status maintenance hours) ============ */
#fleet-cards [id^="gauge-"]{ position:relative; display:inline-block; }
.gauge-fg{ transition:stroke-dashoffset 1.1s cubic-bezier(.3,0,.15,1); }
.gauge-center{ position:absolute; left:50%; top:62%; transform:translate(-50%,-50%); text-align:center; }
.gauge-value{ font-family:var(--font-mono); font-size:11px; font-weight:600; color:var(--text-secondary); white-space:nowrap; }
.gauge-aog{ font-family:var(--font-display); font-size:19px; font-weight:800; color:var(--danger); letter-spacing:.03em;
  display:inline-block; position:relative; top:-8px; }

/* ============ Sidebar collapse/expand ============ */
.sidebar{ transition:flex-basis .28s cubic-bezier(.4,0,.2,1), width .28s cubic-bezier(.4,0,.2,1); position:sticky; }
.sidebar-collapse-btn{ position:absolute; top:74px; right:-12px; width:24px; height:24px; border-radius:50%;
  background:var(--tf-side-active); border:1px solid var(--tf-side-border); color:var(--tf-side-text);
  display:flex; align-items:center; justify-content:center; cursor:pointer; z-index:31; font-size:13px;
  box-shadow:var(--shadow-sm); transition:background .15s; }
.sidebar-collapse-btn:hover{ background:var(--accent); color:#fff; border-color:var(--accent); }

.brand-logo-icon{ display:none; }
.sidebar.collapsed{ width:76px; flex-basis:76px; }
.sidebar.collapsed .brand{ justify-content:center; padding:24px 0 20px; }
.sidebar.collapsed .brand-logo-full{ display:none; }
.sidebar.collapsed .brand-logo-icon{ display:block; height:30px; width:auto; }
.sidebar.collapsed .identity{ margin:0 10px 14px; padding:10px; display:flex; justify-content:center; }
.sidebar.collapsed .identity-row{ gap:0; }
.sidebar.collapsed .identity-row > div:not(.identity-avatar){ display:none; }
.sidebar.collapsed .identity-badge{ display:none; }
.sidebar.collapsed .nav{ padding-left:10px; padding-right:10px; }
.sidebar.collapsed .nav-strip{ justify-content:center; padding:10px; }
.sidebar.collapsed .nav-strip-label{ display:none; }
.sidebar.collapsed .nav-strip-count{ position:absolute; top:4px; right:4px; transform:scale(.85); }
.sidebar.collapsed .nav-strip{ position:relative; }
.sidebar.collapsed .sidebar-footer{ padding:12px 10px 18px; }
.sidebar.collapsed .logout-btn{ justify-content:center; padding:9px; }
.sidebar.collapsed .logout-label{ display:none; }

@media (max-width:880px){
  .sidebar-collapse-btn{ display:none; } /* mobile uses the slide-over pattern instead */
}

/* ============ Day-range control ============ */
.res-range-control{ display:flex; align-items:center; gap:6px; font-size:11.5px; color:var(--text-secondary);
  margin-right:14px; white-space:nowrap; }
.res-range-control input[type="time"]{ padding:5px 7px; border-radius:6px; border:1px solid var(--border-strong);
  background:var(--surface-1); color:var(--text-primary); font-size:12px; width:auto; }

/* ============ Non-blocking warning toasts ============ */
#tf-toast-container{ position:fixed; top:18px; left:50%; transform:translateX(-50%); z-index:200;
  display:flex; flex-direction:column; gap:8px; align-items:center; pointer-events:none; }
.tf-toast{ pointer-events:auto; background:var(--warning-bg); color:var(--warning); border:1px solid var(--warning);
  border-radius:10px; padding:12px 20px; font-size:13px; font-weight:600; max-width:440px; text-align:center;
  white-space:pre-line; box-shadow:var(--shadow-md); opacity:0; transform:translateY(-14px);
  transition:opacity .2s ease, transform .2s ease; cursor:pointer; }
.tf-toast-visible{ opacity:1; transform:translateY(0); }
