/* ============================================================
   Ztor 2.0 — STUDIO TOKENS  ·  the Operate-mode surface layer
   ------------------------------------------------------------
   Reverse-engineered 2026-07-28 from the shipped Creator Studio R2.1
   (`creator-studio-source/ztor-creator-studio/r2.1`). Source of truth for
   the CAPTURE was three cascading files, collapsed here into one:
     1. ds-components/_tokens.css   — the foundation (light :root + dark override)
     2. ds-components/fonts.css     — re-declares the 4 font tokens (WINS over 1)
     3. shared.css                  — :lang(zh-Hant) font + tracking overrides
   Values are captured VERBATIM. Where the three layers disagreed, the
   EFFECTIVE (rendered) value is recorded and the superseded one noted.

   ── Why this file exists ────────────────────────────────────
   PRODUCT.md principle 4 — "Same tokens, two worlds": consumer surfaces
   PERFORM (dark, cinematic, glass), studio surfaces OPERATE (light,
   scannable, dense). Those are genuinely different jobs and they need
   genuinely different values — a 76px display size and a 28px control
   height do not belong to the same scale. So the studio gets its own
   token layer rather than a re-tint of the consumer one.

   ── Why it is SCOPED, not merged ────────────────────────────
   9 token names carry different values in the two worlds:
     --radius-sm  4px → 3px      --chart-1  #4ade80 → #ffa33f
     --radius-md  8px → 6px      --chart-2  #a78bfa → #266DF0
     --radius-lg 12px → 8px      --chart-3  #38bdf8 → #22C55E
     --fw-semibold 600 → 700     --chart-4  #f472b6 → #F8D749
   Merging them into tokens.css would silently restyle every existing
   consumer component. Inside `[data-app="studio"]` they simply shadow the
   root values, so both worlds keep their own answer and neither breaks.

   ── How to use ──────────────────────────────────────────────
   Link AFTER tokens.css, never bundled (same rule as tokens.css):
     <link rel="stylesheet" href="tokens.css">
     <link rel="stylesheet" href="tokens-studio.css">
   Then opt a page (or any subtree) in:
     <html data-app="studio">                    → studio, light
     <html data-app="studio" data-theme="dark">  → studio, dark
     <div data-app="studio"> … </div>            → studio island in a consumer page
   Custom properties inherit, so everything inside the scope reads studio
   values. Nothing outside it changes.

   ── Not captured (deliberate) ───────────────────────────────
   · Component-local custom properties (kpi.css, button.css, card.css,
     input.css, …) — those are component APIs, not foundation tokens, and
     their components are not ported here.
   · `.theme-toggle` styling from _tokens.css — a widget, not a token.
   · Geist / Geist Mono as the primary UI face: superseded in the source
     itself by fonts.css (Satoshi leads, Geist demoted to fallback).

   ⚠ WEBFONT GAP — read before shipping a studio surface
   These tokens name Satoshi · Chiron Hei HK · Noto Sans TC · Geist ·
   Geist Mono · Inter. This repo self-hosts ONLY LINE Seed TW
   (assets/fonts/). Until the rest are copied in with their @font-face
   declarations, studio Latin text falls through to system-ui and studio
   小字中文 falls to the OS face. See README "Studio layer" for the list.
   ============================================================ */

/* ═══════════════════════════════════════════════════════════════════
   STUDIO · LIGHT  (default)  +  all theme-independent scales
   ═══════════════════════════════════════════════════════════════════ */

[data-app="studio"] {

  /* ─────────────────────────────────────────
     COLOR — Role layer (shadcn/ui aligned)
     命名對齊 shadcn/ui 的通用 role；studio 多出來的標 [ext]。
     對齊語意、不對齊數值——品牌橘照樣是 --primary。
     ───────────────────────────────────────── */

  /* Base surfaces / text */
  --background:         #FFFFFF;   /* canvas / body */
  --foreground:         #1A1A1A;   /* off-black — 純黑殺層次 */
  --card:               #FFFFFF;   /* cards / panels */
  --card-foreground:    #000000;
  --popover:            #FFFFFF;   /* popovers / nav 浮層 */
  --popover-foreground: #000000;
  --muted:              #FAFAFA;   /* 次級底 */
  --muted-foreground:   #6E6E68;   /* 輔助文字（對白卡 5.0:1，過 AA）*/
  --accent:             #F3F3F3;   /* 互動 hover 統一色 — 全站 hover 一律吃這支 */
  --accent-foreground:  #000000;
  /* --secondary 於 2026-07-13 退役：全站零消費，hover 一律用 --accent。不復活。 */

  /* Primary — highlighter orange. Same brand hex as the consumer world. */
  --primary:            #ffa33f;
  /* 深墨而非白字：白對 #ffa33f 只有 1.99:1（連 large-text 3:1 都不到），
     #171717 對 #ffa33f 是 9.02:1（AAA），且與夜間版同值 → 主要按鈕兩個主題長得一致。 */
  --primary-foreground: #171717;
  /* [ext] --on-primary ＝「鋪在實色橘上、保證讀得到」的墨色，亮暗同值。
     大面積橘底（hero KPI 整張卡）走這支；小面積按鈕文字走 --primary-foreground。 */
  --on-primary:         #171717;
  --primary-hover:      #ffb866;   /* [ext] shadcn 用 /90，這裡保留具名 hover */

  /* Destructive — 破壞性操作（刪除鈕等）。與 --status-error（狀態徽章）語意分開。 */
  --destructive:            #DA314A;
  --destructive-foreground: #FFFFFF;

  /* Edges */
  --border:        #EAEAEA;        /* hairline — 靠色階分層，不靠重邊 */
  --input:         #EAEAEA;        /* 控件邊（＝border）*/
  --input-surface: var(--card);    /* 控件填色底：亮色＝白卡，靠 border 分界 */
  /* [ext] 巢狀層填色（疊在卡片上的第二層 surface）。亮色＝透明：卡與 nest 同為白，
     單靠 --shadow-nest-up 的向上陰影分層就夠。深色才真的疊一層薄膜。 */
  --nest-surface:  transparent;
  --ring:          var(--primary); /* 品牌橘 focus ring，亮暗同色 */

  /* ── 跨世界相容別名（2026-07-28）────────────────────────────────────
     消費端的語意墨色名稱，在 studio 作用域內對應到 studio 自己的墨色。

     為什麼需要：任何「共用元件」都是用消費端的名字寫的。--text-primary 在
     :root 是 rgba(255,255,255,.95)，而 studio 作用域從來沒有覆寫它——所以
     一個共用元件被放進 studio 作用域時，會拿到「白字」配「亮底」。
     實例：.liquid-glass 的標籤（材質兩個世界相同，但**墨色必須跟著底走**，
     不是跟著材質走），在 BACKSTAGE 亮色下白字幾乎讀不到。

     修在這裡而不是修 .liquid-glass，是因為那是整類問題，不是單一元件的
     問題：任何消費端元件進到 studio 都會踩到同一顆地雷。名字對齊之後，
     共用元件不必知道自己在哪個世界。 */
  --text-primary:   var(--foreground);
  --text-secondary: var(--foreground-muted);
  --text-tertiary:  var(--muted-foreground);
  --text-disabled:  color-mix(in srgb, var(--foreground) 38%, transparent);
  --bg-primary:     var(--surface-page);
  --bg-secondary:   var(--muted);
  --bg-tertiary:    var(--card);
  --bg-card:        var(--card);
  --border-subtle:  var(--border-soft);
  --border-default: var(--border);
  --border-strong:  var(--foreground-muted);

  /* Charts — 品牌 ＋ status 色序，7 階 */
  --chart-1: #ffa33f;   /* 橘 */
  --chart-2: #266DF0;   /* 藍 */
  --chart-3: #22C55E;   /* 綠 */
  --chart-4: #F8D749;   /* 黃 */
  --chart-5: #8B5CF6;   /* 紫 */
  --chart-6: #EC4899;   /* 玫紅 */
  --chart-7: #06B6D4;   /* 青 — 對 chart-2 藍 ΔE2000≈26、chart-3 綠≈34 */

  /* Sidebar — app-shell rail 自成一組 role */
  --sidebar:                    #FBFBFB;
  --sidebar-foreground:         #000000;
  --sidebar-primary:            #ffa33f;
  --sidebar-primary-foreground: #FFFFFF;
  --sidebar-accent:             #F3F3F3;
  --sidebar-accent-foreground:  #000000;
  --sidebar-border:             #EAEAEA;
  --sidebar-ring:               var(--primary);
  --sidebar-active:             #ECECEC;   /* [ext] 已選 pill — 回退用，導覽已選走 --selected-* */

  /* ── Selected / active — 一套配方、三種形態 ────────────────
     「已選中」全站一律用品牌橘，強度隨控件份量調整：
       tint      安靜的持續選取（側欄／次層導覽／篩選 pill／segment／chip）→ 下面這組
       underline 主要檢視切換（tabs）→ --primary 當底線色
       solid     離散且已提交的選擇（pager 目前頁／主 CTA）→ --primary 實色
     實色橘保留給 CTA 與 solid，導覽／篩選走 tint，橘才不會與 CTA 搶焦
     （守住 DESIGN.md 的 One Spotlight Rule：橘 ≤10% 畫面）。 */
  /* [ext] --brand-ink ＝「品牌橘，但可以當文字用」的那一版。--primary 對近白底
     只有 1.92:1；任何要當字／icon 的橘都必須走這支。亮色壓深成同色相 32° 的
     #8F4E00（對 --sidebar 6.23:1、對 14% tint 5.70:1、對白卡 6.45:1，皆過 AA）。 */
  --brand-ink:              #8F4E00;
  --selected-surface:       color-mix(in srgb, var(--primary) 14%, transparent);
  --selected-surface-hover: color-mix(in srgb, var(--primary) 20%, transparent);
  --selected-ink:           var(--brand-ink);   /* 語意別名：這個橘代表「已選中」*/

  /* ── [ext] Studio extensions — shadcn 沒有的面與文字階 ── */
  --surface-shell:               #F0F0EE;   /* app shell 外層 canvas */
  --surface-page:                #FAFAFA;   /* shell 內的 route page */
  --surface-inverse:             #000000;   /* footer / hi-contrast slab */
  --foreground-muted:            #4D4D4D;   /* 中階文字（實色化，非 rgba）*/
  --foreground-on-inverse:       #FFFFFF;   /* 黑 slab 上的文字 */
  --foreground-on-inverse-muted: rgba(255, 255, 255, 0.6);
  --border-soft:                 #EFEFEF;   /* 更淡的分隔線 */
  --border-inverse:              rgba(255, 255, 255, 0.1);   /* 黑 slab 上的 hairline，兩主題同值 */
  --gradient-brand:              linear-gradient(90deg, #ffd9a0 0%, #ffa33f 55%, #ff7a4d 100%);

  /* ── [ext] Status accents ───────────────────────────────────
     三支一組的分工：`--x` 填色 · `--x-fill` 半透明染底 · `--x-ink` 文字。
     元件永遠寫 -ink，由主題決定要不要壓深——這條規則在兩個主題都成立。 */
  --status-success: #22C55E;
  --status-info:    #266DF0;
  --status-warning: #F8D749;
  --status-accent:  #8B5CF6;   /* purple — 額外的分類色相 */
  --status-error:   #DA314A;   /* 狀態徽章的錯誤色。值同 --destructive，暗色分歧 */

  /* Inks — 「狀態色當文字」的可讀版本。
     黃色當文字用在亮底上先天不可能：#F8D749 對白只有 1.42:1 → #8A6D00 4.92:1。 */
  --status-success-ink: #052E16;
  --destructive-ink:    #4C0519;
  --status-warning-ink: #8A6D00;
  --status-info-ink:    #1D4ED8;
  --status-accent-ink:  #6D28D9;

  /* Fills — 染色膠囊的底（配方 = 狀態色 12% 半透明）。
     引用 var(--…) 而非寫死：custom property 延遲解析，深色主題覆寫狀態色後
     這條 fill 自動跟著變，所以只需定義一次。 */
  --status-success-fill: color-mix(in srgb, var(--status-success) 12%, transparent);
  --destructive-fill:    color-mix(in srgb, var(--destructive) 12%, transparent);

  /* Deep — 給「坐在實色暖底上」的膠囊。12% 淡染在飽和橘上幾乎看不出色相，
     改成深實底之後「綠」由底本身承載，字換白。
     由站上那支狀態色推導（35% 狀態色 ＋ 65% 暖黑 #1a1208）而不是另挑一個顏色：
     色相從 144° 移到 130°（往橘走 14°），綠不再跟橘互打；暖黑讓它讀起來像
     「長在這張橘卡上」。白字對比 9.30:1（紅版 12.64:1），AAA。 */
  --status-success-deep: color-mix(in srgb, var(--status-success) 35%, #1a1208);
  --destructive-deep:    color-mix(in srgb, var(--status-error)   35%, #1a1208);

  /* ─────────────────────────────────────────
     GEOMETRY
     ⚠ shadows the root --radius-sm/md/lg (4/8/12px) inside this scope.
     ───────────────────────────────────────── */
  --radius-sm:    3px;
  --radius:       6px;            /* primary buttons */
  --radius-md:    var(--radius);  /* 別名，避免 67 處呼叫點 churn */
  --radius-lg:    8px;            /* nav panels */
  --radius-xl:    16px;           /* cookie banner */
  --radius-shell: 28px;           /* route-page corner inside the sidebar app shell */
  --radius-pill:  9999px;

  /* ─────────────────────────────────────────
     CONTROL SIZES — 表單控件＋按鈕共用高度級（全部 4 的倍數）
     同尺寸的 input 與 button 等高。
     **新增或修改任何單行控件，高度一律從這裡取，不要用 padding 去湊** —
     padding×2 ＋ font-size×line-height 幾乎一定算出小數（站上曾因此長出
     41.5／37.5／35.5 三種對不齊的搜尋框）。
     ───────────────────────────────────────── */
  --control-h-xs: 28px;   /* 密集：表格內欄位 */
  --control-h-sm: 36px;   /* **單行控件實際預設** — input / select / btn / pill / 搜尋框 */
  --control-h-md: 44px;   /* 刻度層的 "default" 命名，非站上實際預設 */
  --control-h-lg: 52px;
  --control-h-xl: 60px;

  /* ─────────────────────────────────────────
     SPACING — --sp-* （px 直命名）
     間距唯一刻度：數字＝px。涵蓋 studio 實際使用的密集節奏（取自 ~443 處實值統計）。
     元件的 gap / padding / margin 一律 var(--sp-N)；奇數微調值（1/3/5/7/9/11/13px）
     屬 optical adjustment、保留字面值不入刻度；負值 margin 亦保留字面值。
     ⚠ 與消費端的 --space-N（N×4px）並存，不互相取代：一個是密集後台的節奏，
       一個是電影感前台的節奏。studio 元件寫 --sp-*。
     ───────────────────────────────────────── */
  --sp-2:  2px;
  --sp-4:  4px;
  --sp-6:  6px;
  --sp-8:  8px;
  --sp-10: 10px;
  --sp-12: 12px;
  --sp-14: 14px;
  --sp-16: 16px;
  --sp-18: 18px;
  --sp-20: 20px;
  --sp-24: 24px;
  --sp-28: 28px;
  --sp-32: 32px;
  --sp-40: 40px;
  --sp-48: 48px;
  --sp-56: 56px;
  --sp-64: 64px;
  --sp-72: 72px;
  --sp-80: 80px;
  --sp-96: 96px;

  --space-shell-gutter: 16px;   /* desktop gap above the route page */

  /* WIDTH — --w-* 欄位／小元件的 max-width（或 flex-basis）刻度，主題無關。
     與 --sp-* 同邏輯：數字＝px。依實際使用值按需擴充，不預先鋪滿。 */
  --w-220: 220px;
  --w-300: 300px;

  /* ─────────────────────────────────────────
     SCROLLBAR — 全站自訂捲軸，不分主題
     顏色由 --foreground 混 transparent 推導，--foreground 本來就會跟著主題翻。
     **混 transparent 而不是混某個 surface token** 是關鍵：同一支捲軸會出現在
     側欄軌、白色 modal、深色卡、甚至實色橘的 hero 卡上；混死某個面等於把錯的
     底色烤進自己身上。
     size ＝軌道寬＝可拖曳的命中區；thumb 的視覺寬度由透明 border 內縮出來，
     所以 hover 變粗是在固定寬度內長大、不會造成 reflow。
     ───────────────────────────────────────── */
  --scrollbar-size:        12px;
  --scrollbar-thumb:       color-mix(in srgb, var(--foreground) 14%, transparent);
  --scrollbar-thumb-hover: color-mix(in srgb, var(--foreground) 32%, transparent);

  /* ─────────────────────────────────────────
     ELEVATION — 海拔階梯 E0–E4
     扁平為底，陰影只表達「浮起的層級」；同層分隔一律用 hairline／surface 色階。
       E0 貼底   無陰影（頁底、側欄、表格列；邊緣用 --shadow-hairline）
       E1 微浮   --shadow-raise      按鈕、輸入框、switch knob
       E2 卡片   --shadow-card       card、清單容器、KPI、sticky 工作列
       E3 懸浮   --shadow-float      下拉、popover、tooltip、拖曳中的列；card hover 升此階
       E4 覆蓋   --shadow-overlay    modal、對話框、抽屜
     規則：一元件一階；互動＝借上一階 token（不自創 hover 陰影）；
     越高越大而淡（offset/blur↑、alpha 收斂）；全站僅此階梯、不寫裸陰影值。
     ⚠ 這是 studio 的深度語言。消費端的深度語言是 liquid glass 的 --lg-shine
       ——兩者不混用：玻璃面不加 --shadow-*，studio 卡片不加 --lg-*。
     ───────────────────────────────────────── */

  --shadow-micro:
    0 4px 4px rgba(23, 23, 23, 0.04);

  /* E1 · low-elevation control raise */
  --shadow-raise:
    0 1px 2px rgba(0, 0, 0, 0.06);
  --shadow-raise-strong:
    0 1px 2px rgba(0, 0, 0, 0.16);

  /* E2 · resting card（drop ＋ rim）*/
  --shadow-card:
    0 2px 8px -1px rgba(12, 10, 9, 0.05),
    0 0 0 1px rgba(23, 23, 23, 0.05);

  /* E3 · floating — 下拉／popover／tooltip／拖曳列；card hover 借用本階 */
  --shadow-float:
    0 8px 24px -8px rgba(12, 10, 9, 0.08),
    0 2px 6px -2px rgba(12, 10, 9, 0.05),
    0 0 0 1px rgba(23, 23, 23, 0.05);
  --shadow-card-hover: var(--shadow-float);

  /* E3 變體 · 去 rim 版（列表列 hover/drag 浮起專用）
     --shadow-float 的 `0 0 0 1px` 是刻意畫的軟性描邊，用來在 dropdown/popover
     這類疊在任意底色上的浮層補輪廓；但列表列的浮起卡背景（白）跟頁面背景（米白）
     色差已經夠明顯，再疊一圈描邊會被誤讀成「有 border」。
     淺色拿掉 rim、只留 drop；深色維持完整 --shadow-float（見 dark override）。 */
  --shadow-lift-flat:
    0 8px 24px -8px rgba(12, 10, 9, 0.08),
    0 2px 6px -2px rgba(12, 10, 9, 0.05);

  /* E4 · overlay — modal／對話框／抽屜（scrim 之上）*/
  --shadow-overlay:
    0 16px 40px -8px rgba(12, 10, 9, 0.18),
    0 0 0 1px rgba(23, 23, 23, 0.08);

  /* E0 邊緣 · sub-pixel rim（分隔用，非浮起）*/
  --shadow-hairline:
    0 0 1px rgba(0, 0, 0, 0.2);

  /* Top-edge highlight — 疊在浮起面頂緣的 1px 內光，給無邊框卡一道「被光打到的
     上緣」，與 --shadow-card 併用做出微立體感。亮色白底上幾乎不可見（無害）；
     深底才顯出上緣高光。 */
  --shadow-edge-top:
    inset 0 1px 0 rgba(255, 255, 255, 0.5);

  /* Nest shadow — 向上柔投影，由「嵌在卡片底部的巢狀層」往上打在母卡面上。
     ⚠ 模糊會往左右外溢，母卡必須 overflow:hidden。
     亮色版：卡與 nest 同為白，這道陰影是唯一的分層線索，所以不能再更淡。 */
  --shadow-nest-up:
    0 -6px 8px rgba(0, 0, 0, 0.05);

  /* Seam shadow — 向右柔投影，由上層主面板蓋向相鄰的下層面板，順著圓角填滿接縫凹口。
     ⚠ 不可掛在捲動容器（其圓角被瀏覽器畫成方角 → 方角陰影）；掛在一個透明、
     真圓角的輔助層（貼上層面板右緣）向右投到下層上。 */
  --shadow-seam:
    7px 0 20px -4px rgba(12, 10, 9, 0.16);

  /* Header shadow — sticky 建立流程 header 下緣的柔和投影，把 header 與下方
     捲動內容分開。由 header 後方等高、內縮、下方大圓角的色塊投出，只露下緣。 */
  --shadow-header:
    0 3px 16px rgba(0, 0, 0, 0.10);

  /* ─────────────────────────────────────────
     MOTION
     Studio 的動態是 UTILITY：一個時長、一條曲線，不做入場編排。
     ⚠ 消費端的 4-ease／非均勻時長刻度（--ease-out/panel/settle/emphasized、
       --dur-*、--reveal-*、--seq-*）是「典禮」語言，studio 不吃。
       --easing 與消費端的 --ease-panel 同值 cubic-bezier(0.32,0.72,0,1) 是巧合，
       不是別名：這裡是通用曲線，那裡是「有質量的面」專用。
     ───────────────────────────────────────── */
  /* 2026-07-28 L：「所有動態都放慢，試 688ms」＋「我要一個沉穩優雅的站」。
     ONSTAGE 的節奏骨幹已釘在 688ms；BACKSTAGE 取 420ms 而非 688ms，理由是
     這支 token 同時餵 hover 回饋——一個 688ms 才完成的 hover 會讀成延遲，
     那是「遲鈍」不是「沉穩」。420ms 明顯慢下來、仍在「立即回應」的知覺門檻內。
     要整站一律 688ms 只需改這一行。 */
  --duration: 420ms;
  --easing:   cubic-bezier(0.32, 0.72, 0, 1);

  /* Frosted overlay recipe — 真正浮在內容上的浮層（modal／dropdown／popover）
     的毛玻璃質感。見檔尾 .overlay-surface 集中規則。 */
  --overlay-blur: blur(14px) saturate(140%);
  --overlay-tint: rgba(0, 0, 0, 0.45);   /* modal backdrop 的加深層 */

  /* ─────────────────────────────────────────
     TYPOGRAPHY — families
     EFFECTIVE values（fonts.css 覆寫 _tokens.css 的 Geist-first 宣告）。
     角色分工（2026-07-28 定案）：
       英文 標題    → Satoshi ＋ 全大寫
       英文 內文/UI → Satoshi
       中文 標題    → LINE Seed TW（粗、大，它的強項）
       中文 內文/UI → 昭源黑體 Chiron Hei HK（LINE Seed 在 12px 內白會填死）
     ⚠ --font-cjk-display / --font-cjk 刻意「不」以 sans-serif 結尾——它們是被組進
       更長堆疊裡的片段，不是完整堆疊。通用字族只能放在整條堆疊的最後一項；
       卡在中間會讓後面的 Satoshi 永遠輪不到（源頭實測過的真實 bug）。
     ───────────────────────────────────────── */
  /* ⚠ 這一段是本檔唯一「非逐字捕獲」的部分（2026-07-28 L 字體裁示覆蓋捕獲契約）。
     兩個世界現在共用同一條字體規則，改動有三：
       1. 移除 Geist / Inter —— 本 repo 從未自帶這兩個字檔，留著只是誤導：
          它們永遠 resolve 失敗，實際落點是後面的 CJK 或 system-ui。
       2. --font-cjk-display / --font-cjk 不再是「無通用字族的片段」。原本它們
          被組進更長的堆疊裡所以沒事，但 --font-cjk-display 這個名字在
          fonts.css 是一條**完整**堆疊；studio 作用域用同名片段遮蔽它，
          任何直接讀該 token 的消費端元件（若被放進 studio 作用域內）就會拿到
          一條沒有結尾通用字族的堆疊。改成完整堆疊即可兩邊都成立。
       3. 拉丁一律 Satoshi，中文標題 LINE Seed TW、中文內文昭源黑體。
     字面本身與 fonts.css 同源；那支檔案擁有所有 @font-face 與
     unicode-range CJK 釘選（拉丁永遠拿不到中文字面）。 */
  --font-cjk-display:
    "Satoshi", "LINE Seed TW", "Chiron Hei HK", "Noto Sans TC",
    "PingFang TC", "Microsoft JhengHei", sans-serif;
  --font-cjk:
    "Satoshi", "Chiron Hei HK", "Noto Sans TC", "LINE Seed TW",
    "PingFang TC", "Microsoft JhengHei", sans-serif;

  --font-display: var(--font-cjk-display);   /* 標題：中文走 LINE Seed */
  --font-ui:      var(--font-cjk);           /* UI／控件：中文走昭源黑體 */
  --font-body:    var(--font-cjk);           /* 內文：同上 */
  --font-mono:    "Geist Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  /* 給所有「要被讀成數量的字」用（金額、KPI 數值、統計）。契約不是「哪個字面」
     而是「這串字是數量」：消費端一律搭 tabular-nums 讓 $684.32 與 $1,560.00 的
     小數點對齊，且標題的全大寫＋正字距規則不該套到數字上。 */
  --font-numeric: "Satoshi", system-ui, -apple-system, sans-serif;

  /* ── Font-size scale — 整數級，studio 唯一來源 ──
     所有 font-size 一律 var(--fs-N)；半 px 已收斂（.5 捨去、<11 併 11）。
     ⚠ 與消費端的角色命名刻度（--fs-h1/--fs-body/…）並存：那套是 role→size，
       這套是 size 本身。studio 元件寫 --fs-N。 */
  --fs-11: 11px;
  --fs-12: 12px;
  --fs-13: 13px;
  --fs-14: 14px;
  --fs-15: 15px;
  --fs-16: 16px;
  --fs-18: 18px;
  --fs-20: 20px;
  --fs-22: 22px;
  --fs-24: 24px;
  --fs-28: 28px;
  --fs-32: 32px;
  --fs-40: 40px;
  --fs-44: 44px;
  --fs-56: 56px;
  --fs-64: 64px;

  /* ── Font-weight scale ──
     ▍全站字重上限 400，除非非重不可。
     階層由「字級 × 顏色 × 留白」承載，不靠加粗——這正是 Satoshi 變輕之後好看的
     原因：它的字面本來就開闊，一加粗就把那份開闊壓掉了。
     （遷移實績：CSS 呼叫點 medium 119→31、semibold 59→0、regular 57→202。）
     只有兩個例外層級：
       500 ＝「不加重就失去意義」：與同尺寸同色的未選中兄弟並排的 active/selected
             狀態，以及 11–12px 燒在染色底上的微型字（badge／chip／monogram）。
       700 ＝「重量本身就是語意」：品牌字標、財務小計／總計列、掃描結果橫幅、語意 <b>。
     兩者以外一律 400。
     ⚠ shadows the root --fw-semibold (600 → 700) inside this scope. */
  --fw-light:   300;   /* 大字級專用（44px＋ display 角色）*/
  --fw-regular: 400;   /* 預設。標題、控件、表頭、數值 */
  /* 內文專用字重。從 --fw-regular 拆出來，因為那支同時餵標題與控件，一起調下去
     標題也會變細。350 是「內文最細不得低於此」的下限。
     實際算繪值被字檔的軸下限夾住，兩支字面落點不同（CSS 字重比對規則：<400 先往下找）：
       昭源黑體 可變軸 250–900 → 真的畫 350
       Satoshi  靜態 300/400/… → 往下落在 300
     也就是中文 350、英數 300。這個落差是刻意留著的，不是 bug：同一數值下方塊字的
     筆畫密度遠高於拉丁字母，看起來本來就比較細，中文多 50 反而讓兩者視覺等重。 */
  --fw-body:    350;
  --fw-medium:  500;   /* 例外一 */
  --fw-bold:    700;   /* 例外二 */
  /* @deprecated — 載入的 Satoshi 無 600，此鍵長年實際渲染成 700（假層級）。
     源頭呼叫點已全數清空（59→0）；保留別名僅為舊碼相容，新程式碼不要再用。 */
  --fw-semibold: var(--fw-bold);

  /* ── Line-height (leading) scale ──
     第 4 個原始字型維度（繼字體／字級／字重）。所有 line-height 一律引用這 7 階。
     命名對齊 shadcn/Tailwind 的 leading-*，數值為資料密集 UI 調過、比 Tailwind
     預設更緊。unitless（隨字級縮放）。 */
  --lh-none:    1;      /* set solid — display 標題、按鈕標籤（單行）*/
  --lh-tight:   1.1;    /* 大標題 — display-44 / h2 / h3 */
  --lh-snug:    1.2;    /* 小標題 / 標籤 — h4、section label */
  --lh-normal:  1.3;    /* caption / meta */
  --lh-comfy:   1.4;    /* 元件內多行說明 / 密集列表 */
  --lh-relaxed: 1.5;    /* 內文 body */
  --lh-loose:   1.6;    /* 大內文 / 長文 body-16 */

  /* ── Typography FOUNDATION scale ────────────────────────────
     每個排版角色 = 5 個維度打包（family / size / weight / line-height / tracking）。
     這是「刻度層」：以尺寸命名，不以用途命名。用途層見下方 role aliases。
     消費端用 .t-* utility class 打包同樣的概念；studio 用 token 五件組，
     因為後台元件需要在自己的 CSS 裡逐項取用（例如只要 size 不要 weight）。 */

  --type-display-64-family:      var(--font-display);
  --type-display-64-size:        var(--fs-64);
  --type-display-64-weight:      var(--fw-light);
  --type-display-64-line-height: var(--lh-none);
  --type-display-64-tracking:    -1.28px;

  --type-display-44-family:      var(--font-display);
  --type-display-44-size:        var(--fs-44);
  --type-display-44-weight:      var(--fw-light);
  --type-display-44-line-height: var(--lh-tight);
  --type-display-44-tracking:    -1px;

  --type-title-40-family:      var(--font-ui);
  --type-title-40-size:        var(--fs-40);
  --type-title-40-weight:      var(--fw-regular);
  --type-title-40-line-height: var(--lh-tight);
  --type-title-40-tracking:    -0.8px;

  --type-title-32-family:      var(--font-ui);
  --type-title-32-size:        var(--fs-32);
  --type-title-32-weight:      var(--fw-regular);
  --type-title-32-line-height: var(--lh-tight);
  --type-title-32-tracking:    -0.6px;

  --type-title-24-family:      var(--font-ui);
  --type-title-24-size:        var(--fs-24);
  --type-title-24-weight:      var(--fw-regular);
  --type-title-24-line-height: var(--lh-snug);
  --type-title-24-tracking:    -0.48px;

  --type-label-15-family:      var(--font-ui);
  --type-label-15-size:        var(--fs-15);
  --type-label-15-weight:      var(--fw-regular);
  --type-label-15-line-height: var(--lh-none);
  --type-label-15-tracking:    -0.3px;

  --type-label-14-family:      var(--font-ui);
  --type-label-14-size:        var(--fs-14);
  --type-label-14-weight:      var(--fw-regular);
  --type-label-14-line-height: var(--lh-snug);
  --type-label-14-tracking:    0;

  --type-body-16-family:      var(--font-body);
  --type-body-16-size:        var(--fs-16);
  --type-body-16-weight:      var(--fw-regular);
  --type-body-16-line-height: var(--lh-loose);
  --type-body-16-tracking:    0;

  --type-body-14-family:      var(--font-body);
  --type-body-14-size:        var(--fs-14);
  --type-body-14-weight:      var(--fw-regular);
  --type-body-14-line-height: var(--lh-relaxed);
  --type-body-14-tracking:    0;

  --type-caption-12-family:      var(--font-ui);
  --type-caption-12-size:        var(--fs-12);
  --type-caption-12-weight:      var(--fw-regular);
  --type-caption-12-line-height: var(--lh-normal);
  --type-caption-12-tracking:    0.05em;

  /* ── Typography ROLE aliases ────────────────────────────────
     用途層：元件寫這一組，不直接寫上面的尺寸層。換刻度時只改這裡的指向。 */

  --type-display-1-family:      var(--type-display-64-family);
  --type-display-1-size:        var(--type-display-64-size);
  --type-display-1-weight:      var(--type-display-64-weight);
  --type-display-1-line-height: var(--type-display-64-line-height);
  --type-display-1-tracking:    var(--type-display-64-tracking);

  --type-page-title-family:      var(--type-display-44-family);
  --type-page-title-size:        var(--type-display-44-size);
  --type-page-title-weight:      var(--type-display-44-weight);
  --type-page-title-line-height: var(--type-display-44-line-height);
  --type-page-title-tracking:    var(--type-display-44-tracking);

  --type-h2-family:      var(--type-title-40-family);
  --type-h2-size:        var(--type-title-40-size);
  --type-h2-weight:      var(--type-title-40-weight);
  --type-h2-line-height: var(--type-title-40-line-height);
  --type-h2-tracking:    var(--type-title-40-tracking);

  --type-h3-family:      var(--type-title-32-family);
  --type-h3-size:        var(--type-title-32-size);
  --type-h3-weight:      var(--type-title-32-weight);
  --type-h3-line-height: var(--type-title-32-line-height);
  --type-h3-tracking:    var(--type-title-32-tracking);

  --type-h4-family:      var(--type-title-24-family);
  --type-h4-size:        var(--type-title-24-size);
  --type-h4-weight:      var(--type-title-24-weight);
  --type-h4-line-height: var(--type-title-24-line-height);
  --type-h4-tracking:    var(--type-title-24-tracking);

  --type-section-label-family:      var(--type-label-14-family);
  --type-section-label-size:        var(--type-label-14-size);
  --type-section-label-weight:      var(--type-label-14-weight);
  --type-section-label-line-height: var(--type-label-14-line-height);
  --type-section-label-tracking:    var(--type-label-14-tracking);

  --type-body-lg-family:      var(--type-body-16-family);
  --type-body-lg-size:        var(--type-body-16-size);
  --type-body-lg-weight:      var(--type-body-16-weight);
  --type-body-lg-line-height: var(--type-body-16-line-height);
  --type-body-lg-tracking:    var(--type-body-16-tracking);

  --type-body-family:      var(--type-body-14-family);
  --type-body-size:        var(--type-body-14-size);
  --type-body-weight:      var(--type-body-14-weight);
  --type-body-line-height: var(--type-body-14-line-height);
  --type-body-tracking:    var(--type-body-14-tracking);

  --type-caption-family:      var(--type-caption-12-family);
  --type-caption-size:        var(--type-caption-12-size);
  --type-caption-weight:      var(--type-caption-12-weight);
  --type-caption-line-height: var(--type-caption-12-line-height);
  --type-caption-tracking:    var(--type-caption-12-tracking);

  --type-button-label-family:      var(--type-label-15-family);
  --type-button-label-size:        var(--type-label-15-size);
  --type-button-label-weight:      var(--type-label-15-weight);
  --type-button-label-line-height: var(--type-label-15-line-height);
  --type-button-label-tracking:    var(--type-label-15-tracking);
}

/* ═══════════════════════════════════════════════════════════════════
   STUDIO · DARK  —  midnight-v2
   ------------------------------------------------------------------
   實色面，不是半透明疊層：值由原半透明疊層算出，外觀近乎不變、改為實色。
   半透明只留給真正浮在內容上的 overlay（見檔尾 .overlay-surface）。

   Shell 層次語意（由深到淺，這個相對關係是硬需求）：
     content #0C0D0D → muted 襯底 #161718 → 外殼/rail #1C1D1E → 卡 #212223 → hover #2A2B2C
   content 最深、外殼明顯較淺、兩者拉開對比 → route page 讀起來是「內凹在外殼裡」。

   Selector 三形態：
     [data-app][data-theme]  html 同時帶兩個屬性（最常見）
     [data-theme] [data-app] 深色 html 裡的 studio 島
     [data-app] [data-theme] studio 殼裡的深色子樹
   ═══════════════════════════════════════════════════════════════════ */

[data-app="studio"][data-theme="dark"],
[data-theme="dark"] [data-app="studio"],
[data-app="studio"] [data-theme="dark"] {

  /* Base surfaces / text */
  --background:         #0C0D0D;   /* content-level，最深 */
  --foreground:         #FDFDFD;
  --card:               #212223;   /* 浮在 content 上的卡，略亮於外殼 */
  --card-foreground:    #FDFDFD;
  --popover:            #212223;   /* ＝卡同層 */
  --popover-foreground: #FDFDFD;
  --muted:              #161718;   /* 嵌套襯底：比卡深、比 content 亮一階 */
  /* #757575 在深色的四種面上全部不到 AA（input-surface 3.08 / card 3.46 /
     sidebar 3.66 / page 4.32），而所有次級文字都吃這一支。
     #979797：對最亮的面 4.85:1、對畫布 6.66:1，四個面全過且留有餘裕。 */
  --muted-foreground:   #979797;
  --accent:             #2A2B2C;   /* hover / 選單項底 */
  --accent-foreground:  #FDFDFD;

  /* Primary — 橘在深色不變 */
  --primary:            #ffa33f;
  --primary-foreground: #171717;
  --on-primary:         #171717;   /* 同亮色版：實色橘上一律深墨（9.02:1）*/
  --primary-hover:      #ffb866;

  /* Destructive */
  --destructive:            #E7000B;
  --destructive-foreground: #FFFFFF;

  /* Edges */
  --border:        #373839;   /* midnight 壓暗後邊界讀不出來 → 全站深色 hairline 一起提亮 */
  --input:         #373839;
  --input-surface: #2A2B2D;   /* 控件填色底：比卡 #212223 亮，filled 欄位在卡面上讀得出 */
  /* 疊在 --card 上的半透明薄膜，合成後 ≈#292A2B。刻意用冷調淺灰 rgb(222,223,233)
     而非純白——純白會把畫布的冷色調洗掉（B−R 由 +2 掉到 +0.8），這個 tint 疊上去
     反而把冷調推到 +3.0，與 midnight 畫布同溫。 */
  --nest-surface:  rgba(222, 223, 233, 0.04);
  /* --ring 不覆寫 → 繼承 var(--primary)＝橘，亮暗同色 */

  /* Charts — dark variants（提亮一階） */
  --chart-1: #ffa33f;
  --chart-2: #5896F3;
  --chart-3: #4ADE80;
  --chart-4: #F3CF58;
  --chart-5: #A78BFA;
  --chart-6: #F472B6;
  --chart-7: #22D3EE;   /* 暗卡面對比 8.8:1 */

  /* Sidebar */
  --sidebar:                    #1C1D1E;   /* rail＝外殼色，明顯亮於 content */
  --sidebar-foreground:         #FDFDFD;
  --sidebar-primary:            #ffa33f;
  --sidebar-primary-foreground: #171717;
  --sidebar-accent:             #262728;   /* rail hover over #1C1D1E */
  --sidebar-accent-foreground:  #FDFDFD;
  --sidebar-border:             #333435;
  --sidebar-ring:               var(--primary);
  --sidebar-active:             #303132;

  /* Selected / active — 深底可直接用品牌橘：
     對 --sidebar 8.49:1、對 14% tint 合成底 6.44:1、對 --card 8.02:1，皆過 AA。
     （亮色版必須壓深成 #8F4E00，深色不必。） */
  --brand-ink:              #ffa33f;
  --selected-surface:       color-mix(in srgb, var(--primary) 14%, transparent);
  --selected-surface-hover: color-mix(in srgb, var(--primary) 20%, transparent);
  --selected-ink:           var(--brand-ink);

  /* [ext] Studio extensions */
  --surface-shell:               #1C1D1E;   /* app shell（rail＋canvas）明顯亮於 content */
  --surface-page:                #0C0D0D;   /* route page ＝ content 底，最深、內凹在外殼裡 */
  --surface-inverse:             #000000;
  --foreground-muted:            #B9B9B9;
  --foreground-on-inverse:       #FDFDFD;
  --foreground-on-inverse-muted: rgba(253, 253, 253, 0.6);
  --border-soft:                 #202122;
  /* --border-inverse 不覆寫 → 黑 slab 上的 hairline 兩主題同值 */
  --overlay-tint:                rgba(0, 0, 0, 0.6);   /* 深底上遮罩要更濃才有存在感 */
  --gradient-brand:              linear-gradient(90deg, #ffb866 0%, #ffa33f 55%, #ff7a4d 100%);
  /* ↑ 拿掉亮色的淡膚起點 #ffd9a0，深底才讀得出漸層 */

  /* [ext] Status accents — 深底提亮版 */
  --status-success: #4ADE80;   /* 提亮，向「暗色其他狀態色都變亮」看齊 */
  --status-info:    #5896F3;
  --status-warning: #F3CF58;
  --status-accent:  #A78BFA;
  /* 狀態徽章的紅另走一支：#E7000B 在深底小字徽章太深不易讀。
     破壞性操作（刪除鈕等）維持 --destructive 不變。 */
  --status-error:   #FF3D47;

  /* Inks — 深底上飽和色本來就讀得到，墨色＝原色，不必壓深。
     留這幾行是為了讓「元件永遠寫 -ink、由主題決定要不要壓深」在兩個主題都成立。 */
  --status-success-ink: var(--status-success);   /* 深卡實測 7.06:1 */
  --status-warning-ink: var(--status-warning);
  --status-accent-ink:  var(--status-accent);
  /* 2026-07-28 L 裁示「檢查字元對比，有些內容看不清楚」——本檔唯一被量測抓到的
     繼承缺陷。#5896F3 疊在 12% 資訊色染底（合成 rgb(40,48,60)）上實測 4.49:1，
     差 0.01 就是不過（12px 屬 normal text，門檻 4.5 不是 3）。
     其餘三支 -ink 在深底本來就過，維持原色；只有藍需要提亮一階。
     用 color-mix 從 --status-info 推導而不是再寫死一個藍——與 --destructive-ink
     同一套作法，之後若調整 --status-info，這支墨色會自動跟著走。 */
  --status-info-ink:    color-mix(in srgb, var(--status-info) 88%, #fff);
  /* 紅墨走 --status-error 而非 --destructive。實測階梯（深色膠囊 rgb(57,30,32) 上）：
     --destructive #E7000B → 3.19:1 ✗；--status-error #FF3D47 → 4.35:1 ✗
     （12px 屬 normal text，門檻 4.5 不是 3）；再提一階才過 → 5.05:1 ✓。
     用 color-mix 推導而不是再寫死一個紅，--status-error 之後被調整時這支會跟著走。 */
  --destructive-ink:    color-mix(in srgb, var(--status-error) 88%, #fff);
  /* --status-*-fill / --status-*-deep 不覆寫：配方引用 var(--status-*)，
     custom property 延遲解析，狀態色一翻它們自動跟著翻。
     --*-deep 也沒有 dark override，這是對的不是漏調：它們專供「坐在實色橘上」的
     膠囊，而 --primary 亮暗同為 #ffa33f，膠囊坐的面根本沒變。 */

  /* Shadows — 深底陰影失效，提高 alpha ＋ 亮色內框補輪廓（階梯規則見亮色區）*/
  --shadow-micro:
    0 4px 4px rgba(0, 0, 0, 0.3);

  --shadow-raise:
    0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow-raise-strong:
    0 1px 2px rgba(0, 0, 0, 0.6);

  --shadow-card:
    0 2px 6px rgba(0, 0, 0, 0.4),
    0 0 0 1px rgba(253, 253, 253, 0.08);

  --shadow-float:
    0 6px 16px -4px rgba(0, 0, 0, 0.5),
    0 0 0 1px rgba(253, 253, 253, 0.10);
  --shadow-card-hover: var(--shadow-float);
  /* 深色沿用完整 --shadow-float（含 rim）：深底本來就無法靠純陰影表現浮起，
     rim 是唯一可見的提示，亮色版拿掉 rim 的理由在這裡不成立。 */
  --shadow-lift-flat: var(--shadow-float);

  --shadow-overlay:
    0 16px 40px -8px rgba(0, 0, 0, 0.6),
    0 0 0 1px rgba(253, 253, 253, 0.12);

  --shadow-hairline:
    0 0 1px rgba(253, 253, 253, 0.2);

  --shadow-edge-top:
    inset 0 1px 0 rgba(253, 253, 253, 0.05);

  --shadow-nest-up:
    0 -8px 8px rgba(0, 0, 0, 0.08);

  --shadow-seam:
    7px 0 22px -2px rgba(0, 0, 0, 0.6);

  --shadow-header:
    0 3px 16px rgba(0, 0, 0, 0.45);
}

/* ═══════════════════════════════════════════════════════════════════
   zh-Hant — CJK 字距歸零
   display/title/label 的負 letter-spacing（~−0.02em）是為拉丁大字做的光學收緊，
   但方塊字本就貼著走，套負字距會把中文擠在一起。繁中模式歸零 → 回到自然間距。
   只動有負值的 token；body/caption 本來就 0 或正值，不需覆寫。
   （英文語系不匹配本規則，維持緊收。）
   ═══════════════════════════════════════════════════════════════════ */

[data-app="studio"]:lang(zh-Hant),
[data-app="studio"] :lang(zh-Hant) {
  --type-display-64-tracking: 0;
  --type-display-44-tracking: 0;
  --type-title-40-tracking:   0;
  --type-title-32-tracking:   0;
  --type-title-24-tracking:   0;
  --type-label-15-tracking:   0;
}

/* ═══════════════════════════════════════════════════════════════════
   COMPANION RULES
   Not tokens — the three rules without which some tokens above have no
   consumer at all. Captured with them so the layer is self-contained.
   ═══════════════════════════════════════════════════════════════════ */

/* color-scheme — 讓「瀏覽器自己畫的」東西跟著主題走。
   <select> 展開後的選單不是我們的 DOM，是作業系統畫的，只有 color-scheme 能影響它。
   沒有這條，所有原生控制項都用淺色主題算繪：select 彈窗、日期選擇器、捲軸、
   自動填入的黃底、拼字檢查底線。只改 .select 的外觀是修不到彈窗的。
   ⚠ 這不是「加了就有深色下拉」的萬靈丹——DESIGN.md 仍要求原生 select 彈窗最終
     換成自家的 popover。這條是讓現況不破圖的底線，不是那個工作的替代品。 */
[data-app="studio"]                    { color-scheme: light; }
[data-app="studio"][data-theme="dark"],
[data-theme="dark"] [data-app="studio"],
[data-app="studio"] [data-theme="dark"] { color-scheme: dark; }

/* Frosted overlay surfaces — 一處治理。
   主要面（card / popover / muted）已是實色，浮層不會透出後方內容；此 blur 保留給
   「真正浮在內容上」的浮層作毛玻璃質感。新浮層加 .overlay-surface 即可，
   改 --overlay-blur 一次全部生效。 */
[data-app="studio"] .overlay-surface {
  -webkit-backdrop-filter: var(--overlay-blur);
          backdrop-filter: var(--overlay-blur);
}

/* Theme-switch transition — 換主題時面色平滑過渡，不閃。
   ⚠ 絕對不要掛在 [data-app="studio"] 本身（2026-07-28 實測抓到）。
   主題切換是在「同一個元素」上改寫 custom property，而該元素的 background-color
   又要靠那支 property 取值——當「宣告變數的元素」與「用該變數做 transition 的元素」
   是同一個時，transition 不會啟動，computed background-color 會**永久卡在舊值**。
   實測：子元素 background:var(--surface-shell) 無 transition → 正確畫 rgb(28,29,30)；
   同一個島本身有 transition → 700ms 後仍是 rgb(240,240,238)。
   （來源專案沒踩到只是湊巧：它的屬性在 <html>、會過場的底色在 <body>，是兩個元素。）

   所以過場只給「作用域的子孫」，不給作用域本身。 */
[data-app="studio"] .studio-fade {
  transition: background-color var(--duration) ease, color var(--duration) ease;
}

@media (prefers-reduced-motion: reduce) {
  [data-app="studio"] .studio-fade { transition: none; }
}
