/* TomoZine — 紹介ページ（LP）専用スタイル。
 *
 * `style.css`（privacy / support の文書用）とは別物。LP は**それ自体が漫画**として読める意匠にする。
 *
 * ■ 黒地（2026-07-30 変更）
 *   アプリの中は紙白のままだが、**LP は黒を基調**にした。黒地に白い紙のコマが浮くほうが
 *   コマの輪郭が強く出て、「ポンポンとコマが生まれる」ヒーローの動きが見える。
 *   紙が出るのは①コマ ②表紙 ③奥付の1ページだけ。
 *
 * ■ 外部リクエストは1本も持たない（`site/README.md` と同じ拘束）
 *   書体は `site/fonts/` に**同梱**（Latin サブセット・計116KB・SIL Open Font License）。
 *   画像は0枚（網点・集中線・表紙・コマ枠はすべてCSS）。CDN/解析/外部画像を足すと
 *   `privacy.html` の「持たないこと」が嘘になる。
 *   **唯一の例外は `data-prelaunch-only` の Sharaku 紹介写真**（`site/sharaku.jpg`・同梱・
 *   外部CDNではない）。本番公開時にその要素ごと消える＝「画像0枚」は公開後に復元される
 *   （下の「公開状態トグル」参照）。
 *
 * ■ 公開状態トグル（2026-08-17）
 *   公開前はウェイトリスト登録ページとして運用する。`<html>` に `launch` クラスが
 *   付くまでは `[data-launch-only]` を隠し `[data-prelaunch-only]`（Sharaku紹介＋
 *   登録フォーム）を出す。**本番公開の手順は `<html lang="en" class="launch">` と
 *   1クラス足すだけ**——ToU/Privacy等の法的リンクと実際の "Get the app" が現れ、
 *   ウェイトリスト側は自動で消える。詳細は下のトグル定義のコメント参照。
 *
 * ■ 動きは全部止められる
 *   `prefers-reduced-motion: reduce` で、ヒーローのポップ・集中線・
 *   表紙の横流れをすべて停止する（止めても情報は全部読める状態を保つ）。
 *
 * ■ モバイルファースト（CLAUDE.md）: ベース値は狭い画面向け、`clamp()` で大画面へ広げる。
 */

/* ── 書体（同梱・Latin サブセットのみ）───────────────────────────────── */

/* 見出し・効果音 */
@font-face {
  font-family: 'Reggae One';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/reggae-one-400.woff2') format('woff2');
}
/* 本文（丸ゴシック＝アプリ既定） */
@font-face {
  font-family: 'Zen Maru Gothic';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/zen-maru-gothic-500.woff2') format('woff2');
}
@font-face {
  font-family: 'Zen Maru Gothic';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/zen-maru-gothic-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Zen Maru Gothic';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url('fonts/zen-maru-gothic-900.woff2') format('woff2');
}
/* 棚の見出し（明朝＝アプリの SERIF と同じ） */
@font-face {
  font-family: 'Zen Old Mincho';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/zen-old-mincho-700.woff2') format('woff2');
}
/* フキダシの中（手書き＝ひとりごとの声） */
@font-face {
  font-family: 'Klee One';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/klee-one-400.woff2') format('woff2');
}

/* ── トークン ────────────────────────────────────────────────────── */

:root {
  color-scheme: dark;

  /* **黒は色を持たない**（2026-08-13）。以前は #0b0b0c / #16161a と青紫側へわずかに
     倒していたが、その冷たい黒に淡い点を敷くと、コマの無い**画面の隅が紫がかって光る**
     ——BeReal のサイトの署名がまさにそれ（黒地＋隅の淡い紫）なので、寄せない。
     地は完全な無彩色にし、点のほうは紙の白（`--chalk` ＝ 少し暖かい白）で敷く。
     暖色側に振っておけば、どう霞んでも紫にはならない。**隅を光らせる装飾は持たない**。 */
  --void: #0b0b0b;
  --paper: #ffffff;
  --ink: #111111;
  --chalk: #f5f3ee;
  --chalk-soft: #a9a7a1;
  --edge: rgba(255, 255, 255, 0.16);

  /* 黒地の上では、影は「紙が浮いている」白のオフセットにする。 */
  --lift-sm: 3px 3px 0 rgba(255, 255, 255, 0.22);
  --lift: 5px 5px 0 rgba(255, 255, 255, 0.26);

  --body: 'Zen Maru Gothic', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  --display: 'Reggae One', 'Zen Maru Gothic', Impact, sans-serif;
  --serif: 'Zen Old Mincho', Georgia, 'Times New Roman', serif;
  --hand: 'Klee One', 'Zen Maru Gothic', 'Segoe UI', sans-serif;

  --frame: 3px;

  /* ── 余白の目盛り（2026-08-10）──────────────────────────────────
   * **余白は3段しか持たない。** 節と節=L / 要素群の間=M / ブロック内=S。
   * 途中の数字（1.4rem・1.6rem・1.8rem・2.2rem…）を各所で個別に決めるのをやめる。
   * 個別に決めていると、画面が広がったときに詰まる場所と空きすぎる場所が混ざり、
   * 「余裕がある」ではなく「散らかっている」に見える。
   *
   * `.sec` の上下パディングは M なので、**隣接する節の間は自動的に 2M** になる
   * （大画面では 2M = 128px = L と一致する。狭い画面では L のほうが小さい＝
   *   モバイルで節間が空きすぎないように、L の下限を意図的に低く取ってある）。
   * だから節の区切り線は要らない（線でなく余白で分ける）。
   * モバイルファースト（CLAUDE.md）なので下限がモバイル値・上限が大画面値。 */
  --space-s: clamp(1.5rem, 5vw, 2rem);   /* 24 → 32 */
  --space-m: clamp(2rem, 8vw, 4rem);     /* 32 → 64 */
  --space-l: clamp(3rem, 13vw, 8rem);    /* 48 → 128（= 2M） */
  --pad-x: clamp(1.5rem, 5vw, 4rem);     /* 外周 24 → 64 */

  /* ── 文字の大きさ（見出し / リード / 本文 の3段）───────────────────
   * **大画面でも見出しは上限で止める。** 器（`.sec` の max-width）と絵だけが伸び、
   * 字は伸びない。上限を止めないと、広い画面で見出しだけが暴れて上の目盛りが効かなくなる。
   * ※ヒーロー中央の `h1` だけはこの段に乗らない——あれは黒いコマの中の一言で、
   *   小さく保つこと自体が意匠（CLAUDE.md「主役はコマ」）。 */
  --fs-display: clamp(1.7rem, 7.5vw, 2.6rem);
  --fs-lede: clamp(1.02rem, 4.2vw, 1.2rem);
  --fs-small: 0.85rem;
  --fs-label: 0.72rem;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

/* ── 公開状態トグル ──────────────────────────────────────────────
   既定（<html> に "launch" が無い状態）＝ウェイトリスト版。
   本番公開の手順は <html lang="en" class="launch"> と1クラス足すだけ。
   HTML 側の要素はどちらも常に存在し、消したり作り替えたりしない——
   出し分けはこの2行だけが担う。 */
html:not(.launch) [data-launch-only] { display: none; }
html.launch [data-prelaunch-only] { display: none; }

body {
  margin: 0;
  background-color: var(--void);
  /* 黒地の網点。点は**紙の白（暖色寄り）**で敷く——純白だと点の霞が青紫に見える。 */
  background-image: radial-gradient(rgba(245, 243, 238, 0.09) 1px, transparent 1.15px);
  background-size: 6px 6px;
  color: var(--chalk);
  font-family: var(--body);
  font-weight: 500;
  font-size: clamp(15px, 4vw, 17px);
  line-height: 1.7;
  -webkit-text-size-adjust: 100%;
  overflow-x: hidden;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--paper);
  color: var(--ink);
  padding: 0.6rem 1rem;
  z-index: 50;
}
.skip:focus { left: 0; }

:focus-visible {
  outline: 3px solid var(--paper);
  outline-offset: 3px;
}

/* ── ヘッダ（黒い細い帯・上に固定）───────────────────────────────── */

.mast {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7rem;
  row-gap: 0.5rem;
  /* マークの左端を、節の本文の左端に合わせる（広い画面では中央寄せの器に食い込ませる）。
     器より狭い画面では max() が外周の `--pad-x` を選ぶので、モバイルは今までどおり。 */
  padding: 0.55rem max(var(--pad-x), (100% - 62rem) / 2 + var(--pad-x));
  background: rgba(11, 11, 11, 0.92);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid var(--edge);
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--display);
  font-size: clamp(1.1rem, 5vw, 1.35rem);
  line-height: 1;
  color: var(--chalk);
  text-decoration: none;
  white-space: nowrap;
}

/* アプリと同じマーク（斜めに割れた2コマ＋フキダシ2つ）。 */
.mark {
  display: block;
  width: clamp(24px, 7vw, 30px);
  height: auto;
  border-radius: 6px;
  /* 黒地にマークの黒が沈むので、紙の縁を1本足す。 */
  outline: 1.5px solid rgba(255, 255, 255, 0.5);
}

.mast .cta { margin-left: auto; }

/* ヘッダ右上のウェイトリストフォーム(2026-08-17)。`.waitlist-form` の基本ルール
   (入力欄の見た目・.cta・.form-status)はそのまま使い、置き方だけをここで上書きする。
   374px 前後の幅ではワードマークと並ばないので、`.mast` の flex-wrap で次の行へ落ちる
   (sticky ヘッダなので折り返しても常に画面内)。
   ※セレクタは `.waitlist-form.waitlist-form--mast` と2クラス重ねて詳細度を上げる
   （`.waitlist-form input[type="email"]` と単クラス同士だと詳細度が同点になり、
   ファイル中で後に出るほう＝下の基本ルールに負けて上書きが効かなかった実例あり）。 */
.waitlist-form.waitlist-form--mast {
  margin: 0 0 0 auto;
  max-width: none;
  flex: 1 1 18rem;
  justify-content: flex-end;
}
.waitlist-form.waitlist-form--mast input[type="email"] {
  flex: 1 1 8rem;
  min-width: 0;
  max-width: 16rem;
  padding: 0.45rem 0.7rem;
  font-size: 0.88rem;
}
.waitlist-form.waitlist-form--mast .cta {
  margin-left: 0;
  padding: 0.5rem 0.9rem;
  font-size: 0.85rem;
  white-space: nowrap;
}
.waitlist-form.waitlist-form--mast .form-status {
  text-align: right;
  font-size: 0.78rem;
}

/* ── ボタン（黒地の上の白いシール）──────────────────────────────── */

/* **ボタンは1種類しか持たない**（2026-08-10）。以前はヒーローが `.cta`・締めが
   `.cta--big` と大きさが違ったが、種類が2つあると「こっちが本命」という序列が生まれ、
   ページのどこを見ればいいのかが1つに定まらなくなる。行き先は1つ（Google Play）なので
   見た目も1つ。置かれた白いシールに見えるよう、静止状態から紙の浮きを持たせる。 */
.cta {
  display: inline-block;
  padding: 0.72rem 1.35rem;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-weight: 900;
  font-size: 1rem;
  line-height: 1.2;
  text-decoration: none;
  border: 2px solid var(--paper);
  border-radius: 2px;
  box-shadow: var(--lift-sm);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.cta:hover { transform: translate(-1px, -1px); box-shadow: var(--lift); }
.cta:active { transform: translate(2px, 2px); box-shadow: none; }

.cta-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7rem 1rem;
  margin: var(--space-m) 0 0;
}

/* ── 節 ───────────────────────────────────────────────────────── */

/* 上下は M。**隣り合う節の間はこれで自動的に 2M（= L）**になるので、
   節の区切り線は持たない（線で割らず、余白で割る）。 */
.sec {
  position: relative;
  max-width: 62rem;
  margin: 0 auto;
  padding: var(--space-m) var(--pad-x);
}

.sec-no {
  display: inline-block;
  font-family: var(--display);
  font-size: var(--fs-label);
  line-height: 1;
  padding: 0.32rem 0.48rem 0.28rem;
  background: var(--paper);
  color: var(--ink);
  margin-bottom: var(--space-s);
}

h2 {
  font-family: var(--serif);
  font-weight: 700;
  font-size: var(--fs-display);
  line-height: 1.14;
  margin: 0;
  color: var(--chalk);
  text-wrap: balance;
}

h3 {
  font-family: var(--body);
  font-weight: 900;
  font-size: 0.98rem;
  margin: 0;
}

p { margin: 0.9rem 0; }

/* 見出しの直後の1段落。**行の切れ目は `<br class="br-md">` で手で決める**（広い画面のみ）。
   ブラウザの折り返し任せだと、意味の途中で折れたり最終行に1語だけ残ったりする。
   ここはコピーとして読ませる場所なので、コマのフキダシ（`lettering.ts`）と同じ考え方で
   組みを人が決める。手で切る行があるので `text-wrap: balance` は当てない。 */
.sec-lede {
  margin: var(--space-s) 0 0;
  font-size: var(--fs-lede);
  max-width: 30em;
  color: var(--chalk);
}

/* 広い画面でだけ効く手動の改行。狭い画面では自動折り返しに任せる
   （固定すると 375px で行があふれる）。 */
.br-md { display: none; }

/* **実機モック付きの節（現在の02〜04）の側では、手動の行は一切効かせない**（2026-08-13）。
   あの3行はフキダシの中に入った（`.koma`）ので、使える幅が列幅 444px ではなく
   フキダシの内側（≒318px）になる。手で切った行がさらに自動で折り返して
   「3行のつもりが6行」になり、手で組んだ意味が消えるどころか読みにくくなる。
   列はこれ以上広がらない（節が max-width に達している）ので、待っても効く幅は来ない。
   フキダシの中は自動折り返しの中央寄せ＝ラギッドな組みに任せる。
   ※このコメントは元々「01〜03」「04」という旧ナンバリング（2026-08-13の並べ替え前、
   コンセプト節が最後の04だった）で書かれていた。現在は02〜04が実機モック付きで、
   01（2026-08-14からコマ2つの `.row--split`）は `.row-text` を使わないので
   このルールの対象外——`.br-md` はそのまま効く。 */
.row-text .br-md { display: none; }

.small { font-size: var(--fs-small); color: var(--chalk-soft); }

em { font-style: normal; font-weight: 700; }

a { color: var(--chalk); text-decoration: underline; text-underline-offset: 0.22em; }

/* ── ヒーロー: 画面いっぱいのコマ＋真ん中に一言 ─────────────────── */

.hero {
  position: relative;
  /* ヘッダの高さ分を引く。 */
  min-height: calc(100vh - 3.6rem);
  min-height: calc(100svh - 3.6rem);
  display: grid;
  place-items: center;
  overflow: hidden;
  padding: clamp(4rem, 14vw, 7rem) clamp(1.1rem, 5vw, 2rem);
}

/* コマ全体を少しだけ落として背景に回す（一様に。丸く暗くすると紙の上では“染み”に見える）。
   加えて **下端だけ黒へ落とす**（2026-08-10）。上半分は完全に透明で、下半分で地の黒へ沈む。
   こうすると原っぱが画面の下辺で「切れる」のでなく**そのまま地の黒に溶ける**ので、
   ヒーローと次の節(01)の間に境界線を引かずに済む。 */
.hero-veil {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(11, 11, 11, 0) 52%, rgba(11, 11, 11, 0.96) 100%),
    rgba(11, 11, 11, 0.2);
}

/* 真ん中の一言は、**それ自体が1つの黒いコマ**。白いコマの原っぱに1枚だけ黒が置かれる。 */
.hero-center {
  position: relative;
  z-index: 2;
  /* 見出しが短いので、幅は文字に任せず固定する（任せると細長い札になる）。 */
  width: min(21rem, 100%);
  text-align: center;
  padding: clamp(1.1rem, 4.5vw, 1.5rem) clamp(1rem, 4vw, 1.5rem) clamp(1.2rem, 4.5vw, 1.6rem);
  background: var(--void);
  border: 3px solid var(--paper);
  box-shadow: 7px 7px 0 rgba(0, 0, 0, 0.55);
  transform: rotate(-0.6deg);
}
.hero-center > * { transform: rotate(0.6deg); }

/* 新着の知らせ（実機の新着チップの移植: 黒いピル・白文字・高さ32px・12.5px）。
   実機は白い紙のフィードの上に出るので黒のままで浮くが、**この紙面は黒地**なので
   埋もれる。コマや中央の一言と同じ考え方で、紙の縁を1本外に足して浮かせる。 */
.hero-toast {
  position: absolute;
  left: 50%;
  bottom: clamp(1.1rem, 4vw, 2.2rem);
  z-index: 3;
  /* JS が無いときはアニメーションが当たらないので、ここで中央に寄せておく。 */
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  height: 32px;
  padding: 0 clamp(0.9rem, 3.5vw, 1.15rem);
  background: var(--void);
  border: 2px solid var(--paper);
  border-radius: 999px;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.5);
  color: var(--paper);
  font-size: 12.5px;
  font-weight: 700;
  white-space: nowrap;
  pointer-events: none;
}
/* 出ては消える（実機の `sh-toastgo` と同じ 7 秒の呼吸）。JS が無いときは出しっぱなし。 */
.js .hero-toast { animation: hero-toast 7s ease-out infinite; }

@keyframes hero-toast {
  0%, 6% { opacity: 0; transform: translate(-50%, 6px); }
  12%, 42% { opacity: 1; transform: translate(-50%, 0); }
  50%, 100% { opacity: 0; transform: translate(-50%, -4px); }
}

h1 {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(1.05rem, 3.4vw, 1.45rem);
  line-height: 1.16;
  letter-spacing: -0.005em;
  margin: 0;
  color: var(--paper);
  text-wrap: balance;
}

/* 見出しの2行目（仕組みを一息で言う行）。同じ見出しの中だが、
   書体と大きさを落として「Say the unsaid.」を主にする。 */
.h1-line {
  display: block;
  margin: 0.55rem 0 1.1rem;
  font-family: var(--body);
  font-weight: 500;
  font-size: 0.6em;
  line-height: 1.4;
  letter-spacing: 0;
  color: var(--chalk-soft);
}

/* ── ヒーローの舞台: コマが次々に生まれる ─────────────────────── */

/* コマの原っぱ＝**実機のフィードを何本か並べたもの**（2026-08-12 作り直し）。
   以前は等分のグリッドに1枚ずつ置いていたが、実機のコマは
   「1行に2コマ・段ごとに高さが違う・幅も不揃い」なので、等分だとコマの中に余白が余り、
   実画面と似ていない絵になっていた。ここでは**実測した段の高さ・コマの幅（px）を
   そのまま flex の重みに使う**——比率が実物と同じまま、帯の本数だけで画面を埋められる。

   2026-08-15: **5本40枚 → 3本20枚**。枚数を優先して詰めた結果、1コマが痩せて
   フキダシの文字が91%も欠けていた（詳細は下の `.stage .balloon`）。
   加えて旧版は帯1〜5が**完全に同一のコピー**で、横に目を移すと同じ紙面の反復だと
   分かってしまっていた。いまは**帯ごとに段の構成（段数・1段のコマ数・高さ・幅）が全部違う**
   ——`index.html` 側で帯ごとに直接書いてある。 */
.stage {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  gap: clamp(0.4rem, 1.8vw, 0.7rem);
  padding: clamp(0.4rem, 1.8vw, 0.7rem);
}

.strip {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(0.3rem, 1.2vw, 0.5rem);
}
/* 狭い画面は1本、34rem から2本、52rem から3本（2026-08-15。旧: 1→3→5本）。
   **本数を減らしたのは1枚を大きくするため**——5本だとデスクトップでも1コマが 100px 台まで
   痩せ、フキダシの中で1行が十数文字しか入らず文字が読めなかった。3本なら 200px 前後＝
   実機（375px 幅に2コマ＝170px 前後）とほぼ同じ寸法になる。
   （`.stage` の先頭には集中線があるので nth-child では数えられない＝通し番号のクラスで持つ） */
.strip--2,
.strip--3 { display: none; }

/* 1段。右→左に読む（実機と同じ row-reverse）。高さの重みは実測 px。 */
.krow {
  flex: var(--h) 1 0;
  min-height: 0;
  display: flex;
  flex-direction: row-reverse;
  gap: 2px;
}
/* 1コマ。幅の重みも実測 px。 */
.slot {
  flex: var(--w) 1 0;
  position: relative;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
  /* 差し替えのたびに JS(`restyleRow`)が scale/rotate を掛ける。レイアウトの箱(flexの
     計算結果)には触れず見た目だけ縮む・傾くので、行内の他のコマへは影響しない。 */
  transform-origin: center;
  transition: transform 0.4s ease;
}


/* 原っぱのコマは実機と同じ比率で並ぶので、フキダシも実機と同じ考え方で組む。
   **字の大きさはコマの幅から決める**（`--fs` は JS が入れる。2026-08-15）。
   実機の比率（148px のコマにセリフ 12px ＝ 0.081）をそのまま使うので、
   コマが大きい帯では字も一緒に大きくなり、**1行に入る文字数がコマの大小によらず一定**になる
   ＝折り返しの回数＝フキダシの行数が実機と同じに保たれる。

   以前は固定値（0.85rem）だったため、細いコマだけ1行が十数文字しか入らず行数が爆発し、
   下の `max-height`（当時4行）で**フキダシ80個のうち73個＝91%が途中で切れていた**
   （最悪の個体は 188px のうち 118px が不可視）。字の大きさをコマに追従させるのが本筋で、
   クランプで隠すのは対症療法だったという判断。 */
.stage .balloon {
  /* 余白は JS（`typeset`）が実測から入れる。ここは組む前の初期値でしかない
     ——楕円の大きさは「組み上がった行長」から逆算するので、CSS では決められない。 */
  padding: clamp(0.18rem, 1vw, 0.26rem) clamp(0.34rem, 1.6vw, 0.5rem);
  font-size: var(--fs, 0.8rem);
  line-height: 1.25;
  border-width: 2px;
}
/* 1行＝1ブロック。**ブラウザに組み直させない**のがこの紙面の要（`typeset` が
   レンズ形に切った行を、そのまま積む）。`nowrap` を外すと自動折り返しが復活して
   長方形に組まれ、丸いフキダシの四隅から文字が出る。 */
.stage .balloon .ln {
  display: block;
  white-space: nowrap;
}
/* **幅の上限は CSS で持たない**（2026-08-15）。`max-width: 92%/98%` を残すと、
   組み上がった幅がそれを超えたときに**箱だけが縮み、`nowrap` の行がそのまま外へ出る**
   （実測: 中身 203px のフキダシが 210px に丸められ、行が枠を突き抜けていた）。
   上限は JS 側が `availW`（コマの内寸から算出）で持ち、`typeset` はそこに
   収まる行数でしか組まないので、CSS 側の保険はむしろ害になる。 */
.stage .balloon--speech,
.stage .balloon--ai { max-width: none; }
/* セリフと返しは**絶対に重ねない**。flex の gap だけだと、丸いフキダシの箱が詰まった
   個体で 2〜6px 食い込む（実機にこの重なりは無い）。確実に離すため溝を持たせる。 */
.stage .balloon--ai { margin-top: 3px; }
/* ※楕円系の「先端の余白」をここで足していた指定は撤去（2026-08-15）。
   余白は `typeset()` が**組み上がった行長から逆算して**入れるので、
   CSS 側で足すと二重になり、楕円が必要以上に大きくなる。 */
/* 返しの「二重線」は**内側**に引く。外側のリング（`0 0 0 3.2px`）にすると枠の外へ
   3.2px はみ出し、上のセリフのフキダシに食い込んで**2つが重なって見える**
   （実機にこの重なりは無い。実機の二重線も内側の白フチ）。
   字は返しのほうが一段小さい（実機は セリフ 12px / 返し 10.5px ＝ 0.875）。 */
.stage .balloon--ai {
  box-shadow: inset 0 0 0 1.3px var(--paper);
  font-size: calc(var(--fs, 0.8rem) * 0.875);
}
/* `.panel .in` と同じ詳細度だと後勝ちで負けるので、`.stage` を足して確実に上書きする。 */
.stage .panel .in {
  overflow: hidden;
  /* 実機と同じ 2px の溝。0 や負の値にすると2つのフキダシが重なって見える。 */
  gap: 2px;
  /* 内側の余白は 3px まで詰める。実機はフキダシがコマの 93% を埋めるので、
     ここが厚いとコマの中に白い余りが残って「実画面と違う」に見える（実測 69% → 80%）。 */
  padding: 3px;
}
/* 生まれた瞬間のポップ（1コマずつ「ポンッ」と置かれる）。
   **`.pop` は写植が終わってから JS が付ける**（2026-08-15）。付いた状態で置くと、
   写植がコマを測る瞬間にアニメーションの 0%（`scale(0.82) rotate(-2.4deg)`）が効いていて、
   **縮んで傾いた座標系の実測値**が返る。それを等倍の px 余白として使うと
   フキダシの楕円が約2割小さく作られ、文字が外へ出る。 */
.slot .panel { height: 100%; }
.slot .panel.pop {
  animation: koma-pop 0.42s cubic-bezier(0.2, 1.5, 0.4, 1) both;
}

@keyframes koma-pop {
  0% { opacity: 0; transform: scale(0.82) rotate(-2.4deg); }
  55% { opacity: 1; transform: scale(1.035) rotate(0.7deg); }
  100% { opacity: 1; transform: none; }
}

/* コマが生まれるたびに一瞬カッと光る集中線（アプリの flashKey の紙版）。 */
.stage-flash {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 190%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background: repeating-conic-gradient(
    from 0deg at 50% 50%,
    rgba(255, 255, 255, 0.55) 0deg 0.3deg,
    transparent 0.3deg 3.2deg
  );
  -webkit-mask-image: radial-gradient(closest-side, transparent 22%, #000 58%, transparent 78%);
  mask-image: radial-gradient(closest-side, transparent 22%, #000 58%, transparent 78%);
  opacity: 0;
  pointer-events: none;
  z-index: 0;
}
.stage-flash.go { animation: flash 0.5s ease-out; }

@keyframes flash {
  0% { opacity: 0.75; transform: translate(-50%, -50%) scale(0.94); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(1.06); }
}

/* ── コマ ─────────────────────────────────────────────────────── */

/* アプリのコマをそのまま持ってくる（`src/components/manga/Panel.tsx` と同じ作り）:
 *   ① 形は**斜めの四辺形**（縦の2辺を同じ向きに倒す＝ガターが斜めの平行線に見える）
 *   ② 枠は3層のクリップの差で描く: 紙の縁 → 墨の枠 → 紙
 *      （アプリはページが紙なので枠＝墨だけでよいが、ここは黒地なので**いちばん外に
 *      紙の縁を1枚足す**。これがページの紙＝ガターに当たる）
 *   ③ 地には必ずトーン（網点）を敷く。無色の白いコマを作らない
 * 斜めの量は px 固定。%にするとコマごとに傾きが変わってガターが楔形になる。 */
/* 形（--clip）はスロット側で決めて継承させる。既定は四角。 */
.panel {
  position: relative;
  background: var(--paper);
  padding: 2px;
  clip-path: var(--clip, polygon(0 0, 100% 0, 100% 100%, 0 100%));
  filter: drop-shadow(4px 4px 0 rgba(255, 255, 255, 0.12));
}
.panel > .ink {
  height: 100%;
  padding: 2.5px;
  background: var(--ink);
  clip-path: var(--clip, polygon(0 0, 100% 0, 100% 100%, 0 100%));
}
.panel .in {
  position: relative;
  height: 100%;
  background: var(--paper);
  color: var(--ink);
  clip-path: var(--clip, polygon(0 0, 100% 0, 100% 100%, 0 100%));
  padding: clamp(0.7rem, 3.2vw, 1.2rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.55rem;
}
.panel .in > * { position: relative; z-index: 1; }

/* コマの中は紙なので、黒地用の淡い文字色をここで墨に戻す。 */
.panel .small { color: #4a4a48; }

/* コマの形（縦の2辺を同じ向きに倒した平行四辺形）。
   1つの行の中では同じ向き・同じ量に揃えるとガターが平行に走る（行ごとに変えて種類を出す）。 */
.sl-r8 { --clip: polygon(8px 0, 100% 0, calc(100% - 8px) 100%, 0 100%); }
.sl-r12 { --clip: polygon(12px 0, 100% 0, calc(100% - 12px) 100%, 0 100%); }
.sl-l8 { --clip: polygon(0 0, calc(100% - 8px) 0, 100% 100%, 8px 100%); }
.sl-l12 { --clip: polygon(0 0, calc(100% - 12px) 0, 100% 100%, 12px 100%); }

/* ── トーン（網点）: アプリの TONE_CONFIG（Panel.tsx）と同じ9種 ──────
   コマの地を覆う1枚。文字より後ろに敷くので ::before で描く（本文は z-index:1）。 */
.in::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.tone--soft::before {
  background-image: radial-gradient(rgba(0, 0, 0, 0.16) 1px, transparent 1.3px);
  background-size: 7px 7px;
}
.tone--dense::before {
  background-image: radial-gradient(rgba(0, 0, 0, 0.3) 1.4px, transparent 1.7px);
  background-size: 6px 6px;
}
.tone--gradient-tl::before {
  background-image: radial-gradient(rgba(0, 0, 0, 0.26) 1.2px, transparent 1.5px);
  background-size: 6.5px 6.5px;
  -webkit-mask-image: linear-gradient(135deg, #000 0%, rgba(0, 0, 0, 0.25) 48%, transparent 80%);
  mask-image: linear-gradient(135deg, #000 0%, rgba(0, 0, 0, 0.25) 48%, transparent 80%);
}
.tone--gradient-br::before {
  background-image: radial-gradient(rgba(0, 0, 0, 0.26) 1.2px, transparent 1.5px);
  background-size: 6.5px 6.5px;
  -webkit-mask-image: linear-gradient(135deg, transparent 20%, rgba(0, 0, 0, 0.25) 52%, #000 100%);
  mask-image: linear-gradient(135deg, transparent 20%, rgba(0, 0, 0, 0.25) 52%, #000 100%);
}
.tone--hatch::before {
  background-image: repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.16) 0 1px, transparent 1px 7px);
}
.tone--hatch-dense::before {
  background-image: repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.26) 0 1px, transparent 1px 4px);
}
.tone--coarse-dot::before {
  background-image: radial-gradient(rgba(0, 0, 0, 0.3) 1.9px, transparent 2.2px);
  background-size: 11px 11px;
}
/* 砂目は3層を少しずつずらして、完全なグリッドに見えないようにする。 */
.tone--sand-light::before {
  background-image:
    radial-gradient(rgba(0, 0, 0, 0.187) 1px, transparent 1.3px),
    radial-gradient(rgba(0, 0, 0, 0.22) 1.3px, transparent 1.6px),
    radial-gradient(rgba(0, 0, 0, 0.165) 0.9px, transparent 1.2px);
  background-size: 4px 4px, 5px 5px, 4px 4px;
  background-position: 0 0, 3px 2px, 1px 2px;
}
.tone--sand-dark::before {
  background-image:
    radial-gradient(rgba(0, 0, 0, 0.357) 1px, transparent 1.3px),
    radial-gradient(rgba(0, 0, 0, 0.42) 1.3px, transparent 1.6px),
    radial-gradient(rgba(0, 0, 0, 0.315) 0.9px, transparent 1.2px);
  background-size: 4px 4px, 5px 5px, 4px 4px;
  background-position: 0 0, 3px 2px, 1px 2px;
}

/* ── フキダシ ──────────────────────────────────────────────── */

/* フキダシ。白地＋細い黒フチ・中央寄せ・しっぽ無しはアプリ（SpeechBalloon.tsx）と同じ。
   形は8種を通し番号から決定的に選ぶ（セリフと返しで倍率を変えて同じコマ内でも揃わない）。 */
.balloon {
  position: relative;
  margin: 0;
  padding: clamp(0.7rem, 3.2vw, 1.1rem) clamp(0.9rem, 4vw, 1.45rem);
  border: 2.5px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--hand);
  font-size: clamp(0.86rem, 3.7vw, 1rem);
  line-height: 1.5;
  text-align: center;
  border-radius: 12px;
}

/* 相方の返し: 二重線で主役をセリフに譲る（形でなく太さ・二重線で差をつける）。 */
.balloon--ai {
  align-self: flex-end;
  max-width: 92%;
  box-shadow: inset 0 0 0 1.5px var(--paper);
  margin-right: 0.3rem;
}

.balloon--speech { align-self: flex-start; max-width: 98%; }

/* 8種の形（アプリの radiusFor と同じ値。small 版を使う＝この紙面のコマは小さい）。
   楕円系は先端の余白を少し足して、文字が曲線に食い込まないようにする。 */
.b--ellipse { border-radius: 50%; padding-left: 1.15em; padding-right: 1.15em; }
.b--egg { border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%; padding-left: 1.1em; padding-right: 1.1em; }
.balloon--ai.b--egg { border-radius: 50% 50% 50% 50% / 55% 55% 45% 45%; }
.b--pill { border-radius: 999px; padding-left: 1.2em; padding-right: 1.2em; }
.b--round { border-radius: 11px / 8px; }
.balloon--ai.b--round { border-radius: 9px / 6px; }
.b--cloud { border-radius: 58% 42% 54% 46% / 46% 56% 40% 60%; }
.balloon--ai.b--cloud { border-radius: 54% 46% 52% 48% / 48% 54% 44% 56%; }
.b--cloud2 { border-radius: 42% 58% 40% 60% / 58% 42% 62% 38%; }
.balloon--ai.b--cloud2 { border-radius: 46% 54% 44% 56% / 54% 46% 58% 42%; }
.b--puff { border-radius: 66% 70% 68% 72% / 70% 66% 72% 68%; }
.balloon--ai.b--puff { border-radius: 58% 62% 60% 64% / 62% 58% 64% 60%; }
.b--petal { border-radius: 10px 10px 10px 3px / 8px 8px 8px 3px; }
.balloon--ai.b--petal { border-radius: 8px 8px 8px 3px / 6px 6px 6px 3px; }

/* ── 特徴3つ: モバイル画面＋テキストのジグザグ（2026-08-10）────────────
 * BeReal.com の実測値をそのまま採る: **画面 0.8 : テキスト 1・溝 64px（=M）・
 * 行と行の間 128px（=L）・画面は左右交互**。狭い画面では縦積みにして
 * **見出し → 本文 → 画面** の順に落とす（画面が下＝先に言葉を読ませる）。
 *
 * 縦積み↔2カラムの切り替えは 52rem（832px）。ここで割ると、2カラム側でテキストが
 * 380px ほど確保できる。48rem で割ると 348px しか無く、`sec-lede` の手動改行
 * （`.br-md`）が入る幅と噛み合わない。
 */

.features { display: grid; gap: var(--space-l); }

.row { display: grid; gap: var(--space-m); align-items: center; }
.row-text { max-width: 34em; }
.row-text .sec-lede { max-width: none; }

/* ── 節そのものが1コマ（01 → 04 が縦に積む4コマ）─────────────────────
 * 見出しと補足を地の文で置くのをやめ、**アプリと同じ単位**に組み替えた（2026-08-13）:
 *   太字の見出し＝**セリフ**（太い1本線・主役） / 補足の説明＝**相方の返し**（二重線・手書き・一段小さい）。
 *   その2つで1コマ（CLAUDE.md「セリフ + 返し = 1コマ」）。節が4つなので、
 *   ページの中央列は上から下へ読む**4コマ**になる。
 * コマの作り（紙の縁 → 墨の枠 → 紙 ＋ 網点）はヒーローの `.panel` をそのまま使い、
 * 傾き（`sl-*`）と網点（`tone--*`）だけ節ごとに変えて、同じ絵が4枚並ばないようにする。
 *
 * ■ ここだけフキダシを楕円・雲形にしない理由
 *   アプリの丸いフキダシが成立するのは `lib/manga/lettering.ts` が行の切れ目を**レンズ形**に
 *   組んでいるからで、ブラウザの自動折り返し（＝常に長方形）で3行のコピーを楕円に入れれば
 *   四隅は必ず外へ出る。静的ページに写植は無い。だからここは
 *   **アプリの round / petal を箱の大きさに合わせて拡大した丸み**を使う
 *   ——形を四角く妥協しているのではなく、同じ形を大きい箱の比率で描いている
 *   （アプリの `radiusFor` も small / large で値を持ち替えている）。
 *
 * ■ フキダシの中だけは中央寄せ
 *   ページの地の文は左寄せのまま（下の特徴3つの節の注記を参照）。**フキダシの中は別**で、
 *   アプリのフキダシは1つ残らず中央寄せ（`SpeechBalloon.tsx`）。ここを左寄せにすると
 *   丸みの左側だけ余白が空いて、フキダシでなく角丸の箱に見える。 */

.koma .panel { filter: drop-shadow(5px 5px 0 rgba(255, 255, 255, 0.14)); }
.koma .panel .in {
  gap: clamp(0.6rem, 2.6vw, 0.9rem);
  padding: clamp(0.95rem, 3.9vw, 1.45rem);
  justify-content: flex-start;
}
/* **コマは列いっぱいには広げない**（2026-08-15 に一回り縮小）。
   字と余白だけ小さくすると背が縮むだけで幅は列のまま＝「平たくなった」に見えるので、
   横幅にも上限を持たせて縦横そろって一回り小さくする。
   狭い画面（1カラムに落ちたあと）は列のほうが狭いので、この上限は当たらない。 */
.sec .koma { max-width: 24rem; }
/* コマ番号は紙の上に乗るので白黒を反転する（黒地では白いシールだった）。 */
.koma .sec-no {
  align-self: flex-start;
  margin-bottom: 0;
  background: var(--ink);
  color: var(--paper);
}
/* セリフ＝見出し。太い1本線・明朝のまま・主役。
   **フキダシは文字の大きさに縮む**（`stretch` にしない）——コマの幅いっぱいに伸ばすと
   帯であってフキダシに見えない。 */
.koma .balloon--speech {
  align-self: flex-start;
  max-width: 100%;
  margin: 0;
  border-width: 3px;
  border-radius: 28px 34px 26px 32px / 20px 24px 18px 22px;
  padding: clamp(0.78rem, 3.1vw, 1.1rem) clamp(0.95rem, 3.9vw, 1.35rem);
  font-family: var(--serif);
  font-weight: 700;
  /* 見出しの段（`--fs-display`）より一回り小さい（2026-08-15）。共通トークンを
     下げると奥付の `h2` まで小さくなるので、コマの中だけで持ち替える。
     2026-08-17: 02/04(「One line in. / Ask me anything.」)が文中の句点で
     `<br>` 改行するようになり、1コマに収まる行数が増えたぶん、もう一段階下げる。 */
  font-size: clamp(1.32rem, 5.7vw, 1.98rem);
  line-height: 1.14;
  color: var(--ink);
}
/* 返し＝補足の説明。**二重線は内側に引く**（外側のリングは上のフキダシに食い込む）。 */
.koma .balloon--ai {
  align-self: flex-end;
  max-width: 96%;
  margin: 0 0.25rem 0 0;
  border-width: 2.5px;
  border-radius: 24px 28px 24px 9px / 18px 20px 18px 7px;
  padding: clamp(0.74rem, 2.95vw, 1rem) clamp(0.95rem, 3.9vw, 1.28rem);
  box-shadow: inset 0 0 0 1.6px var(--paper);
  font-family: var(--hand);
  font-size: clamp(0.95rem, 3.9vw, 1.08rem);
  line-height: 1.55;
  color: var(--ink);
}
/* 丸みの倒れる向きを1コマおきに入れ替える（4枚が同じ型に見えないように）。 */
.koma--b .balloon--speech { border-radius: 32px 26px 34px 28px / 22px 18px 24px 20px; }
.koma--b .balloon--ai { border-radius: 28px 24px 9px 24px / 20px 18px 7px 18px; }

/* 画面は**本番の実寸（375×812px＝端末まるごと）のまま**組んで、`--sc` で縮小する。
   途中で 600px に切っていた時期があり、下のコマがステージの底で断ち切られていた。
   端末の高さのまま出せば、コマ・入力欄・シートのどれも欠けない。
   こうすると中の値を「アプリで測った px」そのままで書ける＝実物とのズレが起きない。
   （以前は em / container query で相対化していたが、相対値に直す過程で本番と
   まったく違う絵になった。実寸を写して縮めるほうが、写し間違いが起きない。） */
.shot-frame {
  --sc: 0.80;
  width: calc(375px * var(--sc));
  height: calc(812px * var(--sc));
  margin: 0 auto;
  /* 縦積みでは**テキストが先・画面が下**（BeReal と同じ順）。DOM は「画面 → テキスト」
     のままにして order で入れ替える——2カラムのときに画面を左に置きたいので、
     DOM 順のほうを画面優先にしてある。 */
  order: 2;
}

/* 端末まるごと（812px）を出すぶん縦に長いので、縮尺は下げる。
   ≥52rem で 812×0.70 ≒ 568 ＝ BeReal の行の高さ（569）とほぼ同じに戻る。 */
@media (min-width: 34rem) { .shot-frame { --sc: 0.75; } }

@media (min-width: 52rem) {
  .row { grid-template-columns: 0.8fr 1fr; }
  /* 01専用: 実機モックの代わりに**コマを2つ**横並びにする（2026-08-14）。
     02〜04は screen 0.8 : text 1 の非対称だが、01は対等な2つの主張（返信の速さ／
     採点の不在）を並べるだけなので列は均等。画面が無いぶん `order` による
     並べ替えも不要——DOM順=表示順のまま、狭い画面でも上から下へ単純に積む。
     列の幅はコマの上限（24rem）で止めて**2つまとめて中央に置く**（2026-08-15）
     ——`1fr 1fr` のままだと列だけ広がってコマが左に寄り、右に余りが出る。 */
  .row--split {
    grid-template-columns: repeat(2, minmax(0, 24rem));
    justify-content: center;
  }
  .shot-frame { order: 0; --sc: 0.70; }
  /* 画面を右に置く行。DOM は「画面 → テキスト」の順のまま
     （縦積みのときに見出しが先に来る順序を壊さない）ので、`order` で入れ替える。
     **列の取り分も一緒に入れ替える**——これを忘れると、右に来た行だけ画面が
     広い側（1fr）に入って1枚だけ大きくなり、3行の高さが揃わない。 */
  .row--flip { grid-template-columns: 1fr 0.8fr; }
  .row--flip .shot-frame { order: 2; }
}

/* ── モバイル実画面の複製 ───────────────────────────────────────
 * スクリーンショットは貼れない（外部通信ゼロ／LPは画像0枚）ので全部CSSで描く。
 * **以下の数値はすべて localhost:3000 の実測値**。目分量で足した値は1つも無い。
 *
 * ■ 2026-08-16: フィードのコマは**手で置くのをやめた**。実機を 375×812 で開いて
 *   描画済みの DOM（コマの矩形・`clip-path` 2枚・トーンの `background-image`・
 *   フキダシの矩形と角丸と改行）をそのまま HTML へ書き出している。手で数枚だけ置いていた
 *   ころは1行に1コマしか無い段ができ、紙面が**歯抜け**に見えていた（実機の `layout.ts` は
 *   en では必ず1行2コマまでで詰めるので、あの隙間は実機には存在しない）。
 *   ついでに、存在しないトーンのクラス（`sh-t--soft` / `sh-t--hatch-l`）を参照していた
 *   コマが地の網点を失って真っ白になっていたのも直っている。
 *   棚名・背表紙の並び・表紙の意匠も 2026-08-14 のカタログ改訂に追随させた。
 *   ・棚の中の地は `#111`（紙ではない）／コマは白い紙＋2px の墨枠
 *   ・コマは片端を画面の端まで裁ち落とす（w=360 @ x=15 ＝ 右端まで）
 *   ・セリフ 12px/15.6・返し 10.5px/13.7（返しのほうが小さい）＋返しは二重線
 *   ・フキダシの改行は `lettering.ts` が組んだレンズ形をそのまま `<br>` で固定
 *   ・シートは 375×406、角丸 16px、枠 3px、影 4px 4px 0（枠は 2026-08-12 に 2.4→3px）
 *   ・棚の中の枠はすべて 2px（タイトルチップ・端の帯・入力欄・フキダシ・背表紙・チップ）
 * 変えるときは**アプリを開いて測り直すこと**。
 */

.shot {
  width: 375px;
  height: 812px;
  transform: scale(var(--sc));
  transform-origin: top left;
  overflow: hidden;
  border-radius: 22px;
  background: var(--ink);
  /* 黒地に置くので紙の縁を1本内側に回す（コマと同じ考え方）。 */
  box-shadow: inset 0 0 0 3px var(--paper), 6px 6px 0 rgba(255, 255, 255, 0.22);
}

.sh-stage {
  position: relative;
  width: 375px;
  height: 812px;
  overflow: hidden;
  font-family: var(--body);
  font-weight: 500;
  line-height: 1.4;
}

/* 棚の中（ShelfView）。地は墨。 */
.sh--shelfview { background: var(--ink); }

/* 棚のタイトル（色つきチップ・明朝）。実装は `left:50%` + `translateX(-50%)` の
   **中身なり**の幅なので、こちらも固定幅を持たない（棚名を差し替えても崩れない）。
   枠 2.5px・角 3px・影 2px 2px 0・網点の地・文字は白＋下向きの淡い影。 */
.sh-title {
  position: absolute;
  left: 50%;
  top: 12px;
  transform: translateX(-50%);
  max-width: 86%;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 7px 16px 8px;
  background-color: var(--c);
  background-image: radial-gradient(rgba(0, 0, 0, 0.12) 1px, transparent 1.1px);
  background-size: 6px 6px;
  border: 2.5px solid var(--ink);
  border-radius: 3px;
  box-shadow: 2px 2px 0 var(--ink);
  font-family: var(--serif);
  font-weight: 700;
  font-size: 16px;
  line-height: 1.2;
  color: #fff;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.28);
  white-space: nowrap;
}

/* 右上のドッグイヤー（当たり判定は矩形・見た目は三角）。 */
.sh-dogear {
  position: absolute;
  right: 0;
  top: 0;
  width: 28px;
  height: 28px;
  z-index: 4;
  background: var(--paper);
  clip-path: polygon(0 0, 100% 0, 100% 78%);
}
.sh-dogear::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.3);
  clip-path: polygon(0 0, 100% 78%, 24% 97%);
}

/* 前後の棚を示す左右の帯（縦書き・明朝）。 */
.sh-peek {
  position: absolute;
  z-index: 4;
  width: 34px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding-top: 10px;
  overflow: hidden;
  background: var(--c);
  border: 2px solid var(--ink);
  color: #fff;
}
.sh-peek--l {
  left: 0;
  border-left: 0;
  border-radius: 0 8px 8px 0;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.22);
}
.sh-peek--r {
  right: 0;
  border-right: 0;
  border-radius: 8px 0 0 8px;
  box-shadow: -2px 2px 0 rgba(0, 0, 0, 0.22);
}
.sh-peek i { font-style: normal; font-size: 12px; line-height: 1; }
.sh-peek span { writing-mode: vertical-rl; font-family: var(--serif); font-size: 11px; line-height: 1; }

/* ── フィード ────────────────────────────────────────────────── */

/* コマの位置・大きさは実測値そのままなので**絶対配置**で置く（flex で組み直すと
   負のマージンや行の詰め方まで真似ることになり、かえってずれる）。 */
.sh-feed { position: absolute; inset: 0; z-index: 1; overflow: hidden; }

/* フィードの中身をまとめて持ち上げる「リール」。**実機と同じで、コマを置くと
   フィード全体が上へ動き、最下段に新しいコマが現れる**（`ShelfView` は投稿のたびに
   `scrollIntoView({block:"end"})` で最下部へ送る）。
   これ以前は「これから生まれるコマ」を最終位置に置いて `opacity:0` から出していたが、
   それだと**生まれるまでの数秒間その場所が黒い穴**になり、紙面が歯抜けに見えていた。
   リールなら、コマは最初から全部そこにあって画面の外にいるだけ＝どの瞬間も穴が無い。 */
.sh-reel { position: absolute; left: 0; right: 0; top: 0; height: 1300px; will-change: transform; }

/* コマ: 墨の面（下）→ 紙（上）。**斜めは2枚のクリップの差で作る**——墨を 11px、
   紙を 13px 倒すと、差の 2px がそのまま枠の太さになる（枠線を引いているのではない）。
   形はコマごとに違うので `--ink-clip` / `--paper-clip` を HTML 側で1枚ずつ渡す
   （実装も inline の clip-path で1枚ずつ指定している）。 */
.sh-koma { position: absolute; filter: drop-shadow(2px 2px 0 rgba(0, 0, 0, 0.2)); }
.sh-ink {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--ink);
  clip-path: var(--ink-clip);
}
.sh-paper {
  position: relative;
  z-index: 1;
  height: 100%;
  background: var(--paper);
  clip-path: var(--paper-clip);
}

/* 地のトーン（網点/斜線/砂目）。**種類ごとのクラスは持たない**（2026-08-16）——
   トーンは `Panel.tsx` の TONE_CONFIG が9種あり、クラスを作るとどれかを写し忘れる
   （実際に `sh-t--soft` / `sh-t--hatch-l` という**存在しないクラス**が HTML から
   参照されていて、その2種のコマだけトーンが敷かれず真っ白になっていた）。
   いまは書き出しのときに実機の `background-image` をそのまま inline で持たせる。 */
.sh-tone { position: absolute; inset: 0; pointer-events: none; }

/* フキダシ。位置・大きさ・角丸は HTML の style で1つずつ指定する（本番の実測値）。
   ここに置くのは、どのフキダシにも共通する組みだけ。 */
.sh-b {
  position: absolute;
  z-index: 1;
  margin: 0;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper);
  color: var(--ink);
  text-align: center;
  font-family: var(--body);
  /* 実装は**大文字**（写植の見え方が変わるので必ず合わせる）。 */
  text-transform: uppercase;
  letter-spacing: 0.01em;
}
/* セリフ: 太い1本線・本文書体・太字。主役。 */
.sh-b--s {
  border: 2.4px solid var(--ink);
  font-size: 12px;
  line-height: 15.6px;
  font-family: var(--body);
  font-weight: 700;
}
/* 返し: 細い線＋**内側の二重線**、字も一段小さい。
   書体はセリフと変える（実装の `--manga-font-ai` ＝ Klee One）——同じコマの中で
   どちらの声かひと目で分かるようにするための区別なので、ここを揃えると意味が消える。 */
.sh-b--a {
  border: 2px solid var(--ink);
  font-size: 10.5px;
  line-height: 13.65px;
  font-family: var(--hand);
  font-weight: 600;
  box-shadow: inset 0 0 0 2px var(--paper), inset 0 0 0 3px rgba(17, 17, 17, 0.5);
}

/* 返しが**顔文字だけ**のときの描き方＝フキダシをやめて置く「動く複数行アスキーアート」
   （`components/manga/ascii-art.ts` ＋ `ReplyStamp`）。等幅・`white-space: pre`・行間 1.08 で
   絵の空白を1つも潰さない。フレームは重ねて置き、`steps(1)` でパラパラ切り替える
   ——クロスフェードすると2枚が半透明で重なって二重にぶれる。
   1周 1.1秒（`AA_DURATION_S`）、字の大きさは実装の `AA_SIZE.small` と同じ。 */
.sh-aa {
  position: absolute;
  z-index: 1;
  display: block;
  text-align: center;
  font-family: "Noto Sans Mono", "DejaVu Sans Mono", Menlo, Consolas, monospace;
  font-size: 9.8px;
  line-height: 1.08;
  white-space: pre;
  color: var(--ink);
}
.sh-aa-f {
  display: block;
  font-style: normal;
  opacity: 0;
}
/* 1枚目だけ既定で見えている＝動きを止めたときここで静止する。 */
.sh-aa-f--1 { opacity: 1; }
/* 2枚目以降は1枚目の上に重ねる（器の高さは1枚目が決める）。 */
.sh-aa-f--2 { position: absolute; left: 0; right: 0; top: 0; }

/* コマの中に格納される「続きをひらく」（ウサＱの回答だけが持つ）。
   実装（`ReadMoreButton`）は**枠のある小さなボタン＋外向きの矢印**で、コマの中央下に置かれる
   ——下線付きのリンク文字ではない（斜めの角で欠けるので右下にも寄せない）。 */
.sh-more {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 4px;
  z-index: 1;
  margin: 0 auto;
  width: max-content;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  background: var(--paper);
  border: 1.5px solid var(--ink);
  border-radius: 3px;
  font-size: 9.5px;
  font-weight: 800;
  line-height: 1.3;
  color: var(--ink);
  white-space: nowrap;
}

/* 入力欄の上に出る黒いピルの帯（実装の `bannerWrap`: 下から 134px・中央寄せ）。
   ウサＱ／本棚ボタン（bottom 78px・高さ最大 46px）の**上**に置いて重ねない。 */
.sh-banner {
  position: absolute;
  left: 0;
  right: 0;
  top: 646px;
  z-index: 4;
  display: flex;
  justify-content: center;
}
/* 置いた直後のピル。**主役は「置けたね」**（行動の肯定）で、取り消しは一段小さく控えめ
   ——同じ大きさで並べると、置いた瞬間にアプリが言うことが「取り消せます」になる。 */
.sh-undo {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 6px 6px 14px;
  background: var(--ink);
  border-radius: 999px;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.22);
  color: #fff;
  font-size: 12.5px;
  line-height: 1.4;
  opacity: 0;
}
.sh-undo b { font-weight: 900; }
.sh-undo i {
  font-style: normal;
  padding: 5px 12px;
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font-size: 10.5px;
  font-weight: 600;
  opacity: 0.62;
}

/* 他人のコマが降ってきたときのチップ（実装の `newChip`）。**own の「置けたね」とは別物**
   ——押しボタン1つだけのシンプルな黒ピル（取り消しの内側ボタンを持たない）。 */
.sh-newpanel {
  border: none;
  padding: 7px 14px;
  background: var(--ink);
  border-radius: 999px;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.22);
  color: #fff;
  font-size: 12.5px;
  font-weight: 700;
  opacity: 0;
}

/* 置いた瞬間の衝撃波リングと擬音（実装の `.manga-shock-ring` / `.manga-impact-word`）。
   `--d` が発火の時刻＝1周 7 秒のどこで鳴るか。中心はコマの実測位置（HTML 側の left/top）。
   墨色なのは、下が紙白のときに白い輪では見えないため。 */
.sh-boom { position: absolute; z-index: 5; width: 0; height: 0; pointer-events: none; }
.sh-ring {
  position: absolute;
  left: 0;
  top: 0;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 3px solid rgba(17, 17, 17, 0.8);
  opacity: 0;
}
.sh-bam {
  position: absolute;
  left: 0;
  top: 0;
  font-family: var(--display);
  font-weight: 900;
  font-size: 26px;
  line-height: 1;
  color: var(--ink);
  text-shadow:
    2px 0 0 #fff, -2px 0 0 #fff, 0 2px 0 #fff, 0 -2px 0 #fff,
    2px 2px 0 #fff, -2px -2px 0 #fff, 2px -2px 0 #fff, -2px 2px 0 #fff;
  white-space: nowrap;
  opacity: 0;
}

/* 親指圏の2つ: 左＝ウサＱ（明るい楕円）／右＝本棚（暗い円）。
   実装（`animations.css` の `.qbbit-neu` / `.qbbit-neu-dark`）と同じ**4層のニューモフィズム**
   ——外側の影と光、内側のフチ光と内影で pillow 状にふくらませる。単純な1層の影にすると
   モノクロUIの中で「ただの丸」になり、押せる立体物に見えない。
   `border-radius: 50%` なのでウサＱ側は正円ではなく**横長の楕円**（62×38）。
   中のアイコンは実装の SVG をそのまま写している（UsaqFace / 本の2パス）。 */
.sh-btn { position: absolute; z-index: 4; border-radius: 50%; display: flex; align-items: center; }
.sh-btn--qbbit {
  left: 15px;
  top: 696px;
  width: 62px;
  height: 38px;
  justify-content: flex-start;
  padding-left: 11px;
  background: linear-gradient(145deg, #f4f2ec, #d9d7d0);
  box-shadow:
    5px 6px 13px rgba(0, 0, 0, 0.28),
    -4px -4px 10px rgba(255, 255, 255, 0.7),
    inset 2px 2px 3px rgba(255, 255, 255, 0.85),
    inset -3px -3px 5px rgba(0, 0, 0, 0.12);
}
.sh-btn--shelf {
  right: 15px;
  top: 688px;
  width: 46px;
  height: 46px;
  justify-content: center;
  background: linear-gradient(145deg, #2e2e2e, #0d0d0d);
  box-shadow:
    5px 6px 13px rgba(0, 0, 0, 0.5),
    -3px -3px 9px rgba(255, 255, 255, 0.06),
    inset 2px 2px 3px rgba(255, 255, 255, 0.13),
    inset -3px -3px 6px rgba(0, 0, 0, 0.55);
}

/* 下端のペン入れ。 */
.sh-input {
  position: absolute;
  left: 15px;
  top: 744px;
  width: 345px;
  height: 54px;
  z-index: 4;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  padding: 0 5px 0 16px;
  background: var(--paper);
  border: 2.5px solid var(--ink);
  border-radius: 24px;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.22);
}
.sh-typed {
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  font-size: 16px;
  color: var(--ink);
}
/* まだ何も打っていない入力欄（②③の裏で待っているほう）。 */
.sh-ph { font-size: 16px; color: #8a8880; white-space: nowrap; overflow: hidden; }
.sh-caret { width: 1.6px; height: 19px; margin-left: 1px; background: var(--ink); }
/* 送信の丸ボタン。**中の絵まで実装と同じ**にする（黒丸だけだと、何のボタンか分からない
   ＝実機と違って見える最大の点だった）。棚のペン入れは羽根ペン、ウサＱは上向きの矢印。 */
.sh-send {
  flex: none;
  margin-left: auto;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--ink);
}

/* コマが生まれた瞬間の集中線。 */
.sh-flash {
  position: absolute;
  left: 50%;
  top: 46%;
  width: 720px;
  height: 720px;
  z-index: 3;
  transform: translate(-50%, -50%);
  background: repeating-conic-gradient(from 0deg at 50% 50%, rgba(255, 255, 255, 0.5) 0deg 0.3deg, transparent 0.3deg 3.2deg);
  -webkit-mask-image: radial-gradient(closest-side, transparent 22%, #000 58%, transparent 78%);
  mask-image: radial-gradient(closest-side, transparent 22%, #000 58%, transparent 78%);
  opacity: 0;
  pointer-events: none;
}

/* ── 下からせり上がるシート（本棚 / ウサＱ）────────────────────── */

.sh-scrim { position: absolute; inset: 0; z-index: 5; background: rgba(17, 17, 17, 0.45); }

.sh-sheet {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 406px;
  z-index: 6;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 3px solid var(--ink);
  border-radius: 16px 16px 0 0;
  box-shadow: 4px 4px 0 rgba(0, 0, 0, 0.22);
  color: var(--ink);
}
.sh-sheet--shelf { background: #f8f6f0; }
/* ウサＱのシートは**網点の地**（実装は #e8e6e0 に 8px の網点）。無地にすると本棚シートと
   見分けが付かなくなる。 */
.sh-sheet--qbbit {
  background-color: #e8e6e0;
  background-image: radial-gradient(rgba(0, 0, 0, 0.1) 1px, transparent 1.3px);
  background-size: 8px 8px;
}
/* ウサＱの受け答えは**大文字にしない**（実装は `uppercase={false}`）。
   大文字なのは棚のフィードのコマだけ。 */
.sh-sheet--qbbit .sh-b { text-transform: none; }

.sh-grab { width: 40px; height: 5px; margin: 10px auto 0; border-radius: 3px; background: rgba(0, 0, 0, 0.25); }

/* 検索 ＋ サイコロ（ランダムに1冊）。 */
.sh-searchrow { display: flex; gap: 8px; margin: 14px 15px 0; }
.sh-search,
.sh-dice {
  height: 45px;
  box-sizing: border-box;
  background: var(--paper);
  border: 2.4px solid var(--ink);
  border-radius: 5px;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.2);
  display: flex;
  align-items: center;
}
.sh-search {
  flex: 1 1 auto;
  min-width: 0;
  gap: 8px;
  padding: 0 10px;
  font-size: 12.5px;
  font-weight: 700;
  color: #8a8880;
  white-space: nowrap;
  overflow: hidden;
}
.sh-search svg { flex: none; }
.sh-dice { flex: none; width: 44px; justify-content: center; }

/* ジャンルの背表紙（棚に立った本の背）。選んでいる1本だけ背が高く、上に墨の線が乗る。 */
.sh-spines { display: flex; align-items: flex-end; gap: 5px; margin: 24px 15px 0; height: 108px; }
.sh-spine {
  flex: none;
  width: 32px;
  height: 92px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--c);
  background-image: radial-gradient(rgba(0, 0, 0, 0.16) 1px, transparent 1.1px);
  background-size: 7px 7px;
  border: 2.4px solid var(--ink);
  border-radius: 2px;
  writing-mode: vertical-rl;
  font-size: 12px;
  font-weight: 700;
  line-height: 1;
  color: #fff;
}
/* Request だけ実装と同じ `margin-left: auto` で右端に単独で浮く
   （運営とユーザーの対話窓口という別枠であることを、他の5ジャンルから切り離した
   位置で示す。実測で Unsaid との間に real spacer 分の隙間が空く）。 */
.sh-spine--request { margin-left: auto; }

/* 選んでいる1本だけ、背が高く・墨の線が上に乗り・地が斜線に変わる（実装と同じ）。 */
.sh-spine--on {
  width: 38px;
  height: 108px;
  background-image: repeating-linear-gradient(-48deg, rgba(0, 0, 0, 0.1) 0 5px, transparent 5px 13px);
  border-radius: 4px 4px 1px 1px;
  box-shadow: 0 -3px 0 var(--ink);
  font-size: 13px;
  font-weight: 900;
}

/* 棚板（背表紙の下を走る墨の1本）。 */
.sh-board { height: 5px; margin: 6px 17px 0; border-radius: 1px; background: var(--ink); }

/* 平台（面陳列・横スクロール）。実装は 92px 幅・比率 10:14.2・溝 10px。 */
/* 平台は2枚を重ねて置く（Love / Everyday）。背表紙を選び直した瞬間に入れ替わる。 */
.sh-flatwrap { position: relative; height: 131px; margin: 14px 0 0 17px; overflow: hidden; }
.sh-flat { position: absolute; left: 0; top: 0; display: flex; gap: 10px; width: max-content; }
.sh-cover {
  position: relative;
  flex: none;
  width: 92px;
  aspect-ratio: 10 / 14.2;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  overflow: hidden;
  background-color: var(--c);
  background-image: repeating-linear-gradient(-48deg, rgba(0, 0, 0, 0.1) 0 5px, transparent 5px 13px);
  border: 1.6px solid var(--ink);
  border-radius: 2px 4px 4px 2px;
  box-shadow: 2px 2.5px 0 var(--paper), 3px 3.5px 0 var(--ink);
}
/* 背のクリース（左端の折り目: 影 → ハイライト） */
.sh-cover::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 7px;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0.28) 0 5px, rgba(255, 255, 255, 0.22) 5px 7px, transparent 7px);
}
.sh-cover b { padding: 6px 6px 0 10px; font-size: 9.5px; font-weight: 900; line-height: 1.25; color: #fff; }
/* 下端の白い帯。**ジャンル名（左）と丸で囲った矢印（右）**の2つが入る（実装と同じ）。
   以前は「Money ›」と1つの文字列で中央寄せにしていて、実機の帯と別物だった。 */
.sh-cover i {
  font-style: normal;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 3px 5px 3px 8px;
  background: var(--paper);
  color: var(--ink);
  font-size: 7.5px;
  font-weight: 800;
}
.sh-cover i em {
  flex: none;
  width: 12px;
  height: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  border: 0.8px solid var(--ink);
  border-radius: 50%;
  font-style: normal;
  font-size: 7px;
  font-weight: 900;
  line-height: 1;
}
/* 「Money · 5 of 40 shelves」。実装は**右寄せの小さな灰**（10px / rgba(0,0,0,0.5)）。
   ジャンルを選び直すと頭の語が入れ替わるので2枚重ね。 */
.sh-count { position: relative; height: 15px; margin: 12px 17px 0; font-size: 10px; font-weight: 700; color: rgba(0, 0, 0, 0.5); }
.sh-count b { position: absolute; left: 0; right: 0; top: 0; font-weight: 700; text-align: right; }

/* ── ウサＱのシート ───────────────────────────────────────────── */

/* 実機は顔もあいさつも行の上端に揃う（行の 48px は下の余白）。center にすると 5px 下がる。 */
.sh-qhead { display: flex; align-items: flex-start; gap: 10px; height: 48px; margin: 6px 15px 0; }
/* シートの中の顔も、棚の中のウサＱボタンと同じ楕円・同じ4層シャドウ・同じ SVG。 */
.sh-face {
  flex: none;
  width: 62px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding-left: 11px;
  border-radius: 50%;
  background: linear-gradient(145deg, #f4f2ec, #d9d7d0);
  box-shadow:
    5px 6px 13px rgba(0, 0, 0, 0.28),
    -4px -4px 10px rgba(255, 255, 255, 0.7),
    inset 2px 2px 3px rgba(255, 255, 255, 0.85),
    inset -3px -3px 5px rgba(0, 0, 0, 0.12);
}
/* あいさつは返し（AI）のフキダシと同じ二重線のカプセル。 */
.sh-greet {
  flex: 1 1 auto;
  height: 47px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 14px;
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: 999px;
  /* 二重線は**両方とも内側**（実装 `inset 0 0 0 2px #fff, inset 0 0 0 3px rgba(17,17,17,0.5)`）。
     2本目を外側リングにすると枠の外へ 3px はみ出し、顔のボタンに食い込む。 */
  box-shadow: inset 0 0 0 2px var(--paper), inset 0 0 0 3px rgba(17, 17, 17, 0.5);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
}
/* 回答の置き場は実機と同じ高さ（y 71..251）で固定する。空でも詰まらないので、
   コマが返る前後でシートの中身が跳ねない。 */
/* 回答の置き場は実機と同じ高さ（シート内 y 80..251 ＝ 171px）で固定。空でも詰まらないので
   コマが返る前後でシートの中身が跳ねない。2往復ぶん（80px×2 ＋ 溝11px）が収まる。 */
.sh-qbody { position: relative; box-sizing: border-box; height: 171px; margin: 9px 15px 0; overflow: hidden; }

/* シート下端のペン入れ（実測 340×55 @ (17,339)・枠 2.4px・丸ピル・送信は 40px の黒丸）。
   **候補に無いことは、ここに自分で打つ。** */
.sh-qinput {
  position: absolute;
  left: 17px;
  bottom: 12px;
  width: 340px;
  height: 55px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  padding: 0 7px 0 18px;
  background: var(--paper);
  border: 2.4px solid var(--ink);
  border-radius: 999px;
  box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.2);
}
/* 打ち始めるまではプレースホルダが見えている（打ち出したら消える）。 */
.sh-ph--q { position: absolute; left: 18px; }

/* 候補は2段が横に流れる（実装も複製したトラックを流している）。 */
.sh-chipsrow { margin-top: 6px; overflow: hidden; }
/* **溝は gap でなく margin-right**（実装と同じ）。継ぎ目のないループは「トラック全幅の半分＝
   1周ぶん」であることに依存しており、gap だと2周の境目にもう1つ溝が入って半分がずれる。 */
.sh-chips { display: flex; width: max-content; padding-left: 17px; }
.sh-chips span {
  flex: none;
  height: 36px;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  margin-right: 7px;
  padding: 0 12px;
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: 4px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
  /* 手で置いたような互い違いの傾き（実装 `rotate(±0.6deg)`）。 */
  transform: rotate(-0.6deg);
}
.sh-chips span:nth-child(even) { transform: rotate(0.6deg); }
/* 下段は操作の代行（黒）。上段と逆向きに流して、2段が同期しないようにする。 */
.sh-chips--do span { background: var(--ink); color: var(--paper); }

/* ── 動き: 指が押して、選ぶまで ────────────────────────────────
 * 3枚とも**1周 7秒**で揃える（バラバラの周期だと、横に並んだ3枚が常にどこか
 * 動いていて落ち着かない）。中身はどれも同じ筋書き:
 *
 *   ① 指が現れる → 入力欄を押す → 打つ → 送信ボタンを押す
 *      → コマがポンッと生まれる → 集中線 → 「↓ New panel」
 *   ② 指が本棚ボタンを押す → シートがせり上がる → 背表紙 Everyday を押す
 *      → 選択が Love から移り、平台が Everyday の5冊に入れ替わる → シートが下りる
 *   ③ 指がウサＱを押す → シートがせり上がる → 候補「Can I delete?」を押す
 *      → チップが選ばれた形（黒）になり、回答がコマで返る → シートが下りる
 *
 * 動かすのは transform / opacity / max-width / visibility と、
 * 選択の入れ替わりだけ width / height / box-shadow（背表紙が実際に伸びるため）。
 * 指の座標（`translate(x, y)`）は **375×600 のステージ座標＝本番の実測 px**。
 * 押す対象を動かしたら、指の座標も一緒に直すこと。
 * `prefers-reduced-motion` の停止リストに**必ず追加すること**（下の @media）。 */

/* AA のコマ送り（実装の `manga-aa-2`）。2枚を 1.1 秒で入れ替える。 */
@keyframes sh-aa2 {
  0%, 49.99% { opacity: 1; }
  50%, 100% { opacity: 0; }
}

@keyframes sh-marq { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* 指。黒地の上でも紙の上でも見えるよう、白い輪と墨の輪を二重に回す。 */
.sh-touch {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 8;
  width: 42px;
  height: 42px;
  margin: -21px 0 0 -21px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.26);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.78), 0 0 0 3.6px rgba(17, 17, 17, 0.55);
  opacity: 0;
  pointer-events: none;
}

/* ── ① 動作: own → 他人が降ってくる → own（2026-08-16 組み直し）───────
   3拍子: ①自分が打つ→送る→ポンッ(n1・BAM) ②他人のコマが静かに降ってくる
   (n2・BAMは鳴らない・「↓ New panel」チップだけ) ③自分がもう一度打つ→送る→ポンッ
   (n3・BAM)。own の2回だけ打鍵アニメを持つ（`sh-typed` は2枚でよい）。 */
/* max-width は**その文字列の実幅**（DOM で実測した `scrollWidth`）。短すぎると
   打ち終わる前に切れ、長すぎると打ち終わってから空白の「間」が出る。
   ①「Blocked, unblocked, blocked again.」= 244px（34字）
   ③「Still setting the table for two.」= 207px（32字）
   どちらもペン入れの可視幅（実測 271px）に収まる＝実機でも**入力欄は1行のまま伸びない**
   （47字だと2行に折れて枠が 55→76px に育つので、そうならない長さを選んである）。
   文言を変えたら必ず測り直すこと。 */
@keyframes sh-type1 { 0%, 2% { max-width: 0; } 13%, 15% { max-width: 244px; } 16%, 100% { max-width: 0; } }
@keyframes sh-type2 { 0%, 53% { max-width: 0; } 68%, 70% { max-width: 207px; } 71%, 100% { max-width: 0; } }
@keyframes sh-caretshow {
  0%, 1% { visibility: hidden; }
  2%, 16% { visibility: visible; }
  17%, 53% { visibility: hidden; }
  54%, 71% { visibility: visible; }
  72%, 100% { visibility: hidden; }
}
/* 送信ボタンは own の2回だけ沈む */
@keyframes sh-press {
  0%, 14% { transform: none; }
  16% { transform: scale(0.86); }
  18%, 69% { transform: none; }
  71% { transform: scale(0.86); }
  73%, 100% { transform: none; }
}
/* ── リールの動き（フィード全体が上がる）─────────────────────────────
   実測の段: R1 45..267 / R2 277..475 / R3 485..710 / R4 720..937 /
             R5 947..1094 / R6 1103..1298
   窓は y=45（タイトルの下）〜約 740（入力欄の上）。各段の**底**が 735 に来るよう持ち上げる:
     P0 = 0（R1〜R3 がぴったり収まる＝満杯・穴ゼロ）
     P1 = 937-735 = 202（R4 が最下段に現れる＝自分の1つめ）
     P2 = 1094-735 = 359（R5 が最下段に現れる＝他人のコマ）
     P3 = 1298-735 = 563（R6 が最下段に現れる＝自分の2つめ）
   実機の `scrollIntoView({behavior:"smooth"})` に合わせて、動く時間は短く・止まりは長く。 */
@keyframes sh-reel-go {
  0%, 15% { transform: translateY(0); }
  20%, 37% { transform: translateY(-202px); }
  42%, 69% { transform: translateY(-359px); }
  74%, 96% { transform: translateY(-563px); }
  100% { transform: translateY(0); }
}
/* 刷り上がり（実装の `manga-panel-print`）。**位置は動かさない**——移動はリールが担当し、
   ここは「そのコマが今この瞬間に刷られた」ことだけを描く（濃度とわずかな跳ね）。

   **リールが動き出す前に刷り終える**のが要（実装も「コマを作る → そこへスクロールする」
   の順）。逆にすると、リールが空のスロットへ動いていく数百ミリ秒のあいだ、
   その場所が黒い穴になる（実測: 順序を逆にしていたとき 200px の穴が一瞬開いていた）。
   リールの移動は 15→20% / 37→42% / 69→74% なので、刷りはその手前で終わらせる。
   n1: 自分が置いた1つめ。 */
@keyframes sh-pop1 {
  0%, 11% { opacity: 0; transform: scale(0.86); }
  15% { opacity: 1; transform: scale(1.03); }
  18%, 100% { opacity: 1; transform: none; }
}
/* n2: 他人のコマが**静かに**現れる（跳ねない・自分の行動ではないので語気を弱める）。 */
@keyframes sh-pop2 {
  0%, 33% { opacity: 0; transform: none; }
  37%, 100% { opacity: 1; transform: none; }
}
/* n3: 自分がもう一度置く。 */
@keyframes sh-pop3 {
  0%, 65% { opacity: 0; transform: scale(0.86); }
  69% { opacity: 1; transform: scale(1.03); }
  72%, 100% { opacity: 1; transform: none; }
}
/* 集中線は own の2回だけ光る（他人のコマでは光らない）。 */
@keyframes sh-flashgo {
  0%, 15% { opacity: 0; transform: translate(-50%, -50%) scale(0.94); }
  18% { opacity: 0.7; }
  26%, 69% { opacity: 0; transform: translate(-50%, -50%) scale(1.06); }
  70% { opacity: 0; transform: translate(-50%, -50%) scale(0.94); }
  73% { opacity: 0.7; }
  81%, 100% { opacity: 0; transform: translate(-50%, -50%) scale(1.06); }
}
/* 3つのバナーは排他: 「置けたね。」(own1) → 「↓ New panel」(他人) → 「置けたね。」(own2)。
   実装のバナー優先順位（retry＞undo＞newChip のうちどれか1つ）と同じく、常に1つだけ出す。 */
/* バナーは**リールが止まってから**出す（コマが着地した合図なので、移動中に出ると早い）。 */
@keyframes sh-undo1-go {
  0%, 18% { opacity: 0; transform: translateY(6px); }
  21%, 32% { opacity: 1; transform: none; }
  35%, 100% { opacity: 0; transform: translateY(-4px); }
}
@keyframes sh-newpanel-go {
  0%, 40% { opacity: 0; transform: translateY(6px); }
  43%, 50% { opacity: 1; transform: none; }
  53%, 100% { opacity: 0; transform: translateY(-4px); }
}
@keyframes sh-undo2-go {
  0%, 72% { opacity: 0; transform: translateY(6px); }
  75%, 87% { opacity: 1; transform: none; }
  90%, 100% { opacity: 0; transform: translateY(-4px); }
}
/* 衝撃波リングと擬音。1周 7 秒のうち、鳴っているのは頭の 0.5〜0.6 秒だけ
   （実装の 0.5s / 0.6s ＝ 7.1% / 8.6%）。`--d` で own の2枚ぶんだけ位相をずらす
   （他人のコマ(n2)には付けない＝自分の行動の証拠を他人のコマに貼らない）。 */
@keyframes sh-ring-go {
  0% { transform: translate(-50%, -50%) scale(0.3); opacity: 0.9; }
  4.3% { opacity: 0.5; }
  7.1%, 100% { transform: translate(-50%, -50%) scale(15); opacity: 0; }
}
@keyframes sh-bam-go {
  0% { opacity: 0; transform: translate(-50%, -50%) scale(0.4) rotate(-14deg); }
  4.7% { opacity: 1; transform: translate(-50%, -140%) scale(1.15) rotate(4deg); }
  6.7% { opacity: 1; transform: translate(-50%, -150%) scale(0.95) rotate(-2deg); }
  8.6%, 100% { opacity: 0; transform: translate(-50%, -165%) scale(1) rotate(0deg); }
}
/* 指は送信ボタンの上に留まって own の2回だけ押す（他人のコマが降る間は手を離して待つ）。 */
@keyframes sh-t-write {
  0%, 6% { opacity: 0; transform: translate(333px, 771px) scale(1.35); }
  10% { opacity: 1; transform: translate(333px, 771px) scale(1); }
  16% { opacity: 1; transform: translate(333px, 771px) scale(0.78); }
  20%, 50% { opacity: 1; transform: translate(333px, 771px) scale(1); }
  71% { opacity: 1; transform: translate(333px, 771px) scale(0.78); }
  75%, 88% { opacity: 1; transform: translate(333px, 771px) scale(1); }
  94%, 100% { opacity: 0; transform: translate(333px, 771px) scale(1.35); }
}


@keyframes sh-caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* ── シート共通（②③）───────────────────────────────────────── */

@keyframes sh-sheetgo {
  0%, 9% { transform: translateY(100%); }
  22%, 88% { transform: none; }
  98%, 100% { transform: translateY(100%); }
}
@keyframes sh-scrimgo {
  0%, 9% { opacity: 0; }
  22%, 88% { opacity: 1; }
  98%, 100% { opacity: 0; }
}
/* シートを呼び出したボタンが沈む。実装の `:active` は `translateY(1px)` ＋ 影の反転で、
   ここでは合成で済む transform だけを写している（影まで動かすと明/暗2種のキーフレームが要る）。 */
@keyframes sh-press-open {
  0%, 7% { transform: none; }
  9%, 12% { transform: translateY(1px) scale(0.96); }
  17%, 100% { transform: none; }
}

/* ── ② 棚: 本棚ボタン(337,711) → 背表紙 Money(185,566) ───────────
   デフォルトで開いた瞬間に選ばれているのは**Everyday**（`useState(GENRES[0].id)`。
   実装はどの棚を読んでいてもシートは毎回 Everyday から開く）。指はそこから**Money**へ移す。
   x=185 は現行7背表紙（Dog-ears/Everyday/Love/Work/Money/Unsaid/[spacer]/Request）
   での Money の中心。背表紙の並びを変えたら測り直すこと。 */

@keyframes sh-t-shelf {
  0%, 2% { opacity: 0; transform: translate(337px, 711px) scale(1.35); }
  6% { opacity: 1; transform: translate(337px, 711px) scale(1); }
  8% { opacity: 1; transform: translate(337px, 711px) scale(0.78); }
  11% { opacity: 1; transform: translate(337px, 711px) scale(1); }
  15%, 24% { opacity: 0; transform: translate(337px, 711px) scale(1); }
  27% { opacity: 0; transform: translate(185px, 566px) scale(1.35); }
  31% { opacity: 1; transform: translate(185px, 566px) scale(1); }
  34% { opacity: 1; transform: translate(185px, 566px) scale(0.78); }
  37%, 50% { opacity: 1; transform: translate(185px, 566px) scale(1); }
  58%, 100% { opacity: 0; transform: translate(185px, 566px) scale(1.35); }
}
/* 選択が Everyday から Money へ移る。背表紙は実際に伸び縮みするので
   width / height を動かす（合成では済まないが、動くのは7本の細い矩形だけ）。 */
@keyframes sh-spine-off {
  0%, 34% { width: 38px; height: 108px; border-radius: 4px 4px 1px 1px; box-shadow: 0 -3px 0 var(--ink); font-size: 13px; }
  38%, 88% { width: 32px; height: 92px; border-radius: 2px; box-shadow: none; font-size: 12px; }
  97%, 100% { width: 38px; height: 108px; border-radius: 4px 4px 1px 1px; box-shadow: 0 -3px 0 var(--ink); font-size: 13px; }
}
@keyframes sh-spine-on {
  0%, 34% { width: 32px; height: 92px; border-radius: 2px; box-shadow: none; font-size: 12px; }
  38%, 88% { width: 38px; height: 108px; border-radius: 4px 4px 1px 1px; box-shadow: 0 -3px 0 var(--ink); font-size: 13px; }
  97%, 100% { width: 32px; height: 92px; border-radius: 2px; box-shadow: none; font-size: 12px; }
}
/* 平台と冊数表示の入れ替え */
@keyframes sh-swap-a { 0%, 34% { opacity: 1; } 38%, 88% { opacity: 0; } 97%, 100% { opacity: 1; } }
@keyframes sh-swap-b { 0%, 34% { opacity: 0; } 38%, 88% { opacity: 1; } 97%, 100% { opacity: 0; } }
/* 表紙はゆっくり流れるが、**選んでいる間は止まる**（動く的は押せない）。 */
@keyframes sh-coverdrift {
  0% { transform: translateX(0); }
  25%, 52% { transform: translateX(-34px); }
  100% { transform: translateX(-148px); }
}

/* ── ③ ウサＱ: ボタン(46,503) → 候補チップ(150,469) ───────────── */

/* ウサＱは**2往復**する: ①候補から選ぶ → ②候補に無いことを自分で打つ。
   ボタン(46,715) → 候補チップ(225,681) → ペン入れ(150,772) → 送信(330,772)。 */
@keyframes sh-t-qbbit {
  0%, 2% { opacity: 0; transform: translate(46px, 715px) scale(1.35); }
  6% { opacity: 1; transform: translate(46px, 715px) scale(1); }
  8% { opacity: 1; transform: translate(46px, 715px) scale(0.78); }
  11% { opacity: 1; transform: translate(46px, 715px) scale(1); }
  14%, 21% { opacity: 0; transform: translate(46px, 715px) scale(1); }
  24% { opacity: 0; transform: translate(225px, 681px) scale(1.35); }
  27% { opacity: 1; transform: translate(225px, 681px) scale(1); }
  30% { opacity: 1; transform: translate(225px, 681px) scale(0.78); }
  33%, 40% { opacity: 1; transform: translate(225px, 681px) scale(1); }
  43% { opacity: 0; transform: translate(225px, 681px) scale(1); }
  45% { opacity: 0; transform: translate(150px, 772px) scale(1.35); }
  48% { opacity: 1; transform: translate(150px, 772px) scale(1); }
  50% { opacity: 1; transform: translate(150px, 772px) scale(0.78); }
  53%, 64% { opacity: 1; transform: translate(150px, 772px) scale(1); }
  67% { opacity: 1; transform: translate(330px, 772px) scale(1); }
  69% { opacity: 1; transform: translate(330px, 772px) scale(0.78); }
  72%, 80% { opacity: 1; transform: translate(330px, 772px) scale(1); }
  86%, 100% { opacity: 0; transform: translate(330px, 772px) scale(1.35); }
}
/* 打鍵（2往復目）。押してから伸び、送信で消える。 */
@keyframes sh-typeq {
  0%, 50% { max-width: 0; }
  64%, 69% { max-width: 210px; }
  70%, 100% { max-width: 0; }
}
/* プレースホルダは打ち始めたら消える。 */
@keyframes sh-phq {
  0%, 50% { opacity: 1; }
  53%, 69% { opacity: 0; }
  72%, 100% { opacity: 1; }
}
/* 打っている間だけカーソルを出す（点滅と両立させるため visibility で切る）。 */
@keyframes sh-caretq {
  0%, 51% { visibility: hidden; }
  53%, 69% { visibility: visible; }
  70%, 100% { visibility: hidden; }
}
/* 押された候補が沈んで、そのまま**選ばれた形（黒）**で残る */
@keyframes sh-chippress {
  0%, 29% { transform: none; background: var(--paper); color: var(--ink); }
  31% { transform: scale(0.94); background: var(--ink); color: var(--paper); }
  36%, 88% { transform: none; background: var(--ink); color: var(--paper); }
  95%, 100% { transform: none; background: var(--paper); color: var(--ink); }
}
/* 上段は選ぶ側。少しだけ送って「Can I delete?」を画面の真ん中へ持ってきたら、
   **押し終わるまで止まる**（動く的は押せないし、押した先が読めない）。
   -130px は3枚目の左端 310px を 180px まで引き寄せる量＝指の x=225 と揃えてある。
   チップの文言や並びを変えたらこの2つを測り直すこと。 */
@keyframes sh-chipshold {
  0% { transform: translateX(0); }
  20%, 54% { transform: translateX(-130px); }
  100% { transform: translateX(-50%); }
}
/* 回答のコマは、押す（打つ）まで**そもそも無い**。まだ聞いていないので当然。
   ①候補を押した直後 → ②自分で打って送った直後、の2枚が順に返る。 */
@keyframes sh-pop-q1 {
  0%, 32% { opacity: 0; transform: scale(0.82) rotate(-1.6deg); }
  37% { opacity: 1; transform: scale(1.03) rotate(0.5deg); }
  41%, 88% { opacity: 1; transform: none; }
  95%, 100% { opacity: 0; transform: scale(0.82) rotate(-1.6deg); }
}
@keyframes sh-pop-q2 {
  0%, 70% { opacity: 0; transform: scale(0.82) rotate(1.4deg); }
  75% { opacity: 1; transform: scale(1.03) rotate(-0.5deg); }
  79%, 88% { opacity: 1; transform: none; }
  95%, 100% { opacity: 0; transform: scale(0.82) rotate(1.4deg); }
}

/* ── 割り当て ─────────────────────────────────────────────────
   `.js` 付きなのは JS が無いときに 0% の姿で固まらせないため（下の停止リストと同じ理由）。 */

.js .sh-touch { animation: 7s ease-in-out infinite; }
.js .sh-touch--write { animation-name: sh-t-write; }
.js .sh-touch--shelf { animation-name: sh-t-shelf; }
.js .sh-touch--qbbit { animation-name: sh-t-qbbit; }

.js .sh-typed--1 { animation: sh-type1 7s linear infinite; }
.js .sh-typed--2 { animation: sh-type2 7s linear infinite; }
.js .sh-caret { animation: sh-caret 1s steps(1) infinite, sh-caretshow 7s step-end infinite; }
/* 送信ボタンが沈むのは own の2回だけ（他人のコマが降る間、入力欄は裏で待っているだけ）。 */
.js .sh-input:not(.sh-input--idle) .sh-send { animation: sh-press 7s ease-out infinite; }
.js .sh-reel { animation: sh-reel-go 7s cubic-bezier(0.32, 0.72, 0, 1) infinite; }
.js .sh-koma--n1 { animation: sh-pop1 7s cubic-bezier(0.2, 1.5, 0.4, 1) infinite; }
.js .sh-koma--n2 { animation: sh-pop2 7s ease-out infinite; }
.js .sh-koma--n3 { animation: sh-pop3 7s cubic-bezier(0.2, 1.5, 0.4, 1) infinite; }
.js .sh-flash { animation: sh-flashgo 7s ease-out infinite; }
.js .sh-banner--undo1 .sh-undo { animation: sh-undo1-go 7s ease-out infinite; }
.js .sh-banner--newpanel .sh-newpanel { animation: sh-newpanel-go 7s ease-out infinite; }
.js .sh-banner--undo2 .sh-undo { animation: sh-undo2-go 7s ease-out infinite; }
.js .sh-ring { animation: sh-ring-go 7s cubic-bezier(0.15, 0.7, 0.3, 1) infinite; animation-delay: var(--d, 0s); }
.js .sh-bam { animation: sh-bam-go 7s cubic-bezier(0.3, 1.5, 0.6, 1) infinite; animation-delay: var(--d, 0s); }

.js .sh-sheet { animation: sh-sheetgo 7s ease-in-out infinite; }
.js .sh-scrim { animation: sh-scrimgo 7s ease-in-out infinite; }
/* 沈むのは、その画面で実際に押される1つだけ（`sh-btn--press` が付いたほう）。 */
.js .sh-btn--press { animation: sh-press-open 7s ease-out infinite; }

.js .sh-spine--on { animation: sh-spine-off 7s ease-in-out infinite; }
.js .sh-spine--pick { animation: sh-spine-on 7s ease-in-out infinite; }
.js .sh-flat--a,
.js .sh-count--a { animation: sh-swap-a 7s ease-in-out infinite; }
.js .sh-flat--b,
.js .sh-count--b { animation: sh-swap-b 7s ease-in-out infinite; }
.js .sh-flat { animation: sh-coverdrift 7s ease-in-out infinite; }
.js .sh-flat--a { animation: sh-swap-a 7s ease-in-out infinite, sh-coverdrift 7s ease-in-out infinite; }
.js .sh-flat--b { animation: sh-swap-b 7s ease-in-out infinite, sh-coverdrift 7s ease-in-out infinite; }

.js .sh-chips--ask { animation: sh-chipshold 7s linear infinite; }
.js .sh-chips--do { animation: sh-marq 17s linear infinite reverse; }
.js .sh-chip--tap { animation: sh-chippress 7s ease-out infinite; }
.js .sh-aa-f { animation: sh-aa2 1.1s steps(1, end) infinite; }
.js .sh-aa-f--2 { animation-delay: -0.55s; }
.js .sh-koma--q1 { animation: sh-pop-q1 7s cubic-bezier(0.2, 1.5, 0.4, 1) infinite; }
.js .sh-koma--q2 { animation: sh-pop-q2 7s cubic-bezier(0.2, 1.5, 0.4, 1) infinite; }
.js .sh-typed--q { animation: sh-typeq 7s linear infinite; }
.js .sh-ph--q { animation: sh-phq 7s step-end infinite; }
.js .sh-caret--q { animation: sh-caret 1s steps(1) infinite, sh-caretq 7s step-end infinite; }

/* ── 「持たない」もの（白い線で消した語）────────────────────────
 * **掲げない。**（2026-08-10 降格）
 * ここは以前 2.9rem の語を3つ縦に積んでいて、見出しより大きい“看板”になっていた。
 * だが No Account / No Follows / No Likes は **制約の一覧であって売り文句ではない**
 * （CLAUDE.md 冒頭）。掲げるのはメインメッセージの2行だけ。
 * 打ち消し線の意匠は残しつつ、字を本文の隣の大きさまで落として**一覧に戻す**。
 * 広い画面では3つを横に並べる——縦に積むと1つずつが主張し、一覧に見えない。 */

.nots {
  margin: var(--space-m) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--space-s);
}

.nots .word {
  position: relative;
  display: inline-block;
  font-family: var(--display);
  font-size: clamp(1.15rem, 4.6vw, 1.4rem);
  line-height: 1.1;
  color: var(--paper);
}

/* 一本の線で消す */
.nots .word::after {
  content: "";
  position: absolute;
  left: -3%;
  right: -3%;
  top: 55%;
  height: clamp(3px, 0.6vw, 4px);
  background: var(--paper);
  transform: rotate(-1.1deg);
}
.nots li:nth-child(even) .word::after { transform: rotate(0.9deg); }

.nots .why {
  display: block;
  margin-top: 0.3rem;
  font-size: var(--fs-small);
  letter-spacing: 0.02em;
  color: var(--chalk-soft);
}

/* ── 打ち消し語を**コマの中**に入れたとき（節01・2026-08-13）──────────
 * 見出し「Nobody keeps score.」が言っていることを、説明文でなく**消された3語**で
 * 見せる。以前はコマの外（黒地）に理由文（`.why`）つきで置いていたが、
 *   ① 節01だけ言葉の量が 02〜04 と揃わず重かった
 *   ② 消された語は"読む一覧"ではなく**一目で分かる絵**なので、理由文は要らない
 * の2点で、コマの中へ移して語だけにした。`.why` は書いても効くように残してある。
 *
 * 紙の上に乗るので、白で引いていた線と字を**墨に反転**する（黒地用の値のままだと
 * 白い字＋白い線＝紙に埋もれて消える）。 */
.koma .nots {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.35rem 1.5rem;
}
/* 広い画面の `.nots li`（9rem の2カラム）は理由文があるときの組みなので、
   コマの中では効かせない。 */
.koma .nots li { display: block; }
.koma .nots .word {
  color: var(--ink);
  /* コマの中では見出し（セリフ）より小さく保つ。主役はあくまでフキダシ。 */
  font-size: clamp(0.95rem, 3.6vw, 1.15rem);
}
.koma .nots .word::after { background: var(--ink); }
.koma .nots .why { color: #4a4a48; }

/* 節のしめくくりに置く補足（節を3つに絞ったぶん、ここで少しだけ説明する）。 */
.note {
  max-width: 40em;
  margin-top: var(--space-s);
}

/* ── 最後の呼びかけ ────────────────────────────────────────── */

/* 締めの一言。**`h1` ではなく段落**（2026-08-10）——`h1` はページに1つ、
   ヒーローの中央のコマだけ。見た目は変えず、見出しの階層だけを正す。
   前の節との間は 2M（=L）に加えてもう一段 L を足し、ここだけ息を長く取る。 */
.finale {
  text-align: center;
  padding-top: var(--space-l);
}
.finale-line {
  margin: 0;
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--fs-display);
  line-height: 1.16;
  color: var(--paper);
  text-wrap: balance;
}
.finale .cta-row { justify-content: center; }

/* ── Sharaku紹介 + ウェイトリストフォーム(ウェイトリスト版だけ・上のトグル参照) ── */
.maker {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  max-width: 28em;
  margin: var(--space-m) auto 0;
  text-align: left;
}
.maker-photo {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--paper);
  flex: none;
}
.maker-name {
  margin: 0;
  font-family: var(--display);
  font-size: 0.95rem;
  color: var(--paper);
}
.maker-bio {
  margin: 0.3rem 0 0;
  font-size: var(--fs-small);
  color: var(--chalk-soft);
  line-height: 1.6;
}

.waitlist-form {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  max-width: 28em;
  margin: var(--space-m) auto 0;
}
.waitlist-form input[type="email"] {
  flex: 1 1 14rem;
  background: transparent;
  border: 2px solid var(--edge);
  color: var(--chalk);
  padding: 0.72rem 0.9rem;
  font-size: 1rem;
  font-family: var(--body);
  border-radius: 2px;
}
.waitlist-form input[type="email"]::placeholder { color: var(--chalk-soft); }
.waitlist-form input[type="email"]:focus-visible {
  outline: 3px solid var(--paper);
  outline-offset: 1px;
}
.waitlist-form .cta { border: 0; cursor: pointer; }
.waitlist-form .cta[disabled] { opacity: 0.5; cursor: default; }
.waitlist-form .form-status {
  flex-basis: 100%;
  margin: 0.4rem 0 0;
  font-size: var(--fs-small);
  color: var(--chalk);
}
.waitlist-form .form-status[hidden] { display: none; }

/* ハニーポット: 人には見えず、読み上げにも出ず、タブでも止まらない(style.css の .hp と同じ考え方)。 */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ── 登録成功ポップ(2026-08-17) ────────────────────────────────
   `.hero-center` と同じ「黒い紙に紙の縁」の語彙を流用する(この紙面で唯一の
   浮き上がるカードの作法なので、新しい見た目を増やさない)。 */
.modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-s);
}
.modal[hidden] { display: none; }
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.72);
}
.modal-card {
  position: relative;
  width: min(22rem, 100%);
  background: var(--void);
  border: 3px solid var(--paper);
  box-shadow: 7px 7px 0 rgba(0, 0, 0, 0.55);
  padding: clamp(1.3rem, 5vw, 1.8rem);
  text-align: center;
}
.modal-card:focus-visible { outline: 3px solid var(--paper); outline-offset: 3px; }
.modal-title {
  margin: 0;
  font-family: var(--display);
  font-size: 1.3rem;
  color: var(--paper);
}
.modal-body {
  margin: 0.6rem 0 1.3rem;
  font-size: var(--fs-small);
  color: var(--chalk-soft);
}

/* ── 奥付（フッタ）─────────────────────────────────────────── */

/* 奥付だけは線を残す（節の区切り線は外したが、ここは本文の外＝別の紙という合図）。 */
.colophon {
  border-top: 1px solid var(--edge);
  padding: var(--space-m) var(--pad-x);
}

.colophon-inner {
  max-width: 62rem;
  margin: 0 auto;
  display: grid;
  gap: var(--space-s);
}

.colophon h2 {
  font-family: var(--body);
  font-size: var(--fs-label);
  font-weight: 900;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--chalk-soft);
  margin-bottom: 0.5rem;
}

.colophon ul { margin: 0; padding: 0; list-style: none; font-size: 0.88rem; }
.colophon li { margin: 0.25rem 0; }

.colophon-end {
  max-width: 62rem;
  margin: var(--space-m) auto 0;
  padding-top: var(--space-s);
  border-top: 1px solid var(--edge);
  font-family: var(--serif);
  font-weight: 700;
  font-size: 0.84rem;
  color: var(--chalk-soft);
}

/* ウェイトリスト版では `.colophon-inner` の3列が丸ごと隠れる(data-launch-only)ので、
   `.colophon` 自身の border-top と、この `.colophon-end` の border-top が、
   空白を挟んで2本並ぶだけの見た目になってしまう(2026-08-17 報告)。
   線は「本文の外＝別の紙という合図」が役目(このファイル冒頭の奥付コメント参照)なので
   1本で足りる——外側の `.colophon` の線をそのまま残し、こちらは消す。 */
html:not(.launch) .colophon-end {
  border-top: 0;
  padding-top: 0;
}

/* よくあるアプリ公開前ページの「SNSハンドルだけ添える」形(2026-08-17)。実在の
   アカウントが確定していないので、リンクは張らずスタンプのような表記だけ置く
   (確定したらここを <a href="https://..."> に変えるだけでよい)。 */
.colophon-handle {
  display: inline-block;
  margin-left: 0.5em;
  font-family: var(--body);
  font-weight: 900;
  color: var(--chalk-soft);
}

/* ── 現れ方（刷り上がる）───────────────────────────────────── */

.js .reveal { opacity: 0; transform: translateY(12px); }
.js .reveal.inked { animation: ink-in 0.5s cubic-bezier(0.2, 0.8, 0.3, 1) forwards; }

@keyframes ink-in {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: none; }
}

/* **節のコマは「ポンッ」と生まれる**（2026-08-15）。ヒーローで新しいコマが置かれるのと
   同じ動き（`koma-pop`）を使い回す——アプリでも投稿した瞬間にコマがこう出るので、
   節01〜04 が縦に積む4コマも同じ生まれ方をするのが筋。
   刷り上がる（`ink-in`＝下からすっと現れる）ほうは**コマでないもの**に残す
   ＝実機の複製（`.shot-frame`）。あれは1枚の画面であってコマではないので、
   ポンッと弾むと「端末が跳ねた」ように見える。 */
.js .koma.reveal.inked {
  animation: koma-pop 0.42s cubic-bezier(0.2, 1.5, 0.4, 1) both;
}

/* ── 動きを止める（全部止めても読める）──────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .reveal { opacity: 1; transform: none; }
  .js .reveal.inked,
  .js .koma.reveal.inked { animation: none; }
  .cta { transition: none; }
  .slot .panel.pop { animation: none; }
  .slot { transition: none; }
  .stage-flash { display: none; }
  /* 新着の知らせは出しっぱなしにする（点滅させない）。 */
  .js .hero-toast { animation: none; opacity: 1; transform: translateX(-50%); }

  /* 実画面の複製の動きも全部止める。**止めた状態が「選び終わった1枚」になる**よう、
     アニメで初期値が 0 のもの（打ちかけの文字・シート・回答のコマ・選択の入れ替え）は
     ここで静止時の見え方を明示する——`animation:none` だけだと 0% の姿
     （文字幅0・シートが画面外・回答が無い・指が消えている）で固まり、絵にならない。
     指そのものは動きの説明でしかないので、止めるときは消す。 */
  .js .sh-touch { animation: none; display: none; }
  .js .sh-typed { animation: none; max-width: 0; }
  .js .sh-caret { animation: none; visibility: hidden; }
  .js .sh-send { animation: none; transform: none; }
  .js .sh-btn--press { animation: none; transform: none; }
  /* 止めた状態＝3拍子を終えたところ（リールは最後まで上がり、3枚とも出ている）。 */
  .js .sh-reel { animation: none; transform: translateY(-563px); }
  .js .sh-koma--new { animation: none; opacity: 1; transform: none; }
  .js .sh-koma--n1,
  .js .sh-koma--n2,
  .js .sh-koma--n3 { animation: none; opacity: 1; transform: none; }
  .js .sh-flash { animation: none; display: none; }
  /* 止めた状態＝own の2回目「置けたね。」が出ているところで固定する
     （他人のコマ(n2)が降った直後の「↓ New panel」は一瞬の知らせなので、
     静止画としては own の肯定のほうを残す）。 */
  .js .sh-banner--undo1 .sh-undo,
  .js .sh-banner--newpanel .sh-newpanel { animation: none; opacity: 0; }
  .js .sh-banner--undo2 .sh-undo { animation: none; opacity: 1; transform: none; }
  /* 擬音と衝撃波は「置いた瞬間」だけの単発演出なので、止めるときは**消す**
     （既定の opacity:0 に戻すだけだと transform だけ残って中途半端な位置に居残る）。 */
  .js .sh-ring,
  .js .sh-bam { animation: none; display: none; }
  .js .sh-sheet { animation: none; transform: none; }
  .js .sh-scrim { animation: none; opacity: 1; }
  /* 選び終わった状態＝Everyday の棚を開いたところで止める。 */
  .js .sh-spine--on { animation: none; width: 32px; height: 92px; border-radius: 2px; box-shadow: none; font-size: 12px; }
  .js .sh-spine--pick { animation: none; width: 38px; height: 108px; border-radius: 4px 4px 1px 1px; box-shadow: 0 -3px 0 var(--ink); font-size: 13px; }
  .js .sh-flat--a,
  .js .sh-count--a { animation: none; opacity: 0; }
  .js .sh-flat--b,
  .js .sh-count--b { animation: none; opacity: 1; }
  .js .sh-aa-f { animation: none; }
  .js .sh-chip--tap { animation: none; background: var(--ink); color: var(--paper); }
  .sh-flat,
  .sh-chips { animation: none; transform: none; }
}

/* ── 広い画面 ───────────────────────────────────────────────── */

@media (min-width: 34rem) {
  /* リードの行を手で切る（狭い画面では効かせない）。 */
  .br-md { display: inline; }
  /* 語と理由を1行に組んで**一覧の見た目**にする（縦に積むと1つずつが主張する）。
     3列に割るのは試したが、`.why` が1行4語まで痩せて読めなくなるのでやめた。 */
  .nots li {
    display: grid;
    grid-template-columns: 9rem minmax(0, 1fr);
    align-items: baseline;
    gap: var(--space-s);
  }
  .nots .why { margin-top: 0; }
  .strip--2 { display: flex; }
}

@media (min-width: 52rem) {
  .colophon-inner { grid-template-columns: repeat(3, 1fr); gap: 2rem; }
  .strip--3 { display: flex; }
}
