/*
 * Kept —— 介面樣式。Dark 係預設(用戶原話「預設為DARK MODE」),淺色係設定頁自己揀嘅第二個選擇。
 * 風格係 X 同 Threads 嘅合體:純黑底、細線分隔、左頭像右內文、圓角 media、一行細 icon 動作。
 * 全部尺寸跟 iOS 對位:safe-area 四邊都食,tab bar 49pt + 底部安全區,header 44pt + 頂部安全區。
 *
 * ⚠️ 換主題只可以靠改下面呢堆 var,唔好喺下面嘅規則度寫死顏色。
 *   --blur / --blur-2  header、狀態列底、tab bar 嗰塊半透明模糊底
 *   --scrim            sheet 背後嗰浸
 *   --ghost            主題 tile 冇封面嗰陣個大 icon 底紋
 * 舖喺相上面嗰啲(.tile .shade / .cap / .ico、video 背景)照樣寫死白同黑 —— 底下係相,兩個主題都一樣。
 */
:root {
  --bg: #000000; --bg-2: #0A0A0A; --card: #101010; --raise: #16181C;
  /* ⚠️ `--muted` 由 #71767B 調亮到 #8B9198（2026-09-18）。
     舊嗰隻喺卡底（#101010）／浮起嗰層（#16181C）上面只有 3.75–4.3:1，過唔到 WCAG AA 嘅 4.5。
     逐個元素量深淺色嗰陣捉到:「留言」嗰個標題 3.9、link 卡個網域行 4.3。
     淺色嗰邊 #536471 本身有 5.9，唔使郁。 */
  --ink: #E7E9EA; --muted: #8B9198; --line: #2F3336; --line-2: #202327;
  --accent: #1D9BF0; --accent-text: #1D9BF0; --on: #FFFFFF; --on-ink: #000000; --danger: #F4212E; --warn: #FFD400;
  --blur: rgba(0,0,0,.72); --blur-2: rgba(0,0,0,.85); --scrim: rgba(91,112,131,.4); --ghost: rgba(255,255,255,.07);
  /* 示範提示卡專用底色（老細 2026-09-19：「其他顏色背景」）—— 要一眼睇得出
     「呢嚿嘢唔係你啲內容」。用強調色調出嚟嘅淡藍,唔開新色系。
     ⚠️ 唔用 color-mix:舊 WKWebView 唔識,唔識嗰陣會連底色都冇,變成透明貼住啲帖。 */
  --note-bg: #11212E; --note-line: #1E4157;
  --sat: env(safe-area-inset-top, 0px); --sab: env(safe-area-inset-bottom, 0px);
  --sal: env(safe-area-inset-left, 0px); --sar: env(safe-area-inset-right, 0px);
  --hdr: 44px; --tab: 49px;
  /* 搜尋欄高度 —— `#sbar` 嘅 `.sbox` 40 ＋ 下面 8 罅。寫死係刻意:搜尋版要**永遠**
     留返呢忽位(見下面 `[data-page="search"]`),唔可以等 JS 度完先知。 */
  --sb: 48px;
  color-scheme: dark;
}
/* 淺色:同一套結構,淨係換色。data-theme 由 index.html 個 inline script 喺畫之前貼上去,唔會閃一下黑 */
:root[data-theme="light"] {
  /*
   * ⚠️ 底色**唔係純白**（用戶 2026-09-17：「背景改返單一白色，不過唔好咁白，
   *    要睇得舒服既白」）。純白 #FFF 喺手機全螢幕咁大一塊會刺眼,
   *    尤其夜晚同室內。#FAFBFC 係差唔多一級嘅暖灰白 —— 望落仲係白,
   *    但唔會撐眼。
   * ⚠️ 卡同張紙要**比底色白**先分得出層次,所以 `--card` 留返純白。
   *    兩者反轉（底白、卡灰）嘅話，成版嘢會望落似俾人 disable 咗。
   */
  /* ⚠️ `--card` 同 `--bg` **一樣色**（用戶 2026-09-17：「淺色要統一為一隻色，
     我見有 2 隻白色」）。本來卡係純白、底係 #FAFBFC，兩隻白撞埋一齊望落唔乾淨。
     卡同底之間靠嗰條 `--line` 幼線分開就夠 —— iOS 原生清單都係咁。
     ⚠️ `--raise` 唔算「白」：佢係輸入格同藥丸嘅填色，要同底色分得出先知撳得。 */
  --bg: #FAFBFC; --bg-2: #F1F5F6; --card: #FAFBFC; --raise: #EDF2F3;
  --ink: #0F1419; --muted: #536471; --line: #CFD9DE; --line-2: #EFF3F4;
  /* ⚠️ `--accent-text` 係「藍色字」專用,同做底色嗰隻 `--accent` 分開。
     淺色底下 #1D9BF0 做字只有 **2.9:1**（要 4.5）—— 2026-09-18 逐個元素量深淺色
     嗰陣捉到:標籤「#議息」「#穿搭」嗰啲喺淺色模式下淺到睇唔清。
     做底色嗰隻唔可以一齊改暗,否則所有藍底變晒深藍。 */
  --accent: #1D9BF0; --accent-text: #0F6AA8; --on: #0F1419; --on-ink: #FFFFFF; --danger: #F4212E; --warn: #8A6100;
  --blur: rgba(255,255,255,.85); --blur-2: rgba(255,255,255,.92); --scrim: rgba(0,0,0,.35); --ghost: rgba(0,0,0,.06);
  --note-bg: #E8F4FD; --note-line: #BCDCF5;
  /*
   * ⚠️ 漸變底**拆咗**（用戶 2026-09-17：「背景改返單一白色」）。
   *    2026-09-16 加過（「淺色改為淺色漸變色背景」），試完唔要。
   *    `--bg-grad` 留空 —— `body` 嗰句 `background-image: var(--bg-grad, none)`
   *    照樣讀得到，唔使改第二度。
   */
  color-scheme: light;
}
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; scrollbar-width: none; }
*::-webkit-scrollbar { display: none; width: 0; height: 0; }   /* 用戶原話「右邊條BAR唔要」;WKWebView 原生嗰條喺 ShareInboxPlugin.load() 熄 */
/* ⚠️ `html` 都要有底色 —— 碌過頭嗰下（rubber band）露出嚟嘅係 `html` 後面嗰塊，
   唔上色就見到 WebView 自己嘅黑底（用戶 2026-09-17：「向下拉時出現黑底」）。
   `body` 有色都唔夠:body 只係內容嗰塊，彈出嚟嗰截係喺佢之外。 */
html { height: 100%; background: var(--bg); }
/* 唔好加 overscroll-behavior: none:iOS 16+ 會真係熄咗 rubber band(用戶原話「碌到最頂或最底都要加返動態效果」)。
 * 淨係唔加仲未夠:Capacitor 本身熄咗 scrollView.bounces,ShareInboxPlugin.load() 負責開返。 */
/*
 * ── 邊度揀得到字 ────────────────────────────────────────────────────
 *
 * ⚠️ 老細 2026-09-19 影咗張圖:長撳側欄,成塊側欄嘅字俾人選中晒,
 *    仲彈咗 iOS 嗰條 Copy / Look Up / Translate 出嚟。佢原話：
 *    「成個 APP 除左 POST 入面既 TOPIC 同輸入框入面文字 同作者名，
 *      其他地方都唔可以 HIGHLIGHT 到」。
 *
 * ⚠️ 所以**預設全部唔准揀**,再逐個位開返。開返嘅只有「你真係會想複製」嗰幾樣:
 *      內文（.txt / .d-txt）、作者名（.who）、主題同標籤藥丸（.lb）、輸入格。
 *    掣、側欄、設定、底欄、日期呢啲一律唔准 —— 長撳佢哋只會誤選,冇人想複製。
 * ⚠️ `-webkit-touch-callout: none` 都要:iOS 嘅長撳選單係另一件事,
 *    淨係熄 user-select 佢照彈。
 * ⚠️ 開返嗰啲要連 `-webkit-touch-callout: default` 一齊,唔係揀到都撳唔出「複製」。
 */
body, .nav, #tabs, #hdr, .rowi, .act, .btn, .pill, .lb, button {
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.txt, .d-txt, .who, .lb, input, textarea, [contenteditable="true"] {
  -webkit-user-select: text; user-select: text; -webkit-touch-callout: default;
}

body { margin: 0; min-height: 100%; background: var(--bg); background-image: var(--bg-grad, none);
  background-attachment: fixed; color: var(--ink);
  font: 15px/1.4 -apple-system, BlinkMacSystemFont, "PingFang HK", "PingFang TC", "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
input, textarea { font: inherit; color: inherit; }
.ic { display: inline-block; vertical-align: middle; flex: none; }
[hidden] { display: none !important; }

/* ── Header:安全區 + 44pt,左隨機、中 wordmark、右設定,同 Threads 一樣 ── */
/*
 * ⚠️ 搜尋頁嗰陣頂欄要 `fixed` 唔可以係 `sticky`。
 *    **sticky 頂唔住 iOS 嘅橡筋** —— 你拉到最頂／推到最底,成塊內容連個 sticky
 *    頂欄一齊郁走,搜尋欄同標題就一齊消失
 *    （用戶 2026-09-17：「個搜尋欄同搜尋字拉到最頂 2 樣野都會消失左」）。
 *    `#tabs` 一路都係 `fixed`,所以佢冇呢個問題。
 * ⚠️ 點解唔全部版都 `fixed`:其餘版有「碌落去自動收埋頂欄」,
 *    `fixed` ＋ 固定上內距嘅話,收埋之後頂部會空咗一截。
 *    搜尋頁唔會自動收埋(嗰度要打字),所以先至安全。
 */
body.searching #hdr { position: fixed; left: 0; right: 0; top: 0; }
/*
 * ⚠️ 留返俾頂欄同搜尋欄嗰忽位,**掛喺搜尋版自己身上,而唔係掛喺 `main` 上面**。
 *
 *    本來寫 `body.searching main { padding-top }`。但 `body.searching` 喺**掃版期間係關住嘅**
 *    （`chromeFor()` 有 `chromePreview` 閘住,唔准掃到一半改版面）——
 *    於是入緊嚟嗰版冇留位,空狀態嗰段字擠晒上搜尋欄下面,掃完大約 0.45 秒之後
 *    先自己跳返落去中間（老細 2026-09-17 錄影,第 114–134 幀同 220–235 幀各一次）。
 *
 *    掛喺版盒上面就兩個狀態一模一樣:
 *      · 掃版中 —— 盒係 `position: absolute` 釘喺畫面頂,padding 151 剛剛好等於
 *        頂欄(sat+44)＋搜尋欄(48),即係佢哋遮住嗰忽
 *      · 定咗形 —— `body.searching` 令頂欄變 `fixed` 離開文流,`main` 由畫面頂開始,
 *        同一個 padding 一樣啱
 * ⚠️ 唔可以兩邊都寫 —— 由 release 到收尾嗰 180–340ms 之間,`body.searching` 已經開咗
 *    而兩層仲係 absolute,兩個 padding 就會疊埋,成版跌低多 151。
 */
#main > [data-page="search"] { padding-top: calc(var(--sat) + var(--hdr) + var(--sb)); }
#hdr { position: sticky; top: 0; z-index: 10; padding-top: var(--sat);
  background: var(--blur); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); }
/* ⚠️ `min-height` 唔係 `height` —— 篩緊多個主題／標籤嗰陣下面嗰行字會摺兩三行，
      寫死高度就會撐爆出去撞住下面第一張卡（用戶 2026-09-17 影咗張圖：
      「依部份可以開幾行顯示曬所有文字，底果行下面留返小小空間，依家太迫」）。 */
.hdr-row { min-height: var(--hdr); display: grid; grid-template-columns: 56px 1fr 56px; align-items: center;
  padding: 0 var(--sar) 0 var(--sal); }
.hdr-row .wm .ic-mark { display: block; margin: 0 auto; }
.hdr-row .wm { text-align: center; font-weight: 800; font-size: 19px; letter-spacing: 1px; }
/* ⚠️ 下面留返一點空間 —— 貼住下面第一張卡就太迫（用戶原話）。
      `line-height` 開返鬆啲，摺兩三行嗰陣先睇得舒服。 */
.hdr-row .wm small { display: block; font-weight: 500; font-size: 12px; color: var(--muted);
  letter-spacing: 0; margin-top: -1px; margin-bottom: 6px; line-height: 1.5; }
.hbtn { width: 56px; height: var(--hdr); display: grid; place-items: center; color: var(--ink); }
.hbtn:active { opacity: .5; }
/* 篩選 pills:Threads 式空心圓角,揀中反白 */
/* ⚠️ 用戶 2026-09-16「佔太多，可以細返啲」—— 分類掣搬咗去側欄之後，呢行淨係
   講「而家篩緊乜」，唔使再企得咁大。34→28 高、字 14→13。 */
/* 備忘錄一覽 —— 一行一則，同 Apple 個備忘錄一樣:粗體第一行，下面日期加頭幾隻字 */
.notelist { display: flex; flex-direction: column; }
/*
 * 備忘錄一覽嘅字（用戶 2026-09-16：「依頁啲中文字體好醜樣 要改」「大細都要」）。
 *
 * ⚠️ 中文唔可以照搬英文嗰套:
 *   · **700 太重。** PingFang 嘅 Bold 筆劃好粗，一行十幾個方塊字排埋一齊會黑成一撻。
 *     600（Semibold）先係 iOS 中文介面嘅慣例。
 *   · **行高要鬆。** 拉丁字母 1.35 夠，方塊字要 1.5 以上先唔會迫埋一舊。
 *   · **主次要拉開。** 本來 17 對 14（差 3 點）—— 兩行字睇落差唔多大，
 *     分唔出邊句係標題。改成 16 對 13，再靠顏色同字重拉開。
 *
 * ⚠️ 省略號嗰個係真 bug:第二行本來係 `display: flex`（為咗擺個平台圖案），
 *    而 **flex 容器嘅 `text-overflow: ellipsis` 唔生效** —— 所以啲字係硬生生
 *    喺右邊切斷，一個「…」都冇（用戶張圖見到「西多士‘」）。
 *    而家個圖案同段字各自一個 inline 仔，段字嗰個先做省略。
 */
/* ⚠️ 寫死最低高度 —— 兩邊（貼文／留言）嘅行一定要一樣高（用戶 2026-09-17：
   「貼文同留言個高度不一」）。留言嗰邊第二行多咗個平台圖案,
   靠內容自己撐高就會受字體 fallback 影響,兩邊差開幾點。
   24（標題）＋ 3（罅）＋ 18（第二行）＋ 27（上下 padding）= 72。 */
.noterow { display: block; width: 100%; text-align: start; padding: 13px 16px 14px;
  min-height: 72px; border-bottom: 1px solid var(--line); }
.noterow b { display: block; font-size: 16px; font-weight: 600; line-height: 1.5;
  letter-spacing: .01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ⚠️ 12 係地板 —— `ui-audit.mjs` 報「字級細過 12」。再細就係細到唔應該。 */
/* ⚠️ 第二行寫死 18 點高 —— 唔寫死嘅話有圖案嗰邊會俾個圖案撐高,
   而圖案幾高係睇字體／平台,唔係我哋話事。 */
.noterow span { display: flex; align-items: center; gap: 5px; margin-top: 3px;
  color: var(--muted); font-size: 12px; line-height: 18px; height: 18px; min-width: 0; }
/* ⚠️ 圖案寫死 13×13 —— 唔寫死嘅話佢會跟住字體走,而字體 fallback 一變就撐高成行 */
.noterow span .ic { flex: none; width: 13px; height: 13px; align-self: center; }
.noterow span i { font-style: normal; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.noterow:active { background: var(--raise); }
/* 編輯器:張紙撐到同詳情頁一樣高，打字格食晒中間，成行掣定喺底 */
#note .sheet-body { height: calc(100% - var(--sat) - 24px - var(--kb)); display: flex; flex-direction: column; }
#note .sheet-body > .inp { flex: 1; min-height: 200px; border: none; background: none; padding: 4px 0;
  font-size: 17px; line-height: 1.55; }
/* ⚠️ 打字格先係主角 —— 佢至少佔 200 點，標嘢嗰段唔可以食佢。
   標嘢嗰段自己捲（最多三成屏），唔好逼到成行掣出界。 */
#note-toggle { flex: none; display: flex; align-items: center; gap: 8px; width: 100%; height: 44px;
  border-top: 1px solid var(--line); color: var(--muted); font-size: 14px; font-weight: 600; }
#note-toggle span { margin-right: auto; }
#note-toggle .ic { flex: none; }
#note-toggle:active { color: var(--ink); }
/*
 * ⚠️ 攤開／摺埋要**過渡**，唔可以 `hidden` 一開一關（用戶 2026-09-16：
 *    「所有彈出黎既野都要慢慢出，而唔係一野彈出彈走」）。
 *    `display` 冇得過渡，所以用 `grid-template-rows: 0fr → 1fr` ——
 *    呢招唔使寫死高度，入面幾多粒藥丸都啱（將來加減主題都唔使改呢度）。
 * ⚠️ 入面嗰層一定要 `min-height: 0` ＋ `overflow: hidden`，
 *    唔係 grid 仔唔會縮，摺唔埋。
 */
#note .sheet-body > #note-more { flex: none; display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows var(--t-in) var(--ez); }
#note .sheet-body > #note-more.open { grid-template-rows: 1fr; }
#note-more > .more-in { min-height: 0; overflow: hidden; }
/* ⚠️ 下邊界用 mask 漸隱 —— 呢個捲動區嘅底係硬切嘅,一行藥丸啱啱好踩住條邊
   就會俾斬一半（用戶 2026-09-17 指過一次）。漸隱之後嗰半粒會淡出,
   望落係「仲有嘢喺下面」而唔係「壞咗」。用 mask 唔使加多層 DOM。 */
#note-more.open > .more-in { overflow-y: auto; max-height: 40vh; padding-bottom: 6px;
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 22px), transparent); }
#note .sheet-body > .btns { margin-top: 0; }

.chips { display: flex; gap: 6px; overflow-x: auto; padding: 2px 12px 7px; scrollbar-width: none; border-bottom: 1px solid var(--line); }
.chips::-webkit-scrollbar { display: none; }
/* 空分類嗰句 —— 唔係掣，唔好扮成掣 */
.chip-note { display: inline-flex; align-items: center; color: var(--muted); font-size: 13px; white-space: nowrap; padding: 0 4px; }
.chip { flex: none; height: 28px; padding: 0 11px; border-radius: 8px; border: 1px solid var(--line); color: var(--ink);
  font-size: 13px; font-weight: 600; display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.chip .ic { width: 14px; height: 14px; color: var(--muted); }
.chip .n { color: var(--muted); font-weight: 500; }
.chip.on { background: var(--on); color: var(--on-ink); border-color: var(--on); }
.chip.on .ic, .chip.on .n { color: var(--on-ink); opacity: .7; }

/* ── 主內容:底部留 tab bar 位 ── */
/*
 * ⚠️ `min-height` 2026-09-18 由 `60vh` 改成「填到視窗底」。
 *    老細原話：「係我的紀錄，下小小既空白位置用手指掃唔到左右」。
 *    死因：掃版嗰三個 touch handler 全部綁喺 `#main`（見 app.js `wirePageSwipe`），
 *    而 `60vh` 喺 956 點高嘅機只有 574 點 —— `#main` 680 點就完，
 *    導航欄喺 873 點，中間 **193 點空白根本唔喺 `#main` 入面**，
 *    手指擺落嗰度 `touchstart` 一世唔會行。內容少嗰幾版（我的紀錄、合集、
 *    篩剩幾件嘅時間線）全部中招,內容夠長就啱返 —— 所以一直時好時壞捉唔實。
 *    `box-sizing: border-box`，所以 `min-height` 已經食埋下面嗰 95 點 padding，
 *    唔會多咗一截捲得郁嘅嘢。
 */
main { padding: 0 var(--sar) calc(var(--tab) + var(--sab) + 12px) var(--sal); min-height: calc(100vh - var(--sat) - var(--hdr)); }
.feed { max-width: 620px; margin: 0 auto; }

/* ── 一則 post:X 嘅格局 ── */
.post { display: grid; grid-template-columns: 36px 1fr; gap: 10px; padding: 12px 12px 4px 10px; border-bottom: 1px solid var(--line); width: 100%; text-align: left; }
.post:active { background: var(--bg-2); }
.av { position: relative; width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center;
  color: #fff; font-weight: 700; font-size: 16px; }
.av .badge { position: absolute; right: -4px; bottom: -4px; width: 19px; height: 19px; border-radius: 50%; background: var(--bg);
  display: grid; place-items: center; }
.av .badge .ic { width: 14px; height: 14px; }
.body { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.who { display: flex; align-items: baseline; gap: 5px; font-size: calc(var(--fs) - 1px); color: var(--muted); min-width: 0; }
.who b { color: var(--ink); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.who span { white-space: nowrap; }
/*
 * 內容字級 —— 老細 2026-09-19：「發現我地啲字比人地大，整個設定比用戶選擇字體，
 * 大中小，預設小 同 THREAD 一樣大小」。
 *
 * ⚠️ 三檔全部由 `--fs` 一個數話事,唔准逐個 class 各寫一套 ——
 *    否則加多一檔就要改十幾處,一定有處漏,而漏咗**唔會有任何錯誤訊息**,
 *    淨係某一忽字唔跟你揀嗰檔。
 * ⚠️ 預設係**小 15px**（Threads 嘅內文就係呢個數）。舊版寫死 16,即係
 *    成條時間線一直大過人哋一級。作者行同詳情頁跟住 `--fs` 上下差一級,
 *    唔可以寫死,否則揀「大」之後作者名仲細過內文。
 */
:root { --fs: 15px; }
:root[data-fs="m"] { --fs: 17px; }
:root[data-fs="l"] { --fs: 19px; }
.txt { font-size: var(--fs); line-height: 1.45; white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere; }
.txt.title { font-weight: 700; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
/*
 * ── 長文「顯示更多」（老細：「過左黎 KEPT 都會係顯示更多，同都係可以返打開顯示全文」）──
 *
 * ⚠️ 本來 `.txt` 成塊用 `-webkit-line-clamp:10` 硬摺，冇得撳開 —— `line-clamp`
 *    冇得 transition，一改就即刻跳，同「所有野都唔係閃過去，係移動過去」相反。
 *    改用 `max-height`（可以過渡嘅屬性），摺埋高度揀到同以前個 10/12 行差唔多，
 *    望落同舊版一樣，淨係加咗條郁得到嘅路。實際有冇爆、爆咗先出粒掣，由
 *    `app.js` 嘅 `measureClamp()` 度 `scrollHeight > clientHeight` 判斷。
 * ⚠️ 時間同曲線**唔自己開新數**——開用 `--t-in`/`--ez`（成個 app「入場、移動」嗰兩個），
 *    收用 `--t-out`/`--ez-out`（「出場」嗰兩個）。`.collapsing` 呢個 class 淨係負責
 *    切返做「出場」嗰組，撳「收起」嗰下由 `toggleClamp()` 加，過渡完由佢除返。
 */
.txt.clamp, .d-txt.clamp { overflow: hidden; transition: max-height var(--t-in) var(--ez); }
.txt.clamp { max-height: 14.5em; }   /* 10 行 @ line-height 1.45 */
.d-txt.clamp { max-height: 18em; }   /* 12 行 @ line-height 1.5 */
.txt.clamp.collapsing, .d-txt.clamp.collapsing { transition-duration: var(--t-out); transition-timing-function: var(--ez-out); }
.more-btn { display: flex; align-items: center; height: 44px; padding: 0; margin: 0; color: var(--accent);
  font-size: 14px; font-weight: 700; background: none; border: none; text-align: left; }
/*
 * ⚠️ 底色**唔可以有** —— 老細 2026-09-19：「我唔想見到啲圖有黑邊」。
 *    個盒有底色嘅話,張相同個框一有少少對唔齊（例如比例一時未知）,
 *    嗰條底色就變成一條「黑邊」。透明嘅話,對唔齊嗰下你見到嘅係卡本身,
 *    唔會突然多咗一條深色帶。
 */
/*
 * ⚠️ 媒體收窄到卡闊度嘅 **85%**、居中（老細 2026-09-19：
 *    「但 THREAD 果個細啲，可以整體咁按比例細返啲」「圖同片都係」）。
 *    Threads 嗰邊同一篇望落細一截,我哋本來係成行撐滿。
 * ⚠️ 收嘅係**個盒嘅闊度**,唔係加 `max-height` —— 加高度上限就會出現
 *    「個框同張相比例唔同」,而嗰個正正係黑邊嘅來源（今日拆咗成日）。
 *    收闊度就係整體按比例縮細:橫相直相一齊細,比例一個字都冇變。
 * ⚠️ **靠左**,唔居中（老細 2026-09-19：「片同相對齊返文字，左邊」）——
 *    左邊要同上面段文字同一條線,右邊留白。居中嘅話兩邊都同文字對唔齊,
 *    成張卡會望落散。所以係 `margin-inline: 0 auto`（左 0、右 auto）。
 */
.media { width: 85%; margin-top: 4px; margin-inline: 0 auto; border-radius: 16px; border: 1px solid var(--line); overflow: hidden; }
/*
 * ⚠️ **唔准裁相**（老細 2026-09-18：「改為同拎落黎個樣係一樣」）。
 *
 *    舊版寫 `max-height: 520px` ＋ `object-fit: cover`,兩樣夾埋就係個病:
 *    一張直度嘅截圖(例如 3:4、9:16)喺 393 點闊之下本來應該高過 520,
 *    俾 `max-height` 封住之後個框變咗 393×520 —— 而 `cover` 嘅做法係
 *    **將張相放大去填滿個框,再裁走出界嗰啲**。
 *    老細原話：「人地張圖片係睇得曬內容，我個APP就睇得幾個字，放到好大」——
 *    「放到好大」就係 cover 嗰下放大,「睇得幾個字」就係裁走咗嘅部分。
 *
 * ⚠️ 修法唔係轉 `contain`:`contain` 係將張相縮細塞入個 393×520 嘅框,
 *    左右兩邊會留低成八十點嘅空帶,望落似張相壞咗。
 *    要**個框本身就跟返張相嘅比例** —— 咁就冇得裁,亦都冇空帶。
 *
 *    `min(100%, 520px * ar)` 就係咁:
 *      橫相(ar 大) → `520px * ar` 大過成行闊 → 出 100%,同舊版一樣撐滿。
 *      直相(ar 細) → 出 `520px * ar`,即係「高度啱啱好 520 嗰陣嘅闊度」,
 *                    張相企喺中間、窄啲,但**完整**。
 *    個框同張相比例一致,所以唔使 `object-fit`（點都唔會變形）,
 *    亦都唔使 `max-height`（高度已經封咗喺 520）。
 *
 * ⚠️ `aspect-ratio` 照留 —— 冇佢個 <img> 未載到就係 **0 點高**,
 *    載到嗰下由 0 彈到真高度,下面所有嘢一齊向下抌。
 *    2026-09-16 量實:一張卡 266 → 478 點,成份時間線 16524 → 18025 點。
 *    四支尺全部報綠(冇節點俾人拆、冇空白幀、幀長正常),因為佢哋量嘅係
 *    「有冇重畫」,唔係「有冇郁位」。呢個要第五支尺 `cls-audit.mjs` 先量得到。
 * ⚠️ fallback 由 `3 / 2` 改成 `1.5`(同一個數,寫法唔同) —— 因為佢而家要入
 *    `calc()` 做乘數,`3 / 2` 嗰種寫法喺 `calc` 入面唔計得。片嗰個同理:16/9 → 1.778。
 * ⚠️ `var(--ar, …)` 入面嗰個 fallback 只係第一次見嗰張圖用。
 *    真實比例由 `app.js` 喺圖載到嗰下量返並且記住(`mediaAR`),
 *    之後由第一幀就已經係啱嘅高度,一點都唔會郁。
 *    1.5 係度返啲示範相片嘅中位數(1.46–1.51)。
 */
/*
 * ⚠️ **冇高度上限。** 老細 2026-09-19：「啲圖唔好固定 SIZE，要跟返佢原本 POST 個 SIZE」。
 *    之前寫 `min(100%, 520px × ar)` —— 直度嘅相會收窄咗擺中間,唔算裁,
 *    但都唔係「原本個樣」。而家成行闊 ＋ 佢自己嘅比例,即係同原帖一模一樣。
 *    代價:一張 9:19.5 嘅手機截圖會佔成個畫面高 —— 呢個係老細拍板嘅取捨。
 */
/* ⚠️ `contain` 係**保險**:個框靠 `--ar`,而 `--ar` 有機會一時未知（第一次見嗰張圖）。
   冇呢句嘅話 `<img>` 預設 `fill`,即係硬扯到啱個框 —— 老細 2026-09-19：「啲圖壓縮曬」。
   `--ar` 啱嗰陣呢句冇任何作用;`--ar` 未知嗰陣佢保住唔變形。唔用 `cover`（嗰個會裁）。 */
/*
 * ⚠️ `var(--ar)` **冇後備值** —— 呢個係特登嘅。
 *    寫 `var(--ar, 1.5)` 即係「唔知比例就當佢 1.5」,而只要估錯,
 *    個框同張相就唔一致 → `contain` 留低空帶（老細：「我唔想見到啲圖有黑邊」）。
 *    CSS 入面 `var(--ar)` 喺 `--ar` 未設嗰陣係 invalid-at-computed-value-time,
 *    成句 `aspect-ratio` 會跌返做 `auto` —— 即係**張相自己撐開**,永遠冇帶。
 * ⚠️ 代價:未見過嘅圖喺載入嗰一刻冇霸位,下面會抌一抌。
 *    但而家絕大部分情況都知比例（抽嗰陣 Threads／IG 個 JSON 已經俾咗 w/h,
 *    `enrichPending` 即刻 `arRemember`），所以呢個代價好細,
 *    而「成日見到黑邊」係老細日日見到嘅嘢。
 * ⚠️ `contain` 照留做保險:萬一 `--ar` 係舊嗰張圖留低（`thumb-<id>.jpg` 會重用同一條路徑),
 *    寧願letterbox一幀都好過扯到變形 —— 張圖一載到,load handler 就會校返啱。
 */
.media img { width: 100%; aspect-ratio: var(--ar); object-fit: contain; display: block; }
/*
 * ⚠️ 片同相一樣:**冇後備比例、冇黑底**。
 *    老細 2026-09-19：「第一個 POST 都仲係有」—— 我拆咗圖嗰個後備,但漏咗條片。
 *    佢第一篇條片真比例係 **0.462**（好直）,塞入 `1.778` 個橫框,
 *    左右就係兩大條 `background: #000` —— 即係最刺眼嗰種黑邊。
 * ⚠️ `background: #000` 一定要拆:片本身唔會透光,個底色淨係喺
 *    「個框大過條片」嗰陣先見到 —— 而嗰個情況就係我哋要杜絕嘅嘢。
 */
.media video { width: 100%; aspect-ratio: var(--ar); display: block; }
/*
 * ⚠️ 片嘅黑邊**唔係 CSS 底色**,係播放引擎喺「個框大過條片」嗰陣自己畫上去嘅 ——
 *    改 `background` 冇用（我試過拆走 `#000`,老細照樣話「片都唔要有黑邊」）。
 *    唯一杜絕方法係個框由第一刻就啱,而片嘅比例要等 `loadedmetadata` 先知。
 * ⚠️ 所以:**未知比例之前唔好畫佢**。知道咗（JS 落咗 inline `--ar`）先現身。
 *    用 `visibility` 唔用 `display` —— `display:none` 會令 WebKit 唔去攞 metadata,
 *    咁就永遠等唔到,變成一條永遠唔出現嘅片。
 * ⚠️ `--ar-wait` 係保險:3 秒都攞唔到 metadata（壞檔、冇 codec）就照畫出嚟,
 *    寧願見到黑邊都好過見到一片空白 —— 由 app.js 嗰個計時器除返個 class。
 */
.media video:not([style*="--ar"]):not(.ar-ready) { visibility: hidden; }
/*
 * 多圖帖 —— **直向排,逐張成行闊,各自用自己嘅比例**。
 *
 * ⚠️ 本來係 2 格正方形格仔 ＋ `object-fit: contain`（為咗唔裁）。結果橫相塞入
 *    正方形格,上下就留低兩條空帶 —— 老細 2026-09-19：「有啲圖有黑邊，改善」。
 *    正方形格同「唔准裁」呢兩樣本質上夾唔埋:個格鎖死咗比例,
 *    唔裁就一定要留白,留白就係黑邊。
 * ⚠️ 所以唔再鎖格:一行一張、跟自己嘅 `--ar`。咁就同原帖一模一樣 ——
 *    唔裁、唔變形、冇空帶（老細一路要求嘅「圖係對返圖」「跟返佢原本 POST 個 SIZE」）。
 *    代價:四張圖嘅帖會好長。呢個係老細揀咗「忠於原帖」之後嘅必然結果。
 * ⚠️ `aspect-ratio` 一定要留 —— 冇佢啲圖未載到就 0 點高,下面成條時間線會抌。
 */
.media.multi { display: grid; grid-template-columns: 1fr; gap: 2px; }
.media.multi img, .media.multi video { width: 100%; aspect-ratio: var(--ar); max-height: none; object-fit: contain; }
.media.multi video { aspect-ratio: var(--ar); }
/* ⚠️ 由 <div> 改咗做 <button>（撳落去開原文），所以要校返 button 嘅預設:
   文字要靠左（button 預設置中）、字型要繼承（button 唔繼承）、闊度要撐滿。
   同時加按壓回饋 —— 一件撳得嘅嘢冇回饋，人哋會以為撳唔到。 */
.linkcard { margin-top: 4px; border: 1px solid var(--line); border-radius: 14px; padding: 12px 14px; display: grid; grid-template-columns: 36px 1fr; gap: 12px; align-items: center; background: var(--bg-2);
  width: 100%; text-align: left; font: inherit; color: inherit; }
.linkcard:active { background: var(--raise); }
.linkcard .lc-ic { width: 36px; height: 36px; border-radius: 10px; background: var(--raise); display: grid; place-items: center; color: var(--ink); }
.linkcard > span:last-child { display: block; min-width: 0; }
.linkcard .lc-t { display: block; font-size: 14px; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.linkcard .lc-d { display: block; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 你嘅筆記 = 你喺呢個 post 下面嘅回覆,同 Threads 一樣 */
.reply { display: grid; grid-template-columns: 24px 1fr; gap: 10px; align-items: start; margin-top: 4px; padding: 8px 10px 8px 8px;
  border-radius: 12px; background: var(--raise); }
/* ⚠️ 本來入面係 t('noteShort')（「Me」／「我」）11px —— 過唔到 12px 嗰條線,
   而且隔籬本身已經寫住「我的筆記」,個圈係多餘。改咗出支筆:
   一個圖示唔使譯,亦唔使賭十二種語言嗰兩個字塞唔塞到入 24px 個圈。
   個字留喺 aria-label,讀屏照讀得返。 */
.reply .av { width: 24px; height: 24px; background: var(--ink); color: var(--bg); }
.reply .rt { font-size: 14px; color: var(--ink); white-space: pre-wrap; word-break: break-word;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.reply .rt small { display: block; color: var(--muted); font-size: 12px; margin-bottom: 1px; }
.labels { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.lb { font-size: 12px; color: var(--muted); border: 1px solid var(--line); border-radius: 6px; padding: 2px 7px; display: inline-flex; align-items: center; gap: 4px; }
.lb .ic { width: 12px; height: 12px; }
.lb.tag { color: var(--accent-text); border-color: transparent; padding-left: 0; }
/* KP02「原帖已刪」——紅色,同 delete/heart 用返同一隻 --danger,唔開新色 */
.lb.gone { color: var(--danger); border-color: var(--danger); }
/* KP03 待辦／已完成 —— 藍色跟 .act.lit 一套色;已完成再淡少少,似「劃咗線」嘅感覺 */
.lb.todo { color: var(--accent); border-color: transparent; }
.lb.todo.done { opacity: .6; }
/* 動作行:跟 Threads,靠左一排,粒同粒之間好近 */
.acts { display: flex; justify-content: flex-start; gap: 6px; margin: 0 0 0 -8px; }
.act { height: 34px; padding: 0 8px; display: inline-flex; align-items: center; gap: 5px; color: var(--muted); font-size: 13px; border-radius: 17px; }
/* ⚠️ 卡上面啲動作圖案要粗啲（用戶 2026-09-16：「我指圖案改粗」）。
   整套 icon 預設 stroke-width 1.8（見 icons.js），喺 18px 嘅灰色圖案上面
   睇落好虛。呢度加到 2.4 —— 只加呢兩粒，唔郁成套。 */
.act .ic { width: 18px; height: 18px; stroke-width: 2.4; }
.act:active { color: var(--ink); background: var(--raise); }
/* 喜歡咗 —— 心心填實兼轉紅。⚠️ 要 fill 唔可以淨係轉色:得個框轉紅，
   喺深色底上面睇落似「未著但 hover 緊」，分唔出著定唔著。 */
.act.heart .ic { fill: var(--danger); stroke: var(--danger); }
/* KP03 待辦（.lit）／已完成（再加 .done）—— 完成之後淡返少少,似劃咗線咁嘅感覺,
   唔開新色，跟返 .lb.todo.done 同一套邏輯 */
.act.done { opacity: .6; }

/* 回收筒 —— 每則上面一條橫欄講仲有幾多日，同兩粒掣 */
/* chip 攤開嗰行 —— 就喺原本嗰行上面多一行，唔遮住時間線。
   ⚠️ 用 grid-template-rows 由 0fr 過渡到 1fr:高度唔使寫死，
      四種分類將來加減都唔使改呢度。 */
/* ⚠️ 自成一行,唔可以喺 `.chips` 入面 —— 嗰個係橫向捲動 flex 容器,
   塞入去會變成一條窄長條（見 app.js `renderChips()`）。 */
.chips-open { display: flex; flex-wrap: wrap; gap: 8px;
  padding: 0 calc(var(--sal) + 12px) 10px; border-bottom: 1px solid var(--line); }

/*
 * 排法側欄 —— 由左邊滑出（見 app.js `openSortNav()`）。
 * ⚠️ 同 sheet 一樣要 `will-change: transform` 只喺郁緊嗰陣加，唔好長期掛住。
 * ⚠️ 闊度用 `min(82vw, 320px)`:窄機唔好逼到得返一條，闊機唔好攤到成版。
 */
.nav { position: fixed; inset: 0; z-index: 25; }
.nav-bg { position: absolute; inset: 0; background: var(--scrim); opacity: 0; transition: opacity var(--t-in) var(--ez); }
.nav.open .nav-bg { opacity: 1; }
.nav-panel { position: absolute; left: 0; top: 0; bottom: 0; width: min(82vw, 320px);
  background: var(--bg); border-right: 1px solid var(--line);
  padding: calc(var(--sat) + 24px) 16px calc(var(--sab) + 16px);
  transform: translateX(-100%); transition: transform var(--t-in) var(--ez); will-change: transform;
  overflow-y: auto; }
.nav.open .nav-panel { transform: none; }
/* ⚠️ 收返埋快過滑出嚟 —— 郁走一件嘢唔使等，郁入嚟先需要時間睇清楚。
      兩邊同一個秒數會覺得收得拖泥帶水。秒數要同 app.js `closeSortNav()` 個 setTimeout 一樣。 */
/* 拖緊 —— 熄晒過渡，唔係手指郁一下就同 transition 打交（同 sheet 一樣道理） */
.nav.dragging .nav-panel, .nav.dragging .nav-bg { transition: none; }
/*
 * ⚠️ 黑罩同面板係**同一件嘢嘅兩半**,收埋嗰陣一定要同一條曲線。
 *
 *    老細 2026-09-19 錄影報「閃」。逐幀量到（模擬器,撳側欄入面一個排法）:
 *        時間    黑罩      面板
 *         41ms   0.67     −8
 *        107ms   0.14     −46      ← 成個畫面已經光返晒,塊面板仲企喺度
 *        341ms   0.00     −320
 *    黑罩少咗 `transition-timing-function`,於是跌返去 `.nav-bg` 本身嗰句 `--ez`,
 *    而 `--ez` 喺 37% 時間就行完 90%;面板用 `--ez-out`(慢起步、尾段先快)。
 *    **一個衝、一個拖**,結果係背景喺 100ms 內爆亮,跟住塊板先一野掃走 —— 就係嗰下閃。
 * ⚠️ 修法係補返同一條曲線,唔係調秒數:兩邊秒數本來就一樣(都係 --t-out),
 *    病喺曲線。呢種「漏咗一句,兩半各行各路」嘅嘢冇任何錯誤訊息,
 *    淨係望落怪怪哋,所以 `verify-motion.mjs` 有條尺守住。
 */
.nav:not(.open) .nav-panel { transition-duration: var(--t-out); transition-timing-function: var(--ez-out); }
.nav:not(.open) .nav-bg { transition-duration: var(--t-out); transition-timing-function: var(--ez-out); }
.nav-panel h2 { margin: 0 0 4px; font-size: 20px; font-weight: 800; }
.nav-row { display: flex; align-items: center; gap: 12px; width: 100%; height: 48px;
  padding: 0 12px; border-radius: 12px; font-size: 16px; color: var(--ink); text-align: left; }
.nav-row span { margin-right: auto; }
.nav-row .ic { color: var(--muted); flex: none; }
.nav-row.on { background: var(--raise); font-weight: 700; }
.nav-row.on .ic { color: var(--ink); }
.nav-row:active { background: var(--raise); }
/* 分類嗰組嘅細標題 —— 同上面排法分得開，但唔好喧賓奪主 */
.nav-panel h3 { margin: 18px 0 6px; font-size: 13px; font-weight: 700; color: var(--muted);
  letter-spacing: .02em; }
/* 主題／平台先至有下一層，粒箭嘴係話俾你知「呢行撳得開」 */
.nav-row .ic-chevron { color: var(--muted); flex: none; }
/*
 * 攤開嗰行 —— 用戶原話係「打開一行 Topic 選擇」，所以係**摺得落嘅一行細粒**，
 * 唔係再一疊 48 點高嘅列:側欄得 320 點闊，十幾個主題排成十幾行就要喺側欄度碌，
 * 而你本來只係想㩒一下揀個主題。
 * ⚠️ 要摺得到就唔可以 `overflow-x: auto`（#chips 嗰個係橫向捲動，
 *    2026-09-16 試過塞落去，四個分類直接竪成四行）。呢度用 flex-wrap。
 */
.nav-subs { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 0 10px 8px; }
.nav-sub { display: inline-flex; align-items: center; gap: 5px; height: 32px; padding: 0 11px;
  border-radius: 16px; border: 1px solid var(--line); font-size: 13px; font-weight: 600; }
.nav-sub .ic { color: var(--muted); flex: none; }
.nav-sub .n { color: var(--muted); font-size: 11px; font-weight: 700; }
.nav-sub.on { background: var(--on); color: var(--on-ink); border-color: var(--on); }
.nav-sub.on .ic, .nav-sub.on .n { color: var(--on-ink); }
.nav-sub:active { background: var(--raise); }
/* 攤開咗但空 —— 講一句，唔係扮成粒撳唔郁嘅掣 */
.nav-note { color: var(--muted); font-size: 13px; padding: 4px 4px 6px; }
/* 揀咗幾多個 —— 摺埋嗰陣一眼睇到呢個分類仲揀緊嘢 */
.npick { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: 9px; background: var(--on); color: var(--on-ink);
  font-size: 11px; font-weight: 800; margin-right: 2px; flex: none; }
@media (prefers-reduced-motion: reduce) {
  .nav-bg, .nav-panel { transition: none; }
}

.trash-row { border-bottom: 1px solid var(--line); }
.trash-bar { display: flex; align-items: center; gap: 8px; padding: 10px 16px 0; font-size: 13px; color: var(--muted); }
.trash-bar span { margin-right: auto; }
.trash-bar .btn { height: 32px; padding: 0 12px; font-size: 13px; }
.act.lit { color: var(--accent); }
.act.warn { color: var(--warn); }

/* ── 主題頁:2 欄封面格,有相就用相做封面 ── */
.page-h { padding: 18px 16px 6px; }
.page-h h2 { margin: 0; font-size: 22px; font-weight: 800; }
.page-h p { margin: 4px 0 0; color: var(--muted); font-size: 14px; }
.tgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 10px 16px 16px; }
.tile { position: relative; aspect-ratio: 1 / 1.08; border-radius: 16px; overflow: hidden; background: var(--raise);
  border: 1px solid var(--line-2); text-align: left; isolation: isolate; }
.tile:active { transform: scale(.98); }
.tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.tile .shade { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(0,0,0,.05) 30%, rgba(0,0,0,.82) 100%); }
.tile .ico { position: absolute; top: 12px; left: 12px; width: 34px; height: 34px; border-radius: 10px; display: grid; place-items: center;
  background: rgba(255,255,255,.14); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); color: #fff; }
.tile .ico .ic { width: 20px; height: 20px; }
.tile .big { position: absolute; right: -14px; bottom: 26px; color: var(--ghost); }
.tile .big .ic { width: 120px; height: 120px; stroke-width: 1.2; }
.tile .cap { position: absolute; left: 12px; right: 12px; bottom: 12px; color: #fff; }
.tile .cap b { display: block; font-size: 17px; font-weight: 800; }
.tile .cap span { font-size: 12px; opacity: .8; }
.tile .peek { position: absolute; left: 12px; right: 12px; bottom: 62px; color: rgba(255,255,255,.85); font-size: 12px; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* ── 清單頁(合集、設定):X 設定嗰種 row ── */
.rows { padding: 6px 0; }
.rowi { display: grid; grid-template-columns: 40px 1fr auto; align-items: center; gap: 12px; padding: 14px 16px; width: 100%; text-align: left; border-bottom: 1px solid var(--line-2); }
.rowi:active { background: var(--bg-2); }
.rowi .rico { width: 40px; height: 40px; border-radius: 12px; background: var(--raise); display: grid; place-items: center; color: var(--ink); }
.rowi .rl b { display: block; font-size: 15px; }
.rowi .rl span { color: var(--muted); font-size: 13px; }
.rowi .rr { color: var(--muted); display: inline-flex; align-items: center; gap: 4px; font-size: 13px; }
.rowi.static:active { background: none; }
/* 有新版:第二行變強調色,提示撳得入去 */
.rowi.upd .rl span { color: var(--accent-text); font-weight: 600; }
/* 外觀:一行兩粒細 pill,深色 / 淺色,揀中反白 */
/* 色寫喺 .seg 度俾 .pill 繼承,唔可以寫喺 .pill 度 —— 咁寫會贏咗 .pill.on 嗰句,反白嗰粒變同底同色 */
.rowi .seg { gap: 8px; color: var(--ink); }
.rowi .seg .pill { height: 32px; padding: 0 12px; font-size: 13px; }
.note-row { padding: 14px 16px; color: var(--muted); font-size: 13px; line-height: 1.55; border-bottom: 1px solid var(--line-2); }
.note-row b { color: var(--ink); display: block; margin-bottom: 4px; font-size: 14px; }

/* ── 空狀態 ── */
/*
 * 空白版 —— 一版嘢就佢自己一個，所以要**企正中間**，唔好浮喺三分一位跟住下面一大片空。
 *
 * ⚠️ 2026-09-17 用戶指住空白版:「依頁要固定，同下面啲格同文字唔岩位，要整靚」。
 *    兩個問題:① 成嚿嘢浮喺上面三分一,下面吉咗一大截;
 *    ② 下面兩粒掣排成一行,右邊嗰粒**爆咗出畫面**（「分享時找不到 Kept」俾切一半）——
 *       因為 `.btns .btn { flex: none }` 令佢哋唔縮亦都唔換行。
 * ⚠️ 呢個 ui-audit 一直報「爆出畫面:0」—— 因為佢每次都塞咗示範內容入去先量，
 *    空白版**根本冇出現過**。支尺量唔到一版佢從來冇見過嘅嘢。
 * ⚠️ 高度要扣埋頂欄同底欄（連安全區），否則「置中」會偏低 ——
 *    因為 100vh 唔計 iOS 嗰兩條 inset。
 */
.empty { text-align: center; color: var(--muted); line-height: 1.7; font-size: 15px;
  padding: 24px 24px calc(var(--tab) + var(--sab) + 24px);
  min-height: calc(100vh - var(--hdr) - var(--sat) - var(--tab) - var(--sab) - 24px);
  display: flex; flex-direction: column; align-items: center; justify-content: center; }
/* ⚠️ 搜尋版仲要減埋搜尋欄嗰 48 —— 唔減嘅話成塊嘢高咗 48,個中心跌低咗 24 又頂穿底 */
#main > [data-page="search"] .empty { min-height: calc(100vh - var(--hdr) - var(--sat) - var(--sb) - var(--tab) - var(--sab) - 24px); }
/* 空白版下面嗰兩粒掣:窄機打直排,唔好擠埋一行爆出畫面。
   ⚠️ `.btns` 本身係張紙底嗰條 sticky 掣列(position:sticky、負 margin、上邊線)——
      喺空白版度乜都唔要,所以全部覆蓋返。本來寫喺 app.js 做 inline style,
      搬咗落嚟,否則 inline 會蓋過呢度嘅嘢。 */
.btns.empty-btns { position: static; flex-direction: column; align-items: stretch;
  width: 100%; max-width: 300px; margin: 24px auto 0; padding: 0; border: 0; background: none; gap: 10px; }
.btns.empty-btns .btn { flex: none; justify-content: center; min-height: 46px; }
/* ⚠️ 一定要 `>` 直屬 —— 寫 `.empty .ic` 嘅話連兩粒掣入面嗰啲 16 點細圖案都會
   俾撐到 44 點，仲要孭埋個 12 點下邊距，於是圖案企得比隔籬啲字高一截。
   2026-09-17 用戶指住空白版嗰兩粒掣：「啲圖案仲係唔岩位」，就係呢個。 */
.empty > .ic { width: 44px; height: 44px; color: var(--line); margin-bottom: 12px; stroke-width: 1.4; }
.empty b { color: var(--ink); display: block; font-size: 18px; margin-bottom: 4px; }

/* 教學頁 —— 見 app.js `helpHtml()` */
.help { padding: 8px 16px calc(var(--tab) + var(--sab) + 24px); }
.help-sec { padding: 20px 0; border-bottom: 1px solid var(--line); }
.help-sec:last-child { border-bottom: 0; }
.help-h { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.help-h b { font-size: 17px; font-weight: 700; }
.help-h .ic { color: var(--muted); flex: none; }
.help p { margin: 0 0 8px; color: var(--muted); font-size: 15px; line-height: 1.6; }
.help p:last-child { margin-bottom: 0; }
/* ⚠️ 步驟要睇得出係一步一步，所以用數字唔用點。留白靠 counter 自己排，
      唔好用 padding-left 夾硬推 —— 兩位數嗰陣就會唔對齊。 */
.help-steps { margin: 0 0 10px; padding: 0; list-style: none; counter-reset: s; }
.help-steps li { counter-increment: s; position: relative; padding: 0 0 0 30px; margin-bottom: 8px;
  font-size: 15px; line-height: 1.6; }
.help-steps li::before { content: counter(s); position: absolute; left: 0; top: 1px;
  width: 21px; height: 21px; border-radius: 50%; background: var(--raise); color: var(--ink);
  font-size: 12px; font-weight: 700; display: grid; place-items: center; }

/* ── Tab bar:49pt + 底安全區,icon only,中間 ＋ 係主動作 ── */
#tabs { position: fixed; left: 0; right: 0; bottom: 0; z-index: 10; transition: transform var(--t-in) var(--ez); will-change: transform; height: calc(var(--tab) + var(--sab)); padding: 0 var(--sar) var(--sab) var(--sal);
  display: flex; background: var(--blur-2); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); border-top: 1px solid var(--line-2); }
/*
 * ⚠️ 未畫嘢之前唔好露條線（用戶 2026-09-16：「開 APP 時唔要下面依條線」）。
 *    `#tabs` 同 `#hdr` 喺 index.html 入面係空殼，等 `renderChrome()` 填 ——
 *    由開 app 到第一次 render 之間（要等 IndexedDB 讀完），
 *    畫面上就係一片黑加一條無端端嘅間線同一忽毛玻璃底。
 *    `:empty` 一過（填咗嘢）就自動變返正常，唔使喺 JS 度加任何 class。
 */
#tabs:empty, #hdr:empty { border: 0; background: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
#tabs.hide { transform: translateY(100%); }
/* 轉版嗰陣頂欄底欄要一步到位,唔好滑 —— 見 app.js `chromeShowNow()` */
#tabs.nojump, #hdr.nojump { transition: none; }
/* 釘住嗰啲行（時間線輸入掣、我的紀錄切換條）轉版嗰陣一樣要一步到位 —— 見 app.js `chromeNoAnim()` */
body.nojump #main > [data-page="note"] .tabseg { transition: none; }
#hdr { transition: transform var(--t-in) var(--ez); }
#hdr.hide { transform: translateY(-100%); }
/* ── 拉到頂 K logo 動畫(Threads 做法,用戶原話「佢個LOGO拉到最後有動畫」):
 * 手指拉住 → 成頁 rubber band 落嚟,header 跟住落,K 隨拉幾遠放大 + 微轉(--pull-s / --pull-r 由 app.js 每個 scroll event 更新);
 * 拉過門檻放手 → #hdr.ptr-spin,K 轉一圈,同時 drainInbox + enrichPending。
 * 拉緊嗰陣唔要 transition(跟手先似 Threads),放手先加返,彈返原大細嗰下就順。 ── */
#hdr .wm .ic-mark { transform: scale(var(--pull-s, 1)) rotate(var(--pull-r, 0deg)); transition: transform var(--t-in) var(--ez); transform-origin: 50% 50%; }
#hdr.pulling .wm .ic-mark { transition: none; }
#hdr.armed .wm .ic-mark { color: var(--accent); }
/*
 * ⚠️ 篩緊嘢嗰陣左上粒掣著藍（用戶 2026-09-16：「如有選 Categories，改為 K 字果隻藍色」）——
 *    篩選 chip 嗰行拆咗之後，如果粒掣同平時一模一樣，你就冇得一眼分到
 *    「而家係全部」定「而家淨係睇緊幾個主題」。同 K 字同一隻藍，一睇就知兩樣係同一件事。
 */
.hbtn.lit .ic { color: var(--accent); }
/* ⚠️ 呢個係上面三個秒數之外唯一嘅例外，而且係刻意:佢唔係「開啟或者移動」，
   係「你放手之後轉一個圈同你講收到」。同張紙升上嚟一樣快嘅話，轉唔夠一個圈就完。 */
#hdr.ptr-spin .wm .ic-mark { animation: ptr-spin .7s cubic-bezier(.3,.7,.3,1); }
@keyframes ptr-spin { from { transform: scale(1.2) rotate(0deg); } to { transform: scale(1) rotate(360deg); } }
/* 狀態列底:一條固定嘅模糊底永遠遮住頂部安全區。以前係 header 縮上去留返 --sat 咁多,
 * 但留低嗰截係 header 最底嘅 chips 條,結果 chips 疊喺時間 / 電池上面(用戶截圖「出現重疊情況」)。 */
body::before { content: ''; position: fixed; top: 0; left: 0; right: 0; height: var(--sat); z-index: 11; pointer-events: none;
  background: var(--blur); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); }
/*
 * 底部導航欄（老細 2026-09-18：「導航欄想整再靚啲」）。三處改動，逐個都有理由：
 *
 * ① **線粗唔再跟住狀態變。** 本來企緊嗰格由 1.7 加粗到 2.4 —— 五個圖案得一個粗咗,
 *    成排望落粗幼唔一、好似搖緊。而家全部 1.9,狀態淨係靠顏色同下面粒點分。
 * ② **企緊嗰格下面一粒點。** 冇字嘅 tab bar 淨靠顏色分,喺深色底上面對比好弱。
 *    一粒 4 點嘅圓點係最細嘅記號,唔會同任何現有形狀撞（ui-audit 嗰條
 *    「一種角色一個外形」照樣過）。
 * ③ **「＋」用返主要掣嗰隻色。** 本來底色係 `--raise`,喺毛玻璃上面幾乎睇唔到,
 *    即係最主要嗰個動作反而最唔顯眼。改用 `--on` / `--on-ink`（同 `.btn.primary`
 *    同一對 token）—— 唔係新發明一隻色,係沿用返設計系統入面「主要動作」嗰個。
 * ⚠️ 撳落去要有反應（縮 4–8%），但只准郁 `transform` —— 郁 width/padding 要重新排版。
 */
/*
 * 底部導航欄。老細 2026-09-18 逐次講到而家呢個樣：
 *   ①「導航欄想整再靚啲」→ 線粗唔再跟住狀態由 1.7 跳到 2.4（五個圖案得一個粗咗，成排望落搖擺）
 *   ②「中間個＋改返原本咁」→ 試過改用主要掣嗰對色，佢唔要，改返 `--raise`
 *   ③「啲 ICON 下面唔要一點」→ 拆咗
 *   ④「想要有個橢圓形左右滑動果隻」→ 企緊嗰格底下一粒橢圓，換格就滑過去
 *
 * ⚠️ 粒橢圓用 `transform` 滑，位置同闊度由 JS 度返（見 `paintTabPill()`）——
 *    唔可以用 `calc(100% / 5 * i)`:個欄有安全區內距，五格唔係啱啱好五等分。
 * ⚠️ 粒橢圓排喺啲掣前面（DOM 次序），啲掣 `position: relative` 就自然疊喺佢上面，
 *    唔使用負 z-index（負 z-index 喺有 backdrop-filter 嘅祖先度會俾人冚咗）。
 */
#tabs .tabpill { position: absolute; left: 0; top: 7px; height: 35px; border-radius: 18px;
  background: var(--raise); pointer-events: none;
  transition: transform var(--t-tap) var(--ez), width var(--t-tap) var(--ez); }
#tabs button { flex: 1; height: var(--tab); display: grid; place-items: center; color: var(--muted);
  position: relative; -webkit-tap-highlight-color: transparent; }
#tabs button .ic { width: 25px; height: 25px; stroke-width: 1.9;
  transition: transform var(--t-tap) var(--ez), color var(--t-tap) var(--ez); }
#tabs button.on { color: var(--ink); }
#tabs button:active .ic { transform: scale(.92); }
#tabs button.add .ic { width: 28px; height: 28px; padding: 3px; border-radius: 10px;
  background: var(--raise); color: var(--ink); box-sizing: content-box; stroke-width: 2.2; }
#tabs button.add:active .ic { transform: scale(.94); }
@media (prefers-reduced-motion: reduce) {
  #tabs button .ic, #tabs .tabpill { transition: none; }
}

/* ── Sheet(詳情 / 新增):由底彈上,頂圓角,食底安全區 ── */
/* 鍵盤高度，由 app.js `keyboardInset()` 寫入。冇鍵盤就係 0。 */
:root { --kb: 0px; }
/*
 * 動畫秒數同曲線 —— 一個地方定曬（用戶 2026-09-16：「好似所有功能都郁得太快，
 * THREAD 係慢啲，跟佢個速度」）。
 *
 * ⚠️ 本來 .22–.3 秒，係「快到你唔覺佢郁過」——  嘢就咁彈咗出嚟，望落似閃多過似郁。
 *    Threads／IG 呢類 app 用 .4 秒頭尾，配一條**急起慢收**嘅曲線
 *    （cubic-bezier(.32,.72,0,1)，iOS 自己張 sheet 就係呢條）：
 *    頭 100 毫秒已經行咗一大半，之後慢慢埋位 —— 所以覺得「跟到手」又「唔趕」。
 *    唔係淨係調長秒數:單純調長而唔換曲線，會變成由頭到尾都慢，嗰種先至叫拖。
 *
 * ⚠️ `--t-out` 要同 `app.js` 個 `SHEET_OUT` 同 `closeSortNav()` 個 setTimeout 一樣。
 *    改一邊唔改另一邊:CSS 長咗 —— 未跌完就俾 hidden 斬斷;JS 長咗 —— 跌完吊喺度等。
 */
/*
 * ⚠️ **成個 app 郁嘅嘢淨係得呢三個秒數**（用戶 2026-09-16：「所有開啟同移動速度要一致」）。
 *    一有第四個數，用戶就會覺得「有啲位快啲有啲位慢啲」，而講唔出邊度出事 ——
 *    佢淨係會話「用得好唔順」。
 *
 *      --t-in   入場、移動（張紙升上嚟、側欄滑出、頂底欄出返、轉版）
 *      --t-out  出場（張紙跌落去、側欄收埋、scrim 淡走）
 *      --t-tap  原地細微反應（箭嘴轉向、彈返位）—— 唔係「入場」，唔應該等咁耐
 *
 *    ⚠️ 加新動畫一律用呢三個，唔好自己寫死一個秒數。
 *    ⚠️ 2026-09-16 調過兩次:.28 → .42（「THREAD 係慢啲」）→ .5（「一按入去開個窗太快」）。
 *    ⚠️ `--t-in` 改咗，`app.js` 個 `SHEET_IN` 要一齊改（focus 要等張紙落定先彈鍵盤）。
 *    ⚠️ 出場**唔跟**入場 —— 郁走一件嘢唔使等，同入場一樣慢只會覺得拖泥帶水。
 */
:root { --t-in: .5s; --t-out: .34s; --t-tap: .2s;
  --ez: cubic-bezier(.32,.72,0,1); --ez-out: cubic-bezier(.4,0,1,1);
  /*
   * 第三條曲線 —— **淨係俾「手指放咗手、由動畫接落去」嗰一種**（左右掃頁）。
   *
   * ⚠️ 點解唔可以用 `--ez`:`--ez` 係**由靜止開始**嗰種（張紙彈上嚟、側欄滑出),
   *    佢喺 16% 嗰度衝到平均速度嘅 **4.22 倍**。由靜止開始睇落好爽,
   *    但接手指嗰下就死 —— 老細 2026-09-18 錄影,逐幀量到:
   *      手指最後幾幀 22 點／幀 → 一放手 45 點 → 67 點（3.0 倍）。
   *    眼睛讀到嘅就係「閃一下」。
   * ⚠️ 修法係**速度接得返**,唔係將秒數調長:調長只係令佢慢慢咁衝過頭。
   *    呢條曲線起步 1.90×平均、峰值 1.91 —— 即係**零中途加速**,一路慢落嚟。
   *    `app.js` 嘅 `swipeOutMs()` 就係攞住嗰個 1.90 去計秒數
   *    （秒數 ＝ 1.90 × 返剩幾多 ÷ 手指速度）,兩邊夾埋先至接得返。
   * ⚠️ 所以呢個數同 `SWIPE_EZ_V0` 係**同一個數**,改一邊就要改另一邊,
   *    `verify-motion.mjs` 會對。
   */
  --ez-swipe: cubic-bezier(.4,.76,.5,1); }
/*
 * 第四個秒數 —— **唯一嘅例外，而且唔係我哋揀嘅**。
 *
 * ⚠️ 上面講明「成個 app 郁嘅嘢淨係得三個秒數」。呢個係例外，因為佢唔係我哋嘅節奏,
 *    係**要同 iOS 個鍵盤夾**:鍵盤升起固定 0.25 秒、固定嗰條曲線。
 *    快過佢 → 張紙升咗上去、鍵盤未到,中間露一條罅;
 *    慢過佢 → 鍵盤到咗位、張紙仲追緊,一樣露罅。
 *    所以呢兩個值**唔准為咗「同其他動畫一致」而改** —— 佢哋要同 iOS 一致。
 * ⚠️ `keyboardWillShow` 係喺鍵盤開始郁**之前**射,所以我哋有成個 0.25 秒可以一齊行。
 */
:root { --t-kb: .25s; --ez-kb: cubic-bezier(.38,.7,.125,1); }
.sheet { position: fixed; inset: 0; z-index: 20; }
/*
 * 鍵盤後面鋪一塊實色底。
 *
 * ⚠️ iOS 個鍵盤本身係**半透明**嘅 —— 佢會透出後面嗰嚿嘢。呢個 app 入面
 *    鍵盤後面係 scrim ＋ 條時間線，於是啲相同文字會隱隱約約透上嚟，
 *    用戶原話「依啲有啲透底 唔知咩色黎」。
 * ⚠️ 系統鍵盤本身改唔到色 —— 但可以控制**佢後面係乜**。鋪一塊 `--bg`，
 *    鍵盤就同一塊實色溝，深色主題全黑、淺色主題淺底，自動跟住轉
 *    （用戶：「個 KEYBOARD 背景改為全黑，淺色背景就返為淺色背景色」）。
 * ⚠️ `--kb` 係 0 嗰陣高度就係 0，乜都唔會畫，所以唔使另外收埋。
 */
.sheet::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0;
  height: var(--kb); background: var(--bg); pointer-events: none; }
.sheet-bg { position: absolute; inset: 0; background: var(--scrim); }
/* ⚠️ 鍵盤彈起嗰陣，張紙要企喺鍵盤上面（`bottom: var(--kb)`），
      而且個 max-height 要一齊扣返鍵盤嗰忽，唔係會頂穿上面安全區。 */
.sheet-body { position: absolute; left: 0; right: 0; bottom: var(--kb); max-height: calc(100% - var(--sat) - 24px - var(--kb)); overflow-y: auto; -webkit-overflow-scrolling: touch;
  background: var(--bg); border-radius: 18px 18px 0 0; border-top: 1px solid var(--line); padding: 0 16px;
  animation: up var(--t-in) var(--ez); }
/*
 * ⚠️ 本來 `translateY(60px)` ＋ `opacity: 0` —— 對一張八百幾點高嘅紙嚟講，
 *    60 點等於「原地淡入」唔係「由底升上嚟」，加上淡入令佢望落似閃出嚟
 *    （用戶 2026-09-16：「按入去出見依個框時都閃，用得好唔順」）。
 *    量過:張紙一出現就已經企喺 84，只升 60 點就到位，而 scrim 要 300ms
 *    先淡到底 —— 兩樣唔同步，所以突兀。
 *
 * 改成由**完全喺畫面外**升上嚟，唔用 opacity（郁位置就夠，淡入反而似閃），
 * 同 scrim 同一個秒數、同一條曲線，兩樣一齊行。
 */
@keyframes up { from { transform: translateY(100%) } }

/* 收埋 —— 用戶 2026-09-15：「依頁要慢慢收埋」。
 *
 * ⚠️ 本來撳「完成」係直接 `hidden = true`，成版嘢即刻無咗,冇過渡。
 *    開嗰陣有 `up` 跌上嚟,收嗰陣咩都冇,一開一收唔對稱。
 *
 * 出嚟嗰條曲線特登同入嗰條唔同:入係 cubic-bezier(.2,.8,.2,1)（慢出快入,似俾人推上嚟）,
 * 出係 cubic-bezier(.4,0,1,1)（越跌越快,似放手跌落去）。兩邊同一條曲線會覺得黐住。
 * `forwards` 唔可以少 —— 冇佢張紙會喺 JS 執行 `hidden` 之前彈返原位,閃一閃。
 *
 * ⚠️ 秒數要同 `app.js` 個 SHEET_OUT 一樣。改一邊唔改另一邊：
 *    改長咗 CSS —— 張紙未跌完就俾 hidden 斬斷；改長咗 JS —— 跌完之後吊喺度等。 */
.sheet-bg { animation: scrim-in var(--t-in) var(--ez) }
/* 拖緊 —— 熄晒動畫同過渡，唔係手指郁一下就同 keyframes 打交 */
.sheet.dragging .sheet-body, .sheet.dragging .sheet-bg { animation: none; transition: none; }
/* ⚠️ 升完就熄咗入場動畫 —— 見 app.js `syncSettled()`。唔熄嘅話，
   之後任何一次「由 animation:none 變返有」都會令佢重播（例如拖一拖再放手）。 */
.sheet.settled .sheet-body, .sheet.settled .sheet-bg { animation: none; }
/* 拖唔夠遠，彈返上去 */
.sheet.snapback .sheet-body { transition: transform var(--t-out) var(--ez); }
.sheet.snapback .sheet-bg { transition: opacity var(--t-out) var(--ez); }
/* 條灰仔野係手柄，要食得晒嗰下手勢，唔好俾瀏覽器攞去做捲動 */
.grab { touch-action: none; }
/* ⚠️ 收埋嗰下量到最長一格 46ms（跌穿 30fps）—— 張紙成八百點高兼有相，
   逐幀要重新合成。`will-change` 叫瀏覽器預先起返個層，之後郁就純 GPU。
   ⚠️ 唔可以長期掛住 will-change（永遠佔住記憶體），所以只喺收埋／拖緊嗰陣加。 */
.sheet.closing .sheet-body, .sheet.dragging .sheet-body { will-change: transform; }
.sheet.closing .sheet-body { animation: down var(--t-out) var(--ez-out) forwards; }
.sheet.closing .sheet-bg { animation: scrim-out var(--t-out) var(--ez-out) forwards; }
/* ⚠️ 由手指放低嗰個位置開始跌，唔係由 0 —— 見 app.js `release()`。
   冇拖過（撳「完成」）嗰陣 `--drag-y` 係 0，行為同以前一樣。 */
@keyframes down { from { transform: translateY(var(--drag-y, 0px)) } to { transform: translateY(100%) } }
@keyframes scrim-in { from { opacity: 0 } }
/* ⚠️ 由手指放低嗰刻嘅透明度開始淡,唔係由 1 —— 同 `down` 用 `--drag-y` 同一個道理。
   冇咗呢句:你拖到一半個底已經淡咗,一放手佢**彈返全黑**再由頭淡出。
   老細 2026-09-18：「個背景灰黑色係第一秒尾段閃左一下」;
   真機逐幀量到 26.18 → 38.15（一格內亮返起點）再重新淡出。
   冇拖過（撳「取消」）嗰陣 `--drag-o` 冇設,預設 1,行為同以前一樣。 */
@keyframes scrim-out { from { opacity: var(--drag-o, 1) } to { opacity: 0 } }

/* 開咗「減少動態效果」就唔好郁,直接無咗 */
@media (prefers-reduced-motion: reduce) {
  .sheet-body, .sheet-bg, .sheet.closing .sheet-body, .sheet.closing .sheet-bg { animation: none; }
}

/* ⚠️ 頂嗰條同底嗰行都要黐住,唔准跟內容碌走(用戶 2026-09-15 兩句):
 *    「一路向下碌都要有上面打橫果條仔野」 —— 條仔野本來係 .sheet-body 入面一件
 *      普通仔,而 .sheet-body 先係捲動嗰個,所以一碌就走埋;
 *    「下面都顯示唔曬」 —— 動作行碌到底先見到,而且掕住安全區。
 *
 *    上下嗰嚿留白而家由呢兩條 bar 自己帶,唔再由 .sheet-body 個 padding 出 ——
 *    sticky 係黐 padding box,留喺 padding 嗰陣頂會露一條罅俾內容碌過。
 *    左右嘅 -16px 負邊距係要撐返滿版:唔係嘅話內容會由左右兩條 padding
 *    嘅罅隙度碌上嚟,望落似遮唔到。 */
.grab { position: sticky; top: 0; z-index: 3; width: auto; height: auto;
  margin: 0 -16px 12px; padding: 10px 0 9px; background: var(--bg); }
.grab::before { content: ''; display: block; width: 36px; height: 5px; border-radius: 3px; background: var(--line); margin: 0 auto; }
.kb-up .btns { padding-bottom: 12px; }
/*
 * 鍵盤郁嗰陣，張紙**跟住鍵盤一齊移動**（用戶 2026-09-17：
 * 「所有野都唔係閃過去，係移動過去，包括打開鍵盤」）。
 *
 * ⚠️ 三個 property 一定要**全部一齊**有過渡，而且同一個秒數同曲線。
 *    呢度本來寫 `transition: bottom .01s linear` —— 以為「幾乎冇過渡」＝「冇過渡」，
 *    但 .01s 喺 120Hz 仍然係足足一幀，而且**只有 `bottom` 有、`max-height` 冇**。
 *    2026-09-17 逐幀量到:有一幀係「高度已經縮到 440、位置未推上去」，
 *    成張紙向下跌咗 263 點，23ms 後先彈返（用戶：「0.1 秒唔知 LOAD 左去邊」）。
 *    **一個 property 有過渡、另一個冇，等於保證會畫出中間態。**
 * ⚠️ 秒數用 `--t-kb` 唔用 `--t-in` —— 要同 iOS 個鍵盤夾，見上面嗰段。
 * ⚠️ `app.js` 嗰邊個捲動補償都要用同一個秒數同曲線一齊行，
 *    否則張紙慢慢郁而內容一野跳，仲難睇過兩樣都跳。
 */
.sheet-body { transition: bottom var(--t-kb) var(--ez-kb),
                          max-height var(--t-kb) var(--ez-kb),
                          height var(--t-kb) var(--ez-kb); }
/* ⚠️ 拖緊／收緊張紙嗰陣唔好要呢個過渡 —— 佢會同 transform 嗰個動畫打交 */
.sheet.dragging .sheet-body, .sheet.closing .sheet-body { transition: none; }
/*
 * 「新增」嗰張要企到同詳情頁一樣咁高（用戶 2026-09-16：
 * 「果頁 APP 直接上到同按啲 PAGE 一樣咁高」）。
 *
 * ⚠️ 詳情頁係內容有幾高就幾高（`max-height`），而新增得三四行嘢，
 *    於是同一個手勢彈出嚟兩個高度 —— 你撳「＋」同撳張卡，張紙唔同高，
 *    望落似兩種唔同嘅嘢。而家夾硬撐到同一個高度。
 * ⚠️ 撐高咗就要處理「掣去咗邊」:`.btns` 係 `sticky bottom:0`，
 *    但容器高過內容嗰陣 sticky 唔會將佢推落底，佢會就咁黐喺輸入格下面，
 *    下面吊住一大橛空白。所以改成 flex 直排、輸入格 `flex:1` 食晒剩低嘅位，
 *    成行掣自然就企喺最底。
 */
#add .sheet-body { height: calc(100% - var(--sat) - 24px - var(--kb)); display: flex; flex-direction: column; }
/*
 * ⚠️ 輸入格**唔好撐高**（用戶 2026-09-16：「唔洗咁大，一行夠，只係貼 URL」）。
 *    我第一版用 `flex: 1` 叫佢食晒剩低嘅位 —— 純粹為咗將成行掣頂落底，
 *    但副作用係一個貼 URL 嘅格變成成版咁高嘅空白，望落似叫你寫文。
 *    改成一行起、跟字長自己生高（app.js `growAdd()`），最多去到四成屏;
 *    剩低嘅位交俾 `margin-top: auto` 推成行掣落底。
 */
.addrow { display: flex; align-items: flex-start; gap: 8px; }
.addrow .inp { flex: 1; min-width: 0; min-height: 46px; max-height: 40vh; overflow-y: auto; }
/* 粒貼上同個框頂對齊 —— 個框生高嗰陣佢唔跟住郁 */
.addrow .btn { flex: none; height: 46px; }
#add .sheet-body > .addrow { flex: none; }
#add .sheet-body > .btns { margin-top: auto; }
.sheet h2 { margin: 6px 0 4px; font-size: 20px; font-weight: 800; }
.hint { color: var(--muted); font-size: 14px; margin: 0 0 12px; line-height: 1.5; }
/* 譯文 —— 靠左一條線，睇得出係「附加喺原文之下」唔係取代咗原文 */
.trans { margin: 10px 0 2px; padding: 8px 0 8px 12px; border-left: 2px solid var(--line);
  font-size: 15px; line-height: 1.6; white-space: pre-wrap; word-break: break-word; }
.trans small { display: block; color: var(--muted); font-size: 12px; margin-bottom: 3px; }
/* 翻譯講嘅嗰句話（已經係你嘅語言／要落語言包…）—— 係資訊唔係警告，唔要黃、唔要 icon */
.trans-note { color: var(--muted); font-size: 13px; line-height: 1.5; margin: 8px 0 2px; }
.d-post { display: grid; grid-template-columns: 40px 1fr; gap: 12px; }
.d-txt { font-size: calc(var(--fs) + 1px); line-height: 1.5; white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere; margin: 6px 0; }
.d-txt.title { font-weight: 700; }
.d-shared { font-size: 15px; color: var(--muted); white-space: pre-wrap; word-break: break-word; border-left: 2px solid var(--line); padding-left: 10px; margin: 8px 0; }
/*
 * ⚠️ 條網址上下都要留白（老細 2026-09-19：「網址上框，網址及 TRANSLATE 都太近，格隔一行」）。
 *    詳情頁呢三嚿係連住嚟嘅:連結卡 → 條網址 → Translate 掣。
 *    佢哋本來一條貼一條,望落似一嚿,分唔清邊個係邊個。
 * ⚠️ 用 `margin` 唔用 `<br>` —— 加空行係內容,留白係版面,唔可以撈亂。
 */
.d-url { font-size: 13px; color: var(--accent); word-break: break-all; margin: 14px 0; }
/* Translate 嗰粒同上面條網址再隔多一行 */
#sheet-content .trans-slot { margin-top: 14px; }
.d-time { color: var(--muted); font-size: 14px; margin: 8px 0 12px; padding-bottom: 12px; border-bottom: 1px solid var(--line); }
.f { display: block; font-size: 13px; color: var(--muted); margin: 14px 0 6px; font-weight: 600; }
/*
 * 輸入格 —— **淨係填色，冇框**（用戶 2026-09-17：「輸入文字果啲一個框框都唔夠 PRO」）。
 *
 * ⚠️ 本來「灰底 ＋ 一條實線框」兩樣一齊落 —— 填色已經講咗「呢度可以打字」,
 *    再加條框就係講多次,而且條框會將個格同周圍啲字割開,望落好重。
 *    iOS 原生（訊息、搜尋、備忘錄）全部係淨填色冇框。
 * ⚠️ 聚焦用 `box-shadow` 唔用 `border` —— border 會改變盒嘅大細,
 *    撳落去成個版面會跳一跳;`box-shadow` 唔佔位。
 * ⚠️ 全部 `.inp` 要一齊改,唔可以淨係改幾個 —— ui-audit 會報「輸入格有兩個外形」。
 */
.inp, textarea.inp { width: 100%; background: var(--raise); border: 0; border-radius: 14px;
  padding: 13px 14px; outline: none; resize: none; font-size: 15px; line-height: 1.45;
  transition: background var(--t-tap) linear, box-shadow var(--t-tap) linear; }
.inp::placeholder { color: var(--muted); opacity: .75; }
/* ⚠️ 聚焦**唔要藍框**（用戶 2026-09-17：「輸入框唔需要顯示藍色框邊」）——
   個游標同鍵盤已經講咗你喺邊度打緊字，再畫個藍框係講多次。
   改成淨係底色深少少，夠你知邊個格著緊,但唔會搶眼。 */
.inp:focus { background: var(--bg-2); }
.pills { display: flex; flex-wrap: wrap; gap: 8px; }
/*
 * ⚠️ 輸入格同緊接住嗰行藥丸要分得開（用戶 2026-09-16：「太近 分返開啲」）。
 *    兩樣嘢黐晒埋一齊，個格同啲藥丸望落似同一件嘢 —— 但一個係打字、
 *    一個係撳，唔係同一個動作。10 點嘅罅就夠講到佢哋係兩件事。
 */
.inp + .pills { margin-top: 10px; }
.pill { height: 34px; padding: 0 14px; border-radius: 17px; border: 1px solid var(--line); font-size: 14px; font-weight: 600; display: inline-flex; align-items: center; gap: 6px; }
.pill .ic { width: 15px; height: 15px; }
.pill.on { background: var(--on); color: var(--on-ink); border-color: var(--on); }
/* ⚠️ 鍵盤起咗就唔使留安全區嗰忽 —— 嗰度已經係鍵盤，留返就多咗一條空白。 */
/*
 * ⚠️ 2026-09-16 我一度以為呢條 sticky bar 冚住咗下面啲主題藥丸（條真機片見到
 *    最後一行藥丸「斬一半」），加咗 70px padding 落 `.more-in` 度。**診斷錯咗。**
 *    量實：`.more-in` 底 779、`.btns` 頂 779 —— 一點都冇重疊。
 *    斬一半嗰下係 `.more-in` **自己個捲動邊界**切嘅（內高 707、可見 338）。
 *    我支臨時檢查尺又一次冇計入 `.more-in` 嘅裁切，所以報咗「8 粒俾人冚住」。
 *    呢個改動已經拆返。⚠️ 要改嘅話係「捲動邊界斬字」呢個觀感問題（加漸隱遮罩之類），
 *    唔係留位問題 —— 兩者修法完全唔同，唔好再撈亂。
 */
/*
 * ⚠️ 條 bar 上面要有一截**漸隱**（用戶 2026-09-17：「我覺得依個位置唔好睇,
 *    有無得整 PRO 啲齊？」）。佢係 sticky,浮喺捲動緊嘅內容上面 ——
 *    冇漸隱嘅話下面嗰行藥丸會喺條 bar 嘅上邊界俾**硬切一半**,
 *    半粒藥丸吊喺度,望落似壞咗多過似「仲有嘢喺下面」。
 * ⚠️ 要 `bottom: 100%` 貼喺條 bar 上面（唔係入面）,而且 `pointer-events: none`,
 *    否則嗰 24 點會食咗你想撳嗰行藥丸。
 */
.btns::before { content: ''; position: absolute; left: 0; right: 0; bottom: 100%;
  /* ⚠️ 漸隱要夠淡 —— 太實嘅話佢自己就變成「多咗一截遮住嘢嘅嘢」。
     18 點、而且由條 bar 嘅底色淡到全透明。 */
  height: 18px; pointer-events: none;
  background: linear-gradient(to top, var(--bg), rgba(0,0,0,0)); }
.btns { display: flex; gap: 10px; justify-content: flex-end; align-items: center;
  position: sticky; bottom: 0; z-index: 3;
  /* ⚠️ 底部只留安全區 ＋ 6 點 —— 本來 +12 再加上面 18 點外邊距，
     成條 bar 就浮高咗一截，上面嗰行標籤／藥丸就俾佢壓住
     （用戶 2026-09-17：「要再低啲，有啲遮住左標籤」）。 */
  margin: 14px -16px 0; padding: 10px 16px calc(var(--sab) + 6px);
  background: var(--bg); border-top: 1px solid var(--line); }
.btn { height: 40px; padding: 0 18px; border-radius: 20px; font-weight: 700; font-size: 15px; display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line); }
/* 淨圖掣 —— 見 app.js 嗰段解釋點解「更新／原文」唔出字 */
.btn.ico { width: 44px; padding: 0; justify-content: center; }
/* 帶住個數字嗰粒（回收筒）—— 要闊返啲先放得落個數 */
.btn.ico:has(.npick) { width: auto; padding: 0 12px 0 10px; gap: 6px; }
.btn.primary { background: var(--on); color: var(--on-ink); border-color: var(--on); }
/* ⚠️ 唔好加 padding-left —— 刪除掣一樣係動作掣，外形要同其餘幾粒一模一樣。
   佢靠 margin-right:auto 推去左邊已經夠分開，改 padding 只會令佢睇落窄一橛。
   （2026-09-15 ui:audit 量到「btn 動作掣有 2 個外形」，根因就係呢度。） */
.btn.danger { color: var(--danger); border-color: transparent; margin-right: auto; }
/* 「貼上」「加檔案」自己一行 —— 見 index.html 嗰段解釋 */
.addtools { display: flex; gap: 8px; padding-top: 10px; }
/*
 * ⚠️ 掣**唔准縮**。本來冇呢句,排唔落嗰陣 flex 會將每粒壓細,
 *    文字就靜靜哋逼埋一舊（德文粒「貼上」由 44 點壓到 20）——
 *    而且 `scrollWidth` 唔會超,所以量幾何嗰支尺一路報綠。
 *    寧願真係爆出去俾支尺捉到,好過睇落「差少少」但每種語言都差少少。
 */
.btns .btn, .addtools .btn { flex: none; }
/* 揀好未存嘅檔 —— 喺輸入格同成行掣之間，一眼數到揀咗幾多個 */
/* 揀咗嘅檔自己排一段，粒「加檔案」永遠喺佢哋下面 —— 見 app.js renderAddFiles() */
.filechips { display: block; padding: 8px 0 0; }
.filerow { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
/* ⚠️ 同藥丸一樣高（34），但係方角 —— 高度一致先睇得出係同一行嘢，
   而方角同圓角嘅分別就係「一個檔」同「揀一樣嘢」嘅分別。 */
.filechip { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; height: 34px; padding: 0 11px;
  border-radius: 8px; border: 1px solid var(--line); font-size: 13px; font-weight: 600; }
.filechip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.filechip .ic { color: var(--muted); flex: none; }
.filechip small { color: var(--muted); font-weight: 500; flex: none; }
/* 卡／詳情頁入面嗰行檔案 */
.files { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0 2px; }
.files .filechip { background: var(--raise); border-color: transparent; }
.files .filechip:active { background: var(--line); }
/* 詳情頁嗰啲可以剷 —— 個 × 要自己夠 44 點高撳得中，唔好淨係一粒細叉 */
#d-files .filechip { padding-right: 2px; }
#d-files .filechip .x { display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; margin-left: 2px; border-radius: 8px; color: var(--muted); }
#d-files .filechip .x:active { background: var(--line); }
.warn-line { color: var(--warn); font-size: 13px; display: flex; gap: 6px; align-items: flex-start; margin-top: 6px; }
.warn-line .ic { width: 16px; height: 16px; margin-top: 1px; }
/* KP02「原帖已刪」——紅色,同「抽唔到快照」嗰句(黃色)分得出係兩件事,一個係
   「未必咁快連上」,一個係「平台確認講咗冇咗」,唔應該望落一樣嚴重 */
.warn-line.gone-line { color: var(--danger); }
/* 跟喺 .warn-line.gone-line 後面嗰粒「原帖仍然存在」—— 同上面隔開少少,唔好貼實個警告句 */
#d-ungone { margin-top: 8px; }

/* 搜尋頁 */
/*
 * 搜尋欄 —— **獨立一個 fixed 元素 `#sbar`**，唔喺頁面內容度、亦唔喺 `#hdr` 入面。
 *
 * ⚠️ 本來擺喺內容度,試過改做 `position: sticky` —— 用戶影咗張圖:向上推嗰下
 *    搜尋欄連頂欄底欄一齊冇咗。原因係 iOS 嘅 rubber band 將成塊內容拉走,
 *    而 **sticky 頂唔住橡筋**（sticky 只係相對捲動,唔係相對橡筋）。
 *    擺入頂欄之後同頂欄同一個命運,而頂欄本來就唔會俾橡筋拉走。
 */
/* 搜尋欄 —— 獨立 fixed,唔喺 #hdr 入面(見 app.js renderChrome 嗰段) */
#sbar { position: fixed; left: 0; right: 0; top: calc(var(--sat) + var(--hdr)); z-index: 9;
  padding: 0 calc(var(--sar) + 16px) 8px calc(var(--sal) + 16px);
  background: var(--blur); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px); }
.sbox { height: 40px; border-radius: 20px; background: var(--raise); display: flex; align-items: center; gap: 8px; padding: 0 14px; color: var(--muted); }
.sbox input { flex: 1; background: none; border: 0; outline: none; color: var(--ink); font-size: 15px; -webkit-appearance: none; }
.sbox input::placeholder { color: var(--muted); }

/*
 * ⚠️ 彈出嚟嘅嘢一律要**慢慢出、慢慢走**（用戶 2026-09-16：
 *    「所有彈出黎既野都要慢慢出，而唔係一野彈出彈走」）。
 *    Toast 本來係 `hidden = false` / `hidden = true` —— 即係無中生有咁出現、
 *    夠鐘就人間蒸發。喺一個成隻 app 都郁得好順嘅畫面度，佢就係最突兀嗰件嘢。
 * ⚠️ 秒數用返成個 app 嗰三個（`--t-in` / `--t-out`），唔好自己寫死 ——
 *    「所有開啟同移動速度要一致」。
 * ⚠️ `[hidden]` 唔可以靠 `display:none` 做開關（display 冇得過渡），
 *    所以改成用 opacity ＋ transform，`display` 交返俾 `.out` 收尾。
 */
.toast { position: fixed; left: 50%; bottom: calc(var(--tab) + var(--sab) + 14px); transform: translateX(-50%); z-index: 30;
  background: var(--accent); color: #fff; padding: 10px 16px; border-radius: 6px; font-size: 14px; font-weight: 600; box-shadow: 0 6px 20px rgba(0,0,0,.4); }
.toast { opacity: 1; transition: opacity var(--t-in) var(--ez), transform var(--t-in) var(--ez); }
.toast[hidden] { display: block; opacity: 0; transform: translate(-50%, 14px) scale(.96); pointer-events: none; }
.toast.gone { opacity: 0; transform: translate(-50%, 14px) scale(.96);
  transition: opacity var(--t-out) var(--ez-out), transform var(--t-out) var(--ez-out); }

/*
 * KP96 —— 自訂確認框(見 app.js `showConfirm()`)。用喺撳「關閉」iCloud 備份嗰下,
 * 淨係呢一個位用,唔係通用 alert。z-index 開過 `.sheet`(20)／`.nav`(25),因為要遮住
 * 設定頁本身(設定唔係 sheet,係普通分頁)。
 * ⚠️ 兩粒掣要**同一個 class、同一個大細**（老細：「唔准做 dark pattern⋯兩粒掣要一樣易撳」）——
 *    唔好幫「關閉」加 `.danger` 或者細一級,亦唔好幫「保持開啟」加 `.primary` 搶眼。
 */
.confirm-wrap { position: fixed; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center; padding: 24px; padding-bottom: calc(24px + var(--sab)); }
.confirm-bg { position: absolute; inset: 0; background: var(--scrim); }
.confirm-card { position: relative; width: 100%; max-width: 320px; background: var(--card); border: 1px solid var(--line); border-radius: 16px; padding: 20px; }
.confirm-card h2 { margin: 0 0 10px; font-size: 17px; font-weight: 700; color: var(--ink); }
.confirm-card p { margin: 0 0 10px; font-size: 14px; line-height: 1.5; color: var(--muted); }
.confirm-card p:last-child { margin-bottom: 18px; }
/* 分享教學（#intro）—— 三步,每步一幅 SVG ＋ 一句字 */
.intro-card { max-height: 82vh; overflow-y: auto; }
.intro-step { display: grid; grid-template-columns: 84px 1fr; gap: 14px; align-items: center; margin: 16px 0; }
.intro-step .art { width: 84px; height: 84px; border-radius: 14px; background: var(--raise);
  display: grid; place-items: center; color: var(--ink); }
.intro-step .art svg { width: 56px; height: 56px; }
/* ⚠️ 步驟號用 --accent,同成隻 app 嗰隻強調色,唔開新色 */
.intro-step .n { color: var(--accent); font-weight: 800; font-size: 13px; letter-spacing: .08em; }
.intro-step b { display: block; font-size: 15px; font-weight: 600; line-height: 1.45; margin-top: 2px; }
.confirm-btns { display: flex; flex-direction: column; gap: 8px; }
.confirm-btns .btn { width: 100%; justify-content: center; min-height: 46px; }

/* 付費版面（#pay）—— 免費額滿咗先出。
   ⚠️ 三粒掣同一個高度、同一個闊度:「暫時不用」唔可以畫到細過「解鎖」。
   ⚠️ 「解鎖」係全版唯一一粒實色掣 —— 一版一處強調,唔好連「回復購買」都搶。 */
.pay-card p.pay-line { margin: 0 0 8px; font-size: 14px; line-height: 1.5; color: var(--ink); }
.pay-card p.pay-line.dim { color: var(--muted); }
.pay-card p.pay-line:last-of-type { margin-bottom: 18px; }
.pay-btns #pay-buy { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 700; }
.pay-btns #pay-buy[disabled] { opacity: .55; }

/* 揀語言個 select —— 七隻語言用 pill 會迫爆一行,所以行原生 select（iOS 自己出轉輪,用家慣手）。
   外觀跟返 .pill,唔好留 Safari 預設嗰個灰底圓角。 */
.sel{
  appearance:none;-webkit-appearance:none;
  font:inherit;font-size:14px;line-height:20px;
  color:var(--ink);background:var(--raise);
  border:1px solid var(--line);border-radius:999px;
  padding:6px 30px 6px 12px;max-width:150px;
  background-image:linear-gradient(45deg,transparent 50%,var(--muted) 50%),linear-gradient(135deg,var(--muted) 50%,transparent 50%);
  background-position:calc(100% - 15px) 52%,calc(100% - 10px) 52%;
  background-size:5px 5px,5px 5px;background-repeat:no-repeat;
}
.sel:focus{outline:2px solid var(--muted);outline-offset:1px}

/* 詳情頁「主題」標題旁邊嗰個細字 —— 話俾用戶知而家仲係自動分類，撳一下就變人手。 */
.f .auto{font-weight:400;font-size:12px;color:var(--muted);text-transform:none;letter-spacing:0}


/*
 * ── 觸控目標：撐大撳得中嘅範圍，但一個字都唔郁外形 ────────────────
 *
 * 2026-09-15 `npm run ui:audit` 量出嚟：490 項「細過 44 點」，但**得四個根因** ——
 * `.act` 34×34（每張卡三粒，所以一個問題出現 446 次）、`.chip` 高 34、
 * `.pill` 高 32–34、`.btn` 高 40。
 *
 * ⚠️ **唔可以直接改高做 44。** 呢隻 app 個樣係 X × Threads 嘅合體：細藥丸、細動作 icon
 *    本身就係個設計。撐到 44 會即刻變成另一隻 app，而且一行放唔落幾粒 chip。
 *
 * 做法：透明 `::after` 由中心撐出去，補夠 44×44。個盒量落仲係 34，但手指撳得中。
 * 柏生 2026-09-14 用同一招（Uma 嗰次），QA 一開始當咗係未修，所以呢度寫明：
 * **量 `getBoundingClientRect()` 係量唔到呢個區嘅**，`tools/ui-audit.mjs` 特登會查
 * 有冇 absolute 定位嘅 `::after` 先算數。
 */
/* ⚠️ 2026-09-18 加咗 `.filechip` —— 新示範內容有語音同 PDF 附件之後，
   嗰粒檔案 chip 先至第一次真係出現喺時間線度，ui-audit 即刻捉到 152×34。
   佢同藥丸一樣係 34 高（明文要一致，見上面），所以行同一招。 */
.act::after, .chip::after, .pill::after, .btn::after, .filechip::after {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: max(100%, 44px); height: max(100%, 44px);
  transform: translate(-50%, -50%);
}
.act, .chip, .pill, .btn, .filechip { position: relative; }

/* 藥丸統一做一個尺寸 —— audit 量到設定頁 13px/32 高、詳情頁 14px/34 高，
   同一種角色兩個外形就係「一睇就知係求其砌」嗰種。跟大嗰個。 */
.rowi .rr .pill { height: 34px; font-size: 14px; padding: 0 14px; }



/*
 * ⚠️ 試過 `.post { content-visibility: auto }` —— **唔可以用**。
 *    帳面上啱:轉返時間線由 51ms 跌到 32ms。但落到真機，
 *    用戶即刻話「點解我個手機黑左無畫面」——
 *    查落 DOM 完全正常（feed 盒 34754 點高、第一張卡 400×393、頂底欄齊全），
 *    即係**排版啱但畫唔出**:WKWebView 會將啲卡當「螢幕外」而跳過繪畫，
 *    留返個啱尺寸嘅空盒 —— 成版嘢就係一片黑。
 *    19ms 換一版黑畫面，唔換。
 * ⚠️ 同一段時間亦試過用 `content-visibility: hidden` 收埋成版（唔用 display:none），
 *    量落一模一樣 50ms，冇用。問題喺卡嘅數量，唔喺收埋嘅方式 ——
 *    真要再快就要自己寫虛擬列表，唔係靠一句 CSS。
 */

/* ⚠️ 轉版**冇**過場動畫，係刻意嘅 —— 見 app.js render() 尾嗰段註解。
   試過淡入，喺黑底上面變成「閃一下暗嘅」，用戶當咗係 load 錯版。 */

/*
 * 時間線頂嗰行「想記錄啲乜？」—— 同 Threads 嗰行一樣，撳落去就開「＋」。
 * ⚠️ 排法要同下面啲卡對齊（同一個 36px 頭像欄 ＋ 10px 罅），
 *    唔對齊嘅話佢望落似「浮喺上面嘅另一嚿嘢」而唔似清單第一行。
 */
.compose { display: grid; grid-template-columns: 36px 1fr; gap: 10px; align-items: center;
  width: 100%; text-align: left; font: inherit; padding: 14px 12px 14px 10px;
  border-bottom: 1px solid var(--line); color: var(--muted); font-size: 16px; }
.compose:active { background: var(--bg-2); }

/*
 * 示範內容提示卡 —— 時間線最頂,未有第一件自己嘅嘢之前一直喺度。
 * 老細 2026-09-19：「固定長期放住係示範頁最頂 what do you want to keep 個位置，
 * 其他顏色背景，按右邊箭嘴可打開教學」。
 *
 * ⚠️ **釘住**（sticky）—— 呢張係全 app 唯一一張釘喺頂嘅卡。碌落去都要見到,
 *    因為佢講緊嘅嘢（「加第一條就會 REPLACE 咗」）係碌到邊都啱嘅。
 *    ⚠️ 同 `.compose` 相反:嗰行老細講明「唔需要固定係頂」,唔好順手一齊釘。
 * ⚠️ 頂欄收埋嗰陣要跟住升上去貼返狀態列 —— 同 `.tabseg` 同一條規矩,
 *    唔跟就會吊喺半空,下面仲會露一忽內容喺佢上面。
 * ⚠️ 要有**實色**底(--note-bg),唔可以透明 —— 釘住嗰陣啲帖會由佢底下經過。
 * ⚠️ 成張係一粒掣(唔淨係嗰幅圖同箭嘴)—— 44pt 觸控目標。
 */
.demo-note { display: grid; grid-template-columns: 48px 1fr 16px; gap: 12px; align-items: center;
  position: sticky; top: calc(var(--sat) + var(--hdr)); z-index: 8;
  width: 100%; padding: 12px; text-align: left; font: inherit;
  background: var(--note-bg); border-bottom: 1px solid var(--note-line); color: var(--ink);
  transition: transform var(--t-in) var(--ez); }
/* ⚠️ **唔可以用 `--hdr-real`。** 嗰個變數淨係喺「我的紀錄」嗰版度過（app.js
   `renderChrome()` 入面 `if (tab === 'note')`）—— 喺時間線度佢係上一版剩低嘅舊數,
   張卡就會黐錯位。呢度嘅頂欄實係 `--sat + --hdr`,直接計,唔使度。 */
body.chrome-hidden .demo-note { transform: translateY(calc(-1 * var(--hdr))); }
/*
 * 張卡向上撐一浸出嚟,補住佢同畫面頂之間嗰條帶。
 *
 * ⚠️ **高度要 `--sat + --hdr`,而且永遠喺度。** 逐格計過先知唔可以慳:
 *    頂欄收埋係 `translateY(-100%)`,即係要行 `--sat + --hdr`(59+44＝103);
 *    張卡由 `sat+hdr` 行到 `sat`,淨係行 `--hdr`(44)。同一個 500ms 行唔同距離,
 *    **過場中途兩者之間必然裂開一條罅**,下層啲帖就由嗰度經過
 *    （老細 2026-09-19：「上面位置滑動時依然會分開左 ICON 行到 This is demo content 行，
 *      佢地之間唔要睇到下一層 LAYER」）。
 *    設 t 為過場進度:頂欄底邊 = 103t,張卡頂 = 59+44t。59+44t > 103t 對所有 t<1 都成立
 *    —— 即係**收埋同彈返出嚟兩個方向都會裂**。撐 103 就頂到 y ≤ 0,幾時都唔會裂。
 * ⚠️ 本來只喺 `body.chrome-hidden` 先撐 —— 嗰個淨係補到「收埋之後」嗰個靜止狀態,
 *    補唔到過場嗰 500ms。老細就係喺滑動途中見到嗰條罅。
 * ⚠️ 頂欄喺度嗰陣呢浸藍會喺佢底下(z-index 8 vs 10),由半透明頂欄透出極淡一層。
 *    量過:深色 #11212E 經 rgba(0,0,0,.72) 出嚟同純黑爭唔到一級,肉眼睇唔出。
 */
.demo-note::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 100%;
  height: calc(var(--sat) + var(--hdr)); background: var(--note-bg); }
.demo-note:active { opacity: .7; }
.demo-note .demo-art { width: 48px; height: 48px; border-radius: 12px; background: var(--card);
  display: grid; place-items: center; color: var(--ink); }
.demo-note .demo-art svg { width: 32px; height: 32px; }
.demo-note .demo-txt { display: block; }
.demo-note .demo-txt b { display: block; font-size: 14px; font-weight: 700; line-height: 1.4; }
.demo-note .demo-txt span { display: block; font-size: 13px; line-height: 1.45; color: var(--muted); margin-top: 2px; }
/* ⚠️ 右邊個箭嘴就係「撳得入教學」嗰個訊號（老細:「按右邊箭嘴可打開教學」）—— 唔准收埋 */
.demo-note .demo-go { display: grid; place-items: center; color: var(--accent); }
.demo-note .demo-go .ic { width: 16px; height: 16px; }
/*
 * ⚠️ 「有哪些新消息想記錄？」**唔釘喺頂**。
 *    2026-09-18 試過釘住（老細本來講「要長期顯示係到」），佢試完話
 *    「有哪些消息想紀錄 唔需要固定係頂」—— 所以佢係普通嘅清單第一行，跟住內容碌。
 *    唔好再「順手」釘返佢。
 */
.compose .av { width: 36px; height: 36px; border-radius: 50%; background: var(--raise);
  display: grid; place-items: center; color: var(--muted); }
.compose .av .ic { width: 16px; height: 16px; }

/*
 * 備忘錄頁嘅兩邊（貼文 ／ 留言）—— 撳得，亦都掃得。
 *
 * ⚠️ 個 class 叫 `.tabseg` 唔叫 `.seg` —— **`.seg` 已經有人用**
 *    （設定頁嗰對「深色／淺色」藥丸，`.rowi .seg`）。我第一版寫咗 `.seg`，
 *    連佢哋都改埋,ui-audit 即刻報「藥丸有 3 個外形」。
 *    加新 class 之前要 grep 一次個名 —— 撞名唔會有任何錯誤訊息,
 *    淨係第二版嘢靜靜哋變咗樣。
 * ⚠️ 兩粒等闊（`1fr 1fr`）:唔等闊嘅話字長嗰邊會霸多啲位，
 *    望落似「嗰邊緊要啲」，但兩邊係平起平坐。
 * ⚠️ 掣要夠 44 點高 —— 36 點過唔到觸控體檢，而且真係唔好撳。
 */
.tabseg { position: relative; display: grid; grid-template-columns: 1fr 1fr;
  border-bottom: 1px solid var(--line); }
/*
 * 備忘錄頁嗰條要黐住頂欄下面,唔可以跟住內容碌走 ——
 * 老細 2026-09-17 錄影:碌低咗就見唔到條切換條,要碌返上先切得到另一邊。
 *
 * ⚠️ 只 scope 落備忘錄版 —— 新增頁(`#add-seg`)同一個 class,佢喺 sheet 入面唔可以黐。
 * ⚠️ `top` 用 `--hdr-real`(renderChrome 度返嘅真高度),唔用 `sat + 44`:
 *    頂欄下面嗰行副標題摺兩三行嗰陣會高過 44,寫死就會疊咗上頂欄。
 * ⚠️ 頂欄收埋嗰陣佢要跟住升上去貼返狀態列 —— 唔係就會吊喺半空,
 *    下面仲會露一忽內容喺佢上面。
 * ⚠️ 要有底色 —— 黐住嗰陣下面啲字會由佢底下經過。
 */
#main > [data-page="note"] .tabseg {
  position: sticky; top: var(--hdr-real, calc(var(--sat) + var(--hdr))); z-index: 8;
  background: var(--blur); -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  transition: transform var(--t-in) var(--ez); }
body.chrome-hidden #main > [data-page="note"] .tabseg {
  transform: translateY(calc(var(--sat) - var(--hdr-real, calc(var(--sat) + var(--hdr))))); }
.tabseg button { padding: 0; font-size: 15px; font-weight: 600; color: var(--muted); min-height: 46px; }
.tabseg button.on { color: var(--ink); }
/* 條底線 —— 佔半版闊，滑過去。入面嗰條先係睇得見嗰截，所以線係短嘅但滑得順 */
.tabseg .bar { position: absolute; bottom: -1px; left: 0; width: 50%; height: 2px;
  transition: transform var(--t-tap) var(--ez); pointer-events: none; }
/* ⚠️ 長度用百分比唔用寫死點數 —— 兩邊字長唔同（「新增 URL」vs「貼文」），
   寫死嘅話短嗰邊會見到條線比個字長一大截。 */
.tabseg .bar::before { content: ''; display: block; margin: 0 auto;
  width: 62%; height: 2.5px; border-radius: 2px; background: var(--ink); }
/* ⚠️ 位置跟 `data-i`（第幾格）唔跟 key —— 備忘錄頁係 post/note、新增頁係 url/post，
   靠 key 嘅話總有一個切換條郁唔到。 */
.tabseg[data-i="1"] .bar { transform: translateX(100%); }
@media (prefers-reduced-motion: reduce) { .tabseg .bar { transition: none; } }

/* ⚠️ `.addrow` 有 `display: flex`，權重高過瀏覽器預設嗰句 `[hidden]{display:none}` ——
   唔補呢句，收起條 URL 格根本冇反應（而且唔會有任何錯誤訊息）。 */
.addrow[hidden], #add-hint[hidden] { display: none; }
/* 新增頁嗰條切換條同備忘錄頁共用 `.tabseg`，但佢企喺標題下面，要留返上下罅 */
#add-seg { margin: 4px 0 12px; }

/* 撳得嘅嘢要望落撳得 —— 條 URL 同張相都開返原文（見 app.js #sheet-content 個 handler） */
.d-url, #sheet-content .media { cursor: pointer; }
#sheet-content .media:active { opacity: .85; }
.d-url:active { opacity: .6; }

/* 留言個標題右邊嗰粒刪除 —— 同檔案 chip 嗰粒一樣細，唔好搶戲 */
.f.labrow { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
/* ⚠️ 44 點係地板（ui-audit 會報）—— 個圖案細，但撳得中嘅範圍唔可以細 */
.f.labrow .x { width: 44px; height: 44px; margin: -8px -10px -8px 0; display: grid; place-items: center;
  color: var(--muted); border-radius: 50%; }
.f.labrow .x:active { background: var(--raise); }

/*
 * 設定頁嘅分組標題。
 * ⚠️ 細、灰、唔搶眼 —— 佢係路標唔係內容。做得太大就變咗五個新嘅「重點」，
 *    反而更加亂（用戶原話係「有啲混亂」，加大隻字解決唔到）。
 * ⚠️ 第一個唔要上邊距,否則成版頂會吉一大截。
 */
.rows .sec { margin: 22px 16px 6px; font-size: 13px; font-weight: 600;
  color: var(--muted); letter-spacing: .02em; }
.rows .sec:first-child { margin-top: 10px; }

/*
 * 掣列上面要留返一截（用戶 2026-09-17：「最底儲存位置要底返啲，太貼合集」）。
 *
 * 量到:新增（貼文）**0px**、詳情頁 14px —— 合集最後一粒藥丸直頭貼住條掣列。
 *
 * ⚠️ 唔可以用 `.btns { margin-top }` —— 試過,冇用,兩層蓋住:
 *    ① 後面 `.btns { margin: 14px -16px 0 }` 個簡寫重設咗佢
 *    ② `#add .sheet-body > .btns { margin-top: auto }`（張紙短過畫面嗰陣要推佢落底）
 *    所以要改為喺**上面嗰嚿**加下內距。
 * ⚠️ 亦唔可以加喺 `.sheet-body` —— 掣列本身就喺入面,加咗連條 bar 底下都多一截。
 * ⚠️ 亦唔可以靠 `.btns::before` 嗰 18 點漸隱當留白 —— 嗰層 `bottom: 100%`、
 *    `pointer-events: none`,唔佔位,啲藥丸照樣碌到佢下面。
 *
 * 兩張紙結構唔同,所以兩條:新增頁 `.btns` 上一個係 `#add-more`；
 * 詳情頁 `.btns` 係喺 `#sheet-content` 入面（`#` 夠特定,蓋得過上面個簡寫）。
 */
#add-more { padding-bottom: 20px; }
#sheet-content > .btns { margin-top: 20px; }

/* 卡上「乜都攞唔到」嗰陣嘅最後防線 —— 係提示唔係內容,所以要淡啲、細啲 */
.txt.hint { color: var(--ink-3); font-size: 13px; }

/* 「刪除」自己一行，喺內容度唔跟鍵盤（用戶 2026-09-17：「刪除制保留返係下面唔需要固定」）。
   ⚠️ 靠左、唔撐闊 —— 撐到成行闊會變成「主要動作」,但佢係最唔應該易撳嗰粒。 */
.delrow { display: flex; margin: 18px 0 0; }
/* ⚠️ **唔好**喺呢度改高度。全 app 嘅 `.btn` 都係 40 點,我一度想撐到 46
   （夾我自己嗰個 44 點觸控標準）,結果 `ui:audit` 即刻報「1 種角色唔一致」——
   呢個 repo 嘅標準係「同一種角色只可以有一個外形」,唔係 44。
   要改就全 app 一齊改,唔可以為咗一粒掣破壞一致性。 */
.delrow .btn { flex: 0 0 auto; }

/* 搜尋欄嗰粒清除掣 —— 借返 `.f.labrow .x` 同一個角色同外形（`ui:audit` 守住一致性）。
   ⚠️ 負外邊距係為咗唔撐高成條搜尋欄:44 點嘅撳區,但視覺上仍然係 40 點高嗰條。 */
.sbox .x { width: 44px; height: 44px; margin: 0 -14px 0 0; display: grid; place-items: center;
  color: var(--muted); background: none; border: 0; flex: 0 0 auto; }
.sbox .x:active { color: var(--ink); }

/*
 * 頭像裁圖（老細 2026-09-18：「My Avatar 可調整圖片」）。
 *
 * ⚠️ 張相用 `transform` 郁,唔好改 `width`／`left` —— 嗰啲每郁一格都要重新排版;
 *    transform 純 GPU,拖起上嚟先會順。
 * ⚠️ 個圓圈係**遮罩**唔係 border:用一個好粗嘅 `box-shadow` 掏個窿出嚟,
 *    咁樣圈外面自動變暗,唔使另外再叠一層。
 * ⚠️ `touch-action: none` 一定要有 —— 唔係你拖張相嗰下會俾 WKWebView 攞去做捲動。
 */
.crop-stage {
  position: relative; width: 100%; aspect-ratio: 1 / 1; max-height: 58vh;
  margin: 4px auto 0; border-radius: 16px; overflow: hidden;
  background: var(--bg-2); touch-action: none; user-select: none;
  display: grid; place-items: center;
}
.crop-stage img {
  position: absolute; left: 50%; top: 50%; transform-origin: center;
  max-width: none; max-height: none; will-change: transform; pointer-events: none;
}
.crop-ring {
  position: absolute; inset: 0; margin: auto; width: 74%; aspect-ratio: 1 / 1;
  border-radius: 50%; pointer-events: none;
  box-shadow: 0 0 0 9999px var(--blur-2); border: 1px solid rgba(255,255,255,.35);
}
.crop-zoom { display: flex; align-items: center; gap: 12px; margin: 16px 2px 0; }
.crop-zoom span { font-size: 13px; color: var(--muted); flex: none; }
.crop-zoom input[type="range"] { flex: 1; accent-color: var(--ink); height: 28px; }
