/* ══════════════════════════════════════════════════════════════════════
   個股深度 —— 行動端樣式
   色票：以 PRISM-TW 的訊號色為主軸（強力買進 #1a6b3a），中性色帶一點
   綠偏移，讓灰階看起來像是被選過的、不是預設灰。
   訊號色不直接吃 API 回傳的 hex：那組是為淺色底調的，深色底要另一組。
   ══════════════════════════════════════════════════════════════════════ */
:root{
  --bg:#f4f3ee;
  --surface:#ffffff;
  --surface-2:#eceae2;
  --surface-3:#f8f7f3;
  --text:#1a2320;
  --text-dim:#5f6b66;
  --text-faint:#8b958f;
  --border:rgba(26,35,32,.11);
  --border-strong:rgba(26,35,32,.2);
  --accent:#1a6b3a;
  --accent-soft:#e6f0ea;
  --on-accent:#ffffff;
  --danger:#b91c1c;
  --danger-soft:#fdeeee;
  /* 實心危險按鈕的文字色。淺色底的 --danger 夠深，白字 6.47:1；深色主題的
     --danger 是提亮過的 #e06a5f，白字只剩 3.28:1（未達 AA），所以那邊要反過來
     用深字——不能兩個主題共用同一個值。 */
  --on-danger:#ffffff;
  --warn:#a9761f;
  --shadow:0 1px 2px rgba(26,35,32,.05), 0 10px 30px -18px rgba(26,35,32,.4);
  /* ⛔ 台股慣例：**紅漲綠跌**，與歐美相反。所有帶方向語意的顏色都走這一套：
     看多/買進/目標價/買超＝紅，看空/賣出/停損/賣超＝綠。
     2026-09-08 之前整個 App 用的是歐美慣例（綠=看多），對台灣使用者是反的。
     ⚠ --accent(#1a6b3a 綠) 是**品牌色**，用在按鈕/分頁等介面元件，不帶漲跌語意，
     不要因為這裡改紅就跟著動它。錯誤訊息的 --danger 紅也一樣不是漲跌語意。 */
  --sig-strong-buy:#b3261e;
  --sig-buy:#c0392b;
  --sig-watch-bull:#cf6a5c;
  --sig-neutral:#a9761f;
  --sig-watch-bear:#5aaa77;
  --sig-sell:#2d9e5a;
  --sig-strong-sell:#1a6b3a;
  /* 籌碼買賣超與訊號色現在是同一套慣例，指過去避免兩邊各改各的 */
  --chip-buy:var(--sig-buy);
  --chip-sell:var(--sig-sell);
  --tab-h:60px;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg:#0f1513;
    --surface:#171f1c;
    --surface-2:#1f2926;
    --surface-3:#141b19;
    --text:#e7ebe8;
    --text-dim:#98a49e;
    --text-faint:#6d7a74;
    --border:rgba(231,235,232,.1);
    --border-strong:rgba(231,235,232,.19);
    --accent:#4aa96f;
    --accent-soft:#18291f;
    --on-accent:#08110c;
    --danger:#e06a5f;
    --danger-soft:#2a1a18;
    --on-danger:#1c0a08;          /* 深字配提亮的紅，5.83:1 */
    --warn:#d1a24f;
    --shadow:0 1px 2px rgba(0,0,0,.4), 0 12px 32px -18px rgba(0,0,0,.8);
    /* 深色底同樣走台股慣例：紅=看多、綠=看空 */
    --sig-strong-buy:#e0574a;
    --sig-buy:#e06a5f;
    --sig-watch-bull:#d98b80;
    --sig-neutral:#d1a24f;
    --sig-watch-bear:#7cc198;
    --sig-sell:#5cb87f;
    --sig-strong-sell:#4aa96f;
    --chip-buy:var(--sig-buy);
    --chip-sell:var(--sig-sell);
  }
}

*{box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
html,body{margin:0;padding:0;height:100%;}
body{
  background:var(--bg);
  color:var(--text);
  font-family:"Noto Sans TC","PingFang TC","Microsoft JhengHei",-apple-system,sans-serif;
  font-size:15px;
  line-height:1.6;
  overscroll-behavior-y:none;
}
button{font-family:inherit;color:inherit;}
.mono,.num{font-family:"IBM Plex Mono",ui-monospace,monospace;font-variant-numeric:tabular-nums;}
[hidden]{display:none !important;}

/* ── 訊號色（用 data-signal 掛，深淺色各一套）────────────────────── */
[data-signal="STRONG_BUY"]{--sig:var(--sig-strong-buy);}
[data-signal="BUY"]{--sig:var(--sig-buy);}
[data-signal="WATCH_BULL"]{--sig:var(--sig-watch-bull);}
[data-signal="NEUTRAL"]{--sig:var(--sig-neutral);}
[data-signal="WATCH_BEAR"]{--sig:var(--sig-watch-bear);}
[data-signal="SELL"]{--sig:var(--sig-sell);}
[data-signal="STRONG_SELL"]{--sig:var(--sig-strong-sell);}

/* ══ 認證 ═══════════════════════════════════════════════════════════ */
.auth-wrap{
  min-height:100dvh;display:flex;align-items:center;justify-content:center;
  padding:24px 20px calc(24px + env(safe-area-inset-bottom));
}

/* 登入卡＝走勢圖橫幅（.auth-hero）+ 表單本體（.auth-card）合成一個物件，
   共用一個 radius/陰影，中間不留縫，看起來是同一張卡片而非兩塊拼接。 */
.auth-card-group{
  width:100%;max-width:380px;border-radius:20px;overflow:hidden;
  box-shadow:var(--shadow);border:1px solid var(--border);
}
.auth-hero{
  height:132px;
  background:linear-gradient(180deg, var(--accent-soft) 0%, var(--surface) 100%);
}
.auth-hero svg{width:100%;height:100%;display:block;}
/* 純裝飾用蠟燭圖紋理，內容由 app.js 的 renderAuthBackdrop() 產生。
   顏色沿用籌碼圖已經建立的台股慣例（紅漲綠跌），不另立第二套語言。 */
.auth-hero .backdrop-up{fill:var(--chip-buy);stroke:var(--chip-buy);}
.auth-hero .backdrop-down{fill:var(--chip-sell);stroke:var(--chip-sell);}
.auth-hero rect{opacity:.6;}
.auth-hero line{stroke-width:2;opacity:.45;}

.auth-card{width:100%;background:var(--surface);padding:28px 26px 32px;}
.brand{display:flex;align-items:center;gap:12px;margin-bottom:28px;}
.brand-mark{width:34px;height:34px;color:var(--accent);flex:none;}
.brand h1{font-size:23px;margin:0;letter-spacing:-.01em;}
.brand-sub{margin:0;font-size:12px;color:var(--text-faint);
  font-family:"IBM Plex Mono",monospace;letter-spacing:.04em;}

.auth-form{display:flex;flex-direction:column;gap:16px;}
.field{display:flex;flex-direction:column;gap:6px;}
.field>span{font-size:13px;color:var(--text-dim);font-weight:500;}
.field input{
  width:100%;padding:13px 14px;font-size:16px; /* 16px 以下 iOS 會自動放大頁面 */
  background:var(--surface);color:var(--text);
  border:1px solid var(--border-strong);border-radius:10px;
  font-family:inherit;transition:border-color .15s;
}
.field input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft);}
.code-input{
  font-family:"IBM Plex Mono",monospace;font-size:26px !important;
  letter-spacing:.4em;text-align:center;padding:14px 0 !important;
}
.hint{font-size:12px;color:var(--text-faint);}

/* 圖形驗證碼：圖片本身是後端畫的 SVG，寫死淺色配色（獨立文件，吃不到頁面的
   CSS variable）。這裡刻意包一層明確的白底卡片框，讓它在深色模式下看起來像
   「插入的一張圖」而不是「沒跟上深色模式的破圖」。 */
.captcha-row{display:flex;align-items:center;gap:10px;}
.captcha-img{
  height:56px;border-radius:8px;background:#f4f3ee;
  border:1px solid var(--border-strong);flex:none;
}
.captcha-refresh{
  width:40px;height:40px;flex:none;display:grid;place-items:center;
  background:var(--surface-2);border:1px solid var(--border-strong);border-radius:8px;
  color:var(--text-dim);font-size:18px;line-height:1;cursor:pointer;
}
.captcha-refresh:active{background:var(--border);}

.btn{
  padding:14px 18px;border-radius:10px;border:1px solid transparent;
  font-size:15px;font-weight:500;cursor:pointer;transition:opacity .15s,transform .1s;
}
.btn:active{transform:scale(.99);}
.btn:disabled{opacity:.55;cursor:default;}
.btn-primary{background:var(--accent);color:var(--on-accent);}
/* 刪除帳號這類不可逆動作：先用外框版（btn-danger-soft）當入口——夠顯眼但不像
   一顆等著被誤觸的紅按鈕；真正送出那一步才用實心版，讓「這是最後一步」看得出來。 */
.btn-danger{background:var(--danger);color:var(--on-danger);}
.btn-danger-soft{
  background:var(--danger-soft);color:var(--danger);
  border-color:var(--danger);
}
.link{background:none;border:none;padding:0;color:var(--accent);
  font-size:inherit;cursor:pointer;text-decoration:underline;text-underline-offset:2px;}
.auth-switch{margin:0;text-align:center;font-size:13.5px;color:var(--text-dim);}
/* 自選股加密的告知。⚠ 用 --warn 而不是 --danger：這不是錯誤，是使用者
   需要在按下去之前知道的後果。紅色會讓人以為自己做錯了什麼。 */
.auth-hint-warn{
  margin:14px 0 0;padding:11px 13px;border-radius:9px;font-size:13px;line-height:1.7;
  background:var(--surface-2);color:var(--text-dim);
  border:1px solid var(--border);border-left:3px solid var(--warn);
}
.auth-hint-warn b{color:var(--text);}
.auth-msg{
  margin:16px 0 0;padding:12px 14px;border-radius:9px;font-size:13.5px;
  background:var(--accent-soft);color:var(--text);border:1px solid var(--border);
}
.auth-msg.is-error{background:var(--danger-soft);border-color:var(--danger);color:var(--danger);}
.verify-lead{margin:0;font-size:14px;color:var(--text-dim);line-height:1.7;}
.verify-lead b{color:var(--text);font-family:"IBM Plex Mono",monospace;font-size:13.5px;}
.disclaimer-mini{margin:24px 0 0;font-size:12px;color:var(--text-dim);text-align:center;}

/* ══ App bar / tabs ═════════════════════════════════════════════════ */
.app-bar{
  position:sticky;top:0;z-index:20;
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:calc(12px + env(safe-area-inset-top)) 18px 12px;
  background:color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter:blur(12px);border-bottom:1px solid var(--border);
}
.app-bar-title{display:flex;align-items:baseline;gap:10px;min-width:0;}
/* 帳號＋登出兩顆要黏在一起：直接當 .app-bar 的子元素會被 space-between
   拆成「標題｜帳號｜登出」三段散在整條上。 */
.app-bar-actions{display:flex;align-items:center;gap:2px;flex:none;}
.app-bar h1{font-size:19px;margin:0;white-space:nowrap;}
.as-of{font-family:"IBM Plex Mono",monospace;font-size:11.5px;color:var(--text-faint);}
.icon-btn{
  width:38px;height:38px;flex:none;display:grid;place-items:center;
  background:none;border:none;border-radius:9px;cursor:pointer;color:var(--text-dim);
}
.icon-btn:active{background:var(--surface-2);}
.icon-btn svg{width:21px;height:21px;}
.icon-btn.is-on{color:var(--accent);}
.icon-btn.is-on svg path{fill:currentColor;}

/* 下拉重新整理：高度由 JS 直接改 inline style 跟著手指走，是否要「彈簧」回彈
   或收合用 .is-settling 這個 class 切換 transition 開關——拖曳中要跟手，
   放開瞬間才要動畫，兩者共用同一個 height 屬性會打架，所以拆成兩態。 */
.pull-indicator{
  height:0;overflow:hidden;display:flex;align-items:center;justify-content:center;
  color:var(--text-faint);position:sticky;top:0;z-index:19;background:var(--bg);
}
.pull-indicator.is-settling{transition:height .2s ease-out;}
.pull-indicator svg{width:20px;height:20px;}
.pull-indicator.is-ready{color:var(--accent);}
.pull-indicator.is-ready svg{transform:rotate(180deg);}
.pull-indicator.is-loading svg{animation:pull-spin .7s linear infinite;}
@keyframes pull-spin{to{transform:rotate(360deg);}}
@media (prefers-reduced-motion:reduce){.pull-indicator.is-loading svg{animation:none;}}

main{padding:14px 16px calc(var(--tab-h) + 28px + env(safe-area-inset-bottom));}

.tab-bar{
  position:fixed;left:0;right:0;bottom:0;z-index:20;
  display:grid;grid-template-columns:repeat(3,1fr);
  background:color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter:blur(12px);border-top:1px solid var(--border);
  padding-bottom:env(safe-area-inset-bottom);
}
.tab-btn{
  height:var(--tab-h);display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:3px;background:none;border:none;cursor:pointer;
  color:var(--text-faint);font-size:11px;
}
.tab-btn svg{width:22px;height:22px;}
.tab-btn.is-active{color:var(--accent);}

/* ══ 清單 ═══════════════════════════════════════════════════════════ */
.stock-list{display:flex;flex-direction:column;gap:8px;}
.stock-row{
  display:grid;grid-template-columns:auto 1fr auto auto;gap:12px;align-items:center;
  width:100%;padding:13px 15px;text-align:left;cursor:pointer;
  background:var(--surface);border:1px solid var(--border);border-radius:12px;
}
.stock-row:active{background:var(--surface-2);}
.row-score{
  width:44px;height:44px;flex:none;display:grid;place-items:center;border-radius:11px;
  background:color-mix(in srgb, var(--sig) 13%, transparent);
  color:var(--sig);font-family:"IBM Plex Mono",monospace;
  font-weight:600;font-size:16px;font-variant-numeric:tabular-nums;
}
.row-main{min-width:0;}
.row-name{font-weight:500;font-size:15px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.row-meta{
  display:flex;gap:8px;align-items:center;font-size:11.5px;color:var(--text-faint);
  font-family:"IBM Plex Mono",monospace;
}
.row-sig{color:var(--sig);font-weight:500;font-family:"Noto Sans TC",sans-serif;}
.row-price{
  text-align:right;font-family:"IBM Plex Mono",monospace;
  font-variant-numeric:tabular-nums;font-size:15px;font-weight:500;
}
.row-price small{display:block;font-size:10.5px;color:var(--text-faint);font-weight:400;}
/* 當日漲跌幅：台股慣例紅漲綠跌，與迷你走勢圖、籌碼圖同一組 token。 */
.row-price small.chg-up{color:var(--chip-buy);}
.row-price small.chg-down{color:var(--chip-sell);}
/* 依籌碼排序時，每一列印出排序的依據。⚠ 「籌碼無資料」用 faint 而不是紅綠
   ——它不是一個方向，是沒有方向可講。 */
.row-price small.row-chip{margin-top:2px;}
.row-price small.row-chip.is-missing{color:var(--text-faint);font-style:italic;}

/* 清單迷你走勢圖：台股慣例紅漲綠跌，跟籌碼圖、登入頁橫幅同一組 token，
   不另立第三套方向色。空著（資料不足 2 個點）時就不佔版面。 */
.row-spark{width:44px;height:26px;flex:none;}
.row-spark.spark-up{color:var(--chip-buy);}
.row-spark.spark-down{color:var(--chip-sell);}

/* 篩選器（條件查詢）。訊號用可複選的 chip；市場/波動層級是互斥選項，
   用原生 <select> 而不是自己刻下拉選單——這是唯讀查詢工具，不需要客製化
   下拉選單的視覺投資，原生元件在無障礙與行動裝置上反而更順手。 */
.filter-bar{display:flex;flex-direction:column;gap:10px;margin-bottom:14px;}
.filter-chips{display:flex;gap:8px;flex-wrap:wrap;}
.chip{
  padding:7px 13px;border-radius:999px;font-size:12.5px;font-weight:500;
  background:var(--surface);border:1px solid var(--border-strong);
  color:var(--text-dim);cursor:pointer;transition:background .15s,color .15s,border-color .15s;
}
.chip.is-active{
  background:var(--accent-soft);border-color:var(--accent);color:var(--accent);
}
/* 全選／清除。長得跟訊號 chip 不一樣，免得被當成第八種訊號——它是動作，
   不是條件。⚠ 刻意不給 is-active 狀態：它沒有「被選中」這回事。 */
.chip-all{
  margin-left:auto;border-style:dashed;color:var(--text-faint);
}
.chip-all:hover{color:var(--accent);border-color:var(--accent);}
.filter-selects{display:flex;gap:8px;flex-wrap:wrap;}
.filter-selects select{
  /* 三個 select 在 400px 寬的手機上會太擠，所以給 min-width 讓它自然換行，
     而不是硬擠成三欄把選項文字截斷。 */
  flex:1 1 30%;min-width:104px;padding:9px 10px;font-size:13px;border-radius:9px;
  background:var(--surface);color:var(--text);border:1px solid var(--border-strong);
  font-family:inherit;
}

/* 「符合 388 檔，已顯示 20 檔」——清單被截斷時必須講出來。 */
.list-summary{
  margin:0 0 10px;font-size:12.5px;color:var(--text-faint);
  display:flex;gap:6px;align-items:baseline;
}
.list-summary b{color:var(--text-dim);font-weight:600;font-variant-numeric:tabular-nums;}

/* 依籌碼排序時的覆蓋率。⛔ 刻意**不**淡化成註腳灰：這行講的是「排在後面的
   那些是沒有資料，不是買超最少」，那是讀懂這份順序的前提，不是補充說明。
   用 warn 的左邊條與 .ev-warn 同一套語彙（那邊也是在講資料本身靠不住）。 */
.list-coverage{
  margin:0 0 12px;padding:8px 11px;border-radius:8px;
  font-size:11.5px;line-height:1.7;color:var(--text-dim);
  background:var(--surface-2);border-left:3px solid var(--warn);
}
.list-coverage b{color:var(--text);font-weight:600;font-variant-numeric:tabular-nums;}

.load-more{
  display:block;width:100%;margin-top:12px;padding:12px;
  font-size:13.5px;font-family:inherit;font-weight:500;
  background:var(--surface);color:var(--text-dim);
  border:1px solid var(--border-strong);border-radius:11px;cursor:pointer;
}
.load-more:hover:not(:disabled){border-color:var(--accent);color:var(--accent);}
.load-more:disabled{opacity:.55;cursor:default;}

.search-bar{margin-bottom:12px;}
.search-bar input{
  width:100%;padding:13px 15px;font-size:16px;background:var(--surface);
  color:var(--text);border:1px solid var(--border-strong);border-radius:11px;
  font-family:inherit;
}
.search-bar input:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft);}

.empty{
  padding:48px 24px;text-align:center;color:var(--text-faint);font-size:14px;line-height:1.8;
}

/* ══ 個股深度 ═══════════════════════════════════════════════════════ */
.detail{
  position:fixed;inset:0;z-index:40;background:var(--bg);
  display:flex;flex-direction:column;
  animation:slide-in .22s cubic-bezier(.32,.72,0,1);
}
@keyframes slide-in{from{transform:translateX(14px);opacity:0}to{transform:none;opacity:1}}
@media (prefers-reduced-motion:reduce){.detail{animation:none}}
.detail-bar{
  display:flex;align-items:center;gap:8px;flex:none;
  padding:calc(10px + env(safe-area-inset-top)) 12px 10px;
  border-bottom:1px solid var(--border);background:var(--bg);
}
.detail-bar-title{flex:1;min-width:0;display:flex;align-items:baseline;gap:8px;}
.detail-bar-title b{font-family:"IBM Plex Mono",monospace;font-size:15px;}
.detail-bar-title span{
  font-size:13.5px;color:var(--text-dim);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.detail-body{
  flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:16px 16px calc(28px + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;gap:14px;
}

/* 比較模式提示：點了「比較」後，去清單挑第二檔股票時的浮動提示條 */
.compare-banner{
  position:fixed;left:12px;right:12px;z-index:45;
  top:calc(12px + env(safe-area-inset-top));
  display:flex;align-items:center;gap:10px;
  padding:11px 14px;border-radius:12px;
  background:var(--accent);color:var(--bg);
  font-size:13.5px;font-weight:500;
  box-shadow:0 6px 20px rgba(0,0,0,.18);
}
.compare-banner span{flex:1;min-width:0;}
.compare-banner .link{color:var(--bg);text-decoration:underline;font-weight:600;flex:none;}

/* 兩檔比較 */
.cmp-header{display:flex;gap:10px;}
.cmp-head-col{
  flex:1;min-width:0;text-align:center;padding:12px 8px;border-radius:12px;
  background:color-mix(in srgb, var(--sig) 10%, var(--surface));
  border:1px solid color-mix(in srgb, var(--sig) 35%, var(--border));
}
.cmp-head-col b{display:block;font-family:"IBM Plex Mono",monospace;font-size:15px;}
.cmp-head-col span{display:block;font-size:12px;color:var(--text-dim);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.cmp-sig{margin-top:6px;font-size:12.5px;font-weight:600;color:var(--sig);}

.cmp-table{display:flex;flex-direction:column;border-top:1px solid var(--border);}
.cmp-row{
  display:grid;grid-template-columns:1fr 1fr 1fr;align-items:center;
  padding:10px 4px;border-bottom:1px solid var(--border);gap:4px;
}
.cmp-label{font-size:12.5px;color:var(--text-dim);}
.cmp-val{
  text-align:center;font-family:"IBM Plex Mono",monospace;font-size:13.5px;
  font-variant-numeric:tabular-nums;color:var(--text);
}
.cmp-val.cmp-better{color:var(--sig-strong-buy);font-weight:600;}

/* 決策卡 */
.verdict-card{
  border-radius:16px;padding:18px;
  background:linear-gradient(160deg,
    color-mix(in srgb, var(--sig) 12%, var(--surface)), var(--surface) 62%);
  border:1px solid color-mix(in srgb, var(--sig) 32%, transparent);
}
.verdict-top{display:flex;justify-content:space-between;align-items:flex-start;gap:14px;}
.verdict-sig{
  font-size:16px;font-weight:700;color:var(--sig);letter-spacing:-.01em;
}
.verdict-score{
  font-family:"IBM Plex Mono",monospace;font-size:42px;font-weight:600;
  color:var(--sig);line-height:1.05;font-variant-numeric:tabular-nums;
}
.verdict-score small{font-size:16px;color:var(--text-faint);font-weight:400;}
/* 總分的母體。⚠ 這一列是那個 42px 數字唯一的基準，不要因為它「只是小字」
   就在窄畫面收掉——收掉之後畫面上就只剩一個沒有刻度的分數。 */
.verdict-rank{
  margin-top:4px;font-size:11.5px;color:var(--text-faint);
  font-family:"IBM Plex Mono",monospace;line-height:1.5;
}
.verdict-rank span{
  margin-left:8px;padding-left:8px;border-left:1px solid var(--border);
  color:var(--text-dim);
}
.verdict-tags{display:flex;flex-direction:column;align-items:flex-end;gap:5px;}
.tag{
  font-size:11px;padding:3px 9px;border-radius:20px;white-space:nowrap;
  background:var(--surface-2);color:var(--text-dim);
  border:1px solid var(--border);
  font-family:inherit;line-height:1.6;   /* button 預設字體不是繼承來的 */
}
/* 波動層級／大盤環境那兩個 tag 是 <button>（點了開名詞說明），
   其餘仍是 <span>。兩者外觀要一樣，只有游標不同。 */
button.tag{cursor:pointer;}
button.tag:active{background:var(--border);}
.tag.tag-accent{background:color-mix(in srgb, var(--sig) 14%, transparent);
  color:var(--sig);border-color:color-mix(in srgb, var(--sig) 30%, transparent);}
/* B1：注意股／處置股徽章。⚠ 用 --danger／--warn，不是 --sig-* ——這不是
   漲跌方向，是主管機關的列管狀態，不該套用紅漲綠跌那套語意。 */
.tag.tag-danger{background:var(--danger-soft);color:var(--danger);border-color:var(--danger);}
.tag.tag-warn{background:color-mix(in srgb, var(--warn) 16%, transparent);
  color:var(--warn);border-color:color-mix(in srgb, var(--warn) 40%, transparent);}

/* 四個面向的分項長條 */
.breakdown-head{
  display:flex;align-items:center;gap:2px;
  font-size:12px;color:var(--text-dim);margin-top:16px;
}
.breakdown{display:flex;flex-direction:column;gap:9px;margin-top:8px;}
.dim{display:grid;grid-template-columns:74px 1fr 58px;gap:10px;align-items:center;}
.dim-name{font-size:12px;color:var(--text-dim);}
.dim-track{height:6px;border-radius:3px;background:var(--surface-2);overflow:hidden;}
.dim-fill{height:100%;border-radius:3px;background:var(--sig);}
.dim-val{
  font-family:"IBM Plex Mono",monospace;font-size:12px;text-align:right;
  color:var(--text-dim);font-variant-numeric:tabular-nums;
}

/* 卡片外殼 */
.card{
  background:var(--surface);border:1px solid var(--border);
  border-radius:14px;padding:16px;
}
.card-title{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  font-size:13px;font-weight:500;color:var(--text-dim);margin-bottom:14px;
}
.card-title .aside{font-size:11px;color:var(--text-faint);
  font-family:"IBM Plex Mono",monospace;}

/* 交易計畫階梯——這頁最主要的視覺，價位按 ATR 實際距離排列 */
.ladder{display:flex;flex-direction:column;gap:0;}
.rung{
  display:grid;grid-template-columns:1fr auto;gap:12px;align-items:center;
  padding:9px 0;border-bottom:1px dashed var(--border);
}
.rung:last-child{border-bottom:none;}
.rung-label{display:flex;align-items:center;gap:9px;font-size:13px;}
.rung-dot{width:8px;height:8px;border-radius:50%;flex:none;}
.rung-note{font-size:11px;color:var(--text-faint);}
.rung-val{
  font-family:"IBM Plex Mono",monospace;font-size:16px;font-weight:500;
  font-variant-numeric:tabular-nums;text-align:right;
}
.rung-val small{display:block;font-size:10.5px;color:var(--text-faint);font-weight:400;}
.rung.is-target .rung-dot{background:var(--sig-buy);}
.rung.is-entry .rung-dot{background:var(--accent);}
/* 停損是「往下」的價位 → 台股慣例用綠，不是 --danger 的紅。
   --danger 保留給真正的錯誤訊息（登入失敗那類），那不是漲跌語意。 */
.rung.is-stop .rung-dot{background:var(--sig-sell);}
.rung.is-entry .rung-val{color:var(--accent);}
.rung.is-stop .rung-val{color:var(--sig-sell);}
/* 四層裡唯一描述風險的那層要在階梯內部也搶得到視線。只加粗，不改順序
   ——階梯是價格軸（見 app.js 那段註解）。 */
.rung.is-primary .rung-label{font-weight:600;color:var(--text);}
.rung.is-primary .rung-val{font-size:18px;font-weight:600;}
.rung.is-primary .rung-dot{width:10px;height:10px;}

/* 退場摘要，排在階梯**上方**。⛔ 這裡放的是「距離」不是價位：價位由下面的
   階梯負責（那是幾何），這一條負責的是「跌到哪要認、上下距離差多少」。 */
.risk-first{
  display:flex;justify-content:space-between;align-items:baseline;gap:14px;
  flex-wrap:wrap;
  margin-bottom:14px;padding-bottom:12px;
  border-bottom:1px solid var(--border);
}
.risk-first span{font-size:12px;color:var(--text-dim);}
.risk-main{display:flex;align-items:baseline;gap:10px;}
.risk-main b{
  font-family:"IBM Plex Mono",monospace;font-size:24px;font-weight:600;
  color:var(--sig-sell);font-variant-numeric:tabular-nums;line-height:1.1;
}
.risk-side{display:flex;align-items:baseline;gap:8px;}
.risk-side b{
  font-family:"IBM Plex Mono",monospace;font-size:15px;color:var(--text);
  font-variant-numeric:tabular-nums;
}

/* 圖表 */
.chart-wrap{margin:-4px -4px 0;}
.chart-wrap svg{display:block;width:100%;height:auto;}
.chart-legend{
  display:flex;gap:14px;justify-content:flex-end;flex-wrap:wrap;margin-top:6px;
  font-size:10.5px;color:var(--text-faint);font-family:"IBM Plex Mono",monospace;
}
.chart-legend span{display:inline-flex;align-items:center;gap:5px;}
/* 圖例的色塊。兩條線同時在圖上時，名字對不到顏色等於沒有圖例。 */
.chart-legend .lg-dot{
  width:9px;height:2.5px;border-radius:2px;flex:none;
}
.chart-legend .lg-dot-score{background:var(--text-dim);}
/* 均線圖例。跟 SVG 裡畫的三條線用同一組（灰階＋不同透明度），不另立色票
   ——理由見 renderChart() 那段註解：均線是背景參考，彩色會被誤讀成方向判斷。 */
.chart-legend .lg-dot-ema20{background:var(--text);opacity:.5;}
.chart-legend .lg-dot-ema60{background:var(--text);opacity:.32;}
.chart-legend .lg-dot-ema120{background:var(--text);opacity:.2;}
/* 疊圖的買/賣超色塊，沿用籌碼柱狀圖同一組 token（紅買綠賣），不另立第二套。 */
.chart-legend .lg-dot-buy{background:var(--chip-buy);}
.chart-legend .lg-dot-sell{background:var(--chip-sell);}
/* 漲跌幅照台股慣例紅漲綠跌，與迷你走勢圖、籌碼圖同一組 token。 */
.chart-legend .lg-up,.chart-change .lg-up{color:var(--chip-buy);font-weight:600;}
.chart-legend .lg-down,.chart-change .lg-down{color:var(--chip-sell);font-weight:600;}

/* 期間漲跌幅 ＋ 大盤基準。自成一列而不是擠在圖例裡——「哪條線是哪個」與
   「這段期間漲了多少、比大盤好不好」是兩件事，混在同一行會兩個都難讀。 */
.chart-change{
  display:flex;gap:10px;flex-wrap:wrap;align-items:baseline;margin-top:5px;
  font-size:10.5px;color:var(--text-faint);font-family:"IBM Plex Mono",monospace;
}
.chart-change .cc-period{
  padding:1px 6px;border-radius:99px;background:var(--surface-2,rgba(128,128,128,.12));
  color:var(--text-dim);
}
.chart-change .cc-rel{margin-left:auto;}

/* 法人籌碼（看盤參考，未進評分）——台股慣例：紅=買超、綠=賣超 */
.chip-bar-buy{fill:var(--chip-buy);}
.chip-bar-sell{fill:var(--chip-sell);}
.chip-axis{stroke:var(--border-strong);stroke-width:1;}
.chip-x{
  font-family:"IBM Plex Mono",monospace;font-size:9px;fill:var(--text-faint);
}
.chip-y{
  font-family:"Noto Sans TC",sans-serif;font-size:9.5px;fill:var(--text-faint);
}
.kv-row b.is-chip-buy{color:var(--chip-buy);}
.kv-row b.is-chip-sell{color:var(--chip-sell);}
.chip-chart-label{
  font-size:11px;color:var(--text-faint);letter-spacing:.02em;margin-bottom:2px;
}
/* 兩張圖各自縮放，這個峰值標籤就是它們的刻度說明，不能省 */
.chip-peak{
  font-family:"IBM Plex Mono",monospace;font-size:9px;fill:var(--text-faint);
}

/* 統計格 */
.stat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;}
.stat{display:flex;flex-direction:column;gap:2px;min-width:0;}
.stat-label{font-size:11px;color:var(--text-faint);}
.stat-val{
  font-family:"IBM Plex Mono",monospace;font-size:17px;font-weight:500;
  font-variant-numeric:tabular-nums;
}
/* ⛔2026-09-15：is-good / is-bad 停用，不再套在勝率上。
   把 62% 塗紅（賺）、48% 塗綠（賠），是在替使用者判斷「這個數字好不好」——
   那是意見不是資料，跟把 STRONG_BUY 改成陳述式標籤是同一件事，當時漏掉了。
   數字照實顯示，好壞由讀的人自己決定。
   ⚠ 兩條規則留著但沒有任何地方在用，是為了讓「為什麼沒有顏色」有跡可循；
     真的要刪的話連同這段註解一起刪，不要只刪規則留下一個沒來由的空白。 */
.stat-sub{font-size:10.5px;color:var(--text-faint);}

.kv{display:flex;flex-direction:column;gap:9px;}
.kv-row{display:flex;justify-content:space-between;align-items:baseline;gap:12px;font-size:13.5px;}
.kv-row span{color:var(--text-dim);}
.kv-row b{font-family:"IBM Plex Mono",monospace;font-weight:500;font-variant-numeric:tabular-nums;}

.note{
  font-size:12px;color:var(--text-dim);line-height:1.7;
  background:var(--surface-3);border-left:2px solid var(--border-strong);
  padding:10px 12px;border-radius:0 8px 8px 0;
}
.note.is-warn{border-left-color:var(--warn);}
.note.is-danger{border-left-color:var(--danger);}

/* ══ 帳號 ═══════════════════════════════════════════════════════════ */
.card-danger{border-color:var(--danger);}
/* 卡片裡的東西本來是靠 .card 的 padding 疊著，這裡要自己排間距 */
.card-danger .note{margin-bottom:14px;}
.card-danger .btn{width:100%;}
.delete-form{display:flex;flex-direction:column;gap:14px;margin-top:14px;}
.delete-form .link{align-self:center;color:var(--text-dim);}
/* ⛔ 免責聲明一律用 --text-dim，**不要**改回 --text-faint。這是法定揭露，
   要求是「顯著」，而 --text-faint 在淺色底只有 2.78:1、深色底 4.07:1，
   兩邊都低於 WCAG AA 的 4.5:1 —— 那樣的灰是設計來被略過的，不是拿來揭露的。
   --text-dim 實測：淺色 5.00:1（#5f6b66 on #f4f3ee）、深色 7.06:1。
   tests/test_api.py 有一項直接從這支 CSS 算對比度把關，改壞會紅。 */
.disclaimer{
  font-size:12px;color:var(--text-dim);line-height:1.7;
  padding:4px 2px 0;text-align:center;
}
/* 三個清單頁共用的那一份：跟在 <main> 尾端，用一條分隔線跟清單切開，
   讓它讀起來是頁面的註腳而不是最後一列資料。 */
.disclaimer-bar{
  margin:18px 0 0;padding-top:14px;border-top:1px solid var(--border);
}

/* ══ 條款同意閘門 ═══════════════════════════════════════════════════ */
/* 沿用 .detail 的覆蓋層，但要蓋在個股頁之上——沒同意就不該還能看到資料 */
#terms-gate{z-index:50;}
.gate-body{justify-content:center;}
.gate-lead{margin:0;font-size:14px;line-height:1.8;color:var(--text-dim);}

/* ══ 名詞說明：ⓘ 與底板 ═══════════════════════════════════════════════ */
.info-btn{
  background:none;border:none;padding:0 2px;margin-left:3px;
  color:var(--text-faint);cursor:pointer;line-height:1;
  font-size:13px;vertical-align:baseline;
}
.info-btn:active{color:var(--accent);}
/* 圖示只有 13px，手指點不到（建議的最小觸控範圍是 44px，這裡取 30px 折衷）。
   用 ::after 撐開可點範圍，而不是加 padding——padding 會把旁邊的文字推開，
   ::after 是絕對定位的覆蓋層，不佔版面空間。 */
.info-btn{position:relative;}
.info-btn::after{
  content:"";position:absolute;top:50%;left:50%;
  width:30px;height:30px;transform:translate(-50%,-50%);
}

/* 底板用 flex 置中，不要用 left/right/transform 去橋。
   ⛔ 原本寫成 `left:0;right:0` 再在斷點裡蓋成 `left:50%;transform:translateX(-50%)`，
   三個毛病疊在一起：
   ① left+right+max-width 是過度約束，right 被丟掉，位置靠 transform 硬橋；
   ② 斷點寫 600px，App 本體是 620px——中間那 20px 會錯開；
   ③ 動畫的 to{transform:none} 在播放期間會把 translateX(-50%) 蓋掉，
      底板先偏一邊再跳回中間。
   flex 置中沒有這些問題：panel 身上完全沒有版面用的 transform，
   動畫要怎麼動都不會影響定位。 */
.sheet{
  position:fixed;inset:0;z-index:70;
  display:flex;align-items:flex-end;justify-content:center;
}
/* ⚠ 這行不能少。上面的 display:flex 會蓋掉 [hidden] 自帶的 display:none，
   少了它底板會永遠開著——而且是「一載入就蓋住整個畫面」那種壞法。 */
.sheet[hidden]{display:none;}
.sheet-backdrop{position:absolute;inset:0;background:rgba(0,0,0,.42);}
.sheet-panel{
  position:relative;                 /* 疊在 backdrop 之上 */
  width:100%;max-width:560px;
  max-height:80dvh;overflow-y:auto;
  background:var(--surface);
  border-radius:18px 18px 0 0;
  border:1px solid var(--border);border-bottom:none;
  padding:10px 20px calc(22px + env(safe-area-inset-bottom));
  box-shadow:0 -8px 40px -12px rgba(0,0,0,.45);
  animation:sheet-up .22s cubic-bezier(.32,.72,0,1);
}
@keyframes sheet-up{from{transform:translateY(16px);opacity:0}to{transform:none;opacity:1}}
@media (prefers-reduced-motion:reduce){.sheet-panel{animation:none}}
.sheet-grip{
  width:36px;height:4px;border-radius:2px;background:var(--border-strong);
  margin:0 auto 14px;
}
.sheet-panel h2{font-size:16px;margin:0 0 10px;}
.sheet-body{font-size:14px;line-height:1.85;color:var(--text-dim);}
.sheet-body b{color:var(--text);}
.sheet-body ul{margin:8px 0;padding-left:1.25em;}
.sheet-body li{margin-bottom:7px;}
.btn-quiet{
  width:100%;margin-top:18px;
  background:var(--surface-2);color:var(--text);border-color:var(--border);
}

/* ══ 條款／隱私權文件頁 ═══════════════════════════════════════════════
   privacy.html 與 terms.html 是獨立的靜態頁（沒有任何 JS），但共用這支 CSS，
   顏色與深色模式才不會跟 App 本體各走各的。 */
.doc-bar{
  position:sticky;top:0;z-index:10;
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:calc(12px + env(safe-area-inset-top)) 18px 12px;
  background:color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter:blur(12px);border-bottom:1px solid var(--border);
  font-size:14px;
}
.doc-back,.doc-link{color:var(--accent);text-decoration:none;}
.doc-back:hover,.doc-link:hover{text-decoration:underline;text-underline-offset:2px;}
.doc{
  max-width:680px;margin:0 auto;
  padding:20px 18px calc(48px + env(safe-area-inset-bottom));
  line-height:1.85;
}
.doc h1{font-size:24px;margin:8px 0 4px;letter-spacing:-.01em;}
.doc h2{
  font-size:16px;margin:32px 0 10px;padding-top:18px;
  border-top:1px solid var(--border);
}
/* 「這不是投資建議」那一節是整份條款的重點，不該跟其他條目長得一樣 */
.doc h2.doc-h2-strong{color:var(--danger);border-top-color:var(--danger);}
.doc p{margin:0 0 12px;}
.doc ul{margin:0 0 12px;padding-left:1.3em;}
.doc li{margin-bottom:8px;}
.doc-meta{
  font-size:12.5px;color:var(--text-dim);
  font-family:"IBM Plex Mono",monospace;margin-bottom:20px !important;
}
.doc-dim{color:var(--text-dim);font-size:12.5px;}
.doc-note{
  font-size:13.5px;color:var(--text-dim);
  background:var(--surface-3);border-left:2px solid var(--border-strong);
  padding:12px 14px;border-radius:0 8px 8px 0;
}
/* 還沒填的欄位要刺眼。這東西被連同網址一起公開出去，就是一份法律上不完整的
   文件——低調的灰色提示一定會被滑過去。 */
.doc-todo{
  font-size:13.5px;line-height:1.9;
  background:var(--danger-soft);color:var(--text);
  border:1px solid var(--danger);border-radius:10px;padding:14px 16px;
}
/* 表格在窄螢幕一定會超出寬度，讓它自己橫捲，不要把整頁撐開 */
.doc-table-wrap{overflow-x:auto;margin:0 0 12px;}
.doc-table{border-collapse:collapse;width:100%;min-width:420px;font-size:13.5px;}
.doc-table th,.doc-table td{
  border:1px solid var(--border);padding:9px 11px;
  text-align:left;vertical-align:top;line-height:1.7;
}
.doc-table th{background:var(--surface-2);font-weight:500;color:var(--text-dim);}
.doc-foot{margin-top:36px;padding-top:18px;border-top:1px solid var(--border);
  text-align:center;font-size:13.5px;}

/* ══ 註冊時的同意勾選 ═════════════════════════════════════════════════ */
.field-consent{
  display:flex;align-items:flex-start;gap:10px;
  font-size:13px;line-height:1.7;color:var(--text-dim);cursor:pointer;
}
/* 勾選框不要縮成一條線，手指也要點得到 */
.field-consent input{
  width:20px;height:20px;flex:none;margin:1px 0 0;accent-color:var(--accent);
}

/* Toast */
.toast{
  position:fixed;left:50%;bottom:calc(var(--tab-h) + 22px + env(safe-area-inset-bottom));
  transform:translateX(-50%);z-index:60;
  background:var(--text);color:var(--bg);
  padding:11px 18px;border-radius:22px;font-size:13.5px;
  box-shadow:var(--shadow);animation:toast-in .2s ease;
  max-width:calc(100vw - 40px);text-align:center;
}
@keyframes toast-in{from{opacity:0;transform:translate(-50%,8px)}to{opacity:1;transform:translate(-50%,0)}}

.skeleton{
  height:76px;border-radius:12px;background:var(--surface);
  border:1px solid var(--border);opacity:.6;
}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}

/* 桌機瀏覽器開起來時收窄成一支手機的寬度，不要讓一列股票拉成整個螢幕寬 */
@media (min-width:620px){
  .app-bar,main,.detail-bar,.detail-body{
    max-width:560px;margin-left:auto;margin-right:auto;
  }
  .tab-bar{max-width:560px;left:50%;transform:translateX(-50%);
    border-left:1px solid var(--border);border-right:1px solid var(--border);}
  .detail{max-width:560px;left:50%;transform:translateX(-50%);
    border-left:1px solid var(--border);border-right:1px solid var(--border);}
  @keyframes slide-in{from{opacity:0}to{opacity:1}}
}


/* ── 投顧版法定揭露（頁尾）────────────────────────────────────────────
   《證券投資顧問事業管理規則》要求為推廣業務製發的文件列明公司登記名稱、
   地址、電話與營業執照字號。刻意做得乾淨而不是縮成一行灰字——在投顧語境下
   這塊是信任訊號，不是要藏起來的免責聲明。 */
.partner-disclosure{
  margin:18px 0 0;padding:14px 16px;border-top:1px solid var(--border);
  font-size:11.5px;line-height:1.75;color:var(--text-faint);
}
.partner-disclosure .disclosure-name{
  font-size:12.5px;font-weight:600;color:var(--text-dim);margin-bottom:2px;
}
.partner-disclosure .disclosure-credit{margin-top:6px;opacity:.7;}
/* 欄位沒填時的紅框。**不要讓它安靜消失**——空白的法定揭露是一份法律上
   不完整的文件，而看起來沒事是最糟的壞法。 */
.partner-disclosure .disclosure-todo{
  margin-bottom:10px;padding:10px 12px;border-radius:9px;
  background:var(--danger-soft, rgba(220,38,38,.08));
  border:1px solid var(--danger, #dc2626);color:var(--danger, #dc2626);
  font-size:12px;line-height:1.7;
}
.auth-msg.is-ok{color:var(--sig-buy);}


/* ── 表單：select 與 textarea 跟 input 同一套外觀 ─────────────────────── */
.field select,.field textarea{
  width:100%;padding:13px 14px;font-size:16px; /* 16px 以下 iOS 會自動放大頁面 */
  background:var(--surface);color:var(--text);
  border:1px solid var(--border-strong);border-radius:10px;
  font-family:inherit;transition:border-color .15s;
}
.field textarea{resize:vertical;min-height:104px;line-height:1.65;}
.field select:focus,.field textarea:focus{outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px var(--accent-soft);}
.btn-block-link{display:block;text-align:center;text-decoration:none;margin-top:12px;}

/* ── 問題回饋 ─────────────────────────────────────────────────────── */
.feedback-form{display:flex;flex-direction:column;gap:12px;}
.feedback-mine-title{margin-top:20px;}
.fb-item{padding:12px 0;border-top:1px solid var(--border);}
.fb-item:first-child{border-top:none;}
.fb-head{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap;font-size:12px;}
.fb-status{padding:1px 8px;border-radius:99px;font-weight:600;font-size:11.5px;
  border:1px solid var(--border-strong);color:var(--text-dim);}
/* 狀態色只分「還沒好」與「好了」兩種，不做紅黃綠三色——使用者需要知道的是
   有沒有人在看，不是一個看起來很緊張的燈號。 */
.fb-status.fb-done{border-color:var(--accent);color:var(--accent);}
.fb-cat{color:var(--text-dim);}
.fb-date{margin-left:auto;color:var(--text-faint);font-family:"IBM Plex Mono",monospace;}
.fb-msg{margin-top:6px;font-size:13.5px;line-height:1.7;white-space:pre-wrap;word-break:break-word;}
.fb-reply{margin-top:8px;padding:10px 12px;border-radius:9px;background:var(--accent-soft);
  font-size:13.5px;line-height:1.7;white-space:pre-wrap;word-break:break-word;}
.fb-reply b{display:block;font-size:11.5px;color:var(--accent);margin-bottom:2px;}

/* ── 新手教學 ─────────────────────────────────────────────────────── */
.onboard{position:fixed;inset:0;z-index:60;display:flex;align-items:center;
  justify-content:center;padding:20px;background:rgba(0,0,0,.55);}
.onboard[hidden]{display:none;}
.onboard-card{width:100%;max-width:420px;background:var(--surface);
  border:1px solid var(--border);border-radius:16px;padding:22px 20px 16px;
  box-shadow:0 20px 60px rgba(0,0,0,.35);}
.onboard-step{font-size:11.5px;color:var(--text-faint);font-family:"IBM Plex Mono",monospace;}
.onboard-title{margin:6px 0 10px;font-size:19px;}
.onboard-body{font-size:14.5px;line-height:1.85;color:var(--text-dim);min-height:156px;}
.onboard-dots{display:flex;gap:6px;justify-content:center;margin:16px 0 14px;}
.onboard-dots i{width:6px;height:6px;border-radius:99px;background:var(--border-strong);
  transition:width .2s;}
.onboard-dots i.on{background:var(--accent);width:16px;}
.onboard-actions{display:flex;align-items:center;gap:8px;}
.onboard-spacer{flex:1;}
.ob-btn{padding:10px 16px;border-radius:10px;font:inherit;font-size:14px;cursor:pointer;
  border:1px solid var(--border-strong);background:transparent;color:var(--text-dim);}
.ob-btn.ob-primary{background:var(--accent);border-color:var(--accent);color:var(--bg);font-weight:600;}
.ob-btn[hidden],#onboard-skip[hidden]{display:none;}

/* ══ K 線型態 ═══════════════════════════════════════════════════════
   ⚠ 型態標籤**一律不著色**。把多方塗紅、空方塗綠會讓「今天出現這個形狀」
   讀成「這是好事／壞事」，而那是觀察到的事實，不是評價——跟訊號 chip
   不著色是同一條原則。方向用文字講，不用顏色講。 */
.pattern-row{display:flex;flex-wrap:wrap;gap:8px;}
.pattern-row .tag{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;padding:5px 11px;}
.pattern-dir{
  font-style:normal;font-size:10.5px;color:var(--text-faint);
  padding-left:6px;border-left:1px solid var(--border);
}

/* ══ 訊號變化 ═══════════════════════════════════════════════════════ */
.held-strip{
  display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;
  padding-bottom:12px;margin-bottom:12px;border-bottom:1px solid var(--border);
  font-size:12px;color:var(--text-dim);
}
.held-strip b{font-size:14px;color:var(--sig);}
.held-strip .held-days{
  margin-left:auto;font-family:"IBM Plex Mono",monospace;
  font-size:12px;color:var(--text);
}
.trans-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;}
.trans-item{
  display:grid;grid-template-columns:auto 1fr auto;gap:10px;align-items:baseline;
  padding:8px 0;border-bottom:1px dashed var(--border);font-size:12.5px;
}
.trans-item:last-child{border-bottom:none;}
.trans-date{font-family:"IBM Plex Mono",monospace;font-size:11.5px;color:var(--text-faint);}
.trans-move{color:var(--text);}
/* 箭頭是唯一帶方向語意的元素，照台股慣例：往多方走＝紅，往空方走＝綠。
   ⚠ 這裡的紅綠說的是「標籤往哪個方向動」，不是「好消息／壞消息」。 */
.trans-arrow{font-style:normal;font-weight:700;padding:0 2px;}
.trans-arrow.is-up{color:var(--chip-buy);}
.trans-arrow.is-down{color:var(--chip-sell);}
.trans-score{
  font-family:"IBM Plex Mono",monospace;font-size:11px;color:var(--text-faint);
  font-variant-numeric:tabular-nums;white-space:nowrap;
}
@media (max-width:360px){
  /* 窄畫面把分數那欄收掉——它是輔助資訊，擠成兩行反而讓日期與變化難讀。
     ⚠ 收的是分數不是日期：日期是「這件事什麼時候發生」，不能省。 */
  .trans-item{grid-template-columns:auto 1fr;}
  .trans-score{display:none;}
}

/* ══ 建議 1/3：資料日戳記與「這個數字怎麼來的」 ════════════════════
   ⚠ 戳記不可以因為窄畫面被收掉。這一頁上同時有五種不同的「現在」
   （籌碼 09-09、價格 09-16、基本面、上一季財報、2002 年起的回測），
   收掉戳記等於把其中四個講錯，而且看不出來。 */
.breakdown-head .bh-stamp{
  margin-left:auto;font-family:"IBM Plex Mono",monospace;
  font-size:10.5px;color:var(--text-faint);
}
.why{margin-top:12px;border-top:1px solid var(--border);padding-top:10px;}
.why summary{
  font-size:11.5px;color:var(--text-dim);cursor:pointer;list-style:none;
  display:inline-flex;align-items:center;gap:5px;
}
.why summary::-webkit-details-marker{display:none;}
.why summary::before{content:'▸';font-size:9px;transition:transform .15s;}
.why[open] summary::before{transform:rotate(90deg);}
.why-list{
  display:grid;grid-template-columns:auto 1fr;gap:5px 12px;
  margin:10px 0 0;font-size:11.5px;line-height:1.7;
}
.why-list dt{color:var(--text-faint);white-space:nowrap;}
.why-list dd{margin:0;color:var(--text-dim);}

/* 逐筆回測明細（A6）。跟 .why 一樣預設收起來，但 summary 用強一點的字級
   ——它不是註腳，是一份可以拿去驗上面那個勝率的資料。 */
.trades{margin-top:12px;border-top:1px solid var(--border);padding-top:10px;}
.trades summary{
  font-size:12.5px;color:var(--accent);cursor:pointer;list-style:none;
  display:inline-flex;align-items:center;gap:5px;font-weight:500;
}
.trades summary::-webkit-details-marker{display:none;}
.trades summary::before{content:'▸';font-size:9px;transition:transform .15s;}
.trades[open] summary::before{transform:rotate(90deg);}

/* ══ 建議 2：矛盾面板 ═══════════════════════════════════════════════
   ⚠ **整區不著色、不用警示樣式。** 這裡陳述的是「兩項方向不同」，
   不是「有風險」——籌碼那一條的回測結果甚至是反直覺的（法人賣壓最重的
   一成後續 20 日勝率反而略高）。做成紅色警告等於把沒驗證過的直覺
   變成一個看起來有根據的判斷。 */
.cf-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:12px;}
.cf-item{
  display:grid;grid-template-columns:1fr auto 1fr;gap:8px;align-items:center;
  padding:11px 12px;border-radius:10px;
  background:var(--surface-2);border:1px solid var(--border);
}
.cf-topic{grid-column:1/-1;font-size:11px;color:var(--text-faint);}
.cf-side{font-size:12.5px;line-height:1.5;}
.cf-side b{display:block;color:var(--text);font-weight:500;}
.cf-side i{
  font-style:normal;font-size:10px;color:var(--text-faint);
  font-family:"IBM Plex Mono",monospace;
}
.cf-vs{font-size:11px;color:var(--text-faint);white-space:nowrap;}
@media (max-width:400px){
  /* 窄畫面改成上下排。⚠ 「與」那一格要留著——沒有它，兩段文字會讀成一句話。 */
  .cf-item{grid-template-columns:1fr;}
  .cf-vs{text-align:left;}
}

/* ══ 建議 5：已知的未來事件 ════════════════════════════════════════ */
.ev-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px;}
.ev-item{display:grid;grid-template-columns:auto 1fr;gap:4px 12px;align-items:baseline;}
.ev-what{
  font-size:12px;color:var(--text-dim);padding:2px 9px;border-radius:20px;
  background:var(--surface-2);border:1px solid var(--border);white-space:nowrap;
}
.ev-when{font-family:"IBM Plex Mono",monospace;font-size:13px;color:var(--text);}
.ev-when i{
  font-style:normal;margin-left:8px;font-size:11px;color:var(--text-faint);
}
.ev-note{grid-column:2;font-size:11px;color:var(--text-faint);}
.ev-warn{
  font-size:11.5px;line-height:1.7;color:var(--text-dim);
  padding:9px 11px;border-radius:8px;
  background:var(--surface-2);border-left:3px solid var(--warn);
}

/* ══ 逐筆明細與財報表格（A6 / A9）══════════════════════════════════
   兩張表共用同一套。⚠ 一定要包在 .table-scroll 裡：手機寬度下欄位會超出
   螢幕，而**整頁不可以橫向捲動**——只有表格自己捲。 */
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;}
.mini-table{
  width:100%;border-collapse:collapse;font-size:12px;white-space:nowrap;
}
.mini-table th,.mini-table td{
  padding:6px 9px;text-align:left;border-bottom:1px solid var(--border);
}
.mini-table th{
  font-weight:500;color:var(--text-faint);font-size:11px;
  position:sticky;top:0;background:var(--surface);
}
.mini-table td.num,.mini-table th.num{text-align:right;}
.mini-table tbody tr:last-child td{border-bottom:none;}
/* 被資料邊界切斷的那幾筆。⛔ 不上紅色——它不是壞掉，是「還沒跑完」，
   用警示色會讓人以為那筆交易有問題。 */
.mini-table tr.is-censored td{background:var(--surface-2);}
.t-faint{color:var(--text-faint);}
.ev-past{margin-top:16px;padding-top:14px;border-top:1px solid var(--border);}
.ev-past-head{font-size:12.5px;font-weight:500;margin-bottom:9px;}

/* ══ B5：市場廣度（今天有多少檔在漲）══════════════════════════════
   ⚠ 漲跌色沿用 --chip-buy/--chip-sell（台股慣例紅漲綠跌），跟籌碼圖、
   迷你走勢圖同一組 token，不另立第四套方向色。 */
.bd-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-bottom:14px;}
.bd-stat{
  text-align:center;padding:10px 6px;border-radius:10px;background:var(--surface-2);
}
.bd-num{
  font-family:"IBM Plex Mono",monospace;font-variant-numeric:tabular-nums;
  font-size:22px;font-weight:600;line-height:1.1;
}
.bd-num.chg-up{color:var(--chip-buy);}
.bd-num.chg-down{color:var(--chip-sell);}
.bd-lab{font-size:11px;color:var(--text-faint);margin-top:4px;white-space:nowrap;}
/* 分歧長條：中線在正中央，往上是上漲家數、往下是下跌家數，共用同一個尺度。
   ⚠ 中線一定要看得見——沒有它，兩側的長度沒有共同的起點可以比。 */
.bd-chart{
  display:flex;align-items:center;gap:1px;height:96px;
  border-top:1px solid var(--border);border-bottom:1px solid var(--border);
  background:linear-gradient(var(--border),var(--border)) center/100% 1px no-repeat;
}
.bd-col{
  flex:1 1 0;min-width:0;height:100%;
  display:flex;flex-direction:column;justify-content:center;
}
.bd-up{background:var(--chip-buy);align-self:stretch;margin-top:auto;opacity:.85;}
.bd-dn{background:var(--chip-sell);align-self:stretch;margin-bottom:auto;opacity:.85;}
.bd-axis{
  display:flex;justify-content:space-between;margin-top:6px;
  font-family:"IBM Plex Mono",monospace;font-size:10.5px;color:var(--text-faint);
}
.t-warn{color:var(--warn);}

/* ══ 建議 6：自選股變化（裝置端比對）══════════════════════════════ */
.watch-changes{
  margin-bottom:14px;padding:13px 15px;border-radius:12px;
  background:var(--surface);border:1px solid var(--border);
}
.wc-head{font-size:13px;font-weight:500;margin-bottom:9px;}
.wc-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px;font-size:12.5px;}
.wc-list b{font-family:"IBM Plex Mono",monospace;}
.wc-move{color:var(--text-dim);font-size:11.5px;margin-left:6px;}
.wc-foot{
  margin-top:10px;padding-top:9px;border-top:1px solid var(--border);
  font-size:11px;line-height:1.7;color:var(--text-faint);
}

/* ══ 走勢圖期間切換（20/60/120/一年）══════════════════════════════
   ⚠ 沿用 .chip 的外觀（訊號篩選那組），因為它們是同一件事：使用者在選條件。
   停用態要看得出來**是資料不夠，不是壞掉**——所以只降對比、不變形，
   並且 title 會說出這檔實際有幾天。 */
.range-bar{display:flex;gap:7px;margin:2px 0 12px;flex-wrap:wrap;}
.range-chip{padding:5px 12px;font-size:12px;}
.range-chip:disabled{opacity:.38;cursor:not-allowed;}

/* K 線圖橫向捲動。⛔ 長期間的 K 線**不壓縮**——把 250 根擠進 340px 每根只有
   1.4px，開高低收一個都看不出來，而它看起來會像一張正常的 K 線圖。
   所以畫布跟著變寬，只有這一塊自己捲（同 .table-scroll 的原則：
   **整頁不可以橫向捲動**）。 */
.candle-scroll{
  overflow-x:auto;-webkit-overflow-scrolling:touch;
  /* 邊緣淡出，讓「還有東西在右邊」看得出來，而不是以為圖就到這裡 */
  mask-image:linear-gradient(90deg,transparent 0,#000 10px,#000 calc(100% - 10px),transparent 100%);
}
.candle-scroll svg{display:block;}

/* ══ 訊號轉折標記（畫在分數區）════════════════════════════════════
   ⛔ **不用紅綠、不用箭頭。** 這頁的紅綠是漲跌語意，用在這裡會被讀成
   「這天該買」；箭頭同理。標記陳述的是「訊號標籤在這天變了」這個事實，
   方向留給下面的「訊號變化」卡片講。 */
.tr-mark{stroke:var(--text-faint);stroke-width:1;stroke-dasharray:2 2;opacity:.55;}
.tr-mark-dot{fill:var(--text-dim);opacity:.8;}
/* 沒有轉折資料的那一段。⛔ 一定要標——實測 250 日視窗有 73% 的天數不在
   轉折表的涵蓋範圍內，而「沒有標記」跟「訊號沒變過」長得一模一樣。 */
.tr-nodata{fill:var(--text-faint);opacity:.07;}
.tr-nodata-edge{stroke:var(--text-faint);stroke-width:1;stroke-dasharray:3 2;opacity:.45;}
.lg-dot-mark{background:var(--text-dim);opacity:.8;height:2px !important;border-radius:0 !important;}
/* 成交量圖例的色塊。用中性色不用漲跌色：量棒本身是逐日著色的，
   圖例若挑其中一色會暗示「量＝紅」或「量＝綠」。 */
.lg-dot-vol{background:var(--text-dim);opacity:.55;}
