/* ── Mini-Folio: picker + generated deck ──
   Follows the same page-skin convention as about.css/projects.css/play.css:
   dark by default (grain-textured body background + a --ink/--border token
   set scoped to this page), switching to a plain #fefefe light mode via
   body.page-mini-folio.theme-light rather than core.css's light-first vars. */

body.page-mini-folio {
  --bg: #0c0906;
  background-color: var(--bg);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0.3'/%3E%3C/filter%3E%3Crect width='400' height='400' filter='url(%23n)' opacity='0.055'/%3E%3C/svg%3E");
  color: var(--ink);
  min-height: 100vh;
}
body.page-mini-folio:not(.theme-light) {
  --ink: rgba(255,255,255,0.92);
  --ink2: rgba(255,255,255,0.68);
  --muted: rgba(255,255,255,0.4);
  --border: rgba(255,255,255,0.1);
  --bord2: rgba(255,255,255,0.2);
  --bg2: rgba(255,255,255,0.08);
  --bg3: rgba(255,255,255,0.14);
}
body.page-mini-folio.theme-light { --bg: #fefefe; }
body.page-mini-folio.theme-light .nav-back { display: none; }
body.page-mini-folio.theme-light .nav { background: var(--bg) !important; border-color: transparent !important; }
body.page-mini-folio.theme-light .nav-logo { color: rgba(30,28,24,0.88) !important; }
body.page-mini-folio.theme-light .nav-clock,
body.page-mini-folio.theme-light .nav-clock-time { color: rgba(30,28,24,0.35) !important; }
body.page-mini-folio.theme-light .nl { color: var(--muted) !important; }
body.page-mini-folio.theme-light .nl:hover,
body.page-mini-folio.theme-light .nl.on { color: var(--ink) !important; }
body.page-mini-folio.theme-light .nl.nav-name { color: rgba(20,18,14,0.88) !important; }

/* ── Nav right slot (game button + theme toggle) — each page defines this
   itself; core.css only has the mobile override, not the base layout. ── */
.nav-r-cs {
  display: flex;
  align-items: center;
  gap: 16px;
  justify-self: end;
}
body.page-mini-folio .cs-theme-toggle {
  background: none;
  border: 0.5px solid rgba(255,255,255,0.22);
  color: rgba(255,255,255,0.5);
  height: 32px;
  border-radius: 100px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  line-height: 1;
  transition: color 0.2s, border-color 0.2s, background 0.2s;
  padding: 0 12px;
}
body.page-mini-folio .cs-theme-toggle svg {
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s;
  display: block;
}
body.page-mini-folio .cs-theme-toggle:hover {
  color: rgba(255,255,255,0.9);
  border-color: rgba(255,255,255,0.5);
}
body.page-mini-folio .cs-theme-toggle:hover svg { transform: rotate(20deg) scale(1.15); }
@keyframes mf-spin-in {
  from { transform: rotate(-90deg) scale(0.6); opacity: 0; }
  to   { transform: rotate(0deg)  scale(1);   opacity: 1; }
}
body.page-mini-folio .cs-theme-toggle.spin svg { animation: mf-spin-in 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; }

body.page-mini-folio.theme-light .nc {
  color: var(--ink) !important;
  border-color: var(--bord2) !important;
}
body.page-mini-folio.theme-light .nc:hover { background: var(--bg2) !important; color: var(--ink) !important; }
body.page-mini-folio.theme-light .cs-theme-toggle {
  border-color: rgba(30,28,24,0.22);
  color: rgba(30,28,24,0.5);
}
body.page-mini-folio.theme-light .cs-theme-toggle:hover {
  color: rgba(30,28,24,0.9);
  border-color: rgba(30,28,24,0.5);
}

/* ── Password gate ── */
.mf-gate { display: none; }
body.mf-locked .mf-gate { display: flex; }
body.mf-locked .mf-wrap,
body.mf-locked .mf-tray,
body.mf-locked .mf-deck,
body.mf-locked .site-footer { display: none !important; }
.mf-gate {
  align-items: center; justify-content: center; min-height: calc(100vh - 72px);
  padding: 24px;
}
.mf-gate-box { max-width: 360px; width: 100%; text-align: center; }
.mf-gate-box .mf-jd-textarea {
  text-align: center; margin-bottom: 14px; padding: 12px 16px;
}
.mf-gate-box .mf-jd-actions { justify-content: center; }

.mf-wrap { max-width: 1180px; margin: 0 auto; padding: 56px 56px 32px; }

.mf-head { max-width: 640px; margin-bottom: 40px; }
.mf-eyebrow {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--rose); margin-bottom: 12px;
}
.mf-title {
  font-family: var(--serif); font-weight: 300; font-size: clamp(34px, 5vw, 56px);
  letter-spacing: -0.02em; line-height: 1.05; color: var(--ink); margin: 0 0 16px;
}
.mf-title em { font-style: normal; font-weight: inherit; color: inherit; }
.mf-sub { font-family: var(--mono); font-size: 13px; line-height: 1.7; color: var(--ink2); }

/* JD box — bento-card recipe (about.css .bento-card) */
.mf-jd-box {
  background: var(--bg); border: 1px solid var(--border); border-radius: 22px; padding: 28px;
  margin-bottom: 40px;
}
body.page-mini-folio.theme-light .mf-jd-box { background: rgba(255,255,255,0.55); }
.mf-jd-label {
  display: block; font-family: var(--mono); font-size: 10px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 12px;
}
.mf-jd-textarea {
  width: 100%; min-height: 110px; resize: vertical; box-sizing: border-box;
  font-family: var(--mono); font-size: 13px; line-height: 1.6; color: var(--ink);
  background: var(--bg2); border: 1px solid var(--border); border-radius: 12px;
  padding: 14px 16px;
}
.mf-jd-textarea::placeholder { color: var(--muted); }
.mf-jd-actions { display: flex; align-items: center; gap: 16px; margin-top: 14px; flex-wrap: wrap; }
.mf-jd-status { font-family: var(--mono); font-size: 11.5px; color: var(--ink2); }
.mf-jd-status.mf-error { color: var(--rose); }

/* Buttons — .sf-cta-btn recipe for the primary action, .bc-bio-action-btn
   recipe (bordered, transparent) for everything secondary. */
.mf-btn-primary {
  font-family: var(--serif); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  background: rgba(255,255,255,0.92); color: #0c0906; border: 0.5px solid rgba(255,255,255,0.92);
  border-radius: 24px; padding: 12px 24px; cursor: pointer; transition: background 0.2s ease;
}
.mf-btn-primary:hover { background: #fff; }
.mf-btn-primary:disabled { opacity: 0.35; cursor: not-allowed; }
body.page-mini-folio.theme-light .mf-btn-primary {
  background: var(--ink); color: var(--bg); border-color: var(--ink);
}
body.page-mini-folio.theme-light .mf-btn-primary:hover { background: rgba(30,28,24,0.85); }
.mf-btn-secondary {
  background: none; color: rgba(255,255,255,0.92); border-color: rgba(255,255,255,0.35);
}
.mf-btn-secondary:hover { background: rgba(255,255,255,0.08); }
body.page-mini-folio.theme-light .mf-btn-secondary {
  background: none; color: var(--ink); border-color: var(--bord2);
}
body.page-mini-folio.theme-light .mf-btn-secondary:hover { background: var(--bg2); }

/* Picker grid — mcard recipe (assets/css/cards.css .mcard) */
.mf-picker-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px; margin-bottom: 140px;
}
.mf-card {
  position: relative; border-radius: 12px; overflow: hidden; cursor: pointer;
  aspect-ratio: 4/3; background: var(--bg2); border: 2px solid transparent;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.mf-card:hover { transform: translateY(-2px); }
.mf-card.selected { border-color: var(--rose); }
.mf-card-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.mf-card-overlay {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,0.78) 100%);
}
.mf-card-check {
  position: absolute; top: 10px; right: 10px; width: 24px; height: 24px; border-radius: 50%;
  background: rgba(255,255,255,0.18); border: 1.5px solid rgba(255,255,255,0.7);
  display: flex; align-items: center; justify-content: center; color: #fff; font-size: 13px;
}
.mf-card.selected .mf-card-check { background: var(--rose); border-color: var(--rose); }
.mf-card-order {
  position: absolute; top: 8px; left: 10px; font-family: var(--mono); font-size: 11px;
  color: #fff; background: var(--rose); border-radius: 50%; width: 20px; height: 20px;
  display: none; align-items: center; justify-content: center;
}
.mf-card.selected .mf-card-order { display: flex; }
.mf-card-content { position: absolute; left: 13px; right: 13px; bottom: 11px; }
.mf-card-tag {
  font-family: var(--mono); font-size: 8.5px; letter-spacing: 0.18em; text-transform: uppercase;
  color: rgba(255,255,255,0.68); margin-bottom: 5px;
}
.mf-card-name { font-family: var(--serif); font-size: 16px; font-weight: 200; color: #fff; line-height: 1.2; }
.mf-card-name em { font-style: normal; font-weight: 400; }
.mf-card.mf-suggested::before {
  content: 'Suggested'; position: absolute; top: 10px; left: 10px; z-index: 2;
  font-family: var(--mono); font-size: 8px; letter-spacing: 0.08em; text-transform: uppercase;
  color: #fff; background: var(--rose); padding: 3px 7px; border-radius: 10px;
}
.mf-card.mf-suggested.selected::before { left: 38px; }

/* Selection tray (sticky bottom bar) */
.mf-tray {
  position: sticky; bottom: 0; z-index: 20; background: var(--bg);
  border-top: 1px solid var(--border); padding: 16px 56px; max-width: 1180px; margin: 0 auto;
}
.mf-tray-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 10px; }
#mf-tray-count { font-family: var(--mono); font-size: 11.5px; font-weight: 500; color: var(--ink); text-transform: uppercase; letter-spacing: 0.06em; }
.mf-tray-hint { font-family: var(--mono); font-size: 10.5px; color: var(--muted); }
.mf-tray-list { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; min-height: 0; }
.mf-tray-chip {
  display: inline-flex; align-items: center; gap: 6px; background: var(--bg2);
  border: 1px solid var(--border); border-radius: 20px; padding: 5px 6px 5px 12px;
  font-family: var(--mono); font-size: 11.5px; color: var(--ink);
}
.mf-tray-chip button {
  border: none; background: transparent; cursor: pointer; width: 20px; height: 20px; line-height: 1;
  color: var(--ink2); border-radius: 50%; font-size: 12px;
}
.mf-tray-chip button:hover { background: var(--bg3); color: var(--ink); }
.mf-generate { width: 100%; }

/* ── Deck ── */
.mf-deck { background: var(--bg); min-height: 100vh; }
.mf-deck-controls {
  position: sticky; top: 0; z-index: 30; display: flex; align-items: center; justify-content: space-between;
  gap: 16px; padding: 14px 24px; background: rgba(12,10,8,0.85); backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border); flex-wrap: wrap;
}
body.page-mini-folio.theme-light .mf-deck-controls { background: rgba(254,254,254,0.85); }
.mf-deck-btn {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.04em; color: var(--ink2);
  background: var(--bg2); border: 1px solid var(--border); border-radius: 20px; padding: 8px 16px; cursor: pointer;
}
.mf-deck-btn:hover { border-color: var(--rose); color: var(--rose); }
.mf-deck-nav { display: flex; align-items: center; gap: 10px; }
.mf-deck-counter { font-family: var(--mono); font-size: 11.5px; color: var(--muted); min-width: 46px; text-align: center; }
.mf-deck-hint { font-family: var(--mono); font-size: 10.5px; color: rgba(255,255,255,0.4); }
@media (max-width: 760px) { .mf-deck-hint { display: none; } }

.mf-slides { max-width: 1000px; margin: 0 auto; padding: 40px 24px 100px; }
/* Every slide is a fixed 16:9 widescreen rectangle (matching the physical
   13.333in x 7.5in page below) both on screen and when printed - see the
   @page rule further down. No slide type is allowed to override this
   aspect-ratio or let its content overflow the box; that used to be the
   "horizontal layout" escape hatch (aspect-ratio:auto + overflow:visible),
   which was exactly why some slides previewed as a tall stretched shape
   instead of the rectangle they'll actually print as. */
.mf-slide {
  display: none; width: 100%; aspect-ratio: 16/9; min-height: 560px;
  border-radius: 0; overflow: hidden; background: #fff; color: #1e1c18;
  box-shadow: 0 30px 80px rgba(0,0,0,0.4);
  position: relative;
}
.mf-slide.mf-active { display: flex; flex-direction: column; }
/* Same fine-grain noise texture used on the homepage nav/hero/content-wrap
   (assets/css/home.css), applied here at the light-mode blend/opacity since
   the deck is forced to theme-light regardless of site theme. */
.mf-slide::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0.3'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='gamma' amplitude='1' exponent='0.5' offset='0'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.3'/%3E%3C/svg%3E"),
    radial-gradient(ellipse at 15% 50%, rgba(196,168,122,0.55) 0%, transparent 60%),
    radial-gradient(ellipse at 82% 18%, rgba(188,158,110,0.35) 0%, transparent 50%);
  background-size: 180px 180px, auto, auto;
  background-blend-mode: normal;
  opacity: 0.14;
}
.mf-slide > * { position: relative; z-index: 1; }

/* Cover slide */
.mf-slide-cover {
  align-items: flex-start; justify-content: center; padding: 64px; background: #fff; color: #1e1c18;
}
/* Eyebrow pill + "Selected work." share one row, width set by JS to match
   .mf-cover-name's own rendered width (see alignCoverHeadRow()) so the
   right-aligned role text lines up exactly with the name's right edge
   below it rather than the slide's own padding edge. */
.mf-cover-head-row { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 14px; }
/* Same recipe as .mf-proj-link ("View full case study") — serif, uppercase,
   bordered pill — instead of a plain mono label. */
.mf-cover-eyebrow {
  display: inline-flex; flex-shrink: 0;
  font-family: var(--serif); font-size: 10px; letter-spacing: 0.03em; text-transform: uppercase;
  color: #211a13; border: 1px solid rgba(33,26,19,0.18); border-radius: 20px;
  padding: 5px 11px;
}
.mf-cover-name { font-family: var(--serif); font-weight: 300; font-size: clamp(22px, 3.1vw, 34px); line-height: 1.05; letter-spacing: -0.03em; margin-bottom: 8px; color: #211a13; }
/* Left edge matches .mf-cover-logo's own inset (40px) rather than the
   slide's 64px content padding. */
.mf-cover-head-row, .mf-cover-name { margin-left: -24px; }
.mf-cover-role { font-family: var(--mono); font-style: normal; font-size: 11px; color: rgba(30,28,24,0.55); white-space: nowrap; }
/* Faded dot-grid arc in the top-right corner, same recipe as the homepage
   hero image's grid (home.css .hn-hero-img::before) — radially masked so
   it fades out toward the slide's center/left. */
.mf-cover-grid-accent {
  position: absolute; top: 0; right: 0; width: 85%; height: 105%;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(30,28,24,0.22) 1px, transparent 1px),
    linear-gradient(90deg, rgba(30,28,24,0.22) 1px, transparent 1px);
  background-size: 32px 32px;
  -webkit-mask-image: radial-gradient(ellipse 130% 55% at 100% 0%, #000 0%, transparent 80%);
  mask-image: radial-gradient(ellipse 130% 55% at 100% 0%, #000 0%, transparent 80%);
}
/* Light strip behind the logo/date/email row — reads like a nav bar, but
   it's just a decorative band on the slide itself, not a real nav. */
.mf-cover-topbar {
  position: absolute; top: 0; left: 0; right: 0; height: 96px;
  background: #fefdfb; border-bottom: 1px solid rgba(30,28,24,0.08);
  z-index: 1;
}
.mf-cover-meta {
  position: absolute; top: 27px; right: 40px; text-align: right;
  font-family: var(--serif); font-size: 11px; letter-spacing: 0.03em; color: rgba(30,28,24,0.38); line-height: 1.6;
  z-index: 1;
}
.mf-cover-meta-date { text-transform: uppercase; }
.mf-cover-logo { position: absolute; top: 31px; left: 40px; height: 34px; width: auto; filter: brightness(0); opacity: 0.55; z-index: 1; }
/* Bottom-third strip of the selected projects' hero photos — same treatment
   on the Closing slide so the deck is visually bookended. */
.mf-cover-strip {
  position: absolute; left: 0; right: 0; bottom: 0; height: 33.33%; display: flex; gap: 4px;
}
.mf-cover-strip img { flex: 1; min-width: 0; width: 100%; height: 100%; object-fit: cover; display: block; }

/* About + Skills slide */
.mf-slide-about {
  align-items: stretch; justify-content: flex-start; padding: 0;
  background: #fefdfb; color: #1e1c18; position: relative;
}
/* Same light strip treatment as .mf-cover-topbar on the cover slide. */
.mf-about-topbar {
  position: relative; z-index: 2; flex-shrink: 0;
  height: 96px; padding: 0 56px;
  background: #3a5c9c; border-bottom: 1px solid rgba(30,28,24,0.08);
  display: flex; align-items: center; justify-content: space-between;
}
.mf-about-topbar .mf-about-eyebrow { color: #fff; border-color: rgba(255,255,255,0.35); }
.mf-about-topbar .mf-about-resume-btn { color: rgba(255,255,255,0.85); }
.mf-about-topbar .mf-about-resume-btn:hover { color: #fff; }
.mf-about-topbar .mf-about-email { color: rgba(255,255,255,0.7); }
/* Decorative full-width banner starting just above the name and running
   down behind the skill cards — the skill cards (z-index:2 via
   .mf-about-body) sit visually on top of it. */
/* Same faded dot-grid accent as the cover slide's top-right corner, mirrored
   into the bottom-right corner here. */
.mf-about-grid-accent {
  position: absolute; bottom: 0; right: 0; width: 65%; height: 65%;
  pointer-events: none; z-index: 1;
  background-image:
    linear-gradient(rgba(30,28,24,0.22) 1px, transparent 1px),
    linear-gradient(90deg, rgba(30,28,24,0.22) 1px, transparent 1px);
  background-size: 32px 32px;
  -webkit-mask-image: radial-gradient(ellipse 95% 95% at 100% 100%, #000 0%, transparent 80%);
  mask-image: radial-gradient(ellipse 95% 95% at 100% 100%, #000 0%, transparent 80%);
}
.mf-about-banner {
  position: absolute; left: 0; right: 0; top: 96px; height: 180px;
  background: url("/public/images/mini-folio-about-banner.jpg") center 25% / cover no-repeat;
  border-top: 1px solid rgba(196,104,122,0.22);
  border-bottom: 1px solid rgba(196,104,122,0.22);
  z-index: 1;
}
.mf-about-eyebrow {
  display: inline-flex; flex-shrink: 0;
  font-family: var(--serif); font-size: 9px; letter-spacing: 0.03em; text-transform: uppercase;
  color: #211a13; border: 1px solid rgba(33,26,19,0.18); border-radius: 20px;
  padding: 5px 10px; margin-bottom: 0;
}
.mf-about-body {
  position: relative; z-index: 2;
  flex: 1; display: flex; gap: 56px; padding: 48px 56px 56px; min-height: 0;
}
.mf-about-col { min-width: 0; }
.mf-about-col-left { flex: 0 0 34%; display: flex; flex-direction: column; justify-content: flex-end; margin-bottom: 16px; }
.mf-about-col-right { flex: 1; display: flex; flex-direction: column; justify-content: flex-end; }
.mf-about-name { font-family: var(--serif); font-weight: 300; font-size: 32px; line-height: 1.05; margin-bottom: 16px; }
.mf-about-bio { font-family: var(--serif); font-size: 13px; line-height: 1.55; color: rgba(30,28,24,0.68); margin-bottom: 0; }
.mf-about-bio-line { display: block; }
.mf-about-bio-line + .mf-about-bio-line { margin-top: 12px; }
.mf-about-actions {
  display: flex; align-items: center; gap: 14px;
}
/* Same recipe as the site nav's light-mode Resume pill (core.css .nc + the
   body.page-mini-folio.theme-light .nc override). */
.mf-about-resume-btn {
  font-family: var(--serif); font-size: 11px; letter-spacing: 0.03em; text-transform: uppercase;
  color: rgba(30,28,24,0.38); background: transparent; border: none;
  border-radius: 0; padding: 0; text-decoration: none; transition: color 0.2s;
}
.mf-about-resume-btn:hover { color: rgba(30,28,24,0.6); }
.mf-about-email { font-family: var(--serif); font-size: 11px; letter-spacing: 0.03em; color: rgba(30,28,24,0.38); }
.mf-about-skills-label { font-family: var(--mono); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: rgba(30,28,24,0.4); margin-bottom: 16px; }
.mf-skill-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; flex: 0 0 auto; align-content: start; width: 100%; }
.mf-skill-card { border: 1px solid rgba(30,28,24,0.14); border-radius: 6px; padding: 16px 18px; background: #fff; }
.mf-skill-name { font-family: var(--serif); font-size: 16px; font-weight: 400; color: #1e1c18; margin-bottom: 6px; }
.mf-skill-just { font-family: var(--serif); font-size: 11px; line-height: 1.4; color: rgba(30,28,24,0.6); margin-bottom: 10px; }
/* Numbers/stat-like tokens get bolded+underlined (highlightRelevant() in
   mini-folio.js) so the words a recruiter's eye skims for stand out from
   the surrounding muted prose instead of reading as one flat sentence. */
.mf-skill-just strong { font-weight: 700; color: #1e1c18; }
.mf-skill-just strong u { text-decoration-color: var(--rose); text-underline-offset: 2px; }
.mf-skill-source {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--rose); border: 1px solid rgba(196,104,122,0.4); border-radius: 12px; padding: 3px 10px;
}

/* TOC slide */
.mf-slide-toc {
  align-items: stretch; justify-content: flex-start; padding: 0;
  background: #fefdfb; color: #1e1c18; position: relative;
}
/* Same light strip treatment as the cover/about topbars. */
.mf-toc-topbar {
  position: relative; z-index: 2; flex-shrink: 0;
  height: 96px; padding: 0 56px;
  background: #fefdfb; border-bottom: 1px solid rgba(30,28,24,0.08);
  display: flex; align-items: center; justify-content: space-between;
}
.mf-toc-eyebrow {
  display: inline-flex; flex-shrink: 0;
  font-family: var(--serif); font-size: 9px; letter-spacing: 0.03em; text-transform: uppercase;
  color: #211a13; border: 1px solid rgba(33,26,19,0.18); border-radius: 20px;
  padding: 5px 10px;
}
.mf-toc-count { font-family: var(--serif); font-size: 11px; letter-spacing: 0.03em; color: rgba(30,28,24,0.38); }
.mf-toc-list {
  position: relative; z-index: 2;
  flex: 1; display: flex; flex-direction: column; justify-content: center;
  list-style: none; margin: 0; padding: 40px 56px 56px;
}
.mf-toc-item { display: flex; align-items: baseline; gap: 20px; padding: 16px 0; border-bottom: 0.5px solid rgba(30,28,24,0.12); }
.mf-toc-num { font-family: var(--mono); font-size: 13px; color: rgba(30,28,24,0.4); width: 24px; }
.mf-toc-name { font-family: var(--serif); font-weight: 300; font-size: 18px; flex: 1; color: #211a13; }
.mf-toc-tag {
  display: inline-flex; flex-shrink: 0;
  font-family: var(--serif); font-size: 9px; letter-spacing: 0.03em; text-transform: uppercase;
  border: 1px solid; border-radius: 20px; padding: 5px 10px;
}

/* Project slide — selector deliberately repeats .mf-slide (not just
   .mf-slide-project) to match .mf-slide.mf-active's specificity (two class
   selectors each). .mf-slide.mf-active sets flex-direction:column as the
   generic base for every slide type; a lone-class .mf-slide-project rule
   can never out-specificity that two-class rule regardless of source
   order, so the "Vertical" (row) layout was silently losing every time a
   project slide became active - this is the real root cause behind the
   "vertical layout doesn't work" reports, not caching or a media query. */
.mf-slide.mf-slide-project { flex-direction: row; position: relative; }
.mf-proj-media { flex: 0 0 42%; position: relative; overflow: hidden; }
/* Per-project layout toggle — sits as a small toolbar below the slide card
   itself (not overlaid on top of the artwork), matching whichever project
   slide is currently active via the adjacent-sibling selector below. Each
   project remembers its own choice, independent of every other slide. */
.mf-slide-layout-toggle { display: none; justify-content: flex-end; gap: 6px; margin-top: 10px; }
.mf-slide.mf-active + .mf-slide-layout-toggle { display: flex; }
.mf-slide-layout-btn {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.04em; text-transform: uppercase;
  color: #fff; background: rgba(0,0,0,0.55); border: 1px solid rgba(255,255,255,0.4);
  border-radius: 16px; padding: 6px 12px; cursor: pointer; transition: background 0.15s, border-color 0.15s;
}
.mf-slide-layout-btn:hover { background: rgba(0,0,0,0.75); border-color: #fff; }
.mf-slide-layout-btn.active { background: var(--rose); border-color: var(--rose); }
/* Horizontal (image on top, stacked) — selectable per project at any screen
   width. Stays inside the same fixed-ratio slide rectangle as every other
   slide (no aspect-ratio/overflow override); the image band is shorter than
   vertical mode's and .mf-proj-body scrolls internally on screen (see
   below) if a full CST block + stats row would otherwise run past the
   bottom of the page, rather than growing the slide taller than one PDF
   page. */
/* Horizontal mode gives the body a shorter band to work with than vertical
   mode does (the top ~1/4 of the slide is the photo), so the CST block +
   stats row was cramming/scrolling instead of just fitting - shrinking the
   photo band and every text element's own size/spacing here (vertical mode
   is untouched) gives the stats row room to sit normally instead of
   getting squeezed against the bottom edge. */
.mf-slide-project.mf-layout-horizontal { flex-direction: column; }
/* Title + tags move up into a solid accent-colored strip (same 96px "nav"
   footprint as the cover/about topbars) when a project slide is in
   horizontal mode, instead of sitting in the body under the photo. */
.mf-proj-topbar {
  flex-shrink: 0; height: 96px; padding: 0 40px;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  overflow: hidden;
}
.mf-proj-topbar-left { display: flex; align-items: center; gap: 14px; min-width: 0; flex: 1; }
.mf-proj-logo-topbar { max-height: 28px; max-width: 120px; object-fit: contain; object-position: left center; display: block; flex-shrink: 0; }
.mf-slide-project.mf-layout-horizontal .mf-proj-title-topbar { font-size: clamp(18px, 2.2vw, 26px); margin-bottom: 0; margin-top: 10px; color: #fff; min-width: 0; text-align: left; }
.mf-proj-tags-topbar { justify-content: flex-end; flex-shrink: 0; }
.mf-proj-tags-topbar .mf-proj-tag { color: #fff; }
.mf-proj-head-row-logo-only { justify-content: flex-start; }

/* Vertical mode: same accent-colored treatment as the horizontal topbar,
   but bleeding across just the top of the text column (head-row + title)
   so the rest of the column (meta/CST/stats) stays on the normal
   neutral/white background below it. */
.mf-slide-project:not(.mf-layout-horizontal) .mf-proj-head-block {
  margin: -44px -48px 20px; padding: 32px 48px 24px;
}
.mf-slide-project:not(.mf-layout-horizontal) .mf-proj-head-block .mf-proj-title { color: #fff; margin-bottom: 0; font-size: clamp(22px, 2.6vw, 30px); }
.mf-slide-project:not(.mf-layout-horizontal) .mf-proj-head-block .mf-proj-logo { max-height: 44px; max-width: 180px; }
.mf-slide-project:not(.mf-layout-horizontal) .mf-proj-head-block .mf-proj-tag { color: #fff; background: rgba(255,255,255,0.22) !important; }
.mf-slide-project:not(.mf-layout-horizontal) .mf-proj-head-block .mf-proj-head-row { margin-bottom: 14px; }
/* CST sits centered in the leftover space between the meta row above and
   the stats row below, instead of stacking immediately under meta with
   fixed spacing - meta-cst-row becomes the flexible column that fills the
   body's remaining height (mirrors horizontal mode's analogous row). */
.mf-slide-project:not(.mf-layout-horizontal) .mf-proj-meta-cst-row { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.mf-slide-project:not(.mf-layout-horizontal) .mf-proj-meta { margin-bottom: 0; margin-top: 20px; }
.mf-slide-project:not(.mf-layout-horizontal) .mf-proj-cst-col { flex: 1; display: flex; flex-direction: column; justify-content: center; min-height: 0; }
.mf-slide-project.mf-layout-horizontal .mf-proj-media { flex: 0 0 32%; border-radius: 0; }
.mf-slide-project.mf-layout-horizontal .mf-proj-body { padding: 50px 40px 22px; }
.mf-slide-project.mf-layout-horizontal .mf-proj-head-row { margin-bottom: 10px; }
.mf-slide-project.mf-layout-horizontal .mf-proj-title { font-size: clamp(18px, 2.2vw, 26px); margin-bottom: 8px; }
/* Base .mf-proj-meta-col is flex:1, spreading Role/Client/Scale/Year evenly
   across the row's full width - fine in vertical mode where there's usually
   4 columns to fill it, but with only 1-2 present (common in horizontal's
   narrower body) that stretches them apart with a big empty gap between
   instead of sitting together. Switch to natural width + a fixed gap so
   they hug the left edge regardless of column count. */
/* Meta (Role/Client/Scale/Year) sits in a narrow left column, CST/blurb in
   a wider right column, instead of both stacking full-width top to bottom. */
.mf-slide-project.mf-layout-horizontal .mf-proj-meta-cst-row { display: flex; gap: 24px; align-items: stretch; flex: 1; min-height: 0; }
.mf-slide-project.mf-layout-horizontal .mf-proj-meta {
  flex: 0 0 120px; margin-bottom: 0; gap: 16px;
  display: flex; flex-direction: column;
  border-right: 1px solid rgba(30,28,24,0.1); padding-right: 20px;
}
.mf-slide-project.mf-layout-horizontal .mf-proj-meta-col { flex: 0 0 auto; }
.mf-slide-project.mf-layout-horizontal .mf-proj-cst-col { flex: 1; display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.mf-slide-project.mf-layout-horizontal .mf-proj-cst { justify-content: flex-start; flex: 0 0 auto; gap: 6px; margin-bottom: 0; }
.mf-slide-project.mf-layout-horizontal .mf-proj-blurb { flex: 0 0 auto; margin-bottom: 0; }
.mf-slide-project.mf-layout-horizontal .mf-cst-text { font-size: 12.5px; line-height: 1.4; }
.mf-slide-project.mf-layout-horizontal .mf-proj-stats { margin-top: auto; }
.mf-slide-project.mf-layout-horizontal .mf-stat { padding: 14px 10px; }
.mf-slide-project.mf-layout-horizontal .mf-stat-n { font-size: 18px; margin-bottom: 2px; }
.mf-slide-project.mf-layout-horizontal .mf-stat-l { font-size: 9px; }
.mf-slide-project.mf-layout-horizontal .mf-proj-link { align-self: flex-end; margin-top: auto; }
.mf-proj-media img { width: 100%; height: 100%; object-fit: cover; }
.mf-proj-body { flex: 1; min-height: 0; padding: 44px 48px; display: flex; flex-direction: column; }
/* Screen-only escape valve: content that's too long to fit the fixed page
   rectangle scrolls inside the body instead of the slide growing past its
   PDF-page proportions. In print there is no scrolling - anything past the
   page edge is clipped, which is the intended "never extends past one
   standard page" behavior. */
@media screen { .mf-proj-body { overflow-y: auto; } }
/* Logo + tag pills always share the same horizontal center line, however
   tall either one ends up being, instead of both just sitting flush to
   the top. */
.mf-proj-head-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 18px; }
.mf-proj-logo { max-height: 32px; max-width: 140px; object-fit: contain; object-position: left center; display: block; }
/* Each category ("Experience Design", "Brand", ...) is its own pill instead
   of one pill with the categories joined by middots. */
/* nowrap + min-width:0 lets this actually shrink as a flex item of
   .mf-proj-head-row (a wrapping flex child otherwise tends toward its
   max-content width instead of shrinking) - fitTagsRow() in mini-folio.js
   then drops trailing pills if it still doesn't fit, rather than letting
   them silently run off the edge. */
.mf-proj-tags { display: flex; flex-wrap: nowrap; justify-content: flex-end; gap: 6px; min-width: 0; overflow: hidden; }
.mf-proj-tag {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
  color: #fff; flex-shrink: 0; white-space: nowrap; padding: 5px 12px; border-radius: 16px;
}
.mf-proj-title { font-family: var(--serif); font-weight: 300; font-size: clamp(26px, 3vw, 36px); line-height: 1.08; margin-bottom: 16px; }
.mf-proj-meta { display: flex; gap: 14px; margin-bottom: 18px; }
.mf-proj-meta-col { flex: 1; min-width: 0; }
.mf-proj-meta-label { font-family: var(--mono); font-size: 9px; letter-spacing: 0.08em; text-transform: uppercase; color: rgba(30,28,24,0.4); margin-bottom: 4px; }
/* Matches .mf-cst-text / body prose (serif, not mono) — color/weight reverted
   back to plain gray, not accent-tinted or bolded. */
.mf-proj-meta-item { font-family: var(--serif); font-size: 13px; color: rgba(30,28,24,0.68); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mf-proj-blurb { font-family: var(--serif); font-size: 15px; line-height: 1.55; color: rgba(30,28,24,0.68); flex: 1; }

/* Condensed Challenge/Strategy/Solution — same idea as the real case-study
   CST block (fabric-gsm/fabric-name), compressed to fit a slide. */
/* Vertical mode: center the CST block in the space between the heading
   section above and the stats row below, instead of top-aligning it
   (horizontal mode keeps top-aligned — see the override above). */
.mf-proj-cst { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 10px; }
.mf-cst-row { display: flex; gap: 10px; align-items: baseline; }
/* Generic gray now (not the project accent) — the accent color moved to
   the Role/Client/Scale/Year meta row instead, so CST reads as calmer
   supporting copy, just bolder to still hold its own. */
.mf-cst-label {
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 700; flex: 0 0 64px; color: rgba(30,28,24,0.45);
}
.mf-cst-text { font-family: var(--serif); font-weight: 400; font-size: 12px; line-height: 1.42; color: rgba(30,28,24,0.7); }
/* Matches the real case-study stats box (case-study.css .stats/.stat/.stat-n/
   .stat-l) — bordered row, centered cells, divider between them — except
   .stat-n keeps the project's accent color here instead of plain ink, and
   keeps the green trend arrow, neither of which exist on the real pages. */
.mf-proj-stats {
  display: flex; margin-top: auto; border: 0.5px solid rgba(30,28,24,0.15);
  border-radius: 8px; overflow: hidden;
}
.mf-stat { flex: 1; padding: 16px 10px; text-align: center; border-right: 0.5px solid rgba(30,28,24,0.15); }
.mf-stat:last-child { border-right: none; }
.mf-stat-n {
  font-family: var(--serif); font-size: 24px; font-weight: 700; letter-spacing: -0.02em;
  line-height: 1; margin-bottom: 5px; display: flex; align-items: baseline; justify-content: center; gap: 4px;
}
.mf-stat-l { font-family: var(--serif); font-size: 10px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: rgba(30,28,24,0.4); line-height: 1.5; }
/* Growth-stat triangle - overrides the accent color it'd otherwise inherit
   from the parent .mf-stat-n (set via inline style per-project) with a
   fixed green regardless of accent. Now an inline SVG (see mini-folio.js)
   rather than a "▲" glyph, since a plain character can't take rounded
   corners - flex-shrink:0 keeps it from squishing next to the number, and
   align-self:center corrects for .mf-stat-n's align-items:baseline (which
   has no sensible meaning for an SVG, unlike the text next to it). */
.mf-stat-trend { color: #2f9e44 !important; flex-shrink: 0; align-self: center; }
.mf-proj-link {
  display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; margin-top: 20px;
  font-family: var(--serif); font-size: 10px; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase;
  text-decoration: none; color: rgba(30,28,24,0.85); border: 1px solid rgba(30,28,24,0.18);
  border-radius: 20px; padding: 9px 18px; transition: border-color 0.2s, color 0.2s;
}
.mf-proj-link:hover { border-color: var(--rose); color: var(--rose); }

/* Photo swap — button overlaid on the frame, panel is a fixed overlay so the
   frame's own size/crop (object-fit: cover) never changes, only its src. */
.mf-swap-btn {
  position: absolute; bottom: 12px; right: 12px; z-index: 2;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.06em; text-transform: uppercase;
  color: #fff; background: rgba(0,0,0,0.55); border: 1px solid rgba(255,255,255,0.4);
  border-radius: 16px; padding: 6px 12px; cursor: pointer; opacity: 0; transition: opacity 0.15s ease;
}
.mf-proj-media:hover .mf-swap-btn { opacity: 1; }
.mf-swap-btn:hover { background: rgba(0,0,0,0.75); border-color: #fff; }

.mf-swap-overlay {
  display: none; position: fixed; inset: 0; z-index: 100; background: rgba(0,0,0,0.75);
  align-items: center; justify-content: center; padding: 32px;
}
.mf-swap-overlay.open { display: flex; }
.mf-swap-panel {
  background: #1a1714; border-radius: 16px; padding: 24px; max-width: 720px; width: 100%;
  max-height: 80vh; display: flex; flex-direction: column;
}
.mf-swap-head {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px;
  font-family: var(--mono); font-size: 12px; letter-spacing: 0.04em; color: rgba(255,255,255,0.85);
}
.mf-swap-close {
  background: none; border: none; color: rgba(255,255,255,0.6); font-size: 20px; line-height: 1;
  cursor: pointer; padding: 0 4px;
}
.mf-swap-close:hover { color: #fff; }
.mf-swap-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 10px;
  overflow-y: auto; padding-right: 4px;
}
.mf-swap-thumb {
  padding: 0; border: 2px solid transparent; border-radius: 8px; overflow: hidden;
  aspect-ratio: 4/3; cursor: pointer; background: rgba(255,255,255,0.06);
}
.mf-swap-thumb:hover { border-color: var(--rose); }
.mf-swap-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Closing slide — restyled to bookend the cover: same logo/meta corner
   placement (via the shared .mf-cover-logo/.mf-cover-meta/.mf-cover-strip
   classes), same name-style serif treatment, same mono sub-line. */
.mf-slide-closing { align-items: flex-start; justify-content: flex-start; text-align: left; padding: 64px; padding-right: 38%; background: #fefdfb; }
/* Photos stack in a right-hand column instead of a horizontal strip along
   the bottom, with the text block confined to the left via the slide's own
   padding-right above. */
.mf-slide-closing .mf-cover-strip {
  top: 96px; bottom: 0; left: auto; right: 0; height: auto; width: 34%;
  flex-direction: column;
}
/* Mirrors .mf-cover-grid-accent but flipped into the bottom-left corner,
   bookending the cover slide's top-right one. */
.mf-closing-grid-accent { top: auto; right: auto; bottom: 0; left: 0; -webkit-mask-image: radial-gradient(ellipse 130% 55% at 0% 100%, #000 0%, transparent 80%); mask-image: radial-gradient(ellipse 130% 55% at 0% 100%, #000 0%, transparent 80%); }
/* Matches .mf-cover-head-row/.mf-cover-name's own -24px offset (aligning to
   the logo's 40px inset rather than the slide's 64px padding) - without
   this, the "Thank You" pill (which reuses .mf-cover-head-row) sits 24px
   left of the title/sub/links below it. */
.mf-closing-title, .mf-closing-sub, .mf-closing-actions { margin-left: -24px; }
.mf-closing-title { font-family: var(--serif); font-weight: 300; font-size: clamp(28px, 4vw, 44px); line-height: 1.05; letter-spacing: -0.03em; margin-bottom: 10px; color: #211a13; }
.mf-closing-sub { font-family: var(--serif); font-size: 13px; color: rgba(30,28,24,0.55); max-width: 420px; margin-bottom: 24px; }
.mf-closing-actions { display: flex; gap: 24px; flex-wrap: wrap; align-items: center; justify-content: flex-start; }
.mf-closing-link {
  font-family: var(--serif); font-size: 11px; letter-spacing: 0.03em; text-transform: uppercase;
  color: rgba(30,28,24,0.55); text-decoration: none; transition: color 0.2s;
}
.mf-closing-link:hover { color: rgba(30,28,24,0.85); }

/* Gallery slide — just the case study's logo + a clean 3-image row, an
   honest preview of how the slide will actually look. The picker UI that
   fills those slots lives in .mf-gallery-panel below the deck instead of
   inside the slide itself, so it never eats into the slide's own
   composition. A project can also be excluded entirely (Gallery: Off on
   its own project slide's toggle), which just hides this slide. */
.mf-slide-gallery { padding: 56px 64px; position: relative; }
.mf-slide-gallery.mf-gallery-hidden { display: none !important; }
.mf-gallery-logo { max-height: 40px; max-width: 220px; object-fit: contain; object-position: left center; margin-bottom: 22px; display: block; filter: brightness(0) invert(1) !important; }
/* min-height:0 on both the row and each slot is the standard flexbox fix for
   a tall/portrait photo otherwise forcing this row (and the whole card)
   taller than its allotted space — without it, a flex item's automatic
   min-height defaults to its content's intrinsic size instead of 0.
   object-fit:contain (not cover) shows the whole photo, letterboxed on the
   slot's own background if its aspect ratio doesn't match the frame — the
   zoom slider in the panel below scales up from there via transform:scale,
   progressively cropping toward a tighter/zoomed-in look. */
.mf-gallery-row { display: flex; gap: 14px; flex: 1; min-height: 0; }
.mf-gallery-slot {
  flex: 1; min-width: 0; min-height: 0; border-radius: 12px; overflow: hidden;
  position: relative; background: #f2f0ec; display: flex; align-items: center; justify-content: center;
}
.mf-gallery-slot img {
  max-width: 100%; max-height: 100%; width: auto; height: auto;
  object-fit: contain; display: block; transform-origin: center center;
}

/* Picker panel — lives below the slide card, on the deck's own dark page
   background (not white like the slides), shown only while a gallery slide
   is the active one. */
.mf-gallery-panel { max-width: 1000px; margin: 0 auto; padding: 20px 24px 48px; }
.mf-gallery-zoom-row { display: flex; gap: 14px; margin-bottom: 16px; }
.mf-gallery-zoom-row input[type=range] { flex: 1; min-width: 0; }
.mf-gallery-picker-label {
  font-family: var(--mono); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 12px;
}
.mf-gallery-slot-select { display: flex; gap: 6px; margin-bottom: 12px; }
.mf-gallery-slot-btn {
  font-family: var(--mono); font-size: 11px; padding: 6px 14px; border-radius: 16px;
  border: 1px solid var(--border); background: var(--bg2); cursor: pointer; color: var(--ink2);
}
.mf-gallery-slot-btn.active { background: var(--rose); border-color: var(--rose); color: #fff; }
.mf-gallery-thumbs { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px; }
.mf-gallery-thumb { flex: 0 0 84px; height: 62px; border-radius: 6px; overflow: hidden; cursor: pointer; border: 2px solid transparent; padding: 0; background: none; }
.mf-gallery-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mf-gallery-thumb:hover { border-color: var(--rose); }

@media (max-width: 900px) {
  .mf-wrap, .mf-tray { padding-left: 24px; padding-right: 24px; }
}
/* Note: there is deliberately no longer an automatic max-width breakpoint
   forcing project slides to stack — that used to override the layout
   unconditionally on any narrow window, which fought with the per-project
   Vertical/Horizontal toggle (a project explicitly set to Vertical would
   silently render stacked anyway below 760px). The toggle is now the only
   thing that decides this, at any viewport width. */

/* Inline-editable slide text — visible only on screen (hidden for print,
   see below), never changes the layout, just hints that it's editable. */
.mf-editable { cursor: text; border-radius: 3px; outline: 1px dashed transparent; outline-offset: 2px; transition: outline-color 0.15s ease; }
.mf-editable:hover { outline-color: rgba(30,28,24,0.25); }
.mf-editable:focus { outline: 1px dashed var(--rose); background: rgba(196,104,122,0.06); }

/* ── "View as Slides" (?present=1) — a plain scrollable webpage version of
   the deck, opened in a new tab in place of window.print()'s Save-as-PDF
   flow. Every slide renders at once (not just the active one) at full
   real size, stacked with a visible gap so each stays visually separate -
   ordinary browser text rendering, no print/PDF scaling-to-fit-paper step
   involved (that step, not the CSS aspect-ratio, was the actual source of
   the shrunk-text/too-much-whitespace look in the exported PDF). */
body.mf-present-mode .nav,
body.mf-present-mode .site-footer,
body.mf-present-mode .mf-deck-controls,
body.mf-present-mode .mf-gallery-panel { display: none !important; }
/* Matches the editable deck's own .mf-slides max-width (1000px) exactly,
   rather than some other number - every font-size on a slide is a fixed px
   value, not scaled to the box's own width, so a wider box here than what
   you were just looking at in the editor makes the identical text read as
   noticeably smaller (more empty box for the same-size letters), which is
   what "the text size scales down" in View as Slides actually was. */
body.mf-present-mode .mf-slides { max-width: 1000px; padding: 40px 24px; }
/* .mf-slide.mf-active is normally what supplies flex-direction:column (see
   above) - present mode never adds mf-active since every slide is shown
   at once, so non-project slides (About, Closing) fell back to the
   browser's default row axis, scattering their children sideways instead
   of stacking them (the "About page formatted weird" report). Restated
   here for every slide; .mf-slide.mf-slide-project's own row-direction
   rule still wins for project slides since it's a more specific selector. */
body.mf-present-mode .mf-slide { display: flex !important; flex-direction: column; margin-bottom: 40px; }
body.mf-present-mode .mf-slide-layout-toggle { display: none !important; }
body.mf-present-mode .mf-editable { cursor: default; outline: none !important; }

/* ── Print: one slide per page ──
   Every slide is authored on-screen inside a fixed 16:9 widescreen box
   (.mf-slide's aspect-ratio above). Without an explicit @page size, the
   printed page takes on whatever ratio the destination paper has, which
   can drift from that ratio depending on the printer/driver's own default
   margins - pinning @page to a physical 13.333in x 7.5in sheet (the same
   16:9 ratio, and the same physical size PowerPoint/Keynote use for a
   widescreen export) means every page, and therefore every slide, keeps
   the identical proportions it has on screen; Chrome then scales that
   fixed-ratio page to fit whatever physical paper size is selected in the
   print dialog, rather than distorting the content to match the paper's
   own shape. Every slide type is capped to exactly one page - none are
   allowed to run taller or shorter than this rectangle, so overflowing
   content clips at the page edge instead of spilling onto a second page. */
@page { size: 13.333in 7.5in; margin: 0; }
@media print {
  .nav, .site-footer, .mf-wrap, .mf-tray, .mf-deck-controls, .mf-gallery-panel { display: none !important; }
  /* `vh` doesn't reliably resolve to the actual @page box height across
     browsers/print engines (it's frequently computed against the default
     portrait page size before the landscape @page override applies), which
     was making the printed/PDF-preview page balloon far taller than the
     on-screen card - the "too tall/zoomed out vs. the card" bug. Pinning
     .mf-slide (and neutralizing every ancestor's own `min-height:100vh`,
     which survives into print otherwise) to the exact physical pixel size
     of 13.333in x 7.5in at the standard 96 CSS-px/inch (1280x720)
     guarantees the printed page is pixel-identical to the @page box, no
     vh involved. */
  html, body, .mf-deck { min-height: 0 !important; height: auto !important; }
  body, .mf-deck { background: #fff !important; }
  .mf-slides { padding: 0; max-width: none; }
  .mf-slide {
    display: flex !important; box-shadow: none; border-radius: 0; page-break-after: always;
    break-after: page; width: 1280px; height: 720px; aspect-ratio: auto; overflow: hidden;
  }
  .mf-slide:last-child { page-break-after: auto; break-after: auto; }
  /* A gallery slide excluded via its project's "Gallery: Off" toggle must
     stay hidden in print too - .mf-slide{display:flex!important} above is
     the same specificity (one class) as .mf-gallery-hidden, so without this
     more-specific override, source order alone would let the print rule
     win and the "hidden" gallery would print anyway. */
  .mf-slide.mf-gallery-hidden { display: none !important; }
  .mf-slide-layout-toggle { display: none !important; }
  * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .mf-editable { outline: none !important; background: none !important; }
}
