html, body { background: #000; color: var(--ivory); margin: 0; font-family: var(--font-ui); }

section.slide {
  width: 1920px; height: 1080px;
  position: relative; overflow: hidden;
  font-family: var(--font-ui);
  color: var(--ivory);
  background: var(--charcoal);
  padding: 96px 140px;
  box-sizing: border-box;
}

/* Hide the slide label by default · kept in the DOM for tooling/scripts. */
.sl-label { display: none; }

/* Standalone page layout for a single slide · always scales to fit viewport 16:9.
   The JS in present.js sets the transform on section.slide to keep it in view. */
body.slide-page {
  margin: 0; padding: 0;
  width: 100vw; height: 100vh;
  overflow: hidden;
  background: #000;
}
body.slide-page section.slide {
  position: absolute;
  top: 0; left: 0;
  transform-origin: 0 0;
  /* transform is set inline in <head> (sync) and kept in sync by present.js on resize. */
  margin: 0;
}
/* Presenting is the fullscreen variant · shares the same scaling behaviour. */
body.presenting { background: #000; }

/* Deck index */
body.index {
  padding: 60px 80px; color: var(--ivory); background: var(--charcoal);
}
body.index h1 { font-family: var(--font-display); font-size: 72px; margin: 0 0 40px; letter-spacing: -0.01em; }
body.index .toc { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 20px; }
body.index .toc a {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 20px 24px; background: var(--charcoal-90); color: var(--ivory);
  text-decoration: none; border-left: 4px solid var(--patagonia);
  font-family: var(--font-mono); font-size: 16px; letter-spacing: 0.08em;
}
body.index .toc a:hover { background: var(--charcoal-70); }
body.index .toc a .num { color: var(--lemon); margin-right: 16px; }
body.index .mode-flag {
  position: fixed; top: 20px; right: 20px;
  padding: 8px 16px; font-family: var(--font-mono); font-size: 14px;
  letter-spacing: 0.15em; text-transform: uppercase;
  background: var(--lemon); color: var(--charcoal);
}

/* Variant cycle HUD · shown briefly when pressing `v` on a standalone slide. */
.variant-hud {
  position: fixed; bottom: 24px; right: 24px;
  padding: 10px 18px; font-family: var(--font-mono); font-size: 14px;
  letter-spacing: 0.15em; text-transform: uppercase;
  background: var(--lemon); color: var(--charcoal);
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
  z-index: 300;
}
.variant-hud.show { opacity: 1; }

/* Slide transitions · fade + 8px slide-up on enter, inverse on exit.
   The transform is composed with the fit() scale — we apply the
   animation to section.slide's children wrapper via a CSS variable so
   the outer transform (scaling) stays untouched. */
body.slide-page section.slide > *:not(h1):not(h2):not(h3) {
  animation: slide-content-in 220ms ease-out both;
}
@keyframes slide-content-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
body.slide-page.slide-exiting section.slide > *:not(h1):not(h2):not(h3) {
  animation: slide-content-out 140ms ease-in both;
}
@keyframes slide-content-out {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(-8px); }
}

/* Streaming text · headings reveal character-by-character.
   JS wraps each char in a span.sc; we fade them in on a stagger.
   Headings start invisible to prevent a flash of the fully-rendered text
   before the JS splits them — `data-streamed` is set synchronously by JS
   before the first paint completes. */
body.slide-page section.slide h1:not([data-streamed]),
body.slide-page section.slide h2:not([data-streamed]),
body.slide-page section.slide h3:not([data-streamed]) { visibility: hidden; }
.sc { opacity: 0; }
.sc.on { opacity: 1; transition: opacity 20ms linear; }
/* Caret rides the most-recently-revealed character. JS moves the
   `.sc-caret` class forward; only while the heading is still streaming
   (body has `.streaming`) do we render it. */
.sc-caret::after {
  content: "▏";
  display: inline-block;
  margin-left: 0.05em;
  color: var(--lemon);
  animation: caret-blink 700ms steps(1, end) infinite;
  vertical-align: baseline;
  font-weight: 400;
}
@keyframes caret-blink { 50% { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  body.slide-page section.slide > *,
  body.slide-page.slide-exiting section.slide > * { animation: none; }
  .sc { opacity: 1; transition: none; }
  .streaming-caret::after { display: none; }
}

/* Dual-mode: metadata field display */
.field-meta {
  display: inline-block;
  background: rgba(249, 215, 28, 0.18);
  border: 2px dashed var(--red);
  color: var(--lemon);
  padding: 2px 10px;
  font-family: var(--font-mono);
  letter-spacing: 0.05em;
  text-transform: none;
  font-size: 0.8em;
  font-style: normal;
  font-weight: 400;
}
.field-meta::before { content: "{ "; opacity: 0.5; }
.field-meta::after  { content: " }"; opacity: 0.5; }
