/* ---- Zen mode ----
   A chrome state of the reader, toggled by zen.js as a .zen class on <html>. The same
   rendered article stays underneath with the same theme, fonts, math, and callouts;
   these rules only change what is drawn around the text. Four continuous variables are
   layered over the reader's existing knobs:
     --zen-scale    multiplier over --reader-size (text size slider)
     --zen-measure  column width in ch, overriding --measure (line width slider)
     --zen-offset   column shift in vw, negative = left of centre (position slider)
     --zen-dim      0..70, how far the backdrop falls from --paper toward --ink
   The fade animations below all collapse to instant changes under prefers-reduced-motion
   via coursebook.css's global reduced-motion rule. */

/* The trigger lives in the sidebar's toolbar next to the search and settings buttons,
   and follows the reader-tools__button vocabulary. */
.zen-trigger {
  flex: none;
  align-self: stretch;
  width: 2.4rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink-soft);
  cursor: pointer;
}
.zen-trigger:hover { color: var(--ink); background: var(--paper-2); }
/* The trigger's display:inline-flex would otherwise override the [hidden] default of
   display:none, leaving a hidden-but-clickable button; honor the attribute explicitly. */
.zen-trigger[hidden] { display: none; }

/* Text scale rides on top of the small/base/large steps: html's font-size is normally
   var(--reader-size) (coursebook.css), so multiplying here scales the article's type and
   its em/rem spacing together, keeping the typographic hierarchy. What makes this a text
   size control and not a magnifier is that the paper itself never moves: --zen-paper-width
   below is px/vw only, the .main paddings derive from it, and the control bar is sized in
   px — so growing the text reflows more words per page instead of zooming the page.

   The paper width runs from a narrow-but-readable column (540px, roughly 50ch at the
   base size) at 0 up to the full screen at 100, independent of font size. Position then
   travels the leftover space: at any width, -100 parks the paper's left edge on the
   screen's left edge and +100 parks its right edge on the screen's right edge, so the
   range adapts to the width slider on its own (and collapses to nothing when the paper
   already fills the screen). */
:root.zen {
  font-size: calc(var(--reader-size) * var(--zen-scale, 1));
  --zen-paper-width: clamp(0px, calc(540px + var(--zen-measure, 30) * (100vw - 540px) / 100), 100vw);
}

/* Hide every navigation surface; keep only the article. This is the sidebar-collapsed
   move taken one level further. */
:root.zen .sidebar,
:root.zen .sidebar-controls,
:root.zen .sidebar-backdrop,
:root.zen .outline,
:root.zen .pager {
  display: none;
}

/* The backdrop is the book's own theme colour, dimmed: --zen-dim mixes the page
   background from --paper toward black — not toward --ink, which is light in dark themes
   and would make the surround glow instead of recede. The text column keeps --paper so
   the article reads as a lit page on a receded ground. */
:root.zen body {
  display: block;
  background: color-mix(in oklab, var(--paper), black calc(var(--zen-dim, 35) * 1%));
}
:root.zen .main {
  width: var(--zen-paper-width);
  /* Margins proportional to the paper, not the viewport: a narrow column on a wide
     screen keeps slim margins instead of inheriting the normal reader's 6vw gutters. */
  padding-inline: clamp(1.25rem, calc(var(--zen-paper-width) * .08), 5rem);
  margin-inline: auto;
  background: var(--paper);
  transform: translateX(calc(var(--zen-offset, 0) * (100vw - var(--zen-paper-width)) / 200));
}
/* The paper is the measure now: the article fills it edge to edge of the padding. */
:root.zen .reader-article { max-width: none; }
/* zen.js parks focus on the article (via a temporary tabindex) when entering Zen and
   after in-place navigation, because the sidebar that held it is display:none'd. A focus
   ring around the entire reading column would be pure noise, so suppress it here; the
   ring stays on every actually interactive element. */
:root.zen .reader-article:focus { outline: 0; }
/* Pages with the "On this page" rail laid .reader-body out as a grid to seat it; in Zen
   the rail is gone, so the article takes the whole paper. */
:root.zen .reader-body:has(.outline) { display: block; }

/* ---- Control bar ----
   Hidden off the bottom edge until the pointer nears it (zen.js sets data-visible) or it
   holds keyboard focus. Hiding by transform+opacity rather than display keeps the
   controls tab-reachable, which is what makes :focus-within work. */
.zen-bar { display: none; }
/* The bar is sized in px, not rem: it is fixed chrome, and chrome that grew with the
   text-size slider would read as the page magnifying. It follows the system's
   floating-panel vocabulary (Paper, Rule-Strong hairline, the 12px radius the search
   dialog uses, the one Float shadow) and the reader-tools control vocabulary inside. */
:root.zen .zen-bar {
  position: fixed;
  left: 50%;
  bottom: 18px; /* zen.js derives the pointer-reveal strip from this inset + offsetHeight */
  z-index: 60;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 18px;
  /* A fixed element at left: 50% only gets the right half of the viewport before its
     auto width wraps; max-content sizes it to the row and lets the transform centre it. */
  width: max-content;
  max-width: min(94vw, 1024px);
  padding: 12px 20px;
  border: 1px solid var(--rule-strong);
  border-radius: 12px;
  background: var(--paper);
  color: var(--ink-soft);
  box-shadow: var(--shadow);
  font-family: var(--font-system);
  font-size: 13px;
  opacity: 0;
  transform: translate(-50%, calc(100% + 26px));
  transition: opacity 240ms cubic-bezier(0.22, 1, 0.36, 1), transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
}
:root.zen .zen-bar[data-visible="true"],
:root.zen .zen-bar:hover,
:root.zen .zen-bar:focus-within {
  opacity: 1;
  transform: translate(-50%, 0);
}
.zen-bar__group { display: flex; align-items: center; gap: 16px; }
/* Group separators: a short centred hairline, not a full-height wall. */
.zen-bar__group + .zen-bar__group { position: relative; padding-left: 18px; }
.zen-bar__group + .zen-bar__group::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 24px;
  background: var(--rule);
}
.zen-bar__control { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.zen-bar__control span {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
}

/* Sliders restyled to the system: a hairline track with a quiet Paper thumb, instead of
   the loud native control. The thumb borrows the button vocabulary (Paper fill, Ink-Soft
   line, Ink on hover); the accent stays reserved for the focus ring, which the global
   :focus-visible rule provides. */
.zen-bar input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 104px;
  height: 16px;
  margin: 0;
  background: transparent;
  cursor: pointer;
}
.zen-bar input[type="range"]::-webkit-slider-runnable-track {
  height: 2px;
  border-radius: 999px;
  background: var(--rule-strong);
}
.zen-bar input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 13px;
  height: 13px;
  margin-top: -5.5px;
  border-radius: 50%;
  background: var(--paper);
  border: 1.5px solid var(--ink-soft);
}
.zen-bar input[type="range"]:hover::-webkit-slider-thumb { border-color: var(--ink); }
.zen-bar input[type="range"]::-moz-range-track {
  height: 2px;
  border-radius: 999px;
  background: var(--rule-strong);
}
.zen-bar input[type="range"]::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--paper);
  border: 1.5px solid var(--ink-soft);
}
.zen-bar input[type="range"]:hover::-moz-range-thumb { border-color: var(--ink); }

/* Buttons follow the system button: transparent at rest, Paper-2 fill on hover, 1px Rule
   line, the shared --radius. The pressed Focus toggle uses the reader-tools active
   treatment (accent text on Paper-3) — no accent border; the accent is rationed. */
.zen-bar button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 30px;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink-soft);
  font: inherit;
  font-weight: 500;
  padding: 4px 11px;
  cursor: pointer;
  transition: background-color 150ms ease, color 150ms ease;
}
.zen-bar button:hover { color: var(--ink); background: var(--paper-2); }
.zen-bar button:active { background: var(--paper-3); }
.zen-bar button:disabled { opacity: .35; cursor: default; }
.zen-bar button:disabled:hover { color: var(--ink-soft); background: transparent; }
.zen-bar button[aria-pressed="true"] {
  color: var(--accent);
  background: var(--paper-3);
}
.zen-bar__nav-btn { width: 30px; padding: 4px 0; }
.zen-bar__nav-btn svg { display: block; }

/* After ~2s of pointer stillness zen.js adds this class and the cursor itself disappears,
   the same vanishing-chrome move as the control bar. The first movement removes it, so a
   reader can never be left hunting for an invisible pointer over a control. */
:root.zen.zen-cursor-idle,
:root.zen.zen-cursor-idle * { cursor: none; }

/* Paragraph focus: dim every top-level block except the one under the pointer, narrowing
   attention to a single block at a time. Presentation layered on the rendered article;
   nothing here depends on the source Markdown. The :has() guard keeps the page fully
   legible until a block has actually been focused. */
:root.zen.zen-focus .reader-article > * { transition: opacity 180ms ease; }
:root.zen.zen-focus .reader-article:has(.zen-focused) > :not(.zen-focused) { opacity: .28; }
