/* ============================================================================
   智刊云 · 智能电子报刊平台 —— 设计系统
   风格方向：现代编辑部（Editorial Modern）
   暖纸质底 · 墨黑文字 · 报头红点缀 · 衬线标题
   ========================================================================== */

/* ---------- 设计令牌 ---------- */
:root{
  /* 底色与表面 */
  --paper:#F6F5F2;
  --paper-2:#EFEDE8;
  --surface:#FFFFFF;
  --surface-2:#FAF9F7;
  --surface-3:#F2F0EC;

  /* 文字 */
  --ink:#15171A;
  --ink-2:#3D434C;
  --ink-3:#6B7280;
  --ink-4:#9CA3AF;
  --ink-5:#C4C8CE;

  /* 描边 */
  --line:#E6E3DC;
  --line-2:#EFEDE8;
  --line-strong:#D6D2C9;

  /* 主色：墨黑（主操作） */
  --brand:#15171A;
  --brand-2:#2A2E35;

  /* 强调色：报头红 */
  --accent:#C8102E;
  --accent-2:#E23B52;
  --accent-soft:#FDECEE;
  --accent-line:#F5C9CF;

  /* 辅助色：政务蓝 / 青色 / 成功 / 警示 */
  --blue:#1B3A8C;
  --blue-2:#2F5BD0;
  --blue-soft:#EDF2FE;
  --teal:#0E7490;
  --teal-soft:#E6F6FA;
  --green:#0F7B4F;
  --green-soft:#E8F6EF;
  --amber:#A15C07;
  --amber-soft:#FDF3E3;
  --violet:#6D28D9;
  --violet-soft:#F3EEFE;

  /* 圆角
     ★ 全部乘 --rs（圆角尺度）：每套视觉风格有自己的 --rs，
       于是「切风格」不只是换色，连圆角语言（锐利 / 圆润）也跟着变。
       var() 在计算值阶段解析，且 --rs 在同为 html 元素的风格块里覆盖，
       所以 :root 这里写 calc 就能被各风格复用，无需逐个风格重写圆角。 */
  --rs:1;
  --r-xs:calc(6px * var(--rs)); --r-sm:calc(8px * var(--rs)); --r:calc(10px * var(--rs));
  --r-md:calc(12px * var(--rs)); --r-lg:calc(16px * var(--rs)); --r-xl:calc(22px * var(--rs));

  /* 阴影（带暖色调） */
  --sh-1:0 1px 2px rgba(28,25,20,.05), 0 1px 1px rgba(28,25,20,.04);
  --sh-2:0 2px 6px rgba(28,25,20,.05), 0 1px 2px rgba(28,25,20,.04);
  --sh-3:0 12px 28px -14px rgba(28,25,20,.18), 0 3px 8px -4px rgba(28,25,20,.07);
  --sh-4:0 24px 56px -22px rgba(28,25,20,.26), 0 6px 16px -8px rgba(28,25,20,.1);
  --sh-pop:0 30px 70px -30px rgba(15,17,20,.4);

  /* 尺寸 */
  --side-w:236px;
  --top-h:60px;
  --maxw:1320px;

  /* ★ 外壳浮层（侧栏 / 顶栏）：两张「浮在背景上的圆角卡片」。
     - 侧栏三面留边距（左 / 上 / 下），顶栏顶部贴齐视口但底边圆角带阴影
     - .main 的 margin-left 必须 = 侧栏左距 + 侧栏宽 + 右距，否则内容被压住
     - 改这里的数值时，820px 断点里的抽屉位移要同步（见 @media(max-width:820px)） */
  --shell-gap:10px;
  --r-shell:18px;
  /* ★ v2.8.0：侧栏顶边贴齐视口后，投影只能从「左 + 下」两个方向立起来（顶部不需要投影）。
     用三档叠影做立体感：远影负责体积、中影负责「离开背景」、近影勾出边缘。
     只给一个大而虚的影会让卡片像贴纸；三档叠加才有厚度（用户要求「底部增加阴影增加立体效果」）。 */
  --sh-shell:0 26px 48px -22px rgba(28,25,20,.42),
             0 12px 24px -12px rgba(28,25,20,.20),
             0 2px 6px -2px rgba(28,25,20,.10);
  --sh-top:0 14px 30px -22px rgba(28,25,20,.42);
  /* ★ v2.8.1：大幅面卡片（大厅 Banner / 详情头图）专用立体投影。
     问题根因：.hero 原来复用 --sh-3 = `0 12px 28px -14px` —— **水平偏移为 0**
     且 spread -14px 把横向范围整段吃掉。probe-v281 实测：
       底部（+0px）L 0.8729 vs 远场 0.9596 → 亮度差 0.087，往下 25px 才收干净；
       右侧（+0px）只有 0.9172，13px 就归零 → 亮度差仅 0.033。
     也就是「影只往下掉、右边几乎没有」= 用户说的「右下底部阴影不明显，立体效果不明显」。
     对策：三档叠影 + **正向 x 偏移**，做出「光从左上方来」的方向感：
       远影 0 30px 58px -26px → 底部延伸 33px，负责体积
       中影 5px 16px 34px -16px → 右侧延伸 6px，负责「离开背景」
       近影 6px  8px 22px  -8px → 右侧延伸 9px，勾出右下轮廓
     只在 .hero 上显式使用，不改 --sh-3 —— 小卡片套这么重的影会显脏。 */
  --sh-hero:0 30px 58px -26px rgba(28,25,20,.44),
            5px 16px 34px -16px rgba(28,25,20,.26),
            6px 8px 22px -8px rgba(28,25,20,.18);
  /* 内容区横向内边距；.top 的右侧留白必须跟它一致，否则顶栏与内容右边不齐 */
  --body-pad:24px;

  /* 字体 */
  --sans:"PingFang SC","HarmonyOS Sans SC","Microsoft YaHei","Hiragino Sans GB",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --serif:"Songti SC","Noto Serif SC","Source Han Serif SC","STSong","SimSun",Georgia,"Times New Roman",serif;
  --mono:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;

  --ease:cubic-bezier(.22,.61,.36,1);
  color-scheme:light;
}

/* ==========================================================================
   深色主题（编辑部夜读）
   仅覆盖 token，再对少数「深底 + 硬编码白字」的交互态做精修，
   保证任意层级都有足够对比度。
   ========================================================================== */
[data-theme="dark"]{
  color-scheme:dark;

  /* 底色与表面 */
  --paper:#121418;
  --paper-2:#0E1014;
  --surface:#191C21;
  --surface-2:#1F232A;
  --surface-3:#272C34;

  /* 文字 */
  --ink:#ECE9E4;
  --ink-2:#C7C4BE;
  --ink-3:#9CA1A9;
  --ink-4:#787D86;
  --ink-5:#565C65;

  /* 描边 */
  --line:#2A2F37;
  --line-2:#22262D;
  --line-strong:#3B424C;

  /* 主色：在深色下略微抬起，保证白字仍可读 */
  --brand:#2B323C;
  --brand-2:#39414D;

  /* 强调色：报头红（深色下提亮） */
  --accent:#F2405C;
  --accent-2:#FF6A82;
  --accent-soft:rgba(242,64,92,.16);
  --accent-line:rgba(242,64,92,.34);

  /* 辅助色 */
  --blue:#8AA7FF;
  --blue-2:#6E93F5;
  --blue-soft:rgba(80,120,240,.16);
  --teal:#43CBE2;
  --teal-soft:rgba(14,140,165,.2);
  --green:#3FD193;
  --green-soft:rgba(24,140,92,.2);
  --amber:#F2B75E;
  --amber-soft:rgba(170,105,20,.22);
  --violet:#B795FB;
  --violet-soft:rgba(115,60,220,.22);

  /* 阴影（深色下更沉） */
  --sh-1:0 1px 2px rgba(0,0,0,.45);
  --sh-2:0 2px 6px rgba(0,0,0,.45);
  --sh-3:0 14px 30px -16px rgba(0,0,0,.7), 0 2px 6px -3px rgba(0,0,0,.4);
  --sh-4:0 26px 60px -24px rgba(0,0,0,.78), 0 6px 16px -8px rgba(0,0,0,.5);
  --sh-pop:0 30px 70px -30px rgba(0,0,0,.85);
  /* 外壳浮层阴影：深色底上必须加深，否则圆角卡片与背景糊在一起 */
  --sh-shell:0 28px 52px -20px rgba(0,0,0,.80),
             0 12px 24px -12px rgba(0,0,0,.58),
             0 2px 6px -2px rgba(0,0,0,.46);
  --sh-top:0 14px 30px -20px rgba(0,0,0,.72);
  /* 深色下同一套几何，只把不透明度往上推：暗底吃光，浅色档的影几乎看不见 */
  --sh-hero:0 30px 58px -26px rgba(0,0,0,.74),
            5px 16px 34px -16px rgba(0,0,0,.54),
            6px 8px 22px -8px rgba(0,0,0,.40);
}

/* —— 深色下的交互态精修：让「激活」用红色语汇表达，而非消失的墨黑 —— */
[data-theme="dark"] .btn--primary{
  background:var(--accent);border-color:var(--accent);color:#fff;
  box-shadow:0 6px 16px -10px rgba(242,64,92,.85);
}
[data-theme="dark"] .btn--primary:hover{background:var(--accent-2);border-color:var(--accent-2);}
[data-theme="dark"] .btn--ghost:hover{background:var(--surface-3);}
[data-theme="dark"] .nav__item.is-on{
  background:linear-gradient(90deg,rgba(242,64,92,.24),rgba(242,64,92,.05));
  color:#fff;box-shadow:none;
}
[data-theme="dark"] .cat.is-on,
[data-theme="dark"] .tpl-pager .pg.is-on{
  background:var(--accent);border-color:var(--accent);color:#fff;
}
[data-theme="dark"] .pow button.is-on,
[data-theme="dark"] .seg__i.is-on{
  background:rgba(242,64,92,.2);border-color:var(--accent);color:#fff;
}
[data-theme="dark"] .tile::after{background:var(--accent);}
[data-theme="dark"] .bar__fill{background:var(--accent);}
[data-theme="dark"] .switch input:checked + .tr{background:var(--accent);}
[data-theme="dark"] .chk input{accent-color:var(--accent);}
[data-theme="dark"] .inp:focus,
[data-theme="dark"] .sel:focus,
[data-theme="dark"] .ta:focus{
  border-color:var(--accent);box-shadow:0 0 0 3px rgba(242,64,92,.16);
}
[data-theme="dark"] .notif__i.is-unread:hover{background:rgba(242,64,92,.22);}
[data-theme="dark"] .np__ov .btn,[data-theme="dark"] .tpl__ov .btn{
  background:rgba(20,22,26,.9);color:#fff;border-color:rgba(255,255,255,.16);
  box-shadow:0 10px 22px -10px rgba(0,0,0,.72), 0 2px 6px -2px rgba(0,0,0,.5);
}
[data-theme="dark"] .np__ov .btn:hover,[data-theme="dark"] .tpl__ov .btn:hover{background:var(--accent);color:#fff;}
[data-theme="dark"] .note--info{border-color:rgba(110,147,245,.36);}
[data-theme="dark"] .note--warn{border-color:rgba(242,183,94,.36);}
[data-theme="dark"] .note--ok{border-color:rgba(63,209,147,.36);}
[data-theme="dark"] .note--err{border-color:var(--accent-line);}
[data-theme="dark"] .dl.chg{border-color:rgba(242,183,94,.36);}
[data-theme="dark"] ::selection{background:rgba(242,64,92,.3);color:#fff;}
[data-theme="dark"] ::-webkit-scrollbar-thumb{background:#3A414B;}
[data-theme="dark"] ::-webkit-scrollbar-thumb:hover{background:#4B535F;}

/* —— 打印/设计画布：始终是纸 —— 深色下也不翻转 —— */
[data-theme="dark"] .canvas,
[data-theme="dark"] .print-only,
[data-theme="dark"] .tpl__stage,
[data-theme="dark"] .tpl-preview{background:#fff;color:#15171A;}

/* —— 编辑器与阅读器本身就是深色 CLI 风格，深色主题下略微抬升底色 —— */
[data-theme="dark"] .ed__top{background:#171A1F;border-bottom-color:#2A2F37;}
[data-theme="dark"] .ed__left,
[data-theme="dark"] .ed__right{background:#171A1F;border-color:#2A2F37;}
[data-theme="dark"] .panel__h{border-bottom-color:#2A2F37;}
[data-theme="dark"] .pgthumb{background:#22262D;border-color:#2A2F37;}
[data-theme="dark"] .rd__side{background:#1A1D22;color:var(--ink-2);}
[data-theme="dark"] .rd-inp{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.12);color:#fff;}

/* ---------- 基础重置 ---------- */
*,*::before,*::after{box-sizing:border-box;}
html,body{height:100%;}
body{
  margin:0;font-family:var(--sans);color:var(--ink);background:var(--paper);
  font-size:14px;line-height:1.6;-webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
}
a{color:inherit;text-decoration:none;}
button{font-family:inherit;font-size:inherit;cursor:pointer;border:none;background:none;color:inherit;}
input,select,textarea{font-family:inherit;font-size:14px;color:inherit;}
img{max-width:100%;display:block;}
h1,h2,h3,h4,h5,h6{margin:0;font-weight:700;line-height:1.3;}
p{margin:0;}
ul,ol{margin:0;padding:0;list-style:none;}
table{border-collapse:collapse;width:100%;}
[hidden]{display:none !important;}

::selection{background:var(--accent-soft);color:var(--accent);}
::-webkit-scrollbar{width:10px;height:10px;}
::-webkit-scrollbar-track{background:transparent;}
::-webkit-scrollbar-thumb{background:#D9D5CD;border-radius:8px;border:3px solid transparent;background-clip:content-box;}
::-webkit-scrollbar-thumb:hover{background:#C0BBB0;background-clip:content-box;}

.serif{font-family:var(--serif);}
.mono{font-family:var(--mono);}
.muted{color:var(--ink-3);}
.dim{color:var(--ink-4);}
.nowrap{white-space:nowrap;}
.ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.center{text-align:center;}
.grow{flex:1;min-width:0;}
.row{display:flex;align-items:center;gap:10px;}
.row--between{display:flex;align-items:center;justify-content:space-between;gap:12px;}
.col{display:flex;flex-direction:column;gap:10px;}
.wrap-f{flex-wrap:wrap;}
.mt-0{margin-top:0 !important;} .mt-8{margin-top:8px;} .mt-12{margin-top:12px;}
.mt-16{margin-top:16px;} .mt-24{margin-top:24px;} .mt-32{margin-top:32px;}
.mb-8{margin-bottom:8px;} .mb-12{margin-bottom:12px;} .mb-16{margin-bottom:16px;} .mb-24{margin-bottom:24px;}
.fs-12{font-size:12px;} .fs-13{font-size:13px;} .fs-15{font-size:15px;} .fs-16{font-size:16px;}
.bold{font-weight:700;} .semibold{font-weight:600;}

/* ============================================================================
   按钮
   ========================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  padding:9px 15px;border-radius:var(--r);border:1px solid var(--line);
  background:var(--surface);color:var(--ink);font-size:13.5px;font-weight:600;
  white-space:nowrap;transition:background .16s var(--ease),border-color .16s var(--ease),
    color .16s var(--ease),transform .12s var(--ease),box-shadow .16s var(--ease);
  box-shadow:var(--sh-1);
}
.btn:hover{background:var(--surface-2);border-color:var(--line-strong);}
.btn:active{transform:translateY(.5px);}
.btn:disabled,.btn.is-disabled{opacity:.45;cursor:not-allowed;transform:none;box-shadow:none;}
.btn .ic{font-size:15px;line-height:1;}

.btn--primary{background:var(--brand);border-color:var(--brand);color:#fff;box-shadow:0 6px 16px -10px rgba(21,23,26,.8);}
.btn--primary:hover{background:var(--brand-2);border-color:var(--brand-2);}
.btn--accent{background:var(--accent);border-color:var(--accent);color:#fff;box-shadow:0 6px 16px -10px rgba(200,16,46,.85);}
.btn--accent:hover{background:var(--accent-2);border-color:var(--accent-2);}
.btn--ghost{background:transparent;border-color:transparent;box-shadow:none;color:var(--ink-2);}
.btn--ghost:hover{background:var(--surface-3);}
.btn--outline{background:transparent;}
.btn--soft{background:var(--surface-3);border-color:transparent;box-shadow:none;}
.btn--soft:hover{background:var(--paper-2);}
.btn--danger{background:var(--surface);border-color:var(--accent-line);color:var(--accent);}
.btn--danger:hover{background:var(--accent-soft);border-color:var(--accent);}
.btn--ok{background:var(--green-soft);border-color:transparent;color:var(--green);}
.btn--ok:hover{background:#DEF0E7;}

.btn--xs{padding:5px 9px;font-size:12px;border-radius:var(--r-sm);gap:4px;}
.btn--sm{padding:7px 12px;font-size:13px;border-radius:var(--r-sm);}
.btn--lg{padding:12px 22px;font-size:15px;border-radius:var(--r-md);}
.btn--block{width:100%;}
.btn--icon{padding:8px;width:36px;height:36px;border-radius:var(--r-sm);}
.btn--icon.btn--xs{width:28px;height:28px;padding:5px;}

/* ============================================================================
   表单
   ========================================================================== */
.inp,.sel,.ta{
  width:100%;padding:9px 12px;border:1px solid var(--line);border-radius:var(--r);
  background:var(--surface);color:var(--ink);transition:.16s var(--ease);
}
.inp::placeholder,.ta::placeholder{color:var(--ink-4);}
.inp:hover,.sel:hover,.ta:hover{border-color:var(--line-strong);}
.inp:focus,.sel:focus,.ta:focus{outline:none;border-color:var(--brand);box-shadow:0 0 0 3px rgba(21,23,26,.07);}
.ta{resize:vertical;min-height:78px;line-height:1.7;}
.sel{
  appearance:none;padding-right:32px;cursor:pointer;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path d='M2.5 4.5L6 8l3.5-3.5' fill='none' stroke='%236B7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  background-repeat:no-repeat;background-position:right 11px center;
}
.inp--search{padding-left:34px;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 14 14'><circle cx='6' cy='6' r='4.2' fill='none' stroke='%239CA3AF' stroke-width='1.5'/><path d='M9.2 9.2L12.5 12.5' stroke='%239CA3AF' stroke-width='1.5' stroke-linecap='round'/></svg>");
  background-repeat:no-repeat;background-position:12px center;}
.inp--sm{padding:7px 10px;font-size:13px;}
.inp--num{width:100%;text-align:left;font-variant-numeric:tabular-nums;}

.field{margin-bottom:14px;}
.field > label,.lb{display:block;font-size:12.5px;font-weight:600;color:var(--ink-2);margin-bottom:6px;}
.field .hint{font-size:11.5px;color:var(--ink-4);margin-top:5px;line-height:1.6;}

/* 开关 */
.switch{position:relative;display:inline-block;width:38px;height:21px;flex-shrink:0;cursor:pointer;}
.switch input{position:absolute;opacity:0;width:0;height:0;}
.switch .tr{position:absolute;inset:0;background:var(--line-strong);border-radius:99px;transition:.2s var(--ease);}
.switch .tr::after{content:"";position:absolute;left:2px;top:2px;width:17px;height:17px;background:#fff;border-radius:50%;transition:.2s var(--ease);box-shadow:0 1px 3px rgba(0,0,0,.2);}
.switch input:checked + .tr{background:var(--brand);}
.switch input:checked + .tr::after{transform:translateX(17px);}
.switch-row{display:flex;align-items:center;gap:10px;font-size:13.5px;}

.chk{display:inline-flex;align-items:center;gap:7px;font-size:13.5px;cursor:pointer;user-select:none;}
.chk input{width:15px;height:15px;accent-color:var(--brand);cursor:pointer;}

/* 分段控件 */
.seg{display:inline-flex;background:var(--surface-3);border-radius:var(--r);padding:3px;gap:2px;}
.seg__i{padding:6px 13px;border-radius:7px;font-size:13px;font-weight:600;color:var(--ink-3);transition:.16s var(--ease);white-space:nowrap;}
.seg__i:hover{color:var(--ink);}
.seg__i.is-on{background:var(--surface);color:var(--ink);box-shadow:var(--sh-1);}

/* ============================================================================
   标签 / 徽章
   ========================================================================== */
.chip{
  display:inline-flex;align-items:center;gap:5px;padding:2px 9px;border-radius:99px;
  font-size:11.5px;font-weight:600;line-height:1.7;white-space:nowrap;
  background:var(--surface-3);color:var(--ink-3);
}
.chip--draft{background:var(--amber-soft);color:var(--amber);}
.chip--reviewing{background:var(--blue-soft);color:var(--blue-2);}
.chip--published{background:var(--green-soft);color:var(--green);}
.chip--archived{background:var(--surface-3);color:var(--ink-3);}
.chip--accent{background:var(--accent-soft);color:var(--accent);}
.chip--violet{background:var(--violet-soft);color:var(--violet);}
.chip--teal{background:var(--teal-soft);color:var(--teal);}
.chip--on{background:var(--green-soft);color:var(--green);}
.chip--off{background:var(--surface-3);color:var(--ink-4);}
.chip--line{background:transparent;border:1px solid var(--line);color:var(--ink-3);}
.chip .d{width:5px;height:5px;border-radius:50%;background:currentColor;}

.tag{display:inline-block;padding:1px 7px;border-radius:5px;font-size:11px;font-weight:600;background:var(--surface-3);color:var(--ink-3);}
.tag--accent{background:var(--accent-soft);color:var(--accent);}

kbd{font-family:var(--mono);font-size:11px;padding:1.5px 5px;border-radius:5px;background:var(--surface-3);border:1px solid var(--line);color:var(--ink-2);}

/* ============================================================================
   登录 / 注册
   ========================================================================== */
.auth{min-height:100vh;display:grid;grid-template-columns:1.05fr .95fr;background:var(--surface);}
.auth__brand{
  position:relative;overflow:hidden;padding:56px 60px;display:flex;flex-direction:column;
  background:linear-gradient(158deg,#1A1D22 0%,#0E1013 55%,#15171A 100%);color:#fff;
}
.auth__brand::before{
  content:"";position:absolute;width:640px;height:640px;right:-240px;top:-220px;border-radius:50%;
  background:radial-gradient(circle,rgba(200,16,46,.28),transparent 66%);
}
.auth__brand::after{
  content:"";position:absolute;width:520px;height:520px;left:-200px;bottom:-240px;border-radius:50%;
  background:radial-gradient(circle,rgba(47,91,208,.2),transparent 68%);
}
.auth__brand > *{position:relative;z-index:2;}
.auth__logo{display:flex;align-items:center;gap:12px;font-size:19px;font-weight:800;letter-spacing:.3px;}
.auth__logo .mk{
  width:40px;height:40px;border-radius:11px;display:grid;place-items:center;
  background:var(--accent);color:#fff;font-family:var(--serif);font-size:21px;font-weight:700;
  box-shadow:0 10px 24px -10px rgba(200,16,46,.9);
}
.auth__hero{margin-top:auto;}
.auth__hero h1{
  font-family:var(--serif);font-size:44px;line-height:1.28;letter-spacing:-.5px;
  font-weight:700;margin-bottom:18px;
}
.auth__hero h1 em{font-style:normal;color:#F2A0AE;}
.auth__hero p{color:rgba(255,255,255,.62);font-size:14.5px;line-height:2;max-width:440px;}
.auth__feats{display:grid;grid-template-columns:1fr 1fr;gap:14px 26px;margin-top:38px;}
.auth__feat{display:flex;gap:10px;align-items:flex-start;font-size:13px;color:rgba(255,255,255,.78);}
.auth__feat .ic{
  width:26px;height:26px;flex-shrink:0;border-radius:8px;display:grid;place-items:center;
  background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.1);font-size:13px;
}
.auth__rule{width:52px;height:3px;background:var(--accent);border-radius:2px;margin:26px 0 22px;}
.auth__meta{margin-top:auto;padding-top:34px;font-size:12px;color:rgba(255,255,255,.34);border-top:1px solid rgba(255,255,255,.08);}

.auth__panel{display:grid;place-items:center;padding:40px 28px;background:var(--paper);}
.auth__card{width:min(400px,100%);}
.auth__card h2{font-size:24px;font-weight:800;margin-bottom:6px;letter-spacing:-.3px;}
.auth__card .sub{color:var(--ink-3);font-size:13.5px;margin-bottom:26px;}
.auth__alt{margin-top:18px;text-align:center;font-size:13.5px;color:var(--ink-3);}
.auth__alt a{color:var(--accent);font-weight:600;border-bottom:1px solid var(--accent-line);}
.demo-box{
  margin-top:22px;border:1px dashed var(--line-strong);border-radius:var(--r-md);
  padding:13px 15px;background:var(--surface);font-size:12.5px;line-height:2;color:var(--ink-3);
}
.demo-box b{color:var(--ink);display:block;margin-bottom:4px;font-size:12px;letter-spacing:.4px;text-transform:uppercase;}
.demo-box .acct{display:flex;justify-content:space-between;gap:10px;cursor:pointer;}
.demo-box .acct code{font-family:var(--mono);font-size:11.5px;color:var(--blue-2);cursor:pointer;}
.demo-box .acct code:hover{text-decoration:underline;}
@media(max-width:980px){.auth{grid-template-columns:1fr;} .auth__brand{display:none;}}

/* ============================================================================
   应用骨架
   ========================================================================== */
.shell{display:flex;min-height:100vh;}

.side{
  width:var(--side-w);flex-shrink:0;
  /* ★ 侧栏 = 从视口顶部「垂下来」的卡片：顶边贴齐视口（top:0）、上方两角为直角，
     下方两角保留圆角 —— 用户明确要求「顶部不要圆角、吸附到顶部」。
     只在左/下留边距，顶部不再留 --shell-gap。
     overflow:hidden 是必需的：否则 .side__foot 里的按钮背景会溢出圆角，
     左下 / 右下角变成直角（折叠成图标轨时尤其明显）。 */
  position:fixed;top:0;left:var(--shell-gap);bottom:var(--shell-gap);right:auto;z-index:40;
  background:var(--surface);border:1px solid var(--line);border-top:0;
  border-radius:0 0 var(--r-shell) var(--r-shell);
  /* 阴影往「下 + 外侧」偏，底部才立得起来（顶部贴边不需要投影） */
  box-shadow:var(--sh-shell);overflow:hidden;
  display:flex;flex-direction:column;padding:16px 12px 14px;
}
.side__brand{display:flex;align-items:center;gap:10px;padding:4px 8px 16px;font-size:16.5px;font-weight:800;letter-spacing:-.2px;}
.side__brand .mk{
  width:32px;height:32px;border-radius:9px;display:grid;place-items:center;
  background:var(--accent);color:#fff;font-family:var(--serif);font-size:17px;font-weight:700;
  box-shadow:0 8px 18px -10px rgba(200,16,46,.9);flex-shrink:0;
}
.side__brand small{display:block;font-size:10px;font-weight:600;color:var(--ink-4);letter-spacing:.6px;margin-top:-2px;}
.side__scroll{flex:1;overflow-y:auto;overflow-x:hidden;margin:0 -4px;padding:0 4px;}
.side__label{font-size:10.5px;font-weight:700;color:var(--ink-4);letter-spacing:.12em;padding:14px 10px 6px;text-transform:uppercase;}
.nav__item{
  display:flex;align-items:center;gap:10px;padding:8.5px 10px;border-radius:var(--r);
  font-size:13.5px;font-weight:500;color:var(--ink-2);margin-bottom:1px;
  transition:background .14s var(--ease),color .14s var(--ease),transform .1s var(--ease);
  cursor:pointer;-webkit-user-select:none;user-select:none;
  text-decoration:none;outline:none;
}
.nav__item:hover{background:var(--surface-3);color:var(--ink);}
.nav__item:active{transform:translateY(.5px);}
.nav__item:focus-visible{background:var(--surface-3);box-shadow:inset 0 0 0 2px var(--brand);}
.nav__item.is-on{background:var(--brand);color:#fff;font-weight:600;box-shadow:0 6px 14px -9px rgba(21,23,26,.9);}
.nav__item.is-on .nav__ic{opacity:1;}
.nav__ic{width:17px;text-align:center;font-size:14.5px;line-height:1;opacity:.78;flex-shrink:0;}
.nav__badge{
  margin-left:auto;min-width:17px;height:17px;padding:0 5px;border-radius:9px;
  background:var(--accent);color:#fff;font-size:10.5px;font-weight:700;
  display:grid;place-items:center;line-height:1;
}
.side__foot{padding-top:12px;border-top:1px solid var(--line-2);margin-top:8px;}
/* ★ 底部两个操作（新建报刊 / 快捷键帮助）：圆角 + 阴影，做成「可按的卡片」。
   折叠成图标轨时宽度只剩 42px，圆角要跟着收小，否则会看起来像个胶囊。 */
.side__foot .sidebtn{
  border-radius:var(--r-md);box-shadow:var(--sh-3);
  transition:box-shadow .2s var(--ease),transform .14s var(--ease),background .2s var(--ease);
}
.side__foot .sidebtn:active{transform:translateY(1px);}
.side__foot #newBtn.sidebtn{
  box-shadow:0 12px 24px -14px color-mix(in srgb, var(--accent) 78%, transparent),
             inset 0 1px 0 rgba(255,255,255,.24);
}
.side__foot #helpBtn.sidebtn{background:var(--surface-2);border:1px solid var(--line);}
.side__foot #helpBtn.sidebtn:hover{background:var(--surface-3);}
html[data-nav="mini"] .side__foot .sidebtn{border-radius:var(--r);}
.me-card{display:flex;align-items:center;gap:10px;padding:8px;border-radius:var(--r-md);transition:.16s var(--ease);cursor:pointer;}
.me-card:hover{background:var(--surface-3);}
.av{
  width:32px;height:32px;border-radius:50%;flex-shrink:0;display:grid;place-items:center;
  background:var(--brand);color:#fff;font-size:13px;font-weight:700;letter-spacing:.5px;
}
.av--a{background:var(--accent);} .av--b{background:var(--blue-2);} .av--t{background:var(--teal);}
.av--v{background:var(--violet);} .av--g{background:var(--green);}
.av--lg{width:40px;height:40px;font-size:15px;}
.av--xl{width:52px;height:52px;font-size:19px;}
.me-card .nm{font-size:13.5px;font-weight:700;line-height:1.3;}
.me-card .rl{font-size:11px;color:var(--ink-4);}

/* 内容区左侧让位 = 侧栏左距 + 侧栏宽 + 侧栏右距（三者缺一内容就会被侧栏压住） */
.main{flex:1;margin-left:calc(var(--side-w) + var(--shell-gap) * 2);min-width:0;display:flex;flex-direction:column;}

.top{
  height:var(--top-h);flex-shrink:0;position:sticky;top:0;z-index:30;
  display:flex;align-items:center;gap:14px;padding:0 22px;
  /* 右侧留白与 .body 的 padding-right 对齐，顶栏右边缘才与内容右边缘齐平 */
  margin-right:var(--body-pad);
  background:rgba(246,245,242,.82);backdrop-filter:blur(14px) saturate(1.5);
  /* ★ 顶部贴齐视口（top:0），只把底边做成圆角 + 阴影 → 立体浮层感。
     只用 border-bottom 时圆角两端的边框线会断开，故写满三边、去掉 border-top。 */
  border:1px solid var(--line);border-top:0;
  border-radius:0 0 var(--r-shell) var(--r-shell);
  box-shadow:var(--sh-top);
}
.top__t{font-size:15.5px;font-weight:700;letter-spacing:-.2px;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;}
/* ★ 顶栏窄屏缺陷的根治：**标题永不收缩，搜索框承担全部收缩**
   ---------------------------------------------------------------------------
   ■ 原写法 `.top__tbox{flex:0 0 auto}` + `.tsearch{min-width:min(190px,26vw)}`：
     两者都不可再让位时，顶栏无路可退 → 撑破容器 → 整页横向滚动。
     该缺陷与**页面标题长度耦合**，所以极难复现：
       #/     标题「报刊大厅」      top__tbox=61px → 900px 视口正常
       #/mp   标题「微信公众号接入」 top__tbox=76px → 900px 视口溢出 12px
     多出的 15px 正是最后一根稻草（360px 溢出 11px、375px 溢出 2px 同理）。
   ■ 但**不能简单改成可收缩**：`.top__tbox` 一可收缩，flex 的「按比例收缩」会在
     宽松视口下也把它压小（实测 900px 时被压到 18px，标题只剩「报」一个字 + 省略号），
     观感比原来的溢出更糟。**根因是 flex 收缩量按 flex-shrink × 基准宽度分配**，
     跟「谁更该让位」无关。
   ■ 正确解法：显式指定收缩优先级 ——
       .top__tbox  flex-shrink:0    （标题是识别当前页的关键信息，永不压缩）
       .tsearch    flex-shrink:999  （搜索框优先被吃掉，且它在极窄屏会直接收起）
     这样任何视口下标题都完整，压力全部由搜索框吸收；搜索框缩到 min-width
     仍不够时，由下面的 400px 断点让它整体隐藏。
   ■ 保留 nowrap + 省略号作为最后兜底（正常不会触发）。
   --------------------------------------------------------------------------- */
.top__tbox{flex:0 0 auto;min-width:0;max-width:100%;overflow:hidden;}
/* 搜索框：可无限让步（先于标题被压缩） */
.tsearch{flex-shrink:999;}
.top__crumb{font-size:11.5px;color:var(--ink-4);margin-top:-1px;}
.top__search{width:min(320px,34vw);}
.top__sp{flex:1;}

/* ============================================================================
   多租户：顶栏「当前机构」徽标
   ---------------------------------------------------------------------------
   ★ 让步顺序：标题(.top__tbox) > 机构徽标(.top__tenant) > 搜索框(.tsearch)。
     徽标排在 .top__tbox 之后、.top__sp 之前，因此它参与收缩而非溢出；
     窄屏（<=1180px）直接隐藏，避免挤压本已紧张的顶栏 —— 机构信息在
     个人中心里仍可看到，不会丢失。
   ========================================================================== */
.top__tenant{flex:0 1 auto;min-width:0;display:flex;align-items:center;}
.top__tenant .chip{max-width:190px;overflow:hidden;text-overflow:ellipsis;display:inline-block;}
.top__tenant .btn--sm{padding:5px 10px;font-size:12.5px;line-height:1.4;}
@media(max-width:1180px){.top__tenant{display:none;}}

.bell{position:relative;}
.bell__btn{position:relative;}
.bell__dot{
  position:absolute;top:-3px;right:-3px;min-width:16px;height:16px;padding:0 4px;
  border-radius:9px;background:var(--accent);color:#fff;font-size:10px;font-weight:700;
  display:grid;place-items:center;line-height:1;border:2px solid var(--paper);
}

.dropdown{
  position:absolute;right:0;top:calc(100% + 8px);min-width:200px;z-index:60;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  box-shadow:var(--sh-4);padding:6px;opacity:0;visibility:hidden;transform:translateY(-4px);
  transition:.16s var(--ease);
}
.dropdown.is-open{opacity:1;visibility:visible;transform:translateY(0);}
.dd__item{display:flex;align-items:center;gap:9px;padding:8px 10px;border-radius:var(--r-sm);font-size:13.5px;color:var(--ink-2);cursor:pointer;}
.dd__item:hover{background:var(--surface-3);color:var(--ink);}
.dd__item .ic{font-size:14px;width:16px;text-align:center;opacity:.8;}
.dd__sep{height:1px;background:var(--line-2);margin:5px 4px;}
.dd__head{padding:8px 10px 4px;font-size:10.5px;font-weight:700;letter-spacing:.1em;color:var(--ink-4);text-transform:uppercase;}

/* 通知面板 */
.notif{
  position:absolute;right:0;top:calc(100% + 8px);width:352px;max-height:440px;overflow-y:auto;z-index:60;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--sh-4);opacity:0;visibility:hidden;transform:translateY(-4px);transition:.16s var(--ease);
}
.notif.is-open{opacity:1;visibility:visible;transform:translateY(0);}
.notif__h{display:flex;align-items:center;justify-content:space-between;padding:13px 16px;border-bottom:1px solid var(--line-2);position:sticky;top:0;background:var(--surface);z-index:2;}
.notif__h b{font-size:14px;}
.notif__i{padding:12px 16px;border-bottom:1px solid var(--line-2);cursor:pointer;transition:.14s;display:flex;gap:11px;}
.notif__i:hover{background:var(--surface-2);}
.notif__i.is-unread{background:var(--accent-soft);}
.notif__i.is-unread:hover{background:#FBE0E4;}
.notif__i .dotp{width:6px;height:6px;border-radius:50%;background:var(--accent);margin-top:7px;flex-shrink:0;}
.notif__i .dotp.read{background:var(--ink-5);}
.notif__t{font-size:13.5px;font-weight:600;line-height:1.45;}
.notif__b{font-size:12.5px;color:var(--ink-3);margin-top:2px;line-height:1.6;}
.notif__m{font-size:11px;color:var(--ink-4);margin-top:5px;}

/* 内容区 */
.body{flex:1;padding:26px var(--body-pad) 60px;}
.wrap{max-width:var(--maxw);margin:0 auto;}
.wrap--narrow{max-width:980px;margin:0 auto;}

.phead{display:flex;align-items:flex-end;justify-content:space-between;gap:18px;margin-bottom:22px;flex-wrap:wrap;}
.phead__t{font-size:25px;font-weight:800;letter-spacing:-.6px;line-height:1.25;}
.phead__d{font-size:13.5px;color:var(--ink-3);margin-top:5px;max-width:640px;line-height:1.7;}
.phead__a{display:flex;gap:9px;align-items:center;flex-wrap:wrap;}

.tbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:18px;}
.tbar__sp{flex:1;}

.sec{margin-top:34px;}
.sec__h{display:flex;align-items:center;justify-content:space-between;gap:14px;margin-bottom:14px;}
.sec__h h3{font-size:16.5px;font-weight:750;letter-spacing:-.2px;display:flex;align-items:center;gap:9px;}
.sec__h h3::before{content:"";width:3px;height:15px;border-radius:2px;background:var(--accent);}
.sec__h .more{font-size:12.5px;color:var(--ink-3);font-weight:600;cursor:default;}

.hr{height:1px;background:var(--line-2);border:none;margin:26px 0;}

/* ============================================================================
   卡片
   ========================================================================== */
.card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);box-shadow:var(--sh-1);}
.card__h{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:15px 18px;border-bottom:1px solid var(--line-2);}
.card__h h3{font-size:14.5px;font-weight:700;}
.card__b{padding:18px;}
.card--pad{padding:18px;}

/* 统计磁贴 */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:14px;}
.tile{
  position:relative;background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:18px;box-shadow:var(--sh-1);overflow:hidden;transition:.2s var(--ease);
}
.tile:hover{box-shadow:var(--sh-3);transform:translateY(-2px);}
.tile::after{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--brand);opacity:.85;}
.tile--accent::after{background:var(--accent);}
.tile--blue::after{background:var(--blue-2);}
.tile--green::after{background:var(--green);}
.tile--amber::after{background:var(--amber);}
.tile--violet::after{background:var(--violet);}
.tile__ic{position:absolute;right:16px;top:15px;font-size:17px;opacity:.22;}
/* ★ v2.8.0 卡片字体统一：以「模板市场」的 .tstat__* 为基准（用户指定的字体模板）。
   原来这里是「衬线体 30px / 行标 500 / 备注 11.5px」，而模板市场是
   「无衬线 24px/800/-.7px / 行标 700 / 备注 11px」——
   同一套产品里两种口径，并排看会明显「不是一套东西」。
   这里把三行文字的字号/字重/字距/行高全部对齐，数字也不再走衬线体。
   卡片结构（左侧 3px 主色条、圆角、阴影）保持不动。 */
.tile__n{font-size:24px;font-weight:800;letter-spacing:-.7px;line-height:1.15;font-variant-numeric:tabular-nums;font-family:inherit;}
.tile__l{font-size:12.5px;color:var(--ink-2);margin-top:2px;font-weight:700;}
.tile__x{font-size:11px;color:var(--ink-4);margin-top:3px;display:flex;align-items:center;gap:4px;}
.tile__x .up{color:var(--accent);font-weight:700;}
.tile__x .down{color:var(--green);font-weight:700;}

/* ============================================================================
   报刊卡片
   ========================================================================== */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(232px,1fr));gap:18px;}
.grid--lg{grid-template-columns:repeat(auto-fill,minmax(268px,1fr));}

/* ============================================================================
   表单栅格 .fgrid —— 固定列数在窄屏会「撑不破也不收缩」
   ---------------------------------------------------------------------------
   ★ 为什么必须抽成类，而不能继续写 `style="display:grid;grid-template-columns:1fr 1fr"`
    （这是本项目实测过的一个真实事故，写在源码里防止后人再写回去）：
   内联的 `1fr 1fr` 是「两列各占 1 份剩余空间」，fr 的**最小值是 auto**，
   而 grid 项默认 `min-width:auto` —— 于是列宽的下限不是 0，而是**内容的最小内容宽**
   （输入框的默认宽度、`placeholder` 的固有宽度…）。桌面 1600px 下看不出来，
   一到 390px，两列各自被内容顶住、整张卡连同 `scrollWidth` 一起被钉死在 473px，
   **且与视口宽度完全无关**（390/360/414 实测 scrollWidth 全是 473）——
   表现就是「手机上部分页面错乱 / 可以左右拖动」。
   ★ 修复有三条缺一不可，少任何一条都只解决一半：
     ① 列模板改成 `minmax(0,1fr)` —— 把列宽下限从 auto 压到 0，列才真的能被压缩；
     ② 栅格项自身加 `min-width:0` —— 否则 `.field` 里的 input 仍会按固有宽度顶开列；
     ③ 窄屏（≤640px）直接退成单列 —— 390px 下硬塞两列，输入框只剩 40px 宽没法用。
   用 `auto-fit + minmax(220px,1fr)` 也能自适应，但本项目这些表单**必须**在桌面上
   严格保持 2 列 / 4 列（列数本身就是设计语言的一部分），所以用显式断点而非 auto-fit。
   ========================================================================== */
.fgrid{
  display:grid;
  grid-template-columns:repeat(var(--fg-cols,2),minmax(0,1fr));
  gap:14px;
}
.fgrid > *{min-width:0;}
.fgrid--2{--fg-cols:2;}
.fgrid--3{--fg-cols:3;}
.fgrid--4{--fg-cols:4;}
@media(max-width:900px){
  .fgrid--4{--fg-cols:2;}
}
@media(max-width:640px){
  .fgrid--2,.fgrid--3,.fgrid--4{--fg-cols:1;}
}

.np{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;
  display:flex;flex-direction:column;box-shadow:var(--sh-1);transition:.22s var(--ease);position:relative;
  cursor:pointer;
}
.np:hover{transform:translateY(-4px);box-shadow:var(--sh-3);border-color:var(--line-strong);}
.np__cover{
  position:relative;aspect-ratio:3/4;background:var(--surface-3);overflow:hidden;
  display:grid;place-items:center;
}
.np__cover img{width:100%;height:100%;object-fit:cover;transition:.4s var(--ease);}
.np:hover .np__cover img{transform:scale(1.035);}
.np__cover canvas,.np__cover .cover-render{width:100%;height:100%;display:block;}
.np__ph{padding:20px;text-align:center;color:var(--ink-3);}
.np__ph .ic{font-size:30px;display:block;margin-bottom:8px;opacity:.4;}
.np__ph .t{font-family:var(--serif);font-size:16px;font-weight:700;color:var(--ink-2);line-height:1.4;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;}
.np__badge{position:absolute;top:10px;left:10px;}
/* ★ 悬停层只作「操作按钮的容器」，背景全透明。
   用户要求：鼠标移上不要出现渐变色，改由卡片边框突出（见 .np:hover）。 */
.np__ov{
  position:absolute;inset:0;background:none;
  display:flex;align-items:flex-end;justify-content:center;gap:8px;padding:14px;
  opacity:0;transition:.22s var(--ease);
}
.np:hover .np__ov{opacity:1;}
/* 没有遮罩衬托后，按钮必须自带白底与投影，否则压在浅色封面上会糊成一片 */
.np__ov .btn{background:rgba(255,255,255,.96);border-color:transparent;color:var(--ink);
  box-shadow:0 10px 22px -10px rgba(15,17,20,.5), 0 2px 6px -2px rgba(15,17,20,.28);}
.np__ov .btn:hover{background:#fff;transform:translateY(-1px);}
.np__ov .btn--accent{background:var(--accent);color:#fff;}
.np__body{padding:13px 15px 15px;display:flex;flex-direction:column;gap:7px;flex:1;}
.np__t{font-size:15px;font-weight:700;line-height:1.42;letter-spacing:-.2px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
.np__meta{font-size:11.5px;color:var(--ink-4);display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
.np__meta .sp{width:3px;height:3px;border-radius:50%;background:var(--ink-5);}
.np__desc{font-size:12.5px;color:var(--ink-3);line-height:1.65;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
.np__foot{margin-top:auto;padding-top:10px;border-top:1px solid var(--line-2);display:flex;align-items:center;justify-content:space-between;gap:8px;}
.np__acts{display:flex;gap:6px;flex-wrap:wrap;}
.np__snip{font-size:11.5px;color:var(--accent);background:var(--accent-soft);padding:5px 8px;border-radius:var(--r-xs);line-height:1.6;}

/* 列表行 */
.np-row{display:flex;align-items:center;gap:14px;padding:12px 14px;border-bottom:1px solid var(--line-2);transition:.14s;cursor:pointer;}
.np-row:hover{background:var(--surface-2);}
.np-row:last-child{border-bottom:none;}
.np-row__thumb{width:46px;height:60px;border-radius:var(--r-sm);background:var(--surface-3);overflow:hidden;flex-shrink:0;
  display:grid;place-items:center;font-size:17px;color:var(--ink-4);}
.np-row__thumb img{width:100%;height:100%;object-fit:cover;}
.np-row__t{font-size:13.5px;font-weight:650;line-height:1.4;}
.np-row__m{font-size:11.5px;color:var(--ink-4);margin-top:2px;}

/* ============================================================================
   Hero 轮播
   ========================================================================== */
.hero{
  position:relative;border-radius:var(--r-xl);overflow:hidden;background:#141619;
  /* ★ v2.8.1：改用 --sh-hero（带正向 x 偏移的三档叠影）。
     原来这里是 --sh-3，横向 spread 被吃光 → 右侧几乎看不到投影。 */
  min-height:296px;margin-bottom:34px;box-shadow:var(--sh-hero);
}
.hero__track{display:flex;transition:transform .6s var(--ease);height:296px;}
.hero__slide{
  min-width:100%;position:relative;display:grid;grid-template-columns:1.15fr .85fr;
  align-items:center;gap:20px;padding:34px 40px;color:#fff;
}
.hero__slide::before{
  content:"";position:absolute;inset:0;
  background:linear-gradient(103deg,var(--hs,#1B3A8C) 0%,rgba(20,22,25,.94) 72%);
}
.hero__slide > *{position:relative;z-index:2;}
.hero__tag{display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:99px;
  background:rgba(255,255,255,.14);font-size:11.5px;font-weight:600;margin-bottom:14px;backdrop-filter:blur(4px);}
.hero__t{font-family:var(--serif);font-size:31px;font-weight:700;line-height:1.32;letter-spacing:-.4px;margin-bottom:11px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
.hero__d{font-size:13.5px;color:rgba(255,255,255,.66);line-height:1.85;max-width:440px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}
.hero__a{display:flex;gap:10px;margin-top:20px;}
.hero__a .btn{background:#fff;border-color:transparent;color:#15171A;}
.hero__a .btn:hover{background:#F2F1EE;}
.hero__a .btn--accent{background:var(--accent);color:#fff;}
.hero__cover{justify-self:center;width:164px;aspect-ratio:3/4;border-radius:6px;overflow:hidden;
  box-shadow:0 26px 50px -20px rgba(0,0,0,.75);background:var(--surface-3);
  transform:rotate(2.5deg);transition:.4s var(--ease);}
.hero__slide:hover .hero__cover{transform:rotate(0deg) translateY(-4px);}
.hero__cover img{width:100%;height:100%;object-fit:cover;}
.hero__dots{position:absolute;bottom:16px;left:40px;display:flex;gap:6px;z-index:3;}
.hero__dot{width:7px;height:7px;border-radius:99px;background:rgba(255,255,255,.32);cursor:pointer;transition:.22s var(--ease);}
.hero__dot.is-on{width:22px;background:#fff;}
.hero__nav{position:absolute;right:22px;bottom:14px;display:flex;gap:7px;z-index:3;}
.hero__nav button{width:30px;height:30px;border-radius:50%;background:rgba(255,255,255,.14);color:#fff;
  display:grid;place-items:center;font-size:14px;backdrop-filter:blur(4px);transition:.16s;}
.hero__nav button:hover{background:rgba(255,255,255,.26);}
@media(max-width:820px){.hero__slide{grid-template-columns:1fr;padding:26px;} .hero__cover{display:none;} .hero__t{font-size:23px;}}

/* 分类导航条 */
.cats{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:20px;}
.cat{
  display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border-radius:99px;
  border:1px solid var(--line);background:var(--surface);font-size:13px;font-weight:600;color:var(--ink-2);
  transition:.16s var(--ease);
}
.cat:hover{border-color:var(--ink-5);color:var(--ink);}
.cat.is-on{background:var(--brand);border-color:var(--brand);color:#fff;}
.cat .n{font-size:11px;opacity:.6;font-weight:500;}

/* ============================================================================
   模板库
   ========================================================================== */
.gal{display:grid;grid-template-columns:repeat(auto-fill,minmax(238px,1fr));gap:20px;}
.tpl{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden;
  box-shadow:var(--sh-1);transition:.24s var(--ease);cursor:pointer;position:relative;
  display:flex;flex-direction:column;
}
.tpl:hover{transform:translateY(-5px);box-shadow:var(--sh-4);border-color:var(--line-strong);}
.tpl__cover{
  position:relative;aspect-ratio:3/4;background:var(--surface-3);overflow:hidden;
}
.tpl__cover canvas,.tpl__cover .cover-render{width:100%;height:100%;display:block;}
.tpl__ov{
  /* ★ v2.7.0：模板卡与报刊卡一致 —— 悬停不再盖渐变遮罩，改为边框转主色。
     这里必须就地清掉（而不是只在末尾用 background:none 覆盖），
     否则源码里留着一条「看着还在压暗封面」的旧规则，很误导。 */
  position:absolute;inset:0;background:none;
  display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:8px;padding:16px;
  opacity:0;transition:.24s var(--ease);
}
.tpl:hover .tpl__ov{opacity:1;}
.tpl__ov .btn{width:100%;}
.tpl__ov .btn--accent{box-shadow:0 8px 20px -10px rgba(200,16,46,.9);}
.tpl__pages{
  position:absolute;top:10px;right:10px;padding:3px 8px;border-radius:99px;
  background:rgba(15,17,20,.62);color:#fff;font-size:11px;font-weight:600;backdrop-filter:blur(6px);
}
.tpl__body{padding:12px 14px 14px;display:flex;flex-direction:column;gap:7px;flex:1;}
.tpl__t{font-size:14px;font-weight:700;line-height:1.4;letter-spacing:-.1px;}
.tpl__scene{font-size:11.5px;color:var(--ink-4);line-height:1.55;
  display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;}
.tpl__foot{margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:8px;padding-top:9px;border-top:1px solid var(--line-2);}
.swatches{display:flex;gap:4px;}
.sw{width:13px;height:13px;border-radius:4px;border:1px solid rgba(0,0,0,.09);}
.tpl__use{font-size:11px;color:var(--ink-4);}

/* 模板详情 */
.tpl-detail{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:26px;}
.tpl-detail__stage{
  background:var(--surface-3);border-radius:var(--r-lg);padding:26px;display:flex;flex-direction:column;
  align-items:center;gap:16px;border:1px solid var(--line);
}
.tpl-detail__page{
  width:min(430px,100%);aspect-ratio:3/4;background:#fff;border-radius:4px;overflow:hidden;
  box-shadow:var(--sh-4);position:relative;
}
.tpl-detail__page .cover-render{width:100%;height:100%;}
.tpl-pager{display:flex;gap:7px;flex-wrap:wrap;justify-content:center;}
.tpl-pager .pg{width:32px;height:24px;border-radius:var(--r-xs);border:1px solid var(--line);background:#fff;
  font-size:11px;font-weight:600;color:var(--ink-3);display:grid;place-items:center;transition:.16s;}
.tpl-pager .pg:hover{border-color:var(--ink-5);}
.tpl-pager .pg.is-on{background:var(--brand);border-color:var(--brand);color:#fff;}
.tpl-detail__info h2{font-family:var(--serif);font-size:24px;font-weight:700;margin-bottom:6px;letter-spacing:-.3px;}
.tpl-detail__info .scene{font-size:12.5px;color:var(--ink-3);margin-bottom:16px;line-height:1.7;}
.kv{display:grid;grid-template-columns:76px 1fr;gap:10px 12px;font-size:13px;padding:16px 0;border-top:1px solid var(--line-2);}
.kv .k{color:var(--ink-4);font-size:12.5px;}
.kv .v{color:var(--ink-2);font-weight:500;}
@media(max-width:900px){.tpl-detail{grid-template-columns:1fr;}}

/* ============================================================================
   表格
   ========================================================================== */
.tbl-wrap{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-1);}
.tbl{font-size:13px;}
.tbl thead th{
  text-align:left;padding:11px 16px;background:var(--surface-2);font-size:11.5px;font-weight:700;
  color:var(--ink-3);letter-spacing:.05em;text-transform:uppercase;border-bottom:1px solid var(--line);
  white-space:nowrap;
}
.tbl tbody td{padding:12px 16px;border-bottom:1px solid var(--line-2);vertical-align:middle;}
.tbl tbody tr:last-child td{border-bottom:none;}
.tbl tbody tr{transition:background .14s;}
.tbl tbody tr:hover{background:var(--surface-2);}
.tbl .num{font-variant-numeric:tabular-nums;font-weight:600;}
.tbl .acts{display:flex;gap:6px;flex-wrap:wrap;}
.tbl--compact thead th{padding:9px 12px;}
.tbl--compact tbody td{padding:9px 12px;}

/* ============================================================================
   图表
   ========================================================================== */
.chart{width:100%;}
/* ★ v2.8.0：svg 必须**等比**缩放。
   原来这里写死 height:220px，而 lineChart 用的是 viewBox="0 0 720 220"
   + preserveAspectRatio="none"，在 1258px 的内容宽度下横向被拉伸 1.747 倍
   （实测 scaleX=1.747 / scaleY=1）。非等比缩放会连 SVG 里的文字一起拉宽 ——
   这就是用户看到「折线图字体虚化」的真正原因。
   改成 width:100% + height:auto 后，渲染比例恒等于 viewBox 比例（1000:260），
   只发生等比缩放，字形不再变形。 */
.chart svg{display:block;width:100%;height:auto;overflow:visible;}
.chart__grid line{stroke:var(--line-2);stroke-width:1;stroke-dasharray:3 5;}
.chart__axis{font-size:11px;font-weight:600;fill:var(--ink-4);font-variant-numeric:tabular-nums;}
.chart__area{fill:url(#areaGrad);}
/* 趋势图是整行 .card，紧随其后的 .sec 被显式写了 margin-top:0，
   实测两者间距 0px —— 图表卡片与「内容状态分布」直接贴合（用户截图圈出）。
   给图表板块自己补一段下外边距，比去改下游兄弟的 margin-top 更稳（下游不止一个）。 */
.sec--chart{margin-bottom:34px;}

/* ---------------------------------------------------------------------------
   后台列表页：统计条 + 底部「共 N 条 · 第 x/y 页」
   --------------------------------------------------------------------------- */
/* 列表页自己的统计条：让 .tile 矮一档，避免把表格挤到首屏之外 */
.stats--tight{grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-bottom:18px;}
.stats--tight .tile{padding:14px 15px;}
.stats--tight .tile__n{font-size:21px;letter-spacing:-.5px;}
.stats--tight .tile__l{font-size:12px;}
.stats--tight .tile__x{font-size:10.5px;margin-top:2px;}
.listfoot{
  display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;
  margin-top:14px;padding:0 3px;
}
.listfoot__s{font-size:12.5px;color:var(--ink-3);font-weight:600;}
.listfoot__s b{color:var(--ink);font-weight:750;font-variant-numeric:tabular-nums;}
.pager--sm{margin:0;justify-content:flex-end;}
.pager--sm .pager__b{min-width:31px;height:31px;padding:0 9px;font-size:12.5px;border-radius:calc(8px * var(--rs, 1));}
.legend{display:flex;gap:16px;flex-wrap:wrap;font-size:12.5px;color:var(--ink-3);}
.lgd{display:flex;align-items:center;gap:7px;}
.lgd__d{width:9px;height:9px;border-radius:3px;flex-shrink:0;}
.lgd__n{font-variant-numeric:tabular-nums;font-weight:700;color:var(--ink);}

.bars{display:flex;flex-direction:column;gap:12px;}
.bar__top{display:flex;justify-content:space-between;font-size:12.5px;margin-bottom:5px;gap:10px;}
.bar__top b{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.bar__top span{color:var(--ink-4);font-variant-numeric:tabular-nums;flex-shrink:0;}
.bar__track{height:7px;border-radius:99px;background:var(--surface-3);overflow:hidden;}
.bar__fill{height:100%;border-radius:99px;background:var(--brand);transition:width .7s var(--ease);}

.donut-wrap{display:flex;align-items:center;gap:22px;flex-wrap:wrap;}
.donut{position:relative;flex-shrink:0;}
.donut__c{position:absolute;inset:0;display:grid;place-items:center;text-align:center;}
.donut__c .n{font-family:var(--serif);font-size:24px;font-weight:700;line-height:1;}
.donut__c .l{font-size:11px;color:var(--ink-4);margin-top:2px;}

/* ============================================================================
   空态 / 骨架
   ========================================================================== */
.empty{text-align:center;padding:66px 20px;color:var(--ink-3);}
.empty .ic{
  width:56px;height:56px;margin:0 auto 14px;border-radius:var(--r-lg);display:grid;place-items:center;
  background:var(--surface-3);font-size:24px;opacity:.8;
}
.empty h4{font-size:15px;color:var(--ink-2);margin-bottom:5px;font-weight:700;}
.empty p{font-size:13px;color:var(--ink-4);max-width:360px;margin:0 auto;line-height:1.75;}

.sk{background:linear-gradient(90deg,var(--surface-3) 25%,var(--paper-2) 37%,var(--surface-3) 63%);
  background-size:400% 100%;animation:sk 1.4s ease infinite;border-radius:var(--r-sm);}
@keyframes sk{0%{background-position:100% 50%}100%{background-position:0 50%}}
.sk--card{height:264px;border-radius:var(--r-lg);}
.sk--line{height:12px;margin-bottom:9px;}

/* ============================================================================
   模态 / 抽屉
   ========================================================================== */
.mask{
  position:fixed;inset:0;z-index:200;background:rgba(21,23,26,.44);backdrop-filter:blur(3px);
  display:grid;place-items:center;padding:22px;animation:fade .18s var(--ease);
}
@keyframes fade{from{opacity:0}to{opacity:1}}
@keyframes pop{from{opacity:0;transform:translateY(10px) scale(.985)}to{opacity:1;transform:none}}
.modal{
  background:var(--surface);border-radius:var(--r-xl);width:min(480px,100%);
  max-height:calc(100vh - 44px);display:flex;flex-direction:column;
  box-shadow:var(--sh-pop);animation:pop .22s var(--ease);overflow:hidden;
}
.modal--sm{width:min(400px,100%);}
.modal--md{width:min(600px,100%);}
.modal--lg{width:min(840px,100%);}
.modal--xl{width:min(1080px,100%);}
.modal__h{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;padding:20px 22px 14px;flex-shrink:0;}
.modal__h h3{font-size:17.5px;font-weight:750;letter-spacing:-.2px;}
.modal__h .sub{font-size:12.5px;color:var(--ink-3);margin-top:4px;line-height:1.65;}
.modal__x{width:28px;height:28px;border-radius:var(--r-sm);display:grid;place-items:center;color:var(--ink-4);font-size:16px;flex-shrink:0;transition:.14s;}
.modal__x:hover{background:var(--surface-3);color:var(--ink);}
.modal__b{padding:0 22px;overflow-y:auto;flex:1;}
.modal__f{display:flex;justify-content:flex-end;gap:9px;padding:18px 22px 20px;flex-shrink:0;border-top:1px solid var(--line-2);margin-top:18px;}
.modal__f--split{justify-content:space-between;}

/* ============================================================================
   Toast
   ========================================================================== */
.toast-root{position:fixed;left:50%;bottom:26px;transform:translateX(-50%);z-index:500;
  display:flex;flex-direction:column;gap:9px;align-items:center;pointer-events:none;}
.toast{
  display:flex;align-items:center;gap:9px;padding:11px 18px;border-radius:var(--r-md);
  background:#15171A;color:#fff;font-size:13.5px;font-weight:500;box-shadow:var(--sh-4);
  animation:toastIn .24s var(--ease);max-width:min(520px,90vw);
}
.toast.out{animation:toastOut .22s var(--ease) forwards;}
.toast .ic{font-size:14px;}
.toast .tc{
  margin-left:2px;padding:0 6px;border-radius:99px;font-size:11px;font-weight:700;
  background:rgba(255,255,255,.22);font-variant-numeric:tabular-nums;
}
.toast--ok{background:#0F7B4F;}
.toast--err{background:#B4122A;}
.toast--warn{background:#A15C07;}
@keyframes toastIn{from{opacity:0;transform:translateY(12px) scale(.97)}to{opacity:1;transform:none}}
@keyframes toastOut{to{opacity:0;transform:translateY(8px) scale(.98)}}

/* ============================================================================
   编辑器
   ========================================================================== */
.ed{display:flex;flex-direction:column;height:100vh;background:var(--paper-2);overflow:hidden;}
.ed__top{
  height:52px;flex-shrink:0;display:flex;align-items:center;gap:10px;padding:0 12px;
  background:#15171A;color:#fff;border-bottom:1px solid #24272C;
}
.ed__brand{display:flex;align-items:center;gap:8px;font-size:13.5px;font-weight:700;white-space:nowrap;}
.ed__brand .mk{width:26px;height:26px;border-radius:7px;background:var(--accent);display:grid;place-items:center;
  font-family:var(--serif);font-size:14px;font-weight:700;}
.ed__title{
  background:#22252A;border:1px solid #32363D;color:#fff;border-radius:var(--r-sm);
  padding:6px 11px;width:250px;font-size:13px;transition:.16s;
}
.ed__title:hover{border-color:#43484F;}
.ed__title:focus{outline:none;border-color:var(--accent);background:#1B1E22;}
.ed__sp{flex:1;}
.ed__ver{font-size:11.5px;color:#8A9099;font-variant-numeric:tabular-nums;}
.ed__presence{display:flex;align-items:center;}
.ed__presence .av{width:26px;height:26px;font-size:11px;border:2px solid #15171A;margin-left:-8px;}
.ed__presence .av:first-child{margin-left:0;}
.ed__presence .who{font-size:11.5px;color:#9CA3AF;margin-left:9px;}

.ebtn{
  display:inline-flex;align-items:center;gap:6px;padding:6.5px 11px;border-radius:var(--r-sm);
  background:#22252A;border:1px solid #32363D;color:#D5D9DE;font-size:12.5px;font-weight:600;
  transition:.14s;white-space:nowrap;
}
.ebtn:hover{background:#2B2F35;border-color:#3E434A;color:#fff;}
.ebtn:disabled{opacity:.4;cursor:not-allowed;}
.ebtn--go{background:var(--accent);border-color:var(--accent);color:#fff;}
.ebtn--go:hover{background:#D8192F;border-color:#D8192F;}
.ebtn .k{font-size:13.5px;line-height:1;opacity:.9;}

.ed__body{flex:1;display:grid;grid-template-columns:212px minmax(0,1fr) 288px;min-height:0;}

/* 左侧：版面 / 图层 */
.ed__left,.ed__right{background:var(--surface);overflow-y:auto;display:flex;flex-direction:column;}
.ed__left{border-right:1px solid var(--line);}
.ed__right{border-left:1px solid var(--line);}
.panel{padding:14px;border-bottom:1px solid var(--line-2);}
.panel__h{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:11px;}
.panel__h h4{font-size:11px;font-weight:700;color:var(--ink-4);letter-spacing:.1em;text-transform:uppercase;}

.pgthumb{
  position:relative;width:100%;aspect-ratio:3/4;border-radius:var(--r-sm);border:1.5px solid var(--line);
  background:#fff;cursor:pointer;overflow:hidden;transition:.16s var(--ease);margin-bottom:10px;
  box-shadow:var(--sh-1);
}
.pgthumb:hover{border-color:var(--ink-5);}
.pgthumb.is-on{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);}
.pgthumb__n{position:absolute;left:5px;top:4px;z-index:3;padding:1px 6px;border-radius:5px;
  background:rgba(21,23,26,.72);color:#fff;font-size:10px;font-weight:700;backdrop-filter:blur(4px);}
.pgthumb__x{position:absolute;right:4px;top:4px;z-index:3;width:19px;height:19px;border-radius:5px;
  background:rgba(21,23,26,.72);color:#fff;font-size:11px;display:none;place-items:center;}
.pgthumb:hover .pgthumb__x{display:grid;}
.pgthumb__mini{position:absolute;inset:0;}

.layer{
  display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:var(--r-sm);font-size:12.5px;
  cursor:pointer;transition:.14s;color:var(--ink-2);margin-bottom:2px;
}
.layer:hover{background:var(--surface-3);}
.layer.is-on{background:var(--accent-soft);color:var(--accent);font-weight:600;}
.layer .ic{width:15px;text-align:center;font-size:12px;opacity:.8;flex-shrink:0;}
.layer .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.layer .eye{margin-left:auto;opacity:0;font-size:11px;color:var(--ink-4);}
.layer:hover .eye{opacity:1;}

/* 画布区 */
.ed__canvas{
  position:relative;overflow:auto;background:
    linear-gradient(90deg,rgba(0,0,0,.028) 1px,transparent 1px) 0 0/22px 22px,
    linear-gradient(0deg,rgba(0,0,0,.028) 1px,transparent 1px) 0 0/22px 22px,
    var(--paper-2);
  display:flex;align-items:flex-start;justify-content:center;padding:34px 34px 80px;
  min-height:0;
}
.canvas-stage{position:relative;flex-shrink:0;}
.canvas{
  position:relative;background:#fff;overflow:hidden;
  box-shadow:0 24px 60px -26px rgba(28,25,20,.45),0 0 0 1px var(--line);
  transform-origin:top center;
}
.canvas.is-grid{background-image:
  linear-gradient(90deg,rgba(21,23,26,.045) 1px,transparent 1px),
  linear-gradient(0deg,rgba(21,23,26,.045) 1px,transparent 1px);
  background-size:10px 10px;}

.el{position:absolute;border:1px solid transparent;box-sizing:border-box;transition:border-color .12s;cursor:move;}
.el:hover{border-color:rgba(200,16,46,.4);}
.el.is-sel{border-color:var(--accent);box-shadow:0 0 0 2px rgba(200,16,46,.14);}
.el.is-drag{cursor:grabbing;}
.el__txt{width:100%;height:100%;outline:none;overflow:hidden;word-break:break-word;white-space:pre-wrap;}
.el__txt[contenteditable="true"]{cursor:text;}
.el__img{width:100%;height:100%;object-fit:cover;display:block;pointer-events:none;}
.el__img--contain{object-fit:contain;}
.el__ph{
  width:100%;height:100%;display:grid;place-items:center;gap:4px;text-align:center;
  background:repeating-linear-gradient(45deg,#F4F3F0,#F4F3F0 9px,#EFEEEA 9px,#EFEEEA 18px);
  color:var(--ink-3);font-size:11.5px;line-height:1.6;
}
.el__ph .ic{font-size:19px;opacity:.5;}
.el__res{
  position:absolute;right:-5px;bottom:-5px;width:11px;height:11px;background:#fff;
  border:2px solid var(--accent);border-radius:3px;cursor:nwse-resize;display:none;z-index:5;
}
.el.is-sel .el__res{display:block;}
.el__tag{
  position:absolute;left:0;top:-19px;padding:1.5px 7px;border-radius:5px 5px 5px 0;
  background:var(--accent);color:#fff;font-size:10px;font-weight:700;white-space:nowrap;display:none;z-index:6;
}
.el.is-sel .el__tag{display:block;}
.el__rot{
  position:absolute;left:50%;top:-26px;width:11px;height:11px;margin-left:-5.5px;border-radius:50%;
  background:#fff;border:2px solid var(--accent);cursor:grab;display:none;z-index:6;
}
.el.is-sel .el__rot{display:block;}
/* 对齐参考线 */
.guide{position:absolute;background:var(--accent);z-index:9;pointer-events:none;}
.guide--v{width:1px;top:0;bottom:0;}
.guide--h{height:1px;left:0;right:0;}
/* 标尺 */
.ruler{position:absolute;background:var(--paper-2);border-color:var(--line);z-index:8;pointer-events:none;}
.ruler--h{left:0;right:0;height:16px;border-bottom:1px solid var(--line);}
.ruler--v{top:0;bottom:0;width:16px;border-right:1px solid var(--line);}
.ruler span{position:absolute;font-size:8.5px;color:var(--ink-4);}

/* 缩放条 */
.zoombar{
  position:absolute;left:50%;bottom:16px;transform:translateX(-50%);z-index:12;
  display:flex;align-items:center;gap:4px;padding:5px;border-radius:99px;
  background:rgba(255,255,255,.94);border:1px solid var(--line);box-shadow:var(--sh-3);
  backdrop-filter:blur(10px);
}
.zoombar button{width:27px;height:27px;border-radius:50%;display:grid;place-items:center;
  font-size:13px;color:var(--ink-2);transition:.14s;}
.zoombar button:hover{background:var(--surface-3);}
.zoombar .val{min-width:48px;text-align:center;font-size:12px;font-weight:700;
  font-variant-numeric:tabular-nums;color:var(--ink-2);}
.zoombar .sep{width:1px;height:18px;background:var(--line);margin:0 3px;}

/* 右侧属性面板 */
.tools{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;}
.tool{
  display:flex;flex-direction:column;align-items:center;gap:3px;padding:8px 3px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--surface);font-size:10.5px;color:var(--ink-3);
  font-weight:600;transition:.15s var(--ease);
}
.tool:hover{border-color:var(--ink-5);color:var(--ink);background:var(--surface-2);}
.tool .k{font-size:15px;line-height:1;}

.pow{display:grid;grid-template-columns:repeat(6,1fr);gap:4px;}
.pow button{aspect-ratio:1;border-radius:var(--r-xs);border:1px solid var(--line);background:var(--surface);
  display:grid;place-items:center;font-size:11px;color:var(--ink-2);transition:.14s;}
.pow button:hover{background:var(--surface-3);border-color:var(--ink-5);}
.pow button.is-on{background:var(--brand);border-color:var(--brand);color:#fff;}

.prop{display:flex;flex-direction:column;gap:11px;}
.prop-row{display:flex;flex-direction:column;gap:5px;}
.prop-row > label{font-size:11.5px;font-weight:600;color:var(--ink-3);}
.prop-2{display:grid;grid-template-columns:1fr 1fr;gap:8px;}
.prop-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:7px;}
.prop-4{display:grid;grid-template-columns:repeat(4,1fr);gap:6px;}
.prop input[type="color"]{width:100%;height:31px;padding:2px;border:1px solid var(--line);border-radius:var(--r-sm);background:var(--surface);cursor:pointer;}
.prop input[type="range"]{width:100%;accent-color:var(--accent);}

.ai-status{display:flex;align-items:center;gap:7px;font-size:11.5px;font-weight:600;padding:8px 10px;border-radius:var(--r-sm);line-height:1.5;}
.ai-status.on{background:var(--green-soft);color:var(--green);}
.ai-status.off{background:var(--surface-3);color:var(--ink-3);}
.ai-status .d{width:6px;height:6px;border-radius:50%;background:currentColor;flex-shrink:0;}
.ai-btn{
  display:flex;align-items:center;gap:8px;width:100%;text-align:left;padding:8.5px 11px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--surface);font-size:12.5px;font-weight:600;color:var(--ink-2);
  transition:.15s var(--ease);margin-bottom:6px;
}
.ai-btn:hover{border-color:var(--ink-5);background:var(--surface-2);color:var(--ink);}
.ai-btn:disabled{opacity:.5;cursor:progress;}
.ai-btn .k{font-size:13px;color:var(--accent);}
.ai-out{
  background:var(--surface-2);border:1px solid var(--line-2);border-radius:var(--r-sm);padding:11px;
  font-size:12px;line-height:1.75;color:var(--ink-2);max-height:230px;overflow-y:auto;
}
.ai-out b{color:var(--ink);}
.ai-out .ok{color:var(--green);font-weight:700;}
.ai-out .err{color:var(--accent);font-weight:700;}

.src{display:inline-block;font-size:10px;font-weight:700;padding:1px 7px;border-radius:99px;margin-left:6px;vertical-align:1px;}
.src--llm{background:var(--violet-soft);color:var(--violet);}
.src--demo{background:var(--surface-3);color:var(--ink-4);}

/* ============================================================================
   阅读器
   ========================================================================== */
/* ★ v2.8.1：阅读器的「皮肤」全部改由 --rd-* 变量驱动（变量定义见下方 body.reading）。
   换阅读背景 = 换一组变量，不再逐条改规则。不写 data-rdbg 时就是原来的深色午夜，
   老行为 / 老截图完全不变。 */
.rd{min-height:100vh;background:var(--rd-bg);color:var(--rd-ink);display:flex;flex-direction:column;}
.rd__top{
  height:58px;flex-shrink:0;display:flex;align-items:center;gap:12px;padding:0 20px;
  border-bottom:1px solid var(--rd-line);background:var(--rd-chrome);
  backdrop-filter:blur(12px);position:sticky;top:0;z-index:40;
}
.rd__t{font-family:var(--serif);font-size:16px;font-weight:700;letter-spacing:.2px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.rd__sub{font-size:11.5px;color:var(--rd-i4);}
.rd__sp{flex:1;}
.btn--dark{background:var(--rd-fill-2);border-color:var(--rd-edge);color:var(--rd-ink);box-shadow:none;}
.btn--dark:hover{background:var(--rd-fill-3);border-color:var(--rd-edge-2);}
.btn--dark.is-on{background:var(--accent);border-color:var(--accent);color:#fff;}

.rd__body{flex:1;display:grid;grid-template-columns:minmax(0,1fr) 320px;min-height:0;}
.rd__main{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:30px 20px;
  background:var(--rd-tex),radial-gradient(1000px 560px at 50% -8%,var(--rd-glow),transparent 68%);min-width:0;}
.rd__stage{perspective:2200px;display:grid;place-items:center;min-height:540px;width:100%;}
.book{position:relative;width:520px;max-width:90vw;aspect-ratio:3/4;transform-style:preserve-3d;transition:transform .18s ease-out;}
.leaf{
  position:absolute;inset:0;transform-origin:left center;transition:transform .92s cubic-bezier(.42,.06,.24,1);
  transform-style:preserve-3d;backface-visibility:hidden;border-radius:3px 9px 9px 3px;overflow:hidden;
  /* 书页本身永远是白纸（不能跟着阅读背景变，否则正文就没法读了），只让投影随背景走 */
  background:#fff;color:var(--ink);box-shadow:var(--rd-leaf-sh);
}
.leaf::after{content:"";position:absolute;left:0;top:0;bottom:0;width:22px;
  background:linear-gradient(90deg,rgba(0,0,0,.19),rgba(0,0,0,.03) 60%,transparent);pointer-events:none;z-index:4;}
.leaf .face{position:absolute;inset:0;overflow:hidden;backface-visibility:hidden;-webkit-backface-visibility:hidden;}
.leaf .face.back{transform:rotateY(180deg);}
.rd__page{position:relative;width:100%;height:100%;}
.rd__foot{display:flex;align-items:center;gap:14px;margin-top:26px;}
.rd .hint{color:var(--rd-i45);}
.rd .hint kbd{background:var(--rd-fill-2);border-color:var(--rd-edge);color:var(--rd-i9);}
.rd__pg{font-size:12.5px;color:var(--rd-i5);font-variant-numeric:tabular-nums;letter-spacing:.5px;}
.pgbar{width:min(320px,50vw);height:3px;border-radius:99px;background:var(--rd-edge);overflow:hidden;}
.pgbar i{display:block;height:100%;background:var(--accent);border-radius:99px;transition:width .4s var(--ease);}

/* ---------- 阅读背景选择器（顶栏按钮 + 圆点浮层） ---------- */
/* 浮层挂在按钮的 relative 容器上：与 .rd__top 的 backdrop-filter 无关，
   不会被毛玻璃的层叠上下文裁掉 */
.rdbg{position:relative;flex:0 0 auto;}
.rdbg__panel{
  position:absolute;right:0;top:calc(100% + 9px);z-index:60;width:198px;
  padding:11px 12px 12px;border-radius:var(--r-md);
  background:var(--rd-chrome);border:1px solid var(--rd-edge);
  box-shadow:0 22px 48px -20px rgba(0,0,0,.6);
  backdrop-filter:blur(14px) saturate(1.4);
  display:none;
}
.rdbg__panel.is-open{display:block;}
.rdbg__h{font-size:11px;font-weight:800;letter-spacing:.08em;color:var(--rd-i4);text-transform:uppercase;margin-bottom:9px;}
.rdbg__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;}
.rdbg__sw{
  position:relative;width:100%;aspect-ratio:1;border-radius:9px;cursor:pointer;
  border:1px solid var(--rd-edge);transition:.16s var(--ease);padding:0;
  background:var(--sw,#111316);
}
.rdbg__sw:hover{transform:translateY(-2px);box-shadow:0 8px 16px -8px rgba(0,0,0,.55);}
.rdbg__sw.is-on{border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-soft);}
/* 选中勾：用 ::after 画，颜色按底色明暗自动选，浅底上不会出现「白勾白底」 */
.rdbg__sw.is-on::after{
  content:"✓";position:absolute;inset:0;display:grid;place-items:center;
  font-size:12px;font-weight:800;color:var(--tick,#fff);
}
.rdbg__name{display:block;margin-top:5px;font-size:10.5px;text-align:center;color:var(--rd-i45);}
.rdbg__c{display:flex;flex-direction:column;align-items:center;}

.rd__side{border-left:1px solid var(--rd-line);background:var(--rd-fill-1);
  display:flex;flex-direction:column;min-height:0;}
.rd__tabs{display:flex;border-bottom:1px solid var(--rd-line);flex-shrink:0;}
.rd__tab{flex:1;padding:13px 8px;text-align:center;font-size:12.5px;font-weight:600;color:var(--rd-i45);
  border-bottom:2px solid transparent;transition:.16s;cursor:pointer;}
.rd__tab:hover{color:var(--rd-i7);}
.rd__tab.is-on{color:var(--rd-ink);border-bottom-color:var(--accent);}
.rd__pane{flex:1;overflow-y:auto;padding:16px;display:none;}
.rd__pane.is-on{display:block;}

.cmt{padding:11px 12px;border-radius:var(--r-md);background:var(--rd-fill-1);margin-bottom:9px;}
.cmt__h{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--rd-i6);}
.cmt__h .av{width:24px;height:24px;font-size:10.5px;}
.cmt__b{margin-top:7px;font-size:13px;line-height:1.72;color:var(--rd-i9);word-break:break-word;}
/* @提醒色：原来写死浅粉 #F2A0AE，浅色底上几乎看不见；改为主色与当前墨色混合，两侧都够对比 */
.cmt__b .at{color:color-mix(in srgb,var(--accent) 58%,var(--rd-ink));font-weight:600;}
.cmt__f{margin-top:8px;display:flex;gap:8px;align-items:center;font-size:11px;color:var(--rd-i36);}
.cmt__f button{font-size:11px;color:var(--rd-i6);}
.cmt__f button:hover{color:var(--rd-ink);}

.rd-inp{
  width:100%;padding:9px 11px;border-radius:var(--r-sm);border:1px solid var(--rd-edge);
  background:var(--rd-fill-1);color:var(--rd-ink);font-size:13px;transition:.16s;
}
.rd-inp::placeholder{color:var(--rd-i32);}
.rd-inp:focus{outline:none;border-color:var(--accent);background:var(--rd-fill-2);}

.catalog__i{display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:var(--r-sm);
  font-size:13px;color:var(--rd-i7);cursor:pointer;transition:.14s;}
.catalog__i:hover{background:var(--rd-fill-hi);color:var(--rd-ink);}
/* 选中态原来写死 rgba(200,16,46,.2)（就是默认红色）→ 切到别的视觉风格时不跟色，用 color-mix 跟随主色 */
.catalog__i.is-on{background:color-mix(in srgb,var(--accent) 22%,transparent);color:var(--rd-ink);}
.catalog__i .n{font-family:var(--serif);font-size:12px;font-weight:700;color:var(--rd-i36);min-width:20px;}

/* 语音朗读条 */
.tts{
  display:flex;align-items:center;gap:9px;padding:12px;border-radius:var(--r-md);
  background:var(--rd-fill-1);border:1px solid var(--rd-line);margin-bottom:14px;
}
.tts button{width:32px;height:32px;border-radius:50%;display:grid;place-items:center;
  background:var(--accent);color:#fff;font-size:13px;transition:.15s;flex-shrink:0;}
.tts button:hover{filter:brightness(1.1);}
.tts button.ghost{background:var(--rd-fill-2);}
.tts .info{flex:1;min-width:0;}
.tts .info .t{font-size:12.5px;font-weight:600;}
.tts .info .s{font-size:11px;color:var(--rd-i36);margin-top:1px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.tts select{background:var(--rd-fill-2);border:1px solid var(--rd-edge);color:var(--rd-ink);
  border-radius:var(--r-xs);padding:4px 6px;font-size:11.5px;}

/* 水印 */
.wm{position:absolute;inset:0;pointer-events:none;z-index:30;overflow:hidden;}
.wm span{position:absolute;color:rgba(21,23,26,.72);font-size:14px;transform:rotate(-28deg);
  white-space:nowrap;font-weight:600;letter-spacing:1px;}

/* 报刊详情页 */
.detail{display:grid;grid-template-columns:300px minmax(0,1fr);gap:34px;}
.detail__cover{aspect-ratio:3/4;border-radius:var(--r-md);overflow:hidden;background:var(--surface-3);
  box-shadow:var(--sh-4);position:relative;}
.detail__cover img{width:100%;height:100%;object-fit:cover;}
.detail__t{font-family:var(--serif);font-size:30px;font-weight:700;line-height:1.3;letter-spacing:-.5px;}
.detail__meta{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin-top:11px;font-size:12.5px;color:var(--ink-3);}
.detail__desc{font-size:14px;line-height:1.95;color:var(--ink-2);margin-top:18px;}
.detail__acts{display:flex;gap:10px;flex-wrap:wrap;margin-top:22px;}
.toc{display:grid;grid-template-columns:1fr 1fr;gap:9px;}
.toc__i{display:flex;align-items:center;gap:11px;padding:11px 13px;border:1px solid var(--line);
  border-radius:var(--r);font-size:13px;background:var(--surface);transition:.16s;cursor:pointer;}
.toc__i:hover{border-color:var(--accent);background:var(--accent-soft);}
.toc__i .n{font-family:var(--serif);font-weight:700;color:var(--accent);font-size:13px;}
.toc__i .t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.detail--pc{display:grid;grid-template-columns:320px minmax(0,1fr);gap:34px;}
/* ★ 窄屏退单列时必须用 minmax(0,1fr) 而不是 1fr ——
   `1fr` 的隐含最小值是 auto（= 内容的最小内容宽），所以 320px 极窄屏下
   列会被内部内容顶到 342px、撑出 36px 横向溢出（实测 scrollWidth=356 @320）。
   改成 minmax(0,1fr) 后列宽下限归 0，才能真正压到容器宽以内。
   同理，`.detail` 自身那条 @880 规则也一并收紧。 */
@media(max-width:880px){
  .detail{grid-template-columns:minmax(0,1fr);}
  .detail__cover{max-width:240px;}
  .detail--pc{grid-template-columns:minmax(0,1fr);}
}
/* 极窄屏（≤360px）再兜一层：卡片内边距与 kv 的首列也要收，
   否则内容侧仍顶着 340px 左右的最小宽。 */
@media(max-width:360px){
  .detail--pc .card--pad{padding:14px;}
  .detail--pc .kv{grid-template-columns:56px minmax(0,1fr);}
  .detail--pc .tabs{gap:0;}
  .detail--pc .tab{padding:10px 11px;font-size:13px;}
}
/* ★ 必须写在这一条 media 之后、且只依赖同一个断点 —— .detail--pc 比 .detail 多一个类名，
   特异度更高（0,2,0 > 0,1,0），若把它的基础声明放在 media 之后就会反过来盖掉响应式规则。
   放在这里：宽屏由上面那条生效，≤880px 由下面这条生效，两条同断点、同特异度，后者胜出。 */
@media(max-width:880px){.detail--pc{grid-template-columns:1fr;}}

/* 详情/审核 信息条 */
.infobar{display:flex;gap:24px;flex-wrap:wrap;padding:14px 18px;background:var(--surface-2);
  border:1px solid var(--line);border-radius:var(--r-md);font-size:12.5px;}
.infobar .it{display:flex;flex-direction:column;gap:2px;}
.infobar .it .k{color:var(--ink-4);font-size:11.5px;}
.infobar .it .v{font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums;}

/* 时间线（审批流 / 版本） */
.timeline{position:relative;padding-left:24px;}
.timeline::before{content:"";position:absolute;left:7px;top:6px;bottom:6px;width:1px;background:var(--line);}
.tl{position:relative;padding-bottom:18px;}
.tl::before{content:"";position:absolute;left:-21px;top:4px;width:9px;height:9px;border-radius:50%;
  background:var(--surface);border:2px solid var(--ink-5);}
.tl.is-ok::before{background:var(--green);border-color:var(--green);}
.tl.is-no::before{background:var(--accent);border-color:var(--accent);}
.tl.is-now::before{background:var(--amber);border-color:var(--amber);box-shadow:0 0 0 4px var(--amber-soft);}
.tl__t{font-size:13.5px;font-weight:650;}
.tl__m{font-size:11.5px;color:var(--ink-4);margin-top:2px;}
.tl__b{font-size:12.5px;color:var(--ink-3);margin-top:5px;line-height:1.7;}

/* 版本对比 */
.diff{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
.diff__col h5{font-size:12px;color:var(--ink-4);margin-bottom:8px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;}
.dl{font-size:12px;padding:6px 9px;border-radius:var(--r-xs);margin-bottom:5px;background:var(--surface-2);
  white-space:pre-wrap;word-break:break-word;line-height:1.65;border:1px solid transparent;}
.dl.chg{background:var(--amber-soft);border-color:#F5DFB0;color:var(--amber);}

/* 提示条 */
.note{display:flex;gap:10px;padding:12px 14px;border-radius:var(--r-md);font-size:12.5px;line-height:1.7;
  background:var(--surface-2);border:1px solid var(--line);color:var(--ink-2);}
.note--info{background:var(--blue-soft);border-color:#D6E2FA;color:#1A3A7A;}
.note--warn{background:var(--amber-soft);border-color:#F5DFB0;color:var(--amber);}
.note--ok{background:var(--green-soft);border-color:#C9E9DA;color:var(--green);}
.note--err{background:var(--accent-soft);border-color:var(--accent-line);color:var(--accent);}
.note .ic{font-size:15px;flex-shrink:0;line-height:1.4;}

/* 进度 */
.prog{height:5px;border-radius:99px;background:var(--surface-3);overflow:hidden;}
.prog i{display:block;height:100%;background:var(--accent);border-radius:99px;transition:width .3s var(--ease);}

/* 标签切换 */
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);margin-bottom:20px;overflow-x:auto;}
.tab{padding:10px 15px;font-size:13.5px;font-weight:600;color:var(--ink-3);border-bottom:2px solid transparent;
  white-space:nowrap;transition:.16s;margin-bottom:-1px;}
.tab:hover{color:var(--ink);}
.tab.is-on{color:var(--ink);border-bottom-color:var(--accent);}

/* 头像组 */
.avgroup{display:flex;align-items:center;}
.avgroup .av{border:2px solid var(--surface);margin-left:-9px;}
.avgroup .av:first-child{margin-left:0;}

/* 加载态 */
.loading{display:grid;place-items:center;min-height:46vh;color:var(--ink-3);gap:14px;}
.spin{width:26px;height:26px;border:2.5px solid var(--line);border-top-color:var(--accent);border-radius:50%;
  animation:spin .8s linear infinite;}
@keyframes spin{to{transform:rotate(360deg)}}
.loading--inline{min-height:auto;padding:34px;}

/* 打印 */
.print-only{display:none;}
@media print{
  body{background:#fff;}
  .side,.top,.ed__top,.rd__top,.rd__side,.rd__foot,.rd__stage,.phead__a,.tbar,.np__acts,.no-print,.fsexit{display:none !important;}
  /* v2.8.2：动作层是 canvas，打印会把它当前那一帧画上去（而且可能是低头看稿的姿势）。
     纸面上要的是标准形象 —— 直接藏掉 canvas、把静态图强制显回来。 */
  .myhero__cv{display:none !important;}
  .myhero__img.is-off{opacity:1 !important;}
  .main{margin-left:0;}
  .rd{background:#fff;color:#000;}
  #printArea{display:block !important;}
  #printArea .leaf{position:relative !important;transform:none !important;box-shadow:none !important;
    width:600px !important;height:800px !important;page-break-after:always;border-radius:0;margin:0 auto;}
  #printArea .leaf::after{display:none;}
  #printArea .face{position:relative !important;transform:none !important;}
}

/* 响应式 */
@media(max-width:1200px){
  .ed__body{grid-template-columns:180px minmax(0,1fr) 262px;}
}
@media(max-width:1080px){
  .ed__body{grid-template-columns:minmax(0,1fr) 268px;}
  .ed__left{display:none;}
  .rd__body{grid-template-columns:1fr;}
  .rd__side{border-left:none;border-top:1px solid rgba(255,255,255,.08);max-height:46vh;}
}
@media(max-width:900px){
  .stats{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));}
  .toc{grid-template-columns:1fr;}
}

/* ============================================================================
   ★ 顶栏 1080px 档：填上 820–1080 这段「没有任何规则」的空档
   ---------------------------------------------------------------------------
   缺陷（实测，不是推测）：顶栏在 **820–1080px 之间会把整页撑出横向滚动** ——
     @900  scrollWidth=1031（溢出 131px）
     @960  scrollWidth=1050（溢出  90px）
     @1000 scrollWidth=1063（溢出  63px）
     @1024 scrollWidth=1071（溢出  47px）
     @1080 scrollWidth=1080 ✅   （所以 1080+ 与 820- 都正常）
   成因：顶栏是 `display:flex` 且所有子项 `flex:0 0 auto`（不可压缩），
   总固有宽度约 1031px 起步；而「精简顶栏」的规则全写在 `max-width:820px` 里，
   于是 820–1080 这段谁都不管 —— ☰ 标题 面包屑 搜索(34vw) 🎨 ◐ ❓ 🔔 ⏻ 平铺不下，
   又没有 overflow 兜底，就把 documentElement 撑宽了。
   ★ 注意这不是「手机上」的问题，而是**平板 / 小笔记本 / 分屏窗口**的问题，
     属于用户截图里「部分页面错乱」最可能的来源之一（手机竖屏走 820 档反而正常）。
   处理取舍：这一段有 820–1080 约 260px 的余量，不必像 820 档那样砍到只剩图标 ——
   只做两件代价最小的事：① 去掉面包屑（信息与标题重复，省 ~150px）；
   ② 搜索框从 `min(320px,34vw)` 收到 `min(220px,24vw)`（省 ~110px）。
   两者合计约 260px，正好覆盖最大缺口 131px，且视觉层级完全不变。
   ========================================================================== */
@media(max-width:1080px){
  .top__crumb{display:none;}
  .top__search{width:min(220px,24vw);}
  /* 兜底：万一将来顶栏又加了按钮，宁可让这一层自己省略，也不要撑破整页 */
  .top__t{overflow:hidden;text-overflow:ellipsis;}
}
@media(max-width:820px){
  /* 侧栏改抽屉：位移必须把 --shell-gap 一起算进去，否则收起后仍有 10px 残留在屏内 */
  .side{transform:translateX(calc(-100% - var(--shell-gap) - 2px));transition:transform .24s var(--ease);}
  .side.is-open{transform:none;box-shadow:var(--sh-pop);}
  .main{margin-left:0;}
  :root{--body-pad:14px;}
  .body{padding:18px var(--body-pad) 50px;}
  /* 窄屏顶栏占满整宽（不再右留白），圆角相应收小 */
  .top{padding:0 12px;margin-right:0;border-radius:0 0 12px 12px;gap:6px;}
  /* ★ 顶栏精简（390 实测）：☰ + 标题 + 搜索 + 🎨 + ◐ + ? + 🔔 + ⏻ 一共放不下 ——
     #logoutBtn 的右边界会被顶到 498.8（视口只有 390），把整个页面撑宽 110px 并
     产生横向滚动。处理：去掉面包屑（信息与页面标题重复）、去掉 ? 帮助入口
     （侧栏底部本就有「快捷键帮助」）、缩小间距与图标尺寸、搜索按钮收进输入框
     （窄屏仍可用回车触发搜索）。 */
  .top__crumb{display:none;}
  #helpTopBtn{display:none;}
  .top .btn--icon{width:32px;height:32px;font-size:14px;}
  /* .top__sp 是「把右侧按钮推到最右」的弹性占位；窄屏它会和搜索框抢空间
     （实测搜索框只分到 70px），去掉它之后搜索框拿满剩余宽度。
     ★ min-width 要写在 .tsearch 上 —— .top__search 的父级不是 flex 容器，
       写在它身上的 flex/min-width 全部无效。 */
  .top__sp{display:none;}
  /* ★ min-width 必须与 .top__search 的宽度同口径（见窄屏 640 段的详细注释）：
     写小了会让搜索框「内部溢出到容器外」，被后面的图标按钮压住。
     ★★ 这里必须用**分开写**的 flex-grow/shrink/basis，不能写 `flex:1 1 auto` 简写 ——
     简写会把 flex-shrink 一并重置成 1，覆盖掉基础层的 `.tsearch{flex-shrink:999}`
     （第一版实测就是这么翻车的：900px 下标题完整、搜索框却不肯让位，
      公众号标题长 15px 就溢出 12px）。
     basis 用 auto 让它先按内容宽（min(190px,26vw)）占位，再靠 shrink 让步。 */
  .tsearch{flex-grow:1;flex-shrink:999;flex-basis:auto;min-width:min(190px,26vw);}
  .top__search{width:auto;}
  #globalSearchBtn{display:none;}
  .grid{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:13px;}
  .gal{grid-template-columns:repeat(auto-fill,minmax(158px,1fr));gap:13px;}
  .phead__t{font-size:21px;}
  .ed__body{grid-template-columns:minmax(0,1fr);}
  .ed__right{display:none;}
  .menu-btn{display:inline-flex !important;}
}
.menu-btn{display:none;}
.scrim{position:fixed;inset:0;background:rgba(21,23,26,.4);z-index:39;animation:fade .18s var(--ease);}

/* ============================================================================
   侧栏收起 / 展开（html[data-nav="mini"]）
   —— .side{width:var(--side-w)} 与 .main{margin-left:var(--side-w)} 共用同一变量，
      切换 data-nav 即让侧栏宽度与内容区占位同时变化，右侧页面自动自适应。
   ========================================================================== */
.side{transition:width .22s var(--ease),padding .22s var(--ease),transform .24s var(--ease);}
.main{transition:margin-left .22s var(--ease);}
html[data-nav="mini"]{--side-w:66px;}

/* 展开/收起按钮（位于品牌行右端） */
.side__fold{
  margin-left:auto;width:24px;height:24px;flex-shrink:0;border:0;padding:0;cursor:pointer;
  border-radius:7px;background:transparent;color:var(--ink-4);
  display:grid;place-items:center;font-size:16px;line-height:1;font-family:var(--sans);
  transition:background .14s var(--ease),color .14s var(--ease);
}
.side__fold:hover{background:var(--surface-3);color:var(--ink);}
.side__fold:focus-visible{outline:none;box-shadow:0 0 0 2px var(--brand);}

/* —— 收起态 —— */
html[data-nav="mini"] .side__brand{flex-direction:column;gap:8px;padding:4px 0 14px;}
html[data-nav="mini"] .side__bname{display:none;}
html[data-nav="mini"] .side__fold{margin-left:0;}
html[data-nav="mini"] .side__scroll{margin:0;padding:0;}

/* 分组标题收成一条细线 */
html[data-nav="mini"] .side__label{
  font-size:0;letter-spacing:0;padding:0;margin:12px 9px 8px;
  border-top:1px solid var(--line-2);height:0;overflow:hidden;
}
html[data-nav="mini"] .nav__item{justify-content:center;padding:9px 0;position:relative;gap:0;}
html[data-nav="mini"] .nav__item>span:not(.nav__ic):not(.nav__badge){display:none;}
html[data-nav="mini"] .nav__ic{width:auto;font-size:16px;opacity:.86;}
html[data-nav="mini"] .nav__item.is-on{box-shadow:0 6px 14px -9px rgba(21,23,26,.9);}
/* 角标退化为右上小圆点 */
html[data-nav="mini"] .nav__badge{
  position:absolute;top:4px;right:9px;min-width:7px;height:7px;width:7px;
  padding:0;font-size:0;line-height:0;border-radius:50%;
}
html[data-nav="mini"] .side__foot{padding-top:10px;margin-top:6px;}
html[data-nav="mini"] .sidebtn{justify-content:center;padding-left:0;padding-right:0;gap:0;}
html[data-nav="mini"] .sidebtn__tx,html[data-nav="mini"] .sidebtn__bd{display:none;}
html[data-nav="mini"] .sidebtn__ic{font-size:16px;}
html[data-nav="mini"] .me-card{justify-content:center;padding:6px 0;gap:0;}
html[data-nav="mini"] .me-card__tx,html[data-nav="mini"] .me-card__arw{display:none;}

/* 窄屏：侧栏本就是抽屉（transform 平移），收起态一律还原成完整体 */
@media(max-width:820px){
  html[data-nav="mini"]{--side-w:236px;}
  html[data-nav="mini"] .side__brand{flex-direction:row;gap:10px;padding:4px 8px 16px;}
  html[data-nav="mini"] .side__bname{display:block;}
  html[data-nav="mini"] .side__fold{display:none;}
  html[data-nav="mini"] .side__label{font-size:10.5px;padding:14px 10px 6px;margin:0;border-top:0;height:auto;}
  html[data-nav="mini"] .nav__item{justify-content:flex-start;gap:10px;padding:8.5px 10px;}
  html[data-nav="mini"] .nav__item>span:not(.nav__ic):not(.nav__badge){display:inline;}
  html[data-nav="mini"] .nav__ic{width:17px;font-size:14.5px;opacity:.78;}
  html[data-nav="mini"] .nav__badge{
    position:static;width:auto;min-width:17px;height:17px;padding:0 5px;
    font-size:10.5px;line-height:1;border-radius:9px;margin-left:auto;
  }
  html[data-nav="mini"] .sidebtn{justify-content:flex-start;padding-left:12px;padding-right:12px;gap:6px;}
  html[data-nav="mini"] .sidebtn__tx{display:inline;}
  html[data-nav="mini"] .me-card{justify-content:flex-start;padding:8px;gap:10px;}
  html[data-nav="mini"] .me-card__tx{display:block;}
}

/* 顶栏帮助入口：平时与其它图标按钮一致，悬停时点亮品牌色便于发现 */
.help-top{color:var(--ink-2);}
.help-top:hover{color:var(--accent);background:var(--accent-soft);}
@media(max-width:820px){
  .top__search{width:min(190px,26vw);}
}
@media(max-width:640px){
  .top__search{display:none;}
}

/* ===== 补充：中号按钮 / 阅读态 / 版本条目 ===== */
.btn--md{padding:9px 16px;font-size:13.5px;border-radius:var(--r-sm);}

/* 沉浸阅读态：隐藏外壳留白。
   ★ v2.8.1「阅读界面支持多背景选择」的**唯一数据源**在这里。
     所有 --rd-* 都挂在 body.reading 上（.rd 是它的后代，直接继承），
     换背景 = 在 body 上加一个 data-rdbg 值。不写 data-rdbg 就是原来的午夜深色，
     老行为与老截图完全一致。
   命名约定：
     --rd-bg/--rd-glow/--rd-tex  页面底色 / 主区顶部光晕 / 叠加纹理
     --rd-chrome/--rd-line       顶栏毛玻璃底 / 全部分隔线
     --rd-fill-1/2/3             三级「填充面」：卡片与输入框 / 次级按钮 / 悬停
     --rd-edge/--rd-edge-2       控件描边 / 描边悬停
     --rd-ink, --rd-i9…--rd-i18  墨色阶梯（正文 → 滚动条）
     --rd-leaf-sh                书页投影（浅底上必须换掉，否则像砸了个坑） */
body.reading{
  --rd-bg:#111316;
  --rd-glow:rgba(47,91,208,.16);
  --rd-tex:none;
  --rd-chrome:rgba(17,19,22,.86);
  --rd-line:rgba(255,255,255,.08);
  --rd-fill-1:rgba(255,255,255,.05);
  --rd-fill-2:rgba(255,255,255,.09);
  --rd-fill-3:rgba(255,255,255,.16);
  --rd-fill-hi:rgba(255,255,255,.06);
  --rd-edge:rgba(255,255,255,.12);
  --rd-edge-2:rgba(255,255,255,.2);
  --rd-ink:#fff;
  --rd-i9:rgba(255,255,255,.9);
  --rd-i7:rgba(255,255,255,.72);
  --rd-i6:rgba(255,255,255,.6);
  --rd-i5:rgba(255,255,255,.5);
  --rd-i45:rgba(255,255,255,.45);
  --rd-i4:rgba(255,255,255,.42);
  --rd-i36:rgba(255,255,255,.36);
  --rd-i32:rgba(255,255,255,.32);
  --rd-i18:rgba(255,255,255,.18);
  --rd-leaf-sh:-6px 0 12px -6px rgba(0,0,0,.5), 28px 34px 70px -28px rgba(0,0,0,.75);
  background:var(--rd-bg);
}
/* —— 四套**浅色**底：墨色与毛玻璃整体反过来 ——
   ★ 这几条必须放在上面那条之后，靠位置覆盖（同类特异度）。
     用列表选择器一次写完，避免将来加浅色底时漏改某一项。 */
body.reading[data-rdbg="paper"],body.reading[data-rdbg="sepia"],
body.reading[data-rdbg="eye"],body.reading[data-rdbg="slate"]{
  --rd-chrome:rgba(255,255,255,.88);
  --rd-line:rgba(20,22,25,.1);
  --rd-fill-1:rgba(20,22,25,.05);
  --rd-fill-2:rgba(20,22,25,.07);
  --rd-fill-3:rgba(20,22,25,.13);
  --rd-fill-hi:rgba(20,22,25,.05);
  --rd-edge:rgba(20,22,25,.14);
  --rd-edge-2:rgba(20,22,25,.24);
  --rd-ink:#191B1E;
  --rd-i9:rgba(25,27,30,.9);
  --rd-i7:rgba(25,27,30,.74);
  --rd-i6:rgba(25,27,30,.62);
  --rd-i5:rgba(25,27,30,.52);
  --rd-i45:rgba(25,27,30,.48);
  --rd-i4:rgba(25,27,30,.44);
  --rd-i36:rgba(25,27,30,.38);
  --rd-i32:rgba(25,27,30,.34);
  --rd-i18:rgba(20,22,25,.2);
  --rd-leaf-sh:0 22px 52px -26px rgba(28,25,20,.4), 0 5px 14px -7px rgba(28,25,20,.16);
}
/* 深色四套 */
body.reading[data-rdbg="graphite"]{--rd-bg:#191B1F;--rd-glow:rgba(150,160,175,.15);--rd-chrome:rgba(25,27,31,.86);
  --rd-tex:repeating-linear-gradient(45deg,rgba(255,255,255,.022) 0 2px,transparent 2px 6px);}
body.reading[data-rdbg="indigo"]{--rd-bg:#0C1526;--rd-glow:rgba(80,120,240,.22);--rd-chrome:rgba(12,21,38,.86);}
body.reading[data-rdbg="forest"]{--rd-bg:#0B1A15;--rd-glow:rgba(24,160,110,.2);--rd-chrome:rgba(11,26,21,.86);}
/* 浅色四套（墨色由上一条列表统一接管，这里只给底色与光晕，另加纸纹） */
body.reading[data-rdbg="paper"]{--rd-bg:#F4F3EF;--rd-glow:rgba(47,91,208,.1);
  --rd-tex:repeating-linear-gradient(0deg,rgba(28,25,20,.026) 0 1px,transparent 1px 3px);}
body.reading[data-rdbg="sepia"]{--rd-bg:#F7EFDC;--rd-glow:rgba(180,125,40,.14);}
body.reading[data-rdbg="eye"]{--rd-bg:#E7EFE4;--rd-glow:rgba(24,150,95,.14);}
body.reading[data-rdbg="slate"]{--rd-bg:#EDEEF1;--rd-glow:rgba(90,110,160,.13);}
body.reading #app{min-height:100vh;}
body.reading::-webkit-scrollbar{width:8px;}
body.reading::-webkit-scrollbar-thumb{background:var(--rd-i18);border-radius:8px;}
body.reading::-webkit-scrollbar-track{background:transparent;}

/* ============================================================================
   全屏模式（v2.8.1 新增：报刊设计页 + 阅读页）
   ---------------------------------------------------------------------------
   唯一开关是 html[data-fs="on"]。原生 Fullscreen API 只负责「藏掉浏览器界面」，
   站内沉浸态（收面板 / 收顶栏）全部由这个属性驱动 —— 于是原生 API 被拒的环境
   （无 allowfullscreen 的 iframe、旧 WebView）功能依然完整，属有意为之。
   写法上全部用后代选择器，不碰任何组件的默认值：退出全屏 = 去掉一个属性，
   不留「改回去忘了还原」的痕迹。
   -------------------------------------------------------------------------- */

/* —— 阅读页：收起顶栏与右侧栏，正文吃满 ——
   ★ .rd__top 一藏，页面上就没有任何入口了，所以必须给一个常驻退出口（.fsexit）。
     这是本组规则里唯一新增的可见元素，只在全屏态出现。 */
html[data-fs="on"] .rd__top{display:none;}
html[data-fs="on"] .rd__body{grid-template-columns:minmax(0,1fr);}
html[data-fs="on"] .rd__side{display:none;}
html[data-fs="on"] .rd__main{padding:16px 20px;}
/* 书页放到「受高度约束」的尺寸：屏幕越扁，靠宽度撑就会溢出上下边界。
   用 min(宽, 高比例) 让它在任何长宽比下都完整可见。
   ★ 系数 58vh 是留过余量的：3/4 的书页高 = 宽 / 0.75 ≈ 1.333×宽，
     58vh 宽 → 77.3vh 高，再加 .rd__foot(≈44px) + 上下 padding + hint 才不溢出。 */
html[data-fs="on"] .book{width:min(640px, 58vh);}
html[data-fs="on"] .rd__stage{min-height:0;}
html[data-fs="on"] .hint{opacity:.7;}

/* 全屏态下的常驻退出口：默认半透明不吃注意力，鼠标移上去才亮起来 */
.fsexit{
  position:fixed;right:18px;top:18px;z-index:120;display:none;align-items:center;gap:7px;
  padding:9px 14px;border-radius:99px;font:inherit;font-size:12.5px;font-weight:700;
  cursor:pointer;appearance:none;
  background:var(--rd-chrome);border:1px solid var(--rd-edge);color:var(--rd-ink);
  backdrop-filter:blur(14px) saturate(1.4);
  box-shadow:0 16px 34px -14px rgba(0,0,0,.62);
  opacity:.5;transition:opacity .2s var(--ease),transform .2s var(--ease);
}
.fsexit:hover{opacity:1;transform:translateY(-1px);}
.fsexit:focus-visible{opacity:1;outline:2px solid var(--accent);outline-offset:2px;}
html[data-fs="on"] .fsexit{display:inline-flex;}

/* —— 编辑器（报刊设计页）：全屏时把左右工具面板收成「可悬停展开的窄轨」——
   ★ 只收 .ed__top 之外的面板宽度、不收 .ed__top 本身：顶栏上有保存 / 预览 /
     返回 / 退出全屏，全屏设计时最需要的就是「随时存一版」，把顶栏也藏掉是自断后路。

   ★★ 这里原先写的是 `display:none`（把两侧面板整个藏掉）—— 那是个**功能缺失级**的
      错误，不是审美取舍：左侧是「版面 / 图层」，右侧是「插入元素 / AI 智能协作 / 属性」，
      这五块恰恰是编辑时最需要反复用的。藏掉之后全屏下**无法插入任何元素、无法改任何属性**，
      等于「全屏」只能在已有元素上挪位置 —— 用户反馈「全屏编辑时两个编辑功能没有了」
      说的就是这件事（实测：全屏态 .ed__left/.ed__right 宽 0、display:none）。
   ★ 新的做法：保留面板 DOM 与全部交互，只把宽度收到 46px 的**图标轨**；
      鼠标悬停（或键盘 focus-within）时展开回原宽并浮在画布之上（不挤压画布）。
      这么做同时满足三个约束：
        ① 功能不丢 —— 面板一直在，随时可点；
        ② 画布不被压 —— 收起态只占 46px×2，展开时用 absolute 浮层，不触发重排；
        ③ 退出全屏零残留 —— 全部规则挂在 `html[data-fs="on"]` 下，
           去掉属性即回到 export 前的默认布局（宽度/定位都由基础层接管）。
      ★ 悬停展开必须同时给 `:focus-within`：纯 hover 会让键盘用户没法用。 */
html[data-fs="on"] .ed__body{
  grid-template-columns:46px minmax(0,1fr) 46px;
  position:relative;
}
html[data-fs="on"] .ed__left,
html[data-fs="on"] .ed__right{
  width:52px;
  overflow-x:hidden;
  overflow-y:auto;
  transition:width .22s var(--ease),box-shadow .22s var(--ease);
  z-index:12;
  /* 收起态不能被 flex 压扁（.ed__left/right 基础层是 flex column） */
  flex:0 0 auto;
  /* ::after 的「可拉开」暗示条要挂在这上面 */
  position:relative;
}
/* ★ 收起态的关键：**把文字隐掉，只留图标** —— 52px 里塞中文会被逐字换行成
   「插/入/元/素」这种竖排乱码（第一版实测就是这个观感，比藏起来更糟）。
   下面这组规则在 .panel 上按「文字类元素」统一处理；
   注意必须排除 .tool / .ai-btn 这类「图标+文字同一节点」的按钮 ——
   它们靠 font-size:0 隐藏文字、再用 .k 把图标放大回来（Icon-font 常用手法）。 */
html[data-fs="on"] .ed__left .panel,
html[data-fs="on"] .ed__right .panel{
  padding:10px 6px;
}
html[data-fs="on"] .ed__left .panel__h h4,
html[data-fs="on"] .ed__right .panel__h h4,
html[data-fs="on"] .ed__left .panel__h button,
html[data-fs="on"] .ed__right #aiStatus,
html[data-fs="on"] .ed__right #aiBrief,
html[data-fs="on"] .ed__right #aiIndustry,
html[data-fs="on"] .ed__right #aiResult,
html[data-fs="on"] .ed__left .dkhead__ref{
  display:none;
}
/* ★ #props 的空态是一段长句 hint（「选中画布中的元素即可编辑属性；也可以在上方
   『插入元素』添加新内容。」）—— 52px 里会竖排成一列单字，比藏掉更难看。
   收起态一并隐掉；展开后（下面的 hover 段）会重新显示。
   注意：只隐 hint，**不隐真正的属性表单** —— 选中元素后 #props 里是 label+input，
   这些在收起态虽然挤，但仍是可交互的兜底内容，不能一起隐藏。 */
html[data-fs="on"] .ed__right #props > .hint{display:none;}
html[data-fs="on"] .ed__right .panel__h,
html[data-fs="on"] .ed__left .panel__h{
  justify-content:center;margin-bottom:8px;
}
html[data-fs="on"] .ed__right .panel__h::before,
html[data-fs="on"] .ed__left .panel__h::before{
  content:"";width:18px;height:2px;border-radius:2px;background:var(--line-strong);
}
/* 图标区改为单列竖排，图标居中 */
html[data-fs="on"] .ed__right .tools{
  grid-template-columns:1fr;gap:4px;
}
html[data-fs="on"] .ed__left .panel,
html[data-fs="on"] .ed__right .panel{overflow:hidden;}
html[data-fs="on"] .ed__right .tool,
html[data-fs="on"] .ed__right .ai-btn{
  display:grid;place-items:center;
  width:40px;height:34px;padding:0;margin:0 auto;
  font-size:0;                      /* 隐藏按钮上的文字 */
  justify-content:center;
}
html[data-fs="on"] .ed__right .tool .k,
html[data-fs="on"] .ed__right .ai-btn .k{
  font-size:15px;line-height:1;     /* 图标恢复尺寸 */
  margin:0;
}
/* 左栏：版面缩略图缩成小方块、图层条目只留色点 */
html[data-fs="on"] .ed__left #pageList,
html[data-fs="on"] .ed__left #layerList{
  max-width:40px;margin:0 auto;
}
html[data-fs="on"] .ed__left .pgthumb{margin-bottom:6px;}
/* 收起态整体加一条「可以拉开」的暗示：内侧细渐变 */
html[data-fs="on"] .ed__left::after,
html[data-fs="on"] .ed__right::after{
  content:"";position:absolute;top:0;bottom:0;width:3px;pointer-events:none;
  background:linear-gradient(180deg,transparent,var(--line),transparent);
}
html[data-fs="on"] .ed__left::after{right:0;}
html[data-fs="on"] .ed__right::after{left:0;}

@media(hover:hover){
  html[data-fs="on"] .ed__left:hover,
  html[data-fs="on"] .ed__left:focus-within,
  html[data-fs="on"] .ed__right:hover,
  html[data-fs="on"] .ed__right:focus-within{
    width:268px;
    box-shadow:var(--sh-pop);
  }
  /* ★★ 右栏必须**向左展开**（锚定右边、往画布方向长），不能原地向右长 ——
     右栏本身贴着视口右缘（实测 x≈1554 @1600 视口），原地加宽会直接长出屏幕，
     面板里的文字被裁掉一半（第一版实测就是这个现象：标签只看到「标题/分隔/页码」
     这类被切掉一半的残词）。
     做法：把右栏的定位基准从 static 改成「钉在父容器右侧」的绝对定位，
     用 right:0 锚定、宽度自己往左长；父级 .ed__body 已经是 position:relative。 */
  html[data-fs="on"] .ed__right:hover,
  html[data-fs="on"] .ed__right:focus-within{
    position:absolute;
    right:0;top:0;bottom:0;
  }
  /* 展开时把上面「收起态专用」的隐藏/居中规则全部还原 */
  html[data-fs="on"] .ed__left:hover .panel,
  html[data-fs="on"] .ed__left:focus-within .panel,
  html[data-fs="on"] .ed__right:hover .panel,
  html[data-fs="on"] .ed__right:focus-within .panel{padding:14px;}
  html[data-fs="on"] .ed__left:hover .panel__h h4,
  html[data-fs="on"] .ed__left:focus-within .panel__h h4,
  html[data-fs="on"] .ed__right:hover .panel__h h4,
  html[data-fs="on"] .ed__right:focus-within .panel__h h4{display:block;}
  html[data-fs="on"] .ed__left:hover .panel__h button,
  html[data-fs="on"] .ed__left:focus-within .panel__h button{display:inline-flex;}
  html[data-fs="on"] .ed__right:hover #aiStatus,
  html[data-fs="on"] .ed__right:focus-within #aiStatus{display:flex;}
  html[data-fs="on"] .ed__right:hover #aiBrief,
  html[data-fs="on"] .ed__right:focus-within #aiBrief,
  html[data-fs="on"] .ed__right:hover #aiIndustry,
  html[data-fs="on"] .ed__right:focus-within #aiIndustry{display:block;}
  html[data-fs="on"] .ed__right:hover #aiResult,
  html[data-fs="on"] .ed__right:focus-within #aiResult{display:block;}
  html[data-fs="on"] .ed__right:hover #props > .hint,
  html[data-fs="on"] .ed__right:focus-within #props > .hint{display:block;}
  html[data-fs="on"] .ed__right:hover .panel__h::before,
  html[data-fs="on"] .ed__right:focus-within .panel__h::before,
  html[data-fs="on"] .ed__left:hover .panel__h::before,
  html[data-fs="on"] .ed__left:focus-within .panel__h::before{display:none;}
  html[data-fs="on"] .ed__right:hover .tools,
  html[data-fs="on"] .ed__right:focus-within .tools{grid-template-columns:repeat(4,1fr);gap:6px;}
  html[data-fs="on"] .ed__right:hover .tool,
  html[data-fs="on"] .ed__right:hover .ai-btn,
  html[data-fs="on"] .ed__right:focus-within .tool,
  html[data-fs="on"] .ed__right:focus-within .ai-btn{
    display:flex;width:auto;height:auto;padding:8px 10px;font-size:inherit;margin:0;
  }
  html[data-fs="on"] .ed__right:hover .tool .k,
  html[data-fs="on"] .ed__right:focus-within .tool .k{font-size:15px;}
  html[data-fs="on"] .ed__left:hover #pageList,
  html[data-fs="on"] .ed__left:focus-within #pageList,
  html[data-fs="on"] .ed__left:hover #layerList,
  html[data-fs="on"] .ed__left:focus-within #layerList{max-width:none;}
}
/* 触摸设备没有 hover —— 全屏下直接把面板显示为完整宽度，可点可滚，
   总比「手指够不到任何属性」强。 */
@media(hover:none){
  html[data-fs="on"] .ed__body{grid-template-columns:minmax(0,1fr);}
  html[data-fs="on"] .ed__left,
  html[data-fs="on"] .ed__right{width:auto;}
}
/* 收窄画布留白：默认是 padding:34px 34px 80px，全屏时把省下的空间全给版面。
   ★ 底部 76px 不能一起收 —— 缩放条 .zoombar 是 absolute;bottom:16px 浮在画布上，
     留白不够会压住版面下缘。左右收到 20px 是因为标尺挂在 stage 的 -20px 处。 */
html[data-fs="on"] .ed__canvas{padding:14px 20px 76px;}

/* 编辑器版本历史条目 */
.ver-item{display:flex;gap:12px;align-items:center;transition:border-color .16s var(--ease),background .16s var(--ease);}
.ver-item:hover{border-color:var(--accent-line) !important;background:var(--accent-soft);}
.ver-item.is-cur{border-color:var(--accent) !important;background:var(--accent-soft);}
.ver-item__t{font-size:13px;font-weight:700;color:var(--ink);}
.ver-item__m{font-size:11.5px;color:var(--ink-3);margin-top:3px;}
.ver-item__prev{flex:0 0 74px;height:98px;border-radius:var(--r-sm);overflow:hidden;background:var(--paper-2);border:1px solid var(--line);}
.ver-item__prev .cover-render{width:74px !important;height:98px !important;}
.ver-item__prev .cover-render > div{transform-origin:top left;}

/* ============================================================================
   【扩展层】视觉风格 · 新增组件 · 全站精修（圆润 + 科技感）
   本段追加于原始设计系统之后，按「低耦合」原则只做三件事：
     1) 新增 token 与 8 套风格覆盖（不改动原 token 语义）
     2) 补齐新增组件的样式（模板市场统计/分页、编辑器字体面板/右键菜单、顶栏风格器）
     3) 对既有组件做圆润化与科技感精修（渐变、发光、微抬升、焦点环）
   ========================================================================== */

/* ---------------------------------------------------------------------------
   1. 扩展令牌
   --grad    主渐变（随风格变化）
   --glow    主色发光阴影
   --ring    焦点/选中光环
   --top-bg  顶栏毛玻璃底色
   --aur-*   页面极光背景（极淡，随风格变化）
   --------------------------------------------------------------------------- */
:root{
  --grad2:#1B3A8C;
  --grad:linear-gradient(135deg,var(--accent) 0%,var(--grad2) 100%);
  --glow:0 8px 24px -10px rgba(200,16,46,.5);
  --glow:0 8px 24px -10px color-mix(in srgb,var(--accent) 52%,transparent);
  --ring:0 0 0 3px rgba(200,16,46,.16);
  --ring:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent);
  --top-bg:rgba(246,245,242,.78);
  --aur-1:rgba(200,16,46,.055);
  --aur-2:rgba(27,58,140,.05);
  --aur-3:rgba(14,116,144,.04);
}
html[data-theme="dark"]{
  --top-bg:rgba(18,20,24,.78);
  --aur-1:rgba(242,64,92,.07);
  --aur-2:rgba(70,110,220,.07);
  --aur-3:rgba(20,160,190,.05);
}

/* ---------------------------------------------------------------------------
   2. 八套视觉风格
   选择器用 html[data-style=...]（特异度 0,1,1）确保同时压过 :root 与
   [data-theme="dark"]（均为 0,1,0），风格色在任何明暗模式下都稳定生效。
   --------------------------------------------------------------------------- */
html[data-style="editorial"]{
  --accent-base:#C8102E;
  --accent:#C8102E; --accent-2:#E23B52; --accent-soft:#FDECEE; --accent-line:#F5C9CF;
  --grad2:#1B3A8C; --aur-1:rgba(200,16,46,.055); --aur-2:rgba(27,58,140,.05); --aur-3:rgba(14,116,144,.04);
}
html[data-style="tech"]{
  --accent-base:#2563EB;
  --accent:#2563EB; --accent-2:#38BDF8; --accent-soft:#EAF2FE; --accent-line:#BFDBFE;
  --blue:#0E7490; --blue-2:#0891B2; --blue-soft:#E6F6FA;
  --grad2:#06B6D4; --aur-1:rgba(37,99,235,.07); --aur-2:rgba(6,182,212,.06); --aur-3:rgba(99,102,241,.05);
}
html[data-style="violet"]{
  --accent-base:#7C3AED;
  --accent:#7C3AED; --accent-2:#A78BFA; --accent-soft:#F5EEFE; --accent-line:#DDD6FE;
  --grad2:#EC4899; --aur-1:rgba(124,58,237,.07); --aur-2:rgba(236,72,153,.055); --aur-3:rgba(56,189,248,.05);
}
html[data-style="forest"]{
  --accent-base:#0F766E;
  --accent:#0F766E; --accent-2:#14B8A6; --accent-soft:#E6F6F2; --accent-line:#A7F3D0;
  --grad2:#65A30D; --aur-1:rgba(15,118,110,.07); --aur-2:rgba(101,163,13,.05); --aur-3:rgba(13,148,136,.05);
}
html[data-style="sunset"]{
  --accent-base:#C2410C;
  --accent:#C2410C; --accent-2:#FB923C; --accent-soft:#FEF1E7; --accent-line:#FED7AA;
  --grad2:#F59E0B; --aur-1:rgba(234,88,12,.07); --aur-2:rgba(245,158,11,.055); --aur-3:rgba(220,38,38,.04);
}
html[data-style="ink"]{
  --accent-base:#A16207;
  --accent:#A16207; --accent-2:#D4AF37; --accent-soft:#FAF3E0; --accent-line:#E7D4A3;
  --brand:#111827; --brand-2:#1F2937;
  --grad2:#111827; --aur-1:rgba(161,98,7,.06); --aur-2:rgba(17,24,39,.05); --aur-3:rgba(212,175,55,.05);
}
html[data-style="rose"]{
  --accent-base:#BE185D;
  --accent:#BE185D; --accent-2:#F472B6; --accent-soft:#FDEEF6; --accent-line:#FBCFE8;
  --grad2:#9333EA; --aur-1:rgba(219,39,119,.07); --aur-2:rgba(147,51,234,.055); --aur-3:rgba(244,114,182,.05);
}
html[data-style="mono"]{
  --accent-base:#374151;
  --accent:#374151; --accent-2:#6B7280; --accent-soft:#F3F4F6; --accent-line:#D1D5DB;
  --blue:#4B5563; --blue-2:#6B7280; --blue-soft:#F3F4F6;
  --teal:#52525B; --green:#4B5563; --amber:#6B7280; --violet:#52525B;
  --grad2:#6B7280; --aur-1:rgba(55,65,81,.05); --aur-2:rgba(107,114,128,.04); --aur-3:rgba(55,65,81,.03);
}
/* 深色模式下的令牌修正（选择器为 html[data-theme="dark"][data-style]，特异度 0,2,1，
   高于上面的 html[data-style=...] (0,1,1)，所以能安全地覆盖风格值）。

   必须走 --accent-base 中转的原因：若直接写 --accent:color-mix(...var(--accent)...)，
   就是「同一元素上的自引用」，CSS 会判定为循环并把该自定义属性置为无效，
   连带 --accent-soft / --accent-line 一起失效。
   原设计系统在深色下本会把报头红提亮（#C8102E -> #F2405C）以保住对比度，
   但风格块 (0,1,1) 压过了 [data-theme="dark"] (0,1,0)，这一步提亮被吃掉了，
   于是深色下 accent 退回浅色值：#C8102E 在 #121418 上仅 3.14:1、
   极简灰 #374151 更是只有 1.82:1（几乎不可见）。这里按 WCAG 4.5:1 统一提亮。 */
html[data-theme="dark"][data-style]{
  --accent:color-mix(in srgb, var(--accent-base) 66%, #fff);
  --accent-2:color-mix(in srgb, var(--accent-2) 80%, #fff);
  --accent-soft:color-mix(in srgb, var(--accent) 20%, transparent);
  --accent-line:color-mix(in srgb, var(--accent) 36%, transparent);
  --blue-soft:color-mix(in srgb, var(--blue) 22%, transparent);
}

/* ---------------------------------------------------------------------------
   2b. 深色维度：把「写死于风格系统之前的报头红」收归主色
   原深色块里有若干 rgba(242,64,92,...) 硬编码（侧栏选中、文本选区、未读悬停），
   它们诞生时 accent 就等于报头红，因此当时正确；但接入风格系统后，
   用户切到科技蓝/极光紫时这些位置会顽固地保持红色。统一改为跟随 --accent。
   --------------------------------------------------------------------------- */
html[data-theme="dark"] .nav__item.is-on{
  background:linear-gradient(90deg,
    color-mix(in srgb,var(--accent) 26%,transparent),
    color-mix(in srgb,var(--accent) 6%,transparent));
  color:#fff;
}
html[data-theme="dark"] ::selection{background:var(--accent-soft);color:var(--accent);}
html[data-theme="dark"] .notif__i.is-unread:hover{
  background:color-mix(in srgb,var(--accent) 22%,transparent);
}

/* 深色下主按钮的渐变还原：
   旧规则 [data-theme="dark"] .btn--primary 特异度是 (0,2,0)，
   高于本层 .btn--primary 的 (0,1,0)，会以 background:var(--accent) 把渐变换成实色。
   注意「更高的特异度永远优先，与书写顺序无关」，所以不能靠把本层规则往后挪来解决，
   必须同样用 html 前缀把特异度提到 (0,2,1)。 */
html[data-theme="dark"] .btn--primary{
  background:var(--grad-btn);border-color:transparent;color:#fff;
  box-shadow:var(--glow),inset 0 1px 0 rgba(255,255,255,.24);
}
html[data-theme="dark"] .btn--primary:hover{
  background:var(--grad-btn);border-color:transparent;
  filter:saturate(1.06) brightness(1.08);
  box-shadow:var(--glow),inset 0 1px 0 rgba(255,255,255,.32);
}
html[data-theme="dark"] .btn--primary:active{transform:translateY(0) scale(.985);filter:none;}

/* ---------------------------------------------------------------------------
   3. 全局精修
   --------------------------------------------------------------------------- */
body{
  background-color:var(--paper);
  background-image:
    radial-gradient(1200px 620px at 10% -10%, var(--aur-1), transparent 62%),
    radial-gradient(900px 520px at 94% 2%, var(--aur-2), transparent 58%),
    radial-gradient(760px 460px at 46% 108%, var(--aur-3), transparent 60%);
  background-attachment:fixed;
}
::selection{background:var(--accent-soft);color:var(--accent);}
*{scrollbar-width:thin;scrollbar-color:var(--line-strong) transparent;}
::-webkit-scrollbar{width:9px;height:9px;}
::-webkit-scrollbar-track{background:transparent;}
::-webkit-scrollbar-thumb{
  background:var(--line-strong);border-radius:99px;
  border:2px solid transparent;background-clip:content-box;
}
::-webkit-scrollbar-thumb:hover{background:var(--ink-4);background-clip:content-box;}
/* 键盘可达性：按钮 / 链接 / 自定义控件画主色描边。
   它们自带圆角，outline 会跟随圆角描出来，所以没问题。 */
button:focus-visible,a:focus-visible,[role="link"]:focus-visible,[tabindex]:focus-visible,
.switch input:focus-visible + .tr{
  outline:2px solid var(--accent);outline-offset:2px;
}
/* 原生勾选框/单选框：本身就是小方块，outline 贴合外形，保留 */
.chk input:focus-visible,.pick input:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
/* ★ v2.8.0：表单控件本身不再画 outline。
   根因：原生 input/select/textarea 的 border-radius 是 0，而它们几乎都被塞进一个
   「圆角外壳」里 —— 顶栏 .top__search 是 99px 胶囊、大厅 .hsearch 是 10px 圆角、
   模板市场 .inp 是 --r 圆角。outline 沿控件自身的直角矩形画出来，
   于是圆角容器内部多出一圈「方格线」（用户截图圈出三个搜索框）。
   解决：聚焦反馈一律交给容器（:focus-within 圆角描边 + 光环），
   控件自身的 border/background 保持透明衔接。 */
input:focus-visible,select:focus-visible,textarea:focus-visible{outline:none;}
/* 容器兜底：任何 .inp/.sel/.ta 之外被包起来的输入，父级带 .field 时也给一圈圆角光环 */
.field:focus-within > label{color:var(--accent);}

/* 主按钮：渐变 + 内高光 */
.btn--primary{
  background:var(--grad-btn);border-color:transparent;color:#fff;
  box-shadow:var(--sh-2),inset 0 1px 0 rgba(255,255,255,.24);
}
.btn--primary:hover{box-shadow:var(--glow),inset 0 1px 0 rgba(255,255,255,.3);}
/* 所有按钮统一「微抬升」手感 */
.btn{will-change:transform;}
.btn:hover{transform:translateY(-1px);box-shadow:var(--sh-2);}
.btn:active{transform:translateY(0) scale(.985);}
.btn--primary:active{transform:translateY(0) scale(.985);}

/* 输入控件焦点环 */
.inp:focus,.sel:focus,.ta:focus{border-color:var(--accent);box-shadow:var(--ring);outline:none;}

/* 分段控件：选中态跟随主色 */
.seg__i.is-on,.seg__b.is-on{
  background:var(--surface);color:var(--accent);box-shadow:var(--sh-1);
}
.seg--xs{padding:2px;border-radius:9px;}
.seg--xs .seg__i,.seg--xs .seg__b{padding:4px 10px;font-size:12px;border-radius:7px;}
.seg__b{
  padding:6px 13px;border-radius:7px;font-size:13px;font-weight:600;
  color:var(--ink-3);transition:.16s var(--ease);white-space:nowrap;cursor:pointer;
}

/* 顶栏：毛玻璃（★ v2.8.1 起底边不再画任何线） */
.top{background:var(--top-bg);}
/* ★★ v2.8.1：删除顶栏底部的「主色发丝线」。
   这条线历史上是 .top::after（left/right 内缩 --r-shell，1~1.5px 主色渐变）。
   v2.8.0 用户第一次说「多了一条线」，我误判成「阴影层与发丝线重叠」——
   只删了阴影里的 `0 1px 0` 硬层，还把发丝线加粗到 1.5px / opacity .42，
   于是本轮用户第二次说「还是有一条线」。
   本轮 A/B 像素取证（_tools/probe-v281.js，DPR=1 逐行扫描）：
     · 基线：y=58 一行 L=0.7417，左右邻居都是 0.987，落差 0.2457，
       横跨 1289/1600 列（= .top 宽 1320 内缩 18px×2），
       颜色随 --grad 走（红→蓝风格实测 rgb(205,179,198)，绿色风格偏绿
       —— 与用户截图里那条「偏绿的线」色相一致）；
     · `addStyleTag(".top::after{display:none}")` 后该行**完全消失** → 真凶确认。
   结论：顶栏与内容的分离只靠 --sh-top 投影，底边一条线都不要。
   注：`content:none` 而不是删掉整条规则 —— 便于将来一眼看出「这里曾有线、被有意关掉」。 */
.top::after{content:none;}

/* 面板标题：主色渐变小竖条 */
.panel__h h4{position:relative;padding-left:10px;}
.panel__h h4::before{
  content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:3px;height:13px;border-radius:2px;background:var(--grad);
}

/* 卡片 / 模板卡：圆润抬升 */
.tpl:hover{transform:translateY(-4px);box-shadow:var(--sh-4);border-color:var(--accent-line);}
.tpl{transition:transform .24s var(--ease),box-shadow .24s var(--ease),border-color .24s var(--ease);}

/* 编辑器工具按钮 */
.tool{transition:background .16s var(--ease),color .16s var(--ease),border-color .16s var(--ease),transform .12s var(--ease);}
.tool:hover{transform:translateY(-1px);border-color:var(--accent-line);}
.ebtn{transition:background .16s var(--ease),color .16s var(--ease),transform .12s var(--ease);}

/* 画布选中光环跟随主色（原实现硬编码为报头红） */
.el.is-sel{border-color:var(--accent);box-shadow:0 0 0 2px var(--ring);}
.el.is-multi{border-style:dashed;border-color:var(--accent);box-shadow:0 0 0 2px var(--ring);}

/* ---------------------------------------------------------------------------
   4. 模板市场：统计概览 / 结果条 / 分页器
   --------------------------------------------------------------------------- */
.tstats{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-bottom:20px;}
.tstat{
  position:relative;padding:15px 16px 14px 54px;border-radius:var(--r-lg);
  background:var(--surface);border:1px solid var(--line);box-shadow:var(--sh-1);
  overflow:hidden;transition:.22s var(--ease);
}
.tstat::after{
  content:"";position:absolute;left:0;right:0;top:0;height:3px;
  background:var(--grad);opacity:.8;
}
.tstat:hover{transform:translateY(-2px);box-shadow:var(--sh-3);border-color:var(--accent-line);}
.tstat__ic{
  position:absolute;left:14px;top:17px;width:28px;height:28px;border-radius:9px;
  display:grid;place-items:center;font-size:14px;font-weight:700;
  background:var(--accent-soft);color:var(--accent);
}
.tstat__v{
  font-size:24px;font-weight:800;letter-spacing:-.7px;line-height:1.15;
  color:var(--ink);font-variant-numeric:tabular-nums;
}
.tstat__k{font-size:12.5px;font-weight:700;color:var(--ink-2);margin-top:2px;}
.tstat__d{
  font-size:11px;color:var(--ink-4);margin-top:3px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.tstat--blue::after{background:linear-gradient(135deg,var(--blue),var(--blue-2));}
.tstat--blue .tstat__ic{background:var(--blue-soft);color:var(--blue);}
.tstat--green::after{background:linear-gradient(135deg,var(--green),#34D399);}
.tstat--green .tstat__ic{background:var(--green-soft);color:var(--green);}
.tstat--amber::after{background:linear-gradient(135deg,var(--amber),#F59E0B);}
.tstat--amber .tstat__ic{background:var(--amber-soft);color:var(--amber);}
@media(max-width:1080px){.tstats{grid-template-columns:1fr 1fr;}}
@media(max-width:640px){.tstats{grid-template-columns:1fr;}}

.tbarbar{
  display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;
  padding:11px 15px;border-radius:var(--r-md);
  background:var(--surface-2);border:1px solid var(--line);margin-bottom:16px;
}
.tbarbar__l{font-size:13px;color:var(--ink-3);}
.tbarbar__l b{color:var(--ink);font-weight:800;font-variant-numeric:tabular-nums;}
.tbarbar__r{display:flex;align-items:center;gap:10px;}
.tbarbar__lab{font-size:12px;font-weight:700;color:var(--ink-4);}

.pager{display:flex;align-items:center;justify-content:center;gap:6px;flex-wrap:wrap;margin:26px 0 8px;}
.pager__b{
  min-width:36px;height:36px;padding:0 11px;border-radius:var(--r-sm);
  border:1px solid var(--line);background:var(--surface);color:var(--ink-2);
  font-size:13px;font-weight:700;font-variant-numeric:tabular-nums;
  display:inline-flex;align-items:center;justify-content:center;
  transition:.16s var(--ease);cursor:pointer;
}
.pager__b:hover:not(:disabled){
  border-color:var(--accent);color:var(--accent);
  transform:translateY(-1px);box-shadow:var(--sh-2);
}
.pager__b.is-on{
  background:var(--grad-btn);border-color:transparent;color:#fff;box-shadow:var(--glow);
}
.pager__b:disabled{opacity:.38;cursor:not-allowed;}
.pager__gap{width:24px;text-align:center;color:var(--ink-4);font-weight:700;}

/* ---------------------------------------------------------------------------
   5. 编辑器：字体 / 艺术字面板
   --------------------------------------------------------------------------- */
.fsel{display:flex;flex-direction:column;gap:6px;}
.fsel__row{display:flex;align-items:center;gap:6px;}
.fsel__row .sel{flex:1;min-width:0;}
.fsel__badge{
  flex-shrink:0;font-size:10.5px;font-weight:800;letter-spacing:.3px;
  color:var(--accent);background:var(--accent-soft);
  border:1px solid var(--accent-line);border-radius:99px;padding:3px 8px;white-space:nowrap;
}
.fsel__pv{
  padding:9px 12px;border-radius:var(--r-sm);
  border:1px dashed var(--line-strong);background:var(--surface-2);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.4;
  transition:.16s var(--ease);
}
.fsel__pv:hover{border-style:solid;border-color:var(--accent-line);background:var(--surface);}
.art-hint{font-size:11.5px;color:var(--ink-4);padding:0 2px;line-height:1.6;}
input[type="color"]{
  width:100%;height:32px;padding:2px;border:1px solid var(--line);
  border-radius:var(--r-sm);background:var(--surface);cursor:pointer;
  transition:.16s var(--ease);
}
input[type="color"]:hover{border-color:var(--accent-line);box-shadow:var(--sh-1);}

/* ---------------------------------------------------------------------------
   6. 编辑器：画布右键菜单
   --------------------------------------------------------------------------- */
.ctx{
  position:fixed;z-index:9000;min-width:216px;max-width:278px;
  padding:6px;border-radius:var(--r-lg);
  background:var(--surface);border:1px solid var(--line);
  box-shadow:var(--sh-pop);
  animation:ctxIn .14s var(--ease);
}
@keyframes ctxIn{
  from{opacity:0;transform:translateY(-5px) scale(.985);}
  to{opacity:1;transform:none;}
}
.ctx__h{
  display:flex;align-items:center;gap:7px;
  padding:8px 10px;font-size:12px;font-weight:800;color:var(--ink-3);
  letter-spacing:.2px;border-bottom:1px solid var(--line-2);margin-bottom:5px;
  overflow:hidden;white-space:nowrap;text-overflow:ellipsis;
}
.ctx__h em{
  font-style:normal;font-size:10.5px;font-weight:800;color:var(--accent);
  background:var(--accent-soft);border-radius:99px;padding:2px 7px;flex-shrink:0;
}
.ctx__bk{
  width:22px;height:22px;border-radius:7px;flex-shrink:0;
  background:var(--surface-3);color:var(--ink-2);
  display:grid;place-items:center;font-size:14px;font-weight:800;
  cursor:pointer;transition:.14s var(--ease);
}
.ctx__bk:hover{background:var(--accent-soft);color:var(--accent);}
.ctx__g{padding:2px;}
.ctx__g--grid{display:grid;grid-template-columns:repeat(3,1fr);gap:4px;}
.ctx__g--grid .ctx__i{justify-content:center;padding:9px 5px;font-size:12.5px;gap:0;}
.ctx__g--grid .ctx__i kbd{display:none;}
.ctx__i{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  width:100%;padding:8px 10px;border-radius:var(--r-sm);
  font-size:13px;font-weight:600;color:var(--ink-2);text-align:left;
  transition:.13s var(--ease);cursor:pointer;
}
.ctx__i:hover{background:var(--accent-soft);color:var(--accent);}
.ctx__i:disabled,.ctx__i.is-dis{opacity:.4;cursor:not-allowed;background:none;}
.ctx__i kbd{
  font-size:10.5px;font-weight:600;color:var(--ink-4);
  background:var(--surface-3);border-radius:5px;padding:1.5px 5px;flex-shrink:0;
}
.ctx__i--sub .ctx__arw{display:flex;align-items:center;gap:5px;color:var(--ink-4);font-weight:800;}
.ctx__sep{height:1px;background:var(--line-2);margin:5px 9px;}
.ctx__scroll{max-height:324px;overflow-y:auto;padding:2px;overscroll-behavior:contain;}
.ctx__glabel{
  font-size:10.5px;font-weight:800;letter-spacing:.7px;color:var(--ink-4);
  padding:9px 10px 4px;text-transform:uppercase;
}
.ctx__f{
  display:flex;align-items:center;gap:9px;width:100%;
  padding:8px 10px;border-radius:var(--r-sm);
  font-size:13.5px;color:var(--ink);text-align:left;
  transition:.13s var(--ease);cursor:pointer;
}
.ctx__f:hover{background:var(--accent-soft);}
.ctx__f.is-on{background:var(--accent-soft);color:var(--accent);}
.ctx__f .ctx__demo{flex:0 0 auto;font-size:16px;line-height:1.3;}
.ctx__f .ctx__tip{flex:1;text-align:right;font-size:10.5px;color:var(--ink-4);}
.ctx__f .ctx__ck{margin-left:auto;flex:0 0 auto;color:var(--accent);font-weight:800;font-size:12px;}
.ctx__f.is-on .ctx__tip{color:var(--accent);opacity:.75;}

/* ---------------------------------------------------------------------------
   7. 顶栏：视觉风格选择器
   --------------------------------------------------------------------------- */
.styler{position:relative;display:flex;align-items:center;}
.styler__panel{
  position:absolute;right:0;top:calc(100% + 10px);width:330px;z-index:80;
  padding:14px;border-radius:var(--r-lg);
  background:var(--surface);border:1px solid var(--line);box-shadow:var(--sh-pop);
  opacity:0;visibility:hidden;transform:translateY(-8px) scale(.98);
  transform-origin:top right;transition:.2s var(--ease);
}
.styler.is-open .styler__panel{opacity:1;visibility:visible;transform:none;}
.styler__h{
  display:flex;align-items:center;gap:8px;
  font-size:13px;font-weight:800;color:var(--ink);margin-bottom:11px;
}
.styler__h em{
  font-style:normal;font-size:11px;font-weight:800;color:var(--accent);
  background:var(--accent-soft);border-radius:99px;padding:2px 8px;
}
.styler__grid{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:12px;}
.styler__c{
  position:relative;display:flex;flex-direction:column;gap:7px;padding:9px;
  border-radius:var(--r-md);border:1px solid var(--line);background:var(--surface-2);
  text-align:left;transition:.16s var(--ease);cursor:pointer;
}
.styler__c:hover{
  border-color:var(--accent-line);background:var(--surface);
  transform:translateY(-1px);box-shadow:var(--sh-2);
}
.styler__c.is-on{border-color:var(--accent);box-shadow:var(--ring);}
/* 色条：结构由内联 SVG 提供（fill 为表现属性，不受本表影响）；
   这里只负责尺寸与圆角，并保留 i 拼块写法作为兼容兜底 */
.styler__sw{display:block;width:100%;height:26px;flex:0 0 26px;min-height:26px;border-radius:7px;overflow:hidden;line-height:0;font-size:0;}
.styler__sw svg{display:block;width:100%;height:26px;}
.styler__sw i{display:block;height:26px;flex:1;min-width:0;}
.styler__sw i:nth-child(1){background-color:var(--a);}
.styler__sw i:nth-child(2){background-color:var(--b);}
.styler__sw i:nth-child(3){background-image:linear-gradient(135deg,var(--a),var(--b));}
.styler__tx{display:flex;flex-direction:column;gap:2px;min-width:0;flex:0 0 auto;}
.styler__n{
  font-size:12.5px;font-weight:700;color:var(--ink);
  line-height:1.35;flex:0 0 auto;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.styler__d{
  font-size:10.5px;color:var(--ink-4);
  line-height:1.4;flex:0 0 auto;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.styler__ck{
  position:absolute;right:8px;top:8px;width:16px;height:16px;border-radius:50%;
  background:var(--accent);color:#fff;font-size:10px;font-weight:800;
  display:grid;place-items:center;
}
.styler__f{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  padding-top:12px;border-top:1px solid var(--line-2);
}
.styler__fl{font-size:12px;font-weight:700;color:var(--ink-3);}

/* ============================================================================
   帮助中心（#/help）
   ========================================================================== */
.hc-head{display:flex;align-items:flex-end;gap:16px;margin-bottom:18px;}
.hc-h1{font-size:24px;font-weight:800;letter-spacing:-.02em;margin:0;line-height:1.2;}
.hc-sub{font-size:13px;color:var(--ink-3);margin-top:5px;max-width:70ch;line-height:1.65;}
.hc-head__r{margin-left:auto;flex-shrink:0;}
.hc-ver{
  display:inline-block;font-size:12px;font-weight:700;color:var(--accent);
  background:var(--accent-soft);border-radius:20px;padding:4px 12px;white-space:nowrap;
}

.hc-wrap{display:grid;grid-template-columns:266px minmax(0,1fr);gap:20px;align-items:start;}
.hc-side{
  position:sticky;top:calc(var(--top-h) + 16px);
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:12px;display:flex;flex-direction:column;
  max-height:calc(100vh - var(--top-h) - 48px);
}
.hc-search{margin-bottom:10px;}
.hc-toc{overflow-y:auto;flex:1;margin:0 -4px;padding:0 4px;overscroll-behavior:contain;}

.hc-sec{
  display:flex;align-items:center;gap:8px;width:100%;border:0;background:transparent;cursor:pointer;
  padding:9px 8px;border-radius:var(--r);font-size:13.5px;font-weight:600;color:var(--ink-2);
  font-family:var(--sans);text-align:left;line-height:1.4;
  transition:background .14s var(--ease),color .14s var(--ease);
}
.hc-sec:hover{background:var(--surface-3);color:var(--ink);}
.hc-sec:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--brand);}
.hc-sec__arw{
  font-size:12px;color:var(--ink-4);display:inline-block;flex-shrink:0;
  transition:transform .16s var(--ease);transform:rotate(0deg);
}
.hc-sec.is-open .hc-sec__arw{transform:rotate(90deg);}
.hc-sec__ic{width:16px;text-align:center;font-size:13px;color:var(--ink-4);flex-shrink:0;}
.hc-sec.is-cur .hc-sec__ic,.hc-sec.is-cur .hc-sec__n{color:var(--accent);}
.hc-sec__n{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.hc-sec__c{
  font-size:11px;font-weight:700;color:var(--ink-4);background:var(--surface-3);
  border-radius:9px;padding:1px 7px;flex-shrink:0;
}
.hc-sec.is-cur .hc-sec__c{background:var(--accent-soft);color:var(--accent);}

.hc-list{
  display:flex;flex-direction:column;gap:1px;
  margin:2px 0 6px 14px;padding-left:10px;border-left:1px solid var(--line-2);
}
.hc-item{
  display:flex;gap:8px;align-items:baseline;border:0;background:transparent;cursor:pointer;
  padding:6px 8px;border-radius:var(--r-sm);font-size:13px;color:var(--ink-2);
  font-family:var(--sans);text-align:left;line-height:1.45;
  transition:background .14s var(--ease),color .14s var(--ease);
}
.hc-item:hover{background:var(--surface-3);color:var(--ink);}
.hc-item:focus-visible{outline:none;box-shadow:inset 0 0 0 2px var(--brand);}
.hc-item.is-on{background:var(--accent-soft);color:var(--accent);font-weight:600;}
.hc-item__no{
  font-size:11px;color:var(--ink-4);flex-shrink:0;min-width:24px;
  font-variant-numeric:tabular-nums;
}
.hc-item.is-on .hc-item__no{color:var(--accent);}
.hc-item__t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}

.hc-main{min-width:0;}
.hc-art{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:26px 30px 28px;
}
.hc-art__top{display:flex;align-items:center;gap:12px;margin-bottom:14px;}
.hc-back{
  border:0;background:transparent;cursor:pointer;color:var(--ink-3);font-size:12.5px;
  font-family:var(--sans);padding:4px 9px;border-radius:var(--r-sm);
  transition:background .14s var(--ease),color .14s var(--ease);
}
.hc-back:hover{background:var(--surface-3);color:var(--ink);}
.hc-art__crumb{
  font-size:12px;color:var(--ink-4);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.hc-art h2{margin:0 0 12px;font-size:26px;font-weight:800;letter-spacing:-.02em;line-height:1.25;}
.hc-art__meta{
  display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  padding-bottom:18px;border-bottom:1px solid var(--line-2);margin-bottom:22px;
}
.hc-no{font-size:12px;font-weight:700;color:#fff;background:var(--accent);border-radius:6px;padding:2px 8px;}
.hc-tag{font-size:11.5px;color:var(--ink-3);background:var(--surface-3);border-radius:6px;padding:2px 8px;}
.hc-meta__sp{flex:1;}
.hc-meta__i{font-size:11.5px;color:var(--ink-4);white-space:nowrap;}

.hc-body{font-size:14.5px;line-height:1.85;color:var(--ink-2);}
.hc-body h3{
  font-size:18px;font-weight:750;color:var(--ink);margin:30px 0 12px;line-height:1.35;
  padding-left:11px;border-left:3px solid var(--accent);
}
.hc-body h3:first-child{margin-top:0;}
.hc-body h4{font-size:15px;font-weight:700;color:var(--ink);margin:22px 0 8px;}
.hc-body p{margin:0 0 14px;}
.hc-body ul,.hc-body ol{margin:0 0 16px;padding-left:22px;}
.hc-body ul{list-style:disc;}
.hc-body ol{list-style:decimal;}
.hc-body li{margin:6px 0;}
.hc-body strong{color:var(--ink);font-weight:700;}
.hc-body em{font-style:italic;}
.hc-body code{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,"Courier New",monospace;
  font-size:12.5px;background:var(--surface-3);border:1px solid var(--line);
  border-radius:5px;padding:1px 6px;color:var(--ink);white-space:nowrap;
}
.hc-note{
  margin:16px 0;padding:13px 16px;border-radius:var(--r);
  background:var(--accent-soft);border-left:3px solid var(--accent);
  font-size:13.5px;color:var(--ink-2);line-height:1.8;
}
.hc-note strong{color:var(--ink);}
.hc-tw{overflow-x:auto;margin:0 0 18px;-webkit-overflow-scrolling:touch;}
.hc-t{width:100%;border-collapse:collapse;font-size:13.5px;}
.hc-t th,.hc-t td{text-align:left;padding:9px 12px;border-bottom:1px solid var(--line-2);vertical-align:top;}
.hc-t th{
  font-size:11.5px;font-weight:700;color:var(--ink-3);letter-spacing:.03em;
  text-transform:uppercase;background:var(--surface-2);white-space:nowrap;
}
.hc-t tbody tr:hover{background:var(--surface-2);}
.hc-t tr:last-child td{border-bottom:0;}

.hc-pager{
  display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:30px;
  padding-top:20px;border-top:1px solid var(--line-2);
}
.hc-pg{
  display:flex;flex-direction:column;gap:3px;border:1px solid var(--line);
  background:var(--surface);border-radius:var(--r);padding:11px 14px;cursor:pointer;
  text-align:left;font-family:var(--sans);
  transition:border-color .16s var(--ease),background .16s var(--ease);
}
.hc-pg--r{text-align:right;align-items:flex-end;}
.hc-pg--off{border:0;background:transparent;cursor:default;padding:0;}
.hc-pg:not(.hc-pg--off):hover{border-color:var(--accent);background:var(--accent-soft);}
.hc-pg__k{font-size:11px;color:var(--ink-4);}
.hc-pg__t{font-size:13.5px;font-weight:600;color:var(--ink);}
.hc-foot{margin-top:18px;text-align:center;font-size:11.5px;color:var(--ink-4);line-height:1.7;}

@media(max-width:980px){
  .hc-wrap{grid-template-columns:1fr;gap:14px;}
  .hc-side{position:static;max-height:none;}
  .hc-toc{max-height:320px;}
  .hc-art{padding:20px 18px 24px;}
  .hc-art h2{font-size:22px;}
}
@media(max-width:560px){
  .hc-head{flex-direction:column;align-items:flex-start;gap:10px;}
  .hc-head__r{margin-left:0;}
  .hc-h1{font-size:20px;}
  .hc-body{font-size:14px;}
  .hc-body h3{font-size:16.5px;}
  .hc-pager{grid-template-columns:1fr;}
}
@media(max-width:620px){
  .styler__grid{grid-template-columns:1fr;}
}

/* 动效：尊重系统「减少动态效果」偏好 */
@media(prefers-reduced-motion:reduce){
  .tpl,.tstat,.btn,.pager__b,.styler__c,.styler__panel,.ctx{transition:none;animation:none;}
  .tpl:hover,.tstat:hover,.btn:hover,.pager__b:hover:not(:disabled),.styler__c:hover{transform:none;}
  .myhero__img,.myhero__cv,.myhero__glow,.myhero__spark,.myhero__dots i,.myhero__say,.myhero__sayT{animation:none;transition:none;}
}

/* ============================================================================
   报刊大厅 · 内联全文搜索框
   原先是一个「🔍 全文搜索」按钮，点击弹模态框输入；改为工具栏内直接输入，
   输入即搜（防抖）、回车立即搜、Esc 清空。
   ============================================================================ */
.hsearch{
  display:flex;align-items:center;gap:7px;height:38px;padding:0 10px 0 11px;
  min-width:258px;background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r);
  transition:border-color .18s var(--ease),box-shadow .18s var(--ease);
}
.hsearch:focus-within{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);}
.hsearch.is-active{border-color:var(--line-strong);}
.hsearch__ic{flex:0 0 auto;font-size:13px;line-height:1;opacity:.55;}
.hsearch__in{
  flex:1 1 auto;min-width:0;height:100%;border:0;background:transparent;outline:none;
  font:inherit;font-size:13.5px;color:var(--ink);-webkit-appearance:none;appearance:none;
}
.hsearch__in::placeholder{color:var(--ink-4);}
/* 统一用自绘清除按钮，屏蔽搜索框原生清除叉 */
.hsearch__in::-webkit-search-cancel-button,
.hsearch__in::-webkit-search-decoration{-webkit-appearance:none;appearance:none;}
.hsearch__n{flex:0 0 auto;font-size:11.5px;font-weight:700;color:var(--ink-3);white-space:nowrap;}
.hsearch__clr{
  flex:0 0 auto;width:20px;height:20px;padding:0;border:0;border-radius:50%;cursor:pointer;
  display:grid;place-items:center;font-size:11px;line-height:1;
  background:var(--surface-3);color:var(--ink-3);transition:.16s var(--ease);
}
.hsearch__clr:hover{background:var(--accent-soft);color:var(--accent);}
@media(max-width:640px){.hsearch{min-width:0;flex:1 1 100%;}}

/* ============================================================================
   我的报刊 · 左「创作能力」/ 右「我的刊物」两栏
   ============================================================================ */
/* 六张统计卡在整行里排开；共用 .stats 的 auto-fit 只够放 5 张，第 6 张会孤零零换行 */
#myStats{grid-template-columns:repeat(auto-fit,minmax(166px,1fr));}

.mypage{
  display:grid;grid-template-columns:394px minmax(0,1fr);
  gap:20px;align-items:start;margin-top:22px;
}
@media(max-width:1120px){.mypage{grid-template-columns:1fr;gap:16px;}}

/* ---------- 左栏：数字人舞台 ---------- */
/* ★ top 必须计入吸顶栏高度（--top-h），与帮助中心 .hc-side 同口径。
   只写 top:16px 时，卡片吸附后 top=16px，而吸顶栏 .top 高 60px、z-index:30，
   卡片顶部 0–44px 整段落在吸顶栏之下被盖住 —— 说话气泡「来看看你的创作能力吧」
   位于 stage 内 top:14px（卡片坐标 14–46px），会被几乎整块遮掉（实测气泡 31–67px，
   遮挡线 60px，仅漏出 7px）。故取 calc(var(--top-h) + 16px) = 76px。
   max-height + overflow-y:auto 是兜底：视口够高时不溢出、不出现滚动条；
   视口偏矮（< 76 + 卡片高）时卡片自身可滚，宁可内滚也不要丢掉底部按钮。 */
.myhero{
  position:sticky;top:calc(var(--top-h) + 16px);
  /* ★ 减去的量不是随意写的：
     滚到页面最底部时，sticky 卡会被 grid area 底部推着上移，此时卡片顶边 =
     区域底部(视口坐标) − 卡片高。区域底部距视口底正好是 body 的下内边距 60px，
     所以要让顶边仍 ≥ 吸顶栏的 76px，卡片高必须 ≤ 视口高 − 60 − 76。
     这里取 100vh − top-h − 76px 正是该上限（v2.7.0 把 2.5D 舞台加高后，
     卡片一度顶到 738px，滚到底时顶边掉到 32.5px，被 60px 的吸顶栏盖住）。 */
  max-height:calc(100vh - var(--top-h) - 76px);overflow:hidden;overflow-y:auto;
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-lg);box-shadow:var(--sh-1);
}
/* 堆叠布局下卡片在文档流里正常滚动，限高与内滚都要复位 */
@media(max-width:1120px){.myhero{position:static;max-height:none;overflow-y:hidden;}}
.myhero__stage{
  position:relative;height:340px;display:flex;align-items:flex-end;justify-content:center;
  padding-bottom:0;overflow:hidden;
  background:
    radial-gradient(120% 78% at 50% 4%,rgba(27,58,140,.13),transparent 62%),
    radial-gradient(90% 60% at 50% 100%,rgba(200,16,46,.07),transparent 60%),
    linear-gradient(180deg,var(--surface-2),var(--surface));
}
/* 地面光：让 2.5D 人物「落」在舞台上，而不是飘着 */
.myhero__stage::after{
  content:"";position:absolute;z-index:1;left:50%;bottom:0;width:228px;height:30px;margin-left:-114px;
  border-radius:50%;filter:blur(11px);pointer-events:none;
  background:radial-gradient(ellipse at center,rgba(27,58,140,.22),transparent 72%);
}
/* ★ 2.5D 背景大字（参考「超大背景字 + 人物 + 对话气泡」的能力介绍构图）
   压在人物身后（z-index:0 < 人像的 2）。
   大字落在头肩高度，两侧从轮廓外露出 —— 这是刻意的「字被人物压住」构图。
   字号必须够大才能露出来：88px × 3 字 = 264px，人像头部宽约 165px，
   两侧各能露出 ~50px；字号降到 60px 左右就会被人像完全盖住、等于白做。

   ★ 副标的落位踩过两次坑，最终放在【右上角】：
     ① 放大字下方 → 正好压在人物下巴，被脸和脖子切成一截一截；
     ② 放人物头顶之上居中 → 与左上角的对话气泡在水平方向撞车，
        气泡右边界 ≈178px、副标左边界 ≈163px，两块叠在一起（截图可见）。
     右上角与气泡分居两侧、互不侵占，中轴留给大字，构图也干净。 */
.myhero__bg{
  position:absolute;z-index:0;inset:0;
  pointer-events:none;-webkit-user-select:none;user-select:none;
}
/* 大字：距舞台顶 65px（正好落在人物顶边 68px 的头肩高度） */
.myhero__bgT{
  position:absolute;left:0;right:0;top:65px;text-align:center;
  font-family:var(--serif);font-size:88px;font-weight:900;line-height:1;letter-spacing:.01em;
  /* 文字用主色的浅混合：8 套风格下都跟着走，又不会抢人物的注意力。
     深浅取 38%→17% 的纵向渐变，比背景光晕深一档，否则在粉色底上会糊成一片 */
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--accent) 38%,var(--surface)) 0%,
    color-mix(in srgb,var(--accent) 17%,var(--surface)) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
/* 副标：右上角，与左上角气泡分居两侧 */
.myhero__bgS{
  position:absolute;right:14px;top:20px;text-align:right;
  font-size:10.5px;font-weight:700;font-style:normal;letter-spacing:.3em;
  color:color-mix(in srgb,var(--accent) 42%,var(--ink-5));
  white-space:nowrap;
}
/* ★ 高度必须写死 px（变量），不能用 height:100%：
   实测 height:100% 在 flex 居中容器里会退化成 auto → 图片按原始尺寸渲染，
   顶部被 overflow:hidden 裁掉，人物头像直接看不见。 */
.myhero__img{
  position:relative;z-index:2;display:block;
  height:272px;width:auto;max-width:100%;
  /* ★ v2.8.1：2.5D 数字人换成生成的半写实素材后，下缘是「腰部截断」。
     直接硬切会在卡片上留一条水平刀口，用遮罩把最后 15% 化进底色，
     人物就像从舞台里长出来（参考站那张也是同样的收尾手法）。
     遮罩只吃 alpha，不影响上面的浮动动画（transform 走另一条通道）。 */
  -webkit-mask-image:linear-gradient(180deg,#000 82%,rgba(0,0,0,.35) 95%,transparent 100%);
  mask-image:linear-gradient(180deg,#000 82%,rgba(0,0,0,.35) 95%,transparent 100%);
  animation:myFloat 5.4s ease-in-out infinite;will-change:transform;
  /* v2.8.2：动作素材接管时静态图要淡出，所以它需要一条 opacity 过渡 */
  transition:opacity .5s var(--ease);
}
/* ★ v2.8.2：人物动作序列（30 帧透明 WebP，canvas 播放）
   容器只做两件事：让静态图与 canvas 精确重叠、用一个变量统一两者尺寸。
   ★ 尺寸必须共用 --mh：静态图与 canvas 是两层，媒体查询里各自写死高度，
     迟早会改一处漏一处 —— 那时两层会错位，接管瞬间人物会「跳一下」。 */
.myhero__fig{
  position:relative;display:flex;align-items:flex-end;justify-content:center;
  --mh:272px;
}
.myhero__fig .myhero__img{height:var(--mh);}
/* canvas 与静态图同尺寸、同 mask、同浮动动画 —— 接管前后是同一套视觉，
   只有内容在动，用户不会察觉「换了一层」。
   居中用 left:50% + 负 margin-left，而不是 transform:translateX(-50%)：
   transform 被 myFloat 的 translateY 占着，用了会互相覆盖。 */
.myhero__cv{
  position:absolute;bottom:0;left:50%;z-index:2;
  height:var(--mh);width:calc(var(--mh) * .7625);margin-left:calc(var(--mh) * -.38125);
  opacity:0;pointer-events:none;transition:opacity .5s var(--ease);
  -webkit-mask-image:linear-gradient(180deg,#000 82%,rgba(0,0,0,.35) 95%,transparent 100%);
  mask-image:linear-gradient(180deg,#000 82%,rgba(0,0,0,.35) 95%,transparent 100%);
  animation:myFloat 5.4s ease-in-out infinite;
}
.myhero__cv.is-on{opacity:1;}
.myhero__img.is-off{opacity:0;}
/* 堆叠布局下舞台更宽，人物放大一点才不显空，背景大字同步放大。
   ★ 大字的 top 要跟着重算：单列时人物顶边 = 舞台高 452 − 人像高 360 = 92px，
     大字 116px 取 top:70 正好压在头肩高度。 */
@media(max-width:1120px){
  .myhero__stage{height:452px;}
  .myhero__img{height:360px;}
  /* ★ 动作层的高度也要跟着放大，否则单列布局下 canvas 比静态图小一圈 */
  .myhero__fig{--mh:360px;}
  .myhero__bgT{top:70px;font-size:116px;}
  .myhero__stage::after{width:268px;margin-left:-134px;}
}
.myhero__glow{
  position:absolute;z-index:1;left:50%;bottom:4%;width:214px;height:214px;margin-left:-107px;
  border-radius:50%;filter:blur(14px);
  background:radial-gradient(circle,rgba(27,58,140,.24),rgba(200,16,46,.11) 56%,transparent 74%);
  animation:myGlow 4.8s ease-in-out infinite;
}
/* 对话气泡：参考图里是「白底圆角 + 小尾巴 + 明显投影」，这里同步加重投影，
   让它在浅色舞台上「浮」起来，而不是贴片 */
.myhero__say{
  position:absolute;z-index:4;left:14px;top:16px;max-width:62%;
  display:flex;align-items:center;gap:7px;
  padding:9px 13px;border-radius:14px;
  background:var(--surface);border:1px solid var(--line);
  box-shadow:0 10px 24px -14px rgba(28,25,20,.42), 0 2px 5px -2px rgba(28,25,20,.14);
  font-size:12.5px;font-weight:700;line-height:1.45;color:var(--ink-2);
  animation:mySayIn .5s var(--ease) both;
}
.myhero__say::after{
  content:"";position:absolute;left:24px;bottom:-5.5px;width:10px;height:10px;
  background:var(--surface);border-right:1px solid var(--line);border-bottom:1px solid var(--line);
  transform:rotate(45deg);
}
.myhero__dots{display:inline-flex;align-items:center;gap:2.5px;flex:0 0 auto;}
/* ★ v2.8.1 提示语轮播：气泡里的文案每 4.2s 换一句（JS 见 renderMy 末尾）。
   换句走「先 .is-out 淡出 → 改 textContent → 去掉 .is-out 淡入」，
   而不是直接改文字 —— 直接改会「闪跳」，且行宽突变会让气泡抽一下。
   换句动画只动 opacity/transform，与 .myhero__say 自身的 mySayIn 入场动画互不冲突。 */
.myhero__sayT{display:inline-block;min-width:0;
  transition:opacity .22s var(--ease),transform .22s var(--ease);}
.myhero__say.is-out .myhero__sayT{opacity:0;transform:translateY(-4px);}
.myhero__dots i{
  display:block;width:3.5px;height:3.5px;border-radius:50%;background:var(--accent);
  animation:myDot 1.25s ease-in-out infinite;
}
.myhero__dots i:nth-child(2){animation-delay:.17s;}
.myhero__dots i:nth-child(3){animation-delay:.34s;}
.myhero__spark{position:absolute;z-index:3;font-size:12px;color:var(--accent);opacity:.45;
  animation:mySpark 4.2s ease-in-out infinite;pointer-events:none;}
/* 舞台加高到 400px 后百分比位置会整体上移，这里按新的高度重新落位；
   d 是新增的第 4 颗星 —— 参考图右上角有一颗明显的大星，需要「主次错落」而不是均匀铺 */
.myhero__spark--a{left:13%;top:15%;}
.myhero__spark--b{right:14%;top:25%;font-size:19px;animation-delay:.85s;}
.myhero__spark--c{right:9%;bottom:26%;font-size:10px;animation-delay:1.7s;}
.myhero__spark--d{left:10%;bottom:31%;font-size:11px;color:var(--grad2);animation-delay:2.5s;}

@keyframes myFloat{0%,100%{transform:translateY(0);}50%{transform:translateY(-7px);}}
@keyframes myGlow{0%,100%{transform:scale(1);opacity:.6;}50%{transform:scale(1.09);opacity:.9;}}
@keyframes mySpark{0%,100%{transform:translateY(0) scale(1);opacity:.35;}
  50%{transform:translateY(-11px) scale(1.18);opacity:.95;}}
@keyframes myDot{0%,60%,100%{opacity:.25;transform:translateY(0);}30%{opacity:1;transform:translateY(-2px);}}
@keyframes mySayIn{from{opacity:0;transform:translateY(6px) scale(.96);}to{opacity:1;transform:none;}}

/* ---------- 左栏：创作能力 ---------- */
.myhero__cap{border-top:1px solid var(--line);padding:14px 15px 15px;background:var(--surface);}
.myhero__capH{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin-bottom:11px;}
.myhero__capH span{font-size:13px;font-weight:800;letter-spacing:.01em;}
.myhero__capH em{font-size:11.5px;font-style:normal;color:var(--ink-4);}
.myhero__grid{display:grid;grid-template-columns:1fr 1fr;gap:9px;}
.cap{
  position:relative;display:flex;align-items:flex-start;gap:9px;
  padding:10px;text-align:left;font:inherit;color:inherit;cursor:pointer;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  transition:.18s var(--ease);
}
.cap:hover{border-color:var(--accent);box-shadow:0 5px 16px rgba(200,16,46,.10);transform:translateY(-1px);}
.cap:active{transform:translateY(0);}
.cap__ic{
  flex:0 0 auto;width:26px;height:26px;border-radius:8px;display:grid;place-items:center;
  background:var(--accent-soft);color:var(--accent);font-size:13px;font-weight:800;line-height:1;
}
.cap__b{min-width:0;display:block;}
.cap__t{display:block;font-size:12.5px;font-weight:800;line-height:1.35;}
.cap__d{display:block;margin-top:2px;font-size:11.5px;line-height:1.5;color:var(--ink-3);}
.cap__go{
  position:absolute;right:8px;top:8px;font-size:13px;color:var(--ink-4);
  opacity:0;transition:.18s var(--ease);
}
.cap:hover .cap__go{opacity:1;color:var(--accent);}
.myhero__chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:11px;}
.myhero__chip{
  padding:2.5px 8px;border-radius:99px;font-size:11px;font-weight:600;
  background:var(--surface-3);color:var(--ink-3);
}
.myhero__foot{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:12px;padding-top:11px;border-top:1px dashed var(--line);
}
.myhero__motto{font-size:11.5px;line-height:1.5;color:var(--ink-3);}
.myhero__motto b{font-weight:800;color:var(--accent);}
@media(max-width:420px){.myhero__grid{grid-template-columns:1fr;}}

/* ---------- 右栏：我的刊物 ---------- */
.mywork{min-width:0;}
.mywork .sec__h h3{font-size:15.5px;}

/* ---------- 我的刊物 · 底部统计与翻页 ----------
   统计口径 = 当前筛选条件下的全集（不是当前页），
   配色一律走 token，浅色 / 深色 / 8 套视觉风格自动适配。 */
.myfoot{
  margin-top:16px;padding:14px 15px 6px;
  background:var(--surface);border:1px solid var(--line);
  border-radius:var(--r-md);box-shadow:var(--sh-1);
}
.myfoot__top{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;}
.myfoot__l{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:13px;color:var(--ink-3);}
.myfoot__l b{color:var(--ink);font-weight:800;font-variant-numeric:tabular-nums;}
.myfoot__l .mfsp{flex:0 0 3px;width:3px;height:3px;border-radius:50%;background:var(--ink-5);}
.myfoot__r{display:flex;align-items:center;gap:10px;}
.myfoot__lab{font-size:12px;font-weight:700;color:var(--ink-4);}

/* 堆叠分布条：用 flex-grow 按条数分配，留间隙也不会撑破容器 */
.myfoot__dist{
  display:flex;gap:2px;height:8px;margin-top:13px;
  border-radius:999px;overflow:hidden;background:var(--surface-3);
}
.myfoot__dist i{display:block;height:100%;min-width:3px;transition:flex-grow .3s var(--ease);}

.myfoot__legend{
  display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;
  margin-top:10px;
}
.myfoot__lgs,.myfoot__sum{display:flex;align-items:center;gap:14px;flex-wrap:wrap;}
.myfoot__lg{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:650;color:var(--ink-3);}
.myfoot__lg b{color:var(--ink);font-weight:800;font-variant-numeric:tabular-nums;}
.myfoot__lg i{display:block;flex:0 0 8px;width:8px;height:8px;border-radius:50%;}
.myfoot__lg i.myfoot__sq{border-radius:2px;background:var(--ink-5);}
.myfoot__lg.is-zero{opacity:.5;}
.myfoot__sum{color:var(--ink-3);}
.myfoot .pager{margin:14px 0 8px;}
@media(max-width:560px){
  .myfoot__top{flex-direction:column;align-items:flex-start;}
  .myfoot__legend{flex-direction:column;align-items:flex-start;gap:8px;}
}

/* ==========================================================================
 *  团队协作 / 分享（v2.5.0 新增）
 *  说明：全部走既有 token（--surface / --ink / --line / --accent …），
 *        因此浅色、深色与 8 套视觉风格下自动适配，无需逐主题重复声明。
 * ======================================================================== */

/* ---------- 标签补充：有效 / 失效 ---------- */
.tag--on{background:var(--green-soft);color:var(--green);border-color:transparent;}
.tag--off{background:var(--surface-3);color:var(--ink-3);border-color:transparent;}

/* ---------- 团队协作页 ---------- */
.team{display:grid;grid-template-columns:296px minmax(0,1fr);gap:18px;align-items:start;}
.team__side{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:14px;
  /* ★ 吸顶偏移必须是「顶栏高度 + 间距」。
     原来写死 top:12px，而 .top 是 sticky 且高 60px、z-index:30 ——
     页面滚到底时实测「我的团队」面板顶边被顶栏盖住 48px，
     标题整行看不见（用户反馈「下拉的顶部文字被遮挡」）。
     再加 max-height + overflow 兜底：团队多了也不会长到溢出视口。 */
  position:sticky;top:calc(var(--top-h) + 14px);
  max-height:calc(100vh - var(--top-h) - 28px);overflow-y:auto;overflow-x:hidden;
}
.team__side .sec__h{margin-top:0;}
.team__i{
  display:flex;gap:10px;align-items:center;padding:10px;border-radius:var(--r);
  cursor:pointer;user-select:none;transition:background .16s var(--ease);
}
.team__i + .team__i{margin-top:4px;}
.team__i:hover{background:var(--surface-2);}
.team__i.is-on{background:var(--accent-soft);box-shadow:inset 0 0 0 1px var(--accent-line);}
.team__i:focus-visible{outline:2px solid var(--accent);outline-offset:1px;}
.team__ava{
  width:34px;height:34px;flex:0 0 34px;border-radius:10px;display:grid;place-items:center;
  background:var(--brand);color:var(--paper);font-size:15px;font-weight:700;
}
.team__n{display:block;font-weight:650;font-size:13.5px;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.team__m{display:block;font-size:11.5px;color:var(--ink-3);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.team__m .tag{font-size:10px;padding:1px 6px;}
.team__main{min-width:0;}

/* 成员表 */
.tmem{display:flex;flex-direction:column;gap:3px;}
.tmem__r{
  display:grid;grid-template-columns:minmax(140px,1.5fr) 84px 72px 110px 62px;
  gap:10px;align-items:center;padding:10px 13px;border-radius:var(--r);
  background:var(--surface);border:1px solid var(--line);
}
.tmem__r:hover{background:var(--surface-2);}
.tmem__r > span:last-child{text-align:right;}

/* 协作报刊卡片 */
.team__nps{display:grid;grid-template-columns:repeat(auto-fill,minmax(216px,1fr));gap:14px;}
.tnp{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  overflow:hidden;cursor:pointer;transition:transform .16s var(--ease),box-shadow .16s var(--ease);
}
.tnp:hover{transform:translateY(-2px);box-shadow:var(--sh-3);}
.tnp:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
.tnp__c{position:relative;aspect-ratio:3/4;background:var(--surface-3);overflow:hidden;display:grid;place-items:center;}
.tnp__c canvas,.tnp__c .cover-render{width:100%;height:100%;display:block;}
.tnp__c .np__ph{position:absolute;inset:0;display:grid;place-items:center;}
.tnp__b{padding:10px 12px 12px;}
.tnp__t{font-size:13px;font-weight:650;color:var(--ink);line-height:1.4;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.tnp__m{margin-top:6px;display:flex;gap:6px;align-items:center;flex-wrap:wrap;}

@media(max-width:1080px){
  .team{grid-template-columns:1fr;}
  .team__side{position:static;}
}
@media(max-width:900px){
  .tmem__r{grid-template-columns:1fr 1fr;row-gap:6px;}
  .tmem__r > span:last-child{text-align:left;}
}

/* ---------- 分享面板 ---------- */
.share__cfg{
  display:flex;gap:16px;align-items:flex-end;flex-wrap:wrap;
  padding:14px 16px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface-2);
}
.share__cfg .field{flex:1 1 280px;}
.share__list{display:flex;flex-direction:column;gap:10px;max-height:340px;overflow:auto;padding-right:2px;}
.share__i{
  display:flex;gap:14px;align-items:flex-start;padding:12px 14px;
  border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface);
}
.share__i.is-dead{opacity:.62;}
.share__qr{
  width:112px;height:112px;flex:0 0 112px;border:1px solid var(--line);
  border-radius:var(--r-sm);overflow:hidden;background:#fff;padding:4px;box-sizing:border-box;
}
.share__qr svg{display:block;width:100%;height:100%;}
.share__url{
  font-family:var(--mono,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace);
  font-size:12px;color:var(--ink-2);word-break:break-all;line-height:1.5;
}
.share__meta{margin-top:5px;display:flex;gap:8px;align-items:center;flex-wrap:wrap;}
.share__meta .tag{font-size:10.5px;padding:1px 7px;}

/* ---------- 单选卡片（归属团队） ---------- */
.picks{display:flex;flex-direction:column;gap:8px;}
.pick{display:flex;gap:10px;align-items:flex-start;padding:11px 13px;border:1px solid var(--line);
  border-radius:var(--r);cursor:pointer;transition:border-color .16s,background .16s;}
.pick:hover{background:var(--surface-2);}
.pick input{margin-top:3px;accent-color:var(--accent);}
.pick__b{display:flex;flex-direction:column;gap:3px;}
.pick__b strong{font-size:13.5px;color:var(--ink);}
.pick__b em{font-size:11.5px;color:var(--ink-3);font-style:normal;}
.pick:has(input:checked){border-color:var(--accent-line);background:var(--accent-soft);}

/* ---------- 候选用户列表 ---------- */
.cand{display:flex;flex-direction:column;gap:6px;max-height:320px;overflow:auto;}
.cand__i{display:flex;gap:10px;align-items:center;justify-content:space-between;
  padding:9px 12px;border:1px solid var(--line);border-radius:var(--r);background:var(--surface);}
.cand__i strong{font-size:13px;color:var(--ink);font-weight:650;}

/* ---------- 公开分享阅读页 ---------- */
.sh-badge{flex:0 0 auto;}
.sh-info .it{display:flex;gap:10px;align-items:flex-start;padding:8px 0;border-bottom:1px dashed var(--line-2);}
.sh-info .it:last-of-type{border-bottom:none;}
.sh-info .k{flex:0 0 76px;font-size:12px;color:var(--ink-3);}
.sh-info .v{font-size:12.5px;color:var(--ink);word-break:break-all;}

/* ---------- 深色下的二维码底板恒为白（保证可扫） ---------- */
html[data-theme="dark"] .share__qr{background:#fff;border-color:var(--line);}

/* ============================================================================
   ★★ v2.6.0 · 风格收口层 + 现代科技质感 ★★
   ----------------------------------------------------------------------------
   为什么要有这一层：此前「主操作色」用的是 --brand，而 --brand 在 8 套风格里
   恒为墨黑 #15171A。于是切换风格时，只有零星几个 --accent 元素在变，
   侧栏选中项、激活的分类 chip、分页器当前页、统计卡左色条……全是黑的 ——
   用户看到的就是「选了风格，但很多地方没跟着变」。
   本层做三件事：
     1) 品牌色阶「跟随风格」：--brand 由每套风格的 --accent-base 推导，
        并以 --rs（圆角尺度）让风格连「圆 / 方」的语言都不同；
     2) 把残留的硬编码色值收归令牌（卡片悬停遮罩、hero、登录页、阅读器…）；
     3) 注入现代科技质感：极光+网格底、毛玻璃、渐变发光按钮、卡片光晕、
        等宽数字、以及风格选择器的下滑展开与延迟收起。
   ========================================================================== */

/* ---------------------------------------------------------------------------
   1. 品牌色阶：跟随风格主色
   —— 通用公式一次覆盖 8 套风格；仅「墨韵黑金 / 极简灰」保持自身克制的近黑。
   --------------------------------------------------------------------------- */
:root{
  --brand-3:color-mix(in srgb, var(--brand) 74%, #fff);
  --brand-soft:color-mix(in srgb, var(--accent) 13%, transparent);
  /* --accent-grad：装饰用（色条 / 光晕 / 图标底），可以亮；
     --grad-btn   ：★ 承载文字用，必须两端都够深。
     原因：白字压在主色→辅色的糖果渐变上时，亮色那一端对比度只有 2~3:1
     （科技蓝辅色 #38BDF8 上白字仅 2.14:1，远低于 WCAG 4.5）。
     故按钮/选中态一律改用「深品牌色 → 主色」的渐变，两端都深，白字稳定达标，
     观感也更接近当下主流工具的「高级深色渐变」而不是糖果色。
     注意 --accent-deep ≠ --accent：深色模式下 --accent 会被整体提亮到 66% 白
     （见上文 html[data-theme="dark"][data-style] 块），提亮后的主色上压白字
     反而只有 2.7:1。所以承载文字的渐变必须走 --accent-deep 这个「深色安全」变体。 */
  --accent-grad:linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 100%);
  --accent-deep:var(--accent);
  --grad-btn:linear-gradient(135deg, var(--brand) 0%, var(--accent-deep) 100%);
  --card-glow:0 0 0 1px color-mix(in srgb, var(--accent) 24%, transparent),
              0 20px 44px -28px color-mix(in srgb, var(--accent) 66%, transparent);
  --scrim:color-mix(in srgb, #0A0C10 52%, transparent);
  --grid-line:color-mix(in srgb, var(--accent) 5%, transparent);
  --glass:color-mix(in srgb, var(--surface) 82%, transparent);
  --surface-warm:var(--surface);
}
html[data-style]{
  --brand:color-mix(in srgb, var(--accent-base) 88%, #0B0D10);
  --brand-2:var(--accent);
  --rs:1;
}
html[data-style="editorial"]{--rs:1;}
html[data-style="tech"]{--rs:1.16;}
html[data-style="violet"]{--rs:1.26;}
html[data-style="forest"]{--rs:1.04;}
html[data-style="sunset"]{--rs:1.36;}
html[data-style="rose"]{--rs:1.44;}
html[data-style="ink"]{--rs:.55;}
html[data-style="mono"]{--rs:.8;}
/* 两套「无彩色 / 黑金」风格保持近黑主色，不走彩色公式 */
html[data-style="ink"]{--brand:#1B1E24;--brand-2:#2B3039;}
html[data-style="mono"]{--brand:#2F3742;--brand-2:#414A57;}
html[data-theme="dark"][data-style]{
  --brand:color-mix(in srgb, var(--accent-base) 60%, #101318);
  --brand-2:color-mix(in srgb, var(--accent-base) 76%, #101318);
  --brand-3:color-mix(in srgb, var(--accent-base) 86%, #fff);
  --brand-soft:color-mix(in srgb, var(--accent) 20%, transparent);
  --glass:color-mix(in srgb, var(--surface) 74%, transparent);
  --grid-line:color-mix(in srgb, var(--accent) 7%, transparent);
  /* 深色下 --accent 已被提亮，直接拿它做「承载文字」的渐变会让白字掉到 2.7:1；
     这里按 --accent-base 重新压深一档，作为白字的底板。 */
  --accent-deep:color-mix(in srgb, var(--accent-base, var(--accent)) 62%, #101318);
}
html[data-theme="dark"][data-style="ink"]{--brand:#2A2F38;--brand-2:#3A414C;}
html[data-theme="dark"][data-style="mono"]{--brand:#4A5361;--brand-2:#5C6674;}

/* ---------------------------------------------------------------------------
   ★ v2.8.0 · 浅色 / 深色 = 两套不同的「色系」
   用户反馈：「风格选择，浅色和深色显示的色系一样，请调整增加浅色和深色不同显示风格」。
   原来的深色只做了一件事 —— 把 --accent 提亮（color-mix(accent-base 66%, #fff)）。
   色相照搬浅色、次级色照搬浅色、底色是纯中性 #121418，
   于是「换到深色」只等于「同一套配色调暗」，观感上没有第二套设计。

   这里给 8 套风格各配一组夜间色系：
     ① 底色带该风格色相的低饱和深调（--paper / --surface 三档），
        让整页在深色下就带上风格气质，而不是一片死灰；
     ② 描边跟着底色一起偏色（否则中性灰线压在有色深底上会「发脏」）；
     ③ 次级色 --grad2 换成互补的夜色调 —— 它决定 Hero 幻灯、渐变按钮、
        极光的第二段，是「一眼看出色系变了」最直接的抓手。

   选择器 (0,2,1) 与上面的深色令牌块同级，写在后面即可覆盖；
   注意这里**不写** --brand / --brand-2，避免压掉 ink / mono 的黑金与灰阶主色。
   --------------------------------------------------------------------------- */
html[data-theme="dark"][data-style="editorial"]{
  --paper:#171013; --paper-2:#120C0F; --surface:#1E171B; --surface-2:#261D22; --surface-3:#302630;
  --line:#342830; --line-2:#2A2026; --line-strong:#463740;
  --grad2:#B07A22;  /* 浅色是墨蓝 #1B3A8C，夜间换成暗金 —— 朱砂 + 金，夜读编辑部 */
  --aur-1:rgba(242,64,92,.11); --aur-2:rgba(176,122,34,.09); --aur-3:rgba(190,24,93,.06);
}
html[data-theme="dark"][data-style="tech"]{
  --paper:#0E1220; --paper-2:#0A0E19; --surface:#151A2B; --surface-2:#1C2338; --surface-3:#252D46;
  --line:#262E48; --line-2:#1E2539; --line-strong:#364160;
  --grad2:#7C5CFF;  /* 浅色是青 #06B6D4，夜间换成电紫 —— 蓝 + 紫，更夜、更电子 */
  --aur-1:rgba(59,130,246,.13); --aur-2:rgba(124,92,255,.11); --aur-3:rgba(34,211,238,.07);
}
html[data-theme="dark"][data-style="violet"]{
  --paper:#120E1E; --paper-2:#0D0A17; --surface:#1A1530; --surface-2:#221B3D; --surface-3:#2C244C;
  --line:#2C2448; --line-2:#231C3A; --line-strong:#3D3260;
  --grad2:#22D3EE;  /* 浅色是玫粉 #EC4899，夜间换成冰青 —— 紫 + 冰青，极光倒过来 */
  --aur-1:rgba(139,92,246,.14); --aur-2:rgba(34,211,238,.10); --aur-3:rgba(236,72,153,.07);
}
html[data-theme="dark"][data-style="forest"]{
  --paper:#0C1512; --paper-2:#08100E; --surface:#13201B; --surface-2:#192A23; --surface-3:#21352C;
  --line:#22372E; --line-2:#1A2B24; --line-strong:#2F4A3E;
  --grad2:#C08A2E;  /* 浅色是草绿 #65A30D，夜间换成暖金 —— 墨绿 + 金，像老铜 */
  --aur-1:rgba(20,184,166,.12); --aur-2:rgba(192,138,46,.09); --aur-3:rgba(101,163,13,.07);
}
html[data-theme="dark"][data-style="sunset"]{
  --paper:#170F0A; --paper-2:#110B07; --surface:#22160E; --surface-2:#2C1D12; --surface-3:#392617;
  --line:#3A2716; --line-2:#2E1F11; --line-strong:#50361F;
  --grad2:#E11D48;  /* 浅色是琥珀 #F59E0B，夜间换成玫红 —— 余烬 + 夜玫 */
  --aur-1:rgba(251,146,60,.13); --aur-2:rgba(225,29,72,.10); --aur-3:rgba(245,158,11,.08);
}
html[data-theme="dark"][data-style="ink"]{
  --paper:#141210; --paper-2:#0F0E0C; --surface:#1C1916; --surface-2:#24201C; --surface-3:#2F2A24;
  --line:#322C24; --line-2:#28231C; --line-strong:#453D31;
  --grad2:#C89B3C;  /* 浅色是近黑 #111827，夜间换成赤金 —— 黑底描金 */
  --aur-1:rgba(200,155,60,.12); --aur-2:rgba(120,90,30,.09); --aur-3:rgba(212,175,55,.06);
}
html[data-theme="dark"][data-style="rose"]{
  --paper:#170E14; --paper-2:#110A0F; --surface:#22141D; --surface-2:#2C1A26; --surface-3:#382131;
  --line:#36212F; --line-2:#2B1A26; --line-strong:#4A2E40;
  --grad2:#38BDF8;  /* 浅色是紫 #9333EA，夜间换成天青 —— 干玫瑰 + 夜色 */
  --aur-1:rgba(244,114,182,.12); --aur-2:rgba(56,189,248,.09); --aur-3:rgba(219,39,119,.07);
}
html[data-theme="dark"][data-style="mono"]{
  --paper:#111214; --paper-2:#0C0D0F; --surface:#181A1D; --surface-2:#1F2226; --surface-3:#282C31;
  --line:#2A2E33; --line-2:#22252A; --line-strong:#3A4046;
  --grad2:#8296B8;  /* 纯灰体系也带一点石板蓝，避免「只是变暗」 */
  --aur-1:rgba(130,150,184,.09); --aur-2:rgba(107,114,128,.07); --aur-3:rgba(148,163,184,.05);
}

/* ---------------------------------------------------------------------------
   2. 现代科技质感 · 页面底
   极光（更饱和一档）+ 极淡的主色科技网格；网格让整页有「工程感」。
   --------------------------------------------------------------------------- */
body{
  background-image:
    radial-gradient(1200px 620px at 10% -10%, var(--aur-1), transparent 62%),
    radial-gradient(900px 520px at 94% 2%, var(--aur-2), transparent 58%),
    radial-gradient(760px 460px at 46% 108%, var(--aur-3), transparent 60%),
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size:auto, auto, auto, 34px 34px, 34px 34px;
  background-attachment:fixed;
  background-color:var(--paper);
}
body.reading{background-image:none;}

/* ---------------------------------------------------------------------------
   3. 现代科技质感 · 顶栏毛玻璃
   --------------------------------------------------------------------------- */
.top{
  background:var(--glass);
  -webkit-backdrop-filter:blur(22px) saturate(1.8);
  backdrop-filter:blur(22px) saturate(1.8);
  /* 浮层化之后三边描边都去掉：只留阴影。
     留着左右边框会和圆角打架（直线边框 + 圆弧转角 = 两端冒尖）。
     ★ v2.8.0：这里原本还有一层 `0 1px 0 color-mix(--line 70%)`，去掉了。
     ★ v2.8.1：`.top::after` 那条主色发丝线关掉了。
     ★★ v2.8.1 二次修复：这里原本还有第二层阴影
        `0 12px 30px -26px color-mix(in srgb, var(--accent) 46%, transparent)`，
        它就是用户两次反馈「还是有一条线」的真正残留 ——
        几何上 spread -26px 把 60px 高的顶栏缩成 **8px 高的细条**，
        再 blur 30px，于是贴着顶栏下沿成了一条**带主色的水平窄带**。
        _tools/zoom-topbar.js + 逐行 RGB 取证（风格 = forest 绿主色）：
          基线      y60 rgb(211.8,215.6,212.1) → 绿通道比红/蓝各高 3.8 → **偏绿**
          `addStyleTag(".top{box-shadow:var(--sh-top)!important}")` 后
                    y60 rgb(221.4,221.1,217.3) → 回到页面底色的中性暖灰
        而用户第一次反馈时我就注意到「那条线偏绿」—— 与这里的色相一致。
        结论：顶栏下沿只保留中性 `--sh-top` 一层投影，**不要任何带主色/细条状的层**。 */
  border-color:transparent;
  box-shadow:var(--sh-top);
}
.top__t{letter-spacing:-.3px;}

/* ---------------------------------------------------------------------------
   4. 现代科技质感 · 按钮与交互件
   --------------------------------------------------------------------------- */
/* 渐变主按钮：底色可横向流动 + 悬停发光 + 内高光 */
.btn--primary,.btn--accent,.pager__b.is-on,.tsearch__go{
  background-size:180% 100%;background-position:0% 50%;
  transition:background-position .55s var(--ease),box-shadow .2s var(--ease),
             transform .14s var(--ease),filter .2s var(--ease);
}
.btn--primary:hover,.btn--accent:hover,.pager__b.is-on:hover{background-position:100% 50%;}
.btn--primary:disabled,.btn--accent:disabled{background-position:0% 50%;}
.btn--primary{background-image:var(--grad-btn);}
.btn--accent{background-image:var(--grad-btn);background-color:var(--accent);
  box-shadow:0 8px 20px -12px color-mix(in srgb, var(--accent) 88%, transparent),inset 0 1px 0 rgba(255,255,255,.22);}
.btn--accent:hover{filter:saturate(1.05) brightness(1.05);
  box-shadow:var(--glow),inset 0 1px 0 rgba(255,255,255,.3);}
.btn--accent:active{transform:translateY(0) scale(.985);filter:none;}

/* 侧栏选中项：渐变底 + 左侧主色光条 + 呼吸光晕 */
.nav__item{position:relative;}
.nav__item.is-on{
  background:linear-gradient(100deg,
    color-mix(in srgb, var(--brand) 96%, transparent),
    color-mix(in srgb, var(--brand-2) 78%, transparent));
  box-shadow:0 10px 22px -14px color-mix(in srgb, var(--brand) 92%, transparent),
             inset 0 1px 0 rgba(255,255,255,.16);
  animation:navGlow 4.6s ease-in-out infinite;
}
.nav__item.is-on::before{
  content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);
  width:3px;height:18px;border-radius:0 3px 3px 0;background:#fff;opacity:.9;
}
@keyframes navGlow{
  0%,100%{box-shadow:0 10px 22px -14px color-mix(in srgb, var(--brand) 92%, transparent),inset 0 1px 0 rgba(255,255,255,.16);}
  50%{box-shadow:0 12px 26px -12px color-mix(in srgb, var(--accent) 78%, transparent),inset 0 1px 0 rgba(255,255,255,.22);}
}
html[data-nav="mini"] .nav__item.is-on::before{display:none;}

/* 分类 chip / 分段控件 / 分页 / 调色板：选中态统一走主色渐变 */
.cat{background:var(--surface);}
.cat:hover{border-color:var(--accent-line);color:var(--accent);background:var(--accent-soft);}
.cat.is-on{
  background:var(--grad-btn);border-color:transparent;color:#fff;
  box-shadow:0 10px 22px -14px color-mix(in srgb, var(--accent) 90%, transparent);
}
.cat.is-on .n{opacity:.82;}
.tpl-pager .pg.is-on,.pow button.is-on{background:var(--grad-btn);border-color:transparent;
  box-shadow:0 8px 18px -12px color-mix(in srgb, var(--accent) 90%, transparent);}
.pager__b.is-on{background-image:var(--grad-btn);}
.seg{background:color-mix(in srgb, var(--surface-3) 78%, transparent);}
.seg__i.is-on,.seg__b.is-on{color:var(--accent);box-shadow:var(--sh-1),0 0 0 1px var(--accent-line) inset;}
.switch input:checked + .tr{background:var(--accent-grad);}
.chk input,.pick input{accent-color:var(--accent);}

/* 统计卡：顶部渐变色条 + 主色光晕 */
.tile::after{background:var(--grad);width:3px;opacity:1;}
.tile:hover{box-shadow:var(--card-glow);transform:translateY(-3px);border-color:var(--accent-line);}
.bar__fill{background:var(--grad);}
.prog i{background:var(--grad);}

/* 卡片悬停：主色描边 + 光晕（原来是中性描边，切风格无感知） */
.np:hover,.tpl:hover,.tstat:hover,.card:hover,.tnp:hover{border-color:var(--accent-line);}
.np:hover{box-shadow:var(--card-glow);}
.tpl:hover{box-shadow:var(--card-glow);}

/* ---------------------------------------------------------------------------
   5. 「没跟随风格」的具体位置 · 逐项收口
   --------------------------------------------------------------------------- */
/* ★ 5.1 报刊 / 模板卡片悬停：由「着色遮罩」改为「边框突出」
   v2.6.0 时这里曾是「品牌色 → 近黑」的着色渐变（为让悬停也跟着风格走），
   但用户明确要求：鼠标移上不要出现渐变色，只要边框突出显示就行。
   于是遮罩层背景一律置为透明，风格跟随改由「边框色 + 光环 + 投影」承担 ——
   三者都取自 --accent，8 套风格下依然两两不同，v2.6.0 的跟随性没有丢。 */
.np__ov,.tpl__ov{background:none;}
.np:hover,.tpl:hover{
  border-color:var(--accent);
  box-shadow:
    0 0 0 2px var(--accent-soft),
    0 16px 32px -20px color-mix(in srgb, var(--accent) 60%, transparent);
}
/* 遮罩没了以后，按钮是唯一压在封面上的元素，必须自带白底 + 投影 */
.np__ov .btn,.tpl__ov .btn{
  background:rgba(255,255,255,.96);border-color:transparent;color:#15171A;
  box-shadow:0 10px 22px -10px rgba(15,17,20,.5), 0 2px 6px -2px rgba(15,17,20,.28);
}
.np__ov .btn:hover,.tpl__ov .btn:hover{background:#fff;transform:translateY(-1px);}
.np__ov .btn--primary,.np__ov .btn--accent,.tpl__ov .btn--primary,.tpl__ov .btn--accent{
  background-image:var(--grad-btn);background-color:var(--accent);color:#fff;
  /* ★ 去掉遮罩后按钮直接压在封面上，而封面色可能正好也是主色
     （模板卡就是一整块纯色封面）→ 加一圈半透明白描边，
     保证在任何底色上都能看清按钮的边界。 */
  box-shadow:0 10px 22px -12px color-mix(in srgb, var(--accent) 92%, transparent),
             0 0 0 2px rgba(255,255,255,.6);
}
.np:hover .np__cover img,.np:hover .np__cover .cover-render{transform:scale(1.035);}
.np__cover .cover-render{transition:transform .45s var(--ease);}

/* 5.2 Hero 轮播：三张幻灯的主色由风格决定，不再写死蓝/红/墨蓝 */
.hero{background:#0C0E12;}
.hero__slide::before{
  background:
    radial-gradient(120% 150% at 4% 0%, color-mix(in srgb, var(--accent) 42%, transparent), transparent 62%),
    radial-gradient(90% 120% at 96% 108%, color-mix(in srgb, var(--grad2) 34%, transparent), transparent 66%),
    linear-gradient(103deg, color-mix(in srgb, var(--accent) 58%, #0C0E12) 0%, #0C0E12 76%);
}
.hero__slide:nth-child(2)::before{
  background:
    radial-gradient(120% 150% at 4% 0%, color-mix(in srgb, var(--grad2) 44%, transparent), transparent 62%),
    radial-gradient(90% 120% at 96% 108%, color-mix(in srgb, var(--accent) 30%, transparent), transparent 66%),
    linear-gradient(103deg, color-mix(in srgb, var(--grad2) 58%, #0C0E12) 0%, #0C0E12 76%);
}
.hero__slide:nth-child(3)::before{
  background:
    radial-gradient(120% 150% at 4% 0%, color-mix(in srgb, var(--accent-2) 40%, transparent), transparent 62%),
    radial-gradient(90% 120% at 96% 108%, color-mix(in srgb, var(--brand) 46%, transparent), transparent 66%),
    linear-gradient(103deg, color-mix(in srgb, var(--accent-2) 46%, #0C0E12) 0%, #0C0E12 78%);
}
.hero__slide::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(var(--grid-line) 1px, transparent 1px) 0 0/34px 34px,
             linear-gradient(90deg, var(--grid-line) 1px, transparent 1px) 0 0/34px 34px;
  opacity:.5;mask-image:linear-gradient(100deg,#000,transparent 68%);
  -webkit-mask-image:linear-gradient(100deg,#000,transparent 68%);
}
.hero__slide > *{position:relative;z-index:2;}
.hero__cover{box-shadow:0 30px 60px -22px rgba(0,0,0,.8),0 0 0 1px rgba(255,255,255,.14);}
.hero__dot.is-on{background:var(--accent-2);}
.hero__nav button:hover{background:color-mix(in srgb, var(--accent) 62%, transparent);}

/* 5.3 报刊占位封面：主色微染，避免一片死灰 */
.np__ph{
  width:100%;height:100%;display:grid;place-items:center;padding:20px;text-align:center;color:var(--ink-3);
  background:
    radial-gradient(120% 90% at 50% 0%, var(--brand-soft), transparent 68%),
    linear-gradient(180deg, var(--surface-2), var(--surface-3));
}
.np__ph .ic{color:var(--accent);opacity:.42;}

/* 5.4 通知 / 提示 / 差异条：硬编码粉、米黄改为主色与语义色的 color-mix */
.notif__i.is-unread{background:var(--accent-soft);}
.notif__i.is-unread:hover{background:color-mix(in srgb, var(--accent) 20%, transparent);}
.note--info{background:var(--blue-soft);border-color:color-mix(in srgb, var(--blue) 26%, transparent);color:var(--blue);}
.note--warn{background:var(--amber-soft);border-color:color-mix(in srgb, var(--amber) 30%, transparent);color:var(--amber);}
.note--ok{background:var(--green-soft);border-color:color-mix(in srgb, var(--green) 28%, transparent);color:var(--green);}
.dl.chg{background:var(--amber-soft);border-color:color-mix(in srgb, var(--amber) 30%, transparent);color:var(--amber);}
.btn--ok:hover{background:color-mix(in srgb, var(--green) 18%, transparent);}
.hc-note{background:var(--accent-soft);border-left-color:var(--accent);}
.empty .ic{background:var(--accent-soft);color:var(--accent);}

/* 5.5 遮罩层：跟随主色（深色下不会翻成白） */
.mask{background:var(--scrim);}
.scrim{background:var(--scrim);}

/* 5.6 登录页：左侧品牌墙由「写死的红/蓝光斑」改为主色光斑 */
.auth__brand{
  background:linear-gradient(158deg,
    color-mix(in srgb, var(--brand) 22%, #14171C) 0%,
    #0C0E12 58%,
    color-mix(in srgb, var(--brand) 12%, #0C0E12) 100%);
}
.auth__brand::before{background:radial-gradient(circle, color-mix(in srgb, var(--accent) 34%, transparent), transparent 66%);}
.auth__brand::after{background:radial-gradient(circle, color-mix(in srgb, var(--grad2) 26%, transparent), transparent 68%);}
.auth__hero h1 em{color:color-mix(in srgb, var(--accent) 62%, #fff);}
.auth__logo .mk,.side__brand .mk{background-image:var(--grad-btn);background-color:var(--accent);box-shadow:var(--glow);}
.auth__rule{background:var(--accent-grad);width:64px;}
.auth__panel{background:transparent;}

/* 5.7 阅读器：主色氛围光
   ★★ v2.8.1 二次修复 —— 这段原本把阅读器的底色与顶栏**写死**成
   `.rd{background:#0C0E12;}` 与 `.rd__top{background:color-mix(in srgb,#101318 86%,transparent);}`。
   它们排在第 1142 行 `.rd{background:var(--rd-bg)}` **之后**，特异度相同 → 靠位置把令牌压掉了。
   后果：用户在「🎨 背景」里选了暖白/米黄/护眼/浅灰，色板打勾、localStorage 也写了、
   body 的 computed 背景色也对了，**可整页看上去还是深色** —— 因为真正铺满屏幕的是 `.rd`。
   验收也因此假过一次：断言量的是 body 的背景色，量错了元素。
   现在这里只保留**新增**的底部光晕，其余颜色一律回到 body.reading 的 --rd-* 变量组。 */
.rd__main{
  background:
    var(--rd-tex),
    radial-gradient(1000px 560px at 50% -8%, var(--rd-glow), transparent 68%),
    radial-gradient(700px 420px at 50% 108%, color-mix(in srgb, var(--grad2) 12%, transparent), transparent 70%);
}
.catalog__i.is-on{background:color-mix(in srgb, var(--accent) 24%, transparent);box-shadow:inset 0 0 0 1px var(--accent-line);}
.pgbar i{background:var(--accent-grad);}

/* 5.8 我的报刊左栏舞台 / 光晕：主色化 */
.myhero__stage{
  background:
    radial-gradient(120% 78% at 50% 4%, color-mix(in srgb, var(--accent) 13%, transparent), transparent 62%),
    radial-gradient(90% 60% at 50% 100%, color-mix(in srgb, var(--grad2) 9%, transparent), transparent 60%),
    linear-gradient(180deg, var(--surface-2), var(--surface));
}
.myhero__glow{background:radial-gradient(circle, color-mix(in srgb, var(--accent) 30%, transparent), color-mix(in srgb, var(--grad2) 14%, transparent) 56%, transparent 74%);}
.myhero__say{border-color:var(--accent-line);}
/* 深色下 --surface 本身很暗，大字沿用浅色那套混合会糊成一片黑，
   单独把主色比例提上去：仍是低对比装饰字，但能看清是「智刊云」 */
html[data-theme="dark"] .myhero__bgT{
  background:linear-gradient(180deg,
    color-mix(in srgb, var(--accent) 54%, var(--surface)) 0%,
    color-mix(in srgb, var(--accent) 30%, var(--surface)) 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
}
/* 地面光同样跟随风格（基础层写的是蓝色常量） */
.myhero__stage::after{background:radial-gradient(ellipse at center, color-mix(in srgb, var(--accent) 26%, transparent), transparent 72%);}
.cap:hover{border-color:var(--accent);box-shadow:0 6px 18px -8px color-mix(in srgb, var(--accent) 34%, transparent);}
.cap__ic{background:var(--accent-soft);color:var(--accent);}
.team__ava{background:var(--grad-btn);color:#fff;}

/* 5.9 编辑器：功能区保持中性深色（设计画布需要稳定），
   只把「主操作 / 选中态」跟随风格，并补一条主色发丝线。 */
.ed__top{position:relative;}
.ed__top::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;
  background:var(--grad);opacity:.34;pointer-events:none;
}
.ebtn--go{background-image:var(--grad-btn);background-color:var(--accent);border-color:transparent;}
.ebtn--go:hover{background-image:var(--grad-btn);filter:brightness(1.08);border-color:transparent;}
.el:hover{border-color:color-mix(in srgb, var(--accent) 42%, transparent);}
.ed__canvas{
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--accent) 4%, transparent) 1px, transparent 1px) 0 0/22px 22px,
    linear-gradient(0deg, color-mix(in srgb, var(--accent) 4%, transparent) 1px, transparent 1px) 0 0/22px 22px,
    var(--paper-2);
}
.zoombar{background:var(--glass);backdrop-filter:blur(14px) saturate(1.6);}

/* 5.10 提示条 / 统计尾色：去掉写死的浅色尾，改用 color-mix */
.tstat--green::after{background:linear-gradient(135deg, var(--green), color-mix(in srgb, var(--green) 62%, #fff));}
.tstat--amber::after{background:linear-gradient(135deg, var(--amber), color-mix(in srgb, var(--amber) 62%, #fff));}
.tstat--blue::after{background:linear-gradient(135deg, var(--blue), var(--blue-2));}

/* 5.11 Toast：中性深底 + 主色微染，避免每次都是同一种黑 */
.toast{
  background:linear-gradient(135deg,
    color-mix(in srgb, var(--accent) 34%, #12141A) 0%, #12141A 62%);
  box-shadow:var(--sh-4),0 0 0 1px rgba(255,255,255,.06) inset;
  backdrop-filter:blur(10px);
}

/* 5.12 数字统一等宽，统计/分页/价格不跳动 */
.tile__n,.tstat__v,.donut__c .n,.myfoot__l b,.pager__b,.tbarbar__l b,.hsearch__n{
  font-variant-numeric:tabular-nums;
}

/* 5.13 滚动条与选区跟主色 */
::-webkit-scrollbar-thumb{background:color-mix(in srgb, var(--accent) 26%, var(--line-strong));}
::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb, var(--accent) 46%, var(--line-strong));}
*{scrollbar-color:color-mix(in srgb, var(--accent) 30%, var(--line-strong)) transparent;}

/* ---------------------------------------------------------------------------
   6. 顶栏搜索：搜索框 + 搜索按钮 + 联想下拉（左右分栏）
   --------------------------------------------------------------------------- */
.tsearch{position:relative;display:flex;align-items:center;gap:8px;}
.tsearch .top__search{
  display:flex;align-items:center;gap:8px;height:38px;padding:0 8px 0 13px;
  background:var(--surface);border:1px solid var(--line);border-radius:99px;
  box-shadow:var(--sh-1);width:min(330px,32vw);
  transition:border-color .18s var(--ease),box-shadow .18s var(--ease),background .18s var(--ease);
}
.tsearch .top__search:hover{border-color:var(--line-strong);}
.tsearch:focus-within .top__search{border-color:var(--accent);box-shadow:var(--ring);}
.tsearch__ic{flex:0 0 auto;font-size:13px;line-height:1;opacity:.5;}
.tsearch__in{
  flex:1 1 auto;min-width:0;height:100%;padding:0;border:0;background:transparent;outline:none;
  font:inherit;font-size:13.5px;color:var(--ink);-webkit-appearance:none;appearance:none;
}
.tsearch__in::placeholder{color:var(--ink-4);}
.tsearch__in::-webkit-search-cancel-button,
.tsearch__in::-webkit-search-decoration{-webkit-appearance:none;appearance:none;}
.tsearch__go{
  flex:0 0 auto;height:27px;padding:0 14px;border:0;border-radius:99px;cursor:pointer;
  background-image:var(--grad-btn);background-color:var(--accent);color:#fff;
  font-size:12.5px;font-weight:700;letter-spacing:.02em;
  box-shadow:0 6px 16px -10px color-mix(in srgb, var(--accent) 92%, transparent);
}
.tsug{
  position:absolute;right:0;top:calc(100% + 10px);z-index:95;
  width:min(566px,calc(100vw - 32px));
  padding:12px;border-radius:var(--r-lg);
  background:var(--glass);border:1px solid var(--line);box-shadow:var(--sh-pop);
  -webkit-backdrop-filter:blur(20px) saturate(1.7);backdrop-filter:blur(20px) saturate(1.7);
  animation:tsugIn .18s var(--ease);
}
.tsug[hidden]{display:none;}
@keyframes tsugIn{from{opacity:0;transform:translateY(-7px) scale(.988);}to{opacity:1;transform:none;}}

/* --------------------------------------------------------------------------
   窄屏兜底：顶栏两个下拉改为「贴视口」定位
   --------------------------------------------------------------------------
   为什么必须单独兜底：它们原本都是 position:absolute + right:0，
   锚点是「各自那个很窄的容器」而不是视口。窄屏时面板宽度接近视口宽，
   right:0 于是一路向左溢出屏幕 —— 实测 390px 下联想面板左边界到过 -101px，
   有一半内容点不到。改成 position:fixed 后 left/right 直接对到视口，
   顶部用吸顶栏高度令牌 --top-h 顶下去，全程不需要 JS 参与。
   （即使祖先 .top 因 backdrop-filter 成为固定定位的包含块，也依然合适：
     .top 通栏且没有 overflow:hidden，不会裁掉面板。） */
@media(max-width:900px){
  .tsug,.styler__panel,.notif{
    position:fixed;left:12px;right:12px;width:auto;
    top:calc(var(--top-h) + 8px);
    transform-origin:top center;
    /* 窄屏下面板正好压在有动效的 hero 上，而 hero 的动画会让 backdrop-filter
       的毛玻璃时有时无；这里索性把底色加到接近不透明，保证文字一定读得清。 */
    background:color-mix(in srgb, var(--surface) 96%, transparent);
  }
  /* ★ .notif 原本是 absolute;right:0 挂在铃铛上（宽 352px）。窄屏铃铛已靠右，
     面板左边缘会跑到视口外（实测 390 下 left=-6）→ 一并改 fixed 全宽。 */
  .notif{max-height:min(440px,calc(100vh - var(--top-h) - 28px));}
}

/* --------------------------------------------------------------------------
   毛玻璃兜底：backdrop-filter 不受支持时（老浏览器 / 部分 GPU 被禁用的环境）
   半透明面板会直接「透明」在内容上，字就糊了。此时把底提到不透明。
   -------------------------------------------------------------------------- */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))){
  .top{background:var(--surface);}
  .tsug,.styler__panel,.zoombar{background:var(--surface);}
}
.tsug__cols{display:grid;grid-template-columns:1fr 1fr;gap:0;}
.tsug__col{min-width:0;padding:0 4px;}
.tsug__col + .tsug__col{border-left:1px solid var(--line-2);margin-left:8px;padding-left:12px;}
.tsug__h{
  display:flex;align-items:center;gap:7px;padding:2px 8px 8px;
  font-size:10.5px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4);
}
.tsug__h em{
  font-style:normal;letter-spacing:0;color:var(--accent);background:var(--accent-soft);
  border-radius:99px;padding:1px 7px;font-size:10.5px;
}
.tsug__list{display:flex;flex-direction:column;gap:2px;max-height:302px;overflow-y:auto;overscroll-behavior:contain;}
.tsug__i{
  display:flex;align-items:center;gap:9px;width:100%;text-align:left;
  padding:8px 9px;border:0;border-radius:var(--r-sm);background:transparent;
  font:inherit;color:var(--ink);cursor:pointer;transition:.13s var(--ease);
}
.tsug__i:hover,.tsug__i.is-on{background:var(--accent-soft);}
.tsug__i.is-on .tsug__t{color:var(--accent);}
.tsug__ic{
  flex:0 0 auto;width:24px;height:24px;border-radius:8px;display:grid;place-items:center;
  font-size:12px;background:var(--surface-3);color:var(--ink-3);transition:.13s var(--ease);
}
.tsug__i.is-on .tsug__ic,.tsug__i:hover .tsug__ic{background-image:var(--grad-btn);color:#fff;}
.tsug__b{min-width:0;flex:1 1 auto;}
.tsug__t{
  display:block;font-size:13px;font-weight:650;line-height:1.35;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.tsug__t mark{background:transparent;color:var(--accent);font-weight:800;}
.tsug__m{
  display:block;font-size:11px;color:var(--ink-4);margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.tsug__py{flex:0 0 auto;font-family:var(--mono);font-size:10.5px;color:var(--ink-4);opacity:.8;}
.tsug__empty{padding:22px 8px;text-align:center;font-size:12.5px;color:var(--ink-4);line-height:1.7;}
.tsug__foot{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:10px;padding-top:10px;border-top:1px solid var(--line-2);
}
.tsug__hint{font-size:11px;color:var(--ink-4);}
.tsug__hint kbd{margin:0 2px;}
.tsug__all{
  border:0;border-radius:99px;padding:5px 13px;cursor:pointer;
  font-size:12px;font-weight:700;color:var(--accent);background:var(--accent-soft);
  transition:.15s var(--ease);
}
.tsug__all:hover{background-image:var(--grad-btn);color:#fff;}
@media(max-width:720px){
  .tsug__cols{grid-template-columns:1fr;}
  .tsug__col + .tsug__col{border-left:0;margin-left:0;padding-left:4px;padding-top:10px;border-top:1px solid var(--line-2);margin-top:8px;}
  .tsug__list{max-height:200px;}
}
/* 窄屏下原本把搜索框整体 display:none，这里改为「保留可用」。
     ★ 390px 的顶栏塞不下全部入口。实测过两轮：
       第一轮：搜索胶囊右边界 272、风格按钮左边界 233 —— 后者整个压在搜索框上
         39px（截图里调色盘图标压住 placeholder 末尾的「板」字）。根因是
         .top__search 宽度写死 min(184px,40vw)=156px，而外层 .tsearch 的
         min-width 只有 96px —— 空间不够时内部溢出容器之外，被后面的按钮盖住。
       第二轮（修完重叠后）：退出按钮右边界 408，页面被撑出 18px。
     两轮加起来说明：不是某一条规则写错，而是顶栏入口总数在 390px 下超载
     （☰ + 标题 + 搜索框 + 风格 + 主题 + 通知 + 退出 ≈ 408px）。
     对策：
       ① .tsearch 的最小宽度与搜索框同口径 —— 从机制上杜绝「内部溢出被覆盖」；
       ② 手机上收起两个入口：通知（#bellWrap）与顶栏主题（#themeBtn）。
          退出（#logoutBtn）必须留 —— 它是全站唯一的退出入口；
          主题在风格面板底部有等价的「明暗模式」胶囊，不丢功能。 */
@media(max-width:640px){
  #bellWrap,#themeBtn{display:none;}
  .top{gap:10px;}
  .tsearch{flex:1 1 auto;min-width:min(160px,41vw);}
  .tsearch .top__search{display:flex;width:100%;}
  .tsearch__go{padding:0 11px;}
}

/* ---------------------------------------------------------------------------
   7. 视觉风格选择器：悬停下滑展开 + 延迟收起 + 面板现代化
   --------------------------------------------------------------------------- */
.styler{position:relative;}
/* 桥接区：按钮与面板之间 10px 的空隙也算在 .styler 内，
   否则鼠标从按钮斜向滑进面板时会先触发一次 mouseleave，造成「闪一下」。 */
.styler::before{
  content:"";position:absolute;left:-10px;right:-10px;top:100%;height:16px;z-index:1;
}
#styleBtn{transition:background .16s var(--ease),color .16s var(--ease),transform .2s var(--ease);}
#styleBtn:hover,.styler.is-open #styleBtn{color:var(--accent);background:var(--accent-soft);}
.styler.is-open #styleBtn{transform:rotate(-12deg) scale(1.06);}
.styler__panel{
  top:calc(100% + 12px);width:356px;padding:16px;z-index:96;
  border-radius:var(--r-xl);
  background:var(--glass);border:1px solid var(--line);box-shadow:var(--sh-pop);
  -webkit-backdrop-filter:blur(22px) saturate(1.7);backdrop-filter:blur(22px) saturate(1.7);
  opacity:0;visibility:hidden;
  transform:translateY(-14px) scale(.97);
  transform-origin:top right;
  transition:opacity .2s var(--ease),transform .34s cubic-bezier(.22,1.1,.36,1),visibility .2s;
  will-change:transform,opacity;
}
.styler.is-open .styler__panel{opacity:1;visibility:visible;transform:none;}
/* 下滑展开：卡片依次落位，做出「抽下来」的节奏 */
.styler.is-open .styler__c{animation:stylerDrop .36s var(--ease) both;}
.styler.is-open .styler__c:nth-child(1){animation-delay:.02s;}
.styler.is-open .styler__c:nth-child(2){animation-delay:.05s;}
.styler.is-open .styler__c:nth-child(3){animation-delay:.08s;}
.styler.is-open .styler__c:nth-child(4){animation-delay:.11s;}
.styler.is-open .styler__c:nth-child(5){animation-delay:.14s;}
.styler.is-open .styler__c:nth-child(6){animation-delay:.17s;}
.styler.is-open .styler__c:nth-child(7){animation-delay:.2s;}
.styler.is-open .styler__c:nth-child(8){animation-delay:.23s;}
@keyframes stylerDrop{from{opacity:0;transform:translateY(-8px);}to{opacity:1;transform:none;}}
.styler__h{font-size:13px;letter-spacing:-.1px;}
.styler__h::before{
  content:"🎨";font-size:13px;filter:saturate(1.1);
}
.styler__h em{background-image:var(--grad-btn);color:#fff;}
.styler__c{border-radius:var(--r-md);background:color-mix(in srgb, var(--surface-2) 72%, transparent);}
.styler__c:hover{border-color:var(--accent-line);background:var(--surface);transform:translateY(-2px);box-shadow:var(--card-glow);}
.styler__c.is-on{border-color:var(--accent);background:var(--accent-soft);box-shadow:var(--ring);}
.styler__c.is-on::after{content:"";position:absolute;inset:-1px;border-radius:inherit;
  background:var(--accent-grad);opacity:.12;pointer-events:none;}
.styler__n{font-size:12.5px;}
.styler__sw{box-shadow:0 4px 12px -8px color-mix(in srgb, var(--accent) 80%, transparent);}
.styler__tip{
  display:flex;align-items:center;gap:6px;margin-top:10px;padding-top:10px;
  border-top:1px solid var(--line-2);font-size:11px;color:var(--ink-4);line-height:1.6;
}
.styler__tip .dot{width:5px;height:5px;border-radius:50%;background:var(--accent);flex:0 0 auto;
  box-shadow:0 0 0 3px var(--accent-soft);}
.styler__pd{display:flex;align-items:center;gap:6px;font-size:11px;}
.styler__pd button{
  border:0;border-radius:99px;padding:4px 10px;cursor:pointer;
  font-size:11.5px;font-weight:700;color:var(--ink-3);background:var(--surface-3);
  transition:.15s var(--ease);
}
.styler__pd button.is-on{background-image:var(--grad-btn);color:#fff;}

/* 尊重系统「减少动态效果」：本层新增的动效一并降级 */
@media(prefers-reduced-motion:reduce){
  .styler__panel,.styler__c,#styleBtn,.tsearch__go,.btn--primary,.btn--accent,.pager__b.is-on{
    animation:none !important;transition:none !important;transform:none !important;
  }
  .nav__item.is-on{animation:none;}
  .styler.is-open .styler__c{animation:none;}
}

/* ============================================================================
   ★ 风格面板窄屏收口（必须放在本文件**最末尾**）
   ---------------------------------------------------------------------------
   为什么放在这里、而不是跟上面的 max-width:560px 写在一起：
   `.styler__panel` 在本文件里被声明了**两次** —— 一次在 2064 行的基础层，
   一次在 3310 行的「悬停展开」层（那里写了 `width:356px; padding:16px`）。
   同特异度下**后写的胜出**，所以任何写在 3310 行之前的窄屏断点都会被它推翻 ——
   第一版把断点写在 2277 行，实测面板依旧是 `w=356 L=13 R=369`（完全没生效），
   就是因为被 3310 行盖掉了。
   → 收口规则一律写在文件末尾，天然获得最高优先级，不必靠 !important 或提特异度。

   缺陷本身：面板 `right:12px` 固定 + `width:356px` 固定 ⇒ 宽度不随视口收缩。
   实测 360px 视口下面板左边界 x=13、右边界 x=369 —— 比视口宽 9px，
   把整页 scrollWidth 撑到 369，表现就是「手机上打开风格面板后页面能左右拖」。
   （原来的写法是 `width:calc(100vw - 32px); right:-64px;` —— 用「视口减 32px」
     配一个硬编码的 -64px 右偏移，本质是在猜触发按钮坐在顶栏的第几个位置，
     顶栏增删一个图标就会失准。）
   ★ 改法：窄屏让面板**左右都锚定**（left+right 同时给值 + width:auto），
   宽度 = 视口 − 左右安全边距，由浏览器算，无论触发按钮挪到哪儿都不会越界。
   ========================================================================== */
@media(max-width:620px){
  .styler__panel{
    left:12px;
    right:12px;
    width:auto;
    max-width:none;
    transform-origin:top center;
  }
}

/* ============================================================================
   ★★ 顶栏收缩的真正收口（1080 档内）—— 写在文件末尾以取得最高优先级
   ---------------------------------------------------------------------------
   现象（实测）：`@900 /mp` 溢出 12px，而 `@900 /` 与 `@900 /me` 都正常。
   诊断数据（900px 视口，/mp「微信公众号接入」）：
     .top 宽 620、右边界 876，但 #logoutBtn 右边界 = 912   → 子项总和 > 容器
     #tsearch  w=288  shrink=999  minW=**auto** ← 关键
   ■ 为什么 shrink=999 也不收缩：flex 的收缩只把元素压到自己的 **min-width** 为止，
     而 flex 项默认 `min-width:auto`（下限 = 内容的最小内容宽）。搜索框里有一个
     `min(320px,34vw)=288px` 的 `.top__search` + 搜索按钮，最小内容宽就把 288 顶住了，
     于是「可无限让步」形同虚设。
   ■ 为什么只在 1080 档复发、而 820 档没事：820 档写了
     `.tsearch{min-width:min(190px,26vw)}`（显式压低下限，所以能收缩）；
     1080 档只把 `.top__search` 宽度从 34vw 收到 24vw，**没有动 `.tsearch` 的 min-width**，
     于是下限仍是 auto → 34vw 的内容宽（288px）继续顶着不放。
   ■ 修法：在 1080 档把 `.tsearch` 的 min-width 也一起收到同一口径。
     必须**同时**改两个地方，只改 `.top__search` 的宽度不解决「下限」问题：
       ① `.tsearch{min-width:min(220px,24vw)}` —— 让下限跟着宽度一起降；
       ② `min-width:0` 还不够：`.top__search` 是 `.tsearch` 的 flex 子项，
          它自己也要能压到 0，否则内部子项（输入框 + 搜索按钮）仍会顶住。
   ★ 这样任何 820–1080 的视口、任何长度标题都不再溢出，且 820 档的既有规则不受影响
     （两段都是 max-width，互不覆盖：更窄的视口由 820 段接管）。
   ========================================================================== */
@media(max-width:1080px) and (min-width:821px){
  .tsearch{min-width:min(220px,24vw);}
  .tsearch .top__search{min-width:0;}
  .tsearch__in{min-width:0;}
}

/* ============================================================================
   ★ 管理后台看板双列布局 .adcols（收口层，写在末尾保证优先级）
   ---------------------------------------------------------------------------
   出处：app.js 的 panelDash()。原先是内联
   `style="display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:18px;"`。
   ■ 两个独立缺陷叠在一起：
     ① 内联样式 → media query 完全失效（同 .detail--pc / .fgrid 的历史事故）；
     ② 右列硬编码 320px → 无论视口多窄都拒绝压缩。
   实测 320px 视口：这一层宽 320、右边界 352（视口只有 320）→
   把 .body 的 scrollWidth 撑到 352、整页横向滚动。
   340px 溢出 12px，360px 起才刚好装下 —— 所以缺陷只在极窄屏暴露，
   桌面与平板完全看不到，属于「手机上部分页面错乱」的典型来源。
   ■ 断点取 900px：右列装的是环形图（140px 圆 + 竖排图例，实测最小内容宽约 282px）
     与带缩略图的报刊行，双列需要 ≈ 320 + 18 + ~480 = 818px 才舒展；
     ≤900px 退单列，两栏上下堆叠，信息层级不变。
   ========================================================================== */
.adcols{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:18px;}
.adcols > *{min-width:0;}
@media(max-width:900px){
  .adcols{grid-template-columns:minmax(0,1fr);}
}

/* ============================================================================
   ★ 极窄屏（≤400px）顶栏保底 —— 写在文件末尾以取得最高优先级
   ---------------------------------------------------------------------------
   背景：顶栏是一排**不可压缩**的图标 + 一个带 min-width 下限的搜索框，
   子项固有宽之和在窄屏会超过容器。修复分两步：
     ① 让标题可压缩（.top__tbox flex:0 1 auto）—— 见上方 .top__tbox 注释；
     ② 让搜索框在更窄的视口**直接让位**（本段）。
   为什么 400px 这个阈值：实测 390/414 在「标题可压缩 + 搜索框 min(190px,26vw)」
   下已经能放下（389/414 均无溢出）；320/360 这类极窄屏则放不下 ——
   此时搜索框的最小宽（26vw≈83px）加上左右图标，仍会差约 20px。
   与其继续抠 1~2px 的间距，不如在极窄屏把搜索框收起：搜索在极窄屏本就不便输入，
   而侧栏/各页顶部都有自己的入口（大厅 .hsearch、模板市场 .tsearch 等）。
   ★ 注意 320px 是远低于本项目设计下限的宽度（iPhone SE 一代 / 老安卓），
     这里做的是「不产生横向滚动」的兜底，不承诺信息架构的完整性。
   ========================================================================== */
@media(max-width:400px){
  .top__sp{display:none;}
  .tsearch{display:none;}
  .top{gap:8px;}
  .top__tbox{flex:1 1 auto;min-width:0;max-width:none;}
  .top{padding:0 10px;}
}



/* ============================================================================
   ★ 顶栏 1081–1200px 档：填上 1080 断点与桌面宽屏之间的空档
   ---------------------------------------------------------------------------
   缺陷（实测取证，非推测）：vw=1152 时顶栏把整页撑出 1px 横向滚动，
     #logoutBtn right=1153.25 vs vw=1152；修掉它之后又发现 1081–1100 仍有
     22px / 3px 溢出 —— 两处是**同一个根因**的不同表现。
   顶栏内部宽度账（_diag-1152d/f 实测）：
     @1152  .top contentW=828  required=874.25  →  富余 46.25px
     @1081  .top contentW=757  required=824.3   →  富余 67.3px
   根因有两条，缺一不可：
     ① 真正生效的宽度规则是 `.tsearch .top__search{width:min(330px,32vw)}`
        （特异性 0,2,0），压过基准层 `.top__search{width:min(320px,34vw)}`（0,1,0）
        → 搜索框 = 330px；且 `.tsearch` 的 min-width 是 **auto**
        （flex 项默认下限 = 内容最小宽 = 330），于是基准层
        `.tsearch{flex-shrink:999}` 一点也兑现不了 —— 被自己的下限钉死。
     ② `.top__t` 与 `.top__crumb` 同处 `.top__tbox`，tbox 是 block 布局，
        两个 block 子元素各自占满父宽 ⇒ 父宽由更宽的那个决定。
        面包屑（「智刊云 / AI 辅助写作 · 多版本初稿 · 投稿与多平台分发」= 275.8px）
        一出现就把 .top__tbox 从 61px 撑到 276px（+215px）。
        既有 `max-width:1080px` 档正是靠 `display:none` 藏掉面包屑换来这段余量，
        1152/1081 落在该档之外 ⇒ 余量被收回 ⇒ 同类缺陷复现。
   修法（沿用 1080 档的同一策略 + 两处同口径收口）：
     ① `.top__crumb{display:none}`   —— 省约 215px（与 1080 档一致）
     ② `.tsearch` 下限与 `.tsearch .top__search` 宽度**同口径**压到 min(280px,28vw)
        —— 省约 50px。必须同时改两处：只改宽度不解决「下限」，只改下限会被
        更高特异性的宽度规则顶回去，两者同口径才不会出现「内部溢出被覆盖」。
     ③ `.tsearch__in{min-width:0}` —— 输入框自身放开下限，否则它把父级顶回去。
     ★ 不碰 `.top__tbox`（标题永不压缩，这是基准层明文的设计契约）。
   断点 1081 起与既有 `max-width:1080px` 无缝衔接；上界 1200 是实测边界，
   1201 起面包屑与 330px 搜索框都恢复。
   ========================================================================== */
@media(min-width:1081px) and (max-width:1200px){
  /* ① 收起面包屑 —— 与 821–1080 档同一策略，省约 215px */
  .top__crumb{display:none;}
  /* ② 下限必须显式给（不能留给 auto —— auto 的下限就是内容宽，收缩无从发生） */
  .tsearch{min-width:min(280px,28vw);}
  /* ③ 与下限同口径；写在 (0,2,0) 这条上才能盖过基准层的 width */
  .tsearch .top__search{width:min(280px,28vw);min-width:0;}
  /* ④ 输入框自身也放开下限 */
  .tsearch__in{min-width:0;}
  /* ⑤ 兜底：万一将来顶栏又加按钮，宁可标题自己省略，也不要撑破整页 */
  .top__t{overflow:hidden;text-overflow:ellipsis;}
}



/* ============================================================================
   ★ 顶栏兜底：让搜索框在【任何宽度】下都保留收缩能力
   ---------------------------------------------------------------------------
   背景（_diag-1152h/i/l 对照实验实测，非推测）：
   把站点名换成长文案（如 24 字）后，1280px 下整页溢出 46px，元凶是 #logoutBtn。
   顶栏内部账：.top clientW=998 / scrollW=1069 → 顶栏自身溢出 71px。
   逐个变量做对照实验的结果：
     A 现状                                  over = 46   （搜索框 w=330）
     B 全宽度压搜索框下限至 min(280px,28vw)   over =  0   （搜索框 w=280）★
     C 去掉 .top__tbox 的 max-width 上限      over = 46   （与 A 完全相同）
   ⇒ C 与 A 逐位相同，证明「给 .top__tbox 设上限」对溢出【毫无作用】，
     该写法已删除，不留无效代码。
   ⇒ 真正的约束是：`.tsearch` 的 min-width 计算值是 **auto**（= 内容最小宽 = 330），
     于是任何宽度下它都一点不让位；而它右侧还有 5 个图标按钮与 7 段 gap。
     只要文案足够长，缺口就一定落在最后一个按钮上。
   ★ 修法：把 1081–1200 档里已验证有效的「下限显式化」提为【全宽度生效】。
     这不改变任何正常观感：正常文案下搜索框右侧始终有富余，
     只有真的挤不下时它才会收缩（这正是基准层 .tsearch{flex-shrink:999}
     本来就想要的语义 —— 只是被 min-width:auto 挡住了）。
   ★ 与 821–1080 档的关系：该档把下限设成 min(220px,26vw)（821px 时 ≈197px），
     比本规则更紧。若不限定范围，本规则的特异性与它相同、又写在文件末尾，
     会把 197 顶回 230 —— 实测 821px 因此新出现 17px 溢出（已复现并修正）。
     ⇒ 本规则**只作用于 1081px 以上**，821–1080 交由该档自己管。
   ★ 为何不给 <=820px 也加同样的规则：该段既有档（`.tsearch{flex-grow:1;
     min-width:min(190px,26vw)}`）已经把下限压得比 280px 方案更紧
     （640px 时 166 vs 179、820px 时 190 vs 230）。虽然实测该段搜索框是被
     flex-grow 撑满的、下限并未起作用（所以加了也「看不出问题」），
     但抬高下限会在窄屏真正挤到时让搜索框更早放弃收缩 ⇒ 属于**潜在的新缺陷**。
     故这里**不引入**，避免「同一属性写两遍且值不同」的隐患。
   ========================================================================== */
@media(min-width:1081px){
  .tsearch{min-width:min(280px,28vw);}
  .tsearch .top__search{min-width:0;}
  .tsearch__in{min-width:0;}
}
.top__crumb{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
