/*
  Hand-maintained CSS - NOT touched by the Tailwind build.

  dist/output.css is generated by the Tailwind CLI and gets fully overwritten
  every time that build runs, so anything added there by hand disappears on
  the next rebuild. This file exists for that case: styling that's too
  fiddly to express as Tailwind utility classes, or genuinely custom rules
  scoped to their own class name (e.g. .spec-table th).

  HARD RULE: never put plain re-declarations of Tailwind's own utility class
  names in here (w-*, p-*, etc.) - even ones that exactly match output.css.
  Tried that 2026-08-14 with the w-* width scale and it broke the homepage:
  this file loads as a second stylesheet AFTER output.css, so an unconditional
  rule here (e.g. .w-full { width: 100%; }) sits later in the cascade than
  output.css's OWN responsive override for that same utility category
  (e.g. @media (min-width:768px) { .md\:w-2\/5 { width: 40%; } }). Same
  specificity, later source position wins - so the duplicate silently beats
  the md:/lg:/etc. variant at every breakpoint where it should have applied,
  even though the duplicated rule was byte-identical to output.css's own.
  This isn't about staleness or correctness of the copied value - it breaks
  regardless, for any utility category that has responsive variants in use
  anywhere in the codebase (which is most of them). Only ever add rules here
  under class names Tailwind doesn't also generate.

  Linked once in header_tailwind.php, loaded on every page.

  WORKING MODE (from 2026-08-14, until the pending Tailwind rebuild is
  done): dist/output.css is a known-stale build, and rebuilding it is its
  own separate, riskier migration the user wants to do as one deliberate
  batch, not incrementally. Until that happens, new/actively-changing
  elements get real hand-written CSS under their own custom class names
  here instead of Tailwind utility classes - renders immediately, no
  rebuild dependency, and can't hit the cascade bug above since a custom
  class name never collides with Tailwind's own utility namespace. This
  doesn't apply retroactively to existing already-working Tailwind-classed
  pages - only to new work done during this period.
*/

/*
  Sticky footer layout (2026-08-14): keeps the footer pinned to the bottom
  of the viewport on pages whose content doesn't fill the screen, instead
  of floating up under sparse content. body is flex/column, .site-main
  (wrapping all per-page content between the nav and the footer, opened in
  header_tailwind.php / closed in footer_tailwind.php) grows to fill the
  remaining space, footer takes its natural height. nav was originally
  position:fixed so it sat outside this flow; since 2026-08-11 (see the
  site-wide palette/nav block below) it's position:sticky instead, still a
  normal flex child that doesn't need to be inside .site-main.
*/
body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background-color: var(--te-bg);
  color: var(--te-slate-600);
  font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.site-main {
  flex-grow: 1;
  width: 100%;
}

/*
  Footer redesign (2026-08-14): reskin of a footer design the user liked
  (grid of link columns, exam-board trust badge, bottom meta strip with
  social icons), adapted from its original dark-navy theme to this site's
  own white/pink/sky palette, and from its placeholder content to
  thinkeconomics' actual exam boards. Structure and responsive behaviour
  (2-column grid on mobile, 4-column from 768px, bottom strip switching
  from stacked to a row with reordering) preserved as requested - same
  768px breakpoint the rest of the site uses for md:.

  Repalette (2026-08-11): recoloured to the blue/pink/slate --te-* variables
  introduced for the nav/homepage redesign further down this file, so the
  footer stops clashing with the new nav. Content and structure untouched -
  this is a colour/font pass only, using the same custom class names.
*/
.site-footer {
  background-color: var(--te-bg-alt);
  color: var(--te-slate-600);
  padding: 40px 20px 20px 20px;
  font-size: 0.95rem;
  border-top: 1px solid var(--te-border);
}

.site-footer-inner {
  max-width: 64rem; /* matches Tailwind's max-w-5xl */
  margin: 0 auto;
}

.footer-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 30px;
  margin-bottom: 40px;
}

.footer-col h3 {
  color: var(--te-slate-500);
  font-weight: 700;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 15px;
}

.footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.footer-col ul li {
  margin-bottom: 10px;
}

.footer-col ul li a {
  color: var(--te-slate-800);
  text-decoration: none;
  transition: color 0.2s;
}

.footer-col ul li a:hover {
  color: var(--te-blue);
}

.exam-badge {
  grid-column: span 2;
  background-color: var(--te-blue-light);
  padding: 12px;
  border-radius: 6px;
  text-align: center;
  font-size: 0.85rem;
  color: var(--te-slate-800);
  border-left: 4px solid var(--te-blue);
}

.exam-badge strong {
  color: var(--te-blue-dark);
}

.footer-bottom {
  border-top: 1px solid var(--te-border);
  padding-top: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
  text-align: center;
}

.footer-socials {
  display: flex;
  gap: 20px;
}

.footer-socials a {
  color: var(--te-slate-400);
  transition: color 0.2s, transform 0.2s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.footer-socials svg {
  width: 20px;
  height: 20px;
  fill: currentColor;
}

.footer-socials a:hover {
  color: var(--te-blue);
  transform: translateY(-2px);
}

.footer-legal {
  display: flex;
  gap: 15px;
  font-size: 0.85rem;
}

.footer-legal a {
  color: var(--te-slate-500);
  text-decoration: none;
}

.footer-legal a:hover {
  color: var(--te-blue);
}

.footer-copyright {
  font-size: 0.85rem;
  color: var(--te-slate-400);
}

/* Desktop layout upgrades - same 768px breakpoint as the rest of the site's md: */
@media (min-width: 768px) {
  .site-footer {
    padding: 60px 40px 30px 40px;
  }

  .footer-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 40px;
  }

  .exam-badge {
    grid-column: span 4;
    text-align: left;
  }

  .footer-bottom {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    text-align: left;
  }

  .footer-legal {
    order: 2;
  }

  .footer-copyright {
    order: 1;
  }
}

/*
  MCQ hub page redesign (2026-08-14): card-based layout adapted from a
  design the user liked, reskinned to the site's own pink/sky/gray palette
  instead of its original blue/purple theme, and using the site's own
  body font (Source Sans Pro, already set on <body> in header_tailwind.php)
  instead of the original's system-font stack. This page deliberately opts
  out of the shared page_top.php/page_bottom.php shell (see that file) -
  the bold unboxed title and card sections here are a different visual
  language on purpose, not an oversight.
  Colors sourced from output.css's compiled values where already present
  there, otherwise from an isolated scratch Tailwind build (gray-50,
  pink-600, gray-600, pink-200) - not typed from memory.

  Repalette (2026-08-11): recoloured to the blue/pink/slate --te-* variables
  from the nav/homepage redesign further down this file, so this page
  matches index.php and the nav instead of the old pink/sky theme. Body
  font already switched to system-ui globally (see the body{} rule above),
  so no font-family override is needed here either. Structure/content and
  the page_top.php/page_bottom.php opt-out are unchanged - colour pass only.
*/
.mcq-page {
  max-width: 48rem;
  margin: 3rem auto;
  padding: 0 1rem;
  color: var(--te-slate-800);
}

.mcq-title {
  font-size: 1.875rem;
  line-height: 2.25rem;
  font-weight: 700;
  color: var(--te-slate-800);
  letter-spacing: -0.025em;
  margin-bottom: 2rem;
}

.mcq-promo {
  background: linear-gradient(135deg, var(--te-blue-light) 0%, var(--te-pink-light) 100%);
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  padding: 2rem;
  text-align: center;
  margin-bottom: 2.5rem;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.05);
}

.generator-btn {
  display: inline-block;
  background-color: var(--te-pink);
  color: #ffffff;
  font-weight: 500;
  font-size: 1.125rem;
  padding: 0.75rem 2rem;
  border-radius: 0.5rem;
  text-decoration: none;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
  margin-bottom: 0.75rem;
  transition: all 0.2s ease;
}

.generator-btn:hover {
  background-color: var(--te-pink-dark);
  transform: translateY(-1px);
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}

.mcq-promo-tagline {
  color: var(--te-slate-600);
  font-size: 0.875rem;
  margin: 0;
  font-weight: 500;
}

.mcq-sections {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

/*
  .card-* below (2026-08-11): renamed from .mcq-section/.mcq-section-title/
  .mcq-section-body/.mcq-category-title/.mcq-link-list/.quiz-link so this
  card-list pattern can be shared with user/dashboard.php, which now uses
  the identical look ("make dashboard look like cards, the way mcq.php
  does"). .mcq-page/.mcq-title/.mcq-promo/.generator-btn/.mcq-sections stay
  MCQ-hub-specific - only the reusable card/list pieces were renamed.
*/
.card-section {
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.05);
  overflow: hidden;
}

.card-section-title {
  background-color: var(--te-bg-alt);
  border-bottom: 1px solid var(--te-border);
  border-top: 4px solid var(--te-blue);
  padding: 0.75rem 1.25rem;
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--te-slate-800);
  margin: 0;
}

.card-section-body {
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

/*
  Prose defaults for bare <ul>/<li>/<a> inside .card-section-body (2026-08-23) - Tailwind's
  preflight reset strips default browser list-style and link colour/underline everywhere, and this
  card system never restored them, so every plain-prose <ul>/<a> written into a .card-section-body
  page (privacy.php, terms.php, cookies.php, faq.php, about.php, contact.php, for-schools.php, the
  two guide-*.php walkthroughs) was rendering as unbulleted lines with invisible links - caught on
  terms.php's Accounts section. :not([class]) scopes this to genuinely bare tags only, so it can
  never win against a more specific styled list like .card-link-list/.card-link (dashboard.php's
  nav-link rows, which deliberately have no bullets/underlines) - those always carry a class, so
  this rule simply doesn't match them.
*/
.card-section-body ul:not([class]) {
  list-style: disc;
  margin: 0 0 1rem 1.5rem;
  padding: 0;
}

.card-section-body li:not([class]) {
  margin-bottom: 0.375rem;
  line-height: 1.6;
}

.card-section-body a:not([class]) {
  color: var(--te-blue);
  text-decoration: underline;
}

.card-section-body a:not([class]):hover {
  color: var(--te-pink);
}

/*
  .card-section-highlight (2026-08-13): a bold pink/magenta variant of .card-section for the
  dashboard's "Get Started" card - onboarding steps an unverified teacher still needs to do, which
  otherwise looked identical to (and got lost among) every other informational card on the page.
*/
.card-section-highlight {
  border-color: var(--te-pink);
  box-shadow: 0 0 0 2px var(--te-pink-light), 0 4px 12px 0 rgba(219, 39, 119, 0.15);
}

.card-section-highlight .card-section-title {
  background: linear-gradient(to right, var(--te-pink), var(--te-pink-dark));
  border-top: none;
  color: #ffffff;
}

.card-section-highlight .card-section-body {
  background-color: var(--te-pink-light);
}

.card-category-title {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--te-pink);
  margin-top: 0;
  margin-bottom: 0.75rem;
}

.card-link-list {
  list-style-type: none;
  padding: 0;
  margin: 0;
  border: 1px solid var(--te-border);
  border-radius: 0.5rem;
  overflow: hidden;
}

.card-link-list li {
  border-bottom: 1px solid var(--te-border);
}

.card-link-list li:last-child {
  border-bottom: none;
}

.card-link {
  display: block;
  padding: 0.75rem 1rem;
  color: var(--te-slate-800);
  text-decoration: none;
  font-size: 0.875rem;
  transition: all 0.2s ease-in-out;
}

.card-link:hover {
  background-color: var(--te-blue-light);
  color: var(--te-blue-dark);
  padding-left: 1.5rem;
}

/*
  mcq.php Phase 2 tiering (2026-08-20): a quiz's row is either a normal .card-link (public, or the
  visitor already has access) or this locked variant - same layout, muted colour, a small lock
  glyph, and it's still a real link (to /login.php) rather than plain disabled text, so a visitor
  can act on it immediately instead of hunting for a login link elsewhere. .tier-badge is the small
  "Free"/"Paid" pill shown next to a non-public quiz's name either way, so a visitor understands the
  tiering even once they're logged in and everything's unlocked.
*/
.card-link-locked {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  color: var(--te-slate-500);
  text-decoration: none;
  font-size: 0.875rem;
  transition: all 0.2s ease-in-out;
}

.card-link-locked:hover {
  background-color: var(--te-bg-alt);
  color: var(--te-slate-600);
  padding-left: 1.5rem;
}

.card-link-locked-hint {
  font-size: 0.75rem;
  color: var(--te-slate-400);
  white-space: nowrap;
}

.tier-badge {
  display: inline-block;
  font-size: 0.688rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  margin-left: 0.5rem;
  vertical-align: middle;
}

.tier-badge-free {
  background-color: var(--te-blue-light);
  color: var(--te-blue-dark);
}

.tier-badge-paid {
  background-color: #fffbeb;
  color: #92400e;
}

/*
  Site-wide palette/font + nav + homepage redesign (2026-08-11): unlike the
  footer and MCQ hub redesigns above (which kept the site's existing
  pink/sky palette and Source Sans Pro), this one adopts the reference
  mockup's OWN blue/pink/slate palette and system-ui font stack, at the
  user's explicit request. The nav lives in header_tailwind.php and is
  shared by every page, so this is a genuine site-wide visual change, not
  something scoped to index.php - the footer and MCQ hub keep their old
  pink/sky styling for now and will look mismatched against the new nav
  until they get their own follow-up pass. Colors/font copied verbatim
  from design_examples/home_example.html, not typed from memory.

  Nav is position:sticky (was position:fixed) and permanently glass -
  translucent white + backdrop-filter blur - rather than transparent-at-top-
  then-opaque-on-scroll, so the old scroll listener that swapped nav
  background classes was deleted from footer_tailwind.php; the mobile
  link-list toggle now uses a custom .nav-open class instead of Tailwind's
  .hidden (see this file's header comment on why a hand-written rule here
  can never redeclare a Tailwind utility class name).

  Pricing section from the mockup (£0/£4.99/£9.99 tiers) was dropped -
  thinkeconomics has no billing system, accounts are teacher-provisioned -
  and replaced with a real Student/Teacher/Admin access section instead
  (.home-access-*), reusing the mockup's 3-card layout with true content.
*/
:root {
  --te-blue: #2563eb;
  --te-blue-dark: #1d4ed8;
  --te-blue-light: #e0f2fe;
  --te-pink: #db2777;
  --te-pink-dark: #be185d;
  --te-pink-light: #fae8ff;
  --te-slate-900: #0f172a;
  --te-slate-800: #1e293b;
  --te-slate-600: #475569;
  --te-slate-500: #64748b;
  --te-slate-400: #94a3b8;
  --te-border: #e2e8f0;
  --te-bg: #fafafa;
  --te-bg-alt: #f8fafc;
}

/*
  scroll-padding-top (2026-08-14): .site-nav below is sticky, not part of document flow removed on
  scroll, so any jump to an in-page target - the #section fragments page_top.php's "Back to
  Dashboard" link can carry, a plain scrollIntoView() call like user_populate.php's CSV-load jump,
  or a native #anchor URL - was landing with its top edge flush against the very top of the
  viewport, which the nav then covers. This offsets every such scroll (native and JS-driven alike -
  scrollIntoView() respects scroll-padding on the scrolling box in all evergreen browsers) so
  targets land just below the nav instead. Generous rather than exact-measured, since nav height
  isn't fixed (content-driven, responsive) - a little extra clearance is harmless, landing under the
  nav isn't.
*/
html {
  scroll-padding-top: 100px;
}

/* --- Nav --- */
.site-nav {
  position: sticky;
  top: 0;
  background-color: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--te-border);
  z-index: 50;
  padding: 1rem 0;
}

.site-nav-inner {
  max-width: 72rem;
  margin: 0 auto;
  padding: 0 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
}

.site-logo {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 800;
  font-size: 1.25rem;
  color: var(--te-slate-800);
  text-decoration: none;
  letter-spacing: -0.025em;
}

.site-logo:hover {
  text-decoration: none;
}

.site-logo-icon {
  height: 1.75rem;
  width: 1.75rem;
  flex-shrink: 0;
}

.site-logo-accent {
  background: linear-gradient(to right, var(--te-blue), var(--te-pink));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.nav-toggle-btn {
  display: flex;
  align-items: center;
  padding: 0.25rem;
  background: none;
  border: none;
  color: var(--te-slate-600);
  cursor: pointer;
}

.nav-toggle-icon {
  width: 1.5rem;
  height: 1.5rem;
  fill: currentColor;
}

.site-nav-links {
  display: none;
  flex-direction: column;
  align-items: stretch;
  gap: 0.25rem;
  width: 100%;
  margin-top: 1rem;
}

.site-nav-links.nav-open {
  display: flex;
}

.nav-link {
  font-size: 0.937rem;
  font-weight: 500;
  color: var(--te-slate-500);
  text-decoration: none;
  padding: 0.625rem 0.25rem;
  transition: color 0.2s ease;
}

.nav-link:hover {
  color: var(--te-blue);
  text-decoration: none;
}

.nav-link-highlight {
  color: var(--te-blue);
  font-weight: 600;
}

.nav-signin-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 0.937rem;
  color: #ffffff;
  background: linear-gradient(to right, var(--te-blue), var(--te-pink));
  padding: 0.625rem 1.25rem;
  border-radius: 0.375rem;
  border: none;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
  margin-top: 0.5rem;
  transition: filter 0.2s ease, box-shadow 0.2s ease;
}

.nav-signin-btn:hover {
  filter: brightness(0.92);
  box-shadow: 0 4px 6px -1px rgba(219, 39, 119, 0.25);
}

@media (min-width: 1024px) {
  .nav-toggle-btn {
    display: none;
  }

  .site-nav-links {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 1.5rem;
    width: auto;
    margin-top: 0;
  }

  .nav-link {
    padding: 0;
  }

  .nav-signin-btn {
    margin-top: 0;
  }
}

/* --- Homepage: hero --- */
.home-hero {
  background: linear-gradient(135deg, #e0f2fe 0%, #fae8ff 100%);
  border-bottom: 1px solid #f3e8ff;
  padding: 4rem 1.5rem 5rem;
}

.home-hero-inner {
  max-width: 72rem;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr;
  gap: 3rem;
  align-items: center;
}

@media (min-width: 768px) {
  .home-hero-inner {
    grid-template-columns: 1fr 1fr;
    gap: 4rem;
  }
}

.home-hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background-color: rgba(255, 255, 255, 0.7);
  padding: 0.375rem 0.75rem;
  border-radius: 9999px;
  border: 1px solid #f0e1f7;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--te-pink);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 1.5rem;
}

.home-hero-heading {
  font-size: 2.5rem;
  line-height: 1.15;
  font-weight: 800;
  color: var(--te-slate-800);
  letter-spacing: -0.03em;
  margin: 0 0 1.25rem 0;
}

@media (min-width: 768px) {
  .home-hero-heading {
    font-size: 3rem;
  }
}

.home-hero-heading-accent {
  background: linear-gradient(to right, var(--te-blue), var(--te-pink));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

.home-hero-sub {
  font-size: 1.125rem;
  line-height: 1.6;
  color: var(--te-slate-600);
  margin: 0 0 2rem 0;
  max-width: 30rem;
}

.home-hero-generator {
  margin-bottom: 2rem;
}

.courier-banner-btn {
  display: inline-block;
  font-family: 'Courier New', Courier, monospace;
  font-weight: 700;
  font-size: 1.125rem;
  background-color: #bae6fd;
  color: #0369a1;
  padding: 0.875rem 2rem;
  text-decoration: underline;
  border: 3px solid #fbcfe8;
  border-radius: 0.5rem;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
  transition: all 0.2s ease-in-out;
}

.courier-banner-btn:hover {
  background-color: #fbcfe8;
  color: #9d174d;
  border-color: #bae6fd;
  transform: translateY(-1px);
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.05);
}

.home-hero-generator-tagline {
  font-size: 0.875rem;
  color: var(--te-slate-600);
  margin: 0.5rem 0 0 0;
  font-weight: 500;
}

.home-hero-ctas {
  display: flex;
  gap: 1rem;
  align-items: center;
  flex-wrap: wrap;
}

.btn-pink {
  display: inline-block;
  background-color: var(--te-pink);
  color: #ffffff;
  font-weight: 600;
  font-size: 1rem;
  padding: 0.75rem 2rem;
  border-radius: 0.5rem;
  text-decoration: none;
  box-shadow: 0 4px 6px -1px rgba(219, 39, 119, 0.2);
  transition: all 0.2s ease;
  border: none;
  cursor: pointer;
}

.btn-pink:hover {
  background-color: var(--te-pink-dark);
  transform: translateY(-1px);
  box-shadow: 0 10px 15px -3px rgba(219, 39, 119, 0.3);
  color: #ffffff;
  text-decoration: none;
}

.btn-pink-lg {
  padding: 1rem 2.5rem;
  font-size: 1.125rem;
}

.btn-outline-blue {
  display: inline-block;
  border: 2px solid var(--te-blue);
  color: var(--te-blue);
  font-weight: 600;
  font-size: 1rem;
  padding: 0.625rem 2rem;
  border-radius: 0.5rem;
  text-decoration: none;
  transition: all 0.2s ease;
}

.btn-outline-blue:hover {
  background-color: #eff6ff;
  text-decoration: none;
}

.home-hero-art {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
}

.home-hero-art svg {
  max-width: 100%;
  height: auto;
  position: relative;
  z-index: 1;
}

.home-hero-art-glow {
  position: absolute;
  width: 100%;
  height: 100%;
  background: radial-gradient(circle, rgba(219, 39, 119, 0.12) 0%, rgba(255, 255, 255, 0) 70%);
  top: -10%;
  left: 10%;
}

/* --- Homepage: shared section chrome --- */
.home-section {
  padding: 4.5rem 1.5rem;
}

.home-section-white {
  background-color: #ffffff;
  border-bottom: 1px solid var(--te-border);
}

.home-section-alt {
  background-color: var(--te-bg-alt);
  border-bottom: 1px solid var(--te-border);
}

.home-section-inner {
  max-width: 72rem;
  margin: 0 auto;
}

.home-section-head {
  text-align: center;
  max-width: 34rem;
  margin: 0 auto 3.5rem auto;
}

.home-section-eyebrow {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--te-blue);
  letter-spacing: 0.1em;
  display: block;
  margin-bottom: 0.5rem;
}

.home-section-title {
  font-size: 1.875rem;
  font-weight: 800;
  color: var(--te-slate-800);
  margin: 0;
}

/* --- Homepage: founding story (2026-10-03) --- */
.home-story-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  align-items: start;
}

@media (min-width: 900px) {
  .home-story-grid {
    grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
    gap: 3rem;
  }
}

.home-story-letter {
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  padding: 2.5rem 2rem;
  color: var(--te-slate-600);
  font-size: 1.05rem;
  line-height: 1.7;
}

.home-story-letter p {
  margin: 0 0 1.1rem 0;
}

.home-story-lead {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--te-slate-800);
  line-height: 1.5;
}

.home-story-pun {
  font-weight: 700;
  color: var(--te-pink);
}

.home-story-pun-aside {
  font-weight: 400;
  font-size: 0.9rem;
  color: var(--te-slate-500);
}

.home-story-signoff {
  border-top: 1px solid var(--te-border);
  margin-top: 1.75rem;
  padding-top: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.home-story-name {
  font-weight: 800;
  color: var(--te-slate-800);
}

.home-story-role {
  font-size: 0.9rem;
  color: var(--te-slate-500);
}

.home-story-role a {
  color: var(--te-blue);
  font-weight: 600;
  text-decoration: none;
}

.home-story-role a:hover {
  text-decoration: underline;
}

.home-story-side {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

.home-story-stat {
  background: linear-gradient(135deg, var(--te-blue-light) 0%, var(--te-pink-light) 100%);
  border-radius: 0.75rem;
  padding: 1.75rem 2rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.home-story-stat-number {
  font-size: 2.75rem;
  font-weight: 800;
  line-height: 1;
  color: var(--te-blue);
}

.home-story-stat-label {
  font-weight: 600;
  color: var(--te-slate-800);
  line-height: 1.4;
}

.home-story-proof {
  margin: 0;
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  border-left: 4px solid var(--te-pink);
  border-radius: 0.5rem;
  padding: 1.5rem 1.75rem;
  font-size: 1.05rem;
  font-style: italic;
  color: var(--te-slate-800);
  line-height: 1.6;
}

.home-story-principle {
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  padding: 1.75rem 2rem;
}

.home-story-principle h3 {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--te-slate-800);
  margin: 0 0 0.5rem 0;
}

.home-story-principle p {
  color: var(--te-slate-600);
  margin: 0 0 0.75rem 0;
}

.home-story-principle ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  color: var(--te-slate-600);
  line-height: 1.55;
}

.home-story-principle strong {
  color: var(--te-slate-800);
}

/* --- For Schools: 2026-27 free-subscription offer panel (for-schools.php, 2026-10-03) --- */
.schools-offer-panel {
  background: linear-gradient(135deg, var(--te-blue-light) 0%, var(--te-pink-light) 100%);
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  padding: 2rem 2rem 2.25rem;
  margin-bottom: 1.25rem;
}

.schools-offer-eyebrow {
  display: block;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--te-pink);
  margin-bottom: 0.5rem;
}

.schools-offer-panel h2 {
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1.3;
  color: var(--te-slate-800);
  margin: 0 0 1rem 0;
}

.schools-offer-panel p {
  color: var(--te-slate-600);
  line-height: 1.65;
  margin: 0 0 0.9rem 0;
}

.schools-offer-panel .btn-pink {
  display: inline-block;
  margin-top: 0.5rem;
}

/* --- Testimonial preview (testimonial-preview.php, 2026-10-03) - reuses .home-testimonial-card
   so the giver sees exactly the landing-page rendering --- */
.testimonial-preview-page {
  background: linear-gradient(135deg, var(--te-blue-light) 0%, var(--te-pink-light) 100%);
  padding: 3.5rem 1.5rem 4.5rem;
}

.testimonial-preview-inner {
  max-width: 44rem;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 2rem;
}

.testimonial-preview-intro {
  text-align: center;
}

.testimonial-preview-intro h1 {
  font-size: 1.875rem;
  font-weight: 800;
  color: var(--te-slate-800);
  margin: 0 0 0.75rem 0;
}

.testimonial-preview-intro p,
.testimonial-preview-next p {
  color: var(--te-slate-600);
  line-height: 1.6;
  margin: 0;
}

.testimonial-preview-frame .home-testimonial-card {
  background-color: #ffffff;
}

.testimonial-preview-next {
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  padding: 1.5rem 1.75rem;
}

.testimonial-preview-next h2 {
  font-size: 1.15rem;
  font-weight: 800;
  color: var(--te-slate-800);
  margin: 0 0 0.5rem 0;
}

.testimonial-preview-form {
  margin: 1.25rem 0 0 0;
}

.testimonial-preview-form button {
  border: none;
  cursor: pointer;
  font-size: 1rem;
}

.testimonial-preview-confirmed {
  border-left: 4px solid #15803d;
}

.testimonial-admin-confirmed {
  display: inline-block;
  margin-top: 0.4rem;
  font-size: 0.75rem;
}

.testimonial-admin-link {
  font-size: 0.75rem;
  word-break: break-all;
  color: var(--te-slate-500);
}

/* --- Testimonial manager (user/testimonial_manager.php, 2026-10-03) --- */
.testimonial-admin-table-wrap {
  overflow-x: auto;
}

.testimonial-admin-quote {
  max-width: 22rem;
  font-size: 0.875rem;
  line-height: 1.5;
}

/* Scoped under .testimonial-admin-actions so these beat .btn-secondary/.btn-danger (defined later
   in this file) and the card's link colour/underline on the Edit <a> - every action button the same
   width, height and style. */
.testimonial-admin-actions {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  width: 10rem;
}

.testimonial-admin-actions form {
  margin: 0;
}

.testimonial-admin-actions .testimonial-admin-btn,
.testimonial-admin-actions .testimonial-admin-btn:visited {
  display: block;
  width: 100%;
  box-sizing: border-box;
  padding: 0.45rem 0.6rem;
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  text-align: center;
  text-decoration: none;
  color: var(--te-slate-600);
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  border-radius: 0.5rem;
  cursor: pointer;
}

.testimonial-admin-actions .testimonial-admin-btn:hover {
  background-color: var(--te-bg-alt);
  border-color: var(--te-slate-400);
  text-decoration: none;
}

.testimonial-admin-actions .testimonial-admin-btn-danger {
  color: #ffffff;
  background-color: #dc2626;
  border-color: #dc2626;
}

.testimonial-admin-actions .testimonial-admin-btn-danger:hover {
  background-color: #b91c1c;
  border-color: #b91c1c;
}

.testimonial-admin-delete {
  margin-top: 0.4rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--te-border);
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.testimonial-admin-delete label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.75rem;
  color: var(--te-slate-500);
}

/* --- Homepage: Student/Teacher capability cards --- */
.home-features-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
}

@media (min-width: 768px) {
  .home-features-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.home-feature-card {
  background-color: var(--te-bg-alt);
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  padding: 2.5rem 2rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.home-feature-icon {
  width: 3rem;
  height: 3rem;
  border-radius: 0.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.25rem;
  font-size: 1.5rem;
}

.home-feature-icon-blue {
  background-color: var(--te-blue-light);
  color: #0284c7;
}

.home-feature-icon-pink {
  background-color: var(--te-pink-light);
  color: #c026d3;
}

.home-feature-card h3 {
  font-size: 1.375rem;
  font-weight: 700;
  color: var(--te-slate-800);
  margin: 0 0 1rem 0;
}

.home-feature-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  color: var(--te-slate-600);
  font-size: 0.937rem;
  line-height: 1.6;
}

.home-feature-list strong {
  color: var(--te-slate-800);
}

.home-feature-card-footer {
  margin-top: 2rem;
}

.btn-card {
  display: inline-block;
  background-color: var(--te-blue);
  color: #ffffff;
  font-weight: 500;
  font-size: 0.875rem;
  padding: 0.5rem 1.25rem;
  border-radius: 0.375rem;
  text-decoration: none;
  transition: background-color 0.2s ease;
}

.btn-card:hover {
  background-color: var(--te-blue-dark);
  text-decoration: none;
}

/* --- Homepage: Testimonials (2026-08-22) --- */
.home-testimonials-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}

@media (min-width: 768px) {
  .home-testimonials-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* A lone testimonial spans the row, centred, rather than sitting half-width on the left */
  .home-testimonial-card:only-child {
    grid-column: 1 / -1;
    justify-self: center;
    max-width: 44rem;
  }
}

.home-testimonial-card {
  background-color: var(--te-bg-alt);
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  padding: 2rem;
}

.home-testimonial-quote {
  font-size: 1.05rem;
  color: var(--te-slate-800);
  line-height: 1.6;
  margin: 0 0 1.25rem 0;
}

.home-testimonial-quote::before {
  content: "\201C";
  color: var(--te-blue);
  font-weight: 800;
}

.home-testimonial-quote::after {
  content: "\201D";
  color: var(--te-blue);
  font-weight: 800;
}

.home-testimonial-attribution {
  display: flex;
  flex-direction: column;
}

.home-testimonial-name {
  font-weight: 700;
  color: var(--te-slate-800);
  font-size: 0.937rem;
}

.home-testimonial-role {
  color: var(--te-slate-500);
  font-size: 0.812rem;
}

.btn-card-pink {
  background-color: var(--te-pink);
}

.btn-card-pink:hover {
  background-color: var(--te-pink-dark);
}

/* --- Homepage: Student/Teacher/Admin access cards (replaces mockup's fake pricing) --- */
.home-access-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  justify-items: center;
}

@media (min-width: 768px) {
  .home-access-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.home-access-card {
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  padding: 2.5rem 2rem;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.02);
  width: 100%;
  max-width: 20rem;
}

.home-access-card-featured {
  border: 2px solid var(--te-blue);
  box-shadow: 0 10px 15px -3px rgba(37, 99, 235, 0.05);
  position: relative;
}

.home-access-card-tag {
  position: absolute;
  top: -0.75rem;
  left: 50%;
  transform: translateX(-50%);
  background-color: var(--te-blue);
  color: #ffffff;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  padding: 0.25rem 0.75rem;
  border-radius: 9999px;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.home-access-card h3 {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--te-slate-500);
  text-transform: uppercase;
  margin: 0 0 1rem 0;
}

.home-access-card-featured h3 {
  color: var(--te-blue);
}

.home-access-card p {
  color: var(--te-slate-600);
  font-size: 0.937rem;
  line-height: 1.6;
  margin: 0 0 1.5rem 0;
}

.home-access-list {
  list-style: none;
  padding: 0;
  margin: 0 0 2rem 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  font-size: 0.937rem;
  color: var(--te-slate-600);
}

.home-access-btn {
  display: block;
  text-align: center;
  font-weight: 600;
  padding: 0.625rem;
  border-radius: 0.5rem;
  text-decoration: none;
}

.home-access-btn:hover {
  text-decoration: none;
}

.home-access-btn-light {
  background-color: #f1f5f9;
  color: var(--te-slate-600);
}

.home-access-btn-blue {
  background-color: var(--te-blue);
  color: #ffffff;
}

.home-access-btn-dark {
  background-color: var(--te-slate-800);
  color: #ffffff;
}

/* --- Homepage: closing CTA banner --- */
.home-cta-banner {
  background: linear-gradient(135deg, var(--te-slate-800) 0%, var(--te-slate-900) 100%);
  color: #ffffff;
  padding: 5rem 1.5rem;
  text-align: center;
}

.home-cta-banner-inner {
  max-width: 32rem;
  margin: 0 auto;
}

.home-cta-banner h2 {
  font-size: 2.25rem;
  font-weight: 800;
  letter-spacing: -0.025em;
  margin: 0 0 1rem 0;
  color: #ffffff;
}

.home-cta-banner p {
  color: var(--te-slate-400);
  font-size: 1.125rem;
  line-height: 1.6;
  margin: 0 0 2.5rem 0;
}

/*
  Login page redesign (2026-08-11): reskin of login.php to the --te-*
  palette, replacing its old bare Tailwind-utility markup (unquoted
  attributes, mismatched red/lime error colours, a stray duplicate <body>
  and mismatched closing tags around the form) with a centred card, same
  hero gradient background as the homepage so it reads as part of the same
  site. Colour/structure pass only - the PHP form-handling logic above the
  markup (validation, password_verify, redirect-back-to-previous-page) is
  untouched.
*/
.auth-page {
  min-height: 60vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4rem 1.5rem;
  background: linear-gradient(135deg, #e0f2fe 0%, #fae8ff 100%);
}

.auth-card {
  width: 100%;
  max-width: 26rem;
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  padding: 2.5rem 2rem;
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 8px 10px -6px rgba(0, 0, 0, 0.05);
}

.auth-title {
  font-size: 1.75rem;
  font-weight: 800;
  color: var(--te-slate-800);
  letter-spacing: -0.025em;
  margin: 0 0 0.375rem 0;
}

.auth-subtitle {
  color: var(--te-slate-500);
  font-size: 0.937rem;
  margin: 0 0 1.75rem 0;
}

.auth-notice {
  background-color: #f0fdf4;
  border: 1px solid #bbf7d0;
  color: #15803d;
  font-size: 0.875rem;
  padding: 0.75rem 1rem;
  border-radius: 0.5rem;
  margin: 0 0 1.25rem 0;
}

.auth-form {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.auth-field {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
}

.auth-label {
  font-size: 0.812rem;
  font-weight: 600;
  color: var(--te-slate-600);
}

.auth-input {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--te-border);
  border-radius: 0.5rem;
  padding: 0.625rem 0.875rem;
  font-size: 0.937rem;
  color: var(--te-slate-800);
  font-family: inherit;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.auth-input:focus {
  outline: none;
  border-color: var(--te-blue);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}

.auth-error {
  display: block;
  color: #dc2626;
  font-size: 0.812rem;
}

.auth-error-block {
  background-color: #fef2f2;
  border: 1px solid #fecaca;
  padding: 0.625rem 0.875rem;
  border-radius: 0.5rem;
  margin: 0;
}

.auth-forgot {
  margin: 0.375rem 0 0 0;
  font-size: 0.812rem;
  text-align: right;
}

.auth-forgot a,
.auth-signup-link a {
  color: var(--te-blue);
  text-decoration: none;
}

.auth-forgot a:hover,
.auth-signup-link a:hover {
  text-decoration: underline;
}

.auth-submit-btn {
  display: block;
  width: 100%;
  background: linear-gradient(to right, var(--te-blue), var(--te-pink));
  color: #ffffff;
  font-weight: 600;
  font-size: 0.937rem;
  padding: 0.75rem;
  border: none;
  border-radius: 0.5rem;
  cursor: pointer;
  box-shadow: 0 4px 6px -1px rgba(37, 99, 235, 0.2);
  transition: filter 0.2s ease, box-shadow 0.2s ease;
}

.auth-submit-btn:hover {
  filter: brightness(0.92);
  box-shadow: 0 10px 15px -3px rgba(219, 39, 119, 0.25);
}

.auth-signup-link {
  text-align: center;
  font-size: 0.875rem;
  color: var(--te-slate-600);
  margin: 0.25rem 0 0 0;
}

/*
  .auth-hint/.auth-hint-list (2026-08-12): password-requirements style hint text under a form
  field, first used in password_reset.php - a smaller, quieter treatment than .auth-error since
  it's guidance, not a validation failure.
*/
.auth-hint {
  font-size: 0.812rem;
  color: var(--te-slate-500);
  margin: 0.5rem 0 0 0;
}

/* Same Tailwind-preflight gap as .card-section-body's fix above - a bare <a> inside .auth-hint
   (e.g. contact.php's "or email support@... directly" line) inherits no link colour/underline by
   default. Caught 2026-08-23. */
.auth-hint a {
  color: var(--te-blue);
  text-decoration: underline;
}

.auth-hint a:hover {
  color: var(--te-pink);
}

.auth-hint-list {
  list-style: disc;
  margin: 0.375rem 0 0 1.25rem;
  padding: 0;
  font-size: 0.812rem;
  color: var(--te-slate-500);
}

.auth-hint-list li {
  margin-bottom: 0.25rem;
}

/*
  page_top.php shell recolour (2026-08-11): page_top.php is a shared
  partial used by admin.php and mcq_questions.php (which nobody asked to be
  redesigned today - it inherits this recolour for free, same as the MCQ
  hub/footer inherited the nav's palette change earlier). Only the title
  band is touched here; $pageWidth/$pageInnerClass stay Tailwind utility
  classes per-page as before, untouched.
*/
.page-shell-title {
  display: block;
  background: linear-gradient(to right, var(--te-blue), var(--te-pink));
  color: #ffffff;
  font-weight: 700;
  font-size: 1.375rem;
  padding: 0.625rem 1rem;
  border-radius: 0.5rem 0.5rem 0 0;
  margin: 0;
}

/*
  .back-to-dashboard-link (2026-08-13): small breadcrumb-style link above .page-shell-title on
  every page_top.php page, so there's always an obvious way back to the dashboard without relying
  on the browser's back button. Global (not a page's own $style_input) since page_top.php is a
  shared partial included by many pages, each with different $style_input contents.
*/
.back-to-dashboard-link {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--te-blue);
  text-decoration: none;
  margin-bottom: 0.5rem;
}
.back-to-dashboard-link:hover {
  color: var(--te-blue-dark);
  text-decoration: underline;
}

/*
  admin.php link list (2026-08-11): .resource-link/.dash-link-row replace
  the repeated `class="ml-2 hover:bg-sky-100"` / `<a class="block">`
  pattern in admin.php's link list - a simpler flat list than dashboard.php
  needed, so it doesn't use the card-based .card-link-list treatment below.
*/
.resource-link {
  display: block;
  padding: 0.5rem 0.75rem;
  border-radius: 0.375rem;
  color: var(--te-slate-800);
  text-decoration: none;
  font-size: 0.937rem;
  transition: background-color 0.2s ease, color 0.2s ease;
}

.resource-link:hover {
  background-color: var(--te-blue-light);
  color: var(--te-blue-dark);
}

.dash-link-row {
  list-style: none;
  margin: 0.125rem 0;
}

/*
  Dashboard redesign (2026-08-11): user/dashboard.php now opts out of the
  page_top.php/page_bottom.php shell entirely (same move mcq.php made
  earlier) and uses the shared .card-* card-list components (renamed from
  .mcq-* above so both pages can use them - "make dashboard look like
  cards, the way mcq.php does") instead of the old bg-pink-300/200/100
  nested heading bands. Every section is now its own .card-section, which
  made the old "wrap in a border only if teacher" special-case in
  dashboard.php's PHP redundant, so that conditional wrapper was dropped -
  all users now see the same boxed-card treatment, only the explanatory
  teacher-facing sentence inside the card stays permission-gated.
  .dash-table replaces dashboard.php's inline $style_input (unscoped
  `th, td { border: 1px solid black }` - applied to literally every table
  on the page, not just this one) with a scoped class using the site's own
  border colour.
*/
.dash-page {
  max-width: 48rem;
  margin: 3rem auto;
  padding: 0 1rem;
  color: var(--te-slate-800);
}

.dash-title {
  font-size: 1.875rem;
  line-height: 2.25rem;
  font-weight: 700;
  color: var(--te-slate-800);
  letter-spacing: -0.025em;
  margin-bottom: 1rem;
}

.dash-sections {
  display: flex;
  flex-direction: column;
  gap: 2.5rem;
}

.dash-welcome {
  background-color: var(--te-blue-light);
  color: var(--te-slate-800);
  font-weight: 600;
  font-size: 1.05rem;
  padding: 0.5rem 0.75rem;
  border-radius: 0.375rem;
  margin: 0 0 2rem 0;
}

.dash-subnote {
  font-weight: 700;
  font-size: 0.812rem;
  color: var(--te-slate-500);
  margin: 0.5rem 0 0.25rem 0.75rem;
}

.dash-table {
  width: 100%;
  border-collapse: collapse;
  margin: 0.5rem auto 0 auto;
  font-size: 0.875rem;
}

.dash-table th,
.dash-table td {
  border: 1px solid var(--te-border);
  padding: 0.5rem 0.75rem;
  text-align: left;
}

.dash-table th {
  background-color: var(--te-bg-alt);
  color: var(--te-slate-800);
  font-weight: 600;
}

.dash-table a {
  color: var(--te-blue);
  text-decoration: underline;
}

.dash-table a:hover {
  color: var(--te-blue-dark);
}

/*
  Markbook (Phase 4, 2026-08-15): the students x assignments grid, one cell per (student,
  assignment) with every linked attempt stacked. Reuses .dash-table for the grid and
  .card-section/.auth-field/.auth-label/.auth-input for the class picker, so the only genuinely new
  pieces are the cell/header treatments below - .mb-overdue distinguishes a "--" for an assignment
  already past its due date from an ordinary still-pending one.

  Update (2026-08-15): "Not yet" shortened to "--", and the percentage bolded (.mb-attempt-pct).
  Header row grew a third line, .mb-assign-review-link, alongside the existing quiz-name link (now
  pointed at mcq_exercise.php directly, so a teacher can forward that exact URL to a student) and
  .mb-assign-due. Attempts were briefly given a divider line between them (.mb-cell-attempts span's
  border-bottom) but removed again once every attempt fit on one line - the plain .mb-cell-attempts
  gap already reads clearly, and the divider wasn't even rendering visibly between two late
  (highlighted) attempts anyway.
*/
.mb-cell-attempts {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.8rem;
  white-space: nowrap;
}

.mb-attempt-pct {
  font-weight: 700;
}

.mb-not-yet {
  color: var(--te-slate-500);
  font-size: 0.8rem;
}

.mb-overdue {
  color: #b91c1c;
  font-weight: 600;
  font-size: 0.8rem;
}

.mb-assign-due {
  display: block;
  font-weight: 400;
  font-size: 0.75rem;
  color: var(--te-slate-500);
}

.mb-assign-review-link {
  display: block;
  font-weight: 400;
  font-size: 0.75rem;
  margin-top: 0.15rem;
}

/*
  Markbook: frozen grid + late-attempt highlight (2026-08-15, simplified 2026-08-16). Excel-style
  "freeze panes" - .mb-table-wrap is a plain (non-sticky) max-height/overflow:auto scroll box;
  within it, .mb-freeze-table's header row and first column use position:sticky relative to that
  box, so they stay visible while the rest scrolls underneath. The corner cell needs both (top and
  left) plus the highest z-index so it stays above whichever of the two edges is currently
  scrolling past underneath it. All three sticky layers need an explicit opaque background or
  content scrolling underneath would show through. .mb-table-wrap also gets `position: relative;
  z-index: 0;` so .mb-freeze-table's inner z-index is contained within its own stacking context and
  can't compete with .mb-export-section after it.
  .mb-attempt-late reuses --te-pink-light (the site's existing light-pink highlight token, see
  .auth-notice/focus states) to flag a late-linked attempt inline, distinguishing it from an
  on-time one without needing a separate legend.

  A page-level "whole table stays pinned below the nav as you scroll the page" behaviour (on top of
  the freeze-panes above) was also built and iterated on at length, but kept causing genuine CSS
  bugs where .mb-export-section (the later sibling) visually overlapped or got covered by the still-
  -pinned table - a CSS stacking-order rule around positioned-vs-static siblings, then a sticky
  "stuck scroll range" issue tied to shared containing blocks. Given the page has nothing after the
  table except the export buttons, the added complexity wasn't worth it - dropped in favour of this
  simpler, bug-free version. Left as a note here so it isn't reintroduced blind.
*/
.mb-table-wrap {
  position: relative;
  z-index: 0;
  max-height: 82vh;
  overflow: auto;
  margin-top: 1rem;
  border: 1px solid var(--te-border);
  border-radius: 0.5rem;
}

.mb-export-section {
  position: relative;
  margin-top: 1.5rem;
  padding-top: 1rem;
  border-top: 1px solid var(--te-border);
  display: flex;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.mb-export-btn {
  display: inline-block;
  border: none;
  border-radius: 0.5rem;
  padding: 0.625rem 1.25rem;
  font-weight: 600;
  font-size: 0.937rem;
  text-decoration: none;
  cursor: pointer;
  transition: filter 0.15s ease;
}

.mb-export-btn:hover {
  filter: brightness(0.95);
}

.mb-export-btn-blue {
  background-color: var(--te-blue-light);
  color: var(--te-blue-dark);
}

.mb-freeze-table {
  margin: 0;
}

.mb-freeze-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
}

.mb-freeze-table .mb-freeze-col {
  position: sticky;
  left: 0;
  z-index: 1;
  background-color: #ffffff;
}

.mb-freeze-table thead th.mb-freeze-corner {
  left: 0;
  z-index: 3;
}

.mb-cell-attempts span.mb-attempt-late {
  background-color: var(--te-pink-light);
  border-radius: 0.25rem;
}

/*
  MCQ generator redesign (2026-08-11): reuses .card-section (dashboard's
  card look) for the filter form, and .auth-field/.auth-label/.auth-input/
  .auth-form/.auth-submit-btn from the login page for the fields and
  primary "Create Quiz" button, rather than inventing new form-field
  styles for a third time. .btn-secondary is new - a full-width outline
  button for "Reset All Parameters", which needed to read as secondary
  next to the gradient primary action. .reset-option recolours the
  "--Reset Category--" placeholder <option> (was bg-pink-200).
*/
.gen-page {
  max-width: 34rem;
  margin: 3rem auto;
  padding: 0 1rem;
}

.gen-title {
  font-size: 1.875rem;
  font-weight: 700;
  color: var(--te-slate-800);
  letter-spacing: -0.025em;
  margin-bottom: 1.5rem;
}

.reset-option {
  background-color: var(--te-pink-light);
  color: var(--te-pink-dark);
}

.btn-secondary {
  display: block;
  width: 100%;
  background-color: #ffffff;
  color: var(--te-slate-600);
  font-weight: 600;
  font-size: 0.937rem;
  padding: 0.75rem;
  border: 1px solid var(--te-border);
  border-radius: 0.5rem;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

.btn-secondary:hover {
  background-color: var(--te-bg-alt);
  border-color: var(--te-slate-400);
}

/*
  MCQ exercise page redesign (2026-08-12): reskins mcq_exercise.php - the actual quiz-taking
  screen, as opposed to mcq.php's link-hub - to the site's --te-* palette instead of its old
  plain pink/sky bg-* classes, and to this working mode's hand-written-CSS convention (this page
  is under active change today, so no new Tailwind utility classes were added to it, including
  in the width/breakpoint change below).

  Options are clickable button-labels wrapping a visually-hidden-but-still-focusable radio input
  (a for/id link, not nesting, since that's how the pre-existing markup already associated them),
  with the text inside the button itself, per the user's explicit request. Selection colour is
  toggled via a JS-added .qz-option-selected class (see handleOptionSelect() in
  mcq_exercise.php) rather than a :checked sibling selector, because the label and its radio
  aren't in a parent/sibling relationship CSS can select across.

  Page width: 1024px is the same breakpoint the nav (.site-nav-links) already switches at, so
  the quiz column narrows to half the viewport in step with the nav going horizontal, rather than
  introducing a new breakpoint. Options grid: 2 columns at that same width, 1 column below it. A
  lone trailing option in an odd-numbered set (e.g. 5 options) is centred under the grid instead
  of left-aligned - done by giving the grid 4 columns with every option spanning 2, so a normal
  pair fills a row edge-to-edge, and the centring class shifts the odd one out to columns 2-3.

  The optionsTable variant (comparison-table-style options, rarer than the plain list) keeps its
  native <table> structure rather than becoming button-styled - a data row isn't a single
  clickable block the way a plain-text/image option is - but shares the palette, and the whole
  row highlights on selection via the same handleOptionSelect()/.qz-option-selected mechanism.
*/
.qz-page {
  width: 100%;
  margin: 2rem auto 3rem auto;
  padding: 0 1rem;
}

@media (min-width: 1024px) {
  .qz-page {
    max-width: 50%;
  }
}

.qz-header {
  margin-bottom: 1.5rem;
}

.qz-title {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--te-slate-800);
  letter-spacing: -0.02em;
  margin: 0 0 0.5rem 0;
}

.qz-student {
  color: var(--te-slate-600);
  font-size: 0.937rem;
  margin: 0;
}

.qz-assign-form {
  margin-top: 0.75rem;
}

.qz-question {
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.05);
  padding: 1.5rem;
}

.qz-progress {
  font-size: 0.812rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--te-pink);
  margin: 0 0 1rem 0;
}

.qz-question-body {
  margin-bottom: 0.5rem;
}

.qz-question-text {
  color: var(--te-slate-800);
  line-height: 1.6;
  margin: 0 0 0.5rem 0;
}

.qz-question-img {
  display: block;
  max-height: 70vh;
  max-width: 100%;
  margin: 0 auto 1rem auto;
}

.qz-mid-table {
  width: 100%;
  border-collapse: collapse;
  margin: 0.75rem auto;
  font-size: 0.875rem;
}

.qz-mid-table td {
  border: 1px solid var(--te-border);
  padding: 0.5rem 0.75rem;
  text-align: center;
  color: var(--te-slate-800);
}

.qz-mid-table-heading {
  text-align: center;
  font-weight: 700;
  color: var(--te-slate-800);
  margin: 1rem 0 0.5rem 0;
}

/*
  mcq_assignment_review.php text-only question review (2026-08-16): reuses the qz-question-body/
  qz-question-text/qz-mid-table* classes above verbatim for the stem/mid-image/mid-table (same
  markup mcq_exercise.php uses for live quiz-taking) - these two are the genuinely new pieces, for
  the plain-text options list shown below that content. .qz-mcq-option-correct reuses the light
  green already established for "correct"-flavoured badges elsewhere (.pp-toggle-btn-model).
*/
.qz-mcq-option-row {
  padding: 0.375rem 0.625rem;
  border-radius: 0.375rem;
  margin: 0 0 0.25rem 0;
}

.qz-mcq-option-correct {
  background-color: #f0fdf4;
  color: #15803d;
}

.qz-options-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.75rem;
  margin-top: 1.25rem;
}

@media (min-width: 1024px) {
  .qz-options-grid {
    grid-template-columns: repeat(4, 1fr);
  }

  .qz-options-grid .qz-option {
    grid-column: span 2;
  }

  .qz-options-grid .qz-option-centered {
    grid-column: 2 / span 2;
  }
}

.qz-option {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  background-color: #ffffff;
  border: 2px solid var(--te-border);
  border-radius: 0.5rem;
  padding: 0.75rem 1rem;
  color: var(--te-slate-800);
  font-size: 0.937rem;
  line-height: 1.4;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.qz-option:hover {
  border-color: var(--te-blue);
  background-color: var(--te-blue-light);
}

.qz-option:focus-within {
  outline: 2px solid var(--te-blue);
  outline-offset: 2px;
}

.qz-option-selected,
.qz-option-selected:hover {
  background-color: var(--te-blue);
  border-color: var(--te-blue);
  color: #ffffff;
}

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

.qz-option-text {
  flex: 1;
}

.qz-option-img {
  max-width: 100%;
  max-height: 8rem;
  margin: 0 auto;
}

.qz-options-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 1.25rem;
  font-size: 0.875rem;
}

.qz-options-table td {
  border: 1px solid var(--te-border);
  padding: 0.5rem 0.75rem;
  text-align: center;
  color: var(--te-slate-800);
}

.qz-options-table th {
  border: 1px solid var(--te-border);
  padding: 0.5rem 0.75rem;
  background-color: var(--te-bg-alt);
  color: var(--te-slate-800);
  font-weight: 600;
}

.qz-options-table tr.qz-option-selected td {
  background-color: var(--te-blue-light);
}

.qz-nav {
  display: flex;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

.qz-nav-btn {
  flex: 1;
  padding: 0.625rem;
  border-radius: 0.5rem;
  font-weight: 600;
  font-size: 0.875rem;
  border: none;
  cursor: pointer;
  text-align: center;
  transition: background-color 0.2s ease, opacity 0.2s ease;
}

.qz-nav-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.qz-nav-btn-secondary {
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  color: var(--te-slate-600);
}

.qz-nav-btn-secondary:hover:not(:disabled) {
  background-color: var(--te-bg-alt);
}

.qz-nav-btn-primary {
  background-color: var(--te-blue);
  color: #ffffff;
}

.qz-nav-btn-primary:hover:not(:disabled) {
  background-color: var(--te-blue-dark);
}

.qz-nav-btn-submit {
  background-color: var(--te-pink);
  color: #ffffff;
}

.qz-nav-btn-submit:hover:not(:disabled) {
  background-color: var(--te-pink-dark);
}

/*
  Submit confirmation modal (the "confirmation page" - #alertBox in mcq_exercise.php).

  display:none/flex is toggled via .qz-modal-open (JS-added, see submit2()/goBack()) rather than
  Tailwind's .hidden - this file loads after output.css, so an unconditional display:flex here
  would sit later in the cascade than output.css's .hidden{display:none} at equal specificity and
  win regardless of whether .hidden was present, exactly the bug this file's header comment warns
  about (hit it for real here on the first pass: the modal showed on page load).
*/
.qz-modal-backdrop {
  position: fixed;
  inset: 0;
  background-color: rgba(15, 23, 42, 0.5);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  z-index: 50;
}

.qz-modal-backdrop.qz-modal-open {
  display: flex;
}

.qz-modal {
  width: 100%;
  max-width: 26rem;
  background-color: #ffffff;
  border-radius: 0.75rem;
  padding: 1.75rem;
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.08);
}

.qz-modal-notice {
  background-color: var(--te-blue-light);
  color: var(--te-slate-800);
  border-radius: 0.5rem;
  padding: 0.875rem 1rem;
  text-align: center;
  font-size: 0.937rem;
}

.qz-modal-notice p {
  margin: 0.125rem 0;
}

.qz-modal-warning {
  background-color: #fef3c7;
  color: #92400e;
  border-radius: 0.5rem;
  padding: 0.875rem 1rem;
  text-align: center;
  font-size: 0.875rem;
  margin-top: 0.75rem;
}

.qz-modal-warning p {
  margin: 0.125rem 0;
}

.qz-modal-actions {
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
  margin-top: 1.25rem;
}

/*
  A few small .auth-* additions (2026-08-12) for user/newuser.php's registration form - reuses
  the existing .auth-field/.auth-label/.auth-input/.auth-form/.auth-notice/.auth-error/
  .auth-error-block/.auth-hint-list components from login.php/password_reset.php rather than
  duplicating them; these four are the genuinely new pieces that form needed.
*/
.auth-field-row {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

@media (min-width: 768px) {
  .auth-field-row {
    flex-direction: row;
  }

  .auth-field-row .auth-field {
    flex: 1;
  }
}

.auth-section-heading {
  font-size: 1rem;
  font-weight: 700;
  color: var(--te-slate-800);
  margin: 0.5rem 0 0 0;
}

.auth-checkbox-row {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  font-size: 0.875rem;
  color: var(--te-slate-600);
}

.auth-checkbox-row input[type="checkbox"] {
  margin-top: 0.2rem;
}

.auth-checkbox-row a {
  color: var(--te-blue);
  text-decoration: underline;
}

/*
  assign_create.php redesign (2026-08-16): "Randomise Question Order"/"Randomise MCQ Options" moved
  from a Yes/No radio pair to a real toggle switch, since both now default on and a plain checkbox
  read ambiguously for "on/off" - .auth-toggle-row is the label wrapping (also the click target,
  same pattern as .auth-checkbox-row), .auth-toggle-switch/-track are the visual switch (a
  standard checkbox-styled-as-a-pill-with-a-sliding-thumb via the checked sibling selector - the
  actual checkbox is visually hidden but still focusable/keyboard-operable, not display:none).
  .auth-optional-tag flags the two free-text notes fields as optional inline next to their label,
  rather than a separate hint line.
*/
.auth-toggle-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  cursor: pointer;
}

.auth-toggle-switch {
  position: relative;
  display: inline-block;
  width: 2.75rem;
  height: 1.5rem;
  flex-shrink: 0;
}

.auth-toggle-switch input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}

.auth-toggle-track {
  position: absolute;
  inset: 0;
  background-color: var(--te-slate-400);
  border-radius: 999px;
  transition: background-color 0.2s ease;
  pointer-events: none;
}

.auth-toggle-track::before {
  content: "";
  position: absolute;
  height: 1.15rem;
  width: 1.15rem;
  left: 0.175rem;
  top: 0.175rem;
  background-color: #ffffff;
  border-radius: 50%;
  transition: transform 0.2s ease;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

.auth-toggle-switch input:checked + .auth-toggle-track {
  background-color: var(--te-blue);
}

.auth-toggle-switch input:checked + .auth-toggle-track::before {
  transform: translateX(1.25rem);
}

.auth-toggle-switch input:focus-visible + .auth-toggle-track {
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.25);
}

.auth-optional-tag {
  font-weight: 400;
  color: var(--te-slate-500);
}

.auth-inline-success {
  font-size: 0.812rem;
  color: #15803d;
  margin: 0.25rem 0 0 0;
}

/*
  Past papers redesign (2026-08-12): pastpapers/questions.php's search form reuses .card-section/
  .card-section-title/.card-section-body and .auth-field/.auth-label/.auth-input/.btn-secondary
  from mcq/generator.php's near-identical filter form (same Exam Board/Qualification/Unit/Year/
  Topic pattern) rather than a third copy of those styles. The .pp-* classes below are the
  genuinely page-specific pieces: the exam-instance grouping headers, question cards, the four
  Show Mark Scheme/Guide/Model Answer/Exam Report toggle buttons and their revealed panels, and
  the bottom exam-paper/mark-scheme/exam-report link row.

  Toggle/reveal colours were widened from the original's 3-shades-of-one-blue (pink/sky-200/
  sky-300/sky-100) to 4 visually distinct categories - pink (mark scheme), blue (guide), green
  (model answer, reusing .auth-notice's existing green rather than inventing a new hue), and
  neutral slate (exam report) - so the four are actually easy to tell apart at a glance.

  toggleHide() (javascript_functions.js, untouched) looks elements up by class name
  (markSchemeToggle_<id> etc.) and toggles Tailwind's .hidden - those class names and .hidden are
  kept exactly as before alongside the new .pp-reveal-* styling classes.
*/
.pp-page {
  width: 100%;
  margin: 2rem auto 3rem auto;
  padding: 0 1rem;
}

@media (min-width: 1024px) {
  .pp-page {
    max-width: 50%;
  }
}

.pp-title {
  font-size: 1.875rem;
  font-weight: 700;
  color: var(--te-slate-800);
  letter-spacing: -0.025em;
  margin-bottom: 1.5rem;
}

.pp-results-title {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--te-slate-800);
  margin: 1.5rem 0 1rem 0;
}

.pp-exam-header {
  position: sticky;
  top: 4rem;
  z-index: 10;
  background-color: var(--te-blue-light);
  border-radius: 0.5rem;
  margin-bottom: 0.75rem;
  padding: 0.5rem 0.75rem;
}

.pp-exam-header a {
  display: block;
  color: var(--te-blue-dark);
  font-weight: 600;
  text-decoration: none;
}

.pp-exam-header a:hover {
  color: var(--te-pink-dark);
}

.pp-question-card {
  background-color: #ffffff;
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  overflow: hidden;
  margin-bottom: 1.25rem;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.05);
}

.pp-question-header {
  background-color: var(--te-pink-light);
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--te-border);
}

.pp-question-header h3 {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--te-slate-800);
  margin: 0;
}

.pp-question-header p {
  font-size: 0.875rem;
  color: var(--te-slate-600);
  margin: 0.25rem 0 0 0;
}

.pp-question-subheader {
  background-color: var(--te-bg-alt);
  padding: 0.5rem 0.75rem;
  border-bottom: 1px solid var(--te-border);
}

@media (min-width: 1024px) {
  .pp-question-subheader {
    width: 50%;
  }
}

.pp-question-subheader h4 {
  font-size: 1rem;
  font-weight: 600;
  color: var(--te-slate-800);
  margin: 0;
}

.pp-question-body {
  padding: 0.75rem;
  color: var(--te-slate-800);
  line-height: 1.6;
}

.pp-question-body p {
  margin: 0 0 0.5rem 0;
}

.pp-question-images {
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.pp-question-images img {
  max-width: 100%;
  height: auto;
}

.pp-toggle-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0 0.75rem;
  margin-bottom: 0.5rem;
}

.pp-toggle-btn {
  border: none;
  border-radius: 0.375rem;
  padding: 0.375rem 0.75rem;
  font-size: 0.812rem;
  font-weight: 600;
  cursor: pointer;
  transition: filter 0.15s ease;
}

.pp-toggle-btn:hover {
  filter: brightness(0.95);
}

.pp-toggle-btn-scheme {
  background-color: var(--te-pink-light);
  color: var(--te-pink-dark);
}

.pp-toggle-btn-guide {
  background-color: var(--te-blue-light);
  color: var(--te-blue-dark);
}

.pp-toggle-btn-model {
  background-color: #f0fdf4;
  color: #15803d;
}

.pp-toggle-btn-report {
  background-color: var(--te-bg-alt);
  color: var(--te-slate-600);
  border: 1px solid var(--te-border);
}

.pp-links-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  padding: 0 0.75rem 0.75rem 0.75rem;
}

.pp-links-row a {
  color: var(--te-blue);
  text-decoration: underline;
  font-size: 0.875rem;
}

.pp-links-row a:hover {
  color: var(--te-blue-dark);
}

.pp-reveal-panel {
  margin: 0 0.75rem 0.75rem 0.75rem;
  padding: 0.75rem;
  border-radius: 0.5rem;
  border-left: 4px solid var(--te-border);
  background-color: var(--te-bg-alt);
}

.pp-reveal-panel h3 {
  font-size: 0.937rem;
  font-weight: 700;
  color: var(--te-slate-800);
  margin: 0 0 0.5rem 0;
}

.pp-reveal-panel p {
  margin: 0 0 0.5rem 0;
  color: var(--te-slate-800);
  line-height: 1.6;
}

.pp-reveal-panel img {
  max-width: 100%;
  height: auto;
  margin: 0 auto;
  display: block;
}

@media (min-width: 1024px) {
  .pp-reveal-model-img {
    max-width: 50%;
  }
}

.pp-reveal-scheme {
  border-left-color: var(--te-pink);
}

.pp-reveal-guide {
  border-left-color: var(--te-blue);
}

.pp-reveal-model {
  border-left-color: #15803d;
}

.pp-reveal-report {
  border-left-color: var(--te-slate-400);
}

.pp-edit-link {
  padding: 0 0.75rem 0.75rem 0.75rem;
}

.pp-edit-link a {
  color: var(--te-blue);
  text-decoration: underline;
  font-size: 0.875rem;
}

.pp-edit-link a:hover {
  color: var(--te-blue-dark);
}

.pp-link-row {
  background-color: var(--te-bg-alt);
  border-top: 1px solid var(--te-border);
  padding: 0.75rem;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.5rem;
}

@media (min-width: 1024px) {
  .pp-link-row {
    grid-template-columns: repeat(2, 1fr);
  }
}

.pp-link-row a {
  display: block;
  text-align: center;
  color: var(--te-blue);
  text-decoration: underline;
  font-size: 0.875rem;
  padding: 0.375rem;
  border-radius: 0.375rem;
  transition: background-color 0.15s ease;
}

.pp-link-row a:hover {
  background-color: var(--te-blue-light);
  color: var(--te-blue-dark);
}

/*
  Privacy policy redesign (2026-08-12): colour/structure pass only - the policy text itself is
  unchanged, user's explicit call ("we will update actual policy later"). Matches the original's
  own two-tier heading treatment (pink for the handful of top-level/emphasis headings - main
  title, "The short version:", "Detailed Privacy and Data Policy", the login-redirect "Hello!"
  banner - blue for the many individual topic headings) just recoloured to --te-*, and widens the
  page column to this site's standard 48rem content-page convention instead of the old lg:w-1/2.
*/
.policy-page {
  max-width: 48rem;
  margin: 3rem auto;
  padding: 0 1rem;
  color: var(--te-slate-800);
}

.policy-title {
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--te-slate-800);
  letter-spacing: -0.025em;
  line-height: 1.3;
  margin-bottom: 1.5rem;
}

.policy-notice {
  background: linear-gradient(135deg, var(--te-blue-light) 0%, var(--te-pink-light) 100%);
  border: 1px solid var(--te-border);
  border-radius: 0.75rem;
  padding: 1.25rem 1.5rem;
  margin-bottom: 1.5rem;
}

.policy-notice p {
  margin: 0 0 0.5rem 0;
}

.policy-notice p:last-child {
  margin-bottom: 0;
}

.policy-highlight-heading {
  font-size: 1.25rem;
  font-weight: 700;
  color: #ffffff;
  background-color: var(--te-pink);
  padding: 0.5rem 0.75rem;
  border-radius: 0.5rem;
  margin: 1.5rem 0 0.75rem 0;
}

.policy-section-title {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--te-blue-dark);
  background-color: var(--te-blue-light);
  padding: 0.5rem 0.75rem;
  border-radius: 0.5rem;
  margin: 1.5rem 0 0.75rem 0;
}

.policy-page p {
  margin: 0 0 0.75rem 0;
  line-height: 1.7;
}

.policy-page ul {
  list-style: disc;
  margin: 0 0 1rem 1.5rem;
  padding: 0;
}

.policy-page li {
  margin-bottom: 0.375rem;
  line-height: 1.6;
}

.policy-page a {
  color: var(--te-blue);
  text-decoration: underline;
}

.policy-page a:hover {
  color: var(--te-blue-dark);
}

/*
  .danger-banner (2026-08-23) - dark, serious styling for the GDPR data-erasure confirm/cancel
  pages and the dashboard's active-deletion-request warning banner (getActiveDeletionRequestForUser()
  in php_functions.php). Deliberately a step darker/heavier than .status-badge-danger (which is a
  small inline flag) or .btn-danger alone (which is just a button colour) - this needs to read as
  "stop and read this" at a glance, for an irreversible action. See
  [[project_thinkeconomics_phase7_launch_prep]].
*/
.danger-banner {
  background-color: #1f1315;
  border: 1px solid #7f1d1d;
  border-radius: 0.75rem;
  padding: 1.5rem;
  color: #fecaca;
  margin-bottom: 1.5rem;
}

.danger-banner h1, .danger-banner h2, .danger-banner h3 {
  color: #ffffff;
  margin-top: 0;
}

.danger-banner p {
  margin: 0 0 0.75rem 0;
  line-height: 1.6;
}

.danger-banner p:last-child {
  margin-bottom: 0;
}

.danger-banner a {
  color: #fca5a5;
  text-decoration: underline;
}

.danger-banner a:hover {
  color: #ffffff;
}

.danger-banner .auth-field {
  margin: 1rem 0;
}

.danger-banner .auth-label {
  color: #fecaca;
}

.danger-banner .auth-input {
  background-color: #2d1b1e;
  border: 1px solid #7f1d1d;
  color: #ffffff;
}

/*
  Teacher/roster management redesign (2026-08-15): class_creator.php, school_registration.php,
  group_manager.php, user_populate.php, teacher_verification.php and
  admin/teacher_verification_queue.php move off their original bg-pink-300/bg-sky-300/border-black
  Tailwind-utility look to the site's --te-* palette, reusing the same shared toolkit as every
  other page in this working mode rather than inventing a fourth copy of it: .card-section/
  .card-section-title/.card-section-body/.card-category-title for section wrappers,
  .auth-form/.auth-field/.auth-label/.auth-input/.auth-error/.auth-field-row/.auth-hint/
  .auth-inline-success for form fields (including the two tables' search/filter row, via
  .auth-field-row), .auth-submit-btn/.btn-secondary for buttons, and .dash-table for the data
  tables. Only genuinely new pieces are below: .btn-danger (destructive actions - Remove Students,
  Reject - didn't have a red equivalent of .auth-submit-btn anywhere yet), .status-badge (the
  verification-status/reply/send-result panels on the two verification pages, previously ad hoc
  bg-lime-300/bg-yellow-100/bg-pink-300 spans), and .cell-center (checkbox/leaving-year table
  columns, where .dash-table's default left-align reads oddly for a lone checkbox).
*/
.btn-danger {
  display: block;
  width: 100%;
  background-color: #dc2626;
  color: #ffffff;
  font-weight: 600;
  font-size: 0.937rem;
  padding: 0.75rem;
  border: none;
  border-radius: 0.5rem;
  cursor: pointer;
  text-align: center;
  transition: background-color 0.2s ease;
}

.btn-danger:hover {
  background-color: #b91c1c;
}

.btn-danger:disabled {
  background-color: var(--te-slate-400);
  cursor: not-allowed;
}

/*
mcq_assignment_review.php Questions section button theming (2026-08-16): applied alongside
.btn-secondary (not replacing it - inherits box model/padding/cursor from there), just overriding
colour so the per-question action buttons read as more prominent than a plain outline button.
.btn-blue-light is the default for that section; .btn-pink-light is reserved for "Click for
Explanation" specifically, to visually distinguish it from the others.
*/
.btn-blue-light {
  background-color: var(--te-blue-light);
  color: var(--te-blue-dark);
  border-color: var(--te-blue-light);
}

.btn-blue-light:hover {
  background-color: var(--te-blue);
  color: #ffffff;
  border-color: var(--te-blue);
}

.btn-pink-light {
  background-color: var(--te-pink-light);
  color: var(--te-pink-dark);
  border-color: var(--te-pink-light);
}

.btn-pink-light:hover {
  background-color: var(--te-pink);
  color: #ffffff;
  border-color: var(--te-pink);
}

.auth-submit-btn:disabled {
  background: var(--te-slate-400);
  cursor: not-allowed;
  box-shadow: none;
}

/*
MCQ Summary stat tiles (user_work_review.php, 2026-08-16) - three headline numbers (quizzes
completed, questions answered, average time per submission). A stat tile rather than a chart: each
number stands alone, there's no series/trend being compared, so a chart would add decoration
without adding information (per the dataviz method's "sometimes the answer is not a chart" case).
*/
.mcq-stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.75rem;
  margin: 0.75rem 0 1rem 0;
}

.mcq-stat-tile {
  background-color: var(--te-blue-light);
  border-radius: 0.5rem;
  padding: 0.75rem 1rem;
  text-align: center;
}

.mcq-stat-tile-value {
  display: block;
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--te-blue-dark);
}

.mcq-stat-tile-label {
  display: block;
  font-size: 0.8rem;
  color: var(--te-slate-600);
}

.mcq-stat-tile-sublabel {
  display: block;
  font-size: 0.7rem;
  color: var(--te-slate-500);
  margin-top: 0.15rem;
}

.status-badge {
  display: block;
  font-size: 0.812rem;
  padding: 0.5rem 0.75rem;
  border-radius: 0.5rem;
  border: 1px solid transparent;
  margin: 0 0 0.5rem 0;
}

.status-badge p {
  margin: 0;
}

.status-badge p + p {
  margin-top: 0.375rem;
}

.status-badge-success {
  background-color: #f0fdf4;
  border-color: #bbf7d0;
  color: #15803d;
}

.status-badge-warning {
  background-color: #fffbeb;
  border-color: #fde68a;
  color: #92400e;
}

.status-badge-danger {
  background-color: #fef2f2;
  border-color: #fecaca;
  color: #b91c1c;
}

.status-badge-info {
  background-color: var(--te-blue-light);
  border-color: #bae6fd;
  color: var(--te-blue-dark);
}

/*
  user_mcq_review.php restyle (2026-08-20) - moved onto the --te-*/.card-section system, replacing
  its original bg-pink-400/raw-Tailwind-utility look. One question block per attempted question,
  each with the question itself, an inline-ish "your answer" tag (reuses .status-badge-success/
  -danger above) and, when one exists, the tutor explanation (.status-badge-info).
*/
.review-question {
  border: 1px solid var(--te-border);
  border-radius: 0.5rem;
  padding: 1rem;
  margin-top: 1rem;
}

.review-question-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--te-slate-800);
  margin: 0 0 0.25rem 0;
}

.review-question-code {
  font-size: 0.75rem;
  color: var(--te-slate-500);
  font-style: italic;
  margin: 0 0 0.75rem 0;
}

.review-answer-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--te-slate-600);
  margin: 0.75rem 0 0.25rem 0;
}

/*
  2026-08-20: full options list for a reviewed question, each option shown with its real text (not
  just the bare letter) - the correct option is always highlighted green, and if the student picked
  a *different* one it's marked with an arrow and highlighted pink (the site's actual brand pink,
  not a generic red "danger" colour - matches the original bg-pink-200/300 convention this page
  used before its restyle). Nothing is marked at all if they left the question blank, other than
  the small "No answer given" note below the list.
*/
.review-options-list {
  list-style: none;
  margin: 0.5rem 0 0 0;
  padding: 0;
}

.review-option {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  padding: 0.4rem 0.6rem;
  border-radius: 0.4rem;
  margin-bottom: 0.3rem;
  border: 1px solid transparent;
}

.review-option-correct {
  background-color: #f0fdf4;
  border-color: #bbf7d0;
  color: #15803d;
  font-weight: 600;
}

.review-option-incorrect {
  background-color: var(--te-pink-light);
  border-color: var(--te-pink);
  color: var(--te-pink-dark);
  font-weight: 600;
}

.review-option-arrow {
  font-weight: 700;
}

/* Pink equivalent of .status-badge-danger, for the rare optionsTable=1 question that falls back
   to a bare-letter badge instead of the full options list above (no per-row text to highlight). */
.review-badge-incorrect {
  background-color: var(--te-pink-light);
  border-color: var(--te-pink);
  color: var(--te-pink-dark);
}

/*
  Guest-visitor "create an account" nudge on user_mcq_review.php - was page-local CSS inside that
  file's own $style_input, moved here once the page adopted the shared --te-*/extras.css system
  instead of its own inline style block. Made deliberately bold/colourful (2026-08-20, user's own
  call) rather than matching the site's usual restrained card look - this is the one conversion
  moment on the whole page, worth standing out rather than blending in.
*/
.guest-signup-cta {
  margin-top: 1.5rem;
  padding: 1.75rem 1.5rem;
  border-radius: 0.9rem;
  text-align: center;
  background: linear-gradient(135deg, var(--te-blue) 0%, var(--te-pink) 100%);
  border: none;
  box-shadow: 0 8px 20px -6px rgba(219, 39, 119, 0.4);
}

.guest-signup-cta p {
  margin: 0 0 1rem 0;
  color: #ffffff;
  font-size: 1.15rem;
  font-weight: 600;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
}

.guest-signup-cta a {
  display: inline-block;
  background-color: #ffffff;
  color: var(--te-pink-dark);
  font-weight: 700;
  font-size: 1.05rem;
  padding: 0.8rem 2rem;
  border-radius: 999px;
  text-decoration: none;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
  transition: transform 0.15s ease;
}

.guest-signup-cta a:hover {
  background-color: var(--te-bg-alt);
  transform: translateY(-1px) scale(1.03);
}

.cell-center {
  text-align: center;
}

/*
  group_manager.php's Teachers/Students side-by-side panels: stacked on mobile, two columns from
  the same 768px breakpoint used throughout (.auth-field-row, .site-nav-links) - not reused
  directly here since a form-field-row class stretched over two card sections read wrong
  semantically even though the underlying CSS is nearly identical.
*/
.gm-panels {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
}

@media (min-width: 768px) {
  .gm-panels {
    grid-template-columns: 1fr 1fr;
  }
}

/*
user_work_review.php restyle (2026-08-16): page-level intro line, the student multi-select
checkbox grid, and the two MCQ Summary charts (donut + histogram). Reuses .card-section/
.auth-form/.auth-field/.dash-table/.auth-hint/.btn-secondary for everything else on the page.
*/
.page-explainer {
  font-size: 0.95rem;
  color: var(--te-slate-600);
  margin: 0 0 1rem 0;
}

.uwr-student-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.uwr-student-check {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.875rem;
  background-color: var(--te-bg-alt);
  border: 1px solid var(--te-border);
  border-radius: 0.375rem;
  padding: 0.5rem 0.6rem;
  cursor: pointer;
}

/* MCQ Summary: Independent vs Assignment donut */
.mcq-pie-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin: 0.5rem 0 1.25rem 0;
}

.mcq-pie-svg {
  width: 120px;
  height: 120px;
  flex-shrink: 0;
}

.mcq-pie-legend {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  font-size: 0.875rem;
  color: var(--te-slate-800);
}

.mcq-pie-legend-item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.mcq-pie-swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  flex-shrink: 0;
}

/* MCQ Summary: activity-over-time histogram */
.mcq-histogram-section {
  margin: 0.5rem 0 1.25rem 0;
}

.mcq-histogram-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.mcq-histogram-title {
  margin: 0;
}

.mcq-histogram-toggle {
  display: flex;
  border: 1px solid var(--te-border);
  border-radius: 0.375rem;
  overflow: hidden;
}

.mcq-histogram-toggle-btn {
  background-color: #ffffff;
  color: var(--te-slate-600);
  border: none;
  padding: 0.35rem 0.75rem;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
}

.mcq-histogram-toggle-btn + .mcq-histogram-toggle-btn {
  border-left: 1px solid var(--te-border);
}

.mcq-histogram-toggle-btn.active {
  background-color: var(--te-blue);
  color: #ffffff;
}

.mcq-histogram-wrap {
  position: relative;
  overflow-x: auto;
}

.mcq-hist-bar {
  fill: var(--te-blue);
}

.mcq-hist-bar-selected {
  fill: var(--te-blue-dark);
}

.mcq-histogram svg rect[role="button"] {
  cursor: pointer;
}

.mcq-hist-gridline {
  stroke: var(--te-border);
  stroke-width: 1;
}

.mcq-hist-axis-label {
  fill: var(--te-slate-500);
  font-size: 10px;
}

.mcq-histogram-hint-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.mcq-histogram-hint {
  margin-top: 0.4rem;
}

/*
Click-to-reveal detail panel (2026-08-16), replacing an earlier hover tooltip - a plain inline
block below the chart rather than an absolutely-positioned floating box, so it can never be
clipped by .mcq-histogram-wrap's overflow-x:auto (which per the CSS spec forces overflow-y to
clip too, the actual bug behind the old tooltip going invisible). Also works on touch devices,
where hover never fires at all.
*/
.mcq-histogram-detail {
  margin-top: 0.75rem;
  background-color: var(--te-bg-alt);
  border: 1px solid var(--te-border);
  border-radius: 0.5rem;
  padding: 0.75rem 1rem;
  font-size: 0.85rem;
}

.mcq-histogram-detail-title {
  margin: 0 0 0.35rem 0;
  font-weight: 700;
  color: var(--te-slate-800);
}

.mcq-histogram-detail-stats {
  color: var(--te-slate-600);
}

.mcq-histogram-detail-quizzes {
  list-style: none;
  margin: 0.5rem 0 0 0;
  padding: 0.5rem 0 0 0;
  border-top: 1px solid var(--te-border);
  color: var(--te-slate-800);
}

.mcq-histogram-detail-quizzes li {
  padding: 0.3rem 0;
}

.mcq-histogram-detail-quizzes li + li {
  border-top: 1px solid var(--te-border);
}

.mcq-histogram-detail-quiz-meta {
  font-size: 0.75rem;
  color: var(--te-slate-500);
  margin-top: 0.1rem;
}
