/* ============================================================
   Yume Design — 3D版TOP専用スタイル（top3d.css）
   ------------------------------------------------------------
   【このファイルの立ち位置】
   3D版 index.html は style.min.css を読み込まない。
   理由：style.min.css は圧縮版ではなく style.css とバイト同一の2600行で、
   読むとカスケード全部（例：main > section:not(.hero):first-child の
   padding-top:168px）を背負う。そこで「3D版TOPに要るブロックだけ」を
   ここへ移植した。移植元＝assets/css/style.css（行番号は各節に明記）。

   【★このファイルの最重要ルール：既定は2D。3Dは opt-in】
   §15 より下の「3Dレイアウト」は html.is-3d が付いたときだけ有効になる。
   is-3d を付けるのは src-3d/main.js:55 で、判定と初期化が【全部】成功したときだけ。
     ・JSオフ／bundle.js の404      → is-3d が付かない → 2D
     ・WebGL2非対応（main.js:35）    → is-3d が付かない → 2D
     ・動きを減らす設定（main.js:32）→ is-3d が付かない → 2D（＋§16のCSS側保険で二重に守る）
     ・初期化で例外（main.js:41-52） → is-3d が付かない → 2D
   つまり全ての失敗経路が、特別扱いなしで自動的に「普通の縦スクロール」へ倒れる。
   ★逆（is-fallback を付けて2Dにする）にしてはいけない。付け忘れ＝紺色一色の
     死区間になり、しかもローダーは3Dの成否と無関係に8秒で必ず閉じる（index.html:209）
     ため、誰も異常に気づけない。

   【DOMは index.html が正。CSSをHTMLに合わせる（逆は禁止）】
   実在するクラス名だけにスタイルを当てること。過去に .hero3d__title /
   .hero3d__scroll という【HTMLに1件も無い】名前へ書いて、H1もキャッチも
   スクロール誘導も無スタイルのまま出荷しかけた事故がある。

   【読み込み順（index.html）】
     1. tokens.min.css   … --color-* 等の変数。ここでは再定義しない
     2. top3d.css        … このファイル
     3. index.html 内の <style> … ローダー（yd-loader）本体
     4. menu.js が <style id="yd-menu-style"> を自前で head に注入
        → ドロワー系（#yd-mobile-drawer*）はmenu.jsの管轄。ここでは触らない

   【前提のDOM契約】menu.js が要求するため必須
     header.site-header > nav.site-nav > a ...（無いと menu.js:114-117 が即return
     ＝ドロワーもスタイル注入も一切走らない）
     .hero / .hero__* のクラス名は使用禁止（menu.js:51-111 applyMobileHero が
     !important 付き cssText を強制注入し、リサイズごとに再実行し、DOMまで動かす）
     → 3D版ヒーローは .hero3d / .hero3d__* の別名前空間を使う。
     文字分解演出をする要素には .no-jawrap を付ける（menu.js:381 の対象外にする）

   【実際のDOM（index.html:242-264）】
     <div class="scene-wrap">                   既定=height:auto／3D時=900svh
       <canvas class="scene-canvas"></canvas>   既定=display:none／3D時=sticky 100svh
       <div class="scene-ui">                   既定=static／3D時=sticky 100svh
         <section class="scene3d hero3d is-active" data-scene="1">
           <div class="hero3d__inner">          ★実DOMは全要素がこの中に入っている
             <h1 class="hero3d__h1 no-jawrap">    SEO用の見出し（視覚上は主役ではない）
             <p  class="hero3d__catch" data-split> ★視覚上の主役「夢を、形に。」
             <p  class="hero3d__sub">             Cormorant Garamond イタリック
             <p  class="hero3d__lead">
             <div class="hero3d__cta"> a.btn.btn--gold / a.btn.btn--ghost
       </div>
       <div class="scroll-hint">                ★.scene-ui の【外】＝色を継承しない
         <span class="scroll-hint__label">SCROLL</span><span class="scroll-hint__line"></span>
       </div>
     </div>
     <footer class="site-footer">…</footer>      通常フロー

   【z-index 予算】超えないこと
     .scene-canvas            0
     .scene-ui / .scroll-hint 1〜99
     .site-header             100（--z-header）
     .yd-loader               99999（index.html インライン）
     #yd-mobile-drawer*       2147483646〜7（menu.js が自前で持つ・触らない）

   【色について】
     body 全体は暗色にしない。--color-text:#2d2d2d が濃紺に乗ると全域で
     判読不能になるため。3Dの背景は canvas 自身が不透明（alpha:false）で描くので、
     暗色は .scene-wrap などコンテナ限定で当てる（既存 .splash と同じ手法）。
     #0c1929 は style.css:903 の .splash 背景と同じ値＝トークンではない実数値。

   【Lenis のCSS】
     lenis@1.3.25 の公式CSS（node_modules/lenis/dist/lenis.css）は
     3Dバンドル側で import する前提（src-3d/main.js:13）。ここには書かない。
     ※公式CSSの lenis-stopped は overflow:clip なので sticky は死なない（実物確認済み）
   ============================================================ */


/* ============================================================
   1. リセット・ベース（移植元：style.css 6-42・最小限）
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* ★重要：style.css:8 の html{overflow-x:hidden} を clip で上書きする。
   hidden は html を「スクロールコンテナ」に変えてしまい、
   その中の position:sticky が無音で死ぬ（エラーもレイアウト崩れも出ない）。
   clip はスクロールコンテナを作らないので sticky が生きたまま横あふれだけ切れる。
   祖先のどこにも overflow-x:hidden を作らないこと。 */
html {
  scroll-behavior: auto;              /* Lenis がスクロールを持つので auto 固定 */
  -webkit-text-size-adjust: 100%;
  overflow-x: clip;
  max-width: 100%;
}
body {
  max-width: 100%;
  font-family: var(--font-jp-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
  color: var(--color-text);
  background: var(--color-base);      /* body は暗くしない（上記【色について】参照） */
  overflow-x: clip;                   /* html と同じ理由で hidden ではなく clip */
  /* 【数字を必ず「大文字の高さで揃った数字」で出す】
     Cormorant Garamond の既定は旧スタイル数字（oldstyle figures）で、0 が小文字の o の形、
     1 が I の形になる。その結果、営業の要である価格が「49,8oo円」、実績が「Ioo%」と
     誤植のように見える（実測して目視確認済み）。
     lining-nums で数字だけ大文字高さのグリフに切り替わる（Cormorant はこの機能を持つ。
     実測：指定すると "100" の幅が 129px→139px に変わる＝別グリフに切替わっている）。
     Inter や Noto Sans は元から lining なので、ここで全体に掛けても影響はない。 */
  font-variant-numeric: lining-nums;
  font-feature-settings: "lnum" 1;    /* font-variant-numeric 非対応ブラウザ向けの保険 */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* 日本語の折り返し最適化：BudouXが挿入するゼロ幅スペース位置で改行 */
  word-break: keep-all;
  overflow-wrap: break-word;          /* はみ出した時の保険のみ */
  line-break: strict;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; transition: color var(--duration-fast) var(--ease-out); }
a:hover { color: var(--color-accent); }
button { font: inherit; cursor: pointer; border: none; background: none; color: inherit; }
ul, ol { list-style: none; }

/* 段落・本文：行末の孤立を防ぐ（style.css 26-30 の3D版TOPで使う分だけ） */
p, li, dd { text-wrap: pretty; }
/* 見出し：行のバランスを自動調整（style.css 33-37 同） */
h1, h2, h3, h4, h5, h6 { text-wrap: balance; }


/* ============================================================
   2. タイポグラフィ（移植元：style.css 44-65）
   ============================================================ */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-jp-serif);
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--color-primary);
}
.en, .font-en {
  font-family: var(--font-en-serif);
  font-style: italic;
  font-weight: 500;
  letter-spacing: var(--ls-wide);
}
.label {
  font-family: var(--font-en-sans);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--color-accent);
  font-weight: 500;
}

/* 装飾線（ゴールドの細線・style.css 384-388） */
.divider { width: 60px; height: 1px; background: var(--color-accent); margin: var(--space-md) 0; }
.divider--center { margin-left: auto; margin-right: auto; }

/* スクリーンリーダー専用（skip link 等） */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}


/* ============================================================
   3. レイアウト（移植元：style.css 68-69）
   フッターの <div class="container"> が使うので必須
   ============================================================ */
.container { width: 100%; max-width: var(--container-max); margin: 0 auto; padding: 0 var(--gutter); }
.container-narrow { max-width: var(--container-narrow); margin: 0 auto; padding: 0 var(--gutter); }


/* ============================================================
   4. サイトヘッダー（移植元：style.css 78-100 / 122-133 / 866-872 / 962-979）
   ============================================================ */
.site-header {
  position: fixed; top: 0; left: 0; right: 0;
  z-index: var(--z-header);           /* =100。canvas(0) と loader(99999) の間 */
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-sm) var(--gutter);
  /* 【3D版TOP専用の変更】下層ページ（style.css）は白背景なのでオフホワイトのヘッダーで正しいが、
     このページは全面が夜空なので、同じ白いヘッダーだと切り取ったように浮く。
     上端だけ濃く、下へ向けて消えるグラデにして夜空へ溶かす。
     こうすると月が上部に来ても「白い板で切られた月」にならず、ヘッダー越しに透けて自然に見える。
     ※このファイルを読むのは index.html だけなので、下層ページのヘッダーには一切影響しない。 */
  background: linear-gradient(180deg, rgba(6, 12, 21, 0.82) 0%, rgba(6, 12, 21, 0.45) 65%, rgba(6, 12, 21, 0) 100%);
  /* 【backdrop-filter は使わない】すりガラスにすると、ヘッダーに掛かった月の上部だけが
     ぼやけて「板で切られた月」になり境界が見える（実画面で確認）。
     ぼかさず暗幕だけにすると、月は薄い夜霧越しに透けたように自然に見える。 */
  /* ★ライブの実挙動を再現：style.css:86 は background/padding を transition 指定するが、
     後方の style.css:966 が同じ .site-header に transition を再指定して打ち消しており、
     実際に効いているのは opacity/transform だけ。ここでも実挙動どおりに書く。 */
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.6s var(--ease-out), transform 0.6s var(--ease-out);
  pointer-events: auto;
}
/* 【3D版TOP専用の変更】移植元（style.css:963）はオフホワイト rgba(250,248,245,0.95) だが、
   この値をこのページに持ち込むと危険な地雷になる：上の .site-nav a と .site-header__logo-text は
   夜空に合わせて色を --color-base（#faf8f5）にしてあるので、ヘッダーが白地になった瞬間
   「オフホワイト地にオフホワイト文字」＝コントラスト約1.0でナビが完全に消える。
   is-scrolled を付けるのは assets/js/main.js:792 だけで、3D版 index.html はそのJSを読まないため
   現状この規則は一度も発火しない（＝今は無害）。しかし将来ヘッダーの追従挙動を足した瞬間に
   無言で発火してナビが消えるので、今のうちに夜空側の値へ揃えておく。
   §4 の設計判断「ヘッダーは夜空へ溶かす（白い板にしない）」とも整合させる＝
   スクロール後は“濃くなるだけ”にする。 */
.site-header.is-scrolled {
  background: rgba(6, 12, 21, 0.92);
  padding-top: 12px; padding-bottom: 12px;
  box-shadow: var(--shadow-sm);
}
.site-header.is-revealed {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.site-header__logo { display: flex; align-items: center; gap: var(--space-xs); }
.site-header__logo img { height: 40px; width: auto; }
/* 3D版TOPのロゴは線画SVG（背景が透明で夜空に溶ける）。高さだけ揃える */
/* ロゴマーク「YD」＝faviconと同じ意匠（Cormorant Garamondの金文字）。
   線画SVGは「YDと読めない」とカイさん指摘（2026-07-17）があり、文字そのものに変えた。
   フォント読込前でもTimes系のセリフ体で出るので、崩れて見える瞬間が無い。 */
.site-header__logo-mark {
  font-family: var(--font-en-serif);
  font-size: 26px;
  font-weight: 600;
  color: var(--color-accent);
  line-height: 1;
  letter-spacing: 0.04em;
  flex-shrink: 0;
}

/* menu.js が注入するハンバーガーボタンは背景 #1a2d4a のベタ塗り（menu.js:26）で、
   夜空の上では四角い板が浮く。ID セレクタ(0,1,0,0)に html.is-3d を足した(0,1,1,1)で上書きする。
   menu.js の <style> は head の末尾に後入れされるが、詳細度で勝つので順序に依存しない。 */
html.is-3d #yd-mobile-drawer-toggle {
  background: rgba(6, 12, 21, 0.55) !important;
  border: 1px solid rgba(201, 169, 97, 0.45) !important;
}
.site-header__logo-text {
  font-family: var(--font-en-serif);
  font-size: var(--fs-lg); font-weight: 600;
  /* 夜空のヘッダーに合わせてオフホワイト（下層の白ヘッダーではネイビーのまま） */
  color: var(--color-base);
  letter-spacing: var(--ls-wide);
}

/* スマホ：移植元（style.css 866-872）は白＋強ぼかしだが、このページは全面が夜空なので
   PC版と同じ「暗幕グラデ・ぼかし無し」に揃える。白いままだと夜空から板が浮き、
   ぼかすと掛かった月の上部だけが濁って境界が見える。スマホは画面が狭くヘッダーの面積比が
   大きいぶん、この差がそのまま第一印象になる。 */
@media (max-width: 768px) {
  .site-header {
    background: linear-gradient(180deg, rgba(6, 12, 21, 0.9) 0%, rgba(6, 12, 21, 0.55) 65%, rgba(6, 12, 21, 0) 100%);
  }
}

/* ヘッダー内ハンバーガー（style.css 122-133）
   ※実際に見えるのは menu.js が body直下に作る #yd-mobile-drawer-toggle の方。
     この .site-header__toggle は menu.js が ≤1024px で display:none !important にする。
     それでも「既定 display:none」をここに置くのは、>1024px で素のボタンが
     露出するのを防ぐため（menu.js のメディアクエリが届かない領域）。 */
.site-header__toggle {
  display: none; width: 40px; height: 40px;
  position: relative;
}
.site-header__toggle span {
  display: block; position: absolute; left: 8px; right: 8px; height: 2px;
  background: var(--color-primary); transition: transform var(--duration-fast);
}
.site-header__toggle span:nth-child(1) { top: 14px; }
.site-header__toggle span:nth-child(2) { bottom: 14px; }
.site-header__toggle.is-open span:nth-child(1) { top: 19px; transform: rotate(45deg); }
.site-header__toggle.is-open span:nth-child(2) { bottom: 19px; transform: rotate(-45deg); }


/* ============================================================
   5. グローバルナビ（移植元：style.css 101-120 / 135-166）
   ============================================================ */
.site-nav { display: flex; align-items: center; gap: var(--space-md); }
.site-nav a {
  font-size: var(--fs-sm);
  letter-spacing: var(--ls-wide);
  position: relative; padding: 8px 0;
  /* 夜空のヘッダーに合わせてオフホワイト（body の --color-text:#2d2d2d を継承すると読めなくなる） */
  color: var(--color-base);
}
.site-nav a::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 100%; height: 1px; background: var(--color-accent);
  transform: scaleX(0); transform-origin: right;
  transition: transform var(--duration) var(--ease-out);
}
.site-nav a:hover::after { transform: scaleX(1); transform-origin: left; }
/* ★セレクタを .site-nav a.site-nav__cta にしている理由：
   上の `.site-nav a`(0,1,1) が `.site-nav__cta`(0,1,0) に詳細度で勝つため、
   単独クラスで color を書くとオフホワイトに上書きされ、金地に白文字＝コントラスト2.12の
   WCAG違反になる（実測で検出した）。a を挟んで(0,2,1)にして確実に勝たせる。 */
.site-nav a.site-nav__cta {
  /* 【3D版TOP専用】下層の白ヘッダーではネイビー地に白文字で映えるが、
     夜空のヘッダーの上ではネイビーが背景に沈んでCTAが見えなくなる。
     常時表示のCTAは「どのシーンでも1クリックで無料相談へ」（設計書§4）の生命線なので、
     背景と最も差がつく金地＋ネイビー文字にする（コントラスト実測 6.15＝WCAG AA）。 */
  background: var(--color-accent); color: var(--color-primary);
  /* !important は移植元のまま。.site-nav a(0,1,1) が .site-nav__cta(0,1,0) より
     詳細度で勝ち padding:8px 0 を押し付けてくるため、構造上ここは外せない */
  padding: 10px 20px !important; border-radius: var(--radius-pill);
  font-weight: 500;
}
.site-nav__cta:hover { background: var(--color-accent); color: var(--color-primary); }
.site-nav__cta::after { display: none; }

/* スマホ幅のドロワー化（style.css 135-166 の移植）
   ※実運用では menu.js が ≤1024px で .site-nav{display:none !important} にするため
     このブロックは基本的に出番がない。ライブと同じ状態を保つために残している。 */
@media (max-width: 768px) {
  .site-header__toggle { display: block; }
  .site-nav {
    position: fixed; top: 0; right: 0; bottom: 0;
    width: 85%; max-width: 360px;
    flex-direction: column; justify-content: flex-start; gap: 0;
    background: var(--color-base);
    transform: translateX(100%); transition: transform var(--duration) var(--ease-out);
    padding: 72px 24px 32px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    box-shadow: -20px 0 60px rgba(10, 13, 8, 0.2);
  }
  .site-nav.is-open { transform: translateX(0); }
  .site-nav > a {
    font-size: 16px;
    padding: 12px 0;
    border-bottom: 1px solid var(--color-line);
    display: block;
    flex-shrink: 0;
  }
  .site-nav > a:last-child { border-bottom: none; }
  .site-nav__cta {
    margin-top: var(--space-md);
    text-align: center;
    background: var(--color-primary) !important;
    color: var(--color-base) !important;
    padding: 16px 24px !important;
    border-radius: var(--radius-pill);
    border-bottom: none !important;
  }
}


/* ============================================================
   6. ボタン（移植元：style.css 317-359）
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; gap: var(--space-xs);
  padding: 14px 32px; border-radius: var(--radius-pill);
  font-size: var(--fs-sm); font-weight: 500;
  letter-spacing: var(--ls-wide);
  transition: all var(--duration) var(--ease-out);
  position: relative; overflow: hidden;
  max-width: 100%;
  justify-content: center;
  text-align: center;
}
@media (max-width: 480px) {
  /* スマホ小画面ではボタン内padding縮小・文字折り返し許可 */
  .btn { padding: 12px 18px; font-size: 13px; white-space: normal; }
}
.btn--primary { background: var(--color-primary); color: var(--color-base); }
.btn--primary:hover {
  background: var(--color-accent); color: var(--color-primary);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}
.btn--outline { border: 1px solid var(--color-primary); color: var(--color-primary); }
.btn--outline:hover { background: var(--color-primary); color: var(--color-base); }
/* ゴールド塗り：#c9a961 の上に #1a2d4a ＝コントラスト 6.1:1（WCAG AA） */
.btn--gold { background: var(--color-accent); color: var(--color-primary); }
.btn--gold:hover { background: var(--color-accent-light); transform: translateY(-2px); }
.btn--ghost { color: var(--color-base); border: 1px solid var(--color-accent); }
.btn--ghost:hover { background: var(--color-accent); color: var(--color-primary); }


/* ============================================================
   7. サイトフッター（移植元：style.css 169-199 / 201-314 / 2560-2568）
   3Dキャンバスの下に通常フローで置く（設計書 Scene 6）
   ============================================================ */
.site-footer {
  background: var(--color-dark); color: var(--color-base);
  padding: var(--space-xl) 0 var(--space-md);
  position: relative;   /* canvas(z:0) と重ならないよう通常フローで下に積む */
  z-index: 1;
}
.site-footer h2, .site-footer h3 { color: var(--color-accent); }
.site-footer__top {
  display: grid; gap: var(--space-lg);
  grid-template-columns: 1fr 1fr 1fr;
  margin-bottom: var(--space-lg);
  padding-bottom: var(--space-lg);
  border-bottom: 1px solid var(--color-line);
}
@media (max-width: 768px) {
  .site-footer__top { grid-template-columns: 1fr; }
}
.site-footer__brand { display: flex; flex-direction: column; gap: var(--space-sm); }
.site-footer__brand-name {
  font-family: var(--font-en-serif);
  font-size: var(--fs-2xl); color: var(--color-accent);
  letter-spacing: var(--ls-wide);
}
.site-footer__tagline { font-size: var(--fs-sm); opacity: 0.8; }
.site-footer__nav h4 {
  color: var(--color-accent); font-size: var(--fs-sm);
  letter-spacing: var(--ls-wider); text-transform: uppercase;
  margin-bottom: var(--space-sm);
  font-family: var(--font-en-sans);
}
.site-footer__nav ul { display: flex; flex-direction: column; gap: 8px; }
.site-footer__nav a { font-size: var(--fs-sm); opacity: 0.8; }
.site-footer__nav a:hover { opacity: 1; color: var(--color-accent); }

/* ----- フッター内の連絡UIボタン（style.css 201-242） ----- */
.footer-contact-btns {
  display: flex; flex-direction: column; align-items: flex-start; gap: 12px;
  margin-bottom: var(--space-sm);
}
.footer-contact-btn {
  display: inline-flex !important;
  align-self: flex-start;
  max-width: 100%;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-pill);
  background: rgba(201, 169, 97, 0.08);
  color: var(--color-base) !important;
  font-size: 13px !important;
  font-weight: 500;
  letter-spacing: 0.05em;
  opacity: 1 !important;
  transition: all 0.3s var(--ease-out);
  text-decoration: none;
}
.footer-contact-btn:hover {
  background: var(--color-accent);
  color: var(--color-primary) !important;
  border-color: var(--color-accent);
  transform: translateX(4px);
}
.footer-contact-btn .icon { font-size: 16px; line-height: 1; }
.footer-contact-btn--primary {
  background: var(--color-accent);
  color: var(--color-primary) !important;
  font-weight: 600;
}
.footer-contact-btn--primary:hover {
  background: var(--color-accent-light);
  transform: translateX(4px);
}

/* ----- アイコンのみの円形ボタン（LINE・電話・Instagram／style.css 244-310） ----- */
.footer-contact-icons { display: flex; gap: 12px; margin-top: 10px; }
.footer-contact-icon {
  width: 48px; height: 48px;
  border-radius: 50%;
  background: rgba(201, 169, 97, 0.1);
  border: 1px solid var(--color-accent);
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  color: var(--color-accent) !important;
  font-size: 22px !important;
  text-decoration: none;
  opacity: 1 !important;
  transition: all 0.3s var(--ease-out);
}
.footer-contact-icon:hover {
  background: var(--color-accent);
  color: var(--color-primary) !important;
  transform: translateY(-3px) scale(1.05);
  box-shadow: 0 8px 20px rgba(201, 169, 97, 0.4);
}
.footer-contact-icon svg { width: 24px; height: 24px; fill: currentColor; display: block; }
/* LINE専用：背景緑＋白文字 */
.footer-contact-icon--line {
  background: #06C755 !important;
  border-color: #06C755 !important;
  color: #fff !important;
}
.footer-contact-icon--line:hover {
  background: #05A847 !important;
  border-color: #05A847 !important;
  color: #fff !important;
  transform: translateY(-3px) scale(1.05);
  box-shadow: 0 8px 20px rgba(6, 199, 85, 0.4);
}
/* 電話専用：明るいゴールド塗りつぶし＋濃ネイビーアイコン */
.footer-contact-icon--phone {
  background: var(--color-accent) !important;
  border-color: var(--color-accent) !important;
  color: var(--color-primary) !important;
}
.footer-contact-icon--phone:hover {
  background: var(--color-accent-light) !important;
  border-color: var(--color-accent-light) !important;
  color: var(--color-primary) !important;
  transform: translateY(-3px) scale(1.05);
  box-shadow: 0 8px 20px rgba(201, 169, 97, 0.5);
}
/* Instagram公式グラデーション */
.footer-contact-icon--instagram {
  background: linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%) !important;
  border-color: transparent !important;
  color: #ffffff !important;
}
.footer-contact-icon--instagram svg { width: 22px; height: 22px; }
.footer-contact-icon--instagram:hover {
  transform: translateY(-3px) scale(1.05);
  box-shadow: 0 8px 20px rgba(220, 39, 67, 0.5);
}

/* ----- 会社情報（style.css 2560-2568） ----- */
.company-info {
  margin-top: 30px; padding-top: 20px;
  border-top: 1px solid rgba(201, 169, 97, 0.2);
  font-size: 12px; line-height: 2; opacity: 0.75;
}
.company-info dt { color: var(--color-accent); font-weight: 600; margin-top: 6px; }
.company-info dd { margin-left: 0; }

/* ----- コピーライト行（style.css 311-314） ----- */
.site-footer__bottom {
  display: flex; justify-content: space-between; flex-wrap: wrap;
  font-size: var(--fs-xs); opacity: 0.6; gap: var(--space-sm);
}


/* ============================================================
   8. <noscript> の案内（index.html:327-338）
   JSが完全に無効な環境でだけ描画される。body の明るい背景の上に出るので
   文字色は body 既定（--color-text #2d2d2d on #faf8f5）でコントラストは足りるが、
   §1 のリセットで list-style も padding も消えているため最低限の体裁を戻す。
   ============================================================ */
.noscript-notice {
  max-width: var(--container-narrow);
  margin: 0 auto;
  padding: var(--space-lg) var(--gutter);
}
.noscript-notice p { margin-bottom: var(--space-sm); }
.noscript-notice ul { display: flex; flex-direction: column; gap: 8px; }
.noscript-notice a { color: var(--color-primary); text-decoration: underline; }


/* ============================================================
   9. fade-in（移植元：style.css 404-408）
   ★3D版TOP（index.html）には .fade-in が【0件】＝現時点では出番がない。
     フッターや今後のシーンで使う可能性があるので定義だけ残す。
     使うときは「既定 opacity:0 → 可視化するのは menu.js:261-277 の
     IntersectionObserver」という組み合わせが前提になる。index.html は
     menu.js を <script defer>（index.html:124）で読んでいるので条件は満たしている。
   ============================================================ */
.fade-in { opacity: 0; transform: translateY(40px); transition: opacity 1s var(--ease-out), transform 1s var(--ease-out); }
.fade-in.is-visible { opacity: 1; transform: translateY(0); }
/* JS完全無効時の保険。index.html の head script が no-js を即剥がすので、
   これが効くのは「JSがそもそも動かない＝<noscript>相当」の環境だけ＝それで正しい */
html.no-js .fade-in { opacity: 1; transform: none; transition: none; }


/* ============================================================
   10. ローダー連動フック（移植元：style.css 970-974 / 2574-2577）
   ローダー本体のCSS/HTML/JSは index.html:136-214 に集約されている
   ============================================================ */
html.yd-loading .site-header {
  opacity: 0;
  transform: translateY(-100%);
  pointer-events: none;
}
html.yd-loading #yd-mobile-drawer-toggle,
html.yd-loading #yd-mobile-drawer-overlay,
html.yd-loading #yd-mobile-drawer,
html.yd-loading .site-header { visibility: hidden !important; }

/* JSが完全に無効な環境ではローダーを閉じるJSも動かない＝黒画面で固まるので、
   最初から出さない（.yd-loader は index.html インラインのクラス名） */
html.no-js .yd-loader { display: none; }


/* ============================================================
   11. シーンの土台【既定＝2D】（ここから3D版TOP固有）
   ★ここに書くのは「3Dが動かない環境で見える姿」＝普通の縦スクロール。
     3D用の指定は §15（html.is-3d）でだけ上書きする。
   ============================================================ */

/* ---- スクロール領域 ----
   既定は height:auto＝セクションが通常フローで縦に並ぶ。
   夜空のグラデーション背景で世界観だけは維持する。
   body ではなくコンテナ限定で暗色にする（既存 .splash{background-color:#0c1929}
   と同じ手法・style.css:903）。body を暗くすると --color-text:#2d2d2d が
   濃紺に乗って全域で判読不能になるため。 */
.scene-wrap {
  position: relative;
  height: auto;
  min-height: 100vh;             /* svh 非対応ブラウザ向けのフォールバック */
  min-height: 100svh;
  background-color: #060c15;
  /* 静的な夜空：星（タイル）→ 月光 → ベースグラデーション の順に重ねる */
  background-image:
    radial-gradient(1.5px 1.5px at 30px 40px,   rgba(250, 248, 245, 0.85) 50%, transparent 51%),
    radial-gradient(1px 1px     at 140px 92px,  rgba(250, 248, 245, 0.55) 50%, transparent 51%),
    radial-gradient(1px 1px     at 205px 212px, rgba(201, 169, 97, 0.70) 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 82px 264px,  rgba(250, 248, 245, 0.45) 50%, transparent 51%),
    radial-gradient(1px 1px     at 262px 148px, rgba(250, 248, 245, 0.70) 50%, transparent 51%),
    radial-gradient(ellipse 120% 70% at 50% 4%, rgba(201, 169, 97, 0.13) 0%, transparent 62%),
    linear-gradient(180deg, #0e1a2d 0%, #0c1929 42%, #060c15 100%);
  background-repeat: repeat, repeat, repeat, repeat, repeat, no-repeat, no-repeat;
  background-size: 320px 320px, 320px 320px, 320px 320px, 320px 320px, 320px 320px, 100% 100%, 100% 100%;
  background-attachment: scroll;
}

/* ---- 3Dキャンバス ----
   ★既定は display:none。3Dが動かない環境で「紺色一色の死区間」を作らないため。
     3D時のみ §15 が sticky で貼りつける（ScrollTrigger の pin は使わない＝
     pinSpacing の自動padding副作用を避け、CSSのstickyで完結させる）。 */
.scene-canvas {
  display: none;
}

/* ---- HTMLオーバーレイ層 ----
   既定は static＝中のセクションが通常フローで縦に並ぶ。 */
.scene-ui {
  position: static;
  height: auto;
  margin-top: 0;
  color: var(--color-base);      /* 夜空の上なのでオフホワイト基調 */
  pointer-events: auto;          /* 既定は普通のページとして選択・操作できる */
}
/* 見出しの既定色（--color-primary＝ネイビー）は夜空の上では読めないので継承に切替。
   ★:where() は詳細度0。素の `.scene-ui h1`(0,1,1) だと `.hero3d__h1`(0,1,0) に
     詳細度で勝ってしまい、個別の色指定を無言で殺す。 */
.scene-ui :where(h1, h2, h3, h4, h5, h6) { color: inherit; }
/* 3D時は .scene-ui 全体が pointer-events:none になる（マウス追従を canvas に届かせるため）。
   そのとき「操作する要素」だけを復活させる。 */
.scene-ui a,
.scene-ui button,
.scene-ui [data-interactive] { pointer-events: auto; }

/* 背景輝度に関わらず WCAG AA を満たすための保険（月が来ると背景が明るくなる）。
   スクリムは「文字の後ろだけ」に置き、面で暗くしない。
   ※index.html には未使用。設計書 Scene2〜5 用の先行定義。 */
.text-scrim {
  text-shadow: 0 2px 20px rgba(12, 25, 41, 0.9), 0 0 6px rgba(12, 25, 41, 0.65);
}
/* 文章量が多いブロック用：半透明パネル
   ※index.html には未使用。設計書 Scene2〜5 用の先行定義。 */
.scene-panel {
  background: rgba(12, 25, 41, 0.45);
  backdrop-filter: blur(8px) saturate(120%);
  -webkit-backdrop-filter: blur(8px) saturate(120%);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  padding: var(--space-md);
}

/* ---- 各シーンの共通土台（実DOM：section.scene3d） ----
   既定は通常フローの1セクション。3D時のみ §15 が absolute/inset:0 で重ねる。 */
.scene3d {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* 中身が枠に収まらないときは中央寄せをやめて上詰めにする。
     通常の center は、はみ出すと padding を突き破って上へあふれるため、
     横向きスマホ（高さ390px前後）で h1 が fixed ヘッダーの裏に潜る（実測 top=48 < ヘッダー下端72）。
     safe を付けると、はみ出す場合だけ start と同じ挙動になり文字が隠れない。
     非対応ブラウザは上行の center にフォールバックする（宣言を2行に分けている理由）。 */
  justify-content: safe center;
  text-align: center;
  padding: var(--space-xl) var(--gutter);
}


/* ============================================================
   12. ヒーロー（section.scene3d.hero3d.is-active／index.html:246-260）
   ★ .hero / .hero__* は使用禁止（menu.js:51-111 が !important cssText を
     強制注入し、リサイズごとに再実行し、.hero__cta を DOM移動までする）。
     名前空間を分けることで !important 合戦を回避している。
   ★ opacity は既定1のまま。h1とCTAはSEO・導線の生命線なので、
     CSS都合で消える状態を作らない（消したいときはJSが明示的に動かす）。
   ============================================================ */
.hero3d {
  min-height: 100vh;             /* svh 非対応ブラウザ向けのフォールバック */
  min-height: 100svh;
  /* 2D時は fixed ヘッダー（実測 desktop 74.39px / mobile 72px）の下に潜らせない。
     3D時は §15 で 0 に戻す（100svh の中央に置きたいので上詰めしない）。 */
  padding-top: calc(76px + var(--space-xl));
}

/* ★実DOMでは h1/p/p/p/div が全部この .hero3d__inner に包まれている。
   つまり .hero3d の直接の子は .hero3d__inner ただ1つ＝.hero3d に gap を書いても
   何も起きない。しかも §1 の *{margin:0} で全マージンが潰れているので、
   ここで間隔を作らないと5要素が行間ゼロで密着する。間隔はこの要素の gap が持つ。 */
.hero3d__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
  width: 100%;
  max-width: var(--container-narrow);
  text-align: center;
}

/* ---- H1：SEOのための実DOM見出し。視覚上は主役ではない ----
   ★display:none / visibility:hidden / font-size:0 は絶対禁止（隠しテキスト扱い
     ＝検索エンジンからのペナルティのリスク）。小さく・金色で「必ず見せる」。
   コントラスト：#c9a961 on #0c1929 ＝ 7.9:1（WCAG AA/AAA）
   ※§18 の `html.is-3d .scene3d[aria-hidden="true"]{visibility:hidden}` はこの禁止に反しない。
     発火するのは「ヒーローをスクロールで通り過ぎた後」だけで、その時点では
     voyage.js が既に opacity:0 にしている＝新たに何かを隠してはいない。
     読み込み直後（＝クローラが見る状態。クローラはスクロールしない）は aria-hidden が
     未設定なので必ず visible になる。実測で確認すること（progress=0 で hero が見えるか）。 */
.hero3d__h1 {
  font-family: var(--font-jp-sans);
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: var(--lh-normal);
  letter-spacing: var(--ls-wider);
  color: var(--color-accent);
  text-shadow: 0 2px 12px rgba(12, 25, 41, 0.85);
}

/* ---- キャッチ：視覚上の主役（設計書§4 Scene1「中央に『夢を、形に。』」） ---- */
.hero3d__catch {
  font-family: var(--font-jp-serif);
  font-size: var(--fs-4xl);      /* clamp(2.5rem, 6vw, 4.5rem) = 40〜72px */
  font-weight: 700;
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--color-base);      /* オフホワイト */
  /* 上下だけ広めに取ると品が出る（gap 16px ＋ ここの 8px ＝ 上下24px） */
  margin-block: var(--space-xs);
  text-shadow: 0 2px 24px rgba(12, 25, 41, 0.9), 0 0 8px rgba(12, 25, 41, 0.6);
}
/* data-split（index.html:249）で1文字ずつ <span> に分解される前提の保険。
   ・文字サイズ・字間・行間は親側にだけ書く＝分解の前後で見た目が変わらない
   ・transform を効かせるため span は inline-block にする。inline-block を
     縦に並べるとベースライン分の隙間が出るが、line-height が親から継承されるので
     行の高さは変わらない
   ・span が1つも無ければ（JS到達前・2D時）この規則は何もしない */
.hero3d__catch > span {
  display: inline-block;
  white-space: pre;              /* 空白文字が span になったとき潰さない */
}

/* ---- サブ：キャッチより明確に小さく。Cormorant Garamond のイタリック ---- */
.hero3d__sub {
  font-family: var(--font-en-serif);
  font-style: italic;
  font-weight: 500;
  font-size: var(--fs-lg);       /* 1.125rem = 18px */
  color: var(--color-accent);
  letter-spacing: var(--ls-wide);
  text-shadow: 0 2px 16px rgba(12, 25, 41, 0.85);
}

.hero3d__lead {
  max-width: 40em;
  font-size: var(--fs-sm);
  line-height: var(--lh-loose);
  opacity: 0.92;
  text-shadow: 0 2px 16px rgba(12, 25, 41, 0.85);
}

.hero3d__cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm);
  margin-top: var(--space-md);   /* gap 16px ＋ ここの 24px ＝ 上に40px */
}

@media (max-width: 768px) {
  .hero3d__inner { gap: var(--space-xs); }
  .hero3d__lead { font-size: 13px; }
}


/* ============================================================
   13. スクロール誘導（div.scroll-hint／index.html:263）
   ★実DOM上、これは .scene-ui の【外】＝.scene-wrap の直下にある。
     したがって .scene-ui{color:var(--color-base)} を継承せず、
     body の --color-text:#2d2d2d を継承してしまう。それが #0c1929 に乗ると
     コントラスト約1.3:1＝実質不可視。→ 継承に頼らず色を【明示】する。
   ★2D（既定）では通常スクロールなので誘導は不要＝display:none。
     3D時だけ §15 が表示する。
   ============================================================ */
.scroll-hint {
  display: none;
  /* ↓継承ではなく明示。この1行が無いと事実上見えなくなる */
  color: var(--color-accent);    /* #c9a961 on #0c1929 ＝ 7.9:1（WCAG AA/AAA） */
  pointer-events: none;          /* 装飾（aria-hidden="true"）＝クリックを奪わない */
}
.scroll-hint__label {
  font-family: var(--font-en-sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  text-shadow: 0 2px 12px rgba(12, 25, 41, 0.8);
}
/* 細い金線（現行 .splash__scroll の美学を踏襲） */
.scroll-hint__line {
  display: block;
  width: 1px;
  height: 50px;
  background: linear-gradient(to bottom, var(--color-accent), transparent);
}


/* ============================================================
   14. シーンオーバーレイ（Scene 2〜5 用の先行定義）
   ※index.html には .scene-overlay / .scene-overlay__inner とも【0件】。
     設計書 Scene2〜5 の受け皿として残している。
   ★既定は opacity:1・通常フロー。3D時だけ §15 が重ねて opacity:0 にし、
     JSがスクロールに合わせて出す。逆にすると2Dで本文が消える。
   ============================================================ */
.scene-overlay {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-xl) var(--gutter);
  opacity: 1;
}
.scene-overlay__inner {
  width: 100%;
  max-width: var(--container-narrow);
  margin: 0 auto;
}


/* ============================================================
   15. 3Dレイアウト【opt-in／html.is-3d のときだけ有効】
   ------------------------------------------------------------
   src-3d/main.js:55 が、下記【全部】をクリアしたときにだけ is-3d を付ける。
     canvas存在 → 動きを減らす設定OFF → WebGL2対応 → detectTier/createStage が例外なし
   したがって JSオフ・bundle.js の404・WebGL2非対応・reduced-motion・初期化例外の
   すべてが、何も特別扱いせずに §11〜§14 の2D表示へ倒れる。

   ★@media (prefers-reduced-motion: no-preference) で丸ごと包んでいるのはCSS側の保険。
     main.js も reduced-motion なら is-3d を付けないが（main.js:32-34）、二重に守る。
     MDNが名指しする「大きなオブジェクトの拡大・パン」＝本件の「海→上昇→星空」
     そのものなので、演出を弱めるのではなく止めて静的表示にする。
     ※prefers-reduced-motion 自体に非対応の古いブラウザでは no-preference が偽になり
       3Dが有効にならない＝安全側に倒れるので、それで正しい。
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {

  /* スクロール距離を持たせる。height は必ず svh。
     vh はモバイルのアドレスバー出入りで値が変わり、ScrollTrigger の start/end が
     再計算されてカメラが飛ぶ（The Pudding公式警告）。
     900svh は【暫定値・実測で調整すること】。「ビューポートの8〜10倍」という数値に
     根拠は無い（Codrops記事は500vh/900vhの2値でいずれも理由の記載なし）。
     公開後にGA4のスクロール深度で「どのシーンで離脱するか」を測ってから詰める。
     長すぎる場合はシーン数を削るのではなく1シーンあたりのsvhを詰める方が体験を壊しにくい。 */
  html.is-3d .scene-wrap {
    /* ---- スクロール量（2026-07-30 実機フィードバックで 900svh → 1400svh へ）----
       カイさんの指摘：「スクロールしたときに違和感があって、スライドをきちんと読むことができない」
       原因は数値で明確だった：
         900svh を5シーンに割り、スマホではサービス3枚・実績3枚をさらに3分割していたため、
         1枚あたり約78svh ＝ iPhone(664px)で約518px のスクロールで次に切り替わる。
         指1回のフリックは慣性込みで500〜1500px進むので、**1回で1〜3枚飛ぶ**＝読む時間が無い。
       1600svh に増やし、読ませたいシーン（サービス・実績）に厚く配分することで、
       1枚あたり「完全に読める距離」を800px以上（フリック1回で飛ばない）確保する。
       実測での確認は tools/qa-scroll.mjs（1スライドあたり何px読めるかを端末別に測る）。
       配分は src-3d/systems/voyage.js の SCENES / SUB_SCENES が持つ（ここは総量だけ）。 */
    height: 1600vh;              /* svh 非対応ブラウザ向けのフォールバック */
    height: 1600svh;
    min-height: 0;
    /* 背景は canvas が不透明（alpha:false）で描くので、2Dの星グラデーションは消す。
       残す background-color は「JS実行前の白フラッシュ対策」と
       「アドレスバー退避で canvas(100svh) の下に隙間が出たとき」の受け皿。 */
    background-image: none;
    background-color: #0c1929;
  }

  html.is-3d .scene-canvas {
    display: block;              /* ★img,svg,video のリセットは canvas に効かない＝
                                    inline のままだとベースライン分の隙間が出る */
    position: sticky;
    top: 0;
    width: 100%;
    height: 100vh;               /* svh 非対応ブラウザ向けのフォールバック */
    height: 100svh;
    z-index: 0;                  /* z-index予算：canvas は必ず 0 */
  }

  /* canvas と同じ範囲に重ねる。canvas の直後に置き、margin-top で canvas 1枚分ぶん
     引き上げてから同じ条件で sticky させる
     （.scene-wrap は height を明示しているので、この負マージンで高さは変わらない）。 */
  html.is-3d .scene-ui {
    position: sticky;
    top: 0;
    height: 100vh;               /* svh 非対応ブラウザ向けのフォールバック */
    height: 100svh;
    margin-top: -100vh;          /* svh 非対応ブラウザ向けのフォールバック */
    margin-top: -100svh;
    z-index: 1;                  /* z-index予算：1〜99 の範囲 */
    /* 素通し＝マウス追従やレイキャストを canvas に届かせる。
       リンク・ボタンだけ §11 の .scene-ui a/button が auto で復活させる */
    pointer-events: none;
  }

  /* 各シーンを 100svh の枠いっぱいに重ねる */
  html.is-3d .scene3d {
    position: absolute;
    inset: 0;
    /* 上下paddingを 0 にしてはいけない。横向きスマホ（高さ390px前後）で h1 が
       fixed ヘッダーの裏に完全に潜る（Playwright実測：h1 top=34 に対しヘッダー下端=72）。
       ヘッダー分と下端のスクロール誘導分を確保し、その内側で中央寄せする。
       背の高い画面では中央寄せの見た目は変わらない。 */
    padding: 76px var(--gutter) var(--space-lg);
    pointer-events: none;
  }
  html.is-3d .hero3d {
    min-height: 0;               /* 100svh の高さは .scene3d の inset:0 が持つ */
    /* padding-top は上の .scene3d 側が持つ（ヘッダー逃げ）。ここで 0 に戻さないこと */
  }

  /* 画面が低いノートPC（例 1280x720）では、空に浮かぶ月と見出しの距離が足りず月が文字に掛かる。
     月は3D側の座標で決まりCSSからは動かせないので、文字の側を下げて避ける。
     背の高い画面（1080p以上）では余裕があるので何もしない。 */
  @media (max-height: 800px) {
    html.is-3d .scene3d {
      padding-top: 108px;
    }
  }

  /* Scene2〜5：3D時だけ隠してJSが出す（2Dでは §14 の opacity:1 のまま） */
  html.is-3d .scene-overlay {
    position: absolute;
    inset: 0;
    padding: 0 var(--gutter);
    pointer-events: none;
    opacity: 0;
  }

  /* ---- スクロール誘導：3D時だけ表示 ----
     .scroll-hint の通常フロー位置は「.scene-ui の直後」＝ y=100svh（画面外の真下）。
     sticky は bottom 指定だと"上へ引く"方向にしか働かず、最初の1画面を過ぎると
     消えてしまう。そこで .scene-ui と同じ手（負マージンで y=0 まで引き上げ →
     top:0 で 100svh ぶん貼りつける）を使い、中身だけ下端に寄せる。
     こうすると .scene-wrap が画面内にある間ずっと下端に居座り、
     フッターに入ると自然に流れて消える。 */
  html.is-3d .scroll-hint {
    display: flex;
    position: sticky;
    top: 0;
    margin-top: -100vh;          /* svh 非対応ブラウザ向けのフォールバック */
    margin-top: -100svh;
    height: 100vh;               /* svh 非対応ブラウザ向けのフォールバック */
    height: 100svh;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;   /* 中身（SCROLL＋金線）だけ下端へ */
    gap: 8px;
    padding-bottom: 24px;
    z-index: 2;                  /* z-index予算：1〜99 の範囲（canvas より前面） */
  }
}


/* ============================================================
   16. 動きを減らす設定（prefers-reduced-motion: reduce）
   ★レイアウトは §15 の @media (…: no-preference) が丸ごと効かなくなることで
     自動的に2Dになる。ここで書くのは「残った動き」を止める分だけ。
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .fade-in { opacity: 1; transform: none; transition: none; }
  .site-header { transition: none; }

  /* 画面内の動きを一律で止める。
     ★ローダー（.yd-loader とその中身）だけは対象外にする。
       index.html:154-158 が reduced-motion 用に「せり上がりも横スライドも出さないが、
       opacity 0.4s のフェードだけは残す」と【意図して】選んでいる。
       ここで transition-duration を潰すとその判断を無言で上書きしてしまう。
       ローダーの動きは index.html 側の @media が自分で止めている（animation:none）。
     ※`transition-duration: revert` で打ち返す案は【使えない】。revert は
       「author オリジンの指定が無かったこと」にするので、index.html の <style>
       （同じ author オリジン）の 0.4s まで巻き戻り、UA既定の 0s になる＝
       フェードを残すどころか完全に消える。除外する方が確実。 */
  *:not(.yd-loader, .yd-loader *),
  *:not(.yd-loader, .yd-loader *)::before,
  *:not(.yd-loader, .yd-loader *)::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}


/* ============================================================
   17. Scene 2〜5 の中身【既定＝2D】（P3で追加）
   ------------------------------------------------------------
   §14 が用意した .scene-overlay / .scene-overlay__inner の受け皿に、
   実DOM（index.html:274-351）の中身を載せる層。

   【ここに書くのは「3Dが動かない環境で見える姿」】
   夜空のグラデ（§11 .scene-wrap）の上に、サービス3枚・実績3枚が
   カードとして普通に縦に並び、全テキストが普通に読める状態。
   3Dの出し入れ（opacity・散らし配置）は §18 が html.is-3d のときだけ上書きする。
   ★逆にしない。ここで opacity:0 や absolute を既定にすると、3Dが動かない環境で
     本文が消える＝営業用サイトとして最悪の壊れ方になる。

   【色とコントラスト（設計書§9-5・qa-3d.mjs [6] が実測する）】
   背景は #060c15（§11 .scene-wrap）。文字は基本オフホワイト。
   半透明の白は【実効色】で効いてくるので、alpha は下限を実測で決めてある：
     rgba(250,248,245,0.60) on #060c15 → 実効 rgb(152,154,155) → 6.95:1（AA）
     rgba(250,248,245,0.40) on #060c15 → 実効 rgb(104,106,111) → 3.63:1（AA割れ）
   ＝ **0.4 は使えない**。設計書§4「悩みは opacity 0.4〜0.6」の下限は
   コントラスト要件（§9-5）と両立しないので、上限側の 0.6 を採る。

   【スクリムは「箱」にしない】
   3D時にここが不透明な板になると夜空が死ぬ（P2でヘッダーが白い板に見えた失敗と同型）。
   背景は半透明の暗幕＋細い金線だけにして、可読性は text-shadow と併せて確保する。
   ============================================================ */

/* ---- オーバーレイ内の共通土台 ----
   §1 の *{margin:0} で全マージンが潰れているので、要素間の間隔は
   ここの gap が唯一の供給源になる（.hero3d__inner と同じ考え方）。
   ★scene2 の worry は §18 で absolute になるが、絶対配置の子は flex の
     レイアウトから外れるだけで衝突しない＝この宣言は全シーンで共用してよい。 */
.scene-overlay__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
}

/* ---- セクション見出し（h2.scene-overlay__title／Scene3・4） ----
   色は §11 の .scene-ui :where(h1..h6){color:inherit} でオフホワイトになっている。
   ここでは大きさと、下に敷く細い金線だけを持つ。 */
.scene-overlay__title {
  font-size: var(--fs-2xl);      /* clamp(1.5rem, 2.5vw, 2rem) = 24〜32px */
  letter-spacing: var(--ls-wide);
  text-shadow: 0 2px 20px rgba(12, 25, 41, 0.9), 0 0 6px rgba(12, 25, 41, 0.65);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-sm);
}
/* 現行の .divider（§2）と同じ美学の細い金線。装飾なので擬似要素で持つ */
.scene-overlay__title::after {
  content: "";
  width: 60px;
  height: 1px;
  background: var(--color-accent);
}

/* ---- 「すべて見る」の導線（p.scene-overlay__more > a／Scene4） ---- */
.scene-overlay__more { font-size: var(--fs-sm); }
/* ★セレクタに a を挟んで(0,2,1)にしている理由：§1 の `a:hover{color:var(--color-accent)}`
   が(0,1,1)なので、単独クラス(0,1,0)で書くと hover 時に負けて色が飛ぶ。
   .site-nav a.site-nav__cta（§5）と同じ対処。 */
.scene-overlay__more a {
  color: var(--color-accent);
  letter-spacing: var(--ls-wide);
  border-bottom: 1px solid rgba(201, 169, 97, 0.4);
  padding-bottom: 4px;
  text-shadow: 0 2px 12px rgba(12, 25, 41, 0.85);
  transition: border-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.scene-overlay__more a:hover,
.scene-overlay__more a:focus-visible { color: var(--color-accent-light); border-bottom-color: var(--color-accent); }


/* ============================================================
   17-1. Scene 2「悩みの星屑」（p.worry × 4／index.html:274-281）
   設計書§4「掠れた白（opacity 0.4〜0.6）、フォントサイズ小さめ。
   ネガティブすぎない演出（禁止事項：暗いトーン過剰）」
   ------------------------------------------------------------
   ★色は opacity ではなく color の alpha で作る。
     opacity を CSS で 0.6 に固定すると、親(main.js)が GSAP で
     「浮かんでは消える」（opacity 0→1→0）を書いた瞬間に上書きされ、
     最大でも 0.6 のはずが 1.0（＝掠れない白）になる。
     color 側に alpha を持たせておけば opacity は親の自由に使える。
   ============================================================ */
.worry {
  font-family: var(--font-jp-serif);
  /* 「小さめ」＝本文(14px)より少し大きい程度に留め、主張させない */
  font-size: clamp(15px, 2.2vw, 20px);
  line-height: var(--lh-normal);
  letter-spacing: var(--ls-wide);
  /* 掠れた白。0.60 は AA を満たす下限（このファイル §17 冒頭の実測値を参照）。
     暗いトーン過剰の禁止に沿って、沈んだ灰ではなく「霞んだ白」にする */
  color: rgba(250, 248, 245, 0.6);
  text-shadow: 0 2px 20px rgba(12, 25, 41, 0.9), 0 0 6px rgba(12, 25, 41, 0.65);
}


/* ============================================================
   17-2. Scene 3「星座＝サービス」（.service-panels / .service-panel）
   実DOM：article.service-panel[data-constellation]
             > span.service-panel__mark / h3.__title / p.__lead / p.__price / a.__link
   ============================================================ */
/* ★列は必ず minmax(0, 1fr)。素の `1fr` は `minmax(auto, 1fr)` の略で、
   トラックに min-content の下限が入る。このページは §1 で
   `word-break: keep-all` を指定しているため、日本語は BudouX が入れた区切り位置
   でしか折れず min-content が非常に大きい（実測：.service-panel__lead が 250〜264px）。
   その結果トラックが均等にならず（実測 276/290/235px）、グリッドが親を突き破る。
   はみ出しは横向きスマホ(844px)で画面外まで出て初めて気づいたが、
   PC(1280px)でも __inner(880px)を26px超えていた＝画面内に収まっていて見えなかっただけ。
   minmax(0, …) で下限を外すと、はみ出す代わりに §1 の overflow-wrap:break-word で折り返す。
   ＝この指定は .work-orbs / .work-stats にも同じ理由で必要。 */
.service-panels {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-sm);
  width: 100%;                   /* 親が align-items:center の flex 列なので明示が要る */
}

/* 夜空に浮かぶ「情報」であって不透明な箱ではない＝暗幕＋細い金線だけ。
   背景色にわざとページ背景(#060c15)と同系の値を使うことで、2Dでは
   ほぼ溶けて見え、3Dでは夜空を透かしたまま文字の後ろだけが締まる。 */
.service-panel {
  display: grid;
  grid-template-columns: 1fr;
  justify-items: start;
  align-content: start;
  gap: 10px;
  padding: var(--space-md);
  text-align: left;              /* .scene3d の text-align:center を打ち消す（本文は左が読みやすい） */
  background: rgba(6, 12, 21, 0.55);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
}

/* 星座のシンボル（筆・灯台・羅針盤）。span なので grid item 化で自動的にブロックになる */
.service-panel__mark {
  font-family: var(--font-jp-serif);
  font-size: clamp(1.75rem, 3vw, 2.25rem);
  font-weight: 700;
  line-height: 1;
  color: var(--color-accent);
  letter-spacing: var(--ls-wide);
  text-shadow: 0 0 18px rgba(201, 169, 97, 0.45);  /* 星として微かに光らせる（ネオンにはしない） */
}

.service-panel__title {
  font-size: var(--fs-lg);
  letter-spacing: var(--ls-wide);
}

.service-panel__lead {
  font-size: var(--fs-sm);
  line-height: var(--lh-loose);
  color: rgba(250, 248, 245, 0.82);   /* on #060c15 ＝ 12.6:1（AA） */
}

/* 価格＝営業の要（設計書§4）。数字を Cormorant Garamond で見せる。
   ※円・月額などのCJKは Cormorant に字が無く serif へフォールバックするが、
     .site-footer__brand-name 等と同じ既存の作法なので揃えてある。
   ※値は pricing.html が正典（設計書§14-3）。ここは見た目だけを持つ。 */
.service-panel__price {
  font-family: var(--font-en-serif);
  font-size: clamp(1.05rem, 1.6vw, 1.3rem);
  font-weight: 600;
  color: var(--color-accent);         /* #c9a961 on #060c15 ＝ 8.2:1（AA） */
  letter-spacing: var(--ls-wide);
  text-shadow: 0 2px 12px rgba(12, 25, 41, 0.85);
}

/* ★(0,2,0) で §1 の a:hover(0,1,1) に勝たせる（下の :hover 側も同じ理由） */
.service-panel__link {
  font-size: var(--fs-sm);
  letter-spacing: var(--ls-wide);
  color: var(--color-accent);
  border-bottom: 1px solid rgba(201, 169, 97, 0.4);
  padding-bottom: 4px;
  transition: border-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
}
.service-panel__link:hover,
.service-panel__link:focus-visible { color: var(--color-accent-light); border-bottom-color: var(--color-accent); }


/* ============================================================
   17-3. Scene 4「実績の光る球体」（.work-orbs / .work-orb / .work-stats）
   実DOM：a.work-orb[data-orb] > span.__category / span.__title / span.__sub
   設計書§4「各カードはホバーで金枠が光り、クリックで works/ 詳細ページへ」
   設計書§9-4「Tabで全リンク到達可能」→ :focus-visible にも同じ見た目を与える
   ============================================================ */
/* 列が minmax(0, 1fr) な理由は .service-panels のコメントを参照 */
.work-orbs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-sm);
  width: 100%;
}

/* 「光る球体」の気配を、上方向からの淡い金のグラデで作る（板ではなく発光体に見せる）。
   ギラギラさせない＝金は 0.10 まで。ネオンは禁止（設計書§2）。 */
.work-orb {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: var(--space-md);
  text-align: left;
  background:
    radial-gradient(ellipse 120% 80% at 50% 0%, rgba(201, 169, 97, 0.1) 0%, transparent 70%),
    rgba(6, 12, 21, 0.55);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-lg);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  transition:
    border-color var(--duration-fast) var(--ease-out),
    box-shadow var(--duration-fast) var(--ease-out),
    transform var(--duration-fast) var(--ease-out);
}

/* ★3D時だけ、カードから「暗幕」と「ぼかし」を外す。
   設計書§4 Scene4 の主役は【球体の中に浮かぶ実績サイトの画面】であって、カードの箱ではない。
   2Dフォールバックでは背景が夜空のグラデだけなので上の暗幕が可読性を支えるが、
   3Dでは同じ暗幕がカードの真後ろにある3Dの写真を覆ってしまう（実測：覆われ面積100%・
   写真は rgba(6,12,21,0.55) と blur(5px) 越しにしか見えない状態だった）。
   3Dの写真は歪み0.000%まで作り込まれているのに、その成果をHTMLが最後に潰していた。
   → 3D時は枠線だけを残し、文字は影で読ませ、カードの上半分を「球の見える窓」として空ける。 */
@media (prefers-reduced-motion: no-preference) {
  html.is-3d .work-orb {
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    /* 上半分を球（実績写真）の居場所として空け、文字は下端へ寄せる */
    justify-content: flex-end;
    min-height: clamp(220px, 26vh, 300px);
    padding-top: clamp(150px, 18vh, 210px);
  }
  /* 暗幕を外したぶん、文字は影で夜空から浮かせる（WCAG AAはQAが実測で担保） */
  html.is-3d .work-orb__category,
  html.is-3d .work-orb__title,
  html.is-3d .work-orb__sub {
    text-shadow: 0 2px 10px rgba(6, 12, 21, 0.95), 0 0 3px rgba(6, 12, 21, 0.9);
  }
}
/* ホバーで金枠が光る（設計書§4）。:focus-visible を必ず同居させる＝
   キーボード操作でも同じ見た目になる（設計書§9-4）。
   ★§1 の a:hover{color:var(--color-accent)} を打ち消して継承に戻す。
     戻さないと中の3つの span が全部ゴールドになり、見出しと補足の区別が消える。 */
.work-orb:hover,
.work-orb:focus-visible {
  color: inherit;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px rgba(201, 169, 97, 0.35), 0 10px 34px rgba(201, 169, 97, 0.22);
  transform: translateY(-3px);
}
/* 既定のフォーカスリングは夜空だと見えにくいので、金枠の見た目に統一したうえで
   outline は消さずにオフセットして併走させる（見た目の統一とリング消失事故の両立） */
.work-orb:focus-visible { outline: 1px solid var(--color-accent); outline-offset: 3px; }

.work-orb__category {
  font-family: var(--font-en-sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: var(--ls-wider);
  color: var(--color-accent);
  text-shadow: 0 2px 12px rgba(12, 25, 41, 0.85);
}
.work-orb__title {
  font-family: var(--font-jp-serif);
  font-size: var(--fs-lg);
  font-weight: 700;
  line-height: var(--lh-tight);
  color: var(--color-base);
  text-shadow: 0 2px 16px rgba(12, 25, 41, 0.85);
}
.work-orb__sub {
  font-size: var(--fs-xs);
  line-height: var(--lh-normal);
  color: rgba(250, 248, 245, 0.78);   /* on #060c15 ＝ 11.3:1（AA） */
}

/* ---- 数字（dl.work-stats > .work-stat > dt + dd > span.count-up） ----
   カウントアップを動かすのは menu.js:225-256 の initCountUp（[data-count] を拾う）。
   menu.js は index.html:126 が全ページ defer で読んでいるので3D版TOPでも動く。
   ※数値は実在値のみ（設計書§14-2）。ここは見た目だけを持つ。 */
.work-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));   /* 理由は .service-panels のコメント参照 */
  gap: var(--space-sm);
  width: 100%;
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-line);   /* 実績カードと数字を細い金線で分ける */
}
.work-stat {
  display: flex;
  flex-direction: column-reverse;            /* DOM順は dt→dd。見せる順は「数字 → ラベル」 */
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  text-align: center;
}
.work-stat + .work-stat { border-left: 1px solid rgba(201, 169, 97, 0.18); }
/* ★数字とラベルだけは「箱」を持たない（金線1本で見せる構成なので、
   ここに .service-panel のような暗幕を敷くと途端に事務的な表になる）。
   その分だけ背景の明るさをまともに受けるので、text-shadow を二段に厚くして
   文字の周りにだけ暗いにじみを作る（§9-5「半透明スクリムか text-shadow を必ず持たせる」）。
   ＝実際、Scene4 のカメラ位置しだいでは背後に月光の道（＝画面で最も明るい場所）が来る。 */
.work-stat dt {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
  color: rgba(250, 248, 245, 0.78);
  text-shadow: 0 2px 20px rgba(12, 25, 41, 0.9), 0 0 6px rgba(12, 25, 41, 0.75);
}
/* dd は「数字＋単位」。単位（日 / + / %）は小さく、数字だけを大きく金色に見せる */
.work-stat dd {
  font-family: var(--font-en-serif);
  font-size: var(--fs-base);
  line-height: 1;
  color: var(--color-accent);
  letter-spacing: var(--ls-tight);
  text-shadow: 0 2px 20px rgba(12, 25, 41, 0.9), 0 0 8px rgba(12, 25, 41, 0.8);
}
.count-up {
  font-size: clamp(2rem, 4vw, 2.75rem);
  font-weight: 600;
  /* 桁が増減しても左右に踊らないようにする（0→3 / 0→95 / 0→100 と伸びるため）＝tabular-nums。
     ★lining-nums を【必ず並べて書く】こと。font-variant-numeric は追記ではなく【置換】なので、
       `tabular-nums` だけ書くと body(§1) から継承した lining-nums が消える。
       実測：この要素の実効値は "tabular-nums" で、lining-nums は実際に消えていた。
       今それでも「100」が正しく見えているのは、body の font-feature-settings:"lnum" 1 が
       低レベルで救っているからにすぎない（画素照合で確認：その1行を外すと「ɪoo」＝
       まさに本番 pricing.html で起きている「49,8oo円」と同じ旧スタイル数字に転落する）。
       つまり数字の正しさが「非対応ブラウザ向けの保険」と書かれた1行に依存していた＝
       誰かがその行を掃除した瞬間に、営業の要である「100%」が無言で誤植に見える状態に戻る。
       両方を明示すれば単独で成立する（修正案の画素は現状と同じ＝見た目は変わらない）。 */
  font-variant-numeric: lining-nums tabular-nums;
}


/* ============================================================
   17-4. Scene 5「月面到達＝最終CTA」（.finale__*）
   設計書§4「中央にCTA：たった30秒で無料相談＋LINEボタン」
   ★.finale__title はヒーローの .hero3d__catch と同格（--fs-4xl）。
     このページの最初と最後で同じ言葉「夢を、形に。」が同じ重さで出る構成。
   ============================================================ */
.finale__label {
  font-family: var(--font-en-sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--color-accent);
  text-shadow: 0 2px 12px rgba(12, 25, 41, 0.85);
}
.finale__title {
  font-size: var(--fs-4xl);      /* clamp(2.5rem, 6vw, 4.5rem)＝.hero3d__catch と同値 */
  color: var(--color-base);
  text-shadow: 0 2px 24px rgba(12, 25, 41, 0.9), 0 0 8px rgba(12, 25, 41, 0.6);
}
.finale__lead {
  max-width: 40em;
  font-size: var(--fs-sm);
  line-height: var(--lh-loose);
  color: rgba(250, 248, 245, 0.92);
  text-shadow: 0 2px 16px rgba(12, 25, 41, 0.85);
}
.finale__cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm);
  margin-top: var(--space-xs);
}


/* ============================================================
   17-5. スマホ（≤768px）の2Dレイアウト
   3列 → 1列。横スクロールは絶対に作らない（§1 の overflow-x:clip 方針）。
   ============================================================ */
@media (max-width: 768px) {
  /* ★`1fr` は `minmax(auto, 1fr)` の略＝トラックに min-content の下限が入る。
     §1 の word-break:keep-all があるため日本語は BudouX の区切り位置でしか折れず、
     min-content が非常に大きくなる。実測（iPhone SE 320px・2026-07-30 本番）：
     枠は 280px なのにトラックが 319.2px になり、.service-panel が右へ19pxはみ出していた。
     minmax(0, …) で下限を外すと、はみ出す代わりに折り返す（理由の詳細は §17-2 のコメント）。
     ★1列でも minmax(0, …) が要る。「1列だから安全」ではない。 */
  .service-panels,
  .work-orbs { grid-template-columns: minmax(0, 1fr); }

  /* 1列になると縦カードは背が高くなりすぎる（3枚で1画面を優に超える）。
     マーク＋見出しを同じ行に置く横型に組み替えて、1枚あたりの高さを詰める。
     ★span.__mark を落款のように見出しの隣へ置く形＝情報は1つも削らない。 */
  .service-panel {
    grid-template-columns: auto 1fr;
    column-gap: 12px;
    row-gap: 8px;
    align-items: baseline;
    padding: var(--space-sm);
  }
  .service-panel__mark  { grid-column: 1; grid-row: 1; }
  .service-panel__title { grid-column: 2; grid-row: 1; }
  /* `1 / -1` は grid-template-columns が2列を明示しているので端まで伸びる */
  .service-panel__lead  { grid-column: 1 / -1; grid-row: 2; }
  .service-panel__price { grid-column: 1 / -1; grid-row: 3; }
  .service-panel__link  { grid-column: 1 / -1; grid-row: 4; }

  .work-orb { padding: var(--space-sm); }
  .work-stats { gap: 10px; }

  /* ---- 見出しが画面の左右へあふれる問題（iPhone SE で左右16pxずつ・実測） ----
     原因は文字数ではなく【min-content 幅】。§1 の word-break:keep-all があるため
     日本語は BudouX が入れた区切り位置でしか折れず、区切り後の「聞かせてください。」9文字が
     40px×9＝352.8px の"ひと続き"になる。要素の幅（shrink-to-fit）は min-content を
     下回れないので、枠が280pxでも要素は352.8pxのまま左右へあふれる。
     ※ §1 の overflow-wrap:break-word では直らない（あれは min-content を小さくしない）。
     → ①スマホでは文字サイズを画面幅に追従させる（SE 320px で 28.8px・iPhone13 で 35.1px）
       ②最後の保険に overflow-wrap:anywhere（min-content を1文字まで下げるので原理的にあふれない。
         ただし他に折る場所が無いときだけ使われる＝通常の折り返しは今までどおり）。
     ★文言は変えない（「その夢、聞かせてください。」はカイさんが決めた言葉）。 */
  .finale__title {
    font-size: clamp(26px, 9vw, 40px);
    overflow-wrap: anywhere;
  }
  .scene-overlay__title,
  .service-panel__title,
  .work-orb__title,
  .service-panel__price { overflow-wrap: anywhere; }
}


/* ============================================================
   18. Scene 2〜5 の3Dレイアウト【opt-in／html.is-3d のときだけ有効】
   ------------------------------------------------------------
   §15 と同じ @media (prefers-reduced-motion: no-preference) で包む。
   main.js も reduced-motion では is-3d を付けない（main.js:39-41）が、CSS側でも二重に守る。
   ここが効かない ＝ §17 の 2D がそのまま生きる＝全テキストが読める、が保証される。
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {

  /* ---- 出番でないシーンを「無い」ことにする【最重要・WCAG 2.4.7】 ----
     Scene1〜5 は5枚とも inset:0 でヒーローの真上に重なっている。
     opacity:0 も pointer-events:none も【キーボード焦点は止めない】ので、
     ヒーローを見ている最中に Tab を押すと、姿の見えないリンクへ順に焦点が入る。
     （実測・修正前：progress=0 で Tab を26回押すと、見えない9本＝Scene3の3本／
       Scene4の4本／Scene5の2本に順番に焦点が入った。WCAG 2.4.7 Focus Visible 不適合、
       設計書§9-4「フォーカス順序が壊れないこと」にも反する）
     → visibility:hidden にすると焦点にもヒットテストにも入らなくなる＝根治する。

     【方式の決定：aria-hidden を鍵にする（親の変更ゼロで成立させる）】
     voyage.js:162-173 の ScrollTrigger が、出番の窓 [start-0.02, end+0.02] に応じて
     既に aria-hidden を 'false'/'true' で書き分けている。これをそのままCSSの鍵に使う。
       ・data-active を新設する案も検討したが、親が実装するまでCSSが機能しない。
         aria-hidden なら【今日のJSのまま】効く（将来 data-active が来ても下の :not() で共存する）。
       ・aria-hidden="true" なのに焦点が入る状態は、それ自体が WCAG 4.1.2 の
         既知の不適合（aria-hidden な要素が焦点可能）。visibility:hidden にすると
         「読み上げ対象外」と「操作対象外」が一致し、意味と挙動がそろう。
       ・transition が切れる心配はない：フェード窓 [start, end] は
         visible 窓 [start-0.02, end+0.02] に完全に内包される＝
         フェード中は必ず aria-hidden="false"＝visible のまま補間される。 */
  html.is-3d .scene3d[aria-hidden="true"] { visibility: hidden; }

  /* ★初期状態の穴を塞ぐ。上のルールだけでは【バグが起きるまさにその瞬間】に効かない。
     ScrollTrigger の onUpdate はスクロールが動くまで一度も呼ばれないため、
     読み込み直後は aria-hidden が【未設定】になる（実測：progress=0 で null）。
     そこで「まだ親が何も言っていない＝出番前」を、ヒーロー以外だけ隠す。
     ・ヒーロー(.hero3d)は対象外＝初回描画で必ず見える（H1とCTAは絶対に消さない）。
       クローラも scroll しないのでこの状態でページを見る＝隠しテキスト扱いの心配がない。
     ・[data-active="1"] と .is-active は逃げ道。親がどちらの方式に寄せても表示できる。 */
  html.is-3d .scene-overlay:not([aria-hidden]):not([data-active="1"]):not(.is-active) {
    visibility: hidden;
  }

  /* ★旧 `.scene-overlay a{pointer-events:none}` ＋ `.is-active a{auto}` の対は【削除した】。
     .is-active を付け外しするJSが最後まで書かれず（src-3d 全体をgrepして0件）、
     出番のシーンでもリンクが押せないまま出荷される寸前だった。
     実測（修正前）：Scene3 p=0.47／Scene4 p=0.72／Scene5 p=0.92 のいずれでも
     リンクの computed pointer-events が none で、elementFromPoint が
     リンクではなく親（.service-panel / .work-orbs / .finale__cta）を返した
     ＝最終CTA「たった30秒で無料相談」が3Dでは一度も押せない状態だった。
     上の visibility:hidden はクリックも焦点も両方止めるので、この対は不要になった。
     ★再追加しないこと。出番のシーンのリンクは §11 の .scene-ui a{pointer-events:auto} が
       復活させる＝それで足りる。 */

  /* ---- 枠 ----
     §15 の `html.is-3d .scene-overlay{padding:0 var(--gutter)}` は
     中身が空だった時点の指定。中身が入った今は、固定ヘッダー
     （実測 desktop 74.39px / mobile 72px）の下に潜らせない余白が要る。
     ★セレクタを .scene3d.scene-overlay (0,3,1) にして、§15 の
       .scene-overlay (0,2,1) と、その中の @media(max-height:800px) の
       .scene3d (0,2,1) の両方に、記述順に依存せず確実に勝たせる。
       （max-height:800px の padding-top:108px は「Scene1 で月が見出しに掛かる」
         ための逃げで、月が視界に無い Scene2〜5 には要らない） */
  html.is-3d .scene3d.scene-overlay {
    padding: 76px var(--gutter) var(--space-lg);
    /* ★safe を付ける理由：§14 の justify-content:center は、中身が枠より高いと
       上下【両方】へあふれて見出しが fixed ヘッダーの裏に潜る（横向きスマホで実際に起きる）。
       safe は、あふれる時だけ start と同じ挙動になって上端の文字を守る。
       非対応ブラウザは §14 の center にフォールバックする。 */
    justify-content: safe center;
  }

  /* ---- Scene 2：悩みを画面の別々の位置へ散らす ----
     2Dでは §17 のまま素直に縦に並ぶ。3Dのときだけ絶対配置で散らす。
     ★位置は top / left / right で持ち、transform は【使わない】。
       親(main.js)が「浮かんでは消える」演出で transform を自由に使えるようにするため
       （translate(-50%) で中央合わせにすると、その1行が親のGSAPと衝突する）。
     ★はみ出し対策：左寄せは left + max-width、右寄せは right + max-width で、
       合計が 100% を超えない組にしてある（left:4% + max 48% = 52% ＜ 100%）。
       これで文字数が増えても横スクロールは原理的に発生しない。 */
  html.is-3d [data-scene="2"] .scene-overlay__inner {
    position: relative;          /* worry の絶対配置の基準 */
    flex: 1 1 auto;              /* 列flexの主軸＝縦いっぱいに広げる（%指定の分母になる） */
    max-width: none;             /* §14 の container-narrow を外して画面幅いっぱいに散らす */
  }
  html.is-3d .worry {
    position: absolute;
    max-width: 48%;
    margin: 0;
  }
  /* 中央（＝カメラの正面・月の通り道）を避けて、上下左右にばらけさせる */
  html.is-3d .worry[data-worry="0"] { left: 4%;   top: 8%; }
  html.is-3d .worry[data-worry="1"] { right: 5%;  top: 30%; }
  html.is-3d .worry[data-worry="2"] { left: 11%;  top: 58%; }
  html.is-3d .worry[data-worry="3"] { right: 9%;  top: 80%; }

  /* ---- Scene 3・4・5：3D時は情報を少し締める ----
     2Dは「読み物」だが、3Dは100svhに収める必要があるので余白を詰める。
     ★文字サイズは落とさない（読めることが最優先）。詰めるのは余白だけ。 */
  html.is-3d .scene-overlay__inner { gap: var(--space-sm); }

  /* ---- 出番のシーンがある間は「SCROLL」を引っ込める ----
     §15 の .scroll-hint は .scene-wrap(900svh) の全域に sticky で居座る設計だが、
     それは Scene2〜5 の中身がまだ空だった時点の判断。中身が入ると実際にぶつかる
     （iPhone 13 実測：SCROLLのラベルと金線 y=563..640 が、Scene3 の3枚目の
      .service-panel(473..635) と、Scene4 の「制作実績をすべて見る」リンク(568..591) に重なる。
      PCは余白が広く当たらないので、スマホでだけ露見する）。
     そもそも SCROLL は「まだスクロールできると気づかせる」ヒーローの誘導であって、
     航海の全編で出し続けるものではない。
     ★:has() 非対応ブラウザではこの規則ごと無視される＝従来通り出たままになるだけ（安全側）。
     ★親(main.js)が自分でフェードさせるならインラインstyleが勝つので、この規則は邪魔をしない。
       transition は【意図的に付けていない】：GSAPが毎フレーム opacity を書く相手に
       CSS transition を掛けると、1フレームごとに補間が挟まって重くなるため。
     ★鍵を .is-active から aria-hidden="false" へ変更（上の §18 冒頭と同じ理由）。
       .is-active を付けるJSは存在せず、この規則は一度も発火していなかった。
       実測（修正前）：progress 0 / 0.24 / 0.47 / 0.72 / 0.92 の【全部】で
       .scroll-hint の opacity が 1 のまま＝航海の最後までSCROLLが出っぱなしだった。 */
  html.is-3d .scene-wrap:has(.scene-overlay[aria-hidden="false"]) .scroll-hint { opacity: 0; }
}


/* ============================================================
   18-1. スマホ（≤768px）の3Dレイアウト
   画面が狭いので、パネルが 100svh からはみ出さないところまで詰める。
   ★qa-3d.mjs [4] が iPhone 13 相当で横方向のはみ出しを実測する。
     縦もここで収める（3枚 × 縦カードでは 1画面に入りきらないため §17-5 の横型が前提）。
   ============================================================ */
@media (prefers-reduced-motion: no-preference) and (max-width: 768px) {
  /* ---- ヒーローの文字が「月の白」に溶ける問題（2026-07-30 実測で発覚）----
     スマホは画面が狭いぶん月が相対的に大きく写り、H1とリード文の真後ろに白い月面が来る。
     実測（iPhone SE 320x568）：H1「木更津のホームページ制作 Yume Design」の
     実画素コントラストが 1.06〜1.3（必要4.5）＝ほぼ読めない。
     SEOと営業の両方で一番大事な1行なので必ず読めるようにする。

     【影だけでは足りない理由】text-shadow は文字の【周り】を暗くするので、
     人の目には縁ができて読みやすくなるが、文字の真下の背景は白い月のまま
     ＝コントラストの数値は1ミリも改善しない（実測で確認）。
     そこで H1 には「文字の形に沿った細い暗がり」を敷く。面で暗幕を張るのではなく、
     文字の背後だけに濃紺の帯を置く＝夜空と月の絵はそのまま残る。 */
  html.is-3d .hero3d__h1 {
    display: inline-block;
    padding: 4px 12px;
    border-radius: var(--radius-pill);
    background: rgba(6, 12, 21, 0.72);
    text-shadow: 0 0 3px rgba(6, 12, 21, 0.98), 0 0 8px rgba(6, 12, 21, 0.9);
  }
  /* リード文は行数が多く帯にすると重いので、影で縁取るだけにする（背景が海＝比較的暗いので足りる） */
  html.is-3d .hero3d__lead {
    text-shadow:
      0 0 3px rgba(6, 12, 21, 0.98),
      0 0 8px rgba(6, 12, 21, 0.95),
      0 2px 18px rgba(6, 12, 21, 0.9);
  }
  /* 装飾のSCROLLも月光の帯に乗ると沈むので同じ手当てをする（実測 iPhone13：4.36／必要4.5） */
  html.is-3d .scroll-hint__label {
    text-shadow: 0 0 3px rgba(6, 12, 21, 0.98), 0 0 8px rgba(6, 12, 21, 0.9);
  }

  /* ---- 金ボタンの文字を濃くする ----
     金地(#c9a961)にネイビー(#1a2d4a)＝計算上は6.0だが、13pxの細い日本語は
     線が細くアンチエイリアスで薄まり、実画素では 3.47〜4.4（必要4.5）に届かない。
     文字色を最も濃いネイビー(#0e1a2d)にして芯を濃くする。金の地色は変えないので印象は同じ。 */
  html.is-3d .btn--gold { color: var(--color-primary-dark); font-weight: 600; }

  /* ---- 悩みの星屑テキスト ----
     設計書§4は「掠れた白（opacity 0.4〜0.6）」。月の明るい面に重なると沈むので濃さを上げ、
     影で縁取る。
     【背景は敷かない】一度 radial-gradient の霞を敷いてみたが、グラデーションは要素の矩形で
     切られるため、実画面では【四角い箱】が浮いて星屑の風情が完全に壊れた（スクショで確認）。
     影だけで実物は問題なく読める（実画面で目視確認済み）。 */
  html.is-3d .worry {
    color: rgba(250, 248, 245, 0.9);
    text-shadow:
      0 0 4px rgba(6, 12, 21, 0.98),
      0 0 10px rgba(6, 12, 21, 0.95),
      0 2px 20px rgba(6, 12, 21, 0.9);
  }

  html.is-3d .scene3d.scene-overlay { padding: 76px var(--gutter) var(--space-md); }
  html.is-3d .scene-overlay__inner { gap: 12px; }
  html.is-3d .scene-overlay__title { gap: 10px; font-size: var(--fs-xl); }

  html.is-3d .service-panels,
  html.is-3d .work-orbs { gap: 10px; }
  html.is-3d .service-panel { padding: 12px 14px; row-gap: 5px; }
  html.is-3d .service-panel__lead,
  html.is-3d .work-orb__sub { font-size: 12px; line-height: var(--lh-normal); }
  html.is-3d .work-orb { padding: 12px 14px; gap: 4px; }
  html.is-3d .work-stats { padding-top: 12px; }

  /* すりガラスは3Dが回っている最中のスマホでは純粋な負荷（GPUが既に月と星で埋まっている）。
     暗幕（rgba）だけ残せば見た目はほぼ変わらないので、スマホ3D時だけ外す。
     ★FPSが足りない時に最初に外すべきレバーがここ、という位置づけ。 */
  html.is-3d .service-panel,
  html.is-3d .work-orb {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* 横向きスマホ・背の低い画面（高さ≦520px）。
   縦の余白から先に削り、それでも足りない分だけ文字を詰める。
   ここまでやっても入りきらない場合は上端が切れずに下があふれる
   （justify-content:safe center）＝見出しから読めるので破綻はしない。 */
@media (prefers-reduced-motion: no-preference) and (max-height: 520px) {
  html.is-3d .scene3d.scene-overlay { padding: 76px var(--gutter) 16px; }
  html.is-3d .scene-overlay__inner { gap: 10px; }
  html.is-3d .scene-overlay__title { font-size: var(--fs-lg); gap: 8px; }
  html.is-3d .scene-overlay__title::after { width: 40px; }
  html.is-3d .service-panel { padding: 10px 12px; }
  html.is-3d .work-orb { padding: 10px 12px; }
  html.is-3d .finale__title { font-size: var(--fs-3xl); }
  html.is-3d .count-up { font-size: 1.75rem; }
  /* 球の窓を padding の実数で決め打つと、縦が極端に短い画面ではカードが枠を突き抜ける
     （min-height:clamp(220px,…) がそのまま高さの下限になるため）。窓は画面の高さに追従させる。
     実測（844x390 の横向き）：この2行が無いと「制作実績をすべて見る」が画面下へ17px出る。 */
  html.is-3d .work-orb { min-height: 0; padding-top: clamp(44px, 16vh, 150px); }
  html.is-3d .work-stats { padding-top: 8px; }

  /* ---- ヒーロー（Scene1）も背の低い画面では収まらない ----
     実測：844x390 で .hero3d__inner が画面下へ40px、926x428 で7px、667x375 で6px出ていた
     （文字サイズが vw 基準なので、横向きにすると幅が増えて文字まで大きくなるのが原因）。
     ★H1・キャッチ・CTAは1つも消さない。縦の余白から先に削り、足りない分だけ
       キャッチを「画面の高さ」基準（vh）にして、横に広がっても背が伸びないようにする。 */
  html.is-3d .hero3d__inner { gap: 6px; }
  html.is-3d .hero3d__catch {
    font-size: clamp(1.75rem, 11vh, 2.75rem);
    margin-block: 0;
  }
  html.is-3d .hero3d__sub { font-size: var(--fs-sm); }
  html.is-3d .hero3d__lead { font-size: 12px; line-height: var(--lh-normal); }
  html.is-3d .hero3d__cta { margin-top: 8px; gap: 10px; }
  html.is-3d .hero3d__cta .btn { padding: 10px 18px; font-size: 13px; }
}

/* ---- 背の低い画面：装飾の「SCROLL」がCTAボタンに重なる ----
   実測 844x390：ボタンの上に SCROLL の文字が乗っていた。
   さらに iPhone SE(320x568) でも「料金プランを見る」の中に SCROLL が刷り込まれていた
   （上の 520px の網から漏れていた。SEは568pxあるため）。
   SCROLL は aria-hidden の装飾で、CTAは営業の導線。ぶつかるなら装飾の側を引っ込める。 */
@media (prefers-reduced-motion: no-preference) and (max-height: 620px) {
  html.is-3d .scroll-hint { display: none; }
}


/* ============================================================
   18-2. スマホの3D：Scene3・4は「1画面に1つ」を大きく見せる
   ------------------------------------------------------------
   【なぜ作り直したか（2026-07-30・本番で発覚）】
   3D時は各シーンが 100svh の枠に position:absolute で重なる。
   PCは横3列に並ぶので収まるが、スマホは §17-5 で【縦積み】になるため構造的に収まらない。
   本番 https://yume-design.net/ の実測：
     iPhone 13(390x664) 実績シーン＝はみ出し21件（カード3枚で縦680px ＞ 枠664px＝3枚目が画面外）
     iPhone SE(320x568) サービス12件／実績22件／CTA2件
   → 小さい要素を3つ詰め込むのをやめ、スクロールに応じて【1つずつ】大きく見せる。
     縦長のスマホには「1つを大きく」の方が合う。情報は1つも削らない（1枚あたりが大きく読みやすくなる）。

   【JS（3D側）との契約】※親＝結城が確定させた設計。ここを勝手に変えないこと
     ・進行度を3等分し、出番のパネル／カードにだけ data-sub-active="1" を付ける。
       出番でないものには "0" を付ける（voyage.js の data-active と同じ書き方）。
         Scene3: 0.34-0.43 筆 ／ 0.43-0.52 灯台 ／ 0.52-0.60 羅針盤
         Scene4: 0.60-0.68 またべゑ ／ 0.68-0.76 aap ／ 0.76-0.84 ANNA
     ・このCSSが1つずつ見せるのは【幅 768px 以下 かつ html.is-3d】のときだけ。
       JS側も同じ 768px で切り替えること（食い違うと、その幅帯だけ1枚しか出ない状態になる）。
     ・**JSが未実装／失敗しても1枚目は必ず出る**（:first-child:not([data-sub-active="0"])）。
       真っ黒な死区間は作らない＝壊れ方を安全側に倒してある。
     ・カードは display:none にしない。scene4-works.js の readOverlay が
       .work-orb の矩形を読んで球の居場所と大きさを決めるため、矩形は常に確定させておく必要がある
       （visibility:hidden なら矩形は残る）。

   【2Dは触らない】ここは全て html.is-3d の中。3Dが動かない環境では §17 のまま
     3枚が普通に縦に並んで全テキストが読める＝最後の砦は無傷。
   【PCも触らない】ここは全て max-width:768px の中（qa-3d.mjs 32/32 の維持で実測確認）。
   ============================================================ */

/* ★モード（3列 or 1つずつ）の出典は【このCSS】。JSはここを読む。
   voyage.js:97 detectSubMode() が
     ①`--yd-sub-scene-mode` が "1"／"0" ならそれに従う（最優先）
     ②無ければ .service-panels の実際の段数を測る
     ③それも読めなければ matchMedia('(max-width: 768px)')
   の順で判断する。①を書いておけば、**CSSのブレークポイントを動かしてもJSが自動で追従する**
   （下の @media の条件を変えたら、この変数の @media も必ず同じ条件にすること）。
   ※custom property は描画に一切影響しない＝PCの見た目は1pxも動かない。 */
html { --yd-sub-scene-mode: 0; }          /* 既定＝PC（横3列のまま） */

@media (prefers-reduced-motion: no-preference) and (max-width: 768px) {
  html.is-3d { --yd-sub-scene-mode: 1; }  /* スマホ幅の3D時だけ「1つずつ」 */


  /* ---- 舞台（3枚を重ねる器）----
     絶対配置の子は親の高さを作らないので、器の高さは flex で確保する。
     ★器の高さ＝「シーンの内側（100svh − 上下padding）から見出し・数字・リンクを引いた残り」。
       実数で決め打ちしないので、どの画面でも原理的に枠からはみ出さない。 */
  html.is-3d [data-scene="3"] .scene-overlay__inner,
  html.is-3d [data-scene="4"] .scene-overlay__inner {
    flex: 1 1 auto;
    min-height: 0;               /* 既定 auto だと中身のぶん縮まず、あふれる */
    width: 100%;
  }
  html.is-3d .service-panels,
  html.is-3d .work-orbs {
    display: block;              /* grid をやめる（子は絶対配置で重ねる） */
    position: relative;          /* 子の inset:0 の基準 */
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
  }

  /* ---- 1つだけ見せる（クロスフェード）----
     ★visibility も併せて切り替える。opacity:0 だけでは見えない要素にキーボード焦点が入る
       （§18 冒頭と同じ理由・WCAG 2.4.7）。
     ★visibility の遅延を「消えるときだけ」にすることで、前が消えてから次が出る死区間を作らずに
       クロスフェードできる（出る側は遅延0・消える側はフェード完了後に hidden）。 */
  html.is-3d .service-panel,
  html.is-3d .work-orb {
    position: absolute;
    inset: 0;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.28s var(--ease-out), visibility 0s linear 0.28s;  /* 0.42s→0.28s：クロスフェード中は文字が薄く読みにくいので短くする（読める区間を広げる） */
  }
  html.is-3d .service-panel[data-sub-active="1"],
  html.is-3d .work-orb[data-sub-active="1"],
  /* ↓JSがまだ何も言っていないとき（未実装・実行前・失敗時）の保険＝1枚目を出す */
  html.is-3d .service-panel:first-child:not([data-sub-active="0"]),
  html.is-3d .work-orb:first-child:not([data-sub-active="0"]) {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.28s var(--ease-out), visibility 0s;
  }

  /* ---- サービス：1つを主役にする ----
     ★箱（暗幕＋金枠）をやめる。1枚が画面いっぱいの高さになるので、そのまま箱にすると
       夜空と星座を全面が覆ってしまう（P2でヘッダーが白い板に見えたのと同型の失敗）。
       文字の後ろだけを柔らかい暗がりで締め、周囲は夜空を透かす。可読性は暗がり＋影で担保する。 */
  html.is-3d .service-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: clamp(8px, 1.8vh, 14px);
    padding: 8px 0;
    background: radial-gradient(ellipse 92% 66% at 50% 50%,
      rgba(6, 12, 21, 0.74) 0%, rgba(6, 12, 21, 0.5) 52%, rgba(6, 12, 21, 0) 78%);
    border: none;
    border-radius: 0;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  /* シンボル（筆／灯台／羅針盤）＝1枚見せの主役。星として淡く光らせる（ネオンにはしない） */
  html.is-3d .service-panel__mark {
    font-size: clamp(2.5rem, 13vw, 3.5rem);
    line-height: 1;
    text-shadow: 0 0 28px rgba(201, 169, 97, 0.5), 0 2px 14px rgba(6, 12, 21, 0.9);
  }
  html.is-3d .service-panel__title {
    font-size: clamp(1.25rem, 5.6vw, 1.75rem);
    line-height: var(--lh-tight);
    /* 箱の暗幕を外したぶん、文字は影で夜空から浮かせる（§9-5） */
    text-shadow: 0 2px 16px rgba(6, 12, 21, 0.95), 0 0 6px rgba(6, 12, 21, 0.85);
  }
  html.is-3d .service-panel__lead {
    max-width: 26em;
    font-size: clamp(13px, 3.8vw, 15px);
    line-height: 1.85;
    color: rgba(250, 248, 245, 0.92);
    text-shadow: 0 2px 14px rgba(6, 12, 21, 0.95), 0 0 6px rgba(6, 12, 21, 0.8);
  }
  /* 価格＝営業の要（設計書§4）。1枚見せで余白ができたぶん、金の細枠で「札」にして必ず目に入れる */
  html.is-3d .service-panel__price {
    font-size: clamp(1.15rem, 5.2vw, 1.5rem);
    line-height: 1.5;
    max-width: 100%;
    padding: 6px 16px;
    border: 1px solid var(--color-line);
    border-radius: var(--radius-pill);
    background: rgba(6, 12, 21, 0.5);
  }
  html.is-3d .service-panel__link {
    font-size: 14px;
    padding-bottom: 6px;
    text-shadow: 0 2px 12px rgba(6, 12, 21, 0.9);
  }

  /* ---- 実績：写真の球を主役にし、文字は下端へ ----
     ★上の空きが、そのまま3D側の「球の窓」になる（scene4-works.js の readOverlay が
       カード上端〜.work-orb__category 上端を窓として実測する）。実数の padding-top では
       画面の高さに追従できないので、justify-content:flex-end で「残り全部」を窓にする。 */
  html.is-3d .work-orb {
    min-height: 0;               /* §17-3 の clamp(220px,…) を解除（短い画面で枠を突き抜けるため） */
    padding: 0 0 clamp(4px, 1.2vh, 10px);
    justify-content: flex-end;
    align-items: center;
    text-align: center;
    gap: 5px;
    /* 文字の後ろだけ下から締める。上の窓は透かしたまま＝実績写真の球を主役にする */
    background: linear-gradient(180deg,
      rgba(6, 12, 21, 0) 52%, rgba(6, 12, 21, 0.55) 82%, rgba(6, 12, 21, 0.72) 100%);
    border: none;
    border-radius: 0;
  }
  html.is-3d .work-orb__category { font-size: 12px; }
  html.is-3d .work-orb__title {
    font-size: clamp(1.375rem, 6vw, 2rem);
    line-height: var(--lh-tight);
  }
  html.is-3d .work-orb__sub {
    font-size: clamp(12px, 3.4vw, 14px);
    color: rgba(250, 248, 245, 0.88);
  }
  /* 数字（最短納期／Lighthouse／データ移行）は残したまま、球の窓を広げるぶんだけ小さくする */
  html.is-3d .work-stats { padding-top: 10px; gap: 8px; }
  html.is-3d .count-up { font-size: clamp(1.5rem, 6vw, 2rem); }

  /* ---- 月が下から突き出して文字に掛かる問題への備え ----
     月の位置は3D側（scene4-works.js / moon.js）の座標で決まり、CSSからは動かせない。
     動かせないなら文字の側で守る。スマホは画面が狭く、月は画面下部の【最も明るい面】として
     必ず文字に掛かる（実測：iPhone SE のサービス／実績／CTAの各シーンで発生）。
     ★大きくぼかした影は明るい面の上では効かない。効くのは「文字の輪郭のすぐ外に置く濃い影」＝
       にじみ半径の小さい影を重ねて、文字のふちに暗い縁取りを作る。 */
  html.is-3d .scene-overlay__more a,
  html.is-3d .service-panel__link,
  html.is-3d .work-orb__category,
  html.is-3d .work-orb__sub,
  html.is-3d .work-stat dt,
  html.is-3d .work-stat dd,
  html.is-3d .finale__lead {
    text-shadow:
      0 0 3px rgba(6, 12, 21, 0.98),
      0 0 8px rgba(6, 12, 21, 0.95),
      0 2px 18px rgba(6, 12, 21, 0.88);
  }
  /* 「LINEで相談」＝白抜きのボタン。Scene5 では月の【真上】に重なるため
     （実測：iPhone SE で月に完全に乗る）、枠線と白文字だけでは沈む。
     塗りではなく暗幕を1枚だけ敷いて、夜空の上では今までどおり・月の上では読める状態にする。 */
  html.is-3d .btn--ghost { background: rgba(6, 12, 21, 0.6); }

  /* ---- 画面の下端だけに効く淡い暗幕（月よけ）----
     月は Scene3〜5 の間、画面の【下から】昇ってくる（実測：サービス／実績／CTAの3シーンとも、
     画面下部の文字＝リンク・数字・ボタンの真後ろを通る）。
     ★面で暗くしない（このファイル §17 の「スクリムは箱にしない」方針）。下端へ向かってだけ
       濃くなるグラデにすると、夜空の上ではほぼ見えず、明るい月が来たときにだけ効く。
     ★z-index:-1 で文字より後ろに敷く。.scene-ui（z-index:1）が積み重ねの文脈を作っているので、
       -1 にしても canvas より後ろへは抜けない（＝3Dの絵を隠さない）。 */
  html.is-3d [data-scene="3"]::after,
  html.is-3d [data-scene="4"]::after,
  html.is-3d [data-scene="5"]::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 40%;
    /* 濃さは画素で決めた。月の最も明るい部分の上でも文字が沈まない下限を実測して詰めてある
       （実測：0.78止まりだと「制作実績をすべて見る」の背後で最悪 3.54＝AA割れ）。 */
    background: linear-gradient(180deg,
      rgba(6, 12, 21, 0) 0%, rgba(6, 12, 21, 0.5) 46%, rgba(6, 12, 21, 0.9) 100%);
    pointer-events: none;
    z-index: -1;
  }
}


/* ============================================================
   19. スマホのスクロールスナップ「1フリック＝1メッセージ」（2026-07-30）
   ------------------------------------------------------------
   カイさんの「スクロールしたときに違和感があって、スライドをきちんと
   読むことができない」への物理対策。
   iOSの慣性の実数式（減速率0.998＝速度×約499pxが惰性で進む）から、
   フリック1回は約650〜2350px進む。1メッセージの割り当ては約460pxなので、
   素のままだと1フリックで1.5〜5枚が必ず飛ぶ＝読めないのは算数の帰結。
   scroll-snap-stop:always は「最初の吸着点を必ず通過しない」仕様なので、
   どんなに速くフリックしても次の1枚で必ず止まる。指の動きは1:1のまま
   ＝スクロールジャックではない（NN/gの批判に当たらない）。

   【デスクトップには絶対に広げない】Lenis とスナップの併用は既知の
   未解決バグがある（Lenis issue #389：方向によってスナップが効かない）。
   スナップは「Lenisを作らないタッチ端末」だけに閉じる（main.jsと対）。
   ============================================================ */
.snap-mark { display: none; }

@media (prefers-reduced-motion: no-preference) and (pointer: coarse) and (max-width: 768px) {
  html.is-3d {
    scroll-snap-type: y mandatory;
  }
  html.is-3d .snap-mark {
    display: block;
    position: absolute;
    left: 0;
    width: 1px;
    height: 1px;
    scroll-snap-align: start;
    scroll-snap-stop: always;
  }
  /* フッターにも吸着点を与える。無いと mandatory が最後の目印（0.84）へ
     引き戻し続け、フッターへ到達できなくなる（MDNが警告する取り残しの型） */
  html.is-3d .site-footer {
    scroll-snap-align: start;
  }
}


/* ============================================================
   20. 実機の日本語折り返し対策（2026-07-30・カイさん実機指摘）
   ------------------------------------------------------------
   症状①「その夢、聞かせてくださ／い。」という不自然な位置で改行される。
   　→ 改行処理（menu.js）が句読点保護のために「い。」だけを一塊にした結果。
   　　 タイトルは .finale__phrase の2つの塊で持ち、折り返しは読点の後だけに固定する。
   症状② 説明文が枠から右にはみ出す。
   　→ 句読点保護の塊（data-ja-nowrap）が右端ギリギリ（実測 370px中369px）にあり、
   　　 実機のヒラギノは検証環境の游ゴシックより文字幅が広いため、その塊が溢れる。
   　　 狭い画面では「句読点の行頭回避」より「はみ出さない」を優先し、塊を解除する。
   　　 文節単位の自然な改行は BudouX が引き続き担うので、読みにくくはならない。
   ============================================================ */
.finale__phrase { display: inline-block; white-space: nowrap; }

@media (max-width: 768px) {
  /* インラインの style="white-space:nowrap" に勝つには !important が必要 */
  html.is-3d .scene3d [data-ja-nowrap] { white-space: normal !important; }
  /* 万一の長い英単語・URL でも溢れない保険 */
  html.is-3d .scene3d p,
  html.is-3d .scene3d h1,
  html.is-3d .scene3d h2,
  html.is-3d .scene3d h3 { overflow-wrap: anywhere; }
}


/* ============================================================
   21. 改行ハウススタイルv2の適用（2026-08-13・カイさん指摘）
   ------------------------------------------------------------
   正典：.claude/skills/homepage-creation/references/japanese-line-break-rules.md
   「1文1行が基本（句点の後は改行）」を構造で保証する。
   リード文の各文を .yd-line（block）で持つ＝どの画面幅でも文の途中で行が終わらない。
   文が画面幅に収まらないときだけ、文の内側で読点・文節（BudouX）で折れる。 */
.yd-line { display: block; }
