@font-face {
  font-family: "Speedee";
  src: url("fonts/Speedee_Bd.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #F5EBD7;
  --red: #E11B22;
  --dark: #2D2A26;
  --orange: #F2A900;
  --yellow: #FCDB7E;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
  overflow: hidden;
  background: var(--bg);
  font-family: "Speedee", "Helvetica Neue", Arial, sans-serif;
  color: var(--dark);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
  overscroll-behavior: none;
  touch-action: manipulation;
}

/* Use the dynamic viewport on mobile so address-bar collapse doesn't truncate. */
@supports (height: 100dvh) {
  html, body { height: 100dvh; }
}

img { -webkit-user-drag: none; user-drag: none; pointer-events: none; }

/* The HTML5 `hidden` attribute must beat any author `display:` rule. */
[hidden] { display: none !important; }

button {
  background: none;
  border: 0;
  padding: 0;
  margin: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

/* ===== View routing + transitions ===== */
.view {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition: opacity 320ms ease, transform 320ms ease;
}

.view[data-active] {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

@media (prefers-reduced-motion: reduce) {
  .view { transition: none; transform: none; }
}

/* ===== HOME VIEW =====
 * Hard rule: nothing scrolls. Whole flow must fit in 100dvh × 100vw.
 *
 * Sizing math: bottom row has 5 step buttons + 4 arrows. Arrow native ratio
 * is ~52/288 = 0.18 of a button width. So row width = 5W + 4*0.18W = 5.72W.
 * Reserve a little breathing room and take the bottom row as the constraint:
 *   --btn-w-by-width  ≈ 16.5vw
 * Vertical constraint: title + 2 rows + dashed + gaps must fit in 100dvh.
 *   --btn-w-by-height ≈ 33vh (button aspect 288/313 ≈ 0.92, so 2 rows = 2.17 W)
 * All 9 buttons share the smaller of those two so they're identical. */
:root {
  --btn-size: min(15.5vw, 33vh, 280px);
  --arrow-size: calc(var(--btn-size) * 0.18);
}

#view-home {
  align-items: center;
  justify-content: space-between;
  padding: clamp(8px, 1.8vh, 24px) clamp(8px, 2vw, 32px);
  gap: clamp(6px, 1vh, 16px);
}

.home-title {
  text-align: center;
  line-height: 1;
  flex: 0 0 auto;
}
.home-title h1 {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(2px, 0.6vh, 8px);
  letter-spacing: 0.01em;
}
.title-mac {
  color: var(--red);
  font-size: min(7vw, 11vh);
  font-weight: 700;
}
.title-flow {
  color: var(--dark);
  font-size: min(4.2vw, 6.5vh);
  font-weight: 700;
  letter-spacing: 0.05em;
}

.flow {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(6px, 1.2vh, 18px);
  width: 100%;
  min-height: 0;
}

.flow-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(4px, 0.9vw, 14px);
  width: 100%;
}

.step {
  flex: 0 0 auto;
  display: block;
  width: var(--btn-size);
  aspect-ratio: 288 / 313;
  transition: transform 120ms ease;
  border-radius: 18px;
}
.step:active { transform: scale(0.96); }
.step:focus-visible { outline: 3px solid var(--red); outline-offset: 4px; }

.step img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.arrow {
  flex: 0 0 auto;
  width: var(--arrow-size);
  height: auto;
}

.dashed-connector {
  flex: 0 0 auto;
  width: min(72vw, 1200px);
  height: auto;
  max-height: 6vh;
  object-fit: cover;
  /* Native asset already curls down at both ends — no flip needed. */
}

/* Portrait / very narrow fallback: cap by width alone, allow rows to wrap */
@media (max-aspect-ratio: 1/1) {
  :root { --btn-size: min(28vw, 22vh, 220px); }
  .flow-row { flex-wrap: wrap; }
  .arrow, .dashed-connector { display: none; }
}

/* ===== VIDEO VIEW ===== */
#view-video {
  background: var(--bg);
  color: var(--dark);
}

/* Video view nav sizing math: 1 back + 9 step thumbs = 10 buttons.
 * Each at width ~9vw fits in the row with small gaps. The active step uses
 * `transform: scale()` which doesn't take additional layout width, so it
 * pops above the row without pushing siblings around. */
/* Nav matches the video frame width below it and is centered horizontally.
 * No bottom border — it sits on the cream page background. */
.video-nav {
  flex: 0 0 auto;
  align-self: center;
  width: min(100%, calc(72vh * 16 / 9));
  display: flex;
  align-items: flex-end;
  gap: clamp(4px, 0.8vw, 12px);
  padding: clamp(28px, 6.5vh, 64px) 0 0 0;
}

.nav-back {
  flex: 0 0 auto;
  height: min(10vh, 9vw, 140px);
  aspect-ratio: 288 / 313;
  transition: transform 120ms ease;
}
.nav-back:active { transform: scale(0.94); }
.nav-back img { width: 100%; height: 100%; object-fit: contain; display: block; }

.nav-steps {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: space-around;
  gap: clamp(2px, 0.5vw, 8px);
  min-width: 0;
}

.nav-step {
  flex: 0 1 auto;
  height: min(13vh, 9vw, 140px);
  aspect-ratio: 288 / 313;
  transition: transform 220ms cubic-bezier(0.2, 0.7, 0.2, 1.2), filter 220ms ease;
  filter: saturate(0.85);
  transform-origin: center bottom;
}
.nav-step img { width: 100%; height: 100%; object-fit: contain; display: block; }

.nav-step.active {
  transform: scale(1.1) translate(0px, 2px);
  filter: saturate(1) drop-shadow(3px 3px 2px rgba(0, 0, 0, 0.45));
  z-index: 2;
}

.nav-step:active { transform: scale(0.95); }
.nav-step.active:active { transform: scale(1.34); }

.video-stage {
  flex: 1 1 auto;
  background: var(--bg);
  min-height: 0;
  display: grid;
  place-items: center;
  padding: clamp(8px, 2vh, 28px) clamp(8px, 2vw, 28px);
}

/* 16:9 box, as large as possible while staying inside the stage.
 * The width is the smaller of (stage content width) and (height budget × 16/9)
 * so the 16:9 aspect ratio is always honored — relying on aspect-ratio +
 * max-height alone doesn't work because width:100% prevents the browser
 * from shrinking width when max-height clamps. */
.video-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  /* 72vh ≈ 100vh − (nav ~22vh + stage padding ~5vh + a small safety margin). */
  width: min(100%, calc(72vh * 16 / 9));
  background: var(--bg);
}

/* Video fills the frame exactly. With a 1080p (16:9) source the picture
 * fills edge-to-edge — no internal letterbox. If a future video has a
 * different aspect, object-fit:contain shows the cream surround instead
 * of black. */
#step-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--bg);
  display: block;
}

.video-missing {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  color: var(--dark);
  background: var(--bg);
  border: 2px dashed var(--red);
  border-radius: 18px;
  text-align: center;
  padding: 24px;
}
.video-missing p { margin: 0; font-size: clamp(20px, 3vw, 36px); }
.video-missing .video-missing-sub {
  font-size: clamp(14px, 1.6vw, 20px);
  opacity: 0.7;
}

/* ===== Network status toast ===== */
.net-status {
  position: fixed;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  background: rgba(0, 0, 0, 0.78);
  color: #fff;
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 14px;
  z-index: 9999;
  pointer-events: none;
  opacity: 0;
  transition: opacity 240ms ease;
}
.net-status[data-show] { opacity: 1; }

* ===== Reconnect update panel ===== */
.update-panel {
  position: fixed;
  right: clamp(8px, 1.5vw, 20px);
  bottom: clamp(8px, 1.5vh, 20px);
  width: min(380px, 92vw);
  background: rgba(20, 16, 12, 0.92);
  color: #fff;
  border-radius: 14px;
  padding: 12px 14px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
  z-index: 9998;
  font-size: 13px;
  line-height: 1.3;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 240ms ease, transform 240ms ease;
}
.update-panel[data-show] { opacity: 1; transform: translateY(0); }

.update-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}
.update-title { font-weight: 700; }
.update-summary { opacity: 0.8; font-size: 12px; }

.update-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 6px;
}

.update-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 4px 10px;
}
.update-row .update-label {
  grid-column: 1 / 2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.update-row .update-status {
  grid-column: 2 / 3;
  font-variant-numeric: tabular-nums;
  opacity: 0.85;
  font-size: 12px;
}
.update-row .update-progress {
  grid-column: 1 / -1;
  height: 4px;
  background: rgba(255, 255, 255, 0.14);
  border-radius: 999px;
  overflow: hidden;
}
.update-row .update-bar {
  height: 100%;
  width: 0%;
  background: var(--orange);
  transition: width 200ms ease;
}
.update-row[data-state="done"] .update-bar { background: #5dd47b; width: 100% !important; }
.update-row[data-state="skip"] .update-bar { background: rgba(255, 255, 255, 0.35); width: 100% !important; }
.update-row[data-state="error"] .update-bar { background: var(--red); width: 100% !important; }
.update-row[data-state="missing"] .update-bar { background: rgba(255, 255, 255, 0.18); width: 100% !important; }
.update-row[data-state="done"] .update-status { color: #5dd47b; }
.update-row[data-state="skip"] .update-status { opacity: 0.6; }
.update-row[data-state="error"] .update-status { color: #ff8a8a; }
.update-row[data-state="missing"] .update-status { opacity: 0.5; }