/* 诗诗 H5 —— shadcn/ui + assistant-ui 风格，原生 CSS，ES2019 安全 */
/* hidden 兜底: 本文件里大量用 id 选择器设 display, 会盖过 UA 的 [hidden]{display:none}。
   缺这一行 → 设置过的 display 元素永远藏不住(onboard 会盖住全屏, scroll-button/emoji-bar 常驻)。 */
[hidden] { display: none !important; }

:root {
  --background: 40 20% 97%;
  --foreground: 240 10% 3.9%;
  --card: 0 0% 100%;
  --card-foreground: 240 10% 3.9%;
  --popover: 0 0% 100%;
  --popover-foreground: 240 10% 3.9%;
  --primary: 342 78% 64%;           /* 降饱和一档: 少一分"喊", 多一分"柔" */
  --primary-foreground: 0 0% 100%;
  --secondary: 40 20% 90%;
  --secondary-foreground: 240 9% 46%;
  --muted: 40 20% 90%;
  --muted-foreground: 240 4% 46%;
  --accent: 40 20% 90%;
  --accent-foreground: 240 9% 46%;
  --destructive: 0 84% 60%;
  --destructive-foreground: 0 0% 100%;
  --border: 40 16% 88%;             /* 边线比之前再软半步 */
  --input: 40 16% 89%;
  --ring: 342 78% 64%;
  --radius: 0.75rem;
  /* ---- 阴影: 一律带色相(玫瑰底), 不用纯黑 ---- */
  --shadow: 0 10px 15px -3px hsl(342 45% 30% / 0.10), 0 4px 6px -4px hsl(342 45% 30% / 0.05);
  --shadow-sm: 0 1px 2px hsl(342 45% 30% / 0.05), 0 6px 20px -10px hsl(342 45% 30% / 0.10);
  --shadow-lg: 0 24px 48px -12px hsl(342 45% 25% / 0.18), 0 8px 16px -8px hsl(342 45% 25% / 0.08);
  /* ---- z-index 层级纪律 ---- */
  --z-scroll-btn: 20;
  --z-sheet: 30;
  --z-onboard: 40;
  --z-modal: 50;
  --z-toast: 60;
  /* ---- 情绪辅助色: 心情上色 / 状态语义, 不与主色抢戏 ---- */
  --mood-happy: 342 84% 65%;   /* 开心 · 玫瑰粉 */
  --mood-soft: 275 55% 70%;    /* 温柔/害羞 · 薰衣草 */
  --mood-low: 215 70% 58%;     /* 低落 · 雾蓝 */
  --mood-sleepy: 250 30% 60%;  /* 夜深/困 · 暮紫 */
  --mood-upset: 8 78% 60%;     /* 小情绪 · 珊瑚 */
  --warm-gold: 38 92% 52%;     /* 会员/高亮 · 暖金 */
  --cool-mint: 168 62% 42%;    /* 在线/成功 · 薄荷深, 浅底可读 */
  /* ---- 动效 token: 统一节奏 ---- */
  --dur-fast: 150ms;
  --dur-normal: 250ms;
  --dur-slow: 420ms;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
  --bubble-her-bg: 20 45% 99%;  /* 她的气泡: 带一丝暖调的近白 */
  --bubble-her-bg-dark: 258 16% 13%;
  /* ---- 科技层(深夜玫瑰): 极光 / 发丝内高光 / 玻璃 ---- */
  --hairline: 0 0% 100%;                 /* 内高光统一走白, 靠 alpha 收敛 */
  --hairline-ink: 342 30% 40%;           /* 浅底上的发丝边偏暖 */
  --glass-card: 258 18% 9%;              /* 玻璃卡(暗) */
  --tech-mint: 168 72% 52%;              /* 科技信号色: 在线/直播/联动 */
  --aurora-a: 342 84% 62%;
  --aurora-b: 268 70% 62%;
  --aurora-c: 190 70% 55%;
  --aurora-opacity: 0.085;   /* 浅底上极光要"若有若无", 否则发灰发脏 */
}

body.dark {
  --background: 258 24% 5%;            /* 深空紫黑, 不是纯黑 —— 冷调里带一丝夜色的紫 */
  --foreground: 250 20% 97%;
  --card: 258 18% 9%;
  --card-foreground: 250 20% 97%;
  --popover: 258 18% 9%;
  --popover-foreground: 250 20% 97%;
  --secondary: 258 14% 15%;
  --secondary-foreground: 250 12% 88%;
  --muted: 258 14% 15%;
  --muted-foreground: 252 10% 64%;
  --accent: 258 14% 15%;
  --accent-foreground: 250 12% 92%;
  --destructive: 0 62.8% 30.6%;
  --destructive-foreground: 0 0% 98%;
  --border: 258 14% 19%;
  --input: 258 16% 12%;
  --ring: 342 74% 66%;
  --shadow: 0 20px 25px -5px hsl(258 40% 2% / 0.5), 0 8px 10px -6px hsl(258 40% 2% / 0.24);
  --shadow-sm: 0 1px 2px hsl(258 40% 2% / 0.4), 0 8px 24px -12px hsl(258 40% 2% / 0.5);
  --shadow-lg: 0 28px 56px -16px hsl(258 40% 2% / 0.6), 0 8px 16px -8px hsl(258 40% 2% / 0.3);
  /* 暗色下主色降饱和一档, 免得粉红刺眼 */
  --primary: 342 76% 66%;
  --mood-happy: 342 70% 68%;
  --mood-soft: 275 45% 72%;
  --mood-low: 215 65% 64%;
  --mood-sleepy: 250 26% 64%;
  --mood-upset: 8 70% 64%;
  --aurora-opacity: 0.20;              /* 暗底上极光才敢亮起来 */
  --bubble-her-bg-dark: 258 16% 13%;
}

html, body {
  height: 100%;
}
body {
  font-family: -apple-system, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Roboto, "Noto Sans SC", sans-serif;
  background: hsl(var(--background));
  color: hsl(var(--foreground));
  display: flex;
  flex-direction: column;
  height: 100dvh;
  overflow: hidden;
  margin: 0;
  -webkit-text-size-adjust: 100%;
}
/* 背景柔光 + 噪点颗粒: 有"纸感", 不再是纯平色块 */
body::before {
  content: '';
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(120% 55% at 85% -12%, hsl(var(--primary) / 0.055), hsl(var(--primary) / 0) 62%),
    radial-gradient(90% 45% at -10% 108%, hsl(var(--mood-soft) / 0.05), hsl(var(--mood-soft) / 0) 60%);
}
body.dark::before {
  background:
    radial-gradient(120% 55% at 85% -12%, hsl(var(--primary) / 0.07), hsl(var(--primary) / 0) 62%),
    radial-gradient(90% 45% at -10% 108%, hsl(var(--mood-low) / 0.06), hsl(var(--mood-low) / 0) 60%);
}
/* 噪点: data-URI SVG feTurbulence, 固定层、不吃指针事件、z=-1 只铺在页面底色上 */
body::after {
  content: '';
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  opacity: 0.022;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 240 240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 240px 240px;
}
body.dark::after { opacity: 0.085; }

/* ═══ 氛围层 (深夜玫瑰): 贴边 wash, 不是"光球" ═══
   为什么放弃圆形光球: `opacity` 乘子 × 极小渐变 alpha 在 8-bit 上量化,
   乘积落到 0/1 边界处正好画出一圈**闭合圆环**(色带伪影)。
   贴边矩形渐变的等高线是平行且均匀的 → 读作"雾", 不会读作"环";
   再叠 body::after 的噪点抖动色阶。只动 transform, 不碰布局。 */
#ambient { position: fixed; inset: 0; z-index: -1; overflow: hidden; pointer-events: none; }
#ambient .orb { position: absolute; left: 0; right: 0; }
#ambient .orb.a {   /* 顶部玫瑰雾: 从她"在的地方"漫下来 */
  top: 0; height: 58vh;
  background: linear-gradient(180deg,
    hsl(var(--aurora-a) / 0.30) 0%,
    hsl(var(--aurora-a) / 0.19) 18%,
    hsl(var(--aurora-a) / 0.11) 38%,
    hsl(var(--aurora-a) / 0.05) 60%,
    hsl(var(--aurora-a) / 0.02) 82%,
    hsl(var(--aurora-a) / 0.008) 100%);
}
#ambient .orb.b {   /* 紫雾: 全宽竖向, 与顶部玫瑰叠成"玫瑰→暮紫"的纵向过渡。
                      跨满全宽 → 左右无边缘; 峰值压在屏幕顶部外 → 无可见直线边界 */
  top: 0; left: 0; right: 0; height: 74vh;
  background: linear-gradient(180deg,
    hsl(var(--aurora-b) / 0.20) 0%,
    hsl(var(--aurora-b) / 0.13) 20%,
    hsl(var(--aurora-b) / 0.075) 40%,
    hsl(var(--aurora-b) / 0.035) 60%,
    hsl(var(--aurora-b) / 0.014) 80%,
    hsl(var(--aurora-b) / 0.004) 94%,
    hsl(var(--aurora-b) / 0) 100%);
}
#ambient .orb.c {   /* 底部薄荷雾: 科技信号色, 只在下缘露一点 */
  bottom: 0; top: auto; height: 42vh;
  background: linear-gradient(0deg,
    hsl(var(--aurora-c) / 0.20) 0%,
    hsl(var(--aurora-c) / 0.11) 24%,
    hsl(var(--aurora-c) / 0.05) 50%,
    hsl(var(--aurora-c) / 0.02) 76%,
    hsl(var(--aurora-c) / 0.006) 100%);
}
/* 浅底模式: 明显收敛, 只留一层暖雾, 免得奶油底发灰发脏 */
body:not(.dark) #ambient .orb.a { opacity: 0.34; }
body:not(.dark) #ambient .orb.b { opacity: 0.22; }
body:not(.dark) #ambient .orb.c { opacity: 0.18; }
body.dark #ambient .orb.c { opacity: 0.85; }
* { box-sizing: border-box; }
button { font-family: inherit; border: none; background: none; cursor: pointer; }

/* 浏览器引导 */
#browser-guide {
  background: hsl(var(--secondary));
  color: hsl(var(--secondary-foreground));
  font-size: 13px; padding: 8px 12px; line-height: 1.5;
}

/* 顶栏 */
#topbar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; padding-top: calc(10px + env(safe-area-inset-top));
  background: hsl(var(--card) / 0.86);
  border-bottom: 1px solid hsl(var(--border) / 0.75);
  box-shadow: inset 0 -1px 0 hsl(var(--hairline) / 0.03), 0 1px 12px -6px hsl(var(--hairline-ink) / 0.10);
  flex: none;
}
.av {
  width: 40px; height: 40px; border-radius: 50%;
  background: linear-gradient(135deg, hsl(var(--primary)), hsl(342 84% 55%));
  color: #fff; font-size: 20px; line-height: 40px; text-align: center; flex: none;
}
.av.her { box-shadow: 0 4px 12px -2px hsl(var(--primary) / 0.4); }
.ttl { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.ttl b { font-size: 16px; font-weight: 600; letter-spacing: 0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: hsl(var(--foreground)); }
#status { font-size: 12px; color: hsl(var(--muted-foreground)); letter-spacing: 0.015em; }
#top-right { display: flex; gap: 8px; flex: none; }
.icb {
  width: 36px; height: 36px; border-radius: 50%;
  background: hsl(var(--secondary)); color: hsl(var(--secondary-foreground));
  display: flex; align-items: center; justify-content: center;
  transition: transform var(--dur-fast, 150ms) var(--ease-out, ease-out), opacity 0.15s;
}
.icb svg { width: 18px; height: 18px; }
.icb:active { transform: scale(0.88); opacity: 0.75; }
/* 主题切换: 日/月双图标, 由 body.dark 控制显隐(JS 不再写 textContent) */
.icb .ic-moon { display: block; }
.icb .ic-sun { display: none; }
body.dark .icb .ic-moon { display: none; }
body.dark .icb .ic-sun { display: block; }

/* 额度条 */
#quota-bar {
  flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 7px 14px; background: hsl(var(--secondary)); color: hsl(var(--secondary-foreground));
  font-size: 13px; border-bottom: 1px solid hsl(var(--border));
  transition: background 0.4s ease, color 0.4s ease;
}
/* 快用完时切换为暖金告警, 提前给心理预期而不是等弹窗 */
#quota-bar.low {
  background: hsl(38 92% 55% / 0.14);
  color: hsl(26 65% 38%);
}
body.dark #quota-bar.low { color: hsl(38 92% 70%); }
#quota-buy {
  border: none; background: hsl(var(--primary)); color: #fff;
  font-size: 12px; padding: 5px 12px; border-radius: 14px; cursor: pointer;
}

/* 聊天区 */
#chat {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;   /* 滚到底不再把整个页面带着弹 */
  padding: 18px 12px 10px; display: flex; flex-direction: column; gap: 12px;
}

/* 消息气泡（assistant-ui / chatbot-ui 风格） */
.msg {
  display: flex; align-items: flex-end; gap: 8px; animation: msgIn var(--dur-normal, 250ms) var(--ease-out, ease-out);
}
.msg.me { flex-direction: row-reverse; align-items: flex-end; }
.bubble {
  max-width: 78%; padding: 10px 14px; border-radius: 1.15rem;
  font-size: 15px; line-height: 1.6; word-break: break-word; white-space: pre-wrap;
  text-wrap: pretty;
  position: relative;
}
.bubble.her {
  background: hsl(var(--bubble-her-bg, var(--card)));
  border: 1px solid hsl(var(--border));
  color: hsl(var(--card-foreground)); border-top-left-radius: 6px;
  /* 发丝内高光 + 暖调投影: 让气泡像"一块有厚度的软材质"而非一块色块 */
  box-shadow: inset 0 1px 0 hsl(var(--hairline) / 0.75), 0 1px 2px hsl(var(--hairline-ink) / 0.06);
}
body.dark .bubble.her {
  background: hsl(var(--bubble-her-bg-dark, var(--card)));
  border-color: hsl(var(--hairline) / 0.075);
  box-shadow: inset 0 1px 0 hsl(var(--hairline) / 0.05), 0 2px 10px -2px hsl(258 40% 2% / 0.5);
}
.bubble.me {
  background: linear-gradient(160deg, hsl(342 80% 67%), hsl(342 78% 57%));
  color: #fff; border-top-right-radius: 6px;
  box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.28), 0 6px 18px -6px hsl(var(--primary) / 0.55);
}
.bubble.retry {
  align-self: center; background: transparent; border: 1px dashed hsl(var(--border));
  color: hsl(var(--destructive)); font-size: 13px; padding: 7px 16px;
}
.bubble.typing {
  align-self: flex-start; background: hsl(var(--bubble-her-bg, var(--card)));
  border: 1px solid hsl(var(--border));
  box-shadow: inset 0 1px 0 hsl(var(--hairline) / 0.7), 0 1px 2px hsl(var(--hairline-ink) / 0.06);
  border-radius: 1.15rem; border-top-left-radius: 6px;
  padding: 12px 16px; display: flex; gap: 5px; width: max-content;
}
body.dark .bubble.typing { background: hsl(var(--bubble-her-bg-dark, var(--card))); border-color: hsl(var(--hairline) / 0.075); }
.bubble.typing span { width: 7px; height: 7px; border-radius: 50%; background: hsl(var(--primary) / 0.75); animation: blink 1.2s infinite; }
.bubble.typing span:nth-child(2) { animation-delay: 0.2s; }
.bubble.typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes blink { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } }
@keyframes msgIn {
  from { opacity: 0; transform: translateY(10px) scale(0.985); }
  to { opacity: 1; transform: none; }
}
.caret { display: inline-block; width: 2px; height: 1em; background: hsl(var(--primary)); vertical-align: -2px; animation: blink 0.7s infinite; }

/* 时间戳: 表格数字, 同一列不再抖动 */
.mt {
  font-size: 11px; color: hsl(var(--muted-foreground)); margin: 4px 0 0;
  display: block; text-align: right;
  font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
}
.msg.me .mt { text-align: left; }

/* 回到底部 */
/* 搜索栏(默认隐藏, 点头部 🔍 展开)。放在 topbar 与 quota-bar 之间, 逻辑同 quota-bar。 */
#searchbar {
  flex: none; display: flex; align-items: center; gap: 8px;
  padding: 7px 12px; background: hsl(var(--secondary)); border-bottom: 1px solid hsl(var(--border));
}
#search-input {
  flex: 1; min-width: 0; font: inherit; font-size: 14px; padding: 7px 10px;
  border: 1px solid hsl(var(--border)); border-radius: 9px; background: hsl(var(--card)); color: inherit;
}
#search-go {
  flex: none; border: none; border-radius: 9px; padding: 7px 12px;
  background: hsl(var(--primary)); color: #fff; font: inherit; font-size: 14px; cursor: pointer;
}
#searchbar .sb-x {
  flex: none; border: none; background: transparent; color: inherit; cursor: pointer; opacity: .7;
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 50%;
  transition: background var(--dur-fast, 150ms), opacity var(--dur-fast, 150ms);
}
#searchbar .sb-x svg { width: 16px; height: 16px; }
#searchbar .sb-x:hover { opacity: 1; background: hsl(var(--muted) / 0.6); }

#scroll-bottom {
  position: fixed; right: 16px; bottom: 88px; width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; border: 1px solid hsl(var(--border) / 0.8);
  background: hsl(var(--card) / 0.82);
  color: hsl(var(--primary)); z-index: var(--z-scroll-btn, 20);
  /* 唯一"真的悬浮在滚动内容之上"的元素 → 这里用 blur 才有意义 */
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  box-shadow: inset 0 1px 0 hsl(var(--hairline) / 0.5), var(--shadow-sm);
  transition: transform var(--dur-fast, 150ms) var(--ease-spring, ease-out);
}
#scroll-bottom svg { width: 20px; height: 20px; }
#scroll-bottom:active { transform: scale(0.88); }
#scroll-bottom.hidden { display: none; }

/* 输入栏（Composer 风格）: 半透明 + 发丝边 + 内高光 = 玻璃, 无需 blur(无物可模糊) */
#inputbar {
  flex: none; display: flex; flex-direction: column; gap: 6px;
  padding: 10px 12px; padding-bottom: calc(10px + env(safe-area-inset-bottom));
  background: hsl(var(--background) / 0.9);
  border-top: 1px solid hsl(var(--border) / 0.7);
  box-shadow: 0 -1px 14px -8px hsl(var(--hairline-ink) / 0.12);
}
#emoji-bar {
  display: flex; gap: 4px; overflow-x: auto; padding: 6px 10px 0;
  background: transparent; -webkit-overflow-scrolling: touch;
  animation: up 0.2s var(--ease-out, ease-out);
}
#emoji-bar button {
  border: none; background: none; font-size: 20px; padding: 6px 6px; cursor: pointer; line-height: 1;
  border-radius: 10px; transition: background var(--dur-fast, 150ms);
}
#emoji-bar button:hover { background: hsl(var(--muted) / 0.7); }
#emoji-bar button:active { background: hsl(var(--accent)); transform: scale(0.92); }
.composer {
  display: flex; gap: 8px; align-items: flex-end;
  background: hsl(var(--card));
  border: 1px solid hsl(var(--border));
  border-radius: 22px; padding: 4px 10px;
  box-shadow: inset 0 1px 0 hsl(var(--hairline) / 0.6), 0 2px 10px -6px hsl(var(--hairline-ink) / 0.18);
  transition: border-color var(--dur-fast, 150ms), box-shadow var(--dur-normal, 250ms) var(--ease-out, ease-out);
}
body.dark .composer {
  background: hsl(var(--glass-card));
  box-shadow: inset 0 1px 0 hsl(var(--hairline) / 0.045), 0 2px 12px -8px hsl(258 40% 2% / 0.6);
}
.composer.focused {
  border-color: hsl(var(--ring) / 0.6);
  box-shadow: 0 0 0 3px hsl(var(--ring) / 0.16), inset 0 1px 0 hsl(var(--hairline) / 0.5);
}
#input {
  flex: 1; min-width: 0; border: none; background: transparent;
  padding: 10px 4px; font-size: 15px; outline: none; color: hsl(var(--foreground));
}
#input::placeholder { color: hsl(var(--muted-foreground)); }
.cb {
  border: none; border-radius: 50%; width: 36px; height: 36px;
  display: flex; align-items: center; justify-content: center; font-size: 18px;
  color: hsl(var(--foreground));
}
.cb-plus { color: hsl(var(--muted-foreground)); }
.cb-send { width: auto; padding: 0 18px; border-radius: 20px; color: #fff; font-weight: 600; font-size: 15px;
  background: linear-gradient(180deg, hsl(342 82% 68%), hsl(342 78% 57%));
  transition: transform var(--dur-fast, 150ms) var(--ease-spring, ease-out), box-shadow 0.2s, opacity 0.2s;
  box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.32), 0 4px 14px -4px hsl(var(--primary) / 0.5); }
.cb-send:active { transform: scale(0.93); box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.25), 0 1px 4px -2px hsl(var(--primary) / 0.5); }
.cb-send:disabled { opacity: 0.5; cursor: not-allowed; box-shadow: none; }

/* 通用按钮族: .b / .b-p / .b-d —— 供引导页 CTA、弹层、后台等复用。
   (b 个 bug: 这两个类此前从未定义, 导致引导页"开始聊"是个透明裸按钮) */
.b {
  border: 1px solid hsl(var(--border)); border-radius: 12px;
  background: hsl(var(--card)); color: hsl(var(--foreground));
  font: inherit; cursor: pointer;
  box-shadow: inset 0 1px 0 hsl(var(--hairline) / 0.55);
  transition: transform var(--dur-fast, 150ms) var(--ease-spring, ease-out), filter var(--dur-fast, 150ms);
}
.b:active { transform: scale(0.97); }
.b-p {
  background: linear-gradient(180deg, hsl(342 82% 68%), hsl(342 78% 57%));
  border-color: transparent; color: #fff; font-weight: 600;
  box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.3), 0 8px 22px -8px hsl(var(--primary) / 0.55);
}
.b-d { color: hsl(var(--destructive)); border-color: hsl(var(--destructive) / 0.35); }

/* 设置面板（shadcn Dialog 风格） */
#sheet-mask.ov {
  position: fixed; inset: 0; background: rgba(8, 4, 10, 0.45); z-index: var(--z-sheet, 30);
  backdrop-filter: blur(2px);
}
#sheet.sh {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sheet, 31);
  background: hsl(var(--background));
  border-top: 1px solid hsl(var(--border));
  border-radius: 1.5rem 1.5rem 0 0;   /* 大圆角盖板, 与气泡同级差 */
  max-height: 90vh; display: flex; flex-direction: column;
  animation: up 0.32s var(--ease-spring, ease-out);
  box-shadow: var(--shadow-lg);
}
@keyframes up { from { transform: translateY(30px); opacity: 0.6; } to { transform: none; opacity: 1; } }
.sh-h { width: 38px; height: 4px; border-radius: 2px; background: hsl(var(--muted)); margin: 10px auto 0; }
.sh-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid hsl(var(--border));
}
.sh-t { font-size: 17px; font-weight: 600; color: hsl(var(--foreground)); }
.sh-x { color: hsl(var(--muted-foreground)); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 50%;
  transition: background var(--dur-fast, 150ms), transform var(--dur-fast, 150ms); }
.sh-x svg { width: 18px; height: 18px; display: block; }
.sh-x:hover { background: hsl(var(--muted) / 0.7); }
.sh-x:active { transform: scale(0.9); }
.sh-body { overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 16px 16px calc(20px + env(safe-area-inset-bottom)); }
/* 分组卡片: 每组一张卡, 代替一坨平铺滚动 */
.g { margin: 14px 0; padding: 14px 14px 6px; border-radius: 14px; background: hsl(var(--card));
  border: 1px solid hsl(var(--border)); }
body.dark .g { border-color: rgb(255 255 255 / 0.07); }
.gt { display: block; font-size: 12px; font-weight: 700; color: hsl(var(--muted-foreground)); margin-bottom: 10px; letter-spacing: 0.02em; }
.f { margin: 12px 0; }
.f label { display: block; font-size: 14px; color: hsl(var(--foreground)); margin-bottom: 6px; }
.f label em { font-style: normal; color: hsl(var(--primary)); font-weight: 600; }
.f input[type=text], .f input[type=number] {
  width: 100%; border: 1px solid hsl(var(--border)); border-radius: 8px;
  padding: 9px 12px; font-size: 15px; outline: none; background: hsl(var(--card));
  color: hsl(var(--card-foreground));
}
.f input[type=text]:focus, .f input[type=number]:focus { border-color: hsl(var(--ring)); }
.f input[type=range] { width: 100%; -webkit-appearance: none; height: 4px; border-radius: 2px; background: hsl(var(--muted)); outline: none; }
.f input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 18px; height: 18px; border-radius: 50%;
  background: hsl(var(--primary)); border: 3px solid #fff; box-shadow: 0 1px 4px rgb(0 0 0 / 0.2);
}
.tg {
  border: 1px solid hsl(var(--border)); border-radius: 999px; padding: 7px 16px;
  background: hsl(var(--card)); color: hsl(var(--foreground)); font: inherit; font-size: 14px; cursor: pointer;
  box-shadow: inset 0 1px 0 hsl(var(--hairline) / 0.55);
  transition: transform var(--dur-fast, 150ms) var(--ease-spring, ease-out), box-shadow var(--dur-fast, 150ms);
}
.tg:active { transform: scale(0.95); }
.tg[aria-pressed="true"] { background: hsl(var(--primary)); border-color: hsl(var(--primary)); color: #fff; font-weight: 600;
  box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.25), 0 3px 10px -4px hsl(var(--primary) / 0.5); }
.sc { display: flex; justify-content: space-between; font-size: 11px; color: hsl(var(--muted-foreground)); margin-top: 5px; }
.r { display: flex; align-items: center; gap: 8px; }
.r span { color: hsl(var(--muted-foreground)); font-size: 14px; }
#sheet-actions { margin-top: 24px; display: flex; flex-direction: column; gap: 9px; }
#sheet-actions button {
  width: 100%; padding: 11px; border-radius: 10px; border: 1px solid hsl(var(--border));
  background: hsl(var(--card)); font-size: 15px; cursor: pointer; color: hsl(var(--foreground));
}
#sheet-actions .b-p { background: hsl(var(--primary)); border-color: hsl(var(--primary)); color: #fff; font-weight: 600; }
#sheet-actions .b-d { color: hsl(var(--destructive)); border-color: hsl(var(--destructive) / 0.3); }
#sheet-msg { margin-top: 14px; font-size: 13px; color: hsl(var(--muted-foreground)); text-align: center; min-height: 18px; }

/* 引导：品牌化落地页（两步：她先开口 → 再问称呼）—— 首次见面 = 唯一允许"铺张"的地方 */
#onboard.ob[hidden] { display: none; }
#onboard.ob {
  position: fixed; inset: 0; z-index: var(--z-onboard, 40); overflow: hidden;
  background: hsl(var(--background) / 0.96);
  backdrop-filter: blur(20px) saturate(1.3);
  -webkit-backdrop-filter: blur(20px) saturate(1.3);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.ob-glow {
  position: absolute; inset: -30% -10% auto; height: 62%;
  background: radial-gradient(60% 60% at 50% 0%, hsl(var(--primary) / 0.28), hsl(var(--primary) / 0) 70%);
  pointer-events: none;
}
body.dark .ob-glow { background: radial-gradient(60% 60% at 50% 0%, hsl(var(--primary) / 0.22), hsl(var(--primary) / 0) 70%); }
.ob-b { position: relative; width: 100%; max-width: 320px; text-align: center; }

.ob-hero { display: flex; flex-direction: column; align-items: center; }
.ob-av {
  position: relative; width: 96px; height: 96px; border-radius: 50%;
  background: linear-gradient(140deg, hsl(342 84% 70%), hsl(342 80% 54%));
  color: #fff; font-size: 38px; display: flex; align-items: center; justify-content: center;
  /* 玻璃环 + 内高光 + 外辉光: 像一颗被托在手中的宝石 */
  box-shadow:
    inset 0 2px 0 hsl(0 0% 100% / 0.35),
    inset 0 -10px 24px -12px hsl(342 70% 30% / 0.7),
    0 0 0 1px hsl(var(--primary) / 0.3),
    0 20px 44px -14px hsl(var(--primary) / 0.6);
  animation: avIn 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.2);
}
@keyframes avIn { from { opacity: 0; transform: scale(0.7); } to { opacity: 1; transform: none; } }
.ob-dot {
  position: absolute; right: 4px; bottom: 4px; width: 18px; height: 18px; border-radius: 50%;
  background: hsl(var(--tech-mint, 168 72% 52%)); border: 3px solid hsl(var(--background));
  box-shadow: 0 0 0 1px hsl(var(--tech-mint) / 0.35), 0 0 14px hsl(var(--tech-mint) / 0.55);
  animation: breathe 2.4s ease-in-out infinite;
}
.ob-name {
  margin: 20px 0 2px; font-size: 27px; font-weight: 700; letter-spacing: 0.02em;
  color: hsl(var(--foreground)); animation: riseIn 0.5s 0.1s both;
}
.ob-st { font-size: 13px; color: hsl(var(--muted-foreground)); letter-spacing: 0.03em; animation: riseIn 0.5s 0.18s both; }
@keyframes riseIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* 她正在打字的提示 */
.ob-say { display: flex; gap: 5px; margin-top: 26px; height: 8px; }
.ob-say i { width: 8px; height: 8px; border-radius: 50%; background: hsl(var(--primary)); animation: blink 1.2s infinite; }
.ob-say i:nth-child(2) { animation-delay: 0.2s; }
.ob-say i:nth-child(3) { animation-delay: 0.4s; }
.ob-say.said {
  font-size: 15px; color: hsl(var(--foreground)); line-height: 1.6;
  height: auto; display: block; animation: riseIn 0.35s both;
}

.ob-form { margin-top: 26px; animation: riseIn 0.4s both; text-align: left; }
.ob-ask { margin-bottom: 18px; }
.ob-ask label { display: block; font-size: 13px; color: hsl(var(--muted-foreground)); margin-bottom: 8px; }
.ob-chips { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 9px; }
.chip {
  padding: 8px 16px; border-radius: 999px; font-size: 14px;
  border: 1px solid hsl(var(--border)); background: hsl(var(--card));
  color: hsl(var(--foreground)); cursor: pointer;
  box-shadow: inset 0 1px 0 hsl(var(--hairline) / 0.6);
  transition: transform var(--dur-fast, 150ms) var(--ease-spring, ease-out),
              background var(--dur-fast, 150ms), border-color var(--dur-fast, 150ms), box-shadow var(--dur-fast, 150ms);
}
.chip:active { transform: scale(0.94); }
.chip.on {
  background: hsl(var(--primary)); border-color: hsl(var(--primary)); color: #fff;
  box-shadow: 0 4px 12px -3px hsl(var(--primary) / 0.5);
}
.ob-ask input {
  width: 100%; border: 1px solid hsl(var(--border)); border-radius: 10px;
  padding: 11px 13px; font-size: 15px; outline: none;
  background: hsl(var(--card)); color: hsl(var(--card-foreground));
  transition: border-color 0.2s, box-shadow 0.2s;
}
.ob-ask input:focus { border-color: hsl(var(--ring)); box-shadow: 0 0 0 2px hsl(var(--ring) / 0.25); }
.ob-cta { width: 100%; margin-top: 6px; padding: 14px; border-radius: 12px; font-size: 16px; }
.ob-note { margin-top: 14px; font-size: 12px; color: hsl(var(--muted-foreground)); text-align: center; }

/* 骨架屏: 模拟真实消息行(她的头像 + 气泡两条), 首屏加载不再是干巴巴的块 */
.skel-rail { align-self: stretch; display: flex; flex-direction: column; gap: 12px; padding: 4px 0; }
.skel { align-self: flex-start; display: flex; align-items: flex-end; gap: 8px;
  background: none; border: none; }
.skel .sk-av { width: 40px; height: 40px; border-radius: 50%; flex: none;
  background: hsl(var(--muted)); }
.skel .sk-b { background: hsl(var(--card)); border: 1px solid hsl(var(--border));
  border-radius: 1.15rem; border-top-left-radius: 6px; padding: 12px 16px; }
.skel i { display: block; height: 9px; border-radius: 5px; background: hsl(var(--muted)); margin: 5px 0;
  animation: sk-pulse 1.4s ease-in-out infinite; }
.skel i { width: 96px; }
.skel i:nth-child(2) { width: 70%; }
@keyframes sk-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }

/* 空状态 */
.empty { align-self: center; text-align: center; color: hsl(var(--muted-foreground)); font-size: 14px; padding: 40px 20px; }

/* ═══ 精细化提升 (2026-10-17) ═══ */

/* 1. 日期分隔线：长会话不糊成一团 */
.daysep {
  align-self: center; display: flex; align-items: center; gap: 10px;
  color: hsl(var(--muted-foreground)); font-size: 11px; letter-spacing: 0.06em;
  margin: 6px 0 2px; user-select: none;
}
.daysep::before, .daysep::after {
  content: ''; height: 1px; width: 42px;
  background: linear-gradient(90deg, hsl(var(--border) / 0), hsl(var(--border)), hsl(var(--border) / 0));
  border-radius: 1px;
}

/* 2. 消息分组：同一说话人连续消息紧凑，头像只在组首出现一次 */
.msg.grouped { margin-top: -6px; }
.msg.grouped .av { visibility: hidden; }
.msg.grouped .mt { display: none; }

/* 3. 头像在线呼吸点：她"活着"的视觉信号；颜色随心情变化(data-mood 由 JS 设置) */
.av { position: relative; }
#avatar .dot {
  position: absolute; right: -1px; bottom: -1px;
  width: 10px; height: 10px; border-radius: 50%;
  background: hsl(var(--tech-mint, 168 72% 52%)); border: 2px solid hsl(var(--card));
  animation: breathe 2.4s ease-in-out infinite;
  transition: background 0.6s ease;
}
/* 信号环: 她"正在打"时头像外圈 ping 一下, 科技感的"我这就在线给你回" */
#avatar::after {
  content: ''; position: absolute; inset: -3px; border-radius: 50%;
  border: 1.5px solid transparent; pointer-events: none;
}
body.her-typing #avatar::after { animation: livePing 1.5s var(--ease-out, ease-out) infinite; }
@keyframes livePing {
  0% { border-color: hsl(var(--tech-mint) / 0.6); transform: scale(0.96); }
  100% { border-color: hsl(var(--tech-mint) / 0); transform: scale(1.34); }
}
body[data-mood="happy"] #avatar .dot { background: hsl(var(--mood-happy)); }
body[data-mood="soft"] #avatar .dot { background: hsl(var(--mood-soft)); }
body[data-mood="low"] #avatar .dot { background: hsl(var(--mood-low)); }
body[data-mood="sleepy"] #avatar .dot { background: hsl(var(--mood-sleepy)); }
body[data-mood="upset"] #avatar .dot { background: hsl(var(--mood-upset)); }
/* 顶栏状态行也跟着心情轻染, 12px 下仍要保持可读 */
#status { transition: color 0.6s ease; }
body[data-mood="low"] #status { color: hsl(var(--mood-low)); }
body[data-mood="soft"] #status { color: hsl(var(--mood-soft)); }
/* 未读徽章: 主动消息来了但人不在看 → 头像右上角小红点(数字计数) */
#avatar .unread-badge {
  position: absolute; top: -5px; right: -5px;
  min-width: 17px; height: 17px; padding: 0 4px; border-radius: 9px;
  background: hsl(0 84% 60%); color: #fff;
  font-size: 10px; font-weight: 700; line-height: 17px; text-align: center;
  box-shadow: 0 2px 6px -1px rgb(0 0 0 / 0.3);
  animation: pop-in 0.25s var(--ease-spring, ease-out);
}
@keyframes pop-in { from { opacity: 0; transform: scale(0.5); } to { opacity: 1; transform: scale(1); } }
@keyframes breathe {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.18); opacity: 0.72; }
}

/* 4. 气泡 hover 微交互（桌面） */
@media (hover: hover) and (pointer: fine) {
  .msg.me:hover .bubble, .msg.her:hover .bubble { transform: translateY(-1px); }
  .bubble { transition: transform 0.15s ease; }
}

/* 5. 输入框发送时轻微回弹 */
.composer.sent { animation: nudge 0.22s ease-out; }
@keyframes nudge {
  0% { transform: scale(1); } 40% { transform: scale(0.985); } 100% { transform: scale(1); }
}

/* 6. 系统提示条（居中细体，不占视觉重量） */
.bubble.sysline {
  align-self: center; background: transparent; border: none;
  color: hsl(var(--muted-foreground)); font-size: 12px;
  padding: 2px 8px; max-width: 92%; text-align: center;
}

/* 7. 设置滑块轨道更细腻 */
.f input[type=range]::-webkit-slider-runnable-track {
  height: 4px; border-radius: 2px; background: hsl(var(--muted));
}
.f input[type=range]::-webkit-slider-thumb { margin-top: -7px; }

/* ═══ 通用弹层（替代原生 confirm） ═══ */
#modal-mask.ov {
  position: fixed; inset: 0; background: hsl(258 40% 4% / 0.55);
  z-index: var(--z-modal, 50);
  backdrop-filter: blur(6px) saturate(1.2);
  -webkit-backdrop-filter: blur(6px) saturate(1.2);
  animation: fadeIn var(--dur-fast, 150ms) ease-out;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
#modal.md {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%,-50%);
  z-index: calc(var(--z-modal, 50) + 1); width: calc(100% - 48px); max-width: 340px;
  background: hsl(var(--card)); color: hsl(var(--card-foreground));
  border: 1px solid hsl(var(--border)); border-radius: 22px;   /* 更大的盖板圆角 */
  box-shadow: inset 0 1px 0 hsl(var(--hairline) / 0.5), var(--shadow-lg);
  overflow: hidden;
  animation: pop 0.26s var(--ease-spring, ease-out);
}
@keyframes pop { from { opacity: 0; transform: translate(-50%,-46%) scale(0.94); } to { opacity: 1; transform: translate(-50%,-50%) scale(1); } }
.md-h { display: none; }
.md-head { padding: 20px 20px 0; text-align: center; }
.md-t { font-size: 18px; font-weight: 600; }
.md-body { padding: 10px 20px 20px; text-align: center; }
.md-sub { font-size: 14px; color: hsl(var(--muted-foreground)); line-height: 1.6; margin-top: 8px; }
.md-in { margin-top: 14px; }
.md-in input {
  width: 100%; padding: 12px; border: 1px solid hsl(var(--border)); border-radius: 10px;
  background: hsl(var(--card)); color: inherit; outline: none; text-align: center;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 17px;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.md-in input:focus { border-color: hsl(var(--ring)); }
.md-list { margin-top: 16px; text-align: left; background: hsl(var(--muted) / .5); border-radius: 12px; padding: 12px 14px; }
.md-list .row { display: flex; justify-content: space-between; align-items: center; font-size: 13px; padding: 5px 0; }
.md-list .row .k { color: hsl(var(--muted-foreground)); }
.md-list .row .v { color: hsl(var(--primary)); font-weight: 600; }
.md-actions { margin-top: 20px; display: flex; flex-direction: column; gap: 9px; }
.md-actions button { width: 100%; padding: 12px; border-radius: 12px; font-size: 15px; cursor: pointer;
  border: 1px solid hsl(var(--border)); background: hsl(var(--card)); color: hsl(var(--foreground)); }
.md-actions .b-p { background: hsl(var(--primary)); border-color: hsl(var(--primary)); color: #fff; font-weight: 600; }

/* 保存 loading 态 */
button.loading { opacity: .7; cursor: progress; pointer-events: none; }
.spinner {
  width: 14px; height: 14px; border: 2px solid rgba(255,255,255,.35);
  border-top-color: #fff; border-radius: 50%; display: inline-block;
  vertical-align: -2px; margin-right: 6px; animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* 加载更多历史 */
.moreload { align-self: center; font-size: 12px; color: hsl(var(--muted-foreground));
  padding: 6px 14px; margin: 2px 0 6px; background: hsl(var(--card)); border: 1px solid hsl(var(--border)); border-radius: 14px; cursor: pointer; }

/* 软键盘: 键盘弹出时压缩聊天区, 保证输入框与最后一条消息可见 */
body.kb-open #chat { padding-bottom: 8px; }

/* 消息状态刻度: 发送中 · / 已送达 ✓ / 失败 ! */
.mstat { font-size: 11px; color: hsl(var(--muted-foreground)); margin: 0 2px 2px; align-self: flex-end; }
.mstat.sent { color: hsl(var(--primary)); }
.mstat.failed { color: hsl(var(--destructive)); font-weight: 700; cursor: pointer; }

/* 收款码 + 订单号 */
.md-qr { margin-top: 14px; text-align: center; }
.md-qr img { width: 190px; height: 190px; object-fit: contain; border-radius: 12px;
  border: 1px solid hsl(var(--border)); background: #fff; }
.md-qr-tip { font-size: 12px; color: hsl(var(--muted-foreground)); margin-top: 8px; }
.md-code { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 12px; }
.md-code span { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 18px;
  letter-spacing: 2px; font-weight: 700; color: hsl(var(--primary)); }
.md-code button { border: 1px solid hsl(var(--border)); background: hsl(var(--card));
  border-radius: 8px; padding: 4px 10px; font-size: 12px; cursor: pointer; color: hsl(var(--foreground)); }
.md-wait { margin-top: 10px; font-size: 12px; color: hsl(var(--muted-foreground)); text-align: center; }
.md-wait .dotp { display: inline-block; animation: blink 1.2s infinite; }

/* 她主动发来的图片 */
.img-bubble { padding: 5px; }
.chat-img { display: block; max-width: 220px; width: 60vw; border-radius: 12px; }
.img-cap { margin-top: 6px; font-size: 13px; line-height: 1.4; }

/* ═══ 体验升级第二波 (2026-10-18) ═══ */

/* 8. 主动消息"冲进来"的动效: 比普通消息多一分"她来找你"的急切 */
@keyframes msgPro {
  0% { opacity: 0; transform: translateY(-14px) scale(0.97); }
  60% { opacity: 1; transform: translateY(2px) scale(1.005); }
  100% { opacity: 1; transform: none; }
}
.msg.pro { animation: msgPro 0.42s var(--ease-spring, ease-out); }

/* 9. 空状态: 一句体面的话, 不是粉底色块 */
.empty-b {
  align-self: center; text-align: center; padding: 36px 24px; color: hsl(var(--muted-foreground));
}
.empty-b .eb-glyph { font-size: 34px; display: block; margin-bottom: 10px; opacity: 0.75; }
.empty-b .eb-t { font-size: 14px; line-height: 1.7; max-width: 230px; margin: 0 auto; }
.empty-b .eb-act { margin-top: 14px; display: inline-block; padding: 8px 20px; border-radius: 999px;
  border: 1px solid hsl(var(--border)); background: hsl(var(--card)); color: hsl(var(--foreground));
  font-size: 13px; cursor: pointer; }

/* 10. 无障碍: 键盘可视焦点 + 减少动效偏好 */
:focus-visible { outline: 2px solid hsl(var(--ring)); outline-offset: 2px; border-radius: 4px; }
:focus:not(:focus-visible) { outline: none; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .caret { animation: none !important; }
}

/* 11. 桌面滚动条: 收细, 不给 Web 布局"工程感" */
@media (hover: hover) and (pointer: fine) {
  #chat::-webkit-scrollbar, .sh-body::-webkit-scrollbar { width: 8px; }
  #chat::-webkit-scrollbar-thumb, .sh-body::-webkit-scrollbar-thumb {
    background: hsl(var(--muted-foreground) / 0.28); border-radius: 4px;
    border: 2px solid transparent; background-clip: content-box;
  }
  #chat::-webkit-scrollbar-track, .sh-body::-webkit-scrollbar-track { background: transparent; }
}

/* 12. hero/onboard 的情绪氛围光随 mood 变 */
body[data-mood="low"] .ob-glow,
body[data-mood="sleepy"] .ob-glow {
  background: radial-gradient(60% 60% at 50% 0%, hsl(var(--mood-low) / 0.2), hsl(var(--mood-low) / 0) 70%);
}
