/* ==========================================================================
   RecArtist 设计系统
   风格取向：深色、克制、以产品截图为主体。参考 screen.studio 的信息密度与
   留白节奏，但配色与品牌走自己的路线（靛蓝 → 紫罗兰渐变）。
   ========================================================================== */

:root {
  /* 背景层次：越靠上层越亮，用亮度差替代边框来分层 */
  --bg-base: #08080c;
  --bg-raised: #0e0e14;
  --bg-card: #121219;
  --bg-elevated: #17171f;
  --bg-input: #0b0b11;

  /* 文字：主/次/弱三级，避免出现纯白造成刺眼 */
  --text-primary: #f4f4f7;
  --text-secondary: #a6a6b4;
  /* 三级文字亮度由对比度反推，不是凭手感调的：
     最亮的常见底色是「半透明标签叠在卡片上」≈ rgb(35,35,41)，
     要在它之上达到 WCAG AA 的 4.5:1，文字灰度至少要 138。取 #8f8f9e 留出余量，
     实测在该底色上 4.90:1、在最深的 #08080c 上 6.27:1。
     原值 #6e6e7d 只有 3.13~3.99，全站 59 处不达标。 */
  --text-tertiary: #8f8f9e;

  --border: rgba(255, 255, 255, 0.08);
  --border-strong: rgba(255, 255, 255, 0.14);

  --brand: #6366f1;
  --brand-bright: #8b8cf9;
  --brand-deep: #4f46e5;
  --accent: #a855f7;
  --accent-cyan: #22d3ee;
  --success: #34d399;
  --warning: #fbbf24;

  --gradient-brand: linear-gradient(135deg, #6366f1 0%, #a855f7 100%);
  --gradient-text: linear-gradient(120deg, #c7c8ff 0%, #ffffff 40%, #d8b4fe 100%);

  --radius-sm: 8px;
  --radius-md: 14px;
  --radius-lg: 20px;
  --radius-xl: 28px;

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.4), 0 12px 32px rgba(0, 0, 0, 0.35);
  --shadow-float: 0 24px 70px rgba(0, 0, 0, 0.6), 0 4px 12px rgba(0, 0, 0, 0.5);
  --shadow-glow: 0 0 0 1px rgba(99, 102, 241, 0.35), 0 18px 50px rgba(99, 102, 241, 0.22);

  --container: 1200px;
  --gutter: 24px;

  /* 产品演示媒体的唯一比例：1920 / 1020 = 1.8824。
     取自素材原生像素（编辑器窗口 1920×1020），不是拍脑袋定的；
     全站 9 张演示截图 + hero 主图 + 画廊图全是这个尺寸。
     ⚠ 视频是 1920×1080（1.7778），与截图**不同**——正因为不同才必须
       由容器钉死比例，否则「视频按自己的比例、截图按自己的比例」两种高度混排。
     改这个值 = 改全站演示媒体比例，页面里不用再逐处改。 */
  --media-ar: 1920 / 1020;

  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
    "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", sans-serif;
  --font-mono: "JetBrains Mono", "SFMono-Regular", Consolas, "Liberation Mono", monospace;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ------------------------------------------------------------------ 重置 */

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: 90px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg-base);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body::before {
  /* 顶部氛围光：给深色页面一个视觉锚点，不是装饰性渐变堆砌 */
  content: "";
  position: fixed;
  inset: 0 0 auto 0;
  height: 900px;
  background:
    radial-gradient(900px 480px at 50% -8%, rgba(99, 102, 241, 0.20), transparent 70%),
    radial-gradient(600px 360px at 88% 4%, rgba(168, 85, 247, 0.13), transparent 72%);
  pointer-events: none;
  z-index: 0;
}

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

/* ★★ height: auto 必须写在**全局复位**里，而不是只写在演示图那一段（第二百九十五批）。
   原因不是"代码整洁"，是故障模式：
     `<img width="1920" height="1020">` 里的 height 是**呈现性提示**，等价于
     内联 `height:1020px`；它只输给作者样式（任何选择器都行），但**不会**输给
     `max-width:100%` —— 于是宽度被压到 613px、高度还是 1020px，图片被横向
     压扁 3 倍（比例 0.6 而不是 1.88）。
   上一批只在 `.feature-row__media img` 上写了 height:auto，而 CSS 缓存 1 小时、
   HTML 是 no-cache ⇒ 用户会拿到"新 HTML + 旧 CSS"，正好绕过那条局部规则，
   比修复前更糟。**写在复位里 = 覆盖面与页面/组件无关，任何一次错配都不会变形。** */
img, video { height: auto; }

/* <picture> 只是格式协商的壳（webp 优先、png 兜底），本身不承载任何视觉。
   用 display: contents 让它不产生盒子，<img> 直接作为父容器的子项参与布局，
   与引入 <picture> 之前的布局完全一致——否则 picture 默认是 inline，
   却包着 display:block 的 img，在 flex / grid 容器里还会改变尺寸计算，
   图片尺寸和间距会莫名其妙地变。 */
picture { display: contents; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 650;
  letter-spacing: -0.028em;
  line-height: 1.12;
}

p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }

::selection { background: rgba(99, 102, 241, 0.4); color: #fff; }

:focus-visible {
  outline: 2px solid var(--brand-bright);
  outline-offset: 3px;
  border-radius: 4px;
}

/* -------------------------------------------------------------- 布局容器 */

.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
  position: relative;
  z-index: 1;
}

.section { padding: 104px 0; position: relative; z-index: 1; }
.section--tight { padding: 72px 0; }

.section-head { max-width: 760px; margin-bottom: 56px; }
.section-head--center { margin-left: auto; margin-right: auto; text-align: center; }

.section-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-bright);
  margin-bottom: 18px;
}

.section-label::before {
  content: "";
  width: 22px;
  height: 1px;
  background: var(--brand-bright);
  opacity: 0.6;
}

.section-title {
  font-size: clamp(1.9rem, 3.4vw, 2.85rem);
  margin-bottom: 18px;
}

.section-sub {
  color: var(--text-secondary);
  font-size: 1.0625rem;
  line-height: 1.65;
}

.gradient-text {
  background: var(--gradient-text);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* ------------------------------------------------------------------ 导航 */

/*
 * 发布预告条（第三百三十七批）。
 *
 * 它**不是**装饰：产品尚未公开发布，首页此前写的是「v0.1.0 已发布」并把主按钮
 * 指向下载页 —— 页面自己就在承诺一件做不到的事。这条横条把"还没有正式发布"
 * 这个事实放在整页最上面一行，且带一个通往订阅表单的入口，
 * 让"想买的人"有地方留下邮箱，而不是只能失望离开。
 *
 * 放在 <nav> 之前而不是里面：nav 是 sticky，横条跟着滚动走掉是对的
 * （它只需要被看见一次，不需要一直占着屏幕）。
 */
.announce {
  background:
    linear-gradient(90deg, rgba(99, 102, 241, 0.30), rgba(139, 140, 249, 0.14) 55%, rgba(99, 102, 241, 0.30));
  border-bottom: 1px solid rgba(99, 102, 241, 0.38);
}

.announce__inner {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 9px 16px;
  font-size: 13.5px;
  line-height: 1.45;
  color: #dcdcff;
  text-align: center;
}

/* 状态标签用琥珀色：整站的绿色圆点（.dot）语义是"在线/可用"，
   这里恰恰相反，沿用绿色会让读者以为已经能用了。 */
.announce__tag {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid rgba(251, 191, 36, 0.45);
  background: rgba(251, 191, 36, 0.14);
  color: #fcd34d;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  flex-shrink: 0;
}

.announce__text { color: #e8e8ff; }

.announce__cta {
  color: #ffffff;
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.45);
  padding-bottom: 1px;
  white-space: nowrap;
}

.announce__cta:hover { border-bottom-color: #ffffff; }

/* 订阅表单被当作 CTA 的落点时，跳锚要避开 sticky 导航（否则标题被压在导航下面）。 */
#notify { scroll-margin-top: 84px; }

.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  background: rgba(8, 8, 12, 0.72);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s, background 0.3s;
}

.nav.is-scrolled {
  border-bottom-color: var(--border);
  background: rgba(8, 8, 12, 0.9);
}

.nav__inner {
  display: flex;
  align-items: center;
  gap: 20px;
  height: 68px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 680;
  font-size: 1.0625rem;
  letter-spacing: -0.02em;
  flex-shrink: 0;
  /* 触控目标下限：品牌链接近 27px 高，手机上不好点 */
  min-height: 34px;
}

.brand__mark {
  width: 30px;
  height: 30px;
  border-radius: 9px;
  background: var(--gradient-brand);
  display: grid;
  place-items: center;
  box-shadow: 0 4px 14px rgba(99, 102, 241, 0.42);
  flex-shrink: 0;
}

.brand__mark svg { width: 17px; height: 17px; }

.nav__links {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: 14px;
}

.nav__link {
  padding: 8px 13px;
  border-radius: var(--radius-sm);
  font-size: 0.9375rem;
  color: var(--text-secondary);
  transition: color 0.2s, background 0.2s;
  white-space: nowrap;
}

.nav__link:hover { color: var(--text-primary); background: rgba(255, 255, 255, 0.05); }
.nav__link.is-active { color: var(--text-primary); }

.nav__right { margin-left: auto; display: flex; align-items: center; gap: 10px; }

/* --------------------------------------------------- 价格入口（单一形态）
   第三百批：价格改成 `nav__links` 里的**普通导航链接**，位置在「常见问题」之后
   （用户要求：`"价格"放到"常见问题"后，风格和"常见问题"一致`）。

   ★ 297 批那套「宽屏按钮 + 窄屏面板链接」的两形态互斥**已删干净**，这不是单纯的
     视觉简化，而是消掉了一整类故障：两形态要靠断点保证"任何宽度下恰好 1 个入口"，
     断点一改就会同时出现两个，而双入口在截图里最难被发现（两处措辞还不同：
     价格 / 定价）。现在**同一个元素**覆盖两个宽度 —— 宽屏在导航行里，≤860px 随
     `.nav__links` 一起收进汉堡面板，不存在"显示哪个"的分支，也就无从错配。
   ⚠ 因此这里**不需要**任何价格专属规则。别再加回来：一旦给价格单独写
     display/断点，就重新引入了"两条渲染路径要互相对齐"的负担。
     当前页高亮复用既有的 `.nav__link.is-active`（见上）。 */

/* 语言切换：分段控件比下拉更直观，且少一次交互 */
.lang-switch {
  display: inline-flex;
  padding: 3px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--border);
  /* 不能被 flex 挤压：窄屏下压缩会让「中文」折成竖排两行 */
  flex-shrink: 0;
}

.lang-switch button {
  border: 0;
  background: transparent;
  color: var(--text-tertiary);
  font-size: 12.5px;
  font-weight: 600;
  padding: 5px 11px;
  border-radius: 999px;
  white-space: nowrap;
  /* 触控目标下限：不加这个按钮只有 26px 高 */
  min-height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: color 0.2s, background 0.2s;
}

.lang-switch button.is-active {
  background: rgba(255, 255, 255, 0.11);
  color: var(--text-primary);
}

.nav__toggle {
  display: none;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  border-radius: var(--radius-sm);
  width: 38px;
  height: 38px;
  color: var(--text-primary);
  place-items: center;
}

/* --------------------------------------------------- 收藏本站（一键收藏）
   浏览器的安全模型不允许 JS 直接触发收藏对话框（window.external.AddFavorite
   是 IE 时代的遗物，现代浏览器全部禁用），所以这个按钮能真实交付的是两件事：
   ①把当前网址复制到剪贴板；②告诉用户最后一步按什么（Ctrl+D / ⌘D / 手机菜单）。
   别试图模拟 keydown 的 Ctrl+D —— 页面根本收不到浏览器保留快捷键的合成事件。 */
.bookmark-wrap { position: relative; flex-shrink: 0; }

.nav__bookmark {
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.04);
  border-radius: var(--radius-sm);
  width: 38px;
  height: 38px;
  color: var(--text-primary);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: color 0.2s, border-color 0.2s, background 0.2s;
}

.nav__bookmark svg { width: 17px; height: 17px; }

.nav__bookmark:hover {
  color: #fff;
  border-color: rgba(255, 255, 255, 0.35);
  background: rgba(255, 255, 255, 0.08);
}

.nav__bookmark.is-done { color: var(--accent, #7c9cff); }

.bookmark-pop {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 60;
  white-space: nowrap;
  padding: 9px 14px;
  border-radius: 10px;
  background: #0a0a10;
  border: 1px solid var(--border);
  color: var(--text-primary);
  font-size: 12.5px;
  font-weight: 500;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  animation: bookmarkPopIn 0.18s ease-out;
}

.bookmark-pop::before {
  content: '';
  position: absolute;
  top: -5px;
  right: 14px;
  width: 8px;
  height: 8px;
  background: #0a0a10;
  border-left: 1px solid var(--border);
  border-top: 1px solid var(--border);
  transform: rotate(45deg);
}

@keyframes bookmarkPopIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

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

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 13px 24px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
  transition: transform 0.2s var(--ease), box-shadow 0.25s, background 0.25s, border-color 0.25s;
}

.btn svg { width: 17px; height: 17px; flex-shrink: 0; }

.btn--primary {
  background: var(--gradient-brand);
  color: #fff;
  box-shadow: 0 6px 20px rgba(99, 102, 241, 0.34);
}

.btn--primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 10px 30px rgba(99, 102, 241, 0.46);
}

.btn--ghost {
  background: rgba(255, 255, 255, 0.05);
  border-color: var(--border-strong);
  color: var(--text-primary);
}

.btn--ghost:hover { background: rgba(255, 255, 255, 0.09); border-color: rgba(255, 255, 255, 0.22); }

.btn--sm { padding: 9px 17px; font-size: 0.875rem; }
.btn--lg { padding: 16px 30px; font-size: 1rem; }
.btn--block { width: 100%; }

.btn[disabled], .btn.is-disabled {
  opacity: 0.42;
  cursor: not-allowed;
  transform: none !important;
  box-shadow: none;
}

/* ------------------------------------------------------------------ 徽标 */

.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: rgba(255, 255, 255, 0.04);
  font-size: 13px;
  color: var(--text-secondary);
}

.pill--brand {
  border-color: rgba(99, 102, 241, 0.42);
  background: rgba(99, 102, 241, 0.13);
  color: #c9caff;
}

.dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 0 3px rgba(52, 211, 153, 0.18);
  flex-shrink: 0;
}

.dot--muted { background: var(--text-tertiary); box-shadow: none; }

/* ★ 修饰类必须写在基础类**之后**：`.dot` 与 `.dot--soon` 选择器权重相同（各一个类），
   同权重下后来者胜。第一版把这条写在 `.dot` 之前（第 260 行），
   于是圆点在浏览器里仍是绿色 rgb(52,211,153) —— 而类名却是 dot--soon，
   只查 class 的判据一条都看不见它。位置与 `.dot--muted` 保持一致。 */
.dot--soon { background: #fbbf24; box-shadow: 0 0 0 3px rgba(251, 191, 36, 0.18); }

/* ------------------------------------------------------------------ Hero */

.hero {
  padding: 78px 0 64px;
  text-align: center;
  position: relative;
  z-index: 1;
}

.hero__badge { margin-bottom: 26px; }

.hero__title {
  font-size: clamp(2.4rem, 6vw, 4.35rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.06;
  margin-bottom: 24px;
}

.hero__sub {
  max-width: 660px;
  margin: 0 auto 34px;
  font-size: clamp(1rem, 1.6vw, 1.1875rem);
  color: var(--text-secondary);
  line-height: 1.6;
}

.hero__actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.hero__meta {
  font-size: 13.5px;
  color: var(--text-tertiary);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
}

.hero__meta span { display: inline-flex; align-items: center; gap: 6px; }

/* 产品截图：屏幕外发光 + 透视，是整页视觉重心 */
.hero__shot {
  margin-top: 58px;
  position: relative;
}

.hero__shot::before {
  content: "";
  position: absolute;
  inset: 8% 6% -10% 6%;
  background: radial-gradient(closest-side, rgba(99, 102, 241, 0.34), transparent 78%);
  filter: blur(52px);
  z-index: 0;
}

.hero__frame {
  position: relative;
  z-index: 1;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-strong);
  background: var(--bg-raised);
  padding: 8px;
  box-shadow: var(--shadow-float);
  overflow: hidden;
}

/* ---------------------------------------------------- 演示媒体（统一比例）
   ★ 这一段同时修三个各自独立的坑，缺一个都会让"比例看起来不固定"：

   ① height: auto —— 必须写。HTML 里的 height="1020" 会被当成
      height:1020px 的**呈现性提示**参与排版，而 CSS 当时只覆盖了 width:100%。
      结果：1920×1020 的截图被渲染成 614×616（比例 0.996 而不是 1.8824），
      纵向拉伸近 1.9 倍。这不是"比例没固定"，是**图片被压变形了**。

   ② aspect-ratio —— 在素材下载完成**之前**就把高度占住。
      视频没有它时：高度先按 poster 算（1.8824），元数据一到变成 16:9（1.7778）
      ⇒ 高度从 326 跳到 345，整块往下顶，下方所有内容跟着抖（CLS）。

   ③ object-fit —— 图片用 contain（产品界面一像素都不能裁）；
      视频用 cover（只裁屏幕录制外缘的窗口标题栏 / 任务栏，约 5.5% 高），
      换来演示行与截图行**完全等高**。9 个媒体块的容器高度从此只由比例决定，
      与素材尺寸、加载时序都无关。 */
.hero__frame img,
.feature-row__media img,
.feature-row__media video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: var(--media-ar);
  border-radius: var(--radius-md);
}

.hero__frame img,
.feature-row__media img { object-fit: contain; }

/* 视频：铺满比例框，裁掉的是桌面录屏的上下外缘（标题栏 / 任务栏） */
.feature-row__media video {
  object-fit: cover;
  background: var(--bg-base);
}

/* ------------------------------------------------------------ 平台条 */

.platform-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
}

.platform-chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 11px 18px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  font-size: 0.9375rem;
  color: var(--text-secondary);
}

.platform-chip svg { width: 18px; height: 18px; }
.platform-chip--active { border-color: rgba(52, 211, 153, 0.35); color: var(--text-primary); }
.platform-chip--muted { opacity: 0.6; }
.platform-chip small { color: var(--text-tertiary); font-size: 12px; }

/* ------------------------------------------------------------------ 卡片 */

.grid { display: grid; gap: 20px; }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* ★★★ 第三百二十三批：三档定价卡专用的列数（列数必须**由卡数派生**）★★★
   来历：310 批团队版下架后定价区只剩 3 张卡，容器却还是 `.grid--4`
   ⇒ 三张卡各占 1/4 宽、整体挤在左侧，右侧空出 293px ≈ 整行 25%。
   ⚠ 为什么另起一个类而不是把 `.grid--4` 改成 `.grid--3`：
     `.grid--3` 在 860px 就塌成单列，而这里 3 张卡在 860px 时还有 257px 宽
     （可读），单列反而把卡片拉到 720px 宽、勾选列表只占左半边（实测截图）。
     `.grid--4` 原来的梯子是 4 → 2（1024）→ 1（620）；本类保留 3 → 2 → 1 的中间档。
   ⇒ 判据不看这套 CSS 写法，只看几何（tools/pricing-probe.js 的 F 组）：
     1280px 下必须"列数==卡数、左右余量≈0、三档等宽等距、关于行中心对称"。 */
.grid--plans { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 26px;
  transition: border-color 0.28s, transform 0.28s var(--ease), background 0.28s;
}

.card--hover:hover {
  border-color: var(--border-strong);
  transform: translateY(-3px);
  background: var(--bg-elevated);
}

.card__icon {
  width: 40px;
  height: 40px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  background: rgba(99, 102, 241, 0.14);
  border: 1px solid rgba(99, 102, 241, 0.24);
  margin-bottom: 16px;
  color: var(--brand-bright);
}

.card__icon svg { width: 20px; height: 20px; }
.card__title { font-size: 1.0625rem; font-weight: 640; margin-bottom: 9px; }
.card__text { color: var(--text-secondary); font-size: 0.9375rem; line-height: 1.62; }

/* 功能大卡：图 + 文，交替左右 */
.feature-row {
  display: grid;
  grid-template-columns: 1fr 1.35fr;
  gap: 56px;
  align-items: center;
}

.feature-row--reverse .feature-row__media { order: 2; }

.feature-row__media {
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--bg-raised);
  padding: 7px;
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

/* 内部 img / video 的圆角与统一比例，由文件上方「演示媒体（统一比例）」段给，
   这里不再重复声明 —— 两处写同一个属性，改一处忘一处就会分叉。 */

.feature-list { display: grid; gap: 14px; margin-top: 26px; }

.feature-list li {
  display: flex;
  gap: 11px;
  font-size: 0.9375rem;
  color: var(--text-secondary);
  line-height: 1.6;
}

.feature-list svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  margin-top: 2px;
  color: var(--success);
}

/* --------------------------------------------------------------- 切换演示 */

.tabs {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--border);
  margin-bottom: 26px;
}

.tabs button {
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  padding: 9px 18px;
  border-radius: 999px;
  font-size: 0.875rem;
  font-weight: 600;
  transition: background 0.22s, color 0.22s;
}

.tabs button.is-active {
  background: var(--gradient-brand);
  color: #fff;
  box-shadow: 0 4px 14px rgba(99, 102, 241, 0.3);
}

.tab-pane { display: none; }
.tab-pane.is-active { display: block; animation: fadeUp 0.42s var(--ease); }

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------- 对比表 */

.spec-table {
  width: 100%;
  border-collapse: collapse;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  font-size: 0.9375rem;
}

.spec-table th,
.spec-table td {
  padding: 15px 20px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}

.spec-table th {
  background: var(--bg-elevated);
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--text-secondary);
}

.spec-table tr:last-child td { border-bottom: 0; }
.spec-table td:first-child { color: var(--text-primary); font-weight: 500; }
.spec-table td { color: var(--text-secondary); }

.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
}

.tag--ok { background: rgba(52, 211, 153, 0.14); color: #6ee7b7; }
.tag--plan { background: rgba(255, 255, 255, 0.07); color: var(--text-tertiary); }
.tag--brand { background: rgba(99, 102, 241, 0.16); color: #c7c8ff; }

/* ------------------------------------------------------------------ 定价 */

.price-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 32px;
  display: flex;
  flex-direction: column;
  position: relative;
}

.price-card--featured {
  border-color: rgba(99, 102, 241, 0.45);
  background: linear-gradient(180deg, rgba(99, 102, 241, 0.09), var(--bg-card) 55%);
  box-shadow: var(--shadow-glow);
}

.price-card__badge {
  position: absolute;
  top: -12px;
  left: 32px;
  padding: 4px 13px;
  border-radius: 999px;
  background: var(--gradient-brand);
  font-size: 12px;
  font-weight: 700;
}

.price-card__name { font-size: 1.125rem; font-weight: 640; margin-bottom: 6px; }
.price-card__desc { color: var(--text-secondary); font-size: 0.875rem; min-height: 42px; }

.price-card__amount {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin: 22px 0 4px;
}

.price-card__amount strong { font-size: 2.6rem; font-weight: 700; letter-spacing: -0.045em; }
.price-card__amount span { color: var(--text-tertiary); font-size: 0.9375rem; }
.price-card__note { font-size: 12.5px; color: var(--text-tertiary); margin-bottom: 24px; }

.price-card ul { display: grid; gap: 12px; margin-bottom: 28px; }
.price-card li { display: flex; gap: 10px; font-size: 0.9375rem; color: var(--text-secondary); }
.price-card li svg { width: 17px; height: 17px; color: var(--success); flex-shrink: 0; margin-top: 3px; }
.price-card .btn { margin-top: auto; }

/* ------------------------------------------------------------------ FAQ */

.faq { display: grid; gap: 10px; }

.faq__item {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-card);
  overflow: hidden;
}

.faq__q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 19px 22px;
  background: transparent;
  border: 0;
  color: var(--text-primary);
  font-size: 0.9688rem;
  font-weight: 580;
  text-align: left;
}

.faq__q svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--text-tertiary);
  transition: transform 0.3s var(--ease);
}

.faq__item.is-open .faq__q svg { transform: rotate(45deg); }

.faq__a {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.34s var(--ease);
}

.faq__a > div {
  padding: 0 22px 21px;
  color: var(--text-secondary);
  font-size: 0.9375rem;
  line-height: 1.68;
}

.faq__a code {
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  background: rgba(255, 255, 255, 0.07);
  padding: 2px 6px;
  border-radius: 5px;
  word-break: break-all;
}

/* ------------------------------------------------------- CTA 与页脚 */

.cta {
  text-align: center;
  padding: 76px 40px;
  border-radius: var(--radius-xl);
  border: 1px solid var(--border-strong);
  background:
    radial-gradient(700px 300px at 50% 0%, rgba(99, 102, 241, 0.24), transparent 70%),
    var(--bg-card);
}

.cta h2 { font-size: clamp(1.7rem, 3.2vw, 2.4rem); margin-bottom: 16px; }
.cta p { color: var(--text-secondary); max-width: 520px; margin: 0 auto 30px; }

.footer {
  border-top: 1px solid var(--border);
  padding: 60px 0 34px;
  margin-top: 40px;
  position: relative;
  z-index: 1;
}

.footer__grid {
  display: grid;
  grid-template-columns: 1.6fr repeat(3, 1fr);
  gap: 44px;
  margin-bottom: 44px;
}

.footer__brand p {
  color: var(--text-tertiary);
  font-size: 0.875rem;
  margin-top: 14px;
  max-width: 290px;
  line-height: 1.65;
}

/* 标题层级：footer 各栏目是 <h3>（父级页面最后一级标题是 h2，不能跳级）。
   这里用标签选择器，改 HTML 的标签名必须同步改这里，否则样式静默丢失。 */
.footer h3 {
  font-size: 0.8125rem;
  font-weight: 640;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  margin-bottom: 16px;
}

.footer li { margin-bottom: 11px; }
.footer li a { color: var(--text-secondary); font-size: 0.9375rem; transition: color 0.2s; }
.footer li a:hover { color: var(--text-primary); }

.footer__bottom {
  padding-top: 26px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 13.5px;
  color: var(--text-tertiary);
}

/* 页脚的法务 / 联系链接组。
   为什么用 flex + gap 而不是行内「·」分隔符：窄屏上一行放不下时，
   行内分隔符会被挤到下一行的行首，出现孤零零一个「·」（首页 hero__meta 踩过同一个坑）。 */
.footer__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 18px;
}

/* 友情链接（外站入口）。三个决定都不是审美，是故障模式：
   ① **单独一行、不进 footer__grid**：语义上它既不属于「产品」也不属于「资源」，
      塞进四列栅格会被当成站内导航的一部分（人这么读，爬虫也这么读）。
   ② **不加自己的 border-top**：它下面紧跟的 `.footer__bottom` 已经有一条 1px 分隔线，
      两条相邻的 1px 线在深色底上会合成一条粗线（第一版就这么翻车的）。
      分隔交给 footer__bottom 那条，这里只给下边距。
   ③ **`flex-wrap` 必须开**：链接会一直加，窄屏 320px 时单行放不下；
      不开 wrap 就是横向溢出（`.footer__legal` 当初踩的是同一个坑）。 */
.footer__partners {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 16px;
  padding-bottom: 22px;
  font-size: 13.5px;
  color: var(--text-tertiary);
}
/* ★★ 第三百零一批：友情链接的可点区域必须 ≥32px（手机触控下限）。
 *
 *   实测：298/299 两批加完两条外链后，`responsive-check` 在 phone / phone-sm 两个
 *   断点的 4 个页面共 8 条全红 —— 链接高度只有 22px（= 13.5px 字号的行高），
 *   手指点上去有一半落在两个链接之间的空白里。
 *
 *   为什么不是"把字号调大"：22px 是 13.5px 文本的自然行高，字号要涨到 20px 才够 32，
 *   而页脚外链在视觉层级上就该是这行小字。可点区域与视觉字号是两件事，
 *   用 `min-height` 把盒子撑到 32px、文字仍在其中垂直居中，两者各自正确。
 *   `inline-flex` 是让 `min-height` 真的生效的前提（inline 元素的盒子高度不可控）。
 *
 *   ⚠ 容器 `gap` 的纵向值从 6px 收到 0：链接自己已经有 32px 的可点高度，
 *     再叠 6px 行距会让这一行在窄屏上占掉 38px×N 条，看起来像漏排的空白。
 *     横向下限 16px 保留 —— 那是两个外链之间的点击间距，不能省。 */
.footer__partners a {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  color: var(--text-secondary);
  transition: color 0.2s;
}
.footer__partners a:hover { color: var(--text-primary); }

/* ---------------------------------------------------------- 订阅表单 */
/* 原先这里是一个指向 /changelog.html 的假 CTA。换成真实表单后需要一点排版：
   标签在输入框之上（可见标签比 placeholder 更可靠 —— placeholder 一输入就消失，
   而且屏幕阅读器对它的支持并不一致）。 */
.subscribe { margin-top: auto; text-align: left; }

.subscribe__label {
  display: block;
  font-size: 12.5px;
  color: var(--text-tertiary);
  margin-bottom: 6px;
}

.subscribe__input {
  width: 100%;
  padding: 10px 13px;
  margin-bottom: 9px;
  border-radius: var(--radius-md, 10px);
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.03);
  color: var(--text-primary);
  font-size: 0.9375rem;
  font-family: inherit;
}

.subscribe__input:focus-visible {
  outline: 2px solid var(--brand-bright);
  outline-offset: 1px;
}

/* 消息文字平时不占位（min-height 保证状态出现时表单不会跳一下）。 */
.subscribe__msg {
  min-height: 18px;
  margin: 8px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--text-tertiary);
}
.subscribe__msg.is-ok { color: #4ade80; }
.subscribe__msg.is-error { color: #fca5a5; }

.subscribe__note {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-tertiary);
}

/* ----------------------------------------------------------- 下载中心 */

.page-head { padding: 62px 0 44px; position: relative; z-index: 1; }
.page-head h1 { font-size: clamp(2rem, 4.2vw, 3rem); margin-bottom: 16px; }
.page-head p { color: var(--text-secondary); max-width: 620px; font-size: 1.0625rem; }

.platform-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px;
}

.platform-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  padding: 26px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  transition: border-color 0.28s, transform 0.28s var(--ease);
}

.platform-card--active {
  border-color: rgba(99, 102, 241, 0.42);
  background: linear-gradient(180deg, rgba(99, 102, 241, 0.1), var(--bg-card) 52%);
}

.platform-card--soon { opacity: 0.62; }
.platform-card--soon:hover { opacity: 0.82; }

.platform-card__top { display: flex; align-items: center; gap: 13px; }
.platform-card__icon {
  width: 42px;
  height: 42px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-secondary);
  flex-shrink: 0;
}

.platform-card--active .platform-card__icon {
  background: rgba(99, 102, 241, 0.16);
  color: var(--brand-bright);
}

.platform-card__icon svg { width: 21px; height: 21px; }
.platform-card__name { font-size: 1.0625rem; font-weight: 640; }
.platform-card__req { font-size: 13px; color: var(--text-tertiary); margin-top: 2px; }
.platform-card .btn { margin-top: auto; }

.release {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 24px;
  align-items: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  padding: 26px 28px;
}

.release + .release { margin-top: 14px; }
.release--latest { border-color: rgba(99, 102, 241, 0.34); }

.release__head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.release__ver { font-size: 1.25rem; font-weight: 680; letter-spacing: -0.02em; }
.release__title { color: var(--text-secondary); font-size: 0.9688rem; margin-bottom: 14px; }

.release__meta {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  font-size: 13px;
  color: var(--text-tertiary);
  font-family: var(--font-mono);
}

.release__meta span { display: inline-flex; align-items: center; gap: 6px; }
.release__actions { display: flex; flex-direction: column; gap: 10px; align-items: stretch; min-width: 190px; }

.hash-box {
  margin-top: 14px;
  padding: 12px 15px;
  border-radius: var(--radius-sm);
  background: var(--bg-input);
  border: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-tertiary);
  word-break: break-all;
  line-height: 1.55;
}

.hash-box strong { color: var(--text-secondary); font-weight: 600; }

.req-list { display: grid; gap: 16px; }
.req-list__row { display: grid; grid-template-columns: 150px 1fr; gap: 20px; font-size: 0.9375rem; }
.req-list__row dt { color: var(--text-tertiary); }
.req-list__row dd { margin: 0; color: var(--text-secondary); }

.note-block {
  padding: 18px 20px;
  border-radius: var(--radius-md);
  border: 1px solid rgba(251, 191, 36, 0.26);
  background: rgba(251, 191, 36, 0.08);
  font-size: 0.9375rem;
  color: #fde68a;
  line-height: 1.65;
}

.stats-strip {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px;
}

.stat-tile {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
  padding: 22px 24px;
}

.stat-tile__value { font-size: 1.9rem; font-weight: 700; letter-spacing: -0.035em; }
.stat-tile__label { color: var(--text-tertiary); font-size: 13px; margin-top: 4px; }

/* ------------------------------------------------------------- 更新日志 */

.timeline { position: relative; padding-left: 30px; }

.timeline::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: var(--border-strong);
}

.timeline__item { position: relative; padding-bottom: 46px; }
.timeline__item:last-child { padding-bottom: 0; }

.timeline__item::before {
  content: "";
  position: absolute;
  left: -30px;
  top: 7px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--bg-base);
  border: 2px solid var(--brand);
}

.timeline__item:first-child::before { background: var(--brand); box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.2); }

.timeline__date {
  font-size: 13px;
  color: var(--text-tertiary);
  font-family: var(--font-mono);
  margin-bottom: 8px;
}

.timeline__title { font-size: 1.25rem; font-weight: 660; margin-bottom: 14px; }

.timeline__notes { display: grid; gap: 11px; }

.timeline__notes li {
  display: flex;
  gap: 11px;
  color: var(--text-secondary);
  font-size: 0.9375rem;
  line-height: 1.62;
}

.timeline__notes li::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--text-tertiary);
  flex-shrink: 0;
  margin-top: 9px;
}

.roadmap-item {
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: 24px;
  padding: 22px 0;
  border-bottom: 1px solid var(--border);
}

.roadmap-item:last-child { border-bottom: 0; }

/* ------------------------------------------------------------- 滚动入场 */

.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}

.reveal.is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; transition: none; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* --------------------------------------------------------------- 工具类 */

.mono { font-family: var(--font-mono); }
.muted { color: var(--text-tertiary); }

/*
 * 只给屏幕阅读器看的文字：视觉上收起，但不脱离无障碍树。
 *
 * ★ 不能用 `display: none` / `visibility: hidden` —— 那两样会把它从无障碍树里
 *   一起摘掉，等于没写。这里用「1px + 裁剪」：元素仍然占位、仍然被读出来，
 *   只是看不见。也刻意**不加** `.hidden` 那种 !important 的 display 覆盖。
 */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.mt-8 { margin-top: 8px; } .mt-16 { margin-top: 16px; }
.mt-24 { margin-top: 24px; } .mt-32 { margin-top: 32px; }
.mt-48 { margin-top: 48px; } .mt-64 { margin-top: 64px; }
.center { text-align: center; }
.hidden { display: none !important; }
.row-between { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.stack-sm { display: grid; gap: 10px; }

/*
 * `visually-hidden` 与上面 `.sr-only` 是**同一条规则**。
 *
 * ★ 为什么不直接改用 .sr-only：它在 index.html 的订阅表单里已经用了一次
 *   （`<label class="visually-hidden" for="subscribeEmail">`），而那条 CSS
 *   此前**根本没有定义** —— 也就是说那个 label 一直以"邮箱地址"四个字正常
 *   显示在输入框上方，把整块表单撑高了一截，而没有任何东西会告诉你这件事。
 *   （同一批里 checkout.html 也沿用了这个类名。）
 *
 * ★ 为什么不把 HTML 改成 .sr-only：那样会让"类名 ↔ 定义"的一致性依赖
 *   "下次改 HTML 的人记得有这回事"。两类名并存但**指向同一条声明**，
 *   HTML 里用哪个都对；删掉任何一个之前，先 grep 清楚谁在用它。
 *   ⚠ 代价说清楚：这些样式**不随元素 `hidden` 属性联动**，
 *     未来若要给它们加 `[hidden]` 联动的 display 覆盖，两处都要改。
 */
.visually-hidden,
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------------------ 计费周期切换 */

.billing-toggle {
  display: inline-flex;
  padding: 4px;
  gap: 2px;
  margin: 0 auto 32px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg-card);
}

.billing-toggle__btn {
  padding: 9px 22px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease;
}

.billing-toggle__btn:hover { color: var(--text-primary); }

.billing-toggle__btn.is-active {
  background: var(--gradient-brand);
  color: #fff;
  box-shadow: var(--shadow-glow);
}

.billing-toggle__btn:focus-visible {
  outline: 2px solid var(--accent-cyan);
  outline-offset: 2px;
}

/* ------------------------------------------------------------------ 热销卡 */

.price-card--hot {
  border-color: rgba(168, 85, 247, 0.42);
  background: linear-gradient(180deg, rgba(168, 85, 247, 0.1), var(--bg-card) 55%);
}

/* 与 .price-card__badge 同为"骑在卡片上沿"的标记，只是靠右：
   .price-card__badge 占左（免费版 "Beta"），热销占右，两者不会同时出现在一张卡上。 */
.price-card__hot-badge {
  position: absolute;
  top: -12px;
  right: 32px;
  padding: 4px 13px;
  border-radius: 999px;
  background: linear-gradient(135deg, #f59e0b, #ef4444);
  color: #fff;
  font-size: 12px;
  font-weight: 700;
}

/* 非当前计费周期的价格行。原价只在这时露出来 ——
   月付视图下把"年付 $90"当原价划掉是撒谎。 */
.price-card__list {
  margin-bottom: 2px;
  color: var(--text-tertiary);
  font-size: 12.5px;
  text-decoration: line-through;
}

/* 立省徽标。数据来自服务端 catalog（save_cents），不是前端算的差价 ——
   见 pricing.js 头注：年付档是**定价政策**（本批 = 10×月付），划线原价同理，
   两者都是目录里的字段；页面自己算就会在政策变更时静默漂移。
   第二百零六批的数：标准 $9/月 → 年付 $90（划线 $108、立省 $18）。 */
.price-card__save {
  display: inline-block;
  align-self: flex-start;
  margin-bottom: 18px;
  padding: 3px 10px;
  border-radius: 999px;
  background: rgba(52, 211, 153, 0.14);
  color: #6ee7b7;
  font-size: 12px;
  font-weight: 600;
}

/* ------------------------------------------------------------------ 发布提醒行 */

.pricing-subscribe {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-top: 36px;
  padding: 22px 26px;
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background: var(--bg-card);
}

.pricing-subscribe__text {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 240px;
}

.pricing-subscribe__text strong { font-size: 1rem; font-weight: 640; }
.pricing-subscribe__text span { color: var(--text-secondary); font-size: 0.875rem; }

/* 行内形态：表单不再撑满，且去掉原来的上边距（间距由容器给）。 */
.subscribe--inline {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 0;
  flex: 1 1 380px;
}

.subscribe--inline .subscribe__input {
  flex: 1 1 220px;
  width: auto;
  margin-bottom: 0;
}

/* 提示消息独占一行：否则窄屏下它会与输入框挤在同一行，把输入框压成一小条。 */
.subscribe--inline .subscribe__msg {
  flex-basis: 100%;
  margin: 0;
}

/* ------------------------------------------------------------------ 定价区脚注 */

.pricing-foot {
  max-width: 760px;
  margin: 24px auto 0;
  color: var(--text-tertiary);
  font-size: 12.5px;
  line-height: 1.75;
  text-align: center;
}

.skeleton {
  background: linear-gradient(90deg, rgba(255,255,255,0.04) 25%, rgba(255,255,255,0.09) 37%, rgba(255,255,255,0.04) 63%);
  background-size: 400% 100%;
  animation: shimmer 1.4s ease infinite;
  border-radius: var(--radius-sm);
  min-height: 20px;
}

@keyframes shimmer {
  0% { background-position: 100% 0; }
  100% { background-position: 0 0; }
}

/* ------------------------------------------------------------- 响应式 */

@media (max-width: 1024px) {
  .feature-row { grid-template-columns: 1fr; gap: 32px; }
  .feature-row--reverse .feature-row__media { order: 0; }
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer__grid { grid-template-columns: 1fr 1fr; gap: 32px; }
}

@media (max-width: 860px) {
  .section { padding: 72px 0; }
  .grid--3 { grid-template-columns: 1fr; }
  /* 定价卡在 861~860 以下保持两列：三张卡此时仍有 ~250px 宽，塌成单列会把卡片
     拉到整屏宽、列表只占左半边（323 批实测截图）。620 以下才真正单列。 */
  .grid--plans { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .platform-cards { grid-template-columns: 1fr; }
  .stats-strip { grid-template-columns: 1fr; }
  .release { grid-template-columns: 1fr; }
  .release__actions { min-width: 0; }
  .req-list__row { grid-template-columns: 1fr; gap: 6px; }
  .nav__links { display: none; }
  .nav__toggle { display: grid; }
  /* 价格没有专属规则：它和「常见问题」一样是 nav__link，随这个面板一起出现
     （见上方「价格入口（单一形态）」）。 */
  .nav__links.is-open {
    display: flex;
    position: absolute;
    top: 68px;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 12px var(--gutter) 18px;
    /* ★★ 第二百九十七批：这里**必须不透明**（原来是 rgba(8,8,12,0.98)）。
       实测：0.98 的 alpha 在**祖先有 backdrop-filter** 的层里会被"漏"出来 ——
       `.nav` 上的 `saturate(180%) blur(18px)` 把这 2% 的漏光放大并模糊成
       一片可读的残影（390px 视口下首页大标题会透在菜单项后面，肉眼清楚可辨）。
       判据不是"看着像不像"：把背景换成不透明色再截同一个区域，残影完全消失
       ⇒ 竞品不是层叠顺序（elementFromPoint 命中 nav__link），是合成层的透明度。
       ⚠ 别改回半透明"为了毛玻璃效果"：菜单是**全宽下拉**，它下面永远压着大字，
         而可读性优先于氛围。 */
    background: #0a0a10;
    border-bottom: 1px solid var(--border);
    backdrop-filter: blur(18px);
  }
  .nav__links.is-open .nav__link { padding: 12px 14px; }
}

@media (max-width: 620px) {
  :root { --gutter: 18px; }
  .grid--2, .grid--4, .grid--plans { grid-template-columns: 1fr; }
  .hero { padding: 52px 0 40px; }
  /* 首屏信息行在窄屏会把分隔点「·」甩到下一行开头（孤行分隔符）。
     直接改两行显示并隐藏分隔点，比让它换行更好看也更好读。 */
  .hero__meta { flex-direction: column; gap: 6px; }
  .hero__meta .muted { display: none; }
  .hero__actions { flex-direction: column; align-items: stretch; }
  .hero__actions .btn { width: 100%; }
  .cta { padding: 48px 22px; }
  .timeline { padding-left: 24px; }
  .roadmap-item { grid-template-columns: 1fr; gap: 8px; }
  .footer__grid { grid-template-columns: 1fr; }
  .spec-table { font-size: 0.875rem; }
  .spec-table th, .spec-table td { padding: 12px 14px; }

  /* 导航挤不下时优先压缩留白，而不是让里面的控件折行 */
  .nav__inner { gap: 10px; }
  .nav__right { gap: 8px; }
  .brand { font-size: 1rem; gap: 8px; }
  .brand__mark { width: 27px; height: 27px; border-radius: 8px; }
  .brand__mark svg { width: 15px; height: 15px; }
  .lang-switch button { padding: 5px 9px; font-size: 12px; }
  .nav__right .btn--sm { padding: 8px 13px; }

  /* 页脚链接原本只有 ~18px 高（行内元素 = 行高），低于 WCAG 2.2 的 24px
     最小触控尺寸。改成 32px 的块级命中区，同时把原来的 11px 外边距收掉，
     整块页脚高度基本不变（原来 20+11=31px/条，现在 32+0）。 */
  .footer li { margin-bottom: 0; }
  .footer li a,
  .footer__bottom a {
    display: inline-flex;
    align-items: center;
    min-height: 32px;
  }
}

/* 320~430px（最窄的手机）横向空间算不过来：品牌 + 语言切换 + 下载按钮 + 菜单
   四件套 ≈ 390px > 320px。硬挤的结果是「中文」被压成竖排两行。
   取舍：导航里的「下载」与汉堡菜单里的「下载」重复，且首屏就有大号下载 CTA，
   而语言切换没有替代入口 —— 所以让下载按钮退场，保住语言切换。 */
@media (max-width: 430px) {
  .nav__right .btn--primary { display: none; }
  /* 收藏按钮同理退场：触屏没有 Ctrl+D，最后一步引导失效；窄导航也挤不下第五件。
     手机上收藏走浏览器自己的菜单（地址栏旁的 ★），页面内按钮反而多余。 */
  .bookmark-wrap { display: none; }
}
