/* ============================================================
   app.css — okane
   Phase 0 時点は「足場が起動して見える」ための最小限。
   本実装(Jelly UI 橋渡し・常時アニメ規定・画面別スタイル)は Phase 4 以降。
   色の実値はここに書かず tokens.css の変数を使うこと。
   ============================================================ */

*, *::before, *::after { box-sizing: border-box; }

/* [hidden] は UA スタイルの display:none だが、.screen 等のクラス側 display が勝ってしまう。
   画面の出し分けを hidden 属性でやる以上、ここで強制する。 */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-ui);
  -webkit-text-size-adjust: 100%;
}

.app {
  /* (!) **height を固定する**。min-height だけだと、中身が縦に溢れたときに
     .app 自身が伸びて文書ごとスクロールする器になり、下の .screen の
     flex-shrink(Hero を詰める)が一切効かない。高さを固定して、
     溢れは各 .screen の中で吸わせる(下の overflow-y)。
     2026-08-28: バナー広告を出すと TOP が 64px ぶん溢れ、進捗の文が
     バナーの裏に半分隠れていた(Pixel_9a で実測)。 */
  height: 100dvh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* --- appbar は廃止(2026-09-22 Hero 化)------------------------------------
   題字と 📊/⚙ はホームの Hero(.hero-top / game.css)に移した。
   appbar はもともと :root[data-screen] でゲーム・ページでは display:none にしており、
   ホーム専用の器だったので、縦 60px ぶんを Hero に回した。 */

/* --- screen: タブレットでは要素を足さず padding-inline で中身を中央へ寄せる ---
   スマホ幅では max() が既定値を選ぶので従来と同じ見え方のまま
   (NEW-APP-GUIDE.md タブレット対応。背景装飾は画面いっぱいに残し、寄せるのは中身だけ) */
.screen {
  flex: 1;
  min-height: 0;          /* flex の子が縮めるようにする(既定の auto だと縮まない) */
  overflow-y: auto;       /* 溢れる画面(図鑑の一覧など)はこの中でスクロールする */
  /* (!!) **横は必ず塞ぐ。** overflow-y だけ指定すると CSS の規定で overflow-x が
     visible から auto に格上げされ、**画面が横にスクロールできてしまう**。
     Jelly のアイコンボタンは押した時の変形用に 44px の枠へ 134px の canvas を
     中央基準で持っており、右端(Hero の 📊/⚙)では画面から 29px はみ出す。
     2026-09-22 のリリース前検品で、ホームが横スクロールした状態のまま残り、
     **題字とメニューが左へずれて切れていた**(エミュレータ実測。指で右へ払うと直る)。 */
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  /* 下は「余白 + セーフエリア + バナーの裏に潜り込む分」。--banner-reserve は
     ads.js が実測して入れる(既定 0px・tokens.css のコメント参照)。 */
  padding-block: var(--space-md)
                 calc(var(--space-xl) + env(safe-area-inset-bottom) + var(--banner-reserve, 0px));
  padding-inline: max(var(--space-md), calc((100% - var(--content-max)) / 2));
}

/* ホームには上端の器(旧 appbar)が無いので、セーフエリアはこの画面が吸う
   (ゲーム画面は .screen--game、ページ枠は .screen--page が同じ形で持っている) */
#screen-top {
  padding-top: calc(var(--space-sm) + env(safe-area-inset-top));
}

/* --- Hero ---
   背景は LQIP(18x32 の極小 WebP を data URI 化したもの。原本 docs/assets/hero-lqip.txt)。
   これが即座に出て、本画像 hero.webp を読み終えたら .is-loaded でフェードインする。
   枠は aspect-ratio で先に確定するので、画像の読み込み前後でレイアウトが動かない(CLS 対策)。
   画像自体は 9:16 だが縦長端末では max-height で潰れるため object-fit: cover で
   上下(空と雲の余白)を切る。左右は切らないので舞っているモチーフは全部残る。 */
.hero {
  position: relative;
  aspect-ratio: 9 / 16;
  max-height: 46dvh;
  /* (!) **足りない高さは Hero が吸う**。TOP は Hero + メニュー4行 + 進捗の1文で、
     バナー広告を出すと WebView が 64px 縮むぶん 46dvh のままでは溢れ、
     進捗の文がバナーの裏に半分隠れる(2026-08-28 Pixel_9a で実測)。
     flex で縮められるようにしておくと、溢れる代わりに Hero が少し詰まる。
     画像は object-fit: cover なので縦が詰まっても破綻しない(切れるのは上下の余白)。
     min-height はこれ以上潰さない下限(狭い端末ではここでスクロールに戻る)。 */
  flex: 0 1 auto;
  min-height: 200px;
  /* (!!) `width: 100%` を必ず書く(2026-09-14・iOS だけ Hero が左に寄っていた)。
          width が auto だと、WebKit は `aspect-ratio` 経由で `max-height: 46dvh` を
          max-width(= 46dvh × 9/16 ≈ 210px)へ転移させ、flex の stretch が効かず
          左端に 210px 幅の箱が置かれる。Chrome は転移しないので Android では出ない。
          幅を明示すれば転移は起きない。margin-inline は念のための保険。 */
  width: 100%;
  margin-inline: auto;
  overflow: hidden;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  background-color: var(--navy);
  background-image: url(data:image/webp;base64,UklGRjABAABXRUJQVlA4ICQBAADwBgCdASoSACAAPwFoq08rJaOiMAgBYCAJbACdMoR5j4Jm5oHef/LsEXyL/Gn9cDDw80vC2Q1l7Qhqmu8JmOpQAP7kuJKq1AU2LJHfNdJ1WKn0glt42oZud7yA5lR7kpq5MWUv5GhFrmdhGark+iuEVNhjKEz92cDYGen+2Yd1Zj9gJGJLJBq7BOFmuOpgu6FWXsOk7XJHwi9M9YR7BKflAQmJZIzisGNxGU7fJwpuyGznPjcN6hRcqmgSJCU3yqWlZu5VQQlKOQDefyxL9OZZkwwfM/HatTRJcstCfC3cvoZaHKewZ5jhTBccyEtvw8ryjLEmFP/x6T2BDRk7+EIzPJzPH8akCuzcTPUrcaHn/hIHAqlgSyV4qNipFv4E8PPpAAAA);
  background-size: cover;
  background-position: center;
}

.hero__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  opacity: 0;
  transition: opacity 420ms ease-out;
  /* 常時アニメ規定「静止した瞬間を作らない」(NEW-APP-GUIDE.md)。
     prefers-reduced-motion ではファイル末尾の一括停止が効く */
  animation: hero-drift 16s ease-in-out infinite alternate;
}

.hero__img.is-loaded { opacity: 1; }

@keyframes hero-drift {
  from { transform: scale(1.02) translateY(-0.5%); }
  to   { transform: scale(1.05) translateY(0.5%); }
}

/* --- TOP のコインくん(2026-09-01 オーナー指示「TOPページに出現させて」) ---
   (!!) **Hero の中に絶対配置する。** TOP は Hero + メニュー4行 + 進捗の1文で
        高さが詰まっていて、バナー広告を出すと WebView が 64px 縮む。
        流し込みで置くと**進捗の文がバナーの裏に隠れる**(2026-08-28 に実測した前例)。
        絶対配置なら**高さを1pxも増やさない**。
   (!) 置くのは**左下**。Hero は空が広く地球と札束は上寄りなので、
       ここだけが絵を隠さない。金色 + 黒縁なので紺の夜空でも白い雲の上でも読める。
   (!!) **コマ送りは JS(js/mascot.js)が持つ。** `.msprite` は付けない。
        あれは「1要素 = 1シート」前提で `steps()` を直書きする仕組みで、
        歩行(8コマ)と待機・リアクション(16コマ)を1つの要素で差し替える
        ここでは使えない。CSS に残すのは**位置と上下の揺れだけ**。
   (!) **2重にしてある。** 外側が位置と左右反転(scaleX)、内側がコマ送りと揺れ。
       同じ要素に載せると transform が食い合う。
   (!) 幅は**絶対長**(`clamp` の vw)。`%` にすると JS が組み立てる
       `background-size`(コマ数 x 幅)と食い違う。 */
.top-mascot {
  position: absolute;
  left: 0;
  bottom: 4px;
  width: clamp(64px, 20vw, 88px);
  height: clamp(64px, 20vw, 88px);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.45));
  will-change: transform;
  /* (!) **足元を軸にする。** 奥へ行くほど縮めて奥行きを見せる(mascot.js の
     DEPTH_SHRINK)ので、中心を軸にすると縮んだときに宙に浮く。 */
  transform-origin: 50% 100%;
}

.top-mascot__body {
  width: 100%;
  height: 100%;
  background-repeat: no-repeat;
  background-position-x: 0;
  /* background-image と background-size は mascot.js が入れる(シートごとにコマ数が違う)。
     ここに置くのは揺れだけ。reduce では上の一括停止(`*` の 0.001ms)が効く */
  animation: mascot-bob 5.5s ease-in-out infinite;
}

/* --- メニュー --- */
.menu {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

/* (!) 塗りは **タグで区別**する。.menu__btn は今は <jelly-button> に付いていて
   (Phase 8 で Jelly UI 化)、その見た目は css/jelly-bridge.css が持つ。
   クラスを残してあるのは、下の「生きているUI」の登場ステージングと
   主役ボタンの nudge がこのクラスを見ているため。
   ここの `button.menu__btn` は **Jelly を使わない素のボタンを足した時の受け皿**
   として残す(セレクタが何にも当たらない状態が正常)。 */
/* TOP メニューの2行組み(2026-09-01 オーナー指示「説明を添えて」)。
   (!) `data-i18n` は **textContent を丸ごと差し替える**ので、ボタン本体には付けない。
       付けると中の <span> ごと消える。見出しと説明の**それぞれに**付けること。
   (!) 中身は Jelly の slot に入るので、**光の DOM 側のこの規則がそのまま効く**
       (shadow の中は触れない)。高さは jelly-bridge.css の
       `--jelly-button-height` を上書きして伸ばしてある。 */
/* アイコン + 文字の並び(2026-09-01 オーナー指示「アイコンを設置」)。
   (!) **アイコンを行頭に固定し、文字は札の真ん中に置く。**
       中央寄せの塊にすると、文言の長さがボタンごとに違うので
       アイコンの縦位置がガタつく。右端に**アイコンと同じ幅の空き**を作って
       左右を対称にし、文字の中心を札の中心に合わせている。
   (!) `flex-direction: row` は書字方向に従うので、**ar(RTL)は自動で左右が入れ替わる**。
       margin-left/right のような物理方向で書かないこと。 */
.menu__row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  width: 100%;
  /* 「まだ見ていない図鑑」のバッジの基準(2026-09-06)。
     (!) バッジは**絶対配置**にして行の高さを1pxも増やさない(index.html の注記)。 */
  position: relative;
}

/* まだ開いていない図鑑の数(2026-09-06)。行末の 32px の空き(.menu__row::after)の
   上に重ねるので、**文字の中心も行の高さも動かない**。
   (!) `inset-inline-end` で書く。`right` にすると ar(RTL)で左右が入れ替わらない
       (.menu__row が書字方向に従う設計なので、物理方向を混ぜない)。
   (!) 面は明るく字は濃く(--coral-bright + --on-accent)。**原色 + 白字にしない** —
       4色の面のどこでもコントラストが足りない(art-style-guide §2)。
   (!) 白い縁は駒アイコンと同じ「ステッカーの2重縁」。緑の面から札を切り離すためのもので、
       細くしたり外したりしない。 */
.menu__badge {
  position: absolute;
  inset-inline-end: 0;
  top: 50%;
  transform: translateY(-50%);
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.625rem;
  font-weight: 800;
  line-height: 1;
  color: var(--on-accent);
  background: var(--coral-bright);
  border-radius: var(--radius-pill);
  box-shadow: 0 0 0 2px #FFFFFF;
  font-variant-numeric: tabular-nums;
}

.menu__badge[hidden] { display: none; }

/* (!) 幅は .menu__icon と必ず同じ値にすること。左右が非対称になると文字が中央からずれる */
.menu__row::after {
  content: '';
  flex: none;
  width: 32px;
}

.menu__icon {
  flex: none;
  width: 32px;
  height: 32px;
  object-fit: contain;
}

.menu__stack {
  display: flex;
  flex: 1;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  line-height: 1.35;
}

/* 主役(スタート)はアイコンも説明も一回り大きく(2026-09-14)。
   (!) `::after` の幅は必ず .menu__icon と同じ値にする(左右対称の空き。上の注記) */
.menu > .menu__btn--primary .menu__icon,
.menu > .menu__btn--primary .menu__row::after { width: 44px; }
.menu > .menu__btn--primary .menu__icon { height: 44px; }
.menu > .menu__btn--primary .menu__sub { font-size: 0.875rem; opacity: 0.8; }

.menu__sub {
  font-size: 0.6875rem;
  font-weight: 600;
  /* 面の色は明るく、字は濃字。説明は少し透かして見出しとの主従を作る。
     (!) 別の色トークンにしない — 面が4色あるので、どれに乗せても成立するのは
         「同じ濃字を透かす」やり方だけ。 */
  opacity: 0.72;
}

button.menu__btn {
  min-height: 52px;
  padding: var(--space-sm) var(--space-lg);
  font: inherit;
  font-weight: 700;
  color: var(--fg);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}

button.menu__btn--primary {
  color: var(--on-accent);
  background: var(--gold);
  border-color: var(--gold-deep);
}

button.menu__btn[disabled] {
  opacity: 0.55;
  cursor: default;
}

.scaffold-note {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.7;
  color: var(--fg-muted);
}

.scaffold-note code {
  font-size: 0.9em;
  color: var(--accent);
}

/* ============================================================
   常時アニメ規定(NEW-APP-GUIDE.md「静止した瞬間を作らない」)
   本実装は Phase 7。ここでは必須の停止規定だけ先に置いておく:
   prefers-reduced-motion: reduce では無限ループ系を全停止・登場系は即時表示。
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ============================================================
   ゲーム画面(Phase 4)
   盤面は canvas 側で world 400x620 の固定系。ここは器の配置だけを面倒みる。
   ============================================================ */

.screen--game {
  gap: var(--space-sm);
  padding-block: calc(var(--space-sm) + env(safe-area-inset-top)) 0;
  padding-bottom: env(safe-area-inset-bottom);
}

.hud {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  /* (!) 合体の梯子(.hud__ladder)を**全幅の最後の行**へ折り返させる。
         `gap` は縦横まとめて入る短縮形なので、**この2行は gap より後ろ**に置いて
         行方向だけ 0 に戻す(前に置くと gap が row-gap を上書きして 8px 空く)。 */
  flex-wrap: wrap;
  row-gap: 0;
}

/* .hud__back は2か所で使う: ページ枠の戻る(#btn-page-back = <jelly-icon-button>)と
   **ゲーム画面 HUD の戻る(#btn-back = 素の <button> のまま)**。
   HUD は Matter.js が 60fps で回っている最中に常時見えている部品なので、
   canvas + rAF で描く Jelly には**しない**(描画が競合する)。
   行の中での据わりだけ両方に当て、塗りは素のボタンにだけ当てる。 */
.hud__back { flex: none; }

button.hud__back {
  min-width: 44px;
  min-height: 44px;
  display: grid;
  place-items: center;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--fg);
  background: none;
  border: 0;
  border-radius: var(--radius-pill);
  cursor: pointer;
}

/* --- RTL(ar)の後始末 ---------------------------------------------------
   ・戻る矢印は文字そのものが方向を持つ。RTL では進行方向が逆なので左右反転させる
     (別の字 → を辞書に入れると、フォントによって字面が揃わない)
   ・Hero の 📊/⚙ は grid の列なので RTL では勝手に左へ回る(旧 appbar の
     inset-inline-end による位置合わせは 2026-09-22 に不要になった) */
[dir="rtl"] .hud__back { transform: scaleX(-1); }

/* 国旗の器。中身は app.js が毎ステージ差し替える(OKANE.ui.flag) */
.hud__flag {
  flex: none;
  display: flex;
  align-items: center;
}

.hud__main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* 国名と通貨名を1行に並べる(2026-08-31 オーナー指示「国名をもっと大きく目立つように」)。
   (!) **狭い端末では通貨名から先に詰める**。国名は主役なので最後まで残す
   — .hud__currency の flex-basis を 0 にして、余った幅だけを使わせている。 */
.hud__titles {
  display: flex;
  align-items: baseline;
  column-gap: 0.4rem;
  row-gap: 0;
  /* 通貨名が入り切らないときは**切らずに次の行へ落とす**。
     「アラブ首長国連邦ディルハム」が「アラブ首…」になっても意味が無いので、
     31通貨のうち長い2〜3件だけ2行になる形にした(短い国は1行のまま) */
  flex-wrap: wrap;
  min-width: 0;
}

/* (!) 国名は**省略しないで折り返す**。ar の「الإمارات العربية المتحدة」や
   ja の「アラブ首長国連邦」は 375px では1行に入らず、`text-overflow: ellipsis` だと
   「الإمارات العربية المت…」になる。**どの国かが分からなくなっては本末転倒**なので、
   縦に伸ばす方を取る(伸びたぶんは .field が吸うので盤面がわずかに小さくなるだけ)。 */
.hud__country {
  flex: 0 1 auto;
  min-width: 0;
  font-size: 1.125rem;
  font-weight: 800;
  line-height: 1.25;
  color: var(--fg);
}

.hud__currency {
  /* min-width が「これ以下なら折り返す」の閾値。0 にすると折り返さず縮むだけになる */
  flex: 1 1 auto;
  min-width: 5.5rem;
  font-size: 0.6875rem;
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hud__label {
  font-size: 0.6875rem;
  letter-spacing: 0.04em;
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hud__score {
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1.1;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

/* --- クリア条件と現在地(2026-08-31) ---
   ワールドツアーは**目標スコアに届けばクリア**(手数の制限は無い)。
   バーの伸びが現在地、文字が条件。届くと .is-done でみどりに変わり
   「クリア!」になる(**プレイは終わらない**ので、そのまま星2・星3を狙える)。 */
.hud__goalrow {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  min-width: 0;
}

.goalbar {
  flex: 1 1 auto;
  min-width: 2.5rem;
  max-width: 7rem;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--line);
  overflow: hidden;
}

.goalbar[hidden] { display: none; }

.goalbar__fill {
  display: block;
  width: 0;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--gold);
  transition: width 260ms ease-out, background-color 200ms ease-out;
}

.hud__goalrow.is-done .goalbar__fill { background: var(--money-green); }

/* 目標に届いたときだけ出る「切り上げる」ボタン(2026-09-01)。
   (!) 素の <button>。HUD に Jelly の部品を置かない規定(index.html のコメント)。
   (!) 面は成功色。HUD は情報が詰まっているので、**出る時だけ場所を取る**
       (hidden のときは display:none が効いて行ごと消える)。 */
.hud__finish {
  align-self: flex-start;
  margin-top: 2px;
  padding: 4px 12px;
  min-height: 28px;
  font: inherit;
  font-size: 0.75rem;
  font-weight: 700;
  color: #FFFFFF;
  background: var(--money-green);
  border: 0;
  border-radius: var(--radius-pill);
  cursor: pointer;
  /* 届いた瞬間に気づけるよう、出てすぐだけ弾む(無限ループにはしない) */
  animation: mascot-pop 420ms cubic-bezier(0.2, 1.4, 0.4, 1) both;
}

.hud__goalrow.is-done .hud__goal {
  color: var(--money-green);
  font-weight: 800;
}

/* --- 「強く投げる」ゲージ(2026-09-01 オーナー指示) -----------------------
   合体できなかったドロップのたびに溜まり、満タンで**レインボーに光って押せる**。
   (!) **ゲージそのものがボタン**。盤面のタップは照準とドロップに直結しているので、
       発動の口を canvas 側に作ると誤爆する(オーナー確定)。
   (!) 素の <button>。HUD に Jelly の部品を置かない規定(index.html のコメント)。
   (!) 高さを増やさない。TOP と同じで、この画面もバナー広告のぶん縮む。
       .hud__goalrow と同じ骨格(バー + 文字の1行)に揃えて 1行ぶんだけ足す。 */
.hud__charge {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  min-width: 0;
  margin: 2px 0 0;
  padding: 0;
  font: inherit;
  background: none;
  border: 0;
  text-align: start;
}

.hud__charge[disabled] { cursor: default; }
.hud__charge:not([disabled]) { cursor: pointer; }

.chargebar {
  flex: 1 1 auto;
  min-width: 2.5rem;
  max-width: 7rem;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--line);
  overflow: hidden;
}

.chargebar__fill {
  display: block;
  width: 0;
  height: 100%;
  border-radius: var(--radius-pill);
  background: var(--sky);
  transition: width 260ms ease-out;
}

.hud__chargetext {
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--fg-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 連鎖でゲージが増えた瞬間。**1回だけ光って戻る**(2026-09-02 オーナー指示
   「連鎖によって…強く投げるゲージにエフェクトがでて、ゲージが溜まります」)。
   (!) 満タンの `is-ready` とは重ねない。あちらは「いま押せる」の常時アニメで、
       主役を取り合うと**押せる合図が読めなくなる**(付け外しは app.js の pulseCharge)。
   (!) `animation` は付け直しただけでは再生されないので、app.js 側で
       いったんクラスを外して reflow を挟んでいる。 */
.hud__charge.is-combo .chargebar__fill {
  animation: charge-combo 460ms ease-out 1;
}

.hud__charge.is-combo .chargebar {
  animation: charge-combo-ring 460ms ease-out 1;
}

@keyframes charge-combo {
  0%   { filter: brightness(1); }
  30%  { filter: brightness(2.1); }
  100% { filter: brightness(1); }
}

@keyframes charge-combo-ring {
  0%   { box-shadow: 0 0 0 0 rgba(111, 192, 232, 0.9); }
  100% { box-shadow: 0 0 0 7px rgba(111, 192, 232, 0); }
}

/* 満タン。**レインボー**(オーナー指示「Max はレインボーにして分かりやすく」)。
   (!) 色は流し続ける。止めると「ただの派手なバー」になって、
       いま押せるという合図に読めない(盤面側のリングと役割を揃えている)。
   (!) background-size を 300% にしてから position を動かす。
       グラデーションは要素幅を基準にするので、広げないと流れない。 */
.hud__charge.is-ready .chargebar__fill {
  position: relative;
  overflow: hidden;
  background: #FF5F6D;   /* 疑似要素が読めない一瞬の下地 */
}

/* (!) 2026-09-14: `background-position` を動かすと満タンの間ずっと毎フレーム
       再ラスタライズになる(電池)。3倍幅のグラデーションを疑似要素に持たせて
       `transform` で流す = コンポジタだけで済み、見た目は同じ。 */
.hud__charge.is-ready .chargebar__fill::before {
  content: "";
  position: absolute;
  /* (!!) `inset: 0` にしないこと。width と left/right が同時に効いて過制約になり、
          RTL(ar)では left が捨てられて**右端基準**になる。すると translateX で
          バーの外へ流れ出て、ほとんどの時間は下地の1色しか見えない。
          物理方向の `left: 0` で LTR/RTL とも左端に固定する(流れる向きは同じでよい)。 */
  top: 0;
  bottom: 0;
  left: 0;
  width: 300%;
  background: linear-gradient(90deg,
    #FF5F6D, #FFC371, #7BE495, #5BC8F5, #A78BFA, #FF5F6D);
  animation: charge-rainbow 1.6s linear infinite;
  will-change: transform;
}

.hud__charge.is-ready .chargebar {
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.35);
  /* (!) 満タンの間だけバーを細くしてよい(2026-09-04)。ここでのバーは
         **「100% に届いた」を示すだけの飾り**で、いま何%かの情報は文字側
         (「コインくんをタップ! 200%」)が持っているため。
         (!!) 溜まっている最中の 2.5rem は**縮めないこと**。あちらはバーが
              唯一の進み具合の表示で、細くすると1目盛りが読めなくなる。
         これで文字に使える幅が 375px で 143px -> **159px**(実測)に増え、
         21ロケールとも「何を押すか」を言い切れる(最小の余裕は vi の 15px)。
         (!) 320px では 104px しか無く、de / ru / vi など15ロケールで**末尾の「%」が
             ellipsis に食われる**。**それは許容**(2026-09-04 オーナー裁定) —
             何を押すかの語が優先で、倍率は盤面のレインボーの輪の太さと速さでも伝わる。
             ここで文言を縮め直さないこと。 */
  min-width: 1.5rem;
}

.hud__charge.is-ready .hud__chargetext {
  color: var(--fg);
  animation: charge-blink 1.2s ease-in-out infinite;
}

@keyframes charge-rainbow {
  from { transform: translateX(0); }
  to { transform: translateX(-66.667%); }
}

@keyframes charge-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

.hud__next {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.hud__next canvas {
  display: block;
  width: 56px;
  height: 56px;
}

.hud__drops {
  font-size: 0.6875rem;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

/* デイリーの残りが10手を切ったら(2026-09-06)。ここだけ札にして締めを作る。
   (!) **原色 + 白字にしない。**11px の字なので、`--coral` をそのまま文字色にすると
       クリーム地で 3:1 前後しか出ない。TOP の4色ボタンと同じ
       「明るい面 + 濃字」の型に揃える(art-style-guide §2・TOP の NEW バッジと同じ)。
   (!) 点滅はファイル中ほどの prefers-reduced-motion の一括停止に乗る。
       色は残るので、アニメを止めても「残り少ない」ことは伝わる。 */
.hud__drops.is-low {
  padding: 1px 7px;
  font-weight: 800;
  color: var(--on-accent);
  background: var(--coral-bright);
  border-radius: var(--radius-pill);
  animation: drops-low 900ms ease-in-out infinite;
}

@keyframes drops-low {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.5; }
}

/* 合体の梯子(2026-09-04・面白さ監査 項目3)。中身は app.js の drawLadder()。
   (!!) **18px より高くしないこと。** 320x568 の実測(2026-09-04・この行 18px + margin 2px):
        ・国名が1行に収まる通貨(TWD だけ)  `.field` 462 → **442px**
        ・国名が2行に折り返す通貨(残り45本)`.field` 450 → **430px**
        `.hud__titles` が2行になるぶん 12px 低いところから始まるので、
        **狭い端末の下限を決めるのは TWD ではなく残り45本**。1px 高くすれば
        全通貨がそのぶん縮む。360x640 以上では 502〜544px あるので余裕がある。
    (!) 430px は作業指示書が置いた目安の 440px をわずかに下回る。**そのまま採用した**
        (2026-09-04 の判断)。440 は指示書が **TWD 1通貨の実測(462)から出した目安**で、
        国名が2行になる残り45本(450 から始まる)を織り込んでいなかった。
        盤面は world 400x760 の固定系を縮小表示しているだけなので機能は壊れず、
        変わるのは倍率 0.592 → 0.566(硬貨 Ø38 が 22.5px → 21.5px)だけ。
        320x568 で 12段の USD を撮って**額面(1¢/5¢/10¢/25¢)が読めること**を確認済み。
        代案は「320px では通貨名を隠す」(12px 戻って全通貨 442)だったが、
        国名・通貨名の詰め方はオーナー指示で決まっている箇所なので触っていない。
   (!!) **`.hud__main` の中に入れないこと。** 375px で 187px・**320px では 132px**
        しかなく、12段が潰れて何の絵か分からなくなる(実測)。
        `.hud` を折り返して全幅の行にするのが唯一入る形。
    (!) 幅・高さは CSS 側が持ち、JS は**バッキングストア(canvas.width/height)だけ**
        触る。JS で style.width を入れると、この 100% が固定値に置き換わって
        端末回転で伸び縮みしなくなる。 */
.hud__ladder {
  flex: 1 0 100%;
  display: block;
  width: 100%;
  height: 18px;
  margin-top: 2px;
}

/* --- 盤面 --- */
/* ============================================================
   出発演出(travel.js)— 世界地図を飛行機で移動して国を紹介する
   プレイ画面の盤面の上に重ねる。**Matter.js はまだ動いていない**ので
   ここで rAF を回しても競合しない(travel.js の注意書きと対)。
   ============================================================ */
.travel {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-md);
  /* どこを押しても飛ばせる。盤面が透けないよう地の色で覆う */
  background: var(--bg);
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}

.travel[hidden] { display: none; }

/* 演出中は盤面を出さない(器の高さを travel が受け取る) */
:root[data-screen="game"] .travel:not([hidden]) ~ .field { display: none; }

.travel__map {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
  border: 2px solid var(--line);
  background: var(--navy);
  box-shadow: var(--shadow-sm);
}

.travel__land { fill: #3D4C70; }

.travel__trail {
  fill: none;
  stroke: var(--gold);
  /* 太さは travel.js が viewBox 幅の比で属性に入れる(寄るほど太くならないように) */
  stroke-linecap: round;
  opacity: 0.85;
}

/* 目的地のピンは着いてから出す(先に出すと答えが分かってしまう) */
.travel__plane { transition: opacity 260ms ease-out; }

.travel__pin { opacity: 0; transition: opacity 200ms ease-out; }
.travel.is-arrived .travel__pin { opacity: 1; }

.travel__halo {
  fill: var(--gold);
  opacity: 0.32;
  animation: travel-pulse 1.4s ease-out infinite;
}

.travel__dot {
  fill: var(--gold);
  stroke: var(--gold-deep);
  stroke-width: 2;
}

@keyframes travel-pulse {
  from { transform: scale(0.6); opacity: 0.5; }
  to   { transform: scale(1.5); opacity: 0; }
}

/* 到着カード。飛んでいる間は伏せておき、着いた瞬間に出す */
.travel__card {
  display: flex;
  align-items: flex-start;
  gap: var(--space-md);
  padding: var(--space-md);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 260ms ease-out, transform 260ms ease-out;
}

.travel.is-arrived .travel__card { opacity: 1; transform: none; }

.travel__text {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.travel__country { font-size: 1.25rem; font-weight: 800; line-height: 1.25; }

.travel__currency { font-size: 0.75rem; color: var(--fg-muted); }

.travel__intro {
  margin: var(--space-xs) 0 0;
  font-size: 0.8125rem;
  line-height: 1.8;
}

/* 「タップでとばす」の案内(2026-09-04)。
   (!) `margin: 0`。器(.travel)は gap を持つ flex 列なので、<p> の既定マージンを
       残すと間隔が二重になる。
   (!) カードと同じく**着いてから**出す。飛行中は地図を見せる(travel.js の注意書きと対)。 */
.travel__skip {
  margin: 0;
  text-align: center;
  font-size: 0.75rem;
  color: var(--fg-muted);
  opacity: 0;
  transition: opacity 260ms ease-out;
}

.travel.is-arrived .travel__skip { opacity: 1; }

.field {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

#game-canvas {
  display: block;
  /* ブラウザ側のスクロール・ピンチに取られると狙いが定まらない */
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}

.field__loading,
.field__error {
  position: absolute;
  margin: 0;
  font-size: 0.875rem;
  color: var(--fg-muted);
}

.field__error { color: var(--coral); max-width: 80%; text-align: center; }

/* 初回だけの一行ガイド(2026-09-04・面白さ監査 項目7)。
   「おなじお金をくっつけよう。札束をつくるとクリア!」を盤面の中ほどに1行だけ出す。
   (!!) **`pointer-events: none` を外さないこと。** 盤面のタップは照準とドロップに
        直結しているので、ガイドがタップを食べると1回目の指が「消すだけ」で終わり
        「押したのに落ちない」になる。消す処理は app.js が .field の capture で拾う。
    (!) 位置は**中ほど**。上端(y 2〜112 の帯)にはコインくんと保持中の駒、それに
        ゲージ満タンの吹き出し(game.js の hint)が居るので重ねない。
    (!) 背景画像は国 × 昼/夕/夜で 93 通りある。濃紺の札 + 白縁にして、
        昼の白い雲でも夜空でも読める形にしてある(駒アートと同じ2重縁の考え方)。 */
.field__guide {
  position: absolute;
  left: 50%;
  top: 52%;
  transform: translate(-50%, -50%);
  z-index: 2;
  margin: 0;
  max-width: 84%;
  padding: 0.5rem 0.9rem;
  text-align: center;
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1.45;
  color: #FFFFFF;
  background: rgb(30 42 68 / 0.84);
  border: 2px solid rgb(255 255 255 / 0.92);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  pointer-events: none;
  animation: guide-in 260ms ease-out both;
}

/* (!) 上で display 系(ここでは position/transform)を指定しているので、
       UA の [hidden] だけでは消えないケースに備えて明示的に畳む
       (.result[hidden] を書いてあるのと同じ理由)。 */
.field__guide[hidden] { display: none; }

@keyframes guide-in {
  from { opacity: 0; transform: translate(-50%, calc(-50% + 8px)); }
  to   { opacity: 1; transform: translate(-50%, -50%); }
}

/* --- とちゅうでやめる確認(2026-09-06)-------------------------------------
   結果カードのスクリム/カードをそのまま踏襲する(同じ場所に同じ形で出るものを
   2種類の見た目にしない)。中の部品だけ **素の <button>** なのでここで着せる。
   (!) `.result` と同じ層に置くが、両方が同時に出ることはない
       (シートを出すのは「ランが生きている = 結果カードが出ていない」時だけ)。 */
.quit {
  position: absolute;
  inset: 0;
  /* (!) 初回ガイド(.field__guide・z-index 2)より上に置く。無指定だと DOM 順では後でも
         ガイドの吹き出しがシートの上に乗って「つづける」を隠す(2026-09-06 エミュレータで実測)。 */
  z-index: 3;
  display: grid;
  place-items: center;
  padding: var(--space-md);
  background: rgb(30 42 68 / 0.45);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  border-radius: var(--radius-lg);
  animation: result-in 220ms ease-out both;
}

/* (!) display 系を上で指定しているので、UA の [hidden] だけでは消えない
       (.result[hidden] を書いてあるのと同じ理由)。 */
.quit[hidden] { display: none; }

.quit__card {
  width: 100%;
  max-width: 17rem;
  padding: var(--space-lg);
  text-align: center;
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.quit__title {
  margin: 0 0 var(--space-sm);
  font-size: 1.0625rem;
  color: var(--fg);
}

.quit__body {
  margin: 0 0 var(--space-lg);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--fg-muted);
}

.quit__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

/* (!) 主役は「つづける」。**先頭に置いて色を付ける**のは、開いた人の多くが
       「押し間違えた/まだ遊ぶ」だから。「やめる」を目立たせない。 */
.quit__btn {
  min-height: 44px;          /* 指で押せる最小(誤爆を避ける) */
  padding: 0.5rem 1rem;
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--fg);
  background: var(--bg);
  border: 2px solid var(--line);
  border-radius: var(--radius-pill);
  cursor: pointer;
}

.quit__btn--primary {
  color: var(--on-accent);
  background: var(--gold);
  border-color: var(--gold-deep);
}

/* --- 結果 --- */
.result {
  position: absolute;
  inset: 0;
  z-index: 3; /* .quit と同じ理由(初回ガイドの z-index 2 より上)。DOM 順で .quit より後なので同値でよい */
  /* (!) grid + place-items: center にしない(2026-09-14)。カードが器より高くなると
         上下にはみ出して**上が切れて届かなくなる**。flex + カード側の margin: auto なら
         収まるときは中央・溢れるときは上から並んでスクロールできる。
         320x568 のツアークリアは 4 ボタン(つぎの国へ / 結果をシェア / もういちど / やめる)で
         カード 671px > 画面 568px(実測)。 */
  display: flex;
  align-items: flex-start;
  justify-content: center;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--space-md);
  background: rgb(30 42 68 / 0.45);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  border-radius: var(--radius-lg);
  animation: result-in 220ms ease-out both;
}

.result[hidden] { display: none; }

.result__card {
  width: 100%;
  max-width: 20rem;
  margin: auto;            /* 収まるときは中央(上の .result の注記) */
  flex: none;
  padding: var(--space-lg);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

.result__title {
  margin: 0 0 var(--space-md);
  font-size: 1.125rem;
  text-align: center;
  color: var(--fg);
}

.result__rows {
  margin: 0 0 var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.result__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-sm);
  padding-bottom: var(--space-xs);
  border-bottom: 1px dashed var(--line);
}

.result__row dt {
  font-size: 0.8125rem;
  color: var(--fg-muted);
}

.result__row dd {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 800;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.result__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

@keyframes result-in {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

/* ============================================================
   Phase 5: 一覧・詳細ページ(ワールドツアー / フリー選択 / 図鑑)
   中身は JS で組む(ui.js の el())。ここは見た目だけ。
   ============================================================ */

.screen--page {
  gap: var(--space-md);
  padding-block: calc(var(--space-sm) + env(safe-area-inset-top))
                 calc(var(--space-xl) + env(safe-area-inset-bottom) + var(--banner-reserve, 0px));
}

.pagebar {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.pagebar__title {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.page-body { min-height: 0; }

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.page-lead {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.7;
  color: var(--fg-muted);
}

/* --- 星 --- */
.stars {
  display: inline-flex;
  gap: 1px;
  flex: none;
}

.star {
  font-size: 0.9375rem;
  line-height: 1;
  color: var(--line);
}

.star--on { color: var(--gold); }

/* --- 国旗(flag-icons の SVG。角丸+細縁で駒と質感を揃える) --- */
.flag {
  flex: none;
  display: block;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 3px;
  border: 1px solid rgb(30 42 68 / 0.18);
  background: var(--bg-elev);
}

.flag--stage { width: 34px; height: auto; }
.flag--pick  { width: 40px; height: auto; }
.flag--card  { width: 44px; height: auto; }
.flag--hero  { width: 72px; height: auto; border-radius: var(--radius-sm); }
.flag--hud   { width: 32px; height: auto; }

/* まだ解放していない国の「?」の札(2026-08-31 オーナー指定「伏せ字を広げる」)。
   img ではなく span なので、.flag の display:block と object-fit は効かない。
   **サイズは .flag--stage / --pick / --card / --hero をそのまま使い回す**ので、
   ここでは中身の据わりと塗りだけを上書きする。 */
.flag--unknown {
  display: grid;
  place-items: center;
  height: auto;
  aspect-ratio: 4 / 3;
  font-size: 0.8125rem;
  font-weight: 800;
  line-height: 1;
  color: var(--fg-muted);
  background: var(--bg);
  border-style: dashed;
  border-color: var(--line);
}

.flag--hero.flag--unknown { font-size: 1.5rem; }

/* --- ワールドツアーのステージ一覧 --- */
.stage-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.stage {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  width: 100%;
  min-height: 56px;
  padding: var(--space-sm) var(--space-md);
  font: inherit;
  text-align: start;
  color: var(--fg);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}

.stage--cleared { border-color: var(--money-green); }

.stage--locked {
  opacity: 0.55;
  cursor: default;
  box-shadow: none;
}

.stage--locked .flag { filter: grayscale(1); }

.stage__no {
  flex: none;
  width: 1.75rem;
  font-size: 0.8125rem;
  font-weight: 800;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

.stage__body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.stage__name {
  font-size: 0.9375rem;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 目標額と自己ベストを**入るときだけ同じ行**に並べる。一覧は31行あるので
   最初から2行にはしない(記録の無い国は 56px のまま)。
   (!!) `wrap` を外さないこと。1行に押し込むと、両方に ellipsis が効いて
   320px では「目標 NT$… / ベスト NT$…」と**どちらの数字も消える**(実測)。
   金額が読めなければこの行を足した意味が無いので、入らないときは折り返す。
   (!) 文字列連結ではなく要素を並べること。ar(RTL)は flex が自動で反転する。 */
.stage__sub {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--space-sm);
  min-width: 0;
}

.stage__meta {
  font-size: 0.6875rem;
  color: var(--fg-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stage__best {
  font-size: 0.6875rem;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.stage__lock { flex: none; font-size: 0.875rem; }

/* --- ワールドツアーの入口メニューに置く「つぎの国」のカード --- */
.tourcard {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.tourcard__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tourcard__no {
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  color: var(--accent);
}

.tourcard__name {
  font-size: 1.0625rem;
  font-weight: 800;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tourcard__meta {
  font-size: 0.75rem;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

/* ★の内訳(「★2 札束 / ★3 金の延べ棒」)。目標額のすぐ下に小さく置く。
   (!) ellipsis を付けないこと。省略すると末尾の「★3 …」から食われるが、
   そこが「何を作れば星3つか」を伝える唯一の箇所。入らなければ折り返させる。 */
.tourcard__stars {
  font-size: 0.6875rem;
  color: var(--fg-muted);
}

/* --- フリーモードの通貨選択 / 図鑑一覧(同じグリッド) --- */
.pick-grid,
.zgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(6.5rem, 1fr));
  gap: var(--space-sm);
}

.pick,
.zcard {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
  padding: var(--space-sm);
  font: inherit;
  color: var(--fg);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
}

.pick--locked,
.zcard--locked {
  opacity: 0.55;
  box-shadow: none;
}

/* 図鑑一覧の「NEW」の札(2026-09-06)。**カードの角にはみ出させて**、
   中央の国旗と重ならないようにする(カードは幅 6.5rem で、旗が中央を占める)。
   (!) 高さを増やさないよう絶対配置。カードの並び(.zgrid)は触らない。
   (!) `inset-inline-end` で書く(ar は自動で左肩へ回る)。 */
.zcard { position: relative; }

.zcard__new {
  position: absolute;
  top: -6px;
  inset-inline-end: -2px;
  padding: 1px 6px;
  font-size: 0.5625rem;
  font-weight: 800;
  line-height: 1.4;
  letter-spacing: 0.02em;
  color: var(--on-accent);
  background: var(--coral-bright);
  border-radius: var(--radius-pill);
  box-shadow: 0 0 0 2px #FFFFFF;
}

.pick--locked { cursor: default; }

.pick--locked .flag,
.zcard--locked .flag { filter: grayscale(1); }

.pick__name,
.zcard__name {
  font-size: 0.75rem;
  font-weight: 700;
  text-align: center;
  line-height: 1.3;
}

.pick__meta,
.zcard__meta {
  font-size: 0.625rem;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

/* --- 図鑑の通貨ページ --- */
.zhead {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-lg);
}

.zhead__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.zhead__country {
  margin: 0;
  font-size: 1.0625rem;
  font-weight: 800;
}

.zhead__currency {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--fg-muted);
}

.zlocked {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.8;
  color: var(--fg-muted);
}

.zsec {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.zsec__title {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  color: var(--accent);
}

.zsec__text {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.9;
}

.zsec__hint {
  margin: 0;
  font-size: 0.6875rem;
  color: var(--fg-muted);
}

/* --- 額面一覧。zukanOnly(ゲームに出ない額面)も並べる(GDD §4.4) --- */
.denoms {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

.denom {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  padding: 0.3rem 0.6rem;
  font-size: 0.8125rem;
  font-weight: 700;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  font-variant-numeric: tabular-nums;
}

.denom--only {
  flex-basis: 100%;
  border-style: dashed;
  border-radius: var(--radius-md);
  font-weight: 400;
  align-items: baseline;
  flex-wrap: wrap;
}

.denom--only .denom__value { font-weight: 700; }

.denom__tag {
  font-size: 0.625rem;
  font-weight: 700;
  color: var(--on-accent);
  background: var(--gold);
  padding: 0.1rem 0.4rem;
  border-radius: var(--radius-pill);
}

.denom__note {
  flex-basis: 100%;
  font-size: 0.75rem;
  line-height: 1.7;
  color: var(--fg-muted);
}

/* 額面ごとの見どころ(材質の色・形・ポリマー・たて型)。データにあるものだけ出る */
.denom__chip {
  font-size: 0.625rem;
  font-weight: 700;
  color: var(--fg-muted);
  background: var(--bg);
  border: 1px solid var(--line);
  padding: 0.05rem 0.35rem;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}

/* 紙幣の実物の主要色。塗りは data の color を CSSOM で入れる(CSP: style 属性は不可) */
.denom__color {
  flex: none;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
  border: 1px solid var(--line);
}

/* --- お金の豆知識(複数件) --- */
.trivia {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.trivia__item {
  position: relative;
  padding-inline-start: 1.1rem;
  font-size: 0.875rem;
  line-height: 1.9;
}

/* 行頭の印。RTL でも内側に来るよう論理プロパティで置く(ar 対応・i18n-spec §1) */
.trivia__item::before {
  content: '●';
  position: absolute;
  inset-inline-start: 0;
  top: 0.35em;
  font-size: 0.5rem;
  line-height: 1;
  color: var(--gold);
}

/* --- 「このお金の特徴」。データから作る項目と値 --- */
.spec {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

/* 項目は左・値は右。**grid で組む**のは、狭い端末で値が先に折り返すのを避けるため
   (flex + min-width だと項目が幅を握って値だけが2行になる) */
.spec__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--space-sm);
  padding: 0.35rem 0.6rem;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
}

.spec__key {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--fg-muted);
}

.spec__val {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 700;
  text-align: end;
  font-variant-numeric: tabular-nums;
}

/* --- ゲーム内アートの展示。pieces.js が合成した canvas をそのまま並べる --- */
.gallery {
  display: flex;
  gap: var(--space-sm);
  overflow-x: auto;
  padding-bottom: var(--space-xs);
  -webkit-overflow-scrolling: touch;
}

.gallery__loading {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--fg-muted);
}

.gitem {
  flex: none;
  width: 4.5rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-xs);
}

.gitem__img {
  width: 100%;
  height: auto;
  max-height: 3.5rem;
  object-fit: contain;
}

/* ゲームには出ない額面(zukanOnly)。**実在するが流通が少ない**ものを図鑑にだけ並べる
   (¥2000 札 / $2 札)。ゲームの駒と混ざらないよう少し落として破線で囲う。 */
.gitem--only .gitem__img {
  opacity: 0.72;
}

.gitem--only .gitem__label::after {
  content: '*';   /* 小さなアスタリスク。文言は額面一覧の「ゲームには出ません」が持つ */
  margin-inline-start: 0.15em;
  color: var(--gold);
}

.gitem__label {
  font-size: 0.625rem;
  text-align: center;
  line-height: 1.3;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

.records {
  margin: 0;
  padding-inline-start: 1.1rem;
  font-size: 0.8125rem;
  line-height: 1.9;
}

/* --- TOP の進捗行 --- */
.top-progress {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.7;
  color: var(--fg-muted);
  text-align: center;
}

/* --- 他アプリ紹介(クロスプロモ) ---------------------------------------
   見た目の本体は css/cross-promo.css(共通実装の配布物・直さない)。
   ここでやるのは **okane のトークンを --cp-* へ流し込むこと**と、置き場所の余白だけ。

   (!) 共通CSSの既定値は `:root` にある。こちらは**枠そのものに付く `.cp-root`**
       なので、継承の近さで必ず勝つ(読み込み順に依存しない)。
       詳細度を上げた `.home-promo.cp-root` のような書き方は要らない。
   (!) 面は --bg-elev(カードと同じ)。字は --fg / --fg-muted、CTA の丸札は
       --accent + --on-accent。ライトは金茶に濃字で 5.2:1、ダークは金に濃字で 9.2:1。
       **ここに生の色を書かないこと**(テーマ切り替えで置いていかれる)。 */
.cp-root {
  --cp-surface: var(--bg-elev);
  --cp-ink: var(--fg);
  --cp-ink-sub: var(--fg-muted);
  --cp-accent: var(--accent);
  --cp-on-accent: var(--on-accent);
  --cp-radius: var(--radius-md);
  --cp-pill: var(--radius-pill);
  --cp-gap: var(--space-sm);
  --cp-pad: var(--space-md);
}

/* TOP のバナー枠。**高さを足しすぎない**のが要件(TOP は Hero + メニュー4行 +
   進捗の1文で既に詰まっていて、はみ出したぶんは Hero が縮んで吸う)。
   そのため上下の padding は一覧のカードと同じ --cp-gap まで詰めてある
   (共通CSSの .cp-card--banner は --cp-pad で背を高くしている)。 */
.home-promo .cp-card--banner {
  padding-block: var(--cp-gap);
}

/* カードは .set-card と同じ縁で囲って、設定画面でもTOPでも「札」に見せる */
.cp-root .cp-card {
  border: 2px solid var(--line);
}

/* 設定画面の一覧。見出しはカードの見出し(.set-card__title)と字の大きさを揃える */
.setting-promo .cp-title {
  font-size: 0.9375rem;
  letter-spacing: 0.02em;
}

/* (!) 枠が空のときに確実に畳む。共通UIは中身が無いと hidden を立てるだけなので、
   display を持つ規則を後から足すと UA の [hidden] に勝ってしまう。 */
.home-promo[hidden],
.setting-promo[hidden] { display: none; }

/* --- レビュー促進カードの色(共通実装 js/review-prompt.js) --------------------
   エンジンは自前で <style> を1枚流し込み、色は --rp-* で受ける
   (_tools/review-prompt/README.md「組み込み」7)。指定が無ければ**アプリの背景の
   明るさを見て**明色・暗色を自動で選ぶが、既定のアクセントは青なので
   金とクリームの画面から浮く。okane のトークンを流して馴染ませる。

   (!) body に置くのは、カードが body 直下に作られるため(枠に付けるクラスが無い)。
   (!) アプリ指定は自動判定より**常に**優先される。ここで両テーマぶんを
       トークン経由で渡しているので、ダークでも作り分けは要らない。
   (!) `--rp-accent-text` を省くと白字になり、ライトの金茶(#C98F1B)で
       コントラストが 3.4:1 まで落ちる。**必ず --on-accent と対で指定すること。**
   (!) style-src 'self' でもエンジンの <style> は通る —— head の
       jelly-csp-shim.js が横取りして adoptedStyleSheets へ載せ替えるため
       (実測で securitypolicyviolation 0件)。**CSP は緩めない。** */
body {
  --rp-surface: var(--bg-elev);
  --rp-text: var(--fg);
  --rp-text-sub: var(--fg-muted);
  --rp-accent: var(--accent);
  --rp-accent-text: var(--on-accent);
  --rp-star-on: var(--gold);
  --rp-star-off: var(--line);
}

/* --- HUD の目標表示(ツアーのみ) --- */
.hud__goal {
  font-size: 0.6875rem;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

/* --- 結果画面の星と一言 --- */
.result__stars {
  display: flex;
  justify-content: center;
  margin-bottom: var(--space-md);
}

.result__stars .star { font-size: 1.75rem; }

.result__note {
  margin: 0 0 var(--space-md);
  font-size: 0.8125rem;
  line-height: 1.7;
  text-align: center;
  color: var(--money-green);
}

/* 注記より控えめな添え書き(デイリーの「明日は …」)。
   (!) display を持たせない。持たせると先頭の [hidden] に勝ってしまい、
   hidden 属性で隠せなくなる(このファイル冒頭のコメントと同じ罠)。 */
.result__sub {
  margin: 0 0 var(--space-md);
  font-size: 0.75rem;
  line-height: 1.7;
  text-align: center;
  color: var(--fg-muted);
}

/* ============================================================
   世界地図(国境を描かない方式・陸地シルエット + ピン)
   ドラッグで移動・つまんで拡大。ピンは変換の外に置くので画面上の大きさは一定。
   ============================================================ */

.map {
  position: relative;
  /* 地図は 720x380。等倍で収めると上下が余るので、器は少しだけ縦を足した比率にする
     (拡大したときの見える範囲を確保しつつ、全体表示で間延びさせない) */
  aspect-ratio: 16 / 10;
  max-height: 52dvh;
  overflow: hidden;
  border-radius: var(--radius-lg);
  border: 2px solid var(--line);
  background: var(--navy);
  box-shadow: var(--shadow-sm);
}

/* 地図の下の「集めた国」。地図カードは 16:10 なので縦長の端末では下が大きく空く。
   (!) カードを縦に伸ばしても地図の絵は大きくならない(全体表示の倍率が幅で決まるため)。
       空きは中身で埋める、というのがこの節の趣旨。 */
.mapcollect {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.mapcollect__count {
  margin: 0;
  text-align: center;
}

.mapcollect__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(2.75rem, 1fr));
  gap: var(--space-sm);
  justify-items: center;
}

.mapcollect__item {
  display: block;
  line-height: 0;
  /* <a> なので既定の下線と色が付く。`?` の札にそれが出ると印刷ミスに見える */
  text-decoration: none;
  color: inherit;
  border-radius: var(--radius-sm);
  /* 国旗そのものが押せることが伝わるように、わずかに持ち上げる */
  box-shadow: var(--shadow-sm);
  transition: transform 140ms ease-out;
}

.mapcollect__item:active { transform: scale(0.94); }

@media (hover: hover) {
  .mapcollect__item:hover { transform: translateY(-2px); }
}

.mapcollect__item img { border-radius: var(--radius-sm); }

/* 未クリアの札は主張させない(集まっていく側を目立たせたいので) */
.mapcollect__item--locked { box-shadow: none; opacity: 0.55; }

.map__svg {
  display: block;
  width: 100%;
  height: 100%;
  /* ブラウザ側のスクロール・ピンチに取られると地図を操作できない */
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  cursor: grab;
}

.map__landpath {
  fill: #3D4C70;
  stroke: #55659200;
  stroke-width: 0;
}

/* ピン。未解放は控えめ、クリア済みは金色で目立たせる(進捗が一目で分かる) */
.pin__halo {
  fill: var(--gold);
  opacity: 0;
  transition: opacity 160ms ease-out;
}

.pin__dot {
  fill: #8C99B8;
  stroke: #1E2A44;
  stroke-width: 1.5;
}

.pin--cleared .pin__dot {
  fill: var(--gold);
  stroke: var(--gold-deep);
}

.pin--sel .pin__halo { opacity: 0.35; }

/* --- 図鑑の通貨ページに置く小さな地図(操作なし・ピン1本) ---
   .map と違い touch-action を触らない。ここは指で動かせない飾りなので、
   縦スクロールを奪うと「地図の上でページが動かない」画面になる。 */
.minimap-wrap {
  border-radius: var(--radius-lg);
  border: 2px solid var(--line);
  background: var(--navy);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.minimap { display: block; }

.minimap__svg {
  display: block;
  width: 100%;
  height: auto;
}

.minimap__land { fill: #3D4C70; }

.minimap__halo {
  fill: var(--gold);
  opacity: 0.3;
}

.minimap__dot {
  fill: var(--gold);
  stroke: var(--gold-deep);
  stroke-width: 2;
}

/* --- 選択したピンの情報 --- */
.mapsheet {
  padding: var(--space-sm) var(--space-md);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
  animation: result-in 180ms ease-out both;
}

.mapsheet[hidden] { display: none; }

.mapsheet__body {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  /* ボタンは自分の行へ折り返させる(下の .mapsheet__go)。
     Jelly のボタンは内側に 168px 相当の最小幅を持っていて、同じ行に置くと
     国名の欄が 0 幅まで潰れる(2026-08-31 に実測) */
  flex-wrap: wrap;
}

.mapsheet__text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.875rem;
}

.mapsheet__meta {
  font-size: 0.6875rem;
  color: var(--fg-muted);
}

.mapsheet__go {
  flex: 1 0 100%;
  min-height: 40px;
  font-size: 0.8125rem;
}

/* --- デイリー挑戦(Phase 6) ---
   物理プロパティ(left/right)を使わない。ar(RTL)で反転させるため。 */
.flag--daily { width: 56px; height: auto; }

.daily__head {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

.daily__headbody {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.daily__date {
  font-size: 0.6875rem;
  color: var(--fg-muted);
}

.daily__country {
  font-size: 1.0625rem;
  line-height: 1.3;
}

.daily__currency {
  font-size: 0.75rem;
  color: var(--fg-muted);
}

.daily__record {
  margin: 0;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-sm);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
}

.daily__record strong { font-size: 1.25rem; color: var(--accent); }

.daily__money,
.daily__plays {
  font-size: 0.75rem;
  color: var(--fg-muted);
}

.daily__sharemsg {
  font-size: 0.75rem;
  color: var(--money-green);
}

/* 明日の国の予告。次を引く一行なので、今日の主役より必ず控えめに */
.daily__tomorrow {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--fg-muted);
}

/* --- 世界ランキング --- */
.rank {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-md);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
}

.rank__title {
  margin: 0;
  font-size: 0.9375rem;
}

.rank__tabs {
  display: flex;
  gap: var(--space-xs);
}

.rank__tab {
  flex: 1;
  min-height: 36px;
  font: inherit;
  font-size: 0.75rem;
  color: var(--fg-muted);
  background: transparent;
  border: 2px solid var(--line);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.rank__tab--on {
  color: var(--on-accent);
  background: var(--gold);
  border-color: var(--gold-deep);
  font-weight: 700;
}

.rank__list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* 上位50件でも画面を占有しすぎない。中でだけ縦スクロールさせる */
  max-height: 17rem;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.rank__row {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-xs) var(--space-sm);
  border-radius: var(--radius-sm);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}

.rank__row:nth-child(odd) { background: rgb(30 42 68 / 0.04); }

.rank__row--me {
  background: rgb(244 185 66 / 0.22);
  font-weight: 700;
}

.rank__no {
  flex: none;
  width: 2.5rem;
  color: var(--fg-muted);
}

.rank__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rank__pt { flex: none; }

.rank__note {
  margin: 0;
  font-size: 0.6875rem;
  color: var(--fg-muted);
}

.rank__sep {
  margin: 0;
  text-align: center;
  color: var(--fg-muted);
}

/* --- 表示名の入力 --- */
.namefield {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.namefield__label {
  font-size: 0.75rem;
  color: var(--fg-muted);
}

.namefield__row {
  display: flex;
  gap: var(--space-sm);
}

.namefield__input {
  flex: 1;
  min-width: 0;
  min-height: 44px;
  padding-inline: var(--space-sm);
  font: inherit;
  font-size: 0.875rem;
  color: var(--fg);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-sm);
}

.submit__msg {
  margin: 0;
  min-height: 1.6em;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--accent);
}

/* 行の中での据わりは Jelly 化した保存ボタンにも要る */
.namefield__save { flex: none; }

button.namefield__save {
  flex: none;
  min-height: 44px;
  padding-inline: var(--space-md);
  font: inherit;
  font-size: 0.8125rem;
  font-weight: 700;
  color: var(--on-accent);
  background: var(--gold);
  border: 2px solid var(--gold-deep);
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.namefield__msg {
  font-size: 0.6875rem;
  color: var(--money-green);
}

/* ============================================================
   設定 / クレジット(Phase 7)
   到達は TOP 右上の ⚙ だけ(メニュー行に「設定」を並べない・TOP定型)。
   アイコンは作り置き素材(www/img/ui/)。出所は docs/asset-provenance.md。
   ============================================================ */
.set {
  gap: var(--space-lg);
}

/* --- マスコットの出迎え。装飾なので読み上げ対象にしない --- */
.set-hello {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

/* (!) <img> ではなく <div>。スプライトシートを背景画像で送るため(下の .msprite)。
   コマ送り(msprite-play)と上下の揺れ(mascot-bob)を**2本重ねている**。
   揺れは別アニメで足す — シートの切り出しが fit 正規化で、絵そのものには
   上下動が入っていないため(tools/make-mascot-frames.mjs の見出し参照) */
/* (!) `.msprite` と**必ず2クラスで書く**。`.msprite` はこの下に定義されていて
   同じ詳細度だと後勝ちで animation を丸ごと奪われ、揺れが消える(2026-09-01 実測) */
.set-hello__img.msprite {
  --w: 72px;
  /* 「大半静止＋時々動く」型。うるさくならないよう揺れの周期を長く取る。
     (!) この規則は animation を**丸ごと**上書きするので、idle を16コマにした
         2026-09-01 に steps(8) → steps(16) もここで直す必要があった。
         片方だけだと空白のコマが出る(.msprite--idle の注記を見ること)。 */
  animation: msprite-play-16 1.04s steps(16) infinite,
             mascot-bob 5.5s ease-in-out infinite;
}

.set-hello__text {
  margin: 0;
  font-size: 0.875rem;
  line-height: 1.7;
  color: var(--fg-muted);
}

@keyframes mascot-bob {
  0%, 62%, 100% { transform: translateY(0) rotate(0); }
  72%           { transform: translateY(-6%) rotate(-3deg); }
  84%           { transform: translateY(-2%) rotate(2deg); }
}

/* --- カード --- */
.set-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-md);
  background: var(--bg-elev);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}

.set-card__title {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  color: var(--accent);
}

.set-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.set__icon {
  flex: none;
  width: 28px;
  height: 28px;
  object-fit: contain;
}

.set-row__label {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--fg-muted);
}

.set-note {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.8;
  color: var(--fg-muted);
}

.set-note--muted { font-size: 0.6875rem; }
.set-note--ok { color: var(--money-green); font-weight: 700; }

.set-sub {
  margin: var(--space-sm) 0 0;
  font-size: 0.8125rem;
  font-weight: 700;
  color: var(--fg);
}

/* --- 選択肢のボタン列 --- */
.seg {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

.seg__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  /* タップ領域 44px 以上(TOP定型のセーフエリア規定と同じ基準) */
  min-height: 44px;
  padding-inline: var(--space-sm);
  font: inherit;
  font-size: 0.8125rem;
  color: var(--fg);
  background: transparent;
  border: 2px solid var(--line);
  border-radius: var(--radius-pill);
  cursor: pointer;
}

.seg__btn .set__icon {
  width: 20px;
  height: 20px;
}

.seg__btn[aria-pressed="true"] {
  color: var(--on-accent);
  background: var(--gold);
  border-color: var(--gold-deep);
  font-weight: 700;
}

/* 言語は22択あるので詰めて並べる。自称表記のまま出すので幅は文字任せ */
.seg--lang .seg__btn {
  font-size: 0.75rem;
  min-height: 40px;
}

/* --- ボタン ---
   .set-btn は **外部リンクの <a>(プライバシーポリシー)** と
   **Jelly 化したボタン** の2種類に付く。塗りが要るのは <a> の方だけなので
   タグで区別する(Jelly の塗りは jelly-bridge.css)。 */
a.set-btn,
button.set-btn {
  display: block;
  width: 100%;
  min-height: 48px;
  padding: var(--space-sm) var(--space-md);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  color: var(--fg);
  background: var(--bg);
  border: 2px solid var(--line);
  border-radius: var(--radius-md);
  cursor: pointer;
}

/* 外部リンク(プライバシーポリシー)。行の高さを揃える */
.set-btn--link {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--sky);
}

.set-btn--danger {
  color: #FFFFFF;
  background: var(--coral);
  border-color: var(--coral);
}

/* --- 版の表示 --- */
.set-defs {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.set-def {
  display: flex;
  justify-content: space-between;
  gap: var(--space-sm);
  font-size: 0.8125rem;
}

.set-def dt {
  color: var(--fg-muted);
}

.set-def dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
}

/* --- 結果カードのマスコット(クリア=祝う / 失敗=しょんぼり) ---
   (!) こちらも <div>。登場のポップ(mascot-pop)とコマ送り(msprite-play)を重ねる */
.result__mascot.msprite {
  --w: 88px;
  margin: 0 auto;
  /* こちらは celebrating / sad(**8コマのまま**)を出すので steps(8) */
  animation: msprite-play-8 0.9s steps(8) infinite,
             mascot-pop 520ms cubic-bezier(0.2, 1.4, 0.4, 1) both;
}

@keyframes mascot-pop {
  from { opacity: 0; transform: scale(0.6) translateY(12px); }
  to   { opacity: 1; transform: none; }
}

/* --- マスコットのスプライトアニメ(Phase 9・2026-09-01 オーナー指示) ---
   横1列8コマのシート(tools/make-mascot-frames.mjs の出力)を steps(8) で送る。

   (!) コマ送りは **px で送る**。background-size / background-position の `%` は
       「コンテナ幅 - 画像幅」を基準にするので、拡大したシートでは**1コマも見えない**
       (2026-09-01 に実測して踏んだ)。
   (!) コマ数 8 は**直書き**。`steps(var(--n))` は WebView で確実に効くとは限らない。
       シートを足すときは必ず8コマに揃えること(docs/mascot-sprite-prompt.md)。
   (!) 置く側は <img> ではなく <div>。alt が無いので aria-hidden を付ける */
.msprite {
  --w: 72px;
  flex: none;
  width: var(--w);
  height: var(--w);
  background-repeat: no-repeat;
  background-position-x: 0;
  background-size: calc(var(--w) * 8) var(--w);
  animation: msprite-play-8 1s steps(8) infinite;
}

@keyframes msprite-play-8 {
  from { background-position-x: 0; }
  to   { background-position-x: calc(var(--w) * -8); }
}
@keyframes msprite-play-16 {
  from { background-position-x: 0; }
  to   { background-position-x: calc(var(--w) * -16); }
}

/* (!) **コマ数はシートごとに違う**(2026-09-01)。idle だけ 8 → 16 に増やしてある
       (オーナー指示「ヌルヌルさせて」)。結果カードの2枚は8コマのまま = 上の既定。
   (!) 周期は 1s のままにせず 1.04s にした。**1コマ 65ms を idle と
       プレイ画面の canvas(game.js の MASCOT_FRAME_MS)で揃える**ため。
   (!) steps() に var() を入れない(WebView で確実に効かない)。コマ数を変えるときは
       この規則と game.js の MASCOT_FRAMES の**両方**を直すこと。 */
.msprite--idle {
  background-image: url("../img/mascot/idle-wave-sheet.webp");
  background-size: calc(var(--w) * 16) var(--w);
  animation: msprite-play-16 1.04s steps(16) infinite;
}
.msprite--celebrating { background-image: url("../img/mascot/celebrating-sheet.webp"); }
.msprite--sad         { background-image: url("../img/mascot/sad-sheet.webp"); }

/* (!) 上の一括停止(duration 0.001ms + iteration 1)だけでは足りない。
   steps(8) の終端は「9コマ目 = 空白」に当たるので、スプライトは明示的に
   止めて先頭コマを出す */
@media (prefers-reduced-motion: reduce) {
  .msprite {
    animation: none !important;
    background-position-x: 0 !important;
  }
}

/* ============================================================
   生きているUI(NEW-APP-GUIDE.md「静止した瞬間を作らない」・Phase 7)

   ・**登場ステージング**: 画面が切り替わった直後、直下の子とリスト行を
     階段状にポップインさせる。`hidden → 表示` でアニメが再スタートする性質を
     使うので **JS は要らない**
   ・**常時アイドル**: 主役ボタン(ワールドツアー)だけを「時々」ナッジする。
     脇役は気配程度。無限ループは「大半静止＋時々動く」型でうるささを避ける
   ・`:where()` で詳細度を 0 にしてあるので、上の個別アニメ(hero-drift 等)と
     衝突しない。**個別指定が常に勝つ**
   ・`prefers-reduced-motion: reduce` はファイル中ほどの一括停止が効く
     (無限ループは1回で止まり、登場系は即時表示になる)
   ============================================================ */
:where(.screen:not([hidden])) > :where(*) {
  animation: stage-in 420ms ease-out both;
}

:where(.menu) > :where(.menu__btn),
:where(.stage-list) > :where(*),
:where(.zgrid) > :where(*),
:where(.set) > :where(*) {
  animation: stage-in 380ms ease-out both;
}

/* 階段状の遅れ。6段目以降は同じ遅れにする(長いリストで待たされないように) */
:where(.menu) > :where(:nth-child(1)),
:where(.stage-list) > :where(:nth-child(1)),
:where(.zgrid) > :where(:nth-child(1)),
:where(.set) > :where(:nth-child(1))  { animation-delay: 0ms; }
:where(.menu) > :where(:nth-child(2)),
:where(.stage-list) > :where(:nth-child(2)),
:where(.zgrid) > :where(:nth-child(2)),
:where(.set) > :where(:nth-child(2))  { animation-delay: 50ms; }
:where(.menu) > :where(:nth-child(3)),
:where(.stage-list) > :where(:nth-child(3)),
:where(.zgrid) > :where(:nth-child(3)),
:where(.set) > :where(:nth-child(3))  { animation-delay: 100ms; }
:where(.menu) > :where(:nth-child(4)),
:where(.stage-list) > :where(:nth-child(4)),
:where(.zgrid) > :where(:nth-child(4)),
:where(.set) > :where(:nth-child(4))  { animation-delay: 150ms; }
:where(.menu) > :where(:nth-child(n+5)),
:where(.stage-list) > :where(:nth-child(n+5)),
:where(.zgrid) > :where(:nth-child(n+5)),
:where(.set) > :where(:nth-child(n+5)) { animation-delay: 200ms; }

@keyframes stage-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

/* 主役ボタンだけ「たまに」誘う。脇役(menu__btn)は動かさない = 階層を守る */
:where(.menu__btn--primary) {
  animation: stage-in 380ms ease-out both, nudge 7s ease-in-out 1.2s infinite;
}

@keyframes nudge {
  0%, 78%, 100% { transform: none; }
  84%           { transform: translateY(-3px) scale(1.015); }
  90%           { transform: translateY(0) scale(1.005); }
}

/* ⚙ は気配程度に。**押せることが伝わればよい**ので大きく動かさない。
   (2026-09-22 Hero 化で ⚙ は絶対配置をやめ Hero の grid に並んだので、
   keyframes 側の translateY(-50%) 打ち消しは不要になった) */
:where(.hero-top__gear) {
  animation: gear-wiggle 11s ease-in-out 3s infinite;
}

@keyframes gear-wiggle {
  0%, 92%, 100% { transform: rotate(0); }
  95%           { transform: rotate(18deg); }
  98%           { transform: rotate(-8deg); }
}
