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

html { -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--f-sans);
  background: var(--c-paper);
  color: var(--c-ink);
  line-height: 1.55;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

/* Prevent any descendant from forcing the whole document wider than the viewport.
   Per-component overflow handlers (.formula, .table-scroll) opt back in to
   horizontal scrolling locally where genuinely needed. */
img, svg, video, canvas { max-width: 100%; }

/* ---------- Decorative paper background ---------- */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  background-image:
    radial-gradient(circle at 12% 18%, rgba(255, 107, 74, 0.08), transparent 35%),
    radial-gradient(circle at 88% 8%, rgba(43, 111, 230, 0.07), transparent 40%),
    radial-gradient(circle at 80% 92%, rgba(123, 91, 217, 0.06), transparent 38%);
  pointer-events: none;
  z-index: 0;
}

main, header, footer { position: relative; z-index: 1; }

/* ---------- Typography ---------- */
h1, h2, h3, h4 { font-family: var(--f-display); font-weight: 600; letter-spacing: -0.01em; line-height: 1.15; }
h1 { font-size: clamp(2rem, 4.5vw, 3.4rem); }
h2 { font-size: clamp(1.6rem, 3vw, 2.2rem); }
h3 { font-size: 1.25rem; font-weight: 600; }

a { color: var(--c-blue-deep); text-decoration: none; }
a:hover { text-decoration: underline; }

.mono { font-family: var(--f-mono); }

/* ---------- Layout ---------- */
.container { max-width: 1200px; margin: 0 auto; padding: 0 var(--sp-5); }

.site-header {
  padding: var(--sp-5) 0;
  border-bottom: 1px solid var(--c-line);
  background: rgba(255, 248, 238, 0.85);
  backdrop-filter: blur(8px);
  position: sticky; top: 0; z-index: 50;
}
.site-header .row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap; }
.brand { display: flex; align-items: center; gap: var(--sp-3); font-family: var(--f-display); font-size: 1.4rem; font-weight: 600; }
.brand-mark {
  width: 38px; height: 38px; border-radius: var(--r-md);
  background: linear-gradient(135deg, var(--c-coral), var(--c-purple));
  display: grid; place-items: center; color: white; font-weight: 700;
  box-shadow: var(--shadow-md);
}
.brand-tag { color: var(--c-ink-soft); font-family: var(--f-sans); font-size: 0.85rem; font-weight: 500; }

/* Header "All courses" back-link — coral-tinted accent pill that signals
   "go up to parent". Visible only when a course is active. Solid-fill on
   hover follows the GitHub / Linear secondary-with-accent-hover pattern.
   Mobile (≤640 px): label collapses; icon stays so the pill keeps a
   recognisable affordance even when the header wraps. */
.nav-home {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px;
  border: 1.5px solid var(--c-coral);
  border-radius: var(--r-pill);
  background: rgba(255, 107, 74, 0.10);
  color: var(--c-coral-deep);
  font-size: 0.85rem; font-weight: 600; line-height: 1;
  text-decoration: none; white-space: nowrap;
  transition: color var(--t-fast), border-color var(--t-fast), background var(--t-fast), transform var(--t-fast);
}
.nav-home:hover {
  background: var(--c-coral); color: white;
  border-color: var(--c-coral-deep);
  text-decoration: none;
  transform: translateX(-1px);
}
.nav-home:hover svg { transform: translateX(-2px); }
.nav-home:active { transform: translateX(-1px) scale(0.97); }
.nav-home:focus-visible { outline: 2px solid var(--c-blue); outline-offset: 2px; }
.nav-home svg { flex-shrink: 0; transition: transform var(--t-fast); }
.nav-home[hidden] { display: none; }

.search {
  display: flex; align-items: center; gap: var(--sp-2);
  background: white; border: 1.5px solid var(--c-line); padding: 8px 14px;
  border-radius: var(--r-pill); width: 280px; max-width: 100%;
  flex: 1 1 220px; min-width: 0;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.search:focus-within { border-color: var(--c-blue); box-shadow: 0 0 0 4px rgba(43, 111, 230, 0.12); }
.search input { border: 0; outline: none; flex: 1; font-size: 0.95rem; background: transparent; color: var(--c-ink); }
.search svg { flex-shrink: 0; color: var(--c-muted); }

/* ---------- Hero ---------- */
.hero { padding: var(--sp-7) 0 var(--sp-6); text-align: center; }
.hero h1 { margin-bottom: var(--sp-3); }
.hero h1 .accent { background: linear-gradient(120deg, var(--c-coral), var(--c-purple)); -webkit-background-clip: text; background-clip: text; color: transparent; }
.hero p { color: var(--c-ink-soft); max-width: 640px; margin: 0 auto; font-size: 1.05rem; }
.hero-stats { display: flex; gap: var(--sp-6); justify-content: center; margin-top: var(--sp-5); flex-wrap: wrap; }
.hero-stat { display: flex; flex-direction: column; align-items: center; }
.hero-stat strong { font-family: var(--f-display); font-size: 2rem; line-height: 1; color: var(--c-coral-deep); }
.hero-stat span { color: var(--c-muted); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.08em; }

/* ---------- Unit sections ---------- */
.unit-section { margin: var(--sp-7) 0; }
.unit-head { display: flex; align-items: baseline; gap: var(--sp-4); margin-bottom: var(--sp-5); flex-wrap: wrap; }
.unit-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: var(--r-pill); font-size: 0.78rem; font-weight: 600;
  background: var(--c-paper-soft); color: var(--c-ink);
  border: 1px solid var(--c-line);
}
.unit-chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--unit-color, var(--c-coral)); }
.unit-head h2 { color: var(--c-ink); }
.unit-count { color: var(--c-muted); font-size: 0.95rem; margin-left: auto; }

/* ---------- Practical card ---------- */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--sp-4); }

.card {
  background: white; border: 1px solid var(--c-line);
  border-radius: var(--r-lg); padding: var(--sp-5);
  display: flex; flex-direction: column; gap: var(--sp-3);
  position: relative; overflow: hidden;
  transition: transform var(--t-base) var(--ease-out), box-shadow var(--t-base), border-color var(--t-base);
  text-decoration: none; color: inherit;
}
.card:hover { text-decoration: none; }
.card.is-active:hover {
  transform: translateY(-4px) rotate(-0.4deg);
  box-shadow: var(--shadow-lg);
  border-color: var(--unit-color, var(--c-coral));
}
.card.is-locked { opacity: 0.65; cursor: not-allowed; }
.card-num {
  font-family: var(--f-display); font-size: 2.4rem; font-weight: 600;
  color: var(--unit-color, var(--c-coral)); line-height: 1;
}
.card-title { font-size: 1.05rem; font-weight: 600; line-height: 1.3; }
.card-foot { display: flex; align-items: center; justify-content: space-between; margin-top: auto; font-size: 0.85rem; color: var(--c-muted); }
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: var(--r-pill); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.02em;
}
.badge.badge-live { background: rgba(60, 179, 113, 0.12); color: var(--c-green-deep); }
.badge.badge-soon { background: var(--c-paper-soft); color: var(--c-muted); }
.card.is-active::after {
  content: "→"; position: absolute; right: 18px; bottom: 14px; font-size: 1.4rem;
  color: var(--unit-color, var(--c-coral)); opacity: 0;
  transform: translateX(-8px);
  transition: opacity var(--t-base), transform var(--t-base);
}
.card.is-active:hover::after { opacity: 1; transform: translateX(0); }

/* ---------- Course picker (root URL with no syllabus chosen) ---------- */
.picker-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--sp-5);
  margin: var(--sp-7) 0;
}
.picker-card {
  background: white; border: 1.5px solid var(--c-line);
  border-radius: var(--r-lg); padding: var(--sp-6);
  display: flex; flex-direction: column; gap: var(--sp-3);
  position: relative; overflow: hidden;
  transition: transform var(--t-base) var(--ease-out), box-shadow var(--t-base), border-color var(--t-base);
  text-decoration: none; color: inherit;
  min-height: 220px;
}
.picker-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 5px;
  background: var(--course-accent, linear-gradient(135deg, var(--c-coral), var(--c-purple)));
}
.picker-card:not(.is-locked):hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: transparent;
  text-decoration: none;
}
.picker-card.is-locked { opacity: 0.55; cursor: not-allowed; }
.picker-mark {
  width: 56px; height: 56px; border-radius: var(--r-md);
  background: var(--course-accent, linear-gradient(135deg, var(--c-coral), var(--c-purple)));
  display: grid; place-items: center; color: white;
  font-family: var(--f-display); font-size: 1.8rem; font-weight: 700;
  box-shadow: var(--shadow-md);
  margin-top: 6px;
}
.picker-label { font-family: var(--f-display); font-size: 1.5rem; font-weight: 600; line-height: 1.2; color: var(--c-ink); }
.picker-tag { font-size: 0.92rem; color: var(--c-ink-soft); }
.picker-foot { margin-top: auto; }

/* ---------- Practical page layout (sidebar + content) ----------

   Goal: the practical content keeps its full container width — the SVG
   animation stage in particular must NOT shrink because the sidebar is
   visible. So the sidebar is positioned `fixed` in the left viewport
   gutter (outside the centred 1200 px container) only when the viewport
   is wide enough to fit it without overlapping the content. Below that
   threshold the sidebar collapses to a drawer triggered by the
   "Jump to practical" button. */
.practical-layout {
  position: relative;
}
.practical-content { min-width: 0; }

/* Sidebar — fixed in the left viewport gutter on wide screens. Hidden by
   default; revealed only when the gutter has room or when the drawer is
   opened. Width clamps to at most 280 px and at least the available gutter
   minus a small breathing margin, so it never overlaps the container. */
.practical-nav-sidebar {
  display: none;
  background: white;
  border: 1px solid var(--c-line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  font-size: 0.92rem;
}
@media (min-width: 1700px) {
  .practical-nav-sidebar {
    display: flex; flex-direction: column;
    position: fixed;
    top: calc(var(--sp-5) + 90px);
    left: max(16px, calc((100vw - 1200px) / 2 - 296px));
    width: min(280px, calc((100vw - 1200px) / 2 - 32px));
    max-height: calc(100vh - 130px);
    /* Apple-style spring-out — translate + fade, with a slight scale so the
       motion has body. Used by both directions (collapse + expand). */
    transform: translateX(0) scale(1);
    opacity: 1;
    transform-origin: left center;
    transition: transform 380ms cubic-bezier(0.32, 0.72, 0, 1),
                opacity 240ms cubic-bezier(0.32, 0.72, 0, 1);
    will-change: transform, opacity;
  }
  .practical-layout.is-sidebar-collapsed .practical-nav-sidebar {
    transform: translateX(calc(-100% - 24px)) scale(0.96);
    opacity: 0;
    pointer-events: none;
  }
}

/* While the page is initialising, suppress every transition on the sidebar
   chrome so the persisted state lands instantly without a stale frame
   playing back the default-state animation. shell.js drops the attribute
   on the next animation frame, after which user-initiated toggles animate
   normally. */
.practical-layout[data-sidebar-init] .practical-nav-sidebar,
.practical-layout[data-sidebar-init] .nav-rail-show,
.practical-layout[data-sidebar-init] .nav-side-collapse {
  transition: none !important;
  animation: none !important;
}

/* ---------- Page loader (practical pages) ----------

   A full-viewport overlay shown immediately while shell.js fetches the
   practical's module, builds the sidebar, applies localised chrome strings
   and renders the SVG stage. Without it the student sees a sequence of
   intermediate paints (sidebar appearing, brand text changing, footer
   updating, content swapping in). The overlay gates all of that behind a
   single fade-out so the final state is what they perceive as "the page". */
#page-loader {
  position: fixed; inset: 0;
  z-index: 1000;
  display: grid; place-items: center;
  background: var(--c-paper);
  /* Same delay as opacity so the element keeps blocking pointer events
     for the full duration of the fade, then is removed from the a11y
     tree once invisible. */
  transition: opacity 320ms cubic-bezier(0.32, 0.72, 0, 1),
              visibility 0s linear 320ms;
  opacity: 1; visibility: visible;
}
#page-loader.is-hidden {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.page-loader-card {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--sp-3);
}
.page-loader-spinner {
  width: 44px; height: 44px;
  border: 3px solid rgba(255, 107, 74, 0.18);
  border-top-color: var(--c-coral);
  border-radius: 50%;
  animation: page-loader-spin 720ms linear infinite;
}
.page-loader-text {
  font-family: var(--f-sans);
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--c-ink-soft);
  letter-spacing: 0.02em;
}
@keyframes page-loader-spin {
  to { transform: rotate(360deg); }
}
/* Respect reduced-motion — drop the spinning animation but keep the dot. */
@media (prefers-reduced-motion: reduce) {
  .page-loader-spinner { animation: none; }
}

/* Floating "show practicals" affordance — appears after the sidebar slides
   away. Designed as a slim vertical card that hugs the left container edge
   so it reads as the same UI element the sidebar belonged to (instead of a
   stray button). Coral accent only on hover so it doesn't pull attention
   from the apparatus. */
.nav-rail-show {
  display: none;
  flex-direction: column; align-items: center;
  gap: 8px;
  position: fixed;
  top: calc(var(--sp-5) + 90px);
  left: max(16px, calc((100vw - 1200px) / 2 - 64px));
  padding: 12px 8px;
  width: 44px;
  border: 1px solid var(--c-line);
  border-radius: 14px;
  background: white;
  color: var(--c-ink-soft);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: color 180ms ease-out, border-color 180ms ease-out,
              background 180ms ease-out, transform 180ms cubic-bezier(0.32, 0.72, 0, 1),
              box-shadow 200ms ease-out;
}
.nav-rail-show:hover {
  color: var(--c-coral-deep);
  border-color: var(--c-coral);
  transform: translateX(2px);
  box-shadow: 0 4px 14px rgba(255, 107, 74, 0.18);
}
.nav-rail-show:focus-visible { outline: 2px solid var(--c-blue); outline-offset: 2px; }
.nav-rail-show svg { flex-shrink: 0; }
.nav-rail-show .nav-rail-show-label {
  /* Vertically-rotated label — reads bottom-up like the spine of a book.
     Keeps the affordance compact (44 px wide) yet self-explanatory. */
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  white-space: nowrap;
  margin-top: 2px;
}

@media (min-width: 1700px) {
  .practical-layout.is-sidebar-collapsed .nav-rail-show {
    display: inline-flex;
    animation: nav-rail-show-in 360ms cubic-bezier(0.32, 0.72, 0, 1) 120ms both;
  }
}
@keyframes nav-rail-show-in {
  from { transform: translateX(-12px) scale(0.92); opacity: 0; }
  to   { transform: translateX(0)     scale(1);    opacity: 1; }
}

/* Collapse button inside the sidebar header — chevron rotates with state. */
.nav-side-collapse {
  appearance: none; -webkit-appearance: none;
  display: inline-grid; place-items: center;
  width: 28px; height: 28px;
  background: transparent; border: 1px solid transparent;
  border-radius: var(--r-md);
  color: var(--c-ink-soft);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast),
              border-color var(--t-fast);
}
.nav-side-collapse:hover {
  background: white; color: var(--c-coral-deep);
  border-color: var(--c-coral);
}
.nav-side-collapse:focus-visible { outline: 2px solid var(--c-blue); outline-offset: 2px; }
.nav-side-collapse svg { width: 14px; height: 14px; flex-shrink: 0; }

.nav-side-head {
  padding: var(--sp-4) var(--sp-4);
  border-bottom: 1px solid var(--c-line);
  background: var(--c-paper-soft);
  flex-shrink: 0;
}
.nav-side-head .row {
  display: flex; align-items: center; gap: var(--sp-3); justify-content: space-between;
}
.nav-side-title {
  font-family: var(--f-display); font-size: 1.05rem; font-weight: 600;
  color: var(--c-ink); line-height: 1.2;
}
.nav-side-count {
  font-size: 0.78rem; color: var(--c-muted);
  font-weight: 500; white-space: nowrap;
}
.nav-side-filter {
  display: flex; align-items: center; gap: 6px;
  margin-top: var(--sp-3);
  background: white;
  border: 1.5px solid var(--c-line);
  border-radius: var(--r-pill);
  padding: 5px 10px;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.nav-side-filter:focus-within { border-color: var(--c-blue); box-shadow: 0 0 0 3px rgba(43, 111, 230, 0.12); }
.nav-side-filter svg { color: var(--c-muted); flex-shrink: 0; }
.nav-side-filter input {
  border: 0; outline: none; flex: 1; min-width: 0;
  font-size: 0.85rem; background: transparent; color: var(--c-ink);
}

.nav-side-list {
  list-style: none; margin: 0; padding: var(--sp-2) 0;
  overflow-y: auto;
  flex: 1 1 auto;
  scrollbar-width: thin;
}
.nav-side-list::-webkit-scrollbar { width: 6px; }
.nav-side-list::-webkit-scrollbar-thumb { background: var(--c-line); border-radius: 4px; }

.nav-side-unit { padding: var(--sp-2) 0; }
.nav-side-unit + .nav-side-unit { border-top: 1px dashed var(--c-line); margin-top: 4px; }
.nav-side-unit-head {
  display: flex; align-items: center; gap: 8px;
  padding: 6px var(--sp-4);
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--c-muted);
}
.nav-side-unit-head .dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--unit-color, var(--c-coral)); flex-shrink: 0;
}

.nav-side-row {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 8px var(--sp-4);
  color: var(--c-ink-soft);
  text-decoration: none;
  border-left: 3px solid transparent;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
  line-height: 1.3;
}
.nav-side-row:hover {
  background: var(--c-paper-soft);
  color: var(--c-ink);
  text-decoration: none;
}
.nav-side-row .num {
  flex-shrink: 0;
  font-family: var(--f-display);
  font-size: 0.92rem; font-weight: 600;
  color: var(--unit-color, var(--c-coral));
  min-width: 26px;
}
.nav-side-row .title {
  flex: 1; min-width: 0;
  font-size: 0.88rem;
  overflow-wrap: anywhere;
}
.nav-side-row .check {
  flex-shrink: 0;
  font-size: 0.85rem;
  color: var(--c-green-deep);
  opacity: 0.7;
}
.nav-side-row.is-current {
  background: rgba(255, 107, 74, 0.10);
  border-left-color: var(--c-coral);
  color: var(--c-coral-deep);
  font-weight: 600;
}
.nav-side-row.is-current .title { color: var(--c-coral-deep); }
.nav-side-row.is-locked {
  opacity: 0.5; cursor: not-allowed; pointer-events: none;
}
.nav-side-row.is-hidden { display: none; }

.nav-side-empty {
  padding: var(--sp-4);
  text-align: center;
  color: var(--c-muted);
  font-size: 0.85rem;
}
.nav-side-empty[hidden] { display: none; }

/* Drawer toggle (visible <1024 px). Sticky-ish pill that opens the
   off-canvas sidebar. */
.nav-drawer-toggle {
  display: none;
  align-items: center; gap: 6px;
  justify-self: start;
  margin-top: var(--sp-3);
  padding: 7px 14px;
  border: 1.5px solid var(--c-line);
  border-radius: var(--r-pill);
  background: white;
  color: var(--c-ink);
  font-size: 0.85rem; font-weight: 500; cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.nav-drawer-toggle:hover { border-color: var(--c-ink-soft); background: var(--c-paper-soft); }
.nav-drawer-toggle:focus-visible { outline: 2px solid var(--c-blue); outline-offset: 2px; }
@media (max-width: 1699.98px) {
  .nav-drawer-toggle { display: inline-flex; }
}

/* Drawer mode: when .is-drawer-open is set on the layout (640–1023 px),
   the sidebar slides in from the left, backed by a dimmer. */
.nav-drawer-backdrop {
  position: fixed; inset: 0;
  background: rgba(20, 22, 28, 0.45);
  z-index: 80;
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-base);
}
.nav-drawer-backdrop[hidden] { display: none; }
.practical-layout.is-drawer-open .nav-drawer-backdrop {
  opacity: 1; pointer-events: auto;
}
@media (max-width: 1699.98px) {
  .practical-layout.is-drawer-open .practical-nav-sidebar {
    display: flex; flex-direction: column;
    position: fixed;
    top: 0; left: 0;
    width: min(320px, 86vw);
    height: 100vh; max-height: 100vh;
    border-radius: 0;
    border-right: 1px solid var(--c-line);
    box-shadow: 0 0 40px rgba(20, 22, 28, 0.18);
    z-index: 90;
    animation: nav-drawer-in 220ms var(--ease-out, cubic-bezier(0.2, 0.8, 0.3, 1));
  }
}
@keyframes nav-drawer-in {
  from { transform: translateX(-100%); }
  to   { transform: translateX(0); }
}

/* ---------- Practical page ---------- */
.crumbs { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-4) 0; font-size: 0.9rem; color: var(--c-ink-soft); flex-wrap: wrap; }
.crumbs a { color: var(--c-ink-soft); }
.crumbs .sep { color: var(--c-muted); }
.crumbs .here { color: var(--c-ink); font-weight: 600; }

.practical-head { padding: var(--sp-5) 0; }
.practical-head .num-tag {
  display: inline-block; font-family: var(--f-display);
  background: var(--unit-color, var(--c-coral)); color: white;
  padding: 4px 14px; border-radius: var(--r-pill); font-size: 0.95rem; font-weight: 600;
  margin-bottom: var(--sp-3);
}
.practical-head h1 { margin-bottom: var(--sp-3); }
.practical-head .subtitle { color: var(--c-ink-soft); font-size: 1.1rem; max-width: 720px; }

.mnemonic {
  background: linear-gradient(180deg, #FFE99B, var(--c-yellow));
  padding: var(--sp-5) var(--sp-5);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  border: 1px solid var(--c-yellow-deep);
  position: relative;
  margin: var(--sp-5) 4px;
  transform: rotate(-0.4deg);
  transform-origin: center;
  font-family: var(--f-display);
  font-size: 1.3rem;
  font-weight: 500;
  color: #5B4500;
  word-break: break-word;
  overflow-wrap: anywhere;
}
.mnemonic::before {
  content: "✏️ Remember it like this"; display: block;
  font-family: var(--f-sans); font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: #8B6500; margin-bottom: 6px;
}

/* ---------- Sections inside practical ---------- */
.section { margin: var(--sp-7) 0; }
.section-head { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.section-head h2 { font-size: 1.5rem; }
.section-head .icon {
  width: 36px; height: 36px; border-radius: var(--r-md);
  background: var(--c-paper-soft); display: grid; place-items: center;
  font-size: 1.1rem;
}

.panel {
  background: white; border: 1px solid var(--c-line);
  border-radius: var(--r-lg); padding: var(--sp-5);
  box-shadow: var(--shadow-sm);
}

/* ---------- Apparatus list ---------- */
.apparatus-list { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-3); }
.apparatus-list li {
  list-style: none; padding: 6px 12px;
  background: var(--c-paper-soft); border: 1px solid var(--c-line);
  border-radius: var(--r-pill); font-size: 0.88rem;
}

/* ---------- Animation stage ---------- */
/* `minmax(0, …)` lets grid columns shrink below the natural width of their
   content. Without this, a long formula or fixed-width SVG inside a grid
   cell forces the cell to grow and pushes the page horizontally. */
.stage-wrap { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-5); }
.stage-wrap > * { min-width: 0; max-width: 100%; }
@media (min-width: 900px) { .stage-wrap { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); } }

.stage {
  position: relative;
  aspect-ratio: 4 / 3;
  background: linear-gradient(180deg, #fbfaf5, #f3eedb);
  border-radius: var(--r-md);
  border: 1px solid var(--c-line);
  overflow: hidden;
  /* Belt-and-braces: never let the stage push its parent wider than the column. */
  max-width: 100%;
  min-width: 0;
}
.stage svg { width: 100%; height: 100%; display: block; }

/* Interactive panel: keep all SVGs and tables inside the container, so a
   wide circuit diagram or a wide truth table can never overflow the page on
   mobile. SVGs already declare a viewBox, so width:100% + height:auto +
   their natural aspect-ratio yields the right rendered size. Files that set
   their own inline maxWidth keep it (inline styles win). */
#interactive-host { min-width: 0; }
#interactive-host > * { max-width: 100%; }
#interactive-host svg {
  max-width: 100%;
  height: auto;
  display: block;
  margin-left: auto;
  margin-right: auto;
}
/* Desktop / tablet: keep the interactive widget readable as a centered
   article-width block instead of stretching sliders + readouts across the
   full panel. The white .panel stays full-width (consistent with Aim &
   Apparatus, Pitfalls) — only its contents centre. Matches the existing
   .subtitle { max-width: 720px } pattern. Mobile (<720px) keeps 100% width.
   The `#interactive-host svg` selector is repeated to tie specificity with
   the unconstrained `#interactive-host svg { max-width: 100% }` rule above
   so SVGs inside the panel cap too — otherwise inline SVGs (vernier,
   micrometer, etc.) keep stretching to ~1100 px on a wide laptop. */
@media (min-width: 720px) {
  #interactive-host > *,
  #interactive-host svg {
    max-width: 720px;
    margin-left: auto;
    margin-right: auto;
  }

  /* Stat rows (label + readout pairs, no slider) render as a stat-card
     grid: each label sits ABOVE its value. The flat children list
     [MSR, rMSR, TSR, rTSR, …] becomes 2 rows × N cols filled column-first
     so labels land on row 1, values on row 2. `:has()` is the modern way
     to detect rows that aren't sliders — supported in every browser
     released after Sep 2022. Requiring `.readout` keeps button-only rows
     (e.g. ce-transistor mode toggles) on their default inline layout. */
  .control-row:not(:has(input[type=range])):has(.readout) {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(80px, max-content));
    grid-template-rows: auto auto;
    grid-auto-flow: column;
    gap: 6px var(--sp-6);
    justify-content: center;
    align-items: center;
    text-align: center;
  }
  .control-row:not(:has(input[type=range])):has(.readout) label {
    margin-left: 0 !important;
    font-size: 0.78rem;
    color: var(--c-ink-soft);
    text-transform: uppercase;
    letter-spacing: 0.08em;
  }
  .control-row:not(:has(input[type=range])):has(.readout) .readout {
    min-width: 90px;
  }
}
/* For tables, wrap them in `.table-scroll` (added by practicals that need it)
   so the table itself can scroll horizontally without breaking the page. */
.table-scroll {
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  /* Subtle visual hint that the table can scroll on small screens. */
  background:
    linear-gradient(to right, white, transparent 8px, transparent calc(100% - 8px), white) 0 0 / 100% 100% no-repeat,
    radial-gradient(farthest-side at 0 50%, rgba(31,41,55,0.10), transparent) 0 0 / 12px 100% no-repeat,
    radial-gradient(farthest-side at 100% 50%, rgba(31,41,55,0.10), transparent) 100% 0 / 12px 100% no-repeat;
  background-attachment: local, scroll, scroll;
}
.table-scroll table { margin: 0; }

.controls { display: flex; gap: var(--sp-2); margin-top: var(--sp-4); flex-wrap: wrap; }
.btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 10px 18px; border-radius: var(--r-pill); font: inherit; font-weight: 600;
  border: 1.5px solid transparent; cursor: pointer; background: white;
  color: var(--c-ink); transition: transform var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
  font-size: 0.92rem;
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.btn:active { transform: translateY(0); }
.btn-primary { background: var(--c-coral); color: white; border-color: var(--c-coral-deep); }
.btn-primary:hover { background: var(--c-coral-deep); }
.btn-ghost { background: white; border-color: var(--c-line); }
.btn-ghost:hover { border-color: var(--c-ink-soft); }

/* Header language selector — segmented control with two visible options.
   Both labels are always rendered; the active one is filled + bold, the
   inactive one is a muted clickable pill. Default is English. */
.lang-switcher {
  display: inline-flex; align-items: stretch;
  background: white;
  border: 1.5px solid var(--c-line);
  border-radius: var(--r-pill);
  padding: 2px;
  gap: 2px;
}
.lang-btn {
  appearance: none; -webkit-appearance: none;
  display: inline-flex; align-items: center;
  padding: 4px 12px;
  border: 0; border-radius: var(--r-pill);
  background: transparent; color: var(--c-ink-soft);
  font: inherit; font-size: 0.82rem; font-weight: 500;
  line-height: 1.4; cursor: pointer; white-space: nowrap;
  transition: background var(--t-fast), color var(--t-fast), font-weight var(--t-fast);
}
.lang-btn:hover { color: var(--c-ink); background: var(--c-paper-soft); }
.lang-btn.is-active {
  background: var(--c-ink);
  color: white;
  font-weight: 700;
  cursor: default;
}
.lang-btn.is-active:hover { background: var(--c-ink); }
.lang-btn:focus-visible { outline: 2px solid var(--c-blue); outline-offset: 2px; }
.btn-icon { width: 40px; height: 40px; padding: 0; justify-content: center; }
.btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }

/* ---------- Step list ---------- */
.steps {
  list-style: none; display: flex; flex-direction: column; gap: var(--sp-2);
  counter-reset: step;
}
.steps li {
  display: flex; gap: var(--sp-3); align-items: flex-start;
  padding: 10px 14px; border-radius: var(--r-md);
  border: 1px solid transparent; transition: background var(--t-base), border-color var(--t-base);
  font-size: 0.95rem;
  counter-increment: step;
}
.steps li::before {
  content: counter(step);
  flex-shrink: 0; width: 26px; height: 26px;
  border-radius: 50%; background: var(--c-paper-soft); color: var(--c-ink-soft);
  display: grid; place-items: center; font-weight: 700; font-size: 0.82rem;
  border: 1.5px solid var(--c-line);
  transition: background var(--t-base), color var(--t-base), border-color var(--t-base);
}
.steps li.is-current {
  background: rgba(255, 107, 74, 0.07);
  border-color: var(--c-coral);
}
.steps li.is-current::before {
  background: var(--c-coral); color: white; border-color: var(--c-coral-deep);
}
.steps li.is-done::before {
  background: var(--c-green); color: white; border-color: var(--c-green-deep);
  content: "✓";
}

/* ---------- Sliders (interactive) ---------- */
.controls-grid { display: grid; gap: var(--sp-4); margin-top: var(--sp-4); }
.control-row { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.control-row label { font-weight: 600; min-width: 80px; }
.control-row input[type=range] { flex: 1; min-width: 0; width: 100%; accent-color: var(--c-coral); }
.control-row input[type=range]:focus-visible { outline: 2px solid var(--c-blue); outline-offset: 4px; border-radius: 4px; }
.readout {
  font-family: var(--f-mono); font-size: 1rem; font-weight: 600;
  color: var(--c-blue-deep); background: rgba(43, 111, 230, 0.08);
  padding: 4px 12px; border-radius: var(--r-pill); min-width: 120px; text-align: center;
}
.readout.green { color: var(--c-green-deep); background: rgba(60, 179, 113, 0.10); }
.readout.purple { color: var(--c-purple-deep); background: rgba(123, 91, 217, 0.10); }
.readout.coral { color: var(--c-coral-deep); background: rgba(255, 107, 74, 0.10); }

/* ---------- Formula & graph ---------- */
.formula {
  font-family: var(--f-mono); font-size: 1.15rem;
  background: linear-gradient(180deg, #f8f3e3, #f1e8c9);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--r-md); border-left: 4px solid var(--c-coral);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  max-width: 100%;
  min-width: 0;
  /* Default: tokens stay on one line and the card scrolls horizontally inside
     itself when the formula won't fit. The mobile media query at the bottom
     of the file relaxes this so equations wrap on phones. */
  white-space: nowrap;
}

.graph-wrap { aspect-ratio: 3 / 2; background: white; border: 1px solid var(--c-line); border-radius: var(--r-md); padding: 12px; max-width: 100%; min-width: 0; }
.graph-wrap svg { width: 100%; height: 100%; display: block; }

/* ---------- Pitfalls ---------- */
.pitfalls { display: flex; flex-direction: column; gap: var(--sp-2); }
.pitfall {
  display: flex; gap: var(--sp-3); padding: 12px 16px;
  background: rgba(244, 114, 182, 0.08); border-left: 4px solid var(--c-pink);
  border-radius: var(--r-md);
}
.pitfall .icon { font-size: 1.2rem; }

/* ---------- YouTube ---------- */
.yt-embed {
  position: relative; aspect-ratio: 16 / 9;
  background: #1F2937; border-radius: var(--r-md); overflow: hidden;
  cursor: pointer; display: grid; place-items: center;
}
.yt-embed::before {
  content: ""; position: absolute; inset: 0;
  background: var(--yt-thumb, linear-gradient(135deg, #4B5563, #1F2937));
  background-size: cover; background-position: center;
  opacity: 0.7;
}
.yt-embed .play {
  position: relative; width: 78px; height: 56px; border-radius: 14px;
  background: rgba(255, 0, 0, 0.92); display: grid; place-items: center;
  box-shadow: 0 6px 24px rgba(0,0,0,0.4);
  transition: transform var(--t-fast), background var(--t-fast);
}
.yt-embed:hover .play { transform: scale(1.06); background: #ff0000; }
.yt-embed .play::after {
  content: ""; width: 0; height: 0;
  border-left: 18px solid white;
  border-top: 11px solid transparent; border-bottom: 11px solid transparent;
  margin-left: 4px;
}
.yt-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.yt-embed .yt-title {
  position: absolute; top: 12px; left: 14px; right: 14px;
  color: white; font-weight: 600; font-size: 0.95rem;
  text-shadow: 0 1px 4px rgba(0,0,0,0.6);
}

/* ---------- Practical nav ---------- */
.practical-nav { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); margin: var(--sp-7) 0; }
@media (max-width: 600px) { .practical-nav { grid-template-columns: 1fr; } .practical-nav .next { text-align: left; } }
.practical-nav a {
  display: flex; flex-direction: column; gap: 4px; padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--c-line); border-radius: var(--r-lg); background: white;
  color: var(--c-ink); text-decoration: none;
  transition: transform var(--t-base), border-color var(--t-base), box-shadow var(--t-base);
}
.practical-nav a:hover { transform: translateY(-2px); border-color: var(--c-coral); box-shadow: var(--shadow-md); }
.practical-nav .dir { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--c-muted); }
.practical-nav .next { text-align: right; }

/* ---------- Footer ---------- */
.site-footer {
  border-top: 1px solid var(--c-line); padding: var(--sp-6) 0;
  color: var(--c-ink-soft); font-size: 0.9rem; margin-top: var(--sp-7);
  background: rgba(255, 248, 238, 0.5);
}
.site-footer .row { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--sp-3); }

/* ---------- Logic gate UI ---------- */
.gate-board { display: flex; flex-direction: column; gap: var(--sp-4); }
.gate-tabs { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.gate-tab {
  padding: 8px 18px; border-radius: var(--r-pill); font-weight: 700;
  background: white; border: 1.5px solid var(--c-line); cursor: pointer;
  font-family: var(--f-mono); font-size: 0.9rem;
  transition: all var(--t-fast);
}
.gate-tab:hover { border-color: var(--c-blue); }
.gate-tab.is-active { background: var(--c-blue); color: white; border-color: var(--c-blue-deep); }
.toggle-row { display: flex; gap: var(--sp-5); align-items: center; flex-wrap: wrap; }
.toggle {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  font-weight: 600;
}
.toggle-switch {
  width: 56px; height: 30px; border-radius: var(--r-pill);
  background: #c4c4c4; position: relative; cursor: pointer;
  transition: background var(--t-fast);
}
.toggle-switch::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 24px; height: 24px; border-radius: 50%; background: white;
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
  transition: transform var(--t-fast);
}
.toggle.on .toggle-switch { background: var(--c-green); }
.toggle.on .toggle-switch::after { transform: translateX(26px); }
.led {
  width: 48px; height: 48px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #ffd1c4, #c1c1c1 60%);
  border: 3px solid #888; transition: background var(--t-fast), box-shadow var(--t-fast);
}
.led.on {
  background: radial-gradient(circle at 35% 30%, #ffe7a0, var(--c-coral) 70%);
  box-shadow: 0 0 24px rgba(255, 107, 74, 0.7), 0 0 48px rgba(255, 107, 74, 0.4);
  border-color: var(--c-coral-deep);
}
.truth-table { width: 100%; border-collapse: collapse; font-family: var(--f-mono); margin-top: var(--sp-4); min-width: 320px; }
.truth-table th, .truth-table td { padding: 8px 12px; border: 1px solid var(--c-line); text-align: center; white-space: nowrap; }
.truth-table th { background: var(--c-paper-soft); font-weight: 700; }
.truth-table tr.is-current { background: rgba(255, 107, 74, 0.12); font-weight: 700; }

/* ---------- Coming soon ---------- */
.coming-soon-msg {
  text-align: center; padding: var(--sp-7) var(--sp-5);
  background: white; border: 2px dashed var(--c-line); border-radius: var(--r-lg);
}
.coming-soon-msg h2 { margin-bottom: var(--sp-3); color: var(--c-ink-soft); }
.coming-soon-msg p { color: var(--c-muted); max-width: 520px; margin: 0 auto; }

/* ---------- Mobile (≤640 px) ---------- */
@media (max-width: 640px) {
  .container { padding: 0 var(--sp-4); }
  .site-header { padding: var(--sp-4) 0; }
  .site-header .row { gap: var(--sp-3); }
  .brand { font-size: 1.15rem; }
  .brand-mark { width: 32px; height: 32px; }
  .brand-tag { font-size: 0.72rem; }
  .search { width: 100%; order: 3; }
  .lang-switcher { order: 2; }
  .nav-home { order: 1; padding: 6px 10px; }
  .nav-home .nav-home-label { display: none; }

  .hero { padding: var(--sp-6) 0 var(--sp-5); }
  .hero p { font-size: 0.98rem; }
  .hero-stats { gap: var(--sp-4); margin-top: var(--sp-4); }
  .hero-stat strong { font-size: 1.6rem; }

  .section { margin: var(--sp-6) 0; }
  .section-head h2 { font-size: 1.25rem; }
  .panel { padding: var(--sp-4); }
  .practical-head { padding: var(--sp-4) 0; }
  .practical-head h1 { line-height: 1.2; }

  .mnemonic { font-size: 1.05rem; padding: var(--sp-4); margin: var(--sp-4) 2px; }

  .stage-wrap { gap: var(--sp-4); }

  .controls .btn { padding: 9px 14px; font-size: 0.88rem; }
  .control-row { gap: var(--sp-2); flex-wrap: wrap; }
  .control-row label { min-width: 0; margin-left: 0 !important; }
  .control-row .readout {
    min-width: 0;
    flex: 1 1 100%;
    text-align: left;
    overflow-wrap: anywhere;
    word-break: break-word;
  }

  .formula {
    font-size: 0.92rem;
    padding: var(--sp-3) var(--sp-4);
    /* Phones: let formula wrap rather than scroll-only — wider equations
       become 2-3 lines instead of an awkward horizontal scrollbar. */
    white-space: normal;
    word-break: keep-all;
  }

  .gate-tabs { gap: 6px; }
  .gate-tab { padding: 6px 12px; font-size: 0.8rem; }
  .toggle-row { gap: var(--sp-3); }

  .crumbs { font-size: 0.82rem; gap: var(--sp-2); }
}

/* Very small phones (≤380 px) — extra typography breathing room. */
@media (max-width: 380px) {
  body { font-size: 15px; }
  .brand-tag { display: none; }
  .lang-btn { padding: 4px 9px; font-size: 0.78rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
  .card.is-active:hover { transform: none; }
}

/* ---------- Beta-disclaimer modal ----------
   Centred card with dim backdrop. Shown only when the student
   switches into Sinhala mode; dismiss requires an explicit button
   click ("තේරුණා · Got it"). */

@keyframes betaModalFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes betaModalSlideIn {
  from { transform: translateY(20px) scale(0.96); opacity: 0; }
  to   { transform: translateY(0) scale(1);       opacity: 1; }
}

.beta-modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(31, 41, 55, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: grid;
  place-items: center;
  padding: var(--sp-5);
  animation: betaModalFadeIn 220ms var(--ease-out) both;
}

.beta-modal {
  position: relative;
  background: white;
  border-radius: var(--r-xl);
  padding: 36px 32px 32px;
  width: 100%;
  max-width: 460px;
  box-shadow:
    0 24px 56px rgba(31, 41, 55, 0.30),
    0 8px 18px rgba(31, 41, 55, 0.16);
  text-align: center;
  animation: betaModalSlideIn 280ms var(--ease-out) both;
  overflow: hidden;
}

/* Soft accent stripe at the top of the card. */
.beta-modal::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 6px;
  background: linear-gradient(90deg, var(--c-coral) 0%, var(--c-yellow) 50%, var(--c-purple) 100%);
}

.beta-modal-icon {
  width: 72px; height: 72px;
  border-radius: 50%;
  background: linear-gradient(135deg, #FFE99B, var(--c-yellow));
  border: 2px solid var(--c-yellow-deep);
  display: grid;
  place-items: center;
  margin: 8px auto var(--sp-4);
  font-size: 32px;
  box-shadow: 0 6px 16px rgba(232, 184, 52, 0.35);
}

.beta-modal-chip {
  display: inline-block;
  font-family: var(--f-mono);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  background: var(--c-coral);
  color: white;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  margin-bottom: var(--sp-3);
}

.beta-modal-title {
  font-family: var(--f-display);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--c-ink);
  margin-bottom: var(--sp-3);
  line-height: 1.2;
}

[data-lang="si"] .beta-modal-title {
  font-family: "Noto Sans Sinhala", "Fraunces", Georgia, serif;
}

.beta-modal-msg {
  font-size: 0.96rem;
  line-height: 1.6;
  color: var(--c-ink-soft);
  margin-bottom: var(--sp-5);
  text-align: left;
}

.beta-modal-btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  background: var(--c-coral);
  color: white;
  font-family: var(--f-sans);
  font-weight: 600;
  font-size: 1rem;
  padding: 13px 32px;
  border: 1.5px solid var(--c-coral-deep);
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: transform var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
  box-shadow: 0 4px 12px rgba(255, 107, 74, 0.30);
  min-width: 180px;
}
.beta-modal-btn:hover {
  background: var(--c-coral-deep);
  transform: translateY(-1px);
  box-shadow: 0 8px 20px rgba(255, 107, 74, 0.40);
}
.beta-modal-btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(255, 107, 74, 0.30);
}
.beta-modal-btn:focus-visible {
  outline: 3px solid rgba(43, 111, 230, 0.45);
  outline-offset: 2px;
}

@media (max-width: 540px) {
  .beta-modal { padding: 32px 24px 28px; }
  .beta-modal-icon { width: 60px; height: 60px; font-size: 28px; }
  .beta-modal-title { font-size: 1.3rem; }
  .beta-modal-msg { font-size: 0.92rem; text-align: center; }
  .beta-modal-btn { width: 100%; padding: 12px 20px; }
}

@media (prefers-reduced-motion: reduce) {
  .beta-modal-backdrop, .beta-modal { animation: none; }
}
