/* ==========================================================================
   Deck stage — all application styling.

   Without single-file components there is no style scoping, so class names are
   namespaced by component instead (.statusbar__*, .remote__*).
   The slides themselves carry their own complete inline styling; nothing here
   targets their internals, and the deck's own global rules are rewritten at
   runtime to sit under .dc-slide (see components/SlideCanvas.js).
   ========================================================================== */

/* --- Reset ---------------------------------------------------------------- */

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

html,
body,
#app {
  height: 100%;
}

body {
  margin: 0;
  background: #0b120d;
  color: #eff5e9;
  font-family: 'Libre Franklin', system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* The projector should never show a scrollbar or bounce. */
  overflow: hidden;
  overscroll-behavior: none;
}

/* …but the remote is a scrolling document. */
body:has(.remote) {
  overflow: auto;
}

button {
  font-family: inherit;
}

:focus-visible {
  outline: 2px solid #e7a008;
  outline-offset: 2px;
}

code {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 0.9em;
  background: rgba(255, 255, 255, 0.07);
  border-radius: 4px;
  padding: 1px 6px;
}

/* --- Slide canvas --------------------------------------------------------- */

.fit {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.canvas {
  position: absolute;
  left: 50%;
  top: 50%;
  transform-origin: center center;
  /* Until the first measurement lands, scale is 0 — an unscaled 1920px canvas
     flashing at full size is far uglier than one extra frame of nothing. */
  will-change: transform;
}

/* Transition: the incoming slide fades in *on top of* the outgoing one, which
   is held fully opaque until it is covered.

   A symmetric crossfade would put both slides at ~50% at the midpoint, and
   because every slide here is a full-bleed opaque design, that reads as two
   overlapping documents rather than a dissolve. Holding the old slide solid
   underneath means there is never a frame you can see through. */
.dc-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  z-index: 0;
}

.dc-slide.is-leaving {
  opacity: 1;
  visibility: visible;
  z-index: 1;
}

.dc-slide.is-active {
  opacity: 1;
  visibility: visible;
  z-index: 2;
  animation: slide-in 300ms ease;
}

@keyframes slide-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* Build steps -------------------------------------------------------------
   Elements marked `data-step="n"` in the deck source stay hidden until the
   presenter has advanced to step n.

   Hidden with opacity, never `display: none`. These slides are flex and grid
   rows of equal-width cards; removing one from layout would let the others
   resize and slide across the screen as each appears. Reserving the space
   keeps every card exactly where the audience will see it, so the only thing
   that changes is whether it is there yet. */
.dc-slide [data-step] {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 340ms ease,
    transform 340ms cubic-bezier(0.22, 1, 0.36, 1);
}

.dc-slide [data-step].is-revealed {
  opacity: 1;
  transform: none;
}

/* --- Stage ---------------------------------------------------------------- */

.stage {
  position: fixed;
  inset: 0;
  background: #0b120d;
  overflow: hidden;
}

.chrome {
  position: absolute;
  z-index: 20;
  transition:
    opacity 420ms ease,
    transform 420ms ease;
}

.chrome--top {
  top: 22px;
  right: 22px;
}

.chrome--bottom {
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
}

.chrome-hidden .chrome {
  opacity: 0;
  pointer-events: none;
}

.chrome-hidden .chrome--top {
  transform: translateY(-8px);
}

.chrome-hidden .chrome--bottom {
  transform: translateX(-50%) translateY(8px);
}

.blackout {
  position: absolute;
  inset: 0;
  background: #000;
  z-index: 10;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 220ms ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

/* --- Boot / failure ------------------------------------------------------- */

.boot {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  color: #a9c4ae;
  font-size: 15px;
  text-align: center;
  padding: 40px;
}

.boot--failed {
  align-items: flex-start;
  justify-content: center;
  max-width: 640px;
  margin: 0 auto;
  text-align: left;
}

.boot h1 {
  margin: 0;
  font-family: 'Spectral', Georgia, serif;
  font-size: 30px;
  font-weight: 600;
  color: #f6f7f0;
}

.boot__detail {
  margin: 0;
  color: #d6a79c;
  line-height: 1.55;
}

.boot__checklist {
  margin: 4px 0;
  padding-left: 20px;
  line-height: 1.9;
  color: #a9c4ae;
}

.boot__spinner {
  width: 26px;
  height: 26px;
  border: 2px solid rgba(243, 194, 75, 0.25);
  border-top-color: #e7a008;
  border-radius: 50%;
  animation: spin 800ms linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* --- Status bar ----------------------------------------------------------- */

.statusbar {
  background: rgba(11, 18, 13, 0.88);
  border: 1px solid rgba(243, 194, 75, 0.22);
  border-radius: 12px;
  padding: 0 0 8px;
  overflow: hidden;
  backdrop-filter: blur(10px);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.35);
}

.statusbar__track {
  height: 3px;
  background: rgba(243, 194, 75, 0.16);
}

.statusbar__fill {
  height: 100%;
  background: #e7a008;
  transition: width 300ms ease;
}

.statusbar__row {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 9px 18px 2px;
  white-space: nowrap;
}

.statusbar__count {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 13px;
  font-weight: 600;
  color: #f3c24b;
  letter-spacing: 0.06em;
}

.statusbar__of {
  color: #6d7f6f;
  font-weight: 400;
}

.statusbar__label {
  font-size: 13px;
  color: #eff5e9;
  max-width: 34ch;
  overflow: hidden;
  text-overflow: ellipsis;
}

.statusbar__steps {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: none;
}

.statusbar__steps i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: rgba(243, 194, 75, 0.28);
  transition: background 200ms ease;
}

.statusbar__steps i.is-done {
  background: #e7a008;
}

.statusbar__offline {
  flex: none;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #ffb4a2;
  background: rgba(226, 114, 91, 0.16);
  border-radius: 999px;
  padding: 2px 8px;
}

.statusbar__keys {
  font-size: 11px;
  color: #7e8f80;
  margin-left: auto;
}

.statusbar kbd {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 4px;
  padding: 1px 5px;
  margin: 0 1px;
  color: #a9c4ae;
}

/* --- Preview / rehearsal -------------------------------------------------- */

.preview {
  position: fixed;
  inset: 0;
  display: grid;
  grid-template-rows: 1fr;
  background: #0b120d;
}

.preview--with-notes {
  grid-template-rows: 1fr minmax(160px, 26vh);
}

.preview__stage {
  position: relative;
  overflow: hidden;
}

.preview__chrome {
  position: absolute;
  bottom: 22px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 12px;
  transition: opacity 420ms ease;
}

.preview__chrome.is-hidden {
  opacity: 0;
  pointer-events: none;
}

.preview__badge {
  background: rgba(11, 18, 13, 0.88);
  border: 1px solid rgba(243, 194, 75, 0.22);
  border-radius: 999px;
  color: #f3c24b;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 7px 14px;
  white-space: nowrap;
}

.preview__notes {
  border-top: 1px solid rgba(243, 194, 75, 0.2);
  background: #0d1710;
  padding: 18px 26px;
  overflow-y: auto;
}

.preview__notes h2 {
  margin: 0 0 8px;
  font-family: 'Spectral', Georgia, serif;
  font-size: 18px;
  color: #f3c24b;
}

.preview__notes p {
  margin: 0;
  font-size: 16px;
  line-height: 1.6;
  color: #d8e4d6;
  max-width: 100ch;
}

.preview__problem {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #ffb4a2;
  padding: 40px;
  text-align: center;
}

/* --- Browser remote ------------------------------------------------------- */

.remote {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: #0b120d;
  color: #eff5e9;
}

.remote__connect {
  margin: auto;
  padding: 32px 24px;
  text-align: center;
}

.remote__connect h1 {
  font-family: 'Spectral', Georgia, serif;
  font-size: 28px;
  margin: 0 0 8px;
}

.remote__lead {
  color: #a9c4ae;
  font-size: 14px;
  margin: 0;
}

.remote__problem {
  color: #ffb4a2;
  font-size: 13px;
  line-height: 1.5;
  margin: 0;
  max-width: 46ch;
}

.remote__bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.remote__index {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-weight: 600;
  color: #f3c24b;
  flex: none;
}

.remote__of {
  color: #6d7f6f;
  font-weight: 400;
}

.remote__label {
  font-size: 14px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}

.remote__screens {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 11px;
  color: #7e8f80;
}

.remote__screens i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #e2725b;
}

.remote__screens i.is-live {
  background: #6fd08c;
}

.remote__panel {
  flex: 1;
  overflow-y: auto;
  padding: 18px;
  -webkit-overflow-scrolling: touch;
}

.remote__eyebrow {
  margin: 0 0 8px;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #7e8f80;
}

/* What the next press puts on screen — the one thing that matters when you
   are facing the audience rather than the deck. */
.remote__next {
  background: rgba(243, 194, 75, 0.08);
  border: 1px solid rgba(243, 194, 75, 0.28);
  border-radius: 12px;
  padding: 16px 18px;
  margin-bottom: 20px;
}

.remote__next h2 {
  margin: 0;
  font-family: 'Spectral', Georgia, serif;
  font-size: 22px;
  line-height: 1.25;
  color: #f3c24b;
}

.remote__next p {
  margin: 8px 0 0;
  font-size: 15px;
  line-height: 1.5;
  color: #d8e4d6;
}

.remote__done {
  margin: 0 0 20px;
  color: #7e8f80;
  font-size: 14px;
}

.remote__revealed {
  margin: 0;
  padding-left: 18px;
  color: #7e8f80;
  font-size: 13px;
  line-height: 1.7;
}

.remote__revealed li {
  display: list-item;
}

.remote__grid-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid transparent;
  border-radius: 10px;
  color: #d8e4d6;
  font: inherit;
  padding: 13px 14px;
  margin-bottom: 8px;
  text-align: left;
  cursor: pointer;
}

.remote__grid-item.is-on {
  border-color: rgba(243, 194, 75, 0.5);
  background: rgba(243, 194, 75, 0.1);
  color: #fff;
}

.remote__grid-index {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  font-size: 12px;
  color: #f3c24b;
  flex: none;
}

.remote__controls {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding: 12px 18px calc(12px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.remote__utility {
  display: flex;
  gap: 8px;
}

.remote__nav {
  display: grid;
  grid-template-columns: 1fr 2.2fr;
  gap: 10px;
}

.remote__step {
  border: 1px solid rgba(243, 194, 75, 0.3);
  background: rgba(255, 255, 255, 0.04);
  color: #f3c24b;
  border-radius: 14px;
  font-size: 30px;
  line-height: 1;
  padding: 20px 0;
  cursor: pointer;
  /* Touch targets sized for someone who is talking and not looking down. */
  touch-action: manipulation;
}

.remote__step--primary {
  background: #e7a008;
  border-color: #e7a008;
  color: #16351f;
}

.remote__ghost {
  flex: 1;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  color: #d8e4d6;
  font: inherit;
  font-size: 13px;
  padding: 9px 12px;
  cursor: pointer;
}

.remote__clock {
  font-family: 'JetBrains Mono', ui-monospace, monospace;
}

/* --- Motion preferences --------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .dc-slide.is-active {
    animation: none;
  }

  /* Still reveal in steps — that is content pacing, not decoration — but
     without the movement. */
  .dc-slide [data-step] {
    transform: none;
    transition: opacity 120ms linear;
  }

  .statusbar__fill {
    transition: none;
  }

  .pairing__dot.warn {
    animation: none;
  }

  .boot__spinner {
    animation-duration: 2.4s;
  }
}
