/* ═══════════════════════════════════════════════════════════════════════════════
   sx-bg.css —— 产品版背景（BG-2a 起）。

   ⚠️ 自 BG-2f（2026-10-12）起，time 模式是**静态「全平」背景**：随时间变化的三层
      （.qctr / .qfog / .qglow）已停止绘制，见本文件**第 9 节**。
      下面第 1 节「时间量」与第 4 节「背景六层」保留的是那三层**当初怎么写的**，
      用来支持回退；不再描述当前屏上的效果。

   来源：BG-1 / BG-1b / BG-1d 的 demo（public/css/theme-quiet.css 第 1、3 节）。
   demo 那个文件里还混着时间滑块 / 调参面板 / 对比键 / HUD 的样式 —— 那些**全部没有搬过来**
   （用户 BG-2 第 4 条：demo 专用的东西不要带进产品）。所以这里只有背景本身。

   只被「此刻 / 那时 / 新建 / 单条记录 / 登录」五页引用，且只在 SX_BG_STYLE=time 时由
   server.js 的 sendPage() 注入 <link>。SX_BG_STYLE=old 时这张表一个字节都不会下发。
   世界页（world.html）按约定保持旧背景，不引用本文件。

   与 demo 的三处刻意不同：
   · 圆弧（.qarc / --arc-o / --ink-4）**整层删除** —— 用户第 2 条选定「圆弧：关
     （不渲染圆弧元素，也不加载与它相关的样式）」，所以连变量都不留。
   · 强度取「明显」档（demo 的三档预设之一，用户第 1 条填的那一档）：
     光晕 .12/.30 · 中心微亮 .08 · 暗角 .35 · 地面雾 .09 · 噪点 .03。
   · 没有 body 上的 q-arc / q-cmp / q-title-current 这些状态类 —— 它们都是 demo 控件用的。

   本文件的颜色规矩（沿用 demo 的 B1）：
   1. 除下面的变量表以外，文件里没有任何颜色字面量。
      连噪点那条 SVG data URI 也是纯数学（feTurbulence + 三通道斜率染色），不含颜色值。
   2. 不得出现 #fff / rgb(255,255,255)；不得出现紫色；不得出现三通道相等的纯灰。
   ═══════════════════════════════════════════════════════════════════════════════ */


/* ═══ 1. 变量表 ═══════════════════════════════════════════════════════════════ */
:root {
  --bg-base: #05070c;                    /* 近黑偏冷：整页的底，不随时间动 */
  --glow-c: 215 30% 60%;                 /* 光晕色 hsl(215 30% 60%)。
                                            只存分量、不带 hsl() 外壳：渐变要逐档给 alpha，
                                            外壳留在 .qglow 里写 hsl(var(--glow-c) / .55)。
                                            这样全表以外一个颜色字面量都不剩（可 grep 验证）。 */
  --ctr-c: 220 25% 50%;                  /* 中心微亮色。S=25% ≠ 0 ⇒ 不是灰（饱和度低的冷蓝灰） */
  --fog-c: 215 35% 55%;                  /* 地面雾色 */
  --vig-c: 4 6 12;                       /* 暗角色。⚠️ 刻意**不用**纯黑 rgba(0,0,0)：
                                            R≠G≠B 才过「不得出现三通道相等的纯灰」自检。
                                            视觉上与纯黑几乎无差别（暗角本来就是往黑里压）。 */

  /* ── 时间量：sx-bg.js 唯一的输出 ──
     三个「刻度」单独写成数值（不带 calc），这样 JS 能读回来复算亮度 ——
     自定义属性读回来的是 token 文本，calc() 那一层不会被求值。
     ⚠️ 所以 --glow-a 这个 calc() 是**给 CSS 用的**，JS 若要复算必须去读它背后的裸数值
        （--glow-a-min / -max）。 */
  --t-l: 0;
  --glow-a-min: .12;                     /* L=0 时的光晕不透明度（「明显」档） */
  --glow-a-max: .30;                     /* L=1 时的光晕不透明度 */
  --glow-hue-max: -8;                    /* L=1 时的色相偏移（度）；负号 = 215° 往 207° 走（蓝往青，不是紫） */
  --glow-a: calc(var(--glow-a-min) + var(--t-l) * (var(--glow-a-max) - var(--glow-a-min)));
  --glow-hue: calc(var(--t-l) * var(--glow-hue-max) * 1deg);
  --glow-r: 70vw;                        /* 光晕半径 = 70% 页面宽度 */

  /* ── 空间感三层的强度旋钮（几何都写在各自的规则里）── */
  --ctr-o: .08;                          /* 中心微亮 */
  --vig-o: .35;                          /* 暗角（原规范把强度写在颜色里；提到这里滑块才能线性映射） */
  --fog-o: .09;                          /* 地面雾 */

  /* ── 噪点：内联 SVG，防色带 ──
     做法刻意不含任何颜色值：feTurbulence 出噪声 → saturate 0 去色 →
     再用 feFuncR/G/B 三通道不同的斜率（.62/.70/.86）把它染成偏冷的灰蓝，
     feFuncA 把纹理自身的 alpha 压到 ≤ --noise-a。
     ⚠️ 两个口径别混：
        --noise-e = **实际颗粒强度**（0~.06，本档 .03）
        --noise-o = **图层不透明度** = e / a（.qnoise 用的口径）
        本档 e=.03 / a=.12 ⇒ o=.25。
        它的作用是把 8bit 量化条带打断（BG-1b 实测：同一行内「完全相同 luma」的
        最长连续段从 102px 降到 9px）。 */
  --noise-e: .03;
  --noise-a: .12;
  --noise-o: calc(var(--noise-e) / var(--noise-a));
  --noise: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='160'%20height='160'%3E%3Cfilter%20id='n'%3E%3CfeTurbulence%20type='fractalNoise'%20baseFrequency='.9'%20numOctaves='2'%20stitchTiles='stitch'/%3E%3CfeColorMatrix%20type='saturate'%20values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncR%20type='linear'%20slope='.62'%20intercept='.40'/%3E%3CfeFuncG%20type='linear'%20slope='.70'%20intercept='.43'/%3E%3CfeFuncB%20type='linear'%20slope='.86'%20intercept='.47'/%3E%3CfeFuncA%20type='linear'%20slope='.12'%20intercept='0'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect%20width='160'%20height='160'%20filter='url(%23n)'/%3E%3C/svg%3E");

  /* ── 时间过渡 ──
     时间变化只走这一个过渡（3 秒），不做持续动画。 */
  --ease-q: cubic-bezier(.32, .72, 0, 1);
  --t-q: 3s;
}


/* ═══ 2. 底色 ═════════════════════════════════════════════════════════════════
   ⚠️ html 也要写：report.html / login.html 的 <head> 里各有一段内联
   `<style>html,body{background:#02050E;margin:0;padding:0}</style>`（那是产品原来的底色），
   而 #02050E ≠ --bg-base #05070c。那段内联样式在文档里比 style.css 更靠前，
   但本文件是最后注入的，同特异性下后者胜 ⇒ 两处都能压掉。
   不写这一条，html 那一层会露出另一种蓝黑（在 overscroll / 地址栏回弹时能看见）。 */
html { background: var(--bg-base); }
body { background: var(--bg-base); }


/* ═══ 3. 把产品的旧背景四层关掉 ═══════════════════════════════════════════════
   .bg-scene   —— 摄影底图（scene-N.jpg，单页最大 175KB，另有 120s 的 bgBreath 呼吸）
   .bg-canvas  —— atmosphere.js 把那张照片用 WebGL 重画一遍（不透明，会盖住 .bg-scene）
   .bg-beam    —— 一束补光
   .bg-rising  —— ambient.js 的浮尘
   time 模式下这四层全部换成上面的纯 CSS 六层。
   ⚠️ 只 display:none 不够：atmosphere.js / ambient.js 由 server.js 在 time 模式下**从 HTML 里
   摘掉**。因为 atmosphere.js 是「读 .bg-scene 的 computed background-image → 取 URL → 画进
   canvas」，只隐藏元素它照样会把照片拉下来并空跑一个渲染循环（display:none 的元素，
   浏览器不会加载它的背景图 —— 这也是 time 模式首屏不再下载那 175KB 的原因）。
   加 !important 是因为 style.css 里这些类带 z-index/opacity，只靠层叠顺序不够稳。 */
.bg-scene,
.bg-canvas,
.bg-beam,
.bg-rising { display: none !important; }


/* ═══ 4. 背景六层 ═════════════════════════════════════════════════════════════
   下面的书写顺序 = 合成顺序 = z-index 0→4。层序是两个刻意的决定，不是随手排的：

   · **暗角(.qvig)放在光晕之上**——它要压暗的正是光晕铺到边缘的那部分。
     放下面的话「中间亮、边缘沉」的纵深就不成立，整页又回到一块平光。
   · **噪点(.qnoise)放在暗角之上**——暗角是一条 .35 的低幅长渐变，
     是最容易出色带的一层；防色带的噪点必须在它之后。

   ⚠️ 注意 .shell（内容层）是 z-index:2。所以 .qbase/.qctr/.qfog（0~1）在内容之下，
   而 .qvig(3)/.qnoise(4) 在内容**之上** —— 这是 demo 一直就有的层序，本次照搬不改：
   暗角在版心处 alpha 为 0（只有四角才压暗），噪点是整页一层的胶片颗粒。
   两件事的真实像素影响都在 BG-2a 的验收里量过。
*/

/* ⓪ 底：只有一个常量色，从不随时间动 */
.qbase {
  position: fixed;
  inset: 0;
  z-index: 0;
  background: var(--bg-base);
  pointer-events: none;
}

/* ① 中心微亮：整个画面唯一「有源头的光」。
   圆心贴在内容列附近（45% / 40%），一路铺到画面 75% 才完全消失 ——
   它不是一盏灯，是让内容那一块比四周**稍微**不黑一点。
   剖面用两层 hsl 直接写（中心 1 → 75% 处 0），强度单独交给 --ctr-o。 */
.qctr {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image: radial-gradient(ellipse at 45% 40%,
    hsl(var(--ctr-c) / 1) 0%,
    hsl(var(--ctr-c) / 0) 75%);
  opacity: var(--ctr-o);
}

/* ② 地面雾：底部中间一个很扁的椭圆，像地平线附近浮着的一层薄雾。
   ellipse 45% 35% 的**半径**分别是视口宽 45% / 高 35%，圆心落在下边缘正中
   ⇒ 屏上实际看到的范围约「宽 90% / 高 35%」（椭圆的上一半）。
   剖面收到 100%，所以边缘是柔的，没有硬边。 */
.qfog {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background-image: radial-gradient(ellipse 45% 35% at 50% 100%,
    hsl(var(--fog-c) / 1) 0%,
    hsl(var(--fog-c) / 0) 100%);
  opacity: var(--fog-o);
}

/* ③ 光晕：很大、极柔和，圆心在顶部偏右，半径 70vw。
   不透明度交给 --glow-a（＝min + L×(max−min)）⇒ 过渡只作用在 opacity 上，
   而 opacity 是合成器能吃的属性，3 秒过渡不会引起逐帧重排。
   剖面：1 → .55(35%) → .22(68%) → 0(100%)，越往外掉得越快，
   这样它读起来是「从画外照进来的一点光」，不是画面里的一团亮斑。 */
.qglow {
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image: radial-gradient(circle var(--glow-r) at 72% -8%,
    hsl(var(--glow-c) / 1) 0%,
    hsl(var(--glow-c) / .55) 35%,
    hsl(var(--glow-c) / .22) 68%,
    hsl(var(--glow-c) / 0) 100%);
  opacity: var(--glow-a);
  filter: hue-rotate(var(--glow-hue));
  transition: opacity var(--t-q) var(--ease-q), filter var(--t-q) var(--ease-q);
}

/* ④ 暗角：从画面中心 70% 处起、到最远的那个角为止，逐渐压暗。
   size 用默认的 farthest-corner ⇒ 渐变里的 100% 就在「视口最远的角」上，
   所以 70% 指的是**到最远角的距离的 70%**。四角压得最重，边线中段基本不动。
   剖面写成 rgb(--vig-c / 0) 70% → rgb(--vig-c / 1) 100%，强度交给 --vig-o。 */
.qvig {
  position: fixed;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background-image: radial-gradient(ellipse at 50% 50%,
    rgb(var(--vig-c) / 0) 0%,
    rgb(var(--vig-c) / 0) 70%,
    rgb(var(--vig-c) / 1) 100%);
  opacity: var(--vig-o);
}

/* ⑤ 噪点：160×160 无缝平铺 —— 它的作用只是不让上面那几层渐变的色带露出来。
   ⚠️ 图层不透明度用 --noise-o（= --noise-e / --noise-a），不是 --noise-e。 */
.qnoise {
  position: fixed;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background-image: var(--noise);
  background-repeat: repeat;
  opacity: var(--noise-o);
}


/* ═══ 5. 用户要求减少动态 ═══════════════════════════════════════════════════════
   产品 style.css 里那条全局 `transition-duration: 0.01ms !important` 本来也会命中，
   这里显式写一遍，不依赖它 —— 用户第 3 条明确要「prefers-reduced-motion 时去掉 transition」。
   ⚠️ BG-2f 起 time 模式是静态全平背景：.qglow 已被第 9 节隐藏、sx-bg.js 也不再启动
      60 秒的 --t-l 定时器 ⇒ 下面这条 transition 已无对象可作用。保留它只是因为
      「回退（删掉第 9 节）时这里要照旧」—— 不再描述当前屏上的行为。 */
@media (prefers-reduced-motion: reduce) {
  .qglow {
    transition: none !important;
  }
}


/* ═══ 6. BG-2c-1：手机顶栏不再竖排（本文件只在 time 模式加载） ═══════════════════
   现状：≤860px 产品把 .nav-side 压成一行（style.css:1901-1929），但那一行里没有任何
   东西被禁止换行 —— 390px 下「品牌 + 此刻 + 那时 + 账号名 + 退出」的总宽超过可用宽度，
   flex 默认收缩就把「此刻」「那时」各挤成一字一行。
   这里只做四件事，字号 / 颜色 / 间距 / 顶栏高度与各项位置一个字不改（见下方实测）：
     ① 导航文字不许换行；③ 不许被压缩（收缩只能由账号名承担，而它已被隐藏）；
     ③ 「退出」的点击热区抬到 ≥44×44：内边距撑开、负外边距抵消，占位与改前逐像素相同；
     ④ 账号名窄屏直接隐藏（BG-2c 的决定）。
   ⚠️ 只在 time 生效：本文件由 injectTimeBackground 注入，SX_BG_STYLE=old 时整个文件
      不会被加载 ⇒ old 模式顶栏与改前完全一致（仍是会竖排的旧样子）。
   注：.nav-link / .nav-brand 的热区**高度**产品本来就是 44px（style.css:1922 的注释），
      这里不动；水平宽度仍随文字 —— 要加宽就得改 18px 的间距，不在本次范围。 */
@media (max-width: 860px) {
  .nav-brand,
  .nav-link,
  .nav-user-logout {
    white-space: nowrap;
    flex: 0 0 auto;
  }

  /* 「退出」：12px 字 ≈14.4px 行高 + 15×2 = 44.4px 高；「退出」24.5px + 10×2 = 44.5px 宽。
     负外边距把它在版面上占的位置还原回原来的 14.4 × 24.5 ⇒ 周围间距不变。 */
  .nav-user-logout {
    padding: 15px 10px;
    margin: -15px -10px;
  }

  .nav-user-name { display: none; }
}


/* ═══ 7. BG-2c-2：登录页「进入」按钮改成淡描边胶囊（本文件只在 time 模式加载） ═══
   改前 = style.css:538-557 给的一颗实心近白胶囊（background: var(--ink-0)，
   color:#08090C）+ 1823-1845 叠的悬停/按压阴影。这里**只覆盖 .login-btn 自己** ——
   不碰共享选择器 `.create-submit, .login-btn`，所以创建页那颗保存胶囊不受影响
   （「保存」本来就是淡描边胶囊，本条的诉求就是让「进入」向它靠）。
   old 模式不加载本文件 ⇒ 仍是原来的白色按钮。
   高度守恒：加 1px 真边框会让外形高度 +2px，所以 padding 上下各减 1px（14→13）抵消。
   改前实测 340×49，改后 340×49（见验收）。
   注 1：字号/字重/圆角外的几何全不变；宽度本来就是 100%。
   注 2：聚焦态用 :focus-visible（键盘聚焦）。用 :focus 会让点完鼠标后按钮一直停在亮态，
         看起来像「卡住了」。若要鼠标点击也亮，把下面第二组选择器换成 :focus 即可。
   注 3：style.css:1833 那条 `.login-btn:hover` 的缩放与阴影没动 —— 本次没要求改它。 */
.login-btn {
  background: rgba(170, 190, 220, 0.06);
  border: 1px solid rgba(170, 190, 220, 0.28);
  border-radius: 999px;
  color: var(--ink-1);
  padding: 13px 29px;   /* 14/30 − 1px 边框 ⇒ 外形高度与改前逐像素相同 */
  opacity: 1;           /* 压掉共享规则 `.create-submit:hover, .login-btn:hover { opacity:.84 }` */
}
.login-btn:hover,
.login-btn:focus-visible {
  border-color: rgba(170, 190, 220, 0.45);
  background: rgba(170, 190, 220, 0.11);
  opacity: 1;           /* 同上：悬停时也得压住那条 .84，否则胶囊会变半透明 */
}


/* ═══ 8. BG-2d：把 time 模式下「需要读的」次要文字提到 ≥4.5:1 ═══════════════════
   起因：BG-2c 的对比度表里，凡是坐在近黑底上的次要文字（原本都是 --ink-3 = 30% 墨）
   都在 1.88~2.49 之间。近黑底把「30% 墨」这个绝对量拉得太低 —— 底越暗，
   同一档 alpha 的相对亮度也越低，所以这档在深色底上根本没成立过。

   ── 只做一件事：把这几条选择器的 color 提到一个统一的可读档 ──
   派生色 = color-mix(in srgb, var(--ink-0) 55%, transparent)
          = rgba(245, 245, 247, .55)（在 sRGB 空间与透明混合 ⇒ 就是 --ink-0 的墨色 + 55% 不透明度）
   · 源变量是产品**已有的** --ink-0（#F5F5F7）；没有新增任何变量、没有新的颜色字面量
     （本文件「除变量表外无颜色字面量」这条规矩仍然成立 —— 派生表达式里只有 var 名和 transparent）。
   · 不是纯白（245,245,247，R≠G≠B）、不是纯灰。
   · 不支持 color-mix() 的浏览器：整条声明被丢弃 ⇒ 自动退回 style.css 的现值，
     **不会降级成别的颜色**，也不会改版面（这就是「不支持时保持原样」）。

   ── 为什么是 55% ──
   按各元素**该处最亮的底**反解，达标（4.5:1）所需的最小 alpha 是 0.470~0.505（最紧的是此刻页
   占位提示，底最亮 #222a35）。取 0.55 是留余量：实测口径（像素取字形）比模型口径低 0.3~0.6，
   0.505 那种刚好压线的值在实测里会掉回 4.5 以下。取 0.55 后 7 条全部落在 5.1~5.9，实测 4.7~5.5。
   上限也守住了：悬停态 --ink-1 = 0.62 > 0.55，当前页 .active = --ink-0 = 1.0 ⇒ 三档层级没坏。

   ── 范围（用户 2026-10-12 锁定：7 条选择器 / 6 类元素）──
   未选中导航项 · 账号名 · 退出 · 登录未选中页签 · 登录两个输入框的占位 · 登录底部小字 ·
   以及「此刻」「新建」两页同一个占位提示（同一句文案，一并提到同一档）。
   · 「此刻」页那条必须连 .home-page 一起写：style.css:806 的 .home-page 前缀是 (0,2,1)，
     只写 (0,1,1) 的 .create-textarea::placeholder 压不住它。
   · 不碰 .nav-link.active / .login-tab.is-active / :hover —— 它们特异性更高（0,2,0），
     仍按原样（--ink-0 / --ink-1）压在上面。
   · 只覆盖这几条选择器，**没有动 --ink-0/1/2/3 本身** —— 那会把全站所有用了 ink 档的地方一起改掉。
   ⚠️ 只在 time 生效：本文件由 injectTimeBackground 注入，SX_BG_STYLE=old 时整张表不下发
      ⇒ old 模式这些文字的颜色与改前逐项相同（BG-2d 验收 b：computed style 比对）。 */

.nav-link,
.nav-user-name,
.nav-user-logout,
.login-tab,
.login-input::placeholder,
.create-textarea::placeholder,
.home-page .create-textarea::placeholder {
  color: color-mix(in srgb, var(--ink-0) 55%, transparent);
}

/* 登录页底部告知小字的换行：现在第二行只剩「处理」两个字（文案宽 340px 的卡片，
   12px 字。实测改前 2 行、第 1 行 329.7px、第 2 行只有 24px）。
   text-wrap: balance 把两行摊匀；不改字号/字重/文案，也不做任何硬折行兜底 ——
   浏览器不认这条就照原来的换行走。 */
.login-foot {
  color: color-mix(in srgb, var(--ink-0) 55%, transparent);
  text-wrap: balance;
}


/* ═══ 9. BG-2f：time 模式改成「全平」静态背景（本文件只在 time 模式加载） ═════════
   BG-2f 第 1 步（只读对比）量出来的结论：上面六层里**只有三层**是色带的来源 ——
   中心微亮(.qctr) / 地面雾(.qfog) / 顶部光晕(.qglow)：
     · 手机 390×844 的竖纹 = .qctr + .qfog；
     · 桌面 1440×900 上区归 .qglow、下区归 .qctr/.qfog。
   第 1 步试过把它们压到「任何时刻整屏亮度跨度 ≤3 级」：光晕的 α 要降两个多数量级，
   那时它已经不随时间变（23:00 只剩 1.20 级），而白天照样回到 6.97 级 —— 等于关掉。
   所以用户 2026-10-12 裁决：**选「全平」，不选 C+**。

   ── 本条只做一件事：在 time 模式下不再绘制这三层 ──
   保留下来的三层 = 底色(.qbase) + 暗角(.qvig) + 噪点(.qnoise)，合起来是一张**静态**图：
   底色是常量，暗角与噪点是固定几何的渐变/贴图，都不含时间项。
   ⚠️ 因此本文件第 1、4 节里描述「随时间变化 / --glow-a 随 L 变」的那些话，
      自本条起只说明**代码保留了什么**，不再描述屏上效果。

   ⚠️ 刻意**不删**这三层的元素、JS 和上面 ① ② ③ 三条规则，只加这一条 display ——
      要回退就删掉这一条（或整站 SX_BG_STYLE=old，本来就不加载本文件），
      不必从 git 里翻旧版本。`.qglow` 也仍然留在 DOM 里，
      sx-bg.js 靠「它还在不在画」判断要不要启动那个 60 秒的 --t-l 定时器（见 sx-bg.js 第 3 节）。
   ⚠️ 加 !important 的理由同第 3 节：这几条规则里带 z-index/opacity，只靠层叠顺序不够稳。 */
.qctr,
.qfog,
.qglow { display: none !important; }
