/* ============================================================
   访客页左栏共享样式 nav.css（四套模板共用，C1 先行落 default）
   尺寸钉死（老板稿，F1 双断点）：栏宽 移动48/桌面120 / 键高 56 / 键距 8 / 命中区≥44
   结构契约：面板绝对叠放，切走 visibility:hidden + opacity:0，
   禁止 display:none（iOS 丢 scrollTop 且 clientHeight=0 会弄坏
   一对一的跟滚判定 app.js isMessageListNearBottom）
   ============================================================ */

:root {
    /* F1 双断点：移动 <768px 窄栏 48（悬浮微挡）；桌面 ≥768px 120（图标+文字入卡一体，下方媒体查询覆写） */
    --visitor-rail-w: 48px;
    --visitor-key-h: 56px;
    --visitor-gap: 8px;
    /* 叠放面板顶部偏移＝顶栏实际高度；nav.js 挂载时会实测覆写此值 */
    --visitor-header-offset: 56px;
    /* 移动端浮层在顶栏下方再落一截，不贴着状态栏（桌面 static 不用） */
    --visitor-rail-drop: 40px;
}

/* wrapper：index.html 里的静态容器，包 rail + stage(#app)。
   未渲染 rail 时（降级/可见项<2）stage 全宽，与现网像素一致 */
.visitor-shell {
    display: flex;
    flex-direction: row;
    width: 100%;
    height: 100%;
    position: relative; /* 悬浮 rail 的定位上下文 */
}

.visitor-stage {
    position: relative;
    flex: 1 1 auto;
    min-width: 0;
    width: 100%;
    height: 100%;
}

/* ---------------- F1 定位模型（2026-08-26 设计双审定稿） ----------------
   移动 <768px：rail 悬浮（absolute）盖在内容上，内容全宽从 0 起，窄栏
   48px 微挡左缘（老板口径：挡一点没事，不能太占中间）。
   桌面 ≥768px：rail position:static 进 shell 的 flex 流，自占 120px 让位，
   与内容入卡一体（下方媒体查询覆写）。
   V1 的 .visitor-has-rail margin/left 让位规则整批废弃（2026-08-26）——
   .visitor-has-rail 类保留作「rail 在场」语义锚：nav.js render() 真渲染
   才挂，降级无栏态无此类（测试钉死）。 */

/* ---------------- 左栏（移动端=悬浮浮层；桌面端见下方媒体查询改 static） ---------------- */

/* F1 移动端（默认）：绝对叠在页面上，内容全宽从 0 起，窄栏微挡左缘。
   键多了只滚浮层本身；padding-bottom 带 safe-area。
   z 序：压在叠放面板(50)之上、灯箱(2000)/toast 之下（例外：灯箱开着时
   body.v-lightbox-open 把 rail 提到 2001——P-104 窄屏批灯箱不盖左栏可点）；
   顶栏/底部输入区
   靠几何避让（顶距=顶栏高+40px、max-height 底部留 80px）不遮输入框。 */
.visitor-rail {
    position: absolute;
    left: 0;
    top: calc(var(--visitor-header-offset, 56px) + var(--visitor-rail-drop, 40px));
    z-index: 60; /* 高于 chat-stream(5)/glass 顶栏(20)/效果图面板(50)，低于灯箱(2000) */
    width: var(--visitor-rail-w);
    height: auto;
    max-height: calc(100% - var(--visitor-header-offset, 56px) - var(--visitor-rail-drop, 40px) - 80px);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    gap: var(--visitor-gap);
    padding: 0 2px; /* 移动 48 栏宽 - 左右各 2 = 44 键宽（命中区≥44 钉死） */
    padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    background: transparent;
    border-right: none;
    pointer-events: none; /* 只让键吃点击，空档不挡聊天滚动 */
}
.visitor-rail::-webkit-scrollbar { display: none; }

/* P-104（390 窄屏批）：灯箱开着时左栏提到灯箱(2000)以上——不再点不动，
   点键先收灯箱再切栏（nav.js 开灯箱挂 body.v-lightbox-open，收灯箱摘类）。
   空档仍穿透（rail pointer-events:none 不变），点黑底关灯箱口径不变。 */
body.v-lightbox-open .visitor-rail { z-index: 2001; }
body.v-lightbox-open .visitor-rail-tip { z-index: 2002; }
@media (min-width: 768px) {
    body.v-lightbox-open .visitor-rail {
        position: relative; /* 桌面 static 时 z-index 不生效，relative 启用（布局零位移） */
        top: 0;             /* 抵消移动端 top 偏移（桌面顶距走 margin-top） */
    }
}

/* 键：移动栏宽 48 - 左右各 2 = 44 宽 / 桌面 120 - 左右各 8 = 104 宽；
   min-height 56，命中区≥44 双断点都成立 */
.visitor-rail-key {
    flex: 0 0 auto;
    width: 100%;
    min-height: var(--visitor-key-h);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 4px 2px;
    /* 卡片键：白卡+边框+圆角；浮层上投影加重，才压得住气泡 */
    border: 1px solid var(--border-light, #E5E5EA);
    border-radius: 12px;
    background: var(--surface-white, #FFFFFF);
    color: var(--text-stone-strong, #636366); /* 闲态加深一档（会诊：2.9:1→≥3:1） */
    font-family: inherit;
    font-size: 12px;
    line-height: 1.25;
    cursor: pointer;
    position: relative;
    pointer-events: auto;
    -webkit-tap-highlight-color: transparent;
    touch-action: manipulation;
    transition: color .15s ease, background-color .15s ease, opacity .15s ease;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .12), 0 1px 3px rgba(0, 0, 0, .06);
}

.visitor-rail-key svg {
    width: 22px;
    height: 22px;
    display: block;
}

.visitor-rail-key-label {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* 选中态：边框/图标/文字跟租户品牌色变量（--brand-primary），
   SVG 用 currentColor 自动变色 */
.visitor-rail-key.active {
    color: var(--brand-primary, #07C160);
    border-color: var(--brand-primary, #07C160);
    /* 选中态做实（会诊 P2）：14% 品牌色底 + 字重 600 + 图标加粗 */
    background: rgba(10, 132, 255, .10); /* 老内核兜底 */
    background: color-mix(in srgb, var(--brand-primary, #07C160) 14%, transparent);
}
.visitor-rail-key.active .visitor-rail-key-label { font-weight: 600; }
.visitor-rail-key.active svg { stroke-width: 2.2; }

/* 置灰键（本批群聊/内部群）：点击只出 toast「暂未开放」，不切面板 */
.visitor-rail-key[aria-disabled="true"] {
    /* 置灰用实浅灰（会诊 P2：禁整键半透明——可用键反而像坏了） */
    color: #B9B9C4;
    opacity: 1;
}

/* 系统三项与后台动态项之间的分隔线 */
.visitor-rail-split {
    flex: 0 0 auto;
    height: 1px;
    margin: 2px 4px;
    background: var(--border-light, #E5E5EA);
}

/* 未读徽标挂点（C4 使用）：钉在键右上角内侧（键 position:relative 为定位基准），
   F1 复核：48/120 双断点下同落点，不随栏宽漂移。
   V1 消息可达性批（2026-09-11）：8px 纯点 → 计数徽标（textContent 写真数字）。
   仍是同一个元素、同一个挂点、同一套挂/清时机；一位数保持 16px 圆，多位横向长，
   99 封顶显示 99+。白描边＝浅色键面/图片底上不糊。 */
.visitor-rail-badge {
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    box-sizing: border-box;
    border-radius: 8px;
    background: #F04438;
    border: 1px solid #FFFFFF;
    color: #FFFFFF;
    font-size: 10px;
    line-height: 14px;
    font-weight: 600;
    text-align: center;
    font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif;
}

/* F3.3：1v1 客服头像改首字占位（app.js span.avatar.avatar-initial）。
   复用各模板 style.css 的 .message .avatar 尺寸/圆角；底色统一品牌色、
   白字，四模板观感一致（specificity 压模板原背景，不用 !important） */
.message span.avatar.avatar-initial {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--brand-primary, #07C160);
    color: #FFFFFF;
    font-size: 14px;
    font-weight: 600;
    object-fit: none; /* img 时代残留属性，span 上无效，写死防模板侧回写 */
}

/* 2026-09-22 老板令：消息行客服头像换真图。img 填满色块（尺寸/圆角复用模板 .message .avatar）；
   破图被 app.js 移除后自然回落首字，观感不破。 */
.message span.avatar.avatar-initial img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: inherit;
    display: block;
}

/* ---------------- F1 移动端：只图标不带字 + 长按文字标签 + 首访气泡 ---------------- */

/* 移动端键面只留图标（文字标签由长按浮出）；桌面端标签常显（下方媒体查询） */
@media (max-width: 767px) {
    .visitor-rail-key-label { display: none; }

    /* G3：rail 在场时消息区左垫 52px——48px 窄栏悬浮盖住消息区最左
       （昵称/@访客被遮）；垫到 52=挡 4px 缝不挡字（老板「挡一点没事」的正确落点）。
       只许移动端：桌面 ≥768 rail 已 position:static 自占位，再垫=双让位。
       降级无栏（无 .visitor-has-rail）全宽不垫，与现网像素一致。 */
    .visitor-has-rail .chat-stream { padding-left: 52px; }

    /* G3 同款：群面板也被悬浮栏盖左缘（群头/公告条/群消息区同款让位；
       发言框在底部 80px 留白内不被盖，不垫；叠层（成员/门/状态）absolute 不受影响） */
    .visitor-has-rail .group-head { padding-left: 52px; }
    .visitor-has-rail .group-notice-bar-head { padding-left: 52px; }
    .visitor-has-rail .group-notice-full { padding-left: 52px; }
    .visitor-has-rail .group-msgs { padding-left: 52px; }
    /* P-104：效果图卡片流同款让位 52px——图标不再压卡片标题/首列图 */
    .visitor-has-rail .vg-list { padding-left: 52px; }
}

/* 长按浮出的文字标签（nav.js touch 守卫挂到 shell 上，贴键右侧） */
.visitor-rail-tip {
    position: absolute;
    z-index: 61; /* rail(60) 之上，灯箱(2000) 之下 */
    background: rgba(28, 28, 30, .82);
    color: #FFFFFF;
    font-size: 12px;
    line-height: 1.2;
    padding: 5px 9px;
    border-radius: 7px;
    white-space: nowrap;
    pointer-events: none;
}

/* 首访一次性引导气泡：本体不吃点击（不抢首击），只有关闭钮可点；
   关闭后 localStorage 记位不再弹（nav.js GUIDE_KEY） */
.visitor-rail-guide {
    position: absolute;
    z-index: 62;
    display: flex;
    align-items: center;
    gap: 8px;
    max-width: 184px;
    background: rgba(28, 28, 30, .88);
    color: #FFFFFF;
    font-size: 12px;
    line-height: 1.35;
    padding: 8px 8px 8px 10px;
    border-radius: 10px;
    pointer-events: none;
}
/* 2026-09-21 修实现偏离 08-26 封版设计（前端交互修复设计_20260826.md:8 限定移动 <768px）：
   桌面左栏键面图标+文字常显，引导气泡冗余且漏点动态群键 ⇒ 桌面不出泡；移动端键只剩图标，气泡保留。 */
@media (min-width: 768px) {
    .visitor-rail-guide { display: none; }
}
.visitor-rail-guide-close {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, .18);
    color: #FFFFFF;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    pointer-events: auto;
    -webkit-tap-highlight-color: transparent;
}

/* ---------------- 叠放面板 ---------------- */

/* 面板同容器绝对叠放；切走=visibility:hidden + opacity:0 +
   pointer-events:none——禁止 display:none、禁止卸载 DOM。
   顶部偏移留出一对一顶栏（标题随面板变，顶栏本体不隐藏）。
   150ms 淡入（老板钉的切换手感）。 */
.visitor-panel {
    position: absolute;
    top: var(--visitor-header-offset);
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 50;
    box-sizing: border-box;
    background: var(--bg-chat, #F2F2F2);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    visibility: hidden;
    opacity: 0;
    pointer-events: none;
    transition: opacity .15s ease, visibility .15s ease;
}

.visitor-panel.active {
    visibility: visible;
    opacity: 1;
    pointer-events: auto;
}

/* 骨架占位（C1 阶段内容位，C2 卡片流替换） */
.visitor-panel-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: var(--text-stone, #8E8E93);
    font-size: 13px;
}

/* 非一对一面板时顶栏隐藏连接态：用 visibility 保留占位，
   顶栏 flex 布局不位移；切回一对一恢复 */
#status.visitor-status-hidden {
    visibility: hidden;
}

/* ============================================================
   C2 效果图面板：卡片流（仿源站卡片样式）
   文案两行折叠「展开/收起」；图网格 1 图大图 / 2·4 两列 / ≥3 三列；
   底部相对时间 + 「详情」（面板内展开精确时间+全文）
   ============================================================ */

.vg-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 12px;
}

.vg-card {
    box-sizing: border-box;
    background: var(--surface-white, #FFFFFF);
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 12px;
    padding: 12px;
}

/* 双向联动（设计 v5.1 §4.2 协议 2，批 L）：openGalleryPost 唤醒目标卡片——
   呼吸高亮 2.5s（=1.25s 一息 ×2），边框跟租户品牌色，光圈由弱到强再收；
   只做视觉引导，不拦点击不抢滚动，2.5s 后由 nav.js 摘类退场 */
.vg-card.vg-card-highlight {
    border-color: var(--brand-primary, #07C160);
    animation: vg-card-highlight-pulse 1.25s ease-in-out 2;
}

@keyframes vg-card-highlight-pulse {
    0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--brand-primary, #07C160) 0%, transparent); }
    50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand-primary, #07C160) 35%, transparent); }
}

/* 文案恒两行折叠（源站样式；老板定稿：全文只在「详情」区，无原地展开钮）。
   -webkit-box 是 line-clamp 的实现手段，与面板级禁 display:none 无关 */
.vg-text {
    font-size: 14px;
    line-height: 1.5;
    color: var(--text-primary, #1C1C1E);
    white-space: pre-wrap;
    word-break: break-word;
}

.vg-text.vg-clamped {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
}

/* 图网格：列数规则在 nav.js 挂类（1→大图 / 2·4→两列 / ≥3→三列） */
.vg-grid {
    display: grid;
    gap: 6px;
    margin-top: 8px;
}

.vg-grid-1 { grid-template-columns: 1fr; }
.vg-grid-2 { grid-template-columns: 1fr 1fr; }
.vg-grid-3 { grid-template-columns: 1fr 1fr 1fr; }

.vg-cell {
    border-radius: 8px;
    overflow: hidden;
    background: var(--border-light, #E5E5EA); /* 图未到位前的底色 */
    cursor: pointer; /* C3 灯箱：点图看原图 */
}

.vg-grid:not(.vg-grid-1) .vg-cell { aspect-ratio: 1 / 1; }

.vg-img {
    width: 100%;
    display: block;
}

.vg-grid-1 .vg-img { height: auto; max-height: 340px; object-fit: cover; }
.vg-grid:not(.vg-grid-1) .vg-img { height: 100%; object-fit: cover; }

/* 底部：相对时间 + 详情（闸门开时 + 购买钮；图床闭环 B）。
   wrap+gap 只在三槽窄屏溢出时生效；两子项时与 space-between 像素一致 */
.vg-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 4px 8px;
    min-height: 44px; /* 老板视觉口径：foot 行高固定=展开/收起时按钮位不被顶跑 */
    margin-top: 8px;
}

/* 图床闭环 B1：折叠态右侧动作组（「详情」+「⚡咨询/购买此款」并排）；
   margin-left:auto 保证窄屏换行后仍右对齐 */
.vg-foot-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-left: auto;
}

.vg-time {
    font-size: 12px;
    color: var(--text-stone, #8E8E93);
}

.vg-detail-btn {
    border: 0;
    background: transparent;
    display: inline-flex;
    align-items: center;
    min-height: 44px; /* 老板视觉口径（2026-08-26）：加大触摸区，视觉仍是文字钮 */
    padding: 0 4px;
    color: var(--brand-primary, #07C160);
    font-size: 12px;
    font-family: inherit;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

/* 详情区：卡片级展开/收起（非面板切换，不受面板级禁令约束） */
.vg-detail {
    display: none;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 0.5px solid var(--border-light, #E5E5EA);
}

.vg-detail.open { display: block; }

.vg-detail-time {
    font-size: 12px;
    color: var(--text-stone, #8E8E93);
    margin-bottom: 4px;
}

.vg-detail-text {
    font-size: 13px;
    line-height: 1.5;
    color: var(--text-primary, #1C1C1E);
    white-space: pre-wrap;
    word-break: break-word;
}

/* 图床闭环 B1：「⚡咨询/购买此款」强行动按钮——品牌色实底胶囊，
   与「详情」文字钮拉开层级（老板红圈显著位）；点击态轻降透明度 */
.vg-buy-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    border: 0;
    border-radius: 999px;
    min-height: 44px; /* 老板视觉口径（2026-08-26）：触摸区≥44px 高、一眼能找到 */
    padding: 6px 16px;
    background: var(--brand-primary, #07C160);
    color: var(--surface-white, #FFFFFF);
    font-size: 14px;
    font-weight: 600;
    font-family: inherit;
    line-height: 1.4;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.vg-buy-btn svg { width: 14px; height: 14px; display: block; flex: none; }

.vg-buy-btn:active { opacity: 0.85; }

/* 详情展开态那颗：全文下方留白区的强行动召唤（设计 §6.2 第二处） */
.vg-detail .vg-buy-btn { margin-top: 8px; }

/* 列表状态行：加载中/没有更多/空态/失败重试 */
.vg-status {
    padding: 8px 12px calc(12px + env(safe-area-inset-bottom, 0px));
    text-align: center;
    font-size: 12px;
    color: var(--text-stone, #8E8E93);
}

.vg-retry {
    border: 0;
    background: transparent;
    padding: 2px 6px;
    color: var(--brand-primary, #07C160);
    font-size: 12px;
    font-family: inherit;
    cursor: pointer;
}

/* 骨架（秒开=骨架 <100ms 先出，数据到再填卡片） */
.vg-skeleton { pointer-events: none; }

.vg-sk-line,
.vg-sk-grid {
    border-radius: 6px;
    background: linear-gradient(90deg, rgba(0, 0, 0, .06) 25%, rgba(0, 0, 0, .10) 37%, rgba(0, 0, 0, .06) 63%);
    background-size: 400% 100%;
    animation: vgShimmer 1.4s ease infinite;
}

.vg-sk-line { height: 14px; margin-bottom: 8px; }
.vg-sk-line.short { width: 60%; }
.vg-sk-grid { height: 120px; border-radius: 8px; }

@keyframes vgShimmer {
    0% { background-position: 100% 50%; }
    100% { background-position: 0 50%; }
}

/* ============================================================
   C2 补：视频格（封面 + 播放键占位）
   ============================================================ */

.vg-cell-video { position: relative; }

.vg-play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(0, 0, 0, .55);
    color: #FFFFFF;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none; /* 点击穿透到格子 */
}

.vg-play svg { width: 20px; height: 20px; display: block; margin-left: 2px; }

/* ============================================================
   C3 灯箱（打开才建、关闭即清；z 高于应用弹窗 1000，低于 toast 9999）
   ============================================================ */

.v-lightbox {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2000;
    background: #000; /* P-104：纯黑遮罩——半透明会透出底层面板/左栏鬼影 */
    display: flex;
    align-items: center;
    justify-content: center;
}

.v-lightbox-stage {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.v-lightbox-media {
    max-width: 100%;
    max-height: 90vh; /* F2：竖长图不铺满——上下留白，点空白可关（P-042） */
    object-fit: contain;
    display: block;
    transition: transform .18s ease; /* F2 双击缩放过渡 */
}

/* F2：拖平移期间关过渡（跟手） */
.v-lightbox-media.v-lightbox-zoomdrag {
    transition: none;
}

video.v-lightbox-media {
    width: 100%;
    max-height: 80%;
    background: #000;
}

/* F2：关闭钮=固定深色底圆形（不透图）——浅色竖长图上 × 不再隐身（P-011） */
.v-lightbox-close {
    position: absolute;
    top: calc(12px + env(safe-area-inset-top, 0px)); /* 刘海不切 × */
    right: 12px;
    width: 44px;   /* 触摸区≥44 */
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: #1B1B1B; /* 深色实底圆形：叠任何浅色图都可见 */
    color: #FFFFFF;
    font-size: 24px;
    line-height: 44px;
    text-align: center;
    cursor: pointer;
    z-index: 2;
}

.v-lightbox-count {
    position: absolute;
    /* P-104：计数落到顶栏区之下（顶栏真高 nav.js 实测写入变量），不再压「效果图」标题 */
    top: calc(var(--visitor-header-offset, 56px) + 8px);
    left: 0;
    padding: 8px 16px;
    color: rgba(255, 255, 255, .85);
    font-size: 13px;
    z-index: 2;
}

.v-lightbox-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    border: 0;
    background: rgba(0, 0, 0, .35);
    color: #FFFFFF;
    font-size: 30px;
    line-height: 1;
    width: 44px;      /* 命中区≥44 */
    height: 56px;
    cursor: pointer;
    z-index: 2;
    border-radius: 8px;
}

.v-lightbox-prev { left: 8px; }
.v-lightbox-next { right: 8px; }

/* 到头/单图：隐藏翻页键（不占命中区） */
.v-lightbox-nav.off { display: none; }

/* F2：放大态提示可拖 */
.v-lightbox-zoomed .v-lightbox-stage,
.v-lightbox-zoomed img.v-lightbox-media { cursor: move; }

.v-lightbox-loading {
    position: absolute;
    width: 28px;
    height: 28px;
    border: 3px solid rgba(255, 255, 255, .25);
    border-top-color: #FFFFFF;
    border-radius: 50%;
    animation: vlbSpin 0.8s linear infinite;
}

.v-lightbox-error {
    position: absolute;
    color: rgba(255, 255, 255, .85);
    font-size: 13px;
}

@keyframes vlbSpin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* ============================================================
   Q4 群聊面板（设计 v3 §三/§六）
   面板本体 .visitor-panel 叠放契约不变；内部改 flex 列：
   群头（群名/人数/成员钮）+ 消息流（内部滚）+ 禁言提示 + 发言框。
   禁言=输入区置灰+提示；成员抽屉内部叠放。文案全 textContent。
   ============================================================ */

.visitor-panel[data-panel="group"] {
    display: flex;
    flex-direction: column;
    overflow: hidden; /* 滚动交给 .group-msgs（面板级 overflow-y 会和内部滚打架） */
}

.group-head {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    background: var(--surface-white, #FFFFFF);
    border-bottom: 0.5px solid var(--border-light, #E5E5EA);
}

.group-head-name {
    flex: 0 1 auto;
    min-width: 0; /* V2 防御（2026-08-25 双审）：长群名可收缩，不顶出成员按钮热区 */
    max-width: 52%;
    font-size: 15px;
    font-weight: 600;
    color: var(--text-primary, #1C1C1E);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.group-head-count {
    flex: 1 1 auto;
    font-size: 12px;
    color: var(--text-stone, #8E8E93);
}

.group-head-members {
    flex: 0 0 auto;
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 10px;
    background: transparent;
    color: var(--text-stone-strong, #636366);
    font-size: 12px;
    padding: 4px 10px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}


/* P-066：消息流外包一层，给「回到底部」浮钮绝对定位（不能放进滚动容器里） */
.group-msgs-wrap {
    flex: 1 1 auto;
    min-height: 0;
    position: relative;
    display: flex;
    flex-direction: column;
}

.group-msgs {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px;
}

.group-history-more {
    align-self: center;
    flex: 0 0 auto;
    border: 0;
    background: transparent;
    color: var(--text-stone, #8E8E93);
    font-size: 12px;
    padding: 4px 8px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.group-jump-bottom {
    position: absolute;
    right: 12px;
    bottom: 12px;
    z-index: 3;
    display: none;
    align-items: center;
    border: 0;
    border-radius: 16px;
    padding: 6px 12px;
    font-size: 12px;
    color: #FFFFFF;
    background: var(--brand-primary, #07C160);
    box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.group-jump-bottom.show { display: flex; }

.group-msg {
    max-width: 78%;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.group-msg.other { align-self: flex-start; align-items: flex-start; }
.group-msg.self { align-self: flex-end; align-items: flex-end; }
.group-msg.system { align-self: center; max-width: 92%; align-items: center; }

.group-msg-who {
    font-size: 11px;
    color: var(--text-stone, #8E8E93);
    padding: 0 4px;
}

.group-bubble {
    font-size: 14px;
    line-height: 1.45;
    padding: 8px 12px;
    border-radius: 12px;
    background: var(--surface-white, #FFFFFF);
    color: var(--text-primary, #1C1C1E);
    white-space: pre-wrap;
    word-break: break-word;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}

.group-msg.self .group-bubble {
    background: var(--brand-primary, #07C160);
    color: #FFFFFF;
}

.group-msg.system .group-bubble {
    background: transparent;
    box-shadow: none;
    color: var(--text-stone, #8E8E93);
    font-size: 12px;
    padding: 2px 8px;
}

.group-msg-failed .group-bubble { opacity: .55; }

/* G2：媒体可点占位（图/视频/GIF/语音）。文案仍 textContent 死标签样子，
   只是可点——点才按类载媒体（灯箱/<audio>），无 url 载荷不挂此类保持不可点 */
.group-bubble-media { cursor: pointer; }
.group-bubble-media:active { opacity: .7; }
/* 语音播放中的泡（再点=暂停） */
.group-bubble-playing { opacity: .7; }

/* G5：自家媒体内联直出（老板 2026-08-27 实测裁定：群里图片视频直接显示，
   真外链才占位）。气泡收窄贴边，媒体自带圆角 */
.group-bubble-inline { padding: 4px; line-height: 0; }
.group-media-img {
    display: block;
    max-width: 220px;
    max-height: 220px;
    width: auto;
    height: auto;
    border-radius: 8px;
    cursor: zoom-in; /* 点图=放大进 C3 灯箱 */
}
.group-media-video {
    display: block;
    width: 260px;
    max-width: 62vw;
    border-radius: 8px;
    background: #000;
}
.group-bubble-inline.group-bubble-video { cursor: default; } /* 视频交互归原生 controls，不挂可点暗示 */
/* 语音声音条：喇叭+秒数，点泡即播（G2 <audio> 单实例） */
.group-voice-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 108px;
    min-height: 24px;
    line-height: 1.45;
}
.group-voice-icon { width: 18px; height: 18px; flex: 0 0 auto; display: inline-flex; }
.group-voice-icon svg { width: 100%; height: 100%; }
.group-voice-dur { font-size: 13px; opacity: .75; }

.group-fail-note {
    font-size: 11px;
    color: #E53E3E;
    padding: 0 4px;
}

.group-mute-tip {
    flex: 0 0 auto;
    text-align: center;
    font-size: 12px;
    color: #B42318;
    background: #FEF3F2;
    padding: 6px 12px;
}

.group-dock {
    flex: 0 0 auto;
    display: flex;
    gap: 8px;
    padding: 8px 12px;
    padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    background: var(--surface-white, #FFFFFF);
    border-top: 0.5px solid var(--border-light, #E5E5EA);
}

.group-input {
    flex: 1 1 auto;
    min-width: 0;
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 18px;
    padding: 8px 14px;
    font-size: 14px;
    background: var(--bg-chat, #F2F2F2);
    color: var(--text-primary, #1C1C1E);
    outline: none;
}

.group-input:disabled { background: #EFEFF4; color: #B9B9C4; }

.group-send {
    flex: 0 0 auto;
    border: none;
    border-radius: 18px;
    padding: 8px 16px;
    font-size: 14px;
    color: #FFFFFF;
    background: var(--brand-primary, #07C160);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.group-send:disabled { background: #C8C8D0; }

/* 状态层（进群中/失败+重试钮）：面板内绝对叠满 */
.group-status {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    background: var(--bg-chat, #F2F2F2);
    color: var(--text-stone, #8E8E93);
    font-size: 13px;
    text-align: center;
    padding: 0 24px;
}

.group-status-retry {
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 14px;
    background: var(--surface-white, #FFFFFF);
    color: var(--text-stone-strong, #636366);
    font-size: 13px;
    padding: 6px 18px;
    cursor: pointer;
}

/* 成员抽屉（面板内叠放；§六：robot 成员已在 JS 侧过滤） */
.group-members {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 5;
    display: flex;
    flex-direction: column;
    background: var(--bg-chat, #F2F2F2);
}

.group-members-head {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    background: var(--surface-white, #FFFFFF);
    border-bottom: 0.5px solid var(--border-light, #E5E5EA);
}

.group-members-title {
    flex: 1 1 auto;
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary, #1C1C1E);
}

.group-members-count { font-size: 12px; color: var(--text-stone, #8E8E93); }

.group-members-close {
    border: none;
    background: transparent;
    font-size: 16px;
    color: var(--text-stone-strong, #636366);
    cursor: pointer;
    padding: 2px 8px;
}

.group-members-list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 8px 12px;
}

.group-member {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--surface-white, #FFFFFF);
    border-radius: 10px;
    padding: 8px 10px;
}

.group-member-avatar {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    background: rgba(7, 193, 96, .14); /* 老内核兜底 */
    background: color-mix(in srgb, var(--brand-primary, #07C160) 14%, #FFFFFF);
    color: var(--brand-primary, #07C160);
}

.group-member-name {
    font-size: 14px;
    color: var(--text-primary, #1C1C1E);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.group-members-empty {
    color: var(--text-stone, #8E8E93);
    font-size: 12px;
    text-align: center;
    padding: 16px 0;
}

/* 防捣乱闭环 S1-03：public 群成员抽屉官方角色旁标（群主/官方客服） */
.group-member-badge {
    flex: 0 0 auto;
    margin-left: auto;
    font-size: 11px;
    line-height: 1.4;
    color: var(--brand-primary, #07C160);
    background: rgba(7, 193, 96, .12); /* 老内核兜底 */
    background: color-mix(in srgb, var(--brand-primary, #07C160) 12%, #FFFFFF);
    border-radius: 8px;
    padding: 2px 8px;
    white-space: nowrap;
}

/* 防捣乱闭环 S1-06：public 禁言常驻引导（频道口文案，非红色警示条） */
.group-mute-tip.group-mute-tip-public {
    text-align: left;
    font-size: 13px;
    line-height: 1.7;
    color: var(--text-primary, #1C1C1E);
    background: var(--surface-white, #FFFFFF);
    border-top: 0.5px solid var(--border-light, #E5E5EA);
    padding: 10px 14px;
}

/* 引导文案里的「1对1客服」可点位（点击切回一对一面板） */
.group-guide-link {
    color: var(--brand-primary, #07C160);
    font-weight: 600;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

/* G1 折叠公告条（老板口径：群头正中心上方一小条，点=翻书展开）
   位置=群面板 flex 列里群头与消息流之间，不随消息滚走；无公告整条
   visitor-chrome-hidden 不占位。展开交互照抄效果图「详情」.open 模式。 */
.group-notice-bar {
    flex: 0 0 auto;
    background: #FFF9E6; /* 公告暖底，与消息区灰底拉开 */
    border-bottom: 0.5px solid var(--border-light, #E5E5EA);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.group-notice-bar-head {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    flex: 0 0 auto; /* P-065：展开时头条钉住，「收起」不跟正文垂直居中跑到半腰 */
}

.group-notice-summary {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 12px;
    color: #8A6D1A;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap; /* P-065：展开仍一行省略——单段公告第一行=全文，禁止摘要区再铺一遍 */
}

.group-notice-toggle {
    flex: 0 0 auto;
    font-size: 12px;
    color: var(--brand-primary, #07C160);
}

/* 展开区：默认收起（同 .vg-detail 口径）；.open 翻书出全文 */
.group-notice-full {
    display: none;
    padding: 0 12px 8px;
    font-size: 12px;
    line-height: 1.55;
    color: #5C4A12;
    white-space: pre-wrap;
    word-break: break-word;
}

/* P-065：展开限高+区内滚动，不把消息流/输入框顶出屏。
   摘要保持 nowrap（上面已钉死），不再 white-space:normal 把第一行当全文铺第二次。 */
.group-notice-bar.open {
    max-height: 40%;
    min-height: 0;
    display: flex;
    flex-direction: column;
}
.group-notice-bar.open .group-notice-full {
    display: block;
    flex: 1 1 auto;
    min-height: 0;
    max-height: 28vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
}

/* ============================================================
   Q5 内部群订单号门（任务拆分 v2 Q5）
   面板内绝对叠层卡片：订单号/联系方式二选一 → 核验 → 带票进群。
   样式跟界面风（卡片/圆角/品牌色按钮同群面板与效果图详情一路）。
   ============================================================ */

.group-gate {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 6;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: var(--bg-chat, #F2F2F2);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.group-gate-card {
    width: 100%;
    max-width: 360px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 16px;
    background: var(--surface-white, #FFFFFF);
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 12px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .08);
}

.group-gate-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text-primary, #1C1C1E);
}

.group-gate-hint {
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-stone, #8E8E93);
}

.group-gate-input {
    width: 100%;
    box-sizing: border-box;
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 10px;
    padding: 10px 12px;
    font-size: 14px;
    background: var(--bg-chat, #F2F2F2);
    color: var(--text-primary, #1C1C1E);
    outline: none;
}

.group-gate-or {
    text-align: center;
    font-size: 12px;
    color: var(--text-stone, #8E8E93);
}

.group-gate-btn {
    border: none;
    border-radius: 18px;
    padding: 10px 16px;
    font-size: 14px;
    color: #FFFFFF;
    background: var(--brand-primary, #07C160);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.group-gate-btn:disabled { background: #C8C8D0; }

.group-gate-error {
    min-height: 16px;
    font-size: 12px;
    line-height: 1.4;
    color: #B42318;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ============================================================
   O3 进群起名叠层（设计 v3 §二；卡片风同订单号门一路）
   ============================================================ */

.group-name {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 7; /* 门(6)之上：起名先于门出现 */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: var(--bg-chat, #F2F2F2);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.group-name-card {
    width: 100%;
    max-width: 360px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 16px;
    background: var(--surface-white, #FFFFFF);
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 12px;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .08);
}

.group-name-title {
    font-size: 15px;
    font-weight: 600;
    color: var(--text-primary, #1C1C1E);
}

.group-name-hint {
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-stone, #8E8E93);
}

.group-name-input {
    width: 100%;
    box-sizing: border-box;
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 10px;
    padding: 10px 12px;
    font-size: 14px;
    background: var(--bg-chat, #F2F2F2);
    color: var(--text-primary, #1C1C1E);
    outline: none;
}

.group-name-row {
    display: flex;
    gap: 8px;
}

.group-name-btn {
    flex: 1 1 auto;
    border: none;
    border-radius: 18px;
    padding: 10px 16px;
    font-size: 14px;
    color: #FFFFFF;
    background: var(--brand-primary, #07C160);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.group-name-btn:disabled { background: #C8C8D0; }

.group-name-skip {
    flex: 0 0 auto;
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 18px;
    background: transparent;
    color: var(--text-stone-strong, #636366);
    font-size: 13px;
    padding: 10px 14px;
    cursor: pointer;
}

.group-name-error {
    min-height: 16px;
    font-size: 12px;
    line-height: 1.4;
    color: #B42318;
}

/* V2 防御（2026-08-25 双审）：起名门隐藏态双保险。
   现隐藏走 .visitor-chrome-hidden（display:none !important）本就不吃点击；
   再钉 pointer-events:none，防将来隐藏机制改 visibility/opacity 时
   全屏叠层复活拦截群头按钮热区（V2 原症状）。 */
.group-name.visitor-chrome-hidden {
    pointer-events: none !important;
}

/* ============================================================
   C4 面板 chrome 规则（demo 规则⑥⑦）
   非一对一面板：藏整条 bottom-dock（快捷回复/+/emoji/发送）、
   欢迎语、快捷回复条。这些是 chrome 元素不是面板——此处允许
   display:none（面板级禁令只约束面板切换，防 iOS 丢 scrollTop）。
   ============================================================ */

.visitor-chrome-hidden {
    display: none !important;
}

/* ---------------- F1 桌面 ≥768px：入卡一体（2026-08-26 设计双审定稿） ----------------
   rail 弃悬浮改 static 进 shell 的 flex 流，自占 120px 宽让位——不再需要
   margin/left 补丁；左栏+内容作为一个整体居中（老板 2026-08-25 审美反馈：
   左栏飘在窗口最左+大片空白太突兀）。顶距对齐顶栏下缘（实测偏移变量）。 */
@media (min-width: 768px) {
    :root { --visitor-rail-w: 120px; }
    .visitor-rail {
        position: static; /* flex 自让位，键面图标+文字常显 */
        flex: 0 0 auto;
        align-self: flex-start; /* 不拉满整列高：首键对齐顶栏下缘，底部不探进输入区 */
        margin-top: calc(var(--visitor-header-offset, 56px) + 12px);
        width: var(--visitor-rail-w);
        height: auto;
        max-height: calc(100% - var(--visitor-header-offset, 56px) - 92px); /* 键多自滚，底留 80+12 不碰 dock */
        padding: 0 8px; /* 120 - 左右各 8 = 104 键宽 */
        padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    }
    .visitor-shell { max-width: 980px; margin: 0 auto; }
}

/* ---------------- 会诊修集体感（2026-08-25 四方会诊） ---------------- */
/* 按压反馈（全界面就左栏键没有）+ 桌面 hover */
.visitor-rail-key:active { transform: scale(.96); }
@media (hover: hover) {
  .visitor-rail-key:hover { box-shadow: 0 6px 18px rgba(0, 0, 0, .16); }
}

/* 顶栏已全宽，缺角不在；品牌块不再画，避免浮层上叠第二个 logo */


/* ============================================================
   S2-05/S3-01/S3-03 合辑卡（设计稿第四章卡片形态）
   半屏封顶；缩略图 1/2/3+ 列（三图/九宫格）；无 tags 行。
   表态完成态只高亮「已收到反馈」，永不展示计数。
   ============================================================ */
.group-msg.digest {
    max-width: 92%;
    width: min(92%, 420px);
    align-self: flex-start;
    align-items: stretch;
}

.group-digest-card {
    max-height: 50vh; /* 任务书钉死 */
    overflow: hidden;
    background: var(--surface-white, #FFFFFF);
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 12px;
    padding: 12px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
    min-width: 0;
}

.group-digest-title {
    font-size: 15px;
    font-weight: 600;
    line-height: 1.4;
    color: var(--text-primary, #1C1C1E);
    word-break: break-word;
}

.group-digest-sub {
    font-size: 13px;
    line-height: 1.45;
    color: var(--text-stone, #8E8E93);
    word-break: break-word;
    white-space: pre-wrap;
}

.group-digest-grid {
    display: grid;
    gap: 4px;
    min-height: 0;
}

.group-digest-grid-1 { grid-template-columns: 1fr; }
.group-digest-grid-2 { grid-template-columns: 1fr 1fr; }
.group-digest-grid-3 { grid-template-columns: 1fr 1fr 1fr; } /* 三图 / 九宫格 */

.group-digest-thumb {
    width: 100%;
    display: block;
    object-fit: cover;
    border-radius: 8px;
    background: var(--border-light, #E5E5EA);
}

.group-digest-grid-1 .group-digest-thumb {
    height: auto;
    max-height: 160px;
}

.group-digest-grid:not(.group-digest-grid-1) .group-digest-thumb {
    aspect-ratio: 1 / 1;
    height: 100%;
}

.group-digest-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.group-digest-gallery,
.group-digest-consult {
    flex: 1 1 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    padding: 6px 12px;
    border: 0;
    border-radius: 10px;
    font-size: 13px;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.group-digest-gallery {
    background: var(--brand-primary, #07C160);
    color: var(--surface-white, #FFFFFF);
}

.group-digest-consult {
    background: rgba(7, 193, 96, .12);
    background: color-mix(in srgb, var(--brand-primary, #07C160) 12%, #FFFFFF);
    color: var(--brand-primary, #07C160);
}

.group-digest-gallery:active,
.group-digest-consult:active { opacity: .85; }

.group-digest-reacts {
    display: flex;
    gap: 8px;
}

.group-digest-react {
    flex: 1 1 0;
    min-height: 36px;
    padding: 6px 8px;
    border: 0.5px solid var(--border-light, #E5E5EA);
    border-radius: 8px;
    background: var(--surface-white, #FFFFFF);
    color: var(--text-primary, #1C1C1E);
    font-size: 13px;
    font-family: inherit;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.group-digest-react.group-digest-react-done {
    background: rgba(7, 193, 96, .12);
    background: color-mix(in srgb, var(--brand-primary, #07C160) 12%, #FFFFFF);
    color: var(--brand-primary, #07C160);
    border-color: var(--brand-primary, #07C160);
    font-weight: 600;
}

.group-digest-react:active { opacity: .85; }

/* ---------- P-110 访客 1v1 撤回灰化（与群面板 Z10 同口径；app.js renderMessage/markMessageRevoked 消费） ---------- */
.message.message-revoked .bubble.revoked-bubble {
    background: var(--surface-muted, rgba(120, 120, 128, .12));
    color: var(--text-secondary, #8E8E93);
    font-size: 12px;
    padding: 6px 10px;
    border-radius: 10px;
}

/* ============================================================
   V1 消息可达性批（2026-09-11，/tmp/ux_reddot_0902.md 方案 A + C1/C2/C3）
   四个出口共用 nav.js 的 chatOccluded() 一套判定：
     ① .visitor-msg-pill      遮挡态新消息浮条（灯箱/视频弹窗/图片预览/离底/无左栏）
     ② .visitor-rail-badge    计数徽标（见上，8px 纯点已升级）+ 标题 (N) + favicon 角标
     ③ .visitor-jump-bottom   1v1 离底 >120px 浮钮（复用 .group-jump-bottom 组件形）
     ④ .visitor-notify-bell / .visitor-notify-prefs  提醒偏好（存量默认开、新通道默认关）
   z 序口径（一处看清，别再撞）：
     浮条 10003 > video-modal 关闭钮 10002 / video-modal 9999（default 模板）
              > 灯箱 2000 > image-modal 1000 > glass 顶栏 20 / rail 60-62
     浮钮 900：只在一对一面板且无遮挡层时外露，天然不与灯箱/弹窗同屏
     铃铛 1500 / 弹层 1501：顶栏之上、灯箱之下（看图时不需要调提醒，也不盖图）
   纪律：命中区≥44px；无循环动画（只一次性 .15s 淡入，与左栏同口径）；
        浮条不自动消失，只给 ×（自动消失＝又会漏）。
   ============================================================ */

/* ---------- ① 遮挡态新消息浮条 ---------- */
.visitor-msg-pill {
    position: fixed;
    z-index: 10003;
    top: calc(var(--visitor-header-offset, 56px) + 8px);
    left: 12px;
    right: 12px;
    display: none;
    align-items: center;
    box-sizing: border-box;
    min-height: 44px;                 /* 触摸命中区≥44（全篇纪律） */
    padding: 4px 4px 4px 12px;
    border-radius: 22px;
    background: #FFFFFF;
    border: 1px solid rgba(0, 0, 0, .08);
    box-shadow: 0 6px 20px rgba(0, 0, 0, .28);   /* 纯黑灯箱上也要看得出边界 */
    font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif;
    transition: opacity .15s ease;    /* 一次性淡入，绝无循环动画 */
}
.visitor-msg-pill.show { display: flex; }

.visitor-msg-pill-main {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 36px;
    padding: 0;
    border: 0;
    background: transparent;
    text-align: left;
    cursor: pointer;
    font-family: inherit;
    -webkit-tap-highlight-color: transparent;
}
.visitor-msg-pill-icon { flex: 0 0 auto; display: flex; color: var(--brand-primary, #07C160); }
.visitor-msg-pill-icon svg { width: 20px; height: 20px; display: block; }
.visitor-msg-pill-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.visitor-msg-pill-title { font-size: 13px; font-weight: 600; color: #1D1D1F; line-height: 1.3; }
.visitor-msg-pill-sum {
    font-size: 12px;
    color: #8E8E93;
    line-height: 1.3;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.visitor-msg-pill-nosum .visitor-msg-pill-sum { display: none; }

.visitor-msg-pill-close {
    flex: 0 0 auto;
    width: 44px;                      /* 视觉 × 居中，命中区 44 */
    height: 44px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: #8E8E93;
    font-size: 22px;
    line-height: 44px;
    text-align: center;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.visitor-msg-pill-close:active { opacity: .6; }

/* 移动端：只显条数不显摘要（公共场合隐私，方案 §⑥ 裁法）；
   rail 在场左起 56px＝不压 48px 悬浮栏（栏顶在 header+40，浮条底在 header+52，横向错开双保险） */
@media (max-width: 767px) {
    .visitor-msg-pill-sum { display: none; }
    body.visitor-rail-on .visitor-msg-pill { left: 56px; }
    /* 灯箱态再下移一档：不压 .v-lightbox-count（同在顶栏下 8px 起的左上角） */
    .visitor-msg-pill.visitor-msg-pill-lb { top: calc(var(--visitor-header-offset, 56px) + 48px); }
}

/* 桌面：限宽 380 落聊天列右上；rail 在场时列中心右偏 60px（120px 栏的一半） */
@media (min-width: 768px) {
    .visitor-msg-pill {
        left: 50%;
        right: auto;
        width: 380px;
        max-width: calc(100% - 48px);
        transform: translateX(-50%);
    }
    body.visitor-rail-on .visitor-msg-pill { left: calc(50% + 60px); }
}

/* ---------- ③ 1v1 离底浮钮（形状口径照抄 .group-jump-bottom，落点改 body fixed） ---------- */
.visitor-jump-bottom {
    position: fixed;
    right: 12px;
    bottom: calc(var(--visitor-dock-h, 80px) + 12px + env(safe-area-inset-bottom, 0px));
    z-index: 900;
    display: none;
    align-items: center;
    min-height: 32px;
    border: 0;
    border-radius: 16px;
    padding: 6px 12px;
    font-size: 12px;
    color: #FFFFFF;
    background: var(--brand-primary, #07C160);
    box-shadow: 0 2px 8px rgba(0, 0, 0, .18);
    cursor: pointer;
    font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif;
    -webkit-tap-highlight-color: transparent;
}
.visitor-jump-bottom.show { display: flex; }
.visitor-jump-bottom:active { opacity: .85; }

/* ---------- ④ 提醒偏好：顶栏铃铛 + 弹层（全挂 body，#app 子树零侵入） ---------- */
.visitor-notify-bell {
    position: fixed;
    /* 顶栏真高由 nav.js measureHeader 实测写入变量（四模板高度不一）→ 垂直居中 */
    top: calc((var(--visitor-header-offset, 56px) - 44px) / 2);
    right: 4px;
    z-index: 1500;
    width: 44px;
    height: 44px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--header-text, #1D1D1F);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.visitor-notify-bell svg { width: 20px; height: 20px; display: block; }
.visitor-notify-bell:active { opacity: .6; }
/* 两条存量通道都关＝灰铃铛（一眼看出现在不响不震） */
.visitor-notify-bell-mute { opacity: .45; }
/* 顶栏右侧让位（只 CSS，不动 #app 结构）：default/clean/modern 的 #status 不被铃铛压 */
body.visitor-notify-ready .header { padding-right: 48px; }

.visitor-notify-prefs {
    position: fixed;
    z-index: 1501;
    top: calc(var(--visitor-header-offset, 56px) + 4px);
    right: 8px;
    width: 264px;
    max-width: calc(100% - 16px);
    display: none;
    flex-direction: column;
    box-sizing: border-box;
    padding: 10px 12px 8px;
    border-radius: 14px;
    background: #FFFFFF;
    border: 1px solid rgba(0, 0, 0, .08);
    box-shadow: 0 8px 28px rgba(0, 0, 0, .22);
    font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif;
}
.visitor-notify-prefs.show { display: flex; }
.visitor-notify-prefs-head {
    font-size: 13px;
    font-weight: 600;
    color: #1D1D1F;
    padding: 2px 0 6px;
}
.visitor-notify-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    border-top: 1px solid rgba(0, 0, 0, .05);
}
.visitor-notify-row-text { flex: 1 1 auto; min-width: 0; }
.visitor-notify-row-label { font-size: 13px; color: #1D1D1F; }
.visitor-notify-row-desc { font-size: 11px; color: #8E8E93; margin-top: 2px; line-height: 1.35; }
.visitor-notify-switch {
    flex: 0 0 auto;
    min-width: 48px;
    height: 30px;
    padding: 0 10px;
    border: 0;
    border-radius: 15px;
    background: #E5E5EA;
    color: #6B6B70;
    font-size: 12px;
    line-height: 30px;
    text-align: center;
    cursor: pointer;
    font-family: inherit;
    -webkit-tap-highlight-color: transparent;
    transition: background .15s ease, color .15s ease;
}
.visitor-notify-switch.on {
    background: var(--brand-primary, #07C160);
    color: #FFFFFF;
}
