/* components.css — 通用组件（frontend-execute.md §1.7 / §3.5） */

/* 眉题：OUR PRODUCTS / LATEST NEWS … */
.eyebrow {
  font-size: var(--font-size-body-md);
  font-weight: var(--font-weight-regular);
  line-height: 1.5rem; /* 设计稿 18/24 */
  color: var(--color-primary);
}

/* 区块标题（48/60 Jost Medium） */
.section-title {
  font-size: clamp(1.75rem, 1.1rem + 2.6vw, var(--font-size-h1));
  font-weight: var(--font-weight-medium);
  line-height: var(--line-height-title);
  color: var(--color-text-1);
}

/* Learn More 链接（设计稿 btn 组件：文字 + 圆角箭头块） */
.btn-more {
  display: inline-flex;
  align-items: center;
  gap: var(--space-5);
  font-size: var(--font-size-body-lg);
  line-height: 1;
  white-space: nowrap;
  color: var(--color-text-1);
}

/* 文字 hover 下划线：从左到右滑出（与 products.html 卡片 Learn More 同款，
   2026-09-18 用户要求推广到全站「文字+箭头」按钮）。
   ⚠ 下划线挂在**文字 span** 上，不是挂在 .btn-more 上 —— 若挂在外层，
   ::after 的 width:100% 会横跨整个按钮、划到箭头方块底下（用户明确不要）。
   选择器用 :not(.btn-more__icon) 而不是 :first-child：index 新闻卡有 3 个
   **纯图标**按钮（只有箭头没有文字），:first-child 会把下划线画到箭头上。
   颜色用 currentColor 跟随文字色（产品卡为白、正文为黑）。
   玻璃盒变体 --glass 排除：盒内文字底到边框仅约 9px，再画线显挤（用户决定）。 */
.btn-more:not(.btn-more--glass) > span:not(.btn-more__icon) {
  position: relative;
}

.btn-more:not(.btn-more--glass) > span:not(.btn-more__icon)::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -.375rem;
  width: 100%;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .2s ease-out;
}

.btn-more:not(.btn-more--glass):hover > span:not(.btn-more__icon)::after,
.btn-more:not(.btn-more--glass):focus-visible > span:not(.btn-more__icon)::after {
  transform: scaleX(1);
}

/* 图标块：35×35 圆角方块，内部是「双箭头跑马灯」。
   机制参考 Comacchio 站点 .max-arrow（2026-09-18 用户指定）：方块自身不动，
   只让内部两个箭头层滑动 —— hover 时出场层滑出右侧、入场层从左侧滑入。
   方块不位移是本机制的前提，否则裁切窗口跟着动，观感会乱。 */
.btn-more__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  position: relative;   /* 箭头层的定位上下文 */
  overflow: hidden;     /* 裁掉滑出方块的箭头层 */
  width: 2.1875rem;   /* 35 */
  height: 2.1875rem;
  border-radius: var(--radius-sm);
  background: var(--color-gray-300);
  color: var(--color-text-2);
  transition: background-color .3s ease;
}

/* 每个箭头层显式占方块宽度的 50% —— 两层并排刚好撑满，
   于是下面的百分比位移与参考站（其箭头宽度≈方块半宽）数学完全一致：
   静止 -150% / -50%，hover 50% / 150%，两层同步 +200%（= 一个方块宽）。
   ⚠ 必须写成 flex:0 0 50%：本项目箭头只有 7.5px，靠内容宽度撑不出半宽。
   ⚠ 结构上必须有两个层（--in / --out）。若新加按钮时只写一个箭头，
      不要用 :nth-child 规则去赌 —— 用显式修饰类，漏写时箭头正常可见（优雅降级），
      而 :nth-child(1) 会让「只有一个箭头」的按钮在静止态被推到 -150% 完全消失且无报错。 */
.btn-more__arrow {
  flex: 0 0 50%;
  display: grid;
  place-items: center;
  transition: transform .3s ease;
}

/* 静止：--in 推到左侧裁掉（-150%），--out 居中（-50%） */
.btn-more__arrow--in  { transform: translateX(-150%); }
.btn-more__arrow--out { transform: translateX(-50%); }

.btn-more__icon svg {
  width: .46875rem;   /* 7.5 */
  height: .703125rem; /* 11.25 */
}

.btn-more:hover .btn-more__icon {
  background: var(--color-primary);
  color: #fff;
}

/* hover：两层同时 +200% → --out 滑出右侧，--in 从左侧滑入 */
.btn-more:hover .btn-more__arrow--in  { transform: translateX(50%); }
.btn-more:hover .btn-more__arrow--out { transform: translateX(150%); }

/* 红色箭头变体（About Us / 产品卡） */
.btn-more--red .btn-more__icon {
  background: var(--color-primary);
  color: #fff;
}

.btn-more--red:hover .btn-more__icon {
  background: var(--color-primary-dark);
}

/* 描边玻璃拟态变体（KV / Solutions，172×51 描边盒） */
.btn-more--glass {
  width: 10.75rem;    /* 172 */
  height: 3.1875rem;  /* 51 */
  padding: .75rem .625rem .75rem .625rem;
  justify-content: space-between;
  border: 1px solid #fff;
  border-radius: var(--radius-sm);
  color: #fff;
  background: rgba(255, 255, 255, .02);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  box-shadow: var(--shadow-btn-glass);
}

.btn-more--glass:hover {
  background: rgba(255, 255, 255, .12);
}

/* 数据项（About 区） */
.stat {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: auto;
  max-width: 16.5625rem;  /* 265 */
  min-height: 8.9375rem; /* 143 */
}

.stat__value {
  font-size: var(--font-size-stat);
  font-weight: var(--font-weight-bold);
  line-height: 6.875rem; /* 110 */
  letter-spacing: -.1875rem;
  color: var(--color-primary);
  text-shadow: 0 4px 10px rgba(255, 255, 255, .3); /* 30% 白色高光 */
}

.stat__label {
  font-size: var(--font-size-body-lg);
  line-height: 1.45;
  color: #fff;
}

/* ---------- 导航（公共组件，1920×96；首页覆盖于 KV 上，子页面白底态见 pages/products.css 的 .page-sub） ---------- */
.site-nav {
  position: absolute;
  inset: 0 0 auto;
  z-index: 10;
  height: 6rem;
  color: #fff;
  transition: background-color .2s ease-out;
}

/* ⚠ 子页面导航在流内（见 pages/products.css 的 .page-sub .site-nav { position: relative }），
   而本元素**没有 border / padding**、只指定了 height —— 指定高度**不阻止**父子外边距折叠。
   于是内层 .site-nav__inner 的 margin-top: 1.75rem(28px) 会一路折叠出去：
   .site-nav__inner → .site-nav → .page → body，把**整页下推 28px**。
   实测后果（products.html @1920）：body/nav 顶边 y=28、main 顶边 124（应为 96）、
   页脚顶边 4358.39（设计 4330）、documentElement.scrollHeight 4770（设计 4742）
   —— 页脚红块下面会多出一条 28px 白边，且所有区块整体偏离设计 28px。
   （首页 nav 是 position: absolute，绝对定位元素自成 BFC，不折叠 → 首页无此问题。）
   `display: flow-root` 建 BFC 阻断折叠链，**对导航内部几何零影响**
   （实测 innerTop 仍 28 / innerBottom 96 / logoTop 32 全部不变），只消掉那 28px 幻影位移。
   不要改用「nav 加 padding-top + inner margin 归零」——那个方案要动 margin 值，
   会和移动/平板档的 .site-nav__inner 外边距规则耦合，脆弱。 */
.page-sub .site-nav {
  display: flow-root;
}

.site-nav.is-scrolled {
  position: fixed;
  background: var(--color-bg-page); /* 下滑导航改白底 */
  color: var(--color-text-1);
  transition: background-color .2s ease-out, color .2s ease-out;
}

.site-nav__inner {
  display: flex;
  align-items: flex-start;
  height: 4.25rem;
  margin: 1.75rem 1.5rem 0;
  border-bottom: 1px solid currentColor;
  transition: border-color .2s ease-out;
}

.site-nav__logo {
  flex: none;
  align-self: flex-start;
  width: 8.75rem;    /* 移动端缩小 30%（200→140） */
  height: 1.625rem;
  margin: .25rem 0 0 .625rem;
}

.site-nav__logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.site-nav__menu {
  display: none;
  padding-top: .625rem;
  margin-left: auto;
}

/* ⚠ 选择器必须收窄到「直接子级」：下拉菜单里也有 ul / a，
   若沿用后代选择器（.site-nav__menu ul），会把 flex + gap:3.75rem 套到下拉项上。 */
.site-nav__menu > ul {
  display: flex;
  gap: 3.75rem;
}

.site-nav__menu > ul > li > a {
  font-size: var(--font-size-body-md);
  font-weight: var(--font-weight-medium);
  line-height: 1.625rem;
}

.site-nav__menu > ul > li > a:hover {
  color: var(--color-gray-300);
}

/* 白底导航（下滑态）hover 用主红 */
.site-nav.is-scrolled .site-nav__menu > ul > li > a:hover {
  color: var(--color-primary);
}

/* ---------- 导航下拉菜单（2026-09-20）----------
   参考 comacchio.com/en 的下拉结构，按它的排版参数实现：
   面板白底黑字（用户定，与子页导航一致）；下拉项 hover 变主红「红字 + 红线」。
   参考站原始值：13px / 500 / uppercase / letter-spacing .015em / 下拉项 padding 16px 0 /
   入场 opacity+translateY(-20px)，逐项延迟。此处字号按项目 token 取 14px。
   ⚠ 导航不在 [data-m-stagger] 容器内 → transition 不会被 motion.css 覆盖（坑 29 不适用）。
   ⚠ 别加 contain / will-change：会提升为独立绘制层，相邻层之间出现 1px 缝隙。 */
.site-nav__has-drop {
  position: relative;
}

.site-nav__drop {
  position: absolute;
  top: 100%;              /* = <li> 底边（约 y=64）*/
  left: 50%;
  transform: translateX(-50%);
  padding-top: 2rem;      /* 透明过渡区：补到导航底边 y=96，鼠标移过去不断 hover */
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .25s ease-out, visibility 0s linear .25s;
  z-index: 20;
}

.site-nav__drop > ul {
  min-width: 17.5rem;     /* 280px */
  padding: .25rem 1.25rem .5rem;
  background: var(--color-bg-page);
  border-top: 1px solid var(--color-border-1);
  box-shadow: var(--shadow-1);
}

.site-nav__drop > ul > li {
  opacity: 0;
  transform: translateY(-20px);
  transition: opacity .3s ease, transform .3s ease;
}

/* 逐项延迟入场（照搬参考站 .2s/.3s/.4s 的节奏，按面板 4 项压缩） */
.site-nav__drop > ul > li:nth-child(1) { transition-delay: .08s; }
.site-nav__drop > ul > li:nth-child(2) { transition-delay: .14s; }
.site-nav__drop > ul > li:nth-child(3) { transition-delay: .2s; }
.site-nav__drop > ul > li:nth-child(4) { transition-delay: .26s; }

.site-nav__drop > ul > li > a {
  display: block;
  padding: 1rem 0;        /* 参考站 16px 0 */
  border-bottom: 1px solid var(--color-border-1);
  color: var(--color-text-1);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-medium);
  letter-spacing: .015em;
  line-height: 1.5rem;
  text-transform: uppercase;
  white-space: nowrap;
  transition: color .2s ease-out, border-color .2s ease-out;
}

.site-nav__drop > ul > li:last-child > a {
  border-bottom: 0;
}

/* hover / 键盘聚焦：红字 + 红线（用户指定） */
.site-nav__drop > ul > li > a:hover,
.site-nav__drop > ul > li > a:focus-visible {
  color: var(--color-primary);
  border-bottom-color: var(--color-primary);
}

/* 展开态：hover / 键盘 focus-within / JS 加的 .is-open */
.site-nav__has-drop:hover .site-nav__drop,
.site-nav__has-drop:focus-within .site-nav__drop,
.site-nav__has-drop.is-open .site-nav__drop {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity .25s ease-out, visibility 0s;
}

.site-nav__has-drop:hover .site-nav__drop > ul > li,
.site-nav__has-drop:focus-within .site-nav__drop > ul > li,
.site-nav__has-drop.is-open .site-nav__drop > ul > li {
  opacity: 1;
  transform: translateY(0);
}

/* ---------- 导航搜索（点图标下拉出搜索框）----------
   用户指定：5px 圆角；框内左侧提示文字、右侧箭头按钮（主红）。 */
.site-nav__search {
  position: relative;
  display: inline-flex;
}

.site-nav__search-panel {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 2.5rem;     /* 补到导航底边 y=96 */
  display: none;
  align-items: center;
  gap: .5rem;
  width: 22.5rem;         /* 360px */
  padding: .3125rem .4375rem .3125rem .75rem;
  background: var(--color-bg-page);
  border: 1px solid var(--color-border-1);
  border-radius: .3125rem;   /* 5px（用户指定；token 里是 4px，此处按指定值）*/
  box-shadow: var(--shadow-1);
}

.site-nav.search-open .site-nav__search-panel {
  display: flex;
}

.site-nav__search-panel input[type="search"] {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-text-1);
  font-family: inherit;
  font-size: var(--font-size-body-sm);
  /* ⚠ 这里**故意不写** outline: none ——
     本规则特异性 (0,2,1) 会压掉 base.css 的全局 :focus-visible (0,1,0)，
     键盘用户就看不到焦点在哪（WCAG 2.4.7 AA）。
     要自定义焦点样式，请补**同特异性**的 :focus-visible 规则，别用 outline: none 一关了之。 */
}

/* 搜索输入框的焦点样式（2026-09-21 用户指定终版）：
   **1px 红边框 + 5px 圆角，仅聚焦时显示**。
   点开搜索时 main.js 会自动聚焦 input，全局 `:focus-visible { outline: 2px solid var(--color-primary) }`
   会让输入框立刻套上一个 2px 红圈；用户先嫌突兀，权衡后改为「更细的同色红边」。
   ⚠⚠ 这里写 `outline: none` 是**成对的**，不是坑 34 ——
     坑 34 指的是「关掉焦点环却没有任何替代指示」。本规则用 `box-shadow` 内描边**接管**了焦点指示，
     键盘用户依然看得见（≠ 无指示）。改这条时务必保证 box-shadow 还在。
   ⚠ 为什么用 `box-shadow: inset` 而不是 `border`：
     `border` 参与盒模型 → 1px 边框会让输入框内容区缩 2px、文字轻微位移；
     `box-shadow: inset` 不占空间，视觉等同一圈 1px 内描边，零位移。
   ⚠ 对比度校验：#c30e23 压在白色输入框（`--color-bg-page`）上 ≈ 5.4:1，
     超 WCAG 1.4.11 对「非文本界面组件」要求的 3:1 → 焦点指示清晰合规（WCAG 2.4.7 亦满足）。
   ⚠ 特异性 (0,3,1) ≥ 基础规则 (0,2,1)，能压过 base.css 的全局 :focus-visible (0,1,0)。
   ⚠ PC 与移动端共用此规则 —— 两端一起生效（用户明确要求两端都改）。
     移动端专属覆盖在文件末尾 `@media (max-width: 1279px)` 段，只改几何、不动颜色样式，
     故本规则在两端一致。 */
.site-nav__search-panel input[type="search"]:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 1px var(--color-primary);   /* #c30e23 */
  border-radius: 5px;                                  /* 用户指定；token 阶梯为 4px，故写裸值 */
}

.site-nav__search-panel input[type="search"]::placeholder {
  color: var(--color-text-3);
}

/* ⚠ 特异性必须高于 .site-nav__actions button（(0,1,1)），故写成 (0,2,0) */
.site-nav__actions .site-nav__search-go {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: .25rem;
  background: var(--color-primary);
  color: #fff;
}

/* ⚠ 必须盖掉 .site-nav__actions button svg 的 scaleY(-1)（那是搜索图标的专用翻转）*/
.site-nav__actions .site-nav__search-go svg {
  width: .75rem;
  height: .75rem;
  transform: none;
}

.site-nav__actions {
  display: none;
  align-items: center;
  gap: 2.625rem;
  padding-top: .625rem;
  margin-left: auto;
}

.site-nav__actions button,
.site-nav__lang {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  color: inherit; /* 跟随导航颜色（顶部白 / 下滑黑） */
}

.site-nav__actions button svg {
  width: 1.0625rem;
  height: 1.0625rem;
  transform: scaleY(-1); /* 设计稿内该图标做了垂直翻转，导出路径为原始坐标，需补回 */
}

.site-nav__lang span {
  font-size: var(--font-size-body-md);
  font-weight: var(--font-weight-medium);
}

/* 移动端汉堡：右缘与白线右端对齐，垂直居中于顶部到白线区间（0–96，中心 48） */
.site-nav__toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: .375rem;
  width: 2.75rem;
  height: 2.75rem;
  padding: .625rem;
  margin: -.125rem 0 0 auto; /* 44 高居中于 0–96 → top 26，扣除 inner 顶部偏移 28 */
}

.site-nav__toggle span {
  height: 2px;
  background: #fff;
  transition: transform .2s ease-out, opacity .2s ease-out, background-color .2s ease-out;
}

/* 下滑白底导航时汉堡线条转黑 */
.site-nav.is-scrolled .site-nav__toggle span {
  background: var(--color-text-1);
}

.nav-open .site-nav__toggle span:nth-child(1) {
  transform: translateY(.5625rem) rotate(45deg);
}

.nav-open .site-nav__toggle span:nth-child(2) {
  opacity: 0;
}

.nav-open .site-nav__toggle span:nth-child(3) {
  transform: translateY(-.5625rem) rotate(-45deg);
}

.site-nav.is-scrolled .site-nav__inner {
  margin-top: 1.75rem;
  border-color: transparent; /* 下滑后分隔线淡出 */
}

.site-nav.is-scrolled {
  height: 5.5rem;
}

/* 展开的移动菜单 */
.nav-open .site-nav__menu {
  display: block;
  position: absolute;
  top: 6rem;
  left: 0;
  right: 0;
  padding: 1rem 1.5rem 1.5rem;
  background: rgba(0, 0, 0, .92);
  color: #fff; /* 面板恒为黑底白字，不随导航变白 */
}

.nav-open .site-nav__menu > ul {
  flex-direction: column;
  gap: 1.25rem;
}

/* 移动/平板（<1280 都是汉堡菜单）：下拉改为「菜单内嵌套展开」（点击一级项 toggle .is-open） */
@media (max-width: 1279px) {
  .site-nav__has-drop > a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
  }

  /* 展开指示：右侧小箭头 */
  .site-nav__has-drop > a::after {
    content: "";
    flex: none;
    width: .5rem;
    height: .5rem;
    margin-top: -.3rem;
    border-right: 1px solid currentColor;
    border-bottom: 1px solid currentColor;
    transform: rotate(45deg);
    transition: transform .2s ease-out, margin-top .2s ease-out;
  }

  .site-nav__has-drop.is-open > a::after {
    margin-top: .1rem;
    transform: rotate(-135deg);
  }

  .site-nav__drop {
    position: static;
    transform: none;
    padding-top: 0;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    display: none;
  }

  .site-nav__has-drop.is-open .site-nav__drop {
    display: block;
  }

  .site-nav__drop > ul {
    min-width: 0;
    padding: .5rem 0 .25rem .875rem;
    background: none;
    border-top: 0;
    box-shadow: none;
  }

  .site-nav__drop > ul > li {
    opacity: 1;
    transform: none;
  }

  .site-nav__drop > ul > li > a {
    padding: .5rem 0;
    border-bottom-color: rgba(255, 255, 255, .18);
    color: rgba(255, 255, 255, .72);
  }

  .site-nav__drop > ul > li > a:hover {
    color: #fff;
    border-bottom-color: var(--color-primary);
  }
}

@media (min-width: 1280px) {
  .site-nav__toggle {
    display: none;
  }

  .site-nav__menu,
  .site-nav__actions {
    display: flex;
  }

  /* 三列网格：logo | 菜单（水平居中） | 动作区 */
  .site-nav__inner {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: start;
    margin: 1.75rem 3.125rem 0; /* 设计稿左右 50px */
  }

  .site-nav__logo {
    width: 12.5rem;   /* 桌面恢复设计稿尺寸 200×37 */
    height: 2.3125rem;
  }

  .site-nav__menu {
    grid-column: 2;
    margin: 0;
  }

  /* ⚠ 一级项必须是 block —— 否则下拉面板顶边会露出 1px 深灰缝（2026-09-20 逐像素实测）
     导航 <li> 里除了 <a> 还有模板缩进留下的空白文本节点，空白会生成行盒，
     把 li 撑到 26.59375px（<a> 的 line-height 是 1.625rem = 26px，多出的 0.59375px 来自空白行盒）。
     下拉面板 = top:100% + padding-top:2rem → 顶边落在 96.59375，比导航底边 96 低 0.59px。
     首页导航是透明的（压在灰度 KV 图上），这 0.59px 会把 KV 图透出来：
     实测 y=95.06–95.94 是导航白色分隔线 rgb(250) → y=96.06–96.94 是漏出的 KV 图 rgb(135)
     → y=97.06 起才是面板浅灰顶边 rgb(217)，一条 1px 深灰线夹在两条浅线之间。
     实测对比（1536×900 index.html）：li 高 26.59375 → 面板顶 96.594（有缝）；
     a 改 block 后 li 高 26 → 面板顶 96.000（与导航底边严丝合缝，逐像素无深行）。
     只作用 ≥1280（<1280 时下拉在文档流内、无此缝，移动端几何保持原样）。 */
  .site-nav__menu > ul > li > a {
    display: block;
  }

  /* ⚠ 下滑态必须把过渡区减 8px，否则导航白底与面板之间露出 8px 页面内容（2026-09-20 实测）
     面板顶边 = li 底边(4rem = 64) + .site-nav__drop 的 padding-top，目标是落在「导航底边」上。
     但 index.html / contacts.html 的下滑态导航会矮 8px（.site-nav.is-scrolled height 6rem → 5.5rem），
     面板若仍按 2rem 补，顶边就落在 96，而导航白底只到 88 —— 中间 8px 露出页面内容
     （首页是灰度 KV 图，实测 navBottom 88 / panelTop 96，肉眼可见一条深色横带）。
     写成差值 calc 而非直接写 1.5rem：日后改导航高度会自动同步。 */
  .site-nav.is-scrolled .site-nav__drop {
    padding-top: calc(2rem - (6rem - 5.5rem)); /* = 1.5rem */
  }

  /* 子页导航下滑不缩高（pages/*.css 的 .page-sub .site-nav.is-scrolled 强制 height:6rem），
     上面那条 8px 补偿在子页不成立 → 还原成 2rem（本选择器 (0,4,0) 压过 (0,3,0)）。 */
  .page-sub .site-nav.is-scrolled .site-nav__drop {
    padding-top: 2rem;
  }

  .site-nav__actions {
    grid-column: 3;
    justify-self: end;
  }

  /* ---------- PC 搜索面板：放在搜索按钮【左侧】、与按钮【同一水平线】（2026-09-21 用户要求）----------
     base 是「`top:100%` + `right:0` + `margin-top:2.5rem`」= 面板挂在按钮**下方**、右缘对齐按钮右缘。
     用户要求改成「在搜索按钮左侧，与搜索按钮平行」→ 本段覆盖为左侧同高。
     ⚠ 只在 ≥1280 生效；<1280 的形态由文件末尾 `@media (max-width:1279px)` 段负责（移动端保持
       「按钮左上方」不变），两端互不干扰。
     ⚠ 垂直居中怎么做：面板是 `position:absolute`，其包含块 = `.site-nav__search`
       （`position:relative`，**盒高 = 按钮高 17px**，实测 btn 43.89–60.89）。
       → `top: 50%` + `translateY(-50%)` 即与按钮**中心对齐**（同一水平线）。
       实测校准（1920/1440/1280 三档一致）：面板 y=32.89–72.89（h=40），
       按钮中心 52.39 → 面板中心 52.89，偏差 0.5px（来自按钮父级 38.8 高的行盒基线，
       非计算错误；视觉上完全共线）。
     ⚠ `margin-top: 2.5rem` 必须归零 —— 那是「向下弹出时补到导航底边 y=96」的偏移量，
       留在左侧方案里会把面板整体下推 40px。
     ⚠ `right: calc(100% + .5rem)`：`100%` 相对包含块（= 按钮宽度 17px）解析，
       故面板右缘 = 按钮左缘 − 8px（与移动端同款 8px 间隙）。 */
  .site-nav__search-panel {
    top: 50%;
    right: calc(100% + .5rem);
    left: auto;
    transform: translateY(-50%);
    margin-top: 0;             /* ⚠ 归零：原 2.5rem 是「向下弹出」的偏移量 */
    /* 用户指定宽度 240px（原 360px） */
    width: 15rem;
  }

  /* `transform` 已用于垂直居中，下拉/弹出动画若有位移需避开 translateY 冲突 ——
     此处面板无入场位移（靠 display 切换），故安全。⚠ 后续若要加动画，用 opacity 而非 translate。 */

  .nav-open .site-nav__menu {
    display: flex;
    position: static;
    padding: 0;
    background: none;
  }
}

/* ---------- <1280：把搜索 + 语言切换放进汉堡菜单面板【底部】（2026-09-21）----------
   背景：`.site-nav__actions` 在 base 里是 `display: none`，只在 ≥1280 恢复 flex
   → 375–1279 全档位「搜索 + 语言切换」完全不存在（盒 0×0，命中 zero-size）。
   用户要求：移动端导航菜单里补上这两项，位置在**菜单项下方（CONTACTS 之下）**；
   **PC 端绝对不能动**。

   ⚠⚠ 为什么不能沿用「绝对定位 + top 偏移」：
   `.site-nav__actions` 与 `.site-nav__menu` 是**兄弟**（同属 `.site-nav__inner`），
   绝对定位的包含块是最近的**定位祖先** = `.site-nav`（`position:absolute; height:6rem`）。
   兄弟之间无法用纯 CSS 表达「跟随对方自适应的底边」——
   `ul` 高度会随下拉展开在 212 ↔ 279.78 ↔ 521+（多开一项再加）之间变化。
   实测过的失败写法：`top: 100%` 解析成 96px（导航自身高度，不是 ul 的 324），
   直接压在第一个菜单项上（48 项断言全红，见 2026-09-21 日志）。

   ✅ 采用的方案：`display: contents` + 纵向流式
   `.nav-open` 时让 `.site-nav__inner` 用 `display: contents` **丢掉自己的盒子**，
   它的四个子项（logo / toggle / menu / actions）就**直接成为 `.site-nav` 的流内容**；
   再把 `__menu` 从 `position:absolute` 改回 `static` → menu 与 actions 自然**顺序纵向排列**，
   actions 天然跟在菜单列表之后、**高度完全自适应**（无论展开几个下拉）。
   这正好复用了坑 33 记的 `display: contents` 手法。
   ⚠ `display: contents` 会让 `__inner` **丢盒**（rect 全 0）→
     它原有的 `margin: 1.75rem 1.5rem 0`、`border-bottom`、`height: 4.25rem` **全部失效**，
     必须把这几项**补到子项上**（见下：logo/toggle 补上边距，menu 承担黑底与左右内边距）。

   几何基线（`_dbg-bottom-plan.js` 实测，375/430/767/768/1024/1279 六档**数值完全一致**）：
   - 收起态：`__inner` y=28 h=68 margin=28px 24px 0 border-bottom 1px right=351(@375)
     `logo` x=34 y=32 140×26 margin-top 4px margin-left 10px ｜ `toggle` 44×44 右对齐
   - 展开态：`menu` x=0 y=96 铺满屏宽 bg=rgba(0,0,0,.92) padding 16/24/24/24
     `ul` y=112 h=279.78 bottom=391.78 ｜ `menu` bottom=415.78（**差 24 = padding-bottom**）
   → 收起态的「导航条」在展开后要整体交给黑面板，所以黑底与左右内边距从 `__inner` 迁到 `menu`。 */
@media (max-width: 1279px) {
  /* 1) 丢盒：四个子项直接成为 .site-nav 的流内容（⚠ 会丢掉 margin/border/height，见下方补偿） */
  .nav-open .site-nav__inner {
    display: contents;
  }

  /* 2) 面板回归文档流：不再绝对定位 → 天然排在 logo/toggle 之后、actions 之前。
        ⚠ 只覆盖 position/top/left/right，**padding 与背景色原样保留**
          （padding: 1rem 1.5rem 1.5rem 保持与收起态无关的既有设计值）。
        ⚠ 面板从「贴屏宽 0..375」变为「贴 __inner 原左右缘」。实测屏宽 375 时
          `__inner` 左缘 24 右缘 351 —— 与面板 padding 的 1.5rem(24) 一致，
          故左缘分毫不变、右缘少 24px 由 padding 余量吸收，菜单项文字起始 x **不变**（待实测确认）。 */
  .nav-open .site-nav__menu {
    display: block;
    position: static;
    /* 面板顶边压到 y=96（= 收起态 `.site-nav` 的盒底，导航分隔线所在）。
       ⚠ 实测校准（不要凭 `__inner` 的 28px margin 推算）：logo/toggle 改绝对定位后，
         `menu` 是流内第一个元素、顶边从 **y=0** 起算（不是 28 ——
         `__inner` 已丢盒，那 28px margin 随之消失，`.site-nav` 自身无 padding）。
         → 直接写 `6rem` = 96px，恰好等于导航高度，一步到位。
         ⚠ 别写成 `4.25rem`（= `__inner` 内容高）—— 那样面板顶只有 68，与导航底边差 28px。 */
    margin-top: 6rem;       /* 96px：面板顶边 = 收起态导航底边 */
    margin-left: 0;         /* 抵消 base 的 `margin-left: auto` */
    margin-right: 0;
    /* ⚠ 面板 padding-bottom 归零：原 1.5rem 是「面板独立成块」时的收尾留白，
       现在 actions 紧随其后，留白会与 actions 的 padding-top 叠加。
       ⚠ 但归零后 `ul` 末项（CONTACTS）会**紧贴** actions 顶边（实测间距 0，太挤）→
         间距改由 actions 的 padding-top 提供（见下，1.75rem）。 */
    padding-bottom: 0;
    background: rgba(0, 0, 0, .92); /* 黑底由面板自持（不再依赖 __inner 的高度） */
    color: #fff;                    /* 面板恒为黑底白字，不随导航变白 */
  }

  /* 3) 补偿：__inner 丢盒后 logo / toggle 变成块级流内容、会**纵向堆叠**（实测 y 分别
        25.59 / 149.59、x 都是 0）→ 必须让它们既不堆叠、又**完全不占据流内高度**，
        否则面板顶边会被它们顶偏（实测浮动方案下面板顶从 96 落到 70）。
        手法：**改回绝对定位**，把它们钉在收起态的原位（logo 34,32 ／ toggle 右缘 24, y=26）。
        ⚠ 它们本来就是不用参与排版的装饰/按钮，绝对定位最干净 ——
          流内只剩 menu + actions，面板顶边就是 `.site-nav` 的自然起点。
        ⚠ 绝对定位的包含块 = `.site-nav`（`position:absolute`），坐标即视口/页面坐标，
          故直接用收起态实测值。 */
  .nav-open .site-nav__logo {
    position: absolute;
    top: 2rem;              /* y=32 */
    left: 2.125rem;         /* x=34（1.5rem 容器内边距 + .625rem 自身 margin） */
    margin: 0;
  }

  .nav-open .site-nav__toggle {
    position: absolute;
    top: 1.625rem;          /* y=26 */
    right: 1.5rem;          /* 右缘 24 */
    margin: 0;
  }

  /* 4) 动作区：在流内跟在菜单列表之后，天然位于 CONTACTS 之下。
        ⚠⚠ 黑底必须自己带 —— `menu` 是独立的兄弟盒，它的背景**止于自己的 padding-box**
          （实测 menu 底 347.78，actions 在 347.78 之后 → 落在面板背景之外，
          实测视觉上「搜索 + RU」压在页面内容上、几乎不可见）。
          不能靠给 menu 加 padding-bottom 解决（actions 不在 menu 盒内）。 */
  .nav-open .site-nav__actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;      /* 右对齐（2026-09-21 用户要求）：语言贴右缘、搜索在其左侧 */
    position: static;
    margin: 0;
    gap: 2rem;
    /* ⚠ padding-top 6.5rem(104px)：**实测校准值**，不是「原值 + 80」的简单相加。
       校准过程（2026-09-21，products.html 逐档实测）：
         · 改前（padding-top 1.75rem=28）：末项底 323.78 → 搜索按钮顶 353.78 = 间距 **29.89**
           （28 padding + 1.89 来自行内 align-items:center 的垂直居中偏移）
         · 目标：间距 +80 → **109.89**
         · 故 padding-top 需 = 28 + 80 + 校准差 = 108 时实测得 113.89（多 4）
           → 取 **104px（6.5rem）** 使间距精确落在 109.89。
       ⚠ 别改成 1.75rem + 80px 的直算式 —— align-items:center 会额外引入约 2px 偏移。 */
    padding: 6.5rem 1.5rem .875rem;
    background: rgba(0, 0, 0, .92); /* 与菜单面板同色，视觉上连成一块 */
    /* ⚠ 不需要 border-top：面板与 actions 同色拼接（实测 gap=0 / sameBg=true），
       画线反而多一道痕。 */
    /* ⚠⚠ 必须显式写 color —— base 的 `color: inherit` 从 `.site-nav` 继承：
       首页/contacts 未下滑时导航是白字（碰巧正确），但**全部子页面 + 任何下滑态**
       导航是「白底黑字」→ 黑字压 rgba(0,0,0,.92) 黑面板 = **完全不可读**
       （实测 8 组组合里 6 组为 rgb(0,0,0)）。不要删、不要改成 inherit。 */
    color: #fff;
  }

  /* 5) 搜索面板：**与搜索按钮同水平线（平行）+ 按钮左侧**（2026-09-21 用户要求）。
       ⚠ 本节经历两版：
         v1（上一轮）：`bottom: 100%` = 面板在按钮**上方**。用户要的是「平行」→ 本次改掉。
         v2（当前）：`top: 50%` + `translateY(-50%)` = 与按钮**中心对齐**，真正同水平线。

       几何推导（决定宽度为什么这么写）：
         移动端 `actions` 行内容 = [搜索面板(绝对定位,不占位)] …… [搜索按钮 17px] gap 32 [语言 47.53px]
         行右内边距 = 1.5rem(24)。故「按钮左缘」距屏幕左缘 = `100vw − 24 − 47.53 − 32 − 17`
         = **`100vw − 120.53`**（≈ `100vw − 7.533rem`）。
         面板要放在按钮左侧、右缘距按钮 8px → 可用宽度 = `100vw − 120.53 − 8` = `100vw − 128.53`
         再留 24px 安全左边距 → 上限 ≈ `100vw − 152.53` ≈ `100vw − 9.533rem`。

       ⚠⚠ 为什么不写死 240px：屏宽 375 时按钮左缘距左 = 254.47，
          `240 + 8 = 248` 只剩 6.47px 左边距 —— 会**几乎贴屏边**（视觉失衡）。
          故宽度写 `min(240px, 可用空间)`：宽屏正好 240，窄屏自动收窄，任何档位都
          **既平行、又不溢出、又保左右留白均衡**。这正是用户说的「不能平行就缩短一点」。

       ⚠ `top: 50%` 的 `50%` 相对**包含块** = `.site-nav__search`（高 = 按钮高 17px）
          → 面板中心 = 按钮中心 ✅（PC 段同款手法，实测偏差 0）。
       ⚠ `margin-bottom` 必须去掉（v1 的 8px 上间距在平行方案下无意义，会破坏垂直居中）。
       ⚠ `transform` 已占用，且面板靠 `display` 切换无入场位移 → 安全。
          ⚠⚠ 不要给面板加 `translate` 位移动画，会与这里的 `translateY(-50%)` 冲突。
       ⚠ 宽度仍不能用 `calc(100% - …)`：面板是 `position:absolute`，`100%` 相对包含块
          （= 按钮宽 17px）→ 会算出 21px。必须用**视口单位**（见上推导）。 */
  .nav-open .site-nav__search-panel {
    top: 50%;                   /* 与按钮中心对齐 → 「平行」 */
    bottom: auto;
    right: calc(100% + .5rem);  /* 面板右缘 = 搜索按钮左缘 − 8px（在按钮左侧） */
    left: auto;
    transform: translateY(-50%);
    margin-top: 0;
    margin-bottom: 0;           /* ⚠ 归零（v1 的 8px 上间距会破坏垂直居中） */
    margin-right: 0;            /* ⚠ 归零：间隙已由 right 的 `calc(100% + .5rem)` 提供，
                                    两处都留会变成 16px（实测踩过） */
    /* 宽度：宽屏封顶 240px，窄屏自动收窄以保左右留白（推导见上方注释）。 */
    width: min(15rem, calc(100vw - 9.533rem));
    /* 下限兜底：极窄屏（<340）防止塌成细条，宁可略溢出也不可不可用 */
    min-width: 9rem;
    max-width: 15rem;           /* 240px 封顶 */
  }
}

/* ---------- 面包屑 Home 图标的可点区（2026-09-20）----------
   图标本体只有 14×13（HTML 里写死 `<svg width="14" height="13">`），低于 WCAG 2.5.8 的
   24×24 下限。用**绝对定位伪元素**把命中区撑到 30×29：伪元素不参与布局、也不画任何东西
   → 面包屑的几何 / 行高 / 间距 / 视觉全部零变化。
   ⚠ 不要为了凑 44×44 把 inset 放到 -11px 以上：相邻面包屑项间距只有 10px（`ol` 的 gap），
     命中区会盖住下一个链接，反而制造「想点 Home 却点到 PRODUCTS」的真冲突。
   ⚠ 7 个页面的面包屑根类名各不相同（products / products-sub / products-detail / solutions /
     solutions-detail / news / news-detail），用 :is() 列全、集中一处维护，
     避免同一条规则在 7 个页面 CSS 里各写一份。
   验收：.workbuddy-ai/tmp/_verify-crumbs-home.js（与改动前基线逐值比对 + 命中区 ≥24×24）。 */
:is(.plist-crumbs, .pmod-crumbs, .pmd-crumbs, .psol-crumbs, .psold-crumbs, .pn-crumbs, .pnd-crumbs) a[aria-label="Home"] {
  position: relative;
}

:is(.plist-crumbs, .pmod-crumbs, .pmd-crumbs, .psol-crumbs, .psold-crumbs, .pn-crumbs, .pnd-crumbs) a[aria-label="Home"]::after {
  content: "";
  position: absolute;
  inset: -8px;
}

/* ---------- 面包屑容器不得裁剪（2026-09-20）----------
   ⚠ 为什么必须显式声明：layout.css 的 `.section { overflow: hidden }` 会落到 5 个页面的
     面包屑根节点上（products-detail / solutions 的 `*-head`，solutions-detail / news /
     news-detail 的 `*-crumbs`），而这些根节点的盒**紧贴面包屑**——news 在 375 下根盒只有
     19px 高、左缘就等于面包屑左缘（24px）。于是上一节给 Home 图标加的 ::after 命中区被裁：
       news 22×19 / news-detail 22×24 / solutions-detail 22×24 → 宽度不达 24（WCAG 2.5.8）；
       solutions 30×24（勉强）/ products-detail 30×29（根盒够大，本就合格）。
     定性依据：越界点 elementFromPoint 返回 main / div.page（落回祖先）= 裁剪，不是被兄弟盖住。
   ⚠ 这些容器**只装一个 <nav aria-label="Breadcrumb">**（不含 hero、不含装饰元素），
     已逐页核对，故 overflow: visible 不会让任何东西溢出。
   ⚠ 特异性必须 ≥ (0,2,0)：`:is()` 只取最具体参数的特异性 (0,1,0)，与 `.section` 打平后
     靠加载顺序取胜太脆弱（虽然 components.css 确实排在 layout.css 之后），故前置 `.section`
     把特异性抬到 (0,2,0)。products / products-sub 的根是 `<nav>`（本就 visible），
     一并列出只为集中声明、防日后回归。
   验收：.workbuddy-ai/tmp/_verify-crumbs-home.js check（7 页 × 5 档，命中区须 ≥24×24） */
:is(.plist-crumbs, .pmod-crumbs),
.section:is(.pmd-head, .psol-head, .psold-crumbs, .pn-crumbs, .pnd-crumbs) {
  overflow: visible;
}

/* ---------- 页脚（1920×412，主色红） ---------- */
.site-foot {
  background: var(--color-primary);
  color: #fff;
}

.site-foot__inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
  padding: var(--space-12) var(--space-6) var(--space-10);
}

.site-foot__brand img {
  width: 10.875rem;  /* 174 */
  height: 1.8125rem; /* 29 */
  object-fit: contain;
}

.site-foot__contacts {
  display: flex;
  flex-direction: column;
  gap: .6875rem; /* 11 */
  margin-top: var(--space-8);
}

.site-foot__contacts li {
  display: flex;
  align-items: center;
  gap: .8125rem;
  font-size: var(--font-size-body);
  line-height: 1.3125rem;
}

.site-foot__contacts svg {
  flex: none;
  color: #fff;
}

.site-foot__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 17.5625rem;  /* 281 */
  height: 3.0625rem;  /* 49 */
  margin-top: var(--space-6);
  border-radius: var(--radius-sm);
  background: #000;
  font-size: var(--font-size-body-sm);
  transition: opacity .2s ease-out;
}

.site-foot__cta:hover {
  opacity: .85;
}

.site-foot__cols {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-10) var(--space-8);
}

.site-foot__col h3 {
  font-size: var(--font-size-body-lg);
  font-weight: var(--font-weight-semibold);
  line-height: 1.8125rem; /* 29 */
}

.site-foot__col ul {
  margin-top: .8125rem;
}

.site-foot__col a {
  display: inline-block;
  font-size: var(--font-size-body);
  line-height: 1.875rem; /* 30 */
}

.site-foot__col a:hover {
  text-decoration: underline;
}

/* h3 内的链接必须跟随标题字号。
   ⚠ 不能省：上面的 .site-foot__col a 把字号压到 body(16px)，而 h3 是 body-lg(18px)——
   不继承的话 NEWS / COMPANY / CONTACTS 会比同级标题小一号（实测墨迹高 13px vs 16px）。 */
.site-foot__col h3 a {
  font-size: inherit;
  line-height: inherit;
}

/* 同级标题之间的间距（2026-09-18 新稿：NEWS / COMPANY / CONTACTS 三行）
   原 2.6875rem(43) 是按「COMPANY 与 CONTACTS 两行」定的；新稿实测行距为 49px，
   即 29(行高) + 20(margin)，故收窄到 1.25rem。 */
.site-foot__col h3 + h3 {
  margin-top: 1.25rem;
}

.site-foot__copyright {
  max-width: 39.9375rem; /* 639 */
  font-size: var(--font-size-caption);
  line-height: 1.4;
}

/* ---------- 页脚 · 仅移动端（<768）：NEWS / COMPANY / CONTACTS 排成一行 ----------
   2026-09-20 用户要求（「仅移动端调整，PC 端绝对不能动」）。

   ⚠ 为什么必须跨满两列：三个标题的**墨迹宽**合计 265.05px（20px/600 Jost，实测
     NEWS 60.33 / COMPANY 100.61 / CONTACTS 104.11），而 .site-foot__cols 在移动端是
     repeat(2, 1fr) 网格 —— 375 视口下单列只有 147.5px，塞进单列必溢出。
   跨列后版权行被挤到下一行（原本与第 3 列并排），故一并让它跨满，
   免得留下 147.5px 的窄列把版权文字压成 7 行。
   ⚠ flex-wrap 是必需的兜底：≤344 视口（如 320）两列合计仅 272px < 297px，
     不 wrap 会横向溢出；wrap 后 CONTACTS 优雅换行，不产生横向滚动。
   ⚠ 本段必须限定 max-width: 767px —— 768–1279 属平板，按项目约定（AGENTS.md）不动。 */
@media (max-width: 767px) {
  .site-foot__cols > section:nth-of-type(3) {
    grid-column: 1 / -1;    /* 跨满两列，才有 327px（375 视口）可用 */
    display: flex;
    flex-wrap: wrap;        /* 极窄视口兜底，见上 */
    align-items: baseline;  /* 三个标题同字号，基线对齐 = 同一水平线 */
    gap: var(--space-5);    /* 20px；375 视口 265.05 + 40 = 305.05 ≤ 327 ✅ */
  }

  /* 排成一行后，纵向的 1.25rem 间距必须归零 ——
     在 flex 行内它不会「消失」，只会把后两项往下压。 */
  .site-foot__cols > section:nth-of-type(3) h3 + h3 {
    margin-top: 0;
  }

  /* 版权行随第 3 列一起跨满（原因见上） */
  .site-foot__copyright {
    grid-column: 1 / -1;
  }
}

@media (min-width: 1280px) {
  .site-foot {
    height: 25.75rem;
  }

  .site-foot__inner {
    flex-direction: row;
    justify-content: space-between;
    padding: 5.3125rem 8.125rem 0 7.0625rem; /* 右内边距 139→130，使栏目区左缘落到 x=1151（新稿） */
  }

  .site-foot__brand {
    flex: none;
  }

  .site-foot__contacts {
    margin-top: 2.0625rem; /* y=147 */
  }

  .site-foot__cta {
    margin-top: var(--space-5);
  }

  .site-foot__cols {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 0;
    /* 2026-09-18 新稿：三列（原四列）。宽度取版权行的 max-width(639)，
       使区块左缘 = 1920 − 130(右内边距) − 639 = 1151，与设计稿一致。
       原值 47.75rem(764) = 163+80+134+90+112+80+105（四列）。 */
    width: 39.9375rem; /* 639 */
    margin-top: 1.6875rem; /* 栏目 y=112 */
  }

  .site-foot__col a {
    white-space: nowrap; /* 设计稿链接均为单行 */
  }

  .site-foot__cols > section:nth-of-type(1) {
    width: 10.1875rem; /* 163 */
  }

  .site-foot__cols > section:nth-of-type(2) {
    width: 8.375rem;    /* 134 */
    margin-left: 6.25rem;  /* 100 → x=1414 */
  }

  /* 第 3 列现在是 NEWS + COMPANY + CONTACTS（原第 4 列已并入）。
     ⚠ 原 nth-of-type(4) 规则（width 105 / margin-left 5rem）已随第 4 列一并删除，
     否则会命中版权行 <p> 之后的兄弟节点造成意外间距。 */
  .site-foot__cols > section:nth-of-type(3) {
    width: 7rem;        /* 112 */
    margin-left: 6.25rem;  /* 100 → x=1648 */
  }

  .site-foot__copyright {
    flex-basis: 100%;
    margin-top: 2.875rem; /* y=318 */
  }
}
