/* ==================================================================
   Xmedia GEO Site — 主题样式
   设计原则：
   1) 纯静态、零框架，改色只需改 :root 变量
   2) 语义化 HTML 优先（h1/h2 层级清晰），利于 AI 与无障碍解析
   3) 移动端优先的响应式栅格

   ★ 配色怎么改？
   本文件 :root 里的是「出厂默认值」，仅供单独打开本文件时兜底。
   实际生效的配色由 src/data/site.json 的 theme 决定，构建时以
   <style id="theme-vars"> 内联注入到每页 <head>，位置在本样式表之后，
   因此同权重下一定覆盖这里的值。
   改配色请走管理后台的「配色方案」面板，不要手改本文件的色值。
   ================================================================== */
:root {
  /* —— 品牌主色 —— */
  --c-primary: #1b5cd8;
  --c-primary-dark: #14459f;
  --c-primary-soft: #eaf1ff;
  --c-on-primary: #ffffff;
  /* hover 底色（--c-primary-dark）上的文字色。两者没有约束关系，
     所以这个值由构建期按「能不能压住 hover 底色」现算：
     浅底（如亮黄）时给深色字，深底时给白字。不要在别处复用 --c-on-primary 配 hover 底色。 */
  --c-on-primary-dark: #ffffff;
  /* 主色当「文字 / 描边 / 焦点框」时的版本。由构建期按可读性派生：
     主色够深就原样用主色，太亮（如亮黄）就等比压暗到浅底上能读清。
     与 tint/line/hover 一样是派生值，不要手填。 */
  --c-primary-ink: #1b5cd8;
  --c-primary-ink-dark: #14459f;
  --c-accent: #00b3a4;
  /* 强调色底上的文字/描边色（卡片出口按钮「了解详情」用它）。
     同样由构建期按可读性现算：亮黄底 → 近黑字，深色底 → 白字。
     候选里刻意不含主题深色（只取白与中性近黑）：主题深色带色相，压在中等明度的
     强调色上反而更暗不下去（教育橙 4.15:1、中国红 4.32:1，都不到小字的 4.5）。
     不要在别处拿 --c-primary / --c-on-primary 配强调色底 —— 那两者互不约束。 */
  --c-on-accent: #14181f;
  /* 由主色推导的半透明色（构建时计算，保证 rgba 与主色始终同步） */
  --c-primary-tint: rgba(27, 92, 216, .13);
  --c-primary-line: rgba(27, 92, 216, .22);
  --c-primary-hover: rgba(27, 92, 216, .35);
  /* 标签（chip）的描边色：由「可读强调色」派生，所以主色是亮黄时
     描边是深金、是蓝色时描边是蓝，永远比 --c-primary-line 更清楚。
     标签是浅底小件，描边太淡等于没有。 */
  --c-primary-ink-line: rgba(27, 92, 216, .6);
  /* --c-primary-edge / --c-primary-edge-dark / --c-edge-dark 由构建期**按需**生成，
     刻意不在这里兜底：主色不是近黑时它们根本不存在，CSS 里
     var(--c-primary-edge, transparent) 就自动退回"无描边"。
     一旦在这里写死一个值，var() 的第二参数就永远不生效了（见 build.js 的 PRIMARY_EDGE）。 */

  /* —— 顶部导航栏 —— */
  --c-header-bg: rgba(255, 255, 255, .94);
  --c-header-fg: #1c2537;
  --c-header-fg-dim: rgba(28, 37, 55, .65);
  --c-header-hover-bg: rgba(28, 37, 55, .06);
  --c-nav-active: #1b5cd8;

  /* —— BANNER 首屏区 —— */
  --c-banner-bg: #f8fbff;
  --c-banner-bg-2: #ffffff;
  --c-banner-fg: #1c2537;

  /* —— 深色通栏（背书条 / CTA）—— */
  --c-bg-deep: #0f2a52;
  --c-deep-fg: #ffffff;
  --c-deep-fg-72: rgba(255, 255, 255, .72);
  --c-deep-line-50: rgba(255, 255, 255, .5);
  --c-deep-fill-12: rgba(255, 255, 255, .12);

  /* —— 页尾 —— */
  --c-footer-bg: #0b1f3d;
  --c-footer-fg: #ffffff;
  --c-footer-fg-85: rgba(255, 255, 255, .85);
  --c-footer-fg-74: rgba(255, 255, 255, .74);
  --c-footer-fg-60: rgba(255, 255, 255, .6);
  --c-footer-fg-50: rgba(255, 255, 255, .5);
  --c-footer-fg-45: rgba(255, 255, 255, .45);
  --c-footer-fg-22: rgba(255, 255, 255, .22);
  --c-footer-fg-10: rgba(255, 255, 255, .1);
  --c-footer-fg-1: rgba(255, 255, 255, .01);
  --c-footer-chip-bg: rgba(255, 255, 255, .1);
  --c-footer-line-12: rgba(255, 255, 255, .12);

  /* —— 文字与底色 —— */
  --c-bg: #ffffff;
  --c-bg-soft: #f6f8fb;
  --c-text: #1c2537;
  --c-text-2: #5a6577;
  --c-text-3: #8a93a3;
  --c-border: #e4e8ef;
  --c-warn: #e0771b;

  /* —— 尺寸与字体（与配色无关，不参与后台调色）—— */

  /* 圆角：全站走「方正硬边」视觉（对齐 Lotus 那类直角板块），四档令牌一律为 0。
     所有圆角位置都只引用下面的变量 —— 想改回圆角只改这几行，不必逐处翻：
       --radius-sm     小件：输入框 / 关闭键
       --radius        常规块：缩略图 / 下拉菜单 / 提示块
       --radius-lg     大块：大图 / 大卡片 / 客服面板 / 聊天气泡
       --radius-round  原本的胶囊与正圆：按钮 / 轮播圆点 / 播放键 / 小圆点
     注意「正圆」也走 --radius-round：值为 0 时是方块，改回 999px 会自动恢复圆形
     （999px 对任何正方元素都等于 50%）。

     ★ 唯一的例外是 --radius-pill（椭圆角胶囊），只给「标签 / chip」这类
     带描边的小件用：卡片分类标签、页尾奖项、右下角客服入口、配单条目上的
     「可选配 / 已升配」标记。型号与单位这类技术标记仍走直角，与标签区分开。
     图片、卡片、按钮、面板一律保持直角 —— 不要把按钮也改成胶囊。
     这条约定由 tools/test-mobile.js 的 B2 段**按选择器**守着。 */
  --radius-sm: 0px;
  --radius: 0px;
  --radius-lg: 0px;
  --radius-round: 0px;
  --radius-pill: 999px;
  --shadow: 0 2px 10px rgba(20, 40, 80, .06);
  --shadow-lg: 0 10px 34px rgba(20, 40, 80, .10);
  --wrap: 1200px;
  /* 产品中心 / 解决方案卡片的图片比例。默认 16:9，与全站基准一致
     （首屏轮播 1600×900、视频嵌入、方案占位图 1200×675）。
     想换成 21/9 只改这一行 —— 但要清楚代价：在同样宽度下 21:9 的图
     比 16:9 矮 24%（"图片更大"的诉求反而更弱），且源图要被裁掉更多高度
     （3:2 实拍裁 36%、16:9 实拍裁 24%），容易切到产品主体。
     这条由 tools/test-card-layout.js 守着。 */
  --card-media-ratio: 16 / 9;
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
          "Microsoft YaHei", "Hiragino Sans GB", sans-serif;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font);
  color: var(--c-text);
  background: var(--c-bg);
  line-height: 1.75;
  font-size: 15px;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: var(--c-primary-ink); text-decoration: none; }
a:hover { color: var(--c-primary-ink-dark); }
h1, h2, h3, h4 { margin: 0 0 .6em; line-height: 1.35; font-weight: 700; letter-spacing: -.01em; }
h1 { font-size: 34px; }
h2 { font-size: 24px; }
h3 { font-size: 18px; }
p { margin: 0 0 1em; color: var(--c-text-2); }
ul, ol { margin: 0 0 1em; padding-left: 1.4em; color: var(--c-text-2); }
li { margin-bottom: .4em; }

.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }
.narrow { max-width: 860px; margin: 0 auto; padding: 0 24px; }
.skip-link {
  position: absolute; left: -9999px;
  background: var(--c-primary); color: var(--c-on-primary); padding: 8px 16px; z-index: 999;
}
.skip-link:focus { left: 12px; top: 12px; }

/* ---------------- Header ---------------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: var(--c-header-bg);
  backdrop-filter: saturate(180%) blur(8px);
  border-bottom: 1px solid var(--c-border);
}
.header-inner { display: flex; align-items: center; gap: 28px; height: 68px; }
.brand { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
/* 站点 LOGO：替换 src/data/site.json 的 brand.logo 即可生效 */
.brand-logo { height: 36px; width: auto; max-width: 220px; object-fit: contain; display: block; }
.footer-brand .brand-logo { height: 32px; }
.brand-mark {
  font-size: 22px; font-weight: 800; color: var(--c-header-fg); letter-spacing: -.03em;
}
.brand-mark span { color: var(--c-header-fg-dim); font-weight: 600; }
.brand-cn { font-size: 13px; color: var(--c-header-fg-dim); }
/* 有 LOGO 图时仍保留文字（供 SEO/读屏），仅视觉隐藏 */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.nav { flex: 1; }
.nav-list { display: flex; gap: 4px; list-style: none; margin: 0; padding: 0; }
.nav-item { position: relative; }
.nav-item > a {
  display: block; padding: 10px 14px; font-size: 15px; color: var(--c-header-fg);
  border-radius: var(--radius-sm); white-space: nowrap;
}
.nav-item > a:hover { background: var(--c-header-hover-bg); color: var(--c-nav-active); }
.nav-item.is-active > a { color: var(--c-nav-active); font-weight: 600; }
.nav-drop {
  display: none; position: absolute; top: 100%; left: 0; min-width: 260px;
  background: var(--c-bg); border: 1px solid var(--c-border); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); list-style: none; margin: 0; padding: 8px;
}
.nav-item:hover .nav-drop { display: block; }
.nav-drop li a {
  display: block; padding: 8px 12px; font-size: 14px; color: var(--c-text-2); border-radius: var(--radius-sm);
}
.nav-drop li a:hover { background: var(--c-primary-soft); color: var(--c-primary-ink); }

.header-actions { display: flex; align-items: center; gap: 14px; }
.header-actions .tel { font-weight: 700; color: var(--c-header-fg); font-size: 15px; }
.nav-toggle { display: none; background: none; border: 0; cursor: pointer; padding: 8px; }
.nav-toggle span { display: block; width: 20px; height: 2px; background: var(--c-header-fg); margin: 4px 0; }

/* ---------------- Buttons ---------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 11px 22px; border-radius: var(--radius-round); font-size: 15px; font-weight: 600;
  transition: .18s; border: 1px solid transparent; cursor: pointer;
}
/* 近黑主色块的轮廓：主色暗到接近纯黑时（--c-primary-edge 会被构建期生成），
   色块在深色导航条 / 首屏 / 深色通栏上会丢掉轮廓，这时描一圈品牌强调色。
   主色本身够亮时该令牌不存在，var() 退回 transparent —— 不改变任何原有观感。 */
.btn-primary { background: var(--c-primary); color: var(--c-on-primary); border-color: var(--c-primary-edge, transparent); }
.btn-primary:hover { background: var(--c-primary-dark); color: var(--c-on-primary-dark); border-color: var(--c-primary-edge-dark, transparent); }
.btn-ghost { background: var(--c-bg); color: var(--c-primary-ink); border-color: var(--c-primary-ink); }
.btn-ghost:hover { background: var(--c-primary-soft); }
.btn-sm { padding: 7px 16px; font-size: 14px; }

/* ---------------- Hero ---------------- */
.hero {
  background:
    radial-gradient(1200px 400px at 78% -10%, var(--c-primary-tint), transparent),
    linear-gradient(180deg, var(--c-banner-bg), var(--c-banner-bg-2));
  padding: 88px 0 64px;
}
.hero-inner { max-width: 900px; }
.eyebrow {
  display: inline-block; font-size: 13px; font-weight: 600; color: var(--c-primary-ink);
  background: var(--c-primary-soft); padding: 5px 14px; border-radius: var(--radius-round); margin-bottom: 20px;
}
.hero h1 { font-size: 44px; margin-bottom: 20px; color: var(--c-banner-fg); }
.hero-lead { font-size: 17px; color: var(--c-text-2); max-width: 780px; }
.hero-actions { display: flex; gap: 14px; margin: 28px 0 44px; flex-wrap: wrap; }
.hero-facts {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px;
  list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--c-border); padding-top: 28px;
}
.hero-facts li { display: flex; flex-direction: column; }
.hero-facts strong { font-size: 28px; color: var(--c-primary-ink); line-height: 1.2; }
.hero-facts span { font-size: 13px; color: var(--c-text-3); }

/* ---------------- 首屏底图轮播（site.hero） ----------------
   与「配色变量驱动」的其余部分不同，这里的文字色**不跟随主题**：
   底图是用户自己上传的照片，深浅完全不可控，只有「白字 + 暗色压暗层」
   才能保证在任何一张照片上都可读。把这三个值收在本区块内，
   既保证可读性，也留了统一调整的入口。 */
.hero-slider {
  --hero-fg: #ffffff;
  --hero-fg-dim: rgba(255, 255, 255, .84);
  --hero-line: rgba(255, 255, 255, .28);
  --hero-scrim: linear-gradient(90deg,
      rgba(6, 14, 26, .82) 0%,
      rgba(6, 14, 26, .58) 46%,
      rgba(6, 14, 26, .20) 100%);
  --hero-fade: .65s;
  position: relative;
  padding: 0;
  overflow: hidden;
  background: var(--c-bg-deep);
}
/* 幻灯片用 grid 叠在同一格上，天然等高；高度由最高的一屏决定 */
.hero-slides { position: relative; display: grid; min-height: clamp(460px, 56vh, 640px); }
.hero-slide {
  grid-area: 1 / 1;
  position: relative;
  display: flex;
  align-items: center;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  /* 淡出结束后再隐藏：这样能完整播完淡出动画，又不让隐形屏能被点到 / Tab 到 */
  transition: opacity var(--hero-fade) ease, visibility 0s linear var(--hero-fade);
}
.hero-slide.is-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity var(--hero-fade) ease, visibility 0s;
}
/* 切换方式：slide 时改用横向位移（淡入淡出仍保留，避免出现两屏都不清楚的中间态） */
.hero-fx-slide .hero-slide { transform: translateX(5%); transition-property: opacity, transform, visibility; }
.hero-fx-slide .hero-slide.is-active { transform: none; }

.hero-bg { position: absolute; inset: 0; z-index: 0; }
.hero-bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 压暗层：让白字在任何照片上都读得清；alt 与文字才是 GEO 价值的来源 */
.hero-bg::after { content: ""; position: absolute; inset: 0; background: var(--hero-scrim); }
.hero-slide-inner { position: relative; z-index: 2; padding: 84px 0 150px; max-width: 900px; }
/* 首屏的小标签走「强调色实心块 + 对比色描边」，与卡片出口按钮（.card-more）同一套语言。
   原先的「半透明白块 + 白字」压在照片上只是"淡淡的"，谁都不会注意到；
   品牌色实心块才能一眼看到，也让整页的引导件统一成一种信号。
   字色与描边走 --c-on-accent（构建期按强调色现算，亮黄 → 近黑字），
   所以换配色时它自动跟着变，不必单独配。 */
.hero-slider .eyebrow {
  color: var(--c-on-accent);
  background: var(--c-accent);
  border: 1px solid var(--c-on-accent);
}
.hero-slider h1,
.hero-slider .hero-title {
  font-size: clamp(30px, 3.5vw, 46px);
  line-height: 1.22;
  margin-bottom: 18px;
  color: var(--hero-fg);
}
.hero-slider .hero-lead { color: var(--hero-fg-dim); max-width: 720px; }
.hero-slider .hero-actions { margin: 30px 0 0; }
.hero-slider .btn-ghost {
  background: rgba(255, 255, 255, .10);
  color: var(--hero-fg);
  /* 深色照片上的描边走品牌强调色；强调色压不住底时退回原来的半透明白。
     首屏按钮底色是压暗过的照片，深浅不可控 —— 与首屏文字同理，不能靠"白 28%"这种弱化描边。 */
  border-color: var(--c-edge-dark, var(--hero-line));
}
.hero-slider .btn-ghost:hover { background: rgba(255, 255, 255, .22); color: var(--hero-fg); }

/* 控件：默认隐藏，只有 JS 生效后才出现 —— 没有 JS 时点击是无效的，
   显示出来反而会骗人。首屏内容本身不依赖 JS（第一屏已服务端渲染为可见）。 */
.hero-arrow,
.hero-dots { display: none; }
.has-js .hero-arrow { display: flex; }
.has-js .hero-dots { display: flex; }
.hero-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 46px; height: 46px; padding: 0; cursor: pointer;
  align-items: center; justify-content: center;
  border-radius: var(--radius-round);
  /* 描边走深底强调色（--c-edge-dark，与首屏的描边按钮同一支令牌）；
     强调色自己压不住照片时该令牌不被生成 → 回退原来的半透明白线，不会变没边。 */
  border: 1px solid var(--c-edge-dark, var(--hero-line));
  background: rgba(9, 18, 32, .42); color: var(--hero-fg);
  font-size: 26px; line-height: 1; backdrop-filter: blur(6px); transition: .2s;
}
/* 悬停整颗点亮成强调色实心 —— 比原来的「把黑底压得更黑」明确得多，
   也和出口按钮用同一个「点亮」信号。 */
.hero-arrow:hover {
  background: var(--c-accent);
  color: var(--c-on-accent);
  border-color: var(--c-on-accent);
}
.hero-prev { left: 20px; }
.hero-next { right: 20px; }
/* 聚焦圈同理走深底强调色：它要对**照片**可见，不是对强调色可见，
   所以用 --c-edge-dark（压不住时回退纯白），而不是直接用 --c-accent。 */
.hero-arrow:focus-visible { outline: 3px solid var(--c-edge-dark, #fff); outline-offset: 2px; }
.hero-dots {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: 104px; z-index: 3;
  gap: 16px; align-items: center;
}
.hero-dot {
  position: relative; width: 12px; height: 12px; padding: 0; cursor: pointer;
  border-radius: var(--radius-round); border: 1px solid rgba(255, 255, 255, .6);
  background: rgba(255, 255, 255, .22); transition: width .25s, background .25s, border-color .25s;
}
/* 圆点视觉上只有 12px，但把可点区域撑到 28px，触屏上才点得准。
   间距特意留到 16px：可点区域刚好相接而不重叠，不会出现「按了却切到旁边那个」。 */
.hero-dot::before { content: ""; position: absolute; inset: -8px; }
/* 当前屏的圆点用强调色实心：与箭头悬停、出口按钮同色，读作「就在这一屏」。
   描边走 --c-on-accent —— 亮黄实心配近黑边、深色实心配白边，两种极端都还看得出轮廓。 */
.hero-dot.is-active { width: 30px; background: var(--c-accent); border-color: var(--c-on-accent); }
.hero-dot:focus-visible { outline: 3px solid var(--c-edge-dark, #fff); outline-offset: 3px; }

/* 数据条压在底图上，用底部渐隐过渡，避免硬边 */
.hero-facts-bar {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 30px 0 20px;
  background: linear-gradient(180deg, rgba(8, 16, 30, 0), rgba(8, 16, 30, .74));
}
.hero-slider .hero-facts { border-top-color: var(--hero-line); padding-top: 20px; }
/* 数据条上的数字（40+ / 15 / 32 / 1）是整屏唯一的「关键数据」，用强调色把它从叙述里拎出来。
   与同一屏的标签底色、当前屏圆点、箭头悬停同源，换配色时一起走。

   走 --c-key-dark 而不是直接写 --c-accent：这支令牌由构建期按
   「对首屏压暗底 ≥ 4.5:1」判定，够亮才生成；后台手填了偏暗的强调色时它不存在，
   这里就回退成 --hero-fg 的白字 —— 宁可朴素，不可不可读。

   为什么不去改 --hero-fg：那是**正文**颜色（h1 / 说明 / 按钮字），
   改它会把整屏文字一起染黄，标题就不再是视觉第一顺位。
   标签（span）也刻意保持白灰：整块都黄会糊成一片，
   层次正是靠「数字黄、标签灰」这一对反差建立的。 */
.hero-slider .hero-facts strong { color: var(--c-key-dark, var(--hero-fg)); }
.hero-slider .hero-facts span { color: rgba(255, 255, 255, .72); }

@media (prefers-reduced-motion: reduce) {
  /* 尊重系统「减少动态效果」：不做位移与淡入淡出，直接切换 */
  .hero-slide { transition: opacity 0s, visibility 0s; }
  .hero-fx-slide .hero-slide { transform: none; }
}

/* ---------------- Trust band ---------------- */
.trust-band { background: var(--c-bg-deep); color: var(--c-deep-fg); padding: 18px 0; }
.trust-inner { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; font-size: 14px; }
.trust-label { opacity: .65; }
.trust-item { position: relative; padding-left: 14px; }
.trust-item::before {
  content: ""; position: absolute; left: 0; top: 8px; width: 5px; height: 5px;
  border-radius: var(--radius-round); background: var(--c-accent);
}

/* ---------------- Sections ---------------- */
.section { padding: 72px 0; }
/* 关于我们页专属：区块间距收紧到全站一半（72 → 36，用户要求减 50%）。
   特异性 (0,2,0) 压过 .section (0,1,0) 与 .section-tight。 */
.about-sec { padding-top: 36px; padding-bottom: 36px; }
.section-tight { padding: 32px 0; }
.section-alt { background: var(--c-bg-soft); }
.section-head { margin-bottom: 32px; }
.section-head h2 { margin-bottom: 6px; }
.section-head p { margin: 0; }

/* ---------------- Cards ---------------- */
.card-grid { display: grid; gap: 20px; }
/* 列数由构建器按数据算好再交给模板（如联系页：有销售卡 → 2 列，关掉 → 1 列）。
   1 列是显式写出来的一档，不是「没配列数」的兜底 —— 否则只剩一张卡时会占左半边、
   右半边空着，看着像排版坏了。 */
.card-grid-1 { grid-template-columns: 1fr; }
.card-grid-2 { grid-template-columns: repeat(2, 1fr); }
.card-grid-3 { grid-template-columns: repeat(3, 1fr); }
.card-grid-4 { grid-template-columns: repeat(4, 1fr); }
.card {
  display: block; background: var(--c-bg); border: 1px solid var(--c-border);
  border-radius: var(--radius-lg); padding: 26px; box-shadow: var(--shadow);
  transition: .2s; color: inherit;
}
a.card:hover {
  transform: translateY(-3px); box-shadow: var(--shadow-lg);
  border-color: var(--c-primary-ink);
}
.card h2 { font-size: 19px; }
.card h3 { font-size: 17px; margin-top: 6px; }
.card p { font-size: 14px; margin-bottom: 12px; }
/* 栏目卡片（产品 / 方案 / 案例 / 知识库）与新闻列表的**摘要文字**首行缩进两个字
   （用户 2026-09-24 要求）。刻意用 .card-body > p / .news-body > p 而不是
   .card p —— 联系页的卡片里也有 <p>（电话 / 邮件 / 地址），全局缩进会把
   那些行也顶歪；.card-body / .news-body 只在摘要卡片里出现，精确无副作用。 */
.card-body > p { text-indent: 2em; }
.news-body > p { text-indent: 2em; }
/* 标签（分类 / 日期 / 类型这类小件）：椭圆角 + 细描边。
   与卡片、图片的直角形成对比，让标签从版式里"拎"出来 —— 参考的是路特斯那种
   亮色描边小胶囊。带图标的（产品分类）与纯文字的（日期、行业）样式完全一致，
   区别只是有没有 <svg>。图标线稿跟随文字色，改主色时一起变。 */
.card-tag {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; line-height: 1.5; color: var(--c-primary-ink);
  background: var(--c-primary-soft); padding: 3px 11px;
  border: 1px solid var(--c-primary-ink-line);
  border-radius: var(--radius-pill); margin-bottom: 10px; vertical-align: middle;
}
.card-tag svg { width: 13px; height: 13px; flex: none; display: block; }
/* 卡片出口（了解详情 / 查看方案 / 阅读全文）：黄底 + 黑框的引导按钮。
   整张卡本来就是一个大链接，这个按钮回答的是"出口在哪" —— 纯文字链接在
   大图卡片里容易被忽略。底色走辅助强调色、文字与描边走构建期算出的
   --c-on-accent（亮黄底给近黑字），所以换配色时它自动跟着变，不用单独配。
   悬停不换色、只压出一小块硬阴影（和全站的方正、无圆角同一套语言），
   避免和卡片自身的 hover 位移叠在一起变成两层动效。 */
.card-more {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 600; line-height: 1.5;
  padding: 4px 12px;
  color: var(--c-on-accent); background: var(--c-accent);
  border: 1px solid var(--c-on-accent);
  border-radius: var(--radius-sm);
  transition: .18s;
}
a.card:hover .card-more { box-shadow: 2px 2px 0 var(--c-on-accent); }
.card-static { cursor: default; }

/* ---------------- Page head / crumbs ---------------- */
.page-head { background: linear-gradient(180deg, var(--c-banner-bg), var(--c-banner-bg-2)); padding: 44px 0 32px; border-bottom: 1px solid var(--c-border); }
.page-head h1 { font-size: 34px; margin-bottom: 10px; color: var(--c-banner-fg); }
/* max-width 曾是 820px —— 各栏目页的引导文字在宽屏上过早折行、右侧大片留白
   （用户 2026-09-24 反馈）。放开后吃满版心宽度（容器本身约 1080px 上限，
   不会出现超长难读的行），折行位置交给文字自然流动。
   text-indent: 2em 首行缩进两个字（用户要求；em 随字号缩放，窄屏也是两字）。 */
.page-lead { font-size: 16px; max-width: none; margin: 0; text-indent: 2em; }
.crumbs { display: flex; gap: 8px; font-size: 13px; color: var(--c-text-3); margin-bottom: 14px; list-style: none; padding: 0; }
.crumbs a { color: var(--c-text-3); }
.crumbs a:hover { color: var(--c-primary-ink); }

/* ---------------- TL;DR 答案块 ---------------- */
.tldr {
  background: var(--c-primary-soft); border: 1px solid var(--c-primary-line);
  border-left: 4px solid var(--c-primary-ink); border-radius: var(--radius);
  padding: 22px 26px;
}
.tldr h2 { font-size: 17px; color: var(--c-primary-ink); margin-bottom: 10px; }
.tldr ul { margin: 0; padding-left: 1.2em; }
/* 速览卡两栏：左信息列表 + 右负责人二维码（用户要求在公司速览卡补二维码） */
.tldr-cols { display: flex; gap: 28px; align-items: flex-start; }
.tldr-cols > ul { flex: 1; min-width: 0; }
.tldr-qr { flex: 0 0 210px; margin-right: 30px; text-align: center; }
.tldr-qr img { width: 130px; height: auto; display: block; margin: 0 auto; background: #fff; padding: 5px; border-radius: var(--radius); }
/* 名称一行不换行：容器加宽到 210px + nowrap（「全国销售总负责人：刘先生 Paco」约 195px） */
.tldr-qr-name { margin: 8px 0 2px; font-size: 13px; font-weight: 600; color: var(--c-primary-ink); white-space: nowrap; }
.tldr-qr-note { margin: 0; font-size: 12px; color: var(--c-ink-60); }
@media (max-width: 760px) {
  .tldr-cols { flex-direction: column; }
  .tldr-qr { flex: none; }
}
.tldr li { color: var(--c-text); font-size: 14.5px; }

/* ---------------- Prose / article ---------------- */
.prose h2 { margin-top: 40px; font-size: 22px; }
.prose h2:first-child { margin-top: 0; }
.prose p { font-size: 15.5px; }
.prose ul { font-size: 15px; }
/* 「公司简介」的正文块。**刻意不限宽**（随 .wrap 占满整栏），与紧随其后的
   图片播放框共用同一条左右边缘 —— 用户明确要求正文宽度放宽到与图片框齐平。
   走过的弯路记一下，免得又被"修回去"：
     · 最初用 .narrow（max-width + margin:auto 的**居中**窄栏）：about 页只有
       这一处是窄栏，宽屏上比下面的图片整体右移 170px ＝ (--wrap 1200 − 860)/2；
     · 改成 max-width:860px 左对齐后不歪了，但正文只占 860，与图片框宽度不同。
   要收窄阅读行长的话，**必须连播放框一起收**（改成同一组宽度），否则又会错开。 */
.about-intro { max-width: none; }
.about-intro + .reel { margin-top: 28px; }
.article-meta { font-size: 13px; color: var(--c-text-3); border-top: 1px solid var(--c-border); padding-top: 16px; margin-top: 36px; }
.quote {
  margin: 28px 0; padding: 18px 22px; border-left: 3px solid var(--c-primary-ink);
  background: var(--c-bg-soft); border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 15px; color: var(--c-text);
}
.link-list li { margin-bottom: 6px; }

/* ---------------- Spec table ---------------- */
.spec-table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.spec-table th, .spec-table td { padding: 13px 16px; border-bottom: 1px solid var(--c-border); text-align: left; vertical-align: top; }
.spec-table th { width: 200px; background: var(--c-bg-soft); font-weight: 600; color: var(--c-text); }
.spec-table td { color: var(--c-text-2); }

/* ---------------- FAQ ---------------- */
.faq-item { border-bottom: 1px solid var(--c-border); padding: 4px 0; }
.faq-item summary {
  cursor: pointer; padding: 16px 0; font-size: 16px; font-weight: 600; color: var(--c-text);
  list-style: none; position: relative; padding-right: 28px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+"; position: absolute; right: 4px; top: 14px; color: var(--c-primary-ink); font-size: 20px;
}
.faq-item[open] summary::after { content: "−"; }
.faq-item p { padding: 0 0 16px; margin: 0; }
.faq-block { margin-top: 40px; }

/* ---------------- Lists ---------------- */
.number-list { counter-reset: n; list-style: none; padding: 0; }
.number-list li {
  counter-increment: n; position: relative; padding-left: 42px; margin-bottom: 14px; font-size: 15px;
}
.number-list li::before {
  content: counter(n); position: absolute; left: 0; top: 2px;
  width: 26px; height: 26px; border-radius: var(--radius-round); background: var(--c-primary-soft);
  color: var(--c-primary-ink); font-size: 13px; font-weight: 700; text-align: center; line-height: 26px;
}

/* ---------------- News ---------------- */
.news-list { list-style: none; padding: 0; margin: 0; }
.news-list li { padding: 18px 0; border-bottom: 1px solid var(--c-border); }
.news-list a { font-size: 16px; font-weight: 600; }
.news-list p { margin: 6px 0 0; font-size: 14px; }
.news-date { display: inline-block; font-size: 13px; color: var(--c-text-3); margin-right: 12px; }
.news-list-page li h2 { font-size: 18px; display: inline; }

/* ---------------- CTA ---------------- */
.cta-band { background: var(--c-bg-deep); color: var(--c-deep-fg); padding: 56px 0; }
.cta-inner { display: flex; align-items: center; justify-content: space-between; gap: 32px; flex-wrap: wrap; }
.cta-band h2 { color: var(--c-deep-fg); margin-bottom: 6px; }
.cta-band p { color: var(--c-deep-fg-72); margin: 0; }
.cta-actions { display: flex; gap: 12px; }
.cta-actions .btn-ghost { background: transparent; color: var(--c-deep-fg); border-color: var(--c-edge-dark, var(--c-deep-line-50)); }
.cta-actions .btn-ghost:hover { background: var(--c-deep-fill-12); color: var(--c-deep-fg); }

/* ---------------- Form ---------------- */
/* 联系我们页的两块方框：「提交需求」表单（.form-panel）与「区域联系人」表格
   （.region-panel）。形制与间距分开写，是为了让「两块长得一模一样」这件事
   只有一处定义 —— 改 .content-panel 一次，两块同时跟着变。

   ★ 为什么方框**不限宽**：限宽（曾写死 820px）会让方框的右边缘比上方的卡片
   网格短一大截，同一页里出现两条参差的右边线，比「输入框略宽一点」难看得多。
   宽度交给 .wrap 统一给，方框铺满即可 —— 三列字段仍各占约 1/3，不会长到一整行。 */
.content-panel {
  padding: 26px 28px 24px;
  background: var(--c-bg-soft); border: 1px solid var(--c-border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow);
}
/* 框与框之间的节奏：两块共用**同一个**上间距，别各写各的。
   间距值刻意不大（曾放大到 64px，用户嫌松）：上下都有了方框这条硬边界之后，
   再靠大留白来分隔就纯粹是浪费高度了 —— 2026-09-24 用户要求收 30%~50%。 */
.form-panel { margin-top: 32px; }
.region-panel { margin-top: 32px; }
/* 方框内的段落节奏：标题与内容是**同一个框里**的两段，间距比页面级的
   .section-head（32px）收一档，否则框内会比框外还松。 */
.form-panel .section-head,
.region-panel .section-head { margin-bottom: 12px; }
.form-panel .section-head h2,
.region-panel .section-head h2 { margin: 0; }
/* 区域说明紧跟在标题下方（页面级 .section-lead 的上边距是负值、给的是通栏版式，
   进方框后要抹平，否则会把标题和说明撞到一起）。 */
.region-panel .section-lead { margin: 0 0 14px; }
.contact-form { display: grid; gap: 13px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
/* 三列两行：姓名 / 单位 / 电话 + 微信 / 邮箱 / 专业类型。
   原来是两列三行，光这一项就多出整整一行的高度（用户要求压缩这块）。
   窄屏（≤720px）由下面 @media 里的 .form-row 规则接管，退回单列。 */
.form-row-3 { grid-template-columns: repeat(3, 1fr); gap: 13px; }
.contact-form label { display: grid; gap: 6px; font-size: 14px; font-weight: 600; color: var(--c-text); }
.contact-form input, .contact-form textarea {
  font: inherit; padding: 10px 13px; border: 1px solid var(--c-border);
  border-radius: var(--radius-sm); background: var(--c-bg); color: var(--c-text);
}
.contact-form input:focus, .contact-form textarea:focus {
  outline: 2px solid var(--c-primary-soft); border-color: var(--c-primary-ink);
}
/* 蜜罐字段：用「移到屏幕外 + 不可见」而不是 display:none ——
   部分表单机器人会跳过 display:none 的字段，但会对「存在但看不见」的字段照填不误。 */
.hp-field {
  position: absolute; left: -9999px; width: 1px; height: 1px;
  overflow: hidden; opacity: 0; pointer-events: none;
}
.form-status {
  margin: 0; padding: 11px 14px; border-radius: var(--radius-sm); font-size: 14px;
  background: var(--c-bg-soft); color: var(--c-text-2); border: 1px solid var(--c-border);
}
.form-status.is-ok { background: #f0fdf4; border-color: #bbf7d0; color: #166534; }
.form-status.is-err { background: #fff7ed; border-color: #fed7aa; color: #92400e; }
.contact-form button[type="submit"]:disabled { opacity: .65; cursor: default; }
.faq-source { font-size: 12.5px; color: var(--c-text-3); margin: -8px 0 14px; }
.form-note { font-size: 13px; color: var(--c-text-3); margin: 0; }

/* ---------------- Footer ---------------- */
.site-footer { background: var(--c-footer-bg); color: var(--c-footer-fg-74); padding: 56px 0 24px; font-size: 14px; }
.site-footer a { color: var(--c-footer-fg-74); }
.site-footer a:hover { color: var(--c-footer-fg); }
.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1.2fr; gap: 36px; padding-bottom: 36px; }
.footer-brand .brand-mark { color: var(--c-footer-fg); font-size: 20px; }
.footer-brand .brand-mark span { color: var(--c-accent); }
.footer-desc { margin: 14px 0; color: var(--c-footer-fg-60); font-size: 13.5px; }
.footer-awards { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  font-size: 12px; background: var(--c-footer-chip-bg); padding: 3px 11px; border-radius: var(--radius-pill);
  border: 1px solid var(--c-footer-line-12);
  color: var(--c-footer-fg-85);
}
.footer-col h4 { color: var(--c-footer-fg); font-size: 15px; margin-bottom: 14px; }
.footer-col ul { list-style: none; padding: 0; margin: 0; }
.footer-col li { margin-bottom: 8px; }
.contact-list li { color: var(--c-footer-fg-60); }
.footer-bottom {
  border-top: 1px solid var(--c-footer-line-12); padding-top: 20px;
  display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; font-size: 13px;
}
.footer-bottom p { margin: 0; color: var(--c-footer-fg-50); }
/* GEO 注释行（llms.txt / sitemap / 中标信息入口）：刻意压到近乎与页脚底色同融
   —— 这行与「中标信息」入口是给 AI 爬虫发现的（进 sitemap 与 llms.txt），对人类访客
   保持最低存在感（用户要求：肉眼看不见）。可访问性底线：hover 时提到 45%。
   ⚠ 特异性必须高于 `.footer-bottom p`（0,1,1）—— 用 (0,2,0) 的选择器，否则被覆盖。 */
.footer-bottom .geo-note { color: var(--c-footer-fg-1); }
.footer-bottom .geo-note a { color: inherit; }
.footer-bottom .geo-note a:hover { color: var(--c-footer-fg-10); }

/* —— 页尾新媒体二维码 —— */
/* 二维码本身多是「深码浅底」，所以给它一个白色底衬：压在深色页尾上既清楚，
   和常见的扫码习惯也一致（手机相册扫白底黑码成功率最高）。 */
.footer-social {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 18px 32px; padding: 22px 0 26px; border-top: 1px solid var(--c-footer-line-12);
}
.footer-social-text h4 { color: var(--c-footer-fg); font-size: 15px; margin: 0 0 5px; }
.footer-social-text p { margin: 0; color: var(--c-footer-fg-60); font-size: 13px; }
/* margin-right: 60px：space-between 下列表默认顶到页尾右缘，加右外距即整块
   （图 + 账号名 + 账号说明）向左移 60px（用户 2026-09-24 要求）。 */
.footer-qr-list { display: flex; flex-wrap: wrap; gap: 64px; list-style: none; margin: 0; padding: 0; margin-right: 60px; }
.footer-qr { display: flex; flex-direction: column; align-items: center; gap: 6px; width: 114px; }
.footer-qr-box {
  width: 114px; height: 114px; background: #fff; padding: 4px;
  display: flex; align-items: center; justify-content: center;
}
.footer-qr-box img { display: block; width: 100%; height: 100%; object-fit: contain; }
/* 没上传二维码时的占位：虚线框明确表达「这里要放一张图」，
   比渲染一个破图（或干脆什么都不显示）都更容易被看出来 */
.footer-qr-empty {
  background: transparent; border: 1px dashed var(--c-footer-line-12);
  color: var(--c-footer-fg-50); font-size: 12px;
}
.footer-qr-name { color: var(--c-footer-fg-85); font-size: 13px; }
.footer-qr-desc { color: var(--c-footer-fg-50); font-size: 12px; text-align: center; }

/* —— 联系我们：联系方式（电话 / 邮件 / 地址 三合一的一张卡） ——
   三块内容用「左侧小标题 + 右侧内容」的两列网格排，比三张独立卡片省掉约一半
   竖向高度，也是「四栏并排 → 两栏」这个改版里把三块合成一栏的落点。
   h3 仍是真标题：AI 抓取与读屏都按结构读得到「电话咨询」这类小标题，
   只是视觉上退成 14px 的标签，不再各占一行。
   每条规则都带 .contact-info-card 前缀是为了压过 .card p —— 后者是 (0,1,1)，
   写平了不生效（margin-bottom:12px 会把三行撑开）。 */
.contact-info-card .info-list { display: grid; gap: 14px; }
.contact-info-card .info-item {
  display: grid; grid-template-columns: 76px 1fr; gap: 3px 14px; align-items: baseline;
}
.contact-info-card .info-item h3 { margin: 0; font-size: 14px; font-weight: 600; color: var(--c-text-2); }
.contact-info-card .info-item p { grid-column: 2; margin: 0; font-size: 14px; }
.contact-info-card .info-item a { color: var(--c-primary-ink); font-weight: 700; }
.contact-info-card .info-item .info-sub { font-size: 13px; color: var(--c-text-3); }

/* —— 联系我们：全国销售总负责人（与「联系方式」卡并排的第二张） ——
   卡片宽度由网格决定（2 列时约 570px，内距跟着 .card 的 26px），所以恢复
   「左信息右二维码」的横排：二维码固定在右上，卡片高度由二维码那一列决定，
   不再随文字行数增长。窄屏退回单列后卡内宽度不足，flex-wrap 会自动折成两行。
   每条规则都带 .sales-card 前缀是为了压过 .card p —— 后者是 (0,1,1)，
   而单独的 .sales-line 只有 (0,1,0)，写平了不生效（margin 那 12px 会跑出来）。 */
.sales-card { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 12px 28px; }
/* 卡片标题必须先独占一行 —— 它是 flex 子项，不这么写就会跟「信息」「二维码」
   挤成并排的三个格子（标题被压成窄条）。flex-basis:100% 让它自己占满一行。 */
.sales-card > h2 { flex: 1 0 100%; margin: 0; }
.sales-info { display: flex; flex-direction: column; gap: 4px; flex: 1 1 240px; }
.sales-card .sales-name { font-size: 16px; font-weight: 700; margin: 0; }
.sales-card .sales-line { margin: 0; font-size: 14px; }
.sales-card .sales-tel { color: var(--c-primary-ink); font-weight: 700; }
.sales-card .sales-note { margin: 0; font-size: 13px; color: var(--c-text-3); }
/* margin-right: 50px 让二维码离卡片右缘留出 50px（用户先后要求「左移 30px」
   再「左移 20px」的累计值）；margin-top: -30px 整列上移（先 20px 后又加 10px，
   图与说明文字一起动，不会分离）。align-items: center 让「微信扫码直接联系」
   与图框水平居中对齐（原来 flex-start 靠左，图放大后文字偏在左边不好看）。 */
.sales-qr { display: flex; flex-direction: column; align-items: center; gap: 6px; flex: 0 0 auto; margin-right: 50px; margin-top: -30px; }
.qr-box {
  width: 156px; height: 156px; padding: 5px; background: #fff;
  border: 1px solid var(--c-border); display: flex; align-items: center; justify-content: center;
}
.qr-box img { display: block; width: 100%; height: 100%; object-fit: contain; }
.qr-empty { background: var(--c-bg-soft); border: 1px dashed var(--c-border); color: var(--c-text-3); font-size: 12px; }
.sales-card .qr-cap { margin: 0; font-size: 12.5px; color: var(--c-text-3); }
/* 「待补充」是给运营看的提示：够淡，不至于让访客当成正式内容 */
.sales-todo, .ct-todo { color: var(--c-text-3); font-weight: 400; }

/* —— 联系我们：各区域联系人 —— */
.section-lead { margin: -18px 0 20px; color: var(--c-text-2); font-size: 14.5px; }
.contact-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.contact-table { width: 100%; border-collapse: collapse; font-size: 14.5px; min-width: 420px; }
.contact-table th, .contact-table td {
  padding: 13px 16px; border-bottom: 1px solid var(--c-border); text-align: left; vertical-align: top;
}
.contact-table th { background: var(--c-bg-soft); font-weight: 600; color: var(--c-text); }
.contact-table td { color: var(--c-text-2); }
.contact-table td a { color: var(--c-primary-ink); font-weight: 600; }
.ct-region { font-weight: 600; color: var(--c-text); white-space: nowrap; }
/* 套进方框之后表头要换个底色：方框底色（.content-panel）与表头默认底色
   都是 --c-bg-soft，同色相叠表头会**整条消失**，只剩几根横线看不出哪行是表头。
   换成页面底色（白）——在浅灰方框上反而成了最清楚的一条分隔带。 */
.region-panel .contact-table th { background: var(--c-bg); }

/* 手机端：页尾二维码竖排（横向挤 4 个会互相压到）。
   销售卡与二维码不需要在这里特殊处理 —— 它就是一张普通卡片，
   内距跟随 .card、卡内是 flex-wrap 的横排，跟着卡片一起变单列后会自动折成两行。 */
@media (max-width: 720px) {
  .footer-social { flex-direction: column; align-items: flex-start; gap: 16px; }
  /* 窄屏竖排靠左，桌面端的「左移 60px」右外距没有意义，归零；图框同步放大 30%（80→104） */
  .footer-qr-list { margin-right: 0; }
  .footer-qr { width: 104px; }
  .footer-qr-box { width: 104px; height: 104px; }
  .contact-table th, .contact-table td { padding: 11px 12px; }
  /* 方框的左右留白跟着窄屏收一收，别把输入框挤到只剩一半宽。
     注意内距挂在 .content-panel 上，这里必须连它一起写 —— 只写 .form-panel
     会「看着像生效了」而实际内距没变（选择器不再匹配任何内距声明）。 */
  .content-panel { padding: 20px 18px 18px; }
  .form-panel, .region-panel { margin-top: 24px; }
  /* 三块联系方式的标题列收窄一点，给邮箱 / 地址多留出可换行的宽度 */
  .contact-info-card .info-item { grid-template-columns: 68px 1fr; gap: 3px 10px; }
}

/* ---------------- Responsive ---------------- */
@media (max-width: 1000px) {
  .card-grid-4 { grid-template-columns: repeat(2, 1fr); }
  .card-grid-3 { grid-template-columns: repeat(2, 1fr); }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  /* 以下「旧 Hero（左文右图）」的规则要用 :not(.hero-slider) 排掉轮播形态，
     否则会把轮播的 padding 与字号一起改掉 */
  .hero:not(.hero-slider) h1 { font-size: 34px; }
  .hero-slider .hero-slide-inner { padding: 64px 0 134px; }
  .hero-slider h1,
  .hero-slider .hero-title { font-size: clamp(28px, 4.4vw, 36px); }
}
@media (max-width: 720px) {
  .nav-toggle { display: block; }
  .nav {
    display: none; position: absolute; top: 68px; left: 0; right: 0; background: var(--c-bg);
    border-bottom: 1px solid var(--c-border); padding: 12px; box-shadow: var(--shadow);
  }
  .nav.is-open { display: block; }
  .nav-list { flex-direction: column; gap: 0; }
  /* 移动菜单背景是白色（--c-bg），但链接色继承自桌面深色导航的 header-fg（白字）
     —— 白底白字看不见（2026-09-27 手机实测）。这里改回正文深色。 */
  .nav-item > a { padding: 12px 8px; color: var(--c-text); }
  .nav-item > a:hover { color: var(--c-primary-ink); }
  .nav-item.is-active > a { color: var(--c-primary-ink); }
  /* 「获取方案」CTA 在窄屏不折行（用户实测「获取方/案」两行） */
  .header-actions .btn { white-space: nowrap; }
  .nav-drop { display: block; position: static; box-shadow: none; border: 0; padding: 0 0 0 12px; }
  .header-actions .tel { display: none; }
  .card-grid-2, .card-grid-3, .card-grid-4 { grid-template-columns: 1fr; }
  .hero:not(.hero-slider) { padding: 56px 0 40px; }
  .hero:not(.hero-slider) h1 { font-size: 27px; }
  .hero-slides { min-height: clamp(400px, 74vh, 540px); }
  .hero-slider .hero-slide-inner { padding: 40px 0 168px; }
  .hero-slider h1,
  .hero-slider .hero-title { font-size: 27px; }
  .hero-slider .hero-lead { font-size: 15px; }
  /* 手机上去掉左右箭头：滑动与圆点更自然，也不会挡住文案 */
  .hero-slider .hero-arrow { display: none; }
  .hero-slider .hero-dots { bottom: 140px; }
  .hero-facts { grid-template-columns: repeat(2, 1fr); }
  h1 { font-size: 26px; }
  .page-head h1 { font-size: 26px; }
  .section { padding: 48px 0; }
  .footer-grid { grid-template-columns: 1fr; }
  .form-row { grid-template-columns: 1fr; }
  .spec-table th { width: 120px; }
}

/* ---------------- Media：图片与视频 ---------------- */
/* 说明：图片对 GEO 的价值不在「好看」，而在 alt + figcaption + ImageObject/VideoObject。
   文案写清「什么产品、什么场景、说明了什么」，图片才会成为可被 AI 引用的证据。 */
.hero-grid { display: grid; grid-template-columns: 1.05fr .95fr; gap: 44px; align-items: center; max-width: var(--wrap); }
.hero-media { min-width: 0; }

.media-figure { margin: 0; }
.media-figure img,
.media-figure video {
  width: 100%; height: auto; border-radius: var(--radius-lg);
  background: var(--c-bg-soft); box-shadow: var(--shadow-lg);
}
.media-figure figcaption {
  margin-top: 10px; font-size: 13px; color: var(--c-text-3); text-align: center; line-height: 1.6;
}
.prose .media-figure { margin: 30px 0; }
/* 富文本（后台编辑器）写入正文的图与视频：结构化数据走 .media-figure，
   这里兜住裸 <img> / wangEditor 的 video 包装层，防止溢出版心。 */
.prose img { max-width: 100%; height: auto; }
.prose [data-w-e-type="video"] { margin: 24px 0; max-width: 100%; }
.prose video { max-width: 100%; height: auto; }
/* 全局 img 是 display:block（版式需要），但块级元素不响应父级的 text-align ——
   富文本里「居左/居中/居右」靠 p 的 text-align 对齐，图片必须回到行内块。
   只限定 .prose p 内的图，不影响 figure/卡片等其它版式。 */
.prose p > img { display: inline-block; }
.prose [data-w-e-type="video"] video { display: inline-block; }

/* 中标信息页（/bids/）：每条记录是一张「事实句卡片」—— 句子是 AI 引用的单元，
   链接行提供官方公告与佐证附件。无圆角（全站直角铁律），灰阶描边。 */
.bids-list { list-style: none; margin: 0; padding: 0; }
.bids-list > li { border: 1px solid var(--c-border); background: var(--c-bg-soft); padding: 18px 22px; margin-bottom: 14px; }
.bid-fact { margin: 0 0 10px; font-size: 15px; line-height: 1.85; }
.bid-links { margin: 0; font-size: 14px; display: flex; gap: 18px; flex-wrap: wrap; }
.bid-links a { font-weight: 600; }

.gallery-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; }
.gallery-grid .media-figure img { box-shadow: var(--shadow); }

/* 卡片缩略图的**兜底尺寸**：给没走「上图下文（card-tile）」的图片卡用。
   当前所有卡片列表都走 card-tile，所以这条平时不生效；保留它是为了让以后
   新加的 .card.card-media 至少不会把图撑成原始尺寸（1200px 宽）。
   它的特异性是 (0,2,0)，与「.card-tile .card-thumb」完全相同 —— 也就是说
   单段的 card-tile 规则压不住它，胜负只看谁写在文件后面。所以下面那条
   必须写成 .card.card-tile 两段，别改回单段。 */
.card-media .card-thumb {
  width: 100%; height: 176px; object-fit: cover;
  border-radius: var(--radius); margin-bottom: 14px; background: var(--c-bg-soft);
}
.card-body { min-width: 0; }

/* 上图下文（所有卡片列表的统一版式）：图片满宽，"出血"到卡片边缘。
   出血是有意的 —— 同样宽度下图能再大约 10%，观感从"卡片里的一张插图"
   变成"带大图的卡片"。文字区自己留内边距，所以卡片本身 padding 归零。
   选择器写到 .card.card-tile 这一级是为了稳赢上面的 .card-media 规则，
   不依赖"谁写在后面"（改版时调整顺序就悄悄失效，是最难查的一类问题）。
   2026-09-23 起首页的四个卡片区块（产品/方案/案例/知识库）与两个栏目页
   全部走这一套；旧的左图右文版式（.card-row）已随之删除。 */
.card.card-tile { padding: 0; overflow: hidden; }
.card.card-tile .card-thumb {
  width: 100%; height: auto; aspect-ratio: var(--card-media-ratio);
  object-fit: cover; margin: 0; border-radius: 0;
  background: var(--c-bg-soft);
}
.card.card-tile .card-body { padding: 20px 26px 24px; }

/* 视频 */
.video-figure video {
  background: #000;
  /* 手机长按视频会弹出「存储视频 / 拷贝」菜单 —— 这是移动端最常见的下载方式，
     JS 的 contextmenu 在 iOS Safari 上根本不触发，只能靠这个专有属性关掉。
     （Android Chrome 的长按菜单拦不住，属已知缺口，见 main.js 里那段说明。） */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  /* 视频区域不参与拖拽，配合 main.js 的 dragstart 拦截 */
  -webkit-user-drag: none;
}
.video-embed { position: relative; width: 100%; aspect-ratio: 16 / 9; background: #000; border-radius: var(--radius-lg); overflow: hidden; }
.video-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.video-empty { position: relative; }
.video-empty img { filter: brightness(.7); }
.play-badge {
  position: absolute; left: 50%; top: 44%; transform: translate(-50%, -50%);
  width: 68px; height: 68px; border-radius: var(--radius-round); background: rgba(255, 255, 255, .92);
  color: var(--c-primary-ink); font-size: 24px; padding-left: 4px;
  display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow-lg);
}
.media-hint { display: block; margin-top: 6px; font-size: 12px; color: var(--c-warn); }
.media-hint code { background: var(--c-bg-soft); padding: 1px 5px; border-radius: var(--radius-sm); font-size: 12px; }

/* 新闻列表缩略图 */
.news-list.has-thumb li { display: flex; gap: 18px; align-items: flex-start; }
.news-thumb-link { flex: 0 0 200px; }
.news-thumb { width: 200px; height: 120px; object-fit: cover; border-radius: var(--radius); background: var(--c-bg-soft); }
.news-body { flex: 1; min-width: 0; }

@media (max-width: 980px) {
  .hero-grid { grid-template-columns: 1fr; gap: 28px; }
}
@media (max-width: 720px) {
  .gallery-grid { grid-template-columns: 1fr; }
  .news-list.has-thumb li { flex-direction: column; gap: 12px; }
  .news-thumb-link { flex: none; align-self: stretch; }
  .news-thumb { width: 100%; height: 180px; }
}

/* ==================================================================
   荣誉与知识产权：双轨反向滚动证书（关于我们页）
   ------------------------------------------------------------------
   视觉目标是"展台"而不是"证书墙"：40 多张证书铺成网格会把页面拉长成一面
   糊掉的墙，滚动轨道让它们依次经过，悬停即停、点击放大。

   几何上有两个必须**与 build.js 一致**的数：--honor-h（图片区高度）与
   --honor-gap（卡片间距）。build.js 用它们算出轨道总宽、进而决定复制几份、
   滚多快，并在 .marquee 上以行内变量下发 —— 所以这里只写兜底值，
   真值由构建期给出。改这两个数请改 build.js 的 HONOR_MEDIA_H / HONOR_GAP。

   间距刻意用 margin-right 而不是 flex 的 gap：
   轨道靠 translateX(-100%) 首尾相接，只有当「最后一张之后也有一个 gap」时，
   接缝处的间距才和别处一样；用 gap 会差半个间距，循环时肉眼能看到"抖一下"。
   ================================================================== */
.honor-block + .honor-block { margin-top: 46px; }
.honor-block-head {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 14px;
  margin-bottom: 16px;
}
.honor-block-head h3 { margin: 0; font-size: 17px; }
.honor-block-head p { margin: 0; font-size: 13.5px; color: var(--c-text-3); }
.honor-count {
  margin-left: auto; white-space: nowrap;
  font-size: 12px; line-height: 1.5; color: var(--c-primary-ink);
  background: var(--c-primary-soft); padding: 3px 11px;
  border: 1px solid var(--c-primary-ink-line); border-radius: var(--radius-pill);
}

/* —— 轨道容器 —— */
.marquee {
  position: relative;
  display: flex;
  overflow: hidden;
  padding: 10px 0 16px;
  /* 两侧渐隐：滚出的卡片消失在边缘，而不是被硬切。48px 略大于一个卡片的
     视觉呼吸尺度，窄屏收到 22px（见下面的媒体查询）。 */
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 48px, #000 calc(100% - 48px), transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 48px, #000 calc(100% - 48px), transparent 100%);
}
/* 一份轨道。副本 rail 由构建期产出、带 aria-hidden（里面的图片框是非聚焦的
   <div>），视觉上与第一份完全接续 —— 所以循环是"没有 JS 也成立"的。
   ⚠ 不要给副本加 inert：inert 的元素连鼠标都点不到，副本又必然出现在视野里，
   加上它就变成"只有左边那截本体能点"（见 build.js 的 honorCardHtml）。 */
.marquee-rail {
  display: flex; flex: none;
  list-style: none; margin: 0; padding: 0;
  animation: honor-scroll var(--marquee-duration, 40s) linear infinite;
  will-change: transform;
}
/* 反向轨道：同一组关键帧倒着播，起点即 -100% 处。
   省一份关键帧，也保证两条轨道的速度、缓动完全一致（不然对位会歪）。 */
.marquee[data-dir="right"] .marquee-rail { animation-direction: reverse; }
@keyframes honor-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-100%, 0, 0); }
}

/* 悬停 / 键盘聚焦 / 手指按住 → 暂停。
   不暂停的话，用户永远点不中一张正在匀速移动的证书。 */
.marquee:hover .marquee-rail,
.marquee:focus-within .marquee-rail,
.marquee:active .marquee-rail { animation-play-state: paused; }

/* —— 卡片 —— */
.honor-card {
  flex: none;
  width: calc(var(--honor-h, 240px) * var(--ar, 1));
  margin-right: var(--honor-gap, 20px);
  list-style: none;
}
.honor-fig {
  display: flex; flex-direction: column; height: 100%; margin: 0;
  background: var(--c-bg); border: 1px solid var(--c-border);
  transition: transform .26s ease, box-shadow .26s ease, border-color .26s ease;
}
/* 放大 + 描边。判据与全站一致：卡片压在浅灰底上，悬停时"补一圈轮廓"
   告诉用户这里可以点 —— 描边取主色派生出的可读色 --c-primary-ink，
   而不是强调色（强调色在浅底上会糊掉，见品牌手册第 3 条原则）。 */
.honor-card:hover .honor-fig {
  transform: translateY(-6px) scale(1.035);
  box-shadow: var(--shadow-lg);
  border-color: var(--c-primary-ink);
}
.honor-shot {
  display: block; width: 100%; height: var(--honor-h, 240px);
  padding: 0; border: 0; background: var(--c-bg-soft);
  cursor: zoom-in; position: relative; overflow: hidden;
}
/* 放大镜光标只给"真点得开"的图片框。判据就是 data-honor-card 本身 ——
   与 main.js 绑事件用的是同一个属性，两处不会各写一套而跑偏。
   没有它的框（缺图的卡片）保持默认箭头，不做"点了没反应"的暗示。 */
.honor-shot:not([data-honor-card]) { cursor: default; }
/* 浏览器不支持 <dialog>（showModal 缺失）时，main.js 会给轨道加 .is-nozoom：
   整块收掉"可点击"暗示。留一个点了没反应的放大光标，比干脆没有这个功能更让人困惑。 */
.marquee.is-nozoom .honor-shot { cursor: default; }
.marquee.is-nozoom .honor-zoom { display: none; }
/* contain 而不是 cover：证书不能裁 —— 裁掉印章或登记号，这张图就废了。
   卡片宽度是按图片真实比例算的，所以正常情况这里不会留白边。 */
.honor-shot img { width: 100%; height: 100%; object-fit: contain; display: block; }
.honor-missing {
  display: flex; align-items: center; justify-content: center;
  height: 100%; padding: 16px; text-align: center;
  font-size: 12.5px; color: var(--c-warn);
}
/* "放大"浮标：底图深浅不可控（用户自己传的证书照片），所以固定走
   强调色底 + 构建期算出的 --c-on-accent 字色，不跟主题走文字色。
   与首屏控件、卡片出口按钮是同一套「强调色小件」语言。 */
.honor-zoom {
  position: absolute; right: 8px; bottom: 8px;
  font-size: 12px; font-weight: 600; line-height: 1.5;
  padding: 3px 10px; border-radius: var(--radius-pill);
  background: var(--c-accent); color: var(--c-on-accent);
  opacity: 0; transform: translateY(4px);
  transition: opacity .2s, transform .2s;
  pointer-events: none;
}
.honor-card:hover .honor-zoom,
.honor-shot:focus-visible .honor-zoom { opacity: 1; transform: none; }
.honor-meta {
  flex: 1; display: flex; flex-direction: column; gap: 4px;
  padding: 12px 14px 14px; border-top: 1px solid var(--c-border);
}
/* 两行截断只是**视觉**截断：完整文本仍在 DOM 里，AI 与搜索引擎读得到全文，
   屏幕阅读器也读得到。不要为了"截断干净"改用 JS 裁字符串 —— 那才是真的丢内容。 */
.honor-name {
  font-size: 13.5px; font-weight: 600; line-height: 1.5; color: var(--c-text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.honor-sub {
  font-size: 12px; line-height: 1.5; color: var(--c-text-3);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* 「一句话说明」是可选字段，填了才出现。它比名称 / 机构低一档：
   颜色更淡、字号更小，读的是"补充"，不抢主体。两行截断同样是**视觉**截断，
   完整文本仍在 DOM 里，AI 与屏幕阅读器读得到全文。 */
.honor-note {
  font-size: 12px; line-height: 1.55; color: var(--c-text-3); opacity: .88;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  padding-top: 2px;
}
.honors-note { margin: 24px 0 0; font-size: 13px; color: var(--c-text-3); }

/* —— 点击看大图（原生 dialog）—— */
.honor-lightbox {
  width: min(1100px, 94vw);
  max-width: 1100px;
  max-height: 92vh;
  padding: 0; border: 0; overflow: hidden;
  background: var(--c-bg); color: var(--c-text);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
}
/* 不要给 dialog 写 position：UA 样式用 position:absolute + inset:0 + margin:auto
   把它居中，覆盖掉就不会居中了。absolute 后代的包含块本来就是它。 */
.honor-lightbox::backdrop { background: rgba(8, 14, 26, .84); }
.honor-lightbox[open] { animation: honor-lb-in .22s ease-out; }
@keyframes honor-lb-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.honor-lb-fig { display: flex; flex-direction: column; margin: 0; }
/* max-width + max-height 一起限制、宽高都 auto —— 浏览器会等比缩到刚好放进
   这个框里。横向的奖项证书受 max-width 约束，竖向的软著证书受 max-height 约束，
   两类都不用各自写一套规则。 */
.honor-lb-fig img {
  display: block; width: auto; height: auto;
  max-width: 100%; max-height: 74vh;
  margin: 0 auto; background: var(--c-bg-soft);
}
.honor-lb-fig figcaption {
  display: flex; flex-direction: column; gap: 4px;
  padding: 14px 18px 16px; border-top: 1px solid var(--c-border);
}
.honor-lb-name { font-size: 15px; font-weight: 600; }
.honor-lb-meta { font-size: 13px; color: var(--c-text-3); }
.honor-lb-note { font-size: 13px; line-height: 1.6; color: var(--c-text-2); }
.honor-lb-note[hidden] { display: none; }
.honor-lb-close,
.honor-lb-nav {
  position: absolute; z-index: 2; cursor: pointer; border: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--c-accent); color: var(--c-on-accent);
  transition: .18s;
}
.honor-lb-close {
  top: 10px; right: 10px; width: 38px; height: 38px;
  border-radius: var(--radius-round); font-size: 16px; line-height: 1;
}
.honor-lb-nav {
  top: 50%; transform: translateY(-50%);
  width: 44px; height: 68px; font-size: 26px; line-height: 1;
}
.honor-lb-nav.is-prev { left: 8px; }
.honor-lb-nav.is-next { right: 8px; }
.honor-lb-close:hover,
.honor-lb-nav:hover { filter: brightness(.9); }
.honor-lb-close:focus-visible,
.honor-lb-nav:focus-visible { outline: 3px solid var(--c-edge-dark, #fff); outline-offset: 2px; }

/* 减少动态效果：不自动滚，退回成一条可以自己滑动的静态行。
   副本 rail 同时隐藏 —— 它存在的唯一理由是让动画接得上，
   不动了就不该让同一批证书在页面上出现两遍。 */
@media (prefers-reduced-motion: reduce) {
  .marquee {
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    -webkit-mask-image: none; mask-image: none;
  }
  .marquee-rail { animation: none; }
  .marquee-rail[aria-hidden="true"] { display: none; }
  .honor-card:hover .honor-fig { transform: none; }
  .honor-lightbox[open] { animation: none; }
}

/* 打印：轨道是"动效"，纸上留不住。摊平成一份完整清单，一张不漏。 */
@media print {
  .marquee { display: block; overflow: visible; padding: 0; }
  .marquee-rail { display: flex; flex-wrap: wrap; animation: none; }
  .marquee-rail[aria-hidden="true"] { display: none; }
  .honor-card { width: 31%; margin: 0 1% 12px 0; }
  .honor-zoom { display: none; }
  .honor-lightbox { display: none !important; }
}

@media (max-width: 720px) {
  .marquee {
    padding: 8px 0 12px;
    -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%);
    mask-image: linear-gradient(90deg, transparent 0, #000 22px, #000 calc(100% - 22px), transparent 100%);
  }
  .honor-block + .honor-block { margin-top: 34px; }
  .honor-block-head h3 { font-size: 16px; }
  .honor-count { margin-left: 0; }
  .honor-meta { padding: 10px 11px 12px; }
  .honor-name { font-size: 12.5px; }
  .honor-lightbox { width: 96vw; max-height: 94vh; }
  .honor-lb-fig img { max-height: 66vh; }
  .honor-lb-nav { width: 36px; height: 54px; font-size: 22px; }
  .honor-lb-close { width: 34px; height: 34px; }
}

/* ==================================================================
   关于我们 · 图片播放框（site.media.about）
   ------------------------------------------------------------------
   一个带边框的框体，框内是一条首尾相接的图片带，由右往左循环滚。
   滚动机制与上面的证书轨道同源（构建期复制轨道 + translateX(-100%) 接续），
   但**类名刻意不复用 marquee**：两者是不同的组件，混用类名会让"数一数有几条
   轨道"这类判断同时命中两处，改一处伤另一处。

   几何上有三个数**必须与 build.js 一致**：一份轨道的宽度就是按 --reel-h-d
   （桌面高度）与 --reel-gap 逐张累加算出来的，复制份数与滚动时长都由它推出。
   所以这里只写兜底值，真值由构建期以行内变量下发 ——
   改高度 / 间距请改 build.js 的 REEL_H / REEL_H_MOBILE / REEL_GAP。
   ================================================================== */
.reel {
  /* --reel-pad 与 ::before 的 inset 共用同一个值：内唇正好压在图片边缘上。
     两者一旦不一致，就会露出一条宽窄不匀的缝。 */
  --reel-pad: 10px;
  --reel-h: var(--reel-h-d, 360px);
  position: relative;
  padding: var(--reel-pad);
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
/* 内圈细描边：与外框一起构成"相框嵌在页面里"的两层结构。
   立体感靠它 + 外阴影，而不是靠加厚边框 —— 厚边框在换配色后会显得笨重。 */
.reel::before {
  content: '';
  position: absolute;
  inset: var(--reel-pad);
  border-radius: var(--radius);
  box-shadow: inset 0 0 0 1px var(--c-border);
  pointer-events: none;
}
.reel-viewport {
  display: flex;
  overflow: hidden;                 /* 框体真正的作用：把带子裁在框内 */
  border-radius: var(--radius);
  background: var(--c-bg-soft);
}
/* 一份图片带。副本由构建期产出、带 aria-hidden（里面没有可聚焦元素，所以
   不需要 tabindex），视觉上与第一份完全接续 —— 循环"没有 JS 也成立"。
   间距用 margin-right 而不是 flex 的 gap：带子靠 translateX(-100%) 首尾相接，
   只有当「最后一张之后也有一个间距」时，接缝处的间距才和别处一样；
   用 gap 会差半个间距，循环时肉眼能看到"抖一下"（证书轨道同因）。 */
.reel-track {
  display: flex; flex: none;
  list-style: none; margin: 0; padding: 0;
  animation: reel-scroll var(--reel-duration, 40s) linear infinite;
  will-change: transform;
}
@keyframes reel-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-100%, 0, 0); }
}
/* 只有 1 张图：不循环（构建期给 data-static）。一张图自己追自己的尾巴，
   看起来像页面卡住了，不如老老实实摆一张。 */
.reel[data-static="1"] .reel-track { animation: none; }
/* 悬停暂停：不暂停的话，用户永远看不清任何一张正在匀速移动的照片。 */
.reel:hover .reel-track { animation-play-state: paused; }
.reel-item {
  flex: none;
  position: relative;
  width: calc(var(--reel-h, 360px) * var(--ar, 1.5));
  height: var(--reel-h, 360px);
  margin-right: var(--reel-gap, 6px);
  background: var(--c-bg-soft);
  list-style: none;
  overflow: hidden;
}
/* cover 而不是 contain：这里是实景照片，裁掉一点边不影响信息，换来带子上下
   齐平、没有参差。（证书不能这么干 —— 裁掉印章或登记号那张图就废了。） */
.reel-item img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* 图注压在照片底部。**刻意不跟随主题**：底图深浅是用户自己传的照片决定的，
   浅底图上"跟随主题的文字色"会直接读不出来 —— 固定白字 + 暗色压暗层最稳。
   （与首屏轮播 .hero-slider 的 --hero-scrim 是同一处理、同一组取色。） */
.reel-cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 22px 12px 9px;
  font-size: 12.5px; line-height: 1.5; color: #fff;
  background: linear-gradient(180deg, rgba(6, 14, 26, 0), rgba(6, 14, 26, .72));
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.reel-missing {
  display: flex; align-items: center; justify-content: center;
  height: 100%; padding: 16px; text-align: center;
  font-size: 12.5px; color: var(--c-warn);
}

/* 窄屏：整条带子矮一档。高度由构建期下发的 --reel-h-m 决定，
   不能用媒体查询硬覆盖 --reel-h-d —— 行内变量是压不过的，只能 !important。 */
@media (max-width: 720px) {
  .reel { --reel-h: var(--reel-h-m, 220px); --reel-pad: 7px; }
  .reel-cap { padding: 18px 10px 7px; font-size: 11.5px; }
}

/* 减少动态效果：不自动滚，退回成一条可以自己滑动的静态带子。
   副本同时隐藏 —— 它存在的唯一理由是让动画接得上，不动了就不该让同一批
   照片在页面上出现两遍。 */
@media (prefers-reduced-motion: reduce) {
  .reel-viewport { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .reel-track { animation: none; }
  .reel-track[aria-hidden="true"] { display: none; }
}

/* 打印：带子是"动效"，纸上留不住。摊平成一张不漏的清单。 */
@media print {
  .reel { box-shadow: none; padding: 0; border: 0; }
  .reel::before { display: none; }
  .reel-viewport { display: block; overflow: visible; }
  .reel-track { display: flex; flex-wrap: wrap; animation: none; }
  .reel-track[aria-hidden="true"] { display: none; }
  .reel-item { width: 31%; height: auto; aspect-ratio: var(--ar, 1.5); margin: 0 1% 10px 0; }
}

/* ==================================================================
   AI 客服助手
   ------------------------------------------------------------------
   配色全部走主题变量（--c-primary 等），所以后台换配色时客服组件跟着变，
   不需要单独维护一套颜色。唯一写死的例外是聊天气泡里的正文色 —— 那是
   「浅底深字 / 主色底白字」两种对比关系，必须固定，否则主题一深就不可读。
   ================================================================== */
.chat-dock {
  position: fixed;
  right: 22px;
  bottom: 22px;
  z-index: 200;                    /* 必须高于 sticky 导航（100） */
  font-size: 14px;
  line-height: 1.65;
  /* 安全区：iPhone 底部横条 / 圆角处不要被遮住 */
  right: calc(22px + env(safe-area-inset-right, 0px));
  bottom: calc(22px + env(safe-area-inset-bottom, 0px));
}

.chat-launcher {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  /* 徽章式入口（用户参考样式）：左侧白圆机器人徽章 + 主题色胶囊。
     左内边距收到徽章外缘 6px，徽章贴边像「头像」，整体仍是 pill 轮廓。 */
  padding: 5px 20px 5px 6px;
  /* 和卡片标签同一套语言：椭圆角 + 细描边。缺省描边用 currentColor，
     所以任何主色下它都是"按钮文字色"的一圈，对比度天然够（黄底深边、蓝底白边）；
     主色近黑时（近黑块在浅底上是个"没有细节的黑洞"）改描品牌强调色，--c-primary-edge。 */
  border: 1px solid var(--c-primary-edge, currentColor);
  border-radius: var(--radius-pill);
  background: var(--c-primary);
  color: var(--c-on-primary);
  font-weight: 600;
  box-shadow: 0 8px 26px rgba(10, 25, 55, .26);
  transition: .18s;
}
.chat-launcher:hover { background: var(--c-primary-dark); color: var(--c-on-primary-dark); border-color: var(--c-primary-edge-dark, currentColor); transform: translateY(-2px); }
/* 白圆机器人徽章：悬停时轻微放大（科技感点睛，颜色走主题变量随主题换色） */
.chat-launcher-badge {
  width: 34px; height: 34px; border-radius: 50%;
  background: #ffffff;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06);
  transition: transform .18s;
}
.chat-launcher:hover .chat-launcher-badge { transform: scale(1.06); }
.chat-launcher-ico { font-size: 17px; line-height: 1; }
/* 面板打开后收起入口文字，只留圆点式的收起按钮，避免遮挡 */
.chat-dock.is-open .chat-launcher { display: none; }

.chat-panel {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 384px;
  max-width: calc(100vw - 32px);
  height: 566px;
  max-height: calc(100vh - 96px);
  display: flex;
  flex-direction: column;
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  box-shadow: 0 18px 60px rgba(8, 20, 45, .28);
  overflow: hidden;
}
.chat-panel[hidden] { display: none; }

.chat-head {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 14px 16px;
  background: var(--c-primary);
  color: var(--c-on-primary);
}
.chat-head-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.chat-head-txt strong { font-size: 15.5px; }
.chat-head-txt span { font-size: 12.5px; opacity: .82; }
.chat-close {
  flex: none; width: 30px; height: 30px; padding: 0; cursor: pointer;
  border: 0; border-radius: var(--radius-sm); background: rgba(255, 255, 255, .18);
  color: var(--c-on-primary); font-size: 19px; line-height: 1;
}
.chat-close:hover { background: rgba(255, 255, 255, .3); }

.chat-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 16px;
  background: var(--c-bg-soft);
}
.chat-msg {
  max-width: 92%;
  margin-bottom: 12px;
  padding: 10px 14px;
  border-radius: var(--radius-lg);
  overflow-wrap: anywhere;
  white-space: normal;
}
.chat-msg-bot {
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  color: var(--c-text);
  border-top-left-radius: var(--radius-sm);
}
/* 用户气泡用主色底 + --c-on-primary 文字：文字色跟主题走（写死白字遇亮黄主色会看不清） */
.chat-msg-user {
  margin-left: auto;
  background: var(--c-primary);
  color: var(--c-on-primary);
  border-top-right-radius: var(--radius-sm);
}
.chat-msg.is-error {
  background: #fff7ed;
  border-color: #fed7aa;
  color: #92400e;
}
.chat-src { margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--c-border); }
.chat-src-label { color: var(--c-text-3); font-size: 12px; margin-right: 4px; }
.chat-src a {
  display: block; font-size: 12.5px; color: var(--c-primary-ink);
  padding: 1px 0; overflow-wrap: anywhere;
}
.chat-notice { font-size: 12px; color: var(--c-warn); margin: 6px 0 0; }

.chat-suggest { margin-top: 6px; }
.chat-suggest-title { font-size: 12.5px; color: var(--c-text-3); margin: 0 0 8px; }
.chat-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.chat-chips li { margin: 0; }
.chat-chip {
  display: block; width: 100%; text-align: left;
  font: inherit; font-size: 13.5px; cursor: pointer;
  padding: 9px 12px;
  border: 1px solid var(--c-primary-line);
  border-radius: var(--radius-sm);
  background: var(--c-bg);
  color: var(--c-primary-ink);
}
.chat-chip:hover { background: var(--c-primary-soft); }
.chat-chip:focus-visible { outline: 2px solid var(--c-primary-ink); outline-offset: 1px; }

.chat-fb {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin: -4px 0 14px; font-size: 12.5px; color: var(--c-text-3);
}
.chat-fb-q { flex: 1 1 100%; }
.chat-fb-btn {
  font: inherit; font-size: 12.5px; cursor: pointer;
  padding: 5px 12px; border-radius: var(--radius-round);
  border: 1px solid var(--c-border); background: var(--c-bg); color: var(--c-text-2);
}
.chat-fb-btn:hover { border-color: var(--c-primary-ink); color: var(--c-primary-ink); }
.chat-fb.is-done .chat-fb-q { flex: 1 1 100%; color: var(--c-text-2); }

.chat-form {
  display: flex; gap: 8px; align-items: center;
  padding: 10px 12px;
  border-top: 1px solid var(--c-border);
  background: var(--c-bg);
}
.chat-form input {
  flex: 1; min-width: 0; font: inherit; font-size: 14px;
  padding: 10px 12px;
  border: 1px solid var(--c-border); border-radius: var(--radius-sm);
  background: var(--c-bg); color: var(--c-text);
}
.chat-form input:focus { outline: 2px solid var(--c-primary-soft); border-color: var(--c-primary-ink); }
.chat-send {
  flex: none; font: inherit; font-weight: 600; cursor: pointer;
  padding: 10px 16px; border: 0; border-radius: var(--radius-sm);
  background: var(--c-primary); color: var(--c-on-primary);
}
.chat-send:hover { background: var(--c-primary-dark); color: var(--c-on-primary-dark); }
.chat-send:disabled { opacity: .6; cursor: default; }

.chat-human {
  padding: 10px 14px 12px;
  border-top: 1px solid var(--c-border);
  background: var(--c-bg-soft);
}
.chat-human-title { margin: 0 0 6px; font-size: 12.5px; color: var(--c-text-3); }
.chat-human-links { display: flex; flex-wrap: wrap; gap: 6px 12px; font-size: 13px; }
.chat-human-links a, .chat-human-links span {
  color: var(--c-primary-ink); cursor: pointer; padding: 2px 0;
}
.chat-human-note { margin: 6px 0 0; font-size: 12px; color: var(--c-text-3); }
.chat-disclaimer {
  margin: 0; padding: 8px 14px 10px;
  font-size: 11.5px; color: var(--c-text-3); background: var(--c-bg-soft);
}

.chat-toast {
  position: absolute; right: 0; bottom: 64px;
  max-width: 280px; padding: 9px 14px;
  background: #1f2937; color: #fff; font-size: 13px;
  border-radius: var(--radius-sm); box-shadow: 0 8px 24px rgba(0, 0, 0, .3);
  transition: opacity .4s, transform .4s;
}
.chat-toast.is-out { opacity: 0; transform: translateY(6px); }

.chat-noscript {
  max-width: 320px; margin-top: 10px; padding: 12px 14px;
  background: var(--c-bg-soft); border: 1px solid var(--c-border);
  border-radius: var(--radius); font-size: 13px; color: var(--c-text-2);
}

/* 手机上：客服面板改成整屏，聊天体验才正常（半屏输入法一弹就看不见了） */
@media (max-width: 720px) {
  .chat-dock.chat-on-mobile {
    right: calc(14px + env(safe-area-inset-right, 0px));
    bottom: calc(14px + env(safe-area-inset-bottom, 0px));
  }
  .chat-panel {
    position: fixed;
    inset: 0;
    width: auto;
    max-width: none;
    height: auto;
    max-height: none;
    border-radius: 0;
    border: 0;
    padding-top: env(safe-area-inset-top, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }
  /* 整屏时把关闭键做大一点，用户不会误以为卡住了 */
  .chat-close { width: 36px; height: 36px; font-size: 22px; }
  .chat-human-links a, .chat-human-links span { padding: 6px 0; }
  body.chat-lock { overflow: hidden; }
  /* 后台关掉了「手机端显示客服」时，手机上不出现入口（桌面端仍可用） */
  .chat-dock:not(.chat-on-mobile) { display: none; }
}

/* 打印时不该出现浮动对话框 */
@media print {
  .chat-dock { display: none !important; }
}

/* ==================================================================
   移动端适配（480px 档）
   ------------------------------------------------------------------
   上面的 1000 / 980 / 720 三档已经处理了栅格塌陷，这里补齐「真正的手机」
   才会暴露的问题：
     · 24px 的页面内边距在 360px 宽的屏上占掉太多，正文只剩 312px；
     · iOS 横竖屏切换会放大字号（text-size-adjust），字号会突然变小或变大；
     · 规格表两列在窄屏上横向溢出，把整页撑出横向滚动条；
     · 页尾链接、导航项的点击区域小于 44px，手指点不准；
     · 时间轴、面包屑这类「桌面布局」在窄屏需要换行。
   规则统一放在文件末尾，靠顺序覆盖前面的同权重声明，避免到处改旧代码。
   ================================================================== */
html {
  /* 阻止 iOS 旋转屏幕时自动放大字号（Safari 的默认行为，很多人以为是「字号变奇怪」） */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  /* 手机上长 URL、长型号不该把页面顶宽 */
  overflow-wrap: break-word;
}

@media (max-width: 720px) {
  .wrap, .narrow { padding: 0 16px; }
  .header-inner { height: 62px; gap: 12px; }
  .brand-logo { height: 30px; max-width: 168px; }
  /* 导航与页尾的点击区域撑到 44px 以上：手指的命中半径比鼠标粗得多 */
  .nav-item > a { padding: 13px 8px; font-size: 15.5px; }
  .nav-drop li a { padding: 11px 12px; }
  .footer-col li { margin-bottom: 2px; }
  .footer-col li a { display: inline-block; padding: 7px 0; }
  .footer-bottom { flex-direction: column; gap: 6px; }
  .crumbs { flex-wrap: wrap; }
  /* 规格表：窄屏改为「可横向滑动」，而不是把页面撑宽。
     用 display:block + overflow-x 让表格自己滚，模板不需要包一层容器。 */
  .spec-table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .spec-table th { width: 104px; white-space: nowrap; }
  /* 首屏轮播：高度交给内容决定。写死 min-height 时，文案一长就会和
     底部的数据条、圆点压在一起 —— 这是手机上最容易翻车的地方。 */
  .hero-slides { min-height: 0; }
  .hero-slider .hero-slide-inner { padding: 46px 0 30px; }
  .hero-slider .hero-facts-bar { position: static; background: rgba(8, 16, 30, .82); padding: 18px 0 16px; }
  .hero-slider .hero-dots { position: static; transform: none; justify-content: center; margin: 0; padding: 12px 0 16px; }
  .hero-slider .hero-slide { align-items: flex-start; }
  .trust-inner { gap: 10px 18px; font-size: 13px; }
  .section { padding: 40px 0; }
  .page-head { padding: 28px 0 22px; }
  .btn { padding: 12px 20px; }
  .hero-actions .btn, .cta-actions .btn { flex: 1 1 auto; }
  .cta-inner { flex-direction: column; align-items: flex-start; gap: 18px; }
  .card { padding: 20px; }
}

@media (max-width: 480px) {
  /* 圆角已统一为直角，小屏不再需要「更紧凑的圆角」这一档 */
  body { font-size: 14.5px; }
  h1 { font-size: 23px; }
  h2 { font-size: 19px; }
  h3 { font-size: 16.5px; }
  .page-head h1 { font-size: 22px; }
  .hero-slider h1, .hero-slider .hero-title { font-size: 23px; }
  .hero:not(.hero-slider) h1 { font-size: 23px; }
  .hero-lead, .page-lead, .prose p { font-size: 14.5px; }
  .wrap, .narrow { padding: 0 14px; }
  .hero-facts { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .hero-facts strong { font-size: 22px; }
  .spec-table th, .spec-table td { padding: 10px 12px; }
  .card-grid { gap: 14px; }
  .contact-form input, .contact-form textarea { padding: 12px 13px; }
}

/* 触屏设备：hover 类的交互（如二级菜单靠悬停展开）完全失效，
   这里统一切换成「点击展开」，由 main.js 注入的 caret 按钮负责（见 .nav-sub-toggle） */
.nav-sub-toggle { display: none; }
@media (max-width: 720px) {
  .nav-item.has-drop { position: relative; }
  .nav-sub-toggle {
    display: flex; align-items: center; justify-content: center;
    position: absolute; right: 4px; top: 4px;
    width: 40px; height: 40px; padding: 0; cursor: pointer;
    border: 0; border-radius: var(--radius-sm); background: transparent;
    color: var(--c-text-3); font-size: 13px;
  }
  .nav-sub-toggle::after { content: "▾"; }
  .nav-item.has-drop.is-open .nav-sub-toggle::after { content: "▴"; }
  .nav-sub-toggle:hover { background: var(--c-primary-soft); color: var(--c-primary-ink); }
  /* 有 JS 时才折叠二级菜单：没有 JS 就保持常显（现状可用），
     绝不能出现「点了没反应、菜单也打不开」的死状态。 */
  .has-js .nav-drop { display: none; }
  .has-js .nav-item.has-drop.is-open .nav-drop { display: block; }
  .has-js .nav-item.has-drop > a { padding-right: 44px; }
}

/* ==================================================================
   自助配单（/configurator/）
   ------------------------------------------------------------------
   这一块全部用 cfg- 前缀：本文件末尾这些规则排在前面所有 @media 之后，
   若复用了通用类名（.card / .form-row 之类），会在窄屏上反过来盖掉那些
   @media 里的适配。用独立前缀就完全没有这个问题。
   ================================================================== */
.cfg-intro p { font-size: 15.5px; }

/* —— 表单 —— */
.cfg-form { display: grid; gap: 26px; }
.cfg-block {
  margin: 0;
  padding: 22px 24px 6px;
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  background: var(--c-bg);
}
.cfg-block legend {
  padding: 0 8px;
  font-size: 16px;
  font-weight: 700;
  color: var(--c-text);
}
.cfg-block > .cfg-block-desc {
  margin: 0 0 18px;
  font-size: 13.5px;
  color: var(--c-text-3);
}
.cfg-fields { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px 24px; }
.cfg-field { display: grid; gap: 6px; align-content: start; }
.cfg-field > label { font-size: 14px; font-weight: 600; color: var(--c-text); }
.cfg-field .req { color: var(--c-warn); }
.cfg-field select,
.cfg-field input[type="number"],
.cfg-field input[type="text"],
.cfg-field input[type="tel"] {
  width: 100%;
  padding: 11px 12px;
  font: inherit;
  font-size: 14.5px;
  color: var(--c-text);
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm);
}
.cfg-field select:focus,
.cfg-field input[type="number"]:focus,
.cfg-field input[type="text"]:focus,
.cfg-field input[type="tel"]:focus {
  outline: none;
  border-color: var(--c-primary-ink);
  box-shadow: 0 0 0 3px var(--c-primary-tint);
}
.cfg-hint { margin: 0; font-size: 12.5px; line-height: 1.6; color: var(--c-text-3); }
.cfg-unit { font-size: 12.5px; color: var(--c-text-3); }

.cfg-actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

/* —— 结果 —— */
.cfg-result[hidden] { display: none; }
.cfg-cat { margin-bottom: 26px; }
.cfg-cat > h3 {
  margin: 0 0 12px;
  padding-left: 10px;
  font-size: 16px;
  border-left: 3px solid var(--c-primary-ink);
}
.cfg-items { display: grid; gap: 12px; }
.cfg-item {
  padding: 16px 18px;
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-bg-soft);
}
.cfg-item-head {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: baseline;
  justify-content: space-between;
}
.cfg-item-head h4 { margin: 0; font-size: 15.5px; color: var(--c-text); }
.cfg-qty {
  flex: none;
  font-size: 14px;
  font-weight: 700;
  color: var(--c-primary-ink);
  white-space: nowrap;
}
.cfg-item-meta { margin: 6px 0 8px; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
/* 型号 / 单位这类技术标记走直角，与「可选配 / 已升配」的椭圆角标签刻意区分开：
   椭圆角在本站是「标签」的专属语言（见 --radius-pill 的说明）。 */
.cfg-item-meta code {
  font-size: 12px;
  color: var(--c-text-3);
  background: var(--c-bg);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: 1px 8px;
}
.cfg-tag {
  font-size: 11.5px;
  color: var(--c-primary-ink);
  border: 1px solid var(--c-primary-ink-line);
  border-radius: var(--radius-pill);
  padding: 1px 8px;
}
.cfg-item-spec,
.cfg-item-reason,
.cfg-item-why,
.cfg-item-link { margin: 0 0 6px; font-size: 13.5px; line-height: 1.7; }
.cfg-item-why { color: var(--c-text-3); }
.cfg-item-link { margin-bottom: 0; }

.cfg-notes { display: grid; gap: 10px; margin: 6px 0 22px; }
.cfg-note {
  padding: 12px 14px;
  font-size: 13.5px;
  line-height: 1.7;
  border-left: 3px solid var(--c-primary-ink);
  background: var(--c-primary-soft);
}
.cfg-note.is-warn { border-left-color: var(--c-warn); background: #fff7ed; color: #8a4b12; }

.cfg-ai {
  margin: 0 0 22px;
  padding: 18px 20px;
  border: 1px solid var(--c-border);
  border-left: 3px solid var(--c-accent);
  border-radius: var(--radius);
}
.cfg-ai h3 { font-size: 15px; margin-bottom: 8px; }
.cfg-ai p { font-size: 14px; margin-bottom: 8px; }
.cfg-ai .cfg-ai-note { margin: 0; font-size: 12.5px; color: var(--c-text-3); }

/* —— 联系区块 —— */
.panel-card {
  padding: 22px 24px;
  border: 1px solid var(--c-border);
  border-radius: var(--radius-lg);
  background: var(--c-bg);
}
.cfg-contact[hidden] { display: none; }
.cfg-contact h3 { font-size: 17px; }
.cfg-contact p { font-size: 13.5px; }
.cfg-contact .form-row { margin-bottom: 14px; }
.cfg-contact label { display: grid; gap: 6px; font-size: 13.5px; font-weight: 600; color: var(--c-text); }
.cfg-contact input,
.cfg-contact textarea {
  width: 100%;
  padding: 11px 12px;
  font: inherit;
  font-size: 14.5px;
  color: var(--c-text);
  border: 1px solid var(--c-border);
  border-radius: var(--radius-sm);
}
.cfg-contact input:focus,
.cfg-contact textarea:focus {
  outline: none;
  border-color: var(--c-primary-ink);
  box-shadow: 0 0 0 3px var(--c-primary-tint);
}
.cfg-contact textarea { margin-bottom: 14px; }
.cfg-disclaimer { margin-top: 18px; }

/* —— 条目库（静态 GEO 清单）—— */
.cfg-lib-cat { margin-bottom: 24px; }
.cfg-lib-cat > h3 {
  margin: 0 0 10px;
  padding-left: 10px;
  font-size: 16px;
  border-left: 3px solid var(--c-primary-ink);
}
.cfg-lib-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.cfg-lib-table th,
.cfg-lib-table td {
  padding: 10px 12px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--c-border);
}
.cfg-lib-table th { background: var(--c-bg-soft); font-weight: 600; color: var(--c-text); white-space: nowrap; }
.cfg-lib-table td { color: var(--c-text-2); line-height: 1.65; }
.cfg-lib-table code { font-size: 12px; color: var(--c-text-3); }

@media (max-width: 900px) {
  .cfg-fields { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  .cfg-block { padding: 18px 16px 4px; }
  .cfg-item { padding: 14px 14px; }
  .cfg-lib-table { font-size: 13px; }
  .cfg-lib-table th, .cfg-lib-table td { padding: 8px 8px; }
}

/* —— 自助配单 · 打印纸面（点「打印 / 存为 PDF」只出需求信息与清单，2026-09）——
   纸面节点由 configurator.js 生成清单后挂到 body 末尾，屏幕上永远 display:none。
   body 的 cfg-has-print-sheet 类是打印开关：有它 → 打印时 body 下除纸面以外的
   直接子元素全部藏起；没有它（还没生成清单）→ 维持老行为，打印整个页面。
   刻意用固定灰阶、不引主题色：这张纸要拿去打印 / 存 PDF，不吃彩墨、不随主题变。 */
.cfg-print-sheet { display: none; }
@media print {
  body.cfg-has-print-sheet > :not(.cfg-print-sheet) { display: none !important; }
  body.cfg-has-print-sheet .cfg-print-sheet {
    display: block;
    color: #111;
    font-size: 12.5pt;
    line-height: 1.6;
  }
  .cfg-print-sheet h2 { font-size: 17pt; margin: 0 0 4px; }
  .cfg-print-sheet .cfg-ps-meta { font-size: 10pt; color: #555; margin: 0 0 18px; }
  .cfg-print-sheet .cfg-ps-sec { margin-bottom: 18px; }
  .cfg-print-sheet h3 {
    font-size: 12pt;
    margin: 0 0 8px;
    padding-bottom: 4px;
    border-bottom: 1.5px solid #111;
  }
  .cfg-print-sheet h4 { font-size: 11pt; margin: 0 0 4px; }
  .cfg-print-sheet .cfg-ps-group,
  .cfg-print-sheet .cfg-ps-cat { margin-bottom: 10px; break-inside: avoid; page-break-inside: avoid; }
  .cfg-print-sheet .cfg-ps-row {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    padding: 3px 0;
    border-bottom: 0.5pt solid #ddd;
  }
  .cfg-print-sheet .cfg-ps-q { color: #555; white-space: nowrap; }
  .cfg-print-sheet .cfg-ps-a { text-align: right; font-weight: 600; }
  .cfg-print-sheet .cfg-ps-summary { font-size: 10.5pt; color: #444; margin: 0 0 10px; }
  .cfg-print-sheet .cfg-ps-item {
    padding: 6px 0;
    border-bottom: 0.5pt solid #ddd;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .cfg-print-sheet .cfg-ps-item-head { display: flex; justify-content: space-between; gap: 16px; margin: 0; }
  .cfg-print-sheet .cfg-ps-item-name { font-weight: 700; }
  .cfg-print-sheet .cfg-ps-item-qty { white-space: nowrap; }
  .cfg-print-sheet .cfg-ps-item-sub { margin: 2px 0 0; font-size: 10pt; color: #444; }
  .cfg-print-sheet .cfg-ps-note { margin: 2px 0; font-size: 10pt; color: #444; }
  .cfg-print-sheet .cfg-ps-disclaimer {
    margin-top: 14px;
    padding-top: 8px;
    border-top: 1.5px solid #111;
    font-size: 9.5pt;
    color: #555;
  }
}

/* ==================================================================
   产品图集轮播（产品页）：横向轨道，5 秒/张自动左移。
   静态优先：全部图片都写在 HTML 里；无 JS 时轨道可横向滑动（兜底可读）。
   有 JS 时 .pgal--js 收起溢出、用 transform 切换 + 圆点导航。 */
.pgal { position: relative; overflow-x: auto; scroll-snap-type: x mandatory; }
.pgal-track { display: flex; margin: 0; padding: 0; list-style: none; }
.pgal-slide { flex: 0 0 100%; margin: 0; scroll-snap-align: start; min-width: 0; }
.pgal-img { aspect-ratio: 16 / 9; background: #fff; border: 1px solid var(--c-border); border-radius: var(--radius); overflow: hidden; display: flex; align-items: center; justify-content: center; }
.pgal-img img, .pgal-img figure { max-width: 100%; max-height: 100%; width: auto; height: auto; margin: 0; }
.pgal-img img { object-fit: contain; display: block; }
.pgal-cap { text-align: center; font-size: 13px; color: var(--c-text-2); margin-top: 8px; }
.pgal-dots { display: none; justify-content: center; gap: 8px; margin-top: 12px; }
.pgal-dots button { width: 10px; height: 10px; padding: 0; border-radius: 50%; border: 1px solid var(--c-primary-ink); background: transparent; cursor: pointer; }
.pgal-dots button[aria-current="true"] { background: var(--c-primary-ink); }
.pgal--js { overflow: hidden; }
.pgal--js .pgal-track { transition: transform .55s ease; }
.pgal--js .pgal-slide[aria-hidden="true"] { visibility: hidden; }

/* ==================================================================
   首页专属调整（用户要求 2026-09-28）
   ① 核心产品卡固定高度（参考较高卡 -10px）：长摘要裁切、按钮贴底；
   ② 首页各区块间距 72px → 50px（-30%）。hero / trust-band 不受影响。 */
.home-sec.section { padding: 50px 0; }
.home-products-grid .card.card-tile { display: flex; flex-direction: column; }
.home-products-grid .card.card-tile .card-thumb { flex: 0 0 auto; }
.home-products-grid .card.card-tile .card-body { flex: 1 1 auto; display: flex; flex-direction: column; overflow: hidden; }
.home-products-grid .card.card-tile .card-body p { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; margin-bottom: 10px; }
.home-products-grid .card.card-tile .card-more { margin-top: auto; align-self: flex-start; }
.home-cases-grid .card.card-tile,
.home-knowledge-grid .card.card-tile,
.home-tile-grid .card.card-tile { display: flex; flex-direction: column; }
.home-cases-grid .card.card-tile .card-body,
.home-knowledge-grid .card.card-tile .card-body,
.home-tile-grid .card.card-tile .card-body { flex: 1 1 auto; display: flex; flex-direction: column; overflow: hidden; }
.home-cases-grid .card.card-tile .card-body p,
.home-knowledge-grid .card.card-tile .card-body p,
.home-tile-grid .card.card-tile .card-body p { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; margin-bottom: 10px; }
.home-cases-grid .card.card-tile .card-more,
.home-knowledge-grid .card.card-tile .card-more,
.home-tile-grid .card.card-tile .card-more { margin-top: auto; align-self: flex-start; }