/* 貪婪監控 — 看盤用深色介面
   配色遵循台股習慣：紅＝漲／強勢，綠＝跌／弱勢
   2026-09 配色第三次改版（只改暗版，亮版不動）：「深靛夜色＋星光金」跟太多
   AI 生成的深色儀表板撞色。站長在三個方向裡選了業界標準路線，對標 TradingView
   與幣安這類交易平台：中性炭黑（不帶紫）四階明度、單一品牌藍只用在互動、紅綠
   改成沉穩不螢光的一組。假突破從鈷藍改成琥珀，把藍色讓給強調色；破底翻青、
   處置紫維持不動。 */

:root {
  /* 告訴瀏覽器這一頁是暗的：原生的下拉選單、觸控裝置的捲軸、自動填入的底色跟著用暗色（2026-10-10 稽核）。
     亮版那一段改回 light。 */
  color-scheme: dark;
  --bg:        #0c0f14;   /* 頁面底：中性炭黑，帶一點點藍，不帶紫 */
  --bg-panel:  #141820;   /* 面板 */
  --bg-raise:  #1b2029;   /* 卡片、列表項、面板標題列 */
  --bg-hover:  #232936;   /* 懸停 */
  --chart-bg:  var(--bg-panel);   /* 支撐壓力圖圖表本體底色，跟其他面板分開一個變數，
                                      這樣亮版可以單獨換圖表底色而不影響其他面板 */
  --chart-rect: #f0b90b;   /* 圖上手畫的矩形（標一段整理區）。2026-10-10 站長：暗版原本用品牌藍，深藍框加 12% 的藍底
                              在深色圖上幾乎看不到，要換成黃色。借琥珀（--warn）的色號，不另外調一支黃——圖上沒有
                              別的琥珀色東西，不會跟「假突破」混；它是站長自己畫的記號，不是第五種語意色 */
  --chart-level: #f1f3f6;  /* 圖上「目前不是撐也不是壓」的其餘關卡線。2026-10-08 站長：暗版原本用品牌藍，
                              跟互動的藍搶眼又分不出層次；先試淺灰白 #c9ced6 太亮，站長選「調暗一點的灰」（#6f7784）。
                              2026-10-20 站長：灰色水平線在暗版很不明顯，先換亮灰 #a4adba，同一天再要「白色、黃色、亮一點」，
                              取白（近白）。不用黃：黃已經是手畫矩形（--chart-rect）跟假突破（--warn 琥珀）的色，
                              線也用黃會跟它們混。目前的撐（綠）壓（紅）靠顏色＋線粗 3px 分開，待確認是灰色短虛線。亮版沿用近黑 */
  --chart-lower-highs: #5cf0b2;  /* 頭頭低的虛線、圓點、字。2026-10-20 站長：暗版不明顯。還是下跌的綠（紅漲綠跌），
                              只是比 --down 亮一階，在深色圖上才讀得出來；亮版照舊用 --down */
  --line:      #2b313c;
  --text:      #eaecef;
  --text-dim:  #b7bdc6;
  --text-mute: #8b93a1;   /* 在 --bg-raise 上約 5:1，過 WCAG AA 4.5:1；換色階一定要重新驗證這一階 */
  --fill-ink:  #0c0f14;   /* 疊在琥珀／青色／綠色這類亮色填滿上的深色字 */
  --accent-ink: #ffffff;  /* 疊在強調藍填滿上的白字（約 4.5:1）。強調色跟其他語意色的字色要分開：
                              藍底要白字，琥珀、青底要深字，共用一個 token 兩邊只能顧一邊 */
  /* 四種語意色整塊填滿時（警示標籤、卡片角旗、篩選 chip）的字色，一種填色一支，看對比挑，
     不看色相（見 DESIGN.md 的 High-Contrast Fill Rule）。2026-10-06 站長決定：暗版紅底改用
     近黑字——11px 白字在 #f6465d 上只有 3.53:1，近黑是 5.4:1，紅色本身不動。 */
  --up-ink:      #0c0f14;
  --down-ink:    #04220f;
  --warn-ink:    #0c0f14;
  --rebound-ink: #0c0f14;

  --up:        #f6465d;   /* 紅：漲、突破 */
  /* 紅綠拿來當「文字」時用的那一支（2026-10-06）。K棒、長條、填色這種圖形照舊用 --up／--down；
     字要 4.5:1，而且常常疊在淡紅、淡綠的底上（狀態章、本期變化）：暗版紅字在淡紅底上原本只有
     4.36:1，提亮一點點；亮版綠字在白底上只有 4.04:1，壓深一階。色相都不變。 */
  --up-text:   #ff5a6e;
  --down-text: #0ecb81;
  --up-soft:   rgba(246, 70, 93, 0.14);
  --down:      #0ecb81;   /* 綠：跌、破底 */
  --down-soft: rgba(14, 203, 129, 0.13);
  --accent:    #2b66f7;   /* 品牌藍：唯一的功能性強調色，只用在互動／選取。2026-10-06 從 #2f6bff 壓深一點點：
                              白字在 #2f6bff 上是 4.499:1，差 0.001 沒到 4.5；#2b66f7 是 4.83:1，看起來一樣 */
  --accent-text: #5b8bff; /* 品牌藍拿來當「文字」（連結、選取中的字）時用亮一階：#2f6bff 在暗底上只有 4.27:1，
                              這支 6.02:1（2026-10-03 稽核）。按鈕底色照舊用 --accent，白字才有 4.5:1 */
  --accent-rgb: 43, 102, 247; /* 跟 --accent 同一個顏色的 R,G,B，給需要自訂透明度的 rgba() 用 */
  --accent-soft: rgba(43, 102, 247, 0.16);
  --warn:      #f0b90b;   /* 琥珀：假突破專用。藍色讓給強調色之後，琥珀跟紅漲綠跌、破底翻青、處置紫都分得開 */
  --warn-soft: rgba(240, 185, 11, 0.14);
  --rebound:      #4ed6d1; /* 破底翻青，維持不動 */
  --rebound-text: #4ed6d1; /* 青色拿來當「字」用的那一支。暗版跟 --rebound 同一支；亮版另外深一階（見亮版那一段） */
  --rebound-soft: rgba(78, 214, 209, 0.13);
  --punish:      #b98cf2; /* 處置紫，維持不動（法規狀態，跟技術面訊號是不同軸線） */
  --punish-text: #b98cf2; /* 紫色當字用的那一支，暗版同一支 */
  --punish-soft: rgba(185, 140, 242, 0.16);

  /* 篩選 chip 懸停時的語意色光暈（見 .filter-chips .chip:hover::before）——獨立成 token，
     亮版維持原本的數值不變 */
  --up-glow:      rgba(246, 70, 93, .45);
  --down-glow:    rgba(14, 203, 129, .45);
  --warn-glow:    rgba(240, 185, 11, .45);
  --rebound-glow: rgba(78, 214, 209, .45);

  --radius: 8px; /* 唯一還在用這個舊變數的地方是 .stat，跟著這次收斂改成 rounded.md */
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, monospace;

  /* 中性黑陰影（不再帶靛色調），保留一條極淡的頂緣高光 */
  --shadow-sm: inset 0 1px 0 rgba(255, 255, 255, .03), 0 1px 2px rgba(0, 0, 0, .45);
  --shadow-md: inset 0 1px 0 rgba(255, 255, 255, .04), 0 10px 26px -8px rgba(0, 0, 0, .6), 0 2px 8px -2px rgba(0, 0, 0, .45);
  --shadow-lg: inset 0 1px 0 rgba(255, 255, 255, .05), 0 28px 64px -14px rgba(0, 0, 0, .7), 0 8px 22px -6px rgba(0, 0, 0, .5);
  --topbar-bg: rgba(12, 15, 20, 0.86); /* 跟 --bg 同色但半透明，給頂欄的毛玻璃——獨立成一個 token
                                          是因為 rgba() 沒辦法直接吃 var() 再疊透明度，亮版要另外給一組值 */
}

/* ---------------- 亮版（Glance 極簡編輯風） ----------------
   2026-09 新增亮／暗切換：暗版是上面 :root 那組「深靛夜色」，亮版是站長指定的
   Glance 極簡編輯風——近白暖灰紙感底、細線邊框、色彩節制。用 <html data-theme="..">
   切換，切換邏輯在 app.js／index.html 的初始化腳本，這裡只負責顏色 token。
   注意：兩邊共用同一套元件結構（卡片、徽章都還是原本的實色填滿樣式），
   亮版不是重新刻一套「外框無填色」的元件，只是換色階——這是有意識的取捨，
   兩套完全不同的元件形狀維護成本太高，先用顏色達到 90% 的觀感差異。 */
:root[data-theme="light"] {
  color-scheme: light;
  --bg:        #f6f4f0;
  --bg-panel:  #ffffff;
  --bg-raise:  #ffffff;
  --bg-hover:  #efece5;
  --chart-bg:  #f6f4f0;   /* 暖紙延伸：沿用頁面外層的米白紙色，工具列維持 --bg-raise 純白
                              造出層次對比。2026-09 從三個底色範本裡選定 */
  --line:      #e2e0da;
  --text:      #1c1c1c;
  --text-dim:  #5c5954;
  --text-mute: #706c63;   /* 原本用 #8f8c84，在白色 --bg-panel 上只有 ~3.2:1，沒過 WCAG AA
                              4.5:1（暗版的 --text-mute 也有同一條「提亮到符合門檻」的註解，
                              亮版是反過來要「壓暗」，邏輯相反但目的一樣：小字級的第三層文字
                              一定要驗證過對比度，不能只憑感覺選一個「看起來霧霧的」灰階） */
  --fill-ink:  #f6f4f0;   /* 亮版的中性填滿（近黑的強調色、深灰）上用淺色字 */
  --accent-ink: #f6f4f0;  /* 亮版強調色是近黑，上面用淺色字，跟 --fill-ink 同值 */
  /* 語意色填滿的字色（見 :root）。亮版的紅、藏青比較深，白／淺字才夠；綠、青比較亮，要深字。
     2026-10-06 之前青色填滿也用 --fill-ink（淺字），破底翻標籤只有 1.61:1。 */
  --up-ink:      #ffffff;  /* #c14a42 上 4.86:1 */
  --down-ink:    #0c0f14;  /* #2f8f5b 上 4.74:1（原本 #04220f 只有 4.19） */
  --warn-ink:    #ffffff;  /* #8a5d00 上 5.77:1 */
  --rebound-ink: #1c1c1c;  /* #4ed6d1 上約 9.6:1 */

  --up:        #c14a42;   /* 紅：漲、突破——亮版飽和度調低，跟整體克制調性一致，色相不變 */
  --up-text:   #ad3d36;   /* 紅字：白底 5.4:1、淡紅底 4.9:1（--up 在淡紅底上只有 3.9） */
  --down-text: #23744a;   /* 綠字：白底 5.2:1（--down 只有 4.04）。跟教學站的 Down Text 同一支 */
  --up-soft:   rgba(193, 74, 66, 0.12);
  --down:      #2f8f5b;   /* 綠：跌、破底 */
  --down-soft: rgba(47, 143, 91, 0.12);
  --accent:    #1c1c1c;   /* 近黑，呼應 Glance 的黑白灰主調，不是另外挑一個彩色強調色 */
  --chart-level: #1c1c1c;  /* 其餘關卡線：亮版跟強調色同一支近黑（原本就是這樣，見暗版那支的說明） */
  --chart-lower-highs: var(--down);  /* 頭頭低：亮版照舊用 --down（站長只要求換暗版） */
  --chart-rect: #1c1c1c;   /* 手畫的矩形：亮版照舊近黑（站長只要求換暗版；近黑框在米白圖上本來就清楚） */
  --accent-text: #1c1c1c; /* 亮版的強調色本來就是近黑，文字用同一支 */
  --accent-rgb: 28, 28, 28;
  --warn:      #8a5d00;   /* 假突破：深琥珀。2026-10-06 之前亮版是藏青（#3d5a86），同一個「假突破」亮暗版兩種
                             顏色，違反 Four-Axis 規則（假突破＝琥珀）。亮底上琥珀要壓到這麼深字才看得清楚（紙色底 5.2:1） */
  --warn-soft: rgba(138, 93, 0, 0.12);
  --rebound:      #4ed6d1; /* 破底翻——站長要求跟暗版用同一支青色，不要亮版自己另外調暗。
                               這支顏色在白底上對比度偏低（約 1.8:1，遠低於 WCAG AA 4.5:1），
                               是刻意的取捨，不是漏掉沒驗證。填滿的徽章、圖上的線、邊框都是這一支。 */
  --rebound-text: #0f766e; /* 青色當「字」用、底是淺色的時候用這一支（同色相、深一階）：白底 5.5:1、淡青底 5.1:1。
                               2026-10-10 稽核量到亮版 54 個警示價位、24 個「本期變化」標籤的青色字只有 1.6～1.8:1，
                               同一排的假突破、突破都讀得清楚，只有破底翻淡掉。青色本身不動，只有字換；
                               漲跌早就有 --up-text／--down-text 這種「字專用」的顏色，/upgrade 的破底翻標籤也是。
                               要改回原樣：把這一行改成 #4ed6d1。 */
  --rebound-soft: rgba(78, 214, 209, 0.13);
  --punish:      #7d6a99; /* 處置 */
  --punish-text: #6f5c8c; /* 紫色當字用：淡紫底上 5.0:1（--punish 只有 4.07） */
  --punish-soft: rgba(125, 106, 153, 0.13);
  /* 以下幾個是 2026-09 暗版改色時才抽成 token 的值，亮版照舊用原本寫死的數字，外觀不變 */
  --accent-soft:  rgba(224, 183, 103, .14);
  --up-glow:      rgba(255, 77, 79, .45);
  --down-glow:    rgba(34, 197, 94, .45);
  --warn-glow:    rgba(138, 93, 0, .45);
  --rebound-glow: rgba(78, 214, 209, .45);

  /* 亮版陰影要很輕、很中性——深版陰影是刻意做出「浮起來」的存在感，
     亮版紙感底色本身已經很亮，陰影只需要極淡的灰階，避免看起來像貼了一層髒污 */
  --shadow-sm: inset 0 1px 0 rgba(255, 255, 255, .6), 0 1px 2px rgba(28, 28, 28, .06);
  --shadow-md: inset 0 1px 0 rgba(255, 255, 255, .6), 0 10px 26px -8px rgba(28, 28, 28, .12), 0 2px 8px -2px rgba(28, 28, 28, .08);
  --shadow-lg: inset 0 1px 0 rgba(255, 255, 255, .6), 0 28px 64px -14px rgba(28, 28, 28, .18), 0 8px 22px -6px rgba(28, 28, 28, .12);
  --topbar-bg: rgba(246, 244, 240, 0.85);
}

/* 暗版底色是平的——對標的交易平台（TradingView、幣安）都不在背景加噪點或光暈，
   那兩層正是讓舊版看起來像「AI 深色儀表板」的來源之一。亮版照舊保留（見下方 body）。 */
:root:not([data-theme="light"]) body { background-image: none; }

* { box-sizing: border-box; }

/* 有些元件自帶 display，會蓋掉瀏覽器內建的 [hidden]{display:none}，
   造成「明明設了 hidden 卻關不掉」。這條確保 hidden 一律有效。 */
[hidden] { display: none !important; }

/* ---------------- 捲軸 ----------------
   2026-10-10 站長：「網站裡所有可以滾動的滑軌是否能夠更換造型？」原本是瀏覽器內建的樣子——
   暗版的畫面上一條白底灰塊、上下還帶箭頭，是整頁唯一不屬於這套設計的東西。
   造型（三個站、會員方案頁都是同一個形狀，顏色各自從自己的 token 取）：軌道透明、沒有箭頭，
   一條細細的圓頭小棒浮在邊上；滑鼠指到變粗一點、變亮，按住拖的時候再亮一階。
   - 顏色只用文字的灰階，不借強調色：捲軸到處都有，上了色就變成滿版的裝飾。
     靜止時跟底色的對比抓 3:1 上下——看得到在哪、但不搶眼。
   - 只在用滑鼠的裝置換（hover: hover 且 pointer: fine）。手機、平板的捲軸本來就是捲的時候才
     浮出來、不佔位置；在 Android 上自訂捲軸會讓它變成一直佔著一條寬度，反而擠到版面。
   - 兩套寫法：Chrome／Edge／Safari 用 ::-webkit-scrollbar（才做得出圓頭和指到變粗）；Firefox 不認得，
     用標準的 scrollbar-color／scrollbar-width（只能換顏色和粗細）。標準那兩個屬性一設，新版 Chrome
     就不理 ::-webkit-scrollbar 了，所以包在 @supports not selector(...) 裡只給 Firefox。
   - 刻意藏起捲軸的地方（題材那排、今日精選那排…）寫的是 .xxx::-webkit-scrollbar { display: none }，
     比這裡的規則具體，照舊藏著。 */
:root {
  --scroll-thumb: color-mix(in srgb, var(--text-mute) 70%, transparent);
}
@media (hover: hover) and (pointer: fine) {
  ::-webkit-scrollbar { width: 12px; height: 12px; }
  ::-webkit-scrollbar-track,
  ::-webkit-scrollbar-corner { background: transparent; }
  ::-webkit-scrollbar-button { display: none; }
  ::-webkit-scrollbar-thumb {
    background-color: var(--scroll-thumb);
    background-clip: padding-box;       /* 四周 3px 透明的邊：看到的小棒 6px 寬，滑鼠抓得到的還是整條 12px */
    border: 3px solid transparent;
    border-radius: 999px;
  }
  ::-webkit-scrollbar-thumb:vertical { min-height: 44px; }
  ::-webkit-scrollbar-thumb:horizontal { min-width: 44px; }
  ::-webkit-scrollbar-thumb:hover { background-color: var(--text-mute); border-width: 2px; }
  ::-webkit-scrollbar-thumb:active { background-color: var(--text-dim); border-width: 2px; }
  @supports not selector(::-webkit-scrollbar) {
    * { scrollbar-width: thin; scrollbar-color: var(--text-mute) transparent; }
  }
}

/* 捲軸出現時版面不要往左跳（2026-10-12 optimize）：強勢榜、題材頁資料回來、頁面變得夠長出現
   捲軸那一刻，整頁置中的內容往左移 6px，算進版面位移（CLS）。先把捲軸的位置留著。
   手機的捲軸是浮在上面的，不受影響；登入頁整頁不捲，下面 html:has(body.login-body) 收回去。 */
html { scrollbar-gutter: stable; }

body {
  margin: 0;
  min-height: 100vh;
  /* 質感兩層：極細顆粒噪點（打散純色的死板感，看盤時完全感覺不到存在）
     ＋畫面上方一道極淡的中性光暈（不用紅/綠，避免跟漲跌語意混在一起） */
  background-color: var(--bg);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 0.05 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),
    radial-gradient(1300px 680px at 50% -14%, rgba(148, 178, 214, .05), transparent 62%);
  background-repeat: repeat, no-repeat;
  background-size: 180px 180px, auto;
  background-attachment: fixed, fixed;
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", "Segoe UI Variable",
               "Segoe UI", "Noto Sans TC", "Microsoft JhengHei", sans-serif;
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2 { margin: 0; font-weight: 600; }

/* ---------------- Icon 系統 ----------------
   全站統一用一套手繪線性 icon（stroke-based，viewBox 24x24，線寬 1.75），
   取代原本到處亂用的 emoji——emoji 顏色是系統決定的，沒辦法跟著漲跌狀態變色，
   線性 icon 用 currentColor，文字變什麼顏色它就跟著變。*/
.icon {
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  vertical-align: -0.15em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon-dots { fill: currentColor; stroke: none; }
.icon .bar { fill: currentColor; stroke: none; }

/* 假突破專用：貓臉造型，眼睛/嘴巴是「挖空」的 X——用背景色填色模擬鏤空，
   不用真的鏤空（SVG mask 在同一頁重複出現多次容易撞 id），臉本身還是吃 currentColor，
   照樣會跟著假突破的漲跌語意變紅變綠 */
.icon-cat { fill: none; stroke: none; }
.icon-cat .cat-face { fill: currentColor; }
.icon-cat .cat-cutout { fill: var(--bg); }

/* 鍵盤操作可視焦點——原本只有輸入框有，按鈕／chip／tab 完全沒有 */
button:focus-visible,
a:focus-visible,
[tabindex]:focus-visible,
input:focus-visible,
select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* 卡片／表格列上「開支撐壓力圖」的按鈕就是股票名稱（2026-10-03：按鈕裡面不能再包按鈕，
   卡片和列本身不再是 role="button"）。外觀照舊，只把語意換成真的按鈕。
   不用 font 簡寫，免得蓋掉 .stock-card-name 自己的字級和字重。 */
.card-open {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  color: inherit;
  font-family: inherit;
  line-height: inherit;
  text-align: left;
  cursor: pointer;
}
.stock-card-name.card-open { display: block; }
.row-open { font-size: inherit; font-weight: inherit; }
/* 焦點框畫在整張卡片／整列上，一眼看得出是哪一檔；不支援 :has() 的瀏覽器維持按鈕自己的焦點框 */
@supports selector(:has(*)) {
  .card-open:focus-visible { outline: none; }
  .stock-card:has(.card-open:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
  #stock-body tr:has(.card-open:focus-visible) { outline: 2px solid var(--accent); outline-offset: -2px; }
}

/* ---------------- 頂列 ---------------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  align-items: center;
  justify-content: space-between;
  padding: 12px 20px;
  background: var(--topbar-bg);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.brand { display: flex; align-items: center; gap: 12px; }
/* 頁名前面的小圖示（2026-10-19 站長：「換貪婪監控這個標誌，低調一點」）。原本是品牌藍淡底的圓形徽章加陰影，
   在頂列裡比頁名還搶眼。現在只剩細線、次要文字的灰，不加底色、不加陰影——頁名才是主角。
   看盤頁（貪婪監控）、登入頁的圖示換成一根K棒穿過一條關卡線（突破），跟這個站在做的事有關，
   不是通用的往上箭頭；題材輪動、強勢榜各自的圖示不變，只是一起變低調。 */
.brand-mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  color: var(--text-dim);
}
.brand-mark .icon { width: 24px; height: 24px; stroke-width: 1.6; }
.brand h1 { font-size: 21px; font-weight: 700; letter-spacing: 0.1px; }
.brand-sub { margin: 3px 0 0; font-size: 12px; color: var(--text-mute); }

.status-strip { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.stat {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1px;
  padding: 5px 12px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  min-width: 84px;
  min-height: 54px; /* 4 顆 stat 只有倒數計時那顆多一條進度條，取它的自然高度當共同高度，
    其他 3 顆內容置中，不然倒數計時那顆會比其他 3 顆高一截 */
  box-shadow: var(--shadow-sm);
}
.stat-label { font-size: 11px; color: var(--text-mute); letter-spacing: 1px; }
.stat-value { font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.stat-value.open   { color: var(--up-text); }
.stat-value.closed { color: var(--text-dim); }

/* 倒數計時：油量表式的量級長條（跟卡片位階條、法人買賣超長條同一套「軌道＋填色」語言），
   數字本身看得懂，長條讓人不用讀數字也能一眼感覺到「還剩多少」 */
.stat-countdown { min-width: 112px; }
.stat-progress {
  height: 3px;
  margin-top: 4px;
  border-radius: 999px;
  background: var(--bg);
  overflow: hidden;
}
.stat-progress-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  border-radius: 999px;
  transition: width 1s linear;
}
/* 倒數快到了，用「亮度＋輕微脈動」表示急迫，不搶 Amber——Amber 全站只保留給
   破底翻反轉警示一種語意，倒數計時器搶用同一個顏色會讓使用者誤以為又有警示發生。
   見 DESIGN.md 三軸色彩規則：不開第四軸，這裡改用既有 --text 提亮＋動畫代替顏色。 */
.stat-countdown.urgent .stat-value { color: var(--text); animation: countdown-pulse 1s ease-in-out infinite; }
.stat-countdown.urgent .stat-progress-fill { background: var(--text-dim); }
@keyframes countdown-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: .55; }
}

/* ---------------- 版面 ---------------- */
.layout {
  display: grid;
  grid-template-columns: minmax(340px, 30%) 1fr;
  gap: 22px;
  padding: 18px 22px 40px;
  align-items: start;
  max-width: 1800px;
  margin: 0 auto;
}

.panel {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: var(--shadow-md);
}

.panel-head {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  justify-content: space-between;
  padding: 13px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-raise);
  /* 頂緣一條極淡的高光，模擬光線從上方打下來的自然立體感 */
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .035);
}
.panel-head h2 { display: inline-flex; align-items: center; gap: 7px; font-size: 15px; font-weight: 700; letter-spacing: 0.02em; }

/* ---------------- 警示紀錄 ---------------- */
.filter-chips { display: flex; gap: 5px; flex-wrap: wrap; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  font-size: 12px;
  font-family: inherit;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 999px;
  cursor: pointer;
  transition: background-color .16s ease, color .16s ease, border-color .16s ease, transform .1s ease;
}
.chip:hover { background: var(--bg-hover); color: var(--text); }
.chip:active { transform: scale(.95); }
/* .chip.active 系列（含 chip-up/down/warn 變體）的底色已改由下面
   .filter-chips .chip.active::before 等規則負責畫（見下方 Dock 式懸停放大
   說明）。這裡不能保留同款規則：.chip.chip-up.active 是 3 個 class
   （specificity 0,0,3,0），比 .filter-chips .chip 的 2 個 class
   （0,0,2,0）更高，就算寫在後面的 .filter-chips .chip { background:
   transparent } 也贏不了它——選取後底色會同時畫在「沒有位移的 .chip 本身」
   和「懸停時位移放大的 ::before」兩層，變成滑鼠移開後原本位置還留著一塊顏色、
   懸停時又在別處放大出一塊顏色的重影。全站目前只有 .filter-chips 底下的
   chip 會被加上 .active + chip-up/down/warn 組合，刪掉這裡不影響其他地方。 */

/* ---------------- Dock 式懸停放大 ----------------
   警示類型篩選、產業分頁這兩排 chip 借用 macOS Dock 的手感：指到的那一顆抬起來
   放大，左右緊鄰的兩顆跟著抬一點點，形成一道波形。

   關鍵在「前一個鄰居」怎麼選——CSS 只有「選後面的兄弟」（+）沒有「選前面的」，
   所以後鄰居用 `:hover + .chip`，前鄰居改用 `:has(+ .chip:hover)`：選出「下一個
   兄弟正在被 hover」的那一顆，剛好就是前鄰居。這是 :has() 才做得到的事。

   ⚠️ 放大的 transform 絕對不能套在 .chip（也就是負責判定 :hover 的那個 <button>）
   自己身上——瀏覽器判定「滑鼠在不在這個元素上」用的是它「目前實際畫出來」的位置，
   transform 會讓那個判定範圍跟著移動／變大。滑鼠如果停在原本邊界附近，範圍一移開
   滑鼠就變成「不在範圍內」→ 縮回去 → 又剛好把範圍移回滑鼠底下 → 再放大……無限
   來回閃爍。所以真正的放大動畫要套在 .chip 以外的層。

   ⚠️ 第二個坑：一開始只把 transform 套在文字層 .chip-face 上，結果變成「文字自己
   跑上去放大，藥丸形狀的底色/邊框留在原地」——因為底色/邊框那時候還是直接畫在
   .chip 自己身上，跟著判定範圍一起維持不動，跟會動的文字整個拆開。

   修法：藥丸形狀的底色/邊框/陰影全部搬到新增的 ::before 偽元素上（不管是平常、
   選取中、hover 哪個狀態，一律由 ::before 負責畫，.chip 本身的 background/
   border 永遠維持透明，只當一個不會變動的判定外殼）。.chip-face（文字）跟
   ::before（底色形狀）套全同一組 transform，兩層數值永遠一致，畫面上就會是
   「藥丸連同文字一起放大抬起」，不會拆開。兩層都是 pointer-events:none 或
   position:absolute 不佔版面，滑鼠移到它們放大溢出的範圍時會直接跳過，不會被
   誤判成「還在 hover .chip」——這樣「有沒有 hover」永遠只看 .chip 自己原本、
   完全不會變動的版面範圍，不管視覺放大到多誇張都不影響判定，就不會來回閃爍。 */
.filter-chips .chip,
.industry-tabs .chip {
  position: relative;
  /* 底色/邊框永遠交給 ::before 畫，.chip 自己在這兩個情境下維持透明——
     不然 ::before 移開之後，.chip 自己沒動過的底色會被看到穿幫（跟這次修的
     bug是同一種「兩層對不起來」的問題，只是換了個地方發生）。
     這裡不用 !important：跟 .chip.active 等規則比，class 數量相同（都是兩個），
     純粹靠這條規則寫在後面（source order）就贏，不需要動用 !important。 */
  background: transparent;
  border-color: transparent;
  transition: color .16s ease;
}
.filter-chips .chip::before,
.industry-tabs .chip::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  border: 1px solid var(--line);
  /* 一定要設 none：::before 是 .chip 的子節點，沒有這行的話，它放大溢出的範圍
     一樣會被算成「還在 hover .chip」，等於把先前修好的邊框閃爍問題原封不動地
     重新引進來一次，只是換成由這一層造成。 */
  pointer-events: none;
  transform-origin: center bottom;
  transition: transform .28s cubic-bezier(.34, 1.56, .64, 1),
              background-color .16s ease, border-color .16s ease, box-shadow .16s ease;
}
.chip-face {
  position: relative;
  z-index: 1; /* 疊在 ::before 之上，文字/圖示才不會被底色蓋住 */
  display: inline-flex;
  align-items: center;
  gap: 5px;
  pointer-events: none;
}
.filter-chips .chip-face,
.industry-tabs .chip-face {
  transform-origin: center bottom;
  transition: transform .28s cubic-bezier(.34, 1.56, .64, 1);
}

/* 選取中（.active）的底色也搬到 ::before，這樣「目前已選取、又被滑鼠移過去」
   的 chip，放大抬起時帶的是它真正在顯示的顏色，不會露出底下沒動過的舊底色。 */
.filter-chips .chip.active,
.industry-tabs .chip.active { color: var(--accent-ink); font-weight: 600; }
.filter-chips .chip.active::before,
.industry-tabs .chip.active::before { background: var(--accent); border-color: var(--accent); }
.filter-chips .chip.chip-up.active   { color: var(--up-ink); }
.filter-chips .chip.chip-up.active::before   { background: var(--up);   border-color: var(--up); }
.filter-chips .chip.chip-down.active { color: var(--down-ink); }
.filter-chips .chip.chip-down.active::before { background: var(--down); border-color: var(--down); }
.filter-chips .chip.chip-warn.active { color: var(--warn-ink); }
.filter-chips .chip.chip-warn.active::before { background: var(--warn); border-color: var(--warn); }
.filter-chips .chip.chip-rebound.active { color: var(--rebound-ink); }
.filter-chips .chip.chip-rebound.active::before { background: var(--rebound); border-color: var(--rebound); }

/* 指到的那一顆：抬最高、放最大，而且整塊填色＋往外發光，直接從那一排裡跳出來。
   填的是「這顆 chip 被選取時本來就會用的顏色」，等於提前預覽點下去的結果，
   不是另外發明一套 hover 專用色。顏色套在 .chip 上（文字），底色/陰影/位移
   套在 ::before 上，放大套在 .chip-face 上——三者用同一組 transform 數值。 */
/* ⚠️ 這一大段全部包在 @media (hover: hover) 裡——觸控螢幕／觸控板點一下之後，
   瀏覽器沒有「滑鼠移開」這個動作可以偵測，:hover 會一直卡在觸發狀態，直到使用者
   點別的地方才取消。結果就是「點下去之後，放大＋變色卡住不放」，症狀很像 bug，
   實際上是觸控裝置對 :hover 天生的行為，不是這裡的邏輯寫錯。(hover: hover) 只
   在「真的有游標可以持續 hover」的裝置上才會是 true，觸控裝置一律排除在外——
   點擊在觸控裝置上只會切換 .active（下面那組規則，跟 :hover 完全分開，用 JS
   classList 控制，不會有卡住的問題），放大動畫則只留給滑鼠使用者。 */
@media (hover: hover) {
  .filter-chips .chip:hover,
  .industry-tabs .chip:hover {
    color: var(--accent-ink);
    font-weight: 600;
  }
  .filter-chips .chip:hover::before,
  .industry-tabs .chip:hover::before {
    background: var(--accent);
    border-color: var(--accent);
    box-shadow: 0 4px 12px -6px rgba(var(--accent-rgb), .45);
    transform: translateY(-4px) scale(1.08);
  }
  .filter-chips .chip:hover .chip-face,
  .industry-tabs .chip:hover .chip-face { transform: translateY(-4px) scale(1.08); }

  /* 漲跌／反轉三種類型各自用自己的語意色，跟它們選取後的填色一致 */
  .filter-chips .chip.chip-up:hover   { color: var(--up-ink); }
  .filter-chips .chip.chip-up:hover::before {
    background: var(--up); border-color: var(--up);
    box-shadow: 0 4px 12px -6px var(--up-glow);
  }
  .filter-chips .chip.chip-down:hover { color: var(--down-ink); }
  .filter-chips .chip.chip-down:hover::before {
    background: var(--down); border-color: var(--down);
    box-shadow: 0 4px 12px -6px var(--down-glow);
  }
  .filter-chips .chip.chip-warn:hover { color: var(--warn-ink); }
  .filter-chips .chip.chip-warn:hover::before {
    background: var(--warn); border-color: var(--warn);
    box-shadow: 0 4px 12px -6px var(--warn-glow);
  }
  .filter-chips .chip.chip-rebound:hover { color: var(--rebound-ink); }
  .filter-chips .chip.chip-rebound:hover::before {
    background: var(--rebound); border-color: var(--rebound);
    box-shadow: 0 4px 12px -6px var(--rebound-glow);
  }

  /* 左右緊鄰的兩顆：抬一半、放一點點——::before 跟 .chip-face 一起動，
     這兩顆通常沒有變色（除非本來就是選取中的那顆），單純視覺變大不脫鉤。 */
  .filter-chips .chip:hover + .chip::before,
  .filter-chips .chip:has(+ .chip:hover)::before,
  .industry-tabs .chip:hover + .chip::before,
  .industry-tabs .chip:has(+ .chip:hover)::before { transform: translateY(-2px) scale(1.03); }
  .filter-chips .chip:hover + .chip .chip-face,
  .filter-chips .chip:has(+ .chip:hover) .chip-face,
  .industry-tabs .chip:hover + .chip .chip-face,
  .industry-tabs .chip:has(+ .chip:hover) .chip-face { transform: translateY(-2px) scale(1.03); }
}

/* 按下去要能從「浮起來的位置」再壓一下，不然原本的 .chip:active 會被上面蓋掉，
   點擊就完全沒有回饋。時間縮短讓按壓感是即時的，不要跟著彈簧慢慢晃 */
.filter-chips .chip:active::before,
.industry-tabs .chip:active::before {
  transform: translateY(-3px) scale(1.05);
  transition-duration: .08s;
}
.filter-chips .chip:active .chip-face,
.industry-tabs .chip:active .chip-face {
  transform: translateY(-3px) scale(1.05);
  transition-duration: .08s;
}

/* chip 抬高 14px ＋放大 1.35 倍之後，視覺上會突出到面板標題列的上緣之外（判定
   hover 的 .chip 本身沒有變大，但畫出來給人看的 .chip-face 確實會超出去）。
   .panel 本來有 overflow:hidden（為了讓標題列的方角不要露出圓角外面），這兩個
   面板會被裁掉浮起來的 chip 頭部，所以改成不裁切、由 .panel-head 自己帶圓角來收邊。 */
.panel-alerts,
.panel-table { overflow: visible; }
.panel-alerts > .panel-head,
.panel-table > .panel-head { border-radius: 14px 14px 0 0; }

/* Grid item 預設 min-width: auto，代表「內容多寬，這個 grid track 就撐多寬」，
   跟 .industry-tabs 想要的「自己內部捲動、不要把外面的版面撐開」正好相反——
   常駐 chip 數一拉多（見 app.js 的 INDUSTRY_TAB_COUNT），.panel-table 就會把
   整個 .layout grid 往右撐爆、逼出頁面級的水平捲軸，.industry-tabs 自己的
   overflow-x 反而完全用不到（畫面上量出來 scrollWidth 等於 clientWidth，
   因為兩個都被撐大了，不是內容被截斷）。加回 min-width: 0，這個 grid item
   才會乖乖收在 1fr 分配到的寬度內，換成 .industry-tabs 自己捲動。 */
.panel-alerts,
.panel-table { min-width: 0; }

/* 圖示吃 currentColor，所以上面把 chip 的 color 設成對比色時，圖示會自動跟著變。
   這裡刻意「不」另外指定圖示顏色——填色之後如果再把圖示塗成同一個語意色，
   就會變成紅底紅圖示，整個糊掉看不見。 */

/* 「近三日」在 .filter-chips 外面（是 .ghost-btn），但視覺上跟那排連在一起，
   給它同樣的浮起手感才不會顯得斷掉 */
#alert-summary-open {
  transform-origin: center bottom;
  transition: transform .28s cubic-bezier(.34, 1.56, .64, 1), background-color .16s ease;
}
#alert-summary-open:hover  { transform: translateY(-3px) scale(1.04); }
#alert-summary-open:active { transform: translateY(-1px) scale(1.01); transition-duration: .08s; }

/* 原本這裡有一條 @media (prefers-reduced-motion: reduce) 規則，系統開著「減少
   動態效果」時會把 transform 直接設成 none——只留顏色變化，位移和放大全部消失。
   拿掉了：這是站長刻意的取捨（見 docs/adr/0001），不因無障礙情境犧牲動態效果。
   2026-08 免費版上線後，網站多了一種匿名陌生訪客（Google 登入即可用），不再只有
   會員；ADR 的決定本身沒有跟著改，但這裡原本的說明曾經用「不用管陌生訪客」當
   理由，那個理由現在不成立了，先更正掉，決定要不要改動畫行為留給站長。 */

.alert-list {
  max-height: calc(100vh - 190px);
  overflow-y: auto;
  padding: 8px;
}

/* 減噪：背景統一是乾淨的 bg-raise 深灰，不再依警示類型疊紅／綠／琥珀色的整塊底色，
   也不用單邊粗色條（那是被機制偵測工具標記過的反樣式，見 DESIGN.md）當狀態指示——
   左邊的 .alert-icon 圓形徽章本身就是顏色鮮明的「狀態標籤」，不需要再疊第二層色塊 */
.alert-item {
  /* ⚠️ 不要加 content-visibility: auto（2026-10-12 optimize 加過、2026-10-13 拿掉）：它附帶的裁切
     會把超出預估高度的東西切掉，卡片就是這樣切掉旗標的（見 .stock-card）。兩百則警示不排版省下的
     時間很少，不值得冒這個險。（2026-10-13 警示只剩標題和時間，起初以為是它，真正的原因是廣告攔截器，
     見下面 .alert-detail 的說明。） */
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 4px 10px;
  padding: 10px 12px;
  margin-bottom: 6px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color .14s ease, transform .1s ease;
}
.alert-item:hover { border-color: var(--accent); }
.alert-item:active { transform: scale(.99); }

.alert-item.fresh { animation: flash-in .7s ease-out; }
@keyframes flash-in {
  0%   { transform: translateY(-6px); opacity: 0; box-shadow: 0 0 0 2px var(--accent); }
  100% { transform: none; opacity: 1; box-shadow: none; }
}

/* 卡片 hover 幻影預覽（見 app.js showAlertPreview）——故意跟上面 flash-in（真的
   有新警示進來，從上面滑進來）用相反方向，從下面浮上來取代原本內容，讓「這是
   我把滑鼠指過去才看到的預覽」跟「這是剛剛真的發生的新警示」在動作上就分得
   出來，不只是內容不同。 */
@keyframes alert-phantom-in {
  0%   { transform: translateY(16px); opacity: 0; }
  100% { transform: none; opacity: 1; }
}
.alert-item.phantom-in { animation: alert-phantom-in .34s cubic-bezier(.16, 1, .3, 1) both; }

/* 圖示改成軟色底的圓形徽章，不是裸線條——裸線條的顏色再對，貼在卡片本身
   就帶淡淡漲跌色暈的背景上還是很容易被吃掉，徽章底色才能讓顏色真的「跳出來」 */
.alert-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: 999px;
  background: var(--bg);
  color: var(--text-dim);
  grid-row: span 2;
  align-self: center;
}
.alert-icon .icon { width: 22px; height: 22px; stroke-width: 1.9; }
.alert-item.up   .alert-icon { background: var(--up-soft);   color: var(--up-text); }
.alert-item.down .alert-icon { background: var(--down-soft); color: var(--down-text); }
.alert-item.warn .alert-icon { background: var(--warn-soft); color: var(--warn); }
.alert-item.rebound .alert-icon { background: var(--rebound-soft); color: var(--rebound-text); }
/* 新聞混進警示的混合時間軸（見 app.js showAlertPreview／docs/adr/0007）。
   用中性色（不是紅/綠/藍/青任何一種既有警示色），因為新聞本身不代表方向；
   這一則是 <a> 不是 <div>，額外重置連結預設樣式才會跟其他警示項目視覺一致。 */
.alert-item.news { color: inherit; text-decoration: none; }
.alert-item.news .alert-icon { background: var(--bg-hover); color: var(--text-dim); }
/* 排版層級：股名跟觸發事件（標籤＋價格）要一眼抓到，代號／備註／時間戳降一階退到背景 */
.alert-title { font-weight: 700; font-size: 14.5px; }
.alert-time { font-size: 11px; color: var(--text-mute); font-variant-numeric: tabular-nums; white-space: nowrap; }
.alert-detail { grid-column: 2 / -1; font-size: 12.5px; color: var(--text-mute); font-variant-numeric: tabular-nums; }
.alert-price { font-family: var(--mono); font-weight: 700; }
/* 第二行的每一段（代號、說明、到價／轉折、昨收）是一個換行單位，只在段和段之間斷開。
   分隔點「・」畫在每一段左邊留的那一格裡；整排往左多拉一格、外層把超出去的切掉——
   所以每一行最前面那一段的分隔點看不到，換到第二行也不會用「・」開頭（2026-10-10 精修）。 */
/* ⚠️ 這一行裡的名字不要用 ad- 開頭（原本叫 ad-row、ad-lead、ad-seg，取 alert detail 的縮寫）：
   廣告攔截器把 ad- 開頭的元素當廣告藏起來，整行不見——2026-10-13 站長用 greedyleek.com 打開看盤頁，
   一般視窗每一則警示都只剩標題和時間，無痕視窗（不跑擴充功能）才正常。本機 localhost 很多攔截器不處理，
   所以之前沒發現。三個網站其他地方也不要取 ad-、ads、banner、sponsor、promo 這類名字。 */
.alert-detail { overflow: hidden; }
.alert-line { display: flex; flex-wrap: wrap; align-items: baseline; margin-left: -1.1em; }
.alert-line > * { position: relative; padding-left: 1.1em; }
.alert-lead { white-space: nowrap; }
.alert-seg::before { content: "・"; position: absolute; left: .05em; width: 1em; text-align: center; }
.alert-item.up .alert-price   { color: var(--up-text); }
.alert-item.down .alert-price { color: var(--down-text); }
.alert-item.warn .alert-price { color: var(--warn); }
.alert-item.rebound .alert-price { color: var(--rebound-text); }
.alert-tag {
  display: inline-block;
  padding: 0 6px;
  margin-right: 6px;
  font-size: 11px;
  border-radius: 4px;
  font-weight: 600;
}
.alert-item.up .alert-tag   { background: var(--up);   color: var(--up-ink); }
.alert-item.down .alert-tag { background: var(--down); color: var(--down-ink); }
.alert-item.warn .alert-tag { background: var(--warn); color: var(--warn-ink); }
.alert-item.rebound .alert-tag { background: var(--rebound); color: var(--rebound-ink); }

/* 滑鼠停在某張卡片時，警示紀錄的標題換成那一檔、旁邊一行小字；預覽期間有新警示進來，
   清單最上面一行提示（2026-10-06）。提示不是按鈕，所以不用品牌藍（One Accent Rule）。 */
.alert-title-hint { margin-left: 8px; font-size: 12px; font-weight: 500; color: var(--text-mute); }
.alert-missed {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0 0 8px;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  background: var(--bg-raise);
  border: 1px solid var(--text-dim);
  border-radius: 8px;
}

/* ---------------- 近三日 警示彙總彈窗 ---------------- */
.alert-summary-nav {
  display: flex;
  gap: 6px;
  padding: 10px 16px 0;
}
.alert-summary-group { margin-bottom: 18px; }
.alert-summary-group:last-child { margin-bottom: 0; }
.alert-summary-group-title {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0 0 8px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text);
}
.alert-summary-group-date { font-size: 11px; font-weight: 400; color: var(--text-mute); font-family: var(--mono); }
.alert-summary-group-count { font-size: 11px; font-weight: 400; color: var(--text-mute); }

/* 依股票整理的彙總（2026-10-06，見 app.js 的 summaryStockHtml）：每天一行各類型則數，
   接著一檔一列，那檔當天的警示照時間串起來 */
.sum-types { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.sum-tag {
  display: inline-block;
  padding: 0 6px;
  font-size: 11px;
  font-weight: 600;
  border-radius: 4px;
  white-space: nowrap;
}
.sum-tag.up      { background: var(--up);      color: var(--up-ink); }
.sum-tag.down    { background: var(--down);    color: var(--down-ink); }
.sum-tag.warn    { background: var(--warn);    color: var(--warn-ink); }
.sum-tag.rebound { background: var(--rebound); color: var(--rebound-ink); }
.sum-stock {
  display: grid;
  grid-template-columns: minmax(0, 8.5em) minmax(0, 1fr);
  align-items: baseline;
  gap: 4px 12px;
  margin-bottom: 6px;
  padding: 8px 12px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color .14s ease;
}
.sum-stock:hover { border-color: var(--text-mute); }
.sum-stock:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sum-stock-name { font-size: 14px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sum-stock-name small { margin-left: 6px; font-size: 11px; font-weight: 400; color: var(--text-mute); }
.sum-events { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; font-size: 12.5px; color: var(--text-mute); }
.sum-ev { display: inline-flex; align-items: baseline; gap: 5px; white-space: nowrap; }
.sum-ev-time { font-variant-numeric: tabular-nums; }
.sum-ev-price { font-family: var(--mono); font-weight: 700; }
.sum-ev.up .sum-ev-price      { color: var(--up-text); }
.sum-ev.down .sum-ev-price    { color: var(--down-text); }
.sum-ev.warn .sum-ev-price    { color: var(--warn); }
.sum-ev.rebound .sum-ev-price { color: var(--rebound-text); }
.sum-ev-arrow { color: var(--text-mute); }
@media (max-width: 640px) {
  .sum-stock { grid-template-columns: minmax(0, 1fr); }
}

/* ---------------- 表格 ---------------- */

/* ---------------- 監控清單：卡片／表格切換 ---------------- */
.view-toggle {
  display: flex;
  gap: 2px;
  padding: 2px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 8px;
}
.view-btn {
  padding: 4px 12px;
  font-size: 12px;
  font-family: inherit;
  color: var(--text-dim);
  background: none;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  transition: color .16s ease, background-color .16s ease, transform .1s ease;
}
.view-btn:hover { color: var(--text); }
.view-btn:active { transform: scale(.95); }
.view-btn.active { background: var(--accent); color: var(--accent-ink); font-weight: 600; }

/* 題材 chip 上的「今日 N」：今天有幾檔觸發警示（2026-10-06，取代「依熱度重排 chip 位置」） */
.itab-hit { margin-left: 6px; font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text-mute); }
.chip.active .itab-hit { color: inherit; opacity: .8; }

/* 產業分類 tab——2026-09-16 從「超過常駐數量就換行」改成「單行、用滑動的方式
   選擇族群」，手機版跟網頁版都適用（站長明確要求兩邊都要）。換行版在窄螢幕
   常駐 chip 一多就擠成兩三行，站長覺得像手機版那樣「滑」過去比較好用；桌面版
   同理，用滑鼠中鍵/觸控板兩指滑動就好，不需要另外做 media query 只給手機。
   50 個產業裡大多數（超過 40 個）出現次數個位數甚至只有 1 檔，這條單行只放
   常駐的 INDUSTRY_TAB_COUNT 個（見 app.js），其餘還是走原本「⋯ 更多」的
   搜尋彈出選單——真的要在 50 個裡面用滑的找，體驗只會更差，搜尋反而更快。 */
.industry-tabs {
  display: flex;
  gap: 8px;
  flex-wrap: nowrap;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  align-items: center;
  padding: 14px 16px 12px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--line);
  cursor: grab;
  /* 右邊緣淡出，暗示「還有更多、可以繼續滑」——比讓 chip 生硬地被裁掉更明顯。 */
  mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent 100%);
}
.industry-tabs::-webkit-scrollbar { display: none; }
.industry-tabs.dragging { cursor: grabbing; scroll-behavior: auto; user-select: none; }
.industry-tabs .chip,
.industry-tabs .more-chip { flex-shrink: 0; }
.itab {
  padding: 6px 13px;
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
}
.itab.active { box-shadow: var(--shadow-md); }
.itab.more-chip {
  padding-left: 10px;
  padding-right: 10px;
  color: var(--accent-text);
  border-style: dashed;
}

.industry-popover {
  margin: 8px 16px 0;
  padding: 10px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 12px;
}
.industry-popover input { width: 100%; margin-bottom: 8px; }
.industry-popover-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  max-height: 220px;
  overflow-y: auto;
}
/* 官方分類殘留（標籤字串剛好等於官方產業別，通常是批次匯入後沒改過）——
   跟站長真的自己取的題材混在一起分不出重點，這裡整組變淡＋掛一個「未分類」
   角標，常駐 tab 列也可能出現（目前選到的產業剛好是這種殘留時）。不用四軸
   語意色的任何一色（不是漲跌方向、不是反轉警示），純中性色。 */
.chip.itab-official { opacity: .55; }
.itab-official-badge {
  margin-left: 5px;
  padding: 0 5px;
  font-size: 10px;
  font-weight: 600;
  color: var(--text-mute);
  border: 1px solid var(--line);
  border-radius: 999px;
}
.industry-popover-divider {
  flex-basis: 100%;
  margin-top: 4px;
  padding-top: 8px;
  border-top: 1px dashed var(--line);
  font-size: 11px;
  color: var(--text-mute);
}
.industry-breakdown {
  margin: 6px 16px 0;
  font-size: 12.5px;
  color: var(--text-mute);
  font-variant-numeric: tabular-nums;
}

/* 股票卡片 */
.stock-grid {
  display: grid;
  /* 220px → 250px：原本這個寬度在寬螢幕（~1920px 視窗）會排出 5 欄，卡片擠得
     沒有空間放新的處置／注意徽章。拉高最小寬度讓同一個螢幕自然少排一欄
     （變 4 欄，每張卡從 ~222px 長到 ~292px），維持 auto-fill 響應式的做法
     不變，不是用死板的 repeat(4, ...) 鎖死欄數，窄螢幕還是會自動再往下收。 */
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 12px;
  padding: 14px 16px;
  max-height: calc(100vh - 260px);
  overflow-y: auto;
}
/* 資料還沒回來：先撐到裝滿時的高度，不然三百張卡片一進來，下面的大盤區塊整塊被推下去
   （2026-10-12 optimize，平板量到版面位移 0.3～0.7）。手機只先畫 20 檔、不設上限高度，不撐。 */
@media (min-width: 641px) {
  .stock-grid:has(> .empty[data-loading]) { min-height: calc(100vh - 260px); }
}
.stock-card {
  /* ⚠️ 不要加 content-visibility: auto（2026-10-12 optimize 加過、同一天拿掉）：它附帶的裁切會把
     右上角跨在邊框上的警示旗標（突破、假突破…）和「今日精選」切掉一半——那天沙盒剛好沒有當天的
     警示、卡片上沒有旗標，檢查時沒看出來，站長在桌機上看到。 */
  position: relative;
  z-index: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 14px 14px 12px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 12px;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: transform .14s ease, border-color .14s ease, box-shadow .14s ease;
}
/* 原本這裡有一個「滑鼠移上去浮現第二張卡片殘影」的景深效果（::before 位移 8-9px
   疊在卡片後面），但實測不管有沒有 hover，那個殘影因為顏色跟背景太接近、位移的
   那圈又只有幾 px，肉眼完全看不出來——是一段不會被注意到的死程式碼，拿掉。
   卡片本身的 hover 位移＋陰影已經足夠表達「這張被指到了」，不缺這層。 */
.stock-card:hover { transform: translateY(-5px); border-color: var(--text-mute); box-shadow: var(--shadow-md); }
.stock-card:active { transform: translateY(-1px) scale(.99); }
/* DESIGN.md 對漲跌狀態的規格只有一條：「整圈邊框改成 Signal Red／Confirm
   Green」，沒有背景漸層發光這件事——之前這裡多加了一層對角漸層色暈
   （linear-gradient(...var(--up-soft)...)），單張卡片好看，但 184 張同時
   攤開、每張都在對角發光，看起來就是隨處可見的「AI 生成後台」樣板感，
   跟別人的網站長得像也是這個原因：色塊/漸層灑滿整張卡是最容易被認出來的
   套路。改回規格原本寫的樣子——只有邊框整圈變色，底色維持跟平常一樣的
   Raise Slate，訊號交給價格數字顏色跟量級長條顏色去帶，卡片本身安靜下來。 */
.stock-card.tone-up   { border-color: var(--up); }
.stock-card.tone-down { border-color: var(--down); }
/* 假突破用琥珀色邊框、破底翻用青色邊框——兩者都跟單純的漲跌方向分開，
   拆成兩色是因為换成琥珀底色系之後，--warn 會跟 --accent 疊在一起分不清楚 */
.stock-card.tone-warn { border-color: var(--warn); }
.stock-card.tone-rebound { border-color: var(--rebound); }

/* 今天真的觸發過警示的卡片（跟純粹「現價站在哪個位置」的 tone-* 邊框分開一層）。
   紅綠盲使用者沒辦法只靠 tone-up／tone-down 的色相分辨突破跟跌破，所以這裡疊兩層
   跟色相無關的線索：邊框加粗（明度/粗細差異，色盲一樣感知得到）＋右上角掛一顆
   帶圖示的旗標，圖示本身四種形狀互不相同（見 renderCards 的 alertFlag 說明），
   顏色在這裡只是「多一點資訊」，不是唯一能依賴的線索。 */
.stock-card.card-hit-today { border-width: 2.5px; }
.card-alert-flag {
  position: absolute;
  top: -9px;
  right: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .02em;
  border-radius: 999px;
  white-space: nowrap;
}
.card-alert-flag .icon { width: 13px; height: 13px; stroke-width: 2.2; }
.card-alert-flag.tone-up   { background: var(--up);   color: var(--up-ink); }
.card-alert-flag.tone-down { background: var(--down); color: var(--down-ink); }
.card-alert-flag.tone-warn { background: var(--warn); color: var(--warn-ink); }
.card-alert-flag.tone-rebound { background: var(--rebound); color: var(--rebound-ink); }

/* 「這檔有新聞」——刻意不跟 card-alert-flag 共用右上角位置，也不做成實色徽章：
   這是「有沒有報導」的輕量提示，不是「事件發生」的警示，權重要明顯比警示低。
   見 docs/adr/0007。內容（標題／日期）走原生 title tooltip，細節要看混合時間軸
   （hover 整張卡片，見 app.js showAlertPreview）。 */
.card-news-flag { display: inline-flex; color: var(--text-mute); }
.card-news-flag .icon { width: 14px; height: 14px; stroke-width: 1.9; }

/* 新聞圖示現在是按鈕（1 則直接開原文、多則彈出清單，見 app.js newsButtonHtml），
   外觀維持原本的輕量灰色圖示，只加上按鈕該有的 hover／focus 回饋 */
.news-btn {
  align-items: center;
  justify-content: center;
  padding: 3px;
  margin: 0;
  font: inherit;
  line-height: 0;
  background: none;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: color .15s;
}
.news-btn:hover { color: var(--accent-text); }
.news-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* 觸控裝置手指比滑鼠粗：點擊範圍放大到約 36px，圖示本身大小不變 */
@media (pointer: coarse) {
  .news-btn { min-width: 36px; min-height: 36px; }
  .row-news-flag.news-btn { margin-left: 0; }
}

.news-popover {
  position: fixed;
  z-index: 40;
  width: min(360px, calc(100vw - 16px));
  max-height: min(420px, 70vh);
  display: flex;
  flex-direction: column;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.news-popover-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  background: var(--bg-raise);
  border-bottom: 1px solid var(--line);
}
.news-popover-title { font-size: 14.5px; font-weight: 700; }
.news-popover-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 32px;
  padding: 0;
  color: var(--text-dim);
  background: none;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}
.news-popover-close:hover { color: var(--text); background: var(--bg-hover); }
.news-popover-list { display: flex; flex-direction: column; gap: 6px; padding: 10px; overflow-y: auto; }
/* 手機：從畫面底部滑出的抽屜，不跟著圖示定位（小螢幕上浮在圖示旁邊容易被切掉） */
@media (max-width: 640px) {
  .news-popover {
    left: 0;
    right: 0;
    bottom: 0;
    top: auto;
    width: 100%;
    max-height: 70vh;
    border-radius: 14px 14px 0 0;
    border-bottom: none;
    box-shadow: var(--shadow-lg);
  }
}

.stock-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}
.stock-card-name { font-size: 14.5px; font-weight: 700; margin-bottom: 3px; }
.stock-card-head-right {
  display: flex;
  align-items: center;
  gap: 6px;
}
.stock-card-code {
  font-size: 11px;
  color: var(--text-mute);
  font-family: var(--mono);
  white-space: nowrap;
  padding-top: 1px;
}

/* 收藏用的星星——空心＝還沒收藏，實心＋Console Blue＝已收藏。用互動／選取色
   （--accent）而不是紅漲綠跌或琥珀，因為這是使用者自己的選取狀態，跟股價方向
   或反轉警示語意完全無關，混用顏色會讓使用者以為星星也代表某種漲跌訊號。 */
.my-watchlist-star {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 3px;
  background: none;
  border: none;
  color: var(--text-dim);
  cursor: pointer;
  font-size: 20px;
  line-height: 0;
  border-radius: 4px;
  transition: color .15s, transform .15s;
}
/* 這顆圖示故意比全站其他 .icon 粗（2.75 而不是共用的 1.75）——18~20px 大小下，
   共用的細線寬度會薄到跟旁邊 .stock-card-code 那種次要灰字混在一起看不出來是
   顆按鈕，加粗才讓「這是一顆星星、可以點」這件事一眼就看得出來。 */
.my-watchlist-star .icon { stroke-width: 2.75; }
.my-watchlist-star:hover { color: var(--accent-text); transform: scale(1.12); }
.my-watchlist-star.active { color: var(--accent-text); }
.my-watchlist-star.active .icon { fill: currentColor; stroke-width: 1.75; }
.my-watchlist-star:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* 表格視圖：星星跟股名同一行，不需要獨立的 head-right 容器 */
.sym-name .my-watchlist-star { margin-right: 2px; vertical-align: -2px; }

/* 站長持股按鈕（公事包）：只有站長帳號看得到，跟 ☆ 同一個手感；按下去的狀態用強調色（選取狀態，One Accent Rule 允許） */
.owner-hold-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 3px;
  font-size: 18px;
  line-height: 0;
  color: var(--text-mute);
  background: none;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: color .15s, transform .15s;
}
.owner-hold-btn .icon { stroke-width: 2; }
.owner-hold-btn:hover { color: var(--accent-text); transform: scale(1.12); }
.owner-hold-btn.active { color: var(--accent-text); }
.owner-hold-btn.active .icon { stroke-width: 2.6; }
.owner-hold-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.sym-name .owner-hold-btn { margin-right: 2px; vertical-align: -2px; }

/* 「我的持股」tab 的星星是純裝飾，永遠實心，跟著 chip 目前的文字顏色走
   （未選取時是 --text-dim，選取中變成 .active 那個深色，見 .industry-tabs .chip.active）。 */
.my-watchlist-tab .icon { fill: currentColor; }
.stock-card-price {
  font-size: 26px;
  font-weight: 800;
  font-family: var(--mono);
  line-height: 1;
  letter-spacing: -0.01em;
}
.stock-card-price.tone-up   { color: var(--up-text); }
.stock-card-price.tone-down { color: var(--down-text); }
.stock-card-price.tone-idle { color: var(--text); }
.stock-card-price.tone-none { color: var(--text-mute); font-weight: 400; }

/* 不用 overflow:hidden 裁圓角：現價超出關卡時位置點會停在最左或最右，被裁掉一半——偏偏那是
   最需要看清楚的時候。圓角改由兩端的警戒區自己帶（2026-10-06） */
.stock-card-band { position: relative; height: 14px; border-radius: 999px; background: var(--bg); }

/* 端點警戒區＋位置點：見 app.js 的 bandZoneMarkup 說明。兩端各留 BAND_ZONE_PCT（16%）
   寬的警戒區，平常是淡色（--down-soft／--up-soft），現價點一旦進入哪一端，那一端就
   整段點亮成飽和色——跟現有「量級長條」的軌道＋填色語言不同，是刻意的新元件：
   支撐／壓力的「位置」需要標兩個方向的距離，不是單一量值的填色能表達的，跟大盤
   系統性風險日的跌幅長條（單一方向的量值）分開處理，不用勉強套同一套視覺語言。 */
.band-zone { position: absolute; top: 0; bottom: 0; width: 16%; transition: background .15s ease; }
.band-zone.zone-support { left: 0; background: var(--down-soft); border-radius: 999px 0 0 999px; }
.band-zone.zone-resistance { right: 0; background: var(--up-soft); border-radius: 0 999px 999px 0; }
.band-zone.zone-support.active { background: var(--down); }
.band-zone.zone-resistance.active { background: var(--up); }
.band-marker {
  position: absolute;
  top: 50%;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--text);
  border: 2px solid var(--bg-raise);
  transform: translate(-50%, -50%);
  z-index: 1;
}

.stock-card-levels {
  display: flex;
  justify-content: space-between;
  font-size: 12.5px;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.stock-card-levels b { color: var(--text); font-weight: 700; font-family: var(--mono); }

.stock-card-foot { display: flex; justify-content: flex-end; }
/* 抓價失敗是系統狀態，不是行情訊號：中性灰＋警告圖示，不用琥珀（琥珀是假突破專用，2026-10-06） */
.stock-card-err { display: inline-flex; align-items: center; gap: 4px; font-size: 11.5px; color: var(--text-dim); }
.table-tools { display: flex; gap: 8px; flex-wrap: wrap; padding: 0 16px; }
.table-tools input, .table-tools select,
.row input, .row select, .field input {
  padding: 5px 9px;
  font-size: 12.5px;
  font-family: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.table-tools input:focus, .table-tools select:focus,
.row input:focus, .field input:focus { outline: 1px solid var(--accent); }

/* ---------------- 收合式搜尋（膠囊） ----------------
   平常只留一顆放大鏡（56px），點下去才滑開成完整輸入框。監控清單上方本來就擠了
   產業分頁＋排序下拉，搜尋不是每分鐘都在用，收起來可以把橫向空間讓給資料本身。

   動畫只動 width 這一個屬性——寬度變化會觸發 reflow，同時再去動 padding、
   font-size 之類的東西會讓每一幀都重排更多內容，滑起來就會頓。圖示用絕對定位
   釘在左邊，不參與寬度變化，展開時才不會跟著位移。 */
.search-pill {
  position: relative;
  display: flex;
  align-items: center;
  width: 56px;
  max-width: 100%;
  overflow: hidden;              /* 收合時把還沒滑出來的輸入文字裁掉 */
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
  transition: width .4s cubic-bezier(.16, 1, .3, 1);
}
/* 有輸入內容時保持展開：不然一移開焦點就縮回去，使用者會看不到自己搜了什麼 */
.search-pill:focus-within,
.search-pill.has-value { width: 300px; }

/* 滑鼠移上去就自動展開，不用先點一下。用 (hover: hover) 包起來只讓真的有游標的
   裝置吃這條——觸控螢幕上「點一下」常會被瀏覽器當成 hover 並且黏住不放，
   那樣手機使用者會遇到搜尋框莫名展開又收不回去 */
@media (hover: hover) {
  .search-pill:hover { width: 300px; }
  .search-pill:hover .search-pill-icon { color: var(--accent-text); }
}

.search-pill-icon {
  position: absolute;
  left: 19px;                    /* 收合成 56px 時剛好落在膠囊正中央 */
  width: 16px;
  height: 16px;
  color: var(--text-mute);
  pointer-events: none;          /* 點圖示等於點輸入框，不要擋住焦點 */
  transition: color .4s ease;
}
.search-pill:focus-within .search-pill-icon,
.search-pill.has-value .search-pill-icon { color: var(--accent-text); }

/* 輸入框本身撐滿膠囊，這樣收合狀態下點任何一處都能聚焦 */
.table-tools .search-pill input {
  width: 100%;
  padding: 6px 14px 6px 44px;    /* 左邊留給釘住的圖示 */
  background: none;
  border: none;
  border-radius: inherit;
}
/* 焦點指示交給膠囊外框，輸入框自己不要再畫一圈（會被 overflow 裁掉變半截） */
.table-tools .search-pill input:focus,
.table-tools .search-pill input:focus-visible { outline: none; }
.search-pill:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb), .15);
}


.table-wrap { max-height: calc(100vh - 210px); overflow: auto; }

table { width: 100%; border-collapse: collapse; }

thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 8px 12px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 1px;
  color: var(--text-mute);
  text-align: left;
  background: var(--bg-raise);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
thead th.num { text-align: right; }

tbody td {
  padding: 7px 12px;
  border-bottom: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
tbody tr { cursor: pointer; transition: background-color .12s ease; }
tbody tr:hover { background: var(--bg-hover); }
tbody tr:active { background: var(--bg-raise); }
td.num { text-align: right; font-family: var(--mono); }

/* 表格版的「今天有觸發」——卡片版是整圈邊框加粗，表格列沒有框可以加粗，改用
   左側粗色條（平常的列完全沒有邊框，這個對比本身就很搶眼）＋淡底色，圖示旗標
   （.row-alert-flag）才是主要線索，這兩個色彩線索只是輔助 */
/* 2026-10-06 拿掉左側 3px 色條（DESIGN.md 的 Don't：不用單邊粗色條當狀態），只留很淡的
   底色——主要線索是列裡的旗標（.row-alert-flag）。底色比 *-soft 再淡一半：原本那層底色
   讓同一列的灰字掉到 4.4:1 */
.row-hit-today.tone-up   { background: color-mix(in srgb, var(--up) 7%, transparent); }
.row-hit-today.tone-down { background: color-mix(in srgb, var(--down) 7%, transparent); }
.row-hit-today.tone-warn { background: color-mix(in srgb, var(--warn) 7%, transparent); }
.row-hit-today.tone-rebound { background: color-mix(in srgb, var(--rebound) 7%, transparent); }
.row-hit-today:hover { background: var(--bg-hover); }
.row-alert-flag {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin-left: 6px;
  padding: 1px 7px;
  font-size: 10.5px;
  font-weight: 700;
  border-radius: 999px;
  vertical-align: middle;
}
.row-alert-flag .icon { width: 11px; height: 11px; stroke-width: 2.2; }
.row-alert-flag.tone-up   { background: var(--up);   color: var(--up-ink); }
.row-alert-flag.tone-down { background: var(--down); color: var(--down-ink); }
.row-alert-flag.tone-warn { background: var(--warn); color: var(--warn-ink); }
.row-alert-flag.tone-rebound { background: var(--rebound); color: var(--rebound-ink); }

/* 表格視圖的「這檔有新聞」，跟卡片版 .card-news-flag 同一個理由不共用
   row-alert-flag 的實色徽章樣式，見 docs/adr/0007。 */
.row-news-flag { display: inline-flex; margin-left: 6px; color: var(--text-mute); vertical-align: middle; }
.row-news-flag .icon { width: 12px; height: 12px; stroke-width: 1.9; }

.sym-name { font-weight: 600; font-size: 12.5px; }
.sym-meta { font-size: 11px; color: var(--text-mute); font-family: var(--mono); }
.sym-industry {
  display: inline-block;
  padding: 0 5px;
  margin-right: 5px;
  font-size: 11px;
  color: var(--accent-text);
  background: rgba(var(--accent-rgb), 0.12);
  border-radius: 999px;
  font-family: inherit;
}
/* 暗版的強調藍只給能點的東西；題材標籤不是按鈕，改用中性灰（亮版照舊） */
:root:not([data-theme="light"]) .sym-industry { color: var(--text-dim); background: var(--bg-hover); }

.price { font-weight: 700; font-size: 14px; }
.price.up { color: var(--up-text); }
.price.down { color: var(--down-text); }
.price.none { color: var(--text-mute); font-weight: 400; }

.gap { font-size: 12.5px; color: var(--text-dim); }
/* 「近」是距離提示，不是警示本身——Amber 保留給真正觸發的破底翻警示，
   這裡只用提亮＋加粗表示「這個數字比較值得看」 */
.gap.near { color: var(--text); font-weight: 700; }

/* 位階長條 */
.band { position: relative; width: 96px; height: 12px; background: var(--bg); border-radius: 999px; }
.band-num { font-size: 11px; color: var(--text-mute); margin-top: 2px; font-family: var(--mono); }

.badge {
  display: inline-block;
  padding: 1px 8px;
  font-size: 11.5px;
  font-weight: 600;
  border-radius: 999px;
  border: 1px solid transparent;
}
.badge.idle  { color: var(--text-dim); border-color: var(--line); }
.badge.above { color: var(--up-text);   background: var(--up-soft);   border-color: var(--up); }
.badge.below { color: var(--down-text); background: var(--down-soft); border-color: var(--down); }
.badge.err   { color: var(--text-dim); border-color: var(--line); }

/* 注意／處置：交易所公告的官方狀態，跟上面 idle/above/below/err（都是「現價站
   在哪個位置」這條軸線）分開，套 .disposition 修飾類別只是為了跟既有 .badge
   共用同一份形狀／字級，不是重新設計一顆徽章。用 margin-right:auto 把它推到
   卡片下方那排的最左邊，右邊的 above/below/idle 徽章維持原本靠右對齊的位置
   不變——平常沒有注意/處置狀態的卡片（絕大多數）這排完全不會受影響。
   margin-left 是另一個情境：表格視圖（.sym-name）裡這顆徽章是緊接在股名
   文字後面的行內元素，不在 flex 容器裡，margin-right:auto 在那裡不會有
   任何效果，徽章會直接貼著股名——加左邊距離跟 .row-alert-flag 用同一個
   6px，讓兩種情境下都跟前面的文字有分隔感。 */
.badge.disposition { margin-right: auto; margin-left: 6px; }
/* 注意股跟處置股是同一軸（交易所公告的法規狀態），都用處置紫：處置填淡底，注意只描邊，看得出輕重。
   2026-10-06 之前注意股用琥珀，撞到假突破那一軸 */
.badge.notice { color: var(--punish-text); background: transparent;         border-color: var(--punish); }
.badge.punish { color: var(--punish-text); background: var(--punish-soft); border-color: var(--punish); }

/* 除權息預告（10 天內要除權息的股票，見 app.js 的 exDivMeta）。不是漲跌方向、也不是交易所的
   法規狀態，所以不借紅綠、不借處置紫：中性描邊，日期用等寬。卡片上靠左（跟處置徽章同一側，
   兩顆都有時除權息在前），表格裡接在股名後面。 */
.badge.exdiv { margin-right: auto; color: var(--text); background: transparent; border-color: var(--text-mute); white-space: nowrap; }
.badge.exdiv b { font-family: var(--mono); font-weight: 700; font-variant-numeric: tabular-nums; }
.stock-card-foot .badge.exdiv:has(+ .disposition) { margin-right: 0; }
.stock-card-foot .stock-card-err + .badge.exdiv { margin-left: 6px; }
.sym-name .badge.exdiv { margin-left: 6px; margin-right: 0; }

/* 面板最下面那一段說明。11.5px 原本是整頁最小的字，偏偏這幾段是寫給第一次來的人看的說明——
   跟 .hint 同一級（12.5px）、行高 1.6（2026-10-10）。
   寬度不要動：同一天試過把字收到「一行最多 50 個字」（靠左一窄條），桌機的面板一千七百多 px 寬，
   右邊六成變成空白，站長看了說空白太多、原本的比較好看。桌機照樣排滿面板；手機本來一行就只有二十幾個字。
   見 DESIGN.md「說明文字：桌機排滿，不收成一窄條」。 */
.table-foot { margin: 0; padding: 9px 16px; font-size: 12.5px; line-height: 1.6; color: var(--text-mute); border-top: 1px solid var(--line); }
.legend-up { color: var(--up-text); font-weight: 700; }
.legend-down { color: var(--down-text); font-weight: 700; }
/* 卡片上面那行顏色對照（原本是清單最底下的 .table-foot，2026-10-24 搬上來） */
.grid-legend { margin: 8px 16px 0; font-size: 12.5px; line-height: 1.6; color: var(--text-mute); }
/* 只有滑鼠用得到的說明（「滑鼠停在卡片上…」），手機、平板觸控不寫 */
@media (hover: none) { .hover-only { display: none; } }

/* 手機收起來的資料說明（app.js 的 foldMethodNotes）：桌機沒有開關、說明照舊攤開 */
.foot-toggle { display: none; }
@media (max-width: 640px) {
  .foot-toggle {
    display: flex; align-items: center; gap: 4px; width: 100%; min-height: 44px; padding: 0 12px;
    font: inherit; font-size: 12.5px; color: var(--text-mute); text-align: left;
    background: none; border: 0; border-top: 1px solid var(--line); cursor: pointer;
  }
  .foot-toggle::after { content: "▾"; transition: transform .16s ease; }
  .foot-toggle[aria-expanded="true"]::after { transform: rotate(180deg); }
  .table-foot.foot-foldable { display: none; }
  .table-foot.foot-foldable.foot-open { display: block; padding-top: 0; border-top: 0; }
}

.empty { padding: 26px 16px; text-align: center; color: var(--text-mute); font-size: 12.5px; }
/* 表格裡那一整列的訊息（沒有資料、載不進來）：全站的 tbody td 預設不折行，手機上長一點的句子會被切掉 */
td.empty { white-space: normal; }
/* 監控清單、今日精選一開始寫的「資料載入中…」：那兩個容器是格狀的，字要橫跨整排、置中 */
.stock-grid > .empty, .picks-row > .empty { grid-column: 1 / -1; width: 100%; margin: 0; }
/* 我的自選：族群標題（2026-10-26）。卡片網格裡佔滿一整行；表格裡是一列。第一個族群上面不留空 */
.my-group-head {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 10px 0 -2px;
  padding: 0 2px 6px;
  border-bottom: 1px solid var(--line);
}
.stock-grid > .my-group-head:first-child { margin-top: 0; }
.my-group-name { font-size: 15px; font-weight: 800; color: var(--text); }
.my-group-count { font-size: 12.5px; color: var(--text-mute); }
/* 我的自選裡的美股（2026-11-12）：美股沒有即時卡片，列成一排可以點的代號，點了開支撐壓力圖 */
.my-us-strip { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px; margin: 0 0 12px; padding: 0 2px 10px; border-bottom: 1px solid var(--line); }
.my-us-strip[hidden] { display: none; }
.my-market-toggle { margin: 0 0 12px; }
.my-market-toggle[hidden] { display: none; }
.my-us-strip .my-group-name { font-size: 15px; font-weight: 800; color: var(--text); }
.my-us-strip .my-group-count { margin-right: 4px; font-size: 12.5px; color: var(--text-mute); }
.my-us-chip { min-height: 32px; padding: 4px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--bg-raise); color: var(--text); font-size: 13px; cursor: pointer; }
.my-us-chip:hover, .my-us-chip:focus-visible { border-color: var(--accent); }
#stock-body .my-group-row td { padding: 14px 12px 6px; border-bottom: 1px solid var(--line); background: var(--bg-raise); }
#stock-body .my-group-row:first-child td { padding-top: 8px; }
#stock-body .my-group-row .my-group-count { margin-left: 8px; }
/* 強勢榜個股結構榜：依族群排序時每一族群前面一列（2026-10-26），字樣跟我的自選的族群標題同一套 */
#stock-body .stk-group-row td { padding: 14px 16px 6px; border-bottom: 1px solid var(--line); background: var(--bg-raise); cursor: default; }
#stock-body .stk-group-row .my-group-count { margin-left: 8px; }
.stk-group-rank { margin-right: 8px; font-size: 13px; font-weight: 700; color: var(--text-mute); }
/* 個股結構榜「套牢比 ≤ __%」（2026-10-26）：數字框小小一格，跟勾選同一行 */
.supply-filter { display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }
.supply-filter-input {
  /* 2026-10-26 站長回報桌機只看得到「3」：Chrome 的上下箭頭吃掉右邊一截，3.4em 放不下兩位數。
     箭頭拿掉、寬度照等寬字算（三位數 100 也放得下） */
  box-sizing: border-box;
  width: calc(3ch + 20px);
  padding: 2px 8px;
  -moz-appearance: textfield;
  appearance: textfield;
  font: inherit;
  font-family: var(--mono);
  font-size: 14px;
  text-align: right;
  color: var(--text);
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.supply-filter-input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.supply-filter-input::-webkit-inner-spin-button, .supply-filter-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
@media (pointer: coarse) { .supply-filter-input { min-height: 32px; font-size: 16px; } }
/* 個股結構榜「族群名次看 20 日／近 5 日」（2026-10-26） */
.stock-rank-pick { display: inline-flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--text-dim); white-space: nowrap; }
.stock-rank-pick .view-btn { font-size: 12.5px; padding: 4px 10px; }
.stk-group-rank.rank-lead { color: var(--accent-text); }
@media (max-width: 640px) {
  .review-stock-wrap #stock-body .stk-group-row { display: block; }
  .review-stock-wrap #stock-body .stk-group-row td { display: block; padding: 12px 12px 6px; }
}
/* 監控清單空的時候：說是哪個篩選擋掉的，下面一顆「清除篩選」（2026-10-06） */
.table-empty p { margin: 0 0 12px; font-size: 13.5px; color: var(--text-dim); }

/* 「再顯示 20 檔」「再看 10 則」：只有手機會出現（桌機清單整份畫出、警示紀錄自己內捲動）。
   括號裡的剩餘數量是輔助資訊，降一階顏色 */
.alert-more { display: none; }
.list-more { display: flex; padding: 4px 10px 14px; }
.list-more .ghost-btn { flex: 1; justify-content: center; min-height: 44px; }
.list-more .ghost-btn, .alert-more .ghost-btn { gap: 0; font-size: 13.5px; } /* 全形括號自己帶空白，不用再加 gap */
.more-count { color: var(--text-mute); font-weight: 400; }
.table-empty .icon { width: 14px; height: 14px; vertical-align: -2px; }

/* 站長持股（非會員，2026-10-21）：分頁上一個小鎖；點進去一排模糊的假卡片，中間蓋一張說明。
   假卡片裡沒有真的資料（名單沒送到瀏覽器），模糊只是樣子。 */
.owner-tab-locked .owner-lock-icon { width: 12px; height: 12px; margin-left: 2px; opacity: .75; }
.table-empty:has(.owner-locked) { padding: 0; text-align: left; }
.owner-locked { position: relative; min-height: 320px; overflow: hidden; border-radius: 10px; }
.owner-fake-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 10px;
  padding: 12px;
  filter: blur(7px);
  opacity: .7;
  pointer-events: none;
  user-select: none;
}
.owner-fake-card { padding: 14px; background: var(--bg-raise); border: 1px solid var(--line); border-radius: 10px; }
.ofc-top { display: flex; align-items: baseline; gap: 8px; }
.ofc-name { font-size: 14.5px; font-weight: 700; color: var(--text); }
.ofc-sym { font-family: var(--mono); font-size: 12px; color: var(--text-mute); }
.ofc-price { margin-top: 8px; font-family: var(--mono); font-size: 20px; font-weight: 800; color: var(--up-text); }
.owner-fake-card:nth-child(3n+2) .ofc-price { color: var(--down-text); }
.ofc-bar { height: 6px; margin-top: 10px; background: var(--line); border-radius: 3px; overflow: hidden; }
.ofc-bar i { display: block; height: 100%; background: var(--text-dim); }
.ofc-lines { display: flex; justify-content: space-between; margin-top: 10px; font-family: var(--mono); font-size: 12px; color: var(--text-mute); }
.owner-lock-box {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(440px, calc(100% - 32px));
  padding: 20px 22px;
  text-align: center;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .35);
}
.owner-lock-badge { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; color: var(--text); background: var(--bg-raise); border: 1px solid var(--line); border-radius: 50%; }
.owner-lock-badge .owner-lock-icon { width: 20px; height: 20px; margin: 0; opacity: 1; }
.table-empty .owner-lock-title { margin: 10px 0 6px; font-size: 16px; font-weight: 700; color: var(--text); }
.table-empty .owner-lock-text { margin: 0 0 14px; font-size: 13.5px; line-height: 1.6; color: var(--text-dim); }
.owner-lock-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.owner-lock-actions a { text-decoration: none; }
.owner-lock-how { display: inline-block; margin-top: 12px; font-size: 12.5px; color: var(--accent-text); }
@media (pointer: coarse) { .owner-lock-how { padding-block: 6px; } }

/* ---------------- 國際行情 ---------------- */
/* 跟上面一整排全市場統計面板之間多留一點呼吸空間，
   視覺上區分「盯盤主戰場」（即時警示／監控清單）跟「輔助參考數據」——
   現在這排輔助面板的第一個是國際行情，這條間距規則跟著搬過來 */
.panel-global { grid-column: 1 / -1; margin-top: 8px; }

.global-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 6px;
  padding: 14px 16px;
}
.global-tile {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 10px 10px 8px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  transition: border-color .14s ease, transform .1s ease;
}
.global-tile:hover { border-color: var(--text-mute); }
.global-tile:active { transform: scale(.98); }.global-tile .g-name { font-size: 12.5px; font-weight: 600; color: var(--text-dim); }
.global-tile .g-price { font-size: 16px; font-weight: 700; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.global-tile .g-pct { font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.global-tile .g-pct.up   { color: var(--up-text); }
.global-tile .g-pct.down { color: var(--down-text); }

/* K棒預覽：hover 層級的浮層，用 md 陰影（lg 保留給彈窗）；K 棒是資料，紅漲綠跌 */
.kbar-preview {
  position: fixed;
  z-index: 30;
  width: 300px;
  padding: 10px 12px 10px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: var(--shadow-md);
  cursor: pointer;
}
.kbar-preview[hidden] { display: none; }
.kp-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.kp-name { font-size: 13px; font-weight: 700; color: var(--text); }
.kp-hint { font-size: 11px; color: var(--text-mute); }
.kp-chart { display: block; width: 100%; height: 120px; border-radius: 6px; }
.kbar-preview.is-loading .kp-chart { background: var(--bg-raise); }
.kp-active { fill: var(--line); }
.kp-candle line { stroke-width: 1; }
.kp-candle.up line { stroke: var(--up); }
.kp-candle.up rect { fill: var(--up); }
.kp-candle.down line { stroke: var(--down); }
.kp-candle.down rect { fill: var(--down); }
.kp-candle.flat line { stroke: var(--text-mute); }
.kp-candle.flat rect { fill: var(--text-mute); }
.kp-nums { margin-top: 8px; min-height: 38px; }
.kp-row1 { display: flex; align-items: baseline; gap: 10px; }
.kp-date, .kp-close, .kp-chg, .kp-row2 { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.kp-date { font-size: 12px; color: var(--text-mute); }
.kp-close { font-size: 15px; font-weight: 700; color: var(--text); }
.kp-chg { font-size: 12px; font-weight: 600; }
.kp-chg.up { color: var(--up-text); }
.kp-chg.down { color: var(--down-text); }
.kp-chg.flat { color: var(--text-mute); }
.kp-row2 { display: flex; gap: 12px; margin-top: 3px; font-size: 11.5px; color: var(--text-dim); }
.kp-status { font-size: 12px; color: var(--text-mute); }

/* ---------------- 全市場漲跌家數 ---------------- */
.panel-breadth { grid-column: 1 / -1; }

.breadth-bar {
  display: flex;
  height: 8px;
  margin: 14px 16px 0;
  border-radius: 4px;
  overflow: hidden;
  background: var(--line);
}
.breadth-bar > span { height: 100%; }
.breadth-bar > span.limit-up,
.breadth-bar > span.up { background: var(--up); }
.breadth-bar > span.flat { background: var(--text-mute); }
.breadth-bar > span.limit-down,
.breadth-bar > span.down { background: var(--down); }

.breadth-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 6px;
  padding: 10px 16px 14px;
}
.breadth-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 10px 8px;
  border-radius: 8px;
  background: var(--bg-raise);
}
.breadth-stat .bs-label { font-size: 11.5px; color: var(--text-mute); }
.breadth-stat .bs-count { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; }
.breadth-stat.limit-up .bs-count,
.breadth-stat.up .bs-count { color: var(--up-text); }
.breadth-stat.limit-down .bs-count,
.breadth-stat.down .bs-count { color: var(--down-text); }
.breadth-stat.flat .bs-count { color: var(--text-mute); }

/* ---------------- 台指期與櫃買指數（漲跌家數面板內嵌的兩張支撐壓力圖） ----------------
   彈窗那張圖的唯讀縮小版，一左一右。標題列一行：名稱、最新（或滑鼠指到那天）的
   日期與開高低收；數字是要比大小的，一律等寬。圖本身不吃滾輪與拖曳，點了開彈窗。 */
.index-charts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  padding: 0 16px 14px;
}
.index-chart {
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--chart-bg);
  overflow: hidden;
}
.ic-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 8px 8px 12px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-raise);
}
/* 文字太長時是數字那一段往下折，按鈕永遠留在右邊同一列 */
.ic-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
}
.ic-name { font-size: 14.5px; font-weight: 700; }
.ic-tag { font-size: 11.5px; color: var(--text-mute); }
.ic-quote {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  color: var(--text-dim);
}
.ic-date { color: var(--text-mute); }
.ic-ohl { display: flex; flex-wrap: wrap; gap: 0 10px; }
.ic-ohl > span { white-space: nowrap; } /* 折行時整組「低 48,158」一起下去，不要標籤跟數字拆兩行 */
.ic-close { font-size: 15px; font-weight: 700; color: var(--text); }
.ic-chg { font-weight: 600; }
.ic-chg.up { color: var(--up-text); }
.ic-chg.down { color: var(--down-text); }
.ic-chg.flat { color: var(--text-mute); }
.ic-open { flex: none; padding: 4px 10px; font-size: 12px; }
/* 3:2：比原本 300px 高的扁長條高得多（撐壓線上下拉得開），但不到正方形那麼佔版面。
   高度封頂在 80vh，一張圖連標題列一定塞得進一個畫面（手機橫拿時也是），不用捲動
   才看得到底部的時間軸；下限也跟著畫面高度走，矮畫面不會被下限撐破。 */
.ic-canvas { aspect-ratio: 3 / 2; max-height: 80vh; min-height: min(260px, 80vh); cursor: grab; } /* 圖是拖曳用的，開彈窗只在右上角按鈕 */
.ic-canvas:active { cursor: grabbing; }

/* ---------------- 產業熱力圖 ---------------- */
.panel-heatmap { grid-column: 1 / -1; }

.heatmap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 6px;
  padding: 14px 16px;
}

.heatmap-tile {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  padding: 10px 10px 8px;
  border-radius: 8px;
  color: var(--text);
  min-height: 64px;
}
.heatmap-tile .hm-name { font-size: 12.5px; font-weight: 600; line-height: 1.25; }
.heatmap-tile .hm-pct { font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; }
.heatmap-tile .hm-turnover { font-size: 11px; font-variant-numeric: tabular-nums; }
/* 手機只先放成交值最大的 9 格（app.js 的 renderHeatmapMore）；桌機、平板全部攤開，沒有這顆鈕 */
.ghost-btn.heatmap-more { display: none; } /* 兩個 class：.ghost-btn 的 display 寫在後面，只寫一個會被蓋過去 */
@media (max-width: 640px) {
  .heatmap-grid:not(.hm-all) .heatmap-tile:nth-child(n+10) { display: none; }
  .ghost-btn.heatmap-more:not([hidden]) { display: flex; justify-content: center; width: calc(100% - 24px); min-height: 44px; margin: -6px 12px 12px; }
}

/* ---------------- 產業資金流向 ---------------- */
.panel-fundflow { grid-column: 1 / -1; }

.fundflow-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; padding: 14px 16px; }
.fundflow-title { margin: 0 0 8px; font-size: 12.5px; font-weight: 700; }
.fundflow-title.in { color: var(--up-text); }
.fundflow-title.out { color: var(--down-text); }
.fundflow-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  margin-bottom: 5px;
  background: var(--bg-raise);
  border-radius: 6px;
  font-size: 12.5px;
}
.fundflow-row .ff-name { flex: 0 0 auto; color: var(--text-dim); }
.fundflow-row .ff-bar-track { flex: 1 1 auto; height: 4px; border-radius: 999px; background: var(--bg); overflow: hidden; }
.fundflow-row .ff-bar { display: block; height: 100%; border-radius: 999px; }
.fundflow-row .ff-bar.up { background: var(--up); }
.fundflow-row .ff-bar.down { background: var(--down); }
.fundflow-row .ff-value { flex: 0 0 auto; font-weight: 700; font-variant-numeric: tabular-nums; }
.fundflow-row .ff-value.up { color: var(--up-text); }
.fundflow-row .ff-value.down { color: var(--down-text); }

/* ---------------- 系統性風險日（大盤＋櫃買） ---------------- */
.panel-crash { grid-column: 1 / -1; }

.crash-list { display: flex; flex-direction: column; gap: 6px; padding: 14px 16px; }

/* 哪個市場出事的標籤。紅綠留給漲跌資料本身、語意色只有四軸（見 DESIGN.md），所以兩個市場
   不靠換色分辨，靠形狀與填滿：大盤＝實心方角、櫃買＝空心膠囊。「全部」清單裡兩個市場
   交錯出現，這樣不用讀字也分得出來。 */
.crash-market {
  font-size: 12px;
  font-weight: 700;
  padding: 1px 7px;
  text-align: center;
  color: var(--text-dim);
  border: 1px solid var(--line);
  border-radius: 4px;
  white-space: nowrap;
}
.crash-market[data-market="taiex"] { color: var(--fill-ink); background: var(--text-dim); border-color: var(--text-dim); }
.crash-market[data-market="otc"] { border-color: var(--text-dim); border-radius: 999px; }

.crash-manual-list { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; }
.crash-manual-row {
  display: grid;
  grid-template-columns: 92px 44px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 7px 12px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.crash-manual-row .crash-date { font-size: 12.5px; color: var(--text-dim); font-family: var(--mono); white-space: nowrap; }
.crash-manual-row .crash-manual-value { font-size: 12.5px; font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--down-text); }

/* 2026-10-06 降一階：原本 18px 粗長條＋19px 粗體綠字，二十幾列攤開是整頁最吵的一塊。
   長條收成 6px（DESIGN.md 量級長條家族的最細一級），大字 15px，列高跟著縮 */
.crash-row {
  display: grid;
  grid-template-columns: 92px 44px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 6px 12px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.crash-row .crash-date { font-size: 12.5px; color: var(--text-dim); font-family: var(--mono); white-space: nowrap; }
.crash-row .crash-bar-track { position: relative; height: 6px; background: var(--bg); border-radius: 3px; overflow: hidden; }
.crash-row .crash-bar-fill { position: absolute; top: 0; bottom: 0; left: 0; background: var(--down); border-radius: 3px; }
.crash-row .crash-value-group { text-align: right; line-height: 1.15; }
.crash-row .crash-value {
  font-size: 15px;
  font-weight: 700;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  color: var(--down-text);
}
#crash-list .crash-more { display: flex; width: fit-content; min-height: 36px; margin: 10px auto; } /* 要贏過後面 .ghost-btn 的 display */
.crash-row .crash-pct { font-size: 11px; font-weight: 600; color: var(--text-mute); font-variant-numeric: tabular-nums; }

/* 主畫面底部的免責聲明。刻意做得安靜——這是有對價關係的服務（會員費）該有的
   法律聲明，但它不該搶走看盤畫面的注意力，一行小字放在最後就夠。
   .site-footer-row 是外層容器（原本這些版面屬性都在 .site-disclaimer 自己身上，
   現在挪出來，因為同一行右側多了一顆頻道 logo，disclaimer 自己只管字體樣式）。 */
.site-footer-row {
  grid-column: 1 / -1;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin: 4px 0 0;
  padding: 12px 4px 0;
  border-top: 1px solid var(--line);
}
.site-disclaimer {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--text-mute);
}
/* 免責聲明後面的一個連結（加到手機主畫面的教學，2026-10-10）：跟聲明一樣安靜，只多一條底線。
   自己一行——接在句號後面會被讀成聲明的一部分；上下多留一點，手指才點得到。 */
.site-footer-link {
  display: block;
  width: fit-content;
  margin-top: 2px;
  padding: 5px 0;
  color: var(--text-dim);
  text-decoration: underline;
  text-decoration-color: var(--text-mute);
  text-underline-offset: 3px;
}
.site-footer-link:hover { color: var(--text); }
@media (pointer: coarse) {
  .site-footer-link { padding: 13px 0; }
}

/* 頻道 logo（Greedy Leek）——延續免責聲明「刻意安靜」的語言，平常幾乎融入
   背景（低透明度），滑過去才看清楚，不是要搶眼的品牌置入。 */
.site-channel-badge {
  flex-shrink: 0;
  margin-top: 1px;
  opacity: .55;
  transition: opacity .16s ease;
}
.site-channel-badge:hover { opacity: 1; }
/* 觸控裝置：徽章只有 17px，用看不見的範圍把點擊區撐到 41px，外觀不變 */
@media (pointer: coarse) {
  .site-channel-badge, .login-channel-badge { position: relative; }
  .site-channel-badge::after, .login-channel-badge::after { content: ""; position: absolute; inset: -12px; }
}
.site-channel-badge img { display: block; width: 17px; height: 17px; object-fit: contain; }

@media (max-width: 640px) {
  .site-footer-row { flex-wrap: wrap; }
}

/* ---------------- 付費版說明頁 ----------------
   /upgrade 已經改用自己獨立的設計系統（static/upgrade.css），不再套用這份監控站
   的樣式表——這頁的工作是說服人，不是給人盯盤，理由跟取捨見 docs/adr/0009。 */

/* ---------------- 免費版 ----------------
   ⚠️ 這一整段都只是「視覺」。真正的遮蔽在伺服器端就做完了（見 app.py 的
   _apply_free_filter）——被鎖住的欄位根本沒有送到瀏覽器。這裡畫的鎖頭是
   佔位符號，不是蓋在真實數字上面的遮罩，按 F12 也挖不出東西。
   2026-10-06 起三頁的佔位符號都是鎖頭（.lock-cell，見 app.js 的 lockMark）：原本看盤畫面
   用模糊條、題材輪動和強勢榜用鎖頭，同一件事三種樣子。 */
.stock-card-levels .lock-cell { vertical-align: -2px; }

/* 被鎖住的卡片：只有關卡被模糊條蓋住，其餘照常。2026-10-06 之前整張卡壓暗到 .72，
   連免費版本來就看得到的現價、代號都跟著掉到 3:1 上下（現價 2.95:1，比大字的門檻還低），
   ADR 0014 說只遮關卡，不遮股價。今日 5 檔靠釘在最上面、加框、角標「今日免費」就認得出來，
   不需要把其他 266 張卡變暗來襯托。 */
.row-locked .gap { opacity: .72; }

/* 今日免費 5 檔：釘在最上面，加一條 accent 邊框跟角標，一眼認得出「這幾檔我看得到」 */
.card-pick { border-color: var(--accent); }
.pick-flag {
  position: absolute;
  top: -8px;
  left: 10px;
  z-index: 2;
  padding: 1px 7px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--accent-ink);
  background: var(--accent);
  border-radius: 999px;
}
.pick-flag.inline {
  position: static;
  margin-left: 6px;
  font-size: 11px;
}

/* ---------------- 今日精選＋我的自選（訪客、免費版，見 docs/adr/0020、app.js 的 renderPicksPanel） ----------------
   看盤畫面最上面一條，橫跨兩欄：左邊系統每天挑的 5 檔，右邊自己選的 3 檔。兩塊分開放，
   不是同一份清單。小卡比清單的股票卡精簡（股名、現價、撐壓、狀態章），點一下開圖。
   1280 以下兩塊上下排；手機每一塊是一排可以左右滑的小卡。 */
.panel-picks {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 3fr);
}
.picks-group { min-width: 0; padding: 12px 16px 14px; }
.picks-group-custom { border-left: 1px solid var(--line); }
.picks-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin-bottom: 10px; }
.picks-head h2 { margin: 0; font-size: 15px; font-weight: 700; }
.picks-head .hint { margin: 0; }
.picks-count { margin-left: 2px; font-weight: 400; color: var(--text-mute); font-variant-numeric: tabular-nums; }
.picks-row { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; }
.picks-group-custom .picks-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.pick-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  min-width: 0;
  padding: 9px 11px 10px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 10px;
  cursor: pointer;
  transition: border-color .14s ease;
}
.pick-tile:hover { border-color: var(--text-mute); }
.pick-tile-head { display: flex; align-items: baseline; gap: 6px; width: 100%; min-width: 0; }
.pick-open {
  min-width: 0;
  padding: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: inherit;
  font-size: 14.5px;
  font-weight: 700;
  text-align: left;
  color: var(--text);
  background: none;
  border: 0;
  cursor: pointer;
}
.pick-open:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.pick-code { flex-shrink: 0; font-size: 11px; color: var(--text-mute); }
.pick-remove {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin: -8px -8px -8px auto;
  padding: 0;
  color: var(--text-mute);
  background: none;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}
.pick-remove .icon { width: 14px; height: 14px; }
.pick-remove:hover { color: var(--text); background: var(--bg-hover); }
.pick-remove:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.pick-price { font-family: var(--mono); font-size: 18px; font-weight: 800; line-height: 1.15; }
.pick-price.tone-up   { color: var(--up-text); }
.pick-price.tone-down { color: var(--down-text); }
.pick-price.tone-idle { color: var(--text); }
.pick-price.tone-none { color: var(--text-mute); font-weight: 400; }
/* 撐、壓各自不拆，但兩個放不下一行就排成兩行（2026-10-11 檢查：四位數帶小數的股價，像「撐 4361.47　壓 5217.57」，
   在手機 148px 的小卡、平板和筆電五張並排的小卡上都凸出卡片右邊） */
.pick-levels { display: flex; flex-wrap: wrap; gap: 0 10px; font-size: 12px; color: var(--text-dim); font-variant-numeric: tabular-nums; }
.pick-levels > span { white-space: nowrap; }
.pick-levels b { color: var(--text); font-weight: 700; font-family: var(--mono); }
.pick-tile-missing { cursor: default; }

.pick-add {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 96px;
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--accent-text);
  background: transparent;
  border: 1px dashed var(--line);
  border-radius: 10px;
  cursor: pointer;
  transition: border-color .14s ease, background-color .14s ease;
}
.pick-add:hover { border-color: var(--accent); background: var(--bg-hover); }
.pick-add:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* 名額滿了那一行裡的「想追蹤更多股票？」：文字按鈕，打開會員說明 */
.picks-head .link-btn {
  padding: 0;
  margin-left: 4px;
  font: inherit;
  color: var(--accent-text);
  background: none;
  border: 0;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* 訪客：我的自選那一塊放一句說明＋登入鈕，不是空的格子 */
.custom-cta {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 10px;
  min-height: 96px;
  padding: 10px 12px;
  border: 1px dashed var(--line);
  border-radius: 10px;
}
.custom-cta p { margin: 0; font-size: 13px; line-height: 1.6; color: var(--text-dim); }

/* 新增自選的搜尋視窗 */
.custom-modal-status { margin: 0 0 10px; }
/* 跟確認框的輸入欄（.confirm-input）同一個樣子；瀏覽器預設的白底輸入框在暗版上很刺眼 */
.custom-search {
  display: block;
  width: 100%;
  padding: 9px 11px;
  font-size: 15px;
  font-family: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.custom-search:focus { outline: 1px solid var(--accent); }
.custom-results { list-style: none; margin: 10px 0 0; padding: 0; max-height: min(52vh, 420px); overflow-y: auto; }
.custom-result {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "name action" "industry action";
  align-items: center;
  column-gap: 12px;
  padding: 8px 2px;
  border-bottom: 1px solid var(--line);
}
.custom-result:last-child { border-bottom: 0; }
.custom-result-name { grid-area: name; font-size: 14px; font-weight: 700; }
.custom-result-name small { margin-left: 6px; font-size: 11px; font-weight: 400; color: var(--text-mute); }
.custom-result-industry { grid-area: industry; font-size: 11.5px; color: var(--text-mute); }
.custom-result .ghost-btn, .custom-result-tag { grid-area: action; }
.custom-result .ghost-btn { min-height: 36px; }
.custom-result-tag { font-size: 12px; color: var(--text-mute); }
.custom-result-note { padding: 10px 2px; font-size: 13px; color: var(--text-dim); line-height: 1.6; }

@media (max-width: 1280px) {
  .panel-picks { grid-template-columns: minmax(0, 1fr); }
  .picks-group-custom { border-left: 0; border-top: 1px solid var(--line); }
}
@media (max-width: 640px) {
  .picks-group { padding: 10px 12px 12px; }
  .picks-row,
  .picks-group-custom .picks-row {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    margin: 0 -12px;
    padding: 0 12px 2px;
  }
  .picks-row::-webkit-scrollbar { display: none; }
  .pick-tile, .pick-add { flex: 0 0 148px; scroll-snap-align: start; }
  .picks-group:not(.picks-group-custom) .picks-head .hint { display: none; } /* 手機上省掉精選的說明，頂端不要先吃掉一整屏 */
  .custom-cta { flex: 1 0 100%; }
  /* 訪客：頂端黏住的狀態列已經有同一顆「Google 登入，建立我的自選」，第一屏不要出現兩顆一樣的按鈕，
     這裡只留一句說明（2026-10-24 /impeccable critique） */
  body.is-guest .custom-cta { min-height: 0; }
  body.is-guest .custom-cta .primary-btn { display: none; }
}

.alert-locked .alert-price { opacity: .5; }

/* 頂部的免費版狀態列（三頁共用，見 levels-chart.js 的 renderFreeBar）。sticky 在最上面，
   讓「我在用免費版」、今天還能解鎖幾檔、升級入口隨時都在視線內。
   底色用面板色疊一層強調色（亮、暗版都成立）；2026-10-06 之前是寫死的深藍漸層，
   亮版的字是近黑，整條幾乎看不見。 */
.free-bar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
  align-items: center;
  justify-content: space-between;
  padding: 13px 20px;
  font-size: 15px;
  color: var(--text);
  background-color: var(--bg-panel);
  background-image: linear-gradient(90deg, rgba(var(--accent-rgb), .16), rgba(var(--accent-rgb), .04));
  border-bottom: 1px solid var(--accent);
}
.free-bar-text { margin: 0; }
.free-bar-text b { color: var(--accent-text); font-variant-numeric: tabular-nums; }
.free-bar-tag { margin-right: 6px; }
/* 短句只在手機用（長句手機藏起來）；桌機長句已經寫了同一件事，兩句一起出現會講兩次（2026-10-06） */
.free-bar-left { display: none; white-space: nowrap; }
/* 自選名額滿了：數字不再用強調色，免得看起來像還有 */
.free-bar.is-spent b[data-free-custom], .free-bar.is-spent b[data-free-custom-short] { color: var(--text-dim); }
.free-bar-actions { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.free-bar-link, .free-bar-alt { color: var(--accent-text); text-decoration: none; font-size: 12.5px; }
.free-bar-link:hover, .free-bar-alt:hover { text-decoration: underline; }
.free-bar-alt { color: var(--text-dim); }
/* 「用 Discord 登入」後面的「怎麼綁？」：連到 /discord 的綁定教學（2026-10-16），跟登入連結黏在一起，手機上一起靠右 */
.free-bar-member { display: inline-flex; align-items: baseline; gap: 8px; }
.free-bar-help { color: var(--accent-text); font-size: 12.5px; text-decoration: none; white-space: nowrap; }
.free-bar-help:hover { text-decoration: underline; }
.free-bar-cta {
  padding: 8px 18px;
  font-family: inherit;
  font-size: 14.5px;
  font-weight: 700;
  color: var(--accent-ink);
  background: var(--accent);
  border: 1px solid var(--accent);
  border-radius: 8px;
  cursor: pointer;
  transition: filter .16s ease, transform .1s ease;
}
a.free-bar-cta { display: inline-flex; align-items: center; text-decoration: none; } /* 訪客版的「用 Google 免費登入」是連結 */
.free-bar-cta:hover  { filter: brightness(1.1); }
.free-bar-cta:active { transform: scale(.97); }

/* 免費版時，只有最上面那條「免費體驗中」列需要黏住——這是唯一放升級入口
   的地方，其他都不用跟著追蹤滾動，不然兩條 sticky 疊在一起既擠又多餘 */
body.is-free .topbar { position: static; }

.locked-feature { position: relative; }

/* 手機：長句拿掉，只留「免費體驗中・今天還能解鎖 N 檔」＋升級鈕一列、兩個文字連結一列。
   原本整段說明折成四五行，黏頂的狀態列有 137px 高，加上底部導覽，第一張股票卡只露出 35px。 */
@media (max-width: 720px) {
  .free-bar {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "text cta" "links links";
    gap: 6px 12px;
    padding: 8px 12px;
    font-size: 13px;
  }
  .free-bar-text { grid-area: text; }
  .free-bar-long { display: none; }
  .free-bar-left { display: inline-block; } /* 整句一起換行，不會斷成「股／票」 */
  .free-bar-actions { display: contents; }
  .free-bar-cta { grid-area: cta; padding: 8px 14px; font-size: 13px; }
  .free-bar-link, .free-bar-alt { font-size: 12px; }
  .free-bar-link { grid-area: links; justify-self: start; }
  .free-bar-member { grid-area: links; justify-self: end; gap: 6px; }
  .free-bar-help { font-size: 12px; }
}
/* 「看看完整版有什麼」(96px) 和「已經是頻道會員？用 Discord 登入 怎麼綁？」(233px) 同一格、一個靠左一個靠右，
   加上左右留白要 365px：360 的 Android、320 的小手機上兩段字直接疊在一起（2026-10-23 檢查）。
   放不下就讓 Discord 那段自己一行、靠左。 */
@media (max-width: 379px) {
  .free-bar { grid-template-areas: "text cta" "links links" "member member"; }
  .free-bar-member { grid-area: member; justify-self: start; }
}
/* 往下捲之後縮成一行 44px（levels-chart.js 的 compactFreeBarOnScroll）：只留身分標籤＋按鈕，兩行文字連結捲回最上面才出現。
   訪客的「想看自己的股票？」跟按鈕講同一件事，縮起來時拿掉；免費版的「我的自選 1 / 3」留著（2026-10-24）。 */
@media (max-width: 720px) {
  .free-bar.is-compact { grid-template-areas: "text cta"; padding: 2px 12px; }
  .free-bar.is-compact .free-bar-link, .free-bar.is-compact .free-bar-member { display: none; }
  .free-bar.is-compact .free-bar-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  body.is-guest .free-bar.is-compact .free-bar-left { display: none; }
  .free-bar.is-compact .free-bar-cta { min-height: 40px; }
}
/* 平板（直放 99px、兩行）也縮（2026-10-24 站長）：這個寬度的狀態列是 flex 不是 grid，長句換成手機那句短的 */
@media (min-width: 721px) and (max-width: 1024px) {
  .free-bar.is-compact { flex-wrap: nowrap; padding-block: 4px; }
  .free-bar.is-compact .free-bar-long, .free-bar.is-compact .free-bar-link, .free-bar.is-compact .free-bar-member { display: none; }
  body:not(.is-guest) .free-bar.is-compact .free-bar-left { display: inline-block; }
  .free-bar.is-compact .free-bar-cta { min-height: 40px; }
}

/* ---------------- 新聞快遞 ---------------- */
/* 新聞快遞跟財經行事曆並排一列，各佔一半——news-groups 內部自己的欄寬
   （240–300px）還是照舊，新聞欄本身變窄之後，通常會從兩欄縮成一欄 */
.panel-row-news {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px;
}
@media (max-width: 900px) {
  .panel-row-news { grid-template-columns: 1fr; }
}

.news-groups {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 300px));
  justify-content: start; /* 現在通常只有一個分類，不讓它撐滿整排空著一大片 */
  gap: 16px 24px;
  padding: 12px 16px;
}
.news-group-title {
  margin: 0 0 5px;
  padding-bottom: 5px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--accent-text);
  border-bottom: 1px solid var(--line);
}
.news-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.news-item { display: flex; flex-direction: column; gap: 1px; }
.news-item a {
  color: var(--text);
  font-size: 12.5px;
  line-height: 1.5; /* 標題常常折成兩行，1.35 兩行黏在一起（2026-10-10） */
  text-decoration: none;
}
.news-item a:hover { color: var(--accent-text); text-decoration: underline; }
.news-item .news-meta { font-size: 11px; color: var(--text-mute); }
/* 標題裡命中監控清單股票名稱的那幾個字——用站內唯一的強調色標出來，不是
   另外挑一個新色相；紅／綠留給真正的漲跌資料用，這裡只是「這是股票名稱」
   的標示，跟這則新聞是利多利空無關，不能用 --up/--down（見 DESIGN.md）。 */
/* 加粗字重而不是另外處理 hover 狀態：滑鼠移過去時整行標題本來就會變成
   --accent（見上面 .news-item a:hover），股票名稱這時候還是靠字重（粗體）
   跟其餘標題文字區分，不需要為了 hover 另外切一個顏色。 */
.news-stock-name { color: var(--text); font-weight: 700; }

/* 新聞分頁鍵。每個分類同時最多也就幾頁（8 則一頁），數量不會失控，
   所以直接列出全部頁碼，不做上一頁/下一頁或省略號那套。 */
.news-pager { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 10px; }
.news-pager-btn {
  min-width: 22px;
  padding: 2px 6px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  cursor: pointer;
  transition: background-color .12s ease, color .12s ease, border-color .12s ease;
}
.news-pager-btn:hover { background: var(--bg-hover); color: var(--text); }
/* 觸控裝置：頁碼原本是十二顆 22×19 的小方塊擠在一起，手指很容易點到隔壁 */
@media (pointer: coarse) {
  .news-pager { gap: 8px; }
  .news-pager-btn { min-width: 36px; min-height: 36px; font-size: 12px; }
}
.news-pager-btn.active {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
  font-weight: 700;
}

/* ---------------- 財經行事曆 ---------------- */
.calendar-cols { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 16px; padding: 14px 16px; }
.calendar-col-title { margin: 0 0 8px; font-size: 12.5px; font-weight: 700; color: var(--text-dim); }
.calendar-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.calendar-item {
  display: grid;
  grid-template-columns: 52px 1fr;
  gap: 8px;
  align-items: baseline;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line);
}
.calendar-item:last-child { border-bottom: none; padding-bottom: 0; }
.calendar-date {
  font-family: var(--mono);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.calendar-label { font-size: 12.5px; line-height: 1.4; color: var(--text); }

@media (max-width: 900px) {
  .calendar-cols { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 640px) {
  .calendar-cols { grid-template-columns: 1fr; }
}

/* ---------------- 按鈕 ---------------- */
.ghost-btn, .primary-btn, .danger-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 13px;
  font-size: 12.5px;
  font-family: inherit;
  border-radius: 8px;
  cursor: pointer;
  border: 1px solid var(--line);
  background: var(--bg-raise);
  color: var(--text);
  text-decoration: none; /* 這三顆按鈕樣式偶爾套在 <a>（例如「復盤」）身上，不設的話
    <a> 會帶著瀏覽器預設底線，跟套在 <button>（例如「管理」）上的沒有底線長得不一樣 */
  transition: background-color .16s ease, border-color .16s ease, filter .16s ease, transform .1s ease;
}
.ghost-btn:hover { background: var(--bg-hover); }
.ghost-btn:active, .primary-btn:active, .danger-btn:active { transform: scale(.96); }
.ghost-btn:disabled, .primary-btn:disabled, .danger-btn:disabled {
  opacity: .4;
  cursor: not-allowed;
  pointer-events: none;
}
.primary-btn { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.primary-btn:hover { filter: brightness(1.12); }
.danger-btn { color: var(--up-text); border-color: var(--up); background: transparent; }
.danger-btn:hover { background: var(--up-soft); }

/* ---------------- 管理面板 ---------------- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, .68);
}
.modal {
  width: min(860px, 100%);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.modal.modal-wide { width: min(1100px, 96vw); }
.modal.modal-narrow { width: min(380px, 100%); }

/* 確認框可能是從管理面板（已經是一個 .modal-backdrop）裡觸發的，z-index 要
   蓋過去它才不會被壓在下面點不到 */
.confirm-backdrop { z-index: 60; }
.confirm-message { white-space: pre-line; line-height: 1.6; color: var(--text-dim); margin: 0; }

/* 確認框當成輸入框用的時候（例如產業改名）多出來的這兩塊。輸入框做滿版＋比一般
   欄位大一點，因為這時候它是整個彈窗唯一要操作的東西，不是表單裡的其中一格。 */
.confirm-input {
  display: block;
  width: 100%;
  margin-top: 14px;
  padding: 9px 11px;
  font-size: 15px;
  font-family: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.confirm-input:focus { outline: 1px solid var(--accent); }
.confirm-error { margin: 8px 0 0; font-size: 12.5px; line-height: 1.5; }
/* 額度用完那一刻，這幾個連結是使用者接下來唯一該做的事——之前用純文字藍字連結
   呈現，太容易被忽略、看起來像順帶一提的備註。改成一排有實際按鈕感的列：
   有背景色塊、有邊框、hover 會位移＋變色，一眼就看得出「這裡可以點」。
   primary（通常是「加入會員」）用實心強調色，其餘用外框樣式做次要層級——
   兩個都做成滿版按鈕會分不出主次，兩個都做成文字連結又會被忽略，這是中間解。 */
.confirm-links { display: flex; flex-direction: column; gap: 8px; margin: 14px 0 2px; }
.confirm-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 14px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 8px;
  text-decoration: none;
  transition: background-color .16s ease, border-color .16s ease, transform .1s ease;
}
.confirm-link::after {
  content: "→";
  color: var(--accent-text);
  font-weight: 700;
  transition: transform .16s ease;
}
.confirm-link:hover { background: var(--bg-hover); border-color: var(--accent); }
.confirm-link:hover::after { transform: translateX(3px); }
.confirm-link:active { transform: scale(.98); }

.confirm-link-primary {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}
.confirm-link-primary::after { color: var(--accent-ink); }
.confirm-link-primary:hover { filter: brightness(1.08); border-color: var(--accent); background: var(--accent); }
/* 次要去處（會員方案、Discord 登入、怎麼綁定）排成最後一行小字，按鈕只留主要的那一兩顆（2026-10-24）。
   上下 padding 撐出手指點得到的高度，字本身維持小字層級 */
.confirm-minor { display: flex; flex-wrap: wrap; gap: 0 18px; margin: 0; font-size: 13px; }
.confirm-minor-link { padding: 10px 0; color: var(--accent-text); text-decoration: none; }
.confirm-minor-link:hover { text-decoration: underline; }

.modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 13px 16px;
  background: var(--bg-raise);
  border-bottom: 1px solid var(--line);
}
.modal-head h2 { font-size: 15px; font-weight: 700; letter-spacing: 0.02em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.modal-body { padding: 16px; overflow-y: auto; }
/* 圖上面那兩行：這檔自己的趨勢、所屬族群強不強（levels-chart.js 的 renderChartStrip）。
   桌機、平板：兩行都攤開，一行一件事，最前面一個小標（這檔自己／所屬族群）對齊；一行排不下自己折。
   手機（直放、橫放）：收成一行摘要（趨勢、族群、族群現在哪一格、近 4 週），點了才攤開，
   攤開的那一塊蓋在圖上面——不把圖擠小（2026-10-10 站長：手機橫放時這兩行佔掉半個畫面）。
   小圖示（趨勢的折線、資金地圖的小方格）用文字色，不用紅綠——方向和位置都不是今天的漲跌。 */
.chart-group-strip {
  position: relative;
  z-index: 7;                 /* 攤開的那一塊要蓋過圖上的工具列（6）；標題列的選單（8）還在它上面 */
  font-size: 13px;
  color: var(--text-dim);
  border-bottom: 1px solid var(--line);
}
.cgs-summary { display: none; }
.cgs-panel { display: grid; gap: 7px; padding: 10px 16px; }
.cgs-row { display: flex; flex-wrap: wrap; align-items: center; gap: 5px 14px; min-width: 0; }
.cgs-label { flex: none; width: 4.6em; font-size: 12px; color: var(--text-mute); }
.cgs-ico { flex: none; width: 20px; height: 20px; color: var(--text); }
.cgs-quad { display: grid; grid-template-columns: repeat(2, 9px); gap: 2px; flex: none; }
.cgs-quad i { width: 9px; height: 9px; border-radius: 2px; background: var(--line); }
.cgs-quad i.on { background: var(--text); }
.cgs-name b { font-size: 14.5px; color: var(--text); }
.cgs-name small { margin-left: 6px; font-size: 12px; color: var(--text-mute); }
/* 站長：族群名字是一顆按鈕，點了換題材（levels-chart.js 的 openThemePicker，2026-10-11）。
   平常看起來跟名字一樣，只多一支鉛筆；滑過去才出框，免得一整排像按鈕 */
.cgs-theme-edit {
  display: inline-flex;
  align-items: center;
  gap: 0;
  min-height: 30px;
  margin: -4px -6px;
  padding: 3px 6px;
  border: 1px solid transparent;
  border-radius: 7px;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.cgs-theme-edit:hover { border-color: var(--line); background: var(--bg-hover); }
.cgs-edit-ico { width: 14px; height: 14px; margin-left: 6px; color: var(--text-mute); }
.cgs-theme-edit:hover .cgs-edit-ico { color: var(--accent-text); }
.cgs-note { font-size: 12px; color: var(--accent-text); white-space: normal; }

.theme-picker {
  position: fixed;
  z-index: 60; /* 圖的彈窗是 50 */
  display: flex;
  flex-direction: column;
  max-height: min(420px, 70vh);
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: var(--shadow-lg);
  font-size: 13px;
}
.theme-picker.busy { opacity: .7; pointer-events: none; }
.tp-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 10px 6px 12px; font-weight: 600; color: var(--text); }
.tp-close { display: inline-flex; padding: 4px; border: none; border-radius: 6px; background: none; color: var(--text-dim); cursor: pointer; }
.tp-close:hover { background: var(--bg-hover); color: var(--text); }
.tp-close .icon { width: 16px; height: 16px; }
.tp-input { margin: 0 10px 6px; }
.tp-list { flex: 1 1 auto; min-height: 60px; overflow-y: auto; padding: 0 6px; }
.tp-item {
  display: flex;
  width: 100%;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  min-height: 34px;
  padding: 6px 8px;
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.tp-item:hover, .tp-item:focus-visible { background: var(--bg-hover); }
.tp-item small { flex: none; font-size: 12px; color: var(--text-mute); }
.tp-item small .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.tp-item.is-current { color: var(--accent-text); font-weight: 600; }
.tp-new b { color: var(--accent-text); }
.tp-group { margin: 8px 8px 2px; font-size: 11.5px; color: var(--text-mute); }
.tp-empty { margin: 8px; font-size: 12.5px; color: var(--text-mute); }
.tp-bad { color: var(--text); }
.tp-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 12px; border-top: 1px solid var(--line); font-size: 12.5px; color: var(--text-dim); }
.tp-foot b { color: var(--text); }
.tp-clear { padding: 4px 10px; border: 1px solid var(--line); border-radius: 7px; background: none; color: var(--text-dim); font: inherit; font-size: 12.5px; cursor: pointer; }
.tp-clear:hover { background: var(--bg-hover); color: var(--text); }
.tp-msg { margin: 0; padding: 0 12px 8px; font-size: 12px; color: var(--text-dim); }
.tp-msg:empty { display: none; }
@media (pointer: coarse) {
  .tp-item { min-height: 44px; }
  .cgs-theme-edit { min-height: 44px; }
}
.cgs-state b { margin-right: 7px; padding: 1px 8px; font-size: 12.5px; color: var(--text); border: 1px solid var(--text-mute); border-radius: 999px; white-space: nowrap; }
.cgs-item { white-space: nowrap; }
.cgs-item .mono, .cgs-brief .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 700; color: var(--text); }
.cgs-item .mono.up, .cgs-brief .mono.up { color: var(--up-text); }
.cgs-item .mono.down, .cgs-brief .mono.down { color: var(--down-text); }
.cgs-stages { white-space: normal; }
.cgs-stage {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 8px;
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--text);
  text-decoration: none;
  border: 1px solid var(--text-mute);
  border-radius: 999px;
}
a.cgs-stage:hover { border-color: var(--accent); color: var(--accent-text); }
.cgs-more {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
  padding: 4px 0;
  font-weight: 600;
  white-space: nowrap;
  color: var(--accent-text);
  text-decoration: none;
}
.cgs-more:hover { text-decoration: underline; text-underline-offset: 3px; }
.cgs-more .icon { width: 14px; height: 14px; }
@media (pointer: coarse) {
  .cgs-more { padding: 13px 0; }
  .cgs-stage { padding: 6px 10px; }
}
@media (max-width: 640px), (max-height: 520px) {
  .cgs-summary {
    display: flex;
    align-items: center;
    gap: 6px 14px;
    width: 100%;
    min-height: 44px;
    padding: 6px 10px 6px 14px;
    font: inherit;
    font-size: 13px;
    text-align: left;
    color: var(--text-dim);
    background: none;
    border: 0;
    cursor: pointer;
  }
  .cgs-brief { display: inline-flex; align-items: center; gap: 6px; min-width: 0; white-space: nowrap; }
  .cgs-brief b { font-weight: 700; color: var(--text); }
  .cgs-brief-group { flex: 0 1 auto; }
  .cgs-brief-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
  .cgs-brief-stage { padding: 1px 8px; font-size: 12px; font-weight: 600; color: var(--text); border: 1px solid var(--text-mute); border-radius: 999px; }
  .cgs-caret { display: inline-flex; align-items: center; gap: 2px; flex: none; margin-left: auto; font-size: 12px; color: var(--text-mute); }
  .cgs-caret .icon { width: 16px; height: 16px; transition: transform .16s ease; }
  .chart-group-strip.open .cgs-caret .icon { transform: rotate(180deg); }
  .cgs-panel {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    gap: 12px;
    max-height: calc(100dvh - 120px);
    padding: 12px 14px 14px;
    overflow-y: auto;
    overscroll-behavior: contain;
    font-size: 12.5px;
    background: var(--bg-panel);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow-lg);
  }
  .chart-group-strip.open .cgs-panel { display: grid; }
  .cgs-row { gap: 4px 10px; }
  /* 攤開之後：小標跟圖示（族群名）一行，標籤和那句白話自己一行，數字和連結再一行 */
  .cgs-label { width: auto; }
  .cgs-state { flex-basis: 100%; }
}
/* 很窄的手機：摘要一行放不下三樣，名單那顆先收（攤開看得到） */
@media (max-width: 400px) {
  .cgs-brief-stage { display: none; }
}

/* 圖表彈窗上的手指（levels-chart.js 的 bindChartModalTouch）：彈窗開著的時候，滑動和兩指縮放不交給瀏覽器——
   圖自己處理拖和縮放，其他地方沒有東西要捲。不寫的話，在標題列上一拖後面的監控清單就跟著捲，
   兩指在圖上張開瀏覽器會去放大整頁。裡面自己會捲的小區塊放行。 */
#chart-modal { touch-action: none; overscroll-behavior: contain; }
#chart-modal .cgs-panel, #chart-modal .ask-ai-menu { touch-action: pan-y; }

/* 觸控裝置：圖上的工具列按鈕從 30px 放大到 36px（手指點得到） */
/* （這幾條前面帶 #chart-modal：工具列的基本樣式寫在這個檔案更後面，不加重的話會被它蓋回去） */
@media (pointer: coarse) {
  #chart-modal .chart-tool-btn { width: 36px; height: 36px; }
  #chart-modal .chart-tool-btn .icon { width: 18px; height: 18px; }
}
/* 橫放的手機（高度很矮）：
   - 唯讀提示／畫線說明那一行不顯示（那一行在 430px 高的畫面上要佔 40px）
   - 工具列排成兩欄（站長有十三顆，一欄要四百多 px；更矮的手機排三欄） */
@media (max-height: 520px) {
  #chart-modal .chart-source-bar { display: none; }
  #chart-modal .modal-head { padding-top: 4px; padding-bottom: 4px; }
  #chart-modal .chart-toolbar { top: 6px; left: 6px; padding: 4px; }
}
/* 工具列排兩欄：橫放的手機，和高度不到 900px 的觸控裝置（平板橫放大約 800px 高，站長十三顆 36px 的按鈕
   排一欄是 525px，圖剛好差幾 px 放不下） */
@media (max-height: 520px), (pointer: coarse) and (max-height: 900px) {
  #chart-modal .chart-toolbar { display: grid; grid-template-columns: repeat(2, auto); gap: 1px 2px; }
  #chart-modal .chart-toolbar .chart-tool-divider { grid-column: 1 / -1; }
}
@media (max-height: 400px) {
  #chart-modal .chart-toolbar { grid-template-columns: repeat(3, auto); }
  #chart-modal .chart-tool-btn { width: 34px; height: 34px; }
}
/* 更矮（在 LINE 之類 App 內建的瀏覽器裡橫放，App 自己上下各一條工具列，網頁只剩兩百多 px 高）：四欄 */
@media (max-height: 320px) {
  #chart-modal .chart-toolbar { grid-template-columns: repeat(4, auto); }
}
/* 手機橫放：工具列改成貼在最左邊的一直條，按鈕多的時候上下滑（2026-10-15 站長拿 TradingView 手機版當例子）。
   上面那幾條（兩欄、三欄、四欄）是工具列浮在圖上的時候用的：浮著的一塊會蓋掉左上角的K棒，排成好幾欄又
   擠成一團。現在整張圖往右讓出 48px，工具列住在那一條裡，不蓋圖；一欄排不下（站長有十幾顆）就在那一條
   裡上下滑——那一條自己會捲，彈窗其他地方照舊不捲（levels-chart.js 的 bindChartModalTouch 放行它）。
   圖、系統性風險日那一排、滑鼠提示都量在 .levels-chart-wrap 裡，所以讓位置的是整個 wrap，不是只有畫布，
   疊在圖上的東西才不會對不準；工具列掛在 wrap 左邊外面（left: -48px）。 */
@media (max-height: 520px) {
  #chart-modal .levels-chart-wrap { margin-left: 48px; width: calc(100% - 48px); }
  #chart-modal .chart-toolbar {
    top: 0;
    bottom: 0;
    left: -48px;
    width: 48px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 6px 0 calc(6px + env(safe-area-inset-bottom));
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    touch-action: pan-y;
    scrollbar-width: none;
    border: 0;
    border-right: 1px solid var(--line);
    border-radius: 0;
    box-shadow: none;
  }
  #chart-modal .chart-toolbar::-webkit-scrollbar { display: none; }
  #chart-modal .chart-tool-btn { flex: none; width: 38px; height: 38px; }
  #chart-modal .chart-toolbar .chart-tool-divider { flex: none; width: 28px; margin: 3px 0; }
  /* 「創高中」那類標籤原本排在浮動工具列右邊；工具列搬走了，回到圖的左上角 */
  #chart-modal .levels-chart-badges { left: 10px; }
}
/* 手機直放（2026-10-21 站長：工具欄縮小，不要遮到後面的「創新高中」那顆標籤）。上面「觸控、高度不到 900px 排兩欄」那條
   是給橫放和平板的；手機直放寬度只有 400 多 px，兩欄的工具列約 100px 寬，把接在它右邊的標籤（left: 58px）蓋掉一截。
   改成一欄、按鈕 36 → 28px、圖示 15px：整條寬約 40px，標籤的位置不用動。按鈕比手指小，但每顆之間有空隙，
   也是站長自己要的（他拿手機看得到哪個大小）。 */
@media (max-width: 640px) and (min-height: 521px) {
  #chart-modal .chart-toolbar { display: flex; flex-direction: column; gap: 1px; padding: 3px; top: 8px; left: 8px; }
  #chart-modal .chart-tool-btn { width: 28px; height: 28px; border-radius: 6px; }
  #chart-modal .chart-tool-btn .icon { width: 15px; height: 15px; }
  #chart-modal .chart-tool-btn.chart-tool-ma { font-size: 11px; }
  #chart-modal .chart-tool-btn.chart-tool-range { font-size: 10.5px; }
  #chart-modal .chart-toolbar .chart-tool-divider { margin: 2px 3px; }
  #chart-modal .levels-chart-badges { top: 8px; left: 48px; }
}
.chart-source-bar { display: flex; align-items: center; gap: 10px; padding: 10px 16px 0; }
.chart-modal-body { padding: 0; height: 72vh; background: var(--chart-bg); }
/* 2026-10-15 站長：「把整體支撐壓力圖（這個彈出來的視窗）放大放寬一點」。原本最寬 1100px、圖固定 72vh，1920 的螢幕
   左右各空 400px、上下也還有空。桌機、筆電、平板：彈窗最寬 1600px，高度撐到畫面上下只留 16px，圖吃掉標題列
   和那幾行以外剩下的全部高度（跟手機整個螢幕那一段同一個做法：flex 撐開，圖表庫 autoSize 跟著）。
   手機（640px 以下、或高度不到 520px 的橫放）本來就是整個螢幕，那一段在後面，不動。 */
@media (min-width: 641px) and (min-height: 521px) {
  #chart-modal { padding: 16px; }
  /* 2026-10-19 站長：「支撐壓力圖再稍微寬一點」——最寬 1600 → 1800（1920 的螢幕左右各剩約 50px） */
  #chart-modal .modal.modal-wide { width: min(1800px, 100%); height: calc(100dvh - 32px); max-height: none; }
  #chart-modal .chart-modal-body { flex: 1 1 auto; height: auto; min-height: 0; }
}

/* 支撐壓力圖懸浮工具列——指標／水平線／水平射線／成交量／清除全部，浮在
   圖表左上角，取代原本「雙擊空白處新增」的手勢。工具按鈕（畫線那三顆＋
   清除）只有登入管理密碼才會出現在畫面上，見 levels-chart.js 的
   renderLevelsChart()；成交量開關不改資料，一直都在。2026-09 從右上角
   移到左上角——圖表庫的價格軸固定畫在最右側，工具列在右邊常常擋住價位
   標籤；左側是空的，且原本站在左上角的 .levels-chart-badges（創高中／
   跌破所有防線）挪到工具列右邊接著排，兩者不重疊。 */
/* 從支撐壓力圖的「管理」跳過來的那一列：亮一下框，讓人知道是哪一列（app.js 的 focusEditRow） */
.edit-row.edit-row-focus { outline: 2px solid var(--accent); outline-offset: -2px; transition: outline-color 0.6s; }

.chart-toolbar {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 6;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 5px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: var(--shadow-sm);
}
.chart-tool-divider { height: 1px; margin: 2px 3px; background: var(--line); }
.chart-tool-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  color: var(--text-dim);
  background: none;
  border: 1px solid transparent;
  border-radius: 7px;
  cursor: pointer;
  transition: background-color .16s ease, border-color .16s ease, color .16s ease, transform .1s ease;
}
.chart-tool-btn .icon { width: 16px; height: 16px; }
.chart-tool-btn:hover { color: var(--text); background: var(--bg-hover); }
.chart-tool-btn:active { transform: scale(.94); }
.chart-tool-btn.active { color: var(--accent-text); background: rgba(var(--accent-rgb),.11); border-color: rgba(var(--accent-rgb),.35); }
.chart-tool-btn.chart-tool-danger:hover { color: var(--up-text); border-color: var(--up); background: var(--up-soft); }
/* 均線開關（5／20／60）——跟其他工具列按鈕共用同一個外框與 active 樣式
   （開啟時金色背景），只是內容是數字不是圖示，另外指定字體：這是使用者
   要辨識的數字（週期），照 Mono-For-Measurement Rule 套等寬字。 */
.chart-tool-btn.chart-tool-ma { font: 700 12px var(--mono); }
/* 「全部／近期」切換：寫字不畫圖示（這個動作沒有通用的圖示），兩個字剛好塞進 30px 寬 */
.chart-tool-btn.chart-tool-range { font-family: inherit; font-size: 11.5px; font-weight: 700; letter-spacing: 0; }

/* 滑鼠停在K棒上的開高低收／漲跌／量浮動卡——比照測驗網站那邊已經有的同一種
   資訊，這裡是後補的，見 levels-chart.js 的 bindHoverTooltip()。 */
.levels-chart-tooltip {
  position: absolute;
  z-index: 8;
  width: 148px;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--bg-raise);
  box-shadow: var(--shadow-sm);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 11.5px;
  pointer-events: none;
  backdrop-filter: blur(4px);
}
.levels-chart-tooltip-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 1.5px 0; color: var(--text); }
.levels-chart-tooltip-row span:first-child { color: var(--text-dim); font-family: inherit; }
.levels-chart-tooltip-row.up span:last-child { color: var(--up-text); }
.levels-chart-tooltip-row.down span:last-child { color: var(--down-text); }
/* 系統性風險日那幾行：小標題＋跟下面開高低收之間的分隔 */
.levels-chart-tooltip-title { font-size: 11px; font-weight: 700; color: var(--text-mute); padding-bottom: 1px; }
.levels-chart-tooltip-sep { height: 1px; margin: 4px 0; background: var(--line); }
.chart-empty {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 24px;
  color: var(--text-dim);
  font-size: 12.5px;
  line-height: 1.8;
}

/* ---------------- 支撐壓力圖（自架 Lightweight Charts） ---------------- */
.levels-chart-wrap { position: relative; height: 100%; width: 100%; }
.levels-chart-canvas { height: 100%; width: 100%; }
/* 系統性風險日的底部事件列（見 levels-chart.js 的 createCrashLane）：時間軸正上方
   一排單字方框，跟台股看盤軟體標「權」「息」同一種慣例。顏色用跌，跟面板上的
   跌幅長條同一個語意。 */
.crash-lane { position: absolute; inset: 0; pointer-events: none; z-index: 6; }
.crash-lane-mark {
  position: absolute;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1px;
  height: 16px;
  min-width: 16px;
  padding: 0 3px;
  border: 1px solid color-mix(in srgb, var(--down) 55%, transparent);
  border-radius: 3px;
  background: var(--down-soft);
  color: var(--down-text);
  font-family: inherit;
  font-size: 10.5px;
  font-weight: 700;
  line-height: 1;
  cursor: default;
  pointer-events: auto;
}
.crash-lane-mark small { font-size: 10px; font-weight: 600; }
.crash-lane-mark:hover, .crash-lane-mark:focus-visible { background: var(--down); color: var(--chart-bg); }
/* 手機上方框只有 16px 高，點擊範圍往外撐到 32px，外觀不變 */
.crash-lane-mark::before { content: ""; position: absolute; inset: -8px -4px; }
/* 查看某一格時才亮出的直條——平常不畫，避免整張圖被風險日切碎 */
.crash-lane-hl {
  position: absolute;
  top: 0;
  z-index: 5;
  pointer-events: none;
  background: color-mix(in srgb, var(--down) 10%, transparent);
  border-inline: 1px dashed color-mix(in srgb, var(--down) 50%, transparent);
}
.crash-lane-tip { width: auto; min-width: 148px; white-space: nowrap; }
/* 選取水平線／射線時浮在圖上方正中央的「短／大」切換（跟 TradingView 選中圖形後
   出現的小工具列同一種位置與概念）。左上角是徽章、右上角是繪圖工具列，中間留給它。 */
.levels-tier-toggle {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 7;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 8px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: var(--shadow-sm);
  font-size: 13px;
}
.levels-tier-toggle .tier-toggle-target { font-family: var(--mono); font-weight: 700; color: var(--text); margin-right: 4px; white-space: nowrap; }
.levels-tier-toggle button {
  min-width: 36px;
  padding: 3px 10px;
  font: inherit;
  font-weight: 700;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  cursor: pointer;
}
.levels-tier-toggle button:hover { color: var(--text); border-color: var(--accent); }
.levels-tier-toggle button.active { color: var(--accent-ink, #fff); background: var(--accent); border-color: var(--accent); }
/* 「待確認」跟短／大是兩件事（一個是層級、一個是站長對這條線有沒有把握），中間隔一條線；
   選中時用跟圖上那條虛線一樣的中性灰，不用強調色 */
.levels-tier-toggle .tier-toggle-sep { width: 1px; align-self: stretch; margin: 2px 2px; background: var(--line); }
.levels-tier-toggle button[data-pending] { border-style: dashed; white-space: nowrap; }
.levels-tier-toggle button[data-pending].active { color: var(--bg); background: var(--text-dim); border-color: var(--text-dim); border-style: solid; }
.levels-tier-toggle .tier-toggle-hint { font-size: 11.5px; color: var(--text-mute); white-space: nowrap; }
.levels-tier-toggle .tier-toggle-hint b { font-family: var(--mono); color: var(--text); }
/* 手指點的裝置（平板、手機）：切換鈕的按鈕至少 36px 高，「刪除」「大／短」才點得準（2026-10-16 站長用 iPad mini） */
@media (pointer: coarse) {
  .levels-tier-toggle button { min-height: 36px; min-width: 44px; }
}
.timing-chip.timing-chip-pending { margin-top: 4px; border-style: dashed; color: var(--text-dim); }
.levels-chart-badges {
  position: absolute;
  top: 10px;
  left: 58px; /* 工具列固定寬度（30px 按鈕＋5px*2 內距＋1px*2 邊框＝42px）＋6px 間距，接在它右邊，避免疊在一起 */
  z-index: 5;
  display: flex;
  gap: 6px;
  pointer-events: none;
}
.levels-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 700;
  border-radius: 999px;
  box-shadow: var(--shadow-sm);
}
.levels-badge.new-high { background: var(--up-soft); color: var(--up-text); border: 1px solid var(--up); }
.levels-badge.new-low  { background: var(--down-soft); color: var(--down-text); border: 1px solid var(--down); }
/* 處置中（交易所公告）：沿用監控卡片處置徽章的紫色 */
.levels-badge.punish { background: var(--punish-soft); color: var(--punish-text); border: 1px solid var(--punish); }

.row { display: flex; gap: 8px; align-items: center; }
.row.wrap { flex-wrap: wrap; }
.edit-bulk-actions { margin-top: 8px; }
.spacer { flex: 1; }
.modal-actions { margin-top: 14px; flex-wrap: wrap; }

.admin-tabs { display: flex; gap: 6px; margin-bottom: 14px; border-bottom: 1px solid var(--line); }
.tab {
  padding: 7px 14px;
  font-size: 12.5px;
  font-family: inherit;
  color: var(--text-dim);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  transition: color .16s ease, border-color .16s ease;
}
.tab:hover { color: var(--text); }
.tab.active { color: var(--text); border-bottom-color: var(--accent); font-weight: 600; }

.edit-list {
  max-height: 46vh;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 8px;
  margin-top: 10px;
}
.edit-row {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 8px;
  align-items: center;
  padding: 6px 10px;
  border-bottom: 1px solid var(--line);
}
.edit-row:hover { background: var(--bg-hover); }
.edit-row.off { opacity: .45; }
.edit-row input[type="number"] { width: 100%; font-family: var(--mono); font-size: 12.5px; }

.edit-levels-row {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  align-items: center;
  margin-top: 2px;
}
.edit-level-chip {
  display: flex;
  align-items: center;
  gap: 2px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 2px 2px 2px 6px;
}
.edit-level-chip input {
  width: 66px;
  font-family: var(--mono);
  font-size: 12px;
  border: none;
  background: none;
  color: var(--text);
  padding: 2px;
}
.edit-level-chip input:focus { outline: none; }
.edit-level-remove {
  border: none;
  background: none;
  color: var(--text-mute);
  cursor: pointer;
  font-size: 12.5px;
  padding: 2px 6px;
  border-radius: 4px;
}
.edit-level-remove:hover { color: var(--up-text); background: var(--up-soft); }
.edit-level-add {
  border: 1px dashed var(--line);
  background: none;
  color: var(--accent-text);
  cursor: pointer;
  font-size: 11.5px;
  padding: 4px 9px;
  border-radius: 6px;
}
.edit-level-add:hover { background: var(--bg-hover); }

/* 射線的 chip／按鈕跟水平線共用同一套規則（.edit-level-chip／.edit-level-remove），
   只多一個虛線邊框呼應圖表上射線本身的虛線畫法，讓人一眼分得出「這條是射線」 */
.edit-ray-chip { border-style: dashed; }
.edit-ray-remove {
  border: none;
  background: none;
  color: var(--text-mute);
  cursor: pointer;
  font-size: 12.5px;
  padding: 2px 6px;
  border-radius: 4px;
}
.edit-ray-remove:hover { color: var(--up-text); background: var(--up-soft); }
.edit-ray-add {
  border: 1px dashed var(--accent);
  background: none;
  color: var(--accent-text);
  cursor: pointer;
  font-size: 11.5px;
  padding: 4px 9px;
  border-radius: 6px;
}
.edit-ray-add:hover { background: var(--bg-hover); }
.edit-personal-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
  font-family: inherit;
  font-size: 11.5px;
  color: var(--accent-text);
  white-space: nowrap;
  text-decoration: none;
  background: none;
  cursor: pointer;
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
}
.edit-personal-link:hover { background: var(--bg-hover); }
.edit-name-group { display: flex; gap: 6px; }
.edit-industry, .edit-bare-name {
  font-size: 12.5px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 3px 7px;
  color: var(--text);
}
.edit-industry { width: 96px; flex-shrink: 0; color: var(--text-dim); cursor: pointer; }
.edit-bare-name { flex: 1; min-width: 0; }
.edit-sym { font-size: 11px; color: var(--text-mute); font-family: var(--mono); margin-top: 2px; }
.edit-head {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 8px;
  padding: 6px 10px;
  font-size: 11px;
  color: var(--text-mute);
  background: var(--bg-raise);
  position: sticky;
  top: 0;
}

.count-pill {
  padding: 3px 10px;
  font-size: 12px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--text-dim);
}

.add-box { margin-top: 12px; }
.add-box summary { cursor: pointer; font-size: 12.5px; color: var(--accent-text); padding: 6px 0; }

.field { display: block; margin-bottom: 14px; }
.field > span { display: block; font-size: 12.5px; margin-bottom: 4px; font-weight: 600; }
.field input { width: 150px; }
.field small { display: block; margin-top: 3px; font-size: 11.5px; color: var(--text-mute); }
.checkbox { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; font-size: 12.5px; }

.hint { font-size: 12.5px; color: var(--text-mute); margin: 0 0 10px; }
.err { color: var(--up-text); font-size: 12.5px; margin: 8px 0 0; }
.ok  { color: var(--down-text); font-size: 12.5px; margin: 8px 0 0; }

/* 看盤卡片上的題材：窄到 360px 以下只剩一個字母（320px 量到「CCL/玻纖布」只顯示「C」），比沒有還難懂，
   乾脆不放——看題材用上面的題材分頁、或點開圖上「所屬族群」那一行（2026-10-12 adapt） */
@media (max-width: 360px) {
  .stock-card .sym-industry { display: none; }
}

/* ---------------- 手機 ---------------- */
@media (max-width: 900px) {
  .layout { grid-template-columns: 1fr; gap: 14px; padding: 12px; }
  .panel-global { margin-top: 0; }
  .alert-list { max-height: 44vh; }
  .table-wrap { max-height: none; }
  /* 單欄時警示在監控清單上面：清單載回來之前先撐到 44vh，不然一進來把下面整頁推下去 */
  .alert-list:has(> .empty[data-loading]) { min-height: 44vh; }
  .breadth-grid { grid-template-columns: repeat(auto-fit, minmax(56px, 1fr)); }
  .index-charts { grid-template-columns: minmax(0, 1fr); }
  .ic-canvas { aspect-ratio: 5 / 4; } /* 單欄時寬度只有手機那麼寬，比例放高一點 K 棒才看得清楚 */
  .heatmap-grid { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); }
  .fundflow-cols { grid-template-columns: 1fr; }
  .crash-row { grid-template-columns: 78px 40px 1fr auto; gap: 8px; } /* 70px 裝不下等寬的 2026-09-03 */
  .crash-manual-row { grid-template-columns: 70px 40px 1fr auto; gap: 8px; }
  .crash-row .crash-value { font-size: 14px; }
  .topbar { padding: 10px 12px; }
  .brand h1 { font-size: 16px; }
  .brand-sub { display: none; }
  .stat { min-width: 68px; padding: 4px 9px; }
  .edit-row, .edit-head { grid-template-columns: 26px 1fr; }
  .edit-name-group { flex-direction: column; }
  .edit-industry { width: 100%; }
  .band { width: 60px; }
  .modal.modal-wide { width: 100%; }
  .chart-modal-body { height: 60vh; }
}

/* ---------------- 會員登入頁 ---------------- */
/* 沒登入的人只會看到這一頁，所以它要能自己站得住：置中、克制，
   沿用站內既有的面板／按鈕語言，不另外長一套視覺 */
html:has(body.login-body) {
  /* overflow-x 是設在 <html> 上的視窗捲動軸，不是 <body> 的——只設
     .login-body 的 overflow:hidden 沒用，手機版還是會出現水平捲動，因為
     .login-bg::before 的 inset:-10% 裝飾性光暈本來就故意比容器寬，需要
     連 <html> 一起裁掉才會真的看不到、也捲不動。 */
  overflow-x: hidden;
  scrollbar-gutter: auto; /* 整頁不捲，留著捲軸的位置只會在右邊多一條空白 */
}
.login-body {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
  overflow: hidden; /* K 棒／走勢線用 viewBox 鋪滿全螢幕，邊緣裁掉比留白自然 */
  /* 賽博龐克配色只在登入頁這一頁生效（scope 在 .login-body，不寫進 :root）——
     全站其餘地方仍然是 DESIGN.md 的安靜配色，這裡是刻意放大音量的唯一例外
     （Moment tier，同時只有一個實例，見上面既有的說明）。青×洋紅是這個類型
     最容易辨認、最不落俗套的組合，霓虹城市天際線／武士刀那套視覺不用，
     整個場景仍然圍繞股票 K 棒本身在做文章，只是把「終端機」的質感做出來。
     漲跌本身的紅／綠語意色不變——真正的交易終端機（Bloomberg 那類）就是
     深色鉻面＋紅綠報價，比自創一套配色更真實，也不會跟全站的漲跌判讀衝突。 */
  --cyber-cyan: #2ee6ff;
  --cyber-cyan-dim: rgba(46, 230, 255, .5);
  --cyber-magenta: #ff2ec4;
}

/* 登入頁背景的股票走勢動畫——K 棒＋走勢線由 login-animation.js 動態產生並用
   anime.js 畫出來（見該檔案開頭的說明）。這裡只負責鋪版：蓋滿整個畫面、
   壓在卡片後面、滑鼠事件穿透（純裝飾，不能擋到卡片或背景點擊）。
   這顆是全站唯一的登入頁，屬於 DESIGN.md 定義的 Moment tier（同時只會有
   一個實例），才允許用這種份量的裝飾動畫——換成警示卡、股票列表那種會同時
   渲染幾十上百個實例的地方就不能這樣做。 */
.login-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.login-chart { position: relative; z-index: 1; width: 100%; height: 100%; display: block; }

/* 懸浮粒子（login-particles.js）：畫在 K 棒走勢與中央暗色暈影（.login-bg::after，
   z-index 2）之上、掃描線之下——壓在暈影底下的話，卡片周圍那一圈會完全看不到粒子。
   整層滑鼠穿透，純裝飾。 */
.login-particles {
  position: absolute;
  inset: 0;
  z-index: 3;
  width: 100%;
  height: 100%;
  display: block;
}

/* CRT 掃描線——終端機質感最省成本的一筆：純 CSS repeating-gradient 疊一層
   極淡的橫紋，緩慢往下捲動。不用額外的 JS 或圖片，GPU 只需要合成一個
   position 位移，效能可以忽略不計。透明度壓得很低，離近看才看得到紋理，
   退遠看是「螢幕在自然呼吸」的質感，不是明顯的裝飾線條。 */
.login-scanlines {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: repeating-linear-gradient(
    to bottom,
    rgba(46, 230, 255, .05) 0px,
    rgba(46, 230, 255, .05) 1px,
    transparent 1px,
    transparent 3px
  );
  background-size: 100% 3px;
  animation: login-scan-drift 9s linear infinite;
  mix-blend-mode: screen;
}
@keyframes login-scan-drift {
  from { background-position: 0 0; }
  to   { background-position: 0 240px; }
}

/* 深空一樣緩慢飄移的兩團模糊色暈——比 SVG 裡的走勢線更後面一層，用純 CSS
   keyframe 跑（不吃 anime.js 的計算成本），28 秒繞一圈、幾乎看不出來在動，
   只在餘光裡感覺到畫面「活著」。這是「質感」的主要來源之一：讓背景有縱深，
   不是一片死板的純色。顏色刻意壓到很低的透明度，才不會跟走勢線搶注意力。 */
.login-bg::before {
  content: "";
  position: absolute;
  inset: -10%;
  z-index: 0;
  background:
    radial-gradient(38% 30% at 22% 28%, rgba(var(--accent-rgb), .16), transparent 70%),
    radial-gradient(34% 26% at 78% 70%, rgba(78, 214, 209, .08), transparent 70%);
  filter: blur(40px);
  animation: login-aura-drift 28s ease-in-out infinite alternate;
}
@keyframes login-aura-drift {
  0%   { transform: translate(0, 0) scale(1); }
  100% { transform: translate(-3%, 2.5%) scale(1.06); }
}

/* 中央往外淡出的暗色暈影——讓卡片周圍的走勢線/K 棒最亮，卡片正後方最暗，
   視覺上像卡片自己在發一圈柔光，不會跟卡片的文字對比度打架 */
.login-bg::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background: radial-gradient(640px 480px at 50% 54%, var(--bg) 0%, transparent 74%);
  opacity: .86;
}

/* 頂部跑馬燈——交易終端機最經典的畫面元素，直接把「這是一個看盤系統」的
   訊息傳達出來，比任何裝飾線條都更貼題。內容由 login-animation.js 動態產生
   一批假代號／價格／漲跌幅，色彩用全站既有的 --up/--down 語意色（不是霓虹色），
   跟真正的交易終端機一樣：外殼可以很賽博龐克，報價本身的紅綠語言不能變，
   不然反而破壞「這是真的在報價」的說服力。 */
.login-ticker {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 4;
  height: 30px;
  overflow: hidden;
  background: rgba(3, 8, 14, .72);
  border-bottom: 1px solid var(--cyber-cyan-dim);
  box-shadow: 0 1px 14px -2px rgba(46, 230, 255, .35);
  backdrop-filter: blur(2px);
}
.login-ticker-track {
  display: flex;
  align-items: center;
  gap: 26px;
  padding-left: 24px;
  height: 100%;
  white-space: nowrap;
  will-change: transform;
}
.ticker-item {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--text-mute);
}
.ticker-item .t-sym { color: var(--text-dim); }
.ticker-item .t-up   { color: var(--up-text); }
.ticker-item .t-down { color: var(--down-text); }

.login-card {
  position: relative;
  z-index: 1;
  width: min(420px, 100%);
  padding: 28px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow-lg), 0 0 0 1px rgba(46, 230, 255, .08), 0 0 46px -18px rgba(46, 230, 255, .5);
}

/* HUD 取景框角——鎖定目標／已授權終端機的視覺語言，四個角各是一個 L 形
   邊框，比整圈邊框更「科技感」，因為它暗示畫面裡還有更多東西沒被畫出來、
   只框住重點。用 border 兩邊組成 L 形，比另外畫 SVG 簡單，效能也更好。 */
.hud-corner {
  position: absolute;
  width: 18px;
  height: 18px;
  z-index: 2;
  border: 2px solid var(--cyber-cyan);
  opacity: 0; /* login-animation.js 進場時用 anime.js 淡入＋輕微位移，見該檔案說明 */
  pointer-events: none;
}
.hud-corner-tl { top: -1px; left: -1px; border-right: none; border-bottom: none; border-radius: 6px 0 0 0; }
.hud-corner-tr { top: -1px; right: -1px; border-left: none; border-bottom: none; border-radius: 0 6px 0 0; }
.hud-corner-bl { bottom: -1px; left: -1px; border-right: none; border-top: none; border-radius: 0 0 0 6px; }
.hud-corner-br { bottom: -1px; right: -1px; border-left: none; border-top: none; border-radius: 0 0 6px 0; }

.login-brand { display: flex; align-items: center; gap: 12px; margin-bottom: 22px; }
.login-brand h1 { font-size: 19px; font-weight: 700; }

/* 文字偶爾故障一下——真正的故障藝術那種水平切片位移＋色版分離＋短暫雜訊，
   不是單純閃一下 RGB 重影。做法：JS（login-animation.js）把文字切成幾條
   水平切片（clip-path 各自裁一條），每條切片各自水平亂跳、其中兩條額外染
   青色／洋紅色（mix-blend-mode: screen，色版分離的來源），整個容器再疊一層
   會隨故障強度變化的 blur——三者疊加大約 1 秒的「糊掉」，最後 20% 的時間
   振幅線性收斂到 0，畫面「跑回」清晰的正常文字，不是被硬生生切斷。平常
   完全看不出來，隔一段隨機時間才觸發一次，故意做得少見——這是「這裡有點
   意思」的訊號，不是要讓人覺得網站真的壞了。 */
.glitch-text { position: relative; display: inline-block; }
.glitch-band {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
  white-space: nowrap;
  will-change: transform, opacity;
}
.glitch-band-cyan    { color: var(--cyber-cyan); mix-blend-mode: screen; }
.glitch-band-magenta { color: var(--cyber-magenta); mix-blend-mode: screen; }
/* 故障開頭那一瞬間額外閃一下的白色雜訊，模擬訊號剛被打斷的感覺，只在
   故障觸發的最初幾格出現，不是持續存在的圖層 */
.glitch-flash {
  position: absolute;
  inset: -4px -8px;
  background: #fff;
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: overlay;
}

.login-hint { font-size: 12.5px; color: var(--text-dim); line-height: 1.7; margin: 0 0 16px; }

/* 頻道 logo（Greedy Leek）——訪客剛從 YouTube 點進來、還不確定是不是同一個站，
   這句話正好是在講「用 YouTube 會員的 Discord 帳號登入」，圖示掛在這句話前面
   當視覺確認，不是另外找地方硬塞一個裝飾。用無字版（小尺寸下文字會糊）。 */
.login-channel-hint { display: flex; align-items: flex-start; gap: 8px; }
.login-channel-badge { flex-shrink: 0; margin-top: 1px; opacity: .8; transition: opacity .16s ease; }
.login-channel-badge:hover { opacity: 1; }
.login-channel-badge img { display: block; width: 20px; height: 20px; object-fit: contain; }

.login-error {
  margin: 0 0 16px;
  padding: 10px 12px;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--warn);
  background: var(--warn-soft);
  border: 1px solid var(--warn);
  border-radius: 8px;
}

/* Discord 品牌色，是外部服務的識別色，不屬於站內三軸語意色的一部分。
   這顆是 Moment tier 元素（畫面上同時只會出現這一顆，見 DESIGN.md「Motion Tiers」），
   套用液態玻璃材質——純 CSS 近似（見 docs/adr/0002-liquid-glass-css-only.md），
   不用 SVG 濾鏡：分層漸層做「霧面＋高光掃過」的光澤，:active 用不對稱圓角模擬
   液體受壓變形。品牌色本身保留不換掉，玻璃是疊加的材質層，不是換色。
   全站不因 prefers-reduced-motion 關閉動畫（見 docs/adr/0001），這裡沒有例外。 */
.login-discord {
  position: relative;
  isolation: isolate; /* 讓 ::before 的 mix-blend-mode 只在按鈕範圍內生效，不溢出去影響外面 */
  overflow: hidden;   /* 高光掃過的範圍要被按鈕邊界裁掉 */
  width: 100%;
  justify-content: center;
  padding: 11px;
  font-size: 14.5px;
  background: #5865f2;
  border-color: #5865f2;
  color: #fff;
  box-shadow: 0 8px 20px -8px rgba(88, 101, 242, .55);
  transition: transform .5s cubic-bezier(.34, 1.56, .64, 1),
              border-radius .5s cubic-bezier(.34, 1.56, .64, 1),
              box-shadow .35s ease, filter .25s ease;
}

/* 圖示＋文字包成一層，明確蓋在下面兩個裝飾用偽元素之上——偽元素是 position:absolute，
   在沒有明確 z-index 的情況下會疊在一般行內內容（圖示、文字）上面，蓋住可讀性，
   所以這裡跟偽元素一起給明確的 z-index 讓文字穩穩贏。 */
.login-discord-label {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* 高光掃過的玻璃層——一條斜向白色亮帶，平常躲在按鈕左側外面。
   mix-blend-mode: overlay 讓亮帶疊在品牌紫上是「提亮」，不是蓋掉底色。 */
.login-discord::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset: -60% -10%;
  background: linear-gradient(
    115deg,
    transparent 35%,
    rgba(255, 255, 255, .55) 48%,
    rgba(255, 255, 255, .75) 50%,
    rgba(255, 255, 255, .55) 52%,
    transparent 65%
  );
  transform: translateX(-70%);
  mix-blend-mode: overlay;
  pointer-events: none;
  transition: transform .6s cubic-bezier(.16, 1, .3, 1);
}

/* 霧面感——上緣一道柔和白色光暈，呼應全站「Lit-From-Above」的光源方向規則
   （見 DESIGN.md Elevation & Depth），讓玻璃像是被同一個光源照到，不是自己發光。 */
.login-discord::after {
  content: "";
  position: absolute;
  z-index: 0;
  inset: 0;
  background: radial-gradient(120% 90% at 50% -10%, rgba(255, 255, 255, .4), transparent 60%);
  opacity: .7;
  pointer-events: none;
  transition: opacity .3s ease;
}

/* 第一階段：滑鼠移過去就開始輕度液化預覽——高光開始滑動、霧面微微提亮，
   還不做形變，形變留給真正按下去的那一刻。 */
.login-discord:hover {
  filter: brightness(1.08) saturate(1.15);
  box-shadow: 0 12px 28px -8px rgba(88, 101, 242, .7);
}
.login-discord:hover::before { transform: translateX(65%); }
.login-discord:hover::after { opacity: 1; }

/* 第二階段：按下去才是真正的「液化擠壓」——不對稱圓角模擬液體受力變形，
   輕微下沉＋縮小模擬按進玻璃裡的觸感。這裡蓋掉全站 .primary-btn:active 的
   scale(.96)，這顆用自己的形變邏輯，過渡時間縮短讓按壓感是即時的。 */
.login-discord:active {
  transform: scale(.97) translateY(1px);
  border-radius: 16px 26px 16px 26px / 20px 14px 20px 14px;
  filter: brightness(.97) saturate(1.25);
  box-shadow: 0 4px 14px -6px rgba(88, 101, 242, .5);
  transition: transform .16s cubic-bezier(.34, 1.56, .64, 1),
              border-radius .16s cubic-bezier(.34, 1.56, .64, 1),
              filter .1s ease, box-shadow .1s ease;
}
.login-discord:active::before { transform: translateX(90%); }

.login-discord .icon { width: 18px; height: 18px; }

/* 2026-10-06：Discord 退成次要按鈕（描邊）。原本兩顆一樣大、Discord 還是飽和的品牌紫，
   看起來比「用 Google 免費登入」更像主要行動；但會來到登入頁的大多是還不是會員的人，
   頻道會員知道自己要按哪顆。跟測驗網站結算畫面同一個分法（實心 Google、描邊 Discord）。
   品牌紫留在描邊和字上；字用提亮的紫（#9aa2ff 在面板底上約 7:1），原色當字不到 4.5:1。 */
.login-discord {
  padding: 9px;
  font-size: 13.5px;
  background: transparent;
  border-color: rgba(88, 101, 242, .75);
  color: #9aa2ff;
  box-shadow: none;
}
.login-discord::before { opacity: .35; }
.login-discord::after { opacity: 0; }
.login-discord:hover {
  background: rgba(88, 101, 242, .16);
  border-color: #5865f2;
  color: #c3c7ff;
  filter: none;
  box-shadow: none;
}
.login-discord:hover::after { opacity: .25; }
.login-discord:active { box-shadow: none; filter: none; }

/* 免費體驗是主要行動：放在 Discord 登入之前，做成最顯眼的一顆，跟 Discord 那顆
   同一套液態玻璃材質語言（見 docs/adr/0002-liquid-glass-css-only.md）——兩顆都是
   Moment tier（同時只會出現這兩顆），才允許這種份量的裝飾。玻璃的底色跟光暈調成
   Google 官方深色模式按鈕的配色（深底、白色 G 標誌方塊），不是隨便挑的顏色；
   Google 品牌本身是四色 G 標誌，不適合直接套用「品牌色當底色」那招（Discord 那樣），
   四色標誌放在任何單一飽和色底上都會有一到兩色糊掉，所以底色維持中性深色，
   讓標誌自己的四色在白色方塊上維持正確對比，跟 Google 官方按鈕規範一致。 */
.login-google {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  width: 100%;
  justify-content: center;
  padding: 11px;
  font-size: 14.5px;
  margin-bottom: 8px;
  background: #131314;
  border: 1px solid #5f6368;
  color: #e3e3e3;
  box-shadow: 0 8px 20px -8px rgba(66, 133, 244, .35);
  transition: transform .5s cubic-bezier(.34, 1.56, .64, 1),
              border-radius .5s cubic-bezier(.34, 1.56, .64, 1),
              box-shadow .35s ease, filter .25s ease;
}
.login-google-label {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.login-google-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  background: #fff;
  border-radius: 4px;
}
.login-google-mark svg { width: 14px; height: 14px; }

/* 高光掃過的玻璃層，跟 Discord 按鈕同一套動態，只是疊在中性深色上而不是品牌色上 */
.login-google::before {
  content: "";
  position: absolute;
  z-index: 0;
  inset: -60% -10%;
  background: linear-gradient(
    115deg,
    transparent 35%,
    rgba(255, 255, 255, .18) 48%,
    rgba(255, 255, 255, .28) 50%,
    rgba(255, 255, 255, .18) 52%,
    transparent 65%
  );
  transform: translateX(-70%);
  mix-blend-mode: overlay;
  pointer-events: none;
  transition: transform .6s cubic-bezier(.16, 1, .3, 1);
}
.login-google::after {
  content: "";
  position: absolute;
  z-index: 0;
  inset: 0;
  background: radial-gradient(120% 90% at 50% -10%, rgba(255, 255, 255, .14), transparent 60%);
  opacity: .7;
  pointer-events: none;
  transition: opacity .3s ease;
}

.login-google:hover {
  border-color: #8e918f;
  filter: brightness(1.15);
  box-shadow: 0 12px 28px -8px rgba(66, 133, 244, .55);
}
.login-google:hover::before { transform: translateX(65%); }
.login-google:hover::after { opacity: 1; }

.login-google:active {
  transform: scale(.97) translateY(1px);
  border-radius: 16px 26px 16px 26px / 20px 14px 20px 14px;
  filter: brightness(.95);
  box-shadow: 0 4px 14px -6px rgba(66, 133, 244, .4);
  transition: transform .16s cubic-bezier(.34, 1.56, .64, 1),
              border-radius .16s cubic-bezier(.34, 1.56, .64, 1),
              filter .1s ease, box-shadow .1s ease;
}
.login-google:active::before { transform: translateX(90%); }

/* 「Discord 登入不了？」原本只有字那麼高（284×19），手機上很難點到（2026-10-06）：
   上下各加 13px，整列 44px 高 */
.login-help { margin-top: 4px; }
.login-help summary { cursor: pointer; padding: 13px 0; font-size: 12.5px; line-height: 18px; color: var(--accent-text); }

.login-free-hint { margin: 0 0 18px; }

/* 不登入也看得到監控清單（docs/adr/0019）：最後一行留一條路，不跟兩顆登入鈕搶 */
.login-guest-link {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  margin-top: 10px;
  border-top: 1px solid var(--line);
  padding-top: 8px;
  font-size: 13px;
  color: var(--text-dim);
  text-decoration: none;
}
.login-guest-link:hover { color: var(--text); }
.login-help ol { margin: 10px 0 0; padding-left: 20px; font-size: 12.5px; color: var(--text-dim); line-height: 1.9; }
.login-help ol b { color: var(--text); font-weight: 700; }
.login-help-more { display: inline-flex; align-items: center; min-height: 40px; margin-top: 4px; font-size: 13px; font-weight: 700; color: var(--accent-text); text-decoration: none; }
.login-help-more:hover { text-decoration: underline; }

.login-admin { margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--line); }
.login-admin .hint { margin-bottom: 8px; }
.login-admin input { flex: 1; min-width: 0; }

/* ---------------- 復盤頁（/review） ----------------
   族群輪動榜／個股結構榜是 Read tier（見 DESIGN.md「Motion Tiers」、
   docs/adr/0004-review-page-read-tier.md）：使用者收盤後要坐下來讀、比
   結構，不是盤中要在幾秒內掃過的內容，字級／間距比全站其餘 Operate tier
   元件更寬鬆。但骨架仍是表格、仍然可能同時渲染上百列，所以只放寬字級跟
   間距，不加彈簧曲線、不疊材質層——放寬的是「閱讀舒適度」，不是「動態
   華麗度」，這一點跟 Moment tier 不一樣，不要混為一談。 */
.review-main {
  max-width: 1800px;
  margin: 0 auto;
  padding: 18px 22px 40px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}
/* 「誰強」「關卡動態」兩個分頁各包一層，裡面的面板跟外層同樣間距（原本 0px，圓角互相頂住） */
#tab-strength, #tab-timing { display: flex; flex-direction: column; gap: 22px; }
#tab-strength[hidden], #tab-timing[hidden] { display: none; }
.review-main .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.review-main .dim  { color: var(--text-dim); }
/* ⚠️ review.js 的 toneOf() 一直都在幫 RS 變化、反彈差、今日漲跌這幾欄的
   td 加上 up/down class，但全站沒有任何一條泛用的 .up/.down 規則會套色
   （其他地方的 up/down 都是 .price.up、.alert-item.up 這種限定在自己元件
   內的規則）——這頁的紅綠語意其實從來沒有真的生效過，數字一直都是預設
   文字色。這裡補上，不是這次重排版新加的行為，是修一個原本就存在的漏網。 */
.review-main .up   { color: var(--up-text); }
.review-main .down { color: var(--down-text); }

/* 大盤下殺區間：整頁的前提條件，所以放在最上面單獨一條 */
.drawdown-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px 14px;
  padding: 12px 16px;
  font-size: 12.5px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow-sm);
}
.drawdown-bar .dd-label { font-weight: 700; color: var(--text-dim); }
.drawdown-bar .dd-range { font-family: var(--mono); color: var(--text); }
.drawdown-bar .dd-decline { font-family: var(--mono); font-weight: 700; }
.drawdown-bar .dd-sep { color: var(--text-mute); }
.drawdown-bar .dd-rec { color: var(--text-dim); }
.drawdown-bar .dd-rec b { color: var(--text); }
.drawdown-bar .dd-none { color: var(--text-mute); }

/* ---------------- 關卡動態（強勢榜的第二個分頁） ----------------
   以前是四組 43 張大卡片（股價 23px 最大字、下面兩排小字），跟同一頁的族群
   輪動榜／個股結構榜完全是兩套版型，看起來格格不入。改成跟那兩張表同一種
   Read tier 表格（見 docs/adr/0004）：主角是「距關卡尺」跟一句話狀況，股價本身
   這裡根本不看，不列。 */
#timing-warning { margin: 0 16px 4px; border-radius: 8px; font-size: 13.5px; }
.timing-lede { margin: 0; padding: 12px 16px 0; font-size: 14px; line-height: 1.65; color: var(--text-dim); }
.timing-lede b { color: var(--text); }

/* 四格：一條關卡的生命週期，同時是圖例跟篩選鈕 */
.timing-flow { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); padding: 14px 16px 6px; }
/* 名單還沒回來的時候（review.html 的 data-loading，review.js 的 renderTiming 拿掉）：先撐到一個畫面高。
   2026-10-13 響應式 QA V-03：只有一行「載入中…」的時候，名單底下的說明和頁尾會出現在畫面裡，
   資料一回來就被推出去，算成版面位移。撐住之後它們一開始就在畫面外，推動看不到。 */
#timing-panel[data-loading] .timing-table-wrap { min-height: 100vh; }
.timing-group-label { grid-row: 1; padding: 0 4px 6px; font-size: 12.5px; color: var(--text-mute); border-bottom: 1px solid var(--line); }
.timing-group-label.right { grid-column: 1 / span 2; margin-right: 10px; }
.timing-group-label.rev { grid-column: 3 / span 2; margin-left: 10px; }
.timing-stage {
  grid-row: 2;
  position: relative;
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr);
  column-gap: 10px;
  align-items: center;
  margin: 8px 5px 0;
  padding: 10px 12px;
  text-align: left;
  font-family: inherit;
  color: var(--text);
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 10px;
  cursor: pointer;
}
.timing-stage:hover { background: var(--bg-hover); }
.timing-stage[aria-pressed="true"] { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.timing-stage:not(:last-child)::after {
  content: "›";
  position: absolute;
  right: -10px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 16px;
  color: var(--text-mute);
}
.timing-sch { width: 76px; height: 40px; grid-row: span 3; }
.timing-sch .sch-level { stroke: var(--accent); stroke-width: 1.4; stroke-dasharray: 4 3; }
.timing-sch .sch-path { fill: none; stroke: var(--text); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.timing-sch .sch-dot { fill: var(--text); }
.ts-name { display: flex; align-items: baseline; gap: 8px; font-size: 14.5px; font-weight: 700; }
.ts-count { font-size: 13px; font-weight: 600; color: var(--text-mute); }
.ts-wait { font-size: 12.5px; color: var(--text-dim); }
.ts-scope { font-size: 11.5px; color: var(--text-mute); }

.timing-rules { padding: 6px 16px 10px; }
.timing-rules summary { cursor: pointer; font-size: 12.5px; color: var(--accent-text); user-select: none; }
.timing-rules summary:hover { color: var(--text); }
@media (pointer: coarse) { .timing-rules summary { padding-block: 8px; } }
/* 觸控裝置：新聞標題一行只有 17px 高、題材輪動「還有 N 個」23px，上下各墊一點到 24px 以上 */
@media (pointer: coarse) {
  .news-item a { padding-block: 4px; }
  .rq-more { min-height: 28px; }
}
.timing-rules p { margin: 8px 0 0; font-size: 13px; line-height: 1.65; color: var(--text-mute); }
.timing-rules p b { color: var(--text-dim); }
/* 寬螢幕：四種判法排成左右兩欄，把面板排滿（2026-10-10）——一欄排到底的話一行一百多個字、有二十幾行。
   先往下排再換欄：左欄＝蓄勢待突破、突破後拉回測試，右欄＝破底翻的兩種，
   跟上面 .timing-flow 的左右兩組（往上突破／突破後又跌回線下）上下對齊；斷點也跟它同一個。
   最後那段總說明橫跨兩欄。 */
@media (min-width: 1101px) {
  #timing-rules-body { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: auto auto; grid-auto-flow: column; column-gap: 20px; }
  #timing-rules-body .timing-rules-note { grid-column: 1 / -1; grid-row: 3; }
}

/* 族群輪動榜沒有大盤下殺區間時，跌幅倍數、反彈差整欄收起（見 review.js 的 syncGroupDrawdownCols） */
.no-dd .col-dd { display: none; }

/* 「欄位怎麼看」：表頭 title 的說明攤成看得到的清單，手機上 title 根本叫不出來（review.js 的 renderColumnHelp） */
.col-help { padding: 2px 16px 8px; border-top: 1px solid var(--line); }
.col-help summary { padding: 13px 0; line-height: 18px; cursor: pointer; font-size: 12.5px; color: var(--accent-text); user-select: none; }
.col-help summary:hover { color: var(--text); }
.col-help dl { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 14px; margin: 0 0 8px; font-size: 13px; line-height: 1.65; }
.col-help dt { font-weight: 700; color: var(--text-dim); }
.col-help dd { margin: 0; color: var(--text-mute); }
@media (max-width: 640px) {
  .col-help dl { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .col-help dd { margin-bottom: 8px; }
}

/* 名單：跟族群輪動榜／個股結構榜同一種表格（字級、列高、次要文字） */
.timing-table-wrap { overflow-x: auto; border-top: 1px solid var(--line); }
.timing-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.timing-table thead th {
  padding: 11px 14px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .3px;
  text-align: left;
  color: var(--text-mute);
  border-bottom: 1px solid var(--line);
}
.timing-table td { padding: 13px 14px; vertical-align: middle; border-bottom: 1px solid var(--line); }
.timing-row { cursor: pointer; }
.timing-row:hover td { background: var(--bg-hover); }
.timing-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.timing-sec td { padding: 16px 14px 6px; font-size: 13px; font-weight: 700; color: var(--text-dim); border-bottom: 0; }
.ts-sec-count { margin-left: 8px; font-weight: 600; color: var(--text-mute); }
.ts-sec-note { margin-left: 10px; font-size: 12.5px; font-weight: 400; color: var(--text-mute); }
.timing-sec-empty td { font-size: 13px; color: var(--text-mute); }
.t-name .stk-name { font-size: 15px; font-weight: 700; }
.t-name .stk-sym { margin-left: 6px; font-size: 12px; color: var(--text-mute); }
.timing-tag { display: block; margin-top: 2px; font-size: 12.5px; color: var(--text-mute); }
/* 「位置」那一欄：同時符合兩格的股票有兩個標籤，放不下就排成兩行（全站的 tbody td 預設不換行；
   2026-10-10 標籤從「已成功」改成「破底翻已成功」之後，兩個並排會超出這一欄） */
.timing-row .t-stage { white-space: normal; }
.timing-chip {
  display: inline-block;
  margin: 1px 4px 1px 0;
  padding: 2px 8px;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--text);
  border: 1px solid var(--text-mute);
  border-radius: 999px;
}

/* 距關卡尺：中間那條直線就是關卡，點在左邊＝收盤還在線下，右邊＝已在線上。
   不用紅綠：在線上／線下不是漲跌 */
.timing-ruler { display: flex; align-items: center; gap: 10px; }
.timing-ruler svg { flex: none; width: 130px; height: 22px; }
.timing-ruler .r-track { stroke: var(--line); stroke-width: 4; stroke-linecap: round; }
.timing-ruler .r-seg { stroke: var(--text-mute); stroke-width: 4; stroke-linecap: round; }
.timing-ruler .r-level { stroke: var(--accent); stroke-width: 2; }
.timing-ruler .r-dot { fill: var(--text); }
.timing-pct { min-width: 58px; font-size: 14px; font-weight: 700; }
.timing-side { display: block; font-size: 12px; font-weight: 400; color: var(--text-mute); }

/* 「現在的狀況」「股票」兩欄的字可以折行（2026-10-11 檢查）。全站的 tbody td 預設不折行，這張表又是固定欄寬：
   一句「橫著走了 45 天，第 6 次碰到 386.41 這條線，收盤還沒站上去」放不下就直接蓋到右邊的走勢圖上，
   1280px 以下每一列都疊字，連 1366 的筆電表格都被撐出 31px 的橫向捲動。 */
.timing-row .t-story, .timing-row .t-name { white-space: normal; }
.timing-row .t-name .stk-name { white-space: nowrap; }
.timing-line { font-size: 14.5px; line-height: 1.55; color: var(--text); }
.timing-line + .timing-line { margin-top: 6px; }
.timing-sub { display: block; font-size: 12.5px; color: var(--text-mute); }
.timing-meta { margin-top: 5px; font-size: 12.5px; color: var(--text-mute); }
/* 2026-10-24 站長：關卡動態每一列只留股名、族群、離關卡多遠、一句狀況；那句底下的小字（貼近壓力、箱型來回、
   幾天前站回…）和「站上均線・上檔套牢・族群名次・10 日均額」那一行，手機、平板、筆電、桌機都不顯示 */
#timing-body .timing-row .t-story .timing-sub, #timing-body .timing-meta { display: none; }
/* 非會員看到的「突破後拉回測試」：一張醒目的卡片（review.js renderTiming，2026-10-24 站長：原本一行灰字看不出來）。
   品牌藍是「可以點、可以做」的顏色，不碰紅綠（紅漲綠跌）。 */
#timing-body .timing-member-only td { padding-top: 12px; padding-bottom: 14px; }
.tm-lock-card {
  display: flex; gap: 14px; align-items: flex-start;
  padding: 16px 18px;
  background: linear-gradient(135deg, rgba(var(--accent-rgb), .16), rgba(var(--accent-rgb), .05));
  border: 1px solid rgba(var(--accent-rgb), .55);
  border-radius: 12px;
}
.tm-lock-icon {
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%;
  color: var(--accent-ink); background: var(--accent);
}
.tm-lock-icon .icon { width: 20px; height: 20px; }
.tm-lock-body { min-width: 0; }
.tm-lock-head { margin: 0; font-size: 17px; font-weight: 700; line-height: 1.45; color: var(--text); }
.tm-lock-head b { font-size: 22px; color: var(--accent-text); }
.tm-lock-text { margin: 4px 0 0; font-size: 14px; line-height: 1.6; color: var(--text-dim); }
.tm-lock-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-top: 12px; }
.tm-lock-main {
  display: inline-flex; align-items: center; min-height: 40px; padding: 0 18px;
  font-size: 14.5px; font-weight: 700; color: var(--accent-ink); text-decoration: none;
  background: var(--accent); border-radius: 8px;
}
.tm-lock-main:hover { filter: brightness(1.1); }
.tm-lock-main:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }
.tm-lock-minor { display: inline-flex; flex-wrap: wrap; gap: 0 14px; font-size: 13px; }
.tm-lock-minor a { padding: 8px 0; color: var(--accent-text); text-decoration: none; }
.tm-lock-minor a:hover { text-decoration: underline; }
@media (max-width: 700px) {
  .tm-lock-card { padding: 14px; gap: 12px; }
  .tm-lock-icon { width: 34px; height: 34px; }
  .tm-lock-main { width: 100%; justify-content: center; }
}
.timing-spark { display: block; width: 120px; height: 30px; }
.timing-spark .l { stroke: var(--accent); stroke-width: 1.2; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }
.timing-spark .p { fill: none; stroke: var(--text-dim); stroke-width: 1.4; vector-effect: non-scaling-stroke; }

@media (max-width: 1100px) {
  .timing-flow { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 8px; }
  .timing-group-label { display: none; }
  .timing-stage { grid-row: auto; margin: 0 4px; }
  .timing-stage::after { display: none; }
}
/* 筆電以下，距關卡那把尺短一點：那一欄只有表格的 19%，130px 的尺加旁邊的數字放不下 */
@media (max-width: 1280px) {
  .timing-ruler svg { width: 96px; }
}
/* 手機：四格的示意圖放在字上面 */
@media (max-width: 700px) {
  .timing-flow { padding: 12px 12px 4px; }
  .timing-stage { grid-template-columns: minmax(0, 1fr); row-gap: 2px; padding: 9px 10px; }
  .timing-sch { width: 64px; height: 28px; grid-row: auto; }
  .ts-name { font-size: 14px; white-space: nowrap; }
  .ts-scope { display: none; }
}
/* 手機和直放的平板（1000px 以下）：表格改成每檔一塊——股名＋距關卡尺一行、狀況一行，位置標籤跟走勢圖省略
   （上面的分段標題已經說了是哪一格）。原本只到 700px：701～1000 還是五欄的表格，欄位擠到字疊在一起
   （2026-10-11 平板直放 820px 檢查抓到）。 */
@media (max-width: 1000px) {
  .timing-table { display: block; width: 100%; }
  .timing-table colgroup, .timing-table thead { display: none; }
  .timing-table tbody { display: block; }
  .timing-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "name ruler" "story story";
    gap: 6px 10px;
    padding: 11px 12px;
    border-bottom: 1px solid var(--line);
  }
  .timing-row td { padding: 0; border: 0; }
  .timing-row .t-name { grid-area: name; }
  .timing-row .t-ruler { grid-area: ruler; }
  .timing-row .t-story { grid-area: story; }
  .timing-row .t-stage, .timing-row .t-spark { display: none; }
  .timing-sec, .timing-sec-empty { display: block; }
  .timing-sec td, .timing-sec-empty td { display: block; padding-left: 12px; padding-right: 12px; white-space: normal; }
}
@media (max-width: 700px) {
  .timing-ruler svg { width: 84px; }
}
/* 直放的平板（701～1000px）一檔一塊的時候右邊還有位置：近 60 日的走勢圖留著，放在狀況那一行的右邊。
   手機沒有這個位置，照舊省略。 */
@media (min-width: 701px) and (max-width: 1000px) {
  .timing-row { grid-template-areas: "name ruler" "story spark"; padding: 13px 14px; }
  .timing-row .t-spark { display: block; grid-area: spark; align-self: center; justify-self: end; }
}

/* ---------------- 抗跌股雷達（強勢榜第三個分頁，2026-10-21） ----------------
   名單沿用關卡動態的 Read tier 表格（.timing-table／.timing-row）；多的是上面一條大盤狀態、
   一排型態篩選、每一列點開的判定細節。大盤在跌是「跌」的語意，徽章用綠（紅漲綠跌）。 */
#radar-panel[data-loading] .timing-table-wrap { min-height: 100vh; }
.radar-market { padding: 12px 16px 2px; }
.radar-market-empty { margin: 0; font-size: 13.5px; color: var(--text-mute); }
.rm-state { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; font-size: 14.5px; }
.rm-state b { font-size: 15px; }
.rm-badge {
  display: inline-block;
  padding: 2px 10px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--down-text);
  background: var(--down-soft);
  border: 1px solid var(--down);
  border-radius: 999px;
}
.rm-badge.rm-off { color: var(--text-dim); background: var(--bg-raise); border-color: var(--line); }
.rm-sub { font-size: 13.5px; line-height: 1.6; color: var(--text-dim); }
.rm-facts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.rm-fact {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  padding: 7px 12px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 8px;
}
.rm-label { font-size: 12px; color: var(--text-mute); }
.rm-value { font-size: 14.5px; font-weight: 700; white-space: nowrap; }
.rm-value small { margin-left: 2px; font-size: 12px; font-weight: 400; color: var(--text-mute); }

.radar-controls { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 16px 10px; }
.radar-filters { display: flex; flex-wrap: wrap; gap: 6px; }
.radar-chip { font-size: 12.5px; padding: 5px 12px; }
.radar-chip .mono { font-size: 12px; color: var(--text-mute); }
.radar-chip[aria-pressed="true"] { color: var(--text); background: var(--accent-soft); border-color: var(--accent); }
.radar-chip[aria-pressed="true"] .mono { color: var(--text); }
.radar-sort { display: inline-flex; align-items: center; gap: 8px; font-size: 12.5px; color: var(--text-mute); }
.radar-sort select {
  padding: 5px 8px;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 8px;
}
@media (pointer: coarse) {
  .radar-chip { min-height: 32px; }
  .radar-sort select { min-height: 34px; }
}

.radar-table td { vertical-align: top; }
.radar-row .r-line { display: block; font-size: 15px; font-weight: 700; }
/* 可以點的欄名（分數、套牢比）：滑鼠指到變亮，跟其他榜的排序欄名一樣 */
.radar-table th[data-radar-sort] { cursor: pointer; user-select: none; white-space: nowrap; }
.radar-table th[data-radar-sort]:hover { color: var(--accent-text); }
.radar-table th[data-radar-sort]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* 股名旁邊開支撐壓力圖的小按鈕（點它只開圖，不會展開那一列） */
.radar-chart-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  margin-left: 6px;
  padding: 0;
  vertical-align: -6px;
  color: var(--text-mute);
  background: transparent;
  border: 1px solid var(--line);
  border-radius: 6px;
  cursor: pointer;
  transition: color .16s ease, background-color .16s ease, border-color .16s ease;
}
.radar-chart-btn .icon { width: 15px; height: 15px; }
.radar-chart-btn:hover { color: var(--text); background: var(--bg-hover); border-color: var(--text-mute); }
.radar-chart-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (pointer: coarse) { .radar-chart-btn { width: 32px; height: 32px; vertical-align: -9px; } }
.radar-row .r-score .mono { font-size: 19px; font-weight: 800; }
/* 2026-10-24 站長：表格和手機卡片都只留股名、型態、漲跌、贏大盤、分數、套牢比；支撐、為什麼被挑出來、
   近 60 日走勢收進股名旁邊那顆鈕展開的細節裡（表頭在 templates/review.html 一起拿掉） */
.radar-row .r-sup, .radar-row .r-why, .radar-row .t-spark { display: none; }
.radar-row .r-supply .mono { font-size: 15px; font-weight: 700; }
.radar-row .r-sup { white-space: normal; font-size: 14px; }
.radar-row .r-why .timing-line { font-size: 13.5px; line-height: 1.55; }
.radar-row .t-stage { white-space: normal; }
.radar-chip-primary { border-color: var(--text); }
.radar-chip-lostmark { color: var(--down-text); border-color: var(--down); }
.radar-note { display: block; margin-top: 3px; font-size: 12px; color: var(--text-mute); }
.radar-row.is-open td { background: var(--bg-hover); border-bottom-color: transparent; }

/* 點開的判定細節 */
.radar-detail td { padding: 4px 14px 16px; background: var(--bg-hover); white-space: normal; }
.rd-facts { display: flex; flex-wrap: wrap; gap: 4px 16px; padding: 4px 0 10px; font-size: 13px; color: var(--text-dim); }
.rd-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.rd-pat { padding: 10px 12px; background: var(--bg-raise); border: 1px solid var(--line); border-radius: 10px; }
.rd-pat.is-ok { border-color: var(--text-mute); }
.rd-pat h4 { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 0 0 6px; font-size: 13.5px; font-weight: 700; }
.rd-two h4 { margin: 0 0 6px; font-size: 13.5px; font-weight: 700; }
.rd-two h4 small { margin-left: 6px; font-size: 12px; font-weight: 400; color: var(--text-mute); }
.rd-pat h4 span { font-size: 12px; font-weight: 600; color: var(--text-mute); }
.rd-pat.is-ok h4 span { color: var(--text); }
.rd-checks, .rd-sups, .rd-score { margin: 0; padding: 0; list-style: none; }
.rd-checks li { display: grid; grid-template-columns: 16px minmax(0, 1fr); gap: 6px; padding: 3px 0; font-size: 12.5px; line-height: 1.5; }
.rd-checks .rc-mark { font-weight: 700; color: var(--text-mute); }
.rd-checks li.ok .rc-mark { color: var(--text); }
.rd-checks li.no .rc-label { color: var(--text-mute); }
.rc-label { display: block; color: var(--text-dim); }
.rc-detail { display: block; color: var(--text-mute); }
.rd-extra { margin: 6px 0 0; font-size: 12px; color: var(--text-mute); }
.rd-two { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; margin-top: 10px; }
.rd-two > div { padding: 10px 12px; background: var(--bg-raise); border: 1px solid var(--line); border-radius: 10px; }
/* 展開那一檔「之前出現在名單上」（review.js 的 radarPastHtml） */
.rd-past { margin-top: 10px; padding: 10px 12px; background: var(--bg-raise); border: 1px solid var(--line); border-radius: 10px; }
.rd-past h4 { margin: 0 0 6px; font-size: 13.5px; font-weight: 700; }
.rd-past h4 small { margin-left: 6px; font-size: 12px; font-weight: 400; color: var(--text-mute); }
.rd-past ul { display: grid; gap: 4px; margin: 0; padding: 0; list-style: none; font-size: 13px; color: var(--text-dim); }

/* 抗跌股雷達：過去的名單之後怎麼走（review.js 的 renderRadarFollowup，radar_followup.py，docs/adr/0027）。
   不用 .timing-table：那個在 1000px 以下會把表頭藏起來、改成一檔一塊，這裡全是數字，沒有表頭就看不懂；
   窄螢幕讓表格在框裡左右滑（第一欄的組別名稱可以折行）。 */
.rf-lede { margin: 0; padding: 12px 16px 0; font-size: 14px; line-height: 1.65; color: var(--text-dim); }
.rf-lede b { color: var(--text); }
.rf-horizons { display: flex; flex-wrap: wrap; gap: 6px; padding: 12px 16px 4px; }
.rf-sub { margin: 0; padding: 14px 16px 8px; font-size: 13.5px; font-weight: 700; color: var(--text-dim); }
/* 長期回測（2026-10-26）：跟上面這幾份名單分開一段 */
/* 抗跌股雷達下面兩段的標題（2026-10-26 站長：「標題明顯一點」）：字放大、前面一條強調色短直條，
   捲動時一眼看得出這裡換了一段。兩個標題同一個樣子 */
.rf-backtest { margin-top: 8px; border-top: 1px solid var(--line); }
#radar-followup .panel-head h2,
.rf-backtest .rf-bt-title {
  position: relative;
  padding-left: 12px;
  font-size: 18px;
  font-weight: 800;
  line-height: 1.4;
  color: var(--text);
}
#radar-followup .panel-head h2::before,
.rf-backtest .rf-bt-title::before {
  content: "";
  position: absolute;
  left: 0;
  top: .22em;
  bottom: .22em;
  width: 4px;
  border-radius: 2px;
  background: var(--accent);
}
.rf-backtest .rf-bt-title { margin: 6px 16px 0; padding-top: 14px; padding-bottom: 6px; }
.rf-backtest .rf-bt-title::before { top: calc(14px + .22em); bottom: calc(6px + .22em); } /* 標題換兩行時直條跟著拉長 */
@media (max-width: 640px) {
  #radar-followup .panel-head h2, .rf-backtest .rf-bt-title { font-size: 16.5px; }
  .rf-backtest .rf-bt-title { margin: 4px 12px 0; }
}
.rf-wrap { overflow-x: auto; border-top: 1px solid var(--line); }
.rf-table { width: 100%; min-width: 620px; border-collapse: collapse; font-size: 13px; }
.rf-table th { padding: 9px 12px; font-size: 12.5px; font-weight: 600; text-align: left; color: var(--text-mute); white-space: nowrap; border-bottom: 1px solid var(--line); }
.rf-table td { padding: 9px 12px; white-space: nowrap; vertical-align: top; border-bottom: 1px solid var(--line); }
.rf-table td.rf-group { min-width: 11em; white-space: normal; color: var(--text-dim); } /* 手機上組別名稱不要折成三行 */
.rf-table tr.rf-base td { background: var(--bg-hover); }
.rf-table td.rf-na { color: var(--text-mute); }
/* 先講一句話、再用長條比（review.js 的 rfSummaryHtml，2026-10-24 站長「有沒有更清楚的表達」）。
   長條只表示「多大」，用中性灰；漲跌的方向靠旁邊的字（紅漲綠跌），長條不搶那個顏色。對照組那一列底色標出來當基準。 */
.rf-summary { margin: 4px 16px 0; padding: 16px 18px; background: var(--bg-raise); border: 1px solid var(--line); border-radius: 12px; }
.rf-says { margin: 0; font-size: 16px; line-height: 1.75; color: var(--text-dim); }
.rf-says b { color: var(--text); }
.rf-caution { margin: 8px 0 0; font-size: 13px; color: var(--text-mute); }
.rf-compare { display: grid; gap: 2px; margin: 14px 0 0; padding: 0; list-style: none; }
.rf-row { display: grid; grid-template-columns: minmax(150px, 1.1fr) minmax(0, 1fr) minmax(0, 1fr); gap: 4px 18px; align-items: center; padding: 8px 10px; border-radius: 8px; }
.rf-row.is-base { background: var(--bg-hover); }
.rf-head { padding-top: 0; padding-bottom: 4px; font-size: 12.5px; font-weight: 600; color: var(--text-mute); }
.rf-head small { display: block; font-weight: 400; }
.rf-name { font-size: 14px; font-weight: 700; color: var(--text); }
.rf-name small { margin-left: 8px; font-size: 12px; font-weight: 400; color: var(--text-mute); }
.rf-cell { display: grid; grid-template-columns: 76px minmax(0, 1fr) auto; align-items: center; gap: 10px; font-size: 14px; }
.rf-bar { position: relative; height: 8px; background: var(--line); border-radius: 4px; }
.rf-bar i { display: block; height: 100%; background: var(--text-mute); border-radius: 4px; transition: width .55s cubic-bezier(.16, 1, .3, 1); }
.rf-row.is-base .rf-bar i { background: var(--text-dim); }
/* 「全部股票」落在哪：一條細線（2026-10-24 delight）。長條跟細線之間那一段：比全部股票少跌＝淡斜線，多跌＝深色。
   全部中性灰，方向的好壞不靠顏色講（紅綠只給漲跌，見 DESIGN.md）。 */
.rf-bar[style*="--base"]::after {
  content: ""; position: absolute; top: -4px; bottom: -4px; left: var(--base); width: 2px; margin-left: -1px;
  background: var(--text-dim); border-radius: 1px;
}
.rf-gap { position: absolute; top: 0; height: 100%; left: 0; width: 0; opacity: 0; transition: opacity .3s ease .45s; }
.rf-bar i[style] ~ .rf-gap[style*="left"] { opacity: 1; }
.rf-gap.is-less { background: repeating-linear-gradient(135deg, var(--text-mute) 0 2px, transparent 2px 5px); opacity: 0; }
.rf-gap.is-more { background: var(--text); border-radius: 0 4px 4px 0; }
.rf-bar i[style] ~ .rf-gap.is-less[style*="left"] { opacity: .55; }
.rf-bar i[style] ~ .rf-gap.is-more[style*="left"] { opacity: .55; }
.rf-vs { min-width: 52px; font-size: 12.5px; color: var(--text-mute); white-space: nowrap; }
.rf-full { margin: 10px 0 0; }
.rf-full > summary { padding: 10px 16px; font-size: 13.5px; color: var(--accent-text); cursor: pointer; user-select: none; }
.rf-full > summary:hover { color: var(--text); }
@media (max-width: 700px) {
  .rf-summary { margin: 4px 12px 0; padding: 14px; }
  .rf-says { font-size: 15px; }
  /* 手機：名稱一行，兩個數字並排在下一行 */
  .rf-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); padding: 8px 6px; }
  .rf-row .rf-name { grid-column: 1 / -1; }
  .rf-head > span:first-child { display: none; }
  .rf-cell { grid-template-columns: auto minmax(0, 1fr); gap: 4px 8px; }
  .rf-cell .rf-vs { grid-column: 1 / -1; }
  .rf-full > summary { padding: 10px 12px; }
}
.rf-note, .rf-empty { margin: 0; padding: 8px 16px 12px; font-size: 12.5px; line-height: 1.6; color: var(--text-mute); }
@media (max-width: 700px) {
  .rf-lede, .rf-sub, .rf-note, .rf-empty { padding-left: 12px; padding-right: 12px; }
  .rf-horizons { padding-left: 12px; padding-right: 12px; }
}
.rd-sups li { display: grid; grid-template-columns: max-content max-content max-content minmax(0, 1fr); align-items: baseline; gap: 2px 10px; padding: 4px 0; font-size: 12.5px; border-top: 1px solid var(--line); }
.rd-sups li:first-child { border-top: 0; }
.rs-name { font-weight: 700; color: var(--text-dim); }
.rs-status { font-weight: 600; }
.rs-why { color: var(--text-mute); }
.rd-score li { display: grid; grid-template-columns: 76px 54px 80px minmax(0, 1fr); align-items: center; gap: 2px 10px; padding: 4px 0; font-size: 12.5px; }
.sp-name { font-weight: 700; color: var(--text-dim); }
.sp-pts small { color: var(--text-mute); font-weight: 400; }
.sp-bar { height: 6px; background: var(--line); border-radius: 3px; overflow: hidden; }
.sp-bar i { display: block; height: 100%; background: var(--text-dim); border-radius: 3px; }
.sp-why { color: var(--text-mute); line-height: 1.5; }
.rd-actions { margin-top: 10px; }

@media (max-width: 1280px) {
  .rd-grid { grid-template-columns: minmax(0, 1fr); }
  .rd-sups li { grid-template-columns: max-content max-content minmax(0, 1fr); }
  .rd-sups .rs-why { grid-column: 1 / -1; }
}
/* 手機和直放的平板（1000px 以下）：跟關卡動態一樣，表格改成每檔一塊 */
@media (max-width: 1000px) {
  .radar-row { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "name score" "stage stage" "chg ex" "story story" "sup supply"; }
  .radar-row .r-supply { grid-area: supply; text-align: right; }
  .radar-row .r-supply::before { content: "套牢比"; display: block; font-size: 12px; color: var(--text-mute); }
  .radar-row .t-name { grid-area: name; }
  .radar-row .r-score { grid-area: score; text-align: right; }
  .radar-row .t-stage { display: block; grid-area: stage; }
  .radar-row .r-chg { grid-area: chg; }
  .radar-row .r-ex { grid-area: ex; text-align: right; }
  .radar-row .r-chg::before { content: "今天漲跌"; display: block; font-size: 12px; color: var(--text-mute); }
  .radar-row .r-ex::before { content: "贏大盤（百分點）"; display: block; font-size: 12px; color: var(--text-mute); }
  .radar-row .r-sup { grid-area: sup; }
  .radar-row .r-sup::before { content: "支撐："; color: var(--text-mute); }
  .radar-row .t-stage .timing-chip { margin-top: 2px; }
  .radar-row .radar-note { display: inline-block; margin: 2px 8px 0 0; }
  .radar-detail { display: block; }
  .radar-detail td { display: block; padding: 4px 12px 14px; }
  .rd-two { grid-template-columns: minmax(0, 1fr); }
  .rd-score li { grid-template-columns: 76px 54px minmax(0, 1fr); }
  .rd-score .sp-why { grid-column: 1 / -1; }
}
@media (min-width: 701px) and (max-width: 1000px) {
  .radar-row { grid-template-areas: "name score" "stage stage" "chg ex" "story spark" "sup supply"; }
}
@media (max-width: 700px) {
  .radar-market { padding: 10px 12px 0; }
  .radar-controls { padding: 10px 12px 8px; }
  .rm-fact { flex: 1 1 calc(50% - 4px); }
  .rm-value { white-space: normal; }
}

/* 兩張表各自內部捲動，而不是把 30+450 列全部攤平——攤平的話整頁會長到
   一萬七千像素，兩張榜不可能同時在視線內，也就沒辦法「看族群、再看個股」。
   表頭 sticky 讓捲到一半還看得到欄位名稱。字級放寬之後每列變高，捲動區
   高度也跟著放寬一點（46/62vh → 50/66vh），不然可視列數掉太多。 */
.review-table-wrap { overflow: auto; }
.review-group-wrap { max-height: 50vh; }
.review-stock-wrap { max-height: 66vh; }
.review-table { width: 100%; border-collapse: collapse; }
/* table-layout:auto（預設）會依每一列實際內容重新計算欄寬，導致同一欄裡
   width:100% 的子元素（例如套牢比長條）在不同列可能算出不同的實際寬度，
   跟同一格裡其他元素（例如上面的數字列）對不齊，長條看起來「歪掉」。
   改用 fixed＋<colgroup> 明確定義欄寬百分比，欄寬固定不再依內容浮動，
   格內元素的 100% 才會是同一個數字，也不會因為篩選出不同內容而欄寬跳動。 */
.review-table-fixed { table-layout: fixed; }
.review-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 11px 14px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .3px;
  color: var(--text-mute);
  text-align: left;
  white-space: nowrap;
  background: var(--bg-raise);
  border-bottom: 1px solid var(--line);
}
.review-table thead th.num { text-align: right; }
.review-table thead th[data-sort] { cursor: pointer; user-select: none; }
.review-table thead th[data-sort]:hover { color: var(--accent-text); }
.review-table tbody td {
  padding: 14px;
  font-size: 15px;   /* Read tier body 級，對齊 DESIGN.md 的 Body（15px），不是 Label（11-12.5px） */
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}
.review-table tbody tr:hover { background: var(--bg-hover); }

/* Read tier 的四層文字階層（hero／body／secondary／tertiary），兩張表共用：
   - hero：這張表存在的理由本身（族群榜的 RS 20日；個股榜的套牢比＋距高）
   - body：預設的 td 字級（15px），股名、現價這類「有意義但不是本表主角」的數字
   - secondary：次要但仍獨立成欄的數字（跌幅倍數／反彈差／套牢比中位；關卡價位）
   - tertiary：純輔助／排序用途，摺進主要欄位當小字（均線、10日均額（美股 20 日）、族群名次、今日、檔數） */
.rt-hero      { font-size: 18px; font-weight: 800; font-family: var(--mono); color: var(--text); }
.rt-hero small { margin-left: 3px; font-size: 11px; font-weight: 600; color: var(--text-mute); font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", sans-serif; }
.rt-secondary { font-size: 13.5px; color: var(--text-dim); }
.rt-tertiary  { display: block; margin-top: 4px; font-size: 12px; color: var(--text-mute); }
.rt-tertiary + .rt-tertiary { margin-top: 2px; }

/* 族群列 */
.group-row { cursor: pointer; }
.stock-row { cursor: pointer; } /* 點列開支撐壓力圖，見 review.js openChartBySymbol */
.group-row.row-active { background: rgba(var(--accent-rgb), .10); }
.group-row.row-active td:first-child { box-shadow: inset 2px 0 0 var(--accent); }
.grp-rank { display: inline-block; width: 26px; color: var(--text-mute); font-size: 13px; font-family: var(--mono); }
.grp-name { font-weight: 700; font-size: 15px; }
.rs-flag { display: inline-flex; margin-left: 5px; vertical-align: -2px; color: var(--up-text); }
.rs-flag .icon { width: 14px; height: 14px; }
/* 族群四格（2026-10-21）：名字旁邊一顆小字標籤＋表格上面一排篩選。顏色跟「近 5 日」的方向走（紅＝這幾天贏大盤、
   綠＝這幾天輸大盤）；「續」是實底、「轉」是框線——轉的才是要多看一眼的那兩格 */
.group-controls { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; padding: 4px 16px 12px; }
.group-controls[hidden] { display: none; }
.group-sort-toggle .view-btn { font-size: 12.5px; }
.quad-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border: 1px solid transparent;
  border-radius: 5px;
  font-size: 11.5px;
  font-weight: 700;
  line-height: 16px;
  vertical-align: 2px;
  white-space: nowrap;
}
.quad-steady_up { color: var(--up-text); background: var(--up-soft); }
.quad-turning_up { color: var(--up-text); border-color: var(--up-text); }
.quad-turning_down { color: var(--down-text); border-color: var(--down-text); }
.quad-steady_down { color: var(--down-text); background: var(--down-soft); }
.quad-chip { background: none; }
/* 量縮：提醒、不是方向，所以不用紅綠；虛線框跟四格的實線框分開 */
.vol-tag {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 5px;
  border: 1px dashed var(--text-mute);
  border-radius: 5px;
  font-size: 11px;
  font-weight: 600;
  line-height: 16px;
  color: var(--text-dim);
  vertical-align: 2px;
  white-space: nowrap;
}
.group-controls-right { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.group-controls-right .review-check[hidden] { display: none; }
.rt-mid { font-size: 15px; font-weight: 700; }
#group-table th[data-gsort] { cursor: pointer; user-select: none; white-space: nowrap; }
#group-table th[data-gsort]:hover { color: var(--accent-text); }
#group-table th[data-gsort]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* 上檔套牢比／距2年高：重用全站的「量級長條」（軌道＋填色），加大成 Read tier
   規格（8px，原本 6px），兩個數字（套牢比、距2年高）並排當這張表的 hero，
   長條在下面當視覺延伸——長條填色仍照套牢比語意（0%＝新高、100%＝完全套牢），
   距2年高不會被硬塞進同一把尺，只是視覺上跟套牢比綁在一起（見 ADR 0004）。
   刻意都不用紅綠——兩者都不是漲跌方向，套色會跟「紅＝漲」的硬性規則打架
   （見 DESIGN.md「The Three-Axis Color Rule」），大小資訊由數字本身跟長條
   長度承載，不由顏色承載。 */
/* 欄寬現在由 <colgroup>（review.html）的固定百分比決定，這裡不用再設
   min-width——兩者同時存在只會讓人搞不清楚實際欄寬到底是誰說了算。 */
.structure-nums { display: flex; align-items: baseline; gap: 14px; margin-bottom: 7px; }
.structure-bar {
  display: block;
  width: 100%;
  height: 8px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 999px;
  overflow: hidden;
}
.structure-bar-fill { display: block; height: 100%; background: var(--text-dim); border-radius: 999px; }

/* 個股列 */
.stk-name { font-weight: 700; font-size: 15px; }
.stk-sym { margin-left: 8px; font-size: 12.5px; color: var(--text-mute); }
/* 美股四大指數成分股的小標（2026-11-08）：比題材標籤更小、方角，只是註記不是按鈕 */
.idx-marks { display: inline-flex; gap: 3px; margin-left: 6px; vertical-align: 1px; }
.idx-mark {
  padding: 0 4px;
  font-size: 11px;
  line-height: 16px;
  color: var(--text-dim);
  border: 1px solid var(--line);
  border-radius: 3px;
}
/* 外觀借 .stock-rank-pick（族群名次看 20 日／近 5 日），兩組長得一樣 */
.stock-index-pick[hidden] { display: none; }
.stock-index-pick .idx-n { margin-left: 4px; font-size: 11px; opacity: .7; }
.stk-tag {
  margin-left: 8px;
  padding: 2px 8px;
  font-size: 12px;
  color: var(--text-dim);
  border: 1px solid var(--line);
  border-radius: 999px;
}
/* 領先族群的名次、手設關卡：重要但不能點，用字重和主文字色強調，不用品牌藍
   （品牌藍只給「點得下去」的東西，One Accent Rule，2026-10-06） */
.rank-lead { color: var(--text); font-weight: 700; }

.lv-badge {
  padding: 2px 8px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 999px;
}
.lv-manual { color: var(--text); font-weight: 700; border: 1px solid var(--text-dim); }
.lv-auto   { color: var(--text-mute); border: 1px solid var(--line); }
/* white-space: normal 是必要的，不是裝飾——這裡繼承了全站通用 tbody td 的
   white-space: nowrap（給密集的 Operate tier 表格寫的），.review-table
   tbody td 自己從沒重設過，害這一串手設關卡價位（含金量最高的資料）被擠出
   可視範圍、要另外橫向捲動才看得到。這裡已經是 display:block 自成一行，
   讓它換行才是原本的設計意圖。 */
.lv-nums   { display: block; margin-top: 5px; font-size: 13px; color: var(--text-dim); white-space: normal; }

/* 篩選列 */
.review-filters { gap: 10px; flex-wrap: wrap; }
.review-search {
  width: 170px;
  padding: 5px 9px;
  font-size: 12.5px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.review-search:focus { outline: 1px solid var(--accent); }
.review-check { margin-bottom: 0; font-size: 12.5px; white-space: nowrap; }
/* 個股結構榜的篩選列（2026-10-26）：搜尋＋「篩選」「排列」兩組，每組前面一個小標，組和組之間一道細線 */
.stock-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; padding: 10px 16px 12px; border-bottom: 1px solid var(--line); }
.stock-toolbar .review-search { flex: 0 1 220px; }
.stock-toolbar .tb-group { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; padding-left: 18px; border-left: 1px solid var(--line); }
.stock-toolbar .tb-label { font-size: 12px; font-weight: 700; color: var(--text-mute); }
.stock-toolbar .review-check { font-size: 13.5px; }
/* 平板、小筆電：兩組會折成兩行，第二行開頭那道分隔線就變成一條沒頭沒尾的線，拿掉 */
@media (min-width: 641px) and (max-width: 1180px) {
  .stock-toolbar .tb-group { padding-left: 0; border-left: none; }
}
@media (max-width: 640px) {
  .stock-toolbar { flex-direction: column; align-items: stretch; gap: 8px; padding: 10px 12px; }
  .stock-toolbar .review-search { flex: none; width: 100%; }
  .stock-toolbar .tb-group { padding-left: 0; border-left: none; gap: 8px 12px; }
  .stock-toolbar .tb-label { width: 100%; }
}
/* 族群輪動榜：大盤最低點就是今天（還沒反彈）時，反彈差整欄收起來 */
#group-table.no-rb .col-rb, #group-table.no-rb td[data-label="反彈差"] { display: none; }
.review-active-group { cursor: pointer; background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.review-active-group .chip-x { margin-left: 4px; font-weight: 700; }

/* 站長工具 */
.tools-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.tools-table td { padding: 6px 0; border-bottom: 1px solid var(--line); }
.tools-table td:last-child { text-align: right; font-family: var(--mono); }
.tools-actions { margin-top: 16px; }
.tools-run { margin: 12px 0 0; font-size: 12.5px; color: var(--accent-text); }

/* ---------------- 頁內分頁（強勢榜：誰強／關卡動態） ----------------
   分頁是「換成另一頁內容」，篩選（.view-toggle）是「同一頁換一批資料」，兩種東西不長成同一個樣子。
   2026-10-10 站長：「誰強跟何時會不會藏得太深，使用者難以發現並使用。」原本分頁也是一組 .view-toggle，
   夾在台股美股、基準指數兩組篩選中間，看起來像第三個篩選。現在分頁自己一列、在篩選上面。
   同一天站長看了第一版（只有字和一條細底線）說「可不可以讓他們再更清楚一點」——兩個分頁連著讀像一行字。
   第二版：每個分頁是一塊（小圖｜名字一行、白話一行），選中的那一塊底下是一盞燈（.pt-ink：一段粗的
   強調色，往上暈開一層很淡的底色），換分頁時燈滑過去；沒選的那一塊字和圖都退一階，指到會浮起一層底。
   小圖畫的就是裡面那件事，跟關卡動態四格的示意圖同一種畫法（虛線是關卡、實線是股價）。
   畫面上只有兩個，屬於 Moment tier。見 DESIGN.md「頁內分頁和篩選」。 */
.review-nav { display: flex; flex-direction: column; gap: 12px; }
.page-tabs {
  position: relative;
  display: flex;
  gap: 6px;
  border-bottom: 1px solid var(--line);
}
.page-tab {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 10px 20px 13px 12px;
  font-family: inherit;
  text-align: left;
  color: var(--text-dim);
  background: none;
  border: none;
  border-radius: 10px 10px 0 0;
  cursor: pointer;
  transition: color .16s ease, background-color .16s ease, transform .1s ease;
}
.page-tab:active { transform: scale(.985); }
.page-tab.active { color: var(--text); cursor: default; }
.page-tab.active:active { transform: none; }
/* 沒選的那一塊：指到浮起一層底，像一張可以翻過去的牌 */
@media (hover: hover) {
  .page-tab:not(.active):hover { color: var(--text); background: var(--bg-panel); }
}
/* 還量不到位置的那一瞬間（或程式沒跑起來）：選中的自己畫一段底線，不會沒有記號 */
.page-tab[hidden] { display: none; } /* 藏起來的分頁（急跌後強勢股，2026-11-08）：.page-tab 的 display:flex 會蓋過 hidden */
.page-tabs:not(.has-ink) .page-tab.active { box-shadow: inset 0 -3px 0 var(--accent); }

/* 那盞燈：位置和寬度由 review.js 的 placeTabInk 量了寫進來 */
.pt-ink {
  position: absolute;
  left: 0;
  top: 0;
  bottom: -1px;
  width: 0;
  pointer-events: none;
  opacity: 0;
  border-bottom: 3px solid var(--accent);
  border-radius: 10px 10px 0 0;
  background: linear-gradient(to top, var(--accent-soft), transparent 82%);
  transition: transform .38s cubic-bezier(.16, 1, .3, 1), width .38s cubic-bezier(.16, 1, .3, 1);
}
.page-tabs.has-ink .pt-ink { opacity: 1; }

.pt-icon { flex: none; width: 34px; height: 26px; overflow: visible; color: var(--text-mute); transition: color .16s ease; }
.page-tab:hover .pt-icon { color: var(--text-dim); }
.page-tab.active .pt-icon { color: var(--text); }
/* 誰強：由長到短排好的三條，第一名那條是強調色 */
.pt-icon-rank .rk { fill: currentColor; }
.pt-icon-rank .rk:nth-of-type(2) { opacity: .62; }
.pt-icon-rank .rk:nth-of-type(3) { opacity: .36; }
.page-tab.active .pt-icon-rank .rk:nth-of-type(1) { fill: var(--accent-text); }
/* 關卡動態：虛線是關卡，實線是股價走到線邊，圓點是現在（跟 .timing-sch 同一種畫法） */
.pt-icon-level .lv-line { stroke: currentColor; stroke-width: 1.5; stroke-dasharray: 4 3; opacity: .7; }
.pt-icon-level .lv-path { fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.pt-icon-level .lv-dot { fill: currentColor; }
.page-tab.active .pt-icon-level .lv-line { stroke: var(--accent-text); opacity: 1; }
/* 抗跌股雷達：淡的那條是大盤一路往下，實線是守在原地的股票，圓點是現在 */
.pt-icon-radar .rd-mkt { fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round; opacity: .45; }
.pt-icon-radar .rd-stk { fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; }
.pt-icon-radar .rd-dot { fill: currentColor; }
.page-tab.active .pt-icon-radar .rd-stk { stroke: var(--accent-text); }
.page-tab.active .pt-icon-radar .rd-dot { fill: var(--accent-text); }

/* 急跌回測分頁的小圖：三根柱子，最右邊那根是強調色；選中、指到時柱子由下往上長一次 */
.pt-icon-study .st-axis { stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; opacity: .55; }
.pt-icon-study .st-bar { fill: currentColor; opacity: .55; transform-box: fill-box; transform-origin: 50% 100%; }
.pt-icon-study .st-top { opacity: 1; }
.page-tab.active .pt-icon-study .st-top, .page-tab:hover .pt-icon-study .st-top { fill: var(--accent); }
.page-tab.pt-play .pt-icon-study .st-bar { animation: st-grow .6s cubic-bezier(.2, .8, .2, 1) both; }
.page-tab.pt-play .pt-icon-study .st-bar:nth-of-type(2) { animation-delay: .08s; }
.page-tab.pt-play .pt-icon-study .st-bar:nth-of-type(3) { animation-delay: .16s; }
@keyframes st-grow { from { transform: scaleY(.15); } to { transform: scaleY(1); } }
.study-panel .rf-backtest:first-child { margin-top: 0; }
/* 急跌回測的股票表（2026-10-26，照抗跌股雷達的樣子）：表格沿用 .timing-table／.radar-table；下面回測的大標 */
.study-panel .radar-market { margin: 12px 16px 0; }
/* 急跌後強勢股：標籤上直接寫過去的成績（2026-10-26），跟檔數分開一點 */
.study-chip { gap: 6px; }
.study-chip .study-ev { padding-left: 7px; border-left: 1px solid var(--line); font-size: 12px; color: var(--text-mute); }
.study-chip .study-ev b { font-weight: 700; }
.study-lede { margin-bottom: 2px; font-size: 15px; color: var(--text); }
.study-lede-sub { margin: 0 16px 10px; font-size: 12.5px; color: var(--text-mute); }
@media (max-width: 640px) { .study-lede-sub { margin: 0 12px 10px; } }
.study-back-title { margin: 22px 0 0; padding: 18px 16px 4px; border-top: 1px solid var(--line); font-size: 13px; font-weight: 700; letter-spacing: .02em; color: var(--text-mute); }
.study-row .s-gap .r-line, .study-row .s-chg .r-line { display: block; font-size: 15px; font-weight: 700; }
.study-row .s-days { white-space: nowrap; }
.study-row .s-days .pb-dots { margin-right: 6px; }
.study-row .s-days .timing-sub { display: inline; }
@media (max-width: 1000px) {
  .study-row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
    grid-template-areas: "name name gap" "stage stage stage" "days chg supply";
    gap: 6px 12px;
  }
  .study-row .t-name { grid-area: name; }
  .study-row .t-stage { display: flex; flex-wrap: wrap; gap: 4px 6px; grid-area: stage; }
  .study-row .t-stage .timing-chip { margin: 0; }
  .study-row .s-gap { grid-area: gap; text-align: right; }
  .study-row .s-days { grid-area: days; }
  .study-row .s-chg { grid-area: chg; }
  .study-row .s-chg::before { content: "當天 "; font-size: 12px; color: var(--text-mute); }
  .study-row .s-chg .r-line { display: inline; }
  .study-row .r-supply { grid-area: supply; text-align: right; white-space: nowrap; }
  .study-row .r-supply::before { content: "套牢比 "; font-size: 12px; color: var(--text-mute); }
  /* 大漲過被打下來那張表沒有「符合的條件」「這一波符合」兩欄 */
  .study-pb-row { grid-template-areas: "name name gap" "chg chg supply"; }
}
/* 大漲過被打下來：從創高的表拆出來自己一段（2026-10-27 站長：放一起會誤會）。標題跟下面回測大標同一種樣子 */
.study-pb { margin-top: 22px; border-top: 1px solid var(--line); }
.study-pb-title {
  position: relative;
  margin: 6px 16px 0;
  padding: 14px 0 6px 12px;
  font-size: 18px;
  font-weight: 800;
  line-height: 1.4;
  color: var(--text);
}
.study-pb-title::before { content: ""; position: absolute; left: 0; top: calc(14px + .22em); bottom: calc(6px + .22em); width: 4px; border-radius: 2px; background: var(--accent); }
.study-pb-note { display: block; font-size: 13px; font-weight: 500; color: var(--text-mute); }
@media (max-width: 640px) { .study-pb-title { margin: 4px 12px 0; font-size: 16.5px; } }
/* 急跌回測版面（2026-10-26 站長「做好一點」）：每一段＝標題 → 一句話 →（名單）→ 重點數字幾格 → 收起來的條件和完整數字 */
.study-sec { padding-bottom: 6px; }
.study-sec + .study-sec { margin-top: 18px; }
.study-take { margin: 0 16px 12px; font-size: 15px; line-height: 1.7; color: var(--text-dim); }
.study-take b { color: var(--text); }
.study-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 10px; margin: 0 16px 12px; }
.study-tile { display: flex; flex-direction: column; gap: 2px; padding: 12px 14px; border: 1px solid var(--line); border-radius: 12px; background: var(--bg-raise); }
.study-tile.is-hl { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.study-tile .st-label { font-size: 13px; font-weight: 700; color: var(--text-dim); }
.study-tile .st-value { font-family: var(--mono); font-size: 24px; font-weight: 800; line-height: 1.25; }
.study-tile .st-sub { font-size: 12.5px; color: var(--text-mute); }
.study-tile .st-sub b { color: var(--text-dim); font-weight: 700; }
.study-more { margin: 0 16px 6px; border-top: 1px solid var(--line); }
.study-more > summary { padding: 12px 0; font-size: 13.5px; color: var(--accent-text); cursor: pointer; user-select: none; }
.study-more > summary:hover { color: var(--text); }
.study-more .rf-meaning { margin: 0 0 12px; }
.study-more .rf-wrap { margin: 0 0 12px; }
.study-sec .pb-list { margin-top: 0; margin-bottom: 12px; }
@media (max-width: 640px) {
  .study-take { margin: 0 12px 10px; font-size: 14.5px; }
  .study-tiles { margin: 0 12px 10px; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .study-tile { padding: 10px 12px; }
  .study-tile .st-value { font-size: 20px; }
  .study-more { margin: 0 12px 6px; }
}
/* 急跌回測：最近一次急跌符合條件的名單（2026-10-26），照族群一列一列，股票是可以點的小鈕 */
.pb-list { margin: 4px 16px 10px; padding: 14px 16px; border: 1px solid var(--line); border-radius: 12px; background: var(--bg-raise); }
.pb-list-title { margin: 0; font-size: 15px; font-weight: 800; color: var(--text); }
.pb-list-note { margin: 4px 0 10px; font-size: 12.5px; color: var(--text-mute); }
/* 每個族群一塊（族群名＋股票），桌機排成多欄，名單不會拉成一長條（2026-10-26 版面整理） */
.pb-groups { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 8px 22px; margin: 0; }
.pb-group { display: grid; grid-template-columns: 6.5em minmax(0, 1fr); gap: 10px; align-items: start; padding: 4px 0; border-bottom: 1px dashed var(--line); }
.pb-group dt { padding-top: 5px; font-size: 13px; font-weight: 700; color: var(--text-dim); }
.pb-group dd { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; }
.pb-stock { display: inline-flex; align-items: baseline; gap: 6px; padding: 4px 10px; font: inherit; font-size: 13.5px; color: var(--text);
  background: var(--bg-panel); border: 1px solid var(--line); border-radius: 8px; cursor: pointer; }
.pb-stock .mono { font-size: 12px; color: var(--text-mute); }
.pb-stock b.mono { font-weight: 700; color: var(--up-text); }
/* 創新高離 MA20 的名單：一個急跌日一列（日期＋急跌強度），整列寬，不分多欄 */
.pb-days { grid-template-columns: minmax(0, 1fr); }
.pb-days .pb-group { grid-template-columns: 7.5em minmax(0, 1fr); }
.pb-days dt { display: flex; flex-direction: column; gap: 1px; }
.pb-days dt small { font-size: 11.5px; font-weight: 600; color: var(--text-mute); }
.pb-none { padding-top: 5px; font-size: 13px; color: var(--text-mute); }
/* 哪幾天符合：一排小圓點（照日期），亮的是符合（2026-10-26 名單整理） */
.pb-dots { display: inline-flex; gap: 2px; margin-right: 2px; align-self: center; }
.pb-dots i { width: 5px; height: 5px; border-radius: 50%; background: var(--line); }
.pb-dots i.on { background: var(--accent-text); }
@media (max-width: 640px) {
  .pb-days .pb-group { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .pb-days dt { flex-direction: row; align-items: baseline; gap: 6px; padding-top: 4px; }
  /* 手機上股票代號先收起來（股名就認得出來），一行才放得下兩檔 */
  .pb-days .pb-stock span.mono { display: none; }
}
/* 創波段新高／創歷史新高切換（2026-10-26）：標題下面一列，右邊一句這一種的定義 */
.ma20-modes { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin: 0 16px 10px; }
.ma20-mode-say { margin: 0; flex: 1 1 320px; font-size: 13px; line-height: 1.6; color: var(--text-mute); }
.ma20-mode-say b { color: var(--text-dim); }
@media (max-width: 640px) { .ma20-modes { margin: 0 12px 10px; } }
.pb-stock:hover { border-color: var(--accent); }
.pb-stock:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (max-width: 640px) {
  .pb-list { margin: 4px 12px 10px; padding: 12px; }
  .pb-groups { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .pb-group { grid-template-columns: 5.2em minmax(0, 1fr); gap: 8px; }
  .pb-group dt { padding-top: 7px; font-size: 12.5px; }
}
@media (pointer: coarse) { .pb-stock { min-height: 34px; } }
.pt-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.pt-name { display: inline-flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 700; line-height: 1.4; white-space: nowrap; }
.pt-desc { font-size: 12.5px; line-height: 1.45; color: var(--text-mute); white-space: nowrap; transition: color .16s ease; }
.page-tab:hover .pt-desc, .page-tab.active .pt-desc { color: var(--text-dim); }
/* 幾檔：中性的小標籤，不上強調色（強調色只留給「現在選的是哪一個」那盞燈和小圖裡的重點） */
.pt-count {
  display: inline-block;
  padding: 1px 8px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.45;
  color: var(--text-dim);
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 999px;
}
.page-tab.active .pt-count { color: var(--text); }

/* ---- 小圖演一次：滑鼠指到、剛選中、名單剛算出來（.pt-play，review.js 加上去、演完拿掉）。
   誰強的三條由上到下一條一條長出來（排出名次）；關卡動態的走勢從左畫到線邊，圓點最後落下。
   關鍵影格沿用「有動靜的那一刻」那一段的 icon-draw／icon-pop／count-bump。 */
.page-tab.pt-play .pt-icon-rank .rk {
  transform-box: fill-box;
  transform-origin: 0 50%;
  animation: pt-bar-grow .46s cubic-bezier(.16, 1, .3, 1) both;
}
.page-tab.pt-play .pt-icon-rank .rk:nth-of-type(2) { animation-delay: 80ms; }
.page-tab.pt-play .pt-icon-rank .rk:nth-of-type(3) { animation-delay: 160ms; }
.page-tab.pt-play .pt-icon-level .lv-path {
  stroke-dasharray: 1 2;
  animation: icon-draw .56s cubic-bezier(.3, .7, .3, 1) both;
}
.page-tab.pt-play .pt-icon-level .lv-dot {
  transform-box: fill-box;
  transform-origin: center;
  animation: icon-pop .26s cubic-bezier(.34, 1.56, .64, 1) both;
  animation-delay: .42s;
}
@media (hover: hover) {
  .page-tab:hover .pt-icon-rank .rk {
    transform-box: fill-box;
    transform-origin: 0 50%;
    animation: pt-bar-grow .46s cubic-bezier(.16, 1, .3, 1) both;
  }
  .page-tab:hover .pt-icon-rank .rk:nth-of-type(2) { animation-delay: 80ms; }
  .page-tab:hover .pt-icon-rank .rk:nth-of-type(3) { animation-delay: 160ms; }
  .page-tab:hover .pt-icon-level .lv-path {
    stroke-dasharray: 1 2;
    animation: icon-draw .56s cubic-bezier(.3, .7, .3, 1) both;
  }
  .page-tab:hover .pt-icon-level .lv-dot {
    transform-box: fill-box;
    transform-origin: center;
    animation: icon-pop .26s cubic-bezier(.34, 1.56, .64, 1) both;
    animation-delay: .42s;
  }
}
/* 抗跌股雷達：大盤那條先往下畫，股票那條接著畫、圓點最後落下 */
.page-tab.pt-play .pt-icon-radar .rd-mkt, .page-tab.pt-play .pt-icon-radar .rd-stk {
  stroke-dasharray: 1 2;
  animation: icon-draw .5s cubic-bezier(.3, .7, .3, 1) both;
}
.page-tab.pt-play .pt-icon-radar .rd-stk { animation-delay: .12s; }
.page-tab.pt-play .pt-icon-radar .rd-dot {
  transform-box: fill-box;
  transform-origin: center;
  animation: icon-pop .26s cubic-bezier(.34, 1.56, .64, 1) both;
  animation-delay: .5s;
}
@media (hover: hover) {
  .page-tab:hover .pt-icon-radar .rd-mkt, .page-tab:hover .pt-icon-radar .rd-stk {
    stroke-dasharray: 1 2;
    animation: icon-draw .5s cubic-bezier(.3, .7, .3, 1) both;
  }
  .page-tab:hover .pt-icon-radar .rd-stk { animation-delay: .12s; }
  .page-tab:hover .pt-icon-radar .rd-dot {
    transform-box: fill-box;
    transform-origin: center;
    animation: icon-pop .26s cubic-bezier(.34, 1.56, .64, 1) both;
    animation-delay: .5s;
  }
}
@keyframes pt-bar-grow { from { transform: scaleX(0); } }
/* 檔數剛算出來、或盤中更新後變了：數字從下面跳上來一次 */
.pt-count.bump { animation: count-bump .36s cubic-bezier(.16, 1, .3, 1) both; }
/* 換分頁：新的那一頁淡進來（只有透明度，沒有位移——底下的表格是 Read tier） */
#tab-strength, #tab-timing, #tab-radar, #tab-yearly { animation: pt-panel-in .2s ease-out; }
@keyframes pt-panel-in { from { opacity: 0; } }
/* 很窄的手機（380px 以下）：兩個分頁各佔一半只剩一百六十幾 px，內距和小圖再收一點，那句白話才排得進
   一行（原本最後一個字自己掉到第二行）。手機的其他規則在下面 640px 那一段，這裡多寫一層選擇器蓋過它。 */
@media (max-width: 380px) {
  .page-tabs .page-tab { gap: 8px; padding: 8px 4px 11px 6px; }
  .page-tabs .pt-icon { width: 26px; height: 20px; }
}
/* 320px 的舊手機：連小圖都放不下（名字後面的檔數會掉到第二行，分頁變成一百 px 高）。
   這個寬度不放小圖，字照常排得進去；選中的那盞燈還在。 */
@media (max-width: 340px) {
  .page-tabs .pt-icon { display: none; }
  .page-tabs .page-tab { padding: 8px 6px 11px 8px; }
}
/* 2026-10-21 加了第三個分頁（抗跌股雷達）：手機上三塊各只剩 120px 上下，白話那一行會折成三行、
   分頁長到 140px 高。640px 以下白話收起來（每一頁裡面第一段就是同一件事），480px 以下小圖也收掉，
   名字才排得進一行；檔數放不下就自己換到名字下面。 */
/* 2026-10-26 加了第四個分頁（急跌回測）：平板、小筆電四塊排不下（820px 時最後一塊被切掉）。
   1280px 以下四塊平均分寬，白話那一行可以換行。 */
@media (min-width: 641px) and (max-width: 1280px) {
  .page-tabs .page-tab { flex: 1 1 0; min-width: 0; padding-right: 10px; }
  .page-tabs .pt-desc { white-space: normal; text-wrap: balance; }
}
@media (max-width: 640px) {
  .page-tabs .pt-desc { display: none; }
  .page-tabs .page-tab { min-height: 52px; }
}
@media (max-width: 480px) {
  .page-tabs .pt-icon { display: none; }
  .page-tabs .page-tab { justify-content: center; padding: 8px 4px 11px; }
  .page-tabs .pt-name { justify-content: center; text-align: center; }
}
/* 2026-11-08 加了第五個分頁（年年創新高）：手機上五塊平均分只剩 75px，名字折成兩三行；直放的平板（768px）
   白話那一行折成三行、「新」的標籤壓到隔壁的名字。1000px 以下改成整列可以左右滑：每一塊照自己的寬度、字不折行，
   選中的那一塊捲進畫面（review.js 的 revealActiveTab）。最右邊露出半塊，看得出後面還有。 */
@media (max-width: 1000px) {
  .page-tabs { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; }
  .page-tabs::-webkit-scrollbar { display: none; }
  .page-tabs .page-tab { flex: 0 0 auto; padding-left: 14px; padding-right: 14px; }
  .page-tabs .pt-name { flex-wrap: nowrap; white-space: nowrap; }
  .page-tabs .pt-desc { white-space: nowrap; }
}

/* 台股／美股、基準指數那一列——跟族群輪動榜的 panel-head 分開放，因為它要同時管兩個
   平行的 view-toggle（市場／基準指數），塞進 panel-head 裡會太擠。只管誰強那幾張表，
   關卡動態分頁整列收起來（review.js 的 setTab）。 */
.review-market-row { gap: 10px; margin-bottom: 2px; }

/* ---------------- 題材總表（/board）----------------
   Read tier（同 /review，見 docs/adr/0004）：這頁同時是會員影片的錄影畫面，
   字級以「錄影時看得清楚」為準。沿用 .review-main／.review-table 的骨架。 */
.board-video {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
  padding: 12px 16px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
}
/* 伺服器先決定這一條會不會出現（data-kind，見 app.py board_page），內容回來之前先撐住高度：
   原本整條等資料回來才冒出來，把資金輪動整塊往下推（2026-10-12 optimize，平板量到 0.59）。
   站長那一版多一個改連結的表單，720px 以下表單換到第二行。 */
.board-video[data-kind="admin"]:empty { min-height: 59px; }
.board-video[data-kind="link"]:empty { min-height: 48px; }
.board-video-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 15px;
  font-weight: 700;
  color: var(--accent-text);
  text-decoration: none;
}
.board-video-link:hover { text-decoration: underline; }
.board-video-link .icon { width: 20px; height: 20px; }
.board-video-link .mono { font-size: 12.5px; font-weight: 400; }
.board-video-form { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-left: auto; }
.board-video-form input {
  min-width: 200px;
  padding: 6px 10px;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 7px;
}
.board-video-form input:focus { outline: 1px solid var(--accent); }

/* 資金地圖（見 board.js 的 renderRotationMap、rotation.py 檔頭）：四象限＋四格清單。
   以前是本週流入／流出榜＋8 週逐週熱力圖，要自己在腦中把 8 格加起來才看得出誰在
   持續轉強；逐週數字收進下面的「逐週明細」。紅＝比平均強、綠＝比平均弱（紅漲綠跌）。 */
.rotation-lede { margin: 0; padding: 12px 16px 0; font-size: 14px; line-height: 1.65; color: var(--text-dim); }
.rotation-lede b { color: var(--text); }
.rotation-lede a { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
.rotation-body {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: 18px;
  padding: 14px 16px 16px;
}
.rotation-map { position: relative; min-width: 0; }
/* 資料回來之前先撐住（2026-10-12 optimize，題材頁平板量到版面位移 0.59）：地圖的 SVG 寬＝容器寬
   （320～760）、高＝寬 × 0.62、至少 300（board.js renderRotationMap），顯示時寬 100%，所以
   比例 1:0.62、最矮 300px。旁邊四格清單的長度看當天各格有幾個族群，下面用常見的高度估。 */
.rotation-map:empty { aspect-ratio: 1 / 0.62; min-height: 300px; }
.rotation-map svg { display: block; width: 100%; height: auto; }
.rotation-map .q-bg { fill: var(--bg-raise); }
.rotation-map .q-bg.q-leading { fill: color-mix(in srgb, var(--up) 7%, var(--bg-raise)); }
.rotation-map .q-bg.q-lagging { fill: color-mix(in srgb, var(--down) 6%, var(--bg-raise)); }
.rotation-map .q-axis { stroke: var(--text-mute); stroke-width: 1; }
.rotation-map .q-flow { fill: none; stroke: var(--text-mute); stroke-width: 1.2; stroke-dasharray: 3 4; opacity: .7; }
.rotation-map .q-name { font-size: 15px; font-weight: 700; fill: var(--text-dim); }
.rotation-map .q-sub, .rotation-map .q-axis-label { font-size: 11.5px; fill: var(--text-mute); }
.rot-g { cursor: pointer; outline: none; }
.rot-g.dim { opacity: .18; }
.rot-dot { stroke: var(--bg-panel); stroke-width: 1.5; }
/* 看不見的大圓：點本身只有 8～18px，手指點不準；點擊範圍撐到 28px（2026-10-06） */
.rot-hit { fill: transparent; }
.rot-dot.up { fill: var(--up); }
.rot-dot.down { fill: var(--down); }
/* 走過來的路線（兩週前 → 上週 → 本週），只在指到／選到時出現 */
.rot-trail-g { display: none; }
.rot-g.focus .rot-trail-g, .rot-g:hover .rot-trail-g { display: inline; }
/* 這週換了象限的族群：預設就畫出路線（2026-10-20 站長：「太不明顯」「有沒有更好的表達方式」，參考 RRG 的尾跡）。
   平常只畫細線、箭頭、兩個空心點，「2 週前／上週」的字等指到才出現，不然十幾條路線的字會疊成一團；
   指到或選到時照舊整條放大、字出現、重畫一次。 */
.rot-g.moved .rot-trail-g { display: inline; }
.rot-g.moved:not(.focus):not(:hover) .rot-trail { opacity: .28; stroke-width: 1.1; }
.rot-g.moved:not(.focus):not(:hover) .rot-arrow { opacity: .4; }
.rot-g.moved:not(.focus):not(:hover) .rot-past-label { display: none; }
.rot-g.moved:not(.focus):not(:hover) .rot-past { opacity: .35; }
.rot-trail { fill: none; stroke-width: 1.6; opacity: .8; }
.rot-trail.up { stroke: var(--up); }
.rot-trail.down { stroke: var(--down); }
.rot-arrow.up { fill: var(--up); }
.rot-arrow.down { fill: var(--down); }
.rot-past { fill: var(--bg-raise); stroke-width: 1.6; }
.rot-past.up { stroke: var(--up); }
.rot-past.down { stroke: var(--down); }
.rot-past-label {
  font-size: 11.5px;
  fill: var(--text-mute);
  paint-order: stroke;
  stroke: var(--bg-raise);
  stroke-width: 3px;
  stroke-linejoin: round;
  pointer-events: none;
}
.rot-label {
  display: none;
  font-size: 12.5px;
  font-weight: 600;
  fill: var(--text);
  paint-order: stroke;
  stroke: var(--bg-raise);
  stroke-width: 3px;
  stroke-linejoin: round;
  pointer-events: none;
}
.rot-g.labeled .rot-label, .rot-g.focus .rot-label, .rot-g:hover .rot-label { display: inline; }
/* 「顯示全部名字」：沒標到的族群，名字放在四個方向裡找得下的位置（board.js 的 extraLabel）；字比主要名字小一點、淡一點 */
.rot-label-extra {
  display: none;
  font-size: 11.5px;
  font-weight: 500;
  fill: var(--text-dim);
  paint-order: stroke;
  stroke: var(--bg-raise);
  stroke-width: 3px;
  stroke-linejoin: round;
  pointer-events: none;
}
.rotation-map.show-all-names .rot-label-extra { display: inline; }
.rotation-map.show-all-names .rot-g.focus .rot-label-extra, .rotation-map.show-all-names .rot-g:hover .rot-label-extra { display: none; } /* 指到時用主要名字那個，不重複 */
.rot-legend { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; margin-top: 6px; font-size: 12px; color: var(--text-mute); }
.rot-legend-moved { display: inline-flex; align-items: center; gap: 6px; }
.rot-legend-moved svg { width: 24px; height: 10px; flex: none; }
.rot-legend-moved line { stroke: var(--text-mute); stroke-width: 1.6; }
.rot-legend-moved path { fill: var(--text-mute); }
.rot-allnames { padding: 3px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--bg-raise); color: var(--text-dim); font: inherit; cursor: pointer; }
.rot-allnames:hover { background: var(--bg-hover); color: var(--text); }
.rot-allnames:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.rot-g:focus-visible .rot-dot { stroke: var(--accent); stroke-width: 2.5; }
.rot-tip {
  position: absolute;
  z-index: 3;
  padding: 7px 10px;
  font-size: 12.5px;
  white-space: nowrap;
  pointer-events: none;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: var(--shadow-sm);
}
.rot-tip b { display: block; margin-bottom: 2px; font-size: 13.5px; }
/* 手機上點住一個點時，說明框裡多一顆「看這個族群的個股」（board.js 的 bind）：這時框要點得到 */
.rot-tip.tappable { pointer-events: auto; }
.rot-tip-go {
  display: block;
  width: 100%;
  min-height: 40px;
  margin-top: 7px;
  padding: 0 12px;
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--text);
  background: var(--bg-panel);
  border: 1px solid var(--accent);
  border-radius: 6px;
  cursor: pointer;
}

.rotation-quads { display: grid; grid-template-columns: 1fr 1fr; gap: 12px 14px; align-content: start; min-width: 0; }
.rot-quad { padding: 10px 12px; background: var(--bg-raise); border: 1px solid var(--line); border-radius: 10px; }
.rot-quad.q-improving, .rot-quad.q-leading { border-color: color-mix(in srgb, var(--up) 35%, var(--line)); }
.rot-quad h3 { display: flex; align-items: baseline; gap: 8px; margin: 0 0 2px; font-size: 14.5px; }
.rq-count { font-size: 12.5px; font-weight: 600; color: var(--text-mute); }
.rot-quad p { margin: 0 0 6px; font-size: 12.5px; color: var(--text-mute); }
.rot-quad ol { margin: 0; padding: 0; list-style: none; }
/* 一格太窄（平板橫放 1180 量到約 190px，題材名剩「AM汽…」三個字）就收掉每列的小走勢線，
   位置讓給名字——走勢方向左邊的地圖已經畫了，名字才是這一列要讓人讀到的東西（2026-10-12 adapt） */
.rot-quad { container-type: inline-size; }
@container (max-width: 250px) {
  .rot-quad ol li { grid-template-columns: minmax(0, 1fr) 58px; } /* 多一層 ol：要贏過後面的 .rot-quad li */
  .rot-quad li .rot-spark { display: none; }
}
.rot-quad li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 56px 58px;
  align-items: center;
  gap: 8px;
  padding: 4px 4px;
  font-size: 14px;
  border-radius: 4px;
  cursor: pointer;
}
.rot-quad li:hover, .rot-quad li.focus { background: var(--bg-hover); }
.rq-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rq-val { font-size: 13px; text-align: right; }
.rq-empty { color: var(--text-mute); cursor: default; }
.rq-more { margin-top: 4px; padding: 2px 4px; font: inherit; font-size: 12.5px; color: var(--accent-text); background: none; border: 0; cursor: pointer; }
.rot-spark { width: 56px; height: 16px; }
.rot-spark polyline { fill: none; stroke-width: 1.3; }
.rot-spark .up { stroke: var(--up); }
.rot-spark .down { stroke: var(--down); }

.rotation-detail { border-top: 1px solid var(--line); }
.rotation-detail summary { padding: 10px 16px; font-size: 12.5px; color: var(--accent-text); cursor: pointer; user-select: none; }
.rotation-detail summary:hover { color: var(--text); }
.rotation-wrap { overflow: auto; max-height: 60vh; }
.rotation-table { width: 100%; border-collapse: collapse; }
.rotation-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 9px 10px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .3px;
  color: var(--text-mute);
  text-align: left;
  white-space: nowrap;
  background: var(--bg-raise);
  border-bottom: 1px solid var(--line);
}
.rotation-table th.num { text-align: right; }
.rotation-table td { padding: 7px 10px; font-size: 14px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.rotation-table td.rot-cell { text-align: right; }
/* 點一列跳到下面的題材段落（board.js），跟右邊四格的清單一樣有指到的底色 */
.rotation-table tbody tr[data-name] { cursor: pointer; }
.rotation-table tbody tr[data-name]:hover td:first-child,
.rotation-table tbody tr[data-name]:focus-visible td:first-child { background: var(--bg-hover); }
.rotation-table tbody tr[data-name]:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.rot-name { font-weight: 600; }
.rot-members, .rot-members-head { margin-left: 8px; font-size: 12px; font-weight: 400; }

.board-filters { gap: 6px; }
.board-filters .chip.active { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }

/* 族群標題列＝分段色帶：比「本期有變化」的個股列（4% 淡底）深得多的底色，上方
   一條加粗分隔線，字級也比個股名（15px）大一階——三件事一起做，才不會跟個股列
   混在一起（只靠字重或只靠底色，窄螢幕只看得到第一欄時仍然分不出來）。底色用
   文字色混進面板色，亮、暗版都成立，不另外挑一個顏色（見 DESIGN.md Four-Axis）。 */
.board-table .board-group th {
  padding: 14px 14px 10px;
  font-size: 13px;
  font-weight: 400;
  text-align: left;
  color: var(--text-mute);
  background: color-mix(in srgb, var(--text) 10%, var(--bg-panel));
  border-top: 2px solid color-mix(in srgb, var(--text) 22%, var(--bg-panel));
  border-bottom: 1px solid var(--line);
}
.board-table tbody tr.board-group:first-child th { border-top: 0; }
.board-table tbody tr.board-group:hover { background: transparent; }
/* 從資金地圖點過來時，目標段落的標題閃一下（見 board.js 的 scrollToThemeSection） */
.board-table tr.board-group.flash th { animation: board-group-flash 1.6s ease-out; }
@keyframes board-group-flash {
  0%, 25% { background: color-mix(in srgb, var(--accent) 22%, var(--bg-panel)); }
  100% { background: color-mix(in srgb, var(--text) 10%, var(--bg-panel)); }
}
.board-group-name { margin-right: 10px; font-size: 18px; font-weight: 800; letter-spacing: 0.02em; color: var(--text); }
.board-group.is-official .board-group-name { color: var(--text-dim); }
.board-group-rs { margin-left: 12px; }
.board-group-basis { margin-left: 4px; font-size: 12.5px; }
.board-group-rs .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 700; }

.board-table { min-width: 860px; } /* 7 欄塞不進手機寬度，寧可橫向捲動也不要把數字擠成兩行 */
.board-row { cursor: pointer; }
/* 免費版被遮住的關卡格子（題材輪動頁、強勢榜共用）：鎖頭而不是「—」——「—」讀起來
   像「沒有資料」，鎖頭才讀得出「有，但要解鎖」。整列仍可點，會問要不要加入自選。 */
.lock-cell { display: inline-flex; color: var(--text-dim); opacity: .75; }
.lock-cell .icon { width: 14px; height: 14px; }
.board-row.has-change { background: color-mix(in srgb, var(--text) 4%, transparent); }
.board-row.has-change:hover { background: var(--bg-hover); }
.board-table tbody td { padding: 11px 14px; }
.board-todo { margin-top: 3px; font-size: 12px; color: var(--text-mute); }

.board-status {
  display: inline-block;
  padding: 2px 8px;
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--text-dim);
  border: 1px solid var(--line);
  border-radius: 999px;
}
.board-status.up { color: var(--up-text); background: var(--up-soft); border-color: transparent; }
.board-status.down { color: var(--down-text); background: var(--down-soft); border-color: transparent; }

.board-changes { display: flex; flex-wrap: wrap; gap: 4px 6px; }
.board-change {
  padding: 2px 8px;
  font-size: 13px;
  white-space: nowrap;
  border-radius: 6px;
  color: var(--text-dim);
  background: color-mix(in srgb, var(--text) 7%, transparent);
}
.board-change .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.board-change.up { color: var(--up-text); background: var(--up-soft); }
.board-change.down { color: var(--down-text); background: var(--down-soft); }
.board-change.warn { color: var(--warn); background: var(--warn-soft); }
.board-change.rebound { color: var(--rebound-text); background: var(--rebound-soft); }

@media (max-width: 1000px) {
  .rotation-body { grid-template-columns: minmax(0, 1fr); }
  .rotation-quads:empty { min-height: 556px; } /* 單欄時清單接在地圖下面，長出來會推下面整頁 */
}
@media (max-width: 720px) {
  .rotation-body { padding: 12px; }
  .rotation-quads { grid-template-columns: minmax(0, 1fr); }
  .rotation-quads:empty { min-height: 1144px; }
  .board-video-form { margin-left: 0; }
  .board-video[data-kind="admin"]:empty { min-height: 132px; }
}

/* 站長工具 — 美股清單 */
.tools-sep { border: none; border-top: 1px solid var(--line); margin: 18px 0 14px; }
.tools-subtitle { margin: 0 0 8px; font-size: 13.5px; color: var(--text); }
.us-bulk-form { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.us-bulk-textarea {
  width: 100%;
  padding: 8px 10px;
  font-size: 12.5px;
  font-family: inherit;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
  resize: vertical;
}
.us-bulk-textarea:focus, .us-bulk-tag-input:focus { outline: 1px solid var(--accent); }
.us-bulk-tag-input {
  width: 100%;
  padding: 7px 10px;
  font-size: 12.5px;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 6px;
}
.us-watchlist-list { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; max-height: 120px; overflow-y: auto; }
.us-watchlist-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 8px;
  font-size: 12px;
  font-family: var(--mono);
  color: var(--text-dim);
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 999px;
}
.us-watchlist-chip small { font-family: inherit; color: var(--text-mute); }
.us-watchlist-chip .chip-x {
  font-family: inherit;
  font-weight: 700;
  color: var(--text-mute);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 0 0 2px;
  line-height: 1;
}
.us-watchlist-chip .chip-x:hover { color: var(--down-text); }

@media (max-width: 900px) {
  .review-main { padding: 12px; gap: 14px; }
  .review-table thead th { padding: 9px 10px; font-size: 12px; }
  .review-table tbody td { padding: 10px; font-size: 13.5px; }
  .rt-hero { font-size: 16px; }
}

/* =====================================================================
   手機版（≤640px）三件事，2026-09：
   1. 頂列不再固定在最上面、狀態縮成一列；導覽按鈕改成固定在底部的導覽列。
      原本狀態格＋按鈕占掉將近 250px 且一直黏在頂端，打開第一屏看不到任何一檔股票。
   2. 股票卡改成兩行的精簡列：一屏從 3 檔變成 8～10 檔。
   3. 監控清單、警示紀錄不再各自內捲動，跟整頁一起捲——手機上捲動區裡面又有
      捲動區，手指很容易卡在錯的那一層。警示紀錄先列最近 3 則、監控清單先畫 20 檔，
      各自底下一顆「再看／再顯示」（2026-10-06，見 app.js 的 alertMoreHtml、renderListMore）。
   桌機版完全不受影響：.top-nav 在桌機是 display:contents，等於不存在。
   ===================================================================== */
.top-nav { display: contents; }

@media (max-width: 640px) {
  /* ---- 1. 頂列 ---- */
  /* 頂列的 backdrop-filter 會讓裡面 position:fixed 的底部導覽列改成相對頂列定位
     （規格如此：filter／backdrop-filter／transform 都會建立 fixed 的包含區塊），
     手機上頂列已經不黏頂，不需要毛玻璃，拿掉才能讓導覽列真的貼在畫面底部 */
  .topbar { position: static; gap: 8px; padding: 10px 12px 8px; -webkit-backdrop-filter: none; backdrop-filter: none; }
  .brand { gap: 8px; }
  .brand-mark { width: 22px; height: 22px; }
  .brand-mark .icon { width: 21px; height: 21px; }
  .brand h1 { font-size: 15.5px; }
  /* 狀態四格縮成一行字（2026-10-24 /impeccable critique）：原本四個方框 54px 高，手機上只要掃一眼
     「收盤、監控幾檔、幾點更新、下次什麼時候」。「收盤／盤中」自己看得懂，不寫「市場」兩個字；
     倒數的油量條改成數字底下一條細線 */
  .status-strip { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 14px; width: 100%; }
  .stat, .stat-countdown { position: relative; flex-direction: row; align-items: baseline; gap: 5px; min-width: 0; min-height: 0; padding: 0; background: none; border: 0; box-shadow: none; }
  .stat:first-child .stat-label { display: none; }
  .stat-label { font-size: 12px; letter-spacing: 0; }
  .stat-value { font-size: 12.5px; white-space: nowrap; }
  .stat-progress { position: absolute; left: 0; right: 0; bottom: -4px; height: 2px; margin: 0; }

  .top-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 25;
    display: flex;
    justify-content: space-around;
    padding: 4px 4px calc(4px + env(safe-area-inset-bottom));
    background: var(--topbar-bg);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    border-top: 1px solid var(--line);
  }
  .top-nav .ghost-btn {
    flex: 1 1 0;
    min-width: 0;
    flex-direction: column;
    gap: 2px;
    min-height: 48px;
    padding: 4px 2px;
    font-size: 11px;
    white-space: nowrap;
    color: var(--text-dim);
    background: transparent;
    border: 0;
    box-shadow: none;
  }
  .top-nav .ghost-btn .icon { width: 19px; height: 19px; }
  .top-nav .ghost-btn:hover, .top-nav .ghost-btn:active { color: var(--text); background: var(--bg-hover); }
  body { padding-bottom: calc(60px + env(safe-area-inset-bottom)); } /* 讓頁尾不被底部導覽列蓋住 */

  /* ---- 3. 只有整頁一個捲動區 ---- */
  .stock-grid { max-height: none; overflow: visible; }
  .alert-list { max-height: none; overflow: visible; }
  /* 警示先列 3 則、其餘收起來，底下「再看 10 則／收起」（.alert-more，見 app.js 的 alertMoreHtml）。
     原本用 :nth-child 固定只露 3 則、沒有任何入口，免費版和訪客的近三日又是鎖的，等於只看得到 3 則 */
  .alert-item.mobile-fold { display: none; }
  .alert-more { display: flex; gap: 8px; padding: 4px 0 6px; }
  .alert-more .ghost-btn { flex: 1 1 auto; justify-content: center; min-height: 44px; }
  .alert-more [data-alert-more="less"] { flex: 0 0 auto; }
  /* 警示區壓成：標題一列、篩選＋近三日一列（可左右滑）、每則警示兩行 */
  .panel-alerts .panel-head .row { flex-wrap: nowrap; width: 100%; overflow-x: auto; scrollbar-width: none; }
  .panel-alerts .panel-head .row::-webkit-scrollbar { display: none; }
  .panel-alerts .filter-chips { flex-wrap: nowrap; }
  .panel-alerts .filter-chips .chip, #alert-summary-open { flex-shrink: 0; white-space: nowrap; }
  .alert-list { padding-top: 8px; padding-bottom: 4px; }
  .alert-item { padding: 8px 10px; column-gap: 9px; }
  .alert-icon { width: 30px; height: 30px; }
  .alert-icon .icon { width: 17px; height: 17px; }
  .alert-title { font-size: 14px; }
  .alert-detail { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* 手機只有一行、超出用刪節號：整排回到一般的行內文字，分隔點跟著字走 */
  .alert-detail .alert-line { display: inline; margin-left: 0; }
  .alert-detail .alert-line > * { position: static; padding-left: 0; }
  .alert-detail .alert-seg::before { position: static; display: inline; }

  /* ---- 2. 精簡股票列（兩行）----
     第一行：股名＋題材｜代號、星星｜現價；第二行：壓／撐｜位置條 */
  .stock-grid { grid-template-columns: minmax(0, 1fr); gap: 11px; padding: 14px 10px 10px; } /* 間距留給「今天觸發」旗標（卡片頂緣往上凸 9px） */
  .stock-card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "head  price"
      "levels band"
      "foot  foot";
    align-items: center;
    column-gap: 12px;
    row-gap: 5px;
    padding: 9px 12px;
    border-radius: 10px;
  }
  .stock-card-head { grid-area: head; align-items: center; min-width: 0; }
  .stock-card-head > div:first-child { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
  .stock-card-name { flex-shrink: 0; max-width: 9em; margin: 0; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .stock-card-head .sym-industry { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .stock-card-head-right { gap: 4px; }
  .stock-card-price { grid-area: price; font-size: 20px; text-align: right; }
  .stock-card-levels { grid-area: levels; justify-content: flex-start; gap: 14px; font-size: 12px; }
  .stock-card-band { grid-area: band; width: 92px; height: 8px; }
  .stock-card-foot { grid-area: foot; }
  /* 狀態徽章（區間內／突破中…）在手機上省略：價格顏色與位置條已經表達同一件事；
     處置／注意這種交易所公告、抓價錯誤訊息照樣顯示 */
  .stock-card-foot .badge:not(.disposition, .exdiv) { display: none; }
  .stock-card-foot:not(:has(.stock-card-err, .disposition, .exdiv)) { display: none; }
}

/* =====================================================================
   三頁共用導覽＋手機版強勢榜、題材輪動（2026-10-06，見監控站評審
   .impeccable/critique/2026-10-05T12-48-55Z__templates.md）
   - 導覽：看盤、題材輪動、強勢榜三頁同一份 .top-nav。桌機不顯示「目前這一頁」那顆
     （頁面標題已經寫了）；手機的底部導覽把它亮起來。原本只有看盤畫面有底部導覽，
     另外兩頁只有左上角一顆「← 回看盤畫面」，拇指搆不到，也看不出自己在哪一頁。
   - 亮暗切換搬出底部導覽：手機上在頂列右上角。底部五格留給「去哪裡」。
   - 強勢榜、題材輪動的表格：手機上每一列改成兩、三行的小卡，數字前面帶小標。原本
     固定欄寬的表格在 364px 寬裡，現價欄只剩 44px，數字互相疊在一起；題材輪動 1012px
     的表只看得到股票、現價、漲跌三欄。
   ===================================================================== */
.top-nav .nav-here { display: none; }
.jump-market { display: none; }

@media (max-width: 640px) {
  .top-nav .nav-here {
    display: inline-flex;
    color: var(--accent-text);
    box-shadow: inset 0 2px 0 var(--accent);
  }
  .top-nav .nav-here:hover, .top-nav .nav-here:active { color: var(--accent-text); }

  /* 免費版的頂列原本設成 static（桌機上只讓免費列黏住），手機上也要 relative，亮暗切換才會
     定位在頂列的右上角，不是跑到最上面被免費列蓋住 */
  .topbar, body.is-free .topbar { position: relative; }
  .topbar .brand { padding-right: 96px; } /* 右上角留給亮暗切換 */
  #theme-toggle {
    position: absolute;
    top: 8px;
    right: 10px;
    min-height: 36px;
    padding: 4px 10px;
  }

  /* 看盤畫面：「大盤」捷徑、題材 chip 列黏在畫面上（免費版黏在免費列下面） */
  .jump-market { display: inline-flex; margin-left: auto; min-height: 36px; }
  .panel-table .industry-tabs {
    position: sticky;
    top: var(--free-bar-h, 0px);
    z-index: 6;
    background: var(--bg-panel);
  }
  #market { scroll-margin-top: calc(var(--free-bar-h, 0px) + 8px); }

  /* 強勢榜上方：分頁（誰強／關卡動態）兩個各佔一半，名字一行、那句白話在下面一行；
     台股美股、基準指數一列，字不折行（原本擠到「台/股」「族/群」一個字一行） */
  .page-tabs { gap: 0; }
  .page-tab { flex: 1 1 0; min-width: 0; gap: 9px; min-height: 56px; padding: 8px 8px 11px; }
  .pt-icon { width: 29px; height: 22px; }
  .pt-name { font-size: 15px; gap: 6px; flex-wrap: wrap; white-space: normal; }
  .pt-count { padding: 0 7px; font-size: 11.5px; }
  .pt-desc { font-size: 12px; white-space: normal; text-wrap: balance; }
  .review-market-row { flex-wrap: wrap; }
  .review-market-row .view-toggle { flex: 1 1 auto; }
  .review-market-row .view-btn,
  .panel-head .view-btn { flex: 1 1 0; min-height: 36px; padding: 6px 10px; white-space: nowrap; }

  /* 三張表共用：表格拆成一列一塊，數字前面的小標來自 data-label */
  .review-group-wrap .review-table, .review-group-wrap .review-table tbody,
  .review-stock-wrap .review-table, .review-stock-wrap .review-table tbody,
  .board-table, .board-table tbody { display: block; }
  .review-group-wrap colgroup, .review-stock-wrap colgroup, .board-table colgroup { display: none; }
  .review-group-wrap tbody td, .review-stock-wrap tbody td, .board-table tbody td {
    display: block;
    padding: 0;
    border: 0;
  }
  .review-group-wrap td[data-label]::before,
  .review-stock-wrap td[data-label]::before,
  .board-table td[data-label]::before {
    content: attr(data-label);
    display: block;
    margin-bottom: 1px;
    font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", "Segoe UI Variable",
                 "Segoe UI", "Noto Sans TC", "Microsoft JhengHei", sans-serif;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0;
    color: var(--text-mute);
  }
  .review-group-wrap tbody td.empty, .review-stock-wrap tbody td.empty, .board-table tbody td.empty { padding: 16px 12px; }

  /* 族群輪動榜：族群＋RS 一行，近 5 日／跌幅倍數／反彈差／套牢比中位一行（舊樣板沒有近 5 日，那一格空著） */
  .review-group-wrap thead { display: none; }
  .review-group-wrap .group-row {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-template-areas: "name name name rs" "rs5 resist rebound supply";
    gap: 6px 10px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--line);
  }
  .review-group-wrap .group-row td:nth-child(1) { grid-area: name; min-width: 0; }
  .review-group-wrap .group-row td:nth-child(2) { grid-area: rs; text-align: right; }
  .review-group-wrap .group-row td[data-label="近 5 日"] { grid-area: rs5; text-align: left; }
  .review-group-wrap .group-row td[data-label="跌幅倍數"] { grid-area: resist; text-align: left; }
  .review-group-wrap .group-row td[data-label="反彈差"] { grid-area: rebound; text-align: left; }
  .review-group-wrap .group-row td[data-label="套牢比中位"] { grid-area: supply; text-align: right; }
  .review-group-wrap .group-row .rt-mid { font-size: 13.5px; }
  .group-controls { padding: 4px 12px 10px; }

  /* 個股結構榜：表頭變成一排可以左右滑的排序鈕；每一列 股票｜現價｜漲跌，下面套牢比、關卡 */
  .review-stock-wrap thead {
    display: block;
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--bg-raise);
    border-bottom: 1px solid var(--line);
  }
  .review-stock-wrap thead tr {
    display: flex;
    gap: 6px;
    padding: 8px 10px;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .review-stock-wrap thead tr::-webkit-scrollbar { display: none; }
  .review-stock-wrap thead th {
    position: static;
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    min-height: 34px;
    padding: 0 12px;
    font-size: 12px;
    background: var(--bg);
    border: 1px solid var(--line);
    border-radius: 999px;
  }
  .review-stock-wrap thead th:not([data-sort]) { display: none; }
  .review-stock-wrap .stock-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "name price chg" "struct struct struct" "lv lv lv";
    gap: 6px 12px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--line);
  }
  .review-stock-wrap .stock-row td:nth-child(1) { grid-area: name; min-width: 0; }
  .review-stock-wrap .stock-row td:nth-child(2) { grid-area: price; align-self: start; }
  .review-stock-wrap .stock-row td:nth-child(3) { grid-area: chg; align-self: start; }
  .review-stock-wrap .stock-row td:nth-child(4) { grid-area: struct; }
  .review-stock-wrap .stock-row td:nth-child(5) { grid-area: lv; }
  /* 股名、代號、題材各自不斷開，放不下的換到下一行——原本整格不換行，320px 時「騰輝電子 6672.TW
     CCL/玻纖布」的題材標籤跑進現價那一欄、蓋住數字（2026-10-12 adapt）。下面那行小字自己占一整行。 */
  .review-stock-wrap .stock-row td.stk-cell { display: flex; flex-wrap: wrap; align-items: baseline; gap: 3px 8px; }
  .review-stock-wrap .stock-row td.stk-cell > .stk-sym,
  .review-stock-wrap .stock-row td.stk-cell > .stk-tag { margin-left: 0; }
  .review-stock-wrap .stock-row td.stk-cell > .idx-marks { margin-left: 0; }
  .review-stock-wrap .stock-row td.stk-cell > .rt-tertiary { flex-basis: 100%; }
  /* 關卡：小標、手設／自動、價位排在同一行（不然一列要多兩行） */
  .review-stock-wrap td.stk-levels::before { display: inline; margin: 0 6px 0 0; }
  .review-stock-wrap td.stk-levels .lv-nums { display: inline; margin: 0 0 0 6px; }

  /* 題材輪動：股票｜現價｜漲跌，撐｜壓｜狀態，本期變化（有才顯示） */
  .board-table { min-width: 0; }
  .board-table thead { display: none; }
  .board-table tr.board-group, .board-table tr.board-group th { display: block; }
  .board-table .board-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas: "name price chg" "sup res status" "changes changes changes";
    gap: 6px 14px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--line);
  }
  .board-table .board-row td:nth-child(1) { grid-area: name; min-width: 0; }
  .board-table .board-row td:nth-child(2) { grid-area: price; }
  .board-table .board-row td:nth-child(3) { grid-area: chg; }
  .board-table .board-row .board-sup { grid-area: sup; text-align: left; }
  .board-table .board-row .board-res { grid-area: res; text-align: left; }
  .board-table .board-row .board-status-cell { grid-area: status; text-align: right; }
  .board-table .board-row .board-changes-cell { grid-area: changes; }
  .board-table .board-row:not(:has(.board-change)) .board-changes-cell { display: none; }
  .board-table td.board-sup::before, .board-table td.board-res::before { display: inline; margin: 0 4px 0 0; }
  /* 「改線：新增 18.62、23.75…」這種長的本期變化，手機上要能折行，不然整張表又被撐出去 */
  .board-table .board-change { white-space: normal; }
}

/* 觸控螢幕：小按鈕的點擊區撐大，圖示和字的大小不變 */
@media (pointer: coarse) {
  .view-btn { min-height: 36px; }
  .panel-alerts .filter-chips .chip, #alert-summary-open { min-height: 36px; }
  /* 星星（加進我的持股）原本 26×26、緊貼代號和新聞鈕，誤觸就改到我的持股：
     點擊區往外撐到 40px，旁邊多留一點間距 */
  .stock-card-head-right { gap: 10px; }
  .my-watchlist-star { position: relative; }
  /* 2026-10-24 從 40px 撐到 44px（-9px＋26px），新聞鈕、新聞換頁鈕也撐到 44px；旁邊的間距 10px，撐出去的範圍不會互相重疊 */
  .my-watchlist-star::after { content: ""; position: absolute; inset: -9px; }
  .card-news-flag, .news-pager-btn { position: relative; }
  .card-news-flag::after, .news-pager-btn::after { content: ""; position: absolute; inset: -4px; }
  .owner-hold-btn { position: relative; }
  .owner-hold-btn::after { content: ""; position: absolute; inset: -7px; }
  .free-bar-link, .free-bar-alt, .free-bar-help { padding: 6px 0; }
}

/* 手機上的圖表彈窗標題列：三顆按鈕（管理／在 TradingView 開啟／關閉）原本帶字，
   擠到股票名稱只剩「方士昶…」、按鈕文字還折成好幾行。手機改成只留圖示的
   40px 方鈕，名稱拿到剩下的寬度。文字用 font-size:0 藏起來而不是拿掉，
   按鈕的無障礙名稱照舊是那幾個字；滑鼠停留提示見各按鈕的 title。 */
@media (max-width: 640px), (max-height: 520px) {
  /* 手機上的支撐壓力圖整個螢幕（2026-10-06）：原本是 60vh 的彈窗，四周還留著遮罩，
     左邊工具列加上右邊價格軸，K棒只剩一半寬。
     2026-10-10：手機橫放也算（寬度超過 640，所以原本拿到的是桌機那個置中的彈窗——
     標題列、上面兩行、提示加起來 220px，430px 高的畫面圖只剩 166px，工具列還被切掉）。
     判斷用高度：高度不到 520px 的就是橫放的手機，平板橫放有七八百。 */
  #chart-modal { padding: 0; }
  #chart-modal .modal.modal-wide {
    width: 100%;
    height: 100dvh;
    max-height: none;
    border: 0;
    border-radius: 0;
  }
  #chart-modal .chart-modal-body { flex: 1 1 auto; height: auto; min-height: 0; padding-bottom: env(safe-area-inset-bottom); }
  #chart-modal .modal-head { gap: 8px; padding: 8px 8px 8px 14px; }
  #chart-modal .modal-head h2 { flex: 1 1 auto; min-width: 0; }
  #chart-modal .modal-head .row { flex: 0 0 auto; flex-wrap: nowrap; gap: 4px; }
  #chart-modal .modal-head .ghost-btn {
    width: 40px;
    height: 40px;
    min-height: 40px;
    padding: 0;
    gap: 0;
    justify-content: center;
    font-size: 0;
  }
  #chart-modal .modal-head .ghost-btn .icon { width: 18px; height: 18px; }
  #chart-modal .chart-source-bar { padding: 8px 14px 0; }
  /* 手機上按鈕靠右，272px 的選單往左展開會超出彈窗、被彈窗的圓角裁掉；
     改成以整條標題列為基準，左右各留 8px 攤開 */
  #chart-modal .ask-ai { position: static; }
  #chart-modal .ask-ai-menu { top: calc(100% - 2px); left: 8px; right: 8px; width: auto; }
}

/* ---------------- 上一檔／下一檔（支撐壓力圖，見 levels-chart.js「上一檔／下一檔」） ----------------
   桌機、平板：在標題列，緊跟在股名後面——[↑ 上一檔] 3 / 14 [下一檔 ↓]　警示紀錄・突破。
   直放的手機：標題列放不下，搬到下面那一行提示的右邊，只留箭頭和數字。
   橫放的手機：留在標題列，按鈕跟旁邊幾顆一樣是 40px 的圖示鈕（上面那段手機規則會把字藏起來）。
   走到頭的那一顆變灰。數字是要對著看的（第幾檔／共幾檔），用等寬字。 */
.chart-seq { display: flex; align-items: center; gap: 6px; min-width: 0; margin: 0 auto 0 14px; }
.chart-seq[hidden] { display: none; }
.chart-seq-btn { flex: none; min-height: 32px; padding: 5px 10px; gap: 3px; font-size: 12.5px; }
.chart-seq-btn .icon { width: 14px; height: 14px; }
.chart-seq-btn:disabled { opacity: .4; cursor: default; }
.chart-seq-btn:disabled:hover { background: var(--bg-raise); }
.chart-seq-pos { flex: none; min-width: 3.2em; text-align: center; font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--text-dim); white-space: nowrap; }
.chart-seq-label { min-width: 0; margin-left: 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; color: var(--text-mute); }
@media (pointer: coarse) { .chart-seq-btn { min-height: 40px; padding-inline: 12px; } } /* 平板：手指按的，至少 40px 高 */
/* 給讀螢幕的人聽的那一句（第幾檔、共幾檔、哪一檔），畫面上不佔位置 */
.chart-seq-say { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
#chart-modal .modal-head h2 { flex: 0 1 auto; min-width: 0; }
/* 直放的手機：在提示那一行的右邊 */
.chart-source-bar > .chart-seq { margin: 0 0 0 auto; gap: 2px; flex: 0 0 auto; } /* 不縮：站長那一版的說明很長，原本把換檔按鈕擠到畫面外（390px 量到下一檔在 425～465px，2026-10-12 adapt） */
.chart-source-bar > .chart-seq .chart-seq-text, .chart-source-bar > .chart-seq .chart-seq-label { display: none; }
.chart-source-bar > .chart-seq .chart-seq-btn { width: 40px; height: 40px; min-height: 40px; padding: 0; justify-content: center; }
.chart-source-bar > .chart-seq .chart-seq-btn .icon { width: 18px; height: 18px; }
.chart-source-bar:has(> .chart-seq:not([hidden])) .hint { min-width: 0; }
.chart-source-bar:has(> .chart-seq:not([hidden])) { align-items: center; padding: 4px 8px 2px 14px; }
/* 標題列右邊那幾顆（問 AI、在 TradingView 開啟）不折行：多了換檔按鈕之後，窄一點的彈窗會把它們擠成兩行 */
#chart-modal .modal-head .row .ghost-btn { white-space: nowrap; }
/* 平板直放（彈窗不到 1000px 寬）：標題列放不下字，換檔只留箭頭和數字，清單名稱不寫 */
@media (max-width: 1000px) {
  #chart-modal .modal-head .chart-seq { margin-left: 8px; gap: 2px; }
  #chart-modal .modal-head .chart-seq-text, #chart-modal .modal-head .chart-seq-label { display: none; }
  #chart-modal .modal-head .chart-seq-btn { width: 40px; padding: 0; justify-content: center; }
}
/* 手機、平板（手指點的裝置，或不到 900px 寬）：不放「在 TradingView 開啟」，位置讓給「分享」（2026-10-21 站長）。
   那一顆是跳出去別的網站、手機上也很少人用；分享是做成圖片丟 LINE／Discord。桌機照舊。 */
@media (pointer: coarse), (max-width: 900px) {
  #chart-modal #chart-open-external { display: none; }
}
/* 再窄一點（641～800px）：「在 TradingView 開啟」也只留圖示，股名才不會被擠成刪節號 */
@media (min-width: 641px) and (max-width: 800px) and (min-height: 521px) {
  #chart-modal #chart-open-external { width: 40px; height: 36px; padding: 0; gap: 0; justify-content: center; font-size: 0; }
  #chart-modal #chart-open-external .icon { width: 16px; height: 16px; } /* 圖示的大小是跟著字級的（1em），字級歸零要自己給 */
}
/* 橫放的手機：標題列很擠，清單名稱不寫 */
@media (max-height: 520px) {
  #chart-modal .modal-head .chart-seq { margin: 0 4px; gap: 2px; }
  #chart-modal .modal-head .chart-seq-label { display: none; }
  #chart-modal .modal-head .chart-seq-pos { min-width: 0; padding: 0 4px; font-size: 11.5px; }
}
/* 圖上面多出來的那一行「警示紀錄」：這一檔在清單上的每一則 */
.cgs-alerts { display: flex; flex-wrap: wrap; gap: 2px 14px; }
.cgs-alert b { font-weight: 700; color: var(--text); }
/* 關圖之後，清單上最後看的那一檔框一下（一次，淡出；不閃） */
.seq-here { outline: 2px solid var(--accent); outline-offset: -2px; animation: seq-here 1.8s ease-out both; }
@keyframes seq-here { 0%, 45% { outline-color: var(--accent); } 100% { outline-color: transparent; } }

/* 第一次看到上一檔／下一檔的說明小框（levels-chart.js 的 maybeShowSeqHint，2026-10-11）。
   跟功能導覽的 .tour-coach 同一套長相（底色、邊框、圓角、陰影、箭頭），只是指著支撐壓力圖上的「下一檔」。
   掛在 body 上（彈窗那一層有 transform，放在裡面 fixed 會跟著偏），z-index 比彈窗（50）高、比確認框（60）低。
   一次只會有一個，進場演一次 0.2s（跟 .tour-coach 一樣），不循環。不寫 prefers-reduced-motion 覆寫（ADR 0001）。 */
.seq-hint {
  position: fixed;
  z-index: 55;
  padding: 13px 15px 12px;
  background: var(--bg-raise);
  border: 1px solid var(--tour-line);
  border-radius: 12px;
  box-shadow: var(--shadow-md);
  color: var(--text);
  animation: tour-coach-in .2s cubic-bezier(.16, 1, .3, 1);
}
.seq-hint-arrow {
  position: absolute;
  top: -7px;
  width: 12px;
  height: 12px;
  margin-left: -6px;
  background: var(--bg-raise);
  border: 1px solid var(--tour-line);
  border-right: 0;
  border-bottom: 0;
  transform: rotate(45deg);
}
.seq-hint-head { display: flex; align-items: flex-start; gap: 10px; }
.seq-hint-head h3 { flex: 1 1 auto; min-width: 0; margin: 0; font-size: 14.5px; font-weight: 700; line-height: 1.45; text-wrap: balance; }
.seq-hint-close {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin: -4px -6px 0 0;
  padding: 0;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--text-mute);
  cursor: pointer;
}
.seq-hint-close:hover { background: var(--bg-hover); color: var(--text); }
.seq-hint-close .icon { width: 15px; height: 15px; }
.seq-hint p { margin: 7px 0 0; font-size: 13.5px; line-height: 1.65; color: var(--text-dim); text-wrap: pretty; }
.seq-hint .seq-hint-keys { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 12.5px; color: var(--text-mute); }
.seq-hint-keys > span { white-space: nowrap; } /* 一組按鍵一起換行，不會把「上一檔」拆成兩行 */
.seq-hint kbd {
  display: inline-block;
  min-width: 1.6em;
  padding: 0 5px;
  font: inherit;
  font-size: 12px;
  line-height: 1.6;
  text-align: center;
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 5px;
}
.seq-hint-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
.seq-hint-actions .ghost-btn, .seq-hint-actions .primary-btn { min-height: 36px; padding: 6px 14px; font-size: 13px; }
.seq-hint-actions .icon { width: 14px; height: 14px; }
@media (pointer: coarse) { .seq-hint-actions .ghost-btn, .seq-hint-actions .primary-btn { min-height: 40px; } }

/* ---------------- 問 AI 漲因（圖表彈窗標題列，見 levels-chart.js、CONTEXT.md「漲因」） ----------------
   主鈕＋小箭頭黏成一顆分段按鈕：主鈕直接問上次選的 AI，小箭頭展開四家。選單浮在
   圖表上方，所以標題列要墊高一層，不然會被下面的圖表畫布蓋住。 */
#chart-modal .modal-head { position: relative; z-index: 8; }
/* ---- 支撐壓力圖：點股名搜尋個股（2026-10-16 站長：「越清楚越好」）----
   股名本身是按鈕：旁邊一個放大鏡一直都在（不是指到才出現——要讓人一眼知道點得下去），指到、按著有底色。
   搜尋框開在股名正下方：大輸入框（16px，iPhone 點進去不會放大頁面）、一行說明能搜多少檔／符合幾檔、
   結果一檔兩行（股名＋代號｜上市上櫃・族群），右邊收盤和漲跌幅（等寬數字、紅漲綠跌）。 */
#chart-modal .modal { position: relative; }
/* ---- 支撐壓力圖：分享圖片的小框（2026-10-16，只有站長）：縮圖＋分享／複製／下載 ---- */
.chart-share {
  position: absolute;
  z-index: 30;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  font-size: 13px;
  animation: cs-in .16s cubic-bezier(.16, 1, .3, 1) both;
}
.sh-head { display: flex; align-items: center; justify-content: space-between; font-weight: 700; color: var(--text); }
.sh-close { display: inline-flex; padding: 4px; border: none; border-radius: 6px; background: none; color: var(--text-dim); cursor: pointer; }
.sh-close:hover { background: var(--bg-hover); color: var(--text); }
.sh-close .icon { width: 16px; height: 16px; }
.sh-preview { min-height: 90px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; background: var(--bg); }
.sh-preview img { display: block; width: 100%; height: auto; }
.sh-note { margin: 0; padding: 16px; font-size: 12.5px; color: var(--text-dim); text-align: center; }
.sh-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.sh-actions:empty { display: none; }
.sh-btn {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 36px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: none;
  color: var(--text);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
.sh-btn:hover { background: var(--bg-hover); }
.sh-btn .icon { width: 15px; height: 15px; }
.sh-btn.sh-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink, #fff); }
.sh-btn.sh-primary:hover { filter: brightness(1.08); }
.sh-msg { margin: 0; font-size: 12px; color: var(--text-dim); }
.sh-msg:empty { display: none; }
@media (pointer: coarse) {
  .sh-btn { min-height: 44px; }
}

.chart-title-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: calc(100% + 8px); /* 左邊往外推了 8px（讓字跟原本的標題對齊），寬度上限要把它算回來，不然字會被切掉 */
  margin: -4px 0 -4px -8px;
  padding: 4px 8px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-align: left;
  cursor: pointer;
}
.chart-title-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chart-title-btn .icon { flex: none; width: 16px; height: 16px; color: var(--text-mute); transition: color .15s ease; }
.chart-title-btn:hover,
.chart-title-btn[aria-expanded="true"] { background: var(--bg-hover); border-color: var(--line); }
.chart-title-btn:hover .icon,
.chart-title-btn[aria-expanded="true"] .icon { color: var(--accent-text); }
.chart-title-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* 股名旁邊的「我的自選」星星（levels-chart.js 的 renderChartStar）：跟卡片上的星星同一個樣子。
   標題排成一行：股名太長時縮股名（後面打點點），星星永遠看得到 */
#chart-modal-title { display: flex; align-items: center; gap: 2px; }
#chart-modal-title .chart-title-btn { min-width: 0; }
#chart-modal-title .chart-star { flex: none; font-size: 18px; }
#chart-modal-title .chart-star[hidden] { display: none; }

.chart-search {
  position: absolute;
  z-index: 30; /* 圖上的工具列 6、選取切換鈕 7 */
  display: flex;
  flex-direction: column;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  font-size: 13px;
  overflow: hidden;
  animation: cs-in .16s cubic-bezier(.16, 1, .3, 1) both;
}
@keyframes cs-in { from { opacity: 0; transform: translateY(-4px); } }
.cs-field {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 10px 10px 0;
  padding: 0 6px 0 12px;
  border: 1.5px solid var(--accent);
  border-radius: 9px;
  background: var(--bg);
}
.cs-field > .icon { flex: none; width: 18px; height: 18px; color: var(--accent-text); }
.cs-input {
  flex: 1 1 auto;
  min-width: 0;
  height: 44px;
  padding: 0;
  border: none;
  outline: none;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 16px; /* 16px 以下 iPhone 點進去會自動放大頁面 */
  caret-color: var(--accent);
}
.chart-search .cs-input:focus,
.chart-search .cs-input:focus-visible { outline: none; box-shadow: none; border: none; } /* 外框那一圈藍就是焦點 */
.cs-input::placeholder { color: var(--text-mute); }
.cs-input::-webkit-search-cancel-button { display: none; }
.cs-close { flex: none; display: inline-flex; padding: 6px; border: none; border-radius: 6px; background: none; color: var(--text-dim); cursor: pointer; }
.cs-close:hover { background: var(--bg-hover); color: var(--text); }
.cs-close .icon { width: 16px; height: 16px; }
.cs-scope { margin: 0; padding: 7px 14px 6px; font-size: 12px; color: var(--text-dim); }
.cs-scope:empty { display: none; }
.cs-list {
  flex: 1 1 auto;
  min-height: 0;
  margin: 0;
  padding: 0 6px 6px;
  list-style: none;
  overflow-y: auto;
  overscroll-behavior: contain;
  touch-action: pan-y;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.cs-group { margin: 4px 8px 4px; font-size: 11.5px; font-weight: 600; color: var(--text-mute); }
.cs-note { margin: 8px; padding: 10px 8px; font-size: 13px; line-height: 1.6; color: var(--text-dim); }
.cs-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 48px;
  padding: 6px 10px;
  border-radius: 8px;
  cursor: pointer;
}
.cs-item.is-active { background: var(--bg-hover); box-shadow: inset 0 0 0 1px var(--line); }
.cs-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cs-name { display: flex; align-items: baseline; gap: 7px; min-width: 0; font-size: 14.5px; font-weight: 700; color: var(--text); white-space: nowrap; }
.cs-code { font-size: 12.5px; font-weight: 500; color: var(--text-dim); }
.cs-current { padding: 0 6px; font-size: 11px; font-weight: 600; line-height: 18px; color: var(--accent-text); border: 1px solid currentColor; border-radius: 999px; }
.cs-meta { display: flex; align-items: center; gap: 4px; min-width: 0; font-size: 12px; color: var(--text-mute); white-space: nowrap; }
.cs-n, .cs-g { min-width: 0; overflow: hidden; text-overflow: ellipsis; } /* 標出來的字和前後的字要在同一個框裡，不然 flex 的間距會把一個詞拆開 */
.cs-lock { display: inline-flex; margin-left: 4px; color: var(--text-mute); }
.cs-lock .icon { width: 13px; height: 13px; }
.cs-item.is-locked .cs-name { color: var(--text-dim); }
.cs-item mark { padding: 0 1px; border-radius: 3px; background: color-mix(in srgb, var(--accent) 22%, transparent); color: inherit; }
.cs-price { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 2px; font-family: var(--mono); font-variant-numeric: tabular-nums; }
.cs-last { font-size: 13.5px; font-weight: 700; color: var(--text); }
.cs-pct { font-size: 12px; color: var(--text-dim); }
.cs-pct.up { color: var(--up-text); }
.cs-pct.down { color: var(--down-text); }
/* 族群個股清單（支撐壓力圖標題列的「族群個股」，2026-10-21）：跟搜尋框同一種列 */
.chart-peers {
  position: absolute;
  z-index: 30;
  display: flex;
  flex-direction: column;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  font-size: 13px;
  overflow: hidden;
  animation: cs-in .16s cubic-bezier(.16, 1, .3, 1) both;
}
.cp-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 12px 12px 0 14px; }
.cp-title { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.cp-title b { font-size: 15px; font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cp-title span { font-size: 12.5px; color: var(--text-dim); white-space: nowrap; }
.cp-close { flex: none; display: inline-flex; padding: 6px; border: none; border-radius: 6px; background: none; color: var(--text-dim); cursor: pointer; }
.cp-close:hover { background: var(--bg-hover); color: var(--text); }
.cp-close .icon { width: 16px; height: 16px; }
.cp-sum { margin: 4px 14px 6px; font-size: 12.5px; line-height: 1.55; color: var(--text-dim); }
.cp-sum .up { color: var(--up-text); }
.cp-sum .down { color: var(--down-text); }
.cp-list { flex: 1 1 auto; min-height: 0; margin: 0; padding: 0 6px 6px; list-style: none; overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
.cp-item:hover, .cp-item:focus-visible { background: var(--bg-hover); outline: none; }
.cp-item:focus-visible { box-shadow: inset 0 0 0 1px var(--accent); }
.cp-item.is-current { background: var(--accent-soft); }
@media (pointer: coarse) { .cp-close { padding: 10px; } }
.cs-foot { display: none; gap: 14px; margin: 0; padding: 8px 14px; border-top: 1px solid var(--line); font-size: 11.5px; color: var(--text-mute); }
.cs-foot kbd {
  display: inline-block;
  min-width: 18px;
  margin-right: 3px;
  padding: 0 4px;
  font-family: inherit;
  font-size: 11px;
  line-height: 17px;
  text-align: center;
  color: var(--text-dim);
  border: 1px solid var(--line);
  border-radius: 4px;
}
@media (hover: hover) and (pointer: fine) {
  .cs-foot { display: flex; } /* 有鍵盤滑鼠的才寫鍵盤用法 */
}
@media (pointer: coarse) {
  .cs-item { min-height: 54px; }
}
/* 手機橫放：趨勢和族群那一行摘要搬進標題列（levels-chart.js 的 placeChartStrip），整個上面只剩一列。
   攤開的那一塊改成對著標題列排（摘要自己不定位），一樣從這一列下面攤開、左右撐滿。
   寫在這裡是因為手機版標題列的樣式在上面那一段，寫在更前面會被蓋回去。 */
@media (max-height: 520px) {
  #chart-modal .modal-head { padding-top: 3px; padding-bottom: 3px; }
  #chart-modal .modal-head h2 { flex: 0 1 auto; max-width: 32%; }
  #chart-modal .modal-head .chart-group-strip { position: static; flex: 1 1 0; min-width: 0; border-bottom: 0; }
  #chart-modal .modal-head .cgs-summary { min-height: 40px; padding: 0 4px 0 8px; gap: 6px 12px; overflow: hidden; }
  #chart-modal .modal-head .cgs-caret-text { display: none; }
  #chart-modal .modal-head .cgs-panel { font-weight: 400; letter-spacing: 0; }
}
/* 橫放但不夠寬（小手機 667px）：摘要只留趨勢和族群的狀態，族群名和名單那顆攤開才看 */
@media (max-height: 520px) and (max-width: 760px) {
  #chart-modal .modal-head .cgs-brief-stage, #chart-modal .modal-head .cgs-brief-name { display: none; }
}
.ask-ai { position: relative; display: inline-flex; }
.ask-ai[hidden] { display: none; }
/* 只有一顆按鈕，按了展開四家 AI 自己挑（2026-10-23，原本是主鈕＋小箭頭） */
.ask-ai-toggle[aria-expanded="true"] { background: var(--bg-hover); }
.ask-ai-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 20;
  width: 272px;
  padding: 6px;
  background: var(--bg-raise);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow-md);
}
.ask-ai-menu-head { padding: 6px 8px 4px; font-size: 11.5px; font-weight: 600; color: var(--text-mute); }
.ask-ai-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
  padding: 8px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--text);
  font: inherit;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .12s ease;
}
.ask-ai-item:hover, .ask-ai-item:focus-visible { background: var(--bg-hover); }
.ask-ai-item-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ask-ai-item-label { font-size: 13px; font-weight: 600; }
.ask-ai-item-note { font-size: 11.5px; color: var(--text-mute); }
.ask-ai-menu-foot {
  margin-top: 4px;
  padding: 8px 8px 4px;
  border-top: 1px solid var(--line);
  font-size: 11px;
  line-height: 1.55;
  color: var(--text-mute);
}

/* ---------------- 當日強勢股落點（強勢榜「誰強」分頁最上面） ----------------
   風格輪動：當日強勢股落在「位階 × 價格帶」哪一格（見 CONTEXT.md、style_rotation.py）。
   Read tier（docs/adr/0004）：收盤後坐下來看的內容，字級比 Operate tier 寬鬆。
   格子深淺＝檔數，用漲的紅色疊——格子裡全是當天大漲的股票，紅色在這裡就是「漲」的
   意思，不是裝飾。成交值占比的增減是「錢多了少了」，不是漲跌，一律中性字色＋箭頭。 */
.style-summary {
  margin: 0;
  padding: 14px 18px 4px;
  font-size: 15px;
  line-height: 1.7;
  color: var(--text);
}
.style-summary b { font-weight: 700; }
.style-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 18px 24px;
  padding: 12px 18px 16px;
  align-items: start;
}
.style-grid {
  display: grid;
  grid-template-columns: 92px repeat(4, minmax(0, 1fr));
  gap: 6px;
}
/* 頁首的資料日期、資金輪動的「資料至」：一開始是「—」，回來變成「資料日期 2026-10-08」（117px）、
   「資料至 2026-10-08」（106px），同一列放不下就換行、整個頁首長高（2026-10-12 optimize）。
   先留好寬度，換不換行第一次排版就決定了。 */
#review-date { display: inline-block; min-width: 118px; }
/* 大盤下殺區間那一條：台股一定會出現（review.html 一開始就沒有 hidden），內容回來之前先撐住它的高度——
   原本等資料回來才冒出來，平板上把當日強勢股落點整塊往下推 95px。高度照寬度量的（一行／兩行／三行）。 */
#drawdown-bar:empty { min-height: 44px; }
@media (max-width: 900px) { #drawdown-bar:empty { min-height: 73px; } }
@media (max-width: 520px) { #drawdown-bar:empty { min-height: 111px; } }
#rotation-asof { display: inline-block; min-width: 108px; text-align: right; }

/* 資料還沒回來時先撐住高度（2026-10-12 optimize：這一區在強勢榜最上面，從空的長到滿的那一下，
   底下整頁被推下去，平板量到版面位移 0.97、桌機 0.65）。格子三列四欄，各寬度都是 237px；
   趨勢圖的高度跟著寬度走（SVG 280:120，上面一行圖例 23px＋間距 6px）；總結一句話大多一行。 */
.style-grid:empty { min-height: 237px; }
.style-summary:empty { min-height: calc(15px * 1.7 + 18px); }
.style-trend:empty::before { content: ""; display: block; margin-top: 29px; aspect-ratio: 280 / 120; }
.sg-corner { min-height: 1px; }
.sg-col-head {
  font-size: 12.5px;
  color: var(--text-dim);
  text-align: center;
  padding-bottom: 2px;
}
.sg-row-head {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text);
}
.sg-row-head small { font-size: 11.5px; font-weight: 400; color: var(--text-mute); }
.sg-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 66px;
  padding: 8px 4px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: color-mix(in srgb, var(--up) calc(var(--heat) * 100%), var(--bg-raise));
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: border-color .15s ease, transform .15s ease, opacity .15s ease;
}
.sg-cell:hover:not(:disabled) { border-color: var(--text-mute); }
.sg-cell:active:not(:disabled) { transform: scale(.98); }
.sg-cell.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.sg-cell.empty { cursor: default; color: var(--text-mute); }
.sg-count { font-size: 22px; font-weight: 700; line-height: 1; }
.sg-share { font-size: 11.5px; color: var(--text-dim); }
.style-foot {
  margin: 10px 0 0;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--text-mute);
}
.style-trend {
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg-raise);
}
.style-trend-head {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  align-items: baseline;
  font-size: 12.5px;
  color: var(--text-dim);
  margin-bottom: 6px;
}
.st-legend { display: inline-flex; align-items: center; gap: 5px; color: var(--text); }
.st-key { display: inline-block; width: 14px; height: 0; border-top: 2px solid; }
.st-key-low { border-color: var(--text); }
.st-key-high { border-color: var(--text-mute); border-top-style: dashed; }
.style-trend-svg { width: 100%; height: auto; display: block; }
.st-grid { stroke: var(--line); stroke-width: 1; }
.st-axis { fill: var(--text-mute); font-size: 10px; font-family: var(--mono); }
.st-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.st-line.st-low { stroke: var(--text); }
.st-line.st-high { stroke: var(--text-mute); stroke-dasharray: 4 3; stroke-width: 1.6; }
.st-dot.st-low { fill: var(--text); }
.style-list {
  margin: 0 18px 16px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg-raise);
}
.style-list-head {
  display: flex;
  gap: 10px;
  align-items: baseline;
  font-weight: 700;
  font-size: 14px;
  margin-bottom: 8px;
}
.style-list-head .mono { font-weight: 400; color: var(--text-dim); font-size: 12.5px; }
.style-list ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
  gap: 0 22px;
}
/* 一檔一行：名稱／代號靠左，數字靠右對齊成欄——名稱不准換行（原本窄欄時會一字一行） */
.style-list li {
  display: grid;
  grid-template-columns: auto 1fr auto auto auto;
  gap: 10px;
  align-items: baseline;
  font-size: 13.5px;
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.style-list li .stk-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
.style-list li .stk-sym { color: var(--text-mute); font-size: 12px; }
.style-list li > .mono { text-align: right; }
.timing-ruler-locked { display: flex; align-items: center; gap: 8px; min-width: 0; }
.tr-lock-text { display: flex; flex-direction: column; gap: 1px; line-height: 1.3; }
.tr-lock-text b { font-size: 13px; font-weight: 600; color: var(--text); }
.tr-lock-text small { font-size: 11.5px; color: var(--text-mute); }

@media (max-width: 900px) {
  .style-body { grid-template-columns: 1fr; }
  .style-summary:empty { min-height: calc(15px * 1.7 * 2 + 18px); }
}
@media (max-width: 520px) {
  .style-summary { padding: 12px 14px 2px; font-size: 14px; }
  .style-body { padding: 10px 12px 14px; }
  .style-grid { grid-template-columns: 62px repeat(4, minmax(0, 1fr)); gap: 4px; }
  .sg-col-head { font-size: 11px; }
  .style-summary:empty { min-height: calc(14px * 1.7 * 3 + 14px); }
  .sg-row-head { font-size: 12.5px; }
  .sg-cell { min-height: 56px; padding: 6px 2px; border-radius: 8px; }
  .sg-count { font-size: 19px; }
  .sg-share { font-size: 11px; }
  .style-list { margin: 0 12px 14px; }
  .style-list ul { grid-template-columns: 1fr; }
  .style-list li { gap: 8px; font-size: 13px; }
}

/* ---------------- 管理面板「安全」分頁（站長操作紀錄、登出所有裝置，見 docs/adr/0015） ---------------- */
.security-actions {
  display: flex;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  margin: 10px 0 18px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg-raise);
}
.security-actions p { margin: 4px 0 0; }
.security-actions .danger-btn { flex-shrink: 0; }
.security-log-title { font-size: 14px; margin: 0 0 4px; }
/* 課程開賣名單（站長後台「安全」分頁）：解開的名單跟下面的操作紀錄之間留一段距離 */
#waitlist-admin-list { margin: 0 0 18px; }
#waitlist-admin-list .modal-actions { margin-top: 8px; }
.security-log-wrap { max-height: 320px; margin-top: 8px; }
.security-log { width: 100%; border-collapse: collapse; font-size: 13px; }
.security-log th, .security-log td { text-align: left; padding: 7px 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
.security-log th { color: var(--text-dim); font-weight: 600; font-size: 12px; }
.security-log .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.security-log .dim { color: var(--text-mute); }
.security-log tr.new-ip td { background: var(--bg-hover); } /* 不用琥珀：那是假突破專用色 */
.badge-new-ip {
  display: inline-block;
  margin-left: 4px;
  padding: 0 6px;
  border-radius: 999px;
  font-size: 11px;
  font-family: inherit;
  font-weight: 700;
  color: var(--text);
  border: 1px solid var(--text-mute);
}
@media (max-width: 520px) {
  .security-actions { flex-direction: column; align-items: stretch; }
}

/* 監控清單排序選單旁的一句說明（選到注意股／處置股時才出現） */
.sort-hint { align-self: center; flex: 1 1 240px; min-width: 0; font-size: 12.5px; line-height: 1.5; color: var(--text-mute); }

/* ==========================================================================
   有動靜的那一刻（2026-10-08，見 DESIGN.md「有動靜的那一刻」）
   畫面平常是安靜的。只有兩種時候東西會動：真的發生事（一則新警示進來），或你指過去
   （chip、族群、句子裡的詞）。動的方式是把那件事「演一次」，演完就停，沒有循環。
   全站不因 prefers-reduced-motion 關閉動畫（見 docs/adr/0001），這裡沒有例外。
   ========================================================================== */

/* ---- 會演的圖示：突破的長條長上去、線往上畫；跌破的線往下畫；假突破的貓歪一下頭、眼睛
   變成 X；破底翻的 W 一筆畫出來。會演的場合只有這幾個（同時最多幾個實例）：剛進來的新警示、
   滑鼠指到卡片時左邊浮上來的那幾則、警示類型 chip（指到或今日則數剛跳）、剛蓋上去的角旗。
   --d 是那一則自己的出場延遲（幻影預覽一則一則錯開），圖示跟著它走。 */
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon .bar {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: icon-bar-rise .3s cubic-bezier(.16, 1, .3, 1) both;
  animation-delay: var(--d, 0ms);
}
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon .bar:nth-of-type(2) { animation-delay: calc(var(--d, 0ms) + 50ms); }
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon .bar:nth-of-type(3) { animation-delay: calc(var(--d, 0ms) + 100ms); }
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon .ic-line {
  stroke-dasharray: 1 2;
  animation: icon-draw .38s cubic-bezier(.3, .7, .3, 1) both;
  animation-delay: calc(var(--d, 0ms) + 150ms);
}
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon .ic-head {
  stroke-dasharray: 1 2;
  animation: icon-draw .2s ease-out both;
  animation-delay: calc(var(--d, 0ms) + 460ms);
}
/* 破底翻沒有長條，W 從頭開始畫，畫久一點（四段轉折） */
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon-rebound .ic-line {
  animation-duration: .5s;
  animation-delay: var(--d, 0ms);
}
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon-rebound .ic-head { animation-delay: calc(var(--d, 0ms) + 440ms); }
/* 假突破：整隻貓歪一下頭，兩眼、嘴巴的 X 一個一個蹦出來（被騙了的臉）。只選 g 裡面的 polygon：
   「全部清掉」那隻圓眼睛的貓不是這個結構，不會跟著動。 */
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon-cat {
  transform-origin: 50% 90%;
  animation: icon-cat-tilt .44s cubic-bezier(.16, 1, .3, 1) both;
  animation-delay: var(--d, 0ms);
}
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon-cat g.cat-cutout polygon {
  transform-box: fill-box;
  transform-origin: center;
  animation: icon-pop .2s cubic-bezier(.16, 1, .3, 1) both;
  animation-delay: calc(var(--d, 0ms) + 180ms);
}
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon-cat g.cat-cutout:nth-of-type(2) polygon { animation-delay: calc(var(--d, 0ms) + 240ms); }
:is(.alert-item.fresh, .alert-item.phantom-in, .filter-chips .chip:hover, .filter-chips .chip.bump, .card-alert-flag.fresh, .row-alert-flag.fresh) .icon-cat g.cat-cutout:nth-of-type(3) polygon { animation-delay: calc(var(--d, 0ms) + 320ms); }
@keyframes icon-bar-rise { from { transform: scaleY(0); } }
@keyframes icon-draw { from { stroke-dashoffset: 1.15; } to { stroke-dashoffset: 0; } }
@keyframes icon-pop { from { transform: scale(0); } }
@keyframes icon-cat-tilt { from { transform: rotate(-14deg); } }

/* ---- 一則新警示的三處回聲（app.js 的 poll／renderAlertCounts）：
   類型 chip 的今日則數跳一下、那一檔的卡片蓋上角旗、它的題材 chip「今日 N」跟著跳。 */
.chip-count {
  display: inline-block;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-mute);
}
.chip:hover .chip-count { color: var(--text-dim); }
/* 多了則數，五顆 chip 在 1280～1440 寬的螢幕排不進一排。桌機讓「近三日」跟折下來的 chip 共用
   同一排（chip 列自己不再是一個盒子），標題列的高度跟加則數之前一樣，不會把警示清單往下擠。
   手機的 chip 列是自己左右滑的一排，不動。 */
@media (min-width: 641px) {
  .panel-alerts .panel-head .filter-chips { display: contents; }
  .panel-alerts .panel-head .row.wrap { gap: 8px 5px; }
}
.chip.active .chip-count { color: inherit; opacity: .8; }
.itab-hit { display: inline-block; }
.chip.bump .chip-count,
.itab-hit.bump { animation: count-bump .36s cubic-bezier(.16, 1, .3, 1) both; }
@keyframes count-bump { from { transform: translateY(70%); opacity: 0; } }
.card-alert-flag.fresh,
.row-alert-flag.fresh { animation: flag-stamp .26s cubic-bezier(.16, 1, .3, 1) both; }
@keyframes flag-stamp { from { transform: scale(1.6); opacity: 0; } }

/* ---- 搜尋框的鍵盤提示：有滑鼠的裝置，指到搜尋膠囊時右邊亮出「/」——在頁面任何地方按 /
   就能開始搜尋。開始打字就讓位給輸入的內容。 */
.search-kbd {
  display: none;
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  padding: 0 6px;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  line-height: 18px;
  color: var(--text-mute);
  border: 1px solid var(--line);
  border-radius: 4px;
  opacity: 0;
  pointer-events: none;
  transition: opacity .16s ease;
}
@media (hover: hover) and (pointer: fine) {
  .search-kbd { display: block; }
  .search-pill:hover .search-kbd { opacity: 1; }
}
.search-pill:focus-within .search-kbd,
.search-pill.has-value .search-kbd { opacity: 0; }

/* ---- 題材輪動：走過來的路線真的「走」一次。指到族群時，線從「2 週前」畫到本週，
   「上週」那一點和箭頭照順序出現——哪一端是起點，看線怎麼走就知道。 */
.rot-g.focus .rot-trail,
.rot-g:hover .rot-trail {
  stroke-dasharray: 1 2;
  animation: rot-trail-draw .46s cubic-bezier(.3, .7, .3, 1) both;
}
.rot-g.focus .rot-past-1,
.rot-g:hover .rot-past-1 { animation: rot-step-in .16s ease-out .16s both; }
.rot-g.focus .rot-arrow,
.rot-g:hover .rot-arrow { animation: rot-step-in .14s ease-out .36s both; }
@keyframes rot-trail-draw { from { stroke-dashoffset: 1.05; } to { stroke-dashoffset: 0; } }
@keyframes rot-step-in { from { opacity: 0; } }

/* 中間兩道虛線弧＝資金順時針繞的方向。第一次畫出來、或指到說明裡的四個詞時，虛線順著方向
   走一小段再停（兩個 keyframes 內容一樣，換名字是為了讓它重新播一次）。 */
.rotation-map svg.intro .q-flow { animation: q-flow-march 1.5s cubic-bezier(.16, 1, .3, 1) both; }
.rotation-map[data-qf] svg .q-flow { opacity: 1; animation: q-flow-march-again 1.1s cubic-bezier(.16, 1, .3, 1) both; }
@keyframes q-flow-march { from { stroke-dashoffset: 42; } to { stroke-dashoffset: 0; } }
@keyframes q-flow-march-again { from { stroke-dashoffset: 42; } to { stroke-dashoffset: 0; } }

/* 句子裡會回答的詞：題材輪動說明的「回溫／領漲／降溫／落後」、強勢榜一句話總結裡的數字。
   虛線底線＝指上去圖會回答；指到或固定住時變實線。 */
.q-word,
.sum-word {
  display: inline;
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: inherit;
  background: none;
  border: 0;
  border-radius: 4px;
  cursor: pointer;
  text-decoration: underline dotted var(--text-mute);
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
  transition: text-decoration-color .14s ease;
}
.q-word:hover, .q-word.on,
.sum-word:hover, .sum-word.on { text-decoration-style: solid; text-decoration-color: currentColor; }
.q-word[aria-pressed="true"],
.sum-word[aria-pressed="true"] { text-decoration-style: solid; text-decoration-color: currentColor; text-decoration-thickness: 2px; }

.rotation-map .q-bg, .rotation-map .q-name, .rot-g { transition: fill .16s ease, opacity .16s ease; }
.rotation-map[data-qf="improving"] .q-bg.q-improving,
.rotation-map[data-qf="cooling"] .q-bg.q-cooling { fill: var(--bg-hover); }
.rotation-map[data-qf="leading"] .q-bg.q-leading { fill: color-mix(in srgb, var(--up) 15%, var(--bg-hover)); }
.rotation-map[data-qf="lagging"] .q-bg.q-lagging { fill: color-mix(in srgb, var(--down) 13%, var(--bg-hover)); }
.rotation-map[data-qf="improving"] .q-name.q-improving,
.rotation-map[data-qf="leading"] .q-name.q-leading,
.rotation-map[data-qf="cooling"] .q-name.q-cooling,
.rotation-map[data-qf="lagging"] .q-name.q-lagging { fill: var(--text); }
.rotation-map[data-qf="improving"] .rot-g:not([data-quad="improving"]),
.rotation-map[data-qf="leading"] .rot-g:not([data-quad="leading"]),
.rotation-map[data-qf="cooling"] .rot-g:not([data-quad="cooling"]),
.rotation-map[data-qf="lagging"] .rot-g:not([data-quad="lagging"]) { opacity: .18; }
.rot-quad { transition: background-color .16s ease, border-color .16s ease; }
.rot-quad.focus { background: var(--bg-hover); border-color: var(--text-mute); }

/* 強勢榜：一句話總結裡的數字是下面哪幾格加起來的——對得上的維持原樣，其餘淡掉 */
.sg-row-head, .sg-col-head { transition: opacity .15s ease; }
.style-grid.has-hl .sg-cell:not(.hl) { opacity: .3; }
.style-grid.has-hl .sg-row-head:not(.hl),
.style-grid.has-hl .sg-col-head:not(.hl) { opacity: .4; }
.style-grid.has-hl .sg-cell.hl { border-color: var(--text-dim); }

/* =====================================================================
   功能導覽（static/tour.js，2026-10-09）——看盤、題材輪動、強勢榜三頁共用
   站長：「監控清單這邊也做像測驗網站一樣的導覽，告訴大家有什麼功能、怎麼用。」
   三樣東西：
   - .tour-ring   圈住這一步在講的那個東西，其餘壓暗。pointer-events: none——導覽開著，
                  底下的按鈕照樣可以按（不是另外一套教學模式）。
   - .tour-coach  說明的小框。桌機浮在目標旁邊、帶一個小箭頭；手機固定在畫面下面、底部導覽的
                  上面（小螢幕上浮動的框很容易蓋住它要指的東西）。
   - .tour-welcome 看盤頁第一次來的歡迎卡，用全站的彈窗骨架（.modal-backdrop＋.modal）。
   顏色只用既有的 token：框和進度條是強調色（「現在選著這個」正是強調色的職責），不借紅綠。
   字級從 DESIGN.md 那張表挑：12／12.5／13.5／14.5／16。數字（第幾步）用等寬。
   同一時間只有一個實例，所以進場可以演一次（0.2s 減速，沒有循環、沒有彈簧）。
   不寫 prefers-reduced-motion 覆寫（docs/adr/0001）。
   ===================================================================== */
:root { --tour-dim: rgba(0, 0, 0, .52); --tour-line: color-mix(in srgb, var(--text-mute) 46%, var(--line)); }
:root[data-theme="light"] { --tour-dim: rgba(28, 28, 28, .34); --tour-line: color-mix(in srgb, var(--text-mute) 38%, var(--line)); }

/* 入口：桌機是頂列的一顆普通按鈕；手機跟亮暗切換一起在右上角 */
.topbar-tools { display: contents; }
/* 平板直放（641～899px）的看盤頁：頂列那一排放不下四格狀態＋四顆換頁＋導覽＋換暗版，最後一兩顆會自己掉到
   第三排（768、820px 是「換暗版」一顆孤零零一排）。跟手機一樣把導覽和亮暗切換收到品牌那一排的右邊。
   題材輪動、強勢榜的頂列東西少，一排放得下，不用動（它們的 .topbar-tools 不在 .status-strip 裡）。
   641～720px 再把換頁按鈕的圖示拿掉，四顆才跟四格狀態排得進同一排。 */
@media (min-width: 641px) and (max-width: 899px) {
  /* 品牌自己佔一整排（右邊留給那兩顆）：不然 800px 上下品牌會跟狀態、換頁擠進同一排，那兩顆就疊在換頁按鈕上 */
  .topbar:has(.status-strip > .topbar-tools) .brand { flex: 1 0 100%; padding-right: 210px; }
  .status-strip > .topbar-tools { position: absolute; top: 12px; right: 20px; display: flex; gap: 8px; }
}
@media (min-width: 641px) and (max-width: 720px) {
  .status-strip > .top-nav > a .icon { display: none; }
}
/* 強勢榜在手機上：「資料日期」那一行要自己佔一排。原本螢幕比 400px 寬一點（430 的大手機、橫放的手機）時，
   它會跟品牌擠進同一排、被推到最右邊，正好壓在右上角的導覽和亮暗切換底下，整行看不到（2026-10-11 檢查）。 */
@media (max-width: 640px) {
  .topbar > .row:has(#review-date) { flex: 1 0 100%; }
}
#tour-open { position: relative; }
/* 還沒看過這一頁的導覽：按鈕右上角一個小點（靜止的，不閃） */
#tour-open.is-new::after {
  content: "";
  position: absolute;
  top: -3px;
  right: -3px;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--accent-text);
  box-shadow: 0 0 0 2px var(--bg);
}
@media (max-width: 640px) {
  .topbar-tools { position: absolute; top: 8px; right: 10px; display: flex; gap: 6px; }
  .topbar-tools #theme-toggle { position: static; }
  #tour-open { min-height: 36px; padding: 4px 10px; }
  .topbar .brand { padding-right: 164px; } /* 右上角現在是兩顆：導覽、亮暗切換 */
  .topbar:has(.account) .brand { padding-right: 210px; } /* 登入的人多一顆帳號鈕（只有圖示） */
  /* 右上角那幾顆是浮在頂列上的（36px 高），品牌那一排只有標題一行（23px）高：按鈕底部超出品牌那排、
     壓到下一排的狀態格——看盤頁「下次掃描」那格多一條進度條、往上凸 4px，跟導覽、換暗版疊了 3px
     （2026-10-23 站長截圖）。品牌那排至少跟按鈕一樣高，下一排就一定在按鈕下面。 */
  .topbar .brand { min-height: 38px; }
}
/* 很窄的手機（≤400px）又登入了：右上角三顆（導覽、亮暗、帳號）把「貪婪監控」擠成兩行（320px 實測）。
   導覽、亮暗切換只留圖示（跟圖表彈窗標題列同一招：字還在、只是不顯示，按鈕名稱照舊唸得出來）。 */
@media (max-width: 400px) {
  .topbar-tools:has(.account) > .ghost-btn {
    width: 36px;
    padding: 0;
    gap: 0;
    justify-content: center;
    font-size: 0;
  }
  .topbar-tools:has(.account) > .ghost-btn .icon { width: 17px; height: 17px; }
  .topbar:has(.account) .brand { padding-right: 132px; }
}

/* 頁面角落的帳號鈕（2026-10-18，templates/_account.html）：桌機露出名字，手機只剩圖示；
   點開是完整名字、用什麼登入、登出。名字最多露出 9 個字，完整的在選單裡。 */
.account { position: relative; }
.account > summary { list-style: none; }
.account > summary::-webkit-details-marker { display: none; }
.account[open] > summary { background: var(--bg-hover); }
.account-name { max-width: 9em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  width: max-content;
  min-width: 200px;
  max-width: min(300px, calc(100vw - 20px));
  padding: 12px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow: var(--shadow-md);
}
.account-who { margin: 0; font-size: 14px; font-weight: 700; overflow-wrap: anywhere; }
.account-via { margin: 2px 0 0; font-size: 12px; color: var(--text-mute); }
.account-menu form { margin: 10px 0 0; }
.account-menu .ghost-btn { width: 100%; justify-content: center; min-height: 36px; }
/* 看盤頁的頂列最擠（四格狀態＋換頁＋導覽＋換暗版），1280 以下帳號鈕只剩圖示，不然 1024 會擠到第二排 */
@media (max-width: 1279px) {
  .status-strip .account-name { display: none; }
}
@media (min-width: 641px) and (max-width: 899px) {
  .topbar:has(.status-strip > .topbar-tools .account) .brand { padding-right: 250px; }
}
/* 帳號鈕被擠到左半邊時（levels-chart.js 量了位置才加），選單改往右展開，不然會超出畫面左邊 */
.account-menu.open-right { right: auto; left: 0; }
/* 選單打開時頂列要在主內容上面：訪客、免費版的頂列是 position: static（讓位給上面的訪客列），z-index 不作用，
   選單會被強勢榜的分頁鈕（.page-tab 的 z-index: 1）蓋住、點不到登出（2026-10-18 實測）。只在打開時提上來。 */
.topbar:has(.account[open]) { z-index: 41; }
body.is-free .topbar:has(.account[open]) { position: relative; }
@media (max-width: 640px) {
  .account-name { display: none; }
  .account-btn { min-height: 36px; padding: 4px 10px; }
}

.tour-ring {
  position: fixed;
  z-index: 44;
  pointer-events: none;
  border: 2px solid var(--accent-text);
  border-radius: 12px;
  box-shadow: 0 0 0 9999px var(--tour-dim);
}
.tour-ring.tour-in { animation: tour-ring-in .24s cubic-bezier(.16, 1, .3, 1); }
@keyframes tour-ring-in { from { opacity: 0; transform: scale(1.03); } }

.tour-coach {
  position: fixed;
  z-index: 46;
  display: flex;
  flex-direction: column;
  padding: 14px 16px 0;
  background: var(--bg-raise);
  border: 1px solid var(--tour-line);
  border-radius: 12px;
  box-shadow: var(--shadow-md);
  color: var(--text);
  outline: none;
}
.tour-coach.tour-in { animation: tour-coach-in .2s cubic-bezier(.16, 1, .3, 1); }
@keyframes tour-coach-in { from { opacity: 0; transform: translateY(6px); } }
.tour-coach.is-sheet {
  left: 8px;
  right: 8px;
  max-height: min(56vh, 430px);
  border-radius: 14px;
}

.tour-arrow {
  position: absolute;
  width: 12px;
  height: 12px;
  background: var(--bg-raise);
  border: 1px solid var(--tour-line);
  transform: rotate(45deg);
}
.tour-arrow[data-side="top"]    { top: -7px;    margin-left: -6px; border-right: 0; border-bottom: 0; }
.tour-arrow[data-side="bottom"] { bottom: -7px; margin-left: -6px; border-left: 0;  border-top: 0; }
.tour-arrow[data-side="left"]   { left: -7px;   margin-top: -6px;  border-right: 0; border-top: 0; }
.tour-arrow[data-side="right"]  { right: -7px;  margin-top: -6px;  border-left: 0;  border-bottom: 0; }

.tour-head { display: flex; align-items: flex-start; gap: 10px; }
.tour-head h2 { flex: 1 1 auto; min-width: 0; margin: 0; font-size: 14.5px; font-weight: 700; line-height: 1.45; text-wrap: balance; }
.tour-close {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin: -4px -6px 0 0;
  padding: 0;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--text-mute);
  cursor: pointer;
  transition: background-color .16s ease, color .16s ease;
}
.tour-close:hover { background: var(--bg-hover); color: var(--text); }
.tour-close .icon { width: 15px; height: 15px; }

.tour-body { min-height: 0; margin-top: 8px; overflow-y: auto; overscroll-behavior: contain; }
.tour-body p { margin: 0 0 8px; font-size: 13.5px; line-height: 1.65; color: var(--text); text-wrap: pretty; }
.tour-body > :last-child { margin-bottom: 0; }
/* 「詞　說明」：四種警示、四格狀態這種一組一組的東西排成兩欄，比塞進一段字裡好找 */
.tour-terms { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 5px 12px; margin: 0 0 8px; font-size: 13.5px; line-height: 1.55; }
.tour-terms > div { display: contents; }
.tour-terms dt { font-weight: 700; color: var(--text); white-space: nowrap; }
.tour-terms dd { margin: 0; color: var(--text-dim); }
.tour-last { margin: 10px 0 0; padding-top: 9px; border-top: 1px solid var(--line); font-size: 12.5px; line-height: 1.6; color: var(--text-mute); }

.tour-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 12px; }
.tour-count { display: flex; align-items: baseline; min-width: 0; font-size: 12px; color: var(--text-mute); white-space: nowrap; }
.tour-count b { flex-shrink: 0; font-family: var(--mono); font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--text-dim); }
.tour-chapter { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* 有三顆按鈕的那一步（上一步／先不開／打開這一檔的圖；或一段的最後一步：上一步／先到這裡／下一段）
   位置不夠寫段名，只留第幾步 */
.tour-foot:has([data-tour="skip-cta"]:not([hidden])) .tour-chapter,
.tour-foot:has([data-tour="pause"]:not([hidden])) .tour-chapter { display: none; }
.tour-actions { display: flex; flex-shrink: 0; gap: 6px; }
.tour-actions .icon { width: 14px; height: 14px; }
/* 進度：跟倒數計時那條同一套「軌道＋填色」（.stat-progress），圓頭的細軌道。
   一段一節（2026-10-11）：節的寬度照那一段有幾步（tour.js 設 flex-grow），走過的段落整節填滿。
   只有一段的導覽（題材輪動、強勢榜）就是原本那一條。 */
.tour-progress { display: flex; gap: 3px; flex-shrink: 0; height: 3px; margin: 12px 0 14px; }
.tour-seg { flex: 1 1 0; min-width: 0; height: 100%; background: var(--bg); border-radius: 999px; overflow: hidden; }
.tour-seg > i { display: block; height: 100%; width: 0; background: var(--accent); border-radius: 999px; transition: width .24s cubic-bezier(.16, 1, .3, 1); }

/* 歡迎卡 */
.modal.tour-card { width: min(460px, 100%); outline: none; }
.tour-card-body { padding: 22px 22px 16px; overflow-y: auto; }
.tour-card-body h2 { margin: 0; font-size: 16px; font-weight: 700; line-height: 1.4; text-wrap: balance; }
.tour-card-lede { margin: 8px 0 0; font-size: 13.5px; line-height: 1.7; color: var(--text-dim); text-wrap: pretty; }
.tour-chapters { list-style: none; margin: 16px 0 0; padding: 0; border-top: 1px solid var(--line); }
.tour-chapters li { border-bottom: 1px solid var(--line); }
.tour-chapters button {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  grid-template-areas: "name steps go" "note note go";
  align-items: center;
  column-gap: 10px;
  row-gap: 1px;
  width: 100%;
  min-height: 56px;
  padding: 9px 6px 9px 4px;
  border: 0;
  background: transparent;
  color: var(--text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color .16s ease;
}
.tour-chapters button:hover { background: var(--bg-hover); }
.tour-chapters button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.tour-chapter-name { grid-area: name; font-size: 14.5px; font-weight: 700; }
.tour-chapter-note { grid-area: note; font-size: 12.5px; line-height: 1.5; color: var(--text-dim); }
.tour-chapter-steps { grid-area: steps; font-size: 12px; font-variant-numeric: tabular-nums; color: var(--text-mute); white-space: nowrap; }
/* 走完的那一段：「3 步」換成一個勾和「看過」。勾用強調色（跟進度條同一個意思），字不搶 */
.tour-chapter-steps.is-seen { display: inline-flex; align-items: center; gap: 4px; color: var(--text-dim); }
.tour-tick { flex-shrink: 0; width: 12px; height: 12px; fill: none; stroke: var(--accent); stroke-width: 2.6; stroke-linecap: round; stroke-linejoin: round; }
.tour-chapters .icon { grid-area: go; width: 16px; height: 16px; color: var(--text-mute); transition: transform .16s ease, color .16s ease; }
.tour-chapters button:hover .icon { transform: translateX(2px); color: var(--text); }
.tour-card-actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 18px; }
.tour-card-actions .ghost-btn, .tour-card-actions .primary-btn { min-height: 38px; padding: 7px 16px; font-size: 13px; }
.tour-card-actions .icon { width: 14px; height: 14px; }
.tour-card-foot { margin: 12px 0 0; font-size: 12px; color: var(--text-mute); }

/* 手指按的：按鈕至少 44px 高 */
@media (pointer: coarse) {
  .tour-actions .ghost-btn, .tour-actions .primary-btn { min-height: 44px; padding: 8px 14px; font-size: 13px; }
  .tour-close { width: 44px; height: 44px; margin: -12px -14px -8px 0; }
  .tour-card-actions .ghost-btn, .tour-card-actions .primary-btn { min-height: 44px; }
}

/* ==========================================================================
   載入時先佔位置（2026-10-10 稽核）
   訪客那一條、今日精選、題材那一排都是資料回來才畫的，原本一畫出來整頁往下跳兩三次——
   桌機實測位移分數（CLS）訪客 0.96、會員 0.26～0.34，超過 0.25 就算差。
   樣板一開始就寫好這個人是訪客／免費版／會員（<body data-viewer>，app.py 的 _viewer_kind），
   這裡照最後會有的高度先把位置留著；高度是各種寬度量出來的，改了這幾塊的版面要回來對。
   ========================================================================== */
/* 訪客／免費版頂端那一條（levels-chart.js 的 renderFreeBar 畫出來之前） */
body[data-viewer="guest"]:not(:has(> .free-bar))::before,
body[data-viewer="free"]:not(:has(> .free-bar))::before { content: ""; display: block; height: 67px; }
/* 題材那一排：內距 26＋一排 chip 33＋底線 1 */
#industry-tabs { min-height: 60px; }
/* 今日精選＋我的自選：資料還沒到之前先看得到空的框（樣板對訪客、免費版不加 hidden） */
body[data-viewer="guest"] #panel-picks,
body[data-viewer="free"] #panel-picks { min-height: 176px; }
@media (max-width: 1280px) {
  body[data-viewer="guest"] #panel-picks { min-height: 332px; }
  body[data-viewer="free"] #panel-picks { min-height: 351px; }
}
@media (max-width: 1199px) {
  body[data-viewer="guest"]:not(:has(> .free-bar))::before,
  body[data-viewer="free"]:not(:has(> .free-bar))::before { height: 99px; }
}
@media (max-width: 640px) {
  body[data-viewer="guest"]:not(:has(> .free-bar))::before,
  body[data-viewer="free"]:not(:has(> .free-bar))::before { height: 79px; }
  body[data-viewer="guest"] #panel-picks { min-height: 338px; }
  body[data-viewer="free"] #panel-picks { min-height: 370px; }
}
/* 兩欄的時候：第一批資料畫好之前，警示和清單兩個面板先撐到跟畫面差不多高（畫好之後本來就是這個高度），
   下面的國際行情一開始就在畫面外，不會先出現在中間、再被擠下去。app.js 畫完第一批就拿掉 is-booting。 */
@media (min-width: 901px) {
  body.is-booting .panel-alerts,
  body.is-booting .panel-table { min-height: calc(100vh - 72px); }
}
/* 題材輪動的資金地圖：畫出來之前照它的長寬比（寬 × 0.62）留高度 */
.rotation-map:empty { aspect-ratio: 100 / 62; }
@media (max-width: 640px) {
  /* 手機上地圖最矮 300px（board.js：高度取「寬 × 0.62」和 300 比較大的那一個） */
  .rotation-map:empty { aspect-ratio: auto; min-height: 300px; }
}

/* ==========================================================================
   （2026-10-10 精修）斷行和瀏覽器自己畫的部分
   ========================================================================== */
/* 一段話、一句說明的最後一行不要只剩一兩個字；標題兩行的時候兩行差不多長。
   舊一點的瀏覽器不認得就照原本的排，不影響版面。 */
p, li, .hint, .table-foot, .calendar-item, .news-item a { text-wrap: pretty; }
h1, h2, h3 { text-wrap: balance; }
/* 選取文字的底色用這一頁的強調色（原本是瀏覽器的預設藍） */
::selection { background: rgba(var(--accent-rgb), .26); }
/* 原生的勾選框、單選鈕、進度條用強調色，不用瀏覽器的預設藍 */
:root { accent-color: var(--accent); }

/* 新功能的「新」字（static/tour.js 最後一段）：頂列「強勢榜」、強勢榜的「抗跌股雷達」分頁後面。
   填滿品牌藍、白字，跟 .pt-count 同一個膠囊形狀、小一號；靜止不閃（看過一次就拿掉，不用吸引第二次）。 */
.news-pill {
  display: inline-block;
  margin-left: 6px;
  padding: 0 6px;
  font-size: 11px;
  font-weight: 700;
  line-height: 1.55;
  letter-spacing: 0;
  color: var(--accent-ink);
  background: var(--accent);
  border-radius: 999px;
  vertical-align: 1px;
}
/* 手機上頂列變成底下那排分頁（圖示在上、字在下）：「新」不排進字裡（會多出一行、跟旁邊不齊），
   改成貼在圖示右上角，像通知的小標 */
@media (max-width: 640px) {
  .top-nav a.has-news { position: relative; }
  .top-nav a .news-pill {
    position: absolute;
    top: 3px;
    left: calc(50% + 7px);
    margin: 0;
    padding: 0 4px;
    font-size: 10px;
    line-height: 1.5;
    box-shadow: 0 0 0 2px var(--bg);
  }
}

/* 手機：右邊的貪婪貓（static/app.js 的 setupSectionCat）。只在監控頁、只在手機寬度。
   貓頭跟著捲動在右邊上下走（位置＝捲到這一頁的哪裡），按一下彈出這一頁每一個區塊，點了滑過去。
   貓的紅是頻道 logo 的紅（跟測驗網站的 GreedyCat 同一個色號），不是漲跌語意。 */
.section-cat, .section-cat-menu { display: none; }
@media (max-width: 640px) {
  .section-cat {
    position: fixed;
    top: 0;
    right: 6px;
    z-index: 28;
    display: block;
    width: 46px;
    height: 46px;
    padding: 4px 3px 5px;
    background: transparent;
    border: 0;
    border-radius: 50%;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: transform .14s cubic-bezier(.16, 1, .3, 1);
    filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .45)) drop-shadow(0 0 1px rgba(0, 0, 0, .5));
  }
  .section-cat[hidden] { display: none; }
  .section-cat svg { display: block; width: 100%; height: 100%; overflow: visible; transition: transform .18s cubic-bezier(.16, 1, .3, 1); }
  /* 按下去縮一下、打開時歪頭（像在問「要去哪？」） */
  .section-cat:active svg { transform: scale(.88); }
  .section-cat.is-open svg { transform: rotate(-12deg) scale(1.06); }
  .section-cat:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 2px; }
  .section-cat .sc-red { fill: #e8504a; stroke: #e8504a; }
  .section-cat .sc-white { fill: #fff; stroke: #fff; }
  .section-cat .sc-line { fill: none; stroke: #fff; stroke-width: 44; stroke-linecap: round; }
  .section-cat .sc-glyph {
    fill: #fff; stroke: #fff; stroke-width: 5; stroke-linejoin: round; font-weight: 700;
    text-anchor: middle; dominant-baseline: central;
    font-family: "Microsoft JhengHei", "PingFang TC", "Noto Sans TC", sans-serif;
  }

  .section-cat-menu {
    position: fixed;
    right: 58px;
    z-index: 29;
    display: block;
    width: min(232px, calc(100vw - 76px));
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 6px;
    background: var(--bg-raise);
    border: 1px solid var(--line);
    border-radius: 12px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
    transform-origin: right center;
    animation: sc-menu-in .18s cubic-bezier(.16, 1, .3, 1) both;
  }
  .section-cat-menu[hidden] { display: none; }
  .sc-menu-title { margin: 2px 8px 4px; font-size: 11px; color: var(--text-dim); letter-spacing: .04em; }
  .section-cat-menu ul { margin: 0; padding: 0; list-style: none; }
  .section-cat-menu button {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 42px;
    padding: 8px 10px;
    font: inherit;
    font-size: 14px;
    text-align: left;
    color: var(--text);
    background: transparent;
    border: 0;
    border-radius: 8px;
    cursor: pointer;
  }
  .section-cat-menu button:active, .section-cat-menu button:hover { background: var(--bg-hover); }
  .section-cat-menu button:focus-visible { outline: 2px solid var(--accent-text); outline-offset: -2px; }
  /* 現在看到的這一塊：品牌藍的字＋左邊一條 */
  .section-cat-menu button[aria-current="true"] { color: var(--accent-text); font-weight: 600; box-shadow: inset 3px 0 0 var(--accent-text); }
}
@keyframes sc-menu-in {
  from { opacity: 0; transform: translateX(8px) scale(.96); }
  to { opacity: 1; transform: none; }
}

/* iPhone：字小於 16px 的輸入框、下拉選單，一點下去 Safari 就自動放大整頁，而且不會自己縮回來
   （2026-10-22 站長回報「不小心把畫面縮得太大」，多半就是點了搜尋框、排序選單）。觸控裝置上一律 16px，
   Safari 就不會自動放大；電腦不受影響。用 !important：各處輸入框各自寫了較小的字級（.search-pill input 等），
   這條是平台的規矩，要壓過它們。 */
@media (pointer: coarse) {
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="file"]),
  select,
  textarea { font-size: 16px !important; }
}

/* 抗跌股雷達：手機、直放平板（1000px 以下）收字（2026-10-22 站長：手機版抗跌雷達太多字）。
   一張卡片原本約 306px、一個畫面兩張半，第一檔要先滑過一整個畫面的說明。現在：
   - 說明只留一句＋「三種型態怎麼分」（review.js 的 radarCompactLede），按了才展開原本那段。
   - 「訊號：收盤確認」那格拿掉（標題旁邊已經寫「用 某天 收盤的資料算的」）。
   - 篩選鈕排一列、可以左右滑。
   - 卡片：股名／分數 → 型態＋上市櫃・族群 → 漲跌、贏大盤、套牢比一排 → 支撐一行 → 為什麼一句。
     「今天大盤…它…贏…」那兩句跟上面的數字重複，只留型態那一句（radarWhyLines）。
   電腦版的表格完全不動。 */
.radar-card-tag { display: none; }
@media (max-width: 1000px) {
  .radar-market .rm-fact-signal { display: none; }
  .rm-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin-top: 8px; }
  .rm-fact { padding: 5px 10px; }
  .rm-label { font-size: 11.5px; }
  .rm-value { font-size: 14px; }

  .radar-row {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto;
    grid-template-areas: "name name score" "stage stage stage" "chg ex supply";
    gap: 6px 12px;
  }
  .radar-row .t-name .timing-tag { display: none; }
  .radar-card-tag { display: inline; font-size: 12.5px; color: var(--text-mute); white-space: nowrap; }
  .radar-row .t-stage { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; }
  .radar-row .t-stage .timing-chip { margin: 0; }
  .radar-row .t-stage .radar-note { margin: 0; }
  .radar-row .r-chg::before { content: "漲跌"; }
  .radar-row .r-ex { text-align: left; }
  .radar-row .r-ex::before { content: "贏大盤"; }
  .radar-row .r-line { display: inline; font-size: 15px; }
  /* 小標跟數字排同一行（「漲跌 +7.88%」），每張卡片少一行 */
  .radar-row .r-chg::before, .radar-row .r-ex::before, .radar-row .r-supply::before { display: inline; margin-right: 5px; }
  .radar-row .r-supply { text-align: right; white-space: nowrap; }
  .radar-row .r-chg .timing-sub, .radar-row .r-ex .timing-sub { font-size: 12px; }
  .radar-row .r-sup { font-size: 13.5px; }
  .radar-row .r-sup::before { content: "支撐 "; }
  .radar-row .r-sup .timing-sub { display: inline; margin-left: 6px; font-size: 12.5px; }
  .radar-row .r-why .timing-line { font-size: 13px; line-height: 1.5; color: var(--text-dim); }
  .radar-row .r-why .timing-line:nth-child(n+2) { display: none; }
}
/* 直放平板：卡片跟手機一樣只留三行（支撐、為什麼、近 60 日小圖都收進展開的細節，2026-10-24 站長） */
@media (min-width: 701px) and (max-width: 1000px) {
  .radar-row { grid-template-areas: "name name score" "stage stage stage" "chg ex supply"; }
}
@media (max-width: 700px) {
  .radar-filters { flex: 1 1 100%; min-width: 0; flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin: 0 -12px; padding: 0 12px; }
  .radar-filters::-webkit-scrollbar { display: none; }
  .radar-filters .radar-chip { flex-shrink: 0; white-space: nowrap; }
}

/* 強勢榜三個分頁收字（2026-10-22 站長：字太多，能隱藏就隱藏、該顯示就顯示；手機、平板、筆電、桌機都一樣）。
   原則：看得到的是「這是什麼」一句、資料、「可以做什麼」一句；怎麼看、怎麼算收進開關。
   - 分頁最上面那段說明 → 一句話＋開關（review.js 的 compactLede）。
   - 表格下面原本攤開的整段說明 → 只留一句可以做什麼（.table-foot），其餘（.table-help）搬進「怎麼看這張表」
     （review.js 的 renderColumnHelp，跟欄位說明合成一個開關）。
   - 當日強勢股落點：看懂格子要的大字／小字／箭頭留著，「位階」是什麼收進開關（.howto）。
   字級、寬度照舊（說明文字桌機排滿面板，見 DESIGN.md「說明文字：桌機排滿，不收成一窄條」）。 */
.lede-short { margin: 0; padding: 12px 16px 0; font-size: 14px; line-height: 1.6; color: var(--text-dim); }
.lede-short b { color: var(--text); }
.lede-toggle {
  margin-left: 4px; padding: 0; font: inherit; font-size: 13.5px; color: var(--accent-text);
  background: none; border: 0; text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}
.lede-toggle:hover { color: var(--text); }
.lede-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
.panel > .lede-full { display: none; }
.panel.lede-open > .lede-full { display: block; padding-top: 6px; }
@media (max-width: 700px) { .lede-short { padding: 10px 12px 0; } }
@media (pointer: coarse) { .lede-toggle { padding: 6px 0; } }

.table-help { display: none; }
.col-help .table-help { display: block; margin: 0 0 10px; }
.col-help .table-help p { margin: 6px 0 0; font-size: 13px; line-height: 1.65; color: var(--text-mute); }
.col-help .table-help b { color: var(--text-dim); }
/* 一句話跟開關連在一起，中間不要再一條分隔線 */
.table-foot + .col-help { border-top: 0; }
.table-foot + .col-help summary { padding-top: 4px; }

.howto { margin-top: 8px; }
.howto summary { cursor: pointer; font-size: 12.5px; color: var(--accent-text); user-select: none; }
.howto summary:hover { color: var(--text); }
.howto p { margin: 6px 0 0; font-size: 13px; line-height: 1.65; color: var(--text-mute); }
.howto p b { color: var(--text-dim); }
@media (pointer: coarse) { .howto summary { padding-block: 8px; } }

/* 關卡動態的四格（2026-10-22 站長 /impeccable bolder）：這四格是這個分頁的入口——先選一種、再看名單——
   原本檔數是名字旁邊的小字（13px 灰），選中只多一圈細框，看起來像四張說明卡。
   現在：檔數是每一格最大的字（跟雷達分數同一級的 mono 粗體），0 檔的整格淡掉；
   選中的那格用篩選鈕同一種選取樣子（--accent-soft 底＋品牌藍框），一眼看得出「今天哪一種最多、我在看哪一種」。
   不加新的顏色、字型、元件，只把系統本來就有的放大。 */
.timing-stage {
  grid-template-columns: 76px minmax(0, 1fr) auto;
  grid-template-areas: "sch name num" "sch wait num" "sch scope num";
}
.timing-stage .timing-sch { grid-area: sch; grid-row: auto; }
.timing-stage .ts-name { grid-area: name; }
.timing-stage .ts-wait { grid-area: wait; }
.timing-stage .ts-scope { grid-area: scope; }
.ts-num { grid-area: num; display: flex; align-items: baseline; gap: 3px; align-self: center; padding-left: 6px; }
.ts-num .mono { font-size: 26px; font-weight: 800; line-height: 1; color: var(--text); font-variant-numeric: tabular-nums; }
.ts-num small { font-size: 12px; color: var(--text-mute); }
.timing-stage.is-empty .ts-num .mono, .timing-stage.is-empty .ts-name { color: var(--text-mute); }
.timing-stage.is-empty .timing-sch { opacity: .45; }
.timing-stage[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.timing-stage[aria-pressed="true"] .ts-name, .timing-stage[aria-pressed="true"] .ts-num .mono { color: var(--accent-text); }
.timing-stage:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 手機：一排兩格，圖在左上、檔數在右上，名字和說明排下面 */
@media (max-width: 700px) {
  .timing-stage { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "sch num" "name name" "wait wait"; }
  .timing-stage .timing-sch { justify-self: start; }
  .ts-num { align-self: start; padding-left: 0; }
  .ts-num .mono { font-size: 22px; }
}

/* 抗跌股雷達最上面那條大盤狀態（2026-10-22 bolder）：「大盤急跌中」是這個分頁存在的理由，原本是一顆小徽章，
   跟下面四格數字同一個份量。急跌中的時候（review.js 加 .is-alert）整條變成「跌」的語意色（綠，紅漲綠跌），
   強度（一般回檔／明顯下殺／極端下殺）放大。沒有急跌的時候照舊是灰的，不搶。 */
.radar-market.is-alert .rm-state {
  padding: 10px 14px;
  background: var(--down-soft);
  border: 1px solid var(--down-glow);
  border-radius: 10px;
}
.radar-market.is-alert .rm-badge { padding: 3px 12px; font-size: 13.5px; }
.radar-market.is-alert .rm-state b { font-size: 18px; color: var(--down-text); }
.radar-market.is-alert .rm-sub { color: var(--text); }
@media (max-width: 700px) {
  .radar-market.is-alert .rm-state { padding: 9px 11px; }
  .radar-market.is-alert .rm-state b { font-size: 16px; }
}

/* 題材輪動：地圖上方的一行結論（2026-10-22 bolder，board.js 的 renderRotationVerdict）。這一頁要回答
   「錢往哪裡跑」，原本要自己從地圖和右邊四格拼；現在一打開就寫：領漲哪幾個、剛轉強（回溫）哪幾個。
   標題級的字（跟面板標題同一級），「領漲」「剛轉強」用會亮的詞（.q-word），指上去地圖那一格亮。
   領漲的族群名用漲的紅（比平均強）；剛轉強（回溫）還比平均弱、只是開始加速，用一般的字色，不標紅。 */
.rotation-verdict { display: flex; flex-wrap: wrap; gap: 6px 22px; margin: 0; padding: 14px 16px 2px; font-size: 16px; line-height: 1.5; color: var(--text); }
.rv-part { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; }
.rv-part .q-word { font-size: 13px; font-weight: 700; color: var(--text-dim); }
.rv-part b { font-weight: 700; color: var(--text); }
.rv-part[data-quad="leading"] b { color: var(--up-text); }
.rv-more { font-size: 12.5px; color: var(--text-mute); }
.rv-none { font-size: 14px; color: var(--text-mute); }
@media (max-width: 700px) {
  .rotation-verdict { flex-direction: column; gap: 4px; padding: 12px 12px 0; font-size: 15px; }
}

/* 手機的字最小 12px（2026-10-24 /impeccable critique）。量過：手機監控頁兩成的字是 11～11.5px——新聞的來源和時間、
   股票代號、題材、熱力圖成交值、系統性風險日的點數、免責聲明、底部導覽的字。桌機照舊（資訊密度優先，見 DESIGN.md）。 */
@media (max-width: 640px) {
  .news-item .news-meta, .stock-card-code, .sym-industry, .heatmap-tile .hm-turnover, .crash-row .crash-pct,
  .site-disclaimer, .site-footer-link, .global-tile .g-pct, .alert-time, .alert-tag, .pick-code, .pick-flag,
  .badge, .breadth-stat .bs-label, .ic-tag, .top-nav .ghost-btn, .itab-hit, .card-alert-flag { font-size: 12px; }
}
/* 這份名單是什麼、數字在說什麼（review.js 的 rfMeaningHtml，2026-10-24） */
.rf-meaning { margin: 14px 0 0; padding: 12px 14px; font-size: 14px; line-height: 1.7; color: var(--text-dim); background: var(--bg-hover); border-radius: 10px; }
.rf-meaning p { margin: 0; }
.rf-meaning b { color: var(--text); }
.rf-meaning ul { display: grid; gap: 4px; margin: 8px 0 0; padding-left: 1.2em; }

/* ---------- 年年創新高（2026-11-08 站長） ----------
   一格一年：實心紅＝那年創歷史新高（紅＝漲）、空框＝沒有、虛線＝上市那一年（不算）、沒框＝還沒上市。
   表頭同一條格子印年份（兩位數），對得上下面每一列 */
.pt-icon-yearly .yr-step { fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; opacity: .7; }
.pt-icon-yearly .yr-dot { fill: currentColor; }
.page-tab.active .pt-icon-yearly .yr-top, .page-tab:hover .pt-icon-yearly .yr-top { fill: var(--up); }
.page-tab.pt-play .pt-icon-yearly .yr-step { stroke-dasharray: 1 2; animation: icon-draw .56s cubic-bezier(.3, .7, .3, 1) both; }
.page-tab.pt-play .pt-icon-yearly .yr-dot { transform-box: fill-box; transform-origin: center; animation: icon-pop .26s cubic-bezier(.34, 1.56, .64, 1) both; }
.page-tab.pt-play .pt-icon-yearly .yr-dot:nth-of-type(1) { animation-delay: .16s; }
.page-tab.pt-play .pt-icon-yearly .yr-dot:nth-of-type(2) { animation-delay: .3s; }
.page-tab.pt-play .pt-icon-yearly .yr-dot:nth-of-type(3) { animation-delay: .44s; }
@media (hover: hover) {
  .page-tab:hover .pt-icon-yearly .yr-step { stroke-dasharray: 1 2; animation: icon-draw .56s cubic-bezier(.3, .7, .3, 1) both; }
  .page-tab:hover .pt-icon-yearly .yr-dot { transform-box: fill-box; transform-origin: center; animation: icon-pop .26s cubic-bezier(.34, 1.56, .64, 1) both; }
  .page-tab:hover .pt-icon-yearly .yr-dot:nth-of-type(1) { animation-delay: .16s; }
  .page-tab:hover .pt-icon-yearly .yr-dot:nth-of-type(2) { animation-delay: .3s; }
  .page-tab:hover .pt-icon-yearly .yr-dot:nth-of-type(3) { animation-delay: .44s; }
}
.yh-lede { font-size: 15px; color: var(--text); }
.yh-strip { display: inline-grid; grid-auto-flow: column; grid-auto-columns: 22px; gap: 4px; vertical-align: middle; }
.yh-strip i { height: 16px; border-radius: 3px; border: 1.5px solid var(--text-mute); box-sizing: border-box; }
.yh-strip i.hit { background: var(--up); border-color: var(--up); }
.yh-strip i.miss { background: transparent; }
.yh-strip i.ipo { border-style: dashed; opacity: .6; }
.yh-strip i.pre { border-color: transparent; background: var(--line); opacity: .35; }
.yh-strip-head { margin-top: 4px; display: grid; width: max-content; }
.yh-strip-head i { height: auto; border: 0; font-style: normal; font-family: var(--mono); font-size: 11px; font-weight: 500; text-align: center; color: var(--text-mute); }
.yh-head { display: block; }
.yh-range { display: none; }
.yh-years-cell .timing-sub { margin-top: 5px; }
.yh-row .yh-off .r-line, .yh-row .yh-close .r-line { display: block; font-size: 15px; font-weight: 700; }
.yh-at-high { color: var(--up-text); }
.yh-ipo { display: inline-block; margin-left: 6px; padding: 1px 6px; border: 1px dashed var(--text-mute); border-radius: 4px; font-size: 12px; color: var(--text-dim); white-space: nowrap; }
@media (max-width: 1000px) {
  .yh-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "name close" "years off";
    gap: 8px 12px;
  }
  .yh-row .t-name { grid-area: name; }
  .yh-row .yh-years-cell { grid-area: years; }
  .yh-row .yh-off { grid-area: off; text-align: right; align-self: end; }
  .yh-row .yh-close { grid-area: close; text-align: right; }
  .yh-row .yh-off::before { content: "離最高價"; display: block; font-size: 12px; color: var(--text-mute); }
  /* 手機上沒有表頭：格子右邊寫「2019–2026」，知道從哪年排到哪年 */
  .yh-row .yh-strip { grid-auto-columns: 18px; gap: 3px; }
  .yh-row .yh-strip i { height: 14px; }
  .yh-row .yh-range { display: inline; margin-left: 6px; font-size: 11px; color: var(--text-mute); vertical-align: middle; }
}
