# scene card 定義(V1) ── story preset が weight按分で「確定的に」選ぶ場面カード。
#
# 非破壊: 既存 compositions/wildcards/recipes は不変更。これは"上に足す保証層"。
# expected_zones = モザイク「確認予定」(予告)。実マスクは生成後にユーザーが1枚ずつ確定。
# tier: main=かんたん用主要 / extra=こだわり温存 / restricted=既定OFF(こだわりで警告付ON)。
# camera_ok は体位と矛盾しないカメラ。story.py が camera_ok から順に割り当てて反復を散らす。
# pose/act は英語(構図プロンプト片)。intro/approach/afterglow は situation を使う。
#   ※ 2026-07-23: afterglow は「SFW寄り」ではなくなった(余韻の再定義で事後の痕跡まで描く)。
#   ※ 2026-07-31: situation_neutral(任意)を追加。V2 経路(PLATE 03 story_design)は場所を
#     scenes/story_settings_v2.yaml の setting から供給するため、カード側の situation に
#     場所固有語(tatami/shoji/engawa/futon 等)が入ると正面衝突する。situation_neutral は
#     場所語を含まない場面表現で、V2 経路がこれを優先して使う。未指定のカードは situation を
#     そのまま使う(フォールバック)。旧 story preset 経路(pipeline/story.py の V1)は
#     situation を今まで通り使うので、既存 recipe / 既存 run / 既存170枚は不変。

schema_version: 1

# ── カメラの「距離」(2026-08-10 追加) ────────────────────────────────
# なぜ足したか: それまでカメラは決まり文句を1つ選ぶだけで、100枚を似た者どうしで
#   まとめると **9系統** しか無かった(上から23枚・寄り17枚・横から17枚で57%)。
#   カード側の camera_ok を「向き」だけにして、ここの「距離」と掛け合わせる。
#   例) 距離5 × 向き5 = 25通り。語数は1枚あたり +1個 に収まる。
#
# ★ここに書く語は必ず Danbooru の実在タグにすること(0枚の語はモデルに通じない)。
#   検査 = scripts/camera_tag_check.py(0枚が1つでもあれば落ちる)。
#   実測 full body 1,254,944 / upper body 1,170,576 / cowboy shot 835,645 /
#        portrait 139,200 / close-up 62,779 / wide shot 23,291
#
# 段ごとに寄り引きの割合を変えてある(中核は結合が見えないと商品にならないので引き寄り)。
# カード側に shot_ok: [...] を書けばそのカードだけ上書きできる。
# no_character の情景カードは no_shot: true で距離を掛けない(自前で書いているため)。
# ★2026-08-11 追加: `wide shot`(23,310枚)。
#   市販4作品の分析で、**作者自身が「この頃の作品からようやく引きの構図も入れられる
#   ようになった」と注釈していた**（公式ガイドブック p.220。和室の天井・柱・障子・庭まで
#   写る後背位）。ところが**うちの距離の軸に wide shot が1語も入っていなかった**。
#   `full body`(全身が入る) と 引き(環境が読める) は別物。
#   ★親密な段(接近・前戯・山場)には入れない。遠すぎて何をしているか分からなくなるため。
camera_shots:
  default:  [full body, upper body, cowboy shot, portrait]
  by_phase:
    intro:     [full body, cowboy shot, upper body, portrait, wide shot]
    approach:  [upper body, cowboy shot, close-up, portrait]
    foreplay:  [upper body, close-up, cowboy shot, portrait]
    main:      [full body, cowboy shot, upper body, close-up, portrait, wide shot]
    climax:    [upper body, close-up, portrait, cowboy shot]
    afterglow: [full body, upper body, cowboy shot, portrait, wide shot]

# ── 体位の系統(2026-08-12・実測)──────────────────────────────────────
# なぜ要るか: 「騎乗位ばかり」の正体は**モデルの崩れではなく指示の枚数**だった。
#   実測(今回100枚): 跨がる系のカード20枚 → 17枚が指示どおり(85%)。
#                    それ以外の80枚 → 跨がって見えたのは9枚(11%)だけ。
#   つまり崩れはわずかで、**ツールが100枚のうち20枚も跨がる系を頼んでいた**のが原因。
#   参考作品60ページの跨がる系は **8.3%**(重複なしで数え直した値)。
#   ★私が最初に報告した「47%」は `girl_on_top` と `straddling` を足した二重計上。
#     正しくは **26%**。数えるときは1枚を1回だけ数えること。
#
# 出どころは2つ:
#   ① キット(`composition_kits_v2.yaml`)の既定枚数
#   ② 枚数を増やすときの拡張(`story_design_run.py` の `_widen_cards_for_scale`)。
#      **カードIDのアルファベット順**に足していたので `main_amazon` から埋まり、
#      跨がる系が偏って増えていた(体位の系統を見ていなかった)。
#
# ここは「どのカードがどの系統か」の表だけを持つ。使う側が薄い系統から順に足す。
# ★カードは1枚も消さない・無効にしない([[feedback-never-hide-user-choices]])。
#   変えるのは「自動で増やすときにどれから足すか」の順番だけ。
# ★2026-08-15 追加: 系統ごとの「目安の割合」。
#   これが無いと自動追加は**均等に**足しにいくので、枚数を増やすほど跨がる系が戻る
#   (実測: 100枚では7%だったのに 350枚では16%へ戻った)。
#   参考作品60ページの実測は **寝ている系43.3% / 跨がる系8.3%** で、均等ではない。
#   ここは「薄い系統から足す」の判定に使うだけ。**カードは1枚も消さない**。
#   合計は1.0でなくてよい(相対比で見る)。
pose_family_targets:
  lying:    0.45
  behind:   0.22
  straddle: 0.18
  standing: 0.08
  group:    0.07

# ── 相手役をどこまで写すか（段F・2026-08-15）────────────────────────────
# ユーザーが「こういうカメラがまだ出ない」と参考の絵を4枚提示。分析すると、足りないのは
# **カメラの位置ではなく「2人と画面の関係」**だった。市販4作品の分析でも
# 相手役の写し方は4段階（A 完全に枠外 / B 手だけ / C 顔だけ / D 全身）に分かれていたのに、
# うちのツールは**常に D（顔なし男性の全身）**しか作れず、画面が常に二人ぶんの体で埋まっていた。
# 主観の割合も **参考24% / うち7%** と大きく開いていた。
#
# ★使う語はすべて Danbooru 実測:
#   solo focus 496,235 / pov 196,479 / out of frame 43,302 /
#   pov+spread legs 33,218 / disembodied hand 22,569 / pov+missionary 16,733 /
#   disembodied penis 9,321 / pov+doggystyle 4,668
#   ★弾いた0枚: disembodied limb / male pov
#
# 仕組み: 選ばれた見せ方が `drop_partner_words: true` を持つとき、
#   **相手役の見た目の語（58歳・太った・禿げ…約20語）を出さない**。
#   代わりに短い語だけを書く。男性器の語と `1boy` は残す（挿入の絵が壊れないため）。
#   ★打ち消し（染み出し対策）は**そのまま**にする。相手役の体は画面内に残るので保護は必要。
#
# ★★2026-08-15 修正（ユーザーが実画像で発見:「男性が指定と全く違う」「また服を着ている」）:
#   20語を**全部**消したのが間違いだった。主観でも彼の**お腹・腕・下半身・下着は写る**のに、
#   写るものの指定まで捨てていた。しかも場面の語に `clothed male nude female`（男は着衣）が
#   残るので、「何か着ろ、ただし何かは指定しない」という指示になっていた。
#   実測（8/15 の100枚を絵から読み取り）:
#       太い    ふつう34% → 主観 0%
#       ハゲ    ふつう86% → 主観 0%
#       年配    ふつう84% → 主観 0%
#   → `keep_axes:` に書いた軸だけは**主観でも書く**。方針は
#     「**写らないものだけ消す。写るものは残す**」。
#   ★打ち消し（anti_body_bleed / anti_male_shirt）は元から出ていたので、
#     直前までは「打ち消しだけあって、打ち消す相手が居ない」空振りだった。
#     今回の修正で positive と counter が噛み合う。
#   ★残る危険 = 体型の染み出し（女性のお腹が出る）。過去に5回踏んだ型なので、
#     次に刷ったら**女性の体型を必ず見る**こと。
#   戻し方: `keep_axes` を空リストにすれば 8/15 の挙動に戻る。
#
# ★空文字("") = 従来どおり全身。多めに混ぜて全部が主観にならないようにする。
# ★男性2人（3P）の場面には効かせない（2人を描き分ける必要があるため・story.py が判定）。
# 戻し方: `enabled: false` の1行。
partner_views:
  enabled: true
  by_phase:
    approach:  ["", "", "", hands_only]
    foreplay:  ["", "", "", hands_only, pov_close]
    main:      ["", "", "", "", pov_close, pov_close]
    climax:    ["", "", "", pov_close]
  options:
    pov_close:
      label_ja: 主観（相手の体は画面の端だけ）
      prompt: "pov, solo focus"
      drop_partner_words: true
      # ★主観でも写るもの＝体・服。だから体型と服と汗は書く。
      #   消えるのは 顔立ち・髪・髪の色・身だしなみ・肌・役割・faceless（＝頭から上）。
      #
      # ★★2026-08-16（刷って実測・age を外した経緯）:
      #   `age`（`adult man, 58 years old`）を入れたら、**主観の絵に男の顔が入り込んだ**。
      #       顔が2つ以上写る絵  直す前 2/21(10%) → age あり 10/24(42%)
      #   「ここに大人の男がいる」と名指しした結果、AIが彼の頭まで画面に入れた。
      #   主観の絵は「彼の頭は枠の外」であることが値打ちなので、これは product として後退。
      #   年齢は主観ではほとんど効いていない（年配 21% / ふつうの絵は 77%）ので、
      #   外しても失うものが小さい。→ **age を外す**。
      #   ★`head out of frame`（28,871枚・実在）は使わない。**性別の印が無い**ので
      #     女性の頭が切れる危険がある（[[rule-tags-must-exist-in-danbooru]] とは別の、
      #     染み出しの型。過去5回踏んでいる）。
      #   ★ふたなり化の見張りは `anti_futanari` が別に効いている（cast_for_card が常に足す）。
      keep_axes: [build, clothes, sweat_level]
      # ★同じ理屈で「2人を並べないと分からない語」も落とす。
      #   体型の指定には身長差が混ざっている（`short male, height difference,
      #   the man is shorter than the woman`）。主観の寄った絵で身長は分からないので
      #   写らないうえ、「2人を並べて見せろ」と言う語なので彼の頭を引き込む。
      #   ★軸ごと落とすと体型（お腹）まで消えるので、**語だけ**落とす。
      drop_phrases: ["height difference", "than the woman", "short male", "tall male"]
      # ★★段G（2026-08-16・6枚の試し刷り2回で確定）:
      #   「後ろから」の系統だけ主観がまったく成立していなかった。
      #   実測（8/16 の100枚を絵から読み取り）:
      #       バック系7枚のうち pov と読めたのは1枚 / 「後ろから」0枚 / 「尻が主役」0枚
      #   Danbooru の枚数を測ると、そのまま学習量の差だった:
      #       girl_on_top+pov 22,256 / missionary+pov 16,746 ← 出ていた
      #       doggystyle+pov   4,670 / prone_bone+pov   243 ← 出ない
      #   ★真因は語の不足だけではなく **`portrait`(140,100枚)との正面衝突**。
      #     カメラの語が相手役の見せ方と無関係に選ばれるので、
      #     「背中と尻を写せ」の絵に「顔を大きく写せ」が乗っていた。
      #   試し刷り: 6案を1枚ずつ → D案のみ主観として成立（ユーザー目視）。
      #             D案を3場面×2枚 → 四つん這い2/2・うつ伏せ2/2 が成立（横向きは不成立）。
      #   ★横向き(spooning)は `lying` の系統なのでここには入らない＝当たらない。
      #   戻し方: この `by_pose_family` を消す1手（他の絵は1文字も変わらない）。
      by_pose_family:
        behind:
          # ★★2026-08-22 追加 `(facing away:1.3)`（オーナー依頼「顔を見せない・男性目線・
          #   お尻がこちら」＝参考画像 画像00089）。
          #   なぜここか: この束は既に「お尻がこちら・見下ろす」を作れている
          #   （本番の実文: `from behind, ass focus, from above`）。
          #   **足りないのは「顔を見せない」の一言だけ**だった。
          #   ★実測 8/22: 男性目線は 100枚の作品に約2枚 配られているが、
          #     「顔を見せない」とは**一度も重なっていなかった**（別々に配られるため 0枚）。
          #   ★Danbooru: `pov + looking_at_viewer` は pov 全体の **58%**
          #     ＝ 主観と言うだけでは女性はこちらを向く。だから明示する。
          #   ★これは引き算ではない。**男性目線でない後ろからの絵**（正面向き・
          #     振り返り・尻アップ）は**1文字も変わらない**（オーナー明示: どれも使える）。
          #   ★この行に顔の向きの語があると、`apply_view_camera` が
          #     **既に焼かれている視線の語を落とす**（story.py。矛盾を防ぐため）。
          #   ★戻し方: `"(facing away:1.3)"` を消す1手。
          add: ["from behind", "ass focus", "from above", "(facing away:1.3)"]
          remove: ["portrait", "looking at viewer", "from side", "dutch angle"]
    hands_only:
      label_ja: 手だけ
      prompt: "disembodied hand, solo focus"
      drop_partner_words: true
      # 手しか写らないので、体型も服も書かない（書いても描く場所が無い）。
      keep_axes: []
      # ★手だけの絵では男性の体を描かせない。挿入の場面には割り当てない
      #   （approach / foreplay だけ）。挿入で 1boy を消すと絵が壊れるため。
      drop_boy_tag: true

pose_families:
  straddle:  [main_cowgirl, main_reverse_cowgirl, main_upright_straddle,
              main_reverse_upright, main_amazon]
  lying:     [main_missionary, main_missionary_ftf, main_folded, main_recumbent,
              main_spooning]
  behind:    [main_doggystyle, main_prone_bone]
  standing:  [main_suspended]
  group:     [main_sandwich, main_spitroast, main_face_and_insert, main_kneeling_bound]

# ── 寄りの絵の作り方(2026-08-12・実測 `scripts/framing_ab.py` 段1〜4・26枚)────────
# ユーザー指摘「もっと寄りがある方がいい」。本番100枚を測ったら
# **88枚が顔15〜25%の同じ枠**で、`close-up` と `wide shot` の絵がほぼ同じだった。
#
# 実測でわかったこと（顔の高さ÷画面の高さ）:
#   19.8%  いまの本番（縦長 832x1216・語はそのまま）
#   20.1%  重み `(close-up:1.4)`              ← 効かない
#   19.7%  組み合わせ `close-up, portrait`     ← 効かない
#   19.8%  LoRA 0.7→0.35                      ← 効かない（0でも28.2%止まり）
#   20.0%  正方形 1024x1024                    ← 効かない
#   20.1%  Hires OFF                          ← 効かない
#   22.6%  全身の形7語を抜く（縦長のまま）
#   26.9%  ＋箱を横長にする
#   34.6%  ＋背景の飾り（天気・季節・光・小物）も抜く   ★これを採用
#   参考作品59ページ = 4.7〜38.4%（中央値18.5%）
#
# 理屈: 縦長の紙には立ち姿がちょうど収まるのでモデルは全身を入れる。横長だと入らない。
#   さらに「背が高い・脚が長い・モデル体型」と書いてあると無理に全身を詰め込む。
#   ★**寄りの絵では、これらの語はどうせ写らない**ので落としても失うものが無い。
#   同じ理由で天気・季節・光の飾りも写らない。
#
# 戻し方: `enabled: false` の1行。語の表を空にすれば語だけ元に戻る。
framing:
  enabled: true
  # 「写らない語を落とす」を効かせる寄り
  tight_shots: [close-up, portrait]
  # 「箱を横長にする」を効かせる寄り。★portrait(顔まわり)は縦長の紙のほうが自然なので
  #   入れない。close-up だけ横長にする(実測でいちばん効くのは close-up)。
  #   実測の内訳: 100枚中 close-up 16枚 / portrait 27枚。
  landscape_shots: [close-up]
  # 寄りでは写らない「全身の形」の語。人物の語(base)から落とす。
  drop_body_words:
    - very slender
    - narrow waist
    - (slender legs:0.9)
    - slender legs
    - tall
    - small head
    - long legs
    - fashion model figure
    - wide hips
    - thick thighs
  # 寄りでは写らない「背景の飾り」。場面の語から落とす。
  #   ★場所そのもの(living room 等)は落とさない。壁や家具の色で場所は伝わるため。
  drop_scene_words:
    - daylight
    - bright
    - soft light
    - dim indoor light
    - summer atmosphere
    - winter atmosphere
    - spring atmosphere
    - autumn atmosphere
    - clear weather
    - rainy weather
    - cloudy weather
    - snowy weather
    - night
    - evening
    - morning

# ── 引きの絵の作り方(2026-08-17・実測 `scripts/wide_from_closeup.py`)──────────
# ★これは「新しい選択肢」ではない。ツールは**前から `wide shot` を配っていた**
#   (実測: 100枚中10枚 / 350枚中33枚)。ところが語では引きにならないので、
#   **同じ10枚が寄りの絵として出ていた**。ここはその10枚の作り方だけを変える。
#   利用者が選ぶものは1つも増えない。
#
# 実測でわかったこと(2026-08-17・全部実画像):
#   語だけ                 失敗。sex + wide shot は38万枚中17枚しか学習が無い
#   外側へ描き足す(outpaint) 不採用。カメラ2台に見える=「壁に飾った額縁」
#   骨格(openpose)で小さく  **大きさを制御できない**(身長30%→12%でも占有50%台)
#   骨格を強くする          3.0で占有14%になるが**絵が破綻**(ノイズ・色崩れ)
#   輪郭(canny)だけ        大きさは正確だが**見本の姿勢しか作れない**
#   **寄りで姿勢→縮めて引き**  **成功**(完成品 work/wide-from-closeup/20260817-235616/)
#
# 手順: ①寄りで姿勢の見本を1枚作る → ②**人物だけ**を切り出して輪郭にする
#       → ③引きの画面の小さな位置へ縮めて置く → ④その輪郭で刷る
#   ★**人物だけ**を切り出すのが肝。部屋ごと縮めると「壁の額縁」になる。
#
# ★測り方: 「顔の大きさ」ではなく**人物が画面を占める割合**で測る。うつ伏せの構図では
#   顔16.8%でも尻が画面の半分を占め、顔で測ると完全に見誤る(実際に見誤った)。
#
# ★道具の分担(いちばんの学び): 輪郭=大きさ・形 / 骨格=姿勢・手・人数 / 言葉=人数・見た目。
#   **3つが同じことを言っていないと言葉が勝つ。** だから下の `drop_words` が要る
#   (「足すだけでは効かない。衝突する語を抜く」)。
#
# 戻し方: `enabled: false` の1行。そうすると引きの10枚も今までどおりの絵に戻る。
composition_control:
  enabled: true
  wide:
    # この語がカメラに入っている絵だけを引きの経路へ回す(＝既に配られている枠)
    shots: [wide shot]
    # 人物が画面の高さに占める割合。0.34=引きの最大(ユーザー判定「これが引きの最大値」)
    #   ★1枚ごとに散らす。同じ作品なら何度組み立てても同じ(再現できる)。
    #
    # ★★2026-08-18 に3通りとも着衣で刷って決めた値(**0.45 は外した**):
    #   0.34  人物 27.0%。部屋は読める。ただし**男性が横に膝立ちする**ことがあり、
    #         「覆いかぶさる」姿勢の再現はやや弱い
    #   0.40  人物 36.1%。**いちばん良い**。男性が彼女に跨がって腰をつかむ形が出て、
    #         畳・障子・縁側・窓の外まで読める
    #   0.45  ★**破綻した**。2人が離れてしまい、男性は布団に1人で膝立ち・
    #         女性は縁側に立っているだけの絵になった(行為の関係が消えた)。
    #         ★頭の数は2で「正しい」ので、**数字だけ見ていたら見逃していた**
    #         ([[rule-symptom-is-not-the-thing]])。
    scales: [0.34, 0.40]
    # ★★2026-08-19: **既定は「縮めない」**（この行を false にすると上の scales が復活する）。
    #   2026-08-18 に見本の作り方を「姿勢の語から組み立てる」へ変えた時点で、
    #   **見本そのものが既に引き**になっていた（頭の大きさ 16.6%／目標画像は 14.9%）。
    #   その引きの見本をさらに 40% へ縮めていたので、線が小さく細くなり、モデルは
    #   それを無視して大きな人物を描いていた（完成品 頭30.7%・頭が3つ）。
    #   着衣A/B（scripts/wide_ctrl_ab.py・種2つ・本番の見た目26語つき）:
    #       縮めない輪郭あり  頭 7.3〜11.4%  ← 8枚とも引き
    #       輪郭なし          頭 20.7・22.0% ← 寄り
    keep_sample_scale: true
    # ★★2026-08-19: 見本として受け取れる「頭の大きさ ÷ 画面の高さ」の上限。
    #   「縮めない」道では**見本の引き具合がそのまま完成品の引き具合**になる。
    #   見本が寄りだと寄りの輪郭をそのまま渡してしまい、**エラーも出ないので気づけない**。
    #   ★物差しに「体の占有」を使ってはいけない（**寝具まで人物として塗る**）。
    #     実際にそれで良い見本を「人物の高さ88%」として捨てた。88% はベッドの高さだった。
    #   実測（絵を1枚ずつ見て良し悪しを付けてから測った）:
    #       良い見本  頭  7.4 / 10.8 / 16.6 / 17.8 %
    #       悪い見本  頭 23.2 / 26.5 / 28.0 / 33.3 %
    #       目標画像  頭 14.9 %
    #     体の占有だと 良い49〜88% / 悪い82〜100% で**重なって区別できない**。
    # ★★2026-08-23 に 0.20 → 0.18。**過去の絵109枚を機械が数えて決めた**
    #   （`scripts/wide_sample_gate_measure.py`・走らせるたびに数え直せる）。
    #   見本の頭の大きさ別に「完成品が本当に引きになった率」:
    #       15〜16% 22枚 73% ／ 16〜17% 2枚 100% ／ 17〜18% 2枚 100%
    #       **18〜19% 16枚 19%** ／ 19〜20% 1枚 0%     ← ここが崖
    #   0.20 のままだと、18〜19% の見本が門を通ってしまい、
    #   **エラーも出ないのに完成品は寄りに戻る**（気づけない）。
    #   実害: 2026-08-23 の「1人で座る 0/12」は見本 18.4% を使った8枚が全滅していた。
    #   ★16〜18% の帯は2枚ずつしか材料が無い（薄い）。絵が増えたら測り直すこと。
    #
    # ★★★2026-08-23 夜 0.18 → 0.22。**利用者が見本12枚を1枚ずつ見て決めた**。
    #   上の 0.18 は「完成品の頭が **20% 以下**になるか」から逆算した数字で、
    #   その 20% 自体を利用者が見たことは一度も無かった＝**機械が機械の都合で決めていた**。
    #   利用者の判定（`work/wide-words-a-asis` と `-b-dropped` の見本12枚）:
    #       引きとして成立  頭 14.2 / 16.7 / 17.3 / 18.5 / 19.4 / 20.6 / 21.1 %
    #       許せる範囲      頭 26.1 / 26.9 / 27.7 %
    #       引きではない    頭 21.5 %（★主観の絵。大きさでは見分けられない）/ 29.6 %
    #   → 「成立」の上限は 21.1%。余白を見て 0.22 にする。
    #   実害（これを直す理由）: 0.18 の門は利用者が使えると言った見本を
    #     **12枚中8枚 捨てていた**。捨てるたびに種を変えて刷り直すので GPU 代がかかる。
    #     実測 2026-08-23 の本番: 見本を24枚刷って合格0枚 → 引きの注文5枚が全部
    #     ふつうの絵に落ちた（完成品の頭 32〜44%）。
    #   ★「2人写っていること」の条件は**外していない**。あれは捨てる条件ではなく
    #     控えに回す条件で（composition_control.py の spare）、控えに回るにも
    #     「遠さが合格」が要る。門が厳しすぎて控えすら残らなかったのが今夜の姿。
    #     門を緩めれば、男性の頭が枠の外に出た見本も控えとして使われる
    #     （利用者はその絵を「成立」と判定した）。
    #   ★取りこぼしを1つ承知で残す: 主観（男性の目線）の見本は頭の大きさでは弾けない。
    #     12枚中1枚。何百枚も刷る前提なら許容する、という利用者判断。
    sample_max_head: 0.22
    # ★★2026-08-19: 同じ札の絵が**同じ構図にならない**ように、輪郭を1枚ごとに散らす。
    #   輪郭を縮めなくなったので、1つの札につき見本1枚＝そのままだと
    #   同じ札の引きは人物の位置も大きさも全部同じになる（作品の中で反復に見える）。
    #   ★決め方は画像IDから。同じ作品を何度組み立てても同じ絵＝再現できる（乱数は使わない）。
    #   ★縮小は 0.9 まで。それ以上小さくすると線が細くなって輪郭が効かなくなる
    #     （2026-08-18 に 0.34 へ縮めて実際に効かなくなった）。
    #   `variants: false` の1行で散らしを止められる。
    # ★★2026-08-19: 1つの札につき見本を何枚作るか。
    #   輪郭を縮めなくなったので、見本1枚＝**その札の引きは全部おなじ姿勢・おなじ角度**。
    #   実画像で見ると、左右反転や少しのずらしだけでは**ほとんど同じ絵**だった。
    #   → 見本そのものを複数作って1枚ごとに使い分ける。
    #   ★見本は Hires も顔補正も無いので1枚 約15秒・$0.005（札あたり $0.005 の増）。
    samples_per_card: 2
    # ★★2026-08-22: 輪郭から**頭のところの線を消す**（顔と髪は LoRA と本番の文章に任せる）。
    #   実害（リタの本番・実画像で確認）: 見本は LoRA を載せずに刷るのでキャラ本人ではなく、
    #   その髪型が輪郭に入って完成品の髪を上書きしていた。同じ run の比較:
    #       輪郭なしの絵  短いボブ＋素直なセーラー服        ← 正しい
    #       輪郭ありの絵  長いウェーブ＋フリルの髪飾り      ← 見本そっくり
    #   消すのは頭の箱の中だけ。姿勢と距離の線は1本も変わらない。
    #
    # ★★★2026-08-24 true → **false**（利用者が実物6枚を見て「Fは全て完璧です」と判定）。
    #   なぜ戻せたか: 上の実害（見本の髪が完成品を上書きする）は**別の手当てで解けた**。
    #     ① 輪郭を土台だけに掛ける（`hires_control: false`）→ 仕上げ段で髪を描き直せる
    #     ② 髪飾りの打ち消しを足す（`hair_ornament_negative`）
    #   利用者判定の経過（`docs/decisions/user-judgments.yaml`）:
    #       頭を消す（A〜D）… 完成品の頭 25.4〜30.9%。利用者「使えるのは10枚中3枚」
    #       頭を残す（E）  … 頭 17.8〜20.6%。「引きの画像としては良い」が
    #                        「髪が長くなる・頭にリボンが付く」
    #       ①を足す（F）  … **髪の長さが解けた**。残るのは飾りと衣装の染み出し
    #       ②も足す（F）  … **「Fは全て完璧です」**（3枚とも合格）
    #   ★頭を消すと**枠が寄る**（消す 25〜31% / 残す 17〜21%）。これが最大の理由。
    #   ★確かめたのは **正常位だけ・3枚だけ・見本1枚だけ**。他の体位は未確認
    #     （後背位・立位対面はそもそも見本が門を通らない＝板 W8）。
    clear_head_in_control: false
    # ★★2026-08-24: 輪郭を**土台だけ**に掛ける（仕上げ段は素の条件＝髪を描き直せる）。
    #   上の false と**組**で効く。片方だけ戻すと利用者判定の条件が崩れる。
    #   ★`hires_lora_strength`（仕上げ段でキャラを 0.7 に戻す）は**採らない**。
    #     入れた G は、同じ打ち消しでも男性にスカートが出た（2/3枚）。
    #     利用者「Gは女性は完璧ですが、2枚目3枚目で男性がやはりスカートを履いてます」。
    #     LoRA が衣装も持つため、強くすると女性の衣装の語が絵全体に効く、という筋。
    hires_control: false
    # 頭の箱は顔しか囲っていないので、髪飾り・襟足のぶんだけ広げて消す。
    # ★消えるのは顔と頭まわりの髪まで。**机に広がった長い髪など、頭から離れた髪は残る**
    #   （そこまで広げると体の線も消えて姿勢が伝わらなくなる）。
    # 広げすぎると肩まで消えるので、箱の大きさに対する割合で 0.35。
    head_margin: 0.35
    variants:
      enabled: true
      flip: true              # 左右反転（人物が右にも左にも来る）
      zooms: [0.9, 1.0, 1.1]  # 少しの拡大縮小
      shift: 0.05             # 左右 ±5%・上下はその半分ずらす
    # ★★2026-08-18: **人数で最適値が違う**（着衣・リビングで実測）。
    #   2人 0.7 … 男性が跨がって腰をつかむ姿勢が出る。1.1 にすると横に立つだけになる
    #   1人 0.7 … **引きにならない**（人物が画面の43.9%）。輪郭が小さく単純なので指示が弱い
    #   1人 1.1 … 部屋全体が読める本物の引きになる（25.4%）
    canny_strength: 0.7
    # 1人の場面だけ強くする（上の実測より）
    canny_strength_solo: 1.1
    # ControlNet を前半だけ効かせる。1.0 まで効かせると色が硬くなり体が歪む(実測)
    end_percent: 0.75
    # 引きは LoRA を弱める。0.7 のままだと骨格・輪郭に**LoRA が勝つ**(実測)
    lora_strength: 0.45
    # ★★2026-08-19 に true → false へ。理由は3つ、全部実測:
    #   ① 目標画像（ユーザー提示）が **832x1216 の縦長**
    #   ② 縦長でも引きは壊れない（着衣A/B: 横長 8.4% 対 縦長 7.6%・ほぼ同じ）
    #   ③ 横長は選別画面で左右が切り落とされ **51.3% しか見えない**
    #      （引きは「部屋が見えること」が値打ちなので、切られると値打ちが消える）
    #   ★横長にしたのは 2026-08-12 の「寄りの絵」の理屈を流用しただけで、
    #     引きで確かめていなかった。
    landscape: false
    # ★引きと正面衝突する語。**抜くのが効く**(足す方向は全滅した)。
    #   `ass focus` が残ると人物の占有が98%になった(実測)。
    # ★★2026-08-22: `ass focus` の行が**消えていた**（すぐ上の説明だけ残っていた）。
    #   壊し試験がこの行を消して元に戻す作りなので、中断で消えたままになったとみられる。
    #   検査は「出力に語が残っていないか」しか見ておらず**素通りした**ので、
    #   観点4に「この表に語が入っているか」の判定を足した。
    drop_words:
      - ass focus
      - close-up
      - portrait
      - pov
      - solo focus
      - blurry foreground
      # ★2026-08-22 追加: `blurry background`(184,611枚)。引きの値打ちは
      #   「部屋が読めること」なのに、背景をぼかせと書いてあると正面から潰す。
      #   `depth of field` を落としているのと同じ理由・同じ家族の語。
      - blurry background
      - depth of field
      - motion blur
      - motion lines
      - emphasis lines
    # 引きでだけ足す語(部屋を厚く言う)。★場所そのものは scene 側が持っている
    # ★★2026-08-19 に実測して2語を捨てた（[[rule-tags-must-exist-in-danbooru]]）:
    #     distant view  Danbooru **0枚** ＝ 書いても効かない
    #     scenery       74,108枚あるが `sex + scenery` は **9枚**(0.002%)＝行為の絵では学習が無い
    #   残したのは実在して行為の絵にもある語だけ:
    #     from above 144,077 / `sex + from above` **6,513枚**(1.674%) ★唯一まともなカメラ語
    #     indoors    542,255 / `sex + indoors` 44,245枚
    #     wide shot   23,510（`sex + wide shot` は17枚。効きは薄いが枠の印なので残す）
    # ★★2026-08-19: `indoors` はここから外した。**場面ごとに屋内/屋外を選ぶ**ように
    #   したため（apply_wide_words が `indoors` か `outdoors` を足す）。
    #   ここに書いたままだと、海辺・露天風呂・森を選んでも「屋内」と書かれてしまう。
    add_words: [from above, wide shot]
    # ①の見本を作るときのカメラ。★輪郭を縮めなくなったので**完成品のカメラもここで決まる**
    # ★★2026-08-19 に `from side` を足した。輪郭を縮めなくなったので
    #   **完成品のカメラは見本のカメラで決まる**。ここが構図の operating point。
    #   本番の道で刷って目で比べた（work/cc-live-ctrl-keep4 対 -side1）:
    #     from above だけ … 真上から。正常位で**男性が仰向けに寝てしまう**ことがある
    #     ＋from side    … 斜め上から。**男性が脚の間で膝立ちして前傾する**
    #                      ＝ 手元の目標画像と同じ形（作成者が用意した参考画像・配布物には含めない）
    #   頭の大きさ: 正常位 14.1→12.1% / 後ろから 18.6→13.6%（目標 14.9%）
    #   実測枚数: from_above 144,077 / from_side 331,842（どちらも実在する語）
    sample_camera: "cowboy shot, full body, from above, from side"
    # ★★2026-08-24（利用者が F/G の6枚を実物で見て指摘）。**引きの絵の打ち消しだけ**に足す。
    #   ① 髪飾り: 利用者「1枚目と3枚目がまだリボンがついたまま」「1枚目が金髪リボン」。
    #      出どころは衣装の `bow` が最有力。実測（scripts/danbooru_combo_count.py・$0）:
    #          bow 1,711,743枚 → うち髪にリボン **753,723枚(44%)**
    #          lolita fashion 42,499 → うち髪飾り 9,776(23%)
    #          serafuku 391,263 → うち髪リボン 47,180(12%)
    #      ★`bow` は利用者が選んだ衣装（胸のリボン）なので**消さない**。
    #        ここに書くのは「**髪の**」が付いた語だけ。素の `bow` `ribbon` は禁止。
    #      実測枚数（全部実在・scripts/danbooru_tag_count.py）:
    #          hair ornament 2,046,279 / hair ribbon 790,932
    #          hair bow        753,722 / hairband      697,759
    hair_ornament_negative: [hair ornament, hair ribbon, hair bow, hairband]
    # ② 女性の衣装が男性へ染み出すのを止める（利用者「男性の足にスカート」
    #   「男性の上の服までセーラー服」）。false にすれば1文字も足さない。
    #   ★語は `outfit_parts` の top / bottom から機械が作る（表を手で持たない）。
    #     形は partner_cast.py の鏡写しと同じで、向きだけ逆:
    #         いままで (woman in polo shirt:1.3)  男性の服 → 女性 を止める
    #         これ     (man in serafuku:1.3)      女性の服 → 男性 を止める
    #   ★性別の印が無い語は1つも置かない（置くと男性の服が全部消えて裸になる）。
    anti_outfit_bleed_to_male: true
    # ★★2026-08-18（本番20枚で発覚）: 見本が**顔と胸の超クローズアップ**になり、
    #   「人物だけ」を切り出しても画面のほぼ全部が人物（部屋の線は6%しか落ちない）。
    #   それを40%に縮めてもモデルは従わず、**20枚とも引きにならなかった**（占有 中央値95.6%）。
    #   原因は**寄らないと描けない語**。`sucking her nipple` `forced kiss` `tongue` は
    #   「そこを見せろ」と要求するので、末尾に `full body` を足しても押し負ける
    #   （[[rule-describing-forces-showing]]「足す方向は全滅・抜くのが効く」）。
    #   → **見本からは「足す言葉(オプション)」と口元の描写を抜く**。
    #   ★抜くのは**見本だけ**。本番の絵の文章からは1語も抜かない
    #     （[[feedback-never-hide-user-choices]]。利用者が選んだ演出は消さない）。
    #   実測: 引きの11枚中**10枚**にこれらの語が乗っていた＝ほぼ全部が失敗する状態だった。
    sample_drop_extra: true            # 場面の「足す言葉」を見本から抜く
    sample_drop_words:                 # 上以外にも寄りを呼ぶ語（表情の札から来る）
      - drooling
      - open mouth
      - tongue
      - tongue out
      - saliva
      - kiss
      - french kiss
      # ★2026-08-22 追加（見本だけ・本番の絵からは落とさない）。
      #   胸の細部の印は**輪郭には1ドットも残らない**のに「そこを見せろ」と
      #   要求するので、見本が寄りになって門で捨てられる。
      #   実測: breasts_apart 61,565 / mole_on_breast 57,891 / inverted_nipples 22,132
      - breasts apart
      - mole on breast
      - inverted nipples
    # 見本づくりに失敗したら(人数が合わない等)、その絵は**今までどおり**に刷る
    fallback_on_mismatch: true

  # ── 後ろからの主観(彼の目線)を骨格で作る(2026-08-17・実測) ────────────
  # ★これも「新しい選択肢」ではない。`partner_views` が前から主観を配っている
  #   (実測: 100枚中24枚)。そのうち**後ろからの系統だけ**が語では成立しない。
  #     実測(8/16 の100枚を絵から読み取り):
  #       バック系7枚のうち pov と読めたのは1枚 / 「後ろから」0枚 / 「尻が主役」0枚
  #     Danbooru の学習量がそのまま出ている:
  #       girl_on_top+pov 22,256 / missionary+pov 16,746  ← 出る
  #       doggystyle+pov   4,670 / prone_bone+pov    243  ← 出ない
  #   `pov`(カメラ＝彼) と `sex from behind`(後ろに男がいる) を両方言うと**両方描く**。
  #
  # 骨格なら原理的にこれが起きない = **1体しか置かなければ2人目を描く余地が無い**。
  #     語だけ  「目線○ かつ 男1人」 1/8(12%) / 男が2人 頻発
  #     骨格    「目線○ かつ 男1人」 2/4(50%) / 男が2人 **0/4**
  #   ★外れた2枚もユーザー判定は「構図としては使える」。つまり**下振れが浅い**。
  #
  # ★手も骨格で置く(2026-08-17・着衣6枚)。骨格に腕が無いと、強くするほど手が消えた
  #   (0.6=両手が腰 / 0.8=手が消える / 1.0=太ももだけ)。
  #   腰・尻・背中を作り分けられるので、同じ骨格でも絵が単調にならない。
  #
  # 戻し方: `enabled: false` の1行(引きはそのまま効く。別々に切れる)。
  pov:
    # ★★2026-08-18 現在 false（＝主観の絵は**従来どおり語で**作る。何も変わらない）。
    #   仕組みは全部できていて検査も通っているが、**実画像で効果を確認できていない**ため。
    #   実測（着衣4枚・本番経路）:
    #     骨格あり / 骨格なし で **絵がほとんど同じ**（強さ 0.8 でも 1.0 でも変わらず）
    #     男の重複は 0/4（ここは狙いどおり。ただし骨格なしでも 0/4 なので手柄ではない）
    #   原因は骨格の置き方。上から見た見本に差し替えて女性の形は正しくなったが、
    #   **彼の腕と脚が画面を斜めに横切る長大な線**になっており、絵として読めない。
    #   8/17 の数値（女性 0.58 / 中心 0.34 等）は**横から見た見本**に合わせたもので、
    #   上から見た見本には合わない。
    #   残っている仕事 = `POV_LAYOUT`（pipeline/composition_pose.py）を、
    #   骨格の絵を目で見ながら詰め直す（GPU 不要で何通りも試せる）→ 着衣で刷って確認。
    #   ★true の1行で有効になる。引き（wide）とは別々に切り替えられる。
    enabled: false
    # この体位の系統にだけ効かせる。他の系統は語のままで足りている(実測)
    pose_families: [behind]
    # カードごとに使う骨格の見本(compositions/refs/*.json)
    # ★**上から見た角度**の見本を使う（横から見た骨格では主観にならない。2026-08-18 実測）。
    #   四つん這い専用の見本はまだ無い。うつ伏せの骨格は「頭が奥・尻が手前」で
    #   彼の目線として成立するので、当面は両方これを使う（2026-08-17 の実測どおり）。
    poses:
      main_prone_bone:  woman_prone_top
      main_doggystyle:  woman_prone_top
    # 手の置き場所。1枚ごとに散らす(同じ骨格でも絵が変わる)
    grabs: [waist, hip, back]
    strength: 0.8
    # 骨格も前半だけ効かせる(1.0 まで効かせると色が硬くなり体が歪む)
    end_percent: 0.75
    # 骨格 0.8 に対して LoRA 0.7 のままだと**骨格が負ける**(2026-08-17 実測)
    lora_strength: 0.45

# ── カメラの「視線・目」(2026-08-11 追加・3つ目の軸) ──────────────────
# なぜ足したか: 100枚×3を絵から読み取ったら、**顔の向きが1ミリも散らばっていなかった**。
#   目を閉じている 31枚 / こちらを見ている 22枚 / 残り47枚は**指示が無くモデル任せ**。
#   前後で数字が動かない(前31/22 → 新29/21)＝ カメラの距離と向きを直しても顔は変わらない。
#   原因は単純で、**視線を決める語がツールのどこにも無かった**。
#
# ★目の状態(閉じる/半目)もここに置く。表情の札(wildcards/nsfw/expr_*.txt)には書かない。
#   両方に書くと「目を閉じる」と「こちらを見る」が同じ絵で綱引きになる。
#   表情の札は 口・頬・涙・汗・体の反応 だけを持つ。
#
# ★向き(camera_ok)に既に "looking back" 等が入っている行では、この軸は**足さない**
#   (pipeline/story.py の build_cameras が判定)。顔の向きが二重指定になるため。
#
# ★ここに書く語も必ず Danbooru の実在タグにすること。実測:
#   looking at viewer 4,818,450 / closed eyes 1,039,661 / one eye closed 609,698 /
#   head tilt 171,783 / half-closed eyes 141,561 / looking down 136,994 /
#   looking up 98,993 / empty eyes 49,372 / looking away 34,943 / rolling eyes 22,521
camera_gaze:
  default:  [looking at viewer, looking away, head tilt, looking down]
  by_phase:
    intro:     [looking at viewer, looking away, head tilt, looking down, closed eyes, looking up]
    approach:  [looking at viewer, looking away, head tilt, looking up, closed eyes, one eye closed]
    foreplay:  [looking at viewer, looking up, closed eyes, half-closed eyes, looking away, one eye closed]
    main:      [closed eyes, half-closed eyes, looking at viewer, looking away, looking up, one eye closed, rolling eyes]
    climax:    [rolling eyes, closed eyes, half-closed eyes, looking up, one eye closed]
    afterglow: [closed eyes, half-closed eyes, empty eyes, looking away, looking up]

# ── カメラの「演出」(2026-08-11 段D 追加・4つ目の軸) ────────────────────
# 市販4作品を読み比べたら **動きの線が 参考10% / うち0%** だった
# (docs/design/camera-grammar-from-commercial-works-2026-08-11.md)。
# 打ちつけの瞬間の集中線・ブレ、日常の背景ぼけ、前景に体を置く奥行き。
# 同じ体位でも「動いて見えるか / 止まって見えるか」を決めている層。
#
# ★空文字("")の候補を混ぜてある = **その絵には演出を付けない**。
#   全部に付けると絵が線だらけになるので、段ごとに空の割合を変えている。
# ★実測: motion lines 120,158 / blurry background 183,556 /
#         emphasis lines 46,725 / blurry foreground 41,404 / motion blur 34,402
# ★擬音レイヤー(PLATE 06)と重なる恐れがある。実画像で必ず見ること。
#
# ★2026-08-11 修正: `depth of field` を全部外した。**品質タグに最初から入っていた**
#   ("masterpiece, ..., soft lighting, depth of field")。同じ語を二度書いても増えない。
#   実測でも 31枚に指示して絵に出たのは **0%** だった。
#   検査 camera_tag_check.py の観点8 が、品質・キャラと重複する語を止める。
camera_mood:
  default:  ["", blurry background, blurry foreground]
  by_phase:
    intro:     ["", blurry background, blurry foreground]
    approach:  ["", blurry background, blurry foreground]
    foreplay:  ["", blurry foreground, motion lines, blurry background]
    main:      ["", motion lines, emphasis lines, motion blur, blurry foreground]
    climax:    ["", motion lines, emphasis lines, motion blur]
    afterglow: ["", blurry background, blurry foreground]

cards:

  # ── intro(導入・着衣・非露出) ──
  intro_standing: {phase: intro, label_ja: 立ち姿・振り返り, situation: "standing indoors, looking over shoulder, relaxed", camera_ok: ["straight-on", "from side", "from behind, looking back", "from above"], expected_zones: [], partner: false, weight: 1, tier: main}   # 経路A s01d より移植
  intro_shoji:    {phase: intro, label_ja: 窓越しの光, situation: "standing by a shoji screen, backlight, quiet", situation_neutral: "standing by a window, backlight, quiet", camera_ok: ["backlighting", "from side", "straight-on", "from above"], expected_zones: [], partner: false, weight: 1, tier: main}   # 経路A s01f より移植
  intro_genkan:   {phase: intro, label_ja: 入口で出迎える,   situation: "standing at the entrance, greeting, gentle smile", camera_ok: ["straight-on", "from side", "from above", "dutch angle"], expected_zones: [], partner: false, weight: 1, tier: main}
  intro_tea:      {phase: intro, label_ja: 床に座って一服,     situation: "sitting on tatami, serving tea, relaxed", situation_neutral: "sitting on the floor, serving a drink, relaxed",         camera_ok: ["from side", "from above", "straight-on", "profile"], expected_zones: [], partner: false, weight: 1, tier: main}
  intro_engawa:   {phase: intro, label_ja: 窓辺で微笑,     situation: "sitting by the engawa, soft smile", situation_neutral: "sitting by a window, soft smile",                camera_ok: ["straight-on", "profile", "from side", "backlighting"], expected_zones: [], partner: false, weight: 1, tier: main}
  intro_lookback: {phase: intro, label_ja: 振り返る視線,   situation: "looking back over shoulder, inviting gaze",        camera_ok: ["from behind, ass focus", "from behind, looking back", "from side", "profile"], focus_ok: ["ass focus"], expected_zones: [], partner: false, weight: 1, tier: main}

  # ── approach(接近・脱ぎ始め・非露出〜谷間) ──
  app_collar:  {phase: approach, label_ja: 襟を開く,   situation: "sitting on the floor, open collar, looking up", camera_ok: ["from above", "straight-on", "from side", "dutch angle"], expected_zones: [], partner: false, weight: 1, tier: main}   # 経路A s02c より移植
  app_neck:    {phase: approach, label_ja: 首筋,       situation: "neck and collarbone, faint blush, breathing", camera_ok: ["from side", "straight-on", "from above", "profile"], expected_zones: [], partner: false, weight: 1, tier: main}   # 経路A s02d より移植
  app_kneel:   {phase: approach, label_ja: 膝立ちで見上げる, situation: "kneeling on the floor, looking up at viewer", camera_ok: ["from above", "pov", "from side", "straight-on"], expected_zones: [], partner: false, weight: 1, tier: main}   # 経路A s02f より移植
  app_futon:   {phase: approach, label_ja: 座って着崩れ, situation: "sitting on futon, clothes loosened, disheveled clothes", situation_neutral: "sitting down, clothes loosened, disheveled clothes", camera_ok: ["straight-on", "from side", "from above", "dutch angle"], expected_zones: [], partner: false, weight: 1, tier: main}   # 経路A s02g より移植
  app_shoulder: {phase: approach, label_ja: 肩に手,       situation: "a hand on her shoulder, close together",             camera_ok: ["straight-on", "from side", "from above", "dutch angle"], expected_zones: [], partner: true, weight: 1, tier: main}
  app_obi:      {phase: approach, label_ja: 帯を緩める,   situation: "loosening the sash, parted lips",                    camera_ok: ["from side", "straight-on", "from above", "profile"], expected_zones: [], partner: false, weight: 1, tier: main}
  app_behind:   {phase: approach, label_ja: 背後から抱擁, situation: "embraced from behind, intimate",                     camera_ok: ["from behind, ass focus", "from side", "from behind, looking back", "dutch angle"], focus_ok: ["ass focus"], expected_zones: [], partner: true, weight: 1, tier: main}
  app_sleeve:   {phase: approach, label_ja: 袖で口元,     situation: "covering mouth with sleeve, blushing, visible cleavage", camera_ok: ["straight-on", "from side", "from above", "profile"], expected_zones: [], partner: false, weight: 1, tier: main}
  app_pulled:   {phase: approach, label_ja: 引き寄せられる, situation: "being pulled close, disheveled clothes",            camera_ok: ["straight-on", "from side", "dutch angle", "from above"], expected_zones: [], partner: true, weight: 1, tier: main}

  # ── foreplay(前戯) ──
  fore_fellatio:    {phase: foreplay, label_ja: 口淫,   pose: "", act: "fellatio, oral",              camera_ok: ["pov", "straight-on", "from side", "from above", "dutch angle"], expected_zones: ["oral", "genitals"], partner: true, weight: 2, tier: main, alt: {2: fore_double_bj}}
  fore_handjob:     {phase: foreplay, label_ja: 手淫,   pose: "", act: "handjob, penis",         camera_ok: ["from side", "pov", "from above", "straight-on"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main, alt: {2: fore_bj_hj}}
  fore_cunnilingus: {phase: foreplay, label_ja: クンニ, pose: "spread legs", act: "cunnilingus, oral",           camera_ok: ["from above", "from side", "pov", "straight-on"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main}
  fore_fingering:   {phase: foreplay, label_ja: 指,     pose: "spread legs", act: "fingering",                   camera_ok: ["from side", "from above", "pov", "straight-on"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main}
  fore_paizuri:     {phase: foreplay, label_ja: パイズリ, pose: "", act: "paizuri, penis", camera_ok: ["pov", "straight-on", "from above", "from side"], focus_ok: ["breast focus"], expected_zones: ["genitals"], partner: true, weight: 1, tier: extra}
  fore_irrumatio:   {phase: foreplay, label_ja: 深口,   pose: "", act: "irrumatio, deepthroat",       camera_ok: ["pov", "from side", "from above", "straight-on"], expected_zones: ["oral", "genitals"], partner: true, weight: 1, tier: extra}
  # ── 胸への愛撫 ── 2026-08-05 追加(ユーザー要望)
  #   ★母乳の語はカードに持たせない。「乳首を舐める/吸う」「乳を揉む」は母乳と関係なく成立し、
  #     PLATE 03 の「▼ この行から」でオプション lactation を効かせておけば、
  #     **同じカードのまま母乳が出ている絵になる**。カード側に母乳を書き込むと
  #     母乳なしの作品で使えなくなるので書かない(1枚で両方に効かせる)。
  #   ★expected_zones に genitals を入れてある。この段階は脱いでいるので性器が画面に入りうる。
  #     多めに申告しておき、実際に不要なら PLATE 06 で「保護不要」を押して外せる(その口はある)。
  #     少なく申告すると**モザイク確認の対象から漏れる**ので、安全な側へ倒す。
  fore_nipple_lick:   {phase: foreplay, label_ja: 乳首を舐める, pose: "", act: "licking nipple, tongue on her nipple, mouth at her breast", camera_ok: ["straight-on", "from side", "from above", "pov"], focus_ok: ["breast focus"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main}
  fore_nipple_suck:   {phase: foreplay, label_ja: 乳首を吸う,   pose: "", act: "breast sucking, lips latched onto her nipple, mouth on her breast", camera_ok: ["straight-on", "from side", "from above", "pov"], focus_ok: ["breast focus"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main}
  # ★★2026-08-18 新設(ユーザー要望「女性側が男性の乳首を触ったり舐めたりする場面が欲しい」)。
  #
  # ★★★2026-08-22 全面書き直し。**刷ったら全部「男→女」になっていた**(オーナーが実画像で発見)。
  #   27枚の完成プロンプトを機械で数えた結果:
  #     女性の乳首の語 27/27枚(100%) / 男性の胸の語 0枚 / 男性が消えた絵 10枚(37%)
  #   原因は4つ重なっていた:
  #     A. 向きを `her tongue on his nipple` などの**英文**で書いていた。
  #        このモデルは Danbooru のタグしか読めないので **5語とも0枚＝完全に無効**だった
  #        ([[two-kinds-of-prompt-models]] `grey male hair` が0枚だったのと同じ型)。
  #     B. 効いていたのは向きを持たない `licking nipple` / `nipple tweak` だけ。
  #        ★実測(2026-08-22): その中身の 95% が「男→女」。
  #          licking_nipple 4,534枚のうち男性の胸が写るのは 303枚(6.7%)、
  #          nipple_tweak 23,754枚のうち 1,246枚(5.2%)。男女1人ずつに絞ると **28枚**。
  #        → 向きを言わずにこの語を書くと、ほぼ必ず逆になる。
  #     C. 同じ1枚に女性の乳首の語だけが3つ自動で付いていた。
  #        ★2026-08-22 撤回: これを止めたら**キャラの設定(陥没乳首・胸のほくろ)まで消え、
  #          リタが別人になった**(オーナー指摘)。女性側は1文字も触らない。
  #     D. 前戯の見せ方「手だけ」「主観」が当たり、男性が消えた(`view_ok: [""]` で止めた)。
  #
  #   ★向きの伝え方は `clothed female nude male`(59,209枚)にした。実測で選んだ理由:
  #       ぽっちゃり男性 × これ         = 1,545枚  ← いちばん多い
  #       ぽっちゃり男性 × topless male =   783枚
  #       ぽっちゃり男性 × licking nipple =  52枚
  #     ★`topless male` / `pectorals` を positive に足すのは**過去に測って却下済み**
  #       (`cast/partner_presets.yaml` の anti_male_shirt: pectorals の68%が muscular と同居し、
  #        ぽっちゃり体型が筋肉質に化ける)。だから胸の語ではなく「女は着衣・男は全裸」で言う。
  #   ★`male_undress: nude` で男性を必ず脱がせる(前は1枚ごとのサイコロで 27枚中9枚だけだった)。
  #
  # ★★★2026-08-22(2回目) ここまでで刷った30枚は **0/30 で全部まだ「男→女」だった**。
  #   1回目の結論「向きを持つ語は Danbooru に存在しない」が**間違いだった**。
  #   1回目は綴りを当てずっぽうに引いていただけ(`male_nipples` `nipple_licking`
  #   `licking_male_nipple` … 全部0枚)。**語の一覧を丸ごと走査したら2つ実在した**:
  #
  #     語                                     全体   1girl+1boy  女の乳首と同居  筋肉質と同居
  #     sucking_male_nipple                    852枚     242枚      128枚        306枚(35.9%)
  #     nipple_stimulation_(female_on_male)    312枚     186枚      100枚          2枚( 0.6%)
  #
  #   ★この2語だけが「女が男にしている」という**向きそのもの**を持つ。
  #     `licking nipple` `nipple tweak` は向きを持たず、中身の95%が「男→女」だった。
  #   ★女性の `nipples` と**ちゃんと同居する**(852枚中538枚 / 312枚中144枚)。
  #     つまり**女性側を触る必要は無い**。1回目に女性の胸の設定を消したのは完全に不要だった。
  #   ★[[prompt-word-order-rule]] 前の語ほど強いので、**向きの語を act の先頭**に置く。
  #   ★括弧つきの語は `\(` で逃がす。逃がさないと ComfyUI が「重み付け」と読んで語が割れる。
  #     そのため act は**シングルクォート**で書く(YAML の二重引用符では `\(` が書けない)。
  #
  # ★★★2026-08-22(3回目) 2回目も **0/7 で全部「男→女」のまま**だった
  #   (run 20260822-152337。語は 7/7枚に届いていた＝文章の問題ではない)。
  #   今度は推測をやめ、`nipple_stimulation_(female_on_male)` の絵 **200枚**を取り寄せて
  #   **一緒に付いている語を数えた**(道具: scripts/danbooru_cooccur_top.py)。
  #
  #     assertive_female  36%  ← ★これが候補に1つも入っていなかった
  #     femdom            40%
  #     pov               47%   / clothed_female_nude_male 35% / hetero 85%
  #
  #   ★数の非対称: 向きの語は312枚、女性の乳首の語 `nipples` は 1,128,843枚＝**3600倍**。
  #     小さい語1つでは勝てない。よく学習された大きい語で主導権を女性側へ寄せる。
  #     `assertive_female` = 18,134枚 / 1boy 85% / 1girl 85% / hetero 72% /
  #     yaoi 0.01% / 筋肉質 1.7%。**余計なものを連れてこない。**
  #   ★`femdom`(21,313枚)は**却下**。絵の 28%が bdsm・22%が bound(縛り)。
  #     欲しいのは「舐める・つまむ」なので縛りに化ける語は使わない。
  #
  #   ★★2回目に自分で足した `sucking male nipple` を**外した**。測ったら
  #     852枚中 434枚(**50.9%**)が `yaoi`(男同士)で、1girl は29%しかなかった。
  #     「男の乳首を吸う」と言ったつもりで、**女性が消える方向**へ引いていた。
  #     → 検査 ④ が `yaoi` との同居20%超を機械で落とす。
  #
  # ★★★2026-08-22(4回目) 3回目も **0/9 で全部「男→女」**だった(run 20260822-160220)。
  #   語は9/9枚に届いていた。**3回とも語の問題ではなかった。**
  #   実画像26枚を並べたら、真因は**画面の作り**だった:
  #     ① 女性がいつも**棒立ち**  → 口の高さが彼の胸に来ない
  #     ② 女性が**服から胸を出している** → 画面で「乳首」と呼べるのが彼女の胸だけ
  #   ★私は3回とも `act`(行為)の欄だけを直していて、**`pose`(姿勢)の欄は空のままだった。**
  #
  #   実測(正解の絵 312枚のうち):
  #     girl_on_top  57枚(18%)   squatting 49枚(16%)
  #     breasts_out  **17枚(5.5%)**  ← うちの刷り出しは 10枚中10枚(100%)
  #   ★同じ文の中で `clothed female nude male`(女は着衣) と `breasts out`(胸を出す)が
  #     **正面から矛盾**してもいた。
  #
  #   → `pose: girl on top` と `female_undress: top_kept`(上は着たまま・下だけ脱ぐ)を足した。
  #     `girl on top`(91,153枚)を選んだ理由(対 squatting):
  #       「女は着衣・男は全裸」と同居 7,393 対 2,573 ／「女性が能動」と同居 7,374 対 1,888
  #       筋肉質へ 0.7% 対 1.2% ／ 男同士へ 0.02% 対 0.6%
  #   ★`female_undress` は `outfits/_undress_wildcards.yaml` の **`by_card:` の棚**から引く。
  #     `stages:` には1行も足していない = **他のカードは1文字も変わらない**。
  #   ★★女性の脱げ方を変えるのは**オーナーの許可を得てから**やった(2026-08-22)。
  #     キャラ設定(陥没乳首・胸のほくろ・離れ乳)は**4回とも1文字も触っていない**。
  #   ★★次に刷ったら**服が消えていないか**を必ず見る。乳首の語は着せる語より強く
  #     服を消す([[clothed-paths-are-six]])。消えていても**女性の設定を勝手に外さない**。
  #
  #   ★`pectoral grab` は**つまむ側から外した**。2026-08-22 に測ったら
  #     2,775枚中 2,050枚(**73.9%**)が `muscular_male` と同居していた。
  #     却下済みの `pectorals`(68%)より悪い。相手役はぽっちゃり中年なので体つきが化ける。
  #     → 検査 ④ が「筋肉質を50%超引っ張る語」をその場で測って落とす。
  #   ★`expected_zones` を genitals にした。男性が全裸になるので股間が画面に入りうる。
  #     少なく申告するとモザイク確認から漏れるので安全な側へ倒す(上の2枚と同じ扱い)。
  #   検査: scripts/male_nipple_card_check.py (壊し方テスト male_nipple_card_break_test.py)
  fore_male_nipple_lick: {phase: foreplay, label_ja: 男性の乳首を舐める, pose: "girl on top", female_undress: top_kept, act: 'assertive female, nipple stimulation \(female on male\), clothed female nude male, licking nipple', camera_ok: ["straight-on", "from side", "from above"], focus_ok: [], expected_zones: ["genitals"], partner: true, weight: 1, tier: main, view_ok: [""], male_undress: nude, negative_extra: "grabbing another's breast, breast sucking"}
  fore_male_nipple_touch: {phase: foreplay, label_ja: 男性の乳首をつまむ, pose: "girl on top", female_undress: top_kept, act: 'assertive female, nipple stimulation \(female on male\), clothed female nude male, nipple tweak', camera_ok: ["straight-on", "from side", "from above"], focus_ok: [], expected_zones: ["genitals"], partner: true, weight: 1, tier: main, view_ok: [""], male_undress: nude, negative_extra: "grabbing another's breast, breast sucking"}
  fore_breast_grab:   {phase: foreplay, label_ja: 乳を揉む,     pose: "", act: "grabbing another's breast, hands squeezing her breasts, fingers sinking into her breasts", camera_ok: ["straight-on", "from side", "from above", "pov"], focus_ok: ["breast focus"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main}
  fore_breast_behind: {phase: foreplay, label_ja: 背後から乳を揉む, pose: "", act: "grabbing another's breast, from behind, hands over her breasts from behind, squeezing her breasts", camera_ok: ["from behind, ass focus", "from side", "from behind, looking back", "dutch angle"], focus_ok: ["ass focus", "breast focus"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main}

  # ── foreplay 3P (男性2人必須) ── 2026-08-01追加。cast.male_min=2 = 3P設定時のみ使う
  fore_double_bj:   {phase: foreplay, label_ja: 二人に交互フェラ, pose: "", act: "fellatio, handjob, 2boys, two erect penises near her face, sucking one while stroking the other", camera_ok: ["from above", "straight-on", "pov", "from side"], expected_zones: ["oral", "genitals"], partner: true, cast: {male_min: 2, male_max: 2, roles: [A, B]}, weight: 1, tier: main}
  fore_bj_hj:       {phase: foreplay, label_ja: フェラ+手コキ, pose: "", act: "fellatio, handjob, 2boys, sucking one erect penis while stroking another with hand, kneeling between two men", camera_ok: ["from side", "straight-on", "from above", "pov"], expected_zones: ["oral", "genitals"], partner: true, cast: {male_min: 2, male_max: 2, roles: [A, B]}, weight: 1, tier: main}

  # ── main(挿入・主要10) ──
  # ★2026-08-12 段E「姿勢の語」を追加。
  #   なぜ: 本番450枚を絵から読むと、正常位を指示した82枚のうち **正常位に見えるのは0枚**で、
  #   跨がる33 / 女性が上32 / 立っている25 に化けていた(全身で撮った16枚でも0/16なので、
  #   寄って写らなかったのではなく本当に出ていない)。
  #   原因は語の強さ。うちは `missionary`(Danbooru 48,187枚) 1語で頼んでいたが、
  #   敵になる `girl_on_top`(90,650) `straddling`(95,653) が2倍あり、そちらへ寄る。
  #   いちばん強い `on back`(352,418) `spread legs`(346,086) を一度も使っていなかった。
  #   参考作品60ページを同じ道具で読むと、寝ている37% / 脚を開く27% / 仰向け23% / 正常位15%
  #   ＝ 欲しい絵は「正常位」より「仰向け＋脚を開く」で書かれている。
  #   ★戻し方: 各 pose から足した語を消すだけ(コードは1行も変えていない)。
  main_missionary:      {phase: main, label_ja: 正常位,      pose: "missionary, on back, spread legs", act: "vaginal, intercourse with a man", camera_ok: ["from above", "straight-on", "pov", "from side", "dutch angle"], camera_avoid: ["from behind"], expected_zones: ["genitals", "union"], partner: true, weight: 3, tier: main, alt: {2: main_face_and_insert}}
  main_missionary_ftf:  {phase: main, label_ja: 対面正常位,  pose: "boy on top, missionary, face-to-face, on back, spread legs", act: "vaginal, intercourse with a man", camera_ok: ["straight-on", "pov", "from side", "dutch angle"], camera_avoid: ["from behind", "from above"], expected_zones: ["genitals", "union"], partner: true, weight: 2, tier: main}
  # ★2026-08-16 カメラを4つ追加(ユーザーが試し刷り6枚を見て「構図として採用できる」と判断)。
  #   いままで後ろからの絵は `from behind, looking back`(振り返る)しか無く、
  #   **振り返らない後ろから**が1枚も作れなかった。実測の枚数は
  #   from behind 325,308 / ass focus 45,071 / from above 143,906 / top-down bottom-up 28,331。
  #   戻し方: 追加した4つを消すだけ(既存の6つは順番も含めて非変更)。
  # ── ★2026-08-21「顔を見せない後ろ姿」を出せるようにした ─────────────────
  #   ユーザー提示の参考（画像00089）にある「うつ伏せで枕に顔をうずめ、こちらに
  #   顔を見せない」構図が、うちのツールから**一度も出ていなかった**
  #   （本番100枚を機械で見て 0枚 / 過去3,806枚の文章に「顔を見せない」語が0個）。
  #   原因は1つだけ。**そう言う語がツールのどこにも無かった**こと。
  #   実測（着衣A/B 20枚・scripts/face_hidden_ab.py）:
  #       本番のまま            0/4
  #       ＋ `facing away`      3/4   ← ★足すだけで出た
  #       ＋目の指示を外す/表情を外す/LoRA を弱める … どれも変わらず（無関係だった）
  #   Danbooru: facing_away 40,022枚 / facing_away+from_behind 26,147枚
  #             sex_from_behind+facing_away+pov 1,083枚（＝参考画像そのもの）
  #   ★`ass focus` は付けない。付けると尻が画面の半分を占めて体のつながりが崩れる
  #     （目標画像はもっと引き。頭の大きさ 18.6%）。
  #   ★★重み 1.3 を付ける理由（2026-08-21・着衣で6種ずつ実測）:
  #       素の `facing away`            2/6
  #       `(facing away:1.3)`           3/6   ← ★これを採用（姿勢は崩れない）
  #       `facing away, top-down bottom-up` 3/6  ← 同点だが**姿勢が崩れる種があった**
  #                                         （女性が上下逆になり、こちらを向く）
  #       両方いっぺんに               3/6   ← top-down と同じ絵。重ねても増えない
  #     ★効く/効かないは**種でほぼ決まる**（同じ種がいつも成功し、同じ種がいつも失敗する）。
  #     `ass focus` の有無・演出の語の有無では**1枚も変わらなかった**。
  #   ★戻し方: 各行から `"from behind, facing away"` と
  #     `"from above, from behind, facing away"` を消す1手。
  #   ★これは「新しい選択肢」ではない。利用者が選ぶものは1つも増えない
  #     （既にある札のカメラが1種類 増えるだけ）。
  main_doggystyle:      {phase: main, label_ja: 後背位,      pose: "doggystyle, all fours", act: "sex from behind", camera_ok: ["from behind, looking back", "from side", "from above", "from below", "dutch angle", "straight-on", "from behind", "from behind, ass focus", "from above, from behind", "top-down bottom-up, ass focus", "from behind, (facing away:1.3)", "from above, from behind, (facing away:1.3)"], focus_ok: ["ass focus"], kiss_helper: "looking back", expected_zones: ["union", "genitals"], partner: true, weight: 3, tier: main, alt: {2: main_sandwich}}
  main_spooning:        {phase: main, label_ja: 側臥位,      pose: "spooning, lying, on side", act: "vaginal, intercourse with a man", camera_ok: ["from side", "from above", "from behind, looking back", "pov", "dutch angle", "from behind", "from behind, ass focus"], camera_avoid: ["straight-on"], focus_ok: ["ass focus", "breast focus"], kiss_helper: "looking back", expected_zones: ["union", "genitals"], partner: true, weight: 2, tier: main}
  main_cowgirl:         {phase: main, label_ja: 騎乗位,      pose: "cowgirl position, straddling, spread legs", act: "vaginal, intercourse with a man", camera_ok: ["from below", "straight-on", "pov", "from side", "dutch angle"], camera_avoid: ["from behind"], focus_ok: ["breast focus"], expected_zones: ["union", "genitals"], partner: true, weight: 3, tier: main, alt: {2: main_sandwich}}
  main_reverse_cowgirl: {phase: main, label_ja: 背面騎乗,    pose: "reverse cowgirl position", act: "vaginal, intercourse with a man", camera_ok: ["from below", "from behind, ass focus", "pov", "from side", "from behind, looking back"], camera_avoid: ["straight-on"], focus_ok: ["ass focus"], kiss_helper: "looking back", expected_zones: ["union", "genitals"], partner: true, weight: 2, tier: main}
  main_upright_straddle: {phase: main, label_ja: 対面座位,   pose: "upright straddle", act: "vaginal, intercourse with a man", camera_ok: ["from side", "straight-on", "dutch angle", "from below"], camera_avoid: ["from above"], expected_zones: ["union", "genitals"], partner: true, weight: 2, tier: main}
  main_amazon:          {phase: main, label_ja: 女性上位,    pose: "amazon position", act: "vaginal, intercourse with a man", camera_ok: ["from below", "straight-on", "from side", "pov"], camera_avoid: ["from behind"], focus_ok: ["breast focus"], expected_zones: ["union", "genitals"], partner: true, weight: 1, tier: main}
  main_prone_bone:      {phase: main, label_ja: 寝バック,    pose: "prone bone, lying, on stomach", act: "sex from behind", camera_ok: ["from above", "from behind, ass focus", "from side", "from behind, looking back", "dutch angle", "from behind", "from above, from behind, ass focus", "top-down bottom-up, ass focus", "from behind, (facing away:1.3)", "from above, from behind, (facing away:1.3)"], camera_avoid: ["straight-on"], focus_ok: ["ass focus"], kiss_helper: "looking back", expected_zones: ["union", "genitals"], partner: true, weight: 2, tier: main}
  main_folded:          {phase: main, label_ja: 屈曲位,      pose: "folded, on back, legs up, spread legs", act: "vaginal, intercourse with a man", camera_ok: ["from above", "straight-on", "from side", "pov", "dutch angle"], camera_avoid: ["from behind"], expected_zones: ["genitals", "union"], partner: true, weight: 2, tier: main}
  # ── main 3P (男性2人必須) ── 2026-08-01追加。既存 main_spitroast は tier: restricted のまま
  main_sandwich:        {phase: main, label_ja: 挟み込み(両側から), pose: "mmf threesome, sandwiched", act: "threesome, group sex, 2boys, one man behind and the other in front, penetration from one side and rubbing from the other", camera_ok: ["from side", "dutch angle", "straight-on", "from above"], expected_zones: ["genitals", "union"], partner: true, cast: {male_min: 2, male_max: 2, roles: [A, B]}, weight: 1, tier: main}
  main_face_and_insert: {phase: main, label_ja: 顔前+挿入, pose: "mmf threesome, one man below, one man near the face", act: "threesome, 2boys, empty eyes, one man penetrating from below while the other stands over her face with erect penis near her mouth, dazed expression", camera_ok: ["from side", "from above", "straight-on", "dutch angle"], expected_zones: ["genitals", "union", "oral"], partner: true, cast: {male_min: 2, male_max: 2, roles: [A, B]}, weight: 1, tier: main}

  # ── main(温存 extra・かんたんには出さない) ──
  main_recumbent:       {phase: main, label_ja: 寝位,        pose: "reclining, lying, on side", act: "vaginal, intercourse with a man", camera_ok: ["from side", "from above", "straight-on", "dutch angle"], expected_zones: ["union", "genitals"], partner: true, weight: 1, tier: extra}
  main_reverse_upright: {phase: main, label_ja: 背面座位,    pose: "reverse upright straddle", act: "vaginal, intercourse with a man", camera_ok: ["from side", "from behind, looking back", "from above", "dutch angle"], camera_avoid: ["straight-on"], focus_ok: ["ass focus"], kiss_helper: "looking back", expected_zones: ["union", "genitals"], partner: true, weight: 1, tier: extra}
  main_suspended:       {phase: main, label_ja: 駅弁,        pose: "suspended congress", act: "vaginal, intercourse with a man", camera_ok: ["from side", "straight-on", "from below", "from behind, looking back"], camera_avoid: ["from above"], expected_zones: ["union", "genitals"], partner: true, weight: 1, tier: extra}

  # ── main(restricted・既定OFF・こだわりで警告付ON) ──
  main_spitroast:     {phase: main, label_ja: スピットロースト, pose: "spitroast", act: "group sex, threesome, 2boys", camera_ok: ["from side", "from above", "straight-on", "dutch angle"], expected_zones: ["union", "genitals", "oral"], partner: true, cast: {male_min: 2, male_max: 2, roles: [A, B]}, weight: 1, tier: restricted, warn: "男性2人・複数人=審査要注意"}
  main_kneeling_bound: {phase: main, label_ja: 膝立ち拘束風,  pose: "kneeling, arms behind back", act: "vaginal, intercourse with a man", camera_ok: ["straight-on", "from above", "from side", "from below"], kiss_helper: "looking back", expected_zones: ["genitals", "union"], partner: true, weight: 1, tier: restricted, warn: "拘束=グレー帯"}

  # ── climax(フィニッシュ=射精の演出)──────────────────────────────────
  # ★2026-08-22 大幅追加。なぜ: 100枚の作品でフィニッシュは **6枚(6%)・3種類しかなく**、
  #   導入6/接近13/前戯22/中核47 の中で**いちばん薄い段**だった。
  #   しかも設計の記録(docs/design/scene-inventory-audit.md)では元は
  #   **「8〜12構図・顔射を含む」**で設計されていた。意図して減らしたのではなく痩せていた。
  #
  # ★語はすべて Danbooru で実測してから採用した(2026-08-22)。出典は利用者提示の2記事
  #   (pororingames.com/cum-prompt/ と aiartrecipe.com/archives/3132)。
  #   ★★**記事の推奨語のうち16語が0枚 = 書いても絵に何も起きない**。全部弾いた:
  #     creampie / cumshot / cum shot / ejaculating / cum inside / semen /
  #     cum facial / cum on face / cum on thigh / cum on thighs / cum on foot /
  #     cum on glasses / cum in anus / cum puddle / covered in cum / pulling out
  #   ★少なすぎて足さなかった: cum in throat 410 / cum bath 274 / cum swap 263
  #   ★弱いので足さなかった: cum on back 1,007(性行為との組み合わせは433枚=0.1%)
  #   ([[two-kinds-of-prompt-models]] 記事の助言は別のエンジン向けか先に見る)
  #
  # ★引きの絵は足していない。実測 `cum in pussy` × `wide shot` = **8枚**、
  #   `full body` でも 3,775枚(2.6%)。**引きは語では作れない**ので寄りだけで正しい。
  #   (カメラの距離は camera_shots の climax = upper body/close-up/portrait/cowboy shot)
  #
  # ── 最初から出る(tier: main)──
  # ★2026-08-22 修正(バグ): `ejaculating while penetrated` の `ejaculating` は **0枚**。
  #   実在するのは `ejaculation`(71,926)。後半は書いても効いていなかった。
  climax_creampie:   {phase: climax, label_ja: 体内,     pose: "spread legs", act: "vaginal, sex, cum in pussy, ejaculation, penis", camera_ok: ["from above", "pov", "from side", "straight-on", "dutch angle"], expected_zones: ["genitals", "union"], partner: true, weight: 2, tier: main, alt: {2: climax_double_bukkake}}
  # ★★2026-08-22（利用者が実機で発見:「胸に出すなら性器が胸の近くでないとおかしい」）。
  #   それまでフィニッシュの文には**男性器のことが1文字も書かれていなかった**。原因は3段:
  #     ① カードが「どこに出すか」しか言っていない（14枚中8枚の pose が空）
  #     ② 語だけでは写らない。Danbooru 実測でその語の絵に男性器が写る割合は
  #        お尻48% / 胸58% / 体61% / 髪65% / 顔67% / 口75%。**4〜5割は写らない**
  #     ③ ツールの男性器の仕組みは利用者が大きさ・勃起状態を**選んだときだけ**動く。
  #        保存の相手役2人はどちらも選んでおらず、一度も動いていなかった
  #   証拠: 利用者が刷った story-20260822-154336 のフィニッシュ10枚すべてに
  #        penis / fellatio / paizuri / erection が1つも無かった。
  #   → **カード自身に書く**。②③のどちらにも依存しないので必ず効く。
  #   ★並びは「位置を決める語 → 結果 → penis」。前の語が優先（[[prompt-word-order-rule]]）。
  #   検査 = scripts/finish_geometry_check.py（本番経路まで通す・わざと壊すと落ちる）
  climax_on_breasts: {phase: climax, label_ja: 体外・胸, pose: "", act: "cum on breasts, penis", camera_ok: ["straight-on", "from above", "pov", "from side"], focus_ok: ["breast focus"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main, alt: {2: climax_double_bukkake}, negative_extra: "cum in pussy, vaginal"}
  # ★2026-08-22 新設（オーナー決定「2枚に分ける」）。胸射で**位置を確実に胸にする**唯一の
  #   測れた方法が paizuri（実測 cum_on_breasts×paizuri = 14,993枚）。
  #   `between_breasts` は 964枚で弱く、`penis on breast` は0枚で存在しない。
  #   ★上の「体外・胸」は消していない。行為を限定したくない人はそちらを使う。
  climax_paizuri:    {phase: climax, label_ja: 乳の間から出す, pose: "", act: "paizuri, cum on breasts, penis", camera_ok: ["straight-on", "pov", "from above", "from side"], focus_ok: ["breast focus"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main, alt: {2: climax_double_bukkake}, negative_extra: "cum in pussy, vaginal"}
  climax_in_mouth:   {phase: climax, label_ja: 口内,     pose: "", act: "fellatio, cum in mouth, penis", camera_ok: ["pov", "straight-on", "from above", "from side"], expected_zones: ["oral", "genitals"], partner: true, weight: 1, tier: main, alt: {2: climax_double_bukkake}, negative_extra: "cum in pussy, vaginal"}
  # ★実測 cum in pussy 142,949 × cumdrip 43,163 の組み合わせ = **29,920枚**。いちばん大きい欠落だった
  climax_cumdrip:    {phase: climax, label_ja: 垂れてあふれる, pose: "spread legs", act: "vaginal, sex, cum in pussy, cumdrip, cum overflow, penis", camera_ok: ["from above", "pov", "from side", "straight-on", "dutch angle"], expected_zones: ["genitals"], partner: true, weight: 2, tier: main, alt: {2: climax_double_bukkake}}
  # ★「射精の瞬間そのもの」を描く語がツールに1つも無かった。ejaculation 71,926 × penis の組み合わせ = 63,332枚
  climax_pullout:    {phase: climax, label_ja: 抜いて出す瞬間, pose: "spread legs", act: "ejaculation, penis", camera_ok: ["from above", "pov", "from side", "straight-on", "dutch angle"], expected_zones: ["genitals"], partner: true, weight: 2, tier: main, alt: {2: climax_double_bukkake}, negative_extra: "cum in pussy, vaginal"}
  # ★cum on body 127,241 は余韻カードだけが持っていた。「かかった瞬間」として独立させる
  climax_on_body:    {phase: climax, label_ja: 体にかける, pose: "", act: "cum on body, penis", camera_ok: ["straight-on", "from above", "pov", "from side", "dutch angle"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main, alt: {2: climax_double_bukkake}, negative_extra: "cum in pussy, vaginal"}
  climax_on_hair:    {phase: climax, label_ja: 髪にかかる, pose: "", act: "cum on hair, penis", camera_ok: ["straight-on", "from above", "pov", "from side"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main, alt: {2: climax_double_bukkake}, negative_extra: "cum in pussy, vaginal"}
  # ── climax 3P (男性2人必須) ── 2026-08-01追加
  climax_double_bukkake: {phase: climax, label_ja: 顔・胸に二人分, pose: "", act: "bukkake, facial, cum on body, 2boys, penis, thick semen dripping from her cheeks and chin, hands beside her head, open mouth", camera_ok: ["straight-on", "from above", "pov", "from side"], expected_zones: ["genitals"], partner: true, cast: {male_min: 2, male_max: 2, roles: [A, B]}, weight: 1, tier: main, negative_extra: "cum in pussy, vaginal"}
  # ★2026-08-22 昇格(オーナー判断)。`facial` は 60,980枚 = 中出し(142,949)に次ぐ2番目の定番なのに、
  #   注意書きつきの棚に眠っていて既定では1枚も出なかった。語は1文字も変えていない。
  #   ついでに直した2点: 3人用の差し替え先が抜けていた / カメラの向きが3つしか無かった(他は5つ)
  climax_facial:     {phase: climax, label_ja: 顔射,     pose: "", act: "facial, penis", camera_ok: ["pov", "straight-on", "from above", "from side", "dutch angle"], expected_zones: ["genitals"], partner: true, weight: 1, tier: main, alt: {2: climax_double_bukkake}, warn: "顔射=審査弱リスク(既定ONはオーナー判断)", negative_extra: "cum in pussy, vaginal"}
  # ── 注意書きつき(tier: restricted・既定では出ない。PLATE 03 で選べば出る)──
  # ★2026-08-22 判断の記録: `penis`(589,401) と `excessive cum`(3,849) は **153倍差**で、
  #   検査(option_tag_check)が綱引きとして参考に挙げる。それでも penis を残した理由:
  #     ・利用者の指摘（男性器が写っていない）に直接効くのはこの語だから
  #     ・bukkake 単体で男性器が写るのは 60%（実測 10,093/16,878）で確実ではない
  #   ★別件の宿題: このカードは元から `bukkake × excessive cum` の共起が **637枚**しかない。
  #     2語の組み合わせ自体が弱い。作り直すなら別途測ること（今回は触らない）。
  climax_excessive:  {phase: climax, label_ja: 多量,     pose: "", act: "bukkake, excessive cum, penis", camera_ok: ["straight-on", "from above", "pov", "from side"], expected_zones: ["genitals"], partner: true, weight: 1, tier: restricted, warn: "多量=審査弱リスク", negative_extra: "cum in pussy, vaginal"}
  # ★中出しの定番演出なのにツールに無かった。cross-section 18,414 / internal cumshot 12,394 / uterus 11,780
  #   組み合わせ実測: cum in pussy × cross-section = 8,694 / × internal cumshot = 10,292
  # ★★2026-08-22 昇格（オーナー判断・実画像で確認してから決めた）。
  #   利用者の指摘「中出しがうまく表現されていない」を追いかけた結論:
  #     **入っているものは見えない**ので、男性器を見せるほど絵は「外」になる。
  #     実測でも Danbooru の中出し＋性行為の絵は **82% に男性器が写っている**
  #     (cum_in_pussy sex penis 78,494 / 同 -penis 16,895)。
  #     ＝ 普通の中出しカードでは「入っている」を描けないのが道理。
  #   → 中を見せる断面図が、測れた唯一の方法。実画像2枚とも成功した:
  #       1枚目 体に断面を重ねる形 ／ 2枚目 隅に断面のコマ（どちらも漫画の作法）
  #     図解っぽくならず、キャラの表情も背景もそのまま馴染んだので既定へ上げる。
  #   ★warn は残す（好みが分かれる表現であることは事実なので画面に出す）。
  #   戻し方: tier を restricted に戻す1語。
  climax_cross_section: {phase: climax, label_ja: 断面図(中の様子), pose: "spread legs", act: "vaginal, cross-section, internal cumshot, cum in pussy, uterus, penis", camera_ok: ["from side", "straight-on", "from above"], expected_zones: ["genitals", "union"], partner: true, weight: 1, tier: main, warn: "断面図=表現が特殊。好みが分かれる"}
  climax_on_ass:     {phase: climax, label_ja: お尻にかける, pose: "", act: "cum on ass, penis", camera_ok: ["from behind, ass focus", "from above", "from side", "from behind"], focus_ok: ["ass focus"], expected_zones: ["genitals"], partner: true, weight: 1, tier: restricted, warn: "既定では出ない(好みが分かれる)", negative_extra: "cum in pussy, vaginal"}
  climax_in_ass:     {phase: climax, label_ja: アナルに出す, pose: "anal", act: "cum in ass, penis", camera_ok: ["from behind, ass focus", "from above", "from side", "from behind"], focus_ok: ["ass focus"], expected_zones: ["genitals", "union"], partner: true, weight: 1, tier: restricted, warn: "アナル=作品のジャンルが変わる"}
  climax_projectile: {phase: climax, label_ja: 飛ばす,   pose: "", act: "projectile cum, penis", camera_ok: ["from side", "straight-on", "from above", "dutch angle"], expected_zones: ["genitals"], partner: true, weight: 1, tier: restricted, warn: "既定では出ない演出", negative_extra: "cum in pussy, vaginal"}
  # ── afterglow(余韻)──
  ag_lookup:  {phase: afterglow, label_ja: 直後・見上げる, situation: "after sex, lying on her back, looking up, limp, cum on body, dazed", camera_ok: ["from above", "pov", "straight-on", "from side"], expected_zones: ["genitals"], partner: false, weight: 1, tier: main, alt: {2: ag_between_two}}   # 経路A s05e より移植
  ag_engawa:  {phase: afterglow, label_ja: 翌朝・窓辺,   situation: "the morning after, sitting by the engawa, backlight, calm", situation_neutral: "the morning after, sitting by a window, backlight, calm", camera_ok: ["backlighting", "from side", "profile", "straight-on"], expected_zones: [], partner: false, weight: 1, tier: main, expr: ["light smile, closed mouth", "happy, light smile", "light smile, parted lips"]}   # 経路A s05f より移植
  # 2026-07-23 再定義。旧版は3枚とも「服を着たまま少し乱れている」で導入/接近と絵が変わらなかった。
  #   時間軸=二段構え(直後2枚+翌朝1枚)/ 到達点=ほぼ全裸(衣装側 states.afterglow が担当)/ 事後の痕跡=明示。
  #   構図は upper body をやめ、脱力した全身が見える画角へ(旧版は3枚中2枚が上半身)。
  #   ★カードIDは preset(short30_rina_washitsu)が参照しているので変えない。中身だけ差し替える。
  ag_futon:      {phase: afterglow, label_ja: 直後・横たわって放心, situation: "after sex, lying on futon, completely spent, limp, spread legs, cum on body, heavy breathing, sweat", situation_neutral: "after sex, lying down, completely spent, limp, spread legs, cum on body, heavy breathing, sweat", camera_ok: ["from side", "from above", "straight-on", "profile"], expected_zones: ["genitals"], partner: false, weight: 1, tier: main, alt: {2: ag_between_two}}
  ag_afterglow:  {phase: afterglow, label_ja: 直後・事後の余韻, situation: "after sex, lying on her back, spread legs, limp, cum on breasts and stomach, flushed skin, dazed", camera_ok: ["from above", "from side", "straight-on", "dutch angle"], expected_zones: ["genitals"], partner: false, weight: 1, tier: main, alt: {2: ag_between_two}}
  # 翌朝は熱が引いた静けさ。裸のままだが痕跡は残さず、上半身+ブランケットで締める(genitals は画角外)。
  #   expr = カード固有の表情プール。phase 既定(expr_afterglow.txt)は直後向けなので、翌朝だけ穏やかな顔に上書きする。
  ag_snuggle:    {phase: afterglow, label_ja: 翌朝・寄り添い,   situation: "the morning after, resting together under a blanket, calm, bare shoulders", camera_ok: ["straight-on", "from side", "from above", "profile"], expected_zones: [], partner: true, weight: 1, tier: main, expr: ["happy, light smile", "light smile, parted lips", "light smile, closed mouth"]}
  # ── afterglow 3P (男性2人必須) ── 2026-08-01追加
  ag_between_two: {phase: afterglow, label_ja: 直後・二人の間で横臥, situation: "after threesome, lying on her back between two men, completely spent, cum on body from two sources, three bodies on the bed, heavy breathing, sweat", situation_neutral: "after threesome, lying on her back between two men, completely spent, cum on body from two sources, three bodies close together, heavy breathing, sweat", camera_ok: ["from above", "from side", "straight-on", "dutch angle"], expected_zones: ["genitals"], partner: true, cast: {male_min: 2, male_max: 2, roles: [A, B]}, weight: 1, tier: main}

  # ── 情景(無人カット) ── 2026-07-26 追加。文字演出レイヤー(Step1)と対になるカード。
  #   参考作品3点すべてが「キャラのいない背景1枚＋環境音」で場所と季節を立てていた。
  #   キャラが写らないので expected_zones は空=モザイク不要、手指・破綻のリスクもない。
  #
  #   ★no_character: true の意味(recipe.py build_jobs が解釈する)
  #     キャラ prompt.base と衣装を差し込まない。代わりに negative_extra で人物を押し出す。
  #     年齢ガードは一切弱めていない: L1(年齢negative)はそのまま、L3/L3'(展開後検査)も通る。
  #     人物を描かせない方針なので L2 の成人アサーションは対象外になるが、
  #     万一人物が出ても L1 negative と下の negative_extra が効く。
  #
  #   ★どの preset にも組み込んでいない(既存 preset の枚数配分を勝手に変えないため)。
  #     使うには preset の blocks.<phase>.cards に足す=ユーザー判断。
  sc_house_day:  {phase: intro, label_ja: 情景・和風の家の外(昼), situation: "no humans, empty scene, exterior of an old japanese house, summer afternoon, cicada season, bright sunlight", camera_ok: ["scenery, wide shot", "scenery, from below", "scenery, from side"], expected_zones: [], partner: false, weight: 1, tier: main, no_character: true, no_shot: true}
  sc_corridor:   {phase: intro, label_ja: 情景・和風の廊下,       situation: "no humans, empty scene, wooden corridor of a japanese house, shoji screens, quiet, afternoon light", camera_ok: ["scenery, wide shot", "scenery, from below", "scenery, from above"], expected_zones: [], partner: false, weight: 1, tier: main, no_character: true, no_shot: true}
  sc_room_night: {phase: afterglow, label_ja: 情景・和室の夜, situation: "no humans, empty scene, japanese room at night, futon laid out, dim lamp light, still air", camera_ok: ["scenery, wide shot", "scenery, from above", "scenery, from side"], expected_zones: [], partner: false, weight: 1, tier: main, no_character: true, no_shot: true}

  # ── 情景(舞台を受け取る版) ── 2026-08-12 追加。
  #   ★上の3枚は和室が文に焼き込まれているので、「リビング」を選んでも和室が出る。
  #     そのため今までどのキットにも入れられなかった。ここは `use_setting: true` で
  #     **選んだ舞台をそのまま受け取る**ので、どの部屋でも成立する。
  #   ★なぜ要るか(実測): **引きは語では作れない**と8通りの試験で確定した
  #     （`wide shot` は 16.8〜21.6% で動かない。LoRA を外しても変わらない）。
  #     一方で**人物が小さく環境が広い絵は奥行きが 1.460**（本番100枚の中央値 1.087）。
  #     ＝ 引きと奥行きは同じ問題で、答えは「人物を主役から降ろす」こと。
  #     参考作品3点すべてが「キャラのいない背景1枚」で場所と時間を立てていた。
  #   ★使う語はすべて Danbooru で実測済み:
  #     no humans 230,919 / bed sheet 122,645 / pillow 201,464 / bed 135,877 /
  #     window 178,013 / curtains 91,307 / indoors 542,427 / scenery 73,797 /
  #     clothes on floor 1,133 / clothes removed 10,237 / still life 9,760
  #     ★弾いた語(0枚): discarded clothes / rumpled bedsheets / sheets /
  #       panties on floor / empty room(40枚)
  #   ★上の3枚は消していない（和室を選ぶ人の選択肢）。
  # ★`scenery` は camera_ok 側が必ず付けるので situation には書かない
  #   (同じ語を2回置くとその語の重みだけが黙って倍になる。2026-08-07 に色で痛い目を見た型)
  sc_room_wide:    {phase: intro,     label_ja: 情景・部屋の引き,     situation: "no humans, nobody, indoors, still air", use_setting: true, camera_ok: ["scenery, wide shot", "scenery, from above", "scenery, from side"], expected_zones: [], partner: false, weight: 1, tier: main, no_character: true, no_shot: true}
  sc_window_light: {phase: intro,     label_ja: 情景・窓と光,         situation: "no humans, nobody, indoors, window, curtains", use_setting: true, camera_ok: ["scenery, from side", "scenery, wide shot", "scenery, from below"], expected_zones: [], partner: false, weight: 1, tier: main, no_character: true, no_shot: true}
  sc_clothes_floor: {phase: approach, label_ja: 情景・脱いだ服,       situation: "no humans, nobody, indoors, clothes on floor, clothes removed, still life", use_setting: true, camera_ok: ["scenery, from above", "scenery, from side", "scenery, wide shot"], expected_zones: [], partner: false, weight: 1, tier: main, no_character: true, no_shot: true}
  sc_bed_only:     {phase: main,      label_ja: 情景・寝具だけ,       situation: "no humans, nobody, indoors, bed, bed sheet, pillow, still life", use_setting: true, camera_ok: ["scenery, from above", "scenery, from side", "scenery, wide shot"], expected_zones: [], partner: false, weight: 1, tier: main, no_character: true, no_shot: true}
  sc_after_room:   {phase: afterglow, label_ja: 情景・事後の部屋,     situation: "no humans, nobody, indoors, bed, bed sheet, pillow, clothes on floor, still life", use_setting: true, camera_ok: ["scenery, wide shot", "scenery, from above", "scenery, from side"], expected_zones: [], partner: false, weight: 1, tier: main, no_character: true, no_shot: true}
