/*
 * PrepGro Theme v3 — Portal "Meridian" reskin.
 *
 * The engine plugin's StudentDashboard injects a runtime <style> block with
 * hardcoded values and !important flags, so neither theme.json nor the
 * --pge-ui-*/--brand-* token bridge can reach it. This file counters those rules
 * with strictly higher specificity (doubled body class) + !important, keeping
 * the fix at the theme level so plugin updates never wipe it.
 *
 * Design language (from prepgro-logo-kit-v34): Outfit, brand blue #1b3beb,
 * ink #03050f/#151c42, chip gradient #0c1b9e→#0a84ff→#4d93ff as the single
 * signature, hairline borders, layered soft elevation. No thick borders,
 * no offset shadows, no decorative rotation.
 */

/* ── Token bridge ──
   The React app reads --pge-ui-* custom properties (set on :root by the plugin
   bundle). Redefining them on the portal body maps the entire app — colors,
   type, borders, status hues — onto the PrepGro kit tokens in one move,
   without touching the compiled bundle. */
body.pge-portal-testprep,
body.pge-portal-competitive {
	--pge-ui-primary: var(--pge-color-primary, #1b3beb);
	--pge-ui-secondary: var(--pge-ink-500, #5f6894);
	--pge-ui-secondary-hover: var(--pge-ink-700, #3d4570);
	--pge-ui-success: var(--pge-green-600, #16a34a);
	--pge-ui-success-light: var(--pge-green-50, #f0fdf4);
	--pge-ui-warning: var(--pge-amber-600, #D97706);
	--pge-ui-warning-light: var(--pge-amber-50, #fffbeb);
	--pge-ui-danger: var(--pge-red-600, #DC2626);
	--pge-ui-danger-light: var(--pge-red-50, #fef2f2);
	--pge-ui-bg: var(--pge-gray-50, #f6f7fc);
	--pge-ui-surface: var(--pge-white, #ffffff);
	--pge-ui-border: var(--pge-gray-200, #dbe0f1);
	--pge-ui-border-hover: var(--pge-ink-400, #868fb6);
	--pge-ui-text-main: var(--pge-ink-950, #03050f);
	--pge-ui-text-secondary: var(--pge-ink-700, #3d4570);
	--pge-ui-text-muted: var(--pge-ink-500, #5f6894);
	--pge-ui-font-family: var(--pge-font-sans, 'Outfit', sans-serif);
}

/* ── Portal surface tokens ──
   Every surface, hairline and text colour in this file reads one of these,
   so dark mode is a matter of re-declaring six values rather than shadowing
   each rule one by one.

   That distinction matters: the rules below carry !important (they have to,
   to beat the bundle's own inline styles), and an !important declaration
   beats a non-!important one no matter how specific the latter is. So the
   old approach — a more-specific `html[data-pge-admin-theme="dark"][data-pge-dark-scope] …` rule
   without !important — could never win, which is why dark mode rendered
   light text on white cards. Flipping the custom properties sidesteps the
   cascade fight entirely. */
body.pge-portal-testprep,
body.pge-portal-competitive {
	--pgp-canvas: var(--pge-color-surface, #eceff9);
	--pgp-surface: var(--pge-white, #ffffff);
	--pgp-surface-2: var(--pge-gray-50, #f6f7fc);
	--pgp-line: var(--pge-color-line, #dbe0f1);
	--pgp-ink: var(--pge-color-ink, #03050f);
	--pgp-body: var(--pge-color-body, #3d4570);
	--pgp-muted: var(--pge-color-muted, #5f6894);
	/* Accent used as a FILL behind white text. Deliberately does not flip in
	   dark mode — see the note on --pge-color-primary below. */
	--pgp-accent-fill: var(--pge-color-primary, #1b3beb);
}
/* Scoped by [data-pge-dark-scope], not the body class alone —
 * `pge-portal-testprep` is on EVERY page, so flipping these globally would
 * drag the marketing pages into a dark mode they have no design for. The
 * scope attribute is stamped pre-paint (App_Shell::theme_boot / the React
 * shells) only on surfaces whose components actually support dark: the
 * dashboard, lesson/microlesson player, exam + diagnostic runners and the
 * result screens. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-testprep,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-competitive {
	--pgp-canvas: #0f131c;
	--pgp-surface: #1c2230;
	--pgp-surface-2: #232c3d;
	--pgp-line: #2a3345;
	--pgp-ink: #eef2f9;
	--pgp-body: #c6cfdd;
	--pgp-muted: #93a0b5;

	/* The React bundle reads the --pge-ui-* bridge directly, so those have to
	   flip too or the app's own components stay light. */
	--pge-ui-bg: #0f131c;
	--pge-ui-surface: #1c2230;
	--pge-ui-border: #2a3345;
	--pge-ui-border-hover: #3a465e;
	--pge-ui-text-main: #eef2f9;
	--pge-ui-text-secondary: #c6cfdd;
	--pge-ui-text-muted: #93a0b5;
	/* --pge-ui-primary is deliberately NOT lightened: the bundle uses it as a
	   button fill with white text, where #1b3beb already gives 8.6:1.
	   Lightening it to an on-dark blue dropped those buttons to 2.5:1. */

	/* Module accent. The bundle sets this inline as
	   `color: var(--pg-evaluate-accent, …)`, so re-declaring the token is
	   enough — nothing that reads it needs an override.

	   Only this one is flipped, deliberately. --pg-elevate-accent (#0a84ff)
	   already clears 4.8:1 on the dark surface, and both --pge-color-primary
	   and --pg-excel-accent-ink are used as button FILLS as well as text —
	   lightening those turned the "Schedule 1:1 support" button into a yellow
	   slab. Measure before flipping a token that does double duty. */
	--pg-evaluate-accent: #6ba4ff;
}



/* ── Canvas ── */
/* :not(.pg-app) — app-shell pages paint their own module grounds
   (body.pg-module-*); this flat canvas must not overrule them. */
body.pge-portal-testprep.pge-portal-testprep:not(.pg-app),
body.pge-portal-competitive.pge-portal-competitive:not(.pg-app) {
	background: var(--pgp-canvas) !important;
	animation: none !important;
	color: var(--pgp-ink) !important;
}

/* ── Portal typography ── */
body.pge-portal-testprep.pge-portal-testprep h1,
body.pge-portal-testprep.pge-portal-testprep h2,
body.pge-portal-testprep.pge-portal-testprep h3,
body.pge-portal-testprep.pge-portal-testprep h4,
body.pge-portal-competitive.pge-portal-competitive h1,
body.pge-portal-competitive.pge-portal-competitive h2,
body.pge-portal-competitive.pge-portal-competitive h3,
body.pge-portal-competitive.pge-portal-competitive h4 {
	font-family: var(--pge-font-heading, 'Outfit', sans-serif) !important;
	font-weight: 600;
	letter-spacing: -0.015em;
}

/* ── App shell typography — the compiled bundle's runtime <style> pins
   Inter on .pge-dash; keep the whole portal on the kit family. ── */
body.pge-portal-testprep.pge-portal-testprep .pge-dash,
body.pge-portal-competitive.pge-portal-competitive .pge-dash {
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
}

/* ── Sidebar: quiet white panel, hairline edge ── */
body.pge-portal-testprep.pge-portal-testprep .pge-dash-sidebar,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-sidebar {
	background: var(--pgp-surface) !important;
	backdrop-filter: none !important;
	-webkit-backdrop-filter: none !important;
	border: 1px solid var(--pgp-line) !important;
	border-radius: 14px !important;
	box-shadow: var(--pge-shadow-sm, 0 1px 2px rgba(3,5,15,.05)) !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-dash-sidebar-header,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-sidebar-header {
	border-bottom: 1px solid var(--pgp-line) !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-dash-sidebar-header h2,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-sidebar-header h2 {
	color: var(--pgp-ink) !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-dash-sidebar-header p,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-sidebar-header p {
	color: var(--pgp-muted) !important;
}

/* ── Sidebar nav items ── */
body.pge-portal-testprep.pge-portal-testprep .pge-dash-nav-item,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-nav-item {
	color: var(--pgp-muted) !important;
	font-weight: 500 !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-dash-nav-item:hover,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-nav-item:hover {
	background: var(--pgp-surface-2) !important;
	color: var(--pgp-ink) !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-dash-nav-item.active,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-nav-item.active {
	background: var(--pge-color-primary-soft, #edf1ff) !important;
	color: var(--pge-color-primary, #1b3beb) !important;
	font-weight: 600 !important;
	box-shadow: none !important;
	border-radius: 10px !important;
}
/* Active indicator bar — chip gradient */
body.pge-portal-testprep.pge-portal-testprep .pge-dash-nav-item.active::before,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-nav-item.active::before {
	background: var(--pge-gradient, linear-gradient(135deg, #0c1b9e, #0a84ff, #4d93ff)) !important;
}

/* The app now renders its own keyed SVG icons (TabIcon) — the old
   emoji-era treatment (hide the icon span, paint positional ::after
   mask icons) is retired; positional icons break the moment the menu
   changes, which is exactly what happened with the grouped menu. */
body.pge-portal-testprep.pge-portal-testprep .pge-dash-nav-icon,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-nav-icon {
	display: inline-flex !important;
	align-items: center;
	width: 18px;
	flex-shrink: 0;
}
/* ── Cards / stat tiles / empty states ── */
body.pge-portal-testprep.pge-portal-testprep .pge-card,
body.pge-portal-testprep.pge-portal-testprep .pge-neu-stat,
body.pge-portal-testprep.pge-portal-testprep .pge-neu-card,
body.pge-portal-testprep.pge-portal-testprep .pge-empty-state,
body.pge-portal-competitive.pge-portal-competitive .pge-card,
body.pge-portal-competitive.pge-portal-competitive .pge-neu-stat,
body.pge-portal-competitive.pge-portal-competitive .pge-neu-card,
body.pge-portal-competitive.pge-portal-competitive .pge-empty-state {
	background: var(--pgp-surface) !important;
	border: 1px solid var(--pgp-line) !important;
	border-radius: 14px !important;
	box-shadow: var(--pge-shadow-sm, 0 1px 2px rgba(3,5,15,.05)) !important;
	transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-card:hover,
body.pge-portal-testprep.pge-portal-testprep .pge-neu-stat:hover,
body.pge-portal-competitive.pge-portal-competitive .pge-card:hover,
body.pge-portal-competitive.pge-portal-competitive .pge-neu-stat:hover {
	transform: translateY(-2px) !important;
	border-color: rgba(27, 59, 235, .40) !important;
	box-shadow: var(--pge-shadow-md, 0 8px 24px -12px rgba(18,38,200,.18)) !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-card-header,
body.pge-portal-competitive.pge-portal-competitive .pge-card-header {
	border-bottom: 1px solid var(--pgp-line) !important;
}

/* ── Stat tile icons — one quiet tint, brand blue ── */
body.pge-portal-testprep.pge-portal-testprep .pge-neu-stat-icon,
body.pge-portal-competitive.pge-portal-competitive .pge-neu-stat-icon {
	background: var(--pge-color-primary-soft, #edf1ff) !important;
	border: 0 !important;
	border-radius: 10px !important;
	box-shadow: none !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-neu-stat:hover .pge-neu-stat-icon,
body.pge-portal-competitive.pge-portal-competitive .pge-neu-stat:hover .pge-neu-stat-icon {
	transform: none !important;
	background: var(--pge-color-accent-soft, #dbe3ff) !important;
}

/* ── Stat values / labels — mono numerals, editorial labels ── */
body.pge-portal-testprep.pge-portal-testprep .pge-neu-stat-value,
body.pge-portal-competitive.pge-portal-competitive .pge-neu-stat-value {
	color: var(--pgp-ink) !important;
	font-family: var(--pge-font-mono, 'JetBrains Mono', monospace) !important;
	font-weight: 700 !important;
	letter-spacing: -0.02em;
	font-variant-numeric: tabular-nums;
}
body.pge-portal-testprep.pge-portal-testprep .pge-neu-stat-label,
body.pge-portal-competitive.pge-portal-competitive .pge-neu-stat-label {
	color: var(--pgp-muted) !important;
	font-weight: 500 !important;
	letter-spacing: .06em;
	text-transform: uppercase;
	font-size: .72rem !important;
}

/* ── Flat stat cards (pge-stat-card family) ── */
body.pge-portal-testprep.pge-portal-testprep .pge-stat-card,
body.pge-portal-competitive.pge-portal-competitive .pge-stat-card {
	border: 1px solid var(--pgp-line) !important;
	border-left-width: 4px !important;
	box-shadow: var(--pge-shadow-sm, 0 1px 2px rgba(3,5,15,.05)) !important;
	border-radius: 12px !important;
}

/* ── Mobile bar ── */
body.pge-portal-testprep.pge-portal-testprep .pge-dash-mobile-bar,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-mobile-bar {
	background: var(--pgp-surface) !important;
	border: 1px solid var(--pgp-line) !important;
	border-radius: 12px !important;
	box-shadow: var(--pge-shadow-sm, 0 1px 2px rgba(3,5,15,.05)) !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-dash-mobile-toggle,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-mobile-toggle {
	color: var(--pgp-ink) !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-dash-mobile-item.active,
body.pge-portal-competitive.pge-portal-competitive .pge-dash-mobile-item.active {
	background: var(--pge-color-primary-soft, #edf1ff) !important;
	color: var(--pge-color-primary, #1b3beb) !important;
}

/* ── Proficiency distribution bar — slim segmented track.
   The compiled bundle renders a 28px solid band with inline styles (a
   full-red bar reads as an error banner). Until the next `npm run build`
   picks up the source fix, restyle it here via inline-style attribute
   hooks: slimmer, pill-shaped, no shouting percentages. ── */
body.pge-portal-testprep.pge-portal-testprep .pge-card div[style*="height: 28px"][style*="border-radius: 8px"],
body.pge-portal-competitive.pge-portal-competitive .pge-card div[style*="height: 28px"][style*="border-radius: 8px"] {
	height: 12px !important;
	border-radius: 999px !important;
	gap: 2px;
	background: var(--pge-gray-100, #eceff9);
}
body.pge-portal-testprep.pge-portal-testprep .pge-card div[style*="height: 28px"][style*="border-radius: 8px"] > div,
body.pge-portal-competitive.pge-portal-competitive .pge-card div[style*="height: 28px"][style*="border-radius: 8px"] > div {
	border-radius: 999px !important;
	font-size: 0 !important; /* tooltip + legend still carry the numbers */
}
/* Soften stock status hues to the kit ramp (old bundle only) */
body.pge-portal-testprep.pge-portal-testprep .pge-card div[style*="height: 28px"] > div[style*="rgb(239, 68, 68)"],
body.pge-portal-competitive.pge-portal-competitive .pge-card div[style*="height: 28px"] > div[style*="rgb(239, 68, 68)"] {
	background: var(--pge-red-600, #DC2626) !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-card div[style*="height: 28px"] > div[style*="rgb(16, 185, 129)"],
body.pge-portal-competitive.pge-portal-competitive .pge-card div[style*="height: 28px"] > div[style*="rgb(16, 185, 129)"] {
	background: var(--pge-green-600, #16a34a) !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-card div[style*="height: 28px"] > div[style*="rgb(59, 130, 246)"],
body.pge-portal-competitive.pge-portal-competitive .pge-card div[style*="height: 28px"] > div[style*="rgb(59, 130, 246)"] {
	background: var(--pge-blue-600, #1b3beb) !important;
}
body.pge-portal-testprep.pge-portal-testprep .pge-card div[style*="height: 28px"] > div[style*="rgb(245, 158, 11)"],
body.pge-portal-competitive.pge-portal-competitive .pge-card div[style*="height: 28px"] > div[style*="rgb(245, 158, 11)"] {
	background: var(--pge-amber-600, #D97706) !important;
}

/* ── Retake nudge ("Did you know?") — brand family, not garden green.
   Duplicates the source-level fix so pre-rebuild bundles render on-brand. ── */
body.pge-portal-testprep.pge-portal-testprep [data-retake-nudge].pge-card,
body.pge-portal-competitive.pge-portal-competitive [data-retake-nudge].pge-card {
	background: linear-gradient(135deg, var(--pge-blue-50, #edf1ff) 0%, var(--pge-gray-25, #f6f7fc) 100%) !important;
	border: 1px solid var(--pge-gray-200, #dbe0f1) !important;
}
body.pge-portal-testprep.pge-portal-testprep [data-retake-nudge].pge-card > div > div:first-child,
body.pge-portal-competitive.pge-portal-competitive [data-retake-nudge].pge-card > div > div:first-child {
	color: var(--pgp-ink) !important;
}
body.pge-portal-testprep.pge-portal-testprep [data-retake-nudge].pge-card p,
body.pge-portal-competitive.pge-portal-competitive [data-retake-nudge].pge-card p {
	color: var(--pgp-body) !important;
}
body.pge-portal-testprep.pge-portal-testprep [data-retake-nudge].pge-card a,
body.pge-portal-competitive.pge-portal-competitive [data-retake-nudge].pge-card a {
	/* --pgp-accent-fill, not --pge-color-primary: this is a FILL behind white
	   text, and dark mode lightens the primary so accent TEXT stays legible
	   on dark cards. Using the text accent here would wash the button out. */
	background: var(--pgp-accent-fill) !important;
	border-radius: 10px !important;
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, .16), 0 2px 8px rgba(27, 59, 235, .25) !important;
}
body.pge-portal-testprep.pge-portal-testprep [data-retake-nudge].pge-card a:hover,
body.pge-portal-competitive.pge-portal-competitive [data-retake-nudge].pge-card a:hover {
	background: var(--pge-color-primary-strong, #0c1b9e) !important;
}
body.pge-portal-testprep.pge-portal-testprep [data-retake-nudge="dismiss"],
body.pge-portal-competitive.pge-portal-competitive [data-retake-nudge="dismiss"] {
	color: var(--pge-ink-400, #868fb6) !important;
}

/* ── Profile-gate banner: urgent but composed ── */
#pge-profile-gate-banner {
	background: var(--pge-color-ink-2, #151c42) !important;
	color: #ffffff !important;
	border-bottom: 0 !important;
	box-shadow: 0 8px 24px -8px rgba(0, 0, 0, .35) !important;
	animation: none !important;
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
}
#pge-profile-gate-banner::before {
	content: "";
	display: block;
	height: 3px;
	background: var(--pge-color-danger, #DC2626);
}
#pge-profile-gate-banner > div > div:first-child {
	background: rgba(220, 38, 38, .18) !important;
	border: 1px solid rgba(220, 38, 38, .45) !important;
	border-radius: 10px !important;
	animation: none !important;
	color: #FCA5A5;
}
#pge-profile-gate-banner strong {
	font-family: var(--pge-font-heading, 'Outfit', sans-serif) !important;
	font-weight: 600 !important;
}
#pge-profile-gate-banner a {
	background: #ffffff !important;
	color: var(--pge-color-ink, #03050f) !important;
	border: 0 !important;
	border-radius: 10px !important;
	box-shadow: 0 2px 8px rgba(0, 0, 0, .25) !important;
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
	font-weight: 600 !important;
}

/* ═══════════════════════════════════════════════════════════════
   LOGIN / GET-STARTED (signup) — .pge-lg-* split-screen template.
   Plugin prints its CSS inline in wp_footer, so overrides carry
   !important. US-school flag colors stay flag-true in the tricolor;
   everything else uses the kit system.
   ═══════════════════════════════════════════════════════════════ */
.pge-lg-wrapper {
	border: 1px solid var(--pgp-line) !important;
	border-radius: 16px !important;
	box-shadow: var(--pge-shadow-lg, 0 24px 48px -16px rgba(18,38,200,.22)) !important;
	background: var(--pgp-surface) !important;
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
}
.pge-lg-theme-us-school .pge-lg-brand,
.pge-lg-theme-edu .pge-lg-brand {
	background:
		radial-gradient(720px 480px at 82% -10%, rgba(10, 132, 255, .28), transparent 60%),
		linear-gradient(160deg, var(--pge-color-ink, #03050f), var(--pge-color-ink-2, #151c42)) !important;
}
/* Flag tricolor stays flag-true — the country-of-operation cue.
   Scoped to the US install: the us-school LAYOUT is shared by every pack
   with hero copy (the engine picks it whenever content.hero exists), so an
   unscoped rule painted US red/navy and a US star on the Canadian login
   panel. Non-US packs render their own content.flag_strip from login.php
   and get no watermark until one is authored for them. */
body.brand-region-usa .pge-lg-theme-us-school .pge-lg-tricolor { height: 4px !important; }
body.brand-region-usa .pge-lg-theme-us-school .pge-lg-tri-saffron { background: #B22234 !important; }
body.brand-region-usa .pge-lg-theme-us-school .pge-lg-tri-white   { background: #F5F1E8 !important; display: block !important; }
body.brand-region-usa .pge-lg-theme-us-school .pge-lg-tri-green   { background: #3C3B6E !important; }
/* Star watermark — USA counterpart of the India chakra */
body.brand-region-usa .pge-lg-theme-us-school .pge-lg-brand::after {
	content: "";
	position: absolute;
	top: 28px; right: 20px;
	width: 280px; height: 280px;
	background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath d='M50 6 L59.5 36.5 L92 36.5 L66 55.5 L75.5 86 L50 67 L24.5 86 L34 55.5 L8 36.5 L40.5 36.5 Z' fill='none' stroke='%237CB0FF' stroke-width='1.6' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center / contain;
	opacity: .28;
	transform: rotate(12deg);
	pointer-events: none;
}
.pge-lg-brand-title, .pge-lg-form-title {
	font-family: var(--pge-font-heading, 'Outfit', sans-serif) !important;
	font-weight: 600 !important;
	letter-spacing: -0.02em;
}
.pge-lg-theme-us-school .pge-lg-brand-title-accent,
.pge-lg-wrapper .pge-lg-brand-title-accent {
	color: var(--pge-color-on-dark, #6ba4ff) !important;
	background: none !important;
	-webkit-background-clip: initial !important;
	background-clip: initial !important;
	-webkit-text-fill-color: var(--pge-color-on-dark, #6ba4ff) !important;
}
.pge-lg-theme-us-school .pge-lg-feature-icon { color: var(--pge-color-on-dark, #6ba4ff) !important; }
.pge-lg-theme-us-school .pge-lg-input:focus {
	border-color: var(--pge-color-primary, #1b3beb) !important;
	box-shadow: 0 0 0 3px rgba(27, 59, 235, .22) !important;
}
.pge-lg-theme-us-school .pge-lg-btn,
.pge-lg-theme-edu .pge-lg-btn {
	background: var(--pge-color-primary, #1b3beb) !important;
	color: #ffffff !important;
	border: 0 !important;
	border-radius: 10px !important;
	box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 1px 2px rgba(3,5,15,.1) !important;
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
	font-weight: 600 !important;
}
.pge-lg-theme-us-school .pge-lg-btn:hover,
.pge-lg-theme-edu .pge-lg-btn:hover {
	background: var(--pge-color-primary-strong, #0c1b9e) !important;
	transform: translateY(-1px);
	box-shadow: inset 0 1px 0 rgba(255,255,255,.14), 0 8px 24px -12px rgba(18,38,200,.4) !important;
}
.pge-lg-theme-us-school .pge-lg-forgot,
.pge-lg-theme-us-school .pge-lg-signup-prompt a { color: var(--pge-color-primary, #1b3beb) !important; }
.pge-lg-tabs { border: 1px solid var(--pgp-line) !important; border-radius: 10px !important; overflow: hidden; }
.pge-lg-tab.active, .pge-lg-tab[aria-selected="true"] {
	background: var(--pge-color-primary, #1b3beb) !important;
	color: #ffffff !important;
}
/* The inactive tab, the field hairlines, the divider and the legal links
   were the one corner of this page the color-only fix above can't reach —
   they were never tied to $primary, just hardcoded slate. */
.pge-lg-tab:not(.is-active):not([aria-selected="true"]) { color: var(--pge-ink-500, #5f6894) !important; }
.pge-lg-input { border-color: var(--pge-color-line, #dbe0f1) !important; }
.pge-lg-divider { color: var(--pge-ink-400, #868fb6) !important; }
.pge-lg-divider::before, .pge-lg-divider::after { background: var(--pge-color-line, #dbe0f1) !important; }
.pge-lg-legal { color: var(--pge-ink-400, #868fb6) !important; }
.pge-lg-legal a { color: var(--pge-ink-500, #5f6894) !important; }
.pge-lg-legal a:hover { color: var(--pge-color-ink, #03050f) !important; }
.pge-lg-social .nsl-container-buttons a { border-color: var(--pge-color-line, #dbe0f1) !important; }

/* Error / success notices. Both login.php and its forgot-password panel set
   these via `style="background:#fef2f2;…"` directly on the element — an
   inline style an external stylesheet can only beat with !important, no
   matter how specific the selector. Colours map to the kit's semantic red
   and green rather than the plugin's literal hexes. */
#pge-lg-error, #pge-fp-error {
	background: var(--pge-red-50, #fef2f2) !important;
	border-color: var(--pge-red-600, #dc2626) !important;
	color: var(--pge-red-600, #dc2626) !important;
	border-radius: 10px !important;
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
}
#pge-lg-success, #pge-fp-success {
	background: var(--pge-green-50, #f0fdf4) !important;
	border-color: var(--pge-green-600, #16a34a) !important;
	color: var(--pge-green-600, #16a34a) !important;
	border-radius: 10px !important;
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
}

/* Signup only: its own trailing <style> block (signup.php), not
   login-styles.php — same class-based pattern as the notices above, so no
   !important fight this time, but kept for consistency with the rest of
   this section. */
.pge-lg-wrapper .pge-sl-message-error {
	background: var(--pge-red-50, #fef2f2) !important;
	border-color: var(--pge-red-600, #dc2626) !important;
	color: var(--pge-red-600, #dc2626) !important;
}
.pge-lg-wrapper .pge-sl-message-success {
	background: var(--pge-green-50, #f0fdf4) !important;
	border-color: var(--pge-green-600, #16a34a) !important;
	color: var(--pge-green-600, #16a34a) !important;
}
.pge-lg-wrapper .pge-lg-trust-row { border-top-color: var(--pge-color-line, #dbe0f1) !important; }
.pge-lg-wrapper .pge-lg-trust-row span { color: var(--pge-ink-400, #868fb6) !important; }

/* ═══════════════════════════════════════════════════════════════
   PASSWORD RESET — .pge-rp-* (templates/public/password-reset.php).
   Zero theme coverage before this: the whole page was on the retired
   system font stack, slate palette and a diagonal-gradient hero. Colour
   already tracks $primary now that PGT_BRAND_PRIMARY filters the
   `pge_primary_color` option in functions.php — this section is the
   typography/shape/shadow half color alone can't fix.
   ═══════════════════════════════════════════════════════════════ */
.pge-rp-wrapper { font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important; }
.pge-rp-hero {
	/* Same ink + radial-glow treatment as .pge-lg-brand, so a visitor who
	   just came from /login/ reads this as the same product, not a diagonal
	   brand-blue gradient with no connection to the page before it. */
	background:
		radial-gradient(720px 480px at 82% -10%, rgba(10, 132, 255, .28), transparent 60%),
		linear-gradient(160deg, var(--pge-color-ink, #03050f), var(--pge-color-ink-2, #151c42)) !important;
}
/* .pge-rp-hero-title is an <h1> on a dark gradient, and the engine's global
   rule (body.pge-portal-*:not(:has(.pge-gje-v5)) h1..h4 { color: ink !important })
   — the same one that hid the module page hero titles — paints it ink-on-ink
   here too, since this page keeps its header/footer chrome (unlike
   login/signup) and so carries the pge-portal-* body class. */
.pge-rp-hero-title {
	font-family: var(--pge-font-heading, 'Outfit', sans-serif) !important;
	font-weight: 600 !important;
	letter-spacing: -.02em;
	color: #fff !important;
	-webkit-text-fill-color: #fff !important;
}
.pge-rp-card-inner {
	border: 1px solid var(--pgp-line, #dbe0f1) !important;
	border-radius: var(--pge-radius-lg, 20px) !important;
	box-shadow: var(--pge-shadow-lg, 0 24px 48px -16px rgba(18,38,200,.22)) !important;
}
.pge-rp-form-title { font-family: var(--pge-font-heading, 'Outfit', sans-serif) !important; color: var(--pge-color-ink, #03050f) !important; }
.pge-rp-form-sub { color: var(--pge-ink-400, #868fb6) !important; }
.pge-rp-label { color: var(--pge-color-body, #3d4570) !important; }
.pge-rp-req { color: var(--pge-red-600, #dc2626) !important; }
.pge-rp-input { border-color: var(--pge-color-line, #dbe0f1) !important; color: var(--pge-color-ink, #03050f) !important; }
.pge-rp-strength-bar { background: var(--pge-gray-100, #eceff9) !important; }
/* Flat, not the plugin's diagonal gradient — the redesign's buttons are
   solid fills; the brand-color hover comes from a darker token step, not
   opacity, matching every other primary button on the site. */
.pge-rp-btn {
	background: var(--pge-color-primary, #1b3beb) !important;
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
}
.pge-rp-btn:hover { background: var(--pge-color-primary-strong, #0c1b9e) !important; opacity: 1 !important; }
.pge-rp-trust { border-top-color: var(--pge-color-line, #dbe0f1) !important; }
.pge-rp-trust span { color: var(--pge-ink-400, #868fb6) !important; }

/* ═══════════════════════════════════════════════════════════════
   EMAIL VERIFICATION — .pge-verify-* / .pge-otp-*
   (templates/public/email-verification.php). Same story as password
   reset: zero coverage, system fonts, slate palette. The verify/resend/
   update buttons set `style="background:$primary"` inline per-element —
   fixed automatically by the option filter, no override needed here.
   ═══════════════════════════════════════════════════════════════ */
.pge-verify-wrap { font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important; }
.pge-verify-card {
	border: 1px solid var(--pgp-line, #dbe0f1) !important;
	border-radius: var(--pge-radius-lg, 20px) !important;
	box-shadow: var(--pge-shadow-lg, 0 24px 48px -16px rgba(18,38,200,.22)) !important;
}
.pge-verify-title { font-family: var(--pge-font-heading, 'Outfit', sans-serif) !important; color: var(--pge-color-ink, #03050f) !important; }
.pge-verify-desc { color: var(--pge-ink-400, #868fb6) !important; }
.pge-verify-desc strong { color: var(--pge-color-body, #3d4570) !important; }
/* Numeral entry — mono face, same as every other numeric field in the
   redesign (scores, prices, question counts). */
.pge-otp-input {
	border-color: var(--pge-color-line, #dbe0f1) !important;
	color: var(--pge-color-ink, #03050f) !important;
	background: var(--pge-gray-50, #f6f7fc) !important;
	font-family: var(--pge-font-mono, monospace) !important;
}
.pge-otp-input:focus { background: var(--pge-white, #fff) !important; }
.pge-verify-status { font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important; }
.pge-status-error {
	background: var(--pge-red-50, #fef2f2) !important;
	color: var(--pge-red-600, #dc2626) !important;
	border-color: var(--pge-red-600, #dc2626) !important;
}
.pge-status-success {
	background: var(--pge-green-50, #f0fdf4) !important;
	color: var(--pge-green-600, #16a34a) !important;
	border-color: var(--pge-green-600, #16a34a) !important;
}
.pge-verify-resend { color: var(--pge-ink-400, #868fb6) !important; }
.pge-email-input { border-color: var(--pge-color-line, #dbe0f1) !important; }

/* ═══════════════════════════════════════════════════════════════
   LOGGED-OUT GATE — .pge-login-required (templates/public/login-required.php).
   Shown on student-only surfaces (e.g. the Excel portal) to a logged-out
   visitor. Its CTA carries classes `pge-btn pge-btn-primary`, which are only
   ever DEFINED in the React bundle's compiled CSS — on a marketing page
   that never loads that bundle, the button was bare underlined link text.
   Styled directly here instead of chasing that class into existing.
   ═══════════════════════════════════════════════════════════════ */
.pge-login-required {
	background: var(--pgp-surface, #fff) !important;
	border: 1px solid var(--pgp-line, #dbe0f1) !important;
	border-radius: var(--pge-radius-lg, 20px) !important;
	box-shadow: var(--pge-shadow-md, 0 8px 24px -12px rgba(18,38,200,.18)) !important;
}
.pge-login-required__message {
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
	color: var(--pgp-body, #3d4570) !important;
}
.pge-login-required__cta {
	background: var(--pge-color-primary, #1b3beb) !important;
	color: #fff !important;
	border-radius: var(--pge-radius-pill, 999px) !important;
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
	box-shadow: inset 0 1px 0 rgba(255,255,255,.16), 0 1px 2px rgba(3,5,15,.1) !important;
	transition: background 140ms var(--pgt-ease, ease), transform 140ms var(--pgt-ease, ease);
}
.pge-login-required__cta:hover {
	background: var(--pge-color-primary-strong, #0c1b9e) !important;
	transform: translateY(-1px);
}

/* ═══════════════════════════════════════════════════════════════
   ALL-EXAMS / exam search — .pge-es__*
   Styling now lives in the plugin's own component stylesheet
   (templates/public/exam-search-styles.php), which consumes the
   --pge-* token contract directly. Theme-side overrides removed —
   per the token contract, branding overrides tokens only, never
   the plugin's component CSS.
   ═══════════════════════════════════════════════════════════════ */

/* ── Floating CTA pill: amber → brand gradient ── */
#pge-floating-cta-btn {
	background: var(--pge-gradient, linear-gradient(135deg, #0c1b9e, #0a84ff, #4d93ff)) !important;
	color: #fff !important;
	font-family: var(--pge-font-sans, 'Outfit', sans-serif) !important;
	font-weight: 600 !important;
	box-shadow: 0 8px 24px -8px rgba(18, 38, 200, .5) !important;
	animation: none !important;
}
#pge-floating-cta-btn:hover {
	box-shadow: 0 12px 32px -8px rgba(18, 38, 200, .6) !important;
}

/* ── Friendly proctor warning overlay (see theme.js initProctorAlerts) ── */
#pgt-proctor-toast {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: none;
	align-items: flex-start;
	justify-content: center;
	padding-top: 12vh;
	background: rgba(3, 5, 15, .45);
	backdrop-filter: blur(3px);
}
#pgt-proctor-toast.is-open { display: flex; }
.pgt-proctor-toast__card {
	background: var(--pgp-surface);
	border: 1px solid var(--pge-color-line, #dbe0f1);
	border-radius: 14px;
	box-shadow: 0 24px 48px -16px rgba(3, 5, 15, .4);
	max-width: 420px;
	width: calc(100% - 32px);
	padding: 1.6rem 1.7rem;
	text-align: center;
	position: relative;
	overflow: hidden;
	animation: pgt-toast-in .26s cubic-bezier(.22,.61,.36,1) both;
}
.pgt-proctor-toast__card::before {
	content: "";
	position: absolute; top: 0; left: 0; right: 0;
	height: 3px;
	background: var(--pge-gradient, linear-gradient(135deg, #0c1b9e, #0a84ff, #4d93ff));
}
.pgt-proctor-toast__card.is-final::before { background: var(--pge-color-danger, #DC2626); }
@keyframes pgt-toast-in { from { opacity: 0; transform: translateY(-12px) scale(.98); } to { opacity: 1; transform: none; } }
.pgt-proctor-toast__head {
	display: inline-block;
	font-family: var(--pge-font-heading, 'Outfit', sans-serif);
	font-weight: 600;
	font-size: 1.15rem;
	color: var(--pge-color-ink, #03050f);
	margin-bottom: .7rem;
}
.pgt-proctor-toast__card.is-final .pgt-proctor-toast__head { color: var(--pge-color-danger, #DC2626); }
.pgt-proctor-toast__reason { color: var(--pgp-body); margin: 0 0 .6rem; font-size: .98rem; line-height: 1.55; }
.pgt-proctor-toast__count { color: var(--pgp-muted); font-size: .84rem; font-weight: 500; margin-bottom: 1.1rem; }
.pgt-proctor-toast__ok {
	font-family: var(--pge-font-sans, 'Outfit', sans-serif);
	font-weight: 600;
	font-size: .93rem;
	color: #fff;
	background: var(--pge-color-primary, #1b3beb);
	border: 0;
	border-radius: 10px;
	box-shadow: inset 0 1px 0 rgba(255,255,255,.16);
	padding: .7rem 1.3rem;
	cursor: pointer;
	transition: background .15s ease;
}
.pgt-proctor-toast__ok:hover { background: var(--pge-color-primary-strong, #0c1b9e); }
@media (prefers-reduced-motion: reduce) { .pgt-proctor-toast__card { animation: none; } }

/* ── Reduced motion ── */
@media (prefers-reduced-motion: reduce) {
	body.pge-portal-testprep.pge-portal-testprep *,
	body.pge-portal-competitive.pge-portal-competitive * {
		transition: none !important;
	}
}

/* ═══════════════════════════════════════════════════════════════════════
   Portal shell — 2026-08 redesign (README §11/§12).

   This block REPLACES the 274-line inline <style> that StudentDashboard.jsx
   used to ship. The component no longer emits a style string; these rules
   live here so they cascade with the rest of the theme and can be edited
   without a JS rebuild.

   Two deliberate departures from what that block did:
     - The neumorphic / glassmorphic treatment is gone. §11 says flat card,
       1px border, cool layered shadow only, and the design system does not
       use transparency or backdrop-filter anywhere.
     - The shell is flex-wrap, not a fixed two-column grid, so the sidebar
       drops above the content on narrow screens with no media query.
   ═══════════════════════════════════════════════════════════════════════ */

/* Portal ground. One quiet surface — the old animated multi-radial azure
   wash is retired along with the neumorphism. */
body.pge-portal-competitive,
body.pge-portal-testprep {
	background: var(--pgp-surface-2);
	color: var(--pgp-ink);
}

.pge-dash {
	max-width: 1200px;
	margin: clamp(18px, 3vw, 28px) auto clamp(40px, 5vw, 56px);
	padding: 0 clamp(14px, 3vw, 28px);
	display: flex;
	flex-wrap: wrap;
	gap: 22px;
	align-items: flex-start;
	font-family: var(--pge-font-sans);
}
/* 240px on desktop, full width when it wraps — no media query needed. */
.pge-dash-sidebar {
	flex: 1 1 240px;
	max-width: 280px;
	width: auto;
	background: var(--pgp-surface);
	border: 1px solid var(--pgp-line);
	border-radius: 20px;
	padding: 16px;
	position: sticky;
	top: 16px;
	align-self: flex-start;
	box-shadow: none;
}
.pge-dash-content { flex: 999 1 560px; min-width: 0; }

/* Below ~900px the sidebar's flex-basis (240) + the content's (560) + gap
   no longer fit one line, so the sidebar wraps onto its own row above the
   content. It's still `position: sticky` there — and a sticky item's
   containing block is the whole `.pge-dash` box, not just its own wrapped
   line, so it keeps sticking through the content row's scroll too. Being
   positioned, it then paints over the in-flow (static) content underneath
   it, which reads as the Readiness page overlapping the sidebar. Drop
   sticky before the wrap point so it just scrolls with the page instead. */
@media (max-width: 900px) {
	.pge-dash-sidebar { position: static; top: auto; }
}

.pge-dash-sidebar-header {
	display: flex;
	align-items: center;
	gap: 11px;
	padding: 6px 8px 16px;
	border-bottom: 1px solid var(--pge-gray-100);
	margin-bottom: 10px;
}
.pge-dash-sidebar-brandchip {
	width: 40px; height: 40px; flex-shrink: 0;
	border-radius: 50%;
	background: var(--pge-gradient);
	display: flex; align-items: center; justify-content: center;
	box-shadow: none;
}
.pge-dash-sidebar-header h2 {
	margin: 0;
	font-size: 14.5px;
	font-weight: 600;
	font-family: var(--pge-font-heading);
	color: var(--pgp-ink);
	letter-spacing: -0.01em;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.pge-dash-sidebar-header p { margin: 2px 0 0; font-size: 12px; color: var(--pge-ink-400); font-weight: 400; }

/* Nav rows: 44px targets, pill-adjacent 12px radius, tint when active. The
   sliding left rail and the translateX hover are gone — 120–150ms, no
   bounces, no motion that moves a hit target under the cursor. */
.pge-dash-nav-item {
	display: flex;
	align-items: center;
	gap: 11px;
	width: 100%;
	margin: 2px 0;
	min-height: 44px;
	padding: 0 12px;
	border: none;
	background: transparent;
	cursor: pointer;
	font-size: 14px;
	font-weight: 500;
	color: var(--pgp-body);
	text-align: left;
	border-radius: 12px;
	font-family: inherit;
	transition: background-color 140ms ease, color 140ms ease;
}
.pge-dash-nav-item::before { content: none; }
.pge-dash-nav-item:hover { background: var(--pgp-surface-2); color: var(--pgp-ink); transform: none; }
.pge-dash-nav-item.active {
	background: var(--pge-blue-50);
	color: var(--pge-color-primary);
	font-weight: 600;
	box-shadow: none;
	outline: none;
	border: none;
}
.pge-dash-nav-icon { width: 17px; height: 17px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; }
.pge-dash-nav-divider { height: 1px; background: var(--pge-gray-100); margin: 10px 0; }
.pge-dash-nav-item--quiet { font-size: 13px; font-weight: 500; color: var(--pge-ink-400); }

/* Flat cards. Explicitly overrides the neumorphic stat treatment (§11:
   "This replaces .pge-neu-stat. Drop the neumorphic treatment entirely"). */
body.pge-portal-competitive .pge-card,
body.pge-portal-competitive .pge-neu-stat,
body.pge-portal-competitive .pge-neu-card,
body.pge-portal-competitive .pge-empty-state,
body.pge-portal-testprep .pge-card,
body.pge-portal-testprep .pge-neu-stat,
body.pge-portal-testprep .pge-neu-card,
body.pge-portal-testprep .pge-empty-state {
	background: var(--pgp-surface);
	border: 1px solid var(--pgp-line);
	border-radius: 20px;
	box-shadow: var(--pge-shadow-sm);
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	transition: box-shadow 140ms ease, transform 140ms ease;
}
body.pge-portal-competitive .pge-card:hover,
body.pge-portal-testprep .pge-card:hover {
	transform: translateY(-1px);
	box-shadow: var(--pge-shadow-md);
}
body.pge-portal-competitive .pge-card-header,
body.pge-portal-testprep .pge-card-header {
	border-bottom: 1px solid var(--pge-gray-100);
}
body.pge-portal-competitive .pge-neu-stat-value,
body.pge-portal-testprep .pge-neu-stat-value {
	font-family: var(--pge-font-mono);
	font-size: 28px;
	font-weight: 700;
	letter-spacing: -0.02em;
	color: var(--pgp-ink);
	-webkit-text-fill-color: currentColor;
	background: none;
}
body.pge-portal-competitive .pge-neu-stat-label,
body.pge-portal-testprep .pge-neu-stat-label {
	font-size: 11.5px;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--pge-ink-400);
}
body.pge-portal-competitive .pge-neu-stat-icon,
body.pge-portal-testprep .pge-neu-stat-icon {
	width: 30px; height: 30px;
	border-radius: 10px;
	background: var(--pge-blue-50);
	color: var(--pge-color-primary);
	box-shadow: none;
	display: inline-flex; align-items: center; justify-content: center;
}
body.pge-portal-competitive .pge-neu-stat:hover .pge-neu-stat-icon,
body.pge-portal-testprep .pge-neu-stat:hover .pge-neu-stat-icon { transform: none; }

/* Score bands (§11) — replaces pge-badge-green / -warning / -red. */
.pge-band { display: inline-flex; align-items: center; font-family: var(--pge-font-mono); font-size: 12.5px; font-weight: 700; border-radius: var(--pge-radius-pill); padding: 5px 11px; }
.pge-band--high { color: #15803d; background: #f0fdf4; }
.pge-band--mid  { color: #b45309; background: #fffbeb; }
.pge-band--low  { color: #b91c1c; background: #fef2f2; }

/* "Retired" badge — the standard level-badge spec, not the old square chip. */
.pge-retired-badge {
	display: inline-flex;
	align-items: center;
	font-size: 10.5px;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	font-style: normal;
	color: var(--pge-ink-500);
	background: var(--pge-gray-100);
	border: 1px solid var(--pgp-line);
	border-radius: var(--pge-radius-pill);
	padding: 2px 8px;
}

/* ── Mobile nav bar ──────────────────────────────────────────────────
 * These rules used to live in StudentDashboard.jsx's inline <style> block.
 * When that block moved here, only its cosmetic half came with it — the
 * structural half (the `display` rules and the whole max-width:768px layer)
 * was left behind, which meant:
 *   - the mobile bar had no `display:none`, so it rendered on desktop;
 *   - its dropdown had no `display:none`, so it was permanently expanded;
 *   - the two <button>s had no base reset, so they drew the browser's
 *     default 2px outset border;
 *   - and on an actual phone the sidebar never hid, the columns never
 *     stacked, and the tables never shrank.
 * The structure is restored below; the styling is the A1 system, not the
 * hardcoded hexes the original used. */
.pge-dash-mobile-bar {
	display: none; /* shown by the max-width:768px block at the end of this file */
	background: var(--pgp-surface);
	border: 1px solid var(--pgp-line);
	border-radius: 16px;
	padding: 10px 16px;
	margin-bottom: 16px;
	box-shadow: var(--pge-shadow-sm);
}
/* Both controls are <button>s: reset the UA chrome or they render as
 * grey 2px-outset system buttons. */
.pge-dash-mobile-toggle,
.pge-dash-mobile-item {
	border: none;
	background: none;
	cursor: pointer;
	font-family: inherit;
	text-align: left;
	-webkit-appearance: none;
	appearance: none;
}
.pge-dash-mobile-toggle {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	padding: 0;
	font-size: 15px;
	font-weight: 600;
	color: var(--pgp-ink);
}
.pge-dash-mobile-toggle svg { transition: transform .2s var(--pgt-ease, ease); }
.pge-dash-mobile-toggle.open svg { transform: rotate(180deg); }
.pge-dash-mobile-dropdown {
	display: none;
	margin-top: 10px;
	padding-top: 10px;
	border-top: 1px solid var(--pge-color-line);
}
.pge-dash-mobile-dropdown.open { display: block; }
.pge-dash-mobile-item {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	min-height: 44px;
	padding: 10px 8px;
	border-radius: 12px;
	font-size: 14px;
	color: var(--pgp-body);
}
.pge-dash-mobile-item:hover { background: var(--pgp-surface-2); }
.pge-dash-mobile-item.active { background: var(--pge-blue-50); color: var(--pge-color-primary); font-weight: 600; }

/* ── Portal responsive layer (was the inline block's max-width:768px) ── */
@media (max-width: 768px) {
	.pge-dash {
		flex-direction: column;
		gap: 0;
		margin: 16px auto !important;
		padding: 0 12px !important;
		max-width: 100% !important;
	}
	.pge-dash-sidebar { display: none; }
	.pge-dash-mobile-bar { display: block; }
	.pge-dash-content { min-width: 0; width: 100%; overflow-x: hidden; }
	.pge-dash-content .pge-card { overflow: hidden; word-break: break-word; border-radius: 8px; }
	.pge-dash-content table { font-size: 13px !important; }
	/* Two-column grids collapse to one. */
	.pge-perf-charts,
	.pge-profile-row { grid-template-columns: 1fr !important; }
	/* Results toolbar: search and filter stack instead of squeezing. */
	.pge-results-toolbar { flex-direction: column; }
	.pge-results-toolbar > div:first-child { max-width: 100% !important; flex: 1 1 100% !important; }
	.pge-results-toolbar .pge-select { width: 100% !important; }
}

@media (prefers-reduced-motion: reduce) {
	.pge-dash-nav-item,
	body.pge-portal-competitive .pge-card,
	body.pge-portal-testprep .pge-card { transition: none; }
}

/* Dark theme (Acorn Next) — same attribute as the rest of the app, and the
 * same portal scope as the token block at the top of this file: the body
 * classes are site-wide, so an unscoped rule here darkens the marketing
 * pages too, which have no dark design.
 *
 * The colour is set on the app container as well as the body. The canvas
 * rule near the top skips `.pg-app` bodies (they paint their own module
 * ground), which left the portal inheriting the UA default black — invisible
 * once the surfaces went dark. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-competitive,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-testprep { background: #0f131c; color: #eef2f9; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app .pge-card,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app .pge-dash,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app .pge-dash-content { color: var(--pgp-ink, #eef2f9); }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-testprep .pge-dash-sidebar,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-competitive .pge-dash-sidebar,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-testprep .pge-card,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-competitive .pge-card,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-testprep .pge-neu-stat,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-competitive .pge-neu-stat,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-testprep .pge-empty-state,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-competitive .pge-empty-state {
	background: #1c2230;
	border-color: #2a3345;
}
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-sidebar-header h2,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-nav-item,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-testprep .pge-neu-stat-value,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-competitive .pge-neu-stat-value { color: #eef2f9; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-sidebar-header p,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-nav-item--quiet,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-testprep .pge-neu-stat-label,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-competitive .pge-neu-stat-label { color: #93a0b5; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-nav-item:hover { background: #232c3d; color: #fff; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-nav-item.active { background: #232c3d; color: #6ba4ff; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-nav-divider,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-sidebar-header,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-testprep .pge-card-header { border-color: #2a3345; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-mobile-bar,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-mobile-dropdown { background: #1c2230; border-color: #2a3345; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-mobile-item { color: #eef2f9; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-mobile-item:hover,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-dash-mobile-item.active { background: #232c3d; }

/* Score bands (README §11) — the badge classes every portal surface already
   uses are restyled in place, so RecentActivityList, ResultsHistoryTable and
   the rest pick up the new bands without touching their markup. */
body.pge-portal-competitive .pge-badge,
body.pge-portal-testprep .pge-badge {
	display: inline-flex;
	align-items: center;
	font-family: var(--pge-font-mono);
	font-size: 12.5px;
	font-weight: 700;
	border-radius: var(--pge-radius-pill);
	padding: 5px 11px;
	border: 0;
}
body.pge-portal-competitive .pge-badge-green,
body.pge-portal-testprep .pge-badge-green   { color: #15803d; background: #f0fdf4; }
body.pge-portal-competitive .pge-badge-warning,
body.pge-portal-competitive .pge-badge-yellow,
body.pge-portal-testprep .pge-badge-warning,
body.pge-portal-testprep .pge-badge-yellow  { color: #b45309; background: #fffbeb; }
body.pge-portal-competitive .pge-badge-red,
body.pge-portal-testprep .pge-badge-red     { color: #b91c1c; background: #fef2f2; }


/* ══════════════════════════════════════════════════════════════════════
   DARK THEME OVERRIDES
   These live at the END of the file on purpose. Several of the light rules
   above are `body.pge-portal-x.pge-portal-x .thing.state { … !important }`,
   which is specificity (0,4,1) WITH !important — identical weight to a
   `html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app .thing.state` rule. When
   two !important declarations tie on specificity, source order decides, so
   a dark rule placed above the light one silently loses. Keeping the whole
   dark layer last removes that trap for anything added later.
   ══════════════════════════════════════════════════════════════════════ */

/* The two values the bundle hardcodes inline rather than reading from a
   token — an inline style can only be reached by an attribute hook, the same
   pattern this file already uses for the proficiency bar. Both belong to the
   amber "do this next" treatment: a light peach plate with dark orange text,
   which inverts to a dark amber plate with light amber text. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app [style*="253, 238, 229"] {
	background: #2b2118 !important;
	border-color: #4a3a24 !important;
}
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app [style*="154, 52, 18"] { color: #fbbf24 !important; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app [style*="29, 78, 216"] { color: #6ba4ff !important; }

/* The engine's status tints are also inline literals, and unlike its
   --pge-adm-* tokens (which it does flip for dark) they stay light — leaving
   pale chips scattered over the dark cards, and in one case dark-mode muted
   text on a light-mode blue plate. Mapped here to the same hue at dark
   luminance so the status still reads at a glance. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app [style*="254, 242, 242"] { background: #2b1a1a !important; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app [style*="255, 251, 235"] { background: #2b2418 !important; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app [style*="240, 253, 244"] { background: #16281d !important; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app [style*="239, 246, 255"] { background: #18202e !important; }
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app [style*="226, 232, 240"] { background: #232c3d !important; }

/* Headings. The engine forces every h1–h4 to its ink with !important
   (`body.pge-portal-*:not(:has(.pge-gje-v5)) h1..h4`), which in dark mode
   paints them near-black on the dark cards — "Profile Information" and
   "In progress" were invisible. Same fight as the marketing page's on-dark
   headings in theme.css, so it needs !important to win. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app :is(h1, h2, h3, h4, h5, h6) {
	color: var(--pgp-ink) !important;
}

/* The active sidebar item is a soft-blue plate with brand-blue text; on a
   dark rail that plate has to darken and the text lighten together, or one
   of the two goes unreadable. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app .pge-dash-nav-item.active {
	background: #1b2740 !important;
	color: #6ba4ff !important;
}

/* Accent as TEXT. Links, tab labels and inline `color: var(--pge-color-primary)`
   all resolve through this token, and #1b3beb only reaches 2.2:1 on the dark
   cards. Scoped to .pge-pro-app rather than the body on purpose: the header's
   "Free check" button is a primary FILL and sits outside the app, so a
   body-level flip would wash it out. Fills inside the app use
   --pgp-accent-fill, which stays brand blue. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app {
	--pge-color-primary: #6ba4ff;
}

/* Blue-800 body copy the bundle sets inline, on the darkened blue plate. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app [style*="30, 64, 175"] { color: #93c5fd !important; }

/* --pge-ui-primary does double duty in the bundle: `background: var(--pge-ui-primary)`
   on filled buttons (white text, fine at #1b3beb) and `color: var(--pge-ui-primary)`
   on text buttons like "All results →" (2.2:1 on a dark card). The inline
   style itself is what separates the two, so match on it — this reaches only
   the text usages and leaves every fill at brand blue. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app [style*="color: var(--pge-ui-primary"] {
	color: #6ba4ff !important;
}

/* Mobile nav, same pairing as the sidebar item above. Hidden at this width,
   but it is the whole navigation on a phone. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] .pge-pro-app .pge-dash-mobile-item.active {
	background: #1b2740 !important;
	color: #6ba4ff !important;
}

/* Surfaces the engine paints that this file does not otherwise own. */
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-testprep .pge-po-card,
html[data-pge-admin-theme="dark"][data-pge-dark-scope] body.pge-portal-competitive .pge-po-card {
	background: var(--pgp-surface) !important;
	border-color: var(--pgp-line) !important;
	color: var(--pgp-ink) !important;
}
