/* File: src/static/css/app.css */
/*
  全ページ共通のスタイル（ADR-0008 / Workers Static Assets）。

  正はこのファイル。public/css/app.css は生成物であり Git 追跡外。
  src/static/ は scripts/build-client.mjs の copyStaticFiles() が
  public/ 直下へ再帰コピーする。esbuild は通らない。

  2026-08-16: Layout.tsx の STYLE 定数から移設（決定21）。
              CSP の style-src を 'self' で成立させるため。
  2026-08-16: 意味的トークンへ刷新し、data-theme による明示切替に対応（決定22）。

  2026-08-17: テーマをユーザーの保存情報にし、既定をライト固定にした（決定27）。

  【テーマの決まり方】
  <html> の data-theme 属性をサーバーが users.theme から出力する。
    属性なし        -> ライト（既定。未ログインは常にこれ）
    "dark"          -> ダーク
  OS の設定（prefers-color-scheme）には追従しない。
  JS は 1 行も使わない。属性は SSR 時点で確定しているため
  読み込み直後にテーマが切り替わる閃き（FOUC）が起きない。
*/

/* ============================================================
   1. トークン
   パレット（生の色）は 1 箇所。意味への割り当ては light / dark。

   既定（:root）がライトそのものであり、ダークは
   :root[data-theme="dark"] の 1 箇所だけ（決定27）。
   ⚠ 解消したのはダークの側だけである。ライトのトークンは
   ここと :root:has(#theme-light:checked)（§1 後半・決定28）の
   2 箇所にあり、必ず同時に編集する。決定22 の 2 箇所制約は
   ダークから消え、代償としてライトへ移った。
   ============================================================ */
:root {
    /* --- パレット --- */
    --p-white: #ffffff;
    --p-gray-50: #f2f6fb;
    --p-gray-100: #e8eef7;
    --p-gray-200: #dde5f0;
    --p-gray-300: #7c8ca5;
    --p-gray-500: #5b6b81;
    --p-gray-600: #4a5768;
    --p-gray-900: #16202e;

    --p-ink-900: #0b1220;
    --p-ink-800: #131c2b;
    --p-ink-700: #1b2537;
    --p-ink-600: #253044;
    --p-ink-500: #566a85;
    /* 2026-08-28: #6e7885 から明るくした。--fg-subtle は面の上で 3.858 しかなく
       AA を割っていた（日付・枠のホバー）。#8b95a3 で 5.70 になる。
       ⚠ ダーク専用である。ライトの --fg-subtle は --p-gray-500 が持つ。 */
    --p-ink-300: #8fa0b8;
    --p-ink-200: #a9b8cd;
    /* 2026-08-28: #e6e9ee から手本の値へ移した（ADR-0020）。
       ⚠ ダークの --fg 全般が変わる。本文・見出し・ヘッダーの文字・吹き出しの地。
         面（ink-800）との比は 14.19 から 14.63 へ上がる。下げる向きではない。
       ⚠ §10 / §16 / §18 の :visited は var() を使えず 16 進で同じ値を持つ。
         ここを変える日は 5 箇所も同時に変える（禁止 287）。2026-08-28 実測 5 箇所。
         片方だけ直すと画面は正常に見え、検査も緑のまま、訪問済みのリンクだけが
         旧い色で取り残される。 */
    --p-ink-050: #e6edf6;

    /* 2026-08-28: 青からインディゴへ移した（ADR-0020 決定2）。
       ⚠ 名は --p-blue-* のまま残す。参照は 9 箇所あり、振り直しの誤りは
         「画面は正常に見えるが 1 テーマだけ古い色」という形で現れる。
         名の嘘を承知で据え置く（決定8）。改名するなら単独の手で行う。
       ⚠ ライトとダークで別の値を採る。単一の値にすると、暗い側が
         --accent-fg との比で AA を割る（決定2）。
       ⚠ -050 と -900（--accent-subtle）の差し替えは任意ではない。
         .share__bookmark[aria-pressed="true"] は --accent を
         --accent-subtle の上に置く。ダークで -300 だけを変えると
         AA を割る（決定4）。余裕は 0.09 しかない。
         この 2 つのどちらかを触る日は必ず測る。
       ⚠ §10 の :visited は var() を使えず 16 進で同じ値を持つ。
         ここを変える日は §10 の 3 箇所も同時に変える（禁止 287）。 */
    --p-blue-600: #0f62c0;
    --p-blue-700: #0b4f9e;
    /* 2026-08-28: 塗り専用の中間色（ADR-0020 / C 案）。
       ⚠ ダークの --accent-solid だけが参照する。ライトは -600 のままである。
       ⚠ -600 はダークの地（ink-900）との比が 2.99 しかなく、塗りの輪郭が沈む。
         -500 なら 4.08 になり、白との比も 4.61 で AA を満たす。
       ⚠ 見本の塗りは -300（#6d7cff）である。白との比が 3.51 で AA を割るため
         採らなかった。鮮やかさを 1 段落として基準を取った差である。
       ⚠ ダークのホバーは -600 が持つ。塗りを明るくする向きのホバーは
         ダークでは成立しない（#6b78f5 で 3.73）。暗くする向きへ倒した。
       ⚠ この値を守る杭は無い（起票 24）。-600 へ戻しても白との比は 6.29 で
         AA を通り、563 件は緑のままである。塗りと地の比は無検査である。 */
    --p-blue-500: #2f74d0;
    --p-blue-050: #e8f2fe;
    --p-blue-300: #58a6ff;
    --p-blue-200: #85c0ff;
    --p-blue-900: #10233b;

    /* 2026-08-27: #c8484b から暗くした（手 G / 訂正 441）。
       --danger-subtle #fdeced の上の文字が 4.103 しかなく、
       .library-item__yes の塗り（白字）も 4.683 で AA の余裕が無かった。
       #b23a3e では最悪の組が 5.157 になる。
       ⚠ 全用途を contrast.test.ts の DANGER_PAIRS が 4 テーマで測る。
         値を戻した日は赤くなる。
       ⚠ §10 の :visited は var() を使えず 16 進で同じ値を持つ。
         ここを変える日は §10 の 2 箇所も同時に変える（禁止 287）。 */
    --p-red-600: #b23a3e;
    --p-red-050: #fdeced;
    --p-red-200: #f0c2c4;
    --p-red-300: #f08c8f;
    --p-red-900: #2a1618;
    --p-red-800: #4d2529;

    --p-green-600: #1f7a4d;
    --p-green-050: #eaf6ef;
    --p-green-200: #b9dfc9;
    --p-green-300: #6bcf9a;
    --p-green-900: #10231a;
    --p-green-800: #23452f;

    /* --- 寸法（テーマに依らない） --- */
    --sp-1: .25rem;
    --sp-2: .5rem;
    --sp-3: .75rem;
    --sp-4: 1rem;
    --sp-5: 1.5rem;
    --sp-6: 2rem;
    --sp-7: 3rem;
    --r-sm: 6px;
    --r-md: 10px;
    --r-lg: 14px;
    --r-pill: 999px;
    --measure: 48rem;
    /* 左右の余白（2026-08-28）。帯（header / footer）は画面いっぱいに広げ、
       中身はこの余白の内側へ置く。
       ⚠ 断点で値が変わる。40rem 未満は --sp-3 へ落とす。375px の可用幅
         351px は ADR-0018 決定3 の前提であり、これより狭めない。
       ⚠ 意味トークンではない。寸法であり全テーマに掛かる。 */
    --gutter: var(--sp-5);

    --font-ui: system-ui, -apple-system, "Hiragino Kaku Gothic ProN",
        "Hiragino Sans", "Yu Gothic UI", "Noto Sans JP", sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Consolas, monospace;

    /* 流体タイポ。375px で下限、960px 付近で上限に達する */
    --fs-base: clamp(1rem, .97rem + .18vw, 1.0625rem);
    --fs-sm: clamp(.85rem, .83rem + .1vw, .9rem);
    --fs-xs: .78rem;
    --fs-h1: clamp(1.5rem, 1.28rem + 1.05vw, 2rem);
    --fs-h2: clamp(1.25rem, 1.17rem + .38vw, 1.4rem);

    /* --- 意味（light: 既定。属性が無いときは必ずこれ） --- */
    color-scheme: light;
    /* ⚠ 名は明るさの順位ではない。--bg-subtle が最も明るい（白）。
       地（ページ全体）を gray-50、面（カード・入力欄・コード・th）を白にし、
       面が地の上に浮く形へ 2026-08-27 に転置した（T51i154）。
       参照側は 1 行も付け替えていない。参照は役（地か面か）の記録であり
       全テーマに掛かる。ダークも --bg < --bg-subtle で向きが揃う。 */
    --bg: var(--p-gray-50);
    --bg-subtle: var(--p-white);
    --bg-inset: var(--p-gray-100);
    --bg-hover: var(--p-gray-100);
    --fg: var(--p-gray-900);
    --fg-muted: var(--p-gray-600);
    --fg-subtle: var(--p-gray-500);
    --border: var(--p-gray-200);
    --border-strong: var(--p-gray-300);
    --accent: var(--p-blue-600);
    --accent-hover: var(--p-blue-700);
    --accent-fg: var(--p-white);
    /* 塗りの上に白を置くための面（2026-08-28 / ADR-0020）。
       ⚠ --accent と分ける。--accent は面の上で読む字の色であり、ダークでは
         明るい（#6d7cff）。白を乗せると 3.51 で AA を割る。かといって
         --accent を暗くすると、面（--bg-subtle）と押下の面（--accent-subtle）の
         上で字として読めなくなる。輝度の上限 0.183 と下限 0.243 が交差しており、
         1 つの値で両方を満たす解は無い（2026-08-28 実測）。
       ⚠ ライトの 2 ブロックだけが -600 / -700 である。ダークは -500 / -600 を
         採る（2026-08-28 / C 案）。塗りの上の白が読めるかは塗りの明るさだけで
         決まるが、塗りが地から浮くかは地の明暗に依る。ダークで -600 は
         地との比が 2.99 しかなく輪郭が沈む。
       ⚠ 名簿の検査は名前だけを見る。値が 3 ブロックで違っても赤くならない。
       ⚠ ここは 2 箇所ある（:root と :root:has(#theme-light:checked)）。
         必ず同時に編集する。
       ⚠ 意味トークンである。NON_SEMANTIC で除外しない。除外すると
         「1 ブロックだけに足した日に赤くする」名簿の目的が消える。 */
    --accent-solid: var(--p-blue-600);
    --accent-solid-hover: var(--p-blue-700);
    --accent-subtle: var(--p-blue-050);
    --danger: var(--p-red-600);
    --danger-subtle: var(--p-red-050);
    --danger-border: var(--p-red-200);
    --danger-fg: var(--p-white);
    --success: var(--p-green-600);
    --success-subtle: var(--p-green-050);
    --success-border: var(--p-green-200);
    /* 影の色を v2 の青みへ寄せた（手 D / ADR-0020）。
       ⚠ rgb 3 値だけを移し、透明度（.06 / .08）は動かさない。影は面の縁を
         示す非テキストであり、濃さを変えると枠線（--border）との強弱が入れ替わる。
       ⚠ ライトは 2 ブロックある（:root と :root:has(#theme-light:checked)）。
         合わせて 4 宣言であり、必ず同時に編集する（決定28 の 2 箇所制約）。
       ⚠ ダークは rgba(0, 0, 0, …) のままである。地が既に青みを持つため、
         影に色を入れると縁が紫に転ぶ（2026-08-28 実測）。 */
    --shadow-1: 0 1px 2px rgba(11, 18, 32, .06);
    --shadow-2: 0 6px 20px rgba(11, 18, 32, .08);
}

/* ダークの割り当て（決定27・28）。
   通常は users.theme='dark' のときサーバーが出力する
   <html data-theme="dark"> で有効になる。OS の設定は見ない。

   2 つ目のセレクタは設定画面のプレビュー（決定28）。
   ラジオを選んだ瞬間にこの画面だけ配色が変わる。
   :has() の引数に ID を含むため特異度は (1,2,0) となり、
   属性セレクタ (0,2,0) より確実に強い。記述順に依存しない。 */
:root[data-theme="dark"],
:root:has(#theme-dark:checked) {
    color-scheme: dark;
    --bg: var(--p-ink-900);
    --bg-subtle: var(--p-ink-800);
    --bg-inset: var(--p-ink-700);
    --bg-hover: var(--p-ink-700);
    --fg: var(--p-ink-050);
    --fg-muted: var(--p-ink-200);
    --fg-subtle: var(--p-ink-300);
    --border: var(--p-ink-600);
    --border-strong: var(--p-ink-500);
    --accent: var(--p-blue-300);
    --accent-hover: var(--p-blue-200);
    /* 2026-08-28: #0b1220 から白へ移した。塗りが --accent-solid（#5865f2）に
       なり、白との比は 4.61 である。旧値は明るい --accent（#6d7cff）の上で
       読ませるための色であり、塗りを暗くした今は役目が無い。 */
    --accent-fg: var(--p-white);
    /* ⚠ ダークだけ -500 / -600 を採る（2026-08-28 / ADR-0020 C 案）。
       ライトの 2 ブロックは -600 / -700 であり、3 ブロックで同値ではない。
       塗りの上の白が読めるかは塗りの明るさだけで決まるが、塗りが地から
       浮くかは地の明暗に依る。ダークは地が暗く、-600 では 2.99 で沈む。
       ⚠ 名簿の検査は名前だけを見る。値が 3 ブロックで違っても赤くならない。
       ⚠ ホバー（-600）では 2.99 に戻る。通常の 4.08 で輪郭は識別できるが、
         ホバー中は地に沈む。起票済み（--accent-subtle の 1.07 と同じ束）。 */
    --accent-solid: var(--p-blue-500);
    --accent-solid-hover: var(--p-blue-600);
    --accent-subtle: var(--p-blue-900);
    --danger: var(--p-red-300);
    --danger-subtle: var(--p-red-900);
    --danger-border: var(--p-red-800);
    /* 旧値 #0b1220 から移した（手 A / ADR-0020）。
       ⚠ v2 で --p-ink-900 が #0b1220 になり、旧値と一致する。地の色と
         「赤の塗りの上で読む字」が同一値になると、片方を動かした日に
         もう片方が黙って付いてくる。値を分けて依存を切る。
       ⚠ var() を使わない。ここは塗りの上の字であり、地の記録ではない。
         意味が一致しないものを借りない（.library-item__yes と同じ理由）。
       ⚠ --danger（#f08c8f）の上で 6.68 である。contrast.test.ts の
         DANGER_PAIRS が 4 テーマで測る。明るくする向きへ戻すと赤くなる。 */
    --danger-fg: #10233b;
    --success: var(--p-green-300);
    --success-subtle: var(--p-green-900);
    --success-border: var(--p-green-800);
    --shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
    --shadow-2: 0 6px 20px rgba(0, 0, 0, .45);
}

/* ライトのプレビュー（決定28）。
   保存済みがダークのとき <html data-theme="dark"> が付いたままなので、
   ライトを選んだ瞬間に打ち消す必要がある。

   ⚠ ライトのトークンはこことセクション 1 冒頭の :root の 2 箇所にある。
     片方だけ直すと「保存済みライト」と「ライトをプレビュー中」で
     配色がズレる。必ず両方を同時に編集する。
     決定27 でダークの 2 箇所制約を解消した代償として、
     今度はライトが 2 箇所になった（決定28 で受け入れたトレードオフ）。 */
:root:has(#theme-light:checked) {
    color-scheme: light;
    --bg: var(--p-gray-50);
    --bg-subtle: var(--p-white);
    --bg-inset: var(--p-gray-100);
    --bg-hover: var(--p-gray-100);
    --fg: var(--p-gray-900);
    --fg-muted: var(--p-gray-600);
    --fg-subtle: var(--p-gray-500);
    --border: var(--p-gray-200);
    --border-strong: var(--p-gray-300);
    --accent: var(--p-blue-600);
    --accent-hover: var(--p-blue-700);
    --accent-fg: var(--p-white);
    /* 塗りの上に白を置くための面（2026-08-28 / ADR-0020）。
       ⚠ --accent と分ける。--accent は面の上で読む字の色であり、ダークでは
         明るい（#6d7cff）。白を乗せると 3.51 で AA を割る。かといって
         --accent を暗くすると、面（--bg-subtle）と押下の面（--accent-subtle）の
         上で字として読めなくなる。輝度の上限 0.183 と下限 0.243 が交差しており、
         1 つの値で両方を満たす解は無い（2026-08-28 実測）。
       ⚠ ライトの 2 ブロックだけが -600 / -700 である。ダークは -500 / -600 を
         採る（2026-08-28 / C 案）。塗りの上の白が読めるかは塗りの明るさだけで
         決まるが、塗りが地から浮くかは地の明暗に依る。ダークで -600 は
         地との比が 2.99 しかなく輪郭が沈む。
       ⚠ 名簿の検査は名前だけを見る。値が 3 ブロックで違っても赤くならない。
       ⚠ ここは 2 箇所ある（:root と :root:has(#theme-light:checked)）。
         必ず同時に編集する。
       ⚠ 意味トークンである。NON_SEMANTIC で除外しない。除外すると
         「1 ブロックだけに足した日に赤くする」名簿の目的が消える。 */
    --accent-solid: var(--p-blue-600);
    --accent-solid-hover: var(--p-blue-700);
    --accent-subtle: var(--p-blue-050);
    --danger: var(--p-red-600);
    --danger-subtle: var(--p-red-050);
    --danger-border: var(--p-red-200);
    --danger-fg: var(--p-white);
    --success: var(--p-green-600);
    --success-subtle: var(--p-green-050);
    --success-border: var(--p-green-200);
    --shadow-1: 0 1px 2px rgba(11, 18, 32, .06);
    --shadow-2: 0 6px 20px rgba(11, 18, 32, .08);
}

/* ============================================================
   2. 基盤
   ============================================================ */
* {
    box-sizing: border-box;
}

body {
    /* 2026-08-28: 幅の制限を body から外した。
       ⚠ body に max-width があると header は親の幅を超えられない。
         position: sticky でも変わらない。帯が本文と同じ幅で止まり、
         左右に地色が残る形になっていた。
       幅を持つのは main と .nav であり、body は器を持たない。 */
    margin: 0;
    padding: 0;
    font-family: var(--font-ui);
    font-size: var(--fs-base);
    line-height: 1.7;
    color: var(--fg);
    background: var(--bg);
    -webkit-text-size-adjust: 100%;
}

/* 本文の器（2026-08-28）。
   読める幅は body ではなくここが持つ。帯は全幅のまま、中身だけが中央に寄る。
   ⚠ 器を新しい要素で足さない。main は Layout.tsx に既にあり、
     div を挟むと同じ役の要素が 2 枚重なる。 */
main {
    display: block;
    max-width: var(--measure);
    margin-inline: auto;
    padding-inline: var(--gutter);
    /* 面の上端に本文が接するのを防ぐ（2026-09-05 / ADR-0025 決定1）。
       ⚠ 錨へ着地したときの余白ではない。あちらは html の
         scroll-padding-block-start が持つ（§3）。2 つの目的を混ぜない。 */
    padding-block-start: var(--sp-5);
    padding-block-end: var(--sp-6);
    /* 本文を面へ載せる（ADR-0025 決定1）。
       ⚠ 角丸と枠を付けない。幅いっぱいの面の上下だけが丸くなり、帯と食い違う。
       ⚠ 器を新しい要素で足さない。ここが唯一の器である（下の注記と同じ）。
       ⚠ 地は深くしていない。面と地の差は 1.085 である（決定2）。地が見えるのは
         --gutter の外側だけであり、40rem 未満ではほとんど見えない。
       ⚠ 面の上の部品を塗りで分けない。識別は縁（--border-strong）が担う
         （決定3）。contrast.test.ts の「面の上の部品」が 4 テーマで測る。
       ⚠ スクロール中は header（同じ面）と --border の 1 本で接する（既知の制限）。 */
    background: var(--bg-subtle);
}

/* 一覧の画面では器を地へ戻す（2026-09-05 / ADR-0025 決定11）。
   面は 1 枚の紙に 1 つである。一覧はカードが既に面を持っており、器にも面を
   敷くと紙の上に同じ紙が乗る（面の上で 1.00）。手本（Qiita）も一覧の地は
   暗いままで、カードだけが浮く。
   ⚠ 器を増やさない。今ある main を :has() で分岐させる（決定1 の禁則）。
   ⚠ 子結合子を書かない。contrast.test.ts の正規化は選択子の中の `>` の
     前後に空白を開き、:has() の中も例外にしない。css.test.ts は括弧を退避
     するため化けない。2 つの検査で照合の形が食い違う（2026-09-05 実測）。
   ⚠ (0,1,1) で main (0,0,1) に勝つ。記述順に依存しない。
   ⚠ 上端の余白も戻す。カードが自身の margin を持ち、器の padding と二重になる。
   ⚠ .cards.profile > article は地と同色へ戻る。押せないカードを浮かせない
     という元の設計意図であり、打ち消しの見直しは要らない。 */
main:has(.cards) {
    padding-block-start: 0;
    background: var(--bg);
}

/* フォーカスリングを全体で統一する（Linear / GitHub の作法）。
   :focus-visible なのでマウス操作では出ず、キーボード操作でのみ現れる。
   個別要素で outline を上書きしないこと。 */
:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--r-sm);
}

::selection {
    background: color-mix(in srgb, var(--accent) 28%, transparent);
}

@media (prefers-reduced-motion: reduce) {
    * {
        transition: none !important;
        animation: none !important;
    }
}

/* ============================================================
   3. タイポグラフィ
   ============================================================ */
h1 {
    font-size: var(--fs-h1);
    line-height: 1.35;
    letter-spacing: -.01em;
    margin-block: 0 var(--sp-4);
}

h2 {
    font-size: var(--fs-h2);
    line-height: 1.4;
    letter-spacing: -.005em;
}

time {
    font-size: var(--fs-sm);
    color: var(--fg-subtle);
}

.hint,
.field .hint {
    font-size: var(--fs-xs);
    color: var(--fg-muted);
    margin: var(--sp-2) 0 0;
}

/* 同意の表示（ADR-0011 決定1）。
   ⚠ .hint（--fg-muted）と同じ扱いにしない。
   法的な合意の根拠となる文であり、補足と同格に見せるべきではない。
   本文と同じ色にし、サイズだけ小さくする。 */
.consent {
    margin: var(--sp-4) 0 0;
    font-size: var(--fs-sm);
    color: var(--fg);
}

/* 錨へ着地したとき sticky ヘッダーが見出しと通知を覆うのを防ぐ（2026-09-05）。
   複数コメントのある記事で削除すると #comments-heading へ着地し、
   通知の上半分が帯の下に入って読めなかった（実測）。
   ⚠ ヘッダー高のトークンを :root へ置かない。意味トークンの名簿
     （contrast.test.ts / 24 件）に混ざる。掛かる先は html だけであり
     テーマごとの値も持たない（§10 の --link-underline と同型）。
   ⚠ --nav-ctl-h は .nav の内側で定義されており html からは解決しない。
     操作部 2.25rem + padding-block .75rem × 2 + 境界 1px で組み、
     余白として .75rem を足す。§4 の値を動かす日はここも動かす。
   ⚠ 狭幅で .nav が flex-wrap で 2 段になる場合は覆いが残る。
     断点を足さない（css.test.ts が 40rem / 60rem で固定）。 */
html {
    scroll-padding-block-start: calc(2.25rem + .75rem * 2 + .75rem + 1px);
}

/* ============================================================
   4. ヘッダー / ナビ / フッター
   ============================================================ */
header {
    position: sticky;
    /* 気に入らなければこの 1 行を消せば元に戻る */
    top: 0;
    z-index: 10;
    margin-bottom: var(--sp-5);
    border-bottom: 1px solid var(--border);
    background: var(--bg-subtle);
    background: color-mix(in srgb, var(--bg-subtle) 88%, transparent);
    backdrop-filter: saturate(1.6) blur(10px);
}

.nav {
    /* 【ヘッダーの操作部の高さの素】T51i153
       ⚠ 値をここ以外に書かない。a.nav-cta（投稿する）と検索の窓・ボタンは
         別の要素であり、宣言を各所に書くと必ず食い違う。D97（§18 の共有
         ボタン）で同じ事故を起こしており、これが 3 度目である。
       ⚠ button は line-height を継承しない。既定の normal が入るため、
         実数で与えないと a との差がそのまま高さの差になる。 */
    --nav-ctl-h: 2.25rem;
    --nav-ctl-pad-block: .35em;
    --nav-ctl-border: 1px;
    --nav-ctl-line: 1.5;

    /* ⚠ 畳んだ板（§22）の包含ブロックはここである（2026-08-28）。
       header に沿わせると、帯が全幅になったぶん板が画面の右端まで飛ぶ。
       ⚠ padding-block も header から移す。器の下端と帯の下端が一致しないと、
         inset-block-start: 100% の板が境界へ食い込む。 */
    position: relative;
    padding-block: var(--sp-3);
    padding-inline: var(--gutter);
    max-width: var(--measure);
    margin-inline: auto;

    display: flex;
    align-items: center;
    gap: var(--sp-3);
    flex-wrap: wrap;
}

.nav .spacer {
    flex: 1;
}

/* --- ブランド ----------------------------------------------------------- */
.brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    font-weight: 700;
    font-size: 1.05rem;
    text-decoration: none;
    letter-spacing: -.01em;
}

/* 遮断の面の名乗り（ADR-0037 / 2026-09-11 / 第 1 回）。
   ⚠ 図と名を横へ並べるだけの規則である。面も断点も下線も持たない。
   ⚠ 値を新しく作らない。間隔は --sp-2（.brand と同じ素）。 */
.maint-brand {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
}

/* ⚠ 葉の色は 1 規則が持つ。遮断の面をこの選択子へ並べ、16 進を 3 箇所目へ
   書き写さない（ADR-0037 決定5 改訂の続き / 2026-09-11）。
   ⚠ 面は骨格を借りないが、様式は同じ源の 1 本を読む。ゆえに規則を共有できる。 */
.brand .icon,
.maint-brand .icon {
    /* 葉を萌黄で固定する（手 C / ADR-0020）。
       ⚠ --accent を参照しない。ブランドの葉はテーマで色が変わる部品ではない。
         参照したままだと、アクセントを青から動かした日に標識まで別の色になる。
       ⚠ 変数を :root へ置かない。意味トークンの名簿（contrast.test.ts）に
         混ざる。掛かる先はこの 1 規則だけであり、テーマごとの値も持たない
         （§10 の --link-underline と同型）。
       ⚠ 4 テーマで 1 つの値が両方の地で見えること。図は非テキストであり
         3:1 で足りる。白 3.12 / #0b1220 5.21（2026-08-29 実測）。
       ⚠ 明るくすると白地で 3:1 を割る。暗くするとダークの地に沈む。
         上下の余裕は狭い。動かす日は必ず両テーマで測る。
       ⚠ ここは 2 箇所ある（app.css と src/static/favicon.svg）。favicon は独立
         した文書であり currentColor が解決しない。値を変える日は両方を変える。
         */
    --logo-moegi: #6aa121;

    /* 文字より少し大きく。1em だと視覚的に小さく見える */
    font-size: 1.15em;
    color: var(--logo-moegi);
}

/* --- アイコンの基本 ------------------------------------------------------ */
/* ⚠ vertical-align を指定しないと、テキストとの並びで下にずれる。
   inline-flex の親の中でも baseline の影響を受ける（ADR-0012 決定1） */
.icon {
    flex: 0 0 auto;
    vertical-align: -0.125em;
}

/* --- 主要動作（投稿する） ------------------------------------------------- */
/* ⚠ 他のリンクと同じ見た目だと、5 つの中から選べない。
   アクセント塗りで 1 つだけ明確に上位に置く（決定2） */
.nav-cta {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: .45em .9em;
    font-size: var(--fs-sm);
    font-weight: 600;
    border-radius: var(--r-sm);
    text-decoration: none;
    background: var(--accent-solid);
    box-shadow: var(--shadow-1);
    transition: background-color .12s ease;
}

.nav-cta:hover {
    background: var(--accent-solid-hover);
}

/* --- 移動系のリンク ------------------------------------------------------ */
.nav-link {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    font-size: var(--fs-sm);
    text-decoration: none;
}

/* --- アイコンのみのリンク（ログアウト） ------------------------------------ */
/* ⚠ 文字を出さない。誤クリックの影響が大きい操作を、
   他のリンクと同じ見た目で並べない（ADR-0004 §7-10） */
.nav-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2rem;
    block-size: 2rem;
    border-radius: var(--r-sm);
    font-size: 1.05rem;
    text-decoration: none;
    transition: background-color .12s ease, color .12s ease;
}

/* ⚠ 赤にしない。ログアウト専用だった頃の名残である（ADR-0018 決定3）。
   今この class を持つのは検索とメニューの summary の 2 つで、
   どちらも破壊的な操作ではない */
.nav-icon:hover {
    background: var(--bg-hover);
}

/* --- 区切りとユーザー名 --------------------------------------------------- */
/* 「移動できる場所」と「自分の状態」を分ける */
.nav-sep {
    inline-size: 1px;
    block-size: 1.2em;
    background: var(--border);
}

/* D43-A により、username が渡された場合のみ a になる（決定2 を改訂）。
   下線は出さず span 版と見た目を揃える。表示名は省略記号で切る（ADR-0008 決定26） */
.nav .user {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    font-size: var(--fs-sm);
    color: var(--fg-subtle);
    text-decoration: none;
}

.nav .user__name {
    display: inline-block;
    max-inline-size: 10ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: bottom;
}

.nav form {
    margin: 0;
}

/* --- フッター ------------------------------------------------------------ */
footer {
    margin-top: var(--sp-7);
    padding-block: var(--sp-4);
    padding-inline: var(--gutter);
    max-width: var(--measure);
    margin-inline: auto;
    border-top: 1px solid var(--border);
    font-size: var(--fs-sm);
    color: var(--fg-subtle);
}

.footer-about {
    margin: 0 0 var(--sp-3);
}

/* ⚠ 中黒（・）で区切らない。リンク文字と同じ大きさで並び読点と紛れる。
   縦罫と余白で分ける（決定3） */
.footer-links {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-4);
}

/* 別のタブで開くリンクの形（2026-09-06）。フッターと本文で同じ見せ方にする。
   同意画面（TermsAgreePage）の 2 本が、印だけ持って間隔を持たなかった。
   ⚠ .body li a と広く取らない。内部リンクまで inline-flex になる。
   ⚠ 属性で狙う。class を新設すると、付け忘れた箇所だけが揃わなくなる。
   ⚠ 2 本に分けて書かない。片方だけ直す事故が起きる（D97 と同型）。
   ⚠ Icon 側に余白を持たせる案は採らない。呼び出しは 28 箇所あり、
     .brand や .share__* など図が単独の箇所に不要な余白が付く。
     それらは既に gap で解いており、二重になる。 */
.footer-links a,
.body a[target="_blank"] {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    /* タップ領域。決定26 と同じ基準に寄せる */
    min-height: 2.2rem;
}

.footer-links a+a {
    position: relative;
}

.footer-links a+a::before {
    content: "";
    position: absolute;
    inset-inline-start: calc(var(--sp-4) / -2);
    inline-size: 1px;
    block-size: 1em;
    background: var(--border);
}

/* ⚠ 上の規則と対である。並べ方だけ及ぼして印の大きさを置き去りにすると、
     同じ印が場所によって濃さと大きさを変える。片方だけ直さない。 */
.footer-links .icon,
.body a[target="_blank"] .icon {
    font-size: .9em;
    opacity: .7;
}

/* ============================================================
   5. 一覧 / メタ / バッジ
   一覧はカードにする（2026-08-22）。⚠ .cards の直下に限る。
   記事詳細も article を使っており、素のセレクタを触ると本文全体が枠に入る。
   ============================================================ */
article {
    padding-block: var(--sp-4);
}

article+article {
    border-top: 1px solid var(--border);
}

.meta {
    display: flex;
    gap: var(--sp-3);
    align-items: baseline;
    flex-wrap: wrap;
    color: var(--fg-muted);
    font-size: var(--fs-sm);
}

/* .meta 内に段落を置く場合（編集画面の公開URL・最終更新）は積む。
   flex-wrap が効いているので flex-basis 100% だけで改行できる */
.meta p {
    flex: 0 0 100%;
    margin: var(--sp-1) 0;
}

/* 著者名と @username（ADR-0010 決定2）。
   表示名は UNIQUE でないため、識別のために handle を併記する。
   ⚠ 折り返しても「名前」と「@handle」が分断されないよう
   1 つの span でまとめている。 */
.meta .author {
    overflow-wrap: anywhere;
}

/* handle は識別の補助であり主役ではない。表示名より弱くする。
   ⚠ かっこは CSS の ::before / ::after で付けない。
   選択してコピーしたときに含まれず、読み上げの扱いもブラウザ依存になる。
   区切りは意味の一部なのでビュー側のテキストに置く（ADR-0010 決定6）。

   ⚠ --fg-subtle は本文（--fg）より薄い。
   ライト・ダークの両方でコントラストは確保されている（ADR-0008 決定22 のトークン）。

   自動生成の username は 17 文字あるため、375px では折り返す。
   .author が overflow-wrap: anywhere を持つため画面外へはみ出さない。 */
.meta .author__handle {
    font-size: var(--fs-xs);
    color: var(--fg-subtle);
    /* かっこの内側で改行されないようにする。
       「ゆうき (@user_」で切れると handle として読めない */
    white-space: nowrap;
}

/* 投稿日時・更新日時（ADR-0012 決定7）。
   アイコンと日付を 1 組にして、折り返しで分断されないようにする */
.meta-date {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    white-space: nowrap;
}

.meta-date .icon {
    opacity: .7;
}

.meta code {
    font-family: var(--font-mono);
    font-size: .85em;
    padding: .1em .4em;
    border-radius: 4px;
    border: 1px solid var(--border);
    background: var(--bg-subtle);
    overflow-wrap: anywhere;
}

.badge {
    font-size: var(--fs-xs);
    padding: .15em .6em;
    border-radius: var(--r-pill);
    border: 1px solid var(--border-strong);
    background: var(--bg-subtle);
    color: var(--fg-muted);
}

/* ページ送りの帯（2026-09-08 / ADR-0035 決定14）。
   ⚠ 新しいクラス名を作らない。状態は aria-current / aria-hidden の属性選択子で
      受ける（.share__like[aria-pressed] と同じ作法）。件数の行は .hint を借りる。
   ⚠ 断点を増やさない。下のタップ領域は §11 と同じ 40rem を使う。 */
.pager {
    /* ⚠ gap を --sp-4 から落とした。番号が 5 個並ぶため、前へ／次へと同じ
       間隔では数字どうしが離れ、1 つの列として読めない。 */
    margin-top: var(--sp-6);
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2);
}

/* 番号・前へ・次へ・省略を同じ箱で組む。
   ⚠ a と span を 1 本で書く。押せる番号（a）と現在位置（span）で寸法が
      違うと、現在位置だけが列の中で上下にずれる。
   ⚠ 塗りを持たせない。識別は縁が担う（ADR-0025 決定3）。 */
.pager a,
.pager span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-inline-size: 2.25rem;
    min-block-size: 2.25rem;
    padding-inline: var(--sp-2);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    font-size: var(--fs-sm);
    text-decoration: none;
}

.pager a:hover {
    background: var(--bg-hover);
    border-color: var(--fg-subtle);
}

/* 押せない前へ／次へ。⚠ 描画ごと消さない。列の両端が現れたり消えたり
   すると、番号の横位置がページごとにずれる。 */
.pager span {
    color: var(--fg-subtle);
}

/* 省略の三点。⚠ 箱を持たせない。押せる番号と同寸だと押せる印に見える。
   読み上げからは Pager.tsx の aria-hidden が外す。
   ⚠ (0,2,0) で上の (0,1,1) に勝つ。記述順に依存しない。 */
.pager [aria-hidden="true"] {
    min-inline-size: auto;
    padding-inline: 0;
    border-color: transparent;
}

/* 現在位置。
   ⚠ 新しい色を作らない。--accent の 3 点組は .theme-option:has(input:checked)
      と .share__bookmark[aria-pressed="true"] が既に使う形であり、
      contrast.test.ts が 4 テーマで測る組でもある。
   ⚠ 色だけに頼らない。太字を併せる。状態そのものは aria-current が持つ。
   ⚠ (0,2,0) で .pager span (0,1,1) に勝つ。記述順に依存しない。 */
.pager [aria-current="page"] {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-subtle);
    font-weight: 600;
}

/* タップ領域（ADR-0035 決定15）。⚠ §11 の断点を増やさない。同じ 40rem を使う。
   ⚠ 省略の三点は上の (0,2,0) が min-inline-size: auto を持つため広がらない。
      メディア問い合わせは特異度を上げない。 */
@media (max-width: 40rem) {

    .pager a,
    .pager span {
        min-inline-size: 2.75rem;
        min-block-size: 2.75rem;
    }
}

/* ============================================================
   6. フォーム / ボタン / 通知
   ============================================================ */
.form-page {
    max-width: 24rem;
    margin-inline: auto;
}

.field {
    margin-block: var(--sp-4);
}

/* display:block だとラベル幅が .field いっぱいに広がり、文字の右の空白も
   クリック領域になる。本文ラベルには CodeMirror へフォーカスを移す
   ハンドラが付いているため、何もない場所を押してキャレットが現れる
   （2026-08-14 実測）。inline-block なら幅が文字幅と一致する。
   後続の input / textarea は width:100% を持つので改行は保たれる。

   ⚠ 【本文と同じ大きさにする】ADR-0010 決定7
   以前は --fs-sm（本文より小さい）+ --fg-muted（薄い）で、
   .hint と同じ色・近い大きさだった。
   その結果「見出し」と「補足」が同格に見え、
   入力欄と説明文のほうが視覚的に強かった。
   フォームの構造を示す要素なので、本文と同じ大きさで --fg にする。 */
.field label {
    display: inline-block;
    font-size: var(--fs-base);
    font-weight: 600;
    margin-bottom: var(--sp-2);
    color: var(--fg);
}

.field input:not([type="checkbox"]),
.field textarea {
    width: 100%;
    padding: .65em .75em;
    font: inherit;
    color: inherit;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    background: var(--bg-subtle);
    transition: border-color .12s ease, box-shadow .12s ease;
}

.field input:hover,
.field textarea:hover {
    border-color: var(--fg-subtle);
}

.field input:focus,
.field textarea:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
}

.field textarea {
    font-family: var(--font-mono);
    line-height: 1.6;
    resize: vertical;
}

/* チェックボックスの行（ADR-0016 決定3 / 2026-08-24）。
   ⚠ .field label は見出し用の規則で inline-block と margin-bottom を持つ。
     input を内包する行に当てると、箱と文字が上下に分かれて離れる。
   ⚠ 箱の大きさは基底の側で除外した。width:100% と padding が当たると
     箱が押し出され、40rem 未満では行いっぱいに伸びる（2026-08-24 実測）。
   既存の 6 個のラベルには触れない。継承で字の大きさと太さは揃う。 */
.field label.check {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    margin-bottom: 0;
    /* タップ領域（決定22）。40rem 未満でも縮めない */
    min-height: 2.75rem;
    cursor: pointer;
}

.field label.check input {
    flex: none;
    margin: 0;
    accent-color: var(--accent);
}

/* ボタンの基本形。primary はアクセント塗り、secondary は輪郭のみ。
   「下書き保存」と「公開する」が同じ見た目だった問題を解消する。 */
.form-page button[type="submit"],
.actions button,
.comment-delete {
    padding: .7em 1.1em;
    font: inherit;
    font-weight: 600;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    cursor: pointer;
    background: var(--accent-solid);
    color: var(--accent-fg);
    box-shadow: var(--shadow-1);
    transition: background-color .12s ease, border-color .12s ease;
}

.form-page button[type="submit"] {
    width: 100%;
}

.form-page button[type="submit"]:hover,
.actions button:hover {
    background: var(--accent-solid-hover);
}

.actions {
    display: flex;
    gap: var(--sp-3);
    margin-top: var(--sp-5);
}

.actions button {
    flex: 1;
}

/* ⚠ color を必ず戻す。.actions button の color は var(--accent-fg) で、
   アクセント塗りの上に乗る前提の値（light=白 / dark=ほぼ黒）。
   継承したままだと secondary はライトで白on白、ダークで黒on黒になり
   ラベルが読めない（2026-08-16 実測）。
   背景は --bg ではなく --bg-subtle。--bg はページ背景と同色で
   輪郭以外の手がかりが無く、押せる領域だと分からない。 */
.actions button.secondary,
.actions a.secondary,
.comment-delete {
    font-weight: 500;
    color: var(--fg);
    background: var(--bg-subtle);
    border-color: var(--border-strong);
    box-shadow: none;
}

.actions button.secondary:hover,
.actions a.secondary:hover,
.comment-delete:hover {
    color: var(--fg);
    background: var(--bg-hover);
    border-color: var(--fg-subtle);
}

/* 削除確認のキャンセルは遷移するだけなので a。見た目はボタンに揃える。
   文字色は :visited 対策のため §10 で指定している */
.actions a.secondary {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: .7em 1.1em;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    text-decoration: none;
}

/* コメントの削除ボタンの寸法（2026-09-05）。共有ボタン（§18）と同寸にする。
   ⚠ §18 の共通形へ選択子を足せない。css.test.ts が あの規則の選択子を
     4 本で toEqual 固定しており、プロパティも SHARE_COMMON で員数固定である。
   ⚠ --share-pad-block / --share-line は §18 の規則自身が持つため
     外からは解決しない（--nav-ctl-* と同型）。値を写すしかない。
   ⚠ 数値を変える日は §18 と両方を変える。D97 と同じ事故が再発する。
   ⚠ min-height は写さない。あれは図だけのボタンのための下限であり、
     文字を持つこのボタンは行ボックスで同じ高さに達する
     （1em × 1.7 + .45em × 2 + 1px × 2）。 */
.comment-delete {
    padding: .45em .9em;
    font-size: var(--fs-sm);
    line-height: 1.7;
    /* 2026-09-09（ADR-0021 刻み 2-1）。button から a へ替えた。
       ⚠ §10 の a は --link-underline を持ち、a:hover が underline へ替える。
         (0,1,0) のこの規則が a (0,0,1) に勝ち、ホバーでも線を出さない。
       ⚠ .actions a.secondary へ宣言を足さない（§23 の注記）。あちらは寸法と
         枠と :visited 対策が絡む共通形であり、css.test.ts が形を見る。
       ⚠ 12 本目である。css.test.ts が員数を数え、所在も対で持つ。 */
    text-decoration: none;
}

.alert,
.notice,
.notice--removed,
.notice--maint {
    padding: .75em 1em;
    border-radius: var(--r-sm);
    border: 1px solid;
    border-left-width: 4px;
    font-size: var(--fs-sm);
}

.alert {
    border-color: var(--danger-border);
    background: var(--danger-subtle);
    color: var(--fg);
}

.notice {
    border-color: var(--success-border);
    background: var(--success-subtle);
    color: var(--fg);
}

/* コメントの削除の完了（2026-09-05）。
   ⚠ .notice を借りない。緑は祝福であり、削除は祝う操作ではない
     （PostFormPage の絵文字の作法と同じ／ADR-0012 決定4）。
   ⚠ .alert を借りない。commentError を .alert へ直した日に
     成功と失敗が同じ姿になる。
   ⚠ 新しい色を作らない。地と枠と本文色の 3 点で組む（§18・§21 と同じ原則）。
   ⚠ --danger-subtle を地にしない。上の文字が 4.103 しかなく、
     DANGER_PAIRS へ用途を足す必要が出る（§2 の注記）。
     縁だけに使えば文字と地の組は --fg / --bg-subtle のままである。 */
.notice--removed {
    border-color: var(--danger-border);
    background: var(--bg-subtle);
    color: var(--fg);
}

/* 予告の帯（2026-09-11 / ADR-0037 決定1 / 層 A / 第 2 回）。
   ⚠ 新しい色を作らない。地と縁と本文色の 3 点で組む（.notice--removed と同じ原則）。
   ⚠ .notice を借りない。緑は完了の色であり、予告は完了ではない。
   ⚠ .alert を借りない。赤は失敗の色であり、予告は失敗ではない。
   ⚠ --bg-subtle を地にしない。面そのものの色であり、面の上では帯が消える。
     contrast.test.ts の名簿にも触れる。
   ⚠ --accent-subtle を地にする。押下の面として既に使われている値である。
     ⚠ この値はコントラストの検査の名簿から漏れている（起票済み）。この帯の組は
        contrast.test.ts の専用の it が 4 テーマで測る。
   ⚠ 余白を自分で持つ。main の先頭へ差し込むため、既定のままでは一覧の画面
     （器の上余白が 0）でヘッダーの帯に接する。
   ⚠ 下線を宣言しない。押しどころを持たない（css.test.ts の 13 本を動かさない）。 */
.notice--maint {
    margin-block: var(--sp-4);
    border-color: var(--accent);
    background: var(--accent-subtle);
    color: var(--fg);
}

/* 投稿管理の編集・削除リンク。
   【2026-09-06】下の余白を落とした。
   ⚠ この節はカードの末尾に来るため、下マージンが .cards > article の
     padding-bottom（16px）へ二重に足される。トップの一覧は末尾が .meta で
     あり、.meta は margin / border / padding のすべてが 0 である
     （2026-09-06 実測）。同じ形のカードなのに下端が 16px と 40px に
     分かれていた。
   ⚠ 上の余白（--sp-2）は残す。.meta との間隔であり別の目的である。
   ⚠ .cards の側で `> *:last-child` として打ち消さない。検索の抜粋
     （.search-snippet は下に --sp-2 を持つ）と自己紹介のカードにも及ぶ。
     あちらの末尾の子は未実測である。
   ⚠ この class を持つのは MyPostsPage の 1 か所だけである
     （2026-09-06 実測。src 側 1 件 / CSS の他 6 件は :visited の色）。 */
.item-actions {
    display: flex;
    gap: var(--sp-4);
    font-size: var(--fs-sm);
    margin: var(--sp-2) 0 0;
}

.item-actions a {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    min-height: 2.2rem;
}

/* 主要動作をページ内にも置く場合の余白 */
.page-actions {
    margin: var(--sp-4) 0 var(--sp-6);
}

/* 編集画面末尾の削除導線。保存操作と視覚的に分離する（GitHub の Danger zone） */
.danger-zone {
    margin-top: var(--sp-7);
    padding: var(--sp-4);
    border: 1px solid var(--danger-border);
    border-radius: var(--r-md);
    background: var(--danger-subtle);
    font-size: var(--fs-sm);
}

.danger-zone a {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
}

/* ログアウトは POST が必要なので form で囲む。見た目はリンクに寄せる */
.linklike {
    padding: 0;
    border: none;
    background: none;
    color: inherit;
    font: inherit;
    font-size: var(--fs-sm);
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
    opacity: .75;
}

.linklike:hover {
    opacity: 1;
}

/* ============================================================
   7. 設定画面（/me/settings）
   ラジオを選択カードに見せる。:has(:checked) で JS なしに選択状態を出す。
   :has 非対応環境では枠が付かないだけで、ラジオとして機能する。

   2026-08-28: .card を削除した。全ビューで未使用の孤児である。
   ⚠ ADR-0020 の「設定のカードを角丸 14px へ」はこの孤児に当たっており、
     画面に一度も出ていない。設定画面で実際にカードに見えるのは
     下の .theme-option であり、角丸は --r-md（10px）である。
   ============================================================ */

.theme-options {
    display: grid;
    /* 【幅が足りれば横に並べる（2026-08-24）】
       auto-fit は入るだけ列を作り、入らなければ 1 列へ戻る。
       断点を足さずに済み、テーマが 3 つに増えても崩れない。
       ⚠ 下限はカード内の説明文が収まる幅にする。これより小さくすると
         360px 級の画面でも 2 列になり、名前と説明が細かく折り返す。 */
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: var(--sp-2);
    margin: 0 0 var(--sp-5);
    padding: 0;
    border: none;
}

/* ⚠ .field label と同じ見た目にする（決定7）。
   どちらもフォームの項目名であり、要素が違うだけで意味は同じ。
   片方だけ変えると揃わない（実際、以前は偶然近い見た目だった）。 */
.theme-options legend {
    padding: 0;
    font-size: var(--fs-base);
    font-weight: 600;
    color: var(--fg);
    margin-bottom: var(--sp-2);
}

.theme-option {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: start;
    gap: var(--sp-1) var(--sp-3);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    background: var(--bg);
    cursor: pointer;
    transition: border-color .12s ease, background-color .12s ease;
}

.theme-option:hover {
    background: var(--bg-hover);
}

.theme-option input {
    margin: .35rem 0 0;
    accent-color: var(--accent);
}

/* 図と名前を 1 行に並べる（2026-08-30 / #2）。
   ⚠ 間隔を空白に依存させない。JSX は要素の間の改行を落とすため、
     文字列の空白で空けると書式を整えた日に詰まる。gap だけが持ち主である。
   ⚠ 図に色を与えない。currentColor のままなら --fg を継ぎ、意味トークンが
     増えない（contrast.test.ts の名簿 24 件に触らない）。
     --fg-subtle は使わない。面の上で 3.351 しかなく別主題である。
   ⚠ 列を増やさない。.theme-option の grid-template-columns: auto 1fr と
     .theme-option__desc の grid-column: 2 は対であり、3 列へ移す日は必ず
     同時に直す（css.test.ts が対で固定する）。 */
.theme-option__name {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    font-weight: 600;
}

.theme-option__desc {
    grid-column: 2;
    font-size: var(--fs-sm);
    color: var(--fg-muted);
}

.theme-option:has(input:checked) {
    border-color: var(--accent);
    background: var(--accent-subtle);
}

/* ============================================================
   8. エディタ（ADR-0006 / ADR-0008）
   ============================================================ */
/* タブ。JS が有効なときだけ表示される */
.tabs {
    display: flex;
    gap: var(--sp-1);
    padding: var(--sp-1);
    border-radius: var(--r-md);
    background: var(--bg-inset);
    width: fit-content;
}

.tabs .tab {
    padding: .4em 1em;
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 500;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    background: transparent;
    color: var(--fg-muted);
    cursor: pointer;
    transition: background-color .12s ease, color .12s ease;
}

.tabs .tab:hover {
    color: var(--fg);
}

.tabs .tab.active {
    background: var(--bg);
    color: var(--fg);
    font-weight: 600;
    box-shadow: var(--shadow-1);
}

/* ツールバー（ADR-0006 段階5） */
.toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-1);
    margin: var(--sp-3) 0 var(--sp-2);
}

.toolbar .tool {
    min-width: 2.3rem;
    padding: .4em .6em;
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 500;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--bg);
    color: var(--fg-muted);
    cursor: pointer;
    transition: background-color .12s ease, color .12s ease, border-color .12s ease;
}

.toolbar .tool:hover {
    background: var(--bg-hover);
    color: var(--fg);
    border-color: var(--border-strong);
}

/* hidden 属性を効かせる（2026-08-14 / ADR-0008 決定15）。
   著者スタイルの display:flex が UA スタイルの [hidden]{display:none} に
   勝つため、属性セレクタで特異度を (0,2,0) に上げて打ち消す。
   !important は使わない。記述順にも依存しない。

   この規則が無いと JS 無効環境でタブとツールバーが表示され、
   押しても何も起きないボタンが並ぶ（2026-08-11 から潜在していた）。 */
.tabs[hidden],
.toolbar[hidden] {
    display: none;
}

.preview-pane {
    min-height: 20rem;
    padding: .2em 1em 1em;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    /* 編集中のプレビューは、公開時の記事本文と同じ面に載せる
       （2026-09-05 / ADR-0025 決定4）。
       ⚠ 旧い理由「記事本文はページ背景の上に載る」は決定1 で偽になった。
         偽になった理由を残さない。
       ⚠ 旧い理由の後段「白にすると中のコード部分（白）と同色になり浮きが消える」は
         公開時の本文でも同じであり、プレビュー固有の事情ではなくなった。
       ⚠ contrast.test.ts の KEPT_SURFACES から FIELD_SURFACES へ移した。
         検査は消していない。4 つとも白にした日に赤くする目的は生きている。 */
    background: var(--bg-subtle);
}

/* CodeMirror（ADR-0008）。既定でスタイルを持たず高さも枠線も無いため、
   .field textarea の値を写して JS の有無で外観が変わらないようにする。
   .cm-editor が外枠、.cm-scroller がスクロール領域、.cm-content が本文。 */
/* 【高さは .cm-content に持たせる】.cm-scroller に min-height を与えると
   テキスト分しか高さを持たない .cm-content との差が
   「クリックしても編集領域に入らない空白」になる（決定19）。
   overflow:hidden も指定しない（内部のレイアウト計算に干渉する）。 */
.field .cm-editor {
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    background: var(--bg-subtle);
    max-height: 70vh;
    transition: border-color .12s ease, box-shadow .12s ease;
}

.field .cm-editor.cm-focused {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
}

.field .cm-scroller {
    font-family: var(--font-mono);
    line-height: 1.6;
}

/* rows={20} 相当の高さ。padding を含む領域すべてが編集可能になり、
   どこをクリックしてもキャレットが入る */
.field .cm-content {
    min-height: 24rem;
    padding: .65em .75em;
    caret-color: var(--fg);
    /* 折り返しは EditorView.lineWrapping が担う。white-space は触らない */
}

.field .cm-cursor,
.field .cm-dropCursor {
    border-left-color: var(--fg);
}

.field .cm-selectionBackground,
.field .cm-editor ::selection {
    background: color-mix(in srgb, var(--accent) 26%, transparent);
}

.field .cm-editor.cm-focused .cm-selectionBackground {
    background: color-mix(in srgb, var(--accent) 34%, transparent);
}

.field .cm-gutters {
    background: var(--bg-subtle);
    border-right: 1px solid var(--border);
    color: var(--fg-subtle);
}

.field .cm-activeLine {
    background: color-mix(in srgb, var(--fg) 4%, transparent);
}

/* --- メディアライブラリ（ADR-0009 / 決定30）--------------------------------
   ⚠ dialog はブラウザ既定で background: Canvas / color: CanvasText を持つ。
     data-theme="dark" のときも中身が白くなるため、意味的トークンで
     明示的に上書きする（決定22 の方針）。 */
dialog {
    max-inline-size: min(56rem, 92vw);
    max-block-size: 82vh;
    padding: var(--sp-5);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-lg);
    background: var(--bg);
    color: var(--fg);
    box-shadow: var(--shadow-2);
}

dialog::backdrop {
    background: rgb(0 0 0 / .55);
}

/* モーダルが開いている間は背景をスクロールさせない（決定31）。
   showModal は背景を inert にしてクリックとフォーカスを遮断するが、
   Chromium はスクロールを止めない（2026-08-18 実測）。
   背景が動くと、閉じた後に編集していた位置が画面外へ移る。

   【JS で body にクラスを付ける方式は取らない】
   閉じる経路が Esc・閉じるボタン・挿入時の close() の 3 つあり、
   外し忘れると全ページがスクロール不能になる。
   :has() なら [open] が消えた瞬間に自動で戻る（決定28 と同じ考え方）。

   このサイトの dialog は showModal でしか開かないため、
   [open] の判定だけで modal かどうかを区別する必要がない。 */
html:has(dialog[open]) {
    overflow: hidden;
}

.library-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-4);
}

.library-head h2 {
    margin: 0;
}

/* 挿入サイズの選択（決定15）。
   .theme-options（設定画面）はカードに説明文を持つ別物であり流用しない。
   375px では折り返す */
.library-size {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2) var(--sp-4);
    margin: var(--sp-3) 0 0;
    padding: 0;
    border: none;
}

.library-size legend {
    padding: 0;
    /* ⚠ ここは大きくしない。モーダル内の横並びであり、
       ラベル群と同じ行に収める必要がある（決定7 の例外）。 */
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--fg-muted);
}

.library-size label {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    font-size: var(--fs-sm);
    /* タップ領域。決定22 の 44px には満たないが、
       ラジオは隣接して並ぶため過剰に広げるとかえって押し間違える */
    min-height: 2.2rem;
    cursor: pointer;
}

.library-size input {
    accent-color: var(--accent);
}

.library-body {
    /* dialog 自体の高さを超えた分をここでスクロールさせる。
       head と hint は固定したまま一覧だけが動く */
    max-block-size: 60vh;
    overflow-y: auto;
    margin-top: var(--sp-4);
    /* 一覧の末尾まで送っても背景へスクロールが連鎖しない。
       §2-1 で背景は止まっているが、こちらは
       「モーダル内で送ったのに外が動く」を別途塞ぐ */
    overscroll-behavior: contain;
}

/* auto-fill にすると、画面幅に応じて列数が変わる。
   ブレークポイントを増やさずに 375px から広い画面まで成立する（決定22） */
.library-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
    gap: var(--sp-3);
}

.library-item__meta {
    font-size: var(--fs-xs);
    color: var(--fg-muted);
    overflow-wrap: anywhere;
}

.library-item__badge {
    position: absolute;
    inset-block-start: var(--sp-2);
    inset-inline-end: var(--sp-2);
    background: var(--bg);
}

/* カードは div、挿入部分だけが button（決定14）。
   button のネストを避けるため。 */
.library-item {
    position: relative;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    background: var(--bg-subtle);
    transition: border-color .12s ease;
}

.library-item:hover {
    border-color: var(--accent);
}

.library-item__pick {
    display: grid;
    gap: var(--sp-1);
    inline-size: 100%;
    padding: var(--sp-2);
    font: inherit;
    text-align: start;
    border: none;
    border-radius: var(--r-md);
    background: none;
    color: var(--fg);
    cursor: pointer;
}

.library-item__pick:hover {
    background: var(--bg-hover);
}

/* ⚠ 縮小版を持たず原寸を表示している。
   ダウンロード量は減らないため img に loading="lazy" を付けている
   （editor.ts 側）。枚数が増えたら Transformations を検討する。 */
.library-item__pick img {
    inline-size: 100%;
    aspect-ratio: 4 / 3;
    object-fit: contain;
    border-radius: var(--r-sm);
    background: var(--bg-inset);
}

/* 削除の 1 段目。バッジの下に重ねる */
.library-item__delete {
    position: absolute;
    inset-block-start: var(--sp-2);
    inset-inline-start: var(--sp-2);
    padding: .2em .6em;
    font: inherit;
    font-size: var(--fs-xs);
    border: 1px solid var(--danger-border);
    border-radius: var(--r-sm);
    background: var(--bg);
    color: var(--danger);
    cursor: pointer;
    opacity: 0;
    transition: opacity .12s ease;
}

/* 常時表示すると視線が削除に引かれる。
   ⚠ :focus-visible を含めないとキーボードで到達できない */
.library-item:hover .library-item__delete,
.library-item__delete:focus-visible {
    opacity: 1;
}

/* 削除の 2 段目。カード全体を覆い、誤クリックで挿入されないようにする */
.library-item__confirm {
    position: absolute;
    inset: 0;
    display: grid;
    align-content: center;
    justify-items: center;
    gap: var(--sp-2);
    padding: var(--sp-3);
    border-radius: var(--r-md);
    background: var(--danger-subtle);
    font-size: var(--fs-sm);
    text-align: center;
}

/* hidden 属性を効かせる（ADR-0008 決定15 と同型）。
   ⚠ 著者スタイルの display:grid が UA の [hidden]{display:none} と
   同じ特異度 (0,1,0) で、後勝ちで無視される。
   属性セレクタで (0,2,0) に上げて打ち消す。
   !important は使わない。記述順にも依存しない。

   この規則が無いと、開いた瞬間に全カードが確認表示になり、
   画像が 1 枚も見えなくなる（2026-08-19 実測）。 */
.library-item__confirm[hidden] {
    display: none;
}

/* 削除の実行ボタン。
   ⚠ 文字色に --bg を使わない。T51i154 で地を白から gray-50 へ転置した際、
     この 1 行だけが「役の記録」ではなく「赤の塗りの上で読める色」の意図で
     書かれており、比が 4.683 から 4.369 へ落ちた（訂正 442 / 禁止 288）。
   ⚠ --accent-fg も流用しない。値は同じ白だが、accent の文字色が
     danger の塗りを規定する形になる。意味が一致しないものを借りない。 */
.library-item__yes {
    padding: .4em 1em;
    font: inherit;
    font-size: var(--fs-sm);
    font-weight: 600;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    background: var(--danger);
    color: var(--danger-fg);
    cursor: pointer;
}

.library-item__yes:disabled {
    opacity: .6;
    cursor: default;
}

.library-item__error {
    display: block;
    padding: 0 var(--sp-2) var(--sp-2);
    font-size: var(--fs-xs);
    color: var(--danger);
}

/* ============================================================
   9. 記事本文（body_html の描画領域）
   スタイルは .body 配下に閉じ込め、サイト自身の UI に影響させない。
   ============================================================ */
.body {
    overflow-wrap: anywhere;
    line-height: 1.85;
}

/* 記事本文のリンクは常時下線にする（2026-08-28 / ADR-0020）。
   ⚠ §10 の a はホバーの間だけ線を出す。本文へは掛けない。--accent と --fg の
     色差はダーク 2.97 / ライト 2.69 であり、非テキストの 3:1 にも届かない。
     線を外すと、周りの文字と色でしか区別できず、その色差が足りない
     （WCAG 1.4.1 / 手法 G183）。
   ⚠ (0,1,1) で a (0,0,1) に勝つ。ホバー時も a:hover が変数を underline へ
     替えるだけなので、値は変わらず線は出たままである。
   ⚠ この規則が無い間はブラウザ既定の下線に依っていた（訂正 371）。 */
.body a {
    text-decoration-line: underline;
}

.body h1,
.body h2,
.body h3,
.body h4 {
    margin: 1.7em 0 .6em;
    line-height: 1.35;
    letter-spacing: -.01em;
}

/* marked が 1 段下げるため h2 が最上位。グローバルの h2 が .body 内にも
   効いて h2 と h3 の差が消えていたため、ここで階層を作る（2026-08-11） */
.body h1 {
    font-size: 1.7rem;
    padding-bottom: .25em;
    border-bottom: 1px solid var(--border);
}

.body h2 {
    font-size: 1.45rem;
    padding-bottom: .25em;
    border-bottom: 1px solid var(--border);
}

.body h3 {
    font-size: 1.2rem;
}

.body h4 {
    font-size: 1.05rem;
}

.body h5,
.body h6 {
    font-size: 1rem;
    color: var(--fg-muted);
}

/* 連続する見出しの間隔を詰める */
.body h2+h3,
.body h3+h4 {
    margin-top: .8em;
}

.body p,
.body ul,
.body ol,
.body table,
.body pre {
    margin: 1em 0;
}

.body li+li {
    margin-top: .3em;
}

.body code {
    font-family: var(--font-mono);
    font-size: .9em;
    padding: .15em .4em;
    border-radius: 4px;
    border: 1px solid var(--border);
    background: var(--bg-subtle);
}

.body pre {
    padding: 1em 1.1em;
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    overflow-x: auto;
    background: var(--bg-subtle);
    line-height: 1.6;
}

/* コードブロックは pre 側の下地を使うため二重の背景を打ち消す */
.body pre code {
    padding: 0;
    border: none;
    border-radius: 0;
    background: none;
    font-size: .88em;
}

.body blockquote {
    margin: 1em 0;
    padding: .3em 0 .3em 1.1em;
    border-left: 3px solid var(--border-strong);
    color: var(--fg-muted);
}

.body table {
    border-collapse: collapse;
    display: block;
    overflow-x: auto;
    font-size: var(--fs-sm);
}

.body th,
.body td {
    border: 1px solid var(--border);
    padding: .5em .85em;
}

.body th {
    background: var(--bg-subtle);
    font-weight: 600;
}

.body img {
    max-width: 100%;
    height: auto;
    border-radius: var(--r-md);
}

.body hr {
    border: none;
    border-top: 1px solid var(--border);
    margin: 2.4em 0;
}

/* body_html 未生成の旧記事のフォールバック */
.body-raw {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* 共有ボタン（ADR-0012 決定9）。
   記事末尾の .post-actions が持つ帯の中に置く（T51i121 / T51i123b）。
   ⚠ 記事の一部ではないため .body の外にあり、
   本文のスタイル（行間 1.85 等）を受けない */
.share {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-3);
}

.share__label {
    font-size: var(--fs-sm);
    color: var(--fg-muted);
}

/* 共有ボタン 2 種の共通形（D97 / 2026-08-23）。
   a と button で別々に書いていたため、宣言が食い違って高さがずれた。
   実測（Computed / Layout）:
     a.share__x       content 75.882 x 24.467  height 38.7604  line-height 24.48px
     button.share__copy content 96.174 x 18.665  height 32.9583  line-height normal
   padding と border は同値であり、差は line-height だけである。
   ⚠ 同じ見た目のものを 2 箇所に書かない。差は必ず再発する。

   ⚠ ナビの nav-cta ほど強くしない。
   主要動作は「読むこと」であり、共有は副次的である。
   文字色は :visited 対策のため §10 で指定している */
.share__x,
.share__copy,
.share__like,
.share__bookmark {
    /* 【高さの素】T51i123c
       下の min-height はこの 3 つだけを参照して高さを組む。
       ⚠ 値をここ以外に書かない。padding や border を変えたときに
         min-height だけ古い値で残るのを構造で防ぐ。 */
    --share-border: 1px;
    --share-pad-block: .45em;
    --share-line: 1.7;

    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--share-pad-block) .9em;
    font-family: inherit;
    font-size: var(--fs-sm);
    font-weight: 500;
    /* ⚠ button は line-height を継承しない。既定の normal が入る。
       inherit ではなく実数で書く。.share は .body の外にあり、
       継承元が本文とは限らないためである */
    line-height: var(--share-line);
    /* 【図だけのボタンも同じ高さにする】T51i123c
       inline-flex の子はブロックになるため、この line-height は
       コンテナ自身の行ボックスを作らない。テキストを持つ 3 種は
       子の span が行ボックスを立てるが、しおりだけの保存は
       図の 1em しか持たず、その差だけ低くなっていた。
       ⚠ 高さを内容に依存させない。下限をここで与える。
       ⚠ 兄弟に合わせて伸ばす形（align-items: stretch）は採らない。
         著者が件数を隠すと .reactions の中が保存だけになり、また縮む。
       ⚠ 1em は font-size（--fs-sm）に対する値であり、padding と同じ基準になる。 */
    min-height: calc(1em * var(--share-line) + var(--share-pad-block) * 2 + var(--share-border) * 2);
    border: var(--share-border) solid var(--border-strong);
    border-radius: var(--r-sm);
    background: var(--bg-subtle);
    box-sizing: border-box;
    transition: background-color .12s ease, border-color .12s ease;
}

.share__x {
    text-decoration: none;
}

/* ⚠ 色は共通側に置かない。share__x は §10 が :visited まで固定し、
   share__copy は継承で足りる。共通化すると :visited 対策が壊れる */
.share__copy {
    color: inherit;
    cursor: pointer;
}

.share__x:hover,
.share__copy:hover {
    background: var(--bg-hover);
    border-color: var(--fg-subtle);
}

/* コピーの結果を色で伝える（D92 / D93 / D95）。
   ⚠ 新しい色を作らない。--success と --danger の 3 点組は
      §6 のフォーム通知が既に使う形であり、ダークの定義も揃っている。
   ⚠ JS は属性を付け外しするだけにする。style を直に書くと
      style-src に unsafe-inline が要る（ADR-0008 決定25 / D86） */
.share__copy[data-share-state="done"] {
    color: var(--success);
    border-color: var(--success-border);
    background: var(--success-subtle);
}

.share__copy[data-share-state="error"] {
    color: var(--danger);
    border-color: var(--danger-border);
    background: var(--danger-subtle);
}

/* ============================================================
   10. リンク色（:visited 対策）

   既定の :visited はダークで紫になりコントラストが落ちる。
   a:visited { color: inherit } と { color: CanvasText } はどちらも
   効かなかった（実測）。訪問履歴の漏洩対策でブラウザが
   参照・解決を伴う値を無視しているためと考えられる。

   ⚠ そのため :visited には var() も使わない（未検証のため）。
     16進リテラルのみを使い、通常状態と訪問済みを同じ値に固定する。
     テーマごとに繰り返すのはこの制約による。
     OS 追従をやめたため、決定22 の 3 ブロックが 2 ブロックに減った。
   ============================================================ */
/* 下線はホバーの間だけ出す（2026-08-28 / ADR-0020）。
   一覧の見出しと著者が常時下線で、行のすべてが押せるように見えていた。
   手本（Qiita）は指が乗った 1 つだけに線を出す。

   ⚠ a:hover へ text-decoration-line を直に書かない。a:hover は (0,1,1) であり、
     .brand / .nav-cta / .nav-link / .nav-icon / .share__x が持つ
     text-decoration: none (0,1,0) に勝つ。ボタンに見せているリンクが
     ホバーの間だけ下線を持つ形になる。実測 9 本が該当する。
   ⚠ 変数だけを切り替える。線の宣言そのものは下の a (0,0,1) の 1 箇所にしか
     無く、より強い規則が none と書けば無条件にそちらが勝つ。除外の名簿を
     持たずに済み、10 本目のボタンを足した日も自動で守られる。
   ⚠ 変数は :root へ置かない。意味トークンの名簿（contrast.test.ts）に
     混ざる。掛かる先は a だけであり、テーマごとの値も持たない。 */
a {
    color: var(--accent);
    --link-underline: none;
    text-decoration-line: var(--link-underline);
    text-underline-offset: 2px;
}

a:hover {
    color: var(--accent-hover);
    --link-underline: underline;
}

.nav a {
    color: var(--fg-muted);
}

.nav a:hover {
    color: var(--fg);
}

.item-actions a.danger,
.danger-zone a {
    color: var(--danger);
}

/* light（既定。data-theme が無いときは必ずこれ） */
a:visited {
    color: #0f62c0;
}

header a,
header a:visited {
    color: #16202e;
}

/* ⚠ nav-cta はアクセント塗りの上に乗る。
   .nav a (0,2,1) に負けないよう要素セレクタを含めて (0,2,1) にする。
   前回 .nav-cta (0,1,1) で書いたため薄いグレーの文字になっていた
   （2026-08-21 実測。.actions a.secondary と同じ形に揃える）。
   :visited では var() を使えない（セクション 10 冒頭を参照） */
.nav a.nav-cta,
.nav a.nav-cta:visited,
.nav a.nav-cta:hover {
    color: #ffffff;
}

/* ⚠ .nav の外にも .nav-cta がある（/me/posts の「新しい記事を書く」）。
   上の .nav a.nav-cta は .nav 配下でしか一致しない。
   外の 1 つは a:visited (0,1,1) に落ち、その色 #0b5fbd は
   背景の --accent と同一値。青地に青字で完全に消えていた
   （2026-08-21 実測。コントラスト比 1:1）。
   ダークは :root[data-theme="dark"] .nav-cta が .nav を前置しない形で
   書かれていたため、こちらだけ正常に見えていた。
   ⚠ ライトとダークで選択子の形を揃えること。片側だけ絞ると露見しない。 */
a.nav-cta,
a.nav-cta:visited,
a.nav-cta:hover {
    color: #ffffff;
}

.nav a:visited {
    color: #4a5768;
}

.actions a.secondary,
.actions a.secondary:visited {
    color: #16202e;
}

/* コメントの削除（2026-09-09 / ADR-0021 刻み 2-1）。
   ⚠ .actions a.secondary と同じ役（--fg）である。値も揃える。
      新しい対比を作らない。
   ⚠ 16 進のみを使う。:visited では var() が解決しない（§10 冒頭）。
   ⚠ (0,2,0) で a:visited (0,1,1) に勝つ。素の .comment-delete (0,1,0) は
      負けるため、要素を前置せずともこの形で足りる。
   ⚠ 4 テーマすべてに置く。テーマ付きの a:visited は (0,3,1) と (1,3,1) で
      あり、1 つでも欠けるとその配色だけ訪問済みが素のリンク色に戻る。
      contrast.test.ts が 4 テーマ分の宣言を求め、表に無い :visited を
      別の it で落とす。 */
.comment-delete:visited {
    color: #16202e;
}

/* ⚠ 共有ボタンも本文と同じ色にする（ADR-0012 決定9）。
   :hover まで固定するのは、a:hover の --accent-hover が
   ホバー時だけ文字色を変えてしまうため。
   .share__x:hover（§9）は背景と枠線だけを変える */
.share__x,
.share__x:visited,
.share__x:hover {
    color: #16202e;
}

.item-actions a.danger:visited,
.danger-zone a:visited {
    color: #b23a3e;
}

/* dark（保存済み、およびプレビュー中。決定28）。
   :has() 側は設定画面でしか一致しない。 */
:root[data-theme="dark"] a:visited,
:root:has(#theme-dark:checked) a:visited {
    color: #58a6ff;
}

:root[data-theme="dark"] header a,
:root[data-theme="dark"] header a:visited,
:root:has(#theme-dark:checked) header a,
:root:has(#theme-dark:checked) header a:visited {
    color: #e6edf6;
}

:root[data-theme="dark"] .nav a:visited,
:root:has(#theme-dark:checked) .nav a:visited {
    color: #a9b8cd;
}

:root[data-theme="dark"] .nav a.nav-cta,
:root[data-theme="dark"] .nav a.nav-cta:visited,
:root[data-theme="dark"] .nav a.nav-cta:hover,
:root:has(#theme-dark:checked) .nav a.nav-cta,
:root:has(#theme-dark:checked) .nav a.nav-cta:visited,
:root:has(#theme-dark:checked) .nav a.nav-cta:hover {
    color: #ffffff;
}

:root[data-theme="dark"] .actions a.secondary,
:root[data-theme="dark"] .actions a.secondary:visited,
:root:has(#theme-dark:checked) .actions a.secondary,
:root:has(#theme-dark:checked) .actions a.secondary:visited {
    color: #e6edf6;
}

:root[data-theme="dark"] .comment-delete:visited,
:root:has(#theme-dark:checked) .comment-delete:visited {
    color: #e6edf6;
}

:root[data-theme="dark"] .share__x,
:root[data-theme="dark"] .share__x:visited,
:root[data-theme="dark"] .share__x:hover,
:root:has(#theme-dark:checked) .share__x,
:root:has(#theme-dark:checked) .share__x:visited,
:root:has(#theme-dark:checked) .share__x:hover {
    color: #e6edf6;
}

:root[data-theme="dark"] .item-actions a.danger:visited,
:root[data-theme="dark"] .danger-zone a:visited,
:root:has(#theme-dark:checked) .item-actions a.danger:visited,
:root:has(#theme-dark:checked) .danger-zone a:visited {
    color: #f08c8f;
}

/* .nav の外の nav-cta（/me/posts の「新しい記事を書く」）を受ける。
   上の .nav a.nav-cta は .nav 配下でしか一致しない。
   ⚠ ライト側の a.nav-cta と選択子の形を揃える（ADR-0012 決定2）。
   素の .nav-cta (0,3,0) のままだと、ダークに a:hover の色を
   1 行足した瞬間に (0,3,1) に負けて文字色が変わる。
   「今そう書かれていない」ことに依存した状態を残さない */
:root[data-theme="dark"] a.nav-cta,
:root[data-theme="dark"] a.nav-cta:visited,
:root[data-theme="dark"] a.nav-cta:hover,
:root:has(#theme-dark:checked) a.nav-cta,
:root:has(#theme-dark:checked) a.nav-cta:visited,
:root:has(#theme-dark:checked) a.nav-cta:hover {
    color: #ffffff;
}

/* light のプレビュー（決定28）。
   保存済みがダークのときに data-theme="dark" を打ち消す。
   ⚠ 上の light 既定ブロックと同じ値を持つ。必ず同時に編集する。 */
:root:has(#theme-light:checked) a:visited {
    color: #0f62c0;
}

:root:has(#theme-light:checked) header a,
:root:has(#theme-light:checked) header a:visited {
    color: #16202e;
}

:root:has(#theme-light:checked) .nav a:visited {
    color: #4a5768;
}

:root:has(#theme-light:checked) .actions a.secondary,
:root:has(#theme-light:checked) .actions a.secondary:visited {
    color: #16202e;
}

:root:has(#theme-light:checked) .comment-delete:visited {
    color: #16202e;
}

:root:has(#theme-light:checked) .share__x,
:root:has(#theme-light:checked) .share__x:visited,
:root:has(#theme-light:checked) .share__x:hover {
    color: #16202e;
}

:root:has(#theme-light:checked) .item-actions a.danger:visited,
:root:has(#theme-light:checked) .danger-zone a:visited {
    color: #b23a3e;
}

:root:has(#theme-light:checked) a.nav-cta,
:root:has(#theme-light:checked) a.nav-cta:visited,
:root:has(#theme-light:checked) a.nav-cta:hover {
    color: #ffffff;
}

:root:has(#theme-light:checked) .nav a.nav-cta,
:root:has(#theme-light:checked) .nav a.nav-cta:visited,
:root:has(#theme-light:checked) .nav a.nav-cta:hover {
    color: #ffffff;
}

/* ============================================================
   11. ブレークポイント（640 / 960 の 2 点のみ）
   点数を増やすと目視確認の組み合わせが増える。
   ============================================================ */
/* 640px 未満（スマホ）。タップ領域を 44px 以上にする */
@media (max-width: 40rem) {

    /* ⚠ 375px の可用幅 351px を保つ。ADR-0018 決定3 の前提である */
    :root {
        --gutter: var(--sp-3);
    }

    .toolbar .tool {
        min-height: 2.75rem;
        min-width: 2.75rem;
    }

    .tabs .tab {
        min-height: 2.5rem;
    }

    .actions {
        flex-wrap: wrap;
    }

    .actions button,
    .actions a.secondary {
        min-height: 2.9rem;
    }

    .field .cm-content {
        min-height: 18rem;
    }

    .field .cm-editor {
        max-height: 60vh;
    }

    .body table {
        font-size: var(--fs-xs);
    }

    /* ナビを 1 行に収める（ADR-0012 決定2 / ADR-0018 決定3）。
       ⚠ 375px の可用幅は 351px しかない。
       全項目を出すと約 462px になり 111px 超過した（2026-08-21 実測）。

       【2026-08-26】幅で隠す方式をやめた。
       「自分の状態」（利用者名・投稿管理・保存した記事・設定・ログアウト）は
       details へ畳んだ（§22）。1 行に並ぶのはサイト名・虫眼鏡・投稿する・
       利用者の 4 つだけであり、項目を足しても溢れない。

       ⚠ 隠す規則をここへ戻さない。畳んだ中では文字を出す。
       ⚠ サイト名は隠さない。識別に必要で、隠すと戻る場所が分からない。 */
    .nav {
        column-gap: var(--sp-1);
        row-gap: var(--sp-1);
    }

    .brand {
        font-size: 1rem;
    }

    .nav-cta {
        padding: .4em .7em;
    }

    dialog {
        padding: var(--sp-3);
        max-inline-size: 96vw;
    }

    /* タップ領域を確保する。hover が無い環境では削除ボタンを常時表示する */
    .library-item__delete {
        opacity: 1;
        min-height: 2.2rem;
    }

    .footer-links {
        gap: var(--sp-1) var(--sp-3);
    }
}

/* 960px 以上。可読幅をわずかに広げ、余白を増やす */
@media (min-width: 60rem) {
    :root {
        --measure: 52rem;
    }

    .nav {
        padding-block: var(--sp-4);
    }
}

/* ============================================================
   14. 2026-08-22 の追加
   ============================================================ */

/* 空のライブラリ（2026-08-22）。
   状態の宣言と操作の案内を分ける。
   ⚠ .hint 一本だと「無い」ことが補足の色に沈み、
   画像が無いのか読み込み中なのかが読み取れない。 */
.library-empty {
    margin: var(--sp-4) 0 var(--sp-3);
    color: var(--fg);
}

/* ライブラリ内の追加ボタン（2026-08-22）。
   ⚠ 空のときだけ editor.ts が差し込む。
   .actions button.secondary を流用しないのは、あちらが flex の子として
   幅を分け合う前提であり、モーダル内に単独で置くと間延びするため。
   高さは決定22 のタップ領域に合わせる。 */
.library-add {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-block-size: 2.75rem;
    padding: .7em 1.1em;
    font: inherit;
    font-weight: 500;
    color: var(--fg);
    background: var(--bg-subtle);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    cursor: pointer;
}

.library-add:hover {
    background: var(--bg-hover);
    border-color: var(--fg-subtle);
}

/* ⚠ 退会確認の username を 1 クリックで選べるようにする。
   ダブルクリックでは末尾に空白が付き、貼り付けた文字列が
   見た目どおりにならない（2026-08-22 実測）。
   サーバー側は trim するため実害は出ていないが、
   見えない文字が入る状態を利用者に見せない。
   ⚠ .body code へは広げない。記事のインラインコードまで
   全選択になると、部分的なコピーができなくなる。 */
.form-page code {
    user-select: all;
}

/* ============================================================
   15. 一覧のカード（2026-08-22）
   ============================================================ */

/* ⚠ .cards > article に限定する。素の article は記事詳細も使う。
   ⚠ 1 列固定である。body が --measure（48rem）で制限されており、
   2 列にすると 1 列あたり約 23rem になりカードとして狭い。
   ⚠ article + article の区切り線は実測 0 件で存在しない。
   打ち消しルールは書かない。書くと線が 1 本増えるだけである。 */
.cards {
    display: grid;
    gap: var(--sp-4);
    margin-block: var(--sp-4);
}

.cards>article {
    padding: var(--sp-4);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--bg-subtle);
    box-shadow: var(--shadow-1);
    /* ⚠ transform を含めない（2026-08-29）。下の :hover で宣言を消したため、
       残すと「効かない遷移」になる。§15 の死んだ宣言（40% の下線色）と同型。 */
    transition: border-color .15s, box-shadow .15s;
}

/* ⚠ 枠の色だけを変える。.library-item:hover と同じ手法にそろえた。
   ⚠ カード全体はリンクにしない。中の著者名がリンクであり、
   入れ子になると押し分けられなくなる。
   ⚠ 浮かせない（2026-08-29 / モック v2）。translateY で 3px 上げると、
     隣接カードとの間隔が上下で非対称になり、連続してなぞったとき一覧が波打つ。
     前後の別は影の強さ（--shadow-1 -> --shadow-2）が担う。
   ⚠ レイアウトを動かす性質の宣言を hover に置かない。transform は
     包含ブロックを作るため、将来カード内に position: absolute を置いた日に
     ホバー中だけ基準がずれる（§22 の板と同型の事故）。 */
.cards>article:hover {
    border-color: var(--accent);
    box-shadow: var(--shadow-2);
}

.cards>article h2 {
    margin-block: 0 var(--sp-2);
}

/* 見出しを面の上で最も明るくする（2026-08-28）。
   ⚠ アクセント色を見出しに使わない。一覧の全行が同じ色になり、
     「どこが押せるか」ではなく「全部が押せる」しか伝わらない。
     ダークで --accent は面の上で 4.92、--fg は 14.63 である。
   ⚠ 押せることは下線が示す。ただし線はホバーの間だけ出す（§10）。
     常時の線は一覧では「全部が押せる」に戻ってしまう。色は階層に使う。
   ⚠ 40% の下線色を消した。線が出ない状態では効かず、線が出る状態
     （ホバー）では下の :hover が currentColor で上書きしていた。
     どちらの状態でも画面に現れない死んだ宣言である。
   ⚠ :visited は §10 の末尾に 4 テーマ分ある。ここを変える日は
     あちらも同時に変える（禁止 287 と同型）。 */
.cards>article h2 a {
    color: var(--fg);
}

/* 著者と日付は見出しより弱くする。
   ⚠ 1 枚のカードに主張を 2 つ置かない。 */
.cards .meta a {
    color: var(--fg-muted);
}

/* 【自己紹介と記事一覧を見分ける / D53-B】
   D44-A で自己紹介に .cards を流用した結果、記事カードと同じ面になった。
   面・角丸・枠・帯の 4 点で差をつける。浮いて押せるのは記事だけにする。
   ⚠ 帯は box-shadow で描く。border-left-width を 3px にすると内容が 2px
   ずれ、記事カードと左端が揃わない。レイアウトを動かさずに印だけ足す。
   ⚠ 色は直書きしない。トークンで書けばテーマ 4 種に追従する。 */
.cards.profile>article {
    background: var(--bg);
    border-color: transparent;
    border-radius: 0;
    box-shadow: inset 3px 0 0 var(--accent);
}

/* ⚠ 押せないものを反応させない（ADR-0012）。
   自己紹介カードは中の外部リンクだけが押せる。カード自体は押せないので
   .cards > article:hover の枠色・影の変化をここで打ち消す。
   ⚠ transform: none を削除した（2026-08-29）。打ち消す対象そのものが
     無くなったためである。無い宣言を打ち消す行を残さない。 */
.cards.profile>article:hover {
    border-color: transparent;
    box-shadow: inset 3px 0 0 var(--accent);
}

/* ============================================================
   16. いいねを押せる形にする（ADR-0016 決定4 / 段階 4b-2）
   ⚠ §9 の共通形（.share__x, .share__copy, .share__like）は触らない。
     3 種の宣言を 1 本にまとめた D97 の形を崩すと高さがずれる。
   ============================================================ */

/* form は枠を持たない。.share の flex の子として button を並べる。
   ⚠ display: contents は使わない。form が箱を失うと、
     将来この中へ 2 つ目の要素を置いたときに並びが崩れる */
.share__form {
    display: inline-flex;
    margin: 0;
}

/* ⚠ button は color を継承しない。既定の ButtonText が入る。
   a 側の下線は共通形が消していないため、ここで落とす */
button.share__like,
a.share__like {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

button.share__like:hover,
a.share__like:hover {
    background: var(--bg-hover);
    border-color: var(--fg-subtle);
}

/* 押した状態（決定6）。
   ⚠ 新しい色を作らない。--danger の 3 点組は §6 と §9 が既に使う形であり、
      ダークの定義も揃っている。
   ⚠ 色だけに頼らない。状態は aria-pressed が持ち、この規則はそれを写す */
.share__like[aria-pressed="true"] {
    color: var(--danger);
    border-color: var(--danger-border);
    background: var(--danger-subtle);
}

.share__like[aria-pressed="true"]:hover {
    background: var(--danger-subtle);
    border-color: var(--danger);
}

/* :visited 対策（§10 と同じ制約）。
   ⚠ a だけを対象にする。素の .share__like に色を書くと
     button の押下色（上）を後勝ちで潰す。
   ⚠ 16進リテラルのみを使う。理由は §10 冒頭 */
a.share__like,
a.share__like:visited,
a.share__like:hover {
    color: #16202e;
}

:root[data-theme="dark"] a.share__like,
:root[data-theme="dark"] a.share__like:visited,
:root[data-theme="dark"] a.share__like:hover,
:root:has(#theme-dark:checked) a.share__like,
:root:has(#theme-dark:checked) a.share__like:visited,
:root:has(#theme-dark:checked) a.share__like:hover {
    color: #e6edf6;
}

:root:has(#theme-light:checked) a.share__like,
:root:has(#theme-light:checked) a.share__like:visited,
:root:has(#theme-light:checked) a.share__like:hover {
    color: #16202e;
}

/* タップ領域は 4 種まとめて §18 の末尾へ移した（T51i123c）。
   ⚠ ここへ書き戻さない。2 本あると片方だけ直す事故が起きる。 */

/* ============================================================
   17. 共有と反応を分ける（T51i121）
   ⚠ §9 の共通形（.share__x, .share__copy, .share__like）は触らない。
     3 種の宣言を 1 本にまとめた D97 の形を崩すと高さがずれる。
   ⚠ 外枠（余白と区切り線）は .post-actions が持つ。
     .share から 3 宣言を移した。両方に書くと線が 2 本になる。
   ============================================================ */

/* 記事末尾の操作帯。共有（左）と反応（右）を対の位置に置く。
   ⚠ space-between で離す。gap だけでは幅が余ったときに隣り合って見え、
     いいねが共有の一機能として読まれる（T51i121 の是正点）。
   ⚠ 折り返しても 2 群の区別は残す。40rem 未満は下の断点で左揃えに戻す */
.post-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--sp-3) var(--sp-4);
    margin-top: var(--sp-6);
    padding-top: var(--sp-4);
    border-top: 1px solid var(--border);
}

/* 反応の群（いいね。T51i122 でブックマークが並ぶ）。
   ⚠ .share と同じ gap にする。2 群で間隔が違うと、
     同じ形のボタンなのに別の仕組みに見える */
.reactions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-3);
}

/* 積んだ後は左揃えにする（§11 の断点を増やさない）。
   ⚠ space-between は主軸にしか効かない。縦に積むと間隔だけが残り、
     2 群が再び 1 つの帯に見える */
@media (max-width: 40rem) {
    .post-actions {
        justify-content: flex-start;
    }
}

/* ============================================================
   18. ブックマーク（T51i122）
   ⚠ 寸法は §9 の共通形へ 4 つ目として加えた。宣言をここへ複製しない。
     3 種 1 本にまとめた D97 の形を崩すと高さが再びずれる。
   ⚠ 押下色はいいねと分ける。同じ色にすると 2 つの操作が同じ意味に見える。
   ============================================================ */

/* ⚠ button は color を継承しない。既定の ButtonText が入る。
   a 側の下線は共通形が消していないため、ここで落とす（§16 と同形） */
button.share__bookmark,
a.share__bookmark {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

button.share__bookmark:hover,
a.share__bookmark:hover {
    background: var(--bg-hover);
    border-color: var(--fg-subtle);
}

/* 保存した状態。
   ⚠ 新しい色を作らない。--accent の 3 点組は §1 に 4 テーマ分の定義がある。
   ⚠ いいねの --danger と分ける。共感と保存は別の操作である。
   ⚠ 色だけに頼らない。状態は aria-pressed が持ち、この規則はそれを写す */
.share__bookmark[aria-pressed="true"] {
    color: var(--accent);
    border-color: var(--accent);
    background: var(--accent-subtle);
}

.share__bookmark[aria-pressed="true"]:hover {
    background: var(--accent-subtle);
    border-color: var(--accent-hover);
}

/* :visited 対策（§10 と同じ制約）。
   ⚠ a だけを対象にする。素の .share__bookmark に色を書くと
     button の押下色（上）を後勝ちで潰す。
   ⚠ 16進リテラルのみを使う。理由は §10 冒頭。
   ⚠ 値は §16 の a.share__like と同一にする。新しい対比を作らない */
a.share__bookmark,
a.share__bookmark:visited,
a.share__bookmark:hover {
    color: #16202e;
}

:root[data-theme="dark"] a.share__bookmark,
:root[data-theme="dark"] a.share__bookmark:visited,
:root[data-theme="dark"] a.share__bookmark:hover,
:root:has(#theme-dark:checked) a.share__bookmark,
:root:has(#theme-dark:checked) a.share__bookmark:visited,
:root:has(#theme-dark:checked) a.share__bookmark:hover {
    color: #e6edf6;
}

:root:has(#theme-light:checked) a.share__bookmark,
:root:has(#theme-light:checked) a.share__bookmark:visited,
:root:has(#theme-light:checked) a.share__bookmark:hover {
    color: #16202e;
}

/* 一覧のカード（2026-08-28）。値は --fg と --fg-muted の解決結果に一致させる。
   ⚠ :visited では var() を使えない（セクション 10 冒頭）。
   ⚠ 詳細度で勝たせるため 4 テーマ分を書く。順序に依存しない。 */
.cards>article h2 a:visited {
    color: #4a5768;
}

.cards .meta a:visited {
    color: #4a5768;
}

:root[data-theme="dark"] .cards>article h2 a:visited,
:root:has(#theme-dark:checked) .cards>article h2 a:visited {
    color: #a9b8cd;
}

:root[data-theme="dark"] .cards .meta a:visited,
:root:has(#theme-dark:checked) .cards .meta a:visited {
    color: #a9b8cd;
}

:root:has(#theme-light:checked) .cards>article h2 a:visited {
    color: #4a5768;
}

:root:has(#theme-light:checked) .cards .meta a:visited {
    color: #4a5768;
}

/* ホバーは訪問済みより後ろに置く（2026-08-28）。
   ⚠ :hover と :visited は詳細度が同じ (0,2,3) である。§15 に置いたままだと
     後から現れる :visited が勝ち、訪問済みのリンクだけホバーで色が変わらない。
     順序に意味があるため §15 へ戻さない。 */
.cards>article h2 a:hover {
    color: var(--accent);
}

.cards .meta a:hover {
    color: var(--accent);
}

/* タップ領域（決定22 / T51i123c）。§11 の断点を増やさず同じ幅で足す。
   ⚠ 4 種を 1 本にまとめた。いいねと保存だけに書いていたため、
     狭幅では共有 2 種だけが低いままだった。同じ帯に並ぶものを分けない。
   ⚠ 要素を前置する。素のクラスでも記述順で後勝ちになるが、
     「今そう並んでいる」ことに依存した状態を残さない（ADR-0012 決定2 と同型）。 */
@media (max-width: 40rem) {

    a.share__x,
    button.share__copy,
    button.share__like,
    a.share__like,
    button.share__bookmark,
    a.share__bookmark {
        min-height: 2.75rem;
    }
}

/* ============================================================
   19. 押した状態の塗り（T51i124）
   押下は背景・枠・文字色の 3 点組で表していたが、図そのものは
   輪郭のままだった。色だけに頼らないと掲げて、色だけが変わっていた。
   ⚠ 3 点組（css.test.ts の SHARE_STATE）へ足さない。あちらは宣言
      集合を完全一致で見ており、押下色の検査も同じ本文に乗っている。
   ⚠ 押下規則の側に書いても効かない。<svg> の fill="none" はその要素
      自身の宣言であり、親から降りてくる継承値より強い。.icon を直接指す。
   ⚠ 色は currentColor。押下時の文字色をそのまま使い、新しい対比を
      作らない（contrast.test.ts の対象は増えない）。
   ⚠ 保存といいねを分けない。片方だけ塗ると書き忘れに見える。
   ============================================================ */

.share__like[aria-pressed="true"] .icon,
.share__bookmark[aria-pressed="true"] .icon {
    fill: currentColor;
}

/* ============================================================
   20. 機能名の吹き出し（T51i125）
   いいねと保存は図だけで、機能名が画面のどこにも出ていなかった。
   名前は aria-label が持つが、それは支援技術にしか届かない。
   ⚠ title 属性を使わない。位置も字形もブラウザが決め、
      キーボードの焦点では出ない（決定2 のログアウトとは目的が違う）。
   ⚠ 語は押下状態で変えない。状態は塗りと aria-pressed が持つ（決定16）。
   ⚠ position は共通形へ書かない。css.test.ts が SHARE_COMMON を
      完全一致で見ている。要素を前置した別規則で当てる（決定2 と同型）。
   ⚠ 色は --fg / --bg の反転。本文と同じ対比であり新しい色を作らない。
   ⚠ 触屏では出さない。囲まないと軽く触れた後も残る。
   ============================================================ */

button.share__like,
a.share__like,
button.share__bookmark,
a.share__bookmark {
    position: relative;
}

.share__like::after,
.share__bookmark::after {
    content: attr(data-tooltip);
    position: absolute;
    top: calc(100% + .35em);
    left: 50%;
    transform: translateX(-50%);
    z-index: 1;
    padding: .25em .6em;
    border-radius: var(--r-sm);
    background: var(--fg);
    color: var(--bg);
    font-size: var(--fs-sm);
    font-weight: 400;
    line-height: 1.5;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
}

/* ⚠ 焦点でも出す。図だけのボタンが 2 つあり、
   キーボードだけで操作する人には名前がどこにも出ない */
.share__like:focus-visible::after,
.share__bookmark:focus-visible::after {
    opacity: 1;
}

@media (hover: hover) {

    .share__like:hover::after,
    .share__bookmark:hover::after {
        opacity: 1;
    }
}

/* ============================================================
   21. 検索（ADR-0017）
   ⚠ .cards は §15 の形をそのまま使う。一覧と検索で枠が違うと、
      同じ記事が別の種類のものに見える。抜粋の 1 行だけを足す。
   ============================================================ */

/* 検索の窓。640px 未満では縦に積む（§11 の断点を増やさない）。
   ⚠ .field を流用しない。あちらは label が block で下に余白を持ち、
      1 行に収める形と噛み合わない */
.search-form {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-3);
    margin-block: var(--sp-4) var(--sp-5);
}

/* ⚠ 読み上げのために残す。placeholder は名前の代わりにならない。
      画面では窓とボタンで用途が明らかなため視覚的には隠す
      （幅 1px と clip-path。ADR-0018 で .nav-link__label の隠しは廃した） */
.search-form__label {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.search-form input[type="search"] {
    flex: 1 1 14rem;
    min-inline-size: 0;
    padding: .65em .75em;
    font: inherit;
    color: inherit;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    background: var(--bg-inset);
    transition: border-color .12s ease, box-shadow .12s ease;
}

.search-form input[type="search"]:hover {
    border-color: var(--fg-subtle);
}

.search-form input[type="search"]:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
}

/* ⚠ .actions button を流用しない。あちらは flex: 1 で幅を分け合う前提で、
      窓の隣に置くと間延びする。塗りは主要動作に揃える */
.search-form button[type="submit"] {
    flex: 0 0 auto;
    /* タップ領域（決定22）。狭幅でも縮めないため断点を使わない */
    min-block-size: 2.75rem;
    padding: .7em 1.3em;
    font: inherit;
    font-weight: 600;
    border: 1px solid transparent;
    border-radius: var(--r-sm);
    cursor: pointer;
    background: var(--accent-solid);
    color: var(--accent-fg);
    box-shadow: var(--shadow-1);
    transition: background-color .12s ease;
}

.search-form button[type="submit"]:hover {
    background: var(--accent-solid-hover);
}

/* 抜粋（決定21）。本文の一部であり見出しより弱く出す。
   ⚠ 3 行で打ち止める。snippet() の語数は 24 に固定しているが、
      3 文字の断片が 24 個で 70 文字前後になり、狭幅では 4 行を超える。
      カードの高さが記事ごとに違うと一覧として読みにくい */
.search-snippet {
    margin-block: 0 var(--sp-2);
    font-size: var(--fs-sm);
    color: var(--fg-muted);
    line-height: 1.7;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow: hidden;
}

/* 一致した箇所（決定20）。
   ⚠ 既定の mark（黄地・黒字）に任せない。ダークで地色から浮き、
      テーマの 2 種で対比が揃わない。
   ⚠ 新しい色を作らない。--accent の 3 点組は §1 に両テーマ分の定義があり、
      ブックマークの押下色が既に使う形である。
   ⚠ 色だけに頼らない。太字を併せる。地色の差が分からない環境でも
      どこが一致したか読める */
.search-snippet mark {
    padding: 0 .15em;
    border-radius: 3px;
    background: var(--accent-subtle);
    color: var(--fg);
    font-weight: 600;
}

/* ============================================================
   22. ヘッダーの畳み込み（ADR-0018）
   ⚠ 幅で HTML を切り替えない。同じ details を、幅ごとに違う見せ方で描く。
      同じ導線が 2 通り存在すると片方だけ直す事故が起きる（D97 と同型）。
   ⚠ JS を持たない。開閉は details が担い、script-src は 'none' のまま。
   ============================================================ */

/* --- 開く目印 ------------------------------------------------------------ */
/* ⚠ 既定の三角を消す。.nav-icon の inline-flex で消える環境が多いが、
   list-style と WebKit の擬似要素の両方を明示する。
   ⚠ 2 本に分けて書く。片方が未対応でも、もう片方が残る */
.nav-search>summary,
.nav-menu>summary {
    list-style: none;
    cursor: pointer;
}

.nav-search>summary::-webkit-details-marker,
.nav-menu>summary::-webkit-details-marker {
    display: none;
}

/* 利用者アイコン ＋ ▾（決定2）。図を 2 つ並べるため幅を広げる */
.nav-menu__summary {
    inline-size: auto;
    gap: var(--sp-1);
    padding-inline: var(--sp-2);
}

/* 開いている間は押した状態を示す。⚠ 色を作らない。--bg-hover を使う */
.nav-search[open]>summary,
.nav-menu[open]>summary {
    background: var(--bg-hover);
}

/* --- 畳んだ中身の置き場 --------------------------------------------------- */
/* ⚠ flex-basis: 100%（flex: 0 0 100%）は使えない。details は summary と
   中身を含む単一の flex 項目であり、100% を与えると目印ごと 2 行目へ移る。
   絶対配置なら summary は 1 行目に残り、中身だけがヘッダーの下へ降りる。
   ⚠ header は position: sticky を持つため包含ブロックになる。入れ物を足さない。
   ⚠ 地色を必ず敷く。header の外側へ出るため、敷かないと本文が透ける。 */
.nav-search>.search-form,
.nav-menu__panel {
    position: absolute;
    inset-block-start: 100%;
    padding: var(--sp-3);
    background: var(--bg-subtle);
    border: 1px solid var(--border);
    border-block-start: none;
    border-end-start-radius: var(--r-md);
    border-end-end-radius: var(--r-md);
    box-shadow: var(--shadow-2);
}

/* 窓は全幅で降りる（Qiita のモバイルと同じ） */
.nav-search>.search-form {
    inset-inline: var(--gutter);
    /* ⚠ §21 の margin を打ち消す。あちらは本文に置く前提の値 */
    margin-block: 0;
}

/* メニューは右寄せの小さな板 */
.nav-menu__panel {
    /* ⚠ 0 にすると器の外へ出る。絶対配置はパディングボックスを基準にする */
    inset-inline-end: var(--gutter);
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
    min-inline-size: 12rem;
}

/* ⚠ 縦に積むので区切りは横線にする。§4 の .nav-sep は縦 1px であり、
   そのままでは見えない。⚠ §4 を書き換えない。あちらは横並び用である */
.nav-menu__panel .nav-sep {
    inline-size: auto;
    block-size: 1px;
    margin-block: var(--sp-1);
}

/* 畳んだ中では文字を出す。タップ領域は決定22 に合わせる。
   ⚠ .nav を前置して (0,3,0) にする。§4 の .nav .user は (0,2,0) で
      同じ強さであり、gap の勝ち負けが記述順で決まってしまう */
.nav .nav-menu__panel .nav-link,
.nav .nav-menu__panel .user {
    gap: var(--sp-2);
    min-block-size: 2.75rem;
    padding-inline: var(--sp-2);
    border-radius: var(--r-sm);
}

.nav-menu__panel .nav-link:hover {
    background: var(--bg-hover);
}

/* ⚠ 文字色は与えない。.nav a:visited (0,2,1) が勝ち、一度開くと戻る。
   4 テーマ × 3 状態の :visited 対策（§10 と同型）は別の区切りで扱う。
   地色だけで区別する */
.nav-menu__panel .nav-link--danger:hover {
    background: var(--danger-subtle);
}

/* ⚠ 畳んだ中では名前を切らない。§4 は 1 行に収めるための 10ch 制限。
   ⚠ .nav を前置する。§4 の .nav .user__name と同じ特異度では
      記述順に依存する（ADR-0012 決定2 と同型の理由） */
.nav .nav-menu__panel .user__name {
    max-inline-size: none;
}

/* --- 狭い画面のタップ領域（決定22）--------------------------------------- */
/* ⚠ §11 の断点を増やさない。同じ 40rem を使う */
@media (max-width: 40rem) {

    .nav-search>summary,
    .nav-menu>summary {
        min-inline-size: 2.75rem;
        min-block-size: 2.75rem;
    }
}

/* --- 広い画面（決定7）----------------------------------------------------- */
/* ⚠ §11 の断点を増やさない。同じ 60rem を使う */
@media (min-width: 60rem) {

    /* 窓を常設する。開閉の目印は消し、open の有無に依存しない */
    .nav-search>summary {
        display: none;
    }

    .nav-search {
        flex: 0 1 22rem;
        min-inline-size: 0;
    }

    /* 方式 1: display で隠す実装を覆す */
    .nav-search>.search-form {
        position: static;
        display: flex;
        padding: 0;
        background: none;
        border: none;
        box-shadow: none;
    }

    /* 方式 2: content-visibility で隠す実装を覆す。
       ⚠ 上と 1 本にまとめない。未対応の環境では
          擬似要素を含む規則ごと無視される */
    .nav-search::details-content {
        content-visibility: visible;
        block-size: auto;
        overflow: visible;
    }

    /* ⚠ ヘッダーの中では窓もボタンも低くする。§21 の 2.75rem と
       .65em の余白は本文に単独で置く前提であり、ナビでは「投稿する」より
       背が高くなる（1200px の実測）。§21 は触らない。あちらは /search の本文用。
       ⚠ 1 本で揃える。片方だけ直すと段差が残る（D97 と同型）。 */
    .nav-search .search-form input[type="search"],
    .nav-search .search-form button[type="submit"] {
        box-sizing: border-box;
        /* ⚠ font-size を揃える（T51i153 / 訂正 389）。em を単位に持つ
           line-height と padding-block は、掛かる font-size が違えば
           異なる px になる。素を共有しても高さは揃わない。
           実測: button 17px（§21 の font: inherit が --fs-base を継ぐ）
                 a.nav-cta 14.4px（--fs-sm）→ 38.73px と 36px の差
           ⚠ 揃える先は --fs-sm である。ヘッダーの基準は「投稿する」であり、
             本文の寸法をナビへ持ち込まない。 */
        font-size: var(--fs-sm);
        min-block-size: var(--nav-ctl-h);
        padding-block: var(--nav-ctl-pad-block);
        line-height: var(--nav-ctl-line);
    }

    .nav-search .search-form button[type="submit"] {
        padding-inline: .9em;
    }

    /* ⚠ 投稿する を検索の窓・ボタンと同じ高さの素で組む（T51i153）。
       上の規則へ選択子を足す形は採らない。css.test.ts が
       「窓とボタンを 1 本で揃える」規則の形そのものを固定しており、
       第 3 の選択子を差すと赤くなる。素を共有すれば目的は足りる。
       ⚠ .nav a.nav-cta (0,2,1) にする。素の .nav-cta (0,1,0) では
         §10 のテーマ規則と同じ強さにならず、記述順に依存する。
       ⚠ 枠は透明で置く。button 側が 1px を持つため、無いと 2px 低くなる。 */
    .nav a.nav-cta {
        box-sizing: border-box;
        min-block-size: var(--nav-ctl-h);
        padding-block: var(--nav-ctl-pad-block);
        border: var(--nav-ctl-border) solid transparent;
        line-height: var(--nav-ctl-line);
    }
}

/* ============================================================
   23. Google でログイン（2026-09-06 / ADR-0005）
   ブランドの取り扱いガイドラインの記号をボタンへ入れる。
   ⚠ .actions a.secondary へ宣言を足さない。あちらは寸法と枠と
      :visited 対策が絡む共通形であり、css.test.ts が形を見る。
      専用の class を 1 枚重ねる（§18 が §9 を触らないのと同型）。
   ⚠ 記号を再着色しない。fill は資産の値のままで、currentColor に
      しない。§19（押下時に .icon を塗る規則）の対象にも入れない。
   ============================================================ */

/* 記号と文字の間隔。.actions a.secondary は inline-flex だが
   gap を持たない（文字だけの前提で書かれている）。 */
.btn-google {
    gap: var(--sp-2);
}

/* 記号の下地（ガイドライン）。
   ⚠ テーマで色を変えない。記号は白地に置く前提の資産である。
      ライトの面（--bg-subtle = 白）の上では見えず、ダークの面
      （#131c2b）の上でだけ円として現れる。1 宣言で両テーマが揃う。
   ⚠ 変数を :root へ置かない。意味トークンの名簿（contrast.test.ts）に
      混ざる。掛かる先はこの 1 規則だけであり、テーマごとの値も持たない
      （.brand .icon の --logo-moegi と同型）。
   ⚠ 対比の検査に載せない。これは図の下地であり文字を載せない。
   ⚠ 寸法は Google の既定に合わせる（ボタン 40px / 記号 20px）。
      下地は記号の周りの余白ぶんを足して 28px とする。 */
.btn-google__mark {
    --google-mark-bg: #ffffff;

    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    inline-size: 1.75rem;
    block-size: 1.75rem;
    border-radius: var(--r-pill);
    background: var(--google-mark-bg);
}

/* ⚠ style 属性で書かない。style-src が 'self' であり属性は拒否される。
      Google の見本にある style="display: block" はここが持つ。 */
.btn-google__mark svg {
    display: block;
    inline-size: 1.25rem;
    block-size: 1.25rem;
}

/* ---------------------------------------------------------------
   24. タグ（2026-09-07 / ADR-0033）

   ⚠ 塗りを宣言しない。ADR-0025 が定めた地と面の対を 1 つ増やすことになり、
      contrast.test.ts の名簿にも触れる。識別は縁と角丸だけで行う
      （決定4 の「識別は縁が担う」と同じ立場）。
   ⚠ 新しいトークンを :root へ足さない。既存の --border-strong / --fg-muted /
      --accent / --r-pill を使う（contrast.test.ts が :root の員数を数える）。
   ⚠ 丸い角を直値で書かない。--r-pill が既に在る（129 行で定義され、764 行と
      2866 行が使う。2026-09-07 実測）。一度 999px と直に書いて巻き戻した。
      同じ事実を 2 か所に置くと、片方だけが動く。
   ⚠ 断点を増やさない。折り返しは flex-wrap が担う。
   ⚠ .share 系の選択子へ足さない。あちらは共通形の員数が固定されている
      （D97 / css.test.ts）。
   ⚠ :visited は §25 が固定する（2026-09-08）。書かなかった間は §10 の
      テーマ規則 :root[data-theme="dark"] a:visited (0,2,1) が
      .post-tags a (0,1,1) に勝ち、開いたタグだけ素のリンク色になっていた。
      訪問の履歴が画面から読み取れる形でもあった。
   ⚠ 直値の取り残しは contrast.test.ts の VISITED_PAIRS が受ける。
      「タグのピル」の 1 行を同じ手で足した。パレットを動かした日に赤くなる。
   --------------------------------------------------------------- */
.post-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    /* 下の余白を 24px から落とした（2026-09-08）。タグが本文の下へ移り、
       続く .post-actions が margin-top var(--sp-6) と padding-top var(--sp-4)
       を自ら持つため、ここで 24px を足すと隙が三重になる。
       ⚠ 直値へ戻さない。--sp-2 が既に在る（§1）。 */
    margin: 0 0 var(--sp-2);
}

.post-tags a {
    display: inline-flex;
    align-items: center;
    padding: 2px 12px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-pill);
    color: var(--fg-muted);
    font-size: 0.8125rem;
    line-height: 1.8;
    text-decoration: none;
}

.post-tags a:hover {
    border-color: var(--accent);
    color: var(--accent);
}

/* ---------------------------------------------------------------
   25. タグの色を訪問の有無で変えない（2026-09-08 / 運営者の判断）

   ⚠ 16 進のみを使う。:visited では var() が解決しない（§10 冒頭）。
      値は --fg-muted の解決結果と一致させる（ライト #4a5768 / ダーク #a9b8cd。
      2026-09-08 にパレットから解決して写した）。
   ⚠ 4 テーマすべてに書く。contrast.test.ts が 4 テーマ分の宣言を求め、
      表に無い :visited を別の it で落とす。
   ⚠ ホバーを訪問済みより後ろに置く。素の 2 本は同じ (0,2,1) であり順序で
      決まる（§18 の .cards と同型の事故）。
   ⚠ テーマ付きの :visited は (0,3,2) であり素のホバー (0,2,1) に勝つ。
      ホバー側もテーマごとに置かないと、開いたタグだけホバーで色が変わらない。
   ⚠ ホバーには var() を使う。:hover は解決するため直値を増やさない。
   ⚠ 縁の色は §24 のホバーが持つ。ここは色だけを扱う。
   --------------------------------------------------------------- */
.post-tags a:visited {
    color: #4a5768;
}

:root[data-theme="dark"] .post-tags a:visited,
:root:has(#theme-dark:checked) .post-tags a:visited {
    color: #a9b8cd;
}

:root:has(#theme-light:checked) .post-tags a:visited {
    color: #4a5768;
}

/* ⚠ §24 と同じ宣言を再度置く。上の :visited より後ろに在ることが目的であり、
      消すと訪問済みのタグがホバーで反応しなくなる。 */
.post-tags a:hover {
    color: var(--accent);
}

:root[data-theme="dark"] .post-tags a:hover,
:root:has(#theme-dark:checked) .post-tags a:hover {
    color: var(--accent);
}

:root:has(#theme-light:checked) .post-tags a:hover {
    color: var(--accent);
}

/* ---------------------------------------------------------------
   26. タグの入力欄を矩形にする（2026-09-08 / ADR-0019 決定6 / ADR-0033 決定16）

   ⚠ 塗りを 1 つも宣言しない。この画面の器（main）は既に --bg-subtle であり、
      .field input の面と同色である。置かなくても姿は変わらず、ADR-0025 の
      地と面の対も contrast.test.ts の名簿も動かない。
   ⚠ 新しいトークンを :root へ足さない。§24 と同じ --border-strong /
      --fg-muted / --accent / --r-pill を借りる。
   ⚠ 断点を増やさない。折り返しは flex-wrap が担う。
   ⚠ .field input の枠を内側で消す。消さないと箱の中に箱が現れる。
   ⚠ 幅を打ち消す。.field input は width: 100% を持ち、矩形と同じ行に並ばない。
   ⚠ 焦点の見せ方は .field input:focus と同じ値にする。JS の有無で
      入力欄の作法が変わって見えないようにする。
   --------------------------------------------------------------- */
.tag-editor {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-1);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-sm);
    transition: border-color .12s ease, box-shadow .12s ease;
}

.tag-editor:hover {
    border-color: var(--fg-subtle);
}

.tag-editor:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
}

/* ⚠ (0,3,1) で .field input:not([type="checkbox"]) (0,2,1) に勝つ。
      記述順に依存しない。 */
.field .tag-editor input[type="text"] {
    flex: 1 1 8rem;
    min-inline-size: 0;
    width: auto;
    padding: .35em .25em;
    border: none;
}

/* ⚠ (0,3,2) で .field input:focus (0,2,1) に勝つ。箱の側が焦点を示すため、
      内側の枠と影を出すと二重になる。 */
.field .tag-editor input[type="text"]:focus {
    outline: none;
    border: none;
    box-shadow: none;
}

/* ⚠ 姿は §24 の .post-tags a に揃える。同じものが場所によって別に見えない
      ようにする。右端だけ詰めるのは外す押しどころを収めるためである。 */
.tag-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
    padding: 2px 4px 2px 12px;
    border: 1px solid var(--border-strong);
    border-radius: var(--r-pill);
    color: var(--fg-muted);
    font-size: 0.8125rem;
    line-height: 1.8;
}

.tag-chip__remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 1.5rem;
    block-size: 1.5rem;
    padding: 0;
    font: inherit;
    /* ⚠ 図の大きさを font-size で稼がない（2026-09-10 / Q44 決着）。
       字形をやめ SVG へ移したため、寸法は下の .icon の規則が持つ。
       ⚠ 箱（1.5rem）は変えない。押しどころの寸法と図の大きさを分けたまま保つ
          （Q44 論点3）。 */
    line-height: 1;
    border: none;
    border-radius: var(--r-pill);
    color: inherit;
    cursor: pointer;
}

/* ⚠ 色だけで示す。§24 のホバーと同じ値であり新しい対比を作らない。 */
.tag-chip__remove:hover {
    color: var(--accent);
}

/* ⚠ 図の寸法を箱と別に持つ（2026-09-10 / Q44 論点3）。Icon は 1em で出るため、
      .tag-chip の 0.8125rem をそのまま継ぐと 1.5rem の箱の中で小さく見える。
   ⚠ 塗りを宣言しない。地と面の対を増やすと contrast.test.ts の名簿に触れる
      （ADR-0025）。色は currentColor のままである。 */
.tag-chip__remove .icon {
    inline-size: .875rem;
    block-size: .875rem;
}

/* ---------------------------------------------------------------
   27. タグと操作帯の隙（2026-09-08）

   タグの下端から罫線まで 56px、罫線から共有ボタンまで 16px で
   3.5 倍の非対称だった。上を 24px へ落として釣り合わせる。
     .post-tags の margin-bottom  8px（§24）
     article の padding-bottom   16px（§5）
     .post-actions の margin-top 32px（§17）  <- ここを 0 にする
   ⚠ article は padding-block を持つ。.post-tags の下マージンは article の
      外へ抜けず相殺もしない。3 段が素直に足し算になる（2026-09-08 実測）。
   ⚠ 隣接セレクタ .post-tags + .post-actions は使えない。前者は article の
      中に、後者は article の兄弟に在る（PostDetail.tsx 実測）。一度この形で
      書こうとして破棄した。同じ誤りを繰り返さないために残す。
   ⚠ §17 の .post-actions を書き換えない。あちらはタグの無い記事にも掛かり、
      そこは本文が直に帯へ続くため 48px のままでよい。
   ⚠ §24 の .post-tags の margin も触らない。あちらは 2026-09-08 に
      24px から落とした値であり、目的が別である。
   ⚠ (0,2,1) で .post-actions (0,1,0) に勝つ。記述順に依存しない。
   ⚠ 結合子の前後に空白を入れない。この綴りは article+article や
      .cards>article と同じ書き方に揃えたものである。
   ⚠ 狭すぎたら var(--sp-2) で 32px へ戻す。直値は書かない。
   --------------------------------------------------------------- */
article:has(.post-tags)+.post-actions {
    margin-top: 0;
}

/* ---------------------------------------------------------------
   28. .meta の中の外部リンク（2026-09-08）

   公開URL とプレビューに外部リンクの記号を添えた。記号が本文から
   離れて折り返さないよう、リンク自体を inline-flex で組む。
   ⚠ .footer-links a と同じ組み方に揃えてある。別の形を持ち込まない。
   ⚠ .meta code は overflow-wrap: anywhere を持つ。長い URL はリンクの
      中で折り返す。記号だけが次行へ落ちないよう align-items は
      baseline ではなく center にする。
   ⚠ 直値を書かない。--sp-1 が既に在る（.meta-date と同じ値）。
   --------------------------------------------------------------- */
.meta-link {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-1);
}

/* ---------------------------------------------------------------
   29. 図を持つボタンの間隔（2026-09-11）

   図を足したボタンで、図と文字が接して見えた。原因は寸法ではない。
   間隔の持ち主は flex の gap であり、それを持つのは inline-flex の規則だけ
   である。a.nav-cta（投稿する）と .brand と .theme-option__name は持ち、
   §6 の .actions button と §21 の検索のボタンは持たない。

   ⚠ 文字列の空白で空けない。JSX は要素の間の改行を落とすため、書式を
      整えた日に詰まる（.theme-option__name の注記と同じ理由）。
   ⚠ Icon の側に余白を持たせない。呼び出しは多数あり、.brand や .share__*
      など図が単独の箇所に不要な余白が付く。それらは既に gap で解いており
      二重になる（.footer-links a の注記と同じ理由）。
   ⚠ 既存の規則へ宣言を足さない。§6 の共通形は .comment-delete と
      .form-page を同居させ、§21 は窓と 1 本で高さを揃えている。どちらも
      別の目的の検査が形そのものを見ている（§23 が .actions a.secondary を
      避けたのと同型）。
   ⚠ :has(.icon) で絞る。図を持たないボタンへ inline-flex を及ぼさない。
      図を足した日に自動で揃い、外した日に自動で戻る。名簿を持たずに済む。
   ⚠ 値を新しく作らない。--sp-2 は .nav-cta と .brand と
      .theme-option__name と .btn-google が既に使う間隔である。
   ⚠ 塗りも枠も宣言しない。ADR-0025 の地と面の対に触れず、
      contrast.test.ts の名簿も動かない。
   ⚠ 下線を宣言しない。text-decoration: none を書くと css.test.ts の員数
      （12 本）が赤くなる。a.secondary の分は §6 が既に持つ。
   ⚠ 特異度で勝つ。.actions button:has(.icon) は (0,2,1) であり
      .actions button (0,1,1) に勝つ。記述順に依存しない。
   ⚠ .actions a.secondary は上の 3 宣言を既に持つ。1 本にまとめて置く。
      分けて書くと、間隔の持ち主が 2 か所になる（D97 と同型）。
   --------------------------------------------------------------- */
.form-page button[type="submit"]:has(.icon),
.actions button:has(.icon),
.actions a.secondary:has(.icon),
.search-form button[type="submit"]:has(.icon) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
}

/* ---------------------------------------------------------------
   30. 商標の図（2026-09-11 / ADR-0040）

   ⚠ 塗りも枠も宣言しない（決定4）。地と面の対を 1 つ増やすと
      contrast.test.ts の「面を敷く全件が名簿に載っている」に触れる。
   ⚠ 新しいトークンを :root へ足さない。--sp-3 と既存の 16 進だけを使う。
   ⚠ 断点を増やさない。押しどころは幅に依らず 2.75rem を持つ。
   ⚠ .meta へ入れない。あちらは baseline の 1 行であり 2rem の図が載らない。
   --------------------------------------------------------------- */
.brand-marks {
    display: flex;
    align-items: center;
    /* ⚠ 折り返す。375px でハンドルが 2 つ並ぶと 1 行に収まらない
       （2026-09-11 / 決定8）。⚠ 断点は増やさない */
    flex-wrap: wrap;
    gap: var(--sp-1) var(--sp-3);
    /* ⚠ カードの末尾に来る。下の余白を持たない（.item-actions と同じ理由） */
    margin: var(--sp-3) 0 0;
}

/* ⚠ 押しどころの寸法と図の大きさを分けて持つ（.tag-chip__remove と同型）。
   ⚠ 13 本目の「下線を持たない規則」である。css.test.ts が員数と所在を
      対で持つ。ここを消す日は向こうの 2 か所も直す。 */
.brand-marks a {
    /* ⚠ 図と文字の組み方は §4 の .footer-links a に揃える。あちらが既に
       解いており、別の流儀を持ち込まない（2026-09-11 / 決定8）。 */
    display: inline-flex;
    align-items: center;
    /* ⚠ 間隔を文字列の空白で空けない。JSX は要素の間の改行を落とす */
    gap: var(--sp-1);
    /* ⚠ 幅の下限を外した。文字が入るため 2.75rem に足りる。高さは残す */
    min-block-size: 2.75rem;
    font-size: var(--fs-sm);
    text-decoration: none;
}

/* ⚠ 2rem は決定2 である。Instagram の最小規定（29px）を上回る。
   ⚠ X の資産は 1200x1227 であり正方形ではない。preserveAspectRatio の
      既定で歪まずに収まり、上下がわずかに余る。縦横比を触らない。 */
.brand-mark {
    flex: 0 0 auto;
    inline-size: 2rem;
    block-size: 2rem;
}

/* --- X の 2 色の切り替え（決定3）-----------------------------------------
   ⚠ data-tone はインクの色ではなく「どの地の上で使うか」である。
      light が持つのは黒の資産である。名前から色を読まない。
   ⚠ 4 テーマすべてに置く。1 つ欠けるとその配色でだけ黒と白が並ぶ。
   ⚠ 特異度で勝たせる。素の (0,2,0) にテーマ付きの (0,3,0) と (1,3,0) が
      勝つ。記述順に依存しない。 */
.brand-mark[data-tone="dark"] {
    display: none;
}

:root[data-theme="dark"] .brand-mark[data-tone="light"],
:root:has(#theme-dark:checked) .brand-mark[data-tone="light"] {
    display: none;
}

:root[data-theme="dark"] .brand-mark[data-tone="dark"],
:root:has(#theme-dark:checked) .brand-mark[data-tone="dark"] {
    display: block;
}

:root:has(#theme-light:checked) .brand-mark[data-tone="light"] {
    display: block;
}

:root:has(#theme-light:checked) .brand-mark[data-tone="dark"] {
    display: none;
}

/* --- Instagram の色（Q45 決着 / 2026-09-11）-------------------------------
   案b を --fg で採った。⚠ 単色のグリフは黒か白に準じる色で置く。
   currentColor のままだと a の色を継ぎ、アクセントの青で商標を塗ることに
   なる。決定3 が X で避けた再着色と同じ性質である。
   ⚠ 16 進のみを使う。訪問済みでは var() が解決しない（§10 冒頭）。
   ⚠ 値は .share__x と同一である。新しい対比を作らない。
   ⚠ 4 テーマ × 3 状態を置く。contrast.test.ts が 4 テーマ分の宣言を求め、
      表に無いものを別の it で落とす。
   ⚠ X はこの色を受けない。資産が fill を自身の属性で持つ。 */
.brand-marks a,
.brand-marks a:visited,
.brand-marks a:hover {
    color: #16202e;
}

:root[data-theme="dark"] .brand-marks a,
:root[data-theme="dark"] .brand-marks a:visited,
:root[data-theme="dark"] .brand-marks a:hover,
:root:has(#theme-dark:checked) .brand-marks a,
:root:has(#theme-dark:checked) .brand-marks a:visited,
:root:has(#theme-dark:checked) .brand-marks a:hover {
    color: #e6edf6;
}

:root:has(#theme-light:checked) .brand-marks a,
:root:has(#theme-light:checked) .brand-marks a:visited,
:root:has(#theme-light:checked) .brand-marks a:hover {
    color: #16202e;
}
