/* Zinit customer demo — page shell, chapter rail, stage scaling, cursor.

   Two palettes live in this package and they never mix. The page AROUND the
   stage (ground, chapter rail, caption, player) is Zinit marketing chrome and
   uses the 2026-08 ID kit, exactly as the investor tour does. Everything INSIDE
   the stage is a reproduction of the product at ai.zinit.com and uses the
   product's own palette from css/product.css, because a customer who later
   logs in should recognise what they were shown. Those product colours are on
   the `keep` list in brand/color-map.json with that reason. */

:root {
  --page-ink: #011e41;
  --page-muted: #8e92af;
  --page-soft: #b9bedb;
  --accent: #e83971;
  --accent-ink: #b02b56;
  --accent-grad: linear-gradient(135deg, #e83971, #b02b56);

  --fast: 140ms;
  --base-t: 220ms;
  --slow: 420ms;
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);

  --font: "Inter", "SF Pro Text", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "InterDisplay", "Inter", system-ui, sans-serif;

  /* Same ground as the investor tour: deep navy, one pink light from the top
     left, a navy lift on the right. */
  --ground:
    radial-gradient(78% 56% at 3% -12%, rgba(239, 116, 156, 0.30) 0%, rgba(239, 116, 156, 0) 58%),
    radial-gradient(70% 55% at 97% -2%, rgba(10, 53, 96, 0.95) 0%, rgba(10, 53, 96, 0) 62%),
    linear-gradient(165deg, #011e41 0%, #011425 62%, #011425 100%);
}

/* Inter is what the product renders in. One variable file covers 400-700;
   labs deploys standalone, so the fonts ship inside the package. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/inter-latin.woff2") format("woff2");
}
@font-face {
  font-family: "InterDisplay";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/inter-display-400.woff2") format("woff2");
}
@font-face {
  font-family: "InterDisplay";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/inter-display-600.woff2") format("woff2");
}
@font-face {
  font-family: "InterDisplay";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/inter-display-700.woff2") format("woff2");
}

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

html, body {
  height: 100%;
  background: #011425;
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
}

.page {
  height: 100dvh;
  background: var(--ground);
  display: flex; flex-direction: column;
  justify-content: center;
  padding: 14px clamp(14px, 2vw, 28px) 10px;
}

.page-head { text-align: center; margin-bottom: 10px; flex: none; }
.page-head .eyebrow {
  display: inline-block;
  font-size: 12.6px; font-weight: 600; letter-spacing: 0.14em;
  text-transform: uppercase; color: #f5a6bf;
  background: rgba(232, 57, 113, 0.16);
  border: 1px solid rgba(232, 57, 113, 0.30);
  padding: 4px 12px; border-radius: 999px; margin-bottom: 8px;
}
.page-head h1 {
  font-family: var(--font-display);
  color: #ffffff;
  font-size: clamp(20px, 2.4vw, 30px); line-height: 1.15; letter-spacing: -0.02em;
}
.page-head p { color: var(--page-soft); margin-top: 5px; font-size: 15.5px; max-width: 760px; margin-inline: auto; line-height: 1.5; }
@media (max-height: 860px) { .page-head p { display: none; } }
@media (max-height: 760px) { .page-head .eyebrow { display: none; } .page-head h1 { font-size: 19px; } }

/* ---- Chapter rail ---- */
.rail {
  display: flex; justify-content: center; gap: 4px;
  flex-wrap: wrap; margin: 0 0 10px; flex: none;
}
.rail button {
  appearance: none; border: 1px solid transparent; background: transparent;
  font: inherit; cursor: pointer; position: relative;
  display: flex; align-items: center; gap: 8px;
  padding: 9px 14px; border-radius: 999px;
  color: var(--page-muted); font-size: 15.4px; font-weight: 500;
  transition: background var(--base-t) var(--ease), color var(--base-t) var(--ease);
}
.rail button .n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.10); color: var(--page-soft);
  font-size: 13px; font-weight: 600;
  transition: inherit;
}
.rail button:hover { color: #fff; background: rgba(255, 255, 255, 0.08); }
.rail button.active { color: #fff; background: rgba(255, 255, 255, 0.12); }
.rail button.active .n { background: var(--accent-grad); color: #fff; }
.rail button.done .n { background: rgba(86, 143, 50, 0.28); color: #ffffff; }
.rail button .bar {
  position: absolute; left: 14px; right: 14px; bottom: 4px; height: 2px;
  border-radius: 2px; background: rgba(255, 255, 255, 0.10); overflow: hidden; opacity: 0;
}
.rail button.active .bar { opacity: 1; }
.rail button .bar i { display: block; height: 100%; width: 0%; background: var(--accent-grad); border-radius: 2px; }

/* ---- Stage ----
   A fixed 1440x810 design surface: the width the product was recorded at, at
   16:9, so a full-screened window is the app at its real density. Scaled by
   engine.js to whatever space is left. */
.stage-frame {
  background: transparent; padding: 0;
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  position: relative; margin-inline: auto; width: 100%;
}
body.is-fs .page { padding: 10px 14px; }
body.is-fs .page-head, body.is-fs .sim-footnote { display: none; }
body.is-fs .rail { margin: 0 0 8px; }
body.is-fs .rail button { padding: 6px 12px; font-size: 14px; }

.player {
  flex: none; display: flex; align-items: center; gap: 10px;
  margin-top: 8px; padding: 0 2px;
}
.player .pp, .player .fs-btn {
  width: 30px; height: 30px; border-radius: 8px; border: none; cursor: pointer;
  background: rgba(255, 255, 255, 0.12); color: #f5a6bf;
  display: flex; align-items: center; justify-content: center; flex: none;
  transition: background var(--fast), color var(--fast);
}
.player .pp:hover, .player .fs-btn:hover { background: rgba(255, 255, 255, 0.24); color: #fff; }
.player .pp.snd.armed { background: rgba(232, 57, 113, 0.22); color: #ffffff; }
.tl { flex: 1; height: 22px; display: flex; align-items: center; cursor: pointer; touch-action: none; }
.tl-track { width: 100%; height: 4px; border-radius: 999px; background: rgba(255, 255, 255, 0.16); position: relative; }
.tl-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0%; border-radius: 999px; background: var(--accent-grad); }
.tl-tick { position: absolute; top: -2px; bottom: -2px; width: 2px; border-radius: 1px; background: rgba(255, 255, 255, 0.38); }
.tl-knob {
  position: absolute; top: 50%; left: 0%;
  width: 12px; height: 12px; border-radius: 50%; background: #fff;
  transform: translate(-50%, -50%); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
}
body.record .player { display: none; }

.stage-scaler { flex: 1; min-height: 0; width: 100%; position: relative; }
.stage {
  width: 1440px; height: 810px;
  background: var(--p-canvas);
  border-radius: 12px;
  overflow: hidden;
  position: absolute; left: 50%; top: 50%;
  transform-origin: center center;
  box-shadow:
    0 2px 6px rgba(0, 0, 0, 0.35),
    0 34px 90px rgba(0, 0, 0, 0.45),
    0 0 80px rgba(232, 57, 113, 0.16);
}

.scene { position: absolute; inset: 0; display: none; }
.scene.on { display: flex; flex-direction: column; }

/* The caption is the presenter's line for each step. Fixed height so a
   two-line caption cannot rescale the stage mid-sentence. */
.stage-caption {
  margin-top: 12px; text-align: center; flex: none;
  font-family: var(--font-display);
  color: #ffffff; font-size: 20px; font-weight: 600; line-height: 1.35;
  letter-spacing: -0.01em;
  height: 56px; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  max-width: 980px; margin-inline: auto;
  transition: opacity var(--slow) var(--ease);
}
.stage-caption.hide { opacity: 0; }
/* Narration captions (v2): one line of at most five words, the word being
   spoken in the kit pink, painted from the clock by the engine. */
.stage-caption .cw { transition: color 120ms linear; }
.stage-caption .cw.on { color: var(--accent); }

.sim-footnote {
  text-align: center; color: var(--page-muted); font-size: 12.8px; margin-top: 7px; flex: none;
}

/* ---- Motion primitives used by the engine and the scenes ---- */
.b-hidden { opacity: 0 !important; pointer-events: none; }
.b-in { animation: bIn var(--slow) var(--ease) both; }
@keyframes bIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.b-pop { animation: bPop 320ms var(--ease) both; }
@keyframes bPop { 0% { transform: scale(0.94); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
.b-fade { animation: bFade var(--slow) var(--ease) both; }
@keyframes bFade { from { opacity: 0; } to { opacity: 1; } }

.type-caret::after {
  content: ""; display: inline-block; width: 1px; height: 1em;
  background: currentColor; margin-left: 1px; vertical-align: -0.12em;
  animation: caret 0.8s steps(1) infinite;
}
@keyframes caret { 50% { opacity: 0; } }

/* ---- Simulated cursor ---- */
.sim-cursor {
  position: absolute; left: 0; top: 0; z-index: 90;
  pointer-events: none; opacity: 0;
  /* Starts in open space below the SOP card, near the first thing it presses,
     minus the tip offset; it used to sit half off the bottom-right corner,
     which on the video's first frame (its thumbnail) read as cut off. After
     its first move it stays wherever its last action ended (engine.js). */
  transform: translate(1150px, 440px);
  transition: transform 480ms cubic-bezier(0.3, 0.7, 0.3, 1), opacity 240ms;
  filter: drop-shadow(0 3px 7px rgba(0, 0, 0, 0.35));
  will-change: transform;
}
.sim-cursor.on { opacity: 1; }
.sim-cursor-idle { display: block; will-change: transform; }
.sim-cursor.press svg { transform: scale(0.86); }
.sim-cursor svg { transition: transform 140ms var(--ease); display: block; }
.sim-ripple {
  position: absolute; z-index: 85; pointer-events: none;
  width: 10px; height: 10px; margin: -5px 0 0 -5px; border-radius: 50%;
  border: 2px solid var(--p-violet);
  animation: simRipple 0.6s var(--ease) forwards;
}
@keyframes simRipple {
  from { transform: scale(0.6); opacity: 0.9; }
  to { transform: scale(4); opacity: 0; }
}

/* ---- Embed mode (?embed=1): white page, stage separates on shadow alone ---- */
body.embed, body.embed .page { background: #ffffff; }
body.embed .page-head, body.embed .sim-footnote { display: none; }
body.embed .page { padding: 12px; }
body.embed .rail { margin: 0 0 12px; }
body.embed .rail button { color: #6a6f8c; }
/* The phone note's page-soft lavender is set for the dark standalone page; on
   the white embed it measured 1.9:1 (Gemini review of /demos, 2026-10-05). The
   embed's own grey is about 5:1. */
body.embed .phone-note { color: #6a6f8c; }
body.embed .rail button .n { background: #e4e6f7; color: #6a6f8c; }
body.embed .rail button:hover { color: #011e41; background: #ffffff; }
body.embed .rail button.active { color: #011e41; background: #ffffff; border-color: #e4e6f7; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08); }
body.embed .rail button.done .n { background: rgba(86, 143, 50, 0.16); color: #568f32; }
body.embed .stage { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10), 0 18px 40px rgba(0, 0, 0, 0.14), 0 44px 100px rgba(0, 0, 0, 0.12); }
body.embed .stage-caption { color: #011e41; }
body.embed .player .pp, body.embed .player .fs-btn { background: rgba(0, 0, 0, 0.06); color: #b02b56; }
body.embed .tl-track { background: rgba(0, 0, 0, 0.12); }
body.embed .tl-tick { background: rgba(0, 0, 0, 0.28); }
body.embed .tl-knob { background: #011e41; }

/* ---- The narrator's highlight (v2) ----
   Marks the part of the screen the narration is naming (engine.js). Kit pink,
   so it reads as the walkthrough's marker rather than a product control. The
   spotlight's navy dim over the rest of the stage is a spread shadow that the
   stage's own overflow clips. */
.hl-ring {
  position: absolute; left: 0; top: 0; width: 0; height: 0; z-index: 80;
  pointer-events: none; opacity: 0;
  border: 3px solid var(--accent); border-radius: 12px;
  box-shadow: 0 0 0 4px rgba(232, 57, 113, 0.16), 0 0 26px rgba(232, 57, 113, 0.34);
  transition: transform 340ms var(--ease), width 340ms var(--ease), height 340ms var(--ease), opacity 260ms linear;
}
.hl-ring.on { opacity: 1; }
.hl-ring.snap { transition: opacity 260ms linear; }
.hl-ring[data-mode="spot"] {
  box-shadow: 0 0 0 4px rgba(232, 57, 113, 0.16), 0 0 26px rgba(232, 57, 113, 0.34), 0 0 0 2400px rgba(1, 30, 65, 0.34);
}

/* ---- Brand cards (v3) ----
   The opening title under the first line and the end card under the last
   two: kit navy with the page's pink light, and the white wordmark file (the
   logo is an asset, never typeset). They sit above the product and the
   pointer. */
.brandcard {
  position: absolute; inset: 0; z-index: 95;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 34px;
  background: radial-gradient(ellipse 70% 55% at 50% -12%, rgba(232, 57, 113, 0.30), transparent 70%), #011e41;
  color: #ffffff; text-align: center;
  transition: opacity 650ms var(--ease);
}
.brandcard.out { opacity: 0; }
.brandcard .bc-logo { width: 380px; height: auto; }
.brandcard .bc-sub { font-family: var(--font-display); font-size: 21px; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(255, 255, 255, 0.7); }
.brandcard .bc-line { font-family: var(--font-display); font-size: 50px; font-weight: 600; line-height: 1.16; letter-spacing: -0.015em; max-width: 1060px; text-wrap: balance; }
#endLogo { width: 300px; opacity: 0; transform: translateY(12px) scale(0.96); transition: opacity 500ms var(--ease), transform 650ms var(--ease); }
#endLogo.on { opacity: 1; transform: none; }

/* ---- "Play with sound" gate (v2) ----
   A browser refuses to start sound before the visitor has interacted with
   the page, so a cold load holds on the first frame behind this button
   (engine.js, Narration track). Adapted from the investor tour's gate, in
   kit colours. It sits on the stage scaler ABOVE the stage: v1 never showed
   the gate (its sound was opt-in) and had no rule for it, so in v2's first
   test the product sidebar lay over the button and swallowed the click. */
.play-gate {
  position: absolute; inset: 0; z-index: 70;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  background: rgba(1, 30, 65, 0.52);
  border-radius: 14px;
}
.play-gate .pg-btn {
  width: 84px; height: 84px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--accent); color: #ffffff;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 18px 44px rgba(1, 30, 65, 0.55);
  transition: transform var(--fast) var(--ease);
}
.play-gate:hover .pg-btn { transform: scale(1.06); }
.play-gate .pg-lbl {
  position: absolute; top: calc(50% + 58px); left: 50%;
  transform: translateX(-50%); white-space: nowrap;
  font-family: var(--font-display);
  color: #ffffff; font-size: 17px; font-weight: 600; letter-spacing: -0.01em;
  text-shadow: 0 2px 12px rgba(1, 30, 65, 0.7);
}
body.record .play-gate { display: none; }

/* ---- Record mode (?record=1): the stage IS the take ---- */
body.record .page-head, body.record .rail, body.record .sim-footnote { display: none; }
body.record .page { padding: 0; height: 100vh; }
body.record .stage { border-radius: 0; box-shadow: none; }
/* A take burns its captions in, in the operator's default for every video
   (2026-09-26, systems/content-engine/video/VOICEOVER-AND-CAPTIONS.md): one
   line of at most five words, white bold type with a thin dark outline and a
   soft shadow, the spoken word in pink, and the whole line at 80% opacity, no
   box. The engine already paints the words from the clock; this only moves
   the line onto the picture. */
body.record .stage-caption {
  position: absolute; left: 0; right: 0; bottom: 54px; z-index: 5;
  height: auto; max-width: none; margin: 0; pointer-events: none;
  font-size: 46px; font-weight: 700; line-height: 1.2; letter-spacing: -0.005em;
  /* A solid outline painted under the fill keeps the words legible over busy
     rows, where a soft shadow alone let the text behind show through. */
  -webkit-text-stroke: 7px rgba(1, 30, 65, 0.92); paint-order: stroke fill;
  text-shadow: 0 3px 14px rgba(1, 30, 65, 0.5);
  opacity: 0.8;
}
body.record.nocap .stage-caption { display: none; }
/* Caption plates for compositing (?record=1&captions=1&plate=black|white):
   everything but the captions is hidden over one flat colour. */
html.plate, html.plate body, html.plate .stage-scaler,
html.plate .stage { background: var(--plate) !important; box-shadow: none !important; }
html.plate .stage * { visibility: hidden !important; }

/* ---- Mobile: scrolling page, numbers-only rail ----
   The caption's fixed two-line box exists so the stage never rescales
   mid-sentence. On a phone the page scrolls and the stage is width-fitted, so
   that reason is gone, and at phone width a caption wraps to three or four
   lines that the fixed box clipped top and bottom (preview, 2026-09-30). */
.phone-note { display: none; text-align: center; color: var(--page-soft); font-size: 13.5px; line-height: 1.45; margin: 0 8px 10px; }
@media (max-width: 700px) {
  .page { height: auto; display: block; padding-bottom: 40px; }
  .stage-frame { display: block; }
  .rail { gap: 2px; }
  .rail button { padding: 8px 10px; }
  .rail button span:not(.n):not(.bar) { display: none; }
  .rail button .bar { left: 8px; right: 8px; }
  .stage-caption { height: auto; font-size: 16px; line-height: 1.4; padding: 0 4px; margin-top: 10px; }
  .phone-note { display: block; }
}

@media (prefers-reduced-motion: reduce) {
  .b-in, .b-pop, .b-fade { animation: none !important; }
  .sim-cursor, .sim-ripple { display: none !important; }
  * { transition-duration: 0.01ms !important; }
}

/* Dev timing HUD (?timer=1) — never inside .stage, so recordings cannot pick it up. */
.sim-hud {
  position: fixed; top: 12px; right: 12px; z-index: 999;
  display: flex; align-items: center; gap: 10px;
  background: rgba(1, 20, 37, 0.92); color: #fff;
  font-family: "SF Mono", ui-monospace, Menlo, monospace;
  font-size: 12.5px; padding: 8px 13px; border-radius: 9px;
  pointer-events: none;
}
.sim-hud b { color: #f5a6bf; font-weight: 700; }
.sim-hud span { color: #f9c8d7; }
