/* uilib-proto.css — レビュー用プロトタイプの共通スタイル（jai-uilib.css の原型。DESIGN.md 準拠） */

/* ========== design tokens ========== */
:root {
  --background: #fafafa; --foreground: #18181b;
  --card: #ffffff; --card-foreground: #18181b;
  --popover: #ffffff; --popover-foreground: #18181b;
  --primary: #18181b; --primary-foreground: #fafafa;
  --secondary: #f4f4f5; --secondary-foreground: #18181b;
  --muted: #f4f4f5; --muted-foreground: #71717a;
  --accent: #f4f4f5; --accent-foreground: #18181b;
  /* status（08-12 確定・§23「Riso 2 色主義」）: 正常 = 藍 / 注意・失敗 = 朱の 2 色で全状態を回す。
     --danger  = tint 面・文字・icon 用（明るい朱）
     --danger-solid = 面をベタ塗りするとき用（白文字が乗る濃度）。--destructive はこれの別名 */
  --success: #1b3fd8; --success-foreground: #ffffff;
  --danger: #ff3b1f; --danger-foreground: #ffffff;
  --danger-solid: #e01a00;
  --destructive: var(--danger-solid); --destructive-foreground: #ffffff;
  --border: #e4e4e7; --input: #e4e4e7;
  --brand: #6366f1; --brand-foreground: #ffffff;
  --ai: #E71F19; --ai-foreground: #ffffff;
  --ring: var(--brand); --radius: 0.375rem;
  --tab-neutral-fill: color-mix(in srgb, var(--foreground) 12%, var(--card));
  --chart-1: #6366f1; --chart-2: #22c55e; --chart-3: #f59e0b; --chart-4: #ef4444; --chart-5: #8b5cf6;
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Hiragino Sans", "Noto Sans JP", sans-serif;
  --font-mono: "Roboto Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-head: "Archivo", var(--font-sans);
  --dur-fast: 120ms; --dur-base: 180ms; --ease: cubic-bezier(0.2, 0, 0, 1);
  --select-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}
.dark {
  --background: #09090b; --foreground: #fafafa;
  --card: #131316; --card-foreground: #fafafa;
  --popover: #131316; --popover-foreground: #fafafa;
  --primary: #fafafa; --primary-foreground: #18181b;
  --secondary: #27272a; --secondary-foreground: #fafafa;
  --muted: #1f1f23; --muted-foreground: #a1a1aa;
  --accent: #27272a; --accent-foreground: #fafafa;
  --success: #7b93ff; --danger: #ff6a4d; --danger-solid: #c8240b;
  --border: #27272a; --input: #3f3f46;
  --brand: #818cf8; --brand-foreground: #18181b;
  --ai: #E71F19; --ai-foreground: #ffffff;
  --chart-1: #818cf8;
  --select-caret: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a1a1aa' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
}

/* ========== base ========== */
* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-font-smoothing: antialiased; }
body { font-family: var(--font-sans); background: var(--background); color: var(--foreground); font-size: 14px; line-height: 1.6; transition: background var(--dur-base) var(--ease), color var(--dur-base) var(--ease); }
/* スクロールバー（07-29 追加・DESIGN.md §3.7）: uilib.css を読む全ページ・全スクロール領域に一括適用。
   OS 既定の太いスクロールバーが uilib の細身デザインの中で唯一浮く要素だったための包括対応。
   個別 comp 側で `.jgt-table-scroll` 等を複製している場合も、同じ見た目（値は uilib token）に揃う。 */
* { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--border); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--muted-foreground); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
*::-webkit-scrollbar-corner { background: transparent; }
.ui-num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
svg.ic { width: 15px; height: 15px; stroke: currentColor; stroke-width: 1.8; fill: none; stroke-linecap: round; stroke-linejoin: round; flex: none; }
/* fill icon（§23・逸脱の最上位表現）: 面 = currentColor / glyph = 載っている面の色（--knock）で抜く。
   glyph を白固定にすると dark の tint 面で浮くため、抜き色は必ず面から取る。
   ベタ塗りの部品（.ui-alert--error 等）は自分の面色を --knock に宣言する */
svg.ic .sld { fill: currentColor; stroke: none; }
svg.ic .knk { stroke: var(--knock, var(--card)); fill: none; stroke-width: 2.1; stroke-linecap: round; }
svg.ic .knkf { fill: var(--knock, var(--card)); stroke: none; }
/* 選択で fill する icon（v1.27.0・2026-08-28 ユーザー指示「少なくとも selected の時は fill type」）:
   §23.3 の `.sld` / `.knk`（面 + 抜き）と**同じ語彙を「選択」に開く**もの。逸脱（エラー）は常時 fill
   だが、選択は状態が往復するので **`-sel` 付きは既定が線画で、選択された時だけ面になる**。
   これは DESIGN.md が icon のみの 2 択 segmented について書いていた「active を fill で示す」の実体
   （それまで文章だけがあり、実装は白 pill しか差が無かった）。
   **抜き色は面から取る**（`--knock`）—— track 形の selected 面は light = --card / dark = --secondary
   なので、白固定にすると dark で浮く（§23.3 と同じ理由）。
   線画の側（未選択）に太さ・色の差を作らないこと —— 選択の主張は「面になる」だけで足り、
   線を太くすると未選択が「薄い」ではなく「壊れている」ように見える。 */
svg.ic .sld-sel { fill: none; }
svg.ic .knk-sel { stroke: currentColor; }
.ui-segment > button.active svg.ic .sld-sel,
.view-toggle > button.active svg.ic .sld-sel { fill: currentColor; stroke: currentColor; }
.ui-segment > button.active svg.ic .knk-sel,
.view-toggle > button.active svg.ic .knk-sel { stroke: var(--knock, var(--card)); }
.ui-segment > button.active svg.ic .knkf-sel,
.view-toggle > button.active svg.ic .knkf-sel { fill: var(--knock, var(--card)); stroke: none; }
/* selected 面の色を --knock として宣言する（抜きの色はここから取る）。has-slide では面を描くのは
   indicator（.slide-ind--seg）だが色は同じなので、宣言はボタン側 1 箇所で足りる */
.ui-segment > button.active, .view-toggle > button.active { --knock: var(--card); }
.dark .ui-segment > button.active, .dark .view-toggle > button.active { --knock: var(--secondary); }
a { color: inherit; }

/* ========== page 骨格 ==========
   main コンテンツ幅はシェルヘッダー（.ui-shell-inner）と同じ 1200px に固定する。
   旧 --narrow(760) / --wide(1400) modifier はタブ列と幅が揃わず廃止（08-04 ユーザー判断） */
.ui-page { max-width: 1200px; margin: 0 auto; padding: 40px 32px 96px; }

.ui-page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 24px; margin-bottom: 40px; }
.ui-page-header .title-block h1 { font-family: var(--font-head); font-weight: 700; font-size: 21px; letter-spacing: 0.12em; text-transform: uppercase; display: flex; align-items: center; gap: 12px; }
.ui-page-header .ver { font-family: var(--font-mono); font-size: 11px; font-weight: 400; letter-spacing: 0; color: var(--brand); border: 1px solid color-mix(in srgb, var(--brand) 35%, transparent); border-radius: 999px; padding: 1px 9px; }
.ui-page-header .desc { font-size: 12.5px; color: var(--muted-foreground); margin-top: 8px; max-width: 560px; }
.ui-page-header .actions { display: flex; gap: 8px; flex: none; }

/* app header — 全 page 共通の最上部（1段目 = jai-info チップ（state の最上位: 現在地とバージョン）/
   2段目 = タイトルブロック（左）+ actions（右）。action の並びはユーティリティ → secondary → primary 最右） */
.ui-app-header { display: flex; flex-direction: column; gap: 16px; margin-bottom: 40px; }
.ui-app-header .info-slot { display: flex; }
.ui-app-header .head-main { display: flex; justify-content: space-between; gap: 24px; align-items: flex-start; }

/* ========== app shell（uilib demo の MPA 化・07-29 追加）==========
   複数ページ共通の最上部シェル（info comp v5 + トップタブ）。sticky + condensed（jai-info の
   bindSticky が .ji-condensed を付与）。旧 index.html の .shell-header/.shell-inner の重複定義を
   ここへ集約する（AGENTS.md「部品が足りなければ先に uilib へ追加」）。詳細は DESIGN.md §4 */
.ui-shell-header { position: sticky; top: 0; z-index: 40; background: var(--background); transition: box-shadow var(--dur-base) var(--ease); }
.ui-shell-inner { padding: 22px 32px 0; max-width: 1200px; margin: 0 auto; width: 100%; transition: padding var(--dur-base) var(--ease); }
.ui-shell-header.ji-condensed { box-shadow: 0 4px 16px rgba(0,0,0,.06); }
.ui-shell-header.ji-condensed .ui-shell-inner { padding-top: 10px; }
.ui-shell-header.ji-condensed .ui-tabs { margin-top: 8px; }
.ui-shell-header .ui-tabs { margin-top: 18px; transition: margin var(--dur-base) var(--ease); }
/* ネスト layout のサブタブ帯（components/_layout・layouts/_layout 等が使う） */
.ui-subnav { max-width: 1200px; margin: 0 auto; width: 100%; padding: 20px 32px 0; }

/* ========== info comp v5 プロトタイプ（full 形態 — DESIGN.md §16）==========
   タイトル行そのものが info comp: [icon(=navPages menu)] TITLE [version chip(=dialog)] + actions（右）/ description（下）。
   uilibProto.infoHeader(el, props) が描画する */
/* v1.23.0（08-26 → 同日再修正）: 3行構造（main/actions・desc/meta・tabs）は当初 .ui-ih 自身の
   grid（列固定）で組んでいたが、列幅が「内容」を見ずに actions 列を確保するため、md 段
   （例: container 859px）で actions 側が幅を取り h1 が早々に ellipsis してしまい
   DESIGN.md §22「狭幅段の譲る順序（actions の行落ち → … → タイトル ellipsis は最後）」に
   反していた。flex wrap に戻す — .ih-main を flex:1 1 320px（basis 320px）にすることで
   「タイトル側に最低 320px 残らないなら actions が先に折り返す」内容幅ベースの行落ちになる
   （xs 段は container が 320px 未満でも flex-shrink で縮んで収まる）。.ih-row は素の flex
   コンテナに戻し、.ih-meta-row も同様（display:contents は撤去 — grid-area 前提の仕組みだったため）。 */
.ui-ih { display: block; }
.ui-ih .ih-row { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 16px; }
/* flex-basis は max-content（icon + .ih-tb の実幅）— basis を固定 px にすると
   icon/sub の幅ぶんタイトルが早々に ellipsis になる（859px 実測: basis 320 で h1 に 205px しか残らず
   「Marketing Dashboard」が切れた）。max-content なら「タイトルが丸ごと収まらない → actions が先に
   行落ち」が内容幅で決まり、規約（タイトル ellipsis は最後）どおりになる。min-width:0 で
   container がタイトルより狭いとき（xs）は単独行で shrink できる。 */
/* align-items は flex-start（旧: center）— .ih-tb は .ih-sub が2行目へ折れると自身の高さが
   h1 の1行ぶんより高くなる。center のままだと icon が「.ih-tb 全体（2行分)」の中央へ寄り、
   h1（1行目）との横並びがずれる（実測 10px 前後）。flex-start なら icon は常に .ih-tb の
   先頭（= h1 の行）に揃う（.ih-tb が1行のときも h1 の行高と icon 34px はほぼ同値なので無害）。 */
.ui-ih .ih-main { flex: 1 1 max-content; display: flex; align-items: flex-start; gap: 12px; min-width: 0; }
.ui-ih .ih-icon { width: 34px; height: 34px; border-radius: 50%; border: none; background: var(--foreground); color: var(--background); display: flex; align-items: center; justify-content: center; cursor: pointer; flex: none; transition: box-shadow var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease); }
.ui-ih .ih-icon:hover { opacity: .85; box-shadow: 0 0 0 3px color-mix(in srgb, var(--foreground) 12%, transparent); }
/* .ih-tb（title-block）: h1 + .ih-sub（+ .ih-menu）をまとめる wrap コンテナ。position:relative は
   .ih-menu（絶対配置）の基準として .ih-main から移した — .ih-tb 自身が h1/sub の折り返しを
   担うため、menu の位置決めもこの箱を基準にするのが自然（見た目の座標は従来と同じ: icon の右）。 */
.ui-ih .ih-tb { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; position: relative; }
/* h1 の flex-basis を max-content にすることで「h1 全文 + .ih-sub が同じ行に入らない →
   .ih-sub（後続 item）だけが次の行へ折れる」が内容幅で自然に決まる（幅の閾値を持たない）。
   折れた .ih-sub は .ih-tb の左端（= icon の右）に揃うので padding-left の細工は不要。 */
/* h1 は伸びない（grow 0）— grow させると余白を h1 が食い、後続の ver chip + ⌘J（.ih-sub）が
   行の右端へ押し出される（859px 実測・08-26 regression）。basis max-content + shrink 1 + min-width 0 で
   「全文が収まらないときだけ縮む（= sub は先に次行へ折れる）」を保つ。 */
.ui-ih h1 { flex: 0 1 max-content; min-width: 0; font-family: var(--font-head); font-weight: 700; font-size: 21px; letter-spacing: 0.12em; text-transform: uppercase; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ui-ih .ih-ver { font-family: var(--font-mono); font-size: 11px; color: var(--brand); border: 1px solid color-mix(in srgb, var(--brand) 35%, transparent); background: transparent; border-radius: 999px; padding: 1px 9px; cursor: pointer; flex: none; transition: background var(--dur-fast) var(--ease); }
.ui-ih .ih-ver:hover { background: color-mix(in srgb, var(--brand) 10%, transparent); }
.ui-ih .ih-menu { top: calc(100% + 6px); left: 0; min-width: 250px; max-height: min(70vh, 560px); overflow-y: auto; }
.ui-ih .ih-desc { font-size: 12.5px; color: var(--muted-foreground); max-width: 640px; }
/* ⓘ（compact 段専用・v1.23.0）: sm 以下（container < 680px）で .ih-desc の代わりに ver チップの
   左へ出す説明アイコン + popover。基本形は非表示（≥680px は従来どおり .ih-desc をそのまま出す）。
   表示切替は @container ui (width < 680px) 側（下方）で行う。 */
.ui-ih .ih-info { display: none; }
.ui-ih .ih-info-pop { display: none; position: absolute; top: calc(100% + 6px); left: 0; z-index: 20; min-width: 220px; max-width: 320px; background: var(--popover); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: 0 8px 24px rgba(0,0,0,.08); padding: 10px 12px; font-size: 12.5px; line-height: 1.5; color: var(--muted-foreground); }
.ui-ih .ih-info-pop.open { display: block; }
.ui-ih .ih-actions { flex: 0 1 auto; margin-left: auto; display: flex; align-items: center; justify-content: flex-end; gap: 8px; min-width: 0; flex-wrap: wrap; }
/* 08-26 フィードバック③: .ih-sub（ver チップ + ⌘J）が既定の div（display:block）のままだと
   中の inline 要素が baseline 揃えになり、ver chip の中心が ⌘J ボタンより 2〜3px 下にズレる
   （実測）。inline-flex + align-items:center で中心を揃える。flex:0 0 auto は自身の内容幅を
   保ち（h1 側にだけ max-content の縮小圧をかけない）、.ih-tb の wrap で「入らなければ次の行」に
   自然に落ちる（同日再修正: 幅の閾値による強制改行トリックは撤去）。 */
.ui-ih .ih-sub { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px; position: relative; }

/* version 単体チップ（最小 variant — 一覧カード内・省スペース用） */
.ui-ver-chip { font-family: var(--font-mono); font-size: 11px; color: var(--brand); border: 1px solid color-mix(in srgb, var(--brand) 35%, transparent); background: var(--card); border-radius: 999px; padding: 2px 10px; cursor: pointer; transition: background var(--dur-fast) var(--ease); }
.ui-ver-chip:hover { background: color-mix(in srgb, var(--brand) 10%, transparent); }

/* jai-info チップ（min 形態のモック — 省スペース・iframe 埋め込み用）。
   構成: [thumb = 現在地 state] [ページ名] [version チップ → info dialog] | [menu → navPages（管理下 page への遷移 + studio リンク）]
   遷移は未来の動作 = action なので menu は右端（Z の法則） */
.ui-info-chip { display: inline-flex; align-items: center; gap: 8px; background: var(--card); border: 1px solid var(--border); border-radius: 999px; padding: 4px 8px 4px 6px; font-size: 12px; transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease); }
.ui-info-chip:hover { border-color: color-mix(in srgb, var(--foreground) 22%, var(--border)); box-shadow: 0 2px 8px rgba(0,0,0,.05); }
.ui-info-chip .thumb { width: 22px; height: 22px; border-radius: 50%; background: var(--foreground); color: var(--background); display: flex; align-items: center; justify-content: center; flex: none; }
.ui-info-chip .thumb svg { width: 12px; height: 12px; }
.ui-info-chip b { font-weight: 500; white-space: nowrap; }
.ui-info-chip .v { font-family: var(--font-mono); font-size: 11px; color: var(--brand); border: none; background: transparent; cursor: pointer; padding: 1px 6px; border-radius: 999px; transition: background var(--dur-fast) var(--ease); }
.ui-info-chip .v:hover { background: color-mix(in srgb, var(--brand) 10%, transparent); }
.ui-info-chip .chip-sep { width: 1px; height: 14px; background: var(--border); }
.ui-info-chip .nav-btn { border: none; background: transparent; cursor: pointer; color: var(--muted-foreground); display: flex; padding: 3px; border-radius: 50%; transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease); }
.ui-info-chip .nav-btn:hover { color: var(--foreground); background: var(--accent); }
.ui-menu .menu-head { padding: 6px 10px 2px; font-family: var(--font-head); font-weight: 500; font-size: 10px; letter-spacing: .2em; text-transform: uppercase; color: var(--muted-foreground); }
.ui-menu-item.current { font-weight: 600; }
.ui-menu-item.current::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--brand); flex: none; }

.ui-crumbs { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted-foreground); margin-bottom: 20px; }
.ui-crumbs a { text-decoration: none; transition: color var(--dur-fast) var(--ease); display: inline-flex; align-items: center; gap: 4px; }
.ui-crumbs a:hover { color: var(--brand); }
.ui-crumbs .cur { color: var(--foreground); }

.ui-page-foot { display: flex; justify-content: space-between; align-items: center; margin-top: 14px; }
.ui-page-foot .count { font-family: var(--font-mono); font-size: 11px; color: var(--muted-foreground); }

/* ========== buttons ========== */
.ui-btn { appearance: none; border: 1px solid transparent; cursor: pointer; font-family: var(--font-sans); font-size: 13px; font-weight: 500; padding: 7px 15px; border-radius: var(--radius); line-height: 1.4; display: inline-flex; align-items: center; gap: 7px; transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease); text-decoration: none; }
.ui-btn:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.ui-btn:disabled { opacity: .45; cursor: not-allowed; }
/* 命名の正は BEM 二重ハイフン（v1.21.0・DESIGN.md §24.4）。単ハイフンは v1.1.0 由来の旧名として維持 */
.ui-btn-primary, .ui-btn--primary { background: var(--primary); color: var(--primary-foreground); }
.ui-btn-primary:hover:not(:disabled), .ui-btn--primary:hover:not(:disabled) { opacity: .85; }
.ui-btn-secondary, .ui-btn--secondary { background: var(--secondary); color: var(--secondary-foreground); border-color: var(--border); }
.ui-btn-secondary:hover:not(:disabled), .ui-btn--secondary:hover:not(:disabled) { background: var(--accent); }
.ui-btn-ghost, .ui-btn--ghost { background: transparent; color: var(--foreground); }
.ui-btn-ghost:hover:not(:disabled), .ui-btn--ghost:hover:not(:disabled) { background: var(--accent); }
.ui-btn-outline, .ui-btn--outline { background: transparent; color: var(--foreground); border-color: var(--input); }
.ui-btn-outline:hover:not(:disabled), .ui-btn--outline:hover:not(:disabled) { background: var(--accent); }
.ui-btn-destructive, .ui-btn--destructive { background: var(--destructive); color: var(--destructive-foreground); }
.ui-btn-destructive:hover:not(:disabled), .ui-btn--destructive:hover:not(:disabled) { opacity: .85; }
.ui-btn-sm, .ui-btn--sm { padding: 5px 11px; font-size: 12px; }
.ui-btn-icon, .ui-btn--icon { padding: 7px; }

/* ========== FormItem（label + control の複合部品 — 最重要の基盤思想）==========
   - label 配置: top / left / auto（auto = wrapper 幅で container query 判定。560px 以上で left）
   - label 横に info icon（ui-tip で説明を出せる）
   - 閲覧（value）と編集（input）を同一構造に内包し、data-mode="view|edit" で切替える。
     value と input は同一メトリクス（layout shift ゼロ原則）なので、詳細・新規・編集を1つの comp で賄う */
.ui-form { container-type: inline-size; }
/* 縦リズムは --form-item-gap で form 単位に調整できる（モーダル等の密なフォーム向け。既定 22px）。
   消費側が .ui-form-item の margin を直接上書きするのを防ぐための逃がし口 */
.ui-form-item { margin-bottom: var(--form-item-gap, 22px); }
.ui-form-label { display: flex; align-items: center; gap: 6px; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted-foreground); font-family: var(--font-head); font-weight: 500; margin-bottom: 7px; }
.ui-form-label .req { color: var(--danger); }
.ui-info-ic { display: inline-flex; color: var(--muted-foreground); cursor: help; opacity: .7; transition: opacity var(--dur-fast) var(--ease); }
.ui-info-ic:hover { opacity: 1; }
.ui-info-ic svg { width: 12px; height: 12px; }

/* left 配置: label は固定幅カラム（--form-label-w）。control 1行目と光学的に揃える */
.ui-form[data-labels="left"] .ui-form-item { display: grid; grid-template-columns: var(--form-label-w, 160px) 1fr; gap: 0 16px; align-items: start; }
.ui-form[data-labels="left"] .ui-form-label { margin-bottom: 0; padding-top: 12px; }
@container (min-width: 560px) {
  .ui-form[data-labels="auto"] .ui-form-item { display: grid; grid-template-columns: var(--form-label-w, 160px) 1fr; gap: 0 16px; align-items: start; }
  .ui-form[data-labels="auto"] .ui-form-label { margin-bottom: 0; padding-top: 12px; }
}

/* view / edit 切替（:has で value を持つ item のみ input を隠す — 新規作成 form は value なしでそのまま動く） */
.ui-form-value { font-size: 13px; line-height: 20px; padding: 8px 12px; border: 1px solid transparent; border-radius: var(--radius); min-height: 38px; display: flex; align-items: center; gap: 8px; transition: border-color var(--dur-base) var(--ease); min-width: 0; position: relative; }
.ui-form-item:not([data-mode="edit"]):has(.ui-form-value) .ui-form-input { display: none; }
.ui-form-item[data-mode="edit"] .ui-form-value { display: none; }
/* hover 鉛筆（.ro-edit-btn）の確保幅は「アイコン実寸 + 数px」だけに留める（DESIGN.md §13 と
   同ページの .ui-inline-edit 原則: padding-right でアイコン分を常に確保する）。以前は
   justify-content: space-between で val とボタンを両端に引き離しており、短い値ほど
   不自然に広い空白ができていた（08-21 ユーザー指摘）。:has() でボタンを持つ行だけに
   絞って余白確保するため、鉛筆のない .ui-form-value（META カード等）には影響しない。 */
.ui-form-value:has(.ro-edit-btn) { padding-right: 30px; }
.ui-form-value .ro-edit-btn { position: absolute; right: 8px; top: 11px; }
/* .val（読み取り値）は flex item の既定 min-width:auto のせいでスラッグ等の長い値が
   コンテンツ固有幅ぶん膨らみ、狭い container で枠外へはみ出す（280px 実測・ユーザー指摘）。
   overflow-wrap で受ける（コンテンツ自体・レイアウトは変えない overflow 安全策 — §25.1b の範囲内） */
.ui-form-value .val { min-width: 0; overflow-wrap: anywhere; }
/* view⇄edit 統合の textarea は auto-resize 前提（min-height を解除し閲覧時と同じ高さに） */
.ui-form-control textarea.ui-form-input { resize: none; overflow: hidden; min-height: 0; }

/* ========== form ========== */
.field { margin-bottom: 22px; }
.field > label { display: block; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted-foreground); margin-bottom: 7px; font-family: var(--font-head); font-weight: 500; }

/* ---- helper / エラー（08-03: FormItem にも適用。DESIGN.md §13）----
   エラーを出しうるフィールドは .help を「常設」し、文言と色だけ差し替える。
   エラー時に .help を生やす実装は必ず layout shift を起こす（fleet 新規セッションの判例）。
   文言が不要なら空の <p class="help"></p> を置けば1行分だけ確保される（:empty の zwsp）。 */
.field .help, .ui-form-control .help { font-size: 11.5px; line-height: 16px; color: var(--muted-foreground); margin-top: 6px; }
.field .help:empty::before, .ui-form-control .help:empty::before { content: '\200b'; } /* 空でも1行確保（shift ゼロ） */
/* invalid は「.field/.ui-form-item に class」でも「control に aria-invalid」でも成立させる
   （React 等で state から aria-invalid だけ出す実装が自然に効くように）。
   枠線の色は control 定義（.ui-input …）の後に置く必要があるので下方に分離してある */
.field.invalid .help, .ui-form-item.invalid .help,
.field:has([aria-invalid="true"]) .help, .ui-form-control:has([aria-invalid="true"]) .help { color: var(--danger); }
/* 「入力は正しいが危険な選択」（例: bypassPermissions）は invalid ではなく helper の tone で警告する */
.help[data-tone="danger"] { color: var(--danger); }

.ui-input, .ui-textarea, .ui-select {
  /* line-height 整数 px 固定 + display:block（inline-block のベースラインギャップ排除）
     — read-only 表示（.ro-val）との高さ完全一致のため（layout shift ゼロ原則） */
  display: block; width: 100%; font-family: var(--font-sans); font-size: 13px; line-height: 20px; color: var(--foreground);
  background: var(--card); border: 1px solid var(--input); border-radius: var(--radius); padding: 8px 12px;
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.ui-input:focus, .ui-textarea:focus, .ui-select:focus { outline: none; border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent); }
/* invalid の枠線（08-03）。**control 定義と :focus の後に置くこと**。
   `.ui-input:focus { border-color: var(--ring) }` と同specificity なので、前に置くと
   「入力中（= focus 中）はエラーでも枠が赤くならない」— エラーを見せたいまさにその瞬間に
   効かないという最悪の順序になる。focus 時は ring も destructive に差し替える */
.field.invalid .ui-input, .field.invalid .ui-textarea, .field.invalid .ui-select,
.ui-form-item.invalid .ui-input, .ui-form-item.invalid .ui-textarea, .ui-form-item.invalid .ui-select,
.ui-input[aria-invalid="true"], .ui-textarea[aria-invalid="true"], .ui-select[aria-invalid="true"] { border-color: var(--danger); }
.ui-input[aria-invalid="true"]:focus, .ui-textarea[aria-invalid="true"]:focus, .ui-select[aria-invalid="true"]:focus,
.field.invalid .ui-input:focus, .ui-form-item.invalid .ui-input:focus { border-color: var(--destructive); box-shadow: 0 0 0 3px color-mix(in srgb, var(--destructive) 18%, transparent); }
.ui-input::placeholder, .ui-textarea::placeholder { color: var(--muted-foreground); }
.ui-textarea { resize: vertical; min-height: 96px; }
.ui-input--mono { font-family: var(--font-mono); font-size: 12.5px; }

/* ========== size 体系（07-22 決定）==========
   全部品共通: 基準 = md。sm / lg を標準展開し、xs / xl は必要になった部品のみ追加する。
   コントロール高の目安: sm 30px / md 38px / lg 44px（整数 line-height 維持 = layout shift ゼロ原則と両立） */
.ui-btn-lg, .ui-btn--lg { padding: 10px 20px; font-size: 14px; }
.ui-input--sm, .ui-select--sm, .ui-textarea--sm { padding: 5px 10px; font-size: 12px; line-height: 18px; }
.ui-input--lg, .ui-select--lg, .ui-textarea--lg { padding: 10px 14px; font-size: 14px; line-height: 22px; }
.ui-select--sm { padding-right: 30px; background-position: right 9px center; background-size: 13px; }
.ui-select--lg { padding-right: 36px; }
.ui-badge--sm { font-size: 10px; padding: 1px 7px; }
.ui-badge--lg { font-size: 12px; padding: 3px 11px; }
.ui-chip--sm { font-size: 11px; padding: 1px 4px 1px 8px; }

/* ========== date / time 系 ========== */
input[type="date"].ui-input, input[type="datetime-local"].ui-input, input[type="time"].ui-input, input[type="month"].ui-input { font-family: var(--font-mono); font-size: 12.5px; width: auto; }
input::-webkit-calendar-picker-indicator { opacity: .55; cursor: pointer; }
.dark input::-webkit-calendar-picker-indicator { filter: invert(1); opacity: .7; }
.ui-daterange { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ui-daterange .sep { color: var(--muted-foreground); font-size: 12px; }

/* select は appearance を落として caret を自前描画（ネイティブ caret の右端張り付き防止。入力系と同じ right 11px に揃える） */
.ui-select { appearance: none; -webkit-appearance: none; padding-right: 34px; background-image: var(--select-caret); background-repeat: no-repeat; background-position: right 11px center; background-size: 14px; cursor: pointer; }
.ui-input:disabled, .ui-textarea:disabled, .ui-select:disabled { background-color: var(--muted); color: var(--muted-foreground); cursor: not-allowed; }

/* 先頭アイコン / 末尾アクション付き input（左 = state / 右 = action の原則） */
.input-wrap { position: relative; }
.input-wrap .lead-ic { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--muted-foreground); pointer-events: none; }
.input-wrap .ui-input--lead { padding-left: 34px; }
.input-wrap .tail-act { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); border: none; background: transparent; cursor: pointer; color: var(--muted-foreground); display: flex; align-items: center; padding: 4px; border-radius: var(--radius); transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease); }
.input-wrap .tail-act:hover { color: var(--foreground); background: var(--accent); }
.input-wrap .ui-input--tail { padding-right: 34px; }

/* number stepper */
.ui-stepper { display: flex; align-items: stretch; border: 1px solid var(--input); border-radius: var(--radius); background: var(--card); overflow: hidden; width: fit-content; }
.ui-stepper button { border: none; background: transparent; cursor: pointer; color: var(--muted-foreground); width: 32px; display: flex; align-items: center; justify-content: center; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-stepper button:hover { background: var(--accent); color: var(--foreground); }
.ui-stepper input { border: none; outline: none; background: transparent; width: 64px; text-align: center; font-family: var(--font-mono); font-size: 13px; line-height: 20px; padding: 8px 0; color: var(--foreground); border-left: 1px solid var(--border); border-right: 1px solid var(--border); }

/* range slider */
input[type="range"].ui-range { -webkit-appearance: none; appearance: none; width: 100%; height: 4px; border-radius: 999px; background: var(--input); outline: none; cursor: pointer; }
input[type="range"].ui-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; border-radius: 50%; background: var(--foreground); border: 2px solid var(--background); box-shadow: 0 0 0 1px var(--border); transition: transform var(--dur-fast) var(--ease); }
input[type="range"].ui-range::-webkit-slider-thumb:hover { transform: scale(1.12); }

/* dropzone（ファイル添付） */
.ui-dropzone { border: 1.5px dashed var(--input); border-radius: var(--radius); background: var(--card); padding: 26px 20px; text-align: center; cursor: pointer; color: var(--muted-foreground); font-size: 12.5px; transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-dropzone:hover, .ui-dropzone.drag { border-color: var(--brand); color: var(--foreground); background: color-mix(in srgb, var(--brand) 4%, var(--card)); }
.ui-dropzone b { font-weight: 500; }

/* cascader（Ant Design 準拠 — v1.5.0 で部品化: uilibProto.cascader(el, opts)。
   トリガー = comboSelect chip 形と共通の .ui-combo-chip / panel = 検索 + 階層カラム。
   検索入力中は .ui-ms-list（flat なフルパス一覧）に切り替わる */
.casc { position: relative; display: inline-flex; }
.casc-panel { position: absolute; top: calc(100% + 4px); left: 0; z-index: 30; display: none; flex-direction: column; background: var(--popover); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: 0 8px 24px rgba(0,0,0,.08); overflow: hidden; }
.casc.open .casc-panel { display: flex; animation: chip-in var(--dur-base) var(--ease); }
.casc.open .ui-combo-chip { border-color: color-mix(in srgb, var(--foreground) 25%, var(--border)); }
.casc.open .ui-combo-chip .caret { transform: rotate(180deg); }
/* ghost トリガー（trigger:'ghost'）: パンくず等の素のテキスト風。枠/ピルなし・hover で薄い面のみ */
.casc-ghost { display: inline-flex; align-items: center; gap: 5px; border: none; background: transparent; padding: 2px 7px; border-radius: var(--radius); font-family: var(--font-sans); font-size: 12px; color: var(--muted-foreground); cursor: pointer; white-space: nowrap; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.casc-ghost:hover { background: var(--accent); }
.casc-ghost:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.casc-ghost .lbl { display: inline-flex; align-items: center; gap: 6px; }
.casc-ghost .lbl b { color: var(--foreground); font-weight: 500; }
.casc-ghost .caret { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex: none; transition: transform var(--dur-fast) var(--ease); }
.casc.open .casc-ghost .caret { transform: rotate(180deg); }
/* カラム内の区切り線（{ divider: true } — root の「ALL」と配下ディレクトリ群の区切り等） */
.casc-sep { height: 1px; background: var(--border); margin: 4px 2px; }
.casc-cols { display: flex; }
.casc-col { min-width: 168px; max-height: 224px; overflow-y: auto; padding: 4px; }
.casc-col + .casc-col { border-left: 1px solid var(--border); }
.casc-item { display: flex; align-items: center; gap: 8px; padding: 7px 10px; border-radius: calc(var(--radius) - 2px); font-size: 13px; cursor: pointer; white-space: nowrap; }
.casc-item .lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.casc-item .hint { font-size: 11px; color: var(--muted-foreground); flex: none; }
.casc-item:hover { background: var(--accent); }
.casc-item.active { background: var(--secondary); font-weight: 500; }
.casc-item.leaf-selected .lbl { font-weight: 600; }
.casc-item svg { color: var(--muted-foreground); }
.casc-flat { min-width: 260px; }

input[type="checkbox"].ui-check, input[type="radio"].ui-radio { accent-color: var(--foreground); width: 15px; height: 15px; cursor: pointer; }
.choice { display: flex; align-items: flex-start; gap: 10px; padding: 10px 0; cursor: pointer; }
.choice b { font-size: 13px; font-weight: 500; display: block; }
.choice span { font-size: 11.5px; color: var(--muted-foreground); display: block; }

.ui-switch { position: relative; display: inline-block; width: 34px; height: 20px; flex: none; }
.ui-switch input { opacity: 0; width: 0; height: 0; }
.ui-switch .knob { position: absolute; inset: 0; background: var(--input); border-radius: 999px; cursor: pointer; transition: background var(--dur-base) var(--ease); }
.ui-switch .knob::before { content: ""; position: absolute; width: 14px; height: 14px; left: 3px; top: 3px; border-radius: 50%; background: var(--card); transition: transform var(--dur-base) var(--ease); }
.ui-switch input:checked + .knob { background: var(--foreground); }
.ui-switch input:checked + .knob::before { transform: translateX(14px); }

/* ========== sortable toggle list（drag handle + トグル付き縦リスト）==========
   表示項目のカスタマイズ UI の標準形（看板ボードのセクション / カード項目設定 等が典型用途）。
   行 = [drag handle（muted・cursor:grab）] [任意の dot/label] [右端 .ui-switch（黒 fill = on）]。
   ドラッグ中の行は半透明 + 影、drop 位置はプレースホルダー線。行 hover は muted 背景。
   動きは transform/opacity のみ。機能 comp（grid-table kanban 等）は本仕様を自前 CSS に複製して従う */
.ui-sort-list { display: flex; flex-direction: column; }
.ui-sort-item { display: flex; align-items: center; gap: 8px; padding: 7px 8px; border-radius: calc(var(--radius) - 1px); transition: background var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease); }
.ui-sort-item:hover { background: color-mix(in srgb, var(--muted) 55%, var(--card)); }
.ui-sort-item.dragging { opacity: .45; box-shadow: 0 4px 16px rgba(0,0,0,.12); }
.ui-sort-handle { color: var(--muted-foreground); cursor: grab; display: flex; flex: none; }
.ui-sort-handle svg { width: 15px; height: 15px; }
.ui-sort-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.ui-sort-label { flex: 1; font-size: 13px; color: var(--foreground); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-sort-placeholder { border: 1.5px dashed var(--muted-foreground); border-radius: calc(var(--radius) - 1px); height: 36px; margin: 2px 0; }

/* chip */
.ui-chip { display: inline-flex; align-items: center; gap: 5px; background: var(--secondary); border: 1px solid var(--border); color: var(--secondary-foreground); border-radius: 999px; padding: 2px 6px 2px 10px; font-size: 12px; animation: chip-in var(--dur-base) var(--ease); }
@keyframes chip-in { from { opacity: 0; transform: scale(.92); } }
.ui-chip button { border: none; background: transparent; cursor: pointer; color: var(--muted-foreground); display: flex; padding: 2px; border-radius: 50%; transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease); }
.ui-chip button:hover { color: var(--foreground); background: var(--accent); }

/* read-only ⇄ edit（シームレス: layout shift ゼロを厳守 —
   .ro-val と入力側は padding / border 幅 / font-size / line-height を完全一致させる。
   複数行は textarea を auto-resize（JS）して閲覧時と同じ高さにする） */
.ro-form .field { position: relative; }
.ro-form .ro-val { font-size: 13px; line-height: 20px; padding: 8px 12px; border: 1px solid transparent; border-radius: var(--radius); min-height: 38px; display: flex; align-items: center; justify-content: space-between; gap: 8px; transition: border-color var(--dur-base) var(--ease); }
.ro-form textarea.ro-input { resize: none; overflow: hidden; min-height: 0; }
.ro-form .field.editing .ro-val { display: none; }
.ro-form .field .ro-input { display: none; }
.ro-form .field.editing .ro-input { display: block; }
/* edit ボタンは行高 20px 内に収める（はみ出すと read-only 側だけ 1px 太り layout shift になる） */
.ro-edit-btn { opacity: 0; border: none; background: transparent; cursor: pointer; color: var(--muted-foreground); display: flex; align-items: center; height: 20px; padding: 0 2px; border-radius: var(--radius); transition: opacity var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ro-edit-btn svg { width: 14px; height: 14px; }
.ro-val:hover .ro-edit-btn, .ui-form-value:hover .ro-edit-btn { opacity: 1; }
.ro-edit-btn:hover { color: var(--foreground); }

/* ========== inline edit（フォーム外の1要素 readonly トグル方式）==========
   見出し・カードタイトル・table セルなど、FormItem の外で「クリックしたら編集できる」を実現する標準形。
   <input readonly> を常時 DOM に置き、readonly 属性の付け外しだけで view/edit を切り替える
   （要素の生成/破棄が発生しないため layout shift ゼロが原理的に保証される）。
   padding / font-size / line-height は .ui-input と完全一致させ、border-color の transparent⇄var(--input)
   切り替えだけで見た目を変える（= シームレス原則の核）。フォーム文脈の FormItem 2 要素方式（§13）とは
   別パターンとして共存する（FormItem = フォーム専用、.ui-inline-edit = 非フォーム文脈専用）。
   右側の鉛筆アイコン（.ui-inline-edit-ic）は「クリックすると編集できる」ヒントで、hover 時のみ
   フェードイン・readonly の間だけ表示（[readonly] 属性セレクタで判定するため JS 側の出し分け不要）。
   アイコン分の padding-right は readonly/editing 両状態で常に同じ値を確保する（= 状態切替で
   横幅メトリクスも変えない。行の高さだけでなく余白変化による疑似シフトも避ける）。 */
.ui-inline-edit-wrap { position: relative; display: block; }
.ui-inline-edit {
  display: block; width: 100%; font: inherit; font-size: 13px; line-height: 20px;
  padding: 8px 30px 8px 12px; border: 1px solid transparent; border-radius: var(--radius);
  background: transparent; color: var(--foreground); cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
.ui-inline-edit:hover:not(:focus) { background: var(--secondary); }
.ui-inline-edit:not([readonly]) {
  cursor: text; background: var(--card); border-color: var(--input);
}
.ui-inline-edit:not([readonly]):focus {
  outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}
/* sm サイズ（.ui-input--sm 相当のメトリクス。カードタイトル等の小さい見出し向け） */
.ui-inline-edit--sm { font-size: 12px; line-height: 18px; padding: 5px 26px 5px 10px; }
.ui-inline-edit-ic { position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  display: flex; color: var(--muted-foreground); opacity: 0; pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease); }
.ui-inline-edit-ic svg { width: 14px; height: 14px; }
.ui-inline-edit-wrap:hover .ui-inline-edit[readonly] ~ .ui-inline-edit-ic { opacity: 1; }

/* ========== toolbar ========== */
.ui-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.ui-toolbar .search { position: relative; flex: 1; max-width: 420px; }
.ui-toolbar .search svg { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--muted-foreground); }
.ui-toolbar .search input { width: 100%; font-family: var(--font-sans); font-size: 13px; color: var(--foreground); background: var(--card); border: 1px solid var(--input); border-radius: var(--radius); padding: 7px 12px 7px 34px; transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease); }
.ui-toolbar .search input:focus { outline: none; border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent); }
.ui-toolbar .spacer { flex: 1; }
.ui-toolbar .ui-select { width: auto; }

/* track 形（muted 面 + selected 白 pill・radius 999px）に統一（08-28・.ui-segment と同形） */
.view-toggle { display: inline-flex; border: 1px solid transparent; border-radius: 999px; overflow: hidden; background: color-mix(in srgb, var(--foreground) 7%, transparent); padding: 3px; gap: 2px; }
.dark .view-toggle { background: color-mix(in srgb, var(--foreground) 10%, transparent); }
.view-toggle button { border: none; background: transparent; cursor: pointer; border-radius: 999px; padding: 5px 9px; color: var(--muted-foreground); display: flex; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
/* selected = 白 pill（card fill + shadow。.ui-segment と統一）。TabGroup（data-slide="seg"）でスライド */
.view-toggle button.active { background: var(--card); color: var(--foreground); box-shadow: 0 1px 3px rgba(0,0,0,.1); }
.view-toggle.has-slide button.active { background: transparent; box-shadow: none; color: var(--foreground); }
.dark .view-toggle:not(.has-slide) button.active,
.dark .view-toggle .slide-ind--seg { background: var(--secondary); box-shadow: 0 1px 3px rgba(0,0,0,.35); }

.quick-filters { display: flex; gap: 6px; margin-bottom: 28px; }
.qf { border: 1px solid var(--border); background: var(--card); color: var(--muted-foreground); font-size: 12px; font-family: var(--font-sans); padding: 4px 12px; border-radius: 999px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; transition: all var(--dur-fast) var(--ease); }
.qf:hover { background: var(--accent); color: var(--foreground); }
/* selected chip は黒 fill（07-22 ユーザー決定 — brand の淡色 fill から変更） */
.qf.active { border-color: var(--foreground); color: var(--background); background: var(--foreground); }
.qf .n { font-family: var(--font-mono); font-size: 10.5px; }

/* ========== KPI ========== */
.ui-stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; margin-bottom: 44px; }
.ui-stat { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 18px 20px; }
.ui-stat .k { font-family: var(--font-head); font-weight: 500; font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted-foreground); display: flex; justify-content: space-between; align-items: baseline; }
.ui-stat .v { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 26px; font-weight: 500; margin-top: 6px; }
.ui-stat .v small { font-size: 14px; font-weight: 400; }
.ui-stat .d { font-family: var(--font-mono); font-size: 11px; margin-top: 2px; }
.ui-stat .d.up { color: var(--success); } .ui-stat .d.down { color: var(--danger); } .ui-stat .d.flat { color: var(--muted-foreground); }

/* ========== section ========== */
.ui-section { margin-bottom: 56px; }
.ui-section-label { font-family: var(--font-head); font-weight: 500; font-size: 12px; letter-spacing: 0.26em; text-transform: uppercase; color: var(--muted-foreground); border-bottom: 1px solid var(--border); padding-bottom: 10px; margin-bottom: 22px; display: flex; justify-content: space-between; align-items: baseline; }
.ui-section-label .more { font-family: var(--font-sans); font-size: 12px; letter-spacing: 0.02em; text-transform: none; color: var(--muted-foreground); text-decoration: none; display: inline-flex; align-items: center; gap: 4px; transition: color var(--dur-fast) var(--ease); cursor: pointer; border: none; background: none; }
.ui-section-label .more:hover { color: var(--brand); }

/* ========== card ========== */
.ui-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 24px; }
.ui-card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.pg-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px; cursor: pointer; display: flex; flex-direction: column; gap: 12px; transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease); }
.pg-card:hover { border-color: color-mix(in srgb, var(--foreground) 22%, var(--border)); box-shadow: 0 4px 16px rgba(0,0,0,.05); }
.pg-card .top { display: flex; align-items: center; justify-content: space-between; }
.pg-card .cat { font-family: var(--font-head); font-weight: 500; font-size: 10px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--muted-foreground); border: 1px solid var(--border); border-radius: 999px; padding: 1px 8px; }
.pg-card .ver { font-family: var(--font-mono); font-size: 11px; color: var(--muted-foreground); }
.pg-card h3 { font-family: var(--font-head); font-weight: 600; font-size: 15px; letter-spacing: 0.1em; text-transform: uppercase; line-height: 1.4; }
.pg-card h3 .ja { display: block; font-family: var(--font-sans); font-weight: 400; font-size: 11.5px; letter-spacing: 0.02em; text-transform: none; color: var(--muted-foreground); margin-top: 4px; }
.pg-card .foot { display: flex; align-items: center; justify-content: space-between; margin-top: auto; padding-top: 12px; border-top: 1px solid var(--border); }
.pg-card .state { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--muted-foreground); }
.pg-card .state .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--success); }
.pg-card .state.stale .dot { background: var(--danger); }
.pg-card .open { color: var(--muted-foreground); display: flex; transition: color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease); }
.pg-card:hover .open { color: var(--foreground); transform: translateX(2px); }

/* ========== list rows（閲覧系・ゆったり） ========== */
.ui-list { border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); overflow: hidden; }
.ui-list .lrow { display: flex; align-items: center; gap: 14px; padding: 13px 18px; border-bottom: 1px solid var(--border); transition: background var(--dur-fast) var(--ease); }
.ui-list .lrow:last-child { border-bottom: none; }
.ui-list .lrow:hover { background: color-mix(in srgb, var(--muted) 55%, var(--card)); }
.lrow .st { display: flex; } .lrow .st.ok { color: var(--success); } .lrow .st.warn { color: var(--danger); }
.lrow .body { flex: 1; min-width: 0; }
.lrow .body b { font-weight: 500; font-size: 13px; }
.lrow .body span { display: block; font-size: 11.5px; color: var(--muted-foreground); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lrow .meta { font-family: var(--font-mono); font-size: 11px; color: var(--muted-foreground); flex: none; }
.lrow .act { border: none; background: transparent; cursor: pointer; color: var(--muted-foreground); display: flex; padding: 6px; border-radius: var(--radius); transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); flex: none; }
.lrow .act:hover { background: var(--accent); color: var(--foreground); }

/* ========== table（作業系・高密度） ========== */
.ui-table-wrap { border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); overflow-x: auto; }
.ui-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.ui-table th { font-family: var(--font-head); font-weight: 500; font-size: 10.5px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted-foreground); text-align: left; padding: 10px 14px; border-bottom: 1px solid var(--border); white-space: nowrap; }
.ui-table th.sortable { cursor: pointer; }
.ui-table th.sortable:hover { color: var(--foreground); }
.ui-table th .sort { font-family: var(--font-sans); }
.ui-table td { padding: 8px 14px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.ui-table tbody tr { transition: background var(--dur-fast) var(--ease); }
.ui-table tbody tr:hover { background: color-mix(in srgb, var(--muted) 55%, var(--card)); }
.ui-table tbody tr:last-child td { border-bottom: none; }
.ui-table tbody tr.selected { background: color-mix(in srgb, var(--brand) 7%, var(--card)); }
.ui-table .mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: 11.5px; }
.ui-table .dim { color: var(--muted-foreground); }
.ui-table .w-check { width: 36px; }
.ui-table .w-act { width: 44px; text-align: right; }

.status-dot { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--muted-foreground); white-space: nowrap; }
.status-dot::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--success); }
/* 注意は「色」ではなく「中空」で 1 段落とす（塗り面を持てない dot での L1 表現・§23） */
.status-dot.warn::before { background: transparent; width: 7px; height: 7px; border: 1.5px solid var(--danger); }
.status-dot.err::before { background: var(--danger-solid); box-shadow: 0 0 0 3px color-mix(in srgb, var(--danger) 18%, transparent); }

/* 選択時アクションバー（左 = state / 右 = action） */
.sel-bar { display: none; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 14px; margin-bottom: 10px; font-size: 12px; background: color-mix(in srgb, var(--brand) 7%, var(--card)); border: 1px solid color-mix(in srgb, var(--brand) 30%, transparent); border-radius: var(--radius); }
.sel-bar.on { display: flex; animation: chip-in var(--dur-base) var(--ease); }
.sel-bar .n { font-family: var(--font-mono); color: var(--brand); }

/* ========== detail / mypage 用 ========== */
.detail-grid { display: grid; grid-template-columns: 1fr 320px; gap: 24px; align-items: start; }
/* grid item は既定 min-width:auto のため、内部の長い値（marketing-dashboard-prod 等）が
   コンテンツの固有幅ぶん列を押し広げ、狭い container で枠外へはみ出す（280px 実測・ユーザー指摘）。
   overflow の安全策として min-width:0 を与える（§25.1b: レイアウトの組み替えではなく overflow 対策） */
.detail-grid > * { min-width: 0; }
/* container 幅応答（DESIGN.md §25）: md 段（<1000px）で META/LINKS サイドバーが枠外へはみ出すため
   本文の下へ縦積み（viewport media query から @container ui へ移行。.ui-container 配下でのみ発動） */
@container ui (width < 1000px) { .detail-grid { grid-template-columns: 1fr; } }
/* .meta-list/.mrow（label+値の手組み横並び）は Detail の Meta カードを FormItem 化した際に
   撤回（DESIGN.md §13・§25.1c・08-21）。他ページからの参照も無いため定義ごと削除。 */

.avatar { width: 56px; height: 56px; border-radius: 50%; background: var(--foreground); color: var(--background); display: flex; align-items: center; justify-content: center; font-family: var(--font-head); font-weight: 600; font-size: 18px; letter-spacing: 0.05em; flex: none; }
.avatar--sm { width: 28px; height: 28px; font-size: 11px; }

/* ========== sliding indicator（micro-interaction）==========
   tab の下線 / pill・segment の黒 fill を選択先へスライドさせる。
   uilib-proto.js が [data-slide="underline|pill|seg"] を自動初期化（JS 無効時は従来の static 表示に自然フォールバック） */
/* position は CSS で決め打ちしない: 消費側が sticky / absolute を指定しているバーを潰さないため
   （`.has-slide { position: relative }` は後勝ちで sticky を殺していた）。
   containing block が必要なケースだけ initTabGroup が「computed が static のときに限り」inline で relative を付ける */
.slide-ind { position: absolute; left: 0; top: 0; opacity: 0; pointer-events: none; transition: left var(--dur-base) var(--ease), top var(--dur-base) var(--ease), width var(--dur-base) var(--ease), height var(--dur-base) var(--ease), opacity var(--dur-fast) var(--ease), background var(--dur-base) var(--ease); }
.slide-ind--underline { top: auto !important; bottom: -1px; height: 2px; background: var(--foreground); }
.slide-ind--pill { background: var(--foreground); border-radius: 999px; z-index: 0; }
.slide-ind--seg { background: var(--card); border-radius: 999px; box-shadow: 0 1px 3px rgba(0,0,0,.1); z-index: 0; }
.dark .slide-ind--seg { background: var(--secondary); box-shadow: 0 1px 3px rgba(0,0,0,.35); }
/* ニュートラル option（「すべて」）へ選択が移ったときの indicator 色（黒 fill を上書き。07-23） */
.slide-ind--neutral { background: var(--tab-neutral-fill); }
.slide-ind--seg.slide-ind--neutral { box-shadow: none; }
.has-slide > button, .has-slide > a { position: relative; z-index: 1; }
/* キーボード操作（08-03）の focus ring。roving tabindex + ←→ 移動を入れた以上、
   「今どこにフォーカスがあるか」が見えないと使えない。outline は inset（-2px）で描く —
   .ui-segment は overflow:hidden、scroll モードのバーは clip されるため外向きだと切れる */
.has-slide > button:focus-visible, .has-slide > a:focus-visible {
  outline: 2px solid var(--ring); outline-offset: -2px; border-radius: calc(var(--radius) - 1px);
}
/* .ui-segment / .view-toggle は track 形（radius 999px）のため focus ring も丸める */
.ui-segment.has-slide > button:focus-visible, .view-toggle.has-slide > button:focus-visible { border-radius: 999px; }
.has-slide .tab.active, .has-slide .ui-tab.active { border-bottom-color: transparent; }
/* pill / chip 系は「全ボタンの fill を透明化」する（不透明のままだと下を通る黒 fill のスライドが見えない）。
   白 fill の代わりに背面（card / background）が透ける — 見た目の差は誤差レベル */
.has-slide .stab, .has-slide .ui-pill, .has-slide .qf { background: transparent; }
.has-slide .stab:hover, .has-slide .ui-pill:hover, .has-slide .qf:hover { background: color-mix(in srgb, var(--muted) 60%, transparent); }
.has-slide .stab.active, .has-slide .ui-pill.active, .has-slide .qf.active { background: transparent; border-color: transparent; }
.has-slide .stab.active:hover, .has-slide .ui-pill.active:hover, .has-slide .qf.active:hover { background: transparent; }
.ui-segment.has-slide button.active { background: transparent; }

/* 日本語（混植）見出し: uppercase の効果が薄く広 tracking は間延びするため 0.06em に落とす（specimen でレビュー中） */
.ui-title-ja { letter-spacing: 0.06em !important; }

/* ========== navigation 部品 ========== */
.ui-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); }
.ui-tab { border: none; background: transparent; cursor: pointer; font-family: var(--font-head); font-weight: 500; font-size: 12px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--muted-foreground); padding: 10px 14px; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease); }
.ui-tab:hover { color: var(--foreground); }
.ui-tab.active { color: var(--foreground); border-bottom-color: var(--foreground); }
/* MPA 化（07-29）: TabGroup は <button> だけでなく <a href> のナビにも同じ見た目を適用する
   （実ページ遷移なので下線消し + inherit color が必要。button には無影響） */
.ui-tab, .ui-pill { text-decoration: none; }

/* ========== TabGroup オーバーフロー（08-03 再定義: collapse / scroll の2モード） ==========
   バーに入りきらないタブの扱いを data-overflow で選ぶ。overflow の CSS も uilib が持つので
   消費側は overflow-x を書かない（書いても後述の !important 相当の指定で uilib 側が正になる）。

   collapse（既定）… バーは横スクロールしない。入りきらないタブは実際に非表示（.is-collapsed）にして
                     右端の「+N ▾」chip のメニューへ集約する。表示と件数が常に一致し重複しない
   scroll        … chip を出さず横スクロールさせる。スクロールバーは隠し、
                     スクロール可能な側だけ端をフェード（.can-scroll-left / .can-scroll-right）
   off           … scroll の別名（後方互換・非推奨）

   .tab-more-menu は overflow コンテナの外（document.body）に position:fixed で開く */
/* collapse は「中身が必ず収まる」ので overflow を作らない。消費側の overflow-x:auto を明示的に打ち消すのは、
   スクロールコンテナ化すると padding box で clip され underline（bottom:-1px）と tab の margin-bottom:-1px が切れるため */
.has-slide[data-overflow="collapse"] { overflow: visible; }
/* !important 必須: タブに inline style（例 style="display:inline-flex" でアイコン + ラベルを並べる）が
   付いていると class ルールでは畳めず、畳んだつもりのタブが幅を食い続ける（現場に markup 修正を強いないため） */
.has-slide[data-overflow="collapse"] > .is-collapsed { display: none !important; }
.has-slide[data-overflow="scroll"] { overflow-x: auto; overflow-y: hidden; scrollbar-width: none; -ms-overflow-style: none;
  --fade-l: 0px; --fade-r: 0px;
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--fade-l), #000 calc(100% - var(--fade-r)), transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #000 var(--fade-l), #000 calc(100% - var(--fade-r)), transparent 100%); }
.has-slide[data-overflow="scroll"]::-webkit-scrollbar { display: none; }
.has-slide[data-overflow="scroll"].can-scroll-left { --fade-l: 28px; }
.has-slide[data-overflow="scroll"].can-scroll-right { --fade-r: 28px; }
/* scroll はスクロールコンテナ = padding box で clip される。underline を境界線に食い込ませない（切れるため） */
.has-slide[data-overflow="scroll"] .slide-ind--underline { bottom: 0; }
/* height は指定しない: バー（flex・高さ auto）では % が解決できず潰れるため align-self: stretch で全高に伸ばす */
.has-slide > .tab-more { flex: none; display: flex; align-items: center; align-self: stretch; padding: 0 2px 0 10px; border: none; background: none; cursor: pointer; }
/* chip button（.ui-pill 準拠の丸ピル）: outline + hover accent、open 中は tonal fill */
.tab-more-chip { display: inline-flex; align-items: center; gap: 4px; padding: 3px 7px 3px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--card); color: var(--muted-foreground); transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease); }
.tab-more:hover .tab-more-chip { background: var(--accent); color: var(--foreground); }
/* focus ring は全高の透明ボタンではなく chip の丸ピルに沿わせる */
.tab-more:focus-visible { outline: none; }
.tab-more:focus-visible .tab-more-chip { outline: 2px solid var(--ring); outline-offset: 1px; }
.tab-more.open .tab-more-chip { background: var(--tab-neutral-fill); border-color: transparent; color: var(--foreground); }
.tab-more .n { font-family: var(--font-mono); font-size: 10.5px; }
.tab-more .caret { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; transition: transform var(--dur-fast) var(--ease); }
.tab-more.open .caret { transform: rotate(180deg); }

.tab-more-menu { position: fixed; min-width: 180px; max-height: 60vh; overflow-y: auto; background: var(--popover); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: 0 8px 24px rgba(0,0,0,.08); padding: 4px; z-index: 1000; animation: chip-in var(--dur-base) var(--ease); }
.tab-more-item { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; border: none; background: transparent; cursor: pointer; padding: 8px 14px; border-radius: calc(var(--radius) - 2px); font-size: 12.5px; color: var(--muted-foreground); transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.tab-more-item:hover { background: var(--accent); color: var(--foreground); }
.tab-more-item.active { color: var(--foreground); font-weight: 500; background: var(--secondary); }
.tab-more-item svg.ic, .tab-more-item .material-icons { flex: none; }

.ui-pill-tabs { display: flex; gap: 6px; }
.ui-pill { border: 1px solid var(--border); background: var(--card); color: var(--muted-foreground); font-size: 12px; font-family: var(--font-sans); padding: 4px 12px; border-radius: 999px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; transition: all var(--dur-fast) var(--ease); }
.ui-pill:hover { background: var(--accent); color: var(--foreground); }
.ui-pill.active { background: var(--foreground); border-color: var(--foreground); color: var(--background); }
/* ニュートラル option（「すべて」等・絞り込み解除）の selected は黒 fill ではなく tonal（07-23 ユーザー決定・DESIGN.md §7）。
   既存の黒 fill ルールより後に置いて優先させる */
.qf[data-tone="neutral"].active, .ui-pill[data-tone="neutral"].active, .stab[data-tone="neutral"].active, .ui-segment:not(.has-slide) button[data-tone="neutral"].active { background: var(--tab-neutral-fill); border-color: transparent; color: var(--foreground); }

/* ========== Chrome 風タブ（.ui-ctabs・v1.28.0） ==========
   「面が持ち上がって content と地続きになる」タブ。既存の TabGroup 3 形（下線 .ui-tabs /
   pill .ui-pill / track .ui-segment）とは目的が違う — **開いている作業単位そのもの**を並べ、
   個別に閉じられ、右端から増やせる器（ブラウザのタブ・エディタのタブ）に限って使う。
   ページ内の view 切替・フィルタには使わない（従来の 3 形が正）。初消費 = Fleet のセッションタブ。

   形: active タブだけが下端左右に**外向きカーブ**を持ち、bar の下線を面で覆って content と繋がる。
   カーブは疑似要素 1 枚を radial-gradient mask で凹ませて作る（SVG も余分な DOM も持たない）。
   面の色は --ctab-fill（既定 var(--card)）。content 側の面色が --card でないときは消費側が上書きする。

   タブ間の区切りは疑似要素ではなく background-image（1px の縦線）で描く。
   ::before / ::after は左右のカーブが専有しているため。 */
/* bar には地色を敷く（Chrome と同じ）。active の面（--ctab-fill = 既定 --card）が
   地色より明るいことで初めて「持ち上がり」が読める — 地色なしで白い card の上に置くと
   active と非 active の差が下線しか残らない（08-28 実測） */
.ui-ctabs {
  /* カーブ半径。10px ではタブ高 34px に対して曲線が小さすぎ、等倍だと「白いゴミ」に見える
     （08-28 実機で 10 / 14 / 24px を比較）。14px で Chrome 実物と同じ「曲線として読める」大きさになる */
  --ctab-r: 14px; --ctab-h: 34px; --ctab-fill: var(--card);
  display: flex; align-items: flex-end;
  background: color-mix(in srgb, var(--muted-foreground) 9%, transparent);
  border-radius: var(--radius) var(--radius) 0 0;
  /* **content 側へ 1px 食い込む**（Chrome と同じ構造・08-28 実機 FB の真因）。
     bar が小数座標（例: y=422.59px）に置かれると、active の底辺と content の上辺が同じ小数座標で接し、
     その 1 行が半透明合成されて「タブの下に灰色の髪の毛線」が出る = 地続きが切れて fillet が
     線の上に乗った塊に見える。active の面と fillet を 1px 下へ伸ばし、bar 自体は margin で 1px 戻す
     （後続の content は位置不変）。bar は positioned にしない — positioned だと後続の content より
     上に描かれ、はみ出した 1px の地色が content を覆ってしまう */
  padding: 0; margin-bottom: -1px;
}
/* bar の下端に境界線は引かない（Chrome と同じ）。線があると、active の面から外へ出る
   カーブが「線の上に乗った出っ張り」に見えて content と地続きにならない（08-28 実機 FB）。
   非 active 側の境界は bar 地色と content 面の色差だけで足りる */
/* タブが増えたら横スクロール（スクロールバーは隠す）。Chrome 同様まず縮み、min-width で止まる */
/* padding は clip 対策: scroll container は padding box で clip するので、先頭 / 末尾タブの fillet
   （本体の外 r px）と 1px の食い込み（下）を padding の内側に収めないと切れる
   （先頭タブが active のとき左 fillet だけ消えて非対称になっていた — 08-28 実測） */
.ui-ctabs-list { display: flex; align-items: flex-end; flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none; padding: 0 var(--ctab-r) 1px; }
.ui-ctabs-list::-webkit-scrollbar { display: none; }

.ui-ctab {
  position: relative; z-index: 1; flex: 0 1 190px; min-width: 56px; max-width: 220px;
  height: var(--ctab-h); display: flex; align-items: center; gap: 7px; padding: 0 10px;
  border: none; background-color: transparent; cursor: pointer;
  font-family: var(--font-sans); font-size: 12.5px; color: var(--muted-foreground);
  white-space: nowrap; text-decoration: none;
  border-radius: var(--ctab-r) var(--ctab-r) 0 0;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
  /* 区切り線（左端 1px・高さ 15px） */
  background-image: linear-gradient(var(--border), var(--border));
  background-size: 1px 15px; background-position: left center; background-repeat: no-repeat;
}
/* 区切り線を消す条件: 先頭 / 自分が active・hover / 直前が active・hover（Chrome と同じ作法） */
.ui-ctab:first-child, .ui-ctab:hover, .ui-ctab.active,
.ui-ctab:hover + .ui-ctab, .ui-ctab.active + .ui-ctab { background-image: none; }
.ui-ctab:hover { background-color: color-mix(in srgb, var(--muted-foreground) 12%, transparent); color: var(--foreground); }
.ui-ctab.active { z-index: 2; background-color: var(--ctab-fill); color: var(--foreground);
  /* 面を 1px 下へ伸ばす（layout を変えない box-shadow）。content 上辺の半透明行を同色で覆う */
  box-shadow: 0 1px 0 var(--ctab-fill); }
/* focus ring は**タブの内側に一回り小さく**描く（Chrome の作法）。輪郭に沿わせると
   外向きカーブ（本体の外に出る疑似要素）が枠の外に取り残され、はみ出した白い塊に見える
   （08-28 ユーザー実機 FB・実測で再現）。内側リングなら「面の中の装飾」として読め、
   下辺も content との地続きを切らない */
.ui-ctab:focus-visible { outline: 2px solid var(--ring); outline-offset: -5px; border-radius: calc(var(--ctab-r) - 4px); }

/* 外向きカーブ（active のみ）。10px 角の面を「隣接する角を中心とした円」でくり抜いて凹ませる */
.ui-ctab.active::before, .ui-ctab.active::after {
  content: ''; position: absolute; bottom: -1px; z-index: -1; pointer-events: none;
  width: var(--ctab-r); height: calc(var(--ctab-r) + 1px); background: var(--ctab-fill);
}
/* **円の中心は「外側の上角」**（左 fillet = 0 0 / 右 fillet = 100% 0）。fillet はその円の外側なので
   タブの壁に沿って全高で接し、床へ向かって細くなる（壁側 tangent 垂直・床側 tangent 水平 = Chrome の形）。
   中心を「タブ側の上角」に置くと鏡像になり、外側に垂直の壁を持つ D 字の塊 = タブ両脇の「線」になる
   （08-28 ユーザー実機 FB の真因。6 倍拡大のピクセル比較で確定） */
/* 半径は必ず**明示**する。`closest-side` は中心が角（0 0 / 100% 0）のとき最も近い辺までの距離が 0 =
   半径 0 になり、mask が何も抜かず四角い塊が残る（08-28 実測。右カーブが凹まない不具合の真因）。
   色停止は 1px 幅の遷移にする（hard stop の radial-gradient は antialias されず輪郭がギザつく） */
.ui-ctab.active::before { left: calc(-1 * var(--ctab-r));
  -webkit-mask-image: radial-gradient(circle var(--ctab-r) at 0 0, transparent calc(100% - 1px), #000 100%);
          mask-image: radial-gradient(circle var(--ctab-r) at 0 0, transparent calc(100% - 1px), #000 100%); }
.ui-ctab.active::after { right: calc(-1 * var(--ctab-r));
  -webkit-mask-image: radial-gradient(circle var(--ctab-r) at 100% 0, transparent calc(100% - 1px), #000 100%);
          mask-image: radial-gradient(circle var(--ctab-r) at 100% 0, transparent calc(100% - 1px), #000 100%); }

.ui-ctab-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; text-align: left; }
/* 状態ドット（favicon 位置）。tone は §23 の 2 色主義に従う（正常 = 藍 / 注意 = 朱） */
.ui-ctab-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--muted-foreground); }
.ui-ctab-dot[data-tone="success"] { background: var(--success); }
.ui-ctab-dot[data-tone="danger"] { background: var(--danger); }
.ui-ctab-dot[data-tone="brand"] { background: var(--brand); }
/* muted は「動いていない」を示す最弱の tone。dark で --border は地色に沈むため
   muted-foreground の減光で作る（両テーマで同じ弱さに見える） */
.ui-ctab-dot[data-tone="muted"] { background: var(--muted-foreground); opacity: .45; }
/* 実行中の脈動（motion は opacity のみ・§ motion 原則） */
.ui-ctab-dot--pulse { animation: ctab-pulse 1.4s var(--ease) infinite; }
@keyframes ctab-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .ui-ctab-dot--pulse { animation: none; } }
/* icon slot（favicon 相当。dot の代わりに svg / material icon を置ける） */
.ui-ctab > svg.ic, .ui-ctab > .material-icons { flex: none; width: 14px; height: 14px; font-size: 14px; }

/* 閉じる ×: active と hover 中のタブでだけ見せる（幅は常に確保 = layout shift ゼロ） */
.ui-ctab-close {
  flex: none; width: 16px; height: 16px; margin-right: -3px; display: grid; place-items: center;
  border: none; background: transparent; border-radius: 50%; cursor: pointer; color: inherit;
  opacity: 0; transition: opacity var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.ui-ctab:hover .ui-ctab-close, .ui-ctab.active .ui-ctab-close, .ui-ctab-close:focus-visible { opacity: 1; }
.ui-ctab-close:hover { background: color-mix(in srgb, var(--muted-foreground) 22%, transparent); }
.ui-ctab-close:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.ui-ctab-close svg { width: 10px; height: 10px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; }

/* + 新規タブ（タブ列の右・bar の中に浮く） */
.ui-ctabs-add {
  flex: none; width: 26px; height: 26px; margin: 0 4px 5px 0; display: grid; place-items: center;
  border: none; background: transparent; border-radius: var(--radius); cursor: pointer;
  color: var(--muted-foreground); transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.ui-ctabs-add:hover { background: var(--accent); color: var(--foreground); }
.ui-ctabs-add:focus-visible { outline: 2px solid var(--ring); outline-offset: -1px; }
.ui-ctabs-add svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; }

/* content 面と繋げるための器（任意）。bar の直下に置くと地続きに見える */
.ui-ctabs-panel { background: var(--ctab-fill, var(--card)); border-radius: 0 0 var(--radius) var(--radius); padding: 16px; }

.ui-pagination { display: flex; gap: 4px; align-items: center; }
.ui-page-btn { min-width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--border); background: var(--card); border-radius: var(--radius); font-family: var(--font-mono); font-size: 12px; cursor: pointer; color: var(--muted-foreground); padding: 0 6px; transition: all var(--dur-fast) var(--ease); }
.ui-page-btn:hover:not(:disabled) { background: var(--accent); color: var(--foreground); }
.ui-page-btn.active { background: var(--foreground); border-color: var(--foreground); color: var(--background); }
.ui-page-btn:disabled { opacity: .45; cursor: not-allowed; }
.ui-page-ellipsis { color: var(--muted-foreground); font-family: var(--font-mono); font-size: 12px; padding: 0 4px; }

.ui-steps { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ui-step { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted-foreground); }
.ui-step .n { width: 22px; height: 22px; border-radius: 50%; border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; font-family: var(--font-mono); font-size: 11px; background: var(--card); }
.ui-step.done .n { background: var(--foreground); color: var(--background); border-color: var(--foreground); }
.ui-step.current { color: var(--foreground); font-weight: 500; }
.ui-step.current .n { border-color: var(--foreground); }
.ui-step-sep { width: 28px; height: 1px; background: var(--border); }

/* ========== surface controls（浮遊 surface の面操作 — DESIGN.md §21）==========
   dock panel / dialog / drawer / 展開型 FAB 等「面そのもの」を操作する外側の操作系。
   content の action バー（.jgt-ctrl 等）とは階層が異なる（ctrl = content 用 / surface-ctrl = 面用）。
   構造: .ui-surface-ctrl（title? + actions の2カラム行）内に
   .ui-surface-ctrl-grow（⤢ = 増加方向のみ。最大段で disabled = 場所は保持）+
   .ui-surface-ctrl-close（× = 離脱。減少方向はここに統合 — 08-03 是正。§21 参照）。
   uilibProto.surfaceControls(el, opts) が生成する */
.ui-surface-ctrl { display: flex; align-items: center; gap: 8px; width: 100%; }
.ui-surface-ctrl-title { display: flex; align-items: center; gap: 6px; min-width: 0; overflow: hidden; }
.ui-surface-ctrl-actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; margin-left: auto; }
/* × の寸法・見た目は §26 の .ui-surface-close と共有（v1.30.0 で 24px → 26px に統一）。grow だけここで定義 */
.ui-surface-ctrl-grow { appearance: none; border: none; background: transparent; cursor: pointer; color: var(--muted-foreground); width: var(--ui-close-size); height: var(--ui-close-size); border-radius: var(--radius); display: flex; align-items: center; justify-content: center; padding: 0; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease); }
.ui-surface-ctrl-grow:hover:not(:disabled) { background: var(--accent); color: var(--foreground); }
.ui-surface-ctrl-grow:disabled { opacity: .35; cursor: not-allowed; }
.ui-surface-ctrl-grow svg.ic { width: var(--ui-close-glyph); height: var(--ui-close-glyph); }
.ui-surface-ctrl-grow:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }

/* ========== surface head（面の見出し行 + 閉じる × — DESIGN.md §26・v1.30.0）==========
   dialog / drawer / dock panel / side pane / 詳細パネル など「面」の最上段の 1 行。
   構造: .ui-surface-head（flex 行）> .ui-surface-head-title（ellipsis）+ .ui-surface-head-meta?
         + .ui-surface-head-actions?（margin-left:auto）+ .ui-surface-close（× = 離脱・必ず右端の最後）。
   寸法は 3 段（--sm 32 / 既定 36 / --lg 44）で、× は段を問わず 26px 角（--ui-close-size）。
   × のグリフ（14px）は箱の中央にあるので、右端を内容端に光学的に揃えるため箱を 6px 外へ出す
   （(26 − 14) / 2）。※ 光学合わせは「右端の最後の子」にだけ効く（途中に置いた × は揃えない） */
:root { --ui-close-size: 26px; --ui-close-glyph: 14px; }
.ui-surface-head { display: flex; align-items: center; gap: 8px; min-height: 36px; padding: 5px 12px; }
.ui-surface-head--sm { min-height: 32px; padding: 3px 10px; gap: 6px; } /* 26px の × + 3px×2 = 32 */
.ui-surface-head--lg { min-height: 44px; padding: 8px 16px; gap: 10px; }
.ui-surface-head-title { flex: 1 1 auto; font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* title が伸びて × を右端へ押す（actions が無い行でも × は右端） */
.ui-surface-head-meta { color: var(--muted-foreground); flex: none; font-size: .92em; }
.ui-surface-head-actions { display: flex; align-items: center; gap: 4px; margin-left: auto; flex: none; }
.ui-surface-close, .ui-surface-ctrl-close {
  appearance: none; border: none; background: transparent; cursor: pointer; color: var(--muted-foreground);
  width: var(--ui-close-size); height: var(--ui-close-size); border-radius: var(--radius);
  display: inline-flex; align-items: center; justify-content: center; padding: 0; flex: none;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.ui-surface-close:hover, .ui-surface-ctrl-close:hover { background: var(--accent); color: var(--foreground); }
.ui-surface-close:focus-visible, .ui-surface-ctrl-close:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.ui-surface-close svg.ic, .ui-surface-ctrl-close svg.ic { width: var(--ui-close-glyph); height: var(--ui-close-glyph); stroke-width: 2; }
/* 右端の光学合わせ（見出し行の最後の子 / actions 群の最後の子 / surface-ctrl の actions の最後の子） */
.ui-surface-head > .ui-surface-close:last-child,
.ui-surface-head-actions > .ui-surface-close:last-child,
.ui-surface-ctrl-actions > .ui-surface-ctrl-close:last-child { margin-right: calc((var(--ui-close-glyph) - var(--ui-close-size)) / 2); }
/* × が 1 つも無い見出し行はその席を空けない（layout shift ゼロ原則は「増減するもの」にだけ適用 — §7 ctabs） */
/* dialog の見出し行: dialog は padding 24px を面全体で持つので、行の padding は 0 にして高さだけ揃える */
.ui-dialog > .ui-surface-head { padding: 0; min-height: 0; margin-bottom: 8px; }
.ui-dialog > .ui-surface-head > h3 { margin-bottom: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* rail（畳まれた状態の標準表現 — DESIGN.md §21「rail は surface への入口」）。
   surface controls 自体は rail では描画しない（rail のクリック自体が復帰導線のため） */
.ui-surface-rail { width: 28px; display: flex; flex-direction: column; align-items: center; gap: 8px; padding-top: 8px; cursor: pointer; background: var(--card); transition: background var(--dur-fast) var(--ease); }
.ui-surface-rail:hover { background: var(--accent); }
.ui-surface-rail-label { writing-mode: vertical-rl; font-size: 10px; color: var(--muted-foreground); letter-spacing: .1em; }
.ui-surface-rail-badge { background: var(--foreground); color: var(--background); border-radius: 999px; font-family: var(--font-mono); font-size: 9px; font-weight: 700; min-width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center; padding: 0 4px; }

/* ========== dropdown button（trigger + panel の複合部品）==========
   toolbar のフィルタ・ソート等「押すと選択パネルが開くボタン」の標準形。
   構造: .ui-dd > .ui-dd-btn（trigger）+ .ui-dd-panel（search? + list + foot?）。
   uilib-proto.js が .ui-dd を自動初期化（開閉 + 外側クリックで閉じる）。
   multi-select は list を checkbox option（.ui-dd-option）で組み、選択数を .n バッジに出す */
.ui-dd { position: relative; display: inline-flex; }
.ui-dd-btn { appearance: none; display: inline-flex; align-items: center; gap: 7px; background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); color: var(--muted-foreground); font-family: var(--font-sans); font-size: 12.5px; padding: 5px 9px 5px 12px; cursor: pointer; white-space: nowrap; transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-dd-btn:hover { background: var(--accent); color: var(--foreground); }
.ui-dd-btn .caret { display: flex; transition: transform var(--dur-base) var(--ease); }
.ui-dd.open .ui-dd-btn .caret { transform: rotate(180deg); }
.ui-dd.open .ui-dd-btn { border-color: color-mix(in srgb, var(--foreground) 25%, var(--border)); color: var(--foreground); }
/* 選択あり = 黒 fill の件数バッジ（selected 表現は黒 fill の原則） */
.ui-dd-btn.has-value { border-color: color-mix(in srgb, var(--foreground) 35%, var(--border)); color: var(--foreground); font-weight: 500; }
.ui-dd-btn .n { font-family: var(--font-mono); font-size: 10.5px; line-height: 1; background: var(--foreground); color: var(--background); border-radius: 999px; padding: 3px 7px; }
.ui-dd-panel, .ui-ms-panel { position: absolute; top: calc(100% + 4px); left: 0; z-index: 30; min-width: 220px; background: var(--popover); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: 0 8px 24px rgba(0,0,0,.08); display: none; overflow: hidden; }
.ui-dd.open .ui-dd-panel, .ui-ms-panel.open { display: block; animation: chip-in var(--dur-base) var(--ease); }
.ui-dd-panel--right { left: auto; right: 0; }
.ui-dd-search { padding: 7px 8px; border-bottom: 1px solid var(--border); }
.ui-dd-search input { display: block; width: 100%; font-family: var(--font-sans); font-size: 12.5px; line-height: 18px; color: var(--foreground); background: var(--card); border: 1px solid var(--input); border-radius: calc(var(--radius) - 1px); padding: 4px 9px; transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease); }
.ui-dd-search input:focus { outline: none; border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent); }
.ui-dd-list, .ui-ms-list { max-height: 240px; overflow-y: auto; padding: 4px; }
.ui-dd-option, .ui-ms-option { display: flex; align-items: center; gap: 9px; padding: 6px 9px; border-radius: calc(var(--radius) - 2px); font-size: 13px; color: var(--foreground); cursor: pointer; transition: background var(--dur-fast) var(--ease); }
.ui-dd-option:hover, .ui-ms-option:hover { background: var(--accent); }
.ui-dd-option.selected { font-weight: 500; }
.ui-dd-option .ui-check { pointer-events: none; }
.ui-dd-option .dot, .ui-ms-option .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.ui-dd-empty, .ui-ms-empty { padding: 10px; font-size: 12px; color: var(--muted-foreground); text-align: center; }
.ui-dd-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 10px; border-top: 1px solid var(--border); font-size: 11.5px; color: var(--muted-foreground); }
.ui-dd-foot button { border: none; background: transparent; cursor: pointer; font-family: var(--font-sans); font-size: 11.5px; color: var(--muted-foreground); padding: 2px 6px; border-radius: calc(var(--radius) - 2px); transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease); }
.ui-dd-foot button:hover { color: var(--foreground); background: var(--accent); }

/* multi select（chip 型 tag input）。.ui-ms-field は .ui-input と同じ枠線/focus ring を持つが、
   要素は input ではなく div（中に chip 群 + 実際の input を wrap で並べる）。
   active 行のハイライトは .ui-cmdk-item.active と同趣旨（黒 fill = selected の対象外・DESIGN.md §18） */
.ui-ms { position: relative; display: inline-flex; flex-direction: column; min-width: 220px; }
.ui-ms-field { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; width: 100%; min-height: 34px;
  background: var(--card); border: 1px solid var(--input); border-radius: var(--radius); padding: 4px 6px; cursor: text;
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease); }
.ui-ms-field:focus-within { border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent); }
.ui-ms-input { flex: 1; min-width: 80px; border: none; outline: none; background: transparent; font-family: var(--font-sans); font-size: 13px; color: var(--foreground); padding: 3px 4px; }
.ui-ms-input::placeholder { color: var(--muted-foreground); }
.ui-ms-option.active { background: var(--accent); } /* commandPalette の .ui-cmdk-item.active と同型 */
.ui-ms-option .lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-ms-option .ui-kbd { flex: none; margin-left: auto; } /* comboSelect option.kbd（v1.26.0）。hint と併用時は hint の右 */
.ui-ms-option .hint { font-size: 11px; color: var(--muted-foreground); flex: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 45%; }
/* 単一値の選択済み option は太字（黒 fill は selected 状態の面には使わない — active は accent） */
.ui-ms-option.selected .lbl { font-weight: 600; }

/* ========== combo select（単一・入力可能 combobox — DESIGN.md §10「select（単一）」）==========
   input 自体がトリガー: focus / 入力で .ui-ms-panel（multi select と共有）が開き、自由入力で絞り込み →
   クリック / Enter で選択。caret は --select-caret を input 背景に描画（.ui-select と同じ affordance）。
   uilibProto.comboSelect(el, opts) が生成・配線する */
.ui-combo { position: relative; display: inline-flex; min-width: 180px; }
.ui-combo-input { display: block; width: 100%; font-family: var(--font-sans); font-size: 13px; line-height: 20px; color: var(--foreground);
  background: var(--card); border: 1px solid var(--input); border-radius: var(--radius); padding: 8px 30px 8px 12px;
  background-image: var(--select-caret); background-repeat: no-repeat; background-position: right 9px center; background-size: 14px;
  cursor: pointer; transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease); }
.ui-combo-input::placeholder { color: var(--muted-foreground); }
.ui-combo-input:focus { outline: none; border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent); cursor: text; }
.ui-combo .ui-ms-panel { min-width: max(100%, 220px); } /* トリガー幅 or 220px の広い方（100% 単独だと chip 形で panel が潰れる） */
/* sm サイズ（.ui-input--sm と同メトリクス） */
.ui-combo--sm .ui-combo-input { padding: 5px 26px 5px 10px; font-size: 12px; line-height: 18px; background-size: 13px; background-position: right 8px center; }
/* ghost 形（パンくず・見出し等のインライン文脈: 枠/面なし・hover で薄い面・focus で input 化） */
.ui-combo--ghost .ui-combo-input { background-color: transparent; border-color: transparent; font-weight: 500; }
.ui-combo--ghost .ui-combo-input:hover:not(:focus) { background-color: var(--accent); }
.ui-combo--ghost .ui-combo-input:focus { background-color: var(--card); }
/* chip 形（トリガー = チップ型 dropdown button [ラベル ▾ (×)]。検索 input は panel 内。
   .ui-dd-btn / .tab-more-chip の系譜: 丸ピル・open 中は caret 180° + 枠締め） */
.ui-combo--chip { min-width: 0; }
.ui-combo-chip { display: inline-flex; align-items: center; gap: 5px; border: 1px solid var(--border); border-radius: 999px; background: var(--card); color: var(--foreground); font-family: var(--font-sans); font-size: 12px; font-weight: 500; padding: 3px 8px 3px 12px; cursor: pointer; white-space: nowrap; transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-combo-chip:hover { background: var(--accent); }
.ui-combo-chip:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.ui-combo.open .ui-combo-chip { border-color: color-mix(in srgb, var(--foreground) 25%, var(--border)); }
.ui-combo-chip.empty .lbl { color: var(--muted-foreground); font-weight: 400; }
.ui-combo-chip .caret { width: 12px; height: 12px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex: none; transition: transform var(--dur-fast) var(--ease); }
.ui-combo.open .ui-combo-chip .caret { transform: rotate(180deg); }
/* 解除行（clearable）: panel 最下段の全幅行。トリガー上の × は誤クリックしやすいため置かない（07-31 判例） */
.ui-combo-clear-row { display: flex; align-items: center; gap: 7px; width: 100%; border: none; background: transparent; border-top: 1px solid var(--border); padding: 7px 12px; font-family: var(--font-sans); font-size: 12px; color: var(--muted-foreground); cursor: pointer; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-combo-clear-row:hover { background: var(--accent); color: var(--foreground); }
.ui-combo-clear-row svg { width: 11px; height: 11px; }
.ui-combo-search { padding: 7px 8px; border-bottom: 1px solid var(--border); }
.ui-combo-search input { display: block; width: 100%; font-family: var(--font-sans); font-size: 12.5px; line-height: 18px; color: var(--foreground); background: var(--card); border: 1px solid var(--input); border-radius: calc(var(--radius) - 1px); padding: 4px 9px; transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease); }
.ui-combo-search input:focus { outline: none; border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent); }

.ui-menu { position: absolute; top: calc(100% + 4px); left: 0; z-index: 20; min-width: 200px; background: var(--popover); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: 0 8px 24px rgba(0,0,0,.08); padding: 4px; display: none; }
.ui-menu.open { display: block; animation: chip-in var(--dur-base) var(--ease); }
.ui-menu-item { display: flex; align-items: center; gap: 9px; padding: 7px 10px; border-radius: calc(var(--radius) - 2px); font-size: 13px; cursor: pointer; color: var(--foreground); transition: background var(--dur-fast) var(--ease); }
.ui-menu-item:hover { background: var(--accent); }
.ui-menu-item.danger { color: var(--danger); }
.ui-menu-item .sc { margin-left: auto; font-family: var(--font-mono); font-size: 10.5px; color: var(--muted-foreground); }
.ui-menu-sep { height: 1px; background: var(--border); margin: 4px 0; }

/* segmented control（track 形。08-28 ユーザー決定で outline+黒fill 型を廃止し統一）:
   外周は下地に依存しない foreground 7%（dark 10%）の半透明 track、selected は白 pill（card fill + shadow）。
   radius は 999px（完全な丸）。並んだフィルタ群を「群 = 1つの丸い面」として読ませるための形
   （outline 型や裸 pill 列だと群の区切りが弱い）。muted 背景だと下地の --muted 面と同化して見えなくなるため
   半透明にした（08-28 追記・marketing の詳細データ帯で実機確認）。active で font-weight を変えない（layout shift ゼロ原則） */
.ui-segment { display: inline-flex; border: 1px solid transparent; border-radius: 999px; overflow: hidden; background: color-mix(in srgb, var(--foreground) 7%, transparent); padding: 3px; gap: 2px; }
.ui-segment button { border: none; background: transparent; cursor: pointer; border-radius: 999px; font-family: var(--font-sans); font-weight: 500; font-size: 12.5px; padding: 5px 14px; color: var(--muted-foreground); white-space: nowrap; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-segment button.active { background: var(--card); color: var(--foreground); box-shadow: 0 1px 3px rgba(0,0,0,.1); }
.ui-segment.has-slide button.active { background: transparent; box-shadow: none; color: var(--foreground); }
.dark .ui-segment { background: color-mix(in srgb, var(--foreground) 10%, transparent); }
.dark .ui-segment:not(.has-slide) button.active,
.dark .ui-segment .slide-ind--seg { background: var(--secondary); box-shadow: 0 1px 3px rgba(0,0,0,.35); }

/* v1.25.0 で .ui-segment 基本形が track 形へ統合されたため中身は不要（非推奨・後方互換の空エイリアス）。
   消費側の再リリース後に削除予定。--soft 前提のセレクタは .ui-segment（track）に読み替える */
.ui-segment--soft {}

/* FAB（chat comp の定位置 = 右下固定。ページ内では position:fixed で使う） */
.ui-fab { width: 48px; height: 48px; border-radius: 50%; border: none; background: var(--primary); color: var(--primary-foreground); display: flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 6px 20px rgba(0,0,0,.22); transition: transform var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease); }
.ui-fab:hover { transform: translateY(-2px); opacity: .9; }
.ui-fab svg { width: 20px; height: 20px; }
.ui-fab--sm { width: 40px; height: 40px; }
.ui-fab--sm svg { width: 17px; height: 17px; }

/* ========== display 部品 ========== */
.ui-badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 500; border-radius: 999px; padding: 2px 9px; border: 1px solid transparent; }
.ui-badge .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.ui-badge--neutral { background: var(--secondary); color: var(--secondary-foreground); border-color: var(--border); }
.ui-badge--outline { background: transparent; border-color: var(--input); color: var(--muted-foreground); }
.ui-badge--brand { background: color-mix(in srgb, var(--brand) 10%, var(--card)); color: var(--brand); border-color: color-mix(in srgb, var(--brand) 35%, transparent); }
.ui-badge--success { background: color-mix(in srgb, var(--success) 12%, var(--card)); color: var(--success); border-color: color-mix(in srgb, var(--success) 35%, transparent); }
.ui-badge--warning { background: color-mix(in srgb, var(--danger) 12%, var(--card)); color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
/* 失敗チップだけは fill（§23・alert の error と同じ文法）。icon を添えると色を見なくても形で分かる */
.ui-badge--destructive { background: var(--danger-solid); color: var(--danger-foreground); border-color: var(--danger-solid); --knock: var(--danger-solid); }
/* badge 内の icon は variant を問わず 12px（新文法の fill badge でも同寸になるよう基底へ昇格） */
.ui-badge svg.ic { width: 12px; height: 12px; margin-right: 1px; }
.ui-badge--destructive svg.ic { width: 12px; height: 12px; margin-right: 1px; }

.avatar--sm { width: 28px; height: 28px; font-size: 11px; }
.avatar--lg { width: 72px; height: 72px; font-size: 22px; }
.avatar-group { display: flex; }
.avatar-group .avatar { border: 2px solid var(--card); }
.avatar-group .avatar + .avatar { margin-left: -9px; }

.ui-tip { position: relative; }
.ui-tip::after { content: attr(data-tip); position: absolute; bottom: calc(100% + 6px); left: 50%; transform: translateX(-50%) translateY(3px); background: var(--foreground); color: var(--background); font-size: 11px; line-height: 1.5; padding: 4px 9px; border-radius: calc(var(--radius) - 1px); white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease); z-index: 30; }
.ui-tip:hover::after { opacity: 1; transform: translateX(-50%); }

.ui-acc { border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); overflow: hidden; }
.ui-acc details { border-bottom: 1px solid var(--border); }
.ui-acc details:last-child { border-bottom: none; }
.ui-acc summary { list-style: none; cursor: pointer; padding: 12px 16px; font-size: 13px; font-weight: 500; display: flex; justify-content: space-between; align-items: center; gap: 10px; transition: background var(--dur-fast) var(--ease); }
.ui-acc summary::-webkit-details-marker { display: none; }
.ui-acc summary:hover { background: color-mix(in srgb, var(--muted) 55%, var(--card)); }
.ui-acc summary svg { transition: transform var(--dur-base) var(--ease); color: var(--muted-foreground); }
.ui-acc details[open] summary svg { transform: rotate(180deg); }
.ui-acc .acc-body { padding: 0 16px 14px; font-size: 12.5px; color: var(--muted-foreground); }

/* score（pagespeed の PSI スコア表示: ≥90 good / 50–89 mid / <50 poor） */
.ui-score { display: inline-flex; align-items: center; justify-content: center; min-width: 40px; height: 40px; border-radius: 50%; font-family: var(--font-mono); font-size: 13px; font-weight: 500; border: 2px solid; padding: 0 4px; background: var(--card); }
.ui-score--good { color: var(--chart-2); border-color: var(--chart-2); background: color-mix(in srgb, var(--chart-2) 8%, var(--card)); }
.ui-score--mid { color: var(--chart-3); border-color: var(--chart-3); background: color-mix(in srgb, var(--chart-3) 10%, var(--card)); }
.ui-score--poor { color: var(--destructive); border-color: var(--destructive); background: color-mix(in srgb, var(--destructive) 8%, var(--card)); }
.ui-score--sm { min-width: 30px; height: 30px; font-size: 11px; border-width: 1.5px; }
.ui-score--lg { min-width: 52px; height: 52px; font-size: 16px; }

/* group divider（release タイムラインの日付 / タグ区切り行） */
.ui-group-divider { display: flex; align-items: center; gap: 10px; margin: 18px 0 10px; }
.ui-group-divider::after { content: ""; flex: 1; height: 1px; background: var(--border); }
.ui-group-divider .gchip { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--border); background: var(--secondary); border-radius: 999px; padding: 2px 10px; font-family: var(--font-mono); font-size: 11px; color: var(--secondary-foreground); }

/* link — foreground + 常時下線（07-23 決定・DESIGN.md §3.3。下線がリンクの識別子・hover で濃くなる） */
.ui-link { color: var(--foreground); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; text-decoration-color: color-mix(in srgb, var(--foreground) 35%, transparent); display: inline-flex; align-items: center; gap: 4px; transition: text-decoration-color var(--dur-fast) var(--ease); }
.ui-link:hover { text-decoration-color: var(--foreground); }
.ui-link--muted { color: var(--muted-foreground); text-decoration-color: color-mix(in srgb, var(--muted-foreground) 35%, transparent); }
.ui-link--muted:hover { color: var(--foreground); }

.ui-empty { text-align: center; padding: 40px 20px; color: var(--muted-foreground); font-size: 12.5px; }
.ui-empty .ic-wrap { width: 44px; height: 44px; border: 1.5px dashed var(--input); border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 12px; }
.ui-empty b { display: block; font-weight: 500; color: var(--foreground); margin-bottom: 2px; }

/* ========== feedback 部品 ========== */
.ui-alert { display: flex; gap: 10px; padding: 12px 14px; border: 1px solid; border-radius: var(--radius); font-size: 12.5px; align-items: flex-start; }
.ui-alert b { display: block; font-weight: 600; font-size: 13px; }
.ui-alert svg { margin-top: 2px; }
/* 強調ラダー（§23）: info = 無彩色 / success・warning = tint / error = ベタ塗り。
   warning と error は同色（--danger）で、差は「面の塗り方」だけで付ける */
.ui-alert--info { background: var(--muted); border-color: var(--border); }
.ui-alert--info svg { color: var(--muted-foreground); }
.ui-alert--success { background: color-mix(in srgb, var(--success) 7%, var(--card)); border-color: color-mix(in srgb, var(--success) 30%, transparent); }
.ui-alert--success svg { color: var(--success); }
.ui-alert--warning { background: color-mix(in srgb, var(--danger) 8%, var(--card)); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
.ui-alert--warning svg { color: var(--danger); }
.ui-alert--error { background: var(--danger-solid); border-color: var(--danger-solid); color: var(--danger-foreground); --knock: var(--danger-solid); }
.ui-alert--error svg { color: var(--danger-foreground); }

/* z-index 200（v1.11.0・50→200 是正）: jai-info の .ji-h5-shell（sticky header・z-100）を overlay の
   backdrop が確実に覆うため。info 側を下げる案は info v5.0.2 + 全 app vendor 差し替え連鎖（C-004 型）が
   必要になるため不採用 — uilib 側の値変更で吸収する（DESIGN.md §20） */
.ui-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.45); display: none; align-items: center; justify-content: center; z-index: 200; }
.ui-overlay.open { display: flex; }
.ui-dialog { background: var(--card); border: 1px solid var(--border); border-radius: calc(var(--radius) * 2); width: min(440px, calc(100vw - 48px)); padding: 24px; box-shadow: 0 16px 48px rgba(0,0,0,.18); animation: dlg-in var(--dur-base) var(--ease); }
@keyframes dlg-in { from { opacity: 0; transform: translateY(6px) scale(.98); } }
.ui-dialog h3 { font-family: var(--font-head); font-weight: 600; font-size: 15px; letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 8px; }
.ui-dialog p { font-size: 12.5px; color: var(--muted-foreground); }
.ui-dialog .dlg-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 20px; }

/* ========== command palette（既定ホットキー ⌘+K・Raycast 風 — Navigation 部品）==========
   構造: .ui-overlay.ui-overlay--top > .ui-cmdk（input 行 + list + foot）。
   uilibProto.commandPalette(opts) が生成・配線する（DESIGN.md §7 Navigation 参照）。
   ハイライト（.active）は一時的なフォーカス状態（hover 同等）なので §18 の黒 fill 対象外 = accent。
   トリガーは .ui-cmdk-btn（虫眼鏡 + placeholder + .ui-kbd の input 風ボタン） */
.ui-overlay--top { align-items: flex-start; padding-top: 14vh; }
/* 汎用キーボードヒント（ホットキー / esc 等の「薄い表示」の正） */
.ui-kbd { display: inline-flex; align-items: center; font-family: var(--font-mono); font-size: 10.5px; line-height: 1; color: var(--muted-foreground); background: var(--background); border: 1px solid var(--border); border-radius: 4px; padding: 3px 5px; }
.ui-cmdk { background: var(--popover); border: 1px solid var(--border); border-radius: calc(var(--radius) * 2); width: min(560px, calc(100vw - 48px)); box-shadow: 0 16px 48px rgba(0,0,0,.18); animation: dlg-in var(--dur-base) var(--ease); overflow: hidden; }
.ui-cmdk-input { display: flex; align-items: center; gap: 10px; padding: 0 16px; border-bottom: 1px solid var(--border); }
.ui-cmdk-input svg.ic { color: var(--muted-foreground); }
/* input と ghost（次の語の先出し・v1.18.0）を重ねる器。**ghost は input の下**に敷き、
   打った文字ぶんを不可視の複製で押し出すので、テキスト幅を実測しなくても続きの位置に出る。
   font まわりは input と 1 文字もずれてはいけないので同じ値を両方に書く（.typed が伸びる長さ = 実測値） */
.ui-cmdk-field { position: relative; flex: 1; min-width: 0; display: flex; }
.ui-cmdk-input input { flex: 1; border: none; outline: none; background: transparent; font-family: var(--font-sans); font-size: 15px; line-height: 22px; color: var(--foreground); padding: 14px 0; min-width: 0; position: relative; z-index: 1; }
.ui-cmdk-input input::placeholder { color: var(--muted-foreground); }
.ui-cmdk-ghost { position: absolute; inset: 0; display: flex; align-items: center; padding: 14px 0; font-family: var(--font-sans); font-size: 15px; line-height: 22px; white-space: pre; overflow: hidden; pointer-events: none; }
.ui-cmdk-ghost .typed { visibility: hidden; font-style: normal; }
.ui-cmdk-ghost .sfx { color: var(--muted-foreground); opacity: .62; font-style: normal; }
/* drill-down 中の現在階層 chip（虫眼鏡の右）。戻るヒントは入力空時の Backspace / esc */
.ui-cmdk-crumb { display: inline-flex; align-items: center; gap: 5px; flex: none; background: var(--secondary); border: 1px solid var(--border); color: var(--secondary-foreground); border-radius: 999px; padding: 2px 10px; font-size: 11.5px; white-space: nowrap; animation: chip-in var(--dur-base) var(--ease); }
.ui-cmdk-list { max-height: 340px; overflow-y: auto; padding: 6px; }
.ui-cmdk-group-head { padding: 8px 10px 4px; font-family: var(--font-head); font-weight: 500; font-size: 10px; letter-spacing: .2em; text-transform: uppercase; color: var(--muted-foreground); }
.ui-cmdk-item { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: calc(var(--radius) - 2px); font-size: 13px; color: var(--foreground); cursor: pointer; transition: background var(--dur-fast) var(--ease); }
.ui-cmdk-item.active { background: var(--accent); }
.ui-cmdk-item svg.ic { color: var(--muted-foreground); }
.ui-cmdk-item .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; } /* 左端の state 色 dot（左 = state の原則） */
.ui-cmdk-item .lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-cmdk-item.current .lbl { font-weight: 600; } /* 現在地（.ui-menu-item.current と同趣旨） */
.ui-cmdk-item .hint { font-size: 11.5px; color: var(--muted-foreground); flex: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 40%; }
.ui-cmdk-item .sc { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted-foreground); flex: none; }
.ui-cmdk-item .drill { display: flex; color: var(--muted-foreground); flex: none; } /* children 持ち = 下階層あり（右 = これから起きる遷移） */
.ui-cmdk-empty { padding: 24px 10px; font-size: 12px; color: var(--muted-foreground); text-align: center; }
.ui-cmdk-foot { display: flex; align-items: center; gap: 14px; padding: 7px 12px; border-top: 1px solid var(--border); font-size: 11px; color: var(--muted-foreground); }
.ui-cmdk-foot .fk { display: inline-flex; align-items: center; gap: 5px; }
/* トリガーボタン（input 風。placeholder テキストは任意 — 無しのコンパクト形も可） */
.ui-cmdk-btn { appearance: none; display: inline-flex; align-items: center; gap: 8px; background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); color: var(--muted-foreground); font-family: var(--font-sans); font-size: 12px; padding: 5px 7px 5px 10px; cursor: pointer; white-space: nowrap; transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-cmdk-btn:hover { border-color: color-mix(in srgb, var(--foreground) 22%, var(--border)); color: var(--foreground); }
.ui-cmdk-btn svg.ic { width: 14px; height: 14px; }
.ui-cmdk-btn .ph { margin-right: 14px; }
/* ghost 形（ヘッダー常駐向け・text-style）: ボタン・ホットキー表示とも枠/背景なし。虫眼鏡は太め・ホットキー表示と近接。
   押下（click / ホットキー）の瞬間は foreground へフラッシュして減衰（bindTrigger が .flash を付ける） */
.ui-cmdk-btn--ghost { border: none; background: transparent; padding: 4px 5px; gap: 4px; }
.ui-cmdk-btn--ghost:hover { color: var(--foreground); }
.ui-cmdk-btn--ghost svg.ic { width: 15px; height: 15px; stroke-width: 2.4; }
.ui-cmdk-btn--ghost .ui-kbd { border: none; background: transparent; padding: 0; font-size: 11px; }
.ui-cmdk-btn:active { color: var(--foreground); }
.ui-cmdk-btn.flash { animation: cmdk-press 0.4s var(--ease); } /* 0-40% は foreground → 残りで元色へ減衰 */
@keyframes cmdk-press { 0%, 40% { color: var(--foreground); } }

.ui-toasts { position: fixed; right: 20px; bottom: 20px; display: flex; flex-direction: column; gap: 8px; z-index: 60; }
.ui-toast { background: var(--foreground); color: var(--background); padding: 10px 14px; border-radius: var(--radius); font-size: 12.5px; display: flex; gap: 10px; align-items: center; box-shadow: 0 8px 24px rgba(0,0,0,.18); animation: toast-in var(--dur-base) var(--ease); }
/* ========== AI 演出（発光ガラス orb・§17）==========
   AI 起点であることは**色ではなく shader 演出**で示す。面は uilibProto.aiOrb() が canvas を敷く。
   ここにあるのは「canvas をどう嵌めるか」と、shader を使えないときのフォールバックだけ。 */
.ui-ai-orb, .ui-btn-ai { position: relative; overflow: hidden; isolation: isolate; }
/* canvas は正方形。長辺に合わせて中央から敷き、はみ出た分は overflow で切る
   （shader 側が円形フェードを持つので、横長の面では上下が切れて発光帯になる） */
/* canvas は z-index:-1 で内容の背面に落とす（親が isolation:isolate なので外へ抜けない）。
   ここで子全体に position:relative を配ると canvas まで in-flow に戻って面が膨らむので配らない */
.ui-ai-orb-canvas { position: absolute; left: 50%; top: 50%; width: calc(100% * var(--orb-scale, 1)); height: auto; aspect-ratio: 1; min-height: 100%; transform: translate(-50%, -50%); z-index: -1; pointer-events: none; }
/* 横長の面（uShape=1）では canvas が面と同じ形。縁は shader が面の輪郭で描くので拡大しない */
.ui-ai-orb-canvas--fit { left: 0; top: 0; width: 100%; height: 100%; aspect-ratio: auto; min-height: 0; transform: none; }

/* FAB 形態（円）— 面はページのテーマに追従する（light では明るいガラス玉になる）。
   icon の色と影も反転させる: light = 濃色 icon + 白影 / dark = 白 icon + 黒影（reference/index.html と同じ扱い） */
/* FAB / icon はテーマ追従の玉。下地は敷かない（写真の上で薄い円板が出るため）— 縁は shader のリムが担う */
.ui-ai-orb { width: 56px; height: 56px; border-radius: 50%; border: none; padding: 0; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; color: #17171c; background: transparent; }
.ui-ai-orb svg { width: 22px; height: 22px; fill: currentColor; stroke: none; filter: drop-shadow(0 1px 2px rgba(255,255,255,.55)); transition: transform var(--dur-base) var(--ease); }
.ui-ai-orb:hover svg { transform: scale(1.12); }
.dark .ui-ai-orb { color: #fff; }
.dark .ui-ai-orb svg { filter: drop-shadow(0 1px 5px rgba(0,0,0,.45)); }
.ui-ai-orb--sm { width: 40px; height: 40px; }
.ui-ai-orb--sm svg { width: 16px; height: 16px; }

/* ボタン形態（面に敷く）— AI 起点の主要アクション専用。同一画面に複数置かない。
   **FAB と同じ素材・同じ色味**にする（下地を黒で塗り分けない）。横長の面では canvas を面より大きく敷いて
   （--orb-scale）円形フェードを面の外へ追い出し、玉の中心部だけが見えるようにする —
   等倍だと左右の端がフェードで抜けて「途中から地の色」になる */
/* AI ボタンの面はテーマに追従する。light は shader の**インクモデル**（フロストガラス + 顔料の粒子 =
   紙から明度を引く）で面が立つので、地を暗く塗る必要はない。
   縁は 1px hairline + 実ドロップシャドウのみ（外側のグロー・虹リングは置かない — 08-12 ユーザー指示） */
.ui-btn-ai { background: transparent; border: none; color: #17171c; text-shadow: 0 1px 2px rgba(255,255,255,.5);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--foreground) 18%, transparent), 0 1px 2px rgba(0,0,0,.10); }
.ui-btn-ai:hover:not(:disabled) { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--foreground) 30%, transparent), 0 2px 4px rgba(0,0,0,.12); }
.dark .ui-btn-ai { color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.5); box-shadow: inset 0 0 0 1px rgba(255,255,255,.14); }
.dark .ui-btn-ai:hover:not(:disabled) { box-shadow: inset 0 0 0 1px rgba(255,255,255,.24); }
.ui-btn-ai svg.ic { stroke: none; fill: currentColor; filter: drop-shadow(0 1px 2px rgba(255,255,255,.5)); }
.dark .ui-btn-ai svg.ic { stroke: none; filter: drop-shadow(0 1px 3px rgba(0,0,0,.5)); }
.ui-btn-ai svg.ic { stroke: none; fill: currentColor; filter: drop-shadow(0 1px 2px rgba(255,255,255,.5)); }
.dark .ui-btn-ai svg.ic { filter: drop-shadow(0 1px 3px rgba(0,0,0,.5)); }
/* 面を敷かず icon だけ orb にする軽い形態（一覧行・メニュー等） */
.ui-ai-orb--icon { width: 22px; height: 22px; border-radius: 50%; flex: none; }

/* フォールバック（WebGL 不可・prefers-reduced-motion）: §17 の唯一の --ai 用途 */
.ui-ai-orb.is-fallback, .ui-btn-ai.is-fallback { background: var(--ai); color: var(--ai-foreground); }

/* 失敗 toast（§23）: 既定の黒 fill に対して、逸脱だけ朱のベタ塗りに差し替える */
.ui-toast--error { background: var(--danger-solid); color: var(--danger-foreground); --knock: var(--danger-solid); }
@keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }

.ui-progress { height: 6px; background: var(--muted); border-radius: 999px; overflow: hidden; border: 1px solid var(--border); }
.ui-progress > span { display: block; height: 100%; background: var(--foreground); border-radius: 999px; transition: width var(--dur-base) var(--ease); }
.ui-spinner { width: 18px; height: 18px; border: 2px solid var(--border); border-top-color: var(--foreground); border-radius: 50%; animation: ui-spin .7s linear infinite; }
@keyframes ui-spin { to { transform: rotate(360deg); } }
.ui-skeleton { background: linear-gradient(90deg, var(--muted) 25%, var(--accent) 50%, var(--muted) 75%); background-size: 200% 100%; animation: ui-sk 1.4s ease infinite; border-radius: var(--radius); }
@keyframes ui-sk { to { background-position: -200% 0; } }

.ui-timeline { display: flex; flex-direction: column; }
.tl-item { display: flex; gap: 14px; padding: 11px 0; border-bottom: 1px dashed var(--border); }
.tl-item:last-child { border-bottom: none; }
.tl-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--border); margin-top: 7px; flex: none; }
.tl-dot.ok { background: var(--success); } .tl-dot.warn { background: var(--danger); } .tl-dot.brand { background: var(--brand); }
.tl-body { flex: 1; font-size: 12.5px; }
.tl-body b { font-weight: 500; }
.tl-body .sub { display: block; font-size: 11.5px; color: var(--muted-foreground); }
.tl-time { font-family: var(--font-mono); font-size: 11px; color: var(--muted-foreground); flex: none; }

/* ========== ヘッダーの文法: scope / verbs / derived（DESIGN.md §22 — v1.12.0）==========
   ヘッダー = 文（subject / scope / verbs / search）。scope = 見ている対象の宣言（名詞・URL に載る）、
   verbs = action 群（動詞・URL に載らない）。search（⌕）は既存 .ui-cmdk-btn--ghost を
   version chip の右（identity 末尾）に置く — 専用 class は不要。 */

/* ---- DateScope pill（.ui-scope）: 粒度・期間・基準日の要約表示 + editor トリガー ---- */
.ui-scope { position: relative; display: inline-flex; flex: none; }
.ui-scope-pill { appearance: none; display: inline-flex; align-items: center; gap: 7px; background: var(--card); border: 1px solid var(--input); border-radius: 999px; padding: 4px 13px; cursor: pointer; font-family: var(--font-mono); font-size: 11.5px; font-variant-numeric: tabular-nums; color: var(--foreground); white-space: nowrap; transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease); }
.ui-scope-pill:hover { border-color: color-mix(in srgb, var(--foreground) 22%, var(--border)); }
.ui-scope-pill:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.ui-scope.open .ui-scope-pill { border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent); }
.ui-scope-pill .sep { color: var(--muted-foreground); opacity: .7; }
.ui-scope-pill .caret { display: inline-flex; color: var(--muted-foreground); transition: transform var(--dur-fast) var(--ease); }
.ui-scope-pill .caret svg { width: 12px; height: 12px; }
.ui-scope.open .ui-scope-pill .caret { transform: rotate(180deg); }

/* derived（集計結果 — read-only）: 枠なしの淡い数値のみ。hover で語に展開（§22。
   枠を持たせると押せそうに見え「scope 変更までの操作対象」が増えたと誤読されるため） */
/* 08-26 フィードバック④: .ih-actions が align-items:normal(=stretch) のため derived pill の
   テキストが上寄りになっていた（release 見本「128 件」で実測）。inline-flex + align-items:center
   で pill 自身の高さの中心にテキストを揃える（.ih-actions 側も align-items:center 済み・上記）。 */
.ui-scope-derived { display: inline-flex; align-items: center; font-family: var(--font-mono); font-size: 10.5px; font-variant-numeric: tabular-nums; color: var(--muted-foreground); opacity: .75; white-space: nowrap; cursor: default; transition: opacity var(--dur-fast) var(--ease); }
.ui-scope-derived .full { display: none; }
.ui-scope-derived:hover { opacity: 1; }
.ui-scope-derived:hover .short { display: none; }
.ui-scope-derived:hover .full { display: inline; }

/* ---- focusOnly（v1.29.0・ops FB）: pill 両脇の送りボタン + 常設 .ui-scope-nav ----
   editor を開かずに 1 単位ずつ移動できるよう pill と一体で描く。押しやすさより「範囲の存在感を
   消す」ことを優先し、‹ › は pill と同じ高さの枠なしボタン（hover で --accent 面のみ）。 */
.ui-scope-nav { position: relative; display: inline-flex; align-items: stretch; gap: 2px; }
.ui-scope-navbtn { appearance: none; border: none; background: transparent; border-radius: 999px; width: 22px; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; color: var(--muted-foreground); font-size: 13px; line-height: 1; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-scope-navbtn:hover:not(:disabled) { background: var(--accent); color: var(--foreground); }
.ui-scope-navbtn:focus-visible { outline: 2px solid var(--ring); outline-offset: -1px; }
.ui-scope-navbtn:disabled { opacity: .3; cursor: not-allowed; }
/* focusOnly の editor は面（カレンダー or brush）1つのみ（preset 列・sc-side 分割が無い）。
   v1.29.1・実機 FB: 通常 editor の min-width 432px を引きずり、幅約230pxのカレンダーが左に寄って
   右が空白になっていた不具合の修正 — brush 面とカレンダー面を同じ固定幅にし、上下左右 padding 12px
   で統一。カレンダーは幅が可変（196px）なので flex で中央に置く。brush は面の幅いっぱいに広げる */
.ui-scope--focus-only .ui-scope-pop { min-width: 0; width: 360px; }
.ui-scope--focus-only .ui-scope-pop .sc-head { padding: 12px; }
.ui-scope-pop .sc-focusonly-body { padding: 12px; box-sizing: border-box; display: flex; justify-content: center; }
.ui-scope-pop .sc-focusonly-body [data-brush] { width: 100%; }
.ui-scope-pop .sc-focusonly-body .ui-cal-focusbar { display: none; } /* 常時 focus モードなので案内文は不要 */

/* ---- scope editor（pill にアンカー・commit セマンティクス。Step 1 = 単位 + ショートカット + 基準日） ---- */
.ui-scope-pop { position: absolute; top: calc(100% + 6px); right: 0; z-index: 60; min-width: 432px; background: var(--popover); border: 1px solid var(--border); border-radius: calc(var(--radius) * 2); box-shadow: 0 12px 32px rgba(0,0,0,.14); display: none; overflow: hidden; }
.ui-scope-pop.open { display: block; animation: chip-in var(--dur-base) var(--ease); }
.ui-scope-pop .sc-head { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--border); }
.ui-scope-pop .sc-head .sc-lab { font-family: var(--font-head); font-weight: 500; font-size: 10px; letter-spacing: .2em; text-transform: uppercase; color: var(--muted-foreground); }
.ui-scope-pop .sc-head .ui-segment button { padding: 3px 13px; font-size: 11.5px; }
/* editor 上端の右肩（v1.15.1）: 「反映の仕方（即時 / 適用）」と「面（brush / カレンダー）」を並べる。
   どちらも **editor の設定** であって scope の値ではないため、値を編むコントロールとは行内で右に分離する */
.ui-scope-pop .sc-modeswitch { margin-left: auto; display: inline-flex; align-items: center; gap: 10px; flex: none; }
.ui-scope-pop .sc-live { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--muted-foreground); cursor: pointer; white-space: nowrap; }
/* 行の高さに収める（既定の .ui-switch は 34x20 で head 行には大きい） */
.ui-scope-pop .sc-live .ui-switch { width: 28px; height: 16px; }
.ui-scope-pop .sc-live .ui-switch .knob::before { width: 12px; height: 12px; left: 2px; top: 2px; }
.ui-scope-pop .sc-live .ui-switch input:checked + .knob::before { transform: translateX(12px); }
/* モード切替は icon のみの 2 択（単発トグルだとアイコンが「今の面」か「行き先」か読めない）。
   セレクタに .sc-head を含めるのは、上の `.sc-head .ui-segment button`（padding 3px 13px）に
   詳細度で勝つため — 単位 segmented と同じ横幅にするとアイコン 1 つに対して間延びする */
.ui-scope-pop .sc-head .sc-faces button { padding: 3px 9px; }
.ui-scope-pop .sc-faces svg { width: 13px; height: 13px; display: block; }
/* （v1.13.0 の enum フィールド行 `.sc-head--fields` / `.sc-fieldgrp` は v1.15.0 で撤去。
   DateScope は期間軸専用であり、device / 計測モード のような対象の宣言はページ側の segmented で行う — §22） */
.ui-scope-pop .sc-body { display: flex; }
.ui-scope-pop .sc-list { flex: 1; min-width: 160px; padding: 6px; display: flex; flex-direction: column; }
.ui-pop .sc-item, .ui-scope-pop .sc-item { display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: calc(var(--radius) - 2px); font-size: 12.5px; color: var(--foreground); cursor: pointer; white-space: nowrap; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-pop .sc-item:hover, .ui-scope-pop .sc-item:hover { background: var(--accent); }
/* selected = tonal（黒 fill ではない）: ショートカットは「常にどれか一つが有効・OFF 状態が無い」常設コントロールで、
   選択は介入ではなくビューの宣言。§18「目立たせるのは逸脱」に照らし .ui-segment と同じ減光表現にする。
   1 つの popover 内で黒 fill は「適用」（唯一の commit 動作）だけに絞る — 08-07 ユーザー指摘の tone down */
.ui-pop .sc-item.on, .ui-scope-pop .sc-item.on { background: var(--tab-neutral-fill); color: var(--foreground); } /* weight は変えない（layout shift ゼロ原則） */
.ui-pop .sc-item.ghost, .ui-scope-pop .sc-item.ghost { color: var(--muted-foreground); cursor: default; }
.ui-pop .sc-item.ghost:hover, .ui-scope-pop .sc-item.ghost:hover { background: transparent; }
.ui-pop .sc-item.on::after, .ui-scope-pop .sc-item.on::after { content: ""; width: 5px; height: 5px; border-radius: 50%; background: color-mix(in srgb, var(--foreground) 55%, transparent); margin-left: auto; flex: none; }
.ui-pop .sc-item .tag, .ui-scope-pop .sc-item .tag { margin-left: auto; font-family: var(--font-mono); font-size: 9px; color: var(--muted-foreground); border: 1px solid var(--border); border-radius: 4px; padding: 0 5px; }
.ui-scope-pop .sc-side { min-width: 252px; border-left: 1px solid var(--border); padding: 12px 14px; display: flex; flex-direction: column; gap: 12px; }
.ui-scope-pop .sc-side .sc-lab { font-family: var(--font-head); font-weight: 500; font-size: 10px; letter-spacing: .2em; text-transform: uppercase; color: var(--muted-foreground); margin-bottom: 5px; }
.ui-scope-pop .sc-range { font-family: var(--font-mono); font-size: 11px; font-variant-numeric: tabular-nums; color: var(--foreground); }
.ui-scope-pop .sc-range .dash { color: var(--muted-foreground); margin: 0 4px; }
.ui-scope-pop .sc-hint { font-size: 10.5px; color: var(--muted-foreground); line-height: 1.5; }
.ui-scope-pop .sc-foot { display: flex; align-items: center; gap: 8px; padding: 9px 12px; border-top: 1px solid var(--border); background: var(--muted); }
.ui-scope-pop .sc-foot .ui-btn { white-space: nowrap; flex: none; }
.ui-scope-pop .sc-prev { margin-right: auto; font-family: var(--font-mono); font-size: 10px; font-variant-numeric: tabular-nums; color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-scope-pop .sc-prev b { color: var(--brand); font-weight: 600; }
.dark .ui-scope-pop .sc-foot { background: var(--secondary); }

/* 基準日ステッパー（‹ val ▾ ›・操作点はここ 1 箇所 — §22） */
.ui-scope-stp { display: inline-flex; align-items: stretch; border: 1px solid var(--input); border-radius: var(--radius); overflow: hidden; background: var(--card); }
.ui-scope-stp button { appearance: none; border: none; background: transparent; cursor: pointer; color: var(--muted-foreground); font-size: 12px; padding: 3px 8px; display: inline-flex; align-items: center; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-scope-stp button:hover:not(:disabled) { background: var(--accent); color: var(--foreground); }
.ui-scope-stp button:disabled { opacity: .35; cursor: not-allowed; }
.ui-scope-stp .val { border-left: 1px solid var(--border); border-right: 1px solid var(--border); font-family: var(--font-mono); font-size: 11px; font-variant-numeric: tabular-nums; color: var(--foreground); padding: 3px 10px; gap: 5px; }
.ui-scope-stp .val svg { width: 11px; height: 11px; color: var(--muted-foreground); }

/* ---- verbs split-button（.ui-splitbtn）: 結合グループ + 融合 ▾。選択状態を持たない（§22 の線引き） ---- */
.ui-splitbtn { position: relative; display: inline-flex; flex: none; border: 1px solid var(--input); border-radius: var(--radius); background: var(--card); }
.ui-splitbtn > button { appearance: none; border: none; background: transparent; cursor: pointer; color: var(--muted-foreground); font-family: var(--font-sans); font-size: 12px; padding: 5px 10px; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-splitbtn > button + button { border-left: 1px solid var(--border); }
.ui-splitbtn > button:first-child { border-radius: calc(var(--radius) - 1px) 0 0 calc(var(--radius) - 1px); }
.ui-splitbtn > button:last-child { border-radius: 0 calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0; }
.ui-splitbtn > button:only-child { border-radius: calc(var(--radius) - 1px); }
.ui-splitbtn > button:hover { background: var(--accent); color: var(--foreground); }
.ui-splitbtn > button:active { background: var(--accent); color: var(--foreground); }
.ui-splitbtn > button:focus-visible { outline: 2px solid var(--ring); outline-offset: -2px; }
.ui-splitbtn > button svg.ic { width: 14px; height: 14px; }
.ui-splitbtn > button.sb-dd { padding: 5px 7px; }
.ui-splitbtn > button.sb-dd svg.ic { width: 13px; height: 13px; }
.ui-splitbtn > button.sb-dd.open { background: var(--accent); color: var(--foreground); }
.ui-splitbtn .ui-menu { top: calc(100% + 6px); left: auto; right: 0; }

/* ---- 汎用アンカー popover（date picker / range picker。配置は scPlacePop が計算 — v1.12.0） ---- */
.ui-pop-anchor { position: relative; display: inline-flex; }
.ui-pop { position: absolute; top: calc(100% + 6px); right: 0; z-index: 60; background: var(--popover); border: 1px solid var(--border); border-radius: calc(var(--radius) * 2); box-shadow: 0 12px 32px rgba(0,0,0,.14); display: none; overflow: hidden; }
.ui-pop.open { display: block; animation: chip-in var(--dur-base) var(--ease); }
.ui-pop-body { padding: 12px 14px; }
.ui-pop-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 9px 12px; border-top: 1px solid var(--border); background: var(--muted); }
.dark .ui-pop-foot { background: var(--secondary); }
.ui-pop-foot .ui-btn { white-space: nowrap; flex: none; }
.ui-pop-foot .ro { margin-right: auto; font-family: var(--font-mono); font-size: 10px; font-variant-numeric: tabular-nums; color: var(--muted-foreground); white-space: nowrap; }

/* ---- date picker / range picker トリガー（input 風） ---- */
.ui-datebtn { appearance: none; display: inline-flex; align-items: center; gap: 8px; background: var(--card); border: 1px solid var(--input); border-radius: var(--radius); padding: 6px 12px; cursor: pointer; font-family: var(--font-mono); font-size: 12px; font-variant-numeric: tabular-nums; color: var(--foreground); white-space: nowrap; transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease); }
.ui-datebtn svg.ic { width: 14px; height: 14px; color: var(--muted-foreground); }
.ui-datebtn:hover { border-color: color-mix(in srgb, var(--foreground) 22%, var(--border)); }
.ui-datebtn:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.ui-pop-anchor.open .ui-datebtn { border-color: var(--ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent); }
.ui-datebtn span.ph { color: var(--muted-foreground); }

/* ---- calendar primitive（.ui-cal — 週起点 = 月曜・DESIGN.md §22・v1.12.0）----
   選択の視覚: 端点 = 黒 fill（selected は黒 fill・§7）/ 範囲内 = brand 淡色面 / 選択途中（tmp）= 減光。
   today は下部の brand dot（枠や fill を使わない — 「今日」は選択状態ではないため） */
.ui-cal { user-select: none; }
.ui-cal-head { display: flex; align-items: center; gap: 4px; margin-bottom: 4px; }
.ui-cal-nav { appearance: none; width: 24px; height: 24px; border: none; background: transparent; border-radius: 6px; color: var(--muted-foreground); cursor: pointer; font-size: 13px; line-height: 1; display: grid; place-items: center; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.ui-cal-nav:hover { background: var(--accent); color: var(--foreground); }
.ui-cal-title { flex: 1; text-align: center; font-family: var(--font-mono); font-size: 11px; font-variant-numeric: tabular-nums; color: var(--foreground); }
.ui-cal-grid { display: grid; grid-template-columns: repeat(7, 28px); }
.ui-cal-dow { font-style: normal; font-family: var(--font-mono); font-size: 9px; color: var(--muted-foreground); text-align: center; padding: 3px 0 5px; }
.ui-cal-day { position: relative; height: 27px; display: grid; place-items: center; font-family: var(--font-mono); font-size: 10.5px; font-weight: 400; font-variant-numeric: tabular-nums; color: var(--foreground); cursor: pointer; border-radius: 6px; transition: background var(--dur-fast) var(--ease); }
.ui-cal-day:hover { background: var(--accent); }
.ui-cal-day.out { color: var(--muted-foreground); opacity: .45; }
.ui-cal-day.today::after { content: ""; position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%); width: 3px; height: 3px; border-radius: 50%; background: var(--brand); }
.ui-cal-day.rng { background: color-mix(in srgb, var(--foreground) 8%, transparent); border-radius: 0; }
/* 範囲は黒系ニュートラルの階調（端点 = 黒を少し落とした面 / 範囲内 = 同色の薄面）。brand は使わない —
   差し色は「逸脱」に取っておく（§18）。violet/indigo は event 固有色のため選択アクセントに使わない */
.ui-cal-day.edge { background: color-mix(in srgb, var(--foreground) 55%, var(--background)); color: var(--background); border-radius: 6px; }
.ui-cal-day.edge.today::after { background: var(--background); }
.ui-cal-day.tmp, .ui-cal-mon.tmp { opacity: .8; } /* 選択途中（2 クリック目待ち）のプレビュー */
.ui-cal-months { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; min-width: 196px; }
.ui-cal-mon { display: grid; place-items: center; height: 30px; font-family: var(--font-mono); font-size: 11px; border-radius: 6px; cursor: pointer; color: var(--foreground); transition: background var(--dur-fast) var(--ease); }
.ui-cal-mon:hover { background: var(--accent); }
.ui-cal-mon.rng { background: color-mix(in srgb, var(--foreground) 8%, transparent); }
.ui-cal-mon.edge { background: color-mix(in srgb, var(--foreground) 55%, var(--background)); color: var(--background); }

/* ---- range picker の 2 カラム（左 = ショートカット sc-list / 右 = calendar — GA4 型・v1.12.0） ---- */
.ui-pop-cols { display: flex; }
.ui-pop-cols .ui-pop-body { border-left: 1px solid var(--border); }
.ui-pop .sc-list { min-width: 148px; padding: 6px; display: flex; flex-direction: column; }
.ui-pop-foot .ro b { color: var(--brand); font-weight: 600; }

/* ---- 基準日（focus）: 直接入力 + カレンダー選択モード（v1.12.0・08-07 ユーザー指摘への対応）---- */
.ui-cal-focusbar { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; padding: 4px 7px; border-radius: var(--radius); background: var(--muted); font-size: 10px; line-height: 1.4; color: var(--muted-foreground); white-space: nowrap; }
.ui-cal-focusbar svg.ic { width: 12px; height: 12px; flex: none; }
.dark .ui-cal-focusbar { background: var(--secondary); }
.ui-cal-focusbar b { color: var(--foreground); font-weight: 500; }
.ui-cal--focus .ui-cal-day.rng, .ui-cal--focus .ui-cal-mon.rng { opacity: .5; }
.ui-cal--focus .ui-cal-day.edge, .ui-cal--focus .ui-cal-mon.edge { opacity: .5; }
/* 基準日 = この面で最も強い（08-07 ユーザー指示: 範囲の両端より基準日の tone を強く）。
   階層は 基準日（黒 fill）> 範囲の両端（foreground 55% の面）> 範囲内（同 8% の薄面） */
.ui-cal-day.foc, .ui-cal-mon.foc { background: var(--foreground); color: var(--background); opacity: 1 !important; border-radius: 6px; }
.ui-cal-day.foc.today::after { background: var(--background); }
.ui-scope-stp .val-in { width: 84px; border: none; background: transparent; font-family: var(--font-mono); font-size: 11px; font-variant-numeric: tabular-nums; color: var(--foreground); padding: 3px 8px; border-left: 1px solid var(--border); border-right: 1px solid var(--border); text-align: center; }
.ui-scope-stp .val-in:focus { outline: none; background: var(--accent); }
.ui-scope-stp .val-in.invalid { color: var(--destructive); }
.ui-scope-pop .sc-focusmode { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; font-size: 11px; color: var(--muted-foreground); border: 1px solid var(--input); background: var(--card); border-radius: var(--radius); padding: 3px 9px; cursor: pointer; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease); }
.ui-scope-pop .sc-focusmode:hover { border-color: color-mix(in srgb, var(--foreground) 22%, var(--border)); color: var(--foreground); }
.ui-scope-pop .sc-focusmode.on { background: var(--tab-neutral-fill); color: var(--foreground); border-color: transparent; }
.ui-scope-pop .sc-focusmode svg { width: 12px; height: 12px; }
/* 基準日モードで範囲外の日 = 無効（範囲内の 1 日にしか基準日は置けない） */
.ui-cal--focus .ui-cal-day.off, .ui-cal--focus .ui-cal-mon.off { color: var(--muted-foreground); opacity: .3; cursor: not-allowed; }
.ui-cal--focus .ui-cal-day.off:hover, .ui-cal--focus .ui-cal-mon.off:hover { background: transparent; }

/* ---- scope brush（別案: 基準日を先に置き span を後から動かす — DESIGN.md §22・v1.12.0）----
   tone の階層は calendar と同じ: 基準日（黒）> 範囲（薄面 + 端のハンドル）> 範囲外（veil で減光） */
.ui-brush { user-select: none; }
.ui-brush-strip { position: relative; height: 52px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--card); overflow: hidden; cursor: crosshair; touch-action: none; }
.ui-brush-strip:focus-visible { outline: 2px solid var(--ring); outline-offset: 2px; }
.ui-brush-spark { position: absolute; inset: 0; width: 100%; height: 100%; color: var(--muted-foreground); opacity: .55; pointer-events: none; }
/* 範囲外は veil で落とす（範囲を「塗る」のではなく外を沈める — 面の主役を範囲内に置く） */
.ui-brush-veil { position: absolute; top: 0; bottom: 0; background: color-mix(in srgb, var(--foreground) 11%, transparent); pointer-events: none; }
.ui-brush-veil--l { left: 0; }
.ui-brush-span { position: absolute; top: 0; bottom: 0; background: transparent; border-left: 1px solid color-mix(in srgb, var(--foreground) 45%, transparent); border-right: 1px solid color-mix(in srgb, var(--foreground) 45%, transparent); cursor: grab; }
.ui-brush.dragging .ui-brush-span { cursor: grabbing; }
.ui-brush-h { position: absolute; top: 0; bottom: 0; width: 11px; cursor: ew-resize; display: flex; align-items: center; justify-content: center; }
.ui-brush-h::after { content: ""; width: 3px; height: 18px; border-radius: 999px; background: color-mix(in srgb, var(--foreground) 55%, var(--background)); transition: background var(--dur-fast) var(--ease); }
.ui-brush-h:hover::after { background: var(--foreground); }
.ui-brush-h--l { left: -6px; }
.ui-brush-h--r { right: -6px; }
/* 基準日 = この面で最も強い（黒の縦線 + キャップ） */
.ui-brush-focus { position: absolute; top: 0; bottom: 0; width: 0; border-left: 2px solid var(--foreground); transform: translateX(-1px); cursor: ew-resize; }
.ui-brush-focus::before { content: ""; position: absolute; top: 0; bottom: 0; left: -7px; width: 16px; } /* 掴みしろ */
.ui-brush-focus .cap { position: absolute; top: 3px; left: 50%; transform: translateX(-50%); background: var(--foreground); color: var(--background); font-family: var(--font-mono); font-size: 9.5px; font-variant-numeric: tabular-nums; line-height: 1; padding: 3px 6px; border-radius: 999px; white-space: nowrap; pointer-events: none; }
.ui-brush-axis { position: relative; height: 15px; margin-top: 5px; }
.ui-brush-axis span { position: absolute; transform: translateX(-50%); font-family: var(--font-mono); font-size: 9.5px; font-variant-numeric: tabular-nums; color: var(--muted-foreground); white-space: nowrap; }
.ui-brush-axis span:first-child { transform: none; }
.ui-brush-axis span:last-child { transform: translateX(-100%); }

/* noSpan（v1.29.1・focusOnly の brush 面）: 範囲の概念が無いため span / ハンドル / veil を描かない —
   基準日（黒の縦線）とスパークライン・目盛だけが残る、ストリップ全体が「基準日を置く」操作になる */
.ui-brush--nospan .ui-brush-span, .ui-brush--nospan .ui-brush-veil, .ui-brush--nospan .ui-brush-foot { display: none; }
.ui-brush--nospan .ui-brush-strip { cursor: pointer; }

/* ---- DateScope の brush 展開版（editor の第一面が直接操作面 — DESIGN.md §22・v1.12.0）---- */
/* 幅は .ui-scope-pop の min-width（432px）に揃える — brush ⇄ カレンダーの切替でパネル幅が変わると
   カーソルが外へ出て閉じてしまうため（08-07 ユーザー指摘） */
.ui-scope-pop .sc-brushwrap { padding: 12px 16px 2px; }
.ui-scope-pop .sc-quick { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 10px 16px; }
.ui-scope-pop .sc-quick + .sc-quick { padding-top: 9px; }
.ui-scope-pop .sc-chip { appearance: none; border: 1px solid var(--input); background: var(--card); border-radius: 999px; padding: 3px 11px; font-size: 11.5px; color: var(--muted-foreground); cursor: pointer; white-space: nowrap; transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease); }
.ui-scope-pop .sc-chip:hover { border-color: color-mix(in srgb, var(--foreground) 22%, var(--border)); color: var(--foreground); }
/* selected = tonal（黒 fill は「適用」に残す — §22 の tone 階層） */
.ui-scope-pop .sc-chip.on { background: var(--tab-neutral-fill); color: var(--foreground); border-color: transparent; }
/* 基準日の固定トグル（brush の脚。既定 off = 期間を動かすと基準日も付いてくる） */
.ui-brush-foot { display: flex; align-items: center; gap: 7px; margin-top: 8px; font-size: 11.5px; color: var(--foreground); cursor: pointer; user-select: none; }
.ui-brush-foot .hint { color: var(--muted-foreground); font-size: 10.5px; }

/* 窓幅の読み（brush 上部）— 単位で scale が変わったことを明示する */
.ui-brush-win { display: flex; align-items: baseline; gap: 8px; margin-bottom: 5px; font-size: 10.5px; color: var(--muted-foreground); }
.ui-brush-win b { color: var(--foreground); font-weight: 600; font-family: var(--font-mono); font-size: 11px; }
.ui-brush-win .rng { margin-left: auto; font-family: var(--font-mono); font-size: 9.5px; font-variant-numeric: tabular-nums; opacity: .8; }
/* 編集中の backdrop（外側クリックで閉じることを示す薄い面。hover-out では閉じない） */
.ui-pop-backdrop { position: fixed; inset: 0; z-index: 55; background: color-mix(in srgb, var(--foreground) 7%, transparent); animation: chip-in var(--dur-base) var(--ease); }
/* 基準日ステッパーの端ジャンプ（|‹ ›|） */
.ui-scope-stp button[data-edge] { font-family: var(--font-mono); font-size: 10.5px; letter-spacing: -.05em; }
/* 基準日グループ内の「固定」トグル */
.ui-scope-pop .sc-pin { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--muted-foreground); cursor: pointer; user-select: none; white-space: nowrap; }
.ui-scope-pop .sc-pin:has(input:checked) { color: var(--foreground); }
.ui-scope-pop .sc-pin .ui-check { width: 13px; height: 13px; }
.ui-scope-stp .val-in { width: 94px; }

/* ========== 指定文法: 意味色（hue）× 強さ（strength）（v1.21.0・DESIGN.md §24）==========
   state 表現部品（badge / chip / alert 等「色を受ける面」）の色指定を「意味色 × 強さ」の
   直交 2 軸に分離する。従来の ui-badge--warning 等は (hue, strength) が 1 語に潰れた旧語彙として
   凍結維持（§5: 削除しない・値も変えない）。action 導線（.ui-btn 系）は閉集合のまま —
   §18「強調は state 表現のみ」。強さの 4 段は §23 の強調ラダーの実装:
     fill = L2 逸脱（ベタ塗り + knock icon）/ tonal = L1 注意（tint 面 + 枠 35%）/
     outline = 枠のみ / ghost = 文字のみ。
   意味色は status の閉集合（§23 Riso 2 色 + brand + neutral）。任意色（カテゴリ /
   アイデンティティ色 — 例: Fleet の fable = violet）は語彙を増やさず、消費側が
   --hue / --on-hue を上書きして注入する（何%で混ぜるか・knock の作法・dark 追従という
   「レシピ」は uilib が独占所有し、消費側には identity の 1 行だけが残る）。
   枠線そのもの（border-style/width）は部品が持つ — 文法が塗るのは色チャンネルだけ。
   同一要素で旧 variant と併用しない（後勝ちでこちらが効く）。 */
.ui-neutral { --hue: var(--foreground); --on-hue: var(--background); }
.ui-brand   { --hue: var(--brand); --on-hue: var(--brand-foreground); }
.ui-success { --hue: var(--success); --on-hue: var(--success-foreground); }
/* danger は §23 の 2 トークン構造を内蔵: tint・文字 = --danger / ベタ塗り面 = --danger-solid。
   fill にすると自動で solid 側に切り替わるので、消費側が §23 を知らなくても踏み外せない */
.ui-danger  { --hue: var(--danger); --hue-solid: var(--danger-solid); --on-hue: var(--danger-foreground); }

.ui-fill, .ui-tonal, .ui-outline, .ui-ghost { background: var(--_bg); color: var(--_fg); border-color: var(--_bd); }
.ui-fill {
  --_bg: var(--hue-solid, var(--hue, var(--foreground)));
  --_fg: var(--on-hue, var(--background));
  --_bd: var(--_bg);
  --knock: var(--_bg); /* fill icon（§23.3）の抜き色が自動で面色になる */
}
.ui-tonal {
  --_bg: color-mix(in srgb, var(--hue, var(--foreground)) 10%, var(--card));
  --_fg: var(--hue, var(--foreground));
  --_bd: color-mix(in srgb, var(--hue, var(--foreground)) 35%, transparent);
}
.ui-outline {
  --_bg: transparent;
  --_fg: var(--hue, var(--foreground));
  --_bd: color-mix(in srgb, var(--hue, var(--foreground)) 45%, transparent);
}
.ui-ghost { --_bg: transparent; --_fg: var(--hue, var(--foreground)); --_bd: transparent; }

/* ---- 部品アダプタ（一般式が部品の配色文法と食い違う箇所だけ最小で書く）---- */
/* alert の tonal: 本文は foreground のまま・意味色は icon にだけ（旧 --success / --warning と同じ文法）。
   fill はアダプタ不要（--_fg が全体に乗る = 旧 --error と同じ） */
.ui-alert.ui-tonal { color: var(--foreground); }
.ui-alert.ui-tonal svg { color: var(--_fg); }
/* chip の fill: × ボタンが muted のままだとベタ塗り面で読めない */
.ui-chip.ui-fill button { color: var(--_fg); opacity: .75; }
.ui-chip.ui-fill button:hover { color: var(--_fg); opacity: 1; background: color-mix(in srgb, var(--_fg) 18%, transparent); }
/* ========== comp layout 層: container size 応答（v1.22.0・DESIGN.md §25）==========
   最終ゴールはページのモバイル（狭幅）対応。comp の size は viewport ではなく「置かれた
   container の幅」で決まるべきで、かつ一律縮小ではなく重要度に応じて配下ごとに落ち方が
   違うべき（2026-08-19 ユーザー提起）。

   [spike 結果・Chrome 151 実測]: 当初案（.ui-imp-N が自分自身に --ui-cq を宣言し、同じ要素を
   @container style(--ui-cq: xs) で読む）は不成立。style() クエリは「クエリされる要素自身」
   ではなく「最も近い祖先コンテナ」で計算した値を見る仕様（size クエリと同じ自己参照防止の
   設計 — 実測: 対象要素に直接セットした値は無視され、祖先要素の値だけが見える。祖先/子で
   別値を張った検証で再現・別ファイルに退避した最小 repro で確認済み）。カスタムプロパティの
   量子化 + style query という主案は、部品自身に注釈クラスを付ける想定の作りとは構造的に噛み
   合わないため、退避方式へ切替:
   → カスタムプロパティの量子化は行わず、各部品が `@container ui (width < Npx)` の閾値
     リテラルを直接書く。重要度はセレクタ（`.ui-imp-3.ui-xxx` で閾値を1段上げる＝早く譲る／
     `.ui-imp-1.ui-xxx` で1段下げる＝粘る／無注釈 = imp-2 が基準の閾値）で表す。
   写像表（唯一のソース。閾値を変えるときはこのコメントと下の @container の数値を両方直す）:
     xs < 420px / sm < 680px / md < 1000px / lg < 1360px / xl ≥ 1360px
   （spike の詳細 → DESIGN.md §25.3・badge/chip の既存 specificity bug → CONCERNS.md C-285）

   [軌道修正・08-21 ユーザー確定・DESIGN.md §25.1b（C-288）]: container 応答の本線は
   **wrapper（card / header / form 等の複合 comp）が配下の「配置（layout）」を組み替える**こと。
   atomic comp（badge/chip/btn 等）は「サイズを段トークン単位で丸ごと切り替える」ことだけが
   許容範囲で、**内部を部分ごとに細かく変える（本文だけ ellipsis 化する等）のは非推奨** —
   badge/chip/btn の一括降格層（下記パイロット (1)(2)）はこの許容範囲に収まるためそのまま維持し、
   alert の内部畳み（本文だけを ellipsis 化する旧パイロット (3)）は撤回した。撤回の詳細・経緯は
   CONCERNS.md C-288 参照。 */

/* ---- 測る層 ----
   .ui-ih-shell（header shell wrapper・v1.23.0）も自分自身を container にする（.ui-form と同じ前例）。
   shell 単体で使うページ（page 側に .ui-container 祖先が無くても）狭幅応答が発動するのはこのため。 */
.ui-container, .ui-ih-shell { container-type: inline-size; container-name: ui; }

/* ---- 方針層（純粋なセレクタフック。宣言は持たない — 実体は各部品の @container ui(...)
   閾値の選び方に現れる。祖先に .ui-container が無ければ selector ごと不成立＝無風） ---- */
/* .ui-imp-1 = 主役: 最後まで譲らない（1つ下の段の閾値まで粘る） */
/* .ui-imp-3 = 添え物: 最初に譲る（1つ上の段の閾値で早々に降格） */
/* 無注釈 = imp-2（既定の閾値） */

/* ---- 部品層: パイロット (1) badge / chip — 一律降格（layout は変えない最小例）。
   sm 段以下で --sm 相当のメトリクスへ自動降格する。明示 size class（--sm/--lg）は
   セレクタから除外して常に auto に勝たせる（:where() による zero-specificity ではなく :not()
   除外を選んだ理由: .ui-badge--sm 等の size modifier は既存コードの都合で base .ui-badge より
   前に定義されており同 specificity では base が後勝ちする — :where() で auto 側の specificity を
   0 にすると base(0,1,0) にも負けて降格が一切効かなくなる。.ui-container .ui-badge:not(明示class)
   は 0,2,0 相当で base に常に勝ち、明示 class が付いた要素には selector ごとマッチしないため
   干渉しない） ---- */
@container ui (width < 1000px) {
  .ui-container .ui-badge.ui-imp-3:not(.ui-badge--sm):not(.ui-badge--lg) { font-size: 10px; padding: 1px 7px; }
  .ui-container .ui-chip.ui-imp-3:not(.ui-chip--sm) { font-size: 11px; padding: 1px 4px 1px 8px; }
}
@container ui (width < 680px) {
  .ui-container .ui-badge:not(.ui-imp-1):not(.ui-imp-3):not(.ui-badge--sm):not(.ui-badge--lg) { font-size: 10px; padding: 1px 7px; }
  .ui-container .ui-chip:not(.ui-imp-1):not(.ui-imp-3):not(.ui-chip--sm) { font-size: 11px; padding: 1px 4px 1px 8px; }
}
@container ui (width < 420px) {
  .ui-container .ui-badge.ui-imp-1:not(.ui-badge--sm):not(.ui-badge--lg) { font-size: 10px; padding: 1px 7px; }
  .ui-container .ui-chip.ui-imp-1:not(.ui-chip--sm) { font-size: 11px; padding: 1px 4px 1px 8px; }
}

/* ---- 部品層: パイロット (2) .ui-btn — sm 段で -sm メトリクスへ降格（action 導線なので
   §24 の hue×strength 対象外だが、container layout（見た目の寸法）は対象） ---- */
@container ui (width < 1000px) {
  .ui-container .ui-btn.ui-imp-3:not(.ui-btn-sm):not(.ui-btn--sm):not(.ui-btn-lg):not(.ui-btn--lg) { padding: 5px 11px; font-size: 12px; }
}
@container ui (width < 680px) {
  .ui-container .ui-btn:not(.ui-imp-1):not(.ui-imp-3):not(.ui-btn-sm):not(.ui-btn--sm):not(.ui-btn-lg):not(.ui-btn--lg) { padding: 5px 11px; font-size: 12px; }
}
@container ui (width < 420px) {
  .ui-container .ui-btn.ui-imp-1:not(.ui-btn-sm):not(.ui-btn--sm):not(.ui-btn-lg):not(.ui-btn--lg) { padding: 5px 11px; font-size: 12px; }
}

/* alert の内部畳み（本文だけを 1 行 ellipsis に畳む実装）は §25.1b により不採用（C-288）。
   atomic comp の内部を部分的に変えるのは非推奨 — サイズの丸ごと切替（パイロット (1)(2)）だけが許容範囲。 */

/* ---- wrapper 層: パイロット .ui-stat-row（card 群の配置組み替え — §25.1b の本線）。
   祖先 .ui-container 配下でのみ発動: 横並び（auto-fit） → 2 列 → 縦積み、と grid-template-columns
   を組み替える。1 枚だけ .ui-imp-3 を付けた stat（添え物）は sm 段で先に全幅帯へ降りて場所を譲る
   （§25 の .ui-imp-N の主用途 = 「wrapper が配置を組み替えるとき、どの配下から場所を譲るか」）。 */
@container ui (width < 680px) {
  .ui-container .ui-stat-row { grid-template-columns: repeat(2, 1fr); }
  /* 配置を譲る = imp-3 が先に全幅帯へ降りる（他の imp-2 stat より先に場所を空ける） */
  .ui-container .ui-stat.ui-imp-3 { grid-column: 1 / -1; padding: 12px 16px; }
}
@container ui (width < 420px) {
  .ui-container .ui-stat-row { grid-template-columns: 1fr; }
}

/* ---- wrapper 層: .ui-page-header（fleet の「狭い窓では actions が 1 行チップに畳む」判例の
   uilib 版）。sm 段で title-block（左）と actions（右）の横並びをやめ、actions がタイトル下の
   行へ降りて折り返す。汎用部品で全ページに使われているため、必ず .ui-container 祖先を要求する
   セレクタのみで書く（container 宣言が無いページは無風のまま）。 ---- */
@container ui (width < 680px) {
  .ui-container .ui-page-header { flex-direction: column; align-items: stretch; gap: 14px; }
  .ui-container .ui-page-header .actions { justify-content: flex-start; flex-wrap: wrap; }
}

/* ---- wrapper 層: .ui-toolbar（search + controls の1行）。sm 段で search を全幅の先頭行へ
   降ろし、残りの controls を2行目へ折り返す（search が「主役」= 常に全幅を確保する側）。 ---- */
@container ui (width < 680px) {
  .ui-container .ui-toolbar { flex-wrap: wrap; }
  .ui-container .ui-toolbar .search { flex-basis: 100%; max-width: none; order: -1; }
}

/* ---- wrapper 層: .ui-card-grid（auto-fill カード列）。sm 段で 2 列に固定し、.ui-imp-3
   （添え物カード）は stat-row と同じ「先に全幅帯へ降りて場所を譲る」パターンで 1/-1 にする
   （xs 段ではなく sm 段に入れる点に注意 — 添え物は他のカードより先に譲るのが趣旨）。
   xs 段はさらに 1 列へ縮める。 ---- */
@container ui (width < 680px) {
  .ui-container .ui-card-grid { grid-template-columns: repeat(2, 1fr); }
  .ui-container .ui-card-grid > .ui-imp-3 { grid-column: 1 / -1; }
}
@container ui (width < 420px) {
  .ui-container .ui-card-grid { grid-template-columns: 1fr; }
}

/* ---- wrapper 層: .ui-steps（横並びのステップ導線）。xs 段で縦積みに組み替える。区切り線
   （.ui-step-sep）は横方向の短い線分で、縦積みでは意味を持たないため同じ段で非表示にする。 ---- */
@container ui (width < 420px) {
  .ui-container .ui-steps { flex-direction: column; align-items: flex-start; gap: 8px; }
  .ui-container .ui-step-sep { display: none; }
}

/* ---- wrapper 層: .ui-list .lrow（Version History・280px 実測・ユーザー指摘）。1行のまま
   横に詰めると版番号（.body b）と日時（.meta）が同じ行の幅を奪い合って衝突する。xs 段では
   order で並びを組み替え、st + body（版番号 + タイトルは元々 body 内部で2行に分かれている）
   + act を1行目に、meta（日時）だけ flex-basis:100% の強制改行トリックで独立した行へ落とす
   （padding-left は st の幅 15px + gap 14px = 29px に揃え、テキストの開始位置に合わせる）。 ---- */
@container ui (width < 420px) {
  .ui-container .ui-list .lrow { flex-wrap: wrap; row-gap: 2px; }
  .ui-container .ui-list .lrow .st { order: 1; }
  .ui-container .ui-list .lrow .body { order: 2; }
  .ui-container .ui-list .lrow .act { order: 3; }
  .ui-container .ui-list .lrow .meta { order: 4; flex-basis: 100%; padding-left: 29px; font-size: 10px; }
}

/* ---- wrapper 層: .ui-ih（info header — layouts 実装の実ヘッダー。.ui-page-header と並ぶ
   もう一つのヘッダー wrapper）。08-26 再修正で grid をやめ flex wrap に戻した
   （理由は上の .ui-ih ブロックのコメント参照 — 列固定 grid は内容幅を見ないため actions が
   幅を取り h1 が早々に ellipsis していた）。.ih-row は「main + actions」の1行 flex、
   .ih-meta-row は「desc + meta」の1行 flex。狭幅で行が折り返るのは内容幅ベース
   （.ih-main の flex-basis:320px より main が縮むと actions が先に次の行へ落ちる）。
   `.ui-container` 祖先の有無に関わらず `.ui-ih-shell` 自身の container 幅でも同じ結果になる
   よう `:where(.ui-container, .ui-ih-shell)` を使う（:where はゼロ specificity）。 ---- */
/* ---- 部品層: .ih-meta-row（desc / 取得日時の1行）。`.ih-meta-row > .ih-meta` が取得日時、
   `.ih-meta-row > :not(.ih-meta)`（p.ih-desc・pagespeed 見本の nav.ui-crumbs 等）が desc 側。
   単独の `p.ih-desc`（ih-meta-row を介さず .ui-ih 直下にある既存出力）は
   `.ui-ih .ih-desc` の block 表示のままで自然に並ぶ。 ---- */
.ui-ih .ih-meta-row { display: flex; align-items: baseline; gap: 16px; margin-top: 6px; }
.ih-meta-row .ih-meta { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted-foreground); }
.ih-meta-row > .ih-meta { flex: none; }
.ih-meta-row > :not(.ih-meta) { flex: 1 1 auto; min-width: 0; }

@container ui (width < 680px) {
  /* sm 段（08-26 ユーザー指示）: 取得日時（meta）は desc の前・右寄せに置く
     （identity → actions → 取得日時 → desc の順を保つ。DOM は変えず order で並べ替え）。 */
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-meta-row { flex-direction: column; align-items: stretch; gap: 2px; }
  :where(.ui-container, .ui-ih-shell) .ih-meta-row > .ih-meta { order: -1; margin-left: 0; align-self: flex-end; }
  /* sm 段は「必ず actions が main の下の行」を保証する（md 段の 320px basis による内容依存の
     行落ちだけでは、actions が極小のときに同じ行のまま残ってしまい 08-26 以前の挙動と
     食い違うため、680px 未満は flex-basis:100% で強制的に折り返す）。 */
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-actions { flex-basis: 100%; margin-left: 0; }
}

/* ---- 部品層: .ui-ih .ih-tb（同日再修正）。ver チップ + ⌘J（.ih-sub）の行落ちは、xs 段の
   幅閾値ではなく .ih-tb の内容幅ベースの wrap（h1: flex 1 1 max-content・.ih-sub: flex 0 0 auto）
   で自然に決まるようにした。h1 が丸ごと収まらない container 幅になった時点で .ih-sub だけが
   次の行へ折れ、折れた位置は .ih-tb の左端（= icon の右）に自動で揃うため padding-left の
   細工も不要になった（旧: flex-basis:100% の強制改行トリック + padding-left:46px、撤去）。
   desc は xs 段でも 2 行 clamp にして高さの暴れを防ぐ（v1.23.0）。 ---- */
@container ui (width < 420px) {
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-desc { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
}

/* ⓘ compact 化（08-26 ユーザー指示）: sm 段以下（container < 680px）で .ih-desc を畳み、
   ver チップの左の ⓘ ボタンへ格納する。420px 未満の -webkit-line-clamp より後段に置き、
   カスケードで確実に勝たせる（680px 未満は 420px 未満も含むため、display:none で desc は
   出しっぱなしにならない）。 */
@container ui (width < 680px) {
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-desc { display: none; }
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-info { display: inline-flex; }
}

/* ---- compact 段（container < 680px）の identity type scale（08-26 ユーザー指示）:
   jai-info の `.ji-condensed`（bindSticky がスクロールで畳んだ姿。libs/info/src/jai-info.js
   283〜289 行）と同値にする。幅由来（container 幅）とスクロール由来（.ji-condensed）で
   「畳んだ姿」を揃えるのが目的 — 両者は直交（DESIGN.md §22）なので、.ji-condensed が
   併存しても破綻しない。 ---- */
@container ui (width < 680px) {
  /* icon 34→26（.ji-condensed .ji-h5-icon と同値）。内側 svg は inline style（width/height）で
     描画されるため、外側スタイルシートから上書きするには !important が必須。
     34→26 の比率（.778 ≒ .ji-condensed .material-icons の 18→14 と同比率）で 15px→12px。 */
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-icon { width: 26px; height: 26px; }
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-icon svg { width: 12px !important; height: 12px !important; }
  /* title h1 21→15（.ji-condensed .ji-h5-title と同値。letter-spacing は現状の 0.12em を維持） */
  :where(.ui-container, .ui-ih-shell) .ui-ih h1 { font-size: 15px; }
  /* version chip（.ih-ver）: jai-info の .ji-h5 に相当チップが無いため今回の指示値で小型化 */
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-ver { font-size: 10px; padding: 0 7px; }
  /* ⌕ ⌘J（.ih-srch）/ ⓘ（.ih-info）: 高さを ver chip（実測 ≒14px）に揃える
     （.ui-cmdk-btn--ghost の sm 相当 — 基本形 padding:4px 5px / svg 15px / .ui-kbd 11px を縮小） */
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-srch,
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-info { padding: 1px 4px; font-size: 10px; }
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-srch svg.ic,
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-info svg.ic { width: 11px; height: 11px; }
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-srch .ui-kbd,
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-info .ui-kbd { font-size: 9px; }
  /* 行間を詰める: .ih-row row-gap 8→6・.ih-sub gap 8→6（xs 段の row-gap 上書き — 下方 <420 ブロック
     — も同じ 6px に揃える。基本形（≥680）の .ih-row gap:10px 16px / .ih-sub gap:8px は不変） */
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-row { row-gap: 6px; }
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-sub { gap: 6px; }
}

/* ---- xs 段 brush up 3点（08-26 3点是正・version 据え置き）。.ih-main/.ih-tb/.ih-actions は
   「icon+.ih-tb」「.ih-actions」という2アイテム構成のせいで、.ih-sub（ver チップ + ⌘J）と
   verbs（.ih-actions 配下）を同じ行に混在させられなかった（.ih-sub が2行目へ折れても
   .ih-actions は常に別枠のまま3行目に居座る）。display:contents で3つとも箱を消し、
   icon / h1 / .ih-sub / .ih-menu / .ih-actions 配下の各要素を .ih-row 直下の flex item に
   フラット化することで、行分配を .ih-row 一段の flex-wrap に一本化する（DOM は無変更）。
   結果: 1行目 = icon + h1（h1 margin-right:auto で左寄せ・入らなければ ellipsis）。
        2行目 = .ih-sub（左・icon 左端に揃う。margin-right:auto で右側を actions に譲る）
                …… verbs 等 .ih-actions 配下（右・入らない要素は自然に3行目へ折れる）。
        3行目 = scope pill 等、2行目に入りきらなかった .ih-actions 配下（右端）。 */
@container ui (width < 420px) {
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-main,
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-tb,
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-actions { display: contents; }
  /* .ih-row が唯一の flex container になるので、折り返し・行内右寄せもここに集約する */
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-row { flex-wrap: wrap; justify-content: flex-end; row-gap: 6px; column-gap: 10px; position: relative; }
  /* .ih-menu（navPages・絶対配置）の基準は本来 .ih-tb だったが contents で箱が消えるため失われる。
     .ih-row（position:relative を上で付与）で受け、icon 直下（08-26 compact 化で icon 26px + gap 4px
     = 30px。旧: icon 34px + gap 4px = 38px）に見えるよう固定値で調整する
     （.ih-row は行が増えると背が伸びるため % 基準の top は使えない）。 */
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-menu { top: 30px; left: 0; }
  /* 1行目: icon + h1 のみを左寄せ。margin-right:auto が同じ行に残る余白を吸収するため、
     h1 の後ろに続く .ih-sub 以降は入りきらなければ次の行へ押し出される（内容幅ベース）。
     max-width: calc(100% - 36px)（08-26 compact 化で icon26px + gap10px。旧: icon34px + gap10px = 44px）は必須の補強 — flex-wrap の折り返し判定は
     各 item の「仮の主軸サイズ」（flex-basis を min/max でクランプした値）で行われ、h1 は icon の
     次に並ぶ2番目の item のため、basis が max-content のまま（未クランプ）だと長い CJK タイトル
     （T152: 代理店・製品別ダッシュボード）で「丸ごと2行目へ落ちて icon と別行になる」— 1番目の
     item だけが持つ「収まらなくても行の先頭に留まる」特例に icon を先取りされてしまうため。
     max-width で hypothetical size を「icon の右に残る幅」以下に強制クランプし、常に icon と
     同じ行に収まる（T152）ようにする。 */
  :where(.ui-container, .ui-ih-shell) .ui-ih h1 { flex: 0 1 max-content; min-width: 0; max-width: calc(100% - 36px); margin-right: auto; }
  /* 2行目左端 = icon 左端に揃う（.ih-tb の左端を継いでいた旧仕様と同じ見え方）。
     margin-right:auto で自分より右の空きを actions（verbs 等）へ譲る。 */
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-sub { margin-right: auto; }
}

/* ---- shell wrapper: .ui-ih-shell / .ui-ih-inner（v1.23.0・DESIGN.md §22 狭幅段の譲る順序）。
   sticky ヘッダーの器そのもの。.ji-h5-shell / .ji-h5-inner（libs/info/src/jai-info.js:249-289）と
   同値にして将来の移植を 1:1 にする。`.ui-ih-shell--static` は specimen 用（sticky を外す）。
   .ji-condensed 時の padding 縮小は `.ui-shell-header.ji-condensed` と同じ値で揃える。 ---- */
.ui-ih-shell { position: sticky; top: 0; z-index: 40; background: var(--background); transition: box-shadow var(--dur-base) var(--ease); }
.ui-ih-shell--static { position: static; }
/* 08-26: `transition: padding` は container query（sm/xs）由来の padding 変更と衝突し、
   Chrome の実装で「トランジションが先に確定した値のまま固定され、以降の cascade 変更を
   一切反映しなくなる」不具合を誘発する（transition の優先度は !important より高いという
   仕様どおりの挙動だが、container query の変化がトランジション再始動のトリガーとして
   正しく扱われないケースがある — 実機検証で確認）。狭幅で padding が縮まなくなるため撤去する
   （ji-condensed の scroll 由来の padding-top 変化も含め、無アニメーションに統一）。 */
.ui-ih-inner { max-width: 1200px; margin: 0 auto; padding: 22px 32px 16px; }
.ui-ih-shell.ji-condensed { box-shadow: 0 4px 16px rgba(0,0,0,.06); }
.ui-ih-shell.ji-condensed .ui-ih-inner { padding-top: 10px; }
.ui-ih-shell.ji-condensed .ih-tabs { margin-top: 8px; }

/* ---- 08-26 フィードバック②: 狭幅（sm/xs）で shell の余白を段階的に詰める（atomic のサイズは
   変えず wrapper の padding / margin-top だけ絞る。目標 = 390px 幅の marketing 見本で
   shell 高さが約230px→170px 前後）。 ---- */
@container ui (width < 680px) {
  :where(.ui-container, .ui-ih-shell) .ui-ih-inner { padding: 14px 20px 10px; }
}
@container ui (width < 420px) {
  :where(.ui-container, .ui-ih-shell) .ui-ih-inner { padding: 12px 12px 8px; }
}

/* ---- 部品層: .ui-ih .ih-tabs（header 3 行目 = タブの器・v1.23.0）。狭幅でも畳まず横スクロール
   （DESIGN.md §22 狭幅規約: タブは overflow-x:auto + スクロールバー非表示 + white-space:nowrap。
   全タブ常時到達可能を優先し段を落とさない）。実際のスクロール主体は中の .ui-tabs 自身
   （TabGroup の data-overflow="scroll" モード・fade edge 付き — infoHeader() が生成する tabs は
   これを使い、chip 退避（collapse）モードは使わない）。.ih-tabs 側の overflow-x:auto は
   TabGroup を経由しない消費のための保険（二重スクロールコンテナにはならない — 中の
   .ui-tabs が先に自分の幅で収まりきり、外側が余ることはあっても縮むことはない）。 ---- */
/* 08-26: margin の transition も .ui-ih-inner と同じ理由（container query 変更との衝突）で撤去 */
.ui-ih .ih-tabs { grid-area: tabs; margin-top: 18px; overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none; }
.ui-ih .ih-tabs::-webkit-scrollbar { display: none; }
.ui-ih .ih-tabs .ui-tabs { flex-wrap: nowrap; }
.ui-ih .ih-tabs .ui-tab { flex: none; }

/* 08-26 フィードバック②: sm/xs で tabs の margin-top を詰める（基本形の後ろに置き cascade で勝たせる） */
@container ui (width < 680px) {
  :where(.ui-container, .ui-ih-shell) .ui-ih .ih-tabs { margin-top: 10px; }
}

/* ---- wrapper 層: .ui-page（280px 実測・ユーザー指摘）。40/32/96 の固定余白は 680px 未満の
   container では左右だけで 64px も食い、狭幅ほど相対的に効いてくる。段階的に絞る。 ---- */
@container ui (width < 680px) {
  .ui-container .ui-page { padding: 28px 20px 64px; }
}
@container ui (width < 420px) {
  .ui-container .ui-page { padding: 16px 12px 40px; }
}

/* ---- wrapper 層: .ui-page-header の title-block（280px 実測・ユーザー指摘）。h1 は
   `display:flex` でタイトル文字列 + ver チップの2アイテム構成のため、xs 段では折り返しを
   許可してチップがタイトル末尾で自然に次行へ落ちるようにする（枠外はみ出し対策）。 ---- */
@container ui (width < 420px) {
  .ui-container .ui-page-header .title-block h1 { flex-wrap: wrap; white-space: normal; }
}

/* ---- wrapper 層: date pill（.ui-scope-pop・280px 実測・ユーザー指摘）。固定 min-width: 432px
   が狭い container からはみ出すため、md 段以下では cqw（最も近い .ui-container の inline-size
   基準の単位 — position:absolute の containing block（.ui-scope 自身の小さい幅）に依存する %
   とは違い、常に container 実寸を参照できる）でクランプする。sc-body（list + side の横並び）は
   さらに xs 段で縦積みにして内部の水平あふれも防ぐ。 ---- */
@container ui (width < 1000px) {
  /* 位置（left/right）は JS の scPlacePop が決める（クランプ境界 = 最寄り .ui-container）。
     ここでは幅のクランプだけを行う */
  :where(.ui-container, .ui-ih-shell) .ui-scope-pop { min-width: 0; width: min(432px, 92cqw); max-width: 92cqw; }
}
@container ui (width < 420px) {
  :where(.ui-container, .ui-ih-shell) .ui-scope-pop .sc-body { flex-direction: column; }
  :where(.ui-container, .ui-ih-shell) .ui-scope-pop .sc-list { min-width: 0; }
  :where(.ui-container, .ui-ih-shell) .ui-scope-pop .sc-side { min-width: 0; border-left: none; border-top: 1px solid var(--border); }
  :where(.ui-container, .ui-ih-shell) .ui-scope-pill { white-space: normal; text-align: left; }
}
