/* ==================================================
   Token 計算器 — 樣式表
   區塊註解採「欄位：」或「──」前綴，標示對應的頁面
   欄位或用途，方便手動修改時快速定位（非每個區塊都有）。
   ================================================== */

/* ── 全域：CSS 變數（深色主題） ──
   所有面板、文字、邊框、token 晶片、開關、提示框共用 */
:root {
  color-scheme: dark;
  --bg: #0d1117;
  --panel: #151b26;
  --panel2: #1c2432;
  --border: #2b3547;
  --text: #e7ecf4;
  --muted: #8b96a8;
  --accent: #d9a520;   /* 深色主交互色（與 `--warn` 警示金黃同值——交互色＝警示色系語意合併） */
  --accent-soft: #323025;   /* 主色 15% 混 `--panel` 的暖褐泛光底（hover/選中/badge 底） */
  --accent-text: #0d1117;   /* 主色底上文字：深色金黃底配近黑；淺色覆寫為白（見 `body.light`） */
  --good: #34d399;
  --bad: #f87171;
  --warn: #d9a520;
  --warn-strong: #d9a520;   /* 強化警示字色：深色與 `--warn`/`--accent` 同值；淺色換墨綠（見 `body.light`） */
  --chip-l: 30%;
  --chip-s: 62%;   /* 彩度：淺色調低→粉彩（與深色同值即深彩） */
  --chip-text: #ffffff;
  --tok-hover: 1.18;
  --tok-ring: rgba(255,255,255,.12);
  --special-stripe: rgba(217,165,32,.18);   /* 特殊 token 斜紋與 `.tok.special` 金框同值 */
  --tip-bg: #eef2f8;
  --tip-text: #16202b;
  --scrollbar-thumb: #3a4658;
  --scrollbar-thumb-hover: #4c5b75;
  --scrollbar-track: #131a26;
  --oversize-bg: #5b1d1d;
  --oversize-border: #7e2a2a;
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
  --paper-texture: none;   /* 背景紋理（深色無紋；淺色復古定義見 `body.light`） */
  --font-head: Georgia, "Iowan Old Style", "Palatino Linotype", "Book Antiqua", "Songti SC", "STSong", "SimSun", "Noto Serif TC", serif;   /* 襯線標題棧（拉丁＋中文宋體；僅淺色復古套用） */
}

/* ── 全域：CSS 變數（淺色主題，`body.light` 覆蓋深色值） ──
   淺色為「復古淺化」：泛黃紙底＋米白卡片＋棕褐邊框＋焦糖主色，
   語意色變數（`--good`/`--bad`/`--warn`/`--oversize-bg`）經對比 AA（≥4.5:1）驗算 */
body.light {
  color-scheme: light;
  --bg: #f2ecdb;
  --panel: #fdf9ec;
  --panel2: #f3ecd9;
  --border: #8a7a5c;
  --text: #3a3122;
  --muted: #6d6147;
  --accent: #8f4b2b;
  --accent-soft: #efe0c8;
  --accent-text: #ffffff;   /* 焦糖底上維持白字 */
  --good: #3f6f3a;
  --bad: #a53030;
  --warn: #8a5f18;
  --warn-strong: #3f6f3a;   /* 強化警示：紙底上金褐不顯眼，換墨綠（與 `--good` 同值、AA 已驗算） */
  /* 淺色 chip＝粉彩底＋深墨字（復古協調）：底 `--chip-s` 35%＋`--chip-l` 70% 對
     `--chip-text`（`#3a3122`）之對比 AA 最低 4.69（藍相）；調整任一值須重算驗證 */
  --chip-l: 70%;
  --chip-s: 35%;
  --chip-text: #3a3122;
  --tok-hover: 1.12;
  --tok-ring: rgba(58,49,34,.18);
  --special-stripe: rgba(143,75,43,.10);
  --tip-bg: #fdf9ec;
  --tip-text: #3a3122;
  --oversize-bg: #7d2727;
  --oversize-border: #a84444;
  --paper-texture:   /* 紙纖維橫紋＋邊緣舊化暈影（純 CSS，離線無外部資源） */
    repeating-linear-gradient(0deg, rgba(122,101,68,.045) 0 1px, transparent 1px 3px),
    radial-gradient(120% 80% at 50% 20%, transparent 55%, rgba(122,101,68,.10) 100%);
}

/* ── 復古淺色：裝飾規則（僅 `body.light` 套用）
   標題以襯線宋體凸顯印刷感；提示框反轉為「墨字米底＋棕框」印刷標籤（深色主題維持現代風） */
body.light header h1,
body.light .panel h2 { font-family: var(--font-head); }
body.light .tooltip {
  border: 1px solid var(--border);
  box-shadow: 0 3px 12px rgba(60,48,28,.35);
}

/* ── 全域：`box-sizing`（所有元素邊框/內距算入寬高） ── */
* { box-sizing: border-box; }

/* ── 全域：捲軸（WebKit：Safari/Chrome） ── */
/* 欄位：所有可捲動區域的捲軸寬度 */
::-webkit-scrollbar { width: 10px; height: 10px; }
/* 欄位：捲軸軌道（透明） */
::-webkit-scrollbar-track { background: transparent; }
/* 欄位：捲軸把手（主題差異收斂至 `--scrollbar-thumb*` 變數；值與原硬編碼相同） */
::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb); border-radius: 5px;
  border: 2px solid transparent; background-clip: padding-box;
}
/* 欄位：捲軸把手 hover */
::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); border: 2px solid transparent; background-clip: padding-box; }

/* ── 全域：捲軸（Firefox） ── */
/* 欄位：捲軸顏色/寬度（thumb/track 同變數化，淺色覆寫見下方 `:root:has(body.light)` 規則） */
:root { scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-track); scrollbar-width: thin; }
/* 欄位：Firefox 視圖捲軸專屬淺色覆寫——捲軸之色由根元素決定、`var()` 以根環境解析，
   `body.light` 的覆寫只及於後裔、不及於根，淺色捲軸值必須在此根層再覆寫；
   未來新增捲軸相關變數請跟隨本規則而非 `body.light`（WebKit 捲軸走 `::-webkit-scrollbar`
   別名選擇器、經變數繼承鏈取淺色值，不受此區影響） */
:root:has(body.light) {
  --scrollbar-thumb: #b3a482;
  --scrollbar-thumb-hover: #8a7a5c;
  --scrollbar-track: #eee7d2;
}

/* ── 全域：頁面基礎 ── */
/* 欄位：`html`/`body` 外邊距清除 */
html, body { margin: 0; padding: 0; }
/* 欄位：頁面主體 — 字型、底色、文字色 */
body {
  font-family: -apple-system, "PingFang TC", "Microsoft JhengHei", "Noto Sans TC", system-ui, sans-serif;
  /* 不可用 `background:` shorthand：會重置 `background-image`（紙紋），需拆 longhand */
  background-color: var(--bg);
  background-image: var(--paper-texture);
  color: var(--text);
  font-size: 14px;
  line-height: 1.55;
}

/* ── 頁面頂部：標題列（`header`，吸附頂端） ── */
/* 欄位：`header` 容器 — 標題列整體（sticky 置頂） */
header {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 20px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20;
}
/* 欄位：`header` 標題「Token 計算器」 */
header h1 { font-size: 17px; margin: 0; }
/* 欄位：`header` 副標題（離線說明、引擎模式） */
header .sub { color: var(--muted); font-size: 12px; }
/* 欄位：`header` 右側「☀️/🌙」主題切換按鈕 */
#themeBtn { margin-left: auto; font-size: 16px; line-height: 1; padding: 6px 10px; }

/* ── 版面：內容容器與雙欄網格 ──
   左欄 320px：Tokenizer / 檔案分析 / 費用估算
   右欄 1fr：文字輸入 / Token 視覺化 */
/* 欄位：`.wrap` — 整體內容容器（置中、限寬） */
.wrap { max-width: 1200px; margin: 0 auto; padding: 16px; }
/* 欄位：`.grid` — 雙欄網格（左 320px 固定 / 右 1fr 自適應） */
.grid { display: grid; grid-template-columns: 320px 1fr; gap: 16px; }
/* 欄位：`.grid` 子欄 — 防止欄內容溢出（flex/長字串） */
.grid > * { min-width: 0; }
/* 欄位：`.grid` — 窄螢幕（≤860px）改單欄堆疊 */
@media (max-width: 860px) { .grid { grid-template-columns: 1fr; } }

/* ── 面板：所有 `.panel` 共用（左/右欄的所有卡片） ── */
/* 欄位：`.panel` — 卡片外框（底色、邊框、圓角、內距、下距） */
.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px;
  margin-bottom: 16px;
}
/* 欄位：`.panel` `h2` — 面板標題列（如「Tokenizer」「文字輸入」） */
.panel h2 {
  font-size: 13px; margin: 0 0 10px; color: var(--muted);
  text-transform: uppercase; letter-spacing: .06em; font-weight: 600;
}
/* 欄位：`.panel-head` — 面板標題列 flex 排版（由 inline `style` 收斂的通用類） */
.panel-head { display: flex; align-items: center; gap: 8px; }
/* 欄位：`.panel-head.fwrap` — 標題列允許換行（按鈕較多的面板）
   （類名刻意避開「`wrap`」：與容器 `.wrap` 規則碰撞會讓標題列誤獲
   `padding: 16px`，Chrome 在 `flex-wrap`＋`padding` 下產生額外換行、高度翻倍） */
.panel-head.fwrap { flex-wrap: wrap; }
/* 欄位：`.spacer` — 標題列右推彈性空白（取代 `<span style="flex:1">`） */
.spacer { flex: 1; }
/* 欄位：`.mt-10`/`.mt-12` — 區塊上邊距（取代 `style="margin-top:…"`；`#metaWrap` 特例 12px） */
.mt-10 { margin-top: 10px; }
.mt-12 { margin-top: 12px; }
/* 欄位：`#srcLabel` — 來源標籤（唯一特例：右推＋去上邊距，非通用 `spacer`/`mt-*` 類） */
#srcLabel { flex: 1; margin-top: 0; }

/* ── 左欄：Tokenizer 面板 ──
   上傳 `tokenizer.json` 與檔案分析共用此樣式 */
/* 欄位：上傳區（tokenizer 拖放區 + 檔案拖放區共用） */
.dropzone {
  border: 2px dashed var(--border);
  border-radius: 8px;
  padding: 22px 14px;
  text-align: center;
  color: var(--muted);
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
/* 欄位：上傳區 — 拖曳檔案進入時的強調框 */
.dropzone.drag { border-color: var(--accent); background: var(--accent-soft); }
/* 欄位：上傳區 — 大圖示（🗂️ / 📄） */
.dropzone .big { font-size: 24px; }
/* 欄位：上傳區 — 粗體提示文字（「拖曳 `tokenizer.json`」） */
.dropzone b { color: var(--accent); }
/* 欄位：上傳區 — 隱藏原生 `<input type=file>`（點擊區觸發） */
.dropzone input[type=file] { display: none; }
/* 欄位：`#fileDrop` — 檔案分析的上傳區：上下內距較 tokenizer 多 5px
   （未上傳任何檔案時這個欄位高度多 10px） */
#fileDrop { padding-top: 27px; padding-bottom: 27px; }

/* ── 左欄：Tokenizer 面板 — 預設清單按鈕 ── */
/* 欄位：`.presets` — 按鈕清單容器（垂直堆疊） */
.presets { display: grid; grid-template-columns: 1fr; gap: 8px; margin-top: 12px; }
/* 欄位：`#panelBody` — Tokenizer 面板展開後的內容區（拖曳區緊貼最後一個按鈕 →
   加上與按鈕間距相同的 8px 間隔，避免緊貼） */
#panelBody { margin-top: 8px; }
/* 欄位：`.preset-btn` — 每個 tokenizer 按鈕（名稱 + 大小） */
.preset-btn {
  background: var(--panel2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 12px;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 8px;
  height: 40px;   /* 固定高度：編輯模式（多出操作按鈕）與一般模式高度強制一致 */
  overflow: hidden;
  transition: border-color .15s, background .15s;
}
/* 欄位：`.preset-btn` hover */
.preset-btn:hover { border-color: var(--accent); background: var(--accent-soft); }
/* 欄位：`.preset-btn` — 目前使用中的 tokenizer（光圈） */
.preset-btn.active {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1px var(--accent);
}
/* 欄位：`.preset-btn` `.pn` — 按鈕內名稱文字 */
.preset-btn .pn { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 欄位：`.preset-btn` `.ps` — 按鈕內大小（MB） */
.preset-btn .ps { color: var(--muted); font-size: 11.5px; font-family: var(--mono); flex-shrink: 0; }
/* 欄位：`.preset-btn` `.pops` — 編輯模式的操作按鈕群容器 */
.preset-btn .pops { display: inline-flex; gap: 4px; margin-left: 6px; flex-shrink: 0; height: 17px; align-items: center; }
/* 欄位：`.preset-btn` `.pbtn` — 操作按鈕（更名/刪除/加入，17px 高） */
.preset-btn .pbtn {
  /* 三操作按鈕同構：無背景 + 彩色邊框區分。
     文字色與邊框同色（兩主題皆可讀）；hover 僅加柔和底色，不變字色不變邊框 */
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 5px;
  font-size: 11px;
  line-height: 1;
  height: 17px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 7px;
  cursor: pointer;
  color: var(--text);
  overflow: hidden;   /* 字形超出 17px 盒一律裁切：按鈕視覺高度恆為 17px */
}
/* 欄位：`.preset-btn` `.pbtn` hover */
.preset-btn .pbtn:hover { background: var(--panel2); }
/* 邊框/文字色：更名 = 主色（金黃）、刪除 = 紅、加入 = 綠 */
/* 欄位：`.pbtn.rename` —「更名」按鈕（主色邊框） */
.preset-btn .pbtn.rename { border-color: var(--accent); color: var(--accent); }
/* 欄位：`.pbtn.rename` hover（主色淡底） */
.preset-btn .pbtn.rename:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }
/* 欄位：`.pbtn.x` —「刪除」按鈕（紅色邊框） */
.preset-btn .pbtn.x { border-color: var(--bad); color: var(--bad); }
/* 欄位：`.pbtn.x` hover（紅色淡底） */
.preset-btn .pbtn.x:hover { background: color-mix(in srgb, var(--bad) 12%, transparent); }
/* 欄位：`.pbtn.ok` —「加入」按鈕（綠色邊框） */
.preset-btn .pbtn.ok { border-color: var(--good); color: var(--good); }
/* 欄位：`.pbtn.ok` hover（綠色淡底） */
.preset-btn .pbtn.ok:hover { background: color-mix(in srgb, var(--good) 12%, transparent); }

/* ── 左欄：Tokenizer 面板 — 載入後的中繼資料表 ── */
/* 欄位：`.meta` — 中繼資料區（模型類型/詞表大小/等） */
.meta { font-size: 12.5px; }
/* 欄位：`.meta` `table` — 表格（寬度撐滿） */
.meta table { width: 100%; border-collapse: collapse; }
/* 欄位：`.meta` `td` — 每列 */
.meta td { padding: 3px 0; vertical-align: top; }
/* 欄位：`.meta` `td:first-child` — 左側欄位名（固定 92px） */
.meta td:first-child { color: var(--muted); width: 92px; }
/* 欄位：`.meta` `td:last-child` — 右側數值（等寬字、可斷行） */
.meta td:last-child { word-break: break-all; font-family: var(--mono); font-size: 12px; }
/* 欄位：`.badge` — 模型類型膠囊標籤（如 BPE、Unigram） */
.badge {
  display: inline-block; padding: 1px 8px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); font-size: 11.5px;
  font-weight: 600; margin-right: 6px;
}

/* ── 右欄：文字輸入面板 — 輸入欄與統計 ── */
/* 欄位：`#input` — 文字輸入 `textarea`（`min-height`，可拖曳調高） */
textarea#input {
  display: block; width: 100%; max-width: 100%; min-height: 173px; resize: vertical;
  border: 1px solid var(--border); border-radius: 8px;
  padding: 10px 12px; font-size: 14px; font-family: var(--mono);
  line-height: 1.5;   /* 與 `#virtual` 一致（斷行模型以行高 21px 換算） */
  tab-size: 4;   /* 與 LineBreak Tab 模型（4 半形單位）一致——瀏覽器預設 8 會使含 Tab 行換行偏移 */
  box-sizing: border-box;   /* 與 `.virtual` 盒模型一致（內容盒 = 總寬 − `padding` − `border`） */
  color: var(--text); background: var(--panel2);
  outline: none;
}
/* 欄位：`#input[hidden]` — 虛擬層啟用時隱藏 `textarea`（`#input` 的 `display:block`
   權重壓過 UA `[hidden]`，需同權重顯式覆寫；`ui-virtual.js` 的高度快照已先於隱藏執行） */
textarea#input[hidden] { display: none; }
/* 欄位：`#input` focus（主色邊框） */
textarea#input:focus { border-color: var(--accent); }
/* 容器：`textarea` 與虛擬顯示層佔同一塊（一次只顯示其一） */
/* 容器：`textarea` 與虛擬顯示層佔同一格（grid 重疊），一次只顯示其一；
   `#virtualBody` 以 `position`:relative 承接 `vrow` 定位，使 content box 位移
   與 `textarea` 的 `padding`（`top` 10px / `left` 12px）完全對齊 */
.input-area { position: relative; display: grid; }
.input-area > textarea#input, .input-area > .virtual { grid-area: 1 / 1; }
/* 欄位：`#virtual` — 大文本（>`VIRTUAL_THRESHOLD_LINES`（2000）行 或 >`VIRTUAL_THRESHOLD_CHARS`
   （40 萬字元））唯讀虛擬顯示層：
   與 `#input` 同字型/同 `padding`/同外觀/同高度（有限高可捲動）——
   `#virtualBody` 以 `position`:relative 承接 `vrow` 定位，使 content box 位移
   與 `textarea` 的 `padding`（`top` 10px / `left` 12px）完全對齊 */
.virtual {
  width: 100%; max-width: 100%; height: 173px; min-height: 173px;
  border: 1px solid var(--border); border-radius: 8px;
  padding: 10px 12px; font-size: 14px; font-family: var(--mono);
  color: var(--text); background: var(--panel2);
  outline: none; overflow-y: auto; overflow-x: hidden;
  scrollbar-gutter: stable;   /* 捲軸槽恆預留：行界計算寬度恆定（與 `#input` 捲軸存在態之 `clientWidth` 同分——兩階段測寬第二段語義恆常化） */
  resize: vertical;   /* 與 `textarea` 相同：可拖曳調高 */
  white-space: pre-wrap; word-wrap: break-word; word-break: break-word;
  line-height: 1.5; box-sizing: border-box;
  tab-size: 4;   /* 與 `#input`/LineBreak 同源：`vrow` 以 `white-space:pre` 直渲，tab 寬一致 */
  user-select: text;
}
.virtual #virtualBody { position: relative; pointer-events: none; }
.virtual .vrow { position: absolute; left: 0; right: 0; white-space: pre; pointer-events: auto; }
/* 欄位：`.stats` — 統計數字網格（Token 數/字元數/…，自動換列） */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
/* 欄位：`.stat` — 單一統計格（卡片） */
.stat {
  background: var(--panel2); border: 1px solid var(--border); border-radius: 8px;
  padding: 8px 12px; text-align: center;
}
/* 欄位：`.stat` `.num` — 統計數字（大、粗、等寬） */
.stat .num { font-size: 20px; font-weight: 700; font-family: var(--mono); }
/* 欄位：`.stat` `.lbl` — 統計標籤（如「Token 數」） */
.stat .lbl { font-size: 11.5px; color: var(--muted); }
/* 欄位：`.stat` `.num.accent` —「Token 數」強調色 */
.stat .num.accent { color: var(--accent); }

/* ── 右欄：Token 視覺化面板 ──
   虛擬捲動：`vspace` 撐高、`trow` 絕對定位、`tok` 為晶片 */
/* 欄位：`#tokenviz` — 視覺化容器（固定 305px，可拖曳調高、內容捲動） */
.tokenviz {
  font-family: var(--mono); font-size: 13.5px; line-height: 1.5;
  position: relative;
  background: var(--bg); border: 1px solid var(--border); border-radius: 8px;
  padding: 10px 12px; height: 305px; min-height: 180px; resize: vertical; overflow: auto;
  scrollbar-gutter: stable;   /* 捲軸槽恆預留：`clientWidth` 語義恆定（垂捲軸出現/消失不再漂移 ~15px → 幾何快照與打包寬一致、末行不溢出誘發水平捲軸） */
  user-select: all;
}
/* 欄位：`.tokenviz` `.vspace` — 虛擬捲動撐高 spacer（總高 = 行數 × 20.25px） */
.tokenviz .vspace { width: 1px; }
/* 欄位：`.tokenviz` `.trow` — 每個顯示行（絕對定位、不換行） */
.tokenviz .trow {
  position: absolute;
  left: 0; right: 0;
  white-space: nowrap;
  display: flex;
  align-items: center;
}
/* 欄位：`.tokenviz` `.trow` `.tcontent` — 行內 token 內容 */
.tokenviz .trow .tcontent { white-space: nowrap; }
/* 欄位：`.tokenviz` `.trow` `.tcount` — 行尾的 token 計數 */
.tokenviz .trow .tcount {
  margin-left: auto;
  padding: 0 8px 0 10px;
  font-size: 10.5px;
  font-family: var(--mono);
  color: var(--muted);
  flex-shrink: 0;
  user-select: none;
}
/* 欄位：`.tokenviz` `.trow.file-start` / `.trow.file-end` — 全檔模式檔界行樣式（各檔獨立
    編碼串接的邊界標示；檔界＝行樣式邊框，無 SEP chips、無分隔行；m≥2 才標記）。
   外緣行（視圖首列/末列）由渲染層（`renderVizWindow`）排除 class——線僅標示檔界分隔語意 */
.tokenviz .trow.file-start {
  border-top: 2px solid var(--accent);
  padding-top: 1px;
}
.tokenviz .trow.file-end {
  border-bottom: 2px solid var(--accent);
  padding-bottom: 1px;
}
/* 欄位：`#vizFileState` — 全檔模式「目前檔」指示器（視窗頂行所屬檔案；動態建立，僅全檔模式顯示）
   長檔名截汰為「…」防標題列被撐爆；全名以 `title` 工具提示承載（`ui-viz.js` 同步設定） */
.viz-fstate {
  font-size: 10.5px;
  color: var(--muted);
  margin-left: 2px;
  white-space: nowrap;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 欄位：`.tokenviz` `.tok` — 單個 token 晶片（彩底、可點選） */
.tokenviz .tok {
  border-radius: 4px; padding: 1px 2px; cursor: pointer;
  color: var(--chip-text);
  box-shadow: inset 0 0 0 1px var(--tok-ring);
  white-space: nowrap;
}
/* 欄位：`.tokenviz` `.tok.special` — 特殊 token（斜紋底 + 主色框） */
.tokenviz .tok.special {
  box-shadow: inset 0 0 0 1.5px var(--accent);
  background-image: repeating-linear-gradient(45deg, var(--special-stripe), var(--special-stripe) 4px, transparent 4px, transparent 8px);
}
/* 欄位：`.tokenviz` `.tok` hover（變亮） */
.tokenviz .tok:hover { filter: brightness(var(--tok-hover)); }
/* 欄位：`.tokenviz` `.tok.plain` — 被篩選開關隱藏的分類（轉純文字） */
.tokenviz .tok.plain {
  color: var(--text);
  box-shadow: none;
  cursor: default;
}
/* 欄位：`.tokenviz` `.empty` — 空狀態文字（— / 0 個 token） */
.tokenviz .empty { color: var(--muted); }

/* ── 左欄：費用估算面板 — 表格（`table.data.costtable`） ── */
/* 欄位：費用表格 — 固定欄寬（避免欄位被壓縮） */
table.data.costtable { table-layout: fixed; }
/* 欄位：`#costPanel` — 費用表格容器（窄屏 fixed layout 下固定寬欄位
   （單價/欄位名 `input`）溢出被裁切，容器水平捲動防護） */
#costPanel { overflow-x: auto; }
/* 欄位：費用表格 — 第一欄（標籤列）寬 120px */
table.data.costtable th:first-child, table.data.costtable td:first-child { width: 120px; }
/* 欄位：費用表格 — 所有儲存格左右內距（3px） */
table.data.costtable th, table.data.costtable td { padding-left: 3px; padding-right: 3px; }
/* Flash/Pro、三個單價欄、預估費用向左靠齊 */
/* 欄位：費用表格 — 數字欄（單價/費用）靠左 */
table.data.costtable th.num, table.data.costtable td.num { text-align: left; }
/* 欄位：費用表格 — 編輯模式的單價 `input`（`type=number`，70px） */
table.data.costtable input[type=number] { width: 70px; }
/* 欄位：費用表格 — 快取命中率調整條（`type=range`）——原生 range 的 track 以「強調色
    半透明」渲染、thumb 取強調色，以 `accent-color: var(--accent)` 收編主題色（深色金黃／淺色焦糖
    隨變數自動解析）。金黃較亮，若實測感官不佳可再微調（本規則唯一落點） */
table.data.costtable input[type=range] { accent-color: var(--accent); }
/* 費用估算編輯模式：標題列 `input`（模型名稱、欄位名稱） */
/* 欄位：費用表格 — 標題列 `input`（模型名/欄位名，72px） */
table.data.costtable th input {
  width: 72px; font-size: 11.5px; padding: 2px 4px;
  background: var(--panel2); color: var(--text);
  border: 1px solid var(--border); border-radius: 5px; font-family: var(--mono);
}
/* 欄位：費用表格 — 標題列 `input` focus */
table.data.costtable th input:focus { border-color: var(--accent); outline: none; }
/* 第一欄為模型名稱（如 Deepseek v4）：`input` 需較寬，避免被截斷 */
/* 欄位：費用表格 — 第一欄（模型名稱）`input` 寬 100px */
table.data.costtable th:first-child input { width: 100px; }
/* 輸入 tokens 鎖定按鈕（嵌於輸入欄位內右方） */
/* 欄位：`.inp-lock` —「輸入 tokens」欄位的鎖定按鈕定位容器 */
.inp-lock { position: relative; display: inline-block; }
/* 欄位：`.inp-lock` `input` — 輸入 tokens 欄（右側預留鎖定鈕空間 36px） */
.inp-lock input { padding-right: 36px; }
/* 欄位：`.inp-lock` `.lock-btn` — 鎖定/解鎖按鈕（🔒/🔓，絕對定位於欄內右側） */
.inp-lock .lock-btn {
  position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
  background: transparent; border: none; padding: 2px 4px; margin-left: 0;
  font-size: 12px; line-height: 1; cursor: pointer;
}
/* 欄位：`.inp-lock` `.lock-btn` hover */
.inp-lock .lock-btn:hover { filter: brightness(1.5); }
/* 欄位：`.inp-lock` `.lock-btn.locked` — 鎖定中的按鈕（主色） */
.inp-lock .lock-btn.locked { color: var(--accent); }

/* ── 通用小按鈕：`.ftotal` ──
   費用估算面板的分頁切換按鈕（A/B/C） */
/* 欄位：`.ftotal` — 分頁按鈕（等寬字、小尺寸） */
.ftotal {
  font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--text);
  text-transform: none; white-space: nowrap;
  background: var(--panel2); border: 1px solid var(--border); border-radius: 6px;
  padding: 2px 10px; cursor: pointer;
}
/* 欄位：`.ftotal` hover */
.ftotal:hover { border-color: var(--accent); color: var(--accent); }
/* 欄位：`.ftotal.active` — 啟用中（如費用分頁 A/B/C 目前頁） */
.ftotal.active { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
/* 欄位：`.ro-badge` —「唯讀」標記（文字輸入欄啟用唯讀虛擬顯示層時顯示） */
.ro-badge {
  display: inline-block; font-size: 10.5px; font-weight: 600; white-space: nowrap;
  line-height: 1;                   /* 不參與標題列行高：免撐高 `h2` */
  align-self: center;               /* flex 子項：預設 stretch 會拉高盒身 */
  color: var(--muted);
  border: 1px solid color-mix(in srgb, var(--muted) 55%, transparent);
  border-radius: 8px; padding: 1px 7px;
}
/* 欄位：`.fcx` —「全部移除」✕（檔案總數按鈕內） */
.fcx { color: var(--muted); cursor: pointer; padding-left: 6px; margin-left: 2px; font-size: 11px; }
/* 欄位：`.fcx` hover（變紅） */
.fcx:hover { color: var(--bad); }

/* ── 左欄：檔案分析面板 — 檔案列表 ── */
/* 欄位：`.filelist` — 已上傳檔案清單（可捲動，最高 363px） */
.filelist { margin-top: 10px; display: flex; flex-direction: column; gap: 6px; max-height: 363px; overflow: auto; }
/* 欄位：`.fitem` — 單一檔案列（名稱 + 大小 + token 數 + ✕） */
.fitem {
  display: flex; align-items: center; gap: 8px;
  background: var(--panel2); border: 1px solid var(--border); border-radius: 7px;
  padding: 6px 10px; cursor: pointer; font-size: 12.5px;
}
/* 欄位：`.fitem` hover */
.fitem:hover { border-color: var(--accent); }
/* 欄位：`.fitem.active` — 目前顯示中的檔案（光圈） */
.fitem.active { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
/* 欄位：`.fitem.oversize` — 過大（>32MB）未載入的檔案（紅底警示） */
.fitem.oversize {
  background: var(--oversize-bg);
  border-color: var(--oversize-border);
  color: #fff;
}
/* 欄位：`.fitem.oversize` hover */
.fitem.oversize:hover { border-color: var(--oversize-border); }
/* 欄位：`.fitem.oversize` 內大小/✕（半透明白） */
.fitem.oversize .fsize, .fitem.oversize .fdel { color: rgba(255,255,255,.72); }
/* 欄位：`.fitem.oversize` 內 ✕ hover */
.fitem.oversize .fdel:hover { color: #fff; }
/* 欄位：`.fitem.oversize` 內 token 數（白字） */
.fitem.oversize .ftok { color: #fff; }
/* 欄位：`.fitem` `.fname` — 檔名（可斷行、撐滿剩餘寬度） */
.fitem .fname { flex: 1; word-break: break-all; min-width: 0; }
/* 欄位：`.fitem` `.fsize` — 檔案大小（灰、等寬） */
.fitem .fsize { color: var(--muted); font-family: var(--mono); font-size: 11.5px; white-space: nowrap; }
/* 欄位：`.fitem` `.ftok` — token 數（粗、等寬） */
.fitem .ftok { font-family: var(--mono); font-weight: 700; white-space: nowrap; }
/* 欄位：`.fitem` `.fdel` — 移除 ✕ */
.fitem .fdel { color: var(--muted); cursor: pointer; padding: 0 4px; font-size: 12px; }
/* 欄位：`.fitem` `.fdel` hover（變紅） */
.fitem .fdel:hover { color: var(--bad); }

/* ── 通用：按鈕列與按鈕 ── */
/* 欄位：`.row` — 按鈕列（貼上/清除/複製/加入分析/存為檔案 等） */
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 10px; }
/* 欄位：`button`/`.btn` — 通用按鈕 */
button, .btn {
  background: var(--panel2); border: 1px solid var(--border); border-radius: 7px;
  padding: 6px 14px; font-size: 13px; cursor: pointer; color: var(--text);
}
/* 欄位：`button` hover */
button:hover, .btn:hover { border-color: var(--accent); color: var(--accent); }
/* 欄位：`button.primary` — 主按鈕（主色底，字色隨主題：深色金黃底近黑字／淺色焦糖底白字） */
button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
/* 欄位：`button.primary` hover（hover 提亮由 `color-mix` 推導、值隨主題；字色以 `--accent-text` 維持對比） */
button.primary:hover { background: color-mix(in srgb, var(--accent) 85%, white); color: var(--accent-text); }
/* 欄位：鍵盤聚焦指示 — 可點擊區塊 `:focus-visible` 以 `outline` 標示；
   僅鍵盤 Tab 導航時顯示，滑鼠操作無視覺變化 */
button:focus-visible, .btn:focus-visible, .dropzone:focus-visible, .fitem:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── 視覺化標題列：開關群（按鈕式，`.chk.pill`） ──
   開關群採「文字即按鈕」：原生 checkbox 視覺隱藏（絕對定位＋`opacity`，
   保留狀態語義與鍵盤焦點），按鈕文字包在 `span.btn-text` 內、選中以
   `--accent` 系樣式標示；省去開關軌道寬度，緩解標題列被全檔模式
   「目前檔」長檔名（`viz-fstate`）撐爆的擁擠。 */
/* 欄位：`label.chk` — 開關 + 文字的整組標籤 */
label.chk { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; cursor: pointer; user-select: none; }
/* 欄位：`.chk.sm` — 小型按鈕（視覺化篩選列用） */
.chk.sm { font-size: 12px; }
/* 欄位：`.chk.pill` — 定位基準（隱藏 `input` 的絕對定位錨） */
.chk.pill { position: relative; }
/* 欄位：`.chk.pill` `input` — 隱藏原生 checkbox（`opacity`＋絕對定位，保留 tab 焦點） */
.chk.pill input { position: absolute; opacity: 0; width: 0; height: 0; }
/* 欄位：`.chk.pill` `.btn-text` — 按鈕主體（未選：中性邊框；選中以強調色高亮） */
.chk.pill .btn-text { padding: 1px 7px; border-radius: 4px; border: 1px solid var(--border); color: var(--muted); background: transparent; transition: .15s; }
/* 欄位：`.chk.pill` 選中 — 強調色樣式（與 `.dropzone.drag`/`.preset-btn:hover` 同值） */
.chk.pill input:checked + .btn-text { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
/* 欄位：`.chk.pill` 鍵盤聚焦指示 — 雙層 ring（外層 `--bg` 隔離、內層 `--accent` 主色，
   兩主題對比皆可讀；與原有開關聚焦模式同位，僅鍵盤 Tab 時顯示） */
.chk.pill input:focus-visible + .btn-text { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent); }

/* ── 通用：資料表（`table.data`） ──
   費用估算表格與其他表格共用 */
/* 欄位：`table.data` — 資料表（寬度撐滿、12.5px） */
table.data { width: 100%; border-collapse: collapse; font-size: 12.5px; }
/* 欄位：`.vsep` — 垂直分隔線（視覺化標題列的「|」） */
.vsep { color: var(--border); font-size: 13px; padding: 0 2px; user-select: none; }
/* 欄位：`table.data` 儲存格 — 底線分隔、內距 */
table.data th, table.data td { border-bottom: 1px solid var(--border); padding: 5px 8px; text-align: left; }
/* 欄位：`table.data` `th` — 表頭（灰、粗、底色） */
table.data th { color: var(--muted); font-weight: 600; background: var(--panel2); }
/* 欄位：`table.data` 數字儲存格 — 靠右、等寬字 */
table.data td.num, table.data th.num { text-align: right; font-family: var(--mono); }
/* 欄位：`table.data` `input` — 表格內 `input`（90px、等寬字） */
table.data input {
  width: 90px; border: 1px solid var(--border); border-radius: 5px;
  padding: 3px 6px; font-family: var(--mono); font-size: 12px;
  background: var(--panel2); color: var(--text);
}

/* ── 通用：輔助樣式 ── */
/* 欄位：`.muted` — 灰字（說明、次要文字） */
.muted { color: var(--muted); }
/* 欄位：`.hidden` — 隱藏元素（`display:none` 強制） */
.hidden { display: none !important; }
/* 欄位：`.err` — 錯誤訊息（紅字） */
.err { color: var(--bad); font-size: 12.5px; margin-top: 8px; white-space: pre-wrap; }
/* 欄位：`.notice` — 提示文字（灰字小字） */
.notice { color: var(--muted); font-size: 12.5px; }
/* 欄位：`.warn` — 警示文字通用類（警示字樣式，同 `.notice` 字級；置於 `.notice` 後——
   依宣告序覆蓋 `.notice` 灰字（同特異度後者勝），勿重排至其前）。現行使用情境：
   `#fileDropNotice` 警示態（記憶體超閾值時兩行換警示文案）；字色取 `--warn-strong`——
   深色＝`--warn` 金黃，淺色預設金褐在紙底不顯眼、換墨綠（語意色驗算同 `--good`） */
.warn { color: var(--warn-strong); font-size: 12.5px; }
/* 欄位：`#presetStatus.idb-warn` — IDB 降級警示（黃字，覆蓋 `.notice` 灰字；維持 `--warn` 金黃） */
#presetStatus.idb-warn { color: var(--warn); font-weight: 600; }
/* 欄位：`footer` — 頁尾（版權/離線說明） */
footer { color: var(--muted); font-size: 11.5px; text-align: center; padding: 10px 0 24px; }

/* ── 通用：提示框（`.tooltip`） ──
   hover token 晶片時顯示 `id`/原始/解碼資訊 */
/* 欄位：`#tip` — 浮動提示框（固定定位、置頂層、不可互動） */
.tooltip {
  position: fixed; z-index: 50; pointer-events: none;
  background: var(--tip-bg); color: var(--tip-text);
  padding: 6px 10px; border-radius: 6px;
  font-size: 12px; font-family: var(--mono); max-width: 420px;
  word-break: break-all; box-shadow: 0 4px 16px rgba(0,0,0,.5);
  white-space: pre-line;
}
