/* ===================================================================
   game-social.css — ゲームのソーシャル UI（2026-09-17 に timeline.html から切り出し）

   WHY このファイルがあるか:
     タグページのフィード（public/games-by-tag.html）とタイムライン（public/timeline.html）は、
     スタンプのチップとピッカー・会話ブロック（コメント欄）・ボトムシート・
     リールの右レールとゲーム中の上のバー・インフォメーションのシートのカード・トースト、
     という**同じソーシャル UI**を出す。マークアップはどちらも timeline.js と同じ形なので、
     見た目の出典も1つにする。以前はタイムラインのページ内 <style> にだけあり、
     style.css を読まないタグページでは同じ UI が描けなかった。
     2か所にコピーすると片方だけ直す事故が必ず起きるので、コピーではなく「移動」した。

   デザイントークン（:root の --tl-*）もここが唯一の出典:
     値はすべて var(--gray-100, #F5F5F5) のように style.css のブランド変数を引き、
     そのフォールバックを内蔵している。style.css を読まないページでも同じ色・角丸・
     影で描ける。トークンを足すときもここに足す（ページ側に同名を書かない）。
     下の :root 内コメントの「この <style> は timeline ページ専用」は切り出し前の記述で、
     いまは複数ページが読む。tl-* 接頭辞の変数と旧名の別名（--bg / --ink 等）は
     style.css・deferred-modals.css と衝突しないことを確認済み（2026-09-17）。

   読み込み順（重要）:
     timeline.html では、この <link> をページ内 <style> の**直前**に置く。
     ページ内 <style> には .tl-published-card .tl-sheet-close や
     html.tl-sheet-open .tl-shell のようなページ固有の上書きが残っていて、
     同じ詳細度なら後勝ちで効く前提で書かれている。順序を入れ替えるとタイムラインの
     見た目が変わる。app-shell の SPA 遷移でも、このリンクは head に、ページ内
     <style> は body に入るので「このファイルが先」は保たれる。
     切り出しのときは、移した規則より前にあって同じ詳細度で上書きしうる残留規則を
     機械的に洗い出した。実際に当たったのは .tl-shell / .tl-sheet / .tl-published-bar の
     :focus-visible（.tl-thread-tap:focus-visible を上書きしてしまう）だけで、
     これは規則ごとこちらへ移して元の相対順序を保った。

   ルールの中のコメントは元の場所からそのまま持ってきた（寸法・色の WHY と経緯）。
   「§カード殻」「prependFreshEvents」などタイムライン固有の話も、その規則を
   直すときに必要な前提なので消していない。
   =================================================================== */

:root {
  /* --- デザイントークン（--tl-*）---------------------------------
     WHY :root に置くか（仕様上のスコープは .tl-shell）: FAB・ボトムシート・
     トースト・ライトボックスは .tl-shell の **外**（body 直下）にある。
     .tl-shell に閉じ込めると画面の半分がトークンを引けない。この <style> は
     timeline ページ専用なので、:root に置いても他ページを汚さない。 */

  /* ── 面（DreamCore ブランドの地・style.css :root と同じ値を引く）────────
     地は --gray-100 #F5F5F5。create / notifications / mypage など他の面と
     同じ地なので、SPA でタブを渡り歩いても紙の色が変わらない。
     中性グレー（#F7F7F8）とクリーム（#FDFBF7）はどちらも「この面だけの色」
     だったので廃止（2026-09-04 夕・founder「DreamCore のポップなトンマナを守って」）。
     カードは純白 + 影。沈む面（チップ・入力欄・押された跡）は白の上に置く
     --gray-100 なので、地と同じ色でも「白の中の窪み」として読める。 */
  --tl-bg: var(--gray-100, #F5F5F5);       /* ページ地（アプリ共通） */
  --tl-surface: var(--white, #FFFFFF);     /* カード面 */
  --tl-surface-sunk: var(--gray-100, #F5F5F5);  /* 白の上の窪み（チップ・入力欄） */
  /* 罫線は1段だけ（2026-09-04 夜・founder「カラーリングが優しくなって DreamCore の
     コントラストがぱきっとした感じがなくなってますね」）。#EDEDED は白の上で
     ほとんど見えず、「線を引いたのに線が無い」状態だった。線を引くなら見える線を
     引く ＝ --gray-200 の1本に畳む。--tl-hairline-strong は同じ値の別名として
     残す（このファイルの既存ルールの参照を全部書き換えないため。意味は
     「面と面の境」で、いまは太さも色も同じ）。 */
  --tl-hairline: var(--gray-200, #E5E5E5);         /* 面の中の区切り（反応の帯・スレッド境界） */
  --tl-hairline-strong: var(--gray-200, #E5E5E5);  /* 面と面の境（ヘッダ下・グリップ） */

  /* インク（白 #FFF 地に対するコントラスト比を併記。文字は 4.5:1 が下限）。
     style.css の --gray-900 / --gray-600 / --gray-400 に揃える。
     3段目（旧 --tl-ink-50 = #6B6B6B・5.3:1）は廃止した（2026-09-04 夜）:
     「本文より一段薄い」を2回（#525252 と #6B6B6B）作ると、どちらも
     「なんとなく薄い灰色」に見えて階層として読めない。DreamCore の
     コントラストは 黒 / 灰 / 赤 の3値で組む。名前は別名として残す
     （約40箇所の参照を機械的に書き換えるより、値を1箇所で畳む方が安全）。 */
  --tl-ink: var(--gray-900, #171717);      /* 17.9:1  一次テキスト（本文・題名・押せる文字） */
  --tl-ink-70: var(--gray-600, #525252);   /*  7.8:1  二次テキスト（meta・補助の数字） */
  --tl-ink-50: var(--gray-600, #525252);   /*  7.8:1  = --tl-ink-70 の別名（旧3段目） */
  --tl-ink-disabled: var(--gray-400, #A3A3A3);  /* 2.5:1  装飾専用。文字色に使わない */

  /* ── アクセント（ブランドの赤 1色）───────────────────────────────
     DreamCore の赤の使い方は style.css の作法をそのまま持ち込む:
       ・淡い赤の面 + 赤い文字 = 選択中 / hover（サイドバーの現在地・.dc-ctx-pill）
       ・赤の塗り + 白抜き文字 = 主行動（作る・投稿する・シェア）
     --tl-accent（#FF3B30）は **文字を載せない塗り**（FAB・リング・栞）専用。
     白抜き 13px を載せる塗りと、白／淡赤の上に置く赤文字は --tl-accent-ink。
     実測（WCAG 相対輝度・2026-09-04）:
       #CE2820 on #FFFFFF                    = 5.32:1  ✓
       #CE2820 on 淡赤（.08 を白に重ねた #FFEFEE）= 4.77:1  ✓
       #FFFFFF on #CE2820                    = 5.32:1  ✓
       #CE2820 on 地 #F5F5F5                 = 4.88:1  ✓
     #FF3B30 に白 13px は 3.55:1、#E5342A でも 4.32:1 で AA を割るので採らない
     （どちらも「赤を明るく保つ」ために本文コントラストを捨てる取引になる）。

     ── ブランドの逃がし口（2026-09-20・PR #907 レビュー B [中18]）─────────
     ここに赤をベタ書きすると WEBLOX（public/css/brands/weblox.css が :root[data-brand="weblox"] で
     --red 系を青に差し替える）だけ色が破れる。ベタ書きをすべて var(--x, <今の値>) に寄せた。
     **フォールバックは今の値そのままなので DreamCore の見た目は 1px も変わらない。**
     WEBLOX 側で定義してほしいのは次の 4 つ（未定義なら今までどおり赤のまま = 無害）:
       --red-rgb    … 影・淡い面の 3 チャンネル（既定 255, 59, 48）。α は規則ごとに違うので
                      色そのものではなくチャンネルを渡す形にした（rgba(var(--red-rgb), .16) 等）
       --red-ink    … 白抜き文字を載せられる濃い赤（game-social は #CE2820・順位/XP は #E60012）
       --red-active … 押した瞬間の濃い赤（#E53529 / #E63329）
       --red-ledge  … 赤い部品の段差（#9E1C13）
     フォールバック値がファイルごとに違うのは、移動前（game.html / timeline.html のページ内 <style>）が
     元から違う値を持っていたため。揃えるのは見た目の変更になるので、この PR では触らない。 */
  --tl-accent: var(--red, #FF3B30);        /* 塗り・リング専用（文字を載せない） */
  --tl-accent-ink: var(--red-ink, #CE2820);   /* 赤文字 / 白抜き文字を載せる塗り */
  --tl-accent-soft: rgba(var(--red-rgb, 255, 59, 48), 0.08);  /* 淡赤の面（選択中・hover・自分の跡） */
  --tl-accent-ring: rgba(var(--red-rgb, 255, 59, 48), 0.55);

  /* ── 角丸（style.css の --r-12 / --r-16 / --r-20 / --r-full に揃える）──
     前の改訂で「札は 4px の角ばった小片」にしていたが、これは Skills 系の
     ダッシュボードの語彙で、DreamCore の丸い・柔らかい形と衝突していた
     （founder 指摘 2026-09-04 夕）。チップ・スタンプ・タブはピルに戻す。
     器（カード・シート）16 / 内側（サムネ・入力欄）10 / 押せる小片はピル、
     の3語彙だけで組む。
     20→16 / 12→10 は 2026-09-05 の採用案（scratchpad/design/look-nintendo.md）。
     器が「板（カートリッジ）」になり、下の段差（ledge）と噛み合う。 */
  --tl-r-container: 16px;          /* カード・シート・お題カード・骨格 */
  --tl-r-inner: 10px;              /* サムネ・入力欄・器の中の箱 */
  --tl-r-pill: 999px;              /* チップ・スタンプ・タブ・文字ボタンの下地・主行動 */
  /* 旧名は別名として残す（このファイル内の既存ルールが引き続き同じ値を読む） */
  --tl-r-card: var(--tl-r-container);
  --tl-r-thumb: var(--tl-r-inner);
  --tl-r-ctl: var(--tl-r-inner);

  /* 間隔。4の倍数「だけ」はやめた（どの行も同じ拍＝機械的に見える）。
     カードの器は 14/14/12、内側は 10/12/8 の3拍で組む。
     ここは founder が「構成はいまのままでいい」と言った部分なので触らない
     ＝ カード高さの決定性（下の §カード殻の表）もそのまま生きる。 */
  --tl-s-4: 4px;
  --tl-s-8: 8px;                   /* 密な行の中（顔と文字・チップ間） */
  --tl-s-10: 10px;                 /* カードの中の段の間 */
  --tl-s-12: 12px;                 /* 段どうし・サムネと本文 */
  --tl-s-14: 14px;                 /* カードの内側（上・左右） */
  --tl-s-16: 16px;
  --tl-s-24: 24px;

  /* ── 輪郭と段差（ledge）─────────────────────────────────────────
     2026-09-05・founder 採用案（scratchpad/design/look-nintendo.md）。
     「画面の中の物を、指で押せる部品にする」。ぼかした影で浮かせるのをやめ、
     1px の輪郭と、ぼかしを持たない段差（下に敷く無ぼかしの影）で厚みを出す。
     押すと部品が段差のぶん実際に沈む（translateY + 段差 0）。

     WHY ぼかしを捨てたか: 柔らかい環境光は1枚なら上品だが、20枚並ぶと
     輪郭どうしが滲んで「白い靄」になり、白いカードが #F5F5F5 の地に溶ける
     （2026-09-04 夜の founder 指摘「コントラストがぱきっとしない」の系統）。
     無ぼかしの段差は何枚並んでも輪郭が濁らない。
     段差の色は面の色に依らない黒の低アルファ（赤い部品だけ同色の暗い版）。 */
  --tl-edge: rgba(23,23,23,0.10);        /* 白面の上に置く部品の輪郭（サムネ等） */
  --tl-ledge-ink: rgba(23,23,23,0.16);   /* 黒・白部品の段差 */
  --tl-ledge-accent: var(--red-ledge, #9E1C13);   /* 赤部品の段差 ＝ #CE2820 の暗い版 */

  /* 影 = 「1px の輪郭」+「無ぼかしの段差」の2成分だけ。
     光源は上ひとつ: y は必ず正、x は必ず 0。
     🐛 2026-09-05: かつてこの段落は途中でコメントを閉じ、末尾でもう一度閉じ記号を
     置いていた。CSS のパーサは2つ目の閉じ記号を **宣言の中のゴミトークン** として
     扱い、次の `;` までを丸ごと捨てる ＝ --tl-shadow-card が未定義のまま published
     され、box-shadow: var(--tl-shadow-card) が initial（none）に落ちて
     **全カードの影が消えて** いた。同じ壊れ方が --tl-z-day と .tl-blurb にもあった。
     コメントの閉じ方には毎回気を付けること。
     シートだけは床から出る紙なので、段差 + 上へ散る環境光の2段を残す
     （下から出る物に接地影は無い ＝ 影で「浮いている」を言う唯一の場所）。 */
  --tl-shadow-card: 0 0 0 1px var(--tl-hairline), 0 3px 0 rgba(23,23,23,0.05);
  --tl-shadow-raised: 0 0 0 1px var(--tl-hairline), 0 5px 0 rgba(23,23,23,0.09);
  --tl-shadow-sheet: 0 -3px 0 rgba(23,23,23,0.08), 0 -24px 48px -28px rgba(0,0,0,0.32);

  /* モーション。押下は速い ＝ 指の下で物が即座に沈む。
     曲線はページ全体で2本だけ: 通常は --tl-ease、弾むのはスタンプ1か所のみ。
     linear / ease-in-out は使わない。 */
  --tl-dur-tap: 90ms;
  --tl-dur-ui: 160ms;
  --tl-dur-sheet: 220ms;
  --tl-dur-enter: 260ms;   /* 初回入場 */
  --tl-ease: cubic-bezier(0.2,0.9,0.25,1);
  --tl-ease-pop: cubic-bezier(0.34,1.56,0.64,1);   /* スタンプの弾みと、公開直後カードの祝いバッジ（2026-09-09）だけに使う */

  /* 書体はアプリ全体と同じ Inter 1本（詳細は <head> のフォント読み込みのコメント）。
     旧 --tl-font-face（丸ゴシック）は廃止し、参照はすべてこの1本に畳んだ。 */
  --tl-font-ui: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  /* z-index の段。数値をその場に散らさず、重なりの順序をここ1箇所で読む。
     グローバルの .bottom-nav は style.css で 2000。シート類はそれより上に置く
     （下だと送信ボタンや最下段のスタンプがナビに隠れ、背景越しにナビが押せる）。

     固定物（本文の上に浮く物）はもう1つも無い（2026-09-04 夜に FAB を撤去）。
     残っているのは sticky の2段（ヘッダ ＝ タブと投稿入口を内包 → 着地バー /
     日付見出し）とシート類だけで、どれも在来フローか画面全体を覆う物。
     段が1つ減ったのは 2026-09-06（タブ行をヘッダへ畳んだ）。

     🐛 2026-09-05: ここも上の影と同じ壊れた閉じ方をしていて、--tl-z-day が
     捨てられていた（日付見出しの sticky が z-index:auto ＝ 後続カードの
     重なり順に負ける）。--tl-shadow-card のコメントに詳細。 */
  --tl-z-day: 5;
  --tl-z-bar: 25;
  --tl-z-header: 30;
  --tl-z-lightbox: 2050;
  --tl-z-backdrop: 2100;
  --tl-z-sheet: 2110;
  --tl-z-toast: 2120;      /* シートより上（シート上の操作結果も見える） */

  /* 旧名は新トークンの別名として残す。このページの共通要素（.tl-btn 等）が
     同じ色を引き続けるための橋で、新しく書くルールでは --tl-* を直接使う。 */
  --bg: var(--tl-bg);
  --panel: var(--tl-surface-sunk);
  --border: var(--tl-hairline);
  --ink: var(--tl-ink);
  --muted: var(--tl-ink-50);
  --accent: var(--tl-accent);
}

/* 反応・痕跡は「出た」ことだけを伝える。位置は動かさない（読んでいる行がずれる） */
@keyframes tl-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
/* スタンプを押した瞬間の1回。押し込んで戻る = 指の下で物が沈んだ手応え */
@keyframes tl-stamp-pop {
  0% { transform: scale(1); }
  45% { transform: scale(0.88); }
  100% { transform: scale(1); }
}
/* 押した人の顔が左から入る。列の先頭に自分が足された、が伝わる最小の動き */
@keyframes tl-face-in {
  from { opacity: 0; transform: translateX(-4px); }
  to { opacity: 1; transform: translateX(0); }
}
/* 「まだ誰も座っていない席」を1回だけ叩く。反応ゼロのカードの ＋ だけ・1回だけ */
@keyframes tl-seat-pulse {
  0% { box-shadow: 0 0 0 0 var(--tl-accent-ring); }
  50% { box-shadow: 0 0 0 2px rgba(var(--red-rgb, 255, 59, 48), 0.18); }
  100% { box-shadow: 0 0 0 0 rgba(var(--red-rgb, 255, 59, 48), 0); }
}

/* キーボード操作の可視化。アイコンだけのボタン（スタンプ・FAB・シート閉じる）は
   フォーカスが見えないと操作不能になるので、全対話要素に共通で当てる */
.tl-shell :focus-visible,
.tl-sheet :focus-visible,
.tl-published-bar :focus-visible {
  outline: 3px solid var(--tl-accent-ring);
  outline-offset: 2px;
  border-radius: 8px;
}

/* 汎用ボタン（シート・エラー・着地バー）= **副次行動**。
   枠なしの文字ボタンで、押せることは太字（700）と、hover / 押下で敷かれる
   **淡い赤の面 + 赤い文字** が言う。これは style.css のサイドバー現在地・
   .dc-ctx-pill と同じ DreamCore の作法で、灰色に沈むだけの前改訂より
   「押すと嬉しいことが起きる」感じが出る（2026-09-04 夕）。
   主行動（.primary）だけが赤で塗られたピル。 */
/* <a> でも <button> でも同じ形になるように inline-flex + text-decoration:none。
   着地バーの「次のお題を見る」はリンクで、素だと下線が付いて1つだけ別の物に見えた。 */
/* 副次行動の文字色は **黒**（--gray-900）。2026-09-04 夜の founder 指摘
   「コントラストがぱきっとした感じがなくなってます」の中心がここだった:
   押せる文字を灰色（--gray-600）にすると、隣の説明文（同じ灰色）と見分けが
   付かず、面全体が「灰色の霧」になる。押せる物は黒・押せない物は灰色、が
   DreamCore の読み方。hover は淡赤の面だけを敷いて **文字は黒のまま**、
   押した瞬間（:active）に赤へ振る ＝ 赤は「いま起きたこと」に取っておく。 */
.tl-btn {
  display: inline-flex; align-items: center; justify-content: center;
  border: 0;
  background: transparent;
  color: var(--tl-ink);
  border-radius: var(--tl-r-pill);
  padding: 8px 12px;
  font-family: var(--tl-font-ui);
  font-weight: 700;
  font-size: 13px;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--tl-dur-tap) var(--tl-ease), color var(--tl-dur-tap) var(--tl-ease), transform var(--tl-dur-tap) var(--tl-ease);
}
.tl-btn:not(.primary):active { background: var(--tl-accent-soft); color: var(--tl-accent-ink); }
@media (hover: hover) and (pointer: fine) {
  .tl-btn:not(.primary):hover { background: var(--tl-accent-soft); }
}
/* 押下は沈む（scale は使わない）。副次は 1px、主行動（.primary）は段差ぶんの 2px */
.tl-btn:not(.primary):active { transform: translateY(1px); }
/* 塗り + 白抜き文字のボタンは --tl-accent（#FF3B30）ではなく --tl-accent-ink
   （#CE2820）。#FF3B30 に白 13px は 3.5:1、候補に挙がった #E5342A でも 4.33:1 で
   WCAG AA の 4.5:1 を割る（13px/700 は「大きな文字」の扱いにならない）。
   #CE2820 は白との比 5.32:1（実測・§トークン）。
   --tl-accent（塗りの赤そのもの）が残るのは FAB と栞とリングの3か所だけで、
   どれも上に白い文字を置かない。
   ここを通るのは カード内「作る」/ 投稿シートの送信 / スレッドの送信 /
   着地バーの「シェア」= 白抜き文字を持つ塗りボタンの全部。
   文字は 13px → **15px/700**（2026-09-04 夜）。主行動が二次テキストと同じ
   13px だったのが「ぱきっとしない」の一因で、面の中でいちばん強い物が
   いちばん小さい字を着ていた。 */
.tl-btn.primary {
  background: var(--tl-accent-ink); color: #fff;
  border-radius: var(--tl-r-pill); padding: 8px 16px;
  font-size: 15px;
  /* 赤い部品の段差は同色の暗い版（.tl-compose-entry と同じ作法） */
  box-shadow: 0 2px 0 var(--tl-ledge-accent);
}
.tl-btn.primary:active {
  background: var(--tl-accent-ink); color: #fff;
  transform: translateY(2px); box-shadow: none;
}
.tl-btn:disabled { opacity: 0.5; cursor: default; }
.tl-btn:disabled:active { transform: none; }

/* === 統一カード（2026-09-04 / founder 指摘への答え）===
   「新着カードと、つぶやき投稿が同一じゃないのでおかしい感じしますね」。
   v3 までは ゲーム＝枠つきカード、ひとこと＝吹き出し、「作って」＝黄色い小カード、
   コメント＝左に青い縦線、と **4種類の器** が同じ流れに並んでいた。
   （「作って」（request）投稿そのものは 2026-09-05 の founder 判断で廃止した。
    文字投稿は「ひとこと」と公式投稿の2種類だけ。以下の記述で「作って」に
    触れている箇所は、その頃の経緯として残している。）
   ここでは器を1つにする: 角丸・余白・文字サイズは .tl-card だけが持ち、
   種類ごとに違うのは .tl-card-body の中身だけ。ヘッダ（誰が・いつ・種類チップ）、
   反応の帯、会話ブロックは全種で同じ markup・同じ CSS。

   ── 枠を外した（2026-09-04 リデザイン・lever 2）────────────────────
   「1px の枠 + 弱い影 + 白」は LLM が最も出しやすいカードで、founder の
   「めっちゃ AI っぽい」の中心。枠は輪郭を **描いて** しまうので、20枚並ぶと
   画面が升目に見える。ここでは輪郭を影に任せる:
     - 接地の 1px（0 1px 2px / 6%）= 紙がそこに置いてある
     - 環境光の散り（0 8px 24px -16px / 18%）= 部屋の光が回り込んだ影
   影の色は純黒の低アルファ（rgba(0,0,0,*)）。2026-09-05 に青灰
   rgba(19,19,26,*) から替えた: 地が中性グレー（#F7F7F8）だった頃の値で、
   いまの地 #F5F5F5 では「うっすら青い縁」が付いて輪郭が濁っていた。
   y は必ず正・x は必ず 0 ＝ 光源はページ全体で「上ひとつ」。
   地（#F5F5F5）と面（#FFF）の 4% の段差が、影の届かない上辺を支える。

   ── 余白は 14/14/12（lever 3）───────────────────────────────────
   4の倍数だけで組んでいたのをやめた。下だけ 12 に詰めるのは視覚補正で、
   カードの最下段は「会話ブロックの最後の行（32px のボタン）」＝ 文字より
   背の高い物なので、上と同じ 14 を取ると下だけ間延びして見える。
   内側の拍は 10（段どうし）/ 12（サムネと本文）/ 8（行の中）の3つ。

   375px 幅での実寸（Playwright / ja / overlay proxy の合成会話データ・
   2026-09-04 リデザイン後の実測。**夕のトンマナ改訂・クリア行の並べ替えでも
   この表は動いていない** — 変えたのは角丸・色・影・書体と、クリア行の中の
   並び順（文 → 顔 → 最速。同じ1行の flex の中の順序だけ）で、padding / gap /
   行の高さ / サムネ寸法には一切触れていないため。並べ替え後の再撮影（375 / 768 /
   1280）で最小構成 281・会話1行 307・3行 351・骨格 281 の一致と、
   .tl-clears-line の行高 18px（= .tl-avatar-tiny の 18px が決める）を再確認済み。
   詳しい積み上げは timeline.js の SKELETON_CARD_HTML のコメントに1つだけ
   置いてある。両方を直すこと）:
     ヘッダ 24（アバター 24 が下限。「⋯」の 24px はマイナスマージンで押し上げない）
     本文  ゲーム 128（サムネ 96x128 が下限。一言・クリア行・文脈チップが載って
                      本文側が超えた回の実測は 139.97 / 149.97）
           ひとこと 24〜72（本文 16px*1.5 で最大3行）
     帯   41（= 上境界 1 + padding-top 8 + チップ 32。コメントは押せるスタンプの
           対象が無いので帯ごと出さない）
     会話 foot だけ 32 / プレビュー1行目 +26 / 2行目以降 +22
     コメントカードの宛先行（2026-09-08・.tl-comment-to）= 15.4 + margin 4 ≈ 19.4。
           nowrap で 2 行にならないので描画後に動かない
   → 最小構成のゲームカード = 26 + 24 + 10 + 128 + 10 + 41 + 10 + 32 = 281px
     （骨格 .tl-skel も同じ 281px）。会話3行つき = 351px。ひとこと = 201〜225px。
     2026-09-07〜: 会話は可変長（畳んだ状態 = 最新3ルート + 各最新2返信・本文2行まで。
     開けば最新20ルート）。固定契約は廃止。骨格は最小構成のまま。
   いずれも **画像の読み込みで高さが動かない**（サムネ 96x128・アバター固定・
   投稿画像は aspect-ratio 固定・スケルトンも同寸）ので、prependFreshEvents の
   「増えた高さぶん scrollTop を足す」補正が成立する。ここを崩さないこと。
   入場アニメは transform/opacity だけなので、この前提に触らない。 */
.tl-card {
  position: relative;
  display: flex; flex-direction: column; gap: 10px;
  border: 0;
  border-radius: var(--tl-r-container);   /* 20px = DreamCore の器（style.css --r-20） */
  background: var(--tl-surface);
  padding: 14px 14px 12px;
  box-shadow: var(--tl-shadow-card);
}

/* ヘッダ: アバター24 + 名前(+公式バッジ) · 相対時刻 / 右に種類チップと「⋯」。
   名前と時刻は三次テキスト＝作品が主役で、人は文脈。 */
.tl-card-head {
  display: flex; align-items: center; gap: 8px;
  min-width: 0; font-size: 11px; color: var(--tl-ink-50);
}
/* 名前は黒（--gray-900）。2026-09-05: 名前を二次インク（#525252）にすると、
   すぐ隣の時刻（同じ #525252）と一体化して「小さい灰色の行」になり、
   誰の作品かが読み取れなかった。DreamCore の読み方は 題名・名前 = 黒 /
   メタ（時刻・件数）= 灰。行の高さは line-height 1.4 のままなので
   カード高さ（§カード殻）は動かない。 */
.tl-card-head .tl-name {
  font-family: var(--tl-font-ui);
  font-size: 12px; font-weight: 700; line-height: 1.4; color: var(--tl-ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 42%;
}

/* アバターは真円（2026-09-04 夕に角丸スクエアから戻した）。
   昼の版は「丸アイコンは SNS のテンプレ」という理由でスクワークルにしていたが、
   DreamCore はアプリ全体（style.css の .user-avatar / サイドバー / mypage）が
   真円で、この面だけ四角い顔になっていた ＝ SPA でタブを渡ると同じ人の顔の
   形が変わる。ブランドの一貫性の方が「テンプレ回避」より優先する
   （founder「DreamCore のポップなトンマナを守って」）。 */
.tl-avatar-24 {
  width: 24px; height: 24px; border-radius: 50%;
  overflow: hidden; background: var(--tl-surface-sunk); flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: var(--tl-ink-50);
}
.tl-avatar-24 img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tl-avatar-tiny {
  width: 18px; height: 18px; border-radius: 50%;
  overflow: hidden; background: var(--tl-surface-sunk); flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 9px; font-weight: 700; color: var(--tl-ink-50);
}
.tl-avatar-tiny img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 中黒は装飾だが「文字」として描かれるので、2.5:1 の --tl-ink-disabled では
   行の途中だけ消えて見えた（2026-09-05）。メタと同じ二次インクに揃える。 */
.tl-dot { color: var(--tl-ink-70); flex: 0 0 auto; }
/* 時刻は「読む数字」なので Inter のまま。桁揃えは body の tabular-nums が持つ */
/* メタは 700（2026-09-05 採用案「部品のラベルは太い」）。色は二次インクのまま */
.tl-time { font-size: 11px; font-weight: 700; line-height: 1.4; color: var(--tl-ink-70); flex: 0 0 auto; }

/* 本文。サムネを持つ種類（ゲーム・コメント）だけ横並びにする */
/* 拍は3つだけ: 10 = 段どうし / 12 = サムネと本文 / 8 = 行の中（下の帯・会話） */
.tl-card-body { min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.tl-card-body-media { flex-direction: row; gap: 12px; align-items: flex-start; }
.tl-card-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }

/* ゲームのサムネ 96x128（高さ固定 = カード高さが画像で動かない前提）。
   黒い再生丸は削除（2026-09-04）: サムネ全面が押せる面なのに、その上に
   「ここが押せます」の丸を重ねるのは同じことを二度言っている。
   代わりに面そのものを沈める（:active）。 */
.tl-card-thumb {
  position: relative;
  width: 96px; height: 128px; flex: 0 0 96px;
  border-radius: var(--tl-r-thumb); overflow: hidden;
  background: linear-gradient(160deg, var(--gray-100, #F5F5F5), var(--gray-200, #E5E5E5));
  /* 輪郭を1本入れて「面の中に嵌まった部品」にする。
     WHY inset ではなく外側の 1px か: inset の影は要素の背景の上・**子の内容の下**
     に描かれ、img が 100%x100% で覆うここでは角丸の外周しか見えない
     （＝輪郭を足したのに輪郭が無い）。外側 1px の box-shadow はレイアウトを
     1px も動かさないので、96x128 / 4:5 / 40x40 の据置寸法にも無害。 */
  box-shadow: 0 0 0 1px var(--tl-edge);
  display: block; text-decoration: none; cursor: pointer;
  transition: transform var(--tl-dur-tap) var(--tl-ease);
}
/* 面（カード・タイル・サムネ）の押下は translateY(1px) scale(0.99)。
   主行動の 2px より浅いのは、序列（主 ＞ 面）を動きの量でも保つため。 */
.tl-card-thumb:active { transform: translateY(1px) scale(0.99); }
.tl-card-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tl-thumb-empty {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  color: var(--tl-ink-disabled);
}
.tl-thumb-empty svg { width: 28px; height: 28px; }

/* z-index: 来歴リンク（.tl-provenance）の当たり判定は上下に伸びていて、題名の
   下端と重なる。後ろの要素の疑似要素が上に載るので、題名を明示的に積み上げて
   「題名の下端を押したら作り方が開いた」を防ぐ。 */
.tl-card-title-link { position: relative; z-index: 1; display: block; text-decoration: none; color: inherit; min-width: 0; cursor: pointer; }
/* 題名は作品の名前 = この面でいちばん「その人のもの」な文字。書体はアプリ全体と
   同じ Inter で、目立たせるのは書体ではなく 16px / 700 という **大きさと太さ**
   （DreamCore の作法。2026-09-04 夕に丸ゴシック指定を撤去）。
   text-wrap: balance は2行に折り返したとき、2行目に単語が1つだけ残る
   （孤立行）のを防ぐ。2行クランプなので balance の対象行数の上限にも収まる。 */
/* 17px / 800（2026-09-04 夜）。16/700 は本文（16px）と同じ大きさで、
   題名が「少し太い本文」にしか見えなかった ＝ カードの中で目が最初に
   着地する場所が決まらない。1px 上げて 1段太くするだけで、題名 → 一言 →
   メタ の3段が一目で分かれる。行の高さは 96x128 のサムネの内側で伸びるので、
   カードの高さは最小構成では変わらない（本文側が 128 を超える回だけ、
   §カード殻の 139.97/149.97 が数 px 増える。画像の到着では動かない＝
   prependFreshEvents の前提は不変）。 */
/* 17px 以上だけ字間を締める（小さい文字には盛らない）。2026-09-05 採用案 */
.tl-card-title {
  font-family: var(--tl-font-ui);
  font-size: 17px; font-weight: 800; line-height: 1.35; color: var(--tl-ink);
  letter-spacing: -0.01em;
  text-wrap: balance;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-width: 0;
}
/* 作者の一言（game.blurb = 公開説明文の1行目）。吹き出しをやめて素のテキストにした:
   ひとことの本文（.tl-text）と同じ扱いにすると、新作カードとつぶやきが
   「同じ物体の別の中身」として読める（2026-09-04 founder 指摘への答え）。
   色は黒（--gray-900）。作者の声は「読ませる文」なので、メタ情報の灰色と
   同じ色にしない（2026-09-04 夜）。
   🐛 2026-09-05: ここも壊れた閉じ方をしていて、規則そのものが（セレクタごと）
   捨てられていた ＝ 一言が 16px の素のテキストのまま2行クランプもされて
   いなかった。--tl-shadow-card のコメントに詳細。 */
.tl-blurb {
  font-size: 14px; line-height: 1.6; color: var(--tl-ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; word-break: break-word;
}

/* 来歴（「作り方」）。枠付きチップをやめてタイトル直下のリンク text にした
   （2026-09-04）: これは行動ではなく作品の来歴で、枠は「押せる物」の記号を
   安売りする。押せることは色と下線ではなく、位置（タイトルの真下）と
   :active の赤で示す。 */
.tl-provenance {
  align-self: flex-start;
  border: 0; background: none; padding: 0;
  /* 2026-09-05: 押せる物は黒 700（.tl-strip-btn / .tl-thread-count と
     同じ規則）。灰色 500 だと隣のメタ情報と同じ字面で、押せることが読めなかった。
     11px のまま・line-height 1.4 のまま・min-height 22px のままなので、
     行の高さは 1px も動かない（カード高さの決定性に無害）。 */
  font-family: inherit; font-size: 11px; font-weight: 700; line-height: 1.4;
  color: var(--tl-ink); text-decoration: none; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
  position: relative; display: inline-flex; align-items: center; min-height: 22px;
}
/* 縦は 22 + 11*2 = 44px。横は文言の実幅しか無く、日本語の「作り方」で 33px
   しか取れていなかった（2026-09-04 QA・finding 4）。left/right 両方を 0 に
   置いたうえで min-width を効かせると、絶対配置の箱は左端を保ったまま
   44px まで伸びる（over-constrained なので ltr では right が譲る）。
   見た目の幅は変わらない（この疑似要素は透明で、文字の位置も動かない）。 */
.tl-provenance::after {
  content: ''; position: absolute; inset: -11px 0; min-width: 44px;
}
.tl-provenance:active { color: var(--tl-accent-ink); }
@media (hover: hover) and (pointer: fine) {
  .tl-provenance:hover { color: var(--tl-accent-ink); }
}

/* 遊んだ痕跡: 文が先・顔が後（2026-09-04 夕・founder「この顔の列は何？」）。
   昼の版は顔を先頭に置いていたが、説明の無い小さい円が3つ並ぶだけの出だしは
   「何の顔か」を右の文まで読まないと判らず、視線が戻る行になっていた。
   「今日8人がクリア」→ 顔 → 「りん 41秒」の順にすると、主語が立ってから
   顔が並ぶので、顔は最初から意味を持って読める。
   緑は廃止 = クリアは達成の演出ではなく事実なので、色で祝わない。
   行の背は最も背の高い .tl-avatar-tiny（18px）が決める ＝ 並べ替えても
   カード高さの決定性（§カード殻の表）は動かない。 */
.tl-clears-line {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 700; line-height: 1.4; min-width: 0;
  color: var(--tl-ink-70);
  animation: tl-fade-in var(--tl-dur-ui) var(--tl-ease);
}
/* 縮む順番: 人数（固定）→ 顔（固定）→ 最速タイム（ここだけ削る）。
   人数は行の要点なので絶対に切らない。最速は「誰かが速かった」が伝われば足りる。 */
.tl-clears { flex: 0 0 auto; white-space: nowrap; }
/* 顔は文の **後ろ** に来るので、列の左端が文とくっつかないように 2px だけ空ける
   （行の gap 8 と合わせて 10px = カードの中の段の拍と同じ）。列の中の重なりは
   margin-left:-4px のままで、これは並びを変えても左から右に重なる向きが正しい。 */
.tl-clears-faces { display: inline-flex; flex: 0 0 auto; margin-left: 2px; }
/* 縁は 2px（面の色）。1.5px では顔どうしの重なりが「にじんだ団子」に見えていた */
.tl-clears-faces .tl-avatar-tiny { margin-left: -4px; border: 2px solid var(--tl-surface); }
.tl-clears-faces .tl-avatar-tiny:first-child { margin-left: 0; }
/* 最新の1人にだけ赤いリング。「たった今この人が遊んだ」が赤を使う理由 */
.tl-clears-faces .tl-avatar-tiny.is-latest { box-shadow: 0 0 0 2px var(--tl-accent); }
.tl-clears-fastest {
  flex: 0 1 auto; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* タイムは比べる数値。桁揃えは body の tabular-nums が持つので専用書体は不要 */
.tl-clears-fastest em { font-style: normal; font-weight: 500; }

/* 文脈チップ（お題 / どのゲームへのコメントか）。
   どの種類でも同じ見た目にする＝カードの語彙を1つに保つ。
   旧「『作って』への答え」チップは 2026-09-05 の request 廃止で消えた。 */
.tl-card-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }

/* 高さは 32px、当たり判定だけ疑似要素で 44px に広げる（密度と指の両立）。
   枠付きの白ピルをやめた（lever 2）: 1枚のカードに枠付きピルが3〜4個並ぶと、
   どれが主行動か読めない。副次行動は枠なしの文字ボタンで、押せることは
   太字（700）と、hover / 押下で敷かれる淡い赤の面 + 赤い文字が言う
   （= サイドバーの現在地と同じ DreamCore の作法。2026-09-04 夕）。 */
.tl-strip-btn {
  position: relative;
  display: inline-flex; align-items: center; gap: 4px;
  height: 32px; padding: 0 12px; margin: 0 -4px;
  border: 0; border-radius: var(--tl-r-pill);
  background: transparent;
  font-family: var(--tl-font-ui); font-size: 13px; font-weight: 700;
  color: var(--tl-ink); text-decoration: none; cursor: pointer;
  white-space: nowrap;
  transition: background var(--tl-dur-tap) var(--tl-ease), color var(--tl-dur-tap) var(--tl-ease), transform var(--tl-dur-tap) var(--tl-ease);
}
.tl-strip-btn svg { width: 12px; height: 12px; }
.tl-strip-btn::after { content: ''; position: absolute; inset: -6px 0; }
/* 枠なしの文字ボタンは形を変えない。押下だけ 1px 沈める（部品は縮まない） */
.tl-strip-btn:active { transform: translateY(1px); background: var(--tl-accent-soft); color: var(--tl-accent-ink); }
@media (hover: hover) and (pointer: fine) {
  .tl-strip-btn:hover { background: var(--tl-accent-soft); }
}

/* --- スタンプチップ（グリフ + 押した人のアイコン。数は出さない = §0） ---
   高さは 32px に抑え、当たり判定だけ疑似要素で上下に広げて 44px にする。
   帯を44pxの箱で組むとカードが一気に伸びて「でかすぎ」に戻るため。
   押された跡（既にあるスタンプ）は **枠を外して紙に沈める**（2026-09-04）:
   枠は「押せる物」の記号なので、既に押された跡と、これから押す ＋ の両方に
   付いていると、どちらが空席か読めない。 */
/* チップ間 4px → 8px（2026-09-04 QA・finding 5）。上下に 6px 伸ばした当たり判定
   どうしが 4px では 2px 食い合い、隣のスタンプを誤爆できていた。
   横並びなのでカードの高さには影響しない（overflow:hidden でクリップされる）。 */
.tl-stamps { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
/* スタンプは「押された跡」＝やわらかいピル（2026-09-04 夕に 4px の角ばった札から
   戻した）。丸いアバターが2〜3個載る器なので、器も丸い方が形が家族になる。
   自分が押した分だけ淡赤 + 赤の細いリング ＝ サイドバー現在地と同じ作法。 */
.tl-stamp, .tl-stamp-add {
  position: relative;
  display: inline-flex; align-items: center; gap: 4px;
  height: 32px; border-radius: var(--tl-r-pill);
  cursor: pointer; font-family: inherit; flex: 0 0 auto;
  border: 0; background: var(--tl-surface-sunk); color: var(--tl-ink);
  transition: background var(--tl-dur-tap) var(--tl-ease), box-shadow var(--tl-dur-tap) var(--tl-ease);
}
.tl-stamp-plus {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  height: 32px; cursor: pointer; font-family: inherit; flex: 0 0 auto;
  border: 0;
  transition: background var(--tl-dur-tap) var(--tl-ease), box-shadow var(--tl-dur-tap) var(--tl-ease);
}
.tl-stamp::after, .tl-stamp-plus::after, .tl-stamp-add::after {
  content: ''; position: absolute; inset: -6px 0;   /* 32 + 12 = 44px の当たり判定（縦） */
}
/* ＋ は実寸 32x32 の正方形で、縦だけ広げても横が 32px のままだった
   （2026-09-04 QA・finding 4）。左右も 6px ずつ広げて 44x44 にする。
   隣のスタンプチップとは gap 8px あるので、6px 伸ばしても当たり判定は重ならない
   （8 - 6 = 2px の隙間が残る）。 */
.tl-stamp-plus::after { inset: -6px; }
/* 跡は「沈んだ部品」＝ 内側の輪郭 + 1px の段差。--tl-stamp-add には付けない
   （あちらは枠なしの文字ボタンで、部品ではない）。 */
.tl-stamp {
  padding: 0 10px;
  box-shadow: inset 0 0 0 1px var(--tl-hairline), 0 1px 0 var(--tl-ledge-ink);
  transition: background var(--tl-dur-tap) var(--tl-ease), box-shadow var(--tl-dur-tap) var(--tl-ease),
              transform var(--tl-dur-tap) var(--tl-ease);
}
.tl-stamp:active { transform: translateY(1px); box-shadow: inset 0 0 0 1px var(--tl-hairline); }
/* 自分が押した分だけ赤（赤の4か所のうちの1つ）。塗りではなく内側リングにするのは、
   グリフと顔の可読性を落とさずに「自分の分」を示せるため。 */
.tl-stamp.mine {
  background: var(--tl-accent-soft); color: var(--tl-accent-ink);
  box-shadow: inset 0 0 0 2px var(--tl-accent), 0 1px 0 var(--tl-ledge-ink);
}
.tl-stamp.mine:active { transform: translateY(1px); box-shadow: inset 0 0 0 2px var(--tl-accent); }
.tl-stamp[aria-busy="true"] { opacity: 0.55; }
.tl-stamp .tl-stamp-glyph { font-size: 15px; line-height: 1; }
/* 押した瞬間の1回だけ（JS が付ける）。押し込んで戻る + 自分の顔が左から入る */
.tl-stamp.tl-stamp-pop { animation: tl-stamp-pop 180ms var(--tl-ease-pop); }
.tl-stamp.tl-stamp-pop .tl-stamp-users > :first-child {
  animation: tl-face-in var(--tl-dur-ui) var(--tl-ease);
}
/* ＋ =「まだ誰も座っていない席」。破線の丸も角丸スクエアもやめて、
   やわらかい灰色の丸（--gray-100）にした（2026-09-04 夕）。
   隣に並ぶスタンプのピル・その中のまるいアバターと同じ family で、
   「空いている席」であることは塗りの薄さだけが言う。 */
.tl-stamp-plus {
  width: 32px; padding: 0;
  border-radius: 50%;
  background: var(--tl-surface-sunk);
  color: var(--tl-ink-50);
  box-shadow: inset 0 0 0 1px var(--tl-hairline), 0 1px 0 var(--tl-ledge-ink);
  transition: background var(--tl-dur-tap) var(--tl-ease), box-shadow var(--tl-dur-tap) var(--tl-ease),
              transform var(--tl-dur-tap) var(--tl-ease);
}
@media (hover: hover) and (pointer: fine) {
  .tl-stamp-plus:hover { background: var(--tl-accent-soft); color: var(--tl-accent-ink); }
}
.tl-stamp-plus svg { width: 16px; height: 16px; }
.tl-stamp-plus:active { transform: translateY(1px); box-shadow: inset 0 0 0 1px var(--tl-hairline); }
/* 反応ゼロのカードが初めて視界に入ったときだけ、1回叩く（JS が付ける） */
.tl-stamp-plus.tl-seat-pulse { animation: tl-seat-pulse 600ms var(--tl-ease) 1; }
/* 文字つきの「スタンプ」は帯の末尾に出る副次行動。枠なしの文字ボタン */
.tl-stamp-add {
  padding: 0 12px; margin: 0 -4px; border: 0; background: transparent;
  font-family: var(--tl-font-ui);
  font-size: 13px; font-weight: 700; color: var(--tl-ink); white-space: nowrap;
}
.tl-stamp-add svg { width: 14px; height: 14px; flex-shrink: 0; }
.tl-stamp-add:active { transform: translateY(1px); background: var(--tl-accent-soft); color: var(--tl-accent-ink); }
@media (hover: hover) and (pointer: fine) {
  .tl-stamp-add:hover { background: var(--tl-accent-soft); }
}
.tl-stamp-users { display: inline-flex; }
.tl-stamp-users img,
.tl-stamp-users span {
  width: 16px; height: 16px; border-radius: 50%;
  /* 縁取りは「載っている面」の色。白の縁取りではなく切り抜きにすると、
     重なった顔が1枚の札から抜かれたように見える */
  border: 1.5px solid var(--tl-surface-sunk); margin-left: -4px;
  background: var(--tl-surface-sunk); object-fit: cover;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 8px; font-weight: 700; color: var(--tl-ink-50);
}
.tl-stamp-users img:first-child,
.tl-stamp-users span:first-child { margin-left: 0; }

/* 押せる文脈チップ（お題 / 答え / 元のゲーム）。枠は持たず、沈んだ灰色のピル。
   押せることは hover / 押下で淡赤 + 赤文字に変わることが言う（押せないラベルは
   灰色のまま動かない）。 */
a.tl-chip-link {
  position: relative;                     /* ::after の当たり判定用（finding 4） */
  display: inline-flex; align-items: center;
  text-transform: none; text-decoration: none;
  font-family: var(--tl-font-ui);
  font-size: 11px; font-weight: 700; line-height: 1.4;
  min-height: 32px; padding: 0 12px; border-radius: var(--tl-r-pill);
  background: var(--tl-surface-sunk); color: var(--tl-ink);
  border: 0; cursor: pointer;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: background var(--tl-dur-tap) var(--tl-ease), color var(--tl-dur-tap) var(--tl-ease), transform var(--tl-dur-tap) var(--tl-ease);
}
/* 見た目 32px・当たり判定 44px（2026-09-04 QA・finding 4）。実寸を上げると
   .tl-card-chips の行が 12px 伸び、カード高さの数え方（§カード殻）が崩れる。 */
a.tl-chip-link::after { content: ''; position: absolute; inset: -6px 0; }
a.tl-chip-link:active { transform: translateY(1px); background: var(--tl-accent-soft); color: var(--tl-accent-ink); }
@media (hover: hover) and (pointer: fine) {
  a.tl-chip-link:hover { background: var(--tl-accent-soft); }
}

/* Official badge。公式は「そういう人」の印であって意味色ではないので、
   赤にも灰にもせず、インクの黒で塗る（色を1つ増やさない） */
.tl-official-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--tl-ink); color: #fff; margin-left: 4px; vertical-align: middle;
  flex-shrink: 0;
}
.tl-official-badge svg { width: 10px; height: 10px; }

/* === 本文テキスト（全種共通）===
   ひとこと・コメント・展開した返信は **同じ文字の扱い**。
   吹き出し（.tl-bubble）をやめたのは、同じ流れに「吹き出しの人」と
   「カードの人」が混在して見えるのを止めるため（2026-09-04 founder 指摘）。
   16px にしたのは、これがカードの主役の1つ（作者の声）だから。 */
.tl-text {
  font-size: 16px; line-height: 1.5; color: var(--tl-ink);
  word-break: break-word; white-space: pre-wrap; min-width: 0;
}

/* 公式投稿の本文内リンク（renderBodyHtml が is_official の本文だけに付与）。
   白地の赤文字は --tl-accent-ink（4.8:1）。塗り用の --tl-accent は 3.1:1 で
   本文の文字色には使えない。 */
.tl-body-link { color: var(--tl-accent-ink); text-decoration: underline; word-break: break-all; }
@media (hover: hover) and (pointer: fine) {
  .tl-body-link:hover { opacity: 0.8; }
}

/* 添付画像。aspect-ratio 固定は timeline.js の追記型 stale リフレッシュ
   （prependFreshEvents）のスクロール補正の前提 — 画像のロード有無で高さが
   動かないからこそ「挿入で増えた高さぶんだけ scrollTop を足す」が効く。 */
.tl-image {
  border-radius: var(--tl-r-inner); overflow: hidden;
  border: 0; background: var(--tl-surface-sunk);
  box-shadow: 0 0 0 1px var(--tl-edge);   /* 外側 1px の理由は .tl-card-thumb 参照 */
  cursor: zoom-in; display: inline-block;
  width: 40%; aspect-ratio: 4 / 5; max-width: 100%;
}
.tl-image img { width: 100%; height: 100%; object-fit: cover; display: block; }

.tl-translation {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 700; color: var(--tl-ink-70);
}
.tl-link-btn {
  position: relative;
  border: 0; padding: 0; background: none;
  color: var(--tl-accent-ink); font-weight: 700; cursor: pointer;
  font-size: inherit; font-family: inherit;
}
.tl-link-btn::after { content: ''; position: absolute; inset: -14px 0; }   /* 当たり判定 44px */

/* === 会話ブロック（全種共通・2026-09-04）===
   ゲームのコメントも、ひとことへの返信も、コメントへの返信も、
   ここに来る。markup も CSS も文言も1本（timeline.js の threadBlockHtml）。
   高さの数え方（prependFreshEvents のスクロール補正の前提）:
     プレビュー1行 = 18px（アバター16 + テキストの line-height 18px）
     list = n*18 + (n-1)*4、foot = 32px、ブロック内 gap = 8px
   アバターは寸法固定なので、画像の遅延読み込みで高さは動かない。
   行高 18px / 行間 4px は **変更禁止**。プレビューの文字だけ 12→13px に
   上げたが、line-height は 18px に固定したままなので高さは動かない。 */
.tl-thread { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.tl-thread-list { display: flex; flex-direction: column; gap: 4px; }
.tl-thread-line {
  display: flex; align-items: center; gap: 4px;
  height: 18px; font-size: 13px; line-height: 18px; min-width: 0;
  animation: tl-fade-in var(--tl-dur-ui) var(--tl-ease);
}
.tl-thread-line .tl-avatar-tiny { width: 16px; height: 16px; font-size: 8px; }
/* === ゲームカードの会話（2026-09-07 夕・founder「ギュッとしすぎ。UI/UX のベスト
   プラクティスで。コメント欄はその場で開く。全面タッチ」）===
   1件 = アバター 20 + （名前・時刻 / 本文）の2段。X / Threads / Instagram のコメント欄と
   同じ作法。本文は畳んだ状態で2行クランプ、開けば全文（500字上限）。
   返信はアバター幅ぶん字下げ + 左線（親子が読める最小の印）。
   1件の全面がタップ対象。器いっぱいに重ねた本物の <button>（.tl-thread-tap）が受け、
   プロフィールリンク・翻訳切替は z-index で上に乗せて押せるままにする（器に
   role=button を付けると中の対話要素が支援技術から届かない）。
   押し心地は背景色で返す（枠は増やさない）。 */
.tl-thread-list-items { gap: 0; }
.tl-thread-item {
  position: relative;
  display: flex; gap: 8px; align-items: flex-start; min-width: 0;
  padding: 6px 6px; margin: 0 -6px;            /* 当たりは本文幅いっぱい・見た目は揃える */
  border-radius: 10px;
  animation: tl-fade-in var(--tl-dur-ui) var(--tl-ease);
  transition: background var(--tl-dur-tap) var(--tl-ease);
}
.tl-thread-tap {
  position: absolute; inset: 0; z-index: 0;
  border: 0; background: transparent; padding: 0; margin: 0;
  border-radius: inherit; cursor: pointer;
}
.tl-thread-tap:focus-visible { outline: 2px solid var(--tl-accent-ink); outline-offset: -2px; }
/* リンク・ボタンは重ねたタップ面の上に */
.tl-thread-item > a, .tl-thread-item .tl-thread-col a, .tl-thread-item .tl-thread-col button { position: relative; z-index: 1; }
.tl-thread-item:has(.tl-thread-tap:active) { background: var(--tl-accent-soft); }
@media (hover: hover) and (pointer: fine) {
  .tl-thread-item:has(.tl-thread-tap:hover) { background: rgba(0, 0, 0, 0.04); }
}
.tl-thread-item-pending { opacity: 0.6; }
.tl-thread-item .tl-avatar-tiny { width: 20px; height: 20px; font-size: 9px; flex: 0 0 auto; margin-top: 1px; }
/* 返信: 親の本文列（アバター 20 + gap 8 = 28）に揃える。16 + 線 2 + 10 = 28。
   線は 2px（18px 行では 3px が太すぎた） */
.tl-thread-item-nested { margin-left: 16px; padding-left: 10px; border-left: 2px solid var(--tl-hairline-strong); border-radius: 0 10px 10px 0; }
.tl-thread-col { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tl-thread-head { display: flex; align-items: baseline; gap: 6px; min-width: 0; line-height: 18px; }
.tl-thread-head .tl-thread-name { max-width: 60%; }
.tl-thread-text { font-size: 13px; line-height: 1.5; color: var(--tl-ink-70); overflow-wrap: anywhere; }
.tl-thread-text-clamp {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}
/* コメントへのスタンプ（2026-09-07）。名前の行の右端に 18px の入口、本文の下に小さな帯。
   帯はゲームの帯（.tl-stamps）と同じ器を 24px に縮めたもの = 同じ語彙・違う大きさ。
   0件のときは器だけ（子が無いので高さ0・gap も効かない）。 */
.tl-thread-stamp-plus {
  position: relative; margin-left: auto; flex: 0 0 auto;
  width: 18px; height: 18px; padding: 0; border: 0; background: transparent;
  color: var(--tl-ink-50); cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
}
.tl-thread-stamp-plus svg { width: 14px; height: 14px; }
.tl-thread-stamp-plus::after { content: ''; position: absolute; inset: -6px; }   /* 当たり判定 30px（行の外へは出さない） */
.tl-thread-stamp-plus:active { color: var(--tl-accent-ink); }
@media (hover: hover) and (pointer: fine) {
  .tl-thread-stamp-plus:hover { color: var(--tl-accent-ink); }
}
.tl-stamps-sm { gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.tl-stamps-sm:empty { display: none; }
.tl-stamps-sm .tl-stamp { height: 24px; padding: 0 8px; gap: 3px; }
.tl-stamps-sm .tl-stamp::after { inset: -4px 0; }
.tl-stamps-sm .tl-stamp .tl-stamp-glyph { font-size: 13px; }
.tl-stamps-sm .tl-stamp-users img, .tl-stamps-sm .tl-stamp-users span { width: 14px; height: 14px; font-size: 7px; }

/* 「返信をもっと見る」は返信と同じ段（字下げ + 左線）に置く。当たり判定は上の
   返信（全面タップ）と重ねない: 縦は実寸 + 2px まで（.tl-thread-more の 44px を上書き） */
.tl-thread-more-nested { margin-left: 16px; padding-left: 10px; border-left: 2px solid var(--tl-hairline-strong); }
.tl-thread-more-nested::after { inset: -2px 0; }
.tl-thread-name {
  font-family: var(--tl-font-ui);
  font-weight: 700; color: var(--tl-ink); flex: 0 0 auto;
  max-width: 38%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* プレビューの本文は1行クランプ。長い返信は「続きがある」ことだけ伝われば足りる
   （全文は「コメントN件」/「返信N件」を開く） */
.tl-thread-line .tl-thread-body {
  flex: 1 1 auto; min-width: 0; color: var(--tl-ink-70);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.tl-thread-foot { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* 「コメントN件」は開閉のトグル＝押せる物。枠の無い灰色文字だと、
   隣の「返信する」だけが押せるように見えていた（2026-09-04）。 */
.tl-thread-count {
  position: relative;
  height: 32px; padding: 0 12px; margin: 0 -4px;
  border: 0; border-radius: var(--tl-r-pill);
  background: transparent;
  font-family: var(--tl-font-ui); font-size: 13px; font-weight: 700;
  color: var(--tl-ink); cursor: pointer; white-space: nowrap;
  transition: background var(--tl-dur-tap) var(--tl-ease), color var(--tl-dur-tap) var(--tl-ease), transform var(--tl-dur-tap) var(--tl-ease);
}
.tl-thread-count::after { content: ''; position: absolute; inset: -6px 0; }   /* 当たり判定 44px */
.tl-thread-count:active { transform: translateY(1px); background: var(--tl-accent-soft); color: var(--tl-accent-ink); }
@media (hover: hover) and (pointer: fine) {
  .tl-thread-count:hover { background: var(--tl-accent-soft); }
}

/* 展開したスレッド（1件ずつ全文 + 行動 + ネストした返信） */
.tl-thread-full {
  display: flex; flex-direction: column; gap: 8px;
  padding-top: 8px; border-top: 1px solid var(--tl-hairline);
}
.tl-reply-item {
  display: flex; gap: 8px; align-items: flex-start; min-width: 0;
  animation: tl-fade-in var(--tl-dur-ui) var(--tl-ease);
}
.tl-reply-col { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.tl-reply-meta { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
/* 部品の境は見える線で ＝ 3px（2px は 1px の輪郭と見分けが付かなかった） */
.tl-reply-nested { margin-left: 12px; padding-left: 12px; border-left: 3px solid var(--tl-hairline-strong); }
.tl-reply-item .tl-text { font-size: 13px; line-height: 1.6; color: var(--tl-ink-70); }
.tl-reply-actions { display: flex; align-items: center; gap: 8px; }
/* 押せる文字なので黒 700（2026-09-05・.tl-provenance と同じ規則） */
.tl-thread-more {
  position: relative;
  align-self: flex-start;
  font-size: 11px; font-weight: 700; color: var(--tl-ink);
  background: none; border: none; cursor: pointer;
  padding: 4px 0; font-family: inherit;
  transition: color var(--tl-dur-tap) var(--tl-ease), transform var(--tl-dur-tap) var(--tl-ease);
}
.tl-thread-more::after { content: ''; position: absolute; inset: -14px 0; }   /* 当たり判定 44px */
.tl-thread-more:active { transform: translateY(1px); color: var(--tl-accent-ink); }
@media (hover: hover) and (pointer: fine) {
  .tl-thread-more:hover { color: var(--tl-ink); }
}
.tl-reply-target {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 11px; font-weight: 700; color: var(--tl-ink-70);
}
/* 会話の入力欄。送信ボタンは押し間違えると書いた文が飛ぶので、
   疑似要素で広げず 44px を実寸で確保する。 */
.tl-thread-form { display: flex; gap: 8px; align-items: flex-start; }
/* 入力欄は枠ではなく沈んだ面で示す（枠を全部外した方針の一部）。
   フォーカス時だけインクの輪郭が立ち上がる = 「いまここに書いている」 */
.tl-thread-form textarea {
  flex: 1 1 auto; min-height: 44px; min-width: 0;
  border: 0; background: var(--tl-surface-sunk);
  box-shadow: inset 0 0 0 1px var(--tl-hairline);
  border-radius: var(--tl-r-inner);
  padding: 12px; font: inherit; font-size: 16px;   /* 16px = iOS の自動ズーム回避 */
  line-height: 1.4; resize: vertical;
  color: var(--tl-ink);
  transition: box-shadow var(--tl-dur-ui) var(--tl-ease), background var(--tl-dur-ui) var(--tl-ease);
}
/* フォーカスは 1.5px の二次インク。2px の黒だと入力欄が「黒い箱」になり、
   文字より枠の方が目立つ（2026-09-04 撮影で確認）。 */
/* focus は 2px の二次インク（2026-09-05 採用案）。1.5px は輪郭で組む面の中で
   「太さの3段目」を作ってしまい、どこが入力中なのか一目で決まらなかった。 */
.tl-thread-form textarea:focus {
  outline: none; background: var(--tl-surface);
  box-shadow: inset 0 0 0 2px var(--tl-ink-70);
}
.tl-thread-send { min-height: 44px; padding: 0 16px; flex: 0 0 auto; border-radius: var(--tl-r-pill); }

/* === Bottom sheets（投稿・スタンプ） === */
.tl-sheet-backdrop {
  position: fixed; inset: 0; z-index: var(--tl-z-backdrop);
  background: rgba(23,23,23,0.45);
  opacity: 0; transition: opacity var(--tl-dur-ui) var(--tl-ease);
}
.tl-sheet-backdrop.open { opacity: 1; }
.tl-sheet-backdrop[hidden] { display: none; }
/* 床から伸びる紙。角丸は器と同じ 16px（カードと同じ家族。以前は 20px で
   カード 14px との差が「なんとなく大きい方」でしかなかった） */
.tl-sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--tl-z-sheet);
  margin: 0 auto; max-width: 560px;
  background: var(--tl-surface);
  border-radius: var(--tl-r-container) var(--tl-r-container) 0 0;
  box-shadow: var(--tl-shadow-sheet);
  padding: 8px 16px calc(16px + var(--safe-bottom, 0px));
  transform: translateY(100%);
  transition: transform var(--tl-dur-sheet) var(--tl-ease);
  max-height: 82vh; max-height: 82dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* スクロールバーは出さない（2026-09-06 founder 指摘）。PC ではシートの右端に
     常時バーが立ち、部品の一部に見える。指・ホイールでのスクロールは変わらない。 */
  scrollbar-width: none;
}
.tl-sheet::-webkit-scrollbar { display: none; }
.tl-sheet.open { transform: translateY(0); }

.tl-sheet[hidden] { display: none; }
/* つまみは 44x5（指1本ぶんの幅）。40x4 は「線」に見えて掴めるものに見えなかった */
.tl-sheet-grip {
  width: 44px; height: 5px; border-radius: var(--tl-r-pill);
  background: var(--tl-hairline-strong); margin: 4px auto 12px;
}
.tl-sheet-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-bottom: 12px;
}
.tl-sheet-title { font-family: var(--tl-font-ui); font-size: 17px; font-weight: 800; letter-spacing: -0.01em; }
/* 当たり判定 44x44、見た目は内側の 32px の丸（tl-sheet-close-mark） */
.tl-sheet-close {
  border: 0; background: none; padding: 0;
  width: 44px; height: 44px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; font-family: inherit;
  transition: transform var(--tl-dur-tap) var(--tl-ease);
}
.tl-sheet-close:active { transform: scale(0.96); }
/* 沈んだ丸（戻るボタン・style.css の .search-btn と同じ語彙） */
.tl-sheet-close-mark {
  width: 32px; height: 32px; border-radius: 50%;
  border: 0; background: var(--tl-surface-sunk);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 16px; line-height: 1; color: var(--tl-ink-50);
}

/* Stamp picker */
.tl-stamp-groups { display: flex; flex-direction: column; gap: 16px; }
.tl-stamp-group-label {
  font-family: var(--tl-font-ui);
  font-size: 12px; font-weight: 700; letter-spacing: 0;
  text-transform: none; color: var(--tl-ink-50); margin-bottom: 8px;
}
/* 升の間隔 4 → 8px（2026-09-04 QA・finding 5）。帯のチップと同じ理由 —
   44px の升が 4px 隣接していると、押したい絵と隣の絵の境目が指の幅より細い。 */
.tl-stamp-grid {
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px;
}
/* 320px 級（iPhone SE 1st / Galaxy Fold の折り畳み時）では 8 列は成立しない:
   シートの内側は 320 - 16*2 = 288px、gap を 8px にすると升は
   (288 - 7*8) / 8 = 29px 幅 = 高さ 44（min-height）に対して細すぎる縦長になる。
   6 列なら (288 - 5*8) / 6 = 41.3px 幅で、min-height 44px とほぼ正方に収まる。
   行数は増えるがシートは縦スクロールするので溢れない（横は 1fr なので常に不発生）。 */
@media (max-width: 359px) {
  .tl-stamp-grid { grid-template-columns: repeat(6, 1fr); }
}
.tl-stamp-cell {
  /* 升も「沈んだ部品」（帯のスタンプと同じ語彙）。border は透明のまま残す
     ＝ 枠の太さで升の寸法が動かない（下の aspect-ratio の WHY と同じ理由）。 */
  border: 1px solid transparent; background: var(--tl-surface-sunk);
  box-shadow: inset 0 0 0 1px var(--tl-hairline);
  border-radius: var(--tl-r-pill);
  /* 縦の 44px は死守（指の下限）。横は列に合わせて縮んでよい。
     aspect-ratio: 1/1 を外した理由（2026-09-04 QA・finding 5 で発覚した既存の
     溢れ。gap 4px の頃から出ていて、8px にして表面化した）:
     aspect-ratio と min-height:44px が組むと、升の**使用幅**が高さから
     44px に引き戻される。8 列では 44*8 + 8*7 = 408px となり、375px 画面の
     シート内側 343px を 65px はみ出して、右端の列が指の届かない場所へ出ていた。
     min-width:0 だけではトラック（1fr = 35.9px）が縮むだけで升自身は 44px の
     まま残り、8px ぶん溢れ続ける（実測）。比率を外すと升は
     トラック幅 x 44px に収まり、横溢れが構造的に起きなくなる。 */
  min-height: 44px; min-width: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 20px; cursor: pointer; font-family: inherit;
  transition: background var(--tl-dur-tap) var(--tl-ease), box-shadow var(--tl-dur-tap) var(--tl-ease),
              transform var(--tl-dur-tap) var(--tl-ease);
}
/* 押下は沈む（scale(0.9) は「部品が縮む」表現なので廃止） */
.tl-stamp-cell:active { transform: translateY(1px); }
.tl-stamp-cell.mine {
  border-color: transparent; background: var(--tl-accent-soft);
  box-shadow: inset 0 0 0 2px var(--tl-accent);
}
@media (hover: hover) and (pointer: fine) {
  .tl-stamp-cell:hover { background: var(--tl-accent-soft); }
}
.tl-stamp-loading { text-align: center; color: var(--tl-ink-50); font-size: 13px; padding: 24px 0; }

/* Toast */
.tl-toast {
  position: fixed; left: 50%;
  bottom: calc(var(--bottom-nav-reserved-space, 72px) + 16px);
  transform: translateX(-50%);
  background: rgba(23,23,23,0.92); color: #fff;
  padding: 10px 18px; border-radius: var(--tl-r-pill);
  font-family: var(--tl-font-ui); font-size: 13px; font-weight: 700;
  opacity: 0; pointer-events: none;
  transition: opacity var(--tl-dur-sheet) var(--tl-ease); z-index: var(--tl-z-toast);
  box-shadow: var(--tl-shadow-raised);
}
.tl-toast.show { opacity: 1; }
.tl-toast.show.is-tappable { pointer-events: auto; }

a.tl-profile-link { color: inherit; text-decoration: none; }
/* アバターを包むリンク **だけ** を inline-flex にする（2026-09-04 リデザインで実測）。
   素の <a>（inline）はテキストのベースラインに乗るので、中の 24px アバターの下に
   ディセンダ分の隙間ができ、.tl-card-head が 24px ではなく 28.5px になっていた。
   しかもそれが起きるのは **アバターが <img> の人だけ**（頭文字のフォールバックは
   24px のまま）＝ カードの高さが「その人がアイコンを設定しているか」というデータで
   4.5px 揺れていた。inline-flex にすると行箱がベースラインから外れ、全カードの
   ヘッダが 24px に揃う。prependFreshEvents のスクロール補正は「種類ごとに高さが
   決まっている」ことが前提なので、揺れは無い方が正しい。

   WHY [aria-hidden="true"] で絞るか（全 .tl-profile-link に当てない）:
   名前を包む方のリンクにも当てたら、中の .tl-name（max-width: 42%）の基準幅が
   リンク自身の縮んだ幅に変わり、「こはる」が「こ.」まで潰れた（撮影で発覚）。
   装飾リンク＝アバター用は wrapProfileLink が aria-hidden を付けているので、
   この属性が「中身が画像1枚だけのリンク」の目印になる。 */
a.tl-profile-link[aria-hidden="true"] { display: inline-flex; align-items: center; flex: 0 0 auto; }
@media (hover: hover) and (pointer: fine) {
  a.tl-profile-link:hover .tl-name,
  a.tl-profile-link:hover .tl-thread-name { text-decoration: underline; }
}

/* 右レール。丸 44px の縦積み（当たり判定は実寸そのもの ＝ 密度より確実さ）。 */
.tl-reel-rail {
  position: absolute; right: 12px; bottom: 16px;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
}
.tl-reel-btn {
  position: relative;
  width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: 0; background: rgba(0,0,0,0.42); color: #fff;
  cursor: pointer;
  transition: transform var(--tl-dur-tap) var(--tl-ease), background var(--tl-dur-tap) var(--tl-ease);
}
.tl-reel-btn svg { width: 22px; height: 22px; }
.tl-reel-btn:active { transform: scale(0.94); }
.tl-reel-btn.is-on { background: var(--tl-accent-ink); }
/* レールは最大 6 つ（スタンプ / コメント / ブックマーク / リミックス / 情報 / 音）。
   44px × 6 + 12px × 5 = 324px。足元の題名・「あそぶ」（左）と取り合わないよう、
   レールは右 12px の縦積みのまま。間隔は 14 → 12（6 つでも 375×812 の下半分に収まる） */

/* 動画のコメントのシート（2026-09-08）。会話ブロックはカードの中の寸法（14px 本文・
   22px の行）をそのまま使う。シートの最大高は .tl-sheet の既定（82dvh）で、
   長い会話はシートの中でスクロールする */
.tl-reel-sheet .tl-sheet-title {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
.tl-reel-sheet-body { padding: 0 0 16px; }   /* 横は .tl-sheet の 16px に任せる */

.tl-reel-sheet-body .tl-thread { border-top: 0; margin-top: 0; padding-top: 0; }
/* 2026-09-20 削除: .tl-reel-info-card（PR #907 レビュー B [中9]）。
   情報シートの中身は 2026-09-18 に game-social/game-info.js の共有パネル（.info-* / game-info.css）へ
   置き換わり、カードの殻を借りる形は消えた（public/ 全体で 0 件を確認）。
   使われない規則を残すと、次に情報シートを触る人が「ここを直せば効く」と読んで空振りする。

   .tl-reel-info-actions は残す。共有パネルの部品（game-info.js）を読めなかった回に
   game-thread.js が出す**縮退のパネル**（題名・作者・あそぶ・Remix）の行がこれを使う
   —— 部品が落ちている以上 game-info.css も来ていないので、縮退側は
   この 1 枚（game-social.css）の中だけで組む必要がある（[中21]）。 */
.tl-reel-info-actions { display: flex; align-items: center; gap: 12px; margin-top: 14px; }
.tl-reel-info-actions .tl-btn.primary { min-height: 44px; padding: 0 22px; }

.tl-reel-play-bar {
  position: absolute; left: 0; right: 0; top: 0; z-index: 7;
  min-height: var(--tl-reel-topbar-h);
  padding: calc(8px + var(--page-safe-top, var(--safe-top, 0px))) 16px 8px;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  background: var(--tl-surface, #fff); border-bottom: 1px solid var(--tl-hairline-strong);
  box-sizing: border-box;
}
.tl-reel-topbar-back, .tl-reel-topbar-btn {
  width: 36px; height: 36px; border-radius: 50%; border: 0;
  background: var(--tl-surface-sunk); color: var(--tl-ink);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  transition: transform var(--tl-dur-tap) var(--tl-ease), background var(--tl-dur-tap) var(--tl-ease);
}
.tl-reel-topbar-btn { color: var(--tl-ink-70); }
.tl-reel-topbar-back:active, .tl-reel-topbar-btn:active { transform: scale(.96); }
.tl-reel-topbar-btn svg { width: 18px; height: 18px; }
.tl-reel-topbar-btn.is-on { background: var(--tl-accent-ink); color: #fff; }
.tl-reel-topbar-actions { display: flex; align-items: center; gap: 4px; }

.tl-reel-rail { z-index: 8; }

/* 押せるトースト（名前入力 → 作ろう）。押せることは下線で言う */
.tl-toast.is-tappable { cursor: pointer; text-decoration: underline; text-underline-offset: 3px; }

/* ── reduced-motion（このファイルの規則ぶん）───────────────────────
   timeline.html 末尾の1ブロックから、ここへ移した規則の分だけを持ってきた。
   規則本体と同じファイルに置く＝片方だけ直して止め忘れる事故を防ぐ。
   動きを止めても状態が読めること、が条件。消すのは「変化を見せるための動き」
   だけで、色・位置・枠は動かさない。 */
@media (prefers-reduced-motion: reduce) {
  .tl-sheet, .tl-sheet-backdrop { transition: none; }
  /* 入場・反応の動きも止める。both を付けているので、animation:none にすると
     最終状態（opacity 1 / translateY 0）で即座に出る＝1枚も欠けない。 */
  .tl-card,
  .tl-reply-item,
  .tl-thread-line, .tl-thread-item,
  .tl-clears-line,
  .tl-stamp.tl-stamp-pop,
  .tl-stamp.tl-stamp-pop .tl-stamp-users > :first-child,
  .tl-stamp-plus.tl-seat-pulse {
    animation: none;
  }
  /* 押下の変形も止める。押した手応えは、淡赤の面と輪郭・段差が引き受ける
     （2026-09-05 採用案の §4: 動きだけ止め、輪郭・段差・色は残す） */
  /* 詳細度は基底と同じか上に揃えること（2026-09-05）。基底には
     `.tl-btn.primary:active` / `.tl-stamp.mine:active` / `a.tl-chip-link:active`
     のように 2 クラス以上・要素付きの規則があり、ここに1クラスの形だけを
     並べると **その3つだけ動きが止まらない**。 */
  .tl-btn:active, .tl-btn.primary:active,
  .tl-card-thumb:active,
  .tl-strip-btn:active, .tl-stamp:active, .tl-stamp.mine:active,
  .tl-stamp-plus:active, .tl-stamp-add:active, .tl-stamp-cell:active,
  .tl-thread-count:active,
  a.tl-chip-link:active, .tl-sheet-close:active,
  .tl-thread-more:active,
  /* 動画タブ（2026-09-06） */
  .tl-reel-btn:active {
    transform: none;
  }
}

/* ══════════════════════════════════════════════════════════════════════
   フィードの中の「遊び終えた後」の表示（2026-09-18 フェーズ 1・計画書
   .claude/plans/feed-game-page-parity.md）

   ゲームページ（public/game.html）はこれらの見た目をインライン <style> に持っている。
   game.html は game-social.css を読まないので、ここは**その写しではなく、フィード用の置き場と
   フィード用の寸法だけ**を持つ（中身の語彙 — 色・角丸・字の大きさ — は game.html と揃えてある）。
   すべて `.dcf-item`（フィードの 1 枠）の下に閉じ込める: この CSS はタイムラインも読むので、
   閉じ込めないと別の面の .xp-card に当たる。
   ══════════════════════════════════════════════════════════════════════ */

/* ── プレイ XP の終了後カード（game-social/xp-card.js が枠ごとに組み立てる）──────────
   置き場は **表紙の外**（renderChrome と同じ層 = .dcf-item 直下）。次の本へスワイプすれば
   枠ごと視界から消えるので、時間では消さない（2026-09-17 founder「完了の知らせは時間で消さない」）。
   z-index 6 = 舞台（.dcf-stage 5）の上・掴み帯（.dcf-strip 7）の下。帯より下に置くのが要点で、
   上に重ねるとカードが「次へ」の掴みどころを塞ぐ（founder 裁定「次へを邪魔しない」）。 */
.dcf-item .xp-card {
  position: absolute;
  left: 50%;
  /* 掴み帯のすぐ上。帯の高さは枠が --dcf-strip で持っている（game-feed.js の CSS） */
  bottom: calc(var(--dcf-strip, 0px) + 10px);
  transform: translateX(-50%) translateY(120%);
  z-index: 6;
  opacity: 0;
  pointer-events: none;
  /* 右レール（.dcf-chrome）は右端に居るので、その幅ぶん内側に収める */
  width: calc(100% - 88px);
  max-width: 360px;
  transition: transform .4s cubic-bezier(.34, 1.2, .64, 1), opacity .3s ease-out;
}
.dcf-item .xp-card[hidden] { display: none; }
.dcf-item .xp-card.visible { transform: translateX(-50%) translateY(0); opacity: 1; pointer-events: auto; }
.dcf-item .xp-card.hiding { transform: translateX(-50%) translateY(120%); opacity: 0; }
.dcf-item .xp-card-inner {
  display: flex;
  align-items: center;
  gap: 12px;
  background: rgba(20, 20, 20, .92);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 14px;
  padding: 12px 14px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, .4);
}
.dcf-item .xp-card-ring { position: relative; width: 44px; height: 44px; flex-shrink: 0; display: block; text-decoration: none; color: inherit; }
.dcf-item .xp-card-ring svg { width: 44px; height: 44px; transform: rotate(-90deg); } /* 12 時方向から時計回りに満ちる */
.dcf-item .xp-ring-bg { fill: none; stroke: rgba(255, 255, 255, .14); stroke-width: 3; }
.dcf-item .xp-ring-fg { fill: none; stroke: var(--red-ink, #E60012); stroke-width: 3; stroke-linecap: round; transition: stroke-dashoffset .6s ease-out; }
.dcf-item .xp-card-level { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 12px; font-weight: 700; letter-spacing: -.02em; }
.dcf-item .xp-card.leveled .xp-card-level { font-size: 13px; color: #FFD34D; } /* 昇格した回だけ金色 */
.dcf-item .xp-card-body { flex: 1; min-width: 0; }
.dcf-item .xp-card-gain { color: #fff; font-size: 17px; font-weight: 700; line-height: 1.2; }
.dcf-item .xp-card-gain[hidden] { display: none; }
.dcf-item .xp-card-sub { color: rgba(255, 255, 255, .72); font-size: 12px; line-height: 1.35; margin-top: 2px; }
.dcf-item .xp-card-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.dcf-item .xp-card-chips:empty { display: none; }
.dcf-item .xp-card-chip { font-size: 10px; font-weight: 700; line-height: 1; padding: 4px 7px; border-radius: 999px; background: rgba(255, 255, 255, .12); color: #fff; }
.dcf-item .xp-card-chip.bonus { background: rgba(230, 0, 18, .85); }
.dcf-item .xp-card-chip.extra { background: rgba(255, 211, 77, .9); color: #1a1a1a; }
.dcf-item .xp-card-make { display: inline-block; margin-top: 6px; color: #FFD34D; font-size: 12px; font-weight: 700; line-height: 1.3; text-decoration: underline; }
.dcf-item .xp-card-make[hidden] { display: none; }
.dcf-item .xp-card-board { display: flex; gap: 5px; margin-top: 7px; }
.dcf-item .xp-card-board[hidden] { display: none; }
.dcf-item .xp-card-board-dot { width: 10px; height: 10px; border-radius: 999px; background: rgba(255, 255, 255, .16); }
.dcf-item .xp-card-board-dot.reward { box-shadow: inset 0 0 0 1px #FFD34D; }
.dcf-item .xp-card-board-dot.filled { background: var(--red-ink, #E60012); box-shadow: none; }
.dcf-item .xp-card-cta { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; padding: 8px 12px; border-radius: 999px; background: #fff; color: #1a1a1a; font-size: 12px; font-weight: 700; text-decoration: none; max-width: 108px; text-align: center; line-height: 1.2; }

/* ── 起動失敗の親側表示 + 自動修復（runtime-repair-client.js の受け皿）────────────
   舞台（.dcf-stage）いっぱいに被せる。ページ全体はリロードしない = フィードを捨てない
   （timeline.js の .tl-reel-runtime-error と同じ考え方）。 */
.dcf-runtime-error {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 24px;
  box-sizing: border-box;
  text-align: center;
  background: rgba(13, 13, 15, .92);
  color: #fff;
  font-family: inherit;
}
.dcf-runtime-error-title { font-size: 16px; font-weight: 700; line-height: 1.3; }
.dcf-runtime-error-message { font-size: 13px; line-height: 1.5; color: rgba(255, 255, 255, .78); max-width: 320px; }
.dcf-runtime-error-actions { display: flex; gap: 8px; margin-top: 6px; flex-wrap: wrap; justify-content: center; }
.dcf-runtime-error-btn { appearance: none; border: 0; border-radius: 9999px; padding: 10px 20px; background: rgba(255, 255, 255, .16); color: #fff; font-size: 14px; font-weight: 700; cursor: pointer; font-family: inherit; }
.dcf-runtime-error-btn.primary { background: #fff; color: #111; }

@media (prefers-reduced-motion: reduce) {
  /* 動きに敏感な人には静止で出す（game.html と同じ配慮）。opacity だけで出し入れする */
  .dcf-item .xp-card,
  .dcf-item .xp-card.visible,
  .dcf-item .xp-card.hiding { transform: translateX(-50%); transition: opacity .2s linear; }
  .dcf-item .xp-ring-fg { transition: none; }
}

/* ══════════════════════════════════════════════════════════════════════
   情報シートの残り + コメントの画像添付（2026-09-18・フェーズ5）
   計画書: .claude/plans/feed-game-page-parity.md
   markup は game-social/game-info.js（遊び方 / タグ / 系譜 / 所有者）と
   game-social/game-thread.js（入力欄の画像）。
   値はゲームページの情報パネル（game.html の .info-*）に合わせてある —— 面の地色が違う
   （ゲームページ = 明るいパネル / フィード = 暗い上のカード）ので、色だけ tl-* の流儀に置き換えた。
   ══════════════════════════════════════════════════════════════════════ */

.tl-info-extra:empty,
.tl-info-owner-slot:empty { display: none; }

.tl-info-row { margin-top: 12px; }
/* 見出しは「遊び方」「タグ」。小さく・薄く・字間を開ける = game.html の .info-section-title と同じ役目 */
.tl-info-row-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  opacity: .55;
  margin-bottom: 5px;
}
/* 作者が書いた改行を保つ（game.html の .info-how-to-play と同じ）。
   pre-line にするのは pre-wrap と違って行頭の字下げを畳むから = 生成文の余分な空白で崩れない */
.tl-info-howto {
  font-size: 13px;
  line-height: 1.6;
  white-space: pre-line;
  word-break: break-word;
}

.tl-info-tags { display: flex; flex-wrap: wrap; gap: 6px; }
/* タグは押すとそのタグのフィードへ（/games/<tag>）。見た目はお題チップ（.tl-chip-link）を継ぐ */
.tl-info-tag { text-decoration: none; }

/* 系譜。件数は後から入る（fetchLineageCount）ので、来る前でも行の高さが変わらないよう inline-flex */
.tl-info-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin-top: 12px;
  font-size: 13px;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.tl-info-lineage-count { opacity: .6; font-weight: 500; }
.tl-info-lineage-count[hidden] { display: none; }

/* 所有者だけの行。上に細い仕切りを引いて「ここから先は自分だけに見えている」を示す */
.tl-info-owner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(127, 127, 127, .22);
}
.tl-info-owner-edit { text-decoration: none; }
/* 依頼済み・満席・券切れ（is-requested）は押せない。押せないことが見て分かるよう薄くする */
.tl-info-owner-review.is-requested,
.tl-info-owner-review:disabled { opacity: .55; cursor: default; }
.tl-info-owner-hint {
  flex-basis: 100%;
  margin: 0;
  font-size: 11px;
  line-height: 1.5;
  opacity: .6;
}
.tl-info-owner-hint[hidden] { display: none; }

/* ── コメントに添える画像 ─────────────────────────────────────────── */
/* 入力欄の上に 1 枚 + ×（ゲームページのゲストブック #commentImagePreview と同じ置き方） */
.tl-thread-image-preview {
  position: relative;
  display: inline-block;
  margin: 8px 0 0;
  max-width: 140px;
}
.tl-thread-image-preview img {
  display: block;
  width: 100%;
  max-height: 120px;
  object-fit: cover;
  border-radius: 8px;
}
.tl-thread-image-remove {
  position: absolute;
  top: -6px;
  right: -6px;
  width: 22px;
  height: 22px;
  border: 0;
  border-radius: 999px;
  background: rgba(0, 0, 0, .72);
  color: #fff;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  font-family: inherit;
}
/* 添付ボタンは送信ボタンの反対側（入力欄の左）。丸い当たり判定を 32px 確保する */
.tl-thread-image-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: inherit;
  opacity: .7;
  cursor: pointer;
  font-family: inherit;
}
.tl-thread-image-btn:disabled { opacity: .35; cursor: default; }
