/* ============================================================================
   HOUSE OF ASPIRANTS - FREE COMPETITIVE EXAM LEARNING PLATFORM
   style.css  |  Design system, layout & reusable components
   Mobile-first. Light + Dark theme via CSS custom properties.
   ========================================================================== */

/* ---------------------------------------------------------------- 1. TOKENS */
:root {
  /* Brand palette */
  --brand: #4f46e5;
  --brand-2: #6366f1;
  --brand-3: #f97316;
  --brand-grad: linear-gradient(135deg, #6366f1 0%, #4f46e5 55%, #f97316 160%);

  /* Semantic colours */
  --success: #16a34a;
  --danger: #dc2626;
  /* Text-safe variants: WCAG AA on the tinted success/danger surfaces
     (chips, tags, badges) in light mode — see html[data-theme="dark"] below. */
  --success-text: #166534;
  --danger-text: #b91c1c;
  --warning: #f59e0b;
  --warning-text: #b45309;
  --info: #0ea5e9;

  /* Theme-dependent (light) */
  --bg: #f6f7fb;
  --bg-2: #eef1f8;
  --surface: #ffffff;
  --surface-2: #f9fafc;
  --text: #0f172a;
  --text-2: #475569;
  --muted: #646d7d;
  --border: #e6e9f2;
  --shadow: 0 10px 30px -12px rgba(15, 23, 42, 0.18);
  --shadow-lg: 0 24px 60px -24px rgba(15, 23, 42, 0.28);
  --ring: rgba(79, 70, 229, 0.35);
  --header-bg: rgba(255, 255, 255, 0.82);

  /* Shape / rhythm */
  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 22px;
  --r-xl: 30px;
  --container: 1200px;
  --header-h: 66px;
  /* Height of the announcement rail above the header. Declared as a token so
     the CLS reservation below stays pixel-exact with the rendered bar. */
  --ann-h: 36px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

html[data-theme="dark"] {
  --bg: #0b1020;
  --bg-2: #0f1730;
  --surface: #131a2e;
  --surface-2: #18203a;
  --text: #e8ecff;
  --text-2: #b4beda;
  --muted: #8b97b5;
  --border: #243050;
  /* Semantic text flips lighter so chips/tags stay AA on dark tints. */
  --success-text: #4ade80;
  --danger-text: #f87171;
  --warning-text: #fbbf24;
  --shadow: 0 12px 34px -14px rgba(0, 0, 0, 0.65);
  --shadow-lg: 0 30px 70px -26px rgba(0, 0, 0, 0.75);
  --ring: rgba(129, 140, 248, 0.45);
  --header-bg: rgba(11, 16, 32, 0.82);
}

/* ----------------------------------------------------------------- 2. RESET */
*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 12px);
}

body {
  font-family: "Inter", "Segoe UI", system-ui, -apple-system, Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  transition: background 0.35s var(--ease), color 0.35s var(--ease);
  /* Safety net: `clip` (not `hidden`) contains accidental sideways scrolling
     on phones WITHOUT turning body into a scroll container — which would
     break the sticky header. Every real overflow cause is fixed at source. */
  overflow-x: clip;
}

/* `hidden` must always win: several blocks below set an explicit display. */
[hidden] { display: none !important; }

img, svg { display: block; max-width: 100%; }
/* Long words / URLs / tokens can never widen a phone screen. */
p, li, td, th, h1, h2, h3, h4 { overflow-wrap: break-word; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; }
ul, ol { list-style: none; padding: 0; }

h1, h2, h3, h4 { line-height: 1.22; font-weight: 800; letter-spacing: -0.02em; }
h1 { font-size: clamp(2rem, 5vw, 3.1rem); }
h2 { font-size: clamp(1.5rem, 3.4vw, 2.2rem); }
h3 { font-size: clamp(1.1rem, 2.2vw, 1.35rem); }

/* Readable scale on a 320–430px screen: big enough to scan, small enough
   that a headline never eats three screens. */
@media (max-width: 559px) {
  h1 { font-size: clamp(1.72rem, 7.6vw, 2.15rem); }
  h2 { font-size: clamp(1.36rem, 6vw, 1.62rem); }
}

:focus-visible {
  outline: 3px solid var(--brand-2);
  outline-offset: 2px;
  border-radius: 6px;
}

::selection { background: var(--brand); color: #fff; }

/* ------------------------------------------------------------ 3. UTILITIES */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: 18px;
}
/* On the narrowest phones (iPhone SE class) those 18px per side were enough
   to push the fixed-width header actions off the right edge of the screen.
   Four more pixels of content width clears it without touching anything. */
@media (max-width: 359px) {
  .container { padding-inline: 14px; }
}

.section { padding: clamp(46px, 7vw, 84px) 0; }
.section-alt { background: var(--bg-2); }

.section-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 26px;
  flex-wrap: wrap;
}
.section-head p { color: var(--muted); margin-top: 6px; }

/* Stacked, full-width section heads on phones: the search field and the
   section CTA each get the whole row instead of fighting for half of it. */
@media (max-width: 719px) {
  .section-head { flex-direction: column; align-items: stretch; gap: 14px; margin-bottom: 22px; }
  .section-head > .btn { width: 100%; }
  .section-head .search-box,
  .search-box { width: 100%; min-width: 0 !important; }
  .search-box .kbd { display: none; } /* no keyboard on a phone */
  /* Input owns the full 54px height of the pill, so the whole field is the
     tap target rather than a 28px text line inside it. */
  .search-box { padding: 0 16px; min-height: 54px; }
  .search-box input { padding: 15px 0; }
}
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 10px;
}
.eyebrow::before {
  content: "";
  width: 22px;
  height: 3px;
  border-radius: 3px;
  background: var(--brand-grad);
}

.muted { color: var(--muted); }

/* Shown at ≥1000px only (desktop nav / hero art). Below that the header
   simply does not have room for it — phones carry Telegram in the bottom bar. */
.hide-sm { display: none !important; }
@media (min-width: 1000px) { .hide-sm { display: inline-flex !important; } }

/* In-content contextual links (articles, related-content modules, cross-links).
   a { color: inherit } globally, so prose links need an explicit treatment:
   brand colour + underline keeps them distinguishable (WCAG 1.4.1). */
.ilink {
  color: var(--brand);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1.5px;
}
a.ilink:hover { text-decoration-thickness: 3px; }
.text-sm { font-size: 0.875rem; }
.center { text-align: center; }
.hidden { display: none !important; }
.mt-1 { margin-top: 8px; } .mt-2 { margin-top: 16px; } .mt-3 { margin-top: 26px; }

.grid { display: grid; gap: clamp(16px, 3.4vw, 20px); }
/* MOBILE-FIRST: every grid starts as a single readable column and only
   becomes multi-column once the viewport can actually hold it. */
.grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }

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

.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 200;
  background: var(--brand); color: #fff; padding: 10px 16px;
  border-radius: 0 0 10px 10px; transition: top 0.2s;
}
.skip-link:focus { top: 0; }

/* --------------------------------------------------------------- 4. BUTTONS */
.btn {
  --btn-bg: var(--surface);
  --btn-fg: var(--text);
  --btn-bd: var(--border);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 12px 22px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.95rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1.5px solid var(--btn-bd);
  transition: transform 0.18s var(--ease), box-shadow 0.25s var(--ease),
    background 0.2s, border-color 0.2s, opacity 0.2s;
  white-space: nowrap;
}
.btn:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
.btn:active { transform: translateY(0); }
.btn:disabled, .btn[disabled] { opacity: 0.5; pointer-events: none; }

.btn-primary {
  background: var(--brand-grad);
  color: #fff;
  border-color: transparent;
  box-shadow: 0 12px 26px -14px rgba(79, 70, 229, 0.9);
}
.btn-ghost { background: transparent; }
.btn-soft { background: color-mix(in srgb, var(--brand) 12%, transparent); color: var(--brand); border-color: transparent; }
.btn-telegram { background: #1a7ba6; color: #fff; border-color: transparent; }
.btn-telegram:hover { background: #17709d; }
.btn-danger { background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger-text); border-color: transparent; }
.btn-success { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success); border-color: transparent; }
.btn-sm { padding: 9px 16px; font-size: 0.86rem; }
.btn-lg { padding: 15px 30px; font-size: 1.02rem; }
.btn-block { width: 100%; }

/* THUMB ZONE (phones only) — every control clears the 44px minimum touch
   target from WCAG 2.5.5 / Apple HIG without changing desktop density. */
@media (max-width: 719px) {
  .btn { min-height: 48px; padding: 12px 20px; font-size: 0.97rem; }
  .btn-sm { min-height: 42px; padding: 10px 17px; font-size: 0.89rem; }
  .btn-lg { min-height: 54px; padding: 15px 26px; font-size: 1.03rem; }
  /* Long labels wrap instead of pushing the layout sideways. */
  .btn { white-space: normal; text-align: center; }
}

.icon-btn {
  width: 44px; height: 44px; flex: none;
  display: inline-grid; place-items: center;
  border-radius: 12px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  color: var(--text-2);
  transition: all 0.2s var(--ease);
}
.icon-btn:hover { color: var(--brand); border-color: var(--brand); transform: translateY(-2px); }

.btn-row { display: flex; gap: 12px; flex-wrap: wrap; }
@media (max-width: 719px) {
  /* Chip rows become an evenly-sized grid instead of a ragged wrap of
     different-width pills — easier to scan and to hit. */
  .btn-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; }
  .btn-row .btn { width: 100%; }
}

/* ---------------------------------------------------------------- 5. BADGES */
.badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: 999px;
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.03em;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  color: var(--brand);
  border: 1px solid color-mix(in srgb, var(--brand) 24%, transparent);
}
.badge-success { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success-text); border-color: color-mix(in srgb, var(--success) 26%, transparent); }
.badge-warn { background: color-mix(in srgb, var(--warning) 16%, transparent); color: var(--warning); border-color: color-mix(in srgb, var(--warning) 30%, transparent); }
.badge-danger { background: color-mix(in srgb, var(--danger) 13%, transparent); color: var(--danger-text); border-color: color-mix(in srgb, var(--danger) 26%, transparent); }
.badge-muted { background: var(--surface-2); color: var(--muted); border-color: var(--border); }
/* Language availability pill (core.js langBadge). Tightened so it can sit
   beside a card title without shouting, and inherits .badge so it needs no
   colour rules of its own — including in dark mode. */
.badge-lang {
  padding: 2px 8px;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  vertical-align: middle;
  margin-left: 8px;
}

/* ---------------------------------------------------------------- 6. HEADER */
/* ANNOUNCEMENT RAIL — a thin credibility line above the sticky header on every
   page. It sits OUTSIDE .site-header on purpose: the header keeps its exact
   66px sticky height, so scroll-padding, sticky TOCs and .tg-rail offsets are
   untouched, and the rail simply scrolls away with the page. */
.ann-bar {
  height: var(--ann-h);
  background: var(--brand-grad);
  color: #fff;
  display: flex;
  align-items: center;
  overflow: hidden;
}
.ann-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(14px, 3vw, 40px);
  height: 100%;
}
.ann-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.ann-ico { font-size: 0.82rem; line-height: 1; }
/* Phones carry only the rank line — one line, one fixed height, no reflow. */
@media (max-width: 759px) {
  .ann-item { font-size: 0.7rem; }
  .ann-item:nth-child(n + 2) { display: none; }
  .ann-full { display: none; }
}
@media (max-width: 359px) { .ann-item { font-size: 0.66rem; } }

.site-header {
  position: sticky; top: 0; z-index: 90;
  background: var(--header-bg);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--border);
}
.header-inner {
  height: var(--header-h);
  display: flex; align-items: center; gap: 14px;
}
/* CLS: reserve the injected header's slot before core.js runs; exactly the
   rendered height (rail + header-inner + 1px border), so the filled state is
   pixel-identical. min-height is a floor only — real content always wins, and
   a no-JS visitor (noscript fallback) simply sees the rail's space unused. */
[data-site-header] { min-height: calc(var(--ann-h) + var(--header-h) + 1px); }
.brand { display: inline-flex; align-items: center; gap: 11px; font-weight: 800; min-width: 0; }
/* max-width:none keeps the mark square on narrow desktop windows: without it
   the brand row squeezes the image (38x38 -> 36x38) and the aspect ratio no
   longer matches. The word beside it is what gives way, not the logo. */
.brand-logo { width: 38px; height: 38px; flex: none; max-width: none; border-radius: 11px; box-shadow: var(--shadow); }
/* Logo has its own black background — give it an edge on the dark header. */
html[data-theme="dark"] .brand-logo { box-sizing: border-box; border: 1px solid var(--border); }
.brand-name { font-size: 1.02rem; letter-spacing: -0.02em; line-height: 1.1; min-width: 0; }
.brand-sub { display: block; font-size: 0.66rem; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase; color: var(--brand); }

@media (max-width: 559px) {
  .brand { gap: 9px; }
  /* Two short lines beat a truncated one — the brand always reads in full. */
  .brand-name { font-size: 0.94rem; line-height: 1.16; }
  .brand-sub { display: none; }
}

.main-nav { display: none; }
.nav-list { display: flex; align-items: center; gap: 2px; }
.nav-link {
  padding: 9px 13px; border-radius: 10px;
  font-size: 0.92rem; font-weight: 600; color: var(--text-2);
  transition: all 0.18s var(--ease);
}
.nav-link:hover { color: var(--brand); background: color-mix(in srgb, var(--brand) 9%, transparent); }
.nav-link.is-active { color: var(--brand); background: color-mix(in srgb, var(--brand) 11%, transparent); }

/* Subject dropdown */
.nav-drop { position: relative; }
.nav-drop-menu {
  position: absolute; top: calc(100% + 10px); left: 0;
  min-width: 250px; padding: 8px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); box-shadow: var(--shadow-lg);
  opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: all 0.2s var(--ease);
  max-height: min(70vh, 460px); overflow: auto;
}
.nav-drop.open .nav-drop-menu { opacity: 1; visibility: visible; transform: translateY(0); }
.nav-drop-menu a {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: 10px;
  font-size: 0.9rem; font-weight: 600;
}
.nav-drop-menu a:hover { background: color-mix(in srgb, var(--brand) 9%, transparent); color: var(--brand); }
.nav-drop-menu .cnt { margin-left: auto; font-size: 0.74rem; color: var(--muted); font-weight: 700; }
/* The global `img, svg { display: block }` reset (line 106) would otherwise
   push this caret onto a line of its own below its label — the dropdown button
   is inline-block, so a block-level child breaks the flow. Scope it back to
   inline so label and caret stay on the one row the nav expects. */
.nav-caret { display: inline-block; vertical-align: -1px; transition: transform 0.2s var(--ease); }
.nav-drop.open .nav-caret { transform: rotate(180deg); }

.header-actions { margin-left: auto; display: flex; align-items: center; gap: 8px; min-width: 0; }

@media (max-width: 559px) {
  .header-inner { gap: 8px; }
  .header-actions { gap: 7px; }
  /* The theme switch lives in the drawer on phones; keeping it here would
     squeeze the brand into an unreadable sliver on 320–390px screens. */
  .header-actions > [data-action="toggle-theme"] { display: none; }
}

/* ---------------------------- HOMEPAGE: PUNJABI-FIRST SECTIONS ------------
   Three components added for the Punjabi-first redesign (brief items 1, 3, 4).
   No new font, no new image and no extra request — grids plus the design
   tokens already on this page, so the performance budget is untouched. */

/* 1. Philosophy panel — "Learn in Punjabi. Compete Everywhere." */
/* `.card` is declared later in this sheet, so the panel needs to out-rank it
   for background and border to keep the brand-tinted wash. */
.card.lang-first {
  position: relative;
  overflow: hidden;
  display: grid;
  gap: 26px;
  background:
    radial-gradient(130% 150% at 100% 0%,
      color-mix(in srgb, var(--brand) 18%, transparent), transparent 62%),
    var(--surface);
  border: 1px solid color-mix(in srgb, var(--brand) 28%, var(--border));
}
@media (min-width: 900px) {
  .lang-first {
    grid-template-columns: minmax(0, 1.55fr) minmax(0, 0.9fr);
    align-items: center;
  }
}
.lang-first h2 { font-size: clamp(1.55rem, 3.4vw, 2.35rem); line-height: 1.15; margin: 10px 0 14px; }
.lang-first p { color: var(--text-2); max-width: 64ch; }
.lang-first-points { list-style: none; display: grid; gap: 10px; margin-top: 18px; }
.lang-first-points li {
  display: flex; gap: 10px; align-items: flex-start;
  font-weight: 600; color: var(--text);
}
.lang-first-points li::before {
  content: "✓"; flex: none;
  color: var(--brand); font-weight: 900; line-height: 1.45;
}
/* The demonstration panel: one sentence in both scripts, always both present. */
.lang-stack { display: grid; gap: 10px; }
.lang-stack-card {
  border-radius: 16px; padding: 16px;
  background: color-mix(in srgb, var(--brand) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--brand) 26%, transparent);
}
.lang-stack-card.is-en { background: var(--bg); border-color: var(--border); }
.lang-stack-card .ls-lang {
  font-size: 0.72rem; font-weight: 800; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--brand);
}
.lang-stack-card.is-en .ls-lang { color: var(--muted); }
.lang-stack-card .ls-text { margin-top: 6px; font-weight: 700; font-size: 1.02rem; }
.lang-stack-note { font-size: 0.82rem; color: var(--muted); text-align: center; }

/* 2. Feature cards */
.feature-grid { display: grid; gap: 16px; }
@media (min-width: 640px) { .feature-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .feature-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.feature-card { display: flex; flex-direction: column; gap: 8px; }
.feature-card .feat-ico {
  width: 46px; height: 46px; border-radius: 14px;
  display: grid; place-items: center; font-size: 1.3rem;
  background: color-mix(in srgb, var(--brand) 13%, transparent);
}
.feature-card h3 { font-size: 1.03rem; margin: 2px 0 0; }
.feature-card p { color: var(--muted); font-size: 0.93rem; margin: 0; }
.feature-card .feat-tag {
  margin-top: auto; padding-top: 12px;
  font-size: 0.72rem; font-weight: 800;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--brand);
}

/* ------------------------------------------------- FREE platform section -- */
/* "FREE" is set as a badge inside the heading, so the promise is the loudest
   thing in the card instead of a claim buried in the body copy. Brand gradient
   only — no new hues enter the palette. */
.free-badge {
  display: inline-block;
  padding: 2px 9px 3px;
  border-radius: 999px;
  background: var(--brand-grad);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.09em;
  line-height: 1.4;
  vertical-align: 2px;
  box-shadow: 0 4px 12px -6px rgba(79, 70, 229, 0.7);
}
.feat-link {
  margin-top: auto; padding-top: 12px;
  font-size: 0.85rem; font-weight: 700;
  color: var(--brand);
  text-decoration: none;
}
.feat-link::after { content: " →"; }
.feat-link:hover, .feat-link:focus-visible { text-decoration: underline; text-underline-offset: 3px; }

/* --------------------------------------------------------- Why choose us -- */
.why-grid {
  list-style: none;
  margin: 0; padding: 0;
  display: grid; gap: 14px;
}
@media (min-width: 700px) { .why-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .why-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.why-item {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 16px 18px;
  box-shadow: var(--shadow);
}
.why-check {
  flex: none;
  width: 26px; height: 26px;
  margin-top: 1px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: color-mix(in srgb, var(--success) 15%, transparent);
  color: var(--success-text);
  font-size: 0.82rem; font-weight: 900;
}
.why-item b { display: block; font-size: 0.97rem; line-height: 1.35; }
.why-item span { display: block; margin-top: 4px; font-size: 0.87rem; line-height: 1.55; color: var(--muted); }
/* Phones: one column, roomier tap area, no cramped 3-up. */
@media (max-width: 699px) { .why-item { padding: 14px 15px; } }

/* ---------------------------------------------- Proof of achievement ----- */
.proof-grid { display: grid; gap: 16px; }
@media (min-width: 640px) { .proof-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .proof-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* A <button>, so a keyboard user can open a document without a pointer. */
.proof-card {
  display: flex; flex-direction: column; gap: 11px;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  padding: 14px;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.proof-card:hover, .proof-card:focus-visible {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
}
.proof-thumb {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--bg-2);
  border: 1px solid var(--border);
}
.proof-thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.proof-zoom {
  position: absolute; right: 8px; bottom: 8px;
  padding: 4px 10px; border-radius: 999px;
  background: rgba(15, 23, 42, 0.74);
  backdrop-filter: blur(6px);
  color: #fff; font-size: 0.7rem; font-weight: 700;
}
a.proof-card { text-decoration: none; }
.proof-thumb-pdf { display: grid; place-items: center; }
.proof-pdf-icon {
  font-weight: 800; font-size: 1.4rem; letter-spacing: 0.06em;
  color: var(--brand);
  padding: 14px 18px; border-radius: var(--r-md);
  border: 2px solid currentColor;
}
.proof-badge { align-self: flex-start; font-size: 0.72rem; font-weight: 700; color: var(--muted); }
.proof-card h3 { margin: 0; font-size: 0.99rem; }
.proof-card p { margin: 0; font-size: 0.86rem; line-height: 1.55; color: var(--muted); }

/* Author rules always outrank the UA's [hidden] { display: none }, so the
   open state is expressed with :not([hidden]) rather than a bare display. */
.proof-lightbox { display: none; }
.proof-lightbox:not([hidden]) {
  position: fixed; inset: 0; z-index: 160;
  display: grid; place-items: center;
  padding: 20px;
  background: rgba(8, 11, 24, 0.88);
  backdrop-filter: blur(8px);
}
.proof-figure {
  margin: 0;
  display: flex; flex-direction: column; gap: 11px;
  max-width: min(940px, 94vw);
}
.proof-figure img {
  display: block;
  max-width: 100%; max-height: 76vh;
  margin-inline: auto;
  object-fit: contain;
  background: #fff;
  border-radius: var(--r-md);
}
.proof-caption { color: #e7eaf3; font-size: 0.9rem; line-height: 1.5; text-align: center; }
.proof-close {
  position: absolute; top: 16px; right: 18px;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.3);
  background: rgba(255, 255, 255, 0.12);
  color: #fff; font-size: 1.05rem; cursor: pointer;
}
.proof-close:hover, .proof-close:focus-visible { background: rgba(255, 255, 255, 0.24); }

/* 3. Trust section — claims only, no invented counters. */
.trust-grid { display: grid; gap: 16px; }
@media (min-width: 620px) { .trust-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .trust-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.trust-item { display: flex; flex-direction: column; gap: 8px; }
.trust-item .trust-ico { font-size: 1.5rem; }
.trust-item h3 { font-size: 1rem; margin: 0; }
.trust-item p { color: var(--muted); font-size: 0.92rem; margin: 0; }

/* ---------------------------------------------------------- LANGUAGE SWITCH
   PUNJABI FIRST. ENGLISH ALWAYS AVAILABLE.
   Both options sit at equal weight side by side — neither is styled as a
   fallback, a toggle-to or the "advanced" choice. Clears 24px on pointer and
   44px on touch, matching the thumb-zone rules used elsewhere in this sheet. */
.lang-switch {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 3px; flex: none;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 999px;
}
.lang-btn {
  appearance: none; -webkit-appearance: none;
  border: 0; background: transparent;
  font: inherit; font-size: 0.78rem; font-weight: 700;
  line-height: 1; color: var(--text-2);
  padding: 7px 11px; border-radius: 999px;
  cursor: pointer; white-space: nowrap;
  transition: background 0.18s var(--ease), color 0.18s var(--ease);
}
.lang-btn:hover { color: var(--brand); }
.lang-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.lang-btn.is-on {
  background: var(--brand); color: #fff;
  box-shadow: 0 5px 14px -8px color-mix(in srgb, var(--brand) 85%, transparent);
}
html[data-theme="dark"] .lang-btn.is-on { color: #fff; }
/* Short forms only on the narrowest phones, where the full words would push
   the brand into a sliver. The full labels stay in the DOM for screen readers. */
/* Short forms only where the full words would push the header past the
   screen: the actions row (language + search + menu) is fixed-width and the
   brand cannot shrink below its longest word, so full labels start causing a
   horizontal scroll around 430px. The full labels stay in the DOM for screen
   readers. */
.lang-short { display: none; }
@media (max-width: 719px) {
  .lang-btn { min-height: 44px; padding: 11px 13px; font-size: 0.82rem; }
}
@media (max-width: 449px) {
  .lang-btn { padding: 11px 12px; }
  .lang-full { display: none; }
  .lang-short { display: inline; }
}
/* Below ~380px the header's fixed-width actions still overran the screen
   even with the short language forms. The search glyph is the only one that
   can go without losing anything: the footer links to search.html, the same
   overlay, on every page. */
@media (max-width: 379px) {
  .header-actions > [data-action="open-search"] { display: none; }
}
.mm-head-actions { display: flex; align-items: center; gap: 8px; flex: none; }

/* Mobile menu */
.mobile-menu {
  position: fixed; inset: 0; z-index: 100;
  background: var(--bg);
  padding: 18px 16px calc(28px + env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  transform: translateX(100%);
  transition: transform 0.32s var(--ease);
  display: flex; flex-direction: column; gap: 6px;
}
.mobile-menu.open { transform: translateX(0); }
.mm-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 10px;
  position: sticky; top: -18px; background: var(--bg);
  padding: 18px 0 8px; z-index: 1;
}
.mm-title { font-weight: 800; }
.mm-group { font-size: 0.79rem; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); margin: 18px 0 6px; }
.mm-link {
  display: flex; align-items: center; gap: 12px;
  min-height: 48px;
  padding: 13px 14px; border-radius: 12px;
  font-weight: 600; background: var(--surface);
  border: 1px solid var(--border); margin-bottom: 8px;
  width: 100%; text-align: left;
}
.mm-link.is-active { border-color: var(--brand); color: var(--brand); }
.mm-link.mm-tg { color: #1a7ba6; }
html[data-theme="dark"] .mm-link.mm-tg { color: #4db6e8; }
.mm-emoji { font-size: 1.15rem; }

/* ------------------------------------------------------------------ 7. HERO */
.hero {
  position: relative;
  overflow: hidden;
  padding: clamp(48px, 8vw, 96px) 0 clamp(40px, 6vw, 74px);
  background:
    radial-gradient(900px 420px at 82% -10%, color-mix(in srgb, var(--brand) 22%, transparent), transparent 60%),
    radial-gradient(700px 400px at 6% 110%, color-mix(in srgb, var(--brand-3) 16%, transparent), transparent 62%),
    var(--bg);
}
.hero-grid {
  display: grid;
  gap: 34px;
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
}
.hero-tag {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 7px 15px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--border);
  font-size: 0.8rem; font-weight: 700; box-shadow: var(--shadow);
}
.pulse-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--success);
  animation: pulse 1.8s infinite;
}
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--success) 65%, transparent); }
  70% { box-shadow: 0 0 0 9px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.hero h1 { margin: 18px 0 6px; }
.hero h1 .grad {
  background: var(--brand-grad);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.hero-tagline {
  font-size: clamp(1.15rem, 2.6vw, 1.5rem);
  font-weight: 700; color: var(--text-2);
  margin-bottom: 10px;
}
.hero-sub { color: var(--muted); max-width: 56ch; margin-bottom: 24px; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 12px; }
/* Tertiary path to the daily drill — keeps "Start Free Quiz" one tap away
   without spending a third button on the two-CTA hierarchy above. */
.hero-alt { margin-top: 15px; font-size: 0.88rem; color: var(--muted); }
.hero-alt a { font-weight: 700; color: var(--brand); text-underline-offset: 3px; }

/* Hero language badges — the Punjabi/English promise, stated above the fold.
   Pill-shaped, token-coloured and large enough to read at a glance without
   competing with the two primary buttons directly above them. */
.lang-badges {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
}
.lang-badge {
  display: inline-flex;
  align-items: center;
  padding: 5px 13px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 0.8rem;
  font-weight: 800;
  line-height: 1.5;
}
.lang-badge.is-pa {
  border-color: color-mix(in srgb, var(--brand) 35%, transparent);
  background: color-mix(in srgb, var(--brand) 9%, transparent);
  color: var(--brand);
}
.lang-badge-note {
  font-size: 0.8rem;
  color: var(--muted);
  font-weight: 600;
}

/* PHONE HERO: less empty space, a headline that fits, and two full-width
   tap targets so the first action never needs a zoomed-in thumb. */
@media (max-width: 719px) {
  .hero { padding: clamp(30px, 7vw, 60px) 0 clamp(26px, 5vw, 44px); }
  .hero h1 { margin: 14px 0 8px; }
  .hero-sub { margin-bottom: 20px; font-size: 0.97rem; }
  .hero-cta { flex-direction: column; gap: 11px; }
  .hero-cta .btn { width: 100%; }
  .hero-tag { font-size: 0.76rem; padding: 7px 13px; }
}

/* ------------------------------------------------------ 7a. HERO MENTOR CARD
   The hero's right column is now the credibility proof instead of decorative
   float-cards. Same surface / border / radius / shadow language as every other
   card, and it stacks UNDER the copy on phones so both CTAs stay above the
   fold. .mentor-photo is display:none until home.js sees it load, so a missing
   founder portrait degrades to the designed credential card, not a
   broken image. */
.hero-visual { position: relative; }
.mentor-figure {
  position: relative;
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  padding: 13px;
}
.mentor-frame {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: calc(var(--r-xl) - 6px);
  overflow: hidden;
  background:
    radial-gradient(120% 90% at 20% 0%, color-mix(in srgb, #fff 26%, transparent), transparent 55%),
    var(--brand-grad);
  display: grid;
  place-items: center;
}
.mentor-photo {
  display: none;
  width: 100%; height: 100%;
  object-fit: cover;
}
.mentor-figure.has-photo .mentor-photo { display: block; }
.mentor-figure.has-photo .mentor-fallback { display: none; }
.mentor-fallback {
  display: flex; flex-direction: column; align-items: center; gap: 7px;
  color: #fff; text-align: center; padding: 18px;
}
.mentor-mono {
  font-size: clamp(3.2rem, 8vw, 4.6rem);
  font-weight: 800; letter-spacing: -0.04em; line-height: 1;
  text-shadow: 0 8px 28px rgba(15, 23, 42, 0.32);
}
.mentor-mono-sub {
  font-size: 0.72rem; font-weight: 800;
  letter-spacing: 0.18em; text-transform: uppercase; opacity: 0.92;
}
.mentor-caption {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 14px 5px 2px;
}
.mentor-id { display: flex; flex-direction: column; min-width: 0; }
.mentor-id strong { font-size: 1.04rem; letter-spacing: -0.015em; }
.mentor-id span { font-size: 0.8rem; color: var(--muted); font-weight: 600; margin-top: 2px; }
.mentor-stats {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  border-top: 1px solid var(--border);
  margin-top: 8px; padding-top: 13px;
}
.mentor-stats span {
  display: flex; flex-direction: column; gap: 2px;
  font-size: 0.72rem; color: var(--muted); font-weight: 600;
  text-align: center;
}
.mentor-stats b { font-size: 0.95rem; color: var(--text); font-weight: 800; }
/* Phones: a shorter frame keeps the card a supporting act, not the headline. */
@media (max-width: 899px) {
  .mentor-frame { aspect-ratio: 16 / 9; }
  .mentor-mono { font-size: clamp(2.6rem, 12vw, 3.4rem); }
}

/* ------------------------------------------------------ 7b. QUICK ACTIONS
   The homepage's whole job: five thumb-sized doors — Start Quiz, Daily Quiz,
   Notes, Leaderboard, Join Telegram — placed above everything else. */
.action-grid {
  display: grid;
  gap: clamp(12px, 3vw, 16px);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (max-width: 359px) { .action-grid { grid-template-columns: minmax(0, 1fr); } }
@media (min-width: 760px) { .action-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

.action-card {
  display: flex; flex-direction: column; gap: 4px;
  padding: 17px 16px 18px;
  min-height: 132px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  transition: transform 0.2s var(--ease), box-shadow 0.25s var(--ease), border-color 0.2s;
}
.action-card:hover, .action-card:focus-visible {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: color-mix(in srgb, var(--brand) 42%, var(--border));
}
.action-card:active { transform: translateY(-1px); }
.action-card .ac-ico {
  width: 44px; height: 44px; border-radius: 14px; flex: none;
  display: grid; place-items: center; font-size: 1.3rem; line-height: 1;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--brand) 26%, transparent);
  margin-bottom: 8px;
}
.action-card h3 { font-size: 1rem; line-height: 1.25; }
.action-card p { font-size: 0.8rem; line-height: 1.45; color: var(--muted); margin-top: 3px; }
.action-card .ac-go {
  margin-top: auto; padding-top: 10px;
  font-size: 0.78rem; font-weight: 800; color: var(--brand);
}

/* Primary = Start Quiz: the gradient marks the one action that matters most. */
.action-card.ac-primary {
  background: var(--brand-grad); color: #fff; border-color: transparent;
  box-shadow: 0 16px 34px -18px rgba(79, 70, 229, 0.95);
}
.action-card.ac-primary .ac-ico { background: rgba(255, 255, 255, 0.2); border-color: rgba(255, 255, 255, 0.38); }
.action-card.ac-primary p, .action-card.ac-primary .ac-go { color: rgba(255, 255, 255, 0.92); }

.action-card.ac-tg {
  background: linear-gradient(150deg, #1a7ba6 0%, #16759d 62%, #4f46e5 175%);
  color: #fff; border-color: transparent;
  box-shadow: 0 16px 34px -18px rgba(26, 123, 166, 0.9);
}
.action-card.ac-tg .ac-ico { background: rgba(255, 255, 255, 0.2); border-color: rgba(255, 255, 255, 0.38); }
.action-card.ac-tg p, .action-card.ac-tg .ac-go { color: rgba(255, 255, 255, 0.92); }

/* Fifth card owns the last (half-empty) mobile row instead of floating alone. */
.action-grid .ac-span { grid-column: 1 / -1; min-height: 0; }
@media (min-width: 760px) { .action-grid .ac-span { grid-column: auto; min-height: 132px; } }

/* --------------------------------------------------- 7c. BOTTOM MOBILE NAV
   Five destinations, one row, always under the thumb. Hidden once the full
   desktop nav takes over at ≥900px. */
.mobile-nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 96;
  display: none;
  background: var(--header-bg);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-top: 1px solid var(--border);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  box-shadow: 0 -10px 26px -18px rgba(15, 23, 42, 0.55);
}
.mobile-nav ul { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); }
.mn-link {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; min-height: 56px; padding: 8px 1px 7px;
  font-size: clamp(0.6rem, 2.8vw, 0.72rem);
  font-weight: 700; letter-spacing: -0.01em;
  color: var(--muted); text-align: center;
  transition: color 0.18s var(--ease);
}
.mn-ico { font-size: 1.16rem; line-height: 1; }
.mn-link span:last-child {
  max-width: 100%; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.mn-link:active { color: var(--brand); }
.mn-link.is-active { color: var(--brand); }
.mn-link.mn-tg { color: var(--tg-blue-text); }
@media (max-width: 899px) {
  .mobile-nav { display: block; }
  /* Content clears the fixed bar; safe-area keeps the iOS home indicator off. */
  body { padding-bottom: calc(56px + env(safe-area-inset-bottom, 0px)); }
}

/* --------------------------------------------------------------- 8. STAT BOX */
.stats-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
/* Stat cards are hidden when their value is unknown, so the count varies.
   A wrapping flex row keeps a leftover card full-width instead of stranded
   at half width in an otherwise empty grid row. */
@media (max-width: 639px) {
  .stats-grid { display: flex; flex-wrap: wrap; gap: 14px; }
  .stats-grid > * { flex: 1 1 calc(50% - 7px); }
}
.stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 20px 16px;
  text-align: center;
  box-shadow: var(--shadow);
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.stat-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-lg); }
.stat-emoji { font-size: 1.5rem; }
.stat-num {
  font-size: clamp(1.6rem, 4vw, 2.3rem);
  font-weight: 800; letter-spacing: -0.03em;
  background: var(--brand-grad);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.stat-label { font-size: 0.82rem; color: var(--muted); font-weight: 600; }

/* -------------------------------------------------------------- 9. CARD GRID */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease), border-color 0.25s;
}
.card-pad { padding: 22px; }
a.card:hover, .card.hoverable:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-lg);
  border-color: color-mix(in srgb, var(--brand) 40%, var(--border));
}

.subject-card { position: relative; overflow: hidden; padding: 24px 22px; display: block; }
.subject-card::after {
  content: ""; position: absolute; inset: auto -30% -60% auto;
  width: 180px; height: 180px; border-radius: 50%;
  background: var(--sc, var(--brand)); opacity: 0.09;
  transition: transform 0.4s var(--ease);
}
.subject-card:hover::after { transform: scale(1.35); }
.subject-icon {
  width: 54px; height: 54px; border-radius: 16px;
  display: grid; place-items: center;
  font-size: 1.5rem; font-weight: 800;
  background: color-mix(in srgb, var(--sc, var(--brand)) 15%, transparent);
  color: var(--sc, var(--brand));
  border: 1.5px solid color-mix(in srgb, var(--sc, var(--brand)) 32%, transparent);
  margin-bottom: 14px;
}
.subject-card h3 { margin-bottom: 6px; }
.subject-card p { color: var(--muted); font-size: 0.88rem; min-height: 42px; }
.subject-meta { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
/* Hierarchy cards (Region / Category / Sub Category inside a grouped subject)
   reuse .subject-card, .subject-icon and .subject-meta wholesale and add only
   the shelf's own "Open →" affordance, so a folder of folders is visibly the
   same object as a folder of files. */
.st-open { display: block; margin-top: 16px; font-weight: 800; font-size: 0.9rem; }

/* A grouped subject's chapter card carries two actions — Open PDF and the
   bookmark — so they share a row instead of the .study-card default of one
   full-width button per line. On a phone .btn-row already becomes a grid and
   each button takes a whole column, which is the target size a thumb wants. */
.study-card .btn-row .st-act { width: auto; flex: 1 1 140px; }

/* The reader's own saved chapters: one strip spanning the whole grid above
   the chapter list, drawn as a dashed outline so it never reads as material
   the site published. Hidden entirely when nothing has been starred. */
.st-saved {
  grid-column: 1 / -1;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px dashed var(--border);
  border-radius: var(--r-md);
}
.st-saved .eyebrow { margin-bottom: 6px; }
.st-saved .muted { font-size: 0.9rem; }
.st-saved-list {
  list-style: none; margin: 12px 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 8px;
}
.st-saved-list li {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 6px 5px 14px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.86rem;
}
.st-saved-list a { color: var(--text); font-weight: 600; text-decoration: none; }
.st-saved-list a:hover, .st-saved-list a:focus-visible { color: var(--brand); }
.st-saved-x {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 32px; min-height: 32px;
  border: 0; border-radius: 50%;
  background: transparent; color: var(--muted);
  font: inherit; line-height: 1; cursor: pointer;
}
.st-saved-x:hover, .st-saved-x:focus-visible {
  color: var(--danger);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
}

/* Quiz / topic card */
.quiz-card { padding: 18px 20px; display: flex; align-items: center; gap: 16px; }
.quiz-card .qc-icon {
  width: 46px; height: 46px; flex: none;
  border-radius: 13px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  font-size: 1.2rem;
}
.quiz-card h4, .quiz-card h3 { font-size: 1rem; margin-bottom: 3px; }
.quiz-card .qc-sub { font-size: 0.8rem; color: var(--muted); }
.quiz-card .qc-go {
  margin-left: auto; flex: none;
  width: 40px; height: 40px; border-radius: 12px;
  display: grid; place-items: center;
  background: var(--brand-grad); color: #fff;
  transition: transform 0.2s var(--ease);
}
a.quiz-card:hover .qc-go { transform: translateX(4px); }

/* Topic declared but its JSON file has no questions yet */
.quiz-card.disabled { opacity: 0.72; cursor: not-allowed; }
.quiz-card.disabled:hover { transform: none; box-shadow: var(--shadow); border-color: var(--border); }
.quiz-card.disabled .qc-icon { background: var(--surface-2); }
.quiz-card.disabled .qc-go { background: var(--surface-2); color: var(--muted); }

/* CATEGORY GROUP — a category that owns sub-categories renders them directly
   beneath it behind a rule, so General Knowledge reads as
   History -> Ancient / Medieval / Modern instead of ten sibling cards with no
   hint of the syllabus nesting. The group spans the full grid with the same
   `1 / -1` the empty state and footer already use, and the children are a
   plain `.grid.grid-3`, which carries the site's responsive column
   breakpoints — one set of breakpoints to maintain, not two. Same tokens,
   same cards: this adds structure, not a new visual language. */
.cat-group { grid-column: 1 / -1; display: grid; gap: clamp(14px, 2.6vw, 18px); }
.cat-group-kids {
  padding-left: clamp(14px, 3vw, 22px);
  border-left: 2px solid color-mix(in srgb, var(--brand) 26%, transparent);
}

/* Empty state */
.empty-state {
  grid-column: 1 / -1;
  text-align: center;
  padding: clamp(34px, 6vw, 58px) 22px;
  border: 2px dashed var(--border);
  border-radius: var(--r-xl);
  background: color-mix(in srgb, var(--surface) 70%, transparent);
}
.empty-state .es-icon {
  width: 68px; height: 68px; margin: 0 auto 16px;
  border-radius: 20px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--brand) 11%, transparent);
  font-size: 1.9rem;
}
.empty-state h3 { margin-bottom: 8px; }
.empty-state p { color: var(--muted); max-width: 52ch; margin-inline: auto; }
.empty-state code {
  background: var(--surface-2); border: 1px solid var(--border);
  padding: 3px 9px; border-radius: 7px; font-size: 0.85em;
}

/* ---------------------------------------------------------------- 10. SEARCH */
.search-overlay {
  position: fixed; inset: 0; z-index: 120;
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding: 12vh 18px 18px;
  overflow-y: auto;
  animation: fadeIn 0.18s var(--ease);
}
.search-panel { max-width: 640px; margin-inline: auto; }
.search-box {
  display: flex; align-items: center; gap: 10px;
  background: var(--surface); border: 1.5px solid var(--border);
  border-radius: 999px; padding: 11px 18px;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.search-box:focus-within { border-color: var(--brand); box-shadow: 0 0 0 4px var(--ring); }
.search-box input { flex: 1; border: 0; background: none; outline: none; min-width: 0; }
.search-box .kbd {
  font-size: 0.7rem; font-weight: 700; color: var(--muted);
  border: 1px solid var(--border); border-radius: 6px; padding: 2px 7px;
}
.search-results { display: grid; gap: 10px; margin-top: 18px; }

/* --------------------------------------------------------------- 11. BANNERS */
.banner-telegram {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 22px 24px;
  border-radius: var(--r-xl);
  background: linear-gradient(120deg, #1a7ba6 0%, #16759d 55%, #4f46e5 160%);
  color: #fff;
  box-shadow: 0 20px 44px -22px rgba(34, 158, 217, 0.9);
  position: relative; overflow: hidden;
}
.banner-telegram::after {
  content: ""; position: absolute; right: -50px; top: -50px;
  width: 190px; height: 190px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
}
.banner-telegram .bt-title { font-size: clamp(1.05rem, 2.4vw, 1.35rem); font-weight: 800; }
.banner-telegram .bt-sub { font-size: 0.9rem; opacity: 0.92; }
.banner-telegram .btn { background: #fff; color: #1478a8; border: 0; position: relative; z-index: 1; }

/* Advertisement slot (managed in HTML - never a popup) */
.ad-slot {
  border: 2px dashed var(--border);
  border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--surface) 65%, transparent);
  min-height: 110px;
  display: grid; place-items: center;
  text-align: center; padding: 18px;
  color: var(--muted);
}
.ad-slot .ad-label {
  font-size: 0.7rem; letter-spacing: 0.2em; text-transform: uppercase;
  font-weight: 800; color: var(--muted); margin-bottom: 4px;
}
/* An empty ad placeholder only costs phone users scroll depth — keep the
   slot for desktop until real creative exists. */
@media (max-width: 719px) { .ad-slot { display: none; } }

/* ---------------------------------------------------------------- 12. FOOTER */
.site-footer {
  margin-top: auto;
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding-top: 46px;
}
.footer-grid {
  display: grid; gap: 30px;
  grid-template-columns: minmax(0, 1fr);
  padding-bottom: 34px;
}
.footer-brand p { color: var(--muted); font-size: 0.9rem; margin-top: 12px; max-width: 40ch; }
/* Brief item 9 — the standing brand statement reads as a credo, so it gets the
   brand rule while the descriptive line under it keeps its quieter treatment. */
.footer-brand .footer-stand {
  color: var(--text-2);
  border-left: 3px solid var(--brand);
  padding-left: 12px;
}
.footer-col h4, .footer-col h2 {
  font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 14px;
}
.footer-col a {
  display: block; padding: 5px 0; font-size: 0.92rem;
  color: var(--text-2); transition: color 0.18s, transform 0.18s;
}
.footer-col a:hover { color: var(--brand); transform: translateX(4px); }

@media (max-width: 719px) {
  /* Rows become real tap targets instead of a dense link list. */
  .footer-col a { padding: 12px 0; font-size: 0.97rem; border-bottom: 1px solid var(--border); }
  .footer-col a:last-child { border-bottom: 0; }
  .footer-col h4, .footer-col h2 { margin-bottom: 6px; }
}
/* Shorter footer on phones: brand first, then the three link columns in two
   columns — roughly half the scrolling. */
@media (min-width: 480px) and (max-width: 899px) {
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 20px; }
  .footer-brand { grid-column: 1 / -1; }
}
.social-row { display: flex; gap: 10px; margin-top: 16px; flex-wrap: wrap; }
.social-link {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 15px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: 0.85rem; font-weight: 700;
  transition: all 0.2s var(--ease);
}
.social-link:hover { border-color: var(--brand); color: var(--brand); transform: translateY(-2px); }
.footer-bottom {
  border-top: 1px solid var(--border);
  padding: 18px 0;
  display: flex; flex-wrap: wrap; gap: 10px 20px;
  align-items: center; justify-content: space-between;
  font-size: 0.85rem; color: var(--muted);
}
.footer-bottom nav { display: flex; gap: 18px; flex-wrap: wrap; }
.footer-bottom a:hover { color: var(--brand); }
@media (max-width: 719px) {
  /* Legal links are 22px tall by default — far below a usable target. */
  .footer-bottom { justify-content: center; gap: 6px 14px; text-align: center; }
  .footer-bottom nav a { display: inline-block; padding: 12px 4px; }
}

/* ------------------------------------------------------------ 13. PAGE HERO */
.page-hero {
  padding: clamp(30px, 5vw, 54px) 0 clamp(20px, 3vw, 30px);
  background:
    radial-gradient(700px 300px at 90% -40%, color-mix(in srgb, var(--brand) 20%, transparent), transparent 60%),
    var(--bg-2);
  border-bottom: 1px solid var(--border);
}
.breadcrumb { display: flex; gap: 8px; align-items: center; font-size: 0.84rem; color: var(--muted); margin-bottom: 12px; flex-wrap: wrap; }
/* A breadcrumb trail is the way back out, so it has to be tappable with a
   thumb: a bare inline link boxes at the font's own ascent (~22px), under the
   24px floor. Giving the flex item a minimum height grows the row by four
   pixels and nothing else. */
.breadcrumb a { display: inline-flex; align-items: center; min-height: 26px; }
.breadcrumb a:hover { color: var(--brand); }
.breadcrumb span { opacity: 0.6; }

/* --------------------------------------------------------- 14. TOAST + misc */
.toast-wrap {
  position: fixed; left: 50%; bottom: 26px; z-index: 150;
  transform: translateX(-50%);
  display: flex; flex-direction: column; gap: 10px; align-items: center;
  pointer-events: none;
}
@media (max-width: 899px) {
  .toast-wrap { bottom: calc(68px + env(safe-area-inset-bottom, 0px)); }
}
.toast {
  background: var(--text); color: var(--bg);
  padding: 11px 20px; border-radius: 999px;
  font-size: 0.88rem; font-weight: 700;
  box-shadow: var(--shadow-lg);
  animation: toastIn 0.3s var(--ease);
}
@keyframes toastIn {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Scroll reveal */
.reveal { opacity: 0; transform: translateY(26px); transition: opacity 0.6s var(--ease), transform 0.6s var(--ease); }
.reveal.in { opacity: 1; transform: none; }

/* Back to top */
.to-top {
  position: fixed; right: 18px; bottom: 18px; z-index: 80;
  opacity: 0; pointer-events: none;
  transition: opacity 0.25s, transform 0.25s;
  transform: translateY(12px);
}
@media (max-width: 899px) {
  /* Sit above the fixed bottom nav instead of underneath it. */
  .to-top { right: 14px; bottom: calc(66px + env(safe-area-inset-bottom, 0px)); }
}
.to-top.show { opacity: 1; pointer-events: auto; transform: none; }

/* Skeleton loading */
.skeleton {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--border) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.3s infinite;
  border-radius: var(--r-md);
}
@keyframes shimmer { to { background-position: -135% 0; } }

/* ------------------------------------------------------------ 15. RESPONSIVE
   Breakpoints are driven by available space, not by device names:
     ≤559  phone        1 column, thumb-sized controls, bottom nav
     ≥560  large phone  2-column card grids
     ≥640  small tablet 3-4 column card grids
     ≥900  desktop      full nav, hero art, sidebar rails
   -------------------------------------------------------------------------- */
@media (min-width: 560px) {
  .grid-2, .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 640px) {
  .stats-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .subjects-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 900px) {
  .container { padding-inline: 26px; }
  .main-nav { display: block; }
  .menu-toggle, .mobile-nav { display: none; }
  .hero-grid { grid-template-columns: minmax(0, 1.08fr) minmax(0, 0.92fr); }
  .hero-visual { min-height: 340px; }
  .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .subjects-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .footer-grid { grid-template-columns: 1.35fr 1fr 1fr 1fr 1.1fr; }
}

/* -------------------------------------------------------- TWO-TIER HEADER
   Measured constraint: .container is hard-capped at 1200px, so the header row
   has exactly 1148px of content width at ANY viewport — a 2560px monitor gets
   no more room than a 1200px laptop. In English the brand (logo + wordmark),
   the gaps and the action cluster (language, search, theme, Telegram) consume
   640px of that, leaving 508px, and the nine desktop items measure 799px. The
   ten-item top nav and the wordmark therefore cannot share one line: the gap
   was 291px, not something padding could close.

   So .header-inner wraps instead of shrinking. Row 1 is the brand and the
   actions; row 2 is the whole navigation at its natural 799px — which also
   fits at the 900px breakpoint (848px of budget), so no item is ever
   truncated, dropped into a submenu or scrolled sideways. Because the brand
   no longer competes for the first row, the wordmark can stay at every
   desktop width and the old rule that hid it between 900–1199px goes away.

   Mobile (<900px) is untouched: one 66px row, drawer for everything, which is
   what 95% of readers see. */
@media (min-width: 900px) {
  :root { --header-h: 88px; }
  .header-inner { flex-wrap: wrap; align-content: center; row-gap: 0; }
  .brand { order: 1; }
  .header-actions { order: 2; }
  .main-nav { order: 3; flex: 1 0 100%; }

  /* Nav links stay at tightened padding: the second row still has to fit
     inside 848px at the 900px floor. Measured in English the nine items plus
     their two carets span 846px at 8px side padding — 2px of slack, which is
     no slack at all once a locale or a fallback font shifts a glyph. 6px
     brings it to ~810 and leaves ~38px, enough that the row can never be
     squeezed into wrapping its caret again. */
  .nav-link { padding: 9px 6px; font-size: 0.87rem; }
  .nav-list { gap: 1px; }
}

/* Column headings inside the Study and Practice dropdowns. Each one now
   carries two trees — the subject list and that system's own material — so
   the reader can see which is which before scanning either. */
.nav-col-head {
  display: block; padding: 7px 12px 3px;
  font-size: 0.68rem; font-weight: 800; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--muted);
}

@media (min-width: 1100px) {
  .subjects-layout { grid-template-columns: minmax(0, 1fr) 320px; align-items: start; }
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* Print */
@media print {
  .site-header, .site-footer, .to-top, .toast-wrap, .ad-slot,
  .tg-float, .tg-exit-overlay, .banner-telegram, .ann-bar,
  .live-ribbon { display: none !important; }
}

/* ==========================================================================
 * STUDENT ACCESS FLOW — auth modal, Google button, account card (auth.js)
 * ========================================================================== */
html.auth-open, html.auth-open body { overflow: hidden; }

.auth-overlay {
  position: fixed; inset: 0; z-index: 150;
  display: grid; place-items: center;
  padding: 20px;
  background: color-mix(in srgb, var(--bg) 55%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  animation: authFade 0.2s var(--ease);
}
@keyframes authFade { from { opacity: 0; } to { opacity: 1; } }

.auth-modal {
  position: relative;
  width: min(440px, 100%);
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 28px 26px 26px;
  box-shadow: var(--shadow-lg);
  animation: authIn 0.24s var(--ease);
}
@keyframes authIn {
  from { opacity: 0; transform: translateY(16px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.auth-close { position: absolute; top: 10px; right: 10px; }
.auth-close:disabled { opacity: 0.5; cursor: not-allowed; }

.auth-title {
  font-size: 1.22rem; line-height: 1.3;
  margin: 2px 34px 8px 0;
}
.auth-tagline { color: var(--muted); font-size: 0.95rem; margin: 0; }
.auth-benefits-label {
  font-size: 0.8rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-2); margin: 18px 0 10px;
}
.auth-benefits { list-style: none; display: grid; gap: 8px; margin: 0 0 18px; padding: 0; }
.auth-benefits li {
  display: flex; gap: 10px; align-items: flex-start;
  font-size: 0.92rem; color: var(--text-2); line-height: 1.45;
}
.auth-benefits li::before {
  content: "✔"; color: var(--brand); font-weight: 800; flex: none;
}

.auth-error {
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger) 35%, transparent);
  color: var(--danger-text);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  font-size: 0.88rem; line-height: 1.45;
  margin-bottom: 14px;
}

.btn-google {
  width: 100%; justify-content: center; gap: 10px;
  background: #ffffff; color: #3c4043;
  border: 1px solid #dadce0;
  font-weight: 600; letter-spacing: 0.01em;
  padding: 13px 18px;
}
.btn-google:hover {
  background: #f8faff; border-color: #c6dafc;
  box-shadow: 0 1px 3px rgba(60,64,67,0.15);
}
.btn-google:focus-visible { outline: 3px solid var(--ring); outline-offset: 2px; }
.btn-google:disabled { opacity: 0.85; cursor: progress; }
.g-logo { flex: none; }
.btn-google.is-loading .g-logo { display: none; }
.btn-google.is-loading::before {
  content: ""; flex: none; box-sizing: border-box;
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid #dadce0; border-top-color: var(--brand);
  animation: gSpin 0.7s linear infinite;
}
@keyframes gSpin { to { transform: rotate(360deg); } }

.auth-preview {
  margin: 14px 0 0; text-align: center;
  font-size: 0.78rem; color: var(--muted); line-height: 1.5;
}

/* ---------------------------------------------------- account card ------- */
.auth-account {
  display: flex; flex-wrap: wrap; gap: 14px; align-items: center;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 16px 18px;
  box-shadow: var(--shadow);
}
.aa-avatar {
  width: 46px; height: 46px; flex: none; border-radius: 50%;
  object-fit: cover; overflow: hidden;
  display: grid; place-items: center;
  background: var(--brand-grad); color: #fff;
  font-weight: 800; font-size: 1.15rem;
}
.aa-avatar img { width: 100%; height: 100%; object-fit: cover; }
.aa-initial { display: grid; place-items: center; width: 100%; height: 100%; }
.aa-meta { min-width: 0; flex: 1 1 180px; }
.aa-name { font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
.aa-sub { color: var(--muted); font-size: 0.85rem; overflow-wrap: anywhere; }
.aa-preview { color: var(--warning-text); }
.aa-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---------------------------------------------------- header chip --------- */
.auth-chip img {
  width: 20px; height: 20px; border-radius: 50%; object-fit: cover;
  display: block;
}
.auth-chip .auth-chip-face, .auth-chip span:not([class]) {
  display: grid; place-items: center; width: 20px; height: 20px;
  border-radius: 50%; background: var(--brand-grad); color: #fff;
  font-size: 0.78rem; font-weight: 800;
}
@media (max-width: 719px) { .auth-chip { display: none !important; } }

/* ==========================================================================
 * TELEGRAM GROWTH & STUDENT CONVERSION SYSTEM
 * Mentor credibility, value-prop grid, desktop rail, rotating banners,
 * dashboard/resource cards, leaderboard boost, footer block, floating
 * button and exit-intent popup.
 * Accent = --tg-blue (#1a7ba6): the only Telegram blue that passes WCAG AA
 * with white text (4.74:1). Raw #229ED9 is 3.02:1 — never carry text on it.
 * ========================================================================== */
:root {
  --tg-blue: #1a7ba6;
  --tg-blue-hover: #17709d;
  --tg-blue-text: #14698c;
}
html[data-theme="dark"] {
  --tg-blue: #1a7ba6;
  --tg-blue-hover: #1b86b5;
  --tg-blue-text: #5cc3ec;
}

@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

/* ------------------------------------------------------- mentor credibility */
.mentor-card {
  position: relative; overflow: hidden;
  display: flex; gap: clamp(18px, 3vw, 34px); flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-xl); box-shadow: var(--shadow);
  padding: clamp(22px, 3.4vw, 34px);
}
.mentor-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 4px;
  background: linear-gradient(90deg, var(--tg-blue), var(--brand));
}
.mentor-avatar {
  width: clamp(78px, 12vw, 104px); height: clamp(78px, 12vw, 104px);
  flex: none; border-radius: 50%;
  display: grid; place-items: center;
  background: linear-gradient(135deg, var(--tg-blue), var(--brand));
  color: #fff; font-weight: 800; font-size: clamp(1.6rem, 4vw, 2.2rem);
  letter-spacing: 0.04em;
  box-shadow: 0 16px 34px -16px rgba(26, 123, 166, 0.9);
}
.mentor-body { flex: 1 1 340px; min-width: 0; }
.mentor-top {
  display: flex; flex-wrap: wrap; gap: 10px 16px;
  align-items: center; justify-content: space-between;
}
.mentor-name { font-size: clamp(1.15rem, 2.4vw, 1.4rem); line-height: 1.25; }
.mentor-role { color: var(--muted); font-size: 0.88rem; margin-top: 3px; }
.mentor-badge {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 14px; border-radius: 999px;
  background: color-mix(in srgb, var(--warning) 16%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--warning) 45%, transparent);
  color: var(--warning-text);
  font-size: 0.8rem; font-weight: 800;
}
.mentor-text { margin-top: 14px; line-height: 1.65; color: var(--text-2); max-width: 74ch; }
.mentor-text.is-muted { margin-top: 8px; color: var(--muted); }
.mentor-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; list-style: none; }
.mentor-chips li {
  font-size: 0.8rem; font-weight: 700; color: var(--text-2);
  background: var(--surface-2); border: 1px solid var(--border);
  padding: 6px 13px; border-radius: 999px;
}
/* Portrait slot: the "GS" monogram is the shipped state and the real photo
   layers over it only when assets/img/mentor.jpg loads (home.js). */
.mentor-avatar { position: relative; overflow: hidden; }
.mentor-avatar img {
  display: none;
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.mentor-avatar.has-photo img { display: block; }
.mentor-avatar.has-photo span { visibility: hidden; }
/* Mission statement — the one line the whole platform is built to deliver. */
.mentor-mission {
  margin: 18px 0 0;
  padding: 15px 18px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand);
  border-radius: var(--r-md);
}
.mentor-mission p {
  margin: 0;
  font-size: clamp(0.95rem, 1.9vw, 1.05rem);
  font-weight: 600;
  line-height: 1.6;
  color: var(--text);
}
.mentor-mission cite {
  display: block; margin-top: 8px;
  font-size: 0.8rem; font-style: normal;
  font-weight: 700; color: var(--muted);
}

/* --------------------------------------------------- exam coverage band -- */
/* Names the exams this portal is built for, then routes every group to a
   real practice destination — a tag cloud with somewhere to go. */
.exam-groups {
  display: grid; gap: 14px;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 900px) {
  .exam-groups { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.exam-group { align-self: start; }
.exam-group h3 {
  font-size: 0.76rem; font-weight: 800; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 12px;
}
.exam-chips { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; }
.exam-chips a {
  display: inline-block; padding: 6px 13px;
  font-size: 0.8rem; font-weight: 700; color: var(--text-2);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; text-decoration: none;
  transition: color 0.18s, border-color 0.18s, transform 0.18s;
}
.exam-chips a:hover {
  color: var(--brand); border-color: var(--brand); transform: translateY(-1px);
}
@media (max-width: 719px) {
  /* Chips are primary navigation on a phone, so they clear 44px like .btn. */
  .exam-chips a { padding: 11px 15px; font-size: 0.87rem; }
}

/* ----------------------------------------------------- value proposition -- */
.tg-value-grid { display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 560px) { .tg-value-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px) { .tg-value-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.tg-value { display: flex; flex-direction: column; }
.tg-value-ico {
  width: 44px; height: 44px; border-radius: 13px; flex: none;
  display: grid; place-items: center; font-size: 1.25rem;
  background: color-mix(in srgb, var(--tg-blue) 13%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--tg-blue) 32%, transparent);
  margin-bottom: 14px;
}
.tg-value h3 { font-size: 0.99rem; line-height: 1.35; margin-bottom: 7px; }
.tg-value p { color: var(--muted); font-size: 0.87rem; line-height: 1.55; }
.tg-mini { list-style: none; display: grid; gap: 6px; margin-top: 10px; }
.tg-mini li {
  position: relative; padding-left: 18px;
  font-size: 0.83rem; color: var(--text-2);
}
.tg-mini li::before {
  content: "→"; position: absolute; left: 0;
  color: var(--tg-blue-text); font-weight: 800;
}

/* ------------------------------------------------- desktop sidebar rail --- */
.subjects-layout { display: grid; gap: 20px; }
.tg-rail-inner { position: sticky; top: calc(var(--header-h) + 16px); }
.tg-rail-card {
  background:
    linear-gradient(165deg, color-mix(in srgb, var(--tg-blue) 11%, var(--surface)), var(--surface) 62%);
  border: 1.5px solid color-mix(in srgb, var(--tg-blue) 34%, var(--border));
  border-radius: var(--r-xl); padding: 22px;
  box-shadow: var(--shadow);
}
.tg-rail-ico {
  width: 46px; height: 46px; border-radius: 14px;
  display: grid; place-items: center; font-size: 1.35rem;
  background: color-mix(in srgb, var(--tg-blue) 15%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--tg-blue) 36%, transparent);
}
.tg-rail-card h3 { font-size: 1.06rem; margin: 14px 0 6px; line-height: 1.3; }
.tg-rail-card > p { color: var(--text-2); font-size: 0.87rem; line-height: 1.55; }
.tg-rail-card .btn { width: 100%; margin-top: 16px; }
@media (max-width: 1099px) { .tg-rail { display: none; } }

/* ------------------------------------------------- rotating TG banners ---- */
.banner-telegram .bt-title,
.banner-telegram .bt-sub,
.banner-telegram .btn { transition: opacity 0.25s ease; }
.banner-telegram.tg-rot-fade .bt-title,
.banner-telegram.tg-rot-fade .bt-sub,
.banner-telegram.tg-rot-fade .btn { opacity: 0; }
.tg-rot-pause {
  position: relative; z-index: 1;
  width: 38px; height: 38px; flex: none;
  display: none; align-items: center; justify-content: center;
  border-radius: 50%; cursor: pointer;
  background: rgba(255, 255, 255, 0.16);
  border: 1px solid rgba(255, 255, 255, 0.45);
  color: #fff; font-size: 0.85rem; line-height: 1;
  transition: background 0.2s;
}
.tg-rot-pause:hover { background: rgba(255, 255, 255, 0.3); }
.tg-rot-pause:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.banner-telegram.tg-rot-on .tg-rot-pause { display: inline-flex; }

/* --------------------------------------------------- footer TG block ------ */
.footer-tg {
  display: flex; flex-wrap: wrap; gap: 16px 26px;
  align-items: center; justify-content: space-between;
  background: linear-gradient(120deg, color-mix(in srgb, var(--tg-blue) 13%, var(--surface)), var(--surface) 70%);
  border: 1.5px solid color-mix(in srgb, var(--tg-blue) 32%, var(--border));
  border-radius: var(--r-xl);
  padding: 20px 22px;
  margin-bottom: 34px;
}
.footer-tg-copy { flex: 1 1 260px; min-width: 0; }
.footer-tg h2 { font-size: clamp(1rem, 2.2vw, 1.16rem); line-height: 1.35; }
.footer-tg-copy p { color: var(--muted); font-size: 0.86rem; margin-top: 5px; }
.footer-tg-list {
  display: flex; flex-wrap: wrap; gap: 8px;
  list-style: none; flex: 1 1 300px;
}
.footer-tg-list li {
  font-size: 0.79rem; font-weight: 700; color: var(--text-2);
  background: var(--surface-2); border: 1px solid var(--border);
  padding: 6px 12px; border-radius: 999px;
}
.footer-tg .btn { flex: none; }

/* --------------------------------------------------- floating TG button ---- */
.tg-float {
  position: fixed; left: 16px;
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  z-index: 80;
  display: inline-flex; align-items: center; gap: 9px;
  padding: 11px 17px; border-radius: 999px;
  background: var(--tg-blue); color: #fff;
  box-shadow: 0 14px 32px -12px rgba(26, 123, 166, 0.85);
  font-size: 0.88rem; font-weight: 800;
  transition: transform 0.2s var(--ease), background 0.2s, box-shadow 0.2s;
}
.tg-float:hover, .tg-float:focus-visible {
  background: var(--tg-blue-hover); color: #fff;
  transform: translateY(-3px);
  box-shadow: 0 18px 36px -12px rgba(26, 123, 166, 0.95);
}
.tg-float .tgf-ico { font-size: 1.05rem; line-height: 1; }
@media (max-width: 899px) {
  /* Phones already carry a Telegram slot in the bottom nav — a second
     floating pill would just cover content. */
  .tg-float { display: none; }
}

/* ------------------------------------------------- live guidance ribbon ----
   The one appointment the platform keeps, kept in view. Centred on desktop so
   it lands in the empty middle between the Telegram pill (bottom-left) and the
   back-to-top button (bottom-right); on phones it sits directly above the
   thumb bar and both of those move clear of it. */
.live-ribbon {
  position: fixed;
  left: 50%;
  bottom: calc(18px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 85;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: min(540px, calc(100vw - 380px));
  padding: 8px 8px 8px 16px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  color: var(--text);
  font-size: 0.88rem;
  font-weight: 700;
  /* Retracted until home.js releases it. Visibility (not just opacity) so the
     Join Now link is neither clickable nor tabbable while it is away, and
     deliberately without a transform change: the reveal is measured against
     this element's own box, and moving it would make the test flap. */
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.28s var(--ease), visibility 0s linear 0.28s;
}
.live-ribbon.is-on {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.28s var(--ease), visibility 0s;
}
.lr-ico { font-size: 1rem; line-height: 1; }
/* min-width:0 is what lets a flex item shrink below its content width —
   without it the nowrap text forces the fixed ribbon wider than the screen
   and drags the whole page into a horizontal scroll. */
.lr-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lr-text b { color: var(--brand); }
.live-ribbon .btn { flex: none; }
@media (max-width: 899px) {
  .live-ribbon {
    left: 14px;
    right: 14px;
    bottom: calc(62px + env(safe-area-inset-bottom, 0px));
    transform: none;
    max-width: none;
    justify-content: center;
    padding: 8px 8px 8px 14px;
  }
  /* Content clears the ribbon as well as the thumb bar underneath it. */
  body { padding-bottom: calc(116px + env(safe-area-inset-bottom, 0px)); }
  .to-top { bottom: calc(122px + env(safe-area-inset-bottom, 0px)); }
}

/* ---------------------------------------------------- exit-intent popup ---- */
.tg-exit-overlay {
  position: fixed; inset: 0; z-index: 140;
  background: color-mix(in srgb, var(--bg) 66%, transparent);
  backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
  display: grid; place-items: center; padding: 18px;
  animation: fadeIn 0.18s var(--ease);
}
.tg-exit {
  width: min(520px, 100%);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-xl); box-shadow: var(--shadow-lg);
  padding: clamp(24px, 4vw, 34px); text-align: center;
  animation: toastIn 0.3s var(--ease);
}
.tg-exit-icon { font-size: 2.1rem; line-height: 1; }
.tg-exit h2 { font-size: clamp(1.2rem, 3vw, 1.5rem); margin: 12px 0 8px; }
.tg-exit-sub { color: var(--text-2); font-size: 0.95rem; line-height: 1.6; }
.tg-exit-list {
  display: grid; gap: 9px; text-align: left;
  max-width: 330px; margin: 18px auto 0; list-style: none;
}
.tg-exit-list li { font-size: 0.9rem; font-weight: 600; color: var(--text-2); }
.tg-exit-list li::before {
  content: "✔ "; color: var(--success-text); font-weight: 800;
}
.tg-exit-actions {
  display: flex; flex-wrap: wrap; gap: 10px;
  justify-content: center; margin-top: 22px;
}

/* ------------------------------------------ dashboard resource cards ------ */
.tg-res-grid { display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 560px) { .tg-res-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 960px) { .tg-res-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.tg-res { display: flex; flex-direction: column; gap: 6px; padding: 20px; }
.tg-res-ico { font-size: 1.5rem; line-height: 1; }
.tg-res h3 { font-size: 0.97rem; line-height: 1.35; }
.tg-res p { color: var(--muted); font-size: 0.85rem; line-height: 1.5; flex: 1; }
.tg-res .tg-res-cta {
  color: var(--tg-blue-text); font-size: 0.83rem; font-weight: 800;
  margin-top: 4px;
}

/* --------------------------------------- profile benefits checklist ------- */
.tg-benefits {
  display: flex; flex-wrap: wrap; gap: 18px 30px;
  align-items: center; justify-content: space-between;
  background:
    linear-gradient(140deg, color-mix(in srgb, var(--tg-blue) 10%, var(--surface)), var(--surface) 65%);
  border: 1.5px solid color-mix(in srgb, var(--tg-blue) 32%, var(--border));
  border-radius: var(--r-xl);
  padding: clamp(20px, 3vw, 28px);
}
.tg-benefits-info { flex: 1 1 360px; min-width: 0; }
.tg-benefits-info h2 { font-size: clamp(1.05rem, 2.2vw, 1.25rem); margin-bottom: 14px; }
.tg-benefits-list {
  display: flex; flex-wrap: wrap; gap: 8px; list-style: none;
}
.tg-benefits-list li {
  font-size: 0.85rem; font-weight: 700; color: var(--text-2);
  background: var(--surface-2); border: 1px solid var(--border);
  padding: 6px 13px; border-radius: 999px;
}
.tg-benefits-list li::before {
  content: "✔ "; color: var(--success-text); font-weight: 800;
}
.tg-benefits .btn { flex: none; }

/* ------------------------------------------ leaderboard rank boost -------- */
.tg-boost {
  display: flex; flex-direction: column; align-items: flex-start;
  background:
    linear-gradient(140deg, color-mix(in srgb, var(--tg-blue) 10%, var(--surface)), var(--surface) 60%);
  border: 1.5px solid color-mix(in srgb, var(--tg-blue) 32%, var(--border));
  border-radius: var(--r-xl);
  padding: clamp(20px, 3vw, 28px);
}
.tg-boost h2 { font-size: clamp(1.05rem, 2.2vw, 1.3rem); }
.tg-boost > p { color: var(--text-2); font-weight: 600; margin-top: 5px; }
.tg-boost-list {
  display: flex; flex-wrap: wrap; gap: 8px;
  list-style: none; margin-top: 16px;
}
.tg-boost-list li {
  font-size: 0.85rem; font-weight: 700; color: var(--text-2);
  background: var(--surface-2); border: 1px solid var(--border);
  padding: 6px 13px; border-radius: 999px;
}
.tg-boost .btn { margin-top: 18px; }

/* ------------------------------------------- resource lock cards ---------- */
.tg-lock-grid { display: grid; gap: 16px; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 640px) { .tg-lock-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .tg-lock-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
a.tg-lock { display: flex; flex-direction: column; gap: 7px; padding: 20px; text-decoration: none; }
.tg-lock-ico {
  width: 42px; height: 42px; border-radius: 12px; flex: none;
  display: grid; place-items: center; font-size: 1.15rem;
  background: color-mix(in srgb, var(--tg-blue) 13%, transparent);
  border: 1.5px solid color-mix(in srgb, var(--tg-blue) 32%, transparent);
}
.tg-lock h3 { font-size: 0.97rem; line-height: 1.35; }
.tg-lock p { color: var(--muted); font-size: 0.85rem; line-height: 1.5; flex: 1; }
.tg-lock .tg-lock-cta {
  color: var(--tg-blue-text); font-size: 0.83rem; font-weight: 800;
}

/* ==========================================================================
   AEO / GEO layer — answer blocks, FAQ, bylines, sources, trust signals
   Built for answer engines (Google AI Overview, ChatGPT, Gemini, Perplexity,
   Copilot): a self-contained answer under every heading, a visible Q&A block
   that needs no JS to reveal, an attributable byline, and named sources.
   Mobile-first: no fixed widths, everything wraps at 320px.
   ======================================================================== */

/* --- Quick answer: the 40-60 word passage engines quote verbatim -------- */
.answer-box {
  margin-top: 16px;
  max-width: 84ch;
  padding: 15px 15px 15px 16px;
  background: color-mix(in srgb, var(--brand) 5%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--brand) 20%, var(--border));
  border-left: 4px solid var(--brand);
  border-radius: var(--r-md);
}
.answer-box .ab-label {
  display: inline-block;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand);
}
.answer-box p {
  margin-top: 7px;
  font-size: 0.97rem;
  line-height: 1.62;
  font-weight: 500;
  color: var(--text);
}
.answer-box p b { font-weight: 800; }

/* --- Byline: who wrote/reviewed it, when, and how to correct it -------- */
.byline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 11px;
  margin-top: 16px;
  padding: 13px 15px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.bl-avatar {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 0.82rem;
  font-weight: 800;
  color: #fff;
  background: var(--brand-grad);
  letter-spacing: 0.02em;
}
.bl-body { flex: 1 1 190px; min-width: 0; }
.bl-label {
  display: block;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.bl-name { display: block; font-size: 0.94rem; font-weight: 700; color: var(--text); }
.bl-meta { display: block; font-size: 0.78rem; color: var(--muted); margin-top: 1px; }
.bl-fix {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  box-sizing: border-box;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--brand);
  text-decoration: none;
  padding: 7px 14px;
  border: 1px solid color-mix(in srgb, var(--brand) 30%, transparent);
  border-radius: 999px;
}
.bl-fix:hover { background: color-mix(in srgb, var(--brand) 8%, transparent); }

/* --- FAQ blocks: visible Q + A, no JS, snippet-shaped ------------------- */
.faq-list { display: grid; gap: 13px; margin-top: 18px; }
.faq-item {
  padding: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.faq-item h3 {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  font-size: 1.01rem;
  line-height: 1.42;
}
.faq-item h3::before {
  content: "Q";
  flex: none;
  width: 23px;
  height: 23px;
  margin-top: 1px;
  border-radius: 7px;
  display: grid;
  place-items: center;
  font-size: 0.72rem;
  font-weight: 800;
  color: #fff;
  background: var(--brand-grad);
}
.faq-item p {
  margin-top: 9px;
  font-size: 0.93rem;
  line-height: 1.66;
  color: var(--muted);
}
.faq-item p:first-of-type { margin-left: 32px; }
.faq-item p b { color: var(--text); font-weight: 700; }

/* --- FAQ hub: category jump chips + grouped sections ------------------- */
.faq-jump { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.faq-jump a {
  display: inline-block;
  padding: 9px 14px;
  min-height: 44px;
  box-sizing: border-box;
  font-size: 0.87rem;
  font-weight: 700;
  color: var(--text-2);
  text-decoration: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 999px;
}
.faq-jump a:hover { color: var(--brand); border-color: color-mix(in srgb, var(--brand) 40%, var(--border)); }
.faq-group { margin-top: 38px; scroll-margin-top: 90px; }
.faq-group > h2 { font-size: clamp(1.15rem, 2.4vw, 1.45rem); }
.faq-group > p.muted { margin-top: 7px; }

/* --- Named sources / official references ------------------------------- */
.sources {
  margin-top: 30px;
  padding: 18px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.sources h2 { font-size: clamp(1.05rem, 2.2vw, 1.25rem); }
.sources > p { margin-top: 7px; font-size: 0.9rem; }
.sources ul { display: grid; gap: 9px; margin-top: 13px; list-style: none; }
.sources li {
  position: relative;
  padding-left: 20px;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--muted);
}
.sources li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--brand-2);
}
.sources li a { font-weight: 700; }
.sources .src-note {
  margin-top: 13px;
  font-size: 0.8rem;
  color: var(--muted);
}

/* --- Trust signals strip ------------------------------------------------ */
.trust-bar {
  display: grid;
  gap: 11px;
  grid-template-columns: minmax(0, 1fr);
  margin-top: 18px;
}
@media (min-width: 560px) { .trust-bar { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .trust-bar { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.trust-item {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 14px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.trust-item .ti-ico {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  font-size: 1rem;
  background: color-mix(in srgb, var(--brand) 9%, transparent);
}
.trust-item b { display: block; font-size: 0.9rem; line-height: 1.35; }
.trust-item span { display: block; font-size: 0.8rem; line-height: 1.5; color: var(--muted); margin-top: 3px; }

/* --- Key takeaways: numbered, scannable, extractable ------------------- */
.takeaways {
  counter-reset: tk;
  display: grid;
  gap: 10px;
  margin-top: 16px;
  list-style: none;
}
.takeaways li {
  counter-increment: tk;
  position: relative;
  padding: 13px 14px 13px 46px;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.takeaways li::before {
  content: counter(tk);
  position: absolute;
  left: 13px;
  top: 13px;
  width: 23px;
  height: 23px;
  border-radius: 7px;
  display: grid;
  place-items: center;
  font-size: 0.75rem;
  font-weight: 800;
  color: #fff;
  background: var(--brand-grad);
}
.takeaways li b { color: var(--text); }

/* --- At-a-glance fact table (highly citable for answer engines) -------- */
.fact-table-wrap { overflow-x: auto; margin-top: 16px; -webkit-overflow-scrolling: touch; }
.fact-table {
  width: 100%;
  min-width: 460px;
  border-collapse: collapse;
  font-size: 0.88rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
}
.fact-table th,
.fact-table td {
  padding: 11px 13px;
  text-align: left;
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.fact-table th {
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface-2);
}
.fact-table tr:last-child td { border-bottom: 0; }
.fact-table td:first-child { font-weight: 700; color: var(--text); }
.fact-table-wrap + .src-note,
.fact-table + .src-note { display: block; margin-top: 9px; font-size: 0.8rem; color: var(--muted); }

/* --- Tiny type floor: supporting copy never below 12px ------------------ */
.answer-box .ab-label, .bl-label, .fact-table th { font-size: 0.75rem; }

/* ==========================================================================
 * PREVIOUS YEAR QUESTIONS — the per-exam paper table (pyq/<slug>/index.html)
 * Built by scripts/build_content.py from the folders in
 * content/previous-year-questions/. One row per year: the question paper and
 * the official answer key side by side, or the words "Not published" for a
 * key the conducting body has not released. Nothing here is a placeholder -
 * the cell is empty because the file is.
 * ========================================================================== */
.pyq-table-wrap { position: relative; }
.pyq-papers {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
}
.pyq-papers thead th {
  text-align: left;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--surface-2);
  padding: 12px 14px;
  border-bottom: 2px solid var(--border);
}
.pyq-papers tbody th,
.pyq-papers tbody td {
  padding: 15px 14px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.pyq-papers tbody th[scope="row"] {
  text-align: left;
  font-weight: 800;
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  width: 1%;
}
.pyq-papers tbody tr:last-child > * { border-bottom: 0; }
.pyq-papers tbody tr { transition: background 0.15s ease; }
.pyq-papers tbody tr:hover { background: color-mix(in srgb, var(--brand) 5%, transparent); }
.pyq-dl { white-space: nowrap; }
.pyq-filemeta { display: block; margin-top: 7px; font-size: 0.78rem; color: var(--muted); }
.pyq-none { display: inline-block; font-size: 0.88rem; font-style: italic; color: var(--muted); }

/* The Punjabi edition of an overview sits under its own label, in its own
   script, without changing the language of the chrome around it. */
.pyq-alt {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px dashed var(--border);
}
.pyq-alt h3 { font-size: 1rem; margin-bottom: 10px; }

/* Phone: one card per year with labelled rows — the same stacked-table
   pattern revision.html uses, so a 360px screen never scrolls sideways. */
@media (max-width: 640px) {
  .pyq-papers thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }
  .pyq-papers,
  .pyq-papers tbody,
  .pyq-papers tr,
  .pyq-papers th,
  .pyq-papers td { display: block; width: auto; }
  .pyq-papers tbody tr {
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    margin-bottom: 14px;
    background: var(--surface);
    overflow: hidden;
  }
  .pyq-papers tbody tr:last-child { margin-bottom: 0; }
  .pyq-papers tbody th,
  .pyq-papers tbody td {
    padding: 12px 14px;
    border-bottom: 1px dashed var(--border);
    width: auto;
  }
  .pyq-papers tbody tr > *:last-child { border-bottom: 0; }
  .pyq-papers tbody th[scope="row"]::before,
  .pyq-papers tbody td::before {
    content: attr(data-label);
    display: block;
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 7px;
  }
}

/* ==========================================================================
 * CONTENT PAGES — study notes, magazine, strategy, sessions, recruitment
 * Rendered by scripts/build_content.py. Same tokens and card language as the
 * rest of the portal; only the reading layout is new.
 * ========================================================================== */
.doc-layout {
  display: grid;
  gap: clamp(20px, 4vw, 34px);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
.doc-badges { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
/* Tags and categories are links when their archive page exists (Phase 4) -
   they keep the badge look, so a reader only notices they move. */
a.badge { text-decoration: none; transition: border-color .15s ease, color .15s ease; }
a.badge:hover, a.badge:focus-visible { color: var(--brand); border-color: color-mix(in srgb, var(--brand) 55%, transparent); }
.doc-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.affiliate-note { margin-top: 18px; max-width: 70ch; }

/* Table of contents — first in the DOM (phones read it first), parked in the
   right rail from 1100px where the reading column stays at a comfortable
   measure. Sticky so it tracks the scroll like a study sidebar. */
.doc-toc {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 18px 20px;
}
.doc-toc h2 {
  font-size: 0.78rem; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 10px;
}
.doc-toc ol { list-style: none; margin: 0; padding: 0; counter-reset: toc; }
.doc-toc li { counter-increment: toc; margin: 0; }
.doc-toc a {
  display: block; position: relative; padding: 6px 0 6px 26px;
  font-size: 0.92rem; color: var(--text-2); border-left: 2px solid transparent;
}
.doc-toc a::before {
  content: counter(toc); position: absolute; left: 6px;
  font-size: 0.76rem; font-weight: 700; color: var(--muted);
}
.doc-toc a:hover, .doc-toc a.is-active { color: var(--brand); border-left-color: var(--brand); }
.toc-meta {
  margin-top: 12px; padding-top: 10px; border-top: 1px dashed var(--border);
  font-size: 0.78rem; font-weight: 600; color: var(--muted);
}

/* Article body ---------------------------------------------------------- */
.doc-body { min-width: 0; }
.prose { color: var(--text-2); font-size: 1.02rem; line-height: 1.76; max-width: 72ch; }
.prose p { margin: 0 0 1.05em; }
.prose h2, .prose h3, .prose h4 {
  color: var(--text); line-height: 1.25; margin: 1.7em 0 0.55em;
  scroll-margin-top: calc(var(--header-h) + 18px);
}
.prose h2 { font-size: clamp(1.22rem, 2.3vw, 1.45rem); }
.prose h3 { font-size: clamp(1.06rem, 2vw, 1.2rem); }
.prose h4 { font-size: 1rem; }
.prose ul, .prose ol { margin: 0 0 1.1em; padding-left: 1.35em; }
.prose li { margin-bottom: 0.42em; }
.prose a { color: var(--brand); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.prose strong, .prose b { color: var(--text); }
.prose blockquote {
  margin: 1.3em 0; padding: 12px 18px; border-left: 3px solid var(--brand);
  background: var(--surface-2); border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.prose blockquote p:last-child { margin-bottom: 0; }
.prose pre {
  margin: 1.3em 0; padding: 14px 16px; overflow-x: auto;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-sm); font-size: 0.9rem;
}
.prose code {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 6px; padding: 0.1em 0.35em; font-size: 0.92em;
}
.prose hr { border: 0; border-top: 1px solid var(--border); margin: 2em 0; }
.prose .md-table { overflow-x: auto; margin: 1.3em 0; }
.prose table { border-collapse: collapse; width: 100%; font-size: 0.95rem; }
.prose th, .prose td { border: 1px solid var(--border); padding: 9px 13px; text-align: left; }
.prose th { background: var(--surface-2); color: var(--text); font-size: 0.82rem;
  letter-spacing: 0.04em; text-transform: uppercase; }

/* Share row — plain links, so sharing works with JavaScript disabled and no
   third-party SDK ever loads on the page. */
.share-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 18px; }
.share-label {
  font-size: 0.76rem; font-weight: 700; letter-spacing: 0.07em;
  text-transform: uppercase; color: var(--muted); margin-right: 2px;
}
.share-btn {
  font-size: 0.86rem; font-weight: 600; padding: 7px 14px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface); color: var(--text-2);
  cursor: pointer; transition: all 0.16s var(--ease);
}
.share-btn:hover { border-color: var(--brand); color: var(--brand); }

/* Previous / next -------------------------------------------------------- */
.prev-next { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
.pn-card {
  display: flex; flex-direction: column; gap: 6px; padding: 17px 20px;
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface); transition: border-color 0.16s var(--ease);
}
.pn-card:hover { border-color: var(--brand); }
.pn-card:last-child { text-align: right; }
.pn-label {
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.pn-title { font-weight: 700; color: var(--text); line-height: 1.35; }
.pn-empty { display: none; }

@media (min-width: 720px) {
  .prev-next { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Learning path chain (auto-generated internal links) --------------------- */
.doc-chain {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch;
}
.chain-step {
  display: flex; flex-direction: column; gap: 3px; min-width: 0;
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface); padding: 11px 15px;
  font-size: 0.9rem; font-weight: 700; line-height: 1.3; color: var(--text);
  text-decoration: none; transition: border-color 0.16s var(--ease);
}
a.chain-step:hover { border-color: var(--brand); color: var(--brand); }
.chain-step em {
  font-style: normal; font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--muted);
}
.chain-step.is-current { border-color: var(--brand); background: var(--surface-2); }
.chain-step.is-reserved { border-style: dashed; color: var(--muted); }

/* Recommendation plan (content templates, Phase 3) ------------------------- */
.rec-group + .rec-group { margin-top: 26px; }
.rec-title {
  font-size: 0.84rem; font-weight: 800; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 12px;
}
/* A slot whose data does not exist yet stays visible and says so - it is
   never linked to a page that is not there. */
.rec-reserved {
  display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  margin: 26px 0 0; padding: 13px 16px;
  border: 1px dashed var(--border); border-radius: var(--r-md);
  background: var(--surface-2);
  font-size: 0.92rem; color: var(--muted); line-height: 1.55;
}

/* Archive index (archives.html) ------------------------------------------- */
.arch-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.arch-list a {
  display: grid; grid-template-columns: 112px minmax(0, 1fr) auto; gap: 12px;
  align-items: baseline; padding: 11px 14px; border-radius: var(--r-md);
  text-decoration: none; color: var(--text);
}
.arch-list a:hover { background: var(--surface-2); }
.arch-list time {
  font-size: 0.8rem; color: var(--muted); font-variant-numeric: tabular-nums;
}
.arch-title { font-weight: 600; line-height: 1.4; }
.arch-tag {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.arch-more {
  font-size: 0.85rem; font-weight: 700; margin-left: 8px;
  color: var(--brand); white-space: nowrap;
}
@media (max-width: 640px) {
  .arch-list a { grid-template-columns: minmax(0, 1fr); gap: 3px; }
}

/* Issue / session card (magazine cover, live-session details) ------------- */
.doc-issue { display: flex; flex-wrap: wrap; gap: 22px; align-items: flex-start; }
/* The width/height attributes reserve the box before the file loads, so the
   card never jumps (and never reports a size it does not have). */
.doc-cover {
  display: block; width: 200px; max-width: 100%; height: auto; flex: none;
  /* the inline aspect-ratio (from front matter) reserves the exact box the
     file will occupy, so nothing moves when the image decodes */
  object-fit: cover;
  border-radius: var(--r-md); border: 1px solid var(--border);
  background: var(--surface-2);
}
.doc-issue-body { flex: 1 1 260px; min-width: 0; }
.doc-facts { display: flex; flex-wrap: wrap; gap: 10px; margin: 14px 0 0; }
.doc-fact {
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface-2); padding: 9px 13px; min-width: 118px;
}
.doc-fact dt {
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.doc-fact dd { margin: 3px 0 0; font-size: 0.92rem; font-weight: 700; color: var(--text); }
.doc-issue .btn-row { margin-top: 16px; }

@media (min-width: 720px) {
  .doc-cover { width: 240px; }
}
@media (min-width: 1100px) {
  .doc-layout { grid-template-columns: minmax(0, 1fr) 280px; }
  .doc-toc { grid-column: 2; grid-row: 1; position: sticky; top: calc(var(--header-h) + 16px); }
  .doc-body { grid-column: 1; grid-row: 1; }
}

/* ---------------------------- PHASE 4: CONTENT PLATFORM -------------------
   Same tokens, same components - these rules only style what the content
   platform adds to an existing page: the facet bar above a listing, the
   author link inside a byline, an editorial subtitle, a named source list
   and the front-matter FAQ. Nothing here changes a Phase 0-3 layout. */
.filter-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px;
  margin: 4px 0 22px; padding: 12px 14px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.filter-group { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }
.fg-label {
  font-size: 0.72rem; font-weight: 800; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}
.filter-chip {
  font: inherit; font-size: 0.8rem; font-weight: 600;
  padding: 5px 11px; border-radius: 999px; cursor: pointer;
  color: var(--text); background: color-mix(in srgb, var(--brand) 6%, transparent);
  border: 1px solid var(--border); transition: all 0.15s var(--ease);
}
.filter-chip:hover { border-color: var(--brand); color: var(--brand); }
.filter-chip[aria-pressed="true"] {
  background: var(--brand); border-color: var(--brand); color: #fff;
}
.filter-reset {
  font: inherit; font-size: 0.8rem; font-weight: 700; cursor: pointer;
  padding: 5px 11px; border-radius: 999px; color: var(--muted);
  background: transparent; border: 1px dashed var(--border);
}
.filter-reset:hover { color: var(--brand); border-color: var(--brand); }
.filter-count { margin: 0 0 0 auto; font-size: 0.8rem; color: var(--text); font-weight: 700; }
.filter-count.is-muted { color: var(--muted); font-weight: 600; }
.is-filtered-out { display: none !important; }

/* Two labelled rows inside ONE facet bar: the dimension chooser, then the
   values of the dimension that is open. Only the Books shelf needs the split,
   and it reuses the chips, labels, reset and count above unchanged. */
.filter-bar > .fg-row {
  flex: 1 0 100%;
  display: flex; flex-wrap: wrap; align-items: center; gap: 7px 10px;
}
.filter-bar > .fg-row > .filter-reset { margin-left: auto; }
/* .filter-bar is display:flex, which would otherwise beat the UA rule for
   [hidden] - the shelf hides the whole bar when the payload is empty. */
.filter-bar[hidden] { display: none; }

/* The shelf card's title is the way into the review. It inherits the card's
   typography instead of reading as an inline hyperlink, and it stays a real
   link so it works without JavaScript and for a screen reader's link list. */
.book-card h3 a { color: inherit; text-decoration: none; }
.book-card h3 a:hover, .book-card h3 a:focus-visible { color: var(--brand); }

/* Author link inside the byline - the E-E-A-T claim, one click from the page. */
.bl-name .bl-link { color: inherit; text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--brand) 45%, transparent); }
.bl-name .bl-link:hover { color: var(--brand); border-bottom-color: var(--brand); }

/* Editorial subtitle under the H1 (content model: `subtitle`). */
.doc-subtitle {
  margin: -4px 0 14px; font-size: clamp(1rem, 1.6vw, 1.15rem);
  color: var(--muted); font-weight: 500; max-width: 62ch;
}

/* `references:` - a numbered source list with the host named on each link. */
.source-list { list-style: decimal; padding-left: 20px; display: grid; gap: 10px; }
.source-list li { font-size: 0.94rem; }
.source-list a { font-weight: 700; color: var(--text); text-decoration: none; }
.source-list a:hover { color: var(--brand); }
.source-list .src-host {
  display: inline-block; margin-left: 7px; font-size: 0.74rem; font-weight: 700;
  color: var(--muted); background: color-mix(in srgb, var(--brand) 7%, transparent);
  padding: 1px 7px; border-radius: 999px;
}

/* `faq:` - the front-matter Q&A reuses the .faq-item contract of faq.html. */
.faq-list { display: grid; gap: 12px; }

/* Two columns keep the Study menu (7 subjects + 6 material) and the Practice
   menu (7 subjects + 8 test types) inside their max-height without a scrollbar
   at every desktop width. The dropdown hangs off the left edge of its button,
   so at the 900px floor a 560px panel starting near x=190 still clears the
   viewport by ~150px. */
@media (min-width: 900px) {
  .nav-drop-menu.nav-cols {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    width: min(560px, calc(100vw - 24px));
  }
}

/* search.html - the same tokens as the Ctrl+K field, on a page of its own. */
.search-page-form { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 20px; }
.search-page-form input[type="search"] {
  flex: 1 1 260px; font: inherit; font-size: 1rem;
  padding: 12px 16px; color: var(--text);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.search-page-form input[type="search"]:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
}
.search-page-form .btn { padding: 12px 22px; }
.search-meta { font-size: 0.85rem; color: var(--muted); margin-bottom: 14px; }

/* books.html - the recommendation card. One cover, one title, one author,
   one recommendation line, one button - nothing else. Additive: it reuses
   .card, .eyebrow and .btn, so nothing outside this page's own containers
   is affected. Mobile first: the cover sits on top and fills the card. */
.book-card { display: flex; flex-direction: column; overflow: hidden; }
.book-card-media {
  display: flex; align-items: stretch; justify-content: center;
  aspect-ratio: 2 / 3;                 /* the shape a book actually is */
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}
.book-card-cover { display: block; width: 100%; height: 100%; object-fit: cover; }
.book-card-body {
  display: flex; flex-direction: column; flex: 1;
  padding: 16px 16px 18px;
}
.book-card h3 { margin: 0; font-size: 1.05rem; line-height: 1.32; }
/* The title stays the way into the detail page. It inherits the card's
   typography instead of reading as an inline hyperlink, and it stays a real
   link so it works without JavaScript and in a screen reader's link list. */
.book-card h3 a { color: inherit; text-decoration: none; }
.book-card h3 a:hover, .book-card h3 a:focus-visible { color: var(--brand); }
.book-card-author { margin: 4px 0 0; font-size: .88rem; color: var(--muted); }
/* The one line this card exists for. Clamped to two lines so a long sentence
   can never turn the shelf back into a wall of text. */
.book-card-rec {
  margin: 10px 0 0; flex: 1; font-size: .94rem; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Single, prominent CTA - the largest tap target on the card. */
.book-cta { width: 100%; margin-top: 14px; text-align: center; padding: 13px 16px; }

/* Subject chips above the shelf. .filter-chip is the shared chip style (PYQ,
   Study and the archives use it too), so nothing new is invented here. */
.group-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 22px; }
.group-chips[hidden] { display: none; }

/* One <section> per subject, rendered by books.js from the payload. */
.book-group { margin-bottom: 8px; }
.book-group-title {
  margin: 0 0 14px; font-size: 1.12rem; letter-spacing: -.01em;
  padding-bottom: 8px; border-bottom: 1px solid var(--border);
}

/* The shelf grid: compact text cards, no cover block unless a real cover
   image has been added. One column on a phone, three to four on a desktop;
   every card in a row is the same height and the buttons line up. */
.book-grid {
  display: grid; gap: 14px;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 640px) {
  .book-grid { gap: 18px; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
}
.book-grid .book-card { height: 100%; }
.book-grid .book-card-media { aspect-ratio: auto; height: 180px; }
.book-grid .book-card-cover { object-fit: contain; background: var(--surface-2); }
.book-grid .book-card-body { padding: 16px 18px 18px; }
.book-grid .book-card h3 { font-size: 1.02rem; }
.book-grid .book-card-rec {
  flex: 0 0 auto; margin: 8px 0 14px; font-size: .9rem; -webkit-line-clamp: 3;
}
.book-grid .book-cta { margin-top: auto; padding: 10px 14px; font-size: .92rem; }
.book-card-group {
  display: block; margin-bottom: 6px;
  font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--brand);
}

/* The initials fallback, filling the card's cover box: it reads as a cover
   placeholder rather than an icon, and an image dropped into
   assets/books/covers/ occupies exactly the same box - no reflow. */
.book-card-media .book-cover {
  width: 100%; height: 100%; margin: 0; border-radius: 0;
  font-size: 2.6rem; box-shadow: none;
}
.book-cover {
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; letter-spacing: .02em;
  color: #fff; background: linear-gradient(155deg, var(--brand), color-mix(in srgb, var(--brand) 55%, #111));
  border-radius: 3px 7px 7px 3px;
  box-shadow: inset 3px 0 0 rgba(0,0,0,.22), var(--shadow-sm);
}
/* The book detail page's cover fallback, sized for the hero. */
.book-cover-lg {
  width: 132px; height: 180px; margin-bottom: 0;
  font-size: 2rem; border-radius: 4px 10px 10px 4px;
}

/* book-<id>.html - the cover, the recommendation and the single CTA. */
.book-pick { display: flex; flex-wrap: wrap; gap: 22px; align-items: flex-start; margin-top: 6px; }
.book-pick-body { flex: 1 1 280px; min-width: 0; }
.book-pick-author { margin: 0 0 12px; font-weight: 700; }
/* revision.html - the chapter chips are tap targets on their own, so they get
   the 24px minimum height the touch-target guideline asks for. Scoped to this
   page's cards so nothing else that reuses .area-chip moves. */
.rev-card .area-chip {
  min-height: 24px; display: inline-flex; align-items: center;
}

/* pyq.html - group headings inside the exam / paper grids. */
.pyq-group-title {
  font-size: clamp(1.05rem, 2.2vw, 1.25rem); margin: 4px 0 14px;
}

/* ============================================================ STUDY SYSTEM
   study.html - the category / chapter / part / material blocks. This surface
   is reading-only, so it deliberately carries no badge that counts quizzes and
   no control that looks like it launches a test; the only interactive thing in
   a chapter block is a link to a note. */
.study-cat { margin-bottom: 34px; }
.study-cat .section-head { margin-bottom: 16px; }
.study-cat .section-head h3 { margin: 4px 0 4px; }

.part-list { list-style: none; margin: 12px 0 0; padding: 0; display: grid; gap: 8px; }
.part-list li {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  padding: 9px 12px; min-height: 24px;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--surface) 70%, transparent);
}
.part-name {
  font-size: 0.87rem; font-weight: 600; color: var(--text);
  min-width: 0; overflow-wrap: anywhere;
}
.part-meta {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
.part-count { font-size: 0.8rem; color: var(--muted); margin: 4px 0 0; }

/* Notes attached to a chapter. auto-fit means a subject with one note does not
   leave three empty columns beside it. */
.material-grid {
  display: grid; gap: 14px; margin-top: 16px;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
/* An honest empty shelf beats a broken-looking one: the pipeline has not
   published a note for this chapter yet, and the reader is told where the
   notes that do exist are. */
.material-empty {
  font-size: 0.86rem; line-height: 1.6; color: var(--muted);
  margin-top: 14px; padding: 12px 14px;
  border: 1px dashed var(--border); border-radius: var(--r-md);
  background: color-mix(in srgb, var(--surface) 60%, transparent);
}
.material-empty a { color: var(--brand); font-weight: 600; }

/* rank-2-blueprint.html - "713" with the "/ 800" set back so the score reads
   first without the denominator competing with it. */
.stat-out {
  font-size: 0.52em; font-weight: 700; letter-spacing: -0.01em;
  color: var(--muted); -webkit-text-fill-color: var(--muted);
}

/* ==========================================================================
   STUDY MATERIAL — the shelf card (study.html?subject=… and study-material.html)
   --------------------------------------------------------------------------
   The build prints this card and study.js prints it again for the SPA view, so
   both are styled by the same rules and a reader never sees two shapes for the
   same file. Additive only: it reuses .card, .card-pad, .eyebrow, .badge and
   .btn, and only touches its own class names.
   ========================================================================== */
.study-card { display: flex; flex-direction: column; }
.study-card h3 { margin-bottom: 6px; }
/* The title is the way in, exactly like the book shelf's: it inherits the
   card's typography instead of reading as an inline hyperlink, and it stays a
   real link so it works with JavaScript off and in a screen reader's list.
   `display:inline-block` plus matched padding/margin is what gives it a
   thumb-sized hit area (~30px) without moving a single line of the layout —
   an inline link only boxes to its font's own ascent, which is under the
   24px floor the site holds its tap targets to. */
.study-card h3 a { color: inherit; text-decoration: none; display: inline-block; padding-block: 4px; margin-block: -4px; }
.study-card h3 a:hover, .study-card h3 a:focus-visible { color: var(--brand); }
.study-card .muted { font-size: 0.9rem; }

/* Badges sit in the flow above the eyebrow rather than floating over the
   title: a long subject name and an absolutely-positioned pill will collide on
   a 320px screen, and an overlapping badge is worse than a taller card. */
.card-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }

/* Language · updated · reading time · size — the four facts a reader picks a
   file by. `margin-top:auto` drops the row (and the button) to the bottom of
   the column, so every card in a row lines up however long its description is. */
.study-meta {
  margin-top: auto; padding-top: 14px;
  font-size: 0.82rem; line-height: 1.5; color: var(--muted);
}
.study-card .btn-row { margin-top: 12px !important; margin-bottom: 0; }
.study-card .btn { width: 100%; justify-content: center; }

/* Search above the shelf: one row that wraps to a full-width field on a
   phone, with a 44px-tall target — the floor for a thumb, not a mouse. */
.material-tools {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  margin-bottom: 12px;
}
.material-search {
  flex: 1 1 240px; min-width: 0; min-height: 44px;
  font: inherit; font-size: 1rem; padding: 11px 15px;
  color: var(--text); background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r-md);
}
.material-search:focus {
  outline: none; border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
}
.material-tools .btn { min-height: 44px; }
.material-count { font-size: 0.85rem; color: var(--muted); margin-bottom: 14px; }

/* ----------------------------------------------- Study: language cards ---
   A subject opens on its languages and on nothing else — no chapter, no
   part, no file until a language is chosen — so the choice has to read as
   the page's only real decision. The flag leads, the native script sits
   under it, and the card is the full tap target (>= 44px on every screen).
   Additive: it reuses .card, .badge and .subject-meta and adds its own
   class names only. */
.lang-card {
  display: flex; flex-direction: column; align-items: flex-start;
  padding: 26px 24px; min-height: 44px;
}
.lang-flag { font-size: 2.2rem; line-height: 1.1; }
.lang-card h3 { margin: 10px 0 2px; font-size: 1.35rem; }
.lang-native { margin: 0 0 10px; color: var(--muted); font-size: 1.05rem; }
.lang-card .muted { font-size: 0.88rem; margin-bottom: 0; }
.lang-card .subject-meta { margin-top: auto; padding-top: 16px; }

/* ----------------------------------------------- Study: part rows --------
   Parts are a sequence, not a shelf: they are listed in reading order down
   one column with the part number leading, because on a phone a reader is
   walking forward one part at a time. Each row is the whole tap target
   (min-height 44px floor) and never scrolls sideways. */
.part-wrap { display: block; }
.part-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.part-rows > li { display: block; }
.part-row {
  display: grid; gap: 6px; padding: 15px 16px; min-height: 44px;
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: color-mix(in srgb, var(--surface) 75%, transparent);
  color: var(--text); text-decoration: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.part-row:hover, .part-row:focus-visible {
  border-color: var(--brand);
  box-shadow: 0 4px 16px color-mix(in srgb, var(--brand) 12%, transparent);
}
.pr-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.pr-num { font-weight: 800; font-size: 1.02rem; letter-spacing: .01em; }
.pr-badges { display: inline-flex; gap: 6px; }
.pr-desc {
  margin: 0; font-size: 0.9rem; line-height: 1.5; color: var(--muted);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.pr-meta {
  font-size: 0.74rem; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
@media (max-width: 480px) {
  .lang-card { padding: 22px 20px; }
  .part-row { padding: 14px 14px; }
}

/* ==========================================================================
 * RANK 2 BLUEPRINT  (rank-2-blueprint.html)
 * --------------------------------------------------------------------------
 * The one page on the site whose whole job is to be believed. Everything below
 * is scoped to `.rb-` / `.rbv-` so it cannot leak into any other module, and
 * every rule is written mobile-first: the layout starts as a single readable
 * column, gains columns only once the viewport can hold them, and never
 * scrolls sideways. No new colours, no new radii, no new type scale — the
 * tokens are the ones the rest of the site already uses.
 * ========================================================================== */

/* ------------------------------------------------------------- 1. HERO ---- */
.rb-hero { padding-bottom: clamp(30px, 5vw, 52px); }
.rb-lede {
  max-width: 62ch;
  margin: 0 0 22px;
  font-size: clamp(1rem, 2.4vw, 1.14rem);
  line-height: 1.65;
  color: var(--text-2);
}

/* The result strip. One card per fact, so a phone shows one stacked column
   rather than four cramped ones; the row only splits when there is room for
   two full-width halves, then four. */
.rb-results {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
  margin: 24px 0 26px;
}
@media (min-width: 500px) { .rb-results { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 980px) { .rb-results { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.rb-result {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--brand) 7%, var(--surface)) 0%,
      var(--surface) 70%);
  box-shadow: var(--shadow);
  min-width: 0;
}
.rb-result-k {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand);
}
.rb-result-v {
  font-size: clamp(1.75rem, 5.4vw, 2.35rem);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.05;
  color: var(--text);
  overflow-wrap: anywhere;
}
/* "No Paid Coaching" is a phrase, not a number: it needs the numeral scale
   pulled back or it wraps into three lines on a phone. */
.rb-result-v--text {
  font-size: clamp(1.12rem, 3.6vw, 1.4rem);
  line-height: 1.2;
  letter-spacing: -0.01em;
  background: var(--brand-grad);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.rb-result-out { font-size: 0.5em; font-weight: 700; color: var(--muted); -webkit-text-fill-color: var(--muted); margin-left: 2px; }
.rb-result-n { font-size: 0.8rem; line-height: 1.45; color: var(--muted); }

/* ------------------------------------------------- 2. VERIFIED RESULT ---- */
.rb-facts {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px;
}
@media (min-width: 560px) { .rb-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .rb-facts { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.rb-fact {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 18px 18px 20px;
  min-height: 44px;
  border: 1px solid var(--border);
  border-left: 3px solid var(--brand);
  border-radius: var(--r-md);
  background: var(--surface);
  min-width: 0;
}
.rb-fact--link {
  text-decoration: none;
  color: inherit;
  transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}
.rb-fact--link:hover, .rb-fact--link:focus-visible {
  border-color: var(--brand);
  box-shadow: 0 8px 22px -14px color-mix(in srgb, var(--brand) 70%, transparent);
  transform: translateY(-2px);
}
.rb-fact-k { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.rb-fact-v { font-size: clamp(1.3rem, 4vw, 1.7rem); font-weight: 800; letter-spacing: -0.03em; line-height: 1.1; }
.rb-fact-out { font-size: 0.6em; color: var(--muted); margin-left: 2px; }
.rb-fact-n { font-size: 0.8rem; color: var(--muted); line-height: 1.45; }

.rb-block { margin-top: clamp(26px, 4vw, 38px); scroll-margin-top: 90px; }
.rb-block-head { margin-bottom: 16px; }
.rb-block-head h3 { font-size: clamp(1.1rem, 3vw, 1.3rem); }
.rb-block-head p { margin-top: 6px; font-size: 0.92rem; max-width: 68ch; }

/* ---------------------------------------------- 2b. DOCUMENT CARDS ------- */
/* A fixed shell per slot: the card exists whether or not there is a file
   behind it, so publishing a scan upgrades a card in place instead of
   reflowing the page under a reader's thumb (no layout shift). */
.rb-doc-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
}
@media (min-width: 640px) { .rb-doc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .rb-doc-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.rb-doc {
  display: flex;
  flex-direction: column;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.rb-doc-thumb {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  background:
    repeating-linear-gradient(135deg,
      var(--surface-2) 0 12px,
      color-mix(in srgb, var(--surface-2) 60%, var(--border)) 12px 24px);
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}
.rb-doc-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}
/* PDFs have no server-rendered thumbnail (rendering one needs a PDF engine
   the deploy does not have), so the card shows an honest, designed face:
   the file type, the extension and the size — never a blank rectangle. */
.rb-doc-face {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 6px;
  text-align: center;
  padding: 14px;
  color: var(--muted);
}
.rb-doc-face b {
  font-size: 1.4rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  color: var(--brand);
}
.rb-doc-face span { font-size: 0.76rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
.rb-doc-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: rgba(15, 23, 42, 0.82);
  color: #fff;
  backdrop-filter: blur(6px);
}
.rb-doc-body { display: flex; flex-direction: column; gap: 8px; padding: 16px 16px 18px; flex: 1 1 auto; min-width: 0; }
.rb-doc-title { margin: 0; font-size: 1.02rem; line-height: 1.35; overflow-wrap: anywhere; }
.rb-doc-note { margin: 0; font-size: 0.87rem; line-height: 1.55; color: var(--muted); }
.rb-doc-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: auto;
  padding-top: 4px;
}
.rb-doc-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.rb-doc-actions .btn { flex: 1 1 auto; min-width: 132px; }

/* Slot with nothing behind it yet: same shell, muted, no dead buttons. */
.rb-doc.is-empty { background: color-mix(in srgb, var(--surface) 62%, transparent); box-shadow: none; }
.rb-doc.is-empty .rb-doc-thumb { aspect-ratio: 16 / 7; }
.rb-doc.is-empty .rb-doc-body { justify-content: center; }
.rb-doc-waiting {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--warning-text);
}
.rb-doc-waiting::before {
  content: "";
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--warning);
  flex: none;
}

/* Analytics strip hung under an answer-sheet card: three numbers, same
   source as the attempt sheet, so nothing on this page can disagree with it. */
.rb-doc-ana {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
  padding: 10px 12px;
  border-top: 1px dashed var(--border);
  background: color-mix(in srgb, var(--brand) 5%, var(--surface));
}
.rb-doc-ana div { text-align: center; min-width: 0; }
.rb-doc-ana dt { font-size: 0.66rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted); }
.rb-doc-ana dd { margin: 2px 0 0; font-size: 1.02rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.rb-doc-ana .a-ok { color: var(--success-text); }
.rb-doc-ana .a-bad { color: var(--danger-text); }
.rb-doc-ana .a-skip { color: var(--warning-text); }
/* Paper 3's strip carries words rather than counts, so it drops a step in
   size to keep "Qualifying" inside a card on a 360px screen. */
.rb-doc-ana--words dd { font-size: 0.86rem; font-weight: 800; letter-spacing: -0.01em; }

/* ------------------------------------------------------- 3. EXAM PATTERN -- */
.rb-paper { display: flex; flex-direction: column; gap: 12px; position: relative; overflow: hidden; }
.rb-paper::after {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: var(--brand-grad);
}
.rb-paper--qual::after { background: linear-gradient(90deg, var(--warning), var(--brand-3)); }
.rb-paper-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.rb-paper-tag {
  display: inline-flex; align-items: center;
  padding: 6px 14px;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  color: var(--brand);
}
/* Paper 3 is a gate, not a score: a separate colour so nobody reads it as a
   fourth source of marks. */
.rb-paper-tag--qual { background: color-mix(in srgb, var(--warning) 18%, transparent); color: var(--warning-text); }
.rb-paper-q { margin: 0; font-size: 0.9rem; color: var(--muted); font-weight: 700; }
.rb-paper-q b { font-size: 1.22rem; color: var(--text); font-weight: 800; }
.rb-paper-q--qual { color: var(--warning-text); }
.rb-paper h3 { margin: 0; font-size: 1.3rem; }
.rb-paper-note { margin: 0; font-size: 0.87rem; line-height: 1.55; color: var(--muted); }
.rb-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.rb-chips li {
  padding: 7px 13px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--text-2);
  min-height: 32px;
  display: inline-flex;
  align-items: center;
}
.rb-paper--qual .rb-chips li {
  border-color: color-mix(in srgb, var(--warning) 34%, var(--border));
  background: color-mix(in srgb, var(--warning) 10%, var(--surface));
  color: var(--warning-text);
}

/* ------------------------------------------ 4. PERFORMANCE / TABLE -------- */
/* Phone: the table stops being a table and becomes one card per subject with
   labelled rows — the standard stacked-table pattern. That is what keeps the
   "no horizontal scrolling" promise on a 360px screen without shrinking type
   below the point where it is readable. */
.rb-table-wrap { position: relative; }
.rb-table {
  width: 100%;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}
.rb-table thead th {
  text-align: left;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0 12px 10px;
  border-bottom: 2px solid var(--border);
}
.rb-table td, .rb-table tbody th { padding: 13px 12px; border-bottom: 1px solid var(--border); }
.rb-table tbody th { text-align: left; font-weight: 700; font-size: 0.95rem; }
.rb-table td { text-align: right; font-size: 0.95rem; font-weight: 700; }
.rb-table td:last-child, .rb-table thead th:last-child { text-align: left; }
.rb-table tbody tr { transition: background 0.15s ease; }
.rb-table tbody tr:hover { background: color-mix(in srgb, var(--brand) 5%, transparent); }
.rb-ok { color: var(--success-text); }
.rb-bad { color: var(--danger-text); }
.rb-skip { color: var(--warning-text); }
.rb-paper-pill {
  display: inline-block;
  padding: 4px 11px;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 800;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-2);
  white-space: nowrap;
}

@media (max-width: 719px) {
  .rb-table thead {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  }
  .rb-table, .rb-table tbody, .rb-table tr, .rb-table th, .rb-table td { display: block; }
  .rb-table tbody tr {
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--surface);
    box-shadow: var(--shadow);
    padding: 14px 16px;
    margin-bottom: 12px;
  }
  .rb-table tbody tr:hover { background: var(--surface); }
  .rb-table tbody th {
    padding: 0 0 11px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 6px;
    font-size: 1.02rem;
    font-weight: 800;
  }
  .rb-table td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 7px 0;
    border-bottom: 0;
    text-align: right;
  }
  .rb-table td::before {
    content: attr(data-label);
    font-size: 0.74rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted);
    text-align: left;
  }
  .rb-table td:last-child { justify-content: space-between; }
}

.rb-totals {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-top: 6px;
}
@media (min-width: 780px) { .rb-totals { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.rb-total {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 18px;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--surface);
  min-width: 0;
}
.rb-total-k { font-size: 0.7rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); }
.rb-total-v {
  font-size: clamp(1.5rem, 5vw, 2rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
  overflow-wrap: anywhere;
}

/* ------------------------------------------------------------- CHARTS ---- */
/* Drawn as inline SVG from the table above, so the numbers can never be read
   two different ways. A figure + figcaption pair keeps them announceable, and
   every svg carries its own aria-label with the same sentence. */
.rb-charts {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(16px, 3vw, 20px);
  margin-top: clamp(26px, 4vw, 36px);
}
@media (min-width: 700px) { .rb-charts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .rb-charts { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.rb-chart {
  margin: 0;
  padding: 18px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow);
  min-width: 0;
}
.rb-chart h3 { margin: 0 0 12px; font-size: 1rem; }
.rb-chart figcaption { margin-top: 10px; font-size: 0.8rem; line-height: 1.5; }
.rb-chart-body { min-height: 190px; }
.rb-chart-body svg { display: block; width: 100%; height: auto; overflow: visible; }
/* SVG text is styled in CSS rather than attributes so the dark theme follows
   the same tokens as every other label on the page. Sizes are set for the
   360-unit viewBox: a phone column is ~300px wide, so the 0.83× scale still
   leaves labels at a readable 12px+. */
.rb-chart-body svg text { font-family: inherit; }
.rb-chart-body .c-lab { font-size: 14.5px; font-weight: 700; fill: var(--text-2); }
.rb-chart-body .c-num { font-size: 13.5px; font-weight: 700; fill: var(--muted); }
.rb-chart-body .c-val { font-size: 15px; font-weight: 800; fill: var(--text); }
.rb-chart-body .c-big { font-size: 34px; font-weight: 800; fill: var(--text); letter-spacing: -0.03em; }
.rb-chart-body .c-sub { font-size: 12.5px; font-weight: 700; fill: var(--muted); letter-spacing: 0.06em; text-transform: uppercase; }
.rb-chart-ph { font-size: 0.83rem; color: var(--muted); text-align: center; padding: 24px 8px; }
.rb-legend { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.rb-legend span { display: inline-flex; align-items: center; gap: 6px; font-size: 0.76rem; font-weight: 700; color: var(--muted); }
.rb-legend i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }

/* ------------------------------------------------------- 5. MISTAKES ----- */
.rb-mistake { display: flex; flex-direction: column; gap: 10px; }
.rb-mistake--clean { border-color: color-mix(in srgb, var(--success) 34%, var(--border)); }
/* The shared .badge-warn paints with raw --warning (#f59e0b), which lands at
   1.9:1 on its own tinted background — axe's worst hit on this page. The dark
   amber token is the same hue at 4.6:1 and reads as a warning just the same,
   so the badge is corrected here rather than touching the global rule every
   other page inherits. */
.rb-mistake .badge-warn { color: var(--warning-text); }
.rb-mistake-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.rb-mistake-n {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.rb-mistake h3 { margin: 0; font-size: 1.08rem; line-height: 1.4; }
.rb-why { margin: 0; display: grid; gap: 4px; }
.rb-why dt {
  margin-top: 8px;
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brand);
}
.rb-why dd { margin: 4px 0 0; font-size: 0.92rem; line-height: 1.62; color: var(--muted); }
.rb-src {
  margin: auto 0 0;
  padding-top: 12px;
  border-top: 1px dashed var(--border);
  font-size: 0.75rem;
  color: var(--muted);
}

/* --------------------------------------------------- 6. STRATEGY CARDS --- */
/* <details> gives the expand/collapse for free: no JS, no initial height, no
   layout shift, and the whole row stays a thumb-sized target. */
.rb-strat { display: grid; gap: 12px; }
.rb-strat-item {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.rb-strat-item > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 16px 18px;
  min-height: 54px;
  cursor: pointer;
  list-style: none;
  position: relative;
  -webkit-tap-highlight-color: transparent;
}
.rb-strat-item > summary::-webkit-details-marker { display: none; }
.rb-strat-item > summary::after {
  content: "+";
  flex: none;
  width: 28px; height: 28px;
  display: grid; place-items: center;
  border-radius: 8px;
  background: color-mix(in srgb, var(--brand) 12%, transparent);
  color: var(--brand);
  font-size: 1.1rem;
  font-weight: 800;
  line-height: 1;
  transition: transform 0.2s var(--ease), background 0.2s ease;
}
.rb-strat-item[open] > summary::after { content: "−"; transform: rotate(180deg); }
.rb-strat-item > summary:focus-visible { outline: 3px solid var(--ring); outline-offset: -3px; }
.rb-strat-item > summary h3 { margin: 0; font-size: 1.02rem; font-weight: 800; }
.rb-strat-body { padding: 0 18px 18px; border-top: 1px solid var(--border); margin-top: -1px; }
.rb-strat-body > p:first-child { margin-top: 14px; }
.rb-strat-body p { font-size: 0.93rem; line-height: 1.68; color: var(--muted); }
.rb-strat-body strong, .rb-strat-body b { color: var(--text); }
.rb-blocks { margin-top: 16px; gap: 12px; }
.rb-blocks .card-pad { padding: 16px; }
.rb-blocks h4 { margin: 4px 0 6px; font-size: 0.98rem; }
.rb-blocks p { font-size: 0.87rem; line-height: 1.55; color: var(--muted); margin: 0; }
@media (max-width: 559px) { .rb-strat-item > summary { padding: 15px 16px; } .rb-strat-body { padding: 0 16px 16px; } }

/* ------------------------------------------- 7. ANSWER-SHEET ANALYSIS ---- */
.rb-sheet { display: flex; flex-direction: column; gap: 12px; }
.rb-sheet-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.rb-sheet h3 { margin: 0; font-size: 1.08rem; }
.rb-sheet-qs {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
  overflow: hidden;
}
.rb-sheet-qs > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 15px; min-height: 46px; cursor: pointer; list-style: none;
  font-size: 0.88rem; font-weight: 800; color: var(--brand);
}
.rb-sheet-qs > summary::-webkit-details-marker { display: none; }
.rb-sheet-qs > summary::after { content: "▾"; transition: transform 0.2s var(--ease); }
.rb-sheet-qs[open] > summary::after { transform: rotate(180deg); }
.rb-qlist { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.rb-q { padding: 14px 15px; border-top: 1px solid var(--border); background: var(--surface); min-width: 0; }
.rb-q-head { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.rb-q-n {
  flex: none;
  font-size: 0.74rem; font-weight: 800; letter-spacing: 0.06em;
  color: #fff; background: var(--brand-grad);
  padding: 3px 9px; border-radius: 999px;
}
.rb-q-t { margin: 0; font-size: 0.93rem; line-height: 1.55; color: var(--text); overflow-wrap: anywhere; }
.rb-q-opts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.rb-q-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 999px;
  font-size: 0.8rem; font-weight: 800;
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text-2);
}
.rb-q-opt.is-sel { border-color: color-mix(in srgb, var(--warning) 40%, var(--border)); background: color-mix(in srgb, var(--warning) 12%, var(--surface)); color: var(--warning-text); }
.rb-q-opt.is-right { border-color: color-mix(in srgb, var(--success) 40%, var(--border)); background: color-mix(in srgb, var(--success) 12%, var(--surface)); color: var(--success-text); }
.rb-q-opt.is-wrong { border-color: color-mix(in srgb, var(--danger) 40%, var(--border)); background: color-mix(in srgb, var(--danger) 12%, var(--surface)); color: var(--danger-text); }
.rb-q-exp { margin: 10px 0 0; font-size: 0.87rem; line-height: 1.6; color: var(--muted); }

/* ------------------------------------------------- 8. PRACTICE / BOOKS --- */
.rb-grp { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.rb-grp-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.rb-grp h3 { margin: 0; font-size: 1.1rem; }
.rb-quizlinks { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.rb-quizlinks a {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 46px; padding: 11px 14px;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface-2);
  color: var(--text); text-decoration: none;
  font-size: 0.9rem; font-weight: 700;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.rb-quizlinks a:hover, .rb-quizlinks a:focus-visible {
  border-color: var(--brand);
  background: color-mix(in srgb, var(--brand) 7%, var(--surface));
}
.rb-quizlinks .n {
  flex: none; font-size: 0.76rem; font-weight: 800;
  color: var(--brand); background: color-mix(in srgb, var(--brand) 12%, transparent);
  padding: 3px 9px; border-radius: 999px;
  font-variant-numeric: tabular-nums;
}
.rb-quizlinks .t { min-width: 0; overflow-wrap: anywhere; }

.rb-book { display: flex; flex-direction: column; gap: 9px; min-width: 0; }
.rb-book-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.rb-book h3 { margin: 0; font-size: 1.1rem; line-height: 1.35; }
.rb-book-auth { margin: 0; font-size: 0.85rem; color: var(--brand); font-weight: 700; }
.rb-book-desc { margin: 0; font-size: 0.9rem; line-height: 1.6; color: var(--muted); }
.rb-book-rate { font-size: 0.84rem; font-weight: 800; color: var(--warning-text); font-variant-numeric: tabular-nums; }
.rb-empty-note { font-size: 0.88rem; color: var(--muted); margin: 0; }

/* ------------------------------------------------------------ 9. CTA ---- */
.rb-cta { text-decoration: none; color: inherit; display: flex; flex-direction: column; gap: 4px; }
.rb-cta h3 { margin: 0; font-size: 1.08rem; }
.rb-cta p { margin: 0; font-size: 0.88rem; line-height: 1.55; color: var(--muted); }
.rb-cta .ilink { margin-top: auto; padding-top: 10px; font-weight: 800; font-size: 0.9rem; }
.rb-more { margin-top: clamp(18px, 3vw, 26px); }
.rb-more h3 { margin: 0; font-size: 1rem; }

/* ==========================================================================
 * DOCUMENT VIEWER
 * --------------------------------------------------------------------------
 * A fixed, full-screen dialog: Preview never navigates away. The chrome is one
 * wrapping bar (icon buttons on a phone, labels revealed from 720px up) so the
 * controls are never smaller than a thumb and never pushed off-screen.
 * ========================================================================== */
.rb-viewer {
  position: fixed;
  inset: 0;
  z-index: 320;
  display: flex;
  flex-direction: column;
  background: #070b16;
  color: #e8ecff;
  overscroll-behavior: contain;
}
.rb-viewer[hidden] { display: none; }
body.rbv-open { overflow: hidden; }

.rbv-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
  padding-top: calc(8px + env(safe-area-inset-top, 0px));
  background: rgba(255, 255, 255, 0.05);
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.rbv-id { display: flex; align-items: center; gap: 8px; min-width: 0; order: 1; }
.rbv-type {
  flex: none;
  padding: 3px 9px; border-radius: 6px;
  font-size: 0.66rem; font-weight: 800; letter-spacing: 0.1em;
  background: var(--brand-grad); color: #fff;
}
.rbv-name {
  font-size: 0.86rem; font-weight: 700; color: #cfd6ee;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0;
}
.rbv-tools {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  order: 2;
  min-width: 0;
}
.rbv-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 42px;
  min-height: 42px;
  padding: 0 10px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.07);
  color: #e8ecff;
  font-size: 0.86rem;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
}
.rbv-btn:hover, .rbv-btn:focus-visible { background: rgba(255, 255, 255, 0.16); border-color: rgba(255, 255, 255, 0.34); }
.rbv-btn:disabled, .rbv-btn[aria-disabled="true"] { opacity: 0.35; pointer-events: none; }
.rbv-btn.rbv-x { background: color-mix(in srgb, var(--danger) 30%, transparent); border-color: transparent; }
.rbv-wide { display: none; }
.rbv-sep { width: 1px; align-self: stretch; background: rgba(255, 255, 255, 0.16); }
.rbv-page, .rbv-zoom {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 42px;
  padding: 0 8px;
  font-size: 0.82rem;
  font-weight: 700;
  color: #cfd6ee;
  font-variant-numeric: tabular-nums;
}
.rbv-page input {
  width: 46px;
  min-height: 34px;
  padding: 4px 6px;
  text-align: center;
  font: inherit;
  font-weight: 800;
  color: #fff;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  -moz-appearance: textfield;
}
.rbv-page input::-webkit-outer-spin-button,
.rbv-page input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.rbv-stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 14px;
  touch-action: pan-x pan-y pinch-zoom;
}
.rbv-stage:focus-visible { outline: 3px solid var(--ring); outline-offset: -3px; }
.rbv-canvas, .rbv-img {
  display: block;
  margin: auto;
  background: #fff;
  box-shadow: 0 18px 48px -18px rgba(0, 0, 0, 0.85);
  max-width: none;
  transform-origin: center center;
}
.rbv-img { height: auto; }
.rbv-spin {
  position: absolute;
  top: 50%; left: 50%;
  width: 42px; height: 42px;
  margin: -21px 0 0 -21px;
  border: 3px solid rgba(255, 255, 255, 0.18);
  border-top-color: var(--brand-2);
  border-radius: 50%;
  animation: rbvSpin 0.8s linear infinite;
}
@keyframes rbvSpin { to { transform: rotate(360deg); } }
.rbv-msg {
  margin: auto;
  max-width: 46ch;
  text-align: center;
  font-size: 0.92rem;
  line-height: 1.6;
  color: #b4beda;
}
.rbv-msg a { color: #a5b4fc; font-weight: 800; }
.rbv-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 12px calc(8px + env(safe-area-inset-bottom, 0px));
  font-size: 0.74rem;
  color: #8b97b5;
  background: rgba(255, 255, 255, 0.04);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.rbv-foot #rbvHint { display: none; }

@media (min-width: 720px) {
  .rbv-wide { display: inline-flex; }
  .rbv-foot #rbvHint { display: inline; }
  .rbv-bar { padding-inline: 14px; }
}

/* The viewer is a fixed overlay, so it owns the viewport: at 720px and up it
   drops the wrap-by-default toolbar for a single locked row. */
@media (max-width: 479px) {
  .rbv-id { order: 2; width: 100%; }
  .rbv-tools { order: 1; width: 100%; justify-content: space-between; }
  .rbv-name { white-space: normal; }
}

/* ------------------------------------------------------------ reduced ---- */
@media (prefers-reduced-motion: reduce) {
  .rb-strat-item > summary::after,
  .rb-sheet-qs > summary::after,
  .rbv-spin { animation: none !important; transition: none !important; }
  .rb-fact--link:hover { transform: none; }
}

/* current-affairs.html and /current-affairs/<language> - the two doors and
   the month-by-month magazine list. */
.ca-door h2 { margin: 6px 0 6px; font-size: clamp(1.15rem, 2.4vw, 1.4rem); }
.ca-months { display: grid; gap: 16px; }
.ca-month-head {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 8px 16px; margin-bottom: 8px;
}
.ca-month-head h3 { margin: 0; }
.ca-month-links { display: inline-flex; gap: 14px; font-size: .9rem; }
.ca-month .part-list { margin: 0; }
.ca-month .part-list li { justify-content: flex-start; flex-wrap: wrap; }
.ca-month .part-list li a { flex: 1 1 auto; font-weight: 600; }
@media (max-width: 560px) { .ca-month .part-meta { flex-basis: 100%; white-space: normal; } }
.ca-month .badge { margin-right: 6px; vertical-align: middle; }

