@charset "utf-8";
/* =============================================================================
   MISSIONMAN v5 — オープニング（上映開始）
   ---------------------------------------------------------------------------
   Concept A の視覚言語だけで組む。新しい色は1つも足していない。
     - 送り穴      : .perf と同じ格子（44px 周期 / 14-30px の穴）
     - スレート    : .slate と同じ組み（REEL タグ＋章名＋タイムコード）
     - 書体        : --cond（英字ラベル）/ --jp（本人の言葉）
     - 色          : --ag-ground / --ag-ink-light / --ag-amber / --ag-paper のみ
     - 粒子・傷    : aging.css のテクスチャ（--ag-tex-grain-*）を流用

   隠しについての規約:
     このファイルの中で opacity:0 を書いてよいのは **.op の内側だけ**。
     .op 自体は HTML で hidden が付いており、JS が外したときにしか存在しない。
     ＝ JS が動かなければオーバーレイは一度も現れず、本編がそのまま読める。
     そのため [hidden] は必ず !important で守る（display 指定に負けさせない）。
   ============================================================================= */

/* ==== 最優先。どんな display 指定より hidden を強くする ==================== */
.op[hidden]{display:none !important}

.op{
  position:fixed;inset:0;z-index:200;
  display:grid;
  grid-template-rows:auto 1fr auto;
  overflow:hidden;
  background-color:var(--op-bg,#0F1013);
  color:var(--ag-ink-light);
  /* 画面全体が一度に切り替わる面なので、内側の合成をここで閉じる */
  isolation:isolate;
  /* 長押し・二度押しでテキストが選択されるのを防ぐ（モバイル） */
  -webkit-user-select:none;user-select:none;
  -webkit-tap-highlight-color:transparent;
  touch-action:manipulation;
}

/* オープニング中は本編を動かさない。
   data-opening（判断）ではなく data-op-lock（実際に開けた）で締める。
   ＝ オーバーレイを開けなかった場合にスクロールだけ止まる事故を作らない。 */
html[data-op-lock="1"],
html[data-op-lock="1"] body{overflow:hidden}

/* ------------------------------------------------------------- 送り穴の帯 */
/* .perf と同じ格子・同じ周期。デスクトップでは幅も同じ 26px にしてあるので、
   ハードカットの瞬間、穴の位置がそのまま本編の .perf へ受け継がれる。 */
.op-strip{
  position:absolute;inset-block:0;z-index:3;
  width:var(--op-perf,10px);
  overflow:hidden;pointer-events:none;
  background:rgba(15,16,19,.72);
  border-inline:1px solid rgba(242,239,233,.10);
}
.op-strip--l{inset-inline-start:0}
.op-strip--r{inset-inline-end:0}
.op-strip > span{
  display:block;width:100%;height:300%;
  background-image:repeating-linear-gradient(
    to bottom,
    transparent 0 14px,
    rgba(242,239,233,.24) 14px 30px,
    transparent 30px 44px);
  background-size:100% 44px;
  animation:op-run 2.6s linear infinite;
}
.op-strip--r > span{animation-delay:-1.3s}
@keyframes op-run{from{translate:0 0}to{translate:0 -44px}}
@media (min-width:1180px){
  .op{--op-perf:26px}     /* 本編の --perf と同値。カットで穴が連続する */
}

/* --------------------------------------------------------------- 映写ランプ */
/* 中央からにじむ温かい光。カーソルで少しだけ動く（--op-lx / --op-ly は JS）。 */
.op-lamp{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(120% 78% at var(--op-lx,50%) var(--op-ly,46%),
      rgba(218,156,23,.16) 0%,
      rgba(218,156,23,.06) 34%,
      rgba(15,16,19,0) 68%);
  opacity:0;
  transition:opacity .5s var(--mo-out,ease-out),background-position .6s ease-out;
}
.op[data-phase]:not([data-phase="black"]) .op-lamp{opacity:1;animation:op-lamp 3.4s ease-in-out infinite}
@keyframes op-lamp{
  0%,100%{opacity:.86}
  38%    {opacity:1}
  61%    {opacity:.92}
}

/* ----------------------------------------------------------- 粒子・傷・埃 */
/* inset は 0 にすること。粒子の移動は background-position で作っており、
   要素をはみ出させる必要が無い。負の inset を入れると 320px で
   tools/check_widths.py が横はみ出しとして検出する（2026-08-06 に実測）。 */
.op-grain{
  position:absolute;inset:0;z-index:5;pointer-events:none;
  opacity:0;
  background-image:var(--ag-tex-grain-base),var(--ag-tex-grain-heavy);
  background-size:180px 180px,240px 240px;
  mix-blend-mode:soft-light;
  transition:opacity .4s linear;
}
.op[data-phase]:not([data-phase="black"]) .op-grain{opacity:.85;animation:op-grain .28s steps(1,end) infinite}
/* 粒子は「毎コマ位置が変わる」のが本体。動かす量は大きくしない */
@keyframes op-grain{
  0%  {background-position:0 0,       0 0}
  25% {background-position:-38px 22px, 30px -18px}
  50% {background-position:26px -30px,-24px 26px}
  75% {background-position:-18px -14px,18px 34px}
  100%{background-position:34px 18px, -30px -22px}
}
/* 縦の傷。フィルムが擦れて付いた線。数本だけ、薄く */
.op-grain::after{
  content:"";position:absolute;inset:0;
  background-image:
    linear-gradient(to right,rgba(242,239,233,.18) 0 1px,transparent 1px),
    linear-gradient(to right,rgba(242,239,233,.10) 0 1px,transparent 1px),
    linear-gradient(to right,rgba(15,16,19,.30) 0 2px,transparent 2px);
  background-repeat:no-repeat;
  background-position:22% 0,63% 0,81% 0;
  background-size:1px 100%,1px 100%,2px 100%;
  animation:op-scratch 1.9s steps(1,end) infinite;
}
@keyframes op-scratch{
  0%  {background-position:22% 0,63% 0,81% 0;opacity:.7}
  33% {background-position:28% 0,58% 0,77% 0;opacity:.35}
  66% {background-position:19% 0,66% 0,86% 0;opacity:.6}
  100%{background-position:24% 0,61% 0,79% 0;opacity:.28}
}

/* --------------------------------------------------------- 映写ゲート（画面） */
/* フィルムが映写窓を通るときの微かな縦揺れ。0.5px 程度に留める。 */
.op-gate{
  position:relative;z-index:4;
  grid-row:2;
  display:grid;
  place-items:center;
  padding-inline:clamp(28px,7vw,80px);
  animation:op-weave 2.1s ease-in-out infinite;
}
@keyframes op-weave{
  0%,100%{transform:translate3d(0,0,0)}
  22%    {transform:translate3d(.3px,-.5px,0)}
  47%    {transform:translate3d(-.4px,.4px,0)}
  61%    {transform:translate3d(0,-.7px,0) rotate(.035deg)}   /* 一瞬だけ斜めにずれる */
  78%    {transform:translate3d(.2px,.3px,0)}
}

/* ------------------------------------------------------------ 上下のスレート */
.op-bar{
  position:relative;z-index:6;
  display:flex;align-items:center;justify-content:space-between;
  gap:.8em 1.2em;flex-wrap:wrap;
  padding:calc(env(safe-area-inset-top,0px) + clamp(12px,2.4vw,22px))
          clamp(22px,5vw,44px)
          clamp(12px,2.4vw,22px);
}
.op-bar--foot{
  grid-row:3;
  padding-block:clamp(12px,2.4vw,22px)
                calc(env(safe-area-inset-bottom,0px) + clamp(14px,2.6vw,24px));
}
.op-slate{
  display:flex;align-items:center;flex-wrap:wrap;gap:.5em .9em;
  margin:0;
  font-family:var(--cond);font-weight:700;
  font-size:var(--step--1);letter-spacing:.2em;text-transform:uppercase;
  line-height:1.2;
}
/* .slate と同じカチンコの縞 */
.op-slate::before{
  content:"";display:block;flex:none;width:44px;height:13px;
  background-image:repeating-linear-gradient(112deg,currentColor 0 7px,transparent 7px 14px);
  opacity:.85;
}
.op-slate-reel{
  padding:.24em .6em;
  background-color:var(--ag-amber);color:var(--ag-ink-dark);
  font-variant-numeric:tabular-nums;
}
.op-slate-name{opacity:.95}
.op-tc{
  font-weight:600;opacity:.62;letter-spacing:.16em;
  font-variant-numeric:tabular-nums;
}
/* フィルムヘッドの焼き込み文字。カウントの前後だけ出る */
.op-mark{
  margin:0;
  font-family:var(--cond);font-weight:600;
  font-size:var(--step--2);letter-spacing:.28em;text-transform:uppercase;
  opacity:0;transition:opacity .3s linear;
}
.op[data-phase="leader"] .op-mark,
.op[data-phase="count"] .op-mark{opacity:.55}
.op-notice{
  margin:0;max-width:26em;
  font-family:var(--jp);font-size:var(--step--2);letter-spacing:.06em;
  line-height:1.7;opacity:0;transition:opacity .4s linear;
}
.op[data-phase="leader"] .op-notice,
.op[data-phase="count"] .op-notice{opacity:.42}

/* ----------------------------------------------------------- カウントリーダー */
.op-count{
  position:absolute;z-index:4;
  inset-block-start:50%;inset-inline-start:50%;
  translate:-50% -50%;
  width:clamp(148px,30vw,232px);aspect-ratio:1;
  display:grid;place-items:center;
  opacity:0;pointer-events:none;
}
.op[data-phase="count"] .op-count{opacity:1}
/* 外周の円と十字。Academy leader のマーク */
.op-count::before{
  content:"";position:absolute;inset:0;
  border:1px solid rgba(242,239,233,.42);
  border-radius:50%;
}
.op-count::after{
  content:"";position:absolute;inset:0;
  background-image:
    linear-gradient(to right,transparent calc(50% - .5px),rgba(242,239,233,.28) calc(50% - .5px) calc(50% + .5px),transparent calc(50% + .5px)),
    linear-gradient(to bottom,transparent calc(50% - .5px),rgba(242,239,233,.28) calc(50% - .5px) calc(50% + .5px),transparent calc(50% + .5px));
}
/* 回る針。1つの数字につき、ちょうど1回転する。
   ---------------------------------------------------------------------
   既定では **アニメーションを持たない**。基準は必ず 0 度。
   以前は `infinite` で回しっぱなしにしていたため、位相がオーバーレイの
   表示開始時刻に固定され、数字の切り替えと恒常的にずれていた
   （540ms のオフセット＝1.8周ぶん）。
   いまは opening.js が数字を書き換えるのと**同じ関数の中で**回し直すので、
   針と数字が原理的にずれない。
   JS が動かないときは針が回らないだけで、数字も円も普通に見える。 */
.op-hand{
  position:absolute;inset:0;
  border-radius:50%;
  background:conic-gradient(from 0deg,
    rgba(242,239,233,.16) 0deg 8deg,
    rgba(242,239,233,0) 8deg 360deg);
  rotate:0deg;
}
/* 予備の経路（Web Animations が使えない環境）。1数字につき1回だけ回る */
.op-hand.is-turning{
  animation:op-hand var(--op-hand-dur,1000ms) linear 1 both;
}
@keyframes op-hand{from{rotate:0deg}to{rotate:360deg}}
.op-n{
  position:relative;
  font-family:var(--cond);font-weight:700;
  font-size:clamp(64px,13vw,124px);line-height:1;
  letter-spacing:.02em;
  font-variant-numeric:tabular-nums;
  color:var(--ag-ink-light);
  text-shadow:0 0 22px rgba(15,16,19,.7);
}
/* 最後の数字（＝「1」）だけ色が変わる。次が白飛びであることの合図。
   針は止めない。最後の1周を回し切ってから白飛びへ進む。
   （以前はここで針を消していたが、それは「2 が最後」だった頃の名残） */
.op-count[data-tail="1"] .op-n{color:var(--ag-amber)}

/* ---------------------------------------------------------------- 本人の言葉 */
/* 1行 = 1つの意味のまとまり。**行の途中で折り返させない**のが最優先。
   「死ぬ前に見る走／馬灯を、」のように熟語が割れると字幕として一気に安くなる。
   そのため字数がそのまま入る幅を確保し、字面は幅から逆算して決める。
   （em ではなく vw を基準にするのは、親のフォントサイズに引きずられないため） */
.op-copy{
  position:relative;z-index:4;
  display:grid;gap:.42em;
  justify-items:center;text-align:center;
  max-width:min(92vw,56rem);
}
.op-line{
  margin:0;
  font-family:var(--jp);font-weight:700;
  font-size:clamp(21px,3.4vw,40px);
  line-height:1.5;letter-spacing:.06em;
  color:var(--ag-ink-light);
  /* 折り返しが避けられない場合でも、熟語の途中では切らせない */
  word-break:keep-all;
  line-break:strict;
  text-wrap:balance;
  /* 基準は「まだ焼き付いていない」状態。合焦して浮かび上がる。
     1文字ずつではなく、意味のまとまりごとに1枚の字幕として出す。 */
  opacity:0;
  filter:blur(6px);
  transform:translateY(4px) scale(1.012);
}
.op-line[data-in="1"]{
  animation:op-title 900ms var(--mo-out,cubic-bezier(.22,1,.36,1)) both;
}
@keyframes op-title{
  0%  {opacity:0;   filter:blur(6px);   transform:translateY(4px) scale(1.012)}
  32% {opacity:.72; filter:blur(1.4px); transform:translateY(1px) scale(1.004)}
  44% {opacity:.46; filter:blur(1.8px)}                       /* 光学焼き込みの明滅 */
  58% {opacity:1;   filter:blur(0);     transform:none}
  70% {opacity:.86}
  100%{opacity:1;   filter:blur(0);     transform:none}
}
/* 表示後の「印刷の揺れ」。読めなくならない範囲（0.4px）に留める */
.op-line[data-in="1"]{
  animation:op-title 900ms var(--mo-out,cubic-bezier(.22,1,.36,1)) both,
            op-print 3.1s steps(1,end) 900ms infinite;
}
@keyframes op-print{
  0%  {translate:0 0}
  25% {translate:.4px -.3px}
  50% {translate:-.3px .2px}
  75% {translate:.2px .4px}
  100%{translate:-.2px -.2px}
}
.op-by{
  margin:.9em 0 0;
  font-family:var(--cond);font-weight:600;
  font-size:var(--step--1);letter-spacing:.34em;text-transform:uppercase;
  opacity:0;transition:opacity .7s linear;
}
.op-copy[data-all="1"] .op-by{opacity:.5}

/* ------------------------------------------------------------- 本編へ入る操作 */
.op-act{
  position:absolute;z-index:5;
  inset-block-end:clamp(58px,13vh,132px);
  display:grid;justify-items:center;gap:.7em;
  opacity:0;transition:opacity .5s var(--mo-out,ease-out);
}
.op[data-phase="cta"] .op-act,
.op[data-phase="ignite"] .op-act{opacity:1}
.op-cta{
  font-family:var(--cond);
  font-size:var(--step-1);letter-spacing:.24em;text-transform:uppercase;
  min-width:min(19em,76vw);
}
.op-cta-sub{
  margin:0;
  font-family:var(--jp);font-size:var(--step--1);letter-spacing:.1em;
  opacity:.55;
}

/* ------------------------------------------------- SKIP と 音声（下のバー） */
.op-btn{
  display:inline-flex;align-items:center;gap:.5em;
  min-height:44px;padding:.4em .9em;
  border:1px solid rgba(242,239,233,.26);
  background:rgba(15,16,19,.5);
  color:var(--ag-ink-light);
  font-family:var(--cond);font-weight:700;
  font-size:var(--step--1);letter-spacing:.2em;text-transform:uppercase;
  cursor:pointer;
  opacity:.62;
  transition:opacity var(--mo-fast,.18s) ease,border-color var(--mo-fast,.18s) ease;
}
.op-btn:hover,.op-btn:focus-visible{opacity:1;border-color:var(--ag-amber)}
.op-btn:focus-visible{outline:3px solid var(--ag-amber);outline-offset:3px}
.op-skip[hidden]{display:none !important}
.op-skip .op-key{
  font-size:.85em;letter-spacing:.12em;opacity:.6;
  padding:.05em .4em;border:1px solid rgba(242,239,233,.28);
}

/* 音声トグル（オープニング内と本編で同じ見た目） */
.snd-dot{
  flex:none;width:9px;height:9px;border-radius:50%;
  background:rgba(242,239,233,.3);
  box-shadow:0 0 0 1px rgba(242,239,233,.28);
}
[data-sound-toggle][data-state="on"] .snd-dot{background:var(--ag-amber);box-shadow:0 0 8px rgba(218,156,23,.7)}
[data-sound-toggle][data-state="dead"]{opacity:.34;cursor:not-allowed}
[data-sound-toggle][data-state="dead"] .snd-dot{background:transparent}

/* ------------------------------------------------------- 白飛び・フィルム焼け */
.op-flash{
  position:absolute;inset:0;z-index:8;pointer-events:none;
  background:var(--ag-paper);
  opacity:0;
}
.op[data-phase="flash"] .op-flash{animation:op-flash 120ms steps(1,end) both}
@keyframes op-flash{
  0%  {opacity:.92}
  50% {opacity:.34}
  100%{opacity:0}
}
/* 点火 → カットの白飛び。ここは焼けを伴って一気に開く */
.op[data-phase="cut"] .op-flash{animation:op-cut 220ms ease-out both}
@keyframes op-cut{
  0%  {opacity:.2}
  40% {opacity:1}
  100%{opacity:1}
}
.op-burn{
  position:absolute;inset:0;z-index:7;pointer-events:none;
  background:radial-gradient(38% 38% at 50% 52%,
    rgba(242,239,233,.96) 0%,
    rgba(218,156,23,.72) 26%,
    rgba(152,0,0,.42) 44%,
    rgba(15,16,19,0) 70%);
  opacity:0;transform:scale(.2);
}
.op[data-phase="ignite"] .op-burn{animation:op-burn var(--op-ignite,760ms) ease-in both}
@keyframes op-burn{
  0%  {opacity:0;  transform:scale(.12)}
  55% {opacity:.5; transform:scale(.7)}
  100%{opacity:.95;transform:scale(2.1)}
}

/* --------------------------------------------------------------- 点火の状態 */
/* フィルムが回り出す。送り穴が加速し、画面がわずかに震える。 */
.op[data-phase="ignite"] .op-strip > span{animation-duration:.42s}
.op[data-phase="ignite"] .op-gate{animation:op-shake .5s ease-out both}
@keyframes op-shake{
  0%  {transform:translate3d(0,0,0)}
  14% {transform:translate3d(-1.6px,1.2px,0)}
  28% {transform:translate3d(1.4px,-1.4px,0)}
  42% {transform:translate3d(-1.1px,-.8px,0)}
  58% {transform:translate3d(.9px,1px,0)}
  74% {transform:translate3d(-.5px,.4px,0)}
  100%{transform:translate3d(0,0,0)}
}
.op[data-phase="ignite"] .op-copy{opacity:.25;transition:opacity .4s linear}
.op[data-phase="ignite"] .op-lamp{opacity:1;animation:none;filter:brightness(1.9)}

/* ============================================ 本編との接続（ハードカット） */
/* オープニングが開いているあいだ、本編側のヒーローのアパーチャは走らせない。
   animation:none = **基準状態（クリップ無し・可視）** なので、
   万一ここで JS が止まってもヒーローが欠けたまま固まることはない。 */
html[data-opening="on"] .hero-frame,
html[data-opening="on"] .hero-img,
html[data-opening="on"] .page-in{animation:none}

/* ハードカットの瞬間に初めてアパーチャを開く。
   ＝ 映写機の光が、そのままヒーロー写真になる。 */
html[data-cut="on"] .hero-frame{
  animation:aperture calc(var(--mo-scene) * .55) var(--mo-out) both;
}
html[data-cut="on"] .hero-img{
  animation:hero-settle calc(var(--mo-scene) * 1.5) var(--mo-out) both;
}
@supports (animation-timeline: view()){
  html[data-cut="on"][data-js="on"][data-motion="full"] .hero-img{
    animation:hero-settle calc(var(--mo-scene) * 1.5) var(--mo-out) both,
              hero-drift linear both;
    animation-timeline:auto,view();
    animation-range:normal,entry 0% exit 100%;
  }
}
/* REEL 00 のスレートも、カットのあとに切り込む */
html[data-cut="on"] #top .slate{animation:splice .5s steps(1,end) both}

/* ======================================================= 小さい画面での調整 */
@media (max-width:720px){
  /* 揺れをさらに弱くする。手に持っている端末では同じ量でも大きく感じる */
  .op-gate{animation-duration:2.8s}
  .op[data-phase="ignite"] .op-gate{animation:op-shake-s .42s ease-out both}
  @keyframes op-shake-s{
    0%  {transform:translate3d(0,0,0)}
    30% {transform:translate3d(-.8px,.6px,0)}
    60% {transform:translate3d(.7px,-.6px,0)}
    100%{transform:translate3d(0,0,0)}
  }
  /* 粒子は負荷が高い。テクスチャを1枚に減らし、書き換え頻度も落とす */
  .op-grain{
    background-image:var(--ag-tex-grain-base);
    background-size:150px 150px;
  }
  .op[data-phase]:not([data-phase="black"]) .op-grain{opacity:.62;animation-duration:.46s}
  .op-grain::after{animation-duration:2.6s}
  /* 小さい画面でも1行が折り返さない字面にする。
     最長行（13文字）× 字幅 × 字間 が 92vw に収まる値を上限にしてある。 */
  .op-line{font-size:clamp(18px,5.1vw,30px);letter-spacing:.02em}
  .op-copy{max-width:94vw;padding-inline:clamp(4px,2vw,16px)}
  .op-count{width:clamp(128px,42vw,180px)}
  .op-act{inset-block-end:clamp(70px,16vh,120px)}
  .op-cta{min-width:min(17em,82vw)}
  .op-notice{display:none}          /* 上段が2行になって窮屈になるため落とす */
  /* スレートと SKIP は必ず同じ行に置く。折り返すと SKIP がスレートの真下に
     ぶら下がり、押し間違えやすい位置に来る（2026-08-06 の実測）。 */
  .op-bar{gap:.5em .6em;flex-wrap:nowrap;align-items:flex-start}
  .op-slate{flex:1 1 auto;min-width:0}
  .op-skip{flex:none}
  .op-bar--foot{flex-wrap:wrap}
}
@media (max-width:520px){
  /* 章名を落として SKIP のぶんの幅を作る。巻番号とタイムコードは残す */
  .op-slate-name{display:none}
}
@media (max-width:400px){
  .op-slate::before{width:30px}
  .op-slate{gap:.4em .6em}
  .op-btn{padding-inline:.7em;letter-spacing:.14em}
}
/* 横に寝かせたときに操作が画面外へ出ない */
@media (max-height:460px){
  .op-act{inset-block-end:clamp(14px,5vh,34px)}
  .op-count{width:clamp(96px,20vh,132px)}
  .op-line{font-size:clamp(19px,4.4vh,30px)}
}

/* ============================================================ 動きの低減 */
/* 明滅・回転・揺れ・粒子の書き換えを全て止める。
   コピーは静止したまま完全に読める状態で出す。 */
@media (prefers-reduced-motion:reduce){
  .op-strip > span,
  .op-gate,
  .op-lamp,
  .op-grain,
  .op-grain::after,
  .op-hand,
  .op-flash,
  .op-burn{animation:none !important}
  .op-gate{transform:none !important}
  .op-lamp{opacity:1}
  .op-grain{opacity:.3}
  .op-line{
    animation:none !important;
    opacity:0;filter:none;transform:none;
    transition:opacity .2s linear;
  }
  .op-line[data-in="1"]{opacity:1}
  .op-count{display:none}
  .op[data-phase="cut"] .op-flash{opacity:1;animation:none !important}
  .op-copy{opacity:1 !important}
}
