/* 文献检索 · 亮灰拟态 (Neumorphism)
   拟态三要素：同色底 + 双向柔光阴影(左上亮/右下暗) + 低饱和强调色。
   凸起 = 卡片/按钮/标签；凹陷 = 输入框/列容器/开关；按下 = inset 反转阴影。 */

:root{
  --bg:#e6ebf2;
  --light:rgba(255,255,255,.92);   /* 左上高光 */
  --dark:rgba(163,177,198,.62);    /* 右下投影 */
  --dark-2:rgba(163,177,198,.85);  /* 按下时更重 */
  --txt:#3b4657;
  --txt-2:#6b7688;
  --txt-3:#98a2b3;
  --accent:#5b7cfa;
  --accent-soft:rgba(91,124,250,.14);
  --cnki:#6c5ce7;   /* 知网 */
  --wanfang:#0ea5a5;/* 万方 */
  --weipu:#e8833a;  /* 维普 */
  --oa:#2f9e57;     /* OA */
  --other:#8492a6;  /* 其他 */
  --danger:#e2564d;
  --r-lg:22px; --r-md:16px; --r-sm:11px;
  --sh-raise:-6px -6px 14px var(--light), 6px 6px 14px var(--dark);
  --sh-raise-sm:-3px -3px 7px var(--light), 3px 3px 7px var(--dark);
  --sh-press:inset -4px -4px 9px var(--light), inset 4px 4px 9px var(--dark);
  /* 整页限宽（2026-10-14 放宽）：从写死 1400px 提到 1760px，宽屏上把「文献 + 界面」
     铺开；两侧的 24px 边距由 .shell 的 padding 提供，窄屏下自动收缩到视口内。 */
  --page-w:1760px;
}

*{margin:0;padding:0;box-sizing:border-box}

body{
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB",Roboto,sans-serif;
  background:var(--bg); color:var(--txt);
  min-height:100vh; -webkit-font-smoothing:antialiased;
  line-height:1.5;
}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
mark{background:var(--accent-soft);color:var(--accent);border-radius:4px;padding:0 3px;font-weight:600}

/* 背景柔光，避免整页死板的纯色 */
.glow{position:fixed;border-radius:50%;filter:blur(80px);pointer-events:none;z-index:0}
.glow.g1{width:420px;height:420px;background:rgba(91,124,250,.10);top:-140px;left:-120px}
.glow.g2{width:380px;height:380px;background:rgba(232,131,58,.08);bottom:-130px;right:-110px}

.shell{position:relative;z-index:1;max-width:var(--page-w);margin:0 auto;padding:0 24px 60px}

/* ── 左上角标头 ──
   2026-10-01 改：原来是照搬「星格陨石」小程序的**玻璃** mini-header，
   用户看过实物后要求改成和搜索框一样的**凹陷拟态**（就是页面本来那套
   亮灰拟态的 --sh-press 凹槽），整站风格才统一。
   所以这里跟 .field 一样吃 var(--sh-press)，玻璃那套 blur / 半透明白底
   全部撤掉 —— 玻璃感只留给里面的卡片（用户明确说卡片保持原样）。 */
.mini-header{
  display:flex;align-items:center;gap:12px;
  width:fit-content;                 /* 贴左上角，不通栏 */
  margin:22px 0 6px;
  padding:0 20px 0 12px;
  height:52px;                       /* 和 .field 同高，两行看着齐 */
  border-radius:16px;                /* 和 .field 同圆角 */
  box-shadow:var(--sh-press);        /* 和 .field 同一个凹槽 */
  transition:box-shadow .18s;
}
.mh-icon{
  width:31px;height:31px;border-radius:10px;flex-shrink:0;
  background:linear-gradient(135deg,#8E7BFF,#5B3FE4);
  display:flex;align-items:center;justify-content:center;font-size:16px;
  box-shadow:var(--sh-raise-sm);
}
.mh-text{
  font-size:18px;font-weight:900;letter-spacing:1.5px;white-space:nowrap;
  font-family:"Avenir Next","Helvetica Neue",sans-serif;
  color:var(--txt);
}
/* 2026-10-02：.mh-ver（「全文定位」胶囊）的元素和样式都删了。
   留着死规则会让下一个人以为标头上还该有个版本/定位标记。 */

/* ── 通用凸起/凹陷 ── */
.raised{box-shadow:var(--sh-raise)}
.raised-sm{box-shadow:var(--sh-raise-sm)}
.inset{box-shadow:var(--sh-press)}

/* ── 搜索面板 ── */
/* ── 搜索面板 ──
   2026-10-01 改：原来是 max-width:900px 居中，比下面三列（1400px）窄一大截，
   左右两边各空出 250px，看起来像「上面一个小框、下面三个大框」。
   用户要求：**和下面三列一样宽，顶满，左边顶左、右边顶右** ——
   也就是和 .grid 用同一个宽度上限、同一个居中方式，两者左右边缘严格对齐。
   同宽之后搜索框本身仍然是凹槽（拟态），只是外框变宽了。 */
.search-panel{
  background:var(--bg); border-radius:var(--r-lg);
  padding:20px 22px 22px; box-shadow:var(--sh-raise);
  /* 和 .grid 同宽（都用 --page-w）+ margin auto。.shell 两侧已有 24px
     padding，所以实际内容宽 = 1760-48，.grid 也在同一个 .shell 里，
     两者天然同宽。写死同一个变量是为了以后改一处不会漏另一处。 */
  max-width:var(--page-w); margin:0 auto;
}

/* Tabs：胶囊凹陷槽 + 凸起选中块 */
.tabs{
  display:flex;gap:5px;padding:6px;border-radius:18px;
  box-shadow:var(--sh-press);margin-bottom:18px;
}
.tab{
  flex:1;padding:11px 6px;border-radius:13px;
  font-size:14px;font-weight:700;color:var(--txt-3);
  transition:all .22s cubic-bezier(.4,0,.2,1);
}
.tab:hover{color:var(--txt-2)}
.tab.active{
  background:var(--bg); color:var(--accent);
  box-shadow:var(--sh-raise-sm);
  transform:translateY(-1px);
}

/* ★ 2026-09-30 默认走知网之后, 两组 tab 必须一眼分得开。
   左边是真知网(联网、要等), 右边是本地库; 分隔竖线 + 字号差别,
   避免用户以为"本地·全文"才是主入口。 */
.tab-web{flex:0 0 auto;padding:11px 20px;font-size:15px}
.tab-web.active{color:var(--cnki)}
.tab-gap{
  flex:0 0 auto;width:1px;align-self:stretch;margin:4px 7px;
  background:var(--txt-3);opacity:.35;
}
.tab-local{flex:1;font-size:13.5px;font-weight:600}
.tabs-note{
  display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;
  margin:-8px 4px 14px;font-size:12.5px;color:var(--txt-3);
}
.tabs-note .tn-current{font-weight:700;color:var(--txt-2)}
.tabs-note .tn-hint{opacity:.85}
/* 知网守护进程实时状态（2026-10-11「busy_op 显式展示」）：后台轮询
   /api/webhealth，知网正在检索时亮「● 检」，空闲亮「● 闲」。 */
.tabs-note .tn-live{
  margin-left:auto;font-size:11.5px;font-weight:600;white-space:nowrap;
  color:var(--txt-3);display:none;
}
.tabs-note .tn-live.busy{color:var(--cnki, #e08a3c)}
.tabs-note .tn-live.idle{color:var(--txt-3)}

/* 搜索框：凹陷槽。右边没有「检索」按钮了 —— 回车或点下面那排维度芯片都触发。 */
.sbar{display:flex;gap:14px;align-items:center}
.field{
  flex:1;display:flex;align-items:center;gap:10px;
  border-radius:16px;padding:4px 18px;height:52px;
  box-shadow:var(--sh-press);
}
.field-icon{font-size:16px;opacity:.55;flex-shrink:0}
.field input{
  flex:1;border:none;outline:none;background:transparent;
  font-size:15px;color:var(--txt);height:100%;
}
.field input::placeholder{color:var(--txt-3)}
/* 聚焦时凹槽再深一点，模拟"按下去" */
.field:focus-within{box-shadow:inset -5px -5px 11px var(--light),inset 5px 5px 11px var(--dark-2)}

.btn{
  padding:14px 34px;border-radius:16px;font-size:15px;font-weight:700;
  transition:transform .12s,box-shadow .12s;
}
.btn.primary{
  color:#fff;
  background:linear-gradient(135deg,#6d8bff,#5b7cfa);
  box-shadow:-4px -4px 10px var(--light),5px 5px 12px var(--dark),inset 0 1px 0 rgba(255,255,255,.28);
}
.btn.primary:hover{transform:translateY(-1px)}
.btn.primary:active{transform:translateY(1px);box-shadow:inset 3px 3px 8px rgba(0,0,0,.18)}
.btn:disabled{opacity:.45;cursor:default;transform:none}

/* 热门 / 历史 */
/* 维度条：这排芯片**就是**检索按钮 —— 点哪个就按哪个维度搜、并且立刻变色。
   所以「点击搜索：」这个提示语要和芯片贴紧（gap 压到 6px），让人一眼看出
   「前面这行字 + 后面这些按钮是一组」，而不是两个独立的东西。 */
.dimbar{display:none;align-items:center;gap:6px;margin-top:14px;flex-wrap:wrap}
.dim-label{color:var(--accent)}
.chip.dim{color:var(--txt-3)}
/* 2026-10-02 用户要求：这一排维度芯片**宽度一律一样**。
   原来宽度跟着文字走（padding 固定），于是「关键词」比「主题/作者/篇名/
   摘要/刊名/全文」宽出一截，一排看着参差不齐。
   用 flex:1 1 0 让七个平分整行；min-width 兜住窄屏（不够就换行，
   换行后每行仍然各自平分）；max-width 防止超宽屏上被拉成大色块。
   ⚠️ 必须挂在 #dim-chips 上而不是 .chip —— .chip 还被下面「热门/历史」
      那排共用，那排是按文字长短排的，不该被拉平。 */
#dim-chips .chip.dim{
  flex:1 1 0;
  min-width:56px;
  max-width:132px;
  display:inline-flex;
  align-items:center;
  justify-content:center;
  text-align:center;
  padding-left:0;
  padding-right:0;
}
.chip.dim.active{
  color:#fff;background:linear-gradient(135deg,#6d8bff,#5b7cfa);
  box-shadow:-3px -3px 7px var(--light),3px 3px 8px var(--dark);
}
/* 选中态再补一点下划感：这一排是「选维度」，实心块容易被当成普通高亮标签 */
.chip.dim.active{font-weight:800}

.quick{display:flex;align-items:center;gap:10px;margin-top:16px;flex-wrap:wrap}
.quick-label{font-size:11.5px;color:var(--txt-3);font-weight:700;letter-spacing:1px;flex-shrink:0}
.chips{display:flex;gap:8px;flex-wrap:wrap;flex:1;align-items:center}
.chip{
  padding:7px 15px;border-radius:12px;font-size:12.5px;font-weight:600;
  color:var(--txt-2); background:var(--bg);
  box-shadow:var(--sh-raise-sm);
  transition:all .18s;
}
.chip:hover{color:var(--accent);transform:translateY(-1px)}
.chip:active{box-shadow:var(--sh-press);transform:translateY(0)}
.chip .x{color:var(--txt-3);margin-left:7px;font-size:13px}
.chip .x:hover{color:var(--danger)}
.linkish{font-size:11.5px;color:var(--txt-3);text-decoration:underline dotted;flex-shrink:0}
.linkish:hover{color:var(--danger)}

/* ── 统计条 ── */
.statbar{
  max-width:var(--page-w);margin:26px auto 0;
  display:flex;justify-content:space-between;align-items:center;
  padding:0 6px;font-size:12px;color:var(--txt-3);flex-wrap:wrap;gap:8px;
}
.stat-right{font-variant-numeric:tabular-nums}
.badge{
  padding:4px 11px;border-radius:10px;font-size:11.5px;font-weight:600;
  box-shadow:var(--sh-raise-sm);
}
.badge.hit{color:var(--accent)}
.badge.cache{color:var(--oa)}
.badge.field{color:var(--txt-2)}
/* 机构筛选后一个源 0 条：橙色提醒。不是错误（请求成功了），
   但得让人一眼看出"是你自己筛掉了"，不至于以为文献库空了。 */
.badge.warn{color:#b45309;background:rgba(234,138,61,.14);
  box-shadow:inset 0 0 0 1px rgba(234,138,61,.30)}
/* 联网结果里「本地库已有」的条数 —— 用绿色，和 ⚡缓存 同色系（都是"省事"的意思） */
.badge.local{color:var(--oa)}

/* ── 结果列 ──
   2026-10-01 改：列框也用和搜索框一样的**凹陷拟态**（var(--sh-press)），
   不再用玻璃 —— 玻璃感只保留给框里一张张的论文卡片。
   .col-head/.col-body 是老结构（本地库老路径、弹层还在用），保留。 */
.grid{
  max-width:var(--page-w);margin:22px auto 0;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(310px,100%),1fr));
  gap:22px;align-items:start;
}
.col{display:flex;flex-direction:column}
.col-glass{
  border-radius:16px;                 /* 和 .field 同圆角 */
  box-shadow:var(--sh-press);         /* 和搜索框同一个凹槽 */
  padding:6px;
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .col-glass{background:linear-gradient(160deg,#fff,#F1ECFF)}
}
.sub{display:flex;flex-direction:column;min-width:0;position:relative}
/* 维普和 OA 之间的分隔线。
   为什么要有：第三列是「维普在上、OA 在下」两段共用一个凹框，
   2026-10-01 之前这里是一条 border-top:1px solid rgba(255,255,255,.55)
   —— 玻璃时代那条白线看着还行，改成拟态（框是实的）之后白线等于没有，
   两段就糊成一坨，看不出 OA 是从维普下面另起的一段。
   现在改成一条**内阴影凹槽**：颜色跟着页面底色走，浅色底上就是一道
   压下去的线，和整页拟态一致，而且不用额外盒模型、不影响左右对齐。 */
/* 维普 / OA 之间的分隔。
   这一版还是不够明显，用户反馈「格子不明显」。原因很直接：
   之前只有一道**内阴影**，颜色是 rgba(120,136,160,.16) —— 16% 的透明度
   压在 #EDE8FA 底上算出来只差几个色阶，1440px 宽的页面上等于没有。
   内阴影的问题还在于它是「凹」，凹的东西天生比周围暗一点就够，
   而这里是浅底浅字，全靠明度差撑着，撑不住。
   现在改成**真的画一条线**：一条 2px 的实体线，中间最深、两头渐隐，
   上面再压一道 1px 高光 —— 这是拟态里「凸起的接缝」的标准画法，
   和旁边「按下」的凹框形成对比，所以哪怕整页都是浅色也一眼能分。
   间距也从 8px 拉到 14px，给这条线留出呼吸的地方。 */
.sub+.sub{
  margin-top:14px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9);
  border-radius:12px;
}
.sub+.sub::before{
  content:"";
  position:absolute;left:10px;right:10px;top:-8px;height:2px;
  border-radius:2px;
  background:linear-gradient(90deg,
    rgba(120,136,160,0) 0%,
    rgba(108,124,150,.55) 18%,
    rgba(108,124,150,.55) 82%,
    rgba(120,136,160,0) 100%);
  box-shadow:0 1px 0 rgba(255,255,255,.95);
  pointer-events:none;
}
.sub-head{
  display:flex;align-items:center;gap:8px;
  padding:10px 12px 9px;
  font-size:14px;font-weight:800;letter-spacing:.4px;
}
.sub-head.foldable{cursor:pointer;user-select:none;border-radius:14px}
/* 凹框里悬停时整行抬起来一点，和下面的下拉/搜索框形成"可选中"的暗示 */
.sub-head.foldable:hover{box-shadow:var(--sh-raise-sm)}
.sub-head .dot{width:9px;height:9px;border-radius:50%;flex-shrink:0;
  box-shadow:inset 1px 1px 2px rgba(0,0,0,.25)}
.sub-head .cnt{
  margin-left:auto;font-size:11.5px;font-weight:600;
  color:var(--txt-3);padding:2px 10px;border-radius:9px;
  box-shadow:var(--sh-press);flex-shrink:0;
}
/* 折叠开关（2026-10-01 重做）
   原来：18×18 的小方块，里面一个 11px 的文字字符 ▸。三个毛病——
     ① 三角实际只有 4~5px 宽，在 1440 宽的页面上是噪点；
     ② 文字三角的字形随系统字体变粗细，Windows/mac 上不一样；
     ③ 它待在标题**左边**，紧挨圆点和「维普」，读起来像源名的前缀，
        没人会想到那是能点的 —— 真正的开关在右端（和计数胶囊一前一后）。
   现在：22×22 的圆钮 + 8px 的 SVG 三角（viewBox 10×10 缩放，不失真），
   悬停变成强调色，展开时整钮 rotate 90°。 */
.fold{
  width:22px;height:22px;flex-shrink:0;padding:0;line-height:1;
  color:var(--txt-2);
  display:flex;align-items:center;justify-content:center;
  border-radius:7px;box-shadow:var(--sh-raise-sm);
  transition:transform .2s cubic-bezier(.4,0,.2,1),color .18s,
             box-shadow .18s;
}
.fold svg{width:9px;height:9px;display:block;fill:currentColor}
.fold:hover{color:var(--accent)}
.fold:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* 展开：三角从朝右转成朝下。转的是**整个钮**，视觉上像开关拨下去 */
.fold.open{transform:rotate(90deg);color:var(--accent)}
/* ── 列内工具条：左「限定范围」下拉 + 右该列的搜索框 ──
   放在列框里面（不是页头），因为列框现在是自足的：一个源 = 一个框 =
   一套「限定 + 搜」，在框里改词只重搜那一个源。
   两个控件都吃 --sh-press（和页头搜索框同一个凹槽），列框本身也是凹槽，
   于是整列从上到下是同一个拟态语言；凸起留给里面一张张的玻璃卡片。 */
.col-tools{
  display:flex;align-items:center;gap:8px;
  padding:2px 8px 9px;
}
.org-sel-wrap{
  display:flex;align-items:center;gap:6px;flex-shrink:0;
  height:34px;padding:0 8px 0 10px;border-radius:12px;
  box-shadow:var(--sh-press);
  max-width:58%;
}
.org-cap{font-size:10.5px;font-weight:700;color:var(--txt-3);white-space:nowrap}
.org-sel{
  flex:1;min-width:0;border:none;outline:none;background:transparent;
  font:inherit;font-size:12px;font-weight:700;color:var(--txt);
  /* 原生下拉的箭头在浅色底上几乎看不见，换成实心三角自己画 */
  appearance:none;-webkit-appearance:none;
  padding:0 14px 0 2px;cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--txt-3) 50%),
                   linear-gradient(135deg,var(--txt-3) 50%,transparent 50%);
  background-position:calc(100% - 7px) 52%,calc(100% - 3px) 52%;
  background-size:4px 4px,4px 4px;
  background-repeat:no-repeat;
  text-overflow:ellipsis;
}
.org-sel:hover{color:var(--accent)}
.org-sel-wrap.none{color:var(--txt-3);cursor:not-allowed}
.org-sel-na{font-size:12px;font-weight:600;color:var(--txt-3)}
/* 选了具体单位就把整个下拉染成主色，一眼看出这一列被限定了 */
.org-sel-wrap.picked{box-shadow:var(--sh-press),inset 0 0 0 1px rgba(79,124,255,.34)}
.org-sel-wrap.picked .org-sel{color:var(--accent)}
.org-sel-wrap.picked .org-cap{color:var(--accent)}
/* 「必须搜完才能点」的锁死态（2026-10-02）。
   锁着的时候要**看起来就是锁着**：整块降透明、去掉指针、连自绘的三角都淡掉。
   光靠浏览器默认的 disabled 灰还不够 —— 原来那个胶囊有边框有阴影，
   灰字加一点透明用户照样会伸手去点，然后发现没反应，以为页面卡了。 */
.org-sel-wrap.off{
  opacity:.46;cursor:not-allowed;
  box-shadow:none;background:repeating-linear-gradient(
    -45deg,transparent,transparent 5px,rgba(127,127,127,.07) 5px,
    rgba(127,127,127,.07) 10px);
}
.org-sel-wrap.off .org-sel{
  cursor:not-allowed;color:var(--txt-3);
  background-image:none;                      /* 不画三角：点不开就别骗人 */
  text-overflow:ellipsis;
}
.org-sel-wrap.off:hover{opacity:.46}

.col-search{
  flex:1;min-width:0;display:flex;align-items:center;gap:7px;
  height:34px;padding:0 12px;border-radius:12px;
  box-shadow:var(--sh-press);
  transition:box-shadow .18s;
}
.col-search:focus-within{box-shadow:inset -4px -4px 9px var(--light),inset 4px 4px 9px var(--dark-2)}
.cs-ico{font-size:12px;opacity:.5;flex-shrink:0}
.cs-inp{
  flex:1;min-width:0;border:none;outline:none;background:transparent;
  font:inherit;font-size:12.5px;color:var(--txt);
}
.cs-inp::placeholder{color:var(--txt-3)}
/* type=search 在 Safari 上自带一个清除叉，和我们自己的控件重复，去掉 */
.cs-inp::-webkit-search-decoration,
.cs-inp::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}

.sub-body{padding:2px 8px 10px;min-height:0}
.sub-body[hidden]{display:none}

.col-head{
  display:flex;align-items:center;gap:9px;
  padding:13px 18px;border-radius:var(--r-md) var(--r-md) 0 0;
  font-size:14.5px;font-weight:800;letter-spacing:.5px;
  box-shadow:var(--sh-raise-sm);
}
.col-head .dot{width:9px;height:9px;border-radius:50%;box-shadow:inset 1px 1px 2px rgba(0,0,0,.25)}
.col-head .cnt{
  margin-left:auto;font-size:11.5px;font-weight:600;
  color:var(--txt-3);padding:2px 10px;border-radius:9px;box-shadow:var(--sh-press);
}
.col-body{
  padding:16px;border-radius:0 0 var(--r-md) var(--r-md);
  box-shadow:var(--sh-press);min-height:110px;
}
.empty-col{text-align:center;padding:30px 10px;color:var(--txt-3);font-size:12.5px}
/* 2026-10-11 第三轮：调试轨迹折叠条。出现条件 = 知网耗时 ≥10s 或 retried 或 ok=false。
   只在风控/卡死时出现，健康 2~12s 的成功检索不会出现这个块。 */
.cnki-trace{margin-top:8px;border-radius:10px;
  background:rgba(79,124,255,.06);border:1px solid rgba(79,124,255,.18);
  font-size:11.5px;line-height:1.55}
.cnki-trace>summary{cursor:pointer;padding:6px 10px;color:var(--txt-2);
  user-select:none;font-weight:500;letter-spacing:.2px}
.cnki-trace>summary:hover{color:var(--txt)}
.cnki-trace-body{padding:4px 10px 8px;max-height:240px;overflow:auto;
  border-top:1px solid rgba(79,124,255,.10);background:rgba(255,255,255,.4)}
.cnki-trace .trc{display:flex;gap:6px;padding:1px 0;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.cnki-trace .trc-ms{flex:0 0 auto;color:var(--txt-3);font-variant-numeric:tabular-nums}
.cnki-trace .trc-step{flex:0 0 auto;color:var(--txt);font-weight:500}
.cnki-trace .trc-more{flex:1 1 auto;color:var(--txt-3);overflow:hidden;
  text-overflow:ellipsis;font-family:ui-monospace,Menlo,monospace;font-size:11px}
/* 2026-10-11 第三轮优化：trace 操作按钮（复制 / 重试知网）。
   玻璃态小按钮，贴在折叠条底部一行。 */
.cnki-trace-actions{display:flex;gap:6px;padding:4px 10px 8px;
  border-top:1px solid rgba(79,124,255,.10);background:rgba(255,255,255,.4)}
.trc-btn{font-size:11.5px;line-height:1;padding:6px 10px;border-radius:8px;
  background:rgba(79,124,255,.12);color:var(--txt);border:1px solid rgba(79,124,255,.25);
  cursor:pointer;user-select:none;font-family:inherit;transition:background .12s}
.trc-btn:hover{background:rgba(79,124,255,.22)}
.trc-btn:active{background:rgba(79,124,255,.30)}
.trc-btn-retry{background:rgba(180,83,9,.12);border-color:rgba(180,83,9,.30);
  color:#b45309}
.trc-btn-retry:hover{background:rgba(180,83,9,.22)}
/* 2026-10-15 C5：检索失败那一列行内的「重试」按钮。摆右端、跟 .hint 同一行，
   让「失败原因 + 一键重试」成对出现，用户不用重打关键词、也不用整页搜。 */
.col-retry{float:right;margin-left:10px;font-size:11.5px;line-height:1;
  padding:5px 11px;border-radius:8px;background:rgba(180,83,9,.12);color:#b45309;
  border:1px solid rgba(180,83,9,.30);cursor:pointer;font-family:inherit;
  user-select:none;transition:background .12s}
.col-retry:hover{background:rgba(180,83,9,.22)}
.col-retry:active{background:rgba(180,83,9,.30)}
.col-retry[disabled]{opacity:.55;cursor:default}

/* ── 卡片：玻璃 ──
   用户要「把里面每个卡片换个样式」，所以卡片从拟态凸起改成半透明玻璃。
   ⚠️ 故意**不**给卡片上 backdrop-filter：一张结果页最多上百张卡，
   每张都 backdrop-filter:blur() 在 Safari 上会把滚动拖到明显卡顿
   （现在靠 content-visibility:auto 才顺的）。玻璃质感用「半透明渐变 +
   内高光 + 4 层阴影」做出来，视觉接近，代价接近零。框只有 3 个，
   那个可以放心用真 blur。 */
.card{
  background:linear-gradient(160deg,rgba(255,255,255,.80),rgba(247,245,255,.62));
  border:1px solid rgba(255,255,255,.86);
  border-radius:var(--r-md);padding:14px 15px;
  margin-bottom:12px;
  box-shadow:
    3px 4px 10px rgba(92,63,228,.08),
    -2px -2px 7px rgba(255,255,255,.92),
    inset 1px 1px 2px rgba(255,255,255,.95),
    inset -1px -2px 3px rgba(92,63,228,.04);
  transition:transform .16s,box-shadow .16s;
  /* ★ 性能：屏幕外的卡片跳过布局/绘制，结果多时滚动不再卡。 */
  content-visibility:auto;contain-intrinsic-size:0 200px;
}
.card:last-child{margin-bottom:0}
.card.clickable{cursor:pointer}
.card.clickable:hover{
  box-shadow:
    4px 5px 13px rgba(92,63,228,.13),
    -2px -2px 7px rgba(255,255,255,.95),
    inset 1px 1px 2px rgba(255,255,255,.95),
    inset -1px -2px 3px rgba(92,63,228,.05);
}
.card.clickable:active{transform:translateY(1px);box-shadow:var(--sh-press)}
.card-title{
  font-size:14.5px;font-weight:700;line-height:1.45;margin-bottom:10px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  word-break:break-word;
}
/* 年份 / CNKI / 期刊论文 这一行：用户要求「拿一个长条的框把他们几个一起
   框出来」，下面那排小框才是按钮。所以：
   ① 整个 meta 是一个**长条容器**，不是几个各自带阴影的小胶囊
      —— .tag 原来的 box-shadow 视觉高度远超 20px，几个叠起来整行虚高；
   ② nowrap：310px 宽的列里 5~6 个标签原来会 flex-wrap 换 2~3 行，
      这才是「上下的高度太大」的真正原因；
   ③ 高度对齐下面那排按钮（.lnk 是 5px+5px 内边距 + 11.5px 字号 +
      1.5 行高 ≈ 27px），用 height:27px 钉死，两行看着一样重。
   标签保留颜色区分（年份灰 / CNKI 蓝 / 期刊论文灰），但不再各自带框。 */
.card-meta{
  display:flex;gap:0;flex-wrap:nowrap;align-items:center;
  height:27px;margin:0 0 8px;line-height:1;
  padding:0 10px;border-radius:9px;
  background:rgba(255,255,255,.50);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.75),
             inset 1px 1px 3px rgba(92,63,228,.05);
  overflow:hidden;white-space:nowrap;
}
.card-meta .tag{
  padding:0;font-size:11px;font-weight:600;line-height:1;
  box-shadow:none;background:none;color:var(--txt-2);
  flex-shrink:0;
}
/* 标签之间用「·」隔开，不靠各自带框来分段 */
.card-meta .tag+.tag::before{
  content:"·";margin:0 6px;color:var(--txt-3);font-weight:400;
}
/* 「📚 本地已有」在长条里靠颜色区分就够了，不给它再套一层填充色块 ——
   长条里嵌一个实心小胶囊会显得像按钮混进了信息行。 */
.card-meta .tag.local{flex-shrink:0;font-weight:700;color:var(--oa)}
.card-meta .tag.entry{color:var(--accent);font-weight:700}
/* .tag 基础形：保留给万一以后在卡片外单独用的场合（.card-meta 里的由上面覆盖） */
.tag{
  padding:2px 8px;border-radius:7px;font-size:10.5px;font-weight:600;
  line-height:1.5;color:var(--txt-2);
}
.tag.hit{color:var(--accent)}
.tag.ref{color:var(--weipu)}
.tag.date{color:var(--txt-3)}
/* 联网卡片上的「📚 本地已有」：绿色，一眼能在这堆结果里挑出来。
   长条里已经有外框了，所以只留颜色、不再自带填充 + 描边。 */
.tag.local{color:var(--oa);font-weight:700}
.card-snippet{
  font-size:12.5px;color:var(--txt-2);line-height:1.65;
  padding:11px 13px;border-radius:12px;margin-bottom:9px;
  box-shadow:var(--sh-press);
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
}
.card-sub{font-size:11.5px;color:var(--txt-3);display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.card-sub .go{margin-left:auto;color:var(--accent);font-weight:700;font-size:11px}

/* 联网卡片：作者/刊名一行（比作者挤在 sub 里更清楚） */
.card-src{font-size:12px;color:var(--txt-2);margin-bottom:8px;display:flex;gap:8px;flex-wrap:wrap}
.card-src .au{font-weight:600}
.card-src .jn{color:var(--txt-3)}
.card-src .au + .jn::before{content:"· ";color:var(--txt-3)}

/* 标签补色 */
.tag.entry{color:var(--accent)}
.tag.type{color:var(--txt-2)}
.tag.oa{color:var(--oa);font-weight:700}
/* 2026-10-01 删掉 .tag.vip 全部规则：用户要求「不用 VIP」。
   它只是知网结果行里有没有「VIP下载通道」那个链接（cnki_dl.py 的 vip 字段），
   是站方的付费标记，跟「我们能不能拿到这篇」无关 —— 留着只让人以为看不了。 */
/* OA 标签在长条里用「方括号」前缀 —— 绿色实心块塞进信息长条会像按钮。 */
.card-meta .tag.oa::before{content:"[";color:var(--oa)}
.card-meta .tag.oa::after{content:"]";color:var(--oa)}
/* 有前缀的标签不再跟前面那个加「·」，否则会变成 「·[OA]」 */
.card-meta .tag.oa+.tag::before{content:none;margin:0}
.card-meta .tag.oa{margin-right:6px}
/* 「❝ 引用」：2026-10-01 按用户要求挪到这排按钮的**最左边**，
   并且改成和 .lnk 一样的框 —— 它是能改写成果的动作，就该跟其它
   动作长得一样，混在信息行里反而不像能点。复制成功变绿闪一下。 */
.lnk.act.citebtn{color:var(--accent-2,#7a5cd8);font-weight:700;cursor:pointer;user-select:none}
.lnk.act.citebtn:hover{color:#fff;background:#7a5cd8;
  box-shadow:-3px -3px 7px var(--light),3px 3px 7px var(--dark)}
.lnk.act.citebtn.done{color:#fff;background:var(--oa);font-weight:800}

/* 「下载 PDF ⤓」：卡片里的动作链接。跟 .lnk 分开是因为它不是 <a>，
   没有下划线默认样式，得自己给 pointer。 */
.lnk.act{cursor:pointer;user-select:none}
.lnk.act.dl{color:var(--accent);font-weight:600}
.lnk.act.dl:hover{background:rgba(79,124,255,.12)}
.lnk.act.dl.busy{color:var(--txt-3);pointer-events:none}
.lnk.act.dl.done{color:var(--oa);font-weight:700}

/* 详情弹层里的 GB/T 7714 引文块：整块可全可选中，按标准排（两端对齐更
   像正式著录，但引文里有大量西文和 [J] 标记，justify 反而难读，故左对齐） */
.cite-box{
  font-size:13px;line-height:1.85;color:var(--txt);
  padding:12px 14px;border-radius:12px;margin-bottom:6px;
  /* 这套是亮灰拟态，没有第二层背景色；引文块要跟普通卡片区分开，
     靠阴影方向：外凸=可点/可读，凹陷=输入。引文是可读的，所以用外凸。 */
  box-shadow:var(--sh-raise-sm);
  user-select:text;-webkit-user-select:text;cursor:text;
  word-break:break-word;
}
/* 「复制」小按钮，挂在 .hint 行右端 */
.hint .mini{
  float:right;margin:-3px 0 0 0;cursor:pointer;
  font:inherit;font-size:11px;font-weight:600;
  padding:3px 11px;border-radius:8px;border:0;
  color:var(--accent);background:rgba(79,124,255,.12);
  transition:background .15s,color .15s;
}
.hint .mini:hover{background:rgba(79,124,255,.22)}
.hint .mini.done{color:var(--oa);background:rgba(47,158,87,.16)}
/* toast 后面这层不用管；但 .hint 里的 mini 是 inline-block 时 float 才稳 */
.hint::after{content:"";display:block;clear:both}

/* 联网卡片底部链接条：引用 / 原文 / 查看 / 下载 / 详情
   2026-10-01 用户要求：
     ① 引用排第一个
     ② 中间四个（引用/原文/查看/下载）间距完全一样
     ③ **详情做成「凹式」按钮，并且钉在最右下端**
   凹式 = 整个 UI 是拟物的（--sh-raise 凸起 / --sh-press 凹陷），
   详情是「次要信息入口」，不该跟左边那四个动作一样凸着抢眼，
   做成内凹正好表达「这是次要的、但位置固定在角落」。
   margin-left:auto 把它推走（之前我为了「间距一致」去掉了，结果详情挤在
   下载后面 —— 用户明确说要放最右下，这里改回来）。 */
.card-links{display:flex;align-items:center;gap:7px;flex-wrap:wrap;margin-top:10px}
/* 凹式：内阴影（深色在左上、亮色在右下 —— 跟凸起的 --sh-raise 反过来），
   背景比卡片略深一档，让它真的「陷进去」而不是只是描边。 */
.card-links .go{
  margin-left:auto;
  color:var(--accent);font-weight:700;font-size:11.5px;
  padding:5px 12px;border-radius:9px;
  background:rgba(92,63,228,.045);
  box-shadow:inset 2px 2px 5px var(--dark),
             inset -2px -2px 5px var(--light);
  transition:color .15s,box-shadow .15s;
}
.card-links .go:hover{
  color:var(--accent);
  box-shadow:inset 1px 1px 3px var(--dark),
             inset -1px -1px 3px var(--light);
}
.card-links .go:active{
  box-shadow:inset 3px 3px 7px var(--dark),
             inset -3px -3px 7px var(--light);
}
/* 「✨ AI查看」：★2026-10-14 新增。占原来「详情」的凹式位（最右下）。
   凹式视觉沿用 .go，只把颜色换成紫色系，跟蓝色的「下载」/绿色的「查看」区分。 */
.card-links .go.ai-view{
  color:var(--accent-2,#7a5cd8);
  font-weight:800;
}
.card-links .go.ai-view:hover{
  color:#fff;
  background:var(--accent-2,#7a5cd8);
  box-shadow:inset 1px 1px 3px rgba(0,0,0,.28),
             inset -1px -1px 3px rgba(255,255,255,.35);
}
/* 「详情」跟「AI查看」换位后落到第 2 位，是普通 .lnk，弱一档
   （它是次要信息入口，不该跟左边那几个动作抢眼）。 */
.lnk.act.det{color:var(--txt-2)}
.lnk.act.det:hover{color:#fff;background:var(--txt-2)}
.lnk{
  font-size:11.5px;font-weight:700;color:var(--accent);text-decoration:none;
  padding:5px 11px;border-radius:9px;box-shadow:var(--sh-raise-sm);
  transition:color .15s,box-shadow .15s;
  /* 按钮行是 5 个框，310px 的列宽装不下会换行。宁可缩小内边距也尽量一行，
     因为「间距不一致」的投诉在换行后会变成更难看的两段。 */
  white-space:nowrap;
}
.lnk:hover{color:#fff;background:var(--accent);box-shadow:-3px -3px 7px var(--light),3px 3px 7px var(--dark)}
.lnk:active{box-shadow:var(--sh-press)}
.lnk.big{font-size:13px;padding:8px 16px}
/* 「查看」：跟引用同族的主动作（点一下就有东西看），用绿色区分于蓝色的
   「下载」—— 一眼看得出哪个是看、哪个是存。 */
.lnk.act.view{color:var(--oa);font-weight:700}
.lnk.act.view:hover{color:#fff;background:var(--oa)}
/* 「下载」：<a download>。给一点区别，让「库里已有 → 直接存」和
   「要现去知网下」不长得一样（后者更危险、更慢）。 */
.lnk.dlx{color:var(--accent);font-weight:700}
/* 兜底链接（知网没给详情页，给的是检索页）：视觉上弱一档，
   点之前就知道它不保证直接落到那篇。 */
.lnk.soft{opacity:.72;border-bottom:1px dashed currentColor}
/* 置灰的按钮：拿不到原文链接 / 这个源不给直链下载。
   保留占位（而不是不渲染）是因为用户要求「每条都要有原文」——
   一条一条地找「为什么这条没有」比看到个灰的更让人困惑。 */
.lnk.dis{color:var(--txt-3);box-shadow:none;cursor:not-allowed;opacity:.55}
.lnk.dis:hover{color:var(--txt-3);background:none;box-shadow:none}
.md-links{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:18px}

/* 列内"检索中"占位（按源渐进加载时每列各自的转圈） */
.col-wait{display:flex;align-items:center;justify-content:center;gap:10px;
  padding:26px 10px;color:var(--txt-3);font-size:12.5px}
.mini-spin{
  width:16px;height:16px;border:2.5px solid #d3dbe6;border-top-color:var(--accent);
  border-radius:50%;animation:spin .75s linear infinite;display:inline-block;
}
/* 统计条里的逐源徽章 */
.badge.srcstat{color:var(--txt-2)}

/* 空状态 */
.blank{
  grid-column:1/-1;text-align:center;padding:80px 20px;
  border-radius:var(--r-lg);box-shadow:var(--sh-press);
}
.blank-ico{font-size:46px;margin-bottom:16px;opacity:.5}
.blank p{font-size:15px;font-weight:700;color:var(--txt-2);margin-bottom:7px}
.blank span{font-size:12px;color:var(--txt-3)}

/* 联网检索进度条（2026-10-13 阶段2）：细条，纯视觉安抚 —— 按耗时渐近，
   不是真实进度（知网不报进度）。 */
.col-wait .cw-bar{margin-top:10px;height:3px;border-radius:3px;
  background:rgba(120,130,150,.18);overflow:hidden}
.col-wait .cw-bar i{display:block;height:100%;width:0;border-radius:3px;
  background:var(--accent);transition:width .3s ease}

/* 骨架屏 */
.sk{background:linear-gradient(90deg,var(--bg) 25%,#dde3ec 50%,var(--bg) 75%);background-size:200% 100%;animation:skw 1.2s linear infinite;border-radius:9px;margin-bottom:11px}
.sk-t{height:14px;width:86%}
.sk-m{height:10px;width:56%;margin-bottom:13px}
.sk-s{height:52px;width:100%}
@keyframes skw{to{background-position:-200% 0}}
.spinner{
  width:30px;height:30px;border:3.5px solid #d3dbe6;border-top-color:var(--accent);
  border-radius:50%;animation:spin .75s linear infinite;margin:0 auto 14px;
}
@keyframes spin{to{transform:rotate(360deg)}}
.loading{grid-column:1/-1;text-align:center;padding:60px;color:var(--txt-3)}

/* ── 详情弹层 ── */
.modal-mask{
  position:fixed;inset:0;z-index:50;
  background:rgba(190,199,214,.55);backdrop-filter:blur(7px);
  display:flex;align-items:center;justify-content:center;padding:14px;
  animation:fade .2s ease;
}
@keyframes fade{from{opacity:0}to{opacity:1}}
.modal{
  position:relative;background:var(--bg);border-radius:var(--r-lg);
  box-shadow:-10px -10px 26px var(--light),10px 10px 26px var(--dark);
  /* 2026-10-14 放宽：常规详情弹层从 860 → 1100（运行时 openAiView 会把它
     进一步拉到 min(1820px,98vw)）。宽度上限由调用方按内容类型动态覆盖。 */
  max-width:min(1100px,96vw);width:100%;max-height:86vh;overflow-y:auto;padding:32px 34px;
  animation:pop .24s cubic-bezier(.34,1.4,.64,1);
}
@keyframes pop{from{transform:scale(.93) translateY(14px);opacity:0}to{transform:none;opacity:1}}
/* ── PDF 阅读器（2026-10-01）────────────────────────────────────
   **上下连续滚动**：整篇一页接一页铺开，滚轮一路往下拉，没有翻页。
   要给 .pdfv 一个**确定的高度**，滚动才会发生在 .pdfv-body 里 ——
   .modal 自己是 max-height:86vh + overflow-y:auto，如果 .pdfv 不限高，
   body 会被内容撑到全篇高度，于是滚的是外层弹层、而且所有页一次性画完
   （IntersectionObserver 认为它们全都「在视口里」），又慢又吃内存。
   86vh 减去 .modal 上下 padding(32px×2=64px) 再留点余量。 */
.pdfv{
  display:flex;flex-direction:column;
  height:min(78vh,1040px);min-height:420px;
}
.pdfv-bar{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding-bottom:12px;margin-bottom:12px;border-bottom:1px solid rgba(0,0,0,.08);
}
.pdfv-name{
  flex:1 1 220px;min-width:0;font-size:14px;font-weight:800;color:var(--txt-1);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.pdfv-tools{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
/* 阅读器右上角唯一的按钮。右边留 44px 给 index.html 里的 .mclose（叉）。 */
.pdfv-dl{
  font-size:12px;padding:6px 12px;border-radius:9px;color:var(--txt-2);
  background:var(--bg);box-shadow:var(--sh-raise-sm);cursor:pointer;
  border:0;font-family:inherit;transition:all .15s;white-space:nowrap;
  margin-right:44px;flex:0 0 auto;
}
.pdfv-dl:hover{color:var(--accent);background:rgba(79,124,255,.12)}
.pdfv-dl:active{box-shadow:var(--sh-press)}
/* 页码用等宽数字：翻页时数字不左右跳 */
.pdfv-pg{
  font-size:12.5px;font-weight:700;color:var(--txt-2);
  font-variant-numeric:tabular-nums;padding:0 6px;white-space:nowrap;
}
.pdfv-tools .mini{
  font-size:12px;padding:5px 10px;border-radius:9px;color:var(--txt-2);
  background:var(--bg);box-shadow:var(--sh-raise-sm);cursor:pointer;
  border:0;font-family:inherit;transition:all .15s;white-space:nowrap;
}
.pdfv-tools .mini:hover{color:var(--accent);background:rgba(79,124,255,.12)}
.pdfv-tools .mini:active{box-shadow:var(--sh-press)}
/* 页面区：整条**纵向连续滚动**，一页接一页，中间留缝。
   不再 flex 居中（居中是给单页用的），改成 block 列 + 逐页堆叠。 */
.pdfv-body{
  /* ★ 必须是 position:relative —— JS 用 page.offsetTop 来定位「跳到第 N 页」。
     .pdfv-page 自带 position:relative，它的 offsetParent 会被解析到最近的
     已定位祖先，也就是 .modal（position:relative）而不是 .pdfv-body，
     于是 offsetTop 是「相对弹层」的距离，scrollTop 却是「相对滚动内容」的距离，
     两者基准不同 → 滚过去总是差一点，看着就是跳不到位。 */
  position:relative;
  flex:1 1 auto;
  /* min-height:0 必须有：flex 子项默认 min-height:auto，
     不给 0 就永远被内容撑开、永远不产生内部滚动。 */
  min-height:0;
  display:block;overflow-y:auto;overflow-x:auto;
  padding:2px 2px 14px;
  scrollbar-gutter:stable;
  /* 滚到头/尾不要把外面的弹层一起带着滚 */
  overscroll-behavior:contain;
}
/* 一页 = 一个白纸块 + 阴影。没渲染时是灰的占位，上面标页码 */
.pdfv-page{
  position:relative;display:block;
  margin:0 auto 14px;
  background:#fff;border-radius:6px;
  box-shadow:0 2px 14px rgba(0,0,0,.13);
  /* 宽度可能比容器宽（窄屏），允许横向滚；宽了就等比缩到容器内 */
  max-width:100%;
}
.pdfv-num{
  position:absolute;inset:0;display:flex;
  align-items:center;justify-content:center;
  font-size:15px;font-weight:700;color:#c3c9d4;
  font-variant-numeric:tabular-nums;pointer-events:none;
}
.pdfv-canvas{
  display:block;background:#fff;border-radius:6px;
  max-width:100%;height:auto;
}
/* PDF.js 渲染期间用的加载态，跟详情弹层里已有的 .loading 共用 */
.pdfv-body .loading{padding:60px 20px}

/* ── AI 查看：双栏（左 AI 解读 / 右 原文 PDF）2026-10-14 ──────────────
   同一个弹层里左右并排。高度同样要在 .aiv 上定死，否则右栏 .pdfv-body
   的内部滚动又会被内容撑掉（跟单阅读器 .pdfv 一个道理）。 */
.aiv{display:flex;flex-direction:column;height:min(80vh,1080px);min-height:440px}
.aiv-bar{
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding-bottom:12px;margin-bottom:12px;border-bottom:1px solid rgba(0,0,0,.08);
}
.aiv-name{
  flex:1 1 240px;min-width:0;font-size:14px;font-weight:800;color:var(--txt-1);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.aiv-dl{
  font-size:12px;padding:6px 12px;border-radius:9px;color:var(--txt-2);
  background:var(--bg);box-shadow:var(--sh-raise-sm);cursor:pointer;border:0;
  font-family:inherit;transition:all .15s;white-space:nowrap;margin-right:44px;flex:0 0 auto;
}
.aiv-dl:hover{color:var(--accent);background:rgba(79,124,255,.12)}
.aiv-dl:active{box-shadow:var(--sh-press)}
/* 双栏（2026-10-14）：CSS Grid 给死比例 —— 左「AI 解读」占 1/3，右「原文 PDF」
   占 2/3。用 flex-basis:33.333% 会被 gap(16px) 吃掉份额、算不准；grid 的
   1fr/2fr 分的是扣掉 gap 后的自由空间，正好 1:2。
   min-width/min-height:0 必须给：grid/flex 子项默认 min-*:auto，不给 0
   内部滚动永远不触发（会被内容撑开）。 */
.aiv-cols{
  flex:1 1 auto;min-height:0;
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr);
  gap:16px;align-items:stretch;
}
/* 左栏：AI 解读，独立滚动 */
.ai-pane{
  min-width:0;min-height:0;overflow-y:auto;
  padding:4px 14px 16px 4px;
  scrollbar-gutter:stable;overscroll-behavior:contain;
}
/* 右栏：原文 PDF，复用 .pdfv-body 的连续滚动 */
.aiv-pdf{min-width:0;min-height:0;display:flex;flex-direction:column}
.aiv-pdf .pdfv-body{flex:1 1 auto;min-height:0}

/* AI 解读内容（2026-10-14 打磨）
   层级：标题行 + 3 张拟态卡片；每张卡左侧一条 3px 紫竖条把三层切开，
   正文行高放宽到 1.9（长文读起来不挤）。 */
.ai-head{
  font-size:15px;font-weight:900;color:var(--txt-1);margin:2px 0 10px;
  display:flex;align-items:center;gap:9px;flex-wrap:nowrap;
}
.ai-title{
  min-width:0;flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;font-size:13px;font-weight:800;color:var(--txt-2);
}
.ai-badge{font-size:10.5px;font-weight:700;padding:3px 9px;border-radius:8px;flex:0 0 auto}
.ai-badge.run{color:var(--accent);background:rgba(79,124,255,.14)}
.ai-badge.new{color:var(--oa);background:rgba(47,158,87,.16)}
.ai-badge.cache{color:var(--txt-3);background:rgba(0,0,0,.05)}
.ai-badge.bad{color:var(--danger);background:rgba(200,60,60,.13)}
.ai-model{font-size:10.5px;color:var(--txt-3);margin:-6px 0 14px}
.ai-tip{font-size:11px;color:var(--txt-3);line-height:1.7;margin-top:8px}
/* AI 异步解析进度（2026-10-14 O8）：入队即回 + 前端轮询，画**真实**进度条。
   与 .cw-bar（联网检索的渐近安抚条）区分：这里更粗（6px）、带阶段文字。 */
.ai-wait{padding:6px 2px}
.ai-wait-msg{font-size:13px;font-weight:700;color:var(--txt-2);margin-bottom:10px}
.ai-bar{margin:2px 0 8px;height:6px;border-radius:6px;
  background:rgba(120,130,150,.18);overflow:hidden}
.ai-bar i{display:block;height:100%;width:0;border-radius:6px;
  background:linear-gradient(90deg,var(--accent),#8f6bff);transition:width .4s ease}
.ai-wait-step{font-size:11.5px;color:var(--accent);font-weight:600}
/* 取消按钮（2026-10-15 O8 增强）：低干扰次要样式，别抢进度条的注意力。 */
.ai-wait-actions{margin-top:12px}
.ai-cancel{font-size:11.5px;font-weight:600;color:var(--txt-3);
  background:transparent;border:1px solid rgba(120,130,150,.4);
  border-radius:8px;padding:5px 12px;cursor:pointer;transition:all .15s ease}
.ai-cancel:hover:not(:disabled){color:var(--danger);border-color:rgba(200,60,60,.5);
  background:rgba(200,60,60,.06)}
.ai-cancel:disabled{opacity:.55;cursor:default}
.ai-layer{
  position:relative;background:var(--bg);border-radius:14px;
  padding:15px 17px 15px 20px;margin-bottom:16px;
  box-shadow:var(--sh-raise-sm);
}
/* 左侧 3px 紫条，把三层从视觉上切成三段 */
.ai-layer::before{
  content:"";position:absolute;left:0;top:14px;bottom:14px;width:3px;
  border-radius:3px;background:linear-gradient(180deg,#8E7BFF,#5B3FE4);opacity:.85;
}
.ai-layer-title{
  font-size:14px;font-weight:800;color:#5B3FE4;
  margin-bottom:10px;display:flex;align-items:center;gap:8px;
}
/* 每层「复制本层」小按钮：hover 才显形，平时不抢视线 */
.ai-copy{
  margin-left:auto;flex:0 0 auto;font-size:10.5px;font-weight:700;
  color:var(--txt-3);padding:3px 8px;border-radius:8px;background:var(--bg);
  box-shadow:var(--sh-raise-sm);opacity:0;cursor:pointer;
  transition:opacity .15s,color .15s;
}
.ai-layer:hover .ai-copy{opacity:1}
.ai-copy:hover{color:var(--accent)}
.ai-copy:active{box-shadow:var(--sh-press)}
.ai-layer-body{font-size:13.5px;line-height:1.9;color:var(--txt-2)}
.ai-layer-body h4{font-size:13px;font-weight:800;color:var(--txt-1);margin:13px 0 6px}
.ai-layer-body p{margin:0 0 10px}
.ai-layer-body ul{margin:0 0 10px;padding-left:20px}
.ai-layer-body li{margin-bottom:5px}
.ai-layer-body b{color:var(--txt-1)}
.ai-layer-body code{
  font-family:ui-monospace,Menlo,monospace;font-size:12px;
  background:rgba(0,0,0,.05);padding:1px 5px;border-radius:5px;
}
@media(max-width:900px){
  /* 窄屏双栏挤不下 → 改成上下：AI 解读在上（≤40vh）、原文在下 */
  .aiv-cols{grid-template-columns:minmax(0,1fr)}
  .ai-pane{max-height:40vh;padding-right:4px}
}
.modal h2{font-size:19px;font-weight:800;line-height:1.45;margin-bottom:16px;padding-right:34px;word-break:break-word}
.mclose{
  position:absolute;top:20px;right:22px;width:34px;height:34px;border-radius:11px;
  font-size:14px;color:var(--txt-2);background:var(--bg);box-shadow:var(--sh-raise-sm);
  display:flex;align-items:center;justify-content:center;transition:all .16s;
}
.mclose:hover{color:var(--danger)}
.mclose:active{box-shadow:var(--sh-press)}
.md-meta{display:flex;gap:9px;flex-wrap:wrap;margin-bottom:20px}
.md-meta span{
  font-size:12px;color:var(--txt-2);padding:6px 13px;border-radius:10px;box-shadow:var(--sh-raise-sm);
}
.md-meta b{color:var(--txt-3);font-weight:600;margin-right:5px}
.hint{font-size:13px;color:var(--txt-2);padding:14px 16px;border-radius:12px;box-shadow:var(--sh-press);margin-bottom:16px}
.pg{margin-bottom:18px}
.pghead{
  font-size:12.5px;font-weight:800;color:var(--accent);
  padding:8px 15px;border-radius:10px;box-shadow:var(--sh-raise-sm);
  display:inline-block;margin-bottom:11px;
}
.snp{
  font-size:13px;line-height:1.8;color:var(--txt-2);
  padding:13px 16px;border-radius:12px;box-shadow:var(--sh-press);margin-bottom:9px;
  border-left:3px solid var(--accent);
}
.cite{
  font-size:12px;color:var(--txt-2);padding:9px 14px;border-radius:10px;
  box-shadow:var(--sh-raise-sm);margin-bottom:7px;line-height:1.6;
}
.cite b{color:var(--weipu);margin-right:7px;font-weight:700}
.path{
  margin-top:18px;padding-top:14px;border-top:1.5px dashed #ccd4e0;
  font-size:10.5px;color:var(--txt-3);word-break:break-all;font-family:ui-monospace,Menlo,monospace;
}

/* Toast */
.toast{
  position:fixed;bottom:30px;left:50%;transform:translateX(-50%) translateY(14px);
  background:var(--bg);color:var(--txt);padding:13px 24px;border-radius:15px;
  box-shadow:var(--sh-raise);font-size:13.5px;font-weight:600;
  opacity:0;pointer-events:none;transition:all .26s;z-index:99;
}
.toast.show{opacity:1;transform:translateX(-50%) translateY(0)}

.ftr{text-align:center;padding:34px 16px 10px;color:var(--txt-3);font-size:11.5px}

@media(max-width:640px){
  .shell{padding:0 13px 44px}
  .search-panel{padding:16px}
  .sbar{flex-direction:column;align-items:stretch}
  .btn.primary{width:100%}
  .tabs{flex-wrap:wrap}
  .tab{flex:1 1 30%;font-size:13px}
  .modal{padding:26px 20px}
  /* 手机上三列会叠成三个竖条，间距压小一点，不然要滑很久才看到第二列 */
  .grid{gap:14px;margin-top:16px}
  .col-glass{border-radius:14px}
  /* 每列宽度只有 313px 了，「限定范围 + 搜索框」并排必然挤：
     下拉只留箭头选、标签和搜索框各占一行的高度由 flex 分配。 */
  .col-tools{flex-wrap:wrap;gap:7px;padding:2px 8px 8px}
  .org-sel-wrap{max-width:100%;flex:1 1 100%;height:32px}
  .col-search{flex:1 1 100%;height:32px}
}

/* ── 登录弹层（2026-10-10）─────────────────────────────────────
   公网实例 7014 需要口令；页面原先没有登录入口，于是 401 看起来像“坏了”。
   这里沿用详情弹层那套遮罩，卡片再收小一点，只放一个凹槽输入框 + 凸起按钮。 */
.login-mask{
  position:fixed;inset:0;z-index:60;
  background:rgba(190,199,214,.55);backdrop-filter:blur(7px);
  display:flex;align-items:center;justify-content:center;padding:24px;
  animation:fade .2s ease;
}
.login-card{
  background:var(--bg);border-radius:var(--r-lg);
  box-shadow:-10px -10px 26px var(--light),10px 10px 26px var(--dark);
  width:100%;max-width:360px;padding:30px 28px 24px;text-align:center;
  animation:pop .24s cubic-bezier(.34,1.4,.64,1);
}
.lg-icon{
  width:52px;height:52px;margin:0 auto 14px;border-radius:16px;
  display:flex;align-items:center;justify-content:center;font-size:24px;
  background:linear-gradient(135deg,#8E7BFF,#5B3FE4);box-shadow:var(--sh-raise-sm);
}
.lg-title{font-size:20px;font-weight:900;letter-spacing:1.5px;color:var(--txt);
  font-family:"Avenir Next","Helvetica Neue",sans-serif}
.lg-sub{font-size:12.5px;color:var(--txt-3);margin:6px 0 20px}
.lg-field{height:50px;margin-bottom:12px}
.lg-err{min-height:18px;font-size:12.5px;color:var(--danger);font-weight:600;margin-bottom:8px}
.lg-btn{
  width:100%;height:46px;border-radius:13px;font-size:15px;font-weight:800;
  letter-spacing:2px;color:var(--accent);background:var(--bg);transition:all .16s;
}
.lg-btn:hover{color:#fff;background:var(--accent)}
.lg-btn:active{box-shadow:var(--sh-press);transform:translateY(1px)}
.lg-btn:disabled{opacity:.55;cursor:default;color:var(--txt-3);background:var(--bg);box-shadow:var(--sh-raise)}
.lg-note{font-size:11.5px;color:var(--txt-3);margin-top:14px}

/* ── 贴链接/DOI 按钮 + 解析弹层（feature D，2026-10-10）──────────────
   入口①：搜索栏右侧的 📎 按钮（.resolve-btn），和搜索框并排；
   入口②：弹层里再贴一次。复用详情弹层那套遮罩 + 玻璃卡片。 */
.resolve-btn{
  flex-shrink:0;white-space:nowrap;height:46px;padding:0 18px;border-radius:13px;
  font-size:13.5px;font-weight:800;color:var(--accent);background:var(--bg);
  transition:all .16s;
}
.resolve-btn:hover{color:#fff;background:var(--accent)}
.resolve-btn:active{box-shadow:var(--sh-press);transform:translateY(1px)}

.resolve-modal{max-width:600px}
.rm-head{font-size:18px;font-weight:900;letter-spacing:.5px;color:var(--txt);
  margin-bottom:6px;padding-right:34px}
.rm-sub{font-size:12.5px;line-height:1.6;color:var(--txt-3);margin-bottom:16px}
.rm-field{height:48px}
.rm-actions{display:flex;align-items:center;gap:12px;margin-top:12px}
.rm-go{
  flex-shrink:0;height:40px;padding:0 22px;border-radius:12px;font-size:14px;
  font-weight:800;color:var(--accent);background:var(--bg);transition:all .16s;
}
.rm-go:hover{color:#fff;background:var(--accent)}
.rm-go:active{box-shadow:var(--sh-press);transform:translateY(1px)}
.rm-go:disabled{opacity:.55;cursor:default;color:var(--txt-3);background:var(--bg);box-shadow:var(--sh-raise)}
.rm-err{font-size:12.5px;color:var(--danger);font-weight:600;line-height:1.5}
.rm-result{margin-top:16px}
.rm-wait{display:flex;align-items:center;gap:10px;padding:16px 4px;color:var(--txt-3);font-size:13px}
.rm-bad{padding:14px 16px;border-radius:12px;font-size:13px;line-height:1.6;color:#b45309;
  background:rgba(180,83,9,.08);box-shadow:var(--sh-press)}
.rm-card .card{cursor:default}
.rm-cands{margin-top:10px;font-size:12.5px;color:var(--txt-3);line-height:1.8}
.rm-cands a{color:var(--accent);font-weight:700;text-decoration:none;margin-right:4px}
.rm-cands a:hover{text-decoration:underline}
.rm-doi{margin-top:10px;font-size:12px;color:var(--txt-3)}
.rm-doi code{font-size:12px;color:var(--txt)}
.rm-warn{margin-top:10px;font-size:12px;line-height:1.6;color:#b45309}

@media(max-width:640px){
  .sbar{flex-direction:column;align-items:stretch}
  .resolve-btn{width:100%;padding:0}
}



/* ── 阶段4（2026-10-13）：可访问性 / 深色模式 / 断点收敛 ─────────────
   只在此处**追加**新规则，不改上面的既有声明，避免动到拟态那套阴影。 */
:root{color-scheme:light dark}

/* 键盘焦点：鼠标点击不显示、Tab 键才显示（:focus-visible），不干扰拟态阴影 */
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:8px}

/* 屏幕阅读器专用文本（视觉隐藏、仍可朗读） */
.visually-hidden{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* 深色模式：同色底拟态在暗色下重取一套变量（亮=更强白、暗=更强黑） */
@media (prefers-color-scheme: dark){
  :root{
    --bg:#1b1f27;
    --light:rgba(255,255,255,.06);
    --dark:rgba(0,0,0,.55);
    --dark-2:rgba(0,0,0,.72);
    --txt:#e7ecf4; --txt-2:#aeb8c7; --txt-3:#7d8798;
    --accent-soft:rgba(91,124,250,.24);
  }
  .glow.g1{background:rgba(91,124,250,.18)}
  .glow.g2{background:rgba(232,131,58,.12)}
  .card{background:linear-gradient(160deg,#242a35,#1b1f27)}
  @supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
    .col-glass{background:linear-gradient(160deg,#242a35,#1b1f27)}
  }
}

/* 平板：三列 auto-fit 到 ~1024px 时容易挤成 2+1，收窄内边距与卡片间距 */
@media (max-width:1024px){
  .shell{padding:0 14px 52px}
  .grid{gap:16px}
}

/* 尊重「减少动态效果」偏好：关掉所有过渡/动画 */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
}
