/* =========================================================
   ABOUT FRIENDS — motion.css（2026-09-29 制作Cowork）
   styles.css の上に重ねる「動きの層」。styles.css は一切触らない。

   振付表
   0 入場 ……… ヘッダーが降りる → タイトル一文字ずつ → カードが奥から回って登場
   1 出会い …… シルエットの足元から光の帯が駆け上がり、顔が現れる
                （PC＝ホバー／スマホ＝自動）。帯はキャラの形で切り抜く
   2 目で追う … 顔だけがマウスの方を見る（2026-09-30 KiMiさん：体ごとでは伝わらない）
                目が先に動き、顔があとからついてくる。鼻と口は目より大きく動く（立体に見える）
                まばたき／触れたときの表情／マウスが無いときは、ときどききょろきょろ
                バットン＝すぐ反応して行き過ぎる／アモ＝遅れてのんびり追う
   3 ズーム …… 押すと一度縮んで（溜め）→ 画面いっぱいに寄る → 図鑑の3Dに着地
   4 図鑑 ……… 名前がせり上がる／数値が数え上がる／3Dが回って登場する
                画像で見ているとき（スマホなど）は、正面の絵の顔もマウスの方を見る・まばたきする
                （3Dの「マウスを向く」は外した。首の骨を入れて作り直してから戻す）
   5 物語 ……… 見出しが一行ずつ／線が中央から伸びる／字間が締まる
   🔴 動きを減らす設定の人には、ぜんぶ止めて「最後の姿」で見せる（末尾）
   ========================================================= */

:root{
  --ease-out:  cubic-bezier(.16, 1, .3, 1);    /* 速く出て、ゆっくり止まる */
  --ease-back: cubic-bezier(.34, 1.56, .64, 1); /* 少し行き過ぎて戻る */
  --ease-io:   cubic-bezier(.65, 0, .35, 1);    /* ゆっくり出て、ゆっくり止まる */
}

/* ---------- JSが動かない環境でも中身は必ず見える ---------- */
html:not(.js) .hero__char,
html:not(.js) .hero__char--amo{ opacity: 1; transform: none; }
html:not(.js) .reveal{ opacity: 1; transform: none; }

/* 読み上げだけに残す文字 */
.sr-only{
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- 読みやすさ（ChatGPT版から採用した分） ---------- */
html{ scroll-padding-top: 90px; }
.hero__eyebrow, .dex__no, .dex__name-en, .hero__char-no,
.profile__h, .profile__list dt, .profile__sub, .profile__skill-l{ color: var(--ink-soft); }
.viewer__btn{ min-height: 48px; }
.viewer__btn.active{ color: var(--ink); }
.viewer__btn.active small{ color: var(--ink-soft); }
.dex--amo .viewer__btn.active,
.dex--amo .viewer__btn.active small{ color: var(--bg-2); }
.viewer__hint{
  font-family: var(--f-jp); font-size: 12px; letter-spacing: .04em;
  line-height: 1.8; color: var(--ink-soft);
}
a:focus-visible, button:focus-visible, .viewer__canvas:focus-visible{
  outline: 3px solid var(--teal); outline-offset: 4px; border-radius: 6px;
}

/* =========================================================
   0 入場
   ========================================================= */
.progress{
  position: fixed; left: 0; right: 0; top: 0; height: 2px;
  z-index: 60; pointer-events: none;
}
.progress span{
  display: block; height: 100%;
  transform-origin: 0 50%;
  transform: scaleX(var(--p, 0));
  background: linear-gradient(90deg, var(--lime), var(--teal-mid));
}
.js .hd{ animation: hdIn .9s var(--ease-out) .05s both; }
@keyframes hdIn{
  from{ transform: translateY(-100%); opacity: 0; }
  to  { transform: none; opacity: 1; }
}
.hd{ transition: padding .5s var(--ease-out), box-shadow .5s, background .5s; }
.hd.is-condensed{
  padding-top: 10px; padding-bottom: 10px;
  background: rgba(250,246,234,.88);
  box-shadow: 0 8px 28px -18px rgba(31,44,41,.4);
}

/* =========================================================
   1 出会い：シルエット → 光の帯 → 顔
   --wipe は「光の帯の高さ」。-16% で全身シルエット、115% で全身カラー
   ========================================================= */
@property --wipe{
  syntax: '<percentage>';
  inherits: true;
  initial-value: -16%;
}
.js .hero__char-frame{
  --wipe: -16%;
  transition: --wipe .62s var(--ease-io);
}
.js .hero__char--amo .hero__char-frame{
  transition: --wipe 1s var(--ease-io);            /* アモはのんびり */
}
.js .hero__char:hover .hero__char-frame,
.js .hero__char:focus-visible .hero__char-frame,
.js .hero__char.revealed .hero__char-frame{ --wipe: 115%; }

/* 本体は最初から下にいる。上のシルエットが下から消えていく */
.js .hero__char-img--reveal,
.js .hero__char:hover .hero__char-img--reveal{ opacity: 1; }
.js .hero__char-img--silhouette,
.js .hero__char:hover .hero__char-img--silhouette,
.js .hero__char.revealed .hero__char-img--silhouette{
  opacity: 1;
  -webkit-mask-image: linear-gradient(to top, transparent var(--wipe), #000 calc(var(--wipe) + 14%));
          mask-image: linear-gradient(to top, transparent var(--wipe), #000 calc(var(--wipe) + 14%));
}

/* 光の帯。キャラの形で切り抜くので、体の上だけを光が走る */
.hero__char-scan{ display: none; }
.js .hero__char-scan{
  display: block;
  position: absolute; inset: 0; z-index: 4;
  pointer-events: none;
  mix-blend-mode: screen;
  background: linear-gradient(to top,
    transparent calc(var(--wipe) - 2%),
    var(--scan) calc(var(--wipe) + 5%),
    transparent calc(var(--wipe) + 13%));
  -webkit-mask: var(--shape) center / contain no-repeat;
          mask: var(--shape) center / contain no-repeat;
}
.hero__char--batton{ --scan: rgba(236,250,150,.95); --shape: url(./assets/batton/batton_hero.png); }
.hero__char--amo   { --scan: rgba(190,228,216,.9);  --shape: url(./assets/amo/amo_hero.png); }
/* ⚠️ 浮遊は「絵をまとめた箱（.hero__char-body）」にだけかける。
      絵・顔の部品・光の帯・シルエットが1つずつ浮くと、少しずつずれて見える。
      箱は script.js が作る。JSが動かない環境では styles.css どおり絵が浮く */
.hero__char-body{ position: absolute; inset: 0; }
.js .hero__char-body{
  animation: heroFloat 6s ease-in-out infinite;
  transition: scale .55s var(--ease-back), translate .55s var(--ease-back);
}
.js .hero__char--amo .hero__char-body{
  animation-delay: -3s;
  transition: scale .95s var(--ease-out), translate .95s var(--ease-out);      /* アモはのんびり */
}
.js .hero__char-img,
.js .hero__char:hover .hero__char-img--reveal{ animation: none; transform: none; }
@media (hover: hover){
  .js .hero__char:hover .hero__char-body{ scale: 1.045; translate: 0 -6px; }
}

/* 顔の部品（script.js が face.js で作る canvas。トップと図鑑の正面の絵） */
.hero__char-part{ position: absolute; z-index: 2; pointer-events: none; }
.hero__char-part--eyes{ transition: scale .5s var(--ease-out); }
/* アモ：触れると眠そうな目が少しだけ開く */
[data-char="amo"].is-awake .hero__char-part--eyes{ scale: 1 1.16; }

/* トップ：カードの囲みを外し、キャラが背景に直接立つ（2026-09-30 KiMiさん「カードに入ってる感を抜いて」）
   白い地・枠線・影・角丸をなくす。頭や光が枠で切れないように overflow も解く */
.hero__char,
.hero__char:hover,
.hero__char--batton:hover,
.hero__char--amo:hover{
  background: none;
  border-color: transparent;
  box-shadow: none;
  border-radius: 0;
  overflow: visible;
}

/* 図鑑：正面の絵は箱ごと浮かせる（顔の部品と一緒に動くように） */
.viewer__front{ position: absolute; inset: 0; }
.js .viewer__front .viewer__fallback-img{ animation: none; }
.js .viewer__front.is-front{ animation: float 5s ease-in-out infinite; }
.viewer__front .hero__char-part{ transition: opacity .45s ease; }
.viewer__front:not(.is-front) .hero__char-part{ opacity: 0; }

/* =========================================================
   2 目で追う（値は script.js がばねで計算して入れる）
   ========================================================= */
.js .hero__char-frame{
  transform:
    perspective(900px)
    rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
    translate3d(var(--tx, 0px), 0, 0);
}
.hero__char.is-looking .hero__char-frame{ will-change: transform; }
.js .hero__char-glow{
  transform: translate(calc(-50% + var(--gdx, 0px)), var(--gdy, 0px));
}
.hero__char.is-looking .hero__char-glow{ opacity: .6; }

/* =========================================================
   3 ズーム
   ========================================================= */
.zoom{ position: fixed; inset: 0; z-index: 100; pointer-events: none; visibility: hidden; }
.zoom.is-on{ visibility: visible; pointer-events: auto; }
.zoom__bg{
  position: absolute; inset: 0; opacity: 0;
  background:
    radial-gradient(circle at 50% 46%, var(--zc-soft, rgba(206,226,77,.35)) 0%, transparent 42%),
    linear-gradient(180deg, var(--bg-1), var(--bg-0));
}
.zoom__ring{
  position: absolute; left: 50%; top: 46%;
  width: 46vmin; height: 46vmin; margin: -23vmin 0 0 -23vmin;
  border-radius: 50%;
  border: 2px solid var(--zc, var(--lime));
  box-shadow: 0 0 40px var(--zc-soft, rgba(206,226,77,.35));
  opacity: 0;
}
.zoom__img{
  position: fixed; left: 0; top: 0; z-index: 2;
  transform-origin: 0 0;
  object-fit: contain;
  will-change: transform, opacity;
  filter: drop-shadow(0 30px 60px rgba(31,44,41,.25));
  pointer-events: none;
}

/* =========================================================
   4 図鑑
   ========================================================= */
/* 名前が一文字ずつせり上がる（script.js が文字を分ける） */
.dex__name-jp .nch{
  display: inline-block; overflow: hidden;
  vertical-align: bottom; padding-bottom: .08em; margin-bottom: -.08em;
}
.dex__name-jp .nch > span{
  display: inline-block;
  transform: translateY(108%);
  transition: transform 1.05s var(--ease-out);
  transition-delay: calc(var(--i, 0) * 70ms);
}
.dex.is-in .dex__name-jp .nch > span{ transform: none; }

/* キャッチの下線が伸びる */
.js .dex__catch{ position: relative; display: inline-block; }
.js .dex__catch::after{
  content: ''; position: absolute; left: 0; right: 0; bottom: -4px; height: 2px;
  background: currentColor; opacity: .45;
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform 1s var(--ease-out) .55s;
}
.js .dex.is-in .dex__catch::after{ transform: scaleX(1); }

/* カードは少しずつずらして立ち上がる */
.dex .profile__card.reveal{ transition-delay: calc(var(--i, 0) * 110ms); }

/* 3D：読み込み中は画像を見せたまま、終わったら差し替える（ChatGPT版から採用） */
.viewer.viewer--loading .viewer__canvas{ display: block; visibility: hidden; }
.viewer.viewer--3d-on .viewer__canvas{ visibility: visible; }
.viewer .viewer3d__loading{ display: none !important; }
.viewer.viewer--loading .viewer3d__loading{
  display: block !important;
  left: 12px; top: 12px; transform: none;
  max-width: calc(100% - 24px);
  padding: 7px 12px; border-radius: var(--radius-s);
  background: var(--bg-2); color: var(--ink);
  font-family: var(--f-jp); font-size: 12px; letter-spacing: .02em;
  opacity: 1; z-index: 4;
}
.viewer__3d-toggle,
.viewer.viewer--3d-on .viewer__3d-toggle{
  display: inline-flex; min-height: 44px;
  font-family: var(--f-jp); font-size: 12px; letter-spacing: .04em;
  background: var(--bg-2) !important; color: var(--ink) !important;
  border: 1px solid var(--line-strong) !important;
  box-shadow: 0 4px 14px -6px rgba(31,44,41,.25);
}
.viewer__3d-toggle svg{ display: inline-block !important; }
.viewer__tools{
  display: flex; align-items: center; justify-content: center;
  flex-wrap: wrap; gap: 8px; margin-top: 12px;
}
.viewer__tools[hidden]{ display: none; }
.viewer__style{ display: flex; gap: 4px; }
.viewer__style button, .viewer__rotate{
  min-height: 44px; padding: 8px 14px;
  font-size: 12px; letter-spacing: .04em;
  border: 1px solid var(--line-strong); border-radius: var(--radius-s);
  background: var(--bg-2); color: var(--ink-soft);
  transition: background .25s, color .25s, border-color .25s;
}
.viewer__style button[aria-pressed="true"]{
  color: var(--bg-2); background: var(--teal); border-color: var(--teal);
}
.viewer__rotate:disabled{ opacity: .55; cursor: default; }

/* =========================================================
   5 物語
   ========================================================= */
.js .story__h > span{
  clip-path: inset(0 0 100% 0);
  transform: translateY(28%);
  transition: clip-path 1.1s var(--ease-out), transform 1.1s var(--ease-out);
}
.js .story__h > span:nth-child(2){ transition-delay: .18s; }
.js .story__h.is-in > span{ clip-path: inset(-10% -4% -12% -4%); transform: none; }

.js .story__body p{
  opacity: 0; transform: translateY(18px);
  transition: opacity .9s ease, transform .9s var(--ease-out);
}
.js .story__body p.is-in{ opacity: 1; transform: none; }

/* 「でも、それでいい。」の両脇の線が、中央から外へ伸びる */
.js .story__emphasis::before,
.js .story__emphasis::after{
  content: ''; display: inline-block; vertical-align: middle;
  width: 40px; height: 1px; background: var(--ink-mute);
  transform: scaleX(0);
  transition: transform .9s var(--ease-out) .25s;
}
.js .story__emphasis::before{ transform-origin: 100% 50%; }
.js .story__emphasis::after { transform-origin: 0 50%; }
.js .story__emphasis.is-in::before,
.js .story__emphasis.is-in::after{ transform: scaleX(1); }
@media (max-width: 768px){
  .js .story__emphasis::before, .js .story__emphasis::after{ width: 24px; }
}

/* Stay Well Forever. の字間が、広いところから締まる */
.js .story__motto{
  opacity: 0; letter-spacing: .42em;
  transition: letter-spacing 1.6s var(--ease-out), opacity 1.2s ease;
}
.js .story__motto.is-in{ opacity: 1; letter-spacing: .08em; }

/* ボタンがカーソルに少し吸い寄せられる（PC） */
.story__btn{
  translate: var(--mx, 0px) var(--my, 0px);
  transition: transform .3s, box-shadow .3s, background .3s, color .3s, translate .5s var(--ease-back);
}
.hd-cta{
  translate: var(--mx, 0px) var(--my, 0px);
  transition: background .25s, color .25s, transform .25s, translate .5s var(--ease-back);
}

/* =========================================================
   🔴 動きを減らす設定の人へ
   styles.css 末尾の「0.01ms」の決まりはそのまま生きている。
   ここでは、この層で足した動きを「最後の姿」に固定する。
   ========================================================= */
@media (prefers-reduced-motion: reduce){
  .js .hero__char-frame{ transform: none !important; }
  .js .hero__char-scan{ display: none; }
  .js .hero__char-glow{ transform: translateX(-50%) !important; }
  .dex__name-jp .nch > span{ transform: none !important; }
  .js .dex__catch::after{ transform: scaleX(1) !important; }
  .js .story__h > span{ clip-path: none !important; transform: none !important; }
  .js .story__body p{ opacity: 1 !important; transform: none !important; }
  .js .story__emphasis::before,
  .js .story__emphasis::after{ transform: scaleX(1) !important; }
  .js .story__motto{ opacity: 1 !important; letter-spacing: .08em !important; }
  .story__btn, .hd-cta{ translate: none !important; }
  .js .hero__char:hover .hero__char-body{ scale: 1; translate: none; }
  .hero__char-part{ display: none; }
  .progress{ display: none; }
}
