/* =========================================================
   小镇主题
   变量、配色档位、头像渐变、气泡与布局构成广场与聊天室的视觉基线；
   底部「主题接线」段负责服务端渲染出的正文与状态样式。
   ========================================================= */

: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);
  --town-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"] .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{width:26px;height:26px;padding:0;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--text-2)}
.mode-dot svg{width:19px;height:19px;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(--town-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;
}
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;
  position:relative;
  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}}
/* 标题和副标题各占一行，Logo 竖着跨过这两行 */
.brand{
  display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:10px;
  align-content:center;
  padding:14px 16px 10px;
}
.brand-logo{
  grid-row:1/span 2;
  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}
/* 放大镜就是提交按钮：整块压在输入框左端那一格里，点它等于提交。
   以前只给 svg 定位，按钮本身还在文档流里，把表单撑出第二行，放大镜跟着掉到框外 */
.search-btn{
  position:absolute;left:0;top:0;width:36px;height:100%;padding:0;border:0;background:none;
  display:flex;align-items:center;justify-content:center;color:#7d8d85;cursor:pointer;
}
.search-btn:hover{color:var(--green-600)}

.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-time{font-size:11px;color:#9aa8a0;flex-shrink:0}
.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);
}
.sf-copy{color:var(--text-2);word-break:break-all}
.sf-copy a{color:var(--green-600);text-decoration:none}
.sf-copy a:hover{text-decoration:underline}
.sf-beian a{display:inline-flex;align-items:center;gap:4px;color:var(--text-2);text-decoration:none;word-break:break-all}
.sf-beian a:hover{color:var(--green-600)}
.bf-ico{width:15px;height:15px;flex:0 0 auto;display:block}
.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.is-child{padding-left:34px}
/* 左栏的就地展开：三角压在行尾，横过来是收着，转下去是展开 */
.c-fold{
  flex-shrink:0;width:24px;height:24px;padding:0;
  display:flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:8px;background:var(--panel);color:var(--text-2);cursor:pointer;
  transition:transform .15s,border-color .15s,color .15s;
}
.c-fold:hover{border-color:var(--green-100);color:var(--green-600)}
.c-fold.is-open{transform:rotate(90deg)}
.c-kids{padding:0 0 4px}
.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{display:block;font-size:14.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 名称与篇数同行：长名字照样省略号，数字不被挤掉 */
.c-tit{display:flex;align-items:baseline;gap:6px;min-width:0}
.c-tit .c-name{flex:0 1 auto}
.c-num{flex:0 0 auto;font-size:11.5px;color:var(--text-2)}
.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-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}

/* ===== 聊天窗 ===== */
.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}
}
/* 上一层：窄屏和 .back-btn 换着出现，宽屏只有它，位置与样式沿用返回那枚 */
.up-btn{display:flex;align-items:center;gap:3px;color:var(--text-2);text-decoration:none;flex:0 0 auto}
.up-btn em{font-style:normal;font-size:12px;white-space:nowrap}
.up-btn:hover{color:var(--green-700)}
.chat-header{
  display:flex;align-items:center;gap:12px;position:relative;
  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}
.chat-mail{display:block;font-size:12px;color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hd-actions{display:flex;align-items:center;gap:2px;padding-left:10px;margin-left:4px;border-left:1px solid var(--line);flex-shrink:0}
.theme-dots{display:flex;align-items:center;gap:8px;flex-shrink:0}
.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[data-theme="green"]{--dot:#22b45c}
.t-dot[data-theme="cyan"]{--dot:#24bcd2}
.t-dot[data-theme="blue"]{--dot:#4a97ee}
.t-dot[data-theme="yellow"]{--dot:#c9981c}
.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)}

/* 聊天室右上角那枚红包：还有得抢才亮着，点开来就地抢，抢完了自己收起来 */
.hd-pkt{position:relative;display:flex;align-items:center;margin-left:2px;flex-shrink:0}
.rp-pill{
  display:flex;align-items:center;gap:4px;padding:5px 9px 5px 7px;
  border:1px solid #e8b48c;border-radius:999px;cursor:pointer;
  background:linear-gradient(#fff3ea,#ffe7d6);color:#c9541f;
  font:inherit;font-size:12px;font-weight:700;line-height:1;
}
.rp-pill[hidden]{display:none}
.rp-pill:hover{border-color:#d98b4f;box-shadow:0 3px 9px rgba(201,84,31,.22)}
.rp-pill:focus-visible{outline:2px solid #c9541f;outline-offset:2px}
.rp-pill svg{width:15px;height:15px}
.rp-n{font-style:normal}
.rp-cap{font-size:12px;font-weight:700;color:var(--text-2);padding:0 2px 2px}
.rp-pop{
  position:absolute;top:calc(100% + 10px);right:0;z-index:24;
  width:min(330px,82vw);padding:10px;background:var(--panel);
  border:1px solid var(--line);border-radius:14px;box-shadow:var(--glow-app);
}
.rp-pop[hidden]{display:none}
.rp-pop .pkt-list{max-height:min(46vh,360px);overflow-y:auto}
.rp-pop .town-pkt{padding:11px 13px;border-radius:13px}
.rp-pop .list-empty{padding:16px 0;text-align:center;font-size:12.5px;color:var(--text-2)}
:root[data-mode="dark"] .rp-pill{background:linear-gradient(#3a2415,#2f1d12);color:#f0a874;border-color:#7d4a26}
/* 窄屏：右上角那排（配色点 + 深浅色 + 红包）挤掉标题，所以先收自己的人数和间距 */
@media (max-width:430px){
  .chat-header{gap:7px;padding:11px 12px}
  .theme-dots{gap:4px}
  .t-dot{width:20px;height:20px}
  .t-dot::before{width:14px;height:14px}
  .hd-actions{padding-left:6px;margin-left:0}
  .chat-title{flex:1 1 auto;min-width:56px}
}

.chat-body{flex:1;overflow-y:auto;padding:18px 16px 10px;min-height:0}
/* 窄屏的文章会话：整页在滚（.chat-body 撑不满，自己不起滚），
   目录条就得跟着视口钉——把这块的滚动盒让出来，吸顶才生效。 */
@media(max-width:767px){.chat[data-kind="post"]>.chat-body{overflow:visible}}
.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 .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:transparent;color:var(--text-2);box-shadow:inset 0 0 0 1px var(--line)}
.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)}}

/* 发红包：入口跟表情同一个个头，排在它左边；单子摊在输入框上方 */
.pkt-pick{
  flex-shrink:0;display:flex;align-items:center;justify-content:center;
  width:38px;height:44px;border:none;border-radius:11px;cursor:pointer;
  background:var(--panel-soft);color:#c9541f;font:inherit;
}
.pkt-pick:hover{color:#c9541f;background:#ffe7d6}
.pkt-pick:focus-visible{outline:2px solid #c9541f;outline-offset:2px}
:root[data-mode="dark"] .pkt-pick{color:#f0a874}
:root[data-mode="dark"] .pkt-pick:hover{background:#3a2415}
.chat-foot{position:relative;flex:0 0 auto}
/* 单子从入口那一侧摊开：整条聊天窗那么宽，眼睛得横着跑一趟才找得到输入格 */
.pkt-sheet{
  position:absolute;left:14px;right:auto;bottom:calc(100% - 6px);z-index:22;
  width:min(400px,calc(100% - 28px));
  padding:10px 12px 12px;background:var(--panel);
  border:1px solid var(--line);border-radius:14px;box-shadow:var(--glow-app);
}
.pkt-sheet[hidden]{display:none}
.ps-cap{display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:12.5px;font-weight:700;color:var(--text-2)}
.ps-close{
  margin-left:auto;display:flex;align-items:center;justify-content:center;
  width:22px;height:22px;padding:0;border:none;border-radius:7px;cursor:pointer;
  background:transparent;color:var(--text-2);
}
.ps-close:hover{background:var(--hover-2);color:var(--text)}
/* 摊在输入框上方的这一小张收紧一档：字段名变窄、格子变小、说明跟着挤回同一行 */
.pkt-sheet .pkt-form{padding:0;background:none;border:0;border-radius:0;gap:7px}
.pkt-sheet .pkt-row{gap:6px 8px}
.pkt-sheet .pkt-label{flex:0 0 54px;font-size:12px}
.pkt-sheet .pkt-row input[type=number]{max-width:86px;padding:6px 9px;font-size:13px}
.pkt-sheet .pkt-row input[type=text]{flex:1;min-width:0;max-width:none;padding:6px 9px;font-size:13px}
.pkt-sheet .pkt-hint{font-size:11px}
.pkt-sheet .pkt-send{padding:7px 18px;font-size:13px}

.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}
/* 点评论上的「回复」后显示：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);
}

.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 回退
   ========================================================= */
/* 正文与消息同在一个滚动容器里：正文在上，评论区在下 */
.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%}
.msgs{max-width:860px;margin:0 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-item.is-child{margin-left:22px;width:calc(100% - 22px)}
/* 总览里一组只铺前几篇，末尾这张是「还剩多少」而不是又一篇文章 */
.card-item.is-more{
  justify-content:center;background:var(--panel-soft);border-style:dashed;
  color:var(--text-2);font-size:12.5px;padding:9px 14px;
}
.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-thumb img{width:100%;height:100%;display:block;object-fit:cover}
.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}

/* 归档 / 分类总览的分组标题（右栏一份清单，左栏选中的是其中一组） */
.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-head.is-fold{align-items:center}
.grp-toggle{
  display:flex;align-items:baseline;gap:8px;flex:1 1 auto;min-width:0;
  padding:0;border:0;background:none;color:inherit;font:inherit;text-align:left;cursor:pointer;
}
.grp-toggle:hover .grp-name{color:var(--green-600)}
.grp-chev{flex:0 0 auto;color:var(--text-2);transform:rotate(90deg);transition:transform .15s ease}
.grp-toggle[aria-expanded="false"] .grp-chev{transform:rotate(0deg)}
.grp-open{flex:0 0 auto;font-size:12px;color:var(--green-600);opacity:.85}
.grp-open:hover{opacity:1;text-decoration:underline}
.card-list[hidden]{display:none}

/* 左栏一次只摊开一组：摊开那组的标题钉在列表顶上，没摊开的两枚留在贴底的胶囊条里 */
.side-grp{display:block}
.side-grp[hidden]{display:none}
.grp-cap{
  position:sticky;top:0;z-index:2;display:flex;align-items:baseline;gap:8px;
  padding:10px 14px;background:var(--panel);border-bottom:1px solid var(--line);
}
.gc-name{font-size:13px;font-weight:700;color:var(--green-700)}
.gc-num{font-size:11.5px;color:var(--text-2);margin-left:auto}
.side-tabs{
  position:sticky;bottom:0;z-index:3;display:flex;flex-direction:column;gap:6px;
  margin:8px 0 -12px;padding:8px 12px 10px;
  background:var(--panel);border-top:1px solid var(--line);
}
.tab-pill{
  display:flex;align-items:center;justify-content:center;gap:6px;width:100%;
  padding:8px 12px;border:1px solid var(--line);border-radius:999px;cursor:pointer;
  background:var(--panel-soft);color:var(--green-700);
  font:inherit;font-size:13px;font-weight:600;text-align:center;
}
.tab-pill:hover{border-color:var(--green-500);box-shadow:var(--glow-btn)}
.tab-pill:focus-visible{outline:2px solid var(--green-600);outline-offset:2px}
.tab-pill[hidden]{display:none}
.tp-n{font-style:normal;font-size:11.5px;font-weight:500;color:var(--text-2)}

/* 友链右栏：订阅源最新内容，两列卡片 */
.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)}
.feed-foot{margin:2px 2px 0;font-size:11.5px;color:var(--text-2)}
@media(max-width:640px){.feed-cards{grid-template-columns:minmax(0,1fr)}}

/* 文章目录：吸顶在正文顶沿的一条，滚过顶沿就钉住；点开摊列表，
   列表绝对压在正文上，不跟着把正文挤下去。 */
.toc-stick{position:sticky;top:0;z-index:4;background:var(--panel);padding:0 0 12px}
.toc-bar{
  display:flex;align-items:center;gap:7px;width:100%;height:36px;padding:0 4px;
  border:0;border-bottom:1px solid var(--line);background:var(--panel);
  color:var(--text-2);font-size:13px;font-weight:600;text-align:left;cursor:pointer;
}
.toc-bar:hover{color:var(--green-600)}
.toc-bar svg{flex-shrink:0}
.toc-cur{
  font-style:normal;font-weight:400;color:var(--text-2);flex-shrink:1;min-width:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis
}
.toc-n{font-style:normal;font-weight:400;font-size:11.5px;margin-left:auto;flex-shrink:0}
.toc-caret{flex-shrink:0;font-size:11px;transition:transform .15s}
.toc-bar[aria-expanded="true"] .toc-caret{transform:rotate(180deg)}
.toc-pop{
  position:absolute;left:0;right:0;top:100%;
  max-height:min(300px,45vh);overflow:auto;
  background:var(--panel);border-bottom:1px solid var(--line);border-radius:0 0 10px 10px;
  box-shadow:var(--glow-app);
}
.toc-pop[hidden]{display:none}
.toc-list{margin:0;padding:4px 2px 8px;list-style:none;font-size:13.5px;line-height:1.7}
.toc-list li.lv2{padding-left:12px}
.toc-list li.lv3{padding-left:24px}
.toc-list a{display:block;padding:1px 8px;border-radius:7px;color:var(--text-2);text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.toc-list a:hover{color:var(--green-600);background:var(--green-50)}
.toc-list a.is-on{color:var(--green-700);font-weight:600}

.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}
/* 从目录跳过来的标题别顶到滚动框上沿 */
/* 从目录跳过来的标题别顶到吸顶条下沿（条约 36px 高） */
.entry-content h2[id],.entry-content h3[id],.entry-content h4[id]{scroll-margin-top:44px}
.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)}

@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-stage{
  position:relative;width:100%;max-width:1080px;margin:0 auto;aspect-ratio:4/3;
  background-size:100% 100%;background-repeat:no-repeat;background-color:var(--panel-soft);
}
.town-man{position:absolute;left:var(--x);top:var(--y)}
.town-man{border:0;background:none;padding:0;color:inherit;font:inherit;cursor:pointer;z-index:3;transition:left 2.6s linear,top 2.6s linear}
.town-go{border:0;background:none;padding:0;color:inherit;font:inherit;cursor:pointer}
.town-folk{position:absolute;inset:0;z-index:2}
.town-man:focus-visible{outline:2px solid var(--green-600);outline-offset:3px;border-radius:8px}

/* 功能建筑：门框铺满整张底图但不接事件，只有房子那块范围接。
   于是点屋顶、点墙根都算点这栋，而房子以外的空地一点就穿过去，不挡过路的村民。
   范围本身不画任何东西——认功能看引路人头顶的牌子。 */
.town-go{position:absolute;inset:0;pointer-events:none;z-index:auto}
.go-out{position:absolute;inset:0;width:100%;height:100%;display:block;overflow:visible;pointer-events:none;z-index:1}
.go-hit{fill:none;stroke:none;pointer-events:all}
.go-man{
  position:absolute;left:var(--x);top:var(--y);z-index:4;
  width:calc(var(--px) * 4);height:calc(var(--px) * 7);
  transform:translate(-50%,-100%);pointer-events:auto;
}
.town-go:hover .go-man{animation:go-nudge .5s ease}
.town-go:focus-visible{outline:none}
@keyframes go-nudge{
  0%{transform:translate(-50%,-100%) translateY(0)}
  35%{transform:translate(-50%,-100%) translateY(-4px)}
  70%{transform:translate(-50%,-100%) translateY(1px)}
  100%{transform:translate(-50%,-100%) translateY(0)}
}
@media (prefers-reduced-motion:reduce){
  .town-go:hover .go-man{animation:none}
}

/* 摊位的引路人：一个摊子一组色，衣服和名字牌从同一组变量取，扫一眼就知道那是什么 */
.town-go{
  --shirt:var(--green-600);
  --tag-a:#eaf7ef;--tag-b:#cfead9;--tag-fg:#22432f;--tag-bd:#7cc39a;
}
.town-board{--shirt:#c8a23a;--tag-a:#fff4d6;--tag-b:#f0dcae;--tag-fg:#6b4e12;--tag-bd:#c8a23a}
.town-stall{--shirt:#2b6c96;--tag-a:#e6f2ff;--tag-b:#c9e0f7;--tag-fg:#1c4a6b;--tag-bd:#7fb0d8}
.town-stand{--shirt:#a8792a;--tag-a:#fdf3d6;--tag-b:#f2e2a8;--tag-fg:#6b5410;--tag-bd:#cfae2e}
.town-desk{--shirt:#63b98a;--tag-a:#dff6e8;--tag-b:#bce6cd;--tag-fg:#14512c;--tag-bd:#63b98a}
.town-pkt-stall{--shirt:#a03427;--tag-a:#ffe9e3;--tag-b:#f7cfc6;--tag-fg:#7a2a1e;--tag-bd:#e08c7a}
.town-ex-stall{--shirt:#2f6b62;--tag-a:#e6f2ef;--tag-b:#cbe7e0;--tag-fg:#1f5049;--tag-bd:#7fb3a9}
/* 传送门不是店，是一扇往外的门，颜色也不套镇上那套绿 */
.town-portal{--shirt:#7357b6;--tag-a:#f0ebff;--tag-b:#dbd1f6;--tag-fg:#3b2a68;--tag-bd:#a892dd}
/* 聊天室的引路人：身后没房子，牌子挂一张门脸；衣服取暖橙，跟传送门那身紫分开 */
.town-room-npc{--shirt:#c96a2b;--tag-a:#ffeee1;--tag-b:#f8d7bd;--tag-fg:#6b3a12;--tag-bd:#e0a068}
.man-tag .tag-ico{width:1.3em;height:1.3em;object-fit:contain;vertical-align:-.28em;margin-right:4px;border-radius:3px}
/* 图标那枚是 svg，跟着牌子字号走，别用 svg 上的属性尺寸 */
.man-tag span.tag-ico{display:inline-flex;vertical-align:-.28em;margin-right:4px}
.man-tag span.tag-ico svg{width:1.25em;height:1.25em}
.town-go .man-tag{
  background:linear-gradient(var(--tag-a),var(--tag-b));
  color:var(--tag-fg);border-color:var(--tag-bd);
  transition:transform .15s,box-shadow .15s,filter .15s;
}
.town-go:hover .man-tag{transform:translateX(-50%) translateY(-1px);filter:brightness(1.05);box-shadow:0 4px 10px rgba(20,40,30,.26)}

:root[data-mode="dark"] .town-go{--tag-a:#2a3b31;--tag-b:#1f2e26;--tag-fg:#cfe6d8;--tag-bd:#4b7a5c}
:root[data-mode="dark"] .town-board{--tag-a:#3b3218;--tag-b:#2b2410;--tag-fg:#f2e0a8;--tag-bd:#8a7420}
:root[data-mode="dark"] .town-stall{--tag-a:#1d3a52;--tag-b:#15293a;--tag-fg:#bfe0f7;--tag-bd:#3d6b90}
:root[data-mode="dark"] .town-stand{--tag-a:#3a3018;--tag-b:#2b2312;--tag-fg:#f0d9a0;--tag-bd:#8a6c20}
:root[data-mode="dark"] .town-desk{--tag-a:#1f3a2a;--tag-b:#162a1f;--tag-fg:#bfe6cc;--tag-bd:#3f7a55}
:root[data-mode="dark"] .town-pkt-stall{--tag-a:#3d211c;--tag-b:#2c1713;--tag-fg:#f6cbbd;--tag-bd:#8a4436}
:root[data-mode="dark"] .town-ex-stall{--tag-a:#1d322e;--tag-b:#152621;--tag-fg:#c2e3d9;--tag-bd:#3f6b62}
:root[data-mode="dark"] .town-portal{--tag-a:#2e2545;--tag-b:#221b33;--tag-fg:#d9ccf5;--tag-bd:#6b56a0}
:root[data-mode="dark"] .town-room-npc{--tag-a:#3d2a18;--tag-b:#2b1e12;--tag-fg:#f5d8b8;--tag-bd:#8a5a2c}

/* 像素小人：一个格子 + box-shadow 拼出的 4×7  sprite，衬衫色随人变 */
.man-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{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;
  max-width:min(240px, 34vw);overflow:hidden;text-overflow:ellipsis;
  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}

/* 小人头顶的「在干什么」：平时不占地方，鼠标放到小人上（或键盘 Tab 到他）才露头。
   露头的这会儿把心情圈藏起来——小卡正好要压在名字牌上方那一格，两个一起摆就叠上了。 */
.man-do{
  position:absolute;bottom:calc(100% + var(--px) + var(--tag-h) + 6px);left:50%;transform:translateX(-50%);
  display:none;flex-direction:column;gap:2px;padding:6px 9px;border-radius:9px;
  background:rgba(28,40,33,.93);color:#eef6f0;font-size:11.5px;line-height:1.45;white-space:nowrap;
  box-shadow:0 6px 16px rgba(20,40,30,.3);pointer-events:none;z-index:6;
}
.man-do::after{
  content:"";position:absolute;left:50%;bottom:-4px;transform:translateX(-50%) rotate(45deg);
  width:8px;height:8px;background:rgba(28,40,33,.93);
}
.md-row{display:flex;gap:10px;justify-content:space-between}
.md-row i{font-style:normal;color:#9fc0ad}
.md-row b{font-weight:600;text-align:right}
.town-man:hover .man-do,.town-man:focus-visible .man-do{display:flex}
.town-man:hover .man-mood,.town-man:focus-visible .man-mood{display:none}
/* 自己那一位从头到脚都黄一档，好让人知道「这个能点」 */
.town-man[data-self="1"] .man-tag{background:#ffe9a8;border-color:#d9a406;color:#4a3a20;font-weight:600}
.town-man[data-self="1"]{cursor:pointer}

/* ============ 小人自己溜达 ============ */
/* 位置走 left/top，所以挪起来是「走过去」而不是瞬移；服务端重画时 JS 会把人摆回原位 */
.man-pix{--flip:1;transform:scaleX(var(--flip));transform-origin:100% 50%}
.town-man.west .man-pix{--flip:-1}
.town-man.walking .man-pix{animation:man-step .42s steps(2,end) infinite}
@keyframes man-step{
  0%{margin-top:0}
  50%{margin-top:calc(var(--px) * -.6)}
  100%{margin-top:0}
}

/* ============ 广场的活气：喷泉、夜色、路灯 ============ */
/* 坐标全按底图 1024×768 画，舞台 4:3 且底图 100% 100%，所以 svg 拉满正好对上 */
.town-fx{position:absolute;inset:0;width:100%;height:100%;z-index:1;pointer-events:none;overflow:visible}
/* transform-box 不给的话，scale 绕的是 viewBox 原点 (0,0)：
   池子中心在 490,400，一呼一吸就被甩出十几像素，看着像光圈在喷泉上漂 */
.ff-water{fill:url(#town-water);transform-box:fill-box;transform-origin:center;animation:ff-tide 3.6s ease-in-out infinite}
@keyframes ff-tide{
  0%{opacity:.72;transform:scale(1,1)}
  50%{opacity:.95;transform:scale(1.04,1.1)}
  100%{opacity:.72;transform:scale(1,1)}
}
.ff-rip{fill:none;stroke:#f2fdff;stroke-width:2.4;transform-box:fill-box;transform-origin:center;opacity:0}
.rp1{animation:ff-ripple 2.8s ease-out infinite}
.rp2{animation:ff-ripple 2.8s ease-out infinite .95s}
.rp3{animation:ff-ripple 2.8s ease-out infinite 1.9s}
@keyframes ff-ripple{
  0%{transform:scale(.12);opacity:.9}
  70%{opacity:.3}
  100%{transform:scale(1);opacity:0}
}
.ff-shine{fill:none;stroke:#ffffff;stroke-width:3;stroke-linecap:round;opacity:.35;animation:ff-shine 3.2s ease-in-out infinite}
@keyframes ff-shine{
  0%{opacity:.18;transform:translateX(-9px)}
  50%{opacity:.7;transform:translateX(9px)}
  100%{opacity:.18;transform:translateX(-9px)}
}
/* 水柱、四股洒开的水、盘沿溢下来的三面水帘：靠虚线沿路径流动，一眼就是活水 */
.ff-jet{fill:none;stroke:#eafbff;stroke-width:6;stroke-linecap:round;opacity:.9;stroke-dasharray:12 9;animation:ff-flow .55s linear infinite}
.ff-arc{fill:none;stroke:#dff5ff;stroke-width:4;stroke-linecap:round;opacity:.85;stroke-dasharray:9 8;animation:ff-flow .8s linear infinite}
.ff-bowl{fill:#bfe9f7;opacity:.55}
.ff-cs{fill:none;stroke:#e6faff;stroke-width:5;stroke-linecap:round;opacity:.8;stroke-dasharray:8 7;animation:ff-flow .5s linear infinite}
.cs2{stroke-width:7;animation-duration:.42s}
.ac3,.cs3{animation-delay:.2s}
.ac4{animation-delay:.35s}
@keyframes ff-flow{to{stroke-dashoffset:-21}}
.fg{fill:#ffffff;opacity:0;transform-box:fill-box;transform-origin:center;animation:ff-glint 2.4s ease-in-out infinite}
.g2{animation-delay:.5s}.g3{animation-delay:1s}.g4{animation-delay:1.5s}.g5{animation-delay:2s}
@keyframes ff-glint{
  0%,100%{opacity:0;transform:scale(.4)}
  50%{opacity:1;transform:scale(1)}
}

/* 夜色压在场子上，人和房子都在底下；灯亮在夜色之上 */
.town-veil{
  position:absolute;inset:0;z-index:5;pointer-events:none;opacity:0;transition:opacity 1.4s ease;
  background:linear-gradient(180deg,rgba(12,26,64,.66),rgba(8,18,46,.5) 55%,rgba(5,11,30,.7));
}
.town-lamps{position:absolute;inset:0;width:100%;height:100%;z-index:6;pointer-events:none;opacity:0;transition:opacity 1.4s ease}
.lp-halo{fill:url(#town-lamp-glow)}
.lp-core{fill:#fff6d8}
:root[data-night="1"] .town-veil{opacity:1}
:root[data-night="1"] .town-lamps{opacity:1}
:root[data-night="1"] .town-lamp{animation:lamp-breathe 3.4s ease-in-out infinite}
/* 错开着呼吸，八盏一起明灭像跳闸。这两条必须带上前面的限定：
   只写 .town-lamp:nth-child() 权重比上面那条 shorthand 低，animation-delay 会被 shorthand 一并抹回 0。
   数的是 g，所以拿 nth-of-type 而不是 nth-child——svg 里第一个孩子是无害的 defs。 */
:root[data-night="1"] .town-lamp:nth-of-type(2n){animation-delay:1.1s}
:root[data-night="1"] .town-lamp:nth-of-type(3n){animation-delay:2.2s}
@keyframes lamp-breathe{
  0%{opacity:.82}
  50%{opacity:1}
  100%{opacity:.82}
}
/* 夜里的喷泉自己发点亮，不然水色被暮气压没了 */
:root[data-night="1"] .town-fx{opacity:.86;filter:brightness(1.18) saturate(1.1)}

@media (prefers-reduced-motion:reduce){
  .town-man{transition:none}
  .town-man.walking .man-pix,
  .ff-water,.ff-rip,.ff-shine,.ff-jet,.ff-arc,.ff-cs,.fg,.town-lamp{animation:none}
  .ff-rip{opacity:.25}
}

/* 点自己弹出的卡片里那一排心情 */
.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)}

/* 公告板引路人头顶的滚动公告 */
.town-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);
}
/* 引路人头顶先压着名字牌，公告得再往上抬一个牌子的高度才不叠在一起 */
.go-man .town-bubble{bottom:calc(100% + var(--px) + var(--tag-h) + 9px)}
.town-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-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-time{color:var(--text-2);font-size:11.5px;margin-top:3px}
/* 头像条上的名片往下翻：头顶那一侧是栏头，往上就撞出去 */
.town-card.tc-below{transform:translate(-50%,0)}

/* ---- 摊子点开的那台小电脑：机身是道具色，深浅两档都一样；屏幕里的雷盘跟着主题走 ---- */
.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)}
/* 排行榜窗口借用同一台机身：榜单在屏幕里自己滚，别让机身被顶出广场 */
.town-pc.is-rank .rank-stage{gap:9px}
.town-pc.is-rank .rank-panel{max-height:min(46vh,340px);overflow:auto;padding:10px 11px;border-radius:12px}
.town-pc.is-rank .rank-metric{margin-bottom:6px}
/* 兑换点窗口：机身宽一点好摆两列货架，货架自己在屏幕里滚 */
.town-pc.is-ex .tpc-case{width:min(560px,100%)}
.town-pc.is-ex .ex-stage{max-width:none;gap:11px;max-height:min(58vh,440px);overflow:auto}
.town-pc.is-ex .ex-grid{gap:10px}
.town-pc.is-ex .ex-card{padding:12px 13px}
/* 红包摊窗口：机身照排行榜那台，摊子在屏幕里自己滚。
   这一台是 position:fixed —— 摊子比别的机身宽，罩整页比只罩一栏舒展，
   窄屏整屏、宽屏整块卡片都算得准，不用跟着外壳换定位基准。 */
.town-pc.is-pkt{position:fixed;inset:0}
.town-pc.is-pkt .tpc-case{width:min(560px,100%)}
.town-pc.is-pkt .pkt-stage{max-width:none;gap:11px;max-height:min(58vh,440px);overflow:auto}
/* 出站确认窗：这一台摊在 .app 上，哪个视图点外链都够得着；固定定位罩住整页 */
.app>.town-pc.is-link{position:fixed;inset:0;z-index:60}
.app>.town-pc.is-link .tpc-case{width:min(390px,100%)}
/* 公告板和机身现在摊在 .app 上：窄屏底下就是当前那一栏，点哪儿就罩哪儿；
   宽屏照旧只罩右栏，左栏那一列功能留着还能点。红包摊和出站窗本来就是固定定位罩整页，不动。 */
@media(min-width:768px){
  .app>.town-sheet{left:calc(50% + 150px)}
  .app>.town-pc:not(.is-pkt):not(.is-link){left:300px}
}
.lk-stage{display:flex;flex-direction:column;align-items:center;gap:9px;text-align:center}
.lk-face{
  position:relative;width:52px;height:52px;border-radius:14px;overflow:hidden;
  display:flex;align-items:center;justify-content:center;
  background:#eef5ee;border:1px solid #cfdcd0;
}
.lk-icon{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
.lk-init{font-size:22px;font-weight:700;color:#2f7a4f}
.lk-name{font-size:14.5px;font-weight:700;word-break:break-all}
.lk-desc{font-size:12.5px;line-height:1.6;color:var(--text-2);word-break:break-all}
/* 地址用等宽单独一块：要看清的就是这行字，混在正文里等于没提示 */
.lk-url{
  width:100%;padding:7px 9px;border-radius:8px;background:#fff;border:1px solid #cfdcd0;
  font-family:ui-monospace,Consolas,monospace;font-size:12px;line-height:1.5;color:#41505f;
  word-break:break-all;text-align:left;
}
:root[data-mode="dark"] .lk-url{background:#161d18;color:#b9c6bb;border-color:#31413a}
:root[data-mode="dark"] .lk-face{background:#161d18;border-color:#31413a}
.lk-tip{margin:0;font-size:12px;color:var(--text-2)}
.lk-acts{display:flex;gap:10px;justify-content:center;padding:2px 0 4px}
.lk-btn{
  padding:6px 20px;border:1px solid #2f7a4f;border-radius:8px;background:#fff;color:#2f7a4f;
  font-size:13px;line-height:1.5;cursor:pointer;text-decoration:none;
}
.lk-btn:hover{background:#eef5ee}
.lk-btn.is-go{background:#2f7a4f;color:#fff}
.lk-btn.is-go:hover{filter:brightness(1.08);background:#2f7a4f}
@media(max-width:520px){
  .tpc-case{width:100%}
  .tpc-deck,.tpc-stand{display:none}
}

.town-hint{position:relative;display:flex;flex-wrap:wrap;gap:5px 14px;justify-content:center;padding:12px 14px 0;font-size:12px;color:var(--text-2)}
/* 状态条上面那道分隔线不拉满：通栏一条会把右栏横切成两截，跟顶上那排按钮抢视线 */
.town-hint::before{
  content:"";position:absolute;left:50%;top:0;transform:translateX(-50%);
  width:min(260px,55%);height:1px;background:var(--line);
}

/* ============ 小镇动态（广场形式之二：不收底图）+ 左栏那份功能列表 ============ */
.town-flow{
  position:relative;display:flex;align-items:flex-start;gap:14px;
  width:100%;max-width:1080px;margin:0 auto;
}
/* 功能列表在左栏，跟会话行同一套宽度，不再套卡片壳 */
.flow-rail{padding:0}
.fr-grp{font-size:11px;color:var(--text-2);padding:12px 16px 4px;letter-spacing:.04em}
.flow-go{
  display:flex;align-items:center;gap:8px;width:100%;padding:10px 14px;
  border:0;border-left:3px solid transparent;background:none;
  font:inherit;font-size:13.5px;color:var(--text);text-align:left;text-decoration:none;cursor:pointer;
}
.flow-go em{font-style:normal;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.flow-go:hover{background:var(--hover)}
.flow-go:focus-visible{outline:2px solid var(--green-600);outline-offset:-2px;border-radius:8px}
.flow-go.is-on{border-left-color:var(--green-600);background:var(--green-50);color:var(--green-700);font-weight:600}
.fr-n{
  margin-left:auto;font-style:normal;font-size:11px;font-weight:500;
  background:var(--green-100);color:var(--green-700);border-radius:999px;padding:0 7px;line-height:16px;
}
.flow-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:11px}
/* 滚动的那句公告：底图那一版贴在引路人头顶，这里没房子可贴，就摊在最上面一行 */
.flow-tip{
  font-size:12.5px;color:var(--green-700);background:var(--green-50);
  border:1px dashed var(--green-100);border-radius:10px;padding:7px 11px;
}
.flow-people{
  display:flex;align-items:center;gap:10px;padding:8px 11px;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;
}
.fp-label{flex:0 0 auto;font-size:12px;color:var(--text-2)}
.town-flow .town-folk{position:static;inset:auto;display:flex;flex-wrap:wrap;gap:6px;z-index:auto}
.town-av{position:relative;width:32px;height:32px;border:0;background:none;padding:0;cursor:pointer}
.town-av .avatar{width:32px;height:32px;font-size:13px}
.town-av[data-self="1"] .avatar{box-shadow:0 0 0 2px #ffe9a8,0 0 0 3px #d9a406}
.av-mood{
  position:absolute;right:-4px;bottom:-4px;
  font-size:11px;line-height:15px;padding:0 3px;background:var(--panel);
  border:1px solid var(--line);border-radius:999px;
}
.av-mood[hidden]{display:none}
/* 头像头顶的提示：离圆头像只留一道缝，箭头和底色沿用小人那套 */
.town-av .man-do{bottom:calc(100% + 8px)}
.town-av:hover .man-do,.town-av:focus-visible .man-do{display:flex}
.flow-feed{
  display:flex;flex-direction:column;gap:8px;padding:12px 13px;
  background:var(--panel-soft);border:1px solid var(--line);border-radius:14px;
}
.flow-day{font-size:11px;color:var(--text-2);text-align:center;margin:2px 0}
.flow-it{display:flex;align-items:center;gap:10px;padding:9px 11px;background:var(--panel);border:1px solid var(--line);border-radius:12px;color:inherit;text-decoration:none}
a.flow-it:hover{border-color:var(--green-500)}
.flow-it .avatar{width:26px;height:26px;font-size:12px;flex:0 0 26px}
.fi-body{flex:1;min-width:0;display:block}
.fi-l1{display:block;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fi-l1 b{color:var(--green-700);font-weight:600}
.fi-l2{display:block;font-size:11.5px;color:var(--text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fi-tm{flex:0 0 auto;font-size:11px;color:var(--text-2)}
.ff-none{margin:0;padding:14px 0;text-align:center;font-size:12.5px;color:var(--text-2)}
:root[data-mode="dark"] .town-av[data-self="1"] .avatar{box-shadow:0 0 0 2px #6b5210,0 0 0 3px #d9a406}

/* ============ 我的资料 ============ */
.town-me{width:100%;max-width:420px;margin:0 auto;display:flex;flex-direction:column;gap:12px}
.tm-face{display:flex;align-items:center;gap:11px;padding:14px 15px;background:var(--panel);border:1px solid var(--line);border-radius:14px}
.tm-face .avatar{width:46px;height:46px;font-size:18px;flex:0 0 46px;overflow:hidden}
.tm-face .avatar-img{width:100%;height:100%;object-fit:cover;border-radius:50%}
.tm-name{font-size:15px;font-weight:700;color:var(--text)}
.tm-role{margin-left:auto;font-size:11.5px;color:var(--green-700);background:var(--green-50);border:1px solid var(--green-100);border-radius:999px;padding:1px 9px}
.tm-note{margin:0;padding:10px 13px;font-size:12.5px;line-height:1.7;color:var(--text-2);background:var(--panel-soft);border:1px solid var(--line);border-radius:12px}
.tm-list{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:4px 15px}
.tm-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:9px 0;font-size:13px;border-bottom:1px solid var(--line)}
.tm-row:last-child{border-bottom:0}
.tm-row span{color:var(--text-2)}
.tm-row b{font-weight:600;color:var(--text);text-align:right}

/* ============ 扫雷摊（照经典盘面：灰盘子 + 立体边 + 红 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:#24408f}
.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:#8ba8ff}
: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}
  .town-bubble{max-width:170px;font-size:11px}
}

/* =========================================================
   扫雷成绩条 · 排行榜 · 红包摊 · 游客发言
   ========================================================= */

/* 整页扫雷上方那一排成绩：告诉玩家这局值多少分、今天还能拿多少 */
.mine-stat{
  display:flex;flex-wrap:wrap;gap:6px 16px;align-items:center;justify-content:center;
  max-width:860px;margin:0 auto 12px;padding:10px 14px;width:100%;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
  font-size:12.5px;color:var(--text-2);
}
.mine-stat b{font-size:14px;font-weight:700;color:var(--green-700)}
.mine-led-out{margin:0;min-height:17px;font-size:11.5px;line-height:1.5;text-align:center;color:var(--green-700)}
.mine-led-out:empty{display:none}

/* ---- 排行榜 ---- */
.rank-stage{
  display:flex;flex-direction:column;gap:12px;
  max-width:860px;margin:0 auto;width:100%;
}
.rank-settle{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px;
  padding:10px 14px;border-radius:12px;font-size:12.5px;color:#6b5410;
  background:linear-gradient(#fff8e6,#f7ecd0);border:1px solid #d8bd7a;
}
.rank-settle.is-done{color:var(--text-2);background:var(--panel-soft);border-color:var(--line)}
.rank-settle-btn{
  border:1px solid #b8912f;border-radius:999px;padding:6px 16px;cursor:pointer;
  background:linear-gradient(#f5e4b0,#e6cd85);color:#5a4308;font-size:12.5px;font-weight:700;
}
.rank-settle-btn:hover{filter:brightness(1.05)}
.rank-settle-btn[disabled]{opacity:.6;cursor:progress}

.rank-tabs{display:flex;flex-wrap:wrap;gap:8px;justify-content:center}
.rank-tab{
  border:1px solid var(--line);background:var(--panel);color:var(--text-2);
  border-radius:999px;padding:7px 20px;font-size:13px;font-weight:600;cursor:pointer;
  transition:background .15s,color .15s,border-color .15s;
}
.rank-tab:hover{border-color:var(--green-100);color:var(--green-700)}
.rank-tab.active{background:var(--green-600);border-color:var(--green-600);color:#fff;box-shadow:var(--glow-btn)}

.rank-panel{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:14px 16px}
.rank-metric{margin-bottom:8px;font-size:12px;color:var(--text-2);text-align:center}

.town-rank{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}
.town-rank-item{
  display:flex;align-items:center;gap:12px;padding:9px 12px;
  background:var(--panel-soft);border:1px solid var(--line);border-radius:12px;
}
.rank-no{flex-shrink:0;width:24px;text-align:center;font-size:15px;font-weight:700;color:var(--text-2)}
.rank-avatar{flex-shrink:0;width:34px;height:34px;border-radius:50%;object-fit:cover;background:var(--green-100)}
.rank-name{flex:1;min-width:0;font-size:14px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.rank-value{flex-shrink:0;font-size:16px;font-weight:700;color:var(--green-700)}
.rank-unit{margin-left:3px;font-size:11px;font-weight:500;font-style:normal;color:var(--text-2)}
.town-rank-top1{background:linear-gradient(#fffaf0,var(--panel));border-color:#e3c37c}
.town-rank-top2{background:linear-gradient(#f8fafb,var(--panel));border-color:#c9d2d8}
.town-rank-top3{background:linear-gradient(#fff8f1,var(--panel));border-color:#dcc0a4}
.town-rank-top1 .rank-no{color:#c08a10}
.town-rank-top2 .rank-no{color:#8f9aa4}
.town-rank-top3 .rank-no{color:#a3652f}
.town-rank-empty{padding:26px 16px;text-align:center;font-size:13px;color:var(--text-2)}

:root[data-mode="dark"] .rank-settle{background:linear-gradient(#3a3628,#2d2a1f);color:#f0d9a0;border-color:#6d5c39}
:root[data-mode="dark"] .rank-settle.is-done{background:var(--panel-soft);color:var(--text-2);border-color:var(--line)}
:root[data-mode="dark"] .rank-settle-btn{background:linear-gradient(#6d5c39,#4a3d22);border-color:#8a7440;color:#f5e8c4}
:root[data-mode="dark"] .town-rank-top1{background:linear-gradient(#332b16,var(--panel));border-color:#6d5c39}
:root[data-mode="dark"] .town-rank-top2{background:linear-gradient(#262d31,var(--panel));border-color:#3f4a52}
:root[data-mode="dark"] .town-rank-top3{background:linear-gradient(#31271c,var(--panel));border-color:#57432c}

/* ---- 红包摊 ---- */
.pkt-stage{display:flex;flex-direction:column;gap:14px;max-width:860px;margin:0 auto;width:100%}
.pkt-lock{
  padding:12px 14px;text-align:center;font-size:13px;color:var(--text-2);
  background:var(--panel-soft);border:1px solid var(--line);border-radius:12px;
}
.pkt-lock a{color:var(--green-600);font-weight:600}
.pkt-form{
  display:flex;flex-direction:column;gap:9px;
  padding:14px 16px;background:var(--panel);border:1px solid var(--line);border-radius:16px;
}
.pkt-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px 10px}
.pkt-label{flex:0 0 68px;font-size:12.5px;color:var(--text-2)}
.pkt-row label{display:inline-flex;align-items:center;gap:5px;font-size:13px;cursor:pointer}
.pkt-row input[type=number],.pkt-row input[type=text]{
  flex:1;min-width:0;max-width:200px;padding:8px 10px;font-size:14px;color:var(--text);
  border:1px solid var(--line);border-radius:10px;background:var(--green-50);
}
.pkt-hint{font-size:11.5px;color:var(--text-2)}
.pkt-send{
  align-self:flex-start;margin-top:2px;padding:9px 24px;border:none;border-radius:999px;cursor:pointer;
  background:linear-gradient(135deg,var(--green-500),var(--green-600));color:#fff;
  font-size:13.5px;font-weight:700;box-shadow:var(--glow-btn);transition:transform .12s,box-shadow .12s;
}
.pkt-send:hover{transform:translateY(-1px);box-shadow:var(--glow-btn-h)}
.pkt-send[disabled]{opacity:.55;cursor:progress;transform:none;box-shadow:none}

.pkt-list{display:flex;flex-direction:column;gap:10px}
.town-pkt{
  padding:13px 15px;background:var(--panel);border:1px solid var(--line);
  border-radius:16px;box-shadow:var(--glow-bub);
}
.town-pkt.is-open{background:linear-gradient(#fff8f2,var(--panel));border-color:#e8b48c}
.town-pkt-head{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.town-pkt-sender{font-size:14px;font-weight:700}
.town-pkt-kind{
  padding:2px 8px;border-radius:999px;font-size:11px;color:#7d4a24;
  background:var(--green-50);border:1px solid var(--green-100);
}
.town-pkt.is-open .town-pkt-kind{background:#ffeede;border-color:#f0c9a3}
.town-pkt-note{font-size:13.5px;line-height:1.6;color:var(--text);word-break:break-all}
.town-pkt-btn{
  display:block;width:100%;margin-top:10px;padding:9px 0;border:none;border-radius:12px;cursor:pointer;
  background:linear-gradient(#c8641f,#a8501a);color:#fff;font-size:13.5px;font-weight:700;
}
.town-pkt-btn:hover{filter:brightness(1.06)}
.town-pkt-btn.is-disabled{
  display:flex;align-items:center;justify-content:center;cursor:default;filter:none;
  background:var(--panel-soft);color:var(--text-2);box-shadow:inset 0 0 0 1px var(--line);
}
.town-pkt-meta{margin-top:8px;font-size:11.5px;color:var(--text-2)}
.town-pkt.is-expired,.town-pkt.is-full{opacity:.72}
.town-pkt.is-mine .town-pkt-sender::after{content:" · 我发的";font-size:11px;font-weight:500;color:var(--text-2)}

:root[data-mode="dark"] .town-pkt.is-open{background:linear-gradient(#33261a,var(--panel));border-color:#6b4a2c}
:root[data-mode="dark"] .town-pkt-btn{background:linear-gradient(#a4571c,#7a3a12)}
:root[data-mode="dark"] .pkt-row input[type=number],:root[data-mode="dark"] .pkt-row input[type=text]{background:var(--hover)}

/* ---- 兑换点 ---- */
.ex-stage{display:flex;flex-direction:column;gap:14px;max-width:860px;margin:0 auto;width:100%}
.ex-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:12px}
.ex-card{
  display:flex;flex-direction:column;gap:8px;padding:14px 15px;
  background:var(--panel);border:1px solid var(--line);border-radius:16px;box-shadow:var(--glow-bub);
}
.ex-card.is-gone{opacity:.62}
/* 缩略图压在卡顶上，负边距抵掉卡片内边距，图就跟卡片同宽齐边；圆角跟着上沿走 */
.ex-thumb{
  width:calc(100% + 30px);margin:-14px -15px 0;height:118px;object-fit:cover;
  border-radius:16px 16px 0 0;display:block;background:var(--green-50);
}
.ex-top{display:flex;align-items:center;gap:8px}
.ex-name{font-size:14.5px;font-weight:700;word-break:break-all}
.ex-kind{
  flex:0 0 auto;padding:2px 8px;border-radius:999px;font-size:11px;
  color:var(--green-700);background:var(--green-50);border:1px solid var(--green-100);
}
.ex-desc{font-size:12.5px;line-height:1.6;color:var(--text-2);word-break:break-all}
.ex-meta{display:flex;align-items:baseline;gap:8px;font-size:12px;color:var(--text-2)}
.ex-meta b{font-size:14px;color:var(--green-700)}
.ex-btn{
  display:block;width:100%;margin-top:auto;padding:9px 0;border:none;border-radius:12px;cursor:pointer;
  background:linear-gradient(135deg,var(--green-500),var(--green-600));color:#fff;
  font-size:13.5px;font-weight:700;text-align:center;list-style:none;
}
.ex-btn:hover{filter:brightness(1.06)}
.ex-btn::-webkit-details-marker{display:none}
.ex-btn.is-off{
  cursor:default;filter:none;background:var(--panel-soft);color:var(--text-2);
  box-shadow:inset 0 0 0 1px var(--line);
}
.ex-form-box{margin-top:auto;width:100%}
.ex-form-box[open] .ex-btn{border-radius:12px 12px 0 0}
.ex-form{
  display:flex;flex-direction:column;gap:8px;margin-top:6px;padding:12px;
  background:var(--panel-soft);border:1px solid var(--line);border-radius:12px;
}
.ex-field{display:flex;flex-direction:column;gap:4px;font-size:12px;color:var(--text-2)}
.ex-field input,.ex-field textarea{
  width:100%;min-width:0;padding:8px 10px;font-size:13.5px;color:var(--text);font-family:inherit;
  background:var(--panel);border:1px solid var(--line);border-radius:9px;resize:vertical;
}
.ex-tip{font-size:11.5px;line-height:1.6;color:var(--text-2)}
.ex-send{
  align-self:flex-start;padding:9px 22px;border:none;border-radius:999px;cursor:pointer;
  background:linear-gradient(135deg,var(--green-500),var(--green-600));color:#fff;
  font-size:13.5px;font-weight:700;box-shadow:var(--glow-btn);transition:transform .12s,box-shadow .12s;
}
.ex-send:hover{transform:translateY(-1px);box-shadow:var(--glow-btn-h)}
.ex-send[disabled]{opacity:.55;cursor:progress;transform:none;box-shadow:none}
.ex-notice{
  padding:12px 14px;font-size:12.5px;line-height:1.7;color:var(--text-2);
  background:var(--panel-soft);border:1px solid var(--line);border-radius:14px;
}
.ex-notice ul{margin:0;padding-left:18px}

.ex-list{display:flex;flex-direction:column;gap:10px}
.ex-row{
  display:flex;flex-direction:column;gap:5px;padding:12px 14px;
  background:var(--panel);border:1px solid var(--line);border-radius:14px;
}
.ex-row.is-done,.ex-row.is-canceled{background:var(--panel-soft);opacity:.82}
.ex-row-top{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px}
.ex-row-name{font-size:14px;font-weight:700}
.ex-row-kind,.ex-row-state{
  padding:2px 8px;border-radius:999px;font-size:11px;
  color:var(--green-700);background:var(--green-50);border:1px solid var(--green-100);
}
.ex-row-state{color:var(--text-2);background:var(--panel-soft);border-color:var(--line)}
.ex-row.is-done .ex-row-state{color:#1d6b3f;background:#e3f5e9;border-color:#b9e2c8}
.ex-row.is-canceled .ex-row-state{color:#8a4436;background:#fbeae6;border-color:#e8c4ba}
.ex-row-credits{margin-left:auto;font-size:12.5px;font-weight:700;color:var(--green-700)}
.ex-row-contact{font-size:12.5px;line-height:1.6;color:var(--text);word-break:break-all}
.ex-row-meta{font-size:11.5px;color:var(--text-2);word-break:break-all}
.ex-row-act{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}
.ex-note{
  flex:1 1 160px;min-width:0;padding:8px 10px;font-size:13px;color:var(--text);
  background:var(--panel-soft);border:1px solid var(--line);border-radius:9px;
}
.ex-act{
  padding:8px 14px;border:1px solid var(--line);border-radius:999px;cursor:pointer;
  font-size:12.5px;font-weight:700;background:var(--panel);color:var(--text);
}
.ex-act.is-done{background:linear-gradient(135deg,var(--green-500),var(--green-600));border-color:transparent;color:#fff}
.ex-act.is-cancel{background:var(--panel-soft);color:#8a4436;border-color:#e8c4ba}
.ex-act[disabled]{opacity:.55;cursor:progress}

:root[data-mode="dark"] .ex-row.is-done .ex-row-state{color:#9fdcb6;background:#1e3527;border-color:#37624a}
:root[data-mode="dark"] .ex-row.is-canceled .ex-row-state{color:#f0c2b4;background:#33201c;border-color:#6b3f36}

/* ---- 游客发言那一排：昵称、邮箱、验证码 ---- */
.chat-fields{flex-wrap:wrap}
.chat-fields .chat-code{flex:0 0 92px;max-width:92px}
.chat-captcha{
  align-self:center;height:34px;border-radius:8px;border:1px solid var(--line);
  background:var(--panel);cursor:pointer;
}
@media(max-width:640px){
  .mine-stat{gap:4px 12px;font-size:12px}
  .rank-panel{padding:12px 12px}
  .pkt-label{flex:1 1 100%}
}
