/* ============================================================
 * new-api 站点背景与玻璃表面
 * ------------------------------------------------------------
 * 首页 /            → bg-home.<hash>.webp（单张）
 * 登录页 /sign-in   → bg-login.<hash>.webp（单张）
 * 其余页面          → PC/移动 × 日/夜 四选一（只有命中的那张会被下载）
 *
 * 文件名里的 8 位哈希是图片内容的 sha256 前 8 位：图变了名字就变，
 * 侧车对 /static/ 的 immutable 缓存自动失效，**不需要手工改版本号**。
 * 换图流程见 webp-bg.js（生成 webp + 同步改写本文件与 site-bg.js 里的 URL）。
 *
 * 设计原则：让「表面」自己半透明，而不是给整页盖遮罩。
 *   页面底 / 主内容区 = 全透明  → 空白区完整透出背景图
 *   卡片 / 侧栏       = 半透明  → 背景透得过来，文字仍清楚
 *   浮动层（下拉弹窗）= 更实    → 压在其他内容之上需要更强遮挡
 *
 * 所有数值都是变量，改这里即可，不需要动图形或重新构建。
 * ============================================================ */

/* ---------------- 可调参数 ---------------- */
:root {
  --mc-surface: 66%; /* 卡片/侧栏底色保留度：小=背景更明显，大=文字更清楚 */
  --mc-popover: 94%; /* 下拉/弹窗/粘性表头：必须比卡片实，否则压不住底下的内容 */
  --mc-shell: 0%; /* 控制台外壳底色保留度：0=和公开页一致（完全露出背景），调大可让控制台更"实" */
  --mc-nav-scrim: 85%; /* 顶栏顶部渐变的不透明度 */
  --mc-halo: 0%; /* 裸露文字的光晕浓度。**默认关**——用户反馈白色光晕看起来像"白边"；
                             顶栏已经有渐变底，够读了。想要就调大（如 60%）。 */
  /* 卡片底色来源。纯白（lab 100%）压在照片上太扎眼，掺一点前景色变柔——
   * 数字越大越白，100% = 原来的纯白。 */
  --mc-card-base: color-mix(in oklch, var(--card) 95%, var(--foreground));
  --mc-surface-blur: 0px; /* 想要毛玻璃效果改成 12px——注意 GPU 开销明显增加 */
  --mc-flex: 12px; /* 表面模糊的半径，配合上一项使用 */
}
html.dark {
  --mc-surface: 74%;
  --mc-popover: 92%;
  --mc-nav-scrim: 80%;
  --mc-halo: 0%;
  /* 夜间的 --card 是 oklch(0.285 0 0)，接近纯黑，叠在夜景上就是一团黑。
   * 掺一点白把它抬成"灰"：比例就是灰度旋钮，数字越小越灰。 */
  --mc-card-base: color-mix(in oklch, var(--card) 86%, white);
}

/* ---------------- 1. 背景图 ----------------
 * 所有规则都以 [data-mc-route] 为门禁：属性由 <head> 里的内联脚本立即写入。
 * 这样在属性出现前没有任何规则匹配，浏览器不会误下另一张背景图
 * （defer 脚本会晚约 1 个网络往返，曾导致首页多下 509KB）。 */

body {
  background-color: transparent;
}

/* 画布底色：首屏/换页那几百毫秒里，浏览器画的是这个颜色，而不是纯白。
 * 取的是对应背景图的平均色（avg-color.js 量的），过渡几乎看不出来。
 * 换页时的白屏主要靠 site-bg.js 的「旧图垫在新图下面」解决，这里是兜底。 */
html[data-mc-route] {
  background-color: #373f25;
}
html[data-mc-route='/'],
html[data-mc-route='/sign-in'] {
  background-color: #68422c;
}
html.dark[data-mc-route] {
  background-color: #141a14;
}
html.dark[data-mc-route='/'],
html.dark[data-mc-route='/sign-in'] {
  background-color: #68422c;
}

html[data-mc-route]:not([data-mc-route='/']):not([data-mc-route='/sign-in'])
  body {
  background-image: url('/static/bg/bg-site-desktop-light.31c137a4.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
}

/* 竖屏一律用竖版素材。
 * 只按宽度断点的话，820×1180 这类**竖屏平板**会落到 PC 素材：16:9 的横版图
 * 在 0.69 的竖屏上 cover 后只剩约 39% 宽度可见，主体经常被裁掉。
 * 条件 = 项目自己的手机断点 768（hooks/use-mobile.ts） ∪ 1024 以内的竖屏。 */
@media (max-width: 767px), (orientation: portrait) and (max-width: 1024px) {
  html[data-mc-route]:not([data-mc-route='/']):not([data-mc-route='/sign-in'])
    body {
    background-image: url('/static/bg/bg-site-mobile-light.5d46ef55.webp');
    background-attachment: scroll;
  }
}

html.dark[data-mc-route]:not([data-mc-route='/']):not(
    [data-mc-route='/sign-in']
  )
  body {
  background-image: url('/static/bg/bg-site-desktop-dark.6724e475.webp');
}
@media (max-width: 767px), (orientation: portrait) and (max-width: 1024px) {
  html.dark[data-mc-route]:not([data-mc-route='/']):not(
      [data-mc-route='/sign-in']
    )
    body {
    background-image: url('/static/bg/bg-site-mobile-dark.dd1571b1.webp');
  }
}

/* 首页：PC 一张，手机/竖屏一张（用户指定）
 * 登录页：单张，不分设备与主题 */
html[data-mc-route='/'] body {
  background-image: url('/static/bg/bg-home.6084e7c8.webp');
}
@media (max-width: 767px), (orientation: portrait) and (max-width: 1024px) {
  html[data-mc-route='/'] body {
    background-image: url('/static/bg/bg-home-mobile.e52d0f72.webp');
  }
}
html[data-mc-route='/sign-in'] body {
  background-image: url('/static/bg/bg-login.6084e7c8.webp');
}

html[data-mc-route='/'] body,
html[data-mc-route='/sign-in'] body {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
}
@media (max-width: 767px), (orientation: portrait) and (max-width: 1024px) {
  html[data-mc-route='/'] body,
  html[data-mc-route='/sign-in'] body {
    background-attachment: scroll;
  }
}

/* iOS / iPadOS 对 background-attachment: fixed 支持很差（错位、覆盖不全、
 * 滚动时整块重绘）。横屏平板正好落在上面两条竖屏规则之外，这里兜底退回 scroll。
 * 放在最后 + 同样式选择器，靠顺序赢过上面的 fixed。 */
@supports (-webkit-touch-callout: none) {
  html[data-mc-route]:not([data-mc-route='/']):not([data-mc-route='/sign-in'])
    body,
  html.dark[data-mc-route]:not([data-mc-route='/']):not(
      [data-mc-route='/sign-in']
    )
    body,
  html[data-mc-route='/'] body,
  html[data-mc-route='/sign-in'] body {
    background-attachment: scroll;
  }
}

/* ---------------- 2. 表面半透明 ----------------
 * 用 :where() 把优先级压到 0，方便你在主题/组件层面随时覆盖某一块。 */

/* 页面底与主内容区：全透明，空白区完整露出背景 */
:where(#root .bg-background) {
  background-color: transparent;
}

/* 卡片：半透明（主力表面，价格页上 22 个元素） */
:where(.bg-card) {
  background-color: color-mix(
    in oklch,
    var(--mc-card-base) var(--mc-surface),
    transparent
  );
}

/* 侧边栏 */
:where(.bg-sidebar) {
  background-color: color-mix(
    in oklch,
    var(--sidebar) var(--mc-surface),
    transparent
  );
}

/* 下拉 / 弹窗：压在其他内容之上，遮挡更强 */
:where(.bg-popover) {
  background-color: color-mix(
    in oklch,
    var(--popover) var(--mc-popover),
    transparent
  );
}

/* 控制台外壳（登录后所有页面）——**只有登录后才存在的一层**。
 * 它的类是 `has-data-[variant=inset]:bg-sidebar`（shadcn 的 sidebar-wrapper），
 * 普通的 .bg-sidebar 选择器匹配不到它；而布局 variant 默认就是 inset，
 * 于是它带着 --sidebar 的实心底色铺满整屏，把背景图整块盖住。
 * 处理成透明后，登录前后观感才一致；想给控制台留一层底就调 --mc-shell。 */
:where(.group\/sidebar-wrapper, [data-slot='sidebar-wrapper']) {
  background-color: color-mix(
    in oklch,
    var(--sidebar) var(--mc-shell),
    transparent
  );
}

/* 数据表：行卡片走 --data-table-card-bg（渠道页一次 19 个），普通 .bg-card 匹配不到 */
[class*='bg-(--data-table-card-bg'] {
  background-color: color-mix(
    in oklch,
    var(--data-table-card-bg, var(--table-row)) var(--mc-surface),
    transparent
  );
}

/* 数据表：整块给一个和卡片同浓度的底。
 * API 密钥、三个日志这些页面的表格原来是「有边框、没底色」——
 * 密排数据直接压在照片上，很难读；概览页的卡片是有玻璃底的，这里补齐成一致。
 * 表格外框是 overflow-hidden + rounded-lg，会自动把这个底裁成圆角。
 * 已经在 bg-card 里的表格不重复上底（两层叠起来会变实）。 */
:where(table:not(.bg-card *)) {
  background-color: color-mix(
    in oklch,
    var(--table-row, var(--background)) var(--mc-surface),
    transparent
  );
}

/* 统计条：钱包页的「当前余额 / 剩余配额 / 总用量」三格、数据看板的用量概览统计条。
 * 它们的写法是「有分隔线（divide-x）、有边框、但没底色」——原本假设页面底不透明。
 * 已经在卡片里的不重复上底（两层叠起来会变实）。 */
:where([class~='divide-x']:not(.bg-card *)) {
  background-color: color-mix(
    in oklch,
    var(--mc-card-base) var(--mc-surface),
    transparent
  );
}

/* 看板里的小统计格（数据看板 summary-cards 的 `bg-background/60 rounded-lg border`）：
 * 它是 60% 的 --background，比卡片更透、底色也不同源，叠在照片上看着"没有底"。
 * 统一成和卡片同一套浓度。 */
:where([class~='bg-background/60']:not(.bg-card *)) {
  background-color: color-mix(
    in oklch,
    var(--mc-card-base) var(--mc-surface),
    transparent
  );
}

/* 「有边框、有圆角、但没底色」的容器 —— app 里这类写法很多（数据看板的图表框、
 * 统计块外框…），它们原本假设页面底是不透明的。
 * 排除两类：已经在卡片里的（会叠实）、里面有 table 的（表格自己已经有底了）。 */
:where(
  div[class~='overflow-hidden'][class~='rounded-lg'][class~='border']:not(
    :has(table)
  ):not(.bg-card *)
) {
  background-color: color-mix(
    in oklch,
    var(--mc-card-base) var(--mc-surface),
    transparent
  );
}

/* 系统设置各栏目的字段容器：写法是 `rounded-lg border`（常带 p-4/p-3），一律没有底色。
 * 这类「有边框、有圆角、没底」的块在 app 里很普遍，统一给卡片同浓度的底。
 * 排除：自带**基础** bg 工具类的（行首或空格后紧跟 bg-，说明它本来就有底，会叠实）、
 *       已经在卡片里的、里面有表格的（表格自己已有底）。
 * 注意别写成 [class*='bg-card']：那样会把 hover:bg- 和 dark:bg- 这些变体也一起排除掉。 */
:where(
  div:is([class~='rounded-lg'], [class~='rounded-md'])[class~='border']:not(
    [class^='bg-']
  ):not([class*=' bg-']):not(:has(table)):not(.bg-card *)
) {
  background-color: color-mix(
    in oklch,
    var(--mc-card-base) var(--mc-surface),
    transparent
  );
}

/* 系统设置 / 游乐场：这两处的 <main> 是透明的，页面里又没有卡片 ——
 * 整页表单、聊天区和空状态直接压在照片上。
 * 给它们的 <main> 铺一层和卡片同浓度的玻璃底。用路由属性限定范围，
 * 别的页面不能加（别处靠卡片分块，再叠一层会把卡片间隙里的背景糊住）。 */
html[data-mc-route^='/system-settings'] main,
html[data-mc-route^='/playground'] main {
  background-color: color-mix(
    in oklch,
    var(--mc-card-base) var(--mc-surface),
    transparent
  );
}

/* 粘性表头/固定列要压住从下面滚过去的行，按浮动层的浓度处理。
 * 必须限定在 thead/th 上：有些滚动容器会用 `**:data-[slot=table-header]:bg-(...)`
 * 这种「后代变体」类名提到同一个 token，按 class 子串匹配会把整个容器一起涂掉。 */
thead[class*='var(--table-header'],
th[class*='var(--table-header'] {
  /* 带回退：万一某个主题没定义 --table-header，color-mix 会因值非法而整条失效，
   * background-color 退化成 transparent——粘性列就会漏出底下滚过去的行。 */
  background-color: color-mix(
    in oklch,
    var(--table-header, var(--background)) var(--mc-popover),
    transparent
  );
}

/* 毛玻璃（默认关闭）：卡片有 78% 遮罩后背景已经很淡，模糊带来的提升有限，
 * 而几十个卡片同时做背景模糊的 GPU 开销不小。想要就解开下面这段。 */
/*
:where(.bg-card, .bg-sidebar, .bg-popover) { backdrop-filter: blur(var(--mc-surface-blur)); }
*/

/* ---------------- 货币字符 ◆ → 绿宝石（彩色字体） ----------------
 * new-api 没有"货币图标"设置项，只有文本符号；于是把这个符号本身做成一个
 * **只覆盖 U+25C6** 的彩色字体（COLRv0 矢量色块，见 build-currency-font.py），
 * 让字体去渲染它：
 *   · 零 DOM 改动 —— 不会再出现"动了 React 记账节点 → removeChild 抛错 → 整页 500"
 *     （日志页翻页/搜索必崩的根因），这类事故从根上消失；
 *   · 零运行时 JS / 观察者开销；canvas 图表里也生效；复制导出仍得到 ◆ 字符。
 * 做法：把 'MC Currency' **追加**到应用字体栈最前面。它只覆盖那一个码位，
 * 其余字符照旧走应用自己的 var(--font-body)/var(--font-mono)，用户换字体也不受影响。
 * 不支持的浏览器（很老的）会回退成系统字体的 ◆，属于优雅降级。 */
@font-face {
  font-family: 'MC Currency';
  src: url('/static/currency/mc-currency.48fee1a1.woff2') format('woff2');
  unicode-range: U+25C6;
  font-display: swap;
}
html body,
html .font-sans {
  font-family: 'MC Currency', var(--font-body, var(--font-sans, sans-serif));
}
html .font-serif {
  font-family: 'MC Currency', var(--font-serif, serif);
}
html .font-mono,
html .tabular-nums,
html code,
html pre,
html kbd,
html samp {
  font-family:
    'MC Currency',
    var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
}

/* ---------------- 3. 裸露文字保护 ----------------
 * 全站只有顶栏是"文字直接压在照片上、底下没有任何表面"。
 * 注意 text-shadow 会**继承给整棵子树**：用裸 `header` 或整页选择器，
 * 会让 hero 标题、卡片里的深色小字、控制台粘性头全都镶一圈白边
 * （就是"某些情况下文字出现白边"）。所以只认那条固定的顶栏。 */

:where(header.fixed.top-0) {
  text-shadow: 0 1px 3px
    color-mix(in oklch, var(--background) var(--mc-halo), transparent);
}

/* 顶栏渐变：公开站的固定顶栏 + 控制台的粘性顶栏（它原来是 bg-background，
 * 被我们置透明后文字同样压在照片上，需要同样的底）。 */
header.fixed.top-0,
header.sticky.top-0 {
  background-image: linear-gradient(
    to bottom,
    color-mix(in oklch, var(--background) var(--mc-nav-scrim), transparent),
    transparent
  );
}
