:root {
  --bg: #f7f5f2;
  --card-bg: #ffffff;
  --text: #3f3a34;
  --text-muted: #756d61; /* 原本 #8a8378 在白卡片上只有3.75:1對比，低於文字最低4.5:1標準，改深一階 */
  --accent: #7a8471;
  --accent-dark: #5f6b58;
  --accent-light: #e7ebe2;
  --side: #b98b4e;
  --side-light: #f3e6d0;
  --border: #e7e2da;
  --radius: 16px;
  /* 兩層陰影：貼近卡片的緊緻接觸影＋更遠更柔的環境影，比單層平面陰影
     多一點「浮起來」的層次感，這是2026-08-27視覺優化那輪加的。 */
  --shadow: 0 1px 2px rgba(60, 50, 30, 0.05), 0 10px 28px -6px rgba(60, 50, 30, 0.12);
  --warning-bg: #fdf1e0;
  --warning-border: #e8b96a;
  --warning-text: #7a5a1e;
  --danger-bg: #fbe4e2;
  --danger-border: #d98883;
  --danger-text: #8a2f28;
  --success: #6fae7c;
  /* 2026-09-08拿掉Google Fonts（Bricolage Grotesque）：改用系統字型，
     跟html/body（見下面那條font-family規則）同一套堆疊，標題不再跟內文
     用兩種字體、也不用等外部字型載入才定型，看起來更像原生App。 */
  --font-display: -apple-system, BlinkMacSystemFont, system-ui, "PingFang TC", "Microsoft JhengHei", sans-serif;

  /* ---------- 動態語彙（2026-09-08）----------
     在這之前，全檔45條transition的緩動曲線清一色是瀏覽器內建的ease，
     時間則是0.1/0.12/0.15/0.18/0.2/0.25/0.3s散在各處手寫。內建ease
     兩頭都慢，用在「東西進場/退場」這種使用者正在盯著看的瞬間會鈍鈍的；
     散落的秒數也讓同一個份量級距的動作看起來各動各的。這裡收成一組
     具名的曲線與時距，後面所有轉場都引用它們，要調整手感只改這裡一處。

     out    ：東西進場/退場、按下回饋——起步快、尾巴收得乾淨，最跟手。
     in-out ：已經在畫面上的東西移動/變形——兩頭對稱才不會偏一邊。
     drawer ：iOS抽屜那條曲線，給由下往上、份量比較重的面板用。
     時距一律壓在300ms以內：press給按下的瞬間，fast給小元件，
     base給整頁/彈窗這種比較大塊的轉場，slow只留給進度環那種
     「要讓人看清楚數字在跑」的敘事型動畫。 */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
  --dur-press: 0.12s;
  --dur-fast: 0.16s;
  --dur-base: 0.22s;
  --dur-slow: 0.32s;

  /* ---------- 材質（2026-09-08）----------
     底部導覽列跟彈窗背幕原本都是純色不透明的色塊，把畫面切成一格一格。
     改成半透明＋背景模糊之後，內容會從底下透出來一點，導覽列讀起來是
     「浮在內容上的一層玻璃」而不是「畫面下緣被切掉一條」——這是原生
     App跟網頁在觀感上差最多的一個地方。
     --chrome-bg引用--card-bg，而CSS變數是在「使用的那個元素上」才展開，
     所以每個主題各自改寫--card-bg之後，這裡完全不用重寫一次。
     不支援backdrop-filter、使用者要求減少透明度、或要求高對比時，
     下面都有對應的退回規則（搜尋prefers-reduced-transparency）。 */
  --chrome-bg: color-mix(in srgb, var(--card-bg) 72%, transparent);
  --chrome-blur: blur(20px) saturate(180%);
  --scrim: rgba(63, 58, 52, 0.42);
}

/* 深色模式：跟著系統設定自動切換，不用手動開關（這個 App 一天到晚開著，
   晚上用亮色系很刺眼，這個優先度不低）。只重新定義色彩變數，其餘
   間距/圓角/排版邏輯完全共用，不用整份重寫一次。 */
/* 系統跟隨深色：只有使用者沒有手動選過主題（沒有data-theme屬性）
   才生效——手動選了淺色/Terminal，這裡就不該蓋過去。 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg: #1c1a17;
    --card-bg: #262320;
    --text: #ece7de;
    --text-muted: #a39c8f;
    --accent: #93a687;
    --accent-dark: #c3d4b8;
    --accent-light: #333d2e;
    --side: #d9ac6e;
    --side-light: #3d3222;
    --border: #3a352e;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 10px 28px -6px rgba(0, 0, 0, 0.4);
    --warning-bg: #3a2f16;
    --warning-border: #8a6a2e;
    --warning-text: #e8c483;
    --danger-bg: #3a201d;
    --danger-border: #8a4540;
    --danger-text: #e69a94;
    --success: #7fc28e;
    --scrim: rgba(0, 0, 0, 0.55); /* 彈窗背幕：深色/高彩底色要各自壓一次，共用淺色那條會太淡 */
  }
}
/* 手動選「深色」：跟系統自動判斷同一組色票，差別只在不管系統設定
   是什麼都強制套用（點主題切換鈕選出來的，不是媒體查詢跟出來的）。 */
:root[data-theme="dark"] {
  --bg: #1c1a17;
  --card-bg: #262320;
  --text: #ece7de;
  --text-muted: #a39c8f;
  --accent: #93a687;
  --accent-dark: #c3d4b8;
  --accent-light: #333d2e;
  --side: #d9ac6e;
  --side-light: #3d3222;
  --border: #3a352e;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 10px 28px -6px rgba(0, 0, 0, 0.4);
  --warning-bg: #3a2f16;
  --warning-border: #8a6a2e;
  --warning-text: #e8c483;
  --danger-bg: #3a201d;
  --danger-border: #8a4540;
  --danger-text: #e69a94;
  --success: #7fc28e;
  --scrim: rgba(0, 0, 0, 0.55); /* 彈窗背幕：深色/高彩底色要各自壓一次，共用淺色那條會太淡 */
}

/* ---------- Terminal 主題（btop/htop風格）---------- */
/* 純黑背景+霓虹綠字，全域強制等寬字體——這組色票刻意不跟其他主題共用
   任何一個值，是完全獨立的第三種身份，不是深色模式的變體。 */
:root[data-theme="terminal"] {
  --bg: #000000;
  --card-bg: #0a0a0a;
  --text: #00ff00;
  --text-muted: #00aa00;
  --accent: #00ff00;
  --accent-dark: #00cc00;
  --accent-light: #003300;
  --side: #00ff00;
  --side-light: #002200;
  --border: #00ff00;
  --shadow: none;
  --warning-bg: #1a1a00;
  --warning-border: #aaaa00;
  --warning-text: #ffff00;
  --danger-bg: #1a0000;
  --danger-border: #aa0000;
  --danger-text: #ff0000;
  --success: #00ff00;
  --scrim: rgba(0, 0, 0, 0.72); /* 彈窗背幕：深色/高彩底色要各自壓一次，共用淺色那條會太淡 */
  --font-display: "Consolas", "Courier New", monospace;
}
:root[data-theme="terminal"] * {
  font-family: "Consolas", "Courier New", monospace !important;
}
/* Terminal主題底下，卡片一律用細綠框取代陰影——陰影在純黑背景上看
   起來很奇怪（模擬「浮起來」這件事本來就假設淺色系環境光），改成
   終端機那種「用邊框畫出區塊」的語言。 */
:root[data-theme="terminal"] .card,
:root[data-theme="terminal"] .task-item {
  border: 1px solid var(--border);
  box-shadow: none;
}
/* 用ASCII區塊進度條取代圓環，btop/htop那種[████░░░░]的視覺。 */
:root[data-theme="terminal"] .hero-ring-wrap { display: none; }
:root[data-theme="terminal"] .hero-ascii-bar { display: flex; }
.hero-ascii-bar {
  display: none; /* 只有Terminal主題才顯示 */
  align-items: center;
  gap: 8px;
  position: relative;
  height: 22px;
  border: 1px solid var(--border);
  /* repeating-linear-gradient畫出固定間隔的直條紋理，模擬終端機常見
     的[####    ]區塊字元，不是用文字硬湊。 */
  background: repeating-linear-gradient(90deg, var(--accent-light) 0 6px, transparent 6px 9px);
  overflow: hidden;
}
.hero-ascii-bar::before {
  content: "[";
  position: absolute;
  left: -14px;
  color: var(--accent);
  font-weight: 700;
}
.hero-ascii-bar::after {
  content: "]";
  position: absolute;
  right: -14px;
  color: var(--accent);
  font-weight: 700;
}
.hero-ascii-bar-fill {
  position: absolute;
  inset: 0;
  width: 0%;
  background: repeating-linear-gradient(90deg, var(--accent) 0 6px, transparent 6px 9px);
  transition: width 0.3s ease;
}
.hero-ascii-bar-label {
  position: relative;
  margin-left: auto;
  padding: 0 8px;
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  background: var(--card-bg);
}

/* ---------- 暖陽主題 (sunrise) ---------- */
/* 第4個主題，2026-09-02我要求「多一點顏色主題可以切換、要生動好看」
   加的——底色換成珊瑚橙調的暖米色（跟原本淺色主題的中性灰調米色是
   不同色相，不是同一個底色調深調淺），主色用飽和的珊瑚橙、輔色用
   對比的深松石綠，兩色互為對比色，是這組主題故意選的「活潑」身份，
   跟原本一路走莫蘭迪灰調的克制感做出區隔。文字/底色的對比度維持跟
   其他主題同一個標準，不是靠犧牲可讀性換鮮豔感——這裡沒有額外的深色
   變體，跟Terminal主題一樣是獨立的單一身份，不跟淺色/深色模式綁定。 */
:root[data-theme="sunrise"] {
  --bg: #fff4e8;
  --card-bg: #fffaf4;
  --text: #3d2b1f;
  --text-muted: #7d5940;
  --accent: #e8632c;
  --accent-dark: #b8471a;
  --accent-light: #fce0cf;
  --side: #1f8a72;
  --side-light: #d2ede6;
  --border: #f5d9bc;
  --shadow: 0 1px 2px rgba(120, 60, 20, 0.08), 0 10px 28px -6px rgba(120, 60, 20, 0.18);
  --warning-bg: #fdecc7;
  --warning-border: #d9a233;
  --warning-text: #7a4f0a;
  --danger-bg: #fbdcd6;
  --danger-border: #d9695f;
  --danger-text: #8a2418;
  --success: #1f8a72;
  --scrim: rgba(90, 45, 15, 0.42); /* 彈窗背幕：深色/高彩底色要各自壓一次，共用淺色那條會太淡 */
}

/* ---------- ink 主題 ---------- */
/* 2026-09新增，跟其他主題一樣只覆寫變數、不複製整份CSS。紙感/墨水
   調性：暖米白底＋近黑字＋深墨綠主色＋赭金輔色，邊框收細、陰影比預設
   sage淺色更克制（沒有預設的雙層柔邊環境影，只留一絲貼合陰影）。 */
:root[data-theme="ink"] {
  --bg: #f3f0ea;
  --card-bg: #fffcf7;
  --text: #1c1917;
  --text-muted: #6b645b;
  --accent: #3f4f4a;
  --accent-dark: #2c3835;
  --accent-light: #dde4e1;
  --side: #8a6a3d;
  --side-light: #ede1cd;
  --border: #e3ddd0;
  --shadow: 0 1px 2px rgba(30, 25, 15, 0.04), 0 3px 10px -4px rgba(30, 25, 15, 0.08);
  --warning-bg: #f7ecd4;
  --warning-border: #c9a25a;
  --warning-text: #6b4f18;
  --danger-bg: #f3e0dd;
  --danger-border: #b97066;
  --danger-text: #7a2d24;
  --success: #4f7a5c;
  --scrim: rgba(28, 25, 23, 0.40); /* 彈窗背幕：深色/高彩底色要各自壓一次，共用淺色那條會太淡 */
}

/* ---------- dusk 主題 ---------- */
/* 深色系，但不是既有深色主題（莫蘭迪灰調）的變體——主色換成薰衣草藍
   （不是綠），輔色換成暖金，是獨立的第三種深色身份，跟terminal/dusk
   互不共用色票，warning/danger/success沿用既有深色主題那組（同樣是
   「深色底」的判讀邏輯，不用重新調一次對比度）。 */
:root[data-theme="dusk"] {
  --bg: #12141c;
  --card-bg: #1a1d28;
  --text: #eceaf4;
  --text-muted: #8b8fa3;
  --accent: #9aa6ff;
  --accent-dark: #c2c9ff;
  --accent-light: #262a45;
  --side: #d4b483;
  --side-light: #3a3222;
  --border: #2a2d3a;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 10px 28px -6px rgba(0, 0, 0, 0.45);
  --warning-bg: #3a2f16;
  --warning-border: #8a6a2e;
  --warning-text: #e8c483;
  --danger-bg: #3a201d;
  --danger-border: #8a4540;
  --danger-text: #e69a94;
  --success: #7fc28e;
  --scrim: rgba(0, 0, 0, 0.55); /* 彈窗背幕：深色/高彩底色要各自壓一次，共用淺色那條會太淡 */
}

/* ---------- ocean 主題 ---------- */
/* 2026-09-08新增3個主題（ocean/plum/carbon），因為原本7個裡面沒有任何
   一個是藍色系或紫色系——sage綠、terminal霓虹綠、sunrise珊瑚橙、ink墨綠、
   dusk是薰衣草「藍紫」但屬深色。這3個各自佔一個原本空著的色相位置，
   不是既有主題調亮調暗的變體。
   ocean：深青藍為主色、暖沙為輔色，底色是帶一點冷調的白，走的是
   「海邊的清晨」那種乾淨、偏冷但不冰的感覺。 */
:root[data-theme="ocean"] {
  --bg: #f2f6f8;
  --card-bg: #ffffff;
  --text: #1b2b33;
  --text-muted: #5d7480;
  --accent: #2b6e8f;
  --accent-dark: #1d4f68;
  --accent-light: #d9e9f0;
  --side: #c98b45;
  --side-light: #f6e6d2;
  --border: #dbe6ec;
  --shadow: 0 1px 2px rgba(20, 50, 65, 0.05), 0 10px 28px -6px rgba(20, 50, 65, 0.14);
  --warning-bg: #fdf1e0;
  --warning-border: #e0b063;
  --warning-text: #7a5518;
  --danger-bg: #fbe4e2;
  --danger-border: #d98883;
  --danger-text: #8a2f28;
  --success: #2e8f7a;
  --scrim: rgba(20, 45, 60, 0.42); /* 彈窗背幕：深色/高彩底色要各自壓一次，共用淺色那條會太淡 */
}

/* ---------- plum 主題 ---------- */
/* 深紫紅為主色、暖金為輔色，底色是很淡的粉灰。整組刻意壓低彩度，
   是「安靜的紫」不是螢光紫——跟sunrise那種高飽和活潑感是兩個方向。 */
:root[data-theme="plum"] {
  --bg: #f8f4f7;
  --card-bg: #fffbfd;
  --text: #2e1f2b;
  --text-muted: #7a6373;
  --accent: #7d3f68;
  --accent-dark: #5c2b4c;
  --accent-light: #ecdcE7;
  --side: #b8863f;
  --side-light: #f4e7cf;
  --border: #e8dce5;
  --shadow: 0 1px 2px rgba(60, 30, 55, 0.05), 0 10px 28px -6px rgba(60, 30, 55, 0.14);
  --warning-bg: #fbeeda;
  --warning-border: #d9a54f;
  --warning-text: #7a5312;
  --danger-bg: #fbe0e0;
  --danger-border: #d17e7e;
  --danger-text: #8a2b2b;
  --success: #5c8f63;
  --scrim: rgba(50, 30, 45, 0.44); /* 彈窗背幕：深色/高彩底色要各自壓一次，共用淺色那條會太淡 */
}

/* ---------- carbon 主題 ---------- */
/* 深色，但跟既有的dark（暖灰＋sage綠）跟dusk（藍紫）都不同：這組是
   完全中性的無彩灰＋冷白主色，對比拉高，接近開發工具的深色介面。
   給「深色但不要有色調」的情境用。 */
:root[data-theme="carbon"] {
  --bg: #0f1113;
  --card-bg: #191c1f;
  --text: #f0f2f4;
  --text-muted: #9aa2a9;
  --accent: #7fb2d9;
  --accent-dark: #b6d6ee;
  --accent-light: #23303a;
  --side: #d8b46a;
  --side-light: #332c1c;
  --border: #2b3034;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 10px 28px -6px rgba(0, 0, 0, 0.55);
  --warning-bg: #3a2f16;
  --warning-border: #8a6a2e;
  --warning-text: #e8c483;
  --danger-bg: #3a201d;
  --danger-border: #8a4540;
  --danger-text: #e69a94;
  --success: #6fbf8c;
  --scrim: rgba(0, 0, 0, 0.6); /* 彈窗背幕：深色/高彩底色要各自壓一次，共用淺色那條會太淡 */
}

* { box-sizing: border-box; }

::selection {
  background: var(--accent);
  color: #fff;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "PingFang TC", "Helvetica Neue", "Microsoft JhengHei", sans-serif;
  transition: background 0.2s ease, color 0.2s ease;
  /* 手機上點兩下整頁放大——viewport已經鎖了maximum-scale/user-scalable，
     這裡在CSS層再加一道：manipulation讓瀏覽器允許正常捲動/單指操作，
     但關掉「連點兩下觸發放大」這個手勢，也順便拿掉點擊的300ms延遲。
     不影響捲動，也不需要另外寫JS還原縮放。 */
  touch-action: manipulation;
}

#app {
  max-width: 480px;
  margin: 0 auto;
  min-height: 100vh;
  /* iOS安全區域（瀏海/Dynamic Island/Home Indicator）：env()在不支援的
     瀏覽器上會被忽略、退回逗號前的固定值，所以這裡用calc()疊加而不是
     取代，安卓/桌面瀏覽器完全不受影響。viewport-fit=cover（見<head>的
     meta viewport）是env()真的能拿到非0值的必要條件，兩個要一起看。 */
  padding: calc(20px + env(safe-area-inset-top)) calc(16px + env(safe-area-inset-right))
    calc(40px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left));
}

.hidden { display: none !important; }

/* 2026-09修：上一版把#view-main切成兩欄，#continue-strip（繼續上次）
   跟#ai-schedule-summary被grid-column丟到右欄，桌面上變成「繼續上次」
   飄在右邊、中間一大塊空洞——拿掉了，桌面維持單欄，只是不再死守480px，
   給內容多一點呼吸空間。#app跟.bottom-nav用同一個max-width（見下面
   .bottom-nav規則），寬螢幕上底欄才會跟內容對齊，不是480對900各管各的。 */
@media (min-width: 900px) {
  #app {
    max-width: 560px;
  }
}

/* 2026-09-01 底部導覽列出現時，#app原本的底部留白不夠蓋過導覽列本身
   的高度，內容最後一塊（例如主畫面「更多功能」按鈕）會被蓋住——疊加
   導覽列的高度上去，跟safe-area-inset-bottom一樣用calc()疊加而不是
   取代原本的padding。 */
body.has-bottom-nav #app {
  padding-bottom: calc(40px + 64px + env(safe-area-inset-bottom));
}

/* 底部導覽：四個入口，安靜、不搶眼——跟App整體「乾淨、少裝飾」的方向
   一致，圖示用純文字符號不用emoji，避免導覽列本身變成視覺焦點。 */
.bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  /* 2026-09-02修：原本是40，比App裡所有全螢幕疊層都高（modal-overlay
     10、cmdk全螢幕搜尋20、applock鎖定畫面25、zen沈浸模式/里程碑慶祝卡
     30）——結果沈浸模式（設計上「其餘全部蓋住」）跟鎖定畫面，底部導覽
     反而穿透蓋在上面，同一份專注計時小工具（15）也被導覽列擋住下半截。
     這支導覽列加進來的時間比上面這些疊層都晚，加的時候沒有對照既有
     的z-index層級，是純粹沒注意到的疏忽。改成5，比modal-overlay(10)
     還低——導覽列只需要蓋過一般頁面內容（沒有設z-index，預設堆疊層
     級是0），不需要蓋過任何modal/疊層。 */
  z-index: 5;
  display: flex;
  max-width: 480px;
  margin: 0 auto;
  /* 2026-09-08改材質：原本是不透明的var(--card-bg)＋一條1px上框線，
     視覺上等於把畫面下緣切掉一條。改成半透明玻璃＋背景模糊之後，
     內容捲動時會從導覽列底下透出來一點，讀起來是「浮在內容上的一層」。
     上框線也一起拿掉，改用下面::before那道很淡的漸層當「捲動邊緣」——
     只有在內容真的捲到導覽列底下時才看得出來，比一條永遠都在的硬線
     安靜很多。 */
  background: var(--chrome-bg);
  -webkit-backdrop-filter: var(--chrome-blur);
  backdrop-filter: var(--chrome-blur);
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  transition: background var(--dur-base) ease, border-color var(--dur-base) ease;
}
/* 捲動邊緣：導覽列上方一小段由透明漸深到底色的遮罩，讓捲過去的內容
   是「淡出到玻璃底下」而不是被一條線硬切斷。pointer-events:none 確保
   它不會擋到底下內容的點擊。 */
.bottom-nav::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 20px;
  pointer-events: none;
  background: linear-gradient(to top, color-mix(in srgb, var(--bg) 80%, transparent), transparent);
}
/* backdrop-filter沒支援（主要是舊版Firefox）就退回不透明底色＋框線，
   也就是2026-09-08之前的樣子——半透明但不模糊會讓文字直接疊在內容上，
   比沒有效果還糟，所以是整組退回而不是只拿掉模糊。 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .bottom-nav {
    background: var(--card-bg);
    border-top: 1px solid var(--border);
  }
  .bottom-nav::before { display: none; }
}
/* 系統層級的「減少透明度」（iOS：輔助使用→顯示與文字大小→降低透明度）
   打開時，玻璃材質整組退回不透明——這個設定的用意就是「不要讓文字疊在
   會動的背景上」，維持模糊等於忽略使用者的明確要求。 */
@media (prefers-reduced-transparency: reduce) {
  .bottom-nav {
    background: var(--card-bg);
    border-top: 1px solid var(--border);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .bottom-nav::before { display: none; }
  .modal-overlay {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
/* 「增加對比」：半透明一律換成實色，並且把區塊邊界用明確的框線畫出來，
   不靠模糊跟陰影暗示層次。 */
@media (prefers-contrast: more) {
  .bottom-nav {
    background: var(--card-bg);
    border-top: 2px solid var(--text);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .bottom-nav::before { display: none; }
  .modal-box { border: 2px solid var(--text); }
}
/* Terminal主題整體語言就是「用邊框畫區塊、不用陰影跟模糊」（見上面
   .card/.task-item的同類覆寫），導覽列跟著同一套，不套玻璃。 */
:root[data-theme="terminal"] .bottom-nav {
  background: var(--card-bg);
  border-top: 1px solid var(--border);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
:root[data-theme="terminal"] .bottom-nav::before { display: none; }
/* 跟#app用同一個寬螢幕max-width（見上面@media (min-width: 900px)），
   不然桌面上#app變寬了、導覽列還卡在480px置中，兩個對不齊。 */
@media (min-width: 900px) {
  .bottom-nav { max-width: 560px; }
}
.bottom-nav-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 4px;
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: 10px;
  transition: color 0.15s ease, background 0.15s ease;
}
.bottom-nav-btn:hover { background: var(--bg); }
.bottom-nav-icon {
  font-size: 18px;
  line-height: 1;
}
.bottom-nav-label {
  font-size: 10.5px;
  letter-spacing: 0.01em; /* 反過來：小字要稍微放鬆才好認，跟上面大字收緊是同一條光學規則的兩端 */
  /* 防呆：就算之後哪個語言的字比中文長，也是省略號收掉，不會擠爆這一格
     或把旁邊的按鈕推歪。 */
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bottom-nav-btn.is-active {
  color: var(--accent-dark);
  font-weight: 600;
}

/* 切換畫面（今天/歷史紀錄/編輯頁）時，被顯示出來的那個 view 淡入＋輕微上移，
   比直接切換乾脆多一點份量感——只做這一個轉場動作，不是每個元件各自加特效。 */
.view:not(.hidden) {
  animation: view-enter var(--dur-base) var(--ease-out);
}
@keyframes view-enter {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* 換日的方向感（由app.js的playDateChangeTransition()掛class）。
   往後一天從右邊進、往前一天從左邊進，跟左右箭頭、跟左右滑的手指方向
   都是同一個方向——「東西從哪裡消失，就從哪裡回來」。18px只是暗示，
   不是真的把整頁推過去；減少動態效果時JS那邊直接不掛class。 */
@keyframes day-in-next {
  from { opacity: 0; transform: translateX(18px); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes day-in-prev {
  from { opacity: 0; transform: translateX(-18px); }
  to { opacity: 1; transform: translateX(0); }
}
/* 一定要帶上.view跟:not(.hidden)：上面那條「切換畫面時淡入」的
   .view:not(.hidden)選擇器權重是(0,2,0)，單寫.day-in-next只有(0,1,0)，
   會整條被蓋掉、換日永遠播成由下往上的view-enter。這裡拉到(0,3,0)壓過去。 */
.view.day-in-next:not(.hidden) { animation: day-in-next var(--dur-base) var(--ease-out); }
.view.day-in-prev:not(.hidden) { animation: day-in-prev var(--dur-base) var(--ease-out); }

.card {
  touch-action: manipulation; /* 卡片連點兩下不放大 */
  /* 淡淡的頂部亮邊，模擬一點點「有光源從上方打下來」的立體感，
     取代原本純色塊——color-mix算相對於--card-bg本身，亮色/暗色模式
     都會自動套用一致的效果，不用另外寫dark mode覆寫規則。 */
  background: linear-gradient(180deg, color-mix(in srgb, var(--card-bg) 94%, white) 0%, var(--card-bg) 65%);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px;
  margin-bottom: 14px;
  /* 主題切換（亮/暗/ink/dusk/terminal）時卡片底色跟著淡入淡出，不要
     跟html/body(見上面的transition:background)一起換色但卡片本身沒動、
     看起來色塊突兀地跳一下。 */
  transition: background 0.2s ease, color 0.2s ease;
}

/* ---------- 登入頁 ---------- */
.view#view-login {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 2026-09-01視覺優化：原本只是主畫面背景上加一絲很淡的暈染，跟通用
     範本沒什麼差異。改成登入頁專屬的品牌背景——莫蘭迪綠（--accent）
     跟暖橘（--side）兩色對角暈開，比主畫面本身更有存在感，但維持
     同一組色票，不是另外調一組更飽和的漸層色。卡片浮在這個背景上，
     跟「App內部」的白卡片-灰底層次做出區隔，一眼就知道「這是入口」。 */
  background:
    radial-gradient(ellipse 620px 480px at 12% -8%, color-mix(in srgb, var(--accent) 30%, transparent), transparent 65%),
    radial-gradient(ellipse 560px 460px at 100% 100%, color-mix(in srgb, var(--side) 26%, transparent), transparent 62%),
    var(--bg);
  padding: 24px 16px;
}
.login-card {
  width: 100%;
  max-width: 360px;
  text-align: center;
  padding: 32px 24px 28px;
  position: relative;
  overflow: hidden;
}
/* 卡片頂緣一條很細的雙色漸層線——唯一「裝飾性」的元素，刻意做得很窄
   （3px），是品牌識別不是搶戲的裝飾條。 */
.login-card::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--accent), var(--side));
}
.login-mark {
  display: flex;
  justify-content: center;
  margin-bottom: 12px;
}
/* 圖示本身放進一個柔和的圓形底，比單獨一株植物飄在空中更有「標誌」的
   份量感——底色用side-light（暖橘的淺色版），跟綠色的植物形成App
   自己的兩色語言，不是隨便挑一個中性灰底。 */
.login-mark-badge {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--side-light), var(--accent-light) 80%);
  display: flex;
  align-items: center;
  justify-content: center;
}
/* 小植物非常輕微的呼吸感——4秒一個循環、只放大3%，比 streak-plant 或
   打勾動畫都慢很多，安靜地「活著」而不是引人注意的效果。 */
.login-mark svg {
  animation: login-mark-breathe 4s ease-in-out infinite;
  transform-origin: 50% 100%;
}
@keyframes login-mark-breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.03); }
}
@media (prefers-reduced-motion: reduce) {
  .login-mark svg { animation: none; }
}
.app-title {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 600;
  color: var(--accent-dark);
  margin: 0 0 4px;
  letter-spacing: -0.02em;
}
/* 標題下方的溫柔副標，跟下面「輸入Email和密碼登入」這種功能性說明文字
   分開——這句是語氣、不是操作指引，用斜體+更淡的顏色跟功能文字拉開一點
   視覺距離，但字級不縮小太多，維持「安靜但看得清楚」。 */
.login-tagline {
  color: var(--text-muted);
  margin: 0 0 10px;
  font-size: 14px;
  font-style: italic;
  opacity: 0.85;
}
.app-subtitle {
  color: var(--text-muted);
  margin: 0 0 20px;
  font-size: 14px;
}
#login-password-form,
#login-email-form,
#login-code-form,
#login-signup-form,
#signup-code-form,
#set-password-form,
#add-task-form,
#task-note-form,
#training-running-form {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* 每日提醒設定：開關列沿用主畫面同一套.task-check打勾框，跟整個App
   打勾的手感是同一種語言，不是另外生一個switch元件。 */
.notify-toggle-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 10px;
  text-align: left;
}
.notify-time-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 14px;
}
.notify-time-row label {
  font-size: 14px;
  color: var(--text);
}
#notify-time-input {
  width: auto;
}
/* 原本每個表單的 input 都用 id 一個一個列出來套樣式，新增註冊表單
   （#signup-email 那組）跟單次任務表單時漏了加，變成完全沒套到樣式、
   長得跟瀏覽器預設一樣醜——改用 type 屬性選取，同一類輸入框自動套用，
   不用每加一個表單就要記得回來加一次 id。 */
/* 故意不加 #app 這種 id 前綴——id 選擇器權重太高，會蓋過後面
   .edit-task-row input / .goal-card input 那些更小顆的表單樣式，
   讓它們沒辦法照原本設計顯示成比較小的輸入框。這裡靠「寫在前面、
   權重打平」讓後面那些更明確的規則能照 CSS cascade 正常覆蓋過去。 */
input[type="email"],
input[type="password"],
input[type="text"],
input[type="time"],
input[type="date"],
input[type="number"],
select,
textarea {
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--border);
  font-size: 15px;
  background: var(--bg);
  color: var(--text);
}
textarea {
  font-family: inherit;
  resize: vertical;
  line-height: 1.4;
}
#login-code {
  font-size: 22px;
  letter-spacing: 6px;
  text-align: center;
}
.login-code-hint {
  font-size: 13px;
  color: var(--text-muted);
  margin: 0 0 2px;
}
.login-status {
  margin-top: 12px;
  font-size: 13px;
  color: var(--text-muted);
  min-height: 18px;
}

/* ---------- 新手引導（Phase 3，2026-08-30新增）---------- */
/* 跟登入頁同一種「置中卡片、輕微暈染背景」的沉靜語氣，不是花俏的
   分步進度條精靈——溫和、低壓力，符合「不製造焦慮」的原則。 */
.view#view-onboarding {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(ellipse 600px 400px at 50% -10%, var(--accent-light), transparent 70%), var(--bg);
  padding: 24px;
}
.onboarding-wrap {
  width: 100%;
  max-width: 380px;
  text-align: center;
}
.onboarding-step h1 {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 600;
  color: var(--accent-dark);
  margin: 0 0 8px;
  letter-spacing: -0.01em;
}
.onboarding-hint {
  color: var(--text-muted);
  font-size: 13.5px;
  margin: 0 0 20px;
  line-height: 1.5;
}
.onboarding-goal-input {
  width: 100%;
  margin-bottom: 8px;
}
#btn-onboarding-add-goal {
  display: block;
  margin: 4px auto 20px;
}
.onboarding-time-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  text-align: left;
}
.onboarding-time-row:last-child { border-bottom: none; }
.onboarding-time-name {
  font-weight: 600;
  color: var(--text);
  flex: 1 1 100%;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* 2026-09-08：類型從原本旁邊一顆不起眼的小select，升格成這一步真正的
   主要決定（直接決定schedule_type，見app.js onboardingTypeToScheduleFields），
   改成自己佔一整行、跟目標名稱同寬，不再跟時間下拉擠在同一排搶視覺
   份量。原本這裡還有一組「每天固定做一點／本週自己抓時間」的二選一
   按鈕（.onboarding-kind-toggle），跟類型是同一件事問兩次，這次拿掉，
   併進類型單一選擇裡。 */
.onboarding-type-select { flex: 1 1 100%; }
.onboarding-time-select { flex-shrink: 0; margin-left: auto; }
.onboarding-primary-btn { width: 100%; margin-top: 20px; }
.onboarding-skip-btn { display: block; margin: 20px auto 0; }
.setup-notice {
  max-width: 440px;
  margin: 60px auto;
  padding: 24px;
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.setup-notice code {
  background: var(--accent-light);
  padding: 2px 6px;
  border-radius: 6px;
}

/* ---------- 按鈕 ---------- */
/* 所有按鈕都是<button>元素，這裡用元素選擇器一次蓋到，不用每個.btn-*
   class各加一次——手機連點兩下不會再觸發整頁放大，順便拿掉300ms點擊
   延遲，不影響捲動。 */
button {
  touch-action: manipulation;
}
.btn-primary {
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 12px;
  padding: 12px 16px;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, transform var(--dur-press) var(--ease-out);
}
.btn-primary:hover { background: var(--accent-dark); }
.btn-primary:active { transform: scale(0.97); }
.btn-secondary {
  background: var(--accent-light);
  color: var(--accent-dark);
  border: none;
  border-radius: 12px;
  padding: 10px 14px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  flex: 1;
  transition: background 0.15s ease, transform var(--dur-press) var(--ease-out);
}
.btn-secondary:hover { background: var(--border); }
.btn-secondary:active { transform: scale(0.97); }
.btn-link {
  background: none;
  border: none;
  color: var(--accent-dark);
  font-size: 14px;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 6px;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.btn-link:hover { opacity: 0.7; }
.btn-link:active { opacity: 0.5; }

/* 帳號設定裡表單存檔後的低調提示：不關掉整個modal，只在存檔按鈕旁邊
   淡入淡出「已儲存」，安靜、不打斷使用者接著改下一個欄位。 */
.form-saved-hint {
  margin-left: 8px;
  font-size: 13px;
  color: var(--success);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.form-saved-hint.is-visible { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .form-saved-hint { transition: none; }
}
/* 登入頁「還沒有帳號」跟「忘記密碼改用驗證碼」兩個替代路徑的視覺層級：
   前者是比較常見的路徑，維持一般連結重量；後者只在忘記密碼時才會用到，
   用上方一條淡分隔線+縮小字級+降到 text-muted 跟主要路徑拉開層次，
   不是兩顆長得一樣的文字擠在一起。 */
.login-alt-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  margin-top: 2px;
}
.login-alt-actions .login-alt-secondary {
  color: var(--text-muted);
  font-size: 12.5px;
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
  width: 100%;
}
.btn-icon {
  background: var(--accent-light);
  border: none;
  border-radius: 10px;
  width: 34px;
  height: 34px;
  font-size: 16px;
  color: var(--accent-dark);
  cursor: pointer;
  transition: background 0.15s ease, transform var(--dur-press) var(--ease-out);
}
.btn-icon:hover:not(:disabled) { background: var(--border); }
.btn-icon:active:not(:disabled) { transform: scale(0.92); }
.btn-icon:disabled { opacity: 0.35; cursor: default; }
.btn-tiny {
  background: none;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
  font-size: 12px;
  color: var(--text-muted);
  cursor: pointer;
  transition: background 0.15s ease;
}
.btn-tiny:hover { background: var(--accent-light); }
.btn-tiny:active { transform: scale(0.94); }
.segmented-btn:active { transform: scale(0.97); }

/* 鍵盤操作的 focus 樣式——滑鼠點擊不會出現，只有 Tab 鍵切換焦點時才顯示，
   兼顧美觀跟無障礙操作。 */
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- 主畫面 header ---------- */
.main-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  row-gap: 8px;
  margin-bottom: 14px;
}
/* 子頁面（編輯模板/編輯目標/歷史紀錄/每日固定清單/進度總覽）的 header
   是「← 返回」+ 標題 + 空白 span 三個元素，原本用 flex space-between 排，
   左邊按鈕文字寬度跟右邊空 span 不對稱，標題視覺上會偏一邊、不是真正
   置中。只有這幾頁需要「三等份、標題永遠置中」，首頁的 header（標題+
   右邊一排控制項，只有兩個子元素）不要套用，不然版面會跑掉。 */
.subpage-header {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  justify-content: initial;
}
.subpage-header > *:first-child { justify-self: start; }
.subpage-header > *:last-child { justify-self: end; }
.app-title-sm {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--accent-dark);
  margin: 0;
  letter-spacing: -0.01em;
}
.header-right {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  row-gap: 6px;
  gap: 10px;
}
.streak-label {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 13px;
  color: var(--accent-dark);
  background: var(--accent-light);
  border-radius: 999px;
  padding: 4px 10px;
  font-variant-numeric: tabular-nums;
}
.streak-plant {
  flex-shrink: 0;
}
.btn-lang {
  background: var(--accent-light);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
  font-size: 12px;
  font-weight: 600;
  color: var(--accent-dark);
  cursor: pointer;
}
.lang-switch-row {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 4px;
}

/* ---------- 今日總覽 hero（日期切換 + 完成度合併成一張卡） ----------
   原本日期切換跟完成度是兩張長得一模一樣的白色圓角卡疊在一起，是最容易
   讓整個畫面看起來像樣板產生的地方——現在合併成一張，中間用一條分隔線
   隔開「切換日期」跟「今天做得怎樣」兩個子區塊，完成分數用 serif 展示
   字體放大當作視覺焦點，不再跟其他卡片長得一模一樣。 */
.today-hero {
  position: relative;
  padding: 18px 18px 16px;
}
/* 2026-09修：改成三欄grid，左右兩欄用同一個固定寬度（64px，剛好夠放
   右欄「›」+「⋯」兩顆），日期才會落在卡片正中央——原本用flex
   space-between排四個元素，右邊比左邊多一顆按鈕，中間的日期看起來
   會偏左。 */
.date-nav {
  display: grid;
  grid-template-columns: 64px 1fr 64px;
  align-items: center;
}
.date-nav-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.date-nav-right {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
}
.date-label {
  font-size: 16px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
/* 2026-08-29新增：每日固定清單頁自己的小翻頁列，跟主畫面.date-nav同一種
   視覺語言但縮小版——這頁不是主畫面，不需要那麼搶眼，夠用就好。 */
.checklist-date-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 4px 0 10px;
}
.checklist-date-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
  min-width: 88px;
  text-align: center;
}
.hero-divider {
  height: 1px;
  background: var(--border);
  margin: 14px 0 12px;
}
/* 2026-09定稿：休息日切換不再佔一整排，收進date-nav那排最右邊一顆小
   圖示（跟btn-prev-day/btn-next-day同一列），標記後用強調色的圓點背景
   表示「現在是休息日」，不用再讀文字才知道狀態。長按#current-date-label
   是另一條路徑，見attachRestDayLongPress()。 */
.rest-day-toggle.is-active {
  background: var(--accent-light);
  color: var(--accent-dark);
}
.hero-rest-note {
  text-align: center;
  font-size: 12px;
  color: var(--text-muted);
  margin: 6px 0 0;
}
/* 休息日當天：ring track跟分隔線改用側色系（--side，App原本就有的焦糖
   色調），跟平常的鼠尾草綠做出區隔——不是「失敗的紅」，是「另一種狀態」
   的中性提示色。 */
.today-hero.hero-rest-day .hero-divider { background: var(--side-light); }
.today-hero.hero-rest-day .hero-ring-track { stroke: var(--side-light); }
.hero-stat {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.02em; /* 大字要收緊：字級一放大，字間看起來就會過鬆（Apple的光學字級原則），這是跟著字級走的值，不是全域一條 */
  font-variant-numeric: tabular-nums;
  color: var(--accent-dark);
  text-align: center;
  margin-bottom: 10px;
  transition: color 0.3s ease;
}

/* 一天全部打勾的小慶祝——這個 App 唯一特意安排的動畫時刻，其他地方
   維持安靜，才不會變成到處閃來閃去的樣板特效。hero-complete 是完成後
   留下的常駐狀態（分數變成強調色），hero-celebrate 只在「剛好達成」
   那一瞬間播放一次跳動+光暈，播完就拿掉，不會一直重複。 */
.today-hero.hero-complete .hero-stat {
  color: var(--success);
}
.today-hero.hero-celebrate {
  animation: hero-celebrate 0.7s ease;
}
@keyframes hero-celebrate {
  0% { transform: scale(1); box-shadow: var(--shadow); }
  35% { transform: scale(1.03); box-shadow: 0 0 0 6px color-mix(in srgb, var(--success) 25%, transparent); }
  100% { transform: scale(1); box-shadow: var(--shadow); }
}
/* ---------- 今日完成度環形進度條 ----------
   從文字+線性進度條改成環形（circular progress），視覺焦點更集中在
   「今天做得怎樣」這件事上。圓環用 stroke-dasharray/dashoffset 畫出
   進度，起點旋轉到12點鐘方向（.hero-ring 的 rotate(-90deg)）。
   漸層沿用既有 accent 色系，達成100%時整條環換成 success 綠色漸層
   （用 ring-done class 切換 stroke，不是另外加新顏色）。 */
.hero-ring-wrap {
  position: relative;
  width: 128px;
  height: 128px;
  margin: 2px auto 6px;
}
.hero-ring {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}
.hero-ring-stop-a { stop-color: var(--accent); }
.hero-ring-stop-b { stop-color: var(--accent-dark); }
.hero-ring-stop-success-a { stop-color: var(--success); }
.hero-ring-stop-success-b { stop-color: color-mix(in srgb, var(--success) 70%, black); }
.hero-ring-track {
  fill: none;
  stroke: var(--accent-light);
  stroke-width: 10;
}
.hero-ring-fill {
  fill: none;
  stroke-width: 10;
  stroke-linecap: round;
  stroke: url(#hero-ring-gradient);
  /* dasharray 由 JS 依圓周長設定；dashoffset 隨完成度推進，帶一點
     「衝過頭再穩下來」的收尾，跟原本線性進度條的手感一致。 */
  transition: stroke-dashoffset 0.6s cubic-bezier(0.34, 1.32, 0.64, 1), stroke 0.3s ease;
}
.hero-ring-fill.ring-done {
  stroke: url(#hero-ring-gradient-success);
}
.hero-ring-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
}
.hero-ring-pct {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -0.02em; /* 大字要收緊：字級一放大，字間看起來就會過鬆（Apple的光學字級原則），這是跟著字級走的值，不是全域一條 */
  font-variant-numeric: tabular-nums;
  color: var(--accent-dark);
  transition: color 0.3s ease;
}
.today-hero.hero-complete .hero-ring-pct {
  color: var(--success);
}
.hero-ring-sub {
  font-size: 13px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
/* 剛好達成100%那一刻，百分比數字輕輕彈一下——跟 hero-celebrate（整張
   卡片的跳動+光暈）同時觸發，但這個只做給數字看，範圍更聚焦。 */
@keyframes hero-num-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.2); }
  100% { transform: scale(1); }
}
.hero-ring-pct.hero-num-pop {
  animation: hero-num-pop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@media (prefers-reduced-motion: reduce) {
  .hero-ring-fill { transition: none; }
  .hero-ring-pct.hero-num-pop { animation: none; }
}
.total-time-text {
  margin-top: 8px;
  font-size: 13px;
  color: var(--text-muted);
  text-align: center;
  font-variant-numeric: tabular-nums;
}
/* 2026-09-01「剩餘時間」/「最重要的事情」：跟total-time-text同一種安靜的
   輔助文字語言，不用色塊或警示色——這兩行只是回答「今天還要做什麼」，
   不是在催促。 */
.hero-remaining,
.hero-most-important {
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--text-muted);
  text-align: center;
}
.hero-most-important { color: var(--accent-dark); }

/* 「昨天→今天」：獨立於today-hero卡片之外，很小的一條，兩個數字平實
   並排，沒有進度條、沒有顏色警示——單純讓人感覺「昨天結束了，今天
   繼續」，不是待辦事項或壓力來源。 */
.yesterday-today-strip {
  display: flex;
  justify-content: center;
  gap: 28px;
  padding: 8px 0 4px;
  font-size: 12.5px;
  color: var(--text-muted);
}
.yt-block {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.yt-label { opacity: 0.75; }
.yt-value {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text);
}

/* 2026-09-01「繼續上次」：橫向捲動的小卡片，跟今日課表那排同一種視覺
   語言（不是checkbox、不是card陰影堆疊），點下去要嘛捲到今天清單裡的
   那一列、要嘛把它鎖進今天——「動作」比「資訊展示」更重要，所以做成
   按鈕而不是純文字列表。 */
.continue-strip { margin: 4px 0 14px; }
.continue-strip-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.continue-strip-list {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 2px 2px 4px;
}
.continue-card {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 12px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--card-bg);
  min-width: 100px;
  max-width: 160px;
  text-align: left;
  cursor: pointer;
  font: inherit;
  color: inherit;
  transition: border-color 0.15s ease;
}
.continue-card:hover { border-color: var(--accent); }
.continue-card-goal {
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.continue-card-next {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* 點「繼續上次」之後捲到那一列，短暫亮一下讓人知道「就是這個」——
   跟hero-celebrate同一種「很細微」的動畫份量，不是彩帶等級的效果。 */
.task-item.continue-highlight {
  animation: continue-flash 1.2s ease;
}
@keyframes continue-flash {
  0%, 100% { background: transparent; }
  20% { background: var(--accent-light); }
}

/* ---------- 新手一次性小提示（見app.js renderOnboardingHint）----------
   只教一句怎麼操作，比warning/deadline banner更輕：沒有邊框、用
   accent-light底色跟文字，看起來像提示不是警告，跟其餘卡片明確分開，
   不會被誤認成需要處理的事項。
   2026-09-08修：原本沿用.onboarding-hint這個名字，結果撞名——新手引導
   （view-onboarding）自己的步驟說明文字<p class="onboarding-hint">早就
   用同一個class名字（見上面登入頁附近那條規則），這裡的規則在原始碼
   裡排在後面，同specificity直接整條蓋掉，把引導頁每一步的說明文字變成
   一顆填色的膠囊框，而不是原本安靜的淡字說明。改名成.first-time-tip，
   跟引導頁那個完全獨立，不共用名字。 */
.first-time-tip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  background: var(--accent-light);
  border-radius: 10px;
  padding: 7px 8px 7px 12px;
  margin-bottom: 10px;
  font-size: 12px;
  color: var(--accent-dark);
}
.hint-dismiss {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border: none;
  background: none;
  color: inherit;
  opacity: 0.7;
  cursor: pointer;
  font-size: 12px;
  border-radius: 50%;
}
.hint-dismiss:hover { opacity: 1; background: color-mix(in srgb, var(--accent-dark) 14%, transparent); }

/* ---------- 一次性行動 deadline 提醒 ---------- */
.deadline-banner {
  background: var(--warning-bg);
  border: 1px solid var(--warning-border);
  border-radius: var(--radius);
  padding: 12px 14px;
  margin-bottom: 14px;
  font-size: 13px;
  color: var(--warning-text);
  line-height: 1.5;
}
.deadline-banner.overdue {
  background: var(--danger-bg);
  border-color: var(--danger-border);
  color: var(--danger-text);
}
.fatigue-reason { margin-top: 2px; opacity: 0.9; }
.fatigue-rest-day-btn {
  display: block;
  margin-top: 8px;
  color: var(--warning-text);
  border-color: var(--warning-border);
}

/* ---------- 今日金句 ---------- */
.quote-card {
  background: var(--accent-light);
  box-shadow: none;
}
.quote-text {
  font-size: 14px;
  font-style: italic;
  color: var(--accent-dark);
  line-height: 1.5;
}

/* 2026-09-01「當天課表直接顯示」：橫向捲動的時間軸小卡片，跟下面可打勾
   的任務清單刻意做出不同的視覺語言（沒有checkbox、沒有勾選動畫）—— 這
   是「參考用」的一眼看完，不是「要完成」的任務。 */
.today-schedule-strip {
  margin: 4px 0 14px;
}
.today-schedule-strip-list {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 2px 2px 4px;
  scrollbar-width: thin;
}
.today-schedule-pill {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 12px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--card-bg);
  min-width: 92px;
}
.today-schedule-pill-time {
  font-size: 11px;
  color: var(--text-muted);
  white-space: nowrap;
}
.today-schedule-pill-name {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
}
.today-schedule-pill.is-now {
  border-color: var(--accent);
  background: var(--accent-light);
}
.today-schedule-pill.is-now .today-schedule-pill-time,
.today-schedule-pill.is-now .today-schedule-pill-name {
  color: var(--accent-dark);
}

/* ---------- 本週目標進度 ---------- */
.goals-progress-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* 2026-09-01「全部累計」：純粹是次數/時數的總量，沒有一個「目標值」可以
   拿來畫進度條（跟goal-progress-row不一樣，那個是「這週完成幾成」有
   分母），所以做成單純的一行「名稱＋數字」，不套用進度條視覺，避免
   使用者誤以為這個數字有個隱含的100%終點。
   2026-09-11改：副專案（有total_target_sessions）跟CPE/AI Git（有總題庫/
   總課程長度）其實有明確分母了，加一行小字完成率——但不是每個項目都有
   （英文/健身這種開放式週目標沒有終點），所以主行維持原本的flex，
   完成率另外包一行小灰字，沒有targetTotal的項目就不會多印這一行。 */
.all-time-totals-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.all-time-total-row {
  display: flex;
  flex-direction: column;
  font-size: 13.5px;
  color: var(--text);
}
.all-time-total-main {
  display: flex;
  justify-content: space-between;
}
.all-time-total-value {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--accent-dark);
}
.all-time-total-percent {
  font-size: 11.5px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.goal-progress-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.goal-progress-label {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.goal-progress-label .gp-fraction {
  color: var(--text-muted);
}
.goal-progress-bar {
  width: 100%;
  height: 8px;
  background: var(--accent-light);
  border-radius: 999px;
  overflow: hidden;
}
.goal-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), var(--accent-dark));
  border-radius: 999px;
  transition: width 0.3s ease, background 0.3s ease;
}
.goal-progress-fill.gp-done {
  /* success也用漸層，同一個色相深淺變化，不是換一個完全不同的顏色家族 */
  background: linear-gradient(90deg, var(--success), color-mix(in srgb, var(--success) 70%, black));
}

.chart-title {
  font-size: 13px;
  color: var(--text-muted);
  margin-bottom: 10px;
}

/* 早餐卡片標題旁邊的「全部打勾/取消」——跟chart-title同一排，靠右，
   不佔額外一行。 */
.checklist-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.checklist-section-header .chart-title { margin-bottom: 0; }

/* 週摘要：三個統計並排（完成率/時間/連續天數），下面兩行文字補上
   「最佳日」「待加強」的具體內容——數字本身沒有情緒，配上這兩行才會
   有「這週過得怎樣」的具體感受，不只是又一組枯燥的百分比。 */
.wr-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-bottom: 12px;
}
.wr-stat {
  text-align: center;
  padding: 8px 4px;
  background: var(--bg);
  border-radius: 10px;
}
.wr-stat-label {
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 2px;
}
.wr-stat-value {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.wr-delta-slot { display: block; font-size: 11px; font-weight: 600; font-family: inherit; }
.wr-delta-up { color: var(--success); }
.wr-delta-down { color: var(--danger-text); }
.wr-delta-flat { color: var(--text-muted); }
.wr-line {
  font-size: 13px;
  color: var(--text);
  margin: 4px 0;
}

/* 體能突破面板：一個項目（跑步配速、或某個健身動作）一塊，標題+目前
   最佳紀錄並排，底下一條迷你折線圖——不用完整座標軸/圖例的正式圖表，
   維持「一眼看完」的sparkline定位。 */
.perf-block { margin-bottom: 14px; }
.perf-block:last-child { margin-bottom: 0; }
.perf-block-header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 13px;
  margin-bottom: 4px;
}
.perf-block-title { color: var(--text); font-weight: 600; }
.perf-block-best { color: var(--side); font-weight: 600; font-variant-numeric: tabular-nums; }
.perf-sparkline { width: 100%; height: 48px; display: block; }
.pr-badge { font-size: 11px; }
.perf-block-1rm {
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.perf-volume-chart { width: 100%; height: 60px; display: block; }
.compile-notes-select { width: 100%; margin-bottom: 10px; }

.rollover-task-list {
  text-align: left;
  max-height: 200px;
  overflow-y: auto;
  margin: 12px 0;
  font-size: 13px;
  color: var(--text);
}
.rollover-task-row { padding: 4px 0; }

.add-task-knapsack-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.add-task-knapsack-row label {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 11px;
  color: var(--text-muted);
}
.add-task-knapsack-row input { width: 100%; }

.knapsack-result { text-align: left; margin: 10px 0; font-size: 13px; }
.knapsack-summary { font-weight: 700; color: var(--text); margin-bottom: 6px; }
.knapsack-item-row { color: var(--text-muted); padding: 2px 0; }

/* 2026-08-30 Phase 4：這幾個原本各自是獨立.card，現在收進主畫面的
   「更多記錄」收合區塊(.main-secondary-section)裡——拿掉個別的卡片
   外框，改用上邊界線分隔，看起來是同一區塊裡的幾組小段落，不是三張
   疊在一起的卡片，跟帳號設定modal裡多個設定群組並排在同一個
   .modal-section的視覺語言一致。 */
.main-secondary-section .market-note-card,
.main-secondary-section .reflection-card {
  padding-top: 14px;
  border-top: 1px solid var(--border);
}
.main-secondary-section .market-note-card:first-of-type {
  padding-top: 0;
  border-top: none;
}
.market-note-card { margin-bottom: 14px; }
.market-sentiment-toggle {
  display: flex;
  gap: 8px;
  margin-bottom: 8px;
}
.market-sentiment-btn {
  flex: 1;
  padding: 8px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text-muted);
  font-size: 13px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.market-sentiment-btn.is-active {
  background: var(--accent-light);
  border-color: var(--accent);
  color: var(--accent-dark);
  font-weight: 700;
}
#market-note-input { width: 100%; }

.reflection-card { margin-bottom: 14px; }

/* 2026-09-01「今日時間軸」：純文字直向清單，不是有刻度/比例的視覺時間軸——
   資料量本來就小（一天頂多十幾件事），做成真正按比例排版的時間軸反而
   小題大作，一條簡單的「時間+名稱」列表已經足夠回答「今天花在哪裡」。 */
.timeline-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.timeline-row {
  display: flex;
  gap: 10px;
  align-items: baseline;
  font-size: 13px;
}
.timeline-clock {
  flex-shrink: 0;
  width: 40px;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  font-size: 12px;
}
.timeline-name { color: var(--text); }
.timeline-row.is-done .timeline-name { color: var(--text-muted); }
.timeline-empty {
  font-size: 12.5px;
  color: var(--text-muted);
}
.timeline-untimed {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
}
.timeline-untimed-title {
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 4px;
}
.timeline-untimed-item {
  font-size: 12.5px;
  color: var(--text-muted);
  padding-left: 50px;
}
.mood-toggle {
  display: flex;
  gap: 6px;
  margin-bottom: 8px;
  flex-wrap: wrap; /* 四個按鈕在窄螢幕不會硬擠成一排，跟header的跑版修法同一招 */
}
.mood-btn {
  flex: 1;
  min-width: 70px;
  padding: 8px 4px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text-muted);
  font-size: 13px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.mood-btn.is-active {
  background: var(--accent-light);
  border-color: var(--accent);
  color: var(--accent-dark);
  font-weight: 700;
}
#reflection-note-input { width: 100%; }

.github-tree-svg { display: block; }
.github-tree-label { font-size: 11px; fill: var(--text-muted); font-family: var(--font-mono, monospace); }

.rpg-level-text {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--accent-dark);
  margin-bottom: 8px;
  text-align: center;
}
.rpg-radar-canvas { width: 100%; max-width: 240px; display: block; margin: 0 auto; }
.rpg-config {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--border);
}
.rpg-config label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: var(--text-muted);
  font-weight: 700;
}
.rpg-config input { flex: 1; min-width: 0; font-size: 12px; }

/* 語音輸入按鈕：辨識中用輕微的呼吸感脈動表示「正在聽」，跟登入頁植物
   呼吸動畫同一種語言，不是突兀的紅點錄音指示。 */
.voice-log-btn {
  display: block;
  margin: 0 0 10px;
}
.voice-log-btn.is-listening {
  color: var(--danger-text);
  animation: voice-pulse 1s ease-in-out infinite;
}
@keyframes voice-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}
.voice-log-status {
  font-size: 12px;
  color: var(--text-muted);
  margin: -4px 0 10px;
}

/* 滑動中的背景色提示：右滑（完成）帶一點success綠、左滑（開備註）帶
   一點accent色——只是簡化版的「這一列本身變色」，不是iOS Mail那種
   在底下另外露出一層背景色塊，維持這個App一貫「不做過度雕琢動畫」
   的原則，但足以讓使用者知道「滑到這個距離會觸發哪個動作」。 */
.task-item.swiping-right { background: color-mix(in srgb, var(--success) 16%, var(--card-bg)); }
.task-item.swiping-left { background: color-mix(in srgb, var(--accent) 16%, var(--card-bg)); }

/* 成就頁：一顆里程碑一列，達成的那幾列稍微亮一點（icon飽和、勾勾用
   success色），沒達成的維持安靜的灰階——不用進度條/等級條這種遊戲化
   包裝，單純清單勾選，符合使用者不要做成幼稚遊戲的要求。 */
.achievements-progress {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 12px;
}
.achievements-list { display: flex; flex-direction: column; gap: 2px; }
.achievement-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 4px;
  border-bottom: 1px solid var(--border);
  opacity: 0.55;
}
.achievement-row:last-child { border-bottom: none; }
.achievement-row.achievement-done { opacity: 1; }
.achievement-icon { font-size: 20px; flex-shrink: 0; }
.achievement-text { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.achievement-title { font-size: 14px; font-weight: 600; color: var(--text); }
.achievement-desc { font-size: 12px; color: var(--text-muted); }
.achievement-mark {
  font-size: 15px;
  font-weight: 700;
  color: var(--text-muted);
  flex-shrink: 0;
}
.achievement-row.achievement-done .achievement-mark { color: var(--success); }

/* ---------- 歷史紀錄頁：週/月分頁 ---------- */
.segmented {
  display: flex;
  background: var(--accent-light);
  border-radius: 999px;
  padding: 3px;
  margin-bottom: 14px;
}
.segmented-btn {
  flex: 1;
  border: none;
  background: none;
  padding: 8px 0;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  /* text-muted 在 accent-light 底色上只有4.2:1，低於本文最低4.5:1標準
     （量過：淺色4.22、深色4.17），改用 --text 保持在9:1以上——用透明度調暗
     一開始也試過，但透明度會把文字顏色往底色混，算出來反而只剩3.2~4.4:1，
     一樣不合格，所以維持滿opacity，靠 active 狀態的白底+陰影去做區分就夠。 */
  color: var(--text);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, transform var(--dur-press) var(--ease-out);
}
.segmented-btn.active {
  background: var(--card-bg);
  color: var(--accent-dark);
  box-shadow: var(--shadow);
}
.history-panel {
  display: flex;
  flex-direction: column;
}

/* 統計類卡片（月熱力圖／本週目標進度／時間分配）用扁平、有邊框、無陰影的
   版本跟上面「今日總覽」「任務清單」這種可互動的區塊區分開——陰影代表
   「可以動的東西」，純資訊區塊不需要浮起來，也順便打破整頁卡片長得
   一模一樣的樣板感。 */
.stat-card {
  box-shadow: none;
  border: 1px solid var(--border);
}

/* 可拖拉排版的儀表板卡片（歷史紀錄月分頁）：桌面滑鼠拖拉排序，手機
   （原生HTML5拖放API本來就不支援觸控）只會看到那顆手把圖示、拖不動，
   不影響卡片本身正常顯示內容。 */
.dashboard-widget {
  position: relative;
  cursor: grab;
}
.dashboard-widget.dashboard-dragging {
  opacity: 0.4;
}
.insight-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
}
.insight-icon { font-size: 16px; flex-shrink: 0; }
.insight-text { display: flex; flex-direction: column; }
.insight-label { font-size: 13px; font-weight: 600; color: var(--text); }
.insight-detail { font-size: 12px; color: var(--text-muted); font-variant-numeric: tabular-nums; }

.dashboard-drag-handle {
  position: absolute;
  top: 10px;
  right: 12px;
  font-size: 12px;
  color: var(--text-muted);
  opacity: 0.5;
  letter-spacing: -2px;
}

/* ---------- 近 30 天熱力圖 ----------
   跟 GitHub 貢獻圖、習慣追蹤 App 常見的月曆熱力圖同一個概念：7 欄對應
   星期日~星期六，顏色深淺代表當天完成率，一眼就能看出最近的規律或斷點，
   比原本一週 7 根長條圖能看到的範圍多了將近 4 倍。 */
/* 卡片標題+30/60/90範圍切換同一行——切換鈕是次要控制項，用比週/月分頁
   小一號的.segmented-sm，不會搶走「近X天完成狀況」這個標題的視覺重量。 */
.heatmap-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}
.heatmap-card-header .chart-title { margin-bottom: 0; }
/* 全部累計的自訂範圍：兩個日期輸入框+一條分隔線，跟.segmented-sm同一排
   節奏，只在選到「自訂」分頁時才出現（見app.js的switchAllTimeTotalsRange）。 */
.atr-custom-range {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.atr-custom-range input[type="date"] { flex: 1; min-width: 0; font-size: 13px; }
.atr-custom-sep { color: var(--text-muted); flex-shrink: 0; }

/* 報表匯出的起迄選擇——跟上面atr-custom-range同一種排法，但這裡永遠
   顯示（不是選到某個分頁才出現），另外多一排快捷按鈕。 */
.export-range-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}
.export-range-row input[type="date"] { flex: 1; min-width: 0; font-size: 13px; }
.export-range-sep { color: var(--text-muted); flex-shrink: 0; }
.export-range-presets {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}
.export-range-presets button { flex: 1; min-width: 70px; padding: 6px 8px; font-size: 13px; }
.segmented-sm {
  padding: 2px;
  width: auto;
}
.segmented-sm .segmented-btn {
  flex: none;
  padding: 4px 10px;
  font-size: 12px;
}
.month-heatmap {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 5px;
}
.heatmap-cell {
  aspect-ratio: 1;
  border-radius: 5px;
  background: var(--accent-light);
  cursor: pointer;
  /* 2026-09拿掉逐格進場動畫（原本用--cell-i算出的stagger delay一格格
     浮現）——熱力圖格數多，逐格animation是渲染時真實量得到的延遲來源，
     直接拿掉，格子一次到位。 */
  transition: transform var(--dur-press) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
/* 觸控裝置點一下會觸發一次假的:hover，效果會黏在原地不走（手指離開
   螢幕不算mouseleave）。只有真的有滑鼠指標時才給這種會動/會浮起來的
   回饋，觸控裝置靠:active就夠了。 */
@media (hover: hover) and (pointer: fine) {
  .heatmap-cell:hover { transform: scale(1.15); }
}
.heatmap-cell.heatmap-selected {
  box-shadow: 0 0 0 2px var(--accent-dark);
}
.heatmap-filler {
  background: transparent;
  cursor: default;
}
.heatmap-level-1 { background: color-mix(in srgb, var(--accent) 30%, var(--accent-light)); }
.heatmap-level-2 { background: color-mix(in srgb, var(--accent) 55%, var(--accent-light)); }
.heatmap-level-3 { background: color-mix(in srgb, var(--accent) 78%, var(--accent-light)); }
.heatmap-level-4 { background: var(--accent); }
/* 休息日：用側色系（--side）的淡底＋小月亮圖案蓋掉原本的完成度色階，
   一眼就能跟「排了但沒做到」的空白/淡色格子分辨出來，不是同一種視覺。 */
.heatmap-rest {
  background: var(--side-light);
  position: relative;
}
.heatmap-rest::after {
  content: "🌙";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  opacity: 0.75;
}
.heatmap-today {
  box-shadow: inset 0 0 0 2px var(--accent-dark);
}
.heatmap-detail {
  margin-top: 10px;
  font-size: 12.5px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  min-height: 16px;
}
/* 完成任務清單那行：比日期/百分比那行再淡一點、字級再小一點，
   份量上明顯是「補充細節」而不是主要資訊，長清單自然換行不截斷。 */
.heatmap-detail-tasks {
  margin-top: 3px;
  font-size: 11.5px;
  color: var(--text-muted);
  opacity: 0.85;
  font-variant-numeric: normal;
  line-height: 1.5;
}
.heatmap-detail-reflection {
  margin-top: 6px;
  font-size: 12px;
  color: var(--text);
  font-variant-numeric: normal;
  font-style: italic;
}
.heatmap-jump-btn {
  display: block;
  margin-top: 8px;
  padding: 0;
  font-size: 12px;
}

/* ---------- 本週時間分配（核心 / 加分） ---------- */
.split-bar {
  display: flex;
  width: 100%;
  height: 10px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--accent-light);
}
.split-segment {
  height: 100%;
}
.split-segment.split-core { background: var(--accent); }
.split-segment.split-side { background: var(--side); }
.split-legend {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--text-muted);
  flex-wrap: wrap;
}
.split-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-variant-numeric: tabular-nums;
}
.split-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
}
.split-dot-core { background: var(--accent); }
.split-dot-side { background: var(--side); }

/* ---------- 任務清單 ---------- */
.task-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}
.btn-add-task {
  display: block;
  width: 100%;
  background: none;
  border: 1px dashed var(--border);
  border-radius: 12px;
  padding: 10px;
  margin-bottom: 16px;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent-dark);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.btn-add-task:hover {
  background: var(--accent-light);
  border-color: var(--accent);
}
/* 2026-09定稿：「今天臨時加一件」＋knapsack小連結放一起，knapsack不再
   是常駐大按鈕（拿掉了原本的.btn-cta-schedule實心強調樣式），只是
   旁邊一顆不搶眼的文字連結。 */
/* 今天頁最底下那排「每天的」checklist快速打勾——跟.checklist-row/
   .task-check是完全同一套視覺語言（借自每日固定清單頁），只是外面
   多包一層margin，跟上面task-list拉開一點距離。 */
.today-checklist-strip {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 4px 0 16px;
}
.today-checklist-more {
  align-self: center;
  font-size: 12px;
}
.add-task-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 16px;
}
.add-task-row .btn-add-task { margin-bottom: 0; }
.add-task-row .btn-link {
  align-self: center;
  font-size: 12px;
}
.task-item {
  touch-action: manipulation; /* 任務列連點兩下不放大；.task-item本來就有左右滑動手勢，manipulation不影響單指滑動/捲動 */
  display: flex;
  flex-wrap: wrap; /* 平常一行排完；.task-item-actions展開時用flex-basis:100%自己跳下一行 */
  align-items: center;
  gap: 12px;
  background: var(--card-bg);
  border-radius: 14px;
  padding: 12px 14px 12px 17px; /* 左邊多留 3px 給 ::before 那條分類色條 */
  box-shadow: var(--shadow);
  cursor: pointer;
  /* 整列本來就是<label>包住checkbox，點哪裡都能切換——這裡只是手機觸控
     的細節：拿掉手機瀏覽器預設的灰色點擊高亮方塊，改用自己的:active
     縮放回饋；user-select擋掉長按選字的殘影，快速連續點幾行也不會
     不小心選到文字。 */
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
  transition: box-shadow var(--dur-fast) var(--ease-out), opacity var(--dur-base) var(--ease-out), transform var(--dur-press) var(--ease-out);
  /* 手機滑動手勢（右滑完成/左滑開備註）：告訴瀏覽器垂直方向自己處理
     （原生捲動維持順暢），水平方向交給JS的touchmove判斷，兩邊分工不
     互相干擾。滑動時的transform由JS直接設定inline style，優先權比這裡
     的transition高，不會互相打架。 */
  touch-action: pan-y;
  /* 換日期／重新渲染時整份清單由上往下依序浮現。--stagger 由 JS 逐列遞增
     設定；這是整個 App 唯一一段編排過的進場動畫，其餘互動都只做單點回饋，
     不到處灑特效。單一列 0.2s，跟modal/切頁同一個「單一轉場≤220ms」的
     份量級距，只是整組疊加stagger delay看起來像一道波。 */
  animation: task-enter var(--dur-base) var(--ease-out) backwards;
  animation-delay: var(--stagger, 0ms);
}
@keyframes task-enter {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
/* 由 renderTaskList() 在「同一天原地重繪」時掛上（例如存了一則備註、改了
   今天份量）。那種情況清單內容沒有換成另一批，重播一次進場波等於在解釋
   一件沒發生的事，而且每做一件小事整個清單閃一次很吵。只有換到另一天
   ／第一次畫才播。 */
#task-list.no-enter-anim .task-item {
  animation: none;
}
/* 觸控裝置點一下會觸發一次假的:hover，效果會黏在原地不走（手指離開
   螢幕不算mouseleave）。只有真的有滑鼠指標時才給這種會動/會浮起來的
   回饋，觸控裝置靠:active就夠了。 */
@media (hover: hover) and (pointer: fine) {
  .task-item:hover:not(.rolled-forward) {
    box-shadow: 0 4px 14px rgba(60, 50, 30, 0.12);
  }
}
.task-item:active:not(.rolled-forward) {
  transform: scale(0.99);
}
.task-item.done {
  opacity: 0.55;
}
/* Vim風格鍵盤導覽的焦點框——用外框+輕微位移表示「現在鍵盤操作的是這一
   列」，不是搶眼的滿版變色，維持這個App一貫低調的互動回饋語言。 */
.task-item.vim-focused {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
/* 自訂打勾框：保留真正的 <input> 負責鍵盤操作跟無障礙語意，只是把它畫成
   透明的、疊在自己畫的圓框上面。這樣才有辦法讓勾勾用「畫出來」的方式出現
   （stroke-dashoffset 動畫），原生 checkbox 是瞬間跳出來的、沒有這個空間。 */
.task-check {
  touch-action: manipulation; /* 打勾框連點兩下不放大 */
  position: relative;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  display: grid;
  place-items: center;
}
.task-check input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
  width: 22px;
  height: 22px;
  border: 1.8px solid var(--border);
  border-radius: 7px;
  background: transparent;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease, transform var(--dur-press) var(--ease-out);
}
.task-check input[type="checkbox"]:hover:not(:disabled) {
  border-color: var(--accent);
}
.task-check input[type="checkbox"]:active:not(:disabled) {
  transform: scale(0.9);
}
.task-check input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.task-check input[type="checkbox"]:checked {
  background: var(--accent);
  border-color: var(--accent);
}
.task-check-mark {
  position: absolute;
  width: 15px;
  height: 15px;
  color: #fff;
  pointer-events: none;
}
.task-check-mark path {
  /* 路徑總長約 16，先整條偏移出去藏起來，打勾時再收回 0 = 一筆畫出勾勾 */
  stroke-dasharray: 16;
  stroke-dashoffset: 16;
  transition: stroke-dashoffset 0.22s cubic-bezier(0.65, 0, 0.35, 1);
}
.task-check input[type="checkbox"]:checked ~ .task-check-mark path {
  stroke-dashoffset: 0;
}

/* 任務內容：名字是主角，補進度標記貼在名字下面當註腳 */
.task-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.task-name {
  font-size: 14px;
  line-height: 1.35;
  /* 劃線用一條「畫出來」的底線，不是瞬間出現的text-decoration：
     text-decoration-line在大多數瀏覽器上沒辦法平滑transition，換成
     單條linear-gradient當背景、animate它的background-size——跟
     checkbox勾勾用stroke-dashoffset「畫出來」是同一套視覺語言，
     打勾/取消勾都是同一條線平滑伸縮，不是瞬間切換。 */
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 55%;
  background-size: 0% 1.5px;
  transition: background-size 0.35s ease;
}
/* UVa題號連結：低調的底線+略深一階的字色，看得出可以點，但不搶走
   任務名稱本身的視覺重量——不是常見那種顯眼的品牌藍色連結。 */
.uva-link {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-underline-offset: 2px;
}
.uva-link:hover { color: var(--accent-dark); }

.task-item.done .task-name {
  background-size: 100% 1.5px;
}
@media (prefers-reduced-motion: reduce) {
  .task-name { transition: none; }
}
/* 任務分類小標籤：目標名稱過雜湊自動決定色相（--tag-hue），同一個目標
   永遠同一個顏色，不用維護對照表。沒有掛目標的任務退回核心/加分既有的
   兩個色調（.task-tag-fixed，用--tag-fixed-color）。淺色模式用淡底深字，
   深色模式反過來，兩邊都刻意壓低飽和度避免太搶眼——這只是輔助辨識用的
   小標籤，不是要吸走整列的注意力。 */
.task-tag {
  align-self: flex-start;
  font-size: 10px;
  font-weight: 700;
  line-height: 1.4;
  padding: 1px 7px;
  border-radius: 999px;
  background: hsl(var(--tag-hue, 140) 40% 90%);
  color: hsl(var(--tag-hue, 140) 40% 32%);
}
@media (prefers-color-scheme: dark) {
  .task-tag { background: hsl(var(--tag-hue, 140) 26% 22%); color: hsl(var(--tag-hue, 140) 45% 78%); }
}
.task-tag.task-tag-fixed {
  background: color-mix(in srgb, var(--tag-fixed-color) 16%, var(--card-bg));
  color: var(--tag-fixed-color);
}
.task-catchup {
  font-size: 11px;
  font-weight: 600;
  color: var(--warning-text);
  background: var(--warning-bg);
  border-radius: 999px;
  padding: 1px 7px;
  align-self: flex-start;
}
/* 2026-08-30拿掉了原本的.task-note-preview自動預覽行規則——不分任務
   類型，note一律只透過📝按鈕點開才看得到，維持外面版面乾淨（見app.js
   buildTaskItem的說明）。 */
/* 2026-09-01「長期目標→今日任務」視覺連結：只有journey型目標（副專案/
   AI Git/CPE暑假衝刺）才會有這一行，一條很細的進度條+分數，不用顏色
   強調、不用百分比數字搶眼——這是「你正在往哪裡走」的安靜提示，不是
   另一個要盯著看的KPI。 */
.task-journey {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 3px;
}
.task-journey-frac {
  font-size: 10.5px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.task-journey-bar {
  flex: 1;
  max-width: 80px;
  height: 3px;
  border-radius: 2px;
  background: var(--border);
  overflow: hidden;
}
.task-journey-bar-fill {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: 2px;
}
/* 時間移到最右邊、等寬數字對齊——原本擺在名字左邊，每列的任務名稱起點
   會因為時間字數不同而參差不齊，眼睛要重新找一次每列的開頭。 */
.task-time {
  font-size: 12px;
  color: var(--text-muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
/* 備註圖示：沒寫備註時很淡（只是一個「可以加備註」的暗示，不搶眼），
   寫過之後變成accent色、更明顯——用同一個按鈕表達兩種狀態，不用另外
   準備「+備註」文字按鈕佔位置，主畫面才不會被沒寫備註的任務洗版。 */
.task-note-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  /* 圖示本身維持13px不放大，但點擊區域用padding撐到接近44px的建議
     觸控大小——手機上這種小圖示按鈕最容易點不準。 */
  padding: 8px;
  margin: -8px -8px -8px 0;
  font-size: 13px;
  line-height: 1;
  opacity: 0.28;
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-press) var(--ease-out);
}
.task-note-btn:hover { opacity: 0.6; }
.task-note-btn:active { transform: scale(0.9); }
.task-note-btn.has-note { opacity: 0.85; }

/* 調整完成份數（✎）：只會出現在已完成的次數制任務上，跟task-note-btn
   同一種小圖示按鈕風格——沒有「有沒有標記」這種二態，維持單一透明度。 */
.task-count-edit-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 8px;
  margin: -8px -8px -8px 0;
  font-size: 13px;
  line-height: 1;
  opacity: 0.28;
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-press) var(--ease-out);
}
.task-count-edit-btn:hover { opacity: 0.6; }
.task-count-edit-btn:active { transform: scale(0.9); }

/* 「今天份量」（🔢）：打勾前調整今天要排多少，跟上面✎（調整完成份數）
   同一種小圖示按鈕風格、故意不同圖示——兩顆一個只在打完勾後出現、
   一個只在還沒打勾時出現，見canEditTodayQuantity()，不會同時出現在
   同一列上。 */
.task-quantity-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 8px;
  margin: -8px -8px -8px 0;
  font-size: 13px;
  line-height: 1;
  opacity: 0.28;
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-press) var(--ease-out);
}
.task-quantity-btn:hover { opacity: 0.6; }
.task-quantity-btn:active { transform: scale(0.9); }

/* 「今天份量」modal：輸入框+單位字+儲存鍵一排，跟補進度modal（單純
   輸入框上下疊按鈕）不同版面，因為這裡多一個要顯示的單位字
   （堂/題/分鐘）。 */
.today-quantity-form {
  display: flex;
  align-items: center;
  gap: 8px;
}
.today-quantity-form input {
  flex: 1;
  min-width: 0;
}
.today-quantity-unit {
  flex-shrink: 0;
  color: var(--text-muted);
  font-size: 14px;
}
.today-quantity-form .btn-primary {
  flex-shrink: 0;
}

/* 「今天最重要」星星——跟task-note-btn同一種小圖示按鈕風格，未標記時
   很淡（存在但不搶戲），標記後變實心黃色，一天只會有一顆亮著。 */
.task-priority-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 8px;
  margin: -8px -8px -8px 0;
  font-size: 13px;
  line-height: 1;
  opacity: 0.22;
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-press) var(--ease-out);
}
.task-priority-btn:hover { opacity: 0.55; }
.task-priority-btn:active { transform: scale(0.9); }
.task-priority-btn.is-active { opacity: 1; filter: drop-shadow(0 0 2px rgba(230, 180, 60, 0.5)); }
/* 鎖定今天優先：只會出現在目前被鎖定的那一列（見buildTaskItem），
   不像⭐是每一列都有、只是透明度不同——一開始就是滿opacity，點一下
   直接解鎖，不需要「淡到看不到」那種常駐視覺存在。 */
.task-lock-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 8px;
  margin: -8px -8px -8px 0;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  transition: transform var(--dur-press) var(--ease-out);
}
.task-lock-btn:active { transform: scale(0.9); }
/* 2026-09-08「今天想換一個」：跟星星/鎖頭不同，這顆帶著文字（目標
   名稱），是個小藥丸形狀的按鈕，不是純圖示——只在mutex規則今天真的排
   除了另一個目標時才出現（見buildTaskItem的shadowGoal判斷），不是常駐。 */
.task-swap-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--chrome-bg, var(--card-bg));
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 12px;
  color: var(--text-muted);
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-press) var(--ease-out);
}
.task-swap-btn:hover { color: var(--text); border-color: var(--accent); }
.task-swap-btn:active { transform: scale(0.94); }

/* 被標記的那一列本身也有一圈很淡的暖色外框，不搶過已完成/未完成的
   主要視覺，只是「這是今天優先」的安靜提示。 */
.task-item.task-flagged-important {
  box-shadow: var(--shadow), 0 0 0 1.5px rgba(230, 180, 60, 0.45);
}

/* 拖拉排序手把——只有「今日安排」（非固定課表）的列才有，跟dashboard
   小工具那組拖拉是同一種原生HTML5 DnD API，手機沒有dragstart事件，
   這顆手把在觸控裝置上看得到但拖不動，不影響其他任何功能。 */
.task-drag-handle {
  flex-shrink: 0;
  color: var(--text-muted);
  opacity: 0.35;
  font-size: 13px;
  cursor: grab;
  line-height: 1;
  letter-spacing: -2px;
}

/* 2026-09「外面只留打勾/名稱/時間」：星/鎖/備註/計時/沈浸/訓練/拖拉全部
   收進這個預設收合的動作列，用一顆「⋯」展開——跟task-item同一個flex
   容器，展開時flex-basis:100%讓它自己另起一行，不用另外開modal/popover。 */
.task-more-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 18px;
  line-height: 1;
  padding: 4px 6px;
  cursor: pointer;
  opacity: 0.6;
}
.task-more-btn:hover { opacity: 1; }
.task-item-actions {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 8px;
  margin-top: 4px;
  border-top: 1px solid var(--border);
}
.task-item-actions.hidden { display: none; }
.task-item.task-dragging {
  opacity: 0.4;
}

/* 任務備註的編輯/預覽分頁——兩顆並排的文字按鈕，選中的那顆用底線+
   加粗標示，跟.segmented-btn那套「圓角膠囊」視覺刻意不同，這裡只是
   單一modal內部的分頁切換，不需要那麼重的容器感。 */
.note-tabs {
  display: flex;
  gap: 16px;
  margin: 2px 0 8px;
  border-bottom: 1px solid var(--border);
}
.note-tab-btn {
  background: none;
  border: none;
  padding: 4px 2px 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.note-tab-btn:hover { color: var(--text); }
.note-tab-btn.is-active {
  color: var(--accent-dark);
  border-bottom-color: var(--accent);
  font-weight: 700;
}

/* 2026-09-01「本學期課表/下學期課表」分頁——跟note-tabs同一種視覺語言，
   直接沿用class名稱不同只是為了語意清楚（這是課表頁不是備註視窗）。 */
.edit-term-tabs {
  display: flex;
  gap: 16px;
  margin: 4px 0 6px;
  padding: 0 2px;
  border-bottom: 1px solid var(--border);
}
.edit-term-tab {
  background: none;
  border: none;
  padding: 4px 2px 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.edit-term-tab:hover { color: var(--text); }
.edit-term-tab.is-active {
  color: var(--accent-dark);
  border-bottom-color: var(--accent);
  font-weight: 700;
}

/* Markdown 預覽區：跟textarea共用同一個外框尺寸手感（padding/字級），
   讓「編輯」跟「預覽」切換時內容區塊高度不要跳來跳去。 */
.note-preview-pane {
  min-height: 110px;
  max-height: 320px;
  overflow-y: auto;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg);
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
}
.note-preview-pane > *:first-child { margin-top: 0; }
.note-preview-pane > *:last-child { margin-bottom: 0; }
.note-preview-pane h1, .note-preview-pane h2, .note-preview-pane h3 {
  font-family: var(--font-display);
  margin: 12px 0 6px;
  color: var(--text);
}
.note-preview-pane h1 { font-size: 18px; }
.note-preview-pane h2 { font-size: 16px; }
.note-preview-pane h3 { font-size: 14px; }
.note-preview-pane p { margin: 0 0 8px; }
.note-preview-pane ul, .note-preview-pane ol { margin: 0 0 8px; padding-left: 20px; }
.note-preview-pane blockquote {
  margin: 0 0 8px;
  padding: 2px 10px;
  border-left: 3px solid var(--accent);
  color: var(--text-muted);
}
.note-preview-pane a { color: var(--accent-dark); }
.note-preview-pane code {
  font-family: "SF Mono", "Fira Code", Consolas, monospace;
  font-size: 12.5px;
  background: var(--accent-light);
  border-radius: 4px;
  padding: 1px 5px;
}
.note-preview-pane pre {
  position: relative;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 12px 12px;
  overflow-x: auto;
  margin: 0 0 10px;
}
.note-preview-pane pre code {
  background: none;
  padding: 0;
  font-size: 12.5px;
  line-height: 1.55;
}
/* mermaid架構圖容器：跟code block同一種卡片語言（邊框+圓角），圖表本身
   置中。mermaid渲染失敗/CDN載入不到時，裡面留的是原始語法純文字——
   用:has(svg)判斷有沒有真的渲染出圖，沒有的話退回等寬字體+自動換行，
   至少讀得懂內容，不是擠成一團的純文字。 */
.note-preview-pane .mermaid {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px;
  margin: 0 0 10px;
  overflow-x: auto;
  display: flex;
  justify-content: center;
}
.note-preview-pane .mermaid:not(:has(svg)) {
  font-family: "SF Mono", "Fira Code", Consolas, monospace;
  font-size: 12px;
  white-space: pre-wrap;
  text-align: left;
  color: var(--text-muted);
}
.note-empty-preview, .note-plain-fallback {
  color: var(--text-muted);
  font-style: italic;
}
.note-plain-fallback { font-style: normal; white-space: pre-wrap; }
/* 程式碼區塊右上角的「複製」小按鈕，跟其他次要文字按鈕同一套語言
   （淡、hover才明顯），不會搶走程式碼本身的注意力。 */
.note-code-copy-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  font-size: 11px;
  padding: 2px 8px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text-muted);
  cursor: pointer;
  opacity: 0.7;
  transition: opacity var(--dur-fast) var(--ease-out);
}
.note-code-copy-btn:hover { opacity: 1; }

/* highlight.js語法上色：不引用官方主題CSS（那些是寫死的固定色盤，
   深色模式會對不上），改成自己對應現有的鼠尾草綠/焦糖色調色盤，讓
   程式碼區塊跟著App本身的淺色/深色模式自動換色。只覆蓋C++/Python/
   Bash這幾種語言實際會用到的token類別，沒出現的類別留給瀏覽器預設。 */
.hljs-keyword, .hljs-selector-tag, .hljs-tag { color: var(--accent-dark); font-weight: 600; }
.hljs-built_in, .hljs-type, .hljs-title.function_, .hljs-title { color: var(--accent); font-weight: 600; }
.hljs-string, .hljs-attr, .hljs-name { color: var(--side); }
.hljs-comment, .hljs-quote { color: var(--text-muted); font-style: italic; }
.hljs-number, .hljs-literal { color: var(--warning-text); }
.hljs-variable, .hljs-params, .hljs-meta { color: var(--text); }
.hljs-deletion { color: var(--danger-text); }
.hljs-addition { color: var(--accent); }

/* 專注計時圖示：跟task-note-btn一樣淡，計時中換成accent色+輕微呼吸感
   （比登入頁植物快一點，這是「正在進行中」的訊號，不是純裝飾），
   一眼就能看出「現在計時的是哪一列」。 */
.task-focus-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 8px;
  margin: -8px -8px -8px 0;
  font-size: 13px;
  line-height: 1;
  opacity: 0.28;
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-press) var(--ease-out), color 0.15s ease;
}
.task-focus-btn:hover { opacity: 0.6; }
.task-focus-btn:active { transform: scale(0.9); }
.task-focus-btn.focus-active {
  opacity: 1;
  color: var(--accent);
  animation: focus-btn-pulse 1.8s ease-in-out infinite;
}
@keyframes focus-btn-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.15); }
}
@media (prefers-reduced-motion: reduce) {
  .task-focus-btn.focus-active { animation: none; }
}

/* 核心/加分：左緣一條細色條，取代原本的文字徽章 */
.task-item {
  position: relative;
  overflow: hidden;
}
.task-item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--accent);
  opacity: 0.85;
}
.task-item.cat-side::before { background: var(--side); }
/* 優先權重視覺化：左緣色條的粗細+透明度一起加大/減小，不是只靠顏色深淺——
   同時用「粗細」這個非色彩訊號，色弱使用者也分得出差異。只有目標型任務
   （英文/CPE/AI Git/健身/半馬/副專案...）才套用，固定課表沒有「優先權重」
   這個概念，維持預設樣子（等同high的粗細，本來就是必須出席、不用分級）。 */
.task-item.priority-highest::before { width: 5px; opacity: 1; }
.task-item.priority-high::before { width: 4px; opacity: 0.85; }
.task-item.priority-medium::before { width: 3px; opacity: 0.6; }
.task-item.priority-low::before { width: 2px; opacity: 0.4; }
.task-item.done::before { opacity: 0.3; width: 3px; }

/* 2026-09-03改：獨立一列，不再貼著/疊進下面task-list第一張卡（之前
   margin-bottom:-4px把自己往下拉、蓋到「核心」那張卡，點卡片/打勾/
   滑動偶爾會誤觸−＋↻）。左「為什麼這樣排」、右−＋↻，跟task-list
   之間留實際的10px空隙，不是負margin硬疊上去。 */
.ai-schedule-summary {
  padding: 2px 4px;
  margin-bottom: 10px;
  font-size: 12.5px;
  color: var(--text-muted);
}
.ai-schedule-summary-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.ai-schedule-summary-actions {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  gap: 6px;
}
.ai-schedule-summary #btn-reroll-schedule,
.ai-schedule-summary #btn-load-less,
.ai-schedule-summary #btn-load-more {
  flex-shrink: 0;
  font-size: 14px;
}
/* 2026-09-01「為什麼這樣排」：跟排程本身同一種安靜、不搶眼的語氣——
   預設收合，想知道理由才點開，不會讓主畫面多一段常駐的說明文字。
   2026-09-03：現在跟−＋↻同一列，左側吃掉剩下的寬度，展開時的<ul>
   往下長高，右邊按鈕靠align-items:flex-start留在列頂端不會被推歪。 */
.ai-schedule-explain {
  flex: 1;
  min-width: 0;
}
.ai-schedule-explain summary {
  cursor: pointer;
  font-size: 11.5px;
  color: var(--text-muted);
  opacity: 0.75;
  list-style: none;
}
.ai-schedule-explain summary::-webkit-details-marker { display: none; }
.ai-schedule-explain summary::before { content: "▸ "; }
.ai-schedule-explain[open] summary::before { content: "▾ "; }
.ai-schedule-explain ul {
  margin: 6px 0 0;
  padding-left: 16px;
  font-size: 12px;
  line-height: 1.6;
  color: var(--text-muted);
}

/* 分區標題：課表 / 每天 / 今天要做。跟下面第一張任務卡拉開明確距離
   （8px→10px），視線先落在標題再落到卡片，不會標題卡片黏在一起分不出
   「這是分類，不是任務」。 */
.task-group-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 6px 2px 10px;
}
.task-group-title:not(:first-child) {
  margin-top: 14px;
}
/* .task-badge / .badge-core / .badge-side 已經移除：核心/加分改用
   .task-item::before 那條左緣色條表示，不再需要文字徽章。時間分配圖表
   那邊用的是自己的 .split-dot-core / .split-dot-side，不受影響。 */
.empty-hint {
  text-align: center;
  color: var(--text-muted);
  font-size: 14px;
  padding: 24px 0;
  /* 空狀態原本一出現就是定格的一句話，現在跟清單本身共用同一套
     「淡入+輕微上移」語言（跟task-enter同一個份量級距），而不是憑空
     出現——這是狀態改變（載入中→確認是空的）的一種，屬於「該有轉場
     卻沒有」的缺口。 */
  animation: view-enter var(--dur-base) var(--ease-out);
}
.empty-hint .empty-icon {
  color: var(--border);
  margin-bottom: 6px;
}
.empty-hint p {
  margin: 0;
}

/* ---------- 底部操作列：改成單一按鈕開選單 ---------- */
/* 原本6個 btn-secondary(flex:1) 擠一排，中文字數少還好，英文版標籤變長
   直接擠爆整排（"CPE / AI Git Progress" 這種）。改成單一按鈕，點開才
   跳出選單，不管中英文都不會跑版。 */
.btn-more-menu {
  width: 100%;
  background: var(--accent-light);
  color: var(--accent-dark);
  border: none;
  border-radius: 12px;
  padding: 12px 14px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, transform var(--dur-press) var(--ease-out);
}
.btn-more-menu:hover { background: var(--border); }
.btn-more-menu:active { transform: scale(0.97); }

.more-menu-box {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.more-menu-item {
  width: 100%;
  text-align: center;
}

/* ---------- 模板編輯頁 ---------- */
.edit-days {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.edit-day-card {
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 14px;
}
.edit-day-card h3 {
  margin: 0 0 10px;
  font-size: 15px;
  color: var(--accent-dark);
}
.edit-task-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 10px;
}
.edit-task-row {
  display: grid;
  grid-template-columns: 80px 1fr 64px auto auto auto;
  gap: 6px;
  align-items: center;
}
.edit-task-row input,
.edit-task-row select {
  padding: 8px 8px;
  border-radius: 8px;
  border: 1px solid var(--border);
  font-size: 13px;
  background: var(--bg);
  color: var(--text);
  min-width: 0;
}
.edit-task-row .btn-icon {
  width: 28px;
  height: 28px;
  font-size: 13px;
  padding: 0;
}

/* ---------- 目標編輯頁 ---------- */
.goals-hint {
  font-size: 13px;
  color: var(--text-muted);
  padding: 0 4px 12px;
  line-height: 1.5;
}
.goals-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 14px;
}
.goal-card {
  touch-action: manipulation; /* 目標卡片連點兩下不放大 */
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.goal-card input,
.goal-card select {
  padding: 8px 8px;
  border-radius: 8px;
  border: 1px solid var(--border);
  font-size: 13px;
  background: var(--bg);
  color: var(--text);
  min-width: 0;
}
.goal-row-1 { display: grid; grid-template-columns: 1fr 100px; gap: 6px; }
.goal-row-2 { display: grid; grid-template-columns: 90px 90px 1fr; gap: 6px; align-items: center; }
.goal-row-2 label { font-size: 12px; color: var(--text-muted); }
.goal-row-3 { display: flex; justify-content: flex-end; }
/* 同一個minmax(0,1fr)修法（見下面.checklist-row-nutrition的說明）：
   同樣是「label包input、沒設width」的排版，同樣有被input預設寬度撐開
   溢出的風險，這裡一併修掉。 */
.goal-row-dates { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.goal-row-dates label { font-size: 11px; color: var(--text-muted); display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.goal-row-dates input { width: 100%; }

/* 2026-09-01「進階規則」：預設收合的<details>，重用.modal-section的視覺
   語言（跟帳號設定modal裡那些收合區塊一致），一般使用者不會被這些欄位
   干擾，只有點開才看得到。 */
.goal-advanced-rules { margin-top: 4px; }
.goal-advanced-rules-hint { font-size: 11px; color: var(--text-muted); margin: 4px 0 8px; }
.goal-weekday-picker { display: flex; gap: 4px; margin-bottom: 8px; }
.goal-weekday-chip {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 6px 0;
  border-radius: 8px;
  border: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-muted);
  cursor: pointer;
}
.goal-weekday-chip:has(input:checked) {
  border-color: var(--accent);
  color: var(--accent-dark);
  font-weight: 600;
}
.goal-weekday-chip input { margin: 0; }
.goal-mutex-label {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 12px;
  color: var(--text-muted);
}
.goal-mutex-label select { width: 100%; }
/* 2026-09-02加：目標卡片最上面的「範本」選單——跟.goal-mutex-label同一種
   窄版label手感，但放在卡片最外層（不在收合的進階規則details裡），
   所以獨立一個class，加一條底線跟下面的名稱/優先度欄位隔開。 */
.goal-row-template {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-bottom: 8px;
  border-bottom: 1px dashed var(--border);
}
.goal-row-template select { width: 100%; }
/* 進度總覽卡片的次要總量行（x／N），比主數字小、顏色淡一點，
   跟.progress-figure-unit同一種「次要資訊」定位但獨立一行顯示。 */
.progress-figure-sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }

/* 每日固定清單編輯頁：早餐品項的4個營養數值輸入框，跟.goal-row-dates
   同一種「小標籤+輸入框」排版語言，只是4欄不是3欄。只有category選
   breakfast時才會顯示這排（見buildChecklistItemEditRow）。 */
/* minmax(0, 1fr)不是隨便寫的——單純1fr的隱含最小寬度是auto（等於欄位
   內容本身的intrinsic寬度），<input>沒設width的話瀏覽器預設寬度大約
   170~180px，4欄乘起來遠超過卡片本身的寬度，欄位就會被撐開、整排往
   右溢出卡片邊界（使用者回報「碳水那格一直超出去」的真正原因）。
   minmax(0,1fr)才會讓每欄真的均分容器寬度、能縮到比輸入框預設寬度
   還窄。 */
.checklist-row-nutrition { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.checklist-row-nutrition label { font-size: 11px; color: var(--text-muted); display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.checklist-row-nutrition input { width: 100%; }

/* 2026-08-27 編輯清單品項頁緊湊化：原本借用.goal-card/.goals-list的排版
   （名稱/分類/份量各自佔一整行+獨立一行的刪除按鈕），對這個頁面來說內容
   量太少、拉得又長又空。改成專屬的緊湊版面：名稱+分類+份量+刪除鈕擠在
   同一行；卡片間距也縮小，滑動時能一次看到更多項目。營養4欄只有早餐
   類別才出現，維持獨立一行（本來就已經是最緊湊的4欄排法，不用再改）。 */
.checklist-edit-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 14px;
}
.checklist-edit-card {
  background: var(--card-bg);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.checklist-edit-card input,
.checklist-edit-card select {
  padding: 6px 8px;
  border-radius: 8px;
  border: 1px solid var(--border);
  font-size: 12.5px;
  background: var(--bg);
  color: var(--text);
  min-width: 0;
}
.checklist-edit-row-main {
  display: grid;
  /* 同一個minmax(0, Xfr)修法：78px/26px是固定寬度不受影響，但1.3fr/1.1fr
     這兩欄一樣有input預設寬度撐開欄位的風險，這裡先一併防範。 */
  grid-template-columns: minmax(0, 1.3fr) 78px minmax(0, 1.1fr) 26px;
  gap: 6px;
  align-items: center;
}
/* 飽和脂肪：次要細項，跟主要4個營養值分開一行、用較淡的標籤字色，
   視覺上明顯比上面那排「輕」，暗示這不是必填的核心資訊。 */
.checklist-secondary-field {
  font-size: 11px;
  color: var(--text-muted);
  display: flex;
  flex-direction: column;
  gap: 2px;
  opacity: 0.85;
}

/* ---------- 訓練日補給 ---------- */
.training-day-toggle-row { margin-bottom: 12px; }
.training-water-row { margin-bottom: 10px; }
.training-water-input-row { margin-bottom: 10px; }
.training-water-input-row input {
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--border);
  font-size: 13px;
  background: var(--bg);
  color: var(--text);
}
/* 快速加水三顆按鈕：跟.btn-tiny同一種淡按鈕語言，平分寬度排一排，
   點了直接累加，不用先點進輸入框打字。 */
.water-quick-add-row {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}
.water-quick-add-row .btn-tiny { flex: 1; }

/* ---------- 全域搜尋（Command Palette）---------- */
/* 疊層對齊畫面上方（VS Code那種command palette的慣例位置），不是像
   其他modal那樣垂直置中——搜尋是「快速跳進去、快速跳出來」的操作，
   貼近header比較符合這個心智模型。 */
.cmdk-overlay {
  align-items: flex-start;
  padding-top: calc(12vh + env(safe-area-inset-top));
}
.cmdk-box {
  width: 100%;
  max-width: 480px;
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
  animation: modal-box-in 0.15s ease;
}
.cmdk-input-row {
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--border);
}
.cmdk-input {
  flex: 1;
  min-width: 0;
  border: none;
  border-radius: 0;
  padding: 16px 18px;
  font-size: 15px;
  background: transparent;
}
.cmdk-close-btn {
  flex-shrink: 0;
  margin-right: 12px;
}
.cmdk-input:focus-visible { outline: none; box-shadow: none; }
.cmdk-results {
  max-height: 55vh;
  overflow-y: auto;
  padding: 6px;
}
.cmdk-result-item {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  border-radius: 8px;
  padding: 8px 10px;
  cursor: pointer;
  font-size: 13px;
}
.cmdk-result-item.is-selected, .cmdk-result-item:hover {
  background: var(--accent-light);
}
.cmdk-result-date {
  flex-shrink: 0;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
}
.cmdk-result-name {
  flex-shrink: 0;
  font-weight: 600;
  color: var(--text);
}
.cmdk-result-note {
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* ---------- 里程碑全息卡（3D傾斜慶祝卡）---------- */
.applock-overlay {
  z-index: 25; /* 比一般modal(10)高，但比milestone-overlay(30)低——鎖定
    畫面本身不需要蓋過里程碑慶祝卡（不太可能同時發生，純粹保守排序） */
}
.applock-icon { font-size: 40px; margin-bottom: 8px; }

.milestone-overlay {
  flex-direction: column;
  perspective: 1200px; /* 子元素的3D transform要有這個才有正確的視覺深度 */
}
.milestone-card {
  position: relative;
  width: 280px;
  padding: 32px 24px;
  border-radius: 20px;
  background: linear-gradient(135deg, var(--accent-dark), var(--accent), var(--side));
  color: #fff;
  text-align: center;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
  transform-style: preserve-3d;
  transition: transform var(--dur-press) var(--ease-out), background 0.2s ease;
  overflow: hidden;
  animation: modal-box-in 0.25s ease;
}
/* 里程碑卡片背景主題：每次慶祝隨機抽一種（見showMilestoneCard()裡的
   MILESTONE_CARD_THEMES），不是固定同一種配色——七種風格對應使用者
   要求的「有質感/酷/帥氣/溫柔/可愛/高冷」+ 原本App自己的暖色調當預設。
   全部維持白色文字，只換背景漸層，不用另外調整卡片內其他樣式。 */
.milestone-theme-default { background: linear-gradient(135deg, var(--accent-dark), var(--accent), var(--side)); }
.milestone-theme-premium { background: linear-gradient(135deg, #2b2320, #4a3f35, #cdaa6d); } /* 有質感：深棕炭色+古銅金 */
.milestone-theme-cool { background: linear-gradient(135deg, #0f2027, #203a43, #2c8fae); } /* 酷：深藍轉青綠 */
.milestone-theme-sharp { background: linear-gradient(135deg, #141414, #3a0d0d, #c1121f); } /* 帥氣：黑轉紅 */
.milestone-theme-gentle { background: linear-gradient(135deg, #c86b85, #a56cc1, #6a89cc); } /* 溫柔：霧粉轉薰衣草紫 */
.milestone-theme-cute { background: linear-gradient(135deg, #ff6f91, #ff9671, #ffc75f); } /* 可愛：粉桃轉奶油黃 */
.milestone-theme-aloof { background: linear-gradient(135deg, #232526, #3a3d40, #5c6b73); } /* 高冷：冷灰銀藍 */
/* 全息光澤：跟著滑鼠位置（--shine-x/--shine-y，由handleMilestoneCardTilt
   設定）移動的一圈柔光，模擬真的全息卡在燈光下轉動時那種反光掃過的
   效果。手機沒有mousemove事件，這兩個變數會停在初始值，光澤固定不動，
   卡片本身依然正常顯示。 */
.milestone-card-shine {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at var(--shine-x, 50%) var(--shine-y, 50%), rgba(255, 255, 255, 0.35), transparent 60%);
  pointer-events: none;
  mix-blend-mode: overlay;
}
.milestone-card-icon { font-size: 40px; margin-bottom: 8px; }
.milestone-card-title {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 700;
  margin-bottom: 4px;
}
.milestone-card-subtitle { font-size: 13px; opacity: 0.9; margin-bottom: 16px; }
.milestone-card-stats { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; }
.milestone-stat {
  background: rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 700;
}
.milestone-close-btn { margin-top: 20px; color: #fff; }

/* ---------- 沈浸模式（Zen Mode）---------- */
/* 全螢幕、無干擾：只留計時、任務名稱、暫停鈕、筆記編輯器四樣東西，
   其餘（任務清單、header、其他modal）全部蓋住。z-index刻意比任何modal
   都高——進沈浸模式時不該同時看到別的彈窗。 */
.zen-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg);
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* 全螢幕疊層，上下都直接貼著螢幕邊緣，一定要加安全區域，不然「✕結束」
     按鈕會被瀏海/Dynamic Island擋住，底下的筆記編輯器也會被Home
     Indicator蓋到。 */
  padding: calc(24px + env(safe-area-inset-top)) calc(20px + env(safe-area-inset-right))
    calc(24px + env(safe-area-inset-bottom)) calc(20px + env(safe-area-inset-left));
  gap: 10px;
  animation: modal-backdrop-in 0.2s ease;
}
.zen-exit {
  align-self: flex-end;
  font-size: 13px;
}
.zen-timer {
  font-family: var(--font-display);
  font-size: 56px;
  font-weight: 700;
  letter-spacing: -0.03em; /* 56px比其他大字更大一階，收得再緊一點 */
  font-variant-numeric: tabular-nums;
  color: var(--accent-dark);
  margin-top: 8px;
}
.zen-task-name {
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
  text-align: center;
  max-width: 480px;
}
.zen-controls {
  display: flex;
  gap: 10px;
  margin-bottom: 8px;
}
.zen-pause-btn, .zen-noise-btn {
  font-size: 20px;
  background: var(--accent-light);
  border-radius: 999px;
  width: 44px;
  height: 44px;
}
.zen-noise-btn.is-active {
  background: var(--accent);
  color: var(--card-bg);
}
.zen-note-tabs {
  display: flex;
  gap: 16px;
  width: 100%;
  max-width: 560px;
  border-bottom: 1px solid var(--border);
}
.zen-note-textarea, .zen-note-preview-pane {
  width: 100%;
  max-width: 560px;
  flex: 1;
  min-height: 0;
}
.zen-note-textarea {
  resize: none;
  font-family: "SF Mono", "Fira Code", Consolas, monospace;
  font-size: 13px;
}
.zen-note-preview-pane {
  max-height: none;
}

/* ---------- 匯出彈窗 ---------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  /* 2026-09-08：背幕從寫死的rgba改成跟著主題走的var(--scrim)——原本
     那條淺褐色半透明蓋在深色主題上幾乎看不出來，等於彈窗背後沒有變暗。
     另外加一層很輕的背景模糊：Apple在「把注意力收到單一任務」時的做法
     是壓暗＋推遠，只壓暗會讓底下的文字還是清晰可讀、眼睛一直被拉回去。
     模糊只給4px，夠讓底層退到背景，又不會糊到認不出自己剛剛在哪一頁。 */
  background: var(--scrim);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  z-index: 10;
  animation: modal-backdrop-in var(--dur-fast) var(--ease-out);
}
@keyframes modal-backdrop-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
.modal-box {
  width: 100%;
  max-width: 360px;
  text-align: center;
  padding: 24px 20px;
  animation: modal-box-in var(--dur-base) var(--ease-out);
  /* 修復bug：帳號設定這個modal內容一路加(GitHub同步/Webhook/Face ID/
     本地同步/量化觀察清單...)，長度早就超過手機螢幕高度，但modal-box
     本身沒有任何高度上限/捲動設定——關閉按鈕在最下面，長度超過螢幕
     的話根本捲不到、點不到，等於卡住出不來。這裡統一加高度上限+可
     直向捲動，其餘比較短的modal不受影響(內容本來就沒那麼高，不會
     觸發捲動)。 */
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  transition: background 0.2s ease, color 0.2s ease;
}
@keyframes modal-box-in {
  from { opacity: 0; transform: scale(0.96) translateY(6px); }
  to { opacity: 1; transform: scale(1) translateY(0); }
}
.modal-box h2 {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 600;
  color: var(--accent-dark);
  margin: 0;
}
.modal-hint {
  font-size: 13px;
  color: var(--text-muted);
  margin: 8px 0 18px;
}
.modal-divider {
  height: 1px;
  background: var(--border);
  margin: 4px 0 16px;
}
.modal-subtitle {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 2px;
}
.modal-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 12px;
}

/* 2026-09 模組開關清單：跟其他checkbox列（例如訓練日補給那排）同一種
   簡單樣式，沒有另外開一套設計語言。 */
.module-toggle-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.module-toggle-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  cursor: pointer;
}
.module-toggle-row input { flex-shrink: 0; }

/* header搬進帳號設定的「顯示」快捷列：搜尋/主題/語言三顆按鈕平分寬度，
   跟原本header裡的圖示按鈕感覺一致，只是換個地方放。 */
.acct-quick-actions {
  flex-direction: row;
  flex-wrap: wrap;
}
.acct-quick-actions button { flex: 1; min-width: 90px; }

/* 主題選單（色票圓點）：一顆顆小圓點直接代表那個主題的主色，點了直接
   切過去，選到的那顆用外框標出來——跟emoji循環鈕是兩個互相補位的
   入口，不是取代關係。 */
.theme-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 16px;
}
.theme-swatch {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 2px solid var(--border);
  cursor: pointer;
  padding: 0;
  transition: transform var(--dur-fast) var(--ease-out), border-color 0.15s ease;
}
/* 觸控裝置點一下會觸發一次假的:hover，效果會黏在原地不走（手指離開
   螢幕不算mouseleave）。只有真的有滑鼠指標時才給這種會動/會浮起來的
   回饋，觸控裝置靠:active就夠了。 */
@media (hover: hover) and (pointer: fine) {
  .theme-swatch:hover { transform: scale(1.1); }
}
.theme-swatch.is-active {
  border-color: var(--text);
  box-shadow: 0 0 0 2px var(--card-bg), 0 0 0 4px var(--text);
}
.theme-swatch-auto {
  background: conic-gradient(#7a8471 0deg 90deg, #93a687 90deg 180deg, #00ff00 180deg 270deg, #e8632c 270deg 360deg);
}

/* 修復實測回報「帳號設定/匯出資料版面很醜、關不掉」——固定在modal頂端
   的標題+✕，捲動時永遠看得到、不用滑到最下面找關閉鈕；每個設定/匯出
   方式收合成<details>，預設是一排短短的標題列，不是一整面牆的表單，
   點開才看得到內容。 */
.modal-sticky-header {
  position: sticky;
  top: -24px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--card-bg);
  margin: -24px -20px 16px;
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--border);
}
.modal-sticky-header h2 { text-align: left; }

/* 2026-09-01 設定分組標題：純粹是閱讀順序的分堆，不是新的互動元件——
   跟.modal-section本身的樣式刻意做出區隔（沒有邊框、沒有背景），這樣
   眼睛掃過去很清楚「這是分類，不是可以點的東西」。第一個分組標題
   （帳號）貼齊上緣，不用額外的margin-top。 */
.modal-group-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  text-align: left;
  margin: 16px 2px 6px;
}
.modal-group-title:first-of-type { margin-top: 4px; }

.modal-section {
  border: 1px solid var(--border);
  border-radius: 12px;
  margin-bottom: 10px;
  padding: 0 14px;
  text-align: left;
}
.modal-section summary {
  padding: 13px 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  list-style: none; /* 拿掉瀏覽器預設的三角形箭頭，改用自己畫的，兩邊圖示風格才一致 */
  display: flex;
  align-items: center;
  justify-content: space-between;
  -webkit-tap-highlight-color: transparent;
}
.modal-section summary::-webkit-details-marker { display: none; }
.modal-section summary::after {
  content: "▾";
  color: var(--text-muted);
  font-size: 12px;
  transition: transform var(--dur-fast) var(--ease-out);
}
.modal-section[open] summary::after { transform: rotate(180deg); }
.modal-section .modal-hint { margin: 0 0 12px; text-align: left; }
.modal-section > form,
.modal-section > .modal-actions,
.modal-section > select { margin-bottom: 14px; }
.modal-section form input,
.modal-section form select { width: 100%; margin-bottom: 8px; }
@media (prefers-reduced-motion: reduce) {
  .modal-section summary::after { transition: none; }
}
/* 新增單次任務彈窗：新增（送出）跟取消緊貼在一起，手機上很容易點錯，
   拉開兩者間距，並把取消的可點擊範圍加大。 */
#add-task-modal #add-task-form .btn-primary {
  margin-bottom: 4px;
}
#add-task-modal #btn-add-task-close {
  margin-top: 16px;
  padding: 10px 20px;
}
#export-modal #btn-export-close {
  margin-top: 16px;
  padding: 10px 20px;
}
#account-modal #btn-account-close {
  margin-top: 16px;
  padding: 10px 20px;
}

/* ---------- 冷啟動載入畫面：骨架屏 ----------
   形狀對照今日總覽卡（環形進度+一行字）跟幾列任務，讓「還在載入」的
   畫面本身就是頁面的輪廓，比一顆跟內容無關的轉圈圈更能減少「畫面
   突然跳出來」的違和感。維持這支App一貫「只在一處做動畫」的克制——
   shimmer只是很淡的明暗掃過，不是花俏效果。 */
.main-loading {
  position: fixed;
  inset: 0;
  background: var(--bg);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  z-index: 20;
  max-width: 480px;
  margin: 0 auto;
}
/* 2026-09修：#app跟.bottom-nav寬螢幕（≥900px）都已經改成560px，這個
   骨架屏loading畫面漏改，還卡在480px——冷啟動那一瞬間骨架屏比底下
   實際頁面窄一截，兩側露出真正的內容，看起來像疊在一起、卡住的畫面。 */
@media (min-width: 900px) {
  .main-loading { max-width: 560px; }
}
.skeleton-hero {
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 24px 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
.skeleton-ring {
  width: 110px;
  height: 110px;
  border-radius: 50%;
  border: 10px solid var(--accent-light);
}
.skeleton-task-item {
  background: var(--card-bg);
  border-radius: 14px;
  box-shadow: var(--shadow);
  padding: 14px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.skeleton-block {
  border-radius: 6px;
  background: linear-gradient(
    90deg,
    var(--accent-light) 25%,
    color-mix(in srgb, var(--accent-light) 55%, var(--card-bg)) 50%,
    var(--accent-light) 75%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s ease-in-out infinite;
}
.skeleton-circle {
  width: 22px;
  height: 22px;
  border-radius: 7px;
  flex-shrink: 0;
}
.skeleton-line {
  height: 14px;
  flex: 1;
}
.skeleton-line-sm {
  height: 12px;
  width: 90px;
}
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton-block { animation: none; }
}

/* ---------- 課程進度：大數字 + 接下來幾堂 ---------- */
/* 「已完成幾堂 / 全部511堂」用一個大數字撐起來——這個頁面存在的理由就是
   回答「我離終點還有多遠」，那個數字本身就該是主角。 */
.progress-figure {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 10px;
}
.progress-figure-num {
  font-family: var(--font-display);
  font-size: 40px;
  font-weight: 700;
  line-height: 1;
  color: var(--accent-dark);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.progress-figure-unit {
  font-size: 13px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.lesson-upcoming {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 10px;
}
.lesson-row {
  display: flex;
  align-items: baseline;
  gap: 9px;
  padding: 7px 8px;
  border-radius: 9px;
  font-size: 13px;
}
/* 只有「下一堂」是實心底、其餘幾堂逐漸淡出——由近到遠的層次，
   讓人一眼落在該做的那堂，而不是平均分配注意力給五列。 */
.lesson-row.current {
  background: var(--accent-light);
}
.lesson-row:not(.current) { opacity: 0.62; }
.lesson-row:nth-child(4):not(.current) { opacity: 0.48; }
.lesson-row:nth-child(5):not(.current) { opacity: 0.36; }
.lesson-tag {
  font-size: 11px;
  font-weight: 700;
  color: var(--accent-dark);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  flex-shrink: 0;
}
.lesson-title {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.lesson-mins {
  font-size: 11px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

/* ---------- 每日固定清單（早餐營養倒扣 / 保健品）----------
   2026-08-27 視覺優化：改用跟主任務清單（.task-item / .task-check）同一套
   卡片＋自訂打勾框語言，讓這頁不會跟其他頁面的風格脫節；營養倒扣的四個
   數值改成跟「本週目標進度」同一套進度條組件（.goal-progress-*），這兩處
   都是直接重用既有class，不是另外造一套視覺語言。這頁新增的只有「打勾後
   轉綠」跟「保健品小圖示」這兩個真正獨有的東西。 */
.checklist-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 14px;
}
.checklist-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--card-bg);
  border-radius: 14px;
  padding: 12px 14px;
  box-shadow: var(--shadow);
  cursor: pointer;
  font-size: 14px;
  color: var(--text);
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
  transition: background 0.25s ease, box-shadow var(--dur-fast) var(--ease-out), transform var(--dur-press) var(--ease-out);
}
/* 觸控裝置點一下會觸發一次假的:hover，效果會黏在原地不走（手指離開
   螢幕不算mouseleave）。只有真的有滑鼠指標時才給這種會動/會浮起來的
   回饋，觸控裝置靠:active就夠了。 */
@media (hover: hover) and (pointer: fine) {
  .checklist-row:hover { box-shadow: 0 4px 14px rgba(60, 50, 30, 0.12); }
}
.checklist-row:active { transform: scale(0.99); }
.checklist-icon {
  font-size: 17px;
  flex-shrink: 0;
  line-height: 1;
  /* 未打勾時比較淡，打勾那一刻連圖示一起「亮起來」，呼應下面說的
     「已完成用鮮明色彩、未完成清爽不搶眼」。 */
  opacity: 0.55;
  transition: opacity var(--dur-base) var(--ease-out);
}
.checklist-name {
  flex: 1;
  transition: color 0.25s ease;
}
/* 2026-08-30：.review-reminder-note原本的獨立卡片樣式已拿掉——複習提醒
   現在是「今日安排」裡的一個真任務列，跟其他任務共用同一套.task-item
   樣式，細節收進note用📝按鈕看，不需要另外的卡片內文字樣式。 */
.checklist-serving {
  font-size: 11.5px;
  color: var(--text-muted);
  background: var(--accent-light);
  border-radius: 999px;
  padding: 3px 9px;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  transition: background 0.25s ease, color 0.25s ease;
}
/* 打勾＝這一格今天做過了，用成功色的淺底＋左緣色條給明顯但不刺眼的回饋；
   未打勾維持一般卡片白底，兩種狀態的對比只靠顏色深淺，不靠「變灰變淡」
   （那是主任務清單「做完的事情該讓開」的邏輯，這裡是健康習慣打卡，做完
   應該被看見，不是被藏起來）。 */
.checklist-row.checked {
  background: color-mix(in srgb, var(--success) 16%, var(--card-bg));
  box-shadow: inset 3px 0 0 var(--success), var(--shadow);
  animation: checklist-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.checklist-row.checked .checklist-icon { opacity: 1; }
.checklist-row.checked .checklist-name { color: var(--accent-dark); font-weight: 600; }
.checklist-row.checked .checklist-serving {
  background: color-mix(in srgb, var(--success) 30%, var(--accent-light));
  color: var(--accent-dark);
}
@keyframes checklist-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.015); }
  100% { transform: scale(1); }
}

/* 早餐營養倒扣：直接借用「本週目標進度」的進度條組件，只是資料來源換成
   營養素。跟goal-progress-bar共用class是刻意的——同一種視覺語言代表同一
   件事「目前進度 vs 目標」，使用者看到這個形狀就知道是進度，不用重新學。 */
.checklist-macro-summary {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 14px;
}
/* 飽和脂肪參考值：純資訊、沒有進度條也沒有警示色——使用者明確要求
   「僅供參考，不做警示或強制提醒」，用跟其他次要文字一樣的muted色，
   不要讓它看起來像另一個要達標的目標。 */
.saturated-fat-note {
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 12px;
}

/* ---------- 其他餐點記錄（午餐/晚餐/點心快速流水帳）----------
   跟早餐/保健品不一樣：這裡不是固定清單+打勾，是「輸入就新增一筆」，
   表單样式沿用.goal-card的input/select外觀（同一種輸入框長相），但版面
   是這個功能專屬的（早餐/保健品沒有新增表單）。 */
.nutrition-log-form {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}
.nutrition-log-form-row { display: flex; gap: 8px; }
.nutrition-log-form-row select { width: 92px; flex-shrink: 0; }
.nutrition-log-macros { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
.nutrition-log-form input,
.nutrition-log-form select {
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--border);
  font-size: 13px;
  background: var(--bg);
  color: var(--text);
  min-width: 0;
}
/* 酒精欄位預設收起來——多數人用不到，不該讓每個人都多看一眼。這是唯一
   會影響熱量、但不影響P/F/C的欄位，跟其他3個必填的巨量營養素分開處理。 */
.nutrition-log-more-toggle {
  align-self: flex-start;
  font-size: 12px;
  padding: 0;
}
.nutrition-log-more { margin-top: -2px; }

.nutrition-log-row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--card-bg);
  border-radius: 14px;
  padding: 10px 12px;
  box-shadow: var(--shadow);
}
/* 這一列本身就是「已經記錄的事實」，沒有打勾前/後的分別，圖示不用像
   checklist-icon那樣未打勾時淡化——固定給滿opacity。 */
.nutrition-log-icon { opacity: 1; }
.nutrition-log-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.nutrition-log-name { font-size: 14px; color: var(--text); }
.nutrition-log-macro-text {
  font-size: 11.5px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
.btn-icon-sm {
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-muted);
  font-size: 13px;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}
.btn-icon-sm:hover { background: var(--danger-bg); color: var(--danger-text); }

/* ---------- 訓練數據紀錄（跑步距離/配速、健身多動作）----------
   task-metric-btn/preview跟task-note-btn/preview完全同一套視覺語言
   （淡圖示直到有紀錄、預覽小字截斷），沒有另外設計一套新樣式——同一個
   任務列上兩種附加資訊（備註/訓練數據）用同一種份量感呈現，不會有一個
   特別搶眼。 */
.task-metric-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 8px;
  margin: -8px -8px -8px 0;
  font-size: 13px;
  line-height: 1;
  opacity: 0.28;
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-press) var(--ease-out);
}
.task-metric-btn:hover { opacity: 0.6; }
.task-metric-btn:active { transform: scale(0.9); }
.task-metric-btn.has-metric { opacity: 0.85; }
.task-metric-preview {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  text-align: left;
  font-size: 12px;
  color: var(--text-muted);
  cursor: pointer;
  align-self: stretch;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.task-metric-preview:hover { color: var(--accent-dark); }

/* 健身動作清單：跟編輯清單品項頁的.checklist-edit-card同一種卡片感，
   一列一個動作，名稱+數值+一個小刪除鍵。 */
.training-exercise-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 10px;
}
.training-exercise-row {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--card-bg);
  border-radius: 10px;
  box-shadow: var(--shadow);
  padding: 8px 10px;
}
.training-exercise-name {
  flex: 1;
  min-width: 0;
  font-size: 13.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.training-exercise-detail {
  font-size: 12px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
/* 新增動作表單：名稱吃剩下的寬度，kg/組/次三個數字欄位盡量窄，
   跟其他餐點記錄的輸入框外觀共用同一種質感(padding/border/字級)。 */
.training-exercise-add-form {
  display: grid;
  grid-template-columns: 1.6fr 0.7fr 0.6fr 0.6fr auto;
  gap: 6px;
  align-items: center;
}
.training-exercise-add-form input {
  padding: 8px 8px;
  border-radius: 8px;
  border: 1px solid var(--border);
  font-size: 13px;
  background: var(--bg);
  color: var(--text);
  min-width: 0;
}

/* ---------- 桌面響應式 ---------- */
@media (min-width: 600px) {
  #app { padding-top: 40px; }
}

/* ---------- 減少動態效果 ----------
   系統層級開了「減少動態效果」（iOS 輔助使用 / Windows 動畫設定）的人，
   通常是因為動畫會引發不適，不是嫌它慢。所以這裡不是把動畫調快，而是
   整組關掉：進場淡入、勾勾描繪、進度條推進、慶祝彩帶全部變成瞬間完成，
   畫面該長怎樣還是長怎樣，只是沒有中間過程。 */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* 課程進度卡的次要說明行（全課程位置、資料來源說明） */
.progress-subline {
  font-size: 12px;
  color: var(--text-muted);
  margin: 8px 0 14px;
  font-variant-numeric: tabular-nums;
}

/* 編輯目標頁：AI Git 課程進度欄位上方的說明 */
.goal-course-hint {
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.5;
  margin: 4px 0 6px;
}
/* Master Plan Phase 5：週六模擬考規則改成goal上的一個明確可勾選flag
   （原本完全藏在程式碼的隱性判斷式裡），只在CPE那張卡片才會出現——
   沿用主畫面同一套.task-check打勾框，跟整個App打勾手感一致。 */
.goal-row-flag {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 6px 0 2px;
}
.goal-flag-label {
  font-size: 12.5px;
  color: var(--text-muted);
  line-height: 1.4;
}

/* 已滾進後續日子、不給重複打勾的舊任務：整列壓暗、勾選框變成不可點，
   跟「未來還沒發生」是不同的意思，所以用自己的樣式而不是沿用舊的
   future-locked（那個規則現在已經沒有任何列會套用到了）。 */
.task-item.rolled-forward {
  opacity: 0.5;
  cursor: default;
}
.task-item.rolled-forward input[type="checkbox"] {
  cursor: not-allowed;
}
.task-rolled {
  font-size: 11px;
  color: var(--text-muted);
  align-self: flex-start;
}

/* ---------- 專注計時浮動視窗 ----------
   固定貼在畫面底部，只在計時中才顯示。故意不做成modal（不蓋
   modal-overlay全螢幕遮罩）——計時的時候應該還能正常操作底下的清單，
   不是被浮動視窗鎖住。跟.card同一種卡片質感（陰影/圓角/背景），只是
   加了fixed定位。 */
.focus-widget {
  position: fixed;
  left: 50%;
  bottom: calc(16px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  width: calc(100% - 32px);
  max-width: 420px;
  background: var(--card-bg);
  border-radius: var(--radius);
  box-shadow: 0 8px 28px -6px rgba(0, 0, 0, 0.35), var(--shadow);
  padding: 12px 16px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  z-index: 15;
  animation: focus-widget-in 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes focus-widget-in {
  from { opacity: 0; transform: translateX(-50%) translateY(12px); }
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
.focus-widget-info {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.focus-widget-time {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--accent-dark);
}
.focus-widget.focus-paused .focus-widget-time { color: var(--text-muted); }
/* 2026-09-02修：底部導覽列出現的頁面（今天/歷史/目標），計時小工具的
   16px底部間距沒有算進導覽列本身的高度——導覽列疊在計時小工具下半截
   上面，把時間數字擋住。跟#app的padding-bottom用同一個64px（導覽列
   實際高度），疊加在原本的16px間距上，把整個小工具往上推到導覽列
   上方，不是重新設計一套間距邏輯。 */
body.has-bottom-nav .focus-widget {
  bottom: calc(16px + 64px + env(safe-area-inset-bottom));
}
.focus-widget-task {
  font-size: 12px;
  color: var(--text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.focus-widget-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
}
.focus-widget-btn { white-space: nowrap; }
#btn-focus-pause {
  width: 30px;
  height: 30px;
  font-size: 14px;
}
@media (prefers-reduced-motion: reduce) {
  .focus-widget { animation: none; }
}
