/* ==========================================================================
   Food Science Daily — design system

   Functional first: this is a study tool, so density, scannability and
   legibility under time pressure beat decoration. Type does the work;
   borders are hairlines, depth is faint, colour is used to mean something
   rather than to fill space.

   Everything is driven by tokens below, so light and dark stay in step.
   ========================================================================== */

:root {
	/*
	 * Redesign, 2026-3. Maroon and white — the beige read as its own
	 * competing colour, so the neutrals go back to a clean near-white
	 * scale and maroon is the only thing left to notice.
	 *
	 * --- neutrals: white, with a faint warm-grey ramp for depth. */
	--n-0:  #ffffff;
	--n-25: #fcfcfb;
	--n-50: #f7f6f4;
	--n-100:#ececea;
	--n-200:#dad8d3;
	--n-300:#bcb9b0;
	--n-400:#948f81;
	--n-500:#6e6857;
	--n-600:#4c463a;
	--n-700:#332f27;
	--n-800:#221f19;
	--n-900:#16140f;

	/* --- accent: maroon. The one interactive colour on the site — links,
	       primary actions, focus rings — nothing else competes with it. */
	--a-50: #f1e2df;
	--a-100:#e3c2bd;
	--a-300:#a5535a;
	--a-500:#7a1f2b;
	--a-600:#5c1520;
	--a-700:#3f0e16;

	/* --- stamp accent: a muted gold, used only for "marked for review". */
	--amber: #b98a3e;
	--amber-hi: #97702f;

	/* --- flash: a hot orange-to-red gradient reserved for promotional
	       banners (the ticker, bundle upsells, the free-tests prompt bar) —
	       everywhere else on the site stays on the quieter maroon/gold
	       system above. Both stops are individually checked at ≥4.5:1
	       against white (#b8300f ≈ 6.1:1, #cc4212 ≈ 4.8:1), so white text
	       stays readable across the whole gradient, not just at one end. */
	--flash-1: #b8300f;
	--flash-2: #cc4212;
	/* Text on a --flash surface. Fixed white, and NOT remapped in the dark
	   blocks, because the gradient underneath it is not remapped either -
	   it is the same deep orange-red in both themes. These surfaces used
	   --on-accent, which does invert, so the ticker and the bundle promo
	   rendered near-black text on dark orange in dark mode at about
	   1.6:1. A token only inverts correctly if what it sits on inverts
	   with it. */
	--on-flash: #ffffff;
	--flash-hi: #8f230a;

	/* --- state colours. Correct is an earthy green, kept well clear of the
	       maroon accent so "right" and "click this" never blur together. */
	--ok-50: #e6ede2;
	--ok-500:#3f6b3a;
	--ok-700:#2d4d29;

	--bad-50: #f4e0dc;
	--bad-500:#a83a2a;
	--bad-700:#7c2a1e;

	--warn-50: #f1e5d1;
	--warn-500:#8a5a12;

	/* --- semantic, remapped wholesale in dark mode */
	--bg:        var(--n-0);
	--bg-sunken: var(--n-100);
	--bg-raised: var(--n-0);
	--ink:       var(--n-900);
	--ink-soft:  var(--n-600);
	--ink-faint: var(--n-500);
	--line:      var(--n-200);
	--line-soft: var(--n-100);
	--accent:    var(--a-500);
	--accent-hi: var(--a-600);
	--accent-bg: var(--a-50);
	--ok:        var(--ok-500);
	--ok-bg:     var(--ok-50);
	--bad:       var(--bad-500);
	--bad-bg:    var(--bad-50);
	--warn:      var(--warn-500);
	--warn-bg:   var(--warn-50);

	/* Text that sits on a filled surface — accent, ink, or a status colour
	   (--ok / --bad / --warn), all of which invert between themes. Declared
	   once, so a button can never end up the same colour as its own
	   background again.

	   Both MUST be re-declared in every dark block, and re-declared to the
	   OPPOSITE end of the ramp. --ink flips from near-black to cream in dark
	   mode, so --on-ink has to flip from cream to near-black with it. It did
	   not: all three dark blocks set --on-ink to #f3f1ec, the same value as
	   --ink, which is cream text on a cream fill at 1:1 — invisible. It hit
	   the sidebar, the selected exam filter, the header CTA, the waitlist
	   button and the exam terminal's board strip at once, which is exactly
	   what a shared token does when it is wrong. */
	--on-accent: #ffffff;
	--on-ink:    var(--n-50);

	--tint:      linear-gradient(180deg, var(--a-50) 0%, transparent 72%);
	--tint-flat: color-mix(in srgb, var(--a-500) 4%, var(--bg));

	/* --- type scale, 1.25 ratio, clamped for fluid headings */
	--t-xs:  0.75rem;
	--t-sm:  0.8125rem;
	--t-base:0.9375rem;
	--t-md:  1.0625rem;
	--t-lg:  1.3125rem;
	--t-xl:  1.625rem;
	--t-2xl: clamp(1.6rem, 1.1rem + 2vw, 2.25rem);
	--t-3xl: clamp(2.1rem, 1.3rem + 3.4vw, 3.6rem);

	/* --- spacing, 4px base */
	--s-1: .25rem;  --s-2: .5rem;   --s-3: .75rem;  --s-4: 1rem;
	--s-5: 1.5rem;  --s-6: 2rem;    --s-8: 3rem;    --s-10: 4.5rem;

	/* Sharper than the old rounded-SaaS scale — a form has corners, not a
	   bubble. Pills survive only for tags, where a stamp/label shape reads
	   as a label rather than a decorative rounding. */
	--r-sm: 3px;
	--r:    6px;
	--r-lg: 10px;
	--r-full: 999px;

	/* Neutral shadows — a tinted shadow reads as a second colour. */
	--shadow-1: 0 1px 2px rgba(22,20,15,.06);
	--shadow-2: 0 1px 3px rgba(22,20,15,.07), 0 8px 20px -8px rgba(22,20,15,.14);
	--shadow-3: 0 2px 6px rgba(22,20,15,.08), 0 18px 44px -12px rgba(22,20,15,.22);

	/* --- three type roles, one job each.
	   UI chrome: nav, buttons, form inputs, table data — stays neutral. */
	--font: "Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
	        "Helvetica Neue", Arial, sans-serif;
	/* Display: headings, eyebrows, labels — condensed and stamped, the
	   register of a regulatory panel title. */
	--font-display: "Barlow Condensed", "Arial Narrow", var(--font);
	/* Reading: question text, explanations, definitions, ledes — the long
	   passages a student actually studies from, set for legibility. */
	--font-read: "Source Serif 4", "Georgia", serif;
	/* Every number on the site — timer, scores, marks, dates — in one
	   tabular face, so a column of digits actually lines up. */
	--mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

	--wrap: 1140px;
}

/* ========================================================== dark theme
   Only the SEMANTIC layer is remapped — the ramps above are untouched, so
   every component keeps working without a single dark-mode override of its
   own. That was the point of the two-layer tokens.

   The 50-level tints (--ok-50 and friends) are far too light to sit on a
   dark ground, so the tinted backgrounds get their own values rather than
   being reused. Text tokens are checked against their surface: --ink on
   --bg is 15.8:1, --ink-soft 7.4:1, --ink-faint 5.1:1 — all clear of
   WCAG AA, because a study site is read for hours at a time.

   Applied three ways, deliberately in this order:
     :root[data-theme="dark"]   an explicit choice, wins over everything
     prefers-color-scheme       the system default, when no choice is stored
     :root[data-theme="light"]  an explicit light choice must beat the
                                system preference, hence the :not() guard
   ========================================================================= */
:root[data-theme="dark"],
:root:not([data-theme="light"]) {
	color-scheme: light;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) {
		color-scheme: dark;
		--bg:        #14120f;
		--bg-sunken: #1d1a16;
		--bg-raised: #1b1815;
		--ink:       #f3f1ec;
		--ink-soft:  #bdb7a9;
		--ink-faint: #928c7e;
		--line:      #34302a;
		--line-soft: #262320;
		--accent:    #d98a8f;
		--accent-hi: #e8a5a9;
		--accent-bg: #2b1a1c;
		--ok:        #7fb173;
		--ok-bg:     #1b2419;
		--bad:       #e08a76;
		--bad-bg:    #2a1a15;
		--warn:      #d2a44f;
		--warn-bg:   #291f10;
		--amber:     #d2a44f;
		--on-accent: #1a0f11;
		--on-ink:    #14120f;
		--tint:      linear-gradient(180deg, #241618 0%, transparent 72%);
		--tint-flat: #191512;
		--shadow-1: 0 1px 2px rgba(0,0,0,.4);
		--shadow-2: 0 1px 3px rgba(0,0,0,.45), 0 8px 20px -8px rgba(0,0,0,.6);
		--shadow-3: 0 2px 6px rgba(0,0,0,.5), 0 18px 44px -12px rgba(0,0,0,.7);
	}
}

:root[data-theme="dark"] {
	color-scheme: dark;
	--bg:        #14120f;
	--bg-sunken: #1d1a16;
	--bg-raised: #1b1815;
	--ink:       #f3f1ec;
	--ink-soft:  #bdb7a9;
	--ink-faint: #928c7e;
	--line:      #34302a;
	--line-soft: #262320;
	--accent:    #d98a8f;
	--accent-hi: #e8a5a9;
	--accent-bg: #2b1a1c;
	--ok:        #7fb173;
	--ok-bg:     #1b2419;
	--bad:       #e08a76;
	--bad-bg:    #2a1a15;
	--warn:      #d2a44f;
	--warn-bg:   #291f10;
	--amber:     #d2a44f;
	--on-accent: #1a0f11;
	--on-ink:    #14120f;
	--tint:      linear-gradient(180deg, #241618 0%, transparent 72%);
	--tint-flat: #191512;
	--shadow-1: 0 1px 2px rgba(0,0,0,.4);
	--shadow-2: 0 1px 3px rgba(0,0,0,.45), 0 8px 20px -8px rgba(0,0,0,.6);
	--shadow-3: 0 2px 6px rgba(0,0,0,.5), 0 18px 44px -12px rgba(0,0,0,.7);
}

/* The exam terminal and calculator paint their own literal colours, so they
   are the two places that need explicit dark handling rather than inheriting
   it from the tokens. */
:root[data-theme="dark"] .fsd-cbt,
:root[data-theme="dark"] .fsd-cbt__left { background: var(--bg); }
:root[data-theme="dark"] .fsd-cbt__right { background: var(--bg-raised); border-left-color: var(--line); }
:root[data-theme="dark"] .fsd-cbt__strip { background: var(--bg-sunken); border-bottom-color: var(--line); }
:root[data-theme="dark"] .fsd-cbt__band { background: var(--bg-raised); }
:root[data-theme="dark"] .fsd-cbt__exam { background: #3a2f1c; color: #f0dfb8; }
:root[data-theme="dark"] .fsd-cbt__foot { background: var(--bg-sunken); border-top-color: var(--line); }
:root[data-theme="dark"] .fsd-pal.is-not-visited { background: var(--bg-raised); border-color: var(--ink-faint); color: var(--ink-soft); }
:root[data-theme="dark"] .fsd-calc { background: var(--bg-raised); border-color: var(--line); }
:root[data-theme="dark"] .fsd-calc__screen { background: var(--bg-sunken); border-bottom-color: var(--line); }
:root[data-theme="dark"] .fsd-calc__out { color: var(--ink); }
:root[data-theme="dark"] .fsd-calc__k { background: var(--bg); color: var(--ink); border-color: var(--line); }
:root[data-theme="dark"] .fsd-calc__k:hover { background: var(--bg-sunken); }
:root[data-theme="dark"] .fsd-calc__k.is-num { background: var(--bg-raised); }

/* Theme toggle in the header. */
.fsd-theme {
	flex: none; width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
	border: 1px solid var(--line); border-radius: var(--r-sm); background: transparent;
	color: var(--ink-soft); cursor: pointer;
}
.fsd-theme:hover { background: var(--bg-sunken); color: var(--ink); }
.fsd-theme__sun { display: none; }
:root[data-theme="dark"] .fsd-theme__sun { display: block; }
:root[data-theme="dark"] .fsd-theme__moon { display: none; }
@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .fsd-theme__sun { display: block; }
	:root:not([data-theme="light"]) .fsd-theme__moon { display: none; }
}


/*
 * This previously read "the site stays on its light paper look regardless
 * of the visitor's OS/browser theme preference". That decision is reversed
 * above: the semantic tokens are now remapped for dark, by explicit choice
 * or by system preference.
 *
 * The reasoning changed with the audience. That note was written about the
 * landing page, where the brand moment does want to stay light — but this
 * is a site people read for hours at a time, often late, and forcing a
 * bright page on someone whose whole machine is dark is a worse experience
 * than the brand inconsistency it was avoiding. The landing hero still
 * paints its own light ground, so the brand moment is unchanged.
 */

/* ---------------------------------------------------------- skip link
   Hidden until focused. The header holds two megamenus, a search box and
   the account controls — dozens of keyboard stops before the content, on
   every page. WCAG 2.4.1.
   ===================================================================== */
.fsd-skip {
	position: absolute; left: 8px; top: -60px; z-index: 200;
	padding: 10px 16px; border-radius: var(--r-sm);
	background: var(--accent); color: var(--on-accent);
	font-weight: 700; text-decoration: none;
	transition: top .12s ease;
}
.fsd-skip:focus { top: 8px; }
/* The target takes focus programmatically; it should not draw a ring. */
main:focus { outline: none; }

/* ------------------------------------------------------------------ reset */

*, *::before, *::after { box-sizing: border-box; }

body.fsd-scope {
	margin: 0;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	font-family: var(--font);
	font-size: var(--t-md);
	line-height: 1.65;
	color: var(--ink);
	background: var(--bg);
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
	font-variant-numeric: tabular-nums;
}
body.fsd-scope > main { flex: 1 0 auto; }

/*
 * :where() keeps this at zero specificity. Written as `.fsd-scope h2` it
 * scored (0,1,1) and beat `.fsd-h2`'s own (0,1,0) margin rule regardless of
 * source order — every heading and paragraph on the site was silently stuck
 * at margin:0, no matter what .fsd-h1/.fsd-h2/.fsd-lede etc. tried to set.
 * Same failure mode as the `a` rule below, just never diagnosed until now.
 */
.fsd-scope :where(h1, h2, h3, h4, p) { margin: 0; }
/*
 * NOTE: the same flaw is latent here - `.fsd-scope` outside :where()
 * still scores (0,1,0), so this ties `.fsd-h2` rather than losing to
 * it and only behaves because every heading rule happens to be
 * declared later in this file. A heading rule added ABOVE this line
 * would silently lose. Not changed here: rewriting it would move
 * margins site-wide for no symptom anyone is reporting.
 */
/*
 * The WHOLE selector goes inside :where(), not just the `a`.
 *
 * This was written as `.fsd-scope :where(a)` to fix exactly the bug it then
 * went on to cause. :where() zeroes what is inside it, but `.fsd-scope` sits
 * OUTSIDE and still scores (0,1,0) — so the rule tied every single-class
 * component rule instead of losing to them, and beat any declared earlier in
 * this file. The skip link, at line 285, rendered accent text on an accent
 * background: invisible, the same failure the comment above claimed to have
 * solved for buttons.
 *
 * Wrapping the whole thing makes it genuinely (0,0,0): a real default that
 * any component rule overrides, wherever it happens to sit in the file.
 */
:where(.fsd-scope a) { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
:where(.fsd-scope a:hover) { color: var(--accent-hi); }

.fsd-scope :focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
	border-radius: var(--r-sm);
}

.fsd-sr {
	position: absolute; width: 1px; height: 1px;
	overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

.fsd-wrap { max-width: var(--wrap); margin-inline: auto; padding: var(--s-8) var(--s-5) var(--s-10); }
.fsd-wrap--narrow { max-width: 460px; }

/* ------------------------------------------------------------- typography */

.fsd-h1 {
	font-size: var(--t-2xl);
	font-weight: 680;
	line-height: 1.15;
	letter-spacing: -.021em;
	margin-bottom: var(--s-3);
}
.fsd-h2 {
	font-size: var(--t-lg);
	font-weight: 660;
	line-height: 1.25;
	letter-spacing: -.014em;
	margin: var(--s-8) 0 var(--s-5);
}
/* One step below .fsd-h2, for subheadings inside a panel or card. The class
   was in use with no rule behind it, so it rendered at the browser default. */
.fsd-h3 {
	font-size: var(--t-md);
	font-weight: 660;
	line-height: 1.3;
	letter-spacing: -.01em;
	margin: var(--s-5) 0 var(--s-3);
}
.fsd-lede { font-size: var(--t-md); color: var(--ink-soft); max-width: 62ch; }
.fsd-sub  { font-size: var(--t-base); color: var(--ink-faint); margin: calc(var(--s-3) * -1) 0 var(--s-4); }
.fsd-eyebrow {
	font-size: var(--t-xs);
	font-weight: 620;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--ink-faint);
}
.fsd-crumbs { margin-bottom: var(--s-3); }
.fsd-crumbs ol {
	display: flex; flex-wrap: wrap; align-items: center;
	list-style: none; margin: 0; padding: 0;
	font-size: var(--t-xs); color: var(--ink-faint);
}
.fsd-crumbs li { display: flex; align-items: center; }
.fsd-crumbs li:not(:last-child)::after {
	content: "/"; margin: 0 var(--s-2); color: var(--line-soft);
}
.fsd-crumbs a { color: var(--ink-faint); text-decoration: none; padding: 5px 0; min-height: 24px; }
.fsd-crumbs a:hover { color: var(--ink); text-decoration: underline; }
.fsd-crumbs span[aria-current] { color: var(--ink-soft); font-weight: 560; }

.fsd-list { color: var(--ink-soft); max-width: 62ch; margin: 0; padding-left: 1.15rem; }
.fsd-list li { margin-bottom: var(--s-2); }
.fsd-pre {
	font-family: var(--mono); font-size: var(--t-sm); line-height: 1.55;
	background: var(--bg-sunken); border: 1px solid var(--line);
	border-radius: var(--r); padding: var(--s-4); overflow-x: auto;
}

/* -------------------------------------------------------------------- nav */

/* Sticky lives on the wrapper, not .fsd-nav itself, so the ticker banner
   right below it scrolls to the top and stops as part of the same fixed
   unit — see layout.php for why a shared ancestor beats a second,
   independently-calculated `top` offset on the ticker alone. */
.fsd-topbar { position: sticky; top: 0; z-index: 50; }

.fsd-nav {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-4); flex-wrap: wrap;
	padding: var(--s-3) var(--s-5);
	background: color-mix(in srgb, var(--bg) 86%, transparent);
	backdrop-filter: saturate(1.6) blur(12px);
	border-bottom: 1px solid var(--line);
}
@supports not (backdrop-filter: blur(1px)) { .fsd-nav { background: var(--bg); } }

/* Sidebar show/hide, header-mounted — only present on the dashboard, to
   the left of the brand. Plain-header styling (dark icon on light bg),
   unlike the dark sidebar it used to live inside. */
.fsd-appnav__collapse {
	flex: none; width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
	border: 1px solid var(--line); border-radius: var(--r-sm); background: transparent;
	color: var(--ink-soft); cursor: pointer; transition: background .14s ease, color .14s ease;
}
.fsd-appnav__collapse:hover { background: var(--bg-sunken); color: var(--ink); }

.fsd-nav__brand {
	display: flex; align-items: center; gap: 10px;
	font-size: var(--t-base); font-weight: 680; letter-spacing: -.012em;
	line-height: 1.2; color: var(--ink); text-decoration: none;
}
.fsd-nav__brand img { flex: none; border-radius: 7px; }
.fsd-nav__brand-text span {
	display: block; margin-top: 1px;
	font-size: var(--t-xs); font-weight: 560; letter-spacing: .05em;
	text-transform: uppercase; color: var(--ink-faint);
}
.fsd-nav__links { display: flex; align-items: center; gap: var(--s-5); }
/*
 * Direct children only. As `.fsd-nav__links a` this reached every link inside
 * the dropdown panels too, and at one class deeper than .fsd-btn it won —
 * which is why the panel's call-to-action rendered as a 26px sliver with
 * 4px of padding instead of a button.
 */
.fsd-nav__links > a {
	font-size: var(--t-base); font-weight: 560; color: var(--ink-soft);
	text-decoration: none; padding: var(--s-1) 0;
	border-bottom: 2px solid transparent;
}
.fsd-nav__links > a:hover { color: var(--ink); border-bottom-color: var(--line); }

.fsd-nav__search {
	display: flex; align-items: center; gap: 6px;
	padding: 6px 10px; border-radius: var(--r-full);
	background: var(--bg-sunken); border: 1px solid var(--line);
	transition: border-color .14s ease;
}
.fsd-nav__search:focus-within { border-color: var(--accent); }
.fsd-nav__search img { flex: none; opacity: .55; }
.fsd-nav__search input {
	width: 132px; border: 0; background: none; font: inherit;
	font-size: var(--t-sm); color: var(--ink);
}
.fsd-nav__search input:focus { outline: none; }
.fsd-nav__search input::placeholder { color: var(--ink-faint); }

.fsd-nav__cta {
	color: var(--on-ink) !important; background: var(--ink);
	padding: var(--s-2) var(--s-4) !important; border-radius: var(--r-sm);
	border-bottom: 0 !important;
}
.fsd-nav__cta:hover { background: var(--n-700); }
.fsd-nav__logout { display: inline; margin: 0; }
.fsd-nav__logout button {
	font: inherit; font-size: var(--t-base); font-weight: 560;
	color: var(--ink-faint); background: none; border: 0; padding: 0; cursor: pointer;
}
.fsd-nav__logout button:hover { color: var(--ink); }

.fsd-foot {
	border-top: 1px solid var(--line);
	padding: var(--s-8) var(--s-5) var(--s-6);
	font-size: var(--t-sm); color: var(--ink-soft);
	background: var(--bg-sunken);
}
.fsd-foot__wrap { max-width: var(--wrap); margin-inline: auto; }
.fsd-foot__grid {
	display: grid; grid-template-columns: 1.3fr repeat(4, 1fr);
	gap: var(--s-6); padding-bottom: var(--s-6);
	border-bottom: 1px solid var(--line);
}
.fsd-foot__brand {
	display: flex; align-items: center; gap: 10px;
	font-size: var(--t-base); font-weight: 680; color: var(--ink);
	text-decoration: none; margin-bottom: var(--s-2);
}
.fsd-foot__brand img { flex: none; border-radius: 7px; }
.fsd-foot__tag { max-width: 32ch; color: var(--ink-faint); }
.fsd-foot__col h3 {
	font-size: var(--t-xs); font-weight: 620; letter-spacing: .06em;
	text-transform: uppercase; color: var(--ink-faint); margin-bottom: var(--s-3);
}
.fsd-foot__col ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s-2); }
.fsd-foot__col a { color: var(--ink-soft); text-decoration: none; display: inline-block; padding: 2px 0; min-height: 24px; }
.fsd-foot__col a:hover { color: var(--ink); text-decoration: underline; }
.fsd-foot__bottom {
	display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
	gap: var(--s-4); padding-top: var(--s-5);
}
.fsd-foot__legal { display: flex; flex-wrap: wrap; gap: var(--s-4); }
.fsd-foot__legal a { color: var(--ink-soft); text-decoration: none; padding: 2px 0; min-height: 24px; display: inline-block; }
.fsd-foot__legal a:hover { color: var(--ink); text-decoration: underline; }
@media (max-width: 860px) {
	.fsd-foot__grid { grid-template-columns: 1fr 1fr; }
	.fsd-foot__brand { margin-top: 0; }
}
@media (max-width: 520px) {
	.fsd-foot__grid { grid-template-columns: 1fr; gap: var(--s-5); }
}

/* ---------------------------------------------------------------- buttons */

.fsd-btn {
	display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
	font: inherit; font-size: var(--t-base); font-weight: 600; line-height: 1;
	/* .85rem, not the old .68rem: at --t-base (15px) + 1px borders, .68rem
	   padding came out to ~39px tall — under the 44px touch-target minimum
	   every primary CTA on the site should clear. .85rem lands at ~44px. */
	padding: .85rem 1.15rem;
	border: 1px solid transparent; border-radius: var(--r-sm);
	cursor: pointer; text-decoration: none; white-space: nowrap;
	transition: background .14s ease, border-color .14s ease, color .14s ease, transform .06s ease;
}
.fsd-btn:active { transform: translateY(.5px); }
.fsd-btn--primary { background: var(--accent); color: var(--on-accent); }
.fsd-btn--primary:hover { background: var(--accent-hi); color: var(--on-accent); }
.fsd-btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.fsd-btn--ghost:hover { border-color: var(--ink-faint); color: var(--ink); }
.fsd-btn--danger { background: var(--bad); color: var(--on-accent); }
.fsd-btn--danger:hover { background: var(--bad-700); color: var(--on-accent); }
.fsd-btn--lg { padding: .85rem 1.5rem; font-size: var(--t-md); }
.fsd-btn--sm { padding: .4rem .75rem; font-size: var(--t-sm); }
.fsd-btn--block { width: 100%; }
.fsd-btn:disabled { opacity: .5; cursor: not-allowed; }

/* Foreground now comes from --on-accent, which dark mode already remaps. */

/* Neutral outline rather than a brand colour — this is the one button on
   the site whose colours are fixed by someone else's brand guidelines, not
   this design system, so it deliberately doesn't try to blend in as a
   themed variant the way --primary/--ghost/--danger do. */
.fsd-btn--google {
	display: inline-flex; align-items: center; justify-content: center; gap: .6rem;
	background: var(--bg-raised); color: var(--ink); border: 1px solid var(--line);
}
.fsd-btn--google:hover { background: var(--bg-sunken); border-color: var(--ink-faint); }
.fsd-btn--google svg { flex: none; }

.fsd-divider { display: flex; align-items: center; gap: var(--s-3); margin: var(--s-5) 0; color: var(--ink-faint); font-size: var(--t-sm); }
.fsd-divider::before, .fsd-divider::after { content: ''; flex: 1 1 auto; height: 1px; background: var(--line); }

/* ---------------------------------------------------------------- notices */

.fsd-notice {
	background: var(--warn-bg); border: 1px solid color-mix(in srgb, var(--warn) 30%, transparent);
	border-radius: var(--r); padding: var(--s-4) var(--s-5); margin: var(--s-4) 0;
	color: var(--warn); font-size: var(--t-base);
}
.fsd-notice p { margin: 0; }
.fsd-notice--error { background: var(--bad-bg); border-color: color-mix(in srgb, var(--bad) 30%, transparent); color: var(--bad); }
/* The success counterpart. Errors had a style; confirmations had none, so a
   saved setting and a silently failed one looked the same. */
.fsd-notice--ok { background: var(--ok-bg); border-color: color-mix(in srgb, var(--ok) 30%, transparent); color: var(--ok); }

.fsd-empty {
	text-align: center; color: var(--ink-faint);
	padding: var(--s-8) var(--s-4);
	background: var(--bg-sunken); border-radius: var(--r-lg);
}

/* ------------------------------------------------------------------- hero */

.fsd-hero {
	background: var(--bg-sunken);
	border-bottom: 1px solid var(--line);
	padding: var(--s-10) 0 var(--s-8);
}
.fsd-hero .fsd-wrap { padding-block: 0; }
.fsd-hero__h1 {
	font-size: var(--t-3xl); font-weight: 700; line-height: 1.06;
	letter-spacing: -.03em; margin: var(--s-3) 0 var(--s-4);
}
.fsd-hero__cta { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-6); }
.fsd-hero__stats {
	display: flex; flex-wrap: wrap; gap: var(--s-8);
	margin-top: var(--s-8); padding-top: var(--s-5);
	border-top: 1px solid var(--line);
}
.fsd-hero__stats strong {
	display: block; font-size: var(--t-xl); font-weight: 680; letter-spacing: -.02em;
}
.fsd-hero__stats span { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .07em; color: var(--ink-faint); }

/* ------------------------------------------------------------------ cards */

.fsd-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); gap: var(--s-4); }

.fsd-card {
	display: flex; flex-direction: column;
	background: var(--bg-raised); border: 1px solid var(--line);
	border-radius: var(--r-lg); padding: var(--s-5);
	transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.fsd-card:hover { border-color: var(--n-300); box-shadow: var(--shadow-2); transform: translateY(-1px); }
@media (prefers-color-scheme: dark) { .fsd-card:hover { border-color: var(--n-600); } }

.fsd-card__badge {
	align-self: flex-start; margin-bottom: var(--s-3);
	font-size: var(--t-xs); font-weight: 650; letter-spacing: .05em; text-transform: uppercase;
	background: var(--accent); color: var(--on-accent); padding: .2rem .55rem; border-radius: var(--r-full);
}
.fsd-card__badge--free { background: var(--ok); }

/* A card can carry a year badge AND a "New Pattern" flag together — group
   them in a row instead of letting the flex-column card stack them. */
.fsd-card__badges { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-bottom: var(--s-3); }
.fsd-card__badges .fsd-card__badge { margin-bottom: 0; }
.fsd-card__badge--newpattern { background: var(--warn); color: var(--on-accent); }


.fsd-card--free { border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.fsd-card--bundle { border-color: color-mix(in srgb, var(--accent) 45%, transparent); background: color-mix(in srgb, var(--accent) 5%, var(--bg-raised)); }
.fsd-card__exam--bundle { color: var(--accent); }
.fsd-card__exam { font-size: var(--t-xs); font-weight: 620; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: var(--s-1); }
/* Product-type kicker on an exam's own landing page — a topic test, a
   previous-year paper, and a free sample should never look interchangeable. */
.fsd-card__exam--paper { color: var(--ink-soft); }
.fsd-card__exam--topic { color: var(--accent); }
.fsd-card__exam--free  { color: var(--ok); }
.fsd-card__title { font-size: var(--t-lg); font-weight: 660; line-height: 1.25; letter-spacing: -.014em; margin-bottom: var(--s-2); }
.fsd-card__blurb { font-size: var(--t-base); color: var(--ink-soft); margin-bottom: var(--s-4); }
.fsd-card__foot { margin-top: auto; padding-top: var(--s-4); display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); }

.fsd-facts {
	display: flex; flex-wrap: wrap; gap: var(--s-5);
	padding: var(--s-3) 0; margin-bottom: var(--s-4);
	border-block: 1px solid var(--line-soft);
}
.fsd-fact__value { font-size: var(--t-lg); font-weight: 680; line-height: 1.1; letter-spacing: -.02em; }
.fsd-fact__label { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .07em; color: var(--ink-faint); }

.fsd-sections { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s-1); margin: 0 0 var(--s-4); padding: 0; }
.fsd-sections li {
	font-size: var(--t-xs); color: var(--ink-soft);
	background: var(--bg-sunken); border: 1px solid var(--line-soft);
	border-radius: var(--r-full); padding: .15rem .55rem;
}

.fsd-price { font-size: var(--t-xl); font-weight: 700; letter-spacing: -.025em; line-height: 1.1; }
.fsd-price small { display: block; margin-top: 2px; font-size: var(--t-xs); font-weight: 520; letter-spacing: 0; color: var(--ink-faint); }
.fsd-price s { opacity: .65; }
.fsd-owned { font-size: var(--t-base); font-weight: 620; color: var(--ok); }
.fsd-lock { font-size: var(--t-sm); font-weight: 560; color: var(--ink-faint); }

/* -------------------------------------------------------------- exam grid */

.fsd-examgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: var(--s-3); }
.fsd-exam {
	display: block; padding: var(--s-4); text-decoration: none; color: var(--ink);
	background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--r);
	transition: border-color .16s ease, box-shadow .16s ease;
}
a.fsd-exam:hover { border-color: var(--accent); box-shadow: var(--shadow-1); }
.fsd-exam h3 { font-size: var(--t-md); font-weight: 660; letter-spacing: -.012em; margin-bottom: var(--s-1); }
.fsd-exam p { font-size: var(--t-sm); color: var(--ink-soft); margin-bottom: var(--s-3); }
.fsd-exam__go { font-size: var(--t-sm); font-weight: 620; color: var(--accent); }
.fsd-exam--soon { background: var(--bg-sunken); }
.fsd-exam--soon h3 { color: var(--ink-soft); }
.fsd-exam__soon { font-size: var(--t-xs); font-weight: 620; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); }

/* ------------------------------------------------------------------ steps */

.fsd-steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: var(--s-4); }
.fsd-step { padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-raised); }
.fsd-step__n {
	width: 26px; height: 26px; margin-bottom: var(--s-3);
	display: grid; place-items: center; border-radius: var(--r-full);
	background: var(--accent-bg); color: var(--accent);
	font-size: var(--t-sm); font-weight: 700;
}
.fsd-step h3 { font-size: var(--t-base); font-weight: 660; margin-bottom: var(--s-1); }
.fsd-step p { font-size: var(--t-sm); color: var(--ink-soft); }

/* ---------------------------------------------------------- panels, forms */

.fsd-panel { background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--s-6); box-shadow: var(--shadow-1); }
.fsd-panel--center { text-align: center; }
.fsd-panel__alt { margin-top: var(--s-4); font-size: var(--t-base); color: var(--ink-faint); text-align: center; }

.fsd-form { display: flex; flex-direction: column; gap: var(--s-4); }
.fsd-field { display: flex; flex-direction: column; gap: var(--s-1); text-align: left; }
.fsd-field > span { font-size: var(--t-sm); font-weight: 600; }
.fsd-field input, .fsd-search input, .fsd-nat {
	font: inherit; font-size: var(--t-base);
	padding: .65rem .8rem; color: var(--ink);
	background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-sm);
	transition: border-color .14s ease, box-shadow .14s ease;
}
.fsd-field input:focus, .fsd-search input:focus, .fsd-nat:focus {
	outline: none; border-color: var(--accent);
	box-shadow: 0 0 0 3px var(--accent-bg);
}
.fsd-field small { font-size: var(--t-xs); color: var(--ink-faint); }

/* ------------------------------------------------------------ series page */

.fsd-split { display: grid; grid-template-columns: minmax(0,1fr) 316px; gap: var(--s-8); align-items: start; }
.fsd-split__side { position: sticky; top: 84px; }

.fsd-buybox { background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--s-5); box-shadow: var(--shadow-2); }
.fsd-buybox__price { font-size: var(--t-2xl); font-weight: 720; letter-spacing: -.03em; line-height: 1.1; }
.fsd-buybox__price s { font-size: var(--t-md); font-weight: 500; color: var(--ink-faint); margin-left: var(--s-2); }
.fsd-buybox__off { font-size: var(--t-sm); font-weight: 650; color: var(--ok); margin: 2px 0 var(--s-4); }
.fsd-buybox__facts { list-style: none; margin: 0 0 var(--s-4); padding: 0; font-size: var(--t-base); }
.fsd-buybox__facts li { padding: var(--s-2) 0; border-bottom: 1px solid var(--line-soft); color: var(--ink-soft); }
.fsd-buybox__facts li:last-child { border-bottom: 0; }
.fsd-buybox__facts strong { color: var(--ink); }
.fsd-buybox__note { font-size: var(--t-xs); color: var(--ink-faint); text-align: center; margin-top: var(--s-3); }
.fsd-buybox__owned { font-weight: 650; color: var(--ok); text-align: center; margin-bottom: var(--s-4); }

.fsd-testlist { list-style: none; margin: 0; padding: 0; }
.fsd-testlist__item { display: flex; align-items: center; gap: var(--s-4); padding: var(--s-4) 0; border-bottom: 1px solid var(--line-soft); }
.fsd-testlist__n {
	flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center;
	border-radius: var(--r-full); background: var(--bg-sunken); border: 1px solid var(--line);
	font-size: var(--t-sm); font-weight: 650; color: var(--ink-soft);
}
.fsd-testlist__body { flex: 1; min-width: 0; }
.fsd-testlist__body h3 { font-size: var(--t-base); font-weight: 640; margin-bottom: 1px; }
.fsd-testlist__body p { font-size: var(--t-sm); color: var(--ink-faint); }

/* --------------------------------------------------------- paywall extras */

.fsd-paywall__price { font-size: var(--t-3xl); font-weight: 720; letter-spacing: -.03em; margin: var(--s-4) 0 var(--s-1); }
.fsd-paywall__note { font-size: var(--t-sm); color: var(--ink-faint); margin-top: var(--s-4); }
.fsd-pay-methods { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-1); margin-top: var(--s-4); }
.fsd-pay-methods span {
	font-size: var(--t-xs); color: var(--ink-faint);
	border: 1px solid var(--line); border-radius: var(--r-sm); padding: .2rem .5rem;
}

/* ----------------------------------------------------------------- tables */

.fsd-tablewrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--r); }
.fsd-table { width: 100%; border-collapse: collapse; font-size: var(--t-base); }
.fsd-table th {
	position: sticky; top: 0;
	text-align: left; font-size: var(--t-xs); font-weight: 640;
	letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint);
	padding: var(--s-3) var(--s-4); background: var(--bg-sunken);
	border-bottom: 1px solid var(--line); white-space: nowrap;
}
.fsd-table td { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line-soft); }
.fsd-table tr:last-child td { border-bottom: 0; }
.fsd-table tbody tr:hover { background: var(--bg-sunken); }
.fsd-score { font-weight: 680; letter-spacing: -.01em; }

.fsd-bar { height: 6px; min-width: 84px; background: var(--line); border-radius: var(--r-full); overflow: hidden; margin-top: 4px; }
.fsd-bar > i { display: block; height: 100%; background: var(--accent); border-radius: var(--r-full); }

.fsd-tag { display: inline-block; font-size: var(--t-xs); font-weight: 650; letter-spacing: .04em; text-transform: uppercase; padding: .12rem .45rem; border-radius: var(--r-sm); }
.fsd-tag--ok { background: var(--ok-bg); color: var(--ok); }
.fsd-tag--muted { background: var(--bg-sunken); color: var(--ink-faint); border: 1px solid var(--line); }
.fsd-tag--weak { background: var(--bad-bg); color: var(--bad); }

/* ------------------------------------------------------------------ stats */

.fsd-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(124px, 1fr)); gap: var(--s-3); margin: var(--s-5) 0; }
.fsd-stat { text-align: center; padding: var(--s-4) var(--s-3); border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-raised); }
.fsd-stat__v { font-size: var(--t-xl); font-weight: 700; letter-spacing: -.025em; line-height: 1.1; }
.fsd-stat__l { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .07em; color: var(--ink-faint); margin-top: 2px; }
.fsd-stat--ok .fsd-stat__v { color: var(--ok); }
.fsd-stat--bad .fsd-stat__v { color: var(--bad); }

/* --------------------------------------------------------- admin dashboard */

.fsd-admin__extlinks { display: flex; gap: var(--s-4); font-size: var(--t-sm); margin: var(--s-3) 0 var(--s-5); }

.fsd-admin__kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--s-3); margin: var(--s-4) 0 var(--s-7); }
.fsd-admin__kpi { padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-raised); }
.fsd-admin__kpi-l { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .07em; color: var(--ink-faint); }
.fsd-admin__kpi-v { font-size: var(--t-xl); font-weight: 700; letter-spacing: -.025em; line-height: 1.2; margin-top: 2px; }
.fsd-admin__kpi-d { font-size: var(--t-xs); font-weight: 620; margin-top: 4px; }
.fsd-admin__kpi-d.is-up { color: var(--ok); }
.fsd-admin__kpi-d.is-down { color: var(--bad); }
.fsd-admin__kpi-d--flat { color: var(--ink-faint); font-weight: 500; }

.fsd-admin__attn { list-style: none; margin: var(--s-4) 0 var(--s-7); padding: 0; display: flex; flex-direction: column; gap: var(--s-2); }
.fsd-admin__attn-item { padding: var(--s-3) var(--s-4); border-radius: var(--r-sm); font-size: var(--t-sm); border-left: 3px solid var(--line); }
.fsd-admin__attn-item.is-bad { background: var(--bad-bg); color: var(--bad); border-left-color: var(--bad); }
.fsd-admin__attn-item.is-warn { background: var(--warn-bg); color: var(--warn); border-left-color: var(--warn); }
.fsd-admin__attn-item.is-good { background: var(--ok-bg); color: var(--ok); border-left-color: var(--ok); }

.fsd-admin__spark { display: flex; align-items: flex-end; gap: 3px; height: 64px; margin: var(--s-4) 0 var(--s-7); padding: var(--s-3); border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-raised); }
.fsd-admin__spark-bar { flex: 1 1 auto; height: var(--h, 0%); min-height: 2px; background: var(--accent); border-radius: 1px; opacity: .8; }
.fsd-admin__spark-bar:hover { opacity: 1; }

.fsd-admin__funnel { display: flex; flex-direction: column; gap: var(--s-3); margin: var(--s-4) 0 var(--s-7); }
.fsd-admin__funnel-row { display: grid; grid-template-columns: 160px 1fr 90px; align-items: center; gap: var(--s-3); }
.fsd-admin__funnel-label { font-size: var(--t-sm); color: var(--ink-soft); }
.fsd-admin__funnel-track { height: 10px; border-radius: var(--r-full); background: var(--bg-sunken); overflow: hidden; }
.fsd-admin__funnel-fill { height: 100%; background: var(--accent); border-radius: var(--r-full); }
.fsd-admin__funnel-n { font-size: var(--t-sm); font-weight: 650; text-align: right; }
.fsd-admin__funnel-pct { display: block; font-size: var(--t-xs); font-weight: 500; color: var(--ink-faint); }
@media (max-width: 520px) {
	.fsd-admin__funnel-row { grid-template-columns: 1fr; gap: var(--s-1); }
	.fsd-admin__funnel-n { text-align: left; }
}

.fsd-results__topbar { display: flex; align-items: center; gap: var(--s-4); margin-bottom: var(--s-5); }
.fsd-results__h1 { margin: 0; }
@media (max-width: 520px) {
	.fsd-results__topbar { flex-direction: column; align-items: flex-start; gap: var(--s-2); }
}

.fsd-result__hero { text-align: center; padding: var(--s-8) var(--s-4); background: var(--bg-sunken); border-radius: var(--r-lg); margin-bottom: var(--s-5); }
.fsd-result__score { font-size: var(--t-3xl); font-weight: 720; letter-spacing: -.035em; line-height: 1; }
.fsd-result__of { font-size: var(--t-base); color: var(--ink-faint); margin-top: var(--s-1); }
.fsd-result__tier { display: inline-block; margin-top: var(--s-3); font-size: var(--t-sm); font-weight: 660; padding: .3rem .9rem; border-radius: var(--r-full); background: var(--accent-bg); color: var(--accent); }

/* "Questions to improve" callout — a direct link into the wrong-answer
   filter, not just a number to notice and forget. */
.fsd-improve {
	display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-4);
	background: var(--bad-bg); border: 1px solid color-mix(in srgb, var(--bad) 25%, transparent);
	border-radius: var(--r); padding: var(--s-4) var(--s-5); margin-bottom: var(--s-5);
}
.fsd-improve__label { font-size: var(--t-xs); font-weight: 680; letter-spacing: .09em; text-transform: uppercase; color: var(--bad); margin-bottom: 4px; }
.fsd-improve__count { font-size: var(--t-md); font-weight: 660; }

/* A short memorable fact, distinct from the worked explanation — visually
   its own thing so it reads as a takeaway, not more of the same paragraph. */
.fsd-tip { background: var(--warn-bg); border-left: 2px solid var(--warn); border-radius: 0 var(--r-sm) var(--r-sm) 0; padding: var(--s-3) var(--s-4); margin-top: var(--s-3); }
.fsd-tip__label { font-size: var(--t-xs); font-weight: 680; letter-spacing: .09em; text-transform: uppercase; color: var(--warn); margin-bottom: 4px; }
.fsd-tip p { font-size: var(--t-base); margin: 0; }

.fsd-rankbar { display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: var(--s-3); padding: var(--s-4); margin-bottom: var(--s-5); text-align: center; background: var(--accent-bg); border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent); border-radius: var(--r); }
.fsd-rankbar strong { display: block; font-size: var(--t-xl); font-weight: 700; letter-spacing: -.025em; }
.fsd-rankbar span { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .06em; color: var(--ink-faint); }
.fsd-ranknote { font-size: var(--t-base); color: var(--ink-faint); text-align: center; margin-bottom: var(--s-5); }

.fsd-nudges { background: var(--accent-bg); border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent); border-radius: var(--r); padding: var(--s-4) var(--s-5); margin: var(--s-5) 0; }
.fsd-nudges__label { font-size: var(--t-xs); font-weight: 680; letter-spacing: .09em; text-transform: uppercase; color: var(--accent); margin-bottom: var(--s-2); }
.fsd-nudges p { font-size: var(--t-base); margin-bottom: var(--s-2); }
.fsd-nudges p:last-child { margin-bottom: 0; }

/* "Next best step" — the card that survives a dismissed popup, on the
   result page itself, so the CTA is never lost even once the overlay above
   is gone. */
.fsd-upnext {
	background: var(--accent-bg); border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
	border-radius: var(--r); padding: var(--s-5); margin-bottom: var(--s-5);
}
.fsd-upnext__label { font-size: var(--t-xs); font-weight: 680; letter-spacing: .09em; text-transform: uppercase; color: var(--accent); margin-bottom: var(--s-2); }
.fsd-upnext__title { font-size: var(--t-md); font-weight: 660; margin-bottom: var(--s-1); }
.fsd-upnext__reason { font-size: var(--t-sm); color: var(--ink-soft); margin-bottom: var(--s-3); }
.fsd-upnext__meta { font-size: var(--t-sm); color: var(--ink-faint); margin-bottom: var(--s-4); }
.fsd-upnext__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); flex-wrap: wrap; }
.fsd-upnext__price { font-size: var(--t-md); font-weight: 660; }

/* Full-screen recommendation popup — rides .fsd-modal-scrim/.fsd-modal for
   the backdrop, card shell and entrance animation every other modal on this
   screen already uses; only what's actually different from a plain confirm
   dialog lives here. */
.fsd-upnext-modal { max-width: 380px; text-align: center; position: relative; }
.fsd-upnext-modal__close {
	position: absolute; top: var(--s-3); right: var(--s-3);
	width: 32px; height: 32px; display: flex; align-items: center; justify-content: center;
	background: transparent; border: 0; border-radius: var(--r-full); color: var(--ink-faint);
	font-size: 1.4rem; line-height: 1; cursor: pointer;
}
.fsd-upnext-modal__close:hover { background: var(--bg-sunken); color: var(--ink); }
.fsd-upnext-modal__icon { font-size: 2rem; margin-bottom: var(--s-3); }
.fsd-upnext-modal__card {
	background: var(--bg-sunken); border-radius: var(--r); padding: var(--s-4);
	margin: var(--s-4) 0 var(--s-5); display: flex; flex-direction: column; align-items: center; gap: 6px;
}
.fsd-upnext-modal__test { font-size: var(--t-md); font-weight: 660; }
.fsd-upnext-modal__meta { font-size: var(--t-sm); color: var(--ink-faint); }
@media (max-width: 480px) {
	.fsd-upnext-modal { max-width: calc(100% - 32px); }
}

/* ------------------------------------------------------------ dashboard */

/* Weak/strong areas — the same numbers as the detailed table below, read
   at a glance before anyone scrolls to the table itself. */
.fsd-areas { display: flex; flex-wrap: wrap; gap: var(--s-2); margin: var(--s-4) 0 var(--s-6); }
.fsd-areas .fsd-tag { font-size: var(--t-sm); padding: .35rem .8rem; }
.fsd-tag--ok { background: var(--ok-bg); color: var(--ok); }

/* Per-exam completion bars. */
.fsd-examprogress { display: grid; gap: var(--s-4); margin: var(--s-4) 0 var(--s-6); }
.fsd-examprogress__row { display: grid; gap: 6px; }
.fsd-examprogress__head { display: flex; justify-content: space-between; font-size: var(--t-sm); }
.fsd-examprogress__head b { font-weight: 660; }
.fsd-examprogress__head span { color: var(--ink-faint); }

/* Recommended-next callout. */
.fsd-recommend {
	display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-4);
	background: var(--accent-bg); border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
	border-radius: var(--r); padding: var(--s-4) var(--s-5); margin: var(--s-4) 0 var(--s-6);
}
.fsd-recommend__label { font-size: var(--t-xs); font-weight: 680; letter-spacing: .09em; text-transform: uppercase; color: var(--accent); margin-bottom: 4px; }
.fsd-recommend__title { font-size: var(--t-md); font-weight: 660; }
.fsd-recommend__why { font-size: var(--t-sm); color: var(--ink-soft); margin-top: 2px; }

/* "Continue practicing" featured card. */
.fsd-continue {
	display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-4);
	background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--r-lg);
	padding: var(--s-5); margin-bottom: var(--s-6); box-shadow: var(--shadow-1);
}
.fsd-continue__label { font-size: var(--t-xs); font-weight: 680; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: 4px; }
.fsd-continue__title { font-size: var(--t-lg); font-weight: 700; }
.fsd-continue__meta { font-size: var(--t-sm); color: var(--ink-soft); margin-top: 2px; }
.fsd-continue__bar { width: 220px; max-width: 100%; }

/* ============================================================ dashboard v2
   Streak header, readiness, weak-area bars, progress trend, exam/topic
   cards and the activity feed. Same maroon/cream tokens as everywhere
   else — no new palette, just more visual weight for the numbers that
   actually answer "am I ready" and "what's weak".
   ========================================================================== */

.fsd-dhead { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-5); flex-wrap: wrap; }
.fsd-streak {
	flex: none; text-align: center; padding: var(--s-3) var(--s-5);
	background: var(--accent-bg); border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
	border-radius: var(--r);
}
.fsd-streak__v { font-family: var(--font-display); font-size: 2rem; font-weight: 800; color: var(--accent); line-height: 1; }
.fsd-streak__l { font-size: var(--t-xs); font-weight: 650; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-faint); margin-top: 2px; }

/* Exam readiness — the one number this page leads with. */
.fsd-readiness {
	margin: var(--s-5) 0; padding: var(--s-5);
	border-radius: var(--r-lg); border: 1px solid var(--line);
	background: var(--bg-raised);
}
.fsd-readiness__head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap; margin-bottom: var(--s-4); }
.fsd-readiness__tier {
	font-size: var(--t-xs); font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
	padding: 5px 12px; border-radius: var(--r-full);
}
.fsd-readiness.is-likely     { border-color: color-mix(in srgb, var(--ok) 30%, transparent); }
.fsd-readiness.is-likely     .fsd-readiness__tier { background: var(--ok-bg); color: var(--ok); }
.fsd-readiness.is-borderline { border-color: color-mix(in srgb, var(--warn) 35%, transparent); }
.fsd-readiness.is-borderline .fsd-readiness__tier { background: var(--warn-bg); color: var(--warn); }
.fsd-readiness.is-needswork  { border-color: color-mix(in srgb, var(--bad) 30%, transparent); }
.fsd-readiness.is-needswork  .fsd-readiness__tier { background: var(--bad-bg); color: var(--bad); }
.fsd-readiness__facts { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-4); margin-bottom: var(--s-4); }
.fsd-readiness__v { font-family: var(--font-display); font-size: 1.7rem; font-weight: 800; letter-spacing: -.02em; }
.fsd-readiness__l { font-size: var(--t-xs); color: var(--ink-faint); margin-top: 2px; }
.fsd-readiness__note { font-size: var(--t-sm); color: var(--ink-soft); margin: 0; max-width: 72ch; }

/* Weak areas — the visual, actionable form of section-strength. */
.fsd-weakareas { display: flex; flex-direction: column; gap: var(--s-4); margin: var(--s-4) 0 var(--s-6); }
.fsd-weakareas__top { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 6px; }
.fsd-weakareas__label { font-weight: 650; }
.fsd-weakareas__pct { font-family: var(--mono); font-weight: 700; color: var(--ink-soft); }
.fsd-weakareas__pct.is-weak { color: var(--bad); }
.fsd-weakareas__pct.is-ok { color: var(--ok); }
.fsd-bar--wide { min-width: 100%; height: 8px; }

/* Score-over-time sparkline — a hand-rolled inline SVG, not a charting
   dependency, consistent with the ticker/marquee elsewhere on the site. */
.fsd-trend { margin: var(--s-4) 0 var(--s-6); padding: var(--s-4) var(--s-5); border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-raised); }
.fsd-trend__svg { width: 100%; height: 120px; display: block; }
.fsd-trend__note { font-size: var(--t-sm); color: var(--ink-soft); margin: var(--s-2) 0 0; }

/* My Exams / My Topics cards. */
.fsd-examcards { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--s-3); }
.fsd-examcard {
	display: block; padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r);
	background: var(--bg-raised); text-decoration: none; color: inherit;
	transition: border-color .14s ease, transform .14s ease;
}
.fsd-examcard:hover { border-color: var(--accent); transform: translateY(-2px); }
.fsd-examcard h3 { font-size: var(--t-base); font-weight: 660; margin-bottom: var(--s-3); }
.fsd-examcard__score { font-family: var(--font-display); font-size: 1.6rem; font-weight: 800; color: var(--accent); }
.fsd-examcard__score span { font-family: var(--font); font-size: var(--t-xs); font-weight: 600; color: var(--ink-faint); margin-left: 4px; text-transform: uppercase; }
.fsd-examcard__meta { font-size: var(--t-xs); color: var(--ink-faint); margin-top: var(--s-2); }

/* Recent activity feed, replacing a raw table with something scannable. */
.fsd-activity { list-style: none; margin: var(--s-4) 0 var(--s-6); padding: 0; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.fsd-activity__row {
	display: flex; align-items: center; gap: var(--s-4);
	padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line-soft);
}
.fsd-activity__row:last-child { border-bottom: 0; }
.fsd-activity__row:nth-child(even) { background: var(--bg-sunken); }
.fsd-activity__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; text-decoration: none; color: inherit; }
.fsd-activity__title { font-weight: 620; color: var(--ink); }
.fsd-activity__title:hover { color: var(--accent); }
.fsd-activity__meta { font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-activity__score {
	flex: none; font-family: var(--mono); font-weight: 700; font-size: var(--t-sm);
	padding: 3px 10px; border-radius: var(--r-full); background: var(--bg-sunken); color: var(--ink-soft);
}
.fsd-activity__score.is-ok { background: var(--ok-bg); color: var(--ok); }
.fsd-activity__score.is-weak { background: var(--bad-bg); color: var(--bad); }
.fsd-activity__time { flex: none; font-size: var(--t-xs); color: var(--ink-faint); width: 4.5rem; text-align: right; }
.fsd-activity__icon { flex: none; font-size: 1.1rem; line-height: 1; width: 1.6rem; text-align: center; }

/* Header identity + notifications, dashboard only. */
.fsd-dhead__id { display: flex; align-items: center; gap: var(--s-4); }
.fsd-dhead__actions { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.fsd-avatar {
	flex: none; width: 48px; height: 48px; border-radius: 50%;
	display: flex; align-items: center; justify-content: center;
	background: var(--accent); color: var(--on-accent);
	font-family: var(--font-display); font-weight: 800; font-size: 1.2rem;
	text-decoration: none;
}
.fsd-avatar--sm { width: 34px; height: 34px; font-size: .9rem; }
.fsd-bell {
	position: relative; display: flex; align-items: center; justify-content: center;
	width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--line);
	color: var(--ink-soft); text-decoration: none; background: var(--bg-raised);
}
.fsd-bell:hover { border-color: var(--accent); color: var(--accent); }
.fsd-bell__badge {
	position: absolute; top: -3px; right: -3px; min-width: 18px; height: 18px; padding: 0 4px;
	border-radius: var(--r-full); background: var(--bad); color: var(--on-accent);
	font-family: var(--mono); font-size: .65rem; font-weight: 700; line-height: 18px; text-align: center;
	border: 2px solid var(--bg);
}

/* Performance-overview stat row. */
.fsd-overview { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--s-3); margin: var(--s-5) 0; }
.fsd-ocard {
	padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-raised);
	display: flex; flex-direction: column; gap: 4px;
}
.fsd-ocard__label { font-size: var(--t-xs); font-weight: 650; text-transform: uppercase; letter-spacing: .05em; color: var(--ink-faint); }
.fsd-ocard__row { display: flex; align-items: baseline; gap: var(--s-2); flex-wrap: wrap; }
.fsd-ocard__v { font-family: var(--font-display); font-size: 1.8rem; font-weight: 800; line-height: 1; }
.fsd-ocard__v--muted { color: var(--ink-faint); }
.fsd-ocard__note { font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-ocard__spark { margin-top: 2px; }
.fsd-delta { font-family: var(--mono); font-size: var(--t-xs); font-weight: 700; padding: 1px 6px; border-radius: var(--r-sm); }
.fsd-delta.is-up { background: var(--ok-bg); color: var(--ok); }
.fsd-delta.is-down { background: var(--bad-bg); color: var(--bad); }
.fsd-ocard--ring { align-items: center; text-align: center; }
.fsd-ocard__ring { position: relative; display: inline-flex; align-items: center; justify-content: center; }
.fsd-ocard__ring--sm { width: 84px; height: 84px; margin: 0 auto var(--s-2); }
.fsd-ocard__ring--lg { width: 150px; height: 150px; }
.fsd-ocard__ringv {
	position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
	font-family: var(--font-display); font-weight: 800; font-size: 1.15rem; text-align: center;
}
.fsd-ocard__ringv--sm { font-size: .82rem; }
.fsd-ocard__ringv--lg { font-size: 1.6rem; display: flex; flex-direction: column; line-height: 1.15; }
.fsd-ocard__ringv--lg small { font-family: var(--font); font-size: var(--t-xs); font-weight: 600; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .04em; }

/* Two-column analysis rows. */
.fsd-drow { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4); margin: var(--s-5) 0; align-items: start; }
.fsd-drow--wide { grid-template-columns: 1.3fr 1fr; }
.fsd-panel-card { padding: var(--s-5); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--bg-raised); }
.fsd-panel-card__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); }
.fsd-panel-card__all { font-size: var(--t-sm); font-weight: 650; color: var(--accent); text-decoration: none; }
.fsd-panel-card__all:hover { text-decoration: underline; }

.fsd-analysis { display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap; margin: var(--s-3) 0; }
.fsd-analysis__body { flex: 1 1 220px; min-width: 0; }
.fsd-analysis__lede { margin-bottom: var(--s-3); }
.fsd-analysis__boxes { display: flex; gap: var(--s-2); flex-wrap: wrap; }
.fsd-analysis__box {
	flex: 1 1 80px; text-align: center; padding: var(--s-2) var(--s-3); border-radius: var(--r-sm);
	background: var(--bg-sunken); font-size: var(--t-xs); color: var(--ink-faint);
}
.fsd-analysis__box b { display: block; font-family: var(--font-display); font-size: 1.15rem; color: var(--ink); }
.fsd-analysis__box.is-ok { background: var(--ok-bg); }
.fsd-analysis__box.is-ok b { color: var(--ok); }
.fsd-analysis__box.is-bad { background: var(--bad-bg); }
.fsd-analysis__box.is-bad b { color: var(--bad); }

/* Recommended-for-you list inside the weak-areas panel. */
.fsd-recfor { margin-top: var(--s-4); padding-top: var(--s-4); border-top: 1px solid var(--line-soft); }
.fsd-recfor__label { font-size: var(--t-xs); font-weight: 680; text-transform: uppercase; letter-spacing: .06em; color: var(--accent); margin-bottom: var(--s-2); }
.fsd-recfor__item { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-2) 0; text-decoration: none; color: inherit; }
.fsd-recfor__icon {
	flex: none; width: 30px; height: 30px; border-radius: 50%; background: var(--accent-bg); color: var(--accent);
	display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: .85rem;
}
.fsd-recfor__title { display: block; font-weight: 620; }
.fsd-recfor__title:hover { color: var(--accent); }
.fsd-recfor__meta { display: block; font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-recfor__cta { display: block; text-align: center; margin-top: var(--s-3); }

/* ---- Week dots, inline in the dashboard header ---- */
.fsd-weekdots { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin-top: 6px; }
.fsd-weekdots__streak { font-weight: 700; font-size: var(--t-sm); margin-right: var(--s-2); }
.fsd-weekdots__d {
	width: 22px; height: 22px; border-radius: 50%;
	display: flex; align-items: center; justify-content: center;
	font-size: .62rem; font-weight: 700;
	background: var(--bg-sunken); color: var(--ink-faint); border: 1px solid var(--line);
}
.fsd-weekdots__d.is-on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.fsd-weekdots__d.is-future { background: transparent; border-style: dashed; opacity: .55; }
.fsd-weekdots__d.is-today { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent); }
.fsd-weekdots__sum { font-size: var(--t-xs); color: var(--ink-faint); margin-left: var(--s-2); }

/* ===================================================== dashboard, cleaned up
   The page was four call-to-action cards deep before anything useful, and
   4,478px tall on a 375px phone -- five and a half screens. Section prompts
   like "How long have you got?" were set at 12px uppercase, which is a label
   size being asked to do a heading's job: the reader met a question written
   smaller than the answers underneath it.
   ========================================================================== */

/* The greeting. Sized down hard on a phone, where the old clamp put a
   26px line above the fold and left room for nothing else. */
.fsd-dhead__h {
	font-family: var(--font-display);
	font-size: clamp(1.4rem, 4.4vw, 2rem);
	font-weight: 800; letter-spacing: -.015em; line-height: 1.15;
	margin: 0 0 2px;
}

/* A section prompt is a question, so it is set like one: sentence case,
   readable size, real weight. Uppercase micro-labels stay for things that
   genuinely are labels. */
.fsd-dsec__h {
	font-family: var(--font-display);
	font-size: clamp(1.05rem, 2.6vw, 1.25rem);
	font-weight: 800; letter-spacing: -.01em; line-height: 1.25;
	margin: 0 0 var(--s-3); text-transform: none; color: var(--ink);
}

/* ---- the week, drawn as a calendar ---- */
.fsd-weekbar {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-4) var(--s-5); flex-wrap: wrap;
	padding: var(--s-3) var(--s-4); margin-bottom: var(--s-4);
	border: 1px solid var(--line); border-radius: var(--r);
	background: var(--bg-raised);
}
.fsd-weekbar__days {
	display: grid; grid-template-columns: repeat(7, 1fr);
	gap: 6px; list-style: none; margin: 0; padding: 0;
	flex: 1 1 220px; max-width: 320px;
}
.fsd-weekday {
	aspect-ratio: 1; min-height: 30px;
	display: flex; align-items: center; justify-content: center;
	border-radius: 50%; border: 1px solid var(--line);
	background: var(--bg-sunken); color: var(--ink-faint);
	font-size: .72rem; font-weight: 800; font-family: var(--font-display);
}
.fsd-weekday.is-on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
/* Not yet happened is not the same as missed, so it is drawn as absent. */
.fsd-weekday.is-future { background: transparent; border-style: dashed; color: var(--ink-faint); opacity: .55; }
.fsd-weekday.is-today { box-shadow: 0 0 0 2px var(--bg-raised), 0 0 0 4px var(--accent); }
.fsd-weekbar__sum { margin: 0; font-size: var(--t-sm); color: var(--ink-soft); }
.fsd-weekbar__sum b { color: var(--ink); font-weight: 750; }
.fsd-weekbar__streak {
	display: inline-flex; align-items: center; gap: 5px;
	margin-right: var(--s-3); font-weight: 750; color: var(--ink);
}

@media (max-width: 560px) {
	/* One job per line on a phone: the calendar, then what it adds up to. */
	.fsd-weekbar { padding: var(--s-3); gap: var(--s-3); }
	.fsd-weekbar__days { max-width: none; flex-basis: 100%; }
	.fsd-weekbar__sum { flex-basis: 100%; font-size: var(--t-xs); }
	.fsd-weekday { min-height: 34px; font-size: .78rem; }
}

/* ---- Hero: the one next action, beside the one headline number ---- */
.fsd-hero2 { display: grid; grid-template-columns: 1.15fr 1fr; gap: var(--s-4); margin: var(--s-5) 0; align-items: stretch; }
.fsd-nextup {
	padding: var(--s-5); border-radius: var(--r-lg);
	background: var(--accent-bg); border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
	display: flex; flex-direction: column;
}
/* The topic used to be set at 1.35rem above the paper title, so "Next up"
   arrived as three stacked headings of descending size before any fact
   about the paper. It is a tag now; the paper's own name is the heading. */
.fsd-nextup__topic {
	display: inline-block; margin: 0 0 var(--s-2);
	/* --r-sm, not a full pill — same reasoning as .fsd-topics li: this is a
	   real catalog label and can run long enough to wrap. */
	padding: 2px 9px; border-radius: var(--r-sm);
	background: var(--accent-bg); color: var(--accent);
	font-family: var(--font); font-size: var(--t-xs);
	font-weight: 750; letter-spacing: .01em;
}
.fsd-nextup__title {
	font-family: var(--font-display); font-weight: 800;
	font-size: clamp(1.15rem, 3vw, 1.4rem); line-height: 1.25;
	letter-spacing: -.01em;
}
.fsd-nextup__meta { font-size: var(--t-xs); color: var(--ink-faint); margin-top: 2px; }
.fsd-nextup__why { font-size: var(--t-sm); color: var(--ink-soft); margin: var(--s-3) 0 var(--s-4); max-width: 46ch; }
.fsd-nextup .fsd-btn { align-self: flex-start; margin-top: auto; }

.fsd-snap {
	padding: var(--s-5); border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--bg-raised);
	display: flex; align-items: center; gap: var(--s-5); flex-wrap: wrap;
}
.fsd-snap__ring { position: relative; flex: none; display: inline-flex; align-items: center; justify-content: center; }
.fsd-snap__v {
	position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
	display: flex; flex-direction: column; align-items: center; line-height: 1.1;
	font-family: var(--font-display); font-size: 1.6rem; font-weight: 800;
}
.fsd-snap__v small { font-family: var(--font); font-size: var(--t-xs); font-weight: 600; color: var(--ink-faint); text-transform: uppercase; letter-spacing: .04em; }
.fsd-snap__side { flex: 1 1 180px; min-width: 0; }
.fsd-snap__tier { font-weight: 700; font-size: var(--t-md); margin-bottom: 4px; }
.fsd-snap__tier.is-ok { color: var(--ok); }
.fsd-snap__tier.is-warn { color: var(--warn); }
.fsd-snap__tier.is-bad { color: var(--bad); }
.fsd-snap__note { font-size: var(--t-sm); color: var(--ink-soft); margin: 0; }
.fsd-snap__note .fsd-note { display: block; margin-top: 6px; }
.fsd-snap__empty { color: var(--ink-soft); font-size: var(--t-sm); }

/* ---- Stat strip: five numbers on one row ---- */
.fsd-strip {
	display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px;
	margin: var(--s-5) 0; border: 1px solid var(--line); border-radius: var(--r);
	background: var(--line); overflow: hidden;
}
.fsd-strip__i { background: var(--bg-raised); padding: var(--s-4); text-align: center; text-decoration: none; color: inherit; }
.fsd-strip__i--link:hover { background: var(--bg-sunken); }
.fsd-strip__i b { display: block; font-family: var(--font-display); font-size: 1.7rem; font-weight: 800; line-height: 1.1; }
.fsd-strip__i b.is-bad { color: var(--bad); }
.fsd-strip__i span { display: block; font-size: var(--t-xs); color: var(--ink-faint); margin-top: 3px; }
.fsd-strip__i i { display: block; font-style: normal; font-size: var(--t-xs); color: var(--ink-faint); margin-top: 3px; }

/* ---- The one tabbed panel carrying every analysis ---- */
.fsd-dtabs { margin: var(--s-5) 0; }
.fsd-dtabs .fsd-guide__panel { border: 1px solid var(--line); border-top: 0; border-radius: 0 0 var(--r) var(--r); }
.fsd-dtabs .fsd-h3 { margin-top: var(--s-6); }
.fsd-dtabs .fsd-guide__panel > .fsd-h3:first-child { margin-top: 0; }

/* ---- Compact "ready to take" list, replacing a grid of 25 cards ---- */
.fsd-openlist { list-style: none; margin: var(--s-3) 0 0; padding: 0; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.fsd-openlist li {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line-soft);
}
.fsd-openlist li:last-child { border-bottom: 0; }
.fsd-openlist li:nth-child(even) { background: var(--bg-sunken); }
.fsd-openlist a { flex: 1 1 auto; min-width: 0; text-decoration: none; color: inherit; }
.fsd-openlist__t { display: block; font-weight: 620; }
.fsd-openlist a:hover .fsd-openlist__t { color: var(--accent); }
.fsd-openlist__m { display: block; font-size: var(--t-xs); color: var(--ink-faint); margin-top: 1px; }
.fsd-openlist__a { flex: none; font-size: var(--t-xs); color: var(--ink-faint); }

.fsd-acct { margin: var(--s-6) 0 var(--s-5); }

/* ---- Weak areas, each with its own practice CTA ---- */
.fsd-weak { display: flex; flex-direction: column; gap: var(--s-4); margin: var(--s-4) 0 var(--s-6); }
.fsd-weak__row { display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap; }
.fsd-weak__main { flex: 1 1 260px; min-width: 0; }
.fsd-weak__top { display: flex; align-items: baseline; gap: var(--s-2); margin-bottom: 6px; }
.fsd-weak__dot { flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--ink-faint); }
.fsd-weak__dot.is-ok { background: var(--ok); }
.fsd-weak__dot.is-warn { background: var(--warn); }
.fsd-weak__dot.is-bad { background: var(--bad); }
.fsd-weak__label { font-weight: 650; }
.fsd-weak__pct { margin-left: auto; font-family: var(--mono); font-weight: 700; color: var(--ink-soft); }
.fsd-weak__pct.is-ok { color: var(--ok); }
.fsd-weak__pct.is-warn { color: var(--warn); }
.fsd-weak__pct.is-bad { color: var(--bad); }

/* ---- Mistake bank buckets (inside the Weak areas tab) ---- */
.fsd-mistakes__buckets { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-3); }
.fsd-mistakes__bucket {
	display: flex; align-items: center; gap: var(--s-2);
	/* --r-sm, not a full pill — the label is a real catalog topic name and
	   can run long enough to wrap; see .fsd-topics li. */
	padding: 6px 12px; border-radius: var(--r-sm); background: var(--bg); border: 1px solid var(--line);
	font-size: var(--t-sm);
}
.fsd-mistakes__bucket b { font-family: var(--mono); color: var(--bad); }

/* ---- Negative marking (inside the Weak areas tab) ---- */
.fsd-negative__facts { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-4); margin-top: var(--s-3); }
.fsd-negative__v { font-family: var(--font-display); font-size: 1.8rem; font-weight: 800; }
.fsd-negative__v.is-ok { color: var(--ok); }
.fsd-negative__v.is-bad { color: var(--bad); }
.fsd-negative__l { font-size: var(--t-xs); color: var(--ink-faint); margin-top: 2px; }
.fsd-negative__note { font-size: var(--t-sm); color: var(--ink-soft); margin: var(--s-4) 0 0; max-width: 74ch; }

/* ---- Mastery list, used by both Study-by-Exam and Study-by-Topic ---- */
.fsd-masterlist { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--s-4); }
.fsd-master {
	display: block; padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r);
	background: var(--bg); text-decoration: none; color: inherit;
	transition: border-color .14s ease, transform .14s ease;
}
.fsd-master:hover { border-color: var(--accent); transform: translateY(-2px); }
.fsd-master__top { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); margin-bottom: 6px; }
.fsd-master__name { font-weight: 650; }
.fsd-master__pct { flex: none; font-family: var(--mono); font-weight: 700; color: var(--ink-soft); }
.fsd-master__pct.is-ok { color: var(--ok); }
.fsd-master__pct.is-warn { color: var(--warn); }
.fsd-master__pct.is-bad { color: var(--bad); }
.fsd-master__meta { font-size: var(--t-xs); color: var(--ink-faint); margin-top: 6px; }

/* ---- PYQ year-over-year ---- */
.fsd-years { display: flex; flex-direction: column; gap: var(--s-2); margin: var(--s-2) 0; }
.fsd-years__row { display: flex; align-items: center; gap: var(--s-3); }
.fsd-years__y { flex: none; width: 3rem; font-family: var(--mono); font-size: var(--t-sm); color: var(--ink-faint); }
.fsd-years__p { flex: none; width: 3.2rem; text-align: right; font-family: var(--mono); font-weight: 700; font-size: var(--t-sm); }
.fsd-years__delta { font-size: var(--t-sm); font-weight: 650; margin: var(--s-2) 0 var(--s-4); }
.fsd-years__delta.is-ok { color: var(--ok); }
.fsd-years__delta.is-bad { color: var(--bad); }

/* ---- Full mock stats ---- */
.fsd-mockstats { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: var(--s-3); margin: var(--s-4) 0; }
.fsd-mockstats div { padding: var(--s-3); border-radius: var(--r-sm); background: var(--bg-sunken); text-align: center; }
.fsd-mockstats b { display: block; font-family: var(--font-display); font-size: 1.3rem; font-weight: 800; }
.fsd-mockstats span { display: block; font-size: var(--t-xs); color: var(--ink-faint); margin-top: 2px; }

.fsd-table--history .fsd-table__when { white-space: nowrap; color: var(--ink-faint); font-size: var(--t-xs); }
.fsd-score.is-ok { color: var(--ok); }
.fsd-score.is-warn { color: var(--warn); }
.fsd-score.is-bad { color: var(--bad); }
.fsd-note { font-size: var(--t-sm); color: var(--ink-faint); max-width: 74ch; }

@media (max-width: 1000px) {
	.fsd-hero2 { grid-template-columns: 1fr; }
	.fsd-strip { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 760px) {
	.fsd-negative__facts { grid-template-columns: 1fr; gap: var(--s-3); }
	.fsd-strip { grid-template-columns: repeat(2, 1fr); }
	.fsd-strip__i b { font-size: 1.4rem; }
	.fsd-weekdots__sum { flex-basis: 100%; margin-left: 0; }
}

/* Horizontal-scroll exam/topic progress cards, inside the segtoggle panel. */
.fsd-scrollcards { display: flex; gap: var(--s-3); overflow-x: auto; padding-bottom: var(--s-2); scrollbar-width: thin; }
.fsd-scrollcard {
	flex: none; width: 168px; padding: var(--s-4); border: 1px solid var(--line); border-radius: var(--r);
	background: var(--bg); text-decoration: none; color: inherit; text-align: center;
	transition: border-color .14s ease, transform .14s ease;
}
.fsd-scrollcard:hover { border-color: var(--accent); transform: translateY(-2px); }
.fsd-scrollcard h3 { font-size: var(--t-sm); font-weight: 660; margin: var(--s-1) 0 2px; }
.fsd-scrollcard__meta { font-size: var(--t-xs); color: var(--ink-faint); }

@media (max-width: 900px) {
	.fsd-overview { grid-template-columns: repeat(2, 1fr); }
	.fsd-drow, .fsd-drow--wide { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
	.fsd-readiness__facts { grid-template-columns: 1fr; gap: var(--s-3); }
	.fsd-activity__row { flex-wrap: wrap; }
	.fsd-activity__time { width: auto; }
	.fsd-overview { grid-template-columns: 1fr 1fr; }
	.fsd-dhead__id { gap: var(--s-3); }

	/* Phone density. Every block on the dashboard was carrying desktop
	   padding, and the sum of it was several screens of empty space
	   between things a student actually taps. */
	.fsd-wrap--dash { padding-left: var(--s-4); padding-right: var(--s-4); padding-top: var(--s-5); }
	.fsd-dhead { margin-bottom: var(--s-3); }
	.fsd-dailycard, .fsd-dseries, .fsd-nudges { padding: var(--s-4); margin-bottom: var(--s-3); }
	.fsd-timepick { margin-bottom: var(--s-4); }
	.fsd-strip { gap: var(--s-2); }
	.fsd-strip__i { padding: var(--s-3); }
	.fsd-strip__i b { font-size: 1.25rem; }
}

/* ================================================================ app shell
   The dashboard's own sidebar layout — dark, high-contrast, distinct from
   the marketing site's white/cream pages the way an app screen should be.
   Built from the same tokens as everywhere else (--ink for the dark
   surface, --accent for anything interactive) rather than a second colour
   system living next to the first.
   ========================================================================== */

.fsd-appshell {
	display: flex;
	align-items: stretch;
	/* So the pinned sidebar still fills the screen on a short dashboard. */
	min-height: calc(100vh - var(--sticky-nav-h, 68px));
}
.fsd-appmain { flex: 1 1 auto; min-width: 0; }

/*
   Pinned, not scrolling: the sidebar holds its position while the dashboard
   scrolls under it, and runs from just below the header to the bottom of the
   screen.

   `top` is the header's measured height rather than 0 — ui.js's
   stickyOffsets() publishes --sticky-nav-h from .fsd-nav on load and resize.
   Two sticky elements both at top:0 would pin to the same spot and the
   sidebar would sit behind the header, which is why this offset exists
   rather than the sidebar simply being sticky.

   sticky rather than fixed so the element stays in the flex row and keeps
   reserving its column — fixed would take it out of flow and the main
   content would need a matching margin-left that has to be kept in sync
   with the width, including while it animates on collapse.

   align-self: flex-start matters: the shell stretches its children by
   default, and a flex item stretched to the container's full height has no
   room to move, so sticky would silently do nothing.
*/
.fsd-appnav {
	flex: none; width: 264px;
	background: var(--ink); color: var(--on-ink);
	display: flex; flex-direction: column;
	padding: var(--s-5) var(--s-4);
	transition: width .16s ease, padding .16s ease;

	position: sticky;
	top: var(--sticky-nav-h, 68px);
	align-self: flex-start;
	height: calc(100vh - var(--sticky-nav-h, 68px));
	overflow-y: auto;
	/* A long menu scrolls inside the rail without handing the scroll back
	   to the page the moment it bottoms out. */
	overscroll-behavior: contain;
}
.fsd-appnav__label {
	font-size: var(--t-xs); font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
	color: color-mix(in srgb, var(--on-ink) 62%, transparent); margin: 0 0 var(--s-3) var(--s-2);
}
.fsd-appnav__list { display: flex; flex-direction: column; gap: 2px; }
.fsd-appnav__item {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-3);
	border-radius: var(--r-sm);
	color: color-mix(in srgb, var(--on-ink) 86%, transparent); text-decoration: none;
	font-size: var(--t-base); font-weight: 560;
	transition: background .14s ease, color .14s ease;
}
.fsd-appnav__item svg { flex: none; opacity: .85; }
.fsd-appnav__item-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
a.fsd-appnav__item:hover { background: color-mix(in srgb, var(--on-ink) 10%, transparent); color: var(--on-ink); }
a.fsd-appnav__item.is-active { background: var(--accent); color: var(--on-accent); }
a.fsd-appnav__item.is-active svg { opacity: 1; }
.fsd-appnav__item.is-soon { color: color-mix(in srgb, var(--on-ink) 55%, transparent); cursor: default; }
.fsd-appnav__soon {
	margin-left: auto; font-family: var(--mono); font-size: .62rem; font-weight: 700;
	letter-spacing: .04em; text-transform: uppercase;
	padding: 2px 7px; border-radius: var(--r-full);
	background: color-mix(in srgb, var(--on-ink) 12%, transparent); color: color-mix(in srgb, var(--on-ink) 70%, transparent);
}

.fsd-appnav__promo {
	margin-top: auto; padding-top: var(--s-5);
}
.fsd-appnav__promo-h { font-weight: 700; color: var(--on-ink); margin-bottom: 4px; }
.fsd-appnav__promo-note { font-size: var(--t-xs); color: color-mix(in srgb, var(--on-ink) 72%, transparent); line-height: 1.5; margin-bottom: var(--s-3); }
.fsd-appnav__promo-btn { width: 100%; }

/* Collapsed: an icon-only rail. Labels, the promo box and the label caption
   drop out; the tooltip (title=) each item already carries picks up the
   wayfinding job the visible text was doing. */
.fsd-appshell.is-collapsed .fsd-appnav { width: 76px; padding-left: var(--s-3); padding-right: var(--s-3); }
.fsd-appshell.is-collapsed .fsd-appnav__label,
.fsd-appshell.is-collapsed .fsd-appnav__item-text,
.fsd-appshell.is-collapsed .fsd-appnav__soon,
.fsd-appshell.is-collapsed .fsd-appnav__promo { display: none; }
.fsd-appshell.is-collapsed .fsd-appnav__item { justify-content: center; padding-left: var(--s-2); padding-right: var(--s-2); }

@media (max-width: 900px) {
	/* The collapse toggle is a desktop-rail concept — below the breakpoint
	   the sidebar is already a compact horizontal bar, so collapsing it
	   further would leave icons with no label and nothing gained. */
	.fsd-appshell, .fsd-appshell.is-collapsed { flex-direction: column; min-height: 0; }
	.fsd-appshell.is-collapsed .fsd-appnav { width: auto; }
	/* Unpinned here: stacked above the content as a horizontal bar, a rail
	   fixed to the viewport would eat most of a phone screen. */
	.fsd-appnav {
		width: auto;
		flex-direction: row; flex-wrap: wrap; align-items: center;
		padding: var(--s-4);
		position: static; height: auto; overflow: visible;
	}
	.fsd-appnav__label { display: none; }
	.fsd-appnav__list { flex-direction: row; flex-wrap: wrap; flex: 1 1 auto; border-top: 0; padding-top: 0; }
	.fsd-appnav__item { padding: var(--s-2) var(--s-3); font-size: var(--t-sm); }
	.fsd-appshell.is-collapsed .fsd-appnav__item-text,
	.fsd-appshell.is-collapsed .fsd-appnav__soon { display: inline; }
	.fsd-appshell.is-collapsed .fsd-appnav__item { justify-content: flex-start; padding-left: var(--s-3); padding-right: var(--s-3); }
	.fsd-appnav__promo { display: none; }
}

/* Leaderboard hub: which board to look at. */
.fsd-lbpick { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s-3); margin: var(--s-4) 0 var(--s-6); }
.fsd-lbpick__i {
	display: block; padding: var(--s-3) var(--s-4);
	border: 1px solid var(--line); border-radius: var(--r);
	background: var(--bg-raised); text-decoration: none; color: inherit;
}
.fsd-lbpick__i:hover { border-color: var(--accent); }
.fsd-lbpick__i.is-on { border-color: var(--accent); background: var(--accent-bg); }
.fsd-lbpick__t { display: block; font-weight: 650; font-size: var(--t-sm); }
.fsd-lbpick__m { display: block; font-size: var(--t-xs); color: var(--ink-faint); margin-top: 2px; }

/* Leaderboard. */
.fsd-leaderboard { list-style: none; margin: var(--s-4) 0; padding: 0; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.fsd-leaderboard li {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line-soft);
	font-size: var(--t-sm);
}
.fsd-leaderboard li:last-child { border-bottom: 0; }
.fsd-leaderboard li.is-you { background: var(--accent-bg); font-weight: 660; }
.fsd-leaderboard__rank { flex: none; width: 22px; text-align: center; color: var(--ink-faint); font-weight: 660; }
.fsd-leaderboard__name { flex: 1; }
.fsd-leaderboard__score { flex: none; font-weight: 660; }

/* Leaderboard-visibility toggle — a plain checkbox styled as a switch. */
.fsd-toggle { display: inline-flex; align-items: center; gap: var(--s-2); font-size: var(--t-sm); cursor: pointer; }
.fsd-toggle input { accent-color: var(--accent); width: 16px; height: 16px; }

/* --------------------------------------------------------------- glossary */

.fsd-search { display: flex; gap: var(--s-2); margin-bottom: var(--s-4); }
.fsd-search__field { flex: 1; }
.fsd-search input { width: 100%; }

.fsd-cats { display: flex; flex-wrap: wrap; gap: var(--s-1); margin-bottom: var(--s-6); }
.fsd-cat {
	font-size: var(--t-sm); font-weight: 560; text-decoration: none; color: var(--ink-soft);
	border: 1px solid var(--line); border-radius: var(--r-full); padding: .3rem .75rem;
	transition: border-color .14s ease, color .14s ease, background .14s ease;
}
.fsd-cat:hover { border-color: var(--accent); color: var(--accent); }
.fsd-cat.is-active { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }

/* Topic tests: horizontal exam tabs (.fsd-cats above) + a vertical subject
   sidebar within the active exam, jumping to that subject further down
   the same page rather than reloading -- there are only a handful of
   subjects per exam, so a full page is short enough that a jump beats a
   second layer of filtering. Both bars stay on screen while scrolling;
   the offsets are read from the real rendered nav height in ui.js
   (stickyOffsets()) since the nav wraps to a second row below a certain
   width and a hardcoded top would either gap or overlap it. */
.fsd-cats--sticky {
	position: sticky; top: var(--sticky-nav-h, 64px); z-index: 40;
	background: var(--bg); padding: var(--s-4) 0; margin-bottom: var(--s-6);
	border-bottom: 1px solid var(--line);
}

.fsd-topiclayout { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: var(--s-8); align-items: start; }
.fsd-topicnav {
	position: sticky;
	top: calc(var(--sticky-nav-h, 64px) + var(--sticky-tabs-h, 64px) + var(--s-4));
	display: flex; flex-direction: column; gap: var(--s-2);
	max-height: calc(100vh - var(--sticky-nav-h, 64px) - var(--sticky-tabs-h, 64px) - var(--s-6));
	overflow-y: auto;
}
.fsd-topicnav__btn {
	display: flex; align-items: center; justify-content: space-between; gap: var(--s-2);
	font-size: var(--t-sm); font-weight: 620; color: var(--ink-soft); text-decoration: none;
	padding: .6rem .85rem; border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--bg-raised);
	transition: border-color .14s ease, color .14s ease, background .14s ease;
}
.fsd-topicnav__btn span {
	font-family: var(--mono); font-size: var(--t-xs); color: var(--ink-faint);
	background: var(--bg-sunken); border-radius: var(--r-full); padding: .05rem .4rem;
}
.fsd-topicnav__btn:hover { border-color: var(--accent); color: var(--accent); }
.fsd-topicmain .fsd-h2:not(:first-child) { margin-top: var(--s-8); }

@media (max-width: 760px) {
	.fsd-topiclayout { grid-template-columns: 1fr; }
	.fsd-topicnav {
		position: static; flex-direction: row; flex-wrap: wrap; gap: var(--s-2);
		max-height: none; overflow-y: visible;
		border-bottom: 1px solid var(--line);
		padding-bottom: var(--s-3); margin-bottom: var(--s-2);
	}
	.fsd-topicnav__btn { flex: 1 1 auto; }
}

.fsd-glossary { display: grid; gap: var(--s-3); }
/* display:block is a no-op on the <article> the listing page uses, and is
   what makes the related-terms cards on a term page work as <a> instead. */
.fsd-gterm { display: block; background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--r); padding: var(--s-5); color: inherit; text-decoration: none; }
.fsd-gterm header { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4); flex-wrap: wrap; margin-bottom: var(--s-2); }
.fsd-gterm h2 { font-size: var(--t-md); font-weight: 680; letter-spacing: -.012em; margin: 0; }
.fsd-gterm__cat { font-size: var(--t-xs); font-weight: 620; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); }
.fsd-gterm > p { font-size: var(--t-base); margin-bottom: var(--s-3); }
.fsd-gterm__see { font-size: var(--t-sm); color: var(--ink-faint); margin-top: var(--s-3); }
.fsd-term__abbr {
	font-family: var(--mono); font-size: var(--t-xs); font-weight: 500;
	background: var(--bg-sunken); border: 1px solid var(--line); border-radius: var(--r-sm);
	padding: .05rem .35rem; margin-left: var(--s-1); color: var(--ink-faint); vertical-align: 1px;
}

.fsd-cta { margin-top: var(--s-10); padding: var(--s-8) var(--s-5); background: var(--bg-sunken); border-radius: var(--r-lg); text-align: center; }
.fsd-cta .fsd-lede { margin-inline: auto; margin-bottom: var(--s-5); }

/* ------------------------------------------------------- why / term panel */

.fsd-why { background: var(--accent-bg); border-left: 2px solid var(--accent); border-radius: 0 var(--r-sm) var(--r-sm) 0; padding: var(--s-3) var(--s-4); margin-top: var(--s-4); }
.fsd-why--tight { margin: 0; background: var(--bg-sunken); border-left-color: var(--line); }
.fsd-why__label { font-size: var(--t-xs); font-weight: 680; letter-spacing: .09em; text-transform: uppercase; color: var(--accent); margin-bottom: var(--s-1); }
.fsd-why--tight .fsd-why__label { color: var(--ink-faint); }
.fsd-why p { font-size: var(--t-base); }

.fsd-terms { margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px dashed var(--line); }
.fsd-terms__label { font-size: var(--t-xs); font-weight: 650; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: var(--s-2); }
.fsd-term { background: var(--bg-sunken); border: 1px solid var(--line-soft); border-radius: var(--r-sm); margin-bottom: var(--s-1); }
.fsd-term summary { cursor: pointer; padding: var(--s-2) var(--s-3); font-size: var(--t-base); font-weight: 600; }
.fsd-term summary::marker { color: var(--accent); }
.fsd-term p { margin: 0 var(--s-3) var(--s-2); font-size: var(--t-sm); }
.fsd-term__matters { color: var(--ink-soft); }

/* --------------------------------------------------------- attempt review */

.fsd-filters { display: flex; flex-wrap: wrap; gap: var(--s-1); margin-bottom: var(--s-4); }
.fsd-filter {
	font: inherit; font-size: var(--t-sm); font-weight: 600; cursor: pointer;
	color: var(--ink-soft); background: var(--bg); border: 1px solid var(--line);
	border-radius: var(--r-full); padding: .35rem .85rem;
	transition: border-color .14s ease, background .14s ease, color .14s ease;
}
.fsd-filter span { opacity: .6; margin-left: var(--s-1); }
.fsd-filter:hover { border-color: var(--ink-faint); color: var(--ink); }
.fsd-filter.is-active { background: var(--ink); border-color: var(--ink); color: var(--on-ink); }

/*
 * .fsd-review__item is the client-rendered twin of .fsd-rev — the same
 * per-question review card, built in JS by runner.js's post-submit screen
 * instead of PHP, for the same result (attempt.php has both a server render
 * and this client one, and they had drifted: .fsd-rev got a full card
 * treatment, .fsd-review__item got none, so consecutive questions ran
 * straight into each other with nothing but a why-box's own background to
 * hint where one ended and the next began.
 */
.fsd-rev, .fsd-review__item { background: var(--bg-raised); border: 1px solid var(--line); border-left-width: 3px; border-radius: var(--r); padding: var(--s-5); margin-bottom: var(--s-3); }
.fsd-rev.is-correct, .fsd-review__item.is-correct { border-left-color: var(--ok); }
.fsd-rev.is-wrong, .fsd-review__item.is-wrong     { border-left-color: var(--bad); }
.fsd-rev.is-skipped, .fsd-review__item.is-skipped { border-left-color: var(--n-300); }
.fsd-rev__head { display: flex; flex-wrap: wrap; gap: var(--s-1); margin-bottom: var(--s-3); }
.fsd-rev__q { font-size: var(--t-base); margin-bottom: var(--s-4); }
.fsd-rev__opts { list-style: none; display: grid; gap: var(--s-1); margin: 0; padding: 0; }
.fsd-rev__opt { font-size: var(--t-base); border: 1px solid var(--line); border-radius: var(--r-sm); padding: var(--s-2) var(--s-3); }
.fsd-rev__opt em { font-size: var(--t-xs); font-style: normal; font-weight: 680; letter-spacing: .05em; text-transform: uppercase; margin-left: var(--s-2); }
.fsd-rev__opt.is-answer { background: var(--ok-bg); border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.fsd-rev__opt.is-answer em { color: var(--ok); }
.fsd-rev__opt.is-chosen-wrong { background: var(--bad-bg); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }
.fsd-rev__opt.is-chosen-wrong em { color: var(--bad); }
.fsd-rev__nat { font-size: var(--t-base); }
.fsd-review__given { color: var(--bad); font-weight: 600; }

.fsd-chip {
	font-size: var(--t-xs); font-weight: 620; letter-spacing: .05em; text-transform: uppercase;
	background: var(--bg-sunken); border: 1px solid var(--line); color: var(--ink-faint);
	border-radius: var(--r-full); padding: .15rem .5rem;
}
.fsd-chip--correct { background: var(--ok-bg); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 35%, transparent); }
.fsd-chip--wrong   { background: var(--bad-bg); color: var(--bad); border-color: color-mix(in srgb, var(--bad) 35%, transparent); }
/* Keyed to the actual sign of the marks awarded, not the result label —
   a wrong MSQ/NAT answer scores 0, not negative, so it must not read red
   the same way a negative-marked wrong MCQ does. */
.fsd-chip--pos { background: var(--ok-bg); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 35%, transparent); font-weight: 700; }
.fsd-chip--neg { background: var(--bad-bg); color: var(--bad); border-color: color-mix(in srgb, var(--bad) 35%, transparent); font-weight: 700; }
/* The question number is what a student actually scans a review list by —
   it was one plain grey pill among type/marks/awarded chips of the exact
   same weight, so it never stood out as the thing to look at first. */
.fsd-chip--qnum { background: var(--accent); color: var(--on-accent); border-color: var(--accent); font-weight: 700; }

/* ------------------------------------------------------------ exam runner */

.fsd-runner { position: fixed; inset: 0; z-index: 9999; display: flex; flex-direction: column; background: var(--bg); }
.fsd-runner__bar { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: var(--s-4); padding: var(--s-2) var(--s-4); background: var(--bg-sunken); border-bottom: 1px solid var(--line); }
.fsd-runner__title { font-size: var(--t-base); font-weight: 650; letter-spacing: -.012em; }
.fsd-timer {
	font-family: var(--mono); font-size: var(--t-lg); font-weight: 600; letter-spacing: .02em;
	padding: .3rem .7rem; border-radius: var(--r-sm);
	background: var(--ok-bg); color: var(--ok); border: 1px solid currentColor;
}
.fsd-timer.is-warn { background: var(--warn-bg); color: var(--warn); }
.fsd-timer.is-danger { background: var(--bad-bg); color: var(--bad); }

.fsd-runner__body { flex: 1; display: flex; overflow: hidden; }
.fsd-runner__main { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
.fsd-runner__q { flex: 1; overflow-y: auto; padding: var(--s-5) var(--s-6); }
.fsd-runner__foot { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); flex-wrap: wrap; padding: var(--s-3) var(--s-5); background: var(--bg-sunken); border-top: 1px solid var(--line); }

.fsd-tabs { flex: 0 0 auto; display: flex; gap: 2px; overflow-x: auto; padding: 0 var(--s-4); background: var(--bg); border-bottom: 1px solid var(--line); scrollbar-width: thin; }
.fsd-tab {
	font: inherit; font-size: var(--t-xs); font-weight: 620; letter-spacing: .05em; text-transform: uppercase;
	white-space: nowrap; cursor: pointer; color: var(--ink-faint);
	background: none; border: 0; border-bottom: 2px solid transparent; padding: var(--s-3) var(--s-3);
}
.fsd-tab:hover { color: var(--ink); }
.fsd-tab.is-active { color: var(--accent); border-bottom-color: var(--accent); }

.fsd-q__meta { display: flex; flex-wrap: wrap; gap: var(--s-1); margin-bottom: var(--s-4); }
.fsd-q__text { font-size: var(--t-md); line-height: 1.6; margin-bottom: var(--s-5); white-space: pre-wrap; max-width: 68ch; }

/* A handful of GATE questions turn on a diagram/structure that has no text
   equivalent — these render alongside the question or its option, at a size
   that reads clearly without dominating the page. */
.fsd-q__img { display: block; max-width: 100%; width: auto; max-height: 360px; margin: 0 0 var(--s-5); border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff; }
.fsd-opt__img { display: block; max-width: 100%; width: auto; max-height: 140px; margin-top: var(--s-2); border: 1px solid var(--line-soft); border-radius: var(--r-sm); background: #fff; }
/* A worked explanation that turns on real notation (fractions, subscripts,
   multi-step algebra) carries a cropped image of the derivation alongside
   the prose — same treatment as .fsd-q__img, sat under the explanation text. */
.fsd-why__img { display: block; max-width: 100%; width: auto; max-height: 360px; margin-top: var(--s-3); border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff; }

.fsd-opts { display: grid; gap: var(--s-2); max-width: 68ch; }
.fsd-opt {
	display: flex; align-items: flex-start; gap: var(--s-3);
	padding: var(--s-3) var(--s-4); cursor: pointer;
	background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--r-sm);
	transition: border-color .14s ease, background .14s ease;
}
.fsd-opt:hover { border-color: var(--accent); }
.fsd-opt.is-picked { border-color: var(--accent); background: var(--accent-bg); }
.fsd-opt input { flex: 0 0 auto; margin-top: .3rem; accent-color: var(--accent); }
.fsd-opt__letter { flex: 0 0 auto; font-weight: 680; }
.fsd-nat { width: 260px; max-width: 100%; font-size: var(--t-md); }

.fsd-palette { flex: 0 0 264px; display: flex; flex-direction: column; overflow: hidden; background: var(--bg-sunken); border-left: 1px solid var(--line); }
.fsd-palette__head { padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line); font-size: var(--t-base); }
.fsd-palette__grid { flex: 1; overflow-y: auto; display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--s-1); align-content: start; padding: var(--s-4); }
.fsd-pal {
	aspect-ratio: 1; font: inherit; font-size: var(--t-sm); font-weight: 640; cursor: pointer;
	color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-sm);
	transition: transform .1s ease;
}
.fsd-pal:hover { transform: scale(1.06); }
.fsd-pal.is-answered { background: var(--ok); border-color: var(--ok); color: var(--on-accent); }
.fsd-pal.is-review { background: var(--n-600); border-color: var(--n-600); color: var(--n-0); }
/*
 * Answered + marked is its own state, not just "whichever colour applies
 * second". A dotted amber corner keeps it identifiable by shape as well as
 * colour, per the no-colour-alone accessibility rule.
 */
.fsd-pal.is-answered.is-review { background: var(--ok); border-color: var(--amber); border-width: 2px; position: relative; }
.fsd-pal.is-answered.is-review::after {
	content: ""; position: absolute; top: -3px; right: -3px;
	width: 8px; height: 8px; border-radius: 50%;
	background: var(--amber); border: 1.5px solid var(--bg-sunken);
}
.fsd-pal.is-current { outline: 2px solid var(--accent); outline-offset: 1px; }
.fsd-legend { display: grid; gap: var(--s-1); padding: var(--s-3) var(--s-4); border-top: 1px solid var(--line); font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: var(--s-1); vertical-align: -1px; }

/* --------------------------------------------------------------- submit modal */

.fsd-modal-scrim {
	position: fixed; inset: 0; z-index: 10000;
	display: flex; align-items: center; justify-content: center;
	padding: var(--s-4);
	background: rgba(6,10,15,.5);
	backdrop-filter: blur(2px);
	animation: fsd-fade .16s ease-out;
}
.fsd-modal {
	width: 100%; max-width: 420px;
	background: var(--bg-raised); border: 1px solid var(--line);
	border-radius: var(--r-lg); box-shadow: var(--shadow-3);
	padding: var(--s-6);
	animation: fsd-modal-in .18s cubic-bezier(.22,.61,.36,1);
}
.fsd-modal h3 { font-size: var(--t-lg); font-weight: 660; letter-spacing: -.014em; margin-bottom: var(--s-2); }
.fsd-modal p { color: var(--ink-soft); margin-bottom: var(--s-4); }
.fsd-modal__stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-2); margin-bottom: var(--s-5); }
.fsd-modal__stat { text-align: center; padding: var(--s-3) var(--s-2); background: var(--bg-sunken); border-radius: var(--r-sm); }
.fsd-modal__stat b { display: block; font-size: var(--t-lg); font-weight: 680; }
.fsd-modal__stat span { font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-modal__actions { display: flex; flex-direction: column; gap: var(--s-2); }
.fsd-modal__actions .fsd-btn { width: 100%; }

@keyframes fsd-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes fsd-modal-in { from { opacity: 0; transform: translateY(8px) scale(.98); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
	.fsd-modal-scrim, .fsd-modal { animation: none; }
}

/* ----------------------------------------------------------------- mobile */

@media (max-width: 900px) {
	.fsd-split { grid-template-columns: 1fr; gap: var(--s-6); }
	.fsd-split__side { position: static; }
}

@media (max-width: 860px) {
	.fsd-runner__body { position: relative; }

	/*
	 * Question palette becomes a slide-in drawer.
	 *
	 * The offsets are plain pixels on purpose. Written as
	 * `right: calc(-1 * min(280px, 82vw))` the closed value will not resolve
	 * against `right: 0`, so the drawer silently refuses to open — it stays
	 * off-screen with the class applied and no error anywhere.
	 *
	 * An absolutely positioned flex child also has no width of its own, hence
	 * the explicit width rather than relying on flex-basis.
	 */
	.fsd-palette {
		position: absolute;
		inset-block: 0;
		width: 280px;
		right: -280px;
		z-index: 20;
		flex: none;
		transition: right .22s cubic-bezier(.22,.61,.36,1);
		box-shadow: var(--shadow-3);
	}
	.fsd-palette.is-open { right: 0; }

	/* Dim the paper behind, and give a tap target for closing. */
	.fsd-palette.is-open::before {
		content: "";
		position: fixed;
		inset: 0;
		right: 280px;
		background: rgba(0,0,0,.28);
		z-index: -1;
	}
}

/* Very narrow phones: keep some of the question visible beside the drawer. */
@media (max-width: 340px) {
	.fsd-palette { width: 82vw; right: -82vw; }
	.fsd-palette.is-open { right: 0; }
	.fsd-palette.is-open::before { right: 82vw; }
}

@media (min-width: 861px) { .fsd-palette__toggle { display: none; } }

@media (max-width: 600px) {
	.fsd-wrap { padding: var(--s-6) var(--s-4) var(--s-8); }
	.fsd-nav { padding: var(--s-3) var(--s-4); }
	.fsd-hero { padding: var(--s-8) 0 var(--s-6); }
	.fsd-hero__stats { gap: var(--s-5); }
	.fsd-runner__q { padding: var(--s-4); }
	.fsd-card, .fsd-panel { padding: var(--s-4); }
}

@media (prefers-reduced-motion: reduce) {
	.fsd-scope *, .fsd-scope *::before, .fsd-scope *::after {
		transition-duration: .01ms !important;
		animation-duration: .01ms !important;
	}
}

@media print {
	.fsd-nav, .fsd-foot, .fsd-filters, .fsd-btn { display: none !important; }
	.fsd-rev { break-inside: avoid; border-left-width: 3px; }
}

/* ==========================================================================
   Motion.

   The reveal class is applied by JS, never by CSS alone — so if the script
   fails to run, content is visible rather than stranded at opacity 0.
   ========================================================================== */

.fsd-will-reveal {
	opacity: 0;
	transform: translateY(10px);
	transition: opacity .5s cubic-bezier(.22,.61,.36,1) var(--reveal-delay, 0ms),
	            transform .5s cubic-bezier(.22,.61,.36,1) var(--reveal-delay, 0ms);
}
.fsd-will-reveal.is-revealed { opacity: 1; transform: none; }

.fsd-bar > i.is-filling { transition: width .8s cubic-bezier(.22,.61,.36,1); }

.fsd-nav { transition: box-shadow .2s ease, border-color .2s ease; }
.fsd-nav.is-stuck { box-shadow: var(--shadow-2); }

/* Lift on hover, settle on press — makes cards feel like objects. */
.fsd-card, .fsd-exam, .fsd-gterm {
	transition: border-color .16s ease, box-shadow .22s cubic-bezier(.22,.61,.36,1),
	            transform .22s cubic-bezier(.22,.61,.36,1);
}
.fsd-card:hover, a.fsd-exam:hover { transform: translateY(-2px); }
.fsd-card:active, a.fsd-exam:active { transform: translateY(0); transition-duration: .05s; }
.fsd-gterm:hover { border-color: var(--n-300); box-shadow: var(--shadow-1); }
@media (prefers-color-scheme: dark) { .fsd-gterm:hover { border-color: var(--n-600); } }

/* Underline grows from the centre rather than snapping in. */
.fsd-tab { position: relative; border-bottom-color: transparent; }
.fsd-tab::after {
	content: ""; position: absolute; left: 50%; right: 50%; bottom: -1px; height: 2px;
	background: var(--accent); transition: left .22s ease, right .22s ease;
}
.fsd-tab.is-active::after { left: 0; right: 0; }

/* The palette square you are on gets a gentle pulse so it is findable. */
@keyframes fsd-pulse {
	0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 45%, transparent); }
	50%      { box-shadow: 0 0 0 5px color-mix(in srgb, var(--accent) 0%, transparent); }
}
.fsd-pal.is-current { animation: fsd-pulse 2.2s ease-out infinite; }

/* Time running out should be impossible to miss. */
@keyframes fsd-blink { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
.fsd-timer.is-danger { animation: fsd-blink 1s steps(2, start) infinite; }

.fsd-btn { position: relative; overflow: hidden; }
.fsd-opt { transition: border-color .14s ease, background .14s ease, transform .12s ease; }
.fsd-opt:active { transform: scale(.995); }
.fsd-filter, .fsd-cat { transition: border-color .14s ease, background .14s ease, color .14s ease, transform .12s ease; }
.fsd-filter:active, .fsd-cat:active { transform: scale(.97); }

.fsd-scope details.fsd-term > summary { transition: color .14s ease; }
.fsd-scope details.fsd-term[open] > summary { color: var(--accent); }

/* Honour the user's setting — and neutralise every animation above. */
@media (prefers-reduced-motion: reduce) {
	.fsd-will-reveal { opacity: 1 !important; transform: none !important; }
	.fsd-pal.is-current, .fsd-timer.is-danger { animation: none !important; }
	.fsd-card:hover, a.fsd-exam:hover { transform: none !important; }
}

/* ==========================================================================
   Modern surface treatment.

   Layered on top of the base rules so the structure is untouched — this is
   the visual language, not the layout.
   ========================================================================== */

/* Hero gets a soft wash of accent instead of flat grey, and much more air. */
.fsd-hero {
	background: var(--tint), var(--bg);
	border-bottom: 1px solid var(--line);
	padding: var(--s-10) 0 var(--s-8);
}
.fsd-hero__h1 { font-weight: 760; letter-spacing: -.035em; }
.fsd-hero .fsd-lede { font-size: 1.15rem; max-width: 56ch; }
.fsd-hero__stats strong { font-size: var(--t-xl); font-weight: 740; }

/* Headings carry more weight and tighter tracking — the single biggest
   contributor to a page feeling current. */
.fsd-h1 { font-weight: 720; letter-spacing: -.028em; }
.fsd-h2 { font-weight: 700; letter-spacing: -.02em; }
.fsd-card__title, .fsd-gterm h2, .fsd-exam h3 { font-weight: 680; letter-spacing: -.018em; }

/* Buttons: a stamped form control, not a bubble. Corners are the site's
   sharp --r-sm, ink-solid fill, a hard 1px press instead of a soft glow. */
.fsd-btn { border-radius: var(--r-sm); }
.fsd-btn--primary { box-shadow: var(--shadow-1); }
.fsd-btn--primary:hover { box-shadow: var(--shadow-2); }
.fsd-btn--ghost { background: var(--bg-raised); border-width: 1.5px; }
.fsd-btn--ghost:hover { background: var(--bg-sunken); border-color: var(--ink); }
.fsd-nav__cta { border-radius: var(--r-sm); }

/* Cards: square-cornered, like a printed form on a table. */
.fsd-card, .fsd-panel, .fsd-buybox, .fsd-gterm, .fsd-exam, .fsd-step, .fsd-stat, .fsd-rev {
	border-radius: var(--r-sm);
}
.fsd-card, .fsd-buybox, .fsd-panel { border-radius: var(--r); }
.fsd-card:hover { box-shadow: var(--shadow-2); border-color: var(--n-400); }
a.fsd-exam:hover { box-shadow: var(--shadow-2); }

/* A plain outlined tag — no rotation, no stamp gimmick, just a label. */
.fsd-card__badge {
	background: transparent; color: var(--accent);
	border: 1px solid currentColor; border-radius: var(--r-sm);
}
.fsd-card__badge--free { color: var(--ok); }
.fsd-price { font-weight: 700; letter-spacing: -.01em; }
.fsd-buybox { background: var(--tint), var(--bg-raised); }
.fsd-buybox__price { font-weight: 700; letter-spacing: -.015em; }

/* Chips and filter pills keep a rounded shape — they behave like tags a
   user picks, which is a different job from a stamped mark of fact. */
.fsd-chip, .fsd-tag, .fsd-sections li, .fsd-pay-methods span, .fsd-term__abbr {
	border-radius: var(--r-full);
}
.fsd-cat, .fsd-filter { border-radius: var(--r-full); }

/* Inputs: sharp corners, a hard ink-blue ring on focus rather than a soft glow. */
.fsd-field input, .fsd-search input, .fsd-nat {
	border-radius: var(--r-sm);
	padding: .78rem .95rem;
}
.fsd-field input:focus, .fsd-search input:focus, .fsd-nat:focus {
	box-shadow: 0 0 0 3px var(--accent-bg);
}

/* Tables sit inside a rounded card rather than a plain box. */
.fsd-tablewrap { border-radius: var(--r); background: var(--bg-raised); }

/* Answer options in the runner — bigger targets, softer shape. */
.fsd-opt { border-radius: var(--r-sm); padding: .85rem 1rem; }
.fsd-pal { border-radius: var(--r-sm); }

/* Result hero: the number is the hero, so let it breathe. */
.fsd-result__hero { background: var(--tint), var(--bg-sunken); border-radius: var(--r-lg); }
.fsd-result__score { font-weight: 780; letter-spacing: -.04em; }
.fsd-rankbar { border-radius: var(--r); }
.fsd-rankbar strong { font-weight: 740; }

/* Notices and coaching read as cards, not warning stripes. */
.fsd-notice, .fsd-nudges { border-radius: var(--r); }
.fsd-why { border-radius: var(--r-sm); border-left-width: 3px; }
.fsd-empty { border-radius: var(--r-lg); }
.fsd-cta { border-radius: var(--r-lg); background: var(--tint), var(--bg-sunken); }

/* Legend swatches were hardcoded hex in the JS, so they ignored dark mode and
   drifted from the palette colours they were meant to match. */
.fsd-legend__ok     { background: var(--ok); }
.fsd-legend__review { background: var(--n-500); }
.fsd-legend__none   { background: var(--bg); border: 1px solid var(--line); }
.fsd-pal.is-review  { background: var(--n-500); border-color: var(--n-500); color: var(--n-0); }

/* --------------------------------------------------------- section picker */

.fsd-pick { border: 1px solid var(--line); border-radius: var(--r); padding: var(--s-5); margin-bottom: var(--s-5); background: var(--bg-raised); }
.fsd-pick__label { font-size: var(--t-xs); font-weight: 650; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint); margin-bottom: var(--s-2); }
.fsd-pick__count { margin-left: var(--s-2); letter-spacing: 0; text-transform: none; font-weight: 600; color: var(--bad); }
.fsd-pick__count.is-done { color: var(--ok); }
/* Had no layout of its own — the compulsory chips relied solely on
   .fsd-chip--fixed's margin-right, with no wrap-gap for a longer list,
   unlike .fsd-pick__grid right below it. Matches that sibling's pattern. */
.fsd-pick__fixed { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.fsd-chip--fixed { background: var(--accent-bg); color: var(--accent); border-color: color-mix(in srgb, var(--accent) 30%, transparent); margin-right: var(--s-1); }

.fsd-pick__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--s-2); }
.fsd-pick__opt {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4); cursor: pointer;
	border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg);
	font-size: var(--t-base); transition: border-color .14s ease, background .14s ease, opacity .14s ease;
}
.fsd-pick__opt:hover { border-color: var(--accent); }
.fsd-pick__opt.is-picked { border-color: var(--accent); background: var(--accent-bg); font-weight: 600; }
.fsd-pick__opt.is-disabled { opacity: .45; cursor: not-allowed; }
.fsd-pick__opt input { accent-color: var(--accent); }
.fsd-pick__total { font-size: var(--t-base); color: var(--ink-soft); margin-top: var(--s-4); }

/* Shown when a question has no written explanation yet — the absence is stated
   rather than leaving a blank the student has to interpret. */
.fsd-why__none {
	font-size: var(--t-sm); color: var(--ink-faint);
	margin-top: var(--s-3); font-style: italic;
}

/* ==========================================================================
   Type roles — 2026 redesign.

   Three faces, three jobs. Display (Barlow Condensed) is for anything that
   is a label or a title — it reads like a stamp, not a sentence. Read
   (Source Serif 4) is for the paragraphs a student is actually studying
   from. Mono (IBM Plex Mono) is for every number on the site, so a column
   of marks or a countdown timer holds its digits in a straight line.
   ========================================================================== */

.fsd-h1, .fsd-h2, .fsd-hero__h1, .fsd-land-hero__h1,
.fsd-eyebrow, .fsd-nav__brand, .fsd-nav__brand-text span,
.fsd-card__title, .fsd-card__exam, .fsd-examtile h3, .fsd-exam h3,
.fsd-gterm h2, .fsd-why__label, .fsd-nudges__label, .fsd-terms__label,
.fsd-pick__label, .fsd-fact__label, .fsd-stat__l,
.fsd-hero__stats span, .fsd-modal h3, .fsd-tab,
.fsd-table th, .fsd-mock__pal-label, .fsd-runner__title, .fsd-buybox__off,
.fsd-testlist__body h3, .fsd-step h3, .fsd-nudges__label, .fsd-tag,
.fsd-cat, .fsd-filter, .fsd-btn {
	font-family: var(--font-display);
}

.fsd-h1, .fsd-hero__h1, .fsd-land-hero__h1 { font-weight: 800; letter-spacing: -.008em; }
.fsd-h2 { font-weight: 700; letter-spacing: 0; }
.fsd-card__title, .fsd-gterm h2, .fsd-examtile h3, .fsd-exam h3,
.fsd-testlist__body h3, .fsd-step h3 { font-weight: 700; letter-spacing: 0; }
.fsd-eyebrow, .fsd-card__exam, .fsd-fact__label, .fsd-stat__l,
.fsd-hero__stats span, .fsd-why__label, .fsd-nudges__label,
.fsd-terms__label, .fsd-pick__label, .fsd-table th, .fsd-mock__pal-label,
.fsd-tag, .fsd-cat, .fsd-filter {
	font-weight: 700; letter-spacing: .07em;
}
.fsd-nav__brand { font-weight: 800; letter-spacing: .01em; text-transform: uppercase; font-size: 1.2rem; }
.fsd-nav__brand-text span { font-weight: 600; letter-spacing: .1em; }
.fsd-tab { font-weight: 700; letter-spacing: .04em; }
.fsd-btn { font-weight: 700; letter-spacing: .02em; text-transform: uppercase; font-size: .85rem; }
.fsd-btn--lg { font-size: .95rem; }
.fsd-btn--sm { font-size: .74rem; }

.fsd-lede, .fsd-land-hero .fsd-lede, .fsd-card__blurb, .fsd-gterm > p, .fsd-why p,
.fsd-q__text, .fsd-rev__q, .fsd-mock__qtext, .fsd-buybox__facts,
.fsd-testlist__body p, .fsd-exam p, .fsd-examtile p, .fsd-step p,
.fsd-cta .fsd-lede, .fsd-term p {
	font-family: var(--font-read);
}
.fsd-q__text, .fsd-rev__q { font-size: 1.08rem; line-height: 1.62; }

.fsd-fact__value, .fsd-price, .fsd-stat__v, .fsd-hero__stats strong,
.fsd-result__score, .fsd-result__of, .fsd-score, .fsd-rankbar strong,
.fsd-buybox__price, .fsd-paywall__price, .fsd-modal__stat b, .fsd-pal,
.fsd-testlist__n, .fsd-price small {
	font-family: var(--mono); font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Exam facts: Questions / Duration / Marks, on every test card. Quiet by
   design — a single hairline, tabular figures, no framing beyond that. The
   information does the work; the panel doesn't need to announce itself.
   ========================================================================== */

.fsd-facts {
	display: flex; flex-wrap: wrap; gap: 0;
	padding: var(--s-3) 0; margin-bottom: var(--s-4);
	border-block: 1px solid var(--line);
}
.fsd-facts > div {
	flex: 1 1 100px; padding: 0 var(--s-4);
	border-right: 1px solid var(--line);
}
.fsd-facts > div:first-child { padding-left: 0; }
.fsd-facts > div:last-child { border-right: 0; }
.fsd-fact__value { font-size: var(--t-lg); font-weight: 700; letter-spacing: 0; }
.fsd-fact__label { margin-top: 3px; }

/* ==========================================================================
   Landing page — scoped repaint.

   Forest green is now the site's accent everywhere (see the root token
   block above), so the landing page no longer needs its own colour
   override. The one thing that stays scoped here is brightness: the
   landing page is the brand moment and stays forced-light regardless of
   OS preference, while every other page still follows the system.
   ========================================================================== */

/*
 * The landing page is the brand moment — bright paper, matching the rest of
 * the redesign — so it stays light even when the visitor's OS prefers dark.
 * Every other page still follows the system, this one just doesn't.
 * Declaring these directly on the element beats the inherited :root values
 * from the dark-mode media query above, regardless of media-query order.
 */
body.fsd-landing {
	--bg:        #ffffff;
	--bg-sunken: #f7f6f4;
	--bg-raised: #ffffff;
	--ink:       #16140f;
	--ink-soft:  #4c463a;
	--ink-faint: #6e6857;
	--line:      #dad8d3;
	--line-soft: #ececea;
	/* Every colour role, not just neutrals — pinning bg/ink alone left
	   accent and state colours free to fall through to the dark-mode
	   values whenever the visitor's OS preferred dark, so a light page
	   could end up with a washed-out dark-mode colour on it. */
	--accent:    #7a1f2b;
	--accent-hi: #5c1520;
	--accent-bg: #f1e2df;
	--ok:        #3f6b3a;
	--ok-bg:     #e6ede2;
	--bad:       #a83a2a;
	--bad-bg:    #f4e0dc;
	--warn:      #8a5a12;
	--warn-bg:   #f1e5d1;
	--amber:     #b98a3e;
	--amber-hi:  #97702f;
	--on-accent: #ffffff;
	--on-ink:    #ffffff;
	--tint:      linear-gradient(180deg, #f1e2df 0%, transparent 72%);
	--shadow-1: 0 1px 2px rgba(22,20,15,.06);
	--shadow-2: 0 1px 3px rgba(22,20,15,.07), 0 8px 20px -8px rgba(22,20,15,.14);
	--shadow-3: 0 2px 6px rgba(22,20,15,.08), 0 18px 44px -12px rgba(22,20,15,.22);
}
/*
 * ...but an EXPLICIT dark choice still wins here.
 *
 * The pin above exists so the visitor's OS preference does not flip the
 * brand moment. A visitor who reaches up and presses the toggle is not
 * expressing an OS preference — they are asking this page to be dark, and
 * on the landing page the toggle is right there in the header, so pinning
 * light made the control look broken on the one page most people would
 * first press it.
 *
 * System preference: still ignored here. Deliberate choice: honoured.
 */
:root[data-theme="dark"] body.fsd-landing {
	--bg:        #14120f;
	--bg-sunken: #1d1a16;
	--bg-raised: #1b1815;
	--ink:       #f3f1ec;
	--ink-soft:  #bdb7a9;
	--ink-faint: #928c7e;
	--line:      #34302a;
	--line-soft: #262320;
	--accent:    #d98a8f;
	--accent-hi: #e8a5a9;
	--accent-bg: #2b1a1c;
	--ok:        #7fb173;
	--ok-bg:     #1b2419;
	--bad:       #e08a76;
	--bad-bg:    #2a1a15;
	--warn:      #d2a44f;
	--warn-bg:   #291f10;
	--amber:     #d2a44f;
	--amber-hi:  #e0b565;
	--on-accent: #1a0f11;
	--on-ink:    #14120f;
	--tint:      linear-gradient(180deg, #241618 0%, transparent 72%);
	--shadow-1: 0 1px 2px rgba(0,0,0,.4);
	--shadow-2: 0 1px 3px rgba(0,0,0,.45), 0 8px 20px -8px rgba(0,0,0,.6);
	--shadow-3: 0 2px 6px rgba(0,0,0,.5), 0 18px 44px -12px rgba(0,0,0,.7);
}

body.fsd-landing .fsd-nav__cta { background: var(--accent); color: var(--on-accent) !important; }
body.fsd-landing .fsd-nav__cta:hover { background: var(--accent-hi); }

/* ------------------------------------------------------------- land: hero */

.fsd-land-hero { padding: var(--s-10) 0 var(--s-8); overflow: clip; position: relative; }
.fsd-land-hero .fsd-wrap {
	padding-block: 0;
	display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
	/*
	 * "b" (the chip row + exam finder) used to share "mock"'s row too, so
	 * .fsd-mock's cell was the full "a"+"b" height while the card itself
	 * was only as tall as "a" — a ~400px blank strip below the card. "b b"
	 * moves the chip row/finder to their own full-width row beneath both
	 * columns instead, so .fsd-mock's cell now matches "a" alone.
	 */
	grid-template-areas: "facts facts" "a mock" "b b";
	row-gap: 0; column-gap: var(--s-8); align-items: start;
}
.fsd-land-hero__a    { grid-area: a; }
.fsd-land-hero__b    { grid-area: b; }
.fsd-land-hero .fsd-land-hero__facts { grid-area: facts; }
.fsd-land-hero__h1 {
	font-size: var(--t-3xl); font-weight: 780; line-height: 1.06;
	letter-spacing: -.03em; margin: var(--s-3) 0 var(--s-4);
}
.fsd-land-hero__h1 em { font-style: normal; color: var(--accent); }
.fsd-land-hero__cta { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-6); }
/* Each button grows to share the row rather than sitting at its own
   content width with a gap of bare column beside it. 160px basis so a
   wrap onto its own line still leaves it a sensible tap target, not a
   sliver, at the point flex-wrap kicks in on narrow columns. */
.fsd-land-hero__cta .fsd-btn { flex: 1 1 160px; }
.fsd-hero-microcopy { margin-top: var(--s-3); font-size: var(--t-sm); color: var(--ink-soft); }

/* Small trust-point row under the hero CTA — true, verifiable product
   facts (not stats), styled as quiet inline chips rather than a second
   loud badge row so it doesn't compete with .fsd-land-hero__facts. */
.fsd-trust-strip {
	display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4);
	list-style: none; margin: var(--s-4) 0 0; padding: 0;
}
.fsd-trust-strip li {
	display: inline-flex; align-items: center; gap: 6px;
	font-size: var(--t-xs); color: var(--ink-soft); font-weight: 600;
}
.fsd-trust-strip svg { flex: none; color: var(--accent); }

/* One line, not a stack — three quick facts read as a single credential,
   not three separate claims. Spans the full hero width (its own grid
   area, above both columns) since the text column alone isn't wide
   enough to hold all three on one line. overflow-x is a safety net for
   very narrow single-column widths, not the primary layout mechanism. */
.fsd-land-hero__facts {
	display: flex; flex-wrap: nowrap; align-items: center; gap: var(--s-3);
	margin-bottom: var(--s-6); overflow-x: auto; scrollbar-width: none;
}
.fsd-land-hero__facts::-webkit-scrollbar { display: none; }
.fsd-land-hero__facts div { display: flex; align-items: center; gap: var(--s-2); font-size: var(--t-sm); color: var(--ink-soft); white-space: nowrap; flex: none; }
.fsd-land-hero__facts svg { flex: none; color: var(--accent); }
.fsd-land-hero__facts div + div::before {
	content: ""; width: 3px; height: 3px; border-radius: 50%;
	background: var(--line); margin-right: var(--s-3); flex: none;
}

.fsd-land-hero__facts--tiles {
	gap: var(--s-5) var(--s-6);
	padding-top: var(--s-6); margin-top: var(--s-6);
	border-top: 1px solid var(--line);
}
/*
 * Direct-child combinator matters here: written as a bare descendant
 * selector this also matched .fsd-land-hero__facticon (itself a div,
 * nested one level deeper) and — at (0,1,1) — beat that rule's own
 * (0,1,0) specificity regardless of source order. The 30x30 icon box
 * inherited flex-grow and stretched to fill the row.
 */
.fsd-land-hero__facts--tiles > div {
	align-items: flex-start; gap: var(--s-3); flex: 1 1 130px;
}
.fsd-land-hero__facts--tiles span { line-height: 1.35; font-weight: 560; }
.fsd-land-hero__facticon {
	flex: none; width: 30px; height: 30px; border-radius: var(--r-sm);
	display: grid; place-items: center; background: var(--accent-bg);
}
.fsd-land-hero__facticon img { width: 16px; height: 16px; }

/* A believable product preview built from real markup, not a screenshot —
   the actual test interface, shrunk, so the promise on the landing page is
   never a picture of something that does not exist. */
.fsd-mock {
	background: var(--bg-raised); border: 1px solid var(--line);
	border-radius: var(--r-lg); box-shadow: var(--shadow-2);
	overflow: hidden;
}
.fsd-mock__bar {
	display: flex; align-items: center; justify-content: space-between;
	padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line);
	background: var(--bg-sunken); font-size: var(--t-xs); color: var(--ink-faint);
}
.fsd-mock__dots { display: flex; gap: 5px; }
.fsd-mock__dots span { width: 8px; height: 8px; border-radius: 50%; background: var(--line); }
.fsd-mock__body { display: grid; grid-template-columns: minmax(0,1fr) 168px; }
.fsd-mock__q { padding: var(--s-5); border-right: 1px solid var(--line); }
.fsd-mock__qmeta { display: flex; justify-content: space-between; font-size: var(--t-xs); color: var(--ink-faint); margin-bottom: var(--s-3); }
.fsd-mock__qtext { font-size: var(--t-sm); font-weight: 560; line-height: 1.5; margin-bottom: var(--s-4); }
.fsd-mock__opt {
	display: flex; align-items: center; gap: var(--s-2);
	padding: var(--s-2) var(--s-3); margin-bottom: var(--s-2);
	border: 1px solid var(--line); border-radius: var(--r-sm); font-size: var(--t-sm);
}
.fsd-mock__opt b {
	display: grid; place-items: center; flex: none;
	width: 20px; height: 20px; border-radius: 50%;
	border: 1px solid var(--n-300); font-size: var(--t-xs); font-weight: 620; color: var(--ink-faint);
}
.fsd-mock__opt.is-picked { border-color: var(--accent); background: var(--accent-bg); }
.fsd-mock__opt.is-picked b { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.fsd-mock__pal { padding: var(--s-4); }
.fsd-mock__pal-label { font-size: var(--t-xs); color: var(--ink-faint); margin-bottom: var(--s-2); }
.fsd-mock__grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 5px; }
.fsd-mock__cell {
	aspect-ratio: 1; border-radius: 5px; display: grid; place-items: center;
	font-size: 10px; font-weight: 620; color: var(--ink-faint); background: var(--bg-sunken);
}
.fsd-mock__cell.is-done { background: var(--accent); color: var(--on-accent); }
.fsd-mock__cell.is-marked { background: var(--amber); color: #3a2705; }
.fsd-mock__cell.is-now { outline: 2px solid var(--accent); outline-offset: 1px; }
.fsd-mock__legend { margin-top: var(--s-3); display: grid; gap: 5px; font-size: 10px; color: var(--ink-faint); }
.fsd-mock__legend span { display: flex; align-items: center; gap: 5px; }
.fsd-mock__legend i { width: 7px; height: 7px; border-radius: 50%; }

/* --------------------------------------------------------- land: exam grid */

.fsd-examtile-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
	gap: var(--s-4);
}
.fsd-examtile {
	--tile-bg: var(--accent-bg);
	--tile-fg: var(--accent);
	--tile-ring: var(--accent);
	position: relative;
	display: flex; flex-direction: column; gap: var(--s-3);
	padding: var(--s-5) var(--s-5) var(--s-4);
	border: 1px solid var(--line); border-radius: var(--r-lg);
	background: var(--bg-raised); text-decoration: none; color: inherit;
	overflow: hidden;
	transition: border-color .18s ease, box-shadow .22s ease, transform .22s cubic-bezier(.2,.7,.3,1);
}
/* A hairline of the body's own colour along the top — enough to read as
   identity from a glance down the grid, not enough to look like a banner ad. */
.fsd-examtile::before {
	content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
	background: var(--tile-ring); opacity: .85;
}
a.fsd-examtile:hover {
	border-color: var(--tile-ring);
	box-shadow: var(--shadow-2), 0 0 0 1px color-mix(in srgb, var(--tile-ring) 22%, transparent);
	transform: translateY(-3px);
}
a.fsd-examtile:hover .fsd-examtile__icon { transform: scale(1.08) rotate(-2deg); }
a.fsd-examtile:hover .fsd-examtile__go { gap: 7px; }
.fsd-examtile__icon {
	width: 44px; height: 44px; border-radius: var(--r-sm);
	display: grid; place-items: center; padding: 5px;
	background: var(--bg-sunken); border: 1px solid var(--line-soft);
	transition: transform .22s cubic-bezier(.2,.7,.3,1);
	/* overflow:hidden is the safety net: a grid item sized with place-items:
	   center does not stretch to the cell, so a percentage width/height on the
	   image below resolves against a track that auto-grows to the image's own
	   intrinsic size — for a real photo (ICAR/NIFTEM, hundreds of px) that
	   blew the 44px tile out to the logo's full size. Clipping here plus a
	   pixel (not percentage) cap on the image closes both ends of that loop. */
	overflow: hidden;
}
.fsd-examtile__icon img { max-width: 34px; max-height: 34px; width: auto; height: auto; object-fit: contain; }
.fsd-examtile--soon { --tile-ring: var(--line); }
.fsd-examtile--soon .fsd-examtile__icon { opacity: .8; }
.fsd-examtile h3 { font-size: var(--t-base); font-weight: 680; letter-spacing: -.012em; }
.fsd-examtile p { font-size: var(--t-xs); color: var(--ink-faint); margin-top: -6px; min-height: 2.4em; }
.fsd-examtile__stats { display: flex; gap: var(--s-4); font-size: var(--t-xs); color: var(--ink-soft); }
.fsd-examtile__stats strong { color: var(--ink); font-weight: 660; }
.fsd-examtile__go {
	margin-top: auto; font-size: var(--t-xs); font-weight: 660; color: var(--tile-fg);
	display: flex; align-items: center; gap: 4px;
	transition: gap .18s ease;
}
.fsd-examtile--soon .fsd-examtile__go {
	color: var(--ink-faint); text-transform: uppercase; letter-spacing: .06em; font-weight: 620;
}

@media (max-width: 900px) {
	.fsd-examtile-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
	.fsd-examtile-grid { grid-template-columns: 1fr; }
	.fsd-examtile { padding: var(--s-4); }
}

/* --------------------------------------------------- land: prepare-for chips */

.fsd-chiprow { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-5); }
.fsd-chip-link {
	font-size: var(--t-sm); font-weight: 600; color: var(--ink-soft);
	padding: .4rem .9rem; border: 1px solid var(--line); border-radius: var(--r-full);
	text-decoration: none; background: var(--bg-raised);
	transition: border-color .16s ease, color .16s ease, background .16s ease;
}
.fsd-chip-link:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-bg); }

/* -------------------------------------------------------- land: exam finder */

.fsd-examfinder {
	display: flex; flex-wrap: wrap; gap: var(--s-3); align-items: center;
	margin-top: var(--s-6); padding: var(--s-4) var(--s-5);
	background: var(--bg-raised); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.fsd-examfinder label { font-size: var(--t-sm); font-weight: 620; color: var(--ink-soft); white-space: nowrap; }
.fsd-examfinder select {
	flex: 1 1 220px; min-width: 0; font: inherit; font-size: var(--t-sm);
	padding: .6rem .8rem; border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--bg); color: var(--ink);
}

/* ---------------------------------------------------- land: active/coming */

.fsd-sectionlabel { font-size: var(--t-xs); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint); margin: var(--s-8) 0 var(--s-2); }
.fsd-sectionlabel:first-of-type { margin-top: var(--s-6); }

/* --------------------------------------------------------- land: waitlist */

.fsd-examtile--soon .fsd-examtile__go { cursor: default; }
.fsd-waitlist { margin-top: auto; }
.fsd-waitlist button {
	width: 100%; font-size: var(--t-xs); font-weight: 660; white-space: nowrap;
	padding: .5rem .8rem; border: 1px solid var(--ink); border-radius: var(--r-sm);
	background: var(--ink); color: var(--on-ink); cursor: pointer;
	transition: opacity .16s ease;
}
.fsd-waitlist button:disabled { opacity: .6; cursor: default; }
.fsd-waitlist.is-done { display: none; }
.fsd-waitlist__note { font-size: var(--t-xs); color: var(--ok); margin-top: var(--s-2); }
.fsd-waitlist__note.is-error { color: var(--bad); }
.fsd-waitlist__note:empty { display: none; }

/* --------------------------------------------------------- land: checklist */

.fsd-checklist { list-style: none; margin: var(--s-3) 0; padding: 0; display: grid; gap: 4px; }
.fsd-checklist li { font-size: var(--t-xs); color: var(--ink-soft); display: flex; align-items: center; gap: 6px; }
.fsd-checklist li::before { content: "✓"; color: var(--ok); font-weight: 700; flex: none; }

/* ------------------------------------------------------------- land: why */

/*
 * Scoped to .fsd-whyrow .fsd-why specifically — written as bare `.fsd-why`
 * and `.fsd-why p` these leaked into every other use of the same class,
 * including the glossary's "Real-life application" box, which got the
 * homepage icon-row's centred flex layout and 24-character line cap instead
 * of a normal full-width paragraph.
 */
.fsd-whyrow { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--s-5); text-align: center; }
.fsd-whyrow .fsd-why { display: flex; flex-direction: column; align-items: center; gap: var(--s-2); padding: var(--s-4); }
.fsd-why__icon {
	width: 44px; height: 44px; border-radius: 50%;
	display: grid; place-items: center; background: var(--accent-bg);
}
.fsd-why__icon img { width: 20px; height: 20px; }
.fsd-whyrow .fsd-why h3 { font-size: var(--t-sm); font-weight: 660; }
.fsd-whyrow .fsd-why p { font-size: var(--t-xs); color: var(--ink-faint); max-width: 24ch; }

/* ------------------------------------------------------------ land: stats */

@media (max-width: 860px) {
	/*
	 * Single column now, so "a"/"b" would otherwise both land above
	 * "mock" in source order — pushing the product preview below the
	 * chip row and exam finder, a full extra screen of scrolling before
	 * a visitor sees what the test actually looks like. Reordered so the
	 * preview follows straight after the CTA instead.
	 */
	.fsd-land-hero .fsd-wrap { grid-template-columns: 1fr; grid-template-areas: "facts" "a" "mock" "b"; }
	/* Single column is narrower than the full wrap the facts row was
	   sized for on desktop — shrink text/icons/gaps so it keeps fitting
	   on one line instead of falling back to its horizontal-scroll net. */
	.fsd-land-hero__facts { gap: 6px; }
	.fsd-land-hero__facts div { font-size: 11.5px; gap: 4px; }
	.fsd-land-hero__facts svg { width: 12px; height: 12px; }
	.fsd-land-hero__facts div + div::before { margin-right: 6px; }
	.fsd-mock { transform: none; max-width: 480px; margin-inline: auto; width: 100%; }
	.fsd-mock__body { grid-template-columns: 1fr; }
	.fsd-mock__q { border-right: 0; border-bottom: 1px solid var(--line); }
	.fsd-mock__grid { grid-template-columns: repeat(8, 1fr); max-width: 260px; }
}
/*
 * Below tablet width, .fsd-mock's own two panels stack (the rule above)
 * instead of sitting side by side — which makes this purely decorative,
 * aria-hidden illustration TALLER on a phone than it is on desktop (561px
 * of a 1682px hero, measured on a 375px viewport — a third of the hero
 * spent on a picture of a test screen, before the actual exam cards). On
 * a real phone that is the single biggest thing standing between opening
 * the site and reaching a real card, so it drops here rather than being
 * asked to reflow into something that was never going to read well
 * one-panel-per-screen-width anyway.
 */
@media (max-width: 640px) {
	.fsd-mock { display: none; }
	/* Phone widths are too narrow for one line even at the tablet's
	   compact sizing — wrap rather than rely on an undiscoverable
	   horizontal scroll for text this short. */
	.fsd-land-hero__facts { flex-wrap: wrap; overflow-x: visible; }
	.fsd-land-hero__facts div + div::before { display: none; }
}

/* ==========================================================================
   Exam mega-menu.

   "Mock tests" in the header opens straight to the thing a returning
   student actually wants — a specific test, not another landing page.
   Left pane picks the exam, right pane lists its tests; both panes are the
   same catalogue data the rest of the site already renders from, so there
   is nothing here that can drift out of sync with the real test list.
   ========================================================================== */

/*
 * Static on purpose: the panel below anchors to .fsd-nav (already sticky,
 * so already a containing block) rather than to this trigger. See the
 * panel's own note.
 */
.fsd-megamenu { position: static; }

.fsd-megamenu__trigger {
	display: inline-flex; align-items: center; gap: 6px;
	font: inherit; font-size: var(--t-base); font-weight: 560; color: var(--ink-soft);
	background: none; border: 0; padding: var(--s-1) 0; cursor: pointer;
	border-bottom: 2px solid transparent;
}
.fsd-megamenu__trigger:hover { color: var(--ink); border-bottom-color: var(--line); }
.fsd-megamenu__chevron { transition: transform .16s ease; }
.fsd-megamenu[data-open] .fsd-megamenu__trigger { color: var(--ink); }
.fsd-megamenu[data-open] .fsd-megamenu__chevron { transform: rotate(180deg); }

/*
 * Anchored to the header's right inset, not to the trigger.
 *
 * This used to be `left: 0` on a relatively-positioned trigger, which
 * worked only because the trigger sat right after the logo: the nav
 * carried seven links, so the group started near the left edge. Cutting
 * the nav to three moved the trigger to roughly mid-header, and a 980px
 * panel opening rightward from there ran ~313px past the viewport and
 * gave the whole page a horizontal scrollbar.
 *
 * Pinning to the nav's own right inset makes the panel's position depend
 * on the header, which is fixed, instead of on how many links happen to
 * sit beside it — so editing the nav can't push it off-screen again.
 *
 * A large, single hub: two card grids (exams, subjects) in a scrollable
 * body, plus a slim "browse by format" rail of the site's other pages —
 * every exam links straight to its own overview page rather than expanding
 * inline, so this scales to a wide catalog without deep nested tab state.
 */
.fsd-megamenu__panel {
	position: absolute; top: calc(100% + 14px); left: auto; right: var(--s-5);
	width: min(920px, calc(100vw - 2 * var(--s-5)));
	background: var(--bg-raised);
	border: 1px solid var(--line);
	border-radius: var(--r);
	box-shadow: var(--shadow-2);
	z-index: 60;
	display: flex; align-items: stretch;
	max-height: min(78vh, 640px);
	overflow: hidden;
}
.fsd-megamenu__panel[hidden] { display: none; }

.fsd-megamenu__body {
	flex: 1 1 auto; min-width: 0; overflow-y: auto;
	padding: var(--s-4) var(--s-4) var(--s-5);
	display: flex; flex-direction: column; gap: var(--s-5);
}

.fsd-megamenu__sectionhead {
	display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3);
	margin-bottom: var(--s-3);
}
.fsd-megamenu__sectiontitle {
	font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
	color: var(--ink-faint);
}
.fsd-megamenu__sectionlink { font-size: var(--t-xs); font-weight: 650; color: var(--accent); white-space: nowrap; }

/* Exam picker as small cards, matching the .fsd-examtile language used for
   "Active test series" on the homepage — an icon plus name reads as "this
   is a real exam" the way a plain text row in a dropdown never quite does. */
.fsd-megamenu__cards {
	display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: var(--s-2);
}

.fsd-megamenu__examcard {
	display: flex; flex-direction: column; align-items: flex-start; gap: 5px;
	padding: var(--s-3); border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--bg-raised); text-decoration: none; color: inherit;
	transition: border-color .14s ease, background .14s ease, transform .14s ease, box-shadow .14s ease;
}
.fsd-megamenu__examcard:hover {
	border-color: var(--accent); background: var(--accent-bg);
	transform: translateY(-1px); box-shadow: var(--shadow-1);
}
.fsd-megamenu__examcard.is-soon { opacity: .7; }
.fsd-megamenu__examcardicon {
	width: 32px; height: 32px; border-radius: var(--r-sm);
	display: grid; place-items: center; overflow: hidden;
	background: var(--bg-sunken); border: 1px solid var(--line-soft);
}
.fsd-megamenu__examcardicon img { max-width: 20px; max-height: 20px; width: auto; height: auto; object-fit: contain; }
.fsd-megamenu__examcardname {
	font-family: var(--font-display); font-weight: 700; font-size: .84rem; letter-spacing: -.005em; line-height: 1.25;
}
.fsd-megamenu__examcardmeta { font-family: var(--mono); font-size: .68rem; color: var(--ink-faint); }

/* -------------------------------------------------------------- rail */
.fsd-megamenu__rail {
	flex: none; width: 214px; overflow-y: auto;
	border-left: 1px solid var(--line); background: var(--bg-sunken);
	padding: var(--s-4) var(--s-3);
	display: flex; flex-direction: column; gap: 2px;
}
.fsd-megamenu__railtitle {
	font-size: .68rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
	color: var(--ink-faint); padding: 0 var(--s-2) var(--s-2);
}
.fsd-megamenu__rail a {
	display: block; padding: var(--s-2) var(--s-2); border-radius: var(--r-sm);
	font-size: .88rem; font-weight: 620; color: var(--ink-soft); text-decoration: none;
}
.fsd-megamenu__rail a:hover { background: var(--bg-raised); color: var(--ink); }

@media (max-width: 760px) {
	.fsd-megamenu__panel {
		position: fixed; top: 60px; left: var(--s-3); right: var(--s-3);
		width: auto; flex-direction: column;
		max-height: calc(100vh - 84px);
	}
	.fsd-megamenu__rail {
		width: auto; border-left: 0; border-top: 1px solid var(--line);
		flex-direction: row; flex-wrap: wrap; gap: var(--s-2);
	}
	.fsd-megamenu__railtitle { flex-basis: 100%; }
}

@media (prefers-reduced-motion: reduce) {
	.fsd-megamenu__chevron { transition: none; }
}

/* ==========================================================================
   Exam hub — start-free band, year groups, compact rows

   The exam page used to render every test in the same .fsd-card: a
   180-minute paid paper and a 25-minute free section looked equally
   weighty, and GATE XL's 36 sectionals filled a 7,000px page. Papers keep
   the card, where the weight is earned. Sectionals get a row.
   ========================================================================== */

.fsd-startfree {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-4); flex-wrap: wrap;
	margin: var(--s-5) 0;
	padding: var(--s-4) var(--s-5);
	background: var(--accent-bg);
	border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
	border-radius: var(--r);
}
.fsd-startfree__h {
	font-family: var(--font-display); font-weight: 700; font-size: 1.15rem;
	letter-spacing: -.01em; margin: 2px 0 4px;
}
.fsd-startfree__note { font-size: var(--t-sm); color: var(--ink-soft); margin: 0; max-width: 46ch; }

/* Bundle promo band — same shape as .fsd-startfree, the flash gradient
   (see :root) rather than the site's quiet accent, so "save money" reads
   as an unmissable, distinct offer from "free". */
.fsd-bundlepromo {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-4); flex-wrap: wrap;
	margin: var(--s-5) 0;
	padding: var(--s-4) var(--s-5);
	background: linear-gradient(120deg, var(--flash-1), var(--flash-2));
	border: 1px solid var(--flash-hi);
	border-radius: var(--r);
	box-shadow: 0 4px 18px -6px color-mix(in srgb, var(--flash-1) 55%, transparent);
}
.fsd-bundlepromo__label {
	font-family: var(--mono); font-size: .7rem; font-weight: 700;
	letter-spacing: .07em; text-transform: uppercase; color: var(--on-flash);
	opacity: .85; margin-bottom: 2px;
}
.fsd-bundlepromo__h {
	font-family: var(--font-display); font-weight: 700; font-size: 1.15rem;
	letter-spacing: -.01em; margin: 2px 0 4px; color: var(--on-flash);
}
.fsd-bundlepromo__note { font-size: var(--t-sm); color: var(--on-flash); opacity: .92; margin: 0; max-width: 50ch; }
.fsd-bundlepromo__facts {
	display: flex; gap: var(--s-4); margin-top: var(--s-2);
	font-size: var(--t-xs); color: var(--on-flash); opacity: .85;
}
.fsd-bundlepromo__facts b { color: var(--on-flash); opacity: 1; font-weight: 700; }
.fsd-bundlepromo__actions { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.fsd-bundlepromo__price { text-align: right; color: var(--on-flash); }
.fsd-bundlepromo__price s { font-size: var(--t-sm); opacity: .75; }
.fsd-bundlepromo__price strong { display: block; font-size: 1.4rem; font-weight: 800; letter-spacing: -.02em; }
.fsd-bundlepromo__save {
	display: inline-block; margin-top: 2px;
	font-size: var(--t-xs); font-weight: 800; color: #fff;
	background: rgb(0 0 0 / .18); padding: 1px 8px; border-radius: var(--r-full);
}
.fsd-bundlepromo .fsd-btn--primary {
	background: #fff; color: var(--flash-hi);
}
.fsd-bundlepromo .fsd-btn--primary:hover { background: var(--n-50); color: var(--flash-hi); }
@media (max-width: 640px) {
	.fsd-bundlepromo { flex-direction: column; align-items: flex-start; }
	.fsd-bundlepromo__price { text-align: left; }
}

/* -------------------------------------------------------- year groups */

.fsd-yeargroup {
	border: 1px solid var(--line);
	border-radius: var(--r);
	margin-bottom: var(--s-3);
	background: var(--bg-raised);
	overflow: hidden;
}
.fsd-yeargroup__head {
	display: flex; align-items: baseline; gap: var(--s-3);
	padding: var(--s-3) var(--s-4);
	cursor: pointer; list-style: none;
	transition: background .14s ease;
}
.fsd-yeargroup__head::-webkit-details-marker { display: none; }
.fsd-yeargroup__head:hover { background: var(--bg-sunken); }
.fsd-yeargroup__head:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* A caret the reader can actually find — <summary>'s native marker is
   hidden above so the row can be laid out as a flex line. */
.fsd-yeargroup__head::before {
	content: ""; flex: none;
	width: 7px; height: 7px; margin-right: 2px;
	border-right: 1.8px solid var(--ink-faint);
	border-bottom: 1.8px solid var(--ink-faint);
	transform: rotate(-45deg); transition: transform .16s ease;
}
.fsd-yeargroup[open] .fsd-yeargroup__head::before { transform: rotate(45deg); }

.fsd-yeargroup__year {
	font-family: var(--font-display); font-weight: 700; font-size: 1rem; letter-spacing: -.01em;
}
.fsd-yeargroup__meta { font-family: var(--mono); font-size: .72rem; color: var(--ink-faint); }

/* -------------------------------------------------------- compact rows */

.fsd-rows { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line-soft); }

.fsd-row {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-2) var(--s-4);
	border-bottom: 1px solid var(--line-soft);
	transition: background .14s ease;
}
.fsd-row:last-child { border-bottom: 0; }
.fsd-row:hover { background: var(--bg-sunken); }

/* The whole left side is the link, so the hit target is the row, not just
   the four words in it. */
.fsd-row__main {
	flex: 1 1 auto; min-width: 0;
	display: flex; flex-direction: column; gap: 1px;
	text-decoration: none; color: inherit; padding: var(--s-2) 0;
}
.fsd-row__title {
	font-weight: 620; font-size: var(--t-base); color: var(--ink);
	display: flex; align-items: center; gap: var(--s-2);
}
.fsd-row__main:hover .fsd-row__title { color: var(--accent); }
.fsd-row__meta { font-family: var(--mono); font-size: .7rem; color: var(--ink-faint); }

.fsd-row__price {
	flex: none; font-family: var(--mono); font-size: var(--t-xs);
	font-weight: 700; color: var(--ink-soft); min-width: 52px; text-align: right;
}
.fsd-row__price.is-free { color: var(--ok-700); }
.fsd-row__cta {
	flex: none; font-size: var(--t-xs); font-weight: 700;
	color: var(--accent); text-decoration: none; white-space: nowrap;
	padding: var(--s-2) var(--s-2);
}
.fsd-row__cta:hover { text-decoration: underline; }

@media (max-width: 560px) {
	/* Price and the duplicate Start link go: the row itself is already the
	   link, and at this width they were crowding the title off the line. */
	.fsd-row__cta { display: none; }
	.fsd-row { padding: var(--s-2) var(--s-3); }
	.fsd-startfree { flex-direction: column; align-items: stretch; }
	/* This CTA's text is a real section name (exam.php passes the section's
	   own label straight through) and can run long — "Start General
	   Aptitude And Computer Literacy →" is 47 characters. .fsd-btn's base
	   white-space: nowrap held that at its full intrinsic width and pushed
	   the whole page 30+px past the viewport on a 375px phone. */
	.fsd-startfree .fsd-btn { white-space: normal; text-align: center; }
}

@media (prefers-reduced-motion: reduce) {
	.fsd-yeargroup__head, .fsd-yeargroup__head::before, .fsd-row { transition: none; }
}

/* ------------------------------------------- mock tests: source filter */

/* The count sits inside the chip so "Previous year papers 10" reads as one
   control, and so an empty filter is visible before it is clicked rather
   than after. */
.fsd-cat__count {
	margin-left: 6px; padding: 1px 5px;
	font-family: var(--mono); font-size: .65rem; font-weight: 700;
	border-radius: var(--r-full);
	background: var(--bg-sunken); color: var(--ink-faint);
}
.fsd-cat.is-active .fsd-cat__count { background: color-mix(in srgb, var(--on-ink) 22%, transparent); color: var(--on-ink); }

/* Provenance, stated on the card itself. This badge is the whole reason
   the two old browse pages could be merged without an original mock ever
   reading as a real past paper. */
.fsd-card__badge--source {
	background: var(--accent-bg);
	color: var(--accent-hi);
	border-color: color-mix(in srgb, var(--accent) 24%, transparent);
}
/* A chip that leads nowhere still shows, so the filter set stays stable as
   you move between exams — it just stops looking clickable. */
.fsd-cat.is-empty { opacity: .5; }

/* The start-free band, reused on the home page. --plain drops the accent
   tint for the second one, so two bands in a column don't compete. */
.fsd-startfree__actions { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.fsd-startfree--plain { background: var(--bg-sunken); border-color: var(--line); }

/* ==========================================================================
   The four products

   Two axes — real questions vs written by us, whole paper vs one part.
   Every test is one cell. The grid is laid out as the 2x2 it actually is,
   with both axes labelled, so the four names don't have to carry the whole
   explanation on their own.
   ========================================================================== */

.fsd-chooser {
	display: grid;
	grid-template-columns: auto 1fr 1fr;
	gap: var(--s-2);
	align-items: stretch;
	margin: var(--s-5) 0 var(--s-6);
}
.fsd-chooser__corner { }
.fsd-chooser__colhead,
.fsd-chooser__rowhead {
	font-family: var(--mono); font-size: .66rem; font-weight: 700;
	letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint);
	display: flex; align-items: center;
}
.fsd-chooser__colhead { padding-left: var(--s-3); }
.fsd-chooser__rowhead { max-width: 5.5rem; line-height: 1.25; }

.fsd-chooser__cell {
	display: flex; flex-direction: column; gap: 3px;
	padding: var(--s-3) var(--s-4);
	border: 1px solid var(--line); border-radius: var(--r);
	background: var(--bg-raised); text-decoration: none; color: inherit;
	transition: border-color .14s ease, background .14s ease, transform .14s ease;
}
.fsd-chooser__cell:hover {
	border-color: var(--accent); background: var(--accent-bg);
	transform: translateY(-1px);
}
.fsd-chooser__cell.is-active { border-color: var(--ink); background: var(--bg-sunken); }
.fsd-chooser__cell.is-blank { border-style: dashed; opacity: .4; background: none; }

.fsd-chooser__name {
	font-family: var(--font-display); font-weight: 700; font-size: 1.02rem;
	letter-spacing: -.01em; display: flex; align-items: center; gap: var(--s-2);
}
.fsd-chooser__count {
	font-family: var(--mono); font-size: .64rem; font-weight: 700;
	padding: 1px 5px; border-radius: var(--r-full);
	background: var(--bg-sunken); color: var(--ink-faint);
}
.fsd-chooser__blurb { font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.4; }

@media (max-width: 720px) {
	/* The 2x2 stops being a grid and becomes four stacked cards. The axis
	   headers go with it — a column header floating above one cell reads as
	   a label for that cell, which is worse than no header at all. */
	.fsd-chooser { grid-template-columns: 1fr; }
	.fsd-chooser__corner,
	.fsd-chooser__colhead,
	.fsd-chooser__rowhead { display: none; }
}

/* ---------------------------------------------- rail items with a blurb */

.fsd-megamenu__railitem {
	display: flex; flex-direction: column; gap: 1px;
	padding: var(--s-2) var(--s-2) var(--s-3);
}
.fsd-megamenu__railname { font-size: .88rem; font-weight: 650; color: var(--ink); }
.fsd-megamenu__raildesc {
	font-size: .72rem; line-height: 1.35; color: var(--ink-faint);
}
.fsd-megamenu__railitem:hover .fsd-megamenu__railname { color: var(--accent); }

/* ------------------------------------------------------------ type chip */

/* Says which of the four this card is, in the same words as the nav and
   the chooser. */
.fsd-typechip {
	display: inline-block; margin-right: var(--s-2);
	font-family: var(--mono); font-size: .6rem; font-weight: 700;
	letter-spacing: .06em; text-transform: uppercase;
	padding: 2px 6px; border-radius: var(--r-sm);
	background: var(--bg-sunken); color: var(--ink-soft);
	border: 1px solid var(--line-soft);
}
.fsd-typechip--previous-year-paper { background: var(--accent-bg); color: var(--accent-hi); border-color: color-mix(in srgb, var(--accent) 24%, transparent); }
.fsd-typechip--sectional-test     { background: var(--accent-bg); color: var(--accent-hi); border-color: color-mix(in srgb, var(--accent) 24%, transparent); }

/* ==========================================================================
   Conversion surfaces — next-step block, free-tests bar, wider fact rows
   ========================================================================== */

/* The block that follows a score. Nothing sat here before, on the one screen
   where the visitor has just demonstrated they are interested. */
.fsd-next {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-5); flex-wrap: wrap;
	margin: var(--s-6) 0;
	padding: var(--s-5);
	background: var(--accent-bg);
	border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
	border-radius: var(--r);
}
.fsd-next__body { flex: 1 1 22rem; min-width: 0; }
.fsd-next__label {
	font-family: var(--mono); font-size: .66rem; font-weight: 700;
	letter-spacing: .08em; text-transform: uppercase; color: var(--accent-hi);
	margin-bottom: 4px;
}
.fsd-next__h {
	font-family: var(--font-display); font-weight: 800; font-size: 1.35rem;
	letter-spacing: -.015em; line-height: 1.2; margin-bottom: 6px;
}
.fsd-next__note { font-size: var(--t-sm); color: var(--ink-soft); margin: 0; max-width: 52ch; }
.fsd-next__actions { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }

/* ------------------------------------------------------------- test ticker */

/*
 * Decorative marquee of what's on the site, right below the nav. The moving
 * track is aria-hidden (see layout.php for why); everything a keyboard or
 * screen-reader visitor needs is the one real CTA link beside it.
 */
.fsd-ticker {
	display: flex; align-items: center; gap: var(--s-4);
	background: linear-gradient(90deg, var(--flash-1), var(--flash-2));
	padding: 0 0 0 var(--s-5);
}
.fsd-ticker__scroll {
	flex: 1 1 auto; min-width: 0; overflow: hidden;
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.fsd-ticker__track {
	display: flex; align-items: center; width: max-content;
	animation: fsd-ticker-scroll 46s linear infinite;
}
/* Pausing on hover/focus lets anyone who wanted to read a specific line
   (rather than just clock that the strip exists) actually do it. */
.fsd-ticker:hover .fsd-ticker__track,
.fsd-ticker:focus-within .fsd-ticker__track {
	animation-play-state: paused;
}
/* A row of real buttons, one straight to each exam — not plain scrolling
   text, so the strip reads (and behaves) as a set of shortcuts rather than
   an announcement. */
.fsd-ticker__item {
	flex: none; display: inline-flex; align-items: center; gap: 7px;
	margin: var(--s-2) var(--s-2) var(--s-2) 0;
	padding: 7px 8px 7px 14px;
	font-family: var(--mono); font-size: var(--t-xs); font-weight: 700;
	color: var(--on-flash); text-decoration: none; white-space: nowrap;
	background: rgb(255 255 255 / .16);
	border: 1px solid rgb(255 255 255 / .35);
	border-radius: var(--r-full);
	transition: background .14s ease, border-color .14s ease;
}
.fsd-ticker__item:hover, .fsd-ticker__item:focus-visible {
	background: rgb(255 255 255 / .34); border-color: rgb(255 255 255 / .6);
}
/* The duplicate copy is aria-hidden + tabindex="-1" for the loop, but that
   doesn't stop a sighted mouse user from clicking it — a visible focus ring
   on something that can't actually receive focus would be a lie, so it's
   suppressed only there. */
.fsd-ticker__item[tabindex="-1"] { outline: none; }
.fsd-ticker__cta {
	flex: none; display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-2) var(--s-5) var(--s-2) var(--s-4);
	border-left: 1px solid rgb(255 255 255 / .3);
	font-size: var(--t-sm);
}
.fsd-ticker__cta a {
	font-weight: 700; color: var(--on-flash); text-decoration: none;
	padding: 4px 10px; white-space: nowrap;
	background: rgb(255 255 255 / .18); border-radius: var(--r-full);
	border: 1px solid rgb(255 255 255 / .35);
}
.fsd-ticker__cta a:hover { background: rgb(255 255 255 / .3); text-decoration: none; }
.fsd-ticker__cta a + a {
	font-weight: 500; color: var(--on-flash); background: none; border-color: transparent;
}

@keyframes fsd-ticker-scroll {
	from { transform: translateX(0); }
	/* Exactly half: the track holds two copies of the same list back to
	   back, so sliding by one copy's width loops with no visible seam. */
	to   { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
	.fsd-ticker__track { animation: none; }
	.fsd-ticker__scroll { overflow-x: auto; }
}

@media (max-width: 640px) {
	.fsd-ticker { flex-direction: column; align-items: stretch; padding-left: 0; }
	.fsd-ticker__scroll { padding-left: var(--s-4); }
	.fsd-ticker__cta { border-left: 0; border-top: 1px solid var(--line); justify-content: center; }
}

/* --------------------------------------------------------- free-tests bar */

/* A bar, not a modal. It never covers the page, which is both why it can be
   shown to search traffic without risking an intrusive-interstitial demotion
   and why it can sit there rather than demanding a decision. */
.fsd-prompt {
	position: fixed; left: var(--s-4); right: var(--s-4); bottom: var(--s-4);
	z-index: 70; margin: 0 auto; max-width: 40rem;
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4);
	background: linear-gradient(120deg, var(--flash-1), var(--flash-2));
	color: var(--on-flash);
	border-radius: var(--r);
	box-shadow: 0 8px 24px -6px color-mix(in srgb, var(--flash-1) 60%, transparent);
}

/*
 * Visible whenever it is not [hidden]. The slide-in is decoration layered on
 * top, never the thing that makes it appear: as a transition from opacity 0
 * it stayed invisible anywhere the transition did not run — a backgrounded
 * tab, a browser that never composited the frame — leaving a bar that was
 * present and clickable but could not be seen.
 */
.fsd-prompt[hidden] { display: none; }
/* No fill-mode: `both` would hold the keyframe's opacity-0 start whenever the
   animation does not actually run, which is the same invisible-bar failure in
   a different costume. Without it, the element's own visible style applies. */
.fsd-prompt.is-in { animation: fsd-prompt-in .22s ease; }

/* Transform only, never opacity. An animation that is running but whose clock
   is not advancing — a backgrounded tab, a frame that never composites — holds
   its start values indefinitely, and a start value of opacity 0 means an
   invisible bar. Held at the start of this one, the bar is fully readable and
   ten pixels low. */
@keyframes fsd-prompt-in {
	from { transform: translateY(10px); }
	to   { transform: none; }
}
.fsd-prompt__text { flex: 1 1 auto; margin: 0; font-size: var(--t-sm); line-height: 1.4; }
.fsd-prompt__text strong { color: #fff; }
.fsd-prompt__close {
	flex: none; background: none; border: 0; cursor: pointer;
	color: var(--n-300); font-size: 1.3rem; line-height: 1;
	padding: 0 2px;
}
.fsd-prompt__close:hover { color: #fff; }

@media (max-width: 560px) {
	.fsd-prompt { flex-wrap: wrap; }
	.fsd-prompt__text { flex-basis: 100%; }
}

@media (prefers-reduced-motion: reduce) {
	.fsd-prompt.is-in { animation: none; }
}

/* ----------------------------------------------------- paywall specifics */

.fsd-facts--wide { margin: var(--s-4) 0; }
.fsd-paywall__sections {
	font-family: var(--mono); font-size: .72rem; color: var(--ink-faint);
	text-align: center; margin-bottom: var(--s-4);
}
.fsd-checklist--paywall { text-align: left; max-width: 30rem; margin: 0 auto var(--s-4); }

/* ==========================================================================
   Header menus — Exams and Tests

   Two panels instead of one, because the catalog has two axes and a single
   panel labelled "Exams" was carrying both the exams and the four test types.
   ========================================================================== */

/* Group labels are <p>, not headings: as <h3> in the header they preceded the
   page's own <h1> and broke the document outline. Styling unchanged. */
.fsd-megamenu__sectiontitle { display: flex; align-items: center; gap: var(--s-2); }
.fsd-megamenu__sectioncount {
	font-family: var(--mono); font-size: .7rem; font-weight: 700;
	padding: 1px 5px; border-radius: var(--r-full);
	background: var(--bg-sunken); color: var(--ink-faint);
	letter-spacing: 0;
}

/* Narrower than the exam grid: four cells, not thirteen. */
/* wrap: the panel is a flex row, so without this the footer sat beside the
   grid and squeezed four cells into 163px each instead of letting them span
   the full 680. */
.fsd-megamenu__panel--tests {
	width: min(680px, calc(100vw - 2 * var(--s-5)));
	flex-wrap: wrap;
}

.fsd-menugrid {
	display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-2);
	padding: var(--s-4);
	flex: 1 1 auto; min-width: 0;
}
.fsd-menugrid__cell {
	display: flex; flex-direction: column; gap: 3px;
	padding: var(--s-3) var(--s-4);
	border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--bg-raised); text-decoration: none; color: inherit;
	transition: border-color .14s ease, background .14s ease;
}
.fsd-menugrid__cell:hover { border-color: var(--accent); background: var(--accent-bg); }
.fsd-menugrid__cell[aria-current="page"] { border-color: var(--ink); background: var(--bg-sunken); }

.fsd-menugrid__top { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); }
.fsd-menugrid__name {
	font-family: var(--font-display); font-weight: 700; font-size: .96rem; letter-spacing: -.01em;
}
.fsd-menugrid__count {
	font-family: var(--mono); font-size: .7rem; font-weight: 700;
	padding: 1px 5px; border-radius: var(--r-full);
	background: var(--bg-sunken); color: var(--ink-faint);
}
.fsd-menugrid__blurb { font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.4; }

/* The two axes, spelled out per cell. In the panel there is no room for the
   labelled 2x2 the pages carry, so each cell states its own coordinates. */
.fsd-menugrid__axes {
	margin-top: 2px;
	font-family: var(--mono); font-size: var(--t-xs); letter-spacing: .02em;
	color: var(--ink-faint);
}

.fsd-menugrid__foot {
	flex-basis: 100%;
	margin: 0; padding: var(--s-3) var(--s-4);
	border-top: 1px solid var(--line-soft); background: var(--bg-sunken);
	font-size: var(--t-xs); color: var(--ink-faint);
}

/* Current page, marked in the header rather than left to be guessed. */
.fsd-nav__links > a[aria-current="page"] {
	color: var(--ink); border-bottom-color: var(--accent);
}
.fsd-megamenu__examcard[aria-current="page"] {
	border-color: var(--ink); background: var(--bg-sunken);
}

@media (max-width: 720px) {
	.fsd-megamenu__panel--tests { width: auto; }
	.fsd-menugrid { grid-template-columns: 1fr; }
}
/* Count beside a section heading — same role as the filter-chip counts. */
.fsd-h2__count {
	margin-left: var(--s-2);
	font-family: var(--mono); font-size: .7rem; font-weight: 700;
	padding: 1px 6px; border-radius: var(--r-full);
	background: var(--bg-sunken); color: var(--ink-faint);
	vertical-align: middle;
}


/* Rail items that carry an icon — the three subjects, beside the exam grid. */
.fsd-megamenu__railitem--icon {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-2);
}
.fsd-megamenu__railitem--icon .fsd-megamenu__examcardicon { flex: none; }
.fsd-megamenu__railitem--icon > span:last-child { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.fsd-megamenu__railtitle { display: flex; align-items: center; gap: var(--s-2); }


/* ==========================================================================
   Header at small widths

   Everything used to sit in one horizontally scrolling strip, which put Sign
   up 224px past the right edge of a 375px screen. Account actions and a menu
   button stay in the bar; the rest collapses behind the button.
   ========================================================================== */

.fsd-nav__account { display: flex; align-items: center; gap: var(--s-4); }
.fsd-nav__links { margin-left: auto; }

/* Hamburger. Desktop never sees it. */
.fsd-navtoggle {
	display: none;
	width: 44px; height: 44px; flex: none;
	align-items: center; justify-content: center;
	background: none; border: 1px solid var(--line); border-radius: var(--r-sm);
	cursor: pointer; color: var(--ink);
}
.fsd-navtoggle__bars { display: block; width: 18px; }
.fsd-navtoggle__bars span {
	display: block; height: 2px; border-radius: 2px; background: currentColor;
	transition: transform .18s ease, opacity .18s ease;
}
.fsd-navtoggle__bars span + span { margin-top: 4px; }
.fsd-nav[data-navopen] .fsd-navtoggle__bars span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.fsd-nav[data-navopen] .fsd-navtoggle__bars span:nth-child(2) { opacity: 0; }
.fsd-nav[data-navopen] .fsd-navtoggle__bars span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 860px) {
	.fsd-navtoggle { display: inline-flex; }
	/* Tighter gaps: brand + account + toggle came to 346px against 343px of
	   room, so the toggle dropped onto its own row. */
	.fsd-nav { flex-wrap: wrap; gap: var(--s-2); }
	.fsd-nav__account { margin-left: auto; gap: var(--s-2); }

	/* Collapsed by default, full-width column when open. */
	.fsd-nav__links {
		display: none;
		flex-basis: 100%; width: 100%; margin-left: 0;
		flex-direction: column; align-items: stretch; gap: 0;
		padding-top: var(--s-2);
		border-top: 1px solid var(--line-soft);
	}
	.fsd-nav[data-navopen] .fsd-nav__links {
		display: flex;
		/* With both accordions open the header reached 1243px on an 812px
		   screen. Capped, it scrolls inside itself instead of turning the
		   whole page into one long header. */
		/* 70% leaves the bar, its padding and a strip of the page visible at
		   every phone height, without doing arithmetic on a header whose own
		   height changes with the viewport. */
		max-height: 70vh;
		max-height: 70dvh;
		overflow-y: auto;
		overscroll-behavior: contain;
	}

	/* 44px minimum on every row, which the 35px inline links missed. */
	.fsd-nav__links > a,
	.fsd-nav__links > .fsd-megamenu > .fsd-megamenu__trigger {
		display: flex; align-items: center;
		min-height: 48px; width: 100%;
		padding: 0 var(--s-2);
		border-bottom: 1px solid var(--line-soft);
		font-size: 1rem;
	}
	.fsd-megamenu { width: 100%; }
	.fsd-megamenu__trigger { justify-content: space-between; }

	/* Panels expand in flow rather than floating over the page: an overlay
	   anchored to a header that has itself just grown taller is a fight
	   nobody wins. */
	.fsd-megamenu__panel,
	.fsd-megamenu__panel--tests {
		position: static; width: 100%; max-width: none;
		border: 0; border-radius: 0; box-shadow: none;
		background: var(--bg-sunken);
		max-height: none; flex-direction: column;
	}
	.fsd-megamenu__rail { width: auto; border-left: 0; border-top: 1px solid var(--line); }
	.fsd-nav__search { flex-basis: auto; width: 100%; margin: var(--s-3) 0; min-height: 44px; }
	.fsd-nav__search input { font-size: 16px; min-height: 40px; } /* under 16px iOS zooms the page on focus */

	/* The strapline is the widest part of the brand and pushed the bar onto a
	   second row, making a sticky header 119px tall on an 812px screen. The
	   wordmark alone identifies the site, and at 1.2rem uppercase it still
	   overflowed the row on its own. */
	.fsd-nav__brand-text span { display: none; }
	.fsd-nav__brand { font-size: .95rem; gap: 8px; min-height: 44px; }
	.fsd-nav__brand img { width: 22px; height: 22px; }

	/* 44px on the account row and the hero chips, which sat at 28 and 36. */
	.fsd-nav__account a,
	.fsd-nav__account button { display: inline-flex; align-items: center; min-height: 44px; }
	.fsd-chip-link { min-height: 44px; display: inline-flex; align-items: center; }
}

/* Informational text in the menu was 10.88px and 11.52px. */
.fsd-megamenu__examcardmeta { font-size: var(--t-xs); }
.fsd-megamenu__sectiontitle { font-size: var(--t-xs); }

/* --------------------------------------------------- target + text floors */

/* The exam name in a card eyebrow was a 14px-tall inline link — under the
   24x24 CSS px minimum WCAG 2.2 AA sets for pointer targets on the web. */
.fsd-card__exam a {
	display: inline-block;
	padding: 5px 0;
	min-height: 24px;
}

/* Informational text in the menu sat between 10.88px and 11.52px. */
.fsd-megamenu__railtitle,
.fsd-megamenu__raildesc,
.fsd-megamenu__sectioncount,
.fsd-megamenu__examcardmeta { font-size: var(--t-xs); }

@media (max-width: 860px) {
	/* Filter chips are a primary control on the browse pages; 33px is over
	   the AA floor but short of comfortable on a phone. */
	.fsd-cat { min-height: 44px; display: inline-flex; align-items: center; }
	.fsd-topicnav__btn { min-height: 44px; display: inline-flex; align-items: center; }
	.fsd-row__cta, .fsd-row__main { min-height: 44px; }
}
/* Counts are content, not decoration — they belong above the 12px floor. */
.fsd-chooser__count,
.fsd-menugrid__count,
.fsd-h2__count,
.fsd-cat__count { font-size: var(--t-xs); }
/* Row meta carries the question count and duration — the two facts a student
   compares between years. 11.2px was too small to be doing that job. */
.fsd-row__meta { font-size: var(--t-xs); }
/* The type chip names which of the four products a card is — the one label
   that tells a past paper from an original mock. It was 9.6px. */
.fsd-typechip { font-size: .7rem; }
@media (max-width: 860px) { .fsd-typechip { font-size: var(--t-xs); } }
/* The "All exams" back-link in an eyebrow was a 15px-tall target. */
.fsd-eyebrow a { display: inline-block; padding: 5px 0; min-height: 24px; }

/* Year-group meta gives the paper count and the setting institute. */
.fsd-yeargroup__meta { font-size: var(--t-xs); }
/* "Log in" beside "Already have one?" is a real destination, not prose, so it
   gets a target rather than the inline-link exception. */
.fsd-panel__alt a { display: inline-block; padding: 4px 0; min-height: 24px; }

/* The 404's search field, and the section list on a buy screen. */
.fsd-404-search input, .fsd-form input[type="search"] { min-height: 44px; }
.fsd-paywall__sections { font-size: var(--t-xs); }
/* Glossary cross-references are inline prose links, which WCAG 2.2 exempts
   from the target minimum — but they are the main way to move around the
   glossary on a phone, so they get the hit area anyway. */
.fsd-gterm__see a { display: inline-block; padding: 2px 0; min-height: 24px; }

/* "Everything for this exam →" is a destination, not prose. */
.fsd-sub a { display: inline-block; padding: 4px 0; min-height: 24px; }

/* ==========================================================================
   Header menus, rebuilt

   One row component for both panels. Every exam used to be a tile with its
   logo floating above a name above a count, so ten different logos read as
   ten different stickers rather than one list; in a 4-wide grid the tenth
   left a hole in the eleventh slot.

   Colours are the homepage's: maroon --accent for anything interactive,
   --bg-sunken for the mark wells, --line for edges. Nothing new introduced.
   ========================================================================== */

.fsd-megamenu__panel {
	padding: var(--s-4);
	gap: var(--s-5);
}
.fsd-megamenu__panel--tests { width: min(620px, calc(100vw - 2 * var(--s-5))); }

.fsd-menucol { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.fsd-menuside {
	flex: none; width: 270px;
	display: flex; flex-direction: column;
	padding-left: var(--s-5);
	border-left: 1px solid var(--line-soft);
}

.fsd-menuhead {
	display: flex; align-items: center; gap: var(--s-2);
	font-family: var(--mono); font-size: var(--t-xs); font-weight: 700;
	letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint);
	margin: 0 0 var(--s-3);
}
.fsd-menuhead__n {
	font-size: .7rem; padding: 1px 6px; border-radius: var(--r-full);
	background: var(--bg-sunken); color: var(--ink-soft); letter-spacing: 0;
}

/* Scrolls once the catalog outgrows the panel, rather than growing the
   panel until it runs off the bottom of the screen. Exams and Subjects
   share the same max-height so the two columns land at the same height
   instead of one trailing off into blank space below the other. */
.fsd-menuscroll {
	overflow-y: auto; overscroll-behavior: contain;
	max-height: 380px;
	margin-right: calc(-1 * var(--s-2)); padding-right: var(--s-2);
}
.fsd-menuscroll::-webkit-scrollbar { width: 8px; }
.fsd-menuscroll::-webkit-scrollbar-thumb {
	background: var(--n-200); border-radius: var(--r-full);
	border: 2px solid var(--bg-raised);
}
.fsd-menuscroll::-webkit-scrollbar-thumb:hover { background: var(--n-300); }
.fsd-menuscroll { scrollbar-width: thin; scrollbar-color: var(--n-200) transparent; }

.fsd-menulist { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.fsd-menulist--2col { grid-template-columns: repeat(2, 1fr); gap: 4px var(--s-3); }

/* The row itself: mark, name, one line of meta. Bigger than a typical nav
   row on purpose — this is choosing which of ten exams to prepare for, not
   a dense settings list, and the old 34px marks read as similar-looking
   stickers rather than the exam's own seal or wordmark. */
.fsd-menurow {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-2);
	border-radius: var(--r-sm);
	text-decoration: none; color: inherit;
	transition: background .14s ease;
}
.fsd-menurow:hover { background: var(--accent-bg); }
.fsd-menurow:hover .fsd-menurow__name { color: var(--accent); }
.fsd-menurow[aria-current="page"] { background: var(--bg-sunken); }
.fsd-menurow[aria-current="page"] .fsd-menurow__name { color: var(--accent); }
.fsd-menurow.is-soon { opacity: .55; }

/* One well for every logo, so a wordmark, a seal and a lettermark all sit at
   the same size on the same ground instead of each bringing its own. */
.fsd-menurow__mark {
	flex: none; width: 48px; height: 48px;
	display: grid; place-items: center;
	background: var(--bg-sunken); border: 1px solid var(--line-soft);
	border-radius: var(--r-sm); overflow: hidden;
}
.fsd-menurow__mark img { max-width: 30px; max-height: 30px; width: auto; height: auto; object-fit: contain; }

.fsd-menurow__text { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.fsd-menurow__name {
	font-family: var(--font-display); font-weight: 700; font-size: 1.05rem;
	letter-spacing: -.005em; line-height: 1.2; color: var(--ink);
	display: flex; align-items: center; gap: var(--s-2);
}
.fsd-menurow__meta {
	font-size: var(--t-xs); color: var(--ink-faint); line-height: 1.35;
	overflow: hidden; text-overflow: ellipsis;
}
.fsd-menurow__n {
	font-family: var(--mono); font-size: .7rem; font-weight: 700;
	padding: 1px 6px; border-radius: var(--r-full);
	background: var(--bg-sunken); color: var(--ink-soft);
}
.fsd-menurow--type { align-items: flex-start; padding: var(--s-3) var(--s-2); }

/* One button per panel, in the homepage's primary style. Neither panel had
   an action in it at all — you could browse a menu and leave. */
.fsd-menucta {
	/* flex:none, or the column squashes the button to 26px. margin-top:auto
	   pins it to the foot of the side column whatever the list height. */
	flex: none;
	margin-top: auto;
	padding-top: .68rem; padding-bottom: .68rem;
	width: 100%;
}
.fsd-menuside .fsd-menucta { margin-top: var(--s-4); }
.fsd-menucol > .fsd-menucta { align-self: flex-start; width: auto; min-width: 15rem; }

@media (max-width: 860px) {
	.fsd-menuside { width: auto; padding-left: 0; border-left: 0; border-top: 1px solid var(--line-soft); padding-top: var(--s-4); margin-top: var(--s-4); }
	.fsd-menulist--2col { grid-template-columns: 1fr; }
	.fsd-menuscroll { max-height: none; overflow: visible; }
	.fsd-menurow { padding: var(--s-3) var(--s-2); }
	.fsd-menucol > .fsd-menucta { width: 100%; }
}

/* ==========================================================================
   Exam guide

   Pattern, previous years and changes are counted from the question banks on
   this server. Eligibility and syllabus are linked to the exam body, never
   copied — they change per notification, and a stale copy on a prep site is
   worse than no copy.
   ========================================================================== */

.fsd-guide {
	margin: var(--s-5) 0 var(--s-6);
	border: 1px solid var(--line);
	border-radius: var(--r);
	background: var(--bg-raised);
	overflow: hidden;
}

.fsd-guide__tabs {
	display: flex; flex-wrap: wrap; gap: 0;
	border-bottom: 1px solid var(--line);
	background: var(--bg-sunken);
}
.fsd-guide__tab {
	font: inherit; font-size: var(--t-sm); font-weight: 620;
	color: var(--ink-soft); background: none;
	border: 0; border-bottom: 2px solid transparent;
	padding: var(--s-3) var(--s-4); min-height: 44px;
	cursor: pointer; white-space: nowrap;
}
.fsd-guide__tab:hover { color: var(--ink); }
.fsd-guide__tab[aria-selected="true"] {
	color: var(--accent); border-bottom-color: var(--accent);
	background: var(--bg-raised);
}

.fsd-guide__panel { padding: var(--s-5); }
.fsd-guide__panel[hidden] { display: none; }
.fsd-guide__lede { font-size: var(--t-base); color: var(--ink-soft); margin: 0 0 var(--s-4); max-width: 70ch; }

.fsd-guide__facts { display: grid; gap: var(--s-3); margin: 0 0 var(--s-4); }
.fsd-guide__facts dt {
	font-family: var(--mono); font-size: var(--t-xs); font-weight: 700;
	letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint);
}
.fsd-guide__facts dd { margin: 2px 0 0; font-size: var(--t-sm); color: var(--ink); }

.fsd-guide__links { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-bottom: var(--s-3); }
.fsd-guide__note { font-size: var(--t-xs); color: var(--ink-faint); margin: 0; max-width: 60ch; }
.fsd-guide__org { display: block; font-family: var(--mono); font-size: .7rem; color: var(--ink-faint); font-weight: 400; }

/* --------------------------------------------- exam-page segmented toggle */

/*
 * Previous Year Papers / Practice Tests, and — nested one level inside
 * Practice Tests — Full Mock Test / Sectional. Bigger, bolder buttons than
 * .fsd-guide__tab's quiet underline tabs on purpose: this toggle decides
 * which of two genuinely different products a candidate sees next, not
 * which read-only fact panel to show.
 *
 * Shares .fsd-guide for the card frame (border/radius/panel padding) and
 * [data-tabs]/role="tab" for the same keyboard model ui.js already wires —
 * only the tablist/button skin below is its own.
 */
.fsd-segtoggle__tabs {
	display: flex; flex-wrap: wrap; gap: var(--s-2);
	padding: var(--s-4) var(--s-4) 0;
	background: var(--bg-raised); border-bottom: 0;
}
.fsd-segtoggle__btn {
	flex: 1 1 220px;
	display: flex; align-items: center; justify-content: center; gap: 8px;
	font: inherit; font-size: var(--t-base); font-weight: 650;
	color: var(--ink); background: var(--bg-sunken);
	border: 1.5px solid var(--line); border-radius: var(--r);
	padding: var(--s-3) var(--s-4); min-height: 48px;
	cursor: pointer; transition: background .14s ease, border-color .14s ease, color .14s ease;
}
.fsd-segtoggle__btn:hover:not([aria-selected="true"]) { border-color: var(--ink-faint); }
.fsd-segtoggle__btn[aria-selected="true"] {
	background: var(--accent); border-color: var(--accent); color: var(--on-accent);
}
/* The sub-toggle sits inside an already-padded panel, so it carries its
   own smaller frame rather than .fsd-guide's again. */
.fsd-segtoggle--sub { border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
.fsd-segtoggle--sub .fsd-segtoggle__tabs { padding: var(--s-3) var(--s-3) 0; background: var(--bg-sunken); }
.fsd-segtoggle--sub .fsd-segtoggle__btn { flex: 1 1 160px; padding: var(--s-2) var(--s-3); font-size: var(--t-sm); min-height: 40px; }
.fsd-segtoggle--sub .fsd-guide__panel { padding: var(--s-4); }
@media (max-width: 560px) {
	.fsd-segtoggle__btn { flex-basis: 100%; }
}
.fsd-guide__pct { font-family: var(--mono); font-size: var(--t-xs); color: var(--ink-faint); margin-left: var(--s-2); }

.fsd-guide__changes { margin: 0; padding-left: 1.1rem; display: grid; gap: var(--s-4); }
.fsd-guide__changehead { font-weight: 650; margin: 0 0 var(--s-2); }
.fsd-guide__difflist { margin: 0; padding-left: 1.1rem; font-size: var(--t-sm); color: var(--ink-soft); }
.fsd-guide__difflist li { margin-bottom: 2px; }

@media (max-width: 640px) {
	.fsd-guide__tabs { overflow-x: auto; flex-wrap: nowrap; }
	.fsd-guide__panel { padding: var(--s-4); }
}
/* A subject a paper did not contain, so the gap reads as absence rather than
   a missing number. */
.fsd-table td.is-absent { color: var(--ink-faint); }
.fsd-guide__totals th, .fsd-guide__totals td { border-top: 2px solid var(--line); font-weight: 700; }

/* Topic bullets on a card. What the test covers — the one thing the card was
   not saying, while it said the question count twice. */
.fsd-topics {
	list-style: none; margin: 0 0 var(--s-3); padding: 0;
	display: flex; flex-wrap: wrap; gap: 4px;
}
.fsd-topics li {
	font-size: var(--t-xs); line-height: 1.3;
	padding: 3px 8px;
	/* --r-sm (3px), not the full stadium pill: some exams' real section
	   names run long enough to wrap onto 3-4 lines (NIFTEM's "Part-B —
	   Food Technology Stream (Section I: ...)"), and a fully rounded pill
	   around wrapped text bulges into an odd capsule shape instead of
	   reading as a contained tag. */
	border-radius: var(--r-sm);
	background: var(--bg-sunken); color: var(--ink-soft);
	border: 1px solid var(--line-soft);
}
.fsd-guide__optional {
	font-family: var(--mono); font-size: .68rem; font-weight: 700;
	padding: 2px 7px; border-radius: var(--r-full);
	background: var(--accent-bg); color: var(--accent-hi);
}

/* Eligibility, inside the About tab. */
.fsd-eligibility {
	margin: var(--s-4) 0;
	padding: var(--s-4);
	background: var(--bg-sunken);
	border: 1px solid var(--line-soft);
	border-radius: var(--r);
}
.fsd-eligibility__h {
	font-family: var(--font-display); font-weight: 700; font-size: 1.05rem;
	letter-spacing: -.01em; margin: 0 0 var(--s-2);
}
.fsd-eligibility__lede { font-size: var(--t-sm); color: var(--ink); margin: 0 0 var(--s-3); max-width: 68ch; }
.fsd-eligibility__list { margin: 0 0 var(--s-3); padding-left: 1.1rem; font-size: var(--t-sm); color: var(--ink-soft); }
.fsd-eligibility__list li { margin-bottom: 4px; }

/* ------------------------------------------------------------ badges
   Locked badges carry their real progress, not a question mark — see
   views/achievements.php.
   ===================================================================== */
.fsd-badges { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--s-4); margin: var(--s-5) 0; }
.fsd-badge {
	display: flex; gap: var(--s-4); padding: var(--s-4);
	border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-raised);
}
.fsd-badge.is-earned { border-color: color-mix(in srgb, var(--ok) 34%, transparent); background: var(--ok-bg); }
.fsd-badge__mark {
	flex: none; width: 44px; height: 44px; border-radius: 50%;
	display: flex; align-items: center; justify-content: center;
	background: var(--bg-sunken); color: var(--ink-faint);
	font-family: var(--mono); font-size: .68rem; font-weight: 700;
}
.fsd-badge.is-earned .fsd-badge__mark { background: var(--ok); color: var(--on-accent); }
.fsd-badge__body { min-width: 0; flex: 1 1 auto; }
.fsd-badge__title { font-family: var(--font-display); font-size: 1.05rem; font-weight: 800; margin: 0 0 3px; }
.fsd-badge.is-earned .fsd-badge__title { color: var(--ok); }
.fsd-badge__note { font-size: var(--t-sm); color: var(--ink-soft); margin: 0 0 var(--s-3); }
.fsd-badge.is-earned .fsd-badge__note { margin-bottom: 0; }
.fsd-badge__prog { font-size: var(--t-xs); color: var(--ink-faint); margin-top: 4px; }

/* ------------------------------------------------- measured difficulty
   Never a declared tag — correct/seen across everyone who answered, and
   only shown past Difficulty::MIN_SEEN. See src/Difficulty.php.
   ===================================================================== */
.fsd-diff {
	display: inline-flex; align-items: center; gap: 7px; flex-wrap: wrap;
	margin-bottom: var(--s-3); padding: 4px 10px;
	border-radius: var(--r-full); background: var(--bg-sunken);
	font-size: var(--t-xs); font-weight: 650;
}
.fsd-diff__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-faint); }
.fsd-diff.is-easy   { color: var(--ok); }
.fsd-diff.is-easy   .fsd-diff__dot { background: var(--ok); }
.fsd-diff.is-medium { color: var(--warn); }
.fsd-diff.is-medium .fsd-diff__dot { background: var(--warn); }
.fsd-diff.is-hard   { color: var(--bad); }
.fsd-diff.is-hard   .fsd-diff__dot { background: var(--bad); }
.fsd-diff__n { font-weight: 500; color: var(--ink-faint); }

/* ------------------------------------------------------ recently viewed
   Rendered by ui.js from localStorage, so it stays hidden until there is
   something real to put in it.
   ===================================================================== */
.fsd-recent { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--s-3); margin-bottom: var(--s-5); }
.fsd-recent__i {
	display: block; padding: var(--s-3) var(--s-4);
	border: 1px solid var(--line); border-radius: var(--r);
	background: var(--bg-raised); text-decoration: none; color: inherit;
	transition: border-color .14s ease;
}
.fsd-recent__i:hover { border-color: var(--accent); }
.fsd-recent__t { display: block; font-weight: 650; font-size: var(--t-sm); }
.fsd-recent__m { display: block; font-size: var(--t-xs); color: var(--ink-faint); margin-top: 2px; }

/* ---------------------------------------------------- saved questions
   Bookmarks and Notes. The star control sits under every reviewed answer;
   the cards below are the /bookmarks and /notes pages.
   ===================================================================== */
.fsd-save { margin-top: var(--s-3); }
.fsd-save > summary {
	cursor: pointer; font-size: var(--t-xs); color: var(--ink-faint);
	list-style: none; display: inline-flex; align-items: center; gap: 5px;
}
.fsd-save > summary::-webkit-details-marker { display: none; }
.fsd-save > summary:hover { color: var(--accent); }
.fsd-save__star { color: var(--line); font-size: .95rem; line-height: 1; }
.fsd-save.is-saved .fsd-save__star { color: var(--amber); }
.fsd-save.is-saved > summary { color: var(--ink-soft); font-weight: 650; }
.fsd-save__body { display: grid; gap: var(--s-3); margin-top: var(--s-3); max-width: 34rem; }
.fsd-save__body label { display: grid; gap: 4px; font-size: var(--t-xs); color: var(--ink-soft); }
.fsd-save__body label em { font-style: normal; color: var(--ink-faint); }
.fsd-save__body textarea {
	width: 100%; padding: 7px 9px; font: inherit; font-size: var(--t-sm);
	border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg);
}
.fsd-save__actions { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }
.fsd-save__msg { font-size: var(--t-xs); color: var(--ink-soft); }

.fsd-saved {
	padding: var(--s-5); margin-bottom: var(--s-4);
	border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-raised);
}
.fsd-saved__head { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-3); flex-wrap: wrap; }
.fsd-saved__type { font-family: var(--mono); font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-saved__q { font-size: var(--t-md); line-height: 1.6; }
.fsd-saved__img { max-width: 100%; margin-top: var(--s-3); border-radius: var(--r-sm); }
.fsd-saved__opts { margin: var(--s-3) 0 0; padding-left: 0; list-style: none; display: grid; gap: 5px; }
.fsd-saved__opts li { padding: 6px 10px; border-radius: var(--r-sm); background: var(--bg-sunken); font-size: var(--t-sm); }
.fsd-saved__opts li.is-answer { background: var(--ok-bg); color: var(--ok); font-weight: 650; }
.fsd-saved__opts b { font-family: var(--mono); margin-right: 6px; }
.fsd-saved__ans { font-size: var(--t-sm); margin: var(--s-3) 0 0; }
.fsd-saved__note {
	margin-top: var(--s-3); padding: var(--s-3) var(--s-4);
	border-left: 3px solid var(--amber); border-radius: 0 var(--r-sm) var(--r-sm) 0;
	background: var(--warn-bg);
}
.fsd-saved__note-label { font-size: var(--t-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--warn); margin-bottom: 3px; }
.fsd-saved__note p { margin: 0; font-size: var(--t-sm); }
.fsd-saved__foot {
	display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
	margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--line-soft);
	font-size: var(--t-xs);
}
.fsd-saved__when { color: var(--ink-faint); }
a.fsd-segtoggle__btn { text-decoration: none; display: inline-flex; align-items: center; }
a.fsd-segtoggle__btn.is-on { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }

/* ------------------------------------------------------ onboarding card
   Shown only to an account with no submitted attempt — the moment the
   dashboard has nothing to report and the student needs a first action.
   ===================================================================== */
.fsd-onboard {
	margin: var(--s-5) 0; padding: var(--s-5);
	border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
	border-radius: var(--r-lg); background: var(--accent-bg);
}
.fsd-onboard__h { font-family: var(--font-display); font-size: 1.25rem; font-weight: 800; margin: 0 0 var(--s-3); }
.fsd-onboard__steps { display: grid; gap: var(--s-3); margin: 0 0 var(--s-4); padding: 0; list-style: none; }
.fsd-onboard__steps li { display: flex; gap: var(--s-3); align-items: flex-start; font-size: var(--t-sm); }
.fsd-onboard__n {
	flex: none; width: 22px; height: 22px; border-radius: 50%;
	display: flex; align-items: center; justify-content: center;
	background: var(--accent); color: var(--on-accent);
	font-size: .68rem; font-weight: 800;
}

/* --------------------------------------------------------------- print
   The answer review is what students revise from, and it was screen-only.
   Everything that is navigation, promotion or interaction is dropped so a
   saved PDF is just the questions, answers and explanations.
   ===================================================================== */
@media print {
	.fsd-topbar, .fsd-ticker, .fsd-prompt, .fsd-foot, .fsd-appnav,
	.fsd-save, .fsd-report, .fsd-print, .fsd-filters, .fsd-next,
	.fsd-offer, .fsd-bundlepromo, .fsd-improve, .fsd-calc { display: none !important; }
	.fsd-appshell { display: block !important; }
	body { background: #fff !important; }
	.fsd-rev, .fsd-saved { break-inside: avoid; page-break-inside: avoid; border-color: #ccc !important; }
	a[href]::after { content: ''; }
	.fsd-wrap { max-width: none !important; padding: 0 !important; }
}

/* ------------------------------------------------- attempt comparison
   Shown after a retake, against the PREVIOUS attempt rather than the best
   one — see views/attempt.php for why.
   ===================================================================== */
.fsd-cmp {
	margin: var(--s-5) 0; padding: var(--s-4) var(--s-5);
	border-radius: var(--r); border: 1px solid var(--line); background: var(--bg-raised);
}
.fsd-cmp.is-up   { border-color: color-mix(in srgb, var(--ok) 32%, transparent); background: var(--ok-bg); }
.fsd-cmp.is-down { border-color: color-mix(in srgb, var(--bad) 28%, transparent); background: var(--bad-bg); }
.fsd-cmp__head { display: flex; align-items: baseline; gap: var(--s-3); flex-wrap: wrap; }
.fsd-cmp__delta { font-family: var(--font-display); font-size: 1.4rem; font-weight: 800; }
.fsd-cmp.is-up   .fsd-cmp__delta { color: var(--ok); }
.fsd-cmp.is-down .fsd-cmp__delta { color: var(--bad); }
.fsd-cmp__vs { font-size: var(--t-sm); color: var(--ink-soft); }
.fsd-cmp__facts { display: flex; gap: var(--s-5); flex-wrap: wrap; margin-top: var(--s-3); }
.fsd-cmp__facts b { font-family: var(--font-display); font-size: 1.15rem; margin-right: 6px; }
.fsd-cmp__facts b.is-bad { color: var(--bad); }
.fsd-cmp__facts span { font-size: var(--t-xs); color: var(--ink-faint); }

/* ------------------------------------------------------ report a question
   Collapsed by default: it belongs on every card but should never compete
   with the explanation the student came to read.
   ===================================================================== */
.fsd-report { margin-top: var(--s-3); border-top: 1px solid var(--line-soft); padding-top: var(--s-3); }
.fsd-report > summary {
	cursor: pointer; font-size: var(--t-xs); color: var(--ink-faint);
	list-style: none; display: inline-block;
}
.fsd-report > summary:hover { color: var(--accent); text-decoration: underline; }
.fsd-report > summary::-webkit-details-marker { display: none; }
.fsd-report__body { display: grid; gap: var(--s-3); margin-top: var(--s-3); max-width: 34rem; }
.fsd-report__body label { display: grid; gap: 4px; font-size: var(--t-xs); color: var(--ink-soft); }
.fsd-report__body label em { font-style: normal; color: var(--ink-faint); }
.fsd-report__body select,
.fsd-report__body textarea {
	width: 100%; padding: 7px 9px; font: inherit; font-size: var(--t-sm);
	border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--bg);
}
.fsd-report__send { justify-self: start; }
.fsd-report__msg { font-size: var(--t-xs); color: var(--ink-soft); margin: 0; min-height: 1em; }
.fsd-report.is-sent .fsd-report__body select,
.fsd-report.is-sent .fsd-report__body textarea,
.fsd-report.is-sent .fsd-report__send { display: none; }
.fsd-report.is-sent .fsd-report__msg { color: var(--ok); font-weight: 650; }

/* ============================================================= calculator
   The on-screen scientific calculator the real exam provides. Floats above
   the paper and is dragged by its title bar, because it will inevitably
   cover the question a candidate is trying to read.
   ========================================================================= */
.fsd-calc {
	position: fixed; top: 96px; right: 320px; z-index: 70;
	width: 268px; border-radius: 6px; overflow: hidden;
	background: #eef2f6; border: 1px solid #7d8b99;
	box-shadow: 0 10px 30px rgb(0 0 0 / .28);
	user-select: none;
}
.fsd-calc[hidden] { display: none; }
.fsd-calc__bar {
	display: flex; align-items: center; justify-content: space-between;
	padding: 5px 8px; background: #1d3a52; color: #fff;
	font-size: var(--t-xs); font-weight: 700; cursor: move;
}
.fsd-calc__x { background: none; border: 0; color: #fff; font-size: 1.1rem; line-height: 1; cursor: pointer; padding: 0 4px; }
.fsd-calc__screen { background: #dbe4ec; padding: 6px 8px; border-bottom: 1px solid #b6c3cf; }
.fsd-calc__mode { font-family: var(--mono); font-size: .6rem; color: #4a5c6d; letter-spacing: .06em; min-height: 12px; }
.fsd-calc__out {
	font-family: var(--mono); font-size: 1.05rem; font-weight: 700; color: #10202e;
	text-align: right; min-height: 26px; word-break: break-all; line-height: 1.3;
}
.fsd-calc__pad { display: grid; grid-template-columns: repeat(6, 1fr); gap: 3px; padding: 6px; }
.fsd-calc__k {
	padding: 7px 2px; font-size: .68rem; font-weight: 650; cursor: pointer;
	background: #fff; color: #1d3a52; border: 1px solid #a9b6c2; border-radius: 3px;
}
.fsd-calc__k:hover  { background: #dce6ef; }
.fsd-calc__k:active { background: #c6d4e0; }
.fsd-calc__k.is-num { background: #f7fafc; font-size: .8rem; font-weight: 750; }
.fsd-calc__k.is-eq  { background: #2e9e4f; border-color: #2e9e4f; color: #fff; }
.fsd-calc__k.is-clear { background: #d33b3b; border-color: #d33b3b; color: #fff; }

.fsd-cbt__tools { display: flex; align-items: center; gap: var(--s-2); }

/* Jump-to-question. */
.fsd-cbt__jump { display: flex; align-items: center; gap: 5px; font-size: var(--t-xs); color: #1d3a52; }
.fsd-cbt__jump input {
	width: 54px; padding: 4px 6px; font: inherit; font-size: var(--t-sm);
	text-align: center; border: 1px solid #9aa7b3; border-radius: 3px; background: #fff;
}

/* Pace warning — speaks only when time and questions left are out of step. */
.fsd-cbt__warn {
	flex: 1 1 auto; min-width: 0; text-align: center;
	font-size: var(--t-xs); font-weight: 650; color: #7a5b12;
}
.fsd-cbt__warn[hidden] { display: none; }
.fsd-cbt__warn.is-urgent { color: #b3261e; }
.fsd-cbt__warn.is-done { color: #2e7d4f; }

@media (max-width: 860px) {
	.fsd-calc { right: 8px; left: 8px; top: 64px; width: auto; }
}

/* =========================================================== exam terminal
   Laid out like the computer-based test a candidate will actually sit, so
   nothing has to be relearned on the day: exam band, candidate panel, section
   tabs, palette down the right with a counted legend, standard button row.

   The palette colours are the convention every Indian CBT shares — grey not
   visited, red seen but unanswered, green answered, purple marked, purple
   with a green dot for answered-and-marked. Those five are load-bearing:
   candidates navigate by them, so they are the one thing that must not be
   restyled to match our own palette.

   Deliberately no exam board's logo or wordmark anywhere here. The layout is
   a functional convention and is fair to reproduce; the branding is not, and
   copying it would also imply an official screen this is not.
   ========================================================================= */
.fsd-cbt { display: flex; flex-direction: column; height: 100vh; background: #f4f6f8; }

.fsd-cbt__band {
	flex: none; display: flex; align-items: stretch; gap: 0;
	background: #fff; border-bottom: 2px solid var(--accent);
}
.fsd-cbt__brand {
	display: flex; align-items: center; padding: 10px var(--s-4);
	font-family: var(--font-display); font-weight: 800; font-size: .95rem;
	color: var(--accent); border-right: 1px solid var(--line); white-space: nowrap;
}
.fsd-cbt__exam {
	flex: 1 1 auto; display: flex; align-items: center; justify-content: center;
	padding: 10px var(--s-4); text-align: center;
	background: #f5e6c8; color: #4a3a1a;
	font-family: var(--font-display); font-weight: 800; font-size: 1.05rem;
}
.fsd-cbt__org {
	display: flex; flex-direction: column; justify-content: center; align-items: flex-end;
	padding: 8px var(--s-4); background: var(--ink); color: var(--on-ink);
	font-size: var(--t-xs); font-weight: 700; white-space: nowrap;
}
.fsd-cbt__org span { font-weight: 500; opacity: .75; }
/* Shown only when a resumed attempt reloads outside fullscreen — resuming
   has no click of its own to request it from, so this supplies one. */
.fsd-cbt__nudge {
	flex: none; display: flex; align-items: center; padding: 8px var(--s-4);
	background: var(--accent); color: var(--on-accent); border: 0; cursor: pointer;
	font-size: var(--t-xs); font-weight: 700; white-space: nowrap;
}
.fsd-cbt__nudge:hover { filter: brightness(1.08); }

.fsd-cbt__strip {
	flex: none; display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-3); padding: 6px var(--s-4);
	background: #dfe7ef; border-bottom: 1px solid #c3d0dc;
}
.fsd-cbt__timer { font-size: var(--t-sm); font-weight: 650; color: #1d3a52; }
.fsd-cbt__timer b { font-family: var(--mono); font-size: 1.05rem; margin-left: 6px; }

.fsd-cbt__cols { flex: 1 1 auto; display: flex; min-height: 0; }
.fsd-cbt__left { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; background: #fff; }
.fsd-cbt__right {
	flex: none; width: 290px; display: flex; flex-direction: column;
	background: #fff; border-left: 1px solid #c3d0dc;
}

/* Candidate panel, top of the palette column — where every CBT puts it. */
.fsd-cbt__cand {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line);
}
.fsd-cbt__avatar {
	flex: none; width: 42px; height: 42px; border-radius: 4px;
	display: flex; align-items: center; justify-content: center;
	background: #c9d6e2; color: #1d3a52;
	font-family: var(--font-display); font-weight: 800; font-size: 1.1rem;
}
.fsd-cbt__candname { font-size: var(--t-sm); font-weight: 650; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* Counted legend. */
.fsd-cbt__legend {
	display: grid; grid-template-columns: 1fr 1fr; gap: 4px var(--s-2);
	padding: var(--s-3) var(--s-4); border-bottom: 1px solid var(--line);
	font-size: .68rem; color: var(--ink-soft);
}
.fsd-cbt__lg { display: flex; align-items: center; gap: 6px; }
.fsd-cbt__lg i {
	flex: none; width: 22px; height: 20px; font-style: normal;
	font-size: .66rem; font-weight: 700;
	display: flex; align-items: center; justify-content: center;
}

/* The five palette states. */
.fsd-pal.is-not-visited   { background: #fff; border: 1px solid #9aa7b3; color: #3a4a58; border-radius: 3px; }
.fsd-pal.is-not-answered  { background: #d33b3b; border-color: #d33b3b; color: #fff; border-radius: 3px 3px 14px 14px; }
.fsd-pal.is-answered      { background: #2e9e4f; border-color: #2e9e4f; color: #fff; border-radius: 14px 14px 3px 3px; }
.fsd-pal.is-review        { background: #6b3fa0; border-color: #6b3fa0; color: #fff; border-radius: 50%; }
.fsd-pal.is-review-answered {
	background: #6b3fa0; border-color: #6b3fa0; color: #fff; border-radius: 50%; position: relative;
}
.fsd-pal.is-review-answered::after {
	content: ''; position: absolute; right: -1px; bottom: -1px;
	width: 9px; height: 9px; border-radius: 50%;
	background: #2e9e4f; border: 1.5px solid #fff;
}
.fsd-cbt .fsd-pal.is-current { outline: 2px solid #1d3a52; outline-offset: 2px; }

.fsd-cbt__foot {
	flex: none; display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap;
	padding: var(--s-3) var(--s-4); border-top: 1px solid var(--line); background: #f4f6f8;
}
.fsd-cbt__spacer { flex: 1 1 auto; }
.fsd-cbt__b { font-size: var(--t-sm); font-weight: 650; padding: 8px 14px; border-radius: 4px; }
.fsd-cbt__b--review { background: #6b3fa0; color: #fff; border: 1px solid #6b3fa0; }
.fsd-cbt__b--clear  { background: #fff; color: var(--ink); border: 1px solid #9aa7b3; }
.fsd-cbt__b--prev   { background: #fff; color: var(--ink); border: 1px solid #9aa7b3; }
.fsd-cbt__b--save   { background: #2e9e4f; color: #fff; border: 1px solid #2e9e4f; }
.fsd-cbt__submit {
	margin: auto var(--s-4) var(--s-4); background: #1d3a52; color: #fff;
	border: 1px solid #1d3a52; font-weight: 700; border-radius: 4px; padding: 10px;
}

@media (max-width: 860px) {
	.fsd-cbt__org, .fsd-cbt__brand { display: none; }
	.fsd-cbt__right { position: fixed; inset: 0 0 0 auto; width: min(320px, 88vw); z-index: 60; box-shadow: var(--shadow-2); transform: translateX(100%); transition: transform .18s ease; }
	.fsd-cbt__right.is-open { transform: none; }
	.fsd-cbt__foot { gap: 6px; }
	.fsd-cbt__b { flex: 1 1 auto; }
}

/* ------------------------------------------------------------ price tag
   Struck former price beside the current one. The old price is muted and
   the new one carries the weight — the reverse (a loud struck price) is
   the pattern that makes a discount feel bigger than it is. See
   views/_price_tag.php for which figures are allowed in here at all.
   ========================================================================= */
.fsd-was { color: var(--ink-faint); font-weight: 500; margin-right: 4px; text-decoration-thickness: 1px; }
.fsd-now { font-weight: inherit; }
.fsd-off {
	display: inline-block; margin-left: 6px; padding: 1px 7px;
	border-radius: var(--r-full);
	background: var(--flash-1); color: #fff;
	font-family: var(--font); font-size: .62rem; font-weight: 800;
	letter-spacing: .03em; text-transform: uppercase; vertical-align: middle;
}
.fsd-paywall__offer {
	font-size: var(--t-sm); font-weight: 650; color: var(--flash-hi);
	margin: calc(var(--s-3) * -1) 0 var(--s-4);
}

/* ---------------------------------------------------------- bundle offer
   The saving on a single test that belongs to a bundle. Uses the same hot
   orange as the bundle band itself so the two read as one offer, but stays
   a thin strip — it is a cross-sell on someone else's card, not the
   headline. Never a struck-through price for the test itself: that price
   was never higher. See views/_bundle_offer.php.
   ========================================================================= */
.fsd-offer {
	display: flex; align-items: center; gap: var(--s-3);
	margin-top: var(--s-3); padding: var(--s-2) var(--s-3);
	border-radius: var(--r-sm);
	background: linear-gradient(90deg, var(--flash-1), var(--flash-2));
	color: #fff; text-decoration: none;
	font-size: var(--t-xs); line-height: 1.35;
}
.fsd-offer:hover { background: var(--flash-hi); }
.fsd-offer__pct {
	flex: none; font-weight: 800; letter-spacing: .02em;
	padding: 2px 8px; border-radius: var(--r-full);
	background: rgb(255 255 255 / .18);
}
.fsd-offer__text { min-width: 0; }
.fsd-offer__text s { opacity: .75; }
.fsd-offer__text b { font-weight: 800; }

/* On the paywall it is a full-width row above the buy button. */
.fsd-paywall__price + .fsd-offer { justify-content: center; margin: 0 auto var(--s-4); max-width: 26rem; }

/* Subjects on a home exam tile. */
.fsd-topics--tile { margin-bottom: var(--s-3); }
/* "+6 other optionals" — a count, not a section, so it reads as secondary. */
.fsd-topics--tile .is-more {
	background: transparent;
	border: 1px dashed var(--line);
	color: var(--ink-faint);
	font-style: italic;
}

/* ----------------------------------------------------------- community
   Aggregate, anonymous, cohort-gated. No user-generated content, so no
   author rows, no avatars and no vote controls to style. See
   src/Community.php for why this is not a discussion board.
   ===================================================================== */
.fsd-commsec { margin: var(--s-6) 0; }
.fsd-commsec .fsd-note { margin-top: 0; }

.fsd-commstats {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
	gap: var(--s-4); margin-top: var(--s-4);
}
.fsd-commstat {
	padding: var(--s-4); border: 1px solid var(--line);
	border-radius: var(--r-lg); background: var(--bg-raised);
}
.fsd-commstat__n {
	display: block; font-family: var(--font-display);
	font-size: 1.6rem; font-weight: 800; line-height: 1.1;
}
.fsd-commstat__l { display: block; margin-top: 4px; font-size: var(--t-xs); color: var(--ink-soft); }

.fsd-commlist { list-style: none; margin: var(--s-4) 0 0; padding: 0; }
.fsd-commrow {
	display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap;
	padding: var(--s-3) 0; border-bottom: 1px solid var(--line-soft);
}
.fsd-commrow:last-child { border-bottom: 0; }

/* Takes the leftover space so the figure on the right stays right. */
.fsd-commrow__main { flex: 1 1 240px; min-width: 0; }
.fsd-commrow__t {
	display: block; font-weight: 650; color: var(--ink); text-decoration: none;
	overflow-wrap: anywhere;
}
a.fsd-commrow__t:hover { color: var(--accent); text-decoration: underline; }
.fsd-commrow__m { display: block; margin-top: 2px; font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-commrow__pct { font-size: var(--t-xs); font-weight: 700; min-width: 3ch; text-align: right; }

/* .fsd-diff carries a bottom margin for its usual place under a question
   stem; inside a row it has to sit on the centre line instead. */
.fsd-commrow .fsd-diff { margin-bottom: 0; }
.fsd-commrow .fsd-bar { flex: 0 1 200px; }

@media (max-width: 640px) {
	.fsd-commrow .fsd-bar { flex-basis: 100%; }
}

/* ------------------------------------------------- house glyph legibility
   The house mark set is drawn in one colour, the accent #7F1D2D. Against
   the light paper that is a comfortable read; against the dark background
   it measures 1.88:1, where WCAG 1.4.11 asks 3:1 of a graphic. Every
   subject icon, the state FSO shields and the GATE mark were affected.

   brightness(1.7) takes it to 3.95:1, measured the same way - the mark
   drawn to a canvas under the identical filter and sampled. Chosen over
   a larger value on purpose: past about 1.8 the red channel clips at 255
   and the accent turns pink, which passes the check and loses the brand.

   Only the house glyphs are touched. The organisation logos carry their
   own colours, are not ours to alter, and a brightness filter would wash
   them out - Catalog::isHouseGlyph() decides which is which from the file
   itself, so the class is never applied to a real logo.

   Guarded with :not([data-theme="light"]) so an explicit light choice
   still beats a dark system preference, matching how the palette above
   is switched.
   ===================================================================== */
:root[data-theme="dark"] .fsd-mark--glyph { filter: brightness(1.7); }

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .fsd-mark--glyph { filter: brightness(1.7); }
}

/* ------------------------------------------------------- inline icon set
   CoreUI Icons Free, inlined by src/Icon.php. Filled, 512 viewBox, and
   painted with currentColor - so unlike the house marks in assets/marks/
   these need no dark-mode filter at all. They take the colour of whatever
   they sit in, in both themes, because an inline SVG can see the page.

   These replaced emoji, which is the point: emoji rendered differently on
   every device, could not take a token, and could not be recoloured. This
   is one fewer visual language on the page, not one more.

   Kept to interface furniture - status, trend, streak, save. Exam and
   subject identity stays with the outline house marks, so the two families
   never sit at the same level.
   ===================================================================== */
.fsd-icon {
	display: inline-block;
	/* Optical, not metric: sits the glyph on the text baseline rather than
	   on the line box, which otherwise rides visibly high next to text. */
	vertical-align: -0.14em;
	flex: none;
}

/* Anywhere an icon leads a line of text, the gap belongs to the container. */
.fsd-snap__tier,
.fsd-weekdots__streak,
.fsd-years__delta,
.fsd-segtoggle__btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
}

.fsd-segtoggle__btn { justify-content: center; }

/* The save star fills once saved — colour carries it, but the control also
   has a visible text label beside it, so colour is never the only signal. */
.fsd-save__star .fsd-icon { vertical-align: -0.16em; }
.fsd-foot__credit { margin-top: 4px; font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-foot__credit a { color: inherit; text-decoration: underline; }
.fsd-foot__credit a:hover { color: var(--ink-soft); }

/* ---------------------------------------------------------- daily challenge
   One decision on the card and one only. The whole point of the feature is
   that a student with five spare minutes doesn't have to choose what to
   study, so this must not offer them a menu.
   ===================================================================== */
.fsd-daily {
	border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
	background: var(--accent-bg);
	border-radius: var(--r); padding: var(--s-6); margin: var(--s-5) 0;
}
.fsd-daily.is-done { border-color: var(--line); background: var(--bg-raised); }

.fsd-daily__eyebrow {
	display: inline-flex; align-items: center; gap: 7px;
	font-size: var(--t-xs); font-weight: 680; letter-spacing: .08em;
	text-transform: uppercase; color: var(--accent); margin-bottom: var(--s-3);
}
.fsd-daily.is-done .fsd-daily__eyebrow { color: var(--ink-faint); }

.fsd-daily__h {
	font-family: var(--font-display); font-size: 1.65rem; font-weight: 800;
	line-height: 1.1; margin: 0 0 var(--s-2);
	display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
}
.fsd-daily__score { font-size: 2.6rem; }
.fsd-daily__score.is-ok   { color: var(--ok); }
.fsd-daily__score.is-warn { color: var(--warn); }
.fsd-daily__score.is-bad  { color: var(--bad); }
.fsd-daily__of { font-family: var(--font-ui, inherit); font-size: 1rem; font-weight: 500; color: var(--ink-soft); }

.fsd-daily__note { color: var(--ink-soft); margin: 0 0 var(--s-4); }
.fsd-daily__fine { margin-top: var(--s-3); margin-bottom: 0; }
.fsd-daily__actions { display: flex; gap: var(--s-3); flex-wrap: wrap; }

/* Wide enough to breathe on its own page, where it isn't sharing a header. */
.fsd-weekdots--wide { margin-top: var(--s-3); }

/* The dashboard's compact version of the same thing. */
.fsd-dailycard {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-4); flex-wrap: wrap;
	border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
	background: var(--accent-bg);
	border-radius: var(--r); padding: var(--s-4) var(--s-5); margin-bottom: var(--s-5);
}
.fsd-dailycard.is-done { border-color: var(--line); background: var(--bg-raised); }
.fsd-dailycard__t { font-weight: 680; display: flex; align-items: center; gap: 7px; }
.fsd-dailycard__m { font-size: var(--t-sm); color: var(--ink-soft); margin-top: 2px; }

@media (max-width: 560px) {
	.fsd-dailycard { flex-direction: column; align-items: stretch; }
	.fsd-dailycard .fsd-btn { width: 100%; justify-content: center; }
}

/* ------------------------------------------------------------ pace analysis
   Reads attempts.question_times, which the runner has been recording on
   every submit since the column was added and nothing had ever read.

   Every comparison is against the student's own median, never a target
   seconds-per-question: no such figure is published for these exams and
   inventing one would be a fabricated standard presented as fact.
   ===================================================================== */
.fsd-speed { margin: var(--s-6) 0; }
.fsd-speed .fsd-note:first-of-type { margin-top: 0; }
.fsd-speed__verdict {
	display: block; margin-top: 4px;
	font-size: var(--t-sm); color: var(--ink-soft);
}

.fsd-speed__tag {
	display: inline-flex; align-items: center; gap: 6px; flex: none;
	padding: 4px 10px; border-radius: var(--r-full);
	background: var(--bg-sunken);
	font-size: var(--t-xs); font-weight: 650; white-space: nowrap;
}
/* Four states, four colours — but each row also carries the verdict in
   words, so the colour is never the only thing saying it. */
.fsd-speed__tag.is-slow-weak    { color: var(--bad); }
.fsd-speed__tag.is-slow-strong  { color: var(--warn); }
.fsd-speed__tag.is-fast-weak    { color: var(--bad); }
.fsd-speed__tag.is-fast-strong  { color: var(--ok); }

@media (max-width: 560px) {
	.fsd-speed__tag { align-self: flex-start; }
}

/* ------------------------------------------------------------ personal best
   The one target on the site that needs nobody else — no cohort, no cutoff,
   no other candidate. It works on a student's first week, when percentile
   and rank still have nothing to say.
   ===================================================================== */
.fsd-pb {
	display: flex; align-items: center; gap: 10px;
	font-size: var(--t-sm); color: var(--ink-soft);
	margin: var(--s-4) 0;
}
.fsd-pb.is-new {
	gap: var(--s-4); padding: var(--s-4) var(--s-5);
	border: 1px solid color-mix(in srgb, var(--ok) 34%, transparent);
	background: var(--ok-bg); border-radius: var(--r); color: inherit;
}
.fsd-pb__mark {
	display: grid; place-items: center; flex: none;
	width: 40px; height: 40px; border-radius: var(--r-full);
	background: color-mix(in srgb, var(--ok) 18%, transparent); color: var(--ok);
}
.fsd-pb__h { font-weight: 720; color: var(--ok); }
.fsd-pb__m { font-size: var(--t-sm); color: var(--ink-soft); margin-top: 2px; }

/* --------------------------------------------------------- pick by time
   Answers "how long have I got", which a student can answer instantly,
   instead of "what should I study", which needs a decision first.

   Each card carries the paper's real length, never a rounded one: a card
   promising twenty minutes that opens a forty-minute paper either gets
   abandoned half-finished or teaches the student to distrust the number.
   ===================================================================== */
.fsd-timepick { margin-bottom: var(--s-5); }
.fsd-timepick__row {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: var(--s-3); margin-top: var(--s-2);
}
.fsd-timecard {
	display: flex; align-items: center; gap: var(--s-3);
	min-height: 62px; padding: var(--s-3) var(--s-4);
	border: 1px solid var(--line); border-radius: var(--r);
	background: var(--bg-raised); text-decoration: none; color: inherit;
	transition: border-color .15s ease, background .15s ease;
}
.fsd-timecard:hover { border-color: var(--accent); background: var(--accent-bg); }
.fsd-timecard__mins {
	flex: none; display: grid; place-items: center; line-height: 1;
	min-width: 52px; padding: 8px 6px; border-radius: var(--r-sm);
	background: var(--bg-sunken);
	font-family: var(--font-display); font-size: 1.3rem; font-weight: 800;
}
.fsd-timecard__mins span {
	display: block; margin-top: 2px;
	font-family: inherit; font-size: .6rem; font-weight: 600;
	letter-spacing: .08em; text-transform: uppercase; color: var(--ink-faint);
}
.fsd-timecard__body { min-width: 0; }
/* One line, clipped. These were 74px, 92px and 114px tall in the same
   column because each title wrapped to a different number of lines, and a
   ragged stack of near-identical cards is most of what reads as clumsy. */
.fsd-timecard__t {
	display: block; font-weight: 680; line-height: 1.35;
	white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fsd-timecard__m { display: block; margin-top: 3px; font-size: var(--t-xs); color: var(--ink-faint); }

/* ------------------------------------------------------- difficulty level
   The authored pitch of a mock, as a badge at the top of its card rather
   than a sentence inside its blurb. Three levels, three labels, three
   colours — so a series of five cards can be told apart at a glance
   instead of all opening with near-identical prose.

   Bright saturated fills with fixed dark ink. The fills do NOT change
   between light and dark, so their text must not either: a token only
   inverts correctly if the surface under it inverts too, which is the
   same rule --on-flash exists for. Measured 9.4:1, 10.0:1 and 5.3:1.

   Never rendered on a real previous-year paper. Those carry no difficulty
   key, because labelling an official exam's difficulty would be inventing
   a fact about somebody else's paper — see Catalog::summary().
   ===================================================================== */
:root {
	--lvl-easy:     #2bd576;
	--lvl-easy-ink: #06240f;
	--lvl-medium:     #ffc02e;
	--lvl-medium-ink: #2a1c00;
	--lvl-hard:       #ff4d6d;
	--lvl-hard-ink:   #2e0410;
}

.fsd-lvl {
	display: inline-flex; align-items: center;
	padding: 4px 11px; border-radius: var(--r-full);
	font-family: var(--mono); font-size: .64rem; font-weight: 800;
	letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
}
.fsd-lvl--easy { background: var(--lvl-easy); color: var(--lvl-easy-ink); }
.fsd-lvl--medium { background: var(--lvl-medium); color: var(--lvl-medium-ink); }
.fsd-lvl--hard   { background: var(--lvl-hard);   color: var(--lvl-hard-ink); }

/* ------------------------------------------------------ AI explanation
   An optional extra BELOW the human-written explanation, never instead of
   it. Only appears on a question the student got wrong, and only when a
   key is configured — with no key there is no button at all, rather than
   one that cannot do anything.

   Deliberately quiet: bordered and unfilled, so it reads as a footnote to
   the authoritative explanation above rather than competing with it.
   ===================================================================== */
.fsd-explain { margin-top: var(--s-3); }
.fsd-explain__ask { display: inline-flex; align-items: center; gap: 7px; }
.fsd-explain__out {
	margin-top: var(--s-3); padding: var(--s-4);
	border: 1px solid var(--line); border-left: 3px solid var(--accent);
	border-radius: var(--r-sm); background: var(--bg-sunken);
	font-size: var(--t-sm); line-height: 1.65; color: var(--ink-soft);
}
.fsd-explain__out p { margin: 0 0 var(--s-3); }
.fsd-explain__out p:last-child { margin-bottom: 0; }
.fsd-explain__out.is-quiet { border-left-color: var(--line); color: var(--ink-faint); }

/* ------------------------------------------------------ exam preferences
   Asked once at sign-up. Checkboxes rather than a dropdown because more
   than one is the normal case - a food-technology candidate sitting GATE XL
   very often sits FSSAI too - and a multi-select dropdown hides both the
   options and the fact that several are allowed.

   It personalises what appears first and never restricts what can be
   opened, so there is no wrong answer for a student to be stuck with.
   ===================================================================== */
.fsd-pickexams { border: 0; padding: 0; margin: 0 0 var(--s-4); }
.fsd-pickexams legend { display: block; width: 100%; padding: 0; margin-bottom: var(--s-2); font-weight: 600; }
.fsd-pickexams__opt {
	display: block; margin-top: 2px;
	font-size: var(--t-xs); font-weight: 500; color: var(--ink-faint);
}
.fsd-pickexams__grid {
	display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
	gap: 6px; margin-bottom: var(--s-2);
}
.fsd-pickexam {
	display: flex; align-items: center; gap: 9px;
	/* 44px tall: this is a tap target on a phone, not just a label. */
	min-height: 44px; padding: 6px 11px;
	border: 1px solid var(--line); border-radius: var(--r-sm);
	background: var(--bg-raised); cursor: pointer;
	font-size: var(--t-sm); line-height: 1.3;
	transition: border-color .14s ease, background .14s ease;
}
.fsd-pickexam:hover { border-color: var(--accent); }
.fsd-pickexam input { flex: none; width: 17px; height: 17px; accent-color: var(--accent); }
.fsd-pickexam:has(input:checked) { border-color: var(--accent); background: var(--accent-bg); }
.fsd-pickexam__name { min-width: 0; overflow-wrap: anywhere; }

/* --------------------------------------------------------- your exams
   The homepage strip for a signed-in student who told us what they sit.
   Promotes, never filters: everything else on the page is still there,
   this just puts their own exams at the top of it.
   ===================================================================== */
.fsd-yours { margin: 0 0 var(--s-6); }
.fsd-yours__head {
	display: flex; align-items: baseline; justify-content: space-between;
	gap: var(--s-3); flex-wrap: wrap; margin-bottom: var(--s-3);
}
.fsd-yours__edit { font-size: var(--t-xs); }
.fsd-yours__row {
	display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
	gap: var(--s-3);
}
.fsd-yourcard {
	display: flex; align-items: center; gap: var(--s-3);
	padding: var(--s-4); border: 1px solid var(--line);
	border-left: 3px solid var(--accent); border-radius: var(--r);
	background: var(--bg-raised); text-decoration: none; color: inherit;
	transition: border-color .14s ease, background .14s ease;
}
.fsd-yourcard:hover { background: var(--accent-bg); }
.fsd-yourcard img { flex: none; }
.fsd-yourcard__t { display: block; font-weight: 660; overflow-wrap: anywhere; }
.fsd-yourcard__m { display: block; margin-top: 2px; font-size: var(--t-xs); color: var(--ink-faint); }

/* ------------------------------------------------------- bundle banners
   A horizontally scrolling rail of one banner per exam.

   It is a real scroll container as well as an animated one: the animation
   is the default, but dragging, swiping and keyboard focus all work, and
   it pauses on hover and on focus-within. A moving target is not clickable,
   and one that slides away as somebody tabs onto it is worse than static.

   Every figure inside comes from the catalogue at render time. The design
   this was built from promised "10 Full Mock Tests + 20 Sectional Tests"
   for an exam with four mocks and one sectional, and struck through a ₹799
   that never existed - which is exactly why none of it is typed by hand.
   ===================================================================== */
.fsd-bnrrail {
	margin: 0 0 var(--s-6);
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scrollbar-width: none;
	/*
	 * Centers whichever banner renders first (FSSAI, per
	 * Catalog::inDisplayOrder()) in the rail at rest, rather than starting
	 * flush against the left edge. Matches the card's own width formula
	 * exactly (.fsd-bnr: width: min(560px, 86vw)) so it stays centered at
	 * every viewport, not just the one it was eyeballed at. Lives on the
	 * outer scroll container, not .fsd-bnrrail__track below — padding
	 * here only shifts where the animated track starts appearing, it
	 * doesn't touch the track's own width or the -50% loop math, which
	 * has to stay exact or the seam between the two duplicated copies
	 * becomes visible.
	 */
	padding-left: calc(50% - (min(560px, 86vw) / 2));
}
.fsd-bnrrail::-webkit-scrollbar { display: none; }

.fsd-bnrrail__track {
	/* No gap here on purpose: the two groups must be exactly equal halves
	   for translateX(-50%) to land on the seam. Each group carries its own
	   trailing gap instead. */
	display: flex; gap: 0; width: max-content;
	/* Slowed from 90s — a card was passing before there was time to read
	   it. */
	animation: fsd-bnr-scroll 160s linear infinite;
}
.fsd-bnrrail__group { display: flex; gap: var(--s-4); padding-right: var(--s-4); }
.fsd-bnrrail:hover .fsd-bnrrail__track,
.fsd-bnrrail:focus-within .fsd-bnrrail__track { animation-play-state: paused; }

@keyframes fsd-bnr-scroll {
	from { transform: translateX(0); }
	/* -50% lands exactly on the start of the duplicate copy, so the loop
	   has no visible seam. */
	to   { transform: translateX(-50%); }
}

.fsd-bnr {
	flex: none; width: min(560px, 86vw);
	display: flex; align-items: stretch; gap: var(--s-4);
	padding: var(--s-5);
	border: 1px solid var(--line); border-radius: var(--r);
	background: var(--bg-raised);
}
.fsd-bnr__main { flex: 1 1 auto; min-width: 0; }
.fsd-bnr__exam {
	font-family: var(--font-display); font-size: 1.5rem; font-weight: 900;
	line-height: 1.05; margin: 0; overflow-wrap: anywhere;
}
/* The same hot orange-to-red --flash gradient the ticker and bundle-promo
   badges already use for "act now" surfaces — a cycle year is exactly that:
   it is what makes "prep for 2026" read as a deadline, not a label, which is
   the whole point of putting it next to a buy button. The maroon --accent
   purchase button stays untouched; this is deliberately a different colour
   so the two don't compete for the same "click me" attention. */
.fsd-bnr__year {
	display: inline-block; vertical-align: middle; margin-left: 6px;
	padding: 2px 9px; border-radius: var(--r-full);
	background: linear-gradient(120deg, var(--flash-1), var(--flash-2));
	box-shadow: 0 2px 8px -2px color-mix(in srgb, var(--flash-1) 65%, transparent);
	font-family: var(--font-body); font-size: var(--t-xs); font-weight: 800;
	letter-spacing: .02em; color: var(--on-flash);
}
/* Larger heading context (series page h1) needs a touch more breathing room
   and a baseline nudge — the badge otherwise reads as glued to the text. */
.fsd-h1__year { margin-left: 10px; vertical-align: 4px; }
.fsd-bnr__kicker {
	display: inline-block; margin: 6px 0 var(--s-3); padding: 3px 10px;
	border-radius: var(--r-full); background: var(--accent); color: var(--on-accent);
	font-size: var(--t-xs); font-weight: 750; letter-spacing: .07em; text-transform: uppercase;
}
.fsd-bnr__stats { display: flex; gap: var(--s-4); flex-wrap: wrap; list-style: none; margin: 0 0 var(--s-3); padding: 0; }
.fsd-bnr__stats li { min-width: 0; }
.fsd-bnr__n { display: block; font-family: var(--font-display); font-size: 1.5rem; font-weight: 800; line-height: 1; }
.fsd-bnr__l { display: block; margin-top: 2px; font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-bnr__feats { list-style: none; margin: 0; padding: 0; font-size: var(--t-xs); color: var(--ink-soft); }
.fsd-bnr__feats li { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; }

.fsd-bnr__buy {
	flex: none; width: 156px;
	display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
	padding-left: var(--s-4); border-left: 1px solid var(--line-soft); text-align: center;
}
.fsd-bnr__price { font-family: var(--font-display); font-size: 2.1rem; font-weight: 900; line-height: 1; }
.fsd-bnr__was { font-size: var(--t-xs); color: var(--ink-faint); margin-bottom: 4px; }
/* The banner's own "Enrol now" button, not the site-wide --accent primary —
   it sits right under the flash-gradient year badge, so matching that
   gradient here (rather than the maroon every other primary button uses)
   keeps the year and the CTA reading as one "act now" unit instead of two
   different colours pulling attention in different directions. */
.fsd-bnr__cta {
	width: 100%; justify-content: center;
	background: linear-gradient(120deg, var(--flash-1), var(--flash-2));
	border-color: var(--flash-hi);
}
.fsd-bnr__cta:hover { background: var(--flash-hi); }

@media (max-width: 560px) {
	.fsd-bnr { flex-direction: column; }
	.fsd-bnr__buy {
		width: auto; flex-direction: row; justify-content: space-between; text-align: left;
		padding-left: 0; padding-top: var(--s-3);
		border-left: 0; border-top: 1px solid var(--line-soft);
	}
	.fsd-bnr__cta { width: auto; }
}

/* Somebody who has asked for less motion gets a rail they scroll
   themselves, not one that creeps while they read it. */
@media (prefers-reduced-motion: reduce) {
	.fsd-bnrrail__track { animation: none; }
}

/* ------------------------------------------------------------ card meta
   Replaces four blocks that made a card 482px tall and pushed its price
   377px below its title: a truncated blurb, a bullet list of the paper's
   own sections, a checklist identical on every card, and a two-column
   facts panel.

   Only what varies per paper survives. Everything removed was either the
   same on every card or a restatement of something already on it.
   ===================================================================== */
.fsd-card__meta {
	font-size: var(--t-xs); color: var(--ink-faint);
	margin: 4px 0 var(--s-4); line-height: 1.5;
}

/* The card itself tightens with its contents - the old padding was set
   for a much taller box. */
.fsd-card { padding: var(--s-4) var(--s-5); }
.fsd-card__title { font-size: var(--t-md); line-height: 1.25; margin-bottom: 0; }
.fsd-card__exam { margin-bottom: 6px; }
.fsd-card__badges { margin-bottom: 8px; }
.fsd-card__foot { margin-top: auto; padding-top: var(--s-3); }

/* The rail sits between the hero and the exam grid, so it keeps a little
   air above it as well as below. */
.fsd-bnrrail { margin-top: var(--s-5); }

/* -------------------------------------------------- a student's own series
   Where a bundle purchase lands. It shows nothing they do not own: no
   prices, no other exams, no upsell. They have paid; the useful thing now
   is the list of papers and a way in.
   ===================================================================== */
.fsd-srhead {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-5); flex-wrap: wrap;
	padding: var(--s-4) var(--s-5); margin-bottom: var(--s-4);
	border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-raised);
}
.fsd-srhead__prog { flex: 1 1 240px; min-width: 0; }
.fsd-srhead__count { font-family: var(--font-display); font-size: 1.5rem; font-weight: 800; margin-bottom: 6px; }
.fsd-srhead__count span { font-family: inherit; font-size: .85rem; font-weight: 500; color: var(--ink-soft); }
.fsd-srhead__facts { display: flex; gap: var(--s-5); flex-wrap: wrap; }
.fsd-srhead__facts b { display: block; font-family: var(--font-display); font-size: 1.25rem; font-weight: 800; }
.fsd-srhead__facts span { display: block; font-size: var(--t-xs); color: var(--ink-faint); }

.fsd-srnext {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-4); flex-wrap: wrap;
	padding: var(--s-4) var(--s-5); margin-bottom: var(--s-5);
	border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
	background: var(--accent-bg); border-radius: var(--r);
}
.fsd-srnext__label {
	font-size: var(--t-xs); font-weight: 700; letter-spacing: .08em;
	text-transform: uppercase; color: var(--accent); margin: 0 0 4px;
}
.fsd-srnext__t { font-weight: 680; margin: 0; overflow-wrap: anywhere; }
.fsd-srnext__m { font-size: var(--t-xs); color: var(--ink-faint); margin: 2px 0 0; }

.fsd-srlist { list-style: none; margin: 0; padding: 0; }
.fsd-srrow {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-4); flex-wrap: wrap;
	padding: var(--s-3) 0; border-bottom: 1px solid var(--line-soft);
}
.fsd-srrow:last-child { border-bottom: 0; }
.fsd-srrow__main { flex: 1 1 240px; min-width: 0; }
.fsd-srrow__t { display: block; font-weight: 650; overflow-wrap: anywhere; }
.fsd-srrow__m { display: block; margin-top: 2px; font-size: var(--t-xs); color: var(--ink-faint); }

/* A past paper sits in the full-length tab because that is what it is: a
   full-length paper. The tag keeps it from reading as something written here.
   The Free tag explains why a bought series lists more papers than the bundle
   charges for. */
.fsd-srtag {
	display: inline-block; vertical-align: 2px; margin-left: 6px;
	padding: 1px 7px; border-radius: 999px;
	font-family: var(--font); font-size: .6875rem; font-weight: 700;
	letter-spacing: .02em; text-transform: uppercase;
	color: var(--ink-soft); background: var(--bg-sunken);
	border: 1px solid var(--line-soft);
}
.fsd-srtag.is-free {
	color: var(--on-accent); background: var(--accent); border-color: var(--accent);
}
.fsd-srempty { margin: 0; padding: var(--s-4) 0; }

@media (max-width: 560px) {
	.fsd-srrow .fsd-btn, .fsd-srnext .fsd-btn { width: 100%; justify-content: center; }
}

/* -------------------------------------------- owned series, on the dashboard
   Progress measured against the bundle rather than the whole catalogue.
   Someone who paid for one exam is working through that exam; telling them
   they are "2 of 177 papers in" answers a question they did not ask.
   ===================================================================== */
.fsd-dseries {
	padding: var(--s-4) var(--s-5); margin-bottom: var(--s-4);
	border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
	background: var(--accent-bg); border-radius: var(--r);
}
.fsd-dseries__head {
	display: flex; align-items: baseline; justify-content: space-between;
	gap: var(--s-3); flex-wrap: wrap; margin-bottom: 6px;
}
.fsd-dseries__t { font-weight: 700; text-decoration: none; color: inherit; }
.fsd-dseries__t:hover { text-decoration: underline; }
.fsd-dseries__c { font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-dseries__next {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--s-3); flex-wrap: wrap; margin-top: var(--s-3);
	font-size: var(--t-sm); color: var(--ink-soft);
}
@media (max-width: 560px) {
	.fsd-dseries__next .fsd-btn { width: 100%; justify-content: center; }
}

/* ---------------------------------------------- settings, out of the way
   The exam picker is a preference, not a dashboard reading, and it was
   383px of checkboxes sitting in the scroll path on a phone. Collapsed by
   default; a <details> keeps it one tap away and keyboard-reachable
   without any script.
   ===================================================================== */
.fsd-fold { border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-raised); }
.fsd-fold > summary {
	cursor: pointer; list-style: none;
	display: flex; align-items: center; justify-content: space-between; gap: var(--s-3);
	padding: var(--s-4); font-weight: 700;
}
.fsd-fold > summary::-webkit-details-marker { display: none; }
.fsd-fold > summary::after {
	content: ""; flex: none; width: 9px; height: 9px;
	border-right: 2px solid var(--ink-faint); border-bottom: 2px solid var(--ink-faint);
	transform: rotate(45deg) translate(-2px, -2px); transition: transform .15s ease;
}
.fsd-fold[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
.fsd-fold > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.fsd-fold__body { padding: 0 var(--s-4) var(--s-4); }
.fsd-fold__hint { font-size: var(--t-xs); font-weight: 500; color: var(--ink-faint); }

/* ------------------------------------------------ banner rail, with arrows
   The rail is a marquee and a scroll container at once. Pressing an arrow
   freezes the animation where it stands (see bannerRail() in ui.js) and
   hands the rail over as an ordinary scroller -- stepping through something
   that is still sliding is worse than having no buttons.
   ===================================================================== */
.fsd-railwrap { position: relative; }
.fsd-bnrrail.is-manual .fsd-bnrrail__track { animation: none; }
/* No scroll-behavior here on purpose: with it set, assigning scrollLeft
   becomes a request for a smooth scroll, and in an engine that does not
   support one the rail never moves at all. bannerRail() in ui.js tweens the
   scroll itself and checks prefers-reduced-motion on the way. */

.fsd-railbtn {
	position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
	width: 40px; height: 40px; padding: 0;
	display: grid; place-items: center;
	border: 1px solid var(--line); border-radius: 50%;
	background: var(--bg-raised); color: var(--ink);
	box-shadow: 0 2px 10px rgb(0 0 0 / .14);
	cursor: pointer;
	transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.fsd-railbtn:hover { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
.fsd-railbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fsd-railbtn.is-prev { left: 10px; }
.fsd-railbtn.is-next { right: 10px; }

/* The chevron, drawn rather than shipped as an icon file. */
.fsd-railbtn span {
	width: 9px; height: 9px;
	border-top: 2px solid currentColor; border-right: 2px solid currentColor;
}
.fsd-railbtn.is-prev span { transform: rotate(-135deg); margin-left: 3px; }
.fsd-railbtn.is-next span { transform: rotate(45deg); margin-right: 3px; }

@media (max-width: 560px) {
	/* Smaller, and tucked in tighter, so they never cover a banner's price. */
	.fsd-railbtn { width: 34px; height: 34px; }
	.fsd-railbtn.is-prev { left: 4px; }
	.fsd-railbtn.is-next { right: 4px; }
}

/* ==========================================================================
   Testimonials — held in reserve for views/home.php's commented-out
   placeholder block. Not referenced by any rendered markup until that
   block is uncommented with verified student data; see the PHP comment
   above it for why it isn't live yet.
   ========================================================================== */

.fsd-testimonials { padding: var(--s-8) 0; }
.fsd-testimonials__title { font-size: var(--t-2xl); font-weight: 700; letter-spacing: -.02em; margin-bottom: var(--s-6); text-align: center; }
.fsd-testimonials__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-5); }
@media (max-width: 900px) { .fsd-testimonials__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .fsd-testimonials__grid { grid-template-columns: 1fr; } }
.fsd-testimonials__card {
	border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--bg-raised);
	padding: var(--s-5); box-shadow: var(--shadow-1); margin: 0;
}
.fsd-testimonials__card blockquote { margin: 0 0 var(--s-4); font-size: var(--t-base); line-height: 1.6; color: var(--ink); }
.fsd-testimonials__card figcaption { display: flex; flex-direction: column; gap: var(--s-1); }
.fsd-testimonials__name { font-weight: 660; }
.fsd-testimonials__meta { font-size: var(--t-xs); color: var(--ink-faint); }

/* ==========================================================================
   Exam Alert Center — homepage card, OPEN applications only, plus an email
   signup. No popup, no multi-column status stack.
   ========================================================================== */

.fsd-eacard {
	border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--bg-raised);
	padding: var(--s-5); margin: var(--s-6) 0; box-shadow: var(--shadow-1);
}
.fsd-eacard__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); margin-bottom: var(--s-4); flex-wrap: wrap; }
.fsd-eacard__title { font-size: var(--t-lg); font-weight: 700; }
.fsd-eacard__sub { font-size: var(--t-xs); color: var(--ink-faint); }
.fsd-eacard__empty { font-size: var(--t-xs); color: var(--ink-faint); }

.fsd-eacard__grid { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-bottom: var(--s-5); }
.fsd-eacard__tile {
	display: flex; flex-direction: column; gap: var(--s-2);
	flex: 1 1 260px; min-width: 0;
	border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3);
	color: var(--ink); background: var(--bg-sunken);
	transition: border-color .12s ease;
}
.fsd-eacard__tile:hover { border-color: var(--accent); }
.fsd-eacard__tilehead { display: flex; align-items: center; gap: var(--s-3); }
.fsd-eacard__tilemain { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.fsd-eacard__tilemain b { font-size: var(--t-sm); font-weight: 640; display: flex; align-items: center; gap: 6px; }
.fsd-eacard__tentative { font-style: normal; font-size: .68rem; font-weight: 650; letter-spacing: .03em; text-transform: uppercase; color: var(--warn); }
.fsd-eacard__count { flex: none; font-size: var(--t-xs); font-weight: 700; color: var(--accent); white-space: nowrap; }

/* Both dates, always — a tile that only ever showed the deadline left
   "when did this open" answerable only by clicking through to the
   official site, for the one piece of information the card exists to
   surface. */
.fsd-eacard__tiledates { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); font-size: .72rem; color: var(--ink-faint); padding-left: calc(28px + var(--s-3)); }
.fsd-eacard__tiledates b { font-weight: 640; color: var(--ink-soft); }

.fsd-eacard__tileactions { display: flex; flex-wrap: wrap; gap: var(--s-2); padding-left: calc(28px + var(--s-3)); margin-top: 2px; }
.fsd-eacard__tilelink {
	font-size: .72rem; font-weight: 660; text-decoration: none; color: var(--accent);
	white-space: nowrap;
}
.fsd-eacard__tilelink:hover { text-decoration: underline; }
.fsd-eacard__tilelink--official { color: var(--ink-soft); }
.fsd-eacard__tilelink--official:hover { color: var(--ink); }

.fsd-eacard__emailform { display: flex; gap: var(--s-3); flex-wrap: wrap; }
.fsd-eacard__emailform input {
	flex: 1 1 220px; min-width: 0;
	border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s-3);
	font-size: var(--t-sm); background: var(--bg-sunken); color: var(--ink);
}
.fsd-eacard__emailform input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.fsd-eacard__err { flex: 1 1 100%; color: var(--bad); font-size: var(--t-xs); margin: 0; }

