.nav{position:sticky;top:0;z-index:30;display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:14px 24px;background:var(--nav-surface);
  background-image:linear-gradient(180deg,var(--nav-glow),transparent 72%);
  border-bottom:1px solid var(--border);
  box-shadow:0 12px 34px rgba(0,0,0,.32)}
.nav::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(124,156,255,.55),transparent);opacity:.8}
.brand{display:flex;align-items:center;gap:10px;font-weight:800;letter-spacing:.5px;flex:0 0 auto;min-width:0}
.brand-name{display:inline-block;font-size:15px;letter-spacing:.4px;max-width:34vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.logo{width:32px;height:32px;border-radius:10px;background:url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%3E%3Cdefs%3E%3ClinearGradient%20id%3D%22g%22%20x1%3D%220%22%20y1%3D%220%22%20x2%3D%221%22%20y2%3D%221%22%3E%3Cstop%20offset%3D%220%22%20stop-color%3D%22%237c9cff%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%23b388ff%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%2232%22%20height%3D%2232%22%20rx%3D%228%22%20fill%3D%22url%28%23g%29%22%2F%3E%3Cpath%20d%3D%22M16%2026%20C10%2020%206%2016%206%2012%20C6%209%208%206%2012%206%20C14%206%2016%208%2016%2010%20C16%208%2018%206%2020%206%20C24%206%2026%209%2026%2012%20C26%2016%2022%2020%2016%2026%20Z%22%20fill%3D%22white%22%20opacity%3D%22.92%22%2F%3E%3Cpath%20d%3D%22M9%2024c0%200%202.5-2%207-2s7%202%207%202%22%20stroke%3D%22white%22%20stroke-width%3D%221.2%22%20fill%3D%22none%22%20opacity%3D%22.6%22%20stroke-linecap%3D%22round%22%2F%3E%3Cpath%20d%3D%22M6%2026c0%200%203.5-2%2010-2s10%202%2010%202%22%20stroke%3D%22white%22%20stroke-width%3D%221%22%20fill%3D%22none%22%20opacity%3D%22.45%22%20stroke-linecap%3D%22round%22%2F%3E%3C%2Fsvg%3E') center/cover no-repeat;box-shadow:0 6px 18px rgba(124,156,255,.5)}
.nav-links{display:flex;gap:4px;align-items:center;flex:1 1 auto;justify-content:center;min-width:0;
  flex-wrap:wrap;row-gap:2px}
/* 2026-09-20：这里原本是 flex-wrap:nowrap + overflow-x:auto（9 个栏目靠横向滚动兜住）。
   现在一级只有 6 项 + 「更多」，改成换行显示，同时**去掉 overflow**——
   overflow:auto 会形成裁剪上下文，把「更多」下拉的浮层切掉一半（菜单看起来“点了没反应”）。
   换行比横向滚动对用户更友好：滚动条藏在 sticky 顶栏里，很多人根本不知道右边还有栏目。
   折行点不随页面变化：一级项数固定，宽度只由字体栈决定（见 test_frontend_nav.py 字重断言）。 */
.nav-more{position:relative;display:inline-flex}
.nav-more>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;gap:5px;
  color:var(--muted);font-size:14px;font-weight:600;padding:8px 14px;border-radius:10px;white-space:nowrap;
  transition:color .2s var(--ease),background .2s var(--ease);user-select:none}
.nav-more>summary::-webkit-details-marker{display:none}
.nav-more>summary::marker{content:""}
.nav-more>summary::after{content:"";width:5px;height:5px;border-right:1.6px solid currentColor;
  border-bottom:1.6px solid currentColor;transform:rotate(45deg) translate(-1px,-1px);
  transition:transform .2s var(--ease)}
.nav-more[open]>summary::after{transform:rotate(-135deg) translate(-2px,-2px)}
.nav-more>summary:hover{color:var(--text);background:var(--surface2)}
/* 与 .nav a.active 同一套视觉（只改颜色/底色/描边，不改盒模型） */
.nav-more>summary.active{color:var(--text);background:var(--surface2);box-shadow:inset 0 0 0 1px var(--border)}
.nav-more-menu{position:absolute;top:calc(100% + 8px);right:0;z-index:40;min-width:172px;margin:0;
  padding:6px;list-style:none;display:flex;flex-direction:column;gap:2px;
  background:var(--surface);border:1px solid var(--border2);border-radius:14px;box-shadow:var(--shadow)}
.nav-more-menu a{display:block;padding:9px 12px;border-radius:9px;font-size:14px}
.nav-actions{display:flex;align-items:center;gap:8px;flex:0 0 auto}
.nav a{color:var(--muted);text-decoration:none;font-size:14px;padding:8px 14px;border-radius:10px;white-space:nowrap;flex:0 0 auto;
  /* 关键：所有链接（含激活项）必须同字重。激活态曾用 font-weight:700，而中文加粗会变宽，
     菜单又是整行居中——于是每换一个页面，全部链接都跟着横移一次，看起来像「导航变形」。
     字重全站恒定后，激活态只改颜色/底色/描边，零布局位移。 */
  font-weight:600;transition:color .2s var(--ease),background .2s var(--ease)}
.nav a:hover{color:var(--text);background:var(--surface2)}
/* 当前所在栏目：全站唯一高亮实现（此前 .nav a.active 根本没有样式，等于没提示）。
   只允许改视觉（颜色/底色/inset 描边），不允许改任何盒模型属性（字号/字重/内外边距）。 */
.nav a.active{color:var(--text);background:var(--surface2);box-shadow:inset 0 0 0 1px var(--border)}
.nav a.active:hover{background:var(--surface3)}
.icon-btn{width:40px;height:40px;border-radius:12px;border:1px solid var(--border);background:var(--surface2);
  color:var(--text);cursor:pointer;font-size:16px;transition:transform .25s var(--ease),background .2s var(--ease)}
.icon-btn:hover{transform:translateY(-2px);background:var(--surface3)}
.acct{display:inline-flex;align-items:center;justify-content:center;font-size:13px;padding:8px 14px;border-radius:999px;
  border:1px solid var(--border);background:var(--surface2);color:var(--text);cursor:pointer;font-weight:700;
  text-decoration:none;transition:.2s var(--ease);max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  /* min-width：账号按钮在「登录(2字)/我的档案/系统管理员(5字)」之间变宽会让居中的菜单整体横移，
     全站钉住同一盒宽，跨页只换文字不挪菜单。 */
  min-width:96px}
.acct:hover{border-color:var(--brand);background:var(--surface3)}
/* 单一断点：≤1160px 一律折成两行（第一行品牌+账号+主题，第二行菜单横向滚动）。
   刻意不用「装不下才折行」——那样同一个宽度下，不同页面会因为账号按钮文字长度不同
   （登录 / 我的档案 / 系统管理员）而折行点不同，导航高度随之在 65/69/83/93px 之间跳变。 */
@media (max-width:1160px){
  .nav{flex-wrap:wrap;padding:10px 14px;padding-top:calc(10px + env(safe-area-inset-top,0px));gap:4px}
  .nav .brand{order:0;margin-right:auto}
  .nav .nav-actions{order:1;margin-left:auto}
  .nav .nav-links{order:2;width:100%;flex:1 0 100%;justify-content:flex-start;padding-top:6px;border-top:1px solid var(--border);gap:2px}
  .nav .nav-links a,.nav-more>summary{padding:7px 10px;font-size:13px}
  .icon-btn{width:42px;height:42px}
}
@media (max-width:560px){
  .brand-name{font-size:13px;letter-spacing:.3px;max-width:46vw}
  .nav a,.nav-more>summary{padding:7px 9px;font-size:12.5px}
  .acct{padding:9px 13px}
}
/* 小屏：一级 6 项本来就要换行，这里只做两件事 ——
   ①把「更多」钉在行尾（margin-left:auto）：它的浮层菜单是 right:0 向左展开的，
     钉在行尾就永远有空间，不会在窄屏上被屏幕边缘切掉；
   ②菜单本身限宽，别挤到屏幕外。菜单仍是浮层（.nav-links 已不再 overflow，
     浮层不会被裁），不占顶栏高度。 */
@media (max-width:600px){
  .nav-more{margin-left:auto}
  .nav-more-menu{min-width:0;max-width:min(180px,calc(100vw - 28px))}
}
/* 小屏（≤430px）第一行还要放账号 / 后台 / 主题三个按钮，不压缩就会把按钮行
   挤成两行（导航 106px → 142px）。这里只压后台按钮的文字（保留图标），
   品牌名继续显示——比整条顶栏换高更容易看懂自己在哪。 */
@media (max-width:430px){
  .brand-name{font-size:12.5px;letter-spacing:.2px;max-width:38vw}
  .acct{max-width:112px;padding:9px 11px;font-size:12.5px}
  #adminBtn{font-size:0;padding:9px 11px}
  #adminBtn::before{content:"后台";font-size:12.5px;letter-spacing:.5px}
}

/* ==== 动效令牌（design_system.py） ==== */
:root{
  --dur-1:120ms; --dur-2:180ms; --dur-3:260ms; --dur-4:380ms; --dur-5:560ms;
  --ease-standard:cubic-bezier(.2,.7,.3,1);
  --ease-enter:cubic-bezier(.16,.84,.24,1);
  --ease-exit:cubic-bezier(.4,0,1,1);
  --ease-spring:cubic-bezier(.34,1.56,.64,1);
  /* 间距/圆角/层级：与既有 --radius-*/--shadow-* 对齐，补齐产品化缺的两档 */
  --radius-xs:6px; --radius-pill:999px;
  --z-nav:30; --z-tabbar:40; --z-palette:80; --z-toast:90;
  --tap:44px;                 /* 移动端最小可点区域 */
}
/* 入场：只做 6px 位移 + 透明度，260ms 内结束；不做缩放（缩放会触发文字重排，肉眼更「抖」） */
@keyframes dsViewIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
@keyframes dsFadeIn{from{opacity:0}to{opacity:1}}
@keyframes dsScaleIn{from{opacity:0;transform:translateY(8px) scale(.97)}to{opacity:1;transform:none}}
@keyframes dsToastIn{from{opacity:0;transform:translateY(10px) scale(.98)}to{opacity:1;transform:none}}
.ds-enter{animation:dsViewIn var(--dur-3) var(--ease-enter) both}
.ds-enter-lg{animation:dsScaleIn var(--dur-4) var(--ease-enter) both}
/* 列表错峰入场：父级加 .ds-stagger，子项自动按序延迟（最多 8 项，避免第 20 项等 1 秒） */
.ds-stagger>*{animation:dsViewIn var(--dur-3) var(--ease-enter) both;
  animation-delay:calc(var(--i,0) * 36ms)}
.ds-stagger>*:nth-child(1){--i:0}.ds-stagger>*:nth-child(2){--i:1}.ds-stagger>*:nth-child(3){--i:2}
.ds-stagger>*:nth-child(4){--i:3}.ds-stagger>*:nth-child(5){--i:4}.ds-stagger>*:nth-child(6){--i:5}
.ds-stagger>*:nth-child(7){--i:6}.ds-stagger>*:nth-child(n+8){--i:7}
/* 区块入场：滚动进入视口时淡入上移一次。给元素加 data-reveal 即可（见 SHELL_JS.reveal）。
   渐进增强——.ds-reveal 由 JS 附加，JS 关闭/失败时正文保持可见，绝不把内容藏起来。 */
.ds-reveal{opacity:0;transform:translateY(12px)}
.ds-reveal.ds-in{opacity:1;transform:none;
  transition:opacity var(--dur-4) var(--ease-enter),transform var(--dur-4) var(--ease-enter)}
/* 交互反馈：悬停抬升 2px、按压回落 —— 全站唯一写法 */
.ds-lift{transition:transform var(--dur-2) var(--ease-standard),box-shadow var(--dur-2) var(--ease-standard)}
.ds-lift:hover{transform:translateY(-2px)}
.ds-press{transition:transform var(--dur-1) var(--ease-standard)}
.ds-press:active{transform:scale(.985)}
button:not(:disabled):active,.btn:not(:disabled):active{transform:translateY(1px) scale(.995)}
/* 键盘可达性：全站统一焦点环（此前只有 10 处 focus-visible） */
:focus-visible{outline:2px solid var(--brand);outline-offset:2px;border-radius:var(--radius-xs)}
a,button,input,select,textarea{-webkit-tap-highlight-color:transparent}
html{scroll-behavior:smooth}
/* 跨页转场：Chromium 126+ 原生支持，纯 CSS 渐进增强（不支持则完全无行为） */
@view-transition{navigation:auto}
::view-transition-old(root){animation:dsFadeIn var(--dur-2) var(--ease-exit) reverse}
::view-transition-new(root){animation:dsFadeIn var(--dur-3) var(--ease-enter)}
/* 顶栏不参与转场：转场期间顶栏重绘会造成「导航抖一下」 */
.nav{view-transition-name:none}
/* 减动效：尊重系统设置（焦虑/前庭敏感用户群体尤其重要）。
   不是"关掉动画"就完事——状态必须仍然可读，所以只把时长压到 1ms、去掉循环。 */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:1ms !important;animation-iteration-count:1 !important;
    transition-duration:1ms !important;scroll-behavior:auto !important;
  }
  .ds-lift:hover{transform:none}
  /* 区块入场在减动效下不做位移/淡入：直接可见（信息不靠动画传达） */
  .ds-reveal{opacity:1;transform:none}
  html{scroll-behavior:auto}
}


/* ==== 状态原语（design_system.py） ==== */
.ds-skeleton{position:relative;overflow:hidden;background:var(--surface2);
  border-radius:var(--radius-sm);border:1px solid var(--border)}
.ds-skeleton::after{content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.07) 45%,transparent);
  animation:dsShimmer 1.35s var(--ease-standard) infinite;transform:translateX(-100%)}
@keyframes dsShimmer{to{transform:translateX(100%)}}
.ds-skeleton-line{height:12px;margin:10px 0}
.ds-skeleton-line.w60{width:60%}.ds-skeleton-line.w80{width:80%}
.ds-skeleton-title{height:18px;width:38%;margin-bottom:14px}
.ds-skeleton-card{height:96px;margin:12px 0}
.ds-skeleton-ring{width:48px;height:48px;border-radius:50%}
/* 统一状态块：空态/错误态/加载态同一骨架，避免每页各画一套 */
.ds-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;
  text-align:center;padding:40px 22px;color:var(--muted)}
.ds-state-ico{width:46px;height:46px;border-radius:14px;display:grid;place-items:center;
  background:var(--surface2);border:1px solid var(--border);color:var(--brand);font-size:20px}
.ds-state-title{color:var(--text);font-weight:700;font-size:15px}
.ds-state-desc{font-size:13px;line-height:1.65;max-width:46ch}
.ds-state-actions{display:flex;gap:8px;margin-top:6px;flex-wrap:wrap;justify-content:center}
.ds-state.is-error .ds-state-ico{color:var(--bad);border-color:rgba(255,111,138,.35)}
/* 忙碌按钮：.ds-busy 期间锁交互 + 内联转圈（替换「按钮文案变…」这类无反馈写法） */
.ds-spinner{width:14px;height:14px;border-radius:50%;flex:0 0 auto;
  border:2px solid currentColor;border-top-color:transparent;animation:dsSpin .7s linear infinite}
@keyframes dsSpin{to{transform:rotate(360deg)}}
.ds-busy{pointer-events:none;opacity:.75}
.ds-busy .ds-spinner{display:inline-block}
/* 顶部滚动进度（长页面可用性） */
#dsProgress{position:fixed;top:0;left:0;height:2px;width:0;z-index:var(--z-palette);
  background:linear-gradient(90deg,var(--brand),var(--accent));opacity:0;
  transition:width var(--dur-1) linear,opacity var(--dur-2) var(--ease-standard)}
#dsProgress.on{opacity:.9}
/* 跳过导航（键盘/读屏用户第一个 Tab 就能直达正文） */
.ds-skip{position:absolute;left:8px;top:-60px;z-index:var(--z-palette);
  background:var(--surface3);color:var(--text);border:1px solid var(--border);
  padding:10px 14px;border-radius:var(--radius-sm);font-size:13px;text-decoration:none;
  transition:top var(--dur-2) var(--ease-enter)}
.ds-skip:focus{top:8px}


/* ==== 应用壳层（design_system.py） ==== */
/* 导航分组（IA）：9 个栏目按「探索 / 成长 / 服务」的顺序平铺（顺序定义在
   psy_ui._NAV_ZONES，NAV_CONTRACT 由它派生）。
   2026-09-20：宽屏下曾额外渲染 .nav-zone 分组文字标签，实测「11px 灰字 + 竖线」
   夹在链接之间只增加噪声（用户反馈顶栏臃肿），已移除；不再提供 .nav-zone 样式，
   避免有人照旧样式把标签加回来。 */
/* 顶栏不放全局搜索 / 命令面板（2026-09-20 用户反馈：快速跳转用不上，顶栏只要
   「登录 + 主题」两个入口）。导航本身已是 9 个平级栏目的单层结构，直达页面；
   原先那套搜索按钮、快捷键提示与命令面板的样式和 JS 已一并删除，别再加回来。 */
/* 页脚 v2：品牌 / 导航 / 支持与法律 / 危机热线 四段（原页脚只有三段且挤在一起）
   2026-09-20 调整：① 品牌栏收窄（1.6fr→1.4fr），链接栏拿到更多横向空间，四栏在
   1080 容器里更均衡；② 窄屏改「品牌通栏 + 两列链接」——原 ≤620px 直接塌成一列，
   而 .foot-main 又被并排的 logo 挤到 ~180px 宽，于是页脚变成一条又长又窄的竖列。 */
.foot-v2{display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr;gap:24px 28px;align-items:start;
  max-width:1080px;margin:0 auto;text-align:left}
.foot-v2 .foot-col-title{color:var(--text);font-weight:700;font-size:12.5px;letter-spacing:.08em;
  text-transform:uppercase;opacity:.9;margin-bottom:10px}
.foot-v2 a{color:var(--muted);text-decoration:none;font-size:13px;display:block;padding:5px 0;
  transition:color var(--dur-2) var(--ease-standard)}
.foot-v2 a:hover{color:var(--brand)}
.foot-v2 .foot-tagline{color:var(--muted);font-size:13px;line-height:1.75;max-width:34ch}
.foot-v2 .foot-ver{color:var(--muted);font-size:12px;opacity:.72;margin-top:12px}
@media (max-width:900px){
  .foot-v2{grid-template-columns:1fr 1fr;gap:22px 26px}
  /* 品牌栏通栏：否则 2 列时被压成半宽，简介每行只放得下几个字 */
  .foot-v2>.foot-col:first-child{grid-column:1/-1}
  /* 「支持与法律」独占一行：它排在 2 列网格的下一行首格，右半会留一大块空白，
     而紧跟着就是危机热线分隔线——通栏后这一行才收得住。 */
  .foot-v2>.foot-col:last-child{grid-column:1/-1}
}
@media (max-width:620px){
  .foot-v2{grid-template-columns:1fr 1fr;gap:18px 18px}
  .foot-v2 .foot-tagline{max-width:none}
}
/* 390px 这类主流手机宽度仍保持 2 列：单列会把 4 栏堆成 ~795px 高的竖条，
   正是「页脚又长又臃肿」的来源；最窄（≤360px，如 iPhone SE）才退单列。 */
@media (max-width:360px){.foot-v2{grid-template-columns:1fr}}
/* 移动端底部导航（≤620px）：
   桌面隐匿、移动固定；页面可用 <body data-shell="no-tab"> 主动关闭
   （如陪伴伙伴页底部是聊天输入区，见 S2 落地说明）。 */
.ds-tabbar{display:none}
@media (max-width:620px){
  :root{--tabbar-h:56px}
  body:not([data-shell="no-tab"]) .ds-tabbar{
    display:grid;grid-template-columns:repeat(5,1fr);position:fixed;left:0;right:0;bottom:0;
    z-index:var(--z-tabbar);background:var(--nav-surface,var(--surface));
    border-top:1px solid var(--border);padding-bottom:env(safe-area-inset-bottom,0px);
    box-shadow:0 -10px 30px rgba(0,0,0,.28)}
  body:not([data-shell="no-tab"]){padding-bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom,0px))}
  .ds-tabbar a,.ds-tabbar button{
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
    min-height:var(--tabbar-h);border:0;background:transparent;color:var(--muted);text-decoration:none;
    font-size:11px;cursor:pointer;transition:color var(--dur-2) var(--ease-standard)}
  .ds-tabbar a.active,.ds-tabbar button.active{color:var(--brand)}
  .ds-tabbar svg{width:20px;height:20px}
  /* 页面级悬浮元素（客服 FAB / 页内 Toast）原本贴屏幕底部，会被底部导航压住——
     实测 companion 页 #kfFab 与第 5 个 tab 重叠（FAB bottom 822 / 导航顶 787），
     属于「看得到点不到」的经典回归。统一抬到导航之上；页面若自带底栏，
     用 <body data-shell="no-tab"> 关闭底部导航（此时本规则自动失效）。 */
  body:not([data-shell="no-tab"]) .kf-fab,
  body:not([data-shell="no-tab"]) [class*="fab"]{
    bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom,0px) + 14px) !important}
  body:not([data-shell="no-tab"]) [id$="Toast"],
  body:not([data-shell="no-tab"]) .seAa-toast{
    bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom,0px) + 8px) !important}
  #dsToastHost{bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom,0px) + 14px) !important}
}


.ds-ico{display:inline-block;vertical-align:-.16em;flex:none;line-height:1}
.ds-ico-brand{color:var(--accent)}
.ds-ico-muted{color:var(--muted)}
h1 .ds-ico,h2 .ds-ico,h3 .ds-ico,.card h3 .ds-ico{vertical-align:-.14em}


.foot-note{text-align:center;color:var(--muted);font-size:13px;margin:40px auto 0;max-width:760px;line-height:1.8}
.foot{text-align:center;color:var(--muted);font-size:13px;margin:60px auto 0;max-width:1080px;line-height:1.8;padding:32px 24px 0;border-top:1px solid var(--border);display:flex;justify-content:space-between;align-items:flex-end;gap:20px;flex-wrap:wrap}
.foot-main{flex:1 1 620px;min-width:0;text-align:left}
.foot-name{font-size:14px;font-weight:700;color:var(--text)}
/* 危机热线是法务口径，必须醒目且独立成段：窄屏下它原本紧贴「支持与法律」的最后一个
   链接（margin-top:1px），看起来像那条链接的下一行。压一条细线把它划成独立区块。 */
.foot-crisis{margin-top:18px;padding-top:14px;border-top:1px solid var(--border);color:var(--muted)}
.foot-meta{margin-top:6px;font-size:12px;color:var(--muted2,#8b93a7)}
.foot-brand{flex-shrink:0;opacity:.9;align-self:flex-end}
.foot-brand img{display:block;height:58px;width:auto;border-radius:10px;border:1px solid var(--border2,var(--border));background:var(--surface,transparent)}
@media (max-width:680px){
  .foot{padding:26px 16px 0;gap:14px}
  /* 内容独占整行、logo 落到下一行右对齐：原实现让 .foot-main 与 logo 并排，
     窄屏下 flex:1 + min-width:0 会把正文压到 ~180px 宽（见 ≤480px 说明）。 */
  .foot-main{flex:1 1 100%}
  .foot-brand{margin-left:auto}
}
@media (max-width:480px){
  /* 页脚：文字块与法舟盟 logo 曾并排钉在同一行（flex-wrap:nowrap + min-width:0），
     390px 下正文只剩 ~180px 宽，四栏塌成一条又长又窄的竖列（实测高 785px）。
     现在内容占满整行，logo 单独落到下一行。 */
  .foot{align-items:flex-start;gap:14px;text-align:left}
  .foot-main{flex:1 1 100%;font-size:12px;line-height:1.62}
  .foot-brand{margin-left:auto}
  .foot-brand img{height:44px;border-radius:9px}
}


.seAc-wrap{position:fixed;inset:0;z-index:200;display:none;align-items:center;justify-content:center;background:rgba(5,8,16,.42);backdrop-filter:blur(14px) saturate(160%);padding:16px}
[data-theme="light"] .seAc-wrap{background:rgba(238,241,248,.62)}
.seAc-wrap.show{display:flex;animation:seAcFade .18s ease-out}
@keyframes seAcFade{from{opacity:0}to{opacity:1}}
/* 两个 tab 的**宽度只有一档**（旧写法给注册栏加了 `.wide` 变体，切一下左右各挪 22px）——
   宽度不变是「切 tab 不突兀」的主因，这条由结构保证。
   高度**按当前栏的内容走**（登录 2 个字段 / 注册 9 个），由 JS 做一次 260ms 的高度过渡
   （见 growCardTo）：刻意不再强制两栏等高。
   为什么要改回来（2026-09-21 晚用户反馈「布局很丑不协调」）：等高 = 卡片高度取两栏最大值，
   于是只有 2 个字段的登录栏被拉出一大块空白（实测 145px），标签与主按钮之间空得像坏掉了。
   用户的原始诉求是「切换时不要突兀」，不是「两栏必须一样高」；用动画抹掉高度差才是根因修复。
   配套改动：两栏不再共处一格参与排版（非当前栏 display:none），卡片高度 = 当前栏内容高；
   窄屏放不下时仍按整卡等比缩放（fitCard），两栏共用同一个 k（否则视觉宽度又跳，见 docstring）。 */
.seAc-card{position:relative;width:100%;max-width:436px;max-height:calc(100vh - 16px);max-height:calc(100dvh - 16px);overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;display:grid;grid-template-rows:auto auto auto auto;background:var(--surface);border:1px solid var(--border2);border-radius:20px;padding:26px 24px 24px;box-shadow:var(--shadow);backdrop-filter:blur(22px) saturate(170%);transition:height var(--dur-3) var(--ease-standard)}
.seAc-card.seAc-anim{overflow:hidden}
.seAc-close{position:absolute;top:12px;right:13px;width:32px;height:32px;display:flex;align-items:center;justify-content:center;background:none;border:none;border-radius:9px;color:var(--muted);font-size:16px;line-height:1;cursor:pointer;transition:color .15s,background .15s}
.seAc-close:hover{color:var(--text);background:var(--surface2)}
.seAc-head{grid-row:1;text-align:center;margin-bottom:16px}
.seAc-head h2{margin:0 0 6px;font-size:22px;font-weight:800;letter-spacing:.2px}
.seAc-head p{color:var(--muted);font-size:13px;margin:0;line-height:1.55}
/* 分段控件：**不再用渐变**。渐变是这个卡片里唯一的「主操作」语言，被 tab 用掉之后
   视觉上和下面的主按钮抢焦点（用户 2026-09-21 反馈「布局很丑不协调」的其中一半）。
   改成「轨道 + 实底药丸」：选中项是卡片同色的浮起块，主按钮才是全卡唯一的渐变。 */
/* 分段控件到表单的间距：**只给 5**，因为表单首个标签自带 13 的上边距 —— 合计 18，
   与「字段之间 13」同一套节奏、且是本卡里最大的一段留白（真正的分段）。
   旧写法 margin-bottom:18 与标签的 13 叠加成 **31**：登录栏在“账号”上方凭空多出一个
   31px 的洞，而密码框到主按钮只有 16、按钮到页脚只有 14 —— 用户 2026-09-22 反馈
   「账号和密码、文字和输入框在整个页面当中的位置不对。上面空太多了，下面太紧凑了」。
   为什么不用 ``label:first-child{margin-top:0}`` 这种“首元素不留上边距”的正统写法：
   注册栏的首行标签不在 ``.seAc-box`` 直接子级里，而在 ``.seAc-grid`` 的单元格里 ——
   选择器要么够不到它（两栏间距变成 5 / 18 不一致），要么连网格第 2 行的行距一起清掉
   （网格的行距全靠 label 的 margin-top，``gap:0 10px`` 的 row-gap 是 0）。 */
.seAc-tabs{grid-row:2;display:flex;gap:4px;background:var(--surface2);border-radius:12px;padding:4px;margin-bottom:5px}
.seAc-tabs button{flex:1;padding:8px;border:none;border-radius:9px;background:none;color:var(--muted);font-size:13.5px;font-weight:600;cursor:pointer;transition:background .15s,color .15s,box-shadow .15s}
.seAc-tabs button:hover{color:var(--text)}
.seAc-tabs button.on{background:var(--nav-surface);color:var(--text);font-weight:700;box-shadow:0 1px 3px rgba(0,0,0,.16)}
/* 表单字段一律**顶对齐**（旧写法 justify-content:center 会把 2 个字段的登录栏
   在「两栏同高」的长行里居中，于是标签上方凭空出现一大块空白 —— 那正是「不协调」）。
   动作区（提示 + 主按钮）用 margin-top:auto 贴到本栏底部：注册栏内容本来就占满整行，
   两栏的主按钮因此落在**同一条水平线**上。 */
.seAc-box{grid-row:3;grid-column:1;display:flex;flex-direction:column;justify-content:flex-start}
.seAc-box.off{display:none}
.seAc-box label{display:block;font-size:12.5px;font-weight:600;color:var(--muted);margin:13px 0 6px}
.seAc-box input{width:100%;padding:11px 13px;border-radius:10px;border:1px solid var(--border);background:var(--surface2);color:var(--text);font-size:14px;box-sizing:border-box;transition:border-color .15s,box-shadow .15s}
.seAc-box input::placeholder{color:var(--muted)}
.seAc-box input:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(124,156,255,.16)}
/* 动作区到最后一个字段的间距（旧 16 → 22）：字段块上移 13px 之后，这里必须比“字段之间”
   明显更宽 —— 否则整块表单看着是贴着按钮的（用户原话「下面太紧凑了」）。
   padding 而非 margin：提示条（.seAc-msg）出现时也要跟着一起下移。 */
.seAc-act{margin-top:auto;padding-top:22px}
.seAc-opt{color:var(--muted);font-weight:400;font-size:11.5px}
.seAc-sel{width:100%;padding:11px 12px;border-radius:10px;border:1px solid var(--border);background:var(--surface2);color:var(--text);font-size:14px;box-sizing:border-box;cursor:pointer;appearance:auto;transition:border-color .15s,box-shadow .15s}
.seAc-sel:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(124,156,255,.16)}
.seAc-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 10px}
.seAc-span2{grid-column:1/-1}
.seAc-birth{display:grid;grid-template-columns:repeat(4,1fr);gap:6px}
.seAc-code{display:flex;gap:8px}
.seAc-code input{flex:1;min-width:0}
.seAc-code button{flex-shrink:0;padding:0 14px;border-radius:10px;border:1px solid var(--brand);background:none;color:var(--brand);font-size:12.5px;font-weight:600;cursor:pointer;white-space:nowrap;transition:background .15s,color .15s}
.seAc-code button:hover:not(:disabled){background:var(--brand);color:#0b0f1a}
.seAc-code button:disabled{opacity:.6;cursor:not-allowed}
.seAc-msg{display:none;margin:0 0 10px;padding:8px 11px;border-radius:8px;font-size:12.5px;line-height:1.5}
.seAc-msg.err{display:block;background:rgba(255,122,138,.12);color:var(--bad);border:1px solid rgba(255,122,138,.25)}
.seAc-msg.ok{display:block;background:rgba(65,214,163,.12);color:var(--good);border:1px solid rgba(65,214,163,.25)}
.seAc-btn{width:100%;padding:12px;border:none;border-radius:10px;background:var(--grad);color:#0b0f1a;font-size:15px;font-weight:700;cursor:pointer;box-shadow:0 8px 20px rgba(124,156,255,.28);transition:transform .12s,box-shadow .15s,opacity .15s}
.seAc-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 10px 24px rgba(124,156,255,.34)}
.seAc-btn:active:not(:disabled){transform:translateY(0)}
.seAc-btn:disabled{opacity:.6;cursor:not-allowed;box-shadow:none}
/* 选填项（出生年月日时）**默认收起**：它原来在注册栏里占掉一整行 + 说明，
   把「两栏同高」的行高顶上去 —— 登录栏（就 2 个字段）于是被拉出一大块空白。
   收起来之后注册栏短了一截，两栏的留白都回到正常量级。
   用原生 <details>：键盘可达、语义正确，不用自己写 aria-expanded。 */
.seAc-more{margin-top:14px;border-top:1px solid var(--border);padding-top:12px}
.seAc-more summary{display:flex;align-items:center;gap:8px;cursor:pointer;list-style:none;font-size:12.5px;font-weight:600;color:var(--muted);padding:2px 0;transition:color .15s}
.seAc-more summary::-webkit-details-marker{display:none}
.seAc-more summary::after{content:"";width:6px;height:6px;margin-left:auto;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(45deg) translate(-2px,-2px);transition:transform .2s}
.seAc-more[open] summary::after{transform:rotate(225deg) translate(-1px,-1px)}
.seAc-more summary:hover{color:var(--text)}
.seAc-more .seAc-birth{margin-top:9px}
.seAc-foot{grid-row:4;text-align:center;margin-top:16px;font-size:12px;color:var(--muted)}
.seAc-tip{font-size:11.5px;color:var(--muted);text-align:left;margin:8px 0 0;line-height:1.5}
/* ---- 移动端：底部抽屉、单列、加大触控区；输入 16px 防 iOS 聚焦缩放 ---- */
@media (max-width:600px){
  .seAc-wrap{padding:0;align-items:flex-end}
  .seAc-card{max-width:100%;max-height:92vh;max-height:92dvh;border-radius:20px 20px 0 0;padding:20px 16px calc(22px + env(safe-area-inset-bottom,0px))}
  .seAc-head{margin-bottom:12px}
  .seAc-head h2{font-size:19px}
  .seAc-head p{font-size:12.5px}
  /* 与桌面同一套算术：5 + 首个标签自带的 11 = 16（窄屏的字段节奏更紧） */
  .seAc-tabs{padding:5px;margin-bottom:5px}
  .seAc-tabs button{min-height:var(--tap,44px);font-size:14px}
  .seAc-grid{grid-template-columns:1fr 1fr;gap:0 8px}
  .seAc-birth{grid-template-columns:1fr 1fr;gap:8px}
  .seAc-box label{margin:11px 0 6px}
  .seAc-box input,.seAc-sel,.seAc-code input{font-size:16px;padding:11px 12px}
  .seAc-code button{padding:0 12px;font-size:13px}
  .seAc-act{padding-top:18px}
  .seAc-btn{padding:13px;font-size:15.5px}
  .seAc-more{margin-top:12px;padding-top:11px}
  .seAc-more summary{padding:8px 0}
  .seAc-close{top:9px;right:9px;width:34px;height:34px;font-size:17px}
}
