/* ============================================================
 * 動きの演出
 *   1. パララックス（絵の奥行き）
 *   2. 幕（画面の切り替え）とロード画面
 *   3. 照準カーソル（PCのみ）
 *   4. 冒険画面のイラストのスライド
 *   5. 咲く花（押したところ・スタンプ獲得・ロード画面）
 *   6. 題字の登場 / 7. 見出しの花 / 8. スタンプ帳の「ぽん」 / 9. ポイントが増えたとき / 10. 花吹雪 / 11. のぞくよづり（0.8.0）
 * 色は css/base.css の :root の変数だけを使う。
 * 「演出を控えめにする」（html.is-lite）のときは、どれも出さない（スライドは、手で送ることだけできる）。
 * ============================================================ */

/* ---------- 1. パララックス ----------
 * js/effects/parallax.js が html に入れる変数を使う。
 *   --yz-sy スクロール量(px)   --yz-mx / --yz-my マウスの位置(-1〜1)
 * かける数字を大きくすると、よく動く。0 にすると動かない。 */
html.yz-parallax-on .hero__art {
  transform: translate3d(calc(var(--yz-mx, 0) * -6px), calc(var(--yz-sy, 0) * 0.22px + var(--yz-my, 0) * -4px), 0);
  will-change: transform;
}
html.yz-parallax-on .hero__copy {
  transform: translate3d(calc(var(--yz-mx, 0) * 4px), calc(var(--yz-sy, 0) * -0.08px), 0);
}
html.yz-parallax-on .secret-head__art {
  transform: translate3d(calc(var(--yz-mx, 0) * -4px), calc(var(--yz-sy, 0) * 0.10px + var(--yz-my, 0) * -3px), 0);
}

/* ---------- 2. 幕とロード画面 ----------
 * 幕は index.html の #yz-curtain。状態は class で切り替える。
 *   is-loading  かくしたまま待つ（開いた直後。is-full が付くと、ロード画面の絵も出す）
 *   is-open     かくした状態から、ななめに走ってひらく（長さ --open-ms。設定の loader.openMs と合わせる）
 *   is-on       画面を切り替えるとき: かくして → ひらく（長さ --curtain-ms。設定の transition.durationMs と合わせる）
 *   is-done     ロード画面で、かめりあーが着いたところ（花が咲く）
 *   is-hold     デザイン確認用に止めているところ */
.curtain {
  --curtain-ms: 460ms;
  --open-ms: 560ms;
  position: fixed; inset: 0; z-index: 95; overflow: hidden;
  pointer-events: none; visibility: hidden;
}
.curtain.is-on, .curtain.is-loading, .curtain.is-open { visibility: visible; }
.curtain__panel {
  position: absolute; top: 0; bottom: 0; left: -30%; right: -30%;
  background: var(--blue-deep);
  box-shadow: -6px 0 0 0 var(--gold), -12px 0 0 0 var(--ink);
  transform: translateX(130%) skewX(-12deg);
}
.curtain__crest {
  position: absolute; left: 50%; top: 50%; width: 136px; height: auto; margin: -68px 0 0 -68px;
  opacity: 0;
}

/* 画面を切り替えるとき */
.curtain.is-on .curtain__panel { animation: yz-curtain-panel var(--curtain-ms) cubic-bezier(.6, 0, .3, 1) both; }
.curtain.is-on .curtain__crest { animation: yz-curtain-crest var(--curtain-ms) ease-out both; }
.curtain.is-on .loader { display: none; }
@keyframes yz-curtain-panel {
  0%, 38% { transform: translateX(0) skewX(-12deg); }
  100% { transform: translateX(130%) skewX(-12deg); }
}
@keyframes yz-curtain-crest {
  0% { opacity: 0; transform: scale(.88); }
  14%, 42% { opacity: 1; transform: scale(1); }
  70%, 100% { opacity: 0; transform: scale(1.05); }
}

/* 開いた直後: かくしたまま待つ */
.curtain.is-loading .curtain__panel { transform: translateX(0) skewX(-12deg); }
.curtain.is-loading .curtain__crest { opacity: 1; }
/* スクリプトが動かなかったときの保険: 6秒たったら、CSSだけでひらく（js/effects/loader.js の FAILSAFE_MS と同じ） */
.curtain.is-loading:not(.is-js) .curtain__panel { animation: yz-curtain-open var(--open-ms) cubic-bezier(.6, 0, .3, 1) 6s both; }
.curtain.is-loading:not(.is-js) .curtain__crest { animation: yz-crest-out var(--open-ms) ease-out 6s both; }

/* ひらく */
.curtain.is-open .curtain__panel { animation: yz-curtain-open var(--open-ms) cubic-bezier(.6, 0, .3, 1) both; }
.curtain.is-open .curtain__crest { animation: yz-crest-out var(--open-ms) ease-out both; }
.curtain.is-open .loader { animation: yz-loader-out 180ms linear both; }
@keyframes yz-curtain-open {
  0% { transform: translateX(0) skewX(-12deg); }
  100% { transform: translateX(130%) skewX(-12deg); }
}
@keyframes yz-crest-out {
  0% { opacity: 1; transform: scale(1); }
  55%, 100% { opacity: 0; transform: scale(1.05); }
}
@keyframes yz-loader-out { to { opacity: 0; } }

/* ロード画面の絵: 紋章の下に、道と かめりあー と よづり。
 * ドット絵は 32px の絵を 2倍（64px）で出す。大きさを変えるときは、整数倍にするとドットがくずれない。
 * 進み具合は --yz-load（0〜1。スクリプトが入れる）。 */
.loader {
  --road: 264px;                 /* 道の長さ */
  --walk: 144px;                 /* かめりあーが歩く距離（道の長さ − よづり − かめりあー ＋ 少し重なる分） */
  position: absolute; left: 50%; top: 50%; width: var(--road); margin: 80px 0 0 calc(var(--road) / -2);
  opacity: 0; text-align: center; color: var(--white);
}
.curtain.is-full .loader { opacity: 1; }
.loader__road { position: relative; height: 122px; }
.loader__road::before {         /* 道（点線） */
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 4px; opacity: .45;
  background: repeating-linear-gradient(90deg, var(--on-dark-mute) 0 4px, transparent 4px 8px);
}
.loader__fill {                 /* 歩いたところ（金の点線） */
  position: absolute; left: 0; bottom: 0; height: 4px; width: calc(var(--yz-load, 0) * var(--walk) + 32px);
  background: repeating-linear-gradient(90deg, var(--gold) 0 4px, transparent 4px 8px);
}
.loader__cat {
  position: absolute; left: calc(var(--yz-load, 0) * var(--walk)); bottom: 4px; width: 64px; height: 64px;
  background: url(../assets/pixel/sprite-kamelia-walk.png) 0 0 / 256px 64px no-repeat;
  transform: scaleX(-1);        /* もとの絵は左向き。右へ歩くので左右を返す */
  animation: yz-walk-64 .56s steps(4) infinite;
}
.loader__yozuri { position: absolute; right: 0; bottom: 4px; width: 64px; height: 64px; }
.loader__yozuri::before, .loader__yozuri::after {   /* 2枚を重ねておき、着いたら笑顔のほうを見せる */
  content: ''; position: absolute; inset: 0;
  background: url(../assets/pixel/yozuri-front.png) 0 0 / 64px 64px no-repeat;
}
.loader__yozuri::after { background-image: url(../assets/pixel/yozuri-happy.png); opacity: 0; }
.loader__flower {               /* 着いたときに咲く青い花 */
  position: absolute; left: 116px; bottom: 56px; width: 64px; height: 64px; opacity: 0;
  background: url(../assets/pixel/sprite-flower.png) 0 0 / 192px 64px no-repeat;
  /* 紺の上でも花の形が分かるよう、白いふちを付ける（ドット1つぶん） */
  filter: drop-shadow(2px 0 0 var(--white)) drop-shadow(-2px 0 0 var(--white)) drop-shadow(0 2px 0 var(--white)) drop-shadow(0 -2px 0 var(--white));
}
.loader__text {
  margin-top: 10px; font-family: var(--font-dot); font-size: 15px; line-height: 1.2; letter-spacing: .06em;
  color: var(--on-dark-mute);
}
.loader__pct { margin-left: 10px; color: var(--on-dark-gold); }
.loader__label--done { display: none; color: var(--on-dark-gold); }
/* 着いたところ */
.curtain.is-done .loader__cat { animation: yz-hop .3s ease-out 1; }
.curtain.is-done .loader__yozuri { animation: yz-hop .3s ease-out 1; }
.curtain.is-done .loader__yozuri::before { opacity: 0; }
.curtain.is-done .loader__yozuri::after { opacity: 1; }
.curtain.is-done .loader__flower { opacity: 1; animation: yz-bloom-pop .3s steps(5, end) both, yz-flower-64 .54s steps(3) .3s infinite; }
.curtain.is-done .loader__label--run { display: none; }
.curtain.is-done .loader__label--done { display: inline; }
@keyframes yz-walk-64 { to { background-position: -256px 0; } }
@keyframes yz-flower-64 { to { background-position: -192px 0; } }
@keyframes yz-bloom-pop { 0% { scale: 0; } 60% { scale: 1.2; } 100% { scale: 1; } }
/* 横向きのスマホなど、たての短い画面では紋章をはぶいて、まんなかに置く */
@media (max-height: 520px) {
  .curtain.is-full .curtain__crest { display: none; }
  .loader { margin-top: -82px; }
}

/* ---------- 3. 照準カーソル（PCのみ） ----------
 * js/effects/reticle.js が、位置（transform）と大きさ（width / height）を入れる。
 * 4つの角は i 要素。is-lock が付くと、押せるものを囲んでいる状態。 */
.reticle {
  position: fixed; left: 0; top: 0; z-index: 91; width: 30px; height: 30px;
  pointer-events: none; opacity: 0; visibility: hidden;
  /* 明るい所でも紺の窓の上でも見えるよう、金の線に紺のふちを付ける */
  filter: drop-shadow(1px 1px 0 var(--ink)) drop-shadow(-1px -1px 0 var(--ink));
  will-change: transform;
}
.reticle.is-on { opacity: .8; visibility: visible; }
.reticle.is-lock { opacity: 1; }
.reticle i { position: absolute; width: 8px; height: 8px; border: 0 solid var(--gold); }
.reticle i:nth-child(1) { left: 0; top: 0; border-width: 2px 0 0 2px; }
.reticle i:nth-child(2) { right: 0; top: 0; border-width: 2px 2px 0 0; }
.reticle i:nth-child(3) { left: 0; bottom: 0; border-width: 0 0 2px 2px; }
.reticle i:nth-child(4) { right: 0; bottom: 0; border-width: 0 2px 2px 0; }
.reticle.is-lock i { width: 12px; height: 12px; border-color: var(--star); animation: yz-lock .24s steps(2, end) 1; }
.reticle__tag {                 /* 囲んだ瞬間だけ出る小さな札（上の文字をかくさないよう、すぐ消える） */
  position: absolute; left: 0; bottom: 100%; margin-bottom: 4px; padding: 1px 5px 0;
  font-family: var(--font-dot); font-size: 11px; line-height: 1.3; letter-spacing: .08em; white-space: nowrap;
  background: var(--ink); color: var(--star); opacity: 0;
}
.reticle.is-lock .reticle__tag { animation: yz-lock-tag .9s linear 1 both; }
.reticle.is-sample .reticle__tag { animation: none; opacity: 1; }      /* デザイン確認用: 札を出したままにする */
@keyframes yz-lock-tag { 0%, 78% { opacity: 1; } 100% { opacity: 0; } }
.reticle.is-low .reticle__tag { bottom: auto; top: 100%; margin: 4px 0 0; }   /* 画面の上の端では、札を下に出す */
@keyframes yz-lock { 0% { border-color: var(--white); scale: 1.5; } 100% { border-color: var(--star); scale: 1; } }
html:not(.yz-reticle-on) .reticle, html.is-touch .reticle, html.is-lite .reticle { display: none; }

/* ---------- 4. 冒険画面のイラストのスライド ----------
 * 絵は .hero__slides の中に重ねて置き、is-on の1枚だけ見せる。送るときは横にすべらせる。
 * 絵の大きさと位置は css/screens.css の .hero__art のまま（絵ごとの切り抜き方は --fit / --pos。設定の heroSlides）。 */
/* 左右になぞって送れるよう、横方向のなぞりはページに渡さない（縦スクロールと、指で広げる拡大はそのまま） */
.hero { touch-action: pan-y pinch-zoom; }
.hero__slides { position: absolute; inset: 0; }
.hero__slides .hero__art {
  opacity: 0; visibility: hidden; translate: 34% 0;
  transition: opacity .5s ease, translate .6s cubic-bezier(.2, .7, .2, 1), visibility 0s linear .6s;
}
.hero__slides .hero__art.is-on { opacity: 1; visibility: visible; translate: 0 0; transition-delay: 0s; }
.hero__slides .hero__art.is-out { translate: -34% 0; }
.hero__slides.is-back .hero__art { translate: -34% 0; }
.hero__slides.is-back .hero__art.is-on { translate: 0 0; }
.hero__slides.is-back .hero__art.is-out { translate: 34% 0; }
.hero__slides.is-still .hero__art { transition: none; }      /* 開いた直後・戻ってきた直後は、動かさずに出す */
.hero__nav {
  position: absolute; left: 6px; bottom: 6px; z-index: 2;
  display: flex; align-items: center; gap: 2px;
}
.hero__next {
  display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; background: none; color: var(--white);
}
.hero__next > span {            /* 見た目は小さく、押せる範囲は 44px */
  display: grid; place-items: center; width: 30px; height: 30px;
  background: var(--blue-deep); box-shadow: 0 0 0 2px var(--white), 0 0 0 4px var(--ink);
}
.hero__next:active > span { translate: 0 1px; }
.hero__pips { display: flex; gap: 4px; padding: 4px 5px; background: var(--white); box-shadow: 0 0 0 2px var(--ink); }
.hero__pips i { width: 6px; height: 6px; background: var(--line); }
.hero__pips i.is-on { background: var(--blue-deep); }
@media (min-width: 920px) {
  .hero__nav { left: auto; right: 10px; bottom: 16px; flex-direction: row-reverse; }
}

/* ---------- 5. 咲く花 ----------
 * 青い花のドット絵（3コマ）を、ぽんと大きくしてから消す。js/effects/bloom.js が、押した位置に置く。 */
.bloom {
  position: fixed; left: 0; top: 0; z-index: 92; width: 32px; height: 32px; margin: -16px 0 0 -16px;
  pointer-events: none;
  background: url(../assets/pixel/sprite-flower.png) 0 0 / 300% 100% no-repeat;
  filter: drop-shadow(1px 0 0 var(--white)) drop-shadow(-1px 0 0 var(--white)) drop-shadow(0 1px 0 var(--white)) drop-shadow(0 -1px 0 var(--white));
  animation: yz-bloom var(--bloom-ms, 620ms) steps(6, end) both, yz-flower-turn calc(var(--bloom-ms, 620ms) * .75) steps(3) infinite;
}
.bloom--64 { width: 64px; height: 64px; margin: -32px 0 0 -32px; }
.bloom.is-sample { animation: yz-flower-turn .54s steps(3) infinite; }   /* デザイン確認用: 消えずに残る */
@keyframes yz-bloom {
  0% { scale: 0; opacity: 1; }
  34% { scale: 1.2; opacity: 1; }
  50%, 78% { scale: 1; opacity: 1; }
  100% { scale: 1; opacity: 0; translate: 0 -8px; }
}
/* 3コマを順に見せる（絵の幅が枠の3倍なので、位置の % は 0 → 50 → 100 と進む。150% は「3コマぶん」） */
@keyframes yz-flower-turn { to { background-position: 150% 0; } }
html.is-lite .bloom { display: none; }

/* スタンプを獲得したとき、まわりに咲く花（js/ui/celebrate.js） */
.cele__flowers { position: absolute; inset: 0; pointer-events: none; }
.cele__flower {
  position: absolute; width: 32px; height: 32px; margin: -16px 0 0 -16px; scale: 0;
  background: url(../assets/pixel/sprite-flower.png) 0 0 / 300% 100% no-repeat;
  animation: yz-bloom-pop .34s steps(5, end) both, yz-flower-turn .6s steps(3) infinite;
}
html.is-lite .cele__flowers { display: none; }

/* ---------- 6. 題字の登場（開いたとき） ----------
 * js/effects/loader.js が、幕がひらくときに html へ yz-intro を付ける（1.3秒ほどで外す。設定の heroIntro）。
 * 題字が上から1文字ずつ出て、つづいて年・ひとこと・日付の札が出る。終わったら何も残さず、ふだんの見た目に戻る。
 * steps() の数は文字数（題字5文字・ひとこと8文字）。文言を変えたら、ここも合わせる。 */
html.yz-intro .hero__name { animation: yz-type-v .44s steps(5, end) .22s backwards; }
html.yz-intro .hero__year { animation: yz-pop-in .2s steps(3, end) .62s backwards; }
html.yz-intro .hero__lead { animation: yz-type-v .44s steps(8, end) .5s backwards; }
html.yz-intro .hero__date span { animation: yz-slide-in .26s steps(4, end) .86s backwards; }
html.yz-intro .hero__date span + span { animation-delay: .98s; }
/* 文字のふち（白い影）まで入るよう、切り抜きは少し外側から */
@keyframes yz-type-v { from { clip-path: inset(-6px -6px 100% -6px); } to { clip-path: inset(-6px -6px -6px -6px); } }
@keyframes yz-pop-in { from { scale: 0; } to { scale: 1; } }
@keyframes yz-slide-in { from { opacity: 0; translate: 14px 0; } to { opacity: 1; translate: 0 0; } }

/* ---------- 7. 見出しの花 ----------
 * 見出し（.section-title）の頭に、青い花を1つ置く。スクロールで画面に入ってくるときに咲く。
 * 咲く動きは、対応しているブラウザだけ（animation-timeline）。対応していないブラウザでは、咲いたままの花が出る。
 * 切るときは、設定の bloom.headings を false に（html の yz-heading-flower が付かなくなる）。 */
html.yz-heading-flower .section-title::before {
  content: ''; flex: none; align-self: center; width: 32px; height: 32px; margin: -6px -2px -6px -4px;
  background: url(../assets/pixel/sprite-flower.png) 0 0 / 300% 100% no-repeat;
  image-rendering: pixelated;
}
@supports (animation-timeline: view()) {
  html.yz-heading-flower:not(.is-lite) .section-title::before {
    animation: yz-bloom-pop linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 28%;
  }
}

/* ---------- 8. スタンプ帳の「ぽん」 ----------
 * スタンプ帳をひらくと、押してあるスタンプが順に押される。ひらいているあいだに増えたスタンプも、その1つだけ押される。
 * 切るときは、設定の celebrate.bookPon を false に。 */
html.yz-book-pon .book .seal--slot.seal--on { animation: yz-pon-soft .42s cubic-bezier(.3, .9, .4, 1) backwards; }
html.yz-book-pon .book .slot:nth-child(2) .seal--slot.seal--on { animation-delay: .12s; }
html.yz-book-pon .book .slot:nth-child(3) .seal--slot.seal--on { animation-delay: .24s; }
html.yz-book-pon .book .slot:nth-child(4) .seal--slot.seal--on { animation-delay: .36s; }
html.yz-book-pon .book .slot:nth-child(n+5) .seal--slot.seal--on { animation-delay: .48s; }
@keyframes yz-pon-soft {
  0% { transform: scale(1.24) rotate(calc(var(--seal-rot, 0deg) - 12deg)); opacity: 0; }
  55% { opacity: 1; }
  78% { transform: scale(.95) rotate(var(--seal-rot, 0deg)); }
  100% { transform: scale(1) rotate(var(--seal-rot, 0deg)); opacity: 1; }
}
html.is-lite .book .seal--slot.seal--on { animation: none; }

/* ---------- 9. ポイントが増えたとき ----------
 * 上の「ポイント」の下に出る「+10pt」の札。位置は js/effects/gain.js が入れる。数字のカウントアップも同じスクリプト。 */
.gain {
  position: fixed; left: 0; top: 0; z-index: 92; translate: -50% 0; padding: 2px 8px 1px;
  font-family: var(--font-dot); font-size: 18px; line-height: 1.2; white-space: nowrap;
  background: var(--star); color: var(--gold-ink); box-shadow: 0 0 0 2px var(--ink);
  pointer-events: none;
  animation: yz-gain var(--gain-ms, 1400ms) linear both;
}
.gain small { font-size: 12px; }
.gain.is-sample { animation: none; }           /* デザイン確認用: 消えずに残る */
@keyframes yz-gain {
  0% { scale: 0; opacity: 1; }
  10% { scale: 1.2; }
  16%, 70% { scale: 1; opacity: 1; translate: -50% 0; }
  100% { scale: 1; opacity: 0; translate: -50% -22px; }
}
html.is-lite .gain { display: none; }

/* ---------- 10. 花吹雪 ----------
 * スタンプがぜんぶそろったとき・ごほうび解放のとき、画面いっぱいに2〜3秒だけ降る。数は設定の celebrate.shower。
 * 1つずつの落ちる長さ（--d）・出るまでの待ち（--w）・横への流れ（--drift）は js/effects/bloom.js が入れる。 */
.shower { position: fixed; inset: 0; z-index: 93; overflow: hidden; pointer-events: none; }
.shower__bit { position: absolute; top: -40px; animation: yz-shower var(--d, 2000ms) linear var(--w, 0ms) both; }
.shower__bit--flower {
  width: 32px; height: 32px;
  background: url(../assets/pixel/sprite-flower.png) 0 0 / 300% 100% no-repeat;
  animation: yz-shower var(--d, 2000ms) linear var(--w, 0ms) both, yz-flower-turn .6s steps(3) infinite;
}
.shower__bit--petal { width: 6px; height: 6px; background: var(--blue); box-shadow: 3px 3px 0 0 var(--license-a); }
.shower__bit--star {
  width: 9px; height: 9px;
  background: linear-gradient(var(--gold), var(--gold)) center / 3px 100% no-repeat, linear-gradient(var(--gold), var(--gold)) center / 100% 3px no-repeat;
}
@keyframes yz-shower {
  0% { translate: 0 0; opacity: 1; }
  86% { opacity: 1; }
  100% { translate: var(--drift, 0px) calc(100vh + 80px); opacity: 0; }
}
html.is-lite .shower { display: none; }

/* ---------- 11. のぞくよづり ----------
 * 大きさ・位置（下からの高さ）・コマ送りは js/effects/peek.js が入れる。絵の下にある「台」は、この枠で切って見せない。 */
.peek { position: fixed; right: 14px; bottom: 0; z-index: 2; overflow: hidden; pointer-events: none; visibility: hidden; }
.peek.is-on { visibility: visible; }
.peek__sprite { display: block; background-repeat: no-repeat; }
html.is-lite .peek { display: none; }

/* ---------- 動きを控えめにするとき ---------- */
html.is-lite .curtain { display: none; }
@media (prefers-reduced-motion: reduce) { .curtain { display: none; } }
