/* Reference: 原神开头.mp4, 3.75–5.0 s: logo over white -> defocused scene -> focus. */
#intro {
  position: fixed; inset: 0; z-index: 3000; overflow: hidden;
  background: #fff; isolation: isolate;
  transition: opacity 600ms ease;
  --intro-height: 100vh;
  --intro-glow-rgb: 220, 190, 212;
  --intro-glow-light: 239, 226, 236;
}
@supports (height: 100dvh) { #intro { --intro-height: 100dvh; } }
#intro[hidden] { display: none; }
#intro.is-out { opacity: 0; pointer-events: none; }
#intro-v1, #intro-v2, #intro .intro-white {
  position: absolute; inset: 0; width: 100%; height: 100%;
}
#intro #intro-v1 {
  z-index: 2; object-fit: contain; mix-blend-mode: multiply;
  pointer-events: none;
}
#intro #intro-v2 { z-index: 0; overflow: hidden; }
#intro .intro-white { z-index: 1; background: #fff; pointer-events: none; }
#intro .intro-shell {
  position: absolute; inset: -32px; width: calc(100% + 64px); height: calc(100% + 64px);
  object-fit: cover; filter: blur(28px) saturate(.85) brightness(.84);
  background: #e7e9e5;
}
#intro .intro-frame {
  position: absolute; left: 50%; top: 50%;
  width: min(100vw, calc(var(--intro-height) * 1080 / 1522));
  height: min(var(--intro-height), calc(100vw * 1522 / 1080));
  transform: translate(-50%, -50%);
}
#intro .intro-frame-in { width: 100%; height: 100%; }
/* 2026-10-17 兜底（先生报「画面崩了」）：主片必须按纸框比例装进去，
   不许被任何全局 video 规则改成铺满 —— 加 !important 把这条钉死。 */
#intro #intro-scene, #intro #intro-ripple {
  display: block; width: 100%; height: 100%; object-fit: contain;
  /* A small feather joins the actual frame to its live background. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 14px, #000 calc(100% - 14px), transparent), linear-gradient(0deg, transparent, #000 14px, #000 calc(100% - 14px), transparent);
  -webkit-mask-composite: source-in;
  mask-image: linear-gradient(90deg, transparent, #000 14px, #000 calc(100% - 14px), transparent), linear-gradient(0deg, transparent, #000 14px, #000 calc(100% - 14px), transparent);
  mask-composite: intersect;
}
#intro #intro-scene {
  width: 100% !important; height: 100% !important;
  object-fit: contain !important; object-position: center center !important;
  max-width: 100% !important; max-height: 100% !important;
}
#intro .intro-frame, #intro .intro-frame-in { overflow: hidden; }
/* White recedes under the logo; there is no added circle/flash or hard scene cut. */
#intro[data-state="reveal"] .intro-white { animation: introWhite 850ms linear both; }
#intro[data-state="reveal"] .intro-frame-in { animation: introFocus 1350ms cubic-bezier(.2,.6,.3,1) both; }
#intro[data-state="v2"] .intro-white, #intro[data-state="v2"] #intro-v1 { visibility: hidden; }
@keyframes introWhite { from { opacity: 1; } to { opacity: 0; } }
@keyframes introFocus {
  from { filter: blur(12px) brightness(1.32); transform: scale(1.045); }
  to { filter: blur(0) brightness(1); transform: scale(1); }
}
#intro .intro-controls {
  position: absolute; top: max(16px, env(safe-area-inset-top)); right: max(16px, env(safe-area-inset-right));
  z-index: 3; display: flex; gap: 8px; opacity: 0;
  transition: opacity 200ms ease;
}
#intro:hover .intro-controls, #intro:focus-within .intro-controls,
#intro[data-state="v2"] .intro-controls, #intro.needs-play .intro-controls { opacity: 1; }
#intro .intro-btn {
  min-height: 44px; padding: 10px 14px; cursor: pointer;
  font: 600 12px/1.2 var(--wl-hei, sans-serif);
  color: #16181a; background: rgba(255,255,255,.9);
  border: 1px solid rgba(22,24,26,.28); border-radius: 2px;
}
#intro .intro-btn:hover { background: #fff; }
#intro .intro-btn:focus-visible { outline: 2px solid #14788c; outline-offset: 3px; }
#intro .intro-status {
  position: absolute; bottom: max(24px, env(safe-area-inset-bottom)); left: 0; right: 0;
  z-index: 3; margin: 0; text-align: center; color: #474d52; font: 13px/1.5 sans-serif;
}
#intro .intro-status:empty { display: none; }
@media (prefers-reduced-motion: reduce) {
  #intro, #intro * { animation: none !important; transition: none !important; }
}

#intro.is-paused *, #intro.is-paused .intro-white { animation-play-state: paused !important; }

/* ══ 手机上给信封一点提示（2026-10-03 · 先生："手机上让信封微微搏动"）════════
   为什么需要它：
     · 开场视频 kawano-proportional.mp4 长 **116 秒**；
     · 三个按钮（开启声音/暂停/跳过）被**有意**藏起来（见上面那条注释），
       "信封本身就是进入的控制" —— 点了它 **2 秒导航就活、3 秒完全进入**；
     · 但信封靠的是 `:hover::before` 的光晕提示，而**手机没有悬停**，
       屏幕上没有任何东西告诉手指"这里可以点"，于是人可能干等两分钟。
   所以只在**没有悬停能力**的设备上，让那圈光晕自己轻轻呼吸。
   ⚠️ 电脑端一字不动：这条整段包在 `@media (hover: none)` 里。
   ⚠️ 用 opacity 不用 transform：`::before` 身上的 `translate(-50%,-50%)` 是定位用的，
      动 transform 会把它挪走；opacity 只让光晕明暗，位置纹丝不动。
   ⚠️ 幅度要**小**：这是一句"可以点这里"，不是一声喊。.30↔.55 在手机屏幕上
      刚好能被余光扫到，又不至于像广告。
   ⚠️ **为什么用 max-width 而不是 `@media (hover: none)`**（2026-10-03 实测教训）：
      祥先写的是 `@media (hover: none)`，然后发现**在无头 Edge 里永远不命中** ——
      `Emulation.setDeviceMetricsOverride` 只改尺寸，**不改触摸能力**，
      无头浏览器照样报 `(hover: hover) = true`。
      于是祥既没法在这台机器上验证它，也没法声称"手机上一定生效"。
      改用 `max-width` 判断窄屏：跟这个文件里既有的窄屏段（`max-width: 520px`）一个路子，
      在真手机上同样命中，**而且祥在这里能真正验穿**。
      这是"宁可选一条自己能验证的路"那条原则。 */
@keyframes introEnvelopeBreath {
  0%, 100% { opacity: .30; }
  50%      { opacity: .55; }
}
@media (max-width: 520px) {
  #intro[data-state="v2"] #intro-envelope::before {
    animation: introEnvelopeBreath 1900ms ease-in-out 2600ms infinite;
  }
  /* 进场动画一开始（data-state="entering"）就停 —— 那时候正在穿进门里，
     再闪就是噪音。 */
  #intro[data-state="entering"] #intro-envelope::before { animation: none; }
}
/* 声明"晕动不适"的人不该被任何东西闪到：把动画换成**常亮但很淡**的光晕，
   提示仍在，一个像素都不动。注意精简动画那条全局规则里就带 !important，
   所以这里必须也用 !important 才压得住。 */
@media (prefers-reduced-motion: reduce) and (max-width: 520px) {
  #intro[data-state="v2"] #intro-envelope::before { animation: none !important; opacity: .34 !important; }
}

/* Envelope seal: normalized against the original 1080 × 1522 composition. */
#intro .intro-frame-in { position: relative; }
#intro-envelope {
  position: absolute; left: 54.4%; top: 46.9%; transform: translate(-50%, -50%);
  width: 25%; height: 12%; min-width: 44px; min-height: 44px;
  border: 0; padding: 0; background: transparent; cursor: pointer;
  border-radius: 4px; -webkit-tap-highlight-color: transparent;
  visibility: hidden; touch-action: manipulation;
}
#intro[data-state="v2"] #intro-envelope { visibility: visible; }
#intro-envelope::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 52%; aspect-ratio: 1; transform: translate(-50%, -50%);
  background: radial-gradient(circle closest-side, rgba(var(--intro-glow-light),.65), rgba(var(--intro-glow-rgb),.22) 40%, transparent 70%);
  opacity: 0; transition: opacity 220ms ease; pointer-events: none;
}
#intro-envelope:hover::before, #intro-envelope:focus-visible::before { opacity: 1; }
#intro-envelope:focus-visible { outline: 2px solid #14788c; outline-offset: 5px; }
#intro .intro-envelope-hint {
  position: absolute; left: 50%; top: calc(100% + 8px); transform: translateX(-50%);
  width: max-content; padding: 5px 9px; background: rgba(255,255,255,.9);
  color: #474d52; font: 12px/1.5 var(--wl-hei, sans-serif);
  pointer-events: none; transition: opacity 200ms ease;
}
#intro .intro-portal { position: absolute; inset: 0; z-index: 4; pointer-events: none; visibility: hidden; }
#intro[data-state="entering"] .intro-portal { visibility: visible; }
#intro .intro-wave, #intro .intro-flash {
  position: absolute; left: var(--envelope-x); top: var(--envelope-y);
  transform: translate(-50%, -50%); aspect-ratio: 1; opacity: 0;
}
#intro .intro-wave {
  width: min(78vmin, 700px);
  background: radial-gradient(circle closest-side, transparent 43%, rgba(var(--intro-glow-light),.12) 48%, rgba(var(--intro-glow-light),.66) 57%, rgba(var(--intro-glow-rgb),.6) 63%, transparent 73%);
  filter: blur(5px);
}
#intro[data-state="entering"] .intro-wave { animation: envelopeWave 1100ms cubic-bezier(.15,.55,.25,1) both; }
#intro .intro-flash {
  width: var(--portal-size);
  background: radial-gradient(circle closest-side, #fff 0%, #fff 65%, rgba(255,255,255,.85) 78%, rgba(255,255,255,0) 100%);
}
@keyframes envelopeWave {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(.10); }
  18% { opacity: 1; }
  65% { opacity: .8; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.55); }
}
#intro[data-state="entering"] #intro-v1,
#intro[data-state="entering"] .intro-white { visibility: hidden; }
#intro[data-state="entering"] .intro-frame-in { animation: envelopeApproach 1800ms ease-in both; }
@keyframes envelopeApproach {
  from { transform: scale(1); filter: brightness(1); }
  to { transform: scale(1.05); filter: brightness(1.12); }
}
#intro[data-state="entering"] .intro-controls { opacity: 0; pointer-events: none; }
#intro[data-state="entering"] { transition: opacity 1100ms ease-out; }
#intro.entry-covered #intro-v2 { visibility: hidden; }
#intro.entry-covered .intro-portal { visibility: hidden; }
@media (prefers-reduced-motion: reduce) {
  #intro .intro-wave, #intro .intro-frame-in { animation: none !important; }
}

/* Keep the entrance free of visible labels; the envelope remains the entry control. */
#intro .intro-controls, #intro .intro-envelope-hint { display: none; }

/* Refracted live pixels share the video's exact geometry and edge feather. */
#intro #intro-ripple { position: absolute; inset: 0; pointer-events: none; visibility: hidden; }
#intro .has-ripple #intro-ripple { visibility: visible; }
#intro .has-ripple #intro-scene { visibility: hidden; }
#intro[data-state="entering"] .intro-wave { opacity: .4; animation: none; visibility: hidden; }
@media (prefers-reduced-motion: reduce) { #intro #intro-ripple { display: none; } }

/* Crop of the original 1920 x 1080 logo film, at exactly the original scale. */
#intro-logo { position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); width:min(calc(100vw * 530 / 1920),calc(var(--intro-height) * 530 / 1080)); height:auto; aspect-ratio:530 / 108; display:block; }

