/* ============================================================================
   Feasify Design Tokens  ·  v0.1  ·  2026-08-04  ·  DS-1
   ----------------------------------------------------------------------------
   这份文件是从 static/index.html（1,020 行 CSS）与 static/collect.html 里
   **实测**出来的取值收敛而成，不是凭空新拟的一套。每组都标了现状取值与出现次数。

   用法：
     <link rel="stylesheet" href="/static/design/tokens.css">
   主题：
     默认跟随系统（prefers-color-scheme）。
     显式指定：<html data-theme="light"> / <html data-theme="dark">

   🔴 布局铁律：所有尺寸 token 都是「盒子」的，不是「字数」的。
      要上 en / te reo Māori / 简中三语，加语言只能加字典不改布局，故：
      按钮/药丸/字段一律用 min-height + padding，禁止写死 width/height 卡文本。
   ========================================================================== */

/* AI 环形描边的旋转角。注册成 <angle> 才能被 animation 插值（裸自定义属性不可动画）。
   消费方只需 animation:<name> Ns linear infinite 去推 --ai-rot 到 360deg。 */
@property --ai-rot{ syntax:'<angle>'; inherits:false; initial-value:0deg; }

:root{
  /* ── 中性阶（slate）────────────────────────────────────────────────────
     现状是 gray 与 slate 两套灰混用：文字多走 gray(#111827/#1f2937/#374151/
     #6b7280/#9ca3af)，深色面与卡背多走 slate(#0f172a/#0d1524/#f8fafc/#e2e8f0)。
     统一到 slate：暗色主题现有取值已经 100% 是 slate，地图底 #eef1f5 也偏冷。   */
  --n-0:#ffffff;
  --n-25:#f8fafc;      /* 现状 #f8fafc(7) + #f9fafb(1) */
  --n-50:#f1f5f9;      /* 现状 #f1f5f9(4) + #f1f1f1(2) + #f1f5f4(2) */
  --n-100:#e2e8f0;     /* 现状 #e2e8f0(8) + #e5e7eb(3) + #eff1f4(2) */
  --n-200:#cbd5e1;     /* 现状 #cbd5e1(1) + #d1d5db(1) */
  --n-300:#94a3b8;     /* 现状 #94a3b8(7) + #9ca3af(4)；仅作图标/装饰，见 --fg-faint */
  --n-500:#64748b;     /* 现状 #64748b(3) + #6b7280(4) */
  --n-600:#475569;
  --n-700:#334155;
  --n-800:#1e293b;
  --n-900:#0f172a;
  --ink:#16181d;       /* 品牌近黑，正文默认色 + logo 底；刻意保留，非 slate-900 */

  /* ── 深色面（已存在于 #chatmodal，本次只是把它命名）──────────────────── */
  --d-sunken:#0a1120;  /* 现状 #chatmodal .chatrow input / .chatclip 底 */
  --d-base:#0d1524;    /* 现状 #chatmodal .tmbox / .tmbody 底 */
  --d-raised:#1b2740;  /* 现状 #chatmodal .chatmsg.ca 气泡底 */

  /* ── 品牌 teal ────────────────────────────────────────────────────────
     🔴 #0EA882 在白底只有 3.03:1 —— 作为「面」（按钮底/图形/边框）够 WCAG
        组件级 3:1，但作为「小号文字」不达正文 4.5:1。故拆成三个用途：      */
  --brand:#0EA882;         /* 面：填充、图标、边框、地图高亮。50 处，身份色不动 */
  --brand-text:#0e7c63;    /* 白底上的 teal 文字/链接。5.14:1 ✅ 该值已在库中(.vkind.k-model) */
  --brand-solid:#0b7a5f;   /* 承载白字的实心按钮底。白字 5.30:1 ✅ 见 DESIGN_NOTES「待拍板」 */
  --brand-hover:#0c9472;   /* 现状 3 处；另有 #0c9670 / #0b8a6b 两个同义值 */
  --brand-active:#0b8a6b;  /* = collect.html 的 --teal-dark */
  --brand-fg:#ffffff;

  /* teal 透明色：现状 16 种 alpha（.05/.06/.07/.08/.09/.1/.10/.12/.13/.14/
     .16/.18/.22/.28/.35/.45）共 30 处 —— 收敛成 4 档 */
  --brand-tint:rgba(14,168,130,.06);        /* 卡底、选中行底 */
  --brand-tint-md:rgba(14,168,130,.12);     /* 药丸/徽章底、active 态 */
  --brand-tint-strong:rgba(14,168,130,.18); /* hover 加深 */
  --brand-line:rgba(14,168,130,.35);        /* 描边 */

  /* ── AI 界面子调色板 ─────────────────────────────────────────────────
     Ask Feasify（chat 弹层、hero 上的 askbtn）刻意与主界面拉开：青—靛的
     "科技感"渐变与环形描边。这是**有意的次级身份**，不是随手写的，故命名保留；
     但只允许出现在 AI 相关界面，别外溢到地块/法规/报告。                    */
  --ai-cyan:#22d3ee;
  --ai-sky:#7dd3fc;
  --ai-indigo:#6366f1;
  --ai-ring:conic-gradient(from var(--ai-rot,0deg),var(--ai-cyan),var(--ai-indigo),var(--brand),var(--ai-cyan));

  /* ── 语义前景 ─────────────────────────────────────────────────────────
     现状 --value / --foreground 同值不同名；--label / --muted / --muted-fg
     三名同指 #6B7280；--muted-foreground **从未声明**却被用了 10 次（真 bug）  */
  --fg:var(--ink);           /* 17.76:1 on 白 */
  --fg-muted:var(--n-500);   /*  4.76:1 on 白 ✅ 次要文字唯一合法值 */
  --fg-faint:var(--n-300);   /*  2.54:1 —— 🔴 仅限图标/分隔符/装饰，禁用于文字 */
  --fg-on-brand:#ffffff;

  /* ── 语义背景 ─────────────────────────────────────────────────────── */
  --bg:#eef1f5;              /* 地图底 --mapbg / --background */
  --bg-surface:var(--n-0);   /* 卡片、弹层实底 */
  --bg-sunken:var(--n-25);   /* 内嵌块、只读区、代码/说明块 */
  --bg-muted:#eceff3;        /* 现状 --muted-bg */

  /* ── 描边 ─────────────────────────────────────────────────────────────
     现状 --border / --divider / --innerline / --btnline 四个名字 + 硬编码
     #f1f1f1 / #f1f5f4；宽度 1px(94) / 0.5px(15) / 1.5px(7) / 2px(10)        */
  --border:rgba(206,210,218,.7);   /* 悬浮玻璃面的边，半透明是刻意的 */
  --border-solid:var(--n-100);     /* 实底卡片的边 */
  --divider:var(--n-100);          /* 分区线 */
  --divider-subtle:#eff1f4;        /* 字段行之间的细线（原 --innerline） */
  --border-strong:var(--n-200);    /* 输入框/次级按钮 */
  --focus-ring:0 0 0 3px rgba(14,168,130,.25);

  /* ── 状态色（每档 fg / bg / line 三件套，成对使用才保对比度）────────────
     现状：危险红 6 个值、成功绿 6 个、警示琥珀 7 个                          */
  --ok:#059669;      --ok-fg:#0b7a5f;   --ok-bg:#ecfdf5;  --ok-line:#a7f3d0;
  --warn:#d97706;    --warn-fg:#92400e; --warn-bg:#fef3c7; --warn-line:#fcd34d; /* 6.37:1 ✅ */
  --danger:#dc2626;  --danger-fg:#b91c1c; --danger-bg:#fef2f2; --danger-line:#fecaca; /* 5.91:1 ✅ */
  --info:#2563eb;    --info-fg:#1d4ed8; --info-bg:#eef2ff; --info-line:#c7d2fe;
  --neutral-fg:#475569; --neutral-bg:#e8edf3; --neutral-line:#c3cdd9;          /* 6.44:1 ✅ */

  /* ── 字阶 ─────────────────────────────────────────────────────────────
     现状 25 级 / 372 处，含 9.5 / 10.5 / 11.5 / 12.5 / 13.5 五个半像素级
     （共 76 处）—— 半像素在非整数 DPR 下取整不稳，且每个都紧贴一个整数级。
     收敛成 9 级：                                                            */
  --fs-3xs:10px;   /* 图例、管线标注、大写微标签 */
  --fs-2xs:11px;   /* 元信息、脚注、徽章 */
  --fs-xs:12px;    /* 次要正文、药丸、弹窗行（现状最高频 65 处） */
  --fs-sm:13px;    /* 正文默认（54 处） */
  --fs-md:14px;    /* 输入框、加强正文 */
  --fs-lg:16px;    /* 小标题、弹层标题 */
  --fs-xl:18px;    /* 区块标题、关键数字 */
  --fs-2xl:20px;   /* 地址主标题 */
  --fs-3xl:32px;   /* hero 数字（租金估算） */

  /* 营销 / 出版级字阶（DS-3 补）。产品 UI 最大只到 32px，但落地页 h1 是 60px、
     报告封面地址是 40pt —— 这两处此前完全在 token 体系之外，各写各的。         */
  --fs-d3:32px;    /* 报告内页大标题（现状 report_feasify 28pt） */
  --fs-d2:44px;    /* 落地页次级宣言 / 报告封面副标 */
  --fs-d1:60px;    /* 落地页 h1（现状 landing md:text-6xl） */

  --fw-regular:400; --fw-medium:500; --fw-semibold:600; --fw-bold:700;

  --lh-none:1;      /* 图标、单行数字 */
  --lh-tight:1.3;   /* 标题 */
  --lh-snug:1.45;   /* 紧凑正文（字段值、弹窗） */
  --lh-normal:1.6;  /* 说明段落 */

  --ls-tight:-.2px; /* 大标题 */
  --ls-wide:.4px;   /* 大写微标签 */
  --ls-display:-1.2px; /* ≥44px 的大字必须再收紧，否则字间显松（DS-3 补） */
  --ls-caps:.18em;     /* 落地页 eyebrow 式全大写微标（现状 landing tracking-[0.2em]） */

  /* 品牌展示字体：落地页自托管的可变字重 Space Grotesk（标题）/ Instrument Sans（正文）。
     产品 UI 仍用 --font-sans（系统字，零加载成本）。⚠️ 两者是**两套字**，见 DESIGN_NOTES。 */
  --font-display:"Space Grotesk",var(--font-sans);
  --font-body:"Instrument Sans",var(--font-sans);

  --font-sans:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"PingFang SC","Microsoft YaHei",Helvetica,Arial,sans-serif;
  --font-mono:ui-monospace,SFMono-Regular,Menlo,monospace;
  --font-num:tabular-nums;   /* 配合 font-variant-numeric，所有数字列必须用 */

  /* ── 间距 ─────────────────────────────────────────────────────────────
     现状 gap 18 种 / 152 处。刻度按**实测频次**定，不是照搬 4px 纯栅格：
     6px(22) 与 10px(22) 是图标—文字之间的真实高频档，硬塞进 4/8/12 会让
     所有带图标的按钮观感变化；而 5(18)/7(12)/9(9) 是同一意图的随手值，收敛掉。 */
  --sp-0_5:2px; --sp-1:4px; --sp-1_5:6px; --sp-2:8px; --sp-2_5:10px;
  --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:24px; --sp-8:32px; --sp-10:40px;

  /* ── 圆角 ─────────────────────────────────────────────────────────────
     现状 32 种 / 204 处。原 token 只有 18/12/9，而**最高频的 8px(24 处)**
     和 6px(16 处) 根本没有 token，只能硬编码 —— 这就是圆角散开的直接原因。
     8px 与 9px(20 处) 差 1px，肉眼不可分，合并到 8px。                      */
  --r-2xs:4px;    /* 勾选、进度条、mark 高亮 */
  --r-xs:6px;     /* 小徽章、法规 badge、图例色块 */
  --r-sm:8px;     /* 按钮、输入框（吸收原 9px） */
  --r-md:12px;    /* 卡片、内嵌块、消息气泡（吸收 10/11px） */
  --r-lg:18px;    /* 悬浮玻璃面板 —— 品牌签名圆角（吸收 14/16/20px） */
  --r-full:999px; /* 药丸 */
  --r-circle:50%; /* 圆点、圆形图标底（10 处，刻意保留） */

  /* ── 阴影 ─────────────────────────────────────────────────────────────
     现状 --float-shadow 用了 28 处（好），另有 37 个一次性阴影             */
  --shadow-xs:0 1px 3px rgba(20,24,33,.12);
  --shadow-sm:0 2px 10px rgba(20,24,33,.10);
  --shadow-float:0 8px 30px rgba(20,24,33,.12),0 2px 8px rgba(20,24,33,.05); /* 悬浮控件 */
  --shadow-modal:0 18px 55px rgba(15,23,42,.22);                             /* 居中弹层 */
  --shadow-glow-brand:0 4px 14px rgba(14,168,130,.35);

  /* ── 毛玻璃 ───────────────────────────────────────────────────────────
     现状 11 种 blur（3/4/6/8/10/12/14/16/20/22px）。16px 是事实标准(26 处) */
  --blur-glass:blur(16px);      /* 全部悬浮控件：工具条/搜索/药丸/底图条 */
  --blur-glass-lg:blur(22px);   /* 大面积：详情面板、法规抽屉、手机抽屉 */
  --blur-scrim:blur(6px);       /* 弹层遮罩 */
  --scrim:rgba(20,24,33,.45);

  /* 玻璃面板底色：白底 92% 是事实标准（--panel-bg） */
  --glass-bg:rgba(255,255,255,.92);
  --glass-border:var(--border);

  /* ── 动效 ─────────────────────────────────────────────────────────────
     现状 20 种 transition。.15s 是事实标准；.34s 那条 morph 曲线用了 3 处   */
  --dur-fast:150ms;   /* 颜色/背景/边框态变化 */
  --dur-base:200ms;   /* 淡入淡出、位移 */
  --dur-slow:340ms;   /* 面板 morph、抽屉滑动 */
  --ease-out:cubic-bezier(.2,.85,.3,1);   /* morph 专用，勿换 */
  --ease-standard:cubic-bezier(.4,0,.2,1);

  /* ── 层级 ─────────────────────────────────────────────────────────────
     现状 26 个散值（-1 → 5200），无阶梯。下面按**现网实际**归档，不重排。   */
  --z-map:0;
  --z-chrome:600;      /* controlbar / basemaps / ctrbar / mapctrl */
  --z-panel:650;       /* 详情面板 */
  --z-topbar:700;      /* 顶栏 / 工具条 / 语言药丸 */
  --z-auth:720;        /* 登录药丸（须压过 panel） */
  --z-sheet:1200;      /* 手机底部抽屉，须压过 Leaflet 控件层(1000) */
  --z-popover:1400;    /* 数据鲜度浮层 / chat 容器 */
  --z-drawer:2000;     /* 法规抽屉 */
  --z-drawer-tab:2001; /* 法规页签 */
  --z-modal:3000;      /* 居中弹层 */
  --z-modal-top:3010;  /* 付费墙（须压过报告弹层） */
  --z-toast:3600;      /* 🔴 现状 #toast=3000 与 .tmodal 同层，弹层开着时吐司被吃掉 */
  --z-fs:3500;         /* 演示模式退出键 */

  /* ── 触控 ─────────────────────────────────────────────────────────── */
  --hit-min:44px;      /* 手机/平板上任何可点元素的最小命中区 */

  /* ========================================================================
     兼容别名 —— 让 tokens.css 能被 index.html 直接 <link> 进去而不改一行旧码。
     接线时先挂这块，旧变量名全部继续有效；再逐个把旧名替换成上面的语义名。
     ⚠️ --muted-foreground 在 index.html 里被用了 10 次却从未声明（真 bug），
        这里补上即修复；--teal-dark 同理（只在 collect.html 声明过）。
     ====================================================================== */
  --teal:var(--brand);
  --teal-dark:var(--brand-active);
  --accent:var(--brand);
  --mapbg:var(--bg);
  --background:var(--bg);
  --foreground:var(--fg);
  --value:var(--fg);
  --card:var(--bg-surface);
  --label:var(--fg-muted);
  --muted:var(--fg-muted);
  --muted-fg:var(--fg-muted);
  --muted-foreground:var(--fg-muted);   /* ← 补声明，修 10 处失效 */
  --muted-bg:var(--bg-muted);
  --innerline:var(--divider-subtle);
  --btnline:var(--border-strong);
  --up:var(--ok);
  --down:var(--danger);
  --yellow:#FFD600;
  --red:#FF5A5F;
  --radius:var(--r-lg);
  --radius-sm:var(--r-md);
  --radius-xs:var(--r-sm);
  --panel-bg:var(--glass-bg);
  --float-shadow:var(--shadow-float);
}

/* ==========================================================================
   深色主题
   取值不是新拟的：#chatmodal 早就有一套完整的深色面（#0a1120/#0d1524/#1b2740
   + #e2e8f0/#94a3b8/#64748b 文字），这里只是把它从一个弹层提升为全局主题。
   ========================================================================== */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){ color-scheme:dark; }
}
[data-theme="dark"]{ color-scheme:dark; }

@media (prefers-color-scheme:dark){ :root:not([data-theme="light"]){
  --bg:#070c14;
  --bg-surface:var(--d-base);
  --bg-sunken:var(--d-sunken);
  --bg-muted:var(--d-raised);
  --fg:#e2e8f0;                    /* 14.81:1 on #0d1524 */
  --fg-muted:#94a3b8;              /*  7.12:1 ✅ */
  --fg-faint:#64748b;              /*  3.84:1 —— 同样只作装饰，不作文字 */
  --brand-text:#34d399;            /*  9.50:1 on 深底（白底那档 #0e7c63 在深色上会糊） */
  --brand-solid:var(--brand);      /* 深底上 #0EA882 承白字 6.04:1 已达标，无须压暗 */
  --border:rgba(148,163,184,.25);
  --border-solid:rgba(148,163,184,.18);
  --border-strong:rgba(148,163,184,.5);
  --divider:rgba(148,163,184,.18);
  --divider-subtle:rgba(148,163,184,.12);
  --glass-bg:rgba(13,21,36,.82);
  --scrim:rgba(6,10,20,.62);
  --ok-fg:#34d399;   --ok-bg:rgba(52,211,153,.12);   --ok-line:rgba(52,211,153,.3);
  --warn-fg:#fbbf24; --warn-bg:rgba(217,119,6,.16);  --warn-line:rgba(251,191,36,.32);
  --danger-fg:#f87171; --danger-bg:rgba(220,38,38,.14); --danger-line:rgba(248,113,113,.32);
  --info-fg:#93c5fd; --info-bg:rgba(37,99,235,.16);  --info-line:rgba(147,197,253,.3);
  --neutral-fg:#94a3b8; --neutral-bg:rgba(148,163,184,.14); --neutral-line:rgba(148,163,184,.28);
  --shadow-xs:0 1px 3px rgba(0,0,0,.4);
  --shadow-sm:0 2px 10px rgba(0,0,0,.45);
  --shadow-float:0 8px 30px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3);
  --shadow-modal:0 18px 60px rgba(0,0,0,.55);
  --focus-ring:0 0 0 3px rgba(14,168,130,.4);
}}

[data-theme="dark"]{
  --bg:#070c14;
  --bg-surface:var(--d-base);
  --bg-sunken:var(--d-sunken);
  --bg-muted:var(--d-raised);
  --fg:#e2e8f0;
  --fg-muted:#94a3b8;
  --fg-faint:#64748b;
  --brand-text:#34d399;
  --brand-solid:var(--brand);
  --border:rgba(148,163,184,.25);
  --border-solid:rgba(148,163,184,.18);
  --border-strong:rgba(148,163,184,.5);
  --divider:rgba(148,163,184,.18);
  --divider-subtle:rgba(148,163,184,.12);
  --glass-bg:rgba(13,21,36,.82);
  --scrim:rgba(6,10,20,.62);
  --ok-fg:#34d399;   --ok-bg:rgba(52,211,153,.12);   --ok-line:rgba(52,211,153,.3);
  --warn-fg:#fbbf24; --warn-bg:rgba(217,119,6,.16);  --warn-line:rgba(251,191,36,.32);
  --danger-fg:#f87171; --danger-bg:rgba(220,38,38,.14); --danger-line:rgba(248,113,113,.32);
  --info-fg:#93c5fd; --info-bg:rgba(37,99,235,.16);  --info-line:rgba(147,197,253,.3);
  --neutral-fg:#94a3b8; --neutral-bg:rgba(148,163,184,.14); --neutral-line:rgba(148,163,184,.28);
  --shadow-xs:0 1px 3px rgba(0,0,0,.4);
  --shadow-sm:0 2px 10px rgba(0,0,0,.45);
  --shadow-float:0 8px 30px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3);
  --shadow-modal:0 18px 60px rgba(0,0,0,.55);
  --focus-ring:0 0 0 3px rgba(14,168,130,.4);
}

/* 降低动效偏好：所有 token 时长归零，组件不必各自再写一遍 */
@media (prefers-reduced-motion:reduce){
  :root{ --dur-fast:0ms; --dur-base:0ms; --dur-slow:0ms; }
}
