/* ============================================================
   このファイルは生成物です。直接編集しないでください。
   正典: parts/<name>/part.css  ／ 連結順: parts/manifest.json
   再生成: node tools/build.mjs
   ============================================================ */
/* ============================================================
   smuto-ui スターター
   ------------------------------------------------------------
   この1枚が移植の実体。別プロジェクトへ持って行くときは
   ① :root の -raw 4色だけ差し替える（派生には触らない）
   ② 要らない部品の節を消す

   規約（この CSS 自身も守っている）:
   ・margin / padding は4値で書く
   ・縦の余白は margin-bottom（margin-top / padding-top を使わない）
   ・角丸は 4px（円 50% と、明示採用したピル 999px だけ例外）
   ・!important を使わない
   ・状態は data-* / modifier（is-* を使わない）
   ・色だけ CSS 変数。寸法は px 直値
============================================================ */

/* ---- 基礎 ---- */
* { box-sizing: border-box; }
html, body { margin: 0px 0px 0px 0px; padding: 0px 0px 0px 0px; }
body {
  background: var(--bg); color: var(--ink);
  font-family: var(--font); font-size: 16px; line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}
html[data-preload] * { transition: none; }
h1, h2, h3, p, ul, li, dl, dd { margin: 0px 0px 0px 0px; padding: 0px 0px 0px 0px; }
ul { list-style: none; }
code { font-family: var(--mono); font-size: 14px; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
a { color: inherit; text-decoration: none; }
/* **`hidden` を必ず効かせる。** ブラウザの既定は `[hidden] { display: none }` だが、
   これは弱い規則なので、こちらが `display` を書いた瞬間に負ける ――
   実際 `.btn { display: inline-flex }` が勝って、`<button class="btn" hidden>` が
   出たままだった（モーダルの 3 つ目の釦が、渡していない画面でも並んでいた）。

   **`!important` は使わない**（基本規約 4）。代わりに `html` を前に置いて詳しさを
   1 つ上げる ―― (0,1,1) となり、単独クラスの `display`（0,1,0）に必ず勝つ。
   順番にも依存しない（土台はいちばん先に読まれるので、後勝ちには頼れない）。 */
html [hidden] { display: none; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 動きを抑える設定の上書きは **reduced-motion パーツが 1 か所で持つ**（連結の最後）。
   ここに書くと、あとから読む `scroll-behavior: smooth` に打ち消される
   ―― メディアクエリは詳しさを足さないので、同じ詳しさなら後に読んだほうが勝つ。 */
.app-icon { width: 20px; height: 20px; flex-shrink: 0; fill: currentColor; }

/* ---- 送りは滑らせる ----
   ページ自体は送らないので、`html` ではなく**送る枠のそれぞれ**に付ける。
   `html { scroll-behavior: smooth }` だけでは中の枠に効かない（実際に効かなかった）。
   アンカー移動・`scrollIntoView`・キーボードの PageUp/Down がまとめて滑らかになる。 */
html,
.site-main,
.nav-panel,
.data-table__scroll,
.side-panel__body { scroll-behavior: smooth; }

/* ---- スクロールバー（全体共通・ここ 1 か所で決める）----
   **細い棒を出す。**

   かつては `* { scrollbar-width: none }` で全部消し、縁のぼかし（`data-more`）だけで
   「まだ続く」を示していた。**戻した。** 理由は 3 つ、どれも実測:

     ・**ぼかしが付く枠は 7 種だけ**（part.js の `SEL`）で、それ以外は棒も合図も無かった。
       実測（ある配備先の詳細画面）: `.site-main__flush` が縦に送れるのに `data-more` なし・
       棒 0px、`.card-strip` が横に送れて同じく何も無し
     ・**横に送れる枠には合図が無い。** `data-more` は上下しか持っていない
     ・ぼかしは「まだ続く」しか言わない。**どこに居るか・どれだけ残っているか**は
       言えないし、掴んで動かせない

   消した理由は「行が数件しか無くても棒が立って表の一部に見える」だったが、
   送る枠はすべて `overflow: auto`（`scroll` は 1 つも無い）―― 中身が溢れたときしか
   立たない。**前提のほうが間違っていた。**

   ぼかしは残す。棒と役目が違う（棒＝位置と量／ぼかし＝続きの向き）。
   ナビの面（サイドバー・パネル・ツリー）だけは各パーツが自分で消している ――
   あそこは行が下線で区切られていて、縦の棒が「もう 1 本の罫」に見えるため。

   色は `--hairline-strong`（罫と同じ濃さ）。**新しい色を作らない。**
   角丸 4px は「面を持つもの」の値と同じ ―― 例外を作らない。 */
/* OS 既定の棒は太い帯で、罫線・角丸とぶつかって「表やパネルの一部」に見える。
   **細い線にして、つまみだけがうっすら見える形**にそろえる ―― 見せかけの太さは
   `background-clip: padding-box` ＋ 透明な 2px の枠で作る（8px の場所に 4px の線）。
   **この形はこの skill の最初の版から変えていない。** 太さ・角丸・色をここで 1 回だけ決める。

   **`*` には掛けない。** 全要素に配ると、Chrome が**紙に刷るときに表の中身を
   1 行も描かなくなった**（実測: PDF に出る行が 2 → 0。webkit 側の指定だけなら起きない）。
   「場所ごとに書き分けない」という元の決めは**見た目のこと**なので、
   当てる相手を名指ししても崩れない ―― 見た目は 1 か所のままにしてある。

   **当てるのは「追従する見出しを内側に持たない枠」だけ。**
   `.site-main`（`.page-head--sticky` が貼り付く）・`.site-main__flush`（見出しを外に出して本文だけ送る器）・
   `.data-table__scroll`（見出しは別表で残る）は
   ブラウザの棒を消し、**幅を食わない棒を自分で描く**（parts/scroll-bar）――
   ブラウザの棒は 10px の幅を食い、列をそろえるために見出し側にも同じ空きが要るため。
   ナビの面（サイドバー・パネル・ツリー）も各パーツが自分で消している ――
   あそこは行が下線で区切られていて、縦の棒が「もう 1 本の罫」に見えるため。

   【2026-09-12】**送る枠を 4 つ足した**（`.page__body` / `.list-scroll` / `.drawer__body` / `.sp-drawer`）。
   名指しの列に入っていなかったので、この 4 つだけ **OS 既定の太い帯**が出ていた ――
   配備先の実測で、本文を送る `.page__body` が 27 画面・カードの一覧 `.list-scroll` が 7 画面。
   いちばんよく見る枠が、細い棒（重ね物・入力欄）とも自前の棒（本文・表）とも違う
   3 つめの姿になっていた。**当てる相手を名指しにした代償**がここで出た形なので、
   送る枠を足したら必ずこの列にも足す。
   4 つとも**内側に貼り付く見出しを持たない**（`.page-head--sticky` は `.page__body` の
   兄弟で、送る枠の中では `position: static` に戻る）ので、自前の棒ではなく細い棒の側。

   `.sp-drawer` はナビの面だが、**消す側ではなく細い棒の側**に入れる ―― 消してよいのは
   「送れることが形から自明な場所」で、☰ の中身は節の数で丈が変わり、
   縁のぼかし（`data-more`）も付いていない。棒を消すと「まだ下に続く」合図が 1 つも無くなる。 */
.side-panel__body::-webkit-scrollbar,
.drawer__body::-webkit-scrollbar,
.sp-drawer::-webkit-scrollbar,
.modal__body::-webkit-scrollbar,
.page__body::-webkit-scrollbar,
.list-scroll::-webkit-scrollbar,
pre::-webkit-scrollbar,
textarea::-webkit-scrollbar { width: 8px; height: 8px; }
.side-panel__body::-webkit-scrollbar-track,
.drawer__body::-webkit-scrollbar-track,
.sp-drawer::-webkit-scrollbar-track,
.modal__body::-webkit-scrollbar-track,
.page__body::-webkit-scrollbar-track,
.list-scroll::-webkit-scrollbar-track,
pre::-webkit-scrollbar-track,
textarea::-webkit-scrollbar-track { background-color: transparent; }
.side-panel__body::-webkit-scrollbar-thumb,
.drawer__body::-webkit-scrollbar-thumb,
.sp-drawer::-webkit-scrollbar-thumb,
.modal__body::-webkit-scrollbar-thumb,
.page__body::-webkit-scrollbar-thumb,
.list-scroll::-webkit-scrollbar-thumb,
pre::-webkit-scrollbar-thumb,
textarea::-webkit-scrollbar-thumb {
  border-radius: 4px;                                           /* 角丸は全体で 4px */
  background-color: var(--hairline-strong);
  background-clip: padding-box;              /* 枠に貼り付いて見えないよう余白を作る */
  border: 2px solid transparent;
}
/* **枠の中にポインタがある間だけ**強める ―― つまみ自体に載せたときではない。
   どこを送っているかが、つまみを探す前に分かる。 */
.side-panel__body:hover::-webkit-scrollbar-thumb,
.drawer__body:hover::-webkit-scrollbar-thumb,
.sp-drawer:hover::-webkit-scrollbar-thumb,
.modal__body:hover::-webkit-scrollbar-thumb,
.page__body:hover::-webkit-scrollbar-thumb,
.list-scroll:hover::-webkit-scrollbar-thumb,
pre:hover::-webkit-scrollbar-thumb,
textarea:hover::-webkit-scrollbar-thumb {
  background-color: color-mix(in srgb, var(--ink) 28%, transparent);
  background-clip: padding-box;
}

/* ---- Firefox だけ、標準のプロパティで近づける ----
   **`scrollbar-width` / `scrollbar-color` を素で書いてはいけない。**
   Chrome 121 以降は、この 2 つのどちらかが指定されていると
   **`::-webkit-scrollbar` の指定をまるごと無視する**（相互排他になった）。
   素で書いていた頃は、上で 8px の場所に 4px の線を描いているのに、
   実際に出ていたのは**ブラウザ既定の thin（実測 10px・Linux では矢印付き）**だった
   ―― 太さも角丸も効かず、「1 か所で決める」はずの姿が Chrome だけ別物になっていた
   （実測 2026-09-12。`offsetWidth - clientWidth` が 8px ではなく 10px）。

   そこで **`::-webkit-scrollbar` を持たないブラウザにだけ**当てる。
   Firefox は疑似要素を持たないので `selector(::-webkit-scrollbar)` が偽になり、ここが効く。
   Chromium / WebKit は真なので**この節を読まず**、上の自前の形がそのまま出る。
   近似なのは承知のうえ ―― Firefox には 4px の線を描く手段が無い。 */
@supports not selector(::-webkit-scrollbar) {
  .side-panel__body,
  .drawer__body,
  .sp-drawer,
  .modal__body,
  .page__body,
  .list-scroll,
  pre,
  textarea {
    scrollbar-width: thin;
    scrollbar-color: var(--hairline-strong) transparent;
  }
}

/* 追従する見出しを抱えている枠。ブラウザの棒は消し、parts/scroll-bar が上に浮かせて描く */
.site-main,
.site-main__flush,
.data-table__scroll {
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.site-main::-webkit-scrollbar,
.site-main__flush::-webkit-scrollbar,
.data-table__scroll::-webkit-scrollbar { width: 0px; height: 0px; }

/* 続きのある側だけ薄れる。両側にあるときは上下とも。 */
[data-more="down"] { mask-image: linear-gradient(to bottom, #000000 calc(100% - 24px), transparent 100%); }
[data-more="up"] { mask-image: linear-gradient(to bottom, transparent 0px, #000000 24px); }
[data-more="both"] { mask-image: linear-gradient(to bottom, transparent 0px, #000000 24px, #000000 calc(100% - 24px), transparent 100%); }

/* ---- トークン（この skill の配色の正典。式ごと写す）----
   色の値を書いてよいのはここだけ。ほかは var(--…) しか書かない。
   使う色は絞る。緑は使わない ――
   完了の印も「良い」ではなく「そうなっている」状態なのでアクセントの青。 */
:root {
  color-scheme: light;   /* 地が白でないので明示する。既定のままだと OS の選択欄・日付欄だけ白く出る */

  /* ---- 土台の 3 色 ＋ アクセント（利用者が触れるのはこれだけ）----
     **ライトは白にしない。** 真っ白は面積が大きいぶん眩しく、長く見ていられない。
     決め方は 2 つの数で、どちらを外しても苦情になる（実際に両方やった）。
       明るさ … 白 1.000 に対し **0.858**
       黄み（R-B の差）… **26**（紙として読ませる面はここまで振ってよい）
     実在するライトモードの黄みは Claude.ai 5〜10 / Notion 4 / Readwise セピア 13 / iA Writer 2。
     器（この --bg）はそれより濃くてよいが、**本文と箱はそこから明るい側へ離す**（下の 3 段）。

     **一度 #faf3e0（明るさ 0.898）から 2% 落とした。** 「ライトが明るすぎる」ため。
     落としたのは器と本文と縞の 3 つで、箱（白）は動かさない ―― 読む面がいちばん
     明るい、という段の意味を保つ。結果、箱と器の差が 1.108 → 1.158 に開いて
     白い箱の輪郭がむしろ見やすくなった（字は 13.79 → 13.20:1 で AAA のまま）。 */
  --bg-raw: #f5eedb;      /* 器（ヘッダー・サイドバー・レール・下帯）のクリーム */
  --ink-raw: #1c2b36;     /* 字。紙を温めるぶん、字は青みの紺黒にして締める */
  --line-raw: #d8e0e6;    /* 罫。紺を 16% 白に重ねた色 */
  --accent-raw: #0a3d62;  /* 紺。字・リンク・釦。白地で 11.3:1 */

  --bg: var(--bg-raw);
  --ink: var(--ink-raw);
  --line: var(--line-raw);
  /* ---- 面の 3 段。**ライトとダークで割り当てを同じにする** ----
       器   --bg      … ページの外枠（ヘッダー・サイドバー・レール・下帯）
       面   --surface … 器の上に置く箱（カード・表の枠・右から出る枠・図）
       沈み --sunken  … 面の**中**に置く注記・吹き出し・読ませる枠
     ライトだけ「器と箱を同色にして本文を沈める」形にすると、テーマを切り替えたときに
     **どこにどの色が乗るかが入れ替わって見える**（実際そうなった）。
     読む面をいちばん明るくし、その周りを色で囲うのがこの並びの意図。 */
  --surface: #ffffff;            /* 箱。器より明るい */
  /* **どのパーツも読んでいないが、消さない。** 配備先が使う（実測: ある配備先の
     app.css が 4 箇所）。skill は「面の段」を配る側なので、段そのものを持つ。 */
  --sunken: var(--bg);           /* 箱の中に沈めるもの。器と同じ高さまで落とす */
  /* 本文の面。**器と箱のちょうど真ん中**（明るさ 0.898 → 0.949 → 1.000 の等間隔）。
     ここを白にすると白い箱が白い地に溶けて輪郭が消える。 */
  --main-face: #f7f4ed;
  /* 側面（レール・パネル）の地。**器よりさらに一段濃くする。**
     器（#f5eedb）のままだと本文の面（#f7f4ed）との差が 1.05:1 しかなく、
     境目が罫線だけになって「同じ面が続いている」ように見えた（実測）。
     字を 7% 混ぜて #e6e0cf、本文との差 1.20:1。字との差は 11.0:1 でまだ十分。 */
  /* 側面（左のサイドバー・右のレール）の面。器よりほんの少し濃くして、
     本文（--main-face）との境目を色で示す ―― 罫 1 本より柱として読める。
     【2026-09-10】ここを主色の紺にして「濃い柱＋明るい本文」を試した。**戻した。**
     素の金が 5.38:1 で読めるようになる代わりに、**柱に敷いた写真が紺の膜ごしになり
     青一色に染まった**（富士山が青くなった）。本番で動いている姿と別物になる。
     選択の金は本番と同じ素の金のまま、地はクリームへ戻す
     ―― 金は「どれが今の場所か」を探す手がかりで、読むための色ではない
     （読む字は --ink / --sub / --mute で、そちらは AA を満たす）。 */
  --rail-face: var(--bg);
  /* 伸びたレール（本文の上へ出る部分）のすりガラス。柱の色から作るので、
     柱の地を変えても伸びた先と色が割れない。 */
  --rail-material: color-mix(in srgb, var(--rail-face) 88%, transparent);
  --border-strong: var(--ink);   /* 構造の仕切りは文字色と同じ濃さ */
  --sub: color-mix(in srgb, var(--ink) 82%, var(--bg));
  --grey: color-mix(in srgb, var(--ink) 74%, var(--bg));
  --mute: color-mix(in srgb, var(--ink) 70%, var(--bg));
  /* 表の**見出し帯**。列の名前を載せる帯なので、行の縞よりは存在感を持たせる。
     器のクリームと同じ高さ（白い表との差 0.10）。ここを濃くすると表全体が重くなる。 */
  --shadow: color-mix(in srgb, var(--ink) 14%, transparent);
  /* 厚手のガラス。重ね物（小窓・右から出る枠）の面はこれ。**不透明な板にしない**
     ―― 地が枠のところだけ切れて「板が 1 枚貼ってある」ように見える。
     **器の色から作る。** 面（白）から作ると、白い本文の上に乗ったとき境目が消える。 */
  --material-thick: color-mix(in srgb, var(--bg) 88%, transparent);
  --hairline: color-mix(in srgb, var(--ink) 14%, transparent);
  /* 構造の仕切り。**白地で 2.5:1 前後まで濃くする。**
     26%（1.7:1）だと、白い本文の上に置いた白い箱の輪郭が見えない。
     本文の中の箱に影は落とさない（影は浮くものだけ）ので、見せるのはこの罫 1 本。 */
  --hairline-strong: color-mix(in srgb, var(--ink) 45%, transparent);
  --accent: var(--accent-raw);
  --accent-soft: color-mix(in srgb, var(--accent) 12%, transparent);
  --warn: #b93131;
  --success: var(--accent);      /* 緑は使わない */

  /* ---- 金 ----
     **紺は字、金は飾り**と役割で分ける。金は白地で 2.10:1 しか無いので字にできない。
     出る所は 足元の帯・伸びる下線／立つ棒・レールの絵・行に載せたときの地 の 4 つだけ。
     「載せたとき」と「選ばれているとき」を**同じ金**にする ―― 分けると、
     指しているのか選んであるのかを色で見分けられなくなる。 */
  --gold: #d4af37;
  /* ---- カーソルの下の地 ----
     **金で薄く染める。** 一度「染めずに、いちばん明るい面（箱の白）まで**明るくする**だけ」
     にして戻した。あれは行が本文の地の上に乗っていた頃の作りで、表の枠が面（--surface＝白）を
     敷いた今は**持ち上げる先が無い** ―― 白い行に載せても何も変わらず、枠だけが出ていた（実測）。

     金 24% は白の上で 1.181:1、縞（#f4efdf）に対して 1.147:1。**縞の行でも素の行でも同じ色になる**
     ―― 半透明なので `td` の地を置き換えると枠の白が透ける。どの行に載せても見え方が変わらない。
     青（--accent）で染めない。青は「押せる」「選ばれている」の色で、通りがかりの色ではない
     ―― そこは変えていない。金は飾りの色なので、通りがかりに使える。 */
  --hover-face: color-mix(in srgb, var(--gold) 24%, transparent);
  /* 載せたときに出る枠。**面と同じ色で 1 つの仕草にする。**
     `--border-strong`（＝ほぼ黒）で 14.5:1 まで出していたのをやめた ―― 面が色を持つように
     なったので、そこへ黒い枠を重ねると「枠が主役の行」が 1 本だけ現れて重い。
     ダークは面を明るくするだけなので、あちらは従来どおり枠が受け持つ（下）。 */
  --hover-line: var(--select-ink);   /* 載せたときの線も状態の色（金を 2 種類に割らない）*/

  /* ---- テーマで入れ替わる面。**規則は 1 本、値だけ 2 通り** ----
     ライトの作り（器＝クリーム／本文＝薄いクリーム／箱＝白／縞と金の帯）は
     ダークには持ち込まない。規則を書き分けると同じ指定が 2 か所に散るので、値で切る。 */
  --panel-face: var(--bg);       /* 小窓・トーストの地 */
  /* 表の 1 行おきの縞。**器（--bg）と同じ明るさまで落とす。**
     #fcf9f1 だった ―― あれは本文の地（--main-face）と同じ段で、表が面（白）を
     敷くようになると白との差が **1.052:1**（青 1 階調）しか無く、縞に見えなかった。
     器の高さ（黄み 21）まで落とすと **1.158:1**。新しい段は作らず、
     すでにある 3 段（器 0.898 / 本文 0.949 / 箱 1.000）の**いちばん下**を使う。 */
  /* **名前は 1 つ。** かつて `--zebra` も宣言してあって、解説（data-table.md）は
     あちらを教えていた ―― 実体は `--stripe` なので、解説どおりに書いても縞は出ない。
     使われないほうを消す。 */
  --stripe: #f4efdf;
  --band-face: var(--gold);      /* 下帯 */
  /* 下帯に乗る字。**白は使えない** ―― 金の帯（#d4af37）の上で 2.1:1 しか無く、
     AA を大きく割っていた（実測。bin/check-contrast.py）。字の色をそのまま乗せると 6.9:1。
     「帯だから白字」は塗りが濃い前提の癖で、この金は明るい。 */
  --band-ink: var(--ink);
  /* **線と図形に使う金。** `--gold` そのままだとクリームの上で **1.82:1** しかなく、
     図形の下限（3:1）を大きく割る ―― 飾りの下線は「見えなくてもいい飾り」だから
     それでよいが、**枠と絵は「そこに何かある」を伝える仕事**なので届かせる。
     ダークでは `--gold` が `--accent` に戻るので、そちらは既定の明るさで足りる。

     【2026-09-10】#a1852a から #8f7625 へ。**測った地がクリーム 1 種だけだった。**
     この色がいちばん使われるのは右レールの絵で、そこの地はクリームではなく
     **側面の面**（--rail-face・実測 (221,214,203)）―― そこでは 2.47:1 で割れていた。
     4 つの地すべてで測り直した: 器 3.79 / 本文 3.99 / 面 4.39 / **側面 3.04**。
     （地を 1 種類しか見ずに色を決めて割ったのは 2 度目。1 度目は白地だけ見て暗い地の白字を潰した） */
  --gold-line: #8f7625;
  /* **選ばれているものの字の色。** ライトは金、ダークはキーカラーの青。
     「選択＝アクセント（紺）」にしていたが、**この UI で選択が金に見えるのは
     ライトのときだけ**という指摘が 3 回続いた。金は飾りではなく状態の色として使う。

     ただし `--gold`（#d4af37）そのままは地の上で 1.46〜2.10:1 ―― **字としては読めない**。
     色相と彩度はそのままに明度だけ落として #6e5b1c、4 つの地すべてで 4.58:1 以上
     （器 5.71 / 本文 6.02 / 面 6.61 / 側面 4.58）。金の系統は残る。
     状態は色だけで示していない（下線が伸びる）ので、色は読めるほうを取る。 */
  /* **選ばれているものの色は素の金**（明るいとき）／キーカラーの青（暗いとき）。
     節の名前・選んだ項目・伸びる下線・立つ棒・載せたときの線が、全部この 1 色。

     【2026-09-10】ここは 3 度動かした: #6e5b1c（4.62:1）→ #8f7625（3.07:1）→ 素の金。
     **明るい地の上に「明るい金の字」は物理的に置けない** ―― 実測で、地
     (221,215,205) の上で 4.5:1 を満たす金の上限は #6e5b1c で、これは茶に見える。
     素の金は **1.47:1**（字の下限 4.5 も図形の下限 3.0 も満たさない）。

     それでもこちらを採ったのは、**色だけで状態を示していない**から ――
     選んでいる項目は下線が伸び、レールの行は棒が立ち、節の名前は位置で分かる。
     色は「どれが今の場所か」を**探すための手がかり**で、読むための色ではない。
     読む字（本文・説明・表）は --ink / --sub / --mute で、そちらは AA を満たす。
     戻すなら #8f7625（3.07:1・図形の下限は満たす）か #6e5b1c（4.62:1・茶に見える）。 */
  --select-ink: var(--gold);
  /* ---- 右レールの釦（枠と絵を別の色にする）----
     **枠は構造の色、絵は飾りの色。** 枠まで飾り色にすると、四角ごと飾りに見えて
     「押せるもの」に見えなくなる ―― 枠は仕切りと同じ濃さ、中の絵だけが飾り色。
     ライト: 枠は字の色＝黒（12.52:1）／絵は濃い金（3.07:1）。
     ダーク: 枠は字の色＝白（12.74:1）／絵は青（6.4:1）。
     **`--border-strong` ではなく `--ink` を使う。** 仕切りの色は暗いところでは
     字より薄い灰（#e8eaed 26% 混ぜ）で、白にならなかった ―― ここは「枠をはっきり
     見せる」場所なので、字と同じ濃さを取る。 */
  /* 枠は字の色を**薄めて**使う。字そのままだと線が主役になり、四角ばかりが目に入った。
     60% で 3.83:1 ―― 図形の下限（3:1）は超えたまま、線としては引っ込む（実測）。 */
  --rail-btn-line: color-mix(in srgb, var(--ink) 60%, transparent);
  /* 柱が濃くなったので、絵も**状態の色**（素の金）にする。罫用の暗い金（--gold-line）は
     明るいクリームの上で 3:1 を作るための色で、濃い紺の上では逆に沈む（実測 1.9:1）。 */
  --rail-btn-ink: var(--select-ink);
  --band-border: 0px;            /* 帯を塗るので上の罫は要らない */
  --rail-fill: none;             /* レールの釦に塗りを滑らせない（枠の色で 3 段階を出す） */
  /* 塗りが滑ってきたとき、その上に乗る絵の色。**ライトは塗らないので飾り色のまま。** */
  /* 【2026-09-10】`var(--gold)` だった。**塗りは滑らせない**（--rail-fill: none）と
     決めたのに、絵の色だけ「塗りの上に乗る前提」で残っていた ―― 素の金は側面の面の上で
     **1.46:1** で、図形の下限 3:1 を大きく割る。塗らないのだから枠と同じ濃さの金を使う。 */
  --rail-fill-ink: var(--select-ink);
  /* 釦の**押す前**の地。ホバーで初めて色が付くと、押そうとした時点でしか「押せる」と分からない。
     ごく薄い**無彩**にする ―― 自分の色（赤・青）で塗ると、赤い釦が並んだときその行だけ
     警告が鳴っているように見えるし、字とのコントラストも削る。自分の色はホバーで初めて出す。
     **ライトだけ。** ダークは地が暗く、赤の字が塗る前から 4.67:1 しか無いので、
     どんな塗りを乗せても AA を割る（実測）。あちらは枠と字だけで足りている。 */
  /* **釦の地は「自分の色」で敷く。** ここは一度ひっくり返している ――
     長らく「自分の色では塗らない（無彩のごく薄い地だけ）」だった。理由は
     「赤い釦が並ぶと、その行だけ警告が鳴っているように見える」「字とのコントラストを削る」。
     そのあと 5% の無彩 → 白（--surface）まで上げたが、**まだ地味だという判断**で
     自分の色に替えた。決めたのは作者。

     **式は 1 つで足りる。** 混ぜる相手を `currentColor` にすると、青の釦は青の、
     赤の釦は赤の、中立は字の色の地になる ―― 種類ごとにトークンを増やさない
     （一度 --btn-face-primary / --btn-face-danger と 3 つに分けて、これに畳んだ）。
     同じ式を状態の札（.tag）でも使う。

     **薄さは 10% 止まり。** 字は同じ色の濃いほうを載せるので、地が濃くなるほど
     字が沈む。器（--surface）に混ぜて**必ず不透明**にする ――
     透過だと、下に何が来るかで濃さが変わって釦ごとに違う地になる。

     **ダークは塗らない。** 地が暗く、赤の字が塗る前から 4.67:1 しか無いので、
     どんな塗りを乗せても AA を割る（実測）。あちらは枠と字だけで足りている。 */
  --btn-face: color-mix(in srgb, currentColor 10%, var(--surface));

  /* 補助の釦（やめる・閉じる・絞り込み・並び替え）の字と枠。
     **ライトは据え置き。** 字を --ink にすると --accent と明るさが 0.02 しか違わず、
     小さな釦で「すすめる操作」と見分けられない（既存の実測）。枠も、地を持つぶん
     --hairline-strong で足りている。
     ダークだけ両方 --ink へ上げる ―― 下のダークのトークン参照。 */
  /* ホバーの地。**ライトは一段濃く**（10% → 18%）。
     休止と同じ式で、混ぜる割合だけ上げる。 */
  --btn-face-hover: color-mix(in srgb, currentColor 18%, var(--surface));
  --btn-ink: var(--grey);
  --btn-line: var(--hairline-strong);

  /* ---- レールとパネルの背面に敷く写真（任意。既定は敷かない）----
     **この skill は絵を持たない。** 敷きかたは parts/rail-image が持ち、
     何を敷くかはホストがここへ入れる: `--rail-image-left: url("...")`。

     **濃さはテーマごとに持つ。同じ % は同じ薄さにならない。**
     一度ライトとダークで共用していて、**ライトだけ写真が消えた**。
     暗幕は写真の明暗の幅を (1-a) 倍に縮めるが、見えるかどうかは縮めた幅ではなく
     **地の明るさとの比**で決まる（Weber）。同じ 92% を実測すると ――
       ライト（地 243）… 写真の残り **15.2%**  ＝ 目には何も無い
       ダーク （地  35）… 写真の残り **143.8%** ＝ 写真がそのまま見える
     ライトは地が明るいぶん、同じ絵を見せるのに**薄い暗幕**が要る。

     **濃さは 1 つ。一度 2 段（絵だけの面／文字が乗る面）に分けて、戻した。**
     分けていたのは「写真を敷いた 56px のレールに文字が無い」ときの話で、
     写真を左の列 1 枚に移した（parts/rail-image）いま、**写真が乗る面はどれも文字を持つ**。
     残った薄いほうの使い手は右レールだけで、そこだけ薄いと**左右で絵の強さが揃わない**
     ―― 実測でダークの右レールだけ残り 85.1%、左の列は 50.0% で、右だけが主張していた。
     どのみち文字が読める濃さが要るのだから、1 つにして左右をそろえる。 */
  --rail-image-left: none;
  --rail-image-right: none;
  /* **暗幕は器の色を運ぶ。** 82% では写真が透けて、レールが (232,222,211) の灰みになり、
     本文の面 (243,241,234) より暗い「灰色の帯」に見えていた ―― 配備先を並べて分かった
     （写真を敷いていない画面ではクリームの帯に見え、敷いた画面だけ灰色だった）。
     **幕は器ではなく側面の色から作る。** 器（--bg）で作っていたとき、側面を一段濃くしても
     幕が上から器の色を塗り直すので**まったく効かなかった**（実測: 面を #e6e0cf にしても
     描かれたのは (239,231,215)）。幕を側面の色にすると、濃さがそのまま出る。
     実測（左レールの平均色 / 本文は (244,241,235)）:
       器 92%     → (239,231,215)  ばらつき 10.5（本文とほぼ同じ明るさ）
       側面 92%   → (225,218,204)  ばらつき 9.7
       側面 86%   → (221,214,203)  ばらつき 10.7  ← 濃さも写真の見えも足りる
       側面 80%   → (218,210,201)  ばらつき 12.1（写真が主役になりはじめる）
     ばらつき＝写真がどれだけ透けているか（大きいほど絵が見える）。 */
  /* 幕の濃さは**本番で動いている値**（82%）。写真の気配が残る濃さで、
     ここを上げると柱が無地の帯に見え、下げると写真が主役になる。 */
  --rail-veil: linear-gradient(color-mix(in srgb, var(--rail-face) 82%, transparent),
                               color-mix(in srgb, var(--rail-face) 82%, transparent));
  /* **右から出るパネルだけ幕を強くする。** 長い文が乗るのはここだけで、
     レールに乗るのは絵と 1 行の名前 ―― 写真のムラは絵の上では気にならないが、
     文の上では行によって読みやすさが変わる（地の平均は 5.79:1 で足りているのに
     「見づらい」という指摘が出たのがこれ）。
     実測（ムラ＝写真がどれだけ透けているか。小さいほど地が静か）:
       86% → ムラ 6.4 ／ 94% → ムラ 4.7 ／ 96% → ムラ 4.5
     94% で写真の気配は残るまま、文の下は静かになる。 */
  /* **柱の色ではなく、パネル自身の面から作る。** 柱を濃い紺にしたとき、これが
     --rail-face を見ていたので**右パネルの地まで紺になり**、その上の暗い字が沈んだ
     （実測: 地 (30,72,101) に字 (67,78,84)）。パネルは本文と同じ側の面。 */
  --panel-veil: linear-gradient(color-mix(in srgb, var(--panel-face) 94%, transparent),
                                color-mix(in srgb, var(--panel-face) 94%, transparent));


  /* ---- 読ませるコードの板 ----
     **どちらのテーマでも暗いまま**にする 2 つ。端末の見た目を借りている所なので、
     ライトで明るい板に変えると「実行するもの」に見えなくなる。
     色を直に書いてよいのはここだけ、の原則を通すために**トークンに出す**
     ―― 一度 parts/code-block が #1a1a1a / #f7f7f7 を直に持っていて、
     テーマを持たないぶん暗いテーマで地に沈んでいた（実測。誰も気づかない場所だった）。 */
  --code-face: #1a1a1a;
  --code-ink: #f7f7f7;

  /* **ノトサンズを先に置く。** 一度 `system-ui` 始まりにしていたが、それだと
     **端末ごとに別の書体が出る** ―― macOS はヒラギノ、Windows は Yu Gothic UI、
     Linux は Noto。同じ画面を見ながら話しているのに字面が違い、
     「この字が細い」「ここだけ詰まっている」が噛み合わなかった。
     製品の顔は 1 つにする ―― 見る人の端末ではなく、**製品が書体を決める**。

     並びの意味:
       "Noto Sans JP"      … Google Fonts で配る名前（読み込んだときはこれ）
       "Noto Sans CJK JP"  … OS に入っているときの名前（Linux はたいていこちら）
       "Noto Sans"         … 和文が要らない画面の欧文
     そのあとは**入っていない端末のための受け皿**（system-ui 以下）。

     ★ **どこでもノトにしたいなら、配備先が webfont を読む。** 上の 2 つは
     macOS / Windows には入っていないので、読まなければ受け皿へ落ちる。
     読むときは太さも一緒に：見出しが 800 なので `wght@400..800` を取らないと
     **偽の太字**（横に引き伸ばしたもの）になる。 */
  --font: "Noto Sans JP", "Noto Sans CJK JP", "Noto Sans",
    system-ui, -apple-system, "Segoe UI", Roboto, "Hiragino Kaku Gothic ProN", Meiryo, sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* 左右の列幅。畳む／右を開くで動くのはこの 2 つだけ。
     **右パネルは左サイドバーと同じ幅**にそろえてある（左右で器の大きさを変えない）。 */
  /* **開いているときの幅**。畳んでも変わらない定数（畳んだ幅は --shell-col-left が持つ）。
     パネルの中身がこの値で自分を固定する ―― 畳む間に幅なりで折り返させないため。 */
  --shell-sidebar-w: 340px;
  --shell-rail-w: 56px;
  --info-w: 340px;
  /* 行の高さも変数に出す。右から出る枠（詳細・設定）が上下端をここから読むので、
     ヘッダーの高さを変えても 3 か所を直して回らずに済む。 */
  --main-pad: 40px;      /* 本文の左右余白。**送り棒を枠の端へ寄せる計算がこの値を読む**ので、
                            .site-main の padding を直値で書かずここから引く */
  --shell-header-h: 96px;
  --shell-footer-h: 56px;
  /* 速さは**動く距離**で決める（SKILL.md の速度の表）。5 つだけ持ち、直値をその場で作らない。
     ここに無い速さを書き足したくなったら、まず「何がどれだけ動くのか」を上の並びに当てはめる。 */
  --color: 0.2s;         /* 字だけの色。動かない                       */
  /* **列の幅の速さ（--motion 0.35s）は消した。** 誰も読まないまま残っていた ――
     列の遷移は `grid-template-columns` に transition を掛ける方式をやめて
     `--shell-col-left` を遷移させる形（parts/app-shell）に変えたとき、
     読む先が --slide に移ったのに、変数と速度の表だけが取り残されていた。
     表は「列は出入りする面より**短く**」と言い、実体は**同じ値**という逆の状態。
     左のパネルは「列が広がる」と「中身が出る」が 1 つの動きなので、
     別の速さを持たせると枠と中身がずれて見える。--slide に一本化する。 */
  --tint: 0.4s;          /* 面の色。動かないが面積が広い                */
  --slide: 0.65s;        /* 横から出入りする面。数百 px 動く            */
  --slide-ease: ease;
  /* **敷き板（引き出し）だけは別の曲線。** 横から出入りする面は基本 --slide だが、
     引き出しは画面の端から板が滑り出す仕草で、iOS のシートと同じ曲線のほうが
     「掴んで引き出した」ように見える。**ただし直値で書かない** ―― 直値だと
     `.drawer` の visibility の遅延（＝板が消えきってから当たりを外す）と
     ずれても誰も気づけない。実際に片方だけ書き換えて、板が消える前に
     押せなくなった。速さは 1 か所で持つ。 */
  --sheet: 0.5s;
  --sheet-ease: cubic-bezier(0.32, 0.72, 0, 1);
  --underline: 0.4s;     /* 伸びる下線。行の幅ぶん                      */
  /* 順に出す演出（ナビの項目・表の行）の刻み。**製品を通してこの 1 つ**
     ―― 画面ごとに変えると、移るたびに別の演出に見える。長さは「順に出す件数」の
     頭打ちで抑える（全体の長さ ÷ 件数で刻みを割り出さない）＝ advanced-stagger.md 参照 */
  /* 刻みが短いと「一斉に出た」に見えて、演出の意味（順に目を運ぶ）が消える。
     **2 回上げている**:
       40ms … 5 枚並んでも全部出るまで 0.2 秒で、目が追う前に終わる
       70ms … 項目が 2〜3 個の節では、まだ**同時に出たようにしか見えない**
              （0.6 秒の重なりのほうが刻みより長く、差が重なりに埋もれる）
     110ms は 1 つあたりの長さ（0.8s）の 1/7 で、隣どうしの立ち上がりが目で分かる。
     **3 回目に上げた**: 150ms（1.05s の 1/7）。パネルが出るのが速いという声で、
     枠（--slide 0.45s → 0.65s）と中身をそろえて 1 段ゆっくりにした。
     比（1/7）は動かさない ―― ここを崩すと「順に出る」が「一斉に出る」に戻る。
     頭打ち（LEAD = 12）と合わせて、最後の 1 つが出終わるまで約 2.9 秒。 */
  --stagger-step: 150ms;
  --reveal: 1.05s;       /* 1 つあたりの長さ。刻みと合わせてここだけで持つ */
  /* **送りながら現れるもの**（一覧の 1 件・カード）は別に持つ。
     上の 2 つは「ページや枠を開いた直後」の演出で、利用者は待っている ―― 速いほうがよい。
     こちらは読みながら下へ送っている最中に出るので、**1 枚ずつ目に入る速さ**でよい。
     同じ値にすると、どちらかが必ず不満になる（行き先が遅い／カードが速すぎる）。 */
  --stagger-scroll: 120ms;
  --reveal-scroll: 0.9s;
}
/* ダークは土台を差し替え、混ぜ比率も変える（同じ式では両方を再現できない） */
:root:not([data-theme="light"]) {
  @media (prefers-color-scheme: dark) {
    color-scheme: dark;
    --bg-raw: #232529;
    --ink-raw: #e8eaed;
    --line-raw: #373a40;
    --surface: color-mix(in srgb, var(--ink) 5%, var(--bg));   /* ダークは面を地より持ち上げる */
    --sunken: var(--bg);           /* 沈みは地まで落とす（面より下・地と同じ） */
    --border-strong: color-mix(in srgb, var(--ink) 26%, var(--bg));
    --sub: color-mix(in srgb, var(--ink) 78%, var(--bg));
    --grey: color-mix(in srgb, var(--ink) 66%, var(--bg));
    --mute: color-mix(in srgb, var(--ink) 64%, var(--bg));
    --shadow: rgba(0, 0, 0, 0.55);
    --material-thick: color-mix(in srgb, var(--surface) 86%, transparent);
    --hairline: color-mix(in srgb, var(--ink) 16%, transparent);
    --hairline-strong: color-mix(in srgb, var(--ink) 30%, transparent);
    --warn: #fa6b6b;   /* 載せた行は明るくなるので、その上でも AA が要る（#fa5252 は 3.96:1 で割れた） */
    --accent: #48b3dc;
    /* ---- ライトの作りはここへ持ち込まない ----
       暗いところでは、箱を**持ち上げた面と影**で見せるのがいちばん分かりやすい。
       金を足す・本文に面を敷く・帯を塗る、はどれも情報を増やすだけで区別を増やさない。
       **縞だけは別**（下）。あれは箱と地の話ではなく、行と行の話なので暗いところでも要る。 */
    --gold: var(--accent);         /* 飾りはキーカラーに戻す */
    /* 【2026-09-11】**暗いときの罫は白（字の色）にする。** ここはキーカラーの青にしていたが、
       この線を読むのは報せの札（parts/toast）だけで、**ただの報せが明るい水色で光って**
       いた。暗いところは色を足さない、という上の決めに素直に合わせると、
       飾りの線は無彩＝字の色。ライトは金のまま（明るい地では白が引けない）。 */
    --gold-line: var(--ink);
    --select-ink: var(--accent);   /* 暗いときの選択はキーカラーの青 */
    /* 枠は字の色（白）、絵はキーカラー（青）。式はライトと同じで、値だけ入れ替わる */
    /* 暗いところも同じ薄さ（白 60% で 5.51:1） */
    --rail-btn-line: color-mix(in srgb, var(--ink) 60%, transparent);
    --rail-btn-ink: var(--accent);
    /* 載せた地は無彩のまま**明るくする**（ライトだけ金で染める。暗いところは色を足さない）。
       6% → 9%。縞を引くようになって、6% では縞の行との差が 1.058:1 しか無かった（実測）。 */
    --hover-face: color-mix(in srgb, var(--ink) 9%, transparent);
    --main-face: transparent;      /* 本文に面を敷かない（器の地をそのまま継ぐ） */
    /* 暗いところは器の地と同じ（明るいところだけ一段濃くする）。
       **transparent ではなく値を入れる** ―― 下の暗幕がこの色から作られるので、
       透明にすると幕が消えて写真が素で出る。 */
    --rail-face: var(--bg);
    --rail-material: color-mix(in srgb, var(--rail-face) 88%, transparent);
    --panel-face: var(--surface);  /* 小窓・トーストは持ち上げた面。影が効く */
    /* 縞。**一度「暗いところでは引かない」と決めて、戻した。**
       理由は「持ち上げた面と影で箱を見せるので、縞は情報を増やすだけ」だったが、
       それは箱と地を見分ける話で、**行と行を見分ける話ではない**。長い一覧では
       暗いほうが目が横に滑る。ライトと同じ段（1.113:1）を面の上に足す。 */
    --stripe: color-mix(in srgb, var(--ink) 4%, var(--surface));
    --band-face: transparent;      /* 下帯は塗らない */
    --band-ink: var(--mute);       /* 塗らないので字は弱い字の色。**黒のままにすると地と同色で消える** */
    --band-border: 1px solid var(--border-strong);
    /* **一度「暗いときは塗りを滑らせる」にして、戻した。** 載せるたびに釦がまるごと
       アクセントで塗りつぶされ、「押した」ではなく「別の状態になった」に見えた。
       反応は枠と絵の色＋薄い地だけで足りる（ライトと同じ振る舞いにそろえる）。 */
    --rail-fill: none;
    /* 暗幕は**ライトよりずっと濃く**する。暗い地では残った写真がそのまま出るので、
       ライトと同じ濃さにすると写真が主役になって字が読めない（上の Weber の裏返し）。

       **96% → 88% へ薄くした（絵をもう少し見せたい）。88% が下限。**
       どこまで薄くできるかは**その面に実際に乗っている字**が決める。面だけを撮って
       （字を透明にして）明るさを測り、いちばん弱い字との比を出した:

         暗幕 96% … 面の上位 1% 0.0263 → 比 7.22
         暗幕 90% … 0.0400 → 4.86
         暗幕 **88%** … 0.0455 → **4.58**（下限のすぐ上）
         暗幕 86% … 0.0508 → 4.34 ← **AA(4.5) を割る**

       **いちばん弱い字は `--accent`（L=0.388）** ―― この面に乗っているのは
       選択中の項目（accent）と行き先の名前（L=0.520）の 2 色だけで、
       `--mute` は 1 つも無い。一度 `--mute` を基準に測って 90% で止めたが、
       **その色は写真の上に出ていなかった**（測り直して 88% まで来た）。
       「弱い色」を頭で選ばず、**その面に出ている色を数えてから**測ること。

       写真を差し替えたら測り直す ―― 明るい絵に替えれば同じ % でも割る。
       これ以上明るくしたいなら、暗幕ではなく**上に乗る字のほう**を上げる
       （accent を明るくする／写真を暗いものに替える）。 */
    --rail-veil: linear-gradient(color-mix(in srgb, var(--rail-face) 88%, transparent),
                                 color-mix(in srgb, var(--rail-face) 88%, transparent));
    --panel-veil: linear-gradient(color-mix(in srgb, var(--panel-face) 94%, transparent),
                                  color-mix(in srgb, var(--panel-face) 94%, transparent));
    /* **塗りの上では絵を地の色にする。** 塗りは --accent、絵の --gold も
       ダークでは --accent に戻る＝**同じ色**なので、載せた瞬間に絵が塗りに溶けて
       消えていた（ライトは塗らないので起きない。だからライトだけ正しく見えた）。 */
    /* 【2026-09-10】`var(--bg)` だった ―― 塗りが滑ってくる前提の色で、
       **塗りをやめた**（--rail-fill: none）あとは「地と同じ色の絵」になり、
       開いている釦の絵が消えていた（実測: 絵 rgb(35,37,41) / 地 rgb(35,37,41)）。 */
    --rail-fill-ink: var(--accent);
    --hover-line: color-mix(in srgb, var(--ink) 70%, var(--bg));   /* 載せた面の上で 5.7:1。26% では 1.6:1 で見えない */
    --btn-face: transparent;       /* ダークの釦は塗らない（赤の字に余裕が無い） */
  /* **ダークの補助の釦は字と枠を --ink まで上げる。**
     ダークは地を持たない（上の transparent）ので、--grey（ink 66%）＋
     --hairline-strong（ink 30%）だと**押す前は「読む字」と見分けが付かず**、
     載せて初めて釦だと分かる状態になっていた（実案件での実測。承認済みの直しは
     client.css 1 節 ―― あちらは 1 つの釦に絞って当てていたのを、ここで一般化した）。
     主要（--accent）とは色相で分かれるので、白へ上げても混同しない。
     ライトは地を持つので、この引き上げは要らない。 */
  /* **ダークのホバーは「面（--surface）へ持ち上げる」だけにする。**
     休止は透明（地 --bg #232529）なので、ホバーで面の色に変わるだけで段は出る。
     色を混ぜるのは 2% まで ―― 実測（2026-09-11。地 #232529 / 面 #2d2f33）:
         currentColor  0%   warn 4.71  accent 5.59  ink 11.13
                       2%   warn 4.60  accent 5.39  ink 10.50   ← ここが上限
                       4%   warn 4.49  ★ AA 割れ
                      18%   warn 3.63  accent 4.06  ★ 2 つとも割れる
     **18% はライトの値をそのまま流用していたもの**で、ダークでは主要と破壊的の
     2 つが AA を割っていた（`.btn:hover` がトークンを読まず --surface を直に
     混ぜていたため、「ダークは塗らない」の決めが休止にしか効いていなかった）。
     段はライトと同じく「一段濃く」だが、**濃さを運ぶのは色ではなく面**。 */
  --btn-face-hover: color-mix(in srgb, currentColor 2%, var(--surface));
  --btn-ink: var(--ink);
  --btn-line: var(--ink);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  /* **一度 #1a1b1e から 1 段持ち上げた。** 「ダークが暗すぎる」ため。
     真っ黒に寄せるほど、白い字との差が開いて長く読むと目が疲れる（字は 14.29 → 12.74:1
     で AAA のまま）。面（--surface）は地から作るので、地を上げれば段ごと上がる。 */
  --bg-raw: #232529;
  --ink-raw: #e8eaed;
  --line-raw: #373a40;
  --surface: color-mix(in srgb, var(--ink) 5%, var(--bg));   /* ダークは面を地より持ち上げる */
  --sunken: var(--bg);           /* 沈みは地まで落とす（面より下・地と同じ） */
  --border-strong: color-mix(in srgb, var(--ink) 26%, var(--bg));
  --sub: color-mix(in srgb, var(--ink) 78%, var(--bg));
  --grey: color-mix(in srgb, var(--ink) 66%, var(--bg));
  --mute: color-mix(in srgb, var(--ink) 64%, var(--bg));
  --shadow: rgba(0, 0, 0, 0.55);
  --material-thick: color-mix(in srgb, var(--surface) 86%, transparent);
  --hairline: color-mix(in srgb, var(--ink) 16%, transparent);
  --hairline-strong: color-mix(in srgb, var(--ink) 30%, transparent);
  --warn: #fa6b6b;   /* 載せた行は明るくなるので、その上でも AA が要る（#fa5252 は 3.96:1 で割れた） */
  --accent: #48b3dc;
  /* ---- ライトの作りはここへ持ち込まない ----
     暗いところでは、箱を**持ち上げた面と影**で見せるのがいちばん分かりやすい。
     金を足す・本文に面を敷く・帯を塗る、はどれも情報を増やすだけで区別を増やさない。
     **縞だけは別**（下）。あれは箱と地の話ではなく、行と行の話なので暗いところでも要る。 */
  --gold: var(--accent);         /* 飾りはキーカラーに戻す */
  /* 【2026-09-11】暗いときの罫は白（字の色）。理由は上の @media 側と同じ */
  --gold-line: var(--ink);
  --select-ink: var(--accent);   /* 暗いときの選択はキーカラーの青 */
  /* 枠は字の色（白）、絵はキーカラー（青）。式はライトと同じで、値だけ入れ替わる */
  /* 暗いところも同じ薄さ（白 60% で 5.51:1） */
  --rail-btn-line: color-mix(in srgb, var(--ink) 60%, transparent);
  --rail-btn-ink: var(--accent);
  /* 載せた地は無彩のまま**明るくする**（ライトだけ金で染める。暗いところは色を足さない）。
     6% → 9%。縞を引くようになって、6% では縞の行との差が 1.058:1 しか無かった（実測）。 */
  --hover-face: color-mix(in srgb, var(--ink) 9%, transparent);
  --main-face: transparent;      /* 本文に面を敷かない（器の地をそのまま継ぐ） */
  /* 暗いところは器の地と同じ（明るいところだけ一段濃くする）。
     **transparent ではなく値を入れる** ―― 下の暗幕がこの色から作られるので、
     透明にすると幕が消えて写真が素で出る。 */
  --rail-face: var(--bg);
  --rail-material: color-mix(in srgb, var(--rail-face) 88%, transparent);
  --panel-face: var(--surface);  /* 小窓・トーストは持ち上げた面。影が効く */
  /* 縞。**一度「暗いところでは引かない」と決めて、戻した。**
     理由は「持ち上げた面と影で箱を見せるので、縞は情報を増やすだけ」だったが、
     それは箱と地を見分ける話で、**行と行を見分ける話ではない**。長い一覧では
     暗いほうが目が横に滑る。ライトと同じ段（1.113:1）を面の上に足す。 */
  --stripe: color-mix(in srgb, var(--ink) 4%, var(--surface));
  --band-face: transparent;      /* 下帯は塗らない */
  --band-ink: var(--mute);       /* 塗らないので字は弱い字の色。**黒のままにすると地と同色で消える** */
  --band-border: 1px solid var(--border-strong);
  /* **一度「暗いときは塗りを滑らせる」にして、戻した。** 載せるたびに釦がまるごと
     アクセントで塗りつぶされ、「押した」ではなく「別の状態になった」に見えた。
     反応は枠と絵の色＋薄い地だけで足りる（ライトと同じ振る舞いにそろえる）。 */
  --rail-fill: none;
  /* 暗幕は**ライトよりずっと濃く**する。暗い地では残った写真がそのまま出るので、
     ライトと同じ濃さにすると写真が主役になって字が読めない（上の Weber の裏返し）。 */
  /* **OS 追従の側と同じ値にする。** 片方だけ 96% のままで、
     「ダークを自分で選んだとき」だけ写真が暗いままだった ―― 明るくした直しが
     切替の道に入っていなかった。値の根拠は上の @media 側のコメント（88% で 4.58:1）。 */
  --rail-veil: linear-gradient(color-mix(in srgb, var(--rail-face) 88%, transparent),
                               color-mix(in srgb, var(--rail-face) 88%, transparent));
  /* **柱の色ではなく、パネル自身の面から作る。** 柱を濃い紺にしたとき、これが
     --rail-face を見ていたので**右パネルの地まで紺になり**、その上の暗い字が沈んだ
     （実測: 地 (30,72,101) に字 (67,78,84)）。パネルは本文と同じ側の面。 */
  --panel-veil: linear-gradient(color-mix(in srgb, var(--panel-face) 94%, transparent),
                                color-mix(in srgb, var(--panel-face) 94%, transparent));
  /* 塗りの上では絵を地の色にする（理由は上の @media 側のコメント）。
     ここにも書く ―― 暗いときの値は 2 か所に要る（check-consistency の ㉓）。 */
  /* 【2026-09-10】`var(--bg)` だった ―― 塗りが滑ってくる前提の色で、
     **塗りをやめた**（--rail-fill: none）あとは「地と同じ色の絵」になり、
     開いている釦の絵が消えていた（実測: 絵 rgb(35,37,41) / 地 rgb(35,37,41)）。 */
  --rail-fill-ink: var(--accent);
  --hover-line: color-mix(in srgb, var(--ink) 70%, var(--bg));   /* 載せた面の上で 5.7:1。26% では 1.6:1 で見えない */
  --btn-face: transparent;       /* ダークの釦は塗らない（赤の字に余裕が無い） */
  /* **ダークの補助の釦は字と枠を --ink まで上げる。**
     ダークは地を持たない（上の transparent）ので、--grey（ink 66%）＋
     --hairline-strong（ink 30%）だと**押す前は「読む字」と見分けが付かず**、
     載せて初めて釦だと分かる状態になっていた（実案件での実測。承認済みの直しは
     client.css 1 節 ―― あちらは 1 つの釦に絞って当てていたのを、ここで一般化した）。
     主要（--accent）とは色相で分かれるので、白へ上げても混同しない。
     ライトは地を持つので、この引き上げは要らない。 */
  /* **ダークのホバーは「面（--surface）へ持ち上げる」だけにする。**
     休止は透明（地 --bg #232529）なので、ホバーで面の色に変わるだけで段は出る。
     色を混ぜるのは 2% まで ―― 実測（2026-09-11。地 #232529 / 面 #2d2f33）:
         currentColor  0%   warn 4.71  accent 5.59  ink 11.13
                       2%   warn 4.60  accent 5.39  ink 10.50   ← ここが上限
                       4%   warn 4.49  ★ AA 割れ
                      18%   warn 3.63  accent 4.06  ★ 2 つとも割れる
     **18% はライトの値をそのまま流用していたもの**で、ダークでは主要と破壊的の
     2 つが AA を割っていた（`.btn:hover` がトークンを読まず --surface を直に
     混ぜていたため、「ダークは塗らない」の決めが休止にしか効いていなかった）。
     段はライトと同じく「一段濃く」だが、**濃さを運ぶのは色ではなく面**。 */
  --btn-face-hover: color-mix(in srgb, currentColor 2%, var(--surface));
  --btn-ink: var(--ink);
  --btn-line: var(--ink);
}

/* ---- テーマ切替の見せ方（上から下へ掃く） ----
   切替そのものは part.js（3 状態を 1 つ進める）。ここは**掃く形**だけを持つ。

   全部が同じ瞬間に反転すると、画面が一度点滅したようにしか見えず、
   どちらへ変えたのか目が追えない。**新しい色を上端から下へ開く**と、
   「いま切り替えた」ことと「どちらへ切り替えたか」が同時に伝わる。

   長さは `--slide`（横から出入りする面）と同じ段 ―― 画面の端から端まで
   渡る動きなので、この UI でいちばん長い値に合わせる。新しい値は作らない。

   古い面は動かさない（`animation: none`）。両方を動かすと、
   下から出ていく面と上から入る面がすれ違って何が起きたのか読めない。 */
::view-transition-old(root) { animation: none; }
::view-transition-new(root) { animation: themeWipe var(--slide) var(--slide-ease) forwards; }
/* ---- 順に現れる仕草。**製品を通してこの 1 つ** ----
   一度 3 つに分かれていた ―― `navItemIn`（translateY 4px・下から）／`rowReveal`（-6px・上から）／
   `panelItemIn`（-6px・上から）。うち 2 つは中身が完全に同じで、`rowReveal` は
   data-table と stagger の**両方が宣言**していた（同じ名前を 2 回定義）。
   残る 1 つだけ向きも距離も違い、**左のナビだけ下から出ていた**。
   速さ（--reveal / --stagger-step）は 1 か所なのに動きが 3 か所にあると、
   直したつもりで 1 つだけ変わる。名前も定義もここへ寄せる。 */
@keyframes revealIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

@keyframes themeWipe {
  from { clip-path: inset(0% 0% 100% 0%); }
  to { clip-path: inset(0% 0% 0% 0%); }
}
/* 動きを抑える設定では掃かない。**色は変える** ―― 動きを消すのではなく
   静かな等価表現へ置き換える（parts/reduced-motion と同じ考えかた）。 */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-new(root) { animation: none; }
}

/* ---- 本文へ飛ぶ（skip link）----
   キーボードだけで使う人は、**ページを開くたびに左のナビを全部通ってから本文に着く**。
   実測した雛形では、本文の前に押せる物が 21 個あった（全 43 個）。
   画面を移るたび 21 回 Tab を押すことになるので、最初の 1 つに近道を置く。

   **画面から消さない。** `display: none` や `visibility: hidden` にすると
   Tab の順からも外れ、近道そのものが押せなくなる ―― 位置だけ画面の外へ出す。

   **滑らせない。** 出る距離は 50px 足らずで、速さの表（動く距離で決める）に
   当てはまる段が無い。ここに新しい速さを作るより、即座に出すほうが良い
   ―― 遅れると「押したのに出ない」と読まれて、もう一度押される。 */
.skip-link {
  position: fixed;
  top: 8px;
  left: 8px;
  /* 210 は重なり順の表のいちばん上。出るのは**何も開いていないとき**だけなので
     順を争う相手が居ない（重ね物が開いているあいだは背面ごと inert で塞がる）。 */
  z-index: 210;
  padding: 8px 16px 8px 16px;
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background-color: var(--bg);
  color: var(--ink);
  font-size: 14px;
  font-weight: 700;
  transform: translateY(-200%);
}
.skip-link:focus { transform: translateY(0px); }

/* ============================================================
   アプリシェル — 4 領域（sidebar / main / rail ＋ header・footer）
   ページ自体はスクロールさせない。送るのは中の枠だけ。
   ============================================================ */
.app {
  display: grid; height: 100vh; overflow: hidden;
  /* 1fr ではなく minmax(0, 1fr)。1fr の最小は auto＝中身の高さなので、
     本文が長いと真ん中の行が伸びてフッターが画面外へ押し出される。 */
  grid-template-rows: var(--shell-header-h) minmax(0, 1fr) var(--shell-footer-h);
  /* 動くのは**変数**（--shell-col-left）で、列そのものではない。下の @property 参照。 */
  --shell-col-left: var(--shell-sidebar-w);
  grid-template-columns: var(--shell-col-left) 1fr var(--shell-rail-w);
  grid-template-areas:
    "header  header header"
    "sidebar main   rail"
    "footer  footer footer";
  /* **`grid-template-columns` そのものには transition を掛けない。**
     `transition: grid-template-columns var(--motion) ease` を持っていて、
     畳んだときに **列が古い値のまま固まった**（変数は 56px になっているのに
     算出された列は 340px のまま。押して 0.5 / 1.5 / 3 秒後のいずれでも動かなかった）。
     結果、パネルだけ消えて**幅 340px の空白の帯**が残る。
     切り分けは「外す／列を宣言し直す」の 2 通りで試し、**効いたのは外すほうだけ**。

     代わりに**変数のほうを遷移させる**（下の @property で <length> として登録済み）。
     列は毎フレーム新しい長さを読み直すだけなので、上の固まりかたは起きない。 */
  transition: --shell-col-left var(--slide) var(--slide-ease);
  background: transparent;
  position: relative; z-index: 1;
}
/* **カスタムプロパティは既定で「型の無い文字列」なので、そのままでは遷移しない**
   （340px から 56px へ *飛ぶ*）。<length> として登録して初めて補間される。
   `inherits: true` ―― パネルの中身もこの幅を読む（parts/nav-rail）。
   `initial-value` に var() は書けない仕様なので、ここだけ直値になる。
   **この値は使われない** ―― .app が必ずトークンから入れ直すので、
   未設定のときの保険でしかない（トークンと食い違っても画面には出ない）。 */
@property --shell-col-left {
  syntax: "<length>";
  inherits: true;
  initial-value: 340px;
}
/* 最小化（一文字レール）。レールの幅だけが残る。
   **--shell-sidebar-w のほうは書き換えない** ―― あちらは「開いているときの幅」で、
   畳んでも変わらない定数。パネルの中身がその幅で自分を固定するのに使う
   （畳む間に幅なりで折り返させないため。parts/nav-rail）。 */
html[data-sidebar-collapsed] .app { --shell-col-left: var(--shell-rail-w); }
/* 右から出る枠は**重ねて出す**（本文の列幅は動かさない）。
   詳細と設定で出方をそろえた結果、どちらも一時的に覆うものになった。 */

/* ---- ヘッダー ----
   **器（本文の外にあって上に乗るもの）だけが影を持つ。** 本文の中は平ら。
   影は**近い影と遠い影の 2 枚重ね**にする ―― 遠い影 1 枚だけだと、
   すぐ下にある仕切りの実線に飲まれて「書いたのに見えない」になる
   （SKILL.md「影は本文の外にあって、上に乗るものだけに付ける」の実測より）。
   面は transparent のまま。box-shadow は境界の外へ描くので効く。 */
.site-header {
  grid-area: header; z-index: 20;
  /* バーは高さ固定。中身がはみ出したら**切る**。
     切らないと、狭い画面（縦積み）で見出しが下の段に垂れ、z-index 20 で
     レールの項目を覆う ―― 押せるのに押せなく見える状態になっていた。 */
  overflow: hidden;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 0px 40px 0px 40px;
  border-bottom: 1px solid var(--border-strong);
  background: transparent;
  box-shadow: 0px 1px 2px var(--hairline-strong), 0px 6px 14px var(--shadow);
}

.site-header__eyebrow {
  font-family: var(--mono); font-size: 14px; letter-spacing: 0.08em; color: var(--mute);
}

.site-header__title { font-size: 24px; font-weight: 800; letter-spacing: 0.02em; }

.site-header__right { display: flex; align-items: center; gap: 12px; }

/* ヘッダーの検索欄。`.field`（フォームの行）とは別物なので名前を分ける
   ―― 同じ名前だと後勝ちで潰し合う。 */
.site-header__search {
  width: 220px; height: 36px; padding: 0px 12px 0px 12px;
  border: 1px solid var(--hairline-strong); border-radius: 4px;
  background: var(--surface); color: var(--ink); font-size: 16px;
}

.site-header__search::placeholder { color: var(--mute); }

.site-header__search:focus { border-color: var(--accent); outline: none; }

/* ---- フッター ---- */
.site-footer {
  grid-area: footer; display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 0px 40px 0px 40px; border-top: var(--band-border);
  /* 下帯。ライトは色を持つ帯（--band-face）、ダークは塗らない。
     **字は --band-ink。** 帯を塗らないテーマで字を固定色にすると地と同色で消える。 */
  /* 【2026-09-11】等幅（--mono）をやめた。下帯に並ぶのは**読ませる字**
     （会社情報の行き先・ログインしている人）で、桁をそろえる必要が無い。
     ここだけ等幅にすると、同じ画面の中で下帯だけ字面が変わって見える
     ―― 配備先から「字体が戻っていない場所がある」と申し送りが来た実測地点。
     等幅が働くのは `code` と、桁をそろえる数字（`.data-table__num`）。 */
  background: var(--band-face); font-size: 16px;
  letter-spacing: 0.04em; color: var(--band-ink);
}

/* ============================================================
   左 aside — 2 段構造（レール ＋ パネル）
   ============================================================ */
.site-sidebar {
  grid-area: sidebar; min-height: 0;
  border-right: 1px solid var(--border-strong);
  /* **側面は器よりもう一段濃い面を敷く。** 透明（＝器の地）のままだと、本文の面との差が
     1.05:1 しかなく、境目が罫線だけになって「同じ面が続いている」ように見えた。
     暗いところでは `--rail-face` が transparent に戻る＝従来どおり器の地を継ぐ。 */
  background: var(--rail-face);
  /* 伸びたレールが本文の上へはみ出せるように切らない */
  overflow: visible;
}

.site-sidebar__menu { display: flex; height: 100%; min-width: 0; min-height: 0; }

/* ── レール ── 56px を確保するのは枠。レール自身は絶対配置で浮く ── */
.nav-rail__slot { position: relative; flex: 0 0 56px; width: 56px; }

.nav-rail {
  position: absolute; top: 0px; bottom: 0px; left: 0px; width: 56px;
  display: flex; flex-direction: column;
  border-right: 1px solid var(--hairline);
  /* 伸びる前のラベルはここで切られる（幅を押し広げない） */
  overflow: hidden; background: transparent;
  transition: width var(--slide) var(--slide-ease), background-color var(--slide) var(--slide-ease),
              box-shadow var(--slide) var(--slide-ease);
}

/* **キーボードで中に居るあいだだけ伸ばす。**
   【2026-09-11】`.nav-rail--open`（＝マウスで載せた印）は JS が付けなくなった
   ―― 載せるだけで伸びると、レールは左パネルの上に浮いているので
   「左パネルが最大と最小を行き来する」に見え、**通り道に置いてあるだけで起きる**。
   規則そのものは残す（印を自分で付けたい配備先のため）が、
   **マウスの合図を足し直さないこと**（理由は references/sidebar-rail-panel.md §4）。
   キーボードは動いてよい ―― 自分で送った結果なので、意図せず動くことにならない。
   浮いているので影を持つ（本文の上に重なるものは影・中のものは平ら） */
.nav-rail--open, .nav-rail:has(:focus-visible) {
  width: 264px; z-index: 40;
  background: var(--rail-material);
  -webkit-backdrop-filter: blur(30px) saturate(180%);
  backdrop-filter: blur(30px) saturate(180%);
  box-shadow: 8px 0px 32px var(--shadow);
}

/* **パネルが出ているあいだは、サイドバーの列を丸ごと覆う。**
   264px は「畳んでいて列がレールだけ（56px）のとき、本文の上へ重なる」ための幅。
   パネルが出ていると列は --shell-sidebar-w（340px）あるので、右に 76px だけ
   パネルが残る ―― 節見出しの罫と項目の下線が帯の横から覗いて、
   **中身が2重に出ている**ように見える（実測。skill の見本でも起きていた）。
   直値を足さず、列の幅そのものを読む。 */
html:not([data-sidebar-collapsed]) .nav-rail--open,
html:not([data-sidebar-collapsed]) .nav-rail:has(:focus-visible) { width: var(--shell-sidebar-w); }

.nav-rail__list { display: flex; flex-direction: column; }

/* 用が済んだあとに行く場所と畳むボタンは下端へ寄せる */
.nav-rail__list--bottom { margin: auto 0px 0px 0px; border-top: 1px solid var(--hairline); }

.nav-rail__link {
  position: relative; display: flex; align-items: center; gap: 12px;
  width: 100%; height: 48px;
  /* **4 の倍数の例外。** 左 18px は選んだ数字ではなく計算で出ている ――
     56px のレールの中で 20px の絵を中央に置くと (56 − 20) / 2 = 18。
     18＋10＝28 でレールの真ん中。伸びたときも絵の位置は動かない（字だけが右に現れる）。
     ここを 16 や 20 に丸めると、**絵が中央でなくなる**。 */
  padding: 0px 16px 0px 18px;
  text-align: left; color: var(--mute); background: transparent;
  transition: color var(--color) ease;
}

/* 名前。閉じているあいだは枠の外にあって切られているので、
   透明度だけで出し入れする（幅の計算には関わらせない） */
.nav-rail__label {
  flex: 1; min-width: 0; font-size: 16px; line-height: 1.4;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  opacity: 0; transition: opacity 0.2s ease;
}

.nav-rail--open .nav-rail__label,
.nav-rail:has(:focus-visible) .nav-rail__label { opacity: 1; }

/* 現在地の線。左端に立て、hover / 選択中に上下いっぱいへ伸びる
   （パネルの項目で下線が左→右に伸びるのと同じ演出を 90° 回したもの） */
.nav-rail__link::before {
  content: ""; position: absolute; left: 0px; top: 50%;
  /* 立つ棒は**選択の色**。以前は飾りの金（--gold）だった ―― 暗いときは --gold も
     選択の色もキーカラーの青で一致するので気づけないが、**明るいときだけ金が 2 種類に割れ**、
     字（読める濃さの金）と棒（素の金）で色が違って見えた。状態を示すものは 1 色にする。 */
  width: 2px; height: 0px; background: var(--select-ink);
  transform: translateY(-50%); transition: height 0.35s ease;
}

/* 載せたときと選ばれているときは**同じ飾り色**（--gold。ダークではキーカラーに戻る）。
   分けると、指しているのか選んであるのかを色で見分けられない。 */
.nav-rail__link:hover { color: var(--select-ink); }

.nav-rail__link:hover::before { height: 16px; }

/* 字はアクセント、立つ棒は飾り色（理由は parts/nav-panel の同じ規則） */
.nav-rail__link--active { color: var(--select-ink); }

.nav-rail__link--active::before { height: 100%; }

.nav-rail__icon { width: 20px; height: 20px; }

.nav-rail__toggle::before { content: none; }

/* ── パネル ── いま開いている節の見出しと項目。畳んでいる間は出さない ── */
.nav-panel {
  flex: 1; min-width: 0; min-height: 0;
  display: flex; flex-direction: column; overflow-y: auto;
  scrollbar-width: none;
}

.nav-panel::-webkit-scrollbar { display: none; }

/* ---- 畳むときは**消さずに、縮む列に飲み込ませる** ----
   `display: none` だった。右から出る枠（transform で滑る）と並べると、
   こちらだけ**一瞬で消えて列が遅れて縮む**＝1 つの操作なのに 2 つの動きがばらばらに見える。
   列の幅は変数で遷移するようになった（parts/app-shell）ので、パネルは
   **その場に居たまま端から切られていく**のが正しい見えかたになる。

   横だけ切る。縦は長い一覧のために送れるままにしておく。 */
.nav-panel { overflow-x: clip; }

/* 中身は**開いているときの幅で固定**する。列なりに縮ませると、飲み込まれる 0.45 秒のあいだ
   文字が折り返しながら潰れていくのが見える。列は動くが中身は動かない。 */
.nav-panel__title,
.nav-panel__body { width: calc(var(--shell-sidebar-w) - var(--shell-rail-w)); }

/* 畳み終わってから見えなくする（0s ＋ 遅延）。
   すぐ `visibility: hidden` にすると飲み込まれる前に消えるし、`display: none` と違って
   **畳んだあとも Tab で入れてしまう**のを防ぐ ―― 幅 0 の見えない項目に焦点が飛ぶ。
   開くときは遅延なしで戻す（待つ理由が無い）。 */
.nav-panel { visibility: visible; transition: visibility 0s; }

html[data-sidebar-collapsed] .nav-panel {
  visibility: hidden;
  transition: visibility 0s linear var(--slide);
  pointer-events: none;
}

/* 節の名前。レールで選んでいるものが文字で読める唯一の場所なので見出しとして立てる */
.nav-panel__title {
  flex: 0 0 auto; padding: 16px 24px 16px 24px;
  font-size: 16px; font-weight: 800; letter-spacing: 0.02em; line-height: 1.4;
  /* 節の名前も**選ばれているものの色**（明るいとき金／暗いとき青）。
     `--accent` にしていたので、明るいときだけ**ここだけ紺**で、下の項目（金）と
     色が割れていた ―― 同じ「いま居る場所」を指す 2 つが別の色を持っていた。 */
  color: var(--select-ink); border-bottom: 1px solid var(--hairline);
}

/* 節の中の項目。罫線は敷かず、ホバーと現在地でだけ下線が伸びる。
   絵記号は持たない（節の絵はレールが持っている） */
.nav-panel__body { display: flex; flex-direction: column; gap: 2px; padding: 8px 16px 16px 16px; }

.nav-panel__list { display: flex; flex-direction: column; gap: 2px; }

/* 節の項目の入場。番号（--i）は JS が配り、刻みは製品共通の変数から読む。
   **これは「1 枚の画面の中でレールを押して節を差し替えた」合図**なので、
   差し替えが起きるときだけ意味がある。
   **ページごとに読み直す作り（サーバー描画の多ページ ― Blade / Rails / Django 等）では止める。**
   読み直すたびに全項目が動くので、利用者からは「項目を押すたびにアニメーションが出る」と見える
   ―― 実際にそう言われた。プロジェクト側の CSS に 1 行だけ書いて上書きする:
       .nav-panel__list > li { animation: none; } */
/* 左の行き先も、右のパネルと同じ速さで刻む（--reveal / --stagger-step の 2 つだけで決める） */
.nav-panel__list > li { animation: revealIn var(--reveal) cubic-bezier(0.22, 1, 0.36, 1) both; animation-delay: calc(var(--i, 0) * var(--stagger-step)); }


/* ---- 節を切り替えたときは、**見出しから順に**入場させる ----
   見出し（節の名前）だけ動かないままだった。節を切り替えると名前がその場で差し替わり、
   下の項目だけが遅れて出る ―― 1 つの面が届いたのではなく、**2 つの出来事**に見える。
   実際「一気に変わる」と報告された。見出しが先に出て、項目がそれに続く。 */
.nav-panel__title { animation: revealIn var(--reveal) cubic-bezier(0.22, 1, 0.36, 1) both; }

/* 項目は見出しの 1 つぶん後ろから。**このパネルの中だけ**ずらす ――
   見出しを持たない並び（docs のサイドバー）に足すと、先頭が理由なく待つ。 */
.nav-panel .nav-panel__list > li { animation-delay: calc((var(--i, 0) + 1) * var(--stagger-step)); }

.nav-panel__item {
  --nav-indent: 12px;
  position: relative; display: block; width: 100%;
  padding: 8px 12px 8px var(--nav-indent);
  text-align: left; font-size: 16px; color: var(--sub);
  transition: color var(--color) ease;
  /* **折り返しを自然任せにしない。** パネルは 240px しかないので長い項目は必ず折れる。
     既定のままだと語の途中で切れ、「ビジネスロジック・レースコンディ／ション」
     「API Top ／ 10:2023）」のように読めない位置で分断される（実測）。
     文節の切れ目で折り、括弧や句読点が行頭に来ないようにする。
     auto-phrase 非対応の環境では normal に落ちるだけで、崩れない。 */
  word-break: auto-phrase;
  line-break: strict;
}

/* 階層の字下げ。1 段目だけ 24px（アイコン 1 個ぶん）下げて親子を分け、
   2 段目からは 16px 刻み。深さは 4 段まで ―― それより深いのは情報設計の問題で、
   字下げで解決しない（references/sidebar-rail-panel.md）。 */
.nav-panel__item--depth-1 { --nav-indent: 24px; }

.nav-panel__item--depth-2 { --nav-indent: 40px; }

.nav-panel__item--depth-3 { --nav-indent: 56px; }

.nav-panel__item--depth-4 { --nav-indent: 72px; }

.nav-panel__item::after {
  content: ""; position: absolute; left: var(--nav-indent); bottom: 4px;
  /* 伸びる下線も**選択の色**（理由は parts/nav-rail の立つ棒と同じ ――
     明るいときだけ字と線で金が 2 種類に割れていた）。 */
  width: 0px; height: 1px; background: var(--select-ink); transition: width var(--underline) ease;
}

.nav-panel__item:hover { color: var(--select-ink); }

.nav-panel__item:hover::after,
.nav-panel__item--active::after { width: calc(100% - var(--nav-indent) - 12px); }

/* 選択中は**字をアクセント、下線を飾り色**にする。字まで金にすると、明るい面の上で
   1.82:1 しか無かった（実測）―― 金は線で効く色で、字で読ませる色ではない。
   ダークでは --gold が --accent に戻るので、どちらのテーマでも同じ式で足りる。 */
.nav-panel__item--active { color: var(--select-ink); }

/* ---- 行き先を**包んでいる**形（既存プロジェクトの取り込み） ----
   `.nav-panel__item` 自身が `<a>` なら行いっぱいが押せる。けれど既存の案件では
   行が器（div）で、中に `<a>` や form 越しの釦（ログアウト）が入っている。
   そのままだと**押せるのは中身の高さ（字 1 行）だけ**で、行の上下 8px が
   反応しない帯として残る。横も、form に包まれた釦は字の幅で止まるので、
   他の行が端まで押せる中で 1 行だけ反応しない（実際にそう報告された）。

   直しかたは**器が手放した余白を中身が持つ**。器を flex にして中身を縦いっぱいへ伸ばし、
   余白は**四方とも**中身の padding へ移す ―― 丈も字の位置も包まない行と同じまま。
   **左右も移すこと。** 上下だけ移したときは、字下げのぶん（--nav-indent）が
   **行の左端の押せない帯**として残った（実測 24px。深い段ほど広い）。
   縦中央を `align-items: center` で作らないこと。中の文字が匿名フレックス項目になり
   `text-overflow: ellipsis` が効かなくなる（パネルを狭めたとき字が切れずにあふれる）。

   **この形を案件側の CSS で書き直さない。** 一度、配備先が
   `.site-sidebar .nav-menu`（詳しさ 0,2,0）で同じことを書いており、
   丈・罫線・字の太さ・下線の形が正典と割れていた（下線は 2px・左 16px）。
   references/sidebar-rail-panel.md「押せるのは行の枠ではなく中身」 */
.nav-panel__item:has(> a, > form) { display: flex; padding: 0px 0px 0px 0px; }

.nav-panel__item > a,
.nav-panel__item > form {
  flex: 1 1 auto; min-width: 0px; align-self: stretch;
  /* block のまま。flex にすると中の文字で ellipsis が効かない */
  display: block; padding: 8px 12px 8px var(--nav-indent); margin: 0px 0px 0px 0px;
  font: inherit; color: inherit; background: transparent; border: 0px;
  text-align: left; text-decoration: none; cursor: pointer;
  /* 包む形は 1 行で収める（器の丈が折り返しで伸びると、罫線の無い並びで行が数えられない） */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* form 越しの釦（Rails の button_to と同じ形）。**器は余白を持たず、中の釦が持つ** ――
   form に padding を置くと、その帯を押しても submit が起きない。 */
.nav-panel__item > form { display: flex; padding: 0px 0px 0px 0px; }

.nav-panel__item > form > button,
.nav-panel__item > form > input[type="submit"] {
  flex: 1 1 auto; min-width: 0px; align-self: stretch;
  display: block; padding: 8px 12px 8px var(--nav-indent); margin: 0px 0px 0px 0px;
  font: inherit; color: inherit; background: transparent; border: 0px;
  text-align: left; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ---- 本文 ---- */
/* 本文の面。**器（--bg）と箱（--surface）の真ん中**に置く。
   ライトは薄いクリーム、ダークは transparent（器の地をそのまま継ぐ）＝ --main-face が切り替える。
   ここを箱と同色にすると、白い箱が白い地に溶けて輪郭が消える。 */
.site-main {
  grid-area: main; min-height: 0; overflow-y: auto;
  padding: 0px var(--main-pad) 64px var(--main-pad); background: var(--main-face);
  /* `scrollIntoView` は要素の上端を枠の上端に合わせるので、貼り付いている
     見出し（`.page-head--sticky`）の**裏側**に停まる。その高さぶん手前で停める。
     高さは page-head の JS が実測して `--sticky-head-h` に入れる（決め打ちにしない
     ―― 見出しは説明文の行数と画面幅で伸び縮みする）。
     **送る枠に 1 回書く。** 送り先ごとに `scroll-margin-top` を書くと、
     新しい送り先を足した人が必ず忘れる。 */
  scroll-padding-top: var(--sticky-head-h, 0px);
}

/* 本文の中の節。左パネルの項目から `scrollIntoView` で送られてくる先。
   上の余白は**節どうしの間**のためで、停止位置の担保ではない
   （それは `.site-main` の `scroll-padding-top` が持つ）。 */
.site-main__section { padding: 48px 0px 0px 0px; }
/* **最初の節には上の余白を持たせない。** 上の余白は「節どうしの間」のためで、
   1 つめの上に居るのは節ではなく見出し ―― 全部に付けると最初の節だけ落ち窪む
   （`.site-main__anchor` と同じ理由。基本規約5 の「全部に上余白を付けない」がこれ）。 */
.site-main__section:first-child { padding: 0px 0px 0px 0px; }
.site-main__section p { padding: 8px 0px 0px 0px; font-size: 16px; color: var(--sub); }
.site-main__section code { font-family: var(--mono); font-size: 14px; color: var(--ink); }

/* 送り先の見出し。ここまで `scrollIntoView` で送られてくる。
   上の余白は間のためで、停止位置は `.site-main` の `scroll-padding-top` が決める。 */
.site-main__anchor { padding: 32px 0px 0px 0px; }
/* **最初の節には上の余白を持たせない。** 上の余白は「節どうしの間」のためで、
   1 つめの上に居るのは節ではなく見出し（.page-head）―― あちらが下線の下の空きを
   持っているので、足すと 16 + 32 = 48px になって最初の節だけ落ち窪む。
   （ここは余白を**作って**いるのではなく消している。だから基本規約5 に反しない） */
.site-main__anchor:first-child { padding: 0px 0px 0px 0px; }
.site-main__anchor-title {
  padding: 0px 0px 8px 0px;
  border-bottom: 1px solid var(--hairline);
  font-size: 16px; font-weight: 700; color: var(--ink);
}

/* ---- 内側の枠が送るとき、**送り棒は枠の端に出す** ----
   本文（.site-main）そのものが送るぶんには、棒は器の右端に出るので何もしなくてよい。
   問題は「見出しと絞り込みは動かさず、一覧だけ送る」形にしたとき。
   その枠は左右の余白のぶん内側にあるので、**棒が本文の途中に浮く**（縁から 40px 離れた所に線が立つ）。
   さらに棒の幅ぶん中身が狭まるので、送れる画面と送れない画面で本文の右端が揃わない。

   右の余白を外へ出し、**同じだけ負のマージンで戻す**。枠だけが器の端まで広がり、中身の位置は動かない。
   左も同じ手で、影や光りが切れないぶんだけ広げてよい。

   併せて守ること ―― **追従するもの（見出し・検索・絞り込みの帯・件数）を送る枠の中に入れない。**
   入れると棒がその横まで伸びて「動かないものの横に棒がある」状態になる。器はこう組む:
     枠（flex 縦）
       ├ 見出し・検索・帯・件数   … flex: 0 0 auto（送られない）
       └ 一覧・表                 … .site-main__flush（ここだけ送る） */
.site-main__flush {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 0px var(--main-pad) 8px 0px;
  margin: 0px calc(var(--main-pad) * -1) 0px 0px;
}
/* **空表示を器いっぱいに広げる、その1段。**
   `.empty-state` は `flex: 1` を持っているが、それは**親が伸びている flex コンテナの
   ときだけ**効く。`.site-main__flush` は既定で `display: block` なので、指定はあるのに
   無効だった ―― 実測で高さが中身なり（129px）になり、506px の器の上端に貼り付いて
   下に 377px 余っていた。self-check が言う「`:has` の伸長をメッセージまでの祖先すべてに
   連鎖させる」の、**器の側が持つべき1段をこちらが持っていなかった**。
   **空のときだけ**にするのは、表や一覧が入っている画面の並びを変えないため。 */
.site-main__flush:has(> .empty-state) { display: flex; flex-direction: column; }

/* ---------- 送って着いた節も、開いたパネルと同じ出方をする ----------
   左のパネルは中身が作り直されるたびに `revealIn` が走る（parts/nav-rail）。
   本文の節は一度作られたきりなので、素で同じ規則を当てると**読み込みの瞬間に
   全部の節が同時に**出終わり、送って着いたときには何も起きない
   （実測: `#sec-5-0` の算出値が `animation: none` ―― 左は出るのに本文は出なかった）。
   画面に入った節にだけ印（`data-in`）を付け、そこから**パネルと同じ速さ**で出す。

   **印が付くまでは何も当てない。** `.fade-in` のように素で `opacity: 0` を敷くと、
   JS が動かない環境で本文が丸ごと消える（あのパーツは実際それで真っ白になった）。
   ここは「印が付いたときだけ動く」ので、JS が無ければ**ただ静かに出ているだけ**。 */
.site-main__section[data-in] > * {
  animation: revealIn var(--reveal) cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--i, 0) * var(--stagger-step));
}

/* **本文まるごとには枠を出さない。**
   `<main class="site-main" tabindex="-1">` は「本文へ移動」の**着地点**として
   焦点を持てるようにしてあるだけで、押せるものではない。
   右から出る枠を Esc で閉じると、焦点は開いた場所へ返る途中でここに落ちることがあり、
   直前がキーボード操作なのでブラウザは `:focus-visible` と判定する
   ―― 結果、**画面の中央に 2px の青枠が 1 枚出る**（実測）。

   枠の役目は「次にキーを打つとどこが動くか」を示すこと。本文全体を囲っても
   行き先は分からず、面が光ったようにしか見えない。送って着いたこと自体が合図になる。
   個々の行やボタンの枠は今までどおり出る（ここで消しているのは器だけ）。

   **焦点を外すのではなく枠だけ消す**（`blur()` すると「本文へ移動」で飛んだあと
   Tab がページの先頭に戻ってしまう）。
   **base-reset ではなくここに置く** ―― `.site-main` の持ち主はこのパーツで、
   横断パーツが他パーツのクラスを持つと ⑬ カスケード順と ㉒ 根は 1 つに触れる。 */
.site-main:focus-visible,
.site-main__flush:focus-visible { outline: none; }

/* ============================================================
   ページ見出しと説明文 — **全画面でここ 1 か所だけがサイズを決める**
   画面ごとに見出しサイズを変えない。揃っていないと「別のシステム」に見える。
   正典の解説: references/page-head.md
   ============================================================ */
.page-head {
  flex: 0 0 auto;
  padding: 0px 0px 12px 0px;
  border-bottom: 1px solid var(--hairline-strong);
  /* **下線の下を必ず空ける。** 空けないと、直後に枠を持つ箱（表・カード）が来る画面で
     下線と箱の枠が接し、**下線が箱の枠にしか見えない** ―― 同じ見出しなのに
     「線がある画面と無い画面」が生まれる（実測: 一覧は表が下線の 0px 下から始まり、
     節から始まる画面だけ線が見えていた）。空きは見出しが持つ。
     下に来るものの側で持たせると、新しい画面を作る人が必ず忘れる。 */
  margin: 0px 0px 16px 0px;
}

/* 見出しは要素でもクラスでも同じ体裁になる。
   新規は `h1`（マークアップが素直）、既存プロジェクトに後入れするときは
   `.page-head__title` を足すだけで揃えられる ―― どちらか一方に強制しない。

   **見出しの段は h1 に限らない。** かつては `.page-head h1` だけを整えていて、
   `<h2>` を置いた配備先で**字が 18px になっていた** ―― 規則が当たらず、
   ブラウザ既定の 1.5em が親の 12px に掛かった値。文書の外形上 h2 や h3 が正しい画面
   （1 枚に節が並ぶ画面・下位の階層）は普通にあるので、**段は書き手が決め、
   見た目はここが決める**。`:is()` で 3 段とも受ける。
   `bin/check-font-size.py` が算出値で見つけた（CSS の grep では出ない ―― 書いていないのだから）。 */
.page-head :is(h1, h2, h3),
.page-head__title {
  font-size: 20px; font-weight: 800; letter-spacing: 0.01em; line-height: 1.2;
  color: var(--ink);
  text-wrap: balance;
  margin: 0px 0px 0px 0px;
}

/* 説明文は**ペインの幅をそのまま使う**。`max-width: 62ch` は読み物（記事）の値で、
   管理画面の注記に当てると 1 行が短くなりすぎて読みにくい。 */
.page-head p,
.page-head__sub {
  font-size: 14px; color: var(--sub); margin: 0px 0px 0px 0px;
  /* 日本語は約物以外どこでも折れるので、狭い注記だと「選ん／でください。」と
     中途半端な位置で切れる。文節で折り、行頭に句読点が来ないようにする。 */
  line-break: strict;
  word-break: auto-phrase;
}
.page-head p + p,
.page-head__sub + .page-head__sub { padding: 4px 0px 0px 0px; }

/* 見出しと説明文のあいだ。**説明文が続くときだけ**見出しが下余白を持つ。
   どちらも margin: 0 で、あいだが**実測 0px** だった ―― 20px の見出しの
   すぐ下に 13px の注記が続き、2 行で 1 つの見出しのように見える。
   常には持たせない（`:has` で絞る）―― 説明文が無い画面まで下の罫までが
   12px から 20px に伸びて、見出しだけの画面と並べたとき高さがずれる。 */
.page-head :is(h1, h2, h3):has(+ p),
.page-head :is(h1, h2, h3):has(+ .page-head__sub),
.page-head__title:has(+ p),
.page-head__title:has(+ .page-head__sub) { margin: 0px 0px 8px 0px; }

/* ---------- 見出しの右にボタンを置くとき ---------- */
.page-head--action {
  display: flex;
  align-items: flex-start;      /* center にしない。説明文が 2 行のとき見出しが下がる */
  justify-content: space-between;
  gap: 16px;
}
/* display:flex は [hidden]（UA スタイル）に勝つ。打ち消さないと、詳細を開いても
   一覧側の見出しが残って見出しが二重に出る。 */
.page-head--action[hidden] { display: none; }
.page-head__action { flex: 0 0 auto; width: auto; }

/* ---- 狭い画面: 見出しと釦を縦に積む（中身の分岐幅 768。骨組みの 899 とは別）----
   横に並べたままだと、釦が縮まないぶん見出しが 1 文字ずつ縦に折れる。
   釦は 1 つずつ縦に積まず、横に並べて折り返す（積むと縦に伸びるだけ）。
   **大きさをそろえるのは `parts/button`**（`.page-head__action > .btn`）。
   ここは並べ方だけを持つ ―― 同じことを 2 か所で決めない。 */
@media screen and (max-width: 768px) {
  .page-head--action {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .page-head__action {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }
}

/* ---------- スクロールしても上に残す（ページ先頭の見出しだけ） ---------- */
/* 送るのは `.site-main` なので、その中で貼り付ける。
   **本文中の節見出しには付けない** ―― `.page-head` は節ごとにも使うので、
   全部に付けると送るたび次々に貼り付いて上に積み重なる。付けてよいのは
   ページ先頭の 1 つだけ。だから既定にはせず modifier で明示的に選ばせる。 */
.page-head--sticky {
  position: sticky;
  top: 0px;
  z-index: 1;
  /* 下を流れてくる本文が透ける。飾りの塗りではなく**地**を敷いて塞ぐ
     （透明のままだと文字が重なって読めない）。
     **隠す相手＝本文の面と同じ色でなければならない。** 別の色にすると、
     貼り付いた帯だけ違う面が乗ったように見える（実際そうなった）。

     ただし `--main-face` は**暗いときだけ transparent**（本文に面を敷かず器の地を
     そのまま継ぐ設計）。これ 1 つだけを敷くと、暗いときは塞げない ――
     実測で `rgba(0, 0, 0, 0)` になり、送った本文が見出しに重なって出た。
     器の地を下に、本文の面を上に、**2 枚**敷く。ライトは面が乗り、ダークは器の地が出る。 */
  background-color: var(--bg);
  background-image: linear-gradient(var(--main-face), var(--main-face));
  /* 貼り付いたとき見出しが枠の上端に接しないよう、**上余白も自分で持つ**。
     ここを外に出す（前にスペーサーを置く）と、その高さぶん**送ってから貼り付く**＝
     動いて見える。実際 `.main-spacer-top`（32px）が前に居て 32px 動いていた。 */
  padding: 32px 0px 12px 0px;
}

/* **追従するものを送る枠の中に入れない。**
   検索欄・絞り込みの帯・件数の行は送られない側なので、送る枠の**外**（兄弟）に置く。
   中に入れると、送り棒がその横まで伸びて「動かないものの横に棒がある」状態になるうえ、
   棒のぶん本文の幅が縮む。器はこうする ――
     枠（flex 縦）
       ├ 見出し・検索・帯・件数   … flex: 0 0 auto（送られない）
       └ 一覧・表                 … flex: 1 1 auto; overflow-y: auto（ここだけ送る）
   確かめ方: 送る枠を洗い、その中に position: sticky や固定の子が居ないこと。

   **送る枠の最初の子にする。** `position: sticky` は「流れの位置まで送られてから」
   貼り付くので、前に何か（スペーサー・パンくず・ツールバー）を置くと、その高さが
   そのまま「動く範囲」になる。上の余白が欲しいならこの要素の padding を増やす。
   `tools/check-consistency.mjs` の ⑧ がこれを見張る。 */

/* 見出しの右に置く釦（parts/button を借りる）。**button 側から page-head を触らない** ―― 根は 1 つ */

/* ---------- 一覧の行（下線区切り・ホバーで下線が伸びる） ---------- */
.row-list { border-top: 1px solid var(--line); margin: 0px 0px 24px 0px; }
.row-list__item {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    width: 100%;
    padding: 16px 0px 16px 0px;
    border: 0px;
    border-bottom: 1px solid var(--line);
    background: transparent;
    text-align: left;
    cursor: pointer;
}
.row-list__item::after {
    content: "";
    position: absolute;
    left: 0px;
    bottom: -1px;
    width: 0px;
    height: 1px;
    background: var(--accent);
    transition: width var(--underline) ease;
}
.row-list__item:hover::after { width: 100%; }
/* 行は画面を開いたら 1 つずつ現れる。表の行と**同じ動き・同じ刻み**（仕草は parts/tokens の revealIn 1 つ）
   ―― 一覧の形が表でも行でも吹き出しでも、入場の見え方は 1 つ。番号（--i）は JS が配る。 */
html[data-js] .row-list__item { animation: revealIn var(--reveal) cubic-bezier(0.22, 1, 0.36, 1) backwards; animation-delay: calc(var(--i, 0) * var(--stagger-step, 70ms)); }
/* **開いている 1 件（いま右の枠・別ペインで見ているもの）は下線ではなく枠で囲む。**
   下線は「触っている／いまのページ」を示すもので、行の下端 1 本にしか出ないため、
   隣の行の上端と見分けがつかず「どれを開いているか」が読めない。
   表の行と同じ inset の影 ＋ 薄い地にそろえる（data-table.md §4-d と同じ見せ方＝
   一覧の形が表でもカードでも吹き出しの一覧でも、開いている 1 件の見え方は 1 つ）。
   枠を引くぶん、字は左右に 12px 入れる（枠と字が貼り付くと窮屈に見える）。 */
.row-list__item--open {
    padding: 16px 12px 16px 12px;
    box-shadow: inset 0px 0px 0px 1px var(--accent);
    background: color-mix(in srgb, var(--accent) 8%, var(--bg));
}
.row-list__item--open::after { width: 0px; }
.row-list__item--open .row-list__item-name { color: var(--accent); font-weight: 800; }
.row-list__item-name { font-size: 16px; font-weight: 700; line-height: 1.5; color: var(--ink); }
.row-list__item-note { font-size: 16px; color: var(--mute); }

/* ---------- 空表示 ---------- */
.empty-state {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-height: 0;
    margin: 0px 0px 0px 0px;
    padding: 32px 32px 32px 32px;
    text-align: center;
    color: var(--mute);
    font-size: 16px;
    line-height: 1.9;
}
.empty-state[hidden] { display: none; }
/* 空表示も画面を開いたときに現れる（表の行・一覧の行と同じ入場）。
   ただし**動かさず、明るさだけ**で出す ―― 真ん中に置いた 1 かたまりが上下に動くと、
   読む前に位置が変わって落ち着かない。長さは「読ませる文」なので行の入場より少し長い。
   `html[data-js]` のときだけ動かす（JS が動かない環境で出てこなくならないように）。 */
html[data-js] .empty-state { animation: paneEmptyIn 0.6s ease backwards; animation-delay: 80ms; }
@keyframes paneEmptyIn { from { opacity: 0; } to { opacity: 1; } }

/* ---- 知らせの面（注意書き・できない理由）----
   **これは「行」ではなく「面」なので、塗ってよい**（構造的不変条件 1 の例外ではなく、
   そもそも対象外 ―― 塗ってはいけないのは状態を持つ操作の行・タブ・item）。
   地は `--sunken`（器と同じ高さまで落とした沈み）で、面より下に見せる。

   3 つの大きさを 1 つの部品で持つ:
     .notice            … 本文の上に置く帯（1〜3 行）
     .notice--warn      … 気をつけて読ませるもの。**枠と字の色だけ**変える
     .notice--block     … 操作そのものを出せないときに、操作の代わりに置く面

   **`--warn` で地を赤く塗らない。** 暗いテーマは地が暗く、赤の字に余裕が無い
   ―― どんな塗りを重ねても AA を割る（ボタンの色と同じ理由）。 */
.notice {
  margin: 0px 0px 24px 0px;
  padding: 12px 16px 12px 16px;
  border: 1px solid var(--hairline-strong);
  border-radius: 4px;
  background-color: var(--sunken);
  font-size: 16px;
  line-height: 1.8;
  color: var(--sub);
}
.notice--warn { border-color: var(--warn); color: var(--warn); }

/* **2 文以上あるときは中に `<p>` を積む**（1 文 = 1 段落・基本規約 #9）。
   段落として離さず、行送りぶんだけ空ける ―― 帯の中で段落が離れると、
   1 つの知らせが 2 つに見える。 */
.notice p + p { margin: 4px 0px 0px 0px; }

/* 操作の代わりに置く面。**できない理由を出したまま操作を残さない** ――
   「送っても失敗します」と書いた横に送る釦があると、人は送る（実際に送った）。 */
.notice--block {
  padding: 24px 24px 24px 24px;
  border-color: var(--warn);
}
.notice__title {
  margin: 0px 0px 8px 0px;
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
}

/* ---- 状態の印（タグ）----
   **表の中にあった定義をここへ出した。** 状態の印は表だけのものではない
   ―― 詳細画面では名前と値の対（parts/kv）の中に出るし、行の中にも出る。
   表のパーツに置いていたので、**表を持っていかない画面には状態の印が来なかった**
   （配備先は `.kv` の中で使っている）。

   **塗らない。** 枠と字だけで、色は `currentColor` から取る
   ―― 塗ると「押せる面」に見えて、押しに来る。 */
.tag {
  display: inline-flex; align-items: center; height: 24px;
  padding: 0px 8px 0px 8px; border-radius: 4px; border: 1px solid currentColor;
  /* 【2026-09-11】等幅（--mono）をやめた。札に入るのは「有効」「規約未同意」
     「管理者」といった**語**で、桁をそろえる相手がいない。一覧に並べたとき
     ここだけ字面が変わり、状態が別の種類の情報に見えていた（下帯と同じ申し送り）。 */
  font-size: 14px;
  /* **自分の色を薄く敷く**（釦と同じ式・同じトークン）。枠と字だけの札は、
     一覧に並んだとき「ただの字」に見えて状態として拾えなかった。
     `currentColor` 混ぜなので、段を増やしても地が自動で付いてくる。
     ダークは塗らない（トークンが transparent）。 */
  background-color: var(--btn-face);
}
/* 危ないほうは 2 つとも `--warn`。**緑は使わない**（トークンの `--success` はアクセント色） */
.tag--ok { color: var(--success); } .tag--warn { color: var(--warn); } .tag--ng { color: var(--warn); }

/* ---- 名前と値の対（定義リスト）----
   **右パネルの中にあった定義をここへ出した。** 名前と値を並べるのは詳細画面の本文でも
   同じで、パネルのパーツに置いていたので**パネルを持っていかない画面には来なかった**
   （配備先は本文の「内容」節で使っている）。しかも器の左右余白（24px）まで
   一緒に付いてきて、本文に置くと理由の無い字下げになっていた。

   **器の余白は器が持つ**（`.side-panel .kv`）。部品そのものは持たない。

   名前の列は 96px 固定。中身なりにすると、節をまたいだとき値の頭がそろわない。 */
.kv {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 12px;
  margin: 0px 0px 0px 0px;
  padding: 0px 0px 0px 0px;
  font-size: 16px;
  color: var(--ink);
}
/* 名前は弱い字。**値と同じ濃さにしない** ―― どちらが答えか読めなくなる */
.kv dt { color: var(--mute); font-size: 14px; }
.kv dd { margin: 0px 0px 0px 0px; }

/* ---- 説明の箇条書き（右パネル・注記）----
   「この画面でできること」のような**読ませる並び**。一覧の行（parts/list-row）とは別物で、
   押せないし状態も持たない ―― だから下線も引かない。

   印は `::before` の矢印で描く。**絵文字を使わない**（環境ごとに大きさと縦位置が変わり、
   行の頭がそろわない）。`list-style` を使わないのは、印の色を字と変えられないため。 */
.aside-list {
  margin: 0px 0px 16px 0px;
  padding: 0px 0px 0px 0px;
  list-style: none;
}
.aside-list li {
  position: relative;
  margin: 0px 0px 8px 0px;
  padding: 0px 0px 0px 16px;
  line-height: 1.8;
}
.aside-list li::before {
  content: "→";
  position: absolute;
  left: 0px;
  top: 0px;
  color: var(--accent);
}
.aside-list li:last-child { margin: 0px 0px 0px 0px; }
/* 頭の語だけ立てる。**行ごと太字にしない** ―― 並べたとき、どれが要点か読めなくなる */
.aside-list__term { display: block; font-weight: 700; color: var(--ink); }

/* ---- 本文の中のリンク ----
   **下線基調の UI なのに、本文のリンクだけ決まりが無かった。** 土台は
   `a { color: inherit; text-decoration: none; }`（parts/base-reset）で下線を落としているので、
   何も足さないと本文中のリンクが**ただの字**になる ―― 押せることが分からない。

   下線は**行やタブと同じ語彙**で引く（`::after` を伸ばす）。ブラウザ既定の
   `text-decoration` に戻さないのは、字の下すれすれに出て伸びないため
   ―― 1 画面の中に「伸びる下線」と「伸びない下線」が混ざる。

   **下線は文字幅に合わせる**（`display: inline-block`）。行いっぱいに引くと、
   短いリンクの右に線だけが伸びる。 */
.link-underline {
  position: relative;
  display: inline-block;
  max-width: 100%;
  padding: 0px 0px 4px 0px;
  color: var(--accent);
}
.link-underline::after {
  content: "";
  position: absolute;
  left: 0px;
  bottom: 0px;
  width: 0px;
  height: 1px;
  background-color: var(--accent);
  transition: width var(--underline) ease;
}
.link-underline:hover::after { width: 100%; }
/* **焦点でも出す。** ホバーだけだと、キーボードで来た人には
   「いまどのリンクに居るか」が輪郭でしか分からない。 */
.link-underline:focus-visible::after { width: 100%; }

/* ---- ページ送り ----
   **前後だけ**にする。件数が数十のうちはページ番号を並べる意味が無く、
   番号を並べると「1 2 3 … 47」の 47 が押されて、戻ってこられなくなる。

   釦は `parts/button` をそのまま使う ―― 送りのためだけの釦を作らない。
   押せない側は `aria-disabled="true"` を付ける（`.btn[aria-disabled]` が薄くする）。
   `<a>` を消して穴を空けない ―― 消すと押す場所が左右に動いて、
   端に着いたときだけ「次へ」の位置がずれる。

   いま何枚目かは `.page-head__sub`（parts/page-head）で書く。**新しい字の大きさを作らない。** */
/* **横は真ん中にそろえる。** 左に寄せていたが、送りは表の下に 1 つだけ置く操作で、
   表は器の幅いっぱいに広がる ―― 左端に寄せると、幅の広い画面では表の右 3 分の 2 に
   何も無く、「次へ」を探しに視線が左下まで戻ることになる。真ん中なら表の中心線の
   延長にあり、どの幅でも同じ場所に居る。 */
.pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin: 24px 0px 0px 0px;
}
.pager__at { margin: 0px 0px 0px 0px; }

/* ボタンは 3 種。**どれも押す前から色を持ち、ホバーで変わるのは地だけ**。
   ホバーで初めて色が付く作りだと、押そうとした時点でしか意味が分からない。

     .btn           中立（既定）      枠 hairline-strong / 字 ink
     .btn--primary  すすめる操作      枠・字ともアクセント（青）
     .btn--danger   取り返しが要る    枠・字とも warn（赤）

   **押す前から地を持つ**（`--btn-face` / `--btn-face-primary` / `--btn-face-danger`）。
   枠と字だけだと、明るい地の上で「読む字」と見分けが付かず、載せて初めて押せると分かる。

   **ここは一度ひっくり返している。** 長らく「自分の色では塗らない（無彩のごく薄い地）」で、
   理由は「赤い釦が並ぶと、その行だけ警告が鳴っているように見える」「字とのコントラストを削る」。
   5% の無彩 → 白（--surface）と上げても地味だという判断で、**自分の色を薄く敷く形**にした。
   決めたのは作者。薄さは 10% 止まりで、字が沈まない範囲に置いてある（値は parts/tokens）。
   ダークは塗らない（3 つとも transparent）。
   地は線より遅く変える（0.4s）―― 枠の色は動かないので、変化は地だけが担う。 */
.btn {
  /* **`<button>` 前提にしない。** `<a>` や `<span>` に同じ class を付けると
     inline のままで height が効かず、字が上に寄る（実測で上下 3〜8px ずれていた）。
     どの要素で使っても同じ箱・同じ中央になるよう、ここで並べ方まで決める。 */
  display: inline-flex; align-items: center; justify-content: center;
  line-height: 1; white-space: nowrap;
  /* 高さは**入力欄と同じ 36px**。34px だった ―― 並べたとき 2px 低く、
     4 の倍数からも外れていた（form-fields の .field input と同値にそろえる）。 */
  height: 36px; padding: 0px 16px 0px 16px; border-radius: 4px;
  /* 中立の字は `--grey`。`--ink` にすると `--primary` のキーカラーと**明るさが 0.02 しか違わず**、
     小さな釦では「すすめる操作」と「ふつうの操作」が見分けられない（実測）。
     薄くして退かせ、色の付いた釦を前へ出す。 */
  border: 1px solid var(--btn-line); color: var(--btn-ink); font-size: 14px;
  background-color: var(--btn-face);
  transition: background-color var(--tint) ease;
}

/* 地は `.btn` の `--btn-face` が持つ（`currentColor` 混ぜなので、色を変えれば地も付いてくる）。
   **種類ごとに地を書き足さない** ―― 書き足すと、字の色だけ変えた新しい種類に地が付かない。 */
.btn--primary { border-color: var(--accent); color: var(--accent); }

.btn--danger { border-color: var(--warn); color: var(--warn); }

/* ホバーも一段濃く。3 種ぶん書いていたのを 1 つに畳んだ。
   **式を直に書かず、休止と同じくトークンを読む**（2026-09-11）――
   直に書いていたせいで「ダークは塗らない」がホバーに効かず、
   暗いときだけ主要と破壊的が AA を割っていた（濃さの根拠は parts/tokens）。 */
.btn:hover { background-color: var(--btn-face-hover); }

/* 押せない釦。**薄くするだけにしない**（opacity で全部薄めると字が読めなくなる）。
   字と枠を弱い色に落とし、地は持たせない ―― 「押せる面」に見せないため。 */
.btn[disabled], .btn[aria-disabled="true"] {
  color: var(--mute);
  border-color: var(--hairline);
  background-color: transparent;
  cursor: not-allowed;
}

.btn[disabled]:hover, .btn[aria-disabled="true"]:hover { background-color: transparent; }

.toolbar { display: flex; align-items: center; gap: 8px; padding: 16px 0px 12px 0px; flex-wrap: wrap; }

.toolbar__spacer { margin: 0px 0px 0px auto; }

/* ============================================================
   8. 入力欄
============================================================ */
.field { margin: 0px 0px 12px 0px; }
.field label {
    display: block;
    font-size: 16px;
    font-weight: 500;
    color: var(--mute);
    margin: 0px 0px 8px 0px;
}
.field input,
.field select {
    width: 100%;
    height: 36px;
    padding: 0px 12px 0px 12px;
    font-family: inherit;
    font-size: 16px;                /* 16 未満は iOS が拡大する。スケールの例外 */
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--hairline-strong);
    border-radius: 4px;
    transition: border-color var(--color) ease;
}
/* プルダウンの矢印。**ブラウザ既定の矢印は枠の右端に貼り付いていて、字とも枠とも間が無い。**
   自分で下向きのくの字を描き、右に 12px・字との間に 12px 空ける（右の内余白 36px）。
   **回さない。** 開閉に合わせて回す近似は、閉じても上向きのまま固まる
   （select はフォーカスを保持し続けるため＝ custom-select.md）。
   動かしたいならネイティブを隠して自前 UI を重ねる ―― どちらかにする。
   矢印は背景画像なので CSS 変数の色を読めない。テーマ 3 状態ぶん書き分ける
   （字と同じ `--mute` 相当の値を直に書く。ここだけの例外）。 */
.field select {
    appearance: none;
    padding: 0px 36px 0px 12px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8L9.5 4.5' fill='none' stroke='%236b7280' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 12px 12px;
}
:root[data-theme="dark"] .field select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8L9.5 4.5' fill='none' stroke='%239aa2b0' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .field select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8L9.5 4.5' fill='none' stroke='%239aa2b0' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
}
.field textarea {
    width: 100%;
    padding: 8px 12px 8px 12px;
    font-family: inherit;
    font-size: 16px;
    line-height: 1.6;
    color: var(--ink);
    background: var(--surface);
    border: 1px solid var(--hairline-strong);
    border-radius: 4px;
    resize: vertical;
    transition: border-color var(--color) ease;
}
.field input:focus,
.field select:focus,
.field textarea:focus { outline: none; border-color: var(--accent); }

/* ---- 補足と誤り ----
   **入力欄はあったのに、誤りの出し方が無かった。** 送って戻ってきた画面で
   「何が悪かったのか」を出す場所が決まっていないと、各画面が自分で作る
   ―― 実際、ある配備先は 10 箇所で自前のクラスを使っていた。

   どちらも欄の**下**に置く。上に置くと、入力中の欄が誤りの行のぶん下へ動く。

   **誤りを地の色で塗らない。** 暗いテーマは地が暗く、赤の字に余裕が無い
   （ボタン・知らせの面と同じ理由）。字の色と、下の欄の枠だけで示す。 */
.field__note {
  margin: 8px 0px 0px 0px;
  font-size: 14px;
  line-height: 1.8;
  color: var(--mute);
}
/* 2 つめ以降は詰める。1 文 = 1 段落で割ると、補足のあいだが空きすぎる */
.field__note + .field__note { margin: 0px 0px 0px 0px; }
.field__error {
  margin: 8px 0px 0px 0px;
  font-size: 14px;
  line-height: 1.8;
  color: var(--warn);
}
/* 誤りのある欄は枠でも示す。**色だけに頼らない**（色が分かりにくい人には何も伝わらない） */
.field:has(> .field__error) input,
.field:has(> .field__error) select,
.field:has(> .field__error) textarea { border-color: var(--warn); }
/* ラジオ・チェックは「四角い入力欄」ではないので共通指定から外す */
.field input[type="radio"],
.field input[type="checkbox"] {
    width: auto;
    height: auto;
    padding: 0px 0px 0px 0px;
    background: none;
    border: 0px;
    flex: 0 0 auto;
}
.field label:has(> input[type="radio"]),
.field label:has(> input[type="checkbox"]) {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 0px 0px 0px 0px;
    font-weight: 400;
    color: var(--ink);
    cursor: pointer;
}
/* オートフィルの黄色は background では消えない。適用を超長 transition で無効化する */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
select:-webkit-autofill {
    -webkit-text-fill-color: var(--ink);
    caret-color: var(--ink);
    transition: background-color 9999s ease-in-out 0s;
}

/* ---- 入力の手がかり（placeholder）。解説: references/form-fields.md ---- */
.field input::placeholder,
.field textarea::placeholder {
  color: var(--mute);      /* 値（--ink）よりはっきり弱く。ただし読める濃さを保つ */
  opacity: 1;              /* Firefox は既定で薄める。二重に薄くしない */
}

/* ---- ファイルの欄 ----
   中の釦（`::file-selector-button`）は**欄の中身**なので、ほかの欄の字と
   同じ列から始める。左の内余白をここだけ 8px に詰めていて、**釦の枠だけが
   列から 3px はみ出していた**（実測。他の欄は padding-left 12px ＝ 字が x+12 から）。
   欄の中で最初に目に入るのは釦の枠なので、そこを列に載せる。

   高さも 36px のまま ―― 「native の釦が窮屈に見える」と 44px にして戻した。
   1 行だけ背が高いと、上下の欄と段が合わずに**行そのものがずれて見える**。
   窮屈さは釦を 28px に抑えて内側で解く（欄の中身 34px に対して上下 3px ずつ）。

   体裁は `.btn` の小さいほうにそろえる。ここだけ別の釦に見せない。 */
.field input[type="file"] {
  display: flex;                  /* 中身（釦とファイル名）を縦中央に置く */
  align-items: center;
}
.field input[type="file"]::file-selector-button {
  height: 28px;
  margin: 0px 12px 0px 0px;
  padding: 0px 12px 0px 12px;
  border: 1px solid var(--hairline-strong);
  border-radius: 4px;
  background: var(--btn-face);
  color: var(--ink);
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: background-color var(--tint) ease;
}
.field input[type="file"]::file-selector-button:hover {
  background: color-mix(in srgb, var(--ink) 8%, transparent);
}

/* ---- ファイルを選ぶ欄 ----
   **釦の字を自分で決めるため**にある。素の `input[type="file"]` は
   `::file-selector-button` に体裁だけ足せるが、**字はブラウザが持っていて変えられない**
   ―― 日本語の画面に「Choose File / No file chosen」と英語で出る（実測）。
   言い回しをそろえられない部品が 1 つだけ画面に残ることになる。

   作り: 本物の `input` を**残したまま透明にして釦の上に重ねる**。
   **`display: none` で隠す道は採らない** ―― 送り（Tab）の順から外れて、
   キーボードだけでは選べない欄になる。透明なら焦点は当たり、Space で開く。
   実測: 釦の中心を押すと当たるのは `.file-pick__input`（本物が開く）で、
   送りの順にも残っている。

   釦の見た目は **parts/button をそのまま借りる**（`.btn` を一緒に付ける）。
   選ぶための釦を別に作らない ―― 1 画面に 2 種類の釦の作法ができる。

   **`--primary`（すすめる操作）を付ける。** この欄でやることは「選ぶ」の 1 つだけで、
   迷う相手が居ない ―― 中立の釦にすると、注記に埋もれて入口が見つからない。
   赤（`--danger`）は使わない。選び直しは取り返しがつく操作なので。 */
.file-pick {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

/* 釦と、その上に重ねる本物の入力欄を入れる箱。
   重ねる相手が釦だけなので、行いっぱいが押せてしまうことはない
   ―― 行ごと押せると、名前を選ぼうとした指でファイル選択が開く。 */
.file-pick__slot {
  position: relative;
  display: inline-flex;
  flex: 0 0 auto;
}

.file-pick__input {
  position: absolute;
  inset: 0px;
  width: 100%;
  height: 100%;
  /* **消さずに透かす。** `display: none` / `visibility: hidden` は
     Tab の順から外れる（＝キーボードだけでは開けない欄になる）。 */
  opacity: 0;
  cursor: pointer;
}
/* 焦点の輪郭は**釦のほうに描く**（透明な入力欄に描いても見えない）。
   太さと色は土台の `:focus-visible` と同じ ―― ここで別の輪郭を作らない。 */
.file-pick__input:focus-visible + .btn {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* ホバーも釦へ渡す。重なっているのは入力欄なので、釦は自分では気づけない。
   **式は parts/button の `.btn:hover` と同じ**にする ―― ここだけ `--hover-face` にしていて、
   この釦だけ載せたときの色が違っていた（見直しで見つけた）。 */
/* 隠した input に載せたときも、釦と同じ地にする。**式を直に書かずトークンを読む**
   （2026-09-11）―― 直に書いていると、ダークの上限（2%）や枠の中の面の色が効かず、
   ここだけ `.btn:hover` と違う地になる。 */
.file-pick__input:hover + .btn { background-color: var(--btn-face-hover); }

.file-pick__icon { width: 16px; height: 16px; margin: 0px 8px 0px 0px; flex-shrink: 0; }

/* 選んだファイルの名前。**空にしない** ―― JS が動かない環境でも
   「まだ選んでいない」と読めるよう、初期の字は HTML に置く。 */
.file-pick__name {
  margin: 0px 0px 0px 0px;
  min-width: 0px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
  overflow-wrap: anywhere;
}
/* まだ選んでいないときは一段落とす（値ではなく状態なので） */
.file-pick__name[data-empty="1"] { color: var(--mute); }
/* 誤りがあるときは**名前のほう**を赤くする。**釦を赤くしない** ――
   赤い釦は「取り返しのつかない操作」の色（`.btn--danger`）で、選び直すのは危なくない。
   悪いのは選ばれた値なので、値に印を付ける。

   **`.field` の側から辿らない。** `.field:has(> .field__error)` と書くと、
   この部品が `.field`（parts/form-fields の持ち物）を定義していることになる
   ―― 検査 ① が名前の衝突として落とす。誤りは**入力欄そのものが `aria-invalid` で持つ**
   ので、そちらを見る（読み上げが読むのと同じ印を見ることになる）。 */
.file-pick:has(.file-pick__input[aria-invalid="true"]) .file-pick__name { color: var(--warn); }

/* 大きさは名前の後ろに、等幅で。**別の行にしない** ―― 1 件 1 行で読ませる */
.file-pick__size { color: var(--mute); font-family: var(--mono); }

/* 狭いときは縦に積む。横に並べたままだと、長いファイル名が釦を押しつぶす */
@media screen and (max-width: 768px) {
  .file-pick { align-items: flex-start; flex-direction: column; gap: 8px; }
}

/* 一覧の表 — **見出しと中身を別の表に分ける**。送るのは中身のほうだけ。
   sticky な thead を送る枠の中に入れると、棒が見出しの横まで伸びて
   右端が切れる（＝見出しにも棒があるように見える）。
   列がずれないよう、両方に同じ colgroup と `table-layout: fixed` を入れる。 */
/* **枠には面を敷く（--surface）。** 表はトークンの並びが「箱」と呼んでいるもの
   ―― 器の上に置く箱（カード・表の枠・右から出る枠・図）は --surface、という
   割り当てをここでも守る。敷かないと 2 つ壊れる:
     ・ライトの縞（--stripe）が消える。あれは**白い面の上のクリームの帯**として
       決めた色なので、本文の地（--main-face #f7f4ed）の上に乗せると
       #fcf9f1 との差が青 1 階調になって見えない（実測）
     ・ダークで箱が地に沈む。暗いところは「持ち上げた面と影」で箱を見せるのに、
       枠線 1 本だけになる
   狭い画面に畳んだときの行（下の @media）は前から --surface を敷いており、
   **広い画面だけ抜けていた**。 */
.data-table__wrap {
  border: 1px solid var(--hairline-strong); border-radius: 4px; overflow: hidden;
  display: flex; flex-direction: column; max-height: 44vh;
  background: var(--surface);
}
/* 中身の側は棒のぶん狭い。見出しにも**測った値と同じだけ**余白を入れて右端をそろえる。
   固定値にしないのは、送るものが無ければ 0・Firefox の太い棒なら約 11px と
   環境で変わるため（JS が offsetWidth - clientWidth を書く）。 */
/* **下線は表ではなく枠のほうに引く。** `th` に引くと、右の余白（棒のぶん）は
   表の外なので線が枠の手前で切れ、右上に細い切れ込みが見える。
   枠は余白を含んだ幅を持っているので、ここに引けば列は合ったまま線だけが端まで届く。 */
.data-table__head {
  flex-shrink: 0;
  background: var(--surface);
  border-bottom: 1px solid var(--hairline-strong);
}
.data-table__scroll { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; }
table { width: 100%; border-collapse: collapse; font-size: 14px; table-layout: fixed; }
/* 列の名前は**太字**（700）。600 だと本文（400）との差が字面に出ず、
   帯の色と字の弱さ（--mute）だけで「見出しである」と言っていた。
   太さは製品の段のうち「強い本文」に当たる 700 ―― 見出しの 800 は
   ページ見出し（.page-head h1）が使う段なので、そこまでは上げない。
   色は --mute のまま。太くしたぶん、濃さまで上げると帯が主役になる。 */
thead th {
  /* **横は中央にそろえる。** 見出し・数字・札（完了 / 要対応）を 1 本の軸に乗せる。
     **一度これを左にしていて、戻した。** 桁ごとに寄せが変わると（名前は左・数は右・
     札は中央）、目が列の頭を探し直すことになって表の軸が読めない。
     文章の桁だけは `.data-table__start` で左に残す（下）。 */
  text-align: center; font-weight: 700; color: var(--mute);
  padding: 8px 12px 8px 12px;
  /* **本文（13px）より大きくする。** 12px だった ―― 列の名前が中身より小さく、
     「見出しである」ことを色と字間だけで言っていた。
     太さでは足りない: 和文フォントは 600 と 700 が同じ面に落ちることがあり
     （Noto Sans CJK は Regular / Medium / Bold / Black の 4 段しか持たない）、
     実測でインク量が 600 と 700 で同値（7.63%）＝**字面が 1px も変わらない**。
     大きさは環境に関わらず必ず効くので、そちらで差を付ける。 */
  font-size: 16px; letter-spacing: 0.04em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  /* **見出しと中身のあいだの線。** ふだんは枠（.data-table__head）が引く ―― th に引くと
     右の余白（棒のぶん）は表の外なので、線が枠の手前で切れて右上に切れ込みが出る（上の注記）。
     ところが**枠を持たない単体の表**（1 枚で完結する表）は誰も引かず、実測で
     `border-bottom: 0px none` ―― 見出しと中身が地続きになって、どこまでが見出しか読めない。
     そこで既定は th が引き、枠があるときだけ下（.data-table__head thead th）で消す。 */
  border-bottom: 1px solid var(--hairline-strong);
}
/* 枠が引くので、th は引かない（2 本になる） */
.data-table__head thead th { border-bottom: none; }
/* 中身も見出しと**同じ軸**に乗せる。片方だけ中央にすると、列の名前と中身が
   ずれて見える ―― 見出しは別の表（.data-table__head）なので、揃え方を書き忘れると
   そこだけ左に残る（実際そうなっていた）。 */
tbody td {
  padding: 8px 12px 8px 12px; border-bottom: 1px solid var(--hairline);
  vertical-align: middle; text-align: center;
}
/* 文章の桁だけ左に残す。中央にすると行ごとに字の始まりが変わり、
   上から名前をたどれない（長さがまちまちなので毎行ずれる）。
   **どの桁が文章かは markup が言う** ―― 付けるのは使う側。 */
thead th.data-table__start,
tbody td.data-table__start { text-align: left; }
/* **長い文章の桁**（.data-table__long）。寄せとは別の印 ―― 中央にそろえたい表でも、
   名前の桁は切らずに折り返したい。既定の「1 行で切って `…`」は、
   一覧から目的の行を探す桁では末尾が見えず選べない。
   狭い画面ではこの印がカードの「ラベルを上・中身を下」にも効く（下の @media）。 */
tbody td.data-table__long {
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: normal;
}
/* 列の縦罫。**最終列には引かない**（外枠の内側に線が二重になる）。
   横罫より薄くする ―― 目は行方向に読むので、縦を同じ濃さにすると
   升目が主役になって中身が読みにくくなる。 */
thead th:not(:last-child),
tbody td:not(:last-child) { border-right: 1px solid var(--hairline); }
tbody tr { transition: background-color 0.15s ease; }
/* 1 行おきの縞。ライトだけ引く（--stripe。ダークは transparent）。
   白い面の上でクリームの帯になるので、目が横に滑らず、どの行を見ているか分かる。 */
tbody tr:nth-of-type(odd) td { background-color: var(--stripe); }
/* 載せた行の地は**無彩か飾り色**。青（--accent-soft）で染めない
   ―― 青は「押せる」「選ばれている」の色で、通りがかりの色ではない。 */
/* 載せた行は**明るくし、罫を濃くする**。縞の行は地が白へ上がって分かるが、
   もともと白い行は地が変わらないので、そこは罫が受け持つ（どちらの行でも必ず印が出る）。 */
/* **`td` に当てる。** 縞は `td` の地なので、`tr` に塗っても上から塗り潰されて効かない
   （縞の行だけホバーが出ない状態になっていた）。 */
tbody tr { cursor: pointer; }
tbody tr:hover td { background-color: var(--hover-face); }
/* **外周をぐるりと出す。** セルの罫は下と右にしかないので、色だけ変えても
   上と左が欠けて「行が囲まれた」に見えない（実際そうなっていた）。
   `border` ではなく `outline` を使う ―― `border-collapse` の畳み込みで隣の行と
   罫を取り合い、上の行の下罫と食い合って 1 本ぶんずれるため。
   `outline-offset: -1px` で内側に引き、行の高さも隣との間隔も変えない。
   キーボードの焦点（`:focus-visible` の 2px アクセント）とは太さも色も別なので混ざらない。 */
tbody tr:hover { outline: 1px solid var(--hover-line); outline-offset: -1px; }
/* 行の入場。**画面を開いたとき 1 行ずつ現れる。**
   一覧は端から読むものなので、全部が同時に立ち上がると目の置きどころが決まらない。
   上から順に出せば視線は 1 行目から下りる（サイドバーの入場と同じ曲線・同じ刻み＝
   刻みは製品を通して 1 つ＝ --stagger-step）。
   ・番号（--i）は part.js が配る。頭打ち（LEAD）も part.js が持つ ―― 200 行を 1 つずつ出すと
     最後まで数秒かかり「重い画面」に見える
   ・`backwards` は必須。付けないと待っているあいだ最終状態のまま見えて、
     「全部出てから一部が動く」に見える
   ・`html[data-js]` のときだけ動かす。**行は隠さない**（opacity で先に伏せない）＝
     印が付かなかった行が「消える」道を作らない（advanced-stagger.md「印を付けない道を作らない」）
   ・`data-preload` のあいだは base-reset が animation ごと止めるので、描画が済んでから始まる
   ・動きを抑える設定は reduced-motion パーツが全部止める（ここに書き足さない）
   ・**打鍵で絞り込む画面では、最初の打鍵で animation を外す** ―― 絞るたびに 1 行ずつ出ると読めない */
html[data-js] .data-table__scroll tbody tr {
  animation: revealIn var(--reveal) cubic-bezier(0.22, 1, 0.36, 1) backwards;
  animation-delay: calc(var(--i, 0) * var(--stagger-step, 70ms));
}
/* 横に送る枠の棒。**土台（base-reset）ではなくここで決める** ――
   `.data-table__wrap` を持っているのはこのパーツで、土台から他人の class を狙うと
   あとから読むこちらに負ける（検査 ⑬ が落とす）。
   見出しは枠の中で一緒に横へ動くので、**追従する部分の横に立つ棒にはならない**。 */
.data-table__wrap::-webkit-scrollbar { width: 8px; height: 8px; }
.data-table__wrap::-webkit-scrollbar-track { background-color: transparent; }
.data-table__wrap::-webkit-scrollbar-thumb {
  border-radius: 4px;
  background-color: var(--hairline-strong);
  background-clip: padding-box;              /* 8px の場所に 4px の線だけ見せる（土台と同じ形） */
  border: 2px solid transparent;
}
.data-table__wrap:hover::-webkit-scrollbar-thumb {
  background-color: color-mix(in srgb, var(--ink) 28%, transparent);
  background-clip: padding-box;
}
/* Firefox だけ標準のプロパティで近づける。**素で書くと Chrome が上の指定を全部捨てる**
   ―― 理由と実測は base-reset の同じ節に書いてある。 */
@supports not selector(::-webkit-scrollbar) {
  .data-table__wrap {
    scrollbar-width: thin;
    scrollbar-color: var(--hairline-strong) transparent;
  }
}

/* ---- 数字の列 ----
   **本文の升目だけ右にそろえる。** 桁数が違う数を中央にそろえると、
   一の位が縦に並ばず「どちらが大きいか」を桁を数えて読むことになる。
   `tabular-nums` はもともとこの列のために入れていた（字幅をそろえる指定）が、
   中央のままでは**その指定が働かない** ―― 幅をそろえても、そろえる基準の端が無い。

   **見出し（`thead th`）は中央のまま。** 一度 `th.data-table__num` も右へ寄せて戻した ――
   見出しは「その列が何か」を言う札で、値ではない。値と同じ端に寄せると、
   列の中で札だけが右に落ちて、**中央にそろえた他の見出しと段が合わなくなる**。
   そろえるのは数どうしであって、数と名前ではない。 */
.data-table__num { font-family: var(--mono); font-variant-numeric: tabular-nums; }
tbody td.data-table__num { text-align: right; }
/* **3 つめの分岐幅。理由をここに書く。**
   骨組み 899 と中身 768 の 2 つでは、900〜1240px の「PC の骨組みのままで本文が狭い」帯を
   扱えない（899 以下では表はもうカードに畳まれている）。任意の列だけこの幅で隠す。
   長く数字だけが置いてあって理由が無く、規約の「分岐幅は 2 つだけ」と黙って食い違っていた。
   **これ以外に 3 つめを足さない**（SKILL.md 基本規約7）。 */
@media (max-width: 1240px) { .data-table__col--opt { display: none; } }
tbody td { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 表そのものにも名前を付けておく。見出し側と本文側で**同じ colgroup と同じ名前**を使うと、
   列がずれていないことを目でも確かめられる（解説: references/data-table.md）。 */
.data-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
/* 狭幅でも隠さない列（店名など、行を特定できる 1 列）。`.data-table__col--opt` の逆。 */
.data-table__col--fixed { position: sticky; left: 0px; }

/* ---- 狭いときは 1 件 1 枚のカードに畳む（解説: references/data-table.md §3-b）----

   **表の HTML は組み替えない。CSS だけで姿を変える。** 幅で書き分けると、幅を変えても
   姿が変わらず実機を出さないと確かめられない（User-Agent 判定は iPad も拾う）。
   見出しの表は隠し、代わりに td の data-label を各値の前へ出す。
   data-card は上段の置き場所 ―― title は主役、mark は状態、media は写真。 */
@media screen and (max-width: 768px) {
  /* 【2026-09-11】**地も外す。** 枠・角丸・送りは外していたのに `background: var(--surface)`
     だけ残っていた ―― 表がカードに畳まれた時点で、この器は「箱」ではなく**ただの並び**に
     なる。地が残っていると、**カードとカードの 12px の隙間まで面の色で埋まり**、
     1 枚ずつの紙に見えない（実測: 隙間が地ではなく面の色で出ていた）。
     箱であることはカードのほうが引き受ける（罫・角丸・影を持っている）。 */
  .data-table__wrap {
    max-height: none; border: 0px; border-radius: 0px; overflow: visible;
    background: transparent;
  }
  .data-table__head { display: none; }              /* 見出しは data-label が引き受ける */
  .data-table__scroll { overflow: visible; }
  .data-table__scroll table,
  .data-table__scroll tbody { display: block; width: 100%; }
  .data-table__scroll colgroup { display: none; }   /* 列の幅はカードでは意味を持たない */

  /* 1 枚のカード */
  .data-table__scroll tbody tr {
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 0px;
    margin: 0px 0px 12px 0px; padding: 16px 16px 16px 16px;
    /* 【2026-09-11】**操作を持つ一覧カードの値にそろえた。**
       罫が --hairline（ink 14% / 暗 16%）で、影が 2 枚（0px 2px 4px ＋ 0px 8px 20px）
       だった ―― 罫が弱く、遠いほうの影だけが広く出て「境目がぼやけたまま浮いている」
       状態になる。罫を 1 段濃くし、影は近い 1 枚にする。
       値の出どころは 実案件の企業検索カード（`.co-card`）。承認済みの見た目で、
       ライト／ダークとも同じ式のままトークンに追随する。
       ★ 影の変数が**色だけ**のときは `box-shadow: var(--shadow)` と書かない
         ―― 形が足りず、指定ごと捨てられる（computed が none になる）。 */
    border: 1px solid var(--hairline-strong); border-radius: 4px; background: var(--surface);
    /* ★ 【2026-09-11】**積むカードの影は縁だけ。** 一覧カードの影（0px 2px 6px）を
       ここにも入れていたが、**縦に積むカードでは隙間に影が溜まる** ―― 間は 12px しか
       ないので、上下のカードの影が重なって**地より暗い帯**になり、利用者からは
       「カードの間に色が付いている」と見える。かといって影を全部やめると、今度は
       **1 枚の長い面に見えて境目が読めない**（「繋がっている」と言われた）。

       **隙間の真ん中が地の色まで戻るか**を目安に、描いて測って決めた（ダーク・間 12px）:
           なし          #232529 … #232529   浮きが無い
           0px 1px 2px   #1d1f23 … #232529   ← 縁だけ締まり、真ん中は地に戻る
           0px 1px 3px   #1c1d21 … #232529
           0px 2px 4px   #17191b … #222428   戻りきらない
           0px 2px 6px   #18191c … #202226   戻りきらない（＝溜まっていた値）
       `0px 1px 2px` は skill が既に他所（ヘッダー・ドロップダウン）で使っている段で、
       新しい値は作っていない。

       **並べて置くカード**（企業検索のように隙間が広いもの）は `0px 2px 6px` のまま
       ―― 隣まで届かないので溜まらない。積むか並べるかで影の大きさを変える。
       指しているとき／中に焦点があるときは大きい影を出す（下）―― 1 枚だけなので溜まらない。 */
    box-shadow: 0px 1px 2px var(--shadow);
    transition: border-color var(--color) ease, background-color var(--tint) ease,
                box-shadow var(--color) ease;
  }

  /* 指しているとき／中に焦点があるとき。**外枠をはっきり変え、影で持ち上げる。**
     中の地はほとんど動かさない（ink 2%）―― 大きく塗り替えると、載せただけで
     カードが別物になり、字の読みやすさも落ちる。
     0 ぼかしの輪（`0px 0px 0px 1px`）は罫を太らせずに 1 段濃く見せる手
     ―― 枠の太さを変えると中身が 1px ずれて、行がガタつく。
     `:focus-within` を並べるのは、キーボードで中の釦へ入ったときも同じ姿にするため
     （載せたときだけ分かる作りにしない）。 */
  .data-table__scroll tbody tr:hover,
  .data-table__scroll tbody tr:focus-within {
    border-color: var(--hover-line);
    background-color: color-mix(in srgb, var(--ink) 2%, var(--surface));
    /* 遠いほうの影は**指している 1 枚だけ**なので、隣と溜まらない。
       近いほうは 0 ぼかしの輪で、罫を太らせずに濃く見せる。 */
    box-shadow: 0px 0px 0px 1px var(--hover-line), 0px 6px 16px var(--shadow);
  }

  /* **PC の行の作法はカードでは使わない。**
     行は幅いっぱいで輪が描けないので、内側の輪（`outline` を内向きに引く）と
     升目の地（--hover-face）で示していた。カードは外枠と影で示せるので、そのまま
     重ねると **輪が二重**になり、地のほうは「カード全体の塗り替え」になって
     上の ink 2% の決めと真っ向からぶつかる。 */
  /* 升目の中に `<br>` でぶら下げた注記（「未確認」「ご用意できず」等）。
     **`<br>` は行を変えるだけで間を作らない** ―― 本体が折り返していると、
     注記が「折り返しの続き」にしか見えない（実測）。色を変えても、
     **間が同じなら同じ塊に見える**。塊にして升目と升目の間ぶん空ける。
     4px では効かない ―― 本文の行送りが 16px × 1.7 = 27.2px あり、差が出ない。 */
  .data-table__scroll tbody tr > td br + span {
    display: block;
    margin: 8px 0px 0px 0px;
  }

  .data-table__scroll tbody tr:hover { outline: none; }
  .data-table__scroll tbody tr:hover td,
  .data-table__scroll tbody tr:focus-within td { background-color: transparent; }

  /* 中の値。既定は「ラベル：値」の 1 行。
     ★ 【2026-09-11】**両端に離すのをやめた。**
     ずっと `justify-content: space-between` ＋ `text-align: right` で、名札を左端・
     値を右端に置いていた。カードの幅ぶん（実測 390px の画面でカード 358px）まるごと
     空くので、**短い値ほど遠い** ―― 「ID」と「1069」が 300px 以上離れ、目が往復しないと
     どの名札の値なのか確かめられない。表なら列が対応を保証するが、カードにその柱は無い。

     名札のすぐ右に置き、間は**全角コロン**が受け持つ。読み上げでも「ID、1069」と
     続けて読まれる（離して置いても読み順は同じだが、目で追うときだけ差が出ていた）。
     値の左端が行ごとに変わるのは承知のうえ ―― 対応の確かさを取る。
     桁をそろえて読ませたい表は `.data-table__long`（下）で名札を上に出す。 */
  .data-table__scroll tbody td {
    display: flex; flex: 1 1 100%; align-items: baseline;
    justify-content: flex-start; gap: 0px;
    padding: 8px 0px 0px 0px; border: 0px;
    text-align: left; white-space: normal; overflow: visible;
  }
  .data-table__scroll tbody td::before {
    /* **間は全角コロンが持っている余白だけ。** `gap` を足すと二重になり、
       「ID： 1069」と 1 字ぶん空いて見える（実測: gap 4px ＋ コロンの後ろ半角ぶん）。
       値が釦の桁でも、釦は自分の余白と枠を持っているので接して見えない。 */
    content: attr(data-label) "："; flex: 0 0 auto; text-align: left; color: var(--mute);
  }
  /* 縦罫は**横に並んだ列**を仕切るためのもの。縦に積んだら仕切る相手がおらず、
     各行の右端に 1px の切れ端だけが残る。 */
  .data-table__scroll tbody td:not(:last-child) { border-right: 0px; }
  /* 畳んだら列は落とさない ―― 縦積みでは幅の取り合いが無く、
     消しても何も広がらない（読めない値が 1 つ増えるだけ）。 */
  .data-table__scroll tbody td.data-table__col--opt { display: flex; }

  /* 上段（写真・主役・印）。見出しを出さず、高さをそろえて下に 1 本引く。
     baseline のままだと箱の高さがまちまちで、下線が段違いの 2〜3 本に割れる。 */
  .data-table__scroll tbody td[data-card="media"],
  .data-table__scroll tbody td[data-card="title"],
  .data-table__scroll tbody td[data-card="mark"] {
    align-self: stretch;
    margin-bottom: 8px; padding-bottom: 8px;
    border-bottom: 1px solid var(--hairline);
  }
  .data-table__scroll tbody td[data-card="media"]::before,
  .data-table__scroll tbody td[data-card="title"]::before,
  .data-table__scroll tbody td[data-card="mark"]::before { content: none; }
  /* 【2026-09-11】**名札を出さない桁は `gap` を戻す。**
     既定の桁は間を全角コロンが持っているので `gap: 0px` にしてあるが、
     この 3 つはコロンが出ない ―― 印の桁（絵 ＋ 字）がそのまま接して
     「✓有効」と詰まって出た（実測 390px）。4 の倍数の最小段で離す。 */
  .data-table__scroll tbody td[data-card="media"],
  .data-table__scroll tbody td[data-card="title"],
  .data-table__scroll tbody td[data-card="mark"] { gap: 8px; }

  .data-table__scroll tbody td[data-card="media"] { order: -3; flex: 0 0 auto; width: 72px; }
  /* 一覧の写真は「これだ」と見分ける手掛かりで、見るための絵ではない。
     幅いっぱいにすると 1 件で画面が埋まり、見比べられなくなる。
     縦横比はまちまちなので contain（cover だと端の柄だけが写る）。 */
  .data-table__scroll tbody td[data-card="media"] img { width: 60px; height: 60px; object-fit: contain; }

  /* **文章の桁（.data-table__long）は、ラベルを上・中身を下にする。**
     既定の「ラベル ─ 値」は 1 行に収まる短い値のための形で、両端に離して置く。
     折り返す文章（商品名・会社名）だと右半分の狭いところに押し込まれ、
     1 行あたりの字数が減って、読み進めるほど目が左右に振られる。
     CSS からは字数を測れないので、markup の印に頼る。

     **この印は一度 `.data-table__start` に相乗りしていて、外した。**
     あれは「寄せ」の印で、これは「桁の性格（長い文章か）」―― 別の話なのに 1 つの
     class に載せていたため、**寄せを中央に変えただけで折り返しまで消えた**
     （実測: 名前の桁が「…」で切れた）。印を 2 つに分ける。 */
  .data-table__scroll tbody td.data-table__long,
  /* 落とす印の付いた桁（下で display を戻している）にも当てる。詳しさが同じだと
     あとに書いたほうが勝つので、印ぶん 1 つ強くして名指しする。 */
  .data-table__scroll tbody td.data-table__long.data-table__col--opt {
    display: block;
    text-align: left;
  }
  /* 名札を 1 行使って出すので、**コロンは付けない**（行末に浮いた記号が残る）。 */
  .data-table__scroll tbody td.data-table__long::before {
    content: attr(data-label);
    display: block; margin: 0px 0px 2px 0px;
  }

  /* 主役と印は「ラベル ─ 値」の器ではないので flex にしない
     ―― 中身が 2 つ以上あると、<br> で改行したつもりのものが横に並ぶ。
     伸び代の基準は 0。auto（＝名前の長さ）だと、長い名前のときに
     印だけが次の行へ落ちて下線が途中で切れる。 */
  .data-table__scroll tbody td[data-card="title"] {
    order: -2; display: block; flex: 1 1 0; min-width: 0;
    text-align: left; font-weight: 600; font-size: 16px;
    /* 語の途中で折らない。日本語は単語の区切りが無いので、既定だと
       「カラフルバームクーヘン」が「カラフルバームク」「ーヘン」と割れる。
       文節で折る（html に lang="ja" が要る）。 */
    line-break: strict; word-break: auto-phrase;
  }
  .data-table__scroll tbody td[data-card="mark"] { order: -1; display: block; flex: 0 0 auto; }

  /* **写真のあるカードでは、主役を写真の隣に置かない。**
     写真と印を引くと主役に残るのは 230px 前後で、語の途中で折れる。
     1 行目＝写真＋印、2 行目＝主役（幅いっぱい・下線はここ）。 */
  .data-table__scroll tbody tr:has(> td[data-card="media"]) > td[data-card="title"] {
    order: -1; flex: 0 0 100%; padding-right: 0px;
  }
  .data-table__scroll tbody tr:has(> td[data-card="media"]) > td[data-card="mark"] { margin-left: auto; }
  .data-table__scroll tbody tr:has(> td[data-card="media"]) > td[data-card="media"],
  .data-table__scroll tbody tr:has(> td[data-card="media"]) > td[data-card="mark"] {
    margin-bottom: 0px; padding-bottom: 0px; border-bottom: 0px;
  }
  /* 印が付かない行は、枠だけが残って空の帯になる */
  .data-table__scroll tbody td[data-card="mark"]:empty { display: none; }

  /* 縞を敷いている場合は td 側で戻す（塗っているのは tr ではなく td）。
     カードでは「1 枚おきに中だけ色が違う」として出る。 */
  .data-table__scroll tbody tr:nth-of-type(odd) td { background-color: transparent; }

  /* ---- 頭の 20 件だけ出して、あとは「もっと見る」で足す（part.js）----
     PC は高さの決まった箱の中で送るので 200 件でも 1 画面に収まるが、カードに畳むと
     箱をやめてページごと送るので、同じ 200 件が**そのままページの丈**になる。
     **件数は減らさない**（出す順も絞り込みもページの区切りも今までどおり）。
     隠すのは JS が動くときだけ ―― CSS で先に隠すと、押す相手を作れない環境で
     行が出てこなくなる。 */
  .data-table__scroll tbody tr[data-list-more-hidden] { display: none; }

  .data-table__more {
    display: block; width: 100%;
    margin: 4px 0px 0px 0px; padding: 16px 16px 16px 16px;
    border: 1px solid var(--hairline-strong); border-radius: 4px;
    background: var(--surface); color: var(--ink);
    font-size: 16px; font-weight: 600; cursor: pointer;
  }
  .data-table__more:active { background: var(--accent-soft); }
}

/* ---- 枠の外に置く送り棒 ----
   **追従する見出しを内側に持つ枠のための棒。**

   ブラウザの棒は枠の**内側**に立ち、幅を 10px 食う。見出しと本文が別の表になっている
   一覧では、本文だけ 10px 細くなって列がずれる。ずらさないために見出しへ空きを入れると、
   こんどは**追従する見出しの横に棒の空き**ができる（実測でどちらも起きた）。
   中身の上に重ねる形も試したが、`.site-main` では**貼り付いた見出しの上に棒が乗る**。

   だから**枠の外に出す。** 棒は枠の右隣に置き、枠の丈ぶんだけ伸びる ――
   表なら見出しの下から（`.data-table__scroll` の上端＝見出しの外）、
   本文なら本文の枠の右隣（レールとの隙間）。
   幅を食わないので列はずれず、追従する部分の上にも乗らない。

   見た目はブラウザの棒と同じ式で書く（太さ 8px の場所に 4px の線・角丸 4px・
   `--hairline-strong`）。同じアプリの中で棒の太さが場所ごとに変わると、作りかけに見える。 */
.scroll-bar {
  position: absolute;
  width: 8px;
  /* **外側の枠で切った先を刈る。** 表が本文ごと上へ抜けるとき、親指は切る前の丈で
     置いてあるので、切った端から出る。ここで刈らないと、棒の外へ親指が飛び出す。 */
  overflow: hidden;
  /* 重ね物（60 以上）より下、本文より上。ページ見出しの貼り付き（1）とは
     場所が重ならないので争わない。 */
  z-index: 2;
  /* **押せる物にしない。** 親指だけが押しを受ける ―― 溝を押しても何も起きない作りだと、
     押した人は「壊れている」と思う。触れないほうが正直。 */
  pointer-events: none;
}
.scroll-bar__thumb {
  position: absolute;
  left: 0px;
  width: 8px;
  border-radius: 4px;
  background-color: var(--hairline-strong);
  background-clip: padding-box;              /* 枠に貼り付いて見えないよう余白を作る */
  border: 2px solid transparent;
  /* 掴んで動かせるので、ここだけは押しを受ける */
  pointer-events: auto;
  cursor: grab;
  transition: background-color var(--color) ease;
}
/* **枠の中にポインタがある間だけ**強める（土台の `:hover::-webkit-scrollbar-thumb` と同じ振る舞い）。
   棒は枠の外に居るので、枠側から見て `~` で辿る ―― 入れ子ではないため子孫では当たらない。 */
.site-main:hover ~ .scroll-bar > .scroll-bar__thumb,
.site-main__flush:hover ~ .scroll-bar > .scroll-bar__thumb,
.data-table__wrap:hover ~ .scroll-bar > .scroll-bar__thumb,
.scroll-bar__thumb:hover {
  background-color: color-mix(in srgb, var(--ink) 28%, transparent);
  background-clip: padding-box;
}
/* 掴んでいるあいだ。**色は変えない** ―― 手の形だけで足りるし、
   色まで変えると「押した」ではなく「別の状態になった」に見える */
.scroll-bar__thumb[data-drag="1"] { cursor: grabbing; }

/* 中身が溢れていないときは出さない。**要素ごと消さない**（毎回作り直すと
   掴んでいる最中に消える）―― 見えなくするだけにして、位置の計算は続ける。 */
.scroll-bar[hidden] { display: none; }

/* ============================================================
   右レール — サイドパネル / AI の開閉。ボタンは 32×32
   ============================================================ */
.site-rail {
  grid-area: rail; min-height: 0;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 16px 0px 0px 0px;
  /* 左の側面と同じ面を敷く（理由は parts/site-sidebar）。左右で違うと、
     同じ幅の柱が別のものに見える。 */
  border-left: 1px solid var(--border-strong); background: var(--rail-face);
}
/* ここは**パネルの開閉スイッチ**＝画面のモードを切り替える最上位コントロールなので、
   「ボタンは塗らない」の例外にする（SKILL.md 構造的不変条件 1 の最上位切替タブと同じ扱い）。
   見えないと開き直せなくなる場所なので、はっきり目立たせる。

   塗りは **要素の中で動かす**: 地は ::before に持たせて下から迫り上げる。
   開いているあいだは地をゆっくり横へ送り「いまここが開いている」を示す。 */
.site-rail__btn {
  position: relative; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 4px;
  /* **内余白を書いておく。** 書かないとブラウザ既定の `1px 6px` が残り、
     自前で 0 にしている配備先と算出値が食い違う（見た目は 32px 四方の中央寄せなので
     同じに見えるのに、測ると違う）。姿を比べる検査が通らない値を正典に残さない。 */
  padding: 0px 0px 0px 0px;
  /* **枠は構造の色、絵は飾りの色。** 枠だけ無彩の薄い罫にしていたので、右レールが
     「灰色の四角に金の絵」に見えていた。かといって枠まで飾り色にすると、四角ごと飾りに
     見えて「押せるもの」に見えなくなる ―― 枠は仕切りと同じ濃さ、中の絵だけが飾り色。
     ライト: 枠は字の色（12.52:1）／絵は濃い金（3.07:1）。
     ダーク: 枠は字の色＝白（12.74:1）／絵は青（6.4:1）。値は parts/tokens が持つ。 */
  border: 1px solid var(--rail-btn-line);
  background: transparent; color: var(--rail-btn-ink);
  transition: color var(--color) ease, border-color var(--color) ease, background-color var(--tint) ease;
}
/* 滑ってくる塗り。**出すかどうかはテーマが決める**（--rail-fill）。
   ライトは出さず、枠の色だけで 3 段階を示す ―― 平常＝薄い罫 / 載せた＝濃い罫＋飾り色の淡い地 /
   開いている＝飾り色の枠。塗りが滑ると、器の地が明るいテーマでは字が読めなくなる。 */
.site-rail__btn::before {
  display: var(--rail-fill);
  content: ""; position: absolute; inset: 0px;
  background: var(--accent);
  transform: translateY(100%);
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}
/* 絵の大きさは**共通の 20px**（parts/base-reset の `.app-icon`）に任せる。
   ここで 16px に縮めていたので、**左のレールの絵（20px）と右のレールの絵（16px）で
   大きさが違って**いた ―― 同じ幅の柱に並ぶ入口なので、大きさは同じにする。
   32px の枠に 20px の絵で上下左右 6px。中心は左のレールと同じ 28px にそろう
   （左は 56px の柱に 20px の絵を 18px の内余白で置くので 18 + 10 = 28）。 */
.site-rail__btn .app-icon { position: relative; }
/* 絵の色は**塗りが出るかどうか**で決める（--rail-fill-ink）。塗らないテーマでは
   飾り色のまま、塗るテーマでは地の色 ―― 塗りと同じ色のままだと絵が溶けて消える。 */
/* 載せたとき。**枠と絵の両方をうっすら飾り色に寄せる。**
   片方だけ変えると「枠が動いた」「絵が変わった」と別々の出来事に見える ――
   1 つの塊なので、同じだけ寄せて 1 つの反応にする。地は薄く敷くだけ。 */
.site-rail__btn:hover {
  border-color: color-mix(in srgb, var(--rail-btn-ink) 55%, var(--rail-btn-line));
  color: color-mix(in srgb, var(--rail-btn-ink) 80%, var(--ink));
  background-color: var(--hover-face);
}
.site-rail__btn:hover::before { transform: translateY(0px); }
/* 開いているあいだ。枠も飾り色に振り切る（載せたときより一段強い） */
.site-rail__btn[aria-expanded="true"] { border-color: var(--rail-btn-ink); color: var(--rail-fill-ink); }
.site-rail__btn[aria-expanded="true"]::before {
  transform: translateY(0px);
  background: linear-gradient(100deg, var(--accent) 0%,
      color-mix(in srgb, var(--accent) 62%, #ffffff) 45%, var(--accent) 100%);
  background-size: 300% 100%;
  animation: railFlow 4s linear infinite;
}
@keyframes railFlow { from { background-position: 0% 0%; } to { background-position: 300% 0%; } }

/* 動きを抑える設定では流れを止める。塗り（＝どれが開いているか）は残す */
@media (prefers-reduced-motion: reduce) {
  .site-rail__btn::before { transition: none; }
  .site-rail__btn[aria-expanded="true"]::before { animation: none; background: var(--accent); }
}
/* 最下段へ寄せる（margin-top: auto）。**下の隙間は枠の外に取る。**
   padding-bottom で取ると枠の内側が広がり、絵が枠の上へ寄る
   ―― 実測で他のボタンは上下 8px ずつで中央なのに、ここだけ上 0 / 下 16 になり、
   枠と絵がずれて見えた。枠は 32x32 のまま、隙間は margin-bottom が持つ。 */
/* 内余白は持たない。枠は 32x32・中身は flex で中央・絵は 16px なので、
   `1px 6px` は**一度も効いていなかった**（4 の倍数からも外れていた）。 */
.site-rail__spacer { margin: auto 0px 16px 0px; padding: 0px 0px 0px 0px; }

/* ============================================================
   重ね物 — .app の外。z-index は SKILL.md の階層表どおり
   ============================================================ */
.scrim {
  position: fixed; inset: 0px; background: color-mix(in srgb, #000000 38%, transparent);
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease; z-index: 60;
}
.scrim[data-show="1"] { opacity: 1; pointer-events: auto; }

/* ---- 開いた重ね物は、**中身を 1 つずつ**出す ----
   `data-open="1"` を入れるのはこのパーツ（part.js）なので、刻みもここが持つ。
   右から出る枠（side-panel）とドロワー（drawer）で同じ演出になるが、**どちらかの
   パーツに書くと相手のクラスまで名乗ることになる**（後勝ちで潰し合う）。
   頭のかたまりを `[data-open="1"]` だけにして、器の名前は後ろの子孫でしぼる。
   器を `:is(.side-panel__body, .drawer__body)` でまとめない ―― 中の読点で
   セレクタが 2 本に割れて読まれ、やはり相手の名前を名乗ったことになる。

   左（行き先の一覧）は JS が `--i` に通し番号を入れるので、それを読むだけでよい（sidebar-rail-panel）。
   右（詳細・設定・絞り込み）は中身が毎回違って番号を配れないので、**並び順で刻む**。

   出す対象は「1 件」に当たるものだけ ―― 枠の本文の直下・行き先の並び・名前と値の対。
   `.kv` は dt / dd が交互に並ぶので **nth-of-type で対にそろえる**（別々にずらすと名前と値が分かれて出る）。
   10 番目より後はまとめて同じ間で出す。それ以上ずらすと下のほうが 1 秒近く待つ。
   速さは --reveal（1 つあたり）と --stagger-step（刻み）の 2 つだけで決める。 */
[data-open="1"] .side-panel__body > *,
[data-open="1"] .drawer__body > *,
[data-open="1"] .drawer__links > li,
[data-open="1"] .kv > * {
  animation: revealIn var(--reveal) cubic-bezier(0.22, 1, 0.36, 1) backwards;
}
[data-open="1"] .side-panel__body > *:nth-child(1),
[data-open="1"] .drawer__body > *:nth-child(1),
[data-open="1"] .drawer__links > li:nth-child(1),
[data-open="1"] .kv > dt:nth-of-type(1),
[data-open="1"] .kv > dd:nth-of-type(1) { animation-delay: calc(0 * var(--stagger-step)); }
[data-open="1"] .side-panel__body > *:nth-child(2),
[data-open="1"] .drawer__body > *:nth-child(2),
[data-open="1"] .drawer__links > li:nth-child(2),
[data-open="1"] .kv > dt:nth-of-type(2),
[data-open="1"] .kv > dd:nth-of-type(2) { animation-delay: calc(1 * var(--stagger-step)); }
[data-open="1"] .side-panel__body > *:nth-child(3),
[data-open="1"] .drawer__body > *:nth-child(3),
[data-open="1"] .drawer__links > li:nth-child(3),
[data-open="1"] .kv > dt:nth-of-type(3),
[data-open="1"] .kv > dd:nth-of-type(3) { animation-delay: calc(2 * var(--stagger-step)); }
[data-open="1"] .side-panel__body > *:nth-child(4),
[data-open="1"] .drawer__body > *:nth-child(4),
[data-open="1"] .drawer__links > li:nth-child(4),
[data-open="1"] .kv > dt:nth-of-type(4),
[data-open="1"] .kv > dd:nth-of-type(4) { animation-delay: calc(3 * var(--stagger-step)); }
[data-open="1"] .side-panel__body > *:nth-child(5),
[data-open="1"] .drawer__body > *:nth-child(5),
[data-open="1"] .drawer__links > li:nth-child(5),
[data-open="1"] .kv > dt:nth-of-type(5),
[data-open="1"] .kv > dd:nth-of-type(5) { animation-delay: calc(4 * var(--stagger-step)); }
[data-open="1"] .side-panel__body > *:nth-child(6),
[data-open="1"] .drawer__body > *:nth-child(6),
[data-open="1"] .drawer__links > li:nth-child(6),
[data-open="1"] .kv > dt:nth-of-type(6),
[data-open="1"] .kv > dd:nth-of-type(6) { animation-delay: calc(5 * var(--stagger-step)); }
[data-open="1"] .side-panel__body > *:nth-child(7),
[data-open="1"] .drawer__body > *:nth-child(7),
[data-open="1"] .drawer__links > li:nth-child(7),
[data-open="1"] .kv > dt:nth-of-type(7),
[data-open="1"] .kv > dd:nth-of-type(7) { animation-delay: calc(6 * var(--stagger-step)); }
[data-open="1"] .side-panel__body > *:nth-child(8),
[data-open="1"] .drawer__body > *:nth-child(8),
[data-open="1"] .drawer__links > li:nth-child(8),
[data-open="1"] .kv > dt:nth-of-type(8),
[data-open="1"] .kv > dd:nth-of-type(8) { animation-delay: calc(7 * var(--stagger-step)); }
[data-open="1"] .side-panel__body > *:nth-child(9),
[data-open="1"] .drawer__body > *:nth-child(9),
[data-open="1"] .drawer__links > li:nth-child(9),
[data-open="1"] .kv > dt:nth-of-type(9),
[data-open="1"] .kv > dd:nth-of-type(9) { animation-delay: calc(8 * var(--stagger-step)); }
[data-open="1"] .side-panel__body > *:nth-child(n + 10),
[data-open="1"] .drawer__body > *:nth-child(n + 10),
[data-open="1"] .drawer__links > li:nth-child(n + 10),
[data-open="1"] .kv > dt:nth-of-type(n + 10),
[data-open="1"] .kv > dd:nth-of-type(n + 10) { animation-delay: calc(9 * var(--stagger-step)); }
@media (prefers-reduced-motion: reduce) {
  [data-open="1"] .side-panel__body > *,
  [data-open="1"] .drawer__body > *,
  [data-open="1"] .drawer__links > li,
  [data-open="1"] .kv > * { animation: none; }
}

/* 右から出る枠は**詳細も設定も同じ 1 種類**（`.side-panel`）。
   役割の違い（居座る／一時的に覆う）で見た目を変えない ―― 同じ場所に
   同じ大きさで出るものが 2 通りの顔を持つと、開くたびに別の画面に見える。
   出方・色・影・見出しまでそろえ、違うのは中身だけにする。 */
.side-panel {
  position: fixed; top: var(--shell-header-h); right: 0px; bottom: var(--shell-footer-h);
  width: var(--info-w); max-width: 92vw;
  /* 厚手のガラス。面は半透明で、後ろをぼかして持ち上げる。
     左の縁は**ヘアライン**（構造の仕切りではないので `--border-strong` は濃すぎる）。
     影は本文との境目が分かる程度で足りる。 */
  background: var(--material-thick);
  -webkit-backdrop-filter: blur(30px) saturate(180%);
  backdrop-filter: blur(30px) saturate(180%);
  border-left: 1px solid var(--hairline);
  box-shadow: -2px 0px 12px var(--shadow);
  transform: translateX(100%); transition: transform var(--slide) var(--slide-ease);
  z-index: 100; display: flex; flex-direction: column;
}
.side-panel[data-open="1"] { transform: translateX(0px); }
/* 枠の頭・見出し・本文の体裁は**この 1 か所だけ**が持つ。かつて同じ 3 つを
   parts/elevation にも置いていて、連結順で後ろのあちらが勝っていた ―― この節の
   コメントは `--ink` と書いてあるのに、実際に出るのは `--grey` の 13px 大文字だった。
   **影を足すだけの横断パーツに中身の体裁を置かない。** あちらは何も作らないので、
   狙う先の名前が変わっても一度も当たらないまま静かに残る。
   キーカラーを当てるのは見出しの**アイコンだけ**（何の枠かの目印）。 */
.side-panel__head {
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  height: 48px; padding: 0px 16px 0px 16px;
  border-bottom: 1px solid var(--line);
}
/* 枠の題。**同じ役目のものと同じ大きさにする。**
   12px・`text-transform: uppercase`・字間 0.08em・`--grey` だった ―― 英字の小さな
   ラベルの体裁で、重ね物の題としては**この枠だけ別の格**に見えていた。並べると:
     ドロワーの題 20px/800 ・ モーダルの題 16px/800 ・ 左パネルの節名 16px/800
     この枠の題 **12px/700 大文字グレー**  ← ここだけ
   上の注記が「コメントは --ink と書いてあるのに実際に出るのは --grey の 13px 大文字」
   と言っているのは、**事故で勝っていたほうがそのまま残っていた**ため。
   本来の姿（--ink）に戻し、大きさは向かい合う左パネルの節名にそろえる
   ―― 左右で器の大きさを変えない、という骨格の決めと同じ理由。
   `uppercase` と広い字間は日本語には効かないか、効いても読みにくくするだけ。 */
.side-panel__title {
  font-size: 16px; font-weight: 800; letter-spacing: 0.02em; line-height: 1.4;
  color: var(--ink);
  /* 大きくしたぶん、長い題は閉じるボタンを押し出しうる。**押し出させない**
     ―― 溢れたら省略する（枠の頭は 48px 固定で、折り返す余地が無い）。 */
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.side-panel__title .app-icon { color: var(--accent); }
/* 本文は 12px。枠は本文より狭いので、13px だと 1 行に入る字数が減って
   行が増える（同じ内容なのに枠の中だけ間延びして見える）。 */
.side-panel__body {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 16px 16px 16px 16px;
  font-size: 14px; color: var(--sub);
}
.side-panel__body p + p { padding: 8px 0px 0px 0px; }
/* 名前と値の対（parts/kv）を**パネルの中に置いたときだけ**の左右余白。
   器の余白はパネルが持ち、部品そのものは持たない ―― 本文に置いても同じ形で出る。 */
.side-panel .kv { padding: 16px 24px 24px 24px; }

/* ---- SP: 横に並べる幅が無いので縦積み。右パネルは消さず下に積む ---- */
@media (max-width: 899px) {
  .side-panel { top: 0px; bottom: 0px; }
}

/* ── 右の枠の幅をドラッグで変える ──
   左端の細い帯を掴んで動かす。**右端からの距離がそのまま幅**になる。
   幅の正典は `--info-w` 1 つ。枠の width も、詰めるときの列幅も同じ変数を読むので、
   2 か所に別の値を書いてずれる、が起きない。 */
.side-panel__resizer {
  position: absolute;
  top: 0px; left: 0px; bottom: 0px;
  /* 8px。細いと掴めず、太いと中身のスクロールバーと当たり判定が重なる */
  width: 8px;
  cursor: ew-resize;
  z-index: 5;
}
/* 掴めることが分かる印。**常時は出さない**（飾りを増やさない）。
   枠にカーソルが入ったら出す ―― 帯そのものは細くて狙いにくいので、
   枠のどこに居ても「ここが掴める」と分かるようにする。 */
.side-panel__resizer::after {
  content: "";
  position: absolute;
  top: 50%; left: 2px;
  transform: translateY(-50%);
  /* 2px x 32px。もとの実装は views.css で 3x42 を書いたあと panel.css で
     この値に上書きしている（後に読むほうが勝つ）ので、効いているのはこちら。 */
  width: 2px; height: 32px;
  border-radius: 4px;
  background: var(--border-strong);
  opacity: 0;
  transition: opacity 0.15s ease;
}
.side-panel:hover .side-panel__resizer::after,
.side-panel__resizer:hover::after { opacity: 1; }
/* 掴む手前で当たり判定を見せる。塗りではなく地を薄く透かすだけ */
.side-panel__resizer:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); }

/* 掴んでいるあいだ。文字が選ばれないようにし、カーソルを画面全体で固定する
   （帯から外れても掴んだままなので、カーソルが戻ると掴んでいないように見える）。 */
body[data-panel-resizing] { user-select: none; cursor: ew-resize; }
/* **遷移を切る。** 枠の出入りに掛けている `--slide` がドラッグ中も効くと、
   指の位置から枠がその秒数ぶん遅れて付いてきて、掴んでいる感じが消える。 */
body[data-panel-resizing] .side-panel,
body[data-panel-resizing] .app { transition: none; }

/* ---- SP: 枠は画面幅いっぱいなので掴む余地が無い ---- */
@media (max-width: 899px) {
  .side-panel__resizer { display: none; }
}

/* ── 開いたときに本文を幅ぶん詰める（任意）──
   既定は**重ねて出す**（本文の列幅は動かさない）。詳細と設定で出方をそろえた結果、
   どちらも一時的に覆うものになっている。

   ただし「枠が居座って本文と並ぶ」画面では、覆われると下が読めない。
   `<html data-panel-push>` を付けるとその形になる。

   仕掛けは 1 行だけ。シェルの右列（レール）の幅を枠の幅に差し替える ――
   `.app` は `grid-template-columns` に遷移を持っているので、詰めは枠の
   出入りと同じ速さで動く。**幅は `--info-w` 1 つが決める**ので、
   枠の width と詰めの列幅がずれようがない。 */
html[data-panel-push] body[data-panel-open] .app { --shell-rail-w: var(--info-w); }

/* ---- SP: 縦積みなので詰める余地が無い ---- */
@media (max-width: 899px) {
  html[data-panel-push] body[data-panel-open] .app { --shell-rail-w: auto; }
}

/* **詳細パネルと同じ箱**（幅も上下端も）。役割は違っても器の大きさはそろえる ――
   右から出るものが 2 つあって、片方は全画面高・片方はヘッダーとフッターの間、
   では開くたびに別の場所に見える。上下も `--shell-header-h` / `--shell-footer-h` で
   詰めて、ヘッダーとフッターは常に見えたままにする。 */

.modal {
  position: fixed; inset: 0px; display: flex; align-items: center; justify-content: center;
  z-index: 110; opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
}
.modal[data-open="1"] { opacity: 1; pointer-events: auto; }
/* **上・真ん中・下の 3 段。** 1 枚の箱に詰めていて、本文が伸びると釦が画面の外へ
   押し出されて押せなかった（実測: 高さ 92vh を超えたところで下の 2 つが隠れる）。
   段に分けて、**送るのは真ん中だけ**にする ―― 見出しと釦は常に見えたまま。
   ドロワー（.drawer__head / __body）と同じ組み方にそろえてある。 */
/* **枠は `--hairline-strong`。`--gold` で縁取らない。**
   明るいときの `--gold`（#d4af37）は飾りとして落ち着いて見えるが、
   **暗いときの `--gold` はキーカラーに戻る**（tokens: `--gold: var(--accent)`）ので、
   小窓の外枠だけが青（#48b3dc）になる ―― 2026-09-11 に移植案件で実測した。
   枠は「ここまでが小窓」と言うための線で、押せる・選ばれているを示す色ではない。
   飾りの金を線に使いたいときは `--gold-line`（暗いときは字の色に落ちる）を使う。 */
.modal__panel {
  width: 420px; max-width: 92vw; background: var(--panel-face);   /* 重ね物の地。本文と同色にすると境目が消える */
  border: 1px solid var(--hairline-strong); border-radius: 4px;
  box-shadow: 0px 1px 2px var(--hairline-strong), 0px 12px 32px var(--shadow);
  display: flex; flex-direction: column;
  /* 上下 48px は残す。画面いっぱいにすると「重ねて出ている」ことが伝わらない */
  max-height: calc(100dvh - 96px);
}
/* 上と下は罫で区切る。**ドロワー（.drawer__head）と同じ組み方** ―― 同じ「重ね物の器」
   なのに片方だけ線が無いと、開くたびに別の部品に見える。
   線があると、送って本文が途中で切れているときに「どこまでが本文か」も読める。 */
/* **中の物はすべて中央にそろえる。** 小窓は「読ませる面」ではなく「選ばせる面」で、
   目が行き来する距離を短くしたい ―― 左に寄せると、見出し・本文・釦の頭が
   それぞれ別の位置から始まり、視線が 3 回横に振られる。
   本文が長いときは中央ぞろえが読みにくくなるが、**長い本文はそもそも小窓に置かない**
   （読ませたいものは面へ、選ばせたいものだけ小窓へ）。 */
.modal__head {
  flex: 0 0 auto;
  padding: 20px 20px 12px 20px;
  border-bottom: 1px solid var(--hairline);
  text-align: center;
}
.modal__title { font-size: 16px; font-weight: 800; }
/* 真ん中だけが送られる。min-height: 0 が無いと flex の子は縮まず、送りが効かない */
.modal__body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding: 16px 20px 16px 20px;
  /* **本文の段（16px）で出す。** 12px にしていて「小さすぎて見えない」と言われて上げた ――
     ここは注記ではなく**読んで判断する本文**で、取り返しのつかない操作の前に
     いちばん読ませたい字。ラベルや注記の段（12px）に落とす場所ではない。 */
  font-size: 16px; color: var(--sub);
  text-align: center;
}
.modal__body > p + p { padding: 8px 0px 0px 0px; }
.modal__target { padding: 8px 0px 0px 0px; }
/* 下は罫で区切る。送って本文が途中で切れているとき、どこまでが本文かを線が言う */
/* 釦も中央。**2 つでも 3 つでも同じ組み方**で、真ん中を軸に左右へ並ぶ ――
   端に寄せると、2 つのときと 3 つのときで「実行する」の位置が変わって、
   目が毎回探し直すことになる（一度 flex-end で右に寄せていて、戻した）。 */
.modal__foot {
  flex: 0 0 auto;
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;
  padding: 16px 20px 16px 20px;
  border-top: 1px solid var(--hairline);
}
/* **釦は 3 つまで。** 「やめる」「別の道」「実行する」の 3 つで、それ以上は
   選ばせすぎ ―― 4 つ目が要るときは、その操作が 1 つのモーダルに収まっていない。
   狭い画面では横に 3 つ並べると 1 つ 100px を切って字が折れるので、縦に積む。

   **分岐幅は 768px（中身の分岐）。** 一度 480px にしていて戻した ―― 規約は
   「分岐幅は骨組み 899・中身 768 の 2 つだけ。これ以外に 3 つめを足さない」で、
   480 はその 3 つめだった。768 でも詰まる幅は同じで、**新しい分岐を作る理由が無い**。 */
@media screen and (max-width: 768px) {
  .modal__foot { flex-direction: column-reverse; }
  .modal__foot > .btn { width: 100%; }
}

/* ---------- 閉じるボタン（2本線の回転で描く） ---------- */
/* 当たりは 28px、絵は 16px。**当たりを絵に合わせない** ―― 16px 角の釦は
   指でもカーソルでも外しやすく、閉じられないと「開いたまま固まった」と映る。
   絵の大きさは変えないので、見え方は今までと同じ（線は下で中央に置く）。
   配備先の 1 つが独立に 28px へ広げていたのが根拠 ―― 現場で足りていなかった。 */
.close-btn {
    position: relative;
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    padding: 0px 0px 0px 0px;
    background: transparent;
    border: 0px;
    cursor: pointer;
    /* 【2026-09-11】**✕ は平常時から赤にする。**
       もとは `opacity: 0.5` の無彩で、載せたときだけ赤くしていた。2 つ問題があった:
         ・薄いと平常時に「押せるもの」と読めず、**載せて初めて操作だと分かる**
           （SKILL.md「ホバー時だけ操作可能に見える状態にしないこと」に触れる）
         ・同じ画面の中で、右から出る枠の ✕ は赤・小窓の ✕ は無彩と**割れていた**
       ✕ は形そのものが「閉じる・消す」を指しており、色は形が言っていることを
       裏づけるだけ ―― 押す前から赤くても、新しい警告を足したことにはならない。
       **見分けるのは形と位置**（枠の右上に置く）なので、色は 1 つでよい。 */
    color: var(--warn);
    opacity: 1;
    /* 返すのは色。薄さは持たなくなったので opacity は遷移させない */
    transition: color var(--color) ease;
}
/* 載せたときは**濃さで返す**（色はもう赤なので、色では返せない）。
   地は敷かない ―― ✕ は枠を持たない絵で、面を持つ釦ではない（構造的不変条件 1）。 */
.close-btn:hover { color: color-mix(in srgb, var(--warn) 80%, var(--ink)); }
.close-btn::before, .close-btn::after {
    content: "";
    position: absolute;
    top: 50%;
    /* 4 の倍数の例外: 28px の当たりに 16px の線を置いた余り（28−16）÷2＝6。中央そろえ */
    left: 6px;
    width: 16px;
    height: 1px;
    background: currentColor;
}
.close-btn::before { transform: translateY(-50%) rotate(45deg); }
.close-btn::after { transform: translateY(-50%) rotate(-45deg); }

/* トーストは**右上**。本文の読み位置（左上）を塞がず、
   右から出る枠（詳細・設定）と同じ側に集まるので目が迷わない。
   右パネルを開いているあいだはその幅ぶん内側へ寄せる（重ねない）。 */
/* **上書きしない。積む。** 1 枚を使い回すと「保存しました」が読まれる前に
   「削除しました」へ差し替わり、何が起きたのか分からなくなる（実際そうなっていた）。
   器を 1 つ置き、その中へ新しい札を足していく。 */
.toast__stack {
  position: fixed; top: calc(var(--shell-header-h) + 16px); right: 32px; z-index: 120;
  display: flex; flex-direction: column; align-items: flex-end; gap: 8px;
  pointer-events: none;                    /* 器は触れない。触れるのは中の札だけ */
}
/* 【2026-09-11】**右から出る枠が開いても動かさない。**
   長らく `body[data-panel-open] .toast__stack { right: calc(var(--info-w) + 16px) }` と
   枠の幅ぶん内側へ寄せていた（「寄せないと枠の下に潜って読めない」という理由）。やめた。

   ・**そもそも潜らない。** 重なり順は札 120／ドロワー 100／モーダル 110 で、札が最前面。
     隠れるから寄せていたのではなく、枠を覆わないために寄せていた。
   ・**幅を 1 つしか知らない。** `--info-w` 決め打ちなので、右から出る枠が 2 種類ある
     配備先では合わない ―― 実測（つながり 1440）: 640px の枠を開くと、札の右端 1084 に対し
     枠は 800 から始まり、**寄せたのに潜っていた**。正典自身が
     references/overlays.md で「右から出る枠が 2 つ以上あるとき」を想定しているのに、
     ここだけ 1 種類の前提で書いてあった＝**正典の中で食い違っていた**。
   ・動かさなければ、枠が何種類あっても・掴んで幅を変えても、札の位置は変わらない。
     報せは「いま起きたこと」で、出る場所が状況で動くほうが目で追いにくい。

   覆うのは 4 秒（`--reveal` の寿命）で、その間に枠の右上が読めなくなるだけ。
   枠の題は左端にあり、✕ は札の下に来ないので、閉じる道も塞がない。 */

/* **報せは 1 行で出す。** 折り返すと札の高さが中身ごとに変わり、
   積んだときに下の札が飛ぶ（新しいのが増えるたび、読んでいた札が動く）。
   高さが揃っていれば、増えても目は同じ位置を追える。
   幅は中身なり（`width` を決め打ちしない）。長すぎるときだけ端で切る。 */
.toast {
  display: flex; align-items: center; gap: 16px;
  width: auto;
  max-width: min(560px, calc(100vw - 64px));
  color: var(--ink); line-height: 1.6;
  transform: translateY(-8px);
  background: var(--panel-face); border: 1px solid var(--hairline-strong);
  /* 面の左辺にアクセントの縦線は置かない。重大度は枠線と文字の色で足りるし、
     線を置くと角丸を崩さざるを得ず（0px 4px 4px 0px）、
     「角丸は 4px に統一」という本書の看板に例外ができる。 */
  border-radius: 4px;
  box-shadow: 0px 1px 2px var(--hairline-strong), 0px 8px 20px var(--shadow);
  padding: 12px 20px 12px 20px; font-size: 14px;
  opacity: 0; pointer-events: none;
  transition: opacity var(--color) ease, transform var(--color) ease, right var(--slide) var(--slide-ease); z-index: 120;
}
/* 出ている間だけ押せる。**基本の状態（隠れている側）は pointer-events: none。**
   同じ規則の中で auto → none と二度書いていたため後の none が勝ち、
   出ていても押せない＝閉じる釦が効かない状態になっていた。 */
.toast--visible { opacity: 1; transform: translateY(0px); pointer-events: auto; }
/* **種別は枠線（と、危ないものだけ文字）の色で示す。面は塗らない**（editorial のまま）。
   1 種類（警告）しか無かったので、成功も通知も同じ見た目で出ていた ―― 報せの重さが
   読み手に伝わらない。ある配備先が 4 種に分けていたので、それを正典へ引き取る。
     済んだ  → 飾り色（ライト金 / ダーク青）
     報せ    → **色を足さない**（下）
     注意    → 飾り色（済んだと同じ色。違いは言葉が持つ）
     危ない  → 警告色。**ここだけ文字も染める** ―― 見落とすと取り返しがつかない

   【2026-09-11】**「報せ」からキーカラーを外した。** それまで `--accent` を当てていて、
   「ログインしました。」のような**いちばんふつうの報せ**が、暗いところで明るい水色
   （#48b3dc）の枠で出ていた ―― 何も起きていないのに強く光る。配備先から
   「そとわくの色が青ではおかしい」と指摘があり、実測して次が分かった:

     ライト  済んだ #8f7625 ／ 報せ #0a3d62 ／ 注意 #8f7625 ／ 危ない #b93131
     ダーク  済んだ #48b3dc ／ 報せ #48b3dc ／ 注意 #48b3dc ／ 危ない #fa6b6b

   ダークは `--gold` も `--gold-line` も `--accent` に畳まれていたので、
   **報せの枠が明るい水色（#48b3dc）**で出ていた ―― 何も起きていないのに強く光る。

   直したのは **`--gold-line` の暗いときの値**（tokens）で、規則のほうは 3 種とも
   この 1 つを読むまま。`--gold-line` は**この札しか使っていない**ので、
   ここを入れ替えても他の画面は動かない（実測: parts/ の中で読んでいるのは本書だけ）。
     ライト  金（#8f7625）
     ダーク  白（--ink）
   「危ない」だけは別の色のまま ―― 見落とすと取り返しがつかないものなので、
   どちらのテーマでも 1 つだけ赤で立たせる。 */
.toast--done   { border-color: var(--gold-line); }
.toast--notice { border-color: var(--gold-line); }
.toast--warn   { border-color: var(--gold-line); }
.toast--danger { border-color: var(--warn); color: var(--warn); }
/* 1 行で出す。入りきらないときは折らずに端で切る。
   ＝ 札の高さが文言の長さで変わらない。 */
.toast__text {
  flex: 1 1 auto; margin: 0px 0px 0px 0px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 理由を並べるときも 1 つにつき 1 行（件数ぶん縦に積むので、折ると一気に伸びる） */
/* 理由の並び。**器も skill が持つ** ―― 一度どこにも規則が無く、配備先が自分で
   上の空きと字下げと字の大きさを足していた（実測で 1 件・16px にしていて札より大きかった）。
   札は 12px なので中も 12px。字下げは印のぶんだけ（16px）。 */
.toast__reasons {
  margin: 8px 0px 0px 0px; padding: 0px 0px 0px 16px;
  font-size: 14px; line-height: 1.6; color: var(--ink);
}
.toast__reasons > li { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 処理中の全画面ブロック。**操作を遮るものなので、遮っている理由が
   一目で読める大きさ**にする（13px だと画面の真ん中で見落とす）。
   待ちの印はスピナーではなく**走る下線** ―― この UI の状態表現は
   下線に統一してあるので、ここだけ別の語彙を持ち込まない。 */
.busy-overlay {
  position: fixed; inset: 0px; z-index: 200;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px;
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
}
.busy-overlay[data-show="1"] { opacity: 1; pointer-events: auto; }
.busy-overlay__title {
  font-size: 24px; font-weight: 800; letter-spacing: 0.02em; color: var(--ink);
}
.busy-overlay__note { font-size: 16px; color: var(--mute); }
/* 走る下線。幅 240px の溝の中を 96px の線が往復する */
.busy-overlay__bar {
  position: relative; width: 240px; height: 2px;
  background: var(--hairline); overflow: hidden;
}
.busy-overlay__bar::after {
  content: ""; position: absolute; left: 0px; top: 0px; width: 96px; height: 2px;
  background: var(--accent); animation: busySlide 1.1s ease-in-out infinite;
}
@keyframes busySlide {
  0%   { transform: translateX(-96px); }
  100% { transform: translateX(240px); }
}
/* 動きを抑える設定のときの姿（`animation: none; width: 240px`）は
   **parts/reduced-motion が持つ**。以前ここにも同じ 2 行を書いていたが、
   生成物に同じ規則が二度出て、片方だけ直したときに静かに割れる形だった
   （bin/check-overlay.py が見つけた）。置き換えの規則はあちらに集めてある。 */

/* ============================================================
   3-b. 影は「本文の外にあって、上に乗るもの」だけに付ける
   ------------------------------------------------------------
   本文の中のもの（カード・行・ボタン）は平らなまま＝この UI の基調。
   外側の器（ヘッダー・右パネル・伸びたレール）だけが影で浮く。

   ------------------------------------------------------------
   【例外は 1 つだけ ―― 操作を持つ一覧カード】
   「押すと先へ進む」カードが並ぶ一覧（企業検索・検索結果・管理画面の一覧を
   狭い画面で畳んだもの）だけは、平らにしない。**どれを指しているかを面の
   分かれ目だけで示せない**ため ―― カードは上下に密に積まれ、1px の罫は
   隣のカードの罫とくっついて見える。影で 1 枚だけ持ち上げると、指している
   カードが手前に来て、そこだけ読みに行ける。

     通常   0px 2px 6px var(--shadow)
     ホバー／フォーカス
            枠      var(--hover-line)
            地      color-mix(in srgb, var(--ink) 2%, var(--surface))
            影      0px 0px 0px 1px var(--hover-line), 0px 6px 16px var(--shadow)

   **中の地はほとんど動かさない**（ink 2%）。塗り替えると載せただけでカードが
   別物になり、字の読みやすさも落ちる ―― 状態は**外枠と影**が伝える。
   0 ぼかしの輪は枠を太らせずに濃く見せる手（太さを変えると中身が 1px ずれて
   行がガタつく）。`:focus-within` を必ず並べる ―― 載せたときだけ分かる作りにしない。

   **広げない相手**（ここに影を足さない）:
     ・統計の升目・図・グラフの枠（見るだけで押せない）
     ・読ませる本文のパネル・注記・吹き出し（--sunken で沈める側）
     ・ログインの板・約款の枠のような静的な 1 枚
     ・表の行（PC）―― 幅いっぱいで輪が描けないので、内向きの輪と升目の地で示す
   押せないものが浮くと、「押せる」の合図が意味を失う。

   値の出どころは 実案件の企業検索カード（.co-card）。承認済みの実装で、
   ライト／ダークとも同じ式のままトークン（--shadow / --hover-line）に追随する。
   実装は parts/data-table（狭い画面で表を畳んだカード）にある。
   ------------------------------------------------------------
   **光源は上**にそろえる ―― ヘッダーは下へ、右パネルは本文のある左へ、
   レールは本文のある右へ落とす。
============================================================ */
/* 外周の器に使う影は、面の影（--shadow）より濃くする。
   **--shadow（ink 14%）のままでは見えなかった**（3倍に拡大して実測。
   すぐ上にある仕切りの実線に飲まれて、あるのか無いのか分からない）。
   器の影は「境目のすぐ外」に出るので、面に落とす影より強くないと届かない。 */
:root {
    --shadow-edge: color-mix(in srgb, var(--ink) 30%, transparent);
}
:root[data-theme="dark"] {
    /* 暗いときは黒を落としても見えないので、濃さを上げて輪郭で見せる */
    --shadow-edge: rgba(0, 0, 0, 0.6);
}
/* **OS が暗いだけのとき（釦を押していない）も同じ値にする。**
   ここが無いと `[data-theme="dark"]` が当たらず、上のライト用
   `color-mix(--ink 30%)` がそのまま効く ―― 暗いテーマの --ink は白なので、
   **影ではなく白い光**がヘッダーの下に出る（sp-header のコメントが警告している
   のと同じ落とし穴を、この器自身が踏んでいた）。 */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --shadow-edge: rgba(0, 0, 0, 0.6);
    }
}
/* ヘッダーは下へ。近い影で境目を締め、遠い影で本文が下をくぐって見えるようにする。
   仕切りの実線は残す（editorial の骨格）。影はその外側に出る。 */
:root .site-header,
/* 狭い画面のヘッダー（sp-header）も同じ器。自前で --hairline-strong を使うと、
   暗いときは ink が白なので影ではなく白い光になる。ここで 1 か所にそろえる。 */
:root .sp-header { box-shadow: 0px 1px 2px var(--shadow-edge), 0px 6px 14px var(--shadow); }
/* 読み込み時アニメの抑止。描画が済むまで transition を殺しておく
   （外さないと、開いた瞬間に全部の下線が一斉に伸びる）。JS が1フレーム後に外す。 */
:root[data-preload] * {
    transition: none;
    animation: none;
}

/* ---------- ドロワー: 外枠 ----------
   **これが無いと中のシートが行方不明になる。** `.drawer__panel` は `position: absolute` で
   位置を決めるので、基準になる位置指定の祖先が要る。それがここ。
   長らくこの規則だけ実体から抜け落ちていて、解説（references/overlays.md）にしか
   存在しなかった ―― 雛形が `.side-panel` を使っていたため誰も気づかなかった。

   `visibility` は補間しないが**遅れて切り替わる**書き方で出し入れする。
   遅延はパネルの transition と同じ秒数にする（ずれると途中で消えるか、
   消えた後もクリックを吸い続ける）。 */
.drawer {
  position: fixed;
  inset: 0px;
  z-index: 100;
  visibility: hidden;
  transition: visibility 0s linear var(--sheet);
}
/* 開くときは遅延なし（即座に可視にしないとアニメの始点が見えない）。
   値は overlay-base が入れる "1"（"true" ではない） */
.drawer[data-open="1"] {
  visibility: visible;
  transition: visibility 0s linear 0s;
}

/* ---------- ドロワー: 上下右に 12px 空けて浮かぶシート ---------- */
.drawer__panel {
    position: absolute;
    top: 12px;
    right: 12px;
    bottom: 12px;
    width: 440px;
    max-width: calc(92vw - 12px);
    display: flex;
    flex-direction: column;
    border-radius: 4px;
    background: var(--material-thick);
    -webkit-backdrop-filter: blur(30px) saturate(180%);
    backdrop-filter: blur(30px) saturate(180%);
    border: 1px solid var(--hairline);
    box-shadow: 0px 24px 64px var(--shadow);
    transform: translateX(calc(100% + 12px));   /* 右余白ぶんまで画面外へ */
    transition: transform var(--sheet) var(--sheet-ease);   /* iOS シートの曲線（tokens が持つ）*/
}
/* 開閉は overlay-base が `data-open="1"` で行う。ここを "true" にしていたため
   **一度も当たらず、ドロワーが滑り込まなかった**（`side-panel` と同じ約束にそろえる）。 */
.drawer[data-open="1"] .drawer__panel { transform: translateX(0px); }

/* ---------- ドロワー: 居座る形（`.drawer--docked`） ----------
   **右から出る枠が 2 つ以上ある画面のための形**（→ references/overlays.md §0）。
   浮かぶシートをやめて、`.side-panel` と同じ「ヘッダーと下帯の間に居座るパネル」にする。

   **これが無いと、形だけ寄せて出方が食い違う。** 実際に起きた壊れ方（2026-09-11 実測）:
   案件側が `#user-drawer .drawer__panel` に上下右と角丸だけを上書きして
   `.side-panel` と同じ姿にしていたが、**動きの指定は写し忘れていた**。

     右レール → `.side-panel`     transform 0.65s ease                     （--slide）
     表の行   → `.drawer__panel`  transform 0.50s cubic-bezier(.32,.72,0,1)（--sheet）

   同じ縁から同じ大きさで出るのに、片方だけ 0.15 秒速く、曲線も違う。
   並べて見なくても「さっきと違う」と分かる差で、**開くたびに別の画面に見える**。

   浮かぶシートに `--sheet`（iOS の曲線）を当てているのは、**浮いて見せたいから**。
   縁に貼り付く形にした時点でその理由は消えるので、`--slide` に戻す。
   規約は「同じ場所に出るなら、出方・色・影・見出しまでそろえる」（overlays.md §0）。 */
.drawer--docked {
  transition: visibility 0s linear var(--slide);
}
.drawer--docked[data-open="1"] {
  transition: visibility 0s linear 0s;
}
.drawer--docked .drawer__panel {
  top: var(--shell-header-h);
  right: 0px;
  bottom: var(--shell-footer-h);
  max-width: 92vw;
  border-radius: 0px;
  border: 0px;
  border-left: 1px solid var(--hairline);
  box-shadow: -2px 0px 12px var(--shadow);
  transform: translateX(100%);                              /* 右余白が無いので 100% ちょうど */
  transition: transform var(--slide) var(--slide-ease);     /* `.side-panel` と同じ出方 */
}
.drawer--docked[data-open="1"] .drawer__panel { transform: translateX(0px); }
.drawer__head {
    flex: 0 0 auto;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    padding: 24px 24px 16px 24px;
    border-bottom: 1px solid var(--hairline);
}
.drawer__title { font-size: 20px; font-weight: 800; line-height: 1.25; }
/* 行き先の並び。**器は skill が持つ** ―― 一度どこにも規則が無く、配備先が
   自分で上の罫と下の空きを足していた（実測で 1 件）。同じものを次の案件でも
   作ることになるので、既定をこちらへ寄せる。
   上に罫を 1 本引いて「本文の続きではなく別の塊」を示し、下に 16px 空ける。 */
.drawer__links { border-top: 1px solid var(--hairline); margin: 0px 0px 16px 0px; }

.drawer__body { flex: 1; min-height: 0; overflow-y: auto; padding: 24px 24px 24px 24px; }

/* ---- 枠の下端の操作の並び ----
   【2026-09-11】**器がどこにも無く、配備先が自分で作っていた**（実測 1 件。
   つながりの `.drawer-form__actions`）。同じものを次の案件でも作ることになるので
   既定をこちらへ寄せる。中身が長い枠では、いちばん下まで送らないと「更新する」に
   届かないので、**送っても下端に貼り付く**。

   ★ **地は `--panel-face`（枠の面）。ページの地（`--bg`）を敷かない。**
     配備先はここで `--bg` を敷いており、ライトは枠も地も生成りなので気づけないが、
     **ダークは地 #232529 と面 #2d2f33 で段が分かれるので、枠の下端だけ 1 段暗い帯**に
     なっていた（実測: 本文 #323337 / 帯 #282a2d）。枠の中のものは枠の面に乗る。

   ★ **不透明でなければならない。** 貼り付いているあいだ、送られた中身はこの帯の
     **下をくぐる**。半透明（`--material-thick`）にすると字が透けて二重に見える。
     枠の面そのものは半透明でよい ―― あちらの後ろにあるのは本文で、読ませる字ではない。

   ★ `margin` の `auto` と負の値は別々の役。
     上の `auto` … 余った高さを全部吸って、**中身が短い枠でも下端へ落とす**
                   （`position: sticky` だけでは貼り付く先が無く、途中で止まる）。
                   効かせるには親（`.drawer__body` か中の `<form>`）を
                   `display: flex; flex-direction: column` にすること。
     左右下の -24px … `.drawer__body` の padding を打ち消して**枠の端まで**届かせる。
                      帯が文字幅だけの島になると、上の罫が途中で切れて見える。
   ★ `bottom: -24px` も同じ 24px と対。`.drawer__body` の padding を変えたら
     この 3 か所（bottom・margin・padding）を一緒に直す。 */
.drawer__foot {
    position: sticky;
    bottom: -24px;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: 12px;
    margin: auto -24px -24px -24px;
    padding: 16px 24px 16px 24px;
    border-top: 1px solid var(--hairline);
    background: var(--panel-face);
}

/* 取り返しのつかない操作は並びの**反対の端**へ。送る操作の隣に置くと、
   急いでいる人が指の勢いで押す（skill の釦の並びと同じ考え方）。 */
.drawer__foot > .btn--danger { margin: 0px 0px 0px auto; }

/* ============================================================
   骨組み — 狭い画面では PC の骨組みを畳み、ページ自体を送る
   ============================================================
   PC は「ページは動かさず、中の枠だけを送る」作り。
   狭い画面では逆にする ―― 送る面が 2 つあると、どちらが動くのか読めない。

   **分岐幅は 899px。** app-shell が同じ幅で縦積みに切り替わるので、
   ここを 768 にすると 769〜899px で縦積み・768 以下でこちら、と SP の形が 2 つになる。
   （分岐幅を変えるなら両方そろえる。解説: references/sp-breakpoints.md） */
@media (max-width: 899px) {
  /* ★ 【2026-09-11】**帯の丈を言い直す。**
     狭い画面の骨組みは「ヘッダー 56px ／ フッターは中身なり（`auto`・流れの中）」だが、
     `--shell-header-h`（96px）と `--shell-footer-h`（56px）は **PC の値のまま**だった。
     この 2 つは骨組みの外に居るもの ―― 右から出る枠（`.side-panel` / `.drawer--docked`）と
     浮かぶ釦 ―― が上下の位置を読む先なので、狭い画面で開くと**上に 40px の隙間**が空き、
     **下は 56px 足りずに地が覗く**（実測 390×844: 枠が y=96〜788、ヘッダーの下端は 56）。

     **`:root` に書く。`.app` ではない。** 重ねて出す枠は `body` の直下に置くのが作法で、
     `.app` の中に居ない（実測: `#user-drawer` の親は `body`）。

     下の帯（`.site-footer`）は狭い画面では流れの中に居て場所を取らないので **0px**。
     下タブ（`.sp-tabbar`）を出している画面だけ、その丈を入れ直す（すぐ下）。 */
  :root {
    --shell-header-h: 56px;
    --shell-footer-h: 0px;
  }

  /* PC の骨組みは出さない。右レールが持っていた行き先（設定・会社情報）は
     ドロワーの最後の節かフッターへ移す ―― 入口ごと消さない。 */
  .site-header,
  .site-sidebar,
  .site-rail {
    display: none;
  }

  .app {
    /* **短い画面でもフッターを下端に置く。** 中身が少ない画面ではフッターが途中で止まり、
       その下に地の色だけが残る（実測 844px の画面でフッターの下端が 620px ―― 224px の余り）。
       100vh はアドレスバーのぶん実際より高く下端が隠れるので、読める環境では dvh を上書きで使う。 */
    min-height: 100vh;
    min-height: 100dvh;
    height: auto;
    overflow: visible;
    grid-template-columns: minmax(0, 1fr);
    /* 丈は上の `--shell-header-h` と**対で持つ**（数字を 2 か所に置かない）。 */
    grid-template-rows: var(--shell-header-h) minmax(0, 1fr) auto;
    grid-template-areas: "header" "main" "footer";
  }

  /* 下の帯は position: fixed なので本文の高さに入らない。空けないと最後の行が隠れる。
     **あいだは空けない** ―― 16px 空けると地の色が横一本の帯として残り、そこだけ開いて見える。
     切れ目は帯が自分の上辺に持つ 1px の線が受け持つ。 */
  body:has(.sp-tabbar) .app {
    padding: 0px 0px calc(64px + env(safe-area-inset-bottom)) 0px;
  }

  /* 下タブを出している画面は、その丈ぶんを重ねて出す枠にも知らせる
     ―― 知らせないと、右から出た枠がタブの下へ潜る。**空ける値は上と同じ式**。 */
  body:has(.sp-tabbar) {
    --shell-footer-h: calc(64px + env(safe-area-inset-bottom));
  }

  .site-main {
    overflow: visible;
    padding: 0px 16px 32px 16px;
  }

  /* 送るのがページになると、ヘッダーが流れて消えたあと見出しだけが画面上端に残る。
     貼り付くのは .sp-header 1 つにする。 */
  .page-head--sticky {
    position: static;
  }

  /* フッターは 1 行に収まらない。高さを中身なりにして折り返す。 */
  .site-footer {
    height: auto;
    flex-wrap: wrap;
    align-items: flex-start;
    padding: 16px 16px 16px 16px;
  }
}

/* ---- 狭い画面のヘッダー（56px・貼り付く・影）----
   **PC のヘッダーを狭めて使い回さない。** 中身が違う（検索欄と釦 ／ ロゴと ☰）。
   `.site-header` は残したまま 899px で消し、こちらを `.app` の最初の子に置く。

   **役割で高さを変えない。** 移植元は 40px / 70px の 2 通りで、ロゴも 20px / 55px だった
   （20px では筆文字＋英字＋添え字の 3 段組みが潰れて読めない）。56px・ロゴ 36px の 1 本にする。 */
.sp-header {
  display: none;
}

@media (max-width: 899px) {
  .sp-header {
    grid-area: header;
    /* **`sticky`。`fixed` にしない。** fixed だと本文の上に padding-top が要る（基本規約 5 に反する）。
       グリッドの header の行に置いて貼り付ければ、本文は自然にその下から始まる。 */
    position: sticky;
    top: 0px;
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    height: 56px;
    padding: 0px 12px 0px 16px;
    /* 地は不透明にする。中身が下を通るので、透けると字の上に字が重なる */
    background: var(--bg);
    /* **影はここに書かない。** 器（本文の外にあって上に乗るもの）の影は
       `parts/elevation` が 1 か所で持つ ―― あちらは暗いときだけ黒へ切り替える
       `--shadow-edge` を使う。ここで `--hairline-strong` を使うと、暗いときは
       ink が白なので**影ではなく白い光**になる（実測: 地 23 に対して 58）。 */
  }
  .sp-header__logo {
    display: flex;
    align-items: center;
    height: 56px;
    color: var(--ink);
    text-decoration: none;
  }
  .sp-header__logo img {
    max-height: 36px;
    width: auto;
  }
  .sp-header__title {
    font-size: 20px;
    font-weight: 800;
    letter-spacing: 0.02em;
    line-height: 1.2;
  }

  /* ---- ☰（44×44・線 2px）----
     押せる大きさは 44×44（指で押す最小）。3 本の線は箱いっぱい（30×20）にせず中央に置く。
     線は 2px ―― 4px は 24px 幅の中では太く、ロゴの線の太さとも合わない。
     縦位置は flex の中央ぞろえに任せる。`top: 30%` の絶対配置だと、
     ヘッダーの高さを変えたときにずれる（56px なら 16.8px ＝ 3 本 24px の帯が下へはみ出す）。 */
  .sp-header__menu {
    position: relative;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    margin: 0px 0px 0px 0px;
    padding: 0px 0px 0px 0px;
    border: 0px;
    background: transparent;
    cursor: pointer;
  }
  /* **ここの数字は選んでいない。計算で出ている。** 4 の倍数の例外:
     左 10px ＝ (44 − 24) / 2 で 24px の線を 44px の枠の中央に置いた余り。
     上 15 / 21 / 27 も同じで、線 3 本（2px × 3 ＋ 間 6px × 2 ＝ 18px）を
     44px の中央に置くと 15 から始まる。✕ にするときの 6px は線の間そのもの。
     **中央そろえの余りを 4 の倍数に丸めると、中央でなくなる。** */
  .sp-header__menu-line {
    position: absolute;
    left: 10px;
    width: 24px;
    height: 2px;
    background: var(--ink);
    transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.2s ease;
  }
  .sp-header__menu-line:nth-child(1) { top: 15px; }
  .sp-header__menu-line:nth-child(2) { top: 21px; }
  .sp-header__menu-line:nth-child(3) { top: 27px; }

  /* 開いているあいだは ✕。**状態は `aria-expanded` 1 つ**が持つ
     ―― 見た目も読み上げも同じ属性から出る（別クラスを足さない）。 */
  .sp-header__menu[aria-expanded="true"] .sp-header__menu-line:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .sp-header__menu[aria-expanded="true"] .sp-header__menu-line:nth-child(2) { opacity: 0; }
  .sp-header__menu[aria-expanded="true"] .sp-header__menu-line:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
}

/* 動きを抑える設定では線を回さない（消えて現れるだけにする） */
@media (prefers-reduced-motion: reduce) {
  .sp-header__menu-line { transition: none; }
}

/* ---- ☰ の中身（ドロワー）----
   行き先が **7 つ以上**のときはこちら（6 つ以下は下の帯 sp-tabbar）。
   どちらにするかは**数**で決める。役割で決めると、同じ役割で行き先が 1 つ増えた瞬間に帯から溢れる。

   中身と並びは PC の左パネルと**同じ出どころ**にする（行き先が増えるときに直す場所を 1 つに）。 */
.sp-drawer {
  display: none;
}

@media (max-width: 899px) {
  .sp-drawer {
    display: block;
    position: fixed;
    /* **ヘッダーを覆わない。** 画面全部を覆うと、開いているあいだ
       「いま何のサービスの、どの画面から開いたのか」が読めなくなる（ロゴが薄く透けるだけになる）。
       **高さは top と bottom で決める** ―― `height: 100vh` はアドレスバーのぶん下端が隠れる。 */
    top: 56px;
    right: 0px;
    bottom: 0px;
    left: 0px;
    /* 90 は「畳んだサイドバーのフライアウト」の段（SKILL.md の重なり順の表）。
       本文より上、詳細のドロワー 100・モーダル 110 より下 ―― 中から開いた確認は前に出る。 */
    z-index: 90;
    /* **送れる箱にする。** 飾り置き（align-items: flex-start ＋ padding-left: 50px）だと
       項目が増えたとき下が切れる（5 節 11 項目で切れた）。 */
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    /* **透かさない。** 0.95 だと後ろの一覧の字がそのまま読め、字の上に字が重なる。 */
    background: var(--bg);
    transform: translateX(100%);
    /* visibility は退場アニメの**後**に落とす（先に落とすと閉じる動きが飛ぶ）。
       横から出入りする面は 0.65s（SKILL.md の速度の表）。 */
    visibility: hidden;
    transition: transform var(--slide) var(--slide-ease), visibility 0s linear var(--slide);
  }
  .sp-drawer[data-open="1"] {
    transform: translateX(0px);
    visibility: visible;
    transition: transform var(--slide) var(--slide-ease), visibility 0s linear 0s;
  }
  .sp-drawer__body {
    /* 下は指の届く範囲を確保しつつ、iOS の下端（ホームバー）を避ける */
    padding: 16px 20px calc(32px + env(safe-area-inset-bottom)) 20px;
  }

  /* **節ごとに見出しを立てる。** 見出しの無い平らな一覧は、用途の違う 9 項目が同じ重さで並び、
     上から順に読むしかない。PC は節で分かれているのに SP だけ平らだと、
     同じ場所を探すのに 2 通りの読み方が要る。 */
  .sp-drawer__group {
    margin: 0px 0px 24px 0px;
    padding: 0px 0px 24px 0px;
    border-bottom: 1px solid var(--hairline);
  }
  .sp-drawer__group:last-child {
    margin: 0px 0px 0px 0px;
    padding: 0px 0px 0px 0px;
    border-bottom: 0px;
  }
  .sp-drawer__title {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 24px;
    margin: 0px 0px 4px 0px;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.14em;
    color: var(--mute);
  }
  .sp-drawer__list {
    list-style: none;
    margin: 0px 0px 0px 0px;
    padding: 0px 0px 0px 0px;
  }

  /* 行は **44px 以上**（指で押す最小）。`margin: 20px 0` の字の高さだけの行は狙いが外れる。
     **枠は常に 1px 持つ（透明）。** 現在地で枠が付いても字の位置が動かない
     ―― 動くと、開くたびに現在地の行だけがずれて見える。 */
  .sp-drawer__link {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 44px;
    margin: 0px 0px 0px 0px;
    padding: 0px 12px 0px 12px;
    border: 1px solid transparent;
    border-radius: 4px;
    background: transparent;
    color: var(--ink);
    font-size: 16px;
    line-height: 1.4;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    transition: color var(--color) ease;
  }
  /* 現在地は**枠だけ**。薄い塗り＋左の柱の 2 つで 1 つのことを言うと、
     塗りは地の上でほとんど読めないのに行だけが面として浮く。塗らずに線で示す。 */
  .sp-drawer__link--current {
    color: var(--accent);
    border-color: var(--accent);
  }
}

/* 触れる手段のある環境だけホバーを返す（タッチでは押した色が残る） */
@media (hover: hover) {
  .sp-drawer__link:hover { color: var(--accent); }
}

/* 動きを抑える設定。滑らせず、消える・現れるだけにする
   （位置を決めている transform は外す ―― 外さないと閉じている枠が出たままになる）。 */
@media (prefers-reduced-motion: reduce) {
  .sp-drawer {
    transform: none;
    opacity: 0;
    transition: opacity 0.2s ease, visibility 0s linear 0.2s;
  }
  .sp-drawer[data-open="1"] {
    opacity: 1;
    transition: opacity 0.2s ease, visibility 0s linear 0s;
  }
}

/* ---- 下の帯（アイコン 6 つ）----
   行き先が **6 つ以下**のときはこちら（7 つ以上は ☰ のドロワー sp-drawer）。
   押す先が常に見えているのが取り柄で、枠は 6 つが上限（1 枠は 375px の画面で 62px）。 */
.sp-tabbar {
  display: none;
}

@media (max-width: 899px) {
  .sp-tabbar {
    display: block;
    position: fixed;
    right: 0px;
    bottom: 0px;
    left: 0px;
    z-index: 90;                /* ドロワーと同じ段（同じ「行き先」の役） */
    /* **帯そのものは 64px に決め、iOS の下端（ホームバー）の余白は外へ足す。**
       中に足すと帯の高さが変わり、本文側の逃げ（sp-shell）とずれる。 */
    height: calc(64px + env(safe-area-inset-bottom));
    padding: 0px 0px env(safe-area-inset-bottom) 0px;
    background: var(--bg);
    /* 本文との切れ目はこの線 1 本が受け持つ（あいだを空けない。sp-shell の注記） */
    border-top: 1px solid var(--border-strong);
  }
  .sp-tabbar__list {
    display: flex;
    /* **枠を帯の高さいっぱいに伸ばす。** center だと枠が中身なり（絵 22 ＋ 字 12 ＋ 隙間 4 ＝ 38px）に
       しかならず、現在地の塗りが上下に余って**帯の中に札が浮いて**見える。 */
    align-items: stretch;
    height: 64px;
    margin: 0px 0px 0px 0px;
    padding: 0px 0px 0px 0px;
    list-style: none;
  }
  /* **6 等分にする。** `flex: 1 1 auto` だと基準が中身の幅になり、名前の長い項目だけ広くなる
     （実測 375px で「記念日リマインド」82px ／ ほか 63px）。押す位置が項目ごとに変わって見える。 */
  .sp-tabbar__item {
    display: flex;
    flex: 1 1 0px;
    min-width: 0px;
    margin: 0px 0px 0px 0px;
    padding: 0px 0px 0px 0px;
  }
  .sp-tabbar__link {
    display: flex;
    flex: 1 1 0px;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-width: 0px;
    margin: 0px 0px 0px 0px;
    padding: 0px 2px 0px 2px;
    border: 0px;
    background: transparent;
    color: var(--mute);
    /* 10px は読める大きさの下限。8px（移植元）は下限を割っていて、絵だけで見分けていた */
    font-size: 14px;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: color var(--color) ease;
  }
  /* 絵は 24px 固定。**現在地で太らせない** ―― 押すたびに帯の中が動く
     （移植元は 3.2em → 3.7em に太っていた）。 */
  .sp-tabbar__icon {
    flex: 0 0 auto;
    width: 24px;
    height: 24px;
  }
  /* 字は 1 枠 62px に 6 文字まで。入りきらないときは端で切る
     （負の字間で詰めない ―― letter-spacing は正のみ）。 */
  .sp-tabbar__label {
    display: block;
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* **現在地は塗ってよい。** 表示モードそのものを切り替える最上位タブなので、
     「インタラクティブな子要素に background を塗らない」の唯一の例外に当たる
     （構造的不変条件 §1）。 */
  .sp-tabbar__link--current {
    background: var(--accent);
    color: var(--bg);
  }
}

/* 触れる手段のある環境だけホバーを返す。現在地の塗りの上には乗せない（白文字が沈む） */
@media (hover: hover) {
  .sp-tabbar__link:not(.sp-tabbar__link--current):hover { color: var(--accent); }
}

/* ============================================================
   11. 動きを抑える設定（消すのではなく静かな等価表現に置き換える）
============================================================ */
@media (prefers-reduced-motion: reduce) {
    /* まず全部止める（個別の指定は下で静かな等価表現に置き換える） */
    * { transition: none; animation: none; }
    /* 滑らかな送りは酔いの原因になるので、即時送りへ戻す */
    html,
    .site-main,
    .segmented-tabs,
    .nav-panel,
    .data-table__scroll,
    .side-panel__body { scroll-behavior: auto; }

    .toast { transform: none; transition: opacity 0.2s ease; }
    .toast--visible { transform: none; }
    /* **transform を当てない。** 中央寄せは `.modal` の flex（justify/align）が持つので、
       ここで translate(-50%, -50%) を足すと**中央からさらに半分ずれる**。
       実際、動きを抑える設定の人には幅の半分（210px）左・高さの半分上にずれて出ていた。
       `left: 50% / top: 50%` で寄せていた頃の名残で、作りが flex に変わったあとも
       「none にすると中央寄せごと外れる」というコメントごと残っていた。 */
    .modal__panel { transition: opacity 0.2s ease; }
    .drawer__panel { transition: transform 0.2s ease; }
    /* 待ちの印は**走る下線**（`.busy-overlay__bar::after`）。以前ここに書いてあった
       `.busy-overlay__spinner` は実体のどこにも無く、一度も当たらない規則だった。 */
    .busy-overlay__bar::after { animation: none; width: 240px; }
    .nav-panel__item::after, .row-list__item::after, .nav-rail__link::after { transition: width 0.01s linear; }
    /* 開閉マークは `.collapse-rail__chev`（sidebar-collapse-rail）。以前ここに書いてあった
       `.nav-rail__chevron` は実体のどこにも無く、一度も当たらない規則だった。 */
    .collapse-rail__chev { transition: none; }
    .nav-rail__list { transition: none; }
}

/* ---- 強制配色（Windows のハイコントラスト）で印が消えないようにする ----
   **この UI は状態を「色」と「伸びる下線」だけで表す。** その下線は疑似要素の
   `background` で描いてある ―― 強制配色では `background` が系の地の色に置き換わるので、
   **印が地に沈んで完全に消える**。

   実測（`--force-high-contrast` で描いて計算値を読んだ）:
     選択中の項目の印 `rgb(18, 18, 18)` ／ ページの地 `rgb(18, 18, 18)` ―― 同色。
   枠と字は系の色に置き換わって残る（釦は白枠・白字で読めた）ので、**消えるのは印だけ**。
   つまり「どこに居るか」だけが分からなくなる。

   直しかたは**系の色で描き直す**こと。`CanvasText`（地に対する字の色）と
   `Highlight`（選択色）は強制配色でも尊重される。色を選び直すのではなく、
   **系が決めた 2 色に翻訳する**のがこのモードの作法。

   **`forced-color-adjust: none` は使わない。** 自分の色を押し通す指定で、
   系の配色を選んだ人の意思を無視することになる ―― 消えていた印を戻したいだけなので、
   系の色で描けば足りる。 */
@media (forced-colors: active) {
  /* 伸びる下線・立つ棒（ホバーと選択の印）。**選択は Highlight、それ以外は CanvasText** ――
     系が「選ばれているもの」に使うと決めた色を、こちらも選択に使う。 */
  .row-list__item::after,
  .link-underline::after,
  .cselect__option::after,
  .segmented-tabs__tabs::after,
  .sidebar-accordion__label-mark::before,
  .sidebar-accordion__label-mark::after,
  .side-panel__resizer::after,
  .busy-overlay__bar::after,
  .nav-panel__item::after,
  .nav-rail__link::before,
  .site-rail__btn::before,
  /* 閉じる ✕ の 2 本線。`currentColor` で描いてあるので残ると思っていたが、
     **実測すると地と同じ色になった**（器の字の色ごと系の地に寄せられる）。
     ✕ が消えると「閉じる場所」が無くなるので、ここも系の字の色で描き直す。 */
  .close-btn::before,
  .close-btn::after { background-color: CanvasText; }

  /* 自前で描く送り棒の親指も `background` で描いている（parts/scroll-bar）。
     疑似要素ではなく実体の div だが、地に沈む理屈は同じ。 */
  .scroll-bar__thumb { background-color: CanvasText; }

  .nav-panel__item--active::after,
  .nav-rail__link--active::before,
  .cselect__option--selected::after,
  .site-rail__btn[aria-expanded="true"]::before { background-color: Highlight; }

  /* 最上位タブの現在地だけは塗りで表している（構造的不変条件 §1 の例外）。
     塗りごと系の色に置き換える ―― 字も一緒に変えないと、地と同色になって読めない。 */
  .sp-tabbar__link--current { background-color: Highlight; color: HighlightText; }

  /* 状態の印は枠と `currentColor` で描いてあるので系の色になるが、
     **危ないもの／済んだものの区別は消える**（色でしか分けていない）。
     区別が要るときは字を足す ―― ここで色を作り直しても、系の 2 色しか出せない。 */
}

/* ---- 紙に出す ----
   **この UI はページ自体を送らない。** 送るのは中の枠（`.site-main` / `.data-table__scroll`）で、
   枠は画面の高さに切られている ―― そのまま刷ると**1 画面ぶんで切れて、続きが出ない**。
   一覧を刷って渡す用事は必ず出るので、枠を解いておく。

   合わせて、紙に意味の無いものを落とす。ナビ・レール・下帯は**押せない紙の上では
   ただの帯**で、本文の幅をそのぶん奪う。重ね物は「いま開いていないもの」なので出さない。

   **リンクの URL を括弧で書き出す指定は入れない。** 一覧の 1 行ごとに URL が付いて、
   表が読めなくなる（管理画面はリンクが多い）。必要な画面が自分で足す。 */
@media print {
  /* 送る枠を解く。**高さも解く** ―― `overflow: visible` だけでは、
     高さが切られたままなので中身が隠れる（枠の外に出た部分が刷られない）。 */
  .site-main,
  .data-table__scroll,
  .data-table__wrap,
  .side-panel__body {
    overflow: visible;
    height: auto;
    max-height: none;
  }

  /* 骨組みを 1 列にする。列のままだとナビの幅ぶん本文が細くなる */
  .app {
    display: block;
    height: auto;
  }

  /* 紙に意味の無いもの。**押せないので出しても読む人を惑わせるだけ** */
  .site-sidebar,
  .site-rail,
  .site-footer,
  .sp-header,
  .sp-tabbar,
  .sp-drawer,
  .skip-link,
  .scroll-bar,
  .scrim,
  .side-panel,
  .modal,
  .toast__stack,
  .busy-overlay,
  .toolbar,
  .pager { display: none; }

  /* 見出しは残す。**何の画面を刷ったのか**が分からない紙は、あとで捨てられる */
  .site-header {
    position: static;
    border-bottom: 1px solid #000000;
  }

  /* **任意の列を紙では隠さない。** 画面では 1240px 以下で `.data-table__col--opt` を隠すが、
     紙の幅（A4 縦で約 800px）はその内側に入るので、何もしないとスタック・最終配備が
     紙から消える（実測: 刷った紙に「WordPress」が無かった）。隠すのは画面が狭いときの
     都合で、紙には当てはまらない。`revert` で UA の既定（col / cell）に戻す ――
     `table-cell` と書くと `<col class="data-table__col--opt">` まで cell になって列幅が壊れる。 */
  .data-table__col--opt { display: revert; }

  /* **順に現れる仕掛け（revealIn）を止める。** 紙には「あとで出てくる」が無い ――
     刷る瞬間にまだ出番の来ていない行は、`backwards` の初期姿（透明）のまま焼かれる。

     実測（CI 2026-09-12）: 一覧 20 行のうち紙に出たのは 6 行。手元では 20/20 で、
     **同じファイル・同じ指定なのに機械によって結果が変わる** ―― 刷るまでに
     4 秒（`--reveal` の寿命 ＋ 刻み × 行数）経っていれば全部出るので、
     速い機械ほど早く刷って欠ける。時間に依存する検査は、そのぶん静かに壊れる。

     **セレクタは元の規則と同じ形に `html` を足して書く。** `*` では詳細度が足りず
     `html[data-js] .row-list__item`（0,2,0）に負ける ―― メディアクエリは
     詳細度を足さないので、`@media print` の中でも同じ勝負になる（`!important` は使わない）。 */
  html[data-js] .data-table__scroll tbody tr,
  html[data-js] .row-list__item,
  html .site-main__section[data-in] > *,
  html .nav-panel__list > li,
  html .nav-panel__title { animation: none; }

  /* 行を紙の境目で割らない。表は見出しを次の紙にも出す */
  tr, .row-list__item, .site-main__section { break-inside: avoid; }
  thead { display: table-header-group; }

  /* 縁のぼかしを消す。画面で「まだ下に続く」を示す仕掛けで、**紙には続きの向きが無い**
     ―― 最後の 24px だけが薄れた紙が出る。
     （表の行が刷られなくなった件の原因はこれではなかった。犯人は `*` に配った
       `scrollbar-width` で、base-reset 側に理由を書いてある。ここは紙の体裁の話。） */
  [data-more] { mask-image: none; }

  /* 貼り付いていたものを流す ―― 紙の上では貼り付く先が無く、
     `position: sticky` のまま刷ると先頭にだけ出て以降の紙から消える */
  .data-table__head,
  .page-head--sticky { position: static; }
}
