/* ============================================================
   技术要素大市场 · 视觉体系 v4
   定位：科技成果转化服务平台 —— 稳重、权威、克制、有细节。
   设计原则：
     1. 单一主色（品牌蓝）+ 单一点缀色（香槟金），不用高饱和多色渐变；
     2. 层级靠「留白 + 字重 + 细线」建立，不靠重阴影与粗边框；
     3. 所有组件沿用同一套 token，改 token 即全站生效；
     4. 交互态（hover / focus / active / disabled）必须齐全，缺态即显粗糙。
   ============================================================ */
:root {
  /* ---- 主色：品牌蓝 ---- */
  --brand: #17509b;
  --brand-2: #2b74c4;      /* 同色系亮端：既有渐变改指这里后自动变克制 */
  --brand-deep: #0b2e63;   /* 深蓝：页头 / 页脚 / Hero */
  --brand-soft: #edf3fb;
  --brand-line: rgba(23, 80, 155, .18);
  --brand-line-soft: rgba(23, 80, 155, .14);  /* 品牌蓝细线（弱档）：卡片内顶部分隔。注意弱于 --brand-line(.18)，勿合并 */

  /* ---- 点缀：香槟金（只用于细线与徽标，绝不铺面）---- */
  --gold: #b8873b;
  --gold-soft: #faf5ec;

  /* ---- 语义色 ---- */
  --ok: #15803d;
  --ok-soft: #eaf7ee;
  --warn: #b45309;
  --warn-soft: #fdf4e6;
  --danger: #c62b2b;
  --danger-strong: #dc2626;  /* 仅用于数值超限高亮（异常计数 >0） */
  --danger-soft: #fdeded;

  /* ---- 中性 ---- */
  --ink: #0e1726;
  --ink-2: #4a5a70;
  /* ⚠️ 次要文本色。原值 `#8a9aaf` 在白底只有 **2.87:1**、在 `--bg` 上 2.79:1，
     两处都**不达 WCAG 2.1 AA 的 4.5:1**。而它被用在 24 处**正文级**文本上
     （`.empty` / `.loading-box` / `.trace-meta` / `.kv-inline .k` / `.dt-empty` /
     `.ad-by` / 表单分组标签 …），不是纯装饰。现值 `#5f7085`：
     白底 **5.07:1**、`--bg` **4.69:1**，两处均过 AA。
     改的是 token，全站一处生效；护栏 `verify_a11y.py` 会按同一公式复算并守住这条线。 */
  --ink-3: #5f7085;
  --line: #e2e8f0;
  --line-2: #eef2f7;
  /* ⚠️ `--line-3` 与 `--line-2`(#eef2f7) 视觉上几乎相同 —— **这是刻意的**：
     本次任务是"替换硬编码色为令牌、替换前后视觉零变化"，故取精确同值而不做合并。
     日后如需做令牌收敛，可将二者归一（届时是一处**有意的**视觉调整，须单独评审）。 */
  --line-3: #f1f5f9;  /* 列表行之间的极浅分隔线 */
  --bg: #f4f6fa;
  --bg-2: #eaeef5;
  --card: #ffffff;

  /* ---- 形状 ---- */
  --radius: 12px;
  --radius-sm: 8px;
  --radius-xs: 6px;
  --nav-h: 64px;

  /* ---- 阴影：三级，逐级加重 ---- */
  --shadow-1: 0 1px 2px rgba(14, 23, 38, .04), 0 4px 14px rgba(14, 23, 38, .05);
  --shadow-2: 0 2px 6px rgba(14, 23, 38, .06), 0 16px 36px rgba(14, 23, 38, .10);
  --shadow-3: 0 24px 64px rgba(14, 23, 38, .18);
  --shadow: var(--shadow-1); /* 兼容旧引用 */
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.7 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
        "Source Han Sans SC", "Noto Sans SC", "Microsoft YaHei", sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
a { color: var(--brand); text-decoration: none; }
a:hover { color: var(--brand-deep); }
button { font-family: inherit; cursor: pointer; }
h1, h2, h3, h4, h5, b, strong { color: var(--ink); }
::selection { background: rgba(23, 80, 155, .16); }
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }

/* 对话框容器**不应**出焦点环：它是被程序性聚焦的落点（面板里没有可聚焦元素时），
   不是用户 Tab 到的目标。给它 2px 描边只会在每次弹窗打开时糊一整圈蓝框。
   ⚠️ 只豁免容器本身 —— 里面的按钮 / 输入框仍受上面那条 `:focus-visible` 保护。 */
[role="dialog"]:focus { outline: none; }

/* 尊重系统的"减少动态效果"偏好（前庭功能障碍用户会因动效不适）。
   ⚠️ 不是删掉动效，而是把时长压到近乎 0 —— 保留状态切换的**逻辑**，
   只去掉"看得见的运动"。`scroll-behavior` 一并收敛，否则锚点跳转仍是平滑滚动。 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* 跳过导航链接（skip-link）：键盘 / 读屏用户第一次按 Tab 即可绕过整条顶部导航
   直达 `#view` 主内容，不必逐条 Tab 过 20+ 个导航项。
   ⚠️ 默认态**不能**用 `display:none` / `visibility:hidden` —— 那会让它从 Tab 序列里
   消失，"写了 skip-link 却永远 Tab 不到"等于没做。这里用 `transform` 把它移到视口
   上方：元素仍在布局与 Tab 序列中，聚焦时归位到左上角清晰可见。
   z-index 120 > 粘性导航的 40，聚焦时不会被导航盖住。 */
.skip-link {
  position: fixed; top: 0; left: 0; z-index: 120;
  padding: 10px 18px; background: var(--brand-deep); color: #fff;
  font-weight: 600; text-decoration: none;
  border-radius: 0 0 var(--radius-sm) 0;
  box-shadow: var(--shadow-2);
  transform: translateY(-120%);
}
.skip-link:focus { transform: none; }
/* 聚焦环用香槟金：链接底色是深蓝，全局蓝色 outline 在深蓝上对比不足 */
.skip-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* 仅供读屏的不占位文本（screen-reader-only）：视觉上 1×1 且裁掉，但**仍在可访问树里**。
   用途：给"只靠颜色/符号表达"的语义补一段机器可读的文字。当前唯一用途是必填标记
   （`ui.js` 的 `REQ_MARK`）：星号 `*` 用 `aria-hidden` 对读屏隐藏，改由这里的
   「（必填）」播报 —— 于是 label 的可访问名里自然带出"必填"，不再只靠红色。
   ⚠️ 不要改成 `display:none` / `visibility:hidden`：那会把它从可访问树里摘掉，
   读屏同样读不到，等于没加。 */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* SEO 壳层的首屏内容（`app/api/seo.py` 注入）。
   服务端把实体的标题/摘要写进 `#app`，SPA 挂载后会被真实视图整体替换。
   于是同一份 HTML 同时服务三件事：① 无 JS 的爬虫能读到正文；② 真实用户第一帧
   看到的是**实体信息**而不是骨架条（观感更好）；③ 只做路径级 URL、不必上 SSR。
   ⚠️ 不要给它加 `display:none` —— 那会让无 JS 爬虫也读不到，等于白做。 */
.seo-fallback { max-width: 760px; margin: 48px auto; padding: 0 20px; }
.seo-fallback-kind { margin: 0 0 6px; font-size: 13px; color: var(--ink-3); letter-spacing: .04em; }
.seo-fallback-title { margin: 0 0 12px; font-size: 22px; line-height: 1.45; color: var(--ink-1); }
.seo-fallback-desc { margin: 0; font-size: 14px; line-height: 1.75; color: var(--ink-2); }
.seo-fallback-more { margin: 14px 0 0; font-size: 13px; }

/* 滚动条：细窄、低对比，避免破坏页面质感 */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 99px; border: 3px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: #adb9c8; }
::-webkit-scrollbar-track { background: transparent; }

/* ============================================================
   顶部通告条 + 导航
   ============================================================ */
/* 运营公告条（`ops.announcement_bar`）：**留空时这个元素根本不存在** ——
   JS 侧不生成空 div（见 `app.js::topbar()`），所以这里不需要"空态"样式，
   也不会在页面顶部留下一条隐形占位。用暖金底色与下方深色通告条区分开。 */
.announce-bar {
  background: linear-gradient(90deg, #fdf3e0, #fbeacb);
  color: #8a5a06; font-size: 12.5px; font-weight: 600; letter-spacing: .02em;
  text-align: center; padding: 7px 32px;
  border-bottom: 1px solid rgba(138, 90, 6, .18);
}
.topbar {
  background: var(--brand-deep); color: rgba(255, 255, 255, .82);
  font-size: 12px; letter-spacing: .02em;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
}
.topbar-inner {
  max-width: 1240px; margin: 0 auto; padding: 0 32px; height: 34px;
  display: flex; align-items: center; gap: 10px;
}
.topbar .dot {
  width: 5px; height: 5px; border-radius: 50%; background: var(--gold);
  box-shadow: 0 0 0 3px rgba(184, 135, 59, .22); flex: none;
}
.topbar b { color: #fff; font-weight: 600; letter-spacing: .04em; }
.topbar .sep { opacity: .3; }
.topbar .right { margin-left: auto; opacity: .72; }

.nav {
  /* gap 由 20px 收到 14px：一级导航现在有 4 个间隙（品牌 | 分隔 | 栏目 | 我的功能 | 用户区），
     每档宽度都实测过，见下方断点注释。 */
  position: sticky; top: 0; z-index: 40; display: flex; align-items: center; gap: 14px;
  padding: 0 32px; min-height: var(--nav-h);
  background: rgba(255, 255, 255, .9);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 1px 0 rgba(14, 23, 38, .03);
}
.nav-brand { display: flex; align-items: center; gap: 12px; flex: none; }
.nav-logo {
  width: 38px; height: 38px; border-radius: 10px; color: #fff; font-size: 14px; font-weight: 700;
  background: linear-gradient(140deg, var(--brand) 0%, var(--brand-deep) 100%);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .14), 0 3px 10px rgba(11, 46, 99, .28);
  display: grid; place-items: center; letter-spacing: -.02em;
}
.nav-title { display: flex; flex-direction: column; line-height: 1.25; }
.nav-title .cn { font-size: 16px; font-weight: 700; letter-spacing: .01em; color: var(--ink); }
.nav-title .en {
  font-size: 9.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3); font-weight: 600;
}
/* 品牌与菜单之间的细竖线：一条线就能拉开层次 */
.nav-divider { width: 1px; height: 26px; background: var(--line); flex: none; }
.nav-links { display: flex; gap: 2px; margin-left: 4px; flex: 1; flex-wrap: wrap; }
.nav-link {
  padding: 8px 11px; border-radius: var(--radius-sm); color: var(--ink-2); font-size: 13.5px;
  border: none; background: none; position: relative; transition: color .16s, background .16s;
  font-weight: 500;
}
.nav-link:hover { background: #f2f5f9; color: var(--brand); }
.nav-link.active { color: var(--brand); font-weight: 600; }
.nav-link.active::after {
  content: ''; position: absolute; left: 11px; right: 11px; bottom: 1px;
  height: 2px; border-radius: 2px; background: linear-gradient(90deg, var(--brand), var(--gold));
}
.nav-user { display: flex; align-items: center; gap: 12px; flex: none; }
.nav-user .who { text-align: right; line-height: 1.35; }
.nav-user .who .nm { font-size: 13px; font-weight: 600; }
.avatar {
  width: 34px; height: 34px; border-radius: 50%; color: #fff; font-size: 13px; font-weight: 600;
  background: linear-gradient(140deg, var(--brand) 0%, var(--brand-deep) 100%);
  display: grid; place-items: center;
  box-shadow: 0 2px 8px rgba(11, 46, 99, .25);
}

/* ============================================================
   「我的功能」与窄屏抽屉（评估报告 P1-1 / P1-12）
   ============================================================ */

/* 「我的功能」组：登录后按身份出现的 1–2 个主任务（报告 §4.2）。
 * 与公共栏目之间用一条竖线分开 —— 用户要能一眼看出"左边是栏目、右边是入口"。
 * 数量上限由 app.js 的 `mineKeys()` 保证（按身份**互斥**取一组，最多 2 项）。 */
.nav-mine { display: flex; align-items: center; gap: 2px; flex: none; }
.nav-mine::before {
  content: ''; width: 1px; height: 22px; background: var(--line); margin: 0 9px 0 3px;
}
/* 「我的功能」用品牌色 + 字重区分：它是"我的"而不是"公共的"。
 * 只改颜色不改尺寸 —— 尺寸一改，前面算好的每一档宽度全部作废。 */
.nav-link.mine { color: var(--brand); font-weight: 600; }
.nav-link.mine:hover { background: var(--brand-soft); }

/* 汉堡按钮：只在窄屏出现（`display:none` 是基线，1279px 档再打开） */
.nav-burger {
  display: none; width: 40px; height: 34px; flex: none; padding: 0;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: none;
  cursor: pointer; place-items: center; gap: 4px;
}
.nav-burger i { display: block; width: 16px; height: 2px; border-radius: 2px; background: var(--ink-2); }
.nav-burger:hover { background: #f2f5f9; }

/* 抽屉：默认 `display:none` —— 桌面档**永远**不显示，即使 `hidden` 被摘掉。
 * 窄屏档用 `.nav-drawer:not([hidden])` 打开。
 *
 * ⚠️ 为什么不能只靠 HTML 的 `hidden` 属性：`.nav-drawer` 自身一旦有
 * `display:flex` 之类的声明，就会**盖过** `hidden` 自带的 `display:none`
 * （属性选择器的优先级低于类选择器）。所以这里显式写 `[hidden]` 的配对规则。 */
.nav-drawer { display: none; background: #fff; border-bottom: 1px solid var(--line); }
.nav-drawer[hidden] { display: none; }
.nd-group { padding: 10px 16px; border-top: 1px solid var(--line-2); }
.nd-group:first-child { border-top: none; }
.nd-title { font-size: 11.5px; font-weight: 700; letter-spacing: .08em; color: var(--ink-3); margin-bottom: 7px; }
.nd-links { display: flex; flex-wrap: wrap; gap: 6px; }
.nd-links .nav-link { background: #f4f7fa; }
.nd-links .nav-link.active { background: var(--brand-soft); }
.nd-user { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* 账户区跟在功能项之后时才需要间距（访客态它是「我的」组里唯一的内容） */
.nd-links + .nd-user { margin-top: 10px; }
.nd-user .who { line-height: 1.35; }
.nd-user .who .nm { font-size: 13px; font-weight: 600; }
.nd-user .avatar { margin-left: auto; }

/* ------------------------------------------------------------
   导航的三个宽度档
   ------------------------------------------------------------
   实测数据（经理人登录态，2026-10-05，headless Edge）：

     视口      navH      行数   brandW  userW   说明
     1920px     64        1      368    300
     1600px     64        1      368    300
     1440px     75       **2**   368    300   ← 加「我的功能」之前就已经换行
     1200px    113        3      368    300
     1024px    151        4      368    300
      390px    209        3      244     95   ← 报告 P1-12 说"占两行约 120px"，低估了

   根因两条，都在这一档里修：
     ① `.nav-title .en`（英文副标题）把品牌区从 244px 撑到 **368px** ——
        多出来的 124px 全是装饰性小字。报告 §4.6 在移动端也把它归为
        "隐藏不损失任何操作"，桌面同理；
     ② `.nav-user .who`（姓名 + 单位/角色）另占约 205px，而头像本身已是入口。
   于是：≥1600px 两者都显示；1280–1599px 两者隐藏、导航保持**一行**；
   <1280px 整体收进汉堡抽屉（报告 §4.6 的原话要求）。

   ⚠️ 不要把 1280 这一档改小。该档可用宽度约 820px，而
   "公共 8 项 + 我的功能 2 项 + 分隔线"实测需要约 772px，余量不到 50px。
   改小断点 = 导航立刻换行，而换行是本轮要修掉的东西。
   ------------------------------------------------------------ */
@media (max-width: 1599px) {
  .nav-title .en { display: none; }
  .nav-user .who { display: none; }
}

@media (max-width: 1279px) {
  .nav { padding: 0 16px; min-height: 58px; }
  .nav-divider { display: none; }
  /* 栏目 / 我的功能 / 用户区**整组**进抽屉。
   * 访客态下登录入口因此只剩顶部访客条那一个 —— 这正是报告 §4.6 要的
   * "合并重复的登录入口"（它给的另一条路是"只留访客条"，这里走的就是这条）。 */
  .nav-links, .nav-mine, .nav-user { display: none; }
  .nav-burger { display: grid; margin-left: auto; }
  .nav-drawer:not([hidden]) { display: block; }
}

/* 报告 §4.6：顶部信息条在窄屏**整条隐藏**。
 * 它承载的是品牌口号，不是功能，隐藏不损失任何操作；而它此前在 390px 下
 * 被 overflow 裁成"…数字化协 / 同枢纽"，右半句完全不可见、页面又没有横向
 * 滚动条 —— 用户无从知道有内容被吃掉了（这正是 P1-12 的第一条）。 */
@media (max-width: 640px) {
  .topbar { display: none; }
}

.container { max-width: 1240px; margin: 0 auto; padding: 26px 32px 56px; }

/* 面包屑 */
.crumb {
  display: flex; align-items: center; gap: 8px; margin-bottom: 14px;
  font-size: 12.5px; color: var(--ink-3);
}
.crumb a { color: var(--ink-2); }
.crumb a:hover { color: var(--brand); }
.crumb .sep { opacity: .45; font-size: 11px; }
.crumb .cur { color: var(--ink); font-weight: 600; }

/* ============================================================
   页头 / 区块标题
   ============================================================ */
.page-head { margin-bottom: 20px; }
.page-head h1 {
  margin: 0 0 6px; font-size: 23px; font-weight: 700; letter-spacing: -.3px; line-height: 1.35;
}
.page-head p { margin: 0; color: var(--ink-2); font-size: 13.5px; max-width: 760px; }

/* 卡片内小节标题：左侧竖条，克制且能立刻建立层级 */
.sec-title {
  display: flex; align-items: center; gap: 8px;
  font-size: 14px; font-weight: 700; letter-spacing: -.1px;
}
.sec-title::before {
  content: ''; width: 3px; height: 14px; border-radius: 2px;
  background: linear-gradient(180deg, var(--brand), var(--gold)); flex: none;
}
.eyebrow {
  font-size: 11.5px; font-weight: 700; letter-spacing: .14em;
  color: var(--brand); text-transform: uppercase;
}

/* ============================================================
   基础组件
   ============================================================ */
.card {
  background: var(--card); border-radius: var(--radius); padding: 18px;
  border: 1px solid var(--line); box-shadow: var(--shadow-1);
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.card:hover { box-shadow: var(--shadow-2); border-color: rgba(23, 80, 155, .16); }

/* `box(title, body)` 系列帮助函数的标题行（views/resource.js、views/expert.js、views/portal.js）。
 *
 * ⚠️ 这里必须是**类名**而不是行内 `style="margin-bottom:10px"`：行内样式的优先级高于
 * 任何选择器，下面那条 `.card.is-empty > .card-head` 就永远改不动它 —— 第一版正是栽在
 * 这里，空态卡片只收紧了 padding、标题行下面仍留着 10px，实测只省下 12px 高度。 */
.card-head { margin-bottom: 10px; }

/* 空态区块收紧（`box()` 在 body 里发现 `empty-state` 标记时给卡片加 `is-empty`）。
 *
 * 详情页里「服务项目」「设施设备」「入驻条件」「代表成果」这类区块，源数据没填时
 * 只剩一句"暂未填写 X"。若仍按 `padding:18px` 渲染，载体详情页会出现 4 张 100px 高的
 * 空卡片首尾相接 —— 页面主体变成"暂未填写"的重复，真正的信息被挤到看不见。
 *
 * 这里**只压高度、不隐藏**：标题与占位文案都留着，"平台这一项没有数据"仍然读得出来
 * （缺失要看得见），只是不再各占一整片。 */
.card.is-empty { padding: 11px 18px 12px; }
.card.is-empty > .card-head { margin-bottom: 1px; }

.grid { display: grid; gap: 16px; }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-cards { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }

/* 六栏目列表卡片**统一尺寸**（2026-10-08 用户口径：「6 个栏目列表页卡片尺寸，给我改成统一尺寸」）。
 *
 * 六个栏目（技术成果 / 技术需求 / 技术专家 / 技术经理人 / 科技载体 / 科技金融）此前各有
 * 一套卡片：`.result-card`（成果、需求）、`.expert-card`（专家、经理人）、`.resource-card`
 * （载体、金融）。类名不同、内容行数不同（3～5 行），于是同一屏里卡片高度参差，
 * `auto-fill` 栅格又把它们按行对齐 ⇒ 视觉上像"排版坏了"。
 *
 * 修法是**只加一条不依赖具体类名的规则**：
 *   · `min-height` 统一外框高度；
 *   · `display:flex; flex-direction:column` ⇒ 内部行纵向排列，
 *     最后一行由各卡片自己的 `margin-top:auto` 压到底部（六种卡片都已具备）；
 *   · 标题最多 2 行、正文最多 3 行 ⇒ 长标题 / 长简介不会把卡片撑高。
 *
 * ⚠️ 用 `.grid-cards > .card` 而不是六个类名并列：新增栏目时不必再回来加一行选择器，
 *    而这正是"六处各写一份，下一处改动必然只改到其中一处"的老坑。
 * ⚠️ 不写死 `height`：`-webkit-line-clamp` 只压文字不裁内容，写死高度会在
 *    用户放大字号时把"查看档案"按钮切掉。 */
.grid-cards > .card {
  min-height: 196px;
  display: flex; flex-direction: column; gap: 10px;
}
/* `grid-auto-rows: 1fr` ⇒ 同一片栅格里**所有行等高**（不只是行内等高）。
 *
 * 🔴 为什么还要这一条：只有 `min-height` 时，`align-items: stretch`（默认）只能保证
 *    **同一行内**的卡片一样高；行与行之间仍由各自内容决定。线上真浏览器实测（1440px）：
 *    成果/需求/专家/经理人/载体 五栏 4 行行高极差 **0**（本来就一样），
 *    唯独**科技金融**是 [238, 238, 198, 238] —— 第 3 行的三张卡都没有领域标签行，
 *    于是那一行整体矮了 40px，一屏之内就看得出"排版不齐"。
 *    加这一条后：五栏是 no-op（本来就等高），金融那行被抬到 238。
 *
 * ⚠️ 为什么敢全局加：`.grid-cards` 在**线上只剩这 6 个栏目在用** —— `views/knowledge.js`
 *    仍在仓库里但已从 `app.js` 路由中摘除（见 `app.js` 顶部注释），所以不存在
 *    "某个内容长短悬殊的页面被拉成一排空卡"的风险。若将来知识库重新上线，
 *    需要重新评估这一条（届时应把它挂到只属于列表页的类上）。
 */
.grid-cards { grid-auto-rows: 1fr; }
.grid-cards > .card > .result-title,
.grid-cards > .card > .expert-name,
.grid-cards > .card > .expert-head .expert-name {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.grid-cards > .card > .expert-intro { -webkit-line-clamp: 3; }
.row { display: flex; align-items: center; gap: 10px; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.spacer { flex: 1; }
.muted { color: var(--ink-2); }
.small { font-size: 12.5px; }
.tiny { font-size: 11.5px; }
.num { font-variant-numeric: tabular-nums; }

/* ---- 按钮 ---- */
.btn {
  border: 1px solid var(--line); background: #fff; color: var(--ink);
  border-radius: var(--radius-sm); padding: 8px 15px; font-size: 13.5px;
  transition: .16s; white-space: nowrap; font-weight: 500;
  box-shadow: 0 1px 1px rgba(14, 23, 38, .03);
}
.btn:hover { border-color: var(--brand); color: var(--brand); background: #fbfcfe; }
.btn:active { transform: translateY(1px); }
.btn-primary {
  background: linear-gradient(140deg, var(--brand) 0%, var(--brand-deep) 100%);
  color: #fff; border: 1px solid transparent; font-weight: 500;
  box-shadow: 0 2px 8px rgba(11, 46, 99, .22);
}
.btn-primary:hover {
  color: #fff; border-color: transparent;
  background: linear-gradient(140deg, #1c5cae 0%, #123a78 100%);
  box-shadow: 0 4px 14px rgba(11, 46, 99, .3);
}
.btn-ghost { border-color: transparent; background: transparent; color: var(--ink-2); box-shadow: none; }
.btn-ghost:hover { background: #f2f5f9; }
.btn:disabled { opacity: .5; cursor: not-allowed; box-shadow: none; }
.btn-sm { padding: 5px 11px; font-size: 12.5px; border-radius: var(--radius-xs); }

/* ---- 标签 ---- */
.tag {
  display: inline-block; padding: 2px 8px; border-radius: var(--radius-xs); font-size: 11.5px;
  background: #f3f6fa; color: var(--ink-2); margin: 2px 4px 2px 0;
  border: 1px solid var(--line-2);
}
.tag-brand { background: var(--brand-soft); color: var(--brand); border-color: var(--brand-line); }
.tag-ok { background: var(--ok-soft); color: var(--ok); border-color: rgba(21, 128, 61, .18); }
.tag-warn { background: var(--warn-soft); color: var(--warn); border-color: rgba(180, 83, 9, .18); }
/* 人才称号（院士 / 长江学者 / 杰出青年 / 优秀青年 …）：金色系、加粗。
   刻意**不复用** .tag-warn —— 琥珀色在这套色板里代表"待处理 / 有风险"，
   把「院士」标成警告色是语义错位。这里的金是**荣誉**色，与 warn 各管一摊。
   源数据里 `awards` 3,726 条非空（院士 508、长江学者 / 优青 1,383+430…），
   是名录里信息密度最高的一列，此前只在详情页可见。 */
.tag-honor {
  background: #fdf3e0; color: #8a5a06; border-color: rgba(138, 90, 6, .24);
  font-weight: 600;
}
.tag-danger { background: var(--danger-soft); color: var(--danger); border-color: rgba(198, 43, 43, .18); }
/* 卡片右上角的类型徽标：它与左侧机构名同处 .row-between，作为 flex 项会被挤窄，
   「科技园」这类三字标签因此被迫折成「科技 / 园」两行（实测：机构名 12 字时触发）。
   徽标是定长短标签，禁止收缩、禁止折行。
   注意：**不能给 .tag 全局加 nowrap** —— .tag-danger 承载表单校验的长文案
   （见 resource.js 中「请填写对外联系人姓名…」），全局 nowrap 会让它横向溢出。 */
.card-tag { flex: none; white-space: nowrap; }

/* 置顶 / 推荐标签：与 brand 同色系但更醒目，让它在一屏卡片里能被一眼识别。
   刻意不叫「广告」——置顶 / 推荐是平台对外的运营口径，与实际售卖事实一致，
   但不能伪装成「热门」「优质」这类算法口径（那是虚构事实）。 */
.tag-promo { background: var(--brand-soft); color: var(--brand); border-color: var(--brand-line); font-weight: 600; }

/* ---- 广告位 ----
   广告是**附加物**：拉不到时组件会整块移除（见 ads.js），因此这里不需要
   "加载失败"之类的占位样式；容器也不设 min-height，避免留下一条空带。 */
.ad-slot { margin: 0 0 16px; }
.ad-slot:empty { display: none; }
.ad-strip { display: flex; gap: 12px; flex-wrap: wrap; }
.ad-item {
  position: relative; flex: 1 1 320px; min-width: 260px; display: flex; gap: 12px;
  align-items: center; padding: 12px 14px; border: 1px solid var(--line-2);
  border-radius: var(--radius-sm); background: #fbfcfe; color: var(--ink);
  text-decoration: none; transition: border-color .16s, box-shadow .16s;
}
a.ad-item:hover { border-color: var(--brand); box-shadow: var(--shadow-1); }
.ad-img { width: 56px; height: 56px; flex: none; object-fit: cover; border-radius: var(--radius-xs); background: #eef2f7; }
.ad-body { min-width: 0; }
.ad-title { font-weight: 600; font-size: 13.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ad-sub { font-size: 12.5px; color: var(--ink-2); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ad-by { font-size: 11.5px; color: var(--ink-3); margin-top: 3px; }
/* 「广告」标注是**法定义务**（《广告法》要求广告可识别），不能为了美观去掉。
   放在右下角、字号最小，但仍必须在视觉上可辨。 */
.ad-mark {
  position: absolute; right: 8px; bottom: 6px; font-size: 10px; line-height: 1;
  padding: 2px 5px; border-radius: 3px; background: #eef2f7; color: var(--ink-3);
  border: 1px solid var(--line-2);
}

/* ---- 表单 ---- */
.input, .select, textarea.input {
  width: 100%; padding: 9px 12px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  font-size: 13.5px; font-family: inherit; background: #fff; color: var(--ink);
  transition: border-color .16s, box-shadow .16s;
}
.input:hover, .select:hover { border-color: #cfd8e3; }
.input:focus, .select:focus {
  outline: none; border-color: var(--brand); box-shadow: 0 0 0 3px rgba(23, 80, 155, .12);
}
label.field { display: block; margin-bottom: 13px; }
label.field > span {
  display: block; font-size: 12.5px; color: var(--ink-2); margin-bottom: 6px; font-weight: 600;
}

/* ---- 字段标签选择器（.tag-picker / .tp-btn）与省市联动（.region-cascade）----
   这两个组件是「固定取值字段标签化」（2026-10-05 用户第 1 项需求）的前端载体，
   取值域由后端 `app/core/dicts.py` 下发，组件本身由 `static/js/dicts.js` 渲染。

   ⚠️ 它们此前**一条样式都没有**：`.tp-btn` 是裸 `<button>`，于是渲染成一排系统
   默认按钮，更糟的是「已选」（`.on`）与未选**在视觉上完全一样** —— 用户点了
   不知道有没有选中，只会再点一次把它取消掉。组件在代码里成立、在屏幕上看不见，
   比没有组件更危险：静态体检会全绿（它只查取值域是否单源），而用户根本用不了。
   所以样式是组件的一部分，不是可选项。 */
.tag-picker { display: flex; flex-direction: column; gap: 6px; }
.tp-row { display: flex; flex-wrap: wrap; gap: 6px; }
.tp-group { margin-bottom: 6px; }
.tp-group-label { display: block; font-size: 11.5px; color: var(--ink-3); margin-bottom: 4px; }
.tp-btn {
  appearance: none; font: inherit; font-size: 12.5px; line-height: 1.5;
  padding: 4px 10px; border: 1px solid var(--line); border-radius: 999px;
  background: #fff; color: var(--ink-2); cursor: pointer;
  transition: border-color .14s, background .14s, color .14s;
}
.tp-btn:hover { border-color: var(--brand); color: var(--brand); }
.tp-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(23, 80, 155, .12); }
/* 已选态用**实底反白**：必须与 hover 明确区分——两者同时出现（悬停在已选标签上）
   的概率很高，若都只是"变蓝边框"，用户就无法判断自己刚才是选中还是取消。 */
.tp-btn.on { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 600; }
.tp-count.warn { color: var(--warn); }
.tp-empty { display: inline-block; padding: 4px 0; }

/* 省市联动：两级并排。宽度用 flex:1 1 0 而不是固定值，避免"广东省 / 深圳市"这类
   长短不一的名字把第二个 select 挤变形。 */
.region-cascade { display: flex; gap: 8px; }
.region-cascade .rc-prov, .region-cascade .rc-city { flex: 1 1 0; min-width: 0; }

/* 技术领域：标签云 + 逐领域熟悉度。
   为什么不是纯标签云：领域本身是枚举（必须来自字典，否则 AI 判定与筛选都匹配不上），
   而"熟悉度 1-5"是每个领域各自的一个数，两者是**一对多**关系，不能压成一个标签。 */
.domain-tags { display: flex; flex-direction: column; gap: 8px; }
.dt-cloud { display: flex; flex-wrap: wrap; gap: 6px; }
.dt-rows { display: flex; flex-direction: column; gap: 6px; }
.dt-row { display: flex; align-items: center; gap: 8px; }
.dt-name { flex: 0 0 auto; min-width: 108px; font-size: 12.5px; color: var(--ink-2); }
.dt-levels { display: flex; gap: 4px; flex-wrap: wrap; }
.dt-lv {
  appearance: none; font: inherit; font-size: 11.5px; line-height: 1.4;
  width: 26px; height: 24px; padding: 0; border: 1px solid var(--line);
  border-radius: var(--radius-xs); background: #fff; color: var(--ink-3); cursor: pointer;
}
.dt-lv:hover { border-color: var(--brand); color: var(--brand); }
.dt-lv:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(23, 80, 155, .12); }
.dt-lv.on { background: var(--brand-soft); border-color: var(--brand); color: var(--brand); font-weight: 700; }
.dt-empty { font-size: 12.5px; color: var(--ink-3); }

/* 窄屏：两级下拉改为上下排列。并排时每个 select 只剩 ~150px，
   "广东 / 深圳市"这类名字会被截断成"广东 / 深"，用户挑不准。 */
@media (max-width: 520px) {
  .region-cascade { flex-direction: column; }
  .dt-name { min-width: 76px; }
}

/* ---- 进度条 ---- */
.bar-wrap { height: 6px; background: var(--line-2); border-radius: 99px; overflow: hidden; }
.bar { height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--brand), var(--brand-2)); }
.bar-ok { background: linear-gradient(90deg, #2ba25a, #15803d); }
.bar-warn { background: linear-gradient(90deg, #e0a33c, #b45309); }
/* 真实 0 值行：轨道画成虚线而不是浅灰实心。
 * 浅灰实心轨道在 6px 高度上会被整条读成"一根满条"—— 报告 P0-4 对运营后台截图的
 * 那次误读（"0 值也画满整条蓝条"）就是这么来的。虚线让它一眼就是"刻度线"而非"条"。 */
.bar-wrap-zero { background: repeating-linear-gradient(90deg, var(--line-2) 0 3px, transparent 3px 6px); }

/* 计数指标行（运营看板的转化漏斗 / 技术领域分布） */
.metric-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.metric-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 条形固定占 34%：不固定的话每行都按自己标签的长度分配宽度，几行下来条形起点参差不齐，
 * 「同一刻度下比长短」这件事就不成立了 —— 而比长短正是这张图唯一的用途。 */
.metric-bar { flex: 0 0 34%; }
.metric-val { flex: 0 0 auto; width: 34px; text-align: right; font-variant-numeric: tabular-nums; }
.metric-group { margin: 10px 0 6px; }
.metric-group:first-child { margin-top: 2px; }

/* ---- 空态 / 加载 ---- */
.empty, .loading-box { padding: 52px 16px; text-align: center; color: var(--ink-3); }
.empty > div:first-child { margin-bottom: 10px; }
.skeleton {
  background: linear-gradient(90deg, #eef2f7 25%, #f8fafc 50%, #eef2f7 75%);
  background-size: 200% 100%; animation: pulse 1.2s infinite; border-radius: var(--radius-sm);
}
@keyframes pulse { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ---- Toast（提醒浮层）----
 * 位置：**页面正中**（用户反馈：原来贴在右上角，视线要在"正在操作的地方"和
 * "右上角"之间来回找，尤其在手机上基本等于看不见）。
 * 用 `inset:0` + grid 把整组提示居中，多条自然竖排。
 * `pointer-events:none` 是关键而不是修饰：居中的提示正好盖在表单/按钮上，
 * 不关掉指针事件的话，用户点"提交"会点在提示上 —— 表现为"点了没反应"。 */
.toast-wrap {
  position: fixed; inset: 0; z-index: 95; display: grid; grid-auto-rows: min-content;
  justify-items: center; align-content: center; gap: 10px; padding: 20px; pointer-events: none;
}
.toast {
  background: #fff; border-left: 3px solid var(--brand); box-shadow: var(--shadow-2);
  padding: 12px 16px; border-radius: var(--radius-sm); font-size: 13.5px; max-width: 340px;
  border-top: 1px solid var(--line); border-right: 1px solid var(--line); border-bottom: 1px solid var(--line);
  animation: popin .2s ease-out;
}
/* 从上方微微落下 + 缩放，与"居中弹出"的观感一致；
 * 原来的 `slidein` 是从右侧平移进来的，那是右上角定位时代的动画。 */
@keyframes popin { from { opacity: 0; transform: translateY(-8px) scale(.97); } to { opacity: 1; transform: none; } }
.toast.ok { border-left-color: var(--ok); }
.toast.err { border-left-color: var(--danger); }
/* ---- 弹层 ---- */
.modal-mask {
  position: fixed; inset: 0; background: rgba(11, 46, 99, .42); z-index: 80;
  display: grid; place-items: center; padding: 20px;
  backdrop-filter: blur(2px);
}
.modal {
  background: #fff; border-radius: 14px; width: 100%; max-width: 560px;
  max-height: 86vh; overflow: auto; box-shadow: var(--shadow-3);
}
.modal-head {
  padding: 16px 20px; border-bottom: 1px solid var(--line); font-weight: 700;
  display: flex; justify-content: space-between; align-items: center;
}
.modal-body { padding: 20px; }

/* ---- 业务浮层（登录 / 注册）----
 * 复用 `.modal-mask` 的**居中定位**（`display:grid; place-items:center`），
 * 但不复用 `.modal` 的 560px 固定宽 —— 登录浮层是"左品牌 + 右表单"两栏，
 * 注册浮层是单栏长表单，两者宽度与内边距都不一样。
 * z-index 排在普通 modal（80）之下：浮层里再弹确认框时，确认框要在上面。 */
.overlay-mask { z-index: 86; }
/* 🔴 面板宽度必须**贴合内容**，不能 `width: 100%`。
 *
 * 旧写法是 `width: 100%`。实测（1440px 视口）：遮罩内边距 20px ⇒ 面板宽 **1400px**，
 * 而面板里的 `.login-wrap` 自己限了 `max-width: 940px` 且 `margin: 0`（左对齐）
 * ⇒ 登录卡贴在左边，右侧留下 **460px 空白**；关闭按钮按 `right: 12px` 绝对定位，
 * 被推到 **x=1388** —— 空白区的尽头，离登录卡 440px 远。用户的原话是
 * 「登录/注册弹窗的位置、关闭按钮位置都还需要完善」，指的就是这个。
 *
 * 改成 `width: auto` 后由遮罩的 `place-items: center` 居中，面板即内容宽度，
 * 关闭按钮的 `right` 也就落回登录卡的右上角。
 */
.overlay-panel {
  width: auto; max-width: 100%; max-height: 92vh; overflow: auto; position: relative;
}
/* 登录浮层宽度**只在面板这一处**定；`.login-wrap` 不再自己限宽 ——
 * 两个元素各写一个宽度、其中一个还左对齐，就是上面那次事故的直接成因。 */
.overlay-panel.login-overlay { max-width: 940px; }
.overlay-panel.card-panel {
  background: #fff; border-radius: 16px; padding: 28px 30px; max-width: 640px;
  box-shadow: var(--shadow-3);
}
/* 注册浮层：把表单**收进 92vh**，别让首屏就出现内部滚动条。
 *
 * 实测（1440×900）：表单内容 **917px** / 可用 **828px** ⇒ 溢出 89px，
 * 最底部的「注册并登录」被切掉一半 —— 用户看到的是一个"截断的按钮"，
 * 会以为页面坏了。
 *
 * 收紧只作用在 `.overlay-panel.card-panel` 这一个容器内，**不动全局**
 * `.card` / `.page-head` / `.field`：这些是列表页也在用的基线，动它们等于
 * 顺带改了几十个页面的密度。省下的正是那 89px：
 *   面板内边距 28→20（16px） + 页头下边距 20→12 与标题收紧（约 30px）
 *   + 每条字段间距 13→9（约 28px） + 内层卡片内边距 18→14（8px）。
 * `p` 的字号**刻意不动**：它是正文级文案，缩小会碰可读性下限。 */
.overlay-panel.card-panel { padding: 20px 24px; }
.overlay-panel.card-panel .page-head { margin-bottom: 12px; }
.overlay-panel.card-panel .page-head h1 { font-size: 20px; }
.overlay-panel.card-panel .field { margin-bottom: 6px; }
.overlay-panel.card-panel .card { padding: 14px 16px; }
/* 浮层里的登录块：把整屏版的 `min-height:100vh` 与页面级渐变收掉，
 * 只保留"两栏卡片"的形态。渐变改由 `.login-hero` 自己承担。 */
.login-overlay .login-wrap {
  min-height: auto; margin: 0; padding: 0; max-width: 100%;
  grid-template-columns: minmax(0, 1fr) 390px; gap: 0;
  background: #fff; border-radius: 16px; box-shadow: var(--shadow-3); overflow: hidden;
}
.login-overlay .login-hero {
  padding: 40px 36px; height: 100%;
  background:
    radial-gradient(80% 60% at 12% 8%, rgba(43, 116, 196, .18) 0%, transparent 60%),
    radial-gradient(70% 60% at 92% 92%, rgba(184, 135, 59, .14) 0%, transparent 60%),
    linear-gradient(160deg, #eef2f9 0%, #f7f9fc 45%, #eaeef5 100%);
}
.login-overlay .login-card { border: 0; box-shadow: none; border-radius: 0; padding: 36px 30px; }
.login-overlay .login-slogan { font-size: 28px; }
/* 浮层关闭按钮。
 *
 * 位置：面板右上角（面板现在是内容宽度，所以就是登录卡的角）。
 * 旧实现是 `padding: 4px` 的 20×26px 小叉、半透明白底 —— 实测落在 x=1388、
 * 宽 20px，压在 460px 空白区的最右边，用户"找不到关闭按钮"。
 *
 * 用 `position: sticky` 而不是 `absolute`：面板内容高于视口时会**内部滚动**
 * （max-height: 92vh + overflow: auto），`absolute` 会随着内容一起滚走，
 * 滚到底部的人就再也看不到关闭入口。`sticky` 让它始终贴在可视区顶部。
 *
 * `margin: 8px 10px -40px auto`：`margin-left: auto` 把一个 32px 宽的块级元素
 * 右对齐；`margin-bottom: -40px`（= 32 + 8）把自身占位抵掉，后面的内容照旧从
 * 面板顶部开始，不会凭空多出一条 40px 的白带。
 */
.overlay-close {
  position: sticky; top: 8px; z-index: 3;
  display: flex; width: 32px; height: 32px; margin: 8px 10px -40px auto;
  align-items: center; justify-content: center; padding: 0;
  font-size: 14px; line-height: 1; color: var(--ink-2, #475569);
  background: #fff; border: 1px solid var(--line-2); border-radius: 50%;
  box-shadow: var(--shadow-1); cursor: pointer;
}
.overlay-close:hover { background: var(--bg-2, #f8fafc); color: var(--ink, #0f172a); }

/* ============================================================
   首屏 Hero（仅成果广场首屏）
   ============================================================ */
.hero {
  position: relative; overflow: hidden; border-radius: 16px; margin-bottom: 22px;
  padding: 40px 44px; color: #fff;
  background:
    radial-gradient(90% 130% at 88% 12%, rgba(184, 135, 59, .28) 0%, transparent 52%),
    radial-gradient(80% 120% at 8% 100%, rgba(43, 116, 196, .5) 0%, transparent 55%),
    linear-gradient(135deg, #0b2e63 0%, #17509b 52%, #1d64b4 100%);
  box-shadow: 0 12px 40px rgba(11, 46, 99, .22);
}
/* 细网格纹理：让大面积深色不显空 */
.hero::before {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: .5;
  background-image:
    linear-gradient(rgba(255, 255, 255, .06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, .06) 1px, transparent 1px);
  background-size: 46px 46px;
  mask-image: radial-gradient(80% 100% at 20% 0%, #000 0%, transparent 78%);
  -webkit-mask-image: radial-gradient(80% 100% at 20% 0%, #000 0%, transparent 78%);
}
.hero > * { position: relative; }
.hero .eyebrow { color: rgba(255, 255, 255, .72); }
.hero h1 {
  margin: 10px 0 10px; font-size: 30px; line-height: 1.4; font-weight: 800;
  letter-spacing: -.6px; color: #fff; max-width: 640px;
}
.hero .lead { margin: 0; color: rgba(255, 255, 255, .8); font-size: 14px; max-width: 620px; }
.hero-actions { display: flex; gap: 12px; margin-top: 24px; flex-wrap: wrap; }
.hero .btn { border-color: rgba(255, 255, 255, .38); background: rgba(255, 255, 255, .1); color: #fff; }
.hero .btn:hover { background: rgba(255, 255, 255, .18); border-color: rgba(255, 255, 255, .6); color: #fff; }
.hero .btn-solid { background: #fff; color: var(--brand-deep); border-color: #fff; font-weight: 600; }
.hero .btn-solid:hover { background: #f4f7fc; color: var(--brand-deep); }
/* 右上角数据条。整组与左侧文案之间一道分隔线，组内每项之间再各一道 ——
   这样读起来是"一排指标"，而不是四个散落的数字。 */
.hero-stats {
  display: flex; align-items: flex-start; gap: 0; margin-left: auto; flex: none;
  padding-left: 34px; border-left: 1px solid rgba(255, 255, 255, .18);
}
.hero-stat { padding: 0 26px; }
.hero-stat:first-child { padding-left: 0; }
.hero-stat:last-child { padding-right: 0; }
.hero-stat + .hero-stat { border-left: 1px solid rgba(255, 255, 255, .14); }
.hero-stat b { display: block; font-size: 27px; font-weight: 800; letter-spacing: -.5px; font-variant-numeric: tabular-nums; }
.hero-stat span { font-size: 12px; color: rgba(255, 255, 255, .72); }
.hero-row { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }

/* ============================================================
   业务组件
   ============================================================ */
.result-card { display: flex; flex-direction: column; gap: 10px; }
.result-card:hover { transform: translateY(-2px); }
.result-title { font-size: 15px; font-weight: 600; line-height: 1.5; }
.result-title a { color: var(--ink); }
.result-title a:hover { color: var(--brand); }
.score-pill {
  font-variant-numeric: tabular-nums; font-weight: 700; padding: 3px 9px;
  border-radius: var(--radius-xs); font-size: 13px;
}
.score-high { background: var(--ok-soft); color: var(--ok); border: 1px solid rgba(21, 128, 61, .18); }
.score-mid { background: var(--warn-soft); color: var(--warn); border: 1px solid rgba(180, 83, 9, .18); }
.score-low { background: #f3f6fa; color: var(--ink-2); border: 1px solid var(--line-2); }

.stat-card {
  text-align: left; border-top: 2px solid var(--brand);
  background: linear-gradient(180deg, #fff 0%, #fcfdff 100%);
}
.stat-value { font-size: 27px; font-weight: 800; letter-spacing: -.6px; font-variant-numeric: tabular-nums; }
.stat-label { color: var(--ink-2); font-size: 12.5px; }

.factor-row {
  display: grid; grid-template-columns: 84px 1fr 44px;
  align-items: center; gap: 10px; margin: 7px 0; font-size: 12.5px;
}
.factor-name { color: var(--ink-2); }

.timeline { border-left: 2px solid var(--line); padding-left: 18px; margin-left: 6px; }
.timeline-item { position: relative; padding-bottom: 18px; }
.timeline-item::before {
  content: ''; position: absolute; left: -25px; top: 5px; width: 10px; height: 10px;
  border-radius: 50%; background: var(--brand); border: 2px solid #fff;
  box-shadow: 0 0 0 2px var(--brand-soft);
}

.explain-block { border-radius: var(--radius-sm); padding: 12px 14px; background: #f8fafc; border: 1px solid var(--line-2); }
.explain-block h5 { margin: 0 0 6px; font-size: 12.5px; color: var(--ink-2); }
.explain-block ul { margin: 0; padding-left: 18px; font-size: 13px; }
.explain-block li { margin: 3px 0; }
/* ---- 系统信息（可折叠）----
 * 承载"内部组件标识 / 版本串"这类技术细节（报告 P0-6 修法②：迁到折叠区）。
 * 默认折叠是关键：运营平时看不见它，排障时自己展开 —— 而不是把
 * `offline-rule-engine` 摊在看板首屏上，让所有人读成"这平台没上大模型"。
 * 用原生 <details> 而不是自绘折叠：键盘可达、屏幕阅读器可读、无 JS 依赖。 */
.sysinfo { border-radius: var(--radius-sm); padding: 10px 14px; background: #f8fafc; border: 1px solid var(--line-2); }
.sysinfo > summary { cursor: pointer; font-size: 12.5px; color: var(--ink-2); list-style: none;
  display: flex; align-items: center; gap: 6px; }
.sysinfo > summary::-webkit-details-marker { display: none; }
.sysinfo > summary::before { content: '▸'; color: var(--ink-3); transition: transform .15s ease; }
.sysinfo[open] > summary::before { transform: rotate(90deg); }
.sysinfo > ul { margin: 8px 0 6px; padding-left: 18px; font-size: 13px; }
.sysinfo > ul li { margin: 3px 0; }

.step-flow { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.step-dot {
  display: flex; align-items: center; gap: 6px; padding: 4px 11px;
  border-radius: 99px; background: #f3f6fa; color: var(--ink-3); font-size: 12px;
  border: 1px solid var(--line-2);
}
.step-dot.done { background: var(--ok-soft); color: var(--ok); border-color: rgba(21, 128, 61, .18); }
.step-dot.current {
  background: var(--brand-soft); color: var(--brand); font-weight: 600; border-color: var(--brand-line);
}

.table { width: 100%; border-collapse: collapse; font-size: 13px; }
.table th {
  text-align: left; padding: 10px 12px; color: var(--ink-2); font-weight: 600; font-size: 12.5px;
  background: #f7f9fc; border-bottom: 1px solid var(--line);
}
.table td { padding: 11px 12px; border-bottom: 1px solid var(--line-2); vertical-align: middle; }
.table tbody tr:hover { background: #fafcff; }

/* ---- 登录页 ---- */
.login-wrap {
  min-height: 100vh; display: grid; grid-template-columns: minmax(0, 1fr) 410px;
  gap: 60px; align-items: center; max-width: 1120px; margin: 0 auto; padding: 52px 32px;
  background:
    radial-gradient(80% 60% at 12% 8%, rgba(43, 116, 196, .16) 0%, transparent 60%),
    radial-gradient(70% 60% at 92% 92%, rgba(184, 135, 59, .12) 0%, transparent 60%),
    linear-gradient(160deg, #eef2f9 0%, #f7f9fc 45%, #eaeef5 100%);
}
.login-card {
  width: 100%; max-width: none; background: #fff; border-radius: 16px; padding: 32px;
  border: 1px solid var(--line); box-shadow: var(--shadow-2);
}
.demo-acc {
  display: grid; grid-template-columns: 1fr auto; gap: 6px; padding: 8px 11px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: 12.5px; margin-bottom: 7px;
  transition: .16s;
}
.demo-acc:hover { border-color: var(--brand); background: var(--brand-soft); }
.nav-logo.lg { width: 46px; height: 46px; border-radius: 12px; font-size: 17px; }
.nav-logo.lg { background: linear-gradient(140deg, var(--brand) 0%, var(--brand-deep) 100%); }
.login-brand { font-weight: 800; font-size: 18px; letter-spacing: .2px; }
.login-slogan {
  font-size: 34px; line-height: 1.4; margin: 0 0 14px; letter-spacing: -.8px;
  font-weight: 800; color: var(--brand-deep);
}
.login-sub { color: var(--ink-2); font-size: 14px; margin-bottom: 24px; }
.login-points { display: grid; gap: 11px; max-width: 470px; }
.login-point {
  background: rgba(255, 255, 255, .8); border: 1px solid rgba(226, 232, 240, .9);
  border-radius: var(--radius); padding: 13px 15px; backdrop-filter: blur(6px);
  transition: transform .18s, box-shadow .18s, border-color .18s;
}
.login-point:hover { transform: translateX(3px); box-shadow: var(--shadow-1); border-color: var(--brand-line); }
.login-point b { display: block; font-size: 13.5px; margin-bottom: 2px; }
.login-point span { color: var(--ink-2); font-size: 12.5px; }

.ai-badge {
  display: inline-flex; align-items: center; gap: 4px; font-size: 11px; padding: 2px 8px;
  border-radius: var(--radius-xs); background: var(--brand-soft); color: var(--brand);
  border: 1px solid var(--brand-line);
}

/* ---- 七大栏目新增件 ---- */
.guest-bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 32px; background: linear-gradient(90deg, var(--brand-soft), #faf7f1);
  border-bottom: 1px solid var(--brand-line); color: var(--ink-2);
}
.guest-bar > span:first-child { font-weight: 600; color: var(--ink); }
.guest-bar .btn { margin-left: auto; }

.cert-badge {
  display: inline-flex; align-items: center; gap: 3px; margin-left: 6px;
  padding: 1px 7px; border-radius: var(--radius-xs); font-size: 11px; font-weight: 600;
  background: var(--ok-soft); color: var(--ok); border: 1px solid rgba(21, 128, 61, .22);
  white-space: nowrap;
}
.notice-card { text-align: center; padding: 48px 20px; }
.notice-card p { margin: 8px auto 0; max-width: 440px; }

.publish-card { display: flex; flex-direction: column; }
.publish-card:hover { transform: translateY(-2px); }

.expert-card {
  display: flex; flex-direction: column; gap: 10px; cursor: pointer; border: 1px solid transparent;
}
.expert-card:hover { transform: translateY(-3px); border-color: var(--brand-line); }
.expert-head { display: flex; align-items: flex-start; gap: 12px; }
/* 头像 / 徽标配色：色相由 JS 传入 --av-h（已收敛在品牌蓝 200-240 区间），
   配色公式统一下沉到 CSS —— 个体之间有细微差异以保持辨识度，但整体不跳出蓝色系，
   避免"按名字哈希出彩虹色"那种社交产品观感。 */
.expert-avatar, .resource-badge {
  background: linear-gradient(135deg,
    hsl(var(--av-h, 214) 56% 47%),
    hsl(calc(var(--av-h, 214) + 16) 60% 34%));
}
.expert-avatar {
  width: 46px; height: 46px; border-radius: 13px; color: #fff; flex-shrink: 0;
  display: grid; place-items: center; font-size: 18px; font-weight: 700;
  box-shadow: 0 4px 12px rgba(14, 23, 38, .16);
}
.expert-avatar.lg { width: 66px; height: 66px; border-radius: 18px; font-size: 26px; }
.expert-name { font-size: 15px; font-weight: 700; line-height: 1.35; }
.expert-rating { text-align: right; flex-shrink: 0; }
.star { color: #d99a2b; letter-spacing: 1px; font-size: 13px; line-height: 1.2; }
.expert-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.expert-intro {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 34px;
}
.expert-hero, .resource-hero {
  position: relative; overflow: hidden;
  background:
    radial-gradient(120% 140% at 0% 0%, hsl(var(--h, 215) 80% 96%) 0%, transparent 55%),
    radial-gradient(120% 140% at 100% 100%, hsl(calc(var(--h, 215) + 40) 70% 96%) 0%, transparent 55%),
    #fff;
}

.resource-card { display: flex; flex-direction: column; gap: 10px; cursor: pointer; border: 1px solid transparent; }
.resource-card:hover { transform: translateY(-3px); border-color: var(--brand-line); }
.resource-badge {
  width: 32px; height: 32px; border-radius: 9px; flex-shrink: 0; color: #fff;
  font-size: 13px; font-weight: 700; display: grid; place-items: center;
  box-shadow: 0 3px 9px rgba(14, 23, 38, .14);
}
.meta-item { padding: 9px 0; border-bottom: 1px solid var(--line-2); }
.meta-item:last-child { border-bottom: none; }
.kv { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 5px 0; }

.consult-row { transition: background .15s; border-radius: var(--radius-sm); padding-left: 8px !important; padding-right: 8px !important; }
.consult-row:hover { background: #f8fafc; }
.broker-line { transition: background .15s; }
.broker-line:hover { background: #f8fafc; }
.filter-bar { background: linear-gradient(180deg, #fff, #fcfdff); }

/* 页面切换渐入 */
#view { animation: fadein .22s ease-out; }
@keyframes fadein { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* ============================================================
   沟通留痕（结构化事件，不是聊天窗）
   ============================================================ */
.trace-item { padding: 12px 0; border-bottom: 1px solid var(--line-2); }
.trace-item:last-child { border-bottom: none; }
.trace-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.trace-channel {
  flex: none; font-size: 11px; padding: 1px 7px; border-radius: var(--radius-xs);
  background: var(--brand-soft); color: var(--brand); border: 1px solid var(--brand-line);
}
.trace-time { font-size: 11.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.trace-topic { font-size: 13.5px; font-weight: 600; margin-top: 6px; }
.trace-body { font-size: 13px; color: var(--ink-2); margin-top: 4px; }
.trace-conclusion {
  margin-top: 6px; padding: 8px 11px; border-radius: var(--radius-sm);
  background: #f8fafc; border-left: 2px solid var(--brand); font-size: 13px;
}
.trace-meta { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 6px; font-size: 12px; color: var(--ink-3); }
/* 停滞/待对方响应：红色左边框，一眼看出卡在谁 */
.trace-pending { border-left: 4px solid var(--danger); padding-left: 10px; margin-left: -10px; }

/* 结项确认条 */
.settle-bar { display: flex; gap: 18px; flex-wrap: wrap; align-items: center; }
.settle-flag { display: flex; align-items: center; gap: 6px; font-size: 13px; }
.settle-flag .mark {
  width: 18px; height: 18px; border-radius: 50%; display: grid; place-items: center;
  font-size: 11px; color: #fff; background: var(--line); flex: none;
}
.settle-flag.on .mark { background: var(--ok); }
.settle-flag.on { color: var(--ok); font-weight: 600; }

/* ============================================================
   业绩看板
   ============================================================ */
.perf-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(96px, 1fr)); gap: 14px; }
.perf-metric b {
  display: block; font-size: 21px; font-weight: 800; letter-spacing: -.4px;
  font-variant-numeric: tabular-nums; color: var(--brand-deep);
}
.perf-metric span { font-size: 12px; color: var(--ink-2); }
.perf-split {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12px;
  padding: 2px 8px; border-radius: var(--radius-xs);
  background: var(--gold-soft); color: #8a6427; border: 1px solid rgba(184, 135, 59, .28);
}
.rank-no {
  width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center;
  font-size: 12px; font-weight: 700; background: #f3f6fa; color: var(--ink-2); flex: none;
}
.rank-no.top { background: var(--brand); color: #fff; }

/* ============================================================
   页脚
   ============================================================ */
.footer {
  background: var(--brand-deep); color: rgba(255, 255, 255, .68);
  border-top: 3px solid var(--gold); margin-top: 8px;
}
.footer-inner {
  max-width: 1240px; margin: 0 auto; padding: 40px 32px 26px;
  display: grid; grid-template-columns: 1.4fr repeat(4, 1fr); gap: 32px;
}
.footer h5 {
  color: #fff; font-size: 13px; font-weight: 700; margin: 0 0 14px; letter-spacing: .04em;
}
.footer p { margin: 0 0 12px; font-size: 12.5px; line-height: 1.8; max-width: 340px; }
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.footer li { font-size: 12.5px; }
.footer a { color: rgba(255, 255, 255, .7); transition: .16s; }
.footer a:hover { color: #fff; }
.footer-brand { display: flex; align-items: center; gap: 11px; margin-bottom: 14px; }
.footer-brand .nav-logo { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .18); }
.footer-brand .cn { color: #fff; font-weight: 700; font-size: 15px; }
.footer-brand .en { display: block; font-size: 9.5px; letter-spacing: .12em; opacity: .6; text-transform: uppercase; }
.footer-bottom {
  border-top: 1px solid rgba(255, 255, 255, .12); padding: 16px 32px;
  max-width: 1240px; margin: 0 auto; display: flex; gap: 16px; flex-wrap: wrap;
  font-size: 12px; color: rgba(255, 255, 255, .5);
}
.footer-bottom .spacer { margin-left: auto; }

/* ============================================================
   金融机构栏目（额度 / 费率双指标 + 授信产品）
   ============================================================ */
.fin-metrics {
  display: flex; gap: 18px; flex-wrap: wrap;
  padding: 9px 12px; border-radius: var(--radius-sm);
  background: var(--brand-soft); border: 1px solid var(--brand-line);
}
.fin-metrics > div { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.fin-metrics b { color: var(--brand-deep); font-size: 13px; }

.credit-item { padding: 11px 0; border-bottom: 1px solid var(--line-2); }
.credit-item:last-child { border-bottom: none; }

/* 协议 / 政策文档 */
.doc { max-width: 900px; }
.doc-meta {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding-bottom: 14px; margin-bottom: 6px; border-bottom: 1px solid var(--line-2);
}
.doc-meta .btn { margin-left: 0; }
.doc h4 {
  margin: 22px 0 8px; font-size: 14.5px; font-weight: 700;
  padding-left: 10px; border-left: 3px solid var(--brand-line); line-height: 1.5;
}
.doc p { margin: 0 0 10px; font-size: 13.5px; line-height: 1.95; color: var(--ink-2); }
.doc ul, .doc ol { margin: 0 0 12px; padding-left: 22px; }
.doc li { font-size: 13.5px; line-height: 1.9; color: var(--ink-2); margin-bottom: 4px; }

/* 注册页协议勾选：整行可点，勾选框与文案对齐 */
.agree-line {
  display: flex; align-items: flex-start; gap: 9px; margin: 4px 0 12px;
  padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--brand-soft); border: 1px solid var(--brand-line);
  cursor: pointer;
}
.agree-line input[type="checkbox"] { width: 15px; height: 15px; margin: 3px 0 0; accent-color: var(--brand); flex: none; }

/* ============================================================
   移动端
   ============================================================ */
/* ============================================================
   第二期：个人中心 · 身份认证 · 机构管理
   仅追加，不改动上方任何既有规则；配色沿用 token（金色只作强调）。
   ============================================================ */
.profile-head { display: flex; align-items: center; gap: 18px; }
.profile-avatar {
  width: 64px; height: 64px; border-radius: 18px; flex: none; color: #fff;
  font-size: 26px; font-weight: 700; display: grid; place-items: center;
  background: linear-gradient(140deg, var(--brand) 0%, var(--brand-deep) 100%);
  box-shadow: 0 6px 18px rgba(11, 46, 99, .22);
}
.profile-meta { display: flex; flex-wrap: wrap; gap: 6px 22px; margin-top: 6px; font-size: 13px; }
.kv-inline { display: inline-flex; align-items: center; gap: 6px; }
.kv-inline .k { color: var(--ink-3); font-size: 12.5px; }
.kv-inline .v { color: var(--ink); font-weight: 500; }

/* ---- 身份卡：三张并列，状态各自独立 ---- */
.id-card { display: flex; flex-direction: column; border-top: 2px solid var(--line); }
.id-card.is-certified { border-top-color: var(--ok); }
.id-card.is-pending { border-top-color: var(--warn); }
.id-card.is-rejected { border-top-color: var(--danger); }
.id-icon {
  width: 38px; height: 38px; border-radius: 11px; flex: none; color: #fff;
  font-size: 16px; font-weight: 700; display: grid; place-items: center;
  background: linear-gradient(140deg, var(--brand) 0%, var(--brand-deep) 100%);
  box-shadow: 0 3px 10px rgba(11, 46, 99, .2);
}
.id-card.is-certified .id-icon { background: linear-gradient(140deg, #2ba25a 0%, var(--ok) 100%); }
.id-card.is-pending .id-icon { background: linear-gradient(140deg, #e0a33c 0%, var(--warn) 100%); }
.id-card.is-rejected .id-icon { background: linear-gradient(140deg, #d9534f 0%, var(--danger) 100%); }
.id-meta { margin-top: 10px; }
.id-meta .kv { padding: 3px 0; font-size: 12.5px; }
.id-meta .kv b { font-weight: 600; font-variant-numeric: tabular-nums; }
.id-note {
  margin-top: 10px; padding: 8px 11px; border-radius: var(--radius-sm); font-size: 12.5px;
  background: var(--brand-soft); border-left: 2px solid var(--brand); color: var(--ink-2);
}
.id-note.reject { background: var(--danger-soft); border-left-color: var(--danger); color: var(--danger); }
.id-note.warn { background: var(--warn-soft); border-left-color: var(--warn); color: var(--warn); }
.id-actions { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--line-2); display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* ---- 认证类型切换 ---- */
.cert-tabs { display: flex; gap: 8px; flex-wrap: wrap; }
.cert-tab {
  padding: 8px 16px; border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: #fff; font-size: 13.5px; color: var(--ink-2); transition: .16s;
}
.cert-tab:hover { border-color: var(--brand); color: var(--brand); }
.cert-tab.active { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); font-weight: 600; }

/* ---- 身份认证的子类切换（技术经理人 / 技术专家）：比父页签轻一档 ---- */
.cert-subtabs { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.cert-subtab {
  padding: 6px 13px; border: 1px solid var(--line); border-radius: 999px;
  background: #fff; font-size: 12.5px; color: var(--ink-3); transition: .16s;
}
.cert-subtab:hover { border-color: var(--brand); color: var(--brand); }
.cert-subtab.active { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); font-weight: 600; }

/* ---- 分段控件（如「认领已有机构 / 新建机构」）：互斥二选一 ---- */
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.seg-btn {
  padding: 7px 15px; border: 0; border-right: 1px solid var(--line);
  background: #fff; font-size: 13px; color: var(--ink-2); cursor: pointer; transition: .16s;
}
.seg-btn:last-child { border-right: 0; }
.seg-btn:hover { color: var(--brand); }
.seg-btn.active { background: var(--brand-soft); color: var(--brand); font-weight: 600; }

/* ---- 通用字段容器（div.field，与 label.field 同款） ---- */
.field { display: block; margin-bottom: 13px; }
.field > span:first-child {
  display: block; font-size: 12.5px; color: var(--ink-2); margin-bottom: 6px; font-weight: 600;
}
/* 只读主体信息：看得见但明确「改不了」 */
.readonly-field { background: var(--bg-2); color: var(--ink-2); cursor: not-allowed; border-style: dashed; }
.form-set { border: 0; padding: 0; margin: 0; min-width: 0; }
.form-set[disabled] { opacity: .62; }

/* ---- 上传区 ---- */
.uploader { position: relative; }
.uploader-drop {
  border: 1px dashed var(--line); border-radius: var(--radius-sm); padding: 18px 14px;
  text-align: center; color: var(--ink-2); background: #fbfcfe; cursor: pointer;
  transition: border-color .16s, background .16s, color .16s;
}
.uploader-drop:hover { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); }
.uploader.dragover .uploader-drop { border-color: var(--brand); background: var(--brand-soft); color: var(--brand); }
.uploader-drop .up-plus { font-size: 22px; line-height: 1; opacity: .45; margin-bottom: 4px; }
.uploader-list { display: grid; gap: 8px; margin-top: 10px; }
.file-item {
  display: flex; align-items: center; gap: 10px; padding: 8px 11px; font-size: 13px;
  border: 1px solid var(--line-2); border-radius: var(--radius-sm); background: #fff;
}
.file-item.up { opacity: .6; }
.file-item .fname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-item .fsize { flex: none; color: var(--ink-3); font-size: 12px; font-variant-numeric: tabular-nums; }

/* ---- 对外联系人区块：发布表单与技术经理人档案共用 ---- */
.contact-block {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 14px 16px 6px; margin: 0 0 14px; background: #fcfdff;
}
.contact-block .cb-title {
  display: flex; align-items: baseline; gap: 4px; flex-wrap: wrap;
  font-size: 13px; font-weight: 700; margin-bottom: 10px;
}
.contact-block .cb-title::before {
  content: ''; width: 3px; height: 12px; border-radius: 2px; margin-right: 6px;
  background: linear-gradient(180deg, var(--brand), var(--gold));
}

/* ---- 变更对比列表（档案保存结果）---- */
.diff-list { border-top: 1px solid var(--line-2); }
.diff-item {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 7px 0; border-bottom: 1px dashed var(--line-2); font-size: 13px;
}
.diff-item .k { width: 96px; flex: none; color: var(--ink-3); font-size: 12.5px; }
.diff-item .old { color: var(--ink-3); text-decoration: line-through; }
.diff-item .new { color: var(--brand); font-weight: 600; }

/* ---- 行内提示条：info / warn / danger 三态，均用既有 token ---- */
.notice-inline {
  display: flex; gap: 10px; align-items: flex-start; margin-top: 12px;
  padding: 11px 13px; border-radius: var(--radius-sm); font-size: 12.5px; line-height: 1.7;
  background: var(--brand-soft); border: 1px solid var(--brand-line); color: var(--ink-2);
}
.notice-inline.warn { background: var(--warn-soft); border-color: rgba(180, 83, 9, .22); color: var(--warn); }
.notice-inline.danger { background: var(--danger-soft); border-color: rgba(198, 43, 43, .22); color: var(--danger); }

/* ---- 危险动作按钮（报告 P1-9 / §4.8）----
   为什么必须新加这个类：本仓此前**没有**危险按钮样式，所以「重建检索索引」
   用的是与普通按钮完全相同的 `.btn` —— 报告实测原话就是"视觉上与'刷新'同级"。
   问题不在"忘了加类"，而在"那个类不存在"：任何人想给它加危险色都无处可加。 */
.btn-danger { color: var(--danger); background: var(--danger-soft); border-color: var(--danger); }
.btn-danger:hover { background: var(--danger); color: #fff; }

/* ---- 高级操作折叠区（报告 P1-9 / §4.8）----
   重成本、影响全局的动作一律收进这里。默认收起，标题里就写明它是"重成本"。 */
.advanced-ops { border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--card); padding: 12px 14px; }
.advanced-ops > summary { cursor: pointer; font-weight: 600; font-size: 14px; }
.advanced-ops > summary::marker { color: var(--danger); }

@media (max-width: 900px) {
  /* ⚠️ 必须是 `minmax(0, 1fr)`，不能写裸的 `1fr`。
     裸 `1fr` 等价于 `minmax(auto, 1fr)`，而 `auto` 的最小尺寸是内容的 **min-content** ——
     于是当卡片里有一个"不可断行"的长串时，列**不肯缩**，直接顶破容器。
     实测：`#/financial` / `#/carriers` 在 390px 下网格只有 358px，
     而列被撑到 **449px / 426px**，整页横向溢出到 465px（页面级 scrollWidth 也跟着坏了）。
     这两页的卡片里塞的是机构名 + 标签，「珠三角技术转移服务中心…」这类串凑起来
     就超过了 358px。基准样式里的 `.grid-2/3/4` 早就是 `minmax(0, 1fr)`，
     只有这一档漏了 —— 所以是"同一个写法漏了一处"，不是新问题。 */
  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .profile-head { flex-direction: column; align-items: flex-start; gap: 12px; }
  .topbar-inner { padding: 0 16px; }
  .topbar .right { display: none; }
  /* ⚠️ 导航在 900px 档里**不再有任何规则**：它的三档宽度全部由上面的
     `@media (max-width: 1279px)` 统一管（看那一档的实测表与说明）。
     这里曾经写着 `.nav-links { flex: 1 1 100% }`，让菜单换到新的一行平铺 ——
     那正是报告 P1-12 实测到的"导航 8 个栏目平铺占两行、约 120px 高"的成因。
     两条规则并存时，900px 档会**盖住** 1279px 档的 `display:none`
     （同优先级、后出现者胜），抽屉就永远打不开了。 */
  .nav { padding: 0 16px; }
  .container { padding: 20px 16px 40px; }
  .page-head h1 { font-size: 19px; }
  .grid-cards { grid-template-columns: minmax(0, 1fr); }
  .hero { padding: 28px 22px; border-radius: 14px; }
  .hero h1 { font-size: 23px; }
  .hero-stats { padding-left: 0; border-left: none; gap: 24px; margin-left: 0; padding-top: 18px; width: 100%; }
  .hero-stat b { font-size: 22px; }
  .footer-inner { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 26px; padding: 32px 16px 20px; }
  .footer-bottom { padding: 14px 16px; }
  /* 详情页两栏（内联样式）在小屏塌陷为单栏 */
  .grid[style*="1.6fr"] { grid-template-columns: minmax(0, 1fr) !important; }
  .login-wrap { grid-template-columns: minmax(0, 1fr); padding: 28px 18px; gap: 0; }
  .login-hero { display: none; }
  .login-card { max-width: 420px; margin: 0 auto; }
  /* ⚠️ 浮层里的登录块必须**另写一遍**：`.login-overlay .login-wrap`（0,2,0）
   * 的优先级高于上面这条 `.login-wrap`（0,1,0），媒体查询本身**不提升优先级**。
   * 漏了这一条，窄屏上浮层仍是"品牌栏 + 表单"两栏，会把 390px 的屏幕挤到横向溢出。 */
  .login-overlay .login-wrap { grid-template-columns: minmax(0, 1fr); }
  .login-overlay .login-hero { display: none; }
  .login-overlay .login-card { padding: 26px 18px; }
  .overlay-panel.card-panel { padding: 22px 16px; }
  .login-slogan { font-size: 26px; }
  .guest-bar { padding: 8px 16px; }
  .guest-bar .btn { margin-left: 0; }
}

/* ============================================================
   图标基线（icons.js 产物）：装饰性 SVG 与文字对齐；无独立颜色，
   一律 currentColor，由父级 token 决定。
   ============================================================ */
svg[aria-hidden="true"] { display: inline-block; vertical-align: -0.125em; flex: none; }
.empty-icon { color: var(--ink-3); }
.notice-icon { color: var(--ink-3); margin-bottom: 10px; }

/* ============================================================
   需求详情页 · 智能推荐区（Q2）
   1 + 2 布局：匹配成果通栏，推荐经理人 / 匹配专家各半行对称；
   <900px 全塌单栏。复用既有 .card / .tag / .score-pill / .explain-block。
   ============================================================ */
.ai-reco { display: grid; gap: 16px; grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 16px; }
.ai-reco > .card-main { grid-column: 1 / -1; }
.ai-reco .split { display: grid; grid-template-columns: 1fr 1.2fr; gap: 16px; }
.ai-reco .reco-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.ai-reco .reco-head b { font-size: 14px; }
.ai-reco .reco-sub { margin: 0 0 12px; }
/* 匹配成果 · 候选行（可点，键盘可达） */
.ai-reco .cand { display: block; width: 100%; text-align: left; background: none; border: 0;
  border-left: 3px solid transparent; padding: 10px 12px; cursor: pointer; font: inherit; color: inherit; border-radius: 0; }
.ai-reco .cand + .cand { border-top: 1px solid var(--line-2); }
.ai-reco .cand:hover { background: var(--bg); }
.ai-reco .cand[aria-current="true"] { border-left-color: var(--brand); background: var(--brand-soft); }
.ai-reco .cand-title { font-size: 13.5px; font-weight: 600; margin: 6px 0 2px; }
/* 推荐经理人 / 专家 · 行卡 */
.ai-reco .pick { display: flex; gap: 12px; align-items: flex-start; padding: 12px 0; }
.ai-reco .pick + .pick { border-top: 1px solid var(--line-2); }
.ai-reco .pick-main { flex: 1; min-width: 0; }
.ai-reco .pick-name { font-size: 14px; font-weight: 600; }
/* 推荐理由 chip */
.ai-reco .reason-chip { display: flex; gap: 6px; align-items: flex-start; margin-top: 8px;
  background: var(--brand-soft); color: var(--brand); border: 1px solid var(--brand-line);
  border-radius: var(--radius-sm); padding: 8px 11px; font-size: 12.5px; }
/* 五态容器 */
.ai-reco .state-box { text-align: center; padding: 26px 14px; }
.ai-reco .state-icon { color: var(--ink-3); margin-bottom: 10px; }
.ai-reco .state-icon.is-error { color: var(--danger); }
.ai-reco .factor-toggle { display: inline-flex; align-items: center; gap: 4px; background: none; border: 0;
  color: var(--brand); cursor: pointer; font: inherit; font-size: 12.5px; padding: 4px 0; }

@media (max-width: 900px) {
  /* 🔴 窄屏档一律写 `minmax(0, 1fr)`，**不许写裸 `1fr`**。
     `1fr` == `minmax(auto, 1fr)`，而 `auto` 的最小尺寸取内容的 **min-content** ——
     列因此**不肯缩**，会把容器（甚至布局视口本身）顶破。
     实测过：`.grid-cards` 用裸 `1fr` 时，`#/financial` / `#/carriers` 在 390px 下
     把布局视口撑到 465 / 442px。
     ⚠️ 这条铁律覆盖**本文件所有 ≤900px 档**（含写成一行的那种），
     护栏 `scripts/verify_nav_by_role.py` 按 @media 取值域整体断言，不是只盯某个选择器。 */
  .ai-reco { grid-template-columns: minmax(0, 1fr); }
  .ai-reco .split { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .ai-reco > .card { padding: 14px; }
}

/* ============================================================
   门户首页（#/home）
   ------------------------------------------------------------
   定位：入口索引 + 角色分流（判定依据见 docs/decisions/ADR-009）。
   配色一律走上方 token，不引入新色相——首页要"稳"，不需要新视觉语言。
   ============================================================ */
.home-sec { margin-top: 30px; }
.sec-head { display: flex; align-items: baseline; gap: 10px; margin: 0 0 12px; flex-wrap: wrap; }
.sec-head h2 { position: relative; font-size: 16px; font-weight: 700; margin: 0; padding-left: 11px; letter-spacing: .01em; }
/* 标题左侧竖条：本页是长纵向堆叠，全是同一种白卡片容易糊成一片，
   给每个小节一个统一的视觉锚点，扫读时能分段。 */
.sec-head h2::before {
  content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%);
  width: 3px; height: 14px; border-radius: 2px; background: var(--brand);
}
.sec-head .sub { font-size: 12.5px; color: var(--ink-2); }
.sec-more { margin-left: auto; font-size: 12.5px; }

/* ---- 首页专用栅格：3 列 → 2 列 → 1 列 三级断点 ----
   为什么不复用全局 .grid-3 / .grid-4：
     · .grid-4 放 6 张卡会排成 4+2，第二行右半幅整块留白，看着像没加载完；
     · 全局栅格只有"≤900px 直接塌成 1 列"一步，1000~1200px 之间会从 3 列直跳 1 列，
       卡片忽宽忽窄。首页单独一套断点即可，不动其他页面。
   6 张卡在 3 列下正好 3+3，两行都排满。 */
.home-cols { display: grid; gap: 16px; grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1080px) { .home-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .home-cols { grid-template-columns: minmax(0, 1fr); } }

/* ---- 「我要找」意图入口：药丸式，密排 ---- */
.home-intents { display: flex; flex-wrap: wrap; gap: 10px; }
.intent-chip {
  display: inline-flex; align-items: center; padding: 9px 16px;
  border-radius: 99px; font-size: 13px; font-weight: 500;
  background: var(--card); border: 1px solid var(--line); color: var(--ink);
  transition: border-color .16s, color .16s, background .16s;
}
.intent-chip:hover { border-color: var(--brand); color: var(--brand); background: var(--brand-soft); }

/* ---- 资源栏目卡片（合并后为 6 个栏目）---- */
.col-card { position: relative; display: flex; flex-direction: column; gap: 7px; padding-left: 18px; }
.col-card:hover { transform: translateY(-2px); }
/* 左侧竖条：6 张同款白卡片平铺时缺少视觉锚点，加一道色条区分"这是一组栏目入口"；
   悬停时转为品牌色，与卡片整体上浮的反馈同源。 */
.col-card::before {
  content: ''; position: absolute; left: 0; top: 14px; bottom: 14px; width: 3px;
  border-radius: 2px; background: var(--brand-line); transition: background .16s;
}
.col-card:hover::before { background: var(--brand); }
.col-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.col-name { font-size: 14px; font-weight: 600; color: var(--ink); }
.col-stat { font-size: 12px; color: var(--brand); font-variant-numeric: tabular-nums; }
.col-desc { font-size: 12.5px; color: var(--ink-2); line-height: 1.6; }

/* ---- 转化服务链：横向串联，窄屏自动换行 ---- */
.chain { display: flex; align-items: stretch; gap: 6px; flex-wrap: wrap; }
.chain-step {
  flex: 1 1 168px; display: flex; flex-direction: column; gap: 5px;
  padding: 14px; position: relative;
}
.chain-step b { font-size: 13.5px; }
.chain-idx {
  width: 20px; height: 20px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11.5px; font-weight: 600;
  background: var(--brand-soft); color: var(--brand); border: 1px solid var(--brand-line);
}
.chain-arrow {
  align-self: center; flex: none; width: 12px; height: 12px;
  border-top: 1.5px solid var(--line); border-right: 1.5px solid var(--line);
  transform: rotate(45deg); opacity: .8;
}

/* ---- 角色分流 ---- */
.persona-card { display: flex; flex-direction: column; gap: 6px; }
.persona-card:hover { transform: translateY(-2px); }
.persona-card b { font-size: 14px; }

/* ---- 最新成果：紧凑卡片（三行内读完）---- */
.result-mini { display: flex; flex-direction: column; gap: 8px; }
.result-mini:hover { transform: translateY(-2px); }
/* 行数截断：宁可截断也不让某条摘要把整行卡片撑高（卡片高度参差比截断更难看） */
.calc-1, .calc-2 { display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; }
.calc-1 { -webkit-line-clamp: 1; }
.calc-2 { -webkit-line-clamp: 2; min-height: 38px; }

/* ---- 最新需求：行式列表 ---- */
.demand-list { padding: 6px 16px; }
.demand-row {
  display: flex; align-items: center; gap: 14px;
  padding: 11px 0; border-bottom: 1px solid var(--line-2); color: var(--ink);
}
.demand-row:last-of-type { border-bottom: 0; }
.demand-row:hover { color: var(--brand); }
.demand-row-main { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.demand-row-main b { font-size: 13.5px; }
.demand-row-main .calc-1 { min-height: 0; }
.demand-row:hover b { color: var(--brand); }

/* ---- 平台机制与公示 ---- */
.gov-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px 18px; }
.gov-col { display: flex; flex-direction: column; }
.gov-row {
  display: flex; flex-direction: column; gap: 3px; padding: 11px 12px;
  border-left: 2px solid var(--line); color: var(--ink); transition: border-color .16s, background .16s;
}
.gov-row:hover { border-left-color: var(--brand); background: var(--brand-soft); }
.gov-row b { font-size: 13px; }

@media (max-width: 900px) {
  .chain-arrow { display: none; }
  .gov-grid { grid-template-columns: minmax(0, 1fr); }

  /* 首屏窄屏重排：.hero-stats 原本靠 margin-left:auto 靠右、靠 padding-left +
     border-left 与文案隔开。一旦换行到第二行，这两条样式就只剩副作用 ——
     左边缘凭空缩进 34px、分隔线孤零零挂在左边，与上方文案对不齐
     （这正是"排版错位"的观感来源）。换行前先撤掉它们，改用 gap 维持间距。 */
  .hero { padding: 30px 24px; border-radius: 14px; }
  .hero h1 { font-size: 24px; margin: 8px 0; }
  .hero .lead { font-size: 13.5px; }
  .hero-actions { margin-top: 18px; }
  .hero-stats { margin-left: 0; padding-left: 0; border-left: 0; gap: 22px; flex-wrap: wrap; }
  .hero-stat { padding: 0; }
  .hero-stat + .hero-stat { border-left: 0; }
}


/* ---- 个人中心 · 功能面板（登录后功能菜单的唯一入口）----
   2026-10-04 产品定型：顶部导航只保留六个公共栏目 + 个人中心，
   登录后的功能菜单（发布 / 咨询 / 工作台 / 牵线受理 / 我的能力 / 机构管理 /
   运营后台 / 广告推广）全部收进这个面板。四组并排（账户管理 · 信息管理 ·
   认证中心 · 角色功能），窄屏折成两列、再窄折成一列。
   面板条目用 <a>（跳路由）与 <button>（滚动到本页区块）两种形态，
   这里把它们的外观统一成同一款，避免一个像链接一个像按钮。 */
.menu-panel .sec-title { margin-bottom: 0; }
.menu-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px; margin-top: 14px;
}
.menu-group { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.menu-group-title {
  font-size: 12.5px; font-weight: 700; color: var(--ink-2);
  padding-bottom: 6px; border-bottom: 1px solid var(--line); margin-bottom: 2px;
}
.menu-item {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; text-align: left; padding: 9px 10px; cursor: pointer;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: transparent; color: var(--ink); font: inherit; transition: .16s;
}
.menu-item:hover { border-color: var(--brand); background: var(--brand-soft); }
.mi-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mi-main b { font-size: 13px; font-weight: 600; }
.mi-desc { font-size: 11.5px; color: var(--ink-3); line-height: 1.35; }

@media (max-width: 1100px) { .menu-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px) { .menu-grid { grid-template-columns: minmax(0, 1fr); } }

/* ---- 技术经理人详情 · 实时业绩三口径（本年度 / 本月度 / 累计）----
   三个口径并排，宽屏三列、窄屏一列。每个口径内部是"指标名 + 值"的键值对。 */
.perf-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; margin-top: 10px; }
.perf-col {
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  padding: 10px 12px; background: var(--bg-2); min-width: 0;
}
.perf-col-title {
  font-size: 12.5px; font-weight: 700; color: var(--ink-2);
  padding-bottom: 6px; margin-bottom: 6px; border-bottom: 1px solid var(--line);
}
.perf-col .kv { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; padding: 3px 0; }

/* ---- 技术经理人详情 · 右侧业绩排行榜 ---- */
.lb-row {
  display: flex; align-items: center; gap: 10px; padding: 8px 6px;
  border-bottom: 1px solid var(--line-2); color: var(--ink); transition: background .16s;
}
.lb-row:last-child { border-bottom: 0; }
.lb-row:hover { background: var(--brand-soft); }
.lb-rank {
  flex: 0 0 22px; height: 22px; line-height: 22px; text-align: center;
  border-radius: 6px; background: var(--bg-2); color: var(--ink-3);
  font-size: 12px; font-weight: 700;
}
/* 前三名给品牌色底：一眼看出榜首，但不做金银铜（避免视觉上与业务语义无关的暗示） */
.lb-rank.top { background: var(--brand); color: #fff; }
.lb-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.lb-name { font-size: 13px; font-weight: 600; }
.lb-amount { flex: 0 0 auto; text-align: right; font-size: 12px; color: var(--ink-2); }

@media (max-width: 900px) { .perf-cols { grid-template-columns: minmax(0, 1fr); } }

/* ============================================================
   评估报告 §4.6 表格的第 4、5 行（移动端收口的补充两项）
   ============================================================ */

/* ---- 第 5 行：业绩指标按「业绩 / 过程」两组分区 ----
 *
 * 一屏里混排"在办项目"（过程量）与"佣金"（结果量）时，读者得自己分类才看得懂。
 * 两个子标题把"哪些是我已经拿到的、哪些是我正在做的"一次说清。
 *
 * ⚠️ 全局**不干预列数**。报告的原文建议是"改为 2 列 × 5 行（或 3 列）"，
 * 但 `.perf-metrics` 用的是 `repeat(auto-fit, minmax(96px, 1fr))`，auto-fit
 * 本来就会把放不下的项换行 —— 实测 390px 下是 3 列 × 3 行（itemW=97px），
 * 并没有"挤在一行"。"挤在一行"只在 1440px 桌面成立（auto-fit 算出 10 列），
 * 而桌面放得下，不是缺陷。写成固定 2 列会把**桌面**从 1 行拖成 4 行。
 *
 * 🔴 但 **≤640px 必须改 2 列**，理由不是"好看"，是"会丢数字"：
 * 390px 下 3 列只有 **97px/格**，而最长的一个值
 * （佣金 `1,277,120.96`，21px 字号）实测需要 **124px** ——
 * 它会被卡片裁掉，屏幕上读到的是 `1,277,120.9` 这种被切断的数。
 * 改成 2 列后每格约 150px，放得下。
 * 这条**只写在 640px 媒体查询里**，所以桌面逐像素不变。
 *
 * 判据（`scripts/verify_nav_by_role.py`）与运行期断言
 * （`scripts/e2e_nav.mjs` 的「元素级裁切」一条）都盯着这件事：
 * 页面级 `scrollWidth <= innerWidth` 是**查不出**这种裁切的 —— 没有横向滚动条，
 * 数字只是被祖先元素吃掉了。这个盲区就是本轮真被漏过去的一次。
 */
.perf-groups { display: flex; flex-direction: column; gap: 14px; }
.perf-group { min-width: 0; }
.perf-group-title {
  font-size: 11.5px; font-weight: 700; letter-spacing: .08em; color: var(--ink-3);
  margin-bottom: 6px;
}

/* ---- 线索研判队列的状态筛选条：允许换行 ----
 *
 * 390px 下 `.row-between` 只有 320px，而那 5 个 chip
 * （全部 / 待核实 / 已采纳 / 已拒绝 / 已升级）需要 **335px** ——
 * 实测会顶破卡片 15px。它外层 `.row-between` 本来就 `flex-wrap: wrap`，
 * 但这条例筛选条自己没有，于是内部溢出。
 * 加上换行后：窄屏折成 2 行，宽屏本来就一行，**逐像素不变**。
 */
#lead-queue-tabs { flex-wrap: wrap; }

/* ---- 第 4 行：窄屏筛选区折叠 ----
 * 实测：筛选区在 390px 下占 **7 行 / 296px**（报告记的是"约 200px"），近半屏，
 * 列表主体被挤到首屏之外。宽屏是 4 行 / 102px，不该动。
 *
 * ## 为什么用 checkbox + label，而不是 `<details>`
 * `<details>` 的收起状态由浏览器内部机制实现（`::details-content` /
 * content-visibility），**没有可靠的 CSS 能在宽屏把"已收起"强行展开**。
 * 而需求是"窄屏折叠、宽屏逐像素照旧"，两档必须共存 ——
 * 下面这几条规则全部写在 640px 媒体查询里，宽屏一个字都不作用。
 *
 * ## 为什么不需要 JS 记状态
 * 翻页走的是 `#b-list` 的局部替换，filterBar 不在替换范围里，选中状态天然保留；
 * 而"检索后自动收起"也正是想要的行为。
 *
 * ## 为什么不加 `hidden` 属性而用视觉隐藏
 * `hidden` 会让复选框从可聚焦序列里消失（键盘用户再也展不开筛选）。
 * 这里保留它在焦点序列里，只是视觉上不可见 —— 完整的上焦点样式留给批次 6（a11y）。
 */
.filter-toggle-cb {
  position: absolute; width: 1px; height: 1px; margin: 0;
  opacity: 0; pointer-events: none;
}
.filter-toggle-label { display: none; }
.filter-row { min-width: 0; }

@media (max-width: 640px) {
  /* 业绩指标改 2 列：390px 下 3 列只有 97px/格，而最长的值（佣金）需要 124px，
     会被卡片裁掉半个数字。详见上方「第 5 行」那段注释。桌面不受影响。 */
  .perf-metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .filter-bar { padding: 12px 14px; }
  .filter-toggle-label {
    display: flex; align-items: center; gap: 6px;
    font-size: 13.5px; font-weight: 600; color: var(--brand); cursor: pointer;
    padding: 2px 0; user-select: none;
  }
  .filter-toggle-label .chev { font-size: 10px; transition: transform .16s; }
  .filter-toggle-cb:checked ~ .filter-toggle-label .chev { transform: rotate(180deg); }
  /* 收起时整块藏起来 —— 实测筛选区 311px（展开）→ 53px（收起） */
  .filter-row { display: none; }
  .filter-toggle-cb:checked ~ .filter-row { display: flex; }
}
