/* =========================================================================
   Open Psychology Interactives — main stylesheet
   -------------------------------------------------------------------------
   Scope:   site chrome (header, navigation, footer), typography, layout
            primitives and the collection cards used on the landing page and
            the three collection pages.
   Not in scope: styling for individual interactives. That lives in
            components/interactive-shell.css so that a single interactive can
            be copied out of this repository together with its shell.

   Conventions used throughout:
     * Design tokens are CSS custom properties declared on :root.
     * The site has one permanent theme: dark. Both palettes are still
       declared, but the dark one is applied unconditionally, so the
       appearance never follows the browser or operating system colour
       preference. No JavaScript is required for theming, so the site is
       fully styled with scripting disabled.
     * Sizes use rem so the layout respects the reader's browser font size.
     * No external fonts, images or icon libraries are loaded. Everything is
       either system fonts or inline SVG, which keeps the site fast, offline
       friendly and free of third-party copyright.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Design tokens
   ---------------------------------------------------------------------- */

:root {
  /* --- Neutral surfaces (light theme) --- */
  --colour-page: #ffffff;
  --colour-surface: #f5f7fa;
  --colour-surface-raised: #ffffff;
  --colour-border: #d3d9e2;
  --colour-border-strong: #aeb7c4;

  /* --- Text ---
     --colour-text on --colour-page = 17.8:1 contrast
     --colour-text-muted on --colour-page = 7.4:1 (6.9:1 on --colour-surface)
     Both clear WCAG 2.1 AA (4.5:1) and AAA (7:1) for body text. */
  --colour-text: #131820;
  --colour-text-muted: #4c566a;

  /* --- Brand / interactive colours ---
     --colour-accent on --colour-page = 7.9:1, so links are legible without
     relying on underlines alone (underlines are used as well). The same
     ratio applies to white text on an accent-filled button. */
  --colour-accent: #1a4fa0;
  --colour-accent-hover: #123a7a;
  --colour-accent-soft: #e8eefb;
  /* Text drawn on top of an accent-filled surface. It is a token rather than
     a hard-coded white so that the dark palette can flip it in one place —
     there the accent is a light blue, and white on it would be unreadable. */
  --colour-on-accent: #ffffff;
  --colour-focus: #b45309; /* deliberately different hue from --colour-accent
                              so the focus ring is visible on top of links */

  /* --- Module identity colours ---
     One per canonical module. Used only for thin accent bars and small
     uppercase labels, never as a background for body text, so hue choice
     cannot compromise text contrast. Each is also checked as a text colour
     against --colour-page, because the module label uses it as such.
     Colour never carries meaning on its own: every module is named in text
     wherever its accent appears. */
  --colour-cognitive: #8a4b00;
  --colour-research-methods: #1a4fa0;
  --colour-neuropsychology: #145c53;
  --colour-social-critical-psychology: #9e2f45;
  --colour-personality-individual-differences: #7a2e6d;

  /* --- Status colours (for "in preparation" badges) --- */
  --colour-status-bg: #f1ede3;
  --colour-status-text: #5c4a1f;
  --colour-status-border: #d9cdb0;

  /* --- Typography --- */
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  --text-xs: 0.8125rem;
  --text-sm: 0.9375rem;
  --text-base: 1.0625rem;
  --text-lg: 1.1875rem;
  --text-xl: 1.4375rem;
  --text-2xl: 1.75rem;
  --text-3xl: 2.25rem;

  /* --- Spacing scale --- */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;

  /* --- Shape --- */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;

  /* --- Elevation (kept subtle; this is a document, not an app) --- */
  --shadow-sm: 0 1px 2px rgb(19 24 32 / 0.06);
  --shadow-md: 0 2px 8px rgb(19 24 32 / 0.08);

  /* --- Layout --- */
  --measure: 68ch; /* comfortable reading width for prose */
  --container: 72rem;
}

/* Dark palette — the site's only theme. It is declared after the block above
   with the same specificity, so it always wins, whatever the reader's system
   or browser colour preference says. Contrast ratios were checked against
   --colour-page in the same block. */
:root {
  --colour-page: #0f141b;
  --colour-surface: #161d27;
  --colour-surface-raised: #1a2230;
  --colour-border: #2c3644;
  --colour-border-strong: #44506180;

  --colour-text: #e9edf3;       /* 15.7:1 on --colour-page */
  --colour-text-muted: #a8b2c1; /*  8.6:1 on --colour-page, 7.9:1 on surface */

  --colour-accent: #8fb6ff;     /*  9.1:1 on --colour-page */
  --colour-accent-hover: #b3cdff;
  --colour-accent-soft: #1b2740;
  --colour-on-accent: #0f141b;  /*  9.1:1 on --colour-accent */
  --colour-focus: #f0b429;

  --colour-cognitive: #e2ab5f;
  --colour-research-methods: #8fb6ff;
  --colour-neuropsychology: #6fc3b4;
  --colour-social-critical-psychology: #f19aa8;
  --colour-personality-individual-differences: #db9ccd;

  --colour-status-bg: #241f14;
  --colour-status-text: #e2cf9f;
  --colour-status-border: #4a4028;

  --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.4);
  --shadow-md: 0 2px 10px rgb(0 0 0 / 0.45);
}

/* -------------------------------------------------------------------------
   2. Base / reset
   ---------------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* Anchor links, and elements the browser scrolls into view when they take
     focus, land below the sticky header rather than underneath it. This is
     what keeps WCAG 2.2 SC 2.4.11 (Focus Not Obscured) satisfied.

     5rem (80px) clears the 68px single-row header. The value must stay at or
     above the header's real height — see the narrow-viewport override further
     down, and re-measure if the header's contents change. */
  scroll-padding-top: 5rem;
  -webkit-text-size-adjust: 100%;
}

/* Below roughly 460px the wordmark wraps onto a second line and the header
   grows to 122px, reaching 145px at 320px. 5rem would no longer clear it, so
   a focused element could end up behind the header. 9.5rem (152px) covers the
   worst case. The breakpoint is 29em (464px), just above the width at which
   the wordmark stops wrapping, so the two never disagree. */
@media (max-width: 29em) {
  html {
    scroll-padding-top: 9.5rem;
  }
}

body {
  margin: 0;
  background-color: var(--colour-page);
  color: var(--colour-text);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.65;
  /* Push the footer to the bottom of short pages. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* Headings: a clear, predictable hierarchy. Levels are never skipped in the
   markup — size is chosen with these classes/tokens, not by picking a
   different heading level. */
h1,
h2,
h3,
h4 {
  margin: 0 0 var(--space-3);
  line-height: 1.25;
  font-weight: 650;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }
h4 { font-size: var(--text-lg); }

p,
ul,
ol,
dl {
  margin: 0 0 var(--space-4);
}

ul,
ol {
  padding-left: 1.35em;
}

li + li {
  margin-top: var(--space-2);
}

a {
  color: var(--colour-accent);
  text-decoration: underline;
  text-underline-offset: 0.15em;
  text-decoration-thickness: max(1px, 0.06em);
}

a:hover {
  color: var(--colour-accent-hover);
  text-decoration-thickness: max(2px, 0.11em);
}

/* Single, consistent focus treatment for every focusable element.
   :focus-visible keeps the ring away from mouse users, and the outline is
   drawn outside the element so it is never clipped by a rounded corner. */
:focus-visible {
  outline: 3px solid var(--colour-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Fallback for browsers without :focus-visible support. */
@supports not selector(:focus-visible) {
  :focus {
    outline: 3px solid var(--colour-focus);
    outline-offset: 2px;
  }
}

code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background-color: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-sm);
  padding: 0.1em 0.35em;
}

hr {
  border: 0;
  border-top: 1px solid var(--colour-border);
  margin: var(--space-6) 0;
}

/* Respect a reduced-motion preference across the whole site. Interactives
   should also check this via the matchMedia API before animating. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* -------------------------------------------------------------------------
   3. Utilities
   ---------------------------------------------------------------------- */

/* Visible only to assistive technology. Used for extra context that would be
   redundant on screen (for example "opens on GitHub"). */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* The skip link is the first focusable element on every page. It is off
   screen until focused, then drops into the top-left corner. */
.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  transform: translateY(-120%);
  background-color: var(--colour-page);
  color: var(--colour-text);
  border: 2px solid var(--colour-focus);
  border-radius: 0 0 var(--radius-md) 0;
  padding: var(--space-3) var(--space-4);
  font-weight: 600;
  text-decoration: none;
}

.skip-link:focus {
  transform: translateY(0);
}

/* Horizontal page gutter + max width. */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-4);
}

@media (min-width: 40em) {
  .container {
    padding-inline: var(--space-5);
  }
}

/* Constrains long-form text to a readable line length. */
.prose {
  max-width: var(--measure);
}

.text-muted {
  color: var(--colour-text-muted);
}

.section {
  padding-block: var(--space-7);
}

.section--tinted {
  background-color: var(--colour-surface);
  border-block: 1px solid var(--colour-border);
}

.section__header {
  max-width: var(--measure);
  margin-bottom: var(--space-5);
}

.section__header > :last-child {
  margin-bottom: 0;
}

/* -------------------------------------------------------------------------
   4. Site header and navigation
   ---------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background-color: var(--colour-page);
  border-bottom: 1px solid var(--colour-border);
}

/* Nothing inside a tool is pinned, so no tool needs an offset to clear this
   header. `scroll-padding-top` above is what keeps a keyboard-focused element
   from landing underneath it; see components/interactive-shell.css for why
   sticky positioning is not used inside an activity. */

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: 4rem;
  padding-block: var(--space-3);
}

/* Wordmark: text plus a small inline SVG glyph, so no image file is needed. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--colour-text);
  text-decoration: none;
  font-weight: 680;
  line-height: 1.2;
}

.brand:hover {
  color: var(--colour-text);
}

.brand:hover .brand__name {
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.brand__mark {
  flex: none;
  width: 2rem;
  height: 2rem;
  color: var(--colour-accent);
}

.brand__name {
  font-size: var(--text-lg);
  letter-spacing: -0.015em;
}

.brand__tagline {
  display: block;
  font-size: var(--text-xs);
  font-weight: 450;
  color: var(--colour-text-muted);
  letter-spacing: 0;
}

/* The toggle is hidden on wide screens where the full nav is always shown. */
.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--colour-text);
  background-color: var(--colour-surface);
  border: 1px solid var(--colour-border-strong);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
}

.nav-toggle:hover {
  background-color: var(--colour-accent-soft);
}

.nav-toggle__icon {
  width: 1.1rem;
  height: 1.1rem;
}

.site-nav__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
}

.site-nav__list li + li {
  margin-top: 0;
}

.site-nav__link {
  display: block;
  padding: var(--space-2) 0;
  color: var(--colour-text);
  font-size: var(--text-sm);
  font-weight: 550;
  text-decoration: none;
  border-bottom: 2px solid transparent;
}

.site-nav__link:hover {
  color: var(--colour-accent);
  border-bottom-color: var(--colour-accent);
}

/* aria-current="page" marks the page the reader is already on. The visual
   treatment mirrors the semantic state rather than duplicating it. */
.site-nav__link[aria-current="page"] {
  color: var(--colour-accent);
  border-bottom-color: var(--colour-accent);
}

/* --- Collapsed navigation -------------------------------------------------
   Below 64em the nav collapses behind the toggle button. The [hidden]
   attribute is what actually hides it, set by assets/js/main.js, so the
   visual state and the accessibility tree can never disagree. With
   JavaScript disabled the nav simply stays open, which is still usable.

   The breakpoint is 64em (1024px) rather than the 48em used elsewhere in
   this file. With seven navigation items — five modules plus Home and
   Documentation — the full row no longer fits beside the wordmark on a
   tablet-width viewport, and would wrap onto a second line. Collapsing it
   instead keeps the header one row tall at every width.

   assets/js/main.js reads the same 64em value; the two must stay in step. */
@media (max-width: 63.99em) {
  .site-header__inner {
    flex-wrap: wrap;
  }

  .site-nav {
    flex-basis: 100%;
    border-top: 1px solid var(--colour-border);
    padding-block: var(--space-2) var(--space-3);
  }

  .site-nav__list {
    flex-direction: column;
    gap: 0;
  }

  .site-nav__link {
    padding: var(--space-3) 0;
    border-bottom: 1px solid transparent;
  }
}

@media (min-width: 64em) {
  .nav-toggle {
    display: none;
  }

  /* Defence in depth. assets/js/main.js only applies [hidden] below this
     breakpoint, so above it the attribute should never be present. This rule
     exists so that a script error can never leave the navigation unreachable
     on a desktop viewport — it is a safety net, not part of the normal
     behaviour, and in normal operation it matches nothing. */
  .site-nav[hidden] {
    display: block;
  }
}

/* -------------------------------------------------------------------------
   5. Hero
   ---------------------------------------------------------------------- */

.hero {
  padding-block: var(--space-7) var(--space-6);
  border-bottom: 1px solid var(--colour-border);
  /* A flat two-tone wash built from tokens — no image asset involved. */
  background-image: linear-gradient(
    180deg,
    var(--colour-accent-soft) 0%,
    var(--colour-page) 100%
  );
}

.hero__eyebrow {
  display: inline-block;
  margin-bottom: var(--space-3);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--colour-text-muted);
}

.hero h1 {
  max-width: 20ch;
  margin-bottom: var(--space-4);
}

.hero__lead {
  max-width: var(--measure);
  font-size: var(--text-lg);
  color: var(--colour-text-muted);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

@media (min-width: 48em) {
  .hero {
    padding-block: var(--space-8) var(--space-7);
  }

  .hero h1 {
    font-size: 2.75rem;
  }
}

/* -------------------------------------------------------------------------
   6. Buttons
   ---------------------------------------------------------------------- */

.button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  /* 44px minimum tap target, per WCAG 2.5.5 target-size guidance. */
  min-height: 2.75rem;
  padding: var(--space-2) var(--space-5);
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.button--primary {
  background-color: var(--colour-accent);
  border-color: var(--colour-accent);
  /* 7.9:1 in the light palette, 9.1:1 in the dark one — the token carries the
     flip, so this rule is correct under both without a media query. */
  color: var(--colour-on-accent);
}

.button--primary:hover {
  background-color: var(--colour-accent-hover);
  border-color: var(--colour-accent-hover);
  color: var(--colour-on-accent);
}

.button--secondary {
  background-color: transparent;
  border-color: var(--colour-border-strong);
  color: var(--colour-text);
}

.button--secondary:hover {
  background-color: var(--colour-surface);
  border-color: var(--colour-accent);
  color: var(--colour-accent);
}

/* -------------------------------------------------------------------------
   7. Collection cards
   ---------------------------------------------------------------------- */

.card-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-5);
  /* auto-fit + minmax gives 1 / 2 / 3 columns without any media query. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
}

.card-grid > li + li {
  margin-top: 0;
}

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  background-color: var(--colour-surface-raised);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-5);
  transition: box-shadow 150ms ease, border-color 150ms ease;
}

/* Coloured rule across the top identifies the collection at a glance.
   Colour is never the only signal: each card also carries a text label. */
.card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 4px;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  background-color: var(--card-accent, var(--colour-accent));
}

.card:hover {
  border-color: var(--colour-border-strong);
  box-shadow: var(--shadow-md);
}

/* Focus ring is drawn around the whole card when the title link inside it is
   focused, so the keyboard target matches the clickable area. */
.card:has(a:focus-visible) {
  outline: 3px solid var(--colour-focus);
  outline-offset: 2px;
}

.card__label {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--card-accent, var(--colour-accent));
  margin-bottom: var(--space-2);
}

.card__title {
  font-size: var(--text-xl);
  margin-bottom: var(--space-3);
}

/* Stretched link: the whole card is clickable, but only the title is in the
   tab order, so keyboard users get one target rather than several. */
.card__title a {
  color: inherit;
  text-decoration: none;
}

.card__title a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--radius-lg);
}

.card__title a:hover {
  color: var(--card-accent, var(--colour-accent));
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.card__body {
  color: var(--colour-text-muted);
  font-size: var(--text-sm);
  margin-bottom: var(--space-4);
}

.card__footer {
  margin-top: auto;
  padding-top: var(--space-3);
  border-top: 1px solid var(--colour-border);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--card-accent, var(--colour-accent));
}

/* Per-module accent, set on the <li> or card element in the markup. The
   modifier suffix is the canonical module slug, so markup, catalogue entries
   and folder names all use the same identifier. */
.card--cognitive { --card-accent: var(--colour-cognitive); }
.card--research-methods { --card-accent: var(--colour-research-methods); }
.card--neuropsychology { --card-accent: var(--colour-neuropsychology); }
.card--social-critical-psychology { --card-accent: var(--colour-social-critical-psychology); }
.card--personality-individual-differences { --card-accent: var(--colour-personality-individual-differences); }

/* -------------------------------------------------------------------------
   8. Status badges and placeholders
   ---------------------------------------------------------------------- */

/* Small pill used to state, in words, that a collection has no published
   interactives yet. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: 650;
  line-height: 1.4;
  padding: 0.2rem var(--space-3);
  border-radius: 999px;
  border: 1px solid var(--colour-status-border);
  background-color: var(--colour-status-bg);
  color: var(--colour-status-text);
}

.badge__dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background-color: currentColor;
  flex: none;
}

/* A dashed panel that stands in for content that has not been built yet.
   The dashed border is a visual convention only; the text inside always says
   plainly what is and is not available. */
.placeholder {
  border: 2px dashed var(--colour-border-strong);
  border-radius: var(--radius-lg);
  background-color: var(--colour-surface);
  padding: var(--space-5);
  text-align: left;
}

.placeholder__title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-2);
}

.placeholder > :last-child {
  margin-bottom: 0;
}

/* -------------------------------------------------------------------------
   9. Content blocks used on collection and landing pages
   ---------------------------------------------------------------------- */

/* Two-column layout that collapses to one column on narrow screens. */
.split {
  display: grid;
  gap: var(--space-6);
}

@media (min-width: 56em) {
  .split {
    grid-template-columns: 3fr 2fr;
    align-items: start;
  }
}

/* Plain bordered panel for side notes, reuse information, and similar. */
.panel {
  background-color: var(--colour-surface);
  border: 1px solid var(--colour-border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}

.panel > :last-child {
  margin-bottom: 0;
}

.panel__title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-3);
}

/* Numbered "how this is used" list with larger numerals. */
.steps {
  list-style: none;
  counter-reset: step;
  padding: 0;
  display: grid;
  gap: var(--space-4);
}

.steps > li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 2rem 1fr;
  gap: var(--space-3);
  margin-top: 0;
}

.steps > li::before {
  content: counter(step);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background-color: var(--colour-accent-soft);
  color: var(--colour-accent);
  font-size: var(--text-sm);
  font-weight: 700;
}

.steps h3 {
  font-size: var(--text-base);
  margin-bottom: var(--space-1);
}

.steps p {
  margin-bottom: 0;
  color: var(--colour-text-muted);
  font-size: var(--text-sm);
}

/* Simple definition-style list for "planned topics". */
.topic-list {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--space-3);
}

.topic-list > li {
  margin-top: 0;
  padding-left: 1.6rem;
  position: relative;
  font-size: var(--text-sm);
}

/* A small square marker drawn in CSS rather than loaded as an icon file. */
.topic-list > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 0.55rem;
  height: 0.55rem;
  border: 2px solid var(--card-accent, var(--colour-accent));
  border-radius: 2px;
}

.topic-list strong {
  display: block;
  font-weight: 650;
  color: var(--colour-text);
}

/* -------------------------------------------------------------------------
   10. Breadcrumbs (collection pages)
   ---------------------------------------------------------------------- */

.breadcrumbs {
  padding-block: var(--space-4) 0;
  font-size: var(--text-sm);
}

.breadcrumbs ol {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
}

.breadcrumbs li {
  margin-top: 0;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--colour-text-muted);
}

/* Separator is decorative, so it is generated content and hidden from the
   accessibility tree by virtue of being CSS-generated. */
.breadcrumbs li + li::before {
  content: "/";
  color: var(--colour-border-strong);
}

/* -------------------------------------------------------------------------
   11. Footer
   ---------------------------------------------------------------------- */

.site-footer {
  margin-top: auto;
  background-color: var(--colour-surface);
  border-top: 1px solid var(--colour-border);
  padding-block: var(--space-6);
  font-size: var(--text-sm);
}

.site-footer__grid {
  display: grid;
  gap: var(--space-5);
  margin-bottom: var(--space-5);
}

@media (min-width: 48em) {
  .site-footer__grid {
    grid-template-columns: 2fr 1fr 1fr;
    gap: var(--space-6);
  }
}

.site-footer h2 {
  font-size: var(--text-sm);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--colour-text-muted);
  margin-bottom: var(--space-3);
}

.site-footer ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.site-footer li + li {
  margin-top: var(--space-2);
}

.site-footer__bottom {
  border-top: 1px solid var(--colour-border);
  padding-top: var(--space-4);
  color: var(--colour-text-muted);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  justify-content: space-between;
}

.site-footer__bottom p {
  margin: 0;
}

/* -------------------------------------------------------------------------
   12. Windows High Contrast / forced-colours mode
   -------------------------------------------------------------------------
   When forced colours are active the browser discards the author palette and
   substitutes the reader's system colours. Two consequences drive everything
   below:

     1. Any boundary drawn with a background tint alone disappears, because
        backgrounds are replaced. Those boundaries have to be redrawn as
        borders in a system colour keyword.
     2. Only system colour keywords (CanvasText, ButtonText, LinkText,
        Highlight, GrayText, …) are honoured. A custom property resolving to a
        hex value is ignored here, which is why this block repeats values
        rather than using the --colour-* tokens.

   forced-color-adjust is deliberately left at its default of `auto`
   throughout: overriding it would opt elements out of the reader's chosen
   palette, which is the opposite of what this mode is for.

   components/interactive-shell.css carries an equivalent block for the tool
   shell. The two are kept separate so that either file can be used without
   the other; do not merge them.
   ---------------------------------------------------------------------- */

@media (forced-colors: active) {

  /* --- Site chrome boundaries ---
     The header, footer and tinted sections are separated from the page by a
     background tint, which is discarded in this mode. */
  .site-header {
    border-bottom: 1px solid CanvasText;
  }

  .site-footer {
    border-top: 1px solid CanvasText;
  }

  .site-footer__bottom {
    border-top: 1px solid CanvasText;
  }

  .section--tinted {
    border-block: 1px solid CanvasText;
  }

  .hero {
    /* The hero's gradient is dropped; keep the edge it provided. */
    border-bottom: 1px solid CanvasText;
  }

  /* --- Navigation --- */

  /* The current page is marked with a coloured underline. Colour alone never
     carries meaning here — aria-current does the semantic work — but the
     visual cue should survive, so it is redrawn in the system highlight. */
  .site-nav__link[aria-current="page"] {
    border-bottom-color: Highlight;
  }

  .site-nav__link:hover {
    border-bottom-color: LinkText;
  }

  /* The collapsed navigation panel is separated from the header by a border
     that must remain visible. */
  .site-nav {
    border-top-color: CanvasText;
  }

  /* --- Menu toggle --- */
  .nav-toggle {
    border: 1px solid ButtonText;
  }

  .nav-toggle:hover {
    border-color: Highlight;
  }

  /* --- Buttons ---
     Both variants keep the system's own fill and text. They are distinguished
     by border weight rather than colour, because in this mode both would
     otherwise resolve to the same ButtonFace/ButtonText pair. */
  .button--primary {
    border: 2px solid ButtonText;
  }

  .button--secondary {
    border: 1px solid ButtonText;
  }

  .button:hover {
    border-color: Highlight;
  }

  /* --- Cards ---
     The card body needs an explicit boundary, and the accent rule across the
     top is a background colour, so it is redrawn in the system text colour.
     The module is always named in text beside it, so nothing is lost by the
     five accents collapsing to one colour here. */
  .card {
    border: 1px solid CanvasText;
  }

  .card::before {
    background-color: CanvasText;
  }

  .card:hover {
    border-color: Highlight;
  }

  /* --- Panels, placeholders and badges --- */
  .panel {
    border: 1px solid CanvasText;
  }

  .placeholder {
    border: 2px dashed CanvasText;
  }

  .badge {
    border: 1px solid CanvasText;
  }

  /* A small filled circle; without this it would vanish with the background. */
  .badge__dot {
    background-color: CanvasText;
  }

  /* The numbered step markers are a tinted circle with coloured text. */
  .steps > li::before {
    border: 1px solid CanvasText;
  }

  /* The topic list marker is drawn as a bordered square. */
  .topic-list > li::before {
    border-color: CanvasText;
  }

  /* Inline code keeps its outline. */
  code {
    border-color: CanvasText;
  }

  hr {
    border-top-color: CanvasText;
  }

  /* --- Focus ---
     Highlight is the system's selection colour and is guaranteed to contrast
     with both Canvas and ButtonFace. The card rule is listed separately
     because :has() gives it a different specificity. */
  :focus-visible {
    outline: 3px solid Highlight;
    outline-offset: 2px;
  }

  .card:has(a:focus-visible) {
    outline: 3px solid Highlight;
    outline-offset: 2px;
  }

  /* The skip link sits on top of the page when focused, so it needs an opaque
     background and a visible edge of its own. */
  .skip-link {
    background-color: Canvas;
    color: CanvasText;
    border: 2px solid Highlight;
  }
}

/* -------------------------------------------------------------------------
   13. Print
   ---------------------------------------------------------------------- */

@media print {
  .site-header,
  .site-footer,
  .skip-link,
  .hero__actions {
    display: none;
  }

  body {
    color: #000;
    background: #fff;
  }

  /* Expose link destinations, which are otherwise lost on paper. */
  a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    word-break: break-all;
  }
}
