/* 基础重置 + 全站公用的排版件。页面专属样式一律去 page-*.css。 */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; overflow-x: clip; }

body {
  margin: 0;
  overflow-x: clip;
  color: var(--ink);
  background: var(--bg-white);
  font-size: 16px;
  line-height: 1.75;
  font-family: "PingFang SC", "Source Han Sans SC", "Noto Sans SC", "Hiragino Sans GB",
               system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  /* 移动浏览器地址栏展开时可见高度小于 100vh，会把页脚顶出屏外；dvh 跟随实际视口，不支持时退回上一行 */
  min-height: 100dvh;
}

/* 短页面（如正文很短的新闻内页）页脚必须压到视口底部，不能在页脚下方露白底。
   skip-link 是 absolute，不参与这里的主轴排布 */
body > main { flex: 1 0 auto; }
body > .site-footer { flex-shrink: 0; }

/* 内容层跟 --s 等比缩放。dock 贴视口，永不缩。
   PC 页头不跟 --s：≥950 用成稿 82/42/18/64/40，<950 走独立 --hs。移动页头仍跟 --s。见 docs/14。 */
body > .site-header,
body > main,
body > .site-footer { zoom: var(--s); }

html:not([data-layout="mobile"]) body > .site-header { zoom: 1; }

/* zoom 前先按稿宽排：移动 375、PC 至少 1920。≥1920 用 100% 让满铺 hero 继续变宽。 */
html[data-layout="mobile"] body > .site-header,
html[data-layout="mobile"] body > main,
html[data-layout="mobile"] body > .site-footer {
  width: 375px;
  margin-inline: auto;
}

html:not([data-layout="mobile"]) body > main,
html:not([data-layout="mobile"]) body > .site-footer {
  width: max(1920px, 100%);
  margin-inline: auto;
}

body > main,
body > .site-footer { --hairline: calc(1px / var(--s)); }
html[data-layout="mobile"] body > .site-header { --hairline: calc(1px / var(--s)); }

html:not([data-layout="mobile"]) [data-layout-only="mobile"],
html[data-layout="mobile"] [data-layout-only="pc"] { display: none; }

/* 真机滚动条覆盖在内容上、不占宽。Windows / DevTools 经典条会吃掉约 15px，
   再叠 zoom 就会在 390 及以下撑出横向滚动条。移动布局改成不占宽、不露条；
   纵向仍可滚，只是没有拖槽。 */
html[data-layout="mobile"],
html[data-layout="mobile"] body {
  scrollbar-width: none;
}
html[data-layout="mobile"]::-webkit-scrollbar,
html[data-layout="mobile"] body::-webkit-scrollbar {
  width: 0;
  height: 0;
  display: none;
}

img { max-width: 100%; display: block; border: 0; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4 { margin: 0; font-weight: 700; }
p { margin: 0; }
button, input, textarea { font: inherit; color: inherit; }

/* 键盘可达性：设计稿没画焦点态，但不能因此把它去掉 */
:focus-visible {
  outline: calc(2 * var(--hairline)) solid var(--brand);
  outline-offset: calc(2 * var(--hairline));
}

/* T-40：跳过链接 —— 默认裁切屏外（不用 translate：WebKit 可能把移出视口的焦点目标踢出 Tab 序） */
.skip-link {
  position: absolute;
  left: 16px;
  top: 12px;
  z-index: 1000;
  padding: 10px 16px;
  border-radius: 4px;
  background: var(--brand);
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.skip-link:focus,
.skip-link:focus-visible {
  width: auto;
  height: auto;
  margin: 0;
  padding: 10px 16px;
  clip: auto;
  overflow: visible;
  white-space: normal;
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* ---------------------------------------------------------------- 版心 */

.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.container--mid { max-width: var(--container-mid); }
.container--wide { max-width: var(--container-wide); }

/* ---------------------------------------------------------------- 区块标题
   设计稿里所有居中大标题都是这一套：蓝色标题 + 下方蓝/绿两段短线。
   实测（首页「合作案例」，design/pc/首页.jpg）：
     标题字高 35px  → font-size 34px
     线：蓝 60px + 间隙 4px + 绿 33px，粗 5px，距标题 28px
   注意：同一组件在首页「主营业务」处，设计稿把它整体左偏了约 60px（中心 900 而非 960），
   其余区块（合作案例 961、关于我们公司简介 958）都是居中的。
   判断为稿件失误，实现按居中处理，留证见 docs/09-设计稿存疑.md Q2。 */

/* Q22 已决：成稿 ink 互证 F≈36；连带 padding-top 72→77、rule margin-top 28→22 钉住下划线 */
.section-title {
  text-align: center;
  padding-top: 77px;
}

.section-title__text {
  font-size: var(--section-title-size);
  line-height: 1.3;
  color: var(--brand);
}

.section-title__rule {
  display: flex;
  justify-content: center;
  gap: 4px;
  margin-top: 22px;
}

.section-title__rule::before,
.section-title__rule::after {
  content: "";
  height: 5px;
}
.section-title__rule::before { width: 60px; background: var(--brand); }
.section-title__rule::after  { width: 33px; background: var(--accent); }

/* ---------------------------------------------------------------- 按钮 */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 48px;
  padding: 0 32px;
  border: 0;
  border-radius: 999px;
  background: var(--brand);
  color: #fff;
  cursor: pointer;
  transition: background .2s;
}
.btn:hover { background: var(--brand-dark); }

.btn--ghost {
  background: transparent;
  border: var(--hairline) solid var(--brand);
  color: var(--brand);
}
.btn--ghost:hover { background: var(--brand); color: #fff; }

.btn--square { border-radius: var(--radius); }

/* ---------------------------------------------------------------- 跨页切换
 *
 * 站点是 MPA：点导航就是整页重载。旧页面一被丢弃，新页面的首帧往往还没解出
 * banner（uploads 里的海报是 1.5MB 级 PNG），那一帧露的是 hero 容器底色，
 * 页头也跟着从零重画一遍 —— 观感就是「海报和 logo 闪一下」。
 * 点当前栏目自己时同样成立：URL 没变，浏览器照样丢页面重来。
 *
 * 跨文档 View Transition 让浏览器先把新页面渲染就绪、再用旧页面的快照接住这一帧：
 *   - 页头在 layout.css 里单独取名，跨页原地保持，logo 全程不动；
 *   - 其余内容（含 banner）交叉淡入，不再出现底色中间态。
 * 真正消灭闪烁的是「等就绪再切」，动画只是让切换不生硬。
 * 不支持的浏览器整段忽略，行为与改动前一致。
 */
@view-transition { navigation: auto; }

/* 默认 .25s 整页淡入偏长，会让人觉得慢半拍；.2s 足够盖住解码窗口。 */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: .2s;
  animation-timing-function: ease;
}

@media (prefers-reduced-motion: reduce) {
  /* 不能整段关掉：关掉就退回白闪。压到一帧内完成 ——
     「等新页面就绪」的保证仍在，只是不再有可见的淡入。 */
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation-duration: 1ms; }
}

/* ---------------------------------------------------------------- 滚动入场动效
 *
 * 参考站的核心观感是“区块进入视口后分层出现”，不是改变页面几何。
 * 这里用独立 translate 属性，不覆盖页面中用于像素对齐的 transform。
 * 只有 JS 已成功启用 IntersectionObserver 时才隐藏待入场内容；
 * 禁用 JS / 旧浏览器 / 减少动画模式下始终直接展示，避免白屏。
 * 隐藏本身不得带 transition：否则首屏已绘制的内容会先淡出成白屏。 */
@media (prefers-reduced-motion: no-preference) {
  html.motion-ready [data-reveal],
  html.motion-ready [data-reveal-group] > * {
    opacity: 0;
    translate: 0 30px;
  }

  html.motion-ready [data-reveal="left"] { translate: -36px 0; }
  html.motion-ready [data-reveal="right"] { translate: 36px 0; }

  html.motion-ready [data-reveal].is-revealed,
  html.motion-ready [data-reveal-group].is-revealed > * {
    opacity: 1;
    translate: none;
    transition:
      opacity .72s cubic-bezier(.22, 1, .36, 1),
      translate .72s cubic-bezier(.22, 1, .36, 1);
  }

  /* 滑出视口再播：只给 opt-in 节点加离场过渡。首屏隐藏规则仍无 transition，避免白闪。 */
  html.motion-ready [data-reveal-replay]:not(.is-revealed) {
    transition:
      opacity .55s cubic-bezier(.22, 1, .36, 1),
      translate .55s cubic-bezier(.22, 1, .36, 1);
  }

  html.motion-ready [data-reveal-group] > :nth-child(2) { transition-delay: 70ms; }
  html.motion-ready [data-reveal-group] > :nth-child(3) { transition-delay: 140ms; }
  html.motion-ready [data-reveal-group] > :nth-child(4) { transition-delay: 210ms; }
  html.motion-ready [data-reveal-group] > :nth-child(5) { transition-delay: 280ms; }
  html.motion-ready [data-reveal-group] > :nth-child(6) { transition-delay: 350ms; }
  html.motion-ready [data-reveal-group] > :nth-child(7) { transition-delay: 420ms; }
  html.motion-ready [data-reveal-group] > :nth-child(8) { transition-delay: 490ms; }
  html.motion-ready [data-reveal-group] > :nth-child(9) { transition-delay: 560ms; }
  html.motion-ready [data-reveal-group] > :nth-child(10) { transition-delay: 630ms; }

  /* 走马灯复制列不参与入场错峰，否则滑入视口时会是透明的。 */
  html.motion-ready [data-reveal-group] > .is-marquee-clone {
    opacity: 1;
    translate: none;
    transition: none;
  }

  /* 折线以下：内容必须一直可见，只做 12px 上移归位，禁止 opacity 0 / 左右滑入。 */
  html.motion-ready [data-reveal-soft]:not(.is-revealed) {
    translate: 0 12px;
  }

  html.motion-ready [data-reveal-soft].is-revealed {
    translate: none;
    transition: translate .55s cubic-bezier(.22, 1, .36, 1);
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal],
  [data-reveal-group] > *,
  [data-reveal-soft] {
    opacity: 1;
    translate: none;
    transition: none;
  }

  .marquee-track.is-marquee {
    animation: none;
    transform: none;
  }
}

/* 合作案例 / 荣誉资质双行网格走马灯。列宽仍由各页 grid 决定。 */
@keyframes concare-marquee {
  to { transform: translate3d(calc(-1 * var(--marquee-cycle, 0px)), 0, 0); }
}

.marquee-viewport.is-marquee {
  overflow: hidden;
  scroll-snap-type: none;
  scroll-behavior: auto;
}

.marquee-track.is-marquee {
  min-width: 0;
  animation: concare-marquee var(--marquee-duration, 30s) linear infinite;
  will-change: transform;
}

.is-marquee-paused .marquee-track.is-marquee {
  animation-play-state: paused;
}

/* ---------------------------------------------------------------- 屏读专用 */

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

html[data-layout="mobile"] {
  /* 移动稿实测标题 ink 高约 21 ⇒ 曾用 24px。第六轮改为 375 稿 20 / 1920 稿 36，
     字号走 --section-title-size，中间宽靠 --s。线距仍按实测 3。
     padding-top 22 由「上一段底缘 → 标题 ink 顶」反推。
     例外两处各自在页样式里覆盖：服务范围 6、订单查询 0（外层 banner 已给 26）。 */
  .section-title { padding-top: 22px; }
  .section-title__text { font-size: var(--section-title-size); }
  .section-title__rule { gap: 3px; margin-top: 3px; }

  .section-title__rule::before,
  .section-title__rule::after { height: 3px; }
  .section-title__rule::before { width: 37px; }
  .section-title__rule::after  { width: 20px; }
}
