# 文字演出レイヤー(擬音・独白・テロップ・バッジ)のスタイル設定 ── Step1
#
# 元画像は一切書き換えない。ここで決めるのは「別出力PNGに載せる文字の見た目」だけ。
# 仕様の出どころ: docs/design/mosaic-overlay-spec.md §2 / docs/design/story-layer-spec.md
#
# ★フォントの扱い(docs/design/scene-sfx-coverage-audit.md §8 の決定)
#   同梱してよいのは OFL フォントか自作グリフのみ。**システムフォントは同梱不可**。
#   → 2026-08-06 に源暎一式(御琥祢屋・すべて SIL OFL 1.1)を下の font_files: へ配線済み。
#   font: も font_files: も外すと pipeline/thumbnail.py の FONT_CANDIDATES
#   (macOSのヒラギノ等)に落ちる。これは同梱不可なうえ、**Mac以外では die する**ので
#   null に戻してはいけない。
#   ※ 旧コメントが挙げていた「ラテゴ(GenEiLateGoN-U.ttf)」はディスクに無い。エムゴを使う。

# ページキャンバス。既定は生成画像の実寸(832x1216)に合わせる。
# null なら元画像と同じ寸法をそのまま使う。
canvas: null

# ── 出力モード(ユーザー決定 2026-07-26) ─────────────────────────
# 「CG集(擬音だけ)」と「ちょい漫画風(擬音+セリフ)」を選べるようにする。
# 「完全漫画版(吹き出し+コマ割)」は Step2/3。**未実装なので実行させない**。
mode: manga_lite            # 既定=ちょい漫画風(参考作品に近い見た目)
modes:
  sfx_only:
    label_ja: "CG集(擬音だけ)"
    note: "絵を主役にして擬音だけを載せる。CG集の体裁"
    fit: full
    kinds: [sfx]
    implemented: true
  manga_lite:
    label_ja: "ちょい漫画風(擬音+セリフ)"
    note: "擬音に加えて独白・時間経過テロップ・進行バッジまで載せる。話の流れが分かる"
    fit: full
    # ★2026-08-21: badge(「7回目」)を既定から外した。
    #   これは読者に向けた意味ではなく、**制作内部の climax ページ通し番号**を
    #   そのまま出していただけで、作った本人にも意味が伝わらなかった(オーナー実測)。
    #   出す仕組み(overlay.py の badge 出力と辞書の {n}回目)は残してある。
    #   「回数」を作品の演出として意図して使うときだけ、ここへ戻す。
    kinds: [sfx, mutter, telop]
    implemented: true
  manga_full:
    label_ja: "完全漫画版(吹き出し+コマ割)"
    note: "吹き出し4種・ナレーション枠・ルビ・コマ割。Step2/3 で実装予定"
    fit: full
    kinds: [sfx, mutter, telop, badge, balloon, narration]
    implemented: false      # ★画面では「準備中」と出し、黙って中途半端な出力を作らない

# ページ体裁。モードが指定していればそちらが優先。画像ごとに切り替えられる。
#   margin = CGを内側に収め、余白に文字を置く(モザイクと絶対に干渉しない・可読性が高い)
#   full   = CGを全面に置き、文字を画像の上に載せる(参考作品の見た目・干渉検査が働く)
fit: full

# fit: margin のときのレイアウト(キャンバス短辺/長辺に対する比)
margin_layout:
  pad_x: 0.055          # 左右の余白
  pad_top: 0.055        # 上の余白(環境音の擬音を横書きで置く帯)
  pad_bottom: 0.155     # 下の余白(ナレーション・独白を横書きで置く帯)
  bg: [252, 250, 246]   # 余白の地色
  border: null          # CG外周の罫線(不要なら null)。例: [30, 30, 30]

# fit: full のときの設定
full_layout:
  bg: [255, 255, 255]
  safe_margin: 0.025    # 判型端からの安全マージン(文字を端に寄せすぎない)

# ★2026-08-06 配線: すべて OFL(SIL Open Font License 1.1)。同梱可・成人向け可。
#   ここが null だと macOS のヒラギノに落ちる = 同梱不可 かつ Mac以外では die する。
#   パスはリポジトリ相対。存在しないパスは無視して font: に落ちる。
font: fonts/genei/GenEiMGothic_v2.0/GenEiMGothic_v2.0/GenEiMGothic2-Regular.ttf
font_files:
  # 擬音: 源暎ぽっぷる。story-layer-spec.md:298 の実測で「擬音の主力」。全字あり
  sfx: fonts/genei/GenEiPOPle_v1.0/GenEiPOPle_v1.0/GenEiPOPle-Bk.ttf
  # セリフ・独白: 源暎アンチック。fonts/README.md:36「セリフの本命」
  mutter: fonts/genei/GenEiAntique_v6.0a/GenEiAntique_v6.0a/GenEiAntiqueNv6-M.ttf
  telop: fonts/genei/GenEiMGothic_v2.0/GenEiMGothic_v2.0/GenEiMGothic2-Bold.ttf
  badge: fonts/genei/GenEiMGothic_v2.0/GenEiMGothic_v2.0/GenEiMGothic2-Heavy.ttf
  notice: fonts/genei/GenEiMGothic_v2.0/GenEiMGothic_v2.0/GenEiMGothic2-Regular.ttf

# 本命フォントが持っていない字の肩代わり(縦書きのみ・上から順に試す)。
#   ★実測 2026-08-06: Otomanopee は ♡ と一部の漢字(度断次深翌臓誰震)を持たない。
#   ♡ はエロ擬音の必需品なので、擬音フォントを差し替えるときはここが効く。
font_fallbacks:
  - fonts/genei/GenEiPOPle_v1.0/GenEiPOPle_v1.0/GenEiPOPle-Bk.ttf
  - fonts/genei/GenEiMGothic_v2.0/GenEiMGothic_v2.0/GenEiMGothic2-Heavy.ttf

# ── 文字を置きたくない場所 ───────────────────────────────────
# ★2026-08-07 参考作品509ページの実測(sfx-placement-grammar-2026-08-07.md):
#     ・**顔の上には一度も文字が来ていなかった**
#     ・一方 **胴・脚・相手の体には平気で重ねていた**
#   → 避けるのは「顔」だけでよい。人物全体を避ける必要はない(避けたら置く場所が無い)。
avoid:
  use_face_detect: true          # 実際に顔を検出して避ける(1枚あたり数百ms・結果は控える)
  face_pad: 0.05                 # 顔枠の外側にとる余白(短辺比)
  # 顔検出が使えない/失敗したときの保険。縦長の絵で顔が来やすい範囲
  face_band: {x: 0.24, y: 0.0, w: 0.52, h: 0.34}

# ── 擬音を引き寄せる目印(2026-08-07) ─────────────────────────
# ★最大の発見: **確定モザイク枠は「避ける対象」ではなく「引き寄せる目印」だった**。
#   参考作品の打撃音・液体音は結合部の **すぐ外側に放射状** に置かれている。
#   重ねないのは正しいが、遠ざけるのは間違いだった(2026-08-06 の実装は逆)。
attract:
  ring_min: 0.16                 # 目印の中心からの距離(短辺比)。この内側には置かない
  ring_max: 0.46                 # ここまでの範囲に散らす
  fallback: face_side            # 目印が無い絵は顔の脇に置く(声・心理音の定位置)

# ── 種類ごとの大きさ(2026-08-07 実測) ────────────────────────
# ★同じ大きさにしてはいけない。
#   **描き文字**は文字そのものが絵なので、枠いっぱいに字が入っている。
#   **吹き出し込みのセリフ**は枠の中に小さい字が入っているので、
#   描き文字と同じ大きさにすると **中の字が読めない**(実物で確認)。
#   参考作品でも吹き出しは画面幅の1/4ほどあった。
# ★2026-08-07 更新: 大きさは **役割**(絵の形から測ったもの)で決めるのが本線。
#   種類(voice/fluid…)は「何の音か」であって「絵の大きさ」ではない。
#   実測で吹き出しは埋まり具合 0.66〜0.81、描き文字は 0.30〜0.35 と2倍以上離れており、
#   販売者が何も書いていなくても形だけで見分けられる。
asset_height_by_role:
  balloon:   0.30     # 吹き出し込み(セリフ・喘ぎ)。枠の中の字を読ませる
  lettering: 0.15     # 描き文字。文字そのものが絵
  sheet:     1.00     # 敷き詰めシートは1枚で画面いっぱい

# ── 1ページに置ける数の上限(役割ごと) ────────────────────────
# ★セリフ(吹き出し)は1ページ1個(2026-08-07 ユーザー指定)。
#   吹き出しは画面の30%と大きく、2個入ると場所を取り合って重なりの原因になる。
#   種類も多くないので、1ページ1個で十分という判断。
role_limits:
  balloon: 1

# ── 1つの商品にそろえる種類(2026-08-07 ユーザー指摘) ──────────
# ★吹き出しは **商品ごとに絵柄が違う**(トゲトゲ / 細い楕円 / もこもこ雲)。
#   色(番号)を揃えても7商品が混ざると「別のモデルを使っている」ように見える。
#   描き文字は同じ作者の手描きなので混ざっても揃って見える(実物で確認)。
#   どの商品を使うかは在庫の多いものを自動で選ぶ(作品ごとに固定される)。
#   ★2026-08-07 更新: 語が分かる素材(ふきだし①②③)は3商品とも同じ絵柄なので、
#     商品を1つに絞らなくても揃う。ここは空にして、下の known_word_categories に任せる。
one_source_categories: [voice]

# ── 中身(語)が分かる素材を優先する種類 ────────────────────────
# ★セリフ素材は480枚すべて「何と書いてあるか分からない」(2026-08-07 実測)。
#   ファイル名が番号だけで、OCR も効かない(「ドプ」→「O-」自信度0.43)。
#   中身を知らずに置くので、相手が居ない場面に「もっとぎゅってして」が出た。
#   語が分かる素材(ふきだし①②③=198枚)だけを使えば、場面に合わないものが出ない。
#   語が分かる素材が1つも無い環境では、従来どおり全部を候補にする(止まらない)。
known_word_categories: [voice]

# 役割が入っていない古いパック用の受け皿(種類で決める従来の表)
asset_height_by_category:
  voice:    0.30      # 吹き出し込みの喘ぎ声・セリフ。中の字を読ませる
  reaction: 0.20      # 強調・大きい描き文字
  scenery:  0.13      # 環境音は控えめ
  contact:  0.15
  rhythm:   0.15
  fluid:    0.15

# ── 作品ごとのデザイン(表現パターン) ─────────────────────────
# ★1つの作品の中で文字の見た目をそろえるための設定(2026-08-07 ユーザー指定)。
#   市販の素材集は1語につき2〜10通りの表現(赤縁・黒塗り・白抜き…)が入っていて、
#   区別せずに置くと1ページの中でピンク・オレンジ・黒が同居し、統一感が消える。
#   既定はユーザー承認済みの「ピンク＋白フチ」。画面のサムネイルで変えられる。
#   その仲間を持たない素材では、いちばん近い仲間へ自動で寄せる(空にはしない)。
sfx_design: pink_white

# ── 場面ごとの擬音の数(2026-08-07 実測) ──────────────────────
# 参考作品では、着衣の会話ページに行為音は1つも無く、心理音が1〜2個だけだった。
# 絶頂ページでは打撃音が8〜12個 散っていた。**場面で数が3段階に変わる**。
# ★2026-08-07 ユーザー指摘で変更: **服を着ている場面には文字を置かない**。
#   実物で「相手が居ないのに『もっとぎゅってして』」「ブザー音のブーブー」が出た。
#   いま持っている素材に、着衣の場面で使える擬音・セリフが無いのが理由。
#   情景音(蝉時雨など)の素材が入ったら、ここを 1 に戻す。
sfx_counts:
  intro:     {light: 0, standard: 0, heavy: 0}
  approach:  {light: 0, standard: 0, heavy: 0}
  foreplay:  {light: 2, standard: 4, heavy: 6}
  main:      {light: 3, standard: 5, heavy: 7}
  climax:    {light: 5, standard: 9, heavy: 12}
  afterglow: {light: 1, standard: 2, heavy: 3}
  "":        {light: 1, standard: 2, heavy: 3}

# ── 場面カード → その場面で鳴る音(2026-08-07 ユーザー指摘) ────
# ★これが無いと「正常位の場面に胸を揉む音」「指の場面に胸の音」が出る(実際に出た)。
#   原因は、場面を5段階(導入・接近・前戯・中核・絶頂)でしか見ていなかったこと。
#   ツールは場面カード(main_missionary / fore_fellatio …)まで持っていて、
#   買った素材も販売元が行為別(1_挿入 / 3_フェラ・キス / 4_胸 …)に分けている。
#   **ほぼ1対1で対応するのに、繋いでいなかっただけ**。
#
#   左が場面カードの名前(前方一致)、右がその場面で鳴ってよい行為。
#   先に書いたものが勝つので、長い名前を先に置く。
#   ここに無いカードは行為を限定しない(従来どおり種類と段階だけで選ぶ)。
card_acts:
  climax_creampie:    [ejaculate, insert]
  climax_in_mouth:    [ejaculate, oral]
  climax_on_breasts:  [ejaculate, breast]
  climax:             [ejaculate, insert]
  fore_fellatio:      [oral]
  fore_irrumatio:     [oral]
  fore_cunnilingus:   [oral, finger]
  fore_fingering:     [finger]
  fore_handjob:       [hand, finger]
  fore_paizuri:       [breast]
  main:               [insert]          # main_* は全部 挿入(正常位・騎乗位・後背位…)
  app_behind:         [embrace]
  app_pulled:         [embrace]
  app_shoulder:       [embrace]
  app_neck:           [embrace, oral]
  app_kneel:          [embrace]
  app_futon:          [embrace]
  app_collar:         [embrace]
  intro:              []                # 導入は行為音を鳴らさない(環境音と声だけ)

# ── 種類ごとに「出てよい場面」(2026-08-07) ────────────────────
# ★ユーザーは取り込みのとき **種類しか選ばない**。段階はツールが決める(操作を増やさない)。
#   これが無いと「液体音」の素材が着衣の導入シーンに出る(実際に起きた)。
sfx_scope:
  scenery:  [intro, approach, afterglow]       # 環境音: 情景
  voice:    [approach, foreplay, main, climax, afterglow]
  contact:  [foreplay, main, climax]           # 行為音・接触音
  rhythm:   [main, climax]                     # 打撃音
  fluid:    [main, climax]                     # 液体音。**着衣の場面には絶対に出さない**
  reaction: [climax]                           # 反応・強調

# ── kind ごとの見た目 ──────────────────────────────────────────
# size は「キャンバス短辺に対する比」。stroke は文字サイズに対する比。
styles:
  # 擬音: 筆風に見せたいので極太＋縁取り＋わずかな傾き
  sfx:
    size: 0.075
    # 承認済みPNGスタンプを使う場合の高さ。短辺に対する比(1未満)または px。
    # 対象語にスタンプが無いときは size を使う従来のフォント描画へ戻る。
    # ★2026-08-07 訂正: 最初 0.07 にしたが **半分の大きさで読めなかった**(実物で確認)。
    #   原因は測り方の誤り ── 縮小表示で目測し、判型も取り違えていた。
    #   原寸で測り直すと、参考作品の描き文字は **画面の高さの約11%**(短辺比で約0.15)。
    #   docs/design/sfx-placement-grammar-2026-08-07.md §2-2
    asset_height: 0.15
    fill: [18, 18, 18]
    stroke: [255, 255, 255]
    stroke_ratio: 0.13
    vertical: true
    rotate: -8            # 度。ばら撒くときは overlay.py が ±で散らす
    char_spacing: -0.06   # 擬音は詰めたほうが勢いが出る
    col_spacing: 0.15

  # 環境音・情景音: 余白帯に横書きで置く(参考作品Aの蝉時雨と同じ扱い)。
  # 帯は薄いので縦書きにすると絵の上まで垂れてキャラを跨いでしまう。
  sfx_ambient:
    size: 0.030
    fill: [30, 30, 30]
    stroke: [255, 255, 255]
    stroke_ratio: 0.16
    vertical: false
    rotate: 0
    auto_contrast: true

  # 独白・喘ぎ: 吹き出しなしの袋文字ベタ打ち(fit: full で画像の上に載せる)
  mutter:
    size: 0.046
    fill: [255, 255, 255]
    stroke: [25, 25, 25]
    stroke_ratio: 0.14
    vertical: true
    rotate: 0
    char_spacing: 0.02
    col_spacing: 0.30
    max_chars: 11         # この文字数で列を折り返す
    # 明るい背景では白抜きが読めないので、地色に応じて自動で反転する
    auto_contrast: true

  # 独白を余白帯に置くとき(fit: margin)。地色が明るいので黒字・横書き・折り返しあり。
  # ページ体裁を full に切り替えても読めるよう、白フチ＋自動反転を付けてある
  # (余白の上では白フチは見えないので、margin の見た目は変わらない)。
  mutter_margin:
    size: 0.032
    fill: [35, 32, 30]
    stroke: [255, 255, 255]
    stroke_ratio: 0.10
    vertical: false
    rotate: 0
    align: left
    line_spacing: 0.40
    wrap: true
    auto_contrast: true

  # 時間経過テロップ: 画面隅の小さい白箱＋黒太字＋黒枠
  telop:
    size: 0.034
    fill: [20, 20, 20]
    stroke: null
    vertical: false
    box:
      fill: [255, 255, 255, 235]
      outline: [20, 20, 20]
      width: 3
      pad_x: 0.5          # 文字サイズに対する内側余白
      pad_y: 0.25
      radius: 0

  # 進行カウンタのバッジ
  badge:
    size: 0.036
    fill: [235, 62, 140]
    stroke: [255, 255, 255]
    stroke_ratio: 0.16
    vertical: false

  # 巻末のフィクション表記など、地の文
  notice:
    size: 0.026
    fill: [40, 40, 40]
    stroke: null
    vertical: false
    align: center
    line_spacing: 0.45

# ── 自動配置(プールから割り当てるときの置き場所) ─────────────
# 単位はキャンバス比。fit: margin では余白帯の中に、full では安全域の内側に置く。
placement:
  sfx_margin_top:    {x: 0.94, y: 0.013, anchor: rt}   # 上の余白帯(横書き)
  sfx_margin_bottom: {x: 0.62, y: 0.700, anchor: lt}   # 絵の下寄り(行為音)
  # 全面配置のとき。環境音は隅(被写体を避ける)、行為音は行為点の近く。
  #   参考作品も環境音は隅・行為音は結合部近くで使い分けていた。
  #   中央寄りに環境音を置くと、寄りの絵で体の真ん中に載る(実測)。
  sfx_full_corner:   {x: 0.955, y: 0.045, anchor: rt}
  sfx_full:          {x: 0.66,  y: 0.60,  anchor: ct}
  mutter_margin:     {x: 0.075, y: 0.862, anchor: lt}  # 下の余白帯(横書き)
  mutter_full:       {x: 0.06, y: 0.10,  anchor: lt}
  telop:             {x: 0.965, y: 0.020, anchor: rt}
  badge:             {x: 0.965, y: 0.965, anchor: rb}
  notice:            {x: 0.50, y: 0.62,  anchor: cc}

# 1枚あたりの擬音の上限(docs/design/scene-sfx-coverage-audit.md §7-2)
# density は既存 pipeline/story.py の DENSITY_PHASES と同じ語を使う。
sfx_limits:
  none: 0
  light: 1
  standard: 2
  heavy: 3

# 同じ擬音をばら撒く演出(クライマックスのみ)。0 で無効。
scatter:
  climax_repeat: 4
  jitter: 0.16            # 位置のばらつき(キャンバス比)
  angle_jitter: 14        # 角度のばらつき(度)
