/* ==========================================================================
   院里 · 江南院子邻里互助 —— 移动端 Web 版样式
   设计方向：宣纸与青瓷（江南园林的克制美学）
   技术：原生 CSS，零依赖、零构建，file:// 与 WebView 均可直接加载
   ========================================================================== */

/* ---------------------------------------------------------------
   1. 设计令牌（与 PRD / 架构蓝图 / 原型 Demo 完全一致）
   --------------------------------------------------------------- */
:root{
  /* 青瓷绿主色系 */
  --primary:#1F7A5C;
  --primary-dark:#175F47;
  --primary-deep:#0F4535;
  --primary-light:#E6F2ED;
  --primary-mist:#F1F7F4;
  /* 铜金强调 */
  --accent:#E08A2E;
  --accent-deep:#B96F17;
  --accent-light:#FDF1E2;
  /* 语义色 */
  --danger:#D9534F;
  --danger-light:#FBECEB;
  --info:#3B7DA8;
  --info-light:#EAF2F8;
  --plum:#6B4C9A;
  --plum-light:#F1ECF7;
  /* 中性 */
  --bg:#F5F6F4;
  --paper:#FBFAF7;
  --surface:#FFFFFF;
  --border:#E8EAE7;
  --border-strong:#D6DCD8;
  --text:#1A1D1C;
  --text-2:#6B7370;
  --text-3:#9AA09E;
  --text-4:#B9BFBC;
  /* 形状 */
  --r-card:14px;
  --r-btn:10px;
  --r-pill:999px;
  --r-sheet:22px;
  /* 阴影 */
  --sh-card:0 1px 2px rgba(26,29,28,.04);
  --sh-lift:0 4px 16px rgba(26,29,28,.07);
  --sh-pop:0 8px 28px rgba(26,29,28,.12);
  --sh-brand:0 8px 22px rgba(31,122,92,.26);
  /* 字体：标题用宋体营造文人气质，正文用中文字体栈保证可读性 */
  --font:"PingFang SC","HarmonyOS Sans SC","MiSans","Source Han Sans SC","Noto Sans CJK SC","Microsoft YaHei",system-ui,-apple-system,sans-serif;
  --font-display:"Songti SC","STSong","Source Han Serif SC","Noto Serif CJK SC","Noto Serif SC",Georgia,serif;
  --font-mono:ui-monospace,"SFMono-Regular",Consolas,monospace;
  /* 布局 */
  --bar-h:50px;
  --tab-h:58px;
  --safe-t:env(safe-area-inset-top,0px);
  --safe-b:env(safe-area-inset-bottom,0px);
  --pad:16px;
}

/* ---------------------------------------------------------------
   2. 基础重置
   --------------------------------------------------------------- */
*,*::before,*::after{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;
  font-family:var(--font);
  font-size:15px;
  line-height:1.6;
  color:var(--text);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
  -webkit-tap-highlight-color:transparent;
  overscroll-behavior-y:none;
}
h1,h2,h3,h4,p,figure{margin:0}
ul,ol{margin:0;padding:0;list-style:none}
button,input,select,textarea{font:inherit;color:inherit}
button{background:none;border:0;padding:0;cursor:pointer}
a{color:var(--primary);text-decoration:none}
img{max-width:100%;display:block}
svg{display:block;flex:0 0 auto}
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
::selection{background:var(--primary-light);color:var(--primary-dark)}

/* 极淡纸纹 + 双色晕染，营造宣纸质感（纯 CSS，零图片） */
body::after{
  content:"";
  position:fixed;
  inset:0;
  pointer-events:none;
  z-index:0;
  background:
    radial-gradient(circle at 12% 8%,rgba(31,122,92,.055),transparent 42%),
    radial-gradient(circle at 88% 78%,rgba(224,138,46,.05),transparent 40%),
    radial-gradient(circle at 50% 120%,rgba(31,122,92,.04),transparent 55%);
}

/* ---------------------------------------------------------------
   3. 应用外壳
   --------------------------------------------------------------- */
.app{
  position:relative;
  z-index:1;
  display:flex;
  flex-direction:column;
  height:100vh;
  height:100dvh;
  background:var(--bg);
  overflow:hidden;
}

/* 顶部栏 */
.appbar{
  flex:0 0 auto;
  padding-top:var(--safe-t);
  background:var(--surface);
  border-bottom:1px solid var(--border);
  position:relative;
  z-index:20;
}
.appbar[hidden]{display:none}
.appbar.brand{background:var(--primary);border-bottom-color:transparent;color:#fff}
.appbar.brand::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.28),transparent);
}
.appbar-in{
  height:var(--bar-h);
  display:flex;
  align-items:center;
  gap:6px;
  padding:0 10px;
}
.appbar-back{
  width:34px;height:34px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  color:var(--text-2);
  transition:background .16s,color .16s;
}
.appbar.brand .appbar-back{color:#fff}
.appbar-back:active{background:rgba(0,0,0,.06)}
.appbar.brand .appbar-back:active{background:rgba(255,255,255,.16)}
.appbar-title{
  flex:1;min-width:0;
  font-size:17px;
  font-weight:600;
  letter-spacing:.3px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.appbar.brand .appbar-title{font-family:var(--font-display);font-size:19px;letter-spacing:1.6px;font-weight:700}
.appbar-act{
  min-width:34px;height:34px;padding:0 8px;border-radius:9px;
  display:inline-flex;align-items:center;gap:5px;justify-content:center;
  font-size:13.5px;color:var(--text-2);font-weight:500;
  transition:background .16s;
  position:relative;
}
.appbar.brand .appbar-act{color:rgba(255,255,255,.94)}
.appbar-act:active{background:rgba(0,0,0,.06)}
.appbar.brand .appbar-act:active{background:rgba(255,255,255,.16)}
.appbar-act .dot{
  position:absolute;top:5px;right:4px;
  width:8px;height:8px;border-radius:50%;background:var(--danger);
  border:1.6px solid var(--surface);
}
.appbar.brand .appbar-act .dot{border-color:var(--primary)}

/* 内容区 */
.appview{
  flex:1 1 auto;
  overflow-y:auto;
  overflow-x:hidden;
  -webkit-overflow-scrolling:touch;
  position:relative;
  scrollbar-width:thin;
}
.appview[hidden]{display:none}
.appview::-webkit-scrollbar{width:0}
.appview.has-tab{padding-bottom:calc(var(--tab-h) + var(--safe-b))}
/* fixed：页面自带固定底栏（聊天 / 详情输入条），滚动交给内部容器 */
.appview.fixed{overflow:hidden;display:flex;flex-direction:column;padding-bottom:0}
.scroll-area{flex:1 1 auto;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;scrollbar-width:thin}
.scroll-area::-webkit-scrollbar{width:0}

/* 底部导航 */
.tabbar{
  flex:0 0 auto;
  height:calc(var(--tab-h) + var(--safe-b));
  padding-bottom:var(--safe-b);
  background:rgba(255,255,255,.94);
  backdrop-filter:saturate(180%) blur(14px);
  -webkit-backdrop-filter:saturate(180%) blur(14px);
  border-top:1px solid var(--border);
  display:flex;
  align-items:center;
  position:relative;
  z-index:30;
}
.tabbar[hidden]{display:none}
.tab{
  flex:1;
  display:flex;flex-direction:column;align-items:center;gap:2px;
  padding:7px 0 5px;
  color:var(--text-3);
  font-size:10.5px;
  letter-spacing:.2px;
  transition:color .18s;
}
.tab svg{width:21px;height:21px;transition:transform .22s cubic-bezier(.22,.8,.3,1)}
.tab.on{color:var(--primary);font-weight:600}
.tab.on svg{transform:translateY(-1px)}
.tab:active svg{transform:scale(.9)}
.tab-dot{
  position:absolute;top:5px;margin-left:14px;
  min-width:16px;height:16px;padding:0 4px;border-radius:var(--r-pill);
  background:var(--danger);color:#fff;font-size:10px;font-weight:700;
  display:flex;align-items:center;justify-content:center;
  border:1.6px solid var(--surface);
}
.tab-plus{flex:0 0 auto;width:68px}
.tab-plus-btn{
  width:48px;height:48px;border-radius:50%;
  margin-top:-20px;
  background:linear-gradient(142deg,#2A8F6C,#175F47);
  color:#fff;
  display:flex;align-items:center;justify-content:center;
  box-shadow:var(--sh-brand);
  border:4px solid var(--surface);
  transition:transform .2s cubic-bezier(.22,.8,.3,1);
}
.tab-plus-btn svg{width:22px;height:22px}
.tab-plus:active .tab-plus-btn{transform:scale(.92)}
.tab-plus-label{font-size:10.5px;color:var(--text-3);margin-top:1px}

/* 启动态 */
.boot{
  position:absolute;inset:0;z-index:200;
  background:linear-gradient(158deg,#1F7A5C 0%,#26866A 46%,#37A07C 100%);
  color:#fff;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  transition:opacity .4s ease,visibility .4s;
}
.boot.off{opacity:0;visibility:hidden;pointer-events:none}
.boot-mark{
  width:72px;height:72px;border-radius:23px;
  background:rgba(255,255,255,.16);
  border:1px solid rgba(255,255,255,.3);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-display);font-size:34px;font-weight:700;
  margin-bottom:16px;
}
.boot-name{font-family:var(--font-display);font-size:30px;font-weight:700;letter-spacing:8px;text-indent:8px}
.boot-sub{font-size:12.5px;color:rgba(255,255,255,.82);letter-spacing:.6px;margin-top:4px}
.boot-bar{width:96px;height:2px;border-radius:2px;background:rgba(255,255,255,.24);overflow:hidden;margin-top:26px}
.boot-bar i{display:block;height:100%;width:40%;background:#fff;border-radius:2px;animation:bootSlide 1.1s ease-in-out infinite}
@keyframes bootSlide{0%{transform:translateX(-120%)}100%{transform:translateX(300%)}}

/* ---------------------------------------------------------------
   4. 排版工具
   --------------------------------------------------------------- */
.dsp{font-family:var(--font-display);letter-spacing:.4px}
.tnum{font-variant-numeric:tabular-nums}
.t-hero{font-size:27px;font-weight:700;line-height:1.3;font-family:var(--font-display);letter-spacing:.8px}
.t-h1{font-size:19px;font-weight:700;line-height:1.45;font-family:var(--font-display);letter-spacing:.5px}
.t-h2{font-size:16.5px;font-weight:600;line-height:1.5}
.t-h3{font-size:14.5px;font-weight:600;line-height:1.5}
.t-body{font-size:15px;line-height:1.7}
.t-sub{font-size:13.5px;line-height:1.7;color:var(--text-2)}
.t-cap{font-size:12px;color:var(--text-3)}
.t-micro{font-size:11px;color:var(--text-3)}
.t-primary{color:var(--primary)}
.t-gold{color:var(--accent-deep)}
.t-mute{color:var(--text-2)}
.t-dim{color:var(--text-3)}
.t-center{text-align:center}
.t-right{text-align:right}
.t-bold{font-weight:600}
.t-ell{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.t-clamp2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.t-clamp3{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.stack{display:flex;flex-direction:column}
.hstack{display:flex;align-items:center}
.between{display:flex;align-items:center;justify-content:space-between}
.gap6{gap:6px}.gap8{gap:8px}.gap10{gap:10px}.gap12{gap:12px}
.mt4{margin-top:4px}.mt8{margin-top:8px}.mt12{margin-top:12px}.mt16{margin-top:16px}.mt20{margin-top:20px}.mt24{margin-top:24px}
.pad{padding:var(--pad)}
.pad-t{padding-top:var(--pad)}
.pad-x{padding-left:var(--pad);padding-right:var(--pad)}
.grow{flex:1;min-width:0}

/* ---------------------------------------------------------------
   5. 通用组件
   --------------------------------------------------------------- */

/* 5.1 按钮 */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  border-radius:var(--r-btn);
  font-size:15px;font-weight:600;letter-spacing:.4px;
  padding:0 18px;height:46px;
  transition:transform .14s cubic-bezier(.22,.8,.3,1),background .18s,box-shadow .18s,opacity .18s;
  white-space:nowrap;
}
.btn:active{transform:scale(.975)}
.btn-block{display:flex;width:100%}
.btn-p{background:var(--primary);color:#fff;box-shadow:0 4px 14px rgba(31,122,92,.22)}
.btn-p:active{background:var(--primary-dark)}
.btn-o{background:var(--surface);color:var(--primary);border:1.4px solid var(--primary)}
.btn-g{background:var(--primary-light);color:var(--primary)}
.btn-s{background:var(--surface);color:var(--text-2);border:1.2px solid var(--border-strong)}
.btn-gold{background:var(--accent);color:#fff;box-shadow:0 4px 14px rgba(224,138,46,.24)}
.btn-danger{background:var(--danger);color:#fff}
.btn-sm{height:32px;font-size:13px;padding:0 13px;border-radius:8px;font-weight:500}
.btn-md{height:38px;font-size:14px;padding:0 16px;border-radius:9px}
.btn-lg{height:50px;font-size:16px}
.btn[disabled],.btn.is-disabled{
  background:#EBEEEB;color:var(--text-3);border-color:transparent;
  box-shadow:none;cursor:not-allowed;transform:none;
}
.btn-text{height:auto;padding:4px 2px;font-size:13.5px;color:var(--primary);font-weight:600}
.btn-text:active{opacity:.7}

/* 5.2 表单 */
.field{margin-bottom:15px}
.field-label{
  display:block;font-size:12.5px;font-weight:600;color:var(--text-2);
  margin-bottom:7px;letter-spacing:.3px;
}
.field-label .req{color:var(--danger);margin-left:2px}
.field-hint{font-size:11.5px;color:var(--text-3);margin-top:6px;line-height:1.6}
.field-err{
  font-size:11.5px;color:var(--danger);margin-top:6px;
  display:none;align-items:center;gap:4px;
}
.field-err.on{display:flex;animation:shakeIn .28s}
.field-ok{font-size:11.5px;color:var(--primary);margin-top:6px;display:none;align-items:center;gap:4px}
.field-ok.on{display:flex}
@keyframes shakeIn{0%{transform:translateX(-3px)}50%{transform:translateX(3px)}100%{transform:none}}

.input,.select,.textarea{
  width:100%;
  height:48px;
  border:1.4px solid var(--border);
  border-radius:var(--r-btn);
  background:var(--surface);
  font-size:15px;
  padding:0 14px;
  outline:none;
  transition:border-color .18s,box-shadow .18s,background .18s;
  -webkit-appearance:none;appearance:none;
}
.input::placeholder,.textarea::placeholder{color:var(--text-4)}
.input:focus,.select:focus,.textarea:focus{
  border-color:var(--primary);
  box-shadow:0 0 0 3px rgba(31,122,92,.1);
}
.input.err,.select.err,.textarea.err{
  border-color:var(--danger);
  box-shadow:0 0 0 3px rgba(217,83,79,.08);
}
.textarea{
  height:auto;min-height:110px;padding:12px 14px;line-height:1.7;resize:none;
}
.select{
  background-image:url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%236B7370' stroke-width='1.7' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right 14px center;
  padding-right:36px;
}
.select:disabled{background-color:#F7F8F6;color:var(--text-3);cursor:not-allowed}
.ip-group{position:relative}
.ip-group .input{padding-right:120px}
.ip-tail{position:absolute;right:6px;top:6px;bottom:6px;display:flex;align-items:center}
.code-btn{
  height:36px;padding:0 13px;border-radius:8px;
  background:var(--primary-light);color:var(--primary);
  font-size:12.5px;font-weight:600;white-space:nowrap;
  transition:background .18s,color .18s;
}
.code-btn:active{background:#D6EBE1}
.code-btn[disabled]{background:#F0F2F0;color:var(--text-3);cursor:not-allowed}
.house-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px}

/* 5.3 语义化分段控件 */
.seg{
  display:flex;gap:3px;padding:3px;
  background:var(--bg);border-radius:var(--r-pill);
}
.seg-btn{
  flex:1;height:38px;border-radius:var(--r-pill);
  font-size:13.5px;font-weight:600;color:var(--text-2);
  transition:background .2s,color .2s,box-shadow .2s;
}
.seg-btn.on{background:var(--surface);color:var(--primary);box-shadow:var(--sh-card)}

/* 5.4 标签 */
.tag{
  display:inline-flex;align-items:center;gap:3px;
  font-size:11px;font-weight:600;line-height:1;
  padding:4px 9px;border-radius:var(--r-pill);
  white-space:nowrap;
}
.tag-green{background:var(--primary-light);color:var(--primary)}
.tag-gold{background:var(--accent-light);color:var(--accent-deep)}
.tag-blue{background:var(--info-light);color:var(--info)}
.tag-red{background:var(--danger-light);color:var(--danger)}
.tag-plum{background:var(--plum-light);color:var(--plum)}
.tag-gray{background:#F1F3F0;color:var(--text-2)}
.tag-line{border:1px solid var(--border-strong);color:var(--text-2);background:var(--surface)}

/* 5.5 横向筛选条 */
.chips{
  display:flex;gap:8px;overflow-x:auto;
  padding:12px var(--pad) 4px;
  scrollbar-width:none;flex:0 0 auto;
}
.chips::-webkit-scrollbar{display:none}
.chip{
  flex:0 0 auto;height:32px;padding:0 14px;border-radius:var(--r-pill);
  border:1px solid var(--border);background:var(--surface);
  font-size:12.5px;color:var(--text-2);
  transition:background .18s,color .18s,border-color .18s;
}
.chip.on{background:var(--primary);color:#fff;border-color:var(--primary);font-weight:600}

/* 5.6 头像 */
.avatar{
  width:40px;height:40px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-size:14px;font-weight:700;
  flex:0 0 auto;
  background:var(--primary-light);color:var(--primary);
  border:1.6px solid transparent;
  transition:border-color .18s,transform .18s;
  user-select:none;
}
.avatar.tap{cursor:pointer}
.avatar.tap:active{transform:scale(.93);border-color:var(--primary)}
.av-a1{background:#E6F2ED;color:#1F7A5C}
.av-a2{background:#FDF1E2;color:#B96F17}
.av-a3{background:#EAF2F8;color:#3B7DA8}
.av-a4{background:#F1ECF7;color:#6B4C9A}
.av-a5{background:#FBECEB;color:#C0433F}
.av-official{background:linear-gradient(140deg,#1F7A5C,#2E9472);color:#fff}
.av-sm{width:34px;height:34px;font-size:12.5px}
.av-xs{width:30px;height:30px;font-size:11.5px}
.av-lg{width:56px;height:56px;font-size:20px}
.av-xl{width:64px;height:64px;font-size:24px}
.av-ring{border-color:rgba(255,255,255,.4)}

/* 5.7 卡片 / 分组 */
.card{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--r-card);
  box-shadow:var(--sh-card);
}
.card-pad{padding:15px 16px}
.section{margin-top:18px}
.section-head{
  display:flex;align-items:baseline;justify-content:space-between;
  padding:0 var(--pad) 9px;
}
.section-title{
  font-family:var(--font-display);
  font-size:15.5px;font-weight:700;letter-spacing:.8px;
  position:relative;padding-left:11px;
}
.section-title::before{
  content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:3px;height:14px;border-radius:2px;
  background:linear-gradient(180deg,var(--primary),#37A07C);
}
.section-more{font-size:12.5px;color:var(--text-3);display:inline-flex;align-items:center;gap:2px}
.list-title{
  font-size:12px;font-weight:600;color:var(--text-3);
  padding:16px var(--pad) 7px;letter-spacing:.4px;
}
.list{
  margin:0 var(--pad);
  border-radius:var(--r-card);
  overflow:hidden;
  border:1px solid var(--border);
  background:var(--surface);
  box-shadow:var(--sh-card);
}
.list.flush{margin:0;border-radius:0;border-left:0;border-right:0}
.divider{height:1px;background:var(--border);margin:0}
.lattice{
  height:8px;
  background-image:
    linear-gradient(90deg,rgba(31,122,92,.09) 1px,transparent 1px),
    linear-gradient(rgba(31,122,92,.09) 1px,transparent 1px);
  background-size:16px 8px;
  opacity:.6;
}

/* 5.8 列表行 */
.row{
  display:flex;align-items:center;gap:12px;
  padding:14px 16px;
  background:var(--surface);
  border-bottom:1px solid var(--border);
  transition:background .16s;
  width:100%;text-align:left;
}
.row:last-child{border-bottom:0}
.row.tap:active{background:#F7F9F7}
.row-ic{
  width:34px;height:34px;border-radius:10px;
  display:flex;align-items:center;justify-content:center;
  flex:0 0 auto;
}
.row-ic svg{width:18px;height:18px}
.ri-green{background:var(--primary-light);color:var(--primary)}
.ri-gold{background:var(--accent-light);color:var(--accent-deep)}
.ri-blue{background:var(--info-light);color:var(--info)}
.ri-plum{background:var(--plum-light);color:var(--plum)}
.ri-red{background:var(--danger-light);color:var(--danger)}
.ri-gray{background:#F1F3F0;color:var(--text-2)}
.row-main{flex:1;min-width:0}
.row-title{font-size:14.5px;font-weight:500;line-height:1.5}
.row-sub{
  font-size:11.5px;color:var(--text-3);line-height:1.55;margin-top:1px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.row-tail{
  display:flex;align-items:center;gap:7px;
  font-size:12px;color:var(--text-3);flex:0 0 auto;
}
.chev{color:var(--text-4);width:15px;height:15px}
.badge{
  min-width:18px;height:18px;padding:0 5px;border-radius:var(--r-pill);
  background:var(--danger);color:#fff;
  font-size:10.5px;font-weight:700;line-height:18px;text-align:center;
}
.badge-soft{background:var(--primary-light);color:var(--primary)}
.dot-red{width:7px;height:7px;border-radius:50%;background:var(--danger);flex:0 0 auto}

/* 5.9 开关 */
.switch{
  position:relative;width:46px;height:27px;flex:0 0 auto;
  appearance:none;-webkit-appearance:none;
  background:#D8DEDA;border-radius:var(--r-pill);
  cursor:pointer;outline:none;border:0;margin:0;
  transition:background .22s;
}
.switch:checked{background:var(--primary)}
.switch::after{
  content:"";position:absolute;top:3px;left:3px;
  width:21px;height:21px;border-radius:50%;background:#fff;
  box-shadow:0 1px 4px rgba(0,0,0,.2);
  transition:left .22s cubic-bezier(.22,.8,.3,1);
}
.switch:checked::after{left:22px}

/* 5.10 复选框 */
.chk{display:flex;gap:9px;align-items:flex-start;cursor:pointer}
.chk input{
  width:17px;height:17px;margin:3px 0 0;flex:0 0 auto;
  accent-color:var(--primary);
}
.chk span{font-size:12.5px;color:var(--text-2);line-height:1.65}
.chk a{color:var(--primary)}

/* 5.10.1 条款链接（《用户协议》《隐私政策》《未成年人安全承诺》）
   三份文档都**内置在 App 里**，点进去是 App 内页面（#/legal/xxx），
   所以统一做成"蓝色 + 无下划线"的可点样式：蓝色（--info）与正文的墨色、
   主题的绿都不同色相，一眼能看出"这里能点"，又不用下划线去抢注意力。
   ⚠ 这个类是全站唯一定义处（构造点见 pages.js 的 legalLink()）。
     `.chk a.link-doc` 是为了盖过上面那条 `.chk a{color:var(--primary)}`。 */
.link-doc,.chk a.link-doc,a.link-doc{
  color:var(--info);
  text-decoration:none;
  font-weight:600;
  cursor:pointer;
}
.link-doc:active{opacity:.6}

/* ---------------------------------------------------------------
   5.15 条款正文（用户协议 / 隐私条款 / 未成年人安全承诺）
   ---------------------------------------------------------------
   正文 HTML 由 h5/tools/build-legal.js 从官网同名页面生成，类名沿用官网那一套
   （.legal__sec / .note / .legal__meta / .legal__foot）。
   这里给的是移动端等效样式：不是"重新设计一份条款页"，而是让官网那份正文
   在手机宽度下读起来一样舒服 —— 同一份文档，两种载体。 */
.doc{padding:14px var(--pad) 30px}

.doc .legal__hd{
  padding-bottom:11px;margin-bottom:16px;
  border-bottom:1px solid var(--border);
}
.doc .legal__hd h1{
  font-size:19px;font-weight:700;line-height:1.4;
  color:var(--text);
  font-family:var(--font-display);
  letter-spacing:.5px;
}
.doc .legal__meta{
  display:flex;flex-wrap:wrap;gap:6px 10px;margin-top:8px;
  font-size:11px;color:var(--text-3);
}
.doc .legal__meta span{
  background:var(--bg);border:1px solid var(--border);
  border-radius:var(--r-pill);padding:2px 9px;
}

.doc .note{
  background:var(--accent-light);
  border:1px solid #F4E0C2;
  border-radius:var(--r-card);
  padding:12px 14px;
  margin:0 0 16px;
  font-size:12px;line-height:1.8;color:var(--accent-deep);
}
.doc .note b{font-weight:700}

.doc .legal__sec{margin:0 0 18px}
.doc .legal__sec h2{
  position:relative;
  font-size:14.5px;font-weight:700;line-height:1.5;
  color:var(--primary-deep);
  margin:0 0 9px;padding-left:10px;
}
.doc .legal__sec h2::before{
  content:'';position:absolute;left:0;top:4px;bottom:4px;width:3px;
  background:var(--primary);border-radius:2px;
}
.doc .legal__sec p{
  font-size:13.5px;line-height:1.86;color:var(--text-2);
  margin:0 0 7px;text-align:justify;
}
.doc .legal__sec b{color:var(--text);font-weight:600}
.doc .legal__sec ol,
.doc .legal__sec ul{margin:6px 0 7px;padding-left:20px}
.doc .legal__sec li{
  font-size:13.5px;line-height:1.86;color:var(--text-2);margin-bottom:4px;
}
.doc a[href^="tel:"],
.doc a[href^="mailto:"]{color:var(--info)}

/* 条款里的表格（联系方式、法律依据等）：窄屏按卡片式两栏，不横向溢出 */
.doc table{
  width:100%;border-collapse:collapse;margin:8px 0 6px;
  font-size:12.5px;
  border:1px solid var(--border);border-radius:var(--r-card);
  overflow:hidden;
}
.doc table th,
.doc table td{
  padding:8px 10px;text-align:left;vertical-align:top;
  line-height:1.75;border-bottom:1px solid var(--border);
}
.doc table tr:last-child th,
.doc table tr:last-child td{border-bottom:0}
.doc table th{
  width:34%;font-weight:600;color:var(--text);
  background:var(--bg);white-space:nowrap;
}
.doc table td{color:var(--text-2)}
.doc table a{color:var(--info);text-decoration:none}

/* 文末相关文件：正文的"下一页"入口，与正文拉开一点距离 */
.doc .legal__foot{
  margin-top:20px;padding-top:13px;
  border-top:1px solid var(--border);
  font-size:11.5px;line-height:1.9;color:var(--text-3);
}
.doc .legal__foot a{color:var(--info);text-decoration:none}

/* 5.11 统计 / 数据块 */
.stats{display:flex;padding:14px 0}
.stat{flex:1;text-align:center;position:relative}
.stat + .stat::before{
  content:"";position:absolute;left:0;top:14%;bottom:14%;
  width:1px;background:var(--border);
}
.stat-num{
  font-family:var(--font-display);
  font-size:19px;font-weight:700;color:var(--primary);
  display:block;line-height:1.3;
}
.stat-label{font-size:11px;color:var(--text-3)}
.stats.on-brand .stat-num{color:#fff}
.stats.on-brand .stat-label{color:rgba(255,255,255,.82)}
.stats.on-brand .stat + .stat::before{background:rgba(255,255,255,.2)}

/* 5.12 宫格入口 */
.tiles{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;padding:12px}
.tile{
  display:flex;flex-direction:column;align-items:flex-start;gap:6px;
  padding:14px;border-radius:12px;
  background:var(--surface);
  border:1px solid var(--border);
  text-align:left;
  transition:transform .16s cubic-bezier(.22,.8,.3,1),border-color .16s,box-shadow .16s;
}
.tile:active{transform:scale(.975);border-color:var(--primary);box-shadow:var(--sh-lift)}
.tile-ic{
  width:38px;height:38px;border-radius:11px;
  display:flex;align-items:center;justify-content:center;
}
.tile-ic svg{width:19px;height:19px}
.tile-name{font-size:13.5px;font-weight:600}
.tile-sub{font-size:10.5px;color:var(--text-3);line-height:1.5}
.tiles-4{grid-template-columns:repeat(4,1fr);gap:2px;padding:10px 6px}
.tiles-4 .tile{align-items:center;border:0;padding:10px 2px;background:none;gap:7px;text-align:center;border-radius:11px}
.tiles-4 .tile-ic{width:46px;height:46px;border-radius:14px}
.tiles-4 .tile-ic svg{width:22px;height:22px}
.tiles-4 .tile-name{font-size:11.5px;font-weight:500}

/* 5.13 空态 */
.empty{
  text-align:center;padding:56px 28px;color:var(--text-3);
}
.empty-ic{
  width:66px;height:66px;border-radius:50%;
  margin:0 auto 14px;
  background:var(--bg);
  display:flex;align-items:center;justify-content:center;
  color:var(--text-4);
}
.empty-ic svg{width:28px;height:28px}
.empty-title{font-size:14px;font-weight:600;color:var(--text-2);margin-bottom:3px}
.empty-sub{font-size:12px;line-height:1.65;margin-bottom:14px}

/* 5.14 说明条 */
.note-bar{
  margin:12px var(--pad) 0;
  padding:12px 14px;
  border-radius:var(--r-card);
  font-size:11.5px;line-height:1.75;
  border:1px solid transparent;
}
.note-green{background:var(--primary-light);color:var(--primary-dark);border-color:#D2E8DE}
.note-gold{background:var(--accent-light);color:var(--accent-deep);border-color:#F4E0C2}
.note-blue{background:var(--info-light);color:#2C5F82;border-color:#D5E5F1}
.note-gray{background:var(--bg);color:var(--text-2);border-color:var(--border)}
.note-bar b{font-weight:700}

/* ---------------------------------------------------------------
   6. 业务组件
   --------------------------------------------------------------- */

/* 6.1 治理公告置顶条 */
.gov-bar{
  margin:12px var(--pad) 0;
  padding:13px 15px;
  border-radius:var(--r-card);
  background:linear-gradient(136deg,#1F7A5C 0%,#2A8F6C 62%,#37A07C 100%);
  color:#fff;
  display:flex;gap:11px;align-items:center;
  box-shadow:0 8px 20px rgba(31,122,92,.22);
  position:relative;overflow:hidden;
}
.gov-bar::after{
  content:"";position:absolute;right:-26px;top:-26px;
  width:96px;height:96px;border-radius:50%;
  background:rgba(255,255,255,.07);
}
.gov-ic{
  width:34px;height:34px;border-radius:11px;
  background:rgba(255,255,255,.18);
  display:flex;align-items:center;justify-content:center;flex:0 0 auto;
}
.gov-main{flex:1;min-width:0}
.gov-kicker{
  font-size:10.5px;letter-spacing:1.2px;font-weight:600;
  color:rgba(255,255,255,.8);display:block;
}
.gov-title{
  font-size:13.5px;font-weight:600;line-height:1.45;margin-top:1px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.gov-bar.tap:active{transform:scale(.988)}

/* 6.2 帖子卡 */
.post{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--r-card);
  box-shadow:var(--sh-card);
  padding:15px;
  margin-bottom:11px;
  transition:transform .16s cubic-bezier(.22,.8,.3,1),border-color .16s,box-shadow .16s;
}
.post.tap{cursor:pointer}
.post.tap:active{transform:scale(.988);border-color:var(--border-strong)}
.post-head{display:flex;gap:10px;align-items:center;margin-bottom:11px}
.post-who{flex:1;min-width:0}
.post-name{
  font-size:13.5px;font-weight:600;line-height:1.4;
  display:flex;align-items:center;gap:5px;
}
.post-name .auth{
  width:14px;height:14px;border-radius:50%;
  background:var(--primary);color:#fff;
  display:inline-flex;align-items:center;justify-content:center;
  flex:0 0 auto;
}
.post-name .auth svg{width:9px;height:9px;stroke-width:3}
.post-meta-line{font-size:11.5px;color:var(--text-3);margin-top:1px}
.post-title{
  font-family:var(--font-display);
  font-size:16px;font-weight:700;line-height:1.5;
  letter-spacing:.3px;
  margin-bottom:7px;
}
.post-body{
  font-size:13.5px;color:var(--text-2);line-height:1.7;
  margin-bottom:10px;
}
.post-tags{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:11px}
.post-tags span{
  font-size:11.5px;color:var(--text-2);
  background:var(--bg);border-radius:7px;padding:4px 9px;
}
.post-tags span b{color:var(--text);font-weight:600}
.post-imgs{display:flex;gap:7px;margin-bottom:11px}
.post-imgs i{
  width:78px;height:78px;border-radius:10px;flex:0 0 auto;
  background:linear-gradient(140deg,#E6F2ED,#D0E4DB);
  display:flex;align-items:center;justify-content:center;
  color:#8FB3A5;
}
.post-imgs i svg{width:24px;height:24px}
.post-imgs i.alt{background:linear-gradient(140deg,#FDF1E2,#F4E0C2);color:#C79A5C}
.post-foot{
  display:flex;align-items:center;gap:16px;
  padding-top:11px;border-top:1px solid var(--border);
  font-size:11.5px;color:var(--text-3);
}
.post-foot .m{display:inline-flex;align-items:center;gap:4px}
.post-foot .m svg{width:14px;height:14px}
.post-foot .end{margin-left:auto}

/* 6.3 投票 */
.vote-opt{margin-bottom:12px}
.vote-opt:last-child{margin-bottom:0}
.vote-opt-label{
  display:flex;justify-content:space-between;gap:10px;align-items:baseline;
  font-size:13px;color:var(--text-2);margin-bottom:6px;
}
.vote-opt-label b{color:var(--text);font-weight:600}
.vote-opt-pct{font-size:12px;font-weight:700;color:var(--primary);flex:0 0 auto;font-variant-numeric:tabular-nums}
.vote-bar{height:9px;background:#EEF1EE;border-radius:var(--r-pill);overflow:hidden}
.vote-bar i{
  display:block;height:100%;border-radius:var(--r-pill);
  background:linear-gradient(90deg,#37A07C,#1F7A5C);
  transition:width .55s cubic-bezier(.3,.9,.3,1);
}
.vote-bar.lead i{background:linear-gradient(90deg,#E9A64C,#E08A2E)}
.vote-pick{
  display:flex;gap:11px;align-items:center;
  padding:13px;margin-bottom:9px;
  border:1.4px solid var(--border);
  border-radius:var(--r-btn);
  background:var(--surface);
  text-align:left;width:100%;
  transition:border-color .18s,background .18s;
}
.vote-pick:active{background:var(--primary-mist)}
.vote-pick.on{border-color:var(--primary);background:var(--primary-light)}
.vote-check{
  width:21px;height:21px;border-radius:50%;flex:0 0 auto;
  border:1.8px solid var(--border-strong);
  display:flex;align-items:center;justify-content:center;
  color:#fff;transition:background .18s,border-color .18s;
}
.vote-check svg{width:12px;height:12px;stroke-width:3;opacity:0;transition:opacity .18s}
.vote-pick.on .vote-check{background:var(--primary);border-color:var(--primary)}
.vote-pick.on .vote-check svg{opacity:1}
.vote-pick b{font-size:13.5px;font-weight:500;line-height:1.5}

/* 6.4 聊天 */
.chat-body{
  flex:1;overflow-y:auto;
  padding:14px 12px 18px;
  background:#EEF1EE;
  display:flex;flex-direction:column;gap:13px;
  -webkit-overflow-scrolling:touch;
}
.chat-stamp{
  text-align:center;font-size:10.5px;color:var(--text-3);
  background:rgba(255,255,255,.7);
  border-radius:var(--r-pill);
  padding:3px 11px;margin:0 auto;width:fit-content;
}
.msg{display:flex;gap:8px;max-width:88%}
.msg-side{min-width:0}
.msg-bub{
  background:var(--surface);
  border-radius:4px 13px 13px 13px;
  padding:9px 13px;
  font-size:14px;line-height:1.65;
  box-shadow:var(--sh-card);
  word-break:break-word;white-space:pre-wrap;
}
.msg-time{font-size:10px;color:var(--text-3);margin-top:4px}
.msg.me{margin-left:auto;flex-direction:row-reverse;animation:msgInR .26s cubic-bezier(.22,.8,.3,1)}
.msg.them{animation:msgInL .26s cubic-bezier(.22,.8,.3,1)}
.msg.me .msg-bub{background:var(--primary);color:#fff;border-radius:13px 4px 13px 13px}
.msg.me .msg-time{text-align:right}
@keyframes msgInL{from{opacity:0;transform:translateX(-6px)}to{opacity:1;transform:none}}
@keyframes msgInR{from{opacity:0;transform:translateX(6px)}to{opacity:1;transform:none}}
.chat-input{
  flex:0 0 auto;
  display:flex;gap:8px;align-items:center;
  padding:9px 10px calc(9px + var(--safe-b));
  background:var(--surface);
  border-top:1px solid var(--border);
}
.chat-icon{
  width:36px;height:36px;border-radius:50%;flex:0 0 auto;
  background:var(--bg);color:var(--text-2);
  display:flex;align-items:center;justify-content:center;
  transition:background .16s;
}
.chat-icon:active{background:#E4E8E4}
.chat-input .input{
  flex:1;height:38px;font-size:14px;
  border-radius:var(--r-pill);
  background:var(--bg);border-color:transparent;
  padding:0 15px;
}
.chat-input .input:focus{background:var(--surface);border-color:var(--primary)}
.chat-send{
  height:36px;padding:0 17px;border-radius:var(--r-pill);flex:0 0 auto;
  background:var(--primary);color:#fff;
  font-size:13.5px;font-weight:600;
  transition:background .18s,opacity .18s;
}
.chat-send[disabled]{background:#C6D5CF;cursor:not-allowed}

/* 6.5 输入动作条（帖子详情底部） */
.action-bar{
  flex:0 0 auto;
  display:flex;gap:8px;align-items:center;
  padding:9px 12px calc(9px + var(--safe-b));
  background:var(--surface);
  border-top:1px solid var(--border);
}
.act-icon{
  width:38px;height:38px;border-radius:50%;flex:0 0 auto;
  background:var(--bg);color:var(--text-2);
  display:flex;align-items:center;justify-content:center;
  transition:background .2s,color .2s,transform .16s;
}
.act-icon.on{background:var(--primary-light);color:var(--primary)}
.act-icon:active{transform:scale(.92)}

/* 6.6 评论区 */
.cmt{display:flex;gap:11px;padding:13px 0;border-bottom:1px solid var(--border)}
.cmt:last-child{border-bottom:0}
.cmt-head{
  font-size:12.5px;font-weight:600;color:var(--text-2);
  display:flex;align-items:baseline;gap:6px;margin-bottom:3px;
}
.cmt-head small{font-weight:400;color:var(--text-3);font-size:11px}
.cmt-text{font-size:14px;line-height:1.7}
.cmt-foot{
  display:flex;gap:15px;margin-top:6px;
  font-size:11px;color:var(--text-3);
}
.cmt-foot span{transition:color .16s}
.cmt-foot span:active{color:var(--primary)}

/* 6.7 个人中心头图 */
.profile-hero{
  background:linear-gradient(140deg,#1F7A5C 0%,#2A8F6C 58%,#37A07C 100%);
  padding:20px 18px 24px;
  color:#fff;
  position:relative;overflow:hidden;
}
.profile-hero::after{
  content:"";position:absolute;right:-40px;bottom:-60px;
  width:180px;height:180px;border-radius:50%;
  background:rgba(255,255,255,.06);
  border:1px solid rgba(255,255,255,.08);
}
.profile-hero::before{
  content:"";position:absolute;right:18px;top:-40px;
  width:120px;height:120px;border-radius:50%;
  background:rgba(255,255,255,.05);
}
.profile-name{
  font-family:var(--font-display);
  font-size:20px;font-weight:700;letter-spacing:.8px;
  display:flex;align-items:center;gap:8px;
}
.profile-sub{font-size:12px;color:rgba(255,255,255,.86);margin-top:4px}
.profile-meta{font-size:11.5px;color:rgba(255,255,255,.72);margin-top:3px}

/* 6.8 表单卡（认证页） */
.auth-hero{
  background:linear-gradient(154deg,#1F7A5C 0%,#26866A 48%,#37A07C 100%);
  padding:calc(34px + var(--safe-t)) 26px 32px;
  color:#fff;
  position:relative;overflow:hidden;
}
.auth-hero::after{
  content:"";position:absolute;right:-50px;top:-50px;
  width:200px;height:200px;border-radius:50%;
  border:1px solid rgba(255,255,255,.12);
  background:rgba(255,255,255,.05);
}
.auth-hero::before{
  content:"";position:absolute;left:-30px;bottom:-70px;
  width:150px;height:150px;border-radius:50%;
  border:1px solid rgba(255,255,255,.1);
}
.auth-mark{
  width:58px;height:58px;border-radius:19px;
  background:rgba(255,255,255,.16);
  border:1px solid rgba(255,255,255,.3);
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-display);font-size:27px;font-weight:700;
  margin-bottom:15px;
}
.auth-brand{
  font-family:var(--font-display);
  font-size:26px;font-weight:700;letter-spacing:5px;
}
.auth-slogan{font-size:12.5px;color:rgba(255,255,255,.84);margin-top:5px;letter-spacing:.3px}
.auth-body{padding:22px 24px 26px}
.auth-foot{
  padding:0 24px 26px;
  text-align:center;font-size:11px;color:var(--text-3);line-height:1.8;
}
.auth-title{
  font-family:var(--font-display);
  font-size:22px;font-weight:700;letter-spacing:.8px;
  margin-bottom:6px;
}
.step-tags{display:flex;justify-content:center;align-items:center;gap:7px;margin-bottom:20px}
.done-mark{
  width:78px;height:78px;border-radius:50%;
  background:var(--primary-light);color:var(--primary);
  display:flex;align-items:center;justify-content:center;
  margin:0 auto 18px;
  animation:popIn .42s cubic-bezier(.22,.9,.3,1);
}
.done-mark svg{width:36px;height:36px}
@keyframes popIn{0%{transform:scale(.5);opacity:0}60%{transform:scale(1.06)}100%{transform:none;opacity:1}}

/* 6.9 演示账号卡 */
.demo-card{
  border:1px dashed #C9DCD3;
  background:var(--primary-mist);
  border-radius:var(--r-card);
  padding:13px 14px;
}
.demo-line{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  font-size:12px;color:var(--text-2);
  padding:5px 0;
}
.demo-line + .demo-line{border-top:1px dashed #DCE8E2}
.demo-line code{
  font-family:var(--font-mono);font-size:11.5px;
  color:var(--accent-deep);background:#fff;
  border-radius:5px;padding:2px 6px;
}

/* 6.10 名片弹层 */
.profile-card{text-align:center}
.profile-card .avatar{margin:0 auto 12px}
.pc-name{
  font-family:var(--font-display);font-size:19px;font-weight:700;letter-spacing:.6px;
}
.pc-sub{font-size:12px;color:var(--text-3);margin-top:4px;display:flex;align-items:center;justify-content:center;gap:6px;flex-wrap:wrap}
.pc-stats{display:flex;gap:9px;margin:16px 0}
.pc-stats > div{flex:1;background:var(--bg);border-radius:11px;padding:11px 4px}
.pc-stats b{display:block;font-family:var(--font-display);font-size:17px;color:var(--primary)}
.pc-stats span{font-size:10.5px;color:var(--text-3)}
.pc-tip{
  text-align:left;font-size:11.5px;color:var(--text-3);line-height:1.75;
  background:var(--bg);border-radius:10px;padding:11px 13px;margin-bottom:16px;
}

/* ---------------------------------------------------------------
   7. 浮层：弹层 / 对话框 / 轻提示
   --------------------------------------------------------------- */
.sheet-mask{
  position:fixed;inset:0;z-index:100;
  background:rgba(16,22,19,.44);
  backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);
  display:flex;align-items:flex-end;justify-content:center;
  animation:fadeIn .2s;
}
.sheet{
  width:100%;max-width:520px;
  background:var(--surface);
  border-radius:var(--r-sheet) var(--r-sheet) 0 0;
  padding:8px 20px calc(24px + var(--safe-b));
  max-height:84vh;overflow-y:auto;
  animation:sheetUp .3s cubic-bezier(.22,.8,.3,1);
}
.sheet-grip{
  width:36px;height:4px;border-radius:2px;background:var(--border-strong);
  margin:6px auto 14px;
}
.sheet-title{
  font-family:var(--font-display);
  font-size:17px;font-weight:700;letter-spacing:.6px;
  margin-bottom:4px;
}
.sheet-sub{font-size:12.5px;color:var(--text-3);margin-bottom:16px}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@keyframes sheetUp{from{transform:translateY(28px);opacity:.5}to{transform:none;opacity:1}}
@keyframes sheetDown{from{transform:none;opacity:1}to{transform:translateY(28px);opacity:0}}

.dialog-mask{
  position:fixed;inset:0;z-index:110;
  background:rgba(16,22,19,.44);
  backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);
  display:flex;align-items:center;justify-content:center;
  padding:32px;
  animation:fadeIn .2s;
}
.dialog{
  width:100%;max-width:340px;
  background:var(--surface);
  border-radius:18px;
  padding:22px 20px 18px;
  text-align:center;
  animation:popIn .28s cubic-bezier(.22,.9,.3,1);
}
.dialog-title{
  font-family:var(--font-display);
  font-size:17px;font-weight:700;letter-spacing:.5px;
}
.dialog-text{font-size:13.5px;color:var(--text-2);line-height:1.75;margin-top:9px}
.dialog-actions{display:flex;gap:10px;margin-top:20px}

.toast-root{
  position:fixed;left:50%;bottom:96px;transform:translateX(-50%);
  z-index:200;display:flex;flex-direction:column;align-items:center;gap:8px;
  pointer-events:none;width:100%;padding:0 24px;
}
.toast{
  max-width:100%;
  background:rgba(22,28,25,.92);
  color:#fff;
  font-size:13px;line-height:1.5;
  padding:10px 18px;border-radius:var(--r-pill);
  box-shadow:0 8px 24px rgba(0,0,0,.2);
  animation:toastIn .26s cubic-bezier(.22,.9,.3,1);
  backdrop-filter:blur(6px);
  text-align:center;
}
.toast.out{animation:toastOut .24s forwards}
.toast.ok{background:rgba(23,95,71,.95)}
.toast.warn{background:rgba(185,111,23,.95)}
.toast.err{background:rgba(183,63,59,.95)}
@keyframes toastIn{from{opacity:0;transform:translateY(12px) scale(.96)}to{opacity:1;transform:none}}
@keyframes toastOut{to{opacity:0;transform:translateY(-6px) scale(.97)}}

/* ---------------------------------------------------------------
   8. 动效
   --------------------------------------------------------------- */
@keyframes rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes fadeUpSoft{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.page-enter{animation:fadeUpSoft .3s cubic-bezier(.22,.8,.3,1)}
.stagger > *{animation:rise .36s cubic-bezier(.22,.8,.3,1) backwards;animation-delay:calc(var(--i,0) * 42ms)}

.skel{
  background:linear-gradient(100deg,#EEF1EE 30%,#F7F9F7 50%,#EEF1EE 70%);
  background-size:220% 100%;
  animation:shimmer 1.35s linear infinite;
  border-radius:8px;
}
@keyframes shimmer{from{background-position:130% 0}to{background-position:-30% 0}}

/* 加载态行 */
.loading-line{
  display:flex;align-items:center;justify-content:center;gap:9px;
  padding:26px;color:var(--text-3);font-size:12.5px;
}
.spin{
  width:16px;height:16px;border-radius:50%;
  border:2px solid var(--border-strong);
  border-top-color:var(--primary);
  animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}

/* ---- 页面转场（2026-10-14）：导航分三类方向感 ----
   进深层「推入」、返回「弹出」、同级切 tab 只「淡入 + 4px 上浮」。
   只动 transform / opacity（合成层动画，不触发重排），220ms，
   缓动沿用全站既有的 cubic-bezier(.22,.8,.3,1)。
   .view-ghost 是旧页的残影层：旧页节点被整棵搬进来（不深拷贝，滚动位置等
   DOM 状态留在原件上），绝对定位铺满可视区，出场动画走完即移除；
   pointer-events:none 保证它不挡新页的点击。
   .view-next 是新页，负责入场。 */
.view-ghost{
  position:absolute;left:0;right:0;top:0;bottom:0;
  overflow:hidden;pointer-events:none;z-index:0;
  background:var(--bg);
}
/* fixed 页（帖子详情 / 投票 / 聊天）的外层是 flex 纵向，残影层必须一起还原，
   否则内部 .scroll-area 与 .action-bar 的相对关系会走形。 */
.view-ghost.is-fixed{display:flex;flex-direction:column}
/* 固定定位的悬浮件（发布按钮 / 登录页悬浮入口）不跟着残影走：它们本来就钉在视口上，
   搬进残影层反而会在动效期间"漂"到旧位置再突然消失。 */
.view-ghost .fab-fixed,.view-ghost .floatbar{display:none}
.view-next{position:relative;z-index:1;background:var(--bg)}
.view-next.in-r{animation:viewInR .22s cubic-bezier(.22,.8,.3,1)}
.view-next.in-l{animation:viewInL .22s cubic-bezier(.22,.8,.3,1)}
.view-next.in-fade{animation:viewInFade .22s cubic-bezier(.22,.8,.3,1)}
.view-ghost.out-l{animation:viewOutL .22s cubic-bezier(.22,.8,.3,1) forwards}
.view-ghost.out-r{animation:viewOutR .22s cubic-bezier(.22,.8,.3,1) forwards}
@keyframes viewInR{from{opacity:0;transform:translateX(18px)}to{opacity:1;transform:none}}
@keyframes viewInL{from{opacity:0;transform:translateX(-18px)}to{opacity:1;transform:none}}
@keyframes viewInFade{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}
@keyframes viewOutL{from{opacity:1;transform:none}to{opacity:0;transform:translateX(-14px)}}
@keyframes viewOutR{from{opacity:1;transform:none}to{opacity:0;transform:translateX(14px)}}

/* 顶栏标题换页时淡入：给"换页"一个轻量提示，不闪不跳 */
.appbar-title.title-in{animation:titleIn .2s cubic-bezier(.22,.8,.3,1)}
@keyframes titleIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}

/* 骨架 → 真实内容 的交叉淡入：数据到位后换掉骨架时不硬闪 */
.fade-in{animation:contentIn .24s cubic-bezier(.22,.8,.3,1)}
@keyframes contentIn{from{opacity:0}to{opacity:1}}

/* fixed 页（帖子详情 / 投票 / 聊天）的页面容器必须撑满 .appview，
   否则内部的 .scroll-area{flex:1 1 auto} 与 .action-bar{flex:0 0 auto} 形同虚设：
   滚动区只按内容高度排（内容高 = 可视高，等于根本不滚），输入条被顶到内容下方，
   页面下半截白白空着。（.appview.fixed 早先假设"页面渲染出来的就是 flex 容器"，
   后来外层包了一层，而那一层既没给 flex，也不是 display:flex。） */
.appview.fixed > .view-next,
.view-ghost.is-fixed > *{
  flex:1 1 auto;display:flex;flex-direction:column;min-height:0;
}

/* 板块页悬浮发布按钮：随移动视口居中 */
.fab-fixed{
  position:fixed;
  right:16px;
  bottom:calc(var(--tab-h) + var(--safe-b) + 16px);
  z-index:15;
}

/* ---------------------------------------------------------------
   登录页「教学视频 / 添加到手机桌面」悬浮入口组（2026-10-08）
   ---------------------------------------------------------------
   2026-10-08 第二轮：从"一个按钮"改成"一组按钮"（新增「教学视频」）。
   **定位交给容器 .floatbar，按钮只负责长相** —— 容器右对齐贴边，
   所以再加按钮只会让容器向左长，主行动「添加到桌面」始终钉在右下角原位不动
   （用户已经熟悉那个位置，不该因为多一个入口就搬家）。
   容器同样渲染在 #appView（可滚动容器）内部、用 position:fixed：
   手机上等于"钉在视口右下角"，与既有 .fab-fixed 同一做法。
   宽屏下 .app 会缩成 430px 的手机框，此时用媒体查询把**容器**挪回框内 ——
   不挪的话它会飘在手机框外面的空白处（.fab-fixed 现在就是这样）。
   已从桌面图标打开（standalone）时由 JS 不渲染，不靠 CSS 藏。
   ⚠ 类名统一 ah- / addhome 前缀，避免与既有样式撞名。 */
.floatbar{
  position:fixed;right:14px;bottom:calc(20px + var(--safe-b));z-index:20;
  display:flex;align-items:center;gap:8px;
}
.addhome{
  display:inline-flex;align-items:center;gap:7px;
  padding:9px 15px 9px 12px;border:0;border-radius:var(--r-pill);
  background:var(--primary);color:#fff;
  font:inherit;font-size:13px;font-weight:600;letter-spacing:.4px;
  box-shadow:var(--sh-brand);cursor:pointer;white-space:nowrap;
  transition:transform .16s cubic-bezier(.22,.8,.3,1),opacity .2s;
  animation:fadeUpSoft .4s .45s both;
}
.addhome:active{transform:scale(.96)}
.addhome svg{width:18px;height:18px;flex:0 0 auto}
/* 次级入口「教学视频」：纸底 + 品牌字，不跟主行动抢注意力；
   比主按钮早 90ms 出现，让两个按钮有先后感而不是"一起蹦出来"。 */
.addhome--alt{
  background:var(--surface);color:var(--primary);
  border:1px solid var(--primary-light);box-shadow:var(--sh-card);
  animation-delay:.36s;
}
@media (min-width:560px){
  .floatbar{right:calc(50vw - 215px + 14px);bottom:46px}
}

/* 教学视频弹层：9:16 竖屏素材，所以按**高**限制（52vh）等比缩放并居中 ——
   让它跟着手机高度走；按宽度铺满会在矮屏上把弹层顶出屏幕。
   width/height 都留 auto，替换元素会自己按比例缩，不会被拉变形。 */
.tut-wrap{display:flex;justify-content:center;margin:2px 0 14px}
.tut-v{
  display:block;width:auto;height:auto;max-width:100%;max-height:52vh;
  background:#000;border-radius:var(--r-btn);box-shadow:var(--sh-card);
}

/* 引导层内部 */
.ah-app{display:flex;align-items:center;gap:12px;padding-bottom:14px;margin-bottom:14px;border-bottom:1px solid var(--border)}
.ah-app img{width:54px;height:54px;border-radius:13px;flex:0 0 auto;box-shadow:var(--sh-card)}
.ah-app b{display:block;font-size:15px;font-family:var(--font-display)}
.ah-app span{display:block;font-size:12.5px;color:var(--text-3);margin-top:4px;line-height:1.5}
.ah-ua{display:inline-block;margin-left:6px;padding:1px 8px;border-radius:var(--r-pill);
  background:var(--primary-light);color:var(--primary);font-size:11px;font-weight:600}
.ah-steps{counter-reset:ah;margin:0;padding:0;list-style:none}
.ah-steps li{counter-increment:ah;position:relative;padding:0 0 13px 30px;
  font-size:13.5px;line-height:1.65;color:var(--text-2)}
.ah-steps li:last-child{padding-bottom:0}
.ah-steps li::before{content:counter(ah);position:absolute;left:0;top:1px;
  width:20px;height:20px;border-radius:50%;background:var(--primary-light);
  color:var(--primary);font-size:11.5px;font-weight:700;line-height:20px;text-align:center}
.ah-steps b{color:var(--text);font-weight:600}
.ah-note{margin-top:15px;padding:11px 13px;border-radius:var(--r-btn);
  background:var(--primary-mist);font-size:12.5px;line-height:1.65;color:var(--text-2)}
.ah-tip{margin-top:12px;font-size:12px;line-height:1.65;color:var(--text-3)}

/* ---------------------------------------------------------------
   9. 响应式：宽屏居中为移动视口
   --------------------------------------------------------------- */
@media (min-width:560px){
  body{
    display:flex;align-items:center;justify-content:center;
    padding:26px 0;
    background:#E6EAE6;
  }
  body::after{display:none}
  .app{
    width:430px;
    height:min(894px,calc(100vh - 52px));
    border-radius:34px;
    border:1px solid #D5DAD6;
    box-shadow:0 30px 70px rgba(20,26,23,.24);
    overflow:hidden;
    position:relative;
  }
  body::before{
    content:"";
    position:fixed;inset:0;pointer-events:none;z-index:0;
    background:
      radial-gradient(circle at 18% 12%,rgba(31,122,92,.08),transparent 42%),
      radial-gradient(circle at 84% 82%,rgba(224,138,46,.07),transparent 40%);
  }
  .app,.toast-root{z-index:1}
  .fab-fixed{right:calc(50vw - 215px + 16px)}
}

/* ---------------------------------------------------------------
   关于页：整块内容在可视区里居中（2026-10-11）
   ---------------------------------------------------------------
   原来内容贴着顶部、下面留一大片空白，头重脚轻。现在让「品牌标 + 名称 + 版本」
   在**顶部栏以下的整个可视区**里垂直居中（横向本来就居中）。
   ⚠ 高度不用百分比：min-height:100% 依赖父级（.appview 是 flex 子项）高度可解析，
     个别安卓 WebView 上会退化成内容高度、等于没居中。这里直接按视口算，
     并照 .app 的既有做法先给 vh 兜底、再用 dvh 覆盖：不支持 dvh 的浏览器会丢掉那一条，
     vh 那条仍然生效。
   ⚠ 用 min-height 而不是 height：内容比可视区高时（超短屏 / 系统放大字号）要能正常撑开滚动，
      且 flex 居中不会把内容推到顶部栏下面去。
   ⚠ 末尾那个 1px 是顶部栏的 border-bottom（它在 .appbar 上，不在 --bar-h 里）——
      不减掉的话整块会比可视区高 1px，白多出一条 1px 的滚动量。 */
.about-center{
  min-height:calc(100vh - var(--safe-t) - var(--bar-h) - 1px);
  min-height:calc(100dvh - var(--safe-t) - var(--bar-h) - 1px);
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;padding:24px 20px;box-sizing:border-box;
}

/* 深色模式：仅对系统设置生效，保持主色不变 */
@media (prefers-color-scheme:dark){
  /* 有意保留浅色：社区类产品的可信感依赖明亮基调，避免自动反色带来的身份识别混乱 */
}

/* 降低动效偏好 */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
}

/* 打印：仅保留内容 */
@media print{
  .appbar,.tabbar,.chat-input,.action-bar,body::after{display:none !important}
  .appview{overflow:visible;padding:0}
  body{background:#fff}
}
