/* 股票投資紀錄 — 共用樣式（三頁面共用） */

:root {
  /* 台股慣例：紅漲綠跌（維持不變） */
  --color-gain: #c0392b;        /* 白底對比 ≈ 5.6:1，AA 通過 */
  --color-loss: #1e8449;        /* 白底對比 ≈ 4.7:1，AA 通過 */
  --color-primary: #24303f;     /* 主文字：略深化，白底對比 ≈ 12:1 */
  --color-accent: #2980b9;
  --color-accent-hover: #216a99;

  /* 背景層次：頁面底色 → 卡片白，可辨識層次差異 */
  --color-bg: #eef1f6;
  --color-card: #ffffff;
  --color-border: #e2e7f0;
  --color-muted: #5c6b7a;       /* 取代 #7f8c8d（原值僅 3.9:1 不過 AA），白底對比 ≈ 5.9:1 */

  /* 統一圓角與陰影 */
  --radius: 12px;
  --radius-sm: 8px;

  /* 手機底部固定導覽的列高（issue #110／稽核 §5.1）。取值 52px：≥ 44px 觸控
     下限，再加上兩行式標籤不需要的餘裕，與 iOS tab bar 的 49pt 同一量級。
     三處必須用同一個值——導覽自身的列高、<main> 為它預留的下方留白、以及
     Toast 的上抬距離；分別寫死三個 52 遲早會有一個沒跟著改。 */
  --tabbar-h: 52px;
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
  --shadow-md: 0 4px 14px rgba(15, 23, 42, 0.08);

  /* 表格 */
  --color-row-alt: #f7f9fc;     /* 斑馬紋 */
  --color-row-hover: #eef4fb;   /* hover 高亮 */
  --color-th-bg: #f1f4f9;

  /* 參數區黃底概念（保留） */
  --color-settings-bg: #fff9e6;
  --color-warning-bg: #fdf3d8;
  --color-warning-border: #e0b94f;

  /* 深色模式支援：硬編碼色彩轉變數（ui-visual-polish-3, Requirement 1） */
  color-scheme: light;
  --color-header-bg: #24303f;
  --color-input-bg: #ffffff;
  --color-danger-solid: #b03225;   /* 白字對比 ≈ 6.3:1 */
  --badge-buy-bg: #fdecea;  --badge-buy-text: #b03225;
  --badge-sell-bg: #e7f4ec; --badge-sell-text: #17663d;
  --nw-pos-bg1: #fff6f5; --nw-pos-bg2: #fbe9e7; --nw-pos-border: #f2cfca;
  --nw-neg-bg1: #f3faf6; --nw-neg-bg2: #e4f3ea; --nw-neg-border: #c8e6d4;
  --toast-bg: #24303f;      --toast-text: #ffffff;       /* 對比 ≈ 12:1 */
  --toast-fail-bg: #b03225; --toast-fail-text: #ffffff;  /* 對比 ≈ 6.3:1 */
}

/* 深色模式：由 data-theme 屬性驅動（ui-theme-toggle, Requirement 3.1）
   色值逐字沿用 ui-visual-polish-3 已驗算之深色值 */
:root[data-theme="dark"] {
  color-scheme: dark;
  --color-gain: #e07b6d;        /* 深卡片 #1e242e 對比 ≈ 5.3:1，AA 通過；紅=漲不變 */
  --color-loss: #5fbf8f;        /* 深卡片對比 ≈ 6.9:1，AA 通過；綠=跌不變 */
  --color-primary: #dfe5ec;     /* 主文字，深卡片對比 ≈ 12:1 */
  --color-muted: #9aa7b4;       /* 深卡片對比 ≈ 6.3:1，AA 通過 */
  --color-bg: #151a21;
  --color-card: #1e242e;
  --color-border: #333c48;
  --color-row-alt: #232a35;
  --color-row-hover: #2a3442;
  --color-th-bg: #262e3a;
  --color-settings-bg: #2b2513; /* 深色琥珀，保留參數區黃底概念 */
  --color-warning-bg: #33290f;
  --color-warning-border: #8a6d1f;
  /* --color-accent / --color-accent-hover 刻意不覆寫（設計決定：白字按鈕背景兩種配色同值） */
  --color-header-bg: #10161e;
  --color-input-bg: #232b36;
  --color-danger-solid: #c0392b;   /* 白字對比 ≈ 5.4:1，AA 通過 */
  --badge-buy-bg: #3d2422;  --badge-buy-text: #f1a196;   /* 對比 ≈ 6.8:1 */
  --badge-sell-bg: #1d3328; --badge-sell-text: #8fd6ae;  /* 對比 ≈ 8.0:1 */
  --nw-pos-bg1: #2a1d1b; --nw-pos-bg2: #33211e; --nw-pos-border: #4a3029;
  --nw-neg-bg1: #16241c; --nw-neg-bg2: #1b2f23; --nw-neg-border: #2b4a38;
  --toast-bg: #2e3947;      --toast-text: #e8edf3;
  --toast-fail-bg: #5c231d; --toast-fail-text: #f6b6ad;
}

* { box-sizing: border-box; }

/* hidden 屬性優先於任何 display 規則：
   author 樣式（如 .form-field 的 display:flex、.btn 的 display:inline-block）
   會覆蓋 UA 的 [hidden] { display:none }，導致 hidden 元素仍然顯示。
   以 !important 保證 hidden 一律生效（標準做法）。 */
[hidden] { display: none !important; }

body {
  margin: 0;
  font-family: "PingFang TC", "Microsoft JhengHei", "Noto Sans TC", sans-serif;
  background: var(--color-bg);
  color: var(--color-primary);
  line-height: 1.6;
}

/* --- 頁首與導覽 --- */
.site-header {
  background: var(--color-header-bg);
  color: #fff;
  padding: 0.75rem 1.5rem;
  display: flex;
  align-items: center;
  gap: 2rem;
  flex-wrap: wrap;
}
.site-title { font-size: 1.25rem; margin: 0; }
.site-nav { display: flex; gap: 0.5rem; }
.site-nav a {
  color: #ecf0f1;
  text-decoration: none;
  padding: 0.35rem 0.9rem;
  border-radius: 4px;
}
.site-nav a:hover { background: rgba(255, 255, 255, 0.15); }
.site-nav a.active { background: var(--color-accent); color: #fff; }

/* 主題切換按鈕（ui-theme-toggle, Requirement 1）。
   issue #110 起位於 .account-panel 內，故不再自帶 margin-left: auto——
   推到標頭右側改由 .user-menu 負責（見下方）。 */
.theme-toggle {
  background: transparent;
  color: #ecf0f1;                  /* 同 .site-nav a，深底對比 AA 通過 */
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: var(--radius-sm);
  padding: 0.35rem 0.9rem;
  font-size: 0.9rem;
  font-family: inherit;
  cursor: pointer;
}
.theme-toggle:hover { background: rgba(255, 255, 255, 0.15); }
.theme-toggle:focus-visible { outline: 2px solid #ecf0f1; outline-offset: 2px; }

.container { max-width: 1100px; margin: 0 auto; padding: 1.5rem; }

h2 { font-size: 1.15rem; margin: 1.5rem 0 0.75rem; }

/* startup-fund 驗收修正：啟動基金 h3 明顯次於參數設定 h2（避免瀏覽器預設 h3 反而更大） */
#capital-title { font-size: 1rem; margin: 1rem 0 0.5rem; }

/* --- 警示 --- */
.alert {
  padding: 0.75rem 1rem;
  border-radius: var(--radius-sm);
  margin: 1rem 0;
}
.alert-warning {
  background: var(--color-warning-bg);
  border: 1px solid var(--color-warning-border);
}
.alert a { margin-left: 0.5rem; }

/* --- ★累計淨損益卡片（放大強調、依正負變色） --- */
.net-worth-card {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 1.5rem;
  text-align: center;
  margin: 1rem 0;
  box-shadow: var(--shadow-md);
}
.net-worth-title { margin: 0 0 0.25rem; font-size: 1.1rem; }
.net-worth-value {
  font-size: 3rem;
  font-weight: 700;
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.net-worth-hint { color: var(--color-muted); font-size: 0.85rem; margin: 0.25rem 0 0; }

/* 較上一快照的淨值變化（ui-polish-4）：依正負套 .positive/.negative */
.net-worth-delta {
  font-size: 0.95rem;
  font-weight: 600;
  margin: 0.15rem 0 0;
  font-variant-numeric: tabular-nums;
}

/* 淨值卡片依正負套用漸層背景（ui-visual-polish, Requirement 3） */
.net-worth-card.net-worth-positive {
  background: linear-gradient(135deg, var(--nw-pos-bg1), var(--nw-pos-bg2));
  border-color: var(--nw-pos-border);
}
.net-worth-card.net-worth-negative {
  background: linear-gradient(135deg, var(--nw-neg-bg1), var(--nw-neg-bg2));
  border-color: var(--nw-neg-border);
}

/* 正負變色（也用於損益卡片） */
.positive { color: var(--color-gain); }
.negative { color: var(--color-loss); }

/* --- 指標卡片 --- */
/* auto-fit 而非 auto-fill（稽核 §5.5，issue #127）：兩者都按 minmax 算出「塞得下
   幾欄」，差別在欄位沒有卡片時——auto-fill 把空軌留在那裡，auto-fit 收掉空軌讓
   卡片把整列分完。1280px 下容器 1052px 恰好排五欄，故 auto-fill 時「損益」群組
   的兩張卡各 201px、右側留 603px 空白；改 auto-fit 後兩張各 520px 填滿整列。
   欄數本身不變，只有「不足一列時是否留空軌」改變，故三張以上的群組觀感不動。 */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0.75rem;
}
/* 合併卡（多列數值那種）單獨成群時占滿整列（稽核 §5.5 第二、三條）。
   auto-fit 已使單張卡拿到整列寬度，這條在兩種情況下仍必要：
     1. 合併卡與普通卡並存時（目前沒有，但版面規則不該依賴這件事）；
     2. 有人把 auto-fit 改回 auto-fill 時——375px 兩欄下單張卡只會拿到 170px，
        而集中度卡的欄名帶了代號與名稱（「最大持股 2330 台積電」）會斷在詞中間。
   寬度上限由 .card-merged 的 max-width: 420px 收束，故大螢幕不會把三個短列
   拉成一整排寬。原為 #concentration-group 專屬（issue #126），§5.5 要求同樣的
   「單張卡不得只占半列」適用於所有合併卡，故推廣至 .cards 的直接子代。 */
.cards > .card-merged { grid-column: 1 / -1; }
/* 報表的六張卡固定三欄（稽核 §5.5 第四條，issue #127）。auto-fit 只決定「塞得下
   幾欄」，不會為了整除卡片數而少排一欄：1280px 下容器 1052px 排五欄，於是前五張
   一列、「買進 / 賣出金額」獨自落在第二列，右側空 851px，而它又因為多了兩個
   card-row 而高 120px（其餘 91px），看起來像另一種東西而不是同一組指標。
   固定三欄使 6 = 2×3 整除，第二列三張卡同高。
   斷點取 672px：三欄的最小需求為 3×200 + 2×12 = 624px，加上容器左右 padding
   48px。672px 以下 auto-fit 自然落為兩欄（6 = 3×2，同樣整除），故不需另立規則。
   卡片數若不再是 6 或 3 的倍數，這條規則就要重新算——它換來的是整除，不是三欄。 */
@media (min-width: 672px) {
  #report-cards { grid-template-columns: repeat(3, 1fr); }
}
/* 兩欄時落單的最後一張卡撐滿整列（稽核 §5.5 第三條，issue #127）。個股頁的彙總
   有七張卡，375px 兩欄下前六張排三列、「報酬率」獨自留在第四列的左半，右半是
   純粹的空白。auto-fit 幫不上忙——四列的兩個欄軌都有卡片，沒有空軌可收。

   **上界 497px 不是隨手挑的，改動 `.cards` 的 minmax 最小值就必須重算**：
   ≤640px 的軌道下限為 150px、gap 12px、容器左右 padding 各 12px，故三欄所需
   視窗寬為 3×150 + 2×12 + 24 = 498px。實機量測欄數：320px 一欄、344–497px
   兩欄、498px 起三欄。
   為什麼非得有上界：三欄時 `:last-child:nth-child(odd)` 會誤傷——「損益」與
   「成本與費用」在某些設定下恰好是三張卡，第三張既是 last-child 又是 odd，
   但它本來就填滿第一列的第三欄，撐滿整列反而把它推到新的一列去。
   下界不需要：320px 只有一欄，`1 / -1` 等於原本的整列寬，是 no-op。
   `.card-merged` 不受影響（上方已無條件 `1 / -1`）。 */
@media (max-width: 497px) {
  .cards > .card:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
.card {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: 0.9rem 1rem;
  box-shadow: var(--shadow-sm);
}
.card h3, .card h4 { margin: 0; font-size: 0.85rem; color: var(--color-muted); font-weight: 500; }
.card-value {
  margin: 0.25rem 0 0;
  font-size: 1.35rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* --- 按鈕 --- */
.btn {
  display: inline-block;
  padding: 0.5rem 1.25rem;
  border-radius: var(--radius-sm);
  border: none;
  font-size: 1rem;
  cursor: pointer;
  text-decoration: none;
}
.btn-primary { background: var(--color-accent); color: #fff; }
.btn-primary:hover { background: var(--color-accent-hover); }
.btn:disabled { opacity: 0.55; cursor: not-allowed; }

/* 更新市價按鈕 loading spinner（ui-visual-polish, Requirement 5） */
.btn.loading::after {
  content: "";
  display: inline-block;
  width: 0.9em;
  height: 0.9em;
  margin-left: 0.5em;
  vertical-align: -0.15em;
  border: 2px solid rgba(255, 255, 255, 0.35);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .btn.loading::after { animation-duration: 2s; }
}

.export-section { margin: 1.25rem 0; }

/* 持倉彙總頁：更新市價操作區（market-price-auto-update, Requirement 6.1） */
.table-actions { margin: 0.75rem 0; }

/* --- 參數表單（黃底概念） --- */
.settings-section { margin-top: 1.5rem; }
/* 參數設定預設摺疊（ui-polish-4，同 .tx-form-section 模式）：h2、啟動基金區塊、費稅表單一併收合 */
.settings-section.collapsed > h2,
.settings-section.collapsed > #capital-section,
.settings-section.collapsed > .settings-form { display: none; }
#settings-toggle { margin: 0 0 0.25rem; }
.settings-form {
  background: var(--color-settings-bg);
  border: 1px solid var(--color-warning-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 1rem 1.25rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0.75rem 1.25rem;
}
.form-field { display: flex; flex-direction: column; }
.form-field label { font-size: 0.85rem; margin-bottom: 0.2rem; }
.form-field input,
.form-field select {
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: 5px;
  font-size: 1rem;
  background: var(--color-input-bg);
  color: inherit;
}
.form-field input.input-error,
.form-field select.input-error { border-color: var(--color-gain); }
.field-error { color: var(--color-gain); font-size: 0.8rem; min-height: 1.1em; }

/* --- 密碼欄位 + 揭露按鈕（input-ux-improvements, Requirements 2.8, 4） --- */
/* 容器：輸入框寬度完全由容器決定（flex），按鈕改為絕對定位不參與流動配置，
   因此切換 type（password ⇄ text）不會因固有寬度差異造成版面位移（Requirement 4.7）。 */
.password-field { position: relative; display: flex; }

/* 尺寸預算（design.md「尺寸預算：Reveal_Toggle 為何同時滿足 R4.2 與 R4.4」）：
   設按鈕寬 T = 44、邊框 B = 1（左右各 1）、左內距 L、右內距 P。
     不重疊（R4.2）：P ≥ T − B = 43px
     8px 容差（R4.4）：L + P ≤ T + 8 − 2B = 50px
   兩式相減 ⟹ L ≤ 7px，所以**不可沿用 .form-field input 既有的 0.6rem（9.6px）左內距**。
   取 L = 0.25rem（4px）、P = 2.75rem（44px）：L + P = 48 ≤ 50 ✓、P = 44 ≥ 43 ✓。
   本規則必須位於上方 `.form-field input` 之後（同specificity，靠來源順序覆寫）。
   min-height 置於基礎規則而非 640px 區塊：R4.1／R4.4 涵蓋 768px，窄螢幕區塊在該寬度不生效。 */
.password-field input {
  flex: 1 1 0%;
  min-width: 0;
  min-height: 44px;
  padding-left: 0.25rem;
  padding-right: 2.75rem;
}

/* 按鈕以絕對定位疊放於輸入框右側內距區、貼齊右邊框；
   width 為**固定** 44px（而非僅 min-width），避免圖示尺寸把 T 推大而侵蝕 R4.2 的間隙。
   僅使用既有色彩 token（--color-muted 於淺／深主題對比皆 ≥ 4.5:1 > R4.6 的 3:1）。 */
.password-reveal {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 44px;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  color: var(--color-muted);
  border-radius: var(--radius-sm);
}
/* 沿用專案既有 focus 慣例（同 .tx-filter-quick button / .sim-tooltip-trigger）；
   按鈕為定位元素，外框繪於輸入框之上不被裁切（Requirement 2.8） */
.password-reveal:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.form-actions {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 1rem;
}
.form-status { font-size: 0.9rem; }
.form-status.ok { color: var(--color-loss); }
.form-status.fail { color: var(--color-gain); }

/* --- 表格（供交易紀錄/持倉彙總頁共用） --- */
table.data-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--color-card);
  /* 外框改由 .table-wrap 承擔，圓角才不會被表格直角蓋掉 */
}
.data-table th, .data-table td {
  padding: 0.45rem 0.7rem;
  border-bottom: 1px solid var(--color-border);
  text-align: right;
  font-variant-numeric: tabular-nums;
  /* 欄位不換行：外層 .table-wrap 可水平捲動，避免日期等窄欄被壓縮換行 */
  white-space: nowrap;
}
/* sticky header：黏附於 .table-wrap 捲動容器頂端（ui-visual-polish, Requirement 2.3） */
.data-table th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--color-th-bg);  /* 必須不透明，否則捲動時內容透出 */
  font-weight: 600;
}
/* 斑馬紋 + hover（用 td 上色，避免被 sticky th 疊層影響） */
.data-table tbody tr:nth-child(even) td { background: var(--color-row-alt); }
.data-table tbody tr:hover td { background: var(--color-row-hover); }
/* 備註等長文字欄允許換行（覆寫整體 nowrap），並限制最大寬度。

   min-width 是 issue #120 補的。原本只有 max-width：`table.data-table` 是
   `width: 100%` 的自動版面，交易列表的 nowrap 數值欄加起來已超過容器（實測
   1440px：表格最小內容寬 1330px、容器 1050px），自動版面於是把唯一可換行的備註欄
   壓到它的最小內容寬——而 `overflow-wrap: break-word` 讓「最小內容寬」等於**一個
   字元**。兩件事共用同一個宣告：break-word 是為了長字串不撐破表格而加的，卻同時
   讓這一欄可以被壓到近乎消失。

   實測（Chrome 1440px，交易列表，備註 48 字那一列）：
     min-width 無 → 備註欄 74px、列高 425px
     10rem       → 160px、169px      ← 採用
     12rem       → 192px、143px
     16rem       → 256px、118px

   取 10rem 而非更寬的兩個理由：
   1. 個股頁交易明細（12 欄，不擁擠）的備註欄實測是 168px，10rem＝160px 與它實質
      相同，兩張表的同一欄因此不再一寬一窄；該頁本來就寬於 160px，這條規則對它
      「量測到的差異為零」。
   2. 備註在稽核 §5.2 是**次要欄位**。12rem 會讓它變成整張表最寬的一欄（超過
      「操作」的 176px），次要欄位吃掉最多水平預算說不過去。

   代價是表格最小內容寬 +86px（1330 → 1416），且這個增量與視窗寬度無關（表格早已
   等於最小內容寬，1440px 與 768px 量到同一個 1330）。換句話說 `.table-wrap` 的水平
   捲動**本來就已經存在**（1440px 時已溢出 280px），這條規則只是讓它多 86px——不是
   「讓水平捲動提早出現」。 */
.data-table td.wrap, .data-table th.wrap {
  white-space: normal;
  min-width: 10rem;
  max-width: 24rem;
  overflow-wrap: break-word;
}
.data-table td.text, .data-table th.text { text-align: left; }
.data-table td.empty-row { color: var(--color-muted); text-align: center; }
/* 表格內連結（如持倉頁代號 → 個股頁）：accent 色，深淺主題皆通過對比 */
.data-table td a { color: var(--color-accent); }
:root[data-theme="dark"] .data-table td a { color: var(--chart-net); }  /* 深底提高亮度 */

/* 代號連結的觸控目標（issue #113，稽核 §5.4）：本輪量測 40×27，稽核要求
   「擴大至整個儲存格或整列」。
   取儲存格而非整列：整列可點會與列內既有的編輯／刪除鈕搶手勢，也會讓長按選取
   數字變成導航（§8 明文要求確認不影響這兩件事）。而整格已經夠——代號欄本身就
   比 44px 寬，只要把 td 的 padding 讓給連結，欄寬即成為觸控寬度。
   字級與行高一律不動（§7 資訊密度）：唯一的代價是列高由 41px 增至 44px。
   置於基礎規則而非窄螢幕區塊，同 #tx-table .action-cell .btn-small 的既有理由：
   §8.1 涵蓋 768px，而本專案唯一的窄螢幕斷點 640px 在該寬度不生效。 */
.data-table td.ticker-cell { padding: 0; }
.data-table td.ticker-cell > a {
  display: flex;
  align-items: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0.45rem 0.7rem;   /* 沿用 .data-table td 的內距，連結因此填滿整格 */
}

/* 表格容器：成為垂直捲動容器使 sticky 生效；寬表仍可水平捲動（交易紀錄欄位較多） */
.table-wrap {
  overflow: auto;
  max-height: 70vh;
  border-radius: var(--radius);
  border: 1px solid var(--color-border);
  box-shadow: var(--shadow-sm);
}

/* 首欄固定（mobile-experience）：寬表水平捲動時，日期/代號欄固定於左側，
   捲到右側欄位仍知道在看哪一筆。背景必須不透明否則後方欄位透出：
   奇數列補卡片底色；偶數列斑馬紋與 hover 由既有規則（特異性較高）覆蓋。 */
.data-table th:first-child,
.data-table td:first-child {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--color-card);
  box-shadow: 1px 0 0 var(--color-border);   /* 右緣分隔線，提示後方可捲動 */
}
/* 左上角 th：需同時高於 sticky header（z-index: 2）與 sticky 首欄 */
.data-table thead th:first-child {
  z-index: 3;
  background: var(--color-th-bg);
}

/* 交易紀錄的月份小標題（issue #128，稽核 §5.2 的延伸）。

   每個月一個 <tbody>，開頭一列跨欄的 <th scope="rowgroup"> 印「2026 年 9 月・3 筆」。
   分成多個 <tbody> 不只語意正確（HTML 的列群組本來就是這個用途），還讓上方的
   斑馬紋規則 `tbody tr:nth-child(even) td` 在每個月重新起算——小標題恆為第 1 列，
   各月第一筆資料因此一律是第 2 列。寫在單一 tbody 裡插標題列則做不到：各月筆數
   奇偶不同，任何固定的 nth-child 都會讓某些月從有底色開始、某些月從沒有底色開始。
   小標題本身是 <th> 而非 <td>，斑馬紋（選擇器指定 td）不會落到它身上。

   置於基礎規則而非 640px 區塊：桌機表格同樣分組，一份 DOM 兩種版面（§8.4）。 */
.data-table tbody tr.tx-month-row th {
  /* 覆寫兩個 sticky：`.data-table th` 的 top: 0（否則捲動時這一列會浮到 thead
     之上，蓋住欄名）與首欄固定的 left: 0（跨欄的標題沒有「首欄」可固定）。
     position: static 同時使那兩條規則的 z-index 失效，不必逐一歸零。 */
  position: static;
  box-shadow: none;   /* 首欄固定的右緣分隔線在跨欄標題上會畫到表格最右側 */
  padding-top: 0.75rem;
  background: var(--color-card);   /* 不用 --color-th-bg：它是段落標記，不是第二個表頭 */
  color: var(--color-muted);
  font-size: 0.85rem;
  font-weight: 600;
  text-align: left;
}

/* 買賣徽章（ui-visual-polish, Requirement 4） */
.badge {
  display: inline-block;
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
  line-height: 1.5;
}
.badge-buy  { background: var(--badge-buy-bg); color: var(--badge-buy-text); }   /* 對比 ≈ 5.9:1 */
.badge-sell { background: var(--badge-sell-bg); color: var(--badge-sell-text); } /* 對比 ≈ 6.1:1 */

/* 個股頁「佔投資組合 N%」徽章（稽核 §5.6，issue #126）。
   刻意用中性配色而非 --badge-buy/sell：佔比是規模不是損益，套紅綠會讓人以為
   「紅色代表這檔在賺」。兩個主題的對比皆 ≥ 11:1（深底 #262e3a 配 #dfe5ec、
   淺底 #f1f4f9 配 #24303f）。 */
.badge-weight {
  background: var(--color-th-bg);
  color: var(--color-primary);
  border: 1px solid var(--color-border);
}
/* 徽章與說明同一行、窄螢幕自然換行；說明文字沿用 .page-hint 的字級與顏色，
   此處只負責排列，故不重設任何字型屬性 */
.weight-line {
  margin: 0.25rem 0 0.75rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}
.weight-line .page-hint { margin: 0; }

/* 表格內操作按鈕 */
.btn-small {
  padding: 0.2rem 0.6rem;
  font-size: 0.85rem;
  background: var(--color-th-bg);
  color: var(--color-primary);
  margin-right: 0.3rem;
}
.btn-small:hover { background: var(--color-border); }
.btn-danger { color: var(--color-gain); }

/* 交易明細的筆數展開控制項（ticker-detail-refinements R6.7）。
   觸控目標在**基礎規則**即滿足 44px，不只寫在窄螢幕 @media 內：
   R9.1 明文涵蓋 768px，而本專案唯一的窄螢幕斷點是 640px，在 768px 不生效。 */
.row-collapse-toggle {
  margin-top: 0.6rem;
  min-height: 44px;
  min-width: 44px;
  padding: 0.5rem 1rem;
}

/* 摘要卡的逐列展開鈕（issue #111，稽核 §5.2）：由 static/table-cards.js 插入
   每列首格，只在 640px 以下的卡片版面顯示——桌機是完整表格，沒有欄位被收起，
   多一顆按鈕只會佔掉首欄寬度。
   44×44 只寫在這條基礎規則、不在窄螢幕區塊重複：`.password-reveal` 等控制項
   之所以兩處都寫，是因為它們在 641–768px 也看得到而該區間的斷點不生效；本控制項
   在那個區間根本 display: none，不存在同樣的漏洞。 */
.row-toggle {
  display: none;
  min-width: 44px;
  min-height: 44px;
  align-items: center;
  justify-content: center;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: var(--color-th-bg);
  color: var(--color-primary);
  font-size: 0.85rem;
  cursor: pointer;
}

/* 交易表操作欄：三顆按鈕（複製／編輯／刪除）皆為 44×44 觸控目標
   （input-ux-improvements, Requirements 8.3, 8.5, 8.7）。
   置於基礎規則而非窄螢幕區塊：R8.3 涵蓋 768px，而本專案唯一的窄螢幕斷點
   @media (max-width: 640px) 在該寬度不生效。
   三顆都必須同高——R8.5 要求三者 top 差異 ≤ 1px，故不可只放大「複製」。
   刻意的取捨：桌機版交易列高度因此增加至約 44px。本應用主要以手機使用，
   三顆同尺寸的觸控目標比緊湊的桌機列更重要。
   以 #tx-table .action-cell 限定範圍，不影響 Admin_Page 使用者清單的 .btn-small。
   水平間距沿用既有 .btn-small 的 margin-right: 0.3rem（4.8px ≥ R8.5 的 4px）、
   不換行沿用 .data-table td 既有的 white-space: nowrap，皆不需新增規則。 */
#tx-table .action-cell .btn-small {
  min-width: 44px;
  min-height: 44px;
  vertical-align: middle;
}

/* AI 功能按鈕：accent 底白字的緊湊尺寸，工具列中一眼可辨（同 .btn-primary 色票） */
.btn-ai {
  padding: 0.3rem 0.85rem;
  font-size: 0.9rem;
  background: var(--color-accent);
  color: #fff;
}
.btn-ai:hover { background: var(--color-accent-hover); }

/* --- 持倉彙總頁：市價 inline 編輯輸入框 --- */
.page-hint { color: var(--color-muted); font-size: 0.85rem; margin: 0.25rem 0 0.75rem; }
.price-input {
  width: 7em;
  padding: 0.25rem 0.4rem;
  border: 1px solid var(--color-border);
  border-radius: 5px;
  font-size: 0.95rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  background: var(--color-input-bg);
  color: inherit;
}
.price-input:focus { border-color: var(--color-accent); outline: none; }
.price-input.input-error { border-color: var(--color-gain); }

/* --- 使用者管理頁：每日 AI 上限控制項（ai-usage-quota, Requirements 7.5, 7.6） ---
   沿用 .price-input 的輸入框樣式與既有色票／間距 token，不新增語意色。
   44px 觸控目標置於基礎規則（而非僅窄螢幕區塊）：R7.6 於 375px 生效，但
   mobile-responsive-check 亦要求 768px 量測，而本專案唯一的窄螢幕斷點
   @media (max-width: 640px) 在該寬度不生效——同 #tx-table .action-cell
   .btn-small 的既有取捨（桌機列高因此約為 44px）。 */
.quota-cell { white-space: nowrap; }
.quota-input {
  width: 5em;
  min-width: 44px;
  min-height: 44px;
  padding: 0.25rem 0.4rem;
  margin-right: 0.3rem;
  border: 1px solid var(--color-border);
  border-radius: 5px;
  font-size: 0.95rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  background: var(--color-input-bg);
  color: inherit;
}
.quota-input:focus { border-color: var(--color-accent); outline: none; }
.quota-input:disabled { opacity: 0.55; cursor: not-allowed; }
/* 沿用 .btn / .btn-small 的配色與 margin-right，僅補觸控目標尺寸 */
.quota-save-btn { min-width: 44px; min-height: 44px; }

/* 卡片分組（ui-visual-polish-2, Requirement 1） */
.card-group { margin: 0 0 1rem; }
.card-group-title {
  margin: 0 0 0.4rem;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-muted);   /* 白/淡底對比 ≈ 5.9:1，AA 通過 */
  letter-spacing: 0.05em;
}

/* 卡片群組的說明註記（overview-metrics-clarity, Requirement 5.5）。
   視覺沿用 .page-hint（同一個 --color-muted 與 0.85rem），但不共用該 class：
   .page-hint 的 margin 是為區塊之間設計的（0.25rem 0 0.75rem），置於 .cards
   之後會與下一個群組的標題貼太近。此處改為上緊下鬆，使註記在視覺上歸屬於
   它上方的那組卡片而非下一組。

   刻意不套損益紅綠：這是說明文字，不是會計數字。 */
.card-group-note {
  margin: 0.45rem 0 0;
  color: var(--color-muted);
  font-size: 0.85rem;
  line-height: 1.5;
}
/* 註記內的 <strong> 僅加重字重，不改顏色——否則會與紅綠的損益慣例混淆 */
.card-group-note strong { font-weight: 600; }

/* 利息合併卡（ui-visual-polish-2, Requirement 2）。整列寬度規則見上方
   `.cards > .card-merged`——原為集中度卡專屬（issue #126），§5.5 推廣至全部
   合併卡（issue #127）。 */
.card-merged { max-width: 420px; }
.card-rows { margin-top: 0.4rem; display: flex; flex-direction: column; gap: 0.3rem; }
.card-row { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.card-row-label { font-size: 0.85rem; color: var(--color-muted); }
.card-row-value {
  font-size: 1.1rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* 交易表單摺疊（ui-visual-polish-2, Requirement 3） */
.tx-form-section.collapsed > h2,
.tx-form-section.collapsed > .settings-form { display: none; }
#tx-form-toggle { margin: 1rem 0 0.25rem; }

/* --- 月報表（monthly-report） --- */
.report-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  flex-wrap: wrap;
}
.report-month-nav { display: flex; align-items: center; gap: 0.5rem; }
/* 上一期／下一期（issue #113，稽核 §5.4）：稽核量到 33×44，寬度不足。
   ◀▶ 是單一字元，寬度完全由 .btn-small 的左右 padding 決定，故非補 min-width
   不可；min-height 一併補上是因為 640px 斷點外（桌機與 768px 平板）量到 27px。
   置於基礎規則的理由同 .data-table td.ticker-cell > a。 */
.report-month-nav .btn-small {
  min-width: 44px;
  min-height: 44px;
  margin-right: 0;   /* 覆寫 .btn-small 的 0.3rem，間距已由 nav 的 gap 承擔 */
}
/* 月／年模式切換（yearly-report）：沿用 .trend-range 膠囊樣式 */
.report-mode { display: flex; gap: 0.25rem; }
.report-mode button {
  background: var(--color-card);
  color: var(--color-muted);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.2rem 0.7rem;
  font-size: 0.85rem;
  font-family: inherit;
  cursor: pointer;
}
.report-mode button:hover { background: var(--color-row-hover); }
.report-mode button.active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}
.report-mode button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
@media (max-width: 640px) {
  .report-mode button { min-height: 44px; padding: 0.2rem 0.9rem; }
}
.report-month-label {
  font-weight: 600;
  min-width: 7.5em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}
/* AI 結果卡片（巡檢/檢討/覆盤共用；內容由 renderAiResult 結構化渲染） */
.ai-review-section { margin-top: 1.5rem; }
.ai-review-result {
  margin-top: 0.75rem;
  padding: 0.85rem 1.25rem 1rem;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-accent);   /* 左緣 accent 條，標示 AI 產出 */
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  line-height: 1.8;
}
.ai-result-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.6rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--color-border);
}
.ai-result-title { font-weight: 600; }
.ai-result-time { color: var(--color-muted); font-size: 0.8rem; }  /* AA 對比沿用 muted */
.ai-result-list {
  margin: 0;
  padding-left: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.ai-result-list li::marker { color: var(--color-accent); }  /* 裝飾性圓點，非文字對比 */
.ai-result-p { margin: 0.35rem 0; }
.ai-result-ok { margin: 0.35rem 0; font-weight: 600; }
/* 免責聲明（issue #89）：看得到但不搶戲——比正文小、次要色、以細線與內容分隔。
   刻意不用警示底色或 ⚠️：每次都出現的警告等於沒有警告，且會與巡檢的
   ✅／❌ 語意打架。--color-muted 對卡片底色的對比實測為淺色 5.47:1、
   深色 6.36:1，皆過 AA 的 4.5:1（小字門檻）。 */
.ai-result-disclaimer {
  margin: 0.9rem 0 0;
  padding-top: 0.5rem;
  border-top: 1px solid var(--color-border);
  color: var(--color-muted);
  font-size: 0.8rem;
  line-height: 1.6;
}
/* 交易編號引用徽章（巡檢輸出的 #id）；button 版可點擊跳至該筆交易 */
.ai-ref {
  display: inline-block;
  padding: 0 0.4rem;
  border: 1px solid var(--color-border);
  border-radius: 6px;
  background: var(--color-th-bg);
  font-size: 0.85em;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
button.ai-ref {
  cursor: pointer;
  font-family: inherit;
  color: inherit;               /* 沿用主文字色，深淺主題對比皆過 AA */
  text-decoration: underline;   /* 可點擊的視覺提示 */
  text-underline-offset: 2px;
}
button.ai-ref:hover { border-color: var(--color-accent); background: var(--color-row-hover); }
button.ai-ref:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }

/* 巡檢跳轉目標列閃爍高亮：動畫掛在 td 上，才能蓋過 sticky 首欄的不透明底色 */
@keyframes tx-row-flash-kf {
  0%, 55% { background-color: rgba(41, 128, 185, 0.22); }
  100% { background-color: transparent; }
}
.tx-row-flash > td { animation: tx-row-flash-kf 1.8s ease; }

/* --- AI 快速記帳輸入列（ai-quick-entry） --- */
.ai-entry-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;             /* 狀態列 flex-basis:100% 需換行，否則會把輸入框壓扁 */
  gap: 0.5rem;
  margin: 1rem 0 0.25rem;
  padding: 0.6rem 0.75rem;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.ai-entry-icon { font-size: 1.1rem; }
#ai-entry-input {
  flex: 1;
  min-width: 0;                /* flex 收縮，窄螢幕不撐爆 */
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 1rem;             /* ≥16px：避免 iOS 聚焦自動縮放 */
  font-family: inherit;
  background: var(--color-input-bg);
  color: inherit;
}
#ai-entry-input:focus { border-color: var(--color-accent); outline: none; }
#ai-entry-status { flex-basis: 100%; margin: 0; }   /* 狀態列換行顯示 */
#ai-entry-status:empty { display: none; }           /* 空狀態不佔一行 */
/* 快速記帳的免責聲明（issue #89）：與狀態列同樣獨佔一行。與結果卡片那份
   共用尺寸與顏色，但**不共用文案**——理由見 templates/transactions.html。
   此處恆顯示（不隨解析狀態出現／消失）：它要在按下按鈕**之前**就看得到。 */
.ai-entry-disclaimer {
  flex-basis: 100%;
  margin: 0.15rem 0 0;
  color: var(--color-muted);
  font-size: 0.8rem;
  line-height: 1.6;
}
@media (max-width: 640px) {
  #ai-entry-input { min-height: 44px; }
}

/* AI 預填欄位高亮：琥珀淡底提示「這是 AI 填的，請過目」，
   使用者修改該欄或送出後移除 */
#tx-form input.ai-filled, #tx-form select.ai-filled {
  background: var(--color-warning-bg);
  border-color: var(--color-warning-border);
}

/* --- 名稱自動帶出（ticker-name-autofill, Requirements 8.3–8.7, 9.10） --- */

/* 專用色票以**獨立的 :root 區塊新增**，不動既有色票的任何宣告：
   --color-warning-* 已被上方 ai-filled 與參數區黃底佔用、--color-gain 為錯誤色、
   --color-accent 為連結／按鈕色，調動任一個都會外溢到其他頁面。 */
:root {
  --color-info-bg: #e8f1fb;      /* 淡藍底；主文字 #24303f 對比 11.7:1（AA 過） */
  --color-info-border: #2f6fa8;  /* 對淡藍底 4.7:1、對參數區黃底 5.0:1（非文字 ≥3:1） */
}
:root[data-theme="dark"] {
  --color-info-bg: #1c2e42;      /* 深藍底；主文字 #dfe5ec 對比 10.9:1（AA 過） */
  --color-info-border: #5a9bd4;  /* 對深藍底 4.7:1、對深色參數區底 5.1:1 */
}

/* 系統查得並填入的名稱：淡藍底 ＋ 左側加粗實心邊條。
   兩個通道（底色與邊條寬度）使區別**不僅以顏色**呈現（R8.3, WCAG 1.4.1）。
   刻意與上方 `#tx-form input.ai-filled` 分屬不同宣告區塊、且採不同色系
   （藍 vs 琥珀），兩者若同時落在同一欄位仍可辨識（R8.4, R9.10）。
   全域 box-sizing: border-box 使加寬左邊框不改變欄位外框尺寸，
   故標記的施加與移除不造成版面位移。 */
#tx-form input.auto-filled {
  background: var(--color-info-bg);
  border-color: var(--color-info-border);
  border-left-width: 4px;
}

/* 欄位輔助說明（次要文字）：字級與 min-height 沿用 .field-error 的慣例。
   色票用既有 --color-muted：淺色模式對參數區黃底 5.2:1、深色模式 6.2:1，皆過 AA。 */
.field-hint {
  color: var(--color-muted);
  font-size: 0.8rem;
  min-height: 1.1em;
  overflow-wrap: anywhere;       /* 375px 下長訊息可斷行，不水平溢出（R8.6） */
}

/* 名稱查詢狀態列刻意保留**兩行**空間，而非 .field-hint／.field-error 的一行。
   理由（R8.7 零版面位移）：.settings-form 是
   grid-template-columns: repeat(auto-fill, minmax(220px, 1fr))，同一 grid row
   的欄位共用列高，#name 欄位一長高整列都長高。實測（Chromium 於 320–1400px
   逐 8px 掃描）欄位可用寬度下限為 220.5px，而最長訊息
   「股票代號格式錯誤，須為 4 至 6 位數字或大寫英文字母」固有寬度 314px
   ⟹ 必然折成兩行；只留一行必定抽高整列。
   量測依據：font-size 0.8rem = 12.8px、繼承 body 的 line-height 1.6
   ⟹ 單行行框實測 20.46875px，兩行 40.9375px = 3.198em；取 3.3em（42.24px）
   留約 1.3px 餘裕吸收次像素捨入與字體回退差異。同一掃描確認最長訊息在任何
   寬度下皆不超過兩行（最大實測高度恆為 40.9375px），故兩行為上界而非近似值。
   代價是恆定多留一段空白，但 .field-error 本來就恆定保留 1.1em，慣例一致。 */
#ticker-name-status { min-height: 3.3em; }

/* 窄螢幕斷點涵蓋（mobile-responsive-check 第 7 項）：本節刻意**不新增**
   @media (max-width: 640px) 規則，理由如下（皆於 375／414／768px 實測確認）：
   - 觸控目標：auto-filled 只改 background／border-color／border-left-width，
     不動 height／padding，既有窄螢幕規則 `.form-field input { min-height: 44px }`
     仍生效（375／414px 實測 #name 為 44px，與其他欄位同高）。
   - 溢出與折行：≤640px 時 .settings-form 落為單欄，欄位反而更寬
     （375px → 309px、414px → 348px），比桌機多欄時的 220.5px 下限寬鬆；
     最長訊息在三個寬度下皆為單行或兩行且 scrollWidth == clientWidth。
   因此窄螢幕無須額外處理，新增的兩個 class 由既有斷點與上述基礎規則完整覆蓋。 */

/* --- 交易列表篩選列（tx-list-enhancements） --- */
.tx-filter-bar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;             /* 窄螢幕自動換行 */
  margin: 0.5rem 0 0.25rem;
}
.tx-filter-bar select,
.tx-filter-bar input[type="date"] {
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  font-family: inherit;
  background: var(--color-input-bg);
  color: inherit;
}
.tx-filter-sep { color: var(--color-muted); }
.tx-filter-quick { display: flex; gap: 0.25rem; }
.tx-filter-quick button {
  background: var(--color-card);
  color: var(--color-muted);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.2rem 0.7rem;
  font-size: 0.85rem;
  font-family: inherit;
  cursor: pointer;
}
.tx-filter-quick button:hover { background: var(--color-row-hover); }
.tx-filter-quick button.active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;                 /* accent 底白字，同 .trend-range */
}
.tx-filter-quick button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
#tx-filter-count { margin: 0 0 0 auto; }   /* 筆數靠右 */

/* 現價／距今參考欄：中性色，與損益欄視覺區隔（非會計數字不套紅綠） */
.data-table td.ref { color: var(--color-muted); }

@media (max-width: 640px) {
  .tx-filter-bar select,
  .tx-filter-bar input[type="date"],
  .tx-filter-quick button,
  #ai-audit-btn { min-height: 44px; }   /* 觸控目標 */
  #tx-filter-count { margin-left: 0; width: 100%; }
}

/* --- 持股集中度（analysis-tools）：市值佔比堆疊條 + 圖例 --- */
.concentration-bar {
  display: flex;
  height: 28px;
  border-radius: 999px;
  overflow: hidden;
  border: 1px solid var(--color-border);
  background: var(--color-card);
}
.concentration-seg { min-width: 2px; }   /* 極小佔比仍可見 */
.concentration-legend {
  list-style: none;
  margin: 0.6rem 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.25rem;
}
.concentration-legend li {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.9rem;
}
.concentration-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* 個股頁的返回連結（issue #113，稽核 §5.4「剩餘例外一併收斂」）：本輪量測
   117×22.5，寬度夠而高度不足。inline-flex 使 44px 的觸控區包住文字而不必放大
   字級（§7 資訊密度）；寬度不設下限，文字本身已遠超 44px。 */
#back-to-holdings {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* --- 交易試算（analysis-tools）：輸入列 + 結果卡 --- */
.simulate-bar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.simulate-bar select,
.simulate-bar input {
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 1rem;              /* ≥16px：避免 iOS 聚焦自動縮放 */
  font-family: inherit;
  background: var(--color-input-bg);
  color: inherit;
}
.simulate-bar input { width: 8em; }
.sim-result {
  margin-top: 0.75rem;
  padding: 0.85rem 1.25rem;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  max-width: 420px;
}
.sim-row { display: flex; justify-content: space-between; gap: 1rem; }
.sim-label { color: var(--color-muted); font-size: 0.9rem; }
.sim-value { font-weight: 600; font-variant-numeric: tabular-nums; }
@media (max-width: 640px) {
  .simulate-bar select, .simulate-bar input, #sim-btn { min-height: 44px; }
}

/* 報酬率膠囊：沿用買賣徽章色票（ui-visual-polish-2, Requirement 4） */
.badge-rate-pos { background: var(--badge-buy-bg); color: var(--badge-buy-text); }   /* 同 .badge-buy */
.badge-rate-neg { background: var(--badge-sell-bg); color: var(--badge-sell-text); } /* 同 .badge-sell */

/* 刪除確認對話框（ui-visual-polish-3, Requirement 2） */
dialog#delete-confirm-dialog {
  background: var(--color-card);
  color: var(--color-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 1.25rem 1.5rem;
  max-width: 26rem;
}
dialog#delete-confirm-dialog::backdrop { background: rgba(15, 23, 42, 0.45); }
:root[data-theme="dark"] dialog#delete-confirm-dialog::backdrop { background: rgba(0, 0, 0, 0.6); }
.dialog-actions { display: flex; justify-content: flex-end; gap: 0.75rem; margin-top: 1rem; }
.btn-danger-solid { background: var(--color-danger-solid); color: #fff; }

/* Toast 通知（ui-visual-polish-3, Requirement 3）
   位置：右下角。原本在右上角會遮住標頭的使用者名稱/登出/主題切換
   （mobile-experience 回報），右下角在任何視窗寬度都不與操作元件重疊；
   容器錨定 bottom，多則通知向上堆疊。 */
#toast-container {
  position: fixed;
  bottom: 0.75rem;
  right: 0.75rem;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-width: min(22rem, calc(100vw - 1.5rem));
  pointer-events: none;
}
.toast {
  background: var(--toast-bg);
  color: var(--toast-text);
  padding: 0.6rem 1rem;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  font-size: 0.9rem;
  animation: toast-in 0.25s ease-out;
  transition: opacity 0.4s ease;
}
.toast-fail { background: var(--toast-fail-bg); color: var(--toast-fail-text); }
.toast-hide { opacity: 0; }
@keyframes toast-in { from { transform: translateX(0.75rem); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .toast { animation: none; transition: none; } }

/* 窄螢幕 RWD（ui-visual-polish-3, Requirement 4） */
@media (max-width: 640px) {
  .site-header { padding: 0.6rem 0.9rem; gap: 0.5rem 1rem; }
  .site-title { font-size: 1.05rem; }
  /* 導覽連結換行（admin-readonly-view R6.7）：檢視模式下導覽為「四個投資頁 +
     使用者管理」共五個連結，單行需求超過 375／414px 的可用寬度。既有的
     nowrap 會把溢出壓進各 <a> 內部斷行，出現「連結變窄變高、中文一字一行」
     的破版；改為 wrap 使溢出以整個連結為單位落到第二列。

     issue #110 之後這條只作用於 data-nav="admin"（單一「使用者管理」連結）：
     投資頁那一支已改為下方的底部固定導覽，五個連結等寬均分且不換行。 */
  .site-nav { flex-wrap: wrap; }
  .site-nav a { padding: 0.6rem 0.7rem; }                      /* 觸控目標 ≥44px（mobile-experience） */
  .container { padding: 0.75rem; }

  /* 底部固定導覽（issue #110／稽核 §5.1）：手機首屏原本被「四～五個導覽連結
     ＋主題＋登出」吃掉兩到三列，導覽本身比第一筆資料還顯眼。

     做法是不動 DOM——`nav.site-nav` 留在標頭原處，只在窄螢幕改以固定定位
     移到畫面底部。因此 aria-current 的當前位置標記、鍵盤焦點順序（標頭 →
     導覽 → 內容）與既有測試的錨點（tests/web/test_page_nav_active.py 以
     `<nav class="site-nav">` 定位）全部原封不動，只有版面變了。

     只對 data-nav="pages" 生效：admin 非檢視模式的導覽只有一個「使用者管理」
     連結（base.html 的 nav_admin_only 分支），做成整條底部列只會更占空間。 */
  body[data-nav="pages"] .site-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 20;
    gap: 0;
    flex-wrap: nowrap;               /* 覆寫上方的 wrap：等寬均分不需要換行 */
    background: var(--color-header-bg);
    border-top: 1px solid rgba(255, 255, 255, 0.18);
    box-shadow: 0 -2px 6px rgba(15, 23, 42, 0.25);
    /* iPhone 主頁指示器的安全區；未設 viewport-fit=cover 時 env() 為 0，無害 */
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  body[data-nav="pages"] .site-nav a {
    flex: 1 1 0;                     /* 五個連結等寬均分，最窄 375px 亦不溢出 */
    min-width: 0;
    min-height: var(--tabbar-h);     /* 觸控目標（52px ≥ 44px） */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.4rem 0.15rem;
    border-radius: 0;
    font-size: 0.78rem;              /* 「使用者管理」五字於 375px 的 1/5 欄寬內不裁切 */
    white-space: nowrap;
  }
  /* 當前位置：底部列刻意不用 .site-nav a.active 的 accent 實心底——#2980b9
     對白僅 4.30:1（見 .view-banner 的色票註解），字級又比桌機小。改以三個
     通道同時作用：上緣 accent 色條、半透明白底、加粗純白文字（12:1）。 */
  body[data-nav="pages"] .site-nav a.active {
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    font-weight: 600;
    box-shadow: inset 0 3px 0 0 var(--color-accent);
  }
  /* 固定列不得蓋住內容的最後一列：<main> 預留列高 + 安全區 + 一般間距 */
  body[data-nav="pages"] .container {
    padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + 0.75rem);
  }
  /* Toast 錨在右下角（見 #toast-container 註解），底部列出現後要一起上抬，
     否則通知會被壓在導覽下方看不見 */
  body[data-nav="pages"] #toast-container {
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px) + 0.75rem);
  }
  .net-worth-value { font-size: 2rem; }
  /* 自然落為 1–2 欄；auto-fit 使單張卡占滿整列而非只占半列（稽核 §5.5）：
     375px 兩欄下 auto-fill 會讓「資產與負債」的單張卡停在 170px、右半留空 */
  .cards { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  /* 報表的兩張多列卡在窄螢幕占滿整列（issue #129）。375px 兩欄下卡片寬 169.5px、
     扣掉 padding 與框線只剩 135.5px，而「已實現勝率」那一列要放
     欄名 68px ＋ gap 16px ＋ 值 122px＝206px（實測 Chrome，375／414／768px）。
     不加這條的後果不是「擠一點」而是**值被折成兩行**：`58%（7 /` 與 `12）`
     分屬上下兩行，分子分母因此讀不出來（欄名同時折成「已實現」「勝率」）。
     整列寬時可用 317px，三列都是單行。

     為什麼是 `grid-column` 而不是縮小字級：字級是全站的 `.card-row-value`，
     為一張卡改它會讓其他頁的合併卡跟著變小。
     為什麼不用 `.card-merged`（無條件占整列）：那會連桌機一起吃掉，而桌機的
     報表刻意是三欄兩列（§5.5，issue #127）。
     兩張卡都加是刻意的——只讓勝率那張占整列，另一張（買進／賣出金額）就會
     獨自留在最後一列的左半，右半空白，正是 §5.5 第三條禁止的排法。
     六張卡因此在 640px 以下排成 2＋2＋1＋1 四列，每一列都排滿。

     實測（Chrome，本規則生效後）：375px 卡片 170／170／170／170／351／351、
     每列 2＋2＋1＋1；414px 同排法；三列皆單行。641–671px 落為兩欄（290px），
     勝率列也是單行，故不需延伸這條規則。

     **已知且接受**：672–791px（例如 768px 三欄，卡片 232px）欄名會折成
     「已實現」「勝率」兩行，值 `58%（7 / 12）` 不折。那一段需要 206px 而只有
     198px，差 8px；不為這 8px 動手的理由是三個備案都更糟——改字級會影響全站
     合併卡、縮 gap 只剩 0px 餘裕、把欄名縮成「勝率」則與 CONTEXT.md 的正名
     相衝（單獨的「勝率」會與「贏過大盤」混淆）。折的是欄名而非數字，且折在
     詞界上，可讀性不受損。 */
  #report-cards > .card-rows-full { grid-column: 1 / -1; }
  .settings-form { grid-template-columns: 1fr; }
  .btn { min-height: 44px; }                                   /* 觸控目標（Requirement 4.3） */
  .theme-toggle { min-height: 44px; }                          /* 觸控目標（ui-theme-toggle） */
  .form-field input, .form-field select { min-height: 44px; }
  /* input-ux-improvements Requirement 4.5 明文要求此宣告位於既有的
     @media (max-width: 640px) 區塊內（即本區塊，.btn／.form-field input／.theme-toggle
     觸控目標規則所在處）；與 .password-reveal 基礎規則刻意重複。 */
  .password-reveal { min-width: 44px; min-height: 44px; }
  .price-input { min-height: 44px; }
  /* 每日 AI 上限控制項的觸控目標（ai-usage-quota, Requirement 7.6）；
     與基礎規則刻意重複，使 375px 的要求在此區塊明文可見 */
  .quota-input { min-height: 44px; min-width: 44px; }
  .quota-save-btn { min-height: 44px; }
  .data-table { font-size: 0.9rem; }
  /* 表格加密（mobile-experience）：縮小 padding，一屏多見 1–2 欄 */
  .data-table th, .data-table td { padding: 0.4rem 0.55rem; }
  /* 新增交易摺疊按鈕改滿版，好按也更像手機 app 的主要動作 */
  #tx-form-toggle { width: 100%; }

  /* --- 手機資料表：摘要卡＋可展開列（issue #111，稽核 §5.2） ---
     稽核實測：390px 下交易表內容寬約 1190px、容器僅約 366px，買賣別、單價、
     已實現損益與整個「操作」欄都在第一屏之外。版面本身沒破（.table-wrap 的
     overflow: auto 把溢出關在容器裡），壞的是可發現性——不橫捲就不知道有這些欄。

     作法是同一份 <table> 換一種版面：thead 收起，每個 tr 變成一張卡，每個 td
     以 ::before 印出它在 thead 的欄名。欄名文字由 table-cards.js 從 thead 抄進
     data-card-label，值則完全是桌機那些 <td>——**沒有第二條渲染路徑**，金額與
     日期的格式化只有各頁 build*Row 一份（issue #111 §8.4 要求兩者共用格式化規則）。

     只有被標上 .table-cards 的容器改版面（欄數 ≥7 的五張寬表：交易、除權息、
     持倉、個股明細、使用者清單）。報表兩張與資金來源表欄數 ≤6，在 390px 已無
     溢出，維持表格反而比卡片好比較數字。 */
  .table-cards {
    /* 卡片由頁面本身捲動：留著 70vh 的內層捲動容器會變成頁中頁，
       手機上兩層捲動很難操作 */
    max-height: none;
    overflow: visible;
    /* 外框與陰影改由每張卡各自承擔 */
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }
  .table-cards .data-table,
  .table-cards .data-table tbody,
  .table-cards .data-table tr,
  .table-cards .data-table td { display: block; }
  .table-cards .data-table thead { display: none; }   /* 欄名改由每格的 ::before 承擔 */
  .table-cards .data-table tr {
    background: var(--color-card);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-sm);
    margin-bottom: 0.6rem;
    padding: 0.5rem 0.7rem;
  }
  /* 斑馬紋與 hover 在卡片版面沒有意義（卡與卡之間已有間距與邊框），
     留著會讓偶數卡底色不同而看似另一種狀態 */
  .table-cards .data-table tbody tr:nth-child(even) td,
  .table-cards .data-table tbody tr:hover td { background: transparent; }
  .table-cards .data-table td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;          /* 操作欄的按鈕組在 375px 可換行，不撐寬卡片 */
    gap: 0.5rem;
    padding: 0.25rem 0;
    border-bottom: 0;
    text-align: right;
    white-space: normal;      /* 卡片寬度固定，長備註換行而非撐寬 */
    overflow-wrap: anywhere;
  }
  .table-cards .data-table td::before {
    content: attr(data-card-label);
    flex: 0 0 auto;
    color: var(--color-muted);
    font-size: 0.85rem;
    font-variant-numeric: normal;   /* 欄名是文字，不需要等寬數字 */
    text-align: left;
  }
  /* 首格是卡片的標題列：日期或代號本身已說明是什麼，不再印欄名；
     展開鈕同行靠右。position: static 是為了覆寫桌機的 sticky 首欄。 */
  .table-cards .data-table td:first-child {
    position: static;
    box-shadow: none;
    margin-bottom: 0.3rem;
    padding-bottom: 0.4rem;
    border-bottom: 1px solid var(--color-border);
    font-size: 1.05rem;
    font-weight: 600;
    text-align: left;
  }
  .table-cards .data-table td:first-child::before { content: none; }
  /* 卡片版面的代號格：內距已由上面兩條 .table-cards 規則給定，連結不可再自帶
     0.7rem 否則代號會比卡內其他欄位多縮排一截。改以 flex: 1 吃下整格剩餘寬度
     （table-cards.js 把展開鈕 appendChild 到同一格，它自己的 44×44 不受影響），
     觸控區因此是「代號格扣掉展開鈕」而非只有四個字。 */
  .table-cards .data-table td.ticker-cell > a { flex: 1; padding: 0; }
  /* 空狀態／載入中列是單一 colspan 格，沒有欄名可印，也不該長得像有值的卡 */
  .table-cards .data-table td.empty-row {
    justify-content: center;
    border-bottom: 0;
    font-size: 0.9rem;
    font-weight: normal;
  }
  .table-cards .data-table td.empty-row::before { content: none; }

  /* 次要欄位（thead 未標 data-card-primary 者）預設收起。展開狀態只記在展開鈕的
     aria-expanded 一處（同 issue #110 的帳號選單與橫幅說明），故只能用 :has()
     從那顆按鈕推出同列其他格的顯示——把狀態同時寫到 tr 上就會有兩份可能過期的
     資料。:has() 不支援時 table-cards.js 不會加上 .card-secondary 也不插按鈕，
     退化為「整張卡全部欄位都顯示」，不會留下按了沒反應的控制項。 */
  /* 月份小標題（issue #128）在卡片版面不是一張卡：拿掉上面 `.table-cards
     .data-table tr` 給的底色、邊框、圓角與陰影，只留一行小標與上方留白，
     讀起來像段落標題。它正是這張長列表在手機上缺的掃描節奏。 */
  .table-cards .data-table tbody tr.tx-month-row {
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    margin: 0.9rem 0 0.35rem;
    padding: 0;
  }
  /* display: block 必須明寫：上面只把 td 改成 block，<th> 仍是 table-cell，
     在 display: block 的父層裡會被包進匿名表格盒而拿不到整行寬度。 */
  .table-cards .data-table tbody tr.tx-month-row th {
    display: block;
    padding: 0;
    border-bottom: 0;
    background: transparent;
  }

  .table-cards .data-table td.card-secondary { display: none; }
  .table-cards .data-table tr:has(.row-toggle[aria-expanded="true"]) td.card-secondary {
    display: flex;
  }
  .table-cards .data-table .row-toggle { display: inline-flex; }
}

/* --- 登入頁（multi-user-auth, Requirement 1.1）：置中卡片式版面，沿用設計 token --- */
.login-body {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.login-card {
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 2rem;
  width: 100%;
  max-width: 22rem;
}
.login-title {
  margin: 0 0 1.25rem;
  font-size: 1.3rem;
  text-align: center;
}
.login-card form {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
/* 錯誤訊息：--color-gain 於淺/深卡片背景對比皆 ≥ 4.5:1（AA 通過） */
.login-error {
  color: var(--color-gain);
  font-size: 0.9rem;
  min-height: 1.2em;
  margin: 0;
}
/* 被取代說明（single-session-login, Requirements 5.3, 5.6）：與 .login-error
   併用（共用字級），僅覆寫「這不是錯誤」的那幾件事。

   1. 顏色不用 --color-gain。使用者沒做錯任何事——帳號在別的裝置登入是
      **中性說明**，紅色會讓人以為剛才的操作失敗。改用與正文同一個
      --color-primary，資訊性由左側 accent 邊框與淺底面板表達，不靠顏色
      單獨傳達語意（WCAG 1.4.1）。對比實測值（headless Chrome 量測）：
        淺色 #24303f on #f1f4f9 = 12.14:1；深色 #dfe5ec on #262e3a = 10.79:1
        左框 --color-accent #2980b9 對卡片底 = 4.30:1（淺）／3.62:1（深），
        非文字元件 3:1 通過。
   2. 間距：.login-error 的 margin: 0 會讓說明同時貼著標題與表單。上方由
      .login-title 的 1.25rem 下邊距提供（相鄰邊距合併），此處只補下邊距。
   3. min-height 改 auto：.login-error 的 1.2em 是為「空的錯誤區」保留佔位
      高度，而本節點只在有訊息時才存在，且窄螢幕會折成兩行，佔位無意義。
   4. 不設固定高度、不 nowrap、不 overflow: hidden ⟹ 折行後撐高卡片而非
      裁切文字（Requirement 5.6）。 */
.login-notice {
  color: var(--color-primary);
  background: var(--color-th-bg);
  border-left: 3px solid var(--color-accent);
  border-radius: var(--radius-sm);
  margin: 0 0 1rem;
  padding: 0.6rem 0.75rem;
  min-height: auto;
  line-height: 1.5;
  overflow-wrap: break-word;   /* 防護：無空白的長字串也不致水平溢出 */
}
.login-btn { width: 100%; }

/* 兩步驗證（two-factor-login）：驗證碼／引導設定畫面。
   QR 底色固定白：深色主題下 img 周圍若是深底，部分掃描器對比不足會
   掃不到；QR 本身是黑白圖，白框在兩種主題下都正確。 */
.totp-qr { text-align: center; margin: 0.75rem 0; }
.totp-qr img { background: #fff; padding: 8px; border-radius: 4px; }
.totp-setup-lead { margin: 0 0 0.5rem; }
.totp-secret-details { margin: 0 0 0.75rem; font-size: 0.85rem; }
.totp-secret {
  display: block;
  margin-top: 0.35rem;
  word-break: break-all;   /* 32 字元 Base32 無空白，不折行會撐破卡片 */
  user-select: all;        /* 一點即全選，抄寫進驗證器少一步 */
}
.totp-back { margin-top: 0.5rem; }

/* 登入頁的窄螢幕（Requirement 5.6）：說明訊息在 375／414px 下折成兩行，
   使卡片自 354.4px 高變為 425.6px（+71.2px，實測）。此處收斂說明區的垂直
   內距與下邊距（水平內距不動，以維持文字可用寬度），使含瀏覽器工具列的
   可視高度（iPhone SE 約 553px，實測卡片底 489.3px、按鈕底 456.3px）
   仍能完整看到登入按鈕。水平方向不需任何窄螢幕規則：卡片為
   width: 100% + max-width: 22rem，375px 時自然縮為 343px；中文可於任意
   字元處折行，故基礎規則在 375／414／768px 皆不溢出——768px 更是本專案
   唯一的斷點 640px 所不涵蓋的寬度，凡在該寬度也必須成立的事都只能放在
   基礎規則裡（同 .quota-cell、#tx-table .action-cell 的既有取捨）。 */
@media (max-width: 640px) {
  .login-notice { padding: 0.5rem 0.7rem; margin-bottom: 0.75rem; }
}

/* --- 帳號選單（multi-user-auth, Requirements 1.4, 1.5）：標頭右側主題 + 使用者名稱 + 登出 ---

   桌機（>640px）的外觀與 issue #110 之前完全相同：面板直接內嵌成一列，
   #account-toggle 隱藏。窄螢幕才收合成彈出面板（見本檔 640px 區塊）。
   position: relative 是彈出面板的定位錨點；margin-left: auto 承接原本寫在
   .theme-toggle 上的「推至標頭右側」。 */
.user-menu {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-left: auto;
}
/* 帳號鈕只在窄螢幕出現；沿用 .theme-toggle 的透明底 + 淺框外觀 */
.account-toggle {
  display: none;
  background: transparent;
  color: #ecf0f1;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: var(--radius-sm);
  font-size: 1.1rem;
  line-height: 1;
  font-family: inherit;
  cursor: pointer;
}
.account-toggle:hover { background: rgba(255, 255, 255, 0.15); }
.account-toggle:focus-visible { outline: 2px solid #ecf0f1; outline-offset: 2px; }
.account-panel {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}
/* 使用者名稱：深色標頭底，#ecf0f1 對比 AA 通過（同 .site-nav a） */
.user-menu .username {
  color: #ecf0f1;
  font-size: 0.9rem;
}
/* 登出按鈕：沿用 .theme-toggle 外觀（透明底 + 淺框），但不吃 margin-left: auto */
.logout-btn {
  background: transparent;
  color: #ecf0f1;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: var(--radius-sm);
  padding: 0.35rem 0.9rem;
  font-size: 0.9rem;
  font-family: inherit;
  cursor: pointer;
}
.logout-btn:hover { background: rgba(255, 255, 255, 0.15); }
.logout-btn:focus-visible { outline: 2px solid #ecf0f1; outline-offset: 2px; }

/* 金額隱私遮蔽切換鈕（issue #124）：沿用 .theme-toggle 外觀（透明底 + 淺框），
   同 .logout-btn 的作法——複製而非共用 class，避免動到既有測試釘住的選擇器 */
.privacy-toggle {
  background: transparent;
  color: #ecf0f1;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: var(--radius-sm);
  padding: 0.35rem 0.9rem;
  font-size: 0.9rem;
  font-family: inherit;
  cursor: pointer;
}
.privacy-toggle:hover { background: rgba(255, 255, 255, 0.15); }
.privacy-toggle:focus-visible { outline: 2px solid #ecf0f1; outline-offset: 2px; }

/* --- 金額隱私遮蔽（issue #124）：<html data-privacy="masked"> 時模糊金額區 ---

   刻意寫在**基礎規則**：遮蔽必須在所有寬度生效，桌機在辦公室被瞄到跟手機
   在捷運上被瞄到是同一件事。選擇器列的是「會出現金額的區域」，股數／日期／
   代號被一併模糊是接受的代價——遮蔽的目的是路人讀不到，不是遮蔽下繼續操作，
   要看就按一下解除。canvas 也遮：折線的 Y 軸刻度與走勢本身就是金額。
   blur 用 em 隨各元素字級縮放；user-select: none 防「反白選取讓文字浮出」。
   這是視覺遮蔽不是資料保護：DOM 內容原樣都在。 */
[data-privacy="masked"] .net-worth-value,
[data-privacy="masked"] .net-worth-delta,
[data-privacy="masked"] .card-value,
[data-privacy="masked"] .card-row-value,
[data-privacy="masked"] .chart-summary-item dd,
[data-privacy="masked"] .concentration-legend,
[data-privacy="masked"] .data-table tbody,
[data-privacy="masked"] .sim-result,
[data-privacy="masked"] .ai-result-list,
[data-privacy="masked"] .ai-result-p,
[data-privacy="masked"] canvas {
  filter: blur(0.5em);
  user-select: none;
}
/* 持股佔比（issue #126）另立一組，理由是它遮的不是金額而是**持有什麼**：
   個股頁的佔比徽章、總覽集中度卡的代號與名稱（在 .card-row-label 裡，而該
   class 全站到處都是靜態欄名，不能整批遮）、以及超標提醒那句話。百分比本身
   看不出資產規模，但「你有六成押在台積電」同樣是旁人不該讀到的持倉資訊。
   佔比的數值本體走上面那組的 .card-row-value，故此處不重複列。 */
[data-privacy="masked"] .badge-weight,
[data-privacy="masked"] #concentration-group .card-row-label,
[data-privacy="masked"] #concentration-note {
  filter: blur(0.5em);
  user-select: none;
}

@media (max-width: 640px) {
  .logout-btn { min-height: 44px; }   /* 觸控目標，同 .theme-toggle */
  .privacy-toggle { min-height: 44px; }   /* 觸控目標（issue #124） */
  /* 壓縮手機標頭（ui-polish-4 → issue #110／稽核 §5.1）：整組控制項收進
     #account-toggle 的彈出面板，標頭因此只剩產品名稱與這一顆鈕。

     ui-polish-4 當初的做法是在同一列硬省空間——隱藏使用者名稱、主題鈕縮成
     純圖示。面板一出現就不必再省：名稱與完整的主題標籤在面板裡都放得下，
     故 .username 不再隱藏，app.js 的 updateThemeToggle 也不再分窄螢幕。 */
  .account-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;                /* 觸控目標，同 .theme-toggle／.logout-btn */
    padding: 0.35rem 0.5rem;
  }
  .account-panel {
    display: none;                   /* 收合時不占版面，也不進輔助技術的閱讀順序 */
    position: absolute;
    top: calc(100% + 0.4rem);
    right: 0;
    z-index: 30;                     /* 高於底部導覽（20），低於 Toast（1000） */
    flex-direction: column;
    align-items: stretch;
    gap: 0.4rem;
    min-width: 10rem;
    padding: 0.5rem;
    /* 底色用標頭色而非卡片白：面板內三個控制項都是為深底設計的（#ecf0f1
       文字、半透明白框線與 hover），換成淺底就得把每一條顏色重新驗算對比。
       深淺兩個主題的標頭色都已驗算過 AA（見 :root 的色票註解）。 */
    background: var(--color-header-bg);
    border: 1px solid rgba(255, 255, 255, 0.25);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md);
  }
  /* 展開狀態只認 aria-expanded：JS 只翻這一個屬性，視覺與輔助技術因此
     不可能各說各話（少了這條選擇器，帳號選單會永遠打不開）。 */
  .account-toggle[aria-expanded="true"] + .account-panel { display: flex; }
  .account-panel .username { padding: 0 0.2rem; }
  .account-panel .theme-toggle,
  .account-panel .logout-btn { width: 100%; min-height: 44px; }
  /* 獨立一條而不併入上一組：那組選擇器被既有測試以字面比對釘住（issue #124） */
  .account-panel .privacy-toggle { width: 100%; min-height: 44px; }
}

/* --- 使用者管理頁（multi-user-auth, Requirement 4）：沿用設計 token（Task 5.2） --- */
/* 建立使用者表單：沿用 .settings-form 網格，限制寬度避免兩欄過寬 */
.user-form-section .settings-form { max-width: 40rem; }

/* 角色徽章：管理員沿用賣出徽章色票（醒目）、一般使用者沿用買進徽章色票 */
.badge-role-admin { background: var(--badge-sell-bg); color: var(--badge-sell-text); }
.badge-role-user  { background: var(--badge-buy-bg);  color: var(--badge-buy-text); }

/* 重設密碼對話框：沿用刪除確認對話框的卡片樣式 */
dialog#reset-password-dialog {
  background: var(--color-card);
  color: var(--color-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-md);
  padding: 1.25rem 1.5rem;
  max-width: 26rem;
}
dialog#reset-password-dialog::backdrop { background: rgba(15, 23, 42, 0.45); }
:root[data-theme="dark"] dialog#reset-password-dialog::backdrop { background: rgba(0, 0, 0, 0.6); }
dialog#reset-password-dialog .form-field { margin-top: 0.75rem; }
/* 選擇器刻意不依賴 type（input-ux-improvements, Requirement 4.7）：
   原先以 type 屬性選擇器限定密碼欄，會在 Reveal_Toggle 把欄位切成 text 的瞬間停止匹配，
   寬度由 100% 掉回 UA 預設固有寬度，造成切換時的版面位移。 */
dialog#reset-password-dialog .form-field input { width: 100%; }

/* ===========================================================================
   損益走勢圖（pnl-trend-chart Task 3）
   三條折線用中性三色（避免與紅漲綠跌損益色系混淆）；
   深淺主題各自定義，overview.js 以 getComputedStyle 讀取繪圖。
   =========================================================================== */
:root {
  --chart-net: #2980b9;        /* 累計淨損益：藍（同 accent 色系） */
  --chart-realized: #8e44ad;   /* 已實現損益：紫 */
  --chart-unrealized: #b9770e; /* 未實現損益：琥珀 */
}

:root[data-theme="dark"] {
  --chart-net: #5dade2;        /* 深底提高亮度維持對比 */
  --chart-realized: #bb8fce;
  --chart-unrealized: #f0b35e;
}

.trend-section {
  margin-top: 24px;
}

/* 走勢圖標題列：標題 + 區間切換按鈕（trend-range） */
.trend-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  flex-wrap: wrap;             /* 窄螢幕換行，按鈕列落到第二行 */
}
.trend-range { display: flex; gap: 0.25rem; }
.trend-range button {
  background: var(--color-card);
  color: var(--color-muted);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.2rem 0.7rem;
  font-size: 0.85rem;
  font-family: inherit;
  cursor: pointer;
}
.trend-range button:hover { background: var(--color-row-hover); }
.trend-range button.active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;                 /* accent 底白字對比 AA 通過（同 .btn-primary） */
}
.trend-range button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

@media (max-width: 640px) {
  .trend-range button { min-height: 44px; padding: 0.2rem 0.9rem; }  /* 觸控目標 */
}

.trend-chart-container {
  position: relative;          /* Chart.js responsive 需要定位父容器 */
  height: 320px;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 16px;
}

/* ---------------------------------------------------------------------------
   圖表的等價文字摘要（issue #112／稽核 §5.3）
   總覽頁走勢圖與個股頁進出點位圖共用；結構由 chart-summary.js 填值。
   canvas 對螢幕閱讀器等同一張圖片，這一塊才是圖上數字的文字版，
   故它是內容而非裝飾——不因螢幕窄而隱藏，只改排法。
   --------------------------------------------------------------------------- */
.chart-summary {
  margin: 0 0 10px;
}
.chart-summary-title {
  margin: 0 0 4px;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-muted);
}
.chart-summary-list {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 20px;
  margin: 0;
}
.chart-summary-item {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
}
.chart-summary-item dt {
  color: var(--color-muted);
  font-size: 0.85rem;
  white-space: nowrap;         /* 「期初」被折成上下兩字時完全讀不出是什麼 */
}
.chart-summary-item dd {
  margin: 0;
  font-variant-numeric: tabular-nums;   /* 數字等寬，上下對得起來 */
}
.chart-summary-when {
  margin-left: 0.25rem;
  color: var(--color-muted);
  font-size: 0.8rem;
}

@media (max-width: 640px) {
  /* 一行擠不下五項：兩欄網格，區間變化獨占一列（它是最常被問的那一項） */
  .chart-summary-list {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2px 12px;
  }
  .chart-summary-change { grid-column: 1 / -1; }
  /* 日期改成自己一行：兩欄各約 175px，值與括號日期並排會把括號折在中間
     （「（2026-」／「05-25）」），日期反而讀不出來 */
  .chart-summary-item dd { display: flex; flex-direction: column; }
  .chart-summary-when { margin-left: 0; }
  /* 圖表加高（稽核 §5.3）：手機上 320px 讓三條線疊在一起難以分辨 */
  .trend-chart-container { height: 400px; }
}

.trend-empty {
  color: var(--color-muted);
  background: var(--color-card);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius-sm);
  padding: 20px 16px;
  text-align: center;
}

/* ===========================================================================
   市場狀態指示列（realtime-price-sync Task 8.4）
   #market-indicator 由 autorefresh.js::renderMarketIndicator 切換修飾類別
   （live／closed／stale／failure）。狀態以「文字內容」為主要區隔（JS 設定），
   另以「前導圖示形狀」與「左緣色條」重複標示，非僅靠顏色（WCAG 1.4.1）；
   文字色一律用 --color-primary 保證深淺主題皆高對比。
   刻意避開紅／綠（本專案紅漲綠跌），改用 accent／muted／amber／danger 語意色。
   =========================================================================== */
#market-indicator {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0.75rem 0;
  padding: 0.35rem 0.85rem;
  border: 1px solid var(--color-border);
  border-left-width: 4px;               /* 左緣色條，狀態的第二重（非文字）標示 */
  border-radius: var(--radius-sm);
  background: var(--color-card);
  box-shadow: var(--shadow-sm);
  color: var(--color-primary);          /* 高對比文字，AA 通過（深淺主題皆是） */
  font-size: 0.85rem;
  font-weight: 600;
  line-height: 1.5;
}
/* 前導圖示：以字形「形狀」區隔各狀態（供色盲使用者辨識） */
#market-indicator::before {
  font-size: 0.95em;
  line-height: 1;
}

/* 即時同步中（Requirement 4.5）：accent 圓點 + 脈動 */
#market-indicator.live { border-left-color: var(--color-accent); }
#market-indicator.live::before {
  content: "\25CF";                     /* ● 實心圓 */
  color: var(--color-accent);
  animation: market-indicator-pulse 1.6s ease-in-out infinite;
}

/* 失敗提示旁的重試鈕（稽核 §5.7，issue #125）：與文字的間距由
   #market-indicator 的 gap 承擔，歸零 .btn-small 自帶的 margin-right
   以免雙倍間距。觸控目標由 640px 區塊的 .btn 通則涵蓋（44px）。 */
.market-retry-btn { margin-right: 0; }

/* 休市・最近收盤價（Requirement 4.6）：muted 月亮，語意「非交易時段」 */
#market-indicator.closed { border-left-color: var(--color-muted); }
#market-indicator.closed::before {
  content: "\1F311";                    /* 🌑 新月 */
  color: var(--color-muted);
}

/* 資料可能延遲（Requirement 7.5）：警示三角，可與 live／closed 併存並優先呈現
   （宣告順序在 live／closed 之後，等特異性下覆蓋其色條與圖示） */
#market-indicator.stale {
  border-left-color: var(--color-warning-border);
  background: var(--color-warning-bg);
}
#market-indicator.stale::before {
  content: "\26A0";                     /* ⚠ 警示三角 */
  color: var(--chart-unrealized);       /* 琥珀，於淺／深警示底皆可辨（AA） */
  animation: none;                      /* 覆蓋 live 脈動，過時提示保持穩定 */
}

/* 暫時無法取得最新資料（Requirement 7.7）：danger 三角，failure 為獨立狀態 */
#market-indicator.failure {
  border-left-color: var(--color-danger-solid);
  background: var(--color-warning-bg);
}
#market-indicator.failure::before {
  content: "\26A0";                     /* ⚠ */
  color: var(--color-danger-solid);
}

@keyframes market-indicator-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}
/* 尊重減少動態偏好：停用脈動（狀態仍由文字與圖示表達） */
@media (prefers-reduced-motion: reduce) {
  #market-indicator.live::before { animation: none; }
}

/* ===========================================================================
   賣出試算卡（sell-preview-enhancement Task 4.4）
   在既有 .sim-result 容器內，將賣出結果結構化為分組卡片（現金流／損益／
   剩餘部位／擇時參考／說明）與收合的其他計價法比較區。
   設計原則：
     - 沿用既有 token／class：.sim-row / .sim-label / .sim-value、
       .positive / .negative（紅漲綠跌）、.badge-rate-pos / .badge-rate-neg、
       --color-muted，不新增任何色票語意。
     - 正負意義不僅靠顏色（WCAG 1.4.1）：由 ticker.js 以帶號（+/−）與文字備援
       表達，CSS 僅負責版面與中性樣式，故此處不覆寫顏色語意。
   =========================================================================== */

/* 分組區塊：於 .sim-result（flex column）內作為一組相關列的容器 */
.sim-group { display: flex; flex-direction: column; gap: 0.3rem; }
/* 分組之間以細分隔線區隔層次（沿用既有邊框色，非色彩語意） */
.sim-group + .sim-group {
  padding-top: 0.5rem;
  border-top: 1px solid var(--color-border);
}
/* 分組標題：沿用 .card-group-title 的 muted 小標樣式概念（AA 對比 ≈ 5.9:1） */
.sim-group-title {
  margin: 0;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--color-muted);
  letter-spacing: 0.03em;
}

/* 說明文字（均價不變／擇時說明／損益公式等）：中性、次級字級，非會計數字不套紅綠 */
.sim-note {
  color: var(--color-muted);
  font-size: 0.8rem;
  line-height: 1.5;
  margin: 0;
}

/* 說明 tooltip：可 Tab 聚焦之控制項，focus／hover 顯示全文（R6.3–6.5）。
   完整說明文字另以 aria-describedby 關聯之隱藏節點提供輔助科技（見 ticker.js）。 */
.sim-tooltip { position: relative; display: inline-flex; }
.sim-tooltip-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: 50%;
  background: var(--color-th-bg);
  color: var(--color-muted);
  font-size: 0.8rem;
  font-weight: 700;
  font-family: inherit;
  line-height: 1;
  cursor: help;
}
.sim-tooltip-trigger:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
/* 彈出說明：預設隱藏，於控制項 focus／hover 時顯示並保持可見 */
.sim-tooltip-text {
  position: absolute;
  left: 0;
  top: calc(100% + 0.35rem);
  z-index: 5;
  width: max-content;
  max-width: 18rem;
  padding: 0.5rem 0.7rem;
  background: var(--color-card);
  color: var(--color-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.5;
  white-space: normal;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.15s ease;
}
.sim-tooltip:hover .sim-tooltip-text,
.sim-tooltip:focus-within .sim-tooltip-text {
  opacity: 1;
  visibility: visible;
}
@media (prefers-reduced-motion: reduce) {
  .sim-tooltip-text { transition: none; }
}
@media (max-width: 640px) {
  .sim-tooltip-trigger { width: 44px; height: 44px; }   /* 觸控目標 */
  .sim-tooltip-text { max-width: min(18rem, calc(100vw - 3rem)); }
}

/* ===========================================================================
   管理員唯讀檢視（admin-readonly-view Task 6.3）
   View_Banner（base.html，每頁 <main> 內第一個元素）、/admin 的檢視對象標示
   與 View_Entry_Control 的樣式。

   設計原則：
     - 沿用 ticker-name-autofill 已驗算的 --color-info-bg／--color-info-border
       色票，不新增任何語意色。橫幅與 AI 產出卡（.ai-review-result）、市場狀態
       指示列（#market-indicator）同屬「左緣實心邊條」家族，視覺語彙一致。
     - 區分**不僅靠顏色**（R6.3, WCAG 1.4.1）：三個非顏色通道同時作用——
       (a) 6px 加粗左緣實心邊條，(b) 膠囊外框 + 🔒 圖示的「唯讀檢視」標籤，
       (c) 文字內容本身。任一色覺條件下都看得出這是一塊獨立的狀態區塊。
     - 對比度（R6.4）：文字一律 --color-primary，於 --color-info-bg 上
       淺色 11.7:1、深色 10.9:1（色票原註解已驗算）；標籤文字位於
       --color-card 膠囊上，淺／深皆約 12:1。刻意**不**用 --color-accent
       實心底白字：#2980b9 對白僅 4.30:1，未達 R6.4 的 4.5:1。
     - 觸控目標 44×44 置於**基礎規則**（R6.7 涵蓋 768px，而本專案唯一的
       窄螢幕斷點 @media (max-width: 640px) 在該寬度不生效），並依專案慣例
       於 640px 區塊重複宣告（同 .quota-save-btn／.password-reveal）。
   =========================================================================== */

.view-banner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;                 /* 375／414px 換行，不水平溢出（R6.7） */
  gap: 0.4rem 0.75rem;
  margin: 0 0 1rem;
  padding: 0.55rem 0.9rem;
  background: var(--color-info-bg);
  border: 1px solid var(--color-info-border);
  border-left-width: 6px;          /* 左緣實心邊條：非顏色的區分通道（R6.3） */
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  color: var(--color-primary);     /* 對 --color-info-bg ≥ 10.9:1（R6.4） */
  font-size: 0.9rem;
  line-height: 1.5;
}
/* 說明文字：長句在 375px 需能折行，且不得撐出容器 */
.view-banner > span { min-width: 0; overflow-wrap: anywhere; }

/* 窄螢幕的單行形態（issue #110／稽核 §5.1）：桌機不需要它們——完整句子本來
   就放得下，故短籤與說明鈕在基礎規則即隱藏，桌機橫幅與改版前逐字相同。 */
.view-banner-target,
.view-banner-toggle { display: none; }

/* 「唯讀檢視」標籤：膠囊外框 + 前導鎖頭圖示，形狀與圖示皆為非顏色線索。
   底色用 --color-card 而非 accent 實心底，使文字對比達 ≈ 12:1（R6.4）。 */
.view-banner-label {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  flex: 0 0 auto;
  padding: 0.1rem 0.6rem;
  border: 1px solid var(--color-info-border);
  border-radius: 999px;
  background: var(--color-card);
  color: var(--color-primary);
  font-size: 0.85rem;
  font-weight: 700;
  line-height: 1.5;
  white-space: nowrap;
}
.view-banner-label::before {
  content: "\1F512";               /* 🔒 鎖頭：唯讀語意的圖示線索 */
  font-size: 0.9em;
  line-height: 1;
}

/* 離開檢視按鈕：R6.7 明文要求 375／414／768px 皆 ≥ 44×44，故置於基礎規則。
   .btn 的 display: inline-block 搭配 min-height 會使字貼在頂端，改 inline-flex
   置中（同 .password-reveal 的手法）；margin-right 覆寫 .btn-small 的 0.3rem，
   使按鈕換行落到第二列時右緣與橫幅內距對齊。 */
#exit-view-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  margin-right: 0;
  margin-left: auto;               /* 推至橫幅右側，與說明文字明確分離 */
  flex: 0 0 auto;
}

/* /admin 的檢視對象標示（R6.9）：沿用 View_Banner 的手法（左緣實心邊條 +
   info 底色 + 高對比文字），使兩處是同一種狀態提示而非兩套語彙。
   margin-top 0.5rem 與上方 h2 的 0.75rem 下邊距合併為 0.75rem（12px），
   375px 下不與「使用者清單」標題擠在一起（R6.7）。 */
.admin-view-note {
  margin: 0.5rem 0 0.75rem;
  padding: 0.5rem 0.85rem;
  background: var(--color-info-bg);
  border: 1px solid var(--color-info-border);
  border-left-width: 6px;
  border-radius: var(--radius-sm);
  color: var(--color-primary);
  font-size: 0.9rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

/* View_Entry_Control（admin.js 建立的「檢視資料」按鈕）：文字寬度恰好湊出約
   44px 並非保證，明文宣告下限。同列的「重設密碼」「刪除」一併補上 min-height，
   否則同一列會出現一顆 44px 與兩顆 25px 的按鈕，高度不齊反而更難按。 */
.view-entry-btn { min-width: 44px; min-height: 44px; }
#users-table-container .btn-small { min-height: 44px; }

/* 目前正在檢視的那一列：admin.js 已將該按鈕 disabled（.btn:disabled 只降
   透明度）並設 aria-current="true"。此處補「✓ 勾號 + 加框」兩個非顏色線索，
   使「正在檢視的對象」不必只靠淡化程度辨識。 */
.view-entry-btn[aria-current="true"] {
  border: 1px solid var(--color-info-border);
  font-weight: 600;
}
.view-entry-btn[aria-current="true"]::before {
  content: "\2713\FE0E";           /* ✓ 文字樣式勾號（FE0E 抑制彩色 emoji） */
  margin-right: 0.25rem;
}

@media (max-width: 640px) {
  /* 與基礎規則刻意重複，使 375／414px 的觸控目標要求在窄螢幕區塊明文可見
     （同 .quota-save-btn／.password-reveal 的既有慣例） */
  #exit-view-btn { min-width: 44px; min-height: 44px; }
  .view-entry-btn { min-width: 44px; min-height: 44px; }
  #users-table-container .btn-small { min-height: 44px; }

  /* 橫幅壓成單行（issue #110／稽核 §5.1）：原本「🔒 唯讀檢視 ＋ 整句說明 ＋
     離開鈕」在 375px 要折成三列，與底部導覽一起把首屏吃掉近一半。

     收合時只留「唯讀檢視 ＋ 檢視對象 ＋ 說明鈕 ＋ 離開鈕」一列；完整句子由
     #view-banner-toggle 展開成第二列（order 使它落在離開鈕之後，離開鈕因此
     永遠留在第一列的右端）。檢視對象名稱不參與收合——R6.1 要求它常駐。 */
  .view-banner-target {
    display: inline-block;
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 700;
  }
  .view-banner-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    min-width: 44px;
    min-height: 44px;                /* 觸控目標，同 #exit-view-btn */
    padding: 0.2rem 0.5rem;
    background: transparent;
    color: var(--color-primary);
    border: 1px solid var(--color-info-border);
    border-radius: var(--radius-sm);
    font-size: 0.85rem;
    font-family: inherit;
    cursor: pointer;
  }
  .view-banner-toggle:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
  .view-banner-text { display: none; }
  /* 展開狀態同樣只認 aria-expanded（同 .account-panel 的理由） */
  .view-banner-toggle[aria-expanded="true"] + .view-banner-text {
    display: block;
    flex: 1 0 100%;
    order: 1;                        /* 落到離開鈕之後，成為獨立的第二列 */
  }
}
