/*!
 * Multimode TOC — frontend styles.
 *
 * Design principles (spec §12):
 *   - Neutral, clean default design that works with any theme.
 *   - All theme-specific values exposed as CSS custom properties so the
 *     WordPress settings (§10) can override them via an inline :root{} block.
 *   - Zero dependency on theme SCSS variables or mixins.
 *   - Class prefix: mmtoc-   JS hook prefix: data-mmtoc-*
 *
 * Custom properties (defaults below; overridden by MMTOC_Assets::css_vars()):
 *   --mmtoc-accent          Main accent color (links, active dot, progress line).
 *   --mmtoc-bg              Background color of inline / sidebar panels.
 *   --mmtoc-radius          Border radius of panels.
 *   --mmtoc-line            Color of the timeline track line.
 *   --mmtoc-active          Color applied to the currently active item.
 *   --mmtoc-scroll-offset   Matches the fixed-header height (set by PHP → px).
 */

/* ============================================================
   CSS Custom Properties — neutral defaults
   ============================================================ */
:root {
  --mmtoc-accent:        #3858e9;
  --mmtoc-bg:            #f5f6f8;
  --mmtoc-radius:        8px;
  --mmtoc-line:          #d0d3dc;
  --mmtoc-active:        var(--mmtoc-accent);
  --mmtoc-scroll-offset: 0px;
  --mmtoc-icon-image:    none;
}

/* ============================================================
   Scroll-margin for heading anchors (spec §9-1, fixed-header offset)
   Applied broadly so all h2–h4 with an id attribute scroll correctly.
   :where() keeps specificity at zero, so themes can override freely.
   ============================================================ */
:where(h2, h3, h4)[id] {
  scroll-margin-top: calc(var(--mmtoc-scroll-offset) + 16px);
}

/* ============================================================
   1. Shared list / link base styles
   ============================================================ */

/* Reset list markers for both .mmtoc__list and .mmtoc__sublist */
.mmtoc__list,
.mmtoc__sublist {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Indent sublists */
.mmtoc__sublist {
  padding-inline-start: 1.25em;
}

.mmtoc__item {
  margin: 0;
  padding: 0;
}

/* Placeholder items bridge level gaps (e.g. h2 → h4 without h3).
   They carry no link, no counter, no marker — only host the nested sublist. */
.mmtoc__item--placeholder {
  list-style: none;
}

.mmtoc__link {
  display: block;
  padding: 0.5em 0;
  color: inherit;
  text-decoration: none;
  line-height: 1.4;
  font-size: 0.875em;
  transition: opacity 0.15s ease;
}

/* Links keep the inherited text color and never underline; hover/focus is signalled
   by opacity so the TOC reads as plain text links (the accent color is reserved for
   the timeline dot / progress). focus-visible additionally gets the outline below. */
.mmtoc__link:hover,
.mmtoc__link:focus-visible {
  color: inherit;
  text-decoration: none;
  opacity: 0.7;
}

/* Defend the color / underline against theme content-link styles. A single
   .mmtoc__link class is outweighed by rules like
   `.entry-content a:not(...) { color; text-decoration: underline }` (specificity
   0,2,1). Scoping under the root attribute + list raises this to 0,3,0 so the TOC
   links stay plain text without resorting to !important — and only mmtoc links are
   touched. */
[data-mmtoc-root] .mmtoc__list .mmtoc__link,
[data-mmtoc-root] .mmtoc__list .mmtoc__link:hover,
[data-mmtoc-root] .mmtoc__list .mmtoc__link:focus-visible {
  color: inherit;
  text-decoration: none;
}

/* Active / current link (set by JS via aria-current="location").
   Uses the inherited body text color and no underline; the active state is
   signalled by weight (and, in the timeline, the accent dot). This avoids
   relying on the accent color for link TEXT, which can fail contrast when the
   accent is a light brand hue. */
.mmtoc__link[aria-current="location"] {
  color: inherit;
  font-weight: 600;
  text-decoration: none;
}

/* ------------------------------------------------------------
   List markers (icon + number)
   - Icon  (●○■ / image): rendered on .mmtoc__marker::before,
     scoped to [data-mmtoc-icon] which the Builder only sets on
     inline / mobile roots (never the timeline sidebar).
   - Number (1 / 01 / I / a): rendered on .mmtoc__marker::after via a
     CSS counter, scoped to [data-mmtoc-number] set on every root.
   The marker span is a separate element from the timeline dot
   (.mmtoc--timeline .mmtoc__link::before), so the two never collide.
   ------------------------------------------------------------ */

/* Each list level restarts its own counter (list-style-type semantics). */
.mmtoc__list,
.mmtoc__sublist {
  counter-reset: mmtoc-counter;
}

/* Real items advance the counter; placeholder bridges (level gaps) do not. */
.mmtoc__item:not(.mmtoc__item--placeholder) {
  counter-increment: mmtoc-counter;
}

.mmtoc__marker {
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
}

/* Icon — glyph variants. Top-level headings only: scoped to root-list (.mmtoc__list)
   direct items, so sub-level rows show the number (below) but no icon. */
[data-mmtoc-icon="disc"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker::before {
  content: "\25CF"; /* ● */
  margin-inline-end: 0.4em;
}

[data-mmtoc-icon="circle"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker::before {
  content: "\25CB"; /* ○ */
  margin-inline-end: 0.4em;
}

[data-mmtoc-icon="square"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker::before {
  content: "\25A0"; /* ■ */
  margin-inline-end: 0.4em;
}

/* Icon — custom image variant (top-level headings only) */
[data-mmtoc-icon="image"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker::before {
  content: "";
  display: inline-block;
  width: 1em;
  height: 1em;
  margin-inline-end: 0.4em;
  vertical-align: -0.15em;
  background: var(--mmtoc-icon-image) no-repeat center / contain;
}

/* Number schemes — per-level counter styles. Level selectors:
   L1 = root-list item, L2 = one sublist deep, L3 = two sublists deep.
   A placeholder bridge <li> for a skipped level still counts as a depth step. */

/* dec-dot (1. a. i.) */
[data-mmtoc-number="dec-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, decimal) ". "; }
[data-mmtoc-number="dec-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, lower-alpha) ". "; }
[data-mmtoc-number="dec-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, lower-roman) ". "; }

/* dec-paren (1) a) i)) */
[data-mmtoc-number="dec-paren"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, decimal) ") "; }
[data-mmtoc-number="dec-paren"] .mmtoc__list > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, lower-alpha) ") "; }
[data-mmtoc-number="dec-paren"] .mmtoc__list > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, lower-roman) ") "; }

/* nested (1. 1.1. 1.2.1.) — same rule at every depth via counters() */
[data-mmtoc-number="nested"] .mmtoc__marker::after { content: counters(mmtoc-counter, ".") ". "; }

/* ualpha-dot (A. a. i.) */
[data-mmtoc-number="ualpha-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, upper-alpha) ". "; }
[data-mmtoc-number="ualpha-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, lower-alpha) ". "; }
[data-mmtoc-number="ualpha-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, lower-roman) ". "; }

/* uroman-dot (I. A. 1.) */
[data-mmtoc-number="uroman-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, upper-roman) ". "; }
[data-mmtoc-number="uroman-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, upper-alpha) ". "; }
[data-mmtoc-number="uroman-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, decimal) ". "; }

/* zero-dot (01. a. i.) */
[data-mmtoc-number="zero-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, decimal-leading-zero) ". "; }
[data-mmtoc-number="zero-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, lower-alpha) ". "; }
[data-mmtoc-number="zero-dot"] .mmtoc__list > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__sublist > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after { content: counter(mmtoc-counter, lower-roman) ". "; }

/* Marker + text two-column layout (only when a marker attribute is present, i.e. not
   'none'). The marker keeps its intrinsic width; the text takes the rest and wraps
   inside its own column, so a wrapped second line hangs under the text — not under the
   number/icon. The timeline dot is position:absolute, so flex here never moves it. */
[data-mmtoc-icon] .mmtoc__link,
[data-mmtoc-number] .mmtoc__link,
[data-mmtoc-preset] .mmtoc__link {
  display: flex;
  align-items: baseline;
}

/* Preset markers are shaped boxes/circles, so center them against the text row. */
[data-mmtoc-preset] .mmtoc__link {
  align-items: center;
  gap: 0.5em;
}

.mmtoc__text {
  flex: 1 1 auto;
  min-width: 0; /* allow the text column to shrink and wrap instead of overflowing */
}

/* ------------------------------------------------------------
   Marker presets (data-mmtoc-preset) — ready-made combined styles for the
   inline / mobile TOC. A preset replaces the icon/number markers; counters are
   already reset per list and incremented per real item (above), so the numbers
   work without any extra wiring. The timeline sidebar never gets a preset.
   ------------------------------------------------------------ */

/* boxed-leaf: top-level = number in a rounded square (white box, accent border + number);
   sub-levels = an accent-colored icon (the bundled leaf, or a custom mark — see below). */
[data-mmtoc-preset="boxed-leaf"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.7em;
  height: 1.7em;
  padding: 0 0.35em;
  background: #fff;
  border: 1.5px solid var(--mmtoc-accent);
  border-radius: 5px;
  color: var(--mmtoc-accent);
  font-size: 0.8em;
  font-weight: 700;
  line-height: 1;
}

[data-mmtoc-preset="boxed-leaf"] .mmtoc__list > .mmtoc__item > .mmtoc__link > .mmtoc__marker::after {
  content: counter(mmtoc-counter, decimal);
}

/* Sub-level icon. mask + background-color renders it in the accent color; the masked
   image defaults to the bundled leaf and can be overridden site-wide with a custom
   mark via the List icon → custom image setting (--mmtoc-marker-icon). */
[data-mmtoc-preset="boxed-leaf"] .mmtoc__sublist .mmtoc__link > .mmtoc__marker::before {
  content: "";
  display: inline-block;
  width: 1.1em;
  height: 1.1em;
  background-color: var(--mmtoc-accent);
  -webkit-mask: var(--mmtoc-marker-icon, url("../images/leaf.svg")) no-repeat center / contain;
  mask: var(--mmtoc-marker-icon, url("../images/leaf.svg")) no-repeat center / contain;
}

/* circle-fill (filled) / circle-outline (hollow): number in a circle at every level. */
[data-mmtoc-preset="circle-fill"] .mmtoc__marker,
[data-mmtoc-preset="circle-outline"] .mmtoc__marker {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.7em;
  height: 1.7em;
  border-radius: 50%;
  font-size: 0.78em;
  font-weight: 700;
  line-height: 1;
  flex: 0 0 auto;
}

[data-mmtoc-preset="circle-fill"] .mmtoc__marker::after,
[data-mmtoc-preset="circle-outline"] .mmtoc__marker::after {
  content: counter(mmtoc-counter, decimal);
}

/* Filled: circle uses the inherited text color, number reversed to white. */
[data-mmtoc-preset="circle-fill"] .mmtoc__marker {
  background: currentColor;
}

[data-mmtoc-preset="circle-fill"] .mmtoc__marker::after {
  color: #fff;
}

/* Outlined: hollow circle, number in the inherited text color. */
[data-mmtoc-preset="circle-outline"] .mmtoc__marker {
  border: 1.5px solid currentColor;
}

/* Sidebar timeline + preset: the boxed number / icon marker replaces the per-item
   dot (the vertical track line and progress fill are kept). */
.mmtoc-sidebar[data-mmtoc-preset] .mmtoc--timeline .mmtoc__link::before {
  display: none;
}

/* ============================================================
   2. Inline TOC  (.mmtoc.mmtoc-inline)
   ============================================================ */

/* Uses the doubled class (.mmtoc.mmtoc-inline) so the width/spacing win over block
   themes' constrained-layout rule (.is-layout-constrained > :where(...)), which would
   otherwise clamp max-width to the theme content size and ignore --mmtoc-inline-width. */
.mmtoc.mmtoc-inline {
  /* Inline-specific background when set (settings color picker), else the shared color. */
  background: var(--mmtoc-inline-bg, var(--mmtoc-bg));
  border-radius: var(--mmtoc-radius);
  padding: 1em 1.25em;
  margin-block: 1.5em;
  border: 1px solid var(--mmtoc-line);
  max-width: var(--mmtoc-inline-width, none);
}

/* Header row: centered title with the toggle pinned right, and a divider rule below.
   The 1fr / auto / 1fr grid keeps the title optically centered in the full width
   regardless of the toggle width (the empty first column balances the third). */
.mmtoc__head {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 0.5em;
  padding-bottom: 0.75em;
  border-bottom: 1px solid var(--mmtoc-line);
}

.mmtoc__title {
  grid-column: 2;
  font-size: 24px;
  font-weight: 700;
  margin: 0;
  text-align: center;
}

/* Toggle button */
.mmtoc__toggle {
  grid-column: 3;
  justify-self: end;
  appearance: none;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.25em 0.5em;
  font-size: 0.75em;
  color: inherit;
  opacity: 0.6;
  border-radius: 4px;
  transition: opacity 0.15s ease, background-color 0.15s ease;
  white-space: nowrap;
}

.mmtoc__toggle:hover,
.mmtoc__toggle:focus-visible {
  opacity: 1;
  background-color: color-mix(in srgb, currentColor 8%, transparent);
  outline: 2px solid var(--mmtoc-accent);
  outline-offset: 2px;
}

/* Pill toggle (data-mmtoc-toggle-style="button"): a filled accent button with a
   chevron that flips between the expanded and collapsed states. */
[data-mmtoc-toggle-style="button"] .mmtoc__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  padding: 0.45em 0.95em;
  background-color: var(--mmtoc-accent);
  color: #fff;
  opacity: 1;
  border-radius: 999px;
  font-weight: 700;
}

[data-mmtoc-toggle-style="button"] .mmtoc__toggle::after {
  content: "";
  width: 0.5em;
  height: 0.5em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  /* Expanded (aria-expanded="true"): chevron points down. */
  transform: translateY(-0.15em) rotate(45deg);
  transition: transform 0.2s ease;
}

/* Collapsed: chevron points up. */
[data-mmtoc-toggle-style="button"] .mmtoc__toggle[aria-expanded="false"]::after {
  transform: translateY(0.1em) rotate(-135deg);
}

[data-mmtoc-toggle-style="button"] .mmtoc__toggle:hover {
  opacity: 0.85;
  background-color: var(--mmtoc-accent);
}

@media (prefers-reduced-motion: reduce) {
  [data-mmtoc-toggle-style="button"] .mmtoc__toggle::after {
    transition: none;
  }
}

/* Body: smoothly collapses/expands via an animated grid row (1fr <-> 0fr), keyed off
   data-mmtoc-collapsed on the root. overflow:hidden clips the list as the row shrinks.
   visibility:hidden (delayed until the collapse finishes) is the universal fallback that
   removes the clipped links from tab order / the a11y tree even where inert is unsupported;
   it flips back to visible immediately on expand (no delay). */
.mmtoc__body {
  margin-top: 0.75em;
  display: grid;
  grid-template-rows: 1fr;
  overflow: hidden;
  visibility: visible;
  transition: grid-template-rows 0.3s ease, margin-top 0.3s ease, visibility 0s;
}

.mmtoc-inline[data-mmtoc-collapsed] .mmtoc__body {
  grid-template-rows: 0fr;
  margin-top: 0;
  visibility: hidden;
  transition: grid-template-rows 0.3s ease, margin-top 0.3s ease, visibility 0s 0.3s;
}

/* Cap the inline TOC height so a long table of contents does not push the content far
   down the page; scroll the list within the box instead (the scroll lives on the list,
   not the body, so it does not fight the collapse animation's overflow). */
.mmtoc-inline .mmtoc__body > .mmtoc__list {
  min-height: 0;
  max-height: 56vh;
  overflow-y: auto;
}

/* Honour the HTML hidden attribute on our own elements even if a theme resets
   [hidden]. Scoped to mmtoc elements so the plugin never affects unrelated markup. */
.mmtoc__body[hidden],
.mmtoc-sidebar__body[hidden],
.mmtoc-sidebar[hidden],
.mmtoc-mobile__button[hidden],
.mmtoc-mobile__modal[hidden] {
  display: none !important; /* stylelint-disable-line declaration-no-important */
}

/* ============================================================
   3. PC Sidebar  (.mmtoc-sidebar)
   ============================================================ */

.mmtoc-sidebar {
  /* Top offset so it clears a fixed site header. Falls back to the scroll offset
     (header height) + a small margin when no explicit sidebar offset is set. */
  --mmtoc-sb-top: var(--mmtoc-sidebar-offset, calc(var(--mmtoc-scroll-offset, 0px) + 2rem));
  position: fixed;
  inset-block-start: var(--mmtoc-sb-top);
  width: 280px;
  /* Capped at 440px, but never taller than the space below the offset on short screens. */
  max-height: min(440px, calc(100vh - var(--mmtoc-sb-top) - 1rem));
  overflow-y: auto;
  /* Match the inline TOC background (falls back to the shared panel color). */
  background: var(--mmtoc-inline-bg, var(--mmtoc-bg));
  border-radius: var(--mmtoc-radius);
  border: 1px solid var(--mmtoc-line);
  /* No top padding: the sticky head supplies it (so the head's background covers the top
     cleanly while the body scrolls under it). */
  padding: 0 1em 1em;
  z-index: 100;
  /* Top-anchored (not centred): the head stays put and the body collapses upward toward
     the header. Hidden by default; JS removes [hidden] after the inline TOC scrolls off. */
}

/* Left / right variants use logical properties for RTL support (spec §11).
   The offset (sidebar width 280 + ~20 margin) seats it just outside a ~1400px
   content; JS additionally hides it when the real gutter is too narrow. */
.mmtoc-sidebar--left {
  inset-inline-start: max(1rem, calc((100vw - 1400px) / 2 - 300px));
  inset-inline-end: auto;
}

.mmtoc-sidebar--right {
  inset-inline-end: max(1rem, calc((100vw - 1400px) / 2 - 300px));
  inset-inline-start: auto;
}

/* The sidebar/mobile mode-switch breakpoint is emitted inline by
   MMTOC_Assets::breakpoint_css() (configurable; default 1440px), not hardcoded here. */

/* Header row: title + the shared collapse/expand toggle, with the divider rule below.
   Sticky so it stays visible while the body scrolls; its background (and the top padding
   moved here from the nav) covers the content scrolling underneath. */
.mmtoc-sidebar__head {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--mmtoc-inline-bg, var(--mmtoc-bg));
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5em;
  padding-top: 1em;
  margin-bottom: 0.75em;
  padding-bottom: 0.5em;
  border-bottom: 1px solid var(--mmtoc-line);
}

.mmtoc-sidebar__title {
  font-size: 0.8125em;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: inherit;
  opacity: 0.5;
  min-width: 0; /* allow a long title to shrink so the toggle stays visible */
}

/* Smooth collapse/expand of the sidebar body via an animated grid row (1fr <-> 0fr).
   overflow sits on the container (not the list) so the timeline dots — positioned just
   to the left of the list — are not clipped horizontally while it animates. visibility
   (delayed until the collapse finishes) is the universal fallback that removes the clipped
   links from tab order / the a11y tree even where inert is unsupported. */
.mmtoc-sidebar__body {
  display: grid;
  grid-template-rows: 1fr;
  overflow: hidden;
  visibility: visible;
  transition: grid-template-rows 0.3s ease, visibility 0s;
}

.mmtoc-sidebar[data-mmtoc-collapsed] .mmtoc-sidebar__body {
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows 0.3s ease, visibility 0s 0.3s;
}

.mmtoc-sidebar__body > .mmtoc__list {
  min-height: 0;
}

/* ============================================================
   4. Timeline layout  (.mmtoc--timeline)
   Applied to .mmtoc-sidebar__body
   ============================================================ */

/*
 * Spring-inspired easing curve for progress-line / active-dot transitions.
 * Reference: https://ics.media/entry/260402/
 * Approximated with linear() using keyframe sampling of a spring (stiffness
 * 200, damping 20, mass 1). Values rounded to 3 dp for brevity.
 * This variable is applied only to elements inside .mmtoc--timeline.
 */
.mmtoc--timeline {
  --mmtoc-spring: linear(
    0, 0.009, 0.035 2.1%, 0.141, 0.281 6.7%,
    0.723 12.9%, 0.938 16.4%,
    1.017, 1.077, 1.097 24.4%,
    1.09 26.9%, 1.037 36.5%,
    1.007 41.4%, 0.999 49.3%,
    1
  );

  position: relative;
  padding-inline-start: 1.5em;
  /* Inline-start of the 2px vertical line, positioned so its centre lands on the
     top-level dot centre at ANY font size (a fixed px would only match one size).
     The dot centre sits at padding-inline-start(1.5em) - 1.25em*0.875 +
     (0.625em*0.875)/2 = ~0.68em from the container start (the dot is offset in the
     link font-size, which is 0.875em). The "- 1px" offsets half of the line width. */
  --mmtoc-track: calc(0.68em - 1px);
}

/* Track line — full-height vertical bar on --mmtoc-track */
.mmtoc--timeline::before {
  content: "";
  position: absolute;
  inset-inline-start: var(--mmtoc-track);
  inset-block: 0;
  width: 2px;
  background: var(--mmtoc-line);
  border-radius: 1px;
}

/* Progress line — animated fill above the active item (JS sets --mmtoc-progress %) */
.mmtoc--timeline::after {
  content: "";
  position: absolute;
  inset-inline-start: var(--mmtoc-track);
  inset-block-start: 0;
  width: 2px;
  height: var(--mmtoc-progress, 0%);
  background: var(--mmtoc-accent);
  border-radius: 1px;
  transition: height 0.4s var(--mmtoc-spring);
}

/* Each item gets a dot on the timeline track */
.mmtoc--timeline .mmtoc__item {
  position: relative;
}

.mmtoc--timeline .mmtoc__link {
  position: relative; /* positioning context for the dot so it tracks the link row */
  padding-block: 0.3125em;
}

/* Dot marker */
.mmtoc--timeline .mmtoc__link::before {
  content: "";
  position: absolute;
  inset-inline-start: -1.25em; /* align with track centre */
  top: 50%;
  transform: translateY(-50%);
  width: 0.625em;
  height: 0.625em;
  border-radius: 50%;
  background: var(--mmtoc-line);
  transition:
    background-color 0.25s var(--mmtoc-spring),
    transform 0.25s var(--mmtoc-spring);
}

/* Active dot */
.mmtoc--timeline .mmtoc__link[aria-current="location"]::before {
  background: var(--mmtoc-active);
  transform: translateY(-50%) scale(1.4);
}

/* Placeholder items host a nested sublist only: hide their own (non-existent) link
   and dot, but keep the <li> itself visible so the nested real items still render. */
.mmtoc--timeline .mmtoc__item--placeholder > .mmtoc__link {
  display: none;
}

/* Sublist items get slightly smaller dots */
.mmtoc--timeline .mmtoc__sublist .mmtoc__link::before {
  width: 0.4375em;
  height: 0.4375em;
  inset-inline-start: -1.15em;
}

/* ============================================================
   5. Mobile floating button + full-screen modal
   ============================================================ */

.mmtoc-mobile__button {
  position: fixed;
  inset-inline-end: 1.25rem;
  /* Default 1.5rem; raise via --mmtoc-mobile-offset (settings) to clear a site's
     own fixed bottom UI such as a sticky CTA bar. */
  inset-block-end: var(--mmtoc-mobile-offset, 1.5rem);
  z-index: 200;
  appearance: none;
  background: var(--mmtoc-accent);
  color: #fff;
  border: none;
  border-radius: 50%;
  width: 3rem;
  height: 3rem;
  cursor: pointer;
  box-shadow: 0 4px 12px rgb(0 0 0 / 0.2);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.mmtoc-mobile__button:hover,
.mmtoc-mobile__button:focus-visible {
  transform: scale(1.08);
  box-shadow: 0 6px 16px rgb(0 0 0 / 0.28);
  /* 2px / offset 2px to match the toggle and close buttons (and host themes that
     standardize a 2px focus ring). */
  outline: 2px solid var(--mmtoc-accent);
  outline-offset: 2px;
}

/* Button icon (background-image SVG) */
.mmtoc-mobile__button::before {
  content: "";
  display: block;
  width: 1.375rem;
  height: 1.375rem;
  background-image: url("../images/toc-icon.svg");
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;
  /* Invert to white because the button is accent-colored */
  filter: brightness(0) invert(1);
}

/* The wide-screen hide of .mmtoc-mobile is emitted inline by
   MMTOC_Assets::breakpoint_css() (configurable; default 1440px). */

/* Modal backdrop */
.mmtoc-mobile__modal {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgb(0 0 0 / 0.5);
  display: flex;
  align-items: flex-end;
  justify-content: stretch;
}

/* Panel (slide-up sheet) */
.mmtoc-mobile__panel {
  position: relative;
  background: #fff;
  border-start-start-radius: var(--mmtoc-radius);
  border-start-end-radius: var(--mmtoc-radius);
  width: 100%;
  max-height: 75vh;
  overflow-y: auto;
  padding: 1.25rem 1.25rem 2rem;
  /* Slide-up entry animation — driven by JS adding/removing [hidden] */
}

.mmtoc-mobile__title {
  font-size: 1rem;
  font-weight: 700;
  margin-bottom: 0.75em;
  padding-inline-end: 2.5em; /* room for close button */
}

/* Close button (×) */
.mmtoc-mobile__close {
  position: absolute;
  inset-block-start: 1rem;
  inset-inline-end: 1rem;
  appearance: none;
  background: none;
  border: none;
  cursor: pointer;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: inherit;
  opacity: 0.6;
  transition: opacity 0.15s ease, background-color 0.15s ease;
}

.mmtoc-mobile__close:hover,
.mmtoc-mobile__close:focus-visible {
  opacity: 1;
  background-color: color-mix(in srgb, currentColor 10%, transparent);
  outline: 2px solid var(--mmtoc-accent);
  outline-offset: 2px;
}

/* × symbol via pseudo-element */
.mmtoc-mobile__close::before,
.mmtoc-mobile__close::after {
  content: "";
  position: absolute;
  width: 1em;
  height: 2px;
  background: currentColor;
  border-radius: 1px;
}

.mmtoc-mobile__close::before {
  transform: rotate(45deg);
}

.mmtoc-mobile__close::after {
  transform: rotate(-45deg);
}

.mmtoc-mobile__body {
  padding-top: 0.25em;
}

/* ============================================================
   6. Reduced-motion overrides (spec §9-1, §11)
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  /* Disable spring / easing transitions on timeline */
  .mmtoc--timeline::after,
  .mmtoc--timeline .mmtoc__link::before,
  .mmtoc--timeline .mmtoc__link[aria-current="location"]::before {
    transition: none;
  }

  /* Disable generic link hover transitions */
  .mmtoc__link {
    transition: none;
  }

  /* Disable button transitions */
  .mmtoc-mobile__button,
  .mmtoc__toggle {
    transition: none;
  }

  /* Inline / sidebar collapse is instant (no grid-row animation) */
  .mmtoc__body,
  .mmtoc-sidebar__body {
    transition: none;
  }

  /* Disable smooth scrolling (also applied globally as a courtesy) */
  :root {
    scroll-behavior: auto !important; /* stylelint-disable-line declaration-no-important */
  }

  html {
    scroll-behavior: auto !important; /* stylelint-disable-line declaration-no-important */
  }
}

/* ============================================================
   7. RTL support
   All positional rules already use logical properties (inset-inline-*,
   padding-inline-*, border-start-*) so RTL flips automatically.
   Additional explicit overrides are listed here for documentation.

   .mmtoc-sidebar--left  → in RTL becomes visually right
   .mmtoc-sidebar--right → in RTL becomes visually left
   This is the intended behaviour: "left" means "start of content flow".

   To reverse the mapping if a RTL site wants literal left/right:
     :dir(rtl) .mmtoc-sidebar--left  { inset-inline-start: auto; inset-inline-end: ... }
     :dir(rtl) .mmtoc-sidebar--right { inset-inline-end: auto; inset-inline-start: ... }
   That override should be placed in the theme stylesheet, not here.
   ============================================================ */

/* ============================================================
   Font size
   The sidebar (timeline) scales proportionally via its container, so the track / dot
   geometry (which is em-based) stays aligned at any size. Inline and mobile instead set
   the EXACT link text size, so "16px" renders as 16px text (not 0.875 * 16 = 14px).
   ============================================================ */

.mmtoc-sidebar {
  font-size: var(--mmtoc-font-size, 1em);
}

.mmtoc-inline .mmtoc__link,
.mmtoc-mobile .mmtoc__link {
  font-size: var(--mmtoc-font-size, 0.875em);
}

/* ============================================================
   8. Scrollbar styling for sidebar / modal panel (cosmetic only)
   ============================================================ */

.mmtoc-sidebar,
.mmtoc-mobile__panel {
  scrollbar-width: thin;
  scrollbar-color: var(--mmtoc-line) transparent;
}

.mmtoc-sidebar::-webkit-scrollbar,
.mmtoc-mobile__panel::-webkit-scrollbar {
  width: 4px;
}

.mmtoc-sidebar::-webkit-scrollbar-thumb,
.mmtoc-mobile__panel::-webkit-scrollbar-thumb {
  background: var(--mmtoc-line);
  border-radius: 2px;
}
