/* Hallmark · macrostructure: Workbench (app surface, not a tour) · retro-GUI panes: toolbar / results / grid / options
 * theme: custom · vibe: "riso flat, retro GUI, pixel, square corners, cool-leaning" · paper: oklch(97% 0.003 95) · accent: oklch(60% 0.14 235)
 * display: JF Dot MPlus12 (12px) · body: IBM Plex Sans JP · outlier: Silkscreen (wordmark + cell numbers + count badges) · axes: light / risograph-bold / cool
 * studied: no · context: user-provided (audience: self, J-POP · use: search → place → PNG · tone: utilitarian) · v1.1.0
 * Hallmark · pre-emit critique: P4 H4 E4 S5 R4 V4
 */
:root {
  /* paper / ink (cool-tinted, no pure extremes) */
  --color-paper:    oklch(97% 0.003 95);
  --color-paper-2:  oklch(93% 0.004 95);
  --color-paper-3:  oklch(89% 0.005 95);
  --color-ink:      oklch(20% 0.012 250);
  --color-ink-2:    oklch(28% 0.012 250);
  --color-muted:    oklch(46% 0.012 250);
  --color-rule:     oklch(76% 0.012 250);
  --color-rule-2:   oklch(82% 0.012 250);
  --color-bar:      oklch(91% 0.006 250);   /* タイトルバーの下地（OS 9プラチナのグレー。題名が読めるよう明るめ） */
  --color-bar-dark: oklch(66% 0.012 250);   /* タイトルバーの縞の影線 */
  /* つまみの握り・面取りで使う2段の白。**暗い白は地色（--color-bar）との差が見えるところまで落とす**
     （半透明の白55% では地色に溶けて、明るい白と区別が付かなかった） */
  --color-hl:      #ffffff;                 /* 明るい白 */
  /* 暗い白。**つまみの地（--color-bar 91%）より明るくする**。87% だと地より暗く、
     握りの縞が影に見えて立体感が消える（実機で確認）。明るい白（100%）との差は残す */
  --color-hl-dim:  oklch(96% 0.008 250);
  /* **出っぱりの内側の下辺・右辺**。外枠（--color-bar-dark）と同じ色にすると、外枠のすぐ内側に
     同じ濃さの線が並んで**濃いグレーが2本に見える**（実機で「影が二重」と報告。画素で確認した）。
     地（--color-bar 91%）と外枠（66%）の中間にすると、2段の面取りとして読める */
  --color-bevel:   oklch(78% 0.012 250);
  /* 掴んでいる間のつまみの地（`.is-grabbed`）。地（--color-bar）より一段暗くして「押し込んだ」と読ませる */
  --color-thumb-held: var(--color-rule-2);
  /* つまみのドット絵の1マス（2026-09-22）。**端末の画素のちょうど整数倍にする**（JSのsetDotUnitが
     round(画素密度) / 画素密度pxを入れる。2.625倍の端末なら3画素 = 1.143px）。1pxのままだと1マスが
     2.625画素になり、同じ太さのはずの縞が位置によって2画素と3画素にばらつく（真ん中だけ太い、と報告） */
  --u: 1px;
  /* スライダーのつまみ（19×18のドット絵）。**色は上の --color-bar-dark / --color-bevel / --color-hl-dimの写し**
     （SVGの中からはCSS変数が読めない）。上の色を変えたら、ここと暗い地の組の同じ行も直す */
  --range-thumb: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='18' viewBox='0 0 19 18' preserveAspectRatio='none' shape-rendering='crispEdges'%3E%3Cpath fill='oklch(66%25 0.012 250)' d='M0 0h19v1H0zM0 17h19v1H0zM0 0h1v18H0zM18 0h1v18h-1zM5 5h1v8H5zM9 5h1v8H9zM13 5h1v8h-1z'/%3E%3Cpath fill='oklch(78%25 0.012 250)' d='M1 16h17v1H1zM17 1h1v16h-1z'/%3E%3Cpath fill='%23fff' d='M1 1h17v1H1zM1 1h1v16H1zM4 4h1v1H4zM8 4h1v1H8zM12 4h1v1h-1z'/%3E%3Cpath fill='oklch(96%25 0.008 250)' d='M4 5h1v7H4zM8 5h1v7H8zM12 5h1v7h-1zM17 1h1v1h-1zM1 16h1v1H1z'/%3E%3C/svg%3E");
  /* スクロールバーのつまみの枠（外枠＋面取り。border-imageで9つに割って伸ばす）と握りの縞（縦のバー用・横のバー用）。
     色は上の3色の写し。スライダーのつまみと同じく、上の色を変えたら暗い地の組の同じ行も直す */
  --sb-frame: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='5' height='5' viewBox='0 0 5 5' shape-rendering='crispEdges'%3E%3Cpath fill='oklch(66%25 0.012 250)' d='M0 0h5v1H0zM0 4h5v1H0zM0 0h1v5H0zM4 0h1v5H4z'/%3E%3Cpath fill='oklch(78%25 0.012 250)' d='M1 3h3v1H1zM3 1h1v3H3z'/%3E%3Cpath fill='%23fff' d='M1 1h3v1H1zM1 1h1v3H1z'/%3E%3Cpath fill='oklch(96%25 0.008 250)' d='M3 1h1v1H3zM1 3h1v1H1z'/%3E%3C/svg%3E");
  --sb-grip-v: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='16' viewBox='0 0 9 16' shape-rendering='crispEdges'%3E%3Cpath fill='%23fff' d='M0 0h2v2H0zM0 6h2v2H0zM0 12h2v2H0z'/%3E%3Cpath fill='oklch(96%25 0.008 250)' d='M2 0h5v2H2zM2 6h5v2H2zM2 12h5v2H2z'/%3E%3Cpath fill='oklch(66%25 0.012 250)' d='M2 2h7v2H2zM2 8h7v2H2zM2 14h7v2H2z'/%3E%3C/svg%3E");
  --sb-grip-h: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='9' viewBox='0 0 16 9' shape-rendering='crispEdges'%3E%3Cpath fill='%23fff' d='M0 0h2v2H0zM6 0h2v2H6zM12 0h2v2h-2z'/%3E%3Cpath fill='oklch(96%25 0.008 250)' d='M0 2h2v5H0zM6 2h2v5H6zM12 2h2v5h-2z'/%3E%3Cpath fill='oklch(66%25 0.012 250)' d='M2 2h2v7H2zM8 2h2v7H8zM14 2h2v7h-2z'/%3E%3C/svg%3E");
  /* スクロールバーの矢印（上・下・左・右）。**塗りは --color-inkの写し**（暗い地の組も同じ行を直す） */
  --sb-arrow-up: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M4.5 1.5 8 7H1z' fill='%23232a33'/%3E%3C/svg%3E");
  --sb-arrow-down: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M4.5 7.5 1 2h7z' fill='%23232a33'/%3E%3C/svg%3E");
  --sb-arrow-left: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M1.5 4.5 7 1v7z' fill='%23232a33'/%3E%3C/svg%3E");
  --sb-arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M7.5 4.5 2 8V1z' fill='%23232a33'/%3E%3C/svg%3E");
  /* ラジオボタンのドット絵だけで使う灰色（Mac OS 8の図の灰色の段に合わせた。2026-09-22） */
  --color-radio-mid:  oklch(63% 0.008 250);
  --color-radio-deep: oklch(57% 0.008 250);
  --color-radio-dark: oklch(38% 0.010 250);
  /* the six riso inks — badges and one primary accent */
  --color-mustard:  oklch(80% 0.150 88);
  --color-cerulean: oklch(60% 0.140 235);
  --color-lavender: oklch(74% 0.100 295);
  --color-vermilion:oklch(62% 0.200 32);
  --color-mint:     oklch(84% 0.110 165);
  --color-pink:     oklch(78% 0.130 350);
  /* もう1組のパレット（色見本から取った値なのでoklchではなく16進）。
     この6色のどれかを背景に選ぶと、下の [data-palette="pop"] で画面の装飾色もこちらに入れ替わる。
     **backend/render.pyのTOKENSとfrontendのTOKENS_RGBにも同じ値がある。片方だけ変えない** */
  /* 3つ目の組「ナイト」。**地が暗い組**（画面も暗い側のプラチナに入れ替わる） */
  --color-night:         #14181d;
  --color-chalk:         #f2f0ec;
  --color-amber:         #ffb43d;
  --color-azure:         #58a6ff;
  --color-flare:         #ff6b6b;
  --color-violet:        #b18cff;
  --color-jade:          #3ddc97;
  --color-magenta:       #ff5ec4;
  /* ポップの地と文字。**パレットは8色ひと組**なので、クリームと黒も組ごとに持つ */
  --color-ivory:       #fdf4e6;
  --color-charcoal:    #1b2430;
  --color-lemon:       #fbd743;
  --color-ultramarine: #4878da;
  --color-coral:       #f0535a;
  --color-sky:         #87d4ff;
  --color-leaf:        #52a555;
  --color-rose:        #f2418f;
  --color-accent:   var(--color-cerulean);
  --color-accent-ink: var(--color-paper);
  --color-error:    var(--color-vermilion);
  --color-grain:    oklch(20% 0.012 250 / 0.06);   /* overlay modifier for halftone dots */
  /* **影は「地より暗い色」**。地が暗い組ではinkが明るくなるので、影にinkを使うと光って見える */
  --color-shadow:   var(--color-ink);
  /* 色つきの下地に置く文字。**明るい下地には暗いほう、暗い下地には明るいほう**を置く。
     地が暗い組ではこの2つが入れ替わる（下の [data-ground="dark"]） */
  --color-on-light: var(--color-ink);
  --color-on-dark:  var(--color-paper);
  --color-on-light-2: var(--color-ink-2);   /* 明るい下地の上の添え字（見出し・補足） */

  --font-display: "JF Dot MPlus12", "IBM Plex Sans JP", sans-serif;   /* 2026-09-24にDotGothic16から（英字の上辺が波打って見えた。運用ボードと同じ字）。PCは下の上書きを見る */
  --dot-size: 12px;   /* 操作部品の字の大きさ。ドット字は升目の大きさでしか使えない（M+ 12は12px、PCのTM Dot PCは15px） */
  --font-body:    "IBM Plex Sans JP", "Hiragino Sans", "Noto Sans JP", sans-serif;
  --font-outlier: "Silkscreen", "JF Dot MPlus12", monospace;

  --text-xs: 0.64rem; --text-sm: 0.8rem; --text-base: 1rem; --text-md: 1.25rem; --text-lg: 1.5625rem;
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-6: 24px; --space-8: 32px;
  /* フォーカスの枠（HIGに寄せた、2026-09-23）。黒2pxを1px離して囲む。すき間には下地の紙の色が見える。
     以前は青3pxを2px離していた（今どきのブラウザの見た目） */
  --focus-ring: 2px solid var(--color-ink); --focus-gap: 1px;
  --line: 2px;
  --page-inline: var(--space-4);   /* ページ左右の基準余白。ヘッダー・ペイン・フッターで共有 */
  --shadow: 4px 4px 0 var(--color-shadow);
  --shadow-sm: 2px 2px 0 var(--color-shadow);
  /* **1デバイス画素ぶんのCSS px**。起動時に `snapDot()` が端末の画素密度から入れ直す。
     1pxの目は端末の画素に乗らないとにじみ、市松の1つ1つが2画素・3画素と不揃いに丸められる
     （実機は2.625倍。3デバイス画素 ＝1.1429pxにそろえる） */
  --dot: 1px;
  /* 昔のMacの50% グレー: 1目の市松。**グラデーションではなくSVGの型抜き**で描く。
     `repeating-conic-gradient` は縁が必ずぼけるので、拡大すると目が滲んで見えた（実機で報告）。
     `shape-rendering="crispEdges"` なら縁が立つ。色は型抜きなのでトークンのまま使える */
  /* 開閉の三角（Finderのリスト表示と同じ。閉じていると右、開いていると下）。9x9のドット */
  --disclosure: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="9" height="9" shape-rendering="crispEdges"><path d="M2 0h1v1h1v1h1v1h1v1h1v1h-1v1h-1v1h-1v1h-1v1h-1z" fill="%23fff"/></svg>');
  /* 小さな矢印（Little Arrows）の上向きの三角。7x4のドット。下向きは回して使う */
  --arrow-up: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="7" height="4" shape-rendering="crispEdges"><path d="M3 0h1v1h1v1h1v1h1v1H0V3h1V2h1V1h1z" fill="%23fff"/></svg>');
  --arrow-left: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="8" height="7" shape-rendering="crispEdges"><path d="M3 0h1v2h4v3H4v2H3V6H2V5H1V4H0V3h1V2h1V1h1z" fill="%23fff"/></svg>');   /* 左向きの矢印（8×7。サーバー代の欄でBandcampのボタンを指す） */
  --dither-mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="2" height="2" shape-rendering="crispEdges"><path d="M0 0h1v1H0zM1 1h1v1H1z" fill="%23fff"/></svg>');
  --check-mask: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="18" height="13" shape-rendering="crispEdges"><path d="M16 0h2v1H16zM15 1h3v1H15zM14 2h3v1H14zM13 3h3v1H13zM12 4h3v1H12zM2 5h2v1H2zM11 5h3v1H11zM2 6h3v1H2zM10 6h3v1H10zM3 7h3v1H3zM9 7h3v1H9zM4 8h3v1H4zM8 8h3v1H8zM5 9h5v1H5zM6 10h3v1H6zM7 11h1v1H7z" fill="%23fff"/></svg>');   /* チェック印（18×13のドット絵。OS 9の印を1.5倍にしたもの。色はbackgroundで付ける） */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in: cubic-bezier(0.7, 0, 0.84, 0);
  --dur-tick: 100ms; --dur-short: 180ms; --dur-mid: 260ms;
}

*, *::before, *::after { box-sizing: border-box; border-radius: 0; }
html, body { overflow-x: clip; }
html { background: var(--color-paper); color: var(--color-ink); -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }   /* iPhoneを横にしたとき字が勝手に大きくならないように */
/* 日本語の組み（kiso.cssから借りた。2026-09-28）: 行頭の括弧・句読点を詰める、和文と英数字の間を少し空ける、
   小さい「ゃ」や「ー」を行頭に来させない。効かないブラウザでは何も起きない */
body { text-spacing-trim: trim-start; text-autospace: normal; line-break: strict; }
/* 入力欄と選択欄は空けない。ドット字の選択欄（題名の候補「私を構成する9曲」）に1.5pxの半端なすき間が入り、升目からずれた */
button, input, select, textarea { text-autospace: no-autospace; }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.55;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background-color: var(--color-paper);
  background-image: radial-gradient(var(--color-grain) 1px, transparent 1.2px);
  background-size: 6px 6px;
}
h1, h2, h3, legend { font-family: var(--font-display); font-weight: 400; font-style: normal; line-height: 1.15; margin: 0; overflow-wrap: anywhere; min-width: 0; }
button, input, select { font: inherit; color: inherit; }
img { max-width: 100%; display: block; }
:focus { outline: none; }
:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-gap); }
/* 背景色に新しい6色を選んだときは、画面の装飾色（ワードマークの下線・バッジ・強調）も入れ替える。
   **スロットの名前は変えない**（36か所の参照をそのまま活かすため。色だけ差し替わる） */
:root[data-palette="pop"] {
  --color-mustard:  var(--color-lemon);
  --color-cerulean: var(--color-ultramarine);
  --color-lavender: var(--color-sky);
  --color-vermilion:var(--color-coral);
  --color-mint:     var(--color-leaf);
  --color-pink:     var(--color-rose);
}
/* **地が暗い組を選んだときのプラチナ**（2026-09-16）。単純な反転ではなく、暗い地むけに作り直した組。
   面取りの明るさの並び（明るい白 ＞ 暗い白 ＞ 地 ＞ 濃いグレー）は、光が左上から当たるという
   前提ごと保つ（74% ＞58% ＞38% ＞20%）。**影は中間のグレー**にする（下の `--color-shadow`）。
   切り替えは `applyPalette` が地の明るさで決め、`data-ground="dark"` を付ける。
   判定はサーバー側の描画（`render.py` の `light`）と同じ規則にしてある */
:root[data-ground="dark"] {
  --color-paper:    oklch(24% 0.012 250);   /* 既定。実際はパレットの「地」が上書きする */
  --color-paper-2:  oklch(30% 0.012 250);
  --color-paper-3:  oklch(36% 0.012 250);
  --color-ink:      oklch(95% 0.004 95);
  --color-ink-2:    oklch(86% 0.005 95);
  --color-muted:    oklch(68% 0.012 250);
  --color-rule:     oklch(46% 0.012 250);
  --color-rule-2:   oklch(38% 0.012 250);
  --color-bar:      oklch(38% 0.010 250);
  --color-bar-dark: oklch(20% 0.012 250);
  --color-hl:       oklch(74% 0.010 250);
  --color-hl-dim:   oklch(58% 0.010 250);
  --color-bevel:    oklch(29% 0.012 250);   /* 地38% と外枠20% の中間 */
  /* 掴んでいる間のつまみ。rule-2はこの組ではつまみの地と同じ38%で、掴んでも何も変わらなかった（2026-10-12）。
     明るい組と同じく地より一段（9%）暗くする */
  --color-thumb-held: var(--color-bevel);
  --range-thumb: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='18' viewBox='0 0 19 18' preserveAspectRatio='none' shape-rendering='crispEdges'%3E%3Cpath fill='oklch(20%25 0.012 250)' d='M0 0h19v1H0zM0 17h19v1H0zM0 0h1v18H0zM18 0h1v18h-1zM5 5h1v8H5zM9 5h1v8H9zM13 5h1v8h-1z'/%3E%3Cpath fill='oklch(29%25 0.012 250)' d='M1 16h17v1H1zM17 1h1v16h-1z'/%3E%3Cpath fill='%23fff' d='M1 1h17v1H1zM1 1h1v16H1zM4 4h1v1H4zM8 4h1v1H8zM12 4h1v1h-1z'/%3E%3Cpath fill='oklch(58%25 0.010 250)' d='M4 5h1v7H4zM8 5h1v7H8zM12 5h1v7h-1zM17 1h1v1h-1zM1 16h1v1H1z'/%3E%3C/svg%3E");
  --sb-frame: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='5' height='5' viewBox='0 0 5 5' shape-rendering='crispEdges'%3E%3Cpath fill='oklch(20%25 0.012 250)' d='M0 0h5v1H0zM0 4h5v1H0zM0 0h1v5H0zM4 0h1v5H4z'/%3E%3Cpath fill='oklch(29%25 0.012 250)' d='M1 3h3v1H1zM3 1h1v3H3z'/%3E%3Cpath fill='%23fff' d='M1 1h3v1H1zM1 1h1v3H1z'/%3E%3Cpath fill='oklch(58%25 0.010 250)' d='M3 1h1v1H3zM1 3h1v1H1z'/%3E%3C/svg%3E");
  --sb-grip-v: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9' height='16' viewBox='0 0 9 16' shape-rendering='crispEdges'%3E%3Cpath fill='%23fff' d='M0 0h2v2H0zM0 6h2v2H0zM0 12h2v2H0z'/%3E%3Cpath fill='oklch(58%25 0.010 250)' d='M2 0h5v2H2zM2 6h5v2H2zM2 12h5v2H2z'/%3E%3Cpath fill='oklch(20%25 0.012 250)' d='M2 2h7v2H2zM2 8h7v2H2zM2 14h7v2H2z'/%3E%3C/svg%3E");
  --sb-grip-h: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='9' viewBox='0 0 16 9' shape-rendering='crispEdges'%3E%3Cpath fill='%23fff' d='M0 0h2v2H0zM6 0h2v2H6zM12 0h2v2h-2z'/%3E%3Cpath fill='oklch(58%25 0.010 250)' d='M0 2h2v5H0zM6 2h2v5H6zM12 2h2v5h-2z'/%3E%3Cpath fill='oklch(20%25 0.012 250)' d='M2 2h2v7H2zM8 2h2v7H8zM14 2h2v7h-2z'/%3E%3C/svg%3E");
  /* 矢印は明るい文字色にする（2026-09-24、ナイトモードで暗い三角が暗いボタンに沈んで見づらいと報告） */
  --sb-arrow-up: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M4.5 1.5 8 7H1z' fill='oklch(95%25 0.004 95)'/%3E%3C/svg%3E");
  --sb-arrow-down: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M4.5 7.5 1 2h7z' fill='oklch(95%25 0.004 95)'/%3E%3C/svg%3E");
  --sb-arrow-left: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M1.5 4.5 7 1v7z' fill='oklch(95%25 0.004 95)'/%3E%3C/svg%3E");
  --sb-arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 9 9'%3E%3Cpath d='M7.5 4.5 2 8V1z' fill='oklch(95%25 0.004 95)'/%3E%3C/svg%3E");
  /* **暗い地では「地より明るい中間のグレー」**。地より暗い色にすると、地がもう十分暗いので
     影がまったく見えない（実機で報告）。中間のグレーなら、暗い面の縁に落ちた影として読める。
     **34% では「見えづらい」と2度報告があった**ので58% まで上げた（地24% との差が34%）。
     影は市松で敷くので、見た目の明るさは地と混ざって半分ほどに落ちる。数字どおりには出ない。
     地（24%）と明るい白（74%）の中間あたりで、面取りの並びとは喧嘩しない */
  --color-shadow:   oklch(58% 0.010 250);
  --color-grain:    oklch(95% 0.004 95 / 0.05);
  --color-on-light: var(--color-paper);     /* 明るい下地の上に置く文字 ＝ 暗いほう */
  --color-on-dark:  var(--color-ink);       /* 暗い下地の上に置く文字 ＝ 明るいほう */
  --color-on-light-2: var(--color-paper-3); /* 同じく添え字。地よりわずかに明るい暗色 */
}
::selection { background: var(--color-mint); color: var(--color-on-light); }

/* ---------- toolbar (menubar) ---------- */
.bar {
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap;
  padding: 10px var(--page-inline);   /* 上下: 文字インク＋下線の塊（24px）を10pxで挟む。左右: ペインの左端に揃える */
  border-bottom: var(--line) solid var(--color-ink);
  background: var(--color-paper);
}
.wordmark {
  display: flex; align-items: baseline; gap: var(--space-2);
  font-family: var(--font-outlier); font-weight: 700; font-size: var(--text-lg); letter-spacing: 0.04em;
  white-space: nowrap;
}
/* 版ズレはやめ、文字の下にリソの6色（マスタード／セルリアン／朱赤／ラベンダー／ミント／ピンク）を等分に並べた太線（5px）。
   Silkscreen 25pxの大文字インクは16px。行送りを16pxに固定すると
   インクは箱の2px下から始まるので、margin-topで吸収し、インク下端→線まで3px（1ドット）空ける
   （padding 10px = 隙間5px相当 + 線5px。線は背景グラデーションのハードストップで描く） */
.wordmark .mark {
  font-family: "TrackmentoMark", var(--font-outlier);   /* MがHに見えないよう描き替えたロゴ用（2026-09-19） */
  display: inline-block; line-height: 16px; margin-top: -2px;
  padding-bottom: 10px;
  /* 線の頭に小さな四角（マスタード）を離して置く（2026-09-19、リンクカード・動画と同じ形）。
     線は字面から左右に3pxはみ出し、四角（5px角）はすき間2pxを空けてさらに左の外に出す。
     箱を左に10px・右に3px広げ、そのぶん負のマージンで打ち消す（ロゴの字の位置は変わらない） */
  margin-left: -10px; padding-left: 10px; margin-right: -3px; padding-right: 3px;
  background:
    linear-gradient(var(--color-mustard), var(--color-mustard)) left bottom / 5px 5px no-repeat,
    linear-gradient(to right,
    var(--color-mustard)   0 calc(100% / 6),
    var(--color-cerulean)  0 calc(200% / 6),
    var(--color-vermilion) 0 50%,
    var(--color-lavender)  0 calc(400% / 6),
    var(--color-mint)      0 calc(500% / 6),
    var(--color-pink)      0) right bottom / calc(100% - 7px) 5px no-repeat;
}
/* ロゴを押すとトップへ戻る（2026-09-19）。見た目はリンクにしない（色・下線は親のまま） */
.wordmark a.mark { color: inherit; text-decoration: none; }
.wordmark a.mark:focus-visible { outline: var(--line) solid var(--color-ink); outline-offset: 2px; }
.wordmark small { font-family: var(--font-display); font-size: var(--text-xs); color: var(--color-muted); letter-spacing: 0; }
.lang-switch {
  order: 9;   /* 常にバーの右端。直前の .bar-statusがmargin-left:autoで余白を吸うので、これで右端に付く */
  font-family: var(--font-display); font-size: var(--text-sm); line-height: 1;
  padding: 5px 10px; border: var(--line) solid var(--color-ink);
  background: var(--color-paper); color: var(--color-ink); cursor: pointer;
}
.lang-switch:hover { background: var(--color-ink); color: var(--color-paper); }
/* 窓を動かしたあとに出す「窓を元に戻す」（2026-09-25）。言語の切り替えの左 */
.win-reset { order: 9; font-family: var(--font-display); font-size: var(--text-sm); line-height: 1; padding: 5px 10px;
  border: var(--line) solid var(--color-ink); background: var(--color-paper); color: var(--color-ink); cursor: pointer; }
.win-reset[hidden] { display: none; }
/* **吹き出しの説明**（2026-09-27、Mac OS 8/9のバルーンヘルプ。運用ボードのhelp-videosの②）。「?」で出す・隠すを切り替える。
   出しているあいだは、PCは部品にマウスを重ねると、スマホは部品に触れると吹き出しが出る（スマホは覆い #balloon-veilが
   触れた所を受けるので、部品そのものは動かない）。中身はJSのHELP表（無ければtitleの文）。仕組みはdocs/ui.md */
.help-btn { order: 9; font-family: var(--font-display); font-size: var(--text-sm); line-height: 1; padding: 5px 10px;
  border: var(--line) solid var(--color-ink); background: var(--color-paper); color: var(--color-ink); cursor: pointer; }
.help-btn:hover, .help-btn[aria-pressed="true"] { background: var(--color-ink); color: var(--color-paper); }
/* **狭いスマホでは間隔とボタンの内側を詰める**（2026-09-27）。「?」を足してから、幅360〜375pxではロゴ・「?」・「EN」が1行に
   収まらず（328pxに330px）、390pxでも英語の画面の「日本語」が2行目に落ちて、上の帯が49pxから91pxに伸びていた。
   ロゴはピクセルの字なので縮めない。空の部品（ロゴ横の札・状態の1行）にも間隔が付いていたので、空のときは間隔を打ち消す。
   詰めると360pxで「日本語」まで326pxに収まる（320pxは2行のまま） */
@media (max-width: 420px) {
  .bar { gap: var(--space-2); }
  .lang-switch, .help-btn, .win-reset { padding-inline: 7px; }
  .wordmark small:empty { display: none; }
  .bar-status:empty { margin-right: calc(-1 * var(--space-2)); }
}
/* 枠としっぽはJSがSVGの1本の輪郭で描く（.balloon-frame）。Inside Macintosh（More Macintosh ToolboxのHelp Manager、
   図3-4「Standard balloon positions」）の形に合わせ、**しっぽは吹き出しの角から斜めに出る細い楔**にする（2026-09-27、利用者の指摘。
   最初は辺の真ん中にCSSの三角を2枚重ねていて、付け根で枠線が途切れて見えた）。角は四角のまま（サイトの決まり） */
.balloon { position: fixed; z-index: 90; left: 0; top: 0; max-width: min(20rem, calc(100vw - 16px)); isolation: isolate;
  display: grid; gap: var(--space-2); padding: var(--space-2) var(--space-3);
  font-family: var(--font-body); font-size: var(--text-sm); line-height: 1.6; color: var(--color-ink); }
.balloon[hidden] { display: none; }
.balloon p { margin: 0; }
.balloon a { justify-self: start; color: var(--color-ink); }
.balloon-frame { position: absolute; left: 0; top: 0; z-index: -1; overflow: visible; pointer-events: none; }
.balloon-frame .shade { fill: var(--color-ink); }
.balloon-frame .face { fill: var(--color-paper); stroke: var(--color-ink); stroke-width: var(--line); stroke-linejoin: miter; }
.balloon-veil { position: fixed; inset: 0; z-index: 80; }
.balloon-veil[hidden] { display: none; }
/* 出しているあいだの帯。スマホは覆いで「?」も押せなくなるので、ここに「吹き出しを隠す」を置く */
.balloon-bar { position: fixed; z-index: 85; left: 50%; bottom: var(--space-3); transform: translateX(-50%);
  width: max-content; max-width: calc(100vw - 16px);
  display: flex; align-items: center; gap: var(--space-3); padding: var(--space-2) var(--space-3);
  font-family: var(--font-display); font-size: var(--dot-size); line-height: 1.4;
  background: var(--color-bar); color: var(--color-ink); border: var(--line) solid var(--color-ink); box-shadow: var(--shadow-sm); }
.balloon-bar[hidden] { display: none; }
.balloon-bar .btn { flex: none; }
/* **窓は題名バーを掴んで動かせる**（PCだけ。2026-09-25、利用者の案）。並びの流れからは外さず、ずらして描く（transform）ので
   周りの組み方は崩れない。動かしている間は掴んだ窓を前に出し、影を少し深くする */
@media (min-width: 60rem) {
  /* 指でも動かせる（スマホの「PC版の表示」。2026-09-25、利用者が出先で試して動かなかった）。題名バーの上だけはページをスクロールさせない */
  .pane-title { touch-action: none; }
}
@media (min-width: 60rem) and (pointer: fine) {
  .pane-title { cursor: grab; }
  .pane.is-moving { cursor: grabbing; }
  .pane.is-moving > .pane-title { cursor: grabbing; }
}
.pane.is-moved { position: relative; z-index: 20; }   /* 動かした窓は下の窓の部品（プルダウンの矢印など）より前に出す */
.bar-status { margin: 0 0 0 auto; order: 8; font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-muted); white-space: nowrap; }

/* ---------- Mac OS 9（プラチナ）風のスクロールバー ---------- */
/* WebKit系（Chrome / Edge / Safari）だけ見た目を作り替える。Firefoxは疑似要素を持たないので
   scrollbar-colorで色だけ寄せる。
   OS 9は上下（左右）の矢印が両方とも終端側に並ぶので、start側のボタンを消してend側に2つ出す。
   溝は沈んで見えるよう内側の左上を暗く、つまみは浮いて見えるよう内側の左上を明るくする。 */
/* scrollbar-color / scrollbar-widthを書くと、Chromeは ::-webkit-scrollbar-* を丸ごと無視する。
   そのためFirefox用の指定は「::-webkit-scrollbarを解さないブラウザ」に閉じ込める */
@supports not selector(::-webkit-scrollbar) {
  * { scrollbar-width: auto; scrollbar-color: var(--color-bar) var(--color-paper-3); }
}

::-webkit-scrollbar { width: 16px; height: 16px; }
/* **指で操作する画面では太くする**。16pxは指の当たり判定としては狭く（Materialは48dp、Appleは44ptを勧める）、
   つまみを掴み損ねて溝を押し、別の場所へ飛んでしまう。24pxなら掴める（見た目の作りは変えない） */
@media (pointer: coarse) {
  ::-webkit-scrollbar { width: 24px; height: 24px; }
  ::-webkit-scrollbar-thumb:vertical { min-height: 44px; }
  ::-webkit-scrollbar-thumb:horizontal { min-width: 44px; }
}
/* 溝は両側に1pxの線を引いて筋として見せる。片側だけ明るい色にすると紙の地色に溶けて、
   レーンの端が無いように見える */
::-webkit-scrollbar-track { background: var(--color-paper-3); }
::-webkit-scrollbar-track:vertical {
  box-shadow: inset 1px 0 0 var(--color-bar-dark), inset -1px 0 0 var(--color-bar-dark);
}
::-webkit-scrollbar-track:horizontal {
  box-shadow: inset 0 1px 0 var(--color-bar-dark), inset 0 -1px 0 var(--color-bar-dark);
}
/* つまみの縁はborderの場所に描く。**外側に出るbox-shadow（0 0 0 1px）を使ってはいけない**。
   WebKitはスクロールバー部品の外側を描き直さないので、つまみを動かすと縁の線が溝に残る。
   **線は1枚の絵から描く**（2026-09-22、スライダーのつまみと同じ理由）。以前は外枠・面取り・縞を
   9枚の背景に分けて重ねていたが、1枚ずつ端末の画素へ丸められるので、指で拡大したときなどに
   1枚だけずれて帯や筋が出た。つまみは長さが変わるので1枚の絵を引き伸ばせない。そこで
   - 外枠＋面取りは `border-image`（5×5の --sb-frameを9つに割り、角は2px四方のまま・辺だけ伸ばす）。
     外枠は四辺とも濃いグレー、面取りは上・左が白で下・右が中間のグレー（外枠と同じ濃さだと影が二重に見える）、
     右上と左下の角の1pxは暗い白
   - 握りの縞は真ん中に置く1枚の絵（--sb-grip-v / --sb-grip-h）。白線（先頭2pxだけ明るい白、以降は暗い白）＋
     隙間を開けず隣に置く濃いグレー線を1組として、グレーを2pxずらし白線の端から2pxはみ出させる。3組
   面は透かしてあり、地の色はbackground-colorが出す（:hover / :activeの色替えがそのまま効く） */
::-webkit-scrollbar-thumb {
  background-color: var(--color-bar);
  border: calc(2 * var(--u)) solid transparent;
  border-image: var(--sb-frame) 2 / calc(2 * var(--u));
  background-repeat: no-repeat;
  background-position: center;
}
::-webkit-scrollbar-thumb:vertical { min-height: 28px; background-image: var(--sb-grip-v); background-size: calc(9 * var(--u)) calc(16 * var(--u)); }
::-webkit-scrollbar-thumb:horizontal { min-width: 28px; background-image: var(--sb-grip-h); background-size: calc(16 * var(--u)) calc(9 * var(--u)); }
::-webkit-scrollbar-thumb:hover { background-color: var(--color-paper-2); }
::-webkit-scrollbar-thumb:active { background-color: var(--color-rule-2); }
::-webkit-scrollbar-button { display: none; }
::-webkit-scrollbar-button:vertical:start:decrement,
::-webkit-scrollbar-button:vertical:end:increment,
::-webkit-scrollbar-button:horizontal:start:decrement,
::-webkit-scrollbar-button:horizontal:end:increment {
  display: block; width: 16px; height: 16px;
  background-color: var(--color-bar);
  background-repeat: no-repeat; background-position: center; background-size: 9px 9px;
  border: 1px solid var(--color-bar-dark);
  box-shadow: inset 1px 1px 0 var(--color-hl), inset -1px -1px 0 var(--color-bar-dark);
}
::-webkit-scrollbar-button:active { background-color: var(--color-rule-2); }
::-webkit-scrollbar-button:vertical:start:decrement {
  background-image: var(--sb-arrow-up);
}
::-webkit-scrollbar-button:vertical:end:increment {
  background-image: var(--sb-arrow-down);
}
::-webkit-scrollbar-button:horizontal:start:decrement {
  background-image: var(--sb-arrow-left);
}
::-webkit-scrollbar-button:horizontal:end:increment {
  background-image: var(--sb-arrow-right);
}
/* 縦と横が交わる角は**無地**（2026-09-22）。斜めの線はサイズボックス（窓の大きさを変える所）の印で、
   Mac OS 8/9でも窓の右下にしか出ない（Inside Macintoshの図）。ここは大きさを変えられないので、
   線を入れると押せそうに見えるうえ、面取りと線が画素に丸められて崩れて見えた（スマホで報告） */
::-webkit-scrollbar-corner { background: var(--color-bar); }

/* ---------- panes ---------- */
.workbench {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-4);
  padding: var(--space-4) var(--page-inline);
  align-content: start;
  width: 100%;
  max-width: 96rem;          /* 大画面でグリッド欄が伸びすぎないよう全体を1536pxで止めて中央寄せ */
  margin-inline: auto;
}
/* スマホ（1カラム）ではグリッドを先頭に出す */
@media (max-width: 59.99rem) {
  .pane-grid { order: -1; }
  .pane-search { order: 0; }
  .pane-results { order: 1; }
  .pane-options { order: 2; }
}
/* オプション列の幅: 背景色の見本8個（32px、間隔8px）が1行に収まる内側の幅 ＋ ペインの余白と枠線。
   見本は28pxだったが、操作部品の字を16pxのドット字にしたとき比率の選択肢が2列に入らず、32pxぶん広げた（2026-09-24） */
:root { --options-w: calc(8 * 32px + 7 * var(--space-2) + 2 * var(--space-3) + 2 * var(--line)); }
@media (min-width: 60rem) {
  :root { --page-inline: var(--space-6); }
  .workbench {
    grid-template-columns: minmax(0, 17rem) minmax(0, 1fr) minmax(0, var(--options-w));
    grid-template-areas: "search grid options" "results grid options";
    grid-template-rows: auto 1fr;
    padding: var(--space-6) var(--page-inline);
    gap: var(--space-6);
    align-items: start;
  }
  .pane-search { grid-area: search; }
  /* 候補ペインだけは行の高さいっぱいに伸ばしてグリッドと下端を揃える（他のペインは内容ぶんのまま）。
     height:0＋min-height:100% は、行の高さを決めるときに自分の中身を数えさせないための書き方。
     これが無いと候補が増えたぶんだけ行が伸び、グリッドまで一緒に高くなってしまう。
     中のリストが余りを埋めるよう、ペイン → 本体 → リストの順にflexで高さを渡す。
     **伸ばすのはグリッドの下端まで**（--results-h、JSのfitResultsが入れる）。行の高さはオプション列でも決まり、
     オプションのほうが長いと候補の窓が間延びしていた（2026-09-24、スマホのPC版表示で利用者が気づいた） */
  .pane-results { grid-area: results; align-self: stretch; height: 0; min-height: min(100%, var(--results-h, 100%)); display: flex; flex-direction: column; }
  .pane-results .pane-body { flex: 1; min-height: 0; display: flex; }
  .pane-results .results { flex: 1; min-height: 0; max-height: none; }
  .pane-grid { grid-area: grid; }
  .pane-options { grid-area: options; }
}
/* 広い画面では4列: 検索 | 候補 | グリッド | オプション。列幅は3列のときと同じ（検索・候補17rem、オプションは見本8個分） */
@media (min-width: 80rem) {
  .workbench {
    grid-template-columns: minmax(0, 17rem) minmax(0, 17rem) minmax(0, 1fr) minmax(0, var(--options-w));
    grid-template-areas: "search results grid options";
    grid-template-rows: auto;
  }
}
.pane {
  border: var(--line) solid var(--color-ink);
  background: var(--color-paper);
  box-shadow: var(--shadow);
  min-width: 0;
}
/* Mac OS 9（プラチナ）風のタイトルバー。下地はグレー。縞は「2pxの白線」と「その真下の2pxの濃いグレー線を2px右へずらしたもの」の組を
   4px周期で重ねる（左端に白、右端に影が2pxはみ出して凹凸に見える）。ずらし幅はスクロールバーのつまみの握りと同じ。
   題名は中央、件数と折りたたみボックスは右端。
   題名・件数・ボックスの列（バーの上下いっぱい）には縞を描かず下地色で塗る */
.pane-title {
  --bar-inset: 4px;     /* 縞を描かない上下の余白（折りたたみボックスの上下の余白と同じ）。縞はボックスの高さの帯だけに引く */
  --bar-inset-x: 8px;   /* 縞を描かない左端の余白（縞とボックス・題名の間隔と同じ） */
  position: relative; display: flex; align-items: center;
  min-height: calc(28px + var(--line)); padding: 0 0 0 var(--space-2);   /* 右は .tailが端まで塗る（ボックスより右に縞を出さない） */
  /* **縞の帯は20pxで固定**（白2px＋影2pxの5組ちょうど）。`100% - 上下の余白` にしていたときは、
     バーの高さが端数になる端末で6本目の白線が0.5pxだけはみ出して見えた（スマホで報告） */
  --bar-stripes: 20px;
  border-bottom: var(--line) solid var(--color-ink);
  /* **白線は「左端2pxだけ明るい白、それより右は暗い白」**（つまみの握りとまったく同じ規則。
     つまみでは明るい白の層を2px幅で左に置き、その右に暗い白の層を並べている）。
     線の向きを取り違えて「いちばん上の1本だけ純白」にしていた（2026-09-15に指摘） */
  /* **反復（repeating-linear-gradient）ではなく5組を書き下す**。反復だと1周期（4px）を
     端末の画素に丸めた誤差が積もり、20pxの帯の終わりぎわで6周期目が1画素だけ始まる
     （実機の拡大表示で、5組の下に極細の白線として見えていた）。%
     で書けば帯の高さに比例して割り付けられるので、**6本目は存在しない** */
  background:
    linear-gradient(to bottom, var(--stripe-hl)) var(--bar-inset-x) var(--bar-inset) / 2px var(--bar-stripes) no-repeat,
    linear-gradient(to bottom, var(--stripe-dim)) var(--bar-inset-x) var(--bar-inset) / calc(100% - var(--bar-inset-x) - 2px) var(--bar-stripes) no-repeat,
    linear-gradient(to bottom, var(--stripe-dark)) calc(var(--bar-inset-x) + 2px) var(--bar-inset) / calc(100% - var(--bar-inset-x) - 2px) var(--bar-stripes) no-repeat,
    var(--color-bar);
}
/* 縞1組ぶん = 帯の20%（白10% ＋ 空き10%）。5組で100% ちょうど */
.pane-title {
  --stripe-hl: #fff 0 10%, transparent 10% 20%, #fff 20% 30%, transparent 30% 40%, #fff 40% 50%,
    transparent 50% 60%, #fff 60% 70%, transparent 70% 80%, #fff 80% 90%, transparent 90% 100%;
  --stripe-dim: var(--color-hl-dim) 0 10%, transparent 10% 20%, var(--color-hl-dim) 20% 30%, transparent 30% 40%,
    var(--color-hl-dim) 40% 50%, transparent 50% 60%, var(--color-hl-dim) 60% 70%, transparent 70% 80%,
    var(--color-hl-dim) 80% 90%, transparent 90% 100%;
  --stripe-dark: transparent 0 10%, var(--color-bar-dark) 10% 20%, transparent 20% 30%, var(--color-bar-dark) 30% 40%,
    transparent 40% 50%, var(--color-bar-dark) 50% 60%, transparent 60% 70%, var(--color-bar-dark) 70% 80%,
    transparent 80% 90%, var(--color-bar-dark) 90% 100%;
  --stripe-gap-dark: var(--color-bar) 0 10%, var(--color-bar-dark) 10% 20%, var(--color-bar) 20% 30%, var(--color-bar-dark) 30% 40%,
    var(--color-bar) 40% 50%, var(--color-bar-dark) 50% 60%, var(--color-bar) 60% 70%, var(--color-bar-dark) 70% 80%,
    var(--color-bar) 80% 90%, var(--color-bar-dark) 90% 100%;
  --stripe-gap-hl: #fff 0 10%, var(--color-bar) 10% 20%, #fff 20% 30%, var(--color-bar) 30% 40%, #fff 40% 50%,
    var(--color-bar) 50% 60%, #fff 60% 70%, var(--color-bar) 70% 80%, #fff 80% 90%, var(--color-bar) 90% 100%;
}
.pane-title h2 {
  position: absolute; left: 0; right: 0; top: 0; bottom: 0; width: fit-content; margin-inline: auto;   /* transformで中央寄せしない（半端な位置になり境の1px線がにじむ） */
  display: flex; align-items: center; padding: 0 var(--space-2); background: var(--color-bar);
  font-size: var(--text-sm); letter-spacing: 0.04em; white-space: nowrap;
}
.pane-title .tail { position: relative; margin-left: auto; align-self: stretch; display: flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-2); background: var(--color-bar); }   /* 縞→件数、件数→ボックス、ボックス→右端をすべて8pxに */
/* 縞が題名・右端の列にぶつかる所: 白線より影線が2px右へ飛び出す（左隣2px列は影線だけ）。縞が再開する所: 白線が2px先に始まる（右隣2px列は白線だけ） */
/* **箱はバーと同じ高さ（`top: 0; bottom: 0`）にして、帯は背景の位置と大きさで作る**。
   `top: var(--bar-inset); height: var(--bar-stripes)` と書くと、この列だけ別の箱として
   端末の画素へ丸められ、バー本体の縞から1画素ずれる（3組目から下が下へ段ズレして見えた）。
   箱の上端をバーの背景の原点にそろえれば、同じ式・同じ丸めで描かれる */
.pane-title h2::before, .pane-title .tail::before {
  content: ""; position: absolute; left: -2px; top: 0; bottom: 0; width: 2px;
  background: linear-gradient(to bottom, var(--stripe-gap-dark)) 0 var(--bar-inset) / 100% var(--bar-stripes) no-repeat;
}
.pane-title h2::after {
  content: ""; position: absolute; right: -2px; top: 0; bottom: 0; width: 2px;
  background: linear-gradient(to bottom, var(--stripe-gap-hl)) 0 var(--bar-inset) / 100% var(--bar-stripes) no-repeat;
}
.pane-title .count { font-family: var(--font-outlier); font-size: var(--text-xs); background: var(--color-paper); border: var(--line) solid var(--color-ink); padding: 0 var(--space-1); }
/* Explorer風の最小化ボタン。タイトル行のクリックでも開閉できる */
.pane-title { cursor: pointer; user-select: none; }
.fold {
  width: 24px; height: 20px; padding: 0; flex: none;
  display: grid; place-items: center;
  font-family: var(--font-outlier); font-size: var(--text-xs); line-height: 1;
  background: var(--color-paper); border: var(--line) solid var(--color-ink); cursor: pointer;
}
.fold::before { content: "—"; }   /* 窓の畳む箱（OS 9のcollapse box）。畳んでも形は変えない（窓の丈で分かる） */
.pane[data-collapsed="true"] > :not(.pane-title):not(.editor) { display: none; }
.pane[data-collapsed="true"] { box-shadow: var(--shadow-sm); }
.pane-body { padding: var(--space-3); }
/* 検索ペイン内のBandcamp／手入力は見出し付きの小セクションにして畳めるようにする */
.sub { border-top: var(--line) dashed var(--color-rule); }
.sub-title {
  display: flex; align-items: center; gap: var(--space-2); width: 100%;
  padding: var(--space-2) var(--space-3); border: 0; background: var(--color-paper-2);
  font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink-2); text-align: left; cursor: pointer;
}
.sub-title::before {
  content: ""; flex: none; width: calc(9 * var(--u)); height: calc(9 * var(--u)); margin-inline: 3px 4px;
  background: currentColor; -webkit-mask: var(--disclosure) center / 100% 100% no-repeat; mask: var(--disclosure) center / 100% 100% no-repeat;
  transform: rotate(90deg);
}
.sub[data-collapsed="true"] .sub-title::before { transform: none; }
.sub[data-collapsed="true"] > form { display: none; }
.sub > form { border-top: 0; }

/* 「トラック名の一覧から」の表。枠を重ねて1枚の表に見せる（表計算の升目）。行頭の番号は行見出し */
.list-sheet { display: grid; border: var(--line) solid var(--color-ink); background: var(--color-paper); }
.list-row { display: grid; grid-template-columns: 2.25rem minmax(0, 1fr) minmax(0, 1fr) 2rem; }
/* 行の右端の「×」。その行を消す（下の行が詰まる）。行が3つ未満になると空の行が補われる */
.list-del { border: 0; border-left: 1px solid var(--color-rule); background: var(--color-paper-2); color: var(--color-ink-2);
  font-family: var(--font-display); font-size: var(--text-sm); cursor: pointer; padding: 0; }
.list-del:hover { background: var(--color-paper-3); color: var(--color-ink); }
.list-del:active { background: var(--color-ink); color: var(--color-paper); }
.list-del:focus-visible { outline: 2px solid var(--color-ink); outline-offset: -2px; }
/* 3行しかないときは消しても空の行が補われて何も変わらないので、× を見せない（列と線は残して幅をそろえる。利用者の案） */
.list-del:disabled { color: transparent; cursor: default; background: var(--color-paper-2); }
.list-row + .list-row, #list-rows .list-row:first-child { border-top: 1px solid var(--color-rule); }
.list-row > * { min-width: 0; }
.list-row > * + * { border-left: 1px solid var(--color-rule); }
.list-head { background: var(--color-paper-2); font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink-2); }
/* 狭い窓で「アーティスト名」が2行になっても、見出しの字の下端をそろえる。**升そのものは伸ばしたまま、中の字だけ下へ寄せる**
   （升をalign-self: endで寄せると、空の升（右上の × の列）が低くなって縦線が途中で切れる。2026-09-23、利用者の指摘） */
.list-head > span { padding: var(--space-1) var(--space-2); display: flex; align-items: flex-end; }
.list-num { display: grid; place-items: center; background: var(--color-paper-2); font-family: var(--font-outlier); font-size: var(--text-sm); color: var(--color-ink-2); }
/* 入力欄の枠を消すときに**左の線まで消さない**（`.input` の枠を0にする指定のほうが強く、升の縦線が消えていた。2026-09-23、利用者のスマホで） */
.list-row .input { border: 0; border-left: 1px solid var(--color-rule); box-shadow: none; padding: var(--space-1) var(--space-2); }
.list-sheet + .search-actions { margin-top: var(--space-2); }
/* 表の最下段の「＋ 行を足す」。表の1行に見せる（番号の列の幅だけ字を右へ）。20行になったら隠す */
.list-add { display: block; width: 100%; text-align: left; padding: var(--space-1) var(--space-2) var(--space-1) calc(2.25rem + var(--space-2));
  border: 0; border-top: 1px solid var(--color-rule); background: var(--color-paper-2); color: var(--color-ink-2);
  font-family: var(--font-display); font-size: var(--text-sm); cursor: pointer; }
.list-add:hover { background: var(--color-paper-3); color: var(--color-ink); }
.list-add:active { background: var(--color-ink); color: var(--color-paper); }
.list-add:focus-visible { outline: 2px solid var(--color-ink); outline-offset: -2px; }
.list-add[hidden] { display: none; }
.list-row .input:hover { box-shadow: none; background: var(--color-paper-2); }
.list-row .input:focus-visible { outline: 2px solid var(--color-ink); outline-offset: -2px; }
.list-row .input[aria-invalid="true"] { box-shadow: inset 0 0 0 2px var(--color-error); }

/* ---------- controls ---------- */
.field { display: grid; gap: var(--space-1); }
.field label, .field legend { font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink-2); }
fieldset.field { border: 0; padding: 0; margin: 0; }
fieldset.field legend { margin-bottom: var(--space-1); padding: 0; }
.input {
  width: 100%; min-width: 0;
  padding: var(--space-2) var(--space-3);
  border: var(--line) solid var(--color-ink);
  background: var(--color-paper);
  /* **文字色は必ず指定する**。入力欄は色を継承せず、ブラウザ既定の黒のままになるので、
     地が暗いパレットだと黒地に黒い文字になって読めない（利用者から報告） */
  color: var(--color-ink);
  box-shadow: inset 2px 2px 0 var(--color-paper-3);
  transition: box-shadow var(--dur-short) var(--ease-out);
}
/* textareaはfontを継承しないので揃える。縦だけ伸ばせるようにして、横に広げて崩されないようにする。
   **上の余白を2px足す**。凹みの影（`inset 2px 2px`）が上辺と左辺にだけ乗るので、
   上下の余白が同じだと**文字が上に寄って見える**（利用者から報告）。影のぶんだけ下げて釣り合わせる */
textarea.input { font: inherit; resize: vertical; min-height: 4.5em;
  padding-top: calc(var(--space-2) + 2px); }
.input::placeholder { color: var(--color-muted); }
.input:hover { box-shadow: inset 2px 2px 0 var(--color-rule-2); }
.input:focus-visible { outline-offset: 0; box-shadow: inset 2px 2px 0 var(--color-paper-3); }
.input[aria-invalid="true"] { border-color: var(--color-error); box-shadow: inset 2px 2px 0 var(--color-error); }
/* 誤りのある欄に焦点が当たっているときは、**囲みの色も赤にそろえる**。
   青（焦点）と赤（誤り）が二重の枠に見えて、どちらの状態なのか読み取りにくかった */
.input[aria-invalid="true"]:focus-visible { outline-color: var(--color-error); }
.input:disabled { opacity: .5; cursor: not-allowed; }

.btn {
  --sh: calc(2 * var(--dot));   /* 影のずらし量 */
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
  min-height: 40px; padding: var(--space-1) var(--space-4);
  border: var(--line) solid var(--color-ink);
  background: var(--color-paper); color: var(--color-ink);
  font-family: var(--font-display); font-size: var(--text-base); letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap; cursor: pointer;
  transition: transform var(--dur-tick) var(--ease-out), background-color var(--dur-short) var(--ease-out);
}
/* 影: 市松模様（--dither-maskで型抜き）。ボタン本体と重ならないL字だけをclip-pathで残す。
   **模様は右下の角を基準に敷く**（`mask-position: right bottom`）。左上を基準にすると、
   実際に見えるのは右辺と下辺なので、**ボタンの幅・高さが奇数のときだけ市松の白黒が入れ替わり**、
   ボタンごとにドットの始まりが違って見えた（実機で報告） */
.btn::after, .seg span::after, .popup::after {
  content: ""; position: absolute; inset: calc(-1 * var(--line)); pointer-events: none;
  transform: translate(var(--sh), var(--sh));
  background: var(--color-shadow);
  -webkit-mask-image: var(--dither-mask); mask-image: var(--dither-mask);
  -webkit-mask-size: calc(2 * var(--dot)) calc(2 * var(--dot)); mask-size: calc(2 * var(--dot)) calc(2 * var(--dot));
  -webkit-mask-position: right bottom; mask-position: right bottom;
  -webkit-mask-repeat: repeat; mask-repeat: repeat;
  clip-path: polygon(calc(100% - var(--sh)) 0, 100% 0, 100% 100%, 0 100%, 0 calc(100% - var(--sh)), calc(100% - var(--sh)) calc(100% - var(--sh)));
}
@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: var(--color-paper-2); }
}
.btn:active { transform: translate(var(--sh), var(--sh)); }
.btn:active::after { display: none; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; transform: none; }
.btn:disabled::after { display: block; }
.btn-primary { --sh: calc(4 * var(--dot)); background: var(--color-ink); color: var(--color-paper); }
/* 既定のボタン（Returnで押されるもの）は二重の枠で示す（HIG、2026-09-23）。紙の色1pxのすき間の外に黒3px。
   **ずらした影は出さない**（枠の外に影が重なって枠が欠けて見える。OS 9の既定のボタンも影は無い）。
   Returnで押せるのは、窓を開いたときにこのボタンへ焦点を置いているため（ブラウザの既定の動き） */
.btn-default { box-shadow: 0 0 0 1px var(--color-paper), 0 0 0 4px var(--color-ink); margin: 4px; }
.btn-default::after { display: none; }
.btn-default:active { transform: none; }
@media (hover: hover) and (pointer: fine) { .btn-primary:hover { background: var(--color-ink-2); } }
.btn[data-state="loading"] { cursor: progress; }
.btn[data-state="loading"] .label::after { content: "…"; }
.btn[data-state="loading"]::before { content: ""; width: 8px; height: 8px; background: currentColor; animation: blink 1s steps(2) infinite; }
.btn[data-state="error"] { border-color: var(--color-error); }
.btn[data-state="error"]::after { background: var(--color-error); }   /* 型抜きはそのまま。色だけ変える */
.btn[data-state="success"] { border-color: var(--color-mint); }
@keyframes blink { 50% { opacity: 0; } }
@media (pointer: coarse) { .btn { min-height: 44px; } }

.seg { display: flex; flex-wrap: wrap; gap: var(--space-1); max-width: 100%; min-width: 0; }
.seg label { position: relative; flex: 1 1 auto; }   /* 折り返した各行の項目を行幅いっぱいに広げる（右に空きが残らないように） */
.seg input { position: absolute; inset: 0; opacity: 0; margin: 0; }
/* **ソースだけは格子に並べる**。flexで伸ばすと、最後の行に1つしか残らないとき（4つ目の
   VocaDB）にそれだけ行いっぱいに広がり、ボタンの幅が不揃いに見える（利用者から報告）。
   格子なら列の幅が先に決まるので、行が埋まっていなくても幅がそろう */
#sources { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }   /* 常に2列。auto-fitだとスマホのシート（幅が広い）で3列＋1になる */
#sources label { flex: none; }
/* 折り返しても崩れないよう、1項目ずつ四辺の枠を持つ四角いボタンにする */
.seg span {
  --sh: 2px;
  position: relative;
  display: block; padding: var(--space-1) var(--space-3); text-align: center;
  font-family: var(--font-display); font-size: var(--text-sm); white-space: nowrap; cursor: pointer;
  border: var(--line) solid var(--color-ink); background: var(--color-paper);
  transition: transform var(--dur-tick) var(--ease-out), background-color var(--dur-short) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .seg input:not(:disabled):not(:checked) + span:hover { background: var(--color-paper-2); } }
.seg input:checked + span { background: var(--color-ink); color: var(--color-paper); transform: translate(2px, 2px); }
.seg input:checked + span::after { display: none; }
.seg input:focus-visible + span { outline: var(--focus-ring); outline-offset: var(--focus-gap); }
.seg input:disabled + span { opacity: .45; cursor: not-allowed; }
.seg input:disabled + span::after { display: none; }

/* **ラジオボタンの見た目**（2026-09-22、利用者の指定）。1つだけ選ぶもの（ソース・比率・マスの形・サムネの入れ方・曲名リスト）は
   ボタンの並びではなく、Mac OS 9のダイアログのラジオボタンにする（丸い枠と、選ぶと中に黒い点）。
   仕組みはこれまでどおり中身のinput[type=radio]。**文字まで含めた1行全体を押せる**（labelが押せる範囲）ので、点が小さくても押しやすい */
/* **選択肢は2列の格子にそろえる**（2026-09-24）。流し込みだと字が16pxになってから「2つ・1つ・2つ」と
   不ぞろいに折れ、列の頭がずれて見えた。列の幅は中身の幅（max-content）。PCの欄に2列が入るよう比率の名前を短くした */
.seg.radio { display: grid; grid-template-columns: repeat(2, max-content); gap: var(--space-1) var(--space-4); }
.seg.radio label { flex: 0 0 auto; }
#pad-seg { grid-template-columns: repeat(3, max-content); }   /* 余白の段は名前が短いので3つを1行に（2列だと「たっぷり」だけ次の行に落ちる） */
.seg.radio span {
  display: inline-flex; align-items: center; gap: var(--space-2); padding: var(--space-1) 0;
  border: 0; background: none; text-align: left; font-family: var(--font-body); transform: none;
}
.seg.radio span::before {
  /* **ドット絵の丸**（2026-09-22、利用者の指定）。Mac OS 8のヒューマンインターフェースガイドラインの図
     （https://dev.os9.ca/techpubs/mac/HIGOS8Guide/thig-13.htmlのHIG_CG-004.gif）の16x16を**そのまま写した**。
     絵はJSの `RADIO_DOTS` が今の色の変数で16x16の画像に描き、`--radio-off` / `--radio-on` に入れる。
     **1ドットは端末の画素の整数倍**（`--rp`、JSが画素比から決める）。1ドット = 1 CSS pxのbox-shadowで描いていたときは、
     スマホの半端な画素比（2.625など）でドットの幅が2画素と3画素に揃わず、ドット絵に見えなかった（利用者の報告） */
  content: ""; flex: none; width: calc(var(--rp, 1px) * 16); height: calc(var(--rp, 1px) * 16);
  background: var(--radio-off) no-repeat 0 0 / 100% 100%; border: 0; border-radius: 0;
  image-rendering: pixelated;   /* 拡大してもドットをぼかさない */
  position: relative; top: -0.042em;   /* ドット字（M+ 12）のインクは行の中心より0.042em上に出るので、丸のほうを合わせる（2026-09-24。チェックの注を見る） */
}
.seg.radio span::after { display: none; }
.seg.radio input:checked + span { background: none; color: inherit; transform: none; }
.seg.radio input:checked + span::before { background-image: var(--radio-on); }
@media (pointer: coarse) { .seg.radio span { min-height: 40px; } }

.search-form { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-3); }
.hint-btn {
  display: inline-grid; place-items: center; width: 20px; height: 20px; padding: 0; margin-left: var(--space-1); vertical-align: text-bottom;
  font-family: var(--font-outlier); font-size: var(--text-xs); line-height: 1;
  background: var(--color-paper); border: var(--line) solid var(--color-ink); cursor: pointer;
}
.hint-btn[aria-expanded="true"] { background: var(--color-ink); color: var(--color-paper); }
.note { display: grid; gap: var(--space-3); padding: var(--space-3); font-size: var(--text-sm); }
/* アプリ内ブラウザ（X・LINEなど）向けの案内帯。共有が遅い・失敗しやすいので外部ブラウザを勧める */
/* 文章とボタンを横に並べると、「コピーしました」でボタンの幅が変わったときに「閉じる」が
   次の行へ落ちて見た目が動く。文章の下にボタンを置く形にして、幅が変わっても崩れないようにする */
.inapp { display: grid; gap: var(--space-2); padding: var(--space-2) var(--page-inline);
  background: var(--color-mustard); color: var(--color-on-light);
  border-bottom: var(--line) solid var(--color-ink); font-size: var(--text-sm); }
.inapp p { margin: 0; overflow-wrap: anywhere; }
.inapp .btns { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.inapp .btn { min-height: 36px; padding-inline: var(--space-2); }
.inapp[hidden] { display: none; }
/* ソース説明のモーダル（中央のオーバーレイ） */
.modal { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: var(--space-4); }
.modal[hidden] { display: none; }
.modal-panel { position: relative; width: min(100%, 40rem); max-height: 88dvh; display: grid; grid-template-rows: auto minmax(0, 1fr); border: var(--line) solid var(--color-ink); background: var(--color-paper); box-shadow: var(--shadow); }
.modal-body { overflow-y: auto; }
/* グリッドを大きく見る窓。**画面いっぱいに広げる**（16x16だと欄の中では1マス26pxしかない） */
/* **行の高さを画面に固定する**（`minmax(0, 1fr)`）。既定のautoだと、中の並びが縦に長いとき（1x32で4,874px）
   窓の中身の高さで行が決まり、`place-items: center` がその行の真ん中に窓を置くので、窓ごと画面の外
   （y = 2,038px）に出て、白い下敷きしか見えなかった（スマホで報告、2026-09-17） */
.modal-wide { padding: var(--space-2); grid-template-rows: minmax(0, 1fr); z-index: 45; }   /* 曲を探すシート（50）より下に。窓の中のマスを押して開くシートが裏に隠れていた（2026-09-17、実機で報告） */
.modal-wide .modal-panel { min-height: 0; }
/* **max-heightを外す**。もとの .modal-panelは88dvhで頭打ちにしていて、
   heightを指定してもそちらが勝っていた（16x16で1マス42pxから伸びなかった） */
.modal-wide .modal-panel { width: min(100%, 96rem); height: min(100%, 98dvh); max-height: none; }
/* 上がグリッド（余りの高さいっぱい）、下が選択中のマスの編集。**編集は窓の中へ移す**。
   もとの場所（検索ペインの中）は窓の裏に隠れてしまい、マスを選んでも何も起きないように見える */
.zoom-slot { display: grid; grid-template-rows: minmax(0, 1fr) auto; justify-items: center;
             gap: var(--space-2); padding: var(--space-2); min-height: 0; overflow: hidden auto; }   /* 横は中の枠がスクロールするので、窓自身には出さない */
.zoom-slot .editor { width: min(100%, 48rem); }
/* 拡大窓では全部入る大きさにするので、溝のぶんを空けておく必要がない */
/* 「大きく見る」ボタン。タイトル欄の右に置く（タイトルバーの縞の規則に触らないため） */
.grid-head { grid-template-columns: minmax(0, 1fr) auto; align-items: end; }
/* **ボタンの高さはタイトル欄と同じ式で出す**（1行ぶん＋欄の上下の余白＋枠線）。ボタン共通の40pxのままだと
   欄（44.8px）より5px低く、下辺でそろえているぶん上に段差が出ていた（記事のサムネで指摘） */
.grid-head .btn { white-space: nowrap; min-height: calc(1lh + 2 * var(--space-2) + 2 * var(--line)); }
.pl-choices { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-3) 0 var(--space-2); }
.note p { margin: 0; overflow-wrap: anywhere; }
/* **リンクの色の既定は組の青**（`--color-cerulean`。ナイトならアジュール）。指定の無いリンクはブラウザ既定の
   青（#0000EE）になり、暗い地では読めなかった（「サーバー代のおねがい」の中で報告）。
   黒で置きたい所は各所の `.x a` が上書きする */
a { color: var(--color-cerulean); text-decoration-thickness: 2px; text-underline-offset: 3px; }
/* 訪問済みは組の紫のスロット（`--color-lavender`。ナイトならバイオレット）。ラベンダーは淡い色で明るい地では
   薄すぎるので、文字色を35% 混ぜて沈める（暗い地では文字色が明るいので、混ぜると逆に浮いて読める） */
a:visited { color: color-mix(in oklab, var(--color-lavender) 65%, var(--color-ink)); }   /* oklchだと色相が回り込んでピンクに寄る */
.note a { color: var(--color-ink); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }
.note code { font-family: ui-monospace, monospace; background: var(--color-paper); padding: 0 4px; border: 1px solid var(--color-rule); }
.search-actions { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; }
.msg { font-size: var(--text-sm); color: var(--color-muted); margin: 0; min-height: 1.4em; overflow-wrap: anywhere; }
.msg[data-tone="error"] { color: var(--color-ink); border-left: 6px solid var(--color-error); padding-left: var(--space-2); }
/* 「みんなのグリッドから探せるようにする」。**既定はオフ**なので、押しやすさより
   「入れたことに気付ける」ことを優先して、共有ボタンのすぐ下に置く */
.listed { display: flex; align-items: center; flex: 1 1 12rem; min-width: 0; }
/* 「みんなのグリッド」は**ほかのリンクと同じ色**（既定のa: 組の青、開いたことがあれば組の紫）。黒にしていたときは
   ただの文字に見え、押せると気付かれにくかった（利用者の指摘、2026-09-18） */
/* 箱と文を別々の部品にした行。「に載せる」は押しても何も起きないので、指の形のカーソルを出さず、長押しでも選ばせない。
   **リンクはほかのリンクと同じ動きに戻す**（選べる・押した色はブラウザ既定）。行ごと選べなくしていたときは、
   長押ししてもリンクに水色が付かず、下の「サーバー代のおねがい」のリンクと動きが違った（利用者の指摘） */
.check-sep, .check-sep * { -webkit-tap-highlight-color: transparent; }   /* ブラウザの押した色は使わない（どの箱を光らせるかをブラウザが決めるので、行ごと光った） */
.check-sep { cursor: default; }
.check-sep > span { user-select: none; -webkit-user-select: none; }
.check-sep a { cursor: pointer; user-select: auto; -webkit-user-select: auto; touch-action: manipulation; }
/* **押している間の色は自前で描く**（`:active`）。箱は箱だけ、リンクはリンクの文字だけ。色はブラウザの水色と同じ */
.check-sep input:active { box-shadow: inset 0 0 0 18px rgba(51, 181, 229, .4); }
.check-sep a:active { background: rgba(51, 181, 229, .4); }
/* 確認の窓（「トラックを全て外す」）。幅は文だけなので狭くし、ボタンは右に寄せる */
.modal-narrow { width: min(100%, 26rem); }
.confirm-actions { display: flex; justify-content: flex-end; align-items: center; gap: var(--space-2); margin-top: var(--space-3); }
/* 確認窓はOS 9の警告（Alert）の組み方: 左上にアイコン、右に文、ボタンは右下 */
.confirm-body { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: var(--space-4); align-items: start; }
.confirm-body > p { margin-top: 0; }
.confirm-actions { grid-column: 1 / -1; }
/* 32x32のドット絵を画素比の整数倍で置く（--u。つまみと同じ）。色はトークンから */
.caution { width: calc(32 * var(--u)); height: calc(32 * var(--u)); }
.caution .c-fill { fill: var(--color-mustard); }
.caution .c-edge { fill: var(--color-ink); }
.caution .c-mark { fill: var(--color-on-light); }
/* 行の箱の余白（min-height: 28px）を外して、箱と文字の下端が「トラックを全て外す」の枠の下辺に乗るようにする */
.grid-foot .check { min-height: 0; }
.msg-under { margin-top: var(--space-3); }
.msg .undo, .msg .pick { font: inherit; font-weight: 700; color: var(--color-ink); background: none; border: 0; padding: 0; cursor: pointer; text-decoration: underline; }   /* ボタンの真下に置く注釈。.msgはmargin 0なので詰まって見える */
.msg .dup-note { font-weight: 700; color: var(--color-ink); } .msg .dup-note::before { content: ""; display: block; } .msg .dup-note .ic { width: 12px; height: 12px; margin-right: 4px; vertical-align: -1px; fill: currentColor; } .msg .dup-note .ic-fill { fill: var(--color-paper); }   /* 同じトラックの知らせ（2026-09-26）。改行して太字、頭にNoteの吹き出し。塗りと枠は付けない */
.msg .pick { display: block; margin-top: 4px; text-align: left; }   /* Spotifyのアーティストの候補。名前に空白や「,」が入るので1行に1つ */

/* ---------- results ---------- */
/* overflow-x: hiddenは必須。.result:hoverのtranslateX(2px) が横のはみ出しを作り、
   横スクロールバーが出入りするたび縦バーの長さが変わってしまう。
   右の余白はスクロールバーとの間隔（.pane-bodyの余白はバーの外側なので、ここで空けないと曲がバーに貼り付く）。
   hoverの2pxもこの中で受けるので、8pxあれば切れない */
/* 候補の高さも `svh`。`dvh` だとスクロール中にアドレスバーの伸縮で高さが変わり、一覧が伸び縮みする */
.results { list-style: none; margin: 0; padding: 0 var(--space-2) 0 0; display: grid; align-content: start; gap: var(--space-2); max-height: 44svh; overflow: hidden auto; }   /* 上詰め。ペインを伸ばしたとき、中身が少ないと縦に間延びするため */
@media (min-width: 60rem) { .results { max-height: calc(100dvh - 24rem); } }
.result {
  display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: var(--space-3); align-items: center;
  width: 100%; padding: var(--space-2); text-align: left;
  border: var(--line) solid var(--color-ink); background: var(--color-paper); cursor: pointer;
  transition: transform var(--dur-tick) var(--ease-out), background-color var(--dur-short) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) { .result:hover { background: var(--color-paper-2); transform: translateX(2px); } }
.result:active { transform: translate(1px, 1px); }
.result img { width: 56px; height: 56px; object-fit: cover; border: var(--line) solid var(--color-ink); background: var(--color-paper-2); }
.result .t { font-weight: 700; line-height: 1.3; overflow-wrap: anywhere; }
.result .a { font-size: var(--text-sm); color: var(--color-ink-2); overflow-wrap: anywhere; }
.result .meta { display: flex; gap: var(--space-2); align-items: baseline; flex-wrap: wrap; }
.badge {
  font-family: var(--font-outlier); font-size: var(--text-xs); letter-spacing: 0.02em; line-height: 1.6;
  padding: 0 var(--space-1); border: var(--line) solid var(--color-ink); color: var(--color-on-light); white-space: nowrap;
}
.badge[data-source="itunes"]      { background: var(--color-pink); }
.badge[data-source="soundcloud"]  { background: var(--color-vermilion); }
.badge[data-source="youtube"]     { background: var(--color-vermilion); color: var(--color-on-dark); }
.badge[data-source="nicovideo"]   { background: var(--color-paper-3); }
.badge[data-source="bilibili"]    { background: var(--color-cerulean); color: var(--color-on-dark); }
.badge[data-source="spotify"]     { background: var(--color-mint); }
.badge[data-source="otodb"]       { background: var(--color-on-light); color: var(--color-mustard); }
.badge[data-source="vocadb"]      { background: var(--color-lavender); }
.badge[data-source="musicbrainz"] { background: var(--color-lavender); }
.badge[data-source="discogs"]     { background: var(--color-mustard); }
.badge[data-source="bandcamp"]    { background: var(--color-mint); }
.badge[data-source="manual"]      { background: var(--color-cerulean); color: var(--color-on-dark); }
.empty { padding: var(--space-4) var(--space-2); color: var(--color-muted); font-size: var(--text-sm); display: grid; gap: var(--space-1); }
.empty strong { font-family: var(--font-display); font-weight: 400; color: var(--color-ink); font-size: var(--text-base); }

/* ---------- grid ---------- */
.grid-head { display: grid; gap: var(--space-3); margin-bottom: var(--space-3); }
/* 並びの切り替え（grids-multi）。**OS 9のポップアップメニュー**: 枠の右端に区切り線と下向きの三角、影はボタンと同じ市松。
   中身はブラウザのselect。開いた一覧は自前のメニュー（下の .popup-hit / #popmenu。2026-09-25までは端末のものが出ていた） */
.layouts { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin-bottom: var(--space-3); }
.layouts > label { font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink-2); }
/* お題から始める（2026-10-15）。OS 9のダイアログの中身のように、枠線1本とボタンの並び。影・角丸は付けない */
.start-themes { border: var(--line) solid var(--color-ink); padding: var(--space-3); margin-bottom: var(--space-3); display: grid; gap: var(--space-2); justify-items: start; }
.start-themes[hidden] { display: none; }
.start-themes h3 { margin: 0; font-weight: 400; }
.start-btns { display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* 行の見出し（2026-10-11）。入力欄は行ごとに1つ（番号 → 欄）。字数は12まで */
.rowlabels { margin-bottom: var(--space-3); }
.rowlabels .disclose-body { gap: var(--space-2); padding-top: var(--space-2); }
.rowlabels .hint { margin: 0; color: var(--color-muted); font-size: var(--text-sm); }
.rowlab-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr)); gap: var(--space-2) var(--space-3); }
.rowlab-list li { display: flex; align-items: center; gap: var(--space-2); }
.rowlab-list .n { flex: none; min-width: 2ch; font-family: var(--font-outlier); font-size: var(--text-xs); color: var(--color-ink-2); }
/* 行の見出しの列（書き出しと同じく、グリッドの左。幅と字の大きさはsyncPreviewが書き出しの比率で決める） */
.grid[data-labels="on"] { grid-template-columns: var(--labw) repeat(var(--cols, 3), minmax(0, 1fr)); }
.grid .rowhead { align-self: center; min-width: 0; overflow: hidden; white-space: nowrap; font-weight: 700; font-size: var(--labpx); line-height: 1.2;   /* 長い見出しの2行はJSが<br>で折る */ color: var(--grid-ink, var(--color-ink)); }
.popup { --sh: calc(2 * var(--dot)); --arrow-w: 24px; position: relative; display: inline-flex; flex: 1 1 10rem; min-width: 0; max-width: 22rem; }
.popup select {
  -webkit-appearance: none; appearance: none; width: 100%; min-width: 0; min-height: 40px; margin: 0;
  padding: var(--space-1) calc(var(--arrow-w) + var(--space-2)) var(--space-1) var(--space-3);
  border: var(--line) solid var(--color-ink); border-radius: 0; color: var(--color-ink); cursor: pointer;
  background: linear-gradient(var(--color-ink), var(--color-ink)) right var(--arrow-w) top 0 / var(--line) 100% no-repeat, var(--color-paper);
  font-family: var(--font-display); font-size: var(--text-base); text-overflow: ellipsis;
}
.popup::before {
  content: ""; position: absolute; z-index: 1; top: 0; bottom: 0; right: 0; width: var(--arrow-w); pointer-events: none;
  background: var(--color-ink); transform: rotate(180deg);
  -webkit-mask: var(--arrow-up) center / calc(7 * var(--u)) calc(4 * var(--u)) no-repeat; mask: var(--arrow-up) center / calc(7 * var(--u)) calc(4 * var(--u)) no-repeat;
}
/* **影は外の箱にぴったり重ねる**。ボタンは枠線が自分に付いているので影を枠線1本ぶん外へ広げる（`.btn::after` のinset）が、
   ここは枠線が中のselectにあり、外の箱がもう枠線の外側。同じだけ広げると影が1本ぶん太く、ずれて見えた（実機で報告） */
.popup::after { inset: 0; }
@media (hover: hover) and (pointer: fine) { .popup select:hover { background-color: var(--color-paper-2); } }
.popup select:active { background-color: var(--color-paper-2); }
/* 一覧の中の項目はブラウザが描くので、暗い組でも読めるように色だけ渡す */
.popup option { background: var(--color-paper); color: var(--color-ink); }
/* **一覧は自前のOS 9風のメニューで出す**（2026-09-25、利用者の指摘。スマホではブラウザの黒い一覧が出て、サイトの見た目から浮いていた）。
   selectの上に見えない押し口（.popup-hit）を重ね、押したら #popmenuを開く。値はselectに入れてchangeを出すので、今までの処理はそのまま動く。
   PCはボタンの真下に、スマホは画面の真ん中に題名バー付きの窓で出す */
.popup-hit { position: absolute; inset: 0; z-index: 2; padding: 0; border: 0; background: none; cursor: pointer; }
.popmenu { position: fixed; inset: 0; z-index: 70; }
.popmenu[hidden] { display: none; }
.popmenu-backdrop { position: absolute; inset: 0; }
.popmenu-panel { position: absolute; display: grid; grid-template-rows: auto minmax(0, 1fr); border: var(--line) solid var(--color-ink);
  background: var(--color-paper); box-shadow: var(--shadow); max-height: 70dvh; }
.popmenu-panel > .pane-title { cursor: default; }
.popmenu-list { list-style: none; margin: 0; padding: 0; overflow-y: auto; overscroll-behavior: contain; }
.popmenu-list li { display: flex; gap: var(--space-2); align-items: center; padding: var(--space-2) var(--space-3); cursor: pointer;
  font-family: var(--font-display); font-size: var(--dot-size); color: var(--color-ink); }
/* 頭の印は出力オプションと同じ **OS 8のHIGのラジオボタンのドット絵**（2026-09-25、利用者の指定。✓ の字は書体で形が変わり、ドット絵に見えなかった）。
   大きさとずらしは .seg.radio span::beforeと同じ */
.popmenu-list li::before { content: ""; flex: none; width: calc(var(--rp, 1px) * 16); height: calc(var(--rp, 1px) * 16);
  background: var(--radio-off) no-repeat 0 0 / 100% 100%; image-rendering: pixelated; position: relative; top: -0.042em; }
.popmenu-list li[aria-selected="true"]::before { background-image: var(--radio-on); } /* 項目ごとに線で区切る（利用者の指定） */ .popmenu-list li + li { border-top: var(--line) solid var(--color-rule); }
.popmenu-list li:focus { outline: none; }
.popmenu-list li:focus-visible { background: var(--color-ink); color: var(--color-paper); }
@media (hover: hover) and (pointer: fine) { .popmenu-list li:hover { background: var(--color-ink); color: var(--color-paper); } }
@media (max-width: 59.99rem) {
  .popmenu-backdrop { background: color-mix(in oklab, var(--color-ink) 45%, transparent); }
  .popmenu-panel { left: 50% !important; top: 50% !important; transform: translate(-50%, -50%); width: min(92vw, 26rem) !important; }
  .popmenu-list li { padding: var(--space-3) var(--space-4); }
}
@media (min-width: 60rem) { .popmenu-panel > .pane-title { display: none; } }
.layouts .btn { min-height: 40px; }
/* 縦に長いグリッドはこの枠の中でスクロールする */
/* **溝のぶんは空けない**（2026-09-16。`scrollbar-gutter: stable` をやめた。スクロールしない並びで右に
   空きが残っていた）。行が列より多いときだけ縦にあふれるので、出る／出ないが行き来することはない
   （枠の高さは中身の幅から決める正方形。中身の幅がスクロールバーのぶん縮んでも、あふれる向きは変わらない） */
.grid-scroll { overflow: auto; border: var(--line) solid var(--color-ink); }
/* max-heightはJS（syncPreview）が「3行分の高さ」に設定する。4行以上でスクロールバーが出る */
/* スマホでは検索・候補ペインは常時表示せず、空マスのタップか「曲を探す」で出るシートの中だけに置く */
@media (max-width: 59.99rem) {
  .workbench > .pane-search, .workbench > .pane-results { display: none; }
}
@media (min-width: 60rem) { #find-btn { display: none; } }
/* **「大きく見る」はスマホでも出す**。いったん消したが、8x30のように縦に長い並びでは
   画面の高さいっぱいに開くぶん見やすくなる、と実機で確かめて戻した（利用者の判断） */
.grid {
  display: grid;
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
  /* 余白・マスの間隔・背景色は出力と同じ比率でJS（syncPreview）が設定する */
  gap: var(--space-2);
  padding: var(--space-2);
  background: var(--color-paper);
  list-style: none; margin: 0;
  width: 100%;
  min-width: min(100%, 16rem);
}
.grid[data-numbers="off"] .num { display: none; }
/* アーティスト名の候補は縦に積む。**`.seg`（横並びのセグメント）は使わない**。
   あちらは幅を等分するので、名前が1文字ずつ折れてしまう */
.origin-list { display: flex; flex-direction: column; gap: 6px; }
.origin-list .btn { display: block; width: 100%; text-align: left; white-space: normal; overflow-wrap: anywhere; }
/* 注記（転載元の動画IDと日付）は名前の下の行に、小さく */
.origin-list .origin-note { display: block; font-size: .8em; color: var(--color-muted); margin-top: 2px; }
/* 候補の出どころの見出し（otoDB / ニコニコ動画）。ボタンの並びの中に挟む */
.origin-list .origin-cap { margin: 4px 0 0; font-size: .85em; color: var(--color-muted); }
#e-origin-field .note { margin-bottom: 6px; }
/* `hidden` を付けた段・注記を確実に隠す。`.seg { display: flex }` のような具体的な指定が
   `hidden` の既定（display: none）に勝つので、明示的に打ち消す */
.seg[hidden], .note[hidden], .field[hidden] { display: none; }
/* マスの形。横長は動画サイトのサムネイル（16:9）に合わせたもの。**backend/render.pyの
   CELL_H_BY_RATIOと同じ比**にすること（画面と書き出しで形が違って見える） */
.grid[data-cell-ratio="16:9"] .cell { aspect-ratio: 16 / 9; }
/* 「ぼかして埋める」のマス: 同じ絵をぼかした下地を敷き、本体は切らずに収める
   （Canvasの `coverBlurPad` と同じ見た目。正方形のマスでも効く: 16:9のサムネを左右を切らずに入れる） */
.cell .cover-bg { display: none; }
.cell[data-fit="blur"] .cover-bg {
  display: block; position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; filter: blur(6px); z-index: 0;
  /* **下地を外へ広げてから切り取る**。マスちょうどでぼかすと縁がにじんで四角の枠がぼやける
     （書き出し側の `coverBlurPad` と同じ考え方。あちらは広く描いてからclipする） */
  transform: scale(1.12);
}
.cell[data-fit="blur"] { overflow: hidden; }
.cell[data-fit="blur"] > img:not(.cover-bg) { object-fit: contain; position: relative; z-index: 1; }
/* 下地を敷くと重なり順が変わるので、番号・×・曲名の帯を絵より前に出す */
.cell[data-fit="blur"] .cap { z-index: 2; } .cell[data-fit="blur"] .num, .cell[data-fit="blur"] .rm { z-index: 3; }   /* 番号・× は選んだ枠（::after、z 2）より前に。2だと枠に隠れた（2026-09-26、利用者の指摘） */   /* **positionは変えない**（もとのabsoluteのまま）。relativeにすると流れに入って絵を押し下げ、絵がマスの下に寄っていた（2026-09-26、利用者の指摘「ブラーの位置が変」） */
.cell {
  position: relative; aspect-ratio: 1;
  background-color: var(--color-paper-2);
  background-image:
    linear-gradient(45deg, var(--color-paper-3) 25%, transparent 25%, transparent 75%, var(--color-paper-3) 75%),
    linear-gradient(45deg, var(--color-paper-3) 25%, transparent 25%, transparent 75%, var(--color-paper-3) 75%);
  background-size: 16px 16px; background-position: 0 0, 8px 8px;
  min-width: 0;
}
.cell img { width: 100%; height: 100%; object-fit: cover; }
.cell.is-over { outline: 4px solid var(--color-cerulean); outline-offset: -4px; }
.cell { cursor: pointer; }
.cell.is-selected::after { content: ""; position: absolute; inset: 0; border: 5px solid var(--color-mustard); box-shadow: inset 0 0 0 2px var(--color-ink); pointer-events: none; z-index: 2; }
/* **番号バッジと × は選択の枠（z-index 2）より手前に出す**。枠の帯（5px＋黒線2px）が角に重なって番号が隠れていた
   （ナイトのスマホで報告）。枠の角にかぶさる札として見えるように、位置は動かさない */
.cell .num, .cell .rm { z-index: 3; }
/* 「入れる先」の空マス: 破線のマスタード枠 + 中央に矢印 */
.cell.is-target::after { content: ""; position: absolute; inset: 0; border: 5px dashed var(--color-mustard); box-shadow: inset 0 0 0 2px var(--color-ink); pointer-events: none; z-index: 2; }
.cell.is-target::before { content: ""; position: absolute; inset: 0; background: color-mix(in oklab, var(--color-mustard) 55%, transparent); z-index: 1; }
.cell.is-target .num { background: var(--color-mustard); color: var(--color-on-light); }

/* スマホ用の検索シート（空マスをタップすると検索と候補をまとめて下から出す） */
.sheet { position: fixed; inset: 0; z-index: 50; display: grid; align-items: end; }
.sheet[hidden] { display: none; }
.sheet-backdrop { position: absolute; inset: 0; background: color-mix(in oklab, var(--color-ink) 45%, transparent); }
.sheet-panel {
  position: relative; max-height: 88dvh; display: grid; grid-template-rows: auto minmax(0, 1fr);
  border-top: var(--line) solid var(--color-ink); background: var(--color-paper);
  box-shadow: 0 -4px 0 var(--color-ink);
}
/* 計算機（Macのデスクアクセサリ）風の黒いタイトルバー: 黒地に白の題名、右端に「閉じる」 */
.sheet-head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-bottom: var(--line) solid var(--color-ink);
  background: var(--color-ink); color: var(--color-paper);
}
.sheet-head h2 { font-size: var(--text-base); letter-spacing: 0.04em; color: var(--color-paper); }
.sheet-head .btn { margin-left: auto; min-height: 36px; }
.sheet-body { overflow-y: auto; padding: var(--space-3); display: grid; gap: var(--space-3); }
.sheet-body .pane { box-shadow: none; }
.sheet-body .results { max-height: none; overflow: visible; }   /* 引き出しの中ではスクロール箱にしない（上の理由） */
/* 開いている間は後ろをスクロールさせない。**bodyをposition: fixedにしてはいけない**（2026-09-16に一度やって、
   実機のAndroidでシートの中までスクロールできなくなった）。overflow: hiddenで止まらない端末（iOSなど）は
   JS（lockScrollのtouchmove）がシートの外で始まった指の動きだけ止める */
body.sheet-open { overflow: hidden; }
/* **htmlにも掛ける**（指の画面だけ）。`html, body { overflow-x: clip }` があるため、bodyのoverflow: hiddenは
   画面（viewport）に伝わらない（htmlのoverflowがvisibleでないとbodyの指定はviewportに反映されない決まり）。
   htmlを止めれば、指の下にあるスクロール箱は引き出しの中身だけになり、そこが動く。PCはスクロールバーが
   消えて幅が変わるので掛けない（ホイールの伝播はoverscroll-behavior: containが止める） */
@media (pointer: coarse) { html.sheet-open { overflow-y: hidden; } }
/* 中身の端まで行っても、後ろの画面にスクロールを伝えない */
/* **候補の一覧（.results）には付けない**。引き出しの中ではmax-height: noneで中身を全部出すので
   「スクロール余地の無いスクロール箱」になり、containを付けるとAndroid Chromeが「端まで来ている →
   外に伝えない」と判断して、候補の上で指を動かしても .sheet-bodyが動かなくなった（実機で報告） */
.sheet-body, .modal-panel, .grid-scroll.is-zoom { overscroll-behavior: contain; }
/* 背景のtouch-actionは絞らない。後ろのスクロールはhtmlのoverflowと下のtouchmoveの番人で止めてあり、
   ここでpanを禁じると**拡大したあとの1本指の移動**まで止まる（実機で報告） */
.cell.is-selected .num { background: var(--color-mustard); color: var(--color-on-light); }
.cell.is-selected .cap { inset: auto 7px 7px 7px; }   /* 曲名の帯は選んだ枠（5px＋2px）の内側に収める。枠が帯の端に重なって字が線に掛かっていた（2026-09-26、利用者の指摘） */
.grid[data-selecting="true"] .cell:not(.is-selected) { cursor: copy; }
/* 選択中のマスの編集パネル。**地がマスタード（明るい色）なので、中の文字はぜんぶ
   「明るい下地に置く文字」にそろえる**。`--color-ink-2` のままだと、地が暗い組では
   薄い灰色の文字が黄色の上に乗って読めない（実機で報告） */
.editor .field label, .editor .field legend, .editor-meta { color: var(--color-on-light-2); }
/* 選択中のマスの編集パネル */
.editor { display: grid; gap: var(--space-2); padding: var(--space-3); border-bottom: var(--line) solid var(--color-ink);
  background: var(--color-mustard); color: var(--color-on-light); }
.editor .input { background: var(--color-paper); }
.editor[hidden] { display: none; }
.editor-head { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; font-family: var(--font-display); font-size: var(--text-sm); }
.editor-head .num-badge { font-family: var(--font-outlier); font-size: var(--text-xs); background: var(--color-ink); color: var(--color-paper); border: var(--line) solid var(--color-ink); padding: 0 var(--space-1); }
.editor-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); gap: var(--space-2); }
.editor-meta { font-size: var(--text-sm); margin: 0; overflow-wrap: anywhere; }   /* 色は上のon-light-2 */
.editor-meta a { color: var(--color-on-light); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }
.editor-actions { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.cell[draggable="true"] { cursor: grab; }
.cell.is-dragging { opacity: .5; }
.cell .num {
  position: absolute; left: 0; top: 0;
  font-family: var(--font-outlier); font-size: var(--text-xs); line-height: 1.6;
  padding: 0 var(--space-1); background: var(--color-paper); border-right: var(--line) solid var(--color-ink); border-bottom: var(--line) solid var(--color-ink);
}
.cell .rm {
  position: absolute; right: 0; top: 0; width: 28px; height: 28px; padding: 0;
  display: grid; place-items: center;
  font-family: var(--font-outlier); font-size: var(--text-sm); line-height: 1;
  background: var(--color-paper); border: 0; border-left: var(--line) solid var(--color-ink); border-bottom: var(--line) solid var(--color-ink);
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .cell .rm:hover { background: var(--color-vermilion); } }
.cell .rm:active { background: var(--color-vermilion); }
.cell .cap {
  position: absolute; inset: auto 0 0 0; padding: 2px var(--space-1);
  background: var(--color-paper); border-top: var(--line) solid var(--color-ink);
  font-size: var(--text-xs); line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* マスが小さいときは × と曲名を出さない。28pxの × と曲名の帯が小さいマスを覆って、
   ジャケットがほとんど見えなくなるため（横7マスあたりから起きる）。
   曲名と「このマスを外す」はマスをタップすると出る編集パネル（.editor）に寄せる */
.grid[data-dense="true"] .cell .rm, .grid[data-nocap="true"] .cell .cap { display: none; }   /* × は角の部品なので幅64pxまで出す。帯は高さ72pxから（2026-09-26） */
/* 番号も同じ理由で隠す（31pxのマスだと番号だけで3分の1を覆う）。
   選んだマスにも出さない。番号は編集パネルの見出し（「01選択中のマス」）とメッセージ欄に出るので
   情報は失われないし、マスに乗せればツールチップでも分かる。
   **小さくして出すのは駄目**。番号はピクセルフォントなので、10pxまで落とすと字形が潰れて読めない */
.grid[data-dense="true"] .cell .num { display: none; }
/* 画像が取れなかったマス（2026-09-25、利用者の希望）。取れないと番号だけの空マスになり、入れ忘れと見分けがつかなかった。
   真ん中に幅いっぱいの帯で「画像取得失敗」を出す（帯を幅いっぱいにすれば、PCの15px × 6字 = 90pxでも96pxのマスに収まる）。
   ドット字は縮められないので、小さいマス（dense、96px未満）では「失敗」の2字に替える。書き出しの画像は今までどおり空のマス */
.cell .fail { display: none; }
.cell.is-broken > img { visibility: hidden; }
.cell.is-broken .fail { position: absolute; inset: 0; z-index: 1; display: flex; align-items: center; pointer-events: none; }
.cell .fail-band {
  width: 100%; padding: 2px 0; text-align: center; white-space: nowrap; overflow: hidden;
  font-family: var(--font-display); font-size: var(--dot-size); line-height: calc(var(--dot-size) + 4px);   /* 帯の高さを整数のpxに（ドット字がにじまない） */
  background: var(--color-paper); color: var(--color-ink); border-block: var(--line) solid var(--color-ink);
}
.cell .fail-short, .grid[data-narrow="true"] .cell .fail-long { display: none; }
.grid[data-narrow="true"] .cell .fail-short { display: inline; }

.grid-actions { container-type: inline-size; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); margin-top: var(--space-3); }   /* グリッドと同じ幅いっぱい（上限を付けると右に空きが残る） */
.grid-actions .btn { padding-inline: var(--space-2); }
/* グリッド列が狭いとき（スマホのPC表示など）は2列だと文字の余白が足りないので、ボタンを1列に縦積み */
/* 幅が20rem（320px）を切る狭い画面だけ1列。412pxの端末（欄の幅348px）は2×2のまま */
@container (max-width: 20rem) { .grid-actions > .btn { grid-column: 1 / -1; } }
/* **小さいボタン**（2026-09-25、利用者の指定）。よく使う「トラックを探す」「トラックを共有」だけ大きいまま残し、
   ほか（元に戻す・並びを保存・色で並べ替え・端末から画像を選択…など）は高さ28pxにする。字はドット字の升目の大きさから
   下げられないので、高さと左右の余白で控えめにする。スマホでも同じ（利用者の判断） */
.btn.btn-sm { min-height: 28px; padding: 0 var(--space-2); }
/* 「元に戻す」「やり直す」は右に寄せて2つ並べる */
.grid-actions > .history { grid-column: 1 / -1; display: flex; justify-content: flex-end; gap: var(--space-2); }
/* 保存・読み込み・コピー・色で並べ替えは1つの箱で、幅に合わせて折り返す（2列の升目だとPCの細い窓で字がはみ出す） */
.grid-actions > .minor { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* 各ボタンは行の幅いっぱいまで伸ばし、行の右端をそろえる（右に余白が残ると半端に見える。2026-09-25、利用者の指摘）。
   段の分け方はJS（balanceRows）が決める: 1段に入らなければ2＋2のように**段ごとの数をそろえて**折る（3＋1だと残りの1つだけ細長く伸びる）。
   区切りは幅100% の空の要素（.br）で入れる。測るあいだは .measuringで伸ばさずに本来の幅にする */
.grid-actions > .minor > .btn { flex: 1 1 auto; }
.grid-actions > .minor > .br { flex-basis: 100%; height: 0; }
.grid-actions > .minor.measuring > .btn { flex: 0 0 auto; }
/* 背景なしのできあがりは、透明な所が分かるように市松の上に出す（画像の外の地の模様なので、足さない見た目の「グラデーション」には当たらない） */
/* 背景の決め方は、入る列の数で段ごとの数をそろえて並べる（5つなら3＋2や2＋2＋1。4＋1にはしない）。列の数はJS（balanceColumns）が決める。
   既定は1列（JSが動くまで・測れないとき。「ジャケットと反対の色」が長く、はみ出すよりよい） */
#bg-mode-seg { grid-template-columns: max-content; margin-bottom: var(--space-3); }
/* ラジオの組はどれも、JS（balanceColumns）が入る列の数を決める（2026-09-25、利用者の指摘「不必要に改行しない」。
   2列の決め打ちだと、幅に余裕があっても比率が2＋2＋1、トラックリストが2＋1に折れていた）。上の2列はJSが動くまでの既定 */
.seg.radio.measuring { display: flex; flex-wrap: wrap; }
#bg-cands[hidden], #bg-image-box[hidden], #bg-grad-box[hidden], #bg-grad-colors[hidden] { display: none; }
#bg-cands label { flex: 1 1 0; aspect-ratio: auto; height: 32px; }   /* 候補は欄の左右いっぱいに等分（利用者の指定） */
#bg-image-row { display: flex; align-items: center; gap: var(--space-3); }
#bg-image-thumb { width: 128px; aspect-ratio: 16 / 9; object-fit: cover; border: var(--line) solid var(--color-ink); background: var(--color-paper-2); }
#bg-image-thumb:not([src]) { visibility: hidden; }
#bg-image-row { flex-wrap: wrap; }
#bg-image-reset[hidden] { display: none; }
#bg-fit-seg, #bg-tile-seg, #bg-ink-seg { margin-top: var(--space-2); }
#bg-tile-seg[hidden], #bg-none-box[hidden] { display: none; }   /* 候補は4色まで。背景色の見本のように行いっぱいに広げると大きすぎる */
#bg-grad-box { display: grid; gap: var(--space-2); justify-items: start; margin-top: var(--space-2); }
#bg-grad-colors { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.grad-row { display: flex; align-items: center; gap: var(--space-3); }
#bg-grad-thumb { width: 128px; aspect-ratio: 16 / 9; border: var(--line) solid var(--color-ink); background: var(--color-paper-2); }
#bg-grad-thumb:not([src]) { visibility: hidden; }
.grad-chip { width: 32px; height: 28px; padding: 0; border: var(--line) solid var(--color-ink); background: none; cursor: pointer; }
.grad-chip::-webkit-color-swatch-wrapper { padding: 0; } .grad-chip::-webkit-color-swatch { border: 0; }
#bg-image-box { margin-top: var(--space-2); }   /* .btnのdisplayがhidden属性に勝つので明示する */
/* できあがりの見本（2026-09-25、利用者の案）。共有と同じ描き方で端末の中で作って見せる。送らない */
#preview-img { display: block; width: 100%; height: auto; border: var(--line) solid var(--color-ink); }
#preview-img[hidden] { display: none; }
/* 白い字の透過は暗い市松の上に出す */
#preview-img.is-clear.is-dark, #output-img.is-clear.is-dark { background: repeating-conic-gradient(#2a2d33 0 25%, #1b1d22 0 50%) 0 0 / 16px 16px !important; }
#preview-img.is-clear, #output-img.is-clear { background: repeating-conic-gradient(var(--color-paper-3) 0 25%, var(--color-paper) 0 50%) 0 0 / 16px 16px; }
/* スマホは「曲を探す・共有／保存・読み込み」の2×2。PCは「曲を探す」が無いので共有だけ1行いっぱい */
@media (min-width: 60rem) { #preview-btn { grid-column: 1 / -1; } }   /* PCは「曲を探す」が無いので「できあがりを見る」を1行いっぱい */
/* **取り消せない操作は、いちばん押すものから遠く・最後・小さく**（OS 9のSpecialメニューの末尾にEmpty Trash… があるのと同じ）。
   以前は「曲を探す」の真上に「全部クリア」があり、利用者から「ヒヤヒヤする」と言われた */
/* 最後の行: 左に「みんなのグリッド」の2段、右に「トラックを全て外す」。幅が足りなければボタンが次の行の右端に落ちる */
.grid-foot { grid-column: 1 / -1; display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end;   /* 説明の行はボタンの下辺にそろえる（利用者の指定） */
  gap: var(--space-2); margin-top: var(--space-2); }
/* **「トラックを全て外す」は説明文の下、右端に単独で置く**（2026-09-21、利用者の指定）。
   ボタンの列から縦にも横にも離れるので、続けて押したときに当たりにくい */
.clear-row { display: flex; justify-content: flex-end; margin-top: var(--space-3); }
/* **「トラックを全て外す」は線で区切って離す**（2026-09-25）。赤くはしない: 危ないボタンがいちばん目立ってしまい、
   HIGでも色は付けない（確かめるのは確認窓と「元に戻す」の役目）。利用者と決めた */
.clear-row { border-top: var(--line) solid var(--color-rule); padding-top: var(--space-3); }

/* ---------- options ---------- */
.opts { display: grid; gap: var(--space-4); }
/* **グループボックス**（2026-09-25、Mac OS 8のHIG）。1段目は彫り込んだ2pxの線（濃い線の右下に明るい線）、題は枠の上辺に重ねて左に置く。
   内側の余白はHIGの数字（上12px・左右と下10px）に題の高さを足したもの。2段目（.gbox-sub）は1pxの線で、決め方ごとの補足の設定を囲む */
.gbox { position: relative; display: grid; gap: var(--space-4); margin-top: 0.7em; padding: calc(12px + 0.4em) 10px 10px;
  border: 1px solid var(--color-bevel); box-shadow: inset 1px 1px 0 var(--color-hl), 1px 1px 0 var(--color-hl); }
.gbox-title { position: absolute; top: -0.7em; left: 8px; padding: 0 4px; background: var(--color-paper); color: var(--color-ink);
  font-family: var(--font-display); font-size: var(--dot-size); line-height: 1.4; }
/* 畳む三角（Mac OS 8のHIGのdisclosure triangle）。右向きが閉じ、下向きが開き */
.disclose { display: flex; align-items: center; gap: var(--space-2); width: 100%; min-width: 0; padding: var(--space-1) 0; border: 0; background: none;
  color: var(--color-ink); font-family: var(--font-display); font-size: var(--dot-size); text-align: left; cursor: pointer; }
.disclose .tri { flex: none; width: 0; height: 0; border-left: 7px solid var(--color-ink); border-top: 5px solid transparent; border-bottom: 5px solid transparent; }
.disclose[aria-expanded="true"] .tri { transform: rotate(90deg); }
.disclose:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-gap); }
.disclose-head { display: grid; gap: var(--space-1); }
/* 畳んでいるときの今の値。長いので見出しの下に折り返して出す（右に1行だとスマホで半分以上切れる。2026-09-25、利用者の選択） */
.disclose-sum { margin: 0; padding-left: calc(7px + var(--space-2)); color: var(--color-muted); font-size: var(--text-sm); line-height: 1.6; }
.disclose[aria-expanded="true"] + .disclose-sum { display: none; }
.disclose-body { display: grid; gap: var(--space-4); }
.disclose-body[hidden] { display: none; }
.gbox-sub { display: grid; gap: var(--space-2); margin-top: var(--space-2); padding: 10px; border: 1px solid var(--color-bevel); }
.custom-size { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); }
.custom-size label { display: inline-flex; align-items: center; gap: var(--space-1); font-family: var(--font-display); }
.input.num { width: 4.5rem; padding: var(--space-1) var(--space-2); font-variant-numeric: tabular-nums; -moz-appearance: textfield; appearance: textfield; }
.input.num::-webkit-inner-spin-button, .input.num::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
/* 横 × 縦の小さな矢印（OS 9のLittle Arrows、2026-09-23）。欄の右に上下2つ。押し続けると続けて増減する。
   ブラウザの数値欄の上下ボタンは端末ごとに見た目が違うので消して、こちらで描く */
.stepper-wrap { display: inline-flex; align-items: stretch; gap: 2px; }
.stepper { display: inline-grid; grid-template-rows: 1fr 1fr; width: 17px; border: var(--line) solid var(--color-ink); background: var(--color-paper); }
.stepper button {
  position: relative; padding: 0; border: 0; background: none; color: var(--color-ink); cursor: pointer;
  touch-action: none; -webkit-tap-highlight-color: transparent;
}
.stepper button + button { border-top: var(--line) solid var(--color-ink); }
.stepper button::before {
  content: ""; position: absolute; inset: 0; margin: auto; width: calc(7 * var(--u)); height: calc(4 * var(--u));
  background: currentColor; -webkit-mask: var(--arrow-up) center / 100% 100% no-repeat; mask: var(--arrow-up) center / 100% 100% no-repeat;
}
.stepper button[data-step="-1"]::before { transform: rotate(180deg); }
.stepper button:active, .stepper button.is-held { background: var(--color-ink); color: var(--color-paper); }
@media (pointer: coarse) { .stepper { width: 28px; } }
/* 「表示」のチェックは横に流し込む。入らないものは次の行へ回る（縦に1つずつ積むと場所を食う） */
.check-row { display: flex; flex-wrap: wrap; column-gap: var(--space-4); row-gap: 0; }
.check { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); cursor: pointer; min-height: 28px; }
/* 文字だけ0.042em下げる。**ドット字（M+ 12）は漢字のインクが行の中心より0.042em上**に出る（2026-09-24。
   フォントのascent 880 / descent 229と漢字の字面 -144〜880から出した値。12pxで0.5px）。
   DotGothic16のときは逆に0.056em下に出ていて、0.056em上げていた。
   Plexのときは逆に上に出るので0.15em下げていたが、ドット字に替えてもそのままだったため箱より3px下がり、
   「チェックボックスとのラインが崩れている」と利用者に言われた。**pxで1pxと書くとスマホでずれる**
   （画素比2〜3で字が端末の画素2〜3.5画素ぶん上に出た。emなら0.5画素以内）。狭い画面の13pxは下の上書きを見る */
.check > span { position: relative; top: 0.042em; }
.check input {
  appearance: none; width: 18px; height: 18px; margin: 0; flex: none;
  border: var(--line) solid var(--color-ink); background: var(--color-paper);
  box-shadow: inset 2px 2px 0 var(--color-paper-3);
  display: grid; place-items: center; cursor: pointer;
}
/* 入れたら**白い箱に黒いチェック印**（OS 9の作法。印は18×13のドット絵をSVGの型抜きで描く。
   斜線をCSSで回して描くと滑らかすぎてサイトの見た目から浮く）。黒く塗って白い四角を置く形は、小さいと
   「枠が太くなった」ようにしか見えず、入ったかどうか分かりにくい（利用者の指摘、2026-09-16） */
/* **印は箱から右上へはみ出す**（OS 9の実物と同じ。箱の中に収めると窮屈で、印が小さく見える） */
.check input { position: relative; overflow: visible; }
.check input:checked::after, .check input:checked::before {
  content: ""; position: absolute; left: 0; top: 0; width: 18px; height: 13px; background: var(--color-ink);   /* 右上の先端が枠の角に乗る（OS 9と同じ向き） */
  -webkit-mask: var(--check-mask) 0 0 / 18px 13px no-repeat; mask: var(--check-mask) 0 0 / 18px 13px no-repeat;
}
/* 印の影（同じ形を1px右下にずらして敷く。::beforeなので印の下に来る）。**枠の線には掛けない**:
   影は枠の内側だけで切る（線の上に乗ると、線が灰色ににじんで見える。利用者の指摘） */
.check input:checked::before { left: 1px; top: 1px; background: var(--color-paper-3);   /* 箱の内側の影（insetのpaper-3）と同じ薄さ */
  clip-path: inset(0 5px 0 0); }   /* 枠の内寸（14×14）で切る。線に掛けない。印そのものは枠の外へ出てよい */
/* **枠の外へ出た先端にも同じ1px右下の影**。labelの擬似要素で同じ形をもう1枚敷き、**枠より外側だけ**残す
   （枠の線に掛からない）。印はlabelのx=2（枠の内側）から始まるので、影はx=3、枠の外はx≥18 → 局所15pxで切る */
.check { position: relative; }
.check:has(> input:checked)::before {
  content: ""; position: absolute; left: 3px; top: calc(50% - 7px); width: 18px; height: 13px;   /* 縦は2px下（枠の外は下に落ちる余地があるぶん、影が下へ伸びて見える） */
  background: var(--color-paper-3); pointer-events: none;
  -webkit-mask: var(--check-mask) 0 0 / 18px 13px no-repeat; mask: var(--check-mask) 0 0 / 18px 13px no-repeat;
  clip-path: inset(0 1px 0 16px);   /* 枠の外に出た先端の影だけ（右端も1px切って出過ぎを抑える） */
}
.check input:disabled { opacity: .5; cursor: not-allowed; }
.swatches { display: flex; gap: var(--space-2); margin-top: var(--space-2); }   /* 見出しとの間は選択枠（外側5px）の分だけ広めに */
.swatches label { position: relative; flex: 1 1 0; min-width: 0; aspect-ratio: 1; }   /* 見本は間隔8pxのまま行幅いっぱいに等分（PCの列幅では32px）。右に空きが残らない。
   折り返さない（2026-09-25。枠で囲んで幅が減ったとき、8個目だけ次の行に落ちて行幅いっぱいの大きな四角になっていた） */
/* 「配色パレットを選ぶ…」。**ほかのボタンと同じ影付きの .btnにする**（2026-09-18）。見出しの横に細い枠だけで
   置いていたときは、見出しの飾りに見えて押せると気付かれにくかった。名前の「…」はOS 9の決まりで「窓が開く」の印 */
.pal-open { width: 100%; margin-top: var(--space-3); font-size: var(--text-sm); }
/* 指で触る画面のスクロールバー（自前）。**スマホのブラウザはスクロールバーを「触れる部品」として
   扱わない**（指の入力はつまみの上にあっても中身のスクロールに回る）ので、ブラウザ任せだと掴めない。
   溝の位置に自分の要素を重ね、指の操作を自分で受ける。見た目は ::-webkit-scrollbarと同じ規則 */
.tsb { display: none; }
@media (pointer: coarse) {
  /* **バーが要るときだけ幅を空ける**（`layout()` が付け外しする）。いつも空けると、
     スクロールしない並びでマスが狭くなる */
  /* **溝のぶんは、出るときだけ空ける**（2026-09-16に「常に空ける」から戻した。スクロールしない
     並びで右に24pxの空きが残るのは無駄、という指摘）。出し入れで枠が痙攣した件は、
     `attachTouchScrollbar` の判定側で止める（8pxの遊び＋2コマ続けて同じ判定のときだけ切り替える） */
  .tsb-host.tsb-on { padding-right: 24px; }
  .tsb-host::-webkit-scrollbar { width: 0; height: 0; }    /* ブラウザのものは出さない（二重になる） */
  .tsb { display: block; position: absolute; width: 24px; background: var(--color-paper-3);
    box-shadow: inset 1px 0 0 var(--color-bar-dark), inset -1px 0 0 var(--color-bar-dark); touch-action: none; }
  .tsb[hidden] { display: none; }
  /* 見た目は ::-webkit-scrollbar-thumb:verticalと同じ絵（枠はborder-image、縞は真ん中の1枚） */
  .tsb-thumb { position: absolute; left: 0; width: 100%; min-height: 44px; box-sizing: border-box;
    background-color: var(--color-bar);
    border: calc(2 * var(--u)) solid transparent; border-image: var(--sb-frame) 2 / calc(2 * var(--u));
    background-image: var(--sb-grip-v); background-size: calc(9 * var(--u)) calc(16 * var(--u));
    background-position: center; background-repeat: no-repeat; }
  .tsb-thumb:active { background-color: var(--color-rule-2); }
  /* 上下の矢印（2026-09-24、スマホで出ていないと指摘）。見た目は ::-webkit-scrollbar-buttonと同じ作りで、
     24pxに合わせて三角だけ大きくする。溝が短くてつまみと両方は入らないときは出さない（.tsb-short） */
  .tsb-btn { position: absolute; left: 0; width: 100%; height: 24px; box-sizing: border-box;
    background-color: var(--color-bar);
    background-repeat: no-repeat; background-position: center; background-size: 13px 13px;
    border: 1px solid var(--color-bar-dark);
    box-shadow: inset 1px 1px 0 var(--color-hl), inset -1px -1px 0 var(--color-bar-dark); }
  .tsb-btn:active, .tsb-btn[data-held] { background-color: var(--color-rule-2); }
  .tsb-up { top: 0;
    background-image: var(--sb-arrow-up); }
  .tsb-down { bottom: 0;
    background-image: var(--sb-arrow-down); }
  .tsb.tsb-short .tsb-btn { display: none; }
}
/* 送信中の窓。**上りが細いと80秒かかる**ことがあり、何も出ていないと「固まった」と思って
   押し直される。押し直されると同じ1MBがもう一度流れるので、進み具合を見せる意味がある */
.up-bar { height: 18px; border: var(--line) solid var(--color-ink); background: var(--color-paper-2);
  box-shadow: inset 0 1px 0 rgb(0 0 0 / 0.16); overflow: hidden; }
.up-fill { height: 100%; width: 0; background: var(--color-mustard);
  border-right: var(--line) solid var(--color-ink); transition: width .2s linear; }
.up-fill[data-done="1"] { border-right: none; }
.up-pct { font-family: var(--font-outlier); font-size: var(--text-sm); margin: var(--space-1) 0 0;
  font-variant-numeric: tabular-nums; }
.up-note { color: var(--color-muted); font-size: var(--text-sm); margin: var(--space-1) 0 0; }
/* 待っているあいだに作者の曲を1つ出す（サーバー代のおねがいと同じ趣旨） */
.up-promo { margin-top: var(--space-3); border: var(--line) solid var(--color-ink);
  background: var(--color-paper-2); padding: var(--space-2) var(--space-3); }
.up-promo .lbl { font-family: var(--font-outlier); font-size: var(--text-xs); color: var(--color-muted);
  display: block; letter-spacing: 0.04em; }
.up-promo a { color: var(--color-ink); text-decoration: underline; text-decoration-thickness: 2px;
  text-underline-offset: 3px; }
/* パレットの一覧（モーダルの中）。1行が1組の8色 */
.pal-lanes { display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-3) 0; }
/* 1行に入りきらない幅（スマホ）では折り返す。名前・8色・ボタンの順に段が増える */
.pal-lane { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); padding: var(--space-2); border: var(--line) solid var(--color-rule); background: var(--color-paper-2); }
.pal-lane[data-active="true"] { border-color: var(--color-ink); box-shadow: 3px 3px 0 var(--color-shadow); }
.pal-lane .pal-name { flex: 1 1 auto; min-width: 5em; font-size: var(--text-sm); }
.pal-lane .pal-btns { display: flex; gap: var(--space-2); margin-left: auto; }
@media (max-width: 560px) {
  .pal-lane .pal-name { flex-basis: 100%; }   /* 名前を1段目に独立させ、色とボタンを下の段へ送る */
  .pal-lane .pal-chips { flex: 1 1 auto; }
  .pal-lane .pal-btns { flex-basis: 100%; margin-left: 0; }
}
.pal-lane .pal-chips { display: flex; gap: 2px; }
.pal-lane .pal-chips span, .pal-lane .pal-chips button { width: 22px; height: 22px; border: var(--line) solid var(--color-ink); padding: 0; }
/* 自作の組の色は押して直せる。編集中のものは黒い輪で示す */
.pal-lane .pal-chips button { cursor: pointer; }
.pal-lane .pal-chips button[aria-pressed="true"] { outline: 3px solid var(--color-ink); outline-offset: 2px; }
.pal-lane .btn { padding: 2px var(--space-2); font-size: var(--text-sm); }
.pal-actions { display: flex; gap: var(--space-2); }
/* 地と文字が近すぎる組の注意書き（1行いっぱいに出す） */
.pal-warn { flex-basis: 100%; margin: 2px 0 0; font-size: 12px; color: var(--color-muted); }
/* 8色の受け渡し（コピー・貼り付け） */
.pal-io { margin-top: var(--space-3); display: flex; flex-direction: column; gap: var(--space-1); }
.pal-io-row { display: flex; gap: var(--space-2); }
.pal-io-row .input { flex: 1 1 auto; min-width: 0; }
#pal-file-btn { align-self: flex-start; }
.swatches input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.swatches span { display: block; width: 100%; height: 100%; border: var(--line) solid var(--color-ink); background: var(--sw); }
.swatches input:checked + span { outline: 3px solid var(--color-ink); outline-offset: 2px; }
.swatches input:focus-visible + span { outline: var(--focus-ring); outline-offset: var(--focus-gap); }
.custom-color { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-3); font-family: var(--font-display); font-size: var(--text-sm); }
.custom-color button { width: 28px; height: 28px; padding: 0; border: var(--line) solid var(--color-ink); background: var(--sw, var(--color-paper)); cursor: pointer; }
.custom-color button.is-on { outline: 3px solid var(--color-ink); outline-offset: 2px; }
.custom-color button:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-gap); }
/* 選んである見本にキーボードで焦点が来ても、選択の太枠（3px）を細い焦点の輪で上書きしない。
   上書きすると選択の印がそこだけ細くなる（2026-10-12、色だけに頼らない表示の点検で） */
.swatches input:checked:focus-visible + span,
.custom-color button.is-on:focus-visible { outline: 3px solid var(--color-ink); outline-offset: 2px; }
/* カスタムカラーの色相・彩度・明度スライダー。つまみの位置が色で分かるよう、溝に色の帯を敷く */
.hsv { display: grid; gap: var(--space-1); margin-top: var(--space-2); padding: var(--space-2) var(--space-2) var(--space-1); border: var(--line) solid var(--color-ink); background: var(--color-paper-2); }
.hsv[hidden] { display: none; }   /* display: gridがhidden属性のdisplay: noneに勝ってしまうため明示 */
.hsv label { display: flex; justify-content: space-between; font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink-2); }
/* 色相・彩度・明度の溝も、余白やマスの間隔と同じ「凹み」に見せる。中身が色の帯なだけで作りは同じ
   （枠は濃いグレー、左上に影、右下に白）。つまみは共通のものをそのまま使う */
.hsv input[type="range"]::-webkit-slider-runnable-track {
  height: 12px; box-sizing: border-box; background: var(--track);
  border: 1px solid var(--color-bar-dark);
  box-shadow: inset 0 1px 0 rgb(0 0 0 / 0.16);
}
.hsv input[type="range"]::-webkit-slider-thumb { margin-top: calc(5px - 9 * var(--u)); }   /* (12 - 18) / 2から1px上へ。帯の凹みの中で少し浮いて見せる */
.hsv .hex { font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink-2); text-align: right; font-variant-numeric: tabular-nums; }
/* つまみと溝はMac OS 9の作り。スクロールバー（上）と同じ言葉づかいにそろえる。
   **溝は凹み**（左上が濃く右下が白）、**つまみは出っぱり**（左上が白く右下が濃い）＋ 真ん中に握りの縞 */
/* **つまみの操作はこちらで全部やる**ので、ブラウザ独自のジェスチャ（スクロール・値の追従）は切る。
   `touch-action: pan-y` を残していたため、後から書いた `none` が同じ詳細度に負けて効いておらず、
   Androidでは溝を叩くと値が飛んだままだった（実機で3回報告があった） */
input[type="range"] { appearance: none; width: 100%; height: 22px; background: transparent; margin: 0; cursor: default; touch-action: none; }
input[type="range"]::-webkit-slider-runnable-track {
  /* **影は上辺だけ**。右下に白を入れると、枠線と合わさって二重線に見える（スマホの実機で顕著だった） */
  height: 7px; box-sizing: border-box; background: var(--color-paper-2);
  border: 1px solid var(--color-bar-dark);
  box-shadow: inset 0 1px 0 rgb(0 0 0 / 0.16);
}
input[type="range"]::-webkit-slider-thumb {
  appearance: none; width: calc(19 * var(--u)); height: calc(18 * var(--u)); margin-top: calc(3px - 9 * var(--u)); box-sizing: border-box;   /* 1マス = --u（上の :root） */
  background-color: var(--color-bar);
  /* **線は全部1枚のドット絵（--range-thumb）に描く**（2026-09-22）。Inside Macintoshの図と同じ作り。
     以前は外枠・面取り・握りの縞を13枚の背景に分けて重ねていたが、背景は1枚ずつ端末の画素へ
     丸められるので、画素密度が整数でない端末（実機は2.625倍）や**指で拡大したとき**に1枚だけずれ、
     下辺の下に地色の帯・右辺の外に白い筋・縞の太さの不ぞろいが出た（実機で報告）。
     1枚の絵なら中の線は同じ丸めで描かれ、互いにずれない。面は透かしてあり、地の色は
     background-colorが出す（掴んでいる間の色 `.is-grabbed` もそのまま効く）。
     絵の中身: 外枠は四辺とも濃いグレー、面取りは上・左が白で下・右が中間のグレー
     （外枠と同じ濃さにすると影が二重に見える）、右上と左下の角の1pxは暗い白、
     握りの縞は白線（上端1pxだけ明るい白）の右隣に1px下へずらした濃いグレー線を3組 */
  background-image: var(--range-thumb);
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

/* 掴んでいる間の色は `.is-grabbed`（下）で出す。**`:active` は使わない**:
   `<label for>` を長押しすると、押されたのが見出しでも `input` が `:active` になり、
   つまみが押されたように見えてしまう（実機で報告） */
/* Firefox（::-webkit-* が効かないので同じ見た目を別に指定する） */
input[type="range"]::-moz-range-track { height: 5px; background: var(--color-paper-2); border: 1px solid var(--color-bar-dark); }
input[type="range"]::-moz-range-thumb { width: 17px; height: 16px; border-radius: 0; background: var(--color-bar); border: 1px solid var(--color-bar-dark); }
input[type="range"]:focus-visible { outline-offset: 4px; }
/* **指やマウスで掴んだときは焦点の輪を出さない**。受け皿（.range-pad）に入力を移したので、
   `el.focus()` が「部品を触っていない所からの焦点当て」になり、Chromeがキーボード操作とみなして
   `:focus-visible` が当たるようになった（つまみの外に輪が出る。実機で報告）。
   矢印キーを押したら外して、キーボードのときはこれまでどおり輪を出す */
input[type="range"].no-ring:focus-visible { outline: none; }
/* **つまみの操作はすべて受け皿（.range-pad）で受ける**。`input` 自身は `pointer-events: none` で
   入力をいっさい受け取らないので、ブラウザ既定の「押した位置へ値が飛ぶ」が**起こりようがない**。
   CSSの `touch-action` や `preventDefault` に頼る形は、Androidの実機で何度直しても
   すり抜けが残った（2026-09-15、3回の報告）。キーボード（矢印キー）は今までどおり効く */
.range-wrap { position: relative; display: block; }
.range-wrap input[type="range"] { pointer-events: none; }
/* **縦のスクロールは通す**（`pan-y`。2026-09-25、利用者の指摘「マスの間隔のあたりでスクロールが空振りする」）。
   以前は `none` で、溝の上に指が乗っただけでもページが動かなかった。つまみの上で触れたときだけJSが既定の動きを止める */
.range-pad { position: absolute; inset: -6px 0; touch-action: pan-y; cursor: default; }   /* 上下6pxは指の遊び（受け皿22px → 34px。隣の色のスライダーの受け皿とは重ならない） */
/* 掴んでいる間の色。`:active` は入力を受け取らなくなったので効かない */
input[type="range"].is-grabbed::-webkit-slider-thumb { background-color: var(--color-thumb-held); }
input[type="range"].is-grabbed::-moz-range-thumb { background-color: var(--color-thumb-held); }
output { font-variant-numeric: tabular-nums; }

/* ---------- output ---------- */
/* できあがりは**それ自体を窓にする**（2026-09-16）。共有したあと、そのままオプションを
   いじって作り直したいときに、画像のぶんだけ延々とスクロールすることになっていた（スマホで報告）。
   窓にすればタイトルバーの「−」で畳めて、下のオプションがすぐ出る */
.pane-output { margin-top: var(--space-4); }
.pane-output > .pane-body { display: grid; gap: var(--space-3); }
/* できあがりの窓（2026-09-25）。見本は押すと大きく見られる。共有したあとのURLなどは #share-doneにまとめて出す */
.out-shot { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }
.out-shot img { display: block; width: 100%; height: auto; border: var(--line) solid var(--color-ink); }
.out-shot[hidden], #share-done[hidden] { display: none; }
.out-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.out-actions #share-btn { flex: 1 1 auto; }
#share-done { display: grid; gap: var(--space-3); }
.pane-output .listed .check { min-height: 0; }
.output[hidden] { display: none; }
/* 比率はJSが入れる（別オリジンから読むので、読み終わるまで高さが0だと画面が飛ぶ）。
   **幅は欄いっぱい**（`width: 100%`）。`width: auto` だと、置き換え要素はgridの伸ばす指定が
   効かないので左に寄り、しかも高さの頭打ちに当たった比率のときだけ右に余りが出る
   （「左に寄っている・左右ぴったりでない」と報告があった）。
   **高さの頭打ちは外した**。画面の高さ（`dvh` / `svh`）で切ると、切られた比率だけ幅が縮んで
   また左右に余りが出る。縦長の並びは縦に長く出るが、できあがりを確かめる場所なのでそれでよい
   （`dvh` はスクロールでアドレスバーが隠れると値が変わり、画像ごと伸び縮みして
     下の欄がずれる、という別の問題もあった） */
.output img { display: block; width: 100%; height: auto;
  border: var(--line) solid var(--color-ink); box-shadow: var(--shadow); }
.share-url { display: grid; gap: var(--space-1); }
.share-url .lbl { font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink-2); }
.share-url .input { font-family: ui-monospace, monospace; font-size: var(--text-sm); }
/* ボタンに添えるドット絵（12×12。1ドット = 1pxのときだけ潰れない） */
.btn .ic { flex: none; width: 12px; height: 12px; fill: currentColor; }
/* 画像のまとまり。URLのまとまりと区切り線で分ける（HIGのseparator line） */
.share-img { display: grid; grid-template-columns: max-content; gap: var(--space-1); padding-top: var(--space-3); border-top: var(--line) solid var(--color-rule); }
.share-img .lbl { font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink-2); }
.share-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* 自分の共有をあとから外す・消す（2026-09-26）。取り消せない「消す」はURLの列から離して下の段に置く */
.share-own { display: flex; flex-wrap: wrap; gap: var(--space-2); padding-top: var(--space-3); border-top: var(--line) solid var(--color-rule); }   /* 外す・消すも画像のまとまりと区切る */ .share-own .btn[hidden] { display: none; }   /* .btnのdisplayがhidden属性に勝つので打ち消す */
/* **スマホでは共有のあとのボタンを2列の格子に**（2026-09-26、利用者の指摘）。流し込みだと「3つ・1つ」と不ぞろいに折れた。
   グリッド窓のボタン（2×2）と同じ考え。外す・消すの段も2列。隠れているボタンは数えない */
@media (max-width: 59.99rem) {
  .share-actions, .share-own, .share-img { display: grid; grid-template-columns: 1fr 1fr; }
  .share-actions:has(#native-share-btn:not([hidden])) #open-share { grid-column: 1 / -1; }   /* 3つのときは「開く」を横いっぱいに */
  .share-img .lbl { grid-column: 1 / -1; }
  .share-actions > [hidden] { display: none; }
}
.support { display: grid; gap: var(--space-1); padding-top: var(--space-3); border-top: var(--line) solid var(--color-rule); font-size: var(--text-sm); color: var(--color-ink-2); }
.support .album { font-family: var(--font-display); color: var(--color-ink); }
/* 作者の顔（ボタンの絵88×31の左の四角27×27（2〜28ドット目）を2倍で切り抜く）と一人称の一言 */
.maker { display: flex; align-items: center; gap: var(--space-2); }
.maker-face { flex: none; width: 54px; height: 54px; background-size: 176px 62px; background-position: -4px -4px; image-rendering: pixelated; }
/* 広告枠。いまは中身が自分の音楽（つなぎ）で、AdSenseの審査が通ったら中身とラベルを差し替える */
/* bodyがflexなので、幅を絞るだけだと左に寄る。align-selfで中央に置く */
/* 見た目は「本体から切り離した、隅の小箱」（2026-09-25）。灰色の平らな見出しの帯に、左は題名、右は小さな札。
   **警告に見せない**: 帯に縞を引かない（窓に見せない）・閉じるボタンを置かない・赤や黄を使わない・影を付けない
   （AdSenseは広告をOSの画面や通知に見せかける配置を禁じている）。広告を入れたら題名は「広告」か「スポンサーリンク」だけ */
.promo { width: min(960px, 100%); align-self: center; margin-top: var(--space-4); border: var(--line) solid var(--color-ink); background: var(--color-paper); display: grid; }
.promo-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); min-height: 28px; padding: 0 var(--space-2); background: var(--color-bar); border-bottom: var(--line) solid var(--color-ink); }
.promo-tag { font-family: var(--font-outlier); font-size: var(--text-xs); color: var(--color-muted); border: 1px solid var(--color-rule); padding: 0 var(--space-1); background: var(--color-paper); }
.promo-body { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3); padding: var(--space-3); }
.promo-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); }   /* ボタンの右に曲のリンク2行。幅が足りなければ下に回り込む */
.promo-text { display: grid; gap: var(--space-2); min-width: 0; }
.promo-btn { flex: none; display: block; line-height: 0; }   /* 枠の左下（文の後ろ）に置く */
/* 2倍で見せる。**1ドット = 2 × --u**（端末の画素の整数倍。176pxと書くと2.625倍の端末でドットの太さがばらつく） */
.promo-btn img { width: calc(var(--u) * 176); height: calc(var(--u) * 62); image-rendering: pixelated; }
/* 「値段は自由です」がどのリンクの話かを示す、左のボタンを指す矢印（2026-09-27、利用者の希望）。8×7のドット絵を2倍で */
.point-left { display: inline-block; vertical-align: middle; width: calc(var(--u) * 16); height: calc(var(--u) * 14); margin-right: var(--space-1);
  position: relative; top: -0.08em; background: var(--color-ink);
  -webkit-mask: var(--arrow-left) 0 0 / 100% 100% no-repeat; mask: var(--arrow-left) 0 0 / 100% 100% no-repeat; }
.promo-row.stacked .point-left { transform: rotate(90deg); }   /* 文がボタンの下に回り込んだら上を指す（JSが .stackedを付ける） */
/* 広告が入る場所。PCは468×60、スマホは320×100（どちらもAdSenseの固定の大きさ） */
.ad-slot { width: 468px; height: 60px; max-width: 100%; margin-inline: auto; background: var(--color-paper-2); display: grid; place-items: center; font-size: var(--text-sm); color: var(--color-muted); }
@media not all and (min-width: 60rem) { .ad-slot { width: 320px; height: 100px; } }
/* 広告を囲む立体の枠（2026-09-27、利用者の希望）。見本はteacup「掲示板自動作成システム」（1998）の下の広告で、
   `<table border="5">` をブラウザが描いた枠を画素で実測して写した: 外に5ドットの出っぱり・2ドットの隙間・
   内に1ドットのへこみ・1ドットの余白。**枠は中身の大きさに縮んで、ぴったり囲む**（width: fit-content）。
   そのため広告は固定の大きさ（468×60・320×100）にすること。レスポンシブ広告は幅が決まらず、枠が行いっぱいに伸びる。
   光はOS 9の面取りと同じく左上から。明るい辺・暗い辺は実測のグレー（168・84）に近い --color-bevel / --color-muted、
   暗い地では面取りの並び（明るい白 ＞ 外枠）に合わせて --color-hl / --color-bar-dark。線の太さは --uの倍数（ドットをにじませない） */
.ad-frame { --adf-lt: var(--color-bevel); --adf-dk: var(--color-muted);
  width: fit-content; max-width: 100%; margin-inline: auto; line-height: 0;
  padding: calc(2 * var(--u)); border: calc(5 * var(--u)) solid; border-color: var(--adf-lt) var(--adf-dk) var(--adf-dk) var(--adf-lt); }
:root[data-ground="dark"] .ad-frame { --adf-lt: var(--color-hl); --adf-dk: var(--color-bar-dark); }
.ad-frame > * { box-sizing: content-box; margin: 0; padding: var(--u);   /* 中身（.ad-slot）の468×60を削らない */
  border: var(--u) solid; border-color: var(--adf-dk) var(--adf-lt) var(--adf-lt) var(--adf-dk); }
.ad-slot img { width: 100%; height: 100%; image-rendering: pixelated; }
/* PayPalの広告（468×60のGIF 1枚）。スマホでも同じ絵を幅に合わせて縮める（.ad-slotの320×100は使わない） */
.promo-banner > .ad-slot { width: min(468px, calc(100vw - 48px)); height: auto; aspect-ratio: 468 / 60; }   /* 自前の広告の絵（PayPal）。1倍の絵を画素密度の端数でにじませない */
/* 広告が来なかったとき（AdSenseがinsにdata-ad-status="unfilled" を付ける）は欄ごと隠す。空の枠と見出しだけ残さない */
.promo:has(ins.adsbygoogle[data-ad-status="unfilled"]) { display: none; }
.promo .lbl { font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink); }
.promo p { margin: 0; font-size: var(--text-sm); color: var(--color-ink-2); }
.promo .album { font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink); }
/* サーバー代の進み具合の棒（2026-09-26）。棒はアップロードの .up-bar / .up-fillをそのまま使う。数字はpaintFundが入れる */
.fund { display: grid; gap: var(--space-1); width: 100%; }
.fund[hidden] { display: none; }
.fund-head, .fund-bar { max-width: 28rem; }   /* 棒は短めに。下の文は横いっぱいに流す */
.fund-head { display: flex; justify-content: space-between; gap: var(--space-2); }
.fund-lbl { font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-ink); }
.fund-pct { font-family: var(--font-outlier); font-size: var(--text-sm); color: var(--color-ink); font-variant-numeric: tabular-nums; }
.fund-bar { height: 14px; }
.fund-note { font-size: var(--text-sm); color: var(--color-ink-2); }
.promo .elsewhere { font-size: var(--text-sm); color: var(--color-ink-2); }   /* 主役はBandcamp。ほかは従として小さく並べる */
.spec { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); font-size: var(--text-sm); color: var(--color-ink-2); margin: 0; }   /* 幅があれば横に並び、足りなければ折り返す */
.spec > div { display: grid; gap: var(--space-1); flex: 1 1 8rem; align-content: start; }   /* 各項目は8remを基準に、並んだ行の幅を均等に分け合う */
/* align-content: start … 同じ行の項目は背の高いもの（2行に折れた「余白」）に合わせて伸びる。上詰めにしないと伸びたぶんが
   見出しと値の行に割り振られ、短い項目の値だけ下にずれる（2026-09-24、字を16pxのドット字にして折れやすくなり、利用者が「段ズレ」と報告） */
.spec dt { font-family: var(--font-display); color: var(--color-muted); }
.spec dd { margin: 0; font-variant-numeric: tabular-nums; word-break: keep-all; }   /* 空白の位置でだけ折る（「左／右」と字の間で割れた。数の前後はJSがNBSPにするので、「/」の後でだけ折れる） */

footer { padding: var(--space-3) var(--page-inline); border-top: var(--line) solid var(--color-ink); font-family: var(--font-display); font-size: var(--text-sm); color: var(--color-muted); display: flex; gap: var(--space-4); flex-wrap: wrap; }
#view-switch { order: 1; margin-left: auto; }   /* 右下に置く（ほかの項目より後ろ・右寄せ） */
footer a { color: var(--color-ink); text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 3px; }
/* 下のページのリンクは語の途中で折らない（2026-09-27。「使い方の動画」を足したらスマホで「更｜新情報」と割れた） */
.foot-page { white-space: nowrap; }

/* **操作部品の字はドット字（JFドットM+ 12）の12pxにそろえる**（2026-09-24、利用者が見本で決めた。PCもスマホも同じ）。
   M+ 12は12pxの升目で作られた字なので、ほかの大きさ（--text-smの12.8pxなど）ではにじむ。12pxか24pxだけを使う。
   それまでのDotGothic16（PC 16px・スマホ13px）は英字のAが山形・C/O/Rの角が欠けていて、上辺が波打って見えた。
   題名バー・見出し・入力欄の名前・チェックとラジオ・折りたたみの見出し・フッターが対象。
   **曲名・説明文・メッセージ・書き出し画像はPlexのまま**（長い文はドット字だと読みづらい。書き出しはPlexの字幅で
   render.pyと割り付けを合わせてある）。個々の規則を直さずここで上書きするのは、対象を1か所で見渡すため */
.pane-title h2, legend, .field label, .field legend, .sub-title, .seg span, .seg.radio span, .check > span,
.layouts > label, .custom-color, .custom-size label, .hsv label, .hsv .hex, .lang-switch, .spec dt, .spec dd,
footer, .editor-head, .list-head, .bar-status, .pal-open, .share-url .lbl, .promo .lbl, .support .album, .promo .album,
h1, h2, h3, .wordmark small, .list-del, .list-add, .empty strong,
.btn, .popup select, span.label, h2[id$="-title"] {
  font-family: var(--font-display); font-size: var(--dot-size); letter-spacing: 0;
}
/* **PCだけ15pxの「TM Dot PC」に大きくする**（2026-09-24、利用者が見本で決めた）。12pxはPCの画面では小さかった。
   中身は2つのフォントの組: 日本語はGalmuri14（15pxの升目のゴシック）を2目下げたもの、英数字は東雲ゴシック14を
   size-adjustで14pxに縮めたもの（どちらも1目 = 1px。fonts/split/fonts.css、scripts/build_fonts.pyのSOURCES）。
   東雲14だけだと はね・はらいが明朝寄りに見え、Galmuri14だけだと英字がプロポーショナルで背が高く浮いた。
   縦の位置は描いた点を数えて合わせた（経緯はscripts/make_pc_dot_font.py）。スマホはM+ 12の12pxのまま */
@media (min-width: 60rem) {
  :root { --font-display: "TM Dot PC", "JF Dot MPlus12", "IBM Plex Sans JP", sans-serif; --dot-size: 15px; }
}
/* 入力欄の名前でも、長い説明を兼ねているものは本文の字に戻す */
label[for="bc-url"] { font-family: var(--font-body); font-size: var(--text-sm); }
@media not all and (min-width: 60rem) {
  label[for="bc-url"] { font-size: var(--text-sm); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; }
}