/* ==========================================================================
   primitives.css — ボタン・チップ・タブ・入力・シート・トースト・ガラス
   全ページ共通。グッズコレクションもこれを使う。
   ⚠️ 1画面に .btn-primary は 1 つだけ。
   ========================================================================== */

/* 🔴🔴【便B・B-11】`hidden` 属性は、地の指定（`display: flex` 等）を持つクラスが同じ要素に
   付くと、そのクラスの指定に負けて効かなくなることがある。個別に `.x[hidden]{display:none}`
   を足さず、ここ1か所で塞ぐ（`public/styles/global.css:484` に同じ規則が既にあるが、
   このファイル単体で読まれる場面のためにも重ねておく＝上書きし合わない・害はない）。 */
[hidden] { display: none !important; }

/* --- 1 主ボタン ----------------------------------------------------------
   塗り。一般ページは橙、BORUTO ページはシアン、グッズは「ページのテーマ色」。
   色は --btn-ac / --btn-on で差し替える（既定は橙）。
   🔴🔴【是正・2026-09-09・PM裁定＝pack_contradiction（`.mp2-seg` 44pxと同型）】
   地（--btn-ac の既定＝--fire）はオーナー決定でテーマ固定（明暗で変わらない・ブランド面は
   常に明るい側の橙）。⇒ 文字（--btn-on）も**同じ理由でテーマ固定でなければならない**——
   地がテーマ固定なのに文字だけテーマ可変（旧 var(--text)＝暗いとき#EDEDF0）にすると、
   暗いときだけ地と文字がどちらも動かず正しく見える組み合わせが崩れる（実測＝2.29:1、
   基準4.5を大幅に下回る）。**このファイル自身の1行目「色はトークンから」という指示を
   文字どおり読むと、まさにこの動くトークンを選んでしまう**＝規約の逐語と意図が食い違う
   （`.mp2-seg`のタップ域と同種の矛盾）。⇒ **意図（地に合わせて文字も固定）を優先し、
   逐語（トークンを使う）よりテーマ固定トークン --ink を選ぶ。**
   ⚠️ インライン上書き（コレクションの `style="--btn-on:var(--col-on-ac)"` 等）はこの既定を
   経由しない別経路＝`--col-on-ac` 自体がテーマ固定かどうかは別途実測が要る（このコメントは
   既定値だけの話）。 */
.btn-primary {
  --btn-ac: var(--fire);
  --btn-on: var(--ink);
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--tap-primary); padding: 0 22px;
  border: 0; border-radius: var(--r-pill);
  background: var(--btn-ac); color: var(--btn-on);
  /* 🔴【UAT第9便⑲・椿さんご指摘 2026-09-17】ボタンには下線を引かない。
     ⚠️ サイト全体の `a` が橙の下線を引く（global.css）。`<a class="btn-…">` は
        リンクでもあるのでその下線を受け継ぐ。⇒ **部品の側で打ち消す。**
     ⭐ 打ち消すのはボタンだけ＝本文中のふつうのリンクの下線は残る（そちらは意図どおり）。 */
  text-decoration: none;
  /* 🔴【WO-092・第6便・椿さん 2026-09-21】「文字の大きさは規定に揃えて。」＝15px → 6段の16px
     （規定の言葉でも `--fs-body` は「**主なボタンの文字**」と書いてある）。 */
  font: 700 var(--fs-body)/1 var(--font-body); white-space: nowrap; cursor: pointer;
}
.btn-primary:hover  { filter: brightness(.94); }
.btn-primary:active { filter: brightness(.88); transform: translateY(1px); }
.btn-primary[disabled] { opacity: .45; cursor: not-allowed; filter: none; }
/* 🔴🔴【UAT第8便⑮⑯・椿さん 2026-09-17「タップしていること・登録中・アップロード中を示す」】
   通信中＝JS が `aria-busy="true"`（と `disabled`）を付ける。ボタンの文字を透明にして幅を保ち、
   真ん中で渦（うずまき・.bnto-load-spinner と同じ絵）を回す。終わったら JS が外す。
   ⚠️ 色は `--btn-on`（そのボタンの文字色）＝橙の地には墨、透明の地にも墨で見える。 */
button[aria-busy="true"], a[aria-busy="true"] { position: relative; color: transparent !important; pointer-events: none; }
button[aria-busy="true"][disabled] { opacity: 1; cursor: progress; }
button[aria-busy="true"]::after, a[aria-busy="true"]::after {
  content: ''; position: absolute; inset: 0; margin: auto; width: 22px; height: 22px;
  background-color: var(--btn-on, var(--ink, #1a1a1a));
  -webkit-mask: url("/icons/uzumaki-spinner.svg") center/contain no-repeat;
          mask: url("/icons/uzumaki-spinner.svg") center/contain no-repeat;
  animation: bnto-spin .8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  button[aria-busy="true"]::after, a[aria-busy="true"]::after { animation: none; }
}
@media (min-width: 900px) { .btn-primary { height: var(--tap); font-size: var(--fs-note); } }

/* --- 2 副ボタン（線だけ）------------------------------------------------- */
.btn-secondary {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: var(--tap); padding: 0 20px;
  border: 1.5px solid var(--hair); border-radius: var(--r-pill);
  background: transparent; color: var(--text);
  text-decoration: none;   /* 🔴【UAT第9便⑲】上の .btn-primary と同じ理由 */
  /* 【椿さん その23・案B】--fs-note（15px）に */
  font: 600 var(--fs-note)/1 var(--font-body); white-space: nowrap; cursor: pointer;
}
.btn-secondary:hover { background: var(--tint); }
.btn-secondary:active { background: var(--nb-press, var(--tint)); transform: translateY(1px); }   /* 🔴【UAT第8便⑮】押した合図 */

/* --- 3 文字だけ ----------------------------------------------------------- */
.btn-text {
  display: inline-flex; align-items: center; gap: 4px;
  height: var(--tap); padding: 0 8px;
  /* 🔴【WO-092・第9便・PM 実測 2026-09-21】椿さん「文字だけボタンのオレンジが明るい表示で薄い」。
     ■ 実測（WCAG の濃さの比）＝`--fire-dark`(#d95e00) は
       白(#fff) に対して 3.78 ／ ページの地(#f4f4f5) に対して 3.66 ／ 暗い表示の面(#26262A) に対して 3.98。
       **明るい表示でも暗い表示でも 4.5 に届いていなかった。**
     ■ 面のオレンジ（`--fire`・`--fire-dark`）は1ドットも変えない＝**文字のときだけ**別の札を使う。
       明るい表示 #b54a00 … 白 5.32 ／ 地 4.81　　暗い表示 #FF7601 … 面 5.63　いずれも 4.5 以上。
     ⚠️ 札の定義は public/styles/global.css の明るい側と暗い側の両方に置く（片方だけだと反転する）。 */
  border: 0; background: transparent; color: var(--fire-text, var(--fire-dark));
  text-decoration: none;   /* 🔴【UAT第9便⑲】上の .btn-primary と同じ理由 */
  /* 【椿さん その23・案B】--fs-note（15px）に */
  font: 600 var(--fs-note)/1 var(--font-body); white-space: nowrap; cursor: pointer;
}

/* --- 4 アイコンだけ（閉じる 戻る 共有 保存 検索 画像を添付 の6つのみ）----
   aria-label を必ず書く。それ以外の操作をアイコンにしない。 */
.btn-icon {
  display: grid; place-items: center;
  width: var(--tap); height: var(--tap);
  border: 0; border-radius: 50%;
  background: transparent; color: var(--text); cursor: pointer;
  text-decoration: none;   /* 🔴【UAT第9便⑲】上の .btn-primary と同じ理由 */
}
.btn-icon:hover { background: var(--tint); }
.btn-icon:active { background: var(--nb-press, var(--tint)); transform: translateY(1px); }   /* 🔴【UAT第8便⑮】押した合図 */
.btn-icon--bordered { border: 1.5px solid var(--hair); background: var(--canvas-card); }
.btn-icon svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
/* 🔴【パックからの逸脱・PM裁定 2026-09-10・実測で発見】上の行はこのファイル自身の中で
   矛盾している。`docs/handoff/icons.md:21` は同じパックの中で「`fill="none" stroke="currentColor"
   stroke-width:2` を付けると Material Symbols は消えます」と明記している。Material Symbols は
   線画ではなく塗り（`viewBox="0 -960 960 960"` の塗り潰しパス）で、960単位のパスを20pxへ
   縮小したときstroke-width 2は見た目0.04px＝実測で computed fill:none / stroke可視 を確認済み
   （壊れた記号に見える）。⇒ **`fill:none` の行は消さない**（`.btn-icon` には本物の線画アイコンも
   在り、そちらはこの指定が要る）。**Material Symbols だけを viewBox で狙い撃ちして上書きする**
   （意図を明記した`icons.md`側を優先し、矛盾する`primitives.css`側の逐語には従わない）。 */
.btn-icon svg[viewBox="0 -960 960 960"] { fill: currentColor; stroke: none; }

/* --- 5 取り消せない操作（必ず文字）--------------------------------------- */
.btn-danger {
  display: inline-flex; align-items: center;
  height: var(--tap); padding: 0 8px;
  border: 0; background: transparent; color: var(--danger);
  /* 【椿さん その23・案B】--fs-note（15px）に */
  font: 600 var(--fs-note)/1 var(--font-body); white-space: nowrap; cursor: pointer;
}
.btn-danger--outlined { padding: 0 18px; border: 1.5px solid var(--danger); border-radius: var(--r-pill); font-weight: 700; }

/* --- チップ（絞り込み・カテゴリ選び）------------------------------------- */
.chip {
  display: inline-flex; align-items: center;
  height: 36px; padding: 0 14px; flex: none;
  border: 1px solid var(--hair); border-radius: var(--r-pill);
  background: transparent; color: var(--text);
  /* 🔴【WO-092・第6便・椿さん 2026-09-21】13px → 6段の14px（「小さな補助ボタンの文字」）。 */
  font: 500 var(--fs-note)/1 var(--font-body); white-space: nowrap; cursor: pointer;
}
.chip[aria-pressed='true'] { background: var(--text); border-color: var(--text); color: var(--canvas); font-weight: 600; }

/* --- セグメント（自分／みんな・ライト／ダーク）---------------------------
   ⚠️ 帯から生えるタブにしない（浮いて見える）。ガラス地に白いピル。 */
.segmented { display: inline-flex; gap: 2px; padding: 3px; border-radius: var(--r-pill); background: var(--tint); }
/* 【椿さん その23・案B】--fs-note（15px）に */
.segmented > button {
  height: 36px; padding: 0 22px; flex: none;
  border: 0; border-radius: var(--r-pill);
  background: transparent; color: var(--text);
  font: 600 var(--fs-note)/1 var(--font-body); white-space: nowrap; cursor: pointer;
}
/* 🔴【WO-092・2026-09-19】フォーラムの「感想｜記事」はページの移動なので <a>。見た目の値は button と同じ。
   ⚠️ button の規則は1文字も変えない（サイトのほかの切り替えが使っているため）。 */
/* 【椿さん その23・案B】--fs-note（15px）に */
.segmented > a {
  height: 36px; padding: 0 22px; flex: none;
  border: 0; border-radius: var(--r-pill);
  background: transparent; color: var(--text);
  font: 600 var(--fs-note)/1 var(--font-body); white-space: nowrap; cursor: pointer;
  text-decoration: none;
  display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
}
/* 🔴【便C-3・椿さん指示・2026-09-12】「立体加工」（浮き影）は規定外なので外す。地と太字だけ残す。 */
.segmented > button[aria-selected='true'] { background: var(--canvas-card); font-weight: 700; }
.segmented > a[aria-current='page'] { background: var(--canvas-card); font-weight: 700; color: var(--text); }
/* 🔴🔴【椿さん裁定 A（決まり優先）・2026-09-12】押す的は --tap（44px）を下回らない。
   ⭐ ただし<b>見える大きさは変えない</b>＝「全て」の札で既に採った形と同じ
  （押せる範囲44px・見える札34px）。見た目はモックのまま、指だけ届くようにする。
   ⚠️ 当たり判定は<b>透明な面</b>なので、隣と重ならない大きさに留める
     （色の丸は36px＋間8px＝44pxで<u>ちょうど接する</u>・重ならない）。 */
.segmented > button,
.segmented > a,
.toggle { position: relative; }
.segmented > button::before,
.segmented > a::before,
.toggle::before {
  /* 押せる範囲の真ん中寄せも物理の left:50%（右から左で1枚分ずれないように・上の .sheet と同じ理由）。 */
  content: ''; position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: max(100%, var(--tap)); height: max(100%, var(--tap));
}

/* --- 平らな見出し（ヒーロー帯は作らない）---------------------------------
   全ページ共通。48px・下に罫1本。左に題、右にアイコン。 */
.page-head {
  display: flex; align-items: center; gap: 6px;
  width: 100%; max-width: var(--content-max); margin: 0 auto;
  height: 48px; padding: 0 8px 0 16px;
  border-bottom: 1px solid var(--hair);
  background: var(--glass-bg); backdrop-filter: var(--glass-blur);
  position: sticky; top: 0; z-index: 5;
}
/* 🔴【WO-092・第6便・椿さん 2026-09-21】「文字の大きさは規定に揃えて。」
   ⚠️ ここは第4版の絵の実測値（題17px・添え11px・ボタン13px）をそのまま写していた場所。
      絵より**あとに出たご指示**なので、6段（16／12）へ寄せる。差は1〜2px。
   ⚠️ この部品はフォーラムだけでなく、コレクション・マップなど**見出しの行を持つ面すべて**に出る。
   ⚠️ このファイルは文字サイズの門（`tests/font-scale.test.mjs`）の見る範囲の**外**にある＝
      だから規定の外のまま残っていた。門を広げるかは別途（広げると下流を数え直す必要がある）。 */
.page-head__title { font: 900 var(--fs-body)/1 var(--font-body); white-space: nowrap; }
.page-head__meta  { font: 600 var(--fs-mini)/1 var(--font-body); color: var(--text-dim); white-space: nowrap; }
.page-head__spacer { margin-inline-start: auto; }
/* PC の見出し行末に置く主・副ボタン。--tap（44px）を下回らない */
.page-head .btn-primary, .page-head .btn-secondary { height: var(--tap); font-size: var(--fs-mini); padding: 0 18px; }

/* --- 入力 ----------------------------------------------------------------- */
.field {
  width: 100%; height: var(--tap);
  padding: 0 12px;
  border: 1px solid var(--hair); border-radius: var(--r-input);
  background: var(--canvas-card); color: var(--text);
  font: 400 16px/1 var(--font-body);           /* 16px 未満にしない（iOS が拡大する） */
}
.field:focus-visible { outline: 2px solid var(--col-ac, var(--fire)); outline-offset: 1px; }
/* 🔴【WO-092・第6便・椿さん 2026-09-21】11px → 6段の12px（「ごく小さい印（ラベル）」）。 */
.field-label { display: block; font: 700 var(--fs-mini)/1.4 var(--font-body); color: var(--text-dim); margin-bottom: 4px; }

/* --- 個数のステッパー ----------------------------------------------------- */
.stepper { display: inline-flex; align-items: center; height: var(--tap); border: 1px solid var(--hair); border-radius: var(--r-input); background: var(--canvas-card); }
.stepper > button { width: var(--tap); height: var(--tap); border: 0; background: transparent; color: var(--text); font-size: 18px; cursor: pointer; }
/* 【椿さん その23・案B】--fs-body（17px）に */
.stepper > output { width: 36px; text-align: center; font: 700 var(--fs-body)/1 var(--font-body); }

/* --- つまみ --------------------------------------------------------------- */
.toggle { position: relative; width: 44px; height: 26px; flex: none; border: 0; border-radius: 13px; background: var(--hair); cursor: pointer; }
/* theme-invariant: always-dark surface — do not tokenise（PM裁定・2026-09-09＝ライト/ダークいずれの
   --hair トラックの上でも白いつまみは正しい。--canvas-card 等の役割札に置き換えるとダークで
   トラックと同化して見えなくなる。check-hardcoded-fff.mjs のベースライン内・扱いは docs/handoff/*
   と同じ「実装物のリテラル」として数える） */
.toggle::after { content: ''; position: absolute; top: 3px; inset-inline-start: 3px; width: 20px; height: 20px; border-radius: 50%; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.3); transition: inset-inline-start .16s ease; }
.toggle[aria-pressed='true'] { background: var(--col-ac, var(--fire)); }
.toggle[aria-pressed='true']::after { inset-inline-start: 21px; }

/* --- 下から出るシート ----------------------------------------------------- */
/* 🔴【パックからの逸脱・PM裁定 2026-09-10】重なりの順番だけ 40/41 → 400/401 へ上げる。
   ⚠️ **パックの数字が間違っているのではない。**パックは1枚で完結する見本として書かれていて、
   その中でいちばん高いのは 50（固定行の主ボタン）＝**40 で全部より上に出る**。
   ⇒ **このサイトに載せると足りない**＝サイトの上の帯 `.header`（global.css:3078）と
   下部ナビ（同 :4185）が **z-index:100**。40 のままだと、シートを開いても
   **オレンジの帯だけが暗くならずに手前に残る**（実測 2026-09-10・窓 -c8 が /collection/ の
   実物で発見）。⭐ **「暗くする覆い」が一部だけ効いていない状態は、覆いが無いより紛らわしい。**
   🔴 **上げ方の決め方**＝①サイトの chrome（100）より上 ②サイト全体の覆い
   （`.bt-share-overlay` 10000・`.bt-celebrate` 1200 等）より下＝**その間に置く**。
   ⚠️ `.lang-menu` の 200 は `.header`（z-index:100）が作る積み重ねの内側なので競合しない。
   ⚠️ **2つの差（backdrop < sheet）はパックのまま**＝覆いの上にシートが乗る関係は変えない。
   🔴🔴【重要・2026-09-10 に実測で判明】**この数字だけでは効かない場所がある。**
   `#mp2-shell` は `isolation:isolate` ＋ `z-index:1` を持つ（`MemberProfileShell.astro` ~13640・
   フッターの紋章が前に出る不具合を直したときの措置）。⇒ **その中に置かれたシートは、
   400 と書いても外の `#sm-header`（10）や `.bn-nav`（90）と比べてもらえない**——
   親が作った積み重ねの中で頭打ちになる。⭐ **積み重ねを作る親の内側では、子の z-index は
   外の世界に届かない**（`memory: zindex_loses_outside_its_box`）。
   🔴🔴【2026-09-12・設計し直し】**逃げ方は「運び出す」ではなく「箱ごと持ち上げる」。**
   ⚠️ 運び出す（portal）やり方は、**箱に残ったもの（写真の位置・サイズ調整）が
   運び出したシートより前に出られなくなる**＝実測で「調整パネルが開いているのに押せない」
   ＝画像が登録できない状態になった。⭐ **片方を助けて、もう片方を必ず壊す形だった。**
   ⇒ いまは `#mp2-shell:has(<覆いのある操作>:not([hidden]))` で**箱の z-index を 500 へ上げる**
     （MemberProfileShell.astro の #mp2-shell の直後）。箱の中は
     **覆い400 → シート401 → 写真の調整600** の1本の階段。
   ⭐ **新しいシート・オーバーレイを足すときは、運び出さずにこの階段へ並べる。**
   **40 のままか 400 かで見た目が変わらないときは、まず「箱が持ち上がっているか」を疑う**
   （中の数字を上げ続けても永久に直らない）。 */
.sheet-backdrop { position: fixed; inset: 0; z-index: 400; background: rgba(0,0,0,.38); }
.sheet {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 401;
  max-height: 86vh; overflow: auto;
  /* 🔴【WO-rv2-C・Step3・PM裁定2026-09-09・パックからの逸脱＝owner-decisions-notes.md 記録】
     下端の padding に safe-area を足す。この一式はスマホアプリ化前提（App Store/Google Play）
     なので safe-area-inset-bottom が0でない機種（ホームインジケータ付き iPhone 等）が主戦場。
     BottomNav.astro が既に同じ計算（bottom:calc(10px + env(...))）を持っている。 */
  padding: 10px 16px calc(20px + env(safe-area-inset-bottom, 0px));
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  background: var(--canvas-card); color: var(--text);
  box-shadow: var(--elev-sheet);
  display: flex; flex-direction: column; gap: 12px;
}
/* 🔴【便B・B-10(4)】上まで引き上げた「持ち上げた形」（モック collection-sheet-lifted.html＝
   上端10px）。既定の max-height:86vh のままだと、JS が高さを viewport-10px にしても
   ここで頭打ちになる＝この状態のときだけ上限を引き上げる（900px未満のみ・B-9のPC版は
   isDraggable が false なのでこのクラスは付かない）。 */
.sheet--lifted { max-height: calc(100dvh - 10px); }
/* 🔴🔴【便B・B-9・椿さんのご指摘2026-09-11】「PCは全幅モーダルじゃなくて良いし、まず下から
   出てくるんじゃなくて真ん中にオーバーレイで良い」。900px未満（スマホ・タブレット縦）は
   このファイルのままボトムシート＝上の .sheet 本体は1ドットも変えない。900px以上だけ
   中央のオーバーレイへ切り替える。⚠️ .sheet を使うのはコレクションの2つのシート
  （#mp2-col-form・#mp2-col-page-form）だけ（grep で数えて確認済み・他画面には影響しない）。 */
@media (min-width: 900px) {
  .sheet {
    /* 🔴【WO-092・2b】真ん中に置くのは物理の left:50%（左右対称なので向きに関係ない）。
       inset-inline-start だと右から左（アラビア語）で right:50% になり、translate(-50%) と重なって
       左へ1枚分ずれた（1440px で左 -120px・PM 実測 2026-09-19）。 */
    inset: auto;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: min(560px, 86%);
    max-height: 78vh;
    border-radius: var(--r-sheet);
    padding: 16px;
  }
  .sheet__grip { display: none; }
}
/* 🔴🔴【椿さん指摘・2026-09-13／PM 原因特定】**掴む面では、ブラウザの縦スクロールを止める。**
   ⚠️ これが無いと、指の縦移動をブラウザが先にスクロールとして食べてしまい、
      引き上げと取り合いになって**シートが小刻みに震えて見える。**
   ⭐ 同じ引き上げ機構を使っている里マップ側には元から付いていた（理由もコードに書いてある）。
      **こちらには1件も無かった。**
   ⚠️ 掴む面（取っ手・見出しの行）だけに付ける＝中身まで止めると、フォームが縦に読めなくなる。
   ⚠️ 900px 以上では引き上げないので付けない（下の @media で `.sheet__grip` を消している）。 */
@media (max-width: 899px) {
  .sheet__grip,
  .sheet__head { touch-action: none; }
}
.sheet__grip { width: 40px; height: 4px; flex: none; margin: 0 auto; border-radius: 2px; background: var(--hair); }
.sheet__head { display: flex; align-items: center; gap: 8px; flex: none; }
/* 🔴🔴【椿さん指摘「シートもなんかズレてますよ」の直し・PM実測 2026-09-12】
   .sheet は高さを固定した縦の flex。中身が入りきらないと <b>flex は既定で子を縮める</b>ので、
   52px 指定の名前欄が 26px で描かれる等、全部の欄がモックより薄くなっていた。
   ⇒ 題の行より下を丸ごとこの入れ物に入れ、<b>ここだけをスクロール</b>させる。
      これはモックと同じ作り（実測＝シート658px ＝ 題79px ＋ 中身579px）。
   ⚠️ 子に flex:none を効かせるのが要点。overflow だけ足しても縮みは止まらない。 */
.sheet__body {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 12px;
  /* 🔴🔴【椿さんご指摘・2026-09-22／PM 実測で原因特定】「文字を書き込もうとするとスマホだと枠がはみ出す」。
     ⚠️ **欄の幅の問題ではない**＝390/360/320/280px のどれでも、長い文字を入れてもはみ出しは 0px。
     🔴 出ていたのは**焦点の枠線**＝`.field:focus-visible` は太さ2px・ずらし1px なので、欄の**外側3px**に描く。
        ところがこの入れ物は左右の余白が 0 で、子は端から端まで伸びる（column flex の stretch）。
        ⇒ **枠線の置き場所が無い。**はみ出すか、`overflow-x: clip` を足した面では縁で切り落とされる。
     ⇒ 内側に3px 作り、同じだけ外へ広げる。**中身の幅は1pxも変わらない**（border-box の外が6px広がり、
        内側の余白が6px食うので相殺される）。
     🔴 ここに置く理由＝**下敷きを使う面すべてで同じ形**だから（聖地マップの記録・詳細、コラムの絞り込み、
        コレクションの品…）。1面だけ直すと、次に作る面でまた出る（椿さん＝「他と同じにしてくれれば良いのです」）。
     ⭐ 検査＝`tests/sheet-focus-ring.test.mjs`（足した日に壊して赤を確認ずみ）。 */
  padding-inline: 3px; margin-inline: -3px;
}
.sheet__body > * { flex: none; }
/* ⚠️ 上の1行は<b>直接の子</b>しか守らない。入れ子の中のボタン・欄は依然として縮む
   （実測 2026-09-12＝ページ設定の「この行を消す」が height:44px 指定なのに 28px で描画）。
   ⇒ 中の操作部品も名指しで潰さない。 */
.sheet__body button,
.sheet__body input,
.sheet__body select,
.sheet__body textarea,
.sheet__body .field,
.sheet__body .stepper,
.sheet__body .toggle { flex: none; }
.sheet__title { font: 900 18px/1 var(--font-body); white-space: nowrap; }
/* 🔴🔴【WO-145・item D・PM是正・2026-09-27】.sheet__note（旧「上の一覧にすぐ反映」）は
   コレクションの設定シートだけが使っていた（grep済み＝src/public のどこにも他の呼び出しが
   無い）。その注記自体をグループの並べ替えについて撤去した＝この汎用クラスも使い手が
   0件になったので、ここで一緒に片付ける（残すと「まだどこかで使っている」と誤解される）。 */
/* 【椿さん その23・案B】--fs-note（15px）に */
.sheet__head .btn-primary { margin-inline-start: auto; height: var(--tap); padding: 0 20px; font-size: var(--fs-note); }

/* --- PC の横並びナビ（左レールは廃止）------------------------------------
   スマホ・タブレット＝下部ナビ、PC＝この上バー。中身は --content-max で中央寄せ。 */
.top-nav { height: 60px; background: var(--glass-bg); backdrop-filter: var(--glass-blur); border-bottom: 1px solid var(--glass-edge); display: flex; justify-content: center; }
.top-nav__inner { width: 100%; max-width: var(--content-max); padding: 0 40px; display: flex; align-items: center; gap: 6px; }
.top-nav a { display: flex; align-items: center; gap: 7px; flex: none; height: 38px; padding: 0 14px; border-radius: var(--r-pill); color: var(--text); text-decoration: none; font: 500 13px/1 var(--font-body); white-space: nowrap; }
.top-nav a[aria-current='page'] { background: var(--fire); color: var(--text); font-weight: 700; }
.top-nav a[aria-current='page'] svg { stroke-width: 2.4; }
.top-nav svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
@media (max-width: 899px) { .top-nav { display: none; } }

/* --- 下部ナビ直上の固定アクション行 ---------------------------------------
   ⚠️ 下部ナビ（56px）＋下の余白（10px）＋間（10px）＝ bottom: 76px 固定。ずらさない。
   🔴🔴【WO-rv2-C・Step3・PM裁定2026-09-09・パックからの逸脱＝owner-decisions-notes.md 記録】
   パック文字通りの `bottom: 76px` には safe-area-inset-bottom が無い＝この一式はスマホアプリ化
   前提（App Store/Google Play・iPhone は PWA を包む）なので、ホームインジケータ付き iPhone
   （safe-area-inset-bottom が0でない）が主戦場。文字通りに実装すると「下部ナビの10px上」という
   パック自身の決まりがそのターゲット機種で破れる＝文字に従うと意図に反するので、
   BottomNav.astro 既存の bottom:calc(10px + env(...)) と同じ式に揃えた。 */
.action-row {
  position: fixed; inset-inline: 0; bottom: calc(76px + env(safe-area-inset-bottom, 0px)); z-index: 30;
  padding: 0 16px; display: flex; gap: 8px;
}
.action-row .btn-primary { flex: 1; box-shadow: var(--elev-float); }
.action-row .btn-secondary { flex: none; height: var(--tap-primary); background: var(--canvas-card); }
/* 下端のフェード。固定行の裏で本文が切れて見えるのを防ぐ */
.scroll-fade { position: absolute; inset-inline: 0; bottom: 0; height: 110px; pointer-events: none; background: linear-gradient(180deg, transparent, var(--canvas) 62%); }
@media (min-width: 900px) { .action-row, .scroll-fade { display: none; } }  /* PC は見出し行末に置く */

/* --- トースト（保存しました）--------------------------------------------- */
/* 🔴【WO-rv2-C・Step3・PM裁定2026-09-09・パックからの逸脱＝owner-decisions-notes.md 記録】
   .action-row と同じ理由で safe-area を足す（トーストは常に action-row の10px上＝
   76+48-2=86px相当の位置に浮く設計なので、同じ式で揃える）。 */
.toast {
  position: fixed; inset-inline: 16px; bottom: calc(86px + env(safe-area-inset-bottom, 0px)); z-index: 50;
  display: flex; justify-content: center; pointer-events: none;
}
/* theme-invariant: always-dark surface — do not tokenise（PM裁定・2026-09-09＝トーストは通知
   なので、ページのテーマに関わらず一貫した見た目を保つ意図の固定配色。--canvas-card/--text に
   置き換えるとダークテーマで背景が明るく反転し白文字が読めなくなる） */
/* 【椿さん その23・案B】--fs-note（15px）に */
.toast > span {
  display: inline-flex; align-items: center; gap: 8px;
  height: var(--tap); padding: 0 20px;
  border-radius: var(--r-pill);
  background: #1C1B19; color: #fff;
  font: 600 var(--fs-note)/1 var(--font-body); white-space: nowrap;
  box-shadow: 0 10px 28px rgba(0,0,0,.35);
}
.toast svg { width: 17px; height: 17px; fill: none; stroke: var(--col-ac, var(--fire)); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }

/* --- 注意の帯（上限・著作権）--------------------------------------------- */
/* 【椿さん その23・案B】--fs-mini（13px）に */
.notice {
  display: flex; align-items: flex-start; gap: 8px; flex: none;
  padding: 10px 16px;
  font: 400 var(--fs-mini)/1.6 var(--font-body);
}
.notice svg { width: 16px; height: 16px; flex: none; margin-top: 2px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }
.notice--danger  { background: var(--danger-bg); border-bottom: 1px solid var(--danger-edge); color: var(--danger); }
.notice--private { background: var(--tint); border-bottom: 1px solid var(--hair); color: var(--text); }

/* ══════════════════════════════════════════════════════════════════
   うずまきの待機表示（椿さんご指示 2026-09-16・UAT 第6便 ⑩）
   ── 使い方 ──
     <div class="bnto-load" role="status" aria-label="読み込み中…">
       <span class="bnto-load-spinner" aria-hidden="true"></span>
     </div>
   読み込みが終わったら、**この <div> ごと取り除く**（hidden で残さない＝椿さんご指示）。

   🔴 なぜ枠（border）で描かないか＝ビルドの門（scripts/check-old-style-decard.mjs）が
      「2px 以上の枠」の本数を数えており、足すと赤くなる。線画の型抜きなら枠を1本も増やさない。
   🔴 なぜ色を CSS 側に置くか＝色の正本は :root の --fire 1か所（AGENTS.md「地の色の正本は
      1か所だけ」と同じ理由）。絵の中に橙色を焼き込むと、色を変える人が2か所直すことになる。
   ⚠️ --fire が届かない場所でも消えないよう、控えの色を書いてある（変数が未定義だと
      background-color の宣言ごと無効になり、**印が見えなくなる**）。
   ⚠️ -webkit- 付きも必ず併記する（Safari / iOS）。
   ══════════════════════════════════════════════════════════════════ */
.bnto-load {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 96px;
  padding: var(--space-sm, 16px) 0;
}
/* 🔴【WO-131・2026-09-25・椿さん その13】画面の待ち表示は、うずまきから SHINOBILIA の手裏剣（ロゴの印）に替えた。
   逐語＝「せっかく手裏剣のロゴにしたので、シノビリアのロゴをくるくる回す形にしてもらっていいですか。刃先の方に回るようなイメージでリアリティは担保したいと思います」
   ⚠️ 絵はヘッダーの印と同じファイル（/icons/symbol.svg）＝新しい絵を描かない・ヘッダーで一度読めば控えから出る。
   ⚠️ 回る向きは時計回り（下の bnto-spin のまま）＝4枚の刃の先は、どれも根元から見て時計回りの側へ約21度傾いている
      （PM 実測 2026-09-25・刃の根元の中心と刃先の角度を比べた）⇒ 時計回りに回すと刃先が先頭になる。
   🔴 手裏剣にするのは画面の待ち表示だけ。会員のアイコンの丸（.av-wait-spin）とボタンの通信中（aria-busy）はうずまきのまま。
      逐語＝「待機中の画面上にはえー、待機中であるシュリケンを回してほしいと思うけど画像なんだろうアイコンアバターとか全てに手裏剣を回さなくていいという事を言いたい」 */
.bnto-load-spinner {
  width: 40px;
  height: 40px;
  flex: none;
  background-color: var(--fire, #FF7601);
  -webkit-mask: url("/icons/symbol.svg") center / contain no-repeat;
          mask: url("/icons/symbol.svg") center / contain no-repeat;
  animation: bnto-spin .8s linear infinite;
}
@keyframes bnto-spin { to { transform: rotate(360deg); } }
/* 🔴🔴【UAT第7便⑧・椿さんご決定 2026-09-16】**既にある骨組みの上に重ねる。**
   逐語＝「すでにあるちらつく骨組みありますが、そのレイヤー上に渦巻きが回るようにした方が良いのでは？」
   ⚠️ **骨組みは消さない**＝「これから何が出るか」の予告を失うと、情報が減る。
   ⚠️ `pointer-events: none`＝下にあるものの操作を邪魔しない。
   ⚠️ 置き場所（`.bnto-skel-host`）に `position: relative` が要る＝重ねる相手を決めるため。 */
.bnto-skel-host { position: relative; }
.bnto-load--over {
  position: absolute;
  inset: 0;
  min-height: 0;
  padding: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .bnto-load-spinner { animation: none; }
}

/* 🔴【WO-130・2026-09-25・椿さん その12】会員のアイコンの画像を待っているあいだの丸。
   逐語＝「待ってる間は待ってる間であることがわかるようにしてほしいかな。じゃないと、あれ、登録したのに外れてると思われてしまいそう。」
   ⇒ 名前の色と頭文字を消して、灰色の丸の中でうずまき（.bnto-load-spinner と同じ絵・同じ回り方）を回す。
   ⚠️ 頭文字は「アイコンを登録していない人」の見た目＝待っているあいだに出すと、登録した人が外れたように見える。
   ■ 使い方＝画面の JS が丸に .av-wait を付け、中に <span class="av-wait-spin" aria-hidden="true"></span> を1つ置く。
     画像が届いたら画像に替えて .av-wait を外す。読めなかったら .av-wait だけ外す（頭文字と名前の色に戻る）。
   ⚠️ うずまきは丸の真ん中に重ねる（position:absolute）＝丸の並べ方（grid／flex）に左右されない。
      丸の中に残る頭文字は、grid の丸では1段目に居座ってうずまきを下へ押す（ヘッダーの丸で 5.5px ずれた実測）。
   ⚠️ 頭文字の文字は透明に、ほかの中身（頭文字の箱・印の絵・読み込み中の画像）は隠す＝ホームの流れの頭文字は
      自分の文字の大きさと色を持つ箱に入っているので、丸の側の指定だけでは消えない。
   ⚠️ 地と文字の色は !important＝名前の色を style 属性で塗っている丸がある（ヘッダー・フォーラム・ホームの流れ）。
   ⚠️ 飾りの ::before／::after を使わない＝プロフィールの本人の丸は、カメラの印に両方を使っている。 */
.av-wait { position: relative; background: var(--nb-wait, #E4E4E7) !important; color: transparent !important; }
.av-wait > :not(.av-wait-spin) { visibility: hidden; }
.av-wait-spin { display: none; }
.av-wait > .av-wait-spin {
  display: block;
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(76%, max(22px, 40%));
  height: min(76%, max(22px, 40%));
  background-color: var(--fire, #FF7601);
  -webkit-mask: url("/icons/uzumaki-spinner.svg") center / contain no-repeat;
          mask: url("/icons/uzumaki-spinner.svg") center / contain no-repeat;
  animation: bnto-spin .8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .av-wait > .av-wait-spin { animation: none; }
}

/* --- 押す的を 44px にする（見た目は1ドットも変えない）------------------------
   🔴【2026-09-23・PM】椿さんの決まり＝**押す的は 44px**（逐語「44のまで良いです。」）。
   ⭐ **箱は太らせず、透明な四角を重ねて押せる範囲だけ広げる。**この形は既にこのリポジトリ
      の15か所で動いている（例＝`#mp2-shell .mp2-plus::after`）。
   ■ 測り方＝`node scripts/qa/qa-tap-target.mjs`。**この検査は擬似要素の大きさも読んで
     大きいほうを採る**ので、箱を太らせなくても通る。
   ■ ⚠️ **この検査は `setViewport` を持たない＝パソコンの大きさ（800×600）で測っている。**
     44px は**指で触るとき**の決まりなので、PM は同じ集め方でスマホ（390×844）でも測った
     （2026-09-23・パソコン115件／スマホ132件）。**下の一覧は両方の大きさで確かめたもの。**
   🔴 **ここに1行足すときは、必ず先に〈隣との隙間〉を測る。**
     重なると、押したつもりと違うほうが反応する（＝44px にした意味が消えるどころか悪くなる）。
     実測の例＝トップのいいね／共有は隣まで 22.4px あり、必要な 21.2px を満たしている。
   🔴 **わざと入れていないもの（消さない・足さない）**
     ・**里マップの建物（`.am-bldg` ＋ `--inert`）＝椿さんの決定で今回はこのまま**（2026-09-23）。
       実測＝パソコン12件・**スマホ27件**。建物どうしの隙間が **0px** で、スマホでは最小
       **11.3×21.1px**（爪の先ほど）。⇒ **透明な四角で広げると隣の建物が押せなくなる**ので、
       この手は使えない。44px にするには**絵ごと大きくする**しかなく、それは見た目のやり直し。
       ⭐ `/about/` はサイト紹介のページで毎日使う画面ではないため、**リリース後の宿題**にした。
       ⚠️ **「やり残し」ではなく「やらないと決めた」。**直すときは絵の作り直しから始める。
     ・地図の＋−（`.maplibregl-ctrl-zoom-in` / `-out`）＝**2026-09-23 に箱ごと 44px にした**
       （`src/components/SpotFlatMap.astro`）。上下に隙間なく並ぶので、ここの手（透明な四角）は
       使えなかった。⭐ **同じ地図の現在地ボタンが既に44pxだったので、それに合わせた。**
   ⚠️ `min-width` / `min-height: 100%` ＝**元より小さくしないため。**横に長いリンク
      （例＝おしらせの「忍界ニュースを見る」124px）を 44px 幅に縮めてしまわない。
   ⚠️ トップのタイムラインは**行全体が押せる面**なので、いいね／共有の的が 44px に広がると
      その分だけ「行を開く」より「いいね」が優先される。**これは意図した取り引き**＝22.8px の
      的を外して行が開くより良い。椿さんに実物で見ていただく。
   🔴 壊し確認＝この塊を消すと `qa-tap-target` の件数が 99 件ぶん増える。 */
.dl-act,
.chip,
.notice-link,
.colev-tab,
.an-all-link,
.nf-link,
.btn-text-link,
.action-btn--share,
.action-btn--ig,
#bt-select-toggle,
.news-chip-filter,
.spot-map-search-btn,
.spot-map-filter-open {
  position: relative;
}
.dl-act::after,
.chip::after,
.notice-link::after,
.colev-tab::after,
.an-all-link::after,
.nf-link::after,
.btn-text-link::after,
.action-btn--share::after,
.action-btn--ig::after,
#bt-select-toggle::after,
.news-chip-filter::after,
.spot-map-search-btn::after,
.spot-map-filter-open::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  min-width: 100%;
  min-height: 100%;
  transform: translate(-50%, -50%);
}
