/* ════════════════════════════════════════════════════════════════════════
   SoloCogs · MASTER STYLESHEET
   ────────────────────────────────────────────────────────────────────────
   This is the single source of truth for SoloCogs' brand, tokens,
   typography, nav, footer, buttons, hero patterns, eyebrows, cards,
   utilities, and the subject palette swap (data-subject).

   Architectural rule
   ──────────────────
   ▸ If a pattern will be reused on 2+ pages, it lives HERE so it
     cannot drift across the site (e.g. .btn-primary, .hero-eyebrow,
     .solo-icon-frame, --solo-mastery, marketing hero pattern).

   ▸ A page that is intentionally its own visual world - Hall of Lab
     Legends, Atomic Vault, future immersive experiences - gets its
     own .css file, scoped to that page, with whatever palette and
     chrome that world needs. The shared brand patterns above still
     apply to ANY brand chrome that surface uses.

   ▸ Page-specific .css files for normal pages (dashboards, quizzes,
     resource shells) should be LAYOUT-ONLY: grid placement, spacing,
     responsive breakpoints. They consume tokens from this file
     rather than redefining colours/typography.

   History
   ───────
   ▸ 2026-06-11: Merged css/styles.css (legacy base) into this file
     to remove the "which file do I extend?" ambiguity that was
     causing brand drift. The legacy section sits first so the
     cascade order (legacy beaten by Solo 2027 tokens) is preserved.

   ▸ 2026-06-11: Legacy --teal (#2A7F7F) token retired; all consumers
     swept to --solo-mastery-deep (#14B8A6).

   See CLAUDE.md "Locked design rules" for the visual-design contract
   that this file implements.
   ════════════════════════════════════════════════════════════════════════ */

/* ════════════════════════════════════════════════════════════════════════
   PART 1 - LEGACY BASE (merged from styles.css 2026-06-11)
   ────────────────────────────────────────────────────────────────────────
   Typography, layout primitives, nav, footer, and legacy page chrome
   that pre-dates the Solo 2027 reskin. Loads first so the Solo 2027
   tokens + components below can override on tied specificity.
   ════════════════════════════════════════════════════════════════════════ */
/* Skip-to-content link (WCAG 2.4.1 Bypass Blocks) - visually hidden until
   focused, then slides in. Pill shape + navy/white for AA contrast. */
.skip-link {
  position: absolute; left: 8px; top: -56px; z-index: 9999;
  background: #1B3A6B; color: #fff; padding: 10px 16px;
  border-radius: 999px; font-weight: 600; text-decoration: none;
  transition: top .15s ease;
}
.skip-link:focus { top: 8px; outline: 3px solid #2DD4BF; outline-offset: 2px; }

:root {
  --navy: #1B3A6B;
  --navy-dark: #0f2347;
  --navy-light: #2a5298;
  /* --teal removed 2026-06-11: legacy desaturated grey-teal (#2A7F7F)
     conflicted with the modern clean teal (--solo-mastery-deep #14B8A6
     defined in solocogs-theme.css). All consumers swept to the modern
     token in the same commit. --teal-light + --teal-pale below are
     different tokens (paler variants) and stay. */
  --teal-light: #3a9e9e;
  --teal-pale: #e8f5f5;
  --green: #3a7d44;
  --green-pale: #eaf3eb;
  --sand: #c8a882;
  --sand-pale: #faf6f0;
  --gold: #e8b84b;
  --white: #ffffff;
  --off-white: #fafaf8;
  --text: #1a1a2e;
  --text-mid: #4a4a6a;
  --text-light: #8888aa;
  --border: #e8e8f0;
  --bio: #3a7d44;
  --bio-pale: #eaf3eb;
  --chem: #9e3a1a;
  --chem-pale: #fdf0eb;
  --phys: #1B3A6B;
  --phys-pale: #eef1f8;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* Global keyboard-focus ring. Applies on every page regardless of
   body theme class. Dual-ring (teal core + navy outer halo) so the
   focus indicator hits WCAG SC 1.4.11 non-text contrast (3:1) against
   both the off-white page background and the white card surfaces.
   Bio teal alone scores ~1.5:1 against #F8FAFC and fails. The outer
   navy box-shadow gives a 14:1 outline that's unmistakable from any
   distance while keeping the brand-teal core visible. */
:focus-visible {
  outline: 2px solid var(--teal, #14B8A6);
  outline-offset: 3px;
  box-shadow: 0 0 0 5px rgba(15, 23, 42, .55);
  border-radius: 4px;
}
/* Native mouse focus (post-click) - suppress the default browser
   black/dotted ring that lingers on buttons after clicking. */
:focus:not(:focus-visible) {
  outline: none;
}

html { overflow-x: clip; }

body {
  font-family: 'DM Sans', sans-serif;
  color: var(--text);
  background: var(--off-white);
  font-size: 16px;
  line-height: 1.7;
}

h1, h2, h3, h4 {
  font-family: 'Lora', serif;
  line-height: 1.3;
}

/* ── NAV ── */
nav {
  background: var(--white);
  border-bottom: 1px solid var(--border);
  padding: 0 2rem;
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 68px;
}

.nav-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
}

.nav-logo {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--teal-pale);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--border);
  overflow: hidden;
  flex-shrink: 0;
}

.nav-logo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.nav-name {
  font-family: 'Lora', serif;
  font-size: 17px;
  font-weight: 600;
  color: var(--solo-heading-color, var(--navy));
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 2rem;
  list-style: none;
}

.nav-links a {
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  color: var(--text-mid);
  transition: color 0.2s;
}

.nav-links a:hover, .nav-links a.active {
  color: var(--solo-heading-color, var(--navy));
}

.nav-cta {
  background: var(--navy);
  color: var(--white) !important;
  padding: 9px 18px;
  border-radius: 999px;        /* PILL - locked button-shape rule */
  transition: background 0.2s !important;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  line-height: 1;
}

.nav-cta:hover {
  background: var(--navy-dark) !important;
}

.nav-signin {
  border: 1.5px solid var(--border);
  color: var(--solo-heading-color, var(--navy)) !important;
  padding: 8px 16px;
  border-radius: 999px;        /* PILL - locked button-shape rule */
  transition: border-color 0.2s, background 0.2s !important;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  line-height: 1;
  font-weight: 500;
}

.nav-signin:hover {
  border-color: var(--navy);
  background: var(--off-white) !important;
}

.nav-signout-btn {
  border: 1.5px solid var(--border);
  color: var(--solo-heading-color, var(--navy)) !important;
  padding: 8px 16px;
  border-radius: 999px;
  background: transparent;
  font-family: 'DM Sans', sans-serif;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.nav-signout-btn:hover {
  border-color: var(--navy);
  background: var(--off-white);
}

/* ── BURGER MENU ── */
.nav-burger {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px;
  border-radius: 6px;
  flex-shrink: 0;
}
.nav-burger span {
  display: block;
  height: 2px;
  background: var(--navy);
  border-radius: 2px;
  transition: transform 0.25s ease, opacity 0.25s ease;
  transform-origin: center;
}
.nav-burger.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-burger.open span:nth-child(2) { opacity: 0; }
.nav-burger.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 768px) {
  .nav-burger { display: flex; }

  .nav-links {
    display: none;
    position: absolute;
    top: 68px;
    left: 0;
    right: 0;
    background: var(--white);
    border-bottom: 1px solid var(--border);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0.5rem 0;
    box-shadow: 0 6px 24px rgba(27,58,107,0.10);
    z-index: 99;
  }
  .nav-links.open { display: flex; }

  .nav-links li { border-bottom: 1px solid var(--border); }
  .nav-links li:last-child { border-bottom: none; }

  .nav-links a {
    display: block;
    padding: 14px 1.75rem;
    font-size: 15px;
  }
  .nav-cta {
    display: block;
    margin: 0.75rem 1.75rem 0.5rem;
    text-align: center;
    border-radius: 999px;        /* PILL - locked button-shape rule */
    padding: 12px 18px;
  }
}

/* ── HERO SLIDESHOW ── */
.hero-slideshow {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero-slide {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  animation: hero-slide 18s infinite;
}

.hero-slide:nth-child(1) { animation-delay: 0s; }
.hero-slide:nth-child(2) { animation-delay: 6s; }
.hero-slide:nth-child(3) { animation-delay: 12s; }

.hero-slide-overlay {
  position: absolute;
  inset: 0;
  background: rgba(13, 27, 46, 0.65);
}

@keyframes hero-slide {
  0%     { opacity: 0; }
  5.56%  { opacity: 1; }
  27.78% { opacity: 1; }
  33.33% { opacity: 0; }
  100%   { opacity: 0; }
}

/* ── HERO ── */
.hero {
  background: #0d1b2e;
  background-image:
    radial-gradient(ellipse 70% 80% at 75% 50%, rgba(42,127,127,0.15) 0%, transparent 65%),
    radial-gradient(ellipse 50% 50% at 10% 90%, rgba(42,82,152,0.2) 0%, transparent 60%);
  padding: 6rem 2rem;
  position: relative;
  overflow: hidden;
}

.hero-inner {
  max-width: 1180px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 400px;
  gap: 5rem;
  align-items: center;
}

.hero-left {
  position: relative;
  z-index: 1;
}

.hero-right {
  position: relative;
  z-index: 1;
}

.hero-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(42,127,127,0.18);
  border: 1px solid rgba(42,158,158,0.35);
  color: #7dd4d4;
  font-family: 'DM Sans', sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: 100px;
  margin-bottom: 2rem;
}

.hero h1 {
  font-size: clamp(2.2rem, 3.5vw, 3.4rem);
  color: var(--white);
  margin-bottom: 1.5rem;
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

.hero h1 em {
  color: var(--gold);
  font-style: italic;
}

.hero-sub {
  font-size: 1.05rem;
  color: rgba(255,255,255,0.62);
  margin-bottom: 2.5rem;
  max-width: 480px;
  line-height: 1.8;
}

.hero-btns {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  position: relative;
  z-index: 2;
}

/* Right column - angles stack */
.hero-angles-stack {
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,0.14);
  background: rgba(8,18,36,0.82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  margin-bottom: 1rem;
}

.hero-angle-item {
  display: flex;
  align-items: flex-start;
  gap: 1.25rem;
  padding: 1.4rem 1.5rem;
  border-bottom: 1px solid rgba(255,255,255,0.1);
  transition: background 0.2s;
}

.hero-angle-item:last-child { border-bottom: none; }
.hero-angle-item:hover { background: rgba(255,255,255,0.05); }

.angle-num {
  font-family: 'Lora', serif;
  font-size: 1.4rem;
  font-weight: 600;
  color: var(--gold);
  line-height: 1;
  min-width: 28px;
  padding-top: 2px;
}

.hero-angle-title {
  font-family: 'DM Sans', sans-serif;
  font-size: 11px;
  font-weight: 700;
  color: rgba(255,255,255,0.95);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  margin-bottom: 5px;
}

.hero-angle-desc {
  font-size: 13px;
  color: rgba(255,255,255,0.78);
  line-height: 1.6;
}

.hero-tagline-strip {
  padding: 1rem 1.5rem;
  border-radius: 10px;
  background: rgba(8,18,36,0.82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(232,184,75,0.35);
  font-family: 'Lora', serif;
  font-style: italic;
  font-size: 13px;
  color: rgba(255,255,255,0.82);
  line-height: 1.6;
}

.hero-tagline-strip strong {
  color: var(--gold);
  font-weight: 600;
  display: block;
  font-size: 14px;
}

.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--solo-mastery-deep);
  color: var(--white);
  padding: 13px 28px;
  border-radius: 999px;                         /* PILL - per locked button-shape rule */
  font-family: 'DM Sans', sans-serif;
  font-size: 15px;
  font-weight: 500;
  text-decoration: none;
  transition: background 0.2s;
  cursor: pointer;
  border: none;
  line-height: 1;
}

.btn-primary:hover { background: var(--teal-light); }

.btn-outline {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--white);
  padding: 13px 28px;
  border-radius: 999px;                         /* PILL - per locked button-shape rule */
  font-family: 'DM Sans', sans-serif;
  font-size: 15px;
  font-weight: 500;
  text-decoration: none;
  border: 1.5px solid rgba(255,255,255,0.5);
  transition: all 0.2s;
  cursor: pointer;
  line-height: 1;
}

.btn-outline:hover {
  background: rgba(255,255,255,0.18);
  border-color: rgba(255,255,255,0.8);
}

/* ── SECTIONS ── */
.section {
  padding: 4rem 2rem;
  max-width: 1100px;
  margin: 0 auto;
}

.section-sm { padding: 3rem 2rem; max-width: 1100px; margin: 0 auto; }

.section-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  /* Brand Mastery Deep teal - the legacy --teal (#2A7F7F) was muted enough
     to read as "grey with a teal glow" against light backgrounds. House
     rule: section eyebrows are clean teal, no greyed-out look. */
  color: var(--solo-mastery-deep, #14B8A6);
  margin-bottom: 0.75rem;
}

.section-title {
  font-size: clamp(1.5rem, 3vw, 2.2rem);
  color: var(--solo-heading-color, var(--navy));
  margin-bottom: 1rem;
}

.section-intro {
  font-size: 1.05rem;
  color: var(--text-mid);
  max-width: 620px;
  margin-bottom: 3rem;
  line-height: 1.7;
}

/* ── PHILOSOPHY STRIP ── */
.philosophy-strip {
  background: var(--teal-pale);
  border-top: 1px solid #c8e8e8;
  border-bottom: 1px solid #c8e8e8;
  padding: 3rem 2rem;
}

.philosophy-inner {
  max-width: 860px;
  margin: 0 auto;
  text-align: center;
}

.philosophy-quote {
  font-family: 'Lora', serif;
  font-size: clamp(1.1rem, 2vw, 1.5rem);
  font-style: italic;
  color: var(--solo-heading-color, var(--navy));
  line-height: 1.6;
  margin-bottom: 1rem;
}

.philosophy-attr {
  font-size: 13px;
  color: var(--solo-mastery-deep);
  font-weight: 500;
}

/* ── CARDS ── */
.cards-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}

.cards-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem;
}

.card {
  background: var(--white);
  border: none;
  border-radius: 16px;
  padding: 2rem;
  box-shadow: 0 1px 3px rgba(27,58,107,0.05), 0 4px 20px rgba(27,58,107,0.07);
  transition: transform 0.2s, box-shadow 0.2s;
}

.card:hover {
  transform: translateY(-3px);
  box-shadow: 0 4px 8px rgba(27,58,107,0.08), 0 16px 36px rgba(27,58,107,0.11);
}

.card-icon {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.25rem;
  font-size: 22px;
}

.icon-bio { background: var(--bio-pale); }
.icon-chem { background: var(--chem-pale); }
.icon-phys { background: var(--phys-pale); }
.icon-teal { background: var(--teal-pale); }
.icon-sand { background: var(--sand-pale); }

.card h3 {
  font-family: 'Lora', serif;
  font-size: 1.1rem;
  color: var(--solo-heading-color, var(--navy));
  margin-bottom: 0.6rem;
  font-weight: 600;
}

.card p {
  font-family: 'DM Sans', sans-serif;
  font-size: 14px;
  color: var(--text-mid);
  line-height: 1.7;
}

/* ── OFFER CARDS ── */
.offer-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.offer-header {
  padding: 1.5rem 1.75rem;
  border-bottom: 1px solid var(--border);
  min-height: 130px;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

.offer-header h3 {
  font-family: 'Lora', serif;
  font-size: 1.15rem;
  color: var(--solo-heading-color, var(--navy));
  line-height: 1.3;
}

.offer-header p {
  font-family: 'DM Sans', sans-serif;
  font-size: 13px;
  color: var(--text-mid);
  margin-top: 6px;
  line-height: 1.5;
}

.offer-body {
  padding: 1.25rem 1.75rem;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.offer-features {
  list-style: none;
  margin-bottom: 1.25rem;
  flex: 1;
}

.offer-features li {
  font-size: 14px;
  color: var(--text-mid);
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.offer-features li:last-child { border-bottom: none; }

.offer-features li::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--solo-mastery-deep);
  margin-top: 7px;
  flex-shrink: 0;
}

.btn-navy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--navy);
  color: var(--white);
  padding: 10px 22px;
  border-radius: 999px;                         /* PILL - per locked button-shape rule */
  font-family: 'DM Sans', sans-serif;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  border: none;
  cursor: pointer;
  transition: background 0.2s;
  line-height: 1;
}

.btn-navy:hover { background: var(--navy-dark); }

.btn-teal {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--solo-mastery-deep);
  color: var(--white);
  padding: 10px 22px;
  border-radius: 999px;                         /* PILL - per locked button-shape rule */
  font-family: 'DM Sans', sans-serif;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  border: none;
  cursor: pointer;
  transition: background 0.2s;
  line-height: 1;
}

.btn-teal:hover { background: var(--teal-light); }

/* ── BADGE ── */
.badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 20px;
  margin-bottom: 0.75rem;
}

.badge-bio { background: var(--bio-pale); color: var(--bio); }
.badge-chem { background: var(--chem-pale); color: var(--chem); }
.badge-phys { background: var(--phys-pale); color: var(--phys); }
.badge-teal { background: var(--teal-pale); color: var(--solo-mastery-deep); }
.badge-navy { background: var(--phys-pale); color: var(--solo-heading-color, var(--navy)); }
/* Dark-mode badge overrides: badge-navy's --navy text was dark-on-dark, and
   badge-teal sat too light. Use translucent fills + light text in dark mode. */
body.dark-mode .badge-teal { background: rgba(45, 212, 191, 0.16); color: #5EEAD4; }
body.dark-mode .badge-navy { background: rgba(99, 102, 241, 0.18); color: #C7D2FE; }
@media (prefers-color-scheme: dark) {
  body:not(.light-mode):not(.dark-mode) .badge-teal { background: rgba(45, 212, 191, 0.16); color: #5EEAD4; }
  body:not(.light-mode):not(.dark-mode) .badge-navy { background: rgba(99, 102, 241, 0.18); color: #C7D2FE; }
}

/* ── ABOUT PAGE ── */
.about-hero {
  background: linear-gradient(135deg, var(--navy) 0%, var(--navy-light) 100%);
  padding: 4rem 2rem;
  color: white;
}

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

.about-hero h1 {
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  color: white;
  margin-bottom: 1rem;
}

.about-hero p {
  color: rgba(255,255,255,0.8);
  font-size: 1.05rem;
  line-height: 1.7;
}

.about-avatar {
  width: 180px;
  height: 180px;
  border-radius: 50%;
  background: rgba(255,255,255,0.15);
  border: 3px solid rgba(255,255,255,0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Lora', serif;
  font-size: 48px;
  color: rgba(255,255,255,0.6);
}

.tri-boxes {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  margin: 2rem 0;
}

.tri-box {
  border-radius: 10px;
  padding: 1.25rem;
  text-align: center;
}

.tri-box-1 { background: var(--bio-pale); }
.tri-box-2 { background: var(--chem-pale); }
.tri-box-3 { background: var(--phys-pale); }

.tri-box-num {
  font-family: 'Lora', serif;
  font-size: 2rem;
  font-weight: 600;
  margin-bottom: 4px;
}

.tri-box-1 .tri-box-num { color: var(--bio); }
.tri-box-2 .tri-box-num { color: var(--chem); }
.tri-box-3 .tri-box-num { color: var(--phys); }

.tri-box-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--solo-heading-color, var(--navy));
  margin-bottom: 4px;
}

.tri-box-desc {
  font-size: 12px;
  color: var(--text-mid);
  line-height: 1.5;
}

.credentials {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1rem;
}

.credential-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 1rem;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.credential-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--solo-mastery-deep);
  margin-top: 6px;
  flex-shrink: 0;
}

.credential-text {
  font-size: 14px;
  color: var(--text-mid);
  line-height: 1.5;
}

/* ── RESOURCES PAGE ── */
.resources-hero {
  background: var(--sand-pale);
  border-bottom: 1px solid var(--border);
  padding: 3rem 2rem;
}

.resources-hero-inner { max-width: 760px; margin: 0 auto; }

.resource-pack {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  transition: box-shadow 0.2s;
}

.resource-pack:hover {
  box-shadow: 0 4px 20px rgba(27,58,107,0.1);
}

.resource-pack-header {
  padding: 1.25rem 1.5rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.resource-pack-body { padding: 1.25rem 1.5rem; }

.resource-pack-title {
  font-family: 'Lora', serif;
  font-size: 1rem;
  color: var(--solo-heading-color, var(--navy));
}

.resource-pack-meta {
  font-size: 12px;
  color: var(--text-light);
  margin-top: 3px;
}

.resource-price {
  font-family: 'Lora', serif;
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--solo-heading-color, var(--navy));
}

.resource-features {
  list-style: none;
  margin-bottom: 1rem;
}

.resource-features li {
  font-size: 13px;
  color: var(--text-mid);
  padding: 4px 0;
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.resource-features li::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--solo-mastery-deep);
  margin-top: 7px;
  flex-shrink: 0;
}

.free-tag {
  display: inline-block;
  background: var(--green-pale);
  color: var(--green);
  font-size: 11px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 20px;
}

/* ── DIAGNOSTIC PAGE ── */
.diagnostic-hero {
  background: var(--navy);
  padding: 3.5rem 2rem;
  color: white;
}

.diagnostic-hero-inner { max-width: 760px; margin: 0 auto; }

.diagnostic-hero h1 {
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  color: white;
  margin-bottom: 1rem;
}

.diagnostic-hero p {
  color: rgba(255,255,255,0.8);
  max-width: 580px;
  line-height: 1.7;
}

.topic-columns {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
  margin-bottom: 2rem;
}

.topic-col {
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid var(--border);
}

.topic-col-header {
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  color: white;
  font-size: 14px;
  font-weight: 600;
}

.tc-bio { background: var(--bio); }
.tc-chem { background: var(--chem); }
.tc-phys { background: var(--phys); }

.topic-col-body { padding: 8px; background: var(--white); }

.topic-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 7px;
  margin-bottom: 3px;
  font-size: 12px;
  font-weight: 500;
}

.topic-row:last-child { margin-bottom: 0; }

.topic-free-bio { background: var(--bio-pale); color: var(--bio); border: 1px solid #c8ddc8; }
.topic-free-chem { background: var(--chem-pale); color: var(--chem); border: 1px solid #e8c8b8; }
.topic-free-phys { background: var(--phys-pale); color: var(--phys); border: 1px solid #c8d4e8; }
.topic-locked { background: #f8f8f8; color: var(--text-light); border: 1px solid var(--border); opacity: 0.7; }

.topic-dot-bio { width: 7px; height: 7px; border-radius: 50%; background: var(--bio); flex-shrink: 0; }
.topic-dot-chem { width: 7px; height: 7px; border-radius: 50%; background: var(--chem); flex-shrink: 0; }
.topic-dot-phys { width: 7px; height: 7px; border-radius: 50%; background: var(--phys); flex-shrink: 0; }

.lock-glyph { font-size: 10px; flex-shrink: 0; opacity: 0.4; }

.topic-free-label {
  margin-left: auto;
  font-size: 10px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 10px;
  white-space: nowrap;
}

.tfl-bio { background: #c0dd97; color: #27500a; }
.tfl-chem { background: #f5c4b3; color: #712b13; }
.tfl-phys { background: #b5d4f4; color: #0c447c; }

.paper-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-light);
  padding: 6px 4px 3px;
  border-top: 1px solid var(--border);
  margin-top: 3px;
}

.paper-label:first-child { border-top: none; padding-top: 3px; margin-top: 0; }

/* ── PRICING ── */
.pricing-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
}

.price-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.75rem;
  text-align: center;
  display: flex;
  flex-direction: column;
}
.price-card .btn-navy { margin-top: auto; }

.price-card.featured {
  border-color: var(--navy);
  border-width: 2px;
  position: relative;
}

.featured-badge {
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--navy);
  color: white;
  font-size: 11px;
  font-weight: 600;
  padding: 3px 14px;
  border-radius: 20px;
}

.price-name {
  font-family: 'Lora', serif;
  font-size: 1.1rem;
  color: var(--solo-heading-color, var(--navy));
  margin-bottom: 0.5rem;
}

.price-amount {
  font-family: 'Lora', serif;
  font-size: 2.2rem;
  font-weight: 600;
  color: var(--solo-heading-color, var(--navy));
}

.price-period {
  font-size: 12px;
  color: var(--text-light);
  margin-bottom: 1rem;
}

.price-desc {
  font-size: 13px;
  color: var(--text-mid);
  line-height: 1.6;
  margin-bottom: 1.25rem;
}

/* ── CONTACT ── */
.contact-hero {
  background: var(--teal-pale);
  border-bottom: 1px solid #c8e8e8;
  padding: 3rem 2rem;
}

.contact-hero-inner { max-width: 760px; margin: 0 auto; }

.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
  align-items: start;
}

.contact-form {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 2rem;
}

.form-group { margin-bottom: 1.25rem; }

.form-label {
  display: block;
  font-size: 13px;
  font-weight: 500;
  color: var(--solo-heading-color, var(--navy));
  margin-bottom: 6px;
}

.form-input, .form-select, .form-textarea {
  width: 100%;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 7px;
  font-family: 'DM Sans', sans-serif;
  font-size: 14px;
  color: var(--text);
  background: var(--off-white);
  outline: none;
  transition: border-color 0.2s;
}

.form-input:focus, .form-select:focus, .form-textarea:focus {
  border-color: var(--solo-mastery-deep);
  background: var(--white);
}

.form-textarea { min-height: 120px; resize: vertical; }

.contact-info {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.contact-info-item {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem 1.5rem;
}

.contact-info-item h4 {
  font-size: 14px;
  color: var(--solo-heading-color, var(--navy));
  margin-bottom: 4px;
}

.contact-info-item p {
  font-size: 13px;
  color: var(--text-mid);
  line-height: 1.6;
}

/* ── FOOTER ── */
footer {
  background: var(--navy-dark);
  color: rgba(255,255,255,0.7);
  padding: 3rem 2rem 2rem;
  margin-top: 4rem;
}

.footer-inner {
  max-width: 1100px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 2fr repeat(4, 1fr);
  gap: 2rem;
  margin-bottom: 2rem;
}

.footer-brand-name {
  font-family: 'Lora', serif;
  font-size: 18px;
  color: white;
  margin-bottom: 0.75rem;
}

.footer-tagline {
  font-size: 13px;
  font-style: italic;
  color: rgba(255,255,255,0.6);
  margin-bottom: 0.5rem;
  line-height: 1.6;
}

.footer-col-title {
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(255,255,255,0.5);
  margin-bottom: 1rem;
}

.footer-links { list-style: none; }
.footer-links li { margin-bottom: 0.5rem; }
.footer-links a {
  font-size: 14px;
  color: rgba(255,255,255,0.65);
  text-decoration: none;
  transition: color 0.2s;
}
.footer-links a:hover { color: white; }

.footer-bottom {
  max-width: 1100px;
  margin: 0 auto;
  border-top: 1px solid rgba(255,255,255,0.1);
  padding-top: 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
}

.footer-legal {
  font-size: 12px;
  color: rgba(255,255,255,0.4);
}

.footer-tri {
  font-size: 12px;
  font-style: italic;
  color: rgba(255,255,255,0.4);
}

/* ── TUITION PAGE ── */
.tuition-hero {
  background: var(--navy);
  padding: 3.5rem 2rem;
}

.tuition-hero-inner { max-width: 760px; margin: 0 auto; }

.tuition-hero h1 {
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  color: white;
  margin-bottom: 1rem;
}

.tuition-hero p {
  color: rgba(255,255,255,0.8);
  max-width: 580px;
  line-height: 1.7;
}

.process-steps {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.process-step {
  display: flex;
  align-items: flex-start;
  gap: 1.25rem;
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.25rem 1.5rem;
}

.step-num {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--navy);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Lora', serif;
  font-weight: 600;
  font-size: 15px;
  flex-shrink: 0;
}

.step-content h4 {
  font-size: 15px;
  color: var(--solo-heading-color, var(--navy));
  margin-bottom: 4px;
}

.step-content p {
  font-size: 14px;
  color: var(--text-mid);
  line-height: 1.6;
}

.rag-explainer {
  background: var(--teal-pale);
  border: 1px solid #c8e8e8;
  border-radius: 12px;
  padding: 1.75rem;
  margin-bottom: 1.5rem;
}

/* ── MISC ── */
.divider {
  height: 1px;
  background: var(--border);
  margin: 0;
}

.text-center { text-align: center; }
.mb-2 { margin-bottom: 2rem; }
.mb-3 { margin-bottom: 3rem; }

.callout {
  background: var(--sand-pale);
  border: 1px solid #e8dcc8;
  border-radius: 12px;
  padding: 1.75rem;
  display: flex;
  align-items: flex-start;
  gap: 1rem;
}

.callout-icon {
  font-size: 24px;
  flex-shrink: 0;
}

.callout h4 {
  font-size: 1rem;
  color: var(--solo-heading-color, var(--navy));
  margin-bottom: 4px;
}

.callout p {
  font-size: 14px;
  color: var(--text-mid);
  line-height: 1.6;
}

.full-width-strip {
  background: var(--navy);
  padding: 3.5rem 2rem;
  text-align: center;
}

/* H2 / P / button rules need to win against the global body.theme-solo h2
   selector in solocogs-theme.css. Doubling the selector with the theme-solo
   prefix gives us the specificity to do that without !important spam. */
.full-width-strip h2,
body.theme-solo .full-width-strip h2 {
  font-size: clamp(1.4rem, 2.5vw, 2rem);
  color: #F0FDFA;
  margin-bottom: 0.75rem;
}

.full-width-strip p,
body.theme-solo .full-width-strip p {
  color: rgba(255,255,255,0.75);
  font-size: 1rem;
  margin-bottom: 1.75rem;
  max-width: 520px;
  margin-left: auto;
  margin-right: auto;
}

.full-width-strip a.btn-primary,
body.theme-solo .full-width-strip a.btn-primary {
  display: inline-block;
  background: var(--solo-mastery, var(--solo-mastery-deep));
  color: #FFFFFF;
  text-shadow: 0 1px 2px rgba(15, 23, 42, 0.18);
  border: 1px solid transparent;
  border-radius: 999px;
  padding: 14px 28px;
  font-family: var(--solo-font-head, 'DM Sans', sans-serif);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  transition: background 0.18s, box-shadow 0.18s, transform 0.18s;
}
.full-width-strip a.btn-primary:hover,
body.theme-solo .full-width-strip a.btn-primary:hover {
  background: var(--solo-mastery-deep, var(--teal-dark, var(--solo-mastery-deep)));
  box-shadow: 0 0 0 4px rgba(45, 212, 191, 0.28);
  transform: translateY(-1px);
}

/* ── COMPARISON TABLE ── */
.compare-wrap { max-width: 860px; margin: 0 auto; }
.compare-table { width: 100%; border-collapse: collapse; }
.compare-table th, .compare-table td { padding: 13px 16px; border-bottom: 1px solid var(--border); font-size: 14px; text-align: left; }
.compare-table th { font-size: 12px; font-weight: 600; color: var(--text-light); text-transform: uppercase; letter-spacing: 0.08em; background: var(--off-white); }
.compare-table th.col-free { background: var(--off-white); }
.compare-table th.col-full { background: var(--navy); color: white; border-radius: 8px 8px 0 0; }
.compare-table th.col-sub { background: var(--solo-mastery-deep); color: white; border-radius: 8px 8px 0 0; }
.compare-table td:first-child { color: var(--text); font-weight: 500; }
.compare-table td.col-free, .compare-table td.col-full, .compare-table td.col-sub { text-align: center; }
.tick { color: var(--solo-mastery-deep); font-size: 16px; font-weight: 700; }
.cross { color: #ccc; font-size: 16px; }
.partial { color: var(--gold); font-size: 13px; font-weight: 500; }
.compare-table tr:hover td { background: var(--off-white); }
.compare-price { font-family: 'Lora', serif; font-size: 1.4rem; font-weight: 600; }
.compare-period { font-size: 11px; color: rgba(255,255,255,0.7); display: block; margin-top: 2px; }
.compare-cta { display: inline-block; margin-top: 12px; padding: 8px 20px; border-radius: 999px; font-size: 13px; font-weight: 500; cursor: pointer; border: none; }
.cta-free { background: var(--off-white); color: var(--solo-heading-color, var(--navy)); border: 1px solid var(--border); }
.cta-full { background: white; color: var(--solo-navy); /* darkmode-ok */ }
.cta-sub { background: white; color: var(--solo-mastery-deep); /* darkmode-ok */ }
.section-group-label { font-size: 11px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-light); padding: 14px 16px 6px; background: var(--off-white); }

/* ── RESULTS PAGES ── */
.results-hero-free { background: var(--navy); padding: 3rem 2rem; }
.results-hero-sub { background: linear-gradient(135deg, var(--navy) 0%, var(--solo-mastery-deep) 100%); padding: 3rem 2rem; }
.results-inner { max-width: 760px; margin: 0 auto; }
.grade-pill { display: inline-flex; align-items: center; justify-content: center; width: 72px; height: 72px; border-radius: 50%; font-family: 'Lora', serif; font-size: 2rem; font-weight: 600; margin-bottom: 1rem; }
.grade-pill-free { background: rgba(255,255,255,0.15); color: white; border: 3px solid rgba(255,255,255,0.4); }
.grade-pill-sub { background: var(--gold); color: var(--solo-heading-color, var(--navy)); border: 3px solid rgba(255,255,255,0.4); }
.rag-summary-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin: 1.5rem 0; }
.rag-summary-card { background: var(--white); border: 1px solid var(--border); border-radius: 10px; padding: 1rem; text-align: center; }
.rag-count { font-family: 'Lora', serif; font-size: 1.8rem; font-weight: 600; color: var(--solo-heading-color, var(--navy)); }
.rag-label-sm { font-size: 12px; color: var(--text-mid); margin-top: 4px; line-height: 1.4; }
.where-now-box { background: var(--teal-pale); border: 1px solid #c8e8e8; border-radius: 12px; padding: 1.5rem; margin: 1.5rem 0; }
.where-now-title { font-family: 'Lora', serif; font-size: 1.05rem; color: var(--solo-heading-color, var(--navy)); margin-bottom: 0.5rem; }
.where-now-text { font-size: 14px; color: var(--text-mid); line-height: 1.7; }
.misconception-item { background: #faeeda; border: 1px solid #ef9f27; border-radius: 10px; padding: 1rem 1.25rem; margin-bottom: 8px; font-size: 13px; color: #633806; line-height: 1.6; }
.confidence-item { background: var(--phys-pale); border: 1px solid #b5d4f4; border-radius: 10px; padding: 1rem 1.25rem; margin-bottom: 8px; font-size: 13px; color: #0c447c; line-height: 1.6; }
.sub-upgrade-box { background: var(--navy); border-radius: 12px; padding: 1.75rem; text-align: center; margin: 2rem 0; }
.sub-upgrade-box h3 { font-size: 1.1rem; color: white; margin-bottom: 0.5rem; }
.sub-upgrade-box p { font-size: 13px; color: rgba(255,255,255,0.75); margin-bottom: 1.25rem; line-height: 1.6; }

/* ── ACCOUNT CREATION ── */
.account-hero { background: var(--navy); padding: 3rem 2rem; }
.step-flow { display: flex; align-items: center; gap: 0; margin-bottom: 2rem; flex-wrap: wrap; }
.step-flow-item { display: flex; align-items: center; gap: 8px; }
.step-flow-num { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; flex-shrink: 0; }
.step-flow-num-done { background: var(--solo-mastery-deep); color: white; }
.step-flow-num-active { background: var(--navy); color: white; }
.step-flow-num-pending { background: var(--border); color: var(--text-light); }
.step-flow-label { font-size: 13px; font-weight: 500; color: var(--text-mid); }
.step-flow-arrow { margin: 0 12px; color: var(--border); font-size: 18px; }
.account-card { background: var(--white); border: 1px solid var(--border); border-radius: 14px; padding: 2rem; max-width: 520px; margin: 0 auto; }
.account-type-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 1.5rem; }
.account-type-btn { border: 2px solid var(--border); border-radius: 999px; padding: 1.25rem; text-align: center; cursor: pointer; transition: all 0.2s; background: var(--white); }
.account-type-btn:hover { border-color: var(--navy); }
.account-type-btn.selected { border-color: var(--navy); background: var(--phys-pale); }
.account-type-icon { font-size: 28px; margin-bottom: 8px; }
.account-type-label { font-size: 14px; font-weight: 600; color: var(--solo-heading-color, var(--navy)); }
.account-type-desc { font-size: 12px; color: var(--text-mid); margin-top: 4px; line-height: 1.4; }
.pin-inputs { display: flex; gap: 10px; justify-content: center; margin: 1rem 0; }
.pin-input { width: 52px; height: 56px; border: 2px solid var(--border); border-radius: 10px; text-align: center; font-size: 1.5rem; font-family: 'Lora', serif; color: var(--solo-heading-color, var(--navy)); background: var(--off-white); outline: none; }
.pin-input:focus { border-color: var(--solo-mastery-deep); background: var(--solo-bg-elevated); }
.safeguarding-note { background: var(--bio-pale); border: 1px solid #c8ddc8; border-radius: 8px; padding: 10px 14px; font-size: 12px; color: #27500a; line-height: 1.6; margin-top: 1rem; }

/* ── DASHBOARDS ── */
.dashboard-nav { background: var(--white); border-bottom: 1px solid var(--border); padding: 0 2rem; display: flex; align-items: center; gap: 2rem; height: 52px; overflow-x: auto; }
.dash-nav-link { font-size: 13px; font-weight: 500; color: var(--text-mid); text-decoration: none; white-space: nowrap; padding-bottom: 2px; border-bottom: 2px solid transparent; cursor: pointer; transition: all 0.2s; }
.dash-nav-link.active { color: var(--solo-heading-color, var(--navy)); border-bottom-color: var(--navy); }
.dash-hero { background: var(--off-white); border-bottom: 1px solid var(--border); padding: 1.5rem 2rem; }
.dash-hero-inner { max-width: 1100px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.dash-greeting { font-family: 'Lora', serif; font-size: 1.3rem; color: var(--solo-heading-color, var(--navy)); }
.dash-sub-greeting { font-size: 13px; color: var(--text-mid); margin-top: 3px; }
.dash-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; margin-bottom: 1.5rem; }
.dash-stat { background: var(--white); border: 1px solid var(--border); border-radius: 10px; padding: 1.25rem; }
.dash-stat-num { font-family: 'Lora', serif; font-size: 2rem; font-weight: 600; color: var(--solo-heading-color, var(--navy)); }
.dash-stat-label { font-size: 12px; color: var(--text-mid); margin-top: 4px; }
.progress-row { background: var(--white); border: 1px solid var(--border); border-radius: 10px; padding: 1rem 1.25rem; margin-bottom: 8px; display: flex; align-items: center; gap: 1rem; }
.progress-subject-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.progress-subject-name { font-size: 14px; font-weight: 500; color: var(--solo-heading-color, var(--navy)); flex: 1; }
.progress-grade { font-family: 'Lora', serif; font-size: 1.2rem; font-weight: 600; color: var(--solo-heading-color, var(--navy)); margin-right: 4px; }
.progress-bar-wrap { flex: 2; height: 8px; background: var(--border); border-radius: 4px; overflow: hidden; }
.progress-bar-fill { height: 100%; border-radius: 4px; }
.alert-item { background: #faeeda; border: 1px solid #ef9f27; border-radius: 10px; padding: 1rem 1.25rem; margin-bottom: 8px; display: flex; align-items: flex-start; gap: 10px; }
.alert-dot { width: 8px; height: 8px; border-radius: 50%; background: #ba7517; flex-shrink: 0; margin-top: 5px; }
.alert-text { font-size: 13px; color: #633806; line-height: 1.6; }
.student-card { background: var(--white); border: 1px solid var(--border); border-radius: 12px; padding: 1.25rem 1.5rem; margin-bottom: 10px; display: flex; align-items: center; gap: 1rem; }
.student-avatar { width: 40px; height: 40px; border-radius: 50%; background: var(--phys-pale); display: flex; align-items: center; justify-content: center; font-family: 'Lora', serif; font-size: 16px; font-weight: 600; color: var(--solo-heading-color, var(--navy)); flex-shrink: 0; }
.student-name { font-size: 15px; font-weight: 500; color: var(--solo-heading-color, var(--navy)); }
.student-meta { font-size: 12px; color: var(--text-mid); margin-top: 2px; }

/* ── STUDENT VIEW ── */
.student-hero { background: linear-gradient(135deg, #1a6b3a 0%, #2a7f7f 100%); padding: 2.5rem 2rem; }
.student-streak { display: inline-flex; align-items: center; gap: 8px; background: rgba(255,255,255,0.15); border: 1px solid rgba(255,255,255,0.25); border-radius: 20px; padding: 6px 14px; margin-bottom: 1rem; }
.student-streak-text { font-size: 12px; color: white; font-weight: 500; }
.topic-progress-card { background: var(--white); border: 1px solid var(--border); border-radius: 12px; overflow: hidden; margin-bottom: 10px; }
.topic-progress-header { padding: 1rem 1.25rem; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; }
.topic-progress-body { padding: 1rem 1.25rem; }
.grade-shape { display: inline-flex; align-items: center; justify-content: center; font-size: 11px; font-weight: 700; margin-right: 4px; }
.shape-circle { width: 28px; height: 28px; border-radius: 50%; background: #639922; color: white; }
.shape-square { width: 28px; height: 28px; border-radius: 3px; background: #378add; color: white; }
.shape-triangle { width: 0; height: 0; border-left: 14px solid transparent; border-right: 14px solid transparent; border-bottom: 24px solid #d85a30; display: flex; align-items: flex-end; justify-content: center; padding-bottom: 3px; color: white; font-size: 9px; }
.well-done-box { background: var(--bio-pale); border: 1px solid #c0dd97; border-radius: 10px; padding: 1.25rem; text-align: center; margin: 1.5rem 0; }
.well-done-title { font-family: 'Lora', serif; font-size: 1.1rem; color: var(--bio); margin-bottom: 4px; }
.well-done-text { font-size: 13px; color: var(--text-mid); }

/* ── POLICY PAGES ── */
.policy-hero {
  background: linear-gradient(135deg, #1B3A6B 0%, #2a5298 100%);
  padding: 3rem 2rem 2.5rem; color: white;
}
.policy-hero-inner { max-width: 860px; margin: 0 auto; }
.policy-back {
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: 12px; font-weight: 600; color: rgba(255,255,255,.6);
  text-decoration: none; text-transform: uppercase; letter-spacing: .08em;
  margin-bottom: 1.25rem; transition: color .15s;
}
.policy-back:hover { color: rgba(255,255,255,.9); }
.policy-hero h1 { font-family: 'Lora',serif; font-size: clamp(1.6rem,3vw,2.2rem); margin: 0 0 .6rem; line-height: 1.2; }
.policy-meta { font-size: 12.5px; color: rgba(255,255,255,.55); display: flex; gap: 1.5rem; flex-wrap: wrap; }
.policy-meta span::before { content: ''; }

.policy-body { max-width: 860px; margin: 0 auto; padding: 3rem 2rem 4rem; }
.policy-body h2 {
  font-family: 'Lora',serif; font-size: 1.2rem; color: var(--solo-heading-color, var(--navy));
  margin: 2.5rem 0 .65rem; padding-bottom: .5rem;
  border-bottom: 1px solid var(--border);
}
.policy-body h2:first-child { margin-top: 0; }
.policy-body h3 { font-size: 14px; font-weight: 700; color: var(--solo-heading-color, var(--navy)); margin: 1.25rem 0 .35rem; }
.policy-body p { font-size: 14px; color: var(--text-mid); line-height: 1.85; margin: 0 0 .85rem; }
.policy-body ul, .policy-body ol { padding-left: 1.4rem; margin: 0 0 .85rem; }
.policy-body li { font-size: 14px; color: var(--text-mid); line-height: 1.8; margin-bottom: .2rem; }
.policy-body strong { color: var(--solo-heading-color, var(--navy)); }
.policy-body a { color: var(--solo-mastery-deep); }
.policy-contact-box {
  background: var(--off-white); border: 1px solid var(--border);
  border-radius: 12px; padding: 1.25rem 1.5rem; margin-top: 2rem;
}
.policy-contact-box p { margin: 0; }

/* "Who runs SoloCogs" callout shown at the top of every policy so the
   legal entity (Portsdown Tuition) and the brand (SoloCogs) are
   explicitly named once, then referenced consistently throughout the
   document. */
.policy-operator-note {
  background: #F0FDFA; border: 1px solid rgba(45, 212, 191, 0.45);
  border-left: 3px solid #14B8A6;
  border-radius: 12px; padding: 1.1rem 1.4rem;
  margin: 0 0 2rem;
}
.policy-operator-note p { margin: 0 0 .55rem; font-size: 14px; line-height: 1.7; color: var(--text-mid); }
.policy-operator-note p:last-child { margin-bottom: 0; }
.policy-operator-note strong { color: var(--solo-heading-color, var(--navy)); }
body.dark-mode .policy-operator-note { background: rgba(45, 212, 191, 0.10); border-color: rgba(45, 212, 191, 0.35); }
body.dark-mode .policy-operator-note p { color: #CBD5E1; }
body.dark-mode .policy-operator-note strong { color: #5EEAD4; }
@media (prefers-color-scheme: dark) {
  body:not(.light-mode):not(.dark-mode) .policy-operator-note { background: rgba(45, 212, 191, 0.10); border-color: rgba(45, 212, 191, 0.35); }
  body:not(.light-mode):not(.dark-mode) .policy-operator-note p { color: #CBD5E1; }
  body:not(.light-mode):not(.dark-mode) .policy-operator-note strong { color: #5EEAD4; }
}

.policy-index-grid {
  display: grid; grid-template-columns: repeat(auto-fit,minmax(260px,1fr));
  gap: 1rem; max-width: 1060px; margin: 2rem auto;
}
.policy-index-card {
  background: var(--white); border: 1px solid var(--border);
  border-radius: 14px; padding: 1.4rem 1.5rem;
  text-decoration: none; display: block;
  transition: box-shadow .2s, border-color .2s;
}
.policy-index-card:hover { box-shadow: 0 4px 18px rgba(0,0,0,.09); border-color: var(--solo-mastery-deep); }
.policy-index-icon { font-size: 1.5rem; margin-bottom: .6rem; }
.policy-index-title { font-family: 'Lora',serif; font-size: 15px; font-weight: 600; color: var(--solo-heading-color, var(--navy)); margin-bottom: .3rem; }
.policy-index-desc { font-size: 13px; color: var(--text-mid); line-height: 1.6; }

/* ══════════════════════════════════════════════════
   MOBILE - RESPONSIVE BREAKPOINTS
══════════════════════════════════════════════════ */
@media (max-width: 768px) {

  /* ── General spacing ── */
  .section { padding: 2.5rem 1.25rem; }
  .section-sm { padding: 2rem 1.25rem; }
  .mb-3 { margin-bottom: 2rem; }

  /* ── Hero (index page) ── */
  .hero { padding: 3rem 1.25rem; }
  .hero-inner {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  .hero-right { display: none; }
  .hero h1 { font-size: clamp(1.8rem, 7vw, 2.6rem); }
  .hero-slide-overlay { background: rgba(13, 27, 46, 0.78); }

  /* ── Cards grids ── */
  .cards-3 { grid-template-columns: 1fr; }
  .cards-2 { grid-template-columns: 1fr; }

  /* ── Feature cards: icon + title on same row ── */
  .card {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 0.85rem;
    text-align: left;
  }
  .card-icon { margin-bottom: 0; flex-shrink: 0; }
  .card h3   { flex: 1; min-width: 0; margin-bottom: 0; font-size: 1rem; }
  .card p    { width: 100%; margin-top: 0.65rem; }

  /* ── Offer card bullet lists: always left-aligned ── */
  .offer-features { text-align: left; }

  /* ── Footer: hide nav-duplicate columns on mobile ── */
  .footer-pages-col, .footer-tools-col { display: none; }

  /* ── Footer ── */
  footer { padding: 2rem 1.25rem 1.5rem; margin-top: 2rem; }
  .footer-inner {
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
    margin-bottom: 1.5rem;
  }
  .footer-inner > div:first-child {
    grid-column: 1 / -1;
  }
  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
  }

  /* ── Contact page ── */
  .contact-grid { grid-template-columns: 1fr; }

  /* ── About page ── */
  .about-hero-inner {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
  .about-avatar { display: none; }
  .tri-boxes { grid-template-columns: 1fr; }
  .credentials { grid-template-columns: 1fr; }

  /* ── Diagnostic / baseline page ── */
  .topic-columns { grid-template-columns: 1fr; }
  .diagnostic-hero { padding: 2.5rem 1.25rem; }

  /* ── Pricing ── */
  .pricing-grid { grid-template-columns: 1fr; }

  /* ── Contact hero ── */
  .contact-hero { padding: 2rem 1.25rem; }

  /* ── Resources hero ── */
  .resources-hero { padding: 2rem 1.25rem; }

  /* ── Tuition hero ── */
  .tuition-hero { padding: 2.5rem 1.25rem; }

  /* ── About / policy / diagnostic heroes ── */
  .about-hero { padding: 2.5rem 1.25rem; }
  .policy-hero { padding: 2rem 1.25rem; }
  .policy-body { padding: 2rem 1.25rem 3rem; }

  /* ── Safeguarding page ── */
  .sg-hero-inner, .sg-creds-grid {
    grid-template-columns: 1fr !important;
  }
  .sg-hero-right { margin-top: 1.5rem; }

  /* ── RAG explainer ── */
  .rag-explainer .cards-3 { grid-template-columns: 1fr; }

  /* ── Compare table - horizontal scroll ── */
  .compare-wrap { overflow-x: auto; }
  .compare-table { min-width: 520px; }

  /* ── Comparison table wrapper needs padding ── */
  .compare-wrap { padding-bottom: 0.5rem; }

  /* ── Dashboard ── */
  .dash-grid { grid-template-columns: 1fr 1fr; }
  .dash-hero-inner { flex-direction: column; align-items: flex-start; }

  /* ── Full width strip ── */
  .full-width-strip { padding: 2.5rem 1.25rem; }

  /* ── Callout ── */
  .callout { flex-direction: column; gap: 0.75rem; }

  /* ── Process steps ── */
  .process-step { flex-direction: column; gap: 0.75rem; }
  .step-num { flex-shrink: 0; }
}

@media (max-width: 480px) {
  /* Extra small screens */
  .footer-inner { grid-template-columns: 1fr; }
  .dash-grid { grid-template-columns: 1fr; }
  .account-type-grid { grid-template-columns: 1fr; }
  .rag-summary-grid { grid-template-columns: 1fr; }
  .nav { padding: 0 1rem; }
}
.policy-index-arrow { font-size: 12px; color: var(--solo-mastery-deep); font-weight: 700; margin-top: .6rem; display: block; }

/* ── Policy index grid ── */
@media (max-width: 640px) {
  .policy-index-grid { grid-template-columns: 1fr !important; }
}

/* ── Register form ── */
@media (max-width: 540px) {
  .auth-card { padding: 1.75rem 1.25rem; border-radius: 12px; }
  .plan-cards { grid-template-columns: 1fr !important; }
}

/* ── Student dashboard ── */
@media (max-width: 480px) {
  /* force 2-col cat-grid at tiny size */
  .cat-grid { grid-template-columns: repeat(2, 1fr) !important; }
}

/* ── Tuition page ── */
@media (max-width: 640px) {
  .tuition-grid { grid-template-columns: 1fr !important; }
  .session-types { grid-template-columns: 1fr !important; }
}

/* ── Nav: ensure sign-in/out buttons stay readable ── */
@media (max-width: 768px) {
  .nav-signin, .nav-signout-btn {
    padding: 8px 14px;
    font-size: 13px;
  }
}



/* ════════════════════════════════════════════════════════════════════════
   PART 2 - SOLO 2027 THEME (originally css/solocogs-theme.css)
   ────────────────────────────────────────────────────────────────────────
   Design tokens, subject palette swap, modern component styles.
   These rules sit after the legacy base so they win cascade ties.
   ════════════════════════════════════════════════════════════════════════ */
/* ════════════════════════════════════════════════════════════
   GLOBAL [hidden] IMMUNISATION
   ────────────────────────────
   The HTML [hidden] attribute is supposed to render display:none, but
   any later class with display:flex/grid/block beats it on specificity.
   We hit this with the flashcards carousel where all 9 cards rendered
   at once. !important here ensures [hidden] wins everywhere - if you
   need visual-hide-but-render, use opacity or visibility, not [hidden].
   ════════════════════════════════════════════════════════════ */
[hidden] { display: none !important; }

/* ════════════════════════════════════════════════════════════
   SOLOCOGS · THEME · "Universal Mastery 2027"
   Source-of-truth brand system.

   USAGE
   ─────
   1. Drop into <head> AFTER any existing stylesheets:
        <link rel="stylesheet" href="css/solocogs-theme.css">
      Adding this file alone changes nothing - it only defines tokens
      and opt-in classes. Existing pages keep working untouched.

   2. To switch a page over to the Solo brand, add `theme-solo` to <body>:
        <body class="theme-solo">
      That kicks in Lexend + Atkinson, the soft-slate background, and
      the soft-charcoal type colour for that page only.

   3. Use the `.btn-solo-*`, `.card-solo`, `.pill-*` etc. utility classes
      to swap components piece by piece. No bulk rewrite needed.

   PHILOSOPHY
   ──────────
   Universal Design for Learning (UDL). No pure white (Irlen support).
   No pure black (visual vibration). Lexend for dyslexia-tuned heads.
   Atkinson Hyperlegible for body. 1.6× line-height by default.
   ════════════════════════════════════════════════════════════ */


/* ─── 1 · TYPOGRAPHY IMPORTS ──────────────────────────────── */
/* Lexend → headings & data tables (dyslexia-tuned, professional)
   Atkinson Hyperlegible → body copy (UDL hyperlegibility)
   Fonts are loaded via <link rel="stylesheet"> in every page's head
   (audit-verified across 100+ HTML files). The @import that used to
   live here was a duplicate request - removed for one fewer round-
   trip on every page load. */


/* ─── 2 · BRAND TOKENS ────────────────────────────────────── */
/* These are global the moment the file loads, but they only do
   anything when an element actually references them. So they're safe. */
:root {

  /* Surfaces - never pure white (Irlen support) */
  --solo-bg:           #F8FAFC;
  --solo-bg-elevated:  #FFFFFF;          /* used sparingly, e.g. focal cards */
  --solo-bg-overlay:   rgba(248,250,252,0.85);
  --solo-divider:      #E2E8F0;
  --solo-border:       #CBD5E1;

  /* Text - never pure black (no vibration) */
  --solo-text:         #334155;          /* Soft Charcoal - primary body */
  --solo-text-mute:    #475569;          /* Slate-600 - was #64748B (passed AA, failed AAA); now 7.1:1 = AAA */
  --solo-text-soft:    #64748B;          /* was #94A3B8 (2.85:1 on bg - FAILED AA). Now 4.65:1 = AA pass */
  --solo-navy:         #1E293B;          /* deepest heading colour */

  /* The "Solo" Palette */
  --solo-mastery:        #2DD4BF;        /* Electric Teal · Confidently Correct - for fills + accents (NOT text on white) */
  --solo-mastery-deep:   #14B8A6;        /* Slightly deeper teal - used for borders + spinners + accents */
  --solo-mastery-text:   #0F766E;        /* WCAG-safe teal for TEXT on white (5.4:1, passes AA normal text). Use this any time teal coloured COPY sits on a light bg. */
  --solo-mastery-pale:   #CCFBF1;
  --solo-mastery-glow:   rgba(45, 212, 191, 0.25);

  --solo-confidence:      #F59E0B;       /* Sunrise Amber · Lucky Guess / Boost Needed */
  --solo-confidence-deep: #D97706;
  --solo-confidence-pale: #FEF3C7;

  --solo-misconception:      #475569;    /* Deep Slate · Misconception / Gap */
  --solo-misconception-deep: #334155;
  --solo-misconception-pale: #E2E8F0;

  --solo-violet: #8B5CF6;                /* used sparingly for spec markers */

  /* Type system */
  --solo-font-head:    'Lexend', system-ui, -apple-system, "Segoe UI", sans-serif;
  --solo-font-body:    'Atkinson Hyperlegible', Georgia, "Iowan Old Style", serif;
  --solo-line-height:  1.6;              /* UDL default */
  --solo-letter-tight: -0.01em;
  --solo-letter-loose: 0.01em;

  /* Radii */
  --solo-radius-sm: 8px;
  --solo-radius:    14px;
  --solo-radius-lg: 22px;
  --solo-radius-xl: 28px;

  /* Elevation - flat-ish, only lift hover/focal elements */
  --solo-shadow-1: 0 1px 2px rgba(15,23,42,0.04), 0 1px 1px rgba(15,23,42,0.03);
  --solo-shadow-2: 0 4px 12px rgba(15,23,42,0.06), 0 2px 4px rgba(15,23,42,0.04);
  --solo-shadow-3: 0 12px 28px rgba(15,23,42,0.10), 0 4px 8px rgba(15,23,42,0.05);

  /* Motion */
  --solo-ease:  cubic-bezier(0.4, 0, 0.2, 1);
  --solo-fast:  120ms;
  --solo-slow:  280ms;
}

/* UDL - honour reduced-motion preference globally */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ─── DARK MODE (Phase 1) ──────────────────────────────────────
   Token-level swap so any element built on the --solo-* variables
   inherits a sensible dark palette automatically.

   THREE states:
   - Default (no class)        → light theme (existing tokens)
   - body.dark-mode            → manual user-selected dark
   - body.light-mode           → manual user-selected light, even if OS is dark
   - @media prefers-color-scheme: dark + no manual override → auto dark

   Per the Zen Lab brief: never pure black (Irlen support). Use the existing
   navy (#0F172A) as the page floor and lighten cards on top of it. Accent
   colours (mastery teal, confidence amber, misconception slate) stay as
   they are - they're already vivid enough to read on dark.

   This is Phase 1 - it handles the BASE surface + text + dividers + the
   theme-solo body styles. Per-page inline <style> blocks that hardcode
   light backgrounds (e.g. nav bar, resource pages' bespoke chrome) still
   need follow-up dark variants in a Phase 2 pass. */

/* Dark-mode token swap.
   --solo-navy and --navy are KEPT DARK (they're used as panel backgrounds
   on the footer, full-width strip, action hub, etc.). Heading text colour
   flips light via --solo-heading-color, not by remapping --solo-navy. */
@media (prefers-color-scheme: dark) {
  body:not(.light-mode):not(.dark-mode) {
    --solo-bg:            #0F172A;
    --solo-bg-elevated:   #1E293B;
    --solo-bg-overlay:    rgba(15, 23, 42, 0.88);
    --solo-divider:       #334155;
    --solo-border:        #475569;
    --solo-text:          #CBD5E1;
    --solo-text-mute:     #94A3B8;
    --solo-text-soft:     #64748B;
    /* heading colour flips light via this var, --solo-navy stays as the
       dark surface (#1E293B) so background uses of --solo-navy still
       render dark in dark mode. */
    --solo-heading-color: #E2E8F0;
    --solo-mastery-pale:  rgba(45, 212, 191, 0.14);
    --solo-body-color:    var(--solo-text);
    /* Legacy palette tokens used by styles.css. Same principle: --navy
       is also used as a dark surface (.full-width-strip, hero) so we
       keep it dark - text on those surfaces is already light by design. */
    --white:        #1E293B;
    --off-white:    #0F172A;
    --text:         #E2E8F0;
    --text-mid:     #CBD5E1;
    --text-light:   #94A3B8;
    --border:       #334155;
    --teal-pale:    rgba(45, 212, 191, 0.12);
    --green-pale:   rgba(34, 197, 94, 0.12);
    --sand-pale:    rgba(245, 158, 11, 0.10);
    --bio-pale:     rgba(45, 212, 191, 0.12);
    --chem-pale:    rgba(245, 158, 11, 0.12);
    --phys-pale:    rgba(99, 102, 241, 0.12);
  }
}
body.dark-mode {
  --solo-bg:            #0F172A;
  --solo-bg-elevated:   #1E293B;
  --solo-bg-overlay:    rgba(15, 23, 42, 0.88);
  --solo-divider:       #334155;
  --solo-border:        #475569;
  --solo-text:          #CBD5E1;
  --solo-text-mute:     #94A3B8;
  --solo-text-soft:     #64748B;
  --solo-heading-color: #E2E8F0;
  --solo-mastery-pale:  rgba(45, 212, 191, 0.14);
  --solo-body-color:    var(--solo-text);
  --white:        #1E293B;
  --off-white:    #0F172A;
  --text:         #E2E8F0;
  --text-mid:     #CBD5E1;
  --text-light:   #94A3B8;
  --border:       #334155;
  --teal-pale:    rgba(45, 212, 191, 0.12);
  --green-pale:   rgba(34, 197, 94, 0.12);
  --sand-pale:    rgba(245, 158, 11, 0.10);
  --bio-pale:     rgba(45, 212, 191, 0.12);
  --chem-pale:    rgba(245, 158, 11, 0.12);
  --phys-pale:    rgba(99, 102, 241, 0.12);
}
/* Soften the heavy white-card shadows on a dark page - they look
   wrong on a navy floor. */
body.dark-mode .solo-hero-card {
  box-shadow: 0 1px 2px rgba(0,0,0,0.5), 0 1px 1px rgba(0,0,0,0.35);
}
@media (prefers-color-scheme: dark) {
  body:not(.light-mode):not(.dark-mode) .solo-hero-card {
    box-shadow: 0 1px 2px rgba(0,0,0,0.5), 0 1px 1px rgba(0,0,0,0.35);
  }
}

/* ════════════════════════════════════════════════════════════════
   CLS GUARD - default aspect-ratio for undimensioned images
   ────────────────────────────────────────────────────────────────
   Resource pages have 50+ <img> tags each, lazy-loaded but without
   width/height attributes. Without a reserved layout box, the browser
   shifts content as each image streams in - the CLS budget is gone
   before the first sub-unit renders. Setting a default aspect-ratio
   gives the browser a placeholder to reserve. Explicit width/height
   attributes still win (per HTML spec), so dimensioned imgs are
   unaffected. 16/9 is the closest single ratio to the bulk of our
   diagram + micrograph content (most sit between 4/3 and 16/9). */
img:not([width]):not([height]) {
  aspect-ratio: 16 / 9;
  max-width: 100%;
  height: auto;
}
/* Belt-and-braces: containers that intentionally use square / circular
   images (avatars, legend portraits, deck tiles) shouldn't have the
   16/9 default forced on their children. Most of these set width/
   height explicitly via inline-style or :is() pinning, but the
   defensive opt-out keeps the cascade legible. */
.solo-avatar img,
.sd-avatar img,
.pd-avatar img,
.legend-portrait img,
.hol-frame-img,
.pd-stat-icon img,
.sd-stat-icon img,
.solo-deck__tile img {
  aspect-ratio: auto;
}

/* ════════════════════════════════════════════════════════════════
   SHARED COMPONENT - .solo-icon-frame
   ────────────────────────────────────────────────────────────────
   Tinted square containing a Lucide-style stroke icon. Lifts the
   icon to feel like an "active component" rather than decorative
   emoji. Was previously duplicated inline in about.html + how-it-
   works.html; consolidated here so every page picks it up via
   solocogs-theme.css. Square (rounded), NOT pill - per CLAUDE.md
   it lives outside the pill-button rule. */
.solo-icon-frame {
  width: 48px; height: 48px;
  border-radius: 12px;
  background: var(--solo-mastery-pale);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.6rem;
  color: var(--solo-mastery-deep);
  filter: drop-shadow(0 0 6px rgba(20, 184, 166, 0.30));
  transition: filter 0.35s ease, transform 0.35s ease;
}
.solo-icon-frame svg { width: 22px; height: 22px; stroke-width: 2; }
.solo-icon-frame--pulse svg {
  animation: solo-icon-pulse 2.6s ease-in-out infinite;
  transform-origin: center;
}
@keyframes solo-icon-pulse {
  0%, 100% { transform: scale(1);     opacity: 1;   }
  50%      { transform: scale(1.12);  opacity: .85; }
}
.solo-icon-frame:hover,
.origin-card:hover .solo-icon-frame,
.hiw-trip-card:hover .solo-icon-frame {
  filter: drop-shadow(0 0 14px rgba(20, 184, 166, 0.65));
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .solo-icon-frame,
  .solo-icon-frame--pulse svg { animation: none; transition: none; }
}

/* ════════════════════════════════════════════════════════════════
   DARK-MODE PASS 2 - hub + dashboard page chrome
   ────────────────────────────────────────────────────────────────
   Hub pages (cell-biology-hub.html, organisation-hub.html, etc.)
   and the main dashboards predate the dark-mode token system and
   hardcode white `#FFFFFF` card backgrounds on their hero cards, "Now Playing"
   resume cards, and chunk-grid cards. Without these overrides the
   nav + chrome stays white on a dark page (the screenshot the user
   sent shows exactly this split).

   Recolours the common card class names + softens shadows. Light
   mode unaffected since selectors are body.dark-mode-prefixed (and
   the auto-dark @media block mirrors the same selectors). Heading
   colour is set to var(--solo-navy), which the legacy-token remap
   already inverts to a near-white in dark mode.
   ════════════════════════════════════════════════════════════════ */
.dark-mode-card-recolour,
body.dark-mode .cbh-hero,
body.dark-mode .cbh-resume-hero,
body.dark-mode .cbh-card,
body.dark-mode .resource-pack,
body.dark-mode .contact-form,
body.dark-mode .contact-info-item,
body.dark-mode .credential-item,
body.dark-mode .process-step,
body.dark-mode .price-card,
body.dark-mode .progress-row,
body.dark-mode .student-card,
body.dark-mode .dash-stat,
body.dark-mode .topic-progress-card,
body.dark-mode .topic-col-body,
body.dark-mode .account-card,
body.dark-mode .auth-card,
body.dark-mode .policy-index-card,
body.dark-mode .sd-resume-card,
body.dark-mode .sc-fc-component,
body.dark-mode .solo-skel-card {
  background: var(--solo-bg-elevated, #1E293B);
  border-color: var(--solo-divider, #334155);
  color: var(--solo-text, #CBD5E1);
  box-shadow: 0 1px 2px rgba(0,0,0,0.5), 0 1px 1px rgba(0,0,0,0.35);
}
body.dark-mode .cbh-hero { border-bottom-color: var(--solo-divider, #334155); }
/* Headings on cards: most page CSS hardcodes `color: var(--solo-heading-color, var(--solo-navy))`
   which now stays dark in dark mode. Override to the heading-text
   colour so headings actually read. Scoped to common card containers
   so we don't accidentally light up text that's meant to sit on a
   teal/amber/navy panel. */
body.dark-mode .cbh-hero h1,
body.dark-mode .cbh-resume-hero h1,
body.dark-mode .cbh-card h3,
body.dark-mode .cbh-card h2,
body.dark-mode .cbh-section-title,
body.dark-mode .price-name,
body.dark-mode .progress-grade,
body.dark-mode .progress-subject-name,
body.dark-mode .dash-stat-num,
body.dark-mode .student-name,
body.dark-mode .topic-progress-header,
body.dark-mode .policy-index-title,
body.dark-mode .solo-zen-card__title,
body.dark-mode .solo-hero-card__title,
body.dark-mode .bento-cell h3,
body.dark-mode .card-solo h3,
body.dark-mode .card h3,
body.dark-mode .sc-fc-term,
body.dark-mode .sc-fc-def,
body.dark-mode .sd-resume-title,
/* Resource-shell renderer text - these all use `color: var(--solo-heading-color, var(--solo-navy))`
   for "title text" but live inside dark-mode-elevated cards so they
   become invisible. List is generated from grep of all .rs-* classes
   that hardcode --solo-navy as text colour. */
body.dark-mode .rs-title,
body.dark-mode .rs-kc-prompt,
body.dark-mode .rs-ev-q,
body.dark-mode .rs-ev-cmd,
body.dark-mode .rs-ep-q,
body.dark-mode .rs-ep-cmd,
body.dark-mode .rs-es-text,
body.dark-mode .rs-im-badge,
body.dark-mode .rs-hl-score,
body.dark-mode .rs-dr-cell,
body.dark-mode .rs-dr-clue,
body.dark-mode .rs-dr-die,
body.dark-mode .rs-dr-pick,
body.dark-mode .rs-dr-status,
body.dark-mode .rs-calc-q,
body.dark-mode .rs-calc-answer,
body.dark-mode .rs-c3calc-q-text,
body.dark-mode .rs-c3calc-input,
body.dark-mode .rs-c3calc-worked-q,
body.dark-mode .rs-c3calc-steps,
body.dark-mode .rn-step,
body.dark-mode .rn-subunit-title,
body.dark-mode .calc-inp,
body.dark-mode .calc-qtxt,
body.dark-mode .calc-wbody,
body.dark-mode .mes-step,
body.dark-mode .met-block,
body.dark-mode .oe-calc-display { color: var(--solo-heading-color, #E2E8F0); }
/* Body text inside the same containers should be the soft-slate dark-mode
   body colour (not the original near-navy slate that's now invisible). */
body.dark-mode .cbh-hero p,
body.dark-mode .cbh-hero .cbh-lede,
body.dark-mode .cbh-section-sub,
body.dark-mode .policy-index-desc,
body.dark-mode .price-desc,
body.dark-mode .sd-resume-state,
body.dark-mode .solo-zen-card__desc,
body.dark-mode .solo-hero-card__desc,
body.dark-mode .bento-cell p,
body.dark-mode .card-solo p,
body.dark-mode .card p { color: var(--solo-text, #CBD5E1); }
/* Form inputs need their light-mode #fff swap too so typed text is
   readable on the dark page. */
body.dark-mode .form-input,
body.dark-mode .form-select,
body.dark-mode .form-textarea,
body.dark-mode .edit-field {
  background: var(--solo-bg-elevated, #1E293B);
  border-color: var(--solo-divider, #334155);
  color: var(--solo-text, #E2E8F0);
}
/* Pricing card "featured" border-darker variant still wants its
   navy accent visible in dark mode - flip to mastery teal. */
body.dark-mode .price-card.featured { border-color: var(--solo-mastery); }

/* Light heroes on marketing/landing pages (.hero.solo-hero) use a heavy
   light-slate wash over a background image. In dark mode my legacy-token
   remap turned the headline + body text light - but the hero wash stayed
   light, so the text becomes invisible. Override the wash to dark in
   dark mode. Loses the background image (image paths are page-relative,
   not CSS-relative) but reads as an intentional dark hero. Tagline +
   eyebrow chips become teal-glow-on-dark, which is the platform's
   primary look anyway. */
body.dark-mode .hero.solo-hero,
body.dark-mode .resources-hero,
body.dark-mode .baseline-hero,
body.dark-mode .about-hero,
body.dark-mode .pricing-hero,
body.dark-mode .policy-hero {
  /* Stacked layers: top wash for legibility on the headline column,
     then the moody dark hero image, then the solid gradient fallback
     so the design stays intact even if the image hasn't been generated
     yet (drop the file at /images/dark-mode/homepage-hero.jpg). */
  background:
    linear-gradient(95deg, rgba(15, 23, 42, 0.75) 0%, rgba(15, 23, 42, 0.55) 40%, rgba(15, 23, 42, 0.15) 100%),
    url('../images/dark-mode/homepage-hero.jpg') center/cover no-repeat,
    linear-gradient(135deg, #0F172A 0%, #1E293B 100%) !important;
}
body.dark-mode .hero.solo-hero::before {
  background: radial-gradient(ellipse 800px 500px at 25% 20%, rgba(45, 212, 191, 0.22) 0%, transparent 70%) !important;
}
body.dark-mode .hero.solo-hero::after {
  background: radial-gradient(circle at 85% 85%, rgba(245, 158, 11, 0.10) 0%, transparent 50%) !important;
}
body.dark-mode .solo-hero-eyebrow {
  background: rgba(45, 212, 191, 0.12);
  border-color: rgba(45, 212, 191, 0.35);
  color: var(--solo-mastery);
}

/* Action hub panel that wraps "Try SoloCognition" + "Open SoloLab".
   In light mode it's a Deep Charcoal #1E293B panel against the light
   hero (the dark-panel-on-light contrast trick). In dark mode that
   --solo-navy var got flipped to light by the dark-mode remap, so the
   panel went pale grey on the now-dark hero - looks broken. Override
   to a subtle elevated dark + teal accent ring so it still reads as
   a focal CTA panel. */
body.dark-mode .solo-hero-action-hub {
  background: rgba(15, 23, 42, 0.65) !important;
  border: 1px solid rgba(45, 212, 191, 0.30) !important;
  box-shadow:
    0 0 0 1px rgba(45, 212, 191, 0.08),
    0 12px 36px rgba(0, 0, 0, 0.55),
    0 2px 6px rgba(0, 0, 0, 0.25) !important;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
body.dark-mode .solo-hero-action-hub .solo-hero-meta {
  color: rgba(248, 250, 252, 0.78);
}

/* Key-term + scientist popups - both hardcode background:white with no
   dark-mode treatment. In dark mode they appeared as bright white squares
   floating on a navy page. Flip to elevated dark surface + adjust the
   image-wrap, close button, and arrow accordingly. */
body.dark-mode .kt-def-popup,
body.dark-mode .sci-popup {
  background: var(--solo-bg-elevated, #1E293B) !important;
  border-color: var(--solo-mastery-deep, #14B8A6) !important;
  color: var(--solo-text, #CBD5E1) !important;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55), 0 4px 10px rgba(0, 0, 0, 0.35) !important;
}
body.dark-mode .kt-def-popup-arrow,
body.dark-mode .sci-popup-arrow {
  background: var(--solo-bg-elevated, #1E293B) !important;
  border-top-color: var(--solo-mastery-deep, #14B8A6) !important;
  border-left-color: var(--solo-mastery-deep, #14B8A6) !important;
}
body.dark-mode .kt-def-term,
body.dark-mode .sci-popup-name { color: var(--solo-heading-color, #E2E8F0) !important; }
body.dark-mode .kt-def-text,
body.dark-mode .sci-popup-body { color: var(--solo-text, #CBD5E1) !important; }
body.dark-mode .sci-popup-close {
  background: rgba(15, 23, 42, 0.85) !important;
  color: var(--solo-text, #CBD5E1) !important;
}
body.dark-mode .sci-popup-imgwrap {
  background: rgba(20, 184, 166, 0.10) !important;
  border-color: var(--solo-divider, #334155) !important;
}
body.dark-mode .sci-popup-img-placeholder { color: var(--solo-text-mute, #94A3B8) !important; }

/* Light-slate band sections (.solo-section-band, .philosophy-strip,
   .solo-pattern-dots) hardcode #F1F5F9 / #F8FAFC / similar pale slates
   in their inline page styles. Without an override they stay light in
   dark mode, with light-on-light text. Flip these to the elevated
   dark surface so they read as "deeper than the page floor". */
body.dark-mode .solo-section-band,
body.dark-mode .solo-section-band.section,
body.dark-mode .philosophy-strip,
body.dark-mode .philosophy-strip.solo-section-band,
body.dark-mode .solo-pattern-dots.section.solo-section-band {
  background: var(--solo-bg-elevated, #1E293B) !important;
}
body.dark-mode .solo-pattern-dots::before {
  background-image: radial-gradient(circle, rgba(45, 212, 191, 0.18) 1.2px, transparent 1.5px) !important;
}

/* Auto-dark (OS preference) gets the same treatment when neither
   manual class is set on the body. */
@media (prefers-color-scheme: dark) {
  body:not(.light-mode):not(.dark-mode) .hero.solo-hero,
  body:not(.light-mode):not(.dark-mode) .resources-hero,
  body:not(.light-mode):not(.dark-mode) .baseline-hero,
  body:not(.light-mode):not(.dark-mode) .about-hero,
  body:not(.light-mode):not(.dark-mode) .pricing-hero,
  body:not(.light-mode):not(.dark-mode) .policy-hero {
    background:
      linear-gradient(95deg, rgba(15, 23, 42, 0.75) 0%, rgba(15, 23, 42, 0.55) 40%, rgba(15, 23, 42, 0.15) 100%),
      url('../images/dark-mode/homepage-hero.jpg') center/cover no-repeat,
      linear-gradient(135deg, #0F172A 0%, #1E293B 100%) !important;
  }
  body:not(.light-mode):not(.dark-mode) .hero.solo-hero::before {
    background: radial-gradient(ellipse 800px 500px at 25% 20%, rgba(45, 212, 191, 0.22) 0%, transparent 70%) !important;
  }
  body:not(.light-mode):not(.dark-mode) .hero.solo-hero::after {
    background: radial-gradient(circle at 85% 85%, rgba(245, 158, 11, 0.10) 0%, transparent 50%) !important;
  }
  body:not(.light-mode):not(.dark-mode) .solo-hero-eyebrow {
    background: rgba(45, 212, 191, 0.12);
    border-color: rgba(45, 212, 191, 0.35);
    color: var(--solo-mastery);
  }
  body:not(.light-mode):not(.dark-mode) .solo-hero-action-hub {
    background: rgba(15, 23, 42, 0.65) !important;
    border: 1px solid rgba(45, 212, 191, 0.30) !important;
    box-shadow:
      0 0 0 1px rgba(45, 212, 191, 0.08),
      0 12px 36px rgba(0, 0, 0, 0.55),
      0 2px 6px rgba(0, 0, 0, 0.25) !important;
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
  }
  body:not(.light-mode):not(.dark-mode) .solo-hero-action-hub .solo-hero-meta {
    color: rgba(248, 250, 252, 0.78);
  }
  body:not(.light-mode):not(.dark-mode) .solo-section-band,
  body:not(.light-mode):not(.dark-mode) .solo-section-band.section,
  body:not(.light-mode):not(.dark-mode) .philosophy-strip,
  body:not(.light-mode):not(.dark-mode) .philosophy-strip.solo-section-band,
  body:not(.light-mode):not(.dark-mode) .solo-pattern-dots.section.solo-section-band {
    background: var(--solo-bg-elevated, #1E293B) !important;
  }
  body:not(.light-mode):not(.dark-mode) .solo-pattern-dots::before {
    background-image: radial-gradient(circle, rgba(45, 212, 191, 0.18) 1.2px, transparent 1.5px) !important;
  }
}

/* Continued: existing auto-dark pass-2 selectors (cards, forms, etc.) */
@media (prefers-color-scheme: dark) {
  body:not(.light-mode):not(.dark-mode) .cbh-hero,
  body:not(.light-mode):not(.dark-mode) .cbh-resume-hero,
  body:not(.light-mode):not(.dark-mode) .cbh-card,
  body:not(.light-mode):not(.dark-mode) .resource-pack,
  body:not(.light-mode):not(.dark-mode) .contact-form,
  body:not(.light-mode):not(.dark-mode) .contact-info-item,
  body:not(.light-mode):not(.dark-mode) .credential-item,
  body:not(.light-mode):not(.dark-mode) .process-step,
  body:not(.light-mode):not(.dark-mode) .price-card,
  body:not(.light-mode):not(.dark-mode) .progress-row,
  body:not(.light-mode):not(.dark-mode) .student-card,
  body:not(.light-mode):not(.dark-mode) .dash-stat,
  body:not(.light-mode):not(.dark-mode) .topic-progress-card,
  body:not(.light-mode):not(.dark-mode) .topic-col-body,
  body:not(.light-mode):not(.dark-mode) .account-card,
  body:not(.light-mode):not(.dark-mode) .auth-card,
  body:not(.light-mode):not(.dark-mode) .policy-index-card,
  body:not(.light-mode):not(.dark-mode) .sd-resume-card,
  body:not(.light-mode):not(.dark-mode) .sc-fc-component,
  body:not(.light-mode):not(.dark-mode) .solo-skel-card {
    background: var(--solo-bg-elevated, #1E293B);
    border-color: var(--solo-divider, #334155);
    color: var(--solo-text, #CBD5E1);
    box-shadow: 0 1px 2px rgba(0,0,0,0.5), 0 1px 1px rgba(0,0,0,0.35);
  }
  body:not(.light-mode):not(.dark-mode) .form-input,
  body:not(.light-mode):not(.dark-mode) .form-select,
  body:not(.light-mode):not(.dark-mode) .form-textarea,
  body:not(.light-mode):not(.dark-mode) .edit-field {
    background: var(--solo-bg-elevated, #1E293B);
    border-color: var(--solo-divider, #334155);
    color: var(--solo-text, #E2E8F0);
  }
  body:not(.light-mode):not(.dark-mode) .cbh-hero h1,
  body:not(.light-mode):not(.dark-mode) .cbh-resume-hero h1,
  body:not(.light-mode):not(.dark-mode) .cbh-card h3,
  body:not(.light-mode):not(.dark-mode) .cbh-card h2,
  body:not(.light-mode):not(.dark-mode) .cbh-section-title,
  body:not(.light-mode):not(.dark-mode) .price-name,
  body:not(.light-mode):not(.dark-mode) .progress-grade,
  body:not(.light-mode):not(.dark-mode) .progress-subject-name,
  body:not(.light-mode):not(.dark-mode) .dash-stat-num,
  body:not(.light-mode):not(.dark-mode) .student-name,
  body:not(.light-mode):not(.dark-mode) .topic-progress-header,
  body:not(.light-mode):not(.dark-mode) .policy-index-title,
  body:not(.light-mode):not(.dark-mode) .solo-zen-card__title,
  body:not(.light-mode):not(.dark-mode) .solo-hero-card__title,
  body:not(.light-mode):not(.dark-mode) .bento-cell h3,
  body:not(.light-mode):not(.dark-mode) .card-solo h3,
  body:not(.light-mode):not(.dark-mode) .card h3,
  body:not(.light-mode):not(.dark-mode) .sc-fc-term,
  body:not(.light-mode):not(.dark-mode) .sc-fc-def,
  body:not(.light-mode):not(.dark-mode) .sd-resume-title,
  body:not(.light-mode):not(.dark-mode) .rs-title,
  body:not(.light-mode):not(.dark-mode) .rs-kc-prompt,
  body:not(.light-mode):not(.dark-mode) .rs-ev-q,
  body:not(.light-mode):not(.dark-mode) .rs-ev-cmd,
  body:not(.light-mode):not(.dark-mode) .rs-ep-q,
  body:not(.light-mode):not(.dark-mode) .rs-ep-cmd,
  body:not(.light-mode):not(.dark-mode) .rs-es-text,
  body:not(.light-mode):not(.dark-mode) .rs-im-badge,
  body:not(.light-mode):not(.dark-mode) .rs-hl-score,
  body:not(.light-mode):not(.dark-mode) .rs-calc-q,
  body:not(.light-mode):not(.dark-mode) .rs-calc-answer,
  body:not(.light-mode):not(.dark-mode) .rs-c3calc-q-text,
  body:not(.light-mode):not(.dark-mode) .rs-c3calc-input,
  body:not(.light-mode):not(.dark-mode) .rn-step,
  body:not(.light-mode):not(.dark-mode) .rn-subunit-title,
  body:not(.light-mode):not(.dark-mode) .calc-qtxt,
  body:not(.light-mode):not(.dark-mode) .calc-wbody,
  body:not(.light-mode):not(.dark-mode) .mes-step { color: var(--solo-heading-color, #E2E8F0); }
  body:not(.light-mode):not(.dark-mode) .cbh-hero p,
  body:not(.light-mode):not(.dark-mode) .cbh-hero .cbh-lede,
  body:not(.light-mode):not(.dark-mode) .cbh-section-sub,
  body:not(.light-mode):not(.dark-mode) .policy-index-desc,
  body:not(.light-mode):not(.dark-mode) .price-desc,
  body:not(.light-mode):not(.dark-mode) .sd-resume-state,
  body:not(.light-mode):not(.dark-mode) .solo-zen-card__desc,
  body:not(.light-mode):not(.dark-mode) .solo-hero-card__desc,
  body:not(.light-mode):not(.dark-mode) .bento-cell p,
  body:not(.light-mode):not(.dark-mode) .card-solo p,
  body:not(.light-mode):not(.dark-mode) .card p { color: var(--solo-text, #CBD5E1); }
}


/* ─── 3 · THEME ROOT (opt-in) ─────────────────────────────── */
/* Apply class="theme-solo" to <body> to switch the page over.
   Without this class the file is a no-op for typography/background.

   The two contextual colour vars below - --solo-heading-color and
   --solo-body-color - let any nested component locally override the
   default heading/body colour without a specificity war. Components
   like .solo-banner and .card-glassmorphic redefine these on
   themselves; their <h1>/<p> children pick up the override via
   normal CSS variable inheritance. */
body.theme-solo {
  --solo-heading-color: var(--solo-navy);
  --solo-body-color:    var(--solo-text);
  background: var(--solo-bg);
  color: var(--solo-body-color);
  font-family: var(--solo-font-body);
  font-size: 16px;
  line-height: var(--solo-line-height);
  letter-spacing: var(--solo-letter-loose);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
/* Combined-class wins over body.theme-solo (0,0,2,1 > 0,0,1,1) so the
   dark-mode heading + body colour overrides STICK on pages that have
   both `theme-solo` AND `dark-mode` classes - otherwise theme-solo's
   --solo-heading-color rule (further down in source) cascades over
   body.dark-mode's setting. */
body.theme-solo.dark-mode {
  --solo-heading-color: #E2E8F0;
  --solo-mastery-pale:  rgba(45, 212, 191, 0.14);
  --solo-body-color:    var(--solo-text);
  /* Resource pages have an inline `body.theme-solo { --off-white: #F8FAFC; ... }`
     block that re-points the legacy tokens to LIGHT values and loads after
     this file - tying the plain body.dark-mode remap on specificity and
     winning on source order. This higher-specificity selector (0,1,2) beats
     it, so the shell + cards + text actually flip. --navy stays dark (it's a
     surface colour, used for dark panels). */
  --off-white:  #0F172A;
  --white:      #1E293B;
  --text-mid:   #CBD5E1;
  --text-light: #94A3B8;
  --border:     #334155;
  --teal-pale:  rgba(45, 212, 191, 0.14);
  --bio-pale:   rgba(45, 212, 191, 0.14);
  --sand-pale:  rgba(245, 158, 11, 0.12);
}
@media (prefers-color-scheme: dark) {
  body.theme-solo:not(.light-mode):not(.dark-mode) {
    --solo-heading-color: #E2E8F0;
    --solo-mastery-pale:  rgba(45, 212, 191, 0.14);
    --solo-body-color:    var(--solo-text);
    --off-white:  #0F172A;
    --white:      #1E293B;
    --text-mid:   #CBD5E1;
    --text-light: #94A3B8;
    --border:     #334155;
    --teal-pale:  rgba(45, 212, 191, 0.14);
    --bio-pale:   rgba(45, 212, 191, 0.14);
    --sand-pale:  rgba(245, 158, 11, 0.12);
  }
}

body.theme-solo h1,
body.theme-solo h2,
body.theme-solo h3,
body.theme-solo h4,
body.theme-solo .h-solo {
  font-family: var(--solo-font-head);
  color: var(--solo-heading-color);   /* var indirection - override per-component */
  font-weight: 600;
  letter-spacing: var(--solo-letter-tight);
  line-height: 1.25;
}

body.theme-solo h1 { font-size: clamp(1.9rem, 3.2vw, 2.6rem); margin-bottom: 0.6rem; }
body.theme-solo h2 { font-size: clamp(1.4rem, 2.2vw, 1.7rem); margin: 1.5rem 0 0.6rem; }
body.theme-solo h3 { font-size: 1.1rem; margin: 1.1rem 0 0.4rem; }

/* Unit-header titles live on a dark navy gradient hero. They need to
   invert from --solo-heading-color (navy) to a soft off-white that
   reads cleanly without glare, plus a touch of letter-spacing and a
   subtle drop-shadow for "atmospheric HUD" depth against the gradient.
   Applies to every unit's hero universally - cell biology, organisation,
   and any future unit that uses the standard .rs-unit-header markup.

   Contrast: #E2E8F0 on #0F172A ≈ 14.8:1 → WCAG AAA for normal text. */
body.theme-solo .rs-unit-header .rs-unit-title,
body.theme-solo h1.rs-unit-title {
  color: #E2E8F0;
  letter-spacing: 0.02em;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
body.theme-solo .rs-unit-header .rs-unit-sub {
  color: rgba(255, 255, 255, 0.82);
}

body.theme-solo a {
  color: var(--solo-mastery-deep);
  text-decoration-color: rgba(20, 184, 166, 0.4);
  text-underline-offset: 3px;
  transition: text-decoration-color var(--solo-fast) var(--solo-ease);
}
body.theme-solo a:hover { text-decoration-color: var(--solo-mastery-deep); }

body.theme-solo ::selection {
  /* Saturated mastery + white text so highlights are readable on BOTH
     the off-white page bg and the dark hero strips (heroes, CTAs, deck).
     Previous pale-lavender bg + slate text disappeared against dark
     navy heroes. */
  background: var(--solo-mastery-deep);
  color: #FFFFFF;
}
body.theme-solo ::-moz-selection {
  background: var(--solo-mastery-deep);
  color: #FFFFFF;
}

body.theme-solo *:focus-visible {
  outline: 2px solid var(--solo-mastery);
  outline-offset: 3px;
  /* Outer dark halo for 3:1 non-text contrast against the off-white
     page bg (--solo-bg #F8FAFC). Teal alone is ~1.5:1 and fails
     WCAG 2.2 SC 1.4.11. */
  box-shadow: 0 0 0 5px rgba(15, 23, 42, .55);
  border-radius: 4px;
}

/* Quick Mode (Round 2 persona-audit action): a one-tap "shut everything
   that's not the core content" toggle. Mia + Imani both wanted this.
   Quiet layer suppressions live here so any page that picks up the
   body class gets the behaviour with no per-page wiring. */
body.solo-quick-mode .kt,
body.solo-quick-mode strong.kt,
body.solo-quick-mode .vocab-term,
body.solo-quick-mode [data-vocab],
body.solo-quick-mode .sci-link {
  /* Strip the dotted underlines + cursor-help signals. The underlying
     popover JS still runs on click for students who actively want a
     definition, so no behaviour is lost. */
  border-bottom: 0 !important;
  cursor: inherit !important;
}
body.solo-quick-mode .sci-link::before { content: '' !important; margin: 0 !important; }
body.solo-quick-mode [data-cogs-tip],
body.solo-quick-mode .cogs-tip { display: none !important; }
body.solo-quick-mode .rp-skill-chip {
  background: var(--solo-bg, #F8FAFC) !important;
  border-color: var(--solo-divider, #E2E8F0) !important;
  color: var(--solo-text-mute, #64748B) !important;
}
body.solo-quick-mode .rp-skill-chip-code {
  background: transparent !important;
  color: inherit !important;
}
/* Dark mode: invert the halo to a translucent light surround so the
   focus ring stays visible against the dark page background. */
body.dark-mode *:focus-visible,
body.theme-solo.dark-mode *:focus-visible {
  box-shadow: 0 0 0 5px rgba(248, 250, 252, .35);
}

/* Eyebrow / micro-label / "section-label" elements - these are non-h-tags
   used as ALL-CAPS data labels (e.g. "WHY IT WORKS", "THE PLATFORM"). They
   should render in Lexend per the brand spec ("headings/data tables in
   Lexend"), even though they aren't actual <h*> elements. Catches anything
   tagged as .eyebrow, .section-label, or .h-solo. */
body.theme-solo .section-label,
body.theme-solo .eyebrow,
body.theme-solo .eyebrow-solo {
  font-family: var(--solo-font-head);
  font-weight: 600;
  letter-spacing: 0.1em;
}

/* ─── 3b · GLOBAL NAV CONSISTENCY (Sleek 2027) ─────────────
   Overrides legacy .nav-links / .nav-cta / .nav-signin colours so the top
   nav reads as one coherent system on every Solo'd page. Specificity 0,0,2,1
   beats the legacy single-class rules in styles.css.

   Hierarchy:
     · Standard text links → Soft Charcoal (Lexend medium)
     · Hover / active → Mastery Teal
     · Sign-in / Sign-out / dashboard CTA → unified bordered or filled buttons */
body.theme-solo .nav-links a {
  font-family: var(--solo-font-head);
  font-weight: 500;
  color: var(--solo-text);                              /* Soft Charcoal #334155 */
  transition: color var(--solo-fast) var(--solo-ease);
}
body.theme-solo .nav-links a:hover {
  color: #2DD4BF;                                       /* Bright Electric Teal */
}
body.theme-solo .nav-links a.active {
  color: #2DD4BF;                                       /* Bright Electric Teal */
  font-weight: 600;
}

/* Sign-in + Sign-out - bordered ghost buttons in the nav, same look so they
   read as a paired control. */
body.theme-solo .nav-links a.nav-signin,
body.theme-solo .nav-links a.nav-signout-btn {
  background: transparent !important;
  border: 1.5px solid var(--solo-divider) !important;
  color: var(--solo-text) !important;
  font-weight: 600;
  border-radius: 999px;
}
body.theme-solo .nav-links a.nav-signin:hover,
body.theme-solo .nav-links a.nav-signout-btn:hover {
  border-color: var(--solo-mastery) !important;
  color: var(--solo-mastery-deep) !important;
  background: rgba(45, 212, 191, 0.06) !important;
}

/* "SoloSight" CTA (the dynamic dashboard link injected by auth.js) - primary
   button. Solid Solo-navy with Light Slate text so it punches as the active
   logged-in indicator. */
body.theme-solo .nav-links a.nav-cta {
  background: var(--solo-navy) !important;
  color: #F8FAFC !important;
  font-weight: 600;
  border-radius: var(--solo-radius-sm);
}
body.theme-solo .nav-links a.nav-cta:hover {
  background: var(--solo-misconception-deep) !important;
  color: #FFFFFF !important;
}

/* Admin-only nav items (e.g. the SoloSight link on public pages).
   Hidden by default; revealed when auth.js adds .auth-role-admin or
   .auth-role-owner to the body. Legacy tutor accounts also receive
   .auth-role-admin so they're covered too. */
nav .nav-links li[data-staff-role="admin"] { display: none; }
body.auth-role-admin nav .nav-links li[data-staff-role="admin"],
body.auth-role-owner nav .nav-links li[data-staff-role="admin"] {
  display: list-item;
}
/* Any signed-in role (student, parent, teacher) ALSO sees the SoloSight
   nav link - js/auth.js rewrites its href so each role lands on their
   own dashboard (student-dashboard / parent-dashboard / dashboard). */
body.auth-role-student nav .nav-links li[data-staff-role="admin"],
body.auth-role-parent  nav .nav-links li[data-staff-role="admin"],
body.auth-role-teacher nav .nav-links li[data-staff-role="admin"] {
  display: list-item;
}
/* Pricing nav is now visible to all users, including signed-in ones
   (rule reversed 2026-06-04 - users may want to compare plans, switch
   tier, or refer a family member to pricing). The legacy hide rule
   used to live here. */

/* Parents are not the learner - they oversee. Hide the learning
   surfaces from the parent nav so the only path is to their own
   Parent SoloSight. Practicals stays on the public marketing nav
   for everyone else. */
body.auth-role-parent nav .nav-links li:has(#nav-sololab),
body.auth-role-parent nav .nav-links li:has(#nav-solocognition),
body.auth-role-parent nav .nav-links li:has(#nav-practicals),
body.auth-role-parent nav .nav-links li:has(#nav-home),
body.auth-role-parent nav .nav-links li:has(#nav-about) { display: none; }
/* Audit AMBER 26: :has() fallback for Safari < 15.4 + iOS 15.3
   (legacy school iPads). auth.js applyAuthBodyClasses() also tags
   the relevant nav items with .parent-nav-hide so the rule above
   (modern path) and the rule below (legacy path) reach the same
   end state. */
body.auth-role-parent nav .nav-links li.parent-nav-hide { display: none; }

/* Two-state visibility: any element tagged data-auth-state="logged-out"
   or "logged-in" is hidden until js/auth.js puts the matching body class
   on the page. Hidden-by-default means a brief blank during auth resolve
   rather than a flash of the wrong state. Works on any element type. */
[data-auth-state="logged-out"],
[data-auth-state="logged-in"] { display: none; }
body.auth-logged-out [data-auth-state="logged-out"],
body.auth-logged-in  [data-auth-state="logged-in"]  { display: revert; }

/* ════════════════════════════════════════════════════════════
   Closed-beta gate placeholder
   ────────────────────────────────────────────────────────────
   Pages add `is-checking-access` to <body> so the page stays
   hidden until the inline ADMIN_EMAILS gate has resolved. Old
   pattern used visibility:hidden on body, which gave ND/SEND
   users a totally blank white page that read as "broken /
   frozen". New pattern: hide every direct child instead, and
   paint a friendly "Checking access…" placeholder via ::before
   so the user knows the page is actively doing something. The
   placeholder fades after 250ms so it never flashes for fast
   admin loads. If the gate fires within the budget, the page
   reveals cleanly; if the auth.js safety timer expires the body
   gets `gate-error` and shows a recovery message instead of
   silently revealing protected content.
   ════════════════════════════════════════════════════════════ */
body.is-checking-access > * { visibility: hidden; }
body.is-checking-access::before {
  content: 'Checking access…';
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  visibility: visible;
  background: var(--solo-bg, #F8FAFC);
  color: var(--solo-text-mute, #64748B);
  font-family: 'Lexend', sans-serif;
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.04em;
  z-index: 99999;
  animation: solo-gate-fadein 0.25s ease-out 0.2s both;
}
body.is-checking-access::after {
  content: '';
  position: fixed;
  top: calc(50% - 36px); left: calc(50% - 14px);
  width: 28px; height: 28px;
  border: 3px solid rgba(45, 212, 191, 0.25);
  border-top-color: var(--solo-mastery, #2DD4BF);
  border-radius: 50%;
  visibility: visible;
  z-index: 99999;
  animation: solo-gate-spin 0.85s linear infinite, solo-gate-fadein 0.25s ease-out 0.2s both;
}
@keyframes solo-gate-spin   { to { transform: rotate(360deg); } }
@keyframes solo-gate-fadein { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  body.is-checking-access::after { animation: solo-gate-fadein 0.25s ease-out 0.2s both; }
}
/* Recovery state: safety timer fires before the gate resolves. */
body.gate-error::before {
  content: 'We could not verify your access. Try refreshing, or sign in again.';
  white-space: pre-wrap;
  max-width: 360px;
  text-align: center;
  padding: 0 1.5rem;
  color: var(--solo-text, #334155);
  animation: none;
}
body.gate-error::after {
  content: '';
  border-color: rgba(220, 38, 38, 0.25);
  border-top-color: #DC2626;
  animation: none;
}

/* ════════════════════════════════════════════════════════════════
   BREADCRUMB  ·  "You are here" strip
   ────────────────────────────────────────────────────────────────
   Compact Subject › Unit › Sub-unit strip rendered above each
   resource page's unit header. The Sub-unit cell is updated by JS
   when the student navigates between sub-units (the resource pages
   call SoloBreadcrumb.setSection(name)).
   ════════════════════════════════════════════════════════════════ */
.solo-breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  flex-wrap: wrap;
  font-family: var(--solo-font-head);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--solo-text-mute);
  text-transform: uppercase;
  margin: 0.75rem 0 0.45rem;
  padding: 0;
}
.solo-breadcrumb a {
  color: var(--solo-mastery-deep, #0F766E);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 0.15s ease;
}
.solo-breadcrumb a:hover,
.solo-breadcrumb a:focus-visible {
  border-bottom-color: var(--solo-mastery-deep, #0F766E);
}
.solo-breadcrumb .sep {
  color: var(--solo-text-mute);
  opacity: 0.7;
}
.solo-breadcrumb .current {
  color: var(--solo-heading-color, var(--solo-navy, #0F172A));
  max-width: 280px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Subject-tinted accent palette. Default mastery* vars are teal (cell-
   biology / generic). Pages tag <body data-subject="chemistry|physics">
   to swap the WHOLE palette to amber / indigo. This is the same pattern
   the chemistry hubs use locally (the .unit-chemistry-c* var override) —
   centralised here so every chemistry / physics page picks it up just
   by setting the body attribute. */
body[data-subject="chemistry"] {
  --solo-mastery:      #F59E0B;
  --solo-mastery-deep: #B45309;
  --solo-mastery-pale: #FEF3C7;
  --solo-mastery-glow: rgba(245, 158, 11, 0.25);
}
body[data-subject="physics"] {
  --solo-mastery:      #6366F1;
  --solo-mastery-deep: #1E40AF;
  --solo-mastery-pale: #DBEAFE;
  --solo-mastery-glow: rgba(99, 102, 241, 0.25);
}

/* Top-bar breadcrumb link colour needs explicit override because the
   default rule above hardcodes color: var(--solo-mastery-deep, #0F766E)
   with a fallback that wins if the var is unset. The var IS set on
   chemistry / physics bodies, so the var resolves correctly — but we
   also restate it here for hover border-bottom-color which is computed
   separately. */
body[data-subject="chemistry"] .solo-breadcrumb a:hover,
body[data-subject="chemistry"] .solo-breadcrumb a:focus-visible {
  border-bottom-color: #B45309;
}
body[data-subject="physics"] .solo-breadcrumb a:hover,
body[data-subject="physics"] .solo-breadcrumb a:focus-visible {
  border-bottom-color: #1E40AF;
}

/* Brand & top-nav are subject-AGNOSTIC: the SoloCogs gear, "Cogs" wordmark,
   and the active nav link always read as the platform's teal regardless
   of which subject the page is themed for. Without these overrides the
   data-subject palette swap above repaints the brand chrome too. */
body[data-subject] .solo-brand-css-gear { fill: #2DD4BF; }
body[data-subject] .solo-brand-css .solo-brand-css-cogs { color: #2DD4BF; }
body[data-subject].theme-solo .nav-links a:hover,
body[data-subject].theme-solo .nav-links a.active {
  color: #2DD4BF;                                       /* Bright Electric Teal */
}
body[data-subject].theme-solo .nav-links a.nav-signin:hover,
body[data-subject].theme-solo .nav-links a.nav-signout-btn:hover {
  border-color: #2DD4BF !important;
  color: #2DD4BF !important;
  background: rgba(45, 212, 191, 0.06) !important;
}

/* ════════════════════════════════════════════════════════════════
   PRINT STYLES  ·  Revision-friendly output
   ────────────────────────────────────────────────────────────────
   Strip the platform chrome (nav, control deck, ribbons, tours,
   footers) so any resource / SoloCog / lab page prints as a clean
   black-on-white revision sheet. The student-visible CONTENT
   (paragraphs, tables, figures, key boxes) stays visible.
   ════════════════════════════════════════════════════════════════ */
@media print {
  /* Reset background to white to save ink and lift contrast. */
  html, body { background: #fff !important; /* darkmode-ok */ color: #000 !important; }
  body { font-size: 11pt; line-height: 1.45; }

  /* Hide all interactive / decorative chrome. */
  nav, .solo-footer, .solo-deck, .solo-deck__pip,
  .solo-cogs-pin, .solo-cogs-bubble, #solo-tour, .solo-tour-overlay,
  .solo-hero-card__ribbon, .solo-hero-card__cta,
  .colour-picker-bar, .results-bg-picker,
  .nav-burger, .ab-btn, .sc-fab, .solo-control-deck,
  #progress-tracker-wrap, .quiz-header .colour-picker-bar,
  .plain-toggle, .plain-mode-active-banner,
  .auth-welcome-strip, .sololab-baseline-callout,
  .hol-gate-overlay, .arc-gate-overlay,
  audio, video, button:not([data-print="keep"]),
  [data-print="hide"] {
    display: none !important;
  }

  /* Layout reset: stack everything, no fixed positioning. */
  *, *::before, *::after {
    position: static !important;
    box-shadow: none !important;
    text-shadow: none !important;
    background-attachment: scroll !important;
  }

  /* Headings: don't strand a heading at the bottom of a page. */
  h1, h2, h3, h4 { page-break-after: avoid; break-after: avoid; color: #000; }
  h1 { font-size: 18pt; }
  h2 { font-size: 15pt; }
  h3 { font-size: 13pt; }

  /* Keep figures + tables together; allow wrapping if too tall. */
  figure, table, .cb-fig, .hl-box {
    page-break-inside: avoid;
    break-inside: avoid;
  }

  /* Images: keep at original size up to page width. */
  img {
    max-width: 100% !important;
    height: auto !important;
    display: block;
    margin: 0.6em auto;
  }

  /* Tables: visible borders, readable text. */
  table, .cb-tbl {
    border-collapse: collapse;
    width: 100%;
    margin: 0.6em 0;
  }
  table th, table td, .cb-tbl th, .cb-tbl td {
    border: 1px solid #555 !important;
    padding: 4px 6px !important;
    color: #000 !important;
  }
  thead { display: table-header-group; }

  /* Key boxes: keep the visual hierarchy but with print-friendly tint. */
  .hl-box {
    border: 1px solid #888 !important;
    background: #f4f4f4 !important;
    padding: 6px 10px !important;
    margin: 0.5em 0 !important;
    color: #000 !important;
  }

  /* Key-term highlights: render as bold-italic instead of coloured. */
  .kt {
    background: transparent !important;
    color: #000 !important;
    font-weight: 700;
    font-style: italic;
  }

  /* Links: show the URL in print so paper readers can follow them.
     Skip internal hash-only links since printing "#mid-section" is noise. */
  a[href]:not([href^="#"]):not([href^="javascript:"])::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    color: #555;
  }

  /* Page margins (A4 friendly). */
  @page { margin: 18mm 14mm; }

  /* Sub-unit / activity sections: start each on a fresh page when
     a printable break marker is set. Pages that want this can add
     class="print-page-break" to the next section header. */
  .print-page-break { page-break-before: always; break-before: always; }
}


/* ─── 3c · LOCKED-BRIEF TEAL CTAs (Contrast Pass 2026-04-26) ───
   The Zen Lab brief mandates navy/charcoal text on mastery-teal buttons
   (9.3:1 AAA). White-on-teal is BANNED on this brand.

   Pattern: navy text on teal at rest. On hover, invert to white-on-deep-teal
   so the button still feels "active" without sacrificing legibility.

   Usage: tag any primary CTA button or anchor with `.solo-cta-primary`.
   The listed legacy class names (.contact-submit, .pr-card-cta, .wl-submit,
   .pr-b2b-cta) are auto-fixed by these rules so existing pages don't need
   to be re-tagged. Going forward, prefer `.solo-cta-primary`.

   Specificity note: prefixed with `body.theme-solo` so we beat inline
   <style> blocks on individual pages, which load after theme.css. The
   `!important` on color is required for anchor-element CTAs because
   legacy styles.css carries a broad `a { color }` rule. */
body.theme-solo .solo-cta-primary,
body.theme-solo .contact-submit,
body.theme-solo .pr-card-cta,
body.theme-solo .wl-submit,
body.theme-solo .pr-b2b-cta,
body.theme-solo .btn-solo-teal,
body.theme-solo a.btn-solo-teal,
body.theme-solo a.btn-solo-teal:visited {
  background: var(--solo-mastery) !important;
  color: var(--solo-heading-color, var(--solo-navy)) !important;
  border: 1px solid transparent;
  font-family: var(--solo-font-head);
  font-weight: 700;
  letter-spacing: 0.01em;
  cursor: pointer;
  text-decoration: none;
  text-shadow: none !important;
  transition: background var(--solo-fast) var(--solo-ease),
              color var(--solo-fast) var(--solo-ease),
              box-shadow var(--solo-fast) var(--solo-ease),
              transform var(--solo-fast) var(--solo-ease);
}
body.theme-solo .solo-cta-primary:hover:not(:disabled),
body.theme-solo .contact-submit:hover:not(:disabled),
body.theme-solo .pr-card-cta:hover:not(:disabled),
body.theme-solo .wl-submit:hover:not(:disabled),
body.theme-solo .pr-b2b-cta:hover,
body.theme-solo .btn-solo-teal:hover:not(:disabled),
body.theme-solo a.btn-solo-teal:hover {
  background: var(--solo-mastery-deep) !important;
  color: #FFFFFF !important;
  box-shadow: 0 0 0 4px rgba(45, 212, 191, 0.28), var(--solo-shadow-2);
  transform: translateY(-1px);
}

/* Exception: inside the homepage navy "action hub" panel, the .btn-solo-teal
   sits on a dark navy background where navy text would vanish. Force white
   text inside that container only. The selector specificity (0,0,3,0) beats
   the universal rule above. */
body.theme-solo .solo-hero-action-hub .btn-solo-teal,
body.theme-solo .solo-hero-action-hub a.btn-solo-teal {
  color: #FFFFFF !important;
  text-shadow: 0 1px 2px rgba(15, 23, 42, 0.25);
}
body.theme-solo .solo-hero-action-hub .btn-solo-teal:hover:not(:disabled),
body.theme-solo .solo-hero-action-hub a.btn-solo-teal:hover {
  color: #FFFFFF !important;
}

/* Exception: pricing-card secondary Annual CTA sits beneath the primary
   Monthly one. Ghost / outlined style so visual hierarchy stays clean
   (primary = Monthly trial, secondary = Annual save-2-months). Specificity
   (0,0,2,0) beats the universal .pr-card-cta rule above. */
body.theme-solo .pr-card-cta.pr-card-cta-secondary {
  background: transparent !important;
  color: var(--solo-mastery-deep) !important;
  border: 1.5px solid var(--solo-mastery);
}
body.theme-solo .pr-card-cta.pr-card-cta-secondary:hover:not(:disabled) {
  background: rgba(45, 212, 191, 0.08) !important;
  color: var(--solo-mastery-deep) !important;
  border-color: var(--solo-mastery-deep);
  box-shadow: 0 0 0 3px rgba(45, 212, 191, 0.18);
}


/* ─── 3d · COOKIE CONSENT BANNER ────────────────────────────
   Mounted by js/solo-cookie-consent.js on first visit. Bottom-anchored
   floating bar with reject + accept buttons. Loads on every page so it
   fires once, regardless of which surface the user lands on. */
#solo-cookie-banner {
  position: fixed;
  left: 1rem; right: 1rem; bottom: 1rem;
  z-index: 9500;
  background: var(--solo-bg-elevated, #FFFFFF);
  border: 1px solid var(--solo-divider, #E2E8F0);
  border-radius: var(--solo-radius, 14px);
  box-shadow: 0 18px 40px rgba(15, 23, 42, 0.18),
              0 4px 10px rgba(15, 23, 42, 0.08);
  padding: 1.1rem 1.25rem;
  max-width: 780px;
  margin: 0 auto;
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.25s ease, transform 0.25s ease;
}
#solo-cookie-banner.open { opacity: 1; transform: translateY(0); }

.solo-cc-inner {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 1.25rem;
  align-items: center;
}
@media (max-width: 640px) {
  .solo-cc-inner { grid-template-columns: 1fr; gap: 0.85rem; }
}

.solo-cc-text {
  font-family: var(--solo-font-body, 'Atkinson Hyperlegible', sans-serif);
  font-size: 0.85rem;
  color: var(--solo-text, #334155);
  line-height: 1.55;
}
.solo-cc-text strong {
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--solo-heading-color, var(--solo-navy, #1B3A6B));
  display: block;
  margin-bottom: 0.25rem;
}
.solo-cc-text p { margin: 0; }
.solo-cc-text a {
  color: var(--solo-mastery-deep, #0F766E);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.solo-cc-actions {
  display: flex;
  gap: 0.55rem;
  flex-shrink: 0;
}
@media (max-width: 640px) {
  .solo-cc-actions { width: 100%; }
  .solo-cc-actions .solo-cc-btn { flex: 1; }
}

.solo-cc-btn {
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-weight: 700;
  font-size: 0.85rem;
  padding: 0.65rem 1.2rem;
  border-radius: 999px;
  border: 1.5px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s ease, color 0.15s ease,
              border-color 0.15s ease, box-shadow 0.15s ease,
              transform 0.15s ease;
}
.solo-cc-btn-reject {
  background: transparent;
  color: var(--solo-text, #334155);
  border-color: var(--solo-divider, #E2E8F0);
}
.solo-cc-btn-reject:hover {
  background: var(--solo-bg, #F1F5F9);
  border-color: var(--solo-text-mute, #64748B);
}
/* Accept button uses the locked-brief teal CTA pattern (navy on teal). */
.solo-cc-btn-accept {
  background: var(--solo-mastery, #2DD4BF);
  color: var(--solo-heading-color, var(--solo-navy, #1B3A6B));
}
.solo-cc-btn-accept:hover {
  background: var(--solo-mastery-deep, #0F766E);
  color: #FFFFFF;
  box-shadow: 0 0 0 4px rgba(45, 212, 191, 0.28);
  transform: translateY(-1px);
}


/* ─── 4 · TYPE UTILITY CLASSES ────────────────────────────── */
/* These work even on pages that haven't opted into theme-solo,
   so you can dab the Solo style onto a single component first. */
.h-solo {
  font-family: var(--solo-font-head);
  color: var(--solo-heading-color, var(--solo-navy));
  font-weight: 600;
  letter-spacing: var(--solo-letter-tight);
  line-height: 1.25;
}
.body-solo {
  font-family: var(--solo-font-body);
  line-height: var(--solo-line-height);
  color: var(--solo-text);
}
.eyebrow-solo {
  font-family: var(--solo-font-head);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--solo-text-soft);
}

.text-mastery       { color: var(--solo-mastery-deep); }
.text-confidence    { color: var(--solo-confidence-deep); }
.text-misconception { color: var(--solo-misconception-deep); }
.text-mute          { color: var(--solo-text-mute); }
.text-soft          { color: var(--solo-text-soft); }
.text-navy          { color: var(--solo-heading-color, var(--solo-navy)); }


/* ─── 5 · SURFACES & CARDS ────────────────────────────────── */
.bg-solo               { background: var(--solo-bg); }
.bg-solo-elevated      { background: var(--solo-bg-elevated); }
.bg-mastery-pale       { background: var(--solo-mastery-pale); }
.bg-confidence-pale    { background: var(--solo-confidence-pale); }
.bg-misconception-pale { background: var(--solo-misconception-pale); }

.card-solo {
  background: var(--solo-bg-elevated);
  border: 1px solid var(--solo-divider);
  border-radius: var(--solo-radius);
  padding: 1.25rem 1.5rem;
  box-shadow: var(--solo-shadow-1);
}
.card-solo--lift       { box-shadow: var(--solo-shadow-2); }
.card-solo--hover      {
  transition: box-shadow var(--solo-fast) var(--solo-ease),
              transform  var(--solo-fast) var(--solo-ease),
              border-color var(--solo-fast) var(--solo-ease);
}
.card-solo--hover:hover {
  box-shadow: var(--solo-shadow-3);
  transform: translateY(-2px);
  border-color: var(--solo-mastery);
}

/* Glassmorphic - for lab interfaces (beakers, slides, microscope viewfinder) */
.card-glassmorphic {
  background: rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(10px) saturate(140%);
  -webkit-backdrop-filter: blur(10px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, 0.7);
  border-radius: var(--solo-radius);
  box-shadow: var(--solo-shadow-2), inset 0 1px 0 rgba(255, 255, 255, 0.6);
  padding: 1.25rem 1.5rem;
}

/* Sleek 2027 banner - the canonical "page hero" / "welcome strip" surface.
   Subtle navy → deep-slate gradient, Light Teal-White type baked in via the
   contextual --solo-heading-color / --solo-body-color overrides. Drop on any
   container: <section class="solo-banner">. Layout (flex, padding, etc.) is
   left to the consuming component so the banner adapts to its setting.
   Defaults below cover the common case. */
.solo-banner {
  --solo-heading-color: #F0FDFA;                   /* Light Teal-White */
  --solo-body-color:    rgba(240, 253, 250, 0.85);
  background: linear-gradient(135deg, var(--solo-navy) 0%, var(--solo-misconception-deep) 100%);
  color: var(--solo-body-color);
  border-radius: var(--solo-radius-lg);
  padding: 1.75rem 2rem;
  box-shadow: var(--solo-shadow-2);
  position: relative;
}
.solo-banner h1, .solo-banner h2, .solo-banner h3 { color: var(--solo-heading-color); }
/* Slightly muted variants for secondary metadata inside the banner */
.solo-banner .body-mute  { color: rgba(240, 253, 250, 0.75); }
.solo-banner .body-soft  { color: rgba(240, 253, 250, 0.6); }
/* Optional gradient flavours - apply alongside .solo-banner */
.solo-banner--mastery {
  background: linear-gradient(135deg, var(--solo-mastery-deep) 0%, var(--solo-mastery) 100%);
}
.solo-banner--mastery h1, .solo-banner--mastery h2, .solo-banner--mastery h3 { color: #1E293B; }
.solo-banner--confidence {
  background: linear-gradient(135deg, #B45309 0%, var(--solo-confidence) 100%);
}
.solo-banner--confidence h1, .solo-banner--confidence h2, .solo-banner--confidence h3 { color: #3A2A06; }

/* Soft brand glow - for focal elements like avatars, primary CTAs, "current"
   indicators. Two-layer halo: tight inner ring + diffuse outer shadow.
   Apply to any rounded element. */
.solo-glow-mastery {
  box-shadow: 0 0 0 4px rgba(45, 212, 191, 0.18),
              0 8px 24px rgba(45, 212, 191, 0.45);
}
.solo-glow-confidence {
  box-shadow: 0 0 0 4px rgba(245, 158, 11, 0.18),
              0 8px 24px rgba(245, 158, 11, 0.45);
}

/* Canonical SoloCogs brand lockup - global standard for nav bars + headers.
   Replaces the legacy <svg> + .nav-name pattern with a single image asset
   that's pixel-aligned across the whole site.

   USAGE (light surfaces - most pages):
     <a href="index.html" class="solo-brand">
       <img src="images/solocogs-logo.svg" alt="SoloCogs">
     </a>

   USAGE (dark surfaces - tutor dashboard sidebar):
     same markup but use the dark-variant asset (e.g. solocogs-logo-light.png)
     OR add the .solo-brand--on-dark modifier to apply a soft white glow.

   Sizing: 40px default, 32px compact, 56px large. Padding lets the lockup
   breathe against any nav background. */
.solo-brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  padding: 0.4rem 0.6rem;
  border-radius: var(--solo-radius-sm);
  transition: opacity var(--solo-fast) var(--solo-ease),
              background var(--solo-fast) var(--solo-ease);
}
.solo-brand img {
  display: block;
  height: 32px;          /* canonical nav-bar logo height - locked to spec */
  width: auto;
  max-width: 100%;
}
.solo-brand:hover { opacity: 0.85; }
.solo-brand:focus-visible {
  outline: 2px solid var(--solo-mastery);
  outline-offset: 2px;
}
.solo-brand--compact img { height: 32px; }
.solo-brand--large   img { height: 56px; }

/* Optional: softens the lockup slightly on a dark backdrop without needing
   a separate light-mode asset. Use only if you don't have a dark-variant png. */
.solo-brand--on-dark img {
  filter: drop-shadow(0 0 6px rgba(255, 255, 255, 0.45));
}

/* Temporary CSS-only "reverse logo" for dark surfaces (e.g. tutor sidebar)
   while the design partner produces a true light-variant raster asset.
   Renders as: [Mastery-teal gear SVG]  Solo / Cogs (stacked wordmark).
   Swap to a real light-mode <img> tag once the asset is ready - same
   ".solo-brand" wrapper class will work, the inner content just changes. */
.solo-brand-css {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  text-decoration: none;
  padding: 0.2rem 0;
  transition: opacity var(--solo-fast) var(--solo-ease);
}
a.solo-brand-css:hover { opacity: 0.85; }
a.solo-brand-css:focus-visible {
  outline: 2px solid var(--solo-mastery);
  outline-offset: 4px;
  border-radius: var(--solo-radius-sm);
}
.solo-brand-css-gear {
  flex-shrink: 0;
  width: 32px;                          /* default - overridden per context (sidebar, footer) */
  height: 32px;
  fill: var(--solo-mastery);            /* Electric Teal - locked across both variants */
  display: block;
}

/* Wordmark layout - gear-aligned stacked "Solo / Cogs" lockup. The inner span
   classes carry weight + colour individually so each glyph hits the brand
   exactly: Solo = Bold, Cogs = Regular, in both variants.
   Specificity bump via .solo-brand-css ancestor (0,0,2,0) wins over any
   host-page "all spans inside .db-logo look like X" rules (typically 0,0,1,1). */
.solo-brand-css .solo-brand-css-wordmark {
  display: inline-flex;
  flex-direction: column;
  font-family: var(--solo-font-head);   /* Lexend */
  font-size: 1.1rem;
  line-height: 0.95;
  letter-spacing: -0.01em;
  opacity: 1;
  text-transform: none;
  margin: 0;
}
.solo-brand-css .solo-brand-css-solo,
.solo-brand-css .solo-brand-css-cogs {
  display: block;
  font-size: inherit;
  letter-spacing: inherit;
  opacity: 1;
  text-transform: none;
  margin: 0;
  font-family: inherit;
}
/* Locked weights across both variants - Bold "Solo" + Regular "Cogs". */
.solo-brand-css .solo-brand-css-solo { font-weight: 700; }
.solo-brand-css .solo-brand-css-cogs { font-weight: 400; }

/* DEFAULT = dark-surface variant (sidebar + footer). Light Slate "Solo",
   Mastery Teal "Cogs", Mastery Teal gear (gear inherits from base above). */
.solo-brand-css .solo-brand-css-solo { color: #F8FAFC; }                /* Soft Slate */
.solo-brand-css .solo-brand-css-cogs { color: var(--solo-mastery); }    /* Electric Teal */

/* LIGHT variant - for nav bars + auth-card brand marks on light surfaces.
   Soft Charcoal Bold "Solo" + Mastery Teal Regular "Cogs", gear stays teal. */
.solo-brand-css.solo-brand-css--light .solo-brand-css-solo { color: var(--solo-text); }      /* #334155 Soft Charcoal */
.solo-brand-css.solo-brand-css--light .solo-brand-css-cogs { color: var(--solo-mastery); }   /* #2DD4BF Electric Teal */


/* ─── 6 · BUTTONS ─────────────────────────────────────────── */
/* ════════════════════════════════════════════════════════════════
   BUTTON SHAPE RULE (locked 2026-05-12):
   ALL clickable CTAs across SoloLab / SoloCognition / SoloSight use
   pill shape (border-radius: 999px). Containers, text inputs and
   panels remain rectangles - only action buttons are pills.
   When adding a new button class, default to inheriting .btn-solo
   so the shape stays uniform; do not introduce 8/10/12px button
   radii. If you find one, change it.
   ════════════════════════════════════════════════════════════════ */
.btn-solo {
  font-family: var(--solo-font-head);
  font-size: 14px;
  font-weight: 600;                     /* bumped to 600 - legibility on coloured backgrounds */
  line-height: 1;
  letter-spacing: var(--solo-letter-loose);
  padding: 12px 22px;                   /* slightly more horizontal padding to balance the pill */
  border-radius: 999px;                 /* PILL - per locked button-shape rule */
  border: 1px solid transparent;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  text-decoration: none;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--solo-fast) var(--solo-ease),
              color            var(--solo-fast) var(--solo-ease),
              border-color     var(--solo-fast) var(--solo-ease),
              transform        var(--solo-fast) var(--solo-ease),
              box-shadow       var(--solo-fast) var(--solo-ease);
}
.btn-solo:focus-visible { outline: 2px solid var(--solo-mastery); outline-offset: 2px; box-shadow: 0 0 0 5px rgba(15, 23, 42, .55); }
.btn-solo:disabled      { opacity: 0.5; cursor: not-allowed; }
.btn-solo:active:not(:disabled) { transform: translateY(1px); }

.btn-solo-teal {
  background: var(--solo-mastery);
  color: var(--solo-heading-color, var(--solo-navy));                          /* Deep Charcoal - Contrast Pass 2026-04-26 (charcoal-on-teal = 9.3:1 AAA) */
  font-family: var(--solo-font-head);               /* Lexend Bold for unmistakable weight on the teal */
  font-weight: 700;
  box-shadow: 0 1px 0 rgba(15, 23, 42, 0.06);
}
.btn-solo-teal:hover:not(:disabled) {
  background: var(--solo-mastery-deep);
  color: var(--solo-heading-color, var(--solo-navy));
  box-shadow: 0 0 0 4px rgba(45, 212, 191, 0.22),
              var(--solo-shadow-2);
}

.btn-solo-amber {
  background: var(--solo-confidence);
  color: #3A2A06;
}
.btn-solo-amber:hover:not(:disabled) {
  background: var(--solo-confidence-deep);
  color: white;
}

.btn-solo-slate {
  background: var(--solo-misconception);
  color: white;
}
.btn-solo-slate:hover:not(:disabled) { background: var(--solo-misconception-deep); }

.btn-solo-ghost {
  background: transparent;
  color: var(--solo-text);
  border-color: var(--solo-border);
}
.btn-solo-ghost:hover:not(:disabled) {
  background: var(--solo-misconception-pale);
  border-color: var(--solo-text-mute);
}

.btn-solo-link {
  background: transparent;
  color: var(--solo-mastery-deep);
  padding: 4px 0;
  border-radius: 0;
}
.btn-solo-link:hover:not(:disabled) { color: var(--solo-mastery); }


/* ─── 7 · PILLS & DOTS ────────────────────────────────────── */
/* Pills replace the RAG language across the platform. Same 3-state
   capture as before - just rebranded copy and palette. */
.pill-solo {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 999px;
  font-family: var(--solo-font-head);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.pill-mastery       { background: var(--solo-mastery-pale);      color: var(--solo-mastery-deep); }
.pill-confidence    { background: var(--solo-confidence-pale);   color: var(--solo-confidence-deep); }
.pill-misconception { background: var(--solo-misconception-pale);color: var(--solo-misconception-deep); }
.pill-neutral       { background: var(--solo-bg); color: var(--solo-text-mute); }

/* Inline dots - used for pre→post confidence pips, status indicators, etc. */
.dot-solo {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  vertical-align: middle;
  border: 1px solid rgba(0, 0, 0, 0.06);
  flex-shrink: 0;
}
.dot-mastery       { background: var(--solo-mastery); }
.dot-confidence    { background: var(--solo-confidence); }
.dot-misconception { background: var(--solo-misconception); }
.dot-empty         { background: transparent; border-color: var(--solo-border); }


/* ─── 8 · MASTERY RING (subject cards) ────────────────────── */
/* HTML pattern:
     <div class="mastery-ring" style="--ring-progress:42">
       <span class="mastery-ring__label">42%</span>
     </div>
   The conic-gradient draws the filled arc; the ::before pseudo-element
   is the inner "hole". Set --ring-size for chunkier subject-tile rings. */
.mastery-ring {
  --ring-size:      56px;
  --ring-thickness:  6px;
  --ring-progress:   0;
  width:  var(--ring-size);
  height: var(--ring-size);
  border-radius: 50%;
  background:
    conic-gradient(
      var(--solo-mastery) calc(var(--ring-progress) * 1%),
      var(--solo-divider) 0
    );
  display: inline-grid;
  place-items: center;
  position: relative;
  flex-shrink: 0;
}
.mastery-ring::before {
  content: '';
  width:  calc(var(--ring-size) - var(--ring-thickness) * 2);
  height: calc(var(--ring-size) - var(--ring-thickness) * 2);
  border-radius: 50%;
  background: var(--solo-bg-elevated);
}
.mastery-ring__label {
  position: absolute;
  font-family: var(--solo-font-head);
  font-weight: 600;
  font-size: 13px;
  color: var(--solo-heading-color, var(--solo-navy));
}


/* ─── 9 · BEAD PATH (SoloLab vertical progress) ──────────── */
/* HTML pattern:
     <div class="bead-path">
       <span class="bead bead--done"></span>
       <span class="bead-link bead-link--done"></span>
       <span class="bead bead--current"></span>
       <span class="bead-link"></span>
       <span class="bead bead--locked"></span>
     </div> */
.bead-path {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  padding: 12px 0;
}
.bead {
  --bead-size: 14px;
  width:  var(--bead-size);
  height: var(--bead-size);
  border-radius: 50%;
  background: var(--solo-divider);
  position: relative;
  z-index: 1;
  flex-shrink: 0;
  transition: transform var(--solo-fast) var(--solo-ease),
              box-shadow var(--solo-fast) var(--solo-ease);
}
.bead--done    { background: var(--solo-mastery); box-shadow: 0 0 0 3px var(--solo-mastery-glow); }
.bead--current {
  background: var(--solo-mastery);
  box-shadow: 0 0 0 4px var(--solo-mastery-glow);
  animation: bead-pulse 2.4s var(--solo-ease) infinite;
}
.bead--locked  { background: transparent; border: 2px solid var(--solo-border); }
.bead-link {
  width: 2px;
  height: 28px;
  background: var(--solo-divider);
}
.bead-link--done { background: var(--solo-mastery); }
@keyframes bead-pulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(45, 212, 191, 0.25); }
  50%      { box-shadow: 0 0 0 8px rgba(45, 212, 191, 0.10); }
}


/* ─── 10 · BENTO GRID (homepage feature cards) ───────────── */
.bento-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.25rem;
}
.bento-cell {
  background: var(--solo-bg-elevated);
  border: 1px solid var(--solo-divider);
  border-radius: var(--solo-radius-lg);
  padding: 1.5rem 1.5rem 1.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  transition: border-color var(--solo-fast) var(--solo-ease),
              box-shadow   var(--solo-fast) var(--solo-ease),
              transform    var(--solo-fast) var(--solo-ease);
}
.bento-cell:hover {
  border-color: var(--solo-mastery);
  box-shadow: var(--solo-shadow-2);
  transform: translateY(-2px);
}
.bento-cell--feature {
  grid-column: span 2;
  background: linear-gradient(135deg, var(--solo-bg-elevated) 0%, var(--solo-mastery-pale) 130%);
}
@media (max-width: 640px) {
  .bento-cell--feature { grid-column: span 1; }
}


/* ─── 11 · LAYOUT HELPERS ────────────────────────────────── */
.solo-stack    { display: flex; flex-direction: column; gap: 1rem; }
.solo-row      { display: flex; flex-direction: row;    gap: 1rem; align-items: center; }
.solo-row--wrap{ flex-wrap: wrap; }
.solo-section  { max-width: 1100px; margin: 0 auto; padding: 2.5rem 1.5rem; }
.solo-narrow   { max-width: 720px;  margin: 0 auto; padding: 2rem 1.5rem; }


/* ─── 12 · PLAIN-ENGLISH GLOBAL TOGGLE ───────────────────── */
/* Convention:
     <span class="lang-aqa">photosynthesis</span>
     <span class="lang-plain">how plants make food from sunlight</span>
   Adding `class="plain-english"` to <body> swaps which is shown.
   Default: AQA wording is shown, Plain is hidden. */
.lang-plain { display: none; }
body.plain-english .lang-aqa   { display: none; }
body.plain-english .lang-plain { display: revert; }


/* ─── 13 · HONEYCOMB CELL (SoloSight Tactical Map) ───────── */
/* For the spec-coverage heatmap. Use as a div with the modifier classes. */
.honeycomb-cell {
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
  width: 56px;
  height: 64px;
  display: inline-grid;
  place-items: center;
  font-family: var(--solo-font-head);
  font-size: 11px;
  font-weight: 600;
  background: var(--solo-divider);
  color: var(--solo-text-mute);
  margin: 2px;
  cursor: pointer;
  transition: transform var(--solo-fast) var(--solo-ease);
}
.honeycomb-cell:hover            { transform: scale(1.06); }
.honeycomb-cell--mastery         { background: var(--solo-mastery);       color: #1E293B; }
.honeycomb-cell--confidence      { background: var(--solo-confidence);    color: #3A2A06; }
.honeycomb-cell--misconception   { background: var(--solo-misconception); color: white; }
.honeycomb-cell--gap             { background: #CBD5E1;                   color: var(--solo-text-mute); }


/* ─── 14 · FOOTER (Sleek 2027 - Safeguarding lives here) ──
   Deep Charcoal background, Lexend column headers in Soft Teal,
   Atkinson body in Soft Slate. Drops a 1px white-fade top border to
   separate cleanly from the page above. */
.solo-footer {
  background: var(--solo-navy);                         /* #1E293B Deep Charcoal */
  color: rgba(248, 250, 252, 0.75);                     /* Soft Slate body */
  padding: 3.5rem 1.5rem 1.75rem;
  margin-top: 0;                                        /* override legacy footer margin so we sit flush */
  font-family: var(--solo-font-body);                   /* Atkinson links */
  font-size: 13.5px;
  line-height: 1.7;
  /* No top border - the CTA strip + footer share the same Deep Charcoal,
     so they flow as one continuous block. Any divider would clutter the seam. */
}
.solo-footer a {
  color: rgba(248, 250, 252, 0.75);
  text-decoration: none;
  transition: color var(--solo-fast) var(--solo-ease);
}
.solo-footer a:hover { color: var(--solo-mastery); }
.solo-footer h4 {
  color: var(--solo-mastery);                           /* Soft Teal column headers */
  font-family: var(--solo-font-head);                   /* Lexend */
  margin: 0 0 0.85rem;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 600;
}

/* 4-column grid: Brand · Tools · Support · Legal. Brand col is wider so the
   wordmark + tagline don't feel cramped. */
.solo-footer__grid {
  max-width: 1180px;
  margin: 0 auto 2.5rem;
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 3rem;
}
@media (max-width: 720px) {
  .solo-footer__grid { grid-template-columns: 1fr 1fr; gap: 2rem; }
}
@media (max-width: 480px) {
  .solo-footer__grid { grid-template-columns: 1fr; gap: 1.75rem; }
}
.solo-footer__brand-tagline {
  color: rgba(248, 250, 252, 0.6);
  font-size: 13px;
  line-height: 1.6;
  margin-top: 1.1rem;
  max-width: 28ch;
}
.solo-footer__col ul { list-style: none; padding: 0; margin: 0; }
.solo-footer__col li { margin-bottom: 0.55rem; }

/* Bottom strip - copyright + tagline, lightest on the page so it sits quietly. */
.solo-footer__bottom {
  max-width: 1180px;
  margin: 0 auto;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
  font-size: 12px;
  color: rgba(248, 250, 252, 0.5);
}
/* Footer reverse logo - reuses .solo-brand-css; this just sizes it for footer scale. */
.solo-footer .solo-brand-css { padding: 0; }
.solo-footer .solo-brand-css-gear { width: 36px; height: 36px; }
.solo-footer .solo-brand-css-wordmark { font-size: 1.2rem; }


/* ─── 14b · ARCHITECTURAL UTILITIES ───────────────────────
   Reusable surface helpers that work on any page. */

/* Light slate band - the canonical "middle section" backdrop. Sits between
   the white-toned hero and the dark-toned footer, providing the structural
   break between top-of-page and bottom-of-page zones. */
.solo-section-band { background: var(--solo-bg); }

/* Subtle dot grid - adds technical / lab-like texture without competing for
   attention. The element gets relative positioning so children stack above
   the pattern via the > * z-index rule. Pair with any section. */
.solo-pattern-dots {
  position: relative;
  overflow: hidden;
}
.solo-pattern-dots::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle, rgba(45, 212, 191, 0.22) 1.2px, transparent 1.5px);
  background-size: 22px 22px;
  background-position: 0 0;
  pointer-events: none;
  opacity: 0.55;
}
.solo-pattern-dots > * { position: relative; z-index: 1; }


/* ─── 15 · READER LAYOUT (policy & safeguarding) ─────────── */
.solo-reader {
  max-width: 720px;
  margin: 0 auto;
  padding: 3rem 1.5rem 4rem;
  font-size: 17px;
  line-height: 1.75;
  color: var(--solo-text);
}
.solo-reader h1 { font-size: 2rem;    margin-bottom: 1.5rem; }
.solo-reader h2 { font-size: 1.35rem; margin: 2.25rem 0 0.75rem; }
.solo-reader h3 { font-size: 1.05rem; margin: 1.5rem 0 0.5rem; }
.solo-reader p  { margin-bottom: 1rem; }
.solo-reader ul,
.solo-reader ol { margin: 0 0 1rem 1.25rem; }
.solo-reader li { margin-bottom: 0.4rem; }


/* ─── 16 · POLICY PAGES - SOLO OVERRIDES ─────────────────── */
/* Scoped under body.theme-solo so legacy pages keep working untouched.
   Styles the legacy `.policy-*` markup so the policy bundle shares the
   same hero / card / footer language as the marketing pages without
   needing per-file rewrites of the content. */

body.theme-solo .policy-hero {
  background:
    radial-gradient(ellipse 800px 480px at 50% 30%, rgba(45, 212, 191, 0.12) 0%, transparent 70%),
    linear-gradient(180deg, var(--solo-bg) 0%, #FFFFFF 100%) !important;
  border-bottom: 1px solid var(--solo-divider);
  padding: 4rem 1.5rem 3rem;
  text-align: center;
  color: var(--solo-text);
}
body.theme-solo .policy-hero-inner {
  max-width: 760px; margin: 0 auto;
}
body.theme-solo .policy-hero h1 {
  font-family: var(--solo-font-head) !important;
  font-weight: 700;
  font-size: clamp(2rem, 4vw, 2.8rem) !important;
  line-height: 1.1; letter-spacing: -0.02em;
  color: var(--solo-heading-color, var(--solo-navy)) !important;
  margin: 0.5rem auto 0.75rem !important;
}
body.theme-solo .policy-back {
  display: inline-flex; align-items: center;
  background: var(--solo-bg-elevated);
  border: 1px solid var(--solo-divider);
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
  font-family: var(--solo-font-head);
  font-size: 0.78rem; font-weight: 600;
  color: var(--solo-text-mute) !important;
  letter-spacing: 0.02em;
  text-decoration: none;
  box-shadow: var(--solo-shadow-1);
  margin-bottom: 1rem;
  transition: transform var(--solo-fast) var(--solo-ease), color var(--solo-fast) var(--solo-ease);
}
body.theme-solo .policy-back:hover {
  color: var(--solo-mastery-deep) !important;
  transform: translateX(-2px);
}
body.theme-solo .policy-meta {
  display: flex; justify-content: center; flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  font-family: var(--solo-font-head);
  font-size: 0.78rem; font-weight: 500;
  color: var(--solo-text-mute);
  margin-top: 0.5rem;
}
body.theme-solo .policy-meta span {
  display: inline-flex; align-items: center;
}
body.theme-solo .policy-meta span::before {
  content: '';
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--solo-mastery);
  margin-right: 0.45rem;
}

/* ─ Body of a single policy ─ */
body.theme-solo .policy-body {
  max-width: 760px; margin: 0 auto;
  padding: 3rem 1.5rem 4rem;
  font-family: var(--solo-font-body);
  font-size: 1rem; line-height: 1.75;
  color: var(--solo-text);
}
body.theme-solo .policy-body h2 {
  font-family: var(--solo-font-head) !important;
  font-weight: 700;
  font-size: 1.25rem !important;
  color: var(--solo-heading-color, var(--solo-navy)) !important;
  letter-spacing: -0.01em;
  margin: 2.25rem 0 0.75rem !important;
  padding-top: 1.25rem;
  border-top: 1px solid var(--solo-divider);
}
body.theme-solo .policy-body h2:first-child {
  margin-top: 0 !important; padding-top: 0; border-top: none;
}
body.theme-solo .policy-body h3 {
  font-family: var(--solo-font-head) !important;
  font-weight: 600;
  font-size: 1rem !important;
  color: var(--solo-heading-color, var(--solo-navy)) !important;
  margin: 1.5rem 0 0.4rem !important;
}
body.theme-solo .policy-body p {
  font-family: var(--solo-font-body);
  font-size: 0.97rem;
  color: var(--solo-text);
  line-height: 1.75;
  margin: 0 0 0.9rem;
}
body.theme-solo .policy-body ul,
body.theme-solo .policy-body ol {
  padding-left: 1.4rem;
  margin: 0 0 1rem;
}
body.theme-solo .policy-body li {
  font-family: var(--solo-font-body);
  font-size: 0.95rem;
  color: var(--solo-text);
  line-height: 1.7;
  margin-bottom: 0.4rem;
}
body.theme-solo .policy-body li::marker {
  color: var(--solo-mastery-deep);
}
body.theme-solo .policy-body strong {
  color: var(--solo-heading-color, var(--solo-navy)); font-weight: 700;
}
body.theme-solo .policy-body a {
  color: var(--solo-mastery-deep);
  text-decoration: underline;
  text-decoration-color: rgba(20, 184, 166, 0.35);
  text-underline-offset: 2px;
}
body.theme-solo .policy-body a:hover {
  text-decoration-color: var(--solo-mastery-deep);
}
body.theme-solo .policy-body code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.85em;
  background: var(--solo-bg);
  border: 1px solid var(--solo-divider);
  border-radius: 6px;
  padding: 0.08em 0.4em;
  color: var(--solo-heading-color, var(--solo-navy));
}

/* ─ Contact box at the end of every policy ─ */
body.theme-solo .policy-contact-box {
  margin-top: 2.5rem;
  background: linear-gradient(135deg, rgba(45, 212, 191, 0.10) 0%, rgba(45, 212, 191, 0.04) 100%);
  border: 1px solid rgba(45, 212, 191, 0.30);
  border-radius: 14px;
  padding: 1.25rem 1.5rem;
}
body.theme-solo .policy-contact-box p {
  font-family: var(--solo-font-body);
  font-size: 0.97rem;
  color: var(--solo-text);
  margin: 0;
  line-height: 1.7;
}
body.theme-solo .policy-contact-box strong {
  color: var(--solo-heading-color, var(--solo-navy));
}
body.theme-solo .policy-contact-box a {
  color: var(--solo-mastery-deep);
  text-decoration: underline;
  font-weight: 700;
}

/* ─ Index grid (policies.html) ─ */
body.theme-solo .policy-index-grid {
  display: grid !important;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)) !important;
  gap: 1.25rem !important;
  max-width: 1080px !important;
  margin: 0 auto !important;
}
body.theme-solo .policy-index-card {
  background: var(--solo-bg-elevated) !important;
  border: 1px solid var(--solo-divider) !important;
  border-radius: 14px !important;
  padding: 1.5rem !important;
  text-decoration: none !important;
  box-shadow: var(--solo-shadow-1);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  position: relative;
  overflow: hidden;
  transition: transform var(--solo-fast) var(--solo-ease),
              box-shadow var(--solo-fast) var(--solo-ease),
              border-color var(--solo-fast) var(--solo-ease);
}
body.theme-solo .policy-index-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: var(--solo-mastery);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--solo-slow) var(--solo-ease);
}
body.theme-solo .policy-index-card:hover {
  transform: translateY(-2px);
  border-color: rgba(45, 212, 191, 0.4) !important;
  box-shadow: var(--solo-shadow-2) !important;
}
body.theme-solo .policy-index-card:hover::before {
  transform: scaleX(1);
}
body.theme-solo .policy-index-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--solo-mastery-pale);
  color: var(--solo-mastery-deep);
  margin-bottom: 0.85rem;
  font-size: 0;                   /* nukes any residual emoji glyph */
}
body.theme-solo .policy-index-icon .solo-icon {
  stroke: currentColor;
  width: 22px;
  height: 22px;
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
body.theme-solo .policy-index-title {
  font-family: var(--solo-font-head) !important;
  font-weight: 700;
  font-size: 1rem !important;
  color: var(--solo-heading-color, var(--solo-navy)) !important;
  margin-bottom: 0.45rem !important;
  letter-spacing: -0.01em;
}
body.theme-solo .policy-index-desc {
  font-family: var(--solo-font-body);
  font-size: 0.9rem !important;
  color: var(--solo-text) !important;
  line-height: 1.65 !important;
  margin-bottom: 0.85rem;
}
body.theme-solo .policy-index-arrow {
  font-family: var(--solo-font-head) !important;
  font-size: 0.78rem !important;
  font-weight: 700;
  color: var(--solo-mastery-deep) !important;
  letter-spacing: 0.02em;
  margin-top: auto !important;
}

/* ─ "Last reviewed" callout below policy index ─ */
body.theme-solo .policy-index-foot {
  max-width: 1080px;
  margin: 1.5rem auto 0;
  padding: 0.85rem 1.1rem;
  background: var(--solo-bg);
  border: 1px solid var(--solo-divider);
  border-radius: 10px;
  font-family: var(--solo-font-body);
  font-size: 0.88rem;
  color: var(--solo-text-mute);
  line-height: 1.65;
}
body.theme-solo .policy-index-foot strong {
  color: var(--solo-heading-color, var(--solo-navy));
  font-weight: 700;
}
body.theme-solo .policy-index-foot a {
  color: var(--solo-mastery-deep);
  text-decoration: underline;
  font-weight: 700;
}

@media (max-width: 640px) {
  body.theme-solo .policy-hero { padding: 2.5rem 1rem 2rem; }
  body.theme-solo .policy-body { padding: 2rem 1rem 3rem; }
  body.theme-solo .policy-index-grid { grid-template-columns: 1fr !important; }
}


/* ─── 17 · ICONS & ZEN-LAB CARD PATTERN ──────────────────
   Inline SVG line icons replace decorative emojis across the platform.
   Convention: 24×24 viewBox, fill="none", stroke="currentColor",
   stroke-width="2", stroke-linecap="round", stroke-linejoin="round".
   Apply `.solo-icon` for default sizing + mastery teal stroke. Use
   `.solo-icon--charcoal` to render in deep navy on teal backgrounds. */

.solo-icon {
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  stroke: var(--solo-mastery);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  display: inline-block;
  vertical-align: middle;
}
.solo-icon--charcoal { stroke: var(--solo-navy); }
.solo-icon--mute     { stroke: var(--solo-text-mute); }
.solo-icon--inverse  { stroke: #FFFFFF; }
.solo-icon--lg { width: 32px; height: 32px; }
.solo-icon--xl { width: 48px; height: 48px; }
.solo-icon--sm { width: 18px; height: 18px; stroke-width: 2.2; }

/* ─ Zen Lab subject card ─
   Replaces the older image-backed Subject Hero Cards. Pure white card,
   4px subject-coloured accent bar on the LEFT, a single line-icon in
   mastery teal, Lexend deep-charcoal heading, Atkinson slate-grey body,
   solid mastery-teal pill CTA with charcoal text. No solid colour bars,
   no gradients - subject identity comes from the icon + accent stripe. */

.solo-zen-card {
  --zen-accent: var(--solo-mastery);     /* default; subject classes override */
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--solo-bg-elevated);
  border: 1px solid var(--solo-divider);
  border-radius: 16px;
  padding: 1.75rem 1.75rem 1.75rem 2rem;
  text-decoration: none;
  color: inherit;
  overflow: hidden;
  box-shadow: var(--solo-shadow-1);
  transition: transform var(--solo-fast) var(--solo-ease),
              box-shadow var(--solo-fast) var(--solo-ease),
              border-color var(--solo-fast) var(--solo-ease);
}
.solo-zen-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; bottom: 0;
  width: 4px;
  background: var(--zen-accent);
}
.solo-zen-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--solo-shadow-2);
  border-color: rgba(45, 212, 191, 0.4);
}
.solo-zen-card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: var(--solo-mastery-pale);
  color: var(--solo-mastery-deep);
  margin-bottom: 1.1rem;
}
.solo-zen-card__icon .solo-icon {
  stroke: currentColor;
  width: 28px;
  height: 28px;
}
.solo-zen-card__eyebrow {
  font-family: var(--solo-font-head);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--solo-text-mute);
  margin: 0 0 0.4rem;
}
.solo-zen-card__title {
  font-family: var(--solo-font-head);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--solo-heading-color, var(--solo-navy));
  margin: 0 0 0.65rem;
}
.solo-zen-card__desc {
  font-family: var(--solo-font-body);
  font-size: 0.95rem;
  color: var(--solo-text);                /* Slate Grey - keeps body distinct from heading */
  line-height: 1.65;
  margin: 0 0 1.5rem;
  flex: 1;
}
.solo-zen-card__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--solo-mastery);
  color: var(--solo-heading-color, var(--solo-navy));                 /* Deep Charcoal - Contrast Pass (9.3:1 AAA) */
  font-family: var(--solo-font-head);
  font-size: 0.92rem;
  font-weight: 700;
  padding: 0.7rem 1.2rem;
  border-radius: 999px;
  align-self: flex-start;
  letter-spacing: 0.005em;
  transition: transform var(--solo-fast) var(--solo-ease),
              box-shadow var(--solo-fast) var(--solo-ease),
              background var(--solo-fast) var(--solo-ease);
}
.solo-zen-card:hover .solo-zen-card__cta {
  background: var(--solo-mastery-deep);
  color: var(--solo-heading-color, var(--solo-navy));
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(45, 212, 191, 0.40);
}

/* Subject accent palette - locked Clarity Pass 2026-04-26.
   Bio = Solo Teal · Chem = Confidence Amber · Phys = Indigo.
   Vibrant, full-height 4px rails on the left of every white card. */
.solo-zen-card--bio  { --zen-accent: var(--solo-mastery); }     /* Solo Teal #2DD4BF */
.solo-zen-card--chem { --zen-accent: var(--solo-confidence); }  /* Sunrise Amber #F59E0B */
.solo-zen-card--phys { --zen-accent: #4F46E5; }                 /* Indigo */
/* Bump the Zen rail to 4px and ensure it always paints to the full card height */
.solo-zen-card::before {
  width: 4px !important;
}

/* Reusable subject-tinted CSS variables - for any non-zen card pattern that
   needs the same accent without using .solo-zen-card directly. */
.solo-subject-bio  { --subj-color: var(--solo-mastery);    --subj-pale: var(--solo-mastery-pale); }
.solo-subject-chem { --subj-color: var(--solo-confidence); --subj-pale: var(--solo-confidence-pale); }
.solo-subject-phys { --subj-color: #4F46E5;                --subj-pale: #E0E7FF; }

/* ─ "Subject Library" / "Active Labs" wrapper ─
   Flex-row layout with a consistent 1.5rem gap so cards sit snug rather than
   spreading across the viewport with empty grid cells. align-items: stretch
   makes every card in a row match the tallest sibling, so descriptions of
   different lengths still produce a perfectly clean grid. */
/* CSS Grid (not flex) so columns stay the SAME width even when the last row
   isn't fully populated. With flex+max-width, an 8-card grid filled to a
   3-up grid leaves a 2-card last row whose cards expand to max-width, ending
   up wider than the squeezed cards in the rows above - looks misaligned.
   Grid pins each column to the same fraction regardless of fill. */
.solo-zen-grid,
.solo-card-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.5rem;
  max-width: 1180px;
  margin: 0 auto;
  align-items: stretch;          /* equal-height cards - no jagged grid */
}
.solo-zen-grid > .solo-zen-card,
.solo-zen-grid > .solo-hero-card,
.solo-card-row > .solo-zen-card,
.solo-card-row > .solo-hero-card {
  display: flex;                 /* card itself is a flex column so the body can stretch */
  flex-direction: column;
  min-width: 0;                  /* grid item: allow shrink below intrinsic content size */
}
@media (max-width: 900px) {
  .solo-zen-grid,
  .solo-card-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
  .solo-zen-grid,
  .solo-card-row { grid-template-columns: 1fr; }
}

/* ════════════════════════════════════════════════════════════
   .solo-hero-card  ·  IMAGE-HERO PREMIUM SUBJECT CARD
   "Science Without Walls" feel - bright high-key image takes the top half
   of the card; below it sits a clean white body with Lexend H3, Atkinson
   description, AQA topic meta line, and a solid mastery-teal pill CTA.
   A vibrant 4px subject accent bar runs the full height of the LEFT edge.
   ════════════════════════════════════════════════════════════ */
.solo-hero-card {
  --card-accent: var(--solo-mastery);
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--solo-bg-elevated);
  border: 1px solid var(--solo-divider);
  border-radius: 18px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  box-shadow: var(--solo-shadow-1);
  transition: transform var(--solo-fast) var(--solo-ease),
              box-shadow var(--solo-fast) var(--solo-ease),
              border-color var(--solo-fast) var(--solo-ease);
}
/* The 4px subject accent rail - runs the full height of the card but sits
   BEHIND the image (z-index 1) so it only shows over the white body section.
   Stops the colored rail from striping across the colorful science image. */
.solo-hero-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; bottom: 0;
  width: 4px;
  background: var(--card-accent);
  z-index: 1;
}
.solo-hero-card:hover {
  transform: translateY(-3px);
  border-color: var(--card-accent);
  box-shadow: 0 18px 36px rgba(15, 23, 42, 0.12),
              0 4px 8px rgba(15, 23, 42, 0.06);
}
.solo-hero-card__media {
  position: relative;
  aspect-ratio: 3 / 2;                  /* premium full-width hero - bigger than 16/10 */
  background-color: var(--solo-bg);     /* fallback while/if the image is missing */
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  /* background-image is set inline via the style attribute on each card -
     direct inline declaration is the most reliable across browsers. */
  overflow: hidden;
  z-index: 2;                           /* sits over the rail so it isn't striped */
  /* Match the parent card's rounded corners on the top edge so the topic-img
     layer (which has border-radius: inherit) gets clipped to the curve.
     Without this the media is a square box, the inherited radius is 0, and
     the topic-img's own stacking context lets pointy corners leak past the
     card's outer overflow:hidden in some browsers. */
  border-top-left-radius: inherit;
  border-top-right-radius: inherit;
  /* Smooth transition for the on-hover glow intensifier below. */
  transition: filter .24s ease, box-shadow .24s ease;
}
/* On hover the subject-coloured wireframes in the dark-background image
   "wake up" - we punch saturation + brightness so the existing neon glow
   reads more strongly, and add a soft inner halo in the card's accent
   colour so the glow reads as light coming OUT of the image. */
.solo-hero-card:hover .solo-hero-card__media,
.solo-hero-card:focus-visible .solo-hero-card__media {
  filter: brightness(1.18) saturate(1.25);
  box-shadow:
    inset 0 0 32px 4px color-mix(in srgb, var(--card-accent, #2DD4BF) 38%, transparent),
    inset 0 0 6px 1px color-mix(in srgb, var(--card-accent, #2DD4BF) 28%, transparent);
}
.solo-hero-card__media::after {
  /* Soft top-down vignette so any heading text near the bottom edge stays
     legible and the image's brightness reads as "high-key" not blown out. */
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(15, 23, 42, 0) 60%, rgba(15, 23, 42, 0.18) 100%);
  pointer-events: none;
}
/* Defensive: kill default user-agent outlines / borders on linkified
   tile images. Some browsers paint a grey square outline on hover or
   focus around <img>-only <a> elements; the card's own border + the
   focus-ring rule below handle it cleanly without that artefact. */
.solo-hero-card,
.solo-hero-card:hover,
.solo-hero-card:focus,
.solo-hero-card:focus-visible {
  outline: none;
}
.solo-hero-card:focus-visible {
  box-shadow:
    0 0 0 3px rgba(45, 212, 191, 0.40),
    0 18px 36px rgba(15, 23, 42, 0.12),
    0 4px 8px rgba(15, 23, 42, 0.06);
}
.solo-hero-card__media,
.solo-hero-card__media img {
  border: 0;
  outline: 0;
}
/* Floating subject badge over the image was a duplicate of the title below
   - hidden globally per Clarity Pass refinement 2026-04-26. The eyebrow line
   ("AQA GCSE · Topic N") + H3 title ("Biology") in the body cover labelling. */
.solo-hero-card__badge { display: none !important; }
.solo-hero-card__body {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 1.85rem 2rem 1.85rem 2.15rem; /* roomier internal padding - text no longer hugs edges */
  flex: 1;
}
.solo-hero-card__eyebrow {
  font-family: var(--solo-font-head);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--solo-text-mute);
  margin: 0 0 0.45rem;
}
.solo-hero-card__title {
  font-family: var(--solo-font-head);
  font-size: 1.55rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  color: var(--solo-heading-color, var(--solo-navy));                /* Solid Deep Charcoal - Clarity Pass */
  margin: 0 0 0.55rem;
  line-height: 1.15;
}
.solo-hero-card__desc {
  font-family: var(--solo-font-body);
  font-size: 0.95rem;
  color: var(--solo-text);                /* Slate Grey #475569 */
  line-height: 1.6;
  margin: 0 0 1.5rem;
  flex: 1;                                /* eats remaining space so CTAs align across cards */
}
.solo-hero-card__meta {
  font-family: var(--solo-font-head);
  font-size: 0.78rem;
  color: var(--solo-text-mute);
  margin: 0 0 1rem;
}
.solo-hero-card__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  background: var(--solo-mastery);
  color: var(--solo-heading-color, var(--solo-navy));                /* Deep Charcoal - Contrast Pass (9.3:1 AAA) */
  font-family: var(--solo-font-head);
  font-size: 0.95rem;
  font-weight: 700;
  padding: 0.8rem 1.5rem;
  border-radius: 999px;
  /* Default = full-width on small screens. Desktop override below pins to bottom-left at fixed width. */
  align-self: stretch;
  width: 100%;
  max-width: none;
  margin-top: auto;                       /* push CTA to the bottom of the card body */
  letter-spacing: 0.005em;
  box-shadow: 0 1px 0 rgba(15, 23, 42, 0.06);
  transition: transform var(--solo-fast) var(--solo-ease),
              background var(--solo-fast) var(--solo-ease),
              box-shadow var(--solo-fast) var(--solo-ease);
}
.solo-hero-card__cta svg {
  stroke: currentColor;
  width: 16px; height: 16px;
  flex-shrink: 0;
}
.solo-hero-card:hover .solo-hero-card__cta {
  background: var(--solo-mastery-deep);
  color: var(--solo-heading-color, var(--solo-navy));
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(45, 212, 191, 0.40);
}
@media (min-width: 540px) {
  /* Desktop: button hugs bottom-left at a comfortable fixed width. */
  .solo-hero-card__cta {
    align-self: flex-start;
    width: auto;
    min-width: 9rem;
  }
}

/* Status pill (e.g. "Active" / "Coming this term") that lives in the body */
.solo-hero-card__status {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-family: var(--solo-font-head);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--solo-mastery-deep);
  margin-bottom: 0.85rem;
}
.solo-hero-card__status::before {
  content: '';
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--solo-mastery);
  box-shadow: 0 0 0 3px rgba(45, 212, 191, 0.22);
}
.solo-hero-card__status--scheduled { color: var(--solo-text-mute); }
.solo-hero-card__status--scheduled::before { background: var(--solo-text-soft); box-shadow: none; }
.solo-hero-card__status--complete { color: var(--solo-mastery-deep); }
.solo-hero-card__status--complete::before { background: var(--solo-mastery); }

/* Subject variants apply the accent to the rail + status dot + cta border */
.solo-hero-card--bio  { --card-accent: var(--solo-mastery);    --ribbon-color: #0F766E; }
.solo-hero-card--chem { --card-accent: var(--solo-confidence); --ribbon-color: #B45309; }
.solo-hero-card--phys { --card-accent: #4F46E5;                --ribbon-color: #4338CA; }

/* ════════════════════════════════════════════════════════════════
   TOPIC-CARD IMAGE OVERLAY  ·  Two-state hover-flip
   ────────────────────────────────────────────────────────────────
   Each card can carry one portrait JPG whose TOP half is state A and
   bottom half is state B. We size the image at 2x card height and
   swap background-position on hover for an instant A->B flip. Shared
   by subject-dashboard.html (SoloLab) and assessment-dashboard.html
   (SoloCognition). */
.solo-hero-card__topic-img {
  position: absolute;
  inset: -1px;                       /* overshoots parent so corner pixels don't leak */
  z-index: 4;
  background-image: var(--topic-card-img, none);
  background-size: 100% 200%;        /* image is 2x card height */
  background-position: 0% 0%;        /* state A (top half) */
  background-repeat: no-repeat;
  pointer-events: none;
  border-radius: inherit;
}
.solo-hero-card:hover .solo-hero-card__topic-img,
.solo-hero-card:focus-visible .solo-hero-card__topic-img {
  background-position: 0% 100%;      /* state B (bottom half) */
}
/* When the topic image is present the card already has plenty of visual
   weight, so we soften the hover/focus shadow to keep the rounded corners
   clean. */
.solo-hero-card:has(.solo-hero-card__topic-img):hover {
  box-shadow: 0 8px 22px rgba(15, 23, 42, 0.10),
              0 2px 4px rgba(15, 23, 42, 0.05);
}
.solo-hero-card:has(.solo-hero-card__topic-img):focus-visible {
  box-shadow:
    0 0 0 3px rgba(45, 212, 191, 0.40),
    0 8px 22px rgba(15, 23, 42, 0.10);
}
/* Coming-soon tiles desaturate the topic image so the "not yet" reads. */
.solo-hero-card--soon .solo-hero-card__topic-img,
.solo-hero-card[aria-disabled="true"] .solo-hero-card__topic-img {
  filter: grayscale(85%) opacity(0.55) brightness(0.95);
}

/* ════════════════════════════════════════════════════════════════
   CORNER RIBBON - lab vs cog disambiguation
   ────────────────────────────────────────────────────────────────
   Diagonal flag in the top-right corner of each subject card so a
   student can tell at a glance whether the card opens a SoloLab
   (flask icon) or a SoloCognition assessment (brain icon). Subject
   colour comes from --ribbon-color set by the .solo-hero-card--bio
   / --chem / --phys variants above.

   Markup:
     <span class="solo-hero-card__ribbon" data-mode="lab"></span>
     <span class="solo-hero-card__ribbon" data-mode="cog"></span>

   The icon is injected via mask-image so we don't need an SVG node
   in every card and the colour comes from the ribbon flag itself.
   ════════════════════════════════════════════════════════════════ */
.solo-hero-card { position: relative; }   /* needed so the ribbon anchors */
/* Corner-ribbon geometry, rebuilt for v2:
   - Container is 130×130 anchored top-right of the card.
   - Stripe: 200×40 rectangle whose centre sits at (50% of container, 50%
     of container) - so it diagonals exactly through the corner area.
   - Icon: 32px, also anchored at the container centre then translated to
     sit ON the stripe (not in the corner above it). The icon counter-rotates
     so it reads upright on the diagonal. */
.solo-hero-card__ribbon {
  position: absolute;
  top: 0;
  right: 0;
  width: 130px;
  height: 130px;
  overflow: hidden;
  pointer-events: none;
  z-index: 5;
}
.solo-hero-card__ribbon::before {
  content: '';
  position: absolute;
  /* Anchor stripe + icon centre near the top-right corner of the
     container rather than the geometric centre, so the visible ribbon
     reads as a true corner banner rather than a slash across the
     middle of the corner block. */
  top: 30%;
  right: 30%;
  width: 220px;
  height: 40px;
  margin-top: -20px;
  margin-right: -110px;
  background: var(--ribbon-color, var(--solo-mastery));
  /* +45deg gives the conventional top-right corner banner direction
     (cloth draped from the corner, slope \). */
  transform: rotate(45deg);
  transform-origin: center center;
  box-shadow: 0 4px 10px rgba(15, 23, 42, 0.22);
}
/* Icon anchored to the same centre as the stripe so it sits ON the stripe
   regardless of the stripe rotation. The mask paints a white symbol on
   the coloured ribbon background. */
.solo-hero-card__ribbon::after {
  content: '';
  position: absolute;
  top: 30%;
  right: 30%;
  width: 30px;
  height: 30px;
  margin-top: -15px;
  margin-right: -15px;
  background-color: #FFFFFF;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
  z-index: 2;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,0.25));
}
/* Erlenmeyer flask for SoloLab cards. */
.solo-hero-card__ribbon[data-mode="lab"]::after {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M9 3h6'/><path d='M10 3v6.5L4.5 19a1 1 0 0 0 .87 1.5h13.26A1 1 0 0 0 19.5 19L14 9.5V3'/><path d='M7 16h10'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M9 3h6'/><path d='M10 3v6.5L4.5 19a1 1 0 0 0 .87 1.5h13.26A1 1 0 0 0 19.5 19L14 9.5V3'/><path d='M7 16h10'/></svg>");
}
/* Brain icon for SoloCognition cards - SIDE-VIEW silhouette. The shape
   reads as a brain in profile (facing left): wavy cerebrum along the
   top, cerebellum bump at the lower-back-right, brainstem nub below.
   Single solid filled path so the mask paints a clean white silhouette
   on the coloured ribbon. */
.solo-hero-card__ribbon[data-mode="cog"]::after {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' fill-rule='evenodd'><path d='M4 8C3 5 7 3 10 4C12 3 14 3 15 5C17 4 20 5 20 8C22 9 22 11 20 12C22 13 21 16 18 16L18 19L15 19L15 16C13 17 10 17 8 16C5 17 3 14 4 12C2 11 2 9 4 8ZM7 7C8 6 11 6 12 7C13 6 15 6 16 7C17 8 17 10 16 11C15 12 13 12 12 11C11 12 9 12 8 11C7 10 7 8 7 7Z'/></svg>");
          mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='black' fill-rule='evenodd'><path d='M4 8C3 5 7 3 10 4C12 3 14 3 15 5C17 4 20 5 20 8C22 9 22 11 20 12C22 13 21 16 18 16L18 19L15 19L15 16C13 17 10 17 8 16C5 17 3 14 4 12C2 11 2 9 4 8ZM7 7C8 6 11 6 12 7C13 6 15 6 16 7C17 8 17 10 16 11C15 12 13 12 12 11C11 12 9 12 8 11C7 10 7 8 7 7Z'/></svg>");
}

/* Subject-tinted CTAs on SoloLab + SoloCognition landing pages.
   Biology stays on mastery teal (correct by design); Chemistry recolours
   to Chem Amber and Physics to Phys Indigo so all three subject cards
   carry their own brand on the "Open lab" / "Start assessment" CTAs. */
.solo-hero-card--chem .solo-hero-card__cta {
  background: #B45309;            /* Chem Amber - AAA on white text */
  color: #FFFFFF;
}
.solo-hero-card--chem:hover .solo-hero-card__cta {
  background: #92400E;
  color: #FFFFFF;
  box-shadow: 0 6px 16px rgba(180, 83, 9, 0.40);
}
.solo-hero-card--phys .solo-hero-card__cta {
  background: #4338CA;            /* Phys Indigo */
  color: #FFFFFF;
}
.solo-hero-card--phys:hover .solo-hero-card__cta {
  background: #3730A3;
  color: #FFFFFF;
  box-shadow: 0 6px 16px rgba(67, 56, 202, 0.40);
}

/* When the card represents a SCHEDULED unit the body is dimmed slightly. */
.solo-hero-card--scheduled { opacity: 0.78; }
.solo-hero-card--scheduled .solo-hero-card__cta {
  background: var(--solo-divider);
  color: var(--solo-text-soft);
  text-shadow: none;
  cursor: not-allowed;
  pointer-events: none;
  box-shadow: none;
}
.solo-hero-card--scheduled:hover {
  transform: none;
  border-color: var(--solo-divider);
  box-shadow: var(--solo-shadow-1);
}
.solo-hero-card--scheduled:hover .solo-hero-card__cta {
  background: var(--solo-divider);
  transform: none;
  box-shadow: none;
}

@media (max-width: 480px) {
  .solo-hero-card__body { padding: 1.2rem 1.25rem 1.3rem 1.45rem; }
  .solo-hero-card__title { font-size: 1.3rem; }
}

/* Icon chip - used wherever a feature/policy card needs a small line icon
   on a pale-teal disc. Standardises the rounded square + mastery palette
   so it never reverts to a coloured emoji background. */
.solo-icon-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--solo-mastery-pale);
  color: var(--solo-mastery-deep);
  margin-bottom: 0.85rem;
  flex-shrink: 0;
}
.solo-icon-chip .solo-icon {
  stroke: currentColor;
  width: 24px;
  height: 24px;
}
.solo-icon-chip--sm {
  width: 36px;
  height: 36px;
  margin-bottom: 0.6rem;
}
.solo-icon-chip--sm .solo-icon { width: 20px; height: 20px; }
.solo-icon-chip--lg {
  width: 56px;
  height: 56px;
}
.solo-icon-chip--lg .solo-icon { width: 30px; height: 30px; }

/* Override the legacy .card-icon emoji-background utilities when used
   inside body.theme-solo so they always render as the clean teal chip. */
body.theme-solo .card-icon {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: var(--solo-mastery-pale);
  color: var(--solo-mastery-deep);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.85rem;
  font-size: 0;                    /* nukes any stray emoji glyph */
}
body.theme-solo .card-icon .solo-icon {
  stroke: currentColor;
  width: 24px;
  height: 24px;
}


/* ════════════════════════════════════════════════════════════
   SoloCogs Universal Flashcard Component (`.sc-fc-*`)

   The single canonical key-words / vocabulary flashcard pattern used
   across every unit and sub-unit. When you build a new key-words
   activity (Biology, Chemistry, Physics, future subjects) USE THIS -
   do not invent another local flashcard style.

   ── Markup contract ──────────────────────────────────────────
   <div class="sc-fc-component" data-init="sc-flashcards" data-total="N">
     <p class="sc-fc-intro">Tap each card to flip it. Lock these in
        before the content section.</p>
     <div class="sc-fc-stage">
       <button type="button" class="sc-fc-card" data-fcard="0"
               aria-label="Flashcard - tap to flip">
         <div class="sc-fc-face sc-fc-front">
           <span class="sc-fc-eyebrow">Term</span>
           <span class="sc-fc-term">Cell</span>
           <span class="sc-fc-hint">↻ Tap to flip</span>
         </div>
         <div class="sc-fc-face sc-fc-back">
           <span class="sc-fc-eyebrow">Definition</span>
           <p class="sc-fc-def">The basic unit of life…</p>
         </div>
       </button>
       <button class="sc-fc-card" data-fcard="1" hidden …>…</button>
     </div>
     <div class="sc-fc-nav">
       <button class="rs-btn" data-fc-prev disabled>← Previous</button>
       <span class="sc-fc-counter"><span data-fc-cur>1</span> of N</span>
       <button class="rs-btn rs-btn-teal" data-fc-next>Next →</button>
     </div>
   </div>

   ── JS contract ──────────────────────────────────────────────
   - One card visible at a time. Hidden cards use the [hidden] attr.
   - Card click toggles `.is-flipped` on .sc-fc-card.
   - Prev/Next steps via [data-fc-prev]/[data-fc-next], reading
     [data-fcard] indices and writing into [data-fc-cur] for the count.
   - Each unit's renderer wires its own keyboard navigation; we don't
     bind global keys here so multi-component pages stay decoupled.

   ── Design rationale (SEND / dyslexia / UDL) ─────────────────
   - Front: white→soft-slate gradient, navy term, mastery-teal eyebrow.
     Bright but not glaring; high contrast; not pure white.
   - Back: pale-teal tinted card. The colour shift itself signals
     "you've flipped to the definition" - a cognitive cue that
     reduces working-memory load.
   - Term in Lexend (dyslexia-tuned). Definition in Atkinson
     Hyperlegible (UDL hyperlegibility). Line-height 1.7.
   - Definition column-capped to ~44ch for comfortable scanning.
   - 44px minimum touch targets on prev/next.
   - prefers-reduced-motion: disables the rotate-Y transition.
   ════════════════════════════════════════════════════════════ */

.sc-fc-component {
  background: var(--solo-bg-elevated, #FFFFFF);
  border: 1px solid var(--solo-divider);
  border-radius: var(--solo-radius, 14px);
  padding: 1.25rem 1.4rem 1.4rem;
  box-shadow: var(--solo-shadow-1, 0 1px 3px rgba(15, 23, 42, 0.06));
}
/* When nested inside an outer panel (e.g. .rs-card on cell-biology pages),
   drop our own panel chrome so the parent provides it. Avoids the
   "card inside a card" double-frame look. */
.rs-card .sc-fc-component {
  background: transparent;
  border: 0;
  padding: 0;
  box-shadow: none;
}
.sc-fc-intro {
  font-family: var(--solo-font-body);
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--solo-text);
  margin: 0 0 1.1rem;
}
.sc-fc-stage {
  position: relative;
  perspective: 1400px;
  max-width: 540px;
  margin: 0 auto;
}

.sc-fc-card {
  /* Reset native button styles - card is also our flip target */
  appearance: none;
  -webkit-appearance: none;
  background: linear-gradient(180deg, #FFFFFF 0%, var(--solo-bg, #F1F5F9) 100%);
  border: 1.5px solid var(--solo-mastery, #2DD4BF);
  padding: 1.85rem 1.75rem 1.65rem;
  font: inherit;
  color: inherit;
  text-align: center;

  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  aspect-ratio: 16 / 10;
  min-height: 230px;
  cursor: pointer;
  /* No 3D rotation: the actual renderer emits a single text span, so
     the previous rotateY(180deg) flip mirrored the def back to the
     student. Flip is now signalled by a background tint change driven
     by .is-flipped; the JS handler swaps the text content for the
     definition on the same span. */
  transition: background 0.25s ease, border-color 0.25s ease;
  border-radius: 18px;
  box-shadow:
    0 1px 3px rgba(15, 23, 42, 0.06),
    0 8px 20px rgba(15, 23, 42, 0.04);
}
.sc-fc-card[hidden] { display: none !important; }
.sc-fc-card.is-flipped {
  background: var(--solo-mastery-pale, #CCFBF1);
  border-color: var(--solo-mastery-deep, #14B8A6);
}
.sc-fc-card:focus-visible {
  outline: 3px solid var(--solo-mastery-deep);
  outline-offset: 4px;
}

.sc-fc-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 18px;
  padding: 1.85rem 1.75rem 1.65rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  box-sizing: border-box;
  border: 1.5px solid var(--solo-divider);
  box-shadow:
    0 1px 3px rgba(15, 23, 42, 0.06),
    0 8px 20px rgba(15, 23, 42, 0.04);
  gap: 0.65rem;
}

/* Front: bright cream with a teal accent strip up top */
.sc-fc-front {
  background: linear-gradient(180deg, #FFFFFF 0%, var(--solo-bg, #F1F5F9) 100%);
  border-color: var(--solo-mastery, #2DD4BF);
}
.sc-fc-front::before {
  content: '';
  position: absolute;
  top: 0;
  left: 12%;
  right: 12%;
  height: 4px;
  background: var(--solo-mastery, #2DD4BF);
  border-radius: 0 0 4px 4px;
}

/* Back: pale-teal tint - the colour itself signals "you flipped" */
.sc-fc-back {
  background: var(--solo-mastery-pale, #CCFBF1);
  border-color: var(--solo-mastery, #2DD4BF);
  transform: rotateY(180deg);
}

.sc-fc-eyebrow {
  font-family: var(--solo-font-head);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--solo-mastery-deep, #0F766E);
}
.sc-fc-term {
  font-family: var(--solo-font-head);
  font-size: clamp(1.5rem, 3vw, 2rem);
  font-weight: 700;
  color: var(--solo-heading-color, var(--solo-navy));
  line-height: 1.2;
  letter-spacing: -0.01em;
  max-width: 100%;
  word-break: break-word;
}
.sc-fc-def {
  font-family: var(--solo-font-body);
  font-size: 1rem;
  line-height: 1.7;
  color: var(--solo-heading-color, var(--solo-navy));
  max-width: 44ch;
  margin: 0;
}
.sc-fc-hint {
  font-family: var(--solo-font-body);
  font-size: 0.82rem;
  color: var(--solo-text-mute);
  margin-top: 0.4rem;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.sc-fc-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-top: 1.2rem;
  flex-wrap: wrap;
}
.sc-fc-counter {
  font-family: var(--solo-font-head);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--solo-text-mute);
  flex: 1 1 auto;
  text-align: center;
}
.sc-fc-nav .rs-btn { min-height: 44px; }   /* SEND-friendly target */

@media (prefers-reduced-motion: reduce) {
  .sc-fc-card { transition: none; }
}
@media (max-width: 520px) {
  .sc-fc-stage { max-width: 100%; }
  .sc-fc-card  { min-height: 210px; }
  .sc-fc-face  { padding: 1.4rem 1.25rem; }
}


/* ─── End of solocogs-theme.css ─────────────────────────── */


/* ════════════════════════════════════════════════════════════════
   BASELINE / RESOURCE bottom callout strip - dark navy band with
   teal pill CTA. Used at the foot of resources.html ()
   and baseline.html (). Single shared definition so both
   surfaces stay in sync.
   ════════════════════════════════════════════════════════════════ */
.sololab-baseline-callout {
  background: var(--solo-navy);
  padding: 4rem 2rem;
  text-align: center;
  margin: 0;
}
.sololab-baseline-callout .eyebrow {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--solo-mastery);
  margin-bottom: 0.85rem;
  font-family: var(--solo-font-head);
}
.sololab-baseline-callout h2 {
  font-family: var(--solo-font-head);
  font-weight: 700;
  font-size: clamp(1.5rem, 2.6vw, 2.1rem);
  letter-spacing: -0.01em;
  color: #F0FDFA;
  margin-bottom: 0.85rem;
}
.sololab-baseline-callout p {
  color: rgba(240, 253, 250, 0.75);
  font-family: var(--solo-font-body);
  font-size: 1rem;
  line-height: 1.6;
  max-width: 540px;
  margin: 0 auto 1.75rem;
}
body.theme-solo .sololab-baseline-callout a,
.sololab-baseline-callout a {
  display: inline-block;
  background: var(--solo-mastery);
  color: #0F172A;
  font-family: var(--solo-font-head);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.01em;
  padding: 14px 26px;
  border-radius: var(--solo-radius-sm);
  text-decoration: none;
  transition: background var(--solo-fast) var(--solo-ease),
              box-shadow var(--solo-fast) var(--solo-ease),
              transform var(--solo-fast) var(--solo-ease);
}
body.theme-solo .sololab-baseline-callout a:hover,
.sololab-baseline-callout a:hover {
  background: #5EEAD4;
  color: #0F172A;
  box-shadow: 0 0 0 4px rgba(45, 212, 191, 0.28), var(--solo-shadow-2);
  transform: translateY(-1px);
}

/* ════════════════════════════════════════════════════════════════════════
   SKELETON LOADERS - reusable placeholder shimmer
   ────────────────────────────────────────────────────────────────────────
   Drop .solo-skel onto any element to render the soft slate shimmer.
   Helpers:
     .solo-skel--text     1em-tall line (defaults to 90% width)
     .solo-skel--title    larger heading line (1.4em, 60% width)
     .solo-skel--block    full-width 100px block
     .solo-skel--circle   round avatar / icon
     .solo-skel--card     padded card-shaped block with internal lines
     .solo-skel--btn      pill button shape
   Wrap a region in .solo-skel-region to compose multi-line layouts.
   Replace skeletons with real content by removing the .solo-skel class
   (or unmounting the placeholder element). prefers-reduced-motion users
   get a static placeholder - no shimmer animation.
   ════════════════════════════════════════════════════════════════════════ */

@keyframes solo-skel-shimmer {
  0%   { background-position: -160% 0; }
  100% { background-position:  260% 0; }
}

.solo-skel {
  position: relative;
  display: block;
  background-color: #E2E8F0;                             /* slate-200 base */
  background-image: linear-gradient(
    90deg,
    rgba(226, 232, 240, 0) 0%,
    rgba(248, 250, 252, 0.85) 50%,
    rgba(226, 232, 240, 0) 100%
  );
  background-size: 200% 100%;
  background-repeat: no-repeat;
  background-position: -160% 0;
  border-radius: 6px;
  color: transparent !important;
  -webkit-user-select: none;
  user-select: none;
  pointer-events: none;
  animation: solo-skel-shimmer 1.4s ease-in-out infinite;
  overflow: hidden;
}
.solo-skel * { visibility: hidden; }

.solo-skel--text   { width: 90%; height: 1em;    margin: 0.35em 0; border-radius: 4px; }
.solo-skel--text.short { width: 55%; }
.solo-skel--text.full  { width: 100%; }
.solo-skel--title  { width: 60%; height: 1.4em;  margin: 0.5em 0;  border-radius: 6px; }
.solo-skel--block  { width: 100%; height: 100px;                  border-radius: 10px; }
.solo-skel--circle { width: 40px; height: 40px;                   border-radius: 50%; flex-shrink: 0; }
.solo-skel--btn    { display: inline-block; width: 120px; height: 38px; border-radius: 999px; }

.solo-skel-card {
  background: var(--solo-bg-elevated);
  border: 1px solid var(--solo-divider, #E2E8F0);
  border-radius: 12px;
  padding: 1.1rem 1.2rem;
  box-shadow: var(--solo-shadow-1, 0 1px 2px rgba(15,23,42,0.04));
}
.solo-skel-card .solo-skel { background-color: #EEF2F7; }

@media (prefers-reduced-motion: reduce) {
  .solo-skel { animation: none; background-image: none; }
}

/* ════════════════════════════════════════════════════════════════════════
   BUTTON VISUAL FEEDBACK - .solo-btn drop-in
   ────────────────────────────────────────────────────────────────────────
   Adds press depression + focus ring + loading state to any button. To
   show a spinner mid-action, set [data-loading="true"] on the button -
   the existing label is hidden and a 16px spinner spins in its place.
   Buttons keep their width while loading so the layout doesn't jump.
   ════════════════════════════════════════════════════════════════════════ */

@keyframes solo-btn-spin {
  to { transform: rotate(360deg); }
}

button.solo-btn,
.solo-btn {
  position: relative;
  cursor: pointer;
  transition:
    transform 90ms var(--solo-ease, ease-out),
    box-shadow 120ms var(--solo-ease, ease-out),
    background-color 120ms var(--solo-ease, ease-out),
    filter 120ms var(--solo-ease, ease-out);
  will-change: transform;
}
button.solo-btn:hover:not(:disabled):not([data-loading="true"]),
.solo-btn:hover:not(:disabled):not([data-loading="true"]) {
  filter: brightness(1.04);
}
button.solo-btn:active:not(:disabled):not([data-loading="true"]),
.solo-btn:active:not(:disabled):not([data-loading="true"]) {
  transform: translateY(1px) scale(0.985);
  filter: brightness(0.96);
}
button.solo-btn:focus-visible,
.solo-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(45, 212, 191, 0.45);
}
button.solo-btn:disabled,
.solo-btn:disabled,
button.solo-btn[aria-disabled="true"],
.solo-btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
  filter: grayscale(0.4);
}
button.solo-btn[data-loading="true"],
.solo-btn[data-loading="true"] {
  cursor: progress;
  pointer-events: none;
}
button.solo-btn[data-loading="true"] > *,
.solo-btn[data-loading="true"] > * {
  visibility: hidden;
}
button.solo-btn[data-loading="true"]::after,
.solo-btn[data-loading="true"]::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 16px; height: 16px;
  margin: -8px 0 0 -8px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: solo-btn-spin 0.7s linear infinite;
  visibility: visible !important;
  opacity: 0.9;
}
@media (prefers-reduced-motion: reduce) {
  button.solo-btn,
  .solo-btn { transition: none; }
  button.solo-btn[data-loading="true"]::after,
  .solo-btn[data-loading="true"]::after { animation: none; }
}

/* Tap-target ripple - subtle pulse on click for ALL buttons that opt in via
   class .solo-btn. Doesn't fire while loading or disabled. Uses a single
   animated ::before pseudo so it costs almost nothing. */
@keyframes solo-btn-ripple {
  0%   { transform: scale(0.4); opacity: 0.35; }
  100% { transform: scale(2.6); opacity: 0; }
}
.solo-btn[data-rippling]::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: currentColor;
  opacity: 0.18;
  pointer-events: none;
  animation: solo-btn-ripple 480ms ease-out forwards;
}

/* ════════════════════════════════════════════════════════════════════════
   SoloA11y - accessibility panel + applied modes
   ────────────────────────────────────────────────────────────────────────
   - .a11y-dyslexic on <html>          → switches base font to OpenDyslexic
   - .a11y-soc on <html>               → hover cursor + soft outline on speakables
   - .a11y-speaking on an element      → brief teal flash while it's being read
   - #a11y-panel                       → centred modal with all controls
   - #a11y-sel-pill                    → floating "Play" pill near selection
   ════════════════════════════════════════════════════════════════════════ */

@font-face {
  font-family: 'OpenDyslexic';
  src: url('https://cdn.jsdelivr.net/npm/opendyslexic@1.0.3/woff/OpenDyslexic-Regular.woff') format('woff');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'OpenDyslexic';
  src: url('https://cdn.jsdelivr.net/npm/opendyslexic@1.0.3/woff/OpenDyslexic-Bold.woff') format('woff');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

html.a11y-dyslexic,
html.a11y-dyslexic body,
html.a11y-dyslexic p,
html.a11y-dyslexic li,
html.a11y-dyslexic h1,
html.a11y-dyslexic h2,
html.a11y-dyslexic h3,
html.a11y-dyslexic h4,
html.a11y-dyslexic h5,
html.a11y-dyslexic h6,
html.a11y-dyslexic .subunit-body,
html.a11y-dyslexic .quickcheck-q,
html.a11y-dyslexic input,
html.a11y-dyslexic textarea,
html.a11y-dyslexic button,
html.a11y-dyslexic label {
  font-family: 'OpenDyslexic', 'Atkinson Hyperlegible', system-ui, sans-serif !important;
  letter-spacing: 0.01em;
}

/* Speak-on-click visual affordance - shows a subtle dotted underline on
   text blocks so users know the click target. Light enough not to feel noisy. */
html.a11y-soc p,
html.a11y-soc li,
html.a11y-soc h1,
html.a11y-soc h2,
html.a11y-soc h3,
html.a11y-soc h4,
html.a11y-soc [data-speakable] {
  cursor: pointer;
  position: relative;
}
html.a11y-soc p:hover,
html.a11y-soc li:hover,
html.a11y-soc h1:hover,
html.a11y-soc h2:hover,
html.a11y-soc h3:hover,
html.a11y-soc h4:hover,
html.a11y-soc [data-speakable]:hover {
  background: rgba(45, 212, 191, 0.06);
  border-radius: 4px;
}

.a11y-speaking {
  background: rgba(252, 211, 77, 0.25) !important;
  transition: background 200ms ease;
  border-radius: 4px;
}

/* Panel */
#a11y-panel {
  position: fixed; inset: 0; z-index: 9700;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
}
#a11y-panel[hidden] { display: none; }
#a11y-panel .a11y-backdrop {
  position: absolute; inset: 0;
  background: rgba(15, 23, 42, 0.55);
  backdrop-filter: blur(2px);
}
#a11y-panel .a11y-card {
  position: relative;
  background: var(--solo-bg-elevated);
  border-radius: 16px;
  max-width: 520px; width: 100%;
  max-height: 90vh; overflow-y: auto;
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.35);
}
.a11y-card-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1.1rem 1.4rem;
  border-bottom: 1px solid var(--solo-divider, #E2E8F0);
}
.a11y-card-head h2 {
  margin: 0; font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-size: 1.15rem; color: var(--solo-heading-color, var(--solo-navy, #0F172A));
}
.a11y-close {
  background: transparent; border: none; cursor: pointer;
  font-size: 1.6rem; line-height: 1; color: var(--solo-text-mute, #64748B);
  padding: 0 0.4rem; border-radius: 6px;
}
.a11y-close:hover { background: var(--solo-bg); }
.a11y-card-foot {
  padding: 1rem 1.4rem;
  border-top: 1px solid var(--solo-divider, #E2E8F0);
  text-align: right;
}
.a11y-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 1rem;
  padding: 1rem 1.4rem;
  border-bottom: 1px solid var(--solo-divider, #E2E8F0);
}
.a11y-row:last-of-type { border-bottom: none; }
.a11y-row-title {
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-weight: 600; font-size: 0.95rem;
  color: var(--solo-heading-color, var(--solo-navy, #0F172A));
}
.a11y-row-sub {
  font-size: 0.82rem; color: var(--solo-text-mute, #64748B);
  margin-top: 0.2rem;
}
.a11y-row-action {
  display: inline-flex; align-items: center; gap: 0.5rem;
}
.a11y-btn {
  background: #F1F5F9; /* darkmode-ok */ color: #1E293B;
  border: 1px solid var(--solo-divider, #E2E8F0);
  border-radius: 999px; /* PILL - locked button-shape rule */
  padding: 0.45rem 0.85rem;
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-size: 0.85rem; font-weight: 600;
  cursor: pointer;
  transition: background 120ms ease, transform 90ms ease;
}
.a11y-btn:hover { background: #E2E8F0; }
.a11y-btn:active { transform: scale(0.97); }
.a11y-btn.primary { background: #2DD4BF; color: #0F172A; border-color: #14B8A6; }
.a11y-btn.primary:hover { background: #5EEAD4; }
.a11y-btn.ghost { background: transparent; border-color: var(--solo-divider, #E2E8F0); }
.a11y-font-current {
  min-width: 3.5rem; text-align: center;
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-weight: 700; color: var(--solo-heading-color, var(--solo-navy, #0F172A));
}
.a11y-select, #a11y-rate {
  border: 1px solid var(--solo-divider, #E2E8F0);
  border-radius: 6px;
  padding: 0.4rem 0.5rem;
  font-family: inherit; font-size: 0.9rem;
  max-width: 220px;
}
.a11y-toggle {
  position: relative; display: inline-block;
  width: 44px; height: 24px;
}
.a11y-toggle input { opacity: 0; width: 0; height: 0; }
.a11y-toggle-track {
  position: absolute; inset: 0;
  background: #CBD5E1; border-radius: 999px;
  transition: background 160ms ease;
  cursor: pointer;
}
.a11y-toggle-knob {
  position: absolute; top: 3px; left: 3px;
  width: 18px; height: 18px;
  background: #fff; /* darkmode-ok */ border-radius: 50%;
  transition: transform 160ms ease;
  box-shadow: 0 1px 2px rgba(0,0,0,0.2);
}
.a11y-toggle input:checked + .a11y-toggle-track { background: #2DD4BF; }
.a11y-toggle input:checked + .a11y-toggle-track .a11y-toggle-knob { transform: translateX(20px); }

@media (max-width: 540px) {
  .a11y-row { grid-template-columns: 1fr; gap: 0.5rem; }
  .a11y-row-action { justify-content: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  .a11y-speaking, .a11y-toggle-track, .a11y-toggle-knob,
  .a11y-btn { transition: none; }
}

/* ════════════════════════════════════════════════════════════════════════
   DARK-MODE LAB / GAME CARD OVERRIDES
   ────────────────────────────────────────────────────────────────────────
   Per-lab CSS files (rp3-lab.css, rp6-lab.css, mastery-exam-technique.css,
   mastery-games.css, solo-quiz-shell.css) hard-code white `#fff` on
   their card surfaces. In dark mode that left bright-white panels glaring
   on a dark page - jarring for ND/dyslexic students who switch themes.
   This block remaps those surfaces to the elevated-bg variable so the
   theme swap actually flows through. Targeted class names only - leaves
   intentionally-white surfaces (scientific drawing canvases, eyepiece
   views, PDF-preview panels) untouched.
   ════════════════════════════════════════════════════════════════════════ */
body.dark-mode .rp3-shelf-item,
body.dark-mode .rp3-bench-item,
body.dark-mode .rp3-results-table,
body.dark-mode .rp3-lab-card,
body.dark-mode .rp6-card,
body.dark-mode .rp6-stage,
body.dark-mode .rp6-results,
body.dark-mode .me-card,
body.dark-mode .me-slide,
body.dark-mode .mg-card,
body.dark-mode .mg-stage,
body.dark-mode .mg-tile,
body.dark-mode .sq-question-card,
body.dark-mode .sq-results-card,
body.dark-mode .lab-card,
body.dark-mode .gate-q,
body.dark-mode .gate-q__opt,
body.dark-mode .step-pill,
body.dark-mode .rs-mission,
body.dark-mode .rs-mastery {
  background: var(--solo-bg-elevated, #1F2A3D) !important;
  color: var(--solo-text, #E2E8F0);
  border-color: var(--solo-divider, #334155);
}
body.dark-mode .gate-q { background: #1A2433 !important; }
body.dark-mode .gate-q__opt { background: var(--solo-bg-elevated, #1F2A3D) !important; }

/* Mission "X complete - revisit it any time!" sits on a gradient in light
   mode. In dark mode flatten the gradient so it reads as a calm panel. */
body.dark-mode .rs-mission,
body.dark-mode .rs-mastery {
  background: linear-gradient(135deg, #1F2A3D 0%, #182232 100%) !important;
}

/* SoloQuiz results-background colour swatches: in dark mode flip the
   default "white" choice to "dark elevated" so a learner who has never
   set a custom background isn't blinded after results render. */
body.dark-mode .results-shell[style*="#ffffff"],
body.dark-mode .results-shell:not([data-bg-customised]) {
  background: var(--solo-bg-elevated, #1F2A3D) !important;
  color: var(--solo-text, #E2E8F0);
}


/* ─── Per-unit SoloCognition CTA banner on each hub ─────────
   Sits directly after the cbh-hero on every Biology/Chemistry/
   Physics unit hub. Routes the student to <unit>-quiz.html for
   adaptive sampling of that unit only. */
.cbh-quiz-cta {
  padding: 0 1.5rem;
  margin: 1.2rem 0 0.4rem;
}
.cbh-quiz-cta-inner {
  max-width: 1200px;        /* match .cbh-hero-inner / .cbh-resume-hero so the
                               banner lines up with the rest of the page */
  margin: 0 auto;
  background: linear-gradient(135deg, #FFFFFF 0%, var(--solo-mastery-pale, #F0FDFA) 100%);
  border: 1px solid var(--solo-mastery, #2DD4BF);
  border-radius: 14px;
  padding: 1rem 1.25rem;
  display: flex; gap: 1.2rem;
  align-items: center; justify-content: space-between;
  flex-wrap: wrap;
  box-shadow: 0 1px 3px rgba(15,23,42,.04);
}
.cbh-quiz-cta-eyebrow {
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-weight: 700; font-size: .72rem;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--solo-mastery-deep, #14B8A6);
  margin: 0 0 .25rem;
}
.cbh-quiz-cta-eyebrow::before {
  content: ''; display: inline-block;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--solo-mastery, #2DD4BF);
  box-shadow: 0 0 0 3px rgba(45, 212, 191, 0.22);
  margin-right: .55rem; vertical-align: middle;
}
.cbh-quiz-cta-lede {
  font-family: var(--solo-font-body, 'Atkinson Hyperlegible', system-ui, sans-serif);
  color: var(--solo-text, #334155);
  font-size: .95rem; line-height: 1.45;
  margin: 0; max-width: 56ch;
}
.cbh-quiz-cta-btn {
  flex-shrink: 0;
  background: var(--solo-mastery, #2DD4BF);
  color: #0F172A;
  border: 1.5px solid var(--solo-mastery-deep, #14B8A6);
  border-radius: 999px;
  padding: .65rem 1.2rem;
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-weight: 700; font-size: .85rem;
  text-decoration: none;
  transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
  display: inline-flex; align-items: center; gap: .4rem;
}
.cbh-quiz-cta-btn:hover {
  transform: translateY(-1px);
  background: var(--solo-mastery-deep, #14B8A6);
  color: #FFFFFF;
  box-shadow: 0 4px 12px rgba(15,118,110,.25);
}
.cbh-quiz-cta-btn:focus-visible {
  outline: 3px solid var(--solo-mastery, #2DD4BF);
  outline-offset: 3px;
}
@media (max-width: 640px) {
  .cbh-quiz-cta-inner { padding: .9rem 1rem; }
  .cbh-quiz-cta-btn   { width: 100%; justify-content: center; }
}
/* The generic `body.theme-solo a` link rule (specificity 0,1,2) outranks the
   plain `.cbh-quiz-cta-btn` colour above (0,1,0), tinting the pill text to the
   theme link colour and producing low-contrast colour-on-colour text. Match
   the Enter-the-lab CTA (.cbh-jump-cta) by using the same high-specificity
   selector + navy heading colour, so every pill reads at full contrast. */
body.theme-solo a.cbh-quiz-cta-btn { color: var(--solo-heading-color, var(--solo-navy, #0F172A)); }
body.theme-solo a.cbh-quiz-cta-btn:hover { color: #FFFFFF; }

/* ─── Tier toggle: HT-only sections + HT badge ───────────────
   Foundation students see HT-tagged resource-page sections as a
   closed "Higher tier extension" card with a Peek button that
   reveals the section inline (interactives stay disabled so the
   peek is preview-only). Higher students see HT sections rendered
   normally with a small "HT" badge in the title. */
.rs-tier-badge {
  display: inline-flex; align-items: center;
  padding: .12rem .45rem; border-radius: 999px;
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-weight: 800; font-size: .58rem;
  letter-spacing: .12em; text-transform: uppercase;
  vertical-align: middle;
  margin-left: .4rem;
}
.rs-tier-badge--ht {
  color: #6D28D9;
  background: #EDE9FE;
  border: 1px solid #C4B5FD;
}
.rs-ht-peek {
  background: linear-gradient(135deg, #FFFFFF 0%, #F5F3FF 100%);
  border: 1.5px solid #C4B5FD;
  border-radius: 14px;
  padding: 1rem 1.2rem;
  margin: .75rem 0;
}
.rs-ht-peek-head {
  display: flex; gap: 1rem; align-items: center;
  flex-wrap: wrap;
}
.rs-ht-peek-badge {
  flex-shrink: 0;
  padding: .25rem .6rem; border-radius: 999px;
  background: #6D28D9; color: #FFFFFF;
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-weight: 700; font-size: .68rem;
  letter-spacing: .12em; text-transform: uppercase;
}
.rs-ht-peek-lede {
  flex: 1; min-width: 16ch;
  color: var(--solo-text, #334155);
  font-size: .9rem; line-height: 1.45;
  margin: 0;
}
.rs-ht-peek-btn {
  flex-shrink: 0;
  background: #FFFFFF; /* darkmode-ok */
  color: #6D28D9;
  border: 1.5px solid #6D28D9;
  border-radius: 999px;
  padding: .5rem 1rem;
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-weight: 700; font-size: .8rem;
  cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.rs-ht-peek-btn:hover { background: #6D28D9; color: #FFFFFF; }
.rs-ht-peek.is-open  .rs-ht-peek-body {
  margin-top: 1rem; padding-top: 1rem;
  border-top: 1px dashed #C4B5FD;
}
.rs-ht-peek-body { opacity: .85; }
.rs-ht-peek-body * { pointer-events: none !important; }
.rs-ht-peek-body input, .rs-ht-peek-body button, .rs-ht-peek-body textarea {
  pointer-events: none !important; opacity: .7;
}

/* ─── HT card badge (hub cards for Higher-tier sub-units) ──────
   solo-ht-badges.js scans hub-card links and injects a small "HT"
   badge into each card whose sub-unit has Higher-tier extensions.
   Foundation students never see these. */
.solo-ht-card-badge {
  display: inline-flex; align-items: center;
  padding: .1rem .4rem; border-radius: 999px;
  background: #6D28D9; color: #FFFFFF;
  font-family: var(--solo-font-head, 'Lexend', sans-serif);
  font-weight: 800; font-size: .56rem;
  letter-spacing: .14em; text-transform: uppercase;
  vertical-align: middle;
  margin-left: .35rem;
  flex-shrink: 0;
  /* Slight glow so the badge reads against busy card backgrounds */
  box-shadow: 0 0 0 1px rgba(255,255,255,0.4);
}
.solo-ht-card-decorated { position: relative; }
@media (prefers-reduced-motion: no-preference) {
  .solo-ht-card-badge {
    transition: background .12s ease, transform .12s ease;
  }
  .solo-ht-card-decorated:hover .solo-ht-card-badge {
    background: #5B21B6;
    transform: scale(1.06);
  }
}


/* ════════════════════════════════════════════════════════════════════════
   CANONICAL MARKETING HERO  (added 2026-06-11)
   ────────────────────────────────────────────────────────────────────────
   Previously every landing/marketing page (about, pricing, contact,
   how-it-works, sololabs-overview, baseline, resources) re-defined
   the same hero pattern under a different class name (.about-sc-hero,
   .pr-hero, .sololabs-hero, .pricing-hero, etc.). That's how the
   "teal dot + uppercase eyebrow + big H1" rhythm started drifting -
   each redefinition added or trimmed something.

   ONE canonical class set, used by every marketing/landing hero:

       <div class="solo-marketing-hero">
         <div class="solo-marketing-hero-inner">
           <div class="hero-eyebrow">PAGE NAME</div>
           <h1>The marketing line.</h1>
           <p>The subtitle.</p>
         </div>
       </div>

   New marketing pages should use these classes directly. Page-specific
   CSS files no longer need to redefine the hero - they only own the
   page's bespoke content below the hero.
   ════════════════════════════════════════════════════════════════════════ */

.solo-marketing-hero {
  background:
    radial-gradient(ellipse 900px 540px at 50% 30%, rgba(45, 212, 191, 0.14) 0%, transparent 70%),
    linear-gradient(180deg, var(--solo-bg) 0%, #FFFFFF 100%);
  padding: 4.75rem 1.5rem 3.5rem;
  border-bottom: 1px solid rgba(45, 212, 191, 0.45);
  text-align: center;
}
.solo-marketing-hero-inner {
  max-width: 820px;
  margin: 0 auto;
}
.solo-marketing-hero .hero-eyebrow {
  display: inline-flex; align-items: center;
  background: transparent; border: none; padding: 0; box-shadow: none;
  font-family: var(--solo-font-head);
  font-size: 0.78rem; font-weight: 700;
  color: var(--solo-mastery-deep);
  letter-spacing: 0.12em; text-transform: uppercase;
  margin-bottom: 1.15rem;
}
.solo-marketing-hero .hero-eyebrow::before {
  content: '';
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--solo-mastery);
  box-shadow: 0 0 0 3px rgba(45, 212, 191, 0.25);
  margin-right: 0.55rem;
}
.solo-marketing-hero h1 {
  font-family: var(--solo-font-head);
  font-weight: 700;
  font-size: clamp(2.3rem, 5.2vw, 3.6rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--solo-heading-color, var(--solo-navy));
  margin: 0 auto 1.2rem;
  max-width: 18ch;
}
.solo-marketing-hero p,
.solo-marketing-hero .hero-sub {
  font-family: var(--solo-font-body);
  font-size: clamp(1rem, 1.3vw, 1.15rem);
  line-height: 1.6;
  color: var(--solo-text);
  max-width: 56ch;
  margin: 0 auto;
}
