/* =========================================================
   Chatroom 聊天室主题
   视觉规格来自「聊天室主题预览 · Typecho」设计稿，
   变量、配色档位、头像渐变、气泡与布局逐条照搬；
   底部「主题接线」段仅补充服务端渲染需要的正文与状态样式。
   ========================================================= */

:root{
  --green-700:#0f6b38;
  --green-600:#1aa34a;
  --green-500:#22b45c;
  --green-100:#ddf3e6;
  --green-50:#f1faf4;
  --bg:#e7f0ea;
  --panel:#ffffff;
  --text:#20292a;
  --text-2:#75817c;
  --line:#e2ebe5;
  --bg-a:#dceae2; --bg-b:#e7f0ea; --bg-c:#d4e8dc;
  --panel-soft:#f4f8f5;
  --hover:#f2f8f4;
  --hover-2:#f4f9f6;
  --glow-app:0 18px 48px rgba(20,90,55,.18);
  --glow-logo:0 4px 10px rgba(26,163,74,.28);
  --glow-btn:0 4px 12px rgba(26,163,74,.3);
  --glow-btn-h:0 6px 16px rgba(26,163,74,.36);
  --glow-bub:0 4px 12px rgba(26,163,74,.22);
  --glow-home:0 6px 16px rgba(26,163,74,.26);
  --av1:linear-gradient(135deg,#2fbf6b,#1aa34a);
  --av2:linear-gradient(135deg,#21b5a3,#0e9483);
  --av3:linear-gradient(135deg,#6cb828,#4a8f12);
  --av4:linear-gradient(135deg,#159a5b,#0e7a45);
  --av5:linear-gradient(135deg,#37b26f,#1f8f52);
  --av6:linear-gradient(135deg,#8ab52c,#6b9218);
  --cr-bg:none;
}
:root[data-theme="cyan"]{
  --green-700:#0e7a8f; --green-600:#12a3bb; --green-500:#24bcd2; --green-100:#d8f0f5; --green-50:#eefafc;
  --bg-a:#dbeaee; --bg-b:#e7f1f3; --bg-c:#d2e6eb;
  --panel-soft:#f1f8fa; --hover:#eef6f8; --hover-2:#f2f9fb;
  --glow-app:0 18px 48px rgba(10,120,140,.18); --glow-logo:0 4px 10px rgba(18,163,187,.28);
  --glow-btn:0 4px 12px rgba(18,163,187,.3); --glow-btn-h:0 6px 16px rgba(18,163,187,.36);
  --glow-bub:0 4px 12px rgba(18,163,187,.22); --glow-home:0 6px 16px rgba(18,163,187,.26);
  --av1:linear-gradient(135deg,#2fb8cc,#12a3bb); --av2:linear-gradient(135deg,#2bb8a8,#0e9c8c);
  --av3:linear-gradient(135deg,#3fb8c8,#1f8f9e); --av4:linear-gradient(135deg,#18a8bd,#0e8496);
  --av5:linear-gradient(135deg,#2fc4d6,#1796a9); --av6:linear-gradient(135deg,#56c4d0,#2b96a4);
}
:root[data-theme="blue"]{
  --green-700:#1a56a8; --green-600:#2b7de0; --green-500:#4a97ee; --green-100:#dcebfb; --green-50:#f0f6fd;
  --bg-a:#dde7f3; --bg-b:#e8eef7; --bg-c:#d5e2f0;
  --panel-soft:#f2f6fb; --hover:#eef4fb; --hover-2:#f2f7fc;
  --glow-app:0 18px 48px rgba(30,90,180,.18); --glow-logo:0 4px 10px rgba(43,125,224,.28);
  --glow-btn:0 4px 12px rgba(43,125,224,.3); --glow-btn-h:0 6px 16px rgba(43,125,224,.36);
  --glow-bub:0 4px 12px rgba(43,125,224,.22); --glow-home:0 6px 16px rgba(43,125,224,.26);
  --av1:linear-gradient(135deg,#4a97ee,#2b7de0); --av2:linear-gradient(135deg,#5aa3f2,#3b83d6);
  --av3:linear-gradient(135deg,#6fa8ec,#3f7fce); --av4:linear-gradient(135deg,#3a86e6,#2566b8);
  --av5:linear-gradient(135deg,#5ba0f0,#2e6fc9); --av6:linear-gradient(135deg,#7db3f0,#4a86cf);
}
:root[data-theme="yellow"]{
  --green-700:#7d5f00; --green-600:#a87f14; --green-500:#c9981c; --green-100:#f6e9c0; --green-50:#fdf9ea;
  --bg-a:#efe7d3; --bg-b:#f4eee0; --bg-c:#e9ddc4;
  --panel-soft:#faf6ec; --hover:#f6f1e3; --hover-2:#f8f4ea;
  --glow-app:0 18px 48px rgba(140,110,20,.18); --glow-logo:0 4px 10px rgba(201,160,18,.28);
  --glow-btn:0 4px 12px rgba(201,160,18,.3); --glow-btn-h:0 6px 16px rgba(201,160,18,.36);
  --glow-bub:0 4px 12px rgba(201,160,18,.22); --glow-home:0 6px 16px rgba(201,160,18,.26);
  --av1:linear-gradient(135deg,#c9981c,#a87f14); --av2:linear-gradient(135deg,#cfae2e,#b08d1c);
  --av3:linear-gradient(135deg,#c9b23a,#a08a1c); --av4:linear-gradient(135deg,#cfa71e,#b08d14);
  --av5:linear-gradient(135deg,#dfbe45,#bf9c22); --av6:linear-gradient(135deg,#d9c452,#b09d2c);
}

/* ============ 深色档：只改中性色与光晕，四套配色各自再压暗主色 ============ */
:root[data-mode="dark"]{
  --green-700:#8fe0b4; --green-600:#5cc98d; --green-500:#33ac6f; --green-100:#25402f; --green-50:#1c3126;
  --bg:#121917;
  --panel:#1b2320;
  --text:#e7efe9;
  --text-2:#93a49a;
  --line:#2c3833;
  --bg-a:#151d1a; --bg-b:#121917; --bg-c:#0f1614;
  --panel-soft:#202a25;
  --hover:#222d27;
  --hover-2:#253129;
  --glow-app:0 18px 48px rgba(0,0,0,.5);
  --glow-logo:0 4px 10px rgba(0,0,0,.4);
  --glow-btn:0 4px 12px rgba(0,0,0,.42);
  --glow-btn-h:0 6px 16px rgba(0,0,0,.5);
  --glow-bub:0 4px 12px rgba(0,0,0,.36);
  --glow-home:0 6px 16px rgba(0,0,0,.4);
}
:root[data-mode="dark"][data-theme="cyan"]{
  --green-700:#8fdfe9; --green-600:#4cc4d6; --green-500:#22a8bd; --green-100:#1e3a40; --green-50:#172c31;
  --bg-a:#121b1d; --bg-b:#101718; --bg-c:#0d1517;
}
:root[data-mode="dark"][data-theme="blue"]{
  --green-700:#a9ccf7; --green-600:#6ba6ec; --green-500:#3f81d6; --green-100:#1f3049; --green-50:#182538;
  --bg-a:#131a24; --bg-b:#111721; --bg-c:#0e141d;
}
:root[data-mode="dark"][data-theme="yellow"]{
  --green-700:#f0dda0; --green-600:#d9bb5c; --green-500:#b8901f; --green-100:#3a3320; --green-50:#2b2618;
  --bg-a:#1b1811; --bg-b:#161410; --bg-c:#121009;
}
/* 深色下需要跟着翻白的几处硬编码 */
:root[data-mode="dark"] body.has-bg::before{background:rgba(6,10,8,.55)}
:root[data-mode="dark"] .msg.them .bubble{background:var(--panel);box-shadow:0 1px 2px rgba(0,0,0,.35)}
:root[data-mode="dark"] .t-dot.active::before{box-shadow:0 0 0 2px var(--panel),0 0 0 4px rgba(230,240,235,.4),inset 0 0 0 1px rgba(255,255,255,.12)}
:root[data-mode="dark"] .reply-bar .rb-close:hover{background:var(--text);color:var(--panel)}
:root[data-mode="dark"] .mode-dot .mi-moon{display:none}
:root[data-mode="dark"] .mode-dot .mi-sun{display:inline}
/* 深浅色按钮：不要色点那个圆，直接显示太阳 / 月亮 */
.mode-dot::before{display:none}
.mode-dot{color:var(--text-2)}
.mode-dot svg{width:16px;height:16px;transition:transform .12s}
.mode-dot:hover svg{transform:scale(1.15);color:var(--green-600)}
.mode-dot .mi-sun{display:none}
.mode-dot .mi-moon{display:inline}

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
body{
  font-family:"PingFang SC","Microsoft YaHei","Segoe UI",system-ui,-apple-system,sans-serif;
  background-color:var(--bg-b);
  background-image:var(--cr-bg),linear-gradient(160deg,var(--bg-a) 0%,var(--bg-b) 55%,var(--bg-c) 100%);
  background-position:center top;
  background-repeat:no-repeat;
  background-attachment:fixed;
  background-size:cover;
  color:var(--text);
  font-size:15px;
  line-height:1.6;
}
/* 背景图上层盖一层薄遮罩，聊天窗四周不至于花到看不清 */
body.has-bg::before{
  content:"";position:fixed;top:0;left:0;right:0;bottom:0;z-index:-1;pointer-events:none;
  background:rgba(255,255,255,.42);
}
button{font-family:inherit;font-size:inherit}
a{color:inherit;text-decoration:none}
input,textarea{font-family:inherit}
:focus-visible{outline:2px solid var(--green-600);outline-offset:2px}

.app{
  display:flex;
  flex-direction:column;
  height:100vh;
  height:100dvh;
  background:var(--panel);
}
@media(min-width:768px){
  body{display:flex;align-items:center;justify-content:center}
  .app{
    flex-direction:row;
    max-width:1180px;
    width:100%;
    margin:14px auto;
    height:calc(100vh - 28px);
    height:calc(100dvh - 28px);
    border-radius:16px;
    overflow:hidden;
    box-shadow:var(--glow-app);
  }
}

/* ===== 侧栏 ===== */
.sidebar{
  display:flex;flex-direction:column;
  width:100%;min-height:0;
  background:var(--panel);
  border-right:1px solid var(--line);
}
@media(min-width:768px){.sidebar{width:300px;flex-shrink:0}}
.brand{
  display:flex;align-items:center;gap:10px;
  padding:14px 16px 10px;
}
.brand-logo{
  position:relative;
  width:38px;height:38px;border-radius:11px;flex-shrink:0;
  background:linear-gradient(135deg,var(--green-500),var(--green-600));
  display:flex;align-items:center;justify-content:center;color:#fff;
  box-shadow:var(--glow-logo);
}
/* 后台填了 Logo 时替换这颗渐变图标：底色透明、图撑满圆角框；图加载失败被 onerror 摘掉后渐变图标自己回来 */
.brand-logo:has(.brand-img){background:none;box-shadow:none}
.brand-logo:has(.brand-img) svg{display:none}
.brand-img{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain;border-radius:11px;display:block}
.brand-name{font-size:16px;font-weight:700;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.brand-sub{font-size:11px;color:var(--text-2);letter-spacing:.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.search{position:relative;margin:6px 14px 12px}
.search input{
  width:100%;height:38px;border:none;border-radius:11px;
  background:var(--green-50);color:var(--text);
  padding:0 12px 0 36px;font-size:16px;
}
.search input::placeholder{color:#9aa8a0}
.search svg{position:absolute;left:11px;top:50%;transform:translateY(-50%);color:#7d8d85;pointer-events:none}

.nav-row{display:flex;align-items:stretch;gap:2px;padding:4px 10px 10px;border-bottom:1px solid var(--line);margin-bottom:10px}
.nav-item{
  flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  border:none;background:transparent;cursor:pointer;color:#7d8d85;
  padding:7px 2px;min-height:46px;border-radius:10px;
}
.nav-item em{font-style:normal;font-size:10.5px;line-height:1}
.nav-item svg{display:block}
.nav-item.active{color:var(--green-600);background:var(--green-50)}
.nav-item:hover{background:var(--hover)}

.c-status{font-size:11px;color:#9aa8a0;flex-shrink:0}
.c-status.on{color:var(--green-600)}
.c-time{font-size:11px;color:#9aa8a0;flex-shrink:0}
.c-count{
  font-size:11px;color:var(--green-600);background:var(--green-50);
  border:1px solid var(--green-100);border-radius:10px;padding:1px 7px;flex-shrink:0;
}
.c-arrow{font-size:17px;color:#b3bfb8;flex-shrink:0;line-height:1}
.c-feed{
  display:inline-flex;align-items:center;gap:3px;flex-shrink:0;
  height:18px;padding:0 6px;border-radius:9px;
  background:var(--green-50);color:var(--green-600);
  font-size:11px;line-height:1;cursor:pointer;
}
.c-feed:hover{background:var(--green-100)}

.contact-list{flex:1;overflow-y:auto;min-height:0;padding:0 0 12px}
.side-foot{
  flex-shrink:0;
  border-top:1px solid var(--line);
  padding:10px 16px 12px;
  font-size:11px;line-height:1.7;
  color:var(--text-2);
}
.foot-copy{color:var(--text-2);word-break:break-all}
.foot-row a{
  display:inline-flex;align-items:center;gap:5px;
  color:var(--text-2);text-decoration:none;word-break:break-all;
}
.foot-row a:hover{color:var(--green-600)}
.foot-row img{width:13px;height:13px;flex-shrink:0}
.contact{
  display:flex;align-items:center;gap:12px;
  padding:11px 14px 11px 16px;cursor:pointer;
  border-left:3px solid transparent;
  transition:background .15s;
}
.contact:hover{background:var(--hover-2)}
.contact.active{background:var(--green-50);border-left-color:var(--green-600)}
.contact.kind-post .avatar{border-radius:9px}
.contact.kind-link{cursor:pointer}
.avatar{
  position:relative;
  width:42px;height:42px;border-radius:50%;flex-shrink:0;
  display:flex;align-items:center;justify-content:center;
  color:#fff;font-size:17px;font-weight:600;
  overflow:hidden;
}
.a1{background:var(--av1)}
.a2{background:var(--av2)}
.a3{background:var(--av3)}
.a4{background:var(--av4)}
.a5{background:var(--av5)}
.a6{background:var(--av6)}
.avatar-img{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;display:block;border-radius:inherit}
.c-main{flex:1;min-width:0;display:block}
.c-top{display:flex;align-items:center;justify-content:space-between;gap:8px}
.c-name{font-size:14.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.c-badge{
  min-width:20px;height:20px;padding:0 6px;border-radius:10px;
  background:var(--green-600);color:#fff;font-size:11.5px;font-weight:600;
  display:flex;align-items:center;justify-content:center;
}
.c-badge.zero{display:none}
.c-sub{
  font-size:12.5px;color:var(--text-2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%;
  display:block;
}
.list-empty{padding:32px 16px;text-align:center;color:var(--text-2);font-size:13.5px}

/* ===== 评论视图的折叠：文章评论 / 聊天记录两份清单 ===== */
.cmt-fold[hidden]{display:none}
.cmt-switch{
  display:block;margin:6px 12px 10px;padding:8px 12px;
  border:1px dashed var(--line);border-radius:8px;
  background:var(--panel-soft);color:var(--green-700);
  font-size:12.5px;font-weight:600;text-align:center;text-decoration:none;cursor:pointer;
}
.cmt-switch:hover{background:var(--green-50);border-style:solid;border-color:var(--green-600)}

/* ===== 聊天窗 ===== */
.chat{display:none;flex:1;flex-direction:column;min-width:0;background:var(--panel-soft);position:relative}
.app.show-chat .chat{display:flex}
.app.show-chat .sidebar{display:none}
@media(min-width:768px){
  .chat{display:flex}
  .app.show-chat .sidebar{display:flex}
  .back-btn{display:none!important}
}
.chat-header{
  display:flex;align-items:center;gap:12px;
  padding:11px 16px;background:var(--panel);border-bottom:1px solid var(--line);
}
.chat-title{flex:1;min-width:0}
.chat-name{font-size:15px;font-weight:700;display:flex;align-items:center;gap:6px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.online-dot{width:8px;height:8px;border-radius:50%;background:#cfd8d3;flex-shrink:0}
.online-dot.on{background:var(--green-500)}
.chat-mail{font-size:12px;color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hd-actions{display:flex;align-items:center;gap:2px}
.hd-btn{
  width:40px;height:40px;border:none;background:transparent;border-radius:10px;
  display:flex;align-items:center;justify-content:center;color:#5d6b64;cursor:pointer;
  transition:background .15s;
}
.hd-btn:hover{background:var(--green-50);color:var(--green-600)}
.icon-btn{width:44px;height:44px;display:inline-flex;align-items:center;justify-content:center}
.theme-dots{display:flex;align-items:center;gap:8px;padding-left:10px;margin-left:4px;border-left:1px solid var(--line)}
.t-dot{
  width:24px;height:24px;border:none;background:transparent;cursor:pointer;
  position:relative;padding:0;display:flex;align-items:center;justify-content:center;
}
.t-dot::before{
  content:'';width:16px;height:16px;border-radius:50%;
  background:var(--dot,#ccc);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.08);
  transition:transform .12s;
}
.t-dot:hover::before{transform:scale(1.18)}
.t-dot::after{content:'';position:absolute;inset:-10px;border-radius:50%}
.t-dot.active::before{box-shadow:0 0 0 2px #fff,0 0 0 4px rgba(30,40,35,.45),inset 0 0 0 1px rgba(0,0,0,.08)}
@media(max-width:520px){
  .hd-btn[data-act="open"]{display:none}
}

.chat-body{flex:1;overflow-y:auto;padding:18px 16px 10px;min-height:0}
.msg{display:flex;gap:10px;margin-bottom:18px;max-width:100%}
.msg.me{flex-direction:row-reverse}
.msg-main{max-width:min(74%,560px);min-width:0}
.meta{
  display:flex;align-items:baseline;gap:8px;
  margin-bottom:4px;font-size:12px;color:var(--text-2);
}
.meta .mname{font-weight:600;color:#3f4d46}
:root[data-mode="dark"] .meta .mname{color:#c3d1c8}
.meta .memail{font-size:11.5px}
.meta .mtime{margin-left:auto}
.msg.me .meta{justify-content:flex-end}
.bubble{
  padding:10px 14px;border-radius:13px;
  font-size:14px;line-height:1.65;word-break:break-word;
}
.msg.them .bubble{
  background:#fff;border:1px solid var(--line);
  border-top-left-radius:3px;
  box-shadow:0 1px 2px rgba(30,80,55,.05);
}
.msg.me .bubble{
  background:linear-gradient(135deg,var(--green-500),var(--green-600));
  color:#fff;border-top-right-radius:3px;
  box-shadow:var(--glow-bub);
}
/* 从「评论」列表跳转过来时高亮那一条 */
.msg.focus .bubble{animation:msg-focus 2.4s ease-out}
@keyframes msg-focus{
  0%,60%{box-shadow:0 0 0 3px var(--green-300,#8fe0af)}
  100%{box-shadow:0 0 0 0 rgba(0,0,0,0)}
}
.bubble p{margin:.4em 0}
.bubble p:first-child{margin-top:0}
.bubble p:last-child{margin-bottom:0}
.bubble img{max-width:100%;height:auto;border-radius:8px}
.bubble a{color:var(--green-600);text-decoration:underline}
.msg.me .bubble a{color:#fff}
.bubble pre{background:var(--panel-soft);border:1px solid var(--line);border-radius:8px;padding:8px 10px;overflow-x:auto;font-size:12.5px}
.reply-to{display:inline-block;font-size:12px;color:var(--green-600);margin-right:6px}
.msg.me .reply-to{color:#fff;opacity:.85}

/* 同一作者连发时收敛头像与元信息（设计稿没有的细节，纯视觉） */
.msg.same .meta{display:none}
.msg.same{margin-bottom:10px}

/* 二级嵌套：文章会话里的回复挂到被回复的那条下面，只嵌一层 */
.msg-children{margin:-8px 0 18px 52px;padding-left:12px;border-left:2px solid var(--line)}
.msg-children .msg{margin-bottom:12px}
.msg-children .avatar{width:30px;height:30px;font-size:13px}
.msg-children .msg-main{max-width:min(86%,540px)}
.mtag{
  display:inline-block;padding:0 6px;border-radius:999px;
  font-size:11px;line-height:17px;background:var(--green-100);color:var(--green-700);
}
.mtag.ai{background:#efe6fb;color:#6b46c1}
.m-reply{
  appearance:none;border:0;background:transparent;cursor:pointer;
  color:var(--text-2);font-size:11.5px;line-height:17px;padding:0 5px;border-radius:6px;
}
.m-reply:hover{color:var(--green-700);background:var(--green-50)}

/* 表情面板：入口在输入框左侧，面板往上弹 */
.emoji{position:relative;flex-shrink:0}
.emoji > summary{
  list-style:none;display:flex;align-items:center;justify-content:center;
  width:38px;height:44px;border-radius:11px;cursor:pointer;
  background:var(--panel-soft);color:var(--text-2);
}
.emoji > summary::-webkit-details-marker{display:none}
.emoji > summary:hover{color:var(--green-600);background:var(--green-50)}
.emoji-pop{
  position:absolute;left:0;bottom:calc(100% + 8px);z-index:20;
  width:min(324px,76vw);display:grid;grid-template-columns:repeat(10,1fr);gap:2px;
  padding:8px;background:var(--panel);border:1px solid var(--line);
  border-radius:12px;box-shadow:var(--glow-app);
}
.emoji-item{
  appearance:none;border:0;background:transparent;cursor:pointer;
  font-size:19px;line-height:1;padding:5px 0;border-radius:8px;
}
.emoji-item:hover{background:var(--green-50)}
@media (max-width:560px){.emoji-pop{grid-template-columns:repeat(8,1fr)}}

.chat-input{
  display:flex;flex-direction:column;gap:10px;
  padding:12px 14px 14px;background:var(--panel);border-top:1px solid var(--line);
}
.chat-fields{display:flex;gap:10px}
.chat-fields input{
  flex:1;min-width:0;border:none;border-radius:11px;
  background:var(--green-50);padding:9px 12px;color:var(--text);font-size:14px;
}
.chat-fields input::placeholder{color:#9aa8a0}
.chat-as{font-size:12.5px;color:var(--text-2)}
.chat-as a{color:var(--green-600)}
/* 点评论上的「回复」后显示：parent 隐藏域已写入，这里只是给用户看见挂在哪条上 */
.reply-bar{
  display:none;align-items:center;justify-content:space-between;gap:8px;
  align-self:flex-start;max-width:100%;
  font-size:12px;color:var(--green-700,#2f7d52);
  background:var(--green-50);border:1px solid var(--line);
  border-radius:8px;padding:5px 6px 5px 10px;
}
.reply-bar.on{display:flex}
.reply-bar .rb-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.reply-bar .rb-close{
  flex-shrink:0;border:none;background:transparent;cursor:pointer;
  width:20px;height:20px;line-height:20px;padding:0;
  border-radius:6px;color:var(--text-2);font-size:12px;
}
.reply-bar .rb-close:hover{background:#fff;color:var(--green-600)}
.chat-send{display:flex;align-items:flex-end;gap:10px}
.chat-input textarea{
  flex:1;min-width:0;resize:none;border:none;outline:none;
  font-size:16px;line-height:1.5;color:var(--text);
  background:var(--panel-soft);border-radius:12px;padding:10px 14px;height:44px;
  max-height:120px;
}
.chat-input textarea::placeholder{color:#9aa8a0}
.send-btn{
  width:46px;height:46px;border:none;border-radius:50%;
  background:linear-gradient(135deg,var(--green-500),var(--green-600));
  color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;
  box-shadow:var(--glow-btn);
  transition:transform .12s,box-shadow .12s;
}
.send-btn:hover{transform:translateY(-1px);box-shadow:var(--glow-btn-h)}
.send-btn:active{transform:scale(.94)}
.send-btn[disabled]{opacity:.55;cursor:progress;transform:none;box-shadow:none}
.chat-closed{padding:14px;text-align:center;color:var(--text-2);font-size:13.5px;background:var(--panel);border-top:1px solid var(--line)}
.msg.pending{opacity:.6}
.msg.failed .bubble{background:#fdeceb;border-color:#f6c9c6;color:#9c2b26}
.new-msgs{position:absolute;left:50%;bottom:88px;transform:translateX(-50%);z-index:5}
.new-msgs button{
  border:none;border-radius:14px;background:var(--green-600);color:#fff;
  font-size:12.5px;padding:6px 14px;cursor:pointer;box-shadow:var(--glow-btn);
}

/* ===== 右下浮动操作钮：深色切换 + 直达评论区 + 一滚就露出的回到顶部 =====
   位置分两档，跟 floatNavPaint() 的 doc-scroll 判定对应：
   - 容器在滚（桌面右栏读文章）：sticky 粘在 #chatBody 右下角，不压输入框；
   - 文档在滚（整页文章 / 独立页 / 窄屏）：#chatBody 自己也带着 overflow:auto，
     但高度等于内容，sticky 会被它困在内容末尾（只滚到底才看得到），所以改成 fixed 钉在视口右下角。
   height:0 + column-reverse 让钮子往上叠：不给正文末尾添出一段空白。 */
.float-nav{
  position:sticky;bottom:14px;z-index:7;height:0;
  display:flex;flex-direction:column-reverse;align-items:flex-end;gap:8px;
  margin-right:-6px;
}
/* 整页 / 窄屏：离屏幕底边留足距离，靠右下但不贴角、也不压着页底发言框。服务端默认给这一档，前端按实际容器改 */
.float-nav.doc-scroll{position:fixed;right:18px;bottom:88px;z-index:30;margin-right:0}
.fn-btn{
  width:38px;height:38px;padding:0;border:1px solid var(--line);border-radius:50%;
  background:var(--panel);color:var(--text-2);cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  /* 容器高 0 时 flex 子项默认会被压扁，38×38 的圆会变成椭圆；这里禁止收缩 */
  flex:0 0 auto;
  box-shadow:0 3px 12px rgba(20,30,25,.14);
  transition:background .15s,color .15s,border-color .15s;
}
.fn-btn:hover{background:var(--green-50);color:var(--green-600);border-color:var(--green-600)}
/* 「回到顶部」服务端就预置 fn-off（在顶部本不该露脸），JS 一滚就摘。
   隐藏这条挂在 html.cr-js 上，而不是 body.no-js 的反面：cr-js 由 header 里那行内联脚本在首次绘制之前打上，
   所以有脚本时第一帧就是隐藏的，不会再出现「先亮一下再淡出去」；没脚本时这条不生效，按钮都常驻可点，走真锚点。 */
/* 藏起来时直接不占位：独立页「直达评论区」上方不留空洞，也不会给正文末尾添出一段空白 */
html.cr-js .fn-btn.fn-off{display:none}
/* 一滚就露脸：display 从 none 切回来时重新触发这段淡入 */
@keyframes fnPop{from{opacity:0;transform:translateY(8px) scale(.85)}to{opacity:1;transform:none}}
html.cr-js .fn-btn:not(.fn-off){animation:fnPop .18s ease-out}
:root[data-mode="dark"] .fn-btn{box-shadow:0 3px 12px rgba(0,0,0,.5)}

.toast{
  position:fixed;left:50%;bottom:30px;transform:translate(-50%,12px);
  background:#1d2b24;color:#fff;font-size:13.5px;
  padding:9px 16px;border-radius:9px;opacity:0;pointer-events:none;
  transition:opacity .22s,transform .22s;z-index:60;
  box-shadow:0 8px 24px rgba(0,0,0,.18);
}
.toast.show{opacity:1;transform:translate(-50%,0)}
@media(prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}

/* =========================================================
   主题接线：聊天窗内的正文与清单、列表页、非 JS 回退
   ========================================================= */
.main{flex:1;min-width:0;min-height:0;overflow-y:auto;background:var(--panel-soft);display:flex;flex-direction:column}

/* 正文与消息同在一个滚动容器里：正文在上，评论区在下 */
.post-doc{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:16px 18px;margin:0 auto 14px;max-width:860px;width:100%}
.post-meta{display:flex;flex-wrap:wrap;gap:4px 14px;font-size:12.5px;color:var(--text-2);margin-bottom:10px}
.post-meta .p-author{color:var(--green-600);font-weight:600}
.post-meta .p-edit a{color:var(--green-600)}
.room-sep{display:flex;justify-content:center;margin:6px 0 16px}
.msgs{max-width:860px;margin:0 auto}
.room-sep span{
  font-size:11.5px;color:var(--text-2);background:var(--panel);
  border:1px solid var(--line);border-radius:10px;padding:2px 10px;
}

/* 文章目录：正文标题够三个才出现。正文上方是一块展开的目录，
   滚过它之后整块吸在滚动容器顶、由脚本折成一条（.toc-stuck），当前小节高亮 */
.post-toc{
  background:var(--panel-soft);border:1px solid var(--line);border-radius:12px;
  padding:0 12px;margin:0 0 12px;
  position:sticky;top:0;z-index:6;
}
.post-toc summary{
  display:flex;align-items:center;gap:8px;cursor:pointer;list-style:none;
  padding:9px 0;font-size:12.5px;font-weight:600;color:var(--green-600);
}
.post-toc summary::-webkit-details-marker{display:none}
.toc-caret::before{content:'▸';font-size:11px;display:inline-block;transition:transform .16s}
.post-toc[open] .toc-caret::before{transform:rotate(90deg)}
.post-toc .toc-n{
  font-size:11px;font-weight:600;color:var(--green-700);background:var(--green-50);
  border-radius:9px;padding:1px 7px;
}
/* 折叠态那一条换成「当前小节 + 第几/共几」，展开态只留标题与总数 */
.post-toc .toc-cur,.post-toc .toc-pos,.post-toc[open] .toc-cur{display:none}
.post-toc:not([open]) .toc-label{display:none}
.post-toc:not([open]) .toc-cur{
  display:block;flex:1;min-width:0;color:var(--text-2);font-weight:500;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.post-toc:not([open]) .toc-pos{display:block;font-size:11px;color:var(--text-2);font-weight:500}
.post-toc:not([open]) .toc-n{display:none}
/* 吸顶后浮在正文之上，加一道投影分清层次 */
.post-toc.toc-stuck{box-shadow:0 6px 16px rgba(20,60,40,.12);border-radius:0 0 12px 12px}
/* 零高度占位：sticky 的自己报不出「自然位置」，脚本靠它判断有没有滚过目录；
   吸顶后脚本又把目录展开时的高度回填给它——折叠只改视觉，正文一行都不许跳 */
.toc-sentinel{display:block;height:0;margin:0;padding:0;border:0;font-size:0}
/* 整页文章（post.php）里 #chatBody 也是 overflow:auto 却滚不动，sticky 会被它困住——
   这一档由脚本换 fixed 钉在视口顶，宽度与正文卡片对齐（卡片左右各 18px 内边距 + 1px 边框） */
.post-toc.toc-fixed{
  position:fixed;top:0;left:50%;transform:translateX(-50%);z-index:8;
  width:calc(min(860px,100% - 32px) - 38px);
  transition:opacity .16s;
}
/* 正文卡片滚出视野后这条没有归属对象了，淡出；占位不撤，所以正文不会跟着动 */
.post-toc.toc-gone{opacity:0;pointer-events:none}
/* 目录本身可能很长：窄屏限高内滚，别把正文顶出首屏 */
.toc-list{
  list-style:none;margin:0 0 10px;padding:0;
  max-height:44vh;overflow-y:auto;
}
.toc-list li{break-inside:avoid}
.toc-list a{
  display:block;font-size:13.5px;line-height:1.5;color:var(--text-2);
  border:0;border-radius:8px;padding:4px 8px;
}
.toc-list a:hover{color:var(--green-600);background:var(--green-50)}
.toc-list a.toc-on{color:var(--green-600);background:var(--green-50);font-weight:600}
.toc-list .toc-d1{padding-left:14px}
.toc-list .toc-d2{padding-left:28px}
/* 宽屏两列按「先填满左列」排，父子标题才不会被拆到两边 */
@media(min-width:760px){
  .toc-list{columns:2;column-gap:22px;max-height:none;overflow:visible}
}
/* 吸顶后在条上点开，列表脱流下拉，压住正文而不是把正文顶开 */
.post-toc.toc-stuck .toc-list{
  position:absolute;top:100%;left:0;right:0;margin:0;padding:4px 10px 10px;
  background:var(--panel);border:1px solid var(--line);border-radius:0 0 12px 12px;
  box-shadow:0 10px 22px rgba(20,60,40,.16);
  max-height:min(56vh,420px);overflow-y:auto;
}

/* 分类 / 归档会话的文章清单 */
.card-list{display:flex;flex-direction:column;gap:10px;max-width:860px;margin:0 auto;width:100%}
.card-item{
  display:flex;align-items:center;gap:12px;width:100%;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  padding:12px 14px;cursor:pointer;
}
.card-item:hover{border-color:var(--green-100);background:var(--green-50)}
.card-thumb{
  width:56px;height:56px;flex-shrink:0;border-radius:10px;overflow:hidden;
  background:var(--green-100) center/cover no-repeat;
  color:var(--green-700);font-size:20px;font-weight:600;
  display:flex;align-items:center;justify-content:center;
}
.card-main{flex:1;min-width:0;display:block}
.card-name{display:block;font-size:15px;font-weight:600;line-height:1.45;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.card-sub{display:block;font-size:12.5px;color:var(--text-2);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.card-meta{display:block;font-size:11.5px;color:#9aa8a0;margin-top:4px}

/* 归档 / 分类总览的分组标题（右栏一份清单，左栏选中的是其中一组） */
.grp-head{
  display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;
  max-width:860px;margin:18px auto 8px;width:100%;padding:0 2px;
}
.grp-head:first-child{margin-top:0}
.grp-name{font-size:14px;font-weight:700;color:var(--green-700)}
.grp-count{font-size:12px;color:var(--text-2)}
.grp-desc{font-size:12px;color:var(--text-2);flex:1 1 100%}
.grp-empty{
  max-width:860px;margin:0 auto;font-size:12.5px;color:var(--text-2);
  padding:10px 14px;border:1px dashed var(--line);border-radius:12px;background:var(--panel-soft);
}

/* 友链右栏：订阅源最新内容，两列卡片 */
.feed-cards{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;
  max-width:860px;margin:0 auto;width:100%;
}
.feed-card{
  display:flex;flex-direction:column;gap:5px;min-width:0;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:12px 14px;
  color:var(--text);cursor:pointer;
}
.feed-card:hover{border-color:var(--green-100);background:var(--green-50)}
.fc-top{display:flex;align-items:baseline;gap:8px;min-width:0}
.fc-site{
  flex:0 1 auto;min-width:0;font-size:12px;font-weight:600;color:var(--green-700);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.fc-time{flex-shrink:0;margin-left:auto;font-size:11.5px;color:#9aa8a0}
.fc-title{
  font-size:14.5px;font-weight:600;line-height:1.5;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}
.fc-text{
  font-size:12.5px;line-height:1.6;color:var(--text-2);word-break:break-all;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.feed-card.miss{background:var(--panel-soft);border-style:dashed}
.feed-card.miss .fc-site{color:var(--text-2)}
@media(max-width:640px){.feed-cards{grid-template-columns:minmax(0,1fr)}}

/* 没有输入框的视图（分类 / 归档 / 友链）补一条底部收边，右栏面板不再敞口 */
.chat-foot{flex-shrink:0;border-top:1px solid var(--line);background:var(--panel);min-height:14px}

.entry-content{font-size:15px;line-height:1.85}
.entry-content h2,.entry-content h3,.entry-content h4{margin:1.1em 0 .5em;line-height:1.4;scroll-margin-top:56px}
.entry-content p{margin:.8em 0}
.entry-content img{max-width:100%;height:auto;border-radius:10px}
.entry-content a{color:var(--green-600);border-bottom:1px solid var(--green-100)}
.entry-content pre{background:var(--panel-soft);border:1px solid var(--line);border-radius:10px;padding:14px;overflow-x:auto;font-size:13px}
.entry-content code{background:var(--panel-soft);border-radius:5px;padding:1px 5px;font-size:13px}
.entry-content blockquote{border-left:3px solid var(--green-100);padding-left:14px;color:var(--text-2);margin:.8em 0}
.entry-content ul,.entry-content ol{padding-left:1.6em;margin:.8em 0}
/* Markdown 表格：正文里的 <table> 是 Markdown 直接生成的，没有外层容器可加，
   所以让表格自身变成块级滚动盒——窄屏或列多时横向滚动，而不是把正文面板撑破 */
.entry-content table{
  display:block;width:100%;overflow-x:auto;
  border-collapse:collapse;margin:1.1em 0;
  font-size:14px;line-height:1.6;background:var(--panel);
}
.entry-content thead{background:var(--green-50)}
.entry-content th,.entry-content td{
  border:1px solid var(--line);padding:8px 12px;
  text-align:left;vertical-align:top;
}
.entry-content th{font-weight:600;color:var(--green-700)}
.entry-content tbody tr:nth-child(2n){background:var(--panel-soft)}
.entry-content tbody tr:hover{background:var(--green-50)}

/* 文章列表页（分类/标签/归档/搜索）：会话卡片 */
.entry-list{padding:18px 16px 30px;max-width:820px;margin:0 auto;width:100%}
.arch-title{
  font-size:15px;font-weight:600;color:var(--green-600);
  background:var(--green-50);border-radius:10px;padding:10px 14px;margin-bottom:16px;
}
.entry{
  display:block;background:var(--panel);border:1px solid var(--line);border-radius:14px;
  padding:16px 18px;margin-bottom:12px;box-shadow:0 1px 2px rgba(30,80,55,.04);
}
.entry:hover{border-color:var(--green-100);background:var(--green-50)}
.entry-title{font-size:16px;line-height:1.5;margin-bottom:6px}
.entry-title a{color:inherit}
.entry-title a:hover{color:var(--green-600)}
.entry-meta{display:flex;flex-wrap:wrap;gap:4px 14px;font-size:12.5px;color:var(--text-2)}
.entry-summary{font-size:13.5px;color:#4c5a53;margin-top:6px}
:root[data-mode="dark"] .entry-summary{color:#a7b6ad}
.pager{padding:10px 0}
.page-nav{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;list-style:none}
.page-nav li a,.page-nav li span{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:36px;height:36px;padding:0 12px;border-radius:10px;
  background:var(--panel);border:1px solid var(--line);font-size:13px;
}
.page-nav li.current span{background:var(--green-600);color:#fff;border-color:var(--green-600)}
.back-home{text-align:center;margin-top:14px}
.back-home a{color:var(--green-600);font-weight:600}

/* 无 JS：单页先显示聊天窗，正文在其下方顺排；列表页保持左栏可点 */
/* 阅读页高度随内容变化，body 的 flex 居中会把超出视口的顶部裁到不可回滚的位置，这里退回文档流 */
body.no-js{display:block}
.no-js .app.mode-room{display:block;height:auto;max-width:none;margin:0;border-radius:0}
.no-js .app.mode-room .sidebar{display:none}
.no-js .app.mode-room .chat{display:flex;height:auto;min-height:60vh}
@media(max-width:767px){
  .msg-main{max-width:82%}
  /* 窄屏输入框贴着底边：提示条上移，别压住输入框和发送键 */
  .toast{bottom:96px;max-width:calc(100% - 28px);text-align:center}
}

/* =========================================================
   小镇广场
   底图是死的，传送门 / 公告板 / 扫雷摊 / 守望者 / 小人全部按底图的
   百分比叠上去（--x / --y 由服务端算好）。换一张同构图的底图也能对上。
   ========================================================= */
.town{
  /* 一个像素格。底图按容器宽度整体缩放，小人固定 3px 就会在宽屏上小成一粒米，
     所以这一档跟着视口走，两端兜住：窄屏不至于糊成一坨，宽屏与底图同比例。 */
  --px:clamp(2.6px, .42vw, 5.4px);
  --tag-fs:max(10.5px, var(--px) * 2.3);   /* 名字牌字号（+ 上下 3px 内边距与 1px 边框 = 牌高）*/
  --tag-h:calc(var(--tag-fs) + 8px);
  --mood-box:max(22px, var(--px) * 4.6);   /* 心情气泡是个正方，边长也随人放大 */
  /* 只向上出血（贴住聊天窗头部），左右不出：负的水平外边距会把这一栏撑得比
     .chat-body 的内容框还宽，内容一高就多出一条横向滚动条。 */
  position:relative;margin:-18px 0 -10px;padding-bottom:12px;
}
.town-view{position:relative;width:100%}
.town-stage{
  position:relative;width:100%;max-width:1080px;margin:0 auto;aspect-ratio:4/3;
}
/* 底图单独一层：夜景只压这一层，滤镜不影响叠在上面的弹层与定位 */
.town-sky{
  position:absolute;inset:0;z-index:0;background-size:100% 100%;background-repeat:no-repeat;
  background-color:var(--panel-soft);
}
/* 夜景：底图压暗，路灯逐盏亮起来。灯位是照着自带底图的灯头量的，
   --s 缩放光晕（贴边那盏收一点，别把光漏到广场外面），--d 让各盏灯错开闪烁 */
.town-stage[data-night="1"] .town-sky{filter:brightness(.62) saturate(1.15) hue-rotate(-12deg)}
.town-stage[data-night="1"] .town-sky::after{content:"";position:absolute;inset:0;background:rgba(24,28,74,.22)}
.town-stage[data-night="1"] .town-fount{opacity:.72}
.town-lamp{
  position:absolute;left:var(--x);top:var(--y);width:calc(11% * var(--s,1));aspect-ratio:1;z-index:1;
  transform:translate(-50%,-50%);border-radius:50%;pointer-events:none;
  opacity:0;transition:opacity 2s;
  background:radial-gradient(circle,rgba(255,231,158,.46) 0,rgba(255,212,122,.2) 36%,rgba(255,212,122,0) 70%);
}
/* 灯头那一点最亮 */
.town-lamp::before{
  content:"";position:absolute;left:50%;top:50%;width:13%;aspect-ratio:1;
  transform:translate(-50%,-50%);border-radius:50%;
  background:radial-gradient(circle,#fffbe8 0,rgba(255,228,148,.9) 40%,rgba(255,228,148,0) 76%);
}
/* 顺着灯杆落到地上的一圈光 */
.town-lamp::after{
  content:"";position:absolute;left:50%;top:150%;width:74%;height:22%;
  transform:translate(-50%,-50%);border-radius:50%;
  background:radial-gradient(circle,rgba(255,222,148,.24),rgba(255,222,148,0) 68%);
}
.town-stage[data-night="1"] .town-lamp{
  opacity:1;animation:townLamp 5.4s ease-in-out infinite;animation-delay:var(--d,0s);
}
@keyframes townLamp{0%,100%{filter:brightness(1)}42%{filter:brightness(.85)}68%{filter:brightness(1.07)}}

/* 喷泉：底图里的池子是静的，这三组白片子叠上去当活水——上沿落水、落水点的水花、池面涟漪。
   容器按底图的池子量（横向 40.5%～55.5%、纵向 45%～59%），换底图会错位。 */
.town-fount{
  position:absolute;left:48%;top:52%;width:15%;aspect-ratio:1.45;z-index:1;
  transform:translate(-50%,-50%);pointer-events:none;
}
/* 三股落水：从上盆边缘掉到池面，repeating 渐变沿 y 平移，看着就是水在流。
   左右按上盆的宽度摊开（容器是池子那么宽，三股落在 38% / 50% / 62%）*/
.ft-jet{
  position:absolute;top:18%;height:40%;width:3%;border-radius:999px;
  background:repeating-linear-gradient(to bottom,rgba(255,255,255,.85) 0 15%,rgba(255,255,255,0) 15% 20%);
  animation:townJet .95s linear infinite;
}
.ft-jet-a{left:50%}
.ft-jet-b{left:38%;width:2.4%;opacity:.8;animation-duration:1.15s;animation-delay:-.3s}
.ft-jet-c{left:62%;width:2.6%;opacity:.72;animation-duration:1.3s;animation-delay:-.62s}
/* 落水砸起来的水花，在落水点上轻轻呼吸 */
.ft-foam{
  position:absolute;left:50%;top:46%;width:34%;height:15%;transform:translate(-50%,-50%);
  border-radius:50%;
  background:radial-gradient(circle,rgba(255,255,255,.8) 0,rgba(255,255,255,.34) 46%,rgba(255,255,255,0) 74%);
  animation:townFoam 1.7s ease-in-out infinite;
}
/* 涟漪：从落水点往外扩的椭圆圈，三道错开 */
.ft-ring{
  position:absolute;left:50%;top:42%;width:44%;height:24%;margin-left:-22%;
  border:max(1px,.14vw) solid rgba(255,255,255,.62);border-radius:50%;
  animation:townRing 3.6s ease-out infinite;
}
.ft-ring-b{animation-delay:1.2s}
.ft-ring-c{animation-delay:2.4s}
@keyframes townJet{from{background-position-y:0}to{background-position-y:20%}}
@keyframes townFoam{0%,100%{transform:translate(-50%,-50%) scale(1);opacity:.72}50%{transform:translate(-50%,-50%) scale(1.14,.86);opacity:.95}}
@keyframes townRing{0%{transform:scale(.12);opacity:0}18%{opacity:.75}100%{transform:scale(1.06);opacity:0}}
.town-go,.town-npc,.town-man{position:absolute;left:var(--x);top:var(--y)}
.town-go,.town-man{border:0;background:none;padding:0;color:inherit;font:inherit;cursor:pointer;z-index:3}
.town-go{transform:translate(-50%,-50%)}
.town-folk{position:absolute;inset:0;z-index:2}
.town-go:focus-visible,.town-man:focus-visible{outline:2px solid var(--green-600);outline-offset:3px;border-radius:8px}

/* 头顶的小牌子：一处一个色，扫一眼就知道那是什么，不用读完字 */
.tp-tag,.tb-tag,.ts-tag{
  display:block;white-space:nowrap;font-size:11px;line-height:1;font-weight:600;
  margin:6px auto 0;padding:4px 8px;border-radius:999px;text-align:center;
  box-shadow:0 2px 6px rgba(20,40,30,.2);
  transition:transform .15s,box-shadow .15s,filter .15s;
}
/* 传送门：紫，跟门洞的光一个色系 */
.tp-tag{background:linear-gradient(#f0e8ff,#dcc9ff);color:#3b2a63;border:1px solid #b39ae0}
/* 公告板：羊皮纸的黄褐 */
.tb-tag{background:linear-gradient(#fff4d6,#f5e0a8);color:#6b4e12;border:1px solid #c8a23a}
/* 扫雷摊：旗子的钢蓝 */
.ts-tag{background:linear-gradient(#e6f2ff,#c9e0f7);color:#1c4a6b;border:1px solid #7fb0d8}
.town-go:hover .tp-tag,.town-go:hover .tb-tag,.town-go:hover .ts-tag{
  transform:translateY(-1px);filter:brightness(1.05);box-shadow:0 4px 10px rgba(20,40,30,.26);
}
:root[data-mode="dark"] .tp-tag{background:linear-gradient(#3b2f5c,#2b2145);color:#d9c9ff;border-color:#6b55a8}
:root[data-mode="dark"] .tb-tag{background:linear-gradient(#4a3a16,#33270f);color:#f0d9a0;border-color:#8a6c20}
:root[data-mode="dark"] .ts-tag{background:linear-gradient(#1d3a52,#15293a);color:#bfe0f7;border-color:#3d6b90}

/* 传送门：一个发光的门洞，点它进聊天室 */
.tp-gate{
  display:block;width:34px;height:44px;margin:0 auto;
  border-radius:50% 50% 12% 12%/62% 62% 8% 8%;
  background:radial-gradient(62% 62% at 50% 34%,rgba(255,255,255,.95),var(--green-500) 58%,var(--green-700));
  box-shadow:0 0 16px var(--green-500),inset 0 0 12px rgba(255,255,255,.65);
  animation:townPulse 2.6s ease-in-out infinite;
}
@keyframes townPulse{0%,100%{transform:scale(1);opacity:.9}50%{transform:scale(1.07);opacity:1}}
@media(prefers-reduced-motion:reduce){.tp-gate{animation:none}}
/* 随机传送门：同一扇门换个色，免得和进聊天室那扇混成一处 */
.town-toss .tp-gate{
  background:radial-gradient(62% 62% at 50% 34%,rgba(255,255,255,.95),#3fb0a8 58%,#1c6f6a);
  box-shadow:0 0 16px #3fb0a8,inset 0 0 12px rgba(255,255,255,.65);
}
.town-toss .tp-tag{background:linear-gradient(#e4f7f5,#bfe6e1);color:#12514c;border:1px solid #6bb8b0}
:root[data-mode="dark"] .town-toss .tp-tag{background:linear-gradient(#17414a,#0f2c33);color:#b6e6df;border-color:#2f6f70}

/* 公告板：书页 */
.tb-page{
  display:block;width:30px;height:23px;margin:0 auto;position:relative;
  background:linear-gradient(#fffdf5,#efe3c6);border:1px solid #b99b62;border-radius:3px 6px 6px 3px;
  box-shadow:0 2px 5px rgba(40,30,10,.32);
}
.tb-page::before{content:"";position:absolute;left:50%;top:3px;bottom:3px;width:1px;background:rgba(120,95,55,.55)}
.tb-page::after{
  content:"";position:absolute;left:5px;right:5px;top:7px;height:9px;
  background:repeating-linear-gradient(to bottom,rgba(120,95,55,.5) 0 1px,transparent 1px 4px);
}

/* 像素小人：一个格子 + box-shadow 拼出的 4×7  sprite，衬衫色随人变 */
.man-pix,.npc-pix{
  position:absolute;left:var(--px);top:calc(var(--px) * 2);width:var(--px);height:var(--px);
  color:var(--shirt,var(--green-600));
  box-shadow:
    var(--px) calc(var(--px) * -2) 0 var(--town-hair,#3a2a1e),
    calc(var(--px) * 2) calc(var(--px) * -2) 0 var(--town-hair,#3a2a1e),
    var(--px) calc(var(--px) * -1) 0 var(--town-skin,#f0c9a2),
    calc(var(--px) * 2) calc(var(--px) * -1) 0 var(--town-skin,#f0c9a2),
    calc(var(--px) * 3) 0 0 currentColor,
    var(--px) var(--px) 0 currentColor,calc(var(--px) * 2) var(--px) 0 currentColor,calc(var(--px) * 3) var(--px) 0 currentColor,
    var(--px) calc(var(--px) * 2) 0 currentColor,calc(var(--px) * 2) calc(var(--px) * 2) 0 currentColor,
    var(--px) calc(var(--px) * 3) 0 var(--town-pants,#39435c),calc(var(--px) * 2) calc(var(--px) * 3) 0 var(--town-pants,#39435c),
    var(--px) calc(var(--px) * 4) 0 var(--town-shoe,#20242c),calc(var(--px) * 2) calc(var(--px) * 4) 0 var(--town-shoe,#20242c);
}
.town-man,.town-npc{width:calc(var(--px) * 4);height:calc(var(--px) * 7);transform:translate(-50%,-100%)}
.town-man:hover{filter:brightness(1.12)}
.town-man.picked{outline:2px solid var(--green-600);outline-offset:3px;border-radius:4px}
.man-shadow{
  position:absolute;left:50%;bottom:calc(var(--px) * -1);transform:translateX(-50%);
  width:calc(var(--px) * 4.6);height:max(4px, var(--px) * 1.5);border-radius:50%;
  background:rgba(20,30,25,.3);filter:blur(1px);
}
.man-tag{
  position:absolute;bottom:calc(100% + var(--px));left:50%;transform:translateX(-50%);
  white-space:nowrap;font-size:var(--tag-fs);line-height:1;padding:3px 6px;border-radius:999px;
  background:rgba(238,249,242,.92);color:#22382e;border:1px solid rgba(47,158,99,.32);
  box-shadow:0 1px 4px rgba(20,40,30,.2);
}
:root[data-mode="dark"] .man-tag{background:rgba(28,42,35,.92);color:#cfe6d8;border-color:rgba(95,224,138,.28)}

/* 心情气泡：只有选了心情的小人才挂出来，压在名字牌上方 */
.man-mood{
  position:absolute;bottom:calc(100% + var(--px) + var(--tag-h) + 2px);left:50%;transform:translateX(-50%);
  min-width:var(--mood-box);height:var(--mood-box);padding:0 max(6px, var(--px) * 1.2);
  border-radius:calc(var(--mood-box) / 2);
  background:#ffe066;border:1px solid #d9a406;color:#4a3a20;
  font-size:max(13px, var(--px) * 2.7);line-height:calc(var(--mood-box) - 2px);
  text-align:center;white-space:nowrap;
  box-shadow:0 2px 6px rgba(60,45,5,.28);
}
.man-mood[hidden]{display:none}
/* 悬停提示：归宿地 / 心情 / 正在做。出现时把名字牌与心情气泡让开，免得叠成两层字。
   窄屏没有 hover，点了直接开名片（里面同样带这一行），所以这一层在窄屏整个不出现。 */
.man-tip{
  position:absolute;bottom:calc(100% + var(--px));left:50%;
  transform:translateX(-50%) translateY(3px);
  min-width:max-content;max-width:230px;padding:6px 9px;border-radius:10px;
  background:rgba(24,34,28,.94);color:#eaf5ee;border:1px solid rgba(255,255,255,.16);
  box-shadow:0 6px 18px rgba(10,25,15,.32);
  font-size:12px;line-height:1.55;text-align:left;white-space:normal;
  opacity:0;visibility:hidden;pointer-events:none;z-index:6;
  transition:opacity .12s,transform .12s;
}
.man-tip span{display:block}
.town-man:hover .man-tip,.town-man:focus-visible .man-tip{
  opacity:1;visibility:visible;transform:translateX(-50%) translateY(0);
}
.town-man:hover .man-tag,.town-man:focus-visible .man-tag,
.town-man:hover .man-mood,.town-man:focus-visible .man-mood{opacity:0}
/* 自己那一位从头到脚都黄一档，好让人知道「这个能点」 */
.town-man[data-self="1"] .man-tag{background:#ffe9a8;border-color:#d9a406;color:#4a3a20;font-weight:600}
.town-man[data-self="1"]{cursor:pointer}

/* 点自己弹出的卡片里那一排心情 */
.tc-moods{display:flex;flex-wrap:wrap;gap:4px;align-items:center;margin-top:8px}
.tc-moods-tip{width:100%;font-size:11px;color:var(--text-2);margin-bottom:2px}
.tc-mood{
  width:27px;height:27px;padding:0;border:1px solid var(--line);border-radius:8px;
  background:var(--panel);color:var(--text);font-size:14px;line-height:1;cursor:pointer;
}
.tc-mood:hover{border-color:var(--green-600);background:var(--green-50)}
.tc-mood.on{border-color:#d9a406;background:#ffe9a8;box-shadow:0 0 0 2px rgba(217,164,6,.25)}
.tc-mood.off{width:auto;padding:0 8px;font-size:11px;color:var(--text-2)}
.tsh-tip{margin-top:10px;padding-top:8px;border-top:1px dashed #cbb27f;font-size:11.5px;line-height:1.6;color:#8a7745;text-align:center}
:root[data-mode="dark"] .tsh-tip{color:var(--text-2);border-top-color:var(--line)}

/* 守望者头顶的滚动公告 */
.npc-bubble{
  position:absolute;bottom:calc(100% + 9px);left:50%;transform:translateX(-50%);
  width:max-content;max-width:240px;white-space:normal;text-align:center;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:6px 10px;
  font-size:12px;line-height:1.5;color:var(--text);box-shadow:var(--glow-btn);
}
.npc-bubble::after{
  content:"";position:absolute;left:50%;bottom:-5px;transform:translateX(-50%) rotate(45deg);
  width:8px;height:8px;background:var(--panel);border-right:1px solid var(--line);border-bottom:1px solid var(--line);
}
.town-npc{z-index:4}

/* 点开公告板摊开的那页 */
.town-sheet{
  position:absolute;left:50%;top:10%;transform:translateX(-50%);width:min(420px,86%);z-index:6;
  background:linear-gradient(#fffdf6,#f6efdd);color:#4a3a20;
  border:1px solid #cbb27f;border-radius:10px;box-shadow:0 18px 40px rgba(30,25,10,.35);
  padding:14px 16px 12px;
}
.tsh-head{font-size:15px;font-weight:700;letter-spacing:.5px;margin-bottom:8px;text-align:center}
.tsh-list{list-style:none;display:flex;flex-direction:column;gap:7px;font-size:13px;line-height:1.7}
.tsh-list li{padding-left:14px;position:relative}
.tsh-list li::before{content:"";position:absolute;left:0;top:.65em;width:5px;height:5px;border-radius:50%;background:#b99b62}
.tsh-none{font-size:13px;text-align:center;opacity:.75}
.tsh-close{
  display:block;margin:12px auto 0;padding:5px 16px;border-radius:999px;cursor:pointer;
  border:1px solid #b99b62;background:#fffdf6;color:#6a5326;font-size:12.5px;font-weight:600;
}
.tsh-close:hover{background:#f6efdd}
/* 深色下这张纸换成旧纸色，免得一整块米白砸在黑底上 */
:root[data-mode="dark"] .town-sheet{
  background:linear-gradient(#3a3628,#2d2a1f);color:#e6dcc0;border-color:#6d5c39;
  box-shadow:0 18px 40px rgba(0,0,0,.5);
}
:root[data-mode="dark"] .tsh-list li::before{background:#c8a86a}
:root[data-mode="dark"] .tsh-close{background:#3a3628;border-color:#6d5c39;color:#e6dcc0}
:root[data-mode="dark"] .tsh-close:hover{background:#464130}

/* 点小人弹出的那张卡 */
.town-card{
  position:absolute;z-index:7;transform:translate(-50%,-100%);max-width:250px;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;
  box-shadow:var(--glow-app);padding:9px 12px;font-size:12.5px;line-height:1.6;color:var(--text);
}
.town-card .tc-name{font-weight:700;margin-bottom:2px}
.town-card .tc-where{color:var(--green-700)}
.town-card .tc-doing{color:var(--text-2);font-size:12px;margin-top:2px}
.town-card .tc-time{color:var(--text-2);font-size:11.5px;margin-top:3px}

/* ---- 摊子点开的那台小电脑：机身是道具色，深浅两档都一样；屏幕里的雷盘跟着主题走 ---- */
.town-pc{
  position:absolute;inset:0;z-index:9;display:flex;
  gap:0;padding:10px;overflow:auto;
}
.town-pc[hidden]{display:none}
.tpc-veil{position:absolute;inset:0;border:0;padding:0;background:rgba(14,22,18,.46);cursor:pointer}
.tpc-case{
  /* 居中用 margin:auto 而不是 align-items:center：机身比舞台高时，
     居中的弹性子元素顶部会被裁进滚不到的区域，auto 边距在放不下时自己归零。 */
  position:relative;margin:auto;width:min(360px,100%);flex-shrink:0;
  background:linear-gradient(#f0ead9,#dbd3bd 62%,#c7bea6);
  border:1px solid #a89c82;border-radius:16px 16px 7px 7px;padding:12px 12px 0;
  box-shadow:0 20px 44px rgba(0,0,0,.42),inset 0 2px 0 rgba(255,255,255,.8),inset 0 -2px 0 rgba(0,0,0,.14);
}
.tpc-screen{background:#29302b;border-radius:10px;padding:9px 9px 10px;box-shadow:inset 0 2px 10px rgba(0,0,0,.62)}
.tpc-bar{display:flex;align-items:center;gap:8px;padding:0 2px 8px;color:#cfe6d6;font-size:12px}
.tpc-power{
  width:8px;height:8px;border-radius:50%;flex-shrink:0;
  background:#5fe08a;box-shadow:0 0 7px #5fe08a;
}
.tpc-name{flex:1;min-width:0;font-family:ui-monospace,Consolas,monospace;font-weight:700;letter-spacing:.4px}
.tpc-off{
  width:24px;height:21px;flex-shrink:0;border:1px solid #6d7a70;border-radius:4px;
  background:#3d463f;color:#e2ece5;font-size:11px;line-height:1;cursor:pointer;padding:0;
}
.tpc-off:hover{background:#a8372f;border-color:#c9564d;color:#fff}
.tpc-crt{
  position:relative;background:#f4f1e6;border-radius:6px;padding:10px;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.2),inset 0 0 26px rgba(70,110,88,.18);
}
/* 老显像管的扫描线，压在内容上但不出手 */
.tpc-crt::after{
  content:"";position:absolute;inset:0;border-radius:6px;pointer-events:none;opacity:.16;
  background:repeating-linear-gradient(rgba(40,60,48,.5) 0 1px,transparent 1px 3px);
}
.town-pc .mine{max-width:none;gap:5px}
.tpc-deck{
  display:flex;align-items:center;gap:6px;padding:9px 6px;
  background:linear-gradient(#d8d0ba,#cbc3ad);border-top:1px solid #b3a98f;
}
.tpc-key{
  width:15px;height:6px;border-radius:2px;background:#efeade;
  box-shadow:inset 0 -1px 0 rgba(0,0,0,.2);
}
.tpc-slot{
  margin-left:auto;width:56px;height:8px;border-radius:2px;background:#6f6754;
  box-shadow:inset 0 1px 2px rgba(0,0,0,.5);
}
.tpc-stand{
  width:48%;height:13px;margin:0 auto;border-radius:0 0 8px 8px;
  background:linear-gradient(#bdb49c,#a99f86);box-shadow:inset 0 -2px 0 rgba(0,0,0,.14);
}
:root[data-mode="dark"] .tpc-crt{background:#202822;box-shadow:inset 0 0 0 1px rgba(0,0,0,.5),inset 0 0 26px rgba(90,150,115,.16)}
:root[data-mode="dark"] .tpc-crt::after{opacity:.22;background:repeating-linear-gradient(rgba(150,200,170,.32) 0 1px,transparent 1px 3px)}
@media(max-width:520px){
  .tpc-case{width:100%}
  .tpc-deck,.tpc-stand{display:none}
}

.town-hint{display:flex;flex-wrap:wrap;gap:5px 14px;justify-content:center;padding:12px 14px 0;font-size:12px;color:var(--text-2)}

/* 窄屏不再整张地图跟着屏宽缩：舞台固定 720×540，套在一个 56vh 的窗口里用手指拖，
   小人和名牌保住能读的尺寸；三块弹层跳出舞台贴住屏幕，免得被拖出视野。
   名片的 left/top 是 JS 写在 style 上的百分比，只能 !important 覆盖。 */
@media(max-width:767px){
  .town{--px:3.6px;margin:-14px 0 -8px}
  .town-view{height:56vh;min-height:320px;overflow:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain;scrollbar-width:none}
  .town-view::-webkit-scrollbar{display:none}
  .town-stage{width:720px;height:540px;max-width:none;margin:0;aspect-ratio:auto}
  .town-sheet{position:fixed;left:10px;right:10px;top:auto;bottom:10px;width:auto;max-height:66vh;overflow:auto;transform:none;z-index:40}
  .town-card{position:fixed;left:50%!important;top:auto!important;right:auto;bottom:10px;transform:translateX(-50%);max-width:min(300px,calc(100% - 24px));z-index:40}
  /* 窄屏没有悬停：详情走点开的名片，这层提示整个不参与布局 */
  .man-tip{display:none}
  .town-pc{position:fixed;inset:0;z-index:40}
}
@media(min-width:768px){.town-drag-tip{display:none}}

/* ============ 扫雷摊（照经典盘面：灰盘子 + 立体边 + 红 LED + 中间笑脸） ============ */
.mine{max-width:340px;margin:0 auto;display:flex;flex-direction:column;gap:6px}
.mine-bar{
  display:flex;align-items:center;justify-content:space-between;gap:8px;padding:5px 7px;
  background:#f6f6f3;border:2px solid;border-color:#fff #8b8b88 #8b8b88 #fff;
}
.mine-led{
  min-width:54px;text-align:center;padding:1px 6px;flex-shrink:0;
  font-family:ui-monospace,Consolas,monospace;font-size:17px;letter-spacing:1.5px;color:#ff3b30;
  background:#121010;border:2px solid;border-color:#8b8b88 #fff #fff #8b8b88;
}
.mine-face{
  width:30px;height:30px;padding:0;flex-shrink:0;cursor:pointer;
  font-size:16px;line-height:1;color:#141414;background:#d9d9d5;
  border:2px solid;border-color:#fff #7c7c78 #7c7c78 #fff;
}
.mine-face:hover{background:#e3e3df}
.mine-face:active{border-color:#7c7c78 #fff #fff #7c7c78}
.mine-tools{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:6px}
.mine-diff{display:flex;gap:4px;flex-wrap:wrap}
.mine-tab{
  padding:2px 6px;font-size:10px;line-height:1.5;cursor:pointer;color:#3c3c3a;background:#d9d9d5;
  border:2px solid;border-color:#fff #8b8b88 #8b8b88 #fff;
}
.mine-tab:hover{background:#e3e3df}
.mine-tab.active{color:#111;background:#bfbfba;border-color:#8b8b88 #fff #fff #8b8b88}
.mine-best{font-size:11px;color:var(--text-2)}
.mine-board{
  /* 格子最多 22px：初级 9 列铺不满就居中，16 列挤得下就自己缩到 18px 左右，
     整台机器因此比原来小一圈，不再占满半张广场。 */
  --w:9;display:grid;grid-template-columns:repeat(var(--w),minmax(0,22px));justify-content:center;
  gap:0;padding:3px;
  background:#c9c9c5;border:3px solid;border-color:#fff #6f6f6b #6f6f6b #fff;
}
.mine-cell{
  aspect-ratio:1;border:0;border-radius:0;padding:0;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:700;color:transparent;background:#d9d9d5;
  box-shadow:inset 2px 2px 0 #fff,inset -2px -2px 0 #9d9d98;
}
.mine-cell:hover{filter:brightness(1.05)}
.mine-cell.open{background:#c7c7c2;box-shadow:inset 1px 1px 0 #a3a39e;cursor:default;filter:none}
.mine-cell.open.n1{color:#2b7de0}
.mine-cell.open.n2{color:#1f8f52}
.mine-cell.open.n3{color:#c0392b}
.mine-cell.open.n4{color:#5b3fa8}
.mine-cell.open.n5{color:#8a5a1c}
.mine-cell.open.n6{color:#0e8496}
.mine-cell.open.n7{color:#4a4a4a}
.mine-cell.open.n8{color:#8d8d8d}
.mine-cell.flag{color:#c0392b}
.mine-cell.boom{background:#e0a49c;box-shadow:inset 1px 1px 0 #a3a39e}
.mine-cell.wrong{background:#d3c3bd;text-decoration:line-through}
.mine-tip{margin:0;font-size:11px;color:var(--text-2);text-align:center}
/* 关掉小电脑的那枚按钮（整页那一盘没有可退的地方，服务端不给它） */
.mine-quit{
  padding:6px 10px;cursor:pointer;font-size:12px;font-weight:700;color:#f6ece2;
  background:linear-gradient(#7a4a38,#5d3628);border:2px solid;border-color:#a9705a #3b2118 #3b2118 #a9705a;
}
.mine-quit:hover{filter:brightness(1.12)}
.mine-quit:active{border-color:#3b2118 #a9705a #a9705a #3b2118}
:root[data-mode="dark"] .mine-bar{background:#2c332e;border-color:#4b544d #141916 #141916 #4b544d}
:root[data-mode="dark"] .mine-led{background:#0b0d0c;border-color:#4b544d #141916 #141916 #4b544d}
:root[data-mode="dark"] .mine-face{color:#e2ece5;background:#3a423c;border-color:#4d574f #202722 #202722 #4d574f}
:root[data-mode="dark"] .mine-tab{color:#c3cec6;background:#3a423c;border-color:#4d574f #202722 #202722 #4d574f}
:root[data-mode="dark"] .mine-tab.active{color:#f2f7f3;background:#274d38;border-color:#202722 #4d574f #4d574f #202722}
:root[data-mode="dark"] .mine-board{background:#2a312c;border-color:#4b544d #141916 #141916 #4b544d}
:root[data-mode="dark"] .mine-cell{background:#3a423c;box-shadow:inset 2px 2px 0 #4d574f,inset -2px -2px 0 #232a25}
:root[data-mode="dark"] .mine-cell.open{background:#242b26;box-shadow:inset 1px 1px 0 #1a201b}
:root[data-mode="dark"] .mine-cell.boom{background:#6b2f27}
:root[data-mode="dark"] .mine-cell.wrong{background:#3a332c}
/* 雷盘数字：浅色那套是照白盘子调的，压到黑盘上 2/4/5/7 号几乎看不见，整排提亮 */
:root[data-mode="dark"] .mine-cell.open.n1{color:#6db3ff}
:root[data-mode="dark"] .mine-cell.open.n2{color:#57d99a}
:root[data-mode="dark"] .mine-cell.open.n3{color:#ff7a6b}
:root[data-mode="dark"] .mine-cell.open.n4{color:#b79bff}
:root[data-mode="dark"] .mine-cell.open.n5{color:#ffc861}
:root[data-mode="dark"] .mine-cell.open.n6{color:#5fd6e8}
:root[data-mode="dark"] .mine-cell.open.n7{color:#d8e2db}
:root[data-mode="dark"] .mine-cell.open.n8{color:#9fb0a6}
@media(max-width:640px){
  .mine-cell{font-size:11px}
  .npc-bubble{max-width:170px;font-size:11px}
}

/* =========================================================
   窄屏吸底导航栏：小镇 / 聊天 / 公告 / 扫雷 / 传送 / 风格
   ---------------------------------------------------------
   只在列表形态输出（chatroom_mob_bar_html() 里判过），宽屏整条不显示。
   --mob-bar-h 由 html.has-mob-bar 撑起：告示牌、提示条、浮动钮都照它避让，
   没这一栏的页面（单篇文章 / 独立页）它是 0，底下的间距保持原样。
   ========================================================= */
:root{--mob-bar-h:0px}
.mob-bar,.mob-veil,.pop-host{display:none}
.mob-btn{
  flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  border:none;background:transparent;cursor:pointer;color:#7d8d85;
  font-size:10.5px;line-height:1;padding:0 2px;text-decoration:none;
}
.mob-btn em{font-style:normal;line-height:1}
.mob-btn svg{display:block}
.mob-btn:hover,.mob-btn.on{color:var(--green-600)}
.mob-style-pop{
  position:absolute;left:50%;bottom:calc(100% + 8px);transform:translateX(-50%);
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  padding:8px 10px;box-shadow:0 10px 26px rgba(20,30,25,.18);white-space:nowrap;
}
.mob-style-pop[hidden]{display:none}
.theme-dots[data-labeled]{gap:9px}
.theme-dots[data-labeled] .msp-tag{font-size:10.5px;color:var(--text-2);align-self:center}
:root[data-mode="dark"] .mob-style-pop{box-shadow:0 10px 26px rgba(0,0,0,.5)}

@media(max-width:767px){
  html.has-mob-bar{--mob-bar-h:calc(52px + env(safe-area-inset-bottom,0px))}
  /* 栏钉在视口底下，不进 flex 流：窄屏的文章会话本来就整页滚，
     会话窗一长就会把流里的栏顶到屏幕外，所以避让交给下面两处 padding */
  html.has-mob-bar .mob-bar{
    display:flex;align-items:stretch;height:var(--mob-bar-h);
    padding-bottom:env(safe-area-inset-bottom,0px);
    background:var(--panel);border-top:1px solid var(--line);
    position:fixed;left:0;right:0;bottom:0;z-index:36;
    box-shadow:0 -3px 14px rgba(20,30,25,.10);
  }
  /* 清单形态：左栏自己让出一栏高，底部收边不会被压住 */
  html.has-mob-bar .sidebar{padding-bottom:var(--mob-bar-h)}
  /* 会话形态：窄屏整页滚，输入框是窗里最后一块，让出的这一截正落在栏后面 */
  html.has-mob-bar .chat{padding-bottom:var(--mob-bar-h)}
  /* 弹层宿主摊平（display:contents）：告示牌与小电脑自己带 fixed，位置照旧按屏幕算 */
  html.has-mob-bar .pop-host{display:contents}
  html.has-mob-bar .mob-veil{display:block;position:fixed;inset:0;background:rgba(18,28,22,.42);z-index:34}
  html.has-mob-bar .mob-veil[hidden]{display:none}
  /* 右上角那组换色钮窄屏收进「风格」里；没 JS 时留着——那还是唯一能点动的一处 */
  html.cr-js .chat-header .theme-dots{display:none}
  /* 广场那枚随机传送门窄屏不给：小屏上开新标签页是跳出站外，吸底栏也没给它留位置 */
  .town-toss{display:none}
  /* 吸底栏摊开的告示牌让开一栏高（房里那份与宿主那份同一待遇）；小电脑本来就是整屏盖住栏，不用动 */
  html.has-mob-bar .town-sheet{bottom:calc(var(--mob-bar-h) + 10px)}
  html.has-mob-bar .toast{bottom:calc(var(--mob-bar-h) + 14px)}
  html.has-mob-bar .float-nav.doc-scroll{bottom:calc(var(--mob-bar-h) + 14px)}
}

/* =========================================================
   窄屏清单的两份变体（服务端按 ?mob=1 换 markup，纯 CSS 分派）
   ========================================================= */
/* 通讯录：订阅卡片直接铺进左栏，一列到底 */
.contact-list .feed-cards{grid-template-columns:minmax(0,1fr);max-width:none;padding:0 12px;gap:10px}

/* 归档：时间线——一条竖线串起月份，该月的文章挂在节点底下 */
.tl{position:relative;margin:0 14px 12px;padding-left:16px}
.tl::before{
  content:'';position:absolute;left:4px;top:10px;bottom:10px;width:2px;
  background:var(--line);border-radius:2px;
}
.tl-m{position:relative;display:flex;align-items:baseline;gap:8px;margin:16px 0 4px}
.tl-m::before{
  content:'';position:absolute;left:-16px;top:6px;width:10px;height:10px;border-radius:50%;
  background:var(--green-500);box-shadow:0 0 0 3px var(--panel);
}
.tl-my{font-size:13px;font-weight:700;color:var(--green-700)}
.tl-n{font-size:11.5px;color:var(--text-2);margin-left:auto}
.tl-item{
  display:flex;align-items:baseline;gap:8px;padding:7px 10px;border-radius:10px;
  color:var(--text);text-decoration:none;cursor:pointer;
}
.tl-item:hover{background:var(--green-50)}
.tl-t{flex:1;min-width:0;font-size:13.5px;line-height:1.5;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tl-d{flex-shrink:0;font-size:11.5px;color:#9aa8a0}
