/* =================================================================
   PAGES — styles specific to one page type
   -----------------------------------------------------------------
   Lesson articles (including practice exercises, common mistakes,
   quiz, and FAQ blocks), search results, the style guide, and every
   tool page (Bug Checker, Compare Code, the Try It editor, the
   Exercise/quiz level page, Interview Prep). The largest file here —
   most of what makes one page type look different from another lives
   in this one, rather than being split further; see the note in the
   codebase's history for why a fully granular per-page split wasn't
   pursued (real effort/risk tradeoff, not an oversight).
================================================================= */

/* ---------------------------------------------------------------
   Article
--------------------------------------------------------------- */
.article { min-width: 0; max-width: 720px; padding-top: 40px; }
/* #docs-main's own max-width for the lesson page specifically is now
   set directly in layout.css, alongside the rest of .lesson-layout's
   flex-based sizing (sidebar/main/toc-rail widths and padding) that
   replaced an earlier grid-based approach here — keeping the article
   width override together with the rest of that structural rework
   rather than split across two files. */

.breadcrumb {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin: 0 0 18px;
}
.breadcrumb a { color: var(--ink-soft); }
.breadcrumb a:hover { color: var(--accent); }
/* Icons — inline SVGs that inherit text color via currentColor */
.icon { display: inline-block; vertical-align: -1px; color: var(--ink-soft); }

.breadcrumb__sep { margin: 0 7px; color: var(--border); display: inline-flex; vertical-align: middle; }

.article__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 10px;
}
.article__title-group {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.article__head-actions {
  display: flex;
  align-items: center;
  /* Pixel-measured from the target design: an even 8px gap between
     all three buttons (prev/next/share alike), not a narrower 6px
     within the prev/next pair and a wider 10px before share. */
  gap: 8px;
  flex-shrink: 0;
}
.article__head-nav { display: flex; gap: 8px; }
.article__head-nav-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Matches .share-btn--icon's own 38px square exactly — was a
     smaller, inconsistent 34px, pixel-measured against the target
     design as the odd one out next to the (already-correct) share
     button. */
  width: 38px;
  height: 38px;
  background: var(--surface);
  border: 1px solid var(--border);
  /* 12px per explicit request (was 6px). */
  border-radius: 12px;
  color: var(--ink-soft);
}
.article__head-nav-btn svg { width: 12px; height: 12px; }
.article__head-nav-btn:hover { color: var(--accent); border-color: var(--accent); text-decoration: none; }
.article__head-nav-btn.is-disabled { opacity: 0.35; cursor: default; }

/* ---------------------------------------------------------------
   Reusable visual tooltip (data-tooltip attribute)
   A CSS-driven tooltip bubble, used instead of relying purely on
   the native browser title attribute (which has an inconsistent
   delay and no visual styling) for icon-only controls where the
   label isn't otherwise visible on screen.
--------------------------------------------------------------- */
[data-tooltip] { position: relative; }
[data-tooltip]::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  background: #202124;
  color: #fff;
  font-size: 0.78rem;
  font-weight: 500;
  white-space: nowrap;
  padding: 5px 9px;
  border-radius: 6px;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.12s ease;
  z-index: 40;
}
[data-tooltip]:hover::after,
[data-tooltip]:focus-visible::after {
  opacity: 1;
  visibility: visible;
}
.article h1 {
  font-size: 2rem;
  line-height: 1.2;
  margin: 0 0 10px;
  letter-spacing: -0.01em;
}
/* Lesson page's own h1 sizing/weight set directly via Tailwind
   classes in the markup (text-3xl lg:text-4xl font-extrabold
   tracking-tight, matching the reference file), restated explicitly
   here for the same specificity reason the tags__label and section h2
   fixes elsewhere in this file needed: .article h1 above
   (element+class) otherwise silently wins over those single-class
   utilities despite loading earlier. font-size: inherit was tried
   first and was wrong for the same reason it was wrong there too —
   it pulls the parent's font-size, not the Tailwind class's intended
   value, so the actual text-3xl/lg:text-4xl sizes are restated
   explicitly instead. Scoped to #docs-main rather than editing the
   rule above, since .article is shared with the other 7 page
   templates using that class, where the existing 2rem/bold sizing
   still applies. */
#docs-main h1 {
  font-size: 1.875rem;
  line-height: 1.2;
  margin: 0 0 10px;
  letter-spacing: -0.025em;
  font-weight: 800;
}
@media (min-width: 1024px) {
  #docs-main h1 { font-size: 2.25rem; }
}
/* Same fix as #docs-main h1 above, for the lesson page's own section
   headings ("Overview", "Explain Like I'm New", etc.), which the
   markup already sets to text-xl font-bold (matching the mockup) —
   .article h2 (further up this file) otherwise silently wins with its
   own blanket 24px, the same element+class-vs-single-utility-class
   specificity gap. This was flagged as still outstanding when the h1
   fix above was written but not actually applied at the time; doing
   it now. Scoped to #docs-main rather than editing .article h2
   itself, since that rule is shared with the other page templates
   using the .article class, where its 24px still applies. */
#docs-main h2:not(.tags__label) {
  font-size: 1.25rem;
  margin: 0 0 12px;
  letter-spacing: normal;
}
/* Inside the title group specifically (paired with the course logo),
   the h1's own bottom margin is dropped — flexbox align-items:
   center measures each item's full box including margin, so an
   asymmetric bottom margin on just the h1 was shifting it out of
   true vertical alignment with the logo beside it. The same visual
   spacing below the whole row is preserved instead via margin-bottom
   on .article__head itself, so nothing is lost, just moved to where
   it doesn't distort the flex alignment. */
.article__title-group h1 { margin: 0; }
.share-btn {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 14px;
  font-family: var(--sans);
  font-size: 0.85rem;
  color: var(--ink-soft);
  cursor: pointer;
  margin-top: 4px;
  white-space: nowrap;
}
.share-btn--icon {
  width: 38px;
  height: 38px;
  padding: 0;
  justify-content: center;
  margin-top: 0;
  /* 12px per explicit request (was the shared .share-btn base's 6px),
     matching the prev/next buttons it sits beside. */
  border-radius: 12px;
}
/* Same fix as the code toolbar buttons: the icon-wrapping span is
   plain, not a flex item itself, so the generic .icon
   vertical-align: -1px rule nudges just the icon out of true
   center relative to the button's flex-centered content. Making
   the wrapper an inline-flex box of its own sidesteps that rule
   entirely. */
.share-btn > span:first-child {
  display: inline-flex;
  align-items: center;
}
.share-btn:hover { color: var(--accent); border-color: var(--accent); }
.share-btn.is-copied { color: var(--accent); border-color: var(--accent); }

/* Single left-aligned inline flow, matching the mockup — this used to
   be justify-content: space-between with "Last updated" in its own
   span, which pushed it all the way to the card's right edge instead
   of flowing right after "3 min read" like the mockup shows. */
.meta {
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex-wrap: wrap;
  color: var(--ink-soft);
  font-size: 0.88rem;
  margin: 8px 0 20px;
}
.meta__updated { white-space: nowrap; }
/* "Lesson X of Y" sits in its own light pill in the mockup, distinct
   from the plain-text reading-time/last-updated segments beside it —
   background sampled from the mockup's own pixels (rgb(241,245,249),
   Tailwind's slate-100). */
.meta__lesson-count {
  background: #F1F5F9;
  padding: 3px 8px;
  /* Rounded corners, not a full stadium/pill shape — the mockup's
     corner curvature is much shallower than 999px would render. */
  border-radius: 6px;
  white-space: nowrap;
}

.rule {
  border: none;
  border-top: 1px solid var(--border);
  margin: 8px 0 28px;
}

/* ---------------------------------------------------------------
   Ad slot
--------------------------------------------------------------- */
.ad-slot {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 0 28px;
  /* Solid border, not dashed — pixel-sampled from the mockup, which
     shows a plain 1px slate-200 line. Fill is slate-100 (#F1F5F9),
     a shade darker than the page's own slate-50 background, so the
     slot actually reads as its own box instead of nearly disappearing
     against the page (var(--bg) is slate-50, the same color as the
     page behind it). */
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #F1F5F9;
  color: var(--ink-soft);
  font-size: 0.78rem;
  overflow: hidden;
}
.ad-slot--rectangle { height: 200px; width: 100%; }
.ad-slot--bottom { margin-top: 8px; margin-bottom: 32px; }
/* 16px radius specifically for this page's own rectangle ad slots,
   matching the reference file's rounded-2xl (its ad placeholders use
   that consistently, both the main rectangle and the sidebar square
   — the latter already carries its own rounded-2xl utility class
   directly in its markup, so only the rectangle variant here, styled
   through this shared .ad-slot base rule rather than a class on the
   element itself, needs the override). Scoped rather than changing
   the shared 8px/200px above, since .ad-slot is reused by
   chapters-rail.php elsewhere with no equivalent reference calling
   for a change there. Height is added here too, for the same
   reason: the mockup's placeholder measures ~68px tall — a slim
   banner shape — not the 200px "medium rectangle" convention this
   was set to. */
.lesson-layout .ad-slot--rectangle { border-radius: 16px; height: 68px; }
/* The lesson's very first ad slot (right after the meta row, before
   "Overview") now matches the sidebar's own square ad box instead of
   its sibling "bottom of lesson" rectangle slot — explicitly
   requested to share that box's exact UI: same 8px radius (overriding
   the 16px every other rectangle slot on this page gets, just above)
   and the same lighter slate-400 label color, computed live from
   .toc-rail .ad-slot--square (rgb(148,163,184)) rather than reused
   from a token, since no existing token is this exact shade. Content
   copy was shortened from "Advertisement Placeholder" to plain
   "Advertisement" in index.php to match too. */
.lesson-layout .ad-slot--top { border-radius: 8px; color: #94A3B8; }
.ad-slot--leaderboard {
  height: 44px;
  width: 320px;
  flex-shrink: 1;
  min-width: 0;
  margin: 0;
}

.ad-slot__label { display: block; }
.ad-slot__skeleton { display: none; }
.ad-slot.is-loading {
  border-style: solid;
  border-color: var(--border);
}
.ad-slot.is-loading .ad-slot__label { display: none; }
.ad-slot.is-loading .ad-slot__skeleton {
  display: block;
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--color-shimmer-1) 25%, var(--color-shimmer-2) 50%, var(--color-shimmer-1) 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
}
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

.ad-slot--square {
  flex-direction: column;
  height: 240px;
  width: 100%;
  max-width: 240px;
  margin: 24px auto 0;
}
/* Shorter, compact ad shape specifically for the lesson page's right
   "on this page" rail (matching the supplied mockup) — scoped to
   .toc-rail rather than changing .ad-slot--square itself, since that
   shared class is also used by chapters-rail.php's own ad slot in a
   different layout context, where the taller default height is
   still the intended shape. */
/* Text color pixel-sampled from the same mockup: rgb(148,163,184),
   Tailwind's slate-400 — lighter than the shared .ad-slot rule's own
   --ink-soft (slate-600), which reads too dark for this small, quiet
   sidebar placeholder specifically. */
.toc-rail .ad-slot--square { height: 64px; max-width: none; margin-top: 24px; color: #94A3B8; }
/* width/margin removed per explicit request, scoped to the
   Character Count tool's own side column — that column already
   sizes and positions this box itself (.charcount-side, a flex
   item), so the shared rule's own max-width:240px + auto-centering
   margin above just fought that instead of filling it. */
.charcount-side .ad-slot--square { width: auto; max-width: none; margin: 0; }

/* ---------------------------------------------------------------
   Left/right advertisement rails: Exercise (listing + level/quiz)
   and Interview Q & A — these three page templates lost their
   sidebar entirely in an earlier round, leaving the main content
   the only thing on the page; this flanks it with a skyscraper ad
   slot on each side instead, reusing the same .ad-slot component
   the rest of the site already uses rather than a new ad UI.
--------------------------------------------------------------- */
.tool-ads-layout {
  display: flex;
  align-items: flex-start;
  gap: 24px;
  /* 1280px per explicit request (was 1400px), matching the header's
     own .topbar__inner max-width and the shared .layout container. */
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 24px;
}
.tool-ads-layout > .styleguide { flex: 1; min-width: 0; }
.tool-ads-rail {
  flex: 0 0 200px;
  width: 200px;
  position: sticky;
  top: 76px;
}
.ad-slot--skyscraper { height: 600px; width: 100%; margin: 32px 0 0; }
/* A live ad unit (Exercise and Interview Q&A pages' left/right rails)
   holds a real <ins class="adsbygoogle"> instead of the simulated
   skeleton/label placeholder, so the fixed height and
   overflow:hidden inherited from the shared .ad-slot rule above
   would clip whatever size AdSense actually renders at — auto-format
   ads size themselves to the container's width but not necessarily
   to this box's fixed 600px height. Letting height follow content
   and dropping the clip avoids that, while keeping the same border/
   background/width treatment as every other ad slot on the site. */
.ad-slot--live { height: auto; min-height: 250px; overflow: visible; display: block; }

/* ---------------------------------------------------------------
   Lesson diagrams: hand-drawn inline SVGs illustrating structural
   concepts (document structure, semantic layout, nesting, tables,
   forms, etc.), themed with the same CSS custom properties as the
   rest of the site rather than hardcoded colors.
--------------------------------------------------------------- */
.lesson-diagram {
  margin: 0 0 28px;
  padding: 20px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  text-align: center;
}
.lesson-diagram svg { max-width: 100%; height: auto; display: block; margin: 0 auto; }
.lesson-diagram figcaption {
  margin-top: 12px;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.article section { margin: 0 0 48px; scroll-margin-top: 88px; }
/* Tighter card-to-card spacing specifically for the redesigned lesson
   page's own sections (Overview, Explain Like I'm New, etc. — see
   index.php's .lesson-section usage), matching the supplied mockup's
   measured ~32px gap rather than the 48px the generic .article
   section rule above uses. Scoped this way (an extra .lesson-section
   class, not editing the rule above) because .article section is
   shared across 8 different page templates — 404 pages, the style
   guide, quiz levels, the editor — where the wider 48px gap is still
   what's intended; only this page's own sections should get the
   tighter spacing. Two classes here outweighs the rule above's
   class+element combination, so this correctly wins for exactly the
   sections that opt into it. */
.article .lesson-section { margin-bottom: 32px; }
/* The accent dot before "Overview" was removed per explicit request
   (its ::before rule and the class that triggered it, both dead code
   now — the class name is stripped from index.php's markup too). */
.article h2 {
  font-size: 24px;
  margin: 0 0 12px;
  letter-spacing: -0.005em;
}
.article p { margin: 0 0 18px; }
.article ul { margin: 0 0 18px; padding-left: 0; }
.article li { margin-bottom: 6px; }

.article code {
  font-family: var(--mono);
  font-size: 0.86em;
  background: var(--bg);
  padding: 1px 5px;
  border-radius: 4px;
  color: var(--ink);
}
/* Amber-tinted inline code specifically within Common Mistakes items,
   matching the reference file's bg-amber-100 (its warning boxes theme
   inline code to match their own amber background, rather than using
   the neutral gray .article code above uses everywhere else). */
.mistakes code { background: #fef3c7; color: #78350f; }
.article pre {
  background: var(--bg);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 40px 18px 18px;
  overflow-x: auto;
  margin: 0;
  position: relative;
}
.article pre code {
  background: none;
  padding: 0;
  color: inherit;
  font-size: 0.86rem;
  line-height: 1.6;
}

.code-block {
  position: relative;
  margin: 0 0 16px;
}

.code-toolbar {
  position: absolute;
  top: 8px;
  right: 10px;
  left: 10px;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px;
}
.code-copy,
.code-preview-btn,
.code-edit-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0;
  color: var(--ink-soft);
  cursor: pointer;
  text-decoration: none;
}
/* Copy, Edit, Preview reading order left to right — set with flex
   order rather than changing DOM append order, since Copy/Preview
   and Edit are wired up in two separate JS passes over each code
   block and always land in the DOM as Copy, Preview, Edit. */
.code-copy { order: 1; }
.code-edit-btn { order: 2; }
.code-preview-btn { order: 3; }
/* The icon-wrapping span inside each toolbar button is plain, not a
   flex item itself, so the generic .icon vertical-align: -1px rule
   (meant for icons sitting inline within running text) was nudging
   just the icon out of true center relative to the button's own
   label text. Making the wrapper an inline-flex box of its own
   sidesteps that rule entirely and guarantees pixel-accurate
   centering regardless of what's inside it. */
.code-copy > span:first-child,
.code-preview-btn > span:first-child,
.code-edit-btn > span:first-child {
  display: inline-flex;
  align-items: center;
}
.code-copy:hover,
.code-preview-btn:hover,
.code-edit-btn:hover { color: var(--ink); border-color: var(--ink-soft); text-decoration: none; }
.code-copy.is-copied { color: var(--primary-dark); border-color: var(--primary); background: var(--color-primary-subtle); }
.code-preview-btn.is-active { color: var(--accent); border-color: var(--accent); background: var(--color-primary-subtle); }

/* Line numbers: each source line becomes its own block-level span,
   numbered via a CSS counter so JS never has to keep the numbers in
   sync itself — just rebuild the lines and the count follows. */
.code-block__code {
  display: block;
  counter-reset: line;
}
.code-line {
  display: block;
  padding-left: 2.6em;
  position: relative;
  white-space: pre;
}
.code-line::before {
  counter-increment: line;
  content: counter(line);
  position: absolute;
  left: 0;
  width: 2em;
  text-align: right;
  color: var(--ink-soft);
  opacity: 0.6;
  user-select: none;
}
.code-line:empty::after { content: '\00a0'; } /* keep blank lines visible/selectable */

/* The editable textarea (and its Reset button) that now sits above
   the live preview iframe, turning "Preview" from a static,
   read-only render into an actual live demo — type a change here and
   the iframe below updates automatically. */
.code-preview-editwrap {
  margin-top: 10px;
  border: 1px solid var(--border);
  border-radius: 8px 8px 0 0;
  border-bottom: none;
  background: var(--bg);
  overflow: hidden;
}
.code-preview-edit {
  display: block;
  width: 100%;
  min-height: 90px;
  max-height: 320px;
  padding: 12px 14px;
  border: none;
  background: transparent;
  resize: vertical;
  font-family: var(--mono);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ink);
}
.code-preview-edit:focus { outline: none; background: var(--surface); }
.code-preview-reset {
  display: block;
  margin-left: auto;
  padding: 6px 14px;
  border: none;
  border-top: 1px solid var(--border);
  background: var(--bg);
  color: var(--ink-soft);
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
}
.code-preview-reset:hover { color: var(--accent); }
.code-preview-frame {
  display: block;
  width: 100%;
  min-height: 60px;
  margin-top: 0;
  border: 1px solid var(--border);
  border-radius: 0 0 8px 8px;
  background: #fff;
}

/* ---------------------------------------------------------------
   Search results
--------------------------------------------------------------- */

.search-results {
  list-style: none;
  margin: 0;
  padding: 0;
}
.search-results li {
  border-bottom: 1px solid var(--border);
}
.search-results a {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 14px 8px;
  margin: 0 -8px;
  border-radius: 6px;
  color: var(--ink);
  transition: background 0.12s ease;
}
/* Color-only hover — constancy check: matches the lesson page's own
   chapter list and "On this page" rail (both recently stripped of
   background), rather than the filled-background treatment this used
   to have with no color change of its own (background was the only
   hover feedback, so color is added here — accent — not just the
   background removed). */
.search-results a:hover { text-decoration: none; color: var(--accent); }
.search-results__num {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-soft);
  min-width: 24px;
}
.search-results__title {
  display: block;
  font-size: 1rem;
  font-weight: 500;
}
.search-results__chapter {
  display: block;
  font-size: 0.82rem;
  color: var(--ink-soft);
  margin-top: 2px;
}

/* ---------------------------------------------------------------
   Practice exercise
--------------------------------------------------------------- */
/* .practice's own margin-top/padding-top removed — this used to be
   the section's only top spacing before the card-based redesign gave
   every .lesson-section its own consistent 32px gap (see that rule
   above); keeping both stacked them, pushing this section noticeably
   further from "Learn by Fixing" above it than the supplied mockup's
   consistently-spaced cards call for. .practice h2's margin removed
   for the same reason .tags__label's needed the same fix earlier:
   it's an element+class selector, edging out the mb-4 Tailwind class
   already set directly on this heading in the markup despite loading
   before it, since specificity — not just source order — decides here. */
.practice__card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 22px 24px;
}
.practice__title { font-weight: 700; margin: 0 0 10px; }
.practice__card > p:not(.practice__title) { margin: 0 0 14px; color: var(--ink); }
.practice__hint summary {
  cursor: pointer;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--ink-soft);
  list-style: none;
  display: flex;
  align-items: center;
  gap: 8px;
}
.practice__hint summary:hover { color: var(--accent); }
.practice__hint summary::-webkit-details-marker { display: none; }
.practice__hint summary::after { content: none; }
.practice__hint[open] summary::after { content: '\2212'; }
.practice__hint p { margin: 10px 0 0; color: var(--ink-soft); font-size: 0.92rem; }

/* "Learn by Fixing" disclosure toggle ("What's wrong with this code?")
   needs the same default-marker suppression as .practice__hint and
   .faq__item summary above — without it, the browser draws its own
   triangle marker in front of the arrow character already in the link
   text, which the mockup doesn't show (just a plain "→", no marker). */
.mistake-toggle::-webkit-details-marker { display: none; }
.mistake-toggle::marker { content: ''; display: none; }

/* ---------------------------------------------------------------
   Common mistakes
--------------------------------------------------------------- */
/* .mistakes's own margin-top/padding-top removed, same reason as
   .practice above: superseded by .lesson-section's consistent 32px
   gap now that every section is its own card. .mistakes h2's margin
   removed for the same specificity reason too — beats the mb-4
   Tailwind class already on this heading in the markup. */

/* ---------------------------------------------------------------
   Quiz
--------------------------------------------------------------- */
/* .quiz's own margin-top/padding-top removed, same reason as
   .practice/.mistakes above. .quiz h2's margin removed for the same
   specificity reason too — beats the mb-1 Tailwind class already on
   this heading in the markup. */
.quiz__intro { color: var(--ink-soft); font-size: 0.92rem; margin: 0 0 24px; }
.quiz__question {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 18px 20px;
  margin: 0 0 16px;
}
.quiz__question legend {
  font-weight: 600;
}
.quiz__option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 4px;
  cursor: pointer;
  font-size: 0.94rem;
  border-radius: 6px;
}
.quiz__option:hover { background: var(--bg); }
.quiz__option input { accent-color: var(--primary-dark); width: 16px; height: 16px; flex-shrink: 0; }
.quiz__question.is-correct { border-color: var(--color-success-border); background: var(--color-success-bg); }
.quiz__question.is-incorrect { border-color: var(--color-error-border); background: var(--color-error-bg); }
.quiz__explain {
  margin: 12px 4px 0;
  padding: 10px 12px;
  background: var(--bg);
  border-radius: 6px;
  font-size: 0.88rem;
  color: var(--ink-soft);
}
.quiz__completions {
  margin: 6px 0 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

/* ---------------------------------------------------------------
   Quiz app: one question at a time, with immediate feedback and a
   final results screen (replaces the old all-at-once radio form
   above, which is kept only for the style guide's static demo).
--------------------------------------------------------------- */
.quizapp__progress {
  display: flex;
  gap: 4px;
  margin-bottom: 8px;
}
.quizapp__segment {
  flex: 1;
  height: 4px;
  border-radius: 999px;
  background: var(--border);
}
.quizapp__segment.is-current { background: var(--ink-soft); }
.quizapp__segment.is-correct { background: var(--color-success-text); }
.quizapp__segment.is-incorrect { background: var(--color-error-text); }
.quizapp__counter {
  display: block;
  text-align: right;
  font-size: 0.8rem;
  color: var(--ink-soft);
  margin-bottom: 20px;
}
.quizapp__question {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 18px;
}
.quizapp__question-num { color: var(--ink-soft); font-weight: 700; margin-right: 4px; }
.quizapp__options { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.quizapp__option {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  width: 100%;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
  font-family: var(--sans);
  font-size: 0.94rem;
  color: var(--ink);
  cursor: pointer;
}
.quizapp__option:hover:not(:disabled) { border-color: var(--ink-soft); }
.quizapp__option:disabled { cursor: default; }
/* 12px radius specifically on the lesson page's own quiz, matching
   the reference file's rounded-xl (its other quiz-level pages, also
   using this same JS-generated .quizapp__option markup, keep the 8px
   above — no equivalent reference image calls for a change there). */
.lesson-layout .quizapp__option { border-radius: 12px; }
.quizapp__option-letter {
  flex-shrink: 0;
  font-weight: 700;
  color: var(--ink-soft);
}
.quizapp__option-body { min-width: 0; }
.quizapp__option-feedback {
  display: block;
  margin-top: 6px;
  font-size: 0.85rem;
  font-weight: 400;
}
.quizapp__option.is-correct-choice {
  background: var(--color-success-bg);
  border-color: var(--color-success-border);
}
.quizapp__option.is-correct-choice .quizapp__option-letter,
.quizapp__option.is-correct-choice .quizapp__option-feedback { color: var(--color-success-text); }
.quizapp__option.is-incorrect-choice {
  background: var(--color-error-bg);
  border-color: var(--color-error-border);
}
.quizapp__option.is-incorrect-choice .quizapp__option-letter,
.quizapp__option.is-incorrect-choice .quizapp__option-feedback { color: var(--color-error-text); }

.quizapp__validation {
  margin: 0 0 4px;
  font-size: 0.85rem;
  color: var(--color-error-text);
}
.quizapp__nav {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 12px;
}
.quizapp__nav-btn {
  border-radius: 8px;
  padding: 11px 24px;
  font-weight: 600;
  font-size: 0.94rem;
  cursor: pointer;
  font-family: var(--sans);
}
.quizapp__nav-btn--back {
  background: var(--surface);
  color: var(--ink-soft);
  border: 1px solid var(--border);
}
.quizapp__nav-btn--back:hover { color: var(--ink); border-color: var(--ink-soft); }
.quizapp__nav-btn--next {
  background: none;
  color: var(--primary);
  border: 1px solid var(--primary);
}
.quizapp__nav-btn--next:hover { background: var(--color-primary-subtle); }
.quizapp__nav-btn--next:disabled { background: none; color: var(--ink-soft); border-color: var(--border); cursor: not-allowed; }

.quizapp__results-title {
  font-size: 1.05rem;
  font-weight: 700;
  margin: 0 0 16px;
}
.quizapp__results-row { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.quizapp__results-percent {
  font-size: 2.6rem;
  font-weight: 800;
  color: var(--ink);
  line-height: 1;
}
.quizapp__stat {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 18px;
  border-radius: 8px;
  font-weight: 600;
  font-size: 0.9rem;
  min-width: 140px;
}
.quizapp__stat span:last-child { font-size: 1.2rem; font-weight: 800; }
.quizapp__stat--correct { background: var(--color-success-bg); color: var(--color-success-text); }
.quizapp__stat--incorrect { background: var(--color-error-bg); color: var(--color-error-text); }
.quizapp__retry {
  margin-top: 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 11px 22px;
  font-weight: 600;
  font-size: 0.94rem;
  color: var(--ink);
  cursor: pointer;
  font-family: var(--sans);
}
.quizapp__retry:hover { border-color: var(--ink-soft); }



/* ---------------------------------------------------------------
   FAQ
--------------------------------------------------------------- */
/* .faq's own margin-top/padding-top removed, same reason as
   .practice/.mistakes/.quiz above. .faq h2's margin removed for the
   same specificity reason too — beats the mb-4 Tailwind class already
   on this heading in the markup. */
.faq__item {
  transition: border-color 0.12s ease;
}
.faq__item[open] { border-color: var(--color-primary-subtle); }
.faq__item summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  text-align: left;
}
.faq__item summary:hover { color: var(--accent); }
/* <summary> isn't covered by the site's global a/button/input focus
   rule (it's a distinct element type), so without this it would
   fall back to the browser's own default blue outline — visually
   inconsistent with the accent-colored focus treatment used on
   every other interactive element on the site. */
.faq__item summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary::marker { content: ''; display: none; }
.faq__item summary::after {
  content: '\2304';
  display: inline-block;
  color: var(--ink-soft);
  font-size: 1.1rem;
  flex-shrink: 0;
  transition: transform 0.15s ease;
}
.faq__item[open] summary::after { transform: rotate(180deg); }
.faq__q-label {
  flex: 1;
  min-width: 0;
  text-align: left;
}
.faq__item p {
  margin: 0 0 14px;
  color: var(--ink-soft);
  font-size: 0.92rem;
  text-align: left;
}
.faq__num { color: var(--ink); font-weight: 700; }

/* ---------------------------------------------------------------
   Tags
--------------------------------------------------------------- */
/* .tags itself, and its child selectors below, no longer style
   anything: the section's actual markup (index.php) now carries its
   own Tailwind utility classes directly (a plain <ul> of <li><span>
   pills, not this old dedicated .tags__label h2 + .tags span
   structure this block was written for). Kept only as host to the
   .article h2 override just below, which still matters. */
.tags { margin-top: 24px; }
/* Tag pill fill: needs its own rule rather than Tailwind's bg-slate-100
   utility because that utility was never referenced elsewhere in the
   markup at build time, so this site's statically-compiled tailwind.css
   never generated its base (non-hover) rule — only .hover\:bg-slate-100
   exists in that file. Hardcoded to the same slate-100 hex Tailwind
   itself uses, pixel-matched against the target design (no border,
   unlike this pill's old bg-slate-50 + border-slate-200 treatment). */
.tags__pill { background: #F1F5F9; }

/* .article h2 (further up this file) sets a blanket 24px size for
   every h2 inside lesson content — appropriate for the lesson's own
   section headings, but not for .tags__label, which is deliberately
   small (Tailwind's text-sm, set directly in the markup) as a
   quiet section label, not a heading on the same visual level as
   "Overview" or "Common mistakes". A class selector on the h2 itself
   matches that .article h2 rule's specificity exactly, and following
   it here in source order lets it win the tie. */
.article h2.tags__label { font-size: 0.875rem; margin: 0; letter-spacing: normal; }
/* Same specificity problem as the label above, for the same reason:
   .article ul (elsewhere in this file) sets a 18px bottom margin
   meant for genuine lesson-content lists, which otherwise still wins
   over a plain Tailwind margin utility on this ul since neither a
   single class nor that ul's own tag-name selector alone would beat
   a rule combining both. Scoped through the tags section specifically
   so other .article ul elements keep their intended spacing. */
.article .tags ul { margin: 0; }
.article .tags li { margin: 0; }

/* ---------------------------------------------------------------
   Prev / next pager
--------------------------------------------------------------- */
/* Simple text-link row (page counter or prev link on the left, next
   link on the right, separated by a top border) rather than the
   two-card grid this replaced — matching both the reference file and
   the actual mockup, cross-checked directly against each other after
   the reference's structure here initially looked like it might be a
   further instance of the reference/mockup divergence seen elsewhere
   in this project (colors, the quiz progress bar, tag shape) but
   turned out this time to genuinely match the mockup exactly: a
   minimal "1/146" counter plus a single, unboxed "next lesson →"
   link, no bordered cards at all. All of .pager__link's old
   card-styling properties (padding, background, border, max-width)
   and the now-unused .pager__text/.pager__label/.pager__title rules
   (that nested label+title structure isn't part of the new markup)
   are removed below rather than kept dormant. */
.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin: 36px 0;
}
.pager--top {
  margin-top: 20px;
  margin-bottom: 28px;
}
/* #0e172b per explicit request (was #4f46e5, and #334155 plain slate
   before that). */
.pager__link { color: #0e172b; }
.pager__link:hover { color: #0e172b; }

/* ---------------------------------------------------------------
   Was this helpful?
--------------------------------------------------------------- */
/* Card styling (background/border/radius/padding/centering) used to
   live here on the outer <section>, but the markup's inner div now
   carries its own Tailwind card utilities (rounded-2xl border
   border-slate-200 bg-white p-6 text-center shadow-xs) for exactly
   the same properties — leaving both meant every visit rendered a
   card nested inside an identical card, a double border/box the
   target design doesn't have. Kept to just the section's own outer
   spacing; the inner div owns the actual card now. */
.feedback { margin: 0 0 28px; }
.feedback__question { margin: 0; font-weight: 700; font-size: 0.88rem; color: var(--ink); }
.feedback__buttons { display: flex; gap: 10px; }
/* Background, border, border-radius, padding, font-size and resting
   text color used to live here, but the markup now carries its own
   Tailwind utility classes for exactly those properties, one variant
   for "Yes" (emerald) and one for "No" (rose) per the mockup — this
   base rule's own copies of them were unlayered CSS silently beating
   those layered utilities regardless of specificity (the same
   Tailwind-v4-layer gotcha documented elsewhere in this project),
   flattening both buttons to the same plain gray look. Keeping only
   the structural, variant-independent properties here lets the
   Tailwind classes control color per button as intended. */
.feedback__btn {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--sans);
  cursor: pointer;
}
.feedback__btn.is-selected { color: var(--accent); border-color: var(--accent); background: var(--color-primary-subtle); }
.feedback__btn:disabled { cursor: default; opacity: 0.75; }
.feedback__count { font-variant-numeric: tabular-nums; }
.feedback__thanks { margin: 0; font-size: 0.85rem; color: var(--ink-soft); }

/* ---------------------------------------------------------------
   Style guide
--------------------------------------------------------------- */
.styleguide {
  /* min-width: 0 overrides the browser default of min-width: auto
     for a grid/flex item. Without it, a wide-but-scrollable
     descendant (like a quiz question's <pre> code block, which has
     overflow-x: auto but also long unbroken lines) can still force
     this whole column wider than its 1fr grid track intends, since
     grid track sizing considers a descendant's min-content width
     before overflow rules ever get applied.

     width: 100% is just as essential here as min-width: 0, for a
     related but distinct reason: width: auto combined with the
     margin: 0 auto below (both margins auto) disables a grid item's
     default stretch-to-fill behavior — auto margins on a grid item
     consume the leftover space themselves, which makes the item
     shrink-to-fit its own content instead of filling (then being
     capped by max-width within) its track. That's what actually
     caused the visible width difference between quiz questions:
     without width: 100%, this box was silently resizing to whatever
     each question's own content happened to need — shorter question
     text and a short code block making it narrower, a longer one
     making it wider — never reliably filling or capping at 900px at
     all. width: 100% resolves the box's width from the grid track
     first, and max-width then caps that, before auto margins get
     any leftover space to center within.
  */
  min-width: 0;
  width: 100%;
  max-width: 900px;
  margin: 0 auto;
  padding: 48px 24px 80px;
}
.styleguide__intro { margin-bottom: 40px; }
/* Middle-panel parity with the lesson page's own #docs-main h1: same
   extra-bold weight and tight tracking, and bottom-only margin (was
   10px 0, adding an extra top gap the lesson page's h1 doesn't have). */
.styleguide__intro h1 {
  /* 2.25rem per the supplied reference (pixel-measured cap-height
     matches the lesson page's own desktop #docs-main h1 size, was
     1.9rem). */
  font-size: 2.25rem;
  font-weight: 800;
  letter-spacing: -0.025em;
  margin: 0 0 10px;
}
.sg-section {
  margin-bottom: 40px;
  padding-bottom: 32px;
  border-bottom: 1px solid var(--border);
}
.sg-section h2 { font-size: 1.2rem; margin: 0 0 18px; }
.sg-note { color: var(--ink-soft); font-size: 0.88rem; margin-top: 16px; }
.sg-swatches { display: flex; flex-wrap: wrap; gap: 20px; }
.sg-swatch {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 0.8rem;
  width: 110px;
}
.sg-swatch__block {
  display: block;
  height: 64px;
  border-radius: 8px;
  border: 1px solid var(--border);
}
.sg-swatch code { font-size: 0.75rem; }
.sg-type { margin: 0 0 14px; }
.sg-icons { display: flex; gap: 32px; }
.sg-icon-sample {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--ink-soft);
}
.sg-icon-sample .icon { width: 20px; height: 20px; color: var(--accent); }
.sg-row { display: flex; align-items: center; gap: 16px; }
.sg-chip-demo {
  display: inline-block;
  padding: 5px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.82rem;
  color: var(--ink-soft);
}
.home {
  max-width: 1280px; /* per explicit request, was 1400px */
  margin: 0 auto;
  padding: 56px 24px 80px;
}
.home__hero { text-align: center; margin-bottom: 48px; }
.home__eyebrow {
  color: var(--accent);
  font-weight: 600;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  margin: 0 0 12px;
}
.home__hero h1 {
  font-size: 2.3rem;
  line-height: 1.2;
  margin: 0 0 16px;
  letter-spacing: -0.01em;
}
.home__lede {
  color: var(--ink-soft);
  font-size: 1.1rem;
  max-width: 560px;
  margin: 0 auto;
}
.home__group-heading {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 14px;
}
.home__courses {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  margin-bottom: 32px;
}
.home__course-card {
  background: var(--surface);
  border: 1px solid var(--border);
  /* 16px — constancy check: matches the lesson page's own content
     cards (rounded-2xl), the site's reference-verified standard for
     this "bordered content card" pattern (was 12px). */
  border-radius: 16px;
  padding: 28px;
  display: flex;
  flex-direction: column;
  /* Resting shadow-xs — constancy check: the lesson page's own
     content cards carry Tailwind's shadow-xs at rest; this card had
     no shadow until hover, reading "flatter" than its lesson-page
     counterpart. */
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
.home__course-title-group {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 10px;
}
/* 1.25rem — constancy check: matches the lesson page's own section
   headings (was 1.3rem), the same "this card's title" role. */
.home__course-card h2 { margin: 0; font-size: 1.25rem; }
/* 0.875rem — constancy check: this had no font-size at all, so it
   inherited the 1rem base and read larger than the equivalent
   secondary card text everywhere else on the site (the lesson page's
   own card copy, and .quiz-level-card p, are both text-sm/0.88rem). */
.home__course-card p { color: var(--ink-soft); margin: 0 0 20px; font-size: 0.875rem; }
.home__course-card-link {
  position: absolute;
  inset: 0;
  z-index: 1;
}
.home__course-card {
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
/* border-color: var(--accent) — constancy check: was var(--ink-soft),
   a neutral gray; .quiz-level-card's identical hover treatment (same
   shadow) already uses the brand accent color, so this now matches
   that established hover language instead of being the one card on
   the site that turns gray on hover. */
.home__course-card:hover {
  border-color: var(--accent);
  box-shadow: 0 4px 16px rgba(15, 16, 19, 0.08);
}





/* ---------------------------------------------------------------
   404 page inline search
--------------------------------------------------------------- */
.search-inline {
  display: flex;
  gap: 8px;
  margin-top: 24px;
  max-width: 420px;
}
.search-inline input {
  flex: 1;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-family: var(--sans);
  font-size: 0.92rem;
}
.search-inline button {
  background: var(--primary);
  color: #FFFFFF;
  border: none;
  border-radius: 6px;
  padding: 10px 16px;
  font-weight: 600;
  cursor: pointer;
}
.search-inline button:hover { background: var(--primary-dark); }

/* ---------------------------------------------------------------
   Code Checker tool
--------------------------------------------------------------- */
.checker-results { padding: 16px; overflow-y: auto; flex: 1; }

/* ---------------------------------------------------------------
   Compare Checker: two full checker panels (language buttons, code
   input, results) side by side, each independent.
--------------------------------------------------------------- */
.compare-checker {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 0;
}
.compare-checker__panel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}
.compare-checker__panel:first-child { border-right: 1px solid var(--border); }
.compare-checker__panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.compare-checker__panel-label {
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--ink);
}
.compare-checker__code {
  flex: 1 1 auto;
  min-height: 0;
  border-bottom: none;
}


.checker-results__empty { color: var(--ink-soft); font-size: 0.9rem; }
.checker-results__summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-radius: 8px;
  font-weight: 700;
  margin-bottom: 14px;
}
.checker-results__summary--ok { background: var(--color-success-bg); color: var(--color-success-text); }
.checker-results__summary--issues { background: var(--color-error-bg); color: var(--color-error-text); }
.checker-issue {
  padding: 10px 12px;
  border-left: 3px solid var(--color-error-border);
  background: var(--color-error-bg);
  border-radius: 0 6px 6px 0;
  margin-bottom: 8px;
  font-size: 0.88rem;
}
.checker-issue--warning { border-left-color: var(--color-warning-text); background: var(--color-warning-bg); }
.checker-issue__line { font-family: var(--mono); font-weight: 700; margin-right: 6px; color: var(--ink-soft); }

/* ---------------------------------------------------------------
   Mobile / tablet: hamburger-triggered sidebar drawer,
   "On this page" rail hidden, and general responsive polish
--------------------------------------------------------------- */



/* ---------------------------------------------------------------
   Standalone editor: autocomplete suggestion dropdown
--------------------------------------------------------------- */
.editor-autocomplete {
  position: absolute;
  display: none;
  margin: 0;
  padding: 4px;
  list-style: none;
  min-width: 140px;
  max-height: 200px;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(28, 27, 43, 0.14);
  font-family: var(--mono);
  font-size: 0.85rem;
  z-index: 200;
}
.editor-autocomplete li {
  padding: 5px 8px;
  border-radius: 5px;
  cursor: pointer;
  color: var(--ink);
}
.editor-autocomplete li:hover,
.editor-autocomplete li.is-active {
  background: var(--color-primary-subtle);
  color: var(--accent);
}

/* ---------------------------------------------------------------
   Leveled quiz landing page (Beginner/Intermediate/Advanced cards)
--------------------------------------------------------------- */
.quiz-levels {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.quiz-level-card {
  display: block;
  padding: 22px 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  /* 16px — constancy check: matches the site's other bordered content
     cards (was 8px), same reasoning as .home__course-card above. */
  border-radius: 16px;
  color: var(--ink);
  text-align: center;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  /* Resting shadow-xs — constancy check, same reasoning as
     .home__course-card above. */
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
.quiz-level-card:hover { border-color: var(--accent); box-shadow: 0 4px 16px rgba(15, 16, 19, 0.08); text-decoration: none; }
/* 1.25rem — constancy check: matches the lesson page's section
   headings and .home__course-card's title (was 1.1rem). */
.quiz-level-card h2 { margin: 0 0 6px; font-size: 1.25rem; }
.quiz-level-card p { margin: 0; color: var(--ink-soft); font-size: 0.88rem; }


/* ---------------------------------------------------------------
   HTML Quiz: 20-level staged system
--------------------------------------------------------------- */
.quiz-intro-lede { color: var(--ink-soft); font-size: 1.05rem; margin: 0 0 20px; }
.level-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 8px;
}
.level-tab {
  padding: 10px 16px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink-soft);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.level-tab:hover { color: var(--ink); text-decoration: none; }
.level-tab.is-active { color: var(--accent); border-bottom-color: var(--accent); }
.level-tab--top { color: var(--color-warning-text); }
.level-tab--top:hover { color: var(--color-warning-text); }
.level-tab--top.is-active { color: var(--color-warning-text); border-bottom-color: var(--color-warning-text); }
.level-tab--top .level-tab__count { background: var(--color-warning-bg); color: var(--color-warning-text); }
.level-tab__count {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--bg);
  font-size: 0.74rem;
  font-weight: 700;
}
.level-tab.is-active .level-tab__count { background: var(--color-primary-subtle); color: var(--accent); }
.interview-faq { margin-top: 0; padding-top: 4px; }

.quiz-summary {
  /* Two-column grid, not a tight-gap flex row — matches the
     reference, where the second stat sits flush with the card's
     horizontal midpoint rather than immediately after the first
     stat's own width (was display:flex; gap:28px, which bunched
     both stats together on the left). */
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  padding: 24px 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  /* 12px — constancy check: matches the lesson sidebar's own bordered
     stat strip (.sidebar__progress), the same component (was 10px). */
  border-radius: 12px;
  margin-bottom: 32px;
}
.quiz-summary__stat { display: flex; flex-direction: column; gap: 2px; }
.quiz-summary__stat-num { font-size: 1.85rem; font-weight: 800; line-height: 1.2; color: #0e172b; }
.quiz-summary__stat-label { font-size: 0.85rem; color: var(--ink-soft); }

/* 32px — constancy check: matches the lesson page's own section
   gutter (.article .lesson-section) and .quiz-summary just above it
   on this same page (was 36px, a stray 4px mismatch). */
.quiz-stage { margin-bottom: 32px; }
.quiz-stage__heading {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 1.15rem;
  margin: 0 0 14px;
}
.quiz-stage__number {
  /* Plain muted number, no circle badge — matches the reference,
     which sets the stage index in the same weight/size as the
     heading text rather than as a pill (was a filled accent-tinted
     circle). */
  flex-shrink: 0;
  color: #94A3B8;
  font-size: 1em;
  font-weight: 700;
}
.quiz-stage__focus { font-weight: 400; color: var(--ink-soft); font-size: 0.85em; }
.quiz-stage__progress {
  margin-left: auto;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--ink-soft);
  white-space: nowrap;
}
.quiz-stage__progress.is-complete { color: var(--color-success-text); }
.quiz-levels--stage { grid-template-columns: repeat(4, 1fr); }


.quiz-level-card--soon { opacity: 0.5; cursor: default; }
.quiz-level-card { border-left: 3px solid transparent; }
.quiz-level-card.is-excellent { border-left-color: var(--color-success-text); }
.quiz-level-card.is-good { border-left-color: var(--accent); }
.quiz-level-card.is-practice { border-left-color: var(--color-warning-text); }
.quiz-level-card.is-retry { border-left-color: var(--color-error-text); }
.quiz-level-card__status { margin: 0; }

/* Loading skeleton shown while JS populates the quiz — without
   this, the container is genuinely empty markup, so a slow
   connection (or JS failing to run at all) leaves visible blank
   white space with no indication a quiz was ever coming. */
.quiz-lvl__loading-bar {
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--color-shimmer-1) 25%, var(--color-shimmer-2) 50%, var(--color-shimmer-1) 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
  margin-bottom: 24px;
}
.quiz-lvl__loading-line {
  height: 14px;
  border-radius: 6px;
  background: linear-gradient(90deg, var(--color-shimmer-1) 25%, var(--color-shimmer-2) 50%, var(--color-shimmer-1) 75%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
  margin-bottom: 12px;
  width: 60%;
}
.quiz-lvl__loading-line--wide { width: 90%; }
.quiz-lvl__loading-line--short { width: 40%; }


/* Header row parity with the supplied reference: the page's own H1
   and the "Started HH:MM" badge share one row (the badge lives in
   PHP markup right next to the H1, filled in by JS — see
   startedSlot above — rather than inside the card below, which the
   reference keeps free of it). */
.quiz-lvl__intro {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}
.quiz-lvl__started {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--ink-soft);
  font-size: 0.82rem;
  white-space: nowrap;
}

/* The whole question — meta, progress, difficulty/hint row, prompt,
   answer field, and actions — now sits inside one bordered/shadowed
   card, matching the site's established card pattern (same recipe
   as the Interview Prep tabs+accordion card) rather than sitting
   directly on the page background. */
.quiz-lvl-card {
  border: 1px solid var(--border);
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  padding: 24px;
}
.quiz-lvl-card__divider {
  border-top: 1px solid var(--border);
  margin: 20px 0;
}
.quiz-lvl-card__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}
.quiz-lvl__counter {
  font-size: 0.88rem;
  font-weight: 700;
  color: var(--ink);
}
/* Neutral gray, pixel-sampled from the reference's "Structure" badge
   — was accent-tinted (subtle indigo bg/text), which no longer
   reads right now that --accent is the site's dark navy rather than
   indigo; this topic badge was never meant to carry accent color in
   the reference to begin with. */
.quiz-lvl__topic-badge {
  padding: 2px 9px;
  border-radius: 999px;
  background: #F1F5F9;
  color: #1E293B;
  font-size: 0.74rem;
  font-weight: 600;
}

.quiz-lvl__progress {
  display: flex;
  gap: 4px;
}
.quiz-lvl__segment {
  flex: 1;
  height: 4px;
  border-radius: 999px;
  background: var(--border);
}
.quiz-lvl__segment.is-current { background: var(--ink); }
.quiz-lvl__segment.is-correct { background: var(--color-success-text); }
.quiz-lvl__segment.is-incorrect { background: var(--color-error-text); }

.quiz-lvl__meta2 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 16px;
}
/* Difficulty badge, pixel-sampled from the reference's "EASY" pill
   (#4F46E5 text on a #EEF2FE tint) — this site's own former indigo
   accent, reintroduced here specifically as this badge's own color
   rather than reverting the site-wide accent change; every other
   difficulty label reuses the same treatment absent a reference
   showing otherwise. */
.quiz-lvl__diff {
  display: inline-flex;
  padding: 3px 10px;
  border-radius: 999px;
  background: #EEF2FE;
  color: #4F46E5;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.quiz-lvl__hint-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  border: none;
  background: none;
  padding: 0;
  color: var(--ink-soft);
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
}
.quiz-lvl__hint-btn:hover,
.quiz-lvl__hint-btn.is-active { color: #4F46E5; }
.quiz-lvl__hint {
  padding: 10px 14px;
  margin: 0 0 16px;
  border-radius: 8px;
  background: #EEF2FE;
  color: #3730A3;
  font-size: 0.85rem;
  line-height: 1.5;
}

.quiz-lvl__question { border: none; padding: 0; margin: 0; }
.quiz-lvl__question legend { font-weight: 700; font-size: 1.3rem; line-height: 1.35; padding: 0; margin-bottom: 18px; color: var(--ink); }
.quiz-lvl__code {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px 16px;
  margin: 0 0 16px;
  max-width: 100%;
  overflow-x: auto;
  font-family: var(--mono);
  font-size: 0.85rem;
}

.quiz-lvl__options { display: flex; flex-direction: column; gap: 8px; margin-bottom: 16px; }
.quiz-lvl__option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.92rem;
  transition: border-color 0.12s ease, background 0.12s ease;
}
/* Same min-width: auto default issue as the grid tracks above, just
   the flexbox version of it: without min-width: 0 here, this text
   span (a flex child) could force the option row wider than
   intended if the option text is long or hard to break cleanly. */
.quiz-lvl__option > span:last-child { min-width: 0; overflow-wrap: break-word; }
.quiz-lvl__option:hover { border-color: var(--accent); }
/* :focus-within rather than relying on the native radio's own
   outline alone — that outline only draws around the small circular
   input itself, easy to miss within a much larger clickable row.
   Highlighting the whole option box gives keyboard users the same
   clear "this is where you are" signal mouse users get from hover,
   without waiting until an option is actually selected. */
.quiz-lvl__option:focus-within { border-color: var(--accent); box-shadow: 0 0 0 2px var(--color-primary-subtle); }
/* Visual feedback for the option currently picked, before Check
   answer is even clicked — without this, clicking a radio gives
   almost no feedback beyond the browser's own tiny native dot,
   which makes the whole interaction feel unresponsive. */
.quiz-lvl__option:has(input:checked) {
  border-color: var(--accent);
  background: var(--color-primary-subtle);
}
.quiz-lvl__option:has(input:checked) .quiz-lvl__option-letter {
  background: var(--accent);
  color: #FFFFFF;
}
.quiz-lvl__option input { flex-shrink: 0; }
.quiz-lvl__option-letter {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: var(--bg);
  font-size: 0.78rem;
  font-weight: 700;
  transition: background 0.12s ease, color 0.12s ease;
}
.quiz-lvl__option.is-correct { border-color: var(--color-success-text); background: var(--color-success-bg); }
.quiz-lvl__option.is-incorrect { border-color: var(--color-error-text); background: var(--color-error-bg); }

/* Label above the answer field, matching the reference's "Your
   Answer / Code Solution:" caption — the field itself grew from a
   single-line input into a multi-line textarea in the same change
   (see rows="5" in app.js), since the reference clearly shows a tall
   answer box rather than one text line. */
.quiz-lvl__input-label {
  display: block;
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--ink);
  margin-bottom: 8px;
}
.quiz-lvl__input {
  display: block;
  width: 100%;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: var(--mono);
  font-size: 0.92rem;
  line-height: 1.5;
  resize: vertical;
  margin-bottom: 16px;
  transition: border-color 0.12s ease, background 0.12s ease;
}
.quiz-lvl__input:focus { border-color: var(--accent); outline: none; }
.quiz-lvl__input.is-correct { border-color: var(--color-success-text); background: var(--color-success-bg); }
.quiz-lvl__input.is-incorrect { border-color: var(--color-error-text); background: var(--color-error-bg); }

/* Icon + bold title + description, one shared shape for the
   missing-answer validation notice and the correct/incorrect result
   after checking — matches the reference's "Empty Answer" card
   (icon, bold heading, description line below it), was a single
   line of plain text with no title or icon. */
.quiz-lvl__explain {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 14px 16px;
  border: 1px solid transparent;
  border-radius: 8px;
  margin: 0 0 16px;
}
.quiz-lvl__explain-icon { flex-shrink: 0; margin-top: 1px; }
.quiz-lvl__explain-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.quiz-lvl__explain-title { font-size: 0.92rem; font-weight: 700; }
.quiz-lvl__explain-desc { font-size: 0.88rem; line-height: 1.5; }
.quiz-lvl__explain--correct {
  background: var(--color-success-bg);
  border-color: var(--color-success-border);
  color: var(--color-success-text);
}
.quiz-lvl__explain--incorrect {
  background: var(--color-error-bg);
  border-color: var(--color-error-border);
  color: var(--color-error-text);
}
.quiz-lvl__explain--validation {
  background: var(--color-warning-bg);
  border-color: var(--color-warning-border);
  color: var(--color-warning-text);
}

/* Skip on its own at the left, Check answer + Next question grouped
   at the right — matches the reference's button layout, was all
   three buttons grouped together at the start. */
.quiz-lvl__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; }
.quiz-lvl__actions-right { display: flex; flex-wrap: wrap; gap: 10px; }

/* Results screen now sits inside the same bordered/shadowed
   .quiz-lvl-card as the question screen (was its own unstyled block
   sitting directly on the page background) — text-align/padding
   here layers on top of the card's own 24px padding rather than
   replacing it. */
.quiz-lvl__results { text-align: center; padding: 16px 0; }
.quiz-lvl__score { font-size: 2.2rem; font-weight: 700; margin: 0; }
.quiz-lvl__band { font-size: 1.05rem; font-weight: 600; margin: 0 0 4px; }
.quiz-lvl__time { font-size: 0.85rem; color: var(--ink-soft); margin: 0 0 20px; }
.quiz-lvl__results--excellent .quiz-lvl__band { color: var(--color-success-text); }
.quiz-lvl__results--good .quiz-lvl__band { color: var(--accent); }
.quiz-lvl__results--practice .quiz-lvl__band { color: var(--color-warning-text); }
.quiz-lvl__results--retry .quiz-lvl__band { color: var(--color-error-text); }

.quiz-lvl__topics { max-width: 360px; margin: 0 auto 16px; text-align: left; }
.quiz-lvl__topics-heading {
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink-soft);
  margin: 0 0 8px;
}
.quiz-lvl__topic-row {
  display: flex;
  justify-content: space-between;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 0.9rem;
}
.quiz-lvl__topic-row.is-weak { color: var(--color-error-text); font-weight: 600; }
.quiz-lvl__weak-note {
  max-width: 360px;
  margin: 0 auto 20px;
  padding: 10px 14px;
  background: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
  border-radius: 8px;
  color: var(--color-warning-text);
  font-size: 0.85rem;
  text-align: left;
}
.quiz-lvl__results .quiz-lvl__actions { justify-content: center; margin-bottom: 16px; }
.quiz-lvl__back { margin: 0; }

/* Matches the reference file's own font-sans (Tailwind's default
   system-font stack) for the redesigned lesson-page content — not
   a custom "Inter" web font as an earlier pass through this file
   assumed from the mockup screenshot alone, before an actual copy of
   the reference HTML/Tailwind source this project has been matching
   against was available to check directly. Tailwind's font-sans
   stack itself lists "Noto Sans" as a fallback entry, which this
   site already loads explicitly as its site-wide base font (see
   --sans in tokens.css) rather than leaving it to chance via system
   availability — so using --sans directly here, with no additional
   font-family layered in front of it, tracks the reference's actual
   intent more closely than the previous Inter override did. Scoped
   to #docs-main rather than changing the global body font, same as
   the property this replaces was scoped, since that's a separate,
   pre-existing site-wide decision this lesson-page redesign doesn't
   otherwise touch. */
#docs-main { font-family: var(--sans); }

/* Dark-themed code blocks within the lesson's own written content
   specifically (#article-body — data.php's authored HTML), matching
   the supplied mockup. CSS-only, deliberately: an earlier attempt at
   this same visual result added a second, competing JavaScript
   wrapper around these same code blocks, which conflicted with the
   .code-block/.code-toolbar/.code-line system above (already
   providing line numbers and copy/preview/edit buttons) badly enough
   to break its line numbering entirely (every line showing "1"
   instead of counting up) — confirmed and fixed by removing that
   duplicate script outright, not patching around it. This color
   override achieves the same dark-theme look working purely through
   that existing, working system's own CSS, so there's no second
   script left to conflict with it. Scoped to #article-body rather
   than the broader .article pre this overrides, since .article is
   also the main content wrapper on several other, untouched page
   templates (interview prep, quiz, etc.) whose own code blocks should
   keep their original light styling. */
#article-body pre {
  background: #0F172A;
  color: #E2E8F0;
  border-color: #1E293B;
}
#article-body .code-line::before { color: #64748B; opacity: 1; }
#article-body .code-copy,
#article-body .code-preview-btn,
#article-body .code-edit-btn {
  background: #1E293B;
  border-color: #334155;
  color: #94A3B8;
}
#article-body .code-copy:hover,
#article-body .code-preview-btn:hover,
#article-body .code-edit-btn:hover { color: #F1F5F9; border-color: #475569; }

/* Styling for the raw, hand-authored lesson content in #article-body
   (data.php's $article['content'] — plain <p>, <pre><code>, <ul>
   etc. with no classes of their own, so they can't be targeted with
   Tailwind utility classes directly the way the rest of this
   redesign's own markup can). Plain CSS here, rather than Tailwind's
   typography plugin (prose classes), since that plugin was never
   actually installed as part of this project's Tailwind build —
   using its class names without it present would silently generate
   no CSS at all. */
#article-body p { color: #334155; line-height: 1.7; margin: 0 0 16px; }
#article-body p:last-child { margin-bottom: 0; }
/* No #article-body pre background/border/padding/margin rule here —
   the existing .code-block/.article pre system above already governs
   all of that (border, radius, padding) for every code block in this
   area; an earlier, now-removed version of this rule duplicated those
   properties with slightly different values, which — landing later
   in this same file at equal selector specificity — was silently
   winning over and undoing the dark-theme override just above,
   despite that override coming first. */
#article-body code { font-family: var(--font-brand, monospace); font-size: 0.9em; }
#article-body ul, #article-body ol { color: #334155; line-height: 1.7; margin: 0 0 16px; padding-left: 24px; }
