/* ── RESET & BASE ─────────────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{font-size:var(--text-md);-webkit-text-size-adjust:100%}
body{font-family:'Inter',system-ui,-apple-system,sans-serif;background:#eef2f9;background-image:radial-gradient(700px 380px at 8% -10%,rgba(47,111,224,.12),transparent 60%),radial-gradient(600px 380px at 108% 0,rgba(18,178,106,.10),transparent 55%);background-attachment:fixed;color:#1e293b;line-height:1.5;min-height:100vh;-webkit-font-smoothing:antialiased}
a{color:inherit;text-decoration:none}
button{cursor:pointer;font-family:inherit}
input,select,textarea{font-family:inherit}
img{max-width:100%;display:block}

/* ── CSS VARIABLES ────────────────────────────────────────────────────────── */
:root{
  --brand:#1a3c5e;
  --brand-light:#2d6a9f;
  --brand-dark:#12293f;
  --accent:#f0a500;
  --accent-light:#fef3c7;
  --white:#ffffff;
  --black:#0f172a;
  --grey-50:#f8fafc;
  --grey-100:#f1f5f9;
  --grey-200:#e2e8f0;
  --grey-300:#cbd5e1;
  --grey-400:#94a3b8;
  --grey-500:#64748b;
  --grey-600:#475569;
  --grey-700:#334155;
  --grey-800:#1e293b;
  --grey-900:#0f172a;
  --green:#16a34a;
  --green-light:#dcfce7;
  --red:#dc2626;
  --red-light:#fee2e2;
  --yellow:#d97706;
  --yellow-light:#fef3c7;
  --blue:#2563eb;
  --blue-light:#dbeafe;
  --sidebar-w:240px;
  --topbar-h:60px;
  --radius-sm:6px;
  --radius:10px;
  --radius-lg:14px;
  --radius-xl:20px;
  /* Dashboard visual refresh — chart/accent palette (charts + KPI accents; the
     navy --brand stays the shell brand). Soft cool-tinted shadows are SHARED
     tokens, so the lift applies app-wide (deliberate). */
  --c-blue:#2f6fe0;
  --c-blue-deep:#1e50c8;
  --c-green:#2f9e34;
  --c-emerald:#12b26a;
  --c-amber:#e0972a;
  --c-red:#e2504a;
  --c-purple:#5a4fd0;
  --ink:#16233b;
  --muted:#68758c;
  --line:rgba(20,40,80,.08);
  --shadow-sm:0 1px 3px rgba(20,40,80,.05);
  --shadow:0 8px 24px rgba(20,40,80,.09);
  --shadow-lg:0 10px 30px rgba(0,0,0,.1),0 4px 10px rgba(0,0,0,.06);
  --transition:.18s ease;
  --transition-slow:.3s ease;
  --transition-fast:.1s ease;
  /* --navy is the brand under an older name: ~17 portal rules and a number of
     inline styles read var(--navy,#1a3c5e). Every theme block below therefore
     sets --navy to the SAME value as --brand, so those call sites follow the
     theme without editing each one.
     Deliberately a LITERAL per theme rather than the tidier
     `--navy: var(--brand)`. Both work, but the alias adds a var()->var() hop
     for no benefit, and while chasing a repaint problem here it was one more
     indirection to rule out. (The repaint problem turned out to be style
     invalidation, not the alias — SettingsPage.applyTheme forces a recalc; see
     the note there.) Keep --navy in step with --brand in every block below. */
  --navy:#1a3c5e;
  --radius-2xl:24px;
  --shadow-xl:0 20px 60px rgba(0,0,0,.12),0 8px 20px rgba(0,0,0,.08);
  /* ── TYPE SCALE ───────────────────────────────────────────────────────────
     SIX steps, each with a job. Replaces 47 distinct sizes in this file and
     48 in the page JS — a band so narrow (.78 / .8 / .82 / .84) that the
     sizes are visually indistinguishable while still shifting line-height and
     baselines, which is why rows never quite aligned and card density drifted
     page to page.

     THE FLOOR IS 12px. The app was too SMALL, not too large: 224 page-JS and
     66 main.css declarations sat below 12px (down to 8.8px). Everything under
     the floor moves UP to --text-xs. That growth is deliberate and is the one
     visible change this pass is allowed to make.

     THE MAPPING (apply this rule everywhere, including PR 2 — do not re-decide
     per file):
        < 12.0px            -> --text-xs     (the floor; grows)
        12.0 - 12.4px       -> --text-xs
        12.5 - 13.5px       -> --text-sm
        13.6 - 15.0px       -> --text-base
        15.1 - 17.0px       -> --text-md
        17.1 - 22.0px       -> --text-lg
        > 22.0px (TEXT)     -> --text-xl

     CARVE-OUT — decorative glyphs are NOT type. font-size is also how this app
     sizes emoji and icon characters (.pp-msg-icon, .pp-empty-icon,
     .pp-avatar-init, .splash-logo, empty-state emoji). Those are graphics
     drawn with a glyph; snapping them to a text step would resize artwork for
     no reason. They keep their literal sizes and are exempt from the guard
     test. Only text takes a token. */
  --text-xs:0.75rem;      /* 12px — micro-labels, column labels, badges       */
  --text-sm:0.8125rem;    /* 13px — secondary/meta text, helper copy          */
  --text-base:0.875rem;   /* 14px — body, table cells, form fields (workhorse)*/
  --text-md:1rem;         /* 16px — card titles, section headings             */
  --text-lg:1.25rem;      /* 20px — page titles                               */
  --text-xl:1.75rem;      /* 28px — KPI numbers / hero figures                */

  /* Line-height travels WITH size: inconsistent leading misaligns rows just as
     badly as inconsistent size. Tight for headings/figures where the box is
     sized to the text; normal for anything that can wrap. */
  --leading-tight:1.2;
  --leading-normal:1.5;

  /* ── SPACING SCALE (4px base) ─────────────────────────────────────────────
     Replaces 54 hand-picked values in this file. Card padding, form gaps,
     table cell padding and section margins all snap to these. Sub-4px values
     (hairline offsets, .1rem letter-spacing-ish nudges) are left alone —
     they are optical adjustments, not layout spacing. */
  --space-1:4px;
  --space-2:8px;
  --space-3:12px;
  --space-4:16px;
  --space-5:24px;
  --space-6:32px;

  /* Radii were equally ad hoc — 14 distinct values. --radius/-sm/-lg already
     existed; these fill the gaps the sweep found. --radius-pill replaces the
     99px/999px pair used for pills and chips. */
  --radius-md:12px;
  --radius-pill:999px;
  --content-max:1400px;
}

/* ── ACCENT THEMES (light only) ─────────────────────────────────────────────
   Applied via data-theme on <html>; index.html sets it BEFORE first paint from
   localStorage, so there is no flash of the default palette.

   Each theme overrides ONLY the brand/accent family. Greys and the semantic
   colours (green/red/yellow/blue, --c-amber, the AI panel's warn amber) are
   deliberately SHARED: a warning must look like a warning in every theme, and
   only the brand identity changes. DARK MODE IS NOT HERE — it needs a full
   tokenisation of ~1,000 colours and is deferred.

   CONTRAST IS A HARD REQUIREMENT, verified not assumed. The sidebar is a solid
   --brand fill with white text and primary buttons are --brand on white, so
   every --brand below clears WCAG AA 4.5:1 against #fff:
     default #1a3c5e 11.34   ocean #2f6fe0 4.70   emerald #12694f 6.65
     indigo  #4f46e5  6.29   slate #334155 10.35
   Ocean is the thinnest margin (4.70) — it passes, but do not darken the text
   or lighten that blue without re-checking. --accent is used for small
   highlights and NEVER as a background for white body text (gold on white is
   2.08:1), which is why it is exempt from the 4.5 bar. */
:root[data-theme="ocean"] {
  --brand:#2f6fe0;        /* the logo blue */
  --navy:#2f6fe0;        /* legacy alias of --brand; literal, see the note in :root */
  --brand-light:#5b8ef0;
  --brand-dark:#1e50c8;
  --accent:#06b6d4;       /* cooler accent than the default gold */
  --accent-light:#cffafe;
}
:root[data-theme="emerald"] {
  --brand:#12694f;
  --navy:#12694f;        /* legacy alias of --brand; literal, see the note in :root */
  --brand-light:#189c76;
  --brand-dark:#0c4a38;
  --accent:#12b26a;       /* the logo green */
  --accent-light:#d1fae5;
}
:root[data-theme="indigo"] {
  --brand:#4f46e5;
  --navy:#4f46e5;        /* legacy alias of --brand; literal, see the note in :root */
  --brand-light:#7c74f0;
  --brand-dark:#3730a3;
  --accent:#8b5cf6;
  --accent-light:#ede9fe;
}
:root[data-theme="slate"] {
  --brand:#334155;        /* near-neutral, for schools wanting understatement */
  --navy:#334155;        /* legacy alias of --brand; literal, see the note in :root */
  --brand-light:#475569;
  --brand-dark:#1e293b;
  --accent:#0ea5e9;
  --accent-light:#e0f2fe;
}
/* data-theme="default" (or absent) uses the :root values above — existing
   users see no change unless they choose otherwise. */

/* Theme swatches (Settings → Appearance). Each swatch previews its own palette
   using the literal hexes, because a swatch must show the theme it OFFERS, not
   the theme currently active. */
.theme-swatches{display:flex;gap:.75rem;flex-wrap:wrap}
.theme-swatch{position:relative;display:flex;flex-direction:column;align-items:center;gap:.45rem;background:none;border:none;padding:0;cursor:pointer;font:inherit}
.theme-swatch-chip{width:56px;height:56px;border-radius:14px;border:2px solid var(--grey-200);display:block;position:relative;overflow:hidden;transition:transform .15s,border-color .15s,box-shadow .15s}
.theme-swatch:hover .theme-swatch-chip{transform:translateY(-2px);box-shadow:var(--shadow)}
.theme-swatch[aria-pressed="true"] .theme-swatch-chip{border-color:var(--grey-800);box-shadow:0 0 0 3px var(--grey-100)}
.theme-swatch-chip::after{content:"";position:absolute;right:0;bottom:0;width:50%;height:50%;border-top-left-radius:12px}
.theme-swatch-name{font-size:var(--text-xs);font-weight:600;color:var(--grey-600)}
.theme-swatch[aria-pressed="true"] .theme-swatch-name{color:var(--grey-900);font-weight:700}
.theme-swatch-tick{position:absolute;top:-4px;right:-4px;width:18px;height:18px;border-radius:50%;background:var(--green);color:#fff;font-size:var(--text-xs);display:none;align-items:center;justify-content:center;font-weight:700}
.theme-swatch[aria-pressed="true"] .theme-swatch-tick{display:flex}

/* ── SPLASH SCREEN ────────────────────────────────────────────────────────── */
.splash-screen{position:fixed;inset:0;background:var(--brand);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2rem;z-index:9999;transition:opacity .4s ease}
/* The splash carries the SCHOOL's name once a session exists, and nothing at
   all before that — never the platform's mark (see index.html). */
.splash-school{color:var(--white);font-size:var(--text-lg);font-weight:800;letter-spacing:-.2px;text-align:center;padding:0 var(--space-4);max-width:22rem}
.splash-screen.hidden{opacity:0;pointer-events:none}
.splash-logo{display:flex;align-items:center;gap:.75rem;color:white;font-size:1.75rem;font-weight:700;letter-spacing:-.02em}
.splash-loader{width:180px;height:3px;background:rgba(255,255,255,.15);border-radius:99px;overflow:hidden}
.loader-bar{height:100%;background:var(--accent);border-radius:99px;animation:load 1.8s ease-in-out infinite}
@keyframes load{0%{width:0;margin-left:0}50%{width:60%;margin-left:20%}100%{width:0;margin-left:100%}}

/* ── LAYOUT ───────────────────────────────────────────────────────────────── */
.app-layout{display:flex;min-height:100vh}
.sidebar{position:fixed;top:0;left:0;width:var(--sidebar-w);height:100vh;height:100dvh;background:linear-gradient(180deg,var(--brand),#142f4a);display:flex;flex-direction:column;z-index:100;transition:transform var(--transition);overflow:hidden}
.main-content{margin-left:var(--sidebar-w);flex:1;min-width:0;display:flex;flex-direction:column;min-height:100vh}
.topbar{height:var(--topbar-h);background:rgba(255,255,255,.85);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border-bottom:1px solid var(--line);display:flex;align-items:center;padding:0 1.5rem;gap:1rem;position:sticky;top:0;z-index:50;box-shadow:var(--shadow-sm)}
.page-content{flex:1;padding:1.75rem;max-width:1400px;width:100%}

/* ── SIDEBAR COMPONENTS ───────────────────────────────────────────────────── */
.sidebar-brand{padding:1.25rem 1.2rem;display:flex;align-items:center;gap:.75rem;border-bottom:1px solid rgba(255,255,255,.08)}
/* THE SCHOOL'S MARK — the sidebar is dark and a school logo is typically dark
   text on transparent, so it sits on a WHITE ROUNDED CHIP or it would be
   invisible. Same reasoning as the report-card PDF's logo chip. Verified with
   both a dark-text and a light logo. */
.school-logo-chip{background:var(--white);border-radius:var(--radius-md);padding:var(--space-2) var(--space-3);display:flex;align-items:center;justify-content:center;width:100%;min-height:52px;box-shadow:0 1px 3px rgba(0,0,0,.18)}
.school-logo-chip img{max-width:100%;max-height:40px;width:auto;height:auto;object-fit:contain;display:block}
/* No-logo fallback: initials chip + the school's name. Never the platform mark,
   never an empty gap. */
.school-name-mark{display:flex;align-items:center;gap:var(--space-2);min-width:0;width:100%}
.school-initials{flex-shrink:0;width:34px;height:34px;border-radius:var(--radius-md);background:var(--white);color:var(--brand);font-size:var(--text-sm);font-weight:800;display:flex;align-items:center;justify-content:center;letter-spacing:.5px}
.school-name{color:var(--white);font-size:var(--text-base);font-weight:700;line-height:var(--leading-tight);overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;word-break:break-word}
.sidebar-brand-logo{width:36px;height:36px;flex-shrink:0}
.sidebar-brand-text{color:white}
.sidebar-brand-text h1{font-size:var(--text-md);font-weight:700;line-height:1.2}
.sidebar-brand-text p{font-size:var(--text-xs);color:rgba(255,255,255,.45);margin-top:.1rem}
.sidebar-nav{padding:.75rem 0;flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}
.nav-section-label{padding:.5rem 1.2rem .3rem;font-size:var(--text-xs);font-weight:700;letter-spacing:.08em;color:rgba(255,255,255,.3);text-transform:uppercase}
/* Rounded pill highlight (visual refresh) — replaces the flat left-border bar.
   Margin/radius on the BASE item so hover and active align identically. */
.nav-item{display:flex;align-items:center;gap:.65rem;padding:.6rem .95rem;margin:1px .6rem;border-radius:12px;color:rgba(255,255,255,.7);font-size:var(--text-sm);font-weight:500;transition:all var(--transition);cursor:pointer;user-select:none}
.nav-item:hover{background:rgba(255,255,255,.07);color:white}
.nav-item.active{background:rgba(255,255,255,.14);color:white}
.nav-item svg{width:18px;height:18px;flex-shrink:0;opacity:.8}
.nav-item.active svg{opacity:1}
.nav-item .badge{margin-left:auto;background:var(--accent);color:#1a1a1a;font-size:var(--text-xs);font-weight:700;padding:1px 7px;border-radius:99px;min-width:20px;text-align:center}
.sidebar-footer{padding:1rem 1.2rem;border-top:1px solid rgba(255,255,255,.08);margin-top:auto}
/* PASS 6: polished sidebar profile block (sidebar-only classes) */
.user-chip{display:flex;align-items:center;gap:.7rem;margin-bottom:.7rem;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:.6rem .7rem}
.user-avatar{width:38px;height:38px;border-radius:50%;background:var(--accent);display:flex;align-items:center;justify-content:center;font-weight:800;font-size:var(--text-base);color:#1a1a1a;flex-shrink:0;border:2px solid rgba(255,255,255,.18);box-shadow:0 2px 8px rgba(0,0,0,.22)}
.user-info{flex:1;min-width:0}
.user-name{font-size:var(--text-base);font-weight:700;color:white;letter-spacing:-.1px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
.user-role{font-size:var(--text-xs);color:rgba(255,255,255,.5);text-transform:capitalize;letter-spacing:.2px;margin-top:.05rem}
.btn-signout{width:100%;display:flex;align-items:center;justify-content:center;gap:.45rem;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.12);color:rgba(255,255,255,.75);padding:.55rem;border-radius:10px;font-size:var(--text-sm);font-weight:600;cursor:pointer;transition:background var(--transition),color var(--transition),border-color var(--transition)}
.btn-signout:hover{background:rgba(255,255,255,.13);color:white;border-color:rgba(255,255,255,.2)}

/* ── TOPBAR COMPONENTS ────────────────────────────────────────────────────── */
.topbar-left{display:flex;align-items:center;gap:.75rem;flex:1}
.topbar-title{font-size:var(--text-md);font-weight:600;color:var(--grey-800)}
.topbar-breadcrumb{display:flex;align-items:center;gap:.4rem;font-size:var(--text-sm);color:var(--grey-500)}
.topbar-breadcrumb span{color:var(--grey-300)}
.topbar-right{display:flex;align-items:center;gap:.5rem}
.topbar-btn{width:36px;height:36px;border:none;background:var(--grey-100);border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;color:var(--grey-600);transition:all var(--transition);position:relative}
.topbar-btn:hover{background:var(--grey-200);color:var(--grey-800)}
.topbar-btn .notif-dot{position:absolute;top:7px;right:7px;width:7px;height:7px;background:var(--red);border-radius:50%;border:2px solid white}
.back-btn{display:flex;align-items:center;gap:.4rem;font-size:var(--text-sm);color:var(--grey-500);background:none;border:none;padding:.35rem .6rem;border-radius:var(--radius-sm);transition:all var(--transition)}
.back-btn:hover{background:var(--grey-100);color:var(--grey-800)}

/* ── CARDS ────────────────────────────────────────────────────────────────── */
.card{background:white;border:1px solid var(--line);border-radius:18px;padding:1.4rem 1.5rem;box-shadow:var(--shadow-sm);transition:all var(--transition)}
.card:hover{box-shadow:0 4px 14px rgba(20,40,80,.07)}
.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.25rem;padding-bottom:1rem;border-bottom:1px solid var(--grey-100)}
.card-title{font-size:var(--text-md);font-weight:600;color:var(--grey-800);display:flex;align-items:center;gap:.5rem}
.card-title svg{color:var(--brand)}

/* ── KPI CARDS ────────────────────────────────────────────────────────────── */
.kpi-grid{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:.85rem;margin-bottom:1.5rem;overflow-x:auto}
/* Dashboard KPIs: lay out over two roomy rows of three rather than one squeezed row of six. */
.kpi-grid-dash{grid-template-columns:repeat(3,minmax(0,1fr));overflow-x:visible;gap:14px}
/* Dashboard visual refresh — icon-on-top KPI cards, DASH-SCOPED so other pages'
   inline KPI rows keep their compact horizontal layout. No HTML change. */
.kpi-grid-dash .kpi-card{flex-direction:column;align-items:flex-start;gap:.6rem;padding:1rem 1.1rem;border-radius:16px}
.kpi-grid-dash .kpi-card:hover{transform:translateY(-2px);box-shadow:var(--shadow)}
.kpi-grid-dash .kpi-icon{width:44px;height:44px;border-radius:12px}
.kpi-grid-dash .kpi-value{font-size:var(--text-xl);font-weight:800;letter-spacing:-.5px}
.kpi-grid-dash .kpi-label{font-size:var(--text-sm);color:var(--grey-500);font-weight:500}
/* Outstanding gets a faint danger tint (cosmetic emphasis, keyed off its red icon). */
.kpi-grid-dash .kpi-card:has(.kpi-icon.red){background:#fef5f5;border-color:#f3cccc}
.kpi-card{background:white;border:1px solid var(--grey-200);border-radius:var(--radius-lg);padding:.85rem 1rem;box-shadow:var(--shadow-sm);display:flex;align-items:center;gap:.65rem;transition:all var(--transition);min-width:0}
.kpi-card:hover{box-shadow:var(--shadow);transform:translateY(-1px)}
.kpi-icon{width:40px;height:40px;border-radius:var(--radius);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.kpi-icon.blue{background:var(--blue-light);color:var(--blue)}
.kpi-icon.green{background:var(--green-light);color:var(--green)}
.kpi-icon.yellow{background:var(--yellow-light);color:var(--yellow)}
.kpi-icon.red{background:var(--red-light);color:var(--red)}
.kpi-icon.brand{background:#e8f0f7;color:var(--brand)}
.kpi-body{flex:1;min-width:0}
.kpi-value{font-size:var(--text-lg);font-weight:700;color:var(--grey-900);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.kpi-label{font-size:var(--text-sm);color:var(--grey-500);margin-top:.15rem}
.kpi-trend{font-size:var(--text-xs);font-weight:600;margin-top:.3rem}
.kpi-trend.up{color:var(--green)}
.kpi-trend.down{color:var(--red)}

/* ── BUTTONS ──────────────────────────────────────────────────────────────── */
.btn{display:inline-flex;align-items:center;gap:.45rem;padding:.5rem 1.1rem;border-radius:var(--radius-sm);font-size:var(--text-base);font-weight:600;border:none;transition:all var(--transition);white-space:nowrap;cursor:pointer}
.btn:disabled{opacity:.55;cursor:not-allowed}
.btn-primary{background:var(--brand);color:white}
.btn-primary:hover:not(:disabled){background:var(--brand-dark);transform:translateY(-1px);box-shadow:0 2px 8px rgba(26,60,94,.25)}
.btn-accent{background:var(--accent);color:#1a1a1a}
.btn-accent:hover:not(:disabled){background:#d4920a;transform:translateY(-1px);box-shadow:0 2px 8px rgba(240,165,0,.25)}
.btn-secondary{background:var(--grey-100);color:var(--grey-700);border:1px solid var(--grey-200)}
.btn-secondary:hover:not(:disabled){background:var(--grey-200);border-color:var(--grey-300);transform:translateY(-1px)}
.btn-danger{background:var(--red-light);color:var(--red);border:1px solid #fecaca}
.btn-danger:hover:not(:disabled){background:#fecaca;border-color:var(--red);transform:translateY(-1px)}
.btn-ghost{background:none;color:var(--grey-600)}
.btn-ghost:hover:not(:disabled){background:var(--grey-100);transform:translateY(-1px)}
.btn-sm{padding:.35rem .75rem;font-size:var(--text-sm)}
.btn-lg{padding:.7rem 1.5rem;font-size:var(--text-md)}
.btn-icon{padding:.5rem;border-radius:var(--radius-sm);background:var(--grey-100);color:var(--grey-600);border:none;display:inline-flex;align-items:center;justify-content:center;transition:all var(--transition)}
.btn-icon:hover{background:var(--grey-200);color:var(--grey-800);transform:scale(1.05)}

/* ── FORMS ────────────────────────────────────────────────────────────────── */
.form-group{margin-bottom:1.1rem}
.form-label{display:block;font-size:var(--text-sm);font-weight:600;color:var(--grey-700);margin-bottom:.4rem}
.form-label .required{color:var(--red);margin-left:.2rem}
.form-control{width:100%;padding:.6rem .85rem;border:1.5px solid var(--grey-200);border-radius:var(--radius-sm);font-size:var(--text-base);color:var(--grey-800);background:white;transition:border-color var(--transition),box-shadow var(--transition);-webkit-appearance:none}
.form-control:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(26,60,94,.1)}
.form-control.error{border-color:var(--red)}
.form-control:disabled,.form-control[readonly]{background:var(--grey-50);color:var(--grey-500);cursor:not-allowed}

/* ── PASSWORD FIELD + REVEAL (Components.passwordField) ───────────────────── */
/* Edge draws its OWN reveal (::-ms-reveal) once the field has content and
   focus. Left alone that is two eyes side by side, and it is also the reason
   the control looked like it "sometimes" existed — it was Edge's, not ours.
   Suppressed so there is exactly one, on every browser. */
input[type=password]::-ms-reveal,
input[type=password]::-ms-clear{display:none}
.pwd-field{position:relative;display:block}
/* Right padding clears BOTH our button and the browser/password-manager key
   icon, which is drawn inside the field — otherwise the two overlap. */
.pwd-field .pwd-input{padding-right:3.25rem}
.pwd-toggle{position:absolute;top:0;right:0;height:100%;width:44px;min-height:44px;display:flex;align-items:center;justify-content:center;background:none;border:0;padding:0;cursor:pointer;color:var(--grey-400);border-radius:var(--radius-sm);-webkit-tap-highlight-color:transparent}
.pwd-toggle:hover{color:var(--grey-600)}
.pwd-toggle:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
.pwd-toggle svg{display:block;pointer-events:none}
select.form-control{padding:.55rem .85rem}
textarea.form-control{min-height:90px;resize:vertical}
.form-hint{font-size:var(--text-xs);color:var(--grey-400);margin-top:.3rem}
.form-error{font-size:var(--text-xs);color:var(--red);margin-top:.3rem;display:flex;align-items:center;gap:.3rem}
.input-group{display:flex}
.input-prefix{padding:.6rem .85rem;background:var(--grey-100);border:1.5px solid var(--grey-200);border-right:none;border-radius:var(--radius-sm) 0 0 var(--radius-sm);font-size:var(--text-base);color:var(--grey-500);white-space:nowrap;display:flex;align-items:center}
.input-group .form-control{border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
.form-grid.cols-3{grid-template-columns:1fr 1fr 1fr}
.form-grid.full{grid-column:1/-1}

/* ── TABLES ───────────────────────────────────────────────────────────────── */
.table-wrapper{overflow-x:auto;border-radius:var(--radius-lg);border:1px solid var(--grey-200)}
/* A genuinely wide table scrolls inside .table-wrapper at tablet widths — but
   the min-width MUST release when ≤480px stacks rows into cards, or every
   card is forced to the table's min-width and the whole page scrolls sideways.
   Use this class instead of an inline min-width on any .data-table. */
.table-wide{width:100%;min-width:900px}
@media(max-width:480px){.table-wide{min-width:0}}
.data-table{width:100%;border-collapse:collapse;font-size:var(--text-base)}
.data-table th{background:var(--grey-50);padding:.7rem 1rem;text-align:left;font-size:var(--text-xs);font-weight:700;color:var(--grey-500);text-transform:uppercase;letter-spacing:.05em;border-bottom:2px solid var(--grey-200);white-space:nowrap}
.data-table td{padding:.75rem 1rem;border-bottom:1px solid var(--grey-100);vertical-align:middle;color:var(--grey-700)}
.data-table tr:last-child td{border-bottom:none}
.data-table tr:hover td{background:var(--grey-50)}
.data-table .actions{display:flex;align-items:center;gap:.5rem}

/* ── TOUCH-FRIENDLY FORM ELEMENTS ───────────────────────────────────────── */
input[type="checkbox"],
input[type="radio"] {
  width: 20px;
  height: 20px;
  cursor: pointer;
  margin: 12px;
}
input[type="checkbox"] + label,
input[type="radio"] + label {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  cursor: pointer;
  min-height: 48px;
  padding: 0.5rem;
  font-size: var(--text-md);
  color: var(--grey-700);
}
input[type="checkbox"]:focus,
input[type="radio"]:focus {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* ── TOUCH FEEDBACK ─────────────────────────────────────────────────────── */
.btn:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: 0 1px 3px rgba(0,0,0,.12);
}
.data-row:active, .list-item:active {
  background: var(--grey-100);
}

/* ── BADGES ───────────────────────────────────────────────────────────────── */
.badge{display:inline-flex;align-items:center;padding:2px 10px;border-radius:99px;font-size:var(--text-xs);font-weight:700;text-transform:uppercase;letter-spacing:.03em;white-space:nowrap}
.badge-green{background:var(--green-light);color:var(--green)}
.badge-red{background:var(--red-light);color:var(--red)}
.badge-yellow{background:var(--yellow-light);color:var(--yellow)}
.badge-blue{background:var(--blue-light);color:var(--blue)}
.badge-grey{background:var(--grey-100);color:var(--grey-600)}
.badge-brand{background:#e8f0f7;color:var(--brand)}

/* ── ALERTS ───────────────────────────────────────────────────────────────── */
.alert{padding:.85rem 1rem;border-radius:var(--radius-sm);font-size:var(--text-base);display:flex;align-items:flex-start;gap:.65rem;margin-bottom:1rem}
.alert svg{flex-shrink:0;margin-top:.1rem}
.alert-success{background:var(--green-light);color:#166534;border:1px solid #bbf7d0}
.alert-danger{background:var(--red-light);color:#991b1b;border:1px solid #fecaca}
.alert-warning{background:var(--yellow-light);color:#92400e;border:1px solid #fde68a}
.alert-info{background:var(--blue-light);color:#1e40af;border:1px solid #bfdbfe}

/* ── MODALS ───────────────────────────────────────────────────────────────── */
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:500;display:flex;align-items:center;justify-content:center;padding:1rem;opacity:0;pointer-events:none;transition:opacity var(--transition)}
.modal-overlay.open{opacity:1;pointer-events:all}
.modal{background:white;border-radius:var(--radius-xl);padding:1.75rem;width:100%;max-width:520px;max-height:90vh;overflow-y:auto;box-shadow:var(--shadow-lg);transform:translateY(10px);transition:transform var(--transition)}
.modal-overlay.open .modal{transform:translateY(0)}
.modal-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.25rem}
.modal-title{font-size:var(--text-md);font-weight:700;color:var(--grey-900)}
.modal-close{background:none;border:none;color:var(--grey-400);font-size:var(--text-lg);line-height:1;padding:.25rem;border-radius:var(--radius-sm);transition:all var(--transition)}
.modal-close:hover{background:var(--grey-100);color:var(--grey-700)}
.modal-footer{display:flex;justify-content:flex-end;gap:.65rem;margin-top:1.5rem;padding-top:1.25rem;border-top:1px solid var(--grey-100)}

/* ── SKELETON LOADERS ─────────────────────────────────────────────────────── */
.skeleton{background:linear-gradient(90deg,var(--grey-100) 25%,var(--grey-200) 50%,var(--grey-100) 75%);background-size:200% 100%;animation:shimmer 1.4s infinite;border-radius:var(--radius-sm)}
@keyframes shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}
.skeleton-text{height:.85rem;border-radius:99px;margin-bottom:.5rem}
.skeleton-title{height:1.25rem;width:60%;border-radius:99px}

/* ── SYNC STATUS ──────────────────────────────────────────────────────────── */
.sync-bar{position:fixed;bottom:1rem;right:1rem;background:var(--grey-900);color:white;padding:.55rem 1rem;border-radius:var(--radius);font-size:var(--text-sm);display:flex;align-items:center;gap:.5rem;box-shadow:var(--shadow-lg);z-index:400;transform:translateY(100px);transition:transform .3s ease;opacity:0}
.sync-bar.show{transform:translateY(0);opacity:1}
.sync-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}
.sync-dot.syncing{background:var(--accent);animation:pulse 1s infinite}
.sync-dot.synced{background:var(--green)}
.sync-dot.failed{background:var(--red)}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.4}}

/* ── EMPTY STATE ──────────────────────────────────────────────────────────── */
.empty-state{text-align:center;padding:4rem 1.5rem;color:var(--grey-400)}
.empty-state svg{margin:0 auto 1.5rem;width:64px;height:64px;opacity:.5;color:var(--grey-300)}
.empty-state h3{font-size:var(--text-lg);font-weight:700;color:var(--grey-600);margin-bottom:.6rem}
.empty-state p{font-size:var(--text-base);color:var(--grey-500);line-height:1.6;max-width:400px;margin:0 auto}

/* ── LIST ITEMS & DATA ROWS ──────────────────────────────────────────────── */
.list-item,.data-row{display:flex;align-items:center;gap:1rem;padding:1rem;border:1px solid var(--grey-100);border-radius:var(--radius);margin-bottom:.75rem;background:white;transition:all var(--transition);min-height:64px;cursor:pointer}
.list-item:hover,.data-row:hover{background:var(--grey-50);border-color:var(--grey-200);box-shadow:var(--shadow-sm)}
.list-item-icon,.data-row-icon{width:44px;height:44px;border-radius:var(--radius);display:flex;align-items:center;justify-content:center;flex-shrink:0;background:var(--grey-50);color:var(--grey-600);font-weight:700}
.list-item-content,.data-row-content{flex:1;min-width:0}
.list-item-title,.data-row-title{font-size:var(--text-md);font-weight:600;color:var(--grey-800);margin-bottom:.3rem}
.list-item-meta,.data-row-meta{font-size:var(--text-sm);color:var(--grey-500)}
.list-item-action,.data-row-action{flex-shrink:0;display:flex;align-items:center;gap:.5rem}

/* ── SETUP BANNER ─────────────────────────────────────────────────────────── */
.setup-banner{background:linear-gradient(135deg,var(--brand),var(--brand-light));color:white;border-radius:var(--radius-lg);padding:1.25rem 1.5rem;margin-bottom:1.5rem;display:flex;align-items:center;gap:1rem;flex-wrap:wrap}
.setup-banner-body{flex:1;min-width:200px}
.setup-banner-body h3{font-size:var(--text-md);font-weight:700;margin-bottom:.2rem}
.setup-banner-body p{font-size:var(--text-sm);opacity:.85}

/* ── PAGE HEADER ──────────────────────────────────────────────────────────── */
.page-header{margin-bottom:1.5rem}
.page-header-top{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}
.page-title{font-size:var(--text-lg);font-weight:700;color:var(--grey-900)}
.page-subtitle{font-size:var(--text-base);color:var(--grey-500);margin-top:.2rem}
.page-actions{display:flex;align-items:center;gap:.65rem;flex-wrap:wrap}

/* ── PLATFORM ADMIN SPECIFIC ──────────────────────────────────────────────── */
.platform-layout{min-height:100vh;background:#0d1b2a;display:flex}
.platform-sidebar{width:220px;background:#0d1b2a;border-right:1px solid rgba(255,255,255,.07);display:flex;flex-direction:column;padding:1.5rem 0}
.platform-brand{padding:0 1.25rem 1.5rem;display:flex;align-items:center;gap:.65rem;color:white;font-size:var(--text-md);font-weight:700;border-bottom:1px solid rgba(255,255,255,.07)}
.platform-nav{padding:1rem 0;flex:1}
.platform-nav-item{display:flex;align-items:center;gap:.65rem;padding:.6rem 1.25rem;color:rgba(255,255,255,.55);font-size:var(--text-sm);cursor:pointer;transition:all var(--transition);border-left:3px solid transparent}
.platform-nav-item:hover{color:white;background:rgba(255,255,255,.05)}
.platform-nav-item.active{color:white;background:rgba(255,255,255,.08);border-left-color:#a78bfa}
.platform-main{flex:1;display:flex;flex-direction:column;overflow:hidden}
.platform-topbar{height:56px;background:#0d1b2a;border-bottom:1px solid rgba(255,255,255,.07);display:flex;align-items:center;padding:0 1.5rem;gap:1rem}
.platform-topbar-title{color:white;font-size:var(--text-base);font-weight:600;flex:1}
.platform-content{flex:1;overflow-y:auto;padding:1.5rem;background:#111827}
.platform-card{background:#1a2535;border:1px solid rgba(255,255,255,.07);border-radius:var(--radius-lg);padding:1.5rem}
.platform-card-title{font-size:var(--text-base);font-weight:700;color:white;margin-bottom:1.25rem;display:flex;align-items:center;gap:.5rem;padding-bottom:.875rem;border-bottom:1px solid rgba(255,255,255,.07)}

/* ── LOGIN PAGE ───────────────────────────────────────────────────────────── */
/* ── LOGIN: SPLIT LAYOUT ────────────────────────────────────────────────────
   The door, and the ONLY place the platform brand appears. Left = Edumora
   panel, right = the form. The supplied logo is a COMPLETE artwork (it carries
   its own light background, the "School Management System" strapline and the
   Learn/Manage/Analyze/Empower row), so the panel adds no text of its own —
   anything else would duplicate what is already inside the image — and its
   background is near-white so the artwork blends instead of sitting on a slab.
   The image is used AS IS: constrained by width with object-fit:contain, never
   stretched, never recoloured. */
.login-split{min-height:100vh;display:grid;grid-template-columns:1.1fr 1fr;background:var(--white)}
.login-brand{position:relative;overflow:hidden;display:flex;align-items:center;justify-content:center;padding:var(--space-6);background:#fbfcfe}
.login-brand-img{width:100%;max-width:560px;height:auto;object-fit:contain;display:block}
.login-formside{display:flex;align-items:center;justify-content:center;padding:var(--space-5) var(--space-4);background:linear-gradient(135deg,var(--brand-dark) 0%,var(--brand) 100%)}
.login-split .login-card{margin:0}

/* The reveal: two curtains part to uncover the logo, then the form settles.
   ~700ms total, once per page load. Purely decorative — the curtains sit in
   the BRAND panel only and are pointer-events:none, so the form is usable the
   instant it paints, never gated by the animation. */
.login-curtain{position:absolute;top:0;bottom:0;width:50%;background:var(--brand-dark);z-index:2;pointer-events:none}
.login-curtain-l{left:0}
.login-curtain-r{right:0}
.login-reveal .login-curtain-l{animation:loginPartL .62s cubic-bezier(.65,0,.35,1) forwards}
.login-reveal .login-curtain-r{animation:loginPartR .62s cubic-bezier(.65,0,.35,1) forwards}
.login-reveal .login-brand-img{animation:loginLogoIn .5s ease .28s both}
.login-reveal .login-card{animation:loginCardIn .45s ease .3s both}
@keyframes loginPartL{to{transform:translateX(-101%)}}
@keyframes loginPartR{to{transform:translateX(101%)}}
@keyframes loginLogoIn{from{opacity:0;transform:scale(.965)}to{opacity:1;transform:none}}
@keyframes loginCardIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

@media(max-width:768px){
  /* Stack, brand panel COMPACT on top: the form must be reachable without
     scrolling on a 360px phone, so the panel is capped by viewport height. */
  .login-split{grid-template-columns:1fr;grid-template-rows:auto 1fr;min-height:100vh}
  .login-brand{padding:var(--space-3) var(--space-4);max-height:26vh}
  .login-brand-img{max-width:300px;max-height:22vh}
  .login-formside{padding:var(--space-4) var(--space-3)}
  .login-split .login-card{padding:var(--space-5) var(--space-4)}
}

.login-page{min-height:100vh;background:linear-gradient(135deg,var(--brand-dark) 0%,var(--brand) 50%,var(--brand-light) 100%);display:flex;align-items:center;justify-content:center;padding:1rem}
.login-card{background:white;border-radius:var(--radius-xl);padding:2.5rem;width:100%;max-width:420px;box-shadow:var(--shadow-lg)}
.login-logo{display:flex;align-items:center;gap:.75rem;margin-bottom:2rem;justify-content:center}
.login-logo-text{font-size:var(--text-xl);font-weight:800;color:var(--brand);letter-spacing:-.02em}
.login-title{font-size:var(--text-lg);font-weight:700;color:var(--grey-900);margin-bottom:.4rem;text-align:center}
.login-subtitle{font-size:var(--text-base);color:var(--grey-500);text-align:center;margin-bottom:1.75rem}
.login-divider{text-align:center;margin:1.25rem 0;color:var(--grey-400);font-size:var(--text-sm);display:flex;align-items:center;gap:.75rem}
.login-divider::before,.login-divider::after{content:'';flex:1;height:1px;background:var(--grey-200)}

/* ── TABS ─────────────────────────────────────────────────────────────────── */
.tabs{display:flex;border-bottom:2px solid var(--grey-200);margin-bottom:1.5rem;overflow-x:auto;gap:0}
.tab-btn{background:none;border:none;padding:.65rem 1.25rem;font-size:var(--text-base);font-weight:500;color:var(--grey-500);border-bottom:3px solid transparent;margin-bottom:-2px;white-space:nowrap;transition:all var(--transition);display:flex;align-items:center;gap:.4rem}
.tab-btn:hover{color:var(--brand)}
.tab-btn.active{color:var(--brand);border-bottom-color:var(--brand);font-weight:600}
.tab-pane{display:none}
.tab-pane.active{display:block}

/* ── CHECKLIST ────────────────────────────────────────────────────────────── */
.checklist-item{display:flex;align-items:center;gap:1rem;padding:1rem 1.25rem;border:1.5px solid var(--grey-200);border-radius:var(--radius);margin-bottom:.65rem;transition:all var(--transition);cursor:pointer}
.checklist-item:hover{border-color:var(--grey-300);box-shadow:var(--shadow-sm)}
.checklist-item.done{border-color:#bbf7d0;background:#f0fdf4}
.checklist-item.pending{border-color:var(--grey-200)}
.checklist-check{width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:var(--text-md)}
.checklist-item.done .checklist-check{background:var(--green-light);color:var(--green)}
.checklist-item.pending .checklist-check{background:var(--grey-100);color:var(--grey-400)}
.checklist-body{flex:1}
.checklist-body h4{font-size:var(--text-base);font-weight:600;color:var(--grey-800);margin-bottom:.15rem}
.checklist-body p{font-size:var(--text-sm);color:var(--grey-500)}
.checklist-action{color:var(--grey-400)}

/* ── MOBILE RESPONSIVE ──────────────────────────────────────────────────────
   BREAKPOINTS — exactly THREE, use no others (fix/mobile-layout-tables):
     480px  phone     (stacked .data-table cards, bottom-sheet modals)
     768px  tablet    (sidebar → hamburger, single-column grids)
     1024px small laptop (touch-size forms/buttons, grid collapses)
   Do not reintroduce 640/900 — they fragmented into 21 inconsistent queries
   before this was standardised. Pick the nearest of the three instead.     */
@media(max-width:768px){
  .sidebar{transform:translateX(-100%)}
  .sidebar.open{transform:translateX(0)}
  .main-content{margin-left:0}
  .page-content{padding:1rem}
  .form-grid{grid-template-columns:1fr}
  .kpi-grid{grid-template-columns:repeat(3,1fr)}
  .mobile-hide{display:none}
  .topbar{padding:0 1rem}
  .hamburger{display:flex}
}
@media(max-width:480px){
  .kpi-grid{grid-template-columns:1fr 1fr !important;gap:.5rem}
  .login-card{padding:1.75rem}
  .modal{border-radius:var(--radius-lg) var(--radius-lg) 0 0;max-height:85vh;position:fixed;bottom:0;left:0;right:0;max-width:100%}
  .modal-overlay{align-items:flex-end}
  .data-table{font-size:var(--text-base)}
  .data-table thead{display:none}
  .data-table tr{display:block;border:1px solid var(--grey-200);border-radius:var(--radius);margin-bottom:.75rem;padding:1rem}
  .data-table td{display:flex;justify-content:space-between;align-items:center;padding:.5rem 0;border:none;font-size:var(--text-base);min-height:auto}
  .data-table td::before{content:attr(data-label);font-weight:700;color:var(--grey-600);font-size:var(--text-xs);text-transform:uppercase;flex-shrink:0;margin-right:.6rem}
  /* The value half of a stacked cell must be able to wrap — an unbroken
     reference/email would otherwise push the card wider than the phone. */
  .data-table td{overflow-wrap:anywhere;min-width:0}
}
.hamburger{display:none;background:none;border:none;color:var(--grey-600);padding:.4rem;border-radius:var(--radius-sm);cursor:pointer}
.sidebar-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.4);z-index:99}
.sidebar-overlay.show{display:block}

/* ── UTILITY ──────────────────────────────────────────────────────────────── */
.flex{display:flex}.flex-1{flex:1}.items-center{align-items:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}
.text-sm{font-size:var(--text-base)}.text-xs{font-size:var(--text-xs)}.text-lg{font-size:var(--text-lg)}
.font-bold{font-weight:700}.font-semibold{font-weight:600}
.text-brand{color:var(--brand)}.text-muted{color:var(--grey-500)}.text-danger{color:var(--red)}.text-success{color:var(--green)}
.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-6{margin-top:1.5rem}
.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}
.p-4{padding:1rem}.p-6{padding:1.5rem}
.rounded{border-radius:var(--radius)}.rounded-lg{border-radius:var(--radius-lg)}
.w-full{width:100%}
.hidden{display:none!important}
.truncate{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
.grid-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:1rem}
/* Dashboard lower section (now Academic Period alone — School Information was
   removed as static, non-actionable content). auto-fit rather than the rigid
   .grid-2 two-up: it removed the 641–768px squeeze, and it is also why dropping
   one of the two cards leaves no empty column — the survivor simply spans the
   row. Scoped to #dash-lower (id > class, so it overrides .grid-2 here only —
   the global .grid-2 is untouched). */
#dash-lower{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}


/* ═══════════════════════════════════════════════════════════
   PARENT PORTAL PREMIUM
   ═══════════════════════════════════════════════════════════ */
@keyframes ppFadeUp { from{opacity:0;transform:translateY(14px)} to{opacity:1;transform:translateY(0)} }
@keyframes ppSpin { to{transform:rotate(360deg)} }
@keyframes ppProgress { from{width:0} }
@keyframes ppPulse { 0%,100%{transform:scale(1);opacity:1} 50%{transform:scale(1.4);opacity:.6} }

/* ── PASS 1 redesign: hero banner (portal-only classes) ──────────────────── */
.pp-hero{background:linear-gradient(135deg,#0c2238 0%,#163a5e 48%,#1d4e8a 100%);border-radius:var(--radius-xl,20px);padding:1.6rem 1.75rem;margin-bottom:1.25rem;position:relative;overflow:hidden;box-shadow:0 12px 32px rgba(11,32,55,.30),0 2px 8px rgba(11,32,55,.16);animation:ppFadeUp .4s ease both}
.pp-hero::before{content:'';position:absolute;inset:0;background:radial-gradient(120% 90% at 85% -15%,rgba(255,255,255,.12),transparent 58%);pointer-events:none}
.pp-hero::after{content:'';position:absolute;bottom:-100px;left:34%;width:300px;height:300px;background:rgba(255,255,255,.035);border-radius:50%;pointer-events:none}
.pp-hero-inner{display:flex;align-items:center;gap:1.15rem;position:relative;z-index:1}
.pp-avatar{width:64px;height:64px;border-radius:50%;border:2.5px solid rgba(255,255,255,.35);object-fit:cover;flex-shrink:0;box-shadow:0 6px 18px rgba(0,0,0,.28)}
.pp-avatar-init{width:64px;height:64px;border-radius:50%;background:rgba(255,255,255,.14);border:2.5px solid rgba(255,255,255,.3);display:flex;align-items:center;justify-content:center;font-size:1.4rem;font-weight:800;color:#fff;flex-shrink:0;box-shadow:0 6px 18px rgba(0,0,0,.25);letter-spacing:.5px}
.pp-hero-name{font-size:var(--text-lg);font-weight:800;color:#fff;letter-spacing:-.3px;margin-bottom:.45rem;text-shadow:0 1px 3px rgba(0,0,0,.25)}
.pp-hero-meta{display:flex;align-items:center;gap:.45rem;flex-wrap:wrap}
.pp-badge{padding:.22rem .7rem;border-radius:20px;font-size:var(--text-xs);font-weight:700;letter-spacing:.3px;display:inline-flex;align-items:center;gap:.25rem}
.pp-badge-class{background:rgba(255,255,255,.16);color:#fff}
.pp-badge-good{background:rgba(74,222,128,.22);color:#bbf7d0;border:1px solid rgba(74,222,128,.35)}
.pp-badge-warn{background:rgba(251,191,36,.2);color:#fde68a;border:1px solid rgba(251,191,36,.35)}
.pp-snum{color:rgba(255,255,255,.55);font-size:var(--text-xs);font-family:ui-monospace,monospace;letter-spacing:.2px}

/* ── PASS 1 redesign: tab strip — segmented pills, scroll-on-mobile kept ──── */
.pp-tabs{display:flex;gap:.3rem;margin-bottom:1.4rem;overflow-x:auto;scrollbar-width:none;padding:.1rem 0 .3rem;-webkit-overflow-scrolling:touch}
.pp-tabs::-webkit-scrollbar{display:none}
.pp-tab{background:none;border:none;outline:none;padding:.55rem 1rem;font-size:var(--text-base);font-weight:600;color:var(--grey-500,#64748b);cursor:pointer;border-radius:10px;white-space:nowrap;transition:background .15s,color .15s,box-shadow .15s}
.pp-tab:hover{background:var(--grey-100,#f1f5f9);color:var(--navy,#1a3c5e)}
.pp-tab.active{background:var(--navy,#1a3c5e);color:#fff;font-weight:700;box-shadow:0 3px 10px rgba(26,60,94,.28)}
/* PASS-5 follow-up: unread-notice count pill on the portal Notices tab (portal-only).
   Soft red "attention" pill; reads on both the active (navy) and inactive (light) tab. */
.pp-tab-badge{display:inline-flex;align-items:center;justify-content:center;min-width:1.05rem;height:1.05rem;padding:0 .35rem;border-radius:999px;background:var(--red,#dc2626);color:#fff;font-size:var(--text-xs);font-weight:800;line-height:1;vertical-align:middle;margin-left:.15rem}

/* ── PASS 1 redesign: overview summary cards (portal-only) ────────────────── */
.pp-overview{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.7rem;margin-bottom:1.4rem;animation:ppFadeUp .4s .1s ease both}
.pp-ov{background:#fff;border:1px solid var(--grey-200,#e2e8f0);border-radius:var(--radius-lg,14px);padding:1rem 1.1rem;display:flex;align-items:center;gap:.85rem;cursor:pointer;box-shadow:var(--shadow-sm,0 1px 3px rgba(0,0,0,.08));transition:transform .18s ease,box-shadow .18s ease}
.pp-ov:hover{transform:translateY(-3px);box-shadow:var(--shadow,0 4px 12px rgba(0,0,0,.08))}
.pp-ov-icon{width:44px;height:44px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:1.2rem;flex-shrink:0}
.pp-ov-lbl{font-size:var(--text-xs);color:var(--grey-400,#94a3b8);font-weight:700;text-transform:uppercase;letter-spacing:.6px;margin-bottom:.22rem}
.pp-ov-val{font-size:var(--text-md);font-weight:800;color:var(--grey-800,#1e293b);line-height:1.15}

/* ── PASS 1: card frame — light premium refine (chrome only, body unchanged) ─ */
.pp-card{background:#fff;border:1px solid var(--grey-200,#e2e8f0);border-radius:16px;padding:1.35rem;margin-bottom:1rem;box-shadow:var(--shadow-sm,0 1px 3px rgba(0,0,0,.08));transition:box-shadow .2s ease,transform .2s ease;animation:ppFadeUp .35s ease both}
.pp-card:hover{box-shadow:var(--shadow,0 4px 12px rgba(0,0,0,.08));transform:translateY(-2px)}
.pp-card-hdr{display:flex;justify-content:space-between;align-items:center;margin-bottom:1.1rem}
.pp-card-ttl{font-size:var(--text-sm);font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--grey-600,#475569)}

.pp-ring-wrap{display:flex;align-items:center;gap:1.5rem;padding:.5rem 0}
.pp-ring{position:relative;width:80px;height:80px;flex-shrink:0}
.pp-ring svg{transform:rotate(-90deg)}
.pp-ring-track{fill:none;stroke:#e8eef7;stroke-width:9}
.pp-ring-fill{fill:none;stroke-width:9;stroke-linecap:round;transition:stroke-dashoffset 1s cubic-bezier(.4,0,.2,1)}
.pp-ring-lbl{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
.pp-ring-pct{font-size:var(--text-md);font-weight:800;color:var(--grey-800,#1e293b);line-height:1}
.pp-ring-sub{font-size:var(--text-xs);color:var(--grey-400,#94a3b8);font-weight:600;text-transform:uppercase;margin-top:.1rem}

/* ── PASS 3 redesign: Attendance tab — NEW headline ring + stat tiles ───────
   pp-att-* is a BRAND-NEW portal-only family, distinct from the shared pp-ring*
   (dashboard donut). Nothing here touches pp-ring*. */
.pp-att-hero{display:flex;flex-direction:column;align-items:center;gap:.65rem;padding:.6rem 0 1.1rem}
.pp-att-ring{position:relative;width:120px;height:120px;flex-shrink:0;margin:0 auto}
.pp-att-ring svg{transform:rotate(-90deg)}
.pp-att-ring-track{fill:none;stroke:var(--grey-100,#f1f5f9);stroke-width:10}
.pp-att-ring-fill{fill:none;stroke-width:10;stroke-linecap:round;transition:stroke-dashoffset 1s cubic-bezier(.4,0,.2,1)}
.pp-att-ring-lbl{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center}
.pp-att-ring-pct{font-size:var(--text-xl);font-weight:800;line-height:1;letter-spacing:-.5px}
.pp-att-ring-sub{font-size:var(--text-xs);color:var(--grey-400,#94a3b8);font-weight:700;text-transform:uppercase;letter-spacing:.6px;margin-top:.25rem}
.pp-att-caption{font-size:var(--text-sm);color:var(--grey-500,#64748b);font-weight:600;text-align:center}
.pp-att-tiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.6rem}
.pp-att-tile{text-align:center;border-radius:12px;padding:.85rem .4rem;border:1px solid var(--grey-100,#f1f5f9)}
.pp-att-tile-val{font-size:var(--text-xl);font-weight:800;line-height:1}
.pp-att-tile-lbl{font-size:var(--text-xs);font-weight:700;text-transform:uppercase;letter-spacing:.5px;margin-top:.3rem;color:var(--grey-500,#64748b)}

/* ── PASS 4: shared list / detail components for the lighter tabs (portal-only).
   One coherent row/header/pill/detail language reused across Results, Behaviour,
   Timetable, Profile, Submissions so they match the Pass 1-3 family. NEW classes
   only — does NOT edit the app-wide card-header/card-title (markup swaps to these). */
.pp-lhdr{display:flex;justify-content:space-between;align-items:center;gap:.75rem;padding:1rem 1.25rem;border-bottom:1px solid var(--grey-100,#f1f5f9)}
.pp-lhdr-ttl{font-size:var(--text-sm);font-weight:800;color:var(--navy,#1a3c5e);letter-spacing:-.1px;display:flex;align-items:center;gap:.4rem}
.pp-lhdr-count{font-size:var(--text-xs);color:var(--grey-400,#94a3b8);font-weight:600;white-space:nowrap}
.pp-lrow{padding:.95rem 1.25rem;border-bottom:1px solid var(--grey-100,#f1f5f9)}
.pp-lrow:last-child{border-bottom:none}
.pp-lrow-top{display:flex;justify-content:space-between;align-items:flex-start;gap:.75rem}
.pp-lrow-title{font-weight:700;color:var(--grey-800,#1e293b);font-size:var(--text-base);display:flex;align-items:center;gap:.45rem;flex-wrap:wrap;min-width:0}
.pp-lrow-date{font-size:var(--text-xs);color:var(--grey-400,#94a3b8);white-space:nowrap;flex-shrink:0}
.pp-lrow-body{font-size:var(--text-sm);color:var(--grey-600,#475569);line-height:1.55;margin-top:.35rem}
.pp-lrow-note{font-size:var(--text-sm);color:var(--grey-600,#475569);background:var(--grey-50,#f8fafc);border:1px solid var(--grey-100,#f1f5f9);padding:.5rem .65rem;border-radius:8px;margin-top:.45rem}
/* generic status pill — geometry only; colour set inline (data-driven). */
.pp-tag{display:inline-flex;align-items:center;padding:.2rem .6rem;border-radius:20px;font-size:var(--text-xs);font-weight:800;letter-spacing:.4px;text-transform:uppercase;white-space:nowrap}
/* detail rows (Profile) */
.pp-drow{display:flex;justify-content:space-between;gap:1rem;padding:.62rem 0;border-bottom:1px solid var(--grey-100,#f1f5f9);font-size:var(--text-base)}
.pp-drow:last-child{border-bottom:none}
.pp-drow-lbl{color:var(--grey-400,#94a3b8);text-transform:uppercase;letter-spacing:.4px;font-size:var(--text-xs);font-weight:700;flex-shrink:0}
.pp-drow-val{color:var(--grey-800,#1e293b);font-weight:600;text-align:right}
/* timetable slot row */
.pp-tt-day{font-weight:800;font-size:var(--text-sm);color:var(--navy,#1a3c5e);text-transform:uppercase;letter-spacing:.4px;padding:.9rem 0 .4rem;border-bottom:2px solid var(--grey-100,#f1f5f9);margin-bottom:.2rem}
.pp-tt-slot{display:grid;grid-template-columns:84px 1fr auto;gap:.65rem;padding:.5rem 0;font-size:var(--text-sm);border-bottom:1px solid var(--grey-100,#f1f5f9);align-items:center}
.pp-tt-time{color:var(--grey-500,#64748b);font-weight:700;font-size:var(--text-sm)}
.pp-tt-subj{color:var(--grey-800,#1e293b);font-weight:700}
.pp-tt-teacher{color:var(--grey-400,#94a3b8);font-size:var(--text-xs);text-align:right}

/* ── PASS 5: message rows (Notices & Notifications) — portal-only. Read-state is
   CLASS-DRIVEN (.is-unread), never inferred from inline styles, so mark-as-read
   can't silently break. Notices' per-type tint stays inline (data-driven); these
   rules own the layout, the unread emphasis (bold title + dot), and the default
   unread background (notifications). */
.pp-msg{display:flex;gap:.85rem;padding:1rem 1.25rem;border-bottom:1px solid var(--grey-100,#f1f5f9);cursor:pointer;background:#fff;transition:background-color .15s ease}
.pp-msg:last-child{border-bottom:none}
.pp-msg:hover{background:var(--grey-50,#f8fafc)}
.pp-msg.is-unread{background:#f0f9ff}            /* notifications default unread tint (notices override inline by type) */
.pp-msg-icon{font-size:1.4rem;flex-shrink:0;line-height:1.3}
.pp-msg-body{flex:1;min-width:0}
.pp-msg-head{display:flex;justify-content:space-between;align-items:flex-start;gap:.75rem;margin-bottom:.2rem}
.pp-msg-title{font-weight:500;font-size:var(--text-base);color:var(--grey-800,#1e293b)}
.pp-msg.is-unread .pp-msg-title{font-weight:700}
.pp-msg-date{font-size:var(--text-xs);color:var(--grey-400,#94a3b8);white-space:nowrap;flex-shrink:0}
.pp-msg-text{font-size:var(--text-sm);color:var(--grey-600,#475569);line-height:1.55}
.pp-msg-meta{font-size:var(--text-xs);color:var(--grey-400,#94a3b8);margin-top:.4rem;text-transform:uppercase;letter-spacing:.4px;font-weight:700}
.pp-msg-dot{width:8px;height:8px;background:var(--blue,#2563eb);border-radius:50%;margin-top:.45rem;display:none}
.pp-msg.is-unread .pp-msg-dot{display:block}
.pp-msg-attach{display:inline-block;margin-top:.4rem;font-size:var(--text-sm);text-decoration:none;font-weight:600}

.pp-stats{display:flex;gap:.75rem;flex-wrap:wrap}
.pp-stat{flex:1;min-width:70px;background:var(--grey-50,#f8fafc);border-radius:10px;padding:.65rem .85rem;text-align:center}
.pp-stat-val{font-size:var(--text-lg);font-weight:800}
.pp-stat-lbl{font-size:var(--text-xs);font-weight:600;text-transform:uppercase;letter-spacing:.3px;color:var(--grey-400,#94a3b8);margin-top:.1rem}

.pp-prog-wrap{margin:.75rem 0 .5rem}
.pp-prog-labels{display:flex;justify-content:space-between;font-size:var(--text-xs);color:var(--grey-500,#64748b);margin-bottom:.35rem}
.pp-prog-track{height:8px;background:#f1f5f9;border-radius:99px;overflow:hidden}
.pp-prog-fill{height:100%;border-radius:99px;animation:ppProgress .9s .3s cubic-bezier(.4,0,.2,1) both;transition:width .5s ease}

/* ── PASS 2 redesign: Fees tab — invoice cards (portal-only classes) ──────── */
.pp-fee-card{background:#fff;border:1px solid var(--grey-200,#e2e8f0);border-radius:16px;padding:1.35rem;margin-bottom:1rem;box-shadow:var(--shadow-sm,0 1px 3px rgba(0,0,0,.08));transition:box-shadow .2s ease,transform .2s ease;animation:ppFadeUp .35s ease both}
.pp-fee-card:hover{box-shadow:var(--shadow,0 4px 12px rgba(0,0,0,.08));transform:translateY(-2px)}
.pp-fee-hdr{display:flex;justify-content:space-between;align-items:flex-start;gap:.75rem;margin-bottom:1.1rem}
.pp-fee-term{font-size:var(--text-md);font-weight:800;color:var(--navy,#1a3c5e);letter-spacing:-.2px;margin-bottom:.2rem}
.pp-fee-inv{font-size:var(--text-xs);color:var(--grey-400,#94a3b8)}
.pp-fee-pill{padding:.28rem .8rem;border-radius:20px;font-size:var(--text-xs);font-weight:800;letter-spacing:.5px;text-transform:uppercase;white-space:nowrap;flex-shrink:0}
/* Billed / Paid / Balance as premium stat tiles; the value colour stays inline
   (data-driven: navy billed, green paid, red/green balance) so outstanding stands out. */
.pp-fee-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.6rem;margin-bottom:1rem}
.pp-fee-stat{text-align:center;background:var(--grey-50,#f8fafc);border:1px solid var(--grey-100,#f1f5f9);border-radius:12px;padding:.7rem .4rem}
.pp-fee-val{font-size:var(--text-md);font-weight:800;margin-bottom:.2rem;line-height:1.1}
.pp-fee-lbl{font-size:var(--text-xs);font-weight:700;text-transform:uppercase;letter-spacing:.5px;color:var(--grey-400,#94a3b8)}
.pp-fee-actions{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:1rem;padding-top:1rem;border-top:1px solid var(--grey-100,#f1f5f9);align-items:center}
/* NEW portal-scoped fee buttons — self-contained, do NOT depend on the shared
   .pp-btn (used by the settings payment-plan form). Pass-1 navy pill language. */
.pp-fee-btn{display:inline-flex;align-items:center;gap:.35rem;padding:.5rem 1rem;border-radius:10px;font-size:var(--text-sm);font-weight:700;cursor:pointer;text-decoration:none;border:1.5px solid var(--grey-300,#d1d5db);background:#fff;color:var(--navy,#1a3c5e);transition:background .15s,border-color .15s,box-shadow .15s,transform .15s}
.pp-fee-btn:hover{background:var(--grey-50,#f8fafc);border-color:var(--navy,#1a3c5e)}
.pp-fee-btn-pri{display:inline-flex;align-items:center;gap:.35rem;padding:.5rem 1.1rem;border-radius:10px;font-size:var(--text-sm);font-weight:700;cursor:pointer;text-decoration:none;border:none;background:var(--navy,#1a3c5e);color:#fff;box-shadow:0 3px 10px rgba(26,60,94,.25);transition:background .15s,box-shadow .15s,transform .15s}
.pp-fee-btn-pri:hover{background:#15304d;box-shadow:0 5px 16px rgba(26,60,94,.32);transform:translateY(-1px)}

.pp-btn{display:inline-flex;align-items:center;gap:.35rem;padding:.4rem .9rem;border-radius:8px;font-size:var(--text-sm);font-weight:600;cursor:pointer;border:none;transition:all .15s;text-decoration:none}
.pp-btn-out{background:transparent;color:var(--navy,#1a3c5e);border:1.5px solid var(--grey-300,#d1d5db)}
.pp-btn-out:hover{background:var(--grey-50,#f8fafc);border-color:var(--navy,#1a3c5e)}
.pp-btn-pri{background:var(--navy,#1a3c5e);color:white}
.pp-btn-pri:hover{background:#15304d;box-shadow:0 4px 12px rgba(26,60,94,.3)}

/* Scroll container: on narrow screens the row keeps its single-row layout and
   the history scrolls horizontally instead of the receipt button wrapping. */
.pp-pay-history{overflow-x:auto;-webkit-overflow-scrolling:touch}
/* Five columns for the five cells (date, receipt#, method, amount, button). */
.pp-pay-row{display:grid;grid-template-columns:84px minmax(80px,1fr) auto auto auto;gap:.6rem;padding:.7rem 0;border-bottom:1px solid var(--grey-100,#f1f5f9);align-items:center;font-size:var(--text-sm);min-width:460px}
.pp-pay-row:last-child{border-bottom:none}
.pp-pay-date{color:var(--grey-600,#475569);font-weight:500;white-space:nowrap}
.pp-pay-rcpt{font-family:monospace;font-size:var(--text-sm);color:var(--navy,#1a3c5e);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pp-pay-method{display:inline-flex;align-items:center;padding:.15rem .6rem;background:var(--grey-100,#f1f5f9);border-radius:6px;font-size:var(--text-xs);font-weight:600;color:var(--grey-600,#475569);white-space:nowrap}
.pp-pay-amt{font-weight:800;color:var(--green,#16a34a);text-align:right;white-space:nowrap}
.pp-pay-rcpt-btn{white-space:nowrap;font-size:var(--text-xs);font-weight:700;color:var(--navy,#1a3c5e);text-decoration:none;padding:.28rem .6rem;border:1.5px solid var(--grey-200,#e2e8f0);border-radius:8px;justify-self:end;transition:background .15s,border-color .15s}
.pp-pay-rcpt-btn:hover{background:var(--grey-50,#f8fafc);border-color:var(--navy,#1a3c5e)}

/* PASS-5 refinement: Results rows — explicit, comfortable columns on desktop so
   subject / mark / grade / performance form clean aligned columns across the row
   width instead of bunching at the right. Mobile (<=768px) keeps the 3-col layout
   below (perf hidden). Portal-only classes; data/markup unchanged. */
.pp-res-row{display:grid;grid-template-columns:1fr 84px 52px minmax(120px,160px);gap:1rem;padding:.85rem .15rem;border-bottom:1px solid var(--grey-100,#f1f5f9);align-items:center}
.pp-res-row:last-child{border-bottom:none}
.pp-res-sub{font-weight:600;font-size:var(--text-base);color:var(--grey-800,#1e293b)}
.pp-res-mark{font-size:var(--text-base);font-weight:700;color:var(--grey-700,#374151);text-align:center}
.pp-res-grade{width:34px;height:34px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:var(--text-sm);font-weight:800;justify-self:center}
.pp-res-perf{font-size:var(--text-sm);color:var(--grey-500,#64748b);text-align:left}

.pp-empty{text-align:center;padding:3rem 1.5rem;animation:ppFadeUp .4s ease both}
.pp-empty-icon{width:72px;height:72px;margin:0 auto 1rem;background:var(--grey-100,#f1f5f9);border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:2rem}
.pp-empty-title{font-size:var(--text-md);font-weight:700;color:var(--grey-800,#1e293b);margin-bottom:.4rem}
.pp-empty-msg{font-size:var(--text-base);color:var(--grey-400,#94a3b8);max-width:320px;margin:0 auto;line-height:1.6}

.pp-spinner{width:32px;height:32px;border-radius:50%;border:3px solid var(--grey-200,#e2e8f0);border-top-color:var(--navy,#1a3c5e);animation:ppSpin .7s linear infinite;margin:0 auto}
.pp-pulse{width:8px;height:8px;border-radius:50%;display:inline-block;animation:ppPulse 1.5s ease-in-out infinite}

.pp-child-pills{display:flex;gap:.5rem;flex-wrap:wrap;margin-bottom:1rem}
.pp-child-pill{padding:.4rem 1rem;border-radius:20px;font-size:var(--text-sm);font-weight:600;cursor:pointer;border:1.5px solid var(--grey-300,#d1d5db);background:#fff;color:var(--grey-600,#475569);transition:all .15s}
.pp-child-pill:hover{border-color:var(--navy,#1a3c5e);color:var(--navy,#1a3c5e)}
.pp-child-pill.active{background:var(--navy,#1a3c5e);border-color:var(--navy,#1a3c5e);color:#fff;box-shadow:0 2px 8px rgba(26,60,94,.22)}


/* ── GLOBAL ENHANCEMENTS (Phase 2) ──────────────────────────────────────── */

/* btn-outline: outline variant using brand colour */
.btn-outline{background:transparent;color:var(--brand);border:1.5px solid var(--grey-300);transition:all var(--transition)}
.btn-outline:hover:not(:disabled){background:var(--grey-50);border-color:var(--brand);color:var(--brand-dark)}

/* badge-outline: bordered badge for status pills */
.badge-outline{background:transparent;border:1.5px solid currentColor;font-weight:600}
.badge-outline.badge-green{color:var(--green)}
.badge-outline.badge-red{color:var(--red)}
.badge-outline.badge-yellow{color:var(--yellow)}
.badge-outline.badge-blue{color:var(--blue)}

/* card-hover: opt-in lift effect for interactive cards */
.card-hover{transition:box-shadow var(--transition),transform var(--transition);cursor:pointer}
.card-hover:hover{box-shadow:var(--shadow);transform:translateY(-2px)}

/* ── ADDITIONAL UTILITIES ────────────────────────────────────────────────── */
.flex-col{display:flex;flex-direction:column}
.flex-wrap{flex-wrap:wrap}
.justify-center{justify-content:center}
.justify-end{justify-content:flex-end}
.items-start{align-items:flex-start}
.items-end{align-items:flex-end}
.items-stretch{align-items:stretch}
.gap-0{gap:0}
.gap-5{gap:1.25rem}
.gap-6{gap:1.5rem}
.min-w-0{min-width:0}
.overflow-hidden{overflow:hidden}
.overflow-x-auto{overflow-x:auto}
.cursor-pointer{cursor:pointer}
.select-none{user-select:none}
.pointer-events-none{pointer-events:none}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.opacity-50{opacity:.5}
.opacity-75{opacity:.75}
.line-clamp-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.text-center{text-align:center}
.text-right{text-align:right}
.text-brand-dark{color:var(--brand-dark)}
.text-accent{color:var(--accent)}
.text-white{color:white}
.bg-white{background:white}
.bg-grey-50{background:var(--grey-50)}
.border-bottom{border-bottom:1px solid var(--grey-200)}
.rounded-full{border-radius:9999px}
.rounded-2xl{border-radius:var(--radius-2xl)}
.shadow-xl{box-shadow:var(--shadow-xl)}
.w-8{width:2rem}.h-8{height:2rem}
.w-10{width:2.5rem}.h-10{height:2.5rem}
.w-12{width:3rem}.h-12{height:3rem}
.shrink-0{flex-shrink:0}
.grow{flex-grow:1}

@media(max-width:768px){
  .pp-hero{padding:1.25rem 1.3rem;border-radius:16px}
  .pp-hero-name{font-size:var(--text-lg)}
  .pp-avatar,.pp-avatar-init{width:56px;height:56px;font-size:1.25rem}
  .pp-overview{grid-template-columns:1fr;gap:.55rem}
  .pp-fee-grid{gap:.45rem}
  .pp-fee-stat{padding:.6rem .3rem}
  .pp-fee-val{font-size:var(--text-base)}
  .pp-fee-btn,.pp-fee-btn-pri{padding:.5rem .85rem;font-size:var(--text-sm)}
  .pp-stats{gap:.5rem}
  .pp-ring-wrap{gap:1rem}
  .pp-att-tiles{gap:.45rem}
  .pp-att-tile{padding:.7rem .3rem}
  .pp-att-tile-val{font-size:var(--text-lg)}
  .pp-att-ring,.pp-att-ring svg{width:108px;height:108px}
  .pp-att-ring-pct{font-size:var(--text-xl)}
  .pp-pay-row{gap:.5rem;font-size:var(--text-sm)}
  .pp-res-row{grid-template-columns:1fr auto auto}
  .pp-res-perf{display:none}
  .pp-tab{padding:.5rem .85rem;font-size:var(--text-sm)}
}

/* ── ACCORDION SIDEBAR ───────────────────────────────────────────────────── */
.nav-group { border-bottom: 1px solid rgba(255,255,255,.06); }
.nav-group-btn {
  width:100%; background:none; border:none; outline:none;
  display:flex; align-items:center; gap:.65rem;
  padding:.75rem 1.2rem; cursor:pointer;
  color:rgba(255,255,255,.55); font-size:var(--text-xs); font-weight:700;
  transition:all var(--transition); text-align:left;
  letter-spacing:.1em; text-transform:uppercase;
}
.nav-group-btn:hover { background:rgba(255,255,255,.06); color:white; }
.nav-group-btn.open { color:white; background:rgba(255,255,255,.05); }
.nav-group-btn svg.chevron { margin-left:auto; transition:transform .25s ease; flex-shrink:0; opacity:.5; }
.nav-group-btn.open svg.chevron { transform:rotate(90deg); opacity:1; }
.nav-group-btn .nav-group-icon { width:18px; height:18px; flex-shrink:0; opacity:.7; }
.nav-group-btn.open .nav-group-icon { opacity:1; }
/* Content-driven accordion: an open group sizes to ITS CONTENT via the grid
   0fr→1fr trick — never a fixed max-height cap. (A 400px cap used to clip the
   admin's 13-item Settings list at ~485px, hiding Audit Log + Role Permissions
   off the bottom — see nav-accordion-no-clip.test.js, which fails if a pixel cap
   is reintroduced.) The accordion must never clip its own items: when the whole
   sidebar is taller than the viewport, .sidebar-nav (overflow-y:auto, #25)
   scrolls instead. The inner wrapper carries the overflow:hidden the collapse
   animation needs. */
.nav-group-items {
  display:grid; grid-template-rows:0fr;
  transition:grid-template-rows .3s cubic-bezier(.4,0,.2,1);
}
.nav-group-items.open { grid-template-rows:1fr; }
.nav-group-items-inner { overflow:hidden; min-height:0; }
/* PASS 6: refined nav items + premium active state (sidebar-only) */
.nav-sub-item {
  display:flex; align-items:center; gap:.6rem;
  padding:.55rem 1.2rem .55rem 2.7rem; margin:.05rem .6rem .05rem 0;
  color:rgba(255,255,255,.6); font-size:var(--text-sm); font-weight:500;
  cursor:pointer; border-left:3px solid transparent; border-radius:0 9px 9px 0;
  transition:background var(--transition),color var(--transition); user-select:none;
}
.nav-sub-item:hover { color:white; background:rgba(255,255,255,.06); }
.nav-sub-item.active { color:white; background:rgba(255,255,255,.12); border-left-color:var(--accent); font-weight:700; }
.nav-sub-item svg { width:15px; height:15px; flex-shrink:0; opacity:.7; }
.nav-sub-item.active svg { opacity:1; }

/* ── SEARCH OVERLAY ──────────────────────────────────────────────────────── */
.search-overlay {
  position:fixed; inset:0; background:rgba(0,0,0,.5);
  z-index:1000; display:flex; align-items:flex-start;
  justify-content:center; padding-top:80px;
  opacity:0; pointer-events:none;
  transition:opacity .2s ease;
  backdrop-filter:blur(4px);
}
.search-overlay.open { opacity:1; pointer-events:all; }
.search-box {
  background:white; border-radius:16px; width:100%; max-width:580px;
  box-shadow:0 24px 64px rgba(0,0,0,.25); overflow:hidden;
  transform:translateY(-12px); transition:transform .2s ease;
}
.search-overlay.open .search-box { transform:translateY(0); }
.search-input-wrap {
  display:flex; align-items:center; gap:.75rem;
  padding:1rem 1.25rem; border-bottom:1px solid var(--grey-100);
}
.search-input-wrap svg { color:var(--grey-400); flex-shrink:0; }
.search-input {
  flex:1; border:none; outline:none; font-size:var(--text-md);
  color:var(--grey-800); background:transparent;
  font-family:inherit;
}
.search-input::placeholder { color:var(--grey-300); }
.search-kbd {
  font-size:var(--text-xs); padding:.2rem .45rem; background:var(--grey-100);
  border-radius:4px; color:var(--grey-400); font-family:monospace;
  border:1px solid var(--grey-200);
}
.search-results { max-height:360px; overflow-y:auto; padding:.5rem 0; }
.search-section-label {
  font-size:var(--text-xs); font-weight:700; text-transform:uppercase;
  letter-spacing:.08em; color:var(--grey-400);
  padding:.5rem 1.25rem .25rem;
}
.search-result-item {
  display:flex; align-items:center; gap:.75rem;
  padding:.6rem 1.25rem; cursor:pointer;
  transition:background var(--transition);
}
.search-result-item:hover, .search-result-item.selected { background:var(--grey-50); }
.search-result-icon {
  width:32px; height:32px; border-radius:8px;
  display:flex; align-items:center; justify-content:center;
  flex-shrink:0; font-size:var(--text-xs); font-weight:700; color:white;
}
.search-result-title { font-size:var(--text-base); font-weight:600; color:var(--grey-800); }
.search-result-sub { font-size:var(--text-xs); color:var(--grey-400); }
.search-empty { text-align:center; padding:2rem; color:var(--grey-400); font-size:var(--text-base); }
.search-hint { padding:.75rem 1.25rem; border-top:1px solid var(--grey-100); display:flex; gap:1rem; }
.search-hint span { font-size:var(--text-xs); color:var(--grey-400); display:flex; align-items:center; gap:.3rem; }

/* ── NOTIFICATIONS PANEL ─────────────────────────────────────────────────── */
.notif-panel {
  position:fixed; top:var(--topbar-h); right:1rem;
  width:340px; max-height:480px;
  background:white; border-radius:12px;
  box-shadow:0 12px 40px rgba(0,0,0,.15);
  border:1px solid var(--grey-200);
  z-index:400; overflow:hidden;
  display:flex; flex-direction:column;
  opacity:0; pointer-events:none;
  transform:translateY(-8px) scale(.97);
  transition:all .2s ease;
}
.notif-panel.open { opacity:1; pointer-events:all; transform:translateY(0) scale(1); }
.notif-panel-header {
  display:flex; align-items:center; justify-content:space-between;
  padding:.85rem 1rem; border-bottom:1px solid var(--grey-100);
  flex-shrink:0;
}
.notif-panel-title { font-size:var(--text-base); font-weight:700; color:var(--grey-800); }
.notif-mark-read { font-size:var(--text-xs); color:var(--brand); cursor:pointer; font-weight:600; background:none; border:none; }
.notif-mark-read:hover { text-decoration:underline; }
.notif-list { overflow-y:auto; flex:1; }
.notif-item {
  display:flex; gap:.75rem; padding:.85rem 1rem;
  border-bottom:1px solid var(--grey-50);
  transition:background var(--transition); cursor:pointer;
}
.notif-item:hover { background:var(--grey-50); }
.notif-item.unread { background:#f0f7ff; }
.notif-item-icon {
  width:34px; height:34px; border-radius:10px;
  display:flex; align-items:center; justify-content:center;
  font-size:.9rem; flex-shrink:0;
}
.notif-item-title { font-size:var(--text-sm); font-weight:600; color:var(--grey-800); margin-bottom:.15rem; }
.notif-item-msg { font-size:var(--text-xs); color:var(--grey-500); line-height:1.4; }
.notif-item-time { font-size:var(--text-xs); color:var(--grey-300); margin-top:.2rem; }
.notif-empty { text-align:center; padding:2.5rem 1rem; color:var(--grey-400); font-size:var(--text-base); }
.notif-footer { padding:.6rem 1rem; border-top:1px solid var(--grey-100); text-align:center; flex-shrink:0; }
.notif-dot-badge {
  position:absolute; top:6px; right:6px;
  min-width:16px; height:16px; border-radius:99px;
  background:var(--red); color:white;
  font-size:var(--text-xs); font-weight:800;
  display:flex; align-items:center; justify-content:center;
  padding:0 3px; border:2px solid white;
}

/* ══════════════════════════════════════════════════════════════════════════
   MOBILE RESPONSIVE LAYER — Edumora
   Breakpoints: 1024px (small laptop), 768px (tablet), 480px (phone) — the
   only three; see the note at the top of the responsive section.
   ══════════════════════════════════════════════════════════════════════════ */

@media(max-width:768px) {

  /* ── TOPBAR ── */
  .topbar-title { font-size:var(--text-base); max-width:160px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .topbar-right { gap:.25rem; }
  .topbar-btn { width:34px; height:34px; }

  /* ── PAGE HEADER ── */
  .page-header { margin-bottom:1rem; }
  .page-header-top { flex-direction:column; align-items:flex-start; gap:.75rem; }
  .page-title { font-size:var(--text-lg); }
  .page-subtitle { font-size:var(--text-sm); }

  /* ── DASHBOARD GREETING ── */
  #school-logo-wrap img,
  #school-logo-wrap div { width:42px !important; height:42px !important; font-size:var(--text-base) !important; }
  #dash-welcome { font-size:var(--text-lg) !important; }

  /* ── CARDS ── */
  .card { border-radius:10px; }
  .card-header { padding:.875rem 1rem; flex-wrap:wrap; gap:.5rem; }

  /* ── KPI CARDS ── */
  .kpi-card { padding:.8rem .9rem; gap:.6rem; }
  .kpi-icon { width:40px !important; height:40px !important; font-size:1rem; }
  .kpi-value { font-size:var(--text-md); }
  .kpi-label { font-size:var(--text-xs); }

  /* ── TABS ── */
  .tab-btn { padding:.6rem .875rem; font-size:var(--text-sm); white-space:nowrap; }
  [style*="display:flex;gap:0;border-bottom"] { overflow-x:auto; -webkit-overflow-scrolling:touch; }

  /* ── TABLES ── */
  .table-wrapper { overflow-x:auto; -webkit-overflow-scrolling:touch; }
  .data-table { font-size:var(--text-base); }
  .data-table th, .data-table td { padding:.65rem .85rem; }

  /* ── FORMS ── */
  .form-control { font-size:var(--text-base); }
  .btn { font-size:var(--text-sm); }
  .btn-sm { font-size:var(--text-xs); padding:.3rem .65rem; }

  /* ── MODALS ── */
  .modal { width:calc(100vw - 2rem) !important; max-width:100% !important; }

  /* ── SIDEBAR OVERLAY ── */
  .sidebar-overlay { display:block; opacity:0; pointer-events:none; transition:opacity .2s; }
  .sidebar-overlay.show { opacity:1; pointer-events:all; }

  /* ── NOTIFICATIONS PANEL ── */
  .notif-panel { width:calc(100vw - 2rem) !important; right:.5rem !important; }

  /* ── SEARCH OVERLAY ── */
  .search-overlay { padding-top:40px; padding-left:.75rem; padding-right:.75rem; }
  .search-box { border-radius:12px; }
}

@media(max-width:768px) {

  /* ── LAYOUT ── */
  .page-content { padding:.75rem; }
  .grid-2 { grid-template-columns:1fr !important; }
  /* SYSTEMIC: .grid-3 was missing its mobile stack (only .grid-2 had one). */
  .grid-3 { grid-template-columns:1fr !important; }

  /* PROFILE HERO (shared, panel-tail PR A): the student / staff / admission
     profile headers are a gradient flex row (avatar + name block w/ min-width +
     action-button group). The name block's min-width forced the actions to wrap
     to a cramped narrow row in portrait. On a phone, stack the hero vertically
     (avatar, name, actions full-width) so the width is used well. Desktop (>768px)
     keeps the original horizontal layout untouched; landscape phones/tablets (769–1024px)
     fit horizontally already. The min-width:0 relaxes the inline name min-width. */
  .profile-hero { flex-direction:column !important; align-items:stretch !important; }
  .profile-hero > * { min-width:0 !important; }

  /* FILTER BARS (panel-tail PR A): form-CONTROL inline widths are relaxed at
     ≤1024px (line ~1070), but the .form-group WRAPPERS keep an inline min-width
     (attendance/settings filter bars) and cramp on a phone. Relax it. */
  .form-group[style*="min-width"] { min-width:0 !important; }
  /* SYSTEMIC: collapse fixed multi-column INLINE grids (repeat(3..6,...)) to 2
     columns so wide content can't overflow the viewport on mobile. The portal
     uses no `repeat(` inline grids (its one inline grid is `1.2fr 50px auto 1fr`),
     so this can't bleed into pp-*; responsive auto-fit/minmax grids don't contain
     the literal "repeat(3..6" and are unaffected. */
  div[style*="grid-template-columns:repeat(3"],
  div[style*="grid-template-columns:repeat(4"],
  div[style*="grid-template-columns:repeat(5"],
  div[style*="grid-template-columns:repeat(6"] { grid-template-columns:repeat(2,minmax(0,1fr)) !important; }
  /* NOTE: the inline `1fr 1fr` panel family is handled ADAPTIVELY in the
     @media(max-width:1024px) block below (auto-fit) — not stacked here — so it
     reflows correctly across phone portrait AND landscape. */

  /* ── DASHBOARD ── */
  .kpi-grid { grid-template-columns:repeat(2,1fr) !important; gap:.6rem; }
  /* SYSTEMIC (reported bug): .kpi-grid-dash opted out of scroll via
     overflow-x:visible, so wide dashboard fee cards clipped with no way to reach
     them. Restore horizontal scroll on mobile; columns already drop to 2 above. */
  .kpi-grid-dash { overflow-x:auto !important; }
  #dash-lower { gap:.75rem; }

  /* ── PAGE HEADER ── */
  .page-header-top > div:last-child { width:100%; }
  .page-header-top > div:last-child .btn { flex:1; justify-content:center; }

  /* ── INVOICE WEB VIEW ── */
  #invoice-view-wrap .card > div[style*="grid-template-columns:repeat(4"] {
    grid-template-columns:repeat(2,1fr) !important;
  }
  #invoice-view-wrap .card > div[style*="grid-template-columns:1fr 1fr"] {
    grid-template-columns:1fr !important;
  }
  #invoice-view-wrap div[style*="border-right:1px solid var(--grey-200)"] {
    border-right:none !important;
    border-bottom:1px solid var(--grey-100);
  }

  /* ── INVOICE ACTION BAR ── */
  #invoice-view-wrap > div:first-child {
    flex-wrap:wrap;
    gap:.5rem;
  }
  #invoice-view-wrap > div:first-child > div[style*="margin-left:auto"] {
    margin-left:0 !important;
    width:100%;
    display:grid !important;
    grid-template-columns:1fr 1fr;
    gap:.4rem;
  }

  /* ── TABLES ── data scrolls horizontally via .table-wrapper{overflow-x:auto};
     the old destructive column-hiding (nth-child display:none) is removed so NO
     column is hidden on mobile. ── */
  /* SYSTEMIC: tables with inline `table-layout:fixed;width:100%` fit their
     .table-wrapper exactly, so they squeeze/clip columns instead of triggering the
     wrapper's scroll. Give them a min-width on mobile so they exceed the wrapper and
     it scrolls (table-layout:fixed then spreads it across the % column widths). The
     inline width:100% keeps desktop fit-to-width — this rule is mobile-only, so
     desktop is unchanged. Matches all such tables (fees/admissions/settings/students). */
  .data-table[style*="table-layout:fixed"] { min-width:680px; }

  /* ── STUDENT PROFILE HERO ── */
  div[style*="linear-gradient(135deg"] { border-radius:12px !important; }

  /* ── ATTENDANCE REGISTER ── */
  .att-status-group { flex-wrap:wrap !important; }
  .att-status-group .btn { font-size:var(--text-xs) !important; padding:.15rem .4rem !important; }

  /* ── SETTINGS TABS ── */
  .settings-tabs { overflow-x:auto; }

  /* ── FILTER BARS ── */
  div[style*="display:flex;gap:.75rem;align-items:flex-end"] {
    flex-wrap:wrap;
  }
  div[style*="display:flex;gap:.75rem;align-items:flex-end"] > div,
  div[style*="display:flex;gap:.75rem;align-items:flex-end"] > select {
    width:100% !important;
    min-width:0 !important;
  }
}

@media(max-width:480px) {

  /* ── TYPOGRAPHY ── */
  .page-title { font-size:var(--text-lg) !important; }
  body { font-size:var(--text-base); }

  /* ── KPI ── */
  .kpi-grid { grid-template-columns:1fr 1fr !important; gap:.6rem; }
  .kpi-card { padding:.7rem; min-height:60px; }
  .kpi-value { font-size:var(--text-md); }
  .kpi-icon { width:40px !important; height:40px !important; }

  /* ── SIDEBAR BRAND ── */
  .sidebar-brand-text h1 { font-size:var(--text-base); }
  .sidebar-brand-text p { display:none; }

  /* ── TOPBAR ── */
  .topbar { padding:0 .75rem; }
  .topbar-title { max-width:120px; font-size:var(--text-sm); }

  /* ── USER CHIP ── */
  .user-name { font-size:var(--text-sm); }
  .user-role { font-size:var(--text-xs); }

  /* ── BUTTONS IN ACTION BARS ── */
  .page-header-top button,
  .page-header-top .btn { font-size:var(--text-xs); padding:.3rem .6rem; }

  /* ── CARDS ── */
  .card { border-radius:8px; }
  .card-header { padding:.75rem; }

  /* ── MODALS FULL SCREEN ── */
  .modal { margin:0 !important; border-radius:16px 16px 0 0 !important; }
  .modal-header, .modal-body { padding:1rem; }
  .modal-footer { padding:.75rem 1rem; }

  /* ── INVOICE INFO BAND ── */
  #invoice-view-wrap div[style*="grid-template-columns:repeat(4"] {
    grid-template-columns:1fr 1fr !important;
  }

  /* ── STAFF / STUDENT HERO ── */
  div[style*="linear-gradient(135deg"] > div[style*="display:flex;align-items:center"] {
    flex-wrap:wrap;
  }

  /* ── FEE MANAGEMENT ── */
  .kpi-grid.inv-summary { grid-template-columns:1fr 1fr !important; }

  /* ── TIMETABLE ── */
  #tt-grid-area { overflow-x:auto; -webkit-overflow-scrolling:touch; }
  #tt-grid-area table { min-width:500px; }

  /* ── SEARCH BOX ── */
  .search-input { font-size:var(--text-base); }
  .search-result-item { padding:.5rem 1rem; }
  .search-result-icon { width:28px; height:28px; font-size:var(--text-xs); }
}

/* ── PRINT STYLES ── */
@media print {
  .sidebar, .topbar, .sidebar-overlay, #fp-back-btn,
  .btn, button:not(.print-keep), .notif-panel, .search-overlay { display:none !important; }
  .main-content { margin-left:0 !important; }
  .page-content { padding:0 !important; }
  .card { box-shadow:none !important; border:1px solid #e2e8f0 !important; }
  body { background:white !important; }
  #invoice-print-area { page-break-inside:avoid; }
}

/* ── MOBILE FIXES PASS 2 ─────────────────────────────────────────────────── */

/* Ensure hamburger always visible on mobile portrait */
@media(max-width:1024px) {
  .hamburger { display:flex !important; }
  .sidebar { transform:translateX(-100%); }
  .sidebar.open { transform:translateX(0); }
  .main-content { margin-left:0 !important; }
  .sidebar-overlay { display:block; opacity:0; pointer-events:none; transition:opacity .2s; }
  .sidebar-overlay.show { opacity:1; pointer-events:all; }
}

/* Fix clamping and overlapping in tables */
@media(max-width:1024px) {
  /* Tables scroll horizontally via .table-wrapper (no destructive column-hiding). */

  /* Fix invoice info band overflow */
  div[style*="grid-template-columns:repeat(4,1fr)"] {
    grid-template-columns:repeat(2,1fr) !important;
  }

  /* Fix two-column grids */
  div[style*="grid-template-columns:1fr 2fr"],
  div[style*="grid-template-columns:2fr 1fr"] {
    grid-template-columns:1fr !important;
  }

  /* Grid/flex children default to min-width:auto, so ONE long unbroken string
     (an email, a payment reference) widens its column past the container and
     drags the whole page sideways. min-width:0 restores shrinkability — the
     minmax(0,1fr) fix, applied at the child so it covers every inline grid. */
  div[style*="display:grid"] > *, .grid-2 > *, .grid-3 > *, .form-grid > * {
    min-width:0;
  }

  /* PANEL-TAIL (adaptive): the inline `1fr 1fr` grid FAMILY reflows by AVAILABLE
     WIDTH, so rotation re-flows sensibly instead of a blunt single-column stack —
     phone PORTRAIT (~390px) -> 1 col (full cards don't clip; form pairs go
     full-width), phone LANDSCAPE (~750px) -> 2 cols (room returns), small tablets
     -> 2+. Scoped to <=1024px so DESKTOP (>1024px) keeps the original 2-col design.
     Floor 200px: above the width a full card needs to avoid clipping (forces 1 col
     across all phone-portrait widths up to ~430px) yet below landscape-phone width
     (2 cols return on rotation). The substring also catches `1fr 1fr 1fr` /
     `1fr 1fr auto` / `1fr 1fr Npx auto`. Portal-safe (portal's only inline grid is
     `1.2fr 50px auto 1fr`); class-based .grid-2/.grid-3 handled elsewhere. */
  div[style*="grid-template-columns:1fr 1fr"] {
    grid-template-columns:repeat(auto-fit,minmax(200px,1fr)) !important;
  }

  /* Fix action bars with many buttons */
  div[style*="display:flex;gap:.5rem"] > .btn,
  div[style*="display:flex;gap:.75rem"] > .btn {
    font-size:var(--text-xs) !important;
    padding:.3rem .5rem !important;
  }

  /* Fix KPI grid */
  .kpi-grid { grid-template-columns:repeat(2,1fr) !important; }

  /* Fix filter bars */
  .form-control[style*="width:"] { width:100% !important; min-width:0 !important; }

  /* Fix page header buttons wrapping */
  .page-header-top { flex-wrap:wrap; }
  .page-header-top > div:last-child { 
    display:flex; flex-wrap:wrap; gap:.4rem; width:100%;
  }

  /* Fix student/staff hero gradient cards */
  div[style*="linear-gradient(135deg"] div[style*="display:flex;gap:.5rem"] {
    flex-wrap:wrap;
  }
}

/* Portrait phone specific */
@media(max-width:480px) {
  /* Tables scroll horizontally via .table-wrapper (no destructive column-hiding). */

  /* Stack all inline flex rows */
  .card-header { flex-direction:column; align-items:flex-start !important; }
  .card-header > * { width:100%; }
  .card-header .btn, .card-header button { width:auto !important; }

  /* Fix fee invoice summary */
  #inv-summary { grid-template-columns:1fr 1fr !important; }

  /* Fix invoice action bar */
  #invoice-view-wrap > div:first-child {
    flex-wrap:wrap !important;
    gap:.4rem !important;
  }
  #invoice-view-wrap > div:first-child button {
    flex:1;
    font-size:var(--text-xs) !important;
    padding:.3rem .5rem !important;
  }

  /* Fix Bill To / Amount Summary stacking */
  div[style*="grid-template-columns:1fr 1fr;border-bottom"] {
    grid-template-columns:1fr !important;
  }

  /* Fix attendance status buttons */
  .status-btn { font-size:var(--text-xs) !important; padding:.15rem .35rem !important; }

  /* Timetable horizontal scroll */
  #tt-grid-area, .table-wrapper { 
    overflow-x:auto !important; 
    -webkit-overflow-scrolling:touch;
  }

  /* Fix modal width */
  .modal { 
    width:100vw !important; 
    max-width:100vw !important;
    margin:0 !important;
    border-radius:16px 16px 0 0 !important;
  }

  /* Search overlay full width */
  .search-box { border-radius:12px; width:100% !important; max-width:100% !important; }
  .search-overlay { padding:1rem .5rem !important; align-items:flex-start !important; padding-top:60px !important; }
}

/* ── MOBILE BOTTOM NAV ───────────────────────────────────────────────────── */
.mobile-bottom-nav {
  display: none;
  position: fixed;
  bottom: 0; left: 0; right: 0;
  height: 60px;
  background: white;
  border-top: 1px solid var(--grey-200);
  box-shadow: 0 -4px 20px rgba(0,0,0,.08);
  z-index: 200;
  padding: 0 env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
.mobile-bottom-nav-inner {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  height: 100%;
}
.mobile-nav-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  cursor: pointer;
  border: none;
  background: none;
  padding: .4rem .2rem;
  color: var(--grey-400);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: .02em;
  transition: color .15s;
  -webkit-tap-highlight-color: transparent;
  position: relative;
}
.mobile-nav-item svg { width: 22px; height: 22px; transition: transform .15s; }
.mobile-nav-item.active { color: var(--brand); }
.mobile-nav-item.active svg { transform: translateY(-1px); }
.mobile-nav-item .mob-badge {
  position: absolute;
  top: 6px; right: calc(50% - 18px);
  min-width: 14px; height: 14px;
  background: var(--red);
  color: white; font-size: var(--text-xs); font-weight: 800;
  border-radius: 99px; padding: 0 3px;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid white;
}
.mobile-nav-more-btn { position: relative; }

@media(max-width:1024px) {
  .mobile-bottom-nav { display: block; }
  .page-content { padding-bottom: 72px !important; }
  /* The fixed bottom-nav (60px, z-index:200) overlays the bottom of the open
     sidebar drawer, hiding the sign-out button. Lift the sidebar footer above the
     ribbon (+ iOS safe-area) so sign-out is fully visible/tappable on mobile.
     Mobile-only — desktop has no bottom ribbon. */
  .sidebar-footer { padding-bottom: calc(1rem + 60px + env(safe-area-inset-bottom)); }
}

/* ── SHORT VIEWPORT (phone landscape) ────────────────────────────────────── */
/* The nav itself was never the problem — .sidebar-nav already scrolls. The
   problem is the fixed chrome around it: the brand chip above, and below it a
   footer stacking a ~50px user-chip over a ~40px full-width sign-out, plus the
   60px bottom-nav clearance. That is ~180px of footer. In landscape (~360-420px
   of viewport height) the scrollable module list was left with ~100-160px —
   two or three items.
   So this compacts the CHROME, never the nav, and removes nothing: the user's
   identity and sign-out both stay, moved onto one row.
   The 60px clearance is KEPT: .mobile-bottom-nav is shown on width alone
   (max-width:1024px) and a landscape phone is ~740-850px wide, so the ribbon
   really is on screen — verified in the browser, not assumed. */
@media (max-height: 500px) {
  .sidebar-brand { padding: .5rem .9rem; }
  .school-logo-chip { min-height: 38px; padding: var(--space-1) var(--space-2); }
  .school-logo-chip img { max-height: 28px; }
  .school-initials { width: 28px; height: 28px; }
  .school-name { -webkit-line-clamp: 1; }
  .sidebar-nav { padding: .35rem 0; }

  /* Footer becomes ONE row: identity on the left, icon-only sign-out on the
     right. flex-shrink:0 on the footer stops it being squeezed out of the
     layout by the nav — .sidebar is overflow:hidden, so a clipped footer would
     be unreachable rather than merely small. */
  .sidebar-footer {
    display: flex; align-items: center; gap: .5rem;
    flex-shrink: 0;
    padding: .5rem .9rem;
  }
  .user-chip { margin-bottom: 0; flex: 1; min-width: 0; padding: .35rem .45rem; }
  .user-avatar { width: 30px; height: 30px; font-size: var(--text-sm); }
  .user-name { -webkit-line-clamp: 1; }
  .user-role { display: none; }
  /* Icon-only, but still a full 44px target. The label is hidden from sight,
     not from assistive tech — the button keeps its aria-label. */
  .btn-signout { width: 44px; min-width: 44px; height: 44px; flex-shrink: 0; padding: 0; }
  .btn-signout .signout-label { display: none; }
}

/* The bottom-ribbon clearance belongs ONLY where the ribbon exists. It is shown
   on width alone (max-width:1024px), which a landscape phone (~740-850px) does
   match — so the clearance is required there. A short DESKTOP window is short
   but wide, has no ribbon, and must not get 60px of dead space. */
@media (max-height: 500px) and (max-width: 1024px) {
  .sidebar-footer { padding-bottom: calc(.5rem + 60px + env(safe-area-inset-bottom)); }
}

/* ── TOUCH-FRIENDLY TABLE ROWS ───────────────────────────────────────────── */
@media(max-width:1024px) {
  .data-table tbody tr {
    cursor: pointer;
    position: relative;
    transition: background .12s;
    min-height: 60px;
  }
  .data-table tbody tr:active { background: var(--grey-50) !important; }
  .data-table tbody tr[style*="cursor:pointer"]::after {
    content: '';
    position: absolute;
    right: .75rem;
    top: 50%;
    transform: translateY(-50%);
    width: 6px; height: 6px;
    border-right: 2px solid var(--grey-300);
    border-top: 2px solid var(--grey-300);
    transform: translateY(-50%) rotate(45deg);
  }
  /* NOTE: no `.data-table td { display:flex }` here — at 481–768px+ it dropped the
     td's table-cell behaviour (cells left the column grid → header horizontal but
     body collapsed/misaligned) while thead stayed visible. Removed so mid-width screens
     renders a NORMAL table that scrolls in .table-wrapper. The ≤480px tables→cards
     transform (with its own td display:flex + thead:none + tr:block) is unaffected;
     the row tap target is preserved by `.data-table tbody tr { min-height:60px }`. */
}

/* ── SETUP-WIZARD STEPPER (PR C) ─────────────────────────────────────────────
   Desktop keeps the full 7-circle track. On phones the 7 nowrap labels overflow,
   so ≤768px swaps to a compact "Step X of N" + current-label + progress bar. */
.wizard-steps-compact { display: none; }
@media(max-width:768px) {
  .wizard-steps-full { display: none !important; }
  .wizard-steps-compact { display: block !important; }
}

/* ── STICKY ACTION BUTTON ────────────────────────────────────────────────── */
.sticky-action-bar {
  display: none;
}
@media(max-width:768px) {
  .sticky-action-bar {
    display: flex;
    position: fixed;
    bottom: 60px; left: 0; right: 0;
    padding: .75rem 1rem;
    background: white;
    border-top: 1px solid var(--grey-100);
    box-shadow: 0 -2px 12px rgba(0,0,0,.08);
    gap: .5rem;
    z-index: 190;
  }
  .sticky-action-bar .btn { flex: 1; justify-content: center; }
}

/* ── MOBILE FORM IMPROVEMENTS ────────────────────────────────────────────── */
@media(max-width:1024px) {
  input[type="number"] { -moz-appearance: textfield; }
  input[type="number"]::-webkit-outer-spin-button,
  input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; }
  .form-control, select.form-control, input.form-control {
    font-size: var(--text-md) !important;
    min-height: 48px;
    padding: 0.85rem 1rem !important;
  }
  textarea.form-control { font-size: var(--text-md) !important; min-height: 140px; }
  .btn { min-height: 48px; padding: 0.75rem 1.25rem; font-size: var(--text-base); }
  .btn-sm { min-height: 40px; padding: 0.5rem 1rem; }
  .btn-lg { min-height: 48px; padding: 0.85rem 1.5rem; }
  .btn-icon { min-width: 44px; min-height: 44px; font-size: 1.05rem; }
  .input-prefix { min-height: 48px; padding: 0.85rem 1rem; font-size: var(--text-md); }
}

/* ── REPORT CARD MOBILE ──────────────────────────────────────────────────── */
@media(max-width:1024px) {
  #report-card-paper {
    max-width:100% !important;
    margin:0 !important;
    border-radius:8px !important;
    font-size:var(--text-xs) !important;
  }

  /* Action bar on report card - stack buttons */
  #res-tab-content > div:first-child {
    flex-direction:column !important;
    align-items:stretch !important;
  }
  #res-tab-content > div:first-child > div {
    display:grid !important;
    grid-template-columns:1fr 1fr !important;
    gap:.4rem !important;
    width:100% !important;
  }
  #res-tab-content > div:first-child > div .btn {
    width:100% !important;
    justify-content:center !important;
    font-size:var(--text-xs) !important;
  }
}

@media(max-width:768px) {
  #report-card-paper {
    font-size:var(--text-xs) !important;
    border-radius:0 !important;
  }

  /* Report card header - stack logo and school info */
  #report-card-paper > div:first-child {
    padding:.75rem !important;
  }

  /* Subject results table - scrollable */
  #report-card-paper table {
    font-size:var(--text-xs) !important;
  }
  #report-card-paper .table-wrapper,
  #report-card-paper div[style*="overflow-x"] {
    overflow-x:auto !important;
    -webkit-overflow-scrolling:touch !important;
  }

  /* Hide position column on small screens */
  #report-card-paper table th:last-child,
  #report-card-paper table td:last-child {
    display:none !important;
  }

  /* Stack summary boxes */
  #report-card-paper div[style*="grid-template-columns:repeat(4"] {
    grid-template-columns:repeat(2,1fr) !important;
  }

  /* Comments section full width */
  #report-card-paper div[style*="grid-template-columns:1fr 1fr"] {
    grid-template-columns:1fr !important;
  }

  /* Page content no side padding for report card */
  #res-tab-content {
    padding:0 !important;
  }
}

/* ── REPORT CARD PORTRAIT SCALING ───────────────────────────────────────── */
@media(max-width:768px) {
  #report-card-paper {
    transform-origin: top left;
    transform: scale(0.52);
    width: calc(100% / 0.52) !important;
    margin-bottom: calc(-48% + 20px) !important;
    overflow: visible !important;
  }
}

@media(min-width:769px) and (max-width:1024px) {
  #report-card-paper {
    transform-origin: top left;
    transform: scale(0.72);
    width: calc(100% / 0.72) !important;
    margin-bottom: calc(-28% + 20px) !important;
    overflow: visible !important;
  }
}

/* ── FIX CONTENT CLIP ON MOBILE ─────────────────────────────────────────── */
@media(max-width:1024px) {
  .app-layout {
    overflow-x: hidden;
  }
  .main-content {
    width: 100% !important;
    min-width: 0 !important;
    overflow-x: hidden;
  }
  .page-content {
    width: 100% !important;
    min-width: 0 !important;
    box-sizing: border-box;
  }
  /* Ensure tabs don't overflow */
  .tab-btn-group, [style*="border-bottom:2px solid var(--grey-200)"] {
    overflow-x: auto !important;
    -webkit-overflow-scrolling: touch !important;
    scrollbar-width: none;
  }
  .tab-btn-group::-webkit-scrollbar { display: none; }
}


/* ── AI ASSISTANT PANEL ─────────────────────────────────────────────────── */
.ai-fab {
  position: fixed;
  bottom: 80px;
  right: 24px;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 4px 20px rgba(99,102,241,.5), 0 0 0 0 rgba(99,102,241,.4);
  animation: ai-pulse 2.5s infinite;
  transition: transform .2s, box-shadow .2s;
  z-index: 1000;
  color: white;
  font-size: 1.4rem;
}
.ai-fab:hover {
  transform: scale(1.1);
  box-shadow: 0 6px 28px rgba(99,102,241,.7), 0 0 0 8px rgba(99,102,241,.15);
}
.ai-fab .ai-fab-tooltip {
  position: absolute;
  right: 60px;
  background: #1e1e2e;
  color: white;
  font-size: var(--text-xs);
  font-weight: 600;
  padding: .35rem .75rem;
  border-radius: 6px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s;
  letter-spacing: .02em;
}
.ai-fab:hover .ai-fab-tooltip { opacity: 1; }
@keyframes ai-pulse {
  0% { box-shadow: 0 4px 20px rgba(99,102,241,.5), 0 0 0 0 rgba(99,102,241,.4); }
  70% { box-shadow: 0 4px 20px rgba(99,102,241,.5), 0 0 0 12px rgba(99,102,241,0); }
  100% { box-shadow: 0 4px 20px rgba(99,102,241,.5), 0 0 0 0 rgba(99,102,241,0); }
}

/* AI Slide Panel */
.ai-panel-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.35);
  backdrop-filter: blur(4px);
  z-index: 1100;
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s;
}
.ai-panel-overlay.open { opacity: 1; pointer-events: all; }

.ai-slide-panel {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  width: min(520px, 100vw);
  background: linear-gradient(160deg, #0f0f1a 0%, #1a1a2e 50%, #16213e 100%);
  z-index: 1200;
  transform: translateX(100%);
  transition: transform .35s cubic-bezier(.4,0,.2,1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.ai-slide-panel.open { transform: translateX(0); }

.ai-panel-header {
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid rgba(255,255,255,.08);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: rgba(99,102,241,.12);
  flex-shrink: 0;
}
.ai-panel-title {
  display: flex;
  align-items: center;
  gap: .65rem;
}
.ai-panel-logo {
  width: 32px; height: 32px;
  background: linear-gradient(135deg,#6366f1,#8b5cf6);
  border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  font-size: 1rem;
}
.ai-panel-name { font-size: var(--text-md); font-weight: 700; color: white; letter-spacing: -.01em; }
.ai-panel-sub { font-size: var(--text-xs); color: rgba(255,255,255,.45); margin-top: 1px; }
.ai-panel-close {
  width: 30px; height: 30px;
  border-radius: 8px;
  background: rgba(255,255,255,.08);
  border: none; cursor: pointer;
  color: rgba(255,255,255,.6);
  font-size: var(--text-md);
  display: flex; align-items: center; justify-content: center;
  transition: background .15s, color .15s;
}
.ai-panel-close:hover { background: rgba(255,255,255,.15); color: white; }

.ai-panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 1.25rem;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,.15) transparent;
}

/* AI Chat Input */
.ai-chat-wrap {
  padding: 1rem 1.25rem;
  border-top: 1px solid rgba(255,255,255,.08);
  flex-shrink: 0;
  background: rgba(0,0,0,.2);
}
.ai-chat-box {
  display: flex;
  gap: .5rem;
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 12px;
  padding: .5rem .75rem;
  transition: border-color .2s;
}
.ai-chat-box:focus-within { border-color: rgba(99,102,241,.6); }
.ai-chat-input {
  flex: 1;
  background: none;
  border: none;
  outline: none;
  color: white;
  font-size: var(--text-sm);
  font-family: inherit;
}
.ai-chat-input::placeholder { color: rgba(255,255,255,.3); }
.ai-chat-send {
  width: 30px; height: 30px;
  background: linear-gradient(135deg,#6366f1,#8b5cf6);
  border: none;
  border-radius: 8px;
  cursor: pointer;
  color: white;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--text-base);
  transition: opacity .15s, transform .15s;
  flex-shrink: 0;
}
.ai-chat-send:hover { opacity: .85; transform: scale(1.05); }
.ai-chat-suggestions {
  display: flex; flex-wrap: wrap; gap: .4rem;
  margin-bottom: .75rem;
}
.ai-suggestion-chip {
  background: rgba(99,102,241,.15);
  border: 1px solid rgba(99,102,241,.3);
  border-radius: 99px;
  padding: .3rem .75rem;
  font-size: var(--text-xs);
  color: rgba(255,255,255,.7);
  cursor: pointer;
  transition: background .15s, color .15s;
  white-space: nowrap;
}
.ai-suggestion-chip:hover { background: rgba(99,102,241,.35); color: white; }

/* AI Cards */
.ai-section-label {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(255,255,255,.35);
  margin: 1rem 0 .5rem;
}
.ai-card {
  background: rgba(255,255,255,.05);
  border: 1px solid rgba(255,255,255,.08);
  border-radius: 12px;
  padding: 1rem;
  margin-bottom: .65rem;
  transition: background .15s;
}
.ai-card:hover { background: rgba(255,255,255,.08); }
.ai-card-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: .5rem;
}
.ai-card-title { font-size: var(--text-sm); font-weight: 600; color: rgba(255,255,255,.85); }
.ai-badge {
  font-size: var(--text-xs); font-weight: 700; letter-spacing: .04em;
  padding: .2rem .55rem; border-radius: 99px; text-transform: uppercase;
}
.ai-badge-green { background: rgba(34,197,94,.15); color: #4ade80; border: 1px solid rgba(34,197,94,.2); }
.ai-badge-yellow { background: rgba(251,191,36,.15); color: #fbbf24; border: 1px solid rgba(251,191,36,.2); }
.ai-badge-red { background: rgba(239,68,68,.15); color: #f87171; border: 1px solid rgba(239,68,68,.2); }
.ai-badge-blue { background: rgba(99,102,241,.2); color: #a5b4fc; border: 1px solid rgba(99,102,241,.3); }
.ai-card-text { font-size: var(--text-sm); color: rgba(255,255,255,.5); line-height: 1.6; }
.ai-card-value { font-size: var(--text-xl); font-weight: 800; color: white; margin: .25rem 0 .1rem; }
.ai-card-meta { font-size: var(--text-xs); color: rgba(255,255,255,.4); }

/* Skeleton */
.ai-skeleton {
  background: linear-gradient(90deg, rgba(255,255,255,.05) 25%, rgba(255,255,255,.1) 50%, rgba(255,255,255,.05) 75%);
  background-size: 200% 100%;
  animation: ai-shimmer 1.5s infinite;
  border-radius: 6px;
}
@keyframes ai-shimmer { 0%{background-position:200% 0} 100%{background-position:-200% 0} }

/* Chat response bubble */
.ai-response {
  background: rgba(99,102,241,.12);
  border: 1px solid rgba(99,102,241,.2);
  border-radius: 12px;
  padding: 1rem;
  margin-bottom: .65rem;
}
.ai-response-label { font-size: var(--text-xs); font-weight: 700; color: #a5b4fc; letter-spacing: .06em; margin-bottom: .5rem; }
.ai-response-text { font-size: var(--text-sm); color: rgba(255,255,255,.75); line-height: 1.7; }

/* ── AI panel display polish (panel-scoped) ─────────────────────────────────
   Premium prose typography for the (XSS-sanitised) markdown render, named
   student tables, and the quality-floor a11y rules. All scoped to the AI panel;
   no :root token or shared class touched. */
.ai-pad { padding-top: .75rem; }
.ai-empty { font-size: var(--text-sm); color: rgba(255,255,255,.35); padding: .5rem 0; }

/* Prose: one quiet body role + a clear header scale; boldness spent on headers
   and strong only. */
.ai-prose { font-size: var(--text-sm); line-height: 1.7; color: rgba(255,255,255,.68); }
.ai-prose > :first-child { margin-top: 0; }
.ai-prose .ai-md-p { margin: .4rem 0; }
.ai-prose .ai-md-h1 { font-size: var(--text-base); font-weight: 700; letter-spacing: -.01em; color: rgba(255,255,255,.92); margin: .95rem 0 .4rem; }
.ai-prose .ai-md-h2 { font-size: var(--text-sm); font-weight: 700; color: rgba(255,255,255,.85); margin: .85rem 0 .35rem; }
.ai-prose .ai-md-h3 { font-size: var(--text-xs); font-weight: 600; color: rgba(255,255,255,.72); margin: .75rem 0 .3rem; }
.ai-prose .ai-md-list { margin: .35rem 0 .55rem; padding-left: 1.15rem; }
.ai-prose .ai-md-list li { margin-bottom: .22rem; line-height: 1.6; }
.ai-prose strong { font-weight: 700; color: rgba(255,255,255,.9); }
.ai-prose em { font-style: italic; color: rgba(255,255,255,.8); }

/* Named student tables (option d) — sit below the anonymised prose. */
.ai-tbl-title { font-size: var(--text-xs); font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: rgba(255,255,255,.4); margin: 1rem 0 .45rem; }
.ai-tbl-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; border: 1px solid rgba(255,255,255,.08); border-radius: 10px; }
.ai-tbl { width: 100%; border-collapse: collapse; font-size: var(--text-xs); }
.ai-tbl th { text-align: left; font-size: var(--text-xs); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: rgba(255,255,255,.4); background: rgba(255,255,255,.03); padding: .5rem .6rem; white-space: nowrap; border-bottom: 1px solid rgba(255,255,255,.08); }
.ai-tbl td { padding: .5rem .6rem; color: rgba(255,255,255,.7); border-top: 1px solid rgba(255,255,255,.05); white-space: nowrap; vertical-align: middle; }
.ai-tbl tbody tr:hover td { background: rgba(255,255,255,.03); }
.ai-tbl-r { text-align: right; font-variant-numeric: tabular-nums; }
.ai-tbl-name { font-weight: 600; color: rgba(255,255,255,.85); }
.ai-tbl-num { margin-left: .4rem; font-size: var(--text-xs); color: rgba(255,255,255,.35); font-variant-numeric: tabular-nums; }
.ai-tbl-bad { color: #f87171; font-weight: 600; }
.ai-tbl-warn { color: #fbbf24; font-weight: 600; }

/* Risk pill */
.ai-pill { display: inline-block; font-size: var(--text-xs); font-weight: 700; letter-spacing: .04em; padding: .12rem .45rem; border-radius: 99px; white-space: nowrap; }
.ai-pill-critical { background: rgba(239,68,68,.16); color: #f87171; border: 1px solid rgba(239,68,68,.25); }
.ai-pill-high { background: rgba(251,191,36,.16); color: #fbbf24; border: 1px solid rgba(251,191,36,.25); }
.ai-pill-medium { background: rgba(99,102,241,.18); color: #a5b4fc; border: 1px solid rgba(99,102,241,.28); }
.ai-pill-low { background: rgba(34,197,94,.15); color: #4ade80; border: 1px solid rgba(34,197,94,.22); }

/* Quality floor: visible keyboard focus on the panel's interactive controls. */
.ai-fab:focus-visible, .ai-panel-close:focus-visible, .ai-chat-send:focus-visible,
.ai-suggestion-chip:focus-visible, .ai-chat-input:focus-visible {
  outline: 2px solid #a5b4fc; outline-offset: 2px;
}

/* Quality floor: respect reduced-motion (kills the shimmer + slide/accordion
   transitions, incl. the inline max-height transition on the accordion bodies). */
@media (prefers-reduced-motion: reduce) {
  .ai-skeleton { animation: none; }
  .ai-slide-panel, .ai-panel-overlay, .ai-fab { transition: none; }
  [id^="acc-body-"] { transition: none !important; }
  /* The login reveal degrades to a plain fade — and the curtains are removed
     outright rather than left parked over the artwork. */
  .login-reveal .login-curtain { display: none; }
  .login-reveal .login-brand-img { animation: none; }
  .login-reveal .login-card { animation: loginCardFade .01s both; }
  @keyframes loginCardFade { from { opacity: 1; } to { opacity: 1; } }
}

/* Progress bar */
.ai-progress-wrap { margin: .5rem 0; }
.ai-progress-label { display: flex; justify-content: space-between; font-size: var(--text-xs); color: rgba(255,255,255,.4); margin-bottom: .3rem; }
.ai-progress-bar { height: 5px; background: rgba(255,255,255,.08); border-radius: 99px; overflow: hidden; }
.ai-progress-fill { height: 100%; border-radius: 99px; transition: width .6s ease; }

/* Settings sidebar navigation */
.settings-nav-btn {
  display: flex;
  align-items: center;
  gap: .5rem;
  width: 100%;
  background: none;
  border: none;
  padding: .55rem 1rem;
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--grey-600);
  text-align: left;
  cursor: pointer;
  transition: all .15s;
  border-radius: 0;
}
.settings-nav-btn:hover { background: var(--grey-50); color: var(--brand); }
.settings-nav-btn.active { background: var(--blue-light); color: var(--brand); font-weight: 600; }
