/* ══════════════════════════════════════════════════════════════════════════
   Relationship Space — 视觉层（母图：reference/mother-ui.png）
   俯视清澈海面 · 粉晶 + 茶绿 · 轻透面板 · 有人住的私人空间，不是后台工具。

   三条硬约束（来自项目历史，别回退）：
   1) 不用 backdrop-filter：部分 Windows GPU 驱动下整元素渲染不出来（SW v4 修复）。
      透明感靠"低不透明白 + 背后本身柔和的海面"，靠材质分层，不靠毛玻璃。
   2) [hidden] 必须压得住 display:flex/grid（.panel / .modal-mask 都踩过）。
   3) 字体全部本地托管、全部 OFL-1.1，页面零外部请求（见 static/fonts/LICENSES.md）。
   ══════════════════════════════════════════════════════════════════════════ */

/* ── 字体：中英文是一套系统，不是"英文好看+中文兜底" ────────────────── */

@font-face {                       /* 品牌手写体：只用于 Relationship Space 字样 */
  font-family: "RS Brand";
  src: url("fonts/greatvibes-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {                       /* 标题衬线（拉丁），可变 400–700 */
  font-family: "RS Display";
  src: url("fonts/lora-var.woff2") format("woff2-variations");
  font-weight: 400 700; font-style: normal; font-display: swap;
}
@font-face {                       /* 正文/UI（拉丁），可变 */
  font-family: "RS Sans";
  src: url("fonts/inter-var.woff2") format("woff2-variations");
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {                       /* 等宽：只给 hash / 技术详情 / 时间戳 */
  font-family: "RS Mono";
  src: url("fonts/plexmono-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
/* 中文两款（RS Sans SC / RS Serif SC）的 @font-face 不在这里：
   它们按 unicode-range 切成了 14 片，规则由 tools/subset_fonts.py 生成到
   static/fonts/fonts.css，页面在本文件之前引它。切片的理由见那个脚本的开头。 */

*, *::before, *::after {
  margin: 0; padding: 0; box-sizing: border-box;
  -webkit-tap-highlight-color: transparent;
}

:root {
  /* ── 母图色板 ─────────────────────────────────────── */
  --tea-mist:    #D3DECD;   /* 茶绿最浅一档，和 --quartz-mist 对称；次按钮用它起手 */
  --tea-pale:    #C7CEC0;
  --tea:         #A7B8A3;
  --tea-deep:    #8B9C86;
  --quartz-mist: #FBF1F3;
  --quartz-pale: #F4E2E5;
  --quartz:      #E7C7CF;
  --quartz-deep: #D9AEB7;
  --quartz-ink:  #B4818D;
  --haze-blue:   #D8E0EA;
  --pale-yellow: #F3DEBA;
  --tea-ink:     #33453A;   /* 茶绿次按钮上的字：在 --tea-pale→--tea 渐变上 5.5:1 */

  /* ── 文字 ────────────────────────────────────────── */
  --ink:       #2C3833;
  --ink-soft:  #384540;
  --ink-mute:  #44524D;   /* 玻璃薄了一档，次级文字跟着压深：面板上要 ≥3:1 */
  --ink-pink:  #5F3E47;   /* 次级粉字压深一档：旧值 #8C5F68 在输入框/面板压到海面暗处时
                             只有 2.2–2.3:1，低于次级文字 3:1。色相不变（348°），只降明度
                             L .461→.376，最差底 3.02。--accent-ink 用的也是它，顺带把侧栏
                             选中态文字从 3.12 抬到 4.65。改之前先跑 tools/ui_check.py */
  --hairline:  rgba(120,140,132,.16);
  --hairline-pink: rgba(200,160,170,.28);

  /* ── 材质分层 ──────────────────────────────────────
     这一档不是"看着差不多就行"，是照着母图量出来的。做法：取每个元素内部与
     它紧邻的海面，反解等效白色叠加 α = (元素 - 海面) / (1 - 海面)：

       输入框 0.08 ＜ 面板 0.29 ＜ 选中胶囊 0.37(玫瑰) ＜ 自己气泡 0.46(玫瑰)
              ＜ AI 气泡 0.60

     两条结论改了这一版：
     一、面板本来是 0.60，比母图厚一倍——海全被糊住了，"清澈海面"白做。
     二、母图里**面板内的卡片几乎不额外加白**（实测 Δα≈0），层级是靠
         一圈更亮的描边和投影撑出来的，不是靠再叠一层牛奶。所以 surface-2
         很淡，真正干活的是 --edge 和 --shadow-*。

     和母图的唯一有意偏差：面板取 0.33、输入框取 0.31，都比母图厚。母图是静态
     稿，它的字只要好看；这里的字要压在会动的海面上真读。按 `tools/ui_check.py`
     的合成结果，这一档下正文在中位海面上是 4.7:1、次级 3.2:1；海最暗的那一档
     正文掉到 3.9:1（AA 大字通过），再薄就真的读不动了。改这几个数之前先跑那个脚本。 */
  --surface-1: rgba(255,255,255,.16);                                   /* 悬浮底/chip */
  --surface-2: linear-gradient(178deg, rgba(255,255,255,.20), rgba(255,255,255,.12)); /* 面板内的卡片 */
  --surface-3: linear-gradient(178deg, rgba(255,255,255,.38), rgba(255,255,255,.28)); /* 面板（母图 0.29，这里 0.33：见下）*/
  /* 弹窗/信纸：要能读长文。.90/.82 时下面聊天气泡的正文还会透上来 ——
     手机上一眼就看得见下面聊天正文的字影，而这是全站唯一一块「读信」的界面。
     这一档是弹窗专用（全站只有 .modal 用它），不是 §5 记为不推项的
     --surface-3 / .input-pill —— 那两个薄是为了让海透过来，弹窗的职责恰好相反。
     配合 .modal-mask .36→.55，弹窗内纯净区的字影 stddev 4.44→1.75（−61%），极差 19→15。
     再往上推到 .975/.955 只多拿到 1.75→1.21，却开始失去玻璃感，不值。 */
  --surface-4: linear-gradient(178deg, rgba(255,255,255,.95), rgba(255,255,255,.91));
  --surface-pink: linear-gradient(150deg, rgba(255,255,255,.26), rgba(244,226,229,.62));
  --edge:      rgba(255,255,255,.34);
  --edge-soft: rgba(255,255,255,.14);
  --inner-top: inset 0 1px 0 rgba(255,255,255,.34);
  --shadow-soft:  0 10px 26px rgba(66,88,80,.17);
  --shadow-lift:  0 16px 38px rgba(66,88,80,.22);
  --shadow-panel: 0 20px 54px rgba(70,90,84,.14), inset 0 1px 0 rgba(255,255,255,.55);
  --shadow-pink:  0 10px 26px rgba(196,150,160,.26);

  /* ── Ocean（左右侧背景海面）────────────────────────────
     颜色由主题决定（下面 [data-theme] 各改一套），动态由「动态海面强度」决定：
       --sea-k    速度倍数（动画 duration 除以它）
       --sea-amp  位移幅度倍数（只给非平铺层：swell / sheen；
                  焦散是无缝平铺，位移必须正好等于一张 tile，改不得）
       --sea-play 0 档时整片水 paused
     这三个由 atmosphere.js 的 setIntensity() 写在 <html> 上。

     下面这一套颜色是「粉晶暮海」预设（#E8CFD6 → #9E7F8B）算出来的兜底值：
     atmosphere.js 的 applyOcean() 起来后会用 inline 变量覆盖它。
     **它只属于左右两侧的卡片**，和 --chat-bg / --accent-* 没有任何关系。 */
  --sea-foam: rgba(245,233,237,.55);   /* 最亮的那层泡沫光 */
  --sea-mid:  rgba(158,127,139,.42);
  --sea-deep: rgba(142,114,125,.42);
  --sea-a:    #CCB1BA;   /* 底色渐变四档，从上到下 */
  --sea-b:    #B699A3;
  --sea-c:    #C3A7B0;
  --sea-d:    #D6BCC4;
  --sea-glint-a: rgba(244,220,218,.44);   /* 水面反光 */
  --sea-glint-b: rgba(229,203,204,.34);
  --sea-glint-c: rgba(248,234,233,.26);
  --sea-k:       1;
  --sea-amp:     1;
  --sea-play:    running;
  --sea-caustic-k: 1;
  --sea-pink-k:    1;
  /* Crystal Glint 的三支笔。写成逗号三元组是为了 JS 能直接拼进 rgba()，
     也为了 CSS 这边 rgba(var(--glint-cool), .5) 能用。饱和度都在 12% 以下：
     要的是矿物的冷光，不是霓虹。 */
  --glint-cool:  242,246,248;   /* 冷白 */
  --glint-shell: 240,220,218;   /* 贝壳粉 */
  --glint-lilac: 220,213,226;   /* 极淡灰紫 */
  /* 中央聊天区的纯色底。**自己一个独立的值**，不从 Theme 推导、也不从 Ocean
     推导；真正生效的那份由 applyChatBackground() 按 chat_background_color
     写成 inline 变量。换 Ocean 预设时这个值不会被碰。 */
  --chat-bg: #E6DADD;
  /* 页面底：卡片之外的地方。Ocean 只在卡片里，这里不该有水纹 */
  --page-bg: #DFD3D6;

  /* ── 主强调（Theme 层唯一开关点）────────────────────── */
  --accent:       var(--quartz);
  --accent-deep:  var(--quartz-deep);
  --accent-pale:  var(--quartz-pale);
  --accent-mist:  var(--quartz-mist);
  --accent-ink:   var(--ink-pink);
  --accent-glow:  rgba(217,174,183,.40);
  --accent-line:  rgba(217,174,183,.55);

  /* ── 尺度 ────────────────────────────────────────── */
  --r-panel: 26px;
  --r-card:  18px;
  --r-bubble: 20px;
  --r-pill:  999px;
  --gap:     14px;
  --side-w:  272px;
  --rail-w:  296px;

  /* ── 字体角色（Desktop / Mobile 统一）────────────────── */
  --font-brand:   "RS Brand", "RS Display", "RS Serif SC", "Songti SC", serif;
  --font-display: "RS Display", "RS Serif SC", "Songti SC", "Noto Serif SC", serif;
  --font-body:    "RS Sans", "RS Sans SC", "PingFang SC", "HarmonyOS Sans SC",
                  "Noto Sans SC", "Microsoft YaHei", system-ui, sans-serif;
  --font-ui:      var(--font-body);
  --font-letter:  "RS Display", "RS Serif SC", "PingFang SC", "Noto Serif SC", serif;
  --font-mono:    "RS Mono", ui-monospace, "SF Mono", Menlo, Consolas,
                  "RS Sans SC", monospace;
  --font-emoji:   "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji";

  /* ── Motion System ──────────────────────────────────
     一套 easing / duration，全站共用；spring 曲线用 Motion 的
     duration+bounce 模型算成 CSS linear()，不引任何动画运行时。 */
  --ease-out:    cubic-bezier(.22, 1, .36, 1);
  --ease-inout:  cubic-bezier(.45, 0, .2, 1);
  --ease-enter:  cubic-bezier(.16, 1, .3, 1);
  --spring-soft: linear(0, 0.0419, 0.1409, 0.2661, 0.3974, 0.5221, 0.6333, 0.7279,
                        0.8052, 0.8663, 0.9131, 0.9476, 0.9722, 0.9891, 0.9999,
                        1.0064, 1.0098, 1.011, 1.0109, 1.01, 1.0087, 1.0072,
                        1.0058, 1.0045, 1.0034);
  --spring-snap: linear(0, 0.0525, 0.1771, 0.3344, 0.4966, 0.6461, 0.7732, 0.8741,
                        0.9488, 1.0002, 1.032, 1.0486, 1.0542, 1.0523, 1.0461,
                        1.0378, 1.029, 1.0207, 1.0135, 1.0078, 1.0034, 1.0004,
                        0.9985, 0.9975, 0.9971, 0.9971, 0.9974);
  --m: 1;                       /* Motion 强度倍数：设置里可调，0 = 关掉 */
  --t-press:  calc(110ms * var(--m));
  --t-hover:  calc(190ms * var(--m));
  --t-enter:  calc(320ms * var(--m));
  --t-panel:  calc(420ms * var(--m));
  --t-spring: calc(560ms * var(--m));

  /* ── 装饰密度：设置里可调 ───────────────────────────── */
  --deco: 1;
}

[data-motion="soft"] { --m: .6; }
[data-motion="off"]  { --m: 0; }
[data-deco="soft"]  { --deco: .55; }
[data-deco="plain"] { --deco: 0; }

/* Theme = **只有** UI 强调色（按钮、胶囊、描边、选中态）和卡片之外的页面底。
   它不再产出任何 --sea-*（那是 Ocean 预设的事），也不再产出 --chat-bg
   （那是中央聊天背景自己的事）。三套状态互不继承。 */
[data-theme="tea"] {
  --page-bg: #D3DED8;
  --accent: #BCCBB6; --accent-deep: var(--tea-deep);
  --accent-pale: #E3EADE; --accent-mist: #F2F6F0; --accent-ink: #4A5A4C;
  --accent-glow: rgba(139,156,134,.35); --accent-line: rgba(139,156,134,.5);
  --hairline-pink: rgba(150,170,145,.26);
}
[data-theme="haze"] {
  --page-bg: #D4DDE9;
  --accent: var(--haze-blue); --accent-deep: #A9BACE;
  --accent-pale: #EAEFF5; --accent-mist: #F5F8FB; --accent-ink: #4D5B6B;
  --accent-glow: rgba(169,186,206,.40); --accent-line: rgba(169,186,206,.55);
  --hairline-pink: rgba(160,180,200,.28);
}

html, body { height: 100%; }

body {
  font-family: var(--font-body), var(--font-emoji);
  color: var(--ink);
  font-size: 14.5px;
  line-height: 1.65;
  background: var(--page-bg);       /* 卡片之外的底；Ocean 不在这一层 */
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ══════════ Ocean（只活在卡片内部）══════════
   这一层**不是**全屏背景。它是 [data-ocean] 卡片的第一个子元素，尺寸被 JS 设成
   视口大小、left/top 设成负的卡片视口坐标，所以五张卡片看到的是同一片海的不同
   窗口；真正的边界由卡片自己的 overflow:hidden 划定。
   中央聊天区不带 data-ocean，它的祖先链上也没有任何 .ocean —— 海在那里不存在，
   不是被什么东西盖住。 */

.ocean {
  position: absolute;
  left: 0; top: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background:
    radial-gradient(120% 80% at 16% 6%,  var(--sea-foam), transparent 56%),
    radial-gradient(85%  65% at 84% 28%, var(--sea-mid), transparent 62%),
    radial-gradient(110% 85% at 56% 98%, var(--sea-deep), transparent 64%),
    linear-gradient(166deg, var(--sea-a) 0%, var(--sea-b) 42%, var(--sea-c) 72%, var(--sea-d) 100%);
}
/* 卡片本来的半透明白玻璃。它原先是卡片自己的 background（画在页面海之上）；
   海搬进卡片之后就得跟着搬到海的上面，否则文字会直接压在水纹上。 */
.ocean-glass {
  position: absolute; inset: 0;
  background: linear-gradient(178deg, rgba(255,255,255,.50), rgba(255,255,255,.40));
}
.card.now > .ocean > .ocean-glass {
  background: linear-gradient(150deg, rgba(255,255,255,.42), rgba(244,226,229,.74));
}
/* 卡片：给 .ocean 当定位与剪裁的容器。
   z-index:0 是要卡片自己成为层叠上下文，好把 z-index:-1 的海关在里面；
   海用负层级沉到所有内容之下，这样**不用**去动任何子元素的 position ——
   .card-ornament / .sidebar-ornament 那种 absolute 装饰件保持原样。 */
[data-ocean] { position: relative; z-index: 0; overflow: hidden; }
[data-ocean] > .ocean { position: absolute; z-index: -1; }

/* WebGL 水面（主路径）：逐像素算，不是贴图平移 */
.atm-gl { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

/* 下面三层是 WebGL 拿不到时的兜底贴图海面；WebGL 上岗就让位 */
.atm-swell {
  position: absolute; inset: -22%;
  background:
    radial-gradient(26% 40% at 30% 32%, rgba(240,249,245,.34), transparent 70%),
    radial-gradient(22% 34% at 72% 58%, rgba(233,243,238,.26), transparent 72%),
    radial-gradient(30% 46% at 52% 84%, var(--sea-deep), transparent 70%);
  animation: swell calc(78s / var(--sea-k)) ease-in-out infinite alternate;
  animation-play-state: var(--sea-play);
  will-change: transform;
}
.atm-caustic { position: absolute; inset: -60%; background-repeat: repeat; will-change: transform; }
.atm-caustic-a {
  background-image: var(--caustic-tex);
  background-size: 330px 520px;
  mix-blend-mode: screen; opacity: calc(.80 * var(--sea-caustic-k));
  transform: rotate(-5deg);
  animation: drift-a calc(104s / var(--sea-k)) linear infinite;
  animation-play-state: var(--sea-play);
}
.atm-caustic-b {
  background-image: var(--caustic-tex);
  background-size: 560px 860px;
  mix-blend-mode: screen; opacity: calc(.34 * var(--sea-caustic-k));
  transform: rotate(4deg);
  animation: drift-b calc(168s / var(--sea-k)) linear infinite;
  animation-play-state: var(--sea-play);
}
.atm-depth {
  position: absolute; inset: -40%;
  background-image: var(--depth-tex);
  background-repeat: repeat; background-size: 720px 980px;
  mix-blend-mode: soft-light; opacity: .58;
  animation: drift-c calc(220s / var(--sea-k)) linear infinite;
  animation-play-state: var(--sea-play);
  will-change: transform;
}
.atm-sheen {
  position: absolute; inset: -18%;
  background:
    radial-gradient(30% 42% at 24% 26%, var(--sea-glint-a), transparent 76%),
    radial-gradient(26% 36% at 76% 66%, var(--sea-glint-b), transparent 78%),
    radial-gradient(20% 30% at 58% 14%, var(--sea-glint-c), transparent 78%);
  animation: sheen calc(64s / var(--sea-k)) ease-in-out infinite alternate;
  animation-play-state: var(--sea-play);
  will-change: transform, opacity;
}
/* Crystal Glint System：星芒画在这张 canvas 上。
   位置和尺寸由 atmosphere.js 按**卡片可见矩形**设（不是铺满视口）——
   五张卡各自只分配自己那块 backing store，并且按 devicePixelRatio 1:1 落像素、
   全程不缩放。上一轮碎光就是死在贴图 minification 里的，这一层必须绕开它。
   混合用 screen，和焦散同一档；它在 .ocean-glass 之下，所以星芒是在水里，
   不是浮在面板上。deco=plain 时整层关掉。 */
.atm-glint {
  position: absolute;
  mix-blend-mode: screen;
  pointer-events: none;
  opacity: var(--deco);
}

/* 卡片滚出视口后，这张卡自己的海面动画停下来（手机上侧栏整个在视口外，
   原来它仍在满速跑动画和求解，纯耗电）。用属性选择器而不是行内样式：
   特异度 (0,3,0) 盖得住 .atm-caustic-a 的 animation-play-state，
   而 freeze() 打的是行内样式，优先级更高，截图取证不受影响。
   重新进入视口时 atmosphere.js 会先把动画 currentTime 对齐到仍在跑的那张卡，
   再放开 —— 五张卡看的是同一片海，不能因为暂停过就错开相位。 */
.ocean[data-offscreen] .atm-swell,
.ocean[data-offscreen] .atm-caustic,
.ocean[data-offscreen] .atm-depth,
.ocean[data-offscreen] .atm-sheen { animation-play-state: paused; }

body.sea-webgl .atm-swell,
body.sea-webgl .atm-caustic,
body.sea-webgl .atm-depth,
body.sea-webgl .atm-sheen { display: none; }

/* 「安静水面」：同一片海，只是把动画停掉。这个开关挂在 <html> 的
   data-ocean-motion 上 —— 中央聊天背景换成图片/视频**不会**碰它。 */
[data-ocean-motion="still"] .atm-caustic,
[data-ocean-motion="still"] .atm-swell,
[data-ocean-motion="still"] .atm-sheen,
[data-ocean-motion="still"] .atm-depth { animation: none; }

@keyframes drift-a {
  from { transform: rotate(-5deg) translate3d(0,0,0); }
  to   { transform: rotate(-5deg) translate3d(0, 520px, 0); }
}
@keyframes drift-b {
  from { transform: rotate(4deg) translate3d(0,0,0); }
  to   { transform: rotate(4deg) translate3d(0, -860px, 0); }
}
@keyframes drift-c { from { transform: translate3d(0,0,0); } to { transform: translate3d(0, -980px, 0); } }
@keyframes swell {
  from { transform: translate3d(calc(-1.5% * var(--sea-amp)), calc(-1% * var(--sea-amp)), 0)
                    scale(calc(1 + .03 * var(--sea-amp))); }
  to   { transform: translate3d(calc(2% * var(--sea-amp)), calc(1.5% * var(--sea-amp)), 0)
                    scale(calc(1 + .10 * var(--sea-amp))); }
}
@keyframes sheen {
  from { transform: translate3d(calc(1% * var(--sea-amp)), 0, 0) scale(calc(1 + .02 * var(--sea-amp)));
         opacity: calc(.85 * var(--sea-pink-k)); }
  to   { transform: translate3d(calc(-2% * var(--sea-amp)), calc(1% * var(--sea-amp)), 0)
                    scale(calc(1 + .08 * var(--sea-amp)));
         opacity: calc(1 * var(--sea-pink-k)); }
}

/* ══════════ 图标 ══════════ */

.icon-defs { position: absolute; width: 0; height: 0; overflow: hidden; }
/* .env 是信封那类"大一号"的线稿图标：尺寸各处自定，但描边画法必须和 .i 一致，
   否则 <use> 出来的 symbol 会用默认的 fill:black 画成一个黑方块。 */
.i, .env {
  width: 19px; height: 19px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
  display: inline-block; vertical-align: -3px;
  transition: color var(--t-hover) var(--ease-out),
              transform var(--t-hover) var(--spring-soft);
}
.i-sm { width: 15px; height: 15px; }
.i-lg { width: 22px; height: 22px; }
.i-xs { width: 12px; height: 12px; }

/* ══════════ 应用骨架 ══════════ */

.app {
  position: relative;
  z-index: 1;
  display: flex;
  gap: var(--gap);
  height: 100%;
  padding: var(--gap);
}

/* ══════════ 侧栏 ══════════ */

.sidebar {
  position: relative;
  width: var(--side-w);
  flex: none;
  display: flex;
  flex-direction: column;
  padding: 20px 14px 12px;
  border-radius: var(--r-panel);
  background: var(--surface-3);
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-panel);
  overflow: hidden;
  z-index: 20;
}
/* 侧栏顶部一道极淡的粉晶光，母图里那种"光从上面落下来" */
.sidebar::before {
  content: "";
  position: absolute; inset: 0 0 auto 0; height: 128px;
  background: linear-gradient(180deg, rgba(247,228,232,calc(.55 * var(--deco))), transparent);
  pointer-events: none;
}
.sidebar > *:not(.ocean) { position: relative; }   /* .ocean 必须留在 absolute：见 [data-ocean] > .ocean */

.brand {
  font-family: var(--font-brand);
  font-size: 27px;
  line-height: 1.25;
  text-align: center;
  color: var(--quartz-ink);
  text-shadow: 0 1px 0 rgba(255,255,255,.8);
  padding: 2px 4px 14px;
  user-select: none;
}

.profile {
  display: flex;
  align-items: center;
  gap: 13px;
  width: 100%;
  padding: 6px;
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: var(--r-card);
  transition: background var(--t-hover) var(--ease-out);
}
.profile:hover { background: var(--surface-1); }

.avatar {
  position: relative;
  width: 40px; height: 40px; flex: none;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 19px;
  font-family: var(--font-emoji), var(--font-body);
  overflow: hidden;
  background: linear-gradient(150deg, var(--quartz-mist), #DCE7E0);
  box-shadow: 0 0 0 2px rgba(255,255,255,.78), 0 4px 12px rgba(80,100,94,.14);
  transition: box-shadow var(--t-hover) var(--ease-out),
              transform var(--t-spring) var(--spring-soft);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar-xl { width: 62px; height: 62px; font-size: 28px; }
.avatar-lg { width: 52px; height: 52px; font-size: 24px; }
.avatar-md { width: 38px; height: 38px; font-size: 18px; }
.avatar-sm { width: 32px; height: 32px; font-size: 15px; }
.avatar-xs { width: 24px; height: 24px; font-size: 12px; }
/* 头像环：粉晶的一圈细光，selected / 有未读时更明显 */
.avatar.ringed { box-shadow: 0 0 0 2px rgba(255,255,255,.85), 0 0 0 3.5px var(--accent-line), 0 4px 12px rgba(80,100,94,.14); }
.avatar-wrap { position: relative; flex: none; }
.avatar-dot {
  position: absolute; right: -1px; bottom: -1px;
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--tea); box-shadow: 0 0 0 2.5px rgba(255,255,255,.9);
}
/* 状态灯：四态必须一眼能分开，但仍留在母图的低饱和区里。
   分辨靠"色相 + 明度"两个维度一起走，不靠提高饱和度——
   在=柔和绿 / 安静着=冷青灰 / 离开=更浅的冷灰 / 联系不上=更暗且更透。
   （历史 bug：away 和 idle 共用一个灰绿，here 干脆没有规则，三态同色。） */
.avatar-dot.thinking { background: var(--accent-deep); animation: dot-breathe 2.4s var(--ease-inout) infinite; }
.avatar-dot.looking { background: var(--pale-yellow); }
.avatar-dot.here { background: #86B48F; }
.avatar-dot.idle { background: #9DB2BC; }
.avatar-dot.away { background: #CBD2D0; }
.avatar-dot.unavailable { background: #8E9A96; opacity: .5; }

.profile-meta { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.profile-name { font-size: 15px; font-weight: 600; color: var(--ink); letter-spacing: .2px; }
.tag {
  align-self: flex-start;
  font-size: 11px;
  padding: 1px 9px;
  border-radius: var(--r-pill);
  color: var(--accent-ink);
  background: linear-gradient(120deg, var(--accent-mist), var(--accent-pale));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.7);
}

.tagline {
  font-family: var(--font-display);
  font-size: 12.5px;
  color: var(--ink-mute);
  text-align: center;
  padding: 12px 6px 14px;
  line-height: 1.8;
}

.nav { display: flex; flex-direction: column; gap: 2px; }

.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 9px 13px;
  border: none;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--ink-soft);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  transition: background var(--t-hover) var(--ease-out),
              color var(--t-hover) var(--ease-out),
              transform var(--t-press) var(--ease-out);
}
.nav-item .i { color: var(--tea-deep); }
.nav-item:hover { background: linear-gradient(96deg, rgba(255,255,255,.22), rgba(251,241,243,.44)); color: var(--ink); }
.nav-item:hover .i { color: var(--accent-deep); transform: translateX(1px); }
.nav-item:active { transform: scale(.985); }
.nav-item.active {
  color: var(--accent-ink);
  font-weight: 600;
  /* 母图实测 #DACDC8（暖、R 领先 18）。旧值合成到海面上是 #C4C7C4——三通道齐平，读成灰，
     粉晶感在选中态上等于没做；根因是中间那个 rgba(251,220,215) 的 G>B，是米白向不是粉向。
     换成 quartz-deep 一族并把尾端也染上淡粉，合成 #DACCCF：R 与母图完全对上，R−B +0→+11。*/
  background: linear-gradient(96deg, rgba(255,255,255,.70), rgba(218,176,185,.94) 45%, rgba(238,216,221,.76));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.6), 0 4px 14px var(--accent-glow);
}
.nav-item.active .i { color: var(--accent-deep); }
/* 选中项左侧一小段粉晶细线 —— 首饰式的细节，不是色块 */
.nav-item.active::before {
  content: "";
  position: absolute; left: 5px; top: 50%;
  width: 2px; height: 0; border-radius: 2px;
  background: linear-gradient(180deg, var(--accent-deep), transparent);
  transform: translateY(-50%);
  animation: nav-mark var(--t-spring) var(--spring-soft) forwards;
}
.nav-label { flex: 1; min-width: 0; }

.nav-badge {
  flex: none;
  min-width: 20px; height: 20px;
  padding: 0 6px;
  font-size: 11px;
  line-height: 20px;
  text-align: center;
  color: var(--accent-ink);
  background: linear-gradient(140deg, var(--accent-mist), var(--accent-pale));
  border-radius: var(--r-pill);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.65), 0 2px 8px var(--accent-glow);
}
.nav-badge[hidden] { display: none; }
.nav-badge.pulse { animation: badge-pop var(--t-spring) var(--spring-snap); }

.side-section {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 16px 6px 6px;
}
.side-section-title {
  flex: 1;
  font-size: 11.5px;
  letter-spacing: 1.6px;
  color: var(--ink-mute);
}

.round-btn {
  width: 26px; height: 26px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: none;
  border-radius: 50%;
  color: var(--accent-ink);
  background: linear-gradient(140deg, var(--accent-mist), var(--accent-pale));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.65), 0 3px 10px var(--accent-glow);
  cursor: pointer;
  transition: transform var(--t-spring) var(--spring-snap),
              box-shadow var(--t-hover) var(--ease-out);
}
.round-btn:hover { transform: scale(1.1) rotate(90deg); }
.round-btn:active { transform: scale(.92); }

.session-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 0 -4px;
  padding: 0 4px 4px;
  scrollbar-width: thin;
  scrollbar-color: var(--accent-line) transparent;
}
.session-list::-webkit-scrollbar { width: 5px; }
.session-list::-webkit-scrollbar-thumb { background: var(--accent-line); border-radius: 3px; }

/* 会话行：每个房间有自己的一点识别度（头像环 + 一条极细的 accent），
   但不做彩虹标签、不做企业 IM 那套。 */
.session-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-radius: var(--r-card);
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  transition: background var(--t-hover) var(--ease-out),
              transform var(--t-press) var(--ease-out);
}
.session-item::before {
  content: "";
  position: absolute; left: 0; top: 14%; bottom: 14%;
  width: 2px; border-radius: 0 2px 2px 0;
  background: var(--room-accent, var(--tea));
  opacity: 0;
  transition: opacity var(--t-hover) var(--ease-out);
}
.session-item:hover { background: var(--surface-1); }
.session-item:hover::before { opacity: .5; }
.session-item:active { transform: scale(.99); }
.session-item.active {
  background: linear-gradient(96deg, rgba(255,255,255,.34), rgba(251,220,215,.70) 92%);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.6);
}
.session-item.active::before { opacity: 1; background: var(--accent-deep); }
.session-mid { flex: 1; min-width: 0; }
.session-title {
  font-size: 13.5px; font-weight: 600; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.session-prev {
  font-size: 12px; color: var(--ink-mute); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.session-prev .trace { color: var(--accent-ink); }
.session-right { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.session-time { font-size: 10.5px; color: var(--ink-mute); font-family: var(--font-mono); }
.session-kind {
  font-size: 10px;
  padding: 0 6px;
  border-radius: var(--r-pill);
  color: var(--tea-deep);
  background: rgba(255,255,255,.55);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
}

.sidebar-foot {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  padding-top: 10px;
  margin-top: 6px;
  border-top: 1px solid var(--hairline);
}
/* 母图侧栏底部这一排是四枚**看得出是按钮**的圆片（带一圈亮边）；我们原来是
   background: transparent 的裸图标，直接坐在会动的海面上：没有可点的暗示，
   图标本身也被浪丝洗掉。给它和 chip 同一档的底，别的都不动。 */
.foot-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: none; border-radius: 50%;
  background: rgba(255,255,255,.30);
  box-shadow: var(--inner-top), inset 0 0 0 1px var(--edge-soft);
  color: var(--tea-deep); cursor: pointer;
  transition: background var(--t-hover) var(--ease-out),
              color var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) var(--ease-out),
              transform var(--t-press) var(--ease-out);
}
.foot-btn:hover {
  background: var(--accent-mist); color: var(--accent-deep);
  box-shadow: var(--inner-top), inset 0 0 0 1px var(--accent-line);
}
.foot-btn:active { transform: scale(.9); }
.foot-spacer { flex: 1; }

.sidebar-ornament {
  position: absolute;
  right: -14px; bottom: -16px;
  width: 108px; height: 108px;
  color: var(--quartz);
  opacity: calc(.6 * var(--deco));
  pointer-events: none;
}
.sidebar-ornament svg { width: 100%; height: 100%; }

/* ══════════ 聊天主区（永远是视觉中心：坐在海面上，不加面板底）══════════ */

.chat-main { position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; }
/* 聊天背景：默认一块主题纯色，也可以是自己传的图片 / 视频。
   它把 Atmosphere 挡在中央区之外——海只留在左右两侧（母图里中间本来也不是海）。
   作用范围严格等于 .chat-main：侧栏和右栏不会被自己的照片污染。 */
.chat-bg {
  position: absolute; inset: 0; z-index: 0;
  border-radius: var(--r-panel);
  overflow: hidden;
  background: var(--chat-bg);
  /* 图片背景走 background-image（由 applyChatBackground 写成 inline），
     不是 <img> —— CSS 背景图不计入页面的 load 事件。下面三条长写在
     shorthand 之后，保证盖住它重置出来的 auto/repeat。没有图时全无影响。 */
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  pointer-events: none;
}
.chat-bg > video {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
/* 上传中：整组选项禁用。只借现有 .choice 加一个"点不动"的表示，不新增控件。 */
.choice:disabled { opacity: .58; cursor: default; }
.choice:disabled:hover { transform: none; }
/* 图片/视频上再压一层极薄的白：气泡和输入框是玻璃，底下太花就读不动了 */
.chat-main > *:not(.chat-bg) { position: relative; z-index: 1; }

.chat-header {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px 12px;
}
.chat-title {
  font-family: var(--font-display);
  font-size: 17px; font-weight: 600; color: var(--ink);
  letter-spacing: .2px;
  text-shadow: 0 1px 0 rgba(255,255,255,.5);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-status {
  font-size: 11.5px; color: var(--ink-mute);
  display: flex; align-items: center; gap: 6px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-status::before {
  content: "";
  width: 6px; height: 6px; flex: none;
  border-radius: 50%;
  background: var(--tea);
  box-shadow: 0 0 0 3px rgba(167,184,163,.28);
  transition: background var(--t-hover) var(--ease-out);
}
.chat-status.is-typing { color: var(--accent-ink); }
.chat-status.is-typing::before {
  background: var(--accent-deep);
  box-shadow: 0 0 0 3px var(--accent-glow);
  animation: dot-breathe 2s var(--ease-inout) infinite;
}
.header-info { flex: 1; min-width: 0; }
.header-actions { display: flex; align-items: center; gap: 4px; margin-left: auto; }

.ghost-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: none;
  border: none; border-radius: 50%;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background var(--t-hover) var(--ease-out),
              color var(--t-hover) var(--ease-out),
              transform var(--t-press) var(--ease-out);
}
.ghost-btn:hover { background: rgba(255,255,255,.5); color: var(--accent-ink); }
.ghost-btn:active { transform: scale(.9); }
.ghost-btn.danger:hover { color: #B4737E; background: rgba(255,236,238,.6); }
.ghost-btn.on { color: var(--accent-ink); background: var(--accent-mist); }

.menu-btn { display: none; position: relative; }
.menu-badge { position: absolute; top: 1px; right: 1px; min-width: 15px; height: 15px; padding: 0 4px; font-size: 10px; line-height: 15px; }

/* ── 消息流 ── */

.chat-messages {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 6px 16px 18px;
  scrollbar-width: thin;
  scrollbar-color: var(--accent-line) transparent;
}
.chat-messages::-webkit-scrollbar { width: 6px; }
.chat-messages::-webkit-scrollbar-thumb { background: var(--accent-line); border-radius: 3px; }

.day-divider {
  align-self: center;
  display: flex; align-items: center; gap: 10px;
  font-size: 11.5px;
  color: #667670;
  letter-spacing: 1px;
  padding: 8px 2px 2px;
  text-shadow: 0 1px 0 rgba(255,255,255,.55);
}
.day-divider::before, .day-divider::after {
  content: ""; width: 26px; height: 1px;
  background: linear-gradient(90deg, transparent, var(--hairline-pink), transparent);
}

.msg-row {
  display: flex;
  gap: 10px;
  max-width: min(66%, 620px);
  animation: msg-in var(--t-enter) var(--spring-soft) both;
}
.msg-row.user { align-self: flex-end; flex-direction: row-reverse; }
.msg-row.ai { align-self: flex-start; }
.msg-row .avatar { width: 38px; height: 38px; font-size: 18px; }
.msg-row.user .avatar { display: none; }

.msg-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.msg-row.user .msg-body { align-items: flex-end; }

.msg-sender { font-size: 11.5px; color: #66746E; padding: 0 6px 1px; text-shadow: 0 1px 0 rgba(255,255,255,.45); }
.msg-row.user .msg-sender { display: none; }

.bubble {
  padding: 11px 16px;
  border-radius: var(--r-bubble);
  font-size: 14.5px;
  line-height: 1.75;
  white-space: pre-wrap;
  word-break: break-word;
  box-shadow: var(--shadow-soft), var(--inner-top);
  transition: box-shadow var(--t-hover) var(--ease-out),
              transform var(--t-hover) var(--spring-soft);
}
.msg-row.ai .bubble {
  /* 象牙而不是纯白：α=.70 下海面的绿会透上来，纯白合成出去是 G−R +3（冷），
     母图是 −1（暖）。源色往象牙偏正好抵消，合成 #DDDDD8 对母图 #DFDEDB。*/
  background: rgba(255,248,243,.70);
  color: #44504B;
  border-top-left-radius: 7px;
}
.msg-row.ai:hover .bubble { box-shadow: var(--shadow-lift), var(--inner-top); }
.msg-row.user .bubble {
  background: linear-gradient(140deg, rgba(252,215,212,.82), rgba(244,201,199,.80));
  color: var(--ink-pink);
  border-top-right-radius: 7px;
  box-shadow: var(--shadow-pink), inset 0 1px 0 rgba(255,255,255,.55);
}
.bubble.error {
  background: rgba(255,255,255,.78);
  color: #A4626C;
  box-shadow: var(--shadow-soft), inset 0 0 0 1px rgba(217,174,183,.55);
}
.msg-time {
  font-size: 11px;
  color: #74827C;
  padding: 0 6px;
  font-family: var(--font-mono);
  letter-spacing: .2px;
  text-shadow: 0 1px 0 rgba(255,255,255,.45);
  opacity: .85;
}

.bubble-img { padding: 6px; }
.bubble-img img {
  max-width: min(300px, 58vw);
  max-height: 340px;
  border-radius: 14px;
  display: block;
  cursor: zoom-in;
  transition: transform var(--t-hover) var(--spring-soft);
}
.bubble-img img:hover { transform: scale(1.012); }
.img-caption { padding: 6px 8px 2px; font-size: 13.5px; }

.msg-quote {
  font-size: 12px;
  color: var(--ink-soft);
  background: rgba(255,255,255,.5);
  border-left: 2px solid var(--accent-deep);
  border-radius: 8px;
  padding: 5px 10px;
  margin-bottom: 5px;
  max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.mode-badge {
  display: inline-flex; align-items: center; gap: 4px;
  align-self: flex-start;
  font-size: 11px;
  color: var(--accent-ink);
  background: linear-gradient(120deg, rgba(255,255,255,.6), var(--accent-mist));
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  border-radius: var(--r-pill);
  padding: 1px 9px;
  margin-bottom: 3px;
}

/* ── 空间里的东西：不同内容类型 = 同一设计系统下的不同材质 ── */

.space-card {
  align-self: flex-start;
  flex: none;
  max-width: min(70%, 560px);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 15px;
  border-radius: var(--r-card);
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--edge-soft), var(--shadow-soft);
  cursor: pointer;
  color: inherit;
  font: inherit;
  text-align: left;
  border: none;
  animation: msg-in var(--t-enter) var(--spring-soft) both;
  transition: transform var(--t-hover) var(--spring-soft),
              box-shadow var(--t-hover) var(--ease-out);
}
.space-card:hover { transform: translateY(-1px); box-shadow: inset 0 0 0 1px var(--edge), var(--shadow-lift); }
.space-card .sc-icon {
  width: 40px; height: 40px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border-radius: 13px;
  background: rgba(255,255,255,.62);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--tea-deep);
}
/* 标题在上、说明在下：两个 span 必须自己成块，
   否则在窄屏上它们会串成一行、折行后互相压在一起（.space-card 还开了 overflow:hidden）。 */
.space-card .sc-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.space-card .sc-title { display: block; font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.35; }
.space-card .sc-sub { display: block; font-size: 12px; color: var(--ink-mute); line-height: 1.4; }
.space-card .sc-go { color: var(--accent-deep); }

/* 信件卡：粉晶纸感，是聊天里最"厚"的一层 */
.space-card.letter {
  background: var(--surface-pink);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.7), var(--shadow-pink);
}
.space-card.letter .sc-icon { background: rgba(255,255,255,.7); color: var(--accent-deep); }
.space-card.letter .sc-title { color: var(--accent-ink); }
/* 未拆封：一点点折角与轻微浮光 */
.space-card.letter.unopened { position: relative; overflow: hidden; align-items: flex-start; }
.space-card.letter.unopened .sc-icon, .space-card.letter.unopened .sc-go { margin-top: 1px; }
.space-card.letter.unopened::after {
  content: "";
  position: absolute; top: 0; right: 0;
  width: 22px; height: 22px;
  background: linear-gradient(225deg, rgba(255,255,255,.9) 50%, transparent 50%);
  box-shadow: -1px 1px 2px rgba(160,120,130,.18);
}
.space-card.letter.unopened::before {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 30%, rgba(255,255,255,.55) 45%, transparent 60%);
  transform: translateX(-120%);
  animation: sheen-sweep 7s var(--ease-inout) infinite;
  animation-delay: 1.5s;
  pointer-events: none;
}

/* 记忆回执 / 系统事件：最薄的一层，几乎只是一行字 */
.space-note {
  align-self: center;
  display: inline-flex; align-items: center; gap: 7px;
  max-width: 82%;
  padding: 5px 14px;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.42);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink-mute);
  font-size: 12px;
  animation: msg-in var(--t-enter) var(--ease-out) both;
}
.space-note .i { color: var(--accent-deep); width: 13px; height: 13px; }
.space-note.memory { color: var(--ink-soft); }

/* 一起看：中等材质 + 一条 accent 边 */
.space-card.watching {
  background: linear-gradient(150deg, rgba(255,255,255,.6), rgba(240,246,242,.5));
  box-shadow: inset 0 0 0 1px var(--edge-soft), var(--shadow-soft),
              inset 3px 0 0 var(--pale-yellow);
}

/* typing / pending */
.chat-pending {
  align-self: flex-start;
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--ink-mute);
  padding: 2px 8px;
}
.chat-pending .dot, .typing .dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent-deep);
  animation: blink 1.3s var(--ease-inout) infinite;
}
.chat-pending .dot:nth-child(2), .typing .dot:nth-child(2) { animation-delay: .18s; }
.chat-pending .dot:nth-child(3), .typing .dot:nth-child(3) { animation-delay: .36s; }

/* ══════════ Composer ══════════ */

.chat-footer { flex: none; padding: 0 16px calc(4px + env(safe-area-inset-bottom)); }
.composer { display: flex; flex-direction: column; gap: 8px; padding-bottom: 9px; }

.mode-pills {
  display: flex; gap: 8px; align-items: center;
  overflow-x: auto; scrollbar-width: none; padding: 1px;
}
.mode-pills::-webkit-scrollbar { display: none; }

.mode-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  padding: 5px 13px;
  border: none;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.46);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink-soft);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  user-select: none;
  transition: background var(--t-hover) var(--ease-out),
              color var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) var(--ease-out),
              transform var(--t-press) var(--spring-snap);
}
.mode-pill:hover { background: rgba(255,255,255,.66); color: var(--ink); transform: translateY(-1px); }
.mode-pill:active { transform: scale(.96); }
.mode-pill.active {
  color: var(--accent-ink);
  background: linear-gradient(96deg, var(--accent-pale), rgba(255,255,255,.6));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.75), 0 4px 14px var(--accent-glow);
}
.mode-pill .i { width: 14px; height: 14px; color: var(--tea-deep); }
.mode-pill.active .i { color: var(--accent-deep); }
.mode-check { display: none; }
.mode-pill.active .mode-check { display: inline-flex; animation: check-in var(--t-spring) var(--spring-snap); }

.composer-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.composer-chips[hidden] { display: none; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 4px 6px 4px 12px;
  border-radius: var(--r-pill);
  background: linear-gradient(120deg, rgba(255,255,255,.6), var(--accent-mist));
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink-soft);
  font-size: 12px;
  animation: chip-in var(--t-enter) var(--spring-snap) both;
}
.chip-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chip-close {
  width: 20px; height: 20px; flex: none;
  border: none; border-radius: 50%;
  background: transparent; color: var(--ink-mute);
  font-size: 13px; line-height: 1; cursor: pointer;
  transition: background var(--t-hover) var(--ease-out), color var(--t-hover) var(--ease-out);
}
.chip-close:hover { background: rgba(255,255,255,.75); color: var(--accent-ink); }

.chat-input-bar { display: flex; align-items: flex-end; gap: 12px; }

.input-pill {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  gap: 4px;
  padding: 7px 10px 7px 16px;
  border-radius: 27px;
  background: linear-gradient(180deg, rgba(255,255,255,.36), rgba(255,255,255,.26));
  box-shadow: inset 0 0 0 1px var(--edge), var(--shadow-soft);
  transition: box-shadow var(--t-hover) var(--ease-out), background var(--t-hover) var(--ease-out);
}
.input-pill:focus-within {
  background: linear-gradient(180deg, rgba(255,255,255,.44), rgba(255,255,255,.32));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.9), 0 0 0 3px var(--accent-glow), var(--shadow-soft);
}
.input-pill textarea {
  flex: 1; min-width: 0;
  resize: none;
  max-height: 132px;
  padding: 8px 4px;
  border: none;
  background: transparent;
  color: var(--ink);
  font: inherit;
  font-size: 14.5px;
  line-height: 1.6;
  outline: none;
}
.input-pill textarea::placeholder { color: #8E9C96; }
.pill-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex: none;
  border: none; border-radius: 50%;
  background: transparent; color: var(--tea-deep);
  cursor: pointer;
  transition: background var(--t-hover) var(--ease-out),
              color var(--t-hover) var(--ease-out),
              transform var(--t-press) var(--spring-snap);
}
.pill-icon:hover { background: var(--accent-mist); color: var(--accent-deep); }
.pill-icon:active { transform: scale(.88); }

.send-btn {
  position: relative;
  width: 52px; height: 52px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 50%;
  cursor: pointer;
  color: #fff;
  background:
    radial-gradient(circle at 34% 28%, rgba(255,255,255,.85), rgba(255,255,255,0) 52%),
    linear-gradient(145deg, var(--accent), var(--accent-deep));
  box-shadow: 0 10px 24px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,.6);
  transition: transform var(--t-spring) var(--spring-snap),
              box-shadow var(--t-hover) var(--ease-out), filter var(--t-hover) var(--ease-out);
}
.send-btn .i { width: 24px; height: 24px; stroke: none; fill: rgba(255,255,255,.95); }
.send-btn:hover { transform: translateY(-1px) scale(1.05); box-shadow: 0 14px 30px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,.78); }
.send-btn:active { transform: scale(.93); }
.send-btn:disabled { filter: saturate(.55) brightness(1.06); cursor: default; box-shadow: none; transform: none; }
.send-btn.sending .i { animation: twinkle 1.1s var(--ease-inout) infinite; }

/* ══════════ 右栏：关于空间 = 此刻的状态 ══════════ */

.rail {
  width: var(--rail-w);
  flex: none;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  overflow-y: auto;
  scrollbar-width: none;
  transition: width var(--t-panel) var(--ease-inout);
}
.rail::-webkit-scrollbar { display: none; }

/* 收起态：缩成一条，只留几个能一眼看懂的标记 */
body.rail-collapsed .rail { width: 56px; }
body.rail-collapsed .rail .card { display: none; }
body.rail-collapsed .rail .rail-strip { display: flex; }
.rail-strip { display: none; flex-direction: column; align-items: center; gap: 10px; padding: 12px 0; }
.rail-strip-btn {
  position: relative;
  width: 40px; height: 40px;
  display: inline-flex; align-items: center; justify-content: center;
  border: none; border-radius: 14px;
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--edge-soft), var(--shadow-soft);
  color: var(--tea-deep); cursor: pointer;
  transition: transform var(--t-hover) var(--spring-soft), color var(--t-hover) var(--ease-out);
}
.rail-strip-btn:hover { transform: translateY(-1px); color: var(--accent-deep); }
.rail-strip-btn .mini-badge {
  position: absolute; top: -4px; right: -4px;
  min-width: 17px; height: 17px; padding: 0 4px;
  font-size: 10px; line-height: 17px; text-align: center;
  border-radius: var(--r-pill);
  color: var(--accent-ink);
  background: linear-gradient(140deg, #fff, var(--accent-pale));
  box-shadow: 0 2px 8px var(--accent-glow), inset 0 0 0 1px rgba(255,255,255,.8);
}

.card {
  position: relative;
  padding: 17px;
  border-radius: var(--r-panel);
  background: var(--surface-3);
  border: 1px solid var(--edge);
  /* 侧栏和右栏卡片本来共用 --shadow-panel，一屏里两档材质完全同厚，谁也不比谁近。
     母图里侧栏是贴底的一整块安静底板，右栏是浮在海面上的四件独立物件。
     alpha 一律不动（玻璃厚度是记过案的有意偏差），只把这一档的投影收紧、压深，
     层级交给投影 —— 和「描边软化 + 投影承担分层」那一版是同一个机制。 */
  box-shadow: var(--shadow-lift), var(--inner-top);
  animation: card-in var(--t-panel) var(--spring-soft) both;
}
.card-title {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-display);
  font-size: 15px; font-weight: 600; color: var(--ink);
  margin-bottom: 4px;
  letter-spacing: .2px;
}
.card-title .i { color: var(--accent-deep); width: 15px; height: 15px; }
.card-sub { font-size: 12px; color: var(--ink-mute); margin-bottom: 13px; }
.card-more {
  margin-left: auto;
  border: none; background: none; cursor: pointer;
  font: inherit; font-size: 12px; color: var(--ink-mute);
  display: inline-flex; align-items: center; gap: 2px;
  transition: color var(--t-hover) var(--ease-out), gap var(--t-hover) var(--ease-out);
}
.card-more:hover { color: var(--accent-ink); gap: 5px; }

.card-ornament {
  position: absolute;
  top: 10px; right: 12px;
  width: 62px; height: 62px;
  color: var(--quartz);
  opacity: calc(.6 * var(--deco));
  pointer-events: none;
}
.card-ornament svg { width: 100%; height: 100%; }

/* 此刻：未拆的信是这张卡的主角，不是一个数字 */
.card.now { background: var(--surface-pink); box-shadow: var(--shadow-lift), var(--inner-top), 0 10px 30px var(--accent-glow); }
.letter-hint {
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 12px 13px;
  border: none; border-radius: var(--r-card);
  background: rgba(255,255,255,.62);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.8), var(--shadow-soft);
  color: var(--accent-ink); font: inherit; text-align: left;
  cursor: pointer; overflow: hidden; position: relative;
  transition: transform var(--t-hover) var(--spring-soft), box-shadow var(--t-hover) var(--ease-out);
}
.letter-hint:hover { transform: translateY(-1px); box-shadow: inset 0 0 0 1px #fff, var(--shadow-lift); }
.letter-hint .env {
  width: 40px; height: 30px; flex: none;
  color: var(--accent-deep);
}
.letter-hint-title { display: block; font-size: 14px; font-weight: 600; line-height: 1.35; }
.letter-hint-sub {
  display: block; font-size: 11.5px; color: var(--ink-mute); margin-top: 1px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.letter-hint::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 30%, rgba(255,255,255,.6) 45%, transparent 62%);
  transform: translateX(-120%);
  animation: sheen-sweep 6.5s var(--ease-inout) infinite;
  pointer-events: none;
}

.stat-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  padding: 10px 6px;
  border-radius: var(--r-card);
  background: rgba(255,255,255,.32);
  box-shadow: var(--inner-top), inset 0 0 0 1px var(--edge-soft),
              0 4px 12px rgba(66,88,80,.09);
}
.stat { text-align: center; min-width: 0; }
.stat-label {
  display: flex; align-items: center; justify-content: center; gap: 3px;
  font-size: 10px; color: var(--ink-mute); letter-spacing: .02em;
}
.stat-label .i { width: 10px; height: 10px; color: var(--accent-deep); }
.stat-value {
  font-size: 21px; font-weight: 500; color: var(--ink); line-height: 1.32;
  font-family: var(--font-display); font-variant-numeric: tabular-nums;
}
/* 有未拆的信时，那个数字自己会亮起来——不用再加一个红点 */
.stat.hot .stat-value { color: var(--accent-deep); }
.stat.hot .stat-label { color: var(--accent-ink); }

.people-row { display: flex; flex-wrap: wrap; gap: 10px; }
.person {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  width: 56px;
  border: none; background: none; cursor: pointer; font: inherit;
  transition: transform var(--t-hover) var(--spring-soft);
}
.person:hover { transform: translateY(-2px); }
.person-name { font-size: 11px; color: var(--ink-soft); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.person-state { font-size: 10.5px; color: var(--ink-mute); }
.person-state.thinking, .person-state.just_back { color: var(--accent-ink); }
.person-state.unavailable { color: var(--quartz-ink); }

.mini-list { display: flex; flex-direction: column; gap: 2px; }
.mini-item {
  display: flex; align-items: center; gap: 10px;
  width: 100%;
  padding: 8px;
  border: none; border-radius: var(--r-card);
  background: transparent; color: inherit; font: inherit;
  text-align: left; cursor: pointer;
  transition: background var(--t-hover) var(--ease-out), transform var(--t-press) var(--ease-out);
}
.mini-item:hover { background: rgba(255,255,255,.46); }
.mini-item:active { transform: scale(.99); }
.mini-thumb {
  width: 36px; height: 36px; flex: none;
  border-radius: 12px;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(150deg, rgba(255,255,255,.72), rgba(215,229,222,.7));
  color: var(--tea-deep);
  box-shadow: var(--inner-top), inset 0 0 0 1px var(--edge-soft),
              0 3px 8px rgba(66,88,80,.10);
}
.mini-thumb.pink { background: linear-gradient(150deg, #fff, var(--accent-pale)); color: var(--accent-deep); }
.mini-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.mini-title { font-size: 13px; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mini-sub { font-size: 11px; color: var(--ink-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mini-tag {
  flex: none;
  font-size: 10.5px;
  padding: 1px 8px;
  border-radius: var(--r-pill);
  color: var(--accent-ink);
  background: var(--accent-pale);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.65);
}

.event-line {
  display: flex; align-items: baseline; gap: 7px;
  padding: 6px 4px;
  font-size: 12.5px; color: var(--ink-soft);
  border-bottom: 1px solid var(--hairline);
}
.event-line:last-child { border-bottom: none; }
.event-line b { color: var(--ink); font-weight: 600; }
.event-line .when { margin-left: auto; font-size: 11px; color: var(--ink-mute); font-family: var(--font-mono); }

/* ══════════ 功能面板 ══════════ */

.panel {
  position: fixed;
  top: var(--gap); bottom: var(--gap); right: var(--gap);
  left: calc(var(--side-w) + var(--gap) * 2);
  z-index: 40;
  display: flex;
  flex-direction: column;
  border-radius: var(--r-panel);
  background: var(--surface-3);
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-panel);
  overflow: hidden;
  animation: panel-in var(--t-panel) var(--spring-soft) both;
}
.panel[hidden] { display: none; }
body.panel-open .chat-main,
body.panel-open .rail { visibility: hidden; }

.panel-header {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 16px 18px 12px;
  padding-top: calc(16px + env(safe-area-inset-top));
  border-bottom: 1px solid var(--hairline);
}
.panel .menu-btn { display: inline-flex; }
.panel-title { font-family: var(--font-display); font-size: 17px; font-weight: 600; color: var(--ink); }
.panel-actions { margin-left: auto; display: flex; gap: 6px; }

.panel-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px 20px calc(24px + env(safe-area-inset-bottom));
  width: 100%;
  max-width: 880px;
  margin: 0 auto;
  scrollbar-width: thin;
  scrollbar-color: var(--accent-line) transparent;
}
.panel-body::-webkit-scrollbar { width: 6px; }
.panel-body::-webkit-scrollbar-thumb { background: var(--accent-line); border-radius: 3px; }
/* 侧栏聊天未读：主动消息不再抄进通知中心之后，这里是唯一的提示。
   沿用 .session-kind 的位置与尺寸，只换成强调色胶囊，不新加一层布局。 */
.session-unread {
  min-width: 17px; padding: 0 6px;
  border-radius: var(--r-pill);
  /* 与导航未读徽标 .nav-badge 同一套配色，别在侧栏另起一种"未读长什么样" */
  color: var(--accent-ink);
  background: linear-gradient(140deg, var(--accent-mist), var(--accent-pale));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.7);
  font-size: 10.5px; font-weight: 600; line-height: 16px;
  text-align: center; font-variant-numeric: tabular-nums;
}

.notification-summary { padding: 10px 12px; margin-bottom: 10px; color: var(--ink-soft); }
.notification-row { width: 100%; display: flex; gap: 12px; align-items: flex-start; text-align: left; padding: 14px; margin: 7px 0; border: 1px solid var(--accent-line); border-radius: 14px; background: var(--panel); color: var(--ink); }
.notification-row.read { opacity: .68; }
.notification-row.needs-you { border-color: var(--accent); box-shadow: inset 3px 0 var(--accent); }
.notification-kind { flex: 0 0 auto; padding: 3px 7px; border-radius: 999px; background: var(--tea-soft); font-size: 11px; }
.notification-row.needs-you .notification-kind { background: var(--accent-soft); color: var(--accent-deep); }
.notification-main { min-width: 0; flex: 1; display: grid; gap: 4px; }
.notification-main span { color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.notification-row time { color: var(--ink-faint); font-size: 11px; white-space: nowrap; }
.autonomy-timeline { display: grid; gap: 7px; margin-bottom: 18px; }
.autonomy-controls { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.activity-row { display: grid; grid-template-columns: auto 1fr auto; gap: 10px; align-items: start; padding: 11px 12px; border: 1px solid var(--hairline); border-radius: 12px; background: var(--panel); }
.activity-row span:nth-child(2) { display: grid; gap: 3px; }
.activity-row small, .activity-row time { color: var(--ink-mute); font-size: 11px; }

/* Remote Executor v1：远程端在线状态与远程动作的可读态。 */
.remote-head { display: flex; justify-content: flex-end; margin-bottom: 8px; }
.activity-row.remote-executor.offline,
.activity-row.remote-executor.stale,
.activity-row.remote-executor.revoked { opacity: .62; }
.activity-row.remote-executor.online { border-color: var(--hairline-pink); }
.activity-row.remote-action.recoverable,
.activity-row.remote-action.timed_out,
.activity-row.remote-action.failed { border-color: var(--hairline-pink); }

.section-title {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px;
  letter-spacing: 1.2px;
  color: var(--ink-mute);
  margin: 22px 2px 10px;
}
.section-title:first-child { margin-top: 4px; }
.section-title::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(90deg, var(--hairline-pink), transparent);
}

.list-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 11px 12px;
  border: none;
  border-radius: var(--r-card);
  background: transparent;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) var(--ease-out),
              transform var(--t-press) var(--ease-out);
}
.list-item:hover { background: rgba(255,255,255,.58); box-shadow: var(--shadow-soft); }
.list-item:active { transform: scale(.995); }
.list-item + .list-item { box-shadow: inset 0 1px 0 var(--hairline); }
.list-item + .list-item:hover { box-shadow: var(--shadow-soft); }
.list-icon {
  width: 38px; height: 38px; flex: none;
  display: flex; align-items: center; justify-content: center;
  border-radius: 13px;
  background: rgba(255,255,255,.62);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--tea-deep);
  font-size: 17px;
}
.list-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.list-title { font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-sub { font-size: 12px; color: var(--ink-mute); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.list-time { flex: none; font-size: 11px; color: var(--ink-mute); font-family: var(--font-mono); }
.list-item.unread .list-title { font-weight: 600; color: var(--accent-ink); }
.list-item.unread .list-icon { background: linear-gradient(140deg, #fff, var(--accent-pale)); color: var(--accent-deep); }

/* ── 信箱：一排信封，不是任务列表 ── */

.letter-row {
  position: relative;
  display: flex; align-items: center; gap: 14px;
  width: 100%;
  padding: 14px 16px;
  margin-bottom: 10px;
  border: none;
  border-radius: var(--r-card);
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--edge-soft), var(--shadow-soft);
  color: var(--ink); font: inherit; text-align: left;
  cursor: pointer; overflow: hidden;
  transition: transform var(--t-hover) var(--spring-soft),
              box-shadow var(--t-hover) var(--ease-out);
}
.letter-row:hover { transform: translateY(-2px); box-shadow: inset 0 0 0 1px var(--edge), var(--shadow-lift); }
.letter-row .env { width: 46px; height: 34px; flex: none; color: var(--tea-deep); }
/* .lr-title / .lr-sub 是两个 inline span，原来挤在同一行上：标题和预览首尾相接，
   预览一长就顶穿整行、盖到右边的时间上（overflow/ellipsis 写在 title 上，对 sub 没用）。
   母图的信箱是两行——上面是谁写的，下面是那句预览。改成列，两行各自省略。 */
.letter-row .lr-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.letter-row .lr-title {
  display: block; font-family: var(--font-display);
  font-size: 15px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.letter-row .lr-sub {
  display: block; font-size: 12px; color: var(--ink-mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.letter-row .lr-when { flex: none; font-size: 11px; color: var(--ink-mute); font-family: var(--font-mono); }

.letter-row.unopened {
  background: var(--surface-pink);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.75), var(--shadow-pink);
}
.letter-row.unopened .env { color: var(--accent-deep); }
.letter-row.unopened .lr-title { color: var(--accent-ink); font-weight: 600; }
.letter-row.unopened::after {              /* 折角 */
  content: "";
  position: absolute; top: 0; right: 0;
  width: 26px; height: 26px;
  background: linear-gradient(225deg, rgba(255,255,255,.92) 50%, transparent 50%);
  box-shadow: -1px 1px 3px rgba(160,120,130,.18);
}
.letter-row.unopened::before {             /* 极慢的浮光：未拆的信在轻轻发亮 */
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 32%, rgba(255,255,255,.55) 47%, transparent 62%);
  transform: translateX(-120%);
  animation: sheen-sweep 7.5s var(--ease-inout) infinite;
  pointer-events: none;
}
.letter-seal {
  position: absolute; left: 30px; top: 50%;
  width: 9px; height: 9px; border-radius: 50%;
  transform: translateY(-50%);
  background: radial-gradient(circle at 35% 30%, #fff, var(--accent-deep));
  box-shadow: 0 2px 6px var(--accent-glow);
}
.letter-row.treasured .env { color: var(--accent-deep); }
.letter-row .lr-star { flex: none; color: var(--accent-deep); }

/* 信纸：读信时是另一种材质 —— 更实、更暖、更像纸 */
.modal-letter {
  max-width: min(620px, 100%);
  background: linear-gradient(178deg, rgba(255,253,253,.96), rgba(252,246,247,.94));
  box-shadow: 0 30px 70px rgba(60,80,74,.24), inset 0 1px 0 rgba(255,255,255,.85);
}
.modal-letter .letter-head {
  display: flex; align-items: center; gap: 12px;
  padding-bottom: 12px; margin-bottom: 14px;
  border-bottom: 1px solid var(--hairline-pink);
}
.modal-letter .letter-title {
  font-family: var(--font-display);
  font-size: 19px; color: var(--ink); font-weight: 600;
}
.modal-letter .letter-meta { font-size: 12px; color: var(--ink-mute); margin-top: 2px; font-family: var(--font-mono); }
.modal-letter .letter-body {
  font-family: var(--font-letter);
  font-size: 15.5px;
  line-height: 2.05;
  color: #4A5450;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 52vh;
  overflow-y: auto;
  padding-right: 6px;
}
.modal-letter .letter-foot { display: flex; align-items: center; gap: 10px; margin-top: 18px; }
.letter-opening { animation: letter-open var(--t-panel) var(--spring-soft) both; }

/* 标签页 */
.tabs { display: flex; gap: 8px; margin-bottom: 12px; overflow-x: auto; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tab {
  flex: none;
  padding: 6px 15px;
  border: none;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.46);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink-soft);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: background var(--t-hover) var(--ease-out),
              color var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) var(--ease-out),
              transform var(--t-press) var(--spring-snap);
}
.tab:hover { background: rgba(255,255,255,.66); color: var(--ink); }
.tab:active { transform: scale(.96); }
.tab.active {
  color: var(--accent-ink);
  background: linear-gradient(96deg, var(--accent-pale), rgba(255,255,255,.6));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.75), 0 4px 12px var(--accent-glow);
}

/* 通用状态
   空/加载/出错三态本来是整个界面里唯一把字直接放在会动的海面上的地方——面板一空，
   底就没了，浪丝从"信箱是空的"中间穿过去。给它自己的一档材质（和右栏卡片同档），
   空屏才读得出是"这里现在什么都没有"，而不是"这里坏了/没渲染出来"。 */
.state {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  max-width: 420px;
  margin: 8px auto;
  padding: 40px 24px;
  border-radius: var(--r-panel);
  background: var(--surface-3);
  box-shadow: var(--shadow-lift), var(--inner-top);
  text-align: center;
  font-size: 13.5px;
  color: var(--ink-mute);
  line-height: 1.9;
  animation: fade-in var(--t-enter) var(--ease-out) both;
}
.state .i { width: 34px; height: 34px; color: var(--quartz-deep); opacity: .85; }
.state.error .i { color: #C08A94; }
.state-title { font-family: var(--font-display); font-size: 14.5px; color: var(--ink-soft); }

.loader { width: 26px; height: 26px; color: var(--accent-deep); animation: twirl 1.6s linear infinite; }
.skeleton {
  height: 14px;
  border-radius: 7px;
  background: linear-gradient(90deg, rgba(255,255,255,.35), rgba(255,255,255,.72), rgba(255,255,255,.35));
  background-size: 220% 100%;
  animation: shimmer 1.5s var(--ease-inout) infinite;
}

/* 表单控件 */
.field {
  width: 100%;
  padding: 10px 14px;
  border: none;
  border-radius: 14px;
  background: rgba(255,255,255,.58);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  outline: none;
  transition: box-shadow var(--t-hover) var(--ease-out), background var(--t-hover) var(--ease-out);
}
.field:focus { background: rgba(255,255,255,.76); box-shadow: inset 0 0 0 1px rgba(255,255,255,.9), 0 0 0 3px var(--accent-glow); }
textarea.field { resize: vertical; line-height: 1.7; }
select.field {
  appearance: none; cursor: pointer; padding-right: 34px;
  background-image: linear-gradient(45deg, transparent 50%, var(--tea-deep) 50%),
                    linear-gradient(135deg, var(--tea-deep) 50%, transparent 50%);
  background-position: calc(100% - 18px) 19px, calc(100% - 13px) 19px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

/* 按钮 */
/* [hidden] 必须压得住 .btn 的 display:inline-flex —— 见文件顶部第 2 条约定，
   .panel / .modal-mask / .msg-menu 都是同一个坑。少这一行，hidden 的按钮照样显示。 */
.btn[hidden] { display: none; }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 9px 20px;
  border: none;
  border-radius: var(--r-pill);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
  transition: transform var(--t-press) var(--spring-snap),
              box-shadow var(--t-hover) var(--ease-out),
              background var(--t-hover) var(--ease-out), filter var(--t-hover) var(--ease-out);
}
.btn:active { transform: scale(.96); }
.btn-accent {
  color: var(--accent-ink);
  font-weight: 600;
  background: linear-gradient(140deg, var(--accent-pale), var(--accent));
  box-shadow: 0 8px 20px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,.7);
}
.btn-accent:hover { filter: brightness(1.03); box-shadow: 0 12px 26px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,.85); }
.btn-accent:disabled { filter: saturate(.5) brightness(1.04); cursor: default; box-shadow: none; }
.btn-plain {
  color: var(--ink-soft);
  background: rgba(255,255,255,.55);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
}
.btn-plain:hover { background: rgba(255,255,255,.75); color: var(--ink); }
.btn-sm { padding: 6px 14px; font-size: 13px; }
.btn-row { display: flex; flex-wrap: wrap; gap: 10px; margin: 4px 0 6px; }
a.btn { text-decoration: none; }

/* ── 按下反馈：母图 Interaction 一栏规定的四态 ──────────────────
   Default / 悬停 / **点击 = 浅黄** / disabled = 灰。
   浅黄 (--pale-yellow #F3DEBA) 是母图色板里明确留给「小面积状态」的那一档，
   之前只用在一个头像状态点上，按下态整个没做——所以点任何东西都只有一个
   缩放，没有颜色回应。这里只在 :active 的一瞬给出，松手即恢复，面积不超过
   控件本身，不构成装饰。 */
.btn-accent:active {
  background: linear-gradient(140deg, var(--pale-yellow), var(--accent));
  box-shadow: 0 4px 12px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,.8);
}
.btn-plain:active { background: rgba(243,222,186,.62); color: var(--ink); }
.ghost-btn:active { transform: scale(.9); background: rgba(243,222,186,.55); color: var(--ink); }
.pill-icon:active { transform: scale(.88); background: rgba(243,222,186,.62); color: var(--accent-deep); }
.chip-close:active { background: rgba(243,222,186,.7); color: var(--ink); }

/* disabled：母图是一枚安静的灰胶囊，不是把主按钮调淡 */
.btn:disabled, .btn[disabled] {
  cursor: default;
  color: var(--ink-mute);
  background: rgba(226,230,228,.62);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.42);
  filter: none;
}
.btn:disabled:hover, .btn[disabled]:hover { filter: none; }

.hint { font-size: 12px; color: var(--ink-mute); line-height: 1.85; margin: 8px 2px; }

/* 设置行 / 分段控件 / 滑杆 */
.setting-row {
  display: flex; align-items: center; gap: 12px;
  width: 100%;
  padding: 12px 14px;
  border: none;
  border-radius: var(--r-card);
  background: rgba(255,255,255,.36);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink);
  font: inherit; font-size: 14px; text-align: left;
  cursor: pointer;
  margin-bottom: 8px;
  transition: background var(--t-hover) var(--ease-out), box-shadow var(--t-hover) var(--ease-out);
}
.setting-row:hover { background: rgba(255,255,255,.56); }
.setting-row.static { cursor: default; }
.setting-row.selected {
  background: linear-gradient(96deg, var(--accent-pale), rgba(255,255,255,.5));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.72), 0 4px 14px var(--accent-glow);
  color: var(--accent-ink);
}
.setting-row .i { color: var(--tea-deep); }
.setting-row.selected .i { color: var(--accent-deep); }
.setting-mid { flex: 1; min-width: 0; }
.setting-sub { font-size: 11.5px; color: var(--ink-mute); margin-top: 1px; }

.segmented {
  display: inline-flex; gap: 3px; padding: 3px;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.4);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
}
.segmented button {
  border: none; background: transparent; cursor: pointer;
  font: inherit; font-size: 12.5px; color: var(--ink-soft);
  padding: 5px 13px; border-radius: var(--r-pill);
  transition: background var(--t-hover) var(--ease-out), color var(--t-hover) var(--ease-out);
}
.segmented button.on {
  color: var(--accent-ink); font-weight: 600;
  background: linear-gradient(120deg, #fff, var(--accent-pale));
  box-shadow: 0 3px 10px var(--accent-glow);
}

/* AI 自主行为：一个行为一行。
   九个行为原本各占一张说明卡 + 一整行四档控件，桌面端要滚三屏才看得完，
   而九段结构完全一样的说明本身没有信息量。这里压成
   [名字] [今天 x/y · ≥Nh] [关闭|低|中|高]，说明折进行内。
   底、边、圆角、四档控件全部沿用 .setting-row / .segmented 的 token。 */
.prc-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  padding: 7px 12px;
  margin-bottom: 5px;
  border-radius: var(--r-card);
  background: rgba(255,255,255,.36);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
}
.prc-item.off { background: rgba(255,255,255,.2); }
.prc-name {
  display: flex; align-items: center; gap: 4px;
  min-width: 0;
  border: none; background: none; padding: 0;
  font: inherit; font-size: 13.5px; color: var(--ink); text-align: left;
  cursor: pointer;
}
.prc-name > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prc-name .prc-caret {
  flex: none; color: var(--tea-deep);
  transform: rotate(90deg);
  transition: transform var(--t-hover) var(--ease-out);
}
.prc-name[aria-expanded="true"] .prc-caret { transform: rotate(-90deg); }
.prc-stat {
  flex: none;
  font-size: 11.5px; color: var(--ink-mute);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.prc-item.off .prc-stat { opacity: .7; }
.prc-item .segmented { padding: 2px; }
.prc-item .segmented button { padding: 4px 10px; font-size: 12px; }
.prc-desc {
  grid-column: 1 / -1;
  margin: 2px 0 4px;
  font-size: 11.5px; line-height: 1.75; color: var(--ink-mute);
}

/* 手机：名字与状态一行、四档另起一行——仍然是一条紧凑行，不退回大卡片 */
@media (max-width: 560px) {
  .prc-item { grid-template-columns: minmax(0, 1fr) auto; row-gap: 6px; }
  .prc-item .segmented { grid-column: 1 / -1; justify-self: stretch; }
  .prc-item .segmented button { flex: 1; text-align: center; padding: 5px 4px; }
}

.member-card {
  padding: 16px;
  margin-bottom: 12px;
  border-radius: var(--r-card);
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--edge-soft), var(--shadow-soft);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.member-head { display: flex; align-items: center; gap: 10px; font-size: 15px; font-weight: 600; }

/* 成员卡内的两块：身份 / 运行底座。沿用既有 token，不引入新的视觉语言。 */
.sub-title {
  margin: 14px 2px 6px; font-size: 12px; font-weight: 600; letter-spacing: .06em;
  color: var(--ink-mute); display: flex; align-items: center; gap: 8px;
}
.sub-title::after {
  content: ""; flex: 1; height: 1px; background: var(--hairline);
}
.kv { display: flex; gap: 10px; padding: 3px 2px; font-size: 12.5px; line-height: 1.7; }
.kv-k { flex: 0 0 52px; color: var(--ink-mute); }
.kv-v { flex: 1; min-width: 0; color: var(--ink-soft); word-break: break-word; }
.kv-note { margin-left: 6px; color: var(--ink-mute); font-size: 11.5px; }
.state-dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 6px; vertical-align: 1px;
}
.state-dot.ok  { background: var(--tea-deep); }
.state-dot.bad { background: var(--quartz-ink); }
.rebind-confirm {
  margin-top: 8px; padding: 10px; border-radius: 12px;
  background: var(--surface-1); box-shadow: inset 0 0 0 1px var(--hairline-pink);
}
.member-head .btn { margin-left: auto; }

/* 头像历史 */
.avatar-hist { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 4px; }
.avatar-hist-item { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 62px; }
.avatar-hist-item .who { font-size: 10.5px; color: var(--ink-mute); text-align: center; line-height: 1.4; }
.avatar-hist-item.self .who { color: var(--accent-ink); }

/* 裁剪器 */
.cropper {
  position: relative;
  width: 100%; height: 300px;
  border-radius: var(--r-card);
  overflow: hidden;
  background: linear-gradient(160deg, #DDE7E2, #C6D5CE);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  touch-action: none;
  cursor: grab;
}
.cropper:active { cursor: grabbing; }
.cropper canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
.cropper-mask {
  position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(circle at center,
              transparent 0 calc(min(50%, 130px) - 1px),
              rgba(120,140,134,.45) calc(min(50%, 130px)));
}
.cropper-ring {
  position: absolute; left: 50%; top: 50%;
  width: min(100%, 260px); height: min(100%, 260px);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  box-shadow: 0 0 0 2px rgba(255,255,255,.9), 0 8px 30px rgba(60,80,74,.25);
  pointer-events: none;
}
.cropper-tools { display: flex; align-items: center; gap: 12px; margin-top: 14px; }
input[type="range"] {
  -webkit-appearance: none; appearance: none;
  flex: 1; height: 4px; border-radius: 3px;
  background: linear-gradient(90deg, var(--accent-deep), var(--accent-pale));
  outline: none;
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 18px; height: 18px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff, var(--accent));
  box-shadow: 0 2px 8px var(--accent-glow), inset 0 0 0 1px rgba(255,255,255,.8);
  cursor: pointer;
  transition: transform var(--t-press) var(--spring-snap);
}
input[type="range"]::-webkit-slider-thumb:active { transform: scale(1.15); }
input[type="range"]::-moz-range-thumb {
  width: 18px; height: 18px; border: none; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff, var(--accent));
  box-shadow: 0 2px 8px var(--accent-glow);
  cursor: pointer;
}

/* 主题 / 氛围选择块 */
.choice-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 10px; }
.choice {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 14px 10px 12px;
  border: none;
  border-radius: var(--r-card);
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink-soft);
  font: inherit; font-size: 13px;
  cursor: pointer; text-align: center;
  transition: background var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) var(--ease-out),
              transform var(--t-hover) var(--spring-soft);
}
.choice:hover { background: rgba(255,255,255,.64); transform: translateY(-2px); }
.choice.selected {
  color: var(--accent-ink);
  box-shadow: inset 0 0 0 1.5px var(--accent-deep), 0 6px 18px var(--accent-glow);
  background: rgba(255,255,255,.66);
}
.choice-swatch {
  width: 62px; height: 62px; border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.62), 0 4px 12px rgba(60,80,74,.10);
  transition: transform var(--t-hover) var(--spring-soft),
              box-shadow var(--t-hover) var(--ease-out);
}
.choice:hover .choice-swatch { transform: scale(1.05); }
.choice.selected .choice-swatch {
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.7),
              0 0 0 2px var(--accent-deep), 0 6px 16px var(--accent-glow);
}
.choice-name { display: flex; align-items: center; justify-content: center; gap: 6px; }
.choice.selected .choice-name::after {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent-deep);
  animation: check-in var(--t-spring) var(--spring-snap);
}

/* 自定主题：种子色 + 几个起点 */
#seedBox { margin-top: 10px; }
input[type="color"] {
  width: 44px; height: 30px; padding: 0;
  border: none; border-radius: 10px;
  background: transparent; cursor: pointer;
  box-shadow: inset 0 0 0 1px var(--edge), 0 4px 12px var(--accent-glow);
}
input[type="color"]::-webkit-color-swatch-wrapper { padding: 3px; }
input[type="color"]::-webkit-color-swatch { border: none; border-radius: 8px; }
input[type="color"]::-moz-color-swatch { border: none; border-radius: 8px; }
.seed-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 2px 2px; }
.seed-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px 5px 6px;
  border: none; border-radius: var(--r-pill);
  background: var(--surface-1);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink-soft); font: inherit; font-size: 12px;
  cursor: pointer;
  transition: background var(--t-hover) var(--ease-out),
              transform var(--t-press) var(--spring-snap);
}
.seed-chip span {
  width: 16px; height: 16px; border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.7);
}
.seed-chip:hover { background: rgba(255,255,255,.55); transform: translateY(-1px); }
.seed-chip:active { transform: scale(.94); }

/* 海面高级项：默认收起，"跟随"状态的滑杆压淡，一眼看出它不是手动定的 */
.adv { margin: 2px 0 6px; }
.adv > summary {
  list-style: none; cursor: pointer;
  padding: 6px 2px; font-size: 12px; color: var(--ink-mute);
  display: flex; align-items: center; gap: 6px;
}
.adv > summary::-webkit-details-marker { display: none; }
.adv > summary::before { content: "▸"; font-size: 10px; transition: transform var(--t-hover) var(--ease-out); }
.adv[open] > summary::before { transform: rotate(90deg); }
.adv > summary:hover { color: var(--accent-ink); }
.adv input[type="range"].auto { opacity: .5; }
.adv .ghost-btn { font-size: 11px; padding: 4px 9px; }
.adv .ghost-btn:disabled { opacity: .35; cursor: default; }

/* ══════════ 记忆页 ══════════ */

.mem-section { margin-bottom: 22px; }
.mem-section-title {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-display);
  font-size: 15px; font-weight: 600;
  color: var(--accent-ink);
  margin: 0 2px 10px;
}
.mem-section-title .i { width: 15px; height: 15px; color: var(--accent-deep); }
.mem-section-count { margin-left: auto; font-size: 11px; font-weight: 400; color: var(--ink-mute); font-family: var(--font-mono); }

.mem-narrative {
  font-family: var(--font-letter);
  font-size: 14px;
  line-height: 2;
  color: var(--ink);
  white-space: pre-wrap; word-break: break-word;
  background: var(--surface-pink);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.65), var(--shadow-soft);
  border-radius: var(--r-card);
  padding: 15px 17px;
  margin-bottom: 10px;
}

.mem-item {
  padding: 12px 14px;
  margin-bottom: 8px;
  border-radius: var(--r-card);
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  transition: background var(--t-hover) var(--ease-out), transform var(--t-hover) var(--spring-soft);
}
.mem-item:hover { background: rgba(255,255,255,.6); transform: translateX(2px); }
.mem-head { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
.mem-content { flex: 1; min-width: 0; font-size: 14px; line-height: 1.8; white-space: pre-wrap; word-break: break-word; }
.mem-time { flex: none; font-size: 11px; color: var(--ink-mute); font-family: var(--font-mono); }

.mem-detail { margin-top: 8px; font-size: 12px; color: var(--ink-mute); font-family: var(--font-mono); }
.mem-detail summary {
  display: inline-flex; align-items: center; gap: 5px;
  cursor: pointer; user-select: none; list-style: none; color: var(--ink-mute);
}
.mem-detail summary::-webkit-details-marker { display: none; }
.mem-detail summary::before { content: "▸"; font-size: 10px; transition: transform var(--t-hover) var(--ease-out); }
.mem-detail[open] summary::before { transform: rotate(90deg); }
.mem-detail summary:hover { color: var(--accent-ink); }
.mem-detail-body {
  margin-top: 8px; padding: 10px 12px;
  border-radius: 12px;
  background: rgba(255,255,255,.5);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  line-height: 1.85; word-break: break-word;
}

/* ══════════ 开发模式 / proposal ══════════ */

.dev-card {
  align-self: stretch;
  margin: 2px 0 4px;
  padding: 16px 18px;
  border-radius: var(--r-panel);
  background: linear-gradient(160deg, rgba(255,255,255,.7), rgba(255,255,255,.5));
  box-shadow: inset 0 0 0 1px var(--edge), var(--shadow-lift);
  animation: card-in var(--t-panel) var(--spring-soft) both;
}
.dev-card-title {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-display);
  font-size: 15px; font-weight: 600; color: var(--ink);
  margin-bottom: 8px;
}
.dev-card-title .i { color: var(--accent-deep); }
.dev-card-row { font-size: 13px; color: var(--ink-soft); line-height: 1.85; word-break: break-word; }
.dev-card-row b { color: var(--ink); font-weight: 600; }
.dev-card .risk-low { color: #6E8C72; }
.dev-card .risk-medium { color: #A8894A; }
.dev-card .risk-high { color: #B4737E; }
.dev-card-actions { display: flex; gap: 10px; margin-top: 14px; flex-wrap: wrap; }
.dev-card-meta {
  margin-top: 10px; font-size: 11.5px; color: var(--ink-mute);
  display: flex; align-items: center; gap: 6px; font-family: var(--font-mono);
}

/* 母图的按钮分三档：主(粉) / 次(茶绿) / 轻(白描边)。我们一直只有主和轻，
   于是「做一件事」和「关掉」并排时长得一模一样，分不出哪个是动作。
   茶绿这一档其实早就存在，只是叫 .btn-approve、只服务开发需求确认、
   而且写死了两个色板外的 hex。这里把它升成通用的次按钮档。
   分工：主 = 唯一提交动作；次 = 真的会做一件事的次要动作；轻 = 关掉/取消。 */
.btn-tea, .btn-approve {
  color: var(--tea-ink); font-weight: 600;
  /* 母图「次按钮」实测 #C3C5BC —— 比茶绿主色 --tea(#A7B8A3) 浅一档，不是主色直接铺 */
  background: linear-gradient(140deg, var(--tea-mist), var(--tea-pale));
  box-shadow: 0 8px 20px rgba(139,156,134,.35), inset 0 1px 0 rgba(255,255,255,.6);
}
.btn-tea:hover, .btn-approve:hover { filter: brightness(1.04); }
.btn-tea:active, .btn-approve:active { background: linear-gradient(140deg, var(--pale-yellow), var(--tea-pale)); }
.btn-tea:disabled, .btn-approve:disabled { filter: saturate(.4) brightness(1.05); cursor: default; box-shadow: none; }
/* 母图的 主(粉)/次(茶绿) 前提是主色为粉。茶绿主题下 --accent 本身就是茶绿，
   次按钮再用茶绿就和主按钮撞成同一族，只剩深浅之差 —— 比它原来是白色的时候还难分。
   母图没有茶绿主题，仲裁不了这一格，所以这里**不擅自另选一个色**：
   茶绿主题下次按钮退回轻按钮的白底，等 owner 定这一格该是什么颜色。 */
[data-theme="tea"] .btn-tea {
  color: var(--ink-soft); font-weight: inherit;
  background: rgba(255,255,255,.55);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
}
[data-theme="tea"] .btn-tea:hover { filter: none; background: rgba(255,255,255,.75); color: var(--ink); }
[data-theme="tea"] .btn-tea:active { background: rgba(243,222,186,.62); color: var(--ink); }

.badge {
  flex: none;
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px;
  padding: 2px 10px;
  border-radius: var(--r-pill);
  white-space: nowrap;
  background: rgba(255,255,255,.62);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink-soft);
}
.badge::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.badge.discussing, .badge.done { color: #5D7B85; }
.badge.awaiting_approval, .badge.pending, .badge.claimed, .badge.running, .badge.in_progress { color: #A0854B; }
.badge.approved, .badge.ticket_created, .badge.succeeded { color: #5F7F63; }
.badge.failed, .badge.needs_human, .badge.failed_needs_human { color: #B4737E; }
.badge.cancelled { color: var(--ink-mute); }

.studio-thread {
  display: block; width: 100%; text-align: left;
  padding: 14px 16px; margin-bottom: 10px;
  border: none; border-radius: var(--r-card);
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink); font: inherit; cursor: pointer;
  transition: background var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) var(--ease-out),
              transform var(--t-hover) var(--spring-soft);
}
.studio-thread:hover { background: rgba(255,255,255,.64); transform: translateY(-1px); box-shadow: var(--shadow-soft); }
.studio-thread-top { display: flex; justify-content: space-between; gap: 10px; align-items: center; }
.studio-thread-title { font-size: 14px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.studio-thread-meta { display: block; font-size: 11.5px; color: var(--ink-mute); margin-top: 5px; }

/* 成本 */
.cost-total {
  padding: 16px 18px;
  border-radius: var(--r-card);
  background: var(--surface-pink);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.65);
  font-size: 14px;
}
.cost-total b { display: block; font-size: 26px; color: var(--accent-ink); line-height: 1.5; font-family: var(--font-mono); }
.data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.data-table th, .data-table td { padding: 9px 10px; text-align: left; border-bottom: 1px solid var(--hairline); }
.data-table th { color: var(--ink-mute); font-weight: 500; font-size: 12px; border-bottom-color: var(--hairline-pink); }
.data-table td:last-child { font-family: var(--font-mono); }
.data-table tr:last-child td { border-bottom: none; }

/* ══════════ 弹窗 / 菜单 / toast ══════════ */

.modal-mask {
  position: fixed; inset: 0; z-index: 60;
  /* 弹窗开着的时候底下那层要真的退下去；.36 压不住聊天正文（见 --surface-4 的注释） */
  background: rgba(150,170,164,.55);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  animation: fade-in var(--t-enter) var(--ease-out);
}
.modal-mask[hidden] { display: none; }

.modal {
  width: min(440px, 100%);
  max-height: 86vh;
  overflow-y: auto;
  padding: 24px;
  border-radius: var(--r-panel);
  background: var(--surface-4);
  border: 1px solid var(--edge);
  box-shadow: 0 30px 70px rgba(60,80,74,.22), inset 0 1px 0 rgba(255,255,255,.72);
  animation: modal-in var(--t-panel) var(--spring-soft) both;
}
.modal-sm { text-align: center; }
.profile-id { display: flex; align-items: center; justify-content: center; gap: 8px; margin: 2px 0 12px; }
.profile-id-name { font-family: var(--font-display); font-size: 16px; color: var(--ink); }
.modal-title { font-family: var(--font-display); font-size: 17px; font-weight: 600; margin-bottom: 12px; }
.modal-hint { font-size: 12.5px; color: var(--ink-mute); margin: 10px 0; line-height: 1.85; }
.modal-actions { display: flex; gap: 10px; margin-top: 18px; justify-content: center; flex-wrap: wrap; }
.modal-reader { max-width: min(600px, 100%); display: flex; flex-direction: column; }
.reader-meta { font-size: 12px; color: var(--ink-mute); margin: -4px 0 14px; font-family: var(--font-mono); }
.reader-content {
  flex: 1; overflow-y: auto;
  white-space: pre-wrap;
  font-family: var(--font-letter);
  font-size: 15px; line-height: 1.95;
  text-align: left;
}
.reader-content img { max-width: 100%; border-radius: 14px; }
/* 母图的个人中心里，退出登录是一枚圆按钮 + 一行小标签，和「切换身份/夜间模式」并排；
   我们只有这一项，所以不硬凑三枚，但至少要是个按钮，不是飘在弹窗底下的一行裸链接。 */
.logout-link {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 18px; padding: 9px 18px;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.5);
  box-shadow: var(--inner-top), inset 0 0 0 1px var(--edge-soft);
  font-size: 12.5px; color: var(--ink-mute); text-decoration: none;
  transition: background var(--t-hover) var(--ease-out), color var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) var(--ease-out);
}
.logout-link .i { width: 15px; height: 15px; }
.logout-link:hover {
  color: var(--accent-ink); background: var(--accent-mist);
  box-shadow: var(--inner-top), inset 0 0 0 1px var(--accent-line);
}

.kind-tabs { display: flex; gap: 8px; margin-bottom: 14px; }
.kind-tab {
  flex: 1; padding: 9px 0;
  border: none; border-radius: var(--r-pill);
  background: rgba(255,255,255,.55);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  color: var(--ink-soft); font: inherit; font-size: 13.5px; cursor: pointer;
  transition: background var(--t-hover) var(--ease-out), color var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) var(--ease-out);
}
.kind-tab.active {
  color: var(--accent-ink); font-weight: 600;
  background: linear-gradient(96deg, var(--accent-pale), rgba(255,255,255,.65));
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.8), 0 4px 14px var(--accent-glow);
}

.roster-pick { display: flex; flex-direction: column; gap: 8px; }
.pick-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 14px;
  border-radius: var(--r-card);
  background: rgba(255,255,255,.5);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
  cursor: pointer;
  transition: background var(--t-hover) var(--ease-out);
}
.pick-row:hover { background: rgba(255,255,255,.72); }
.pick-row input { margin-left: auto; accent-color: var(--accent-deep); width: 17px; height: 17px; }
.pick-name { font-size: 14px; }

.msg-menu {
  position: fixed; z-index: 200;
  min-width: 172px; padding: 6px;
  border-radius: var(--r-card);
  background: rgba(255,255,255,.94);
  border: 1px solid var(--edge);
  box-shadow: 0 18px 40px rgba(60,80,74,.2);
  animation: modal-in var(--t-enter) var(--spring-snap) both;
}
.msg-menu[hidden] { display: none; }
.msg-menu button {
  display: flex; align-items: center; gap: 8px;
  width: 100%; padding: 9px 12px;
  border: none; border-radius: 12px;
  background: none; color: var(--ink);
  font: inherit; font-size: 13.5px; text-align: left; cursor: pointer;
  transition: background var(--t-hover) var(--ease-out), color var(--t-hover) var(--ease-out);
}
.msg-menu button:hover { background: var(--accent-pale); color: var(--accent-ink); }

.toast {
  position: fixed;
  left: 50%; bottom: calc(96px + env(safe-area-inset-bottom));
  transform: translateX(-50%) translateY(8px);
  max-width: min(420px, 88vw);
  padding: 10px 18px;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.94);
  box-shadow: 0 14px 34px rgba(60,80,74,.2), inset 0 0 0 1px var(--edge);
  color: var(--ink);
  font-size: 13px; text-align: center;
  z-index: 90;
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-enter) var(--ease-out), transform var(--t-enter) var(--spring-soft);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* 偶尔出现的小惊喜：一枚很淡的星芒，飘一下就没了 */
.spark {
  position: fixed; z-index: 70;
  width: 18px; height: 18px;
  color: var(--accent);
  pointer-events: none;
  opacity: 0;
  animation: spark-float 2.6s var(--ease-out) forwards;
}
.spark svg { width: 100%; height: 100%; fill: currentColor; }

/* ══════════ 登录页 ══════════ */

.login-wrap { height: 100%; display: flex; align-items: center; justify-content: center; padding: 24px; position: relative; z-index: 1; }
.login-card {
  position: relative;
  width: min(380px, 100%);
  padding: 42px 34px 34px;
  border-radius: 30px;
  text-align: center;
  background: var(--surface-3);
  border: 1px solid var(--edge);
  box-shadow: var(--shadow-panel);
  overflow: hidden;
  animation: card-in var(--t-panel) var(--spring-soft) both;
}
.login-logo {
  font-family: var(--font-brand);
  font-size: 34px;
  line-height: 1.3;
  color: var(--quartz-ink);
  text-shadow: 0 1px 0 rgba(255,255,255,.85);
  margin-bottom: 4px;
}
.login-title { font-family: var(--font-display); font-size: 14px; color: var(--ink-mute); letter-spacing: 2px; margin-bottom: 26px; }
.login-card .field { text-align: center; letter-spacing: 3px; margin-bottom: 16px; }
.login-card .btn { width: 100%; letter-spacing: 4px; }
.login-error { min-height: 22px; margin-top: 12px; font-size: 12.5px; color: #B4737E; }
.login-ornament {
  position: absolute; right: -18px; bottom: -20px;
  width: 120px; height: 120px; color: var(--quartz);
  opacity: calc(.55 * var(--deco)); pointer-events: none;
}
.login-ornament svg { width: 100%; height: 100%; }

/* ══════════ 动效 ══════════ */

@keyframes msg-in { from { opacity: 0; transform: translateY(10px) scale(.985); } to { opacity: 1; transform: none; } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes panel-in { from { opacity: 0; transform: translateY(12px) scale(.995); } to { opacity: 1; transform: none; } }
@keyframes modal-in { from { opacity: 0; transform: translateY(14px) scale(.97); } to { opacity: 1; transform: none; } }
@keyframes card-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes chip-in { from { opacity: 0; transform: translateY(4px) scale(.9); } to { opacity: 1; transform: none; } }
@keyframes check-in { from { opacity: 0; transform: scale(.4); } to { opacity: 1; transform: scale(1); } }
@keyframes badge-pop { 0% { transform: scale(1); } 45% { transform: scale(1.22); } 100% { transform: scale(1); } }
@keyframes nav-mark { from { height: 0; } to { height: 18px; } }
@keyframes blink { 0%, 65%, 100% { opacity: .25; } 32% { opacity: 1; } }
@keyframes dot-breathe { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .55; transform: scale(.82); } }
@keyframes twirl { to { transform: rotate(360deg); } }
@keyframes twinkle { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .55; transform: scale(.86); } }
@keyframes shimmer { from { background-position: 120% 0; } to { background-position: -20% 0; } }
@keyframes sheen-sweep {
  0% { transform: translateX(-120%); }
  55%, 100% { transform: translateX(120%); }
}
@keyframes letter-open {
  from { opacity: 0; transform: translateY(18px) scale(.94) rotateX(8deg); }
  to { opacity: 1; transform: none; }
}
@keyframes sheet-up { from { transform: translateY(102%); } to { transform: none; } }
@keyframes spark-float {
  0% { opacity: 0; transform: translateY(0) scale(.4) rotate(0deg); }
  25% { opacity: .95; transform: translateY(-10px) scale(1) rotate(25deg); }
  100% { opacity: 0; transform: translateY(-42px) scale(.6) rotate(70deg); }
}

/* ══════════ 响应式：Desktop / 平板 / 手机是三套排布 ══════════ */

/* ══════════ 侧栏 / 右栏的可读性 ══════════
   中央聊天区现在有自己的纯色底，字好读；左右两侧还骑在海面上，同一套 --ink
   在那边偏浅。这里只在这两块里把文字再压深一档，并把玻璃底从 .38/.28 抬到
   .50/.40（"轻微增强"：海仍然透得过来，不是糊死）。中央不受影响。 */
.sidebar, .rail {
  --ink:      #212D29;
  --ink-soft: #2C3A35;
  --ink-mute: #3A4842;
  /* 导航图标 / 会话小标签 / 底栏按钮那一档全走 --tea-deep(#8B9C86)，在这层玻璃上
     只有 2.8:1。这里只在这两块里重定义这个 token，hover / active 的覆盖顺序不变。 */
  --tea-deep: #55684F;
}
.sidebar { background: linear-gradient(178deg, rgba(255,255,255,.50), rgba(255,255,255,.40)); }
.rail .card { background: linear-gradient(178deg, rgba(255,255,255,.50), rgba(255,255,255,.40)); }
.rail .card.now { background: linear-gradient(150deg, rgba(255,255,255,.42), rgba(244,226,229,.74)); }
.rail .stat-row { background: rgba(255,255,255,.44); }
/* 时间、次级说明、状态词：--ink-mute 里最容易糊掉的一批，再硬一档 */
.sidebar .session-time,
.sidebar .session-prev,
.rail .mini-sub,
.rail .person-state,
.rail .card-sub { color: #35433E; }

/* ══════════ 图片 / 视频背景下的裸字 ══════════
   判据是中央自己的 data-chat-bg —— 和左右 Ocean 的状态无关。
   聊天背景换成照片或视频之后，中央区里"自己没有底"的那几处会直接压在画面上：
   顶栏标题与状态、日期分隔、发信人、时间戳、以及那排模式 pill 和输入区。
   这里不往背景上叠白雾（那样等于把用户挑的图糊掉一层），而是让每个元素**各自**
   带一小块底：本来就有玻璃底的加厚一档，本来是裸字的补一块贴着字形的浅底。
   只在这两种背景下生效，海面 / 安静水面两档一个像素都不变；配色也不变——
   全部是白色 alpha，没有引入任何新色相。 */
body[data-chat-bg="image"] .chat-title,
body[data-chat-bg="video"] .chat-title,
body[data-chat-bg="image"] .chat-status,
body[data-chat-bg="video"] .chat-status,
body[data-chat-bg="image"] .day-divider,
body[data-chat-bg="video"] .day-divider,
body[data-chat-bg="image"] .msg-sender,
body[data-chat-bg="video"] .msg-sender,
body[data-chat-bg="image"] .msg-time,
body[data-chat-bg="video"] .msg-time {
  /* 收成 inline 级别才会贴着字宽，而不是撑满整行变成一条横带 */
  display: inline-block;
  max-width: 100%;
  border-radius: var(--r-pill);
  background: rgba(255,255,255,.70);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
}
body[data-chat-bg="image"] .header-info,
body[data-chat-bg="video"] .header-info {
  display: flex; flex-direction: column; align-items: flex-start;
}
/* 这两个本来就是 flex（状态点 / 两条细线），保持 flex 才不会散架 */
body[data-chat-bg="image"] .chat-status,
body[data-chat-bg="video"] .chat-status,
body[data-chat-bg="image"] .day-divider,
body[data-chat-bg="video"] .day-divider { display: inline-flex; align-items: center; }
body[data-chat-bg="image"] .chat-title,
body[data-chat-bg="video"] .chat-title { padding: 1px 10px; }
body[data-chat-bg="image"] .chat-status,
body[data-chat-bg="video"] .chat-status { padding: 1px 9px; margin-top: 2px; }
body[data-chat-bg="image"] .day-divider,
body[data-chat-bg="video"] .day-divider { padding: 3px 12px; margin: 5px 0 2px; }
body[data-chat-bg="image"] .msg-sender,
body[data-chat-bg="video"] .msg-sender { padding: 0 8px; }
body[data-chat-bg="image"] .msg-time,
body[data-chat-bg="video"] .msg-time { padding: 0 8px; opacity: 1; }
/* 发信人/时间在 .msg-body 这根 column flex 里默认 stretch，会拉满整行。
   只收这两个自己——动 .msg-body 的 align-items 会连气泡宽度一起改。 */
body[data-chat-bg="image"] .msg-sender,
body[data-chat-bg="video"] .msg-sender,
body[data-chat-bg="image"] .msg-time,
body[data-chat-bg="video"] .msg-time { align-self: flex-start; }
body[data-chat-bg="image"] .msg-row.user .msg-time,
body[data-chat-bg="video"] .msg-row.user .msg-time { align-self: flex-end; }

/* 顶栏那三颗图标本来是全透明的，直接把 hover 那一档的玻璃提成常驻 */
body[data-chat-bg="image"] .chat-header .ghost-btn,
body[data-chat-bg="video"] .chat-header .ghost-btn {
  background: rgba(255,255,255,.62);
  box-shadow: inset 0 0 0 1px var(--edge-soft);
}

/* 下面这些本来就有玻璃底，只是在照片上太薄——各加厚一档，不改颜色 */
body[data-chat-bg="image"] .mode-pill,
body[data-chat-bg="video"] .mode-pill { background: rgba(255,255,255,.74); }
body[data-chat-bg="image"] .mode-pill:hover,
body[data-chat-bg="video"] .mode-pill:hover { background: rgba(255,255,255,.88); }
body[data-chat-bg="image"] .chip,
body[data-chat-bg="video"] .chip {
  background: linear-gradient(120deg, rgba(255,255,255,.86), var(--accent-mist));
}
body[data-chat-bg="image"] .space-note,
body[data-chat-bg="video"] .space-note { background: rgba(255,255,255,.84); }
body[data-chat-bg="image"] .input-pill,
body[data-chat-bg="video"] .input-pill {
  background: linear-gradient(180deg, rgba(255,255,255,.82), rgba(255,255,255,.74));
}
body[data-chat-bg="image"] .input-pill:focus-within,
body[data-chat-bg="video"] .input-pill:focus-within {
  background: linear-gradient(180deg, rgba(255,255,255,.90), rgba(255,255,255,.82));
}

@media (max-width: 1279px) {
  .rail { display: none; }
  .rail.open {
    display: flex;
    position: fixed;
    top: var(--gap); right: var(--gap); bottom: var(--gap);
    width: min(330px, calc(100vw - 28px));
    z-index: 45;
    gap: 0;
    padding: 8px 12px 12px;
    border-radius: var(--r-panel);
    background: linear-gradient(178deg, rgba(255,255,255,.96), rgba(255,255,255,.91));
    border: 1px solid var(--edge);
    box-shadow: 0 24px 60px rgba(60,80,74,.24), inset 0 1px 0 rgba(255,255,255,.6);
    overflow-y: auto;
    animation: panel-in var(--t-panel) var(--spring-soft) both;
  }
  .rail.open .card { background: none; border: none; box-shadow: none; padding: 14px 4px; animation: none; }
  .rail.open .card + .card { border-top: 1px solid var(--hairline); }
  .rail-btn { display: inline-flex; }
  body.rail-collapsed .rail { width: min(330px, calc(100vw - 28px)); }
  body.rail-collapsed .rail .card { display: block; }
  body.rail-collapsed .rail .rail-strip { display: none; }
}
@media (min-width: 1280px) { .rail-btn { display: none; } }

@media (max-width: 1080px) and (min-width: 861px) {
  :root { --side-w: 228px; }
  .sidebar { padding: 18px 12px 12px; }
  .brand { font-size: 23px; padding-bottom: 12px; }
  .avatar-xl { width: 54px; height: 54px; font-size: 25px; }
  .tagline { display: none; }
}

/* ── 手机：聊天本体优先，其他都收进抽屉 / bottom sheet ── */
@media (max-width: 860px) {
  :root { --gap: 10px; }
  .app { padding: 0; gap: 0; }

  .sidebar {
    position: fixed;
    top: 8px; bottom: 8px; left: 8px;
    width: min(300px, 84vw);
    transform: translateX(calc(-100% - 16px));
    transition: transform var(--t-panel) var(--spring-soft);
    box-shadow: 0 24px 60px rgba(60,80,74,.26), inset 0 1px 0 rgba(255,255,255,.5);
    background: linear-gradient(178deg, rgba(255,255,255,.96), rgba(255,255,255,.91));
  }
  .sidebar > .ocean > .ocean-glass {
    background: linear-gradient(178deg, rgba(255,255,255,.96), rgba(255,255,255,.91));
  }
  .sidebar.open { transform: none; }

  .scrim {
    position: fixed; inset: 0; z-index: 15;
    background: rgba(118,142,136,.42);
    opacity: 0; pointer-events: none;
    transition: opacity var(--t-panel) var(--ease-out);
  }
  .scrim.show { opacity: 1; pointer-events: auto; }

  .menu-btn { display: inline-flex; }

  .chat-header {
    padding: calc(8px + env(safe-area-inset-top)) 10px 10px;
    gap: 10px;
    background: linear-gradient(180deg, rgba(255,255,255,.42), rgba(255,255,255,0));
  }
  .chat-bg { border-radius: 0; box-shadow: none; }
  .chat-title { font-size: 16px; }
  .chat-messages { padding: 2px 12px 12px; gap: 12px; }
  .msg-row { max-width: 84%; }
  .msg-row .avatar { width: 34px; height: 34px; font-size: 16px; }
  .bubble { font-size: 15px; padding: 10px 14px; }
  .space-card { max-width: 88%; }

  .chat-footer {
    padding: 0 10px calc(8px + env(safe-area-inset-bottom));
    background: linear-gradient(180deg, rgba(255,255,255,0), rgba(255,255,255,.3) 40%);
  }
  .composer { gap: 6px; padding-bottom: 7px; }
  .mode-pill { padding: 5px 12px; font-size: 12px; }
  .chat-input-bar { gap: 9px; }
  .input-pill { padding: 5px 6px 5px 14px; border-radius: 24px; }
  .input-pill textarea { font-size: 16px; padding: 7px 2px; }  /* iOS 聚焦不缩放 */
  .send-btn { width: 46px; height: 46px; }
  .send-btn .i { width: 21px; height: 21px; }
  .pill-icon { width: 32px; height: 32px; }

  .panel {
    top: 0; right: 0; bottom: 0; left: 0;
    border-radius: 0; border: none;
    background: linear-gradient(178deg, rgba(255,255,255,.94), rgba(255,255,255,.88));
  }
  .panel-body { padding: 14px 14px calc(24px + env(safe-area-inset-bottom)); }

  /* 右栏在手机上从下面推上来（bottom sheet），不是右侧浮层 */
  .rail.open {
    top: auto; left: 0; right: 0; bottom: 0;
    width: 100%;
    max-height: 76vh;
    padding: 10px 14px calc(18px + env(safe-area-inset-bottom));
    border-radius: 26px 26px 0 0;
    border: none;
    box-shadow: 0 -18px 50px rgba(60,80,74,.24);
    animation: sheet-up var(--t-panel) var(--spring-soft) both;
  }
  .rail.open::before {
    content: "";
    display: block; width: 42px; height: 4px; border-radius: 3px;
    background: var(--hairline-pink); margin: 2px auto 8px;
  }
  .rail.open .rail-strip { display: none; }

  .modal { padding: 20px; }
  .toast { bottom: calc(104px + env(safe-area-inset-bottom)); }
  .choice-grid { grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); }
  .cropper { height: 260px; }
}

/* ══════════ 手机底部导航（母图手机版就是这条）══════════
   桌面端不存在：宽屏走左侧 .nav，手机走这条。两边共用 .nav-item 的 active 逻辑。 */
.tabbar { display: none; }

@media (max-width: 860px) {
  :root { --tabbar-h: 60px; }

  .tabbar {
    position: fixed; left: 0; right: 0; bottom: 0;
    z-index: 58;                       /* 在面板/右栏之上、弹窗之下：任何时候都点得到 */
    display: flex; align-items: flex-start; justify-content: space-around;
    height: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
    padding: 7px 6px env(safe-area-inset-bottom);
    background: linear-gradient(180deg, rgba(255,255,255,.88), rgba(255,255,255,.96));
    border-top: 1px solid var(--hairline);
    box-shadow: 0 -10px 30px rgba(60,80,74,.10);
  }
  .tabbar .nav-item {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; margin: 0; padding: 4px 2px;
    height: 46px;                      /* 触控目标不低于 44 */
    border: none; background: none; box-shadow: none;
    color: var(--ink-mute); position: relative;
  }
  .tabbar .nav-item .i { width: 21px; height: 21px; }
  .tab-label { font-size: 10.5px; line-height: 1; }
  .tabbar .nav-item.active { color: var(--accent-ink); background: none; }
  .tabbar .nav-item.active .i { transform: translateY(-1px); }
  .tabbar .nav-item:active { transform: scale(.94); }
  .tab-badge {
    position: absolute; top: 1px; left: 50%; margin-left: 5px;
    min-width: 15px; height: 15px; padding: 0 4px;
    border-radius: 8px;
    background: var(--accent-deep); color: #fff;
    font-size: 10px; line-height: 15px; text-align: center;
    box-shadow: 0 2px 6px var(--accent-glow);
  }

  /* 中间那颗：母图里手机版正中的粉晶罗盘，点开「此刻」 */
  .tab-orb {
    flex: none; width: 54px; height: 54px; margin-top: -14px;
    display: inline-flex; align-items: center; justify-content: center;
    border: none; border-radius: 50%;
    color: var(--accent-ink);
    background: radial-gradient(circle at 34% 30%, #fff 4%, var(--accent-mist) 46%, var(--accent) 100%);
    box-shadow: inset 0 0 0 1px rgba(255,255,255,.75),
                0 8px 22px var(--accent-glow), 0 2px 6px rgba(60,80,74,.12);
    position: relative; cursor: pointer;
  }
  .tab-orb .i { width: 22px; height: 22px; position: relative; z-index: 1; }
  .tab-orb .orb-ring {
    position: absolute; inset: -5px; width: auto; height: auto;
    opacity: .5; color: #fff; pointer-events: none;
    animation: orb-turn 46s linear infinite;
  }
  .tab-orb:active { transform: scale(.93); }

  /* 给底部导航让位：输入区、面板、右栏都要抬起来 */
  .chat-footer { padding-bottom: calc(var(--tabbar-h) + 8px + env(safe-area-inset-bottom)); }
  .panel-body { padding-bottom: calc(var(--tabbar-h) + 24px + env(safe-area-inset-bottom)); }
  .rail.open { padding-bottom: calc(var(--tabbar-h) + 16px + env(safe-area-inset-bottom)); }
  .toast { bottom: calc(var(--tabbar-h) + 22px + env(safe-area-inset-bottom)); }
  .sidebar { bottom: calc(var(--tabbar-h) + 8px + env(safe-area-inset-bottom)); }

  /* 手机上一律不小于 32：拇指点得中 */
  .round-btn { width: 32px; height: 32px; }
  .foot-btn { min-width: 34px; min-height: 34px; }
}

@keyframes orb-turn { to { transform: rotate(360deg); } }

@media (max-width: 400px) {
  .stat-value { font-size: 14px; }
  .msg-row { max-width: 90%; }
}

/* 系统级降噪：跟设置里的"动效强度"是并集，谁更保守听谁的 */
@media (prefers-reduced-motion: reduce) {
  .atm-caustic, .atm-swell, .atm-sheen, .atm-depth { animation: none !important; }
  .letter-row.unopened::before, .letter-hint::after, .space-card.letter.unopened::before { animation: none !important; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}
