/* ==========================================================================
   QiLife — design system
   Daily Ritual · 现代养生日常
   奶油底 + 抹茶绿 + 暖褐墨；大圆角、单层柔和扩散阴影、居中通栏 Hero。
   取自当代健康品牌的视觉语言：敞亮、亲近、日常。
   ========================================================================== */

:root {
  /* 纸与墨 —— 奶油底 + 暖褐墨（比上一版更暖、更"日常"，但一样去黄） */
  --paper: #fbf7f0;
  --paper-2: #ffffff;
  --paper-3: #f5eee3;
  --ink: #2e2a24;
  --ink-2: #4c463d;
  --ink-3: #6b6156;
  --ink-4: #726a5f;   /* 弱化文字。旧值 #9a8f81 在纸底只有 2.97，读不清 */
  --line: #f1e9db;
  --line-2: #e3d9c8;

  /* 抹茶绿 —— 按「用途」分层，这是硬规矩：
     --green       只做填充（按钮底、进度条、描边）。当文字用只有 4.24，不达标
     --green-d     填充的 hover
     --green-ink   只做文字（链接、eyebrow、编号）。纸底 6.6 / 次级底 6.1 / 卡白 7.1
     --green-mark  只做图形（品牌方块底）。非文字，白图标 3.6 ≥ 3.0
     一句话：绿色分「填进去的」和「写出来的」，别混用。 */
  --green: #557a4d;
  --green-d: #47693f;
  --green-ink: #3f6137;
  --green-l: #eaf0e4;
  --green-mark: #6e8f63;

  /* 陶 · 阳热实：警示与热象（柔和赤陶） */
  --clay: #c0674a;
  --clay-d: #9a4d35;
  --clay-l: #faeae3;

  /* 沙 · 节气与成就 */
  --gold: #a78b5b;
  --gold-l: #f7f0de;

  /* 青 · 阴寒虚（与主色绿明确区分） */
  --qing: #3a6e8c;
  --qing-d: #27566f;
  --qing-l: #e8f0f5;

  /* 鼠尾草 · 节气提示条 */
  --sage: #e2eeea;
  --sage-d: #3f6b5c;

  /* 页脚 · 深绿（B 的收束色，全站共用） */
  --deep: #3f5c39;
  --deep-line: #55744f;
  --deep-ink: #f6f2e8;
  --deep-mut: #bcd0b4;
  --deep-lbl: #b5d4aa;  /* 页脚栏标题。旧值 #94ae8b 在深绿底只有 3.10 */

  /* 形状：大圆角 + 单层柔和扩散阴影 —— "轻"感来自半径与阴影，不靠描边 */
  --img-radius: 18px;

  --radius: 16px;
  --radius-lg: 26px;
  --radius-hero: 32px;
  --radius-pill: 999px;

  --shadow-sm: 0 2px 6px rgba(46, 42, 36, 0.04);
  --shadow: 0 10px 26px -8px rgba(46, 42, 36, 0.06);
  --shadow-lg: 0 18px 38px -10px rgba(46, 42, 36, 0.14);

  /* 字体：标题走 DM Sans（几何无衬线，亲和现代），正文 Inter。
     --serif 这个变量名保留不改：全站 h1–h4 与引文都吃它，改名会牵动几十处引用；
     只换值是最小风险的换代方式。 */
  --serif: 'DM Sans', 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --sans: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', 'PingFang SC', 'Noto Sans SC', sans-serif;

  /* 内容宽度：全站只有三档。要加第四档前先问「它和现有三档有什么本质不同」——
     上一版就是因为 1288/1280/780/760/720/660 六套宽度并存、还靠 CSS 声明顺序决定
     哪个生效，才出现"每页内容宽度都不一样"。
     已定档（改之前先看「现在谁在用」，别凭名字猜）：
       --w-page  版心 → .wrap、.site-header__inner
       --w-hero  宽内容 → .hero__copy、.wrap--hero、.quiz-shell
                 （quiz / result 是「工作区」不是「阅读栏」：进度条、题干、
                   选项、雷达图都是操作元素，缩到 720 题干会折行）
       --w-text  阅读栏 → .wrap--text、.section__head、.prose
                 （连续长文与区块标题；连续正文超过 75 字符/行就难读了）
       --gutter  页边距 */
  --w-page: 1288px;
  --w-hero: 880px;
  --w-text: 720px;
  --gutter: 1.25rem;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 700;
  line-height: 1.16;
  letter-spacing: -0.02em;
  margin: 0 0 0.5em;
  color: var(--ink);
}

h1 { font-size: clamp(2rem, 5vw, 3.15rem); }
h2 { font-size: clamp(1.45rem, 3vw, 2.05rem); }
h3 { font-size: 1.2rem; }
h4 { font-size: 1.02rem; }

p { margin: 0 0 1em; color: var(--ink-2); }

a { color: var(--green-ink); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

img { max-width: 100%; height: auto; }

hr { border: 0; border-top: 1px solid var(--line); margin: 2.5rem 0; }

::selection { background: var(--green-l); }

:focus-visible {
  outline: 2.5px solid var(--green);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- 骨架 ---------- */
/* 宽度类「一元素只挂一个」。max-width 已含左右 padding，
   所以 --w-page 的值就是屏幕上看到的版心宽度，不用心算。 */
.wrap { width: 100%; max-width: calc(var(--w-page) + var(--gutter) * 2); margin: 0 auto; padding: 0 var(--gutter); }
.wrap--hero { max-width: calc(var(--w-hero) + var(--gutter) * 2); }
.wrap--text { max-width: calc(var(--w-text) + var(--gutter) * 2); }

/* 页面抬头块（.wrap + .page-head）：标题块与下面的网格同吃页宽，
   段落 / 配图 / 提示条收进阅读宽 --w-text —— 纵向一列左边界因此始终在同一条线上。
   判据来自站点自己：.prose:not(.wrap) 也是这么收的（阅读栏由可读性定，网格由操作性定）。
   🔴 别在 HTML 上内联 max-width:46em / 48em / 52em —— 那会飘成第 4、第 5 个宽度值，
   而且内联优先级高于任何 token 类，改 token 时它不会跟着走。 */
.page-head > .lede,
.page-head > .page-figure,
.page-head > .notice { max-width: var(--w-text); }

/* 文章页（/blog|library|topics/<slug>/）的免责条紧跟在正文后面，
   是 .prose 的兄弟而不是 .page-head 的孩子 —— 上面那条够不着它，
   于是它撑满整个版心（实测 1288px，正文只有 720px，读起来像一条走错片场的横条）。
   设计意图本来就是「免责条维持 720 阅读栏」，这里把同一档宽度补给这条路径。 */
.prose + .notice { max-width: var(--w-text); }

/* 抬头特例（glossary，用户拍板 2026-09-27）：引言/配图放宽到页宽，与 h1 同宽。
   放宽也只吃 token（--w-page 是三档之一），不产生第 4 个宽度值；
   .notice 免责条维持 720 阅读栏不变。 */
.page-head--wide > .lede,
.page-head--wide > .page-figure { max-width: var(--w-page); }

/* 顶栏：胶囊导航 + 绿色 CTA。无下边线——靠一层薄阴影把导航托起来，
   这是 B 的写法（有一道线就把"日常"切成"公文"了）。 */
.site-header {
  position: sticky; top: 0; z-index: 40;
  background: rgba(251, 247, 240, 0.86);
  backdrop-filter: saturate(1.6) blur(14px);
  border-bottom: 0;
}
.site-header__inner {
  display: flex; align-items: center; gap: 1.15rem;
  height: 76px;
}
.brand {
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-family: var(--serif); font-size: 1.4rem; font-weight: 700;
  color: var(--ink); letter-spacing: -0.025em;
}
.brand:hover { text-decoration: none; }
.brand__mark {
  width: 34px; height: 34px; flex: 0 0 34px;
  border-radius: 12px;
  background: var(--green-mark);
  display: grid; place-items: center;
  color: #fff;
}
.nav {
  display: flex; align-items: center; gap: 1.6rem; margin-left: auto;
  background: var(--paper-2);
  border-radius: var(--radius-pill);
  padding: 0.68rem 1.6rem;
  box-shadow: 0 8px 22px -6px rgba(46, 42, 36, 0.07);
}
/* :not(.btn) 是防御性的：导航里可能放按钮式 CTA，
   而 .nav a 的优先级 (0,1,1) 高于 .btn--primary (0,1,0)，
   会把按钮的白字压成深灰（对比度掉到 1.34，等于看不见）。 */
.nav a:not(.btn) { color: var(--ink-3); font-size: 0.9rem; font-weight: 500; }
.nav a:not(.btn):hover { color: var(--ink); text-decoration: none; }
.nav a:not(.btn)[aria-current='page'] { color: var(--green-ink); font-weight: 600; }
.site-header__cta { flex: 0 0 auto; }

/* 账号入口 = 顶栏第二个「独立按钮」，与绿色 CTA 并列（登录后换成「头像 + 昵称」）。
   为什么是 --ghost 而不是 --quiet：站点的顶栏底色就是 --paper，--quiet 的 --paper-3
   压在同一层上几乎看不出边界；白色填充 + 描边才读得出「这是个按钮」，
   且与旁边白色导航胶囊同族、与绿色 CTA 形成主次。 */
.site-header__account { flex: 0 0 auto; }
/* 昵称长了要能截断：这是顶栏里唯一长度不受控的文本，不能让它把条撑破 */
.site-header__account > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.site-header__account img { flex: 0 0 auto; }

.nav-toggle {
  display: none; margin-left: auto;
  background: none; border: 1px solid var(--line-2); border-radius: 12px;
  width: 42px; height: 38px; cursor: pointer; color: var(--ink); font-size: 1.1rem;
}

/* 页脚：深绿收束。整页是奶油，靠这一块重色把页面"合上"。 */
.site-footer {
  margin-top: 5.5rem; padding: 4rem 0 2.5rem;
  border-top: 0;
  background: var(--deep);
  font-size: 0.9rem; color: var(--deep-ink);
}
.site-footer__grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 2.75rem; }
.site-footer h4 { font-size: 0.74rem; text-transform: uppercase; letter-spacing: 0.11em; color: var(--deep-lbl); font-family: var(--sans); font-weight: 700; }
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: 0.5rem; font-size: 0.88rem; }
.site-footer a { color: #dce7d6; }
.site-footer a:hover { color: #fff; }
.site-footer p { color: var(--deep-mut); }
.site-footer .brand { color: var(--deep-ink); }
.site-footer__legal { margin-top: 2.75rem; padding-top: 1.6rem; border-top: 1px solid var(--deep-line); font-size: 0.82rem; color: var(--deep-lbl); }
.site-footer__legal p { margin: 0; color: var(--deep-lbl); }

/* ---------- 按钮 ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  padding: 0.72rem 1.4rem;
  border-radius: var(--radius-pill);
  border: 1.5px solid transparent;
  font: inherit; font-size: 0.95rem; font-weight: 600;
  cursor: pointer; white-space: nowrap;
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease), transform 0.14s var(--ease), box-shadow 0.18s var(--ease);
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--green); color: #fff; }
.btn--primary:hover { background: var(--green-d); }
.btn--ghost { background: var(--paper-2); color: var(--ink); border-color: var(--line-2); }
.btn--ghost:hover { border-color: var(--green-mark); color: var(--green-ink); background: var(--paper-2); }
.btn--quiet { background: var(--paper-3); color: var(--ink-2); }
.btn--quiet:hover { background: var(--line); }
.btn--clay { background: var(--clay); color: #fff; }
.btn--clay:hover { background: var(--clay-d); }
.btn--lg { padding: 0.92rem 1.8rem; font-size: 1.02rem; }
.btn--sm { padding: 0.48rem 0.95rem; font-size: 0.86rem; }
.btn--block { width: 100%; }
.btn[disabled] { opacity: 0.48; cursor: not-allowed; }
.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }

/* ---------- 徽标 / 标签 ---------- */
.chip {
  display: inline-flex; align-items: center; gap: 0.35rem;
  padding: 0.3rem 0.72rem;
  border-radius: var(--radius-pill);
  background: var(--paper-3); color: var(--ink-2);
  font-size: 0.76rem; font-weight: 600; letter-spacing: 0.01em;
  /* 🔴 必须显式写 line-height：UA 样式表给 <button> 的是 line-height: normal（≈1.18），
     而 <a>/<span> 继承 body 的 1.6。同一个 .chip 挂在 button 上就比挂在 a 上矮 2px
     （实测术语表筛选条 27px vs 首页玩法 chip 31px / 卡片分类 chip 29px），
     且这个差异在代码里 grep 不到，只能量。写上就三种标签同高。 */
  line-height: 1.6;
}
.chip--green { background: var(--green-l); color: var(--green-ink); }
.chip--clay { background: var(--clay-l); color: var(--clay-d); }
.chip--gold { background: var(--gold-l); color: #7a6234; }
.chip--outline { background: transparent; border: 1px solid var(--line-2); }
.chip-row { display: flex; flex-wrap: wrap; gap: 0.4rem; }

/* 可点击的 chip（首页玩法入口 / 术语表分类筛选）：加描边与悬停反馈，
   明确"这是入口不是标签"。a 与 button 共用同一套外观，别各写一份。 */
a.chip, button.chip {
  border: 1px solid var(--line-2);
  background: var(--paper-2);
  cursor: pointer;
  transition: border-color 0.16s var(--ease), color 0.16s var(--ease), background 0.16s var(--ease);
}
button.chip { font-family: var(--sans); }
a.chip:hover, button.chip:hover { border-color: var(--green); color: var(--green-ink); background: var(--green-l); text-decoration: none; }

/* eyebrow：小号大写 + 放宽字距。上一版起笔的那道短横已去掉——
   那是"雅致东方"的筋骨，B 的调性要更干净、更没有修辞。 */
.eyebrow {
  display: inline-block;
  font-size: 0.76rem; font-weight: 600; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--green-ink); margin-bottom: 0.85rem;
}

/* Hero 徽标（B 的 pill）：一句话把"免费 / 不用注册"摆在标题之前 */
.badge {
  display: inline-flex; align-items: center;
  padding: 0.45rem 1rem; border-radius: var(--radius-pill);
  background: var(--green-l); color: var(--green-ink);
  font-size: 0.8rem; font-weight: 600;
}

/* ---------- 区块 ---------- */
.section { padding: 4.5rem 0; }
.section--tight { padding: 2.5rem 0; }
.section--paper { background: var(--paper-3); border: 0; }
.section__head { max-width: var(--w-text); margin-bottom: 2.5rem; }
.section__head--center { margin-left: auto; margin-right: auto; text-align: center; }

/* 居中节奏（B 的通栏版式）：区块标题、节气提示、chip 行与按钮行一律居中 */
.section--center .section__head { max-width: var(--w-text); margin-left: auto; margin-right: auto; text-align: center; }
.section--center .section__head .notice { width: fit-content; margin: 0 auto 1.1rem; }
.section--center .chip-row { justify-content: center; }
.section--center .btn-row { justify-content: center; }
.lede { font-size: 1.1rem; color: var(--ink-2); }

/* ---------- Hero：居中题记 + 通栏圆角大图 ----------
   B 的骨架：文字居中成一列（徽标 → 大标题 → 说明 → 双按钮 → meta），
   下面接一整幅 1328:432 的圆角大图。
   冲击力来自尺度与敞亮——不再靠把背景压暗那套（那是国画语言）。 */
.hero {
  padding: 3.25rem 0 0;
  background: var(--paper);
}
.hero__inner { display: flex; flex-direction: column; gap: 2.75rem; align-items: center; }
.hero__copy {
  width: 100%; max-width: var(--w-hero);
  display: flex; flex-direction: column; gap: 1.3rem;
  align-items: center; text-align: center;
}
.hero h1 {
  font-size: clamp(2.05rem, 4.6vw, 3.6rem);
  line-height: 1.12;
  letter-spacing: -0.03em;
  color: var(--ink);
  margin: 0;
  max-width: 21em;
}
.hero h1 em { font-style: normal; color: var(--green-ink); }
.hero__sub {
  font-size: clamp(1rem, 1.1vw, 1.06rem);
  line-height: 1.7;
  color: var(--ink-3);
  max-width: 41em;
  margin: 0;
}
.hero__cta { display: flex; flex-wrap: wrap; gap: 0.8rem; align-items: center; justify-content: center; margin-top: 0.35rem; }
.hero__meta {
  margin: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 0.4rem 1.4rem;
  font-size: 0.82rem; color: var(--ink-4);
}
.hero__meta span { display: inline-flex; align-items: center; gap: 0.35rem; }

/* 通栏大图：宽度吃满容器，比例锁 1328:432（与设计稿一致），
   32px 圆角 + 一层柔阴影，让整幅图"落"在奶油纸面上。 */
.hero__figure {
  position: relative; inset: auto; margin: 0;
  width: 100%;
  aspect-ratio: 1328 / 432;
  border-radius: var(--radius-hero);
  overflow: hidden;
  background: var(--paper-3);
  box-shadow: var(--shadow);
}
.hero__figure img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; }

/* ---------- 卡片 ----------
   纯白卡片落在暖白页面上，靠一层柔和的扩散阴影浮起来——
   这才是"现代"的来源（上一版靠 1px 描边，那是印刷品的语言）。 */
.card {
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.6rem;
  box-shadow: var(--shadow);
}
.card--flat { box-shadow: none; }
.card--pad-lg { padding: 2rem; }
.card__title { margin-bottom: 0.35rem; }
.card__hint { font-size: 0.9rem; color: var(--ink-3); margin: 0; }

.grid { display: grid; gap: 1.15rem; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
/* 卡片内容长短不一时用 --start：默认的 stretch 会把同排卡片拉到一样高，
   短的那张卡底就空出一大块。站内原本有 6 处内联 style="align-items:start"，
   收成这个修饰类，别再内联。 */
.grid--start { align-items: start; }

/* ---------- 测试卡片 ---------- */
.test-card {
  display: flex; flex-direction: column;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.4rem;
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), border-color 0.2s var(--ease);
  color: inherit;
}
.test-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: var(--line-2);
  text-decoration: none;
}
.test-card__top { display: flex; align-items: flex-start; gap: 0.85rem; margin-bottom: 0.9rem; }
.test-card__glyph {
  width: 42px; height: 42px; flex: 0 0 42px; border-radius: 12px;
  background: var(--green-l); color: var(--green-ink);
  display: grid; place-items: center; font-size: 1.2rem;
}
/* 有配图时用图替代字形块：56px 圆角小图，与首页 72px 行内缩略图同源 */
.test-card__thumb {
  width: 56px; height: 56px; flex: 0 0 56px;
  border-radius: 14px; object-fit: cover;
  border: 1px solid var(--line);
}
.test-card h3 { margin: 0 0 0.15rem; font-size: 1.12rem; }
.test-card__sub { margin: 0; font-size: 0.86rem; color: var(--ink-3); }
.test-card__body { font-size: 0.92rem; color: var(--ink-2); flex: 1; }
.test-card__foot { margin-top: 1rem; padding-top: 0.9rem; border-top: 1px solid var(--line); display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.test-card__stat { font-size: 0.8rem; color: var(--ink-3); }
.test-card--wide { grid-column: span 2; }

/* ---------- 玩法 ---------- */
.mode-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 0.9rem; }
.mode-tile {
  background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1.1rem; text-align: left; cursor: pointer; font: inherit; color: inherit;
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease), transform 0.14s var(--ease);
}
.mode-tile:hover { border-color: var(--green); background: var(--green-l); }
.mode-tile.is-active { border-color: var(--green); background: var(--green-l); box-shadow: inset 0 0 0 1px var(--green); }
.mode-tile__label { display: flex; align-items: center; gap: 0.45rem; font-weight: 700; font-size: 0.95rem; margin-bottom: 0.25rem; }
.mode-tile__blurb { font-size: 0.82rem; color: var(--ink-3); line-height: 1.5; }

/* ---------- 答题器 ---------- */
/* 走 --w-hero（880）不是 --w-text：答题器是工作区，与 result 页同档，
   保证「答题 → 结果」跳转时宽度不跳变。 */
.quiz-shell { max-width: calc(var(--w-hero) + var(--gutter) * 2); margin: 0 auto; padding: 1.5rem var(--gutter) 4rem; }

.quiz-bar { display: flex; align-items: center; gap: 1rem; margin-bottom: 1.75rem; }
.quiz-bar__progress { flex: 1; height: 6px; border-radius: 99px; background: var(--paper-3); overflow: hidden; }
.quiz-bar__fill { height: 100%; background: linear-gradient(90deg, var(--green), #4d8f6c); border-radius: 99px; transition: width 0.35s var(--ease); }
.quiz-bar__count { font-size: 0.85rem; font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.quiz-bar__timer { font-size: 0.9rem; font-weight: 700; color: var(--clay); font-variant-numeric: tabular-nums; }
.quiz-bar__timer.is-low { animation: pulse 1s infinite; }
@keyframes pulse { 50% { opacity: 0.45; } }

.quiz-card {
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 2rem 1.75rem;
  box-shadow: var(--shadow);
}
@media (prefers-reduced-motion: no-preference) {
  .quiz-card.is-entering { animation: slideIn 0.28s var(--ease); }
}
@keyframes slideIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

.quiz-q__index { font-size: 0.78rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-4); margin-bottom: 0.6rem; }
.quiz-q__text { font-family: var(--serif); font-size: clamp(1.22rem, 2.6vw, 1.6rem); line-height: 1.34; margin: 0 0 1.5rem; }

.quiz-scene {
  background: var(--gold-l); border-left: 3px solid var(--gold);
  padding: 0.7rem 1rem; border-radius: 10px; margin-bottom: 1rem;
  font-size: 0.86rem; color: #6d5514;
}
.quiz-scene strong { display: block; font-size: 0.95rem; color: #57430f; margin-bottom: 0.15rem; }
.quiz-scene__prompt { font-size: 0.98rem; color: var(--ink-2); margin-top: 0.35rem; font-family: var(--serif); }

.opts { display: flex; flex-direction: column; gap: 0.6rem; }
.opt {
  display: flex; align-items: center; gap: 0.85rem;
  padding: 0.85rem 1.05rem;
  background: var(--paper);
  border: 1.5px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer; font: inherit; font-size: 0.98rem; text-align: left; color: var(--ink);
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease), transform 0.12s var(--ease);
}
.opt:hover { border-color: var(--green); background: var(--green-l); }
.opt:active { transform: scale(0.995); }
.opt.is-selected { border-color: var(--green); background: var(--green-l); box-shadow: inset 0 0 0 1px var(--green); }
.opt__key {
  width: 26px; height: 26px; flex: 0 0 26px; border-radius: 8px;
  display: grid; place-items: center;
  background: var(--paper-3); color: var(--ink-3);
  font-size: 0.78rem; font-weight: 700;
}
.opt.is-selected .opt__key { background: var(--green); color: #fff; }
.opt__label { flex: 1; }
.opt__scale { font-size: 0.8rem; color: var(--ink-4); }

.quiz-nav { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: 1.5rem; }
.quiz-nav__back { background: none; border: 0; color: var(--ink-3); font: inherit; font-size: 0.9rem; cursor: pointer; padding: 0.4rem 0; }
.quiz-nav__back:hover { color: var(--green-ink); }
.quiz-nav__back[disabled] { opacity: 0.35; cursor: default; }
.quiz-kbd { font-size: 0.8rem; color: var(--ink-4); }
.quiz-kbd kbd {
  display: inline-block; padding: 0.1rem 0.35rem; margin: 0 0.1rem;
  border: 1px solid var(--line-2); border-bottom-width: 2px; border-radius: 5px;
  background: var(--paper-2); font-family: var(--sans); font-size: 0.75rem; color: var(--ink-2);
}

/* 二选一 */
.duel { display: grid; grid-template-columns: 1fr auto 1fr; gap: 0.75rem; align-items: stretch; }
.duel__side {
  background: var(--paper); border: 1.5px solid var(--line); border-radius: var(--radius);
  padding: 1.25rem; cursor: pointer; font: inherit; text-align: left; color: var(--ink);
  display: flex; flex-direction: column; gap: 0.75rem;
  transition: border-color 0.16s var(--ease), background 0.16s var(--ease), transform 0.14s var(--ease);
}
.duel__side:hover { border-color: var(--green); background: var(--green-l); transform: translateY(-2px); }
.duel__side-key { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.1em; color: var(--ink-4); }
.duel__side-text { font-family: var(--serif); font-size: 1.08rem; line-height: 1.38; flex: 1; }
.duel__vs { display: grid; place-items: center; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.1em; color: var(--ink-4); }
.duel-bars { margin-top: 1.5rem; display: grid; gap: 0.4rem; }
.duel-bar { display: grid; grid-template-columns: 8.5rem 1fr 2.5rem; gap: 0.6rem; align-items: center; font-size: 0.8rem; color: var(--ink-3); }
.duel-bar__track { height: 6px; border-radius: 99px; background: var(--paper-3); overflow: hidden; }
.duel-bar__fill { height: 100%; border-radius: 99px; background: var(--green); transition: width 0.3s var(--ease); }
.duel-bar__val { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink-2); }

/* 滑动 */
.swipe-stage { position: relative; min-height: 260px; display: grid; place-items: center; user-select: none; }
.swipe-card {
  width: min(100%, 460px);
  background: var(--paper-2); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 2rem 1.6rem; box-shadow: var(--shadow-lg);
  cursor: grab; touch-action: pan-y;
  transition: transform 0.22s var(--ease), box-shadow 0.22s var(--ease);
}
.swipe-card.is-dragging { transition: none; cursor: grabbing; }
.swipe-card__text { font-family: var(--serif); font-size: 1.32rem; line-height: 1.36; text-align: center; margin: 0; }
.swipe-card__hint { text-align: center; font-size: 0.82rem; color: var(--ink-4); margin-top: 1rem; }
.swipe-verdict { position: absolute; top: 1rem; font-size: 0.82rem; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; opacity: 0; transition: opacity 0.15s; }
.swipe-verdict--left { left: 1.5rem; color: var(--clay); }
.swipe-verdict--right { right: 1.5rem; color: var(--green-ink); }
.swipe-card.is-nope .swipe-verdict--left, .swipe-card.is-yes .swipe-verdict--right { opacity: 1; }
.swipe-controls { display: flex; justify-content: center; gap: 1rem; margin-top: 1.5rem; }
.swipe-btn {
  width: 54px; height: 54px; border-radius: 50%;
  border: 1.5px solid var(--line-2); background: var(--paper-2);
  display: grid; place-items: center; cursor: pointer; font-size: 1.15rem; color: var(--ink-2);
  transition: transform 0.14s var(--ease), border-color 0.16s, background 0.16s, color 0.16s;
}
.swipe-btn:hover { transform: scale(1.07); }
.swipe-btn--no:hover { border-color: var(--clay); background: var(--clay-l); color: var(--clay); }
.swipe-btn--yes:hover { border-color: var(--green); background: var(--green-l); color: var(--green-ink); }
.swipe-steps { display: flex; justify-content: center; gap: 0.35rem; margin-top: 1rem; font-size: 0.78rem; color: var(--ink-4); }

/* 多选题 */
.multi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 0.55rem; }
.multi-item {
  display: flex; align-items: flex-start; gap: 0.7rem;
  padding: 0.75rem 0.9rem;
  background: var(--paper); border: 1.5px solid var(--line); border-radius: var(--radius);
  cursor: pointer; font: inherit; font-size: 0.94rem; text-align: left; color: var(--ink-2);
  transition: border-color 0.15s, background 0.15s;
}
.multi-item:hover { border-color: var(--green); }
.multi-item.is-on { border-color: var(--green); background: var(--green-l); color: var(--ink); }
.multi-item__box {
  width: 19px; height: 19px; flex: 0 0 19px; margin-top: 2px; border-radius: 6px;
  border: 1.5px solid var(--line-2); display: grid; place-items: center;
  font-size: 0.7rem; color: #fff;
}
.multi-item.is-on .multi-item__box { background: var(--green); border-color: var(--green); }
.multi-counter { position: sticky; bottom: 0; background: var(--paper-2); border-top: 1px solid var(--line); padding: 1rem 0 0; }

/* ---------- 结果页 ---------- */
.result-hero { padding: 2.5rem 0 1rem; }
.result-hero__label { font-size: 0.78rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-4); }
.result-hero h1 { margin: 0.4rem 0 0.6rem; }
.result-hero__headline { font-size: 1.14rem; color: var(--ink-2); max-width: 46em; }

.verdict-card {
  background: linear-gradient(160deg, var(--paper-2) 0%, var(--green-l) 100%);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-lg);
  padding: 1.75rem;
}
.score-ring { display: grid; place-items: center; gap: 0.25rem; }
.score-ring__num { font-family: var(--serif); font-size: 2.6rem; font-weight: 600; line-height: 1; }
.score-ring__label { font-size: 0.76rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); font-weight: 700; }

.metric { display: flex; flex-direction: column; gap: 0.15rem; }
.metric__value { font-family: var(--serif); font-size: 1.75rem; line-height: 1.1; }
.metric__label { font-size: 0.78rem; color: var(--ink-3); }

.dim-list { display: grid; gap: 0.55rem; }
.dim-row {
  display: grid; grid-template-columns: 12rem 1fr 3.5rem;
  gap: 0.85rem; align-items: center;
  padding: 0.5rem 0.35rem;
  border-radius: 10px;
}
.dim-row.is-primary { background: var(--green-l); }
.dim-row__name { font-size: 0.9rem; font-weight: 600; display: flex; align-items: center; gap: 0.4rem; }
.dim-row__track { height: 9px; border-radius: 99px; background: var(--paper-3); position: relative; overflow: hidden; }
.dim-row__fill { height: 100%; border-radius: 99px; transition: width 0.6s var(--ease); }
.dim-row__mark { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--ink-4); opacity: 0.45; }
.dim-row__val { text-align: right; font-size: 0.88rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.dim-row__status { font-size: 0.72rem; color: var(--ink-3); }

.plan-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1rem; }
.plan-item { background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.1rem; }
.plan-item h4 { display: flex; align-items: center; gap: 0.45rem; margin-bottom: 0.5rem; font-size: 0.95rem; font-family: var(--sans); font-weight: 700; }
.plan-item p { margin: 0; font-size: 0.9rem; }
.plan-item__icon { color: var(--green); }

.confidence { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; font-weight: 700; }
.confidence__dot { width: 8px; height: 8px; border-radius: 50%; }
.confidence--high .confidence__dot { background: var(--green); }
.confidence--medium .confidence__dot { background: var(--gold); }
.confidence--low .confidence__dot { background: var(--clay); }

.reasons { list-style: none; margin: 0.75rem 0 0; padding: 0; font-size: 0.86rem; color: var(--ink-3); }
.reasons li { padding-left: 1.1rem; position: relative; margin-bottom: 0.35rem; }
.reasons li::before { content: '·'; position: absolute; left: 0.3rem; }

.gap-list { display: grid; gap: 0.7rem; }
.gap-item { background: var(--clay-l); border-left: 3px solid var(--clay); border-radius: 10px; padding: 0.8rem 1rem; }
.gap-item strong { font-size: 0.9rem; }
.gap-item p { margin: 0.3rem 0 0; font-size: 0.87rem; color: var(--ink-2); }

.reset-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0.7rem; }
.reset-day {
  background: var(--paper); border: 1.5px solid var(--line); border-radius: var(--radius);
  padding: 0.9rem; cursor: pointer; font: inherit; text-align: left; color: inherit;
  transition: border-color 0.16s, background 0.16s;
}
.reset-day:hover { border-color: var(--green); }
.reset-day.is-done { border-color: var(--green); background: var(--green-l); }
.reset-day__n { font-size: 0.72rem; font-weight: 800; letter-spacing: 0.08em; color: var(--ink-4); text-transform: uppercase; }
.reset-day__task { font-size: 0.88rem; margin-top: 0.3rem; }
.reset-day.is-done .reset-day__task { text-decoration: line-through; opacity: 0.65; }

.streak-row { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.streak-dot { width: 22px; height: 22px; border-radius: 7px; background: var(--paper-3); display: grid; place-items: center; font-size: 0.65rem; color: var(--ink-4); }
.streak-dot.is-done { background: var(--green); color: #fff; }
.streak-dot.is-today { outline: 2px solid var(--gold); outline-offset: 1px; }

.badge-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 0.75rem; }
.badge { text-align: center; padding: 1rem 0.75rem; border: 1px dashed var(--line-2); border-radius: var(--radius); opacity: 0.5; }
.badge.is-earned { opacity: 1; border-style: solid; border-color: var(--gold); background: var(--gold-l); }
.badge__glyph { font-size: 1.4rem; }
.badge__label { font-size: 0.86rem; font-weight: 700; margin-top: 0.25rem; }
.badge__blurb { font-size: 0.76rem; color: var(--ink-3); }

.trend { width: 100%; overflow: visible; }

/* 手写 SVG 图表的轴标签会超出 viewBox，必须允许溢出，否则文字被裁掉 */
.chart { overflow: visible; }
.chart--radar, .chart--quadrant { display: block; margin: 0 auto; }
.chart-host { padding: 0.5rem 1.25rem; }
@media (max-width: 640px) {
  .chart-host { padding: 0.25rem 0.5rem; }
}

/* ---------- 分享卡 ---------- */
/* 款式选择器：6 套风格。每格只有「色卡 + 款式名」两行 ——
   不标国家/区域（2026-09-27 起）：名字本身就是风格描述，
   挂上地域标签反而把用户往「这卡是给哪个国家的人用的」上带。
   底色一律用 --paper-2（白），6 个恰好排成 3×2，
   每格宽度足够放 "Golden Ornament" 这类长名字。 */
.share-styles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.6rem;
}
.share-style {
  display: grid; gap: 0.4rem;
  padding: 0.7rem 0.75rem;
  background: var(--paper-2);
  border: 1px solid var(--line-2);
  border-radius: 14px;
  text-align: left; cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.share-style:hover { transform: translateY(-2px); border-color: var(--green); }
.share-style:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.share-style.is-active {
  border-color: var(--green);
  box-shadow: inset 0 0 0 1px var(--green), var(--shadow-sm);
}
.share-style.is-active .share-style__name { color: var(--green-ink); }
.share-style__swatches { display: flex; gap: 4px; }
.share-style__swatches i {
  width: 16px; height: 16px; border-radius: 5px;
  border: 1px solid rgba(46, 42, 36, 0.18);
}
.share-style__name { font-size: 0.84rem; font-weight: 700; color: var(--ink); line-height: 1.25; }

@media (max-width: 620px) {
  .share-styles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.share-preview { display: grid; place-items: center; }
.share-preview canvas { max-width: 100%; border-radius: var(--radius); box-shadow: var(--shadow-lg); }

/* ---------- 表格 / 文字页 ---------- */
/* 阅读栏。宽度类的值已含 padding，所以这里用 :not(.wrap) 排除掉
   「同一个元素既是宽度容器又是阅读栏」的写法——否则两者都声明 max-width，
   谁生效取决于在文件里的先后顺序，等于埋雷（旧版就是这么冒出 680 这个第四档宽度的）。 */
.prose:not(.wrap) { max-width: var(--w-text); }
.prose h2 { margin-top: 2.5rem; }
.prose h3 { margin-top: 1.75rem; }
.prose ul, .prose ol { color: var(--ink-2); padding-left: 1.3rem; }
.prose li { margin-bottom: 0.4rem; }
.prose blockquote {
  margin: 1.5rem 0; padding: 0.9rem 1.25rem;
  border-left: 3px solid var(--green); background: var(--paper-2);
  border-radius: 0 10px 10px 0; color: var(--ink-2);
}
.prose code { background: var(--paper-3); padding: 0.1rem 0.35rem; border-radius: 5px; font-size: 0.88em; }

.table-wrap { overflow-x: auto; }
table.data { width: 100%; border-collapse: collapse; font-size: 0.92rem; }
table.data th, table.data td { text-align: left; padding: 0.7rem 0.85rem; border-bottom: 1px solid var(--line); }
table.data th { font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--ink-3); }
table.data tr:hover td { background: var(--paper-2); }

.accordion { border-top: 1px solid var(--line); }
.accordion details { border-bottom: 1px solid var(--line); }
.accordion summary {
  cursor: pointer; padding: 1rem 0.25rem; font-weight: 600; font-size: 1rem;
  list-style: none; display: flex; justify-content: space-between; gap: 1rem; align-items: center;
}
.accordion summary::-webkit-details-marker { display: none; }
.accordion summary::after { content: '+'; color: var(--ink-3); font-size: 1.2rem; font-family: var(--sans); }
.accordion details[open] summary::after { content: '−'; }
.accordion__body { padding: 0 0.25rem 1.25rem; color: var(--ink-2); font-size: 0.95rem; }

.notice {
  padding: 0.9rem 1.1rem; border-radius: var(--radius);
  font-size: 0.88rem; border: 1px solid var(--line);
  background: var(--paper-2); color: var(--ink-2);
}
.notice--warn { background: var(--clay-l); border-color: #f0cdc3; color: var(--clay-d); }
.notice--info { background: var(--green-l); border-color: #cfe0d4; color: var(--green-ink); }
.notice--gold { background: var(--gold-l); border-color: #e8dcbb; color: #6d5514; }
.notice--qing { background: var(--sage); border-color: transparent; color: var(--sage-d); border-radius: var(--radius-pill); font-weight: 500; }

.loading { display: flex; align-items: center; justify-content: center; gap: 0.6rem; padding: 3rem 0; color: var(--ink-3); }
.spinner {
  width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--line-2); border-top-color: var(--green);
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.skeleton { background: linear-gradient(90deg, var(--paper-3) 25%, var(--paper-2) 50%, var(--paper-3) 75%); background-size: 200% 100%; animation: shimmer 1.4s infinite; border-radius: 8px; }
@keyframes shimmer { to { background-position: -200% 0; } }

.stack > * + * { margin-top: var(--stack-gap, 1rem); }
.center { text-align: center; }
.muted { color: var(--ink-3); }
.small { font-size: 0.88rem; }
.tiny { font-size: 0.78rem; }
.mt-0 { margin-top: 0; }
.mt-1 { margin-top: 0.75rem; }
.mt-2 { margin-top: 1.5rem; }
.mt-3 { margin-top: 2.5rem; }
.mb-0 { margin-bottom: 0; }
.mb-1 { margin-bottom: 0.75rem; }
.mb-2 { margin-bottom: 1.5rem; }
.hidden { display: none !important; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.flex-between { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }

/* ---------- 配图 ----------
   全部配图为明亮通透的静物摄影，统一走大圆角 + 一层柔阴影，
   让图片落在奶油纸面上，而不是"贴"在纸面上。 */
.figure {
  display: block;
  border-radius: var(--img-radius);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--paper-2);
  box-shadow: var(--shadow);
}
.figure img { display: block; width: 100%; height: auto; }

/* 注意：.hero__figure 的规则在 Hero 一节统一定义。
   这里不要再放一份——配图区在文件更靠后，重复定义会静默覆盖上面的，
   上一轮就是这么让通栏图撑到 1440px 的。 */

/* 内容页抬头横幅：用现代品牌的大图尺度，靠圆角与柔阴影与正文分层，不靠描边。
   高度是 clamp(210px, 26vw, 400px) —— 按阅读栏（--w-text）的宽度标定的比例；
   把它放进 .wrap（1288）会变成 3.4:1 的一道细带，1.75:1 的源图直接被裁掉一半。
   margin 只写 margin-bottom + margin-inline：写 margin 简写会把 HTML 上的 .mt-2 静默压掉
   （上一版就是这样，三页的 mt-2 全是死的）。 */
.page-figure {
  margin-bottom: 2.25rem;
  /* 🔴 必须显式清零左右外边距：UA 样式表里 <figure> 默认 margin: 1em 40px，
     没人重置就在正文左右各缩进 40px —— 实测 about / how-it-works / glossary
     三页的横幅都比它上面那段文字窄 80px，左边界差 40px，一眼可见的"对不齐"。
     只有 .hero__figure 侥幸没中（它写了 margin: 0 简写）。 */
  margin-inline: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 0;
  background: var(--paper-3);
  box-shadow: var(--shadow);
}
.page-figure img { display: block; width: 100%; height: clamp(210px, 26vw, 400px); object-fit: cover; object-position: center; }

/* 库页三段分区横幅 */
.section-figure {
  margin: 0 0 1.75rem;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 0;
  background: var(--paper-3);
  box-shadow: var(--shadow-sm);
}
.section-figure img { display: block; width: 100%; height: clamp(160px, 17vw, 230px); object-fit: cover; object-position: center; }

/* ---------- 测评卡片网格（首页的 6 套测试） ----------
   B 的核心资产就是这六个入口：3×2 卡片网格让它们一眼扫完。
   一张卡片 = 2.64:1 横幅图 + 编号 + 标题 + 一句说明。 */
.tile-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
.tile {
  display: flex; flex-direction: column; gap: 1rem;
  padding: 1.125rem;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  color: inherit;
  transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), border-color 0.2s var(--ease);
}
.tile:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: #dce6d2;
  text-decoration: none;
}
.tile__img {
  display: block; width: 100%;
  aspect-ratio: 390 / 148;
  border-radius: var(--img-radius);
  overflow: hidden;
  background: var(--paper-3);
}
.tile__img img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; }
.tile__top { display: flex; align-items: baseline; gap: 0.7rem; }
.tile__no { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.09em; color: var(--green-ink); font-variant-numeric: tabular-nums; }
.tile h3 { margin: 0; font-size: 1.3rem; line-height: 1.2; }
.tile__sub { margin: 0; font-size: 0.875rem; line-height: 1.57; color: var(--ink-3); }

/* ---------- 知识库：分类模块 + 条目卡 ----------
   默认只铺三个分类模块，点进去才展开条目。
   一屏扫完「有什么」，而不是 47 条从上往下排成长墙。

   🔴 这两块**直接吃站点现有组件**，不另立门户：
     分类模块 = .tile-grid + .tile（与首页那六套测评同一套卡片资产）
     条目网格 = .grid .grid--3 + .card（与 /tests.html 同一套）
   新类只补组件里没有的东西：模块卡多一行入口文案，条目卡多一张 dt/dd 字段表。
   卡片的圆角 / 内边距 / 阴影 / 悬停**一律不在这里重写** —— 在这里写一次，
   全站就多一套卡片标准，这正是上一版"每页宽度都不一样"的成因。
   护栏见 browsertest 的「卡片体系」那一步。 */
.lib-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.75rem; }
.lib-toolbar__count { margin: 0; }

/* 搜索框 = 设计系统 3.2 输入族（.input）的搜索位：
   圆角 --radius(16)、描边 --line-2、hover 转绿描边、focus 绿框 + 3px 浅绿外环、占位符 --ink-4。
   DS 文档把「搜索」明确列进输入族适用场景，此前自造的胶囊形 + 外描边聚焦不属于任何一档。 */
.lib-search {
  padding: 0.62rem 0.9rem; border-radius: var(--radius);
  border: 1.5px solid var(--line-2); background: var(--paper-2);
  font: inherit; font-size: 0.95rem; color: var(--ink); min-width: 260px;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.lib-search:hover { border-color: var(--green-mark); }
.lib-search:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px var(--green-l); }
.lib-search::placeholder { color: var(--ink-4); }

/* 分类模块卡：外观全交给 .tile，这里只多一行入口文案。
   margin-top: auto 把它推到卡底 —— 三张卡标题行数不同，入口文案也能对齐在同一基线。 */
.lib-mod__go { margin-top: auto; font-size: 0.86rem; font-weight: 600; color: var(--green-ink); }

.lib-group { margin-bottom: 2.25rem; }
.lib-group__head { margin-bottom: 0.9rem; }
.lib-hitline { margin-bottom: 1.5rem; }

.lib-back { display: inline-block; font-size: 0.86rem; font-weight: 600; margin-bottom: 0.9rem; }
.lib-cat-head { margin-bottom: 1.5rem; }
.lib-cat-head h2 { margin: 0 0 0.4rem; }
.lib-cat-head .eyebrow { margin-bottom: 0.5rem; }

/* 条目卡：外观交给 .card，这里只排内部字段 */
.lib-item.is-target { box-shadow: 0 0 0 2px var(--gold); }
.lib-item__head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; margin-bottom: 0.55rem; }
.lib-item__title { margin: 0; }
.lib-item__pinyin { font-weight: 400; font-size: 0.92rem; color: var(--ink-3); }
.lib-item__zh { font-family: var(--sans); font-size: 0.88rem; color: var(--ink-3); white-space: nowrap; }
.lib-item .chip-row { margin-bottom: 0.75rem; }
.lib-item__meta { margin: 0; }
.lib-item__meta dt { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--ink-3); }
.lib-item__meta dd { margin: 0.1rem 0 0.55rem; font-size: 0.9rem; line-height: 1.5; color: var(--ink-2); }
.lib-item__meta dd:last-child { margin-bottom: 0; }
/* 注意：这里**不能**用 flex —— <strong> 和后面的纯文本会各成一个 flex item，
   "Avoid if." 会被拆成两块，正文还会被挤成窄列。图标走 inline + 垂直对齐即可。
   外观走站点现成的 .notice--warn（同一色板、同一圆角），这里只补一个上边距。 */
.lib-item__caution { margin: 0.9rem 0 0; }
.lib-item__caution svg { vertical-align: -0.18em; margin-right: 0.28rem; }
.lib-item__caution strong { font-weight: 700; }

/* ---------- 术语表：卡片网格 ----------
   🔴 网格**必须用站点自己的 `.grid .grid--3`**（与 /tests.html、库页条目网格同一套），
   不要再写 CSS columns 瀑布流。
   上一版这里是 `.term-masonry { columns: 3 }` —— 列宽与间距虽然和 `.grid` 一样（417px / 1.15rem），
   但它是全站**唯一**的列规则，且 columns 是"按列灌满"：卡片按列向下排、行与行不对齐，
   页面上看起来就是"这一页跟别的页不是一套"。用户原话：「没有按网站的标准来」。
   现在卡片只多两件事：`break-*` 之类一律不要，列间距与响应式断点全交给 `.grid--N`。 */
/* 工具栏：与库页 .lib-toolbar 同一套形状与节奏 —— 上行是筛选条（术语表独有），
   下行 `[搜索框] …… [条数]`，两者间距与库页一致。
   上一版把搜索框塞在筛选条右边、条数掉到单独一整行，全站只有这一页是这么排的。 */
.term-filters { margin-bottom: 1rem; }
.term-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1.75rem; }
.term-chip.is-active { background: var(--green-l); border-color: var(--green-mark); color: var(--green-ink); }

.term-card__head { display: flex; align-items: baseline; justify-content: space-between; gap: 0.6rem; margin-bottom: 0.5rem; }
.term-card__term { margin: 0; }
.term-card__zh { font-family: var(--sans); font-size: 0.88rem; color: var(--ink-3); white-space: nowrap; }
/* chip 是 inline-flex，直接挂 margin-bottom 在行盒里不会撑开间距 —— 转成块级才排得上 */
.term-card__cat { display: block; width: fit-content; margin-bottom: 0.6rem; }
.term-card__def { margin: 0; font-size: 0.9rem; line-height: 1.55; color: var(--ink-2); }
.term-card__src { margin: 0.7rem 0 0; font-size: 0.74rem; line-height: 1.45; color: var(--ink-3); }

@media (max-width: 640px) {
  /* 工具栏窄屏堆成一列：搜索框吃满宽度，
     否则 flex 会把它收缩到只够放半句占位文案（"Search acupoints, foods, t…"）。 */
  .lib-toolbar, .term-toolbar { flex-direction: column; align-items: stretch; }
  .lib-search { width: 100%; min-width: 0; }
}

/* ---------- 响应式 ---------- */
@media (max-width: 1100px) {
  .hero { padding-top: 2.25rem; }
  .hero__inner { gap: 2rem; }
  .tile-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 900px) {
  /* 通栏图在窄屏压成细条就没内容了，收一档取景比例 */
  .hero__figure { aspect-ratio: 16 / 10; border-radius: var(--radius-lg); }
  .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .site-footer__grid { grid-template-columns: 1fr 1fr; }
  .test-card--wide { grid-column: span 2; }
}

/* 🔴 顶栏收折成一个独立的断点，别再和「页面排版收窄」的 640px 捆在一起。
   为什么是 960：顶栏一行要装下「品牌 + 导航胶囊 + Start a test + Sign in」，
   实测需要约 905px 的内容宽。旧版把收折点定在 640px，于是 641–827px 这段
   顶栏一直撑着 827px 不换行 —— 768px（iPad 竖屏）下整页横向溢出 59px，700px 下 127px。
   这是改版前就存在的溢出，顺手在这里一并修掉。
   ⚠️ 断点一旦隐藏导航，「手机上用什么替代它」必须同时有答案：
   本来导航里有 Sign in，现在它被移出导航做成了按钮 —— 所以这个断点里
   导航胶囊、Start a test 可以收，**Sign in 必须留在条上**，否则手机上就没有登录入口了。 */
@media (max-width: 960px) {
  .nav {
    display: none; position: absolute; left: 0; right: 0; top: 74px;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper-2); border-bottom: 1px solid var(--line);
    border-radius: 0; padding: 0.5rem 1.25rem 1rem; box-shadow: var(--shadow);
  }
  .nav.is-open { display: flex; }
  .nav a:not(.btn) { padding: 0.7rem 0; border-bottom: 1px solid var(--line); }
  /* 顺序：品牌 → Sign in → ≡。DOM 里汉堡在 Sign in 之前，靠 order 把它挪到最后。
     否则读起来像「QiLife ≡ Sign in」——两个不相干的东西并排。 */
  .nav-toggle { display: block; order: 3; margin-left: 0; }
  .site-header__cta { display: none; }
  .site-header__account { order: 2; min-width: 0; max-width: 9rem; }
  /* 🔴 整条右对齐**只由品牌的 auto margin 收边**，右边那组谁都不许再挂 auto margin。
     auto margin 有两条就平分剩余空间 —— 实测 768px 下 Sign in 会漂到条的正中间
     （brand 到它 252px、它到汉堡也 252px），看着像掉队，不像一组。
     为什么偏偏选品牌：它是**两种缓存版本里都在场**的那个元素。
     CDN 各边缘换版有时间差（实测同一时刻 LAX 发 35 分钟前的旧 HTML、DFW 发新的），
     旧 HTML 的右侧只有汉堡、新 HTML 是 Sign in + 汉堡 —— 挂在右边任何一个身上，
     另一种情形就会失效。挂在品牌上，两种版本、以后再加右侧按钮都成立。 */
  .brand { margin-right: auto; }
}

@media (max-width: 640px) {
  /* Hero：按钮改竖排满宽，手指够得着；meta 行收窄 */
  .hero { padding-top: 1.5rem; }
  .hero__copy { gap: 1rem; }
  .hero__cta { flex-direction: column; align-items: stretch; width: 100%; margin-top: 0; }
  .hero__cta .btn { width: 100%; }
  .hero__meta { font-size: 0.78rem; gap: 0.3rem 1rem; }
  .tile-grid { grid-template-columns: 1fr; }
  .grid--2, .grid--3, .grid--4 { grid-template-columns: 1fr; }
  .test-card--wide { grid-column: span 1; }
  .quiz-card { padding: 1.5rem 1.1rem; }
  .duel { grid-template-columns: 1fr; }
  .duel__vs { display: none; }
  .dim-row { grid-template-columns: 1fr 2.5rem; }
  .dim-row__track { grid-column: 1 / -1; order: 3; }
  .dim-row__name { order: 1; }
  .dim-row__val { order: 2; }
  .duel-bar { grid-template-columns: 6.5rem 1fr 2.2rem; }
  .site-footer__grid { grid-template-columns: 1fr; }
  .share-preview canvas { max-width: 100%; }
  .quiz-kbd { display: none; }
}

@media print {
  .site-header, .site-footer, .btn, .quiz-nav { display: none; }
  body { background: #fff; }
}
/* 🔴 [hidden] 的 UA 规则是 display:none，但**任何**作者样式的 display
   （哪怕写在别的选择器上、只要命中了同一个元素）都能把它压掉 ——
   隐藏容器用 <div hidden> 时必须先有这一条，否则「隐藏」是假的。 */
[hidden] { display: none !important; }


/* ==========================================================================
   Design System — 系统扩展层（Extension）
   --------------------------------------------------------------------------
   表单 / 反馈 / 导航 / 数据展示 / 布局原语 —— 站点页面此前没用到、但账号体系必需的组件。
   由 design-assets/design-system/index.html 转正而来（原为「扩展草案」）。
   三条纪律与站点组件一致：只用已有 token、圆角只用三档、不引入新色值/阴影。
   ========================================================================== */

/* ==========================================================================
   QiLife Design System — 系统扩展层（Extension）
   --------------------------------------------------------------------------
   这里定义「站点目前还没用到、但全系统必需」的组件（表单 / 反馈 / 导航 / 数据展示）。
   三条纪律：
     1. 只用 qilife.css 已有的 token。不引入任何新色值、新圆角、新阴影。
     2. 圆角一律 --radius(16) / --radius-lg(26) / --radius-pill，与站点组件同级。
     3. 类名避开站点已用类名，接入时与 qilife.css 无冲突。
   状态：**已并入**（2026-10-01）。本层现为本文件的权威定义，
   design-system/index.html 只保留演示标记，不再自带副本 —— 避免两处定义、两套标准。
   ========================================================================== */

/* ---------- 表单 ---------- */
.field { display: flex; flex-direction: column; gap: 0.35rem; }
.field__label { font-size: 0.82rem; font-weight: 600; color: var(--ink-2); }
.field__help { font-size: 0.78rem; color: var(--ink-3); }
.field__error { font-size: 0.78rem; font-weight: 600; color: var(--clay-d); display: flex; align-items: center; gap: 0.3rem; }
.form-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

.input, .textarea, .select {
  width: 100%; padding: 0.62rem 0.9rem;
  border: 1.5px solid var(--line-2); border-radius: var(--radius);
  background: var(--paper-2); color: var(--ink);
  font: inherit; font-size: 0.95rem;
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}
.textarea { min-height: 104px; resize: vertical; line-height: 1.6; }
.select { appearance: none; padding-right: 2.2rem; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b6156' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.8rem center;
}
.input:hover, .textarea:hover, .select:hover { border-color: var(--green-mark); }
.input:focus, .textarea:focus, .select:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px var(--green-l); }
.input::placeholder, .textarea::placeholder { color: var(--ink-4); }
.input[disabled], .textarea[disabled], .select[disabled] { background: var(--paper-3); color: var(--ink-3); cursor: not-allowed; border-color: var(--line); }
.input[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--clay); }
.input[aria-invalid="true"]:focus, .textarea[aria-invalid="true"]:focus { box-shadow: 0 0 0 3px var(--clay-l); }

/* 勾选 / 单选 / 开关：统一外观但保留原生语义与键盘行为。
   🔴 注意：<input> 是替换元素，::before / ::after 不会生成 —— 所以勾、圆点、滑块
   一律不能用伪元素画（这条踩过：写了 ::after 在浏览器里完全看不见）。
   勾用 background-image（内联 SVG），圆点用 border-width，滑块放在真实 span 上。 */
.check, .radio { display: flex; align-items: flex-start; gap: 0.6rem; font-size: 0.93rem; color: var(--ink-2); cursor: pointer; }
.check input, .radio input {
  appearance: none; margin: 2px 0 0; flex: 0 0 19px; width: 19px; height: 19px;
  border: 1.5px solid var(--line-2); background-color: var(--paper-2); cursor: pointer;
  transition: border-color 0.15s var(--ease), background-color 0.15s var(--ease), border-width 0.15s var(--ease);
}
.check input { border-radius: 6px; }
.check input:checked {
  border-color: var(--green); background-color: var(--green);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-size: 13px 13px; background-position: center; background-repeat: no-repeat;
}
.radio input { border-radius: 50%; }
.radio input:checked { border-color: var(--green); border-width: 6px; }
.check input:focus-visible, .radio input:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }

/* 开关：视觉滑块必须挂在真实元素上，不能是 input 的伪元素 */
.switch { display: inline-flex; align-items: center; gap: 0.6rem; font-size: 0.9rem; color: var(--ink-2); cursor: pointer; }
.switch input { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; }
.switch__track {
  position: relative; width: 40px; height: 23px; flex: 0 0 40px; border-radius: 999px;
  background: var(--line-2); transition: background 0.18s var(--ease);
}
.switch__track::after {
  content: ''; position: absolute; top: 3px; left: 3px; width: 17px; height: 17px; border-radius: 50%;
  background: #fff; box-shadow: var(--shadow-sm); transition: transform 0.18s var(--ease);
}
.switch input:checked + .switch__track { background: var(--green); }
.switch input:checked + .switch__track::after { transform: translateX(17px); }
.switch input:focus-visible + .switch__track { outline: 2px solid var(--green); outline-offset: 2px; }

/* ---------- 反馈 ---------- */
.alert { display: flex; gap: 0.7rem; align-items: flex-start; padding: 0.9rem 1.05rem; border-radius: var(--radius); border: 1px solid var(--line); background: var(--paper-2); font-size: 0.88rem; color: var(--ink-2); }
.alert__icon { flex: 0 0 auto; line-height: 1.5; }
.alert__body { flex: 1; }
.alert__body strong { display: block; margin-bottom: 0.12rem; color: var(--ink); }
.alert--success { background: var(--green-l); border-color: #cfe0d4; color: var(--green-ink); }
.alert--success .alert__body strong { color: var(--green-ink); }
.alert--warn { background: var(--clay-l); border-color: #f0cdc3; color: var(--clay-d); }
.alert--warn .alert__body strong { color: var(--clay-d); }
.alert--info { background: var(--sage); border-color: transparent; color: var(--sage-d); }
.alert--info .alert__body strong { color: var(--sage-d); }

.toast-stack { position: fixed; right: 1.25rem; bottom: 1.25rem; z-index: 60; display: flex; flex-direction: column; gap: 0.6rem; max-width: min(360px, calc(100vw - 2.5rem)); }
.toast { display: flex; gap: 0.6rem; align-items: flex-start; padding: 0.8rem 1rem; border-radius: var(--radius); background: var(--paper-2); border: 1px solid var(--line-2); box-shadow: var(--shadow-lg); font-size: 0.87rem; color: var(--ink-2); }

.progress { display: flex; flex-direction: column; gap: 0.35rem; }
.progress__meta { display: flex; justify-content: space-between; font-size: 0.78rem; color: var(--ink-3); }
.progress__track { height: 6px; border-radius: 999px; background: var(--paper-3); overflow: hidden; }
.progress__bar { height: 100%; border-radius: 999px; background: var(--green); transition: width 0.3s var(--ease); }

.empty-state { text-align: center; padding: 2.5rem 1.25rem; border: 1px dashed var(--line-2); border-radius: var(--radius-lg); background: var(--paper); }
.empty-state__glyph { font-size: 1.6rem; color: var(--green-mark); margin-bottom: 0.5rem; }
.empty-state h4 { margin: 0 0 0.3rem; }
.empty-state p { margin: 0; font-size: 0.88rem; color: var(--ink-3); }

/* 对话框 / 抽屉 */
.modal__backdrop { position: fixed; inset: 0; background: rgba(46, 42, 36, 0.42); backdrop-filter: blur(2px); display: grid; place-items: center; padding: 1.25rem; z-index: 70; }
.modal__panel { width: min(520px, 100%); background: var(--paper-2); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: 1.6rem; }
.modal__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; margin-bottom: 0.7rem; }
.modal__title { margin: 0; font-size: 1.16rem; }
.modal__foot { display: flex; justify-content: flex-end; gap: 0.6rem; margin-top: 1.35rem; }
.modal__close { background: none; border: 0; font-size: 1.15rem; line-height: 1; color: var(--ink-3); cursor: pointer; padding: 0.2rem 0.35rem; border-radius: 7px; }
.modal__close:hover { color: var(--ink); background: var(--paper-3); }

.drawer__panel { width: min(380px, 92vw); height: 100%; background: var(--paper-2); box-shadow: var(--shadow-lg); padding: 1.5rem; overflow: auto; }
.drawer__backdrop { position: fixed; inset: 0; background: rgba(46, 42, 36, 0.42); display: flex; justify-content: flex-end; z-index: 70; }

/* 气泡提示 */
.tip { position: relative; display: inline-flex; }
.tip__bubble {
  position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
  background: var(--ink); color: var(--paper-2); font-size: 0.76rem; line-height: 1.45;
  padding: 0.42rem 0.65rem; border-radius: 9px; white-space: nowrap; pointer-events: none;
  opacity: 0; transition: opacity 0.15s var(--ease);
}
.tip__bubble--static { opacity: 1; position: static; transform: none; }
.tip:hover .tip__bubble { opacity: 1; }

/* ---------- 导航 ---------- */
.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; font-size: 0.8rem; color: var(--ink-3); }
.crumbs a { color: var(--ink-3); }
.crumbs a:hover { color: var(--green-ink); text-decoration: none; }
.crumbs__sep { color: var(--ink-4); }
.crumbs [aria-current="page"] { color: var(--ink); font-weight: 600; }

.tabs { display: flex; gap: 0.25rem; border-bottom: 1px solid var(--line); overflow-x: auto; }
.tab {
  appearance: none; background: none; border: 0; border-bottom: 2px solid transparent;
  padding: 0.6rem 0.95rem; font: inherit; font-size: 0.9rem; font-weight: 600; color: var(--ink-3);
  cursor: pointer; white-space: nowrap; margin-bottom: -1px;
  transition: color 0.15s var(--ease), border-color 0.15s var(--ease);
}
.tab:hover { color: var(--ink); }
.tab[aria-selected="true"], .tab.is-active { color: var(--green-ink); border-bottom-color: var(--green); }

.stepper { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.step { display: inline-flex; align-items: center; gap: 0.45rem; font-size: 0.82rem; color: var(--ink-3); }
.step__dot { display: grid; place-items: center; width: 24px; height: 24px; flex: 0 0 24px; border-radius: 50%; background: var(--paper-3); color: var(--ink-3); font-size: 0.74rem; font-weight: 700; }
.step.is-done .step__dot { background: var(--green); color: #fff; }
.step.is-current { color: var(--ink); font-weight: 600; }
.step.is-current .step__dot { background: var(--green-l); color: var(--green-ink); box-shadow: inset 0 0 0 1.5px var(--green); }
.step__line { width: 22px; height: 1px; background: var(--line-2); }

.pagination { display: flex; flex-wrap: wrap; gap: 0.3rem; align-items: center; }
.page-link {
  display: inline-grid; place-items: center; min-width: 34px; height: 34px; padding: 0 0.5rem;
  border: 1px solid var(--line-2); border-radius: 10px; background: var(--paper-2);
  font-size: 0.85rem; font-weight: 600; color: var(--ink-2); cursor: pointer; font-family: inherit;
}
.page-link:hover { border-color: var(--green); color: var(--green-ink); text-decoration: none; }
.page-link[aria-current="page"] { background: var(--green); border-color: var(--green); color: #fff; }
.page-link[disabled] { opacity: 0.45; cursor: not-allowed; }

/* ---------- 数据展示 ---------- */
.avatar { display: inline-grid; place-items: center; width: 38px; height: 38px; border-radius: 50%; background: var(--green-l); color: var(--green-ink); font-size: 0.84rem; font-weight: 700; flex: 0 0 auto; }
.avatar--lg { width: 52px; height: 52px; font-size: 1.02rem; }
.avatar-row { display: flex; align-items: center; gap: 0.7rem; }

.stat { display: flex; flex-direction: column; gap: 0.1rem; }
.stat__value { font-family: var(--serif); font-weight: 700; font-size: 1.7rem; line-height: 1.05; color: var(--ink); }
.stat__label { font-size: 0.78rem; color: var(--ink-3); }
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1rem; }

.timeline { list-style: none; margin: 0; padding: 0; }
.timeline li { position: relative; padding: 0 0 1.1rem 1.5rem; border-left: 1px solid var(--line-2); }
.timeline li:last-child { border-left-color: transparent; padding-bottom: 0; }
.timeline li::before { content: ''; position: absolute; left: -4.5px; top: 0.35rem; width: 8px; height: 8px; border-radius: 50%; background: var(--green); }
.timeline__when { font-size: 0.74rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-4); }
.timeline__what { font-size: 0.9rem; color: var(--ink-2); }

.dl-inline { margin: 0; }
.dl-inline dt { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: var(--ink-3); }
.dl-inline dd { margin: 0.1rem 0 0.6rem; font-size: 0.9rem; color: var(--ink-2); }
.dl-inline dd:last-child { margin-bottom: 0; }

.ul-plain { list-style: none; margin: 0; padding: 0; }
.ul-plain li { padding: 0.55rem 0; border-bottom: 1px solid var(--line); font-size: 0.9rem; color: var(--ink-2); }
.ul-plain li:last-child { border-bottom: 0; }

.kbd { display: inline-block; padding: 0.1rem 0.35rem; margin: 0 0.1rem; border: 1px solid var(--line-2); border-bottom-width: 2px; border-radius: 5px; background: var(--paper-2); font-family: var(--sans); font-size: 0.75rem; color: var(--ink-2); }

/* ---------- 布局原语 ---------- */
.cluster { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.cluster--between { justify-content: space-between; }
.stack-xs { display: flex; flex-direction: column; gap: 0.5rem; }
.stack-sm { display: flex; flex-direction: column; gap: 1rem; }
.stack-lg { display: flex; flex-direction: column; gap: 2rem; }

/* ==========================================================================
   账号页（sign-in / account）
   --------------------------------------------------------------------------
   这一节只放**设计系统里没有的东西**，其余一律挂现成组件：
     卡片 .card / 标签页 .tabs+.tab / 字段 .field+.input+.field__error
     提示 .alert / 空态 .empty-state / 头像 .avatar / 统计 .stat+.stat-grid
     表格 .table-wrap+table.data / 列表 .ul-plain / 布局 .cluster+.stack-*
   判据：下面每条新类里都不出现 border-radius 之外的「第二套形状标准」
   （没有新阴影、没有新间距刻度、没有新色值）。
   ========================================================================== */

/* 验证码行：输入框吃满剩余宽度，动作按钮固定右侧、与输入框等高。
   设计系统里没有「输入 + 动作」这种组合（.form-grid 是等宽两列，
   把按钮塞进去会得到一个宽得离谱的按钮），所以补这一条。 */
.field__row { display: flex; gap: 0.5rem; align-items: stretch; }
.field__row .input { flex: 1 1 auto; min-width: 0; }
.field__row .btn { flex: 0 0 auto; }

/* 头像选择器：4 个内含圆 + 自定义上传。
   .avatar 是固定尺寸的展示组件，没有「可选/选中」这一态，故另立。 */
.avatar-picker { display: flex; flex-wrap: wrap; gap: 0.6rem; align-items: center; }
.avatar-picker__opt {
  padding: 0; line-height: 0;
  border: 2px solid transparent; border-radius: 50%;
  background: none; cursor: pointer;
  transition: border-color 0.15s var(--ease), transform 0.14s var(--ease);
}
.avatar-picker__opt:hover { transform: translateY(-2px); border-color: var(--green-mark); }
.avatar-picker__opt.is-active { border-color: var(--green); box-shadow: 0 0 0 3px var(--green-l); }
.avatar-picker__opt img { width: 52px; height: 52px; border-radius: 50%; display: block; }
.avatar-picker__opt[disabled] { opacity: 0.5; cursor: not-allowed; transform: none; }

/* 记录条目：一行 = 标题 + 元信息 + 右侧数值。
   .card 负责外观，这里只排内部。 */
.record-item { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; }
.record-item__main { flex: 1 1 14rem; min-width: 0; }
.record-item__title { margin: 0 0 0.2rem; font-size: 1rem; }
.record-item__meta { margin: 0; font-size: 0.82rem; color: var(--ink-3); }
.record-item__side { text-align: right; }

@media (max-width: 640px) {
  .record-item__side { text-align: left; }
}

/* 账号入口已从「导航胶囊里的一条文字链」改成「顶栏第二个独立按钮」
   （.site-header__account），原先那条 `.nav [data-account-link]` 行内对齐规则
   已经没有任何元素能命中，一并删掉 —— 留着会让下一个人以为导航里还有一个账号入口。 */
