/* Slide-mode overrides. The reveal.js wrapper takes over the viewport
   when body.mode-slides is set. We adjust a few defaults so x-ocaml
   cells render comfortably inside slides. */

body.mode-slides {
  background: #ffffff;
}

/* The sidebar + prev/next are .chapter-only; CSS hides them in slide
   mode just like other chapter-only content. */
body.mode-slides .chapter-only { display: none !important; }

/* Quizzes are reading-mode only: the recorded video does not pause
   for them. They stay in the DOM (so localStorage state persists
   across mode toggles) but are not displayed in slide mode. */
body.mode-slides .quiz { display: none !important; }

/* Heading permalinks (the ¶ anchors injected by the runtime) are
   useful in the chapter view for deep-linking, but on a slide
   they are visual clutter that the recorded video should not show. */
body.mode-slides .permalink { display: none !important; }

body.mode-slides .reveal {
  display: block;
  position: fixed;
  inset: 0;
  transition: opacity 0.18s ease-out;
}
/* While the cells are still settling their height after a refresh,
   hide the slide area so the user does not see the ~100px reflow
   that happens as x-ocaml replaces the cell's plain-text body with
   a CodeMirror editor. The runtime script adds [slides-loading] on
   entering slide mode and removes it once cell sizes have been
   quiet for ~150ms (or after a 1500ms failsafe). */
body.mode-slides.slides-loading .reveal {
  opacity: 0;
  pointer-events: none;
}

body.mode-slides .reveal .slides section.slide,
body.mode-slides .reveal .slides section[data-slide] {
  text-align: left;
  font-size: 1.7rem;
  line-height: 1.55;
  padding: 1rem 2rem;
  border-left: none;
  background: transparent;
  /* Cap section at the canvas height (1280x800) and let it scroll
     internally if dynamic content (e.g. an x-ocaml cell's output
     after pressing Run) pushes it past the canvas. overflow-y:auto
     means the scrollbar appears only when overflow actually
     happens; static slides that already fit stay scrollbar-free.
     box-sizing: border-box so the 1rem top + bottom padding stays
     inside the 800px budget. */
  max-height: 800px;
  overflow-y: auto;
  box-sizing: border-box;
  /* Firefox: always render a slim scrollbar (only visible when
     overflow actually happens). */
  scrollbar-width: thin;
  scrollbar-color: rgba(0, 0, 0, 0.35) transparent;
}
/* Webkit/Blink: force the scrollbar to be visible instead of the
   macOS overlay default, so the user sees there's more content
   below when a cell's output pushes the slide past the canvas. */
body.mode-slides .reveal .slides section.slide::-webkit-scrollbar,
body.mode-slides .reveal .slides section[data-slide]::-webkit-scrollbar {
  width: 8px;
}
body.mode-slides .reveal .slides section.slide::-webkit-scrollbar-track,
body.mode-slides .reveal .slides section[data-slide]::-webkit-scrollbar-track {
  background: transparent;
}
body.mode-slides .reveal .slides section.slide::-webkit-scrollbar-thumb,
body.mode-slides .reveal .slides section[data-slide]::-webkit-scrollbar-thumb {
  background: rgba(0, 0, 0, 0.3);
  border-radius: 4px;
}
body.mode-slides .reveal .slides section.slide::-webkit-scrollbar-thumb:hover,
body.mode-slides .reveal .slides section[data-slide]::-webkit-scrollbar-thumb:hover {
  background: rgba(0, 0, 0, 0.5);
}

/* Bullet lists in slide mode: looser spacing, no decorative wall of text. */
body.mode-slides .reveal .slides section ul,
body.mode-slides .reveal .slides section ol {
  margin: 0.4rem 0 0.6rem 1.2rem;
  padding: 0;
}
body.mode-slides .reveal .slides section li {
  margin: 0.55rem 0;
}
body.mode-slides .reveal .slides section p {
  margin: 0.6rem 0;
}

/* Override reveal.js's stock theme upper-casing of headings -- titles
   like "Slide 1 -- Hello" render as "SLIDE 1 -- HELLO" otherwise. */
body.mode-slides .reveal .slides section h1,
body.mode-slides .reveal .slides section h2,
body.mode-slides .reveal .slides section h3,
body.mode-slides .reveal .slides section h4,
body.mode-slides .reveal .slides section h5,
body.mode-slides .reveal .slides section h6 {
  text-transform: none;
  font-family: ui-sans-serif, system-ui, -apple-system, sans-serif;
  margin-top: 0;
}
body.mode-slides .reveal .slides section h1,
body.mode-slides .reveal .slides section h2 {
  font-size: 2.8rem;
}
body.mode-slides .reveal .slides section h3 {
  font-size: 2rem;
}

/* Title slide. Carries course name, lecture title, Module/Lecture
   label, and instructor. Authored in markdown as a `:::slide` block
   wrapping a `<div class="title-slide-inner">`; reveal.js sets
   `style="display: block"` inline on every visible section, so we
   cannot flex the section itself. The inner wrapper takes the
   canvas height and does the vertical centring; text is
   left-aligned. */
body.mode-slides .reveal .slides section:has(.title-slide-inner) {
  text-align: left;
}
body.mode-slides .reveal .slides .title-slide-inner {
  /* Section is capped at 800px with 1rem top + 1rem bottom
     padding (box-sizing: border-box), so the usable inner area
     is 800px - 2rem. Use that exactly so vertical centring fills
     the canvas without spilling into the scrollbar zone. */
  min-height: calc(800px - 2rem);
  max-width: 95%;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
}
body.mode-slides .reveal .slides .title-slide-course {
  font-size: 1.6rem;
  color: var(--muted, #555);
  margin: 0 0 1rem 0;
  letter-spacing: 0.02em;
}
body.mode-slides .reveal .slides .title-slide-lecture {
  font-size: 3.2rem;
  font-weight: 700;
  margin: 0 0 0.8rem 0;
  line-height: 1.15;
}
body.mode-slides .reveal .slides .title-slide-label {
  font-size: 1.4rem;
  color: var(--muted, #555);
  margin: 0 0 2.4rem 0;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
body.mode-slides .reveal .slides .title-slide-instructor {
  font-size: 1.5rem;
  margin: 0;
  line-height: 1.4;
}

body.mode-slides x-ocaml {
  /* em (not rem) so the cell font scales with the slide body
     font-size. The x-ocaml shadow-DOM CSS sets the editor to
     :host { font-size: 1.2em } on top of whatever we set here,
     so the effective rendered code size is host * 1.2. At slide
     body 1.7rem, 0.68em gives a host ~18.5px and a rendered code
     size of ~22px, readable from across a lecture hall while
     leaving room for long lines. */
  font-size: 0.68em;
  margin: 0.6rem 0;
}

/* Plain (non-x-ocaml) code blocks. reveal.js's default theme
   shrinks <pre>/<code> to ~13px, which is unreadable against
   1.35rem bullet text. Bump it back up so verbatim code reads
   at roughly the same size as the rest of the slide content. */
body.mode-slides .reveal .slides section pre,
body.mode-slides .reveal .slides section pre code,
body.mode-slides .reveal .slides section code {
  font-size: 0.9em;
  line-height: 1.4;
}

/* Inline code in slide prose (bullets, paragraphs) blends into
   the surrounding monospace-on-white when uncoloured, especially
   on slides that also show grey-background code blocks. Tint it
   so identifiers like `is_comfortable` or values like `true` pop
   from the prose. Block code inside <pre> (and x-ocaml cells)
   already has its own syntax highlighting; leave that alone. */
body.mode-slides .reveal .slides section code {
  color: #0d6b6b;
}
body.mode-slides .reveal .slides section pre code,
body.mode-slides .reveal .slides section x-ocaml code {
  color: inherit;
}

/* The .cell-wrap is a block-level div around each cell. In slide
   mode reveal.js gives the section a fixed canvas width and the
   cell otherwise stretches to fill it, which puts the Run button
   far to the right of the prose. Cap the wrapper width and align
   it left so it sits flush with the headings and bullets, not
   centred (which would create dead space on the left). */
body.mode-slides .cell-wrap {
  max-width: 85%;
  margin-left: 0;
  margin-right: auto;
}

/* Images in slide mode: size to fit comfortably without pushing
   following content off the slide. We cap both width and height so
   a tall diagram does not run into the lower bullets, and a wide
   diagram does not touch the slide borders. */
body.mode-slides .reveal .slides section img {
  display: block;
  margin: 0.6rem auto;
  max-width: min(92%, 1140px);
  max-height: 66vh;
  width: auto;
  height: auto;
}

/* On a "diagram-only" slide (no text bullets following), let the
   image take more vertical room. We detect this loosely: if the
   <section> has nothing after the <p><img></p> except whitespace,
   the section ends up with a single <p>-wrapped image. Give that
   case more headroom. */
body.mode-slides .reveal .slides section > p:only-of-type img {
  max-height: 78vh;
  max-width: 95%;
}

/* Portrait shots (a single person, biographical asides) are
   tall and would crowd out the rest of the slide at the default
   60vh cap. Pin them well below half the canvas height. */
body.mode-slides .reveal .slides section img.portrait {
  max-height: 32vh;
  max-width: 220px;
}

/* Reset (↺) stays visible in slide mode -- useful when presenting
   to revert a live edit. Position is handled by the cell wrapper
   (chapter.css), which works in both modes. */

/* Header bar shrinks in slide mode to free vertical space. */
body.mode-slides .page-header {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 50;
  background: transparent;
  border-bottom: none;
  padding: 0.4rem 1rem;
}
body.mode-slides .lecture-meta,
body.mode-slides .lecture-title {
  opacity: 0.6;
}

/* Fragments use reveal.js's native behavior. */
.reveal .fragment {
  opacity: 0;
  transition: opacity 0.2s ease-out;
}
.reveal .fragment.visible {
  opacity: 1;
}

/* Two-column (or N-column) slide layout. Authored as :::cols /
   :::col [<n>%] in markdown. .col items use flex: 1 1 0 by default;
   the parser emits an inline style="flex: 0 0 N%;" to pin a width.
   align-items: center vertically centers a short RHS image against
   taller LHS bullets -- the common text+image case. Rules are
   unscoped so the same layout applies in chapter mode, where
   slides also appear inline. */
.cols {
  display: flex;
  gap: 1.5rem;
  align-items: center;
  margin: 0.8rem 0;
}
.cols > .col {
  flex: 1 1 0;
  min-width: 0;
}
/* Inside a column, images should fill the column width rather than
   the slide-wide 92%/1140px cap. Drop the canvas-height cap too: the
   column is already bounded by its sibling's height. */
.cols > .col img,
.cols > .col svg {
  display: block;
  max-width: 100%;
  max-height: none;
  margin: 0 auto;
  height: auto;
}


/* Narrow viewports: stack columns. !important defeats the inline
   style="flex: 0 0 N%;" so a 60%-pinned column does not become a
   60%-height stripe once flex-direction flips. */
@media (max-width: 700px) {
  .cols { flex-direction: column; align-items: stretch; }
  .cols > .col { flex: 0 0 auto !important; }
}

/* Compact precedence table: a tall many-row table needs tighter rows
   to fit the 1280x800 slide canvas without overflow. */
body.mode-slides .reveal .slides section .precedence-table table {
  font-size: 0.85em;
}
body.mode-slides .reveal .slides section .precedence-table th,
body.mode-slides .reveal .slides section .precedence-table td {
  padding: 0.18rem 0.6rem;
  line-height: 1.25;
}
