/* ============================================================
   DECK ENGINE — presentation chrome
   Brand-agnostic. Contains NO brand values: every colour and
   typeface resolves from a --brand-* property supplied by
   brand/colorado.css. The fallbacks are neutral greys so a
   missing brand file degrades to readable, not invisible.

   Lineage: the stage, HUD, navigator, notes and print rules come
   from the selling-summer engine (deck.v2); the build-step and
   motion vocabulary comes from the mmgy system. Both are here
   because they solve different halves of the same problem —
   one gets you through the deck, the other through a slide.
   ============================================================ */

:root {
  /* ---- brand tokens (overridden in brand/colorado.css) ---- */
  --brand-primary:        #666;
  --brand-primary-bright: #888;
  --brand-primary-deep:   #333;
  --brand-ink:            #0A0A0A;
  --brand-paper:          #FFFFFF;
  --brand-bone:           #F2F2F2;

  --brand-f-display: Impact, sans-serif;
  --brand-f-body:    system-ui, -apple-system, sans-serif;
  --brand-f-mono:    ui-monospace, monospace;

  /* ---- engine constants (structural, not brand) ---- */
  --ease-out:   cubic-bezier(.22, 1, .36, 1);
  --slide-fade: 520ms;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  background: #0b0b0c;
  color: var(--brand-paper);
  font-family: var(--brand-f-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---------- STAGE ----------
   A fixed 16:9 stage sized in CSS, not JS. container-type:size
   makes every child sizable in cqw/cqh, so type scales with the
   stage and renders deterministically to PDF — no resize
   listener, no reflow, no fit-box arithmetic to get wrong. */
.deck-shell { position: fixed; inset: 0; display: grid; place-items: center; background: #0b0b0c; }
.stage {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100vw;
  max-width: calc(100vh * 16 / 9);
  height: 100vh;
  max-height: calc(100vw * 9 / 16);
  overflow: hidden;
  background: var(--brand-paper);
  container-type: size;
  container-name: slide;
  box-shadow: 0 30px 90px rgba(0,0,0,0.45);
}

/* Slides overlay the stage and cross-fade. Selected as `.stage > .slide`
   (specificity 0,2,0) rather than `.slide` (0,1,0) on purpose: a deck's
   own `.s-cover { position: relative }` would otherwise win on source
   order, drop the slide into normal flow, and stack the deck vertically
   down the page. That failure is invisible in PDF export — print mode
   makes every slide relative anyway — so it must be prevented here. */
.stage > .slide {
  position: absolute; inset: 0;
  opacity: 0;
  pointer-events: none;
  overflow: hidden;
  /* The OUTGOING slide holds full opacity for the length of the fade and
     then snaps off underneath. It must not fade out in step with the
     incoming one: two half-opaque slides over the stage composite
     darker than either, which is the flash between slides. */
  transition: opacity 0s var(--slide-fade);
}
.stage > .slide.active {
  opacity: 1; pointer-events: auto; z-index: 2;
  transition: opacity var(--slide-fade) var(--ease-out);
}

/* ---------- HUD ----------
   Sits on the stage, not the page, so it lands inside a screen
   recording and inside the PDF crop. Neutral grey rather than
   mix-blend-mode: the Colorado palette runs light, and difference
   blending over sand produces a muddy inversion. */
/* Everything sits bottom-LEFT. The template puts the conference lockup
   bottom-right on every content slide, so a counter in that corner
   would collide with it on most of the deck. */
.hud {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; justify-content: flex-start; gap: 1.5cqw; align-items: center;
  padding: 1.6cqh 2.4cqw;
  font-family: var(--brand-f-mono);
  font-size: 1.15cqh;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute, rgba(0,0,0,.5));
  pointer-events: none;
  z-index: 50;
}
.hud .hud-left, .hud .hud-right { display: flex; gap: 1.5cqw; align-items: center; }
.hud .pip {
  display: inline-block; width: 0.85cqh; height: 0.85cqh; border-radius: 50%;
  background: var(--brand-primary-bright);
}
.hud-right { pointer-events: auto; }

/* Per-slide HUD modes, from data-hud on the slide (deck.js copies it
   across). "light" for photography, where mid-grey type disappears;
   "off" for a slide that should carry nothing but itself. */
.hud { transition: color .3s, opacity .3s; }
.hud[data-mode="light"] { color: rgba(255,255,255,0.82); text-shadow: 0 1px 6px rgba(0,0,0,.35); }
.hud[data-mode="off"]   { opacity: 0; }
.hud[data-mode="off"] .hud-right { pointer-events: none; }
#hud-slide {
  cursor: pointer; padding: 0.4cqh 0.7cqw; border-radius: 2px;
  font-variant-numeric: tabular-nums;
  transition: background .18s ease;
}
#hud-slide:hover { background: var(--hairline, rgba(0,0,0,.1)); }

.progress-bar {
  position: absolute; top: 0; left: 0; height: 0.35cqh; width: 0%;
  background: var(--brand-primary-bright);
  transition: width var(--slide-fade) var(--ease-out);
  z-index: 60;
}

.help {
  position: fixed; right: 22px; top: 22px;
  font-family: var(--brand-f-mono);
  font-size: 10px;
  letter-spacing: 0.2em;
  color: rgba(255,255,255,0.72);
  text-transform: uppercase;
  background: rgba(0,0,0,0.6);
  padding: 8px 14px;
  border: 1px solid rgba(255,255,255,0.18);
  backdrop-filter: blur(8px);
  z-index: 60;
  transition: opacity .6s;
}
.help.fade { opacity: 0; }
.help kbd {
  font-family: var(--brand-f-mono);
  background: rgba(255,255,255,0.2);
  padding: 2px 6px; border-radius: 3px;
  color: #fff; margin: 0 3px;
}

/* ---------- SLIDE NAVIGATOR ----------
   Presenter chrome. Opens on N or a click on the HUD counter; the
   engine builds it from the DOM so a deck needs no extra markup.
   Lives outside .stage, so its clicks never reach the advance
   handler. */
.nav-overlay {
  position: fixed; inset: 0; z-index: 100;
  display: none; place-items: center;
  background: rgba(10, 12, 16, 0.86);
  backdrop-filter: blur(10px);
}
.nav-overlay.open { display: grid; }
.nav-inner { width: min(1180px, 92vw); max-height: 84vh; overflow: auto; padding: 4px; }
.nav-head {
  display: flex; justify-content: space-between; align-items: baseline;
  font-family: var(--brand-f-mono); font-weight: 600; font-size: 11px;
  letter-spacing: 0.24em; text-transform: uppercase;
  color: rgba(255,255,255,0.6);
  padding-bottom: 14px; margin-bottom: 18px;
  border-bottom: 1px solid rgba(255,255,255,0.22);
}
.nav-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 10px; }
.nav-card {
  display: block; text-align: left; cursor: pointer;
  padding: 12px 14px; font: inherit; color: #fff;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.16);
  border-left: 3px solid transparent;
  transition: background .16s ease, border-color .16s ease;
}
.nav-card:hover   { background: rgba(255,255,255,0.15); border-left-color: var(--brand-primary-bright); }
.nav-card.current { background: rgba(255,255,255,0.17); border-left-color: var(--brand-primary-bright); }
/* keyboard cursor — distinct from .current, so you can see where the
   deck is AND where Enter would take it */
.nav-card.sel {
  background: rgba(255,255,255,0.22);
  outline: 2px solid var(--brand-primary-bright); outline-offset: -2px;
}
.nav-card .nc-n {
  display: block; font-family: var(--brand-f-mono); font-weight: 700;
  font-size: 10px; letter-spacing: 0.24em;
  color: var(--brand-primary-bright); margin-bottom: 5px;
}
.nav-card .nc-t {
  display: block; font-family: var(--brand-f-display); font-weight: 400;
  font-size: 15px; line-height: 1.2; letter-spacing: 0.04em; text-transform: uppercase;
}

/* ---------- TYPE SCALE ----------
   Bebas needs POSITIVE tracking: condensed grotesques bleed into
   each other at 0 or negative.

   MINIMUM READABLE SIZE — 2.0cqh. A deck is read across a room,
   not at desk distance. Do NOT set body copy below 2.0cqh to make
   content fit: cut words, or trim padding, instead. Tracked mono
   labels may sit lower, but never under 1.15cqh. */
.d-mega { font-family: var(--brand-f-display); font-weight: 400; font-size: 15cqh; line-height: 0.90; letter-spacing: 0.012em; text-transform: uppercase; }
.d-xl   { font-family: var(--brand-f-display); font-weight: 400; font-size: 11cqh; line-height: 0.94; letter-spacing: 0.015em; text-transform: uppercase; }
.d-lg   { font-family: var(--brand-f-display); font-weight: 400; font-size: 8.2cqh; line-height: 0.98; letter-spacing: 0.018em; text-transform: uppercase; }
.d-md   { font-family: var(--brand-f-display); font-weight: 400; font-size: 6.2cqh; line-height: 1.02; letter-spacing: 0.02em;  text-transform: uppercase; }
.d-sm   { font-family: var(--brand-f-display); font-weight: 400; font-size: 4.4cqh; line-height: 1.06; letter-spacing: 0.024em; text-transform: uppercase; }

.stat-mega { font-family: var(--brand-f-display); font-weight: 400; font-size: 16cqh; line-height: 0.86; letter-spacing: 0.005em; font-variant-numeric: tabular-nums; }
.stat-big  { font-family: var(--brand-f-display); font-weight: 400; font-size: 10cqh; line-height: 0.88; letter-spacing: 0.005em; font-variant-numeric: tabular-nums; }

/* The template's signature: a tracked all-caps subhead under every
   headline. It is the one piece of type the deck must not lose. */
.eyebrow {
  font-family: var(--brand-f-slab); font-weight: 500;
  font-size: 1.65cqh; letter-spacing: 0.26em; text-transform: uppercase;
  color: var(--gold-deep, currentColor);
}
.eyebrow-mono { font-family: var(--brand-f-mono); font-weight: 600; font-size: 1.35cqh; letter-spacing: 0.28em; text-transform: uppercase; }

.body-xl   { font-family: var(--brand-f-body); font-weight: 400; font-size: 3.1cqh;  line-height: 1.42; }
.body-lead { font-family: var(--brand-f-body); font-weight: 400; font-size: 2.6cqh;  line-height: 1.46; }
.body-med  { font-family: var(--brand-f-body); font-weight: 400; font-size: 2.3cqh;  line-height: 1.46; }
.body-sm   { font-family: var(--brand-f-body); font-weight: 400; font-size: 2.05cqh; line-height: 1.48; }
.caption   { font-family: var(--brand-f-body); font-weight: 400; font-size: 1.7cqh;  line-height: 1.4; color: var(--ink-mute, #888); }

/* ---------- ARRIVE ANIMATIONS ----------
   Two systems, deliberately:

   .fx          — animates when the SLIDE arrives. Stagger with .fx-1…12.
   [data-step]  — stays hidden until the presenter CLICKS.

   Rule of both: the VISIBLE state is the base style. We animate
   *from* hidden, never *to* it, so print, reduced-motion and a
   failed script all show finished content. */

:root {
  --fx-dur: .72s;
  --fx-dur-slow: .95s;
  --fx-ease: cubic-bezier(0.2, 0.7, 0.2, 1);
  --fx-ease-draw: cubic-bezier(0.6, 0, 0.4, 1);
  --fx-shift: 40px;
}

@keyframes fx-up    { from { opacity: 0; transform: translateY(var(--fx-shift)); } to { opacity: 1; transform: none; } }
@keyframes fx-down  { from { opacity: 0; transform: translateY(calc(-1 * var(--fx-shift))); } to { opacity: 1; transform: none; } }
@keyframes fx-left  { from { opacity: 0; transform: translateX(-56px); } to { opacity: 1; transform: none; } }
@keyframes fx-right { from { opacity: 0; transform: translateX(56px); }  to { opacity: 1; transform: none; } }
@keyframes fx-in    { from { opacity: 0; } to { opacity: 1; } }
@keyframes fx-scale { from { opacity: 0; transform: scale(1.05); } to { opacity: 1; transform: none; } }
/* Wipes — content is uncovered, not faded. */
@keyframes fx-wipe    { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes fx-wipe-up { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes fx-wipe-dn { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes fx-grow-x  { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes fx-grow-y  { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes fx-draw    { from { stroke-dashoffset: var(--len, 1000); } to { stroke-dashoffset: 0; } }
/* Slow drift on full-bleed photography — the one ambient motion allowed. */
@keyframes fx-bleed   { from { transform: scale(1.08); } to { transform: scale(1); } }

/* `backwards`, not `both`: a finished animation with `both` squats on
   the computed value from the animation origin, which no author rule
   can then override — which would make [data-step-dim] impossible. */
.slide.active .fx { animation: fx-up var(--fx-dur) var(--fx-ease) backwards; }

.slide.active .fx--down    { animation-name: fx-down; }
.slide.active .fx--left    { animation-name: fx-left; }
.slide.active .fx--right   { animation-name: fx-right; }
.slide.active .fx--in      { animation-name: fx-in; }
.slide.active .fx--scale   { animation-name: fx-scale; }
.slide.active .fx--wipe    { animation-name: fx-wipe;    animation-duration: var(--fx-dur-slow); }
.slide.active .fx--wipe-up { animation-name: fx-wipe-up; animation-duration: var(--fx-dur-slow); }
.slide.active .fx--wipe-dn { animation-name: fx-wipe-dn; animation-duration: var(--fx-dur-slow); }
.slide.active .fx--grow-x  { animation-name: fx-grow-x; transform-origin: left center; }
.slide.active .fx--grow-y  { animation-name: fx-grow-y; transform-origin: bottom center; }
.slide.active .fx--draw    { animation-name: fx-draw; animation-duration: 1.4s; animation-timing-function: var(--fx-ease-draw); }
.slide.active .fx--bleed   { animation: fx-bleed 7s .1s ease-out backwards; }

.fx--near { --fx-shift: 18px; }
.fx--far  { --fx-shift: 88px; }

/* Stagger. 110ms apart — quick enough to read as one gesture. */
.slide.active .fx-1  { animation-delay: .08s; }
.slide.active .fx-2  { animation-delay: .19s; }
.slide.active .fx-3  { animation-delay: .30s; }
.slide.active .fx-4  { animation-delay: .41s; }
.slide.active .fx-5  { animation-delay: .52s; }
.slide.active .fx-6  { animation-delay: .63s; }
.slide.active .fx-7  { animation-delay: .74s; }
.slide.active .fx-8  { animation-delay: .85s; }
.slide.active .fx-9  { animation-delay: .96s; }
.slide.active .fx-10 { animation-delay: 1.07s; }
.slide.active .fx-11 { animation-delay: 1.18s; }
.slide.active .fx-12 { animation-delay: 1.29s; }

/* Auto-stagger: .fx-auto on a container gives every .fx child an
   index-based delay. deck.js sets --i. */
.slide.active .fx-auto > .fx { animation-delay: calc(.08s + var(--i, 0) * .085s); }

/* ---------- CLICK-THROUGH BUILDS ----------
   <section class="slide" data-steps>
     <h2>Always visible</h2>
     <div data-step>Revealed on click 1</div>
     <div data-step class="fx--left">Revealed on click 2</div>
     <div data-step="2">Also click 2 — same number groups elements</div>
     <p data-step-until="2">Retires once step 2 arrives</p>
     <li data-step-dim>Greys back as the build moves on</li>
   </section>

   Bare data-step auto-numbers in DOM order; an explicit data-step="N"
   pins the element to that beat and resets the counter, so you can
   interleave freely. deck.js normalises both on load. */

/* visibility keeps it out of the a11y tree and stops it catching
   clicks; opacity does the visual work. */
[data-steps] [data-step]:not([data-step-on]) { opacity: 0; visibility: hidden; }
/* Suppress descendant entrance animations while the step is closed so
   they replay from the top when it opens — changing animation-name away
   from `none` restarts the animation, which is the whole trick. */
[data-steps] [data-step]:not([data-step-on]) * { animation: none !important; }

/* Higher specificity than the .fx rules so a step always wins over a
   slide-entrance animation on the same element. */
.slide.active[data-steps] [data-step][data-step-on] {
  animation: fx-up var(--fx-dur) var(--fx-ease) backwards;
}
.slide.active[data-steps] [data-step][data-step-on].fx--down    { animation-name: fx-down; }
.slide.active[data-steps] [data-step][data-step-on].fx--left    { animation-name: fx-left; }
.slide.active[data-steps] [data-step][data-step-on].fx--right   { animation-name: fx-right; }
.slide.active[data-steps] [data-step][data-step-on].fx--in      { animation-name: fx-in; }
.slide.active[data-steps] [data-step][data-step-on].fx--scale   { animation-name: fx-scale; }
.slide.active[data-steps] [data-step][data-step-on].fx--wipe    { animation-name: fx-wipe;    animation-duration: var(--fx-dur-slow); }
.slide.active[data-steps] [data-step][data-step-on].fx--wipe-up { animation-name: fx-wipe-up; animation-duration: var(--fx-dur-slow); }
.slide.active[data-steps] [data-step][data-step-on].fx--wipe-dn { animation-name: fx-wipe-dn; animation-duration: var(--fx-dur-slow); }
.slide.active[data-steps] [data-step][data-step-on].fx--grow-x  { animation-name: fx-grow-x; transform-origin: left center; }
.slide.active[data-steps] [data-step][data-step-on].fx--grow-y  { animation-name: fx-grow-y; transform-origin: bottom center; }
.slide.active[data-steps] [data-step][data-step-on].fx--draw    { animation-name: fx-draw; animation-duration: 1.4s; animation-timing-function: var(--fx-ease-draw); }

/* Elements that retire as the build progresses. */
[data-steps] [data-step-until] { transition: opacity .42s var(--fx-ease); }
[data-steps] [data-step-until][data-step-spent] {
  opacity: 0; visibility: hidden;
  transition: opacity .42s var(--fx-ease), visibility .42s;
}
/* Dimming instead of hiding: the previous beat greys back so the new
   one reads as current. Use on list rows and numbered columns. */
[data-steps] [data-step-dim] { transition: opacity .42s var(--fx-ease); }
[data-steps] [data-step-dim][data-step-spent] { opacity: .26; }

/* Build progress ticks. deck.js adds the container to any slide with
   steps and fills it, so a build slide needs no markup for it. It sits
   just above the conference lockup, bottom right: small enough to
   ignore from the back of the room, findable from the lectern.
   Colours are explicit rather than currentColor so it reads on
   photography as well as on sand. */
.build-ticks {
  position: absolute; right: 2.8cqw; bottom: 9.8cqh; z-index: 5;
  display: flex; gap: 0.45cqw; align-items: center; pointer-events: none;
}
.build-ticks__tick {
  width: 1.15cqw; height: 0.42cqh; border-radius: 0.21cqh;
  background: var(--ink-mute, #8A8A8A); opacity: .45;
  transition: opacity .3s, background-color .3s;
}
.build-ticks__tick.is-on { background: var(--brand-primary-bright); opacity: 1; }

/* ---------- SPEAKER NOTES ----------
   <aside class="notes"> is authored inside each slide and never
   shown on stage. S opens an overlay for the current slide; P
   rebuilds the page as a printable notes document. */
.slide aside.notes { display: none !important; }

.notes-panel {
  position: fixed; right: 0; top: 0; bottom: 0; width: min(440px, 40vw);
  display: none; flex-direction: column;
  background: rgba(22, 25, 30, 0.95); color: #f1f1f1;
  border-left: 1px solid rgba(255,255,255,0.16);
  backdrop-filter: blur(10px); z-index: 90;
  font-family: var(--brand-f-body); font-size: 15px; line-height: 1.55;
}
.notes-panel.open { display: flex; }
.notes-head {
  display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; align-items: baseline;
  padding: 18px 22px 14px; border-bottom: 1px solid rgba(255,255,255,0.16);
  font-family: var(--brand-f-mono); font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase;
}
.notes-head .nh-n { color: var(--brand-primary-bright); font-weight: 700; }
.notes-head .nh-t { color: #fff; font-family: var(--brand-f-body); font-weight: 700; font-size: 13px; letter-spacing: 0.02em; text-transform: none; }
.notes-head .nh-k { grid-column: 1 / -1; color: rgba(255,255,255,0.5); }
.notes-body { padding: 18px 22px 28px; overflow: auto; }
.notes-body p { margin: 0 0 12px; }
.notes-body ul { margin: 0 0 12px 18px; }
.notes-body li { margin-bottom: 6px; }
.notes-body strong, .notes-body b { color: #fff; }
.notes-body .cue {
  display: block; font-family: var(--brand-f-mono); font-size: 11px;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--brand-primary-bright); margin: 14px 0 6px;
}

/* printable notes document */
body.notes-mode { overflow: auto; background: #fff; color: #3F3F3F; height: auto; }
.notes-doc { max-width: 820px; margin: 0 auto; padding: 56px 32px 96px; font-family: var(--brand-f-body); font-size: 15px; line-height: 1.6; color: #3F3F3F; }
.notes-doc h1 { font-family: var(--brand-f-display); font-weight: 400; font-size: 46px; line-height: 1; letter-spacing: 0.02em; text-transform: uppercase; margin-bottom: 6px; }
.notes-doc .nd-sub { font-family: var(--brand-f-mono); font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; color: #8A8A8A; margin-bottom: 40px; }
.nd-slide { padding: 22px 0 26px; border-top: 1px solid rgba(63,63,63,0.16); break-inside: avoid; }
.nd-meta { display: flex; gap: 16px; font-family: var(--brand-f-mono); font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--brand-primary-deep); margin-bottom: 6px; }
.nd-slide h2 { font-family: var(--brand-f-display); font-weight: 400; font-size: 28px; line-height: 1.05; letter-spacing: 0.02em; text-transform: uppercase; margin-bottom: 12px; }
.nd-notes p { margin: 0 0 10px; }
.nd-notes ul { margin: 0 0 10px 20px; }
.nd-notes .cue { display: block; font-family: var(--brand-f-mono); font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--brand-primary-deep); margin: 12px 0 4px; }

/* ---------- ACCESSIBILITY & OUTPUT SAFETY ----------
   Reduced motion: no travel, no wipes. Content still appears,
   instantly. Print: everything on, everything still, builds fully
   built — a PDF of a build slide shows the finished thought. */
@media (prefers-reduced-motion: reduce) {
  .slide.active .fx,
  .slide.active[data-steps] [data-step][data-step-on] {
    animation: fx-in .01s backwards !important;
  }
  .stage > .slide, .stage > .slide.active { transition: none; }
}

@media print {
  @page { size: 13.333in 7.5in; margin: 0; }

  html, body { width: auto; height: auto; overflow: visible; background: #fff; }

  /* Print backgrounds are dropped by default, and a deck is nothing but
     backgrounds: grounds, chart fills, and the washes that hold white type
     over photography. Without this the closer prints as white text on a
     bright sky. It has to reach pseudo-elements too, which is why it is
     declared on the universal selector rather than only on .slide. */
  *, *::before, *::after {
    -webkit-print-color-adjust: exact !important;
    print-color-adjust: exact !important;
  }

  .deck-shell { position: static; display: block; place-items: initial; }
  .stage {
    position: static;
    width: auto; height: auto;
    max-width: none; max-height: none;
    aspect-ratio: auto;
    container-type: normal;
    box-shadow: none;
    overflow: visible;
  }
  /* matches the 0,2,0 specificity of the screen rule above */
  .stage > .slide {
    position: relative; inset: auto;
    width: 13.333in; height: 7.5in;
    opacity: 1 !important;
    pointer-events: auto;
    transition: none;
    container-type: size;
    container-name: slide;
    overflow: hidden;
    break-after: page;
    page-break-after: always;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  .stage > .slide:last-child { break-after: auto; page-break-after: auto; }

  /* freeze arrivals and fully build every step */
  .fx,
  [data-steps] [data-step],
  [data-steps] [data-step-until],
  [data-steps] [data-step-dim] {
    animation: none !important;
    transition: none !important;
    opacity: 1 !important;
    visibility: visible !important;
    transform: none !important;
    clip-path: none !important;
  }
  .build-ticks { display: none !important; }

  /* 3D flip cards print their front face only. Print renderers do not
     honour backface-visibility, so a back face at rotateY(180deg)
     paints OVER the front and comes out mirrored. */
  .flip__inner { transform: none !important; animation: none !important; }
  .flip__back  { display: none !important; }

  /* presentation chrome is screen-only */
  .hud, .progress-bar, .help, .nav-overlay, .notes-panel { display: none !important; }

  body.notes-mode { background: #fff; }
  .notes-doc { padding: 0; max-width: none; }
}

/* ---------- click counter (HUD) ----------
   Next to the slide number: one ring per click on this slide, filled
   gold as each click lands. Empty on slides without a build. The old
   per-slide ticks are retired in favour of this. */
.build-ticks { display: none !important; }
.hud-steps { display: inline-flex; align-items: center; gap: 0.5em; margin-left: 1em; }
.hud-steps:empty { display: none; }
.hud-steps i {
  width: 2.1em; height: 0.34em; border-radius: 0.17em;
  background: currentColor; opacity: .45;
  transition: background-color .25s, opacity .25s;
}
.hud-steps i.is-on { background: var(--brand-primary-bright); opacity: 1; }
@media print { .hud-steps { display: none !important; } }

/* ---------- fx--pop ----------
   A playful reveal: rises, overshoots a touch and settles, with a small
   tilt that straightens out. For tiles and cards, not for type. */
@keyframes fx-pop {
  0%   { opacity: 0; transform: translateY(9cqh) rotate(-5deg) scale(.9); }
  60%  { opacity: 1; transform: translateY(-1.2cqh) rotate(1.2deg) scale(1.02); }
  100% { opacity: 1; transform: none; }
}
.slide.active .fx.fx--pop { animation-name: fx-pop; animation-duration: .8s; }
.slide.active[data-steps] [data-step][data-step-on].fx--pop {
  animation-name: fx-pop; animation-duration: .8s; animation-timing-function: cubic-bezier(.2,.8,.25,1);
}
