
/* Theme variables -- dark is the default/original palette (unchanged
   values from before this variable pass), overridden by
   [data-theme="light"] set on <html> via the toggle in the tools nav /
   chrome header (SITE_JS toggleTheme()). Semantic accent colors
   (success/error/warning) are kept close to their dark-mode hues in
   light mode too, just darkened slightly for contrast on a white
   background -- that's how most real light/dark course-platform themes
   handle it, not a full hue change per mode. */
:root {
  --bg: #1a1a2e; --bg-alt: #16162a; --bg-panel: #22223a; --bg-deep: #0f0f1e;
  --surface-sunken: #0f0f1e; --input-bg: #12121f;
  --text: #eee; --text-secondary: #ccc; --text-muted: #999; --text-faint: #8b8ba3; --text-disabled: #5a5a70;
  --border: #444; --border-alt: #333; --border-strong: #555; --divider: #262638;
  --accent: #7ec8e3; --accent-strong: #a8d8ea; --accent-hover: #a8d8ea; --on-accent: #12121f;
  --success: #6fcf97; --success-bg: #1e3a2c; --success-hover: #85dba9; --on-success: #12121f; --on-success-bg: #fff;
  --error: #eb5757; --error-bg: #3a1e1e; --on-error-bg: #fff;
  --warning: #f2c94c; --hover-bg: #1e1e38;
  --r-sm: 6px; --r-md: 10px; --r-lg: 14px;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.24);
  --shadow-md: 0 2px 8px rgba(0,0,0,.28);
  --shadow-lg: 0 8px 24px rgba(0,0,0,.34);
  --focus-ring: 0 0 0 3px rgba(126,200,227,.45);
}
:root[data-theme="light"] {
  --bg: #f4f5f9; --bg-alt: #ffffff; --bg-panel: #ffffff; --bg-deep: #e9eaf0;
  --surface-sunken: #f1f2f7; --input-bg: #f7f8fb;
  --text: #1a1a2e; --text-secondary: #333; --text-muted: #666; --text-faint: #667085; --text-disabled: #98a2b3;
  --border: #ccc; --border-alt: #e4e7ec; --border-strong: #bbb; --divider: #e2e2ea;
  --accent: #1d6fa5; --accent-strong: #14507a; --accent-hover: #155a87; --on-accent: #fff;
  --success: #1e7a4c; --success-bg: #e3f5ea; --success-hover: #166139; --on-success: #fff; --on-success-bg: #14532d;
  --error: #b83232; --error-bg: #fbe6e6; --on-error-bg: #7f1d1d;
  --warning: #b54708; --hover-bg: #e8e9f2;
  --shadow-sm: 0 1px 2px rgba(16,24,40,.06);
  --shadow-md: 0 1px 3px rgba(16,24,40,.10), 0 4px 12px rgba(16,24,40,.06);
  --shadow-lg: 0 12px 32px rgba(16,24,40,.12);
  --focus-ring: 0 0 0 3px rgba(29,111,165,.30);
}
.theme-toggle-btn { background: none; border: 1px solid var(--border); color: var(--text-secondary); border-radius: var(--r-sm); padding: .3em .7em; cursor: pointer; font-size: 13px; }
.theme-toggle-btn:hover { border-color: var(--accent); color: var(--accent); }
.theme-toggle-btn:disabled { cursor: default; opacity: .6; }
/* Theme-toggle-spam toast -- see wireThemeToggles()'s rapid-toggle
   tracking in SITE_JS. Fixed/centered so it reads the same regardless of
   which theme-toggle button (chrome nav vs. the static lesson-page one)
   triggered it. */
.theme-spam-toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(0);
  background: var(--bg-alt); border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: .6em 1.1em; font-size: 13px; color: var(--text-secondary); box-shadow: var(--shadow-lg);
  z-index: 9999; opacity: 0; transition: opacity .2s, transform .2s; pointer-events: none;
}
.theme-spam-toast--shown { opacity: 1; transform: translateX(-50%) translateY(-6px); }
/* Final-answer toast (all 3 jokes seen) -- offers an actual Light/Dark
   choice instead of just text, so it needs real pointer events and room
   for two buttons, unlike the plain auto-hiding message toasts above. */
.theme-spam-toast--choice { pointer-events: auto; display: flex; flex-direction: column; gap: .5em; align-items: center; text-align: center; }
.theme-spam-toast__choices { display: flex; gap: .6em; }

/* Global focus ring + transitions -- was entirely absent (design review finding) */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none; box-shadow: var(--focus-ring); border-radius: var(--r-sm);
}
button, .flashcard__btn, .mark-complete, .theme-toggle-btn, a { transition: background .15s, border-color .15s, box-shadow .15s, color .15s; }
@media print { *, *::before, *::after { box-shadow: none !important; } }

.local-nav {
  position: sticky; top: 0; z-index: 99999;
  display: flex; justify-content: space-between; align-items: center; gap: 1em;
  padding: .6em 1em; background: var(--bg); color: var(--text);
  font-family: system-ui, sans-serif; font-size: 14px;
  border-bottom: 1px solid var(--border-alt); box-shadow: var(--shadow-sm);
}
.local-nav__link { color: var(--accent); text-decoration: none; }
.local-nav__link:hover { text-decoration: underline; }
.local-nav__dead { color: var(--text-disabled); }

#site-chrome {
  font-family: system-ui, sans-serif; font-size: 14px;
  background: var(--bg-alt); color: var(--text); border-right: 1px solid var(--border-alt);
  max-width: 320px;
  /* Parent (.course-player__content on captured pages, .lesson-page__layout
     on generated quiz pages) is a flex row with a real height constraint
     (fixed to the viewport) -- without height:100%/min-height:0 here, this
     flex item just grows past that height with its own content (all
     chapters' full lesson lists) instead of stretching to match and
     scrolling internally, and a flex item's default min-height:auto
     defeats align-items:stretch the moment content is taller than the
     container. */
  height: 100%; min-height: 0; overflow-y: auto;
}

/* Layout for generated (non-captured) quiz pages -- these have no
   Thinkific-captured flex/fixed scaffolding of their own (unlike real
   lesson pages, which bring .course-player__content/.course-player with
   them from the capture), so they need their own minimal equivalent:
   a fixed, full-viewport two-column row housing #site-chrome +
   scrollable quiz content, with the nav bar/notes-panel/scripts as
   plain body-level siblings after it (so they overlay on top via
   .local-nav's position:sticky, same as on real lesson pages, instead
   of being pushed below the two-column block in normal flow). */
body.lesson-page { margin: 0; }
.lesson-page__layout { position: fixed; inset: 0; display: flex; }
.lesson-page__main {
  /* padding-top needs to clear .local-nav, a body-level sibling (not a
     child of this fixed layout) that overlays the top of the viewport via
     position:sticky with no real scrolling ancestor -- see .local-nav's
     own comment. On a real captured lesson page the video/title above the
     fold happens to be taller than the nav bar already, so the overlay
     never visibly clips anything there; this synthetic page has no such
     buffer, so its own content (the <h1> right at the top) gets its top
     cut off by the nav bar without this. --nav-h is set in JS from the
     nav's actual rendered height (which varies: it wraps to 2 lines on a
     narrow/zoomed viewport), falling back to a generous static estimate
     for the brief window before that JS runs. */
  flex: 1; overflow-y: auto; box-sizing: border-box;
  padding: 2em; padding-top: calc(2em + var(--nav-h, 60px));
  background: var(--bg); color: var(--text); font-family: system-ui, sans-serif;
}
.lesson-page__main h1 { margin-top: 0; }
#site-chrome .chrome-error {
  padding: 1em; color: var(--text-faint); font-size: 13px; line-height: 1.5;
}
.chrome-header { padding: 1em; border-bottom: 1px solid var(--border-alt); }
.chrome-header__title { color: var(--accent); text-decoration: none; font-weight: 600; }
.chrome-header__title:hover { text-decoration: underline; }
.chapter__header {
  padding: .7em 1em; cursor: pointer; font-weight: 600; color: var(--accent-strong);
  border-bottom: 1px solid var(--divider);
  display: flex; justify-content: space-between; align-items: center; gap: .5em;
}
.chapter__header:hover { background: var(--hover-bg); }
.chapter__count { font-size: 11px; font-weight: 400; color: var(--text-faint); white-space: nowrap; }
.chapter__count--complete { color: var(--success); }
.chapter__panel { padding: .3em 0; }
.chapter__lessons { list-style: none; margin: 0; padding: 0; }
.chapter__lessons li { margin: 0; }
.chapter__empty { padding: .5em 1em; color: var(--text-faint); font-style: italic; font-size: 13px; }
.lesson-link {
  display: flex; align-items: center; gap: .4em;
  padding: .4em 1em .4em 1.2em; color: var(--text-secondary); text-decoration: none; font-size: 13px;
}
.lesson-link:hover { background: var(--hover-bg); color: var(--accent); }
.lesson-link--active { background: var(--hover-bg); color: var(--accent); font-weight: 600; }
.lesson-link__check {
  display: inline-block; width: 14px; height: 14px; flex: 0 0 auto;
  border: 1px solid var(--border-strong); border-radius: 50%; box-sizing: border-box;
}
.lesson-link__check--complete {
  border-color: var(--success); background: var(--success);
  position: relative;
}
.lesson-link__check--complete::after {
  content: ""; position: absolute; left: 4px; top: 1px;
  width: 4px; height: 8px; border: solid var(--bg-alt);
  border-width: 0 2px 2px 0; transform: rotate(45deg);
}
/* Warned completion: a yellow triangle instead of the green check --
   still completed, just flagged as having gone unusually fast. Built as
   a CSS triangle (border trick) rather than an image/icon font so it
   needs no extra asset and recolors for free with the theme variable. */
.lesson-link__check--warned {
  border-color: transparent; background: transparent;
  width: 0; height: 0;
  border-left: 7px solid transparent; border-right: 7px solid transparent;
  border-bottom: 12px solid var(--warning);
  border-radius: 0;
}
.chapter__count--warned { color: var(--warning); }
.chapter__warning-flag { color: var(--warning); font-size: 11px; white-space: nowrap; }
/* Only the profile-hub (full-sentence) version wraps to its own line --
   the sidebar's icon-only version stays inline next to the count, same
   row, since there's no room to spare there. */
.chapter__warning-flag--full {
  display: block; white-space: normal; margin-top: .2em; font-size: 12px;
}

/* Profile picker + course progress meter, in the chrome header */
.profile-picker { margin-top: .6em; font-size: 13px; }
.ph-recurrent { margin-top: 1.5em; padding-top: 1.2em; border-top: 1px solid var(--border-alt); }
.recurrent-track-row { margin: .8em 0; }
.recurrent-track-row select { background: var(--input-bg); border: 1px solid var(--border); color: var(--text); padding: .4em .6em; border-radius: var(--r-sm); font-size: 14px; }
#recurrent-complete-date { background: var(--input-bg); border: 1px solid var(--border); color: var(--text); padding: .4em .6em; border-radius: var(--r-sm); margin-right: .6em; }
.profile-picker__current { color: var(--accent-strong); display: flex; align-items: center; gap: .5em; }
.profile-picker__switch { color: var(--accent); text-decoration: underline; cursor: pointer; font-size: 12px; background: none; border: none; padding: 0; }
.profile-picker__form { display: flex; gap: .4em; }
.profile-picker__input {
  flex: 1; background: var(--bg-deep); border: 1px solid var(--border); color: var(--text);
  padding: .35em .5em; border-radius: 3px; font-size: 13px;
}
.profile-picker__submit {
  background: var(--accent); color: var(--bg-alt); border: none; border-radius: 3px;
  padding: .35em .8em; font-size: 13px; cursor: pointer; font-weight: 600;
}
.profile-picker__hint { color: var(--text-faint); font-size: 11px; margin: .3em 0 0; }

.course-progress { margin-top: .8em; }
.course-progress__bar {
  height: 8px; background: var(--bg-deep); border-radius: 4px; overflow: hidden;
}
.course-progress__fill { height: 100%; background: var(--success); width: 0%; transition: width .3s; }
.course-progress__pct { margin: .3em 0 0; font-size: 12px; color: var(--text-muted); }

.lesson-search {
  display: block; width: 100%; box-sizing: border-box; margin-top: .8em;
  background: var(--bg-deep); border: 1px solid var(--border); color: var(--text);
  padding: .4em .6em; border-radius: 3px; font-size: 13px;
}
.chapter--search-match { display: block !important; }
.lesson-link--search-hidden { display: none !important; }

/* Mark-complete toggle -- rendered in .mark-complete-bottom, a sticky
   BOTTOM bar, instead of the sticky top nav. See that rule below for
   why "bottom of each lesson" means a sticky bar here rather than a
   button appended after the reading content in the DOM. */
.mark-complete {
  background: none; border: 1px solid var(--border-strong); color: var(--text-secondary); border-radius: 3px;
  padding: .3em .8em; font-size: 13px; cursor: pointer;
}
.mark-complete:hover { border-color: var(--accent); color: var(--accent); }
.mark-complete--done { background: var(--success); border-color: var(--success); color: var(--bg-alt); font-weight: 600; }
/* Bare running clock next to Mark Complete/Notes -- deliberately no
   label or goal, see the JS comment on why. Muted so it reads as
   ambient chrome, not an alert. */
.lesson-timer {
  font-variant-numeric: tabular-nums; color: var(--text-faint); font-size: 13px;
  padding: .3em .4em; white-space: nowrap;
}
.mark-complete-banner {
  background: var(--bg-alt); border-left: 3px solid var(--warning); border-radius: var(--r-sm);
  padding: .7em 1em; margin: .5em 1em; font-size: 13px; color: var(--text-secondary);
  box-shadow: var(--shadow-sm);
  /* Same fix .notes-panel needed and for the same reason -- a plain
     static body-level sibling of the fixed-position course-player/
     lesson-page layer paints BEHIND it regardless of DOM order; without
     this the banner is invisible, covered by the video/lesson content. */
  position: relative; z-index: 1;
}
.mark-complete-banner--blocked { border-left-color: var(--danger, var(--warning)); }
/* Mark Complete + its gating banner, placed inside the actual lesson
   content (.fr-view's own reading text on a captured page, the quiz
   result/notice area when that's what's on the page, or
   .lesson-page__main on a generated quiz/test page) so it sits in the
   same white content pane as the lesson, right after it -- not as a
   separate bar in its own band of color. See the JS comment at
   markBottomAnchor for how that target is picked, and why a few
   naive-looking approaches (appending into .course-player__content, a
   flex ROW across video+sidebar; appending as a flex SIBLING of the
   video within .course-player__content-inner, which ignores that
   sibling's own visually-overflowing content when positioning the next
   flex item) land the button somewhere else entirely -- both confirmed
   live before landing on .fr-view itself. --mark-complete-bottom--floating
   is the fallback for the rare page with none of those anchors, so the
   button still renders somewhere rather than silently vanishing. */
.mark-complete-bottom {
  display: flex; align-items: center; gap: .8em; flex-wrap: wrap;
}
.mark-complete-bottom .mark-complete { font-size: 15px; padding: .5em 1.2em; }
.mark-complete-bottom--inline {
  margin: 2em 0 1em; padding-top: 1.2em; border-top: 1px solid var(--border-alt);
}
.mark-complete-bottom--inline .mark-complete-banner { margin: .6em 0 0; flex-basis: 100%; }
/* Thinkific's own leftover lesson-nav footer -- confirmed empty (no text,
   no children) on every captured page checked (17/17 in two chapters).
   It used to hold Thinkific's own Mark-as-Complete/prev/next controls;
   the capture process stripped those out but left the now-blank footer
   shell behind, a plain ~64px white bar sitting right below the lesson
   content. Harmless on its own, but once our own Mark Complete button
   is mounted right above it (inside .fr-view, same as this rule's
   sibling above), the two visually read as one confusing double-decker
   white strip -- hide the dead one. */
#course-player-footer { display: none; }
/* A second, bigger piece of reserved-but-now-dead space: the captured
   reading pane's content wrapper (hashed class, confirmed the same
   "_content_1yintd" across every captured lesson page checked in two
   chapters -- same Thinkific/Ember build) carries an 80px block
   ::after spacer, presumably originally sized to leave room for
   Thinkific's own in-pane complete/next controls. Nothing fills it now
   -- same dead-space problem as #course-player-footer above, just from
   a generated pseudo-element instead of a real one, so !important to
   beat it regardless of the original rule's specificity/order. If a
   future capture comes from a different Thinkific build with a
   different hash, this selector simply stops matching -- harmless, not
   a breakage, just the old dead space would reappear on pages from
   that build. */
._content_1yintd::after { content: none !important; }
/* The real root of the dead space below text/images/video on a captured
   lesson page: the wrapper around BOTH the video player AND the article
   text (hashed class, stable substring "_videoproxy__wrapper" across
   every captured page checked) has its own box height pinned to
   whatever the content pane's viewport-visible height happens to be
   (confirmed live: exactly matched .course-player__content-inner's
   clientHeight, which itself varies with the browser window), NOT to
   the height its actual content (video + full article text, or video +
   images) needs. Its real content spills out past that pinned box via
   overflow:visible, and since flex/flow siblings are positioned from
   each other's BOX size, not visual overflow, the pane's scrollable
   area ends up with that fixed box height reserved regardless of how
   long or short the real content is -- too little box height shows the
   button/content clipped mid-page; too much (a tall window, short
   lesson) leaves blank reserved space below everything, independent of
   whether the lesson has text, images, or a video. Freeing it to size
   to its actual content fixes both directions at once. */
[class*="_videoproxy__wrapper"] { height: auto !important; }
/* The actual root cause of the dead space below the lesson pane (not
   just the ::after spacer and footer row fixed above): the whole chain
   of wrapper layers between the page's one genuinely responsive
   container (.course-player__lesson, a flex child that DOES already
   fill the real viewport height, confirmed live) and the reading pane
   itself is frozen at the EXACT pixel dimensions the page happened to
   be at when it was captured -- .content-modal's own
   `grid-template-rows: 446px 64px` is the clearest example (the 64px
   row is the #course-player-footer's reserved track -- hiding that
   element above didn't free its grid row). None of this comes from an
   inline style (checked live, all empty) and none of it was findable
   by walking document.styleSheets either (every lookup by selector or
   property came back empty despite the rules visibly applying) --
   captured/frozen some other way this couldn't pin down, so these are
   blind overrides verified by their rendered effect rather than by
   finding and replacing the original rule. Each layer gets whatever
   sizing keeps it filling its own parent's real (now-responsive) box
   instead of its frozen capture-time size: flex:1 for a flex child,
   height:100% for a block/grid child, and grid-template-rows: ...1fr
   for a grid container's flexible row (keeping any fixed-size header
   row before it, e.g. .content-surface's 42px title bar, untouched).
   !important throughout since the original rules' specificity/order
   can't be inspected to safely rely on beating them otherwise. */
.surface__container { flex: 1 1 auto !important; min-height: 0 !important; }
.content-surface { height: 100% !important; grid-template-rows: 42px 1fr !important; }
.content-modal-wrapper { height: 100% !important; }
.content-modal { height: 100% !important; grid-template-rows: 1fr !important; }
.course-player__content-inner { height: 100% !important; }
.mark-complete-bottom--floating {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 99999;
  padding: .6em 1em; background: var(--bg); color: var(--text);
  font-family: system-ui, sans-serif; font-size: 14px;
  border-top: 1px solid var(--border-alt); box-shadow: var(--shadow-sm);
}
.mark-complete-bottom--floating .mark-complete-banner { margin: 0; flex-basis: 100%; order: -1; }
.notes-panel {
  background: var(--bg-alt); border: 1px solid var(--border-alt); border-radius: var(--r-md);
  padding: .8em; margin: .5em 1em; box-shadow: var(--shadow-sm);
  /* Needs to be a positioned element (any value, doesn't need to move) --
     it's a body-level sibling of the captured page's fixed-position
     .course-player content layer, same as .local-nav. A plain static div
     there always paints BEHIND a positioned sibling regardless of DOM
     order, so without this the whole panel renders invisible, covered by
     the video/lesson content -- confirmed via elementFromPoint landing on
     the VIDEO element instead of the notes textarea underneath it. */
  position: relative; z-index: 1;
}
.notes-textarea { width: 100%; min-height: 90px; background: var(--bg-deep); border: 1px solid var(--border); color: var(--text); border-radius: 4px; padding: .5em; font-family: inherit; font-size: 14px; box-sizing: border-box; resize: vertical; }
.notes-status { font-size: 12px; color: var(--text-faint); margin-top: .3em; min-height: 1.2em; }
.ph-notes__item { border-bottom: 1px solid var(--divider); padding: .6em 0; }
.ph-notes__lesson { color: var(--accent); font-size: 14px; text-decoration: none; }
.ph-notes__lesson:hover { text-decoration: underline; }
.ph-notes__text { color: var(--text-secondary); font-size: 13px; margin: .3em 0 0; white-space: pre-wrap; }
.badge-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 1em; }
.badge-card { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 1em; text-align: center; box-shadow: var(--shadow-md); }
.badge-card__icon { display: block; font-size: 2em; margin-bottom: .3em; }
.badge-card__title { display: block; color: var(--text); font-weight: 600; font-size: 14px; }
.badge-card__desc { display: block; color: var(--text-muted); font-size: 12px; margin-top: .3em; }
.dashboard-tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 1em; margin: 1.5em 0; }
.dashboard-tile { display: block; text-decoration: none; color: var(--text); transition: border-color .15s; }
.dashboard-tile[hidden] { display: none; } /* an author-stylesheet display:block above otherwise beats the UA [hidden] rule -- same fix as .tools-nav span[data-nav-role][hidden] */
.dashboard-tile:hover { border-color: var(--accent); }
.dashboard-tile .badge-card__title { color: var(--accent); }

.weak-bars { display: flex; flex-direction: column; gap: .5em; margin: .8em 0 1.5em; }
.weak-bar { display: grid; grid-template-columns: minmax(120px, 1fr) 2fr auto; align-items: center; gap: .8em; font-size: 13px; }
.weak-bar__label { color: var(--text-secondary); overflow-wrap: anywhere; }
.weak-bar__label a { color: inherit; text-decoration: underline; text-decoration-color: var(--border-alt); }
.weak-bar__label a:hover { color: var(--accent); }
.weak-bar__track { background: var(--bg-alt); border-radius: 999px; height: 10px; overflow: hidden; }
.weak-bar__fill { display: block; height: 100%; border-radius: 999px; }
.weak-bar--bad .weak-bar__fill { background: var(--error); }
.weak-bar--mid .weak-bar__fill { background: #d9a441; }
.weak-bar--good .weak-bar__fill { background: var(--success); }
.weak-bar__pct { color: var(--text-muted); white-space: nowrap; }
.weak-bar--unauthored { opacity: .55; }
.weak-bar--unauthored .weak-bar__fill { background: repeating-linear-gradient(45deg, var(--text-faint), var(--text-faint) 4px, transparent 4px, transparent 8px); }
.weak-bar--unanswered .weak-bar__fill { background: var(--border-alt); }
.weak-bar--lowsample .weak-bar__pct { font-style: italic; }

.continue-box { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 1em 1.2em; margin: 1em 0; box-shadow: var(--shadow-md); }
.continue-box__cta { display: inline-block; color: var(--accent); font-size: 1.1em; font-weight: 600; text-decoration: none; }
.continue-box__cta:hover { text-decoration: underline; }
.continue-box__cta::before { content: "▶  "; }
.continue-box__done { color: var(--success); font-weight: 600; margin: 0; }
.continue-box__meta { color: var(--text-muted); font-size: 13px; margin: .5em 0 0; }
.continue-box__stale { color: var(--accent-strong); font-size: 13px; margin: 0 0 .6em; }
.continue-box__reviewlinks { display: flex; flex-wrap: wrap; gap: .6em; margin-top: .6em; }
.continue-box__reviewlink { color: var(--accent); border: 1px solid var(--border-alt); border-radius: var(--r-md); padding: .4em .8em; font-size: 13px; text-decoration: none; }
.continue-box__reviewlink:hover { background: var(--hover-bg); }

.testday-section { margin: 1.5em 0; }
.testday-section > h2 { border-bottom: 1px solid var(--border-alt); padding-bottom: .3em; }
.testday-item { margin: .8em 0; }
.testday-item h3 { color: var(--accent); font-size: 15px; margin: 0 0 .2em; }
.testday-item p { margin: 0; color: var(--text-secondary); }
.testday-verified { color: var(--text-faint); font-size: 12px; border-left: 3px solid var(--border-alt); padding-left: .8em; }

.cheatsheet-section { margin: 1.2em 0; break-inside: avoid; }
.cheatsheet-section > h2 { border-bottom: 1px solid var(--border-alt); padding-bottom: .2em; font-size: 16px; }
.cheatsheet-section li { color: var(--text-secondary); margin: .3em 0; line-height: 1.4; }
.cheatsheet-disclaimer { color: var(--text-faint); font-size: 11px; margin-top: 2em; }

.airspace-tabs { display: flex; gap: .5em; flex-wrap: wrap; margin: 1em 0; border-bottom: 1px solid var(--border-alt); }
.airspace-tabs__btn { background: none; border: none; color: var(--text-muted); padding: .6em 1em; cursor: pointer; font-size: 14px; border-bottom: 2px solid transparent; }
.airspace-tabs__btn--active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.airspace-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1.2em; }
.airspace-card { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 1em; box-shadow: var(--shadow-md); }
.airspace-card__svg { display: flex; align-items: center; justify-content: center; min-height: 140px; }
.airspace-card h3 { margin: .5em 0 .2em; font-size: 15px; }
.airspace-card__meaning { color: var(--text-secondary); font-size: 13px; margin: .3em 0; }
.airspace-card__op { color: var(--text-muted); font-size: 12px; }
.airspace-compare__pickers { display: flex; gap: 1em; margin-bottom: 1em; flex-wrap: wrap; }
.airspace-compare__view { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1.2em; }
.airspace-drill__prompt { min-height: 160px; }
.airspace-tile__wrap { overflow-x: auto; margin: 1em 0; }
.airspace-tile__wrap svg { display: block; max-width: 100%; height: auto; }

.wx-row { display: grid; grid-template-columns: 140px 140px 1fr; gap: .8em; padding: .4em 0; border-bottom: 1px solid var(--border-alt); font-size: 13px; align-items: baseline; }
.wx-row__label { color: var(--text-muted); }
.wx-row__raw { color: var(--accent); }
.wx-row__meaning { color: var(--text-secondary); }
.wx-warning { color: var(--error); font-size: 13px; margin-top: .6em; }
.wx-legality { margin-top: 1.2em; padding: 1em; border: 1px solid var(--border-alt); border-radius: var(--r-md); background: var(--bg-panel); }
.wx-legality h3 { margin: 0 0 .5em; font-size: 15px; }
.wx-legality__good { color: var(--success); font-size: 13px; margin: .3em 0; }
.wx-legality__bad { color: var(--error); font-size: 13px; margin: .3em 0; font-weight: 600; }
/* Discussion module -- built, not yet activated on any page (see SITE_JS renderDiscussionThread) */
.discussion-item { border-bottom: 1px solid var(--divider); padding: .6em 0; }
.discussion-item__author { color: var(--accent); font-size: 12px; font-weight: 600; }
.discussion-item__text { color: var(--text-secondary); font-size: 14px; margin: .3em 0 0; white-space: pre-wrap; }
.discussion-form { margin-top: 1em; }

.quiz-notice {
  padding: 1em; background: var(--bg-panel); border: 1px solid var(--border); color: var(--text-secondary);
  font-family: system-ui, sans-serif;
}
.quiz-notice strong { display: block; margin-bottom: .3em; }

.quiz-practice-launch {
  display: block; margin: 0 0 1em; background: var(--accent); color: var(--bg-alt);
  border: none; border-radius: 4px; padding: .6em 1.2em; font-size: 14px;
  font-weight: 600; cursor: pointer; font-family: system-ui, sans-serif;
}
.quiz-practice-launch:hover { background: var(--accent-hover); }
.quiz-practice-launch:disabled { background: var(--border); color: var(--text-muted); cursor: default; }
.quiz-practice-launch:disabled:hover { background: var(--border); }
.quiz-practice {
  font-family: system-ui, sans-serif; background: var(--bg-panel); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 1.5em; max-width: 700px; box-shadow: var(--shadow-md);
}
.quiz-practice__progress { color: var(--text-faint); font-size: 13px; margin: 0 0 .5em; }
.quiz-practice__question { color: var(--text); font-size: 17px; line-height: 1.5; margin: 0 0 1.2em; }
.quiz-scenario { background: var(--bg-panel); border: 1px solid var(--border-alt); border-left: 4px solid var(--accent); border-radius: var(--r-sm); padding: .8em 1em; margin-bottom: .8em; font-size: 15px; font-family: ui-monospace, "SF Mono", Consolas, monospace; white-space: pre-wrap; }
.quiz-scenario__ask { font-weight: 600; }
.quiz-practice__explanation {
  color: var(--text-secondary); background: var(--bg); border-left: 3px solid var(--accent);
  padding: .8em 1em; margin: 0 0 1.2em; line-height: 1.5;
}
.quiz-practice__show, .quiz-practice__grade {
  border: 1px solid var(--border-strong); background: none; color: var(--text-secondary); border-radius: 4px;
  padding: .5em 1.1em; font-size: 14px; cursor: pointer; margin-right: .6em;
}
.quiz-practice__show:hover { border-color: var(--accent); color: var(--accent); }
.quiz-practice__grade-wrap { display: flex; gap: .6em; flex-wrap: wrap; }
.quiz-practice__grade--right { border-color: var(--success); }
.quiz-practice__grade--right:hover { background: var(--success); color: var(--bg-alt); }
.quiz-practice__grade--wrong { border-color: var(--error); }
.quiz-practice__grade--wrong:hover { background: var(--error); color: var(--bg-alt); }
.quiz-practice__summary { color: var(--text); font-size: 18px; font-weight: 600; margin: 0 0 1em; }
.quiz-practice__saved { color: var(--text-faint); font-size: 12px; margin: 1em 0 0; }

.quiz-mc-launch { background: var(--success); }
.quiz-mc-launch:hover { background: var(--success-hover); }
.quiz-cooldown-note { color: var(--text-muted); font-size: 13px; margin: .4em 0 1em; }
.quiz-onetime-note {
  color: var(--text-secondary); background: var(--bg-alt); border: 1px solid var(--border);
  border-radius: var(--r-sm); padding: .5em .8em; font-weight: 600;
}
.ph-history__reset {
  margin-left: .6em; font-size: 12px; padding: .2em .6em; border-radius: var(--r-sm);
  border: 1px solid var(--border); background: none; color: var(--text-secondary); cursor: pointer;
}
.ph-history__reset:hover { border-color: var(--accent); color: var(--accent); }
.quiz-mc__choices { display: flex; flex-direction: column; gap: .5em; margin-bottom: 1.2em; counter-reset: choice-num; }
.quiz-mc__choice {
  display: block; text-align: left; background: var(--surface-sunken); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--r-sm); padding: .7em 1em; font-size: 14px; cursor: pointer; font-family: system-ui, sans-serif;
}
.quiz-mc__choice:hover:not(:disabled) { border-color: var(--accent); background: var(--hover-bg); }
.quiz-mc__choice:disabled { cursor: default; opacity: .75; }
.quiz-mc__choice { position: relative; padding-left: 2.2em; min-height: 44px; }
.quiz-mc__choice::before { counter-increment: choice-num; content: counter(choice-num); position: absolute; left: .7em; top: 50%; transform: translateY(-50%); opacity: .45; font-size: 11px; border: 1px solid currentColor; border-radius: 3px; width: 1.3em; height: 1.3em; display: flex; align-items: center; justify-content: center; }
.quiz-mc__choice--correct { border-color: var(--success) !important; background: var(--success-bg) !important; opacity: 1 !important; color: var(--on-success-bg); }
.quiz-mc__choice--wrong { border-color: var(--error) !important; background: var(--error-bg) !important; opacity: 1 !important; color: var(--on-error-bg); }
/* Select-all ("choose ALL answers that apply") questions -- a <label>
   wrapping a real checkbox instead of a <button>, since answering requires
   toggling possibly-several choices before a separate Submit grades them,
   unlike single-select's click-one-button-to-answer-immediately model. */
.quiz-mc__choice--checkbox { display: flex; align-items: center; gap: .7em; padding-left: 1em; }
.quiz-mc__choice--checkbox::before { display: none; }
.quiz-mc__checkbox-input { width: 18px; height: 18px; flex: 0 0 auto; cursor: pointer; accent-color: var(--accent); }
.quiz-mc__choice--checkbox:has(.quiz-mc__checkbox-input:disabled) { cursor: default; opacity: .75; }
.quiz-mc__multi-hint { color: var(--text-faint); font-size: 13px; margin: .2em 0 0; font-style: italic; }
.quiz-confidence { display: flex; align-items: center; gap: .6em; margin: .8em 0; font-size: 13px; }
.quiz-confidence__label { color: var(--text-muted); }
.quiz-confidence__btn { background: none; border: 1px solid var(--border-alt); color: var(--text-secondary); border-radius: var(--r-md); padding: .3em .8em; cursor: pointer; font-size: 13px; }
.quiz-confidence__btn:hover { background: var(--hover-bg); }
.quiz-confidence__btn--active { border-color: var(--accent); color: var(--accent); font-weight: 600; }
.confidence-breakdown { display: flex; flex-wrap: wrap; gap: .5em; margin: .8em 0; }
.confidence-breakdown__item { font-size: 12px; padding: .3em .7em; border-radius: 999px; border: 1px solid var(--border-alt); }
.confidence-breakdown__item--good { color: var(--success); border-color: var(--success); }
.confidence-breakdown__item--mid { color: #d9a441; border-color: #d9a441; }
.confidence-breakdown__item--bad { color: var(--error); border-color: var(--error); }

.plan-setup { display: flex; flex-wrap: wrap; gap: 1em; align-items: center; margin: 1em 0; }
.plan-banner { background: var(--bg-panel); border: 1px solid var(--accent); border-radius: var(--r-md); padding: .8em 1em; margin: 1em 0; font-size: 13px; }
.plan-days { display: flex; flex-direction: column; gap: .4em; margin: 1em 0; }
.plan-day { display: grid; grid-template-columns: 110px 1fr 80px; gap: .8em; padding: .5em .8em; border-radius: var(--r-md); font-size: 13px; align-items: center; background: var(--bg-panel); border: 1px solid var(--border-alt); }
.plan-day--today { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.plan-day--done .plan-day__status { color: var(--success); }
.plan-day--partial .plan-day__status { color: #d9a441; }
.plan-day--missed .plan-day__status { color: var(--error); }
.plan-day--upcoming .plan-day__status { color: var(--text-muted); }
.plan-day__date { font-weight: 600; }
.plan-day__items { color: var(--text-secondary); }
.print-report__stamp { color: var(--text-muted); font-size: 12px; }
.print-report__disclaimer { color: var(--text-faint); font-size: 11px; margin-top: 2em; }
#ph-print-report h2 { margin-top: 1.2em; border-bottom: 1px solid var(--border-alt); padding-bottom: .2em; font-size: 16px; }

.shortcut-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.5); display: flex; align-items: center; justify-content: center; z-index: 1000; }
.shortcut-overlay[hidden] { display: none; }
.shortcut-overlay__box { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 1.5em; max-width: 420px; box-shadow: var(--shadow-lg); }
.shortcut-overlay__box h3 { margin-top: 0; }
.shortcut-overlay__box p { font-size: 13px; color: var(--text-secondary); line-height: 1.8; }
kbd { background: var(--bg-alt); border: 1px solid var(--border-alt); border-radius: 4px; padding: .1em .5em; font-size: 12px; font-family: monospace; }
.shortcut-hint-btn { position: fixed; right: 1em; bottom: 1em; background: var(--bg-panel); border: 1px solid var(--border-alt); color: var(--text-muted); border-radius: 999px; padding: .4em .8em; font-size: 12px; cursor: pointer; z-index: 100; box-shadow: var(--shadow-md); }
.shortcut-hint-btn:hover { color: var(--accent); border-color: var(--accent); }
@media (max-width: 600px) { .shortcut-hint-btn { display: none; } }

/* Mobile polish -- narrow-viewport fixes for the widest/most interaction-
   heavy screens. Note: this does NOT convert the chrome sidebar into a
   slide-out drawer (a larger structural change); it keeps content usable
   and scrollable at phone widths instead. */
@media (max-width: 600px) {
  .tools-nav { overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
  .exam-nav-grid { overflow-x: auto; }
  table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .quiz-mc__choice, .flashcard__btn, .continue-box__reviewlink, .weak-bar__label a { min-height: 44px; }
  .plan-day, .weak-bar { grid-template-columns: 1fr; }
}

/* index.html only -- scoped under body.index-page so these generic
   selectors (h1, h2, a, ul, li...) can't leak into the styling of
   actual captured lesson pages, which also link this same stylesheet. */
body.index-page {
  font-family: system-ui, sans-serif; max-width: 1080px; margin: 2rem auto;
  padding: 0 1rem; background: var(--bg); color: var(--text);
  font-size: 15px; line-height: 1.6; -webkit-font-smoothing: antialiased;
}
.index-page h1 { color: var(--accent); font-size: 34px; font-weight: 700; letter-spacing: -.02em; }
.index-page h2 { color: var(--accent-strong); margin-top: 2rem; border-bottom: 1px solid var(--border); padding-bottom: .3rem; }
.index-page ul { list-style: none; padding-left: 0; }
.index-page li { margin: .3rem 0; }
.index-page a { color: var(--accent); text-decoration: none; }
.index-page a:hover { text-decoration: underline; }
.index-page .empty { color: var(--text-faint); font-style: italic; }
.index-page .label { font-size: .8rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .05em; }
.index-page .updated { color: var(--text-faint); font-size: .8rem; }

.chrome-header__profile-link { display: block; margin-top: .4em; color: var(--accent); text-decoration: none; font-size: 13px; }
.chrome-header__profile-link:hover { text-decoration: underline; }

/* profile-hub.html only -- scoped under body.profile-page, same reasoning
   as body.index-page above: keeps generic selectors from leaking into
   captured lesson-page content that also links this stylesheet. */
body.profile-page {
  font-family: system-ui, sans-serif; max-width: 1080px; margin: 2rem auto;
  padding: 0 1rem; background: var(--bg); color: var(--text);
  font-size: 15px; line-height: 1.6; -webkit-font-smoothing: antialiased;
}
.ph-back { display: inline-block; margin-bottom: 1em; color: var(--accent); text-decoration: none; font-size: 13px; }
.ph-back:hover { text-decoration: underline; }
.ph-header { display: flex; justify-content: space-between; align-items: baseline; padding: 1em 0; border-bottom: 1px solid var(--border); }
.ph-header__name { color: var(--accent); font-size: 1.4em; }
.ph-header__pct { color: var(--accent-strong); font-size: 1.1em; }
.ph-tabs { display: flex; gap: .5em; margin: 1em 0; border-bottom: 1px solid var(--border-alt); }
.ph-tabs__btn { background: none; border: none; color: var(--text-muted); padding: .6em 1em; cursor: pointer; font-size: 14px; border-bottom: 2px solid transparent; }
.ph-tabs__btn:hover { color: var(--text-secondary); }
.ph-tabs__btn--active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.ph-panel { padding: 1em 0; }
.ph-panel[hidden] { display: none; }
.ph-history__row { display: flex; gap: 1em; align-items: center; padding: .5em 0; border-bottom: 1px solid var(--divider); cursor: pointer; background: none; border-left: none; border-right: none; border-top: none; width: 100%; text-align: left; font-family: inherit; }
.ph-history__row:hover { background: var(--hover-bg); }
.ph-history__lesson { flex: 1; color: var(--text-secondary); }
.ph-history__score { color: var(--text-muted); font-size: 13px; }
.ph-history__score--good { color: var(--success); }
.ph-history__score--bad { color: var(--error); }
.ph-history__empty { color: var(--text-faint); font-style: italic; }
.ph-review__attempt-meta { color: var(--text-muted); font-size: 13px; margin-bottom: 1em; }
.ph-review__item { margin-bottom: 1.5em; padding-bottom: 1.5em; border-bottom: 1px solid var(--divider); }
.ph-review__q { color: var(--text); margin: 0 0 .5em; font-size: 15px; }
.ph-review__choice { display: block; width: 100%; text-align: left; padding: .5em .8em; margin: .3em 0; border: 1px solid var(--border); border-radius: var(--r-sm); color: var(--text-secondary); background: var(--surface-sunken); font-family: inherit; font-size: 14px; }
.ph-review__choice--correct { border-color: var(--success); background: var(--success-bg); color: var(--on-success-bg); }
.ph-review__choice--chosen-wrong { border-color: var(--error); background: var(--error-bg); color: var(--on-error-bg); }
.ph-review__explanation { color: var(--accent-strong); font-size: 13px; margin-top: .5em; }
.ph-review__self { display: inline-block; padding: .3em .8em; border-radius: 4px; font-size: 13px; margin-top: .3em; }
.ph-review__self--right { border: 1px solid var(--success); color: var(--success); }
.ph-review__self--wrong { border: 1px solid var(--error); color: var(--error); }
.ph-review__empty { color: var(--text-faint); font-style: italic; }
.ph-review__sources { margin-top: .5em; font-size: 13px; color: var(--text-faint); }
.ph-review__source-link { color: var(--accent); text-decoration: none; }
.ph-review__source-link:hover { text-decoration: underline; }

.certificate { border: 4px double var(--accent); padding: 3em 2em; text-align: center; background: var(--bg-alt); border-radius: var(--r-lg); box-shadow: var(--shadow-lg); }
.certificate__eyebrow { color: var(--text-muted); text-transform: uppercase; letter-spacing: .1em; font-size: 13px; margin: 0; }
.certificate__name { color: var(--accent); font-size: 2em; margin: .3em 0; }
.certificate__body { color: var(--text-secondary); margin: .3em 0; }
.certificate__course { color: var(--text); font-size: 1.3em; font-weight: 600; margin: .5em 0; }
.certificate__date { color: var(--text-muted); margin-top: 1em; }
.certificate__note { color: var(--text-faint); font-size: 11px; margin-top: 2em; line-height: 1.4; }
@media print {
  .tools-nav, .ph-tabs, .ph-header { display: none !important; }
  body.profile-page { background: #fff; color: #000; }
  .certificate { border-color: #000; background: #fff; }
  .certificate__name, .certificate__course, .certificate__body { color: #000; }
  .certificate__eyebrow, .certificate__date, .certificate__note { color: #333; }
  .certificate-print-btn { display: none !important; }
  .no-print { display: none !important; }
  body.printing .ph-panel, body.printing .ph-tabs, body.printing .ph-header { display: none !important; }
  #ph-print-report h1, #ph-print-report h2, #ph-print-report p { color: #000; }
  .print-report__stamp, .print-report__disclaimer { color: #333 !important; }
  body.cheatsheet-page { background: #fff; color: #000; }
  body.cheatsheet-page h1, body.cheatsheet-page h2, body.cheatsheet-page li, body.cheatsheet-page p { color: #000; }
  body.testday-page { background: #fff; color: #000; }
  body.testday-page h1, body.testday-page h2, body.testday-page h3, body.testday-page p { color: #000; }
}

/* Shared top nav strip used on every depth-0 utility page (profile hub,
   calculators, flashcards, mock exam, glossary, admin dashboard) --
   defined once so it looks/behaves identically everywhere it appears. */
.tools-nav { display: flex; flex-wrap: wrap; gap: 1.2em; padding: .8em 0 1.2em; border-bottom: 1px solid var(--border-alt); margin-bottom: 1.5em; }
.tools-nav a { color: var(--accent); text-decoration: none; font-size: 14px; }
.tools-nav a:hover { text-decoration: underline; }
.tools-nav a.tools-nav__current { color: var(--text); font-weight: 600; text-decoration: none; cursor: default; }
/* The instructor-only link group is a <span> wrapper (so applyNavRoleVisibility()
   has one element to toggle) -- display:contents makes it invisible to the
   flex layout itself, so its <a> children sit in the gap-spaced row exactly
   like every other direct link, not bunched together inside one flex item. */
.tools-nav span[data-nav-role] { display: contents; }
.tools-nav span[data-nav-role][hidden] { display: none; }
.tools-nav span[data-nav-logbook] { display: contents; }
.tools-nav span[data-nav-logbook][hidden] { display: none; }

body.calc-page, body.flashcard-page, body.exam-page, body.glossary-page, body.admin-page,
body.airspace-page, body.testday-page, body.cheatsheet-page, body.weatherdecoder-page, body.audio-page,
body.logbook-page {
  font-family: system-ui, sans-serif; max-width: 1080px; margin: 2rem auto;
  padding: 0 1rem; background: var(--bg); color: var(--text);
  font-size: 15px; line-height: 1.6; -webkit-font-smoothing: antialiased;
}
body.calc-page h1, body.flashcard-page h1, body.exam-page h1, body.glossary-page h1, body.admin-page h1,
body.airspace-page h1, body.testday-page h1, body.cheatsheet-page h1, body.weatherdecoder-page h1, body.audio-page h1,
body.logbook-page h1 {
  color: var(--accent); font-size: 34px; font-weight: 700; letter-spacing: -.02em; line-height: 1.15; margin: 0 0 8px;
}
body.calc-page h2, body.admin-page h2 {
  color: var(--accent-strong); font-size: 20px; font-weight: 650; letter-spacing: -.01em;
  margin-top: 2em; border-bottom: 1px solid var(--border); padding-bottom: .3rem;
}
body.calc-page p.intro, body.flashcard-page p.intro, body.exam-page p.intro, body.glossary-page p.intro,
body.airspace-page p.intro, body.testday-page p.intro, body.cheatsheet-page p.intro, body.weatherdecoder-page p.intro, body.audio-page p.intro {
  color: var(--text-secondary); font-size: 17px; line-height: 1.6; max-width: 68ch; margin-bottom: 1.5em;
}

/* Audio review */
.audio-chapter-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1em; }
.audio-chapter-card { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 1.2em; box-shadow: var(--shadow-md); }
.audio-chapter-card h3 { margin: 0 0 .4em; color: var(--text); }
.audio-chapter-card p { color: var(--text-muted); font-size: 13px; margin-bottom: .8em; }
.audio-player { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 1.4em; margin-top: 1em; }
.audio-controls { display: flex; flex-wrap: wrap; gap: .8em; align-items: center; margin: 1em 0; }
.audio-section-progress { color: var(--text-muted); font-size: 13px; }
.audio-transcript { background: var(--surface-sunken); border-radius: var(--r-sm); border-left: 3px solid var(--accent); padding: 1em 1.2em; margin: 1em 0; }
.audio-transcript h3 { margin-top: 0; color: var(--text); }
.audio-transcript p { color: var(--text-secondary); line-height: 1.7; }

/* Calculators */
.calc-card { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 1.4em; margin-bottom: 1.5em; box-shadow: var(--shadow-md); }
.calc-card h3 { margin-top: 0; color: var(--text); }
.calc-card .calc-desc { color: var(--text-muted); font-size: 13px; margin-bottom: 1em; }
.calc-row { display: flex; flex-wrap: wrap; gap: .8em; align-items: center; margin-bottom: .6em; }
.calc-row label { flex: 0 0 220px; color: var(--text-secondary); font-size: 14px; }
.calc-row input, .calc-row select { background: var(--input-bg); border: 1px solid var(--border); color: var(--text); padding: .4em .6em; border-radius: var(--r-sm); font-size: 14px; width: 140px; }
.calc-result { margin-top: .8em; padding: .8em; background: var(--surface-sunken); border-radius: var(--r-sm); border-left: 3px solid var(--accent); color: var(--text); font-size: 15px; min-height: 1.2em; }
.calc-result .calc-result__warn { color: var(--error); }
.calc-result .calc-result__good { color: var(--success); }

/* Flashcards */
.flashcard-stage { max-width: 560px; margin: 0 auto; }
.flashcard { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 2em 1.5em; min-height: 180px; display: flex; align-items: center; justify-content: center; text-align: center; cursor: pointer; font-size: 17px; color: var(--text); box-shadow: var(--shadow-md); }
.flashcard__side--back { color: var(--accent-strong); font-size: 15px; }
.flashcard__hint { text-align: center; color: var(--text-faint); font-size: 12px; margin-top: .5em; }
.flashcard__controls { display: flex; justify-content: center; gap: .8em; margin-top: 1.2em; }
.flashcard__btn { padding: .6em 1.2em; border-radius: var(--r-md); border: 1px solid var(--border-strong); background: var(--accent); color: var(--on-accent); cursor: pointer; font-size: 14px; font-weight: 600; box-shadow: var(--shadow-sm); }
.flashcard__btn:disabled { background: var(--border); color: var(--text-muted); cursor: default; box-shadow: none; }
.flashcard__btn:hover { background: var(--accent-hover); }
/* Outline style, not the filled .flashcard__btn default -- these two
   variants used to only override border/text color while inheriting
   the filled var(--accent) background, leaving e.g. var(--success) text
   on var(--accent) background at ~1:1 contrast (functionally invisible)
   in both themes. Confirmed by the bug review's contrast measurements. */
.flashcard__btn--know { background: transparent; border-color: var(--success); color: var(--success); box-shadow: none; }
.flashcard__btn--know:hover { background: var(--success-bg); }
.flashcard__btn--dontknow { background: transparent; border-color: var(--error); color: var(--error); box-shadow: none; }
.flashcard__btn--dontknow:hover { background: var(--error-bg); }
.flashcard__progress { text-align: center; color: var(--text-muted); font-size: 13px; margin-bottom: 1em; }
.flashcard__mode { display: flex; align-items: center; justify-content: center; gap: 1em; flex-wrap: wrap; margin: .8em 0; font-size: 13px; }
.flashcard__due-info { color: var(--text-secondary); }
.flashcard__mode-toggle { background: none; border: 1px solid var(--border-alt); color: var(--accent); border-radius: var(--r-md); padding: .3em .8em; cursor: pointer; font-size: 12px; }
.flashcard__mode-toggle:hover { background: var(--hover-bg); }
.flashcard__summary { text-align: center; }

/* Mock exam */
.exam-setup { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 1.4em; margin-bottom: 1.5em; box-shadow: var(--shadow-md); }
.exam-form-note { color: var(--text-muted); font-size: 13px; }
.exam-timer {
  position: sticky; top: 0; z-index: 50; background: var(--bg-alt); padding: .6em 1em;
  border-radius: var(--r-md); margin-bottom: 1em; font-size: 14px; font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--accent-strong); display: flex;
  justify-content: space-between; border: 1px solid var(--border-alt); box-shadow: var(--shadow-sm);
}
.exam-timer--low { color: var(--error); }
.exam-question { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 1.4em; margin-bottom: 1em; box-shadow: var(--shadow-md); display: flex; flex-direction: column; }
.exam-flag { align-self: flex-end; order: -1; background: none; border: 1px solid var(--border); color: var(--text-muted); border-radius: var(--r-sm); padding: .2em .6em; cursor: pointer; font-size: 12px; }
.exam-flag--on { border-color: var(--warning); color: var(--warning); }
.exam-nav-grid { display: flex; flex-wrap: wrap; gap: .4em; margin: 1em 0; }
.exam-nav-grid button { width: 34px; height: 34px; border-radius: var(--r-sm); border: 1px solid var(--border); background: var(--surface-sunken); color: var(--text-secondary); cursor: pointer; font-size: 12px; }
.exam-nav-grid button.answered { border-color: var(--accent); color: var(--accent); }
.exam-nav-grid button.flagged { border-color: var(--warning); color: var(--warning); }
.exam-nav-grid button.current { background: var(--accent); color: var(--bg-alt); font-weight: 600; }
.exam-result--pass { color: var(--success); }
.exam-result--fail { color: var(--error); }

/* Glossary */
.glossary-search { width: 100%; max-width: 400px; padding: .5em .8em; background: var(--input-bg); border: 1px solid var(--border); color: var(--text); border-radius: var(--r-sm); margin-bottom: 1.5em; font-size: 14px; }
.glossary-term { border-bottom: 1px solid var(--divider); padding: .8em 0; }
.glossary-term dt { color: var(--accent); font-weight: 600; font-size: 15px; }
.glossary-term dd { color: var(--text-secondary); margin: .3em 0 0; font-size: 14px; }
.glossary-term[hidden] { display: none; }

/* Admin dashboard */
.admin-table { width: 100%; border-collapse: collapse; margin-top: 1em; font-size: 14px; }
.admin-table th, .admin-table td { text-align: left; padding: .6em .8em; border-bottom: 1px solid var(--divider); }
.admin-table th { color: var(--text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
.admin-table td { color: var(--text); }
.admin-wpm-input { width: 90px; padding: .3em .4em; border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--bg-alt); color: var(--text); font-size: 13px; }
.admin-wpm-save { margin-left: .4em; font-size: 12px; padding: .3em .6em; border-radius: var(--r-sm); border: 1px solid var(--border); background: none; color: var(--text-secondary); cursor: pointer; }
.admin-wpm-save:hover { border-color: var(--accent); color: var(--accent); }
.admin-wpm-save:disabled { cursor: default; opacity: .6; }
.admin-summary { display: flex; gap: 2em; margin-bottom: 1.5em; flex-wrap: wrap; }
.admin-summary__stat { background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: 1em 1.4em; box-shadow: var(--shadow-md); }
.admin-qdiff-row { border: 1px solid var(--border-alt); border-radius: var(--r-md); padding: .8em 1em; margin: .6em 0; background: var(--bg-panel); }
.admin-qdiff-row__scenario { color: var(--text-muted); font-size: 12px; font-family: ui-monospace, "SF Mono", Consolas, monospace; margin: 0 0 .3em; }
.admin-qdiff-row__question { font-weight: 600; margin: 0 0 .3em; }
.admin-qdiff-row__stat { color: var(--error); font-size: 13px; margin: 0 0 .3em; }
.admin-qdiff-row__distractors { color: var(--text-muted); font-size: 12px; margin: 0; }
.admin-retake-row { border: 1px solid var(--border-alt); border-radius: var(--r-md); padding: .8em 1em; margin: .6em 0; background: var(--bg-panel); }
.admin-retake-row__head { font-weight: 600; margin: 0 0 .4em; }
.admin-retake-row__answer { font-size: 13px; margin: 0 0 .2em; }
.admin-retake-row__answer--right { color: var(--success); }
.admin-retake-row__answer--wrong { color: var(--error); }
.admin-summary__stat .n { font-size: 1.6em; color: var(--accent); display: block; }
.admin-summary__stat .l { font-size: 12px; color: var(--text-muted); text-transform: uppercase; }

/* Flight Logbook (Phase 1) -- DRONE_LOGBOOK_PLAN.md */
/* Narrower than the shared 1080px above -- form-like layout reads better
   tighter; background/color/font now correctly come from the shared rule,
   which this page was missing entirely before (the actual theme bug: no
   background/color meant it always showed the plain white browser
   default, ignoring the user's dark/light choice). */
body.logbook-page { max-width: 900px; }
.lb-actions { display: flex; gap: .8em; margin: 1em 0; flex-wrap: wrap; }
.lb-actions button, #lb-add-aircraft, .lb-toggle-btn, .lb-link-btn {
  padding: .6em 1.2em; border-radius: var(--r-lg); border: 1px solid var(--border-alt);
  background: var(--bg-panel); color: var(--text); cursor: pointer; font-size: 14px;
  text-decoration: none; display: inline-block;
}
.lb-actions button:hover, #lb-add-aircraft:hover, .lb-toggle-btn:hover, .lb-link-btn:hover { background: var(--accent); color: #fff; }
.lb-toggle-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); }
.lb-battery-pct-group { display: flex; gap: .5em; flex-wrap: wrap; }
.lb-battery-pct-group .lb-battery-pct-btn { padding: .5em 1em; }
.lb-empty { color: var(--text-muted); font-style: italic; }
.lb-mission-list { list-style: none; padding: 0; }
.lb-mission-list li { padding: .6em 1em; margin-bottom: .5em; background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); }
.lb-field { margin-bottom: 1em; }
.lb-field label { display: block; font-weight: 600; margin-bottom: .3em; font-size: 14px; }
.lb-field input[type="text"], .lb-field input[type="date"], .lb-field input[type="number"], .lb-field textarea, .lb-field select {
  width: 100%; max-width: 420px; padding: .5em; border-radius: var(--r-md); border: 1px solid var(--border-alt);
  background: var(--bg-panel); color: var(--text); font-size: 14px; box-sizing: border-box;
}
.lb-hint { font-size: 12px; color: var(--text-muted); margin: .3em 0 0; }
.lb-warning { background: #fff3cd; color: #664d03; border: 1px solid #ffe69c; border-radius: var(--r-md); padding: .7em 1em; margin: 1em 0; }
.lb-error { color: #b42318; }
.lb-aircraft-row { border: 1px solid var(--border-alt); border-radius: var(--r-lg); padding: .8em; margin-bottom: .8em; display: flex; flex-wrap: wrap; gap: .6em; align-items: center; }
.lb-aircraft-row input[type="text"], .lb-aircraft-row input[type="number"] { width: auto; max-width: 140px; }

/* Phase 2 -- checklist tiering (required/suggested), mission list, nag banner */
.lb-checklist-group { display: flex; flex-direction: column; gap: .3em; margin-bottom: 1em; }
.lb-check-row { display: flex; align-items: center; gap: .5em; padding: .3em .6em; border-radius: var(--r-md); }
/* Fixed-color highlight (same reasoning as .lb-warning/.lb-nag-banner
   above: a light pastel works as a warning color in both themes) -- bug
   fix 2026-10-21: text color was never set here, so dark theme rendered
   near-invisible light-grey-on-pale-yellow/pink text. Explicit dark text
   on both background AND on the label/input children (which don't
   inherit color from their own type-level CSS rules above) fixes it. */
.lb-empty-required { background: #ffe5e5; color: #7a1f1f; }
.lb-empty-suggested { background: #fff8d6; color: #664d03; }
.lb-field.lb-empty-required, .lb-field.lb-empty-suggested {
  border-radius: var(--r-lg); padding: .6em .8em;
}
.lb-field.lb-empty-required { background: #ffe5e5; color: #7a1f1f; }
.lb-field.lb-empty-suggested { background: #fff8d6; color: #664d03; }
.lb-empty-required label, .lb-empty-suggested label { color: inherit; }
.lb-empty-required input[type="text"], .lb-empty-suggested input[type="text"] {
  background: #fff; color: #1a1a1a; border-color: rgba(0,0,0,.2);
}
/* Battery-percent fields: label and the button row sit on one line
   instead of stacking (every other checklist field is a single-line
   label-above-control, but the pill buttons are short enough to fit
   beside the label instead of wasting a whole row under it). */
.lb-field-battery { display: flex; align-items: center; flex-wrap: wrap; gap: .8em; }
.lb-field-battery label { margin-bottom: 0; white-space: nowrap; }
.lb-nag-banner { background: #ffe5e5; border: 1px solid #f5a3a3; color: #7a1f1f; border-radius: var(--r-lg); padding: .7em 1em; margin-bottom: 1em; font-weight: 600; }
.lb-mission-list-item { cursor: pointer; }
.lb-mission-list-item:hover { opacity: .85; }
.lb-print-link { align-self: center; font-size: 14px; }
.lb-submit-btn {
  background: #2e7d32 !important; color: #fff !important; border-color: #2e7d32 !important;
  font-weight: 700;
}
.lb-submit-btn:hover { background: #246628 !important; }
.lb-flight-status-btn {
  padding: .15em .6em; border-radius: var(--r-lg); border: none; cursor: pointer;
  font-size: 12px; font-weight: 700; color: #fff; margin-left: .4em;
}
.lb-status-red { background: #c0392b !important; color: #fff !important; border-color: #c0392b !important; }
.lb-status-red:hover { background: #a5311f !important; }
.lb-flight-status-btn.lb-status-green { background: #2e7d32; }
.lb-flight-status-btn.lb-status-green:hover { background: #246628; }
.lb-mission-badge {
  display: inline-block; padding: .1em .5em; border-radius: var(--r-lg);
  background: var(--accent); color: #fff; font-size: 13px; font-weight: 700;
}
/* Flight list rows (Mission Detail) -- stacked blocks, not one run-on
   inline line, so a long flight name can never visually run into/hide
   the Mission #/Flight # tag or the status+buttons below it. */
.lb-flight-list li { display: flex; flex-direction: column; gap: .2em; }
.lb-flight-name { font-weight: 600; }
.lb-flight-tag { font-size: 13px; color: var(--text-muted); }
.lb-tag-short { display: none; }
.lb-planned-flights-summary { list-style: none; padding: 0; }
.lb-planned-flights-summary li { padding: .7em .8em; margin-bottom: .6em; background: var(--bg-panel); border: 1px solid var(--border-alt); border-radius: var(--r-lg); }
.lb-planned-flights-summary li label { display: block; font-weight: 600; font-size: 13px; margin: .5em 0 .2em; }
.lb-planned-flights-summary li label:first-child { margin-top: 0; }
.lb-planned-flights-summary li input[type="text"], .lb-planned-flights-summary li textarea {
  width: 100%; box-sizing: border-box; padding: .5em; border-radius: var(--r-lg);
  border: 1px solid var(--border-alt); background: var(--bg); color: var(--text); font-size: 14px;
}
@media (max-width: 480px) {
  .lb-tag-full { display: none; }
  .lb-tag-short { display: inline; }
}

/* Printable paper checklist page + the full Mission Export/Print view --
   both share .lb-print-sheet. The site's normal heading/paragraph sizing
   (22px h2, 15px body text, ~1em margins) is built for on-screen reading;
   a full mission record with checklists for even one flight has ~45+
   checklist items plus a dozen info paragraphs, so at normal site sizing
   it ran to 2+ printed pages. These overrides make it print-dense instead.
   Confirmed via a real browser print (2026-10-21, Chrome print-to-PDF
   with headers/footers on) that on-screen DOM height alone understates
   what a printed page can hold -- Chrome reserves extra vertical space
   per page for its own URL/page-number footer, which isn't present in a
   normal browser tab. Sized down from an earlier, too-aggressive pass
   that measured fine on-screen but still overflowed to a 3rd page once
   actually printed with that footer on. */
.lb-print-sheet { max-width: 700px; }
.lb-print-sheet h2 { font-size: 20px; margin: .45em 0 .2em; line-height: 1.22; border-top: 1px solid #999; padding-top: .3em; }
.lb-print-sheet h3 { font-size: 18px; margin: .4em 0 .18em; line-height: 1.22; border-top: 1px solid #999; padding-top: .3em; }
.lb-print-sheet > h2:first-child { border-top: none; padding-top: 0; }
.lb-print-sheet p { font-size: 15px; margin: .15em 0; line-height: 1.28; }
.lb-print-header { display: flex; gap: 1.5em; font-size: 1.1em; font-weight: 600; margin: 1em 0; border-bottom: 1px solid var(--border-alt); padding-bottom: .6em; }
.lb-print-header span { flex: 1; }
/* Two columns, not one long run of rows -- a single column of all ~22
   checklist items was tall enough to spill onto a second printed page;
   splitting each section's rows across two columns keeps the whole
   checklist on one sheet. */
.lb-print-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .12em 1.2em; margin-bottom: .42em; list-style: none; padding: 0; font-size: 14px; line-height: 1.2; }
.lb-print-check { display: flex; align-items: center; gap: .5em; font-size: 13px; }
.lb-print-num { font-weight: 700; min-width: 1.6em; display: inline-block; }
.lb-print-value { display: flex; align-items: baseline; gap: .5em; font-size: 13px; }
.lb-print-flight-page { page-break-before: always; }
.lb-print-photo-page { page-break-before: always; }
.lb-print-photo { max-width: 100%; height: auto; display: block; margin-top: .5em; }
@media print {
  .tools-nav, .lb-print-screen-only { display: none !important; }
  body.logbook-print-page { margin: 0; padding: 0; }
}

/* Version-check banner (site.js's checkSiteVersion()) */
.site-update-banner {
  position: fixed; left: 50%; bottom: 1.2em; transform: translateX(-50%); z-index: 9999;
  display: flex; align-items: center; gap: 1em;
  background: var(--bg-panel); color: var(--text); border: 1px solid var(--border-alt);
  border-radius: var(--r-lg); box-shadow: var(--shadow-md); padding: .8em 1.2em; font-size: 14px;
}
.site-update-banner button {
  background: var(--accent); color: #fff; border: none; border-radius: var(--r-md);
  padding: .4em 1em; cursor: pointer; font-size: 14px;
}
