/* Home Energy Viewer
   1920x1200 の横長タッチパネル向け。タップ対象は最低48px、ホバー前提の操作は作らない。
   系列色は dataviz のカテゴリカル配色を検証済みの並びで使用。
   数値やラベルはテキスト色を着せ、系列色は隣のマークだけが持つ。 */

:root {
    color-scheme: light;

    --surface-0: #f2f1ee;
    --surface-1: #fcfcfb;
    --surface-2: #f7f6f3;
    --border: #dedcd6;
    --border-strong: #c6c3bb;

    --text-primary: #0b0b0b;
    --text-secondary: #52514e;
    --text-muted: #7a7873;

    /*
     * 系列の色。**この値は 2026-08-21 にユーザーが「今の色でいい」と決めたもの。**
     * 見た目の慣れを優先している。良かれと思って差し替えないこと。
     *
     * 検証スクリプトの結果は把握したうえで据え置いている。
     *   node scripts/validate_palette.js "<hex,...>" --mode light --surface "#fcfcfb" --pairs all
     *
     *   下限を割っている組（通常視の下限は15）
     *     残量 #e34948 × 買電 #eb6834    ΔE  7.1   CVD 5.6
     *     買電 #eb6834 × 太陽光 #eda100  ΔE 13.7
     *     暗モード 売電 #9085e9 × 家庭内消費 #3987e5   ΔE 9.8
     *
     * 折れ線・棒とも**端ラベルと凡例で系列を同定できる**ので、色だけに頼っていない。
     * 直すなら、色を足すのではなく買電と売電を1系列に畳む（電力推移ビューが既にその形）。
     * 詳細は docs/makinglog.md 2026-08-21 と docs/tasks.md I-9。
     */
    /*
     * システム概要図の絵の塗り。系列色ではなく「物の色」なので別に持つ。
     * 明るい家・灰色の屋根・濃紺のパネル。暗モードでは下の2か所で入れ替える。
     */
    --sc-struct:     #b3b0a8;   /* 電柱・電線・窓枠 */
    --sc-insulator:  #9e9b93;
    --sc-roof:       #d0cdc5;
    --sc-wall:       #f4f2ee;
    --sc-wall-2:     #e7e4dd;
    --sc-panel-a:    #46587a;   /* パネルの明るい側 */
    --sc-panel-b:    #2b394f;
    --sc-panel-edge: #1a2330;
    --sc-door:       #8d8981;
    --sc-win-off:    #cfccc4;

    --s-load: #2a78d6;      /* 家庭内消費 */
    /* 蓄電池制御（シャドー運転）の版。色は版に固定（検定 明: 通常24.0 / CVD9.2、暗: 通常20.9 / CVD9.4） */
    --x-ref:  #2a78d6;      /* current-1 いまの運用 */
    --x-prim: #eb6834;      /* hedged-1 本命 */
    --x-base: #1baf7a;      /* baseline-1 */
    --s-grid: #eb6834;      /* 買電 / 系統 */
    --s-battery: #1baf7a;   /* 蓄電池 / 充電 */
    --s-solar: #eda100;     /* 太陽光 */
    /* 売電。電力量グラフでは家庭内消費と同じ図に並ぶので、消費の青とは別にする。
       dataviz の検証スクリプトで明暗とも全項目PASS（magenta 案は買電との
       normal-vision ΔE が 12.9 で floor 15 を割り FAIL）。 */
    --s-sell: #4a3aa7;      /* 売電 */
    --s-discharge: #e34948; /* 放電 / 蓄電池残量 */
    /*
     * 電池端の「出た量」の棒（蓄電池タブ・電池の能力）だけに使う。
     *
     * AC側の放電と同じ #e34948 を当てたら、同じ絵の中の放電効率の線 #eb6834 と
     * ΔE00 13.3（下限15）・CVD 7.0（下限9）で下限割れした。線の色は動かせないので
     * 棒の側で解いている。検定値: 線4色と充電の緑に対して 通常34.1 / CVD31.7。
     */
    --s-battery-out: #14503a;
    /*
     * 推定容量の線（蓄電池タブ・電池の能力）。左軸(kWh)に載る唯一の線。
     * 既存6系列と背景に対して検定済み: 通常32.6 / CVD21.6。
     */
    --s-capacity: #e64da8;
    /*
     * コンセントの電圧の線（電力推移）。--s-capacity と同じ色にしてある。
     * 同じ絵に並ぶことが無く、どちらも「他の系列と別の軸で読む値」だから。
     * 電力推移の4系列に対して検定済み: 通常24.2 / CVD9.4。
     */
    --s-volt: #e64da8;

    /* 電気料金の内訳。動かせない固定費の上に、時間帯を安い順に積む。
       dataviz の検証スクリプトで明暗とも検査済み（CVD分離・彩度・明度帯）。 */
    --c-fixed:    #009E73;  /* 基本料金・再エネ賦課金 */
    --c-night:    #0072B2;  /* 夜間 */
    --c-shoulder: #CC79A7;  /* 朝晩 */
    --c-day:      #D55E00;  /* 昼間 */
    --c-fuel:     #8f6fd0;  /* 燃料費調整（負の月はゼロ線の下） */
    --c-ideal:    #CC79A7;  /* 太陽光の理想（快晴時） */
    /*
     * 快晴日の平均出力の線（太陽光タブ）。劣化を読む線。
     * 太陽光の3系列と背景に対して検定済み: 通常44.5 / CVD32.8。
     */
    --c-clear:    #146b3e;

    --good: #0f7a4d;
    --warn: #a35c00;
    --critical: #b3261e;

    /* 数値枠。表示されない桁と小数点のぶんも確保する。
       電力=「99.99」+「kWh」、積算=「999.99」+「kWh」、残量=「100」+「%」 */
    --fig-w: 4.7ch;   --unit-w: 2.9ch;
    --t-fig-w: 5.7ch; --t-unit-w: 4.6ch;
    --soc-fig-w: 3ch; --soc-unit-w: 1.6ch;

    --rail-w: 108px;
    /* 縦画面で下端に貼るレールの高さ。本体の下余白と対で使う（片方だけ直さない）。 */
    --rail-h: 66px;
    --tap: 48px;
}

@media (prefers-color-scheme: dark) {
    :root:where(:not([data-theme="light"])) {
        color-scheme: dark;
        --surface-0: #111110;
        --surface-1: #1a1a19;
        --surface-2: #232322;
        --border: #34342f;
        --border-strong: #4a4a44;
        --text-primary: #ffffff;
        --text-secondary: #c3c2b7;
        --text-muted: #928f86;
        --sc-struct:     #43433d;
        --sc-insulator:  #5c5c53;
        --sc-roof:       #25252a;
        --sc-wall:       #2a2a29;
        --sc-wall-2:     #1e1e1d;
        --sc-panel-a:    #31415a;
        --sc-panel-b:    #161e2b;
        --sc-panel-edge: #0c121c;
        --sc-door:       #15151a;
        --sc-win-off:    #0f1219;
        --s-load: #3987e5;
        --x-ref:  #3987e5;
        --x-prim: #d95926;
        --x-base: #199e70;
        --s-grid: #d95926;
        --s-battery: #199e70;
        --s-solar: #c98500;
        --s-sell: #9085e9;
        --s-discharge: #e66767;
        --s-battery-out: #8fe3c4;   /* 暗は明度を反転させる。検定 通常21.0 / CVD21.6 */
        --s-capacity: #f070b8;      /* 検定 通常23.9 / CVD17.8 */
        --s-volt: #f070b8;      /* 検定 通常21.1 / CVD5.0（既存の系統×太陽光が下限） */

    --c-fixed:    #12a077;
    --c-night:    #3d93cf;
    --c-shoulder: #c4709e;
    --c-day:      #dd6510;
    --c-fuel:     #8f6fd0;
    --c-ideal:    #c4709e;
    --c-clear:    #5fe6ae;   /* 検定 通常45.5 / CVD23.6 */
        --good: #4cc38a;
        --warn: #e5a53a;
        --critical: #f2726b;
    }
}

:root[data-theme="dark"] {
    color-scheme: dark;
    --sc-struct:     #43433d;
    --sc-insulator:  #5c5c53;
    --sc-roof:       #25252a;
    --sc-wall:       #2a2a29;
    --sc-wall-2:     #1e1e1d;
    --sc-panel-a:    #31415a;
    --sc-panel-b:    #161e2b;
    --sc-panel-edge: #0c121c;
    --sc-door:       #15151a;
    --sc-win-off:    #0f1219;
    --surface-0: #111110;
    --surface-1: #1a1a19;
    --surface-2: #232322;
    --border: #34342f;
    --border-strong: #4a4a44;
    --text-primary: #ffffff;
    --text-secondary: #c3c2b7;
    --text-muted: #928f86;
    --s-load: #3987e5;
    --x-ref:  #3987e5;
    --x-prim: #d95926;
    --x-base: #199e70;
    --s-grid: #d95926;
    --s-battery: #199e70;
    --s-solar: #c98500;
    --s-sell: #9085e9;
    --s-discharge: #e66767;
    --s-battery-out: #8fe3c4;   /* 暗は明度を反転させる。検定 通常21.0 / CVD21.6 */
    --s-capacity: #f070b8;      /* 検定 通常23.9 / CVD17.8 */
    --s-volt: #f070b8;      /* 検定 通常21.1 / CVD5.0（既存の系統×太陽光が下限） */

    --c-fixed:    #12a077;
    --c-night:    #3d93cf;
    --c-shoulder: #c4709e;
    --c-day:      #dd6510;
    --c-fuel:     #8f6fd0;
    --c-ideal:    #c4709e;
    --c-clear:    #5fe6ae;   /* 検定 通常45.5 / CVD23.6 */
    --good: #4cc38a;
    --warn: #e5a53a;
    --critical: #f2726b;
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
    margin: 0;
    display: flex;
    background: var(--surface-0);
    color: var(--text-primary);
    font-family: system-ui, -apple-system, "Hiragino Kaku Gothic ProN",
                 "Noto Sans JP", Meiryo, sans-serif;
    font-size: 16px;
    line-height: 1.5;
    overflow: hidden;                 /* 画面固定。スクロールは詳細ビュー内だけ */
    -webkit-font-smoothing: antialiased;
    -webkit-tap-highlight-color: transparent;
}

/* ================= 左メニューレール ================= */

.rail {
    flex: none;
    width: var(--rail-w);
    background: var(--surface-1);
    border-right: 1px solid var(--border);
    display: flex; flex-direction: column; align-items: stretch;
    padding: .6rem .5rem 1rem;
    gap: .3rem;
}
.rail-brand {
    display: flex; justify-content: center; padding: .5rem 0 .9rem;
    color: var(--s-solar);
}
.rail-brand svg { width: 30px; height: 30px; fill: currentColor; }
.rail-spacer { flex: 1 1 auto; }

.rail-btn {
    font: inherit;
    min-height: 72px;                 /* タッチ用に大きく */
    display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: .25rem;
    background: transparent; color: var(--text-secondary);
    border: 1px solid transparent; border-radius: 12px;
    padding: .4rem .2rem; cursor: pointer;
    font-size: .8rem; font-weight: 600;
    transition: background .12s, color .12s;
}
.rail-btn svg {
    width: 26px; height: 26px;
    fill: none; stroke: currentColor; stroke-width: 1.8;
    stroke-linecap: round; stroke-linejoin: round;
}
.rail-btn:active { background: var(--surface-2); }
.rail-btn[aria-selected="true"] {
    background: var(--surface-2);
    border-color: var(--border);
    color: var(--text-primary);
}

/* ================= ステージ ================= */

.stage {
    flex: 1 1 auto; min-width: 0;
    display: flex; flex-direction: column;
    padding: .7rem .9rem .9rem;
    gap: .7rem;
}

.bar {
    flex: none;
    display: flex; align-items: center; gap: .55rem;
    min-height: 40px;
}
/* 見出しは折り返させない。幅が足りないと「シ / ス / テ / ム」と縦に1文字ずつ並ぶ。 */
.bar h1 { margin: 0; font-size: 1.15rem; font-weight: 650; letter-spacing: .01em; white-space: nowrap; }
.bar .spacer { flex: 1 1 auto; }

.pill {
    display: inline-flex; align-items: center; gap: .4rem;
    font-size: .8rem; color: var(--text-secondary);
    background: var(--surface-1); border: 1px solid var(--border);
    border-radius: 999px; padding: .25rem .75rem; white-space: nowrap;
}
.pill.clock { font-variant-numeric: tabular-nums; }
.dot { width: .6rem; height: .6rem; border-radius: 50%; background: var(--text-muted); flex: none; }
.dot.ok { background: var(--good); }
.dot.bad { background: var(--critical); }

.alert-pill {
    display: inline-flex; align-items: center; gap: .45rem;
    font-size: .82rem; color: var(--text-primary);
    background: var(--surface-1);
    border: 1px solid var(--border); border-left: 4px solid var(--warn);
    border-radius: 8px; padding: .25rem .7rem; max-width: 46vw;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.alert-pill.error { border-left-color: var(--critical); }
.alert-pill .icon { color: var(--warn); font-weight: 700; flex: none; }
.alert-pill.error .icon { color: var(--critical); }

/* ================= ビュー ================= */

.view { flex: 1 1 auto; min-height: 0; display: flex; }
.view[hidden] { display: none; }

/* ---------- ホーム ---------- */

.glance {
    flex: 1 1 auto; min-height: 0;
    display: grid;
    gap: .7rem;
    /* 上段=蓄電池（残量＋充放電）、下段=電力3枚。
       4枚を3枚に減らすことで1枚あたりの幅が広がり、数値を大きく取れる。 */
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-rows: auto auto minmax(0, 1fr);
    grid-template-areas:
        "soc   soc   batt"
        "solar load  grid"
        "chart chart save";
}

.soc-panel {
    grid-area: soc; min-width: 0;
    background: var(--surface-1); border: 1px solid var(--border);
    border-radius: 14px; padding: .75rem 1.1rem .9rem;
    display: flex; flex-direction: column;
}
.soc-label { font-size: clamp(.82rem, .88vw, 1.05rem); color: var(--text-secondary); font-weight: 600; }

/* 数値は左に必要な分だけ、残り幅すべてをプログレスが取る */
.soc-main {
    flex: 1 1 auto; min-height: 0; min-width: 0;
    display: flex; align-items: center; gap: clamp(.6rem, 1.7vw, 1.6rem);
}
/* 3桁(100%)ぶんの幅を常に確保する。桁数で幅が変わるとバーの起点が動き、
   残量が増減しただけでバーの全長が伸び縮みして見えてしまう。 */
.soc-num {
    flex: none;
    display: inline-flex; align-items: baseline; justify-content: flex-end;
    font-size: clamp(2.6rem, 4.5vw, 5.4rem); font-weight: 680; line-height: 1;
    font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.soc-num .figure { width: var(--soc-fig-w); text-align: right; }
.soc-num .unit {
    width: var(--soc-unit-w); text-align: left;
    font-size: clamp(1rem, 1.5vw, 1.8rem); font-weight: 550; color: var(--text-muted); padding-left: .1rem;
}
.soc-gauge { flex: 1 1 auto; min-width: 0; }

.soc-track {
    position: relative; height: 56px;
    border-radius: 12px;
    background: var(--surface-2); border: 1px solid var(--border); overflow: hidden;
}
.soc-track > i {
    display: block; height: 100%;
    border-radius: 11px 4px 4px 11px;
    background: var(--soc-color, var(--s-battery));
    transition: width .5s ease, background-color .4s ease;
}
/* 残量3段階（dataviz のステータス配色・明暗共通）。
   明モードでは中位色が背景と 3:1 に届かないため、隣の数値と kWh を
   必ず見せることが成立条件（色だけで残量を示さない）。 */
.soc-track[data-level="low"]  { --soc-color: #d03b3b; }
.soc-track[data-level="mid"]  { --soc-color: #fab219; }
.soc-track[data-level="high"] { --soc-color: #0ca30c; }

/* 放電が止まる残量。ここから下は停電用に残るので「使える量」の下端。
   トラック内は線だけにする。文字を重ねるとバーの色に埋もれて読めない。 */
.soc-track > .reserve {
    position: absolute; top: 0; bottom: 0; width: 2px;
    background: var(--surface-1); box-shadow: 0 0 0 1px var(--text-primary);
    opacity: .75;
}

/* 3項目が横に並ばない幅では折り返す。1100px 付近で見切れていた。 */
.soc-sub {
    display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline;
    gap: .2rem 1rem; margin-top: .5rem; min-width: 0;
}
.soc-sub > * { min-width: 0; }
.soc-kwh {
    display: flex; align-items: baseline;
    font-size: clamp(.85rem, 1.05vw, 1.25rem); color: var(--text-secondary); font-variant-numeric: tabular-nums;
}
.soc-kwh .figure { width: var(--t-fig-w); text-align: right; }
.soc-kwh .unit { width: var(--t-unit-w); text-align: left; padding-left: .25rem; }
.soc-kwh .of { padding-left: .35rem; color: var(--text-muted); }
.soc-state { font-size: clamp(.9rem, 1.13vw, 1.35rem); color: var(--text-muted); }
.soc-reserve-note { font-size: clamp(.75rem, .92vw, 1.05rem); color: var(--text-muted); }

.metric {
    min-width: 0;
    background: var(--surface-1); border: 1px solid var(--border);
    border-radius: 14px; padding: .75rem 1.1rem .8rem;
    display: flex; flex-direction: column; justify-content: center;
    min-height: 168px;
}
/* 上段の蓄電池電力は残量パネルと並ぶため、そちらの高さに追従させる */
.metric[data-tone="battery"] { min-height: 0; }
.metric[data-tone="grid"]    { grid-area: grid; }
.metric[data-tone="solar"]   { grid-area: solar; }
.metric[data-tone="load"]    { grid-area: load; }
.metric[data-tone="battery"] { grid-area: batt; }

.metric-head {
    display: flex; align-items: center; gap: .45rem;
    font-size: .86rem; color: var(--text-secondary); font-weight: 600;
    margin-bottom: .2rem;
}
.metric-head b { color: var(--text-primary); font-weight: 700; }
.metric .swatch { width: .8rem; height: .8rem; border-radius: 4px; flex: none; }
/* 状態ラベルと数値をベースライン揃えで同じ行に置く */
.metric-body { display: flex; align-items: baseline; gap: clamp(.3rem, .62vw, .8rem); min-width: 0; }
.metric-state {
    flex: none; font-size: clamp(.95rem, 1.45vw, 1.75rem); font-weight: 600;
    color: var(--text-secondary); white-space: nowrap;
}
/* 数値は右揃えで幅固定、単位は左揃えで幅固定。
   表示されない桁と小数点のぶんも枠を取るので、値が変わっても
   数値の右端と単位の位置が動かない。tabular-nums で桁幅も揃う。 */
.metric-value {
    display: inline-flex; align-items: baseline;
    font-size: clamp(2.4rem, 3.95vw, 5rem); font-weight: 660; line-height: 1.05;
    font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.metric-value .figure { width: var(--fig-w); text-align: right; }
.metric-value .unit {
    width: var(--unit-w); text-align: left;
    font-size: clamp(.95rem, 1.4vw, 1.7rem); font-weight: 550; color: var(--text-muted);
    padding-left: .2rem;
}
.metric-head { font-size: clamp(.82rem, .88vw, 1.05rem); }

/*
 * 縦が足りない画面。
 *
 * 要件は 1920x1200 で、そこでは何も変わらない。ノートPCやVPN越しの窓で
 * 開いたときに下が切れて節約効果カードが見えなくなるのを防ぐ。
 * **数値の大きさは vw で決めていた**ので、横が広く縦が狭い窓では効かない。
 */
@media (max-height: 900px) {
    .glance { gap: .5rem; }
    .metric { min-height: 120px; padding: .5rem .8rem .55rem; }
    .soc-panel { padding: .5rem .9rem .6rem; }
    .soc-num     { font-size: clamp(2rem, 3.4vw, 3.6rem); }
    .metric-value { font-size: clamp(1.8rem, 3vw, 3.4rem); }
    .metric-state { font-size: clamp(.8rem, 1.1vw, 1.2rem); }
    .glance-save  { padding: .45rem .7rem .5rem; }
}

.glance-chart {
    grid-area: chart; min-height: 0;
    background: var(--surface-1); border: 1px solid var(--border);
    border-radius: 14px; padding: .6rem .8rem .5rem;
    display: flex; flex-direction: column;
}
.glance-chart-head {
    display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
    font-size: .82rem; color: var(--text-secondary); font-weight: 600;
    margin-bottom: .3rem;
}
.glance-chart .chart { flex: 1 1 auto; min-height: 0; }

/* 当日の積算。主役の数値の右に小さく添える */
.metric-today {
    align-self: center;
    display: flex; flex-direction: column; gap: .05rem;
    font-size: clamp(.72rem, .88vw, 1.05rem); color: var(--text-muted);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.metric-today > span { display: flex; align-items: baseline; }
/* ラベル幅を固定して「充電 / ☀充電 / 放電」の数値開始位置を揃える */
.metric-today b {
    width: 3.5em; flex: none;
    font-weight: 600; color: var(--text-secondary);
}
.metric-today .figure { width: var(--t-fig-w); text-align: right; }
.metric-today .unit { width: var(--t-unit-w); text-align: left; padding-left: .25rem; }

.glance-save {
    grid-area: save; min-height: 0; min-width: 0;
    background: var(--surface-1); border: 1px solid var(--border);
    border-radius: 14px; padding: .6rem .85rem .7rem;
    display: flex; flex-direction: column; gap: .1rem;
}
/*
 * 離れて立って読む画面なのに、値が17px・ラベル13pxで、下に約500px余っていた。
 * 文言を足すのではなく、既にある値を大きくする。
 */
.glance-save .kv .k { font-size: clamp(.8rem, .92vw, 1.1rem); }
.glance-save .kv .v { font-size: clamp(1.1rem, 1.5vw, 1.8rem); font-weight: 660; }
.glance-save .kv.lead .v { font-size: clamp(1.5rem, 2.1vw, 2.6rem); }
.glance-save .save-row { gap: .5rem; }

.glance-save .title {
    font-size: .88rem; font-weight: 650; color: var(--text-secondary);
    padding-bottom: .3rem;
}
.glance-save .sub {
    font-size: .82rem; font-weight: 650; color: var(--text-secondary);
    padding: .5rem 0 .15rem;
}
.glance-save .save-row { display: flex; gap: 1.2rem; }
.glance-save .save-row .kv { flex: 1 1 0; }
.glance-save .kv {
    display: flex; align-items: baseline; gap: .6rem;
    padding: .4rem 0; border-bottom: 1px solid var(--border);
}
/* 節約効果カードは全行に下線を引く。行の対応が縦に追いやすくなる。 */
.glance-save .k { font-size: .82rem; color: var(--text-secondary); flex: 1 1 auto; }
.glance-save .v { font-size: 1.05rem; font-weight: 620; font-variant-numeric: tabular-nums; }
/* 先頭の「今日の電気料金」はこのカードの主役なので一段大きくする */
.glance-save .kv.lead { padding-top: .1rem; }
.glance-save .kv.lead .k { font-size: .95rem; color: var(--text-primary); font-weight: 650; }
.glance-save .kv.lead .v { font-size: 1.5rem; font-weight: 680; }

.glance-mode {
    grid-area: mode; min-width: 0; min-height: 0;
    background: var(--surface-1); border: 1px solid var(--border);
    border-radius: 14px; padding: .6rem .85rem .7rem;
    display: flex; flex-direction: column; gap: .1rem;
    overflow-y: auto;
}
.glance-mode .title {
    font-size: .82rem; font-weight: 650; color: var(--text-secondary);
    padding-bottom: .35rem;
}
.glance-mode .title {
    font-size: .88rem; font-weight: 650; color: var(--text-secondary);
    padding-bottom: .3rem;
}
.glance-mode .kv {
    display: flex; align-items: baseline; gap: .6rem;
    padding: .45rem 0; border-bottom: 1px solid var(--border);
}
.glance-mode .kv:last-child { border-bottom: 0; }
.glance-mode .k { font-size: .82rem; color: var(--text-secondary); flex: 1 1 auto; }
.glance-mode .v { font-size: .95rem; font-weight: 620; font-variant-numeric: tabular-nums; }

/* ---------- 詳細パネル ---------- */

.panel {
    flex: 1 1 auto; min-height: 0;
    background: var(--surface-1); border: 1px solid var(--border);
    border-radius: 14px; padding: .8rem 1rem 1rem;
    display: flex; flex-direction: column;
}
.panel.scroll { overflow-y: auto; -webkit-overflow-scrolling: touch; }
.panel h2 { margin: .4rem 0 .1rem; font-size: 1rem; font-weight: 650; }
.panel h2:first-child { margin-top: 0; }
.panel-head {
    display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
    margin-bottom: .55rem;
}
.panel-head .spacer { flex: 1 1 auto; }
/* 注記は縮んで折り返す。伸ばしたままだと操作ボタンが次の行へ落ちる。 */
.panel-head .hint { flex: 1 1 10rem; min-width: 0; margin: 0; }
.hint { margin: 0 0 .5rem; color: var(--text-muted); font-size: .84rem; }
.hint b { color: var(--text-secondary); }
.hint code {
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 4px; padding: .05rem .35rem;
}

.kv-grid {
    display: grid; gap: .45rem; margin: .5rem 0 1rem;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.kv-grid .row {
    display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap;
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 10px; padding: .55rem .8rem; min-height: var(--tap);
}
.kv-grid .k { font-size: .84rem; color: var(--text-secondary); flex: none; white-space: nowrap; }
.kv-grid .v {
    flex: 1 1 auto; min-width: 0; text-align: right;
    font-size: 1rem; font-weight: 620; font-variant-numeric: tabular-nums;
}
/* 値がいつのものかを添える。数字だけだと何と比べた値か分からない項目がある。
   細い欄に入れるので、値と同じ行に並べず必ず下へ回す。 */
.kv-grid .note {
    flex: 1 0 100%; text-align: right;
    font-size: .76rem; color: var(--text-muted);
}

/* ---------- タブ・ボタン（タッチ対応） ---------- */

.tabs { display: inline-flex; gap: .3rem; }
.tabs button, button.ghost {
    font: inherit; font-size: .88rem;
    min-height: var(--tap); padding: 0 1rem;
    background: var(--surface-2); color: var(--text-secondary);
    border: 1px solid var(--border); border-radius: 10px;
    cursor: pointer; white-space: nowrap;
}
.tabs button:active, button.ghost:active { background: var(--border); }
.tabs button[aria-selected="true"] {
    background: var(--s-load); border-color: var(--s-load);
    color: #fff; font-weight: 650;
}

/* ---------- 凡例 ---------- */

.legend { display: flex; flex-wrap: wrap; gap: .3rem .95rem; margin: 0 0 .35rem; }
.legend .item {
    display: inline-flex; align-items: center; gap: .35rem;
    font-size: .84rem; color: var(--text-secondary);
}
.legend .swatch { width: .8rem; height: .8rem; border-radius: 4px; flex: none; }
.legend .swatch.line { height: .22rem; border-radius: 2px; width: 1rem; }
/* 系列の表示切替。タッチで押せるよう当たり判定を広く取る */
.glance-chart-head .title { font-weight: 650; flex: none; }
.glance-chart-head .tabs button { min-height: 34px; padding: 0 .7rem; font-size: .82rem; }
.glance-chart-head .legend { flex: 1 1 auto; }

.legend .item.pick {
    cursor: pointer; user-select: none;
    min-height: 34px; padding: 0 .6rem 0 .4rem;
    border: 1px solid var(--border); border-radius: 999px;
    background: var(--surface-1);
}
.legend .item.pick input {
    width: 1.15rem; height: 1.15rem; margin: 0 .1rem 0 0;
    accent-color: var(--s-load); flex: none;
}
.legend .item.pick:has(input:not(:checked)) { opacity: .5; }

/* ---------- チャート ---------- */

.chart { position: relative; width: 100%; }
/* はみ出したときに下の要素へ描き込ませない。重なると数字が読めなくなる。 */
.chart.grow { flex: 1 1 auto; min-height: 0; overflow: hidden; }
.chart svg { display: block; width: 100%; height: auto; overflow: visible; touch-action: pan-y; }

.chart .grid-line { stroke: var(--border); stroke-width: 1; }
.chart .zero-line { stroke: var(--border-strong); stroke-width: 1; }
.chart .axis-text { fill: var(--text-muted); font-size: 12px; }
.chart .series-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
/* 10分値。10秒値と粒度が36倍違うので、同じ線で描かない。
   細く破線にして「間が埋まっていない」ことを線そのもので示す。 */
.chart .series-line.coarse { stroke-width: 1.5; stroke-dasharray: 6 3; opacity: .85; }
.chart .end-label { font-size: 12px; font-weight: 600; }
.chart .crosshair { stroke: var(--border-strong); stroke-width: 1.5; stroke-dasharray: 3 3; }
.chart .hit { fill: transparent; }

.tooltip {
    position: absolute; z-index: 5; pointer-events: none;
    background: var(--surface-1); color: var(--text-primary);
    border: 1px solid var(--border-strong); border-radius: 10px;
    padding: .5rem .7rem; font-size: .86rem; line-height: 1.5;
    box-shadow: 0 6px 18px rgb(0 0 0 / .18);
    white-space: nowrap; opacity: 0; transition: opacity .12s;
}
.tooltip.on { opacity: 1; }
.tooltip .t-title { color: var(--text-secondary); font-size: .8rem; margin-bottom: .25rem; }
.tooltip .t-row { display: flex; align-items: center; gap: .45rem; }
.tooltip .t-row .sw { width: .65rem; height: .65rem; border-radius: 3px; flex: none; }
.tooltip .t-row .n { color: var(--text-secondary); }
.tooltip .t-row .v {
    margin-left: auto; padding-left: .9rem;
    font-variant-numeric: tabular-nums; font-weight: 650;
}

/* ---------- テーブル表示（色だけに頼らない代替表現） ---------- */

.table-wrap { overflow: auto; height: 100%; -webkit-overflow-scrolling: touch; }
table.data {
    border-collapse: collapse; width: 100%; font-size: .88rem;
    font-variant-numeric: tabular-nums;
}
table.data th, table.data td {
    padding: .45rem .8rem; text-align: right; white-space: nowrap;
    border-bottom: 1px solid var(--border);
}
table.data th:first-child, table.data td:first-child { text-align: left; }
table.data thead th {
    color: var(--text-secondary); font-weight: 650;
    position: sticky; top: 0; background: var(--surface-1);
}
table.data .sw { display: inline-block; width: .65rem; height: .65rem; border-radius: 3px; margin-right: .4rem; }

.skeleton { color: var(--text-muted); font-size: .9rem; padding: 2rem 0; text-align: center; }

/* 往復効率は劣化の推移を読む列なので、他より強く見せる */
.data th:last-child, .data td:last-child { font-weight: 680; color: var(--text-primary); }

/* ---------- 期間指定（日時） ---------- */

.range-pick {
    display: inline-flex; align-items: center; gap: .35rem; flex-wrap: wrap;
}
.range-pick input,
.range-pick select {
    font: inherit; font-size: .82rem;
    min-height: var(--tap); padding: 0 .5rem;
    background: var(--surface-2); color: var(--text-primary);
    border: 1px solid var(--border); border-radius: 10px;
    font-variant-numeric: tabular-nums;
}
.range-pick select { padding-right: .3rem; }
.range-pick .dash { color: var(--text-muted); }
.range-pick button { font-size: .82rem; padding: 0 .8rem; }
.range-pick.on input,
.range-pick.on select { border-color: var(--s-load); }

/* ---------- システム概要図 ---------- */

.flow-grid {
    flex: 1 1 auto; min-height: 0; min-width: 0;
    display: grid; gap: .7rem;
    grid-template-columns: minmax(0, 1fr) minmax(230px, 20rem);
}
.flow-grid .panel { margin: 0; }
.flow-side { overflow-y: auto; }
.flow-side h2 { margin: .2rem 0 .4rem; font-size: 1rem; }
.flow-side h2:first-child { margin-top: 0; }
.flow-side .kv-grid { grid-template-columns: minmax(0, 1fr); }
.flow-canvas { flex: 1 1 auto; min-height: 0; display: flex; }
.flow-canvas svg { width: 100%; height: 100%; }

/*
 * システム概要図 — 家の絵。
 *
 * 塗りは `--sc-*` で持ち、明暗で入れ替える。系列色（--s-solar 等）はそのまま使う。
 * **量を線の太さで表さない。** 線は一定で、上を流れる粒の密度と速さが量を語る。
 */
.flow-canvas .ground     { stroke: var(--border-strong); stroke-width: 2; stroke-linecap: round; }
.flow-canvas .struct     { fill: var(--sc-struct); }
.flow-canvas .insulator  { fill: var(--sc-insulator); }
.flow-canvas .roof       { fill: var(--sc-roof); stroke: var(--border-strong); stroke-width: 2; stroke-linejoin: round; }
.flow-canvas .pv         { fill: url(#flowPanel); stroke: var(--sc-panel-edge); stroke-width: 1.2;
                           filter: drop-shadow(0 0 6px rgba(201, 133, 0, var(--lit, 0))); }
.flow-canvas .wall       { fill: url(#flowWall); stroke: var(--border-strong); stroke-width: 2; }
.flow-canvas .win        { fill: color-mix(in srgb, #ffd591 calc(var(--lit, .2) * 100%), var(--sc-win-off));
                           stroke: var(--sc-struct); stroke-width: 2; }
.flow-canvas .door       { fill: var(--sc-door); stroke: var(--border-strong); stroke-width: 1.2; }
.flow-canvas .knob       { fill: var(--sc-struct); }
.flow-canvas .batt       { fill: var(--surface-2); stroke: var(--border-strong); stroke-width: 2; }
.flow-canvas .batt-fill  { fill: var(--s-battery); opacity: .5; }
/* 放電を止める残量。ここから下は停電のために残る */
.flow-canvas .batt-floor { stroke: var(--s-discharge); stroke-width: 1.6; stroke-dasharray: 4 4; opacity: .65; }
.flow-canvas .batt-soc   { fill: var(--text-primary); font-size: 24px; font-weight: 700;
                           font-variant-numeric: tabular-nums; }

/* 太陽の光条。**電線と同じ「流れる粒」にしない。** 位相をずらしたゆっくりの明滅だけ。 */
.flow-canvas .ray        { stroke: var(--s-solar); stroke-width: 3; stroke-linecap: round; }
.flow-canvas .beam       { stroke: var(--s-solar); stroke-linecap: round; fill: none;
                           animation: sun-shimmer var(--dur, 3s) ease-in-out var(--delay, 0s) infinite; }
@keyframes sun-shimmer { 0%, 100% { opacity: .28 } 50% { opacity: 1 } }

/* 電線。粒と粒の間で線が死んで見えないよう、通電時は線にもうっすら色を載せる。 */
.flow-canvas .wire-base  { fill: none; stroke: var(--sc-struct); stroke-width: 5; stroke-linecap: round; }
.flow-canvas .wire-live  { fill: none; stroke-width: 5; stroke-linecap: round; }
/* 流れていく粒。明るい丸い頭＋薄い尾で、止まった画でも向きが読める。 */
.flow-canvas .spark      { filter: drop-shadow(0 0 3px currentColor); }

.flow-canvas .ro-name    { fill: var(--text-secondary); font-size: 20px; }
.flow-canvas .ro-val     { font-size: 42px; font-weight: 700; font-variant-numeric: tabular-nums; }
.flow-canvas .ro-sub     { fill: var(--text-muted); font-size: 17px; }
.flow-canvas .house-name { fill: var(--text-secondary); font-size: 19px; }
.flow-canvas .house-val  { fill: var(--text-primary); font-size: 54px; font-weight: 700;
                           font-variant-numeric: tabular-nums; }

/* ---------- 電気料金ビュー ---------- */

/* 期間の合計は棒の高さでは読めないので、グラフの下に必ず数字で置く。 */
.cost-sum {
    flex: 0 0 auto;   /* グラフに押し潰されない */
    display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .7rem;
}
.cost-sum .kv {
    flex: 1 1 0; min-width: 0;
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 10px; padding: .5rem .8rem;
    display: flex; align-items: baseline; justify-content: space-between; gap: .6rem;
}
.cost-sum .k { font-size: .85rem; color: var(--text-secondary); white-space: nowrap; }
.cost-sum .v { font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---------- 設定: 燃料費調整 ---------- */

.fuel-head { display: flex; align-items: center; gap: .7rem; margin-bottom: .7rem; }
.fuel-head .tariff-msg { text-align: left; }
.fuel-row {
    display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 10px; padding: .45rem .8rem; margin-bottom: .4rem; min-height: var(--tap);
}
.fuel-row.dirty { border-color: var(--warn); }
.fuel-row .ym { font-weight: 620; font-variant-numeric: tabular-nums; min-width: 6.5rem; }
.fuel-row input[type="month"] { min-width: 9rem; }
.fuel-row input[type="number"] { width: 7rem; text-align: right; }
.fuel-row .yen { font-size: .82rem; color: var(--text-muted); }
.fuel-row .spacer { flex: 1 1 auto; }
/* 手で直した行は、取得しても上書きされない。それが見て分かるようにする。 */
.fuel-row .src {
    font-size: .74rem; padding: .12rem .5rem; border-radius: 999px;
    border: 1px solid var(--border-strong); color: var(--text-secondary);
}
.fuel-row .src.manual { border-color: var(--warn); color: var(--warn); }

/* 年を1行にした表。空白のマスがそのまま「未登録の月」になる。 */
.fuel-grid { width: 100%; table-layout: fixed; margin-bottom: .6rem; }
.fuel-grid th { font-size: .8rem; color: var(--text-secondary); font-weight: 600; }
.fuel-grid tbody th { text-align: left; white-space: nowrap; width: 4.5rem; }
.fuel-grid td { padding: .12rem; }
.fuel-cell {
    width: 100%; min-height: 2.4rem; font: inherit; font-size: .9rem;
    font-variant-numeric: tabular-nums; text-align: right;
    background: transparent; color: var(--text-muted);
    border: 1px dashed var(--border); border-radius: 8px;
    padding: 0 .5rem; cursor: pointer;
}
.fuel-cell.has { background: var(--surface-2); color: var(--text-primary); border-style: solid; }
/* 手で直した月は、取得しても上書きされない。それを見て分かるようにする。 */
.fuel-cell.manual { border-color: var(--warn); }
/* 電力量データがあるのに単価が無い月。その月の料金は燃調を含まない。 */
.fuel-cell.missing { border-color: var(--critical); }
.fuel-cell:active { filter: brightness(.92); }
.hint.warn { color: var(--warn); }
#fuel-editor:empty { display: none; }
.fuel-row button.primary, .fuel-row button.ghost { min-height: 2.2rem; padding: 0 .9rem; font-size: .88rem; }

/* 過去の単価は1行に畳む。改定が何回あっても設定画面の高さが変わらない。 */
.tariff.folded { padding: 0; }
.tariff.folded > *:not(.tariff-fold) { display: none; }
.tariff-fold {
    display: flex; align-items: center; gap: .8rem;
    width: 100%; text-align: left; font: inherit;
    background: transparent; border: 0; color: var(--text-secondary);
    padding: .7rem 1rem; cursor: pointer; min-height: var(--tap);
}
.tariff-fold .txt { flex: 1 1 auto; min-width: 0; }
.tariff-fold b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.tariff-fold:active { filter: brightness(.92); }

/* ---------- 期間の送り戻し ---------- */

/* プリセットの隣。押すと「いま見ている期間の長さ」ぶん前後に動く。 */
.period-nav { display: inline-flex; gap: .3rem; }
.period-nav button {
    min-width: var(--tap); padding: 0 .7rem;
    font-size: .95rem; font-variant-numeric: normal;
}

/* ---------- 知らせ ----------
   指定と違うものを出したときに伝える。**黙って別の期間を出さない**ための入れ物。
   壁のタッチパネルに出るので、閉じる操作は大きく・迷わない位置に置く。 */
.modal {
    position: fixed; inset: 0; z-index: 50;
    display: flex; align-items: center; justify-content: center;
    background: rgb(0 0 0 / .45); padding: 2rem;
}
.modal[hidden] { display: none; }
.modal-box {
    background: var(--surface-1); color: var(--text-primary);
    border: 1px solid var(--border-strong); border-radius: 16px;
    padding: 1.6rem 1.8rem; max-width: 34rem;
    box-shadow: 0 18px 48px rgb(0 0 0 / .35);
}
.modal-box h2 { margin: 0 0 .6rem; font-size: 1.15rem; font-weight: 650; }
.modal-box p {
    margin: 0 0 1.4rem; color: var(--text-secondary);
    font-size: .95rem; line-height: 1.7;
}
.modal-box button { width: 100%; }

/* ---------- 設定の項目カード ----------
   項目の切れ目を枠で示す。長い表が続くと、どこからどこまでが1つの設定なのか
   見出しの字だけでは分からなくなる。 */
.set-card {
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 14px; padding: .8rem 1rem 1rem; margin-bottom: .8rem;
}
.set-card:last-child { margin-bottom: 0; }
.set-card > h2 { margin: 0 0 .2rem; font-size: 1rem; font-weight: 650; }
.set-card .kv-grid { margin-bottom: 0; }
.set-card .kv-grid .row { background: var(--surface-1); }
.set-card .tariff { background: var(--surface-1); }

/* 開閉する見出し。カード全幅をタップ対象にする（指で狙える的を小さくしない）。 */
.set-head {
    font: inherit; width: 100%; min-height: var(--tap);
    display: flex; align-items: center; gap: .8rem;
    background: none; border: 0; padding: 0; margin: 0;
    color: var(--text-primary); cursor: pointer; text-align: left;
}
.set-title { font-size: 1rem; font-weight: 650; flex: none; }
/* 畳んでいる間の要約。閉じていても中身の見当がつくようにする。 */
.set-sum {
    flex: 1 1 auto; min-width: 0;
    font-size: .84rem; color: var(--text-muted);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 開閉の記号。**押せること**と**いま開いているか**を、字ではなく形で示す。
   閉じているとき下向き（＝押すと下に出る）、開いているとき上向き（＝押すと畳む）。 */
.set-head::after,
.tariff-fold::after {
    content: ''; flex: none;
    width: .6rem; height: .6rem; margin-right: .25rem;
    border-right: 2px solid var(--text-secondary);
    border-bottom: 2px solid var(--text-secondary);
    transform: rotate(45deg) translate(-.15rem, -.15rem);
    transition: transform .15s;
}
.set-head[aria-expanded="true"]::after,
.tariff-fold[aria-expanded="true"]::after {
    transform: rotate(-135deg) translate(-.15rem, -.15rem);
}
.set-head[aria-expanded="true"] + .set-body { margin-top: .6rem; }
.set-head[aria-expanded="false"] + .set-body { display: none; }

/* ================= ログイン画面（外部からの入口） =================
   宅内からは表示されない。スマホで開かれる前提で、指1本で完結する幅にする。 */

.login-body {
    display: grid; place-items: center;
    min-height: 100dvh; padding: 1.5rem;
    background: var(--surface-0); color: var(--text-primary);
    overflow: auto;
}
.login {
    width: 100%; max-width: 22rem;
    display: flex; flex-direction: column; gap: .55rem;
    background: var(--surface-1);
    border: 1px solid var(--border); border-radius: 14px;
    padding: 1.6rem 1.4rem 1.4rem;
}
.login-brand { align-self: center; }
.login-brand svg { width: 34px; height: 34px; fill: var(--s-solar); }
.login h1 {
    margin: 0 0 .1rem; text-align: center;
    font-size: 1.15rem; font-weight: 650;
}
.login-note {
    margin: 0 0 .5rem; text-align: center;
    font-size: .82rem; line-height: 1.55; color: var(--text-muted);
}
.login-note code {
    font-size: .95em;
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 5px; padding: .05rem .3rem;
}
/* 失敗の理由は1種類しか出さない（どちらが違うかを教えないため）。
   だからこそ、出たことだけは確実に目に入る強さにする。 */
.login-error {
    margin: 0 0 .3rem;
    background: color-mix(in srgb, var(--critical) 12%, transparent);
    border: 1px solid var(--critical); border-radius: 8px;
    padding: .5rem .7rem;
    font-size: .85rem; line-height: 1.5; color: var(--critical);
}
.login form { display: flex; flex-direction: column; gap: .3rem; }
.login label {
    font-size: .84rem; font-weight: 600; color: var(--text-secondary);
    margin-top: .5rem;
}
.login input {
    font: inherit; min-height: var(--tap);
    background: var(--surface-2); color: var(--text-primary);
    border: 1px solid var(--border-strong); border-radius: 8px;
    padding: .3rem .7rem;
}
/* 6桁は数字だけなので等幅で揃える。打ち間違いに気づきやすい。 */
.login input#code {
    font-variant-numeric: tabular-nums;
    letter-spacing: .35em; text-align: center;
}
.login input:focus-visible {
    outline: 2px solid var(--s-load); outline-offset: 1px;
}
.login input:disabled { opacity: .5; }
.login button {
    font: inherit; font-weight: 650; min-height: var(--tap);
    margin-top: 1.1rem;
    background: var(--s-load); color: #fff;
    border: none; border-radius: 8px; cursor: pointer;
}
.login button:disabled { opacity: .5; cursor: default; }

/* ================= 画面が狭いとき（タブレット縦・PC小窓） =================

   幅ごとに変えるものが違う。切り替える幅もそれぞれ別に決める。
     900px … 「図＋右の一覧」の2列を縦に積む（左が潰れて図が読めなくなる幅）
     720px … 左レールを下端の横並びに移す（レールが幅の1/4を食う幅）
     560px … 概要図そのものを縦長の配置に切り替える（app.js drawFlow と対）
     480px … 接続状態のピルを畳む
*/

/*
 * 概要・蓄電池は「図＋右の一覧」の2列。右列に 230px の下限があるので、
 * 幅が足りないと左が潰れて図が読めなくなる。素直に上下へ積む。
 */

/* ---------- スマホ幅（外出先で見る） ----------
   左レールは 108px あり、390px の画面では幅の1/4を食う。グラフも表も
   残り幅に押し込まれて読めなくなるので、この幅から**レールを下端の横並び**に移す。
   親指が届く位置でもある。 */

/* ---------- 幅の狭いスマホ（iPhone mini 相当まで） ---------- */

/* ---------- 設定画面: 電気料金 ---------- */

.tariff {
    background: var(--surface-2); border: 1px solid var(--border);
    border-radius: 12px; padding: .8rem 1rem 1rem; margin-bottom: .8rem;
}
.tariff-head { display: flex; align-items: center; gap: .8rem; margin-bottom: .8rem; }
.tariff-head label { font-size: .9rem; font-weight: 600; color: var(--text-secondary); }
.tariff input {
    font: inherit; min-height: var(--tap);
    background: var(--surface-1); color: var(--text-primary);
    border: 1px solid var(--border-strong); border-radius: 8px;
    padding: .3rem .6rem; font-variant-numeric: tabular-nums;
}
.tariff input[type="number"] { width: 7.5rem; text-align: right; }
.tariff-grid {
    display: grid; gap: .7rem;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.tariff-cell { display: flex; flex-direction: column; gap: .15rem; }
.tariff-cell label { font-size: .88rem; font-weight: 600; }
.tariff-cell .note { font-size: .76rem; color: var(--text-muted); }
.tariff-input { display: flex; align-items: center; gap: .4rem; margin-top: .2rem; }
.tariff-input .yen { font-size: .82rem; color: var(--text-muted); }
.tariff-foot { display: flex; align-items: center; gap: .7rem; margin-top: .9rem; }
/* 押したボタンの隣に出す。左端に置くと 1920 幅では指から離れすぎて気づけない。 */
.tariff-msg { flex: 1 1 auto; text-align: right; font-size: .85rem; color: var(--text-muted); }
.tariff-msg.ok { color: var(--good); }
.tariff-msg.ng { color: var(--critical); }
.tariff-msg.warn { color: var(--warn); }
/* 未保存のカードは枠で示す。単価が何行もあると、どれを直しかけたか見失う。 */
/*
 * 未保存。1px の枠線だけでは 1920x1200 を離れて見るパネルで気づけない。
 * 左端に太い帯を出し、面にも色を薄く敷いて、視界の端でも分かるようにする。
 */
.tariff.dirty {
    border-color: var(--warn);
    box-shadow: inset 6px 0 0 var(--warn);
    background: color-mix(in srgb, var(--warn) 8%, var(--surface-2));
}

button.primary {
    font: inherit; font-weight: 650; min-height: var(--tap); padding: 0 1.4rem;
    background: var(--s-load); color: #fff;
    border: 1px solid var(--s-load); border-radius: 10px; cursor: pointer;
}
button.primary:active { filter: brightness(.92); }
/* 保存済み。押せないことより「保存されている」ことが伝わる見た目にする。 */
/* 条件が揃うまで押せないボタン。押せるのに何も起きない状態を作らないため。 */
button.ghost:disabled {
    color: var(--text-muted); border-color: var(--border); cursor: default;
    background: transparent;
}
button.primary:disabled {
    /* 「保存済み」は結果の報告そのものなので、薄くして読みにくくしない。
       押せないことは、押せるときの塗りつぶしとの差で伝える。 */
    background: transparent; color: var(--text-secondary);
    border-color: var(--border-strong); cursor: default;
}
#tariff-add { min-height: var(--tap); padding: 0 1.4rem; }

/* ---------- 蓄電池ビュー ---------- */

.battery-grid {
    flex: 1 1 auto; min-height: 0; min-width: 0;
    display: grid; gap: .7rem;
    grid-template-columns: minmax(0, 1fr) minmax(230px, 20rem);
}
.battery-grid .panel { margin: 0; }
/* 右側は2枚を入れ替えて使う。グリッドの列は2つのまま保つ。 */
.batt-side { display: grid; min-height: 0; min-width: 0; }
.batt-side > .panel { min-height: 0; }
/* .panel は display を持つので、hidden だけでは消えない。 */
.batt-side > .panel[hidden] { display: none; }
.run-panel { overflow-y: auto; }
.run-panel .kv-grid { grid-template-columns: minmax(0, 1fr); }
.run-panel h2 { margin: 0 0 .2rem; font-size: 1rem; }
/*
 * 見出し・数値・注記の3つ。数値を折り返させない。
 * 「往復効率」のように見出しが伸びると、横一列では数値の桁が折れる。
 * 見出しを上、数値と注記を下の行に置いて、数値の大きさを守る。
 */
.run-rate {
    display: grid; grid-template-columns: auto 1fr; align-items: baseline;
    gap: .1rem .6rem;
    margin-top: auto; padding-top: .9rem; border-top: 1px solid var(--border);
}
.run-rate .k {
    grid-column: 1 / -1;
    font-size: .9rem; color: var(--text-secondary);
}
.run-rate .v {
    font-size: 2rem; font-weight: 680; font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.run-rate .note { font-size: .78rem; color: var(--text-muted); }

/*
 * 横に並べられなくなるまでは左右のまま粘る。運転設定は5つの固定値なので、
 * 幅を詰めれば入る。縦に積むほうが、見たいグラフを潰すぶん損。
 */

/* ---------- 概要図を縦長に切り替える幅（app.js drawFlow の portrait と対） ---------- */

/* ================= 幅で変えるところ（ここから下は必ず最後に置く） =================

   **メディアクエリを基本定義より前に置かない。** 同じ詳細度なら後ろが勝つので、
   前に置くと上書きしたつもりが効かない（実際、`.battery-grid` の1列化が
   基本定義に負けて、スマホで左が55pxに潰れていた）。
   広い順に並べる。狭い幅ほど後ろ＝強い。
*/

@media (max-width: 1240px) {
    .battery-grid {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: minmax(0, 1fr) auto;
    }
    /* 縦に積むときは横一列の帯にする。5つの固定値のために
       グラフの高さを持っていかせない。 */
    .run-panel { overflow: visible; padding: .6rem .8rem .7rem; }
    .run-panel .kv-grid {
        grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
        margin: .35rem 0 0;
    }
    .run-panel .run-rate { margin-top: .5rem; padding-top: .5rem; }
    .run-panel .run-rate .v { font-size: 1.5rem; }
}

@media (max-width: 1100px) {
    body { overflow: auto; }
    .glance {
        grid-template-columns: repeat(2, 1fr);
        grid-template-rows: auto;
        grid-template-areas:
            "soc   batt"
            "solar load"
            "grid  grid"
            "chart chart"
            "save  save";
    }
    .soc-num { font-size: 3.2rem; }
    .metric-value { font-size: 2.2rem; }
    .glance-chart { min-height: 240px; }
}

@media (max-width: 900px) {
    .flow-grid, .battery-grid { grid-template-columns: minmax(0, 1fr); }
    /* 縦積みでは親に高さが無い。図の高さは drawFlow が縦横比で入れる。 */
    .flow-side, .run-panel { overflow-y: visible; }
}

@media (max-width: 720px) {
    /*
     * **縦画面では、スクロールする箱をページ1つだけにする。**
     *
     * 横画面用の作りは「画面は固定、パネルの中だけが縦に流れる」形で、
     * body・.stage・パネルがそれぞれ独立してスクロールする。これを縦画面へ
     * そのまま持ち込むと、指が触れた場所によってどれが動くかが変わり、
     * **タブごとに挙動が違って見える**（実測: html 605px / body 605px /
     * .stage 668px の3つが同時にスクロール可能だった）。
     * さらに入れ子のせいで下端レールの sticky が効かず、レールが流れていた。
     *
     * 高さの決め打ちを全部やめ、ページが伸びるに任せる。レールは fixed で
     * 画面下端に貼り、その分だけ本体に下余白を取る。
     */
    html, body { height: auto; }
    body { flex-direction: column; overflow: visible; }

    .stage, .view, .glance, .flow-grid, .battery-grid,
    .panel, .panel.scroll, .flow-side, .run-panel {
        overflow: visible;
        min-height: 0;
        max-height: none;
    }
    .stage, .view { flex: 0 0 auto; height: auto; }

    .rail {
        order: 2;
        position: fixed; bottom: 0; left: 0; right: 0; z-index: 20;
        width: auto; flex-direction: row; align-items: stretch;
        border-right: none; border-top: 1px solid var(--border);
        padding: .25rem .3rem calc(.25rem + env(safe-area-inset-bottom));
        gap: .15rem;
        /* 8つは横に収まらない。切り捨てずに横スクロールで全部へ届かせる。 */
        overflow-x: auto; scrollbar-width: none;
    }
    .rail::-webkit-scrollbar { display: none; }
    /* ブランドと余白は縦置き用。横並びでは場所を食うだけなので出さない。 */
    .rail-brand, .rail-spacer { display: none; }
    .rail-btn {
        flex: 0 0 auto;
        min-width: 62px; min-height: 54px;
        padding: .3rem .35rem; gap: .1rem;
        font-size: .68rem; border-radius: 10px;
    }
    .rail-btn svg { width: 22px; height: 22px; }
    /* リンクにしたログアウトも他のボタンと同じ形にする */
    a.rail-btn { text-decoration: none; }

    /* レールは fixed で浮いているので、その高さぶんを本体の下に空ける。
       空けないと、いちばん下の値がレールに隠れて読めない。 */
    .stage {
        order: 1;
        padding: .6rem .6rem calc(var(--rail-h) + .5rem + env(safe-area-inset-bottom));
    }

    /* 見出しは折り返させない。縦積みになって1文字ずつ並ぶのを防ぐ。
       状態のピルは幅が空いているときだけ出す（下の 480px で消える）。 */
    .bar { min-height: 34px; gap: .35rem; }
    .bar h1 { font-size: 1rem; white-space: nowrap; flex: none; }
    /* 余った幅は警告に回す。spacer で右へ寄せると、長い文が画面外へ出て
       末尾が読めないまま切れる。 */
    .bar .spacer { display: none; }
    .bar #notice-slot { flex: 1 1 auto; min-width: 0; display: flex; justify-content: flex-end; }
    .alert-pill { max-width: 100%; }

    /*
     * 縦1列では、行の高さを決め打ちにしない。
     * 既定の `auto auto minmax(0,1fr)` は横3列のときの割り付けで、
     * 1列に畳むと3行目が潰れてカードの中身がはみ出す。
     */
    .view { min-height: auto; }
    .glance {
        min-height: auto;
        grid-template-columns: 1fr;
        grid-template-rows: auto;
        grid-template-areas: "soc" "batt" "solar" "load" "grid" "chart" "save";
    }
    /* 高さは中身に任せる。168px の下限は横3列で高さを揃えるためのもので、
       縦に積むと空白になるだけ。 */
    .metric { min-height: 0; padding: .6rem .9rem .65rem; }
    .soc-panel { padding: .6rem .9rem .7rem; }
    .soc-track { height: 44px; }
    .glance-chart { min-height: 260px; }
    /* 伸縮するグラフは、幅から高さを決める規則（横幅×0.3）だと縦画面で
       150px の下限に張り付き、パネルの下半分が空白のまま残る。
       縦画面では画面の高さを基準にする。 */
    .chart.grow { min-height: 46vh; }

    /* 日付と時刻の2つ組を、1行ずつに割る。折り返し位置が中途半端だと、
       どの時刻がどちらの日付のものか分からなくなる。 */
    .range-pick { width: 100%; }
    .range-pick input[type="date"] { flex: 1 1 9rem; min-width: 0; }
    .range-pick .dash { flex: 0 0 100%; height: 0; visibility: hidden; margin: 0; }

    /* タブ列・期間切替は横に長い。折り返すと押し間違えるので、行のまま流す。 */
    .tabs {
        max-width: 100%;
        overflow-x: auto; scrollbar-width: none;
        padding-bottom: .15rem;
    }
    .tabs::-webkit-scrollbar { display: none; }
    .tabs button { flex: 0 0 auto; }

    .panel-head { flex-wrap: wrap; }
    .panel-head .spacer { display: none; }

    /* 表は縮めずに横スクロールさせる。列を落とすと読む値が消える。 */
    .panel table { min-width: 34rem; }
    .panel.scroll { overflow-x: auto; }

    /*
     * 電気料金の下の集計7項目。横1列（flex: 1 1 0）のままだと、見出しも値も
     * nowrap なので幅が縮まず、**画面の外へ52px溢れていた**（溢れると
     * 下端固定のレールまで画面外へ押し出される）。段に組んで幅を与える。
     */
    .cost-sum {
        display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .cost-sum .kv { min-width: 0; }
}

@media (max-width: 560px) {
    /* 図の中の文字は viewBox(620幅) の座標系にある。360px へ縮むぶん（約0.58倍）を
       見込んで、拾える大きさまで上げる。 */
    /*
     * 縦画面は 1000単位の版面が 370px まで縮む（0.37倍）。
     * 画面上で読める大きさにするには、版面上でその逆数ぶん大きく取る必要がある。
     * ro-val 80 → 実寸 約30px。
     */
    .flow-canvas .ro-name    { font-size: 36px; }
    .flow-canvas .ro-val     { font-size: 80px; }
    .flow-canvas .ro-sub     { font-size: 32px; }
    .flow-canvas .batt-soc   { font-size: 42px; }
}

@media (max-width: 480px) {
    /* 接続状態のピルは3つ並ぶと見出しを押し出す。異常はアラートで出るので、
       正常時に常時見えている必要はない。 */
    .bar .pill { display: none; }
    .stage { padding: .5rem .5rem calc(var(--rail-h) + .5rem + env(safe-area-inset-bottom)); }
    .rail-btn { min-width: 56px; font-size: .64rem; }
    /* 2列でも「燃料費調整 −11,709円」は入りきらない。1列にする。 */
    .cost-sum { grid-template-columns: minmax(0, 1fr); }
}


/* 3軸目（右軸の外側にもう一段）。主役は左右の軸なので、色を落として添える。 */
.chart .axis-text.alt { fill: var(--text-muted); opacity: .85; }


/* ---------- 蓄電池制御（シャドー運転 D-04・暫定）---------- */
/* 1画面に収めず、縦スクロールを許す（開発者向けで、一覧が日々伸びるため）。横には広げない */
.control-grid {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
    display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); gap: .8rem; align-content: start;
}
.control-col { display: flex; flex-direction: column; gap: .8rem; min-width: 0; }
.control-col .panel { flex: none; }
.control-days-panel .table-wrap { max-height: 46rem; height: auto; }
table.data.control-days td { white-space: nowrap; }
/* 原因と印は長いので折り返す。表を横に広げない */
table.data.control-days td:has(.note-cell) { white-space: normal; min-width: 8rem; }
.note-cell span { font-size: .8rem; color: var(--text-secondary); }
.note-cell span + span { color: var(--text-muted); }
table.data.control-days tbody tr { cursor: pointer; height: var(--tap); }
table.data.control-days tbody tr:active,
table.data.control-days tbody tr.on { background: var(--surface-2); }
.hint.warn { color: var(--warn); }
@media (max-width: 1100px) { .control-grid { grid-template-columns: minmax(0, 1fr); } }

/* 1つのセルに複数行（日付と天気・発電と消費・本命が送るはずだった設定）。設定はモニターに写せる形で3行 */
.stack { text-align: left; }
.stack span { display: block; line-height: 1.45; }
.stack b { font-weight: 600; color: var(--text-secondary); margin-right: .2rem; }
.date-cell span + span { font-size: .8rem; color: var(--text-muted); }
/* 振り返り（Claude の所見）。見出しと箇条書きだけ */
.review h3 { margin: .7rem 0 .25rem; font-size: .95rem; font-weight: 650; }
.review ul { margin: 0; padding-left: 1.2rem; }
.review li { margin: .2rem 0; line-height: 1.6; font-size: .9rem; }
.stack .note { font-size: .78rem; color: var(--warn); }

/* 運転設定を送る（D-05）。選択肢は単価の入力と同じ大きさにそろえる（タッチで押せる高さ） */
#card-control select, #card-control input[type="time"] {
    font: inherit; min-height: var(--tap);
    background: var(--surface-1); color: var(--text-primary);
    border: 1px solid var(--border-strong); border-radius: 8px; padding: .3rem .6rem;
}
#card-control .tariff-head label { display: flex; align-items: center; gap: .5rem; }
#card-control .tariff-head input[type="checkbox"] { width: 1.4rem; height: 1.4rem; }
#ctl-log td { white-space: normal; font-size: .82rem; }
#ctl-windows { display: flex; flex-direction: column; gap: .5rem; margin-bottom: .4rem; }
#card-control [hidden] { display: none !important; }
#card-control .ctl-slider { margin: .2rem 0 .4rem; user-select: none; }
#card-control .ctl-sel { display: flex; flex-wrap: wrap; align-items: center; gap: .6rem 1.2rem; padding: .6rem 0 .8rem;
                         border-bottom: 1px solid var(--border); margin-bottom: .6rem; }
#card-control .ctl-range { font-size: 1.15rem; font-weight: 700; min-width: 8.5em; font-variant-numeric: tabular-nums; }
#card-control .ctl-nudge, #card-control .ctl-opt, #card-control .ctl-split { display: inline-flex; align-items: center; gap: .4rem;
                         color: var(--text-secondary); }
#card-control .ctl-nudge button, #card-control .ctl-split button { min-height: var(--tap); }
#card-control .ctl-opt label { display: inline-flex; align-items: center; gap: .25rem; color: var(--text-primary); min-height: var(--tap); }
#card-control .ctl-opt input[type=radio] { width: 1.2rem; height: 1.2rem; }
#card-control #ctl-reserve, .dev-reserve #dev-reserve { width: 18rem; max-width: 40vw; height: var(--tap); accent-color: var(--s-load); }
/* HEMS の間、使われない本体の設定は薄く出す */
.kv-grid .row.off { opacity: .4; }
#card-control #ctl-reserve-dn, #card-control #ctl-reserve-up, .dev-reserve button.ghost { min-height: var(--tap); min-width: 3.2rem; }
/* 予定表全体の設定は1行に1項目。名前を左にそろえ、値は名前のすぐ右に大きく出す */
.ctl-set { display: flex; align-items: center; gap: .6rem; min-height: calc(var(--tap) + .4rem); }
.ctl-set .ctl-label { width: 15em; flex: none; }
.ctl-reserve-val { min-width: 4.2em; font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; }
#card-control .ctl-actions { border-top: 1px solid var(--border); margin-top: .6rem; padding-top: .8rem; }
.ctl-label { font-size: .9rem; font-weight: 600; color: var(--text-secondary); }
/* 本体の放電停止残量。運転設定の表の下に1行。保存は右端 */
.dev-reserve { margin-top: .6rem; }
.dev-reserve .tariff-msg { flex: 1 1 auto; }
#card-control .tabs { margin: .2rem 0 .6rem; }
#card-control .kv-grid .v.warn { color: var(--warn); }

/* 蓄電池制御の残量の推移: 日付の切り替え */
.day-nav { display: inline-flex; align-items: center; gap: .4rem; }
.day-nav button.ghost { min-height: var(--tap); }
.day-nav select { min-height: var(--tap); }
