/* ============================================================
   ClipVault 官网样式
   排版基底对齐 Cerulean 设计稿（ui-demo/010）：
   JetBrains Mono 等宽标题 + Newsreader 衬线正文 + 字重 500 + 设计稿面层色。
   ============================================================ */

/* ============================================================
   加载闪屏（Splash Screen）
   品牌 Logo 描边 → 文字淡入 → 进度条 → 幕布上滑揭开
   ============================================================ */
.splash {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  /* 基底渐变移到 .splash-bg:logo 接力时幕布可独立淡出而 logo 保持不透明 */
  overflow: hidden;
  transition: transform 800ms cubic-bezier(0.76, 0, 0.24, 1), opacity 600ms ease;
}

.splash.is-leaving {
  transform: translateY(-100%);
  opacity: 0;
}

.splash.is-gone {
  display: none;
}

.splash-bg {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(50% 50% at 50% 40%, rgba(79, 185, 216, 0.15), transparent 70%),
    radial-gradient(60% 50% at 30% 70%, rgba(23, 117, 173, 0.1), transparent 70%),
    linear-gradient(168deg, #0b2133 0%, #0f2e47 52%, #123c5c 100%);
}

.splash-content {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.splash-logo {
  width: 80px;
  height: 80px;
  border-radius: 22px;
  display: grid;
  place-items: center;
  /* 与真实应用 logo 一致的蓝色径向渐变 squircle */
  background: radial-gradient(72% 72% at 50% 42%, #1f86c1, #004872);
  border: 1px solid rgba(79, 185, 216, 0.35);
  box-shadow: 0 20px 60px -10px rgba(23, 117, 173, 0.45);
}

.splash-icon {
  width: 50px;
  height: 50px;
}

/* 真实 logo 白色字标：先描边「书写」，再填充实心 */
.splash-icon .splash-mono {
  stroke: #ffffff;
  stroke-width: 9;
  stroke-linejoin: round;
  fill: #ffffff;
  stroke-dasharray: 1950;
  stroke-dashoffset: 1950;
  fill-opacity: 0;
}

.splash-name {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: #fff;
  opacity: 0;
}

.splash-tagline {
  font-family: system-ui, sans-serif;
  font-size: 14px;
  color: rgba(201, 222, 236, 0.7);
  opacity: 0;
}

.splash-bar {
  width: 120px;
  height: 3px;
  border-radius: 2px;
  background: rgba(79, 185, 216, 0.2);
  margin-top: 8px;
  overflow: hidden;
  opacity: 0;
}

.splash-bar-fill {
  width: 0;
  height: 100%;
  border-radius: 2px;
  background: linear-gradient(90deg, #4fb9d8, #1775ad);
}

/* 闪屏粒子 */
.splash-particles {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.splash-particles span {
  position: absolute;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: rgba(79, 185, 216, 0.6);
  opacity: 0;
}

.splash-particles span:nth-child(1) { left: 20%; top: 30%; }
.splash-particles span:nth-child(2) { left: 75%; top: 25%; }
.splash-particles span:nth-child(3) { left: 15%; top: 70%; }
.splash-particles span:nth-child(4) { left: 80%; top: 65%; }
.splash-particles span:nth-child(5) { left: 45%; top: 15%; }
.splash-particles span:nth-child(6) { left: 60%; top: 80%; }

@media (prefers-reduced-motion: no-preference) {
  .splash-icon .splash-mono {
    animation:
      cv-splash-draw 1.1s cubic-bezier(0.65, 0, 0.35, 1) 0.15s forwards,
      cv-mono-fill 0.5s ease 0.95s forwards;
  }
  .splash-name {
    animation: cv-splash-fade 0.6s ease 0.8s forwards;
  }
  .splash-tagline {
    animation: cv-splash-fade 0.6s ease 1.1s forwards;
  }
  .splash-bar {
    animation: cv-splash-fade 0.4s ease 1.3s forwards;
  }
  .splash-bar-fill {
    animation: cv-splash-progress 1s cubic-bezier(0.4, 0, 0.2, 1) 1.4s forwards;
  }
  .splash-logo {
    animation: cv-splash-logo-pulse 2.4s ease-in-out infinite;
  }
  .splash-particles span {
    animation: cv-splash-particle 2.4s ease-in-out infinite;
  }
  .splash-particles span:nth-child(1) { animation-delay: 0s; }
  .splash-particles span:nth-child(2) { animation-delay: 0.4s; }
  .splash-particles span:nth-child(3) { animation-delay: 0.8s; }
  .splash-particles span:nth-child(4) { animation-delay: 1.2s; }
  .splash-particles span:nth-child(5) { animation-delay: 0.2s; }
  .splash-particles span:nth-child(6) { animation-delay: 0.6s; }
}

@media (prefers-reduced-motion: reduce) {
  .splash-icon .splash-mono {
    stroke-dashoffset: 0;
    fill-opacity: 1;
  }
  .splash-name,
  .splash-tagline,
  .splash-bar {
    opacity: 1;
  }
  .splash-bar-fill {
    width: 100%;
  }
  .splash.is-leaving {
    transform: none;
    opacity: 0;
    transition: opacity 100ms ease;
  }
}

@keyframes cv-splash-draw {
  to { stroke-dashoffset: 0; }
}

@keyframes cv-mono-fill {
  to { fill-opacity: 1; }
}

@keyframes cv-splash-fade {
  to { opacity: 1; }
}

@keyframes cv-splash-progress {
  to { width: 100%; }
}

@keyframes cv-splash-logo-pulse {
  0%, 100% { box-shadow: 0 20px 60px -10px rgba(79, 185, 216, 0.3); }
  50% { box-shadow: 0 20px 80px -5px rgba(79, 185, 216, 0.5), 0 0 40px -10px rgba(79, 185, 216, 0.3); }
}

@keyframes cv-splash-particle {
  0% { opacity: 0; transform: translateY(0) scale(0.5); }
  30% { opacity: 0.8; transform: translateY(-10px) scale(1); }
  70% { opacity: 0.4; transform: translateY(-20px) scale(0.8); }
  100% { opacity: 0; transform: translateY(-30px) scale(0.3); }
}

/* ============================================================
   logo 接力（FLIP）：闪屏结束时中央 logo 飞向顶栏品牌标，
   幕布 / 文字 / 粒子同步淡出；落位瞬间与顶栏真 logo 交叉淡换。
   由 site.js 测量起终点矩形并设置 left/top/transform。
   ============================================================ */
.splash.is-handoff {
  pointer-events: none;
}

/* 除 logo 外全部淡出（用新动画覆盖各自的入场动画，从当前可见态渐隐） */
.splash.is-handoff .splash-bg,
.splash.is-handoff .splash-name,
.splash.is-handoff .splash-tagline,
.splash.is-handoff .splash-bar,
.splash.is-handoff .splash-particles {
  animation: cv-splash-fadeout 0.5s ease forwards;
}

@keyframes cv-splash-fadeout {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* 飞行中的 logo：脱离闪屏 flex 布局固定在起点（left/top 由 JS 写入），
   transform 位移 + 缩放到首屏中央品牌位（80px→60px 的就近轻落，
   带轻微过冲回弹的落定手感；圆角随 scale 自然过渡） */
.splash-logo.is-flying {
  position: fixed;
  margin: 0;
  z-index: 10000;
  animation: none;
  will-change: transform;
  transition:
    transform 0.6s cubic-bezier(0.34, 1.18, 0.4, 1),
    opacity 0.18s ease;
}

/* 落位：快速淡出，露出其正下方的首屏品牌位真 logo（交叉淡换掩掉渐变差异） */
.splash-logo.is-landed {
  opacity: 0;
}

/* 接力期间首屏品牌位隐身，落位瞬间接管（限 has-js，JS 失效不误伤；
   回访 skip 路径没有 cv-splashing，品牌位直接可见） */
html.has-js.cv-splashing .stage-logo {
  opacity: 0;
}

.stage-logo {
  transition: opacity 0.18s ease;
}

/* 同一会话已播过（sessionStorage 标记 → 头部内联脚本加类）：闪屏整个不渲染 */
html.cv-skip-splash .splash {
  display: none;
}

/* ============================================================
   全屏动画开场 Stage（一镜到底的起始画面）
   闪屏退出后 → Stage 全屏展示 → 滚动驱动淡出过渡到 Hero
   ============================================================ */
.stage {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background: linear-gradient(168deg, #0b2133 0%, #0f2e47 52%, #0d2a42 100%);
  --scroll-progress: 0;
}

.stage-depth {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.stage-layer {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 80ms ease-out;
  will-change: transform;
}

/* 背景层：光球 */
.stage-orb {
  position: absolute;
  border-radius: 50%;
  filter: blur(60px);
}

.stage-orb--1 {
  width: 400px;
  height: 400px;
  top: 10%;
  left: 15%;
  background: radial-gradient(circle, rgba(79, 185, 216, 0.25), transparent 70%);
}

.stage-orb--2 {
  width: 300px;
  height: 300px;
  bottom: 15%;
  right: 10%;
  background: radial-gradient(circle, rgba(23, 117, 173, 0.3), transparent 70%);
}

.stage-orb--3 {
  width: 200px;
  height: 200px;
  top: 50%;
  right: 30%;
  background: radial-gradient(circle, rgba(51, 151, 195, 0.2), transparent 70%);
}

/* 中间层：浮动代码片段 */
.stage-float {
  position: absolute;
  padding: 10px 18px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(79, 185, 216, 0.15);
  border-radius: 10px;
  backdrop-filter: blur(4px);
  font-family: var(--font-mono);
  font-size: 12px;
  color: rgba(79, 185, 216, 0.7);
  opacity: 0;
  transform: translateY(20px);
}

.stage-float code {
  font-family: inherit;
}

.stage-float--1 { top: 18%; left: 8%; }
.stage-float--2 { top: 12%; right: 12%; }
.stage-float--3 { bottom: 22%; left: 12%; }
.stage-float--4 { bottom: 16%; right: 8%; }

/* 前景层：中心内容 */
.stage-center {
  position: relative;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
  padding: 0 20px;
}

/* 品牌亮相位：闪屏 logo 的接力落点。所有比例 = 闪屏 logo × 0.75
   （盒 80→60 / 圆角 22→16.5 / 字标 50→37.5），交叉淡换才能像素级吻合 */
.stage-logo {
  width: 60px;
  height: 60px;
  border-radius: 16.5px;
  display: grid;
  place-items: center;
  background: radial-gradient(72% 72% at 50% 42%, #1f86c1, #004872);
  border: 1px solid rgba(79, 185, 216, 0.35);
  box-shadow: 0 14px 44px -8px rgba(23, 117, 173, 0.45);
}

.stage-logo svg {
  width: 37.5px;
  height: 37.5px;
}

/* 落位后的待机呼吸微光（与闪屏 logo 同款节奏） */
@media (prefers-reduced-motion: no-preference) {
  .stage-logo {
    animation: cv-stage-logo-breathe 4s ease-in-out 0.6s infinite;
  }
}

@keyframes cv-stage-logo-breathe {
  0%, 100% { box-shadow: 0 14px 44px -8px rgba(23, 117, 173, 0.45); }
  50% { box-shadow: 0 14px 56px -6px rgba(79, 185, 216, 0.55), 0 0 30px -8px rgba(79, 185, 216, 0.3); }
}

.stage-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border: 1px solid rgba(79, 185, 216, 0.3);
  border-radius: 999px;
  background: rgba(79, 185, 216, 0.08);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: rgba(79, 185, 216, 0.9);
  opacity: 0;
  transform: translateY(10px);
}

.stage-badge-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #4fb9d8;
}

.stage-title {
  font-family: var(--font-display);
  font-size: clamp(36px, 6vw, 72px);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.03em;
  color: #fff;
  margin: 0;
}

.stage-char {
  display: inline-block;
  opacity: 0;
  transform: translateY(30px) rotateX(40deg);
  transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.stage-char--accent {
  background: linear-gradient(120deg, #4fb9d8, #8ad6ee);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.stage-sub {
  font-family: var(--font-sans);
  font-size: 16px;
  color: rgba(201, 222, 236, 0.65);
  margin: 0;
  opacity: 0;
  transform: translateY(15px);
}

.stage-cta {
  display: flex;
  gap: 12px;
  margin-top: 8px;
  opacity: 0;
  transform: translateY(15px);
}

.stage-cta .button.secondary {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(79, 185, 216, 0.4);
  color: rgba(255, 255, 255, 0.9);
  box-shadow: none;
}

.stage-cta .button.secondary:hover {
  background: rgba(79, 185, 216, 0.15);
  border-color: #4fb9d8;
  color: #fff;
}

/* 底部滚动指引线 */
.stage-scroll-line {
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 2px;
  height: 60px;
  background: linear-gradient(180deg, rgba(79, 185, 216, 0.5), transparent);
  opacity: 0;
}

.stage-scroll-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #4fb9d8;
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
}

/* ===== Stage 入场动画（闪屏退出后触发）===== */
@media (prefers-reduced-motion: no-preference) {
  .stage.is-entered .stage-badge {
    animation: cv-stage-rise 0.6s ease 0.1s forwards;
  }

  .stage.is-entered .stage-char {
    opacity: 0;
    transform: translateY(30px) rotateX(40deg);
  }

  .stage.is-entered .stage-sub {
    animation: cv-stage-rise 0.6s ease 1.4s forwards;
  }

  .stage.is-entered .stage-cta {
    animation: cv-stage-rise 0.6s ease 1.7s forwards;
  }

  .stage.is-entered .stage-scroll-line {
    animation: cv-stage-rise 0.8s ease 2s forwards;
  }

  .stage.is-entered .stage-float {
    animation: cv-stage-float-in 0.8s ease forwards;
  }
  .stage.is-entered .stage-float--1 { animation-delay: 0.3s; }
  .stage.is-entered .stage-float--2 { animation-delay: 0.6s; }
  .stage.is-entered .stage-float--3 { animation-delay: 0.9s; }
  .stage.is-entered .stage-float--4 { animation-delay: 1.2s; }

  .stage.is-entered .stage-orb {
    animation: cv-stage-orb-breathe 4s ease-in-out infinite;
  }
  .stage.is-entered .stage-orb--2 { animation-delay: 1.3s; }
  .stage.is-entered .stage-orb--3 { animation-delay: 2.6s; }

  .stage.is-entered .stage-scroll-dot {
    animation: cv-stage-scroll-pulse 2s ease-in-out 2.2s infinite;
  }

  /* 滚动时 Stage 内容淡出 + 缩小（通过 JS --scroll-progress）*/
  .has-js .stage-center {
    opacity: calc(1 - var(--scroll-progress) * 2.5);
    transform: scale(calc(1 - var(--scroll-progress) * 0.15));
  }

  .has-js .stage-layer--back {
    opacity: calc(1 - var(--scroll-progress) * 1.5);
  }

  .has-js .stage-layer--mid {
    opacity: calc(1 - var(--scroll-progress) * 2);
  }
}

@media (prefers-reduced-motion: reduce) {
  .stage-char {
    opacity: 1;
    transform: none;
  }
  .stage-badge,
  .stage-sub,
  .stage-cta,
  .stage-scroll-line,
  .stage-float {
    opacity: 1;
    transform: none;
  }
}

@keyframes cv-stage-rise {
  from { opacity: 0; transform: translateY(15px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes cv-stage-float-in {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes cv-stage-orb-breathe {
  0%, 100% { transform: scale(1); opacity: 0.7; }
  50% { transform: scale(1.15); opacity: 1; }
}

@keyframes cv-stage-scroll-pulse {
  0%, 100% { transform: translateX(-50%) translateY(0); opacity: 1; }
  50% { transform: translateX(-50%) translateY(40px); opacity: 0; }
}

/* Stage 浮动元素持续微动 */
@media (prefers-reduced-motion: no-preference) {
  .stage.is-entered .stage-float--1 { animation: cv-stage-float-in 0.8s ease 0.3s forwards, cv-stage-hover 3.5s ease-in-out 1.1s infinite; }
  .stage.is-entered .stage-float--2 { animation: cv-stage-float-in 0.8s ease 0.6s forwards, cv-stage-hover 4s ease-in-out 1.4s infinite; }
  .stage.is-entered .stage-float--3 { animation: cv-stage-float-in 0.8s ease 0.9s forwards, cv-stage-hover 3.8s ease-in-out 1.7s infinite; }
  .stage.is-entered .stage-float--4 { animation: cv-stage-float-in 0.8s ease 1.2s forwards, cv-stage-hover 4.2s ease-in-out 2s infinite; }
}

@keyframes cv-stage-hover {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-8px); }
}

/* ===== 自托管字体 · OFL 1.1（许可证见 assets/fonts/*-OFL.txt） ===== */
@font-face {
  font-family: "JetBrains Mono";
  src:
    local("JetBrains Mono"),
    url("assets/fonts/JetBrainsMono-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src:
    local("JetBrains Mono Italic"),
    url("assets/fonts/JetBrainsMono-Italic-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src:
    local("Newsreader"),
    url("assets/fonts/Newsreader-Variable.woff2") format("woff2-variations");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src:
    local("Newsreader Italic"),
    url("assets/fonts/Newsreader-Italic-Variable.woff2") format("woff2-variations");
  font-weight: 200 800;
  font-style: italic;
  font-display: swap;
}

:root {
  color-scheme: light;

  /* 核心双色 + 同色系派生（与 cerulean 一致） */
  --sky: #4fb9d8;
  --cobalt: #1775ad;
  --mid: #3397c3;
  --sky-soft: #d1e4ee;
  --cobalt-deep: #0f5687;
  /* 应用 AppTheme cerulean 亮色的 accent 族（theme.slint 同值） */
  --accent: #2c7bb6;
  --accent-tint: #eaf1f7;
  --accent-tint-soft: #eaf5fb;

  /* 面层 · 与应用 AppTheme cerulean 亮色逐值对齐：
     bg #F1F5F8 / surface #FFFFFF / raised #FBFCFD / border #E8EEF3 / border-strong #D3DEE6 */
  --page: #f1f5f8;
  --surface: #ffffff;
  --surface-soft: #fbfcfd;
  --line: #e8eef3;
  --line-strong: #d3dee6;
  --soft-line: #e6edf2;

  /* 文本（应用 text-heading #2C3E50 / text-strong #264058 / text-muted #6D8092） */
  --ink: #2c3e50;
  --body: #264058;
  --muted: #6d8092;

  /* 语义色（success 取应用亮色 success-bright） */
  --success: #2e9e6b;
  --warning: #c8872d;
  --danger: #c44545;

  /* 字体栈 · 默认搭配 = JetBrains Mono 标题 + Newsreader 衬线正文 */
  --font-display: "JetBrains Mono", "PingFang SC", "Noto Sans SC", "Microsoft YaHei", system-ui, sans-serif;
  --font-serif: "Newsreader", "Noto Serif SC", "Songti SC", Georgia, serif;
  --font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Noto Sans SC", "Microsoft YaHei", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  /* 旧别名（设计区组件仍在引用） */
  --mono: var(--font-mono);

  --radius: 10px;
  --radius-lg: 14px;
  --shadow: 0 18px 42px -18px rgba(15, 46, 71, 0.18);
  --shadow-soft: 0 8px 22px -12px rgba(15, 46, 71, 0.12);
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

/* 滚动揭示的初始侧移（translate ±72px 等）会在窄屏把页面撑出横向滚动条，
   根上统一裁掉横向溢出；clip 不产生新的滚动容器，sticky 不受影响。 */
html,
body {
  overflow-x: clip;
}

/* 锚点跳转预留吸顶导航高度，章节标题不被顶栏遮住 */
main section {
  scroll-margin-top: 72px;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--body);
  font-family: var(--font-serif);
  font-size: 16px;
  line-height: 1.72;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--cobalt);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

img {
  display: block;
  max-width: 100%;
}

.shell {
  width: min(1120px, calc(100% - 40px));
  margin: 0 auto;
}

/* ===== 顶栏 ===== */
.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(241, 245, 248, 0.82);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid rgba(211, 222, 230, 0.8);
}

.nav {
  min-height: 64px;
  display: flex;
  align-items: center;
  gap: 18px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 17px;
  letter-spacing: -0.01em;
  text-decoration: none;
}

.brand-mark {
  width: 32px;
  height: 32px;
  border-radius: 9px;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, var(--sky), var(--cobalt));
  box-shadow: 0 8px 18px -6px rgba(23, 117, 173, 0.45);
}

.brand-mark svg {
  width: 18px;
  height: 18px;
  color: white;
}

.nav-links {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.nav-links a,
.button {
  min-height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border-radius: var(--radius);
  padding: 8px 14px;
  border: 1px solid transparent;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  color: var(--body);
  transition: background 140ms ease, border-color 140ms ease, transform 120ms ease;
}

.nav-links a:hover {
  background: var(--surface);
  border-color: var(--line);
}

.button {
  background: var(--cobalt);
  color: white;
  border-color: var(--cobalt);
  box-shadow: 0 10px 22px -10px rgba(23, 117, 173, 0.55);
}

.button:hover {
  transform: translateY(-1px);
  filter: brightness(1.04);
}

.button.secondary {
  background: var(--surface);
  color: var(--ink);
  border-color: var(--line-strong);
  box-shadow: none;
}

.button.secondary:hover {
  border-color: var(--cobalt);
  color: var(--cobalt);
  filter: none;
}

/* ===== 通用标题体系（字重 500 + 负字距，去除粗黑体观感） ===== */
h1,
h2,
h3 {
  margin: 0;
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.18;
  letter-spacing: -0.018em;
}

h1 {
  font-size: clamp(34px, 4.6vw, 56px);
  line-height: 1.12;
  max-width: 13ch;
}

h2 {
  font-size: clamp(25px, 3vw, 38px);
}

h3 {
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* mono 大写 eyebrow / 小节标签（设计稿招牌：前置一截短横线） */
.eyebrow,
.section-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin: 0 0 12px;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--cobalt);
  padding: 6px 12px 6px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: linear-gradient(180deg, var(--surface), var(--surface-soft));
  box-shadow: var(--shadow-soft);
}

/* 「正在记录」脉冲点 —— 给开场一个活物感 */
.eyebrow-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--cobalt);
  box-shadow: 0 0 0 0 rgba(23, 117, 173, 0.45);
  flex: none;
}

@media (prefers-reduced-motion: no-preference) {
  .eyebrow-dot {
    animation: cv-eyebrow-pulse 2.4s ease-out infinite;
  }
}

@keyframes cv-eyebrow-pulse {
  0% { box-shadow: 0 0 0 0 rgba(23, 117, 173, 0.4); }
  70% { box-shadow: 0 0 0 7px rgba(23, 117, 173, 0); }
  100% { box-shadow: 0 0 0 0 rgba(23, 117, 173, 0); }
}

/* 标题关键词双色渐变（设计系统招牌：天青→深钴） */
.grad {
  background: linear-gradient(120deg, var(--sky), var(--cobalt) 64%, var(--cobalt-deep));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.section-label {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--muted);
  letter-spacing: 0.1em;
}

.section-label::before {
  content: "";
  width: 20px;
  height: 1px;
  background: var(--line-strong);
}

/* ===== Hero ===== */
.hero {
  position: relative;
  padding: 72px 0 40px;
}

/* hero 左侧局部极光 —— 让开场不是一片平铺底色（压得很低，保可读） */
.hero::before {
  content: "";
  position: absolute;
  top: -8%;
  left: -10%;
  width: 60%;
  height: 120%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(42% 38% at 20% 22%, rgba(79, 185, 216, 0.16), transparent 70%),
    radial-gradient(36% 40% at 8% 64%, rgba(23, 117, 173, 0.1), transparent 72%);
}

.hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(420px, 1.08fr);
  gap: 48px;
  align-items: center;
}

.lead {
  margin: 22px 0 0;
  max-width: 56ch;
  font-family: var(--font-serif);
  font-size: 19px;
  line-height: 1.66;
  color: var(--body);
}

.hero-actions {
  margin-top: 30px;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.hero-meta {
  margin: 30px 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}

.hero-meta li,
.card,
.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-soft);
}

.hero-meta li {
  position: relative;
  overflow: hidden;
  padding: 18px 16px 15px;
  transition: transform 150ms ease, box-shadow 150ms ease;
}

.hero-meta li:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
}

/* 卡顶一截品牌色细线 —— 三张指标卡的统一节奏感 */
.hero-meta li::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, var(--sky), var(--cobalt));
  opacity: 0.7;
}

.metric {
  display: block;
  font-family: var(--font-mono);
  font-size: 30px;
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  background: linear-gradient(120deg, var(--cobalt), var(--cobalt-deep));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.label {
  display: block;
  margin-top: 5px;
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: 12px;
  line-height: 1.4;
}

/* ===== hero 品牌取景框（设计精华展示，2026-07-02 起 hero 即设计入口）===== */
.brand-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 36px 24px 20px;
  /* 与构成解析三联图同款点阵底：暗示「构成网格」 */
  background-image: radial-gradient(rgba(23, 117, 173, 0.1) 1px, transparent 1.2px);
  background-size: 18px 18px;
}

.brand-hero-logo {
  width: 148px;
  height: 148px;
  border-radius: 41px; /* 与真实图标同曲率比例（22/80） */
  display: grid;
  place-items: center;
  background: radial-gradient(72% 72% at 50% 42%, #1f86c1, #004872);
  border: 1px solid rgba(79, 185, 216, 0.35);
  box-shadow: 0 24px 60px -18px rgba(23, 117, 173, 0.5);
}

.brand-hero-logo svg {
  width: 92px;
  height: 92px;
}

@media (prefers-reduced-motion: no-preference) {
  .brand-hero-logo {
    transition: transform 0.8s cubic-bezier(0.22, 0.61, 0.36, 1);
    animation: cv-stage-logo-breathe 4s ease-in-out 1s infinite;
  }
  /* 中心对称的活证明：旋转 180° 与自身完全重合 */
  .brand-hero-logo:hover {
    transform: rotate(180deg);
  }
}

.brand-hint {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 12.5px;
  color: var(--muted);
}

.brand-palette {
  display: flex;
  gap: 8px;
}

.brand-palette span {
  width: 36px;
  height: 18px;
  border-radius: 5px;
  border: 1px solid rgba(15, 46, 71, 0.1);
}

.brand-uses {
  width: 100%;
  padding-top: 12px;
  border-top: 1px solid var(--soft-line);
  text-align: center;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--muted);
}

/* 预览区暖场：从 hero 移来的「实时捕获」取景框，居中窄版 */
.preview-vault {
  max-width: 640px;
  margin: 0 auto 26px;
}

/* ===== 产品取景框 + 内嵌预览 ===== */
.product-frame {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: #dfe8ef;
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
}


/* ===== 区块通用 ===== */
section {
  padding: 52px 0;
}

.section-head {
  max-width: 64ch;
  margin-bottom: 28px;
}

.section-head h2 {
  margin-bottom: 12px;
}

.section-intro {
  margin: 0;
  font-size: 17px;
  color: var(--muted);
}

.grid {
  display: grid;
  gap: 14px;
}

.grid.features {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

/* 功能区：4 列网格。首排两张「视图级」宽卡（白板 / 内容对比）各占 2 列，
   其余 12 张标准卡 4 列 × 3 行。仅作用于 #features，路线图仍保持 3 列。 */
#features .grid.features {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.card--wide {
  grid-column: span 2;
  display: flex;
  flex-direction: column;
}

.card--wide .feat-vig {
  margin-top: auto;
}

.grid.two {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.card {
  padding: 24px;
  transition: border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease;
}

.grid.features .card:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow);
  transform: translateY(-2px);
}

.card p {
  margin: 10px 0 0;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.65;
}

.icon {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  margin-bottom: 16px;
  color: var(--cobalt);
  background: #e7f3f9;
  border: 1px solid #d3e9f2;
}

.icon svg {
  width: 20px;
  height: 20px;
}

/* 功能卡右上角模块徽章：复刻应用的 UPPERCASE 类型徽章（等宽小胶囊 · tint 底） */
.feat-badge {
  position: absolute;
  top: 16px;
  right: 16px;
  padding: 3px 8px;
  border-radius: 5px;
  background: var(--accent-tint);
  color: var(--cobalt);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1.4;
}

/* ============================================================
   视图级宽卡的迷你视觉小样（纯 CSS/SVG 还原应用白板与内容对比）
   ============================================================ */
.feat-vig {
  margin-top: 18px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-soft);
  overflow: hidden;
}

/* ── 白板：点阵画布 + 便签 + 形状 + 箭头连线 + 画笔笔迹 ── */
.vig-wb {
  position: relative;
  height: 150px;
  background-image: radial-gradient(rgba(23, 117, 173, 0.13) 1px, transparent 1.2px);
  background-size: 18px 18px;
}

.vig-note {
  position: absolute;
  top: 20px;
  left: 18px;
  width: 112px;
  height: 62px;
  padding: 10px;
  box-sizing: border-box;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  box-shadow: 0 6px 14px -8px rgba(15, 46, 71, 0.18);
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.vig-note i {
  height: 5px;
  border-radius: 3px;
  background: var(--line-strong);
}

.vig-note i:nth-child(2) {
  width: 68%;
  background: var(--soft-line);
}

.vig-shape {
  position: absolute;
  background: var(--accent-tint);
  border: 1.5px solid var(--accent);
}

.vig-shape--round {
  top: 26px;
  right: 20px;
  width: 92px;
  height: 40px;
  border-radius: 10px;
}

.vig-shape--diamond {
  bottom: 20px;
  right: 66px;
  width: 30px;
  height: 30px;
  rotate: 45deg;
  border-radius: 5px;
}

.vig-wb svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: var(--accent);
}

/* 连线与画笔笔迹：悬停时沿路径重新「书写」（对齐应用白板连线手感） */
.vig-wb .vig-link {
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  stroke-linecap: round;
}

.vig-wb .vig-pen {
  stroke: var(--sky);
  stroke-width: 2.4;
  fill: none;
  stroke-linecap: round;
  opacity: 0.85;
}

@media (prefers-reduced-motion: no-preference) {
  .card--wide:hover .vig-wb .vig-link {
    stroke-dasharray: 150;
    animation: cv-vig-draw 0.9s cubic-bezier(0.4, 0, 0.2, 1) both;
  }
  .card--wide:hover .vig-wb .vig-pen {
    stroke-dasharray: 130;
    animation: cv-vig-draw 0.9s cubic-bezier(0.4, 0, 0.2, 1) 0.25s both;
  }
}

@keyframes cv-vig-draw {
  from { stroke-dashoffset: 150; }
  to { stroke-dashoffset: 0; }
}

/* ── 内容对比：双栏行级 diff（新增 / 删除 / 改动 三色，同应用语义色） ── */
.vig-diff-head {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.vig-diff-head span {
  padding: 7px 12px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--muted);
}

.vig-diff-head span + span {
  border-left: 1px solid var(--line);
}

.vig-diff-body {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.vig-col {
  padding: 8px 0;
}

.vig-col + .vig-col {
  border-left: 1px solid var(--line);
}

.vr {
  position: relative;
  display: flex;
  align-items: center;
  height: 21px;
  padding: 0 12px 0 16px;
}

.vr i {
  height: 5px;
  border-radius: 3px;
  background: var(--soft-line);
}

.vr::before {
  content: "";
  position: absolute;
  left: 0;
  top: 2px;
  bottom: 2px;
  width: 3px;
  border-radius: 0 2px 2px 0;
  background: transparent;
}

.vr.del { background: #fbeaea; }
.vr.del::before { background: var(--danger); }
.vr.del i { background: #e7c4c4; }

.vr.ins { background: #e6f4ec; }
.vr.ins::before { background: var(--success); }
.vr.ins i { background: #bce0ca; }

.vr.chg { background: #fcf3e8; }
.vr.chg::before { background: var(--warning); }
.vr.chg i { background: #f0d9b8; }

/* ===== 设计区 · 展示面板 ===== */
.showcase {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 16px;
}

.panel {
  overflow: hidden;
}

.panel-body {
  padding: 24px;
}

.demo-list {
  display: grid;
  gap: 10px;
  padding: 0;
  margin: 14px 0 0;
  list-style: none;
}

.demo-list a {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: var(--radius);
  background: var(--surface-soft);
  border: 1px solid var(--soft-line);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: 500;
  transition: border-color 140ms ease, background 140ms ease;
}

.demo-list a:hover {
  border-color: var(--line-strong);
  background: var(--surface);
}

.demo-list span {
  color: var(--muted);
  font-family: var(--font-mono);
  font-size: 12px;
}

.code {
  margin: 0;
  padding: 20px;
  overflow: auto;
  background: #0f293e;
  color: #d9f3fb;
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.7;
  -webkit-font-smoothing: auto;
}

/* ===== 开源区 · 资料清单 ===== */
.timeline {
  counter-reset: step;
  display: grid;
  gap: 12px;
}

.step {
  position: relative;
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: 16px;
  padding: 20px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
}

.step::before {
  counter-increment: step;
  content: counter(step, decimal-leading-zero);
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: var(--ink);
  color: white;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 500;
}

.step p {
  margin: 6px 0 0;
  color: var(--muted);
  font-size: 15px;
}

.stack {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 18px;
}

.tag {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--surface);
  border: 1px solid var(--line);
  color: var(--cobalt-deep);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  text-decoration: none;
  transition: border-color 140ms ease, background 140ms ease;
}

.tag:hover {
  border-color: var(--cobalt);
  background: var(--surface-soft);
}

/* ===== 页脚 ===== */
.footer {
  padding: 44px 0 56px;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 14px;
}

.footer .shell {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
}

@media (max-width: 920px) {
  .hero-grid,
  .showcase,
  .grid.features,
  .grid.two {
    grid-template-columns: 1fr;
  }

  /* 功能区 4 列在中等屏先降到 2 列（优先级需盖过上面的 #features 4 列规则）*/
  #features .grid.features {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 600px) {
  #features .grid.features {
    grid-template-columns: 1fr;
  }

  /* 单列时宽卡跨列失效，回到普通一列 */
  .card--wide {
    grid-column: auto;
  }
}

@media (max-width: 640px) {
  .shell {
    width: min(100% - 28px, 1120px);
  }

  .hero {
    padding-top: 44px;
  }

  .hero-meta {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
   双色基石色卡（对齐 010「BASE · 双色基石」）
   ============================================================ */
.base-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

.base-card {
  position: relative;
  border-radius: var(--radius-lg);
  padding: 26px 28px 22px;
  color: #ffffff;
  overflow: hidden;
  min-height: 168px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.base-sky {
  background: var(--sky);
}

.base-cobalt {
  background: var(--cobalt);
}

.base-role {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.82;
  margin: 0;
}

.base-hex {
  font-family: var(--font-mono);
  font-size: 27px;
  font-weight: 500;
  letter-spacing: -0.01em;
  margin: 0;
}

.base-name {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 500;
  margin: 4px 0 12px;
}

.base-use {
  font-family: var(--font-sans);
  font-size: 13px;
  opacity: 0.86;
  line-height: 1.5;
}

/* 双色卡内文字为白色：base-card 嵌在 .card.ds-block 内，需胜过通用
   .card p 的 muted 灰（否则继承的白被直接选择器覆盖，文字会发灰）。 */
.base-card p {
  color: #fff;
}

/* ============================================================
   Cerulean 设计系统展示（仅作用于首页「设计」板块）
   token 与 .cv-* 组件原语收敛进 .cv-scope，避免覆盖站点全局排版。
   ============================================================ */
.cv-scope {
  --sky: #4fb9d8;
  --cobalt: #1775ad;
  --mid: #3397c3;
  --sky-soft: #d1e4ee;
  --cobalt-deep: #0f5687;
  --cv-card: #fbfcfd;
  --cv-border: #d3dee6;
  --cv-border-strong: #b5c4cf;
  --cv-text: #0f2e47;
  --cv-text-body: #264058;
  --cv-text-muted: #6d8092;
  --success: #3cb285;
  --warn: #e8b35a;
  --danger: #c44545;
  --grad-a: linear-gradient(135deg, #4fb9d8 0%, #1775ad 100%);
  --grad-b: linear-gradient(180deg, #4fb9d8 0%, #1775ad 100%);
  --grad-c: linear-gradient(135deg, #4fb9d8 0%, #3397c3 50%, #1775ad 100%);
  --grad-d: radial-gradient(circle at top left, #4fb9d8 0%, #1775ad 90%);
  --grad-e:
    radial-gradient(at 25% 20%, rgba(79, 185, 216, 0.9) 0%, transparent 55%),
    radial-gradient(at 75% 80%, #1775ad 0%, #0f5687 100%);
  --grad-soft: linear-gradient(135deg, #d1e4ee 0%, #b5d4e3 100%);
  --cv-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --cv-system: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Noto Sans SC", "Microsoft YaHei", sans-serif;
  --cv-radius: 10px;
  --cv-radius-lg: 14px;
  --focus-ring: 0 0 0 3px var(--sky-soft);
}

.cv-scope .cv-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 10px 18px;
  border: 1px solid transparent;
  border-radius: var(--cv-radius);
  font-family: var(--cv-system);
  font-size: 14px;
  font-weight: 500;
  color: #fff;
  background: var(--cobalt);
  cursor: pointer;
  transition: transform 120ms ease, filter 140ms ease, border-color 140ms ease;
}

.cv-scope .cv-btn:hover {
  transform: translateY(-1px);
  filter: brightness(1.05);
}

.cv-scope .cv-btn--grad {
  background: var(--grad-a);
  box-shadow: 0 2px 6px -1px rgba(23, 117, 173, 0.35);
}

.cv-scope .cv-btn--ghost {
  background: var(--cv-card);
  border-color: var(--cv-border-strong);
  color: var(--cv-text-body);
}

.cv-scope .cv-btn--ghost:hover {
  border-color: var(--cobalt);
  color: var(--cobalt);
  filter: none;
}

.cv-scope .cv-btn--danger {
  background: var(--danger);
  box-shadow: 0 2px 6px -1px rgba(196, 69, 69, 0.4);
}

.cv-scope .cv-badge {
  display: inline-block;
  font-family: var(--cv-mono);
  font-size: 10px;
  font-weight: 500;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(15, 46, 71, 0.08);
  color: var(--cv-text-muted);
}

.cv-scope .cv-badge--accent {
  background: var(--sky-soft);
  color: var(--cobalt);
}

.cv-scope .cv-input {
  width: 100%;
  padding: 10px 14px;
  background: #fff;
  border: 1px solid var(--cv-border-strong);
  border-radius: var(--cv-radius);
  font-family: var(--cv-system);
  font-size: 13.5px;
  color: var(--cv-text);
  outline: none;
  transition: border-color 140ms ease, box-shadow 200ms ease;
}

.cv-scope .cv-input:focus {
  border-color: var(--sky);
  box-shadow: var(--focus-ring);
}

.cv-scope .cv-kbd {
  font-family: var(--cv-mono);
  font-size: 11px;
  font-weight: 600;
  padding: 2px 7px;
  background: var(--cv-card);
  border: 1px solid var(--cv-border);
  border-bottom-width: 2px;
  border-radius: 4px;
  color: var(--cv-text-body);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
}

.cv-scope .cv-grad-text {
  background: var(--grad-a);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* 设计系统展示 · 版面 */
.ds-stack {
  display: grid;
  gap: 16px;
}

.ds-block {
  padding: 24px;
}

.ds-block > h3 {
  font-size: 16px;
  margin-bottom: 4px;
}

.ds-note {
  margin: 0 0 18px;
  color: var(--muted);
  font-family: var(--font-sans);
  font-size: 13px;
}

.ds-swatches {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(128px, 1fr));
  gap: 10px;
}

.ds-swatch {
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface);
}

.ds-chip {
  height: 50px;
}

.ds-swatch .ds-meta {
  padding: 8px 11px;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.ds-swatch .ds-name {
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--ink);
  font-weight: 500;
}

.ds-swatch .ds-hex {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
}

.ds-grads {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(116px, 1fr));
  gap: 10px;
}

.ds-grad {
  height: 70px;
  border-radius: 10px;
  border: 1px solid rgba(15, 46, 71, 0.08);
  display: flex;
  align-items: flex-end;
  padding: 8px;
}

.ds-grad span {
  font-family: var(--font-mono);
  font-size: 11px;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

.ds-grad.is-soft span {
  color: var(--cobalt);
  text-shadow: none;
}

.ds-twin {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.ds-type {
  display: grid;
  gap: 12px;
}

.ds-type-row {
  display: grid;
  grid-template-columns: 78px 1fr;
  gap: 14px;
  align-items: baseline;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--soft-line);
}

.ds-type-row:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.ds-type-tag {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
}

.ds-sample-display {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 500;
  color: var(--cv-text);
}

.ds-sample-body {
  font-family: var(--font-serif);
  font-size: 18px;
  color: var(--cv-text-body);
}

.ds-sample-mono {
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--cv-text-body);
}

.ds-components {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.ds-comp-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.ds-comp-row > span {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--cv-text-body);
}

.ds-input-wrap {
  flex: 1 1 220px;
  max-width: 300px;
}

/* ===== Hero「实时捕获」金库可视化 =====
   把产品核心循环演给人看：复制的内容一条条被捕获、持续上行、沉淀成
   可检索的卡片。纯 CSS marquee 自运行，悬停暂停可读；reduced-motion
   退化为静态列表（内容照样可见），整块 aria-hidden（语义交给下方说明条）。 */
.vault {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  height: clamp(340px, 44vh, 420px);
  padding: 14px;
  background: linear-gradient(180deg, #eef4f8, #e1eaf1);
  overflow: hidden;
}

/* 捕获流容器：上下渐隐遮罩，做出「冒出 / 沉入」的连续感 */
.capture-feed {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 13%, #000 87%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 13%, #000 87%, transparent);
}

.capture-line {
  flex: none;
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cobalt);
}

.capture-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--cobalt);
  box-shadow: 0 0 0 0 rgba(23, 117, 173, 0.45);
}

/* Ctrl+C 键帽：常驻于「实时捕获」行右侧，每次捕获时按下高亮（演示复制这一源头动作）*/
.copy-keys {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.copy-keys kbd {
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1;
  letter-spacing: normal;
  color: var(--body);
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-bottom-width: 2px; /* 立体键帽：底边略厚 */
  border-radius: 5px;
  padding: 3px 6px;
  box-shadow: 0 1px 0 rgba(15, 46, 71, 0.08);
  transition: transform 90ms ease, background 90ms ease, color 90ms ease,
    border-color 90ms ease, box-shadow 90ms ease, border-bottom-width 90ms ease;
}

/* 按下态：键帽下沉 + 钴蓝高亮（JS 在每次捕获时短暂加 is-pressing）*/
.copy-keys.is-pressing kbd {
  transform: translateY(2px);
  border-bottom-width: 1px;
  box-shadow: none;
  background: var(--cobalt);
  color: #fff;
  border-color: var(--cobalt);
}

/* 尊重「减少动态」：保留高亮反馈但不做下沉位移 */
@media (prefers-reduced-motion: reduce) {
  .copy-keys.is-pressing kbd {
    transform: none;
  }
}

/* 搜索过滤演示：顶栏进入「搜索」态（Ctrl+C→Ctrl+F、强调点），命中卡高亮、其余压暗，
   演示说明条里承诺的「快速搜索」。JS 周期性短暂触发，reduce 时不触发。 */
.capture-label {
  transition: color 0.25s ease;
}
.vault.is-searching .capture-line {
  color: var(--cobalt);
}
.vault.is-searching .capture-label {
  font-weight: 600;
  letter-spacing: 0.06em;
}
.vault.is-searching .capture-dot {
  background: var(--sky);
  box-shadow: 0 0 0 3px rgba(79, 185, 216, 0.22);
}
.clip-chip.is-dim {
  opacity: 0.26;
  filter: saturate(0.65);
  transition: opacity 0.4s ease, filter 0.4s ease;
}
.clip-chip.is-hit {
  box-shadow: 0 0 0 1.5px rgba(23, 117, 173, 0.55), var(--shadow-soft);
  transition: box-shadow 0.3s ease;
}
@media (prefers-reduced-motion: reduce) {
  .clip-chip.is-dim,
  .clip-chip.is-hit {
    transition: none;
  }
}

/* 无 gap / 无 padding：每张卡都带等量 margin-bottom（含最后一张），
   两份内容高度完全相等 → translateY(-50%) 循环无接缝。 */
.capture-track {
  display: flex;
  flex-direction: column;
}

.clip-chip {
  position: relative;
  flex: none;
  margin-bottom: 9px;
  padding: 9px 12px 9px 15px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 9px;
  box-shadow: var(--shadow-soft);
  overflow: hidden;
}

/* 左侧类型色条 —— 一眼区分捕获到的内容类别 */
.clip-chip::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background: var(--cobalt);
}

.clip-chip[data-kind="text"]::before    { background: var(--sky); }
.clip-chip[data-kind="code"]::before    { background: #9370db; }
.clip-chip[data-kind="image"]::before   { background: var(--success); }
.clip-chip[data-kind="file"]::before    { background: var(--warning); }
.clip-chip[data-kind="rich"]::before    { background: #5ba8a8; }

.chip-kind {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.12em;
  color: var(--cobalt);
  padding: 1px 6px;
  border-radius: 4px;
  background: rgba(23, 117, 173, 0.09);
}

.chip-body {
  display: block;
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chip-meta {
  display: block;
  margin-top: 4px;
  font-family: var(--font-sans);
  font-size: 10.5px;
  color: var(--muted);
}

/* frame-bar 里的「已归档 N 条」实时计数 */
.frame-count {
  margin-left: auto;
  flex: none;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: rgba(217, 243, 251, 0.66);
}

/* hero 取景框里改由计数占据右侧弹性位，「实时体验」链接紧随其后 */
.vault-frame .frame-bar .frame-open {
  margin-left: 8px;
}

.frame-count .count {
  color: rgba(217, 243, 251, 0.95);
  font-weight: 600;
}

@media (prefers-reduced-motion: no-preference) {
  .capture-dot {
    animation: cv-eyebrow-pulse 2.4s ease-out infinite;
  }
}

/* ---- 交互演示：复制 → 捕获 → 粘贴（JS 驱动，has-js 才接管）---- *
   滑入位移由 JS 内联在 .capture-track 上做；这里只管各控件外观与高亮。 */

/* 刚捕获高亮：绿色环 + 内联标签，由 JS 在 ~1.4s 后移除（过渡淡出）*/
.clip-chip {
  transition: border-color 600ms ease, box-shadow 600ms ease;
}

.clip-chip.is-fresh {
  border-color: var(--success);
  box-shadow: 0 0 0 2px rgba(60, 178, 133, 0.2), var(--shadow-soft);
}

.fresh-tag {
  margin-left: 6px;
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.08em;
  color: var(--success);
  padding: 1px 6px;
  border-radius: 4px;
  background: rgba(60, 178, 133, 0.13);
}

/* 悬停露出的「粘贴」按钮 —— 演示「复用 / 粘回」那一半 */
.chip-paste {
  position: absolute;
  top: 7px;
  right: 7px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-mono);
  font-size: 9.5px;
  color: var(--cobalt);
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  cursor: pointer;
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity 140ms ease, transform 140ms ease, background 140ms ease,
    color 140ms ease, border-color 140ms ease;
}

.clip-chip:hover .chip-paste {
  opacity: 1;
  transform: translateY(0);
}

.chip-paste:hover {
  background: var(--cobalt);
  color: #fff;
  border-color: var(--cobalt);
}

/* 「复制一条试试」触发按钮 */
.vault-cta {
  flex: none;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--cobalt);
  padding: 6px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: var(--surface);
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, transform 120ms ease;
}

.vault-cta:hover {
  border-color: var(--cobalt);
  background: var(--surface-soft);
}

.vault-cta:active {
  transform: translateY(1px);
}

.vault-cta kbd {
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--muted);
  padding: 1px 5px;
  border: 1px solid var(--line);
  border-radius: 4px;
  background: var(--surface-soft);
}

/* 「已粘贴」气泡：浮在金库顶部中央上升淡出
   （挂在 .vault 上，避开 .clip-chip / .capture-feed 的 overflow 裁切）*/
.paste-pill {
  position: absolute;
  z-index: 3;
  left: 50%;
  top: 38px;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: #fff;
  background: var(--success);
  padding: 3px 11px;
  border-radius: 999px;
  box-shadow: 0 6px 16px -6px rgba(60, 178, 133, 0.6);
  pointer-events: none;
  animation: cv-pill-rise 1000ms ease forwards;
}

@keyframes cv-pill-rise {
  0% { opacity: 0; transform: translate(-50%, 6px); }
  18% { opacity: 1; transform: translate(-50%, 0); }
  78% { opacity: 1; transform: translate(-50%, -8px); }
  100% { opacity: 0; transform: translate(-50%, -16px); }
}

@media (prefers-reduced-motion: reduce) {
  .paste-pill {
    animation: cv-pill-fade 1000ms ease forwards;
  }
}

@keyframes cv-pill-fade {
  0% { opacity: 0; }
  18% { opacity: 1; }
  78% { opacity: 1; }
  100% { opacity: 0; }
}

/* ===== 实时预览板块（全宽大舞台 · facade：先海报，点击载入 iframe）===== */

/* 板块整体：加柔和深色背景过渡，让大 frame 不突兀 */
#preview {
  padding: clamp(48px, 7vh, 80px) 0;
}

#preview .section-head {
  text-align: center;
  margin-left: auto;
  margin-right: auto;
}

.preview-stage {
  /* 居中的克制「浮窗」，不再贴边铺满，与页面留白节奏一致 */
  margin: 8px auto 0;
  max-width: 1000px;
  border-radius: 14px;
  overflow: hidden;
  background: #0f293e;
  border: none;
  box-shadow:
    0 0 0 1px rgba(15, 46, 71, 0.1),
    0 2px 8px rgba(15, 46, 71, 0.06),
    0 30px 70px -22px rgba(15, 46, 71, 0.32);
}

.frame-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  background: #0f293e;
}

.frame-bar .dots {
  display: inline-flex;
  gap: 6px;
}

.frame-bar .dots i {
  width: 10px;
  height: 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.28);
}

.frame-bar .frame-url {
  font-family: var(--font-mono);
  font-size: 11px;
  color: rgba(217, 243, 251, 0.82);
}

.frame-bar .frame-open {
  margin-left: auto;
  flex-shrink: 0;
  color: rgba(217, 243, 251, 0.92);
  font-family: var(--font-mono);
  font-size: 11px;
  text-decoration: none;
  padding: 3px 9px;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  transition: background 140ms ease, border-color 140ms ease;
}

.frame-bar .frame-open:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.34);
}

/* 注意：不要在带 aspect-ratio 的框上再加 max-height —— 矮视口下 max-height
   压低高度后，aspect-ratio 会连宽度一起缩，导致框比舞台窄、右侧留大空隙。
   这里只用 aspect-ratio，框始终满宽、高度按 16:10 自然算。 */
.preview-embed {
  position: relative;
  /* 宽高比对齐海报图 1400×892，避免 object-fit:cover 把侧栏文字裁掉 */
  aspect-ratio: 1400 / 892;
  background: #0f293e;
  /* 关键：把 poster / iframe 裁进本框内。否则入场时 .preview-stage 跑
     cv-zoom-in（opacity+scale）、poster 又跑 cv-shot-parallax 视差，两层
     变换叠加会让被合成的 poster 顶边溢出、糊到上方深色 frame-bar 上，
     形成一条白带割裂标题栏文字（点击载入前的 facade 态最明显）。 */
  overflow: hidden;
}

.preview-embed .poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* 左上对齐：万一有横向裁切，也优先保住侧栏(左) + 顶栏(上)，只裁右下的列表边缘 */
  object-position: left top;
}

.preview-embed .veil {
  position: absolute;
  inset: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 16px;
  text-align: center;
  /* 更柔和的渐隐遮罩：上淡下略深，让真实应用透出来（peek 感），不再一层死板暗幕 */
  background:
    radial-gradient(120% 90% at 50% 62%, rgba(23, 117, 173, 0.28), transparent 60%),
    linear-gradient(180deg, rgba(11, 33, 51, 0.12) 0%, rgba(11, 33, 51, 0.4) 100%);
  color: #fff;
  border: 0;
  font: inherit;
  cursor: pointer;
  transition: background 200ms ease;
}

.preview-embed .veil:hover {
  background:
    radial-gradient(120% 90% at 50% 62%, rgba(23, 117, 173, 0.34), transparent 60%),
    linear-gradient(180deg, rgba(11, 33, 51, 0.18) 0%, rgba(11, 33, 51, 0.46) 100%);
}

.preview-embed .veil:hover .play {
  transform: translateY(-2px);
  box-shadow: 0 18px 40px -10px rgba(23, 117, 173, 0.72);
}

/* 品牌渐变胶囊按钮，取代突兀的白色播放圆 */
.preview-embed .play {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 12px 22px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--sky), var(--cobalt));
  color: #fff;
  font-family: var(--font-sans);
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  box-shadow: 0 12px 30px -8px rgba(23, 117, 173, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.25);
  transition: transform 160ms ease, box-shadow 160ms ease;
}

.preview-embed .play svg {
  width: 16px;
  height: 16px;
}

.preview-embed .veil-text {
  font-family: var(--font-sans);
  font-size: 12.5px;
  color: rgba(226, 240, 250, 0.86);
  max-width: 40ch;
  text-shadow: 0 1px 6px rgba(11, 33, 51, 0.6);
}

.preview-embed iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: #fff;
}

.preview-actions {
  margin-top: 20px;
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
}

.preview-actions .button.secondary {
  background: var(--surface);
  border-color: var(--line);
}

/* ---- 聚焦模式：点「在本页上手体验」→ 预览框钉成浮窗、顶栏收起、整页锁滚 ---- */
/* 退出按钮（默认 hidden，进聚焦才由 JS 显出） */
.frame-bar .frame-exit {
  flex-shrink: 0;
  color: rgba(217, 243, 251, 0.92);
  font-family: var(--font-mono);
  font-size: 11px;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.06);
  padding: 3px 9px;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  transition: background 140ms ease, border-color 140ms ease;
}

.frame-bar .frame-exit:hover {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.34);
}

/* 背板：常驻 DOM，非聚焦时透明不挡点击。
   刻意不用 backdrop-filter：真实 Chrome/Edge 下 backdrop-filter 与叠在其上的
   跨文档 iframe 合成冲突，会把预览 iframe 一起拉进模糊区（用户实测「只显示模糊」）。
   改用稍深的纯色暗幕做聚焦区隔，不依赖模糊合成，规避该 bug。 */
.preview-backdrop {
  position: fixed;
  inset: 0;
  z-index: 55;
  background:
    radial-gradient(120% 100% at 50% 42%, rgba(9, 26, 40, 0.5), rgba(6, 18, 28, 0.78) 100%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms ease;
}

/* 聚焦态：锁整页滚动 + 顶栏上收 + 背板显出 */
html.preview-focus,
html.preview-focus body {
  overflow: hidden;
}

html.preview-focus .topbar {
  transform: translateY(-100%);
  transition: transform 280ms cubic-bezier(0.3, 0.7, 0.2, 1);
}

html.preview-focus .preview-backdrop {
  opacity: 1;
  pointer-events: auto;
}

/* 预览框钉成居中浮窗：脱离文档流固定在视口，滚动 demo 时纹丝不动 */
html.preview-focus .preview-stage {
  position: fixed;
  top: 50%;
  left: 50%;
  width: min(1180px, 94vw);
  height: min(88vh, 880px);
  max-width: none;
  margin: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  box-shadow: 0 40px 120px -30px rgba(9, 26, 40, 0.7);
  /* 覆盖滚动驱动动画（view() 时间线），改为一次性弹入 */
  animation: cv-focus-pop 340ms cubic-bezier(0.2, 0.7, 0.3, 1) both !important;
  animation-timeline: auto !important;
  opacity: 1;
}

/* 聚焦时框内 embed 撑满剩余高度，iframe 铺满；关掉 16:10 比例约束 */
html.preview-focus .preview-embed {
  aspect-ratio: auto;
  flex: 1 1 auto;
  min-height: 0;
}

/* demo 内滚动到底不外溢到页面（同源 iframe 生效） */
.preview-embed iframe {
  overscroll-behavior: contain;
}

@keyframes cv-focus-pop {
  from {
    transform: translate(-50%, -50%) scale(0.955);
    opacity: 0.3;
  }
  to {
    transform: translate(-50%, -50%) scale(1);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  html.preview-focus .preview-stage {
    animation: none !important;
    transform: translate(-50%, -50%);
  }
  html.preview-focus .topbar {
    transition: none;
  }
}

/* ============================================================
   系统架构图（#architecture · 分层 · 忠实 docs/architecture.md）
   ============================================================ */
/* 装配舞台 / 钉住容器：默认就是普通流（无 JS / 不支持 scroll-driven /
   减少动态 时，架构图正常静态整图显示）。仅在「滚动装配」可用时，下方
   guarded 块才把 .arch-stage 撑高 + 让 .arch-pin 钉住，避免空滚。 */
.arch-stage {
  position: relative;
}

.arch {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.arch-endpoint {
  align-self: center;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  background: var(--surface);
  border: 1px dashed var(--line-strong);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--muted);
}

.arch-endpoint svg {
  width: 15px;
  height: 15px;
  color: var(--cobalt);
}

.arch-conn {
  align-self: center;
  width: 2px;
  height: 24px;
  background: linear-gradient(180deg, var(--line-strong), var(--sky));
}

.arch-conn--up {
  background: linear-gradient(180deg, var(--sky), var(--line-strong));
}

.arch-shell {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: linear-gradient(180deg, #edf3f7, #f7fafc);
  padding: 28px 22px 22px;
  display: grid;
  gap: 12px;
}

.arch-shell-tag {
  position: absolute;
  top: -11px;
  left: 22px;
  padding: 3px 12px;
  background: var(--ink);
  color: #fff;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
}

.arch-layer {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 16px 18px;
}

.arch-layer-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.arch-layer-name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
}

.arch-layer-tech {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
}

.arch-mods {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.arch-mod {
  padding: 6px 12px;
  border-radius: 8px;
  background: var(--surface-soft);
  border: 1px solid var(--soft-line);
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--body);
}

.arch-layer--fe {
  border-color: #bfe0ec;
}

.arch-layer--fe .arch-mod {
  background: #eaf6fb;
  border-color: #d3ebf4;
  color: var(--cobalt-deep);
}

.arch-layer--data {
  background: var(--cobalt);
  border-color: var(--cobalt);
}

.arch-layer--data .arch-layer-name {
  color: #fff;
}

.arch-layer--data .arch-layer-tech {
  color: rgba(255, 255, 255, 0.8);
}

.arch-mod--data {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.28);
  color: #fff;
}

.arch-bridge {
  justify-self: center;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 14px;
  border-radius: 999px;
  background: var(--sky-soft);
  color: var(--cobalt-deep);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.03em;
}

/* ============================================================
   开源与资源致谢（#credits）
   ============================================================ */
.credits-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.credit-cat {
  padding: 22px 24px;
}

.credit-cat h3 {
  margin-bottom: 12px;
}

.credit-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
}

.credit-list li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--soft-line);
}

.credit-list li:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.credit-list a {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 14.5px;
  color: var(--ink);
  text-decoration: none;
}

.credit-list a:hover {
  color: var(--cobalt);
  text-decoration: underline;
}

.credit-list .desc {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--muted);
  text-align: right;
}

.credit-list .lic {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--surface-soft);
  border: 1px solid var(--soft-line);
  color: var(--muted);
  white-space: nowrap;
}

/* ============================================================
   友情链接（#links）
   ============================================================ */
.links-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 12px;
}

.link-card {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  text-decoration: none;
  transition: border-color 140ms ease, transform 140ms ease, box-shadow 140ms ease;
}

.link-card:hover {
  border-color: var(--cobalt);
  transform: translateY(-2px);
  box-shadow: var(--shadow-soft);
}

.link-card .lk-name {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
}

.link-card .lk-name svg {
  width: 15px;
  height: 15px;
  color: var(--muted);
  flex-shrink: 0;
}

.link-card .lk-desc {
  font-family: var(--font-sans);
  font-size: 13px;
  color: var(--muted);
}

.link-card--placeholder {
  border-style: dashed;
  background: var(--surface-soft);
}

.link-card--placeholder .lk-name {
  color: var(--muted);
}

@media (max-width: 760px) {
  .ds-twin,
  .base-grid,
  .credits-grid {
    grid-template-columns: 1fr;
  }

  .arch-layer-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
  }
}

/* ============================================================
   电影感运镜系统 ·「一镜到底 · 场景接力」
   整页像一台摄影机在一块连续幕布上推进：底色随滚动游移、顶部进度
   光束持续推进、相邻段落在交界处淡入淡出地交接、架构图随镜头下沉
   逐层点亮——中间没有硬切。

   健壮性（三重兜底，绝不把内容藏没）：
   1. 一切初始隐藏 / 运镜都包在 @media (prefers-reduced-motion:
      no-preference)；开启「减少动态效果」时整套退化为静态直显。
   2. 滚动驱动（scrub）走 CSS scroll-driven animations
      （animation-timeline: view()/scroll()）：跑在合成线程、可被滚动
      随时打断、不卡主线程，用 @supports 包裹。不支持的浏览器走
      @supports not 分支里的 IntersectionObserver 触发式揭示作兜底。
   3. 所有初始隐藏都额外要求 .has-js（JS 启用）；关掉 JS 内容照常显示，
      首屏也不会先显示再隐藏（无 FOUC）。
   位移一律用独立的 translate / scale 属性（不占用 transform），因此
   不影响卡片 hover 的 transform 抬升，两者互不覆盖。
   ============================================================ */

/* 开启「减少动态」时连平滑滚动也关掉，尊重系统设置 */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

/* ---- 连续底幕：固定全屏，居于内容之下（那块「镜头从不离开的空间」）---- */
.cine {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: clip;
}

/* 内容浮在底幕之上 */
main,
.footer {
  position: relative;
  z-index: 1;
}

.cine-aurora {
  position: absolute;
  inset: -16%;
}

/* 两层品牌色极光：天青在上、深钴在下，随滚动此消彼长 → 空间色相由
   天青游移到深钴，做出「镜头一路下沉」的连续感。透明度压得很低，
   保证直接落在页面底色上的标题 / 正文依旧清晰可读。 */
.cine-aurora::before,
.cine-aurora::after {
  content: "";
  position: absolute;
  inset: 0;
}

.cine-aurora::before {
  background:
    radial-gradient(48% 42% at 16% 10%, rgba(79, 185, 216, 0.26), transparent 72%),
    radial-gradient(52% 46% at 90% 24%, rgba(79, 185, 216, 0.19), transparent 74%),
    /* 中部 teal「章节」停靠：让色相旅程在天青→深钴之间多一个过渡停点 */
    radial-gradient(46% 50% at 50% 46%, rgba(51, 151, 195, 0.18), transparent 70%);
}

.cine-aurora::after {
  background:
    radial-gradient(50% 44% at 82% 80%, rgba(23, 117, 173, 0.28), transparent 74%),
    radial-gradient(56% 48% at 12% 90%, rgba(15, 86, 135, 0.17), transparent 76%);
  opacity: 0.5;
}

/* 顶部运镜进度光束：默认不存在（无 scroll-driven 支持时不留痕迹），
   仅在支持 + 允许动态时出现，随整页滚动从左推到右——那条「正在走的胶片」。 */
.cine-beam {
  display: none;
}

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .cine-aurora {
      animation: cv-aurora-drift linear both;
      animation-timeline: scroll(root block);
    }

    .cine-aurora::before {
      animation: cv-fade-out linear both;
      animation-timeline: scroll(root block);
    }

    .cine-aurora::after {
      animation: cv-fade-in linear both;
      animation-timeline: scroll(root block);
    }

    .cine-beam {
      display: block;
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 3px;
      z-index: 30;
      transform-origin: 0 50%;
      transform: scaleX(0);
      background: linear-gradient(90deg, var(--sky), var(--cobalt));
      animation: cv-beam linear both;
      animation-timeline: scroll(root block);
    }
  }
}

@keyframes cv-aurora-drift {
  from {
    translate: 0 -10%;
  }
  35% {
    translate: 3% -2%;
  }
  70% {
    translate: 4% 8%;
  }
  to {
    translate: 0 15%;
  }
}
@keyframes cv-fade-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0.15;
  }
}
@keyframes cv-fade-in {
  from {
    opacity: 0.2;
  }
  to {
    opacity: 0.95;
  }
}
@keyframes cv-beam {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

/* ---- 运镜关键帧 ---- */
@keyframes cv-rise {
  from {
    opacity: 0;
    translate: 0 60px;
    scale: 0.93;
  }
  74% {
    opacity: 1;
    translate: 0 -5px;
    scale: 1.012;
  }
  to {
    opacity: 1;
    translate: 0 0;
    scale: 1;
  }
}

/* 卡片翻转入场：从下方带透视旋转上浮，到位前轻微过冲回弹（更有弹性） */
@keyframes cv-card-flip {
  from {
    opacity: 0;
    translate: 0 84px;
    scale: 0.84;
    rotate: x 12deg;
  }
  68% {
    opacity: 1;
  }
  85% {
    translate: 0 -9px;
    scale: 1.018;
    rotate: x -2deg;
  }
  to {
    opacity: 1;
    translate: 0 0;
    scale: 1;
    rotate: x 0deg;
  }
}

/* 推近入场：从远处放大 */
/* 预览浮窗入场：克制上浮 + 轻微缩放，与区块卡片同一节奏（不再从远处大推近） */
@keyframes cv-preview-in {
  from {
    opacity: 0;
    scale: 0.965;
    translate: 0 34px;
  }
  to {
    opacity: 1;
    scale: 1;
    translate: 0 0;
  }
}

@keyframes cv-zoom-in {
  from {
    opacity: 0;
    scale: 0.8;
    translate: 0 44px;
  }
  60% {
    opacity: 1;
  }
  to {
    opacity: 1;
    scale: 1;
    translate: 0 0;
  }
}

/* 从左侧滑入 */
@keyframes cv-slide-left {
  from {
    opacity: 0;
    translate: -100px 24px;
    scale: 0.92;
  }
  80% {
    opacity: 1;
    translate: 7px -4px;
  }
  to {
    opacity: 1;
    translate: 0 0;
    scale: 1;
  }
}

/* 从右侧滑入 */
@keyframes cv-slide-right {
  from {
    opacity: 0;
    translate: 100px 24px;
    scale: 0.92;
  }
  80% {
    opacity: 1;
    translate: -7px -4px;
  }
  to {
    opacity: 1;
    translate: 0 0;
    scale: 1;
  }
}
@keyframes cv-rise-sharpen {
  from {
    opacity: 0;
    translate: 0 60px;
    filter: blur(9px);
  }
  to {
    opacity: 1;
    translate: 0 0;
    filter: blur(0);
  }
}
/* 小节标签出场：随上一幕滑出顶部时后退淡出（与入场 cv-rise-sharpen 配对 ·
   exit 区间专用 · forwards 填充，入场阶段不回写、两条动画互不打架）*/
@keyframes cv-recede {
  from {
    opacity: 1;
    translate: 0 0;
  }
  to {
    opacity: 0;
    translate: 0 -40px;
  }
}
/* 标题出场：仅向上轻移做视差「镜头推过」、不淡出 → 全程可读 */
@keyframes cv-driftup {
  from {
    translate: 0 0;
  }
  to {
    translate: 0 -52px;
  }
}
/* 卡片 / 面板出场：淡出 + 上移 + 轻微缩小（比 cv-recede 多一点纵深感）。
   forwards 专用：只在 exit 区间填充，入场段不回写。 */
@keyframes cv-recede-scale {
  from {
    opacity: 1;
    translate: 0 0;
    scale: 1;
  }
  to {
    opacity: 0;
    translate: 0 -60px;
    scale: 0.9;
  }
}
/* #preview 钉住放大装配：从远处（0.72×、略低）推近落定。scrub 驱动，
   滚动越快推得越快。配合 .preview-embed{overflow:hidden} 不会溢出。 */
/* #preview 钉住段：入场「发酵鼓胀」+ 出场「卷饼上卷」（需父级 perspective + origin 底边）*/
@keyframes cv-bread-rise {
  from {
    opacity: 0;
    scale: 0.55 0.18;
    rotate: x 26deg;
    border-radius: 90px;
  }
  52% {
    opacity: 1;
  }
  80% {
    scale: 1.03 1.05;
    rotate: x -4deg;
    border-radius: 24px;
  }
  to {
    opacity: 1;
    scale: 1 1;
    rotate: x 0deg;
    border-radius: 16px;
  }
}
@keyframes cv-wrap-rollup {
  from {
    opacity: 1;
    scale: 1 1;
    rotate: x 0deg;
    translate: 0 0;
    border-radius: 16px;
  }
  35% {
    opacity: 1;
    border-radius: 64px;
  }
  to {
    opacity: 0;
    scale: 0.84 0.12;
    rotate: x 78deg;
    translate: 0 -42%;
    border-radius: 130px;
  }
}

@media (prefers-reduced-motion: no-preference) {
  /* ===== Hero 开场：纯 CSS 载入动画（与滚动无关，所有支持动态的浏览器一致）===== */
  .has-js .hero .eyebrow,
  .has-js .hero h1,
  .has-js .hero .lead,
  .has-js .hero .hero-actions,
  .has-js .hero .hero-meta,
  .has-js .hero .product-frame {
    opacity: 0;
    animation: cv-rise 0.72s cubic-bezier(0.22, 0.61, 0.36, 1) both;
  }
  .has-js .hero .eyebrow {
    animation-delay: 0.05s;
  }
  .has-js .hero h1 {
    animation-delay: 0.14s;
  }
  .has-js .hero .lead {
    animation-delay: 0.26s;
  }
  .has-js .hero .hero-actions {
    animation-delay: 0.38s;
  }
  .has-js .hero .hero-meta {
    animation-delay: 0.5s;
  }
  .has-js .hero .product-frame {
    animation-delay: 0.3s;
  }

  /* ===== 兜底：不支持 scroll-driven 时，用 JS 的 IntersectionObserver 触发揭示 ===== */
  @supports not (animation-timeline: view()) {
    .has-js .section-head,
    .has-js .grid.features > .card,
    .has-js .ds-block,
    .has-js .showcase > .panel,
    .has-js .preview-stage,
    .has-js .preview-actions > .button,
    .has-js .arch-endpoint,
    .has-js .arch-shell,
    .has-js .arch-layer,
    .has-js .arch-bridge,
    .has-js .credit-cat,
    .has-js .timeline > .step,
    .has-js .stack,
    .has-js .links-grid > * {
      opacity: 0;
      translate: 0 40px;
      scale: 0.95;
      transition:
        opacity 0.7s cubic-bezier(0.22, 0.61, 0.36, 1),
        translate 0.7s cubic-bezier(0.22, 0.61, 0.36, 1),
        scale 0.7s cubic-bezier(0.22, 0.61, 0.36, 1);
    }

    .has-js .grid.features > .card {
      translate: 0 50px;
      scale: 0.9;
      rotate: x 6deg;
    }

    .has-js .showcase > .panel:first-child,
    .has-js .ds-block:nth-child(odd) {
      translate: -40px 20px;
    }

    .has-js .showcase > .panel:last-child,
    .has-js .ds-block:nth-child(even) {
      translate: 40px 20px;
    }

    .has-js .preview-stage {
      translate: 0 30px;
      scale: 0.965;
    }

    .has-js .is-visible {
      opacity: 1 !important;
      translate: 0 0 !important;
      scale: 1 !important;
      rotate: none !important;
    }
  }

  /* ===== 主路径：scroll-driven「场景接力」（scrub · 跟滚动进度连续驱动）===== */
  @supports (animation-timeline: view()) {
    /* 小节标签：上浮锐化入场 + 离开顶部时后退淡出 = 段落「场景接力」。
       入场 / 出场拆成两条动画各管一段区间（出场 forwards 不回写入场段）*/
    .has-js .section-label {
      animation: cv-rise-sharpen linear both, cv-recede linear forwards;
      animation-timeline: view(), view();
      animation-range: cover 4% cover 30%, exit 0% exit 55%;
    }

    /* 标题：上浮锐化入场 + 离开顶部时向上轻移视差（不淡出，全程可读）*/
    .has-js .section-head h2 {
      opacity: 0;
      animation: cv-rise-sharpen linear both, cv-driftup linear forwards;
      animation-timeline: view(), view();
      animation-range: cover 2% cover 32%, exit 0% exit 100%;
    }
    /* 导语：上浮锐化入场 + 离开顶部时后退淡出，与上一幕交接（不再定死）*/
    .has-js .section-head .section-intro {
      opacity: 0;
      animation: cv-rise-sharpen linear both, cv-recede linear forwards;
      animation-timeline: view(), view();
      animation-range: cover 6% cover 38%, exit 10% exit 65%;
    }

    /* 各类卡片 / 板块：scroll-driven 入场，不同类型用不同动画增加变化感 */

    /* Feature 卡片：从下方旋转滑入 + 缩放，有立体感。
       区间后移到「卡片进入可视阅读区」才渐显（之前 cover 0%~36% 在视口
       下缘就放完，滚快了根本看不到）。3 列网格按「行」错位：第 1 行
       (1·2·3) 先、第 2 行 (4·5·6) 整体延后，形成一行一行接力的渐显。 */
    .has-js .grid.features > .card {
      opacity: 0;
      animation: cv-card-flip linear both, cv-recede-scale linear forwards;
      animation-timeline: view(), view();
      animation-range: cover 10% cover 40%, exit 6% exit 50%;
    }
    /* 第 2 行整体延后；同排同区间齐步升起，避免同排高低不齐（功能区 4 列，第 2 行自第 5 张起）*/
    .has-js .grid.features > .card:nth-child(n + 5) {
      animation-range: cover 22% cover 52%, exit 16% exit 60%;
    }

    /* Preview 预览区：从远处推近。区间略后移，让推近发生在可视区内而非
       视口下缘（与功能卡片同样的考量）。注意：本框内含 poster/iframe，
       变换溢出已由 .preview-embed{overflow:hidden} 兜住，幅度安全。 */
    .has-js .preview-stage {
      opacity: 0;
      animation: cv-preview-in linear both;
      animation-timeline: view();
      animation-range: cover 6% cover 40%;
    }

    /* 预览区下方三按钮：之前完全无动画 → 整节偏静。改为错位渐显上浮，
       在预览框落定后依次升起，给这节一个收尾节奏。 */
    .has-js .preview-actions > .button {
      opacity: 0;
      animation: cv-rise linear both, cv-recede linear forwards;
      animation-timeline: view(), view();
      animation-range: cover 30% cover 64%, exit 12% exit 62%;
    }
    .has-js .preview-actions > .button:nth-child(2) { animation-range: cover 36% cover 70%, exit 18% exit 68%; }
    .has-js .preview-actions > .button:nth-child(3) { animation-range: cover 42% cover 76%, exit 24% exit 74%; }

    /* 设计系统板块：从侧边滑入 + 离场上移淡出（增强非钉住画廊，逐块接力）*/
    .has-js .ds-block {
      opacity: 0;
      animation: cv-slide-left linear both, cv-recede-scale linear forwards;
      animation-timeline: view(), view();
      animation-range: cover 2% cover 38%, exit 8% exit 55%;
    }
    .has-js .ds-twin > .ds-block:last-child {
      animation-name: cv-slide-right, cv-recede-scale;
    }

    /* Showcase 面板：左边从左滑入、右边从右滑入；离场上移淡出 */
    .has-js .showcase > .panel:first-child {
      opacity: 0;
      animation: cv-slide-left linear both, cv-recede-scale linear forwards;
      animation-timeline: view(), view();
      animation-range: cover 4% cover 40%, exit 8% exit 56%;
    }
    .has-js .showcase > .panel:last-child {
      opacity: 0;
      animation: cv-slide-right linear both, cv-recede-scale linear forwards;
      animation-timeline: view(), view();
      animation-range: cover 4% cover 40%, exit 8% exit 56%;
    }

    /* 通用：致谢、时间轴、标签等 —— 入场上浮 + 离场后退淡出，全程跟滚动 */
    .has-js .credit-cat,
    .has-js .timeline > .step,
    .has-js .stack,
    .has-js .links-grid > * {
      opacity: 0;
      animation: cv-rise linear both, cv-recede linear forwards;
      animation-timeline: view(), view();
      animation-range: cover 6% cover 40%, exit 10% exit 60%;
    }

    /* 开源深色段时间轴：5 步自上而下错峰接力（.timeline 仅此段出现，安全）*/
    .has-js .opensource .timeline > .step:nth-child(1) { animation-range: cover 6% cover 40%, exit 10% exit 60%; }
    .has-js .opensource .timeline > .step:nth-child(2) { animation-range: cover 11% cover 45%, exit 14% exit 64%; }
    .has-js .opensource .timeline > .step:nth-child(3) { animation-range: cover 16% cover 50%, exit 18% exit 68%; }
    .has-js .opensource .timeline > .step:nth-child(4) { animation-range: cover 21% cover 55%, exit 22% exit 72%; }
    .has-js .opensource .timeline > .step:nth-child(5) { animation-range: cover 26% cover 60%, exit 26% exit 76%; }

    /* #links 为最后一屏内容（下方仅 footer），没有足够下方行程让 cover 走完，
       原 cover 区间会让它停在半显（~0.69）。统一用更早完成的 cover 区间，
       进入视口即揭示到位；离场区间留着但它本来就不会滚出顶部、不会触发。 */
    .has-js #links .section-head .section-label,
    .has-js #links .section-head h2,
    .has-js #links .section-head .section-intro,
    .has-js #links .links-grid > * {
      animation-range: cover 0% cover 22%, exit 10% exit 60%;
    }

    /* 不做「同排错峰」：同一排卡片用同一区间齐步升起。否则停在揭示中途时
       同排各卡进度不同 → 高低不齐（最后一列尤其明显，要悬停触发重绘才归位）。
       跨排的先后由各自 view() 时间线天然错开（上排先于下排），既有自上而下的
       揭示节奏，又保证每一排内部始终对齐。 */
  }
}

/* ============================================================
   电影化滚动手法 · Cerulean 浅色调性 · 纯 CSS 轻量
   ① 深色全幅「换场」段 + 巨型数字（#privacy）
   ② 粘性钉住 + 要点轮替高亮（.privacy-pin / .privacy-point）
   ③ 金库 / 预览图随滚动视差 / 缩放（.vault / .preview-embed .poster）
   仍遵循三重兜底：reduced-motion 退化静态、@supports 包裹 scroll-driven、
   .has-js 守初始态，绝不把内容藏没。
   ============================================================ */

/* ---- ①② 深色全幅段：本地优先宣言（亮→暗→亮 的「换场」）---- */
.privacy {
  position: relative;
  padding: clamp(72px, 10vh, 128px) 0;
  background: linear-gradient(168deg, #0b2133 0%, #0f2e47 52%, #123c5c 100%);
  color: #e9f2f8;
}

.privacy-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  gap: 56px;
  align-items: start;
}

/* 视差背景「参照物」：大号描边水印，独立层自带 overflow（不波及 .privacy-pin 的 sticky）*/
.privacy-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
}
.privacy-watermark {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: clamp(96px, 19vw, 280px);
  letter-spacing: -0.04em;
  line-height: 1;
  white-space: nowrap;
  color: transparent;
  -webkit-text-stroke: 1.5px rgba(173, 216, 240, 0.12);
}

/* ② 钉住：左列宣言随右列滚动而保持在视口（sticky 锚点）*/
.privacy-pin {
  position: sticky;
  top: 18vh;
  align-self: start;
}

.privacy .section-label {
  color: rgba(180, 210, 230, 0.82);
}
.privacy .section-label::before {
  background: rgba(160, 196, 220, 0.55);
}

.privacy-title {
  color: #fff;
  font-size: clamp(30px, 4vw, 50px);
  line-height: 1.12;
  letter-spacing: -0.02em;
  max-width: 16ch;
}

.privacy-figures {
  margin-top: 36px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.privacy-fig {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* ① 巨型数字：天青渐变描字，在深底上强对比、强存在感 */
.stat-figure {
  font-family: var(--font-mono);
  font-size: clamp(38px, 6vw, 70px);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.03em;
  background: linear-gradient(92deg, #8ad6ee, #4fb9d8 60%, #2f9fce);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.privacy-fig-label {
  font-family: var(--font-sans);
  font-size: 13.5px;
  color: rgba(201, 222, 236, 0.74);
}

.privacy-points {
  display: flex;
  flex-direction: column;
  /* 大幅拉开要点间距 → 右列远高于左列 → 左侧宣言 sticky 钉住停留更久
     （之前右列太矮，左列几乎没停就被带过去，「一滑就过」）。
     窄屏由下方 @media(max-width:920px) 重置回紧凑间距，避免单列过长。 */
  gap: clamp(60px, 24vh, 240px);
  padding: clamp(24px, 10vh, 120px) 0;
}

.privacy-point {
  --pdepth: 0px;
  padding: 2px 0 2px 24px;
  border-left: 2px solid rgba(173, 201, 222, 0.18);
}

.privacy-point-idx {
  display: block;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  color: var(--sky);
}

.privacy-point h3 {
  color: #fff;
  font-size: clamp(20px, 2.4vw, 26px);
  margin-top: 8px;
}

.privacy-point p {
  margin: 10px 0 0;
  color: rgba(206, 226, 240, 0.72);
  font-family: var(--font-serif);
  font-size: 16px;
  line-height: 1.66;
  max-width: 46ch;
}

@media (max-width: 920px) {
  .privacy-grid {
    grid-template-columns: 1fr;
    gap: 36px;
  }
  /* 窄屏取消钉住，恢复正常流，避免与单列内容重叠 */
  .privacy-pin {
    position: static;
  }
  .privacy-points {
    gap: 28px;
    padding: 0;
  }
}

/* ============================================================
   深色章节段：开源协作（#credits 亮 → #opensource 暗 → #links 亮，收尾换幕，
   与 #privacy 同范式）。只改色、不改布局：靠 `.opensource …` 更高特异性覆盖基础
   规则的颜色。步骤卡改为半透明玻璃、序号徽章与标签改为天青系，避免深色上「深徽章
   消失 / 浅标签违和」。reduced-motion / 无 JS / 老浏览器下就是一段静态深色可读区。
   ============================================================ */
.opensource {
  position: relative;
  padding: clamp(72px, 10vh, 128px) 0;
  background: linear-gradient(156deg, #0a1f2e 0%, #0d2a3f 48%, #11344a 100%);
  color: #dde8f0;
}
.opensource .section-label {
  color: rgba(168, 196, 220, 0.82);
}
.opensource .section-label::before {
  background: rgba(160, 196, 220, 0.55);
}
.opensource .section-head h2 {
  color: #fff;
}
.opensource .section-intro {
  color: rgba(206, 226, 240, 0.74);
}
/* 步骤卡：浅底白卡 → 半透明玻璃，与深底融为一幕 */
.opensource .step {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(168, 196, 220, 0.18);
}
/* 序号徽章原为 var(--ink) 深色，在深底上会消失 → 改天青系 */
.opensource .step::before {
  background: rgba(79, 185, 216, 0.16);
  color: #9fdcef;
}
.opensource .step h3 {
  color: #fff;
}
.opensource .step p {
  color: rgba(200, 220, 235, 0.72);
}
/* 标签：浅底深字 → 半透明天青描边，深底上清晰 */
.opensource .tag {
  background: rgba(79, 185, 216, 0.08);
  border-color: rgba(79, 185, 216, 0.32);
  color: #9fdcef;
}
.opensource .tag:hover {
  border-color: var(--sky);
  background: rgba(79, 185, 216, 0.18);
  color: #fff;
}

/* ---- 上述手法的 scroll-driven 增强（全部包在 @supports + reduced-motion）---- */

/* 整页滚动驱动：Hero 区不再做 vault parallax（Stage 已承担开场视差），
   避免与入场动画冲突 + overflow 裁切问题。 */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
  }
}

/* 元素入场驱动（view）：② 要点轮替高亮 + 钉住标签免出场淡出 + ③ 预览图视差 */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* 段落级视差时间线：整段在视口内的滚动进度，驱动背景水印 + 要点错位 */
    .has-js .privacy {
      view-timeline-name: --priv;
      view-timeline-axis: block;
    }
    /* 背景「参照物」水印：随整段滚动反向缓移 + 轻缩放 → 与前景拉开速度差 */
    .has-js .privacy-watermark {
      animation: cv-priv-bg-parallax linear both;
      animation-timeline: --priv;
      animation-range: cover 0% cover 100%;
    }
    /* ② 要点：轮替高亮(view) + 纵向视差错位(--priv，每条速率 --pdepth 不同) */
    .has-js .privacy-point {
      opacity: 0.42;
      animation: cv-spotlight linear both, cv-priv-point-drift linear both;
      animation-timeline: view(), --priv;
      animation-range: cover 28% cover 72%, cover 0% cover 100%;
    }
    /* 仅桌面做要点错位（窄屏间距小，错位会重叠）*/
    @media (min-width: 921px) {
      .has-js .privacy-point:nth-child(1) { --pdepth: 46px; }
      .has-js .privacy-point:nth-child(2) { --pdepth: 30px; }
      .has-js .privacy-point:nth-child(3) { --pdepth: 16px; }
      .has-js .privacy-point:nth-child(4) { --pdepth: 4px; }
    }

    /* 钉住的宣言标签是 sticky 锚点，不套用通用 .section-label 的出场淡出 */
    .has-js .privacy .section-label {
      animation: none;
      opacity: 1;
      translate: 0 0;
    }

    /* ③ 预览大图：facade 海报随滚动做轻微纵向视差（载入 iframe 后即无） */
    .has-js .preview-embed .poster {
      animation: cv-shot-parallax linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 100%;
    }
  }
}

/* #privacy 段落视差关键帧：背景水印与前景要点反向移动 → 强烈相对运动 */
@keyframes cv-priv-bg-parallax {
  from {
    translate: 0 -14%;
    scale: 1.05;
  }
  to {
    translate: 0 14%;
    scale: 1;
  }
}
@keyframes cv-priv-point-drift {
  from {
    translate: 0 var(--pdepth, 0px);
  }
  to {
    translate: 0 calc(var(--pdepth, 0px) * -1);
  }
}

/* ===== 架构图滚动装配（钉住高舞台 · 部件随滚动按数据流逐个落位、堆叠成整图）=====
   仅此分支把 .arch-stage 撑高 + .arch-pin 钉住；不支持 scroll-driven / 减少动态 /
   无 JS 时都不生效，架构图回到普通流的静态整图（见 .arch-stage 基础规则 +
   @supports not(view()) 的 IO 兜底）。部件用内联 --i 定装配顺序，统一由挂在
   .arch-stage 上的命名 view-timeline --arch 驱动，逐个错峰、互不串扰；滚回去自动逆向拆解。 */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* 高舞台：提供约 1 屏的「钉住期」行程，并作为命名时间线源 */
    .has-js .arch-stage {
      /* 200vh：钉住期约 1 屏行程即可完成装配（原 260vh 中段留白过长） */
      min-height: 200vh;
      view-timeline-name: --arch;
      view-timeline-axis: block;
    }
    /* 钉住容器：滚动期间把架构图固定在视口中央，整图原地装配 */
    .has-js .arch-pin {
      position: sticky;
      top: 0;
      min-height: 100vh;
      display: grid;
      place-items: center;
    }

    /* 外框在 entry 段就淡入到位：舞台滚入即见骨架，锚点跳转不落空屏 */
    .has-js .arch-stage .arch-shell {
      opacity: 0;
      animation: cv-arch-frame linear both;
      animation-timeline: --arch;
      animation-range: entry 25% entry 75%;
    }
    /* 端点 + 各层：重物砸落 + 触底承重挤压（自底部挤压 = 落地受力）*/
    .has-js .arch-stage .arch-endpoint,
    .has-js .arch-stage .arch-layer {
      opacity: 0;
      transform-origin: 50% 100%;
      animation: cv-arch-slam linear both;
      animation-timeline: --arch;
      animation-range: contain calc((11 - var(--i)) * 4%) contain calc((11 - var(--i)) * 4% + 14%);
    }
    /* 地基端点（装配首件）提前到 entry 段，钉住一开始就有落位物 */
    .has-js .arch-stage .arch-endpoint:last-child {
      animation-range: entry 40% entry 95%;
    }
    /* 连接线：自下而上「画」出（顺序随地基→顶端反转）*/
    .has-js .arch-stage .arch-conn {
      opacity: 0;
      transform-origin: 50% 0;
      animation: cv-arch-draw linear both;
      animation-timeline: --arch;
      animation-range: contain calc((11 - var(--i)) * 4%) contain calc((11 - var(--i)) * 4% + 10%);
    }
    /* 桥接 pill：弹入扣合 */
    .has-js .arch-stage .arch-bridge {
      opacity: 0;
      animation: cv-arch-pop linear both;
      animation-timeline: --arch;
      animation-range: contain calc((11 - var(--i)) * 4%) contain calc((11 - var(--i)) * 4% + 10%);
    }
  }
}

/* 预览钉住期持续动画：缓慢 Ken-Burns（平移 + 轻缩放），始终被 overflow 裁切 */
@keyframes cv-preview-pan {
  from {
    scale: 1.08;
    translate: 0 -3%;
  }
  to {
    scale: 1.12;
    translate: 0 3%;
  }
}

@keyframes cv-hero-parallax {
  from {
    scale: 1;
    translate: 0 0;
  }
  to {
    scale: 1.03;
    translate: 0 -2%;
  }
}
@keyframes cv-spotlight {
  0% {
    opacity: 0.42;
    border-left-color: rgba(173, 201, 222, 0.18);
  }
  50% {
    opacity: 1;
    border-left-color: var(--sky);
  }
  100% {
    opacity: 0.42;
    border-left-color: rgba(173, 201, 222, 0.18);
  }
}
@keyframes cv-shot-parallax {
  from {
    scale: 1.06;
    translate: 0 -2.2%;
  }
  to {
    scale: 1.06;
    translate: 0 2.2%;
  }
}

/* ---- 架构装配关键帧 ---- */
@keyframes cv-arch-frame {
  from {
    opacity: 0;
    scale: 0.98;
  }
  to {
    opacity: 1;
    scale: 1;
  }
}
/* 重物砸落：自上方快速下坠 → 触底挤压（承重）→ 轻微回弹 → 落定。
   配合 transform-origin: 50% 100%（自底部挤压，像落地受力）；
   --from-y 越大越「重」（下落更高、冲击更明显）。scale 第二值 = 纵向挤压，
   纯纵向不横向溢出。scrub 驱动：滚动越快砸得越快、越慢越像慢动作回放。 */
@keyframes cv-arch-slam {
  0% {
    opacity: 0;
    translate: 0 calc(var(--from-y, -46px) * 4);
    scale: 1 1.07;
  }
  20% {
    opacity: 1;
  }
  46% {
    opacity: 1;
    translate: 0 0;
    scale: 1 1;
  }
  60% {
    translate: 0 0;
    scale: 1 0.82;
  }
  78% {
    translate: 0 -6px;
    scale: 1 1.04;
  }
  100% {
    opacity: 1;
    translate: 0 0;
    scale: 1 1;
  }
}
/* 连接线：纵向画出（配合 transform-origin: 50% 0）*/
@keyframes cv-arch-draw {
  from {
    opacity: 0;
    scale: 1 0;
  }
  to {
    opacity: 1;
    scale: 1 1;
  }
}
/* 桥接 pill：弹入扣合 */
@keyframes cv-arch-pop {
  from {
    opacity: 0;
    scale: 0.82;
  }
  to {
    opacity: 1;
    scale: 1;
  }
}

/* ============================================================
   交互增强系统
   ============================================================ */

/* ---- 1. 导航链接动画下划线 ---- */
.nav-links a {
  position: relative;
}

.nav-links a:not(.button)::after {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 6px;
  height: 2px;
  background: var(--cobalt);
  border-radius: 1px;
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 220ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.nav-links a:not(.button):hover::after,
.nav-links a:not(.button).is-active::after {
  transform: scaleX(1);
}

.nav-links a.is-active {
  color: var(--cobalt);
}

/* ---- 2. 功能卡片鼠标追踪光效 + 3D 倾斜 ---- */
.grid.features {
  perspective: 1200px;
}

.grid.features .card {
  --mx: 50%;
  --my: 50%;
  --rx: 0deg;
  --ry: 0deg;
  position: relative;
  overflow: hidden;
  transform-style: preserve-3d;
  transition: border-color 160ms ease, box-shadow 160ms ease, transform 280ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.grid.features .card::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(
    320px circle at var(--mx) var(--my),
    rgba(79, 185, 216, 0.12),
    transparent 60%
  );
  opacity: 0;
  transition: opacity 300ms ease;
}

.grid.features .card:hover::after {
  opacity: 1;
}

/* 悬停态 = 应用 card-hover token 的网页版：底色 accent-tint-soft、描边天青 #4FB9D8 */
.grid.features .card:hover {
  transform: rotateX(var(--rx)) rotateY(var(--ry));
  background: var(--accent-tint-soft);
  border-color: var(--sky);
  box-shadow: 0 20px 40px -16px rgba(23, 117, 173, 0.22);
}

@media (prefers-reduced-motion: reduce) {
  .grid.features .card:hover {
    transform: none;
  }
  .grid.features .card::after {
    display: none;
  }
}

/* ---- 3. 返回顶部按钮 ---- */
.back-to-top {
  position: fixed;
  bottom: 28px;
  right: 28px;
  z-index: 50;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--cobalt);
  display: grid;
  place-items: center;
  cursor: pointer;
  box-shadow: 0 8px 24px -8px rgba(15, 46, 71, 0.2);
  opacity: 0;
  transform: translateY(12px) scale(0.9);
  pointer-events: none;
  transition: opacity 300ms ease, transform 300ms ease, background 140ms ease, border-color 140ms ease;
}

.back-to-top.is-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}

.back-to-top:hover {
  background: var(--cobalt);
  color: #fff;
  border-color: var(--cobalt);
}

.back-to-top svg {
  width: 20px;
  height: 20px;
}

/* ---- 5. 架构图层交互高亮 ---- */
.arch-shell .arch-layer {
  transition: opacity 200ms ease, transform 200ms ease, box-shadow 200ms ease;
}

.arch-shell:hover .arch-layer {
  opacity: 0.55;
}

.arch-shell:hover .arch-layer:hover {
  opacity: 1;
  transform: scale(1.015);
  box-shadow: 0 6px 20px -6px rgba(23, 117, 173, 0.2);
  z-index: 2;
  position: relative;
}

.arch-shell:hover .arch-bridge {
  opacity: 0.45;
  transition: opacity 200ms ease;
}

@media (prefers-reduced-motion: reduce) {
  .arch-shell:hover .arch-layer:hover {
    transform: none;
  }
}

/* ---- 6. 移动端汉堡菜单 ---- */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  cursor: pointer;
  margin-left: auto;
  flex-shrink: 0;
}

.nav-toggle span {
  display: block;
  width: 18px;
  height: 2px;
  background: var(--ink);
  border-radius: 1px;
  position: relative;
  transition: background 200ms ease;
}

.nav-toggle span::before,
.nav-toggle span::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--ink);
  border-radius: 1px;
  transition: transform 200ms ease, top 200ms ease;
}

.nav-toggle span::before {
  top: -6px;
}

.nav-toggle span::after {
  top: 6px;
}

.nav.is-open .nav-toggle span {
  background: transparent;
}

.nav.is-open .nav-toggle span::before {
  top: 0;
  transform: rotate(45deg);
}

.nav.is-open .nav-toggle span::after {
  top: 0;
  transform: rotate(-45deg);
}

@media (max-width: 920px) {
  .nav {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    padding: 14px 0;
  }

  .nav-toggle {
    display: flex;
  }

  .nav-links {
    display: none;
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    margin-left: 0;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--line);
  }

  .nav.is-open .nav-links {
    display: flex;
  }

  .nav-links a {
    justify-content: flex-start;
  }
}

/* ---- 7. Privacy 数字 hover 放大 ---- */
.privacy-fig {
  transition: transform 200ms ease;
}

.privacy-fig:hover {
  transform: scale(1.04);
}

.privacy-fig:hover .stat-figure {
  filter: brightness(1.15);
}

/* ---- 8. Tag 标签 hover 弹跳 ---- */
.tag {
  transition: border-color 140ms ease, background 140ms ease, transform 180ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.tag:hover {
  transform: translateY(-2px) scale(1.03);
}

/* ---- 9. 时间轴步骤 hover ---- */
.step {
  transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms ease;
}

.step:hover {
  transform: translateX(4px);
  border-color: var(--sky);
  box-shadow: var(--shadow);
}

@media (prefers-reduced-motion: reduce) {
  .privacy-fig:hover,
  .tag:hover,
  .step:hover {
    transform: none;
  }
}

/* ---- 10. 路线图状态药丸 ---- */
.rm-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  margin-bottom: 12px;
  padding: 3px 11px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  border: 1px solid transparent;
}

.rm-status::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
}

.rm-done {
  color: var(--success);
  background: color-mix(in srgb, var(--success) 12%, transparent);
  border-color: color-mix(in srgb, var(--success) 30%, transparent);
}

.rm-wip {
  color: #b87f1f;
  background: color-mix(in srgb, #e8b35a 16%, transparent);
  border-color: color-mix(in srgb, #e8b35a 38%, transparent);
}

.rm-plan {
  color: var(--cobalt);
  background: color-mix(in srgb, var(--cobalt) 10%, transparent);
  border-color: color-mix(in srgb, var(--cobalt) 26%, transparent);
}

/* ============================================================
   11. 功能区 / 路线图：in-flow 揭示（2026-07-02 起不再钉住——
   钉住高舞台在锚点跳转与中速滚动下会露出大片空屏）。卡片揭示由
   通用 .grid.features > .card 的 view() 时间线承担，此处仅保留
   路线图进度条；不支持 scroll-driven 时仍走 IO 兜底揭示。
   ============================================================ */

/* 路线图进度条：默认不存在，仅运镜可用时出现并随滚动从 0 填满 */
.road-progress {
  display: none;
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* ---- 功能区 / 路线图：不再钉住（钉住高舞台在锚点跳转与中速滚动下
       会露出大片空屏，见截图复盘）。卡片走通用 .grid.features > .card 的
       in-flow view() 揭示：一行一行接力升起，页面长度即内容长度。 ---- */

    /* 路线图进度条：挂自身 view() 时间线，滚入路线区时从 0 填满 */
    .has-js .road-progress {
      display: block;
      position: relative;
      width: min(760px, 100%);
      height: 3px;
      margin: 0 auto 32px;
      border-radius: 999px;
      background: var(--soft-line);
      overflow: hidden;
    }
    .has-js .road-progress span {
      position: absolute;
      inset: 0;
      transform-origin: 0 50%;
      transform: scaleX(0);
      background: linear-gradient(90deg, var(--success), #e8b35a 55%, var(--cobalt));
      animation: cv-beam linear both;
      animation-timeline: view();
      animation-range: entry 60% cover 55%;
    }
    /* 注：设计区不做「标题钉住」——其色板/渐变/组件画廊远高于一屏，sticky 标题
       会让卡片从标题背后滚过造成重叠（见 feedback/37）。设计区维持原有的
       逐块侧滑揭示（.ds-block / .showcase 的 view() 动画），不钉住、不重叠。 */
  }
}

/* ============================================================
   12. Hero 落地屏补回运镜（原 Hero 只有一次性入场 + 取景框内的捕获演示，
   落定后整屏静止 —— 见用户反馈「整体没什么动画」）。这里补三处，全部
   gated by no-preference：① 渐变标题待机流光（不滚也在动）② 取景框待机
   轻浮（整框移动，祖先不裁切，安全）③ 文字列随 Hero 滚出时上移视差。
   ============================================================ */
@media (prefers-reduced-motion: no-preference) {
  /* ① 待机流光：渐变标题缓慢流动，落地屏不再静止（背景裁切到文字，无溢出风险）*/
  .has-js .hero h1 .grad {
    background-size: 240% 100%;
    animation: cv-grad-shimmer 8.5s ease-in-out infinite;
  }
  /* ② 取景框待机轻浮：入场 cv-rise 跑完后接一段无限缓浮。两条都是时间轴动画，
     不与滚动时间线冲突；移动的是整个 .product-frame，其祖先不裁切，故安全。
     （此规则在文件末尾，覆盖前面 .hero .product-frame 的入场声明 + 0.3s 延迟）*/
  .has-js .hero .product-frame {
    animation:
      cv-rise 0.72s cubic-bezier(0.22, 0.61, 0.36, 1) 0.3s both,
      cv-frame-float 7.5s ease-in-out 1.6s infinite;
  }
}

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* ③ 文字列：Hero 滚出顶部时整列上移（视差），与取景框拉开速度差。
       仅 exit 区间触发，不影响首屏载入态；下方区块滚上来即遮住，无裁切问题。 */
    .has-js .hero-grid > div:first-child {
      animation: cv-driftup linear both;
      animation-timeline: view();
      animation-range: exit 0% exit 100%;
    }
  }
}

@keyframes cv-grad-shimmer {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}
@keyframes cv-frame-float {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 -7px; }
}

/* ============================================================
   中等高度（701–870px，常见于 Windows 125% 缩放的 1080p 屏）：
   保留钉住运镜，但压缩卡片与架构图，使钉住的一屏装得下全部内容。 */
@supports (animation-timeline: view()) {
  @media (min-width: 921px) and (min-height: 701px) and (max-height: 870px) {
    /* 架构图：压纵向留白为主，字号基本不动（整体大比例 zoom 会把
       11-13px 的正文缩到 9px 级，实测不可读，见 feedback/49）。 */
    .has-js .arch-pin .arch {
      zoom: 0.92;
    }
    .has-js .arch-pin .arch-conn {
      height: 12px;
    }
    .has-js .arch-pin .arch-shell {
      padding: 20px 18px 16px;
      gap: 8px;
    }
    .has-js .arch-pin .arch-layer {
      padding: 10px 14px;
    }
    .has-js .arch-pin .arch-layer-head {
      margin-bottom: 8px;
    }
    .has-js .arch-pin .arch-mod {
      padding: 4px 10px;
    }
    .has-js .arch-pin .arch-bridge {
      padding: 3px 12px;
    }
    .has-js .arch-pin .arch-endpoint {
      padding: 6px 14px;
    }
  }
}

/* ============================================================
   矮窗口 / 窄屏兜底：视口高度装不下「钉住一屏 + 居中的架构整图」，
   或窄屏下内容纵向堆叠远超一屏时，取消架构图的钉住运镜，回退为
   正常流式排布 —— 内容完整可见、不被 sticky 顶栏遮挡、也不会上下
   裁切。仅在支持 scroll-driven 时需要（不支持时本就是正常流 + IO 揭示）。 */
@supports (animation-timeline: view()) {
  @media (max-height: 700px), (max-width: 920px) {
    .has-js .arch-stage {
      min-height: auto;
      padding-block: 4px 40px;
    }
    .has-js .arch-pin {
      position: static;
      min-height: auto;
      padding-top: 0;
      display: block;
    }
    .has-js .arch-stage .arch-shell,
    .has-js .arch-stage .arch-endpoint,
    .has-js .arch-stage .arch-layer,
    .has-js .arch-stage .arch-conn,
    .has-js .arch-stage .arch-bridge {
      opacity: 1;
      animation: none;
    }
  }
}

/* ============================================================
   动效细节专区（#motion）
   用网页原生 CSS/SVG 复刻应用标志性微交互：复制反馈 / 主题过渡 /
   卡片悬停 / 白板连线。每张卡自洽、可悬停可点击。
   ============================================================ */
#motion {
  padding: clamp(48px, 7vh, 80px) 0;
}

.motion-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
  margin-top: 8px;
}

@media (max-width: 760px) {
  .motion-grid {
    grid-template-columns: 1fr;
  }
}

.motion-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 20px;
  border-radius: var(--radius-lg);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-soft);
}

.motion-head h3 {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
}

.motion-head p {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 13px;
  line-height: 1.6;
  color: var(--muted);
}

.motion-head code {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--cobalt);
  background: var(--sky-soft);
  padding: 1px 5px;
  border-radius: 5px;
}

.motion-stage {
  position: relative;
  margin-top: auto;
  min-height: 156px;
  border-radius: var(--radius);
  background: linear-gradient(160deg, #eef4f8, #e2ebf2);
  border: 1px solid var(--soft-line);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 18px;
  overflow: hidden;
}

/* 通用类型徽章 */
.m-kind {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  padding: 2px 7px;
  border-radius: 5px;
  color: var(--cobalt);
  background: rgba(23, 117, 173, 0.12);
}
.m-kind--text {
  color: #2e7d6b;
  background: rgba(60, 178, 133, 0.16);
}
.m-clip-meta {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
}

/* —— 1 · 复制反馈 —— */
.m-clip {
  position: relative;
  width: 100%;
  max-width: 280px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: 0 6px 16px -10px rgba(15, 46, 71, 0.3);
  transition: box-shadow 0.25s ease, border-color 0.25s ease;
}
.m-clip.is-copied {
  border-color: var(--sky);
  box-shadow: 0 0 0 3px rgba(79, 185, 216, 0.35), 0 8px 22px -10px rgba(23, 117, 173, 0.4);
}
.m-clip-body {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink);
  word-break: break-all;
}
.m-copy {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 7px;
  border: 1px solid var(--line);
  background: var(--surface-soft);
  color: var(--cobalt);
  cursor: pointer;
  transition: background 0.15s ease, transform 0.12s ease, border-color 0.15s ease;
}
.m-copy svg {
  width: 15px;
  height: 15px;
}
.m-copy:hover {
  background: var(--sky-soft);
  border-color: var(--sky);
}
.m-copy:active {
  transform: scale(0.9);
}
.m-bubble {
  position: absolute;
  top: 8px;
  right: 44px;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  background: var(--success);
  padding: 3px 9px;
  border-radius: 999px;
  opacity: 0;
  transform: translateY(6px);
  pointer-events: none;
}
.m-bubble.show {
  animation: cv-m-bubble 1.1s ease forwards;
}
@keyframes cv-m-bubble {
  0% { opacity: 0; transform: translateY(6px) scale(0.9); }
  22% { opacity: 1; transform: translateY(0) scale(1); }
  78% { opacity: 1; transform: translateY(-2px) scale(1); }
  100% { opacity: 0; transform: translateY(-12px) scale(0.96); }
}

/* —— 2 · 主题过渡（迷你应用）—— */
.m-mini {
  --mm-bg: #f1f5f8;
  --mm-surface: #ffffff;
  --mm-line: #d3dee6;
  --mm-ink: #2c3e50;
  --mm-muted: #93a4b3;
  --mm-accent: #2c7bb6;
  width: 100%;
  max-width: 280px;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--mm-line);
  background: var(--mm-bg);
  box-shadow: 0 8px 20px -12px rgba(15, 46, 71, 0.35);
  transition: background 0.5s ease, border-color 0.5s ease;
}
.m-mini[data-mode="dark"] {
  --mm-bg: #161b21;
  --mm-surface: #1f262d;
  --mm-line: #2e3741;
  --mm-ink: #e8edf2;
  --mm-muted: #9daab6;
  --mm-accent: #4fb9d8;
}
.m-mini-bar {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 7px 10px;
  background: var(--mm-surface);
  border-bottom: 1px solid var(--mm-line);
  transition: background 0.5s ease, border-color 0.5s ease;
}
.m-mini-bar i {
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--mm-muted);
  opacity: 0.55;
}
.m-mini-title {
  margin-left: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--mm-ink);
  transition: color 0.5s ease;
}
.m-mini-body {
  display: flex;
  min-height: 92px;
}
.m-mini-side {
  width: 64px;
  padding: 9px 8px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  background: var(--mm-surface);
  border-right: 1px solid var(--mm-line);
  transition: background 0.5s ease, border-color 0.5s ease;
}
.m-row {
  height: 7px;
  border-radius: 4px;
  background: var(--mm-line);
  transition: background 0.5s ease;
}
.m-row--on {
  background: var(--mm-accent);
}
.m-mini-list {
  flex: 1;
  padding: 9px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.m-mini-cell {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 8px;
  border-radius: 7px;
  background: var(--mm-surface);
  border: 1px solid var(--mm-line);
  transition: background 0.5s ease, border-color 0.5s ease;
}
.m-mini-cell .m-tag {
  font-family: var(--font-mono);
  font-size: 8px;
  font-weight: 600;
  padding: 1px 4px;
  border-radius: 4px;
  color: var(--mm-accent);
  background: color-mix(in srgb, var(--mm-accent) 16%, transparent);
}
.m-mini-cell b {
  flex: 1;
  height: 6px;
  border-radius: 3px;
  background: var(--mm-ink);
  opacity: 0.7;
  transition: background 0.5s ease;
}
.m-mini-cell i {
  width: 18px;
  height: 6px;
  border-radius: 3px;
  background: var(--mm-muted);
  opacity: 0.5;
  transition: background 0.5s ease;
}
.m-switch {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 6px 12px 6px 7px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface);
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--body);
  transition: border-color 0.15s ease;
}
.m-switch:hover {
  border-color: var(--sky);
}
.m-switch-knob {
  position: relative;
  width: 34px;
  height: 18px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--sky), var(--cobalt));
  flex-shrink: 0;
  transition: background 0.3s ease;
}
.m-switch-knob::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 999px;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.m-switch[aria-checked="true"] .m-switch-knob::after {
  transform: translateX(16px);
}

/* —— 3 · 卡片悬停 —— */
.motion-stage--hover {
  perspective: 700px;
}
.m-hcard {
  position: relative;
  width: 100%;
  max-width: 280px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px;
  border-radius: var(--radius);
  background: var(--surface);
  border: 1px solid var(--line);
  cursor: default;
  transition: transform 0.28s cubic-bezier(0.22, 0.61, 0.36, 1),
    box-shadow 0.28s ease, border-color 0.2s ease;
}
.m-hcard-body {
  font-family: var(--font-sans);
  font-size: 13.5px;
  color: var(--ink);
}
.m-hactions {
  position: absolute;
  top: 10px;
  right: 12px;
  display: flex;
  gap: 6px;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.22s ease, transform 0.22s ease;
}
.m-hbtn {
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 7px;
  background: var(--surface-soft);
  border: 1px solid var(--line);
  color: var(--cobalt);
}
.m-hbtn svg {
  width: 14px;
  height: 14px;
}
.m-hbtn:hover {
  background: var(--sky-soft);
  border-color: var(--sky);
}
.m-hhint {
  font-family: var(--font-sans);
  font-size: 11px;
  color: var(--muted);
  transition: opacity 0.2s ease;
}
.m-hcard:hover {
  transform: translateY(-6px) rotateX(3deg);
  border-color: var(--sky);
  box-shadow: 0 16px 34px -16px rgba(23, 117, 173, 0.5);
}
.m-hcard:hover .m-hactions {
  opacity: 1;
  transform: translateY(0);
}
.m-hcard:hover .m-hhint {
  opacity: 0;
}

/* —— 4 · 白板连线 —— */
.motion-stage--wb {
  background: linear-gradient(160deg, #eef4f8, #e2ebf2);
}
.motion-stage--wb::before {
  /* 白板网格底纹 */
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(23, 117, 173, 0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(23, 117, 173, 0.06) 1px, transparent 1px);
  background-size: 22px 22px;
}
.m-wb-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: var(--cobalt);
}
.m-wb-link {
  stroke-dasharray: 220;
  stroke-dashoffset: 220;
  animation: cv-m-wbdraw 2.6s cubic-bezier(0.65, 0, 0.35, 1) infinite;
}
.motion-stage--wb:hover .m-wb-link {
  animation-duration: 1.3s;
}
@keyframes cv-m-wbdraw {
  0% { stroke-dashoffset: 220; }
  45% { stroke-dashoffset: 0; }
  80% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 0.85; }
}
.m-node {
  position: absolute;
  font-family: var(--font-sans);
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--sky);
  padding: 7px 13px;
  border-radius: 9px;
  box-shadow: 0 6px 16px -10px rgba(15, 46, 71, 0.4);
}
.m-node--a {
  left: 11%;
  top: 22%;
}
.m-node--b {
  right: 11%;
  bottom: 22%;
  border-color: var(--cobalt);
}

@media (prefers-reduced-motion: reduce) {
  .m-bubble.show {
    animation: none;
    opacity: 1;
  }
  .m-wb-link {
    animation: none;
    stroke-dashoffset: 0;
  }
}

/* 动效卡入场（支持 scroll-driven 时随视图错峰浮现；否则由 .is-visible 兜底） */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .has-js .motion-card {
      opacity: 0;
      animation: cv-rise 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) both;
      animation-timeline: view();
      animation-range: entry 0% cover 26%;
    }
  }
}

/* ============================================================
   设计系统 · 品牌标识锚点（#design 内）
   真实应用 logo 在设计系统里露出，作为色板/字体的源头。
   ============================================================ */
.ds-brand-row {
  display: flex;
  align-items: center;
  gap: 28px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.ds-logos {
  display: flex;
  align-items: flex-end;
  gap: 16px;
}
.ds-logo {
  display: grid;
  place-items: center;
  border-radius: 24%;
  background: radial-gradient(72% 72% at 50% 42%, #1f86c1, #004872);
  box-shadow: 0 12px 28px -12px rgba(23, 117, 173, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.ds-logo svg {
  width: 62%;
  height: 62%;
}
.ds-logo--xl { width: 92px; height: 92px; border-radius: 22px; }
.ds-logo--md { width: 56px; height: 56px; border-radius: 15px; }
.ds-logo--sm { width: 34px; height: 34px; border-radius: 9px; }
.ds-brand-meta {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
  min-width: 220px;
}
.ds-brand-meta li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--font-sans);
  font-size: 13px;
}
.ds-bk {
  flex: none;
  width: 64px;
  color: var(--muted);
}
.ds-bv {
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 12.5px;
}

/* ── 字标构成解析：C 分件 / P 分件 / 合体三联图 ──
   C、P 的多边形 = 真实字标 path 的两个字母分件（共用竖笔 x220-280），
   合体图叠深钴矩形标出共用竖笔、白点标出对称中心 (250,250)；
   悬停合体图整体旋转 180°——因中心对称，轮廓与自身完全重合。 */
.ds-anatomy {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin: 16px 0 18px;
}

.ds-anatomy-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 16px 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-soft);
  /* 与白板小样同款点阵底，暗示「构成网格」 */
  background-image: radial-gradient(rgba(23, 117, 173, 0.1) 1px, transparent 1.2px);
  background-size: 16px 16px;
}

.ds-anatomy-tile svg {
  width: 96px;
  height: 96px;
}

.ds-anatomy-tile .ds-ghost {
  fill: none;
  stroke: var(--line-strong);
  stroke-width: 6;
  stroke-dasharray: 14 12;
}

.ds-anatomy-label {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--muted);
  text-align: center;
}

@media (prefers-reduced-motion: no-preference) {
  .ds-anatomy-tile--merge svg {
    transition: transform 0.8s cubic-bezier(0.22, 0.61, 0.36, 1);
  }
  .ds-anatomy-tile--merge:hover svg {
    transform: rotate(180deg);
  }
}

@media (max-width: 600px) {
  .ds-anatomy {
    gap: 8px;
  }
  .ds-anatomy-tile svg {
    width: 72px;
    height: 72px;
  }
}
