/* =====================================================================
   theme.css — THE General Template (Winston "How to Speak" constraints)
   ---------------------------------------------------------------------
   Single source of truth for every deck, every category. Header/list
   boxes, fonts, slide numbers, citations live ONLY here so they stay
   identical across all presentations.

   Design canvas: 1920 x 1080 (16:9). Reveal is configured with
   width/height = canvas in build.mjs, so px below are canvas px.

   LOCKED 2026-06-03: geometry below is approved. To retune later, edit
   ONLY this :root block (then re-view prototype.html); every deck follows.
   ===================================================================== */

:root {
  /* --- palette (white bg, single ink, two stroke colors) --- */
  --bg:            #ffffff;
  --ink:           #111111;
  --header-stroke: #c0392b;   /* red  — header boxes  */
  --list-stroke:   #2e7d32;   /* green — list item boxes */
  --muted:         #555555;   /* captions, citations, page numbers */

  /* --- strokes / corners --- */
  --stroke-w:      4px;
  --radius:        14px;

  /* --- header box (fixed position/size/font across ALL slides) ---
     One margin drives top = left = right, so the box sits high with equal
     gaps and stretches "almost to the edge". Height is shared with list
     items via --box-h so the two box types match exactly. */
  --header-margin: 64px;      /* equal gap: top == left == right */
  --box-h:         140px;     /* identical height for header AND list items */
  --header-w:      calc(1920px - 2 * var(--header-margin));
  --header-top:    var(--header-margin);
  --header-fs:     62px;
  --header-padx:   40px;      /* side gaps allowed inside the box */

  /* --- list item boxes (vertical centered stack) --- */
  --list-w:        1120px;    /* equal width regardless of item count */
  --list-gap:      60px;      /* generous gap between stacked items */
  --list-fs:       46px;
  --list-padx:     36px;

  /* --- body content --- */
  /* derived so it always clears the header box no matter the box size */
  --content-top:   calc(var(--header-top) + var(--box-h) + 56px);
  --content-bot:   120px;     /* bottom reserved (page no / citation) */
  --body-fs:       42px;
  --caption-fs:    30px;

  /* --- chrome --- */
  --cite-fs:       24px;
  --pagenum-fs:    26px;
  --edge-pad:      48px;      /* slide edge padding for chrome */

  /* --- title slide --- */
  --title-fs:      96px;
  --title-meta-fs: 40px;
}

/* ---------------------------------------------------------------------
   Times New Roman, with Tinos (metric-identical, embeddable) as the
   guaranteed-consistent fallback for machines/headless-Chrome that lack
   the real TNR. Stack order: real TNR first, then bundled Tinos.
   --------------------------------------------------------------------- */
@font-face { font-family:'Tinos'; font-style:normal; font-weight:400;
  src:url('fonts/tinos-latin-400-normal.woff2') format('woff2'); font-display:swap; }
@font-face { font-family:'Tinos'; font-style:italic; font-weight:400;
  src:url('fonts/tinos-latin-400-italic.woff2') format('woff2'); font-display:swap; }
@font-face { font-family:'Tinos'; font-style:normal; font-weight:700;
  src:url('fonts/tinos-latin-700-normal.woff2') format('woff2'); font-display:swap; }
@font-face { font-family:'Tinos'; font-style:italic; font-weight:700;
  src:url('fonts/tinos-latin-700-italic.woff2') format('woff2'); font-display:swap; }

:root { --font: "Times New Roman", "Tinos", serif; }

/* ===================== base ===================== */
.reveal            { font-family: var(--font); color: var(--ink); }
.reveal .slides    { text-align: left; }          /* we position explicitly */
html, body, .reveal, .reveal .backgrounds { background: var(--bg) !important; }

/* No background images, ever (enforced). */
.reveal .slide-background { background: var(--bg) !important; }

/* Reveal moves each <section> into a .pdf-page wrapper when exporting to
   PDF, so we must NOT anchor to the section itself (it collapses to zero
   height there, throwing absolute children onto neighbouring pages).
   Instead every slide holds a fixed 1920x1080 .canvas that is THE
   positioning context for header, content, page number and citation —
   identical in live and print modes. overflow:hidden keeps each slide's
   content strictly inside its own page. */
.reveal .slides section { padding: 0; }
.reveal .canvas {
  position: relative; width: 1920px; height: 1080px; overflow: hidden;
}

/* ===================== header box ===================== */
.reveal .canvas > .header {
  position: absolute; top: var(--header-top); left: 50%;
  transform: translateX(-50%);
  width: var(--header-w); min-height: var(--box-h);
  padding: 0 var(--header-padx);
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  border: var(--stroke-w) solid var(--header-stroke);
  border-radius: var(--radius);
  font-size: var(--header-fs); font-weight: 700; line-height: 1.1;
  box-sizing: border-box;
}

/* ===================== content region ===================== */
.reveal .canvas > .content {
  position: absolute; left: 0; right: 0;
  top: var(--content-top); bottom: var(--content-bot);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 28px; padding: 0 var(--edge-pad); box-sizing: border-box;
}
/* When a slide has NO header, content fills the whole vertical space. */
.reveal section.no-header .canvas > .content { top: var(--edge-pad); }

/* images: fit FULLY within the content region (no trimming), never upscale */
.reveal .content .img-single img {
  max-width: 100%; max-height: 100%;
  object-fit: contain; display: block;
}
.reveal .content .img-single { width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center; }
.reveal .content figure { width: 100%; height: 100%; margin: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; }
/* min-height:0 lets the image shrink so the caption always has room */
.reveal .content figure img { flex: 0 1 auto; min-height: 0;
  max-width: 100%; max-height: 100%; object-fit: contain; }
.reveal .content figcaption { flex: none; font-size: var(--caption-fs);
  color: var(--muted); text-align: center; margin-top: 18px; }

/* multiple images side-by-side, equal height, centered.
   min-width:0 defeats flexbox's default min-width:auto, which was forcing
   wide images to overflow (the 3rd/4th-image trimming) instead of shrinking. */
.reveal .content .img-row { display: flex; gap: 40px; width: 100%; height: 100%;
  align-items: center; justify-content: center; }
.reveal .content .img-row img { flex: 0 1 auto; min-width: 0;
  max-width: 100%; max-height: 100%; object-fit: contain; }

/* portrait image + prose: side-by-side split */
.reveal .content .img-split { display: flex; gap: 60px; width: 100%; height: 100%;
  align-items: center; justify-content: center; }
.reveal .content .img-split img { flex: 0 1 auto; min-width: 0;
  max-height: 100%; max-width: 48%; object-fit: contain; }
.reveal .content .img-split .prose { max-width: 46%; font-size: var(--body-fs); line-height: 1.4; }

/* plain body text */
.reveal .content .body { font-size: var(--body-fs); line-height: 1.4; text-align: center; }

/* video */
.reveal .content video { max-width: 100%; max-height: 100%; }

/* YouTube embed — the largest 16:9 frame that fits the content region.
   Our content boxes are wider than 16:9-of-their-height, so size by height. */
.reveal .content .yt { width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center; }
.reveal .content .yt-frame { height: 100%; aspect-ratio: 16 / 9; max-width: 100%; border: 0; display: block; }
.reveal .content .yt-row { display: flex; gap: 40px; width: 100%; height: 100%;
  align-items: center; justify-content: center; }
.reveal .content .yt-row .yt-frame { height: auto; width: 100%; max-height: 100%; min-width: 0; }
.reveal .content figure.yt-fig { gap: 18px; }
.reveal .content figure.yt-fig .yt-frame { flex: 1 1 auto; min-height: 0;
  height: 100%; width: auto; aspect-ratio: 16 / 9; max-width: 100%; }

/* interactive widget host (injected from <deck>/widgets/<slug>.html) */
.reveal .content .widget { width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center; }

/* ===================== list (vertical centered stack) ===================== */
.reveal .content .list { display: flex; flex-direction: column;
  gap: var(--list-gap); align-items: center; width: 100%; }
.reveal .content .list .list-item {
  width: var(--list-w); min-height: var(--box-h);
  padding: 18px var(--list-padx);
  display: flex; align-items: center; justify-content: center;
  text-align: center; line-height: 1.2;
  border: var(--stroke-w) solid var(--list-stroke);
  border-radius: var(--radius);
  font-size: var(--list-fs); box-sizing: border-box;
}

/* ===================== contributions / takeaway (final slide) =====================
   A plain left-aligned bullet list. The (Takeaway) is just another bullet,
   bold, and still a fragment that pops on the next click. No box. */
.reveal .content ul.contrib {
  align-self: flex-start;          /* left-aligned block */
  list-style: disc; text-align: left;
  margin: 0; padding-left: 1.2em; max-width: 1500px;
  font-size: var(--body-fs); line-height: 1.4;
}
.reveal .content ul.contrib li { margin-bottom: 26px; }
.reveal .content ul.contrib li:last-child { margin-bottom: 0; }
.reveal .content ul.contrib li.takeaway { font-weight: 700; }

/* ===================== chrome: page number + citation ===================== */
.reveal .canvas .pagenum { position: absolute; right: var(--edge-pad); bottom: var(--edge-pad);
  font-size: var(--pagenum-fs); color: var(--muted); }
.reveal .canvas .cite { position: absolute; left: var(--edge-pad); bottom: var(--edge-pad);
  font-size: var(--cite-fs); color: var(--muted); max-width: 60%; line-height: 1.25; }
/* citation only renders in the .ref build (build.mjs adds body.with-refs) */
body:not(.with-refs) .reveal .canvas .cite { display: none; }

/* ===================== title slide ===================== */
.reveal section.title-slide .canvas { display: flex; flex-direction: column;
  align-items: center; justify-content: center; text-align: center; }
/* width:100% + text-align:center guarantees horizontal centering regardless
   of flex shrink (a shrink-to-fit title block was sitting left of center). */
.reveal section.title-slide .title { width: 100%; text-align: center;
  font-size: var(--title-fs); font-weight: 700; line-height: 1.1; margin-bottom: 60px; }
.reveal section.title-slide .meta { width: 100%; text-align: center;
  font-size: var(--title-meta-fs); color: var(--ink); line-height: 1.5; }
.reveal section.title-slide .meta .collab { color: var(--muted); }
.reveal section.title-slide .nolaptop { position: absolute; bottom: 70px; left: 50%;
  transform: translateX(-50%); height: 150px; }
.reveal section.title-slide .nolaptop img { height: 100%; }

/* ===================== references page (last slide of .ref build) ===================== */
.reveal section.references .header { /* uses normal header box */ }
.reveal section.references .reflist { position: absolute; top: var(--content-top);
  left: var(--edge-pad); right: var(--edge-pad); bottom: var(--edge-pad);
  font-size: 28px; line-height: 1.4; overflow: auto; }
.reveal section.references .reflist .ref {
  text-indent: -28px; padding-left: 28px; margin-bottom: 14px; }
