/* ============================================================================
   Vyin AI · Robot Lobby UI — Components
   ----------------------------------------------------------------------------
   依賴 tokens.css。所有 class 以 kv- 開頭，BEM：kv-block__element--modifier。

   四層分工：
   · 原語  kv-grow-ring / kv-dot / kv-eyebrow / kv-art / kv-hero
             被多個元件共用的最小單位，改一處全部跟著變。
   · 元件  kv-<component>      只管長相，可以放在任何容器裡。
   觸控規則：可以按的一律是底部的 kv-actions（跟 kv-pill 同一格）；safe area 的卡片永遠不可按。
   · 位置  kv-at-<slot>         把元件放到 1280×800 格線上的固定位置。
   · 版型  kv-screen--<template> 四種畫面骨架，直接子元件自動落到格線，不必再寫 kv-at-*。

   參考稿：design_handoff_vyin_robot_lobby/Vyin Robot Lobby UI.dc.html（2026-09-30）。
   所有數值請看 tokens.css 的來源註記。
   ============================================================================ */

.kv-screen,
.kv-screen *,
.kv-screen::before,
.kv-screen::after,
.kv-side,
.kv-side *,
[class^='kv-'],
[class^='kv-'] * {
  box-sizing: border-box;
}

/* ============================================================== Canvases */

/* Center 1280×800 */
.kv-screen {
  position: relative;
  width: var(--kiosk-center-w);
  height: var(--kiosk-center-h);
  overflow: hidden;
  background: var(--kiosk-surface-base);
  color: var(--kiosk-text-primary);
  font-family: var(--kiosk-font-ui);
  -webkit-font-smoothing: antialiased;
}

/* Side F（前，跟 Center 同面）/ Side B（後，背面）1080×1920 */
.kv-side {
  position: relative;
  width: var(--kiosk-side-w);
  height: var(--kiosk-side-h);
  overflow: hidden;
  background: var(--kiosk-surface-base);
  color: var(--kiosk-text-primary);
  font-family: var(--kiosk-font-ui);
  -webkit-font-smoothing: antialiased;
}

/* Kebbi 臉 1024×600 · proposal（示意，非 Kebbi 實際表情）
   Kebbi 是女媧機器人，表情由它的 SDK 控制、能改多少待實機確認。這個元件只用來在
   原型與矩陣裡示意「哪個畫面對應哪個表情」，不是要廠商重畫 Kebbi 的臉。
   data-emotion：idle / listen / think / speak / countdown / happy / sorry / sleep（對照表見 screens.html 頁尾）
   data-mic：full / cmd / off / dot，驅動臉下方的光條（FOCUS 時收音狀態只靠這條）。 */
.kv-face {
  position: relative;
  width: var(--kiosk-face-w);
  height: var(--kiosk-face-h);
  overflow: hidden;
  background: var(--kiosk-surface-base);
  color: var(--kiosk-text-primary);
  font-family: var(--kiosk-font-display);
}
.kv-face__eyes {
  position: absolute;
  inset: 0 0 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 176px;
  transition:
    transform var(--kiosk-dur-rise) ease,
    translate 900ms cubic-bezier(0.33, 1, 0.68, 1); /* translate = 視線（Micro Moments 01） */
}
.kv-face__eye {
  display: block;
  width: 160px;
  height: 208px;
  border-radius: 80px;
  background: var(--kiosk-text-primary);
  box-sizing: border-box;
  transform-origin: 50% 50%;
  transition:
    width var(--kiosk-dur-rise) ease,
    height var(--kiosk-dur-rise) ease,
    border-radius var(--kiosk-dur-rise) ease,
    transform var(--kiosk-dur-rise) ease,
    opacity var(--kiosk-dur-rise) ease,
    background var(--kiosk-dur-rise) ease,
    box-shadow var(--kiosk-dur-rise) ease;
  animation: kv-face-blink 4.2s ease-in-out infinite;
}
.kv-face__eye:last-child {
  animation-delay: 60ms;
}
.kv-face__mouth {
  position: absolute;
  left: 50%;
  bottom: 112px;
  width: 0;
  height: 20px;
  border-radius: 10px;
  background: var(--kiosk-text-primary);
  transform: translateX(-50%);
  opacity: 0;
  transition:
    width var(--kiosk-dur-rise) ease,
    opacity var(--kiosk-dur-rise) ease;
}
.kv-face__digit {
  position: absolute;
  inset: 0 0 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  font: 800 360px/1 var(--kiosk-font-display);
  opacity: 0;
  transform: scale(0.8);
  transition:
    opacity var(--kiosk-dur-fade) ease,
    transform var(--kiosk-dur-fade) ease;
}
/* 光條：收音狀態。沒有 data-mic 時不顯示。 */
.kv-face__bar {
  position: absolute;
  left: 50%;
  bottom: 32px;
  width: 480px;
  height: 12px;
  border-radius: 6px;
  background: var(--kiosk-text-disabled);
  transform: translateX(-50%);
  opacity: 0;
  transition:
    width var(--kiosk-dur-chrome) ease,
    background var(--kiosk-dur-chrome) ease,
    box-shadow var(--kiosk-dur-chrome) ease,
    opacity var(--kiosk-dur-chrome) ease;
}
.kv-face[data-mic] .kv-face__bar {
  opacity: 1;
}
.kv-face[data-mic='full'] .kv-face__bar {
  background: var(--kiosk-grow-2);
  box-shadow: var(--kiosk-glow-line);
}
.kv-face[data-mic='cmd'] .kv-face__bar {
  width: 240px;
  background: var(--kiosk-grow-2);
}
.kv-face[data-mic='dot'] .kv-face__bar {
  width: 24px;
  background: var(--kiosk-grow-2);
  box-shadow: var(--kiosk-glow-line);
}
.kv-face[data-mic='off'] .kv-face__bar {
  background: var(--kiosk-text-disabled);
}
/* 動作（一次性）：data-gesture="nod" 眼睛往下點一下再回來，播完由 JS 移除屬性。迎賓 / 道別觸發、掃碼完成用。 */
.kv-face[data-gesture='nod'] .kv-face__eyes {
  animation: kv-face-nod 700ms ease-in-out;
}
@keyframes kv-face-nod {
  0%,
  100% {
    translate: 0 0;
  }
  40% {
    translate: 0 56px;
  }
}
/* 表情 */
.kv-face[data-emotion='listen'] .kv-face__eye {
  transform: scale(1.12);
  box-shadow: var(--kiosk-glow-listen);
  animation: none;
}
.kv-face[data-emotion='think'] .kv-face__eyes {
  transform: translate(56px, -48px);
}
.kv-face[data-emotion='think'] .kv-face__eye {
  animation: kv-face-float 1.8s ease-in-out infinite;
}
.kv-face[data-emotion='think'] .kv-face__eye:last-child {
  transform: scale(0.82);
  animation-delay: 200ms;
}
.kv-face[data-emotion='speak'] .kv-face__mouth {
  width: 160px;
  opacity: 1;
  animation: kv-face-speak 420ms ease-in-out infinite alternate;
}
.kv-face[data-emotion='countdown'] .kv-face__eye {
  opacity: 0;
  animation: none;
}
.kv-face[data-emotion='countdown'] .kv-face__digit {
  opacity: 1;
  transform: scale(1);
}
.kv-face[data-emotion='happy'] .kv-face__eye {
  height: 96px;
  border-radius: 80px 80px 0 0;
  background: transparent;
  border: 32px solid var(--kiosk-text-primary);
  border-bottom: 0;
  transform: translateY(-16px);
  animation: none;
}
.kv-face[data-emotion='sorry'] .kv-face__eye {
  height: 136px;
  transform: rotate(-14deg) translateY(24px);
  animation: none;
}
.kv-face[data-emotion='sorry'] .kv-face__eye:last-child {
  transform: rotate(14deg) translateY(24px);
}
.kv-face[data-emotion='sleep'] .kv-face__eye {
  height: 28px;
  opacity: 0.5;
  animation: none;
}
@keyframes kv-face-blink {
  0%,
  93%,
  100% {
    transform: scaleY(1);
  }
  96% {
    transform: scaleY(0.08);
  }
}
@keyframes kv-face-float {
  0%,
  100% {
    translate: 0 0;
  }
  50% {
    translate: 0 -16px;
  }
}
@keyframes kv-face-speak {
  from {
    width: 120px;
    height: 16px;
  }
  to {
    width: 220px;
    height: 36px;
  }
}

/* ============================================================== Primitives
   ---------------------------------------------------------------------------- */

/* Grow 外框 · 雙背景 padding-box / border-box。
   --kv-ring-w 邊寬、--kv-ring-fill 內底。下列元件共用同一段，只覆寫這兩個變數。 */
.kv-grow-ring,
.kv-btn,
.kv-pill.kv-pill--listening,
.kv-qr.kv-qr--active,
.kv-cmd.kv-cmd--ok,
.kv-photo {
  --kv-ring-w: var(--kiosk-grow-border);
  --kv-ring-fill: var(--kiosk-surface-raised);
  border: var(--kv-ring-w) solid transparent;
  background:
    linear-gradient(var(--kv-ring-fill), var(--kv-ring-fill)) padding-box,
    var(--kiosk-grow) border-box;
}

/* 光點 · 圓 + 底色 + 光環。--kv-dot 直徑。 */
.kv-dot,
.kv-mic__dot,
.kv-toast__dot,
.kv-orb {
  --kv-dot: var(--kiosk-mic-dot);
  width: var(--kv-dot);
  height: var(--kv-dot);
  border-radius: 50%;
  flex: none;
}
.kv-dot--full,
.kv-mic--full .kv-mic__dot {
  background: var(--kiosk-grow);
  box-shadow: var(--kiosk-halo-full);
}
.kv-dot--command,
.kv-mic--command .kv-mic__dot {
  background: var(--kiosk-warning);
  box-shadow: var(--kiosk-halo-command);
}
.kv-dot--off,
.kv-mic--off .kv-mic__dot,
.kv-toast__dot {
  background: var(--kiosk-text-disabled);
  box-shadow: none;
}
/* 思考光點 32 · 脈動 .8↔1.1、900ms */
.kv-dot--orb,
.kv-orb {
  --kv-dot: var(--kiosk-orb);
  background: var(--kiosk-grow);
  box-shadow: var(--kiosk-orb-shadow);
  animation: kv-pulse var(--kiosk-dur-pulse) ease-in-out infinite alternate;
}
@keyframes kv-pulse {
  from {
    transform: scale(0.8);
  }
  to {
    transform: scale(1.1);
  }
}

/* Campaign eyebrow · 「現正熱映」。唯一允許用 campaign 色的文字。 */
.kv-eyebrow {
  font: var(--kiosk-type-eyebrow);
  letter-spacing: 0.08em;
  color: var(--kiosk-camp);
  white-space: nowrap;
}

/* 全幅素材層 · 正式素材放 <img> / <video> 進去。 */
.kv-art,
.kv-side__art {
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 0;
}
.kv-art--upper,
.kv-side__art--upper {
  bottom: 420px; /* Side · 上半素材、下半留給邀請（v0.9 後未使用） */
}
.kv-art > img,
.kv-art > video,
.kv-side__art > img,
.kv-side__art > video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* =========================================================== Slideshow
   劇照輪播：多張 img 交替淡入，3s 間隔、1s fade。
   用法：<div class="kv-art kv-slideshow"><img class="kv-slideshow__slide kv-slideshow__slide--active" ...> */
.kv-slideshow__slide {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 1s ease;
}
.kv-slideshow__slide--active {
  opacity: 1;
}

/* Hero 文字堆 · Welcome / Exit / Moving 封面的大標組。 */
.kv-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 40px;
  text-align: center;
}
.kv-hero--left {
  align-items: flex-start;
  text-align: left;
  gap: var(--kiosk-space-6);
}
.kv-hero__eyebrow {
  font: var(--kiosk-type-hero-eyebrow);
  color: var(--kiosk-text-secondary);
}
.kv-hero__eyebrow--active {
  color: var(--kiosk-text-primary); /* 觸發時整句亮起 */
  animation: kv-brighten var(--kiosk-dur-fade) ease-out;
}
/* 觸發句亮起：從暗、微下方浮上來。eyebrow / sub 共用。 */
@keyframes kv-brighten {
  from {
    opacity: 0.3;
    translate: 0 8px;
  }
}
.kv-hero__title {
  font: var(--kiosk-type-hero-lg);
  color: var(--kiosk-text-primary);
}
.kv-hero__title--xl {
  font: var(--kiosk-type-hero-xl);
}
.kv-hero__sub {
  font: var(--kiosk-type-hero-sub);
  color: var(--kiosk-text-secondary);
}
.kv-hero__sub--active {
  color: var(--kiosk-text-primary);
  animation: kv-brighten var(--kiosk-dur-fade) ease-out;
}
.kv-hero__meta {
  font: var(--kiosk-type-hero-meta);
  color: var(--kiosk-text-muted-light);
}

/* Grow 細線 240×6 · Welcome 觸發時 --wide 960 + 綠光 */
.kv-line {
  width: 240px;
  height: 6px;
  border-radius: 3px;
  background: var(--kiosk-grow);
  flex: none;
}
.kv-line--wide {
  width: 960px;
  box-shadow: var(--kiosk-glow-line);
  animation: kv-line-grow var(--kiosk-dur-rise) ease-out; /* 觸發時從 240 長到 960、綠光亮起 */
}
@keyframes kv-line-grow {
  from {
    width: 240px;
    box-shadow: none;
  }
}

/* ============================================================ Placeholder
   素材佔位：斜紋 + mono 標籤。正式素材進來後整個換掉。 */
.kv-ph {
  position: relative;
  background:
    repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.07) 0 2px, transparent 2px 18px),
    var(--kiosk-camp-bg);
}
.kv-ph--neutral {
  background:
    repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.07) 0 2px, transparent 2px 18px),
    var(--kiosk-border);
}
.kv-ph--camera {
  background:
    repeating-linear-gradient(135deg, rgba(255, 255, 255, 0.07) 0 2px, transparent 2px 18px),
    var(--kiosk-raw-camera-bg);
}
/* 佔位層疊在滿版容器上時，容器的 absolute 要贏過 .kv-ph 的 relative */
.kv-ph.kv-art,
.kv-ph.kv-side__art,
.kv-ph.kv-camera {
  position: absolute;
}
.kv-ph__label {
  position: absolute;
  left: 32px;
  bottom: 28px;
  font: var(--kiosk-type-annot-sm);
  color: rgba(255, 255, 255, 0.5);
  white-space: nowrap;
}
.kv-ph__label--top {
  top: 32px;
  bottom: auto;
  left: 40px;
}
.kv-ph__label--center {
  left: 50%;
  bottom: auto;
  top: 50%;
  transform: translate(-50%, -50%);
  font: var(--kiosk-type-annot);
}
.kv-ph__label--corner {
  left: auto;
  right: var(--kiosk-margin);
  top: 150px;
  bottom: auto;
  font: var(--kiosk-type-annot);
}

/* ================================================================ Top bar */
.kv-topbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: var(--kiosk-topbar-h);
}
.kv-topbar--countdown {
  height: var(--kiosk-topbar-count-h);
}
.kv-topbar__left {
  display: flex;
  align-items: center;
  gap: var(--kiosk-space-6);
}
.kv-topbar__meta {
  display: flex;
  align-items: baseline;
  gap: 20px;
}
.kv-logo {
  font: var(--kiosk-type-logo);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
}
.kv-logo--on-media {
  text-shadow: var(--kiosk-text-shadow-logo);
}
.kv-date {
  font: var(--kiosk-type-date);
  color: var(--kiosk-text-secondary);
  white-space: nowrap;
}
.kv-clock {
  font: var(--kiosk-type-clock);
  color: var(--kiosk-text-primary);
}

/* ======================================================= Mic status chip
   Layer 1 · 常駐收音狀態。三態互斥；光點樣式見 Primitives。 */
.kv-mic {
  display: flex;
  align-items: center;
  gap: var(--kiosk-space-3);
}
.kv-mic__label {
  font: var(--kiosk-type-mic);
  color: var(--kiosk-text-secondary);
  white-space: nowrap;
}
/* 壓在媒體上時包一層半透明膠囊 */
.kv-mic--on-media {
  background: var(--kiosk-overlay-media);
  border-radius: var(--kiosk-radius-pill);
  padding: 8px 16px 8px 12px;
}

/* 光條 fallback：只留光點、不帶文字（Focus 層級、Kebbi 光條不可用時） */
.kv-mic--dot .kv-mic__label {
  display: none;
}

/* ============================================================ Hint line
   「重要且常用」的語音指令提示，一次一句，放在底部對話框那格（對話框隱藏時）。
   用在 P03「等一下」與 P06/P07「再拍一次」。辨識到指令時由 .kv-cmd 取代。derived。 */
.kv-hint {
  font: var(--kiosk-type-hint);
  color: var(--kiosk-text-secondary);
  white-space: nowrap;
  text-shadow: var(--kiosk-text-shadow-logo);
}
/* 底部那格被內容用掉時（Review 頁照片到 y 1016），提示放進 QR 卡白板下方 */
.kv-qr > .kv-hint {
  text-shadow: none;
  color: var(--kiosk-text-tertiary);
}
/* 取像告知（法務 2026-10-14：一行小字即可，不需要同意按鈕）：P06 放最底下置中的一小條，不進 QR 卡也不進照片卡（設計師 2026-10-14） */
.kv-screen > .kv-hint.kv-hint--legal {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 36px;
  transform: none;
  text-align: center;
  color: var(--kiosk-text-disabled);
  font-size: 18px;
  line-height: 1;
  text-shadow: none;
  z-index: 5;
}
/* 有置底小條的畫面（P06）：卡片縮一點讓出呼吸空間——相紙 600 → 552 寬（約 410 高）、QR xl 456 → 416；小條在 bottom 36，離卡片約 34、離底 36（設計師 2026-10-14：太貼底） */
.kv-screen:has(> .kv-hint--legal) > .kv-safe > .kv-polaroid--review {
  width: 552px;
}
.kv-screen:has(> .kv-hint--legal) > .kv-safe > .kv-qr--xl {
  height: 416px;
}

/* ============================================================ Route pill
   Attraction Moving · 右上「移動中 · 前往 B 點」，三個站點小圓。derived。 */
.kv-route {
  display: inline-flex;
  align-items: center;
  gap: var(--kiosk-space-4);
  padding: 10px 22px 10px 14px;
  border-radius: var(--kiosk-radius-pill);
  background: var(--kiosk-overlay-media);
}
.kv-route__dots {
  display: flex;
  gap: var(--kiosk-wave-gap);
}
.kv-route__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--kiosk-raw-dot-future);
}
.kv-route__dot--done {
  background: var(--kiosk-text-primary);
}
.kv-route__dot--next {
  background: var(--kiosk-text-tertiary);
}
.kv-route__text {
  font: var(--kiosk-type-route);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
}

/* =========================================================== AI transcript
   沒有標籤、沒有頭像：位置就是身份。已說出 primary，未說出 disabled。 */
.kv-transcript {
  font: var(--kiosk-type-transcript);
  color: var(--kiosk-text-primary);
  max-height: var(--kiosk-ai-h);
  overflow: hidden;
  text-wrap: pretty;
}
.kv-transcript--one-line {
  max-height: 72px;
}
.kv-transcript__unspoken {
  color: var(--kiosk-text-disabled);
}
.kv-transcript__interrupted {
  color: var(--kiosk-border);
  transition: color var(--kiosk-dur-rise) var(--kiosk-ease);
}
.kv-transcript__hint {
  color: var(--kiosk-text-secondary);
}
/* Karaoke 逐字亮：已說出的字用主色，剩餘維持 disabled */
.kv-karaoke__done {
  color: var(--kiosk-text-primary);
}
.kv-karaoke__rest {
  color: var(--kiosk-text-disabled);
}
.kv-transcript__unspoken--done {
  color: var(--kiosk-text-primary);
}
/* 全螢幕媒體上的字幕版 */
.kv-transcript--caption {
  font: var(--kiosk-type-caption);
  max-height: none;
  text-shadow: var(--kiosk-text-shadow-media);
}
/* 預告字幕：停 3s 後 400ms 淡出，讓人專心看片（README：caption fades after 3s）。
   重新加上 class 就會重播；樣式指南捲到該畫面時會重播一次。 */
.kv-transcript--fade {
  animation: kv-caption-out 400ms var(--kiosk-ease) var(--kiosk-dur-caption) forwards;
}
@keyframes kv-caption-out {
  to {
    opacity: 0;
  }
}

/* ========================================================= Status (思考)
   放在 AI 區同一位置或其下緣。延遲 > 0.8s 才顯示。 */
.kv-status {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 48px;
  padding-left: var(--kiosk-space-3);
}
.kv-status__label {
  font: var(--kiosk-type-status);
  color: var(--kiosk-text-secondary);
  white-space: nowrap;
}

/* ===================================================== Sentence progress
   回答超過 2 行時拆句；3 段 48×8，目前句用 Grow。 */
.kv-progress {
  display: flex;
  gap: var(--kiosk-space-3); /* derived */
  align-items: center;
}
.kv-progress__seg {
  width: var(--kiosk-progress-w);
  height: var(--kiosk-progress-h);
  border-radius: 4px;
  background: var(--kiosk-border);
}
.kv-progress__seg--active {
  background: var(--kiosk-grow);
}

/* ======================================================= User dialog pill
   Layer 2 · 召喚式對話框。沒有「你」標籤。 */
.kv-pill {
  display: flex;
  align-items: center;
  gap: 20px;
  width: var(--kiosk-pill-w);
  height: var(--kiosk-pill-h);
  padding: 0 var(--kiosk-pill-pad-x);
  border-radius: var(--kiosk-radius-pill);
  background: var(--kiosk-surface-raised);
  box-shadow: inset 0 0 0 2px var(--kiosk-border);
}
.kv-pill__placeholder {
  flex: 1;
  font: var(--kiosk-type-user-pill);
  color: var(--kiosk-text-tertiary);
  white-space: nowrap;
  overflow: hidden;
}
/* 聆聽中：Grow 4px 外框（見 Primitives）+ 光暈，高 96，即時逐字稿 + 游標 + 波形 */
.kv-pill--listening {
  height: var(--kiosk-pill-h-listen);
  gap: var(--kiosk-space-6);
  box-shadow: var(--kiosk-glow-listen);
}
.kv-pill__live {
  flex: 1;
  display: flex;
  align-items: center;
  gap: var(--kiosk-space-2);
  font: var(--kiosk-type-user-live);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
  overflow: hidden;
}
.kv-caret {
  width: var(--kiosk-caret-w);
  height: var(--kiosk-caret-h);
  border-radius: 2px;
  background: var(--kiosk-text-primary);
  flex: none;
  animation: kv-blink 1s steps(1) infinite;
}
@keyframes kv-blink {
  50% {
    opacity: 0;
  }
}
/* Photo idle：標題用 hero 字級，底部獨立 CTA 按鈕 + 小提示 */
.kv-transcript--hero {
  font: var(--kiosk-type-transcript-hero);
  max-height: 168px; /* 64px × 1.3 × 2 行 = 166.4 */
}
.kv-cta-hint {
  font: var(--kiosk-type-cta-hint);
  color: var(--kiosk-text-secondary);
}

/* ============================================================ Action bar
   觸控規則（設計師 2026-09-30 定案）：**可以按的東西一律住在底部對話框那一格**，
   語音時是 .kv-pill，觸控時是 .kv-actions；safe area 只放資訊，卡片永遠不可按。
   1280×144、按鈕等寬、主要選項在最右、一屏一個。按下：填色升一階 + 縮 97%、120ms。 */
.kv-actions {
  display: flex;
  gap: var(--kiosk-actions-gap);
  width: var(--kiosk-pill-w);
  height: var(--kiosk-pill-h-listen);
}
.kv-actions__btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--kiosk-space-3);
  border-radius: var(--kiosk-radius-pill);
  background: var(--kiosk-border);
  box-shadow: inset 0 0 0 2px var(--kiosk-text-disabled);
  font: var(--kiosk-type-action);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition:
    transform var(--kiosk-dur-press) var(--kiosk-ease),
    background-color var(--kiosk-dur-press) var(--kiosk-ease);
}
.kv-actions__cat {
  font: var(--kiosk-type-tag);
  color: var(--kiosk-text-secondary);
}
/* 決策型動作列：主要按鈕用 CTA 樣式，跟次要按鈕並排 */
.kv-actions > .kv-btn {
  flex: 1;
  font: var(--kiosk-type-action);
}
/* 只有一顆時置中（設計師 2026-10-06 新增）：同動作列的主要鈕尺寸、Grow 外框，寬一半。P01b 用。 */
.kv-actions--single {
  justify-content: center;
}
.kv-actions--single > .kv-btn {
  flex: 0 0 calc((100% - var(--kiosk-actions-gap)) / 2);
}
.kv-actions__btn:active,
.kv-actions__btn--down {
  background: var(--kiosk-text-disabled);
  transform: scale(0.97);
}

/* ================================================================ Waveform
   8 條 8px 寬、圓角 4，顏色照 Grow 色站；高度 12–56 動態。 */
.kv-wave {
  display: flex;
  align-items: center;
  gap: var(--kiosk-wave-gap);
  height: var(--kiosk-wave-bar-max);
  flex: none;
}
.kv-wave__bar {
  width: var(--kiosk-wave-bar-w);
  height: var(--kiosk-wave-bar-min);
  border-radius: 4px;
  animation: kv-wave 1.1s ease-in-out infinite alternate;
}
.kv-wave__bar:nth-child(1) {
  background: var(--kiosk-grow-1);
  animation-delay: 0ms;
}
.kv-wave__bar:nth-child(2) {
  background: var(--kiosk-grow-2);
  animation-delay: -150ms;
}
.kv-wave__bar:nth-child(3) {
  background: var(--kiosk-grow-2);
  animation-delay: -300ms;
}
.kv-wave__bar:nth-child(4) {
  background: var(--kiosk-grow-3);
  animation-delay: -450ms;
}
.kv-wave__bar:nth-child(5) {
  background: var(--kiosk-grow-4);
  animation-delay: -600ms;
}
.kv-wave__bar:nth-child(6) {
  background: var(--kiosk-grow-4);
  animation-delay: -750ms;
}
.kv-wave__bar:nth-child(7) {
  background: var(--kiosk-grow-5);
  animation-delay: -900ms;
}
.kv-wave__bar:nth-child(8) {
  background: var(--kiosk-grow-5);
  animation-delay: -1050ms;
}
@keyframes kv-wave {
  from {
    height: var(--kiosk-wave-bar-min);
  }
  to {
    height: var(--kiosk-wave-bar-max);
  }
}
/* 太吵 / 多人說話：灰階、不動 */
.kv-wave--grey .kv-wave__bar {
  background: var(--kiosk-text-disabled);
  animation: none;
  height: 8px;
}
.kv-wave--grey .kv-wave__bar:nth-child(2n) {
  height: 10px;
}
.kv-wave--grey .kv-wave__bar:nth-child(4) {
  height: 12px;
}
.kv-wave--grey .kv-wave__bar:nth-child(1),
.kv-wave--grey .kv-wave__bar:nth-child(5),
.kv-wave--grey .kv-wave__bar:nth-child(8) {
  height: 8px;
}

/* ============================================================== CTA button
   一屏只有一個。底 Neutral 800 + 4px Grow 外框（見 Primitives）+ CTA 光暈。 */
.kv-btn {
  --kv-ring-fill: var(--kiosk-border);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 16px 36px;
  border-radius: var(--kiosk-radius-pill);
  box-shadow: var(--kiosk-glow-cta);
  font: var(--kiosk-type-cta);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
  cursor: pointer;
}
.kv-btn--lg {
  font: var(--kiosk-type-cta-lg);
  padding: 20px 48px; /* derived · 按 34→56 等比 */
}
.kv-btn--hero {
  font: var(--kiosk-type-cta-hero);
  padding: 24px 64px; /* derived · 特別重要的 CTA，用在 Photo idle 等全螢幕場景 */
}

/* =============================================================== Safe area
   所有卡片 / QR / CTA / 照片的容器。橫向 flex，gap 24。 */
.kv-safe {
  display: flex;
  align-items: flex-start; /* 卡片與 QR 卡同高 268，不撐滿 safe area（設計師 2026-10-06；752 → 800 多出的 48 留在下面） */
  gap: var(--kiosk-card-gap);
  width: var(--kiosk-ai-w);
  height: var(--kiosk-safe-h);
}
.kv-safe--one-line {
  height: var(--kiosk-safe-h-1line);
}
.kv-safe--extended {
  height: var(--kiosk-safe-h-ext);
}
.kv-safe--one-line-extended {
  height: var(--kiosk-safe-h-1line-ext);
}
.kv-safe--center {
  justify-content: center;
}
/* chips + QR 並排：chips 靠左堆疊、QR 靠右（E03 查不到） */
.kv-safe--chips-qr {
  align-items: flex-start;
}
.kv-safe--chips-qr > .kv-chips {
  position: static;
  flex: 1;
}

/* =================================================================== Cards
   Info card：只在資訊比 AI 說的多時才出現。卡片永遠不可按，也不加 Grow 外框；
   Grow 外框只出現在 .kv-actions、.kv-btn、.kv-qr--active、.kv-pill--listening。 */
.kv-card {
  flex: 1;
  height: var(--kiosk-qr-card); /* 同 QR 卡 */
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--kiosk-card-pad-y) var(--kiosk-card-pad-x);
  border-radius: var(--kiosk-radius-card);
  background: var(--kiosk-surface-raised);
  min-width: 0;
}
.kv-card__label {
  font: var(--kiosk-type-card-label);
  color: var(--kiosk-text-secondary);
}
.kv-card__value {
  font: var(--kiosk-type-card-value);
  color: var(--kiosk-text-primary);
}
.kv-card__value--md {
  font: var(--kiosk-type-card-value-md);
}
.kv-card__value--num {
  font: var(--kiosk-type-card-num);
}
/* 建議卡：加 2px 內框 */
.kv-card--outlined {
  box-shadow: inset 0 0 0 2px var(--kiosk-border);
}

/* ================================================================= QR card
   固定 400×400，永遠在 safe-area 最右。 */
.kv-qr {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  width: var(--kiosk-qr-card);
  height: var(--kiosk-qr-card);
  padding: 28px;
  border-radius: var(--kiosk-radius-card);
  background: var(--kiosk-surface-raised);
}
.kv-qr__title {
  font: var(--kiosk-type-qr-title);
  color: var(--kiosk-text-secondary);
  white-space: nowrap;
}
.kv-qr__plate {
  padding: var(--kiosk-qr-plate-pad);
  border-radius: var(--kiosk-radius-plate);
  background: var(--kiosk-white);
}
.kv-qr__code {
  display: block;
  width: var(--kiosk-qr-code);
  height: var(--kiosk-qr-code);
  /* 佔位棋盤；正式 QR 以 <img> 或 <canvas> 取代這個 div */
  background: repeating-conic-gradient(var(--kiosk-surface-base) 0 25%, var(--kiosk-white) 0 50%)
    0 0/18px 18px;
}
/* 唯一 CTA：Grow 外框（見 Primitives）+ 卡片級光暈，標題亮一階 */
.kv-qr--active {
  box-shadow: var(--kiosk-glow-card);
}
}
.kv-qr--active .kv-qr__title {
  color: var(--kiosk-text-muted-light);
}
/* 延伸內容卡（P08 三張 QR 都是可掃的內容）：標題亮一階但不加外框。derived。 */
.kv-qr--offer .kv-qr__title {
  color: var(--kiosk-text-muted-light);
}
/* 440：Exit 唯一 CTA */
.kv-qr--lg {
  width: var(--kiosk-qr-card-lg);
  height: var(--kiosk-qr-card-lg);
}
.kv-qr--lg .kv-qr__title {
  font: var(--kiosk-type-qr-title-lg);
}
.kv-qr--lg .kv-qr__code {
  width: var(--kiosk-qr-code-lg);
  height: var(--kiosk-qr-code-lg);
  background-size: 20px 20px;
}
/* 照片 Review 頁：卡片撐滿照片右側剩餘寬與 684 高，標題 40/700 + 320 白板 */
.kv-qr--xl {
  flex: 1;
  width: auto;
  height: var(--kiosk-photo-h-lg); /* 跟 812×456 的照片框同高（設計師 2026-10-06），不隨 safe area 撐滿 */
  gap: var(--kiosk-space-6);
}
.kv-qr--xl .kv-qr__title {
  font: var(--kiosk-type-qr-title-xl);
  color: var(--kiosk-text-primary);
}
.kv-qr--xl .kv-qr__plate {
  padding: var(--kiosk-qr-plate-pad-lg);
  border-radius: var(--kiosk-radius-plate-lg);
}
.kv-qr--xl .kv-qr__code {
  width: var(--kiosk-qr-code-xl);
  height: var(--kiosk-qr-code-xl);
  background-size: 28px 28px;
}

/* ================================================================== Chips
   建議提問。 */
.kv-chips {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--kiosk-space-4);
}
.kv-chip {
  display: inline-flex;
  align-items: center;
  padding: 20px 32px;
  border-radius: var(--kiosk-radius-pill);
  background: var(--kiosk-surface-raised);
  box-shadow: inset 0 0 0 2px var(--kiosk-border);
  font: var(--kiosk-type-chip);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
}

/* ============================================================ Command pill
   COMMAND 模式的精簡對話框 720×112。辨識到指令 → ✓ 立刻執行；非指令 → 提示 1.5s。 */
.kv-cmd {
  display: flex;
  align-items: center;
  gap: var(--kiosk-space-5);
  width: var(--kiosk-cmd-w);
  height: var(--kiosk-cmd-h);
  padding: 0 var(--kiosk-space-7);
  border-radius: var(--kiosk-radius-pill);
  background: var(--kiosk-overlay-pill);
  box-shadow: inset 0 0 0 2px var(--kiosk-raw-touch-border);
}
.kv-cmd--ok {
  box-shadow: var(--kiosk-glow-listen);
}
.kv-cmd__check {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--kiosk-check);
  height: var(--kiosk-check);
  border-radius: 50%;
  flex: none;
  background: var(--kiosk-success);
  color: var(--kiosk-surface-base);
  font: 900 20px/1 var(--kiosk-font-ui);
}
.kv-cmd__text {
  flex: 1;
  font: var(--kiosk-type-cmd);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
  overflow: hidden;
}
.kv-cmd__tag {
  font: var(--kiosk-type-tag);
  color: var(--kiosk-text-secondary);
  white-space: nowrap;
}
.kv-cmd__hint {
  flex: 1;
  font: var(--kiosk-type-cmd-hint);
  color: var(--kiosk-text-muted-light);
  white-space: nowrap;
}
.kv-cmd__options {
  font: var(--kiosk-type-tag);
  color: var(--kiosk-text-tertiary);
  white-space: nowrap;
}

/* =================================================================== Toast
   OFF 模式：不叫出對話框，只浮一行 3s。 */
.kv-toast {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 16px 32px;
  border-radius: var(--kiosk-radius-pill);
  background: var(--kiosk-overlay-pill);
  box-shadow: inset 0 0 0 2px var(--kiosk-raw-touch-border);
}
.kv-toast__text {
  font: var(--kiosk-type-toast);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
}

/* ============================================================ Media bar
   預告播放中的底部資訊：左片名、右「隨時可以問我」膠囊；下方進度條。derived（README 未列）。 */
.kv-media-bar {
  display: flex;
  align-items: center;
  gap: var(--kiosk-space-6);
}
.kv-media-bar__title {
  font: var(--kiosk-type-media-title);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
}
.kv-media-bar__hint {
  font: var(--kiosk-type-media-hint);
  color: var(--kiosk-text-muted-light);
  background: var(--kiosk-overlay-media);
  border-radius: var(--kiosk-radius-pill);
  padding: 10px 20px;
  white-space: nowrap;
}
/* 進度條：軌 20% 白、進度 primary。--kv-progress 0–100。 */
.kv-media-progress {
  height: var(--kiosk-media-progress-h);
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.2);
  --kv-progress: 0;
}
.kv-media-progress::before {
  content: '';
  display: block;
  height: 100%;
  width: calc(var(--kv-progress) * 1%);
  border-radius: 4px;
  background: var(--kiosk-text-primary);
}

/* ======================================================== Countdown pill
   系統倒數一律在頂列右側，取代日期時間；此時底部對話框隱藏。
   環：--kv-progress 為 0–100 的百分比（inline style 或 JS 設定）。 */
.kv-countdown {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 8px 22px 8px 8px;
  border-radius: var(--kiosk-radius-pill);
  background: var(--kiosk-surface-raised);
  --kv-progress: 100;
}
.kv-countdown__ring {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--kiosk-ring);
  height: var(--kiosk-ring);
  border-radius: 50%;
  flex: none;
  background: conic-gradient(
    var(--kiosk-grow-4) 0 calc(var(--kv-progress) * 1%),
    var(--kiosk-border) 0
  );
}
.kv-countdown__ring::after {
  content: '';
  width: var(--kiosk-ring-inner);
  height: var(--kiosk-ring-inner);
  border-radius: 50%;
  background: var(--kiosk-surface-raised);
}
.kv-countdown__text {
  font: var(--kiosk-type-countdown-pill);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
}
.kv-countdown__num {
  font: var(--kiosk-type-countdown-pill-num);
}

/* ================================================================== Scrims
   獨立元素版。用版型（kv-screen--media / --cover / --standby）時由 ::before/::after 自動產生。 */
.kv-scrim {
  position: absolute;
  left: 0;
  right: 0;
  pointer-events: none;
  z-index: 1;
}
.kv-scrim--top {
  top: 0;
  height: var(--kiosk-scrim-h);
  background: var(--kiosk-scrim-top);
}
.kv-scrim--top-tall {
  top: 0;
  height: var(--kiosk-scrim-h-tall);
  background: var(--kiosk-scrim-top);
}
.kv-scrim--bottom {
  bottom: 0;
  height: var(--kiosk-scrim-h);
  background: var(--kiosk-scrim-bottom);
}
.kv-scrim--cover {
  top: 0;
  bottom: 0;
  background: var(--kiosk-scrim-cover);
}
.kv-dim {
  position: absolute;
  inset: 0;
  background: var(--kiosk-dim);
  pointer-events: none;
  z-index: 4;
}

/* ======================================================== Camera / photo */
.kv-camera {
  position: absolute;
  inset: 0;
  z-index: 0;
}
/* campaign 外框：8px Grow 環，inset 28，圓角 36，用 mask 挖空中間 */
.kv-camera__frame {
  position: absolute;
  inset: var(--kiosk-camera-inset);
  border: var(--kiosk-grow-border-camera) solid transparent;
  border-radius: var(--kiosk-radius-camera);
  background: var(--kiosk-grow) border-box;
  -webkit-mask:
    linear-gradient(#000 0 0) padding-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask:
    linear-gradient(#000 0 0) padding-box,
    linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
  z-index: 2;
}
/* 固定取景框 1040×720，畫面正中（中心 y 540） */
.kv-camera__guide {
  position: absolute;
  left: calc((var(--kiosk-center-w) - var(--kiosk-guide-w)) / 2);
  top: var(--kiosk-guide-top);
  width: var(--kiosk-guide-w);
  height: var(--kiosk-guide-h);
  border: var(--kiosk-guide-border) dashed rgba(255, 255, 255, 0.7);
  border-radius: var(--kiosk-radius-card);
  pointer-events: none;
  z-index: 2;
}
/* 倒數數字 268px 置中 */
.kv-camera__digit {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font: var(--kiosk-type-countdown);
  color: var(--kiosk-text-primary);
  text-shadow: var(--kiosk-text-shadow-digit);
  pointer-events: none;
  z-index: 3;
}
/* 快門白閃 92%，450ms */
.kv-flash {
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.92);
  pointer-events: none;
  z-index: 5; /* 頂列（6）留在白閃上面 */
  animation: kv-flash var(--kiosk-dur-flash) ease-out forwards;
}
.kv-flash--hold {
  animation: none; /* 靜態畫面用 */
}
@keyframes kv-flash {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
/* 照片預覽框：4px Grow 外框（見 Primitives），圓角 32。照片放 <img>，佔位放 .kv-ph */
.kv-photo {
  --kv-ring-w: var(--kiosk-grow-border-photo);
  --kv-ring-fill: var(--kiosk-border);
  position: relative;
  flex: none;
  width: var(--kiosk-photo-w);
  height: var(--kiosk-photo-h);
  border-radius: var(--kiosk-radius-card);
  overflow: hidden;
}
.kv-photo--lg {
  width: var(--kiosk-photo-w-lg);
  height: var(--kiosk-photo-h-lg);
}
.kv-photo > img,
.kv-photo > video,
.kv-photo > .kv-ph {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: calc(var(--kiosk-radius-card) - var(--kiosk-grow-border-photo));
}

/* ========================================================= Side screens
   設計師 2026-09-30 定案：Side 預設只放整張海報（.kv-side > .kv-art），不疊我們的字。
   2026-10-05 確認兩片是前後不是左右：前（F）配合 Center，Photo / Attraction 放素材牆；後（B）永遠整張海報。
   照片牆是 README 的 nice-to-have 變體。Medium fidelity，硬體尺寸確認後再細調。 */
/* Side F · 素材牆 */
.kv-side-wall {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  padding: 24px;
  gap: 24px;
  z-index: 2;
}
.kv-side-wall__title {
  font: var(--kiosk-type-side-title);
  color: var(--kiosk-text-primary);
  padding: 40px 24px 0;
}
.kv-side-wall__grid {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.kv-side-wall__tile {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--kiosk-radius-tile);
}
.kv-side-wall__tile--featured {
  grid-column: 1 / -1;
}
.kv-side-wall__meta {
  font: var(--kiosk-type-side-meta);
  color: var(--kiosk-text-secondary);
}
/* Side F · 拍照流程三態（FOCUS 例外）· 設計師 2026-10-05
   Side 不放文字的規則在拍照時放寬，只放一眼看得懂的大提示，Side F 跟著 Center 的步驟走：
   P02 站位示意（不放鏡像：直式鏡像會讓人以為左右被裁掉，也不用把相機訊號接到這片）、
   P03 看鏡頭（鏡頭在 Center 高度，Side F 在下方，提示往上看）、P04 整片白閃當補光。 */
.kv-side-stand,
.kv-side-look {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 64px;
  color: var(--kiosk-text-primary);
  z-index: 2;
}
.kv-side-stand__figure {
  width: 520px;
  height: auto;
}
.kv-side-stand__figure circle,
.kv-side-stand__figure path,
.kv-side-stand__figure ellipse {
  fill: none;
  stroke: var(--kiosk-grow-2);
  stroke-width: 10;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.kv-side-stand__ground {
  stroke-dasharray: 24 20;
}
.kv-side-stand__text,
.kv-side-look__text {
  font: var(--kiosk-type-side-title);
}
.kv-side-look__arrow {
  width: 360px;
  height: auto;
  animation: kv-side-look 1.2s ease-in-out infinite;
}
.kv-side-look__arrow path {
  fill: none;
  stroke: var(--kiosk-text-primary);
  stroke-width: 28;
  stroke-linecap: round;
  stroke-linejoin: round;
}
@keyframes kv-side-look {
  0%,
  100% {
    translate: 0 0;
  }
  50% {
    translate: 0 -40px;
  }
}
.kv-side-flash {
  position: absolute;
  inset: 0;
  background: #fff;
  z-index: 2;
}
/* Side · Exit 延伸邀請（v2.5）
   無字海報滿版 + 全頁遮罩 + 置中 QR 卡（Grow 外框）。
   設計師：「畫面上還是要有視覺讓人馬上辨識跟電影的關係」。
   工程師備註：如果 Side 接 HTML 的成本太高，可以退回純 JPG 海報版本（posterA / posterB）。 */
.kv-side-exit {
  position: absolute;
  inset: 0;
  z-index: 2;
}
.kv-side-exit > .kv-art > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.kv-side-exit__scrim {
  position: absolute;
  inset: 0;
  background: rgba(10, 10, 10, 0.72);
}
.kv-side-exit__body {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 56px;
  padding: 160px 80px;
  text-align: center;
}
.kv-side-exit--top .kv-side-exit__body { justify-content: flex-start; }
.kv-side-exit--bottom .kv-side-exit__body { justify-content: flex-end; }
.kv-side-exit__cta {
  font: 700 56px/1.3 var(--kiosk-font-ui);
  color: var(--kiosk-text-primary);
}
.kv-side-exit__hint {
  font: var(--kiosk-type-side-meta);
  color: var(--kiosk-text-secondary);
}

/* Side · 預告同步播放（v2.9）
   A06 Trailer 時 Side F / B 同步播放預告。直式螢幕（1080×1920）裡放橫式 16:9 影片垂直置中，
   影片下方放片名、進度條、暫停/停止按鈕（用 DS 的 .kv-actions 視覺）。 */
.kv-side-trailer {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--kiosk-surface-base);
  z-index: 2;
}
.kv-side-trailer__video {
  flex: none;
  width: 1080px;
  height: 608px; /* 1080 × 9/16 ≈ 608 */
  background: #000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.kv-side-trailer__video > video,
.kv-side-trailer__video > .kv-ph {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.kv-side-trailer__info {
  width: 1080px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40px;
  padding: 56px 64px;
}
.kv-side-trailer__title {
  font: 700 44px/1.3 var(--kiosk-font-ui);
  color: var(--kiosk-text-primary);
  text-align: center;
}
.kv-side-trailer__progress {
  width: 100%;
  height: var(--kiosk-media-progress-h);
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.15);
  --kv-progress: 0;
}
.kv-side-trailer__progress::before {
  content: '';
  display: block;
  height: 100%;
  width: calc(var(--kv-progress) * 1%);
  border-radius: 4px;
  background: var(--kiosk-text-primary);
}

/* 媒體控制（v2.9）
   Center：點螢幕 = 暫停/繼續（出現大播放鈕覆蓋）；「結束預告」小按鈕帶 Grow 框。
   Side：不可觸控，純預覽。暫停/停止狀態跟著 Center 走。 */

/* 結束預告按鈕（Center 右下角，跟 media-bar 片名同高） */
.kv-media-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 44px;
  padding: 0 24px;
  border-radius: var(--kiosk-radius-pill);
  border: none;
  background: var(--kiosk-surface-raised);
  color: var(--kiosk-text-primary);
  font: 500 22px/1 var(--kiosk-font-ui);
  cursor: pointer;
  transition: background 120ms ease, transform 120ms ease;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
}
.kv-media-btn:hover {
  background: #3a3a3a;
}
.kv-media-btn:active {
  background: #525252;
  transform: scale(0.97);
}
.kv-media-btn__icon {
  width: 14px;
  height: 14px;
  flex: none;
}
.kv-media-btn--stop .kv-media-btn__icon::before {
  content: '';
  display: block;
  width: 12px;
  height: 12px;
  border-radius: 2px;
  background: currentColor;
}

/* 暫停覆蓋層：點螢幕觸發，顯示大播放鈕 + 半透明暗幕 */
.kv-media-pause {
  position: absolute;
  inset: 0;
  z-index: 8;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.5);
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms ease;
  cursor: pointer;
}
.kv-media-pause.active {
  opacity: 1;
  pointer-events: auto;
}
/* 大播放鈕：圓形 Grow 外框 + 光暈，跟 DS 的 .kv-btn CTA 同語言 */
.kv-media-pause__play {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  border: var(--kiosk-grow-border) solid transparent;
  background:
    linear-gradient(var(--kiosk-surface-raised), var(--kiosk-surface-raised)) padding-box,
    var(--kiosk-grow) border-box;
  box-shadow: var(--kiosk-glow-cta);
  display: flex;
  align-items: center;
  justify-content: center;
}
.kv-media-pause__play::before {
  content: '';
  display: block;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 22px 0 22px 38px;
  border-color: transparent transparent transparent var(--kiosk-text-primary);
  margin-left: 8px; /* 視覺置中補償 */
}

/* Side 播放鈕稍大（直式螢幕空間多） */
.kv-side-trailer .kv-media-pause__play {
  width: 160px;
  height: 160px;
}
.kv-side-trailer .kv-media-pause__play::before {
  border-width: 30px 0 30px 52px;
  margin-left: 10px;
}

/* ===================================================== Micro Moments（v1.8）
   設計師 2026-10-05 確認的十個情境。Kebbi 那半是示意（實機換 SDK 的表情與動作），Center / Side 那半是正式規格。
   全部是「加 class 就播一次」或「設 CSS 變數就跟著動」，JS 只負責時機與事件；接法見 README §5.7。 */

/* 01 無人互動 · 視線：--kv-gx / --kv-gy（px）由 JS 設在 .kv-face 與 .kv-screen 上。
   眼睛跟著看；cover 畫面加 .kv-screen--gaze 時，圖往反方向微移（像海報在被看）。久了沒人：Kebbi sleep + .kv-screen--asleep 讓 CTA 呼吸。 */
.kv-face {
  --kv-gx: 0px;
  --kv-gy: 0px;
}
.kv-face__eyes {
  translate: var(--kv-gx) var(--kv-gy);
}
.kv-screen--gaze > .kv-art > img,
.kv-screen--gaze > .kv-art > .kv-slideshow__slide {
  translate: calc(var(--kv-gx, 0px) * -0.35) 0;
  transition: translate 1200ms cubic-bezier(0.33, 1, 0.68, 1);
}
.kv-screen--asleep > .kv-btn--hero {
  animation: kv-breathe 3200ms ease-in-out infinite;
}
@keyframes kv-breathe {
  0%,
  100% {
    box-shadow: var(--kiosk-glow-cta);
  }
  50% {
    box-shadow: 0 0 72px rgba(31, 111, 224, 0.75);
  }
}
/* 02 有人靠近 · 招呼句從人的那一側滑進來（Kebbi 用 --kv-gx 轉向 + data-gesture="nod"） */
.kv-transcript--from-left {
  animation: kv-slide-l 600ms cubic-bezier(0.33, 1, 0.68, 1);
}
.kv-transcript--from-right {
  animation: kv-slide-r 600ms cubic-bezier(0.33, 1, 0.68, 1);
}
@keyframes kv-slide-l {
  from {
    opacity: 0;
    translate: -96px 0;
  }
}
@keyframes kv-slide-r {
  from {
    opacity: 0;
    translate: 96px 0;
  }
}
/* 03 提到《魔法秘境》· Kebbi 金眼 1s（.kv-face--gold）；Center：一道窄的暖光帶斜掃過素材（.kv-screen--sweep，z 3 在素材與遮罩上、文字下，1100ms）
   + 素材亮度抬一下、換進來的海報從 1.06 推回 1（.kv-slideshow__slide--enter）、標題金光一閃（.kv-transcript--lit）、
   chips 逐顆退場換句再進場並亮金邊（.kv-chip--out / --in / --lit）；Side F 切海報 A 10s 由 JS 做。
   設計師 2026-10-06：第一版整片米色罩住畫面、文字跟著變色，太粗；改成只打在素材上的窄光帶。 */
.kv-face--gold .kv-face__eye {
  background: var(--kiosk-camp);
  box-shadow: 0 0 72px var(--kiosk-camp);
}
/* 光帶：寬 200% 的 ::after，帶在正中（gradient 44–56%），用 translate 從右邊畫面外推到左邊畫面外（±60% 自身寬 = ±1536px），
   終點一定在畫面外。設計師 2026-10-06：第一版用 background-position 百分比，斜角漸層算不準、最後停在畫面左側才被移除。 */
.kv-screen--sweep::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: -50%;
  width: 200%;
  z-index: 3;
  pointer-events: none;
  mix-blend-mode: screen;
  background: linear-gradient(
    104deg,
    transparent 42%,
    oklch(0.84 0.12 68 / 0.22) 46%,
    oklch(0.97 0.08 80 / 0.85) 50%,
    oklch(0.84 0.12 68 / 0.22) 54%,
    transparent 58%
  );
  animation: kv-sweep 2400ms cubic-bezier(0.65, 0, 0.35, 1) forwards; /* 1100ms 太快沒有快慢，拉到 2.4s、慢進快中慢出 */
}
@keyframes kv-sweep {
  from {
    translate: 60% 0;
  }
  to {
    translate: -60% 0;
  }
}
.kv-screen--sweep > .kv-art {
  animation: kv-art-lift 2600ms cubic-bezier(0.45, 0, 0.25, 1);
}
@keyframes kv-art-lift {
  0% {
    filter: brightness(1);
  }
  30% {
    filter: brightness(1.22) saturate(1.12);
  }
  100% {
    filter: brightness(1);
  }
}
.kv-screen--sweep .kv-slideshow__slide {
  transition-duration: 2200ms;
}
.kv-slideshow__slide--enter {
  animation: kv-slide-enter 3600ms cubic-bezier(0.16, 0.6, 0.2, 1) forwards;
}
@keyframes kv-slide-enter {
  from {
    scale: 1.06;
  }
  to {
    scale: 1;
  }
}
.kv-transcript--lit {
  animation: kv-text-lit 2600ms cubic-bezier(0.45, 0, 0.25, 1) 300ms both;
}
@keyframes kv-text-lit {
  0% {
    text-shadow: 0 0 0 transparent;
  }
  25% {
    text-shadow: 0 0 28px oklch(0.84 0.12 68 / 0.9);
  }
  100% {
    text-shadow: 0 0 0 transparent;
  }
}
.kv-chip--out {
  opacity: 0;
  translate: 0 -8px;
  transition:
    opacity 360ms cubic-bezier(0.55, 0, 1, 0.45),
    translate 360ms cubic-bezier(0.55, 0, 1, 0.45);
}
.kv-chip--in {
  animation: kv-chip-in 720ms cubic-bezier(0.16, 0.8, 0.2, 1) both;
}
@keyframes kv-chip-in {
  from {
    opacity: 0;
    translate: 0 10px;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}
.kv-chip--lit {
  animation: kv-chip-lit 3600ms cubic-bezier(0.45, 0, 0.25, 1) both;
}
.kv-chip--in.kv-chip--lit {
  animation:
    kv-chip-in 720ms cubic-bezier(0.16, 0.8, 0.2, 1) both,
    kv-chip-lit 3600ms cubic-bezier(0.45, 0, 0.25, 1) both;
}
@keyframes kv-chip-lit {
  0%,
  20% {
    box-shadow: inset 0 0 0 2px var(--kiosk-camp);
  }
  100% {
    box-shadow: inset 0 0 0 2px var(--kiosk-border);
  }
}
/* 04 提到 Disney · 星星眼 + LED 跑一圈 Grow（.kv-face--star .kv-face--led-run，1.2s 後移除）；Center 上飄星點 .kv-spark（JS 生 20 顆、2s 後移除） */
.kv-face--star .kv-face__eye {
  clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
  border-radius: 0;
  width: 200px;
  height: 200px;
  background: var(--kiosk-grow-3);
  animation: none;
}
.kv-face--led-run .kv-face__bar {
  background: var(--kiosk-grow);
  background-size: 300% 100%;
  animation: kv-led-run 1200ms linear;
}
@keyframes kv-led-run {
  from {
    background-position: 100% 0;
  }
  to {
    background-position: -100% 0;
  }
}
/* 設計師 2026-10-06：原本的星點往上飄太像火光，先改四芒星又跟主視覺不搭；定案「光塵」：
   七十多顆細碎微粒像魔法粉塵被光照到，固定位置快閃、微微往上飄 28px，少數幾顆大一點。
   大小 / 延遲 / 時長 / 橫漂由 JS 設在 --size / --delay / --dur / --dx；--n 閃幾次。 */
.kv-spark {
  position: absolute;
  width: var(--size, 3px);
  height: var(--size, 3px);
  border-radius: 50%;
  background: #fff;
  box-shadow:
    0 0 calc(var(--size, 3px) * 2) var(--kiosk-grow-3),
    0 0 calc(var(--size, 3px) * 5) rgb(244 251 208 / 0.5);
  mix-blend-mode: screen;
  z-index: 7;
  pointer-events: none;
  opacity: 0;
  animation: kv-dust var(--dur, 900ms) ease-in-out var(--delay, 0ms) var(--n, 2);
}
@keyframes kv-dust {
  0% {
    opacity: 0;
    translate: 0 0;
  }
  30% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    translate: var(--dx, 0px) -28px;
  }
}
/* 05 拍照 P02 站進框 · Side F 人形填滿（.kv-side-stand--filled，文字換「很好」由 JS）、Kebbi 光圈眼（.kv-face--aperture） */
.kv-side-stand__figure circle,
.kv-side-stand__figure path {
  transition: fill 500ms ease;
}
.kv-side-stand--filled .kv-side-stand__figure circle,
.kv-side-stand--filled .kv-side-stand__figure path {
  fill: var(--kiosk-grow-2);
}
.kv-face__eye {
  position: relative;
}
.kv-face--aperture .kv-face__eye {
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: transparent;
  border: 34px solid var(--kiosk-text-primary);
  animation: none;
}
.kv-face--aperture .kv-face__eye::after {
  content: '';
  position: absolute;
  inset: 44px;
  border-radius: 50%;
  background: var(--kiosk-text-primary);
}
/* 06 拍照完成 · P05b 拍立得：底圖壓暗（.kv-art--dim），相紙從底部吐出 900ms、照片 2.4s 顯影。
   接著 P06 加 .kv-screen--arrive：照片用 FLIP 從相紙位置飛到格子（transform 由 JS 量測後設定，transition 在這裡）、白框淡出、QR 從右滑入、頂列與 AI 句淡入。 */
.kv-art--dim > img {
  filter: brightness(0.35);
}
/* 拍立得相紙 · 複製自 Vyin 官網活動頁 C01（設計師 2026-10-06 給的 hexed_html.zip / vyin-polaroid.html）。官網那份後續改動不會同步過來。
   原版是 480 寬的手機卡（Instax Wide 99:62、字 7.5–10px）；這裡放大到 820 寬、照片 16:9、字按比例放大，材質 / 月相 / 規格字樣 / 曝光列照搬。
   .kv-polaroid 本身仍是「從底部吐出」的動畫容器；.kv-polaroid__photo 的 class 名不變（P06 的 FLIP 靠它量位置）。 */
.kv-polaroid {
  position: absolute;
  left: 50%;
  bottom: 0;
  width: 820px;
  padding: 34px 34px 48px;
  display: flex;
  flex-direction: column;
  border-radius: 8px;
  background-image:
    radial-gradient(120% 85% at 16% 6%, rgb(255 255 255 / 0.06) 0%, rgb(255 255 255 / 0.015) 34%, rgb(255 255 255 / 0) 62%),
    linear-gradient(180deg, rgb(255 255 255 / 0.02) 0%, rgb(0 0 0 / 0) 26%, rgb(0 0 0 / 0.22) 100%),
    linear-gradient(to right, #34312d 0%, #10100f 17%, #0a0a09 82%, #050505 100%);
  box-shadow:
    0 -1px 0 rgb(255 255 255 / 0.08),
    -1px 0 0 rgb(255 255 255 / 0.055),
    0 1px 0 rgb(255 228 190 / 0.075),
    1px 0 0 rgb(255 228 190 / 0.045),
    0 0 0 1px #030303 inset,
    1px 1px 2px rgb(255 255 255 / 0.07) inset,
    -1px -2px 3px rgb(0 0 0 / 0.69) inset,
    0 40px 100px rgb(0 0 0 / 0.6);
  translate: -50% 120%;
  rotate: -2deg;
  z-index: 7;
  animation: kv-polaroid-up 900ms cubic-bezier(0.33, 1, 0.68, 1) forwards;
}
.kv-polaroid::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='d' filterUnits='userSpaceOnUse' x='0' y='0' width='140' height='140' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='1' seed='5' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='20' intercept='-11.2'/%3E%3C/feComponentTransfer%3E%3CfeComponentTransfer%3E%3CfeFuncA type='discrete' tableValues='0 1'/%3E%3C/feComponentTransfer%3E%3CfeGaussianBlur stdDeviation='0.55'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23d)'/%3E%3C/svg%3E");
  background-size: 100px 100px;
  opacity: 0.11;
}
.kv-polaroid > * {
  position: relative;
  z-index: 1;
}
@keyframes kv-polaroid-up {
  to {
    translate: -50% -56px;
  }
}
.kv-polaroid__photo {
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 2px;
  background: #141414;
  box-shadow: 0 0 0 1px rgb(214 178 121 / 0.22);
}
.kv-polaroid__photo > img,
.kv-polaroid__photo > .kv-ph {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.04) saturate(0) contrast(1.4);
  animation: kv-develop 2400ms ease-out 600ms forwards;
}
@keyframes kv-develop {
  55% {
    filter: brightness(0.55) saturate(0.35) contrast(1.25);
  }
  to {
    filter: none;
  }
}
/* 上緣：兩條細線夾五顆月相 */
.kv-polaroid__head {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-top: 14px;
}
.kv-polaroid__rule {
  flex: 1;
  height: 1px;
  background-image: linear-gradient(90deg, rgb(111 75 39 / 0.38) 0%, rgb(111 75 39 / 0.62) 28%, rgb(111 75 39 / 0.4) 55%, rgb(111 75 39 / 0.58) 84%, rgb(111 75 39 / 0.42) 100%);
}
.kv-polaroid__moons {
  flex: none;
  width: 24%;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.kv-polaroid__moon {
  position: relative;
  display: block;
  width: var(--s, 12.3%);
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #e8cfa6, #c49a5e 58%, #8a6238);
  box-shadow: 0 0 2px rgb(214 178 121 / 0.16);
  overflow: hidden;
}
.kv-polaroid__moon::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: 50%;
  background: #0a0a09;
  transform: translateX(var(--o));
}
/* 下巴：規格字樣 + 定位十字 + 曝光列 */
.kv-polaroid__meta {
  margin-top: 10px;
  font-family: var(--kiosk-font-mono);
  text-transform: uppercase;
  white-space: nowrap;
  line-height: 1.6;
}
.kv-polaroid__spec {
  display: flex;
  align-items: center;
  gap: 18px;
}
.kv-polaroid__reg {
  flex: none;
  width: 22px;
  aspect-ratio: 1;
  fill: none;
  stroke: #a77b43;
  stroke-width: 1;
  opacity: 0.6;
}
.kv-polaroid__spec-text {
  flex: 1;
  color: #d6b279;
  font-size: 17px;
  letter-spacing: 0.14em;
  text-align: center;
  opacity: 0.86;
  overflow: hidden;
}
.kv-polaroid__exposure {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-top: 10px;
  color: #a77b43;
  font-size: 13px;
  letter-spacing: 0.06em;
  opacity: 0.8;
}
.kv-polaroid__shot {
  flex: 1;
  overflow: hidden;
  text-align: right;
}
.kv-polaroid__arrow {
  flex: none;
  width: 34px;
  aspect-ratio: 26 / 18;
  background-image: linear-gradient(100deg, #e8cfa6 0%, #c49a5e 38%, #9c7140 78%, #8a6238 100%);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 26 18'%3E%3Cpath d='M0 6h16V0l10 9-10 9v-6H0z' fill='%23000'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 26 18'%3E%3Cpath d='M0 6h16V0l10 9-10 9v-6H0z' fill='%23000'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: contain;
  mask-size: contain;
  opacity: 0.9;
}

/* P06 預覽頁用的靜態版（設計師 2026-10-13：兩頁連貫；2026-10-14 從 film.css 搬進 DS）：放在 safe area 裡、600 寬、照片已顯影，不吐出不晃。
   整張相紙從 P05b 的位置 FLIP 飛過來（prototype / film 的 arrive）。 */
.kv-polaroid--review {
  position: relative;
  left: auto;
  bottom: auto;
  flex: none;
  width: 600px;
  padding: 25px 25px 34px;
  translate: 0 0;
  rotate: 0deg;
  animation: none;
  z-index: 2;
  transform-origin: 0 0;
}
.kv-polaroid--review .kv-polaroid__photo > img,
.kv-polaroid--review .kv-polaroid__photo > .kv-ph {
  animation: none;
  filter: none;
}
.kv-polaroid--review .kv-polaroid__head {
  margin-top: 10px;
  gap: 14px;
}
.kv-polaroid--review .kv-polaroid__meta {
  margin-top: 6px;
}
.kv-polaroid--review .kv-polaroid__spec {
  gap: 12px;
}
.kv-polaroid--review .kv-polaroid__reg {
  width: 16px;
}
.kv-polaroid--review .kv-polaroid__spec-text {
  font-size: 12.5px;
}
.kv-polaroid--review .kv-polaroid__exposure {
  margin-top: 6px;
  gap: 12px;
  font-size: 10px;
}
.kv-polaroid--review .kv-polaroid__arrow {
  width: 24px;
}
.kv-screen--arrive > .kv-topbar,
.kv-screen--arrive > .kv-transcript {
  animation: kv-fade-in 400ms ease-out 350ms both;
}
.kv-screen--arrive .kv-qr {
  animation: kv-qr-in 520ms cubic-bezier(0.33, 1, 0.68, 1) 250ms both;
}
.kv-screen--arrive .kv-photo {
  transform-origin: 0 0;
  z-index: 7;
  transition: transform 600ms cubic-bezier(0.33, 1, 0.68, 1);
}
.kv-screen--arrive .kv-photo::after {
  content: '';
  position: absolute;
  inset: -34px -34px -48px;
  background: linear-gradient(to right, #34312d 0%, #10100f 17%, #0a0a09 82%, #050505 100%);
  border-radius: 8px;
  z-index: -1;
  animation: kv-frame-out 500ms ease-out 150ms forwards;
}
@keyframes kv-fade-in {
  from {
    opacity: 0;
  }
}
@keyframes kv-qr-in {
  from {
    opacity: 0;
    translate: 80px 0;
  }
}
@keyframes kv-frame-out {
  to {
    opacity: 0;
  }
}
/* 07 思考 A04 · 同步脈動：Center 思考光點、Kebbi 眼睛浮動、LED 呼吸都走 --kiosk-dur-pulse 同一拍（.kv-face--sync） */
.kv-face--sync .kv-face__eye {
  animation: kv-face-float var(--kiosk-dur-pulse) ease-in-out infinite;
}
.kv-face--sync .kv-face__bar {
  animation: kv-bar-breathe var(--kiosk-dur-pulse) ease-in-out infinite;
}
@keyframes kv-bar-breathe {
  0%,
  100% {
    opacity: 0.5;
  }
  50% {
    opacity: 1;
  }
}
/* 08 聽不清楚 E01 · 歪頭：Kebbi 整對眼睛歪 10°（.kv-face--tilt），Center 問句微傾再回正（.kv-transcript--tilt） */
.kv-face--tilt .kv-face__eyes {
  rotate: 10deg;
  transition: rotate 500ms ease;
}
.kv-transcript--tilt {
  transform-origin: 0 50%;
  animation: kv-tilt-text 1400ms ease-in-out;
}
@keyframes kv-tilt-text {
  0%,
  100% {
    rotate: 0deg;
  }
  40% {
    rotate: 1.5deg;
  }
}
/* 09 太吵 E06 · 瞇眼抖（.kv-face--squint，1.2s 後移除）、對話框跟著抖（.kv-pill--shake） */
.kv-face--squint .kv-face__eye {
  height: 60px;
  animation: none;
}
.kv-face--squint .kv-face__eyes {
  animation: kv-shake 600ms ease-in-out;
}
.kv-face--squint .kv-face__bar {
  animation: kv-bar-grey 600ms steps(3) 2;
}
.kv-pill--shake {
  animation: kv-shake-s 600ms ease-in-out;
}
@keyframes kv-shake {
  0%,
  100% {
    translate: 0 0;
  }
  25% {
    translate: -24px 0;
  }
  50% {
    translate: 24px 0;
  }
  75% {
    translate: -12px 0;
  }
}
@keyframes kv-bar-grey {
  50% {
    opacity: 0.3;
  }
}
@keyframes kv-shake-s {
  0%,
  100% {
    translate: 0 0;
  }
  25% {
    translate: -6px 0;
  }
  50% {
    translate: 6px 0;
  }
  75% {
    translate: -3px 0;
  }
}
/* 10 Moving A01 · Kebbi 用 --kv-gx 看向前進方向；路線點換 class 時淡入（到站 Kebbi 回正 + 點頭由 JS） */
.kv-route__dot {
  transition: background 300ms ease;
}

/* ===================================================== v2.1 · 情境事件規格新增的元件
   milo 2026-10-01「情境事件規格」補進來的三個東西：收單橫幅、官方視覺標示、下一部上映小卡。 */

/* 官方視覺標示（巡邏移動播送）：左下「官方視覺」、右下「詳情資訊」小字。 */
.kv-stamp {
  position: absolute;
  left: var(--kiosk-margin);
  bottom: var(--kiosk-pill-bottom);
  padding: 8px 14px;
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: 6px;
  font: var(--kiosk-type-annot-sm);
  letter-spacing: 0.08em;
  color: var(--kiosk-text-muted-light);
  z-index: 6;
}
.kv-stamp--right {
  left: auto;
  right: var(--kiosk-margin);
  border: 0;
  padding: 8px 0;
}

/* 最近場次卡（C17）· 設計師 2026-10-06：問場次一律用這張。
   規則：最多 4 場；只列今天還沒開演的、近到遠；不足 4 場只放有的，不補空位；都開演完 → __empty 一句。
   不放海報（留位置給場次），片名在標題列、場次橫排平分。寬度跟著 safe area，高度 = safe area（316 / 388）。 */
.kv-showtimes {
  flex: 1;
  flex-direction: row;
  align-items: stretch;
  padding: 0;
  overflow: hidden;
}
.kv-showtimes__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--kiosk-card-pad-y) var(--kiosk-card-pad-x);
}
.kv-showtimes__head {
  display: flex;
  align-items: baseline;
  justify-content: flex-start; /* 「最近場次」小字緊貼片名右邊，視線不用切到最右 */
  gap: var(--kiosk-space-5);
}
.kv-showtimes__film {
  font: var(--kiosk-type-card-value-md);
  color: var(--kiosk-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kv-showtimes__kind {
  font: var(--kiosk-type-card-label);
  color: var(--kiosk-text-secondary);
  white-space: nowrap;
}
.kv-showtimes__list {
  display: flex;
  gap: var(--kiosk-space-6);
}
.kv-showtimes__item {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.kv-showtimes__time {
  font: 800 64px/1 var(--kiosk-font-display);
  color: var(--kiosk-text-primary);
}
.kv-showtimes__meta {
  font: var(--kiosk-type-card-label);
  color: var(--kiosk-text-secondary);
  white-space: nowrap;
}
.kv-showtimes__empty {
  font: var(--kiosk-type-card-value-md);
  color: var(--kiosk-text-secondary);
}

/* 送客有人停下：QR 放大 */
.kv-screen--standby > .kv-qr--grow {
  transform: scale(1.18);
  transform-origin: 100% 0;
}

/* 魔法火光彩蛋（Micro Moments 11）· 複製自 Vyin 官網活動頁 C01 的氛圍層（hexed_html.zip / vyin-atmosphere.html，2026-10-06）。
   女主角比莉施法時的紅色火光：10 顆粒子從畫面下半往上飄、邊飄邊左右晃、兩端淡出。只動 transform 與 opacity。
   提到「比莉」（名字才算，「女主角」不算）或「魔法」時由 JS 把 .kv-embers 丟進目前畫面、約 8 秒後移除。vh 換成畫布像素（800 高）。 */
.kv-embers {
  position: absolute;
  inset: 0;
  z-index: 3; /* 在素材與遮罩上、文字與卡片下 */
  overflow: hidden;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 55%, transparent 100%);
  animation: kv-fade-in 600ms ease-out;
}
/* P05b 拍立得頁常駐一層火花在相紙後面（z 3 < 相紙 z 7），增加成就感；--loop 不會被 prototype 清場移除。設計師 2026-10-06 加。 */
.kv-embers--loop {
  animation: kv-fade-in 1200ms ease-out 600ms both;
}
.kv-embers--out {
  animation: kv-embers-out 800ms ease-out forwards;
}

/* 12 提到「復仇者聯盟」或裡面的英雄名（設計師 2026-10-06 加）· 「集結」：不用任何漫威標誌、名稱或配色，只用我們的 UI 做英雄感——
   .kv-hud 疊在畫面上：兩圈震波從中心擴出去、四周粗邊框橘光呼吸兩次（設計師 2026-10-06：相機外框的四角拿掉、白色掃描線拿掉、圈與邊框加粗，只留紅）；素材本身 punch 一下（放大 1.05 → 1、對比飽和拉高再回）。
   顏色只用 Grow 5（橘紅）。約 3.2s 後淡出移除。Kebbi：鎖定 → 戰鬥臉 + 右手舉直 → 嘴角一撇收尾，燈紅白快閃。
   設計師 2026-10-06：第一版 3px 細線不合 DS；線寬改用相機 campaign 外框的 --kiosk-grow-border-camera（8px）、圓角 --kiosk-radius-camera（36px）、光暈 40px 同三級光暈。 */
.kv-hud {
  position: absolute;
  inset: 0;
  z-index: 7;
  pointer-events: none;
  --hud: var(--kiosk-grow-5);
  animation: kv-hud-fade 3200ms ease-in both;
}
@keyframes kv-hud-fade {
  0%,
  78% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
.kv-hud__edge {
  position: absolute;
  inset: 0;
  border-radius: var(--kiosk-radius-screen);
  animation: kv-hud-edge 1400ms ease-out 2 both;
}
@keyframes kv-hud-edge {
  0% {
    box-shadow:
      inset 0 0 0 0 transparent,
      inset 0 0 0 transparent;
  }
  18% {
    box-shadow:
      inset 0 0 0 12px var(--hud),
      inset 0 0 160px rgb(255 106 43 / 0.5);
  }
  100% {
    box-shadow:
      inset 0 0 0 0 transparent,
      inset 0 0 40px rgb(255 106 43 / 0.12);
  }
}
.kv-hud__ring {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 320px;
  height: 320px;
  translate: -50% -50%;
  border-radius: 50%;
  border: 14px solid var(--hud);
  box-shadow:
    0 0 40px var(--hud),
    inset 0 0 40px rgb(255 106 43 / 0.5);
  opacity: 0;
  animation: kv-hud-ring 1000ms cubic-bezier(0.2, 0.7, 0.2, 1) 180ms both;
}
.kv-hud__ring--2 {
  animation-duration: 1400ms;
  animation-delay: 520ms;
  border-width: var(--kiosk-grow-border-camera);
}
@keyframes kv-hud-ring {
  0% {
    scale: 0.15;
    opacity: 1;
  }
  100% {
    scale: 5;
    opacity: 0;
  }
}
.kv-screen--hero > .kv-art {
  animation: kv-hero-punch 700ms cubic-bezier(0.2, 0.8, 0.2, 1) 160ms;
}
@keyframes kv-hero-punch {
  0% {
    scale: 1;
    filter: none;
  }
  25% {
    scale: 1.05;
    filter: contrast(1.25) saturate(1.35) brightness(1.1);
  }
  100% {
    scale: 1;
    filter: none;
  }
}
@keyframes kv-embers-out {
  to {
    opacity: 0;
  }
}
.kv-ember {
  position: absolute;
  bottom: 12%;
  left: var(--x);
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  background: radial-gradient(circle, #ffd9a0 0%, #ff7a2a 18%, rgb(192 52 26 / 0.7) 55%, transparent 72%); /* 設計師 2026-10-06：中間的黃少一點，核心縮到 18% 就轉橙紅 */
  box-shadow: 0 0 calc(var(--size) * 1.5) rgb(255 122 42 / 0.8), 0 0 calc(var(--size) * 3) rgb(255 122 42 / 0.7), 0 0 calc(var(--size) * 6) rgb(192 52 26 / 0.5);
  mix-blend-mode: screen;
  opacity: 0;
  animation: kv-ember-rise var(--dur) linear var(--delay) infinite;
}
@keyframes kv-ember-rise {
  0% {
    transform: translate3d(0, 0, 0);
    opacity: 0;
  }
  12% {
    opacity: var(--op);
  }
  70% {
    opacity: var(--op);
  }
  100% {
    transform: translate3d(var(--drift), -560px, 0);
    opacity: 0;
  }
}

/* ===================================================== Position slots
   只在 .kv-screen 裡使用。把元件放到 1280×800 格線的固定位置。
   用版型（下一節）時不需要這些；混用也可以。 */
.kv-at-topbar {
  position: absolute;
  top: var(--kiosk-topbar-top);
  left: var(--kiosk-margin);
  right: var(--kiosk-margin);
  z-index: 6;
}
.kv-at-topbar--countdown {
  top: var(--kiosk-topbar-count-top);
}
.kv-at-route {
  position: absolute;
  top: var(--kiosk-route-top);
  right: var(--kiosk-margin);
  z-index: 6;
}
.kv-at-progress {
  position: absolute;
  top: 56px; /* derived · 頂列垂直中心 */
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
}
.kv-at-ai {
  position: absolute;
  top: var(--kiosk-ai-top);
  left: var(--kiosk-margin);
  width: var(--kiosk-ai-w);
  z-index: 2;
}
.kv-at-ai--cover {
  width: var(--kiosk-ai-w-cover);
}
.kv-at-caption {
  position: absolute;
  top: var(--kiosk-caption-top);
  left: var(--kiosk-margin);
  right: var(--kiosk-margin);
  z-index: 2;
}
/* 拍照畫面：不放 logo 與狀態 chip，字幕上移到頂列的位置 y 64（設計師 2026-09-30）。
   收音狀態由 Kebbi 光條與指令膠囊承接。 */
.kv-at-caption--camera {
  top: var(--kiosk-caption-top-camera);
}
.kv-at-status {
  position: absolute;
  top: var(--kiosk-status-top);
  left: var(--kiosk-margin);
  z-index: 2;
}
.kv-at-status--in-ai {
  top: var(--kiosk-ai-top);
  height: 72px;
}
.kv-at-safe {
  position: absolute;
  top: var(--kiosk-safe-top);
  left: var(--kiosk-margin);
  z-index: 2;
}
.kv-at-safe--one-line {
  top: var(--kiosk-safe-top-1line);
}
.kv-at-pill {
  position: absolute;
  left: var(--kiosk-pill-x);
  bottom: var(--kiosk-pill-bottom);
  z-index: 5;
}
.kv-at-pill--cta {
  left: var(--kiosk-margin);
}
.kv-at-cmd {
  position: absolute;
  left: var(--kiosk-cmd-x);
  bottom: var(--kiosk-pill-bottom);
  z-index: 5;
}
.kv-at-toast {
  position: absolute;
  left: 50%;
  bottom: var(--kiosk-toast-bottom);
  transform: translateX(-50%);
  z-index: 5;
}
.kv-at-hero {
  position: absolute;
  inset: 0;
  z-index: 2;
}
.kv-at-hero--left {
  left: var(--kiosk-margin);
  right: auto;
  width: var(--kiosk-ai-w-cover);
}
.kv-at-standby-qr {
  position: absolute;
  right: var(--kiosk-margin);
  top: var(--kiosk-standby-qr-top);
  z-index: 2;
}

/* ================================================================ Templates
   四種 Center 畫面骨架。直接子元件依 class 自動落到格線。
   · --dialog   頂列 + AI 區 + safe area + 對話框（P06–P08、A03–A05、E01–E06、W03–W04、X03–X04）
   · --media    滿版媒體 + 上下遮罩 + 字幕 + 媒體版頂列（P02–P05、A06）
   · --cover    滿版 key art + 左側遮罩 + 1100 寬 AI 字（P01、A02、A03；A01 加 --no-scrim 只留海報）
   · --standby  置中光暈 + hero 大標（W01、W02、X01、X02）
   狀態修飾：--one-line、--countdown、--no-pill、--camera、--cover-strong、--no-scrim、--scrim-tall。 */

/* --- dialog 的底（2026-10-14 定，取代 Neutral 950 純底）：
   放一個 .kv-art 進 --dialog，圖是首頁輪播「進對話那一刻」的那張（JS 規則：進對話就凍住、不再換；回首頁才繼續輪播），
   這裡自動壓暗 + 模糊 + 黑色遮罩。沒放 .kv-art 就是純底。 --- */
.kv-screen--dialog > .kv-art > img {
  transform: scale(1.12);
  filter: blur(var(--kiosk-dialog-blur)) brightness(var(--kiosk-dialog-dim)) saturate(0.9);
}
.kv-screen--dialog > .kv-art::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--kiosk-dialog-scrim);
}

/* --- 共用：頂列、對話框、指令膠囊、Toast、進度 --- */
.kv-screen--dialog > .kv-topbar,
.kv-screen--media > .kv-topbar,
.kv-screen--cover > .kv-topbar,
.kv-screen--standby > .kv-topbar {
  position: absolute;
  top: var(--kiosk-topbar-top);
  left: var(--kiosk-margin);
  right: var(--kiosk-margin);
  z-index: 6;
}
.kv-screen--dialog > .kv-pill,
.kv-screen--cover > .kv-pill,
.kv-screen--media > .kv-pill,
.kv-screen--standby > .kv-pill,
.kv-screen--dialog > .kv-actions,
.kv-screen--cover > .kv-actions,
.kv-screen--media > .kv-actions,
.kv-screen--standby > .kv-actions {
  position: absolute;
  left: var(--kiosk-pill-x);
  bottom: var(--kiosk-pill-bottom);
  z-index: 5;
}
.kv-screen--dialog > .kv-cmd,
.kv-screen--media > .kv-cmd {
  position: absolute;
  left: var(--kiosk-cmd-x);
  bottom: var(--kiosk-pill-bottom);
  z-index: 5;
}
.kv-screen--dialog > .kv-toast,
.kv-screen--media > .kv-toast,
.kv-screen--cover > .kv-toast,
.kv-screen--standby > .kv-toast {
  position: absolute;
  left: 50%;
  bottom: var(--kiosk-toast-bottom);
  transform: translateX(-50%);
  z-index: 5;
}
.kv-screen--dialog > .kv-progress {
  position: absolute;
  top: 56px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
}
.kv-screen--dialog > .kv-dim,
.kv-screen--cover > .kv-dim,
.kv-screen--media > .kv-dim,
.kv-screen--standby > .kv-dim {
  z-index: 4;
}

/* --- dialog --- */
.kv-screen--dialog > .kv-transcript,
.kv-screen--cover > .kv-transcript {
  position: absolute;
  top: var(--kiosk-ai-top);
  left: var(--kiosk-margin);
  width: var(--kiosk-ai-w);
  z-index: 2;
}
.kv-screen--dialog > .kv-status {
  position: absolute;
  top: var(--kiosk-status-top);
  left: var(--kiosk-margin);
  z-index: 2;
}
.kv-screen--dialog > .kv-safe,
.kv-screen--dialog > .kv-chips,
.kv-screen--cover > .kv-chips {
  position: absolute;
  top: var(--kiosk-safe-top);
  left: var(--kiosk-margin);
  z-index: 2;
}
/* AI 只有 1 行：safe area 上移到 332、高 508 */
.kv-screen--one-line > .kv-transcript {
  max-height: 72px;
}
.kv-screen--one-line > .kv-safe {
  top: var(--kiosk-safe-top-1line);
  height: var(--kiosk-safe-h-1line);
}
/* 對話框隱藏：safe area 延伸到 y 1016（Review 頁、頂列倒數時）。
   有 .kv-actions 時 safe area 不延伸（底部那格被動作列用掉）。 */
.kv-screen--no-pill > .kv-safe,
.kv-screen--countdown > .kv-safe {
  height: var(--kiosk-safe-h-ext);
}
.kv-screen--no-pill:has(> .kv-actions) > .kv-safe,
.kv-screen--countdown:has(> .kv-actions) > .kv-safe {
  height: var(--kiosk-safe-h);
}
.kv-screen--one-line.kv-screen--no-pill > .kv-safe,
.kv-screen--one-line.kv-screen--countdown > .kv-safe {
  height: var(--kiosk-safe-h-1line-ext);
}
.kv-screen--no-pill > .kv-pill,
.kv-screen--countdown > .kv-pill {
  display: none;
}
/* 頂列有倒數：頂列另外上移 */
.kv-screen--countdown > .kv-topbar {
  top: var(--kiosk-topbar-count-top);
  height: var(--kiosk-topbar-count-h);
}

/* ================================================ 三行 AI、觸控模式、倒數疊加（2026-10-14 用影片定下來的三個修飾）
   --three-line：AI 區三行（216），safe area 下移到 368。只用在 --touch 或純文字回答。
   --touch：純觸控模式（A08 之後、連續 3 組退觸控後的待命版）。對話框拿掉、三個 chips 橫排住進底部那格
            （「底部那格永遠是你怎麼跟我說話」）、卡片與 QR 撐滿內容區（2 行 360、3 行 288；QR 碼 = 卡高 − 132，268 卡時正好 140）。
   --notice：A09 預告收單。頂列右側的日期時間換成倒數膠囊，其他都不動（跟 --countdown 不同：不動頂列位置、對話框、safe area）；
            倒數膠囊放在 .kv-topbar 最後一個子元素，頂列加 .kv-topbar--countdown 變 48 高。可疊在任何畫面。 */
.kv-screen--three-line > .kv-transcript {
  max-height: var(--kiosk-ai-h-3line);
}
.kv-screen--three-line > .kv-safe {
  top: var(--kiosk-safe-top-3line);
}
.kv-screen--touch > .kv-pill {
  display: none;
}
.kv-screen--touch > .kv-chips {
  top: auto;
  bottom: var(--kiosk-pill-bottom);
  left: var(--kiosk-pill-x);
  width: var(--kiosk-pill-w);
  height: var(--kiosk-slot-chips);
  flex-direction: row;
  justify-content: center;
  align-items: center;
}
.kv-screen--touch > .kv-safe {
  height: var(--kiosk-safe-h-touch);
  align-items: stretch;
}
.kv-screen--touch.kv-screen--three-line > .kv-safe {
  height: var(--kiosk-safe-h-touch-3line);
}
.kv-screen--touch > .kv-safe > .kv-card {
  height: auto;
}
.kv-screen--touch > .kv-safe > .kv-qr {
  height: auto;
  width: var(--kiosk-safe-h-touch);
  --kiosk-qr-code: calc(var(--kiosk-safe-h-touch) - 132px);
}
.kv-screen--touch.kv-screen--three-line > .kv-safe > .kv-qr {
  width: var(--kiosk-safe-h-touch-3line);
  --kiosk-qr-code: calc(var(--kiosk-safe-h-touch-3line) - 132px);
}
/* chips 按下態（互動規則：填色升一階 + 縮 97%、120ms） */
.kv-chip {
  transition:
    transform var(--kiosk-dur-press) var(--kiosk-ease),
    background-color var(--kiosk-dur-press) var(--kiosk-ease);
}
.kv-chip:active,
.kv-chip--down {
  background: var(--kiosk-border);
  transform: scale(0.97);
}
.kv-screen--notice > .kv-topbar > .kv-topbar__meta {
  display: none;
}
/* E05 在預告上：說明用字幕位，「重新連線中」小字列放在字幕下方（跟對話畫面的 .kv-status 同 y） */
.kv-screen--media > .kv-status {
  position: absolute;
  top: var(--kiosk-status-top);
  left: var(--kiosk-margin);
  z-index: 3;
}

/* 思考態放在 AI 區本身（回答會出現的位置）：A04 */
.kv-screen--dialog > .kv-status--in-ai {
  top: var(--kiosk-ai-top);
  height: 72px;
}

/* --- media --- */
.kv-screen--media::before,
.kv-screen--media::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: var(--kiosk-scrim-h);
  pointer-events: none;
  z-index: 1;
}
.kv-screen--media::before {
  top: 0;
  background: var(--kiosk-scrim-top);
}
.kv-screen--scrim-tall::before {
  height: var(--kiosk-scrim-h-tall); /* 預告：上遮罩 360 */
}
.kv-screen--media > .kv-media-bar {
  position: absolute;
  left: var(--kiosk-margin);
  bottom: var(--kiosk-media-bar-bottom);
  z-index: 2;
}
/* 提示膠囊移到右上角，不擋影片內容（設計師 2026-10-01）。v2.9：改為暫停+停止按鈕列。 */
.kv-screen--media > .kv-media-bar__hint {
  position: absolute;
  top: var(--kiosk-topbar-top);
  right: var(--kiosk-margin);
  z-index: 2;
}
.kv-screen--media > .kv-media-controls {
  position: absolute;
  bottom: var(--kiosk-media-bar-bottom);
  right: var(--kiosk-margin);
  display: flex;
  gap: 16px;
  z-index: 2;
}
.kv-screen--media > .kv-media-progress {
  position: absolute;
  left: var(--kiosk-margin);
  right: var(--kiosk-margin);
  bottom: var(--kiosk-media-progress-bottom);
  z-index: 2;
}
.kv-screen--media::after {
  bottom: 0;
  background: var(--kiosk-scrim-bottom);
}
.kv-screen--media > .kv-transcript {
  position: absolute;
  top: var(--kiosk-caption-top);
  left: var(--kiosk-margin);
  right: var(--kiosk-margin);
  font: var(--kiosk-type-caption);
  max-height: none;
  text-shadow: var(--kiosk-text-shadow-media);
  z-index: 2;
}
/* Focus 層級（拍照）：頂列隱藏、字幕上移到 y 64、只留任務內容。
   收音狀態由 Kebbi 光條承接；光條不可用時用 .kv-mic--dot 放右上角（fallback）。 */
.kv-screen--camera > .kv-topbar {
  display: none;
}
.kv-screen--camera > .kv-transcript {
  top: var(--kiosk-caption-top-camera);
}
.kv-screen--camera > .kv-hint,
.kv-screen--dialog > .kv-hint,
.kv-screen--cover > .kv-hint {
  position: absolute;
  left: 50%;
  bottom: var(--kiosk-toast-bottom);
  transform: translateX(-50%);
  z-index: 5;
}
/* 有動作列或 CTA 按鈕時，提示移到動作列上方 */
.kv-screen--dialog > .kv-actions ~ .kv-hint,
.kv-screen--cover > .kv-actions ~ .kv-hint {
  bottom: 156px; /* pill-bottom 44 + pill-h 96 + gap 16 */
}
.kv-screen--camera > .kv-mic--dot {
  position: absolute;
  top: var(--kiosk-topbar-top);
  right: var(--kiosk-margin);
  z-index: 6;
}

/* 媒體與 standby、cover 上的頂列：logo 加陰影、收音狀態包膠囊 */
.kv-screen--media .kv-logo,
.kv-screen--standby .kv-logo,
.kv-screen--cover .kv-logo {
  text-shadow: var(--kiosk-text-shadow-logo);
}
/* 亮色底圖：日期時間切深色（預設白色；加 .kv-screen--bg-light 切換） */
.kv-screen--bg-light .kv-date,
.kv-screen--bg-light .kv-clock {
  color: rgba(0, 0, 0, 0.6);
}
.kv-screen--media .kv-mic,
.kv-screen--standby .kv-mic,
.kv-screen--cover .kv-mic {
  background: var(--kiosk-overlay-media);
  border-radius: var(--kiosk-radius-pill);
  padding: 8px 16px 8px 12px;
}

/* --- cover --- */
.kv-screen--cover::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--kiosk-scrim-cover);
  pointer-events: none;
  z-index: 1;
}
.kv-screen--cover-strong::before {
  background: var(--kiosk-scrim-cover-strong);
}
/* Photo Idle（P01）：海報滿版 + 左遮罩，獨立 CTA 按鈕 + 小提示 */
.kv-screen--cover > .kv-btn {
  position: absolute;
  bottom: var(--kiosk-pill-bottom);
  left: var(--kiosk-margin);
  z-index: 5;
}
.kv-screen--cover > .kv-cta-hint {
  position: absolute;
  bottom: var(--kiosk-cta-hint-bottom);
  left: var(--kiosk-margin);
  z-index: 5;
}
/* 海報自己有字時不壓我們的字，也不壓遮罩（Moving A01）：只留頂列與路線膠囊 */
.kv-screen--no-scrim::before {
  display: none;
}
.kv-screen--cover > .kv-transcript {
  width: var(--kiosk-ai-w-cover);
}
.kv-screen--cover > .kv-route {
  position: absolute;
  top: var(--kiosk-route-top);
  right: var(--kiosk-margin);
  z-index: 6;
}

/* --- standby --- */
/* 去字 key art 底（W01–W02、X01–X03）· 設計師 2026-10-05 定案，取代原本 Welcome 的置中紫色光暈（glow 修飾已移除）。
   圖以 --kiosk-keyart-pos 為焦點縮放、壓到 44%，::before 再疊一層置中暗角，置中大標與左欄字才可讀。
   四個值都在 tokens.css，改那裡就好；沒放 .kv-art 的 standby 畫面不會有暗角（:has()，Chromium 105+）。 */
.kv-screen--standby > .kv-art > img {
  object-position: var(--kiosk-keyart-pos);
  transform-origin: var(--kiosk-keyart-pos);
  transform: scale(var(--kiosk-keyart-scale));
  opacity: var(--kiosk-keyart-opacity);
}
.kv-screen--standby:has(> .kv-art)::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--kiosk-vignette-bg);
  opacity: var(--kiosk-keyart-vignette);
  pointer-events: none;
  z-index: 1;
}
.kv-screen--standby > .kv-hero {
  position: absolute;
  inset: 0;
  z-index: 2;
}
/* cover 版型上的左欄 hero（E09 回充電的大字）：同 standby 的 hero--left 寬，垂直置中 */
.kv-screen--cover > .kv-hero--left {
  position: absolute;
  left: var(--kiosk-margin);
  top: 0;
  bottom: 0;
  width: var(--kiosk-ai-w-cover);
  justify-content: center;
  z-index: 2;
}
.kv-screen--standby > .kv-hero--left {
  left: var(--kiosk-margin);
  right: auto;
  width: var(--kiosk-ai-w-cover);
}
.kv-screen--standby > .kv-qr {
  position: absolute;
  right: var(--kiosk-margin);
  top: var(--kiosk-standby-qr-top);
  z-index: 2;
}
.kv-screen--standby > .kv-safe {
  position: absolute;
  top: var(--kiosk-safe-top);
  left: var(--kiosk-margin);
  z-index: 2;
}

/* =========================================================== Grid guides
   開發用格線疊層。加 .kv-guides 到 .kv-screen 才顯示。 */
.kv-guide {
  display: none;
  position: absolute;
  z-index: 50;
  pointer-events: none;
  border: 3px dashed;
}
.kv-guide__tag {
  position: absolute;
  right: 12px;
  top: 10px;
  font: 600 22px/1 var(--kiosk-font-mono);
  white-space: nowrap;
}
.kv-guides .kv-guide {
  display: block;
}
.kv-guide--topbar {
  top: var(--kiosk-topbar-top);
  left: var(--kiosk-margin);
  width: var(--kiosk-ai-w);
  height: var(--kiosk-topbar-h);
  border-color: rgba(163, 163, 163, 1);
  background: rgba(163, 163, 163, 0.07);
  color: rgba(163, 163, 163, 1);
}
.kv-guide--ai {
  top: var(--kiosk-ai-top);
  left: var(--kiosk-margin);
  width: var(--kiosk-ai-w);
  height: var(--kiosk-ai-h);
  border-color: rgba(34, 211, 238, 1);
  background: rgba(34, 211, 238, 0.07);
  color: rgba(34, 211, 238, 1);
}
.kv-guide--safe {
  top: var(--kiosk-safe-top);
  left: var(--kiosk-margin);
  width: var(--kiosk-ai-w);
  height: var(--kiosk-safe-h);
  border-color: rgba(236, 72, 153, 1);
  background: rgba(236, 72, 153, 0.07);
  color: rgba(236, 72, 153, 1);
}
.kv-guide--safe-one-line {
  top: var(--kiosk-safe-top-1line);
  height: var(--kiosk-safe-h-1line);
}
.kv-guide--safe-extended {
  height: var(--kiosk-safe-h-ext);
}
.kv-guide--pill {
  left: var(--kiosk-pill-x);
  top: calc(var(--kiosk-center-h) - var(--kiosk-pill-bottom) - var(--kiosk-pill-h-listen));
  width: var(--kiosk-pill-w);
  height: var(--kiosk-pill-h-listen);
  border-color: rgba(250, 204, 21, 1);
  background: rgba(250, 204, 21, 0.07);
  color: rgba(250, 204, 21, 1);
}

/* ==========================================================================
   Prototype 狀態機（data-chrome / data-mic）
   工程師在 .kv-screen 上設 data-chrome 和 data-mic，CSS 自動控制顯示。
   切換用 200ms opacity transition。
   ========================================================================== */

/* --- transition 基底 --- */
.kv-screen .kv-topbar,
.kv-screen .kv-topbar__meta,
.kv-screen .kv-mic,
.kv-screen .kv-pill,
.kv-screen .kv-actions,
.kv-screen > .kv-btn,
.kv-screen > .kv-cta-hint {
  transition: opacity var(--kiosk-dur-chrome) var(--kiosk-ease);
}

/* --- data-chrome="ambient"：隱藏日期時間、對話框、CTA --- */
.kv-screen[data-chrome="ambient"] .kv-topbar__meta,
.kv-screen[data-chrome="ambient"] .kv-pill,
.kv-screen[data-chrome="ambient"] .kv-actions,
.kv-screen[data-chrome="ambient"] > .kv-btn,
.kv-screen[data-chrome="ambient"] > .kv-cta-hint {
  opacity: 0;
  pointer-events: none;
}

/* --- data-chrome="focus"：隱藏整個頂列（logo + mic + 時間）、對話框、CTA --- */
.kv-screen[data-chrome="focus"] .kv-topbar,
.kv-screen[data-chrome="focus"] .kv-pill,
.kv-screen[data-chrome="focus"] .kv-actions,
.kv-screen[data-chrome="focus"] > .kv-btn,
.kv-screen[data-chrome="focus"] > .kv-cta-hint {
  opacity: 0;
  pointer-events: none;
}

/* --- data-mic：收音狀態驅動 ---
   設定 data-mic 時覆寫 .kv-mic 的光點顏色、標籤文字、光暈。
   實際 class（kv-mic--full / --off / --command / --dot）仍可用於靜態展示，
   data-mic 在 Prototype 階段優先。 */

.kv-screen[data-mic="full"] .kv-mic__dot {
  background: var(--kiosk-grow);
  box-shadow: var(--kiosk-halo-full);
}
.kv-screen[data-mic="off"] .kv-mic__dot {
  background: var(--kiosk-text-disabled);
  box-shadow: none;
}
.kv-screen[data-mic="cmd"] .kv-mic__dot {
  background: var(--kiosk-warning);
  box-shadow: var(--kiosk-halo-command);
}
/* data-mic="dot"：只顯示光點，隱藏標籤（FOCUS fallback） */
.kv-screen[data-mic="dot"] .kv-mic__label {
  display: none;
}
