/* ============================================================
   sfarrens.css — reveal.js presentation theme
   Matches https://sfarrens.github.io design system.
   Light / dark mode toggled via body.dark-mode class,
   with localStorage persistence and prefers-color-scheme
   as the default.
   ============================================================ */

/* ── Font stacks ──────────────────────────────────────────── */
:root {
  --r-font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
                 Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --r-font-mono: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}

/* ── Light mode tokens (default) ──────────────────────────── */
body {
  --r-bg:          #faf9f7;
  --r-surface:     #ffffff;
  --r-text:        #2c2825;
  --r-heading:     #1a1a1a;
  --r-muted:       #7a7068;
  --r-accent:      #c0584e;
  --r-accent-dim:  #9e403a;
  --r-border:      #e4e1db;
  --r-code-bg:     #f4f6f9;
  --r-code-text:   #476582;
  --r-code-top:    rgba(192, 88, 78, 0.18);
  --r-inline-bg:   rgba(192, 88, 78, 0.08);
  --r-select-bg:   rgba(192, 88, 78, 0.22);
  --r-toggle-bg:   rgba(0, 0, 0, 0.06);
  --r-toggle-fg:   #7a7068;

  /* highlight.js light token colours (GitHub/custom palette) */
  --hl-base:       #476582;
  --hl-comment:    #999988;
  --hl-keyword:    #c558f0;
  --hl-type:       #445588;
  --hl-string:     #746d63;
  --hl-number:     #f39200;
  --hl-function:   #378edf;
  --hl-class:      #378edf;
  --hl-variable:   #008080;
  --hl-attr:       #008080;
  --hl-operator:   #c558f0;
  --hl-builtin:    #d04134;
  --hl-tag:        #000080;
  --hl-regexp:     #009926;
}

/* ── Dark mode tokens ──────────────────────────────────────── */
body.dark-mode {
  --r-bg:          #282c36;
  --r-surface:     #31353f;
  --r-text:        #e8e4d8;
  --r-heading:     #ffffff;
  --r-muted:       #9a96a6;
  --r-accent:      #e0705a;
  --r-accent-dim:  #c05a46;
  --r-border:      #3b3f4c;
  --r-code-bg:     #1f222b;
  --r-code-text:   #abb2bf;
  --r-code-top:    rgba(224, 112, 90, 0.35);
  --r-inline-bg:   rgba(224, 112, 90, 0.12);
  --r-select-bg:   rgba(224, 112, 90, 0.28);
  --r-toggle-bg:   rgba(255, 255, 255, 0.08);
  --r-toggle-fg:   #9a96a6;

  /* highlight.js dark token colours (One Dark palette) */
  --hl-base:       #abb2bf;
  --hl-comment:    #5c6370;
  --hl-keyword:    #c678dd;
  --hl-type:       #4ec9b0;
  --hl-string:     #98c379;
  --hl-number:     #d19a66;
  --hl-function:   #61afef;
  --hl-class:      #e5c07b;
  --hl-variable:   #9cdcfe;
  --hl-attr:       #9cdcfe;
  --hl-operator:   #56b6c2;
  --hl-builtin:    #e06c75;
  --hl-tag:        #e06c75;
  --hl-regexp:     #56b6c2;
}

/* Suppress transitions while restoring saved theme on load */
body.no-transition * { transition: none !important; }

/* ── Viewport & background ─────────────────────────────────── */
body {
  background: var(--r-bg);
  background-color: var(--r-bg);
  transition: background-color 0.25s ease;
}

/* ── Reveal core ───────────────────────────────────────────── */
.reveal {
  font-family: var(--r-font-sans);
  font-size: 38px;
  font-weight: 400;
  color: var(--r-text);
  line-height: 1.5;
  transition: color 0.25s ease;
}

/* ── Text selection ────────────────────────────────────────── */
.reveal ::selection {
  color: var(--r-heading);
  background: var(--r-select-bg);
  text-shadow: none;
}

/* ── Headings ──────────────────────────────────────────────── */
.reveal h1,
.reveal h2,
.reveal h3,
.reveal h4,
.reveal h5,
.reveal h6 {
  margin: 0 0 0.4em 0;
  color: var(--r-heading);
  font-family: var(--r-font-sans);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.01em;
  text-transform: none;
  text-shadow: none;
  word-wrap: break-word;
  transition: color 0.25s ease;
}

.reveal h1 {
  font-size: 1.9em;
  font-weight: 700;
  border-bottom: 3px solid var(--r-accent);
  padding-bottom: 0.18em;
  margin-bottom: 0.5em;
}

.reveal h2 {
  font-size: 1.4em;
  border-bottom: 2px solid var(--r-accent);
  padding-bottom: 0.14em;
  margin-bottom: 0.5em;
}

.reveal h3 {
  font-size: 1.15em;
  color: var(--r-accent);
}

.reveal h4 {
  font-size: 0.95em;
  color: var(--r-muted);
}

.reveal h5,
.reveal h6 {
  font-size: 0.85em;
  font-weight: 400;
  color: var(--r-muted);
  font-style: italic;
}

/* ── Body text ─────────────────────────────────────────────── */
.reveal p {
  margin: 0 0 0.55em;
  line-height: 1.6;
}

.reveal strong { font-weight: 600; color: var(--r-heading); }
.reveal em     { color: var(--r-muted); }

/* ── Links ─────────────────────────────────────────────────── */
.reveal a {
  color: var(--r-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.reveal a:hover {
  color: var(--r-accent-dim);
  border-bottom-color: var(--r-accent-dim);
  text-shadow: none;
}

/* ── Lists ─────────────────────────────────────────────────── */
.reveal ul,
.reveal ol {
  display: block;
  text-align: left;
  margin: 0 0 0.5em 1.4em;
}

.reveal li { margin-bottom: 0.2em; line-height: 1.55; }

.reveal ul           { list-style-type: disc; }
.reveal ul ul        { list-style-type: circle; font-size: 0.95em; }
.reveal ul ul ul     { list-style-type: square; }

.reveal ul ul,
.reveal ul ol,
.reveal ol ul,
.reveal ol ol { margin-top: 0.15em; }

/* ── Blockquote ────────────────────────────────────────────── */
.reveal blockquote {
  display: block;
  position: relative;
  margin: 0.7em auto;
  padding: 0.5em 1em 0.5em 1.3em;
  border-left: 4px solid var(--r-accent);
  background: var(--r-surface);
  border-radius: 0 6px 6px 0;
  font-style: italic;
  color: var(--r-muted);
  box-shadow: none;
  width: 88%;
  text-align: left;
  transition: background 0.25s ease;
}

.reveal blockquote p { margin: 0; }

/* ── Code blocks ───────────────────────────────────────────── */
.reveal pre {
  display: block;
  position: relative;
  margin: 0.5em auto;
  padding: 0;
  text-align: left;
  font-size: 0.68em;
  line-height: 1.5;
  word-wrap: normal;
  background: var(--r-code-bg);
  border: 1px solid var(--r-border);
  border-top: 2px solid var(--r-code-top);
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.07);
  overflow: hidden;
  transition: background 0.25s ease, border-color 0.25s ease;
}

body.dark-mode .reveal pre {
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.4);
}

.reveal pre code {
  display: block;
  padding: 1.2em 1.1em;
  overflow: auto;
  max-height: 430px;
  font-family: var(--r-font-mono);
  font-size: inherit;
  color: var(--r-code-text);
  background: transparent;
  word-wrap: normal;
  tab-size: 2;
  border-radius: 0;
}

.reveal pre.has-lang-label { padding-top: var(--code-label-h); }

.reveal .code-lang-label {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--code-label-h);
  display: flex;
  align-items: center;
  padding: 0 0.75em;
  font-family: var(--r-font-sans);
  font-size: 0.75em;
  font-weight: 600;
  color: var(--r-muted);
  letter-spacing: 0.04em;
  background: rgba(0, 0, 0, 0.03);
  border-bottom: 1px solid var(--r-border);
  border-radius: 6px 6px 0 0;
  box-sizing: border-box;
  pointer-events: none;
  user-select: none;
  transition: color 0.25s ease, background 0.25s ease, border-color 0.25s ease;
}

body.dark-mode .reveal .code-lang-label {
  background: rgba(255, 255, 255, 0.03);
}

/* ── Inline code ───────────────────────────────────────────── */
.reveal code {
  font-family: var(--r-font-mono);
  font-size: 0.84em;
  color: var(--r-accent);
  background: var(--r-inline-bg);
  padding: 0.1em 0.35em;
  border-radius: 4px;
}

.reveal pre code {
  color: var(--r-code-text);
  background: transparent;
  padding: 1.2em 1.1em;
  border-radius: 0;
  font-size: inherit;
}

/* ── Tables ────────────────────────────────────────────────── */
.reveal table {
  margin: 0.5em auto;
  border-collapse: collapse;
  font-size: 0.78em;
  width: auto;
}

.reveal table th {
  font-weight: 600;
  color: var(--r-heading);
  background: rgba(192, 88, 78, 0.07);
  border-bottom: 2px solid rgba(192, 88, 78, 0.2);
  padding: 0.45em 0.8em;
  text-align: left;
  white-space: nowrap;
}

body.dark-mode .reveal table th {
  background: rgba(224, 112, 90, 0.1);
  border-bottom-color: rgba(224, 112, 90, 0.3);
}

.reveal table td {
  padding: 0.4em 0.8em;
  border-bottom: 1px solid var(--r-border);
  color: var(--r-text);
  vertical-align: top;
}

.reveal table tr:last-child td { border-bottom: none; }

.reveal table tbody tr:nth-child(even) {
  background: rgba(192, 88, 78, 0.025);
}

body.dark-mode .reveal table tbody tr:nth-child(even) {
  background: rgba(255, 255, 255, 0.02);
}

/* ── HR ────────────────────────────────────────────────────── */
.reveal hr {
  border: none;
  border-top: 1px solid var(--r-border);
  margin: 0.8em 0;
}

/* ── Images ────────────────────────────────────────────────── */
.reveal section img {
  max-width: 100%;
  max-height: 70vh;
  border: none;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
  border-radius: 6px;
}

body.dark-mode .reveal section img {
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.45);
}

/* ── Progress bar ──────────────────────────────────────────── */
.reveal .progress {
  height: 3px;
  background: var(--r-border);
  color: var(--r-accent);
}

.reveal .progress span {
  background: var(--r-accent);
  transition: width 0.2s ease;
}

/* ── Navigation controls ───────────────────────────────────── */
.reveal .controls {
  color: var(--r-accent);
}

.reveal .controls button {
  color: var(--r-accent);
  opacity: 0.5;
}

.reveal .controls button:hover {
  opacity: 1;
}

/* ── Slide number ──────────────────────────────────────────── */
.reveal .slide-number {
  background: transparent;
  color: var(--r-muted);
  font-size: 0.55em;
  font-family: var(--r-font-sans);
}

/* ── Speaker notes ─────────────────────────────────────────── */
.reveal aside.notes {
  font-size: 0.75em;
  color: var(--r-muted);
}

/* ── Copy-to-clipboard button ──────────────────────────────── */

/* Use overflow: visible so the button isn't clipped by border-radius */
.reveal pre { position: relative; overflow: visible; --code-label-h: 2.2em; }

/* But we still need the code content clipped, so limit overflow on code */
.reveal pre code { border-radius: 5px; }

.code-copy-btn {
  position: absolute;
  top: 0.45rem;
  right: 0.5rem;
  z-index: 10;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 1px solid var(--r-border);
  border-radius: 5px;
  background: var(--r-code-bg);
  color: var(--r-muted);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.2s ease, background 0.15s ease,
              color 0.15s ease, border-color 0.15s ease;
}

.code-copy-btn svg { pointer-events: none; }

/* When a language label bar is present, center the button within it
   so it sits perfectly inline with the label text. */
.reveal pre.has-lang-label .code-copy-btn {
  top: 0;
  height: var(--code-label-h);
}

.reveal pre:hover .code-copy-btn { opacity: 1; }

.code-copy-btn:hover {
  background: var(--r-accent);
  border-color: var(--r-accent);
  color: #fff;
  opacity: 1;
}

.code-copy-btn.copied {
  background: #4caf50;
  border-color: #4caf50;
  color: #fff;
  opacity: 1;
}

/* ── Dark-mode toggle button ───────────────────────────────── */
#theme-toggle {
  position: fixed;
  top: 14px;
  right: 16px;
  z-index: 9999;
  width: 34px;
  height: 34px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--r-toggle-bg);
  color: var(--r-toggle-fg);
  cursor: pointer;
  font-size: 15px;
  line-height: 34px;
  text-align: center;
  opacity: 0.65;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  user-select: none;
  transition: background 0.2s ease, color 0.2s ease,
              opacity 0.2s ease, transform 0.15s ease;
}

#theme-toggle:hover {
  opacity: 1;
  background: var(--r-accent);
  color: #fff;
  transform: scale(1.1);
}

/* Moon shown in light mode → click to go dark */
#theme-toggle::before { content: "☾"; }

/* Sun shown in dark mode → click to go light */
body.dark-mode #theme-toggle::before { content: "☀"; }

/* ── Nav-bar palette tokens ────────────────────────────────── */
body {
  --r-nav-bg:    #f5f3ef;
  --r-nav-title: #1a1a1a;
}

body.dark-mode {
  --r-nav-bg:    #1f222b;
  --r-nav-title: #ffffff;
}

/* ── Header height token ────────────────────────────────────── */
:root { --slide-header-h: 1.9em; }

/* ── Prevent flash of unstyled content on load ────────────── */
.reveal .slides { opacity: 0; transition: opacity 0.3s ease; }

/* ════════════════════════════════════════════════════════════
   All custom layouts: fill the viewport, kill reveal centering
   ════════════════════════════════════════════════════════════ */
.reveal .slides > section.layout-title {
  padding: 1.5em !important;
  height: 100% !important;
  top: 0 !important;
  left: 0 !important;
  display: flex !important;
  flex-direction: column !important;
  justify-content: center !important;
  align-items: center !important;
  text-align: center;
  box-sizing: border-box;
}

.reveal .slides > section.layout-slide,
.reveal .slides > section.layout-graphic {
  padding: 0 !important;
  height: 100% !important;
  top: 0 !important;
  left: 0 !important;
  display: flex !important;
  flex-direction: column !important;
  text-align: left;
  box-sizing: border-box;
}

/* reveal.js hides far-away slides via inline `display: none` for
   performance. The `!important` flex rules above otherwise defeat that,
   keeping every slide in the render tree. Let the inline none win when
   reveal sets it. */
.reveal .slides > section.layout-title[style*="display: none"],
.reveal .slides > section.layout-slide[style*="display: none"],
.reveal .slides > section.layout-graphic[style*="display: none"] {
  display: none !important;
}

/* The actual cause of the overview-exit flash: reveal.css tries to
   suppress the fade-transition crossfade while leaving overview mode by
   applying `transition: none` to `.overview-deactivating .slides section`
   (3 classes + 1 element), but that loses the specificity battle against
   its own `.reveal.fade .slides section:not([data-transition])` rule
   (effectively 4 classes/pseudo-classes + 1 element), which still wins
   and applies its `transition: opacity 0.5s`. So the outgoing slide
   visibly crossfades over the previously-present slide for half a second
   instead of snapping instantly. Force the intended instant snap. */
.reveal.overview-deactivating .slides section {
  transition: none !important;
}

/* ════════════════════════════════════════════════════════════
   layout: title
   ════════════════════════════════════════════════════════════ */
.reveal .title-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1em;
  width: 100%;
}

.reveal section.layout-title h1 {
  font-size: 2.2em;
  font-weight: 700;
  border-bottom: 3px solid var(--r-accent);
  padding-bottom: 0.18em;
  margin-bottom: 0.2em;
  color: var(--r-heading);
}

.reveal .title-subtitle {
  font-size: 1.1em;
  font-weight: 400;
  color: var(--r-muted);
  margin: 0 0 0.4em;
}

.reveal .title-author {
  font-size: 0.82em;
  font-weight: 500;
  margin: 0.3em 0 0.65em;
}

.reveal .title-author-link {
  color: var(--r-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.reveal .title-author-link:hover {
  color: var(--r-accent-dim);
  border-bottom-color: var(--r-accent-dim);
}

.reveal .title-logos {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.6em;
  margin: 0.65em 0;
  flex-wrap: wrap;
}

.reveal .org-logo {
  height: 1.7em;
  width: auto;
  object-fit: contain;
}

.reveal section.layout-title .org-logo {
  border: none;
  box-shadow: none;
  border-radius: 0;
  max-height: none;
}

.cosmostat-dark  { display: none; }
body.dark-mode .cosmostat-light { display: none; }
body.dark-mode .cosmostat-dark  { display: block; }

.reveal .title-footer {
  position: absolute;
  bottom: 1.3em;
  left: 0;
  right: 0;
  text-align: center;
  font-size: 0.6em;
  color: var(--r-muted);
  opacity: 0.75;
  letter-spacing: 0.03em;
  transition: color 0.25s ease;
}

/* ════════════════════════════════════════════════════════════
   layout: slide  /  layout: graphic — header bar
   ════════════════════════════════════════════════════════════ */
.reveal .slide-header {
  flex: 0 0 auto;
  height: var(--slide-header-h);
  padding: 0 3.5em 0 1.5em; /* right pad clears theme-toggle */
  display: flex;
  align-items: center;
  background: var(--r-nav-bg);
  border-bottom: 1px solid var(--r-border);
  box-sizing: border-box;
  transition: background 0.25s ease, border-color 0.25s ease;
}

.reveal .slide-header-title {
  font-size: 1.25em;
  font-weight: 600;
  color: var(--r-nav-title);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: color 0.25s ease;
}

/* ── Slide body ──────────────────────────────────────────────── */
.reveal .slide-body {
  flex: 1 1 auto;
  min-height: 0;
  padding: 2em 6.5em; /* 2.5em × 22.8px ≈ 57px, matching header's 1.5em × 38px */
  overflow-y: auto;
  box-sizing: border-box;
  font-size: 0.7em;
}

/* Full-width layout */
.reveal .slide-body.slide-body-full {
  position: relative;
}

.reveal .slide-body.slide-body-full .bg-graphic {
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  opacity: 0.12;
  pointer-events: none;
}

.reveal .slide-body.slide-body-full .slide-body-inner {
  position: relative;
  z-index: 1;
}

/* h1 in slide body: text-width underline, larger than h2+ but smaller than header title */
.reveal .slide-body h1 {
  font-size: 2em;
  font-weight: 600;
  width: fit-content;
  border-bottom: 2px solid var(--r-accent);
  padding-bottom: 0.1em;
  margin-bottom: 0.4em;
}

/* h2 and below: no border, progressively smaller */
.reveal .slide-body h2 {
  font-size: 1.5em;
  border-bottom: none;
  padding-bottom: 0;
}

.reveal .slide-body h3 {
  font-size: 1.2em;
  border-bottom: none;
  padding-bottom: 0;
}

.reveal .slide-body h4,
.reveal .slide-body h5,
.reveal .slide-body h6 {
  font-size: 0.95em;
  border-bottom: none;
  padding-bottom: 0;
}

/* Split layout */
.reveal .slide-body.slide-body-split {
  display: flex;
  flex-direction: row;
  gap: 0.9em;
  overflow: hidden;
}

.reveal .split-content {
  flex: 1;
  min-width: 0;
  overflow-y: auto;
}

.reveal .split-graphic {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.reveal section.layout-slide .split-graphic img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border: none;
  box-shadow: none;
  border-radius: 6px;
}

/* ════════════════════════════════════════════════════════════
   layout: graphic
   ════════════════════════════════════════════════════════════ */
.reveal .slide-body.slide-body-graphic {
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow: hidden;
}

.reveal .graphic-content {
  display: flex;
  flex-direction: column;
  gap: 3.0em;
  min-height: 0;
  overflow: hidden;
}

.reveal .graphic-grid {
  display: grid;
  grid-auto-rows: auto;
  gap: 0.6em;
  align-items: center;
}

.reveal .graphic-item {
  display: flex;
  align-items: center;
  justify-content: center;
  max-height: 18em;
  overflow: hidden;
}

.reveal section.layout-graphic .graphic-item img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border: none;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

body.dark-mode .reveal section.layout-graphic .graphic-item img {
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.4);
}

.reveal .graphic-caption {
  flex-shrink: 0;
  font-size: 0.8em;
  color: var(--r-muted);
  text-align: center;
  font-style: italic;
  margin: 0;
  padding: 0 0 0.25em;
  transition: color 0.25s ease;
}
