/* ============================================================================
   shell.css — ミソラソラ 共通シェル（単一情報源 / SoT）
   v0.23 タスク② ／ 2026-08-10
   対象: index.html（歌集）／ stamper.html（刻印）／ giita.html（追憶）

   構成
     §1  デザイントークン
     §2  刻印互換エイリアス
     §3  ShellHeader 一式
     §4  安全網（ヘッダを構造的に溢れさせない）
     §5  圧縮ラダー（意図した見た目）
     §6  蝶紋章（.bfly-*）
     §7  ボトムタブ ＋ 刻印のオーバーフロー（v0.23 P1-c）
     §8  リクエストコピーの短冊（v0.23.1・歌集のみ）

   ── セクションを幅に乗せる 2 つの書き方（v0.23 P1 / R-1）─────────────
     背景も罫線も持たない箱   → width: var(--w-container); margin-inline: auto;
     背景・罫線を持つ「帯」   → 要素は全幅のまま
                                padding-inline: calc((100% - var(--w-container)) / 2);
     後者は「背景は全幅・中身はコンテナ」（設計稿 §01）を内包ラッパー無しで満たす。
     幅を絞ると罫線が途中で切れるので、帯にはこちらを使うこと。

   読み込み位置
     各 HTML の <head> で Google Fonts の <link> 直後・インライン <style> の直前。
     ⚠ インライン <style> は shell.css より後に来るので、同一詳細度ならページ側が勝つ。
       移行時に各ページの重複定義を消し漏らすと、その画面だけ本ファイルの規則が
       黙って無効化される。移行後は getComputedStyle で「shell.css の値が出ているか」を
       3画面 × 各ブレークポイントで確認すること。

   ── 設計原則（このプロジェクトが2度同じ結論に達したもの）─────────────
     「手順を正しく踏む」より「間違えても壊れない構造」を作る。
       ・L4 防護: 再ロック対象を手で列挙 → 列挙漏れで2か月半 穴が開いた
                  → find 全件走査にして構造的に漏れない形へ（misorasora-lock）
       ・本ファイル: ブレークポイントを正しく選ぶ → 数字を外すと溢れる
                  → §4 の flex-shrink 配分で「外しても溢れない」形へ
     §5 のラダーは「意図した見た目」を作るためのもので、破綻を防いでいるのは §4。
     ラダーの数字が将来ズレても（書体フォールバック・文言変更・タブ追加）、
     §4 がある限りタブとテーマトグルは画面外に出ない。
   ============================================================================ */


/* ============================================================================
   §1  デザイントークン
   出典: index.html / giita.html の :root（両者は完全に同一であることを diff で確認済み）
   ⚠ 値は変更しないこと。②の目的は「1箇所に集める」であって「配色を変える」ではない
   ============================================================================ */
:root,
[data-theme="silence"] {
  --color-bg:           #F7F8FA;
  --color-bg-paper:     #FFFFFF;
  --color-bg-mist:      linear-gradient(180deg, #FAFCFD 0%, #F0F4F8 100%);
  --color-bg-active:    #F0F6FA;
  --color-bg-soft:      #FBFCFD;
  --color-bg-input:     #FCFDFE;

  --color-ink:          #0E1620;
  --color-ink-soft:     #3A4654;
  --color-ink-muted:    #7B8794;
  --color-ink-subtle:   #A8B2BE;

  --color-line:         #DCE3EB;
  --color-line-soft:    #E8EDF2;

  --color-accent:       #6C9BD2;
  --color-accent-deep:  #4A7AB8;
  --color-accent-light: #D4E4ED;
  --color-accent-tint:  #A8C8DC;

  --color-rec:          #E55555;
  --color-on-dark:      #FFFFFF;
}

[data-theme="library"] {
  --color-bg:           #080D14;
  --color-bg-paper:     #16202D;
  --color-bg-mist:      linear-gradient(180deg, #0E1620 0%, #1A2536 100%);
  --color-bg-active:    rgba(108, 155, 210, 0.10);
  --color-bg-soft:      #131D2A;
  --color-bg-input:     #131D2A;

  --color-ink:          #E8EEF4;
  --color-ink-soft:     #B8C5D2;
  --color-ink-muted:    #7B8A9A;
  --color-ink-subtle:   #56657A;

  --color-line:         #2A3648;
  --color-line-soft:    #1F2A3A;

  --color-accent:       #6C9BD2;
  --color-accent-deep:  #A0BFE0;
  --color-accent-light: #3D5670;
  --color-accent-tint:  #5A8FBC;
}

:root {
  --font-serif: 'Noto Serif JP', 'Hiragino Mincho Pro', serif;
  --font-sans:  'Inter', 'Noto Sans JP', sans-serif;
  --font-mono:  'JetBrains Mono', ui-monospace, monospace;

  /* --------------------------------------------------------------------------
     全画面共通のコンテナ基準線（layout_orders_v023.md §01 / v0.23 P1・2026-08-11）

     v0.23 ① の --shell-max: 1720px / --shell-inner: 1640px を置き換えたもの。
     ⚠ 別名で残さないこと。残すと次のセッションが必ず両方を使い、基準線がまた2本になる。

     旧2本立ての理由は「padding 込みの箱」と「padding の内側」を区別する必要が
     あったから。--w-container は padding を使わずコンテンツ幅そのものを決めるので
     1本で足りる。使う側は width: var(--w-container); margin-inline: auto; だけ書き、
     左右 padding は書かない（書くと基準線がその分だけ内側にズレる）。

     ヘッダの背景・罫線は全幅のまま。中身だけがこの幅に乗る（設計稿 §01 の方針）。
     -------------------------------------------------------------------------- */
  --w-gutter:    48px;
  --w-container: min(1680px, calc(100% - 2 * var(--w-gutter)));

  --grid-gap:    20px;
  /* J-1 決定（2026-08-11・Design 姉さん）: 260px 案は 1920px 以上で 6列263px となり
     正準値（1440px キャンバスでの 328px）の 80% まで痩せる。長い曲名の折り返しが
     2行→3行になりカード高が不揃いになるため 280px 据え置き。
     「859件の密度を緩める」狙いは --grid-gap 16→20px の方が担っている。
     260/280 が分岐するのは vw ≧ 1756px のみ（6×260+5×20=1660 ≦ コンテナ）。
     1920px で 6列が欲しくなったら動かすレバーは --card-min ではなく上の 1680px。 */
  --card-min:    280px;

  /* モバイル基盤（layout_orders_v023.md §02）
     ⚠ --bp-* は参照用の記録。@media の条件式に var() は使えない（CSS の仕様）。
       ブレークポイントを動かすときは数値の直書きを grep して全部直すこと。 */
  --bp-mobile:   639px;
  --bp-tablet:   1023px;
  --tap-min:     44px;
  --h-bottom-tabs: 56px;
  --h-mini-player: 56px;
}

/* --------------------------------------------------------------------------
   §1-b  ガター段（コンテナと画面端の余白）

   横方向の余白を --w-gutter 1本に集約する。以前は
     ヘッダ  = .shell-header-inner の padding（40 / 20 / 12px・§3 と §5）
     本文    = 各セクションの padding（40px・index.html）
   と2系統あり、960px 未満では両者が食い違っていた（ヘッダ20 / 本文40）。
   これが「基準線が2本」の狭い画面側の実体。

   段の値は §5 の圧縮ラダーが実績として持っていた数字を踏襲している：
     ≥1200  48px（設計稿 §01 の指定値）
     ≤1199  40px（移行前の実値。下記の実測理由により狭い帯では戻す）
     ≤959   20px（§5 段2 が使っていた値）
     ≤767   14px（設計稿 §02 の --w-page-pad）

   ⚠ ≤1199 で 40px に戻す理由（2026-08-11 実測）:
     全帯 48px にすると左右で 16px 取られ、§5 段1 の余裕が減る。
     刻印 @960px（段1 の最狭ケース）で .sh-spacer が 37.9px → 21.9px に縮んだ。
     溢れてはいないが、§5 が「Google Fonts が落ちて字幅が変わると 13〜19px は消えうる」
     と書いている帯で薄いマージンを更に削るのは割に合わない。
     設計稿の 48px 指定と J-1 の列数表（1440/1680/1920/2560）はいずれも 1200px 以上なので、
     この段を入れても設計値は 1つも変わらない。

   ⚠ §5 はヘッダが溢れないための「圧縮」担当。ここは全画面の「余白」担当で役割が違う。
     §5 の閾値に合わせてあるのは実績のある数字を流用しているだけで、連動はしていない。
   -------------------------------------------------------------------------- */
@media (max-width: 1199px) { :root { --w-gutter: 40px; } }
@media (max-width:  959px) { :root { --w-gutter: 20px; } }
@media (max-width:  767px) { :root { --w-gutter: 14px; } }


/* ============================================================================
   §2  刻印互換エイリアス
   短名は刻印互換のエイリアス。新規コードでは --color-* / --font-* を使う。

   経緯: stamper.html は本文 CSS が独自の短い名前を使っており、参照は 272 箇所。
         D1 で全面リネーム(b)ではなくエイリアス方式(a)を採用した。
         「値が1箇所」であれば単一情報源の目的は達成される。名前の統一は v0.3 の課題。
   ============================================================================ */
:root {
  /* --bg は移行前、刻印だけ silence で #F2F4F7 を持っていた（歌集/追憶は #F7F8FA）。
     handoff の tokens.css:13 / tokens.ts:18 とも正準値は #F7F8FA なので、刻印側の drift と判断し
     エイリアスに統一した。②における唯一の意図的な色変更（ΔE 1〜2 程度）。
     library モードは移行前から両者 #080D14 で一致していたため上書き不要。 */
  --bg:          var(--color-bg);

  --paper:       var(--color-bg-paper);
  --paper-soft:  var(--color-bg-soft);
  --line:        var(--color-line);
  --line-soft:   var(--color-line-soft);
  --ink:         var(--color-ink);
  --ink-soft:    var(--color-ink-soft);
  --ink-muted:   var(--color-ink-muted);
  --ink-subtle:  var(--color-ink-subtle);
  --accent:      var(--color-accent);
  --accent-deep: var(--color-accent-deep);
  --accent-lt:   var(--color-accent-light);
  --danger:      var(--color-rec);

  --serif: var(--font-serif);
  --sans:  var(--font-sans);
  --mono:  var(--font-mono);

  /* 刻印のみが使うモーション定数（--color-* 側に対応物なし） */
  --dur:  150ms;
  --ease: cubic-bezier(0.4,0,0.2,1);
}

/* --sh-* は「ヘッダ専用に別名を付けただけ」で値は --color-* と同一だったため、
   本ファイルには持ち込まない。stamper.html 側の参照を --color-* に置換する（25箇所）。 */


/* ============================================================================
   §3  ShellHeader 一式
   出典: index.html L94-215（= giita.html と同一）。値は一切変更していない。
   クラス名の正: .tab-pill / .tip / .sh-logo-name / .sh-logo-copy / .sh-ver /
                 .theme-toggle / .theme-btn / .theme-dot
   （刻印の .sh-tab / .sh-tip / .sh-series / .sh-copy / .sh-version / .sh-toggle /
     .sh-tbtn / .sh-dot は markup 側を上記へ改名する）
   ============================================================================ */
.shell-header {
  background: var(--color-bg-paper);
  border-bottom: 1px solid var(--color-line);
}
/* v0.23 P1: 左右 padding 40px を --w-container に置き換えた（設計稿 §01）。
   背景と罫線は .shell-header 側にあるので全幅のまま残る。
   ⚠ 左右 padding をここに戻さないこと。戻すとヘッダだけ本文より内側にズレる。
   ⚠ §4 の安全網（flex-shrink 配分）はこの要素に乗っている。width と padding 以外は触らない。 */
.shell-header-inner {
  width: var(--w-container); margin-inline: auto;
  padding: 12px 0;
  display: flex; align-items: center; gap: 28px;
}

/* ロゴ + コピー (gap:12, align baseline) */
.sh-logo {
  display: flex; align-items: baseline; gap: 12px;
}

/* 蝶だけ揃え方を変える（2026-08-12）。文字同士の baseline 揃えはそのまま。

   ── 実測（歌集 1440px・22px の蝶）─────────────────────────
   baseline 揃えでは、中身が空のインラインブロックはベースラインが下マージン端になる。
   実際に蝶の箱の下端 40.97px と文字のベースライン 41.14px が一致していた。
   結果、蝶は字形の視覚中心より 5.85px 高い位置に浮いていた。

   浮きは 2 層に分かれる:
     ① baseline 揃えそのもの        −4.17px  → align-self: center で解消する
     ② 行ボックスの中心 ≠ 字形の中心   −1.50px  → **解消しない。意図して残す**
   ②は行ボックスがディセンダ分だけ字形より下に広いために生じる。
   検索欄（親が既に align-items:center）でも同じ −1.50px が出ており、
   ②だけを取り出した実測値になっている。

   ── ⚠ ②を translateY で潰さないこと（2026-08-12 最終決定・Design 姉さん）───
   蝶は飛んでいるもので、地に座らせるものではない。
   v0.22 で bottom-up を選んだときの「下が地・上が空・その間に蝶が舞う」と揃える。
   ベースラインに沈めるより、文字の上をわずかに舞っているほうがミソラソラ。
   **箱中心 −1.50px の「わずかに上」が、この紋章の正しい居場所。**

   検討の経緯（同じ道を二度たどらないために）:
     translateY(2.5px) → 尾が文字下端より 1.76px 垂れて「沈んで見える」
     translateY(1.5px) → 文字のインク外形中心に一致するが下がりすぎ
     translateY(1px)   → 外形中心と重心の中間。数値としては最も均衡するが、
                         そもそも数値のゼロを目標にしたのが誤りだった
   → **値を持たせない。align-self: center だけ。**
     規則が値を持たないので、書体やサイズが変わっても崩れない。
     3箇所（ヘッダ / 歌集の検索欄 / 刻印の配信選択）すべて同じ規則で揃う。

   ⚠ α重み付き重心（箱中心より 7.65% 上）に合わせないこと。
     決定稿の蝶は (16,16) に紙色の光抜けを持ち、4枚の翅が収束するその点が
     知覚上のアンカーになっている。アンカーは重心ではなく箱の中心。
     重心に合わせると 3.18px 必要になり、尾が文字下端より 2.5px 垂れる。
     1.5px なら尾のはみ出しは +0.76px で、これは「下翅の延長として一本の流れ」の
     末端がわずかに越える量として意図的に残している（Design 姉さん裁定）。

   ⚠ align-self: center は3画面の差も吸収する。baseline のままだと刻印だけ
     −6.43px（body の line-height:1.5 を副題が継承し行ボックスが 28.50px になる）。
     center にすると3画面とも −3.18px に揃い、ページ別の値が要らなくなる。 */
.sh-logo .bfly { align-self: center; }
.sh-logo-name {
  font-family: var(--font-serif); font-size: 19px;
  color: var(--color-ink); font-weight: 500;
  letter-spacing: 0.08em;
}
.sh-logo-copy {
  font-family: var(--font-serif); font-size: 12px;
  color: var(--color-ink-muted);
  letter-spacing: 0.25em;
}

/* 縦罫線 (alignSelf: stretch で自然伸縮) */
.sh-sep {
  width: 1px; align-self: stretch;
  background: var(--color-line-soft);
}

/* タブ群 (gap:0) */
.sh-tabs { display: flex; align-items: center; gap: 0; }

.tab-pill {
  position: relative;
  padding: 8px 18px;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  /* ⚠ 移行時に必要と判明。歌集/追憶は BASE の a{text-decoration:none} に依存していたが
     刻印は .sh-tab 側に持っていたため、共有化でタブに下線が出た。
     ページ側の base に依存せず、共有部品として自足させる */
  text-decoration: none;
  /* 1.455 = Noto Serif JP の line-height:normal 実測値。
     ページ側 body からの継承をやめ、3画面でヘッダ高を揃えるために固定している。
     **丸めるとヘッダ高が動く**（1.5 にすると 66px → 67px）。
     未指定時の実測: 歌集/追憶 body 16px/normal → タブ 41.33px・ヘッダ 66px ／
                     刻印 body 13px/1.5      → タブ 42px   ・ヘッダ 67px
     ②で潰したはずの「ページ側 base への依存」が、高さの経路にだけ残っていた。
     ⚠ なお 66px は設計値ではない。COMPONENTS.md / handoff README はどちらも「≒48px」で、
       実装が累積で太った値に揃えている。是正は v0.3 の棚卸し候補（③ で変える話ではない）。 */
  line-height: 1.455;
  font-family: var(--font-serif); font-size: 16px;
  color: var(--color-ink-muted);
  letter-spacing: 0.2em;
  white-space: nowrap;
  font-weight: 400;
}
.tab-pill.active {
  border-bottom-color: var(--color-ink);
  color: var(--color-ink);
  font-weight: 500;
}
.tab-pill .tip {
  display: none;
  position: absolute; left: 50%; top: 100%;
  transform: translateX(-50%);
  margin-top: 6px; padding: 5px 10px;
  background: var(--color-ink); color: var(--color-bg-paper);
  font-family: var(--font-serif); font-size: 10px;
  letter-spacing: 0.1em; white-space: nowrap;
  z-index: 10; pointer-events: none;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.tab-pill .tip::before {
  content: ''; position: absolute;
  left: 50%; top: -4px;
  transform: translateX(-50%) rotate(45deg);
  width: 8px; height: 8px;
  background: var(--color-ink);
}
.tab-pill:hover .tip { display: block; }

.sh-spacer { flex: 1; }

/* ENTRIES / STREAMS / PLAYS + 数字
   ⚠ ラベルの語は画面ごとに違って正しい（意味が違う）。揃えるのは見た目だけ */
.sh-entries {
  display: flex; align-items: baseline; gap: 8px;
}
.sh-entries-label {
  font-family: var(--font-mono); font-size: 8px;
  color: var(--color-ink-subtle);
  letter-spacing: 0.25em;
}
.sh-entries-num {
  font-family: var(--font-serif); font-size: 16px;
  color: var(--color-ink); font-weight: 500;
  letter-spacing: 0.05em;
  font-variant-numeric: tabular-nums;   /* v0.21 ノート #7。3桁区切りは入れない */
}

/* バージョン（値は ③ 完了時に v α0.23 で3画面統一する。②では器だけ揃える） */
.sh-ver {
  font-family: var(--font-mono); font-size: 9px;
  color: var(--color-ink-subtle);
  letter-spacing: 0.2em;
}

/* ThemeToggle */
.theme-toggle {
  display: flex;
  border: 1px solid var(--color-line);
  background: var(--color-bg-paper);
}
.theme-btn {
  padding: 4px 10px;
  background: transparent; border: none;
  color: var(--color-ink-muted);
  font-family: var(--font-serif); font-size: 11px;
  letter-spacing: 0.15em;
  display: flex; align-items: center; gap: 5px;
  cursor: pointer;
}
.theme-btn.active {
  background: var(--color-ink);
  color: var(--color-bg-paper);
}
.theme-dot {
  width: 7px; height: 7px; border-radius: 50%;
  display: inline-block;
  border: 1px solid var(--color-line);
}
.theme-btn.active .theme-dot { border-color: rgba(255,255,255,0.4); }
.theme-dot-silence { background: #FFFFFF; }
.theme-dot-library { background: #16202D; }


/* ============================================================================
   §4  安全網 — ヘッダを構造的に溢れさせない
   ============================================================================
   これは「見た目を整える」規則ではなく「破綻しない」ことを保証する規則。
   §5 のラダーが将来ズレても（書体フォールバック・文言変更・タブ追加）、
   ここが効いている限り タブとテーマトグルは画面外に出ない。

   ⚠ overflow-x: hidden で解決しないこと。
     あれは溢れを隠すだけで収めていない。追憶（body に overflow-x:hidden あり）で
     実際に起きていたのは「横スクロールが出ないかわりにテーマトグルの蒼ボタンが
     幅45px中13pxしか見えない」状態だった。歌集（overflow 指定なし）は横スクロールが
     出るぶん気づける。隠す側が実害が大きい。

   実測（歌集 @1024px・2026-08-10）:
     適用前   doc幅 1079 / 横スクロールあり / トグル 70px はみ出し
     適用後   doc幅 1009 / 横スクロールなし / トグル 0px  / タブ 298px 不変
              （縮むのは .sh-logo-copy だけ 207 → 133px）
   ---------------------------------------------------------------------------- */
.shell-header-inner { min-width: 0; }

/* 縮んでよいのはキャッチコピーだけ。ロゴ名と蝶は縮ませない
   （min-width:0 を .sh-logo に与えると「ミソラソラ」自体が 103→74px に潰れる。実測済み） */
.sh-logo      { flex-shrink: 1; min-width: 0; }
.sh-logo-name { flex-shrink: 0; }
.sh-logo .bfly, .sh-logo svg { flex-shrink: 0; }

/* white-space:nowrap が無いと2行に折り返し、ヘッダ高が 66→79px に伸びる（実測済み）。
   v0.21「刻印の縦書き発狂」と同じ地雷。省略記号で1行に留めること */
.sh-logo-copy {
  flex-shrink: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* 操作要素・固定長要素は最後まで守る */
.sh-tabs, .sh-entries, .sh-ver, .theme-toggle { flex-shrink: 0; }


/* ============================================================================
   §5  圧縮ラダー — 意図した見た目
   ============================================================================
   ブレークポイントは v0.21 ノートの想定（1440 / 1200 / 960 / 767）を流用。
   落とす順序は「可変長のブランド要素から。固定長の操作要素は最後まで守る」。

   ヘッダが必要とする幅の実測（2026-08-10 / -live）:

     画面     素通し   段1(コピー無)  段2
     歌集     1120      901          689
     刻印     1166      932          682
     追憶     1098      923          703

     帯              適用      必要幅(最大)   余裕      スクロールバー込みの余裕
     w >= 1200       素通し    1166(刻印)     34px      19px
     960 - 1199      段1       932(刻印)      28px      13px   (w=960)
     768 - 959       段2       703(追憶)      65px      50px   (w=768)
     w <= 767        段3       — （2段組みに畳む）

   ⚠ 右欄について。メディアクエリが判定する幅と、実際に使える内容幅は
     縦スクロールバーの分だけズレる（検証環境では判定幅=960 に対し内容幅=945 だった）。
     余裕はこの分を引いた右欄で読むこと。実質 13〜19px しかない。

   ⚠ Google Fonts が落ちてフォールバック書体になると字幅が変わり、13〜19px は消えうる。
     そのときは §4 がコピーを詰めて受け止める。
     ラダー単独では守れていない、という前提で読むこと。

   ⚠ 1279px ではなく 1199px を採る理由:
     境界を上げるほど「コピーが消える帯」が広がる。1279 にすると 1200〜1279px の
     帯でコピーが消え、1366幅の画面で最大化していないウィンドウや OS スケーリングが
     効いた環境がここに落ちる。境界は低いほどブランド表現が生き残る。
     （1366px そのものは 1199 でも 1279 でも素通し帯に入る。消えるのは 1200〜1279 の帯）

   ⚠ 版数を v α0.23 に統一すると歌集のヘッダが約21px 太る（v1.2=29px → 約50px）。
     1200 の壁は割らないが、③ 完了時に3画面の閾値を測り直すこと。
   ---------------------------------------------------------------------------- */

/* ── 段1: キャッチコピーを落とす（可変長・非操作要素から先に） ── */
@media (max-width: 1199px) {
  .sh-logo-copy { display: none; }
}

/* ── 段2: 版数とカウンタを落とし、余白を詰める ──
   .sh-entries-label だけ隠すと帯の中で「590」だけが浮いて意味が読めないので
   .sh-entries ごと落とす */
@media (max-width: 959px) {
  /* 左右 padding 20px は §1-b の --w-gutter: 20px へ移した（v0.23 P1）。
     ここに書くと本文セクションと食い違う。詰めるのは gap だけ */
  .shell-header-inner { gap: 16px; }
  .sh-ver     { display: none; }
  .sh-entries { display: none; }
}

/* ── 段3: モバイル。2段組みに畳む ──
   giita.html / stamper.html が個別に持っていた ≤767 のヘッダ規則を統合したもの */
@media (max-width: 767px) {
  .shell-header-inner {
    flex-wrap: wrap;
    /* 左右 12px は §1-b の --w-gutter: 14px へ移した（v0.23 P1）。縦だけ詰める */
    padding: 6px 0;
    gap: 6px;
  }
  .sh-logo      { flex-basis: auto; gap: 8px; }
  .sh-logo-name { font-size: 15px; }
  .sh-logo .bfly, .sh-logo svg { width: 18px; height: 18px; }
  .sh-sep, .sh-spacer { display: none; }

  .tab-pill      { padding: 4px 10px; font-size: 13px; }
  .tab-pill .tip { display: none; }

  /* ★ §4 の flex-shrink:0 をここで解除する。
     タブ群が 205px のまま縮まないと、狭い端末で溢れが復活する
     （タブレット帯を塞ぐために入れた安全網が、スマホ帯で溢れを作る反転）。
     flex-wrap と併せて、極端に狭い端末ではタブ自体が2段になって収まる。
     実測（モバイル圧縮適用時・追憶）: ロゴ107 / タブ群205 / トグル92
       1段に並べると 440px 必要 → 390px には入らない
       2段目（タブ+トグル）は 327px → 390px にも 360px にも入る */
  .sh-tabs { flex-shrink: 1; min-width: 0; flex-wrap: wrap; }

  .theme-toggle { margin-left: auto; }
  .theme-btn    { padding: 3px 8px; font-size: 10px; }
}


/* ============================================================================
   §6  Butterfly Mark（蝶紋章）
   出典: design_handoff_misorasora/butterfly_mark_spec.md 決定稿 2026-05-10
   v0.23 タスク③ ／ 2026-08-10
   ============================================================================
   ⚠ 下の data-URI は決定稿の SVG から**機械変換**して生成した（手写しではない）。
     生成時に往復デコードして d 属性・opacity が決定稿と一字一句一致することを確認済み。
     編集するときも手で書き換えず、決定稿を直してから再生成すること。

   決定稿 β の要点（実装は長く暫定 SVG のまま止まっていた）:
     viewBox 0 0 32 32 ／ 涙形の尾あり ／ **胴の線は廃止**（「虫」ではなく「紋」に）
     中心の光抜け radial gradient ／ 透明度 .88 / .62 / .48 / .32（この組合せは固定）

   data-URI 方式を採る理由:
     1. 10箇所すべてが <span class="bfly bfly-std bfly-22"> の1行になる
     2. **gradient の id 衝突が構造的に起きない**（id が画像に閉じる）。
        決定稿の「主要 ID をインスタンスごとにユニーク化」という宿題が不要になる
     3. 既存の animation（sl-bfly-idle / sl-bfly-play / hover）は要素側に効くので生きる

   ⚠ バリアントは2つ要る（D2-a）。実装の10箇所は同一ではなかった:
     蒼 (--color-accent 相当) … ヘッダ×3・検索input・QUEUE・SETLIST
     **白** … 動画中央 BFLY_PLAYER / サムネ代替 BFLY_HIST / 刻印の動画プレースホルダ
     1種に統一すると暗い動画・サムネ上の蝶が蒼になって沈むため、.bfly-inv を用意する。
   ---------------------------------------------------------------------------- */
.bfly {
  display: inline-block;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  flex-shrink: 0;
}

/* 標準版 β（蒼 #6C9BD2 = 全テーマ共通の不変の星） */
.bfly-std  { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='none'%3E%3Cdefs%3E%3CradialGradient id='c' cx='50%25' cy='50%25' r='35%25'%3E%3Cstop offset='0%25' stop-color='%23FAFCFD' stop-opacity='.55'/%3E%3Cstop offset='100%25' stop-color='%23FAFCFD' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cpath d='M16 16 C 16 8, 8 4, 4 7 C 1 11, 4 17, 16 16 Z' fill='%236C9BD2' opacity='.88'/%3E%3Cpath d='M16 16 C 16 8, 24 4, 28 7 C 31 11, 28 17, 16 16 Z' fill='%236C9BD2' opacity='.62'/%3E%3Cpath d='M16 16 C 16 22, 12 25, 7 23.5 C 6 26, 5.5 28.4, 6.5 28.9 C 8 28.7, 9 26.7, 9 25.5 C 5 22.5, 8 18.5, 16 16 Z' fill='%236C9BD2' opacity='.48'/%3E%3Cpath d='M16 16 C 16 22, 20 25, 25 23.5 C 26 26, 26.5 28.4, 25.5 28.9 C 24 28.7, 23 26.7, 23 25.5 C 27 22.5, 24 18.5, 16 16 Z' fill='%236C9BD2' opacity='.32'/%3E%3Ccircle cx='16' cy='16' r='6' fill='url(%23c)'/%3E%3C/svg%3E"); }

/* 反転版 β（白）— 暗い動画・サムネの上で使う */
.bfly-inv  { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='none'%3E%3Cdefs%3E%3CradialGradient id='c' cx='50%25' cy='50%25' r='35%25'%3E%3Cstop offset='0%25' stop-color='%23FAFCFD' stop-opacity='.55'/%3E%3Cstop offset='100%25' stop-color='%23FAFCFD' stop-opacity='0'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cpath d='M16 16 C 16 8, 8 4, 4 7 C 1 11, 4 17, 16 16 Z' fill='%23FFFFFF' opacity='.88'/%3E%3Cpath d='M16 16 C 16 8, 24 4, 28 7 C 31 11, 28 17, 16 16 Z' fill='%23FFFFFF' opacity='.62'/%3E%3Cpath d='M16 16 C 16 22, 12 25, 7 23.5 C 6 26, 5.5 28.4, 6.5 28.9 C 8 28.7, 9 26.7, 9 25.5 C 5 22.5, 8 18.5, 16 16 Z' fill='%23FFFFFF' opacity='.48'/%3E%3Cpath d='M16 16 C 16 22, 20 25, 25 23.5 C 26 26, 26.5 28.4, 25.5 28.9 C 24 28.7, 23 26.7, 23 25.5 C 27 22.5, 24 18.5, 16 16 Z' fill='%23FFFFFF' opacity='.32'/%3E%3Ccircle cx='16' cy='16' r='6' fill='url(%23c)'/%3E%3C/svg%3E"); }

/* 特別演出版 γ（コバルト構造色）— 決定稿の制限により **64px 以上限定** */
.bfly-omen { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32' fill='none'%3E%3Cdefs%3E%3CradialGradient id='g' cx='50%25' cy='50%25' r='65%25'%3E%3Cstop offset='0%25' stop-color='%239DCFF7' stop-opacity='1'/%3E%3Cstop offset='40%25' stop-color='%233D6FC0' stop-opacity='1'/%3E%3Cstop offset='100%25' stop-color='%230E1620' stop-opacity='.95'/%3E%3C/radialGradient%3E%3C/defs%3E%3Cpath d='M16 16 C 16 8, 8 4, 4 7 C 1 11, 4 17, 16 16 Z' fill='url(%23g)'/%3E%3Cpath d='M16 16 C 16 8, 24 4, 28 7 C 31 11, 28 17, 16 16 Z' fill='url(%23g)'/%3E%3Cpath d='M16 16 C 16 22, 12 25, 7 23.5 C 6 26, 5.5 28.4, 6.5 28.9 C 8 28.7, 9 26.7, 9 25.5 C 5 22.5, 8 18.5, 16 16 Z' fill='url(%23g)'/%3E%3Cpath d='M16 16 C 16 22, 20 25, 25 23.5 C 26 26, 26.5 28.4, 25.5 28.9 C 24 28.7, 23 26.7, 23 25.5 C 27 22.5, 24 18.5, 16 16 Z' fill='url(%23g)'/%3E%3C/svg%3E"); }

/* サイズ（決定稿の推奨運用サイズ + 実装で使われている実寸） */
.bfly-10 { width:10px; height:10px }
.bfly-13 { width:13px; height:13px }
.bfly-14 { width:14px; height:14px }
.bfly-16 { width:16px; height:16px }
.bfly-18 { width:18px; height:18px }
.bfly-20 { width:20px; height:20px }
.bfly-22 { width:22px; height:22px }
.bfly-64 { width:64px; height:64px }

/* ── 三閃（吉兆スパーク）──
   ⚠ nth-child ではなく **nth-of-type** を使う。決定稿の草案は nth-child だったが、
     .bfly-sparks の中に蝶の <span> も入るため子番号が1つずれ、3粒目が無効になる
     （実測: 1粒目が omenSpark2 を拾い、3粒目は animation:none で光らない）。
     nth-of-type なら <i> だけを数えるので、マークアップの並び順に依存しない。
   .bfly-omen の親に .bfly-sparks を置き、中に <i>×3。
   リズムは決定稿どおり 3.6s 単一サイクルの不等間隔（0% → 32% → 54%）＋3粒目だけ長残光。
   ⚠ γ の発火トリガー（Ulysses 初回 / 3回視聴 / 節目）は ③-b。ここでは実装しない */
.bfly-sparks { position: relative; display: inline-block; }
.bfly-sparks i { position: absolute; border-radius: 50%; opacity: 0; }
.bfly-sparks i:nth-of-type(1){ left:18.75%; top:28.1%;  width:5.6%; height:5.6%; background:#A8C8DC; animation: omenSpark1 3.6s ease-in-out infinite }
.bfly-sparks i:nth-of-type(2){ left:81.25%; top:18.75%; width:4.4%; height:4.4%; background:#9DCFF7; animation: omenSpark2 3.6s ease-in-out infinite }
.bfly-sparks i:nth-of-type(3){ left:87.5%;  top:68.75%; width:6.3%; height:6.3%; background:#A8C8DC; animation: omenSpark3 3.6s ease-in-out infinite }

@keyframes omenSpark1 {
  0%   { opacity: 0; transform: scale(.6); }
  4%   { opacity: 1; transform: scale(1); }
  20%  { opacity: 0; transform: scale(.6); }
  100% { opacity: 0; transform: scale(.6); }
}
@keyframes omenSpark2 {
  0%, 24% { opacity: 0; transform: scale(.6); }
  32%     { opacity: 1; transform: scale(1); }
  48%     { opacity: 0; transform: scale(.6); }
  100%    { opacity: 0; transform: scale(.6); }
}
@keyframes omenSpark3 {
  0%, 46% { opacity: 0; transform: scale(.6); }
  54%     { opacity: 1; transform: scale(1.1); }
  90%     { opacity: 0; transform: scale(.7); }
  100%    { opacity: 0; transform: scale(.6); }
}


/* ============================================================================
   §7  ボトムタブ（v0.23 P1-c・2026-08-11）
   出典: layout_orders_v023.md §02 ／ 橋渡し §6-3（Design 姉さん指定）

   マークアップは 3 画面それぞれに持たせる（index / stamper / giita）。
   SPA ではないので active 判定はファイル単位で静的に書く。

   z-index の層（姉さん指定・「常時側を低く、一時側を高く」）:
     ボトムタブ        40   常時表示
     ミニプレーヤー    30   P2 で追加。タブの上に積むが層は下
     モーダル / 劇場   60   ただし実測で既存は全て 200 以上（下表）なので引き上げ不要
       .gita-modal 1000 ／ .clear-dialog-backdrop 9000 ／ .post-panel 300 ／ .ac-drop 200
     オーバーフローパネル 45   タブより上・モーダルより下

   ⚠ .sh-tabs の display:none は §5 の圧縮ラダー本体（1199/959/767）とは別物。
     ラダーは触らず、639px のブロックとしてここに置いている。
     ボトムタブが存在しない状態でこれを有効にするとナビが消えるので、必ず対で扱うこと。
   ============================================================================ */
.bottom-tabs { display: none; }

/* 刻印だけが持つヘッダ右のオーバーフロー。
   モバイルで下端を主操作（曲開始）に明け渡すため、取消／編集／確定をここへ退避する。
   設計稿 §05「誤爆すると記録が飛ぶ操作を親指ゾーンに置かない」の実装。 */
.sh-overflow { display: none; position: relative; flex-shrink: 0; }
/* ⚠ 枠線を付けないこと（2026-08-11 実機で差し戻し）。
   当たり判定の 44px を枠で見せてしまうと、隣の 静寂/蒼 トグルより明らかに背が高くなって
   ヘッダから浮く。当たり判定は 44px のまま、見えるのは ⋯ のグリフだけにする。
   「見た目は小さく、当たりは 44px」＝ 設計稿 §02 の共通ルールそのもの。 */
.sh-overflow-btn {
  position: relative;
  /* 幅は 44px のまま、高さはテーマトグル（23px）に合わせる。
     ⚠ 高さも 44px にすると刻印のヘッダだけ 36px → 57px に伸び、
       §3 が3画面で揃えているヘッダ高が崩れる（実測で 21px 差）。 */
  width: var(--tap-min); height: 24px;
  display: flex; align-items: center; justify-content: center;
  background: transparent;
  border: none;
  color: var(--color-ink);
  font-size: 16px; line-height: 1;
}
/* 足りない縦 20px を疑似要素で足して当たり判定を 44px にする（設計稿 §02 の .tap 方式）。
   ⚠ 横には広げない。幅は既に 44px あるうえ、左隣のテーマトグルとは gap 6px しかなく、
     横に広げると蒼ボタンの右端のタップを奪う。伸ばすのは上下だけでよい。 */
.sh-overflow-btn::after {
  content: '';
  position: absolute; left: 0; top: 50%;
  width: 100%; height: var(--tap-min);
  transform: translateY(-50%);
}
.sh-overflow-panel {
  display: none;
  position: absolute; right: 0; top: calc(100% + 6px);
  z-index: 45;
  min-width: 210px; padding: 8px;
  background: var(--color-bg-paper);
  border: 1px solid var(--color-line);
  box-shadow: 0 6px 18px rgba(0,0,0,0.18);
}
.sh-overflow.open .sh-overflow-panel { display: block; }


@media (max-width: 639px) {
  .bottom-tabs {
    position: fixed; inset: auto 0 0 0; z-index: 40;
    display: grid; grid-template-columns: repeat(4, 1fr);
    /* iOS のホームバーに重なるとタップを取られる。safe-area は必ず入れる */
    height: calc(var(--h-bottom-tabs) + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--color-bg-paper);
    border-top: 1px solid var(--color-line);
  }
  .bt-tab {
    display: flex; align-items: center; justify-content: center;
    text-decoration: none;
    border-top: 2px solid transparent;
    font-family: var(--font-serif); font-size: 13px;
    letter-spacing: 0.12em;
    color: var(--color-ink-muted);
  }
  /* active は上辺 2px。当たり判定は 56px あるので疑似要素は要らない（姉さん指定） */
  .bt-tab.active {
    border-top-color: var(--color-accent);
    color: var(--color-ink);
    font-weight: 500;
  }

  /* これが無いとリスト最終行がタブに隠れる。
     3 画面とも ≤767px で body の height 固定を解いているので padding が効く。

     ⚠ セレクタが `body` ではなく `html body`（詳細度 0,0,2）なのは必須。
       index.html:29 と giita.html:24 に `html, body { margin:0; padding:0; }` があり、
       インライン <style> は shell.css より後に来るため、`body`（0,0,1）同士では
       あちらが勝って padding が 0 に戻る。実測で 0px になっていた（2026-08-11）。
       !important ではなく詳細度で解いているのは、ページ側が正当に上書きする道を残すため。 */
  html body { padding-bottom: calc(var(--h-bottom-tabs) + env(safe-area-inset-bottom, 0px)); }

  /* ヘッダのタブはボトムへ移設。⚠ .tab-row ではなく .sh-tabs（実装名） */
  .sh-tabs { display: none; }

  .sh-overflow { display: block; }
}


/* ============================================================================
   §8  リクエストコピーの短冊（v0.23.1 / 2026-08-11）
   出典: request_copy_orders.md（Design 姉さん・案 B「潜む短冊」）
   対象: 歌集（index.html）のみ。刻印・追憶・次第は変更なし

   ⚠ 書式は歌集で組まない。assist-core.js の AssistCore.formatLine() を呼ぶ。
     Setlista 側のパーサ制約（% < > の全角化 = sanitizeForSetlista）が
     あちらにしか無いため、自前で組むと「次第と 1 文字違わない」が崩れる。

   字形の作り分け:
     平常 / 失敗 → data-URI の短冊（線画）。色だけ差し替える
     成功       → ::before の「写」＋ 朱の枠
   ⚠ 「写」を data-URI の SVG <text> で描かないこと。
     data-URI 画像の中では Web フォント（Noto Serif JP）が効かず、
     日本語フォントを持たない端末で豆腐になる。DOM テキストなら本文と同じ書体が使える。

   ⚠ 箱は常に 17×17px。状態で幅を変えると押すたびに行が揺れる
     （設計稿 §01「文言トーストは出さない」と同じ理由）。
     短冊は viewBox 24×32 を contain で入れるので、見た目は約 12.75×17px になる。
   ============================================================================ */
.card-copy {
  appearance: none; -webkit-appearance: none;
  margin: 0; padding: 0; border: 0;
  background: transparent no-repeat center / contain;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  width: 17px; height: 17px;
  opacity: .28;                 /* 0.4 を超えると記号として数え始める（姉さん指定） */
  transition: opacity 150ms var(--ease);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 32'%3E%3Cpath d='M7 2 H17 V30 L12 27 L7 30 Z' fill='none' stroke='%236C9BD2' stroke-width='1.4'/%3E%3C/svg%3E");
}
.db-card:hover .card-copy,
.card-copy:focus-visible { opacity: 1; }

/* assist-core.js が読めないときは短冊ごと消す（index.html が html に付ける）。
   ⚠ 「必ず失敗するボタン」を残さないための規則。押せるのに毎回朱になる状態は、
     ユーザーの操作が誤りだったように読める */
.no-request-copy .card-copy { display: none; }

/* 状態表示中は常に不透明 */
.card-copy[data-state] { opacity: 1; }

/* 成功 ── 短冊を消して「写」の朱印に差し替える。箱の寸法は変えない */
.card-copy[data-state="copied"] {
  background-image: none;
  border: 1px solid var(--color-rec);
}
.card-copy::before {
  content: '写';
  display: none;
  font-family: var(--font-serif);
  font-size: 11px; line-height: 1;
  color: var(--color-rec);
}
.card-copy[data-state="copied"]::before { display: block; }

/* 失敗 ── 形は短冊のまま、色だけ朱。× は否定が強すぎる（姉さん指定） */
.card-copy[data-state="failed"] {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 32'%3E%3Cpath d='M7 2 H17 V30 L12 27 L7 30 Z' fill='none' stroke='%23E55555' stroke-width='1.4'/%3E%3C/svg%3E");
}

/* 当たり判定 44px（設計稿 §04）。
   ⚠ 横に広げると隣の歌唱数を食う。歌唱数との間隔は .card-end の gap 16px で確保している
     （17px の見た目に対し 44px は左右へ 13.5px はみ出すため、8px では最後の桁が押せない） */
.card-copy::after {
  content: ""; position: absolute;
  inset: 50% auto auto 50%;
  width: 44px; height: 44px;
  transform: translate(-50%, -50%);
}

/* 歌唱数と短冊のまとまり。.card-row2 の space-between を壊さないための箱 */
.card-end {
  display: flex; align-items: center;
  gap: 16px;
  flex-shrink: 0;
}
