/* component: article/item/page */
/* "More info" link below the description — slightly smaller text so it
   reads as a footer-level affordance. Vertical spacing is handled by the
   generic .item sibling rules in the site stylesheet (lobotomized owl).
   The item title above is still the PageRank-attributed primary link. */
.item__more {
  font-size: var(--size-small);
}

/* component: icon */
/* Material Symbols icon. Theme defaults come from CSS variables on :root
   (--icon-fill, --icon-weight, --icon-grade, --icon-size-{size},
   --icon-optical-size-{size}). Modifier classes override one var at a time
   so the bulk font-variation-settings declaration on .icon stays correct. */

.icon {
  font-family: 'Material Symbols Outlined';
  font-weight: normal;
  font-style: normal;
  display: inline-block;
  line-height: 1;
  vertical-align: middle;
  letter-spacing: normal;
  text-transform: none;
  white-space: nowrap;
  word-wrap: normal;
  direction: ltr;
  -webkit-font-feature-settings: 'liga';
  -webkit-font-smoothing: antialiased;
  font-variation-settings:
    'FILL' var(--icon-fill),
    'wght' var(--icon-weight),
    'GRAD' var(--icon-grade),
    'opsz' var(--icon-optical-size, var(--icon-optical-size-md));
}

/* Size classes set the rendered font-size and pair an optical-size value so
   stroke weights stay visually consistent across the scale. Most size
   classes also auto-shift weight around `--icon-base-weight` so smaller
   icons don't look faint and larger icons don't look heavy:
   3xs +300, 2xs +250, xs +200, sm +50, md/lg unchanged, xl -50, 2xl -100,
   3xl -170. All shifts are clamped to the font's [100, 700] axis range.
   Per-icon inline style or explicit weight override (`&[home|md|500]`)
   wins over these auto-shifts. */

.icon--3xs {
  font-size: var(--icon-size-3xs);
  --icon-optical-size: var(--icon-optical-size-3xs);
  --icon-weight: clamp(100, calc(var(--icon-base-weight) + 300), 700);
}

.icon--2xs {
  font-size: var(--icon-size-2xs);
  --icon-optical-size: var(--icon-optical-size-2xs);
  --icon-weight: clamp(100, calc(var(--icon-base-weight) + 250), 700);
}

.icon--xs {
  font-size: var(--icon-size-xs);
  --icon-optical-size: var(--icon-optical-size-xs);
  --icon-weight: clamp(100, calc(var(--icon-base-weight) + 200), 700);
}

.icon--sm {
  font-size: var(--icon-size-sm);
  --icon-optical-size: var(--icon-optical-size-sm);
  --icon-weight: clamp(100, calc(var(--icon-base-weight) + 50), 700);
}

.icon--md { font-size: var(--icon-size-md); --icon-optical-size: var(--icon-optical-size-md); }
.icon--lg { font-size: var(--icon-size-lg); --icon-optical-size: var(--icon-optical-size-lg); }

.icon--xl {
  font-size: var(--icon-size-xl);
  --icon-optical-size: var(--icon-optical-size-xl);
  --icon-weight: clamp(100, calc(var(--icon-base-weight) - 50), 700);
}

.icon--2xl {
  font-size: var(--icon-size-2xl);
  --icon-optical-size: var(--icon-optical-size-2xl);
  --icon-weight: clamp(100, calc(var(--icon-base-weight) - 100), 700);
}

.icon--3xl {
  font-size: var(--icon-size-3xl);
  --icon-optical-size: var(--icon-optical-size-3xl);
  --icon-weight: clamp(100, calc(var(--icon-base-weight) - 170), 700);
}

.icon--filled   { --icon-fill: 1; }
.icon--outlined { --icon-fill: 0; }

/* Wrapping link around an icon. Inline-block so it can sit inline with text
   without inheriting block-level link defaults. */
.icon-link {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: inherit;
}

/* component: nav/link */
/* Inline link component. Centralises body-content link styling so every
   styled link looks the same whether it carries an icon, just text, or
   just an icon.

   Default: regular inline so adjacent punctuation (a trailing comma,
   period, etc.) stays on the same line as the link's last word. An
   inline-flex wrapper would atomise the link and orphan the punctuation
   to the next line — visible bug in long-link bullet lists.

   When the link contains an icon, switch to inline-flex via :has() so
   the icon and text sit visually centred against each other regardless
   of which is bigger. :has() is supported in Chrome 105+, Safari 15.4+,
   Firefox 121+ — the browser support floor for this site. */

.link {
  display: inline;
  color: var(--primary);
  text-decoration: none;
}

.link:has(.icon) {
  display: inline-flex;
  align-items: center;
  gap: 0.125em;
}

/* Text run — weight 500 + underline. The underline lives on the text
   span (not the anchor) so an adjacent icon glyph isn't underlined. */
.link__text {
  font-weight: var(--weight-medium);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.link:hover .link__text {
  text-decoration-thickness: 0.12em;
}

/* Icon part — sits next to the text without picking up the underline.
   flex-shrink: 0 keeps the icon at its declared size if the link is in
   a constrained-width context. */
.link .icon {
  text-decoration: none;
  flex-shrink: 0;
}

/* Icon-only links — no text run to underline. The icon itself carries
   the affordance; on hover, gently raise its opacity-anchored vibrancy
   instead of trying to underline a glyph. */
.link--icon-only {
  /* Hook for future icon-only-specific tuning (background pill, etc.). */
}

/* component: nav/menu */
/* nav/menu — configurable menu component.
 *
 * One markup, three collapse modes selected via the `menu--<method>` class on
 * the root <nav>. The `menu--collapse-<breakpoint>` class scopes the collapse
 * behaviour to viewport sizes at or below that breakpoint; above it, the list
 * is always visible and the trigger is hidden.
 *
 * Visual presentation (button styling, panel position, decorator artwork) is
 * left to the parent context's CSS — `.header .menu`, `.aside .menu`, etc.
 * This file owns only the state machine.
 */

.menu { position: relative; }
.menu__panel { display: block; }
.menu__list { list-style: none; margin: 0; padding: 0; }
.menu__heading { margin: 0; }

/* Hide the underlying checkbox/button in a way that keeps it focusable. */
.menu__toggle-input { position: absolute; opacity: 0; pointer-events: none; }

/* Default decorator content — override per-context via CSS. */
.menu__toggle-decorator { display: inline-block; }

/* ── Mode: none ──
 * Trigger is either absent or rendered as a static heading. Panel always shown.
 */
.menu--none .menu__toggle { display: none; }

/* ── Mode: toggle (hamburger) ──
 * Checkbox controls visibility. Panel is hidden until the checkbox is checked.
 * Above the configured breakpoint the panel becomes always-visible and the
 * trigger is hidden — see the breakpoint scope blocks below.
 */
.menu--toggle .menu__panel { display: none; }
.menu--toggle .menu__toggle-input:checked ~ .menu__panel { display: block; }

/* ── Mode: dropdown ──
 * Button controls visibility via aria-expanded. Panel is positioned absolutely
 * below the trigger by parent-context CSS. Closes on blur via scripts.js.
 */
.menu--dropdown .menu__panel {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
}
.menu--dropdown .menu__toggle[aria-expanded="true"] ~ .menu__panel { display: block; }

/* ── Breakpoint scopes for the toggle mode ──
 * Above each breakpoint the toggle/checkbox is hidden and the panel is shown
 * unconditionally. The dropdown mode does not honour breakpoints (it stays a
 * dropdown at every viewport — that's the case for chapter selectors etc.).
 */

/* phone: collapse below 640px (tablet up = always-visible) */
@media (min-width: 640px) {
  .menu--toggle.menu--collapse-phone .menu__toggle { display: none; }
  .menu--toggle.menu--collapse-phone .menu__panel { display: block; }
}

/* tablet: collapse below 960px (desktop up = always-visible) */
@media (min-width: 960px) {
  .menu--toggle.menu--collapse-tablet .menu__toggle { display: none; }
  .menu--toggle.menu--collapse-tablet .menu__panel { display: block; }
}

/* laptop: collapse below 1280px (wide up = always-visible) */
@media (min-width: 1280px) {
  .menu--toggle.menu--collapse-laptop .menu__toggle { display: none; }
  .menu--toggle.menu--collapse-laptop .menu__panel { display: block; }
}
