/* layout.css — Tufte-inspired 2-column layout + optional docs-style sidebar
 *
 * Three structural layers:
 *
 * 1. Page chrome at very top: theme toggle (top-right, position: fixed).
 *
 * 2. Optional left sidebar (Sidebar.astro). At ≥80rem (1280px), grid
 *    pins it to the left edge; below 1280px it's hidden and the mobile
 *    nav drawer is the chapter nav (v4.26.0, #80). Toggle per-page via
 *    Base.astro's `showSidebar` prop — default true; landing sets false.
 *
 * 3. Main content (.prose) — Tufte 2-column with sidenotes in right
 *    margin on desktop (≥48rem), inline on mobile (<48rem). See
 *    tokens.css for the three-tier --measure-main width strategy.
 *
 * Zero JavaScript. Pure CSS. Respects Gwern's "no effort" principle:
 * sidenotes are always visible at reading speed; the only thing that
 * changes across breakpoints is where they sit.
 */

/* ===== Optional left sidebar (docs-style nav) ===== */

/* Default layout when sidebar is present but viewport too narrow:
 * stack vertically, hide sidebar. Below 1024px the sidebar component
 * is display:none; the slot occupies full width. */
.layout-with-sidebar {
  display: block;
}
.layout-with-sidebar > .sidebar {
  display: none;
}

/* At 1024px+: pin sidebar to left, main content fills remainder. */
/* v4.26.0 (#80): the full 3-column (sidebar + Tufte gutter) needs room the
 * sidebar steals, so it activates at 80rem (1280px) — below that the drawer is
 * the chapter nav and content runs full-width (the gutter/section-map then fits
 * in the whole viewport). This is where the gutter genuinely fits beside the
 * sidebar with the trimmed measures. */
@media (min-width: 80rem) {
  .layout-with-sidebar {
    display: grid;
    grid-template-columns: 14rem 1fr;   /* trimmed so main+gutter fits beside it */
    grid-template-areas: 'sidebar main';
    min-height: 100vh;
  }
  .layout-with-sidebar > .sidebar {
    display: block;
  }
  .layout-with-sidebar > .layout-main {
    grid-area: main;
    min-width: 0; /* prevent overflow from long pre/code */
  }
}

/* Slightly wider sidebar at 1440px+ — more breathing room for chapter
 * titles. */
@media (min-width: 90rem) {
  .layout-with-sidebar {
    grid-template-columns: 16rem 1fr;
  }
}

.prose {
  /* Container width = main + gutter + sidenote column + outer padding */
  max-width: calc(
    var(--measure-main) + var(--space-6) + var(--measure-side)
    + 2 * var(--space-4)
  );
  margin: var(--space-8) auto;
  padding: 0 var(--space-4);
  position: relative;
}

/* Default: constrain direct children to the main-text measure.
 * The remaining ~31ch becomes the right margin for sidenotes. */
.prose > * {
  max-width: var(--measure-main);
}

/* Sidenote: floats into the right margin on desktop.
 * Float + negative margin-right is the classic Tufte-CSS technique —
 * the element aligns to where it appears in document flow (roughly
 * next to its referencing paragraph), not to a fixed row. */
.sidenote {
  float: right;
  clear: right;
  width: var(--measure-side);
  margin-right: calc(-1 * (var(--measure-side) + var(--space-6)));
  margin-top: 0.3rem;
  margin-bottom: var(--space-3);
  padding-left: var(--space-3);
  border-left: var(--border-bar) solid var(--color-border);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  font-style: italic;
  color: var(--color-text-muted);
  display: block;
  position: relative;
}

/* ===== Auto-numbered sidenote markers (CSS counters) =====
 * Counter resets per .prose so each chapter numbers from 1. The marker
 * and its matching sidenote share the same counter value because only
 * the marker increments it. */
.prose {
  counter-reset: sidenote;
}

.sidenote-marker {
  counter-increment: sidenote;
  color: var(--color-link);
  cursor: help;
  font-size: 0.75em;
  vertical-align: super;
  line-height: 0;
  margin-left: 0.1em;
}
.sidenote-marker::after {
  content: counter(sidenote);
}

/* Sidenote itself prefixes with the counter so readers can match
 * marker-in-main-text with note-in-margin. */
.sidenote::before {
  content: counter(sidenote) ". ";
  font-weight: 500;
  color: var(--color-link);
  margin-right: 0.15em;
}

/* ===== Mobile breakpoint: inline-flow asides =====
 * Sidenotes break out of float and become visually-distinct inline
 * blocks immediately after their position in the document flow.
 * No tap, no reveal, no layout shift — Gwern's "no effort" principle. */
@media (max-width: 48rem) {
  .prose {
    max-width: var(--measure-main);
  }

  .sidenote {
    float: none;
    clear: none;
    width: auto;
    max-width: none;
    margin: var(--space-3) 0 var(--space-3) var(--space-3);
    padding: var(--space-2) var(--space-3);
    border-left: var(--border-bar) solid var(--callout-info);
    background: var(--warm-blue-tint);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    font-size: var(--text-sm);
    font-style: italic;
    color: var(--color-text);
  }
}

/* Escape class for wide content (figures, large tables, code blocks
 * that need the full container width including the sidenote column). */
.wide {
  max-width: none !important;
  width: 100%;
}

/* ===== 1d: additive figure/content placement + per-page width knob =====
 *
 * STRICTLY ADDITIVE. Nothing here changes `.prose`'s block layout or the
 * `.sidenote` float — the gutter placements below REUSE the same Tufte
 * float + negative-margin-right technique `.sidenote` and SectionMap use
 * (the full float→grid migration is deferred). All values are tokens.
 *
 * .column-margin   — generic "float a block into the right gutter" utility
 *                    (the un-figure version of MarginFigure's placement).
 * .margin-figure   — MarginFigure's wrapper: the same gutter float, tuned for
 *                    a figure (small caption, no italic).
 * .column-page     — full-width breakout; an ALIAS of `.wide` (which already
 *                    does the max-width override). Use either.
 * .prose[data-layout="wide"] — the per-page width knob: widen the main text
 *                    measure. Only applies when Chapter.astro emits
 *                    data-layout="wide" from frontmatter `layout: wide`.
 */

/* Float a block into the right gutter — same mechanism as .sidenote: the
 * negative margin-right pulls the box into the --measure-side column so it
 * sits BESIDE the running text instead of pushing the measure. Shown only at
 * >= 64rem (the gutter breakpoint, matching SectionMap); below that it reflows
 * inline in document flow (the rule simply doesn't apply). */
@media (min-width: 64rem) {
  .column-margin,
  .margin-figure {
    float: right;
    clear: right;
    width: var(--measure-side);
    margin-right: calc(-1 * (var(--measure-side) + var(--space-6)));
    margin-top: 0.3rem;
    margin-bottom: var(--space-3);
  }
}

/* MarginFigure: a Figure wrapped for the gutter. The wrapped <figure> fills
 * the column; the caption stays small (margin context = less room) without
 * touching the global .figure/figcaption rules. */
.margin-figure > .figure {
  margin: 0;
  max-width: none;
}
.margin-figure figcaption {
  font-size: var(--text-xs);
  line-height: var(--leading-normal);
}

/* Full-width breakout: an alias of `.wide` (figures, wide tables, code that
 * need the whole container including the gutter column). `.wide` is the
 * canonical escape; `.column-page` reads better next to `.column-margin`. */
.column-page {
  max-width: none !important;
  width: 100%;
}

/* Per-page width knob (frontmatter `layout: wide`). Widen ONLY the main text
 * measure; the container + gutter math in `.prose` already references
 * --measure-main, so this one override flows through. Additive: absent
 * data-layout (or "default") matches nothing, so existing chapters are
 * unaffected. 80ch matches the wide-desktop tier's main measure (tokens.css). */
.prose[data-layout="wide"] {
  --measure-main: 80ch;
}

/* ===== Mobile/tablet nav drawer (v4.26.0, #80) =====
 * Below the sidebar breakpoint (80rem — matching .layout-with-sidebar above and
 * the controller's desktop auto-close) the left Sidebar is display:none — this
 * is the navigation in that range: a hamburger in the chrome row toggles a
 * slide-in drawer reusing NavContent (the same book-scoped nav source as the
 * sidebar). No-JS baseline: `:target` opens it (the toggle is <a href="#nav-drawer">);
 * the inline controller in Base.astro enhances it with focus-trap + ESC + body
 * scroll-lock. Hidden at ≥80rem, where the persistent sidebar is the nav. The
 * ≥64rem gutter tier (sidenote/section-map floats) is a separate, lower breakpoint. */
@media (min-width: 80rem) {
  /* #183: `.chrome-buttons .nav-toggle` (0,2,0), not bare `.nav-toggle` —
   * Base.astro's global `.chrome-button { display: inline-flex }` ties a
   * (0,1,0) selector and wins on cascade order, leaving the hamburger
   * visible at desktop where it opens an invisible drawer and strands the
   * body scroll-lock. Caught by drawer-interaction.spec.ts. */
  .chrome-buttons .nav-toggle,
  .nav-drawer {
    display: none;
  }
}

@media (max-width: 79.98rem) {
  .nav-drawer {
    position: fixed;
    inset: 0;
    z-index: var(--z-drawer, 30);
    visibility: hidden;
  }
  .nav-drawer.is-open,
  .nav-drawer:target {
    visibility: visible;
  }
  .nav-drawer-backdrop {
    position: absolute;
    inset: 0;
    border: 0;
    background: rgba(0, 0, 0, 0.5);
    opacity: 0;
    transition: opacity 200ms ease;
  }
  .nav-drawer-panel {
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: min(20rem, 85vw);
    max-height: 100vh;
    overflow-y: auto;
    background: var(--color-bg-subtle);
    border-right: 1px solid var(--color-border);
    padding: var(--space-6) var(--space-5);
    transform: translateX(-100%);
    transition: transform 220ms ease;
  }
  .nav-drawer.is-open .nav-drawer-panel,
  .nav-drawer:target .nav-drawer-panel {
    transform: translateX(0);
  }
  .nav-drawer.is-open .nav-drawer-backdrop,
  .nav-drawer:target .nav-drawer-backdrop {
    opacity: 1;
  }
  .nav-drawer-dismiss {
    position: absolute;
    top: var(--space-3);
    inset-inline-end: var(--space-3);
    z-index: 1;
  }
}

/* Body scroll-lock while the drawer is open (class toggled by the controller). */
.nav-drawer-locked {
  overflow: hidden;
}

/* ===== Gutter-fit (v4.26.0, #80) =====
 * The Tufte right-gutter (.section-map scrollspy + .sidenote / .column-margin /
 * .margin-figure floats) used to size its main+gutter measure against the FULL
 * viewport, ignoring that a left sidebar steals 14–16rem — so the negative-margin
 * float landed PAST the viewport at 1024px AND 1440px. The fix is in tokens.css:
 * the `--measure-main` / `--measure-side` tiers are trimmed (60/20ch → 66/20ch →
 * 78/24ch) and the sidebar to 14/16rem, so `main + gutter ≤ layout-main` (viewport
 * − sidebar) at every desktop width. The gutter scrollspy now FITS beside the
 * sidebar instead of overflowing — no suppression, no breakpoint games. Verified
 * scrollWidth == clientWidth across the responsive audit harness. */

@media (prefers-reduced-motion: reduce) {
  .nav-drawer-panel,
  .nav-drawer-backdrop {
    transition: none;
  }
}
