/* =========================================================================
   app.css — プランナー SPA（app.html）・システム管理コンソール（system.html）・
   操作マニュアル（manual.html）が読む1枚。
   共有部分（:root の変数・@font-face・ボタン／フォーム／モーダル等の土台）と、
   これら3画面専用の規則だけを、元の並び順のまま収めている。
   公開ページ専用の規則は style.css にある。
   共有部分は style.css にも同じ内容が入る（どちらか一方だけを直さないこと。
   CssBundleSplitTests が両者の食い違いとクラスの取り違えを検査する）。
   ========================================================================= */

/* === Self-hosted fonts (replaces Google Fonts CDN) === */

/* Inter — variable font, latin subset, weights 400-600 */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400 600;
    font-display: swap;
    src: url('/fonts/inter-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Plus Jakarta Sans — variable font, latin subset, weights 500-800 */
@font-face {
    font-family: 'Plus Jakarta Sans';
    font-style: normal;
    font-weight: 500 800;
    font-display: swap;
    src: url('/fonts/plus-jakarta-sans-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
    /* === ニュートラル（グレー）の色見本 — P-112 ===
       これまで style.css には 16 進の色が直書きで散在していて、
       「弱いテキストの色を全体的に見直す」といった判断を 1 箇所の書き換えで
       表現できなかった。よく使われているグレーは実際には slate 系の 1 本の階調
       だったので、まず薄い順に段として名前を与え、直書きをこの変数へ寄せた。
       この差し替えで色の値は 1 つも変えていない（＝見た目は変わらない）。
       新しい規則でグレーを使うときは、直書きせずこの段から選ぶこと。 */
    --slate-50: #f8fafc;
    --slate-100: #f1f5f9;
    --slate-200: #e2e8f0;
    --slate-300: #cbd5e1;
    --slate-400: #94a3b8;
    --slate-500: #64748b;
    --slate-600: #475569;
    --slate-700: #334155;
    --slate-800: #1e293b;

    /* === 状態を表す色の段（赤・橙・紫・藍） — P-115 ===
       P-112 でグレーを段へ寄せたあとも、危険（赤）・注意（橙）・主要操作の派生（紫・藍）は
       16 進の直書きのまま残っていた。「エラーの赤」と言ったときに #dc2626 と #ef4444 の
       どちらを選ぶのかが決まっておらず、近傍のコピーで決まっている状態だったので、
       slate と同じく薄い順の段として名前を与え、値が一致する箇所を寄せた。
       段名（数字）にしているのは、同じ色が「淡い背景の赤」と「濃い文字の赤」の
       両方に使われていて、役割名（--danger など）では一意に決まらないため。
       この差し替えで色の値は 1 つも変えていない（＝見た目は変わらない）。
       白は #fff と #ffffff の 2 流儀があったので #ffffff へ一本化した（描画結果は同じ）。
       新しい規則でこれらの色を使うときは、直書きせずこの段から選ぶこと。
       青・空・ピンク・紫（purple 系）にはまだ段が無い（次に色へ触れる回に寄せる）。
       緑（green・emerald）は P-227 で段を足した（下の「成功・完了」の節）。 */

    /* 赤 — 危険・エラー */
    --red-50: #fef2f2;
    --red-100: #fee2e2;
    --red-200: #fecaca;
    --red-300: #fca5a5;
    --red-400: #f87171;
    --red-500: #ef4444;
    --red-600: #dc2626;
    --red-700: #b91c1c;
    --red-800: #991b1b;
    --red-900: #7f1d1d;

    /* 橙 — 注意・警告 */
    --amber-50: #fffbeb;
    --amber-100: #fef3c7;
    --amber-200: #fde68a;
    --amber-400: #fbbf24;
    --amber-500: #f59e0b;
    --amber-600: #d97706;
    --amber-700: #b45309;
    --amber-800: #92400e;
    --amber-900: #78350f;

    /* 緑 — 成功・完了・収益（P-227）
       成功・完了を表す緑は、Tailwind の green 系（入力率 100% のバッジ・達成率バー・
       テナント管理者や収益のバッジ）と emerald 系（成功トースト・監査ログの「成功」）の
       2 系統が直書きで並んでいた。まず値が完全に一致する箇所をこの段へ寄せた
       （色の値は 1 つも変えていない＝見た目は変わらない）。
       2 系統をどちらかへ一本化するのは見た目が変わるので別の回（P-230）で行う。
       新しい成功表示の色は、直書きせずこの段から選ぶこと。 */
    --green-50: #f0fdf4;
    --green-100: #dcfce7;
    --green-200: #bbf7d0;
    --green-300: #86efac;
    --green-500: #22c55e;
    --green-700: #15803d;
    --green-800: #166534;
    --emerald-100: #d1fae5;
    --emerald-200: #a7f3d0;
    --emerald-500: #10b981;
    --emerald-600: #059669;

    /* 紫 — 主要操作のグラデーション側 */
    --violet-50: #f5f3ff;
    --violet-100: #ede9fe;
    --violet-200: #ddd6fe;
    --violet-300: #c4b5fd;
    --violet-400: #a78bfa;
    --violet-500: #8b5cf6;
    --violet-600: #7c3aed;
    --violet-700: #6d28d9;
    --violet-900: #4c1d95;

    /* 藍 — 主要操作（--primary はこの段を指す） */
    --indigo-50: #eef2ff;
    --indigo-100: #e0e7ff;
    --indigo-200: #c7d2fe;
    --indigo-300: #a5b4fc;
    --indigo-400: #818cf8;
    --indigo-500: #6366f1;
    --indigo-600: #4f46e5;
    --indigo-700: #4338ca;

    /* 空（sky）— 情報・補足（情報バナー・一般ユーザーのバッジ）と横軸の識別（P-228） */
    --sky-100: #e0f2fe;
    --sky-200: #bae6fd;
    --sky-500: #0ea5e9;
    --sky-600: #0284c7;
    --sky-700: #0369a1;
    --sky-800: #075985;

    /* 青（blue）— データの印（条件付き書式の「未達」・コメント・数式セル・お気に入り）とグラフパネル（P-228） */
    --blue-50: #eff6ff;
    --blue-100: #dbeafe;
    --blue-300: #93c5fd;
    --blue-400: #60a5fa;
    --blue-500: #3b82f6;
    --blue-600: #2563eb;
    --blue-700: #1d4ed8;
    --blue-800: #1e40af;

    --bg-color: #f4f7fb;
    --border-color: rgba(226, 232, 240, 0.8);
    --header-bg: rgba(255, 255, 255, 0.85);
    --primary: var(--indigo-600);
    --primary-hover: var(--indigo-700);
    --primary-gradient: linear-gradient(135deg, var(--indigo-600) 0%, var(--violet-600) 100%);
    --primary-gradient-hover: linear-gradient(135deg, var(--indigo-700) 0%, var(--violet-700) 100%);
    --text: var(--slate-800);
    --text-muted: var(--slate-500);

    /* === 暗い節の補助文字色 — P-145 ===
       --text-muted（--slate-500 #64748b）は白地では 4.76:1 で AA を満たすが、
       公開ページの暗い節（#0d1117 / #0a0d14 / #070a10）では 3.98〜4.16:1 と下回る。
       背景が暗い側では文字を「明るく」しなければ比が上がらないため、
       1 つの値を暗くする付け替えでは明暗の両立ができない。
       暗い背景の上に置く補助テキストは、--text-muted ではなくこの段を使うこと
       （--slate-400 は上記3つの背景に対して 7.38〜7.73:1）。 */
    --text-muted-on-dark: var(--slate-400);
    --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
    --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
    --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.05), 0 4px 6px -2px rgba(0, 0, 0, 0.025);
    --card-bg: rgba(255, 255, 255, 0.95);
    --font-heading: 'Plus Jakarta Sans', sans-serif;
    --font-body: 'Inter', sans-serif;
    --glass-blur: blur(12px);
    /* ツールバー／フィルターヘッダー内のボタン・セレクト・入力の高さ・角丸の共通基準（P-18） */
    --toolbar-ctl-h: 32px;
    --toolbar-ctl-radius: 16px;

    /* === 角丸の段 — P-113 ===
       border-radius には 21 種類の値が使われていて、完全なピル形だけでも
       999px と 9999px の 2 流儀に割れていた（描画結果は同じ）。新しい要素を足す
       たびに「どれが正しいのか」を近傍のコピーで決めることになっていたので、
       まず段を宣言し、値が一致する箇所だけを機械的に寄せた。
       この差し替えで角の大きさは 1 箇所も変えていない（＝見た目は変わらない）。
       新しい規則ではこの 4 段から選ぶこと。4px/7px/9px/10px/11px/14px/16px/20px は
       既存の見た目を保つため今回は触っていない（次に角丸へ触れる回に寄せる）。 */
    --radius-sm: 6px;
    --radius-md: 8px;
    --radius-lg: 12px;
    --radius-pill: 9999px;

    /* === 重なりの段 — P-117 ===
       z-index は 29 箇所・13 種類の値に散らばっており（90 の次が 100、
       600 の次が 1000、その次が 10000）、重なる要素を足すたびに
       「既存の何より上で、何より下か」を全件調べ直す必要があった。
       下から上へ並べて名前を与え、直書きをこの段へ寄せた。
       値は 1 つも変えていない（＝重なり順は従来のまま）。
       --z-overlay / --z-dropdown / --z-nav は現状いずれも 200 で同値だが、
       役割が違うので別の名前にしてある（将来分けるときに呼び出し側を
       探さなくて済む）。新しく重なる要素を足すときは、数字を直書きせず
       この段から選ぶこと。
       例外が 2 つあり、どちらも意図的に直書きのまま残している:
       ① #data-grid .jexcel の 3 / 1 — jspreadsheet.min.css 側の z-index: 2 を
          挟む形で上下を決めているため、外部 CSS の値との対応が見えなくなる
          変数へ寄せない（当該箇所のコメントを参照）。
       ② .hero-content / .*-hero-inner 等の z-index: 1 — 背景装飾（::before）より
          前に出すだけの局所的な指定で、画面全体の重なり順とは無関係。 */
    --z-sticky-head: 1;      /* 表の中の固定見出し（ディメンション編集表・軸設定表） */
    --z-grid-head: 10;       /* グリッドの固定ヘッダー行 */
    --z-doc-header: 10;      /* 操作マニュアルの固定ヘッダー（manual.html） */
    --z-grid-col: 20;        /* グリッドの固定列（1列目） */
    --z-grid-corner: 30;     /* 固定行と固定列が交わる角 */
    --z-toolbar: 90;         /* ツールバー（軸設定・フィルター） */
    --z-header: 100;         /* アプリのヘッダー */
    --z-panel: 150;          /* グリッドの上に浮くパネル（AI サマリ・グラフ） */
    --z-overlay: 200;        /* 読み込み中のオーバーレイ */
    --z-dropdown: 200;       /* ヘッダーメニューのドロップダウン */
    --z-nav: 200;            /* 公開ページの固定ナビ */
    --z-skip-link: 300;      /* スキップリンク（フォーカス時に前面へ） */
    --z-tooltip: 600;        /* セルの AI ツールチップ */
    --z-modal: 1000;         /* モーダル */
    --z-toast: 10000;        /* トースト（常に最前面） */

    /* === アニメーションの速さの段 — P-118 ===
       transition の宣言は 32 箇所あり、時間が 0.12s / 0.15s / 0.18s / 0.2s / 0.25s の
       5 通りに分かれていた。ボタンのホバーとカードのホバーで戻りの速さが
       わずかに違うといったばらつきは 1 つ 1 つは気付かれないが、画面全体としての
       「手触りの揃い方」には効くので、3 段とイージング 1 つを名前を付けて寄せた。
       新しい規則で transition を書くときは、秒数を直書きせずこの段から選ぶこと。
       .reveal (0.55s) と .capacity-bar-fill (0.6s) は、操作への応答ではなく
       登場・進捗を見せるための長い動きなので、この段の外に置いている。 */
    --motion-fast: 0.15s;
    --motion-base: 0.2s;
    --motion-slow: 0.25s;
    --motion-ease: cubic-bezier(0.4, 0, 0.2, 1);

    /* === 文字の大きさの段 — P-116 ===
       font-size の宣言は 333 箇所・61 種類に分かれており、主力の 11／12／13／14px の
       まわりに 9px から 32px までの整数値が点在していた。新しい要素を足すたびに
       「1px 大きくするか小さくするか」を近傍のコピーで決めることになっていたので、
       まず段を宣言し、値が完全に一致する箇所だけを機械的に寄せた。
       この差し替えで文字の大きさは 1 箇所も変えていない（＝見た目は変わらない）。
       新しい規則ではこの段から選ぶこと。
       今回触っていない値と、その理由:
       ① 10.5px / 11.5px / 12.5px / 13.5px / 14.5px の半端値（44 箇所）— グリッドの
          密度調整など 1px 未満の差に理由がある箇所がありうるため、1 つずつ見てから寄せる。
       ② rem 指定（約 80 箇所）と clamp()（11 箇所）— px へ寄せると単位の意味
          （利用者のブラウザ設定への追従）が変わるため、単位の方針を決めてから扱う。
       ③ 17px / 18px / 22px / 28px の 1〜2 箇所しかない値 — 段へ寄せると見た目が変わる。 */
    --fs-3xs: 9px;
    --fs-2xs: 10px;
    --fs-xs: 11px;    /* 補助ラベル・バッジ */
    --fs-sm: 12px;    /* 補足文・小さめのコントロール */
    --fs-md: 13px;    /* 画面内の既定の文字サイズ */
    --fs-lg: 14px;    /* 本文・入力欄 */
    --fs-xl: 15px;
    --fs-2xl: 16px;
    --fs-3xl: 20px;   /* 見出し */
    --fs-4xl: 24px;
    --fs-5xl: 32px;
}

body {
    font-family: var(--font-body);
    margin: 0;
    padding: 0;
    background-color: var(--bg-color);
    background-image: radial-gradient(circle at 15% 50%, rgba(79, 70, 229, 0.04), transparent 25%), radial-gradient(circle at 85% 30%, rgba(124, 58, 237, 0.04), transparent 25%);
    color: var(--text);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

.app-container {
    display: none; /* Hidden initially, shown after authentication */
    flex-direction: column;
    height: 100vh;
}

/* P-111: 主作業領域を包む main ランドマーク。
   これまで .toolbar と .grid-container は .app-container の直接の子として
   「高さの余りをグリッドがもらう」縦フレックスに乗っていた。main を1枚挟んでも
   同じ配分が成立するよう、main 自身を同じ縦フレックスにして flex-grow: 1 で
   余りを受け取り、min-height: 0 で内側の .grid-container の overflow: hidden が
   これまでどおり効くようにする（＝グリッドの取り分は挟む前と同じ）。
   狭幅（〜768px）では .app-container が height: auto になり余りが生まれないため、
   main は中身なりの高さになる＝N-49 の縦スクロール文書化もそのまま保たれる。 */
.app-main {
    display: flex;
    flex-direction: column;
    flex-grow: 1;
    min-height: 0;
}

/* P-111: スキップリンク。#data-grid の手前にはフォーカス可能な要素が数十個あり、
   キーボードだけで操作する利用者は読み込みのたびに Tab を押し続けることになっていた。
   display: none だと Tab で拾えなくなるため、画面外へ逃がして :focus で引き戻す
   定番の作法を使う。飛び先（#data-grid / #freesheet-grid）はどちらも tabindex="0"
   を持つので、フラグメント遷移でそのままフォーカスが移る。 */
.skip-link {
    position: absolute;
    top: 0;
    left: -9999px;
    z-index: var(--z-skip-link);
    padding: 10px 18px;
    background: var(--primary);
    color: #ffffff;
    font-size: var(--fs-lg);
    font-weight: 600;
    text-decoration: none;
    border-radius: 0 0 8px 0;
    box-shadow: var(--shadow-md);
}

.skip-link:focus {
    left: 0;
}

/* 表示中でない側のグリッドへ飛ぶリンクは Tab の順路からも外す。
   （body.freesheet-mode は .toolbar / .grid-container を display: none にする） */
.skip-link-freesheet {
    display: none;
}

body.freesheet-mode .skip-link-pivot {
    display: none;
}

body.freesheet-mode .skip-link-freesheet {
    display: block;
}

/* P-155: アプリのヘッダーバー。以前は無限定の `header { ... }` で書いていたが、
   `<header>` はカード・モーダル・記事の見出しにも使う要素なので、そこへ置いた瞬間に
   すりガラスの背景・左右に離す flex・下罫線・影・z-index が一式付いてしまう。
   `.app-header` を名乗るヘッダー（app.html / system.html / manual.html の3枚）だけに当てる。
   manual.html は `.app-header .manual-header` の2枚重ねで、上書きする分だけ後者に書いてある。 */
.app-header {
    background: var(--header-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    padding: 12px 24px;
    border-bottom: 1px solid var(--border-color);
    box-shadow: var(--shadow-sm);
    display: flex;
    justify-content: space-between;
    align-items: center;
    z-index: var(--z-header);
}

.logo-area {
    display: flex;
    align-items: center;
    gap: 12px;
}

.logo-icon {
    font-size: 1.6rem;
    color: var(--primary);
    background: var(--primary-gradient);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

.app-header h1 {
    font-family: var(--font-heading);
    font-size: 1.4rem;
    font-weight: 700;
    margin: 0;
    letter-spacing: -0.02em;
    color: var(--text);
}

.btn {
    padding: 8px 16px;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    cursor: pointer;
    font-weight: 600;
    font-family: var(--font-heading);
    font-size: var(--fs-lg);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    line-height: 1.25;
    text-decoration: none;
    transition: var(--motion-base) var(--motion-ease);
    transition-property: background-color, color, border-color, box-shadow, transform, opacity;
}

.btn-primary {
    background: var(--primary-gradient);
    color: white;
    border: none;
    box-shadow: 0 2px 4px rgba(79, 70, 229, 0.25);
}

.btn-primary:hover:not(:disabled) {
    background: var(--primary-gradient-hover);
    box-shadow: 0 4px 6px rgba(79, 70, 229, 0.35);
    transform: translateY(-1px);
}

/* 無効化されたボタンは押せないことが見た目で伝わるようにする
   （半透明・グレーカーソル・ホバーの浮き上がりを無効化）。
   ページ送りの「前へ/次へ」が端に達したときなど、generic .btn を
   disabled にする箇所で「押せそうに見えるのに反応しない」を防ぐ。表示のみ。 */
.btn:disabled,
.btn[disabled] {
    opacity: 0.55;
    cursor: not-allowed;
    box-shadow: none;
    transform: none;
}

/* 未保存の編集があるときの保存ボタン強調と「未保存」バッジ */
.btn-dirty {
    box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.55), 0 2px 4px rgba(79, 70, 229, 0.25);
}

.unsaved-badge {
    padding: 1px 7px;
    border-radius: var(--radius-pill);
    background-color: var(--amber-500);
    color: #ffffff;
    font-size: var(--fs-xs);
    font-weight: 700;
    line-height: 1.5;
    white-space: nowrap;
    /* 未保存の編集があるときだけ表示されるバッジを穏やかに点滅させ、保存忘れに気づきやすくする */
    animation: unsaved-badge-pulse 2s ease-in-out infinite;
}

@keyframes unsaved-badge-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.5); }
    50% { box-shadow: 0 0 0 4px rgba(245, 158, 11, 0); }
}

.unsaved-badge[hidden] {
    display: none;
}

.btn-secondary {
    background-color: rgba(255, 255, 255, 0.8);
    color: var(--text);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-sm);
}

.btn-secondary:hover:not(:disabled) {
    background-color: #ffffff;
    border-color: var(--slate-300);
    box-shadow: var(--shadow-md);
    transform: translateY(-1px);
}

.btn-icon {
    background: transparent;
    border: none;
    cursor: pointer;
    font-size: 1.1rem;
    padding: 6px;
    margin-left: 4px;
    border-radius: var(--radius-sm);
    transition: var(--motion-base);
    transition-property: background-color, color;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
}

/* P-205: 他のボタンのホバーと同じく :not(:disabled) を付け、無効なアイコンボタンを藍色に光らせない。
   詳細度は 0,3,0 になるが、同じ要素に当たる部品側のホバー（.btn-icon-danger・.btn-icon-chip）も
   :hover:not(:disabled) で、この規則より後ろにあるため後勝ちで部品側が効く。 */
.btn-icon:hover:not(:disabled) {
    background: var(--slate-200);
    color: var(--primary);
}

/* 削除など取り返しのつかない破壊的操作の btn-icon。既定は他のアイコンボタンと同じ控えめな見た目のまま、
   ホバー／フォーカス時のみ淡い赤（danger）を当てて誤クリックを抑止する（P-16, .btn-view-delete と同じ方針。表示のみ・確認ダイアログ挙動は不変） */
.btn-icon-danger:hover:not(:disabled) {
    background: var(--red-50);
    color: var(--red-600);
}
.btn-icon-danger:focus-visible {
    color: var(--red-600);
    box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.18);
}

/* テキスト付きの btn-secondary 版（P-38, セルコメント削除など）。既定は他の btn-secondary と同じ見た目のまま、
   ホバー／フォーカス時のみ淡い赤（danger）を当てて破壊的操作であることを示す（表示のみ・確認ダイアログ挙動は不変） */
.btn-secondary-danger:hover:not(:disabled) {
    background-color: var(--red-50);
    border-color: var(--red-300);
    color: var(--red-600);
}
.btn-secondary-danger:focus-visible {
    color: var(--red-600);
    border-color: var(--red-400);
    box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.18);
}

/* P-186: 押した瞬間の手応え。ホバーで 1px 浮いたボタンを元の高さへ戻し（＝沈む）、影を一段浅くする。
   押し込みは即座に見せたいので transition-duration を 0 にする——離したときは素の状態の
   duration で戻るため、戻りは従来どおり滑らかに補間される。ホバーの規則と詳細度が並ぶので、
   必ずそれより後ろに置くこと（前に置くと後勝ちで負けて何も起きない）。 */
.btn-primary:active:not(:disabled) {
    box-shadow: 0 1px 2px rgba(79, 70, 229, 0.25);
    transform: none;
    transition-duration: 0s;
}

.btn-secondary:active:not(:disabled) {
    background-color: var(--slate-100);
    box-shadow: none;
    transform: none;
    transition-duration: 0s;
}

/* P-186: アイコンボタンは浮き上がらないので、背景色を一段濃くして押下を伝える。
   危険側（.btn-icon-danger・.btn-secondary-danger）はホバーの赤い規則の方が詳細度が高い／
   後勝ちになるため、押下も赤系で一段濃くした規則を別に置く（置かないと灰色へ戻ってしまう）。 */
.btn-icon:active:not(:disabled) {
    background: var(--slate-300);
    transition-duration: 0s;
}

.btn-icon-danger:active:not(:disabled) {
    background: var(--red-100);
}

.btn-secondary-danger:active:not(:disabled) {
    background-color: var(--red-100);
}

.toolbar {
    background: var(--header-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    padding: 16px 24px;
    border-bottom: 1px solid var(--border-color);
    display: flex;
    flex-direction: column;
    gap: 16px;
    z-index: var(--z-toolbar);
    position: relative; /* P-223: 下端の開閉タブの基準。z-index もこれで効く */
}

.axis-config {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
}

.axis-panel, .filters-panel {
    display: flex;
    flex-direction: column;
    gap: 8px;
    background: rgba(248, 250, 252, 0.7);
    padding: 12px 16px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
}

.filters-panel {
    flex-direction: column;
    gap: 0;
}

.config-group {
    display: flex;
    align-items: center;
}

.config-group label {
    margin-right: 8px;
    font-weight: 600;
    font-size: var(--fs-md);
    color: var(--text-muted);
    width: auto;
    min-width: 65px;
    text-align: right;
}

.config-group select {
    padding: 6px 12px;
    min-width: 150px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-color);
    background-color: #ffffff;
    font-size: var(--fs-md);
    color: var(--text);
    /* P-184: :focus で変わる枠色とフォーカスの輪（box-shadow）を同じ速さで動かす。
       border-color だけだと、輪が一瞬で付いてから枠色が 0.2 秒かけて追いかけていた。 */
    transition: var(--motion-base);
    transition-property: border-color, box-shadow;
}

/* P-209: 輪の濃さは .form-input:focus と同じ 0.15。グリッド内検索の「縦軸/横軸」は .form-input を
   持ちながら .config-group の中にあり、詳細度の高いこちらが勝つため、隣の検索欄と輪の濃さがずれていた。 */
.config-group select:focus {
    border-color: var(--primary);
    outline: none;
    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
}

/* P-200: 軸設定パネルの select（.form-input を持たない）も、無効の見た目は .form-input:disabled と同じ値にする。
   以前は展開レベルだけ JS が付ける .select-disabled（opacity: 0.35・pointer-events: none）で淡色化しており、
   透明度が他の無効な欄と揃わず、pointer-events: none で選べない理由の title も出なかった。 */
.config-group select:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    background-color: var(--slate-100);
}

.filters {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    align-items: center;
    margin-top: 8px;
}

.filters .config-group label {
    width: auto;
    min-width: 0;
}

/* P-221: 高さの足りない画面でグリッドの取り分を増やす。.axis-config を display: contents にして、
   軸・ツール・AI サマリ・フィルターを同じ折り返しの並びへ置く。入りきらない AI サマリが自分だけの段を
   作らず、フィルターの左へ入る（1440px で 97px 減）。HTML の順序は変えないのでタブ順も変わらない。
   768px 以下は末尾の狭幅ブロックの縦積みのまま。 */
@media (min-width: 769px) {
    .toolbar {
        flex-flow: row wrap;
    }

    .axis-config {
        display: contents;
    }

    .filters-panel {
        flex: 1 1 640px;
        min-width: 0;
    }
}

/* Checkbox styling */
input[type="checkbox"] {
    accent-color: var(--primary);
    width: 16px;
    height: 16px;
    cursor: pointer;
}

/* Data Grid Container */
.grid-container {
    flex-grow: 1;
    overflow: hidden;
    background: transparent;
    padding: 24px;
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* P-220: 769px 以上でも、画面の高さが足りずグリッドの取り分が下限（calcGridHeight の 300px）に届かない
   ときは、1画面完結をやめてページ全体を縦スクロールする。1画面完結のままだと、はみ出した表の下端が
   切り取られ、最下行と横スクロールバーへ届かない。クラスは calcGridHeight が付け外しする。
   フリーシートはツールバーが消えて取り分の前提が違うので、1画面完結のままにする。 */
body:not(.freesheet-mode) .app-container-flow {
    height: auto;
    min-height: 100vh;
}

body:not(.freesheet-mode) .app-container-flow .grid-container {
    overflow: visible;
}

/* Loading Overlay
   P-08: 大きなテナント・多列ビューで再描画に時間がかかると、薄いオーバーレイ＋小さな
   スピナーでは「操作が効いていない／固まった」と誤解されやすい。背景のコントラストを上げ、
   スピナーと文言を白いカード（.loading-panel）にまとめて中央にはっきり浮かせることで、
   処理中であることを明確に伝える。表示のみ・文言のみの調整で挙動は不変。 */
.loading-overlay {
    position: fixed;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: rgba(241, 245, 249, 0.72);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    z-index: var(--z-overlay);
    pointer-events: all;
}

.loading-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding: 28px 40px;
    background: #ffffff;
    border: 1px solid var(--border-color);
    border-radius: 14px;
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
}

.loading-spinner {
    width: 48px;
    height: 48px;
    border: 4px solid var(--border-color);
    border-top-color: var(--primary);
    border-radius: 50%;
    animation: loading-spin 0.7s linear infinite;
}

@keyframes loading-spin {
    to { transform: rotate(360deg); }
}

.loading-message {
    color: var(--text);
    font-size: var(--fs-lg);
    font-weight: 600;
    letter-spacing: 0.02em;
}

/* 失敗表示の外枠（#loading-error・role="alert"）。読み上げに届くよう常に描画したまま置き、
   中身の .loading-error だけを出し入れする（Q-181）。中身が隠れている間は高さ0の箱になる。
   このためオーバーレイ（.loading-overlay）は gap を持たない——持つと、高さ0のこの箱との間に
   隙間ができてスピナーのパネルが中央から半分ずれる。パネル・失敗表示・確認表示は同時に1つしか
   出さないので、gap はもともと効いていなかった。 */
.loading-error-region {
    max-width: min(520px, calc(100vw - 48px));
}

/* 読み込み失敗表示（.loading-panel と入れ替えで出す）。スピナーを回し続けるより、
   何が起きたかと次の操作（再読み込み）を示すほうが利用者の手が止まらない。 */
.loading-error {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    max-width: min(520px, calc(100vw - 48px));
    padding: 28px 32px;
    background: #ffffff;
    border: 1px solid var(--border-color);
    border-radius: 14px;
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
    text-align: center;
}

/* エラートースト（.toast-error）と同じ赤で「失敗」を一貫させる。 */
.loading-error-icon {
    font-size: var(--fs-5xl);
    color: var(--red-500);
}

.loading-error-message {
    margin: 0;
    color: var(--text);
    font-size: var(--fs-xl);
    font-weight: 600;
}

/* サーバーが返した理由。問い合わせ時にそのまま伝えられるよう、折り返して全文表示する。 */
.loading-error-detail {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-md);
    line-height: 1.6;
    overflow-wrap: anywhere;
}

/* 進捗表示（何%まで進んだか）。総量が分かるときはバーが伸び、分からないときは
   .loading-progress-bar-indeterminate が左右に往復して「動いてはいる」ことだけを示す。 */
.loading-progress {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    width: min(320px, calc(100vw - 96px));
}

.loading-progress-track {
    width: 100%;
    height: 8px;
    background: var(--border-color);
    border-radius: var(--radius-pill);
    overflow: hidden;
}

.loading-progress-bar {
    width: 0;
    height: 100%;
    background: var(--primary);
    border-radius: var(--radius-pill);
    transition: width var(--motion-fast) linear;
}

.loading-progress-bar-indeterminate {
    width: 40%;
    animation: loading-progress-slide 1.2s ease-in-out infinite;
}

@keyframes loading-progress-slide {
    0% { transform: translateX(-100%); }
    100% { transform: translateX(250%); }
}

.loading-progress-text {
    color: var(--text-muted);
    font-size: var(--fs-sm);
    font-variant-numeric: tabular-nums;
    text-align: center;
}

/* 中断ボタン。処理中に押せることが分かるよう、パネル内で他より一段控えめに置く。 */
.loading-cancel-btn {
    margin-top: 2px;
}

/* 描画前の確認（.loading-panel と入れ替えで出す）。規模を伝えてから始めるための関門。 */
.loading-confirm {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    max-width: min(560px, calc(100vw - 48px));
    padding: 28px 32px;
    background: #ffffff;
    border: 1px solid var(--border-color);
    border-radius: 14px;
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18);
    text-align: center;
}

.loading-confirm-icon {
    font-size: var(--fs-5xl);
    color: var(--amber-500);
}

.loading-confirm-message {
    margin: 0;
    color: var(--text);
    font-size: var(--fs-xl);
    font-weight: 600;
}

.loading-confirm-detail {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-md);
    line-height: 1.6;
}

.loading-confirm-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: center;
}

/* 描画を中止／中断したときにグリッドの代わりに出す案内。 */
.grid-oversize-notice {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    margin: 24px auto;
    max-width: min(560px, calc(100vw - 48px));
    padding: 28px 32px;
    background: var(--card-bg);
    border: 1px dashed var(--border-color);
    border-radius: 14px;
    text-align: center;
}

.grid-oversize-icon {
    font-size: var(--fs-5xl);
    color: var(--text-muted);
}

.grid-oversize-message {
    margin: 0;
    color: var(--text);
    font-size: var(--fs-xl);
    font-weight: 600;
}

.grid-oversize-detail {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-md);
    line-height: 1.6;
}

#data-grid {
    background: var(--card-bg);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
    overflow: hidden;
    border: 1px solid var(--border-color);
    min-width: 100%;
}

/* P-154: グリッド（jspreadsheet が描く表）のための既定値。元は `table` という無限定の
   セレクターで、style.css を読み込むあらゆるページのあらゆる表の既定値になっていた。
   そのため新しい表を足すたびに「内容幅いっぱいに伸びる（width: max-content）」から
   始まり、それを打ち消す形でしか書けなかった（`.management-table`・`.legal-table`・
   `.manual-content table`・`.summary-table` は4つとも `width: 100%` で打ち消している）。
   P-151 と同じく `:where()` でグリッドの容器へ限定し、詳細度は 0-0-1 のまま据え置く。 */
:where(#data-grid, #freesheet-grid) table {
    border-collapse: collapse;
    width: max-content;
    font-size: 0.9rem;
}

/* P-01: 横軸メンバー（列）が少ないとき、グリッド右側に大きな余白ができて間延びして
   見えるのを防ぐ。テーブルを最低でもスクロール領域いっぱい（100%）まで広げ、列が少ない
   ときは各列幅が伸びて余白を埋める。列が多く max-content が 100% を超える場合は従来どおり
   max-content（横スクロール）が優先されるため、多列時の挙動は不変。1列目（勘定科目）は
   既存の width/max-width で頭打ちになるため、余白は主にデータ列へ配分される。
   表示のみで集計・編集・保存には影響しない。 */
#data-grid table {
    min-width: 100%;
}

/* P-154: 上と同じ理由でグリッドの容器へ限定する。`:is(th, td)` の詳細度は中の最大値＝
   0-0-1 なので、前置きの `:where()` と合わせて限定前と同じ 0-0-1 を保つ。 */
:where(#data-grid, #freesheet-grid) :is(th, td) {
    border: 1px solid var(--border-color);
    padding: 8px 12px;
    text-align: left;
    min-width: 80px;
}

/* P-153: ここには `th { background-color / color / font-weight / font-size /
   text-transform / letter-spacing / font-family / text-align: center /
   position: sticky; top: 0; z-index }` という無限定の規則があり、**style.css を
   読み込むすべてのページのすべての `<th>`** に当たっていた。これを削除し、実際に
   その見た目を使っている4つの表（`.management-table` / `.legal-table` /
   `.manual-content` / `.summary-table`）の側へ、計算値が変わらない形で移した。
   グリッドの容器へ限定しなかったのは、**jspreadsheet-ce v4 が描く表に `<th>` が
   1つも無い**ため（本物の v4 をCDNから読み込んでピボットとフリーシートを生成し、
   `#data-grid th, #freesheet-grid th` が 0 件であることを実測）。限定しても何にも
   当たらない規則が残るだけなので、移し先を明示するほうが後から追える。
   `position: sticky; top; z-index` を移し先に持って行かないのが P-153 の本体。
   `legal.html` の特商法表は1行が「短い見出し＋長い本文」で本文側が行の高さを決めるため、
   背の低い見出しセルが行の中を下へ滑り、**行から離れて画面上端に貼り付く**。
   1280×300px でスクロール量 400px のとき、見出しセルと行の上端のずれが最大 104px
   （13行中3行で発生）まで開くことを実測した。修正後は同じ測り方で 1280×300px・
   1280×700px・375×600px の3通り × スクロール位置4点 × 全13行の**すべてでずれが 0**
   になる（＝見出しは常に自分の行と一緒に動く）。
   なお `.management-table` でこの `position: sticky` は元から効いていない
   （表自身が `overflow: hidden` でスクロールポートになっており、見出し行が動く余地が
   無い）。スクロール枠に入っている一覧（`.table-scroll` / `.axis-table-wrap` /
   `#dim-edit-table`）の固定見出しは、それぞれ専用の規則が別にあるのでそのまま残る。
   `text-transform: uppercase` も移していない——現在の見出しは HTML の全 `<th>` と、
   配信している唯一のマニュアル（`ユーザー操作マニュアル.md`）の表見出し13行を走査して
   **小文字の英字が1文字も無い**ことを確認済みで、1文字も変わらないため。 */

/* JSpreadsheet Custom Styling Overrides */
.jexcel_container {
    border: none;
    font-family: inherit;
}

.jexcel > thead > tr > td {
    background-color: var(--slate-50) !important;
    color: var(--slate-700) !important;
    font-weight: 700 !important;
    border: 1px solid var(--border-color) !important;
    padding: 8px 12px !important;
    white-space: normal !important;
    height: auto !important;
    vertical-align: middle !important;
    text-align: center !important;
    min-height: 40px;
    font-family: var(--font-heading);
    letter-spacing: 0.02em;
    font-size: var(--fs-md) !important;
}

/* P-20: jspreadsheet-ce v4 が自動生成する行番号列（1, 2, 3...）を非表示にする。
   実際のDOM構造は #data-grid 自体が .jexcel_container であり（.jspreadsheet という
   親クラスは存在しない）、行番号セルの実クラスは .jexcel_index ではなく .jexcel_row
   （コーナーセルは .jexcel_selectall）のため、旧ルールはどの要素にも一致していなかった
   （実機のDOM調査で確認済み）。display:none で <td> を個別に隠すと <colgroup><col> の
   列幅マッピングが1列ずれ、実際の1列目（勘定科目など、data-x="0"）の幅が壊れる副作用が
   あるため、代わりに <colgroup> 側の対応する <col> に visibility:collapse を指定する。
   これは表全体でその列に属するセル（ヘッダー・本文とも）を列ごと描画から除外しつつ、
   他の列の colgroup インデックス対応やセル位置は保持される（実機で横スクロール・
   列幅リサイズを含めて確認済み）。列幅・固定列（P-04）・集計・編集・保存・
   CSV/Excel出力・コピー（isIndexCell が data-x 属性の有無で別途判定しており、
   このCSSとは独立して元々正しく除外している）には影響しない表示のみの変更。 */
#data-grid table.jexcel > colgroup > col:first-child {
    visibility: collapse;
}

/* P-03: 1列目（行ヘッダー＝勘定科目など）の見出しを、本文のメンバー名（左寄せ）と
   左端で揃えるため左寄せにする。データ列の見出しは従来どおり中央寄せのまま。表示のみ。 */
.jexcel > thead > tr > td[data-x="0"],
.jexcel > thead > tr > td:nth-child(2) {
    text-align: left !important;
}

.jexcel > tbody > tr > td {
    border: 1px solid var(--border-color) !important;
    padding: 6px 10px !important;
    font-size: var(--fs-lg);
}

.jexcel > tbody > tr > td.readonly {
    background-color: var(--slate-50) !important;
    color: var(--slate-500) !important;
}

.jexcel_content {
    box-shadow: none;
}

/* P-01: 横軸メンバーが少なくテーブルが画面右側まで届かないとき、白いカード内に
   広い余白が残り間延びして見える。コンテンツ領域にうっすらした背景色を敷くことで、
   白いデータセル（jspreadsheet 既定で背景白）が並ぶ「データ範囲」と、その外側の余白を
   視覚的に分離し、「データはここまで」が一目で伝わるようにする。多列で横スクロールが
   必要な場合も挙動は不変（背景色のみの表示調整で、列幅・集計・編集には影響しない）。
   jspreadsheet.min.css が style.css より後に読み込まれるため、#data-grid（ID）で
   詳細度を上げて確実に適用する。 */
#data-grid .jexcel_content {
    background: var(--slate-100);
}

/* P-192: ここには元々 `:where(#data-grid, #freesheet-grid) td:first-child, … th:first-child` という
   規則（sticky・白背景・左寄せ・太字・幅 300〜450px・`white-space: pre`・省略記号・右に 2px の罫線。
   来歴は P-151）があったが、ヘッドレス Chromium で本物の jspreadsheet-ce v4 を描いて計算値を
   測ると、ほぼ全部が効いていなかった。`td:first-child` はどちらのグリッドでも jspreadsheet が
   描く**行番号セル**（`.jexcel_row`。ピボットは `index: false` で、その列ごと `visibility: collapse`）で、
   実際の1列目（勘定科目など）は `td[data-x="0"]`（DOM 上は2番目の子）。背景・左寄せ・
   `white-space`・罫線は jspreadsheet の `.jexcel > tbody > tr > td:first-child` などに負け、
   幅は `table-layout: fixed` ＋ `<col width>` が決めるので `width` 系は効かない。`th` はグリッドに
   1つも無い（P-153）。
   **効いていたのはフリーシートの行番号の太字と `z-index: 20` の2つだけ**で、後者は害になっていた——
   行番号セルは jspreadsheet 側で `position: relative` なので、`z-index: 20` が付くと固定見出し行
   （`z-index: 2`）より手前に描かれ、**縦にスクロールすると行番号が左上の角へ重なって見えていた**。
   太字だけを、名前で何に当たるか分かるこのセレクターへ移し、残りは削除した。 */
#freesheet-grid .jexcel > tbody > tr > td.jexcel_row {
    font-weight: 600;
}

/* P-04: グリッド本体では、かつてあった td:first-child の規則（P-192 で削除）は非表示の行番号セル
   （data-x属性なし）にしか一致せず、実際に表示される1列目（勘定科目など、data-x="0"）は固定列になっていなかった
   （横スクロールすると本文と一緒に流れてしまう）。実際の1列目に直接 sticky を当てて固定列として
   機能させる。列幅は既存の列幅設定（jspreadsheet の列幅・リサイズ機能）をそのまま使うため、
   幅・padding 等は上書きしない。表示のみの修正で、集計・編集・保存・列幅リサイズ・
   CSV/Excel出力・コピーには影響しない。
   z-index: ヘッダー行の各セルは jspreadsheet.min.css 側で sticky top + z-index:2 が
   一律に付与されているため、左固定にする1列目ヘッダー（コーナーセル）は横スクロールで
   流れてくる他の列見出しの下に隠れないよう、それより高い 3 を指定する。本文側の1列目は
   同じ行の他セル（既定 z-index）より高く、ヘッダー行（2〜3）より低い 1 にして、
   スクロール時の重なり順（ヘッダー行 > 固定列 > 通常セル）を成立させる。 */
#data-grid .jexcel > thead > tr > td[data-x="0"] {
    position: sticky;
    left: 0;
    z-index: 3;
}
#data-grid .jexcel > tbody > tr > td[data-x="0"] {
    position: sticky;
    left: 0;
    z-index: 1;
    /* P-190: 列幅（既定 280px）に入りきらない名前は、jspreadsheet 既定（tableOverflow の
       overflow: hidden ＋ text-overflow: clip）だと文字の途中で断ち切られ、元から短いのか
       切れているのかが区別できない。狭幅（N-55）だけでなく全幅で省略記号を出して
       「まだ続きがある」と伝える。全文は updateTable で付けている title（表示名（ID））で読める。
       （かつてあった `td:first-child` の ellipsis 指定は非表示の行番号セルにしか一致せず、P-192 で削除した。） */
    text-overflow: ellipsis;
}

/* N-17: 横軸の先頭列を指定数だけ横スクロールしても画面左端（行ヘッダー列の右）に固定表示する
   「列固定」。対象列数は表示メニューの「固定する列数」（state.freezeColCount）で選び、
   grid.js の applyFrozenColumns() が対象セル（thead/tbody とも）へ .cell-frozen-col を付与し、
   実測した列幅の累積値を left にJSで設定する（列幅を決め打ちにせず、リサイズ後の実際の
   描画幅を使うため）。z-index は P-04（行ヘッダー列固定）と同じ考え方: ヘッダー行の固定列は
   横スクロールで流れてくる他の列見出しより上（3）、本文の固定列は同じ行の通常セルより上・
   ヘッダー行より下（1）。本文側は cell-editable 等の状態クラスが明示的な背景を持たないため、
   下に隠れず不透明に見えるよう白背景を敷く。 */
#data-grid .jexcel > thead > tr > td.cell-frozen-col {
    position: sticky;
    z-index: 3;
}
#data-grid .jexcel > tbody > tr > td.cell-frozen-col {
    position: sticky;
    z-index: 1;
    background-color: #ffffff;
}
/* 固定列の右端の境界（P-11と同じ考え方の影）。ヘッダー行の td には既に上端固定用の影
   （下記 P-11 のルール）が指定されているため、box-shadow は1つの宣言に両方併記して、
   ヘッダー行の固定列でも右端の影が欠けないようにする（従来は本文側にしか付いておらず、
   ヘッダー行だけ境界が見えなかった）。
   P-194: 影の値はカスタムプロパティ --frozen-col-edge-shadow に置く（印刷時に下の @media print で
   透明へ差し替えるため。--row-header-edge-shadow と同じ作法）。 */
#data-grid .jexcel {
    --frozen-col-edge-shadow: 2px 0 5px -2px rgba(15, 23, 42, 0.13);
}
#data-grid .jexcel > tbody > tr > td.cell-frozen-col-last {
    box-shadow: var(--frozen-col-edge-shadow);
}
#data-grid .jexcel > thead > tr > td.cell-frozen-col-last {
    box-shadow: 0 3px 5px -2px rgba(15, 23, 42, 0.13), var(--frozen-col-edge-shadow);
}
/* 上の cell-frozen-col の白背景は #data-grid でIDによる詳細度を上げているため、後方で
   定義されている cell-summary 等の状態別背景色（IDなしセレクタ）より詳細度が常に高く、
   ソース順に関わらず勝ってしまう。そのため列固定と集計値／読取専用／AIハイライト／
   条件付きハイライトが重なるセルは、意味を持つ背景色が白で覆い隠され「凡例」（P-22）どおりの
   状態表示にならない不具合があった。同じ #data-grid 起点で状態クラスを併記し
   cell-frozen-col 単体より詳細度を上げることで、各状態の背景色を正しく復元する
   （色の値は各状態のルールと同一。判定ロジック・保存・編集には影響しない表示のみの修正）。 */
#data-grid .jexcel > tbody > tr > td.cell-summary.cell-frozen-col {
    background-color: var(--slate-200);
}
#data-grid .jexcel > tbody > tr > td.cell-readonly-leaf.cell-frozen-col {
    background-color: var(--slate-100);
}
#data-grid .jexcel > tbody > tr > td.cell-ai-highlight.cell-frozen-col {
    background-color: var(--amber-100);
}
#data-grid .jexcel > tbody > tr > td.cell-cond-high.cell-frozen-col {
    background-color: var(--red-100);
}
#data-grid .jexcel > tbody > tr > td.cell-cond-low.cell-frozen-col {
    background-color: var(--blue-100);
}

/* P-154: P-151 と同じ理由（→ frontend.md「データグリッド用のセレクターは容器へ限定し…」）で
   グリッドの容器へ限定する。`!important` はグリッド内で
   `.jexcel > tbody > tr > td`（`background-color ... !important`）に勝つために要るので
   残す。グリッドの外では、行 hover を使っている表の側へ同じ色を移した（表ごとの
   通常の規則で足りるため `!important` は付けていない）。 */
:where(#data-grid, #freesheet-grid) tbody tr:hover :is(td, th) {
    background-color: var(--slate-100) !important;
}

/* P-11: ヘッダー行と1列目（勘定科目）はスクロールしても固定されるが、本文との境界に
   視覚差がなく「ここから上／左は固定見出し」と気づきにくい。固定領域の外側エッジに控えめな
   ドロップシャドウを付け、スクロール時に固定行・固定列が本文の上に浮いて見えるようにする。
   jspreadsheet.min.css が style.css より後に読み込まれるため #data-grid で詳細度を上げる。
   表示のみで集計・編集・スクロール挙動には影響しない。 */
#data-grid .jexcel > thead > tr > td {
    box-shadow: 0 3px 5px -2px rgba(15, 23, 42, 0.13);
}
/* P-193: 1列目の右端の影は、かつて `#data-grid td:first-child` に当てていたが、それは非表示の
   行番号セル（P-20 の visibility: collapse）にしか一致せず、実際の1列目（data-x="0"）には
   影が無かった（上の境界にだけ影があり、左の固定列の境界には無い非対称）。影を data-x="0" へ移す。
   - 影の値はカスタムプロパティ --row-header-edge-shadow に置く。列固定（N-17）中は最後の固定列
     （.cell-frozen-col-last）が右端の影を持つので、行ヘッダー列と固定列の間に影が二重に出ないよう、
     表に .cell-frozen-col-last があるときは透明な影へ差し替える（:has で表ごとに判定）。
   - 本文側は `:where()` で包んで詳細度を 0-1-1（td[data-x="0"]）に留める。同じセルに box-shadow で
     描く状態表示——jspreadsheet の選択枠（.highlight-left / .highlight-top の外側の線）と、
     縦軸のグリッド内検索の一致（.cell-search-match / -active の内枠）——の方が常に勝ち、影が
     状態表示を消さないようにするため（その状態の間だけ影は出ない）。
   - ヘッダー行の角（data-x="0"）は上の P-11 の下向きの影を持つので、1つの box-shadow に併記する
     （.cell-frozen-col-last と同じ考え方）。こちらは P-11 の規則に勝つ必要があるので #data-grid の詳細度のまま。 */
#data-grid .jexcel {
    --row-header-edge-shadow: 2px 0 5px -2px rgba(15, 23, 42, 0.13);
}
#data-grid .jexcel:has(td.cell-frozen-col-last) {
    --row-header-edge-shadow: 0 0 transparent;
}
:where(#data-grid .jexcel > tbody > tr) > td[data-x="0"] {
    box-shadow: var(--row-header-edge-shadow);
}
#data-grid .jexcel > thead > tr > td[data-x="0"] {
    box-shadow: 0 3px 5px -2px rgba(15, 23, 42, 0.13), var(--row-header-edge-shadow);
}

/* Global Form Utility Classes */
.form-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-bottom: 16px;
}

/* P-139: 指し示す入力欄が1つに定まらない見出し（ラジオのカード群の問いかけ）は
   <label> ではなく <fieldset> + <legend> で括る。for も囲みも持たない <label> は
   支援技術から「どの入力欄のラベルでもないただの文字」に見え、
   「この7枚は1つの問いに対する選択肢だ」という括りが読み上げに届かないため。
   <fieldset>／<legend> はブラウザ既定で枠線・内側余白・min-inline-size: min-content・
   左右マージンを持つので、.form-group の見た目（縦並び flex・gap 8px・下マージン 16px）へ戻す。 */
fieldset.form-group {
    border: 0;
    padding: 0;
    margin-inline: 0;
    min-inline-size: 0;
}

/* <legend> はフレックスの項目にならず（ブラウザが箱の外へ出して描く）、
   .form-group の gap: 8px が見出しと中身の間には効かない。実測で 8px 詰まったので
   同じ 8px を下マージンで足し、<div> + <label> だったときの隙間へ戻す。 */
fieldset.form-group > legend.form-label {
    padding: 0;
    margin-bottom: 8px;
}

.form-label {
    font-size: var(--fs-md);
    font-weight: 600;
    color: var(--text-muted);
    font-family: var(--font-heading);
}

/* P-81: 入力欄と紐付いたラベル（for 付き）はクリックでフォーカスが移るため、
   その当たり判定があることをカーソル形状で示す。for の無い見出し（span）は既定のまま。 */
label.form-label[for] {
    cursor: pointer;
}

/* P-86: 必須入力項目の目印。空のまま実行ボタンを押すとトーストで差し戻される項目に付ける。
   `*` 記号ではなく「必須」の文字にしているのは、支援技術がラベルと続けて
   「シート名称 必須」と読み上げられるようにするため（記号だと読み上げ方が環境依存になる）。
   HTML の `required` 属性は足さない（ブラウザ標準のバリデーションUIが割り込み、
   既存のトースト警告と二重に出るため。表示のみの目印に留める）。 */
.form-label-required {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: var(--radius-pill);
    background-color: var(--red-50);
    color: var(--red-700);
    border: 1px solid var(--red-200);
    font-size: var(--fs-2xs);
    font-weight: 700;
    line-height: 1.5;
    vertical-align: 1px;
}

/* Global Form Input Style */
.form-input {
    padding: 10px 14px;
    border: 1px solid var(--slate-300);
    border-radius: var(--radius-md);
    background-color: #ffffff;
    color: var(--text);
    font-size: var(--fs-lg);
    transition: var(--motion-base) var(--motion-ease);
    transition-property: background-color, border-color, box-shadow, opacity;
    outline: none;
    box-shadow: var(--shadow-sm);
    font-family: inherit;
    width: 100%;
    box-sizing: border-box;
}

.form-input:focus {
    border-color: var(--primary);
    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
}

.form-input::placeholder {
    /* --slate-400（#94a3b8）は白地で 2.56:1 と SC 1.4.3 の 4.5:1 を大きく下回る。
       プレースホルダーも文字なので、白地で 4.76:1 の --text-muted を使う（P-175）。 */
    color: var(--text-muted);
}

/* P-197: 無効な入力欄の見た目はここ1本で決める。.form-input は背景色・文字色を明示しているため、
   ブラウザ既定の「無効の灰色」が上書きされて、無効でも有効と見分けが付かなかった
   （グラフの「系列の向き」・値のコピーの選択欄・AI 実行中の指示欄・閲覧のみのフリーシート名など）。
   以前は関数ビルダー（#ff-form-pane の中）にだけ同じ宣言があった。 */
.form-input:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    background-color: var(--slate-100);
}

/* Password field with show/hide toggle */
.password-input-wrapper {
    position: relative;
}

.password-input-wrapper .form-input {
    padding-right: 40px;
}

.btn-toggle-password {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    cursor: pointer;
    padding: 6px;
    line-height: 1;
    font-size: var(--fs-xl);
    color: var(--text-muted);
}

.btn-toggle-password:hover {
    color: var(--text);
}

/* Slim table for management */
.management-table {
    width: 100%;
    /* P-154: 無限定の `table` から受け取っていた既定値。表の側で明示する。 */
    font-size: 0.9rem;
    border-collapse: separate;
    border-spacing: 0;
    background: white;
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    border: 1px solid var(--border-color);
}

/* 横に広い表のはみ出しを、表自身の枠の中だけで受け止める（Q-157）。
   .table-scroll（縦スクロール・角丸と枠線を枠側へ移す）とは別物で、こちらは
   .management-table の枠・角丸をそのまま残したまま横方向だけを面倒見る。
   ページ全体を横スクロールさせると、絞り込みの操作列やヘッダーまで一緒に流れてしまう。 */
.table-scroll-x {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

/* .table-scroll-x を「実際に」効かせるための受け皿（Q-157）。
   ブロック整形のままだと、中の表の min-content 幅がカード → .page-content →
   .app-container（縦フレックス）と伝播し、**枠がページ側へ押し広げられて**
   overflow-x が発火しない（実測: 900px 幅で .page-content が 1110px になる）。
   1列グリッドの minmax(0, 1fr) はトラックが min-content 未満まで縮むことを許すため、
   ここで伝播が止まり、はみ出しは .table-scroll-x が受け持つ。
   ブロック整形との違いはマージンの相殺のみで、中身は margin-bottom しか持たないため
   見た目は変わらない。 */
.admin-card-fluid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
}

.management-table th, .management-table td {
    padding: 14px 16px;
    text-align: left;
    border: none;
    border-bottom: 1px solid var(--border-color);
    /* P-154: 無限定の `th, td` から受け取っていた下限幅。列が多い一覧で1列が潰れないよう、
       表の側で明示する。 */
    min-width: 80px;
}

.management-table th {
    background-color: var(--slate-50);
    font-weight: 700;
    color: var(--text-muted);
    font-family: var(--font-heading);
    font-size: var(--fs-md);
    /* P-153: 無限定の `th` から受け取っていた字間。 */
    letter-spacing: 0.05em;
}

.management-table tr:last-child td {
    border-bottom: none;
}

.management-table tr:hover td {
    background-color: var(--slate-100);
}

/* テナント管理表の「DB状態」列（OW-08）。正常は目立たせず、要確認だけを拾えるようにする。 */
/* 状態表示の3色。テナントDBのスキーマ状態（表の「DB状態」列）と、メール送信カードの
   要約行が同じ意味づけ（正常／要対応／不明）で共有する。 */
.db-status-ok,
.email-status-ok {
    color: var(--text-muted);
}

.db-status-error,
.email-status-error {
    color: var(--red-700);
    font-weight: 600;
}

.db-status-unknown,
.email-status-unknown {
    color: var(--amber-700);
}

/* Badge styles for roles */
.badge {
    display: inline-block;
    padding: 4px 10px;
    border-radius: var(--radius-pill);
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    font-family: var(--font-heading);
    letter-spacing: 0.05em;
}
.badge.SuperAdmin { background-color: var(--amber-100); color: var(--amber-800); border: 1px solid var(--amber-200);}
.badge.TenantAdmin { background-color: var(--green-100); color: var(--green-800); border: 1px solid var(--green-200);}
.badge.GeneralUser { background-color: var(--sky-100); color: var(--sky-800); border: 1px solid var(--sky-200);}
.badge-pending { background-color: var(--amber-100); color: var(--amber-800); border: 1px solid var(--amber-200); text-transform: none; letter-spacing: normal; }
.badge-active { background-color: var(--slate-100); color: var(--slate-600); border: 1px solid var(--border-color); text-transform: none; letter-spacing: normal; }

/* Modal styles */
.modal { 
    display: none; 
    position: fixed; 
    z-index: var(--z-modal); 
    left: 0; 
    top: 0; 
    width: 100%; 
    height: 100%; 
    overflow: hidden; 
    background-color: rgba(15, 23, 42, 0.4); 
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    animation: modalBgFadeIn 0.2s ease-out;
}

@keyframes modalBgFadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

.modal-content { 
    background-color: #ffffff; 
    margin: 3% auto; 
    border: 1px solid rgba(255,255,255,0.2); 
    /* width/height に枠線を含める。content-box のままだと、width: 100% を上書きする
       モーダル（キーボードショートカット一覧・オンボーディング）の実寸が常に
       「容器 ＋ 枠線 2px」になり、角丸と枠が画面の外へ出て左右の縁が切れて見える（P-163）。 */
    box-sizing: border-box; 
    width: 90%; 
    max-width: 1200px;
    height: 85%; 
    display: flex; 
    flex-direction: column; 
    border-radius: 16px; 
    box-shadow: var(--shadow-lg); 
    animation: modalContentFadeIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes modalContentFadeIn {
    from { opacity: 0; transform: scale(0.95) translateY(20px); }
    to { opacity: 1; transform: scale(1) translateY(0); }
}

.modal-header { 
    padding: 20px 24px; 
    background-color: rgba(255, 255, 255, 0.9); 
    display: flex; 
    justify-content: space-between; 
    align-items: center; 
    border-bottom: 1px solid var(--border-color);
    border-radius: 16px 16px 0 0;
}

.modal-footer {
    padding: 16px 24px;
    background-color: var(--slate-50);
    border-top: 1px solid var(--border-color);
    border-radius: 0 0 16px 16px;
    display: flex;
    justify-content: flex-end;
    gap: 12px;
}

/* P-92: フッターに実行系ボタンが2つ以上並ぶモーダル（検索と置換）で、取り消し側を左端へ離すための修飾子。
   他のモーダルのように「取り消し側 → 実行系」と隣接させると、位置と配色だけでは実行系と見分けが付かないため。 */
.modal-footer-dismiss {
    margin-right: auto;
}

/* P-97: 右側に実行系と並ぶ破壊的操作（セルコメントの「削除」）だけ、隣の主ボタンとの
   間隔を広げる。左端は「押しても安全な場所」＝取り消し側に譲ったうえで、削除と保存が
   隣り合うことによる誤クリックを距離で緩和するための修飾子（.modal-footer の gap 12px
   ＋ この 16px ＝ 28px）。 */
.modal-footer-danger {
    margin-right: 16px;
}

.modal-header h2 { 
    margin: 0; 
    font-size: var(--fs-3xl); 
    font-weight: 700; 
    color: var(--text); 
    font-family: var(--font-heading);
}

.close-btn { 
    /* P-109: #94a3b8 は白背景で 2.56:1 と大きい文字の基準 3:1 にも届かない。
       モーダルを閉じる導線なので、既存パレットの1段濃い --text-muted（4.76:1）へ寄せる。 */
    color: var(--text-muted); 
    font-size: var(--fs-4xl); 
    font-weight: 400; 
    cursor: pointer; 
    /* P-184: :hover は文字色と背景色を同時に変える。color だけを補間すると、
       背景だけが一瞬で付いて文字色が遅れて追いかけるため、両方を列挙する。 */
    transition: var(--motion-base);
    transition-property: background-color, color;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
}

.close-btn:hover { 
    color: var(--text); 
    background-color: var(--slate-100);
}
/* P-188: 押している間はホバーより一段濃い灰色にする（押し込みは即座に、戻りは補間で）。 */
.close-btn:active {
    background-color: var(--slate-200);
    transition-duration: 0s;
}

.modal-body { 
    display: flex; 
    flex-grow: 1; 
    overflow: hidden; 
    background-color: #ffffff; 
}

.dim-sidebar { 
    width: 260px; 
    border-right: 1px solid var(--border-color); 
    background: var(--slate-50); 
    padding: 20px; 
}

.dim-sidebar ul { list-style-type: none; padding: 0; margin: 0; }

.dim-sidebar li { 
    padding: 12px 16px; 
    cursor: pointer; 
    border-radius: var(--radius-md);
    margin-bottom: 4px;
    font-size: var(--fs-lg);
    font-weight: 500;
    transition: var(--motion-base);
    transition-property: background-color, color, border-color, box-shadow;
    color: var(--text-muted);
}

.dim-sidebar li:hover { 
    background: var(--slate-200); 
    color: var(--text); 
}

.dim-sidebar li.active { 
    background: var(--primary); 
    color: white; 
    font-weight: 600; 
    box-shadow: 0 2px 4px rgba(79, 70, 229, 0.2);
}

.dim-main { 
    flex-grow: 1; 
    padding: 30px; 
    overflow-y: auto; 
    background: #ffffff; 
}

.btn-danger { 
    /* P-109: 白文字を #ef4444（--red-500） に置くと 3.76:1 で 4.5:1 に届かない。既定を従来のホバー色 #dc2626（--red-600）（4.83:1）へ上げ、
       ホバーはもう1段濃い #b91c1c（--red-700）（6.47:1）へずらして押下時の変化を保つ。 */
    background: var(--red-600); 
    color: white; 
    border: none;
}
/* P-206: 無効な確定ボタン（テナント削除・復元。テナントIDを打つまで disabled）が、ホバーで濃い赤と影を出して
   押せそうに見えないよう、他のボタンと同じく :not(:disabled) を付ける。 */
.btn-danger:hover:not(:disabled) { 
    background: var(--red-700); 
    box-shadow: 0 4px 6px rgba(185, 28, 28, 0.3);
}
/* P-188: 押している間はもう1段濃い赤にして影を浅くする（白文字との比は 8.3:1）。 */
.btn-danger:active:not(:disabled) {
    background: var(--red-800);
    box-shadow: 0 1px 2px rgba(185, 28, 28, 0.3);
    transition-duration: 0s;
}

#dim-edit-table { width: 100%; }
#dim-edit-table th, #dim-edit-table td { text-align: left; background: none; position: static; min-width: auto; }
/* P-99: メンバー編集表の見出し行を固定する。スクロールポートは表の祖先の .dim-main なので、
   .management-table が角丸クリップのために持つ overflow: hidden を外さないと（表自身が
   スクロールコンテナ扱いになり）sticky が効かない。外した分の角丸は、枠線を描いている表本体
   ではなく四隅のセルに持たせて見た目を保つ。
   上の `#dim-edit-table th, #dim-edit-table td` が position: static と background: none を
   指定しているため、それより詳細度の高い thead 付きセレクタで上書きする。背景は透過のままだと
   スクロールした本文が透けるので、他の一覧表（.management-table th）と同じ淡いグレーを与える。 */
#dim-edit-table { overflow: visible; }
#dim-edit-table thead th {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky-head);
    background-color: var(--slate-50);
}
#dim-edit-table thead th:first-child { border-top-left-radius: 12px; }
#dim-edit-table thead th:last-child { border-top-right-radius: 12px; }
#dim-edit-table tbody tr:last-child td:first-child { border-bottom-left-radius: 12px; }
#dim-edit-table tbody tr:last-child td:last-child { border-bottom-right-radius: 12px; }
/* P-154: 行 hover の色を ID セレクタで指定し直す。上の
   `#dim-edit-table th, #dim-edit-table td { background: none }`（詳細度 1-0-1）は
   `.management-table tr:hover td`（0-2-1）より強く、これまでは無限定の
   `tbody tr:hover td` に付いていた `!important` だけが勝っていた。その `!important` を
   グリッドの中へ閉じたため、この表だけ行 hover が消える（実測で検出）。
   ID を含む 1-2-1 で指定し直して、他の一覧表と同じ挙動に戻す。 */
#dim-edit-table tbody tr:hover td { background-color: var(--slate-100); }

/* Custom Scrollbar */
::-webkit-scrollbar {
    width: 8px;
    height: 8px;
}
::-webkit-scrollbar-track {
    background: transparent; 
}
::-webkit-scrollbar-thumb {
    background: var(--slate-300); 
    border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
    background: var(--slate-400); 
}

/* Information Guide Banner (for aggregated view mode) */
.info-banner {
    display: none; /* Controlled by JS */
    align-items: center;
    gap: 12px;
    background-color: #f0f7ff; /* Very soft slate blue */
    border: 1px solid var(--sky-100);
    border-radius: var(--radius-lg);
    padding: 12px 18px;
    margin-bottom: 20px;
    box-shadow: var(--shadow-sm);
    animation: slideDown 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes slideDown {
    from {
        opacity: 0;
        transform: translateY(-12px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.info-banner-icon {
    color: var(--sky-600); /* Sky blue information icon */
    font-size: var(--fs-3xl);
    flex-shrink: 0;
}

/* P-216: 文字サイズは段（--fs-*）から選ぶ。バナーは画面内の既定の --fs-md。 */
.info-banner-text {
    color: var(--sky-700);
    font-size: var(--fs-md);
    line-height: 1.5;
}

.info-banner-text strong {
    font-weight: 700;
}

.info-banner-text span.dim-pill {
    background-color: var(--sky-100);
    color: var(--sky-700);
    padding: 2px 8px;
    border-radius: var(--radius-sm);
    font-weight: 600;
    border: 1px solid var(--sky-200);
    font-size: var(--fs-sm);
    margin: 0 2px;
    display: inline-block;
}

/* Selection status bar below the grid (Excel-like: count/sum/average of the selected cells) */
.grid-selection-stats {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    /* 操作ボタン群（一括入力・Undo/Redo・コメント）は左側にまとめ、読み取り情報（入力完了率・選択統計）は
       右側にまとめる。space-between だと画面幅に応じて5要素が均等に離れ、操作ボタン同士のまとまりが崩れて
       いた（P-73）。.grid-comment-group の margin-right:auto で左右2グループに分けている。 */
    /* 操作ボタン群に範囲選択の統計（ピル5個で約700px）を足すと 1440px でも1行に収まらないので、
       統計の塊ごと次の行へ送る。折り返さないと統計が残り幅へ押し込まれ、選択した瞬間にバーが
       50px から 92〜141px へ伸びて、描画時のバーの高さで決めたグリッドの高さ（calcGridHeight）と
       食い違っていた（P-218）。 */
    flex-wrap: wrap;
    gap: 6px 18px;
    padding: 8px 16px;
    background: var(--slate-50);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    /* バーの文字サイズは段（--fs-*）から選ぶ。以前は 12.5px／11.5px の半端な直書きで、中の見出し・入力率バッジの
       12px（--fs-sm）と並んで 11／11.5／12／12.5px の4種類が1本のバーに混ざっていた（P-213）。 */
    font-size: var(--fs-sm);
    color: var(--text-muted);
}

.grid-selection-stats strong {
    color: var(--text);
    font-weight: 700;
    margin-left: 4px;
}

/* 選択範囲への一括入力（ステータスバー左側）: 範囲選択後に値を入力し、選択範囲内の
   編集可能セルすべてへ一括で書き込む。 */
.grid-fill-group { display: flex; align-items: center; gap: 6px; }
/* 一括入力欄が「選択範囲に対する操作」であることを初見でも一目で分かるよう見出しを付ける（P-05）。表示のみ。 */
.grid-fill-label { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; font-size: var(--fs-sm); color: var(--text-muted); white-space: nowrap; margin-right: 2px; }
.grid-fill-label i { color: var(--slate-400); font-size: var(--fs-xs); }
.grid-fill-input { width: 110px; height: var(--toolbar-ctl-h); padding: 0 8px; font-size: var(--fs-sm); }
.grid-fill-btn { height: var(--toolbar-ctl-h); padding: 0 12px; font-size: var(--fs-sm); white-space: nowrap; }

/* Undo/Redo（N-11）: 保存前の編集操作を元に戻す/やり直す。履歴が空のときは無効化表示。 */
.grid-undo-group { display: flex; align-items: center; gap: 4px; }
.grid-undo-btn, .grid-redo-btn { height: var(--toolbar-ctl-h); width: 34px; padding: 0; font-size: var(--fs-md); }

/* セルコメント: 単一セル選択時のみ有効化されるボタン。既存コメントがあるときは active クラスで強調する。 */
/* 操作ボタン群の右端。margin-right:auto で残りの余白を吸収し、これ以降の読み取り情報（完了率バッジ・選択統計）を
   右側にまとめて押し出す。入力完了率バッジが非表示（.hidden）でも成立する（P-73）。 */
.grid-comment-group { display: flex; align-items: center; margin-right: auto; }
.grid-comment-btn { height: var(--toolbar-ctl-h); padding: 0 12px; font-size: var(--fs-sm); white-space: nowrap; }
.grid-comment-btn.btn-cell-comment-active { background: var(--blue-100); border-color: var(--blue-300); color: var(--blue-700); }
.cell-comment-textarea { resize: vertical; min-height: 110px; }

/* N-06: データ入力完了率インジケーター。現在描画中の末端×末端セルのうち、値が入力済み（非ゼロ）の
   件数をバッジで常時表示する（選択操作とは独立、renderGrid のたびに更新）。 */
.grid-completion-badge { display: inline-flex; align-items: center; gap: 6px; padding: 2px 10px; background: #ffffff; border: 1px solid var(--border-color); border-radius: var(--radius-pill); font-size: var(--fs-sm); white-space: nowrap; color: var(--text-muted); }
.grid-completion-badge i { color: var(--slate-400); font-size: var(--fs-xs); }
.grid-completion-badge #grid-completion-badge-text strong { color: var(--text); font-weight: 700; }
/* 全セル入力済みのときは達成を視覚的に強調する。 */
.grid-completion-badge.grid-completion-full { background: var(--green-50); border-color: var(--green-300); color: var(--green-700); }
.grid-completion-badge.grid-completion-full i { color: var(--green-500); }
.grid-completion-badge.grid-completion-full #grid-completion-badge-text strong { color: var(--green-700); }

/* 折り返すかどうかを中身ではなく固定の 720px（ピル5個ぶん）で決める。ヒント文と統計で幅が違っても
   同じ行に留まるので、セルを選んでもバーの高さが変わらない（P-218）。右寄せは、読み取り情報を
   右側へまとめる P-73 の配置を2行目でも保つため。min-height はピル1個の高さで、1行のヒント文のときも
   同じ高さにする。 */
.grid-selection-stats-text { flex: 1 1 720px; min-width: 0; min-height: 25px; text-align: right; }
/* 未選択時はヒント文を控えめ（イタリック・淡色）にして「セルを選ぶと集計が出る」ことを促す。 */
.grid-selection-stats-text.selection-stats-hint { font-style: italic; color: var(--slate-400); }
/* 範囲選択中はバー全体を淡い藍色にし、各指標をピル状にまとめて素早く読み取れるようにする。 */
.grid-selection-stats.selection-stats-active { background: var(--indigo-50); border-color: var(--indigo-200); }
.grid-selection-stats-text .sel-stat { display: inline-flex; align-items: baseline; gap: 6px; white-space: nowrap; padding: 2px 10px; margin-right: 8px; background: #ffffff; border: 1px solid var(--indigo-200); border-radius: var(--radius-pill); }
.grid-selection-stats-text .sel-stat:last-child { margin-right: 0; }
.grid-selection-stats-text .sel-stat-key { color: var(--text-muted); font-size: var(--fs-xs); }
.grid-selection-stats-text .sel-stat strong { margin-left: 0; color: var(--primary); }

/* N-35: 統計表示中はテキスト全体がコピーボタンになる（未選択のヒント表示中は role/tabindex ごと外す）。
   末尾のコピーアイコンで「押せる」ことを示し、ホバー・フォーカスで手掛かりを強める。 */
.grid-selection-stats-text.selection-stats-copyable { cursor: pointer; border-radius: var(--radius-pill); }
.grid-selection-stats-text .sel-stat-copy-icon { margin-left: 8px; color: var(--slate-400); font-size: var(--fs-xs); vertical-align: middle; }
.grid-selection-stats-text.selection-stats-copyable:hover .sel-stat-copy-icon,
.grid-selection-stats-text.selection-stats-copyable:focus-visible .sel-stat-copy-icon { color: var(--primary); }
.grid-selection-stats-text.selection-stats-copyable:hover .sel-stat { border-color: var(--primary); }
.grid-selection-stats-text.selection-stats-copyable:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }

.hero-glow-1 {
    width: 600px;
    height: 400px;
    background: rgba(79, 70, 229, 0.18);
    top: -100px;
    left: -200px;
}

.hero-glow-2 {
    width: 500px;
    height: 350px;
    background: rgba(124, 58, 237, 0.14);
    top: 100px;
    right: -150px;
}

@keyframes capacityPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.55); }
    50%      { box-shadow: 0 0 0 6px rgba(245, 158, 11, 0); }
}

/* Entry animations */
@keyframes fadeSlideUp {
    from { opacity: 0; transform: translateY(24px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes fadeIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Spinner Animation */
.spinner {
    display: inline-block;
    width: 14px;
    height: 14px;
    border: 2.5px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    border-top-color: #ffffff;
    animation: spin 0.8s ease-in-out infinite;
    margin-right: 6px;
    flex-shrink: 0;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

/* Toast Notifications */
/* top はヘッダー実高さ（JS が --header-h に反映、utils.js の initToastPosition）+ 余白。
   ヘッダーは画面幅で1〜2行に折り返すため固定値ではなく変数化し、右上の保存・アカウント等の
   操作ボタンにトーストが重なってクリックできなくなるのを防ぐ（P-33）。JS未反映時は既定値64pxで代用。 */
#toast-container {
    position: fixed;
    top: calc(var(--header-h, 64px) + 12px);
    right: 20px;
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: min(380px, calc(100vw - 40px));
    pointer-events: none;
}

.toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    background: var(--card-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--border-color);
    border-left: 4px solid var(--text-muted);
    border-radius: 10px;
    padding: 12px 14px;
    box-shadow: var(--shadow-lg);
    font-size: var(--fs-lg);
    line-height: 1.5;
    color: var(--text);
    animation: toast-in 0.25s ease-out;
    word-break: break-word;
}

.toast.toast-hide {
    animation: toast-out 0.2s ease-in forwards;
}

.toast-icon { flex-shrink: 0; margin-top: 1px; font-size: var(--fs-2xl); }
.toast-body { flex-grow: 1; white-space: pre-line; }
.toast-close {
    flex-shrink: 0;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--text-muted);
    font-size: var(--fs-lg);
    padding: 0 2px;
    line-height: 1;
}
.toast-close:hover { color: var(--text); }

.toast-success { border-left-color: var(--emerald-500); }
.toast-success .toast-icon { color: var(--emerald-500); }
.toast-error { border-left-color: var(--red-500); }
.toast-error .toast-icon { color: var(--red-500); }
.toast-warning { border-left-color: var(--amber-500); }
.toast-warning .toast-icon { color: var(--amber-500); }
.toast-info { border-left-color: var(--primary); }
.toast-info .toast-icon { color: var(--primary); }

@keyframes toast-in {
    from { opacity: 0; transform: translateX(20px); }
    to { opacity: 1; transform: translateX(0); }
}
@keyframes toast-out {
    to { opacity: 0; transform: translateX(20px); }
}

@media (prefers-reduced-motion: reduce) {
    .toast, .toast.toast-hide { animation: none; }
    .unsaved-badge { animation: none; }
    /* 総量が分からないときの往復アニメーション。動きを止めても「処理中である」ことは
       スピナー横の文言と補足文言（受信量など）で伝わる。 */
    .loading-progress-bar-indeterminate { animation: none; transform: none; width: 100%; }
    .loading-progress-bar { transition: none; }
}

/* === Migrated from inline styles === */

/* Utility */
.hidden { display: none !important; }
/* 一覧の行に並べる小さめのボタン（システム管理画面のテナント/ユーザー一覧の「編集」「削除」）。
   以前は system.js が btn.style.fontSize / btn.style.padding を直接指定しており、同じ2行が
   削除ボタンと編集ボタンで重複していた（E-94）。見た目の定義はここに置く。
   隣り合ったときの間隔も、JS の marginRight ではなく隣接セレクタで持つ。 */
.btn-compact { font-size: var(--fs-sm); padding: 4px 8px; }
.btn-compact + .btn-compact { margin-left: 4px; }
/* 一覧の「操作」列を右寄せする（E-100）。`.management-table th, .management-table td` が
   text-align: left を要素セレクタ込みの詳細度（0,1,1）で指定しているため、クラス単独の
   `.text-right`（0,1,0）では上書きできない。表の中でも効くよう同じ詳細度の指定を併記する。 */
.text-right { text-align: right; }
.management-table th.text-right,
.management-table td.text-right { text-align: right; }

/* System admin page layout */
.page-content { padding: 20px; max-width: 1200px; margin: 0 auto; }
.header-user-info { margin-right: 15px; color: var(--slate-600); font-weight: bold; }
.admin-card { background: white; padding: 30px; border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); margin-bottom: 30px; border: 1px solid var(--border-color); }
.admin-card-title { margin-top: 0; margin-bottom: 25px; font-size: var(--fs-3xl); font-weight: 700; }
.form-section { margin-bottom: 30px; background: var(--slate-50); padding: 20px; border-radius: 10px; border: 1px solid var(--border-color); }
.form-section-row { display: flex; gap: 20px; align-items: flex-end; flex-wrap: wrap; }
.form-section-row-sm { display: flex; gap: 15px; align-items: flex-end; flex-wrap: wrap; }
.form-group-inline { margin-bottom: 0; }
.input-w-150 { width: 150px; }
.input-w-160 { width: 160px; }
.input-w-180 { width: 180px; }
.input-w-230 { width: 230px; }
.input-w-250 { width: 250px; }
.btn-action { height: 42px; }
.btn-refresh { height: 38px; padding: 0 14px; }
.btn-page { padding: 6px 14px; }
.audit-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 12px; }
/* P-57: 「ラベル＋コントロール」を1つのflexアイテム（audit-filter-item）にまとめて折り返し単位にし、
   ラベルと入力欄が別々の行に分かれて左端が不揃いになるのを防ぐ。操作ボタン群（audit-actions）も
   独立したグループとして右寄せ・折り返しさせる。絞り込みロジック・API呼び出しには影響しない。 */
/* P-98: 絞り込み欄は開閉ボタン・操作ボタン群と同じ flex コンテナ（audit-header）の兄弟だが、
   flex-basis:100% で必ず次の行へ送る。こうすると開いている状態の段組み（1段目＝開閉ボタン＋
   操作ボタン群／2段目以降＝絞り込み欄）が従来の高さのまま収まり、閉じたときだけ2段目が消える。 */
.audit-controls { display: flex; gap: 12px 16px; align-items: center; flex-wrap: wrap; flex: 1 1 100%; }
.audit-filter-item { display: flex; align-items: center; gap: 8px; flex-wrap: nowrap; }
.audit-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }
.audit-label-nowrap { margin-bottom: 0; white-space: nowrap; }
/* P-98: 絞り込み欄の開閉ボタン。見た目（アイコン＋ラベル＋シェブロン、開いていると反転）は
   P-76（フリーシートの数式ヘルプ）の作法を踏襲する。<details> ではなくボタン＋aria-expanded に
   したのは、開閉ボタンと操作ボタン群を同じ行に並べたままにするため（<details> だと開いた瞬間に
   中身の幅で1行を占有し、開いている状態が従来より1段ぶん高くなる）。 */
.audit-filter-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    padding: 4px 0;
    border: none;
    background: none;
    cursor: pointer;
    font-family: var(--font-heading);
    font-size: var(--fs-md);
    font-weight: 700;
    color: var(--text-muted);
}
.audit-filter-toggle:hover { color: var(--text); }
.audit-filter-toggle:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 4px; }
.audit-filter-chevron { font-size: var(--fs-3xs); transition: transform var(--motion-fast) ease; }
.audit-filter-toggle[aria-expanded="true"] .audit-filter-chevron { transform: rotate(180deg); }
/* 開いていれば条件は絞り込み欄そのものに見えているので、チップは重複表示になるため隠す。
   P-103 でチップを開閉ボタンの外へ出したため、子孫セレクタではなく隣接セレクタで指す
   （app.html でチップは開閉ボタンのすぐ次の兄弟に置いてある）。 */
.audit-filter-toggle[aria-expanded="true"] + .audit-filter-chips { display: none; }
/* 条件が多いときはチップを折り返す（横に切り捨てない）。絞っている条件が黙って画面外へ
   消えると「見えているログが全部ではない」ことに気づけなくなるため、行が増える方を選ぶ。
   P-103: 開閉ボタンと操作ボタン群のあいだの余白を埋める flex アイテムとして振る舞わせる
   （min-width: 0 が無いと長いチップが行をはみ出して操作ボタン群を押し出す）。 */
.audit-filter-chips { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; flex: 1 1 auto; min-width: 0; }
.audit-filter-chip {
    display: inline-block;
    max-width: 220px;
    padding: 1px 8px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-pill);
    background: var(--slate-50);
    font-family: var(--font-body);
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* 「条件なし」は状態の説明であって絞り込みチップではないので、枠を外して控えめに見せる。 */
.audit-filter-chip-none { border-color: transparent; background: transparent; font-weight: 500; color: var(--text-muted); }
/* Q-159: システム管理コンソールの操作ログは絞り込み欄を畳まないため、チップは開閉ボタンの隣ではなく
   絞り込み欄と表のあいだに独立した1行として置く（system.html）。見出しとチップを同じ行に並べ、
   条件が多いときはチップ側だけが折り返す。 */
.audit-filter-summary { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; min-width: 0; }
.audit-pagination { display: flex; justify-content: space-between; align-items: center; margin-top: 15px; }
.audit-page-info { font-size: var(--fs-md); color: var(--slate-600); }
/* P-66: ユーザー一覧の状態バッジ（.badge-active等）と同じ「淡い背景＋枠＋角丸」のピル状に揃え、
   操作ログの結果表示だけが背景・枠なしの色文字のまま浮いていた不統一を解消（表示のみ、判定ロジックは不変）。 */
.audit-status-success { display: inline-block; padding: 2px 10px; border-radius: var(--radius-pill); font-size: var(--fs-sm); font-weight: 700; color: var(--emerald-600); background-color: var(--emerald-100); border: 1px solid var(--emerald-200); }
.audit-status-error { display: inline-block; padding: 2px 10px; border-radius: var(--radius-pill); font-size: var(--fs-sm); font-weight: 700; color: var(--red-600); background-color: var(--red-50); border: 1px solid var(--red-200); }
.audit-target-jumpable { cursor: pointer; color: var(--primary); text-decoration: underline dotted; }
.audit-target-jumpable:hover { color: var(--primary-hover); }
/* E-79: 監査ログ表のセル装飾。テナント向け（audit-log.js）とSuperAdmin向け（system.js）の
   両方から使う共通クラス（system.js は Q-147 で ES モジュールになったが、表の組み立ては
   2画面で列構成が違うため共有しておらず、共有しているのはこの CSS 側）。
   省略表示の最大幅はテナント向け240px／SuperAdmin向け200pxと画面ごとに異なる。SuperAdmin 側は
   テナント列のぶん列が1つ多いので狭めており、**その画面の省略表示の列（対象・詳細）はすべて
   narrow を付ける**（Q-160。列ごとに幅を変えると、次に列を足す人がどちらに倣うか分からなくなる）。
   CSS 変数で画面ごとの値を切り替えている。
   セレクタを `td.` で修飾しているのは、かつて上方の全体ルール
   `td:first-child, th:first-child`（詳細度 0-1-1）が `white-space: pre` を当てており、
   素のクラス（詳細度 0-1-0）では日時列（1列目）で負けてしまったため。そのルールは P-151 で
   グリッドの容器（`#data-grid` / `#freesheet-grid`）へ限定したので監査ログ表にはもう
   当たらないが、各セルの `white-space` はこのクラス側で明示しているため計算値は変わらない。
   `td.` の修飾は他の表と作法を揃えるためそのまま残す。 */
td.audit-cell-compact { font-size: var(--fs-sm); }
td.audit-cell-nowrap { white-space: nowrap; }
td.audit-cell-truncate { font-size: var(--fs-sm); max-width: var(--audit-cell-max-width, 240px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
td.audit-cell-truncate-narrow { --audit-cell-max-width: 200px; }
.col-min-date { min-width: 140px; }
.ai-section { display: none; margin-top: 20px; background: linear-gradient(135deg, var(--violet-50) 0%, var(--violet-100) 100%); padding: 20px; border-radius: 10px; border: 1px solid var(--violet-200); box-shadow: var(--shadow-sm); }
.ai-section-title { font-weight: 700; color: var(--violet-700); margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
.ai-icon { color: var(--violet-600); }
/* P-216: AI への指示欄は他の入力欄（.form-input）と同じ --fs-lg。.ai-dim-textarea も同じ。 */
.ai-textarea { width: 100%; height: 80px; resize: none; border-color: #c084fc; font-family: inherit; font-size: var(--fs-lg); box-sizing: border-box; }
.ai-usage-count-danger { color: var(--red-500); }
.ai-usage-count-warning { color: var(--amber-500); }
.ai-usage-count-normal { color: var(--violet-600); }

/* app.html header */
.header-btn-mr { margin-right: 10px; }

/* Header dropdown menus (データ / 管理者メニュー / アカウント) */
.header-menu { position: relative; display: inline-block; }
.header-menu-caret { font-size: 0.7em; margin-left: 2px; opacity: 0.7; transition: transform var(--motion-base); }
.header-menu.open .header-menu-caret { transform: rotate(180deg); }
.header-menu-trigger-account { padding-left: 12px; padding-right: 12px; }
.header-menu-trigger-account i.fa-circle-user { font-size: 1.1rem; }
.header-menu-dropdown {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    /* box-sizing を border-box にした分（padding 6px×2 ＋ border 1px×2 ＝ 14px）を
       足して、見た目の最小幅を従来（content-box の 210px）と同じに保つ。 */
    min-width: 224px;
    background: var(--card-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    box-shadow: var(--shadow-lg);
    padding: 6px;
    z-index: var(--z-dropdown);
    display: none;
    /* N-52: 項目が増えるとドロップダウンが画面下端を越え、最下段の項目が
       スクロールでも到達できなくなる（375px でデータメニューが 32px 超過し、
       「利用状況サマリ」が押せなかった）。ドロップダウン自身をスクロールさせて
       必ず届くようにする。狭幅だけの問題ではない（デスクトップでも項目が増えれば
       同じことが起きる）ため全幅で有効にする。
       120px はヘッダー上端からドロップダウン上端までの最大見込み（ヘッダーの
       上下パディング＋トリガー1〜2段＋6px の隙間）に下側の余白を足したもの。
       狭幅（〜768px）はヘッダーが何段にも折り返すため、下の @media で
       ヘッダー高さそのものを差し引く厳密な式へ置き換える。 */
    max-height: calc(100vh - 120px);
    max-height: calc(100dvh - 120px);
    overflow-y: auto;
    overscroll-behavior: contain;
    /* 既定の content-box のままだと padding 6px×2 と border 1px×2 の計 14px が
       max-height の外に付き、上限どおりに収まらない（実測で毎回 14px 超過した）。 */
    box-sizing: border-box;
}
.header-menu-dropdown-right { left: auto; right: 0; }
.header-menu.open .header-menu-dropdown { display: block; }
.header-menu-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    box-sizing: border-box;
    padding: 9px 12px;
    border: none;
    background: transparent;
    color: var(--text);
    font-family: var(--font-heading);
    font-size: var(--fs-lg);
    font-weight: 600;
    text-align: left;
    border-radius: 7px;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--motion-fast);
}
.header-menu-item:hover { background: rgba(79, 70, 229, 0.08); }
/* display: flex を明示しているため UA の [hidden] { display: none } では消えない。
   .ob-step-action[hidden] と同じ作法で companion ルールを添える
   （「サンプルデータを削除」など、条件が揃ったときだけ出す項目のため）。 */
.header-menu-item[hidden] { display: none; }
.header-menu-item i { width: 18px; text-align: center; color: var(--text-muted); }
.header-menu-item-danger { color: var(--red-600); }
.header-menu-item-danger i { color: var(--red-600); }
.header-menu-item-danger:hover { background: rgba(239, 68, 68, 0.1); }
/* P-188: 押している間はホバーの色の不透明度を上げて一段濃くする。押した直後にメニューは
   閉じるが、押したまま指をずらした場合などに「押せている」ことが見える。
   危険側はホバーの赤い規則と詳細度が並ぶため、その後ろに赤系の押下を置く。 */
.header-menu-item:active { background: rgba(79, 70, 229, 0.16); transition-duration: 0s; }
.header-menu-item-danger:active { background: rgba(239, 68, 68, 0.18); }
.header-menu-item-file-hint {
    margin-left: auto;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
    background: rgba(100, 116, 139, 0.12);
    color: var(--text-muted);
    font-size: var(--fs-xs);
    font-weight: 500;
    white-space: nowrap;
}
.header-menu-item-file-hint-danger { background: rgba(220, 38, 38, 0.1); color: var(--red-600); }
.header-menu-divider { height: 1px; background: var(--border-color); margin: 6px 4px; }
.header-menu-userinfo { padding: 8px 12px 4px; color: var(--text-muted); font-size: var(--fs-md); line-height: 1.5; }
/* ユーザー情報末尾のロールバッジ（.badge、user-modal.jsのユーザー一覧と同じ配色）に上余白を付け、
   メール・テナントIDのテキストから視覚的に分離する（P-46, 表示のみ） */
.header-user-role-badge { margin-top: 4px; }

/* 表示オプションのドロップダウン（チェックボックス群＋グループ見出し） */
/* 上の .header-menu-dropdown と同じ理由で border-box の 14px 分を足してある（従来の見た目は 220px 相当）。 */
.display-menu-dropdown { min-width: 234px; }
.display-menu-group-title { padding: 6px 12px 2px; font-family: var(--font-heading); font-size: var(--fs-sm); font-weight: 700; color: var(--text-muted); }
.display-menu-option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border-radius: 7px;
    cursor: pointer;
    font-size: var(--fs-lg);
    font-weight: 600;
    color: var(--text);
    white-space: nowrap;
}
.display-menu-option:hover { background: rgba(79, 70, 229, 0.08); }
.display-menu-option input { cursor: pointer; }
/* P-196: 選択式の設定（表示単位・構成比・予実比較・固定する列数）も、先頭の既定の選択肢
   （円・表示しない・なし）以外を選んでいる間は、チェック済みの行と同じ淡い藍で強調する。
   既定が先頭にある <select> の行にだけ .display-menu-option-default-first を付ける（比較相手のように
   既定の無い選択には付けない）。option:checked は選択中の選択肢に一致するので CSS だけで追従する。
   N-82: disabled の欄は値が残っていても効いていない（階層順の間の表示件数）ので強調しない。 */
/* P-09: チェック済みのオプションを淡い藍背景＋藍文字で強調し、オン/オフを一目で
   把握できるようにする（チェックマークだけでは状態が分かりにくい）。ドロップダウン内の
   表示オプションが対象。表示のみ（CSS のみ）で挙動は変えない。 */
.display-menu-option:has(input:checked),
.display-menu-option-default-first:has(> select:not(:disabled) option:checked:not(:first-child)) {
    background: rgba(79, 70, 229, 0.12);
    color: var(--primary);
}
/* P-188: 押している間はチェック済みの色よりさらに一段濃くする。チェック済みの規則
   （:has の中身の分だけ詳細度が高い）にも勝つよう、同じ形のセレクタを並べる。
   単位セレクトの行（.display-menu-option-select）は行自体を押す部品ではないので除く。 */
.display-menu-option:not(.display-menu-option-select):active,
.display-menu-option:not(.display-menu-option-select):has(input:checked):active {
    background: rgba(79, 70, 229, 0.18);
}
/* N-02: 表示単位（円/千円/百万円）セレクトは他のオプションとレイアウトを揃えつつ、
   ラベルとセレクトを両端に配置してホバー時のクリック領域を確保する。 */
.display-menu-option-select { justify-content: space-between; cursor: default; }
/* P-215: 「並べる列」は字下げ＋ID (説明文) の長い選択肢が入る。閉じた欄の幅に上限を置き、説明文の長い列で
   「表示 ▾」のメニュー全体が広がらないようにする。先頭の ID は切れず、開いた一覧には全文が出る。 */
#sel-row-sort-col { max-width: 200px; }
/* P-208: 中の欄が disabled の行（予実比較「なし」の間の比較相手・ハイライトがオフの間の閾値）は、
   ホバーの藍の背景を付けず、見出しを淡い文字にして「いまは選べない」ことを行でも伝える。
   透明度は欄側の .form-input:disabled に任せる（行ごと 0.55 にすると欄が二重に淡くなる）。
   :has(:disabled) だと無効な <option> にも一致しうるので、直下の欄に限る。 */
.display-menu-option:has(> select:disabled, > input:disabled) { color: var(--text-muted); cursor: not-allowed; }
.display-menu-option:has(> select:disabled, > input:disabled):hover { background: transparent; }
.display-unit-select { width: auto; padding: 3px 6px; font-size: var(--fs-md); }
/* N-07: 条件付きハイライトの閾値入力（円）。表示単位セレクトと同じ横並びレイアウトに揃える。 */
.cond-highlight-threshold-input { width: 100px; padding: 3px 6px; font-size: var(--fs-md); text-align: right; }
/* P-63・P-195: 条件付きハイライトの閾値欄（updateCondHighlightThresholdUi()）と予実比較の「比較相手」
   （updateCompareCategoryUi()）は、意味を持たない間 disabled になる。淡色化は全画面共通の .form-input:disabled
   （opacity: 0.55）に任せ、ここで透明度を上書きしない（P-204。以前はこの2欄だけ 0.5 だった）。 */

/* app.html toolbar */
/* 軸設定パネルの役割（縦軸／横軸）を左端のアクセント色と方向アイコンで一目で区別できるようにする。
   密なツールバーで「どちらが行・列の設定か」を初見でも迷わず把握でき、色は既存パレット内（藍＝primary／空色＝info）に収める。 */
.axis-panel-row { border-left: 3px solid var(--primary); }
.axis-panel-col { border-left: 3px solid var(--sky-500); }
/* P-07: 表示オプション・グラフ・検索をまとめた「ツール」パネルにも左端アクセントを付け、
   縦軸（藍）・横軸（空色）と並ぶ機能グループとして視覚的なリズムを作る。色は中立的な
   スレートで、軸設定やAI（紫）と役割が混ざらないようにする。表示のみの調整。 */
.axis-panel-tools { border-left: 3px solid var(--slate-500); }
.axis-role-icon { margin-right: 5px; font-size: var(--fs-sm); }
.axis-panel-row .axis-role-icon { color: var(--primary); }
.axis-panel-col .axis-role-icon { color: var(--sky-500); }
.config-group-gap { gap: 15px; }

/* ツールバー内の単独アイコンボタン（軸の縦横入れ替え・横軸詳細設定・グリッド内検索の前後/クリア）は、
   既定の透明な btn-icon のままだと「ただのアイコン」に見えて初見ユーザーに押せると気づかれにくい。
   常時うっすらと枠線・背景を付けてボタンであることを示し、ホバーで藍色に強調、
   無効時は淡色にして操作不可を伝える。挙動・配置は変えず、見た目のアフォーダンスのみ強化。 */
.btn-icon-chip {
    background-color: #ffffff;
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-sm);
}
.btn-icon-chip:hover:not(:disabled) {
    background-color: var(--indigo-50);
    border-color: var(--indigo-200);
    color: var(--primary);
}
/* P-188: .btn-icon の押下（灰色）は、詳細度の並ぶ上のホバーの規則に後勝ちで負けて効かない。
   チップ用に、ホバーより一段濃い藍色で影を消した押下の規則を、ホバーの直後に置く。 */
.btn-icon-chip:active:not(:disabled) {
    background-color: var(--indigo-100);
    border-color: var(--indigo-300);
    color: var(--primary);
    box-shadow: none;
    transition-duration: 0s;
}
/* P-202: 無効なチップ（グリッド内検索の前/次の一致）も .config-group select:disabled・.form-input:disabled と
   同じ値（opacity: 0.55・cursor: not-allowed・背景 --slate-100）で淡色にする。以前は文字色を --slate-300 へ
   差し替えて cursor: default にしており、同じパネルの他の無効な欄と「押せない」の伝え方が違った。
   文字色は .btn-icon の既定（--text-muted）のまま——P-205 で .btn-icon:hover が :not(:disabled) を持ったので、
   無効なチップにホバーの藍色は付かない。 */
.btn-icon-chip:disabled {
    opacity: 0.55;
    cursor: not-allowed;
    background-color: var(--slate-100);
    box-shadow: none;
}

/* P-127: 初期状態で disabled なアイコンのみのボタン（前/次の一致・既定/お気に入り・元に戻す/やり直す）
   を包むラッパー。Chromium 系は disabled な要素へポインタイベントを届けないため、ボタン自身に付けた
   `title` はツールチップとして出ない——初見の利用者が「このアイコンは何なのか」を知りたいちょうど
   その時期に、名前を知る手段が無くなる。そこでラッパー側に `title`（名前＋押せるようになる条件）を
   持たせ、無効なうちはラッパーがホバーを受けて説明を出す。ボタンが有効になると、ボタン自身の
   `title` が内側で優先されるので従来どおりの文言に戻る。

   `inline-flex` は高さ対策。既定の `inline` のままだと flex アイテムとして block 化され、
   中の inline-flex なボタンがベースラインに乗ってディセンダ分だけ行箱が高くなり、
   ツールバーの高さが数 px 伸びてしまう。包む以外の見た目は変えない。 */
.btn-disabled-tip {
    display: inline-flex;
}

/* P-128: 視覚的にだけ隠すユーティリティ。読み上げ・`aria-describedby` の参照先としては
   生きたまま、画面には出さない。`display: none` や `visibility: hidden` では読み上げの
   対象からも外れてしまうため、1px に潰して切り抜く従来からの作法を使う。
   （狭幅時のヘッダーで同じ処理を直接書いている箇所があるが、あちらはメディアクエリ内で
   条件付きに効かせるものなのでこのクラスとは共有できない。） */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}
.label-flex { white-space: nowrap; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; }
.label-nowidth-flex { width: auto; text-align: left; cursor: pointer; display: inline-flex; align-items: center; gap: 4px; }
/* P-09: 縦軸／横軸パネルのチェックボックスラベル（すべて表示・末端メンバーのみ・集計位置）も
   トグルチップ風にして、チェック済みの状態を一目で分かるようにする。常時わずかな余白・角丸を
   持たせて見た目を安定させ、チェック時に淡い藍背景＋藍文字＋ブランド色のチェックボックスで強調する。
   表示のみ（CSS のみ）で挙動・配置ロジックは変えない。 */
.label-flex, .label-nowidth-flex {
    padding: 3px 8px;
    border-radius: 7px;
    transition: background-color var(--motion-fast), color var(--motion-fast);
}
.label-flex input[type="checkbox"],
.label-nowidth-flex input[type="checkbox"],
.display-menu-option input[type="checkbox"] {
    accent-color: var(--primary);
}
.label-flex:has(input:checked),
.label-nowidth-flex:has(input:checked) {
    background: rgba(79, 70, 229, 0.12);
    color: var(--primary);
}
/* AI サマリ操作パネル: 横幅いっぱいに広げず（flex-grow を外す）コンテンツ幅に収め、
   ツールバー内で間延びしないコンパクトな見た目にする（P-02）。タイトルと利用回数を
   1行にまとめて高さも抑える。機能（生成・利用回数表示・履歴）は不変。 */
.ai-summary-panel-inner { display: flex; flex-direction: column; justify-content: center; gap: 6px; background: linear-gradient(135deg, var(--violet-50) 0%, var(--violet-100) 100%); padding: 10px 14px; border: 1px solid var(--violet-200); border-radius: var(--radius-lg); min-width: 220px; }
.ai-panel-headline { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.ai-panel-title { font-weight: 700; color: var(--violet-700); display: flex; align-items: center; gap: 6px; font-size: var(--fs-md); }
.ai-panel-usage { font-size: var(--fs-xs); display: flex; align-items: center; gap: 4px; }
.ai-usage-label { font-weight: 600; }
/* P-229: AI 枠の淡い紫地（--violet-100）の上でも 6.38:1。--text-muted（4.01:1）では AA に届かない。 */
.ai-reset-label { color: var(--slate-600); }
.ai-panel-actions { display: flex; gap: 8px; }
.btn-ai-summarize { background: linear-gradient(135deg, var(--violet-600) 0%, var(--indigo-600) 100%); padding: 8px 12px; font-size: var(--fs-md); border-radius: var(--radius-md); box-shadow: 0 4px 6px -1px rgba(124, 58, 237, 0.2); flex: 1; }
.btn-ai-history { padding: 8px 12px; font-size: var(--fs-md); border-radius: var(--radius-md); flex-shrink: 0; }
.filters-header { font-weight: 600; margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center; color: var(--primary); }
/* 各フィルター見出しの漏斗アイコン（このコントロールが絞り込みであることを示す視覚的アンカー） */
.filter-dim-icon { color: var(--slate-400); font-size: var(--fs-xs); margin-right: 5px; }
/* 絞り込み対象ディメンションが無いときのヒント */
.filters-empty-hint { display: flex; align-items: center; gap: 6px; margin-top: 8px; padding: 4px 2px; color: var(--text-muted); font-size: var(--fs-sm); }
.filters-empty-hint i { color: var(--slate-400); }
/* P-221: ノート PC の高さでは、ツールバーの余白を詰めて下限 300px のグリッドを1画面に収める。
   P-224: このブロックは .ai-summary-panel-inner・.filters-header のトップレベル規則より後ろに置く。
   同じ詳細度なので、前に置くと padding と margin-bottom が後ろの規則に負けて効かない
   （GridHeightFollowsLayoutTests が位置を検査する）。 */
@media (min-width: 769px) and (max-height: 800px) {
    .toolbar {
        padding: 10px 24px;
        gap: 10px;
    }

    .axis-panel, .filters-panel, .ai-summary-panel-inner {
        padding: 8px 14px;
    }

    .axis-panel {
        gap: 6px;
    }

    .filters-header {
        margin-bottom: 0;
    }

    .filters {
        margin-top: 6px;
    }
}
/* P-223: ツールバーを1行の要約まで畳む（toolbar-collapse.js が .toolbar-collapsed を付け外しする）。
   開いている間、ボタンはツールバー下端の境界線にかかるタブとして右下に置く。ツールバーの流れに入れると、
   入りきらない幅で自分だけの段を作り、P-221 で詰めた高さを戻してしまうため。
   .toolbar の position: relative（.toolbar の定義側に置く。P-224 の高さのブロックより後ろに .toolbar の
   トップレベル規則を足さないため）はタブの基準で、既存の z-index: var(--z-toolbar) もこれで効く
   （backdrop-filter の重なりの文脈だけだと、後ろの .grid-container がタブの下半分の上に来て押せない）。
   畳んでいる間は軸・フィルターのパネルを隠し、要約とボタンを1行に並べる。値（state）には触れない。 */
.btn-toolbar-toggle {
    position: absolute;
    right: 24px;
    bottom: -11px;
    height: 22px;
    padding: 0 10px;
    gap: 4px;
    font-size: var(--fs-xs);
    color: var(--text-muted);
    border-radius: var(--radius-pill);
}

.btn-toolbar-toggle i {
    font-size: var(--fs-3xs);
}

.toolbar-summary {
    display: none;
}

.toolbar.toolbar-collapsed {
    flex-flow: row nowrap;
    align-items: center;
    gap: 12px;
    padding-top: 8px;
    padding-bottom: 8px;
}

.toolbar.toolbar-collapsed > .axis-config,
.toolbar.toolbar-collapsed > .filters-panel {
    display: none;
}

.toolbar.toolbar-collapsed > .toolbar-summary {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
    gap: 6px;
    min-width: 0;
    margin: 0;
    overflow: hidden;
    white-space: nowrap;
}

.toolbar.toolbar-collapsed > .btn-toolbar-toggle {
    position: static;
    flex: none;
    height: var(--toolbar-ctl-h);
    padding: 0 12px;
    font-size: var(--fs-sm);
    border-radius: var(--toolbar-ctl-radius);
}

.toolbar-summary-item {
    display: inline-flex;
    flex: none;
    align-items: baseline;
    gap: 4px;
    padding: 3px 10px;
    font-size: var(--fs-sm);
    background: rgba(248, 250, 252, 0.7);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-pill);
}

.toolbar-summary-label {
    font-weight: 600;
    color: var(--text-muted);
}

.toolbar-summary-value {
    max-width: 16em;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--text);
}

/* 絞り込み中のフィルター（開いたときの .filter-active）と同じく、藍の段で示す。 */
.toolbar-summary-item-active {
    background: rgba(79, 70, 229, 0.08);
    border-color: rgba(79, 70, 229, 0.35);
}

.toolbar-summary-item-active .toolbar-summary-label,
.toolbar-summary-item-active .toolbar-summary-value {
    color: var(--primary);
}

/* 既定値（先頭メンバー）から変更済み＝「絞り込み中」のフィルターを一目で分かるよう強調する
   （P-45, buildFiltersUIでの判定に連動。表示のみでonFilterChangeのロジックには影響しない） */
.filter-active label { color: var(--primary); font-weight: 700; }
.filter-active .filter-dim-icon { color: var(--primary); }
.filter-active label::after {
    content: '';
    display: inline-block;
    width: 6px;
    height: 6px;
    margin-left: 5px;
    border-radius: 50%;
    background: var(--primary);
    vertical-align: middle;
}
.filter-active select { border-color: var(--primary); background-color: rgba(79, 70, 229, 0.05); }
/* 「表示」ドロップダウンの設定が既定値から1つでも変更されている場合、閉じた状態でも分かるよう
   ボタン自体を強調する（P-61, filter-activeと同じ考え方。表示のみで各設定の保存・描画ロジックには影響しない） */
#btn-display-menu.display-menu-active { color: var(--primary); border-color: var(--primary); background-color: rgba(79, 70, 229, 0.05); position: relative; }
#btn-display-menu.display-menu-active::after {
    content: '';
    position: absolute;
    top: 3px;
    right: 3px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--primary);
}
/* ビュー操作群（選択・保存・既定・複製・リンク・削除）を淡い枠＋背景のチップとしてまとめ、
   隣り合う「フィルター」見出しとの境界を明確にして操作グループの塊を一目で示す（P-14, 表示のみ） */
.view-management-row { display: flex; gap: 8px; align-items: center; padding: 4px 8px; background: rgba(248, 250, 252, 0.7); border: 1px solid var(--border-color); border-radius: 20px; }
/* ビュー管理クラスタの先頭ラベル（保存ビューの呼び出し／保存であることを示すアンカー） */
.view-management-label { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-sm); font-weight: 600; color: var(--text-muted); white-space: nowrap; padding-left: 2px; }
.view-management-label i { color: var(--slate-400); font-size: var(--fs-xs); }
.view-select { width: 180px; height: var(--toolbar-ctl-h); padding: 0 8px; font-size: var(--fs-sm); border-radius: var(--toolbar-ctl-radius); }
/* 保存ビューが多いテナント向けの名称絞り込みボックス（N-31）。ビュー件数が少ない間は hidden で隠れる */
.view-filter-input { width: 150px; height: var(--toolbar-ctl-h); padding: 0 8px; font-size: var(--fs-sm); border-radius: var(--toolbar-ctl-radius); }
.btn-view-save { height: var(--toolbar-ctl-h); padding: 0 12px; font-size: var(--fs-sm); border-radius: var(--toolbar-ctl-radius); }
.btn-view-delete { height: var(--toolbar-ctl-h); padding: 0 10px; font-size: var(--fs-sm); border-radius: var(--toolbar-ctl-radius); }
/* 削除は取り返しのつかない破壊的操作。既定は他のセカンダリ操作と同じ控えめな見た目のまま、
   ホバー／フォーカス時のみ淡い赤（danger）を当てて誤クリックを抑止する（P-13, 表示のみ・確認ダイアログ挙動は不変） */
.btn-view-delete:hover:not(:disabled) { color: var(--red-600); border-color: var(--red-300); background-color: var(--red-50); }
/* P-188: .btn-secondary の押下で沈みはするが、背景はホバーの --red-50 のまま。赤系で一段濃くする。 */
.btn-view-delete:active:not(:disabled) { background-color: var(--red-100); }
.btn-view-delete:focus-visible { color: var(--red-600); border-color: var(--red-400); box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.18); }
.btn-view-duplicate { height: var(--toolbar-ctl-h); padding: 0 10px; font-size: var(--fs-sm); border-radius: var(--toolbar-ctl-radius); }
.btn-view-copy-link { height: var(--toolbar-ctl-h); padding: 0 10px; font-size: var(--fs-sm); border-radius: var(--toolbar-ctl-radius); }
/* 既定ビュー（次回ログイン時に自動読込）の設定トグル。設定中は星を塗りつぶし金色で表示する。
   P-201: 無効時は .btn:disabled（opacity: 0.55）に任せる。以前はここと .btn-view-star だけ 0.5 を上書きしていた。 */
.btn-view-default { height: var(--toolbar-ctl-h); padding: 0 10px; font-size: var(--fs-sm); border-radius: var(--toolbar-ctl-radius); }
.btn-view-default.active { color: var(--amber-700); border-color: var(--amber-500); background: var(--amber-50); }
/* お気に入りビュー（ブラウザ単位、複数登録可）のトグル。既定ビューと区別できるよう青系で表示する */
.btn-view-star { height: var(--toolbar-ctl-h); padding: 0 10px; font-size: var(--fs-sm); border-radius: var(--toolbar-ctl-radius); }
.btn-view-star.active { color: var(--blue-700); border-color: var(--blue-400); background: var(--blue-50); }

/* app.html AI summary panel — グリッドを押し下げない右サイドのオーバーレイドロワー */
.ai-summary-box { display: none; position: absolute; top: 24px; right: 24px; bottom: 24px; width: min(460px, calc(100% - 48px)); z-index: var(--z-panel); flex-direction: column; background: linear-gradient(135deg, rgba(255, 255, 255, 0.97) 0%, rgba(248, 250, 252, 0.97) 100%); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); padding: 16px 20px; border: 1px solid #c084fc; border-radius: var(--radius-lg); box-shadow: 0 10px 25px -5px rgba(124, 58, 237, 0.3), 0 4px 10px -4px rgba(0, 0, 0, 0.1); border-left: 4px solid var(--violet-600); }
.ai-summary-box.open { display: flex; animation: ai-summary-slide-in 0.25s ease-out; }
@keyframes ai-summary-slide-in { from { transform: translateX(20px); opacity: 0; } to { transform: none; opacity: 1; } }

/* app.html グリッド内検索（縦軸/横軸メンバー、N-13） */
.grid-search-group { display: flex; align-items: center; gap: 4px; }
.grid-search-icon { color: var(--slate-400); font-size: var(--fs-md); }
/* 検索対象軸（縦軸/横軸）セレクト。検索入力と揃えた高さ・角丸で1つの検索コントロール群に見せる */
.grid-search-axis-select { height: var(--toolbar-ctl-h); padding: 0 6px; font-size: var(--fs-sm); border-radius: var(--toolbar-ctl-radius); color: var(--text-muted); }
/* P-221: `.config-group select` の min-width: 150px は「縦軸／横軸」の2文字には広すぎ、ツールのパネルを 78px 押し広げていた。 */
.config-group select.grid-search-axis-select { min-width: 64px; }
/* 検索入力の角丸をビュー操作群・グラフ開くボタンと揃え、ツールバー内の基準を統一（P-18, 表示のみ） */
.grid-search-input { height: var(--toolbar-ctl-h); padding: 0 8px; font-size: var(--fs-md); border-radius: var(--toolbar-ctl-radius); }
/* 検索一致件数をピル（バッジ）状に整形し、一致あり／0件で色を変えて検索結果を直感的に示す（P-15, 表示・整形のみ） */
.grid-search-count { display: inline-flex; align-items: center; justify-content: center; font-size: var(--fs-xs); font-weight: 600; color: var(--slate-500); min-width: 44px; height: 22px; padding: 0 8px; border-radius: 11px; text-align: center; white-space: nowrap; font-variant-numeric: tabular-nums; transition: background-color var(--motion-fast), color var(--motion-fast); }
/* 一致あり: ブランド藍のバッジ */
.grid-search-count.grid-search-count-hit { color: var(--indigo-700); background-color: var(--indigo-50); }
/* 0件: 淡い赤で「見つからない」ことをはっきり示す */
.grid-search-count.grid-search-count-none { color: var(--red-600); background-color: var(--red-50); }
/* 未検索（空）時はバッジ地色を出さない */
.grid-search-count:empty { background-color: transparent; }

/* セル値の検索・置換（N-30）: 「検索」の件数プレビュー行。一致あり=藍／0件・エラー=赤で、
   grid-search-count のバッジ配色と揃える。空のときは余白を出さない。 */
.find-replace-result { margin: 4px 0 0; min-height: 1.2em; font-size: 0.9rem; font-weight: 600; }
.find-replace-result:empty { margin: 0; min-height: 0; }
.find-replace-result-hit { color: var(--indigo-700); }
.find-replace-result-none { color: var(--red-600); }

/* 同上: 表示単位が円以外（千円・百万円）のときだけ JS が hidden を外して出す注意書き（Q-69）。
   検索・置換の入力値は常に円なので、画面の数値をそのまま入れるミスを事前に防ぐ。
   ai-dim-error と同じアンバー系の配色で「注意」と分かるようにする。 */
.find-replace-unit-note { margin: 0 0 15px; background: var(--amber-100); border: 1px solid var(--amber-500); border-radius: var(--radius-md); padding: 8px 12px; font-size: 0.85rem; color: var(--amber-800); line-height: 1.6; }

/* app.html chart panel — AIサマリと同方式の右サイドオーバーレイドロワー */
/* グラフ開くボタンの角丸をビュー操作群・検索入力と揃え、ツールバー内の基準を統一（P-18, 表示のみ） */
.btn-open-chart { height: var(--toolbar-ctl-h); padding: 0 12px; font-size: var(--fs-md); white-space: nowrap; border-radius: var(--toolbar-ctl-radius); }
.chart-box { display: none; position: absolute; top: 24px; right: 24px; bottom: 24px; width: min(560px, calc(100% - 48px)); z-index: var(--z-panel); flex-direction: column; background: rgba(255, 255, 255, 0.98); backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur); padding: 16px 20px; border: 1px solid var(--blue-300); border-radius: var(--radius-lg); box-shadow: 0 10px 25px -5px rgba(37, 99, 235, 0.25), 0 4px 10px -4px rgba(0, 0, 0, 0.1); border-left: 4px solid var(--blue-600); }
.chart-box.open { display: flex; animation: ai-summary-slide-in 0.25s ease-out; }
.chart-box-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; flex-shrink: 0; }
.chart-box-title { font-weight: 700; color: var(--blue-700); font-size: 1.1rem; display: flex; align-items: center; gap: 8px; }
.chart-box-controls { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-bottom: 10px; flex-shrink: 0; padding-bottom: 10px; border-bottom: 1px solid var(--border-color); }
.chart-type-seg { display: inline-flex; border: 1px solid var(--border-color); border-radius: var(--radius-md); overflow: hidden; }
.chart-seg { background: transparent; border: none; border-left: 1px solid var(--border-color); padding: 7px 13px; font-size: var(--fs-md); cursor: pointer; color: var(--text-muted); }
.chart-seg:first-child { border-left: none; }
/* 非選択のセグメント（棒/折れ線/円）にもホバー反応を付けて、切り替えボタンであることを伝える */
/* P-210: ホバー・押下・選択中は、同じパネルのチェックボックス（.chart-ctl-check）や「表示 ▾」の項目と同じ藍の段に揃える
   （ホバー 0.08 → 押下・選択中 0.12＋var(--primary)）。以前は直書きの青（#eff6ff／#dbeafe／#1d4ed8）で、セグメントだけ別系統に見えていた。 */
.chart-seg:not(.chart-seg-on):hover { background: rgba(79, 70, 229, 0.08); color: var(--primary); }
/* P-188: 押している間は、選択中（.chart-seg-on）の背景を先に見せて切り替わることを伝える。 */
.chart-seg:not(.chart-seg-on):active { background: rgba(79, 70, 229, 0.12); }
.chart-seg-on { background: rgba(79, 70, 229, 0.12); color: var(--primary); font-weight: 600; }
.chart-ctl-field { font-size: var(--fs-sm); color: var(--text-muted); display: inline-flex; align-items: center; gap: 6px; }
/* P-217: 高さを固定するので、.form-input の上下 padding（10px）を打ち消す。残すと文字の領域が 10px しかなく 12px の文字が欠ける。 */
.chart-ctl-field select { height: 32px; width: auto; padding: 0 8px; font-size: var(--fs-sm); }
.chart-ctl-check { font-size: var(--fs-sm); color: var(--text-muted); display: inline-flex; align-items: center; gap: 6px; padding: 3px 6px; border-radius: var(--radius-sm); }
/* P-65: 縦軸/横軸パネルや「表示」ドロップダウンのチェックボックス群と同じ考え方で、
   チェック時に淡い藍背景＋藍文字で強調する。既定でONの設定であることを一目で伝える（表示のみ）。 */
.chart-ctl-check:has(input:checked) { background: rgba(79, 70, 229, 0.12); color: var(--primary); }
.chart-canvas-wrap { flex: 1; min-height: 0; position: relative; }
/* 円グラフの前提（負の合計値は除外等）を本文と同化させず、インフォボックス風に強調して見落としを防ぐ（P-17, 表示のみ・グラフ描画ロジックには影響なし）。
   出し入れは .hidden クラスで行う（P-198。chart.js の render() が円グラフのときだけ外す）。
   文字は同じパネルの「系列の向き」などの操作欄と同じ --fs-sm（P-214。以前は 11.5px の半端値）。 */
.chart-pie-note { font-size: var(--fs-sm); color: var(--blue-800); margin-top: 8px; flex-shrink: 0; line-height: 1.5; background: var(--blue-50); border-left: 3px solid var(--blue-300); border-radius: var(--radius-sm); padding: 8px 10px; }
.chart-pie-note i { color: var(--blue-500); margin-right: 4px; }
.chart-box-actions { display: flex; gap: 8px; margin-top: 12px; flex-shrink: 0; padding-top: 10px; border-top: 1px solid var(--border-color); }
.ai-summary-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; flex-shrink: 0; }
.ai-summary-title { font-weight: 700; color: var(--violet-700); font-size: 1.1rem; display: flex; align-items: center; gap: 8px; }
.ai-gradient-icon { background: linear-gradient(135deg, var(--violet-700) 0%, var(--indigo-600) 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
.ai-summary-toolbar { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; flex-shrink: 0; }
.ai-history-label { font-size: var(--fs-sm); color: var(--text-muted); flex-shrink: 0; }
.ai-history-select { flex: 1; min-width: 0; height: 30px; padding: 0 8px; font-size: var(--fs-sm); }
/* 分析日時などの補足は、真上の「履歴:」と同じ --fs-sm にし、パネルの中を 12px（補足・操作）と 14px（本文）の2段にする（P-214。以前は 11.5px）。 */
.ai-summary-meta { font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: 8px; flex-shrink: 0; border-bottom: 1px solid var(--border-color); padding-bottom: 8px; }
.ai-summary-content { color: var(--slate-700); font-size: var(--fs-lg); line-height: 1.6; flex: 1; min-height: 0; overflow-y: auto; padding-right: 6px; overscroll-behavior: contain; }
/* AIサマリ本文のマークダウン整形（markdown.js の出力に対応） */
.ai-summary-content h1, .ai-summary-content h2 { font-size: 1.05rem; font-weight: 700; color: var(--violet-700); margin: 16px 0 8px; padding-bottom: 4px; border-bottom: 1px solid var(--violet-200); }
.ai-summary-content h3, .ai-summary-content h4, .ai-summary-content h5, .ai-summary-content h6 { font-size: 0.95rem; font-weight: 700; color: var(--violet-700); margin: 14px 0 6px; }
.ai-summary-content h1:first-child, .ai-summary-content h2:first-child, .ai-summary-content h3:first-child, .ai-summary-content p:first-child { margin-top: 0; }
.ai-summary-content p { margin: 0 0 10px; }
.ai-summary-content ul, .ai-summary-content ol { margin: 0 0 10px; padding-left: 20px; }
.ai-summary-content li { margin: 4px 0; }
.ai-summary-content code { background: var(--slate-100); border: 1px solid var(--border-color); border-radius: 4px; padding: 1px 5px; font-size: var(--fs-md); }
.ai-summary-content hr { border: none; border-top: 1px solid var(--border-color); margin: 12px 0; }

/* app.html modals */
.dim-edit-header { margin-bottom: 25px; display: flex; justify-content: space-between; align-items: flex-end; background: var(--slate-50); padding: 20px; border-radius: 10px; border: 1px solid var(--border-color); }
.dim-edit-left { display: flex; align-items: flex-end; gap: 20px; }
/* P-54: 名称（日本語）を主見出しとして先に置き、内部ID（英語）はラベル付きの控えめなチップとして後ろに添える（表示のみ・ロジック不変） */
.dim-edit-id-group { display: flex; align-items: baseline; gap: 6px; }
.dim-edit-id-label { font-size: var(--fs-2xs); font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.05em; }
.dim-edit-title { margin: 0; color: var(--text-muted); font-weight: 600; font-size: 0.95rem; font-family: monospace; min-width: 70px; }
.dim-input-desc { width: 250px; font-size: 1.15rem; font-weight: 700; color: var(--text); }
.ai-dim-box { margin-bottom: 25px; background: linear-gradient(135deg, var(--violet-50) 0%, var(--violet-100) 100%); padding: 20px; border-radius: var(--radius-lg); border: 1px solid var(--violet-200); box-shadow: var(--shadow-sm); }
.ai-dim-header { font-weight: 700; color: var(--violet-700); margin-bottom: 8px; display: flex; align-items: center; gap: 6px; }
.ai-dim-usage-info { margin-left: auto; font-size: var(--fs-xs); font-weight: normal; display: flex; align-items: center; gap: 4px; }
.ai-dim-row { display: flex; gap: 12px; align-items: flex-end; }
.ai-dim-textarea { height: 60px; flex-grow: 1; resize: none; font-size: var(--fs-lg); border-color: #c084fc; font-family: inherit; box-sizing: border-box; }
.btn-ai-dim { height: 60px; min-width: 140px; background: linear-gradient(135deg, var(--violet-600) 0%, var(--indigo-600) 100%); border-color: transparent; box-shadow: 0 4px 6px -1px rgba(124, 58, 237, 0.2); white-space: nowrap; }
.ai-dim-error { display: none; margin-top: 10px; background: var(--amber-100); border: 1px solid var(--amber-500); border-radius: var(--radius-md); padding: 10px 14px; font-size: var(--fs-md); color: var(--amber-800); line-height: 1.6; }
.btn-add-dim-row { margin-top: 10px; }
.btn-add-dimension { width: 100%; margin-bottom: 10px; }

/* Dimension editor: table (left) + live tree preview (right) */
.dim-edit-split { display: flex; gap: 20px; align-items: flex-start; }
.dim-edit-table-col { flex: 1 1 60%; min-width: 0; }
.dim-tree-col { flex: 1 1 40%; min-width: 260px; position: sticky; top: 0; }
.dim-tree-col-header { font-weight: 700; color: var(--primary); font-size: 0.95rem; margin-bottom: 10px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dim-tree-col-hint { font-weight: 400; font-size: var(--fs-xs); color: var(--text-muted); } /* P-109: #94a3b8 は 2.45:1 で基準未満 */
.dim-tree-preview { background: var(--slate-50); border: 1px solid var(--border-color); border-radius: 10px; padding: 14px 16px; max-height: 480px; overflow: auto; font-size: var(--fs-md); }
.dim-tree-empty { color: var(--text-muted); font-size: var(--fs-md); margin: 0; line-height: 1.6; }
.dim-tree-root, .dim-tree-children { list-style: none; margin: 0; padding: 0; }
.dim-tree-children { margin-left: 10px; padding-left: 14px; border-left: 1px dashed var(--slate-300); }
.dim-tree-node { margin: 3px 0; }
.dim-tree-label { display: flex; align-items: center; gap: 7px; padding: 3px 6px; border-radius: var(--radius-sm); }
.dim-tree-label:hover { background: var(--indigo-50); }
.dim-tree-icon { color: var(--indigo-500); width: 16px; text-align: center; }
.dim-tree-icon-leaf { color: var(--slate-400); width: 16px; text-align: center; }
.dim-tree-id { font-weight: 600; color: var(--text); }
.dim-tree-id-missing { color: var(--slate-300); font-weight: 400; font-style: italic; }
.dim-tree-desc { color: var(--slate-500); }
.dim-tree-desc::before { content: '— '; color: var(--slate-300); }
.dim-tree-badge { font-size: var(--fs-2xs); font-weight: 700; padding: 1px 7px; border-radius: var(--radius-pill); margin-left: 2px; }
.dim-tree-badge-revenue { background: var(--green-100); color: var(--green-700); }
.dim-tree-badge-expense { background: var(--red-100); color: var(--red-700); }
.dim-tree-cycle { color: var(--red-700); font-size: var(--fs-xs); margin: 2px 0 2px 22px; }
@media (max-width: 960px) {
    .dim-edit-split { flex-direction: column; }
    .dim-tree-col { position: static; width: 100%; }
}
.modal-content-user { max-width: 800px; }
.modal-body-user { padding: 30px; flex-direction: column; }
.user-create-row { margin-bottom: 25px; display: flex; gap: 15px; align-items: flex-end; flex-wrap: wrap; background: var(--slate-50); padding: 20px; border-radius: 10px; border: 1px solid var(--border-color); }
/* P-96: 一覧モーダルの表を包むスクロール枠。操作ログ・コメント一覧・セルの内訳の3つは
   スクロールする祖先が無く、モーダルの高さを超えた行がクリップされて読めなかったため
   ここへ集約した。
   - flex: 0 1 auto ＋ min-height: 0 … 行数が少ないときは表の自然な高さのまま（枠だけが
     モーダル下端まで伸びない）、超えたときだけ縮んでスクロールする。
   - 角丸・枠線・影は表からこの枠へ移す … .management-table の overflow:hidden（角丸の
     クリップ用）が残っていると表自身がスクロールポートになり、見出し行の position:sticky
     が効かなくなるため。 */
.table-scroll {
    flex: 0 1 auto;
    min-height: 0;
    overflow-y: auto;
    background: white;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
}
/* P-99: メンバー別フィルター設定の個別設定表（#axis-config-table）も、スクロールポートこそ
   .axis-table-wrap と別物だが「枠が角丸・枠線を持ち、中の表は素通し」という構造は .table-scroll
   と同じなので、同じ扱いにまとめる。副次的に、枠と表で二重になっていた枠線も1本に揃う。 */
.table-scroll > .management-table,
.axis-table-wrap > .management-table {
    border: none;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
}
/* 行数が多い一覧でも列の意味を見失わないよう、見出し行を上端に固定する（P-04 でグリッドに
   入れた固定ヘッダーと同じ考え方）。th の背景色は不透明なので本文が透けない。
   #axis-config-table は thead を axis-modal.js が組み立てるためクラスが付かない。要素で当てる。 */
.table-scroll > .management-table thead th,
.axis-table-wrap > .management-table thead th {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky-head);
}
.modal-content-axis { max-width: 900px; }
.modal-body-axis { padding: 20px; flex-direction: column; }
.axis-desc { margin-bottom: 15px; color: var(--slate-500); font-size: 0.9rem; }
/* P-31: 期間一括切替パネルは下の個別設定テーブルとは別の操作グループだが、地の背景色のみ
   では境界が弱く地続きに見えていた。P-07 と同系統の左アクセント（未使用のティール系）＋
   アイコン付き見出しで「これは一括操作」であることを明示し、個別設定表の直前にも小見出しを
   追加して二段構成であることを示す。表示のみでフィルター上書きロジックには影響しない。 */
.axis-bulk-panel { background: var(--slate-50); border: 1px solid var(--border-color); border-left: 3px solid #0d9488; border-radius: 10px; padding: 14px 16px; margin-bottom: 15px; }
.axis-bulk-title i { color: #0d9488; margin-right: 4px; }
.axis-individual-heading { font-weight: 600; font-size: 0.85rem; color: var(--slate-600); margin: 0 0 8px; }
.axis-individual-heading i { color: var(--slate-500); margin-right: 4px; }
.axis-bulk-title { font-weight: 600; font-size: 0.9rem; margin-bottom: 10px; }
.axis-bulk-row { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; }
.axis-bulk-field { display: flex; flex-direction: column; gap: 4px; font-size: 0.8rem; color: var(--slate-600); min-width: 160px; }
.axis-bulk-field .form-input { height: 34px; padding: 4px 8px; }
.axis-table-wrap { flex-grow: 1; overflow-y: auto; border: 1px solid var(--border-color); border-radius: var(--radius-md); }
.modal-content-save-view { max-width: 400px; height: auto; }
#view-description-input { width: 100%; resize: vertical; }
.modal-body-save-view { padding: 20px; flex-direction: column; }
/* P-30: 利用状況サマリは複数の指標カード＋5列テーブルを持ち、他の単一入力欄向けモーダル
   （modal-content-save-view, max-width:400px）を流用すると窮屈に折り返す。専用に少し広い
   幅を確保し、指標カードを余裕を持って並べられるようにする（表示のみ・集計ロジック不変）。 */
.modal-content-data-summary { max-width: 640px; height: auto; }
.view-public-row { display: flex; gap: 20px; margin-top: 5px; }
/* P-69: 公開設定のラジオだけ P-09 のトグルチップ風の選択強調から取り残されていたため、
   チェックボックス群（.label-flex 等）と同じ淡い藍背景＋藍文字＋ブランド色の accent を当て、
   どちらが選択中か一目で分かるようにする（表示のみ・公開設定の保存値には影響しない）。 */
.label-radio {
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border-radius: var(--radius-sm);
}
.label-radio input[type="radio"] { accent-color: var(--primary); }
.label-radio:has(input:checked) {
    background: rgba(79, 70, 229, 0.12);
    color: var(--primary);
}
/* P-207: 包んでいる入力が無効な間は、ラベルごと .form-input:disabled と同じ透明度・カーソルにする
   （閲覧のみのフリーシートの公開設定、関数ビルダーで引数を使わない間の「列を固定」「行を固定」）。
   以前は淡くなるのはブラウザ既定の小さな丸・四角だけで、ラベルは cursor: pointer と選択中の藍色のまま
   押せそうに見えた。選択中の藍色は値を見せるため残し、淡色化で「選べない」ことを伝える。 */
.label-radio:has(input:disabled),
.label-flex:has(input:disabled),
.label-nowidth-flex:has(input:disabled) {
    opacity: 0.55;
    cursor: not-allowed;
}
.label-radio input:disabled,
.label-flex input:disabled,
.label-nowidth-flex input:disabled {
    cursor: not-allowed;
}
.modal-content-delete-tenant { max-width: 480px; height: auto; }
.modal-header-danger { background: linear-gradient(135deg, var(--red-100), var(--red-200)); border-bottom: 1px solid var(--red-300); }
.modal-title-danger { color: var(--red-700); }
.modal-body-delete { padding: 24px; flex-direction: column; gap: 16px; }
.delete-warning-box { background: var(--red-50); border: 1px solid var(--red-300); border-radius: var(--radius-md); padding: 14px; color: var(--red-900); font-size: var(--fs-lg); line-height: 1.6; }
.delete-label-danger { color: var(--red-900); }
.col-th-account-type { display: none; }

/* Backup restore: preview manifest of the chosen file (shown before the destructive overwrite). */
.backup-manifest { background: var(--slate-50); border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 12px 14px; }
.backup-manifest-title { font-size: var(--fs-md); font-weight: 600; color: var(--text); margin-bottom: 8px; }
.backup-manifest-list { margin: 0; }
.backup-manifest-row { display: flex; justify-content: space-between; gap: 12px; padding: 3px 0; font-size: var(--fs-md); }
.backup-manifest-row dt { color: var(--slate-500); margin: 0; }
.backup-manifest-row dd { margin: 0; font-weight: 600; color: var(--text); }

/* 値をコピーの「既存値を上書き」チェックボックス: データを消しうる操作なので警告色で目立たせる（表示のみ）。 */
.copy-member-overwrite-option {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    background: var(--amber-50);
    border: 1px solid var(--amber-200);
    border-radius: var(--radius-md);
    color: var(--amber-800);
    font-size: var(--fs-lg);
    cursor: pointer;
}
.copy-member-overwrite-option input[type="checkbox"] { accent-color: var(--amber-600); }
.copy-member-overwrite-option i { color: var(--amber-600); }


/* ── Class-based styles introduced by the JS module refactor (replacing inline styles) ── */

/* Spinner variants (previously set via inline style on each button) */
.spinner-dark { border-color: var(--slate-600); border-top-color: transparent; }
.spinner-light { border-color: #ffffff; border-top-color: transparent; }

/* P-06: 横長の表（横軸メンバーが多い表）では、視線が横に移動する間に1行ずれて
   読み間違えやすい。偶数行にごく淡い背景色（ゼブラ縞）を敷いて視線を誘導する。
   集計（cell-summary）・親見出し（cell-row-header-parent）・読取専用（cell-readonly-leaf）・
   AIハイライト（cell-ai-highlight）・検索一致（cell-search-match-active）など明示的な
   背景を持つセル状態は、同じ詳細度かつ本ルールより後方に定義されているため後勝ちで
   従来色を維持する。行ホバー（!important）も従来どおり優先される。
   表示のみの調整で集計・編集・保存には影響しない。 */
.jexcel > tbody > tr:nth-child(even) > td {
    background-color: var(--slate-50);
}

/* Grid cell states (set by updateTable in grid.js) */
.jexcel > tbody > tr > td.cell-readonly-leaf {
    background-color: var(--slate-100);
    /* 入力不可だが集計前の実値を表示するセル。読みやすさのためテキスト濃度を上げつつ
       （旧 #94a3b8 は背景との対比が不足し WCAG AA 未満だった）、入力可能セルとは
       依然として区別できる落ち着いた色味に揃える。 */
    color: var(--slate-500);
    cursor: not-allowed;
    font-weight: normal;
    text-align: right;
}
.jexcel > tbody > tr > td.cell-summary {
    background-color: var(--slate-200);
    color: var(--slate-800);
    /* N-26: ダブルクリックで内訳モーダルを開けるため、編集不可を示す not-allowed ではなく
       クリック可能を示すカーソルにする。 */
    cursor: zoom-in;
    font-weight: 700;
    text-align: right;
}
.jexcel > tbody > tr > td.cell-editable {
    cursor: cell;
    font-weight: normal;
    text-align: right;
}

/* 行ホバー: グリッドの行全体をブランド配色の淡い藍色で強調する（密なグリッドでの
   行追跡を助ける）。汎用の tbody 行ホバー（グレー）より高い詳細度＋!important で
   データグリッドだけを上書きし、管理テーブルのホバーには影響しない。 */
.jexcel > tbody > tr:hover > td,
.jexcel > tbody > tr:hover > th {
    background-color: var(--indigo-50) !important;
}

/* P-08: 数値列の桁を等幅（tabular-nums）にして列内の数字を縦に揃え、桁数の異なる金額が
   混在しても読みやすくする。右寄せの数値セル（入力可能・集計・読み取り専用 leaf）にのみ適用し、
   行ヘッダー（文字列）は対象外。桁区切り・△・赤字などの表示加工と併用でき、内部データ・編集・
   CSV/Excel 出力には一切影響しない表示のみの調整。 */
.jexcel > tbody > tr > td.cell-editable,
.jexcel > tbody > tr > td.cell-summary,
.jexcel > tbody > tr > td.cell-readonly-leaf {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}

/* 入力可能セルにポインタを乗せたとき、より濃い藍色＋内枠線で「ここに直接入力できる」
   ことを一目で示す（初見ユーザーが入力対象セルを迷わず見つけられるようにする affordance）。
   表示のみの変更で編集判定・保存等の挙動には影響しない。 */
.jexcel > tbody > tr > td.cell-editable:hover {
    background-color: var(--indigo-100) !important;
    box-shadow: inset 0 0 0 1.5px var(--primary);
    cursor: cell;
}
.jexcel > tbody > tr > td.cell-row-header {
    font-weight: 500;
    text-align: left;
}
.jexcel > tbody > tr > td.cell-row-header-parent {
    font-weight: 700;
    background-color: var(--slate-200);
    color: var(--slate-800);
    text-align: left;
}

/* N-83: 表示件数で隠した行をまとめた「その他」行の見出し。実在のメンバーと見分けられるよう、
   字の色を落として斜体にする（値のセルは読み取り専用の cell-readonly-leaf）。 */
.jexcel > tbody > tr > td.cell-row-header-other {
    color: var(--slate-500);
    font-style: italic;
}

/* 負の数を赤字表示（updateTable が付与、他の cell-* 状態に重ねて文字色のみ上書き） */
.jexcel > tbody > tr > td.cell-negative {
    color: var(--red-600);
}

/* AIサマリの指摘箇所ハイライト（updateTable が付与、他の cell-* 状態に重ねて適用） */
.jexcel > tbody > tr > td.cell-ai-highlight {
    background-color: var(--amber-100);
    box-shadow: inset 0 0 0 1.5px var(--amber-500);
    cursor: help;
    position: relative;
}
/* 右上の紫コーナーマークで「AIの指摘」だと分かるようにする */
.jexcel > tbody > tr > td.cell-ai-highlight::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    border-style: solid;
    border-width: 0 8px 8px 0;
    border-color: transparent var(--violet-600) transparent transparent;
}

/* 条件付きハイライト: 閾値超過（赤系）・未達（青系）（updateTable が付与、他の cell-* 状態に
   重ねて適用。AIハイライト（黄背景+紫コーナー）とは背景色が異なるため共存しても判別できる） */
.jexcel > tbody > tr > td.cell-cond-high {
    background-color: var(--red-100);
    box-shadow: inset 0 0 0 1.5px var(--red-600);
}
.jexcel > tbody > tr > td.cell-cond-low {
    background-color: var(--blue-100);
    box-shadow: inset 0 0 0 1.5px var(--blue-600);
}

/* グリッド内検索（縦軸メンバー）の一致ハイライト（updateTable が付与） */
.jexcel > tbody > tr > td.cell-search-match {
    box-shadow: inset 0 0 0 1.5px var(--amber-500);
}
.jexcel > tbody > tr > td.cell-search-match-active {
    background-color: var(--amber-100);
    box-shadow: inset 0 0 0 2px var(--amber-600);
}

/* グリッド内検索（横軸メンバー、N-13）の一致ハイライト: ヘッダーセルは updateTable の対象外
   なので applyColumnSearchHighlight（grid.js）が描画後に直接クラスを付与する。縦軸と同じ
   配色・強度で統一し、検索対象軸が変わっても見た目の一貫性を保つ。 */
.jexcel > thead > tr > td.cell-search-match {
    box-shadow: inset 0 0 0 1.5px var(--amber-500) !important;
}
.jexcel > thead > tr > td.cell-search-match-active {
    background-color: var(--amber-100) !important;
    box-shadow: inset 0 0 0 2px var(--amber-600) !important;
}

/* セルコメント（注記）が付いているセルの目印（updateTable が付与）。右上の青コーナーマークで
   AIサマリ指摘の紫コーナーマーク（.cell-ai-highlight）と見分けられるようにする。 */
.jexcel > tbody > tr > td.cell-has-comment {
    position: relative;
}
.jexcel > tbody > tr > td.cell-has-comment::before {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    border-style: solid;
    border-width: 0 7px 7px 0;
    border-color: transparent var(--blue-600) transparent transparent;
}

/* P-22: グリッドのセル背景色・マークの意味を示す凡例（header-menu ドロップダウン）。
   実際のセルクラス（.cell-editable 等）は #data-grid .jexcel 配下でのみ配色されるため、
   ドロップダウン内の色見本は同じ色調を再現した専用クラスで表示する（判定ロジック・
   ツールチップには影響しない表示専用の追加）。 */
.cell-legend-dropdown {
    /* .header-menu-dropdown を border-box にした分（padding 4px×2 ＋ border 1px×2 ＝ 10px）を
       足して、見た目の最小幅を従来（content-box の 220px）と同じに保つ。 */
    min-width: 230px;
    padding: 10px 4px;
}
.cell-legend-title {
    padding: 2px 12px 8px;
    font-size: var(--fs-xs);
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.cell-legend-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 12px;
    font-size: var(--fs-md);
    color: var(--text);
}
.legend-swatch {
    position: relative;
    flex: none;
    width: 16px;
    height: 16px;
    border-radius: 4px;
    border: 1px solid var(--border-color);
    background-color: #ffffff;
}
.legend-swatch-editable { border-color: var(--slate-300); }
.legend-swatch-readonly { background-color: var(--slate-100); border-color: var(--slate-400); }
.legend-swatch-summary { background-color: var(--slate-200); border-color: var(--slate-500); }
.legend-swatch-comment::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    border-style: solid;
    border-width: 0 8px 8px 0;
    border-color: transparent var(--blue-600) transparent transparent;
}
.legend-swatch-ai {
    background-color: var(--amber-100);
    box-shadow: inset 0 0 0 1.5px var(--amber-500);
}
.legend-swatch-ai::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    border-style: solid;
    border-width: 0 8px 8px 0;
    border-color: transparent var(--violet-600) transparent transparent;
}
.legend-swatch-cond-high {
    background-color: var(--red-100);
    box-shadow: inset 0 0 0 1.5px var(--red-600);
}
.legend-swatch-cond-low {
    background-color: var(--blue-100);
    box-shadow: inset 0 0 0 1.5px var(--blue-600);
}
/* P-56: 条件付きハイライトが無効（既定）のときは凡例の該当2項目を淡色化し、
   「現在OFFである」ことを一目で分かるよう小さな注記を添える（toolbar.js の
   updateCellLegendUi() が state.condHighlightEnabled に応じてクラスを切り替える）。 */
.cell-legend-off-note {
    display: none;
    font-size: var(--fs-xs);
    color: var(--text-muted);
}
.cell-legend-item-cond.cell-legend-item-inactive {
    opacity: 0.45;
}
.cell-legend-item-cond.cell-legend-item-inactive .cell-legend-off-note {
    display: inline;
}

/* ハイライトセルのカスタムツールチップ（grid.js initAiHighlightTooltip が配置） */
.ai-cell-tooltip {
    display: none;
    position: fixed;
    z-index: var(--z-tooltip);
    max-width: 320px;
    background: var(--slate-800);
    color: var(--slate-50);
    font-size: var(--fs-sm);
    line-height: 1.5;
    padding: 8px 12px 8px 10px;
    border-radius: var(--radius-md);
    border-left: 3px solid var(--violet-600);
    box-shadow: 0 8px 20px -4px rgba(0, 0, 0, 0.35);
    pointer-events: none;
    white-space: pre-line;
}
.ai-cell-tooltip.visible { display: block; }
.ai-cell-tooltip::before {
    content: '✦ AI分析コメント';
    display: block;
    font-size: var(--fs-xs);
    font-weight: 700;
    color: var(--violet-300);
    margin-bottom: 3px;
    letter-spacing: 0.03em;
}

/* Axis override modal */
.axis-member-cell {
    font-weight: 600;
    background: var(--slate-50);
    border-right: 1px solid var(--slate-200);
    white-space: nowrap;
}
.axis-member-desc { color: var(--slate-500); font-weight: normal; }
.axis-override-select { width: 100%; padding: 4px 8px; height: 34px; }
.axis-override-active {
    border-color: var(--primary);
    color: var(--primary);
    font-weight: bold;
    background-color: rgba(79, 70, 229, 0.12);
}

/* Dimension edit table */
.dim-cell-input { width: 100%; text-align: left; padding: 4px 8px; }
.dim-cell-select { padding: 4px; }
/* 一覧の行内に並べる小ボタン（E-100）。以前は「招待再送」に付いた .btn-user-row-resend の
   実体が CSS に無く、隣の「削除」（12px / 4px 10px）と寸法が揃っていなかった。
   隣り合ったときの間隔も .btn-compact と同じ 4px に揃える。 */
.btn-dim-row-delete, .btn-user-row-delete, .btn-user-row-resend { padding: 4px 10px; font-size: var(--fs-sm); }
.btn-user-row-resend + .btn-user-row-delete { margin-left: 4px; }
.ai-dim-error-detail { font-size: var(--fs-sm); opacity: 0.8; }

/* Cell comment list modal (N-03) */
.cell-comment-list-text { white-space: pre-wrap; word-break: break-word; }
.cell-comment-list-action { white-space: nowrap; }
.btn-cell-comment-jump { padding: 4px 10px; font-size: var(--fs-sm); }
/* N-14: 更新者・更新日時列は折り返さず、やや控えめな文字色で補足情報として表示する */
.cell-comment-list-updated-by,
.cell-comment-list-updated-at { white-space: nowrap; font-size: var(--fs-sm); color: var(--text-muted); }

/* N-25: 未読コメントの件数バッジ（「データ」メニューのトリガーと「コメント一覧」項目）と、
   一覧内で新着行を示す NEW マーク。未保存バッジ（.unsaved-badge）が「注意（橙）」なのに対し、
   こちらは「新着のお知らせ（赤）」として区別する。 */
.comment-unread-badge {
    display: inline-block;
    min-width: 18px;
    padding: 1px 6px;
    border-radius: var(--radius-pill);
    background-color: var(--red-600);
    color: #ffffff;
    font-size: var(--fs-xs);
    font-weight: 700;
    line-height: 1.5;
    text-align: center;
    white-space: nowrap;
}

.comment-unread-badge[hidden] { display: none; }

/* メニュー項目内では右端に寄せ、項目ラベルと重ならないようにする */
.comment-unread-badge-menu-item { margin-left: auto; }

.cell-comment-new-mark {
    display: inline-block;
    margin-right: 6px;
    padding: 0 5px;
    border-radius: 3px;
    background-color: var(--red-600);
    color: #ffffff;
    font-size: var(--fs-2xs);
    font-weight: 700;
    line-height: 1.6;
    vertical-align: middle;
}

.cell-comment-list-unread { background-color: var(--red-50); }

/* Cell drilldown modal (N-26): 内訳一覧の数値列は右寄せ・等幅数字。合計行(tfoot)は
   一覧との区切りが分かるよう太字＋上枠線にする。 */
.cell-drilldown-value {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
    white-space: nowrap;
}
#cell-drilldown-modal tfoot td {
    font-weight: 700;
    border-top: 2px solid var(--border, var(--slate-200));
}
/* P-96: 内訳が多くてスクロールしても「合計」は常に見えている方が有用なので、
   スクロール枠の下端に固定する。行 hover（.management-table tr:hover td）で背景が
   変わると固定行が明滅して見えるため、ここで打ち消して見出し行と同じ色に固定する。 */
#cell-drilldown-modal .table-scroll tfoot td,
#cell-drilldown-modal .table-scroll tfoot tr:hover td {
    position: sticky;
    bottom: 0;
    z-index: 1;
    background-color: var(--slate-50);
}
#cell-drilldown-note { font-size: var(--fs-sm); }
/* N-46: 軸のメンバー別上書きにより、対象セルと異なるフィルターで数えられた明細行にだけ
   出す「適用フィルター」列。金額そのものではなく数え方の注記なので、行の主役（値）より
   一段弱い見た目にして、上書きを使っていないテナントでは列ごと非表示にする。 */
.cell-drilldown-filter {
    font-size: var(--fs-sm);
    color: var(--slate-500, #64748b);
    white-space: nowrap;
}

/* =========================================================================
   操作マニュアル ビューア (manual.html)
   ========================================================================= */
.manual-body { background: var(--bg-color); color: var(--text); min-height: 100vh; }
.manual-header {
    position: sticky; top: 0; z-index: var(--z-doc-header);
    background: var(--card-bg);
    backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
    border-bottom: 1px solid var(--border-color);
    /* P-159: `.app-header` から受け取る `display: flex` と `padding: 12px 24px` を打ち消す。
       flex と余白は内側（`.manual-header-inner`）だけが持つ設計なので、外側も flex だと
       `.manual-header-inner` が「中身の幅のフレックスアイテム」になり、
       `max-width: 920px; margin: 0 auto` が効かず本文列と縦のラインが揃わなくなる
       （実測 460px のまま画面中央へ寄り、`justify-content: space-between` も働かない）。
       さらに外側と内側の `padding` が二重に足し算され、ヘッダーが 84.5px へ膨らんでいた。 */
    display: block;
    padding: 0;
}
.manual-header-inner {
    max-width: 920px; margin: 0 auto; padding: 12px 24px;
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.manual-main { max-width: 920px; margin: 0 auto; padding: 32px 24px 80px; }
.manual-content { font-size: var(--fs-xl); line-height: 1.75; color: var(--text); }
.manual-content h1 { font-size: 1.8rem; font-weight: 800; margin: 8px 0 20px; }
.manual-content h2 {
    font-size: 1.35rem; font-weight: 700; margin: 36px 0 14px;
    padding-bottom: 8px; border-bottom: 2px solid var(--border-color);
}
.manual-content h3 { font-size: 1.12rem; font-weight: 700; margin: 26px 0 10px; color: var(--primary); }
.manual-content h4, .manual-content h5, .manual-content h6 { font-size: var(--fs-2xl); font-weight: 700; margin: 18px 0 8px; }
.manual-content p { margin: 0 0 14px; }
.manual-content a { color: var(--primary); text-decoration: underline; }
.manual-content ul, .manual-content ol { margin: 0 0 14px; padding-left: 24px; }
.manual-content li { margin: 6px 0; }
.manual-content code {
    background: var(--slate-100); border: 1px solid var(--border-color);
    border-radius: 4px; padding: 1px 6px; font-size: 0.9em;
}
.manual-content hr { border: none; border-top: 1px solid var(--border-color); margin: 28px 0; }
.manual-content blockquote {
    margin: 0 0 16px; padding: 12px 16px;
    border-left: 4px solid var(--primary);
    background: rgba(79, 70, 229, 0.06);
    border-radius: 0 8px 8px 0; color: var(--text-muted);
}
.manual-content table {
    width: 100%; border-collapse: collapse; margin: 0 0 18px;
    font-size: var(--fs-lg); background: #ffffff;
    border: 1px solid var(--border-color); border-radius: var(--radius-md); overflow: hidden;
}
.manual-content th, .manual-content td {
    border: 1px solid var(--border-color); padding: 8px 12px; text-align: left; vertical-align: top;
    /* P-154: 無限定の `th, td` から受け取っていた下限幅。 */
    min-width: 80px;
}
/* P-153: 無限定の `th` から受け取っていた見出しの見え方（色・字送り・書体・字間）。 */
.manual-content thead th {
    background: var(--slate-50); font-weight: 700;
    color: var(--text-muted); font-size: var(--fs-sm);
    font-family: var(--font-heading); letter-spacing: 0.05em;
}
.manual-content tbody tr:nth-child(even) { background: rgba(248, 250, 252, 0.6); }
/* P-154: 無限定の `tbody tr:hover` から受け取っていた行 hover。行数の多い表で、
   読んでいる行を見失わないための手掛かりなので残す。 */
.manual-content tbody tr:hover td, .manual-content tbody tr:hover th {
    background-color: var(--slate-100);
}
/* 地が --bg-color（#f4f7fb）で白より暗く、--text-muted では 4.43:1 と足りないため 1 段濃い --slate-600（7.05:1）にする（P-149）。 */
.manual-loading, .manual-error { color: var(--slate-600); text-align: center; padding: 48px 0; }
.manual-error { color: var(--red-600); }
.u-color-var-primary { color: var(--primary); }
.u-display-none { display:none; }
.u-flex-shrink-0 { flex-shrink: 0; }
.u-margin-bottom-0 { margin-bottom:0; }
.u-margin-right-8px { margin-right: 8px; }
.u-margin-top-4px-2 { margin-top: -4px; }
.u-margin-0 { margin:0; }
.u-margin-10px-0-0 { margin: 10px 0 0; }
.u-margin-8px-0-0 { margin: 8px 0 0; }
.u-padding-0 { padding:0; }
.u-width-100 { width: 100%; }

/* Small semantic classes for HTML generated in JS (system.js) — kept out of the
   auto-generated utility block above. */
.spinner-on-primary { border-color:#ffffff; border-top-color:transparent; }
/* 一覧テーブルが0件のときの共通表示（P-82）。表の外に段落を置かず、必ず tbody 内の
   colspan セルとして描くことで、どのモーダルでも同じ位置・同じ見た目になる。
   セレクタを `td.table-empty-cell` としているのは詳細度の都合で、`.table-empty-cell`
   （0,1,0）だけでは `.management-table th, .management-table td`（0,1,1）に負けて
   中央寄せ・余白が一切効かなかったため（左寄せのまま表示されていた）。
   hover の背景も打ち消す——行が1行しか無く、しかも選べる対象ではないため。 */
td.table-empty-cell { text-align:center; color:var(--text-muted); padding:24px 20px; font-size:var(--fs-md); line-height:1.6; }
.management-table tr:hover td.table-empty-cell { background-color:transparent; }
/* ディメンション管理の編集表だけ ID セレクタでセルを左寄せしているため（上記 #dim-edit-table）、
   空状態セルだけ中央寄せへ戻す。 */
#dim-edit-table td.table-empty-cell { text-align:center; }

/* 利用状況サマリ（データメニュー → 利用状況サマリ） */
.summary-totals {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 12px;
    margin-bottom: 20px;
}
.summary-card {
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 14px 16px;
    text-align: center;
}
.summary-card-value {
    font-family: var(--font-heading);
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--primary);
    line-height: 1.2;
}
.summary-card-label {
    margin-top: 4px;
    font-size: 0.8rem;
    color: var(--text-muted);
}
.summary-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}
.summary-table th,
.summary-table td {
    padding: 8px 10px;
    border-bottom: 1px solid var(--border-color);
    text-align: left;
    /* P-154: 無限定の `th, td` から受け取っていた下限幅。 */
    min-width: 80px;
}
.summary-table th {
    color: var(--text-muted);
    font-weight: 600;
    /* P-153: 無限定の `th` から受け取っていた見出しの見え方。 */
    background-color: var(--slate-50);
    font-size: var(--fs-sm);
    font-family: var(--font-heading);
    letter-spacing: 0.05em;
}
/* P-154: 無限定の `tbody tr:hover` から受け取っていた行 hover。 */
.summary-table tbody tr:hover td, .summary-table tbody tr:hover th {
    background-color: var(--slate-100);
}
.summary-table .summary-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.summary-rate-cell { min-width: 120px; }
.summary-rate-wrap {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
}
.summary-rate-bar {
    flex: 1 1 auto;
    max-width: 80px;
    height: 8px;
    border-radius: var(--radius-pill);
    background: var(--border-color);
    overflow: hidden;
}
.summary-rate-fill {
    height: 100%;
    width: 0;
    border-radius: var(--radius-pill);
}
.summary-rate-fill.summary-rate-high { background: var(--green-500); }
.summary-rate-fill.summary-rate-mid { background: var(--amber-500); }
.summary-rate-fill.summary-rate-low { background: var(--red-500); }
.summary-rate-text {
    min-width: 34px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* =========================================================================
   キーボードショートカットヘルプモーダル
   ========================================================================= */
.modal-content-keyboard-help { max-width: 560px; width: 100%; }
/* 他の .modal-body-* 同様に flex-direction: column を指定しないと、基底の .modal-body
   （display:flex、行方向）がそのまま効き、各セクションが横並びの列に押し込まれて
   説明文が1文字ずつ縦積みで折り返される（P-49）。 */
.modal-body-keyboard-help { padding: 8px 24px 20px; flex-direction: column; overflow-y: auto; }

/* <kbd> 要素: キーキャップ風のスタイル */
kbd {
    display: inline-block;
    padding: 2px 7px;
    font-family: var(--font-body);
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--text);
    background: var(--slate-100);
    border: 1px solid var(--slate-300);
    border-bottom-width: 2px;
    border-radius: 5px;
    white-space: nowrap;
    line-height: 1.5;
}

/* セクション見出し */
.kb-section { margin-bottom: 20px; }
.kb-section:last-child { margin-bottom: 0; }
.kb-section-title {
    font-size: var(--fs-xs);
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin: 0 0 8px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border-color);
}

/* ショートカット行: キー列と説明列を2カラムで揃える */
.kb-list { margin: 0; padding: 0; }
.kb-row {
    display: grid;
    grid-template-columns: 200px 1fr;
    align-items: center;
    gap: 12px;
    padding: 5px 0;
}
.kb-row dt { font-size: var(--fs-md); }
.kb-row dd { margin: 0; font-size: var(--fs-md); color: var(--text); }

/* =========================================================================
   N-43: はじめかたガイド（初回ログイン時の「最初にやること3ステップ」）
   公開ページの #how と同じ3ステップを、プランナーの明るい配色に合わせて
   縦積みのリストで見せる（ランディングの .step-card はダーク配色前提のため
   流用しない）。表示専用でデータ・集計には影響しない。
   ========================================================================= */
.modal-content-onboarding { max-width: 620px; width: 100%; }
.modal-body-onboarding { padding: 8px 24px 20px; flex-direction: column; overflow-y: auto; }

.ob-lead {
    margin: 4px 0 18px;
    font-size: var(--fs-md);
    line-height: 1.7;
    color: var(--text-muted);
}

.ob-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.ob-step {
    display: flex;
    gap: 14px;
    align-items: flex-start;
    padding: 14px 16px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--slate-50);
}

.ob-step-num {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: var(--fs-md);
    color: #ffffff;
    background: var(--primary);
}

.ob-step-body { min-width: 0; }

.ob-step-title {
    margin: 2px 0 6px;
    font-size: var(--fs-lg);
    font-weight: 700;
    color: var(--text);
}

.ob-step-desc {
    margin: 0;
    font-size: var(--fs-md);
    line-height: 1.7;
    color: var(--text);
}

.ob-step-action { margin-top: 10px; }
/* .btn が display: inline-flex を明示しているため、UA の [hidden] { display: none } は
   上書きされてしまう。.freesheet-visibility-badge[hidden] / .ff-arg-member[hidden] と
   同じ作法で companion ルールを添える。 */
.ob-step-action[hidden] {
    display: none;
}

/* 「サンプル値を入れて試す」の補足文（N-45）。ボタンの下に置き、押す前に
   「空のセルにだけ入る」「1クリックで消せる」ことを読ませる。 */
.ob-sample-note {
    margin: 8px 0 0;
    font-size: var(--fs-sm);
    line-height: 1.6;
    color: var(--text-muted);
}

.ob-note {
    margin: 16px 0 0;
    font-size: var(--fs-sm);
    line-height: 1.6;
    color: var(--text-muted);
}

/* =========================================================================
   キーボード操作のフォーカス表示（アクセシビリティ）
   マウスのクリックでは出さず、Tab 等のキーボード操作時のみ明確なフォーカス
   リングを表示する（:focus-visible）。ボタン・アイコンボタン・ドロップダウン
   項目・チェックボックス／ラジオ・セグメント切替など、これまで視覚的な
   フォーカス指標が無かった要素に統一したリングを与え、キーボードだけでも
   現在位置を見失わないようにする。テキスト入力／セレクトは既存の :focus
   リング（border + box-shadow）があるため対象外。
   ========================================================================= */
.btn:focus-visible,
.btn-icon:focus-visible,
.header-menu-item:focus-visible,
.header-menu-trigger:focus-visible,
.chart-seg:focus-visible,
.close-btn:focus-visible,
.template-card:focus-visible,
.template-more-summary:focus-visible,
.dim-sidebar li:focus-visible,
.audit-target-jumpable:focus-visible,
.btn-toggle-password:focus-visible,
#data-grid:focus-visible,
input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* グリッド領域は枠線とぴったり合うようリングを内側寄りに */
#data-grid:focus-visible {
    outline-offset: -2px;
    border-radius: var(--radius-lg);
}

/* =========================================================================
   N-01: グリッド印刷（印刷プレビュー）
   ヘッダー・ツールバー・サイドパネル・モーダルを非表示にし、グリッドのみを
   スクロールなしのフルサイズで印刷する。#data-grid の高さ・overflow は
   jspreadsheet が inline style で固定するため !important で上書きする。
   表示専用の調整でデータ・編集内容には影響しない。
   ========================================================================= */
@media print {
    body {
        background: #ffffff;
    }

    .app-header,
    .toolbar,
    #grid-selection-stats,
    #ai-summary-display,
    #chart-panel,
    #info-banner,
    .loading-overlay,
    .modal {
        display: none !important;
    }

    .app-container {
        display: block !important;
        height: auto !important;
    }

    /* P-111 で挟んだ main も、上2つと同じくブロックへ戻して1枚の文書として流す */
    .app-main {
        display: block !important;
    }

    .skip-link {
        display: none !important;
    }

    .grid-container {
        overflow: visible !important;
        padding: 0 !important;
        display: block !important;
    }

    #data-grid {
        box-shadow: none !important;
        border: none !important;
        overflow: visible !important;
    }

    #data-grid .jexcel_content {
        height: auto !important;
        max-height: none !important;
        overflow: visible !important;
        background: #ffffff !important;
    }

    #data-grid table {
        width: 100% !important;
    }

    #data-grid .jexcel > thead > tr > td {
        position: static !important;
        box-shadow: none !important;
    }

    /* P-194: 本文側の「固定の境界」の影（行ヘッダー列＝P-193・最後の固定列＝N-17）も、スクロールの無い
       紙では意味を持たないので消す。box-shadow を !important で消すと、同じセルに box-shadow で描く
       状態表示（検索一致・条件付きハイライトの内枠）まで紙から消えるため、影の値の変数だけを透明へ
       差し替える（画面と同じ詳細度で、後ろにあるこちらが勝つ）。 */
    #data-grid .jexcel {
        --row-header-edge-shadow: 0 0 transparent;
        --frozen-col-edge-shadow: 0 0 transparent;
    }

    th, td {
        -webkit-print-color-adjust: exact;
        print-color-adjust: exact;
    }
}

/* ============================================================
   フリーシートモード（N-23 アドバンスPlanner）
   body.freesheet-mode でピボット系UIとフリーシートの表示を入れ替える。
   表示切替はクラスのみで行い、インライン style は使わない（CSP 準拠）。
   ============================================================ */

.freesheet-container {
    display: none;
    flex-direction: column;
    flex-grow: 1;
    min-height: 0;
    padding: 16px 24px 24px;
    gap: 10px;
}

body.freesheet-mode .toolbar,
body.freesheet-mode .grid-container,
body.freesheet-mode #btn-submit {
    display: none;
}

body.freesheet-mode .freesheet-container {
    display: flex;
}

.freesheet-toolbar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.freesheet-mode-label {
    font-weight: 700;
    color: var(--text-muted);
    white-space: nowrap;
}

.freesheet-title {
    font-weight: 600;
    max-width: 320px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* P-75: 読込中フリーシートの共有範囲（公開＝テナント全員 / 自分のみ）を示すバッジ。
   ユーザー状態バッジ（.badge-active / .badge-pending）と同じピル作法。公開設定ラジオ（P-69）の
   藍系トーンに合わせ、公開＝淡い藍・自分のみ＝淡いスレートで区別する。表示のみ。 */
.freesheet-visibility-badge {
    display: inline-block;
    padding: 2px 10px;
    border-radius: var(--radius-pill);
    font-size: var(--fs-xs);
    font-weight: 700;
    white-space: nowrap;
}
/* display を明示しているため、UA の [hidden] { display: none } は上書きされてしまう。
   .unsaved-badge[hidden] / .comment-unread-badge[hidden] と同じ作法で companion ルールを添える。 */
.freesheet-visibility-badge[hidden] {
    display: none;
}
.freesheet-visibility-badge-public {
    background-color: rgba(79, 70, 229, 0.12);
    color: var(--primary);
    border: 1px solid rgba(79, 70, 229, 0.25);
}
.freesheet-visibility-badge-private {
    background-color: var(--slate-100);
    color: var(--slate-600);
    border: 1px solid var(--border-color);
}

/* P-74: フリーシートツールバーの「シート識別（ラベル・タイトル・読込セレクト）」と
   操作ボタン群、および操作ボタンの機能グループ間に細い縦罫で視覚的リズムを付ける（P-07/P-14と同じ観点）。
   flex-wrap 折り返し時は通常の flex アイテムとして流れ、レイアウトは崩れない。 */
.freesheet-toolbar-sep {
    width: 1px;
    align-self: stretch;
    min-height: 20px;
    background: var(--border-color);
    margin: 0 2px;
}

.freesheet-select {
    min-width: 200px;
    max-width: 320px;
}

/* P-76: 数式ヘルプは <details> の二段構成。要点1行は常時見えるので初見でも迷わず、
   習熟ユーザーは畳んでグリッドの表示領域を広げられる（開閉状態は free-sheet.js が localStorage に保存）。
   CSP でインライン script/style が禁止されているため、開閉は <details> のネイティブ挙動を使う。 */
.freesheet-hint {
    font-size: var(--fs-sm);
    color: var(--text-muted);
    line-height: 1.6;
}

.freesheet-hint-summary {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    cursor: pointer;
    padding: 2px 0;
    /* 既定の三角マーカーを消し、右端のシェブロンで開閉を示す */
    list-style: none;
}
.freesheet-hint-summary::-webkit-details-marker {
    display: none;
}
.freesheet-hint-summary:hover {
    color: var(--text);
}
.freesheet-hint-summary:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
    border-radius: 4px;
}

.freesheet-hint-lead {
    min-width: 0;
}

/* 「詳しい書き方」トグルは淡いチップ。開いているときはシェブロンを反転させる。 */
.freesheet-hint-more {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 1px 8px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-pill);
    font-size: var(--fs-xs);
    font-weight: 600;
    white-space: nowrap;
}
.freesheet-hint-chevron {
    font-size: var(--fs-3xs);
    transition: transform var(--motion-fast) ease;
}
.freesheet-hint[open] .freesheet-hint-chevron {
    transform: rotate(180deg);
}

.freesheet-hint-body {
    padding: 4px 0 0 20px;
}

.freesheet-hint code {
    background: var(--slate-100);
    border: 1px solid var(--border-color);
    border-radius: 4px;
    padding: 0 4px;
}

#freesheet-grid {
    flex-grow: 1;
    min-height: 0;
    overflow: auto;
    background: #ffffff;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
}

/* 数式セル: 計算結果を表示中であることを控えめな色とマークで示す */
#freesheet-grid td.fs-formula-cell {
    background: #f5f9ff;
    color: var(--blue-700);
    font-variant-numeric: tabular-nums;
}

#freesheet-grid td.fs-formula-error {
    background: var(--red-50);
    color: var(--red-700);
    font-weight: 600;
}

.freesheet-settings-hint {
    font-size: var(--fs-sm);
    color: var(--text-muted);
    margin: 4px 0 0;
}

/* フリーシート「関数の挿入」ダイアログ（N-23 追補）。左に関数一覧、右にラベル付き入力欄＋
   プレビューという2ペイン構成は dim-modal（ディメンション管理）と同じ .dim-sidebar/.dim-main
   を流用し、専用CSSは狭いサイズ調整と入力フォーム部分のみに絞る。 */
.modal-content-formula-builder {
    max-width: 760px;
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    margin: 4% auto;
}

.modal-body-formula-builder {
    overflow: hidden;
    flex: 1;
}

.modal-body-formula-builder .dim-sidebar { width: 220px; }
.modal-body-formula-builder .dim-sidebar ul { display: flex; flex-direction: column; gap: 2px; }
.modal-body-formula-builder .dim-main { padding: 24px; }

.ff-target-cell {
    margin: 0 0 4px;
    font-weight: 600;
    color: var(--text);
}

.ff-function-desc {
    margin: 0 0 16px;
    color: var(--text-muted);
    font-size: 0.85rem;
    line-height: 1.5;
}

.ff-form-row {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 12px;
}

.ff-form-row-label {
    display: flex;
    align-items: center;
}

/* ZD 引数行: 指定方法（メンバー／セル参照）と値の入力欄を縦に並べる（N-39） */
.ff-arg-control {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.ff-arg-mode {
    max-width: 220px;
}

.ff-arg-member[hidden] {
    display: none;
}

.ff-arg-ref {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.ff-arg-ref[hidden] {
    display: none;
}

.ff-arg-ref-input {
    max-width: 120px;
}

.ff-arg-ref-input.ff-invalid {
    border-color: var(--red-600);
}

/* ZD表ウィザード: 行／列の軸ブロックを2カラムに並べる（N-38） */
.ff-axis-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
    margin-bottom: 16px;
}

.ff-axis-block {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.ff-axis-title {
    margin: 0;
    font-weight: 600;
    color: var(--text);
}

.ff-axis-members {
    height: auto;
    padding: 4px;
}

.ff-fixed-block {
    margin-bottom: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--border-color);
}

.ff-table-options {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    padding-top: 12px;
    border-top: 1px solid var(--border-color);
}

.ff-table-options .ff-form-row {
    flex-direction: row;
    align-items: center;
    margin-bottom: 0;
    gap: 8px;
}

.ff-label-mode {
    max-width: 180px;
}

@media (max-width: 720px) {
    .ff-axis-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.ff-preview-block {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--border-color);
}

.ff-preview-text {
    display: block;
    background: var(--slate-100);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 10px 12px;
    font-family: var(--font-mono, monospace);
    font-size: 0.85rem;
    word-break: break-all;
    white-space: pre-wrap;
}

.ff-preview-hint {
    margin: 6px 0 0;
    font-size: 0.8rem;
    color: var(--text-muted);
}


/* =========================================================================
   N-49: 狭幅（〜768px）でのアプリシェルの縦配分
   ---------------------------------------------------------------------
   デスクトップのシェルは `.app-container { height: 100vh }` の1画面完結で、
   グリッド領域が `flex-grow: 1` で「余り」をもらう作りになっている。狭幅では
   ヘッダー（375px で 201px）とツールバー（同 808px）だけで 100vh を使い切るため、
   グリッドの取り分は 48px まで潰れ、さらに `.grid-container { overflow: hidden }`
   が 300px 相当の表を切り取ってしまう。結果、ページを最下部まで送っても
   データグリッドの可視高さが 0px になり（N-47 の実測で 375/390/768px の3幅とも 0）、
   閲覧専用の用途ですら主画面へ到達できなかった。

   そこで狭幅では1画面完結をやめ、**通常の縦スクロール文書**として扱う。
   ヘッダーとツールバーはページ上部に流れ、下へスクロールすればグリッドが出る。
   広い幅（769px 以上）は 1 画面完結が正しいので一切変更しない。

   JS でのレイアウト計算は入れない（`calcGridHeight()` は
   `Math.max(300, …)` の下限を持つため、狭幅では自動的に 300px が採用される）。
   ========================================================================= */
@media (max-width: 768px) {
    /* 高さの上限をなくす。min-height に替えることで、内容が短いテナントでも
       背景が画面下まで届く見た目は保たれる。 */
    .app-container {
        height: auto;
        min-height: 100vh;
    }

    /* 「余りをもらう」前提が成立しないため、自前の最低高さを持たせる。
       overflow は visible に戻す（hidden のままだと、取り分が足りないときに
       中身が無言で消える＝今回の症状そのものになる）。 */
    .grid-container {
        overflow: visible;
        min-height: 60vh;
    }

    /* フリーシート（N-23）側も同じシェルの上に乗っており、`#freesheet-grid` は
       `flex-grow: 1; min-height: 0`、jspreadsheet は `tableHeight: '100%'` で
       親の高さに追従する。シェルが auto 高になると両者が 0 に潰れるため、
       こちらにも最低高さを与えて同じ症状を作らないようにする。 */
    .freesheet-container {
        overflow: visible;
        min-height: 60vh;
    }

    #freesheet-grid {
        min-height: 50vh;
    }

    /* 選択範囲ステータスバーは5つの操作・情報グループを横一列に並べる前提で、375px でも
       716px を必要とする。従来この超過は `.grid-container` の overflow: hidden が
       隠していただけで、入力率バッジ（`#grid-completion-badge`）と選択統計
       （`#grid-selection-stats-text`）は読めないままだった（N-47 内訳2）。上で
       縦スクロール文書へ切り替えると、同じ超過が今度はページの横スクロールとして
       表に出るため、ここで折り返せるようにして両方まとめて解消する。 */
    .grid-selection-stats {
        gap: 10px 12px;
    }

    /* 読み取り情報を右端へ押し出すための余白吸収（P-73）は、折り返すと行末に
       不自然な空きを作るだけになるので狭幅では外す。 */
    .grid-comment-group {
        margin-right: 0;
    }

    /* バーの中で最も長い要素。単独の行へ落として折り返させる。 */
    .grid-selection-stats-text {
        flex-basis: 100%;
        text-align: left;
        overflow-wrap: anywhere;
    }

    /* 指標名が長いピルは、幅の狭い画面では画面を越えないようピルの中で折り返す。 */
    .grid-selection-stats-text .sel-stat {
        white-space: normal;
    }

    /* N-55: 行ヘッダー列（勘定科目など）の幅を狭幅だけ詰める。
       375px ではグリッドの内側スクローラ（.jexcel_content）の幅が 323px しかなく、
       行ヘッダー列の既定 280px（grid.js の columns[0].width）がそのほとんどを占めるため、
       データ列（既定 100px）は 43px しか見えず**1列も丸ごと入らない**。行ヘッダー列は
       `position: sticky; left: 0` で常に左端に貼り付くので、内側を横へ送っても残り幅は
       増えない＝「数字を見に来たのに数字が見えない」状態になっていた（N-49 の実測）。

       幅は <colgroup> の <col> に当てる。jspreadsheet は table-layout: fixed のテーブルへ
       `<col width="280">` を出力しており（列幅は td 側の width/min-width ではなく col が決める）、
       width 属性は presentational hint ＝ 作成者スタイルより弱いため、ここでの指定が勝つ。
       col に当てることで、列幅記憶（N-12）が広い画面で保存した値を持っていても、狭幅では
       この幅が適用される（保存値そのものは書き換えないので、広い画面へ戻せば元どおり）。
       :nth-child(2) は非表示の行番号列（col:first-child = visibility: collapse）の次＝
       実際の1列目（data-x="0"）を指す。

       140px にすると 375px でも 183px（323 − 140）が残り、100px のデータ列が1列まるごと
       視界に入る。名前が入りきらない分は jspreadsheet 既定の overflow: hidden で切られる
       （行ヘッダーのセルには updateTable で「表示名（ID）」の title を付けているため、
       広い画面ではホバーで全文を確認できる）。列幅ドラッグの掴み代は狭幅では引き続き
       画面外のことがあるが、これは N-55 の対象外（マニュアルに「列幅の調整は広い画面で行う」と明記済み）。 */
    #data-grid table.jexcel > colgroup > col:nth-child(2) {
        width: 140px;
    }

    /* 上で列を詰めると入りきらない名前が出る。省略記号（…）は狭幅に限らず全幅で付けている
       （P-190。行ヘッダーの sticky を当てている `td[data-x="0"]` の規則を参照）。 */

    /* =====================================================================
       N-52: ヘッダーのドロップダウンを画面内に収める。

       狭幅ではヘッダーのボタン群が3段に折り返すため、各メニューの `.header-menu`
       は右へも下へも流れる。ドロップダウンはその `.header-menu` を基準にした
       絶対配置なので、375px でデータメニューを開くと右へ 96px はみ出し、
       下端も画面外へ 32px 出て、最下段の「利用状況サマリ」が押せなかった
       （N-47 内訳4 の実測）。

       そこで狭幅だけ、アンカーを `.header-menu` から `header` 自体へ移す。
       `header` を包含ブロックにすると、ドロップダウンは「ヘッダーの真下・
       ヘッダー幅いっぱい」に出るので、何段に折り返しても右へはみ出さない。
       項目の並び・id・ハンドラの配線は一切変えていない（表示位置のみ）。

       スコープは `header` の中に限る。ツールバーの「表示 ▾」（`#menu-display`）も
       同じ `.header-menu` / `.header-menu-dropdown` を使い回しており、そちらの
       `position: static` 化は包含ブロックを初期包含ブロックへ飛ばして
       `top: calc(100% + 6px)` を壊すため。
       ===================================================================== */

    /* P-155: ドロップダウンを持つのは app.html のヘッダーだけなので、操作マニュアルの
       ヘッダー（`.manual-header`）は除く。`.app-header`（0-1-0）だけで書くと、
       先に書いてある `.manual-header { position: sticky }`（同じ 0-1-0）を後出しで
       押し負かし、**768px 以下でマニュアルの固定ヘッダーが固定されなくなる**
       （実測で検出: position が sticky → relative に変わっていた）。 */
    .app-header:not(.manual-header) {
        position: relative;
    }

    .app-header .header-menu {
        position: static;
    }

    .app-header .header-menu-dropdown,
    .app-header .header-menu-dropdown-right {
        left: 0;
        right: 0;
        /* max-height の 100% は包含ブロック（`header` のパディングボックス）の
           高さ、つまりヘッダー高さそのもの。`top: calc(100% + 6px)` と対にして
           「ヘッダーの下に残っている高さ − 余白」を上限にできるので、
           ヘッダーが何段に折り返しても下端が画面外へ出ない。 */
        max-height: calc(100vh - 100% - 16px);
        max-height: calc(100dvh - 100% - 16px);
    }

    /* 幅がヘッダー幅に固定されるため、長いラベル（「Excel編集用ダウンロード」など）は
       nowrap のままだと横へあふれる。狭幅では折り返して全文を見せる
       （高さが増える分は上の max-height ＋ 内側スクロールが受ける）。 */
    .app-header .header-menu-item {
        white-space: normal;
    }

    /* =====================================================================
       N-50: 狭幅でヘッダーの操作ボタン群を1段に収める。

       ヘッダーの高さは 768px で 96px、375px・390px では **201px**（3段折り返し）で、
       画面の 1/4 を常時表示のヘッダーが占めていた（N-47 の実測）。狭幅では
       画面の高さが最も希少な資源で、これが N-49 の「グリッドに 48px しか残らない」の
       一因にもなっていた。

       取った手は、ボタンを別メニューへ畳むのではなく、**ラベルを視覚的に隠して
       アイコンだけにする**ことで幅を詰め、1段に収める方法。別メニューへ畳む案は
       採らなかった——header-menu.js の `closeAllMenus()` は `.header-menu` を一律に閉じるため
       `.header-menu` の入れ子が作れず（内側を開くと外側が閉じる）、入れ子を避けるには
       項目を複製して新しい id とハンドラを配線することになるが、本項目の実装方針は
       「メニュー項目の id とハンドラの配線は一切変えない」と定めている。アイコンのみなら
       CSS だけで済み、しかも全ての導線が従来どおり**1タップ**のまま残る（畳むと 2タップになる）。

       ラベルは `display: none` ではなくクリップで隠すので、スクリーンリーダーには
       従来どおり「データ」「管理者メニュー」と読まれる。見える利用者向けには各ボタンの
       `title` がそのまま残る。保存（`#btn-submit`）だけは文字を残す——主導線であり、
       未保存バッジの付く先でもあるため。
       ===================================================================== */
    /* P-159: マニュアルのヘッダーは `padding: 0` で内側に余白を任せているので、
       ここで外側の余白を戻してしまわないよう対象から外す（`.app-header`（0-1-0）だけで
       書くと、先に書いてある `.manual-header { padding: 0 }`（同じ 0-1-0）を
       後出しで押し負かしてしまうため）。 */
    .app-header:not(.manual-header) {
        padding: 10px 12px;
    }

    /* アイコンのみになる分、ボタン間の間隔も詰める（タップ目標の大きさは
       下の min-width/min-height で保つので、詰めても押しにくくはならない）。 */
    .app-header .header-btn-mr {
        margin-right: 6px;
    }

    /* ロゴの見出しと、操作ボタンのラベルを視覚的にだけ隠す。 */
    /* P-160: クリップの対象は app.html / system.html のヘッダーだけ。マニュアルの
       ヘッダーは要素が2つ（ロゴ＋戻るボタン）しか無く詰める必要が無いのに、
       無限定の `.app-header h1` が当たって**ページの題名が狭幅で消えていた**
       （実測 191×33.6px → 1×1px）。しかも見出しが消えて内側が縮んだぶん
       「プランナーに戻る」が折り返し、ヘッダーは逆に 84.5px → 107px へ伸びていた。
       `.header-btn-label` は app.html のボタンにしか無いので、こちらは据え置く。 */
    .app-header:not(.manual-header) h1,
    .app-header .header-btn-label {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        border: 0;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    /* ラベルが無くなった分、左右の余白も詰める。ただし 44x44 CSS px（N-53 の下限）を
       下回らないよう min-width / min-height を与える。アイコン化でタップ目標が
       小さくなるのでは本末転倒になるため。 */
    .app-header nav .btn {
        padding: 8px 10px;
        min-width: 44px;
        min-height: 44px;
    }

    /* =====================================================================
       P-160（続き）: マニュアルの見出しを残したまま、ヘッダーを1段に収める。

       クリップを外しただけだと 1.4rem の見出し（191px）と「プランナーに戻る」
       （164.3px）が 375px の中に並ばず、見出しが2段に折り返してヘッダーが
       92.2px になる。app.html のようにラベルを隠す手は採らない——マニュアルは
       「いま何を読んでいるか」の手掛かりが見出ししか無いページで、それを消すのが
       P-160 そのものだから。代わりに**見出しとロゴの寸法を狭幅用に落として幅を作る**。
       必要幅の内訳（375px・内側の余白 12px のとき中身に使えるのは 351px）:
         ロゴ 20.8 ＋ 間隔 8 ＋ 見出し 143 ＋ 間隔 10 ＋ 戻る 164.3 = 346px。
       戻るボタンの高さ（62px = 44px のタップ目標 ＋ 上下の余白と罫線、N-53）が
       ヘッダー高さを決めるので、1段に収まれば 83px 前後で落ち着く。
       ===================================================================== */
    .manual-header-inner {
        padding: 10px 12px;
        gap: 10px;
    }

    .manual-header .logo-area {
        gap: 8px;
        /* 見出しが縮むより先にフレックスアイテムが縮まないよう、下限を外す。 */
        min-width: 0;
    }

    .manual-header .logo-icon {
        font-size: 1.3rem;
    }

    .manual-header h1 {
        font-size: 1.05rem;
    }

    /* 1段に収める前提なので、戻るボタンのラベルは途中で折り返させない。 */
    .manual-header .logo-area,
    .manual-header .btn {
        white-space: nowrap;
    }

    /* =====================================================================
       N-51: 狭幅でツールバーとフィルターを縦積みにして横のはみ出しを解消する。

       N-49 で1画面完結をやめた結果、ツールバーの必要幅（375px で 534px）が
       ページ全体の横スクロール 159px として表に出ていた（390px では 144px）。
       横へずれる画面は縦スクロールと操作が競合し、数字を目で追う用途そのものを
       壊すため、狭幅では**横に並べる前提のレイアウトを縦積みへ切り替える**。

       原因は1か所ではなく、次の3つが重なっている。
         (a) `.axis-config` は wrap するが、パネル自体の幅は中身の必要幅
             （tools パネルで 510px）になるため、パネルごと画面外へ出る。
         (b) `.config-group` は `display: flex` のみで折り返さない。375px では
             縦軸グループが 415px、グリッド内検索グループが 474px を必要とする。
         (c) ラベルの `min-width: 65px`（右寄せ）とセレクトの `min-width: 150px` は
             「横に十分な幅がある」前提の揃えで、狭幅では死に幅になる。

       グリッド本体（`.jexcel_content`）の横スクロールは**現状のまま維持する**。
       あちらは内側に閉じており、表として正しい挙動（N-47 の内訳6）。
       ===================================================================== */

    /* 左右 24px の余白は 375px では画面の 13% を占める。中身を1列に積む以上、
       余白より中身に幅を回す。 */
    .toolbar {
        padding: 12px;
        gap: 12px;
    }
    /* P-223: 狭幅ではボタンが 44px（タッチの最小）になり、下端に掛けると最後のフィルターに重なる。
       縦積みでページごとスクロールする幅なので、流れの中で右端に置く。 */
    .btn-toolbar-toggle {
        position: static;
        align-self: flex-end;
    }

    .axis-panel, .filters-panel {
        padding: 10px 12px;
    }

    /* (a) パネルが親より広くならないようにする。flex アイテムの既定 `min-width: auto`
       は「中身の必要幅より小さくならない」という意味なので、これを解除しないと
       下の折り返しを入れてもパネル側が縮まない。`max-width: 100%` と対にすることで、
       入りきらないパネルは親幅まで縮んで1枚ずつの縦積みになり、入るパネルは
       従来どおり横に並ぶ（768px では縦の取り分を減らさない）。 */
    .axis-config > * {
        flex: 1 1 100%;
        min-width: 0;
        max-width: 100%;
    }

    /* (b) 操作グループを折り返せるようにする。入りきらない部品は次の行へ送る。 */
    .config-group {
        flex-wrap: wrap;
        row-gap: 8px;
    }

    /* (c) ラベル列を揃えるための固定幅・右寄せを外す。折り返した後は
       そもそも列が揃わないため、揃えるための幅を確保する意味が無い。 */
    .config-group label {
        min-width: 0;
        text-align: left;
    }

    /* (c) セレクトの下限 150px を外し、残り幅で頭打ちにする。
       `width: auto` も併せて指定する——`.form-input` を併用しているセレクト
       （グリッド内検索の対象軸など）は `width: 100%` を持っており、折り返しを
       許した途端に「1行まるごとを占める部品」になって、後続の部品を全部
       次の行へ押し出してしまうため。中身（最長の選択肢）ぶんの幅に戻す。 */
    .config-group select {
        width: auto;
        min-width: 0;
        max-width: 100%;
    }

    /* グリッド内検索の入力欄（160px 固定）は、flex アイテムの既定 `min-width: auto`
       ＝ input の min-content 幅（size 属性ぶん）が下限になっていて縮まない。
       ここを解除して、折り返した行の残り幅に合わせて縮めるようにする。
       **`width` は 160px のまま残す**——`flex-basis` を小さくすると、この行の
       max-content 幅が縮んで `.axis-panel-tools` 自体が細くなり、768px のように
       横幅に余裕がある場合でも検索グループが3行に折り返してしまうため。 */
    .grid-search-group .input-w-160 {
        min-width: 0;
    }

    /* ビュー操作群（ラベル＋絞り込み＋セレクト＋ボタン5つ）は 405px 必要で、
       `justify-content: space-between` の横並びのままだと縮められる側の見出しが
       16px まで潰れ、「フィルター」が1文字ずつ縦に改行される。折り返しを許して
       操作群を次の行へ落とす（入る幅では従来どおり横一列のまま）。 */
    .filters-header {
        flex-wrap: wrap;
        gap: 8px;
    }

    /* 見出し自体は折り返さない。 */
    .filters-header > span {
        white-space: nowrap;
    }

    .view-management-row {
        flex-wrap: wrap;
        row-gap: 6px;
        min-width: 0;
        max-width: 100%;
    }

    .view-select {
        max-width: 100%;
    }

    /* =====================================================================
       N-53: タップ目標を 44x44 CSS px 以上にする。

       N-47 の実測で「幅によらず 44x44 未満のタップ目標が 37 件」あり、うち
       ヘッダーの5件は N-50（PR #647）の `header nav .btn` で下限を満たした。
       残りはツールバー・ビュー操作・グリッド操作の操作子で、高さが 31〜36px、
       アイコンのみのボタンは幅も 29〜36px しかない。指の接触面（Apple HIG 44pt /
       Material 48dp）より小さく、隣の操作子を誤って押しやすい。数字を扱う製品では
       誤タップが入力ミスに直結し、取り消しの手間が大きい。

       下限は狭幅だけに与える。広い画面はポインタで狙うため現状の密度が正しく、
       全幅で 44px にするとツールバーが縦に伸びてグリッドの取り分（N-49）を削る。

       `.btn` / `.btn-icon` は `display: inline-flex; align-items: center;
       justify-content: center` なので、min-height を足しても中身は中央のまま
       高さだけが伸びる（padding を積むと文字位置がずれるため min-* を使う）。
       ===================================================================== */
    .btn,
    .btn-icon,
    .form-input,
    select,
    .skip-link {
        min-height: 44px;
    }

    /* アイコンだけのボタン（元に戻す・やり直す・お気に入り・前後の一致など）は
       幅も 44px を下回るため、横方向の下限も与える。テキスト付きのボタンや
       150px 幅のセレクトは元から超えているので、この指定では変化しない。 */
    .btn,
    .btn-icon,
    select {
        min-width: 44px;
    }

    /* 軸設定のチェックボックス6個（`#chk-row-all` など）は 16x16 で最小だが、
       **チェックボックス自体は拡大しない**——ネイティブの描画がそのまま 44px の
       四角になり、文字より大きな箱が並ぶ見た目になるため。いずれも `<label>` が
       入力を包んでおり、ラベルのどこを押してもトグルできる（HTML の仕様）。
       そこでラベル側を 44px の当たり判定にし、文字列も含めて押せるようにする。
       （P-161 以前は `.label-nowidth` だけ flex ではなく、ここで並べ方を揃えていた。
       同クラスは縦軸パネルの2ラベルだけが使っており、横軸側の `.label-nowidth-flex` へ
       統合して削除済み。）

       この解法では入力要素自身の矩形は 16x16 のまま残るため、
       `assets/measure_mobile_layout.py` の `TAP_JS` は当たり判定の実体である
       ラベルの矩形で判定するよう同じ変更で直してある（N-52 で `DROPDOWN_JS` を
       直したのと同じ理由——直したものを不合格と判定させないため）。 */
    .label-flex,
    .label-nowidth-flex,
    .display-menu-option {
        display: inline-flex;
        align-items: center;
        min-height: 44px;
    }

    /* 上の下限で、グリッド内検索の行（セレクト 150px ＋ 入力 160px ＋ 前後ボタン）が
       375px で 474px → 499px へ広がり、ページ全体の横スクロールが 159px → 184px と
       **悪化する**。押しやすくするために横へずらす画面を作っては本末転倒なので、
       この行だけ折り返しを許して吸収する（実測 375px で 184 → 106px、390px で
       169 → 91px と、着手前の 159／144px より短くなる）。
       なお [N-51] は同じ狭幅ブロックで `.config-group` 全体に折り返しを与えて
       横スクロールを 0 にする。あちらが入れば本規則はその一部に含まれる。 */
    .grid-search-group {
        flex-wrap: wrap;
    }

    /* P-152: 同じステータスバーの「選択範囲」の組（見出し＋値の入力欄＋一括入力ボタン）も
       折り返しの対象から漏れており、320px 幅ではステータスバーの枠から右へ 4px はみ出していた
       （実測。360px 以上では収まる）。上の `.grid-search-group` と同じ作法で折り返しを許す。
       flex-wrap は入りきらないときにだけ働くため、収まっている 360px 以上の見た目は変わらない
       （実測: 360／375／480／768px とも組の幅 259px・高さ 44px のまま）。 */
    .grid-fill-group {
        flex-wrap: wrap;
    }

    /* P-162: 操作ログの絞り込みのうち「期間」の組だけは中身が4つ（見出し＋開始日＋
       「〜」＋終了日）あり、P-57 が `.audit-filter-item` に与えた `flex-wrap: nowrap`
       のままだと1行に収まりきらない。`.modal-body` が `overflow-x: hidden` なので、
       **はみ出した 83px ＝ 終了日の入力欄の右半分は切り落とされて操作もスクロールも
       できない**。**この 83px は「組の右端 440px − モーダル本文の右端 357px」＝
       どちらも画面左端からの絶対座標で測った値**（375px 幅。414px でも同じ。480px
       以上では収まる）。P-171: 以前は「組の幅 392px − 本文の幅 338px」という別の
       測り方の対も併記していたが、組の左端は本文の左端と一致しない（絞り込みの並びの
       中で右へずれている）ため引き算がつながらず、79px・83px と食い違う値が3ファイルに
       残っていた。**基準は絶対座標の右端どうしに一本化する**。
       P-57 の狙いは「見出しと入力欄が別々の行に分かれて左端が不揃いになるのを防ぐ」
       ことなので、狭幅では折り返しを許して**組の中で**次の行へ送る。見出しは先頭に
       残るため左端の不揃いは起きない。入りきる幅では flex-wrap は働かないので、
       480px 以上の見た目は変わらない。 */
    .audit-filter-item {
        flex-wrap: wrap;
    }

    /* P-174・P-176: 一覧（.dim-sidebar）／編集（.dim-main）の2ペインを持つモーダルを
       縦積みへ切り替える。横並びのままだと 375px で右ペインがディメンション管理で 183px、
       「関数の挿入」で 181px まで潰れていた（実測）。両モーダルの .modal-body に付けた
       共通の修飾クラス .modal-body-split の下に書く（素の .dim-sidebar/.dim-main には
       書かない）。ディメンション管理だけの中身の詰めは、続く .modal-body-dim の下に置く。 */
    .modal-body-split {
        flex-direction: column;
    }

    /* 一覧は上段へ。縦に並べると6件で 300px を超えて編集側を押し出すため、チップ状に
       折り返して並べ、件数が多いときだけ自分の中で縦スクロールさせる。
       「関数の挿入」側は広い画面用に ul を flex-direction: column にしているので、
       ここで row へ戻す（同じ詳細度で、こちらが後に来る）。 */
    .modal-body-split .dim-sidebar {
        width: auto;
        flex: 0 0 auto;
        max-height: 30vh;
        overflow-y: auto;
        padding: 12px 16px;
        border-right: none;
        border-bottom: 1px solid var(--border-color);
        /* P-177: 一覧が 30vh を超えて中でスクロールするとき、続きがある側の縁にだけ薄い影を
           出す（スクロールシャドウ）。チップを 44px にしたことで 375×812 でも「関数の挿入」の
           10個が収まらなくなり、しかも切れ目がちょうど行の境に来て最後の IF が丸ごと隠れ、
           続きがあると気付けなかった。影は scroll（箱に固定）、それを覆う背景色の帯は local
           （中身と一緒に動く）で描くので、端までスクロールし切った側と、溢れていない一覧では
           帯が影を隠して何も見えない。画面の高さに左右されず、JS も要らない。 */
        background:
            linear-gradient(var(--slate-50) 30%, transparent) center top / 100% 40px no-repeat local,
            linear-gradient(transparent, var(--slate-50) 70%) center bottom / 100% 40px no-repeat local,
            radial-gradient(farthest-side at 50% 0, rgba(15, 23, 42, 0.14), transparent) center top / 100% 12px no-repeat scroll,
            radial-gradient(farthest-side at 50% 100%, rgba(15, 23, 42, 0.14), transparent) center bottom / 100% 12px no-repeat scroll,
            var(--slate-50);
    }

    .modal-body-split .dim-sidebar ul {
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        gap: 6px;
    }

    /* P-177: チップは押して切り替える部品（ディメンション／関数の選択）なので、N-53 の
       タップ目標の下限 44px を与える。padding だけでは 36px（375px の実測）に留まり、
       N-53 が .btn などに与えた min-height からも漏れていた。文字は flex で縦中央に置く。
       行が伸びた分「関数の挿入」の一覧は 30vh の中で縦スクロールになる（続きの合図は上の
       .dim-sidebar のスクロールシャドウ）。box-sizing を border-box にしないと padding の
       16px が上乗せされて 60px になる。 */
    .modal-body-split .dim-sidebar li {
        display: flex;
        align-items: center;
        box-sizing: border-box;
        min-height: 44px;
        margin-bottom: 0;
        padding: 8px 12px;
        border: 1px solid transparent;
        font-size: var(--fs-md);
    }

    /* P-181: 縦の一覧なら「行全体が押せる」ことが並び方で分かるが、チップ状に折り返すと
       選ばれていない項目は背景も枠も無い文字だけになり、見出しや説明文と見分けにくかった。
       狭幅のときだけ白地＋枠でボタンらしく見せる（--slate-50 の一覧の地との差で形が出る）。
       枠の 1px は上の li に透明で先に取ってあるので、選択の切り替えで高さも幅も動かない。
       素の .dim-sidebar li:hover・li.active と詳細度が並ぶと後勝ちで塗りを潰すので、
       :not(.active) で選択中を外し、hover もこの下で描き直す。 */
    .modal-body-split .dim-sidebar li:not(.active) {
        background: #ffffff;
        border-color: var(--border-color);
    }

    .modal-body-split .dim-sidebar li:not(.active):hover {
        background: var(--slate-200);
    }

    /* 編集側は下段で残りの高さを受け取り、縦にだけスクロールする。 */
    .modal-body-split .dim-main {
        flex: 1 1 auto;
        min-height: 0;
        padding: 16px;
    }

    .modal-body-dim .dim-edit-header {
        flex-wrap: wrap;
        align-items: flex-start;
        gap: 12px;
        padding: 14px;
        margin-bottom: 16px;
    }

    .modal-body-dim .dim-edit-left {
        flex-wrap: wrap;
        gap: 8px 16px;
        min-width: 0;
        width: 100%;
    }

    .modal-body-dim .dim-edit-left .form-group {
        flex: 1 1 100%;
        min-width: 0;
    }

    .modal-body-dim .dim-input-desc {
        width: 100%;
    }

    .modal-body-dim .ai-dim-box {
        padding: 14px;
        margin-bottom: 16px;
    }

    .modal-body-dim .ai-dim-header {
        flex-wrap: wrap;
    }

    /* 指示欄とボタンを横に並べると、ボタンの最小幅 140px で指示欄が数文字幅まで潰れる。 */
    .modal-body-dim .ai-dim-row {
        flex-direction: column;
        align-items: stretch;
    }

    .modal-body-dim .btn-ai-dim {
        height: auto;
        min-height: 44px;
        min-width: 0;
    }

    /* メンバー表（5列＋入力欄）は 383px 必要で、狭幅では収まりきらない。はみ出しを
       ペイン全体の横スクロールにせず、表の列だけで横へ送れるようにする。
       引き換えに、この幅では見出し行の固定（P-99）は効かなくなる（スクロールポートが
       この列になり、縦には送られないため）。見出しが横送りに追従する方を優先した。
       分割部は 960px 以下で既に縦積みだが、align-items: flex-start のままだと列が中身の
       幅まで伸びて overflow-x が働かないので、幅を親に揃えさせる。 */
    .modal-body-dim .dim-edit-split {
        align-items: stretch;
    }

    .modal-body-dim .dim-edit-table-col {
        overflow-x: auto;
    }

    .modal-body-dim .dim-tree-col {
        min-width: 0;
    }
}

/* N-50（続き）: 375px より狭い端末向けの詰め。
   アイコン化後の操作ボタン群は 44+54+54+68+57 = 277px 必要で、マージンと
   ロゴアイコンとヘッダーの左右余白を足すと 375px では 1段に収まるが、360px
   （Android に多い幅）ではわずかに足りず 2段に戻ってしまう。ボタン間の間隔と
   ヘッダーの左右余白をさらに詰めて 360px も 1段に収める（320px はこれでも 2段だが、
   従来の 3段・201px からは半分以下になる）。 */
@media (max-width: 374px) {
    /* P-159: 上と同じ理由でマニュアルのヘッダーは対象から外す。 */
    .app-header:not(.manual-header) {
        padding: 10px 8px;
    }

    .app-header .header-btn-mr {
        margin-right: 4px;
    }

    /* P-160（続き）: 320px では見出しと戻るボタンを1段に並べきれない
       （必要幅 330px に対し中身に使えるのは 296px）。ここは**見出しを1行で残し、
       戻るボタンを次の段へ送る**——見出しを消して1段に収める案は、狭い画面ほど
       「いま何を読んでいるか」が要るという P-160 の前提に反する。
       ヘッダー高さは従来の 107px とほぼ同じまま、題名が出るようになる。 */
    .manual-header-inner {
        flex-wrap: wrap;
        gap: 6px 10px;
    }

    .manual-header .logo-icon {
        font-size: 1.15rem;
    }

    .manual-header h1 {
        font-size: 0.95rem;
    }

    /* 次の段へ送られた戻るボタンは、1段に収まる幅のときと同じ右端へ置く
       （`justify-content: space-between` は項目が1つだけの段では左寄せになるため）。 */
    .manual-header-inner .btn {
        margin-left: auto;
    }
}

/* P-119: ディメンション追加ダイアログ。OS 標準の prompt() 2連発（ID → 名称）を、
   他のモーダルと同じ体裁の入力フォームへ置き換えたもの。prompt() は入力規則を書く場所が
   無く、英数字以外を入れると閉じてからトーストで差し戻されるため、打った文字ごと消えていた。
   幅はビュー保存モーダル（modal-content-save-view）と同じ 400px に揃える。 */
.modal-content-add-dim { max-width: 400px; height: auto; }
.modal-body-add-dim { padding: 20px; flex-direction: column; }

/* 入力欄の下に添える補足文。**この役割のクラスはこれ1つだけ**（P-125）。
   かつて .ff-hint（0.85rem）・.axis-bulk-hint（0.8rem）と分かれて同じ役割が 3 通りの大きさで
   出ていたため、ここへ寄せて 2 つの定義を削除した。
   名前が似ている .freesheet-hint* は「入力欄の補足文」ではなく <details> の開閉する
   ヘルプパネル一式なので、統合しない（取り違えないこと）。
   色は P-109 でコントラスト基準を満たすことを確認済みの --text-muted を使う。 */
.form-field-hint {
    margin: 4px 0 0;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    line-height: 1.5;
}

/* 補足文が続けて並ぶときだけ、別の文だと読み分けられる間隔を空ける。
   （.ff-hint は margin を持たず <p> の既定余白に任せていたため、寄せ先でも
   連続する 2 文が地続きにならないようにするための 1 行。） */
.form-field-hint + .form-field-hint {
    margin-top: 10px;
}

/* 直前が flex コンテナ（.axis-bulk-row）のときだけ間隔を戻す（P-133）。
   上の 4px は「直前が入力欄1つ」を想定した値だが、そこでの実際の見た目の隙間は
   4px ではなく 12px になる——inline-block の <input> が行ボックスに乗るぶんの
   ディセンダが下に付くため。.axis-bulk-row は flex コンテナでその余りが出ないので、
   同じ 4px を書くとこの 1 箇所だけ他の補足文より 8px 詰まって行に貼り付く
   （実測: 直前 .form-input = 12px ／ 直前 .axis-bulk-row = 4px）。しかもここの補足文は
   単一の入力欄ではなく行全体（セレクト4つ＋「一括適用」ボタン）に掛かる。 */
.axis-bulk-row + .form-field-hint {
    margin-top: 10px;
}

/* 入力内容の誤りをその場で伝える一行。role="alert" と併せて使う。 */
.form-field-error {
    margin: 12px 0 0;
    padding: 8px 10px;
    border: 1px solid var(--red-200);
    border-radius: var(--radius-sm);
    background: var(--red-50);
    color: var(--red-700);
    font-size: var(--fs-sm); /* P-216: 同じ欄の補足文 .form-field-hint と同じ段 */
    line-height: 1.5;
}

/* 表示・非表示は「中身が空かどうか」で決める（Q-181。公開ページの .error-msg-box:empty と同じ作法）。
   欄は常に DOM にあって空のまま置き、文言を入れるだけで出す。.hidden（display: none）で出し入れすると、
   role="alert" を付けていてもアクセシビリティツリーに載っておらず、読み上げが走らないことがある。
   空のときは余白・枠を落として高さ0にする（ここで display: none を書くと元の木阿弥になる）。 */
.form-field-error:empty {
    margin: 0;
    padding: 0;
    border: 0;
}

/* 誤りのある入力欄そのものにも赤い枠を出し、どの欄が対象かを一目で分かるようにする。 */
.form-input.is-invalid { border-color: var(--red-500); }
.form-input.is-invalid:focus { border-color: var(--red-500); box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.18); }

/* P-121: 取り消せない操作の確認ダイアログ（utils.js の showConfirm()）。OS 標準の confirm() は
   見出しも配色も既定ボタンも変えられないため、「ビューを1つ消す」と「テナント全体のデータが
   消える」が同じ見た目・同じ「OK」で出ていた。ここでは危険度を①見出しのアイコン色、
   ②実行側ボタンの配色、③「何をするのか」を書いたボタン文言の3つで示す。
   幅は入力欄を持たない読み物なので、ディメンション追加（400px）より1段広い 460px。 */
.modal-content-confirm { max-width: 460px; height: auto; }
.modal-body-confirm { padding: 20px 24px 24px; flex-direction: column; }

/* 見出しのアイコン。tone に応じて JS が -danger／-warning を付け替える
   （色は .btn-danger の #dc2626、.loading-confirm-icon の #f59e0b と同じ値に揃える）。 */
.confirm-modal-icon-danger { color: #dc2626; }
.confirm-modal-icon-warning { color: #f59e0b; }

/* 主文。まず1〜2文で「何が起きるのか」を読ませるので、補足より1段大きく太い。 */
.confirm-modal-message {
    margin: 0;
    color: var(--text);
    font-size: var(--fs-xl);
    font-weight: 600;
    line-height: 1.7;
}

/* 補足段落。confirm() では \n\n で区切るしかなかったものを、段落として組む。 */
.confirm-modal-details {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 14px;
}

.confirm-modal-detail {
    margin: 0;
    color: var(--text);
    font-size: var(--fs-md);
    line-height: 1.7;
}

/* 「この件数は概算です」のような、読まなくても操作の判断は付く注記。主文・補足より弱くする。 */
.confirm-modal-note {
    margin: 14px 0 0;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    line-height: 1.6;
}

/* Q-163: 1行のテキストを入力させるダイアログ（utils.js の showPrompt()）。OS 標準の prompt() は
   上限文字数をその場で示せず、誤って OK すると入力した値が戻らない。確認ダイアログと同じ作りに
   揃えたうえで、入力欄・補足・エラーを縦に積む。幅は1行の入力欄なので確認ダイアログより1段狭い。 */
.modal-content-prompt { max-width: 420px; height: auto; }
.modal-body-prompt { padding: 20px 24px 24px; flex-direction: column; gap: 8px; }

/* 上限文字数などの補足。入力の判断材料だが、読まなくても操作できるので弱くする。 */
.prompt-modal-hint {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    line-height: 1.6;
}

/* 検証に引っかかったときの理由は、入力欄の直下に出す（トーストだと、直す対象の欄から目が離れる）。
   見た目は専用クラスを持たず、同じ役割の既存部品 .form-field-error をそのまま使う（Q-172）。
   .modal-body-prompt は gap: 8px で子要素を離すので、.form-field-error 自身の上余白だけ打ち消す。 */
.modal-body-prompt .form-field-error {
    margin-top: 0;
}

/* 空の欄（高さ0）は描画されたままなので、gap: 8px が直前の子との間にもう1つ入る。
   その分だけ引き戻し、空のときのダイアログの高さを .hidden で隠していた頃と同じにする（Q-181）。 */
.modal-body-prompt .form-field-error:empty {
    margin-top: -8px;
}

/* P-106: 「視差効果を減らす」を有効にしている利用者向けの打ち消し。
   これまで打ち消していたのは .toast / .unsaved-badge / .reveal の3ブロックだけで、
   無限に回り続けるスピナー2種をはじめ大半のアニメーションが対象外だった。

   **このブロックはファイル末尾に置くこと。** @media は詳細度を一切上げないため、
   打ち消したい元の宣言（例: .ai-summary-box.open・.hero-title）より前に書くと
   同詳細度の後勝ちで負けて無効になる。上の2596行付近のブロックが .toast /
   .unsaved-badge だけで済んでいるのは、たまたま両者の定義がその手前にあるため。 */
@media (prefers-reduced-motion: reduce) {
    /* 無限に回り続けるスピナー2種は「処理中である」ことを伝える唯一の手掛かりなので、
       animation: none で止めない（止まった輪は、処理中なのか固まったのか区別が付かない）。
       0.7s／0.8s を 2.4s まで遅くし、視界の端で目を引く速い回転だけを取り除く。
       .spinner の ease-in-out は遅くすると「止まっては動く」ように見えるため linear に揃える。 */
    .loading-spinner { animation-duration: 2.4s; }
    .spinner { animation-duration: 2.4s; animation-timing-function: linear; }

    /* 登場時に位置・大きさ・不透明度が動くだけの演出は、消しても失われる情報が無いので止める
       （モーダルの背景と本体、集計ビューの案内バナー、AIサマリ／グラフの右サイドドロワー）。 */
    .modal { animation: none; }
    .modal-content { animation: none; }
    .info-banner { animation: none; }
    .ai-summary-box.open,
    .chart-box.open { animation: none; }

    /* P-185: ホバーでボタンが 1px 浮き上がる演出も止める。押せることは影と背景色の変化で
       伝わるので、位置の移動だけを取り除く（影・背景色の補間は残す）。元の :hover 規則と
       同じセレクタで書き、詳細度を揃えたうえで後勝ちにする。 */
    .btn-primary:hover:not(:disabled),
    .btn-secondary:hover:not(:disabled) { transform: none; }
}

/* P-187: タッチ端末（主たる入力にホバーが無い）では、ホバーの浮き上がりを止める。
   タッチのブラウザはタップした要素に :hover を「次に別の場所をタップするまで」残すため、
   止めないとタップしたボタン・カードが浮いたまま固まり、選択中・押下中と見分けが付かない。
   止めるのは位置の移動だけで、影・枠色・背景色の変化は残す（色まで止めるとタッチ端末で
   「押せる」手掛かりが減る）。押した瞬間の手応えは P-186 の :active が受け持つ。
   すぐ上の prefers-reduced-motion のブロックと同じ理由で、元の :hover 規則と同じセレクタで
   書き、ファイル末尾に置く。浮き上がりの規則を足したら、ここにも同じセレクタを足すこと。 */
@media (hover: none) {
    .btn-primary:hover:not(:disabled),
    .btn-secondary:hover:not(:disabled) { transform: none; }
}

/* =========================================================================
   P-167: ハイコントラスト（Windows のコントラストテーマ ＝ forced-colors）での
   フォーカス表示。

   入力欄のフォーカスリングは `outline: none` ＋ `box-shadow: 0 0 0 3px …`
   で描いているが、**forced-colors ではブラウザが box-shadow を一切描かない**
   （実測: 通常 `rgba(79,70,229,0.15) 0 0 0 3px` → forced-colors では `none`）。
   残るのは 1px の枠線の色だけで、3px のリングに比べて手掛かりが弱い。
   ボタン類は共通の `:focus-visible`（outline）を持つため forced-colors でも
   そのまま残り、失格しているのは box-shadow だけに頼る下の 4 系統である。

   `Highlight` はシステムのフォーカス色で、利用者が選んだテーマに追従する
   （forced-colors では作者の指定した色はどのみち無視されるため、システム色を
   名前で指すのが唯一効く書き方）。

   **このブロックはファイル末尾に置くこと。** @media は詳細度を上げないので、
   打ち消したい `.form-input:focus`（1109 行）などより後ろに無いと同詳細度の
   後勝ちで負ける（すぐ上の prefers-reduced-motion のブロックと同じ理由）。
   ========================================================================= */
@media (forced-colors: active) {
    .form-input:focus,
    .form-input.is-invalid:focus,
    .config-group select:focus,
    .bec-input:focus,
    .bec-select:focus {
        outline: 2px solid Highlight;
        outline-offset: 1px;
    }
}
