:root {
  --bg: #f6f7f9;
  --card: #ffffff;
  --text: #1a1d23;
  --muted: #6b7280;
  --line: #e3e6ea;
  --accent: #2f6fed;
  --up: #d13b3b;      /* 台股習慣：紅漲綠跌 */
  --down: #16a34a;
  --warn-bg: #fff7e6;
  --warn-line: #f0c36d;
  --warn-text: #8a5a00;
  --radius: 12px;
  --shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 1px 3px rgba(16, 24, 40, .04);

  /* 配置分類色。六項檢查（亮度帶／彩度／色盲分離／一般視覺／對比）在白底與
     深色卡片底下全部通過。改之前請照 CLAUDE.md 的「配色」一節重跑驗證。 */
  --cat-stock: #2f6fed;
  --cat-cashlike: #17a673;
  --cat-crypto: #c98500;

  /* 個別標的的類別色盤。順序本身就是色盲安全機制，**不要重排也不要循環**——
     第 9 項一律併進「其他」用中性灰，絕不臨時生一個新色相。
     淺色模式下 series-3／4／5 對比低於 3:1，靠圖例一定有文字標籤補足。 */
  --series-1: #2a78d6;
  --series-2: #eb6834;
  --series-3: #1baf7a;
  --series-4: #eda100;
  --series-5: #e87ba4;
  --series-6: #008300;
  --series-7: #4a3aa7;
  --series-8: #e34948;
  --series-other: #8a94a6;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14161a;
    --card: #1c1f25;
    --text: #e8eaed;
    --muted: #9aa3af;
    --line: #2c3039;
    --accent: #6f9bff;
    --up: #ff6b6b;
    --down: #4ade80;
    --warn-bg: #322a16;
    --warn-line: #6b5620;
    --warn-text: #e8c877;
    --shadow: none;

    /* 深色是另外挑過的色階，不是把淺色翻轉 —— 同樣八個色相，重新踩在深底的亮度帶上 */
    --series-1: #3987e5;
    --series-2: #d95926;
    --series-3: #199e70;
    --series-4: #c98500;
    --series-5: #d55181;
    --series-6: #008300;
    --series-7: #9085e9;
    --series-8: #e66767;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang TC",
               "Noto Sans TC", "Microsoft JhengHei", sans-serif;
  font-size: 15px;
  line-height: 1.55;
  -webkit-text-size-adjust: 100%;
}

/* 1200 是被交易紀錄那張表決定的，不是隨手挑的閱讀寬度：它有十欄、全部 nowrap，
   2026-08-13 實測需要 1066px，而 1080 的版面只給得出 1010（扣掉 wrap 與 card 的
   padding），差的 55px 一定會蓋掉最右邊那一欄。把 cell padding 縮到 8px 也只降到
   1026，仍然不夠 —— 這張表在 1080 底下是真的塞不下。**要往回縮之前先量那張表。** */
.wrap { max-width: 1200px; margin: 0 auto; padding: 16px; }

/* ---------------------------------------------------------------- 頁首 */
header.top {
  display: flex; flex-wrap: wrap; gap: 12px;
  align-items: center; justify-content: space-between;
  padding: 14px 0 18px;
}
header.top h1 { font-size: 19px; margin: 0; letter-spacing: .5px; }
.top-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.price-time { font-size: 12px; color: var(--muted); }
.price-time.stale { color: var(--warn-text); font-weight: 600; }

.seg { display: flex; background: var(--card); border: 1px solid var(--line);
       border-radius: 10px; overflow: hidden; }
.seg button {
  border: 0; background: transparent; color: var(--muted);
  padding: 7px 14px; font-size: 14px; cursor: pointer; font-family: inherit;
}
.seg button[aria-pressed="true"] { background: var(--accent); color: #fff; font-weight: 600; }

button.btn {
  font-family: inherit; font-size: 14px; cursor: pointer;
  background: var(--card); color: var(--text);
  border: 1px solid var(--line); border-radius: 9px; padding: 7px 14px;
}
button.btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
button.btn.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
button.btn.primary:hover:not(:disabled) { filter: brightness(1.08); color: #fff; }
button.btn.danger { color: var(--up); }
button.btn:disabled { opacity: .5; cursor: default; }
button.btn.small { padding: 4px 10px; font-size: 13px; }

nav.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); margin-bottom: 18px;
           overflow-x: auto; }
nav.tabs button {
  border: 0; background: none; font-family: inherit; font-size: 15px; cursor: pointer;
  color: var(--muted); padding: 9px 14px; border-bottom: 2px solid transparent; white-space: nowrap;
}
nav.tabs button[aria-selected="true"] { color: var(--text); border-bottom-color: var(--accent); font-weight: 600; }

/* ---------------------------------------------------------------- 卡片 */
.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px; box-shadow: var(--shadow);
  margin-bottom: 16px;
}
.card h2 { font-size: 15px; margin: 0 0 14px; font-weight: 600; }
.card h2 .sub { font-weight: 400; color: var(--muted); font-size: 13px; margin-left: 8px; }

/* start 不是 center：個別檢視的圖例有二十幾列，置中會把左邊的總資產推到卡片中間 */
.grid2 { display: grid; grid-template-columns: 260px 1fr; gap: 24px; align-items: start; }
/* 配置圖與圖例。用 class 而非行內樣式，否則行內樣式會蓋掉下面的手機版規則，
   欄寬寫死會把整頁撐得比視窗寬，右側內容就被切掉了。 */
/* align-items 用 start 不是 center：圖例可能有二十幾列，置中會讓環圈圖飄到中間 */
.alloc { display: grid; grid-template-columns: 220px 1fr; gap: 20px; align-items: start; }
@media (max-width: 720px) {
  .grid2, .alloc { grid-template-columns: 1fr; gap: 16px; }
  .total-value { font-size: 28px; }
  .stats { gap: 16px 20px; }
  .wrap { padding: 12px; }
  .card { padding: 14px; }
  .table-scroll { margin: 0 -14px; padding: 0 14px; }
}

.total-label { font-size: 13px; color: var(--muted); }
.total-value { font-size: 34px; font-weight: 700; letter-spacing: -.5px; margin: 2px 0 6px;
               font-variant-numeric: tabular-nums; }
.total-sub { font-size: 13px; color: var(--muted); }

.stats { display: flex; flex-wrap: wrap; gap: 26px; margin-top: 14px; }
.stat-label { font-size: 12px; color: var(--muted); }
.stat-value { font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; }

.legend { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px;
          min-width: 0; }
.legend li { display: flex; align-items: center; gap: 9px; font-size: 14px; min-width: 0; }
.legend .swatch { width: 11px; height: 11px; border-radius: 3px; flex: none; }
.legend .lg-label { flex: 1; white-space: nowrap; }
.legend .lg-pct { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
.legend .lg-val { color: var(--muted); font-size: 13px; font-variant-numeric: tabular-nums;
                  text-align: right; white-space: nowrap; }
@media (min-width: 721px) { .legend .lg-val { min-width: 110px; } }

/* 標的數一多，環圈圖就讀不出誰大誰小了 —— 圖例每列補一條比例長條，
   讓排序與倍數關係用長度呈現，那是比角度可靠得多的編碼。 */
.legend .lg-bar { flex: 1; height: 6px; min-width: 40px; background: var(--line);
                  border-radius: 3px; overflow: hidden; }
.legend .lg-bar > span { display: block; height: 100%; }
.legend .lg-name { min-width: 92px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.legend .lg-name small { display: block; font-size: 11px; color: var(--muted); }
.legend li.drillable { cursor: pointer; }
.legend li.drillable:hover .lg-name { color: var(--accent); }
.legend li.folded { opacity: .75; padding-left: 20px; font-size: 13px; }
@media (max-width: 720px) { .legend .lg-bar { display: none; } }

/* 配置檢視切換（總配置／股票／類現金／加密貨幣／自訂） */
.chart-switch { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.chart-switch button {
  font-family: inherit; font-size: 13px; cursor: pointer; white-space: nowrap;
  background: transparent; color: var(--muted);
  border: 1px solid var(--line); border-radius: 20px; padding: 4px 12px;
}
.chart-switch button:hover { color: var(--accent); border-color: var(--accent); }
.chart-switch button[aria-pressed="true"] {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
}
/* 第二列：選哪一組自訂配置。刻意做得比上面那排小、用方角，
   免得跟固定的五個檢視看起來是同一層 */
.chart-switch.sub { margin-top: -8px; }
.chart-switch.sub button { font-size: 12px; border-radius: 6px; padding: 3px 10px; }
.chart-switch.sub button[aria-pressed="true"] {
  background: transparent; color: var(--accent); border-color: var(--accent);
}
.chart-bar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 12px; }

/* 持倉篩選後的小計。用「・」分隔而不是做成四個 stat 方塊 ——
   它是表格的註腳不是主角，做大了會跟上面的分頁標題搶視線 */
.filter-sum {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  font-size: 13px; color: var(--muted); margin: -4px 0 12px;
}
.filter-sum strong { color: var(--text); font-size: 14px; }
.filter-sum span { font-variant-numeric: tabular-nums; }
/* 分隔點用 currentColor 調淡，不要用 --line ——
   那是邊框色，深色模式下（#2c3039）在卡片上等於看不見。
   窄螢幕不畫：那裡會折行，折到行首的分隔點看起來像沒寫完的句子 */
@media (min-width: 721px) {
  .filter-sum span + span::before { content: '・'; margin-right: 10px; opacity: .45; }
}

/* 交易紀錄的排序列。做成下拉而不是像持倉那樣一排按鈕 —— 選項有七個，
   排成按鈕在手機上會折成三行，而這一頁的主角是下面那張表 */
.tx-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px;
  font-size: 13px; color: var(--muted); margin: 0 0 12px;
}
.tx-toolbar label { display: flex; align-items: center; gap: 6px; }
.tx-toolbar select { font-size: 13px; padding: 4px 8px; }

/* ---------------------------------------------------------------- 表格 */
.table-scroll { overflow-x: auto; margin: 0 -18px; padding: 0 18px; }
table { width: 100%; border-collapse: collapse; font-size: 14px; }
th, td { padding: 9px 10px; text-align: right; white-space: nowrap; }
th { font-size: 12px; color: var(--muted); font-weight: 600; border-bottom: 1px solid var(--line); }
td { border-bottom: 1px solid var(--line); font-variant-numeric: tabular-nums; }
th:first-child, td:first-child { text-align: left; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr.clickable { cursor: pointer; }
tbody tr.clickable:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.sym { font-weight: 600; }
.sym small { display: block; font-weight: 400; color: var(--muted); font-size: 12px; }
.up { color: var(--up); }
.down { color: var(--down); }
.muted { color: var(--muted); }
.detail td { background: color-mix(in srgb, var(--accent) 4%, transparent); font-size: 13px; }
.detail dl { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
             gap: 10px 20px; margin: 0; text-align: left; white-space: normal; }
.detail dt { font-size: 12px; color: var(--muted); }
.detail dd { margin: 0; font-weight: 600; font-variant-numeric: tabular-nums; }
/* 明細列裡的說明文字一定要給寬度上限。表格儲存格會撐到內容的自然寬度，
   一段沒有斷點的中文會把整張表拉到 1700px 寬，連帶讓上面的欄位全部要橫向捲動
   —— 實測存款頁溢位 707px。max-width 就是那個斷點。 */
.detail .hint { max-width: 760px; white-space: normal; text-align: left; margin: 10px 0 0; }

/* 釘選置頂的交易。底色只是輔助，真正的識別靠 📌 與「已釘選」按鈕 ——
   淺色模式下這個底色對比很低，不能當成唯一的訊號。 */
tbody tr.pinned td { background: color-mix(in srgb, var(--accent) 5%, transparent); }
tbody tr.after-pin td { border-top: 2px solid var(--line); }
.pin-mark { margin-right: 5px; font-size: 12px; }
/* 圖示按鈕。用文字（「釘選」／「已釘選」）會把這一欄撐寬，1280 寬的視窗下
   「刪除」就被擠出畫面外要橫向捲動才點得到，所以這裡只放圖示，語意交給
   title 與 aria-label。未釘選時壓低不透明度，才看得出兩種狀態的差別。 */
button.btn.small.pin { padding: 4px 7px; font-size: 12px; opacity: .45; }
button.btn.small.pin:hover:not(:disabled) { opacity: 1; }
button.btn.small.pin.on { opacity: 1; border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }

/* 交易紀錄的操作欄釘在右緣。上面把 wrap 放寬到 1200 之後，滿版的視窗已經放得下
   整張表，**這一段是給視窗比較窄的時候用的**（例如螢幕左右分割）——
   表一旦比容器寬，溢位永遠落在最右邊那一欄，被切掉的就一定是「刪除」。
   縮 cell padding（省 40px）或把「刪除」也改成圖示（省 18px）都只夠撐一陣子，
   多一個長帳戶名或多一位數的數量就會再壞一次；釘住則完全不隨內容寬度變動。
   （更早之前把「釘選」縮成圖示，就是同一個問題的第一次發作。）
   ⚠️ **背景必須是不透明色**，不能像上面那些一樣 color-mix 到 transparent ——
   否則橫向捲動時底下的欄位會從按鈕之間透出來。釘選列的底色因此要另外混到
   var(--card) 上，才會跟沒釘住時看起來一樣。
   ⚠️ **手機（≤720px）刻意不釘**：操作欄 155px，在 390 寬的螢幕上會吃掉 42%
   並把「類型」壓在底下，而手機本來就是用手指橫掃，沒有桌機那個「捲不到」的問題。
   ⚠️ **那個 box-shadow 不是裝飾，拿掉會漏字。** sticky 的 right: 0 對齊的是捲動容器的
   *內容* 邊，而 .table-scroll 右邊還有 18px padding（上面那組 margin -18／padding 18）——
   那 18px 不被釘住的欄位蓋到，捲動時底下的帳戶名會從「刪除」右邊冒出半個字。
   用 18px 的實心陰影把那條縫補起來；顏色固定 var(--card) 不跟著釘選列變色，
   這樣沒有溢位時釘選列的底色才會跟同一列其他欄一起停在內容邊，不會多出一塊。 */
@media (min-width: 721px) {
  .tx-actions { position: sticky; right: 0; background: var(--card);
                box-shadow: 18px 0 0 var(--card); border-left: 1px solid var(--line); }
  tbody tr.pinned .tx-actions { background: color-mix(in srgb, var(--accent) 5%, var(--card)); }
}

.pill { display: inline-block; font-size: 11px; padding: 1px 7px; border-radius: 20px;
        border: 1px solid var(--line); color: var(--muted); }
.pill.stale { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn-text); }

.notice { background: var(--warn-bg); border: 1px solid var(--warn-line); color: var(--warn-text);
          border-radius: 10px; padding: 11px 14px; font-size: 13px; margin-bottom: 16px; }
.notice ul { margin: 6px 0 0; padding-left: 18px; }
.empty { text-align: center; color: var(--muted); padding: 34px 10px; font-size: 14px; }
.empty p { margin: 0 0 12px; }

/* ---------------------------------------------------------------- 表單 */
.form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
label.field { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); }
input, select, textarea {
  font-family: inherit; font-size: 14px; padding: 7px 9px;
  border: 1px solid var(--line); border-radius: 8px;
  background: var(--bg); color: var(--text); width: 100%;
}
input:focus, select:focus { outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
                            outline-offset: -1px; border-color: var(--accent); }
/* 由其他欄位算出來的輸入框（換匯的第三格、以總額反推的單價）。給個視覺提示，
   免得使用者對著它打字卻打不進去，以為畫面壞了。 */
input:read-only { background: color-mix(in srgb, var(--muted) 10%, transparent); color: var(--muted); }
.form-actions { display: flex; gap: 8px; margin-top: 14px; align-items: center; flex-wrap: wrap; }
/* 放在表格上方時，間距要往下擺，不然會跟標題的 margin-bottom 疊在一起 */
.form-actions.top { margin: 0 0 14px; }
.hint { font-size: 12px; color: var(--muted); }
.hint.warn { color: var(--warn-text); }
small.warn { color: var(--warn-text); }

/* 自訂配置的編輯畫面：上半是分組（可改名、可刪），下半是每檔一個下拉。
   表單自己撐滿一個固定高度、只讓標的清單捲 —— 讓整個對話框捲的話，
   標的三十幾檔加上幾個分組就會把「儲存」推到看不見的地方，
   使用者得先捲到底才找得到按鈕。分組多的時候上半也自己捲，同樣的道理 */
.layout-form { display: flex; flex-direction: column; max-height: min(78vh, 700px); }
/* 只有標的清單能被壓縮，其餘照自己的高度 —— 不寫這行的話 flex 預設會把
   分組那一區也一起壓扁，建了三組卻只看得到一組 */
.layout-form > *:not(.pick-list) { flex: none; }
.layout-form #layout-groups { max-height: 28vh; overflow-y: auto; }
/* 對帳表單。帳戶多的時候只讓清單捲，說明與按鈕照自己的高度 ——
   跟 .layout-form 同一個道理，少了 flex: none 那行，flex 預設會把說明文字與
   「儲存」一起壓扁，帳戶列表卻撐得老長。
   .rec-list 的負邊界改成 20px（不是 .table-scroll 預設的 18）是為了對齊 dialog
   自己的 padding，否則清單會停在離對話框邊緣 2px 的地方。 */
.rec-form { display: flex; flex-direction: column; max-height: min(78vh, 700px); }
.rec-form > *:not(.rec-list) { flex: none; }
.rec-list { overflow-y: auto; margin: 0 -20px; padding: 0 20px; }
.rec-list th, .rec-list td { padding: 7px 8px; }
.rec-list input[type="checkbox"] { cursor: pointer; }

.grp-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.grp-row .grp-no { flex: none; width: 20px; text-align: center; font-size: 12px;
                   color: var(--muted); font-variant-numeric: tabular-nums; }
.grp-row input { flex: 1; }
.pick-list { flex: 1 1 auto; min-height: 120px; overflow-y: auto; margin-top: 14px;
             border: 1px solid var(--line); border-radius: 10px; padding: 0 12px 12px; }
.pick-sec { margin-top: 12px; }
.pick-sec .stat-label { position: sticky; top: 0; background: var(--card);
                        padding: 6px 0 4px; z-index: 1; }
.pick-row { display: flex; align-items: center; gap: 10px; padding: 3px 0; }
.pick-row .pick-sym { flex: 1; min-width: 0; font-size: 14px; font-weight: 600; }
.pick-row .pick-sym small { display: block; font-weight: 400; font-size: 12px; color: var(--muted);
                            overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pick-row select { flex: none; width: 130px; }

/* 定期定額扣款日：券商只開放特定日期，做成一排可點的方塊比下拉選單好選 */
.days { display: flex; flex-wrap: wrap; gap: 8px; }
.days .day {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  font-size: 14px; color: var(--text);
  border: 1px solid var(--line); border-radius: 8px; padding: 5px 11px;
}
.days .day:has(input:checked) { border-color: var(--accent); color: var(--accent); font-weight: 600; }
.days .day input { width: auto; margin: 0; }

/* 實際成交金額與計畫金額差太多的那一列。多半是扣款失敗或股數打錯一位數 */
tr.dca-warn td { background: var(--warn-bg); }

/* 交割金額試算：讓你在存檔前就能跟券商 App 的數字對一下 */
.calc { display: grid; grid-template-columns: auto 1fr; gap: 3px 18px;
        margin: 0 0 8px; max-width: 300px; font-size: 13px; }
.calc dt { color: var(--muted); }
.calc dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }
.calc .total { border-top: 1px solid var(--line); padding-top: 5px; margin-top: 3px;
               font-weight: 700; color: var(--text); font-size: 14px; }

dialog {
  border: 1px solid var(--line); border-radius: var(--radius); padding: 20px;
  background: var(--card); color: var(--text); max-width: 720px; width: calc(100% - 32px);
}
dialog::backdrop { background: rgba(0, 0, 0, .45); }
dialog h3 { margin: 0 0 16px; font-size: 16px; }

/* ---------------------------------------------------------------- 圖表 */
.donut { width: 100%; max-width: 220px; height: auto; display: block; margin: 0 auto; }
/* 環圈中間的總額。字級寫死在 SVG 座標系裡，會跟著圖一起等比縮放 */
.donut-label { fill: var(--muted); font-size: 12px; }
.donut-value { fill: var(--text); font-size: 19px; font-weight: 700;
               font-variant-numeric: tabular-nums; }
.donut-sub { fill: var(--muted); font-size: 11px; }
/* viewBox 依容器實際寬度產生，所以維持等比縮放，文字才不會被橫向壓扁 */
.linechart { width: 100%; height: auto; display: block; }
.linechart .grid { stroke: var(--line); stroke-width: 1; }
.linechart .tick { fill: var(--muted); font-size: 11px; }
.linechart .line { fill: none; stroke: var(--accent); stroke-width: 2;
                   stroke-linejoin: round; stroke-linecap: round; }
.linechart .area { fill: color-mix(in srgb, var(--accent) 12%, transparent); stroke: none; }
.linechart .dot { fill: var(--accent); }
.linechart .dot-partial { fill: var(--card); stroke: var(--warn-line); stroke-width: 2; }
.chart-empty { fill: var(--muted); font-size: 13px; }

.toast {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  background: var(--text); color: var(--bg); padding: 10px 18px; border-radius: 22px;
  font-size: 14px; box-shadow: 0 4px 16px rgba(0,0,0,.2); z-index: 50; max-width: 90vw;
}
.toast.error { background: var(--up); color: #fff; }

pre.log { background: var(--bg); border: 1px solid var(--line); border-radius: 8px;
          padding: 12px; font-size: 12px; max-height: 320px; overflow: auto;
          white-space: pre-wrap; word-break: break-all; }
