@font-face {
  font-family: 'Merriweather';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('/assets/fonts/merriweather-300.woff2') format('woff2');
}
@font-face {
  font-family: 'Merriweather';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/merriweather-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Merriweather';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/merriweather-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/atkinson-hyperlegible-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Atkinson Hyperlegible';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/atkinson-hyperlegible-700.woff2') format('woff2');
}
:root {
  --body-font: 'Merriweather', Georgia, serif;
  /* Used anywhere content should read as "not reading prose" -- UI chrome
     (the sidebar) and callout blocks (blockquote) alike. Atkinson
     Hyperlegible: open source (SIL license), designed by the Braille
     Institute specifically for low-vision readability -- self-hosted,
     same as Merriweather, no external font-CDN dependency. */
  --ui-font: 'Atkinson Hyperlegible', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --text-color: #1a1a1a;
  --bg-color: #ffffff;
  --link-color: #1155cc;
  /* All three of these are reader-adjustable via the sliders in
     .sidebar-settings, and persisted per-reader in localStorage -- see
     base.njk's inline scripts. Values here are just the starting
     defaults. */
  --sidebar-width: 230px;
  /* 700 is deliberately the midpoint of the Text width slider's 500-900
     range. */
  --content-width: 700px;
  --font-scale: 0.85;
}

/* Every rem-based size on the page (body text, headings, list indents,
   .page's own padding/max-width) is relative to this root font-size, so
   scaling it here scales reading text AND its surrounding spacing
   together, proportionally, from one slider. Sidebar/footer chrome is
   deliberately NOT rem-based (see .sidebar, .site-footer below) so it
   stays a constant size regardless of the reader's text-size choice. */
html {
  font-size: calc(16px * var(--font-scale));
}

* {
  box-sizing: border-box;
}

body {
  background: var(--bg-color);
  color: var(--text-color);
  font-family: var(--body-font);
  font-weight: 300;
  font-size: 1.05rem;
  /* Fixed px, not a unitless ratio -- the gap between wrapped lines stays
     constant across every font-size slider setting; only the glyph size
     itself changes. A unitless value would grow/shrink the line spacing
     right along with the text, which read as the whole page "changing
     size" rather than just the text. */
  line-height: 30.4px;
  letter-spacing: 0.01em;
  margin: 0;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* Row layout for the optional sidebar + main content. Only these two are
   flex-row children -- .site-footer is a sibling of this wrapper, not
   inside it, so it always flows full-width below rather than becoming a
   third item in the row (which pushed it to the top-right on any page
   without a sidebar, e.g. a plain listing page with no headings). */
/* The sidebar's shaded background + divider line are painted here, on
   .layout itself, as a background gradient -- not sized to an actual
   sidebar box. An earlier version tried to stretch .sidebar's own box to
   match .page's height via align-items:stretch (with a nested
   position:sticky child to keep the nav content pinned); that worked in
   Chromium but not in Firefox -- a real cross-browser inconsistency in
   how stretch interacts with a sticky descendant's intrinsic height.
   A gradient sidesteps it entirely: .layout's height is just normal
   content-driven block sizing (no flex-stretch involved), so the
   background is guaranteed to span exactly as tall as the content is,
   identically in every browser. Cleared via .sidebar-collapsed (toggled
   in base.njk's JS) when the sidebar itself is hidden. */
h1, h2 {
  font-family: var(--body-font);
  font-weight: 700;
  color: var(--text-color);
  line-height: 1.3;
}

/* Explicit, not left to the browser default -- without this, <strong>/<b>
   use the UA's relative "bolder" step, which computes off the inherited
   weight (300 for body text) rather than jumping straight to the loaded
   700 weight file. That relative step landed too close to 400 to read as
   real emphasis in this font, which is why bold text wasn't visible
   enough -- pin it to the actual bold weight instead. */
strong, b {
  font-weight: 700;
}

h1 {
  font-size: 1.6rem;
  letter-spacing: 0.03em;
  margin: 0 0 1.5rem;
  text-align: center;
}

h2 {
  font-size: 1.5rem;
  letter-spacing: 0.02em;
  margin: 2.5rem 0 1rem;
}

/* H3 is intentionally body-styled — it's the top-tier item of a numbered
   list (see eleventy.config.js's list_item_headings plugin), used purely
   as a bookmark/outline anchor, not a visually distinct heading. Not bold,
   and its margin matches .page li's exactly so it reads as just another
   item in the list, not a section break. */
h3 {
  font-family: var(--body-font);
  font-weight: 300;
  font-size: 1rem; /* html's own font-size already carries --font-scale
    (see :root/html above), so a plain 1rem tracks the slider with no
    calc() needed here */
  margin: 0; /* matches .page li's margin exactly -- see the "uniform
    vertical rhythm" note below */
}

/* Vertical spacing is deliberately uniform everywhere -- a wrapped line
   within one list item/paragraph, a new list item, and a new paragraph
   all use the exact same baseline-to-baseline distance (body's fixed
   30.4px line-height, see above). No extra block margin is added on top
   of that, so "new line" and "new paragraph/item" read as the same kind
   of vertical step rather than two different gap sizes. */
p, ul {
  margin: 0;
}

a {
  color: var(--link-color);
}

/* Callout-style content that should visually "stick out" without being
   numbered as a step -- e.g. a reference list of color values. Distinct
   from code: this is real prose/data, not source code, so it stays out
   of fenced code blocks (see .page pre/code below) -- Markdown's other
   built-in non-numbered block construct, and a real semantic match
   (Word's own "Quote" paragraph style, which the docx converter can
   detect the same way it already detects Heading-styled list items). */
.page {
  flex: 1;
  min-width: 0;
  /* Reader-adjustable via the "Text width" slider (--content-width, see
     :root above) -- deliberately a separate variable from --font-scale,
     not rem-based off it, so column width and text size are independent
     controls. */
  max-width: var(--content-width);
  margin: 0 auto;
  padding: 3rem 1.5rem 6rem;
}

/* Short standalone pages (the site-root course list, etc.) -- pins
   .page-footer to the true bottom of the viewport instead of it just
   trailing right after a couple of lines of content. Scoped to this class
   specifically, not applied to .page-footer generally: on the long
   tutorial/assignment pages there's no leftover space for margin:auto to
   consume anyway (content already exceeds one viewport), so this would be
   a no-op there -- but scoping it explicitly avoids relying on that being
   true forever. */
