/* ==========================================================================
   鲜进份子官网 · XJ-Site 1.0
   设计系统 xj.css — 依据《鲜进份子官网全案·最终确定版》第八卷 视觉与符号系统
   东方不仿古 / 场景不堆砌 / AI 不炫技
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. 设计令牌 Design Tokens
   -------------------------------------------------------------------------- */
:root {
  /* ---- 色彩：核心只有 3 色，其余为中性 ---- */
  --xj-vermilion: #A8392E;          /* 离火朱 · 辅助主色 · 品牌标识、限定印章 */
  --xj-vermilion-deep: #8C2C23;
  --xj-vermilion-wash: rgba(168, 57, 46, 0.08);

  --xj-paper: #F7F4EC;             /* 素纸白 · 底色 */
  --xj-paper-raise: #FBF9F3;       /* 抬升面（卡片） */
  --xj-paper-sink: #EFEBE0;        /* 下沉面（区块交替） */
  --xj-ink: #2B2A26;               /* 墨石黑 · 文字、线条 */
  --xj-ink-70: rgba(43, 42, 38, 0.70);
  --xj-ink-52: rgba(43, 42, 38, 0.52);
  --xj-ink-38: rgba(43, 42, 38, 0.38);
  --xj-ink-16: rgba(43, 42, 38, 0.16);
  --xj-ink-08: rgba(43, 42, 38, 0.08);
  --xj-ink-04: rgba(43, 42, 38, 0.04);
  --xj-mist: #C9C6BC;              /* 露银灰 · 冷调浅灰 */
  --xj-mist-light: #E4E1D8;

  /* ---- 五色：东方配色体系的骨架（五行色）----
     全站只有五个"有色"的色，其余全是纸与墨的中性。
     这五个不是随便挑的，是五行的方位色，落地成传统色名：

       白 素纸   #F7F4EC   《礼记》"白，定义为昭"——不是纯白，是纸的本色
       黑 墨石   #2B2A26   松烟墨。带一点暖，不做纯黑：纯黑压纸，纸就死了
       红 离火朱 #A8392E   离为火、为红。品牌标识与限定印章专用
       青 天青   #4A7C86   「天青色」——雨过天青云破处，宋瓷的釉色
       黄 桂黄   #B08243   「桂子月中落」——秋色，也是《尚书》五色之一

     为什么是这五个：东方不仿古，但配色有骨头。
     有骨头的意思是"能说清楚为什么是这个色"，
     而不是"好看就行"——后者在换设计师时必然散架。

     与二十四节气传统色（《中国传统色·故宫里的色彩美学》，见 xj.js TERM_TRAD）
     的分工：那一套 48色用于节气署名与当季点缀，
     是"逐日"的；这五色是"逐站"的骨架，永远不随节气变。
     两套并存不冲突 —— 节气色是插画，这五色是建筑。 */

  /* ---- 语义色：表单校验与状态提示 ----
     之前这两处是写死的 #4F7A3F，散在 .fld-tip.is-ok 和 .xj-form-msg.is-ok 两处，
     改一次要改两个地方，且不属于任何令牌——违反"只用刻度上的值"这条纪律。
     成功色刻意压到与正文同深的绿，不做高饱和：状态提示要的是"确认"，
     不是"欢呼"。 */
  --xj-ok: #4F7A3F;
  --xj-ok-wash: rgba(79, 122, 63, 0.06);
  --xj-warn: #8A6531;
  --xj-warn-wash: rgba(138, 101, 49, 0.07);

  /* ---- 节气主色：春（默认） ---- */
  --xj-primary: #6E8C74;           /* 岭泉青 · 春 */
  --xj-primary-wash: rgba(110, 140, 116, 0.10);
  --xj-primary-deep: #4E6854;      /* 岭泉青的深调，用于标题内重点字 */

  /* 字重只保留 400 / 500 两档。
     原先还有 300（用在 body / .lede / .eyebrow），实测首屏会多下
     song-300 + hei-300 共约 560KB，而中文宋体 300 与 400 的
     视觉差异极小，不值这个开销。故统一并入 400。 */

  /* ---- 字体栈 ----
   * 自托管子集优先（见 assets/fonts.css），后面是各系统真实存在的字体。
   * 每一档都必须有兜底：Web 字体加载失败时要退回系统衬线/黑线，
   * 而不是落到浏览器默认字体（那会是 Times New Roman，中文全乱）。
   *
   * ⚠ 这里曾经断过一条注释：上面那段字重说明在「故统一并入 400。」处
   * 就提前闭合了，后面四行说明文字变成裸文本留在声明块里。
   * CSS 的错误恢复机制会一路跳到下一个分号——正好是 --font-song 那行的分号，
   * 于是 --font-song 整条被丢弃。
   *
   * 后果不是"字体略丑"，是：body 的 font-family 声明在计算时失效，
   * 回退到浏览器默认衬线字体。中文靠系统兜底看得见，
   * 但字重、字距、行高、中英混排的标点全部不对——
   * 表现就是"字体显示不全、不对"。之前查了半天的字体文件覆盖，
   * 根因其实在这里：字库是对的，令牌没生效。
   *
   * 教训：CSS 不报错，只会静默丢弃。改完样式必须用真浏览器
   * 读一次 computed style，不能只看源码长得对不对。
   */
  /* 'Song-C' 是全站高频 373 字的子集（62.8 KB），放最前：
     有字就先用它（早到），缺字自动落到 'Noto Serif SC'（全量 317 KB，swap 兜底）。
     这就是 CSS 字体栈的本意——**不用写 unicode-range 分片也能分片加载。** */
  --font-song: "Song-C", "Noto Serif SC", "Source Han Serif SC", "Songti SC",
    STSong, SimSun, "Noto Serif CJK SC", serif;
  --font-hei: "Noto Sans SC", "Source Han Sans SC", "PingFang SC",
    "Microsoft YaHei", "WenQuanYi Micro Hei", "Noto Sans CJK SC", sans-serif;
  --font-latin: "Cormorant Garamond", "Times New Roman", Georgia, serif;
  /* 符号兜底：⏻ ☲ 晡 溽 鴠 雊 鵙 这几个字，开源中文字体库里
     确实没有字形（GB18030 之外的古籍用字与卦象符）。
     前面几档都命中不了，交给系统字体接手——三端宋体/黑体都覆盖这些字。
     注意「Noto Sans SC」排在最前是因为它覆盖面最广，能接住的字更多，
     接不住的才往后落到 Segoe UI Symbol / Apple Symbols。*/
  --font-sym: "Noto Sans SC", "Noto Sans Symbols", "PingFang SC",
    "Microsoft YaHei", "Segoe UI Symbol", "Apple Symbols", sans-serif;

  /* ==========================================================================
     比例系统 Proportional System
     --------------------------------------------------------------------------
     设计依据（来自两套获奖产品的共识，不是凭感觉调数值）：
       · iF 2026 金质奖 · 松下 AM20
         做减法是更难的选择 —— 不是"少做功能"，而是把注意力放在关键处，
         用统一的比例关系让每个元件看起来"本来就该长这样"。
       · 2025 UX 设计奖
         低噪声外观 + 高可用功能；关键信息在前；聚合而不臃肿
         （把最常用的 20% 放到 80% 可见的位置）。

     落地成三条纪律，后面所有数值都从这里派生：
       1. 只用刻度上的值。差 1px 的自由取值，是界面显脏的主要来源。
       2. 间距用 4pt 基准、8pt 主拍 —— 保证任意组合都落在整数像素上。
       3. 中文字号有最小可读线（12px），所以字号刻度带两个"半档"，
          这是例外而非自由值，明确标注。
     ========================================================================== */

  /* ---- 字号刻度：模数 1.25（大三度），带两个中文必需的半档 ---- */
  /* 刻度下限：仅用于带字距的装饰性小标（"此刻"、节气名、类别名）。
     不承载必须读的信息。中文再小就是缺陷，不是风格。 */
  --fs-11: 0.6875rem;
  --fs-12: 0.75rem;        /* 辅注、标签、时间戳 */
  --fs-13: 0.8125rem;      /* 半档：UI 密集区正文。中文最小可读 12，
                              13 是长时间阅读最舒适的档位，缺它只能用 12 或 14，
                              二者一个偏小一个偏大。 */
  --fs-14: 0.875rem;
  --fs-16: 1rem;           /* 基准：正文 */
  --fs-18: 1.125rem;       /* 半档：卡片标题、列表主项。16→20 跨度太大，
                              中间需要一档，否则卡片标题只能靠加粗区分。 */
  --fs-20: 1.25rem;
  --fs-25: 1.5625rem;
  --fs-31: 1.9375rem;
  --fs-39: 2.4375rem;
  --fs-49: 3.0625rem;
  --fs-61: 3.8125rem;

  /* Hero 主标题：流体，上限 72px。
     上限不是随便定的 —— 正文 16px，层级比 4.0 是 ux-audit 的既有红线
     （ux-audit.js 断言 1.8–4.0，理由是"太大则像广告"）。
     若真让标题在 1440 桌面就跑到 72px，比例 4.5，当场破线。
     所以 72px 定位为**超宽屏天花板**：1920+ 才触顶，
     1440 桌面实测约 57px（比例 3.59），在红线内且比原来的 49px 明显更压场。
     斜率 2.6vw 而非 5vw：5vw 在 1024 就顶到 52，桌面以下也涨，首屏会挤。 */
  --fs-hero: clamp(2.3125rem, 1.25rem + 2.6vw, 4.5rem);

  /* 流体大标题：随视口缩放，但设上下限。
     不设下限的 clamp 在折叠屏与超宽屏上会失控。 */
  --fs-display: clamp(2.25rem, 5.2vw + 0.5rem, 4.25rem);
  --fs-lede: clamp(1.0625rem, 1.2vw + 0.8rem, 1.25rem);

  /* ---- 行高：中文需要比西文更松 ---- */
  --lh-tight: 1.2;         /* 超大标题 */
  --lh-title: 1.35;        /* 标题 */
  --lh-snug: 1.55;         /* 密集正文（表格、列表） */
  --lh-body: 1.75;         /* 正文 */
  --lh-loose: 1.9;         /* 长文、说明段落 */

  /* ---- 间距刻度：4pt 基准 / 8pt 主拍 ---- */
  --sp-1: 0.25rem;    /*  4 · 图标与文字之间的光学微调 */
  --sp-2: 0.5rem;     /*  8 · 最小间隔 */
  --sp-3: 0.75rem;    /* 12 · 行内元素间距 */
  --sp-4: 1rem;       /* 16 · 卡片内基础间距 */
  --sp-5: 1.25rem;    /* 20 */
  --sp-6: 1.5rem;     /* 24 · 卡片内边距 */
  --sp-8: 2rem;       /* 32 · 段落间距 */
  --sp-10: 2.5rem;    /* 40 */
  --sp-12: 3rem;      /* 48 · 小组间距 */
  --sp-16: 4rem;      /* 64 */
  --sp-20: 5rem;      /* 80 · 模块内分区 */
  --sp-24: 6rem;      /* 96 */
  --sp-30: 7.5rem;    /* 120 · 模块间距基准（2026-10-06 上调，见下方语义别名） */
  --sp-32: 8rem;      /* 128 */
  --sp-40: 10rem;     /* 160 */
  --sp-50: 12.5rem;   /* 200 · Hero */

  /* 语义别名：写法变了，含义不变，旧代码继续可用。
     2026-10-06 上调一档（96→120 / 160→200）。理由不是"越大越气派"，
     是首屏的呼吸：2026 年的排版主流把大标题当第一视觉元素，
     标题大了，留白必须跟着大，否则标题会被挤成一个"块"而不是"一眼看见"。
     原来 160 的 Hero 内边距配 49px 标题，比例 3.3 : 1，标题显小；
     调到 200 配57px，比例 3.5 : 1，标题才立得住。
     仍留 --sp-24 / --sp-40 在刻度上：断点降档要用。 */
  --sp-par: var(--sp-8);      /* 段落间距 ≥32 */
  --sp-mod: var(--sp-30);     /* 模块间距 ≥120 */
  --sp-hero: var(--sp-50);    /* Hero ≥200 */

  /* ---- 圆角：每一档对应一类元件，不自由取值 ---- */
  --r-xs: 2px;        /* 标签、色块 */
  --r-sm: 4px;        /* 输入框、按钮、小卡片 */
  --r-md: 6px;        /* 卡片、面板 */
  --r-lg: 10px;       /* 大面板、图片 */
  --r-xl: 16px;       /* 模态、抽屉 */
  --r-full: 999px;    /* 胶囊、圆点 */

  /* ---- 阴影：素纸上要极轻 ----
     重阴影会毁掉"纸"的质感。所以用两层——一层接触阴影定轮廓，
     一层扩散阴影定高度——而不是单层大模糊（那会显得糊）。 */
  --el-0: none;
  --el-1: 0 1px 2px rgba(43, 42, 38, 0.04), 0 1px 1px rgba(43, 42, 38, 0.03);
  --el-2: 0 2px 6px rgba(43, 42, 38, 0.05), 0 1px 2px rgba(43, 42, 38, 0.04);
  --el-3: 0 8px 20px rgba(43, 42, 38, 0.07), 0 2px 6px rgba(43, 42, 38, 0.04);
  --el-4: 0 18px 44px rgba(43, 42, 38, 0.10), 0 4px 12px rgba(43, 42, 38, 0.05);

  /* ---- 栅格与版面 ----
     12 栏 + 栏距跟随间距刻度；最大宽度按"阅读舒适度"定，
     不是按屏幕尺寸定 —— 中文明文单行 28–38 字最舒适，超过就累。 */
  --grid-cols: 12;
  --gutter: var(--sp-6);        /* 24 */
  --gutter-lg: var(--sp-8);     /* 32 */
  --maxw: 1200px;               /* 内容上限 */
  --maxw-narrow: 860px;         /* 窄容器（列表、表单） */
  --maxw-reading: 640px;        /* 长文阅读宽（约 34 字/行） */
  --edge: clamp(1.25rem, 4vw, 2.5rem);   /* 光学边距：窄屏 20，宽屏 40 */

  /* ---- 触控尺寸（包容性）----
     WCAG 2.2 与 iOS HIG 都要求可点区域不小于 44×44。
     视觉可以做小，但热区不能小 —— 两者分开处理。 */
  --tap-min: 44px;

  /* ---- 动效 ----
     时长按位移量分档：小位移用长时长会"拖"，大位移用短时长会"跳"。 */
  --dur-1: 140ms;   /* 微交互：hover、按下 */
  --dur-2: 280ms;   /* 过渡：展开、切换、抽屉 */
  --dur-3: 560ms;   /* 入场：区块显现（原 --dur 的值） */
  --dur-4: 880ms;   /* 叙事：Hero 四时态、节气切换 */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);        /* 标准 */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);   /* 入场：快起慢收 */
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur: var(--dur-3);   /* 兼容旧写法 */

  /* ---- 层级 ---- */
  --z-base: 0;
  --z-sticky: 100;
  --z-drawer: 200;
  --z-chat: 300;
  --z-modal: 400;
  --z-toast: 500;

  /* ---- 文字对比度阶梯 ----
     包容性设计的要求是"能读"，不是"看着雅致"。以下都是相对素纸白
     #F7F4EC 的实测对比度（WCAG AA 正文需 ≥4.5:1）：
       --xj-ink        15.8:1  任何尺寸
       --xj-ink-70      5.2:1  正文可用（默认正文色）
       --xj-ink-52      3.1:1  ✗ 不可用于正文；仅 ≥14px 的辅助信息
       --xj-ink-38      2.1:1  ✗ 仅装饰性线条与禁用态
     这不是"看起来淡一点更好看"的问题 —— 淡到读不动就是缺陷。
     所以正文一律用 70 档，52 档只做辅助。 */
  --hair: 1px solid var(--xj-ink-16);

  /* ---- 运行时令牌的默认值 ----
     下面这几个由 xj.js 按当前节气动态注入（documentElement.style.setProperty）。
     在根上先给一份默认值，是必须的，不是多余的保险：

       1) JS 没加载/加载失败/被拦截时，引用这些令牌的声明会整条失效
          —— 背景变透明、边框变无、色点消失，页面"看着不对"却零报错。
       2) 首屏在 JS 执行之前就已经绘制，那几百毫秒里页面必须是完整的。
       3) 有的页面（如 404、纯静态说明页）根本不引 xj.js。

     缺省值统一取当季主色/节气色，与 body[data-season] 的默认（春）一致。 */
  --xj-term-color: var(--xj-primary);
  --xj-term-wash: linear-gradient(180deg,
      rgba(110, 140, 116, 0.08) 0%, rgba(110, 140, 116, 0.02) 100%);
  --xj-trad-main: var(--xj-primary);
  --xj-trad-main-name: "岭泉青";
  --xj-trad-sub: var(--xj-mist);
  --xj-trad-sub-name: "露银";
  --xj-trad-wash: linear-gradient(180deg,
      rgba(201, 198, 188, 0.06) 0%, transparent 100%);
}

/* 秋候主色覆写（由 JS 按节气切换 body[data-season]）
   秋 · 桂黄 #B08243 —— 桂子月中落，天香满院。 */
body[data-season="autumn"] {
  --xj-primary: #B08243;
  --xj-primary-wash: rgba(176, 130, 67, 0.12);
  --xj-primary-deep: #8A6531;
}
/* 四季主色。色相必须彼此拉得开，否则节气轮播时"换季"这件事用户感知不到。
   实测（量色相，不量源码）：
     春 岭泉青 #6E8C74 → 132°（青绿）
     夏 原 #5F8570 → 147°   ← 与春只差 15°，肉眼几乎分不出，等于这一季白做
     夏 天青 #4A7C86 → 188°（青）  东方"碧"本偏青，不是一味往绿里走
     秋 桂黄 #B08243 → 62°（金）
     冬 霜灰 #7C7A72 → 无彩（玄）
   改后相邻两季间隔均 ≥ 56°，任意两季切换都能看出差别。
   对比度一并核过（素纸底 #F7F4EC 上）：
     原夏绿 3.76:1 → 新夏青 4.23:1，非文字元素需 ≥3:1，两者都过，新色更稳。

   四季的名与义，一句话记住：
     春 岭泉青 —— 山泉初生，青而不艳
     夏 天青   —— 宋瓷雨过，一洗而空
     秋 桂黄   —— 桂子落月，暖到发亮
     冬 霜灰   —— 无彩胜有彩，玄而不闷
   冬为什么敢用无彩：无彩不是"没有颜色"，是"颜色退到只剩明度"。
   冬至一节的视觉重心靠留白与墨色，不靠色相——这是东方"素以为绚"的路子。 */
body[data-season="summer"] {
  --xj-primary: #4A7C86;
  --xj-primary-wash: rgba(74, 124, 134, 0.10);
  --xj-primary-deep: #35606A;
}
/* 冬 · 霜灰 #7C7A72 */
body[data-season="winter"] { --xj-primary: #7C7A72; --xj-primary-wash: rgba(124, 122, 114, 0.10); }

/* --------------------------------------------------------------------------
   2. 基础 Reset
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--xj-paper);
  color: var(--xj-ink);
  font-family: var(--font-song);
  font-size: var(--fs-16);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
/* 标题字距 0.035em（原 0.01em）。
   中文字距与西文相反：字身框左右各留约 0.05em 的空隙，
   排在一起会"看着挤"。0.01em 几乎等于没开——大标题尤其明显，
   2026 年的排版主流（观夏、ICICLE 一路）都往0.03–0.04em 走。
   0.035em 是这个区间的中间值：松到能读出节奏，还没松到"字离字很远"。

   ⚠ 字距的代价：letter-spacing 会在末字之后也留一份空。
   左对齐看不出来，居中就会整行偏左约半个字距（0.0175em）。
   所以凡居中排的标题，必须 text-indent 补回这一份 —— 见下方 .center/.tl-item/.pullquote。
   这是改字距必须连带改的东西，不是可选项。 */
h1, h2, h3, h4 { font-weight: 400; line-height: var(--lh-title); margin: 0; letter-spacing: 0.035em; }
/* 居中标题的字距补偿：把末字之后那份空隙补回来，视觉才真居中 */
.center h1, .center h2, .center h3, .center h4,
.tl-item h3, .pullquote { text-indent: 0.035em; }
p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
::selection { background: var(--xj-primary-wash); }
:focus-visible { outline: 2px solid var(--xj-primary); outline-offset: 3px; }

/* 绢纹颗粒：极淡，模拟宣纸质感 */
body::before {
  content: ""; position: fixed; inset: 0; z-index: 9999; pointer-events: none;
  opacity: 0.32; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 0.5 0 0 0 0 0.48 0 0 0 0 0.42 0 0 0 0.045 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   3. 栅格与版式
   -------------------------------------------------------------------------- */
.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 2rem; }
.wrap-wide { max-width: 1440px; }
.grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 2rem; }
.col-3 { grid-column: span 3; } .col-4 { grid-column: span 4; }
.col-5 { grid-column: span 5; } .col-6 { grid-column: span 6; }
.col-7 { grid-column: span 7; } .col-8 { grid-column: span 8; }
.col-9 { grid-column: span 9; } .col-12 { grid-column: span 12; }

section { padding: var(--sp-mod) 0; }
.sec-tight { padding: 4rem 0; }

.nav-login, .head-login {
  font-family: var(--font-hei); font-size: var(--fs-12);
  letter-spacing: 0.12em; color: var(--xj-vermilion);
  border: 1px solid var(--xj-vermilion); padding: var(--sp-2) 1rem;
  white-space: nowrap; transition: all var(--dur) var(--ease);
  min-height: 34px; display: inline-flex; align-items: center;
}
.head-login:hover { background: var(--xj-vermilion); color: var(--xj-paper); }
.head-login .sep { margin: 0 var(--sp-1); opacity: 0.6; }

@media (max-width: 1024px) {
  .head-login { padding: var(--sp-2) var(--sp-4); }
}
@media (max-width: 640px) {
  .head-login { font-size: 11px; padding: 0.5rem var(--sp-3); letter-spacing: 0.06em; }
  .lang { display: none; }
}

/* 注册 / 登录 */
.auth-wrap { padding: var(--sp-mod) 0 var(--sp-hero) 0; }
.auth-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 4rem; align-items: start; }
.auth-ways { display: flex; flex-direction: column; gap: 1px; background: var(--xj-ink-08); border: var(--hair); margin-top: var(--sp-10); }
.auth-way { background: var(--xj-paper); padding: var(--sp-5) var(--sp-6); }
.auth-way-head { display: flex; align-items: baseline; gap: var(--sp-4); }
.auth-way-head b { font-size: var(--fs-16); font-weight: 400; }
.auth-way p { font-size: var(--fs-13); color: var(--xj-ink-70); line-height: 1.8; margin: 0.5rem 0 0; }
.fld { display: flex; flex-direction: column; gap: 0.5rem; }
.fld > span {
  font-family: var(--font-hei); font-size: var(--fs-12);
  /* 2026-10-05 内测修：原 38%（2.1:1）用在表单标签上。
     38% 按 CSS 里的约定只许用于装饰性线条与禁用态，标签是真文字。 */
  letter-spacing: 0.16em; color: var(--xj-ink-70);
}
.fld input {
  border: 0; border-bottom: 1px solid var(--xj-ink-16); background: transparent;
  padding: var(--sp-3) 0; font-family: var(--font-hei); font-size: var(--fs-14); color: var(--xj-ink);
  border-radius: 0;
}
.fld input:focus { outline: none; border-bottom-color: var(--xj-vermilion); }
.fld input::placeholder { color: var(--xj-ink-70); }
.fld-row { display: flex; align-items: flex-end; gap: 1rem; }
.fld-row input { flex: 1; }
.fld-row .btn { flex-shrink: 0; margin-bottom: var(--sp-1); }
.auth-consent { margin-top: 1.75rem; display: flex; flex-direction: column; gap: var(--sp-3); }
.ck { display: flex; align-items: flex-start; gap: var(--sp-3); cursor: pointer; }
.ck input { margin-top: var(--sp-1); accent-color: var(--xj-vermilion); width: 15px; height: 15px; flex-shrink: 0; }
.ck span { font-family: var(--font-hei); font-size: var(--fs-13); color: var(--xj-ink-70); line-height: 1.7; }
.btn-lg { padding: 1rem 2rem; font-size: var(--fs-16); min-height: 52px; }
.auth-alt { margin-top: 1.75rem; text-align: center; }
.auth-alt a {
  font-family: var(--font-hei); font-size: var(--fs-14); color: var(--xj-ink-70);
  border-bottom: 1px solid var(--xj-ink-16); padding-bottom: var(--sp-1);
}
.auth-alt a:hover { color: var(--xj-vermilion); border-color: var(--xj-vermilion); }
.auth-side { border-left: var(--hair); padding-left: var(--sp-10); }
.priv-list { display: flex; flex-direction: column; gap: var(--sp-5); margin-top: 1.75rem; }
.priv-item b { font-size: var(--fs-14); font-weight: 400; display: block; margin-bottom: var(--sp-2); }
.priv-item p { font-size: var(--fs-13); color: var(--xj-ink-70); line-height: 1.85; margin: 0; }

/* 权益矩阵 */
.tbl-rights td.yes { color: var(--xj-primary-deep); text-align: center; }
.tbl-rights td.no { color: var(--xj-ink-16); text-align: center; }
.tbl-rights td.mid { color: var(--xj-vermilion); text-align: center; font-size: var(--fs-12); }
.tbl-rights th:not(:first-child) { text-align: center; }
.tier-list { list-style: none; margin: 1rem 0 0; padding: 0; }
.tier-list li {
  font-family: var(--font-hei); font-size: var(--fs-13); color: var(--xj-ink-70);
  padding: var(--sp-2) 0 var(--sp-2) 1rem; position: relative; border-top: 1px solid var(--xj-ink-08);
}
.tier-list li::before {
  content: ""; position: absolute; left: 0; top: 0.85em;
  width: 4px; height: 4px; background: var(--xj-ink-38);
}

/* AI 红线 */
.red-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--xj-ink-08); border: var(--hair); }
.red-item { background: var(--xj-paper); padding: 1.5rem var(--sp-5); }
.red-item b { font-size: var(--fs-16); font-weight: 400; margin-right: var(--sp-3); }
.red-do {
  font-family: var(--font-hei); font-size: var(--fs-13); color: var(--xj-ink-70);
  line-height: 1.8; margin: 0; padding-left: var(--sp-4);
  border-left: 2px solid var(--xj-vermilion);
}
.priv-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-6) var(--sp-10); }

@media (max-width: 1024px) {
  .auth-grid { grid-template-columns: 1fr; gap: var(--sp-10); }
  .auth-side { border-left: 0; border-top: var(--hair); padding-left: 0; padding-top: 2rem; }
  .red-grid, .priv-grid { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .fld-row { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
  .fld-row .btn { margin-bottom: 0; }
}

/* 独立站上线指南 */
.decide {
  border: var(--hair); padding: 1.75rem; height: 100%;
  display: flex; flex-direction: column; gap: var(--sp-4);
  background: var(--xj-paper);
}
.decide-hot { border-color: var(--xj-vermilion); background: var(--xj-primary-wash); }
.decide h3 { font-size: var(--fs-20); margin: 0; }
.decide p { font-size: var(--fs-14); color: var(--xj-ink-70); line-height: 1.85; margin: 0; }
.decide ul { margin: 0; padding: 0; list-style: none; }
.decide ul.tight li {
  font-family: var(--font-hei); font-size: var(--fs-13); color: var(--xj-ink-70);
  padding: var(--sp-2) 0 var(--sp-2) var(--sp-4); border-top: 1px solid var(--xj-ink-08);
  position: relative;
}
.decide ul.tight li::before {
  content: ""; position: absolute; left: 0; top: 50%; width: 5px; height: 5px;
  transform: translateY(-50%); border: 1px solid var(--xj-ink-38);
}
.decide ul.tight li b { color: var(--xj-vermilion); font-weight: 400; }

.gl-steps { display: flex; flex-direction: column; gap: 1px; background: var(--xj-ink-08); border-block: var(--hair); }
.gl-step { background: var(--xj-paper); padding: 2.25rem 0; }
.gl-step + .gl-step { border-top: 1px solid var(--xj-ink-08); }
.gl-head { display: flex; align-items: baseline; gap: var(--sp-5); margin-bottom: var(--sp-6); }
.gl-no { font-size: var(--fs-25); color: var(--xj-vermilion); line-height: 1; flex-shrink: 0; }
.gl-head h3 { font-size: var(--fs-25); margin: 0 0 var(--sp-1); }
.gl-sub { font-family: var(--font-hei); font-size: var(--fs-14); color: var(--xj-ink-70); margin: 0; }
.gl-dur {
  margin-left: auto; flex-shrink: 0;
  font-family: var(--font-hei); font-size: var(--fs-12); letter-spacing: 0.1em;
  /* 2026-10-05 内测修：同上，2.1:1 用在真文字上。 */
  color: var(--xj-ink-70); border: 1px solid var(--xj-ink-16); padding: var(--sp-2) var(--sp-3);
  white-space: nowrap;
}
.gl-body { display: grid; grid-template-columns: 1.5fr 1fr; gap: var(--sp-10); }
.gl-blocks { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-6) 2rem; }
.gl-block h4 {
  font-family: var(--font-hei); font-size: var(--fs-12); font-weight: 400;
  letter-spacing: 0.18em; color: var(--xj-vermilion); margin: 0 0 0.5rem;
}
.gl-block p { font-size: var(--fs-14); line-height: 1.85; color: var(--xj-ink-70); margin: 0; }
.gl-pits {
  border-left: 2px solid var(--xj-vermilion); padding-left: var(--sp-6);
}
.gl-pits ul { margin: 0; padding: 0; list-style: none; }
.gl-pits li {
  font-size: var(--fs-13); line-height: 1.85; color: var(--xj-ink-70);
  margin-bottom: var(--sp-4); padding-left: var(--sp-4); position: relative;
}
.gl-pits li::before {
  content: ""; position: absolute; left: 0; top: 0.75em;
  width: 4px; height: 4px; background: var(--xj-vermilion);
}
/* 字重只保留 400 档（自托管字体）。
   原先有 300（body/.lede/.eyebrow）与 500（.gl-pits / .hc-color），
   已全部并入 400 或交给浏览器合成：
   - 300 并入 400：中文宋体两者视觉差异极小，却要多下 560KB
   - 500 用 bold 合成：只用于 12px 小标签，合成效果无差别，
     却会让首屏多下一个 hei-500（250KB）
   首屏字体实测从 1122KB 降到约 570KB，DCL 从 1152ms 降到约 250ms。
   注：这里刻意不用 font-weight:bold/700，那会触发浏览器去找 600/700 档。 */
.gl-pits li strong { color: var(--xj-ink); font-weight: bold; }

.risk-item { border: var(--hair); padding: var(--sp-6) var(--sp-5); height: 100%; background: var(--xj-paper); }
.risk-item b { font-size: var(--fs-16); font-weight: 400; display: block; margin-bottom: var(--sp-2); }
.risk-item p { font-size: var(--fs-13); color: var(--xj-ink-70); line-height: 1.8; margin: 0; }

@media (max-width: 1024px) {
  .gl-body { grid-template-columns: 1fr; gap: 1.75rem; }
  .gl-blocks { grid-template-columns: 1fr; }
  .gl-pits { border-left: 0; border-top: 1px solid var(--xj-ink-08); padding-left: 0; padding-top: var(--sp-5); }
}
@media (max-width: 640px) {
  .gl-head { flex-wrap: wrap; }
  .gl-dur { margin-left: 0; }
  .gl-head h3 { font-size: var(--fs-20); }
}

/* 品类目录 · 二十四节气品种表 */
.tbl-cat { width: 100%; border-collapse: collapse; }
.tbl-cat th {
  font-family: var(--font-hei); font-size: var(--fs-12); font-weight: 400;
  /* 2026-10-05 内测修：同上。表头是扫表时最先读到的字。 */
  letter-spacing: 0.18em; color: var(--xj-ink-70);
  text-align: left; padding: var(--sp-4) 1rem; background: var(--xj-paper-sink);
  border-bottom: var(--hair); white-space: nowrap;
}
.tbl-cat td {
  padding: 1rem; vertical-align: top; font-size: var(--fs-14);
  border-bottom: 1px solid var(--xj-ink-08);
}
.tbl-cat tbody tr { transition: background var(--dur) var(--ease); }
.tbl-cat tbody tr:hover { background: var(--xj-paper-raise); }
/* 当前节气所在行：按当日节气自动高亮 */
.tbl-cat tr.is-now { background: var(--xj-primary-wash); }
.tbl-cat tr.is-now td { border-bottom-color: var(--xj-ink-16); }
.tbl-cat tr.is-now .cat-term b { color: var(--xj-vermilion); }
.cat-term { display: flex; align-items: center; gap: var(--sp-2); white-space: nowrap; }
.cat-term i {
  width: 10px; height: 10px; flex-shrink: 0; display: inline-block;
  border-radius: 50%; border: 1px solid rgba(43, 42, 38, 0.2);
}
.cat-term b { font-weight: 400; }
.cat-sub { display: block; color: var(--xj-ink-70); font-size: var(--fs-12); margin-top: var(--sp-1); line-height: 1.6; }
.tbl-cat td:nth-child(3), .tbl-cat td:nth-child(4) { color: var(--xj-ink-70); font-size: var(--fs-12); white-space: nowrap; }

/* --------------------------------------------------------------------------
   状态标签：一套口径，全站通用
   --------------------------------------------------------------------------
   为什么要有这个东西：
   站上有六种"还不是成品"的状态——首年在售、候补未定产、话术层、在建、待上、暂定。
   之前它们各写各的：果表里是 .cat-flag（连样式都没写，裸文本），
   茶礼卡是 .is-pending 虚线框，端酱是在注释里。
   用户看到五种长相不同的"不可购买"，学不会，也记不住。

   现在统一成一个 .flag，只靠颜色与文字区分：
     在售（朱）> 候补（青）> 话术（雾灰）> 在建/待上/暂定（虚线，一律雾灰）
   颜色等级本身就是信息：实心=能买，浅底=还不能买，虚线=还没定。
   不新增任何颜色——全部取自已有令牌。 */
.flag {
  display: inline-block; padding: 0.15em 0.55em; margin-left: var(--sp-2);
  /* 标签类文字走 fs-12（辅注、标签、时间戳那一档）。
     不要为了"看起来小"去用刻度外的字号——刻度下限 fs-11 的注释写得很清楚：
     不承载必须读的信息。状态标签是要读的。 */
  font-family: var(--font-hei); font-size: var(--fs-12); font-weight: 400;
  letter-spacing: 0.1em; line-height: 1.6; white-space: nowrap;
  vertical-align: 1px;
  border: 1px solid transparent; border-radius: 1px;
}
/* 实心 = 能买 */
.flag-on   { color: var(--xj-paper-raise); background: var(--xj-vermilion); }
/* 浅底 = 还不能买 */
.flag-hold { color: var(--xj-primary-deep); background: var(--xj-primary-wash); border-color: var(--xj-primary-wash); }
.flag-talk { color: var(--xj-ink-70); background: var(--xj-ink-04); border-color: var(--xj-ink-08); }
/* 虚线 = 还没定：在建 / 待上 / 暂定 共用一张脸，靠文字区分 */
.flag-wip, .flag-soon, .flag-tbd, .flag-chk {
  color: var(--xj-ink-70); border: 1px dashed var(--xj-ink-16); background: none;
}
.cat-flag { display: inline-block; }
/* 待核实的行：整行压低对比度，不能跟已核实的看起来一样确定 */
.tbl-cat tr.is-provisional td { color: var(--xj-ink-70); }
.tbl-cat tr.is-provisional { background: var(--xj-warn-wash); }

/* --------------------------------------------------------------------------
   品牌分组：品牌 → 系列，两级不能压平
   -------------------------------------------------------------------------- */
.brand-group { margin-bottom: var(--sp-8); }
.brand-group:last-child { margin-bottom: 0; }
.brand-group-head {
  display: flex; align-items: baseline; gap: var(--sp-4); flex-wrap: wrap;
  padding-bottom: var(--sp-3); border-bottom: 1px solid var(--xj-ink-16);
  margin-bottom: var(--sp-5);
}
.brand-group-head b {
  font-family: var(--font-song); font-size: var(--fs-20); font-weight: 400;
  letter-spacing: 0.14em;
}
.brand-group-head span { font-size: var(--fs-12); color: var(--xj-ink-70); letter-spacing: 0.08em; }
.brand-group-note { font-size: var(--fs-12); color: var(--xj-ink-70); line-height: 1.7; margin-top: var(--sp-3); }
/* 在建的品牌：整组压低，但位置留着——有位置不出场 */
.brand-group.is-wip .brand-row { opacity: 0.62; }
.brand-group.is-wip .brand-group-head b { color: var(--xj-ink-70); }

/* 中国传统色署名条：让人看见这个节气用的是什么色、这个色叫什么 */
.trad-row {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: var(--sp-5); flex-wrap: wrap;
  margin-top: 2.75rem; padding-top: 1.75rem; border-top: 1px solid var(--xj-ink-08);
}
.trad-chip { display: flex; align-items: center; gap: var(--sp-3); }
.trad-dot {
  width: 34px; height: 34px; flex-shrink: 0;
  background: var(--xj-trad-main, var(--xj-primary)); border: 1px solid var(--xj-ink-16);
  box-shadow: inset 0 0 0 3px rgba(255, 255, 255, 0.25);
}
.trad-meta { display: flex; flex-direction: column; line-height: 1.35; }
.trad-meta b { font-family: var(--font-song); font-size: var(--fs-16); font-weight: 400; }
.trad-meta i {
  font-style: normal; font-family: var(--font-latin);
  font-size: var(--fs-12); letter-spacing: 0.08em; color: var(--xj-ink-70);
}
.trad-note {
  font-family: var(--font-hei); font-size: var(--fs-12);
  color: var(--xj-ink-70); margin-left: auto; max-width: 26em; line-height: 1.7;
}

@media (max-width: 640px) {
  .trad-row { gap: 1rem; }
  .trad-note { margin-left: 0; }
}

/* 当季主推带：随节气换色，由 body[data-term-color] 驱动 */
.push-band {
  padding: var(--sp-mod) 0;
  background:
    linear-gradient(180deg, var(--xj-paper-sink) 0%, var(--xj-paper) 100%);
  border-top: 1px solid var(--hair);
  border-bottom: 1px solid var(--hair);
  position: relative; overflow: hidden;
}
.push-band::before {
  content: ""; position: absolute; inset: 0;
  background: var(--xj-term-wash, transparent);
  opacity: 0.5; pointer-events: none;
  transition: background var(--dur-4) var(--ease);
}
.push-grid {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 1.35fr 1fr; gap: 4rem; align-items: center;
}
.push-title {
  font-size: var(--fs-49); line-height: 1.1; margin: 0 0 0.5rem;
  color: var(--xj-vermilion);
}
.push-prod {
  font-family: var(--font-song); font-size: var(--fs-25);
  margin: 0 0 var(--sp-6); color: var(--xj-ink);
}
.push-why {
  font-size: var(--fs-16); line-height: 1.9;
  max-width: 30em; margin: 0; color: var(--xj-ink-70);
  border-left: 2px solid var(--xj-term-color, var(--xj-primary));
  padding-left: var(--sp-5);
}
.push-side {
  margin-top: 1.75rem; display: flex; align-items: center; gap: var(--sp-3);
  font-family: var(--font-hei); font-size: var(--fs-14); color: var(--xj-ink-70);
}
.push-side-art { display: flex; justify-content: center; align-items: center; }
.push-side-art svg { width: 100%; max-width: 320px; height: auto; }
.push-note { position: relative; z-index: 1; margin-top: var(--sp-10); }

@media (max-width: 1024px) {
  .push-grid { grid-template-columns: 1fr; gap: var(--sp-10); }
  .push-title { font-size: var(--fs-31); }
  .push-prod { font-size: var(--fs-20); }
}

.eyebrow {
  /* 2026-10-05 内测修：38% → 62%。实测 12px 的字在 38% 墨色上只有 2.15:1，
   * 读不清。38% 是给大字号做"弱化"用的，12px 已经在下限之下，
   * 弱化就该让位给可读性。 */
  font-family: var(--font-hei); font-size: var(--fs-12); font-weight: 400;
  letter-spacing: 0.32em; text-transform: uppercase; color: var(--xj-ink-70);
  display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-6);
}
.eyebrow::after { content: ""; flex: 1; height: 1px; background: var(--xj-ink-08); }
.eyebrow.is-vermilion { color: var(--xj-vermilion); }

h1 { font-size: var(--fs-49); }
h2 { font-size: var(--fs-31); }
h3 { font-size: var(--fs-20); }
h4 { font-size: var(--fs-16); }

.lede { font-size: var(--fs-20); line-height: 1.7; color: var(--xj-ink-70); font-weight: 400; }
.muted { color: var(--xj-ink-70); }
.small { font-size: var(--fs-14); }
.tiny { font-size: var(--fs-12); }
.serif-latin { font-family: var(--font-latin); letter-spacing: 0.06em; }
.num { font-family: var(--font-latin); font-size: var(--fs-25); line-height: 1; }

/* 左对齐为默认；仅 Hero 与仪式性内容居中 */
.center { text-align: center; }
.rule { height: 1px; background: var(--xj-ink-08); border: 0; margin: 0; }

/* --------------------------------------------------------------------------
   4. 核心符号 ☲ 离卦（标准 / 春候 / 秋候 / 火）
   符号不是贴上去的 logo，是空间本身的构件
   -------------------------------------------------------------------------- */
.mark { display: block; color: var(--xj-vermilion); }
.mark-line { stroke: currentColor; stroke-width: 2; stroke-linecap: square; fill: none; }
.mark-bud { fill: var(--xj-primary); }
.mark-drop { fill: var(--xj-primary); }
.mark-flame { fill: var(--xj-vermilion); }

@keyframes markSpread { 0% { transform: scaleX(0.1); } 100% { transform: scaleX(1); } }
.mark-anim .mark-line { transform-origin: center; animation: markSpread 720ms var(--ease) both; }
.mark-anim .mark-line:nth-child(2) { animation-delay: 90ms; }
.mark-anim .mark-line:nth-child(3) { animation-delay: 180ms; }

/* 背景水印：极淡，几乎不可见 */
.watermark {
  position: absolute; pointer-events: none; z-index: 0;
  color: var(--xj-ink); opacity: 0.032;
}
.wm-tr { top: 4%; right: 4%; width: 320px; }
.wm-bl { bottom: 2%; left: -4%; width: 280px; }
.wm-flame { color: var(--xj-vermilion); opacity: 0.04; }

/* --------------------------------------------------------------------------
   5. 导航
   -------------------------------------------------------------------------- */
.site-head {
  position: sticky; top: 0; z-index: 90;
  background: rgba(247, 244, 236, 0.92);
  backdrop-filter: saturate(1.1) blur(12px);
  border-bottom: var(--hair);
}
.head-in { display: flex; align-items: center; height: 76px; gap: var(--sp-10); }
.logo { display: flex; align-items: center; gap: var(--sp-3); flex-shrink: 0; }
.logo-seal {
  width: 34px; height: 34px; display: grid; place-items: center;
  border: 1.5px solid var(--xj-vermilion); color: var(--xj-vermilion);
}
.logo-seal svg { width: 20px; height: 20px; }
.logo-txt { display: flex; flex-direction: column; line-height: 1.1; }
.logo-txt b { font-size: var(--fs-16); font-weight: 400; letter-spacing: 0.16em; }
.logo-txt span {
  /* 2026-10-05 内测修：10px + 38% 墨色实测 2.15:1。
   * 这是「东方饮食生活方式策展人」——这个站最核心的一句自我说明，
   * 压在页头页脚。它读不清，这句话就等于不存在。提到 11px + 62%。 */
  font-family: var(--font-hei); font-size: 11px;
  letter-spacing: 0.20em; color: var(--xj-ink-70);
}

.nav { display: flex; align-items: center; gap: var(--sp-8); margin-left: auto; }
.nav a {
  font-size: var(--fs-14); color: var(--xj-ink-70); position: relative;
  padding: var(--sp-2) 0; transition: color var(--dur) var(--ease); white-space: nowrap;
}
.nav a::after {
  content: ""; position: absolute; left: 50%; right: 50%; bottom: 0; height: 1px;
  background: var(--xj-vermilion); transition: left var(--dur) var(--ease), right var(--dur) var(--ease);
}
.nav a:hover { color: var(--xj-ink); }
.nav a:hover::after, .nav a[aria-current="page"]::after { left: 0; right: 0; }
.nav a[aria-current="page"] { color: var(--xj-ink); }

.head-tools { display: flex; align-items: center; gap: var(--sp-4); flex-shrink: 0; }
.icon-btn {
  /* 触控底线写在这里，而不是另起一条后置规则：
     后置的同名类规则会和 .nav-toggle{display:none} 撞车——
     两者特异性相同（都是单类），后者在文件更后面就会赢，
     结果宽屏上汉堡按钮藏不住。教训：给基类补尺寸，别另开一条。 */
  min-width: var(--tap-min);
  min-height: var(--tap-min);
  width: var(--tap-min); height: var(--tap-min);
  display: grid; place-items: center;
  border: 1px solid var(--xj-ink-16); color: var(--xj-ink-70);
  transition: all var(--dur) var(--ease);
}
.icon-btn:hover { border-color: var(--xj-ink); color: var(--xj-ink); }
.icon-btn svg { width: 15px; height: 15px; }
/* 工具位的文字兜底（2026-10-27）
   原来 .tool-label 在样式表里根本没有规则：它继承正文的宋体 16px，
   塞进 44px 见方的按钮里必然折行——"AI 导购"就成了"AI 导 / 购"两行。
   正常情况下这里不会出现（构建期给的是火焰符号），
   但只要脚本走了兜底分支，就得有人接着。 */
.icon-btn-txt { min-width: auto; padding: 0 12px; }
.tool-label {
  font-family: var(--font-hei); font-size: var(--fs-12);
  letter-spacing: .06em; line-height: 1; white-space: nowrap;
}
.lang { font-family: var(--font-latin); font-size: var(--fs-12); letter-spacing: 0.1em; color: var(--xj-ink-70); }
.nav-toggle { display: none; }

/* 移动端导航抽屉：默认隐藏，由 .is-open 展开为全屏下拉面板 */
@media (max-width: 1024px) {
  .nav {
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    margin-left: 0; padding: var(--sp-2) var(--sp-6) var(--sp-6);
    background: var(--xj-paper); border-block: var(--hair);
    box-shadow: 0 20px 40px rgba(43, 42, 38, 0.12);
    max-height: calc(100vh - 76px); overflow-y: auto;
  }
  /* 折叠态必须真正不可见、不可聚焦，不能只是视觉隐藏 */
  .nav:not(.is-open) { display: none; }
  .nav.is-open { display: flex; }
  .nav a {
    padding: 1rem 0; font-size: var(--fs-16);
    border-bottom: 1px solid var(--xj-ink-08);
  }
  .nav a:last-child { border-bottom: 0; }
  .nav a::after { display: none; }
  .nav a[aria-current="page"] { color: var(--xj-vermilion); }
  /* 展开态头部压一层遮罩，点空白即收起 */
  .site-head.nav-open::after {
    content: ""; position: absolute; inset: 100% 0 -100vh 0;
    background: rgba(43, 42, 38, 0.28); z-index: -1;
  }
  .site-head { position: relative; }
}

/* 表格横向滚动容器：手机上表格不撑破布局 */
.table-scroll {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  border: var(--hair);
}
.table-scroll table { border: 0; }
.table-scroll .tbl { min-width: 720px; }

/* 节气当前状态条 */
.jieqi-bar {
  border-bottom: var(--hair); background: var(--xj-paper-raise);
  font-family: var(--font-hei); font-size: var(--fs-12); color: var(--xj-ink-52);
}
.jieqi-bar-in { display: flex; align-items: center; justify-content: space-between; height: 38px; gap: 1.5rem; }
.jieqi-now { display: flex; align-items: center; gap: var(--sp-2); }
.jieqi-dot { width: 5px; height: 5px; background: var(--xj-vermilion); border-radius: 50%; animation: pulse 2.4s var(--ease) infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
.jieqi-links { display: flex; gap: var(--sp-6); }
.jieqi-links a { color: var(--xj-ink-70); transition: color var(--dur) var(--ease); }
.jieqi-links a:hover, .jieqi-links a.is-now { color: var(--xj-vermilion); }

/* --------------------------------------------------------------------------
   6. 按钮
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-8); font-size: var(--fs-14);
  border: 1px solid var(--xj-ink); color: var(--xj-ink); background: transparent;
  transition: all var(--dur) var(--ease); position: relative; overflow: hidden;
  letter-spacing: 0.04em; white-space: nowrap;
}
.btn::before {
  content: ""; position: absolute; inset: 0; background: var(--xj-ink);
  transform: scaleY(0); transform-origin: bottom; transition: transform var(--dur) var(--ease); z-index: 0;
}
.btn span { position: relative; z-index: 1; }
.btn:hover { color: var(--xj-paper); }
.btn:hover::before { transform: scaleY(1); }
.btn-seal { border-color: var(--xj-vermilion); color: var(--xj-vermilion); }
.btn-seal::before { background: var(--xj-vermilion); }
.btn-seal:hover { color: var(--xj-paper); }
.btn-solid { background: var(--xj-ink); color: var(--xj-paper); }
.btn-solid::before { background: var(--xj-vermilion); }
.btn-solid:hover { color: var(--xj-paper); }
.btn-ghost { border-color: var(--xj-ink-16); color: var(--xj-ink-70); }
.btn-sm { padding: var(--sp-2) var(--sp-5); font-size: var(--fs-12); }
.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.arrow-link {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-14); color: var(--xj-ink); padding-bottom: 2px;
  border-bottom: 1px solid var(--xj-ink-16); transition: all var(--dur) var(--ease);
}
.arrow-link svg { width: 13px; height: 13px; transition: transform var(--dur) var(--ease); }
.arrow-link:hover { color: var(--xj-vermilion); border-color: var(--xj-vermilion); }
.arrow-link:hover svg { transform: translateX(4px); }

/* --------------------------------------------------------------------------
   7. Hero
   -------------------------------------------------------------------------- */
.hero { position: relative; padding: var(--sp-hero) 0 5rem; overflow: hidden; }
.hero-in { position: relative; z-index: 2; }
/* 2026-10-05 内测修：朱红字直接落在纸色上实测 1.52:1，读不清。
 * 印章是"这是哪个品牌的"——读不清就等于没有。
 * 给一个极淡的朱红底 + 朱红字，既守住对比度又不喧宾夺主。 */
.hero-seal {
  display: inline-flex; align-items: center; gap: var(--sp-3);
  margin-bottom: 2.25rem; align-self: flex-start;
  font-family: var(--font-hei); font-size: var(--fs-12); letter-spacing: 0.24em;
  color: var(--xj-vermilion);
  background: rgba(143, 61, 44, 0.09);
  padding: var(--sp-1) var(--sp-2);
}
.hero-seal::before { content: ""; width: 28px; height: 1px; background: var(--xj-vermilion); }
.hero h1 { font-size: var(--fs-hero); line-height: 1.22; max-width: 15em; }
.hero h1 em { font-style: normal; color: var(--xj-primary-deep); }
.hero-sub { margin-top: 1.75rem; font-size: var(--fs-20); color: var(--xj-ink-70); max-width: 26em; line-height: 1.7; }
.hero-meta {
  display: flex; flex-wrap: wrap; gap: var(--sp-10); margin-top: 3rem;
  padding-top: 2rem; border-top: var(--hair);
}
.hero-meta div { display: flex; flex-direction: column; gap: var(--sp-1); }
.hero-meta dt { font-family: var(--font-hei); font-size: var(--fs-12); letter-spacing: 0.2em; color: var(--xj-ink-70); }
.hero-meta dd { margin: 0; font-size: var(--fs-16); }
.hero-art { position: relative; aspect-ratio: 3 / 4; }

/* Hero 水墨视觉：以 CSS 晕染 + SVG 器物线描构建，不使用素材库通用图 */
.ink-wash {
  position: absolute; inset: 0; overflow: hidden;
  background:
    radial-gradient(ellipse 62% 48% at 28% 22%, var(--xj-primary-wash) 0%, transparent 68%),
    radial-gradient(ellipse 48% 40% at 76% 68%, var(--xj-vermilion-wash) 0%, transparent 70%),
    linear-gradient(168deg, var(--xj-paper-raise) 0%, var(--xj-paper-sink) 100%);
}
.ink-wash::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(ellipse 70% 55% at 50% 92%, rgba(43,42,38,0.10) 0%, transparent 70%);
}
.ink-figure { position: absolute; inset: 0; display: grid; place-items: center; }
.ink-figure svg { width: 74%; height: auto; color: var(--xj-ink); opacity: 0.5; }
.ink-figure .stroke { fill: none; stroke: currentColor; stroke-width: 1.1; stroke-linecap: round; }
.ink-figure .stroke-thin { fill: none; stroke: currentColor; stroke-width: 0.6; opacity: 0.7; }
.ink-figure .fill-wash { fill: var(--xj-primary); opacity: 0.14; }
.ink-figure .fill-warm { fill: var(--xj-vermilion); opacity: 0.1; }

/* AI 标记：告诉用户这一块是引擎实时生成的 */
.ai-tag {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--font-hei); font-size: 10px; letter-spacing: 0.2em;
  color: var(--xj-ink-70); border: 1px solid var(--xj-ink-08);
  padding: var(--sp-1) var(--sp-2); border-radius: 1px;
}
.ai-tag i { width: 4px; height: 4px; background: var(--xj-primary); border-radius: 50%; font-style: normal; }

/* --------------------------------------------------------------------------
   8. 卡片
   -------------------------------------------------------------------------- */
.card {
  background: var(--xj-paper-raise); border: var(--hair); padding: 1.75rem;
  position: relative; transition: all var(--dur) var(--ease);
  display: flex; flex-direction: column; gap: var(--sp-3);
}
.card:hover { border-color: var(--xj-ink-70); transform: translateY(-3px); }
.card-title { font-size: var(--fs-20); }
.card-body { font-size: var(--fs-14); color: var(--xj-ink-70); line-height: 1.8; }
.card-foot { margin-top: auto; padding-top: 1rem; }
.card-idx { font-family: var(--font-latin); font-size: var(--fs-14); color: var(--xj-ink-70); letter-spacing: 0.1em; }
.card-seal { position: absolute; top: 1.6rem; right: 1.8rem; color: var(--xj-vermilion); opacity: 0.8; }
.card-seal svg { width: 18px; height: 18px; }
.card-hover-line { position: absolute; left: 0; top: -1px; width: 0; height: 1px; background: var(--xj-vermilion); transition: width var(--dur) var(--ease); }
.card:hover .card-hover-line { width: 100%; }

.card-visual { position: relative; aspect-ratio: 4 / 3; overflow: hidden; background: var(--xj-paper-sink); }
.card-visual .ink-wash { transition: transform 720ms var(--ease); }
.card:hover .card-visual .ink-wash { transform: scale(1.04); }
/* 2026-10-05 内测修：原来 10px + 62% 黑底，叠在浅色水墨图上实测 1.04:1。
 * 问题不是"半透明好看"，是**10px 的字本来就已在可读下限之下**，
 * 对比度再不够等于没写。改成 11px + 82% 黑底 —— 图还透得出来（0.18），
 * 但文字稳了。实测提到 7:1 以上。 */
.card-visual-tag {
  position: absolute; left: 1rem; bottom: 1rem; z-index: 2;
  font-family: var(--font-hei); font-size: 11px; letter-spacing: 0.16em;
  color: var(--xj-paper); background: rgba(30,29,26,0.82);
  padding: var(--sp-1) var(--sp-2);
  backdrop-filter: blur(4px);
}

/* 场景九宫格 */
.grid-9 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--xj-ink-08); border: var(--hair); }
.cell {
  background: var(--xj-paper); padding: 2.25rem 1.75rem; position: relative;
  transition: background var(--dur) var(--ease); min-height: 190px;
  display: flex; flex-direction: column; gap: var(--sp-2);
}
.cell:hover { background: var(--xj-paper-raise); }
.cell-name { font-size: var(--fs-20); display: flex; align-items: baseline; gap: var(--sp-3); }
.cell-time { font-family: var(--font-latin); font-size: var(--fs-12); color: var(--xj-ink-70); letter-spacing: 0.08em; }
.cell-hook { font-size: var(--fs-14); color: var(--xj-ink-70); line-height: 1.75; }
.cell-brands { margin-top: auto; display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.chip {
  /* 2026-10-05 内测修：52%（约 3.5:1）配 10px 不够。提到 62% + 11px。 */
  font-family: var(--font-hei); font-size: 11px; letter-spacing: 0.12em;
  border: 1px solid var(--xj-ink-16); padding: var(--sp-1) 0.5rem; color: var(--xj-ink-70);
}
.chip-seal { border-color: var(--xj-vermilion); color: var(--xj-vermilion); }
.cell.is-now { background: var(--xj-primary-wash); }
.cell.is-now .cell-name::after {
  content: "此刻"; font-family: var(--font-hei); font-size: var(--fs-11); letter-spacing: 0.18em;
  color: var(--xj-vermilion); border: 1px solid var(--xj-vermilion); padding: var(--sp-1) var(--sp-1);
}

/* 品牌家族横向陈列 */
.brand-row { display: flex; flex-wrap: wrap; border-top: var(--hair); border-left: var(--hair); }
.brand-item {
  flex: 1 1 200px; border-right: var(--hair); border-bottom: var(--hair);
  padding: 2rem var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-3);
  min-height: 150px; transition: background var(--dur) var(--ease);
}
.brand-item:hover { background: var(--xj-primary-wash); }
.brand-item h4 { font-size: var(--fs-16); letter-spacing: 0.06em; }
.brand-item p { font-size: var(--fs-12); color: var(--xj-ink-70); line-height: 1.7; }
.brand-mark { color: var(--xj-primary); }
.brand-mark svg { width: 26px; height: 26px; }

/* --------------------------------------------------------------------------
   9. 节气时间轴
   -------------------------------------------------------------------------- */
.timeline { position: relative; padding: 3rem 0; overflow-x: auto; }
.timeline-track { display: flex; gap: 0; min-width: max-content; position: relative; padding-top: var(--sp-10); }
.timeline-track::before { content: ""; position: absolute; top: 6px; left: 0; right: 0; height: 1px; background: var(--xj-ink-08); }
.tl-item { position: relative; padding: 0 1.5rem; min-width: 96px; text-align: center; }
.tl-item::before {
  content: ""; position: absolute; top: -2.6rem; left: 50%; transform: translateX(-50%);
  width: 5px; height: 5px; background: var(--xj-ink-16); border-radius: 50%;
  transition: all var(--dur) var(--ease);
}
.tl-item:hover::before { background: var(--xj-primary); }
.tl-item.is-now::before { background: var(--xj-vermilion); width: 7px; height: 7px; box-shadow: 0 0 0 4px var(--xj-vermilion-wash); }
.tl-name { font-size: var(--fs-14); color: var(--xj-ink-70); display: block; }
.tl-item.is-now .tl-name { color: var(--xj-vermilion); }
.tl-date { font-family: var(--font-latin); font-size: 10px; color: var(--xj-ink-70); letter-spacing: 0.06em; }
.tl-season-tag { position: absolute; top: -4.4rem; left: 0; right: 0; font-family: var(--font-hei); font-size: var(--fs-11); letter-spacing: 0.2em; color: var(--xj-ink-70); }

/* 五食辰时间轴 */
.shichen { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1px; background: var(--xj-ink-08); border-block: var(--hair); }
.shichen-item { background: var(--xj-paper); padding: 2rem var(--sp-6); text-align: left; transition: background var(--dur) var(--ease); }
.shichen-item:hover { background: var(--xj-paper-raise); }
.shichen-item.is-now { background: var(--xj-primary-wash); }
.shichen-name { font-size: var(--fs-20); margin-bottom: var(--sp-1); }
.shichen-time { font-family: var(--font-latin); font-size: var(--fs-12); color: var(--xj-ink-70); letter-spacing: 0.06em; }
.shichen-mood { font-size: var(--fs-12); color: var(--xj-ink-70); margin-top: var(--sp-3); line-height: 1.7; }

/* --------------------------------------------------------------------------
   10. 内容：文章、食谱、引用
   -------------------------------------------------------------------------- */
.prose { max-width: 40em; }
.prose p { margin-bottom: var(--sp-6); color: var(--xj-ink-70); }
.prose h3 { margin: 3rem 0 var(--sp-5); font-size: var(--fs-25); }
.prose h4 { margin: 2.25rem 0 var(--sp-4); font-size: var(--fs-16); }
.prose blockquote {
  margin: var(--sp-10) 0; padding: var(--sp-6) 0 var(--sp-6) 1.75rem;
  border-left: 2px solid var(--xj-vermilion); color: var(--xj-ink-70); font-size: var(--fs-20);
  line-height: 1.7;
}
.prose ul { margin: 0 0 var(--sp-6); }
.prose ul li { position: relative; padding-left: var(--sp-6); margin-bottom: var(--sp-2); color: var(--xj-ink-70); }
.prose ul li::before { content: ""; position: absolute; left: 0; top: 0.95em; width: 5px; height: 1px; background: var(--xj-vermilion); }
.prose figure { margin: var(--sp-10) 0; }
.prose figcaption { font-size: var(--fs-12); color: var(--xj-ink-70); margin-top: var(--sp-3); }

.pullquote { text-align: center; padding: 4rem 0; }
.pullquote p { font-size: var(--fs-31); line-height: 1.5; max-width: 20em; margin: 0 auto; }
.pullquote cite { display: block; margin-top: var(--sp-6); font-style: normal; font-family: var(--font-hei); font-size: var(--fs-12); letter-spacing: 0.2em; color: var(--xj-ink-70); }

/* 三候 */
.hou { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--xj-ink-08); border: var(--hair); }
.hou-item { background: var(--xj-paper); padding: 1.75rem var(--sp-6); }
.hou-n { font-family: var(--font-latin); font-size: var(--fs-12); color: var(--xj-vermilion); letter-spacing: 0.2em; }
.hou-name { font-size: var(--fs-16); margin: 0.5rem 0 var(--sp-2); }
.hou-desc { font-size: var(--fs-12); color: var(--xj-ink-70); line-height: 1.7; }

/* 食材 / SKU 网格 */
.ing-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--xj-ink-08); border: var(--hair); }
.ing-item { background: var(--xj-paper); padding: var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-2); transition: background var(--dur) var(--ease); }
.ing-item:hover { background: var(--xj-paper-raise); }
.ing-name { font-size: var(--fs-16); }
.ing-desc { font-size: var(--fs-12); color: var(--xj-ink-70); line-height: 1.7; }
.ing-from { font-family: var(--font-hei); font-size: 10px; letter-spacing: 0.14em; color: var(--xj-ink-70); }

.sku-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-6); }
.sku { background: var(--xj-paper-raise); border: var(--hair); display: flex; flex-direction: column; transition: all var(--dur) var(--ease); }
.sku:hover { border-color: var(--xj-ink-70); transform: translateY(-3px); }
.sku-visual { position: relative; aspect-ratio: 1; overflow: hidden; }
.sku-visual .ink-wash { inset: 0; }
.sku-body { padding: var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-2); flex: 1; }
.sku-brand { font-family: var(--font-hei); font-size: 10px; letter-spacing: 0.2em; color: var(--xj-vermilion); }
.sku-name { font-size: var(--fs-16); }
.sku-spec { font-size: var(--fs-12); color: var(--xj-ink-70); }
.sku-foot { margin-top: auto; padding-top: 1rem; display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; }
.sku-price { font-family: var(--font-latin); font-size: var(--fs-20); }
.sku-price small { font-size: var(--fs-12); color: var(--xj-ink-70); }
.sku-note { font-size: 11px; color: var(--xj-ink-70); font-family: var(--font-hei); line-height: 1.6; }

/* --------------------------------------------------------------------------
   11. 表单与线索
   -------------------------------------------------------------------------- */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-6) 2rem; }
.field { display: flex; flex-direction: column; gap: 0.5rem; }
.field-full { grid-column: 1 / -1; }
.field label { font-family: var(--font-hei); font-size: var(--fs-12); letter-spacing: 0.16em; color: var(--xj-ink-70); }
.field label i { color: var(--xj-vermilion); font-style: normal; }
.field input, .field select, .field textarea {
  font: inherit; font-size: var(--fs-14); color: var(--xj-ink);
  background: transparent; border: 0; border-bottom: 1px solid var(--xj-ink-16);
  padding: var(--sp-3) 0; transition: border-color var(--dur) var(--ease); width: 100%;
  border-radius: 0; font-family: var(--font-hei);
}
.field textarea { min-height: 110px; resize: vertical; line-height: 1.7; }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--xj-vermilion); }
.field input::placeholder, .field textarea::placeholder { color: var(--xj-ink-16); }
.check { display: flex; gap: var(--sp-3); align-items: flex-start; font-family: var(--font-hei); font-size: var(--fs-12); color: var(--xj-ink-70); line-height: 1.7; cursor: pointer; }
.check input { appearance: none; width: 14px; height: 14px; border: 1px solid var(--xj-ink-38); flex-shrink: 0; margin-top: 2px; position: relative; cursor: pointer; }
.check input:checked { background: var(--xj-vermilion); border-color: var(--xj-vermilion); }
.check input:checked::after { content: ""; position: absolute; left: 4px; top: 1px; width: 4px; height: 8px; border: solid var(--xj-paper); border-width: 0 1.5px 1.5px 0; transform: rotate(45deg); }

/* 线索分层说明 */
.tier { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--xj-ink-08); border: var(--hair); }
.tier-item { background: var(--xj-paper); padding: var(--sp-6) var(--sp-6); }
.tier-grade { font-family: var(--font-latin); font-size: var(--fs-25); color: var(--xj-vermilion); }
.tier-range { font-size: var(--fs-12); color: var(--xj-ink-70); font-family: var(--font-latin); }
.tier-strategy { font-size: var(--fs-12); color: var(--xj-ink-70); margin-top: var(--sp-3); line-height: 1.7; }

/* --------------------------------------------------------------------------
   12. AI 对话（隐形服务者）
   -------------------------------------------------------------------------- */
.chat-fab {
  position: fixed; right: 1.8rem; bottom: 1.8rem; z-index: 80;
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-5); background: var(--xj-ink); color: var(--xj-paper);
  box-shadow: 0 6px 24px rgba(43,42,38,0.16);
  transition: all var(--dur) var(--ease);
}
.chat-fab:hover { background: var(--xj-vermilion); }
.chat-fab svg { width: 16px; height: 16px; }
.chat-fab span { font-size: var(--fs-14); letter-spacing: 0.06em; }

.chat-panel {
  position: fixed; right: 1.8rem; bottom: 1.8rem; z-index: 95;
  width: 380px; max-width: calc(100vw - 2.4rem); height: 540px; max-height: calc(100vh - 3.6rem);
  background: var(--xj-paper); border: var(--hair);
  display: flex; flex-direction: column;
  opacity: 0; transform: translateY(12px); pointer-events: none;
  transition: all var(--dur) var(--ease);
  box-shadow: 0 12px 48px rgba(43,42,38,0.14);
}
.chat-panel.is-open { opacity: 1; transform: translateY(0); pointer-events: auto; }
.chat-head { padding: var(--sp-4) var(--sp-5); border-bottom: var(--hair); display: flex; align-items: center; gap: var(--sp-3); }
.chat-head b { font-size: var(--fs-14); font-weight: 400; letter-spacing: 0.08em; }
.chat-head .ai-tag { margin-left: auto; }
.chat-close { font-size: 20px; line-height: 1; color: var(--xj-ink-70); }
.chat-body { flex: 1; overflow-y: auto; padding: var(--sp-5); display: flex; flex-direction: column; gap: 1rem; }
.msg { max-width: 84%; padding: var(--sp-3) 1rem; font-size: var(--fs-14); line-height: 1.7; animation: fadeUp var(--dur) var(--ease) both; }
.msg-bot { background: var(--xj-paper-sink); align-self: flex-start; }
.msg-user { background: var(--xj-ink); color: var(--xj-paper); align-self: flex-end; }
.msg-bot a { color: var(--xj-vermilion); border-bottom: 1px solid var(--xj-vermilion); }
.chat-quick { display: flex; flex-wrap: wrap; gap: var(--sp-2); padding: 0 var(--sp-5) var(--sp-4); }
.chat-quick button {
  font-family: var(--font-hei); font-size: 11px; color: var(--xj-ink-52);
  border: 1px solid var(--xj-ink-16); padding: var(--sp-1) var(--sp-2);
  transition: all var(--dur) var(--ease);
}
.chat-quick button:hover { border-color: var(--xj-vermilion); color: var(--xj-vermilion); }
.chat-input { border-top: var(--hair); padding: var(--sp-4) var(--sp-5); display: flex; gap: var(--sp-3); align-items: center; }
.chat-input input { flex: 1; border: 0; background: transparent; font: inherit; font-size: var(--fs-14); font-family: var(--font-hei); }
.chat-input input:focus { outline: none; }
.chat-note { font-size: 10px; color: var(--xj-ink-70); font-family: var(--font-hei); padding: 0 var(--sp-5) var(--sp-4); line-height: 1.6; }

/* 站内搜索 */
.search-ov {
  position: fixed; inset: 0; z-index: 100; background: rgba(247,244,236,0.97);
  backdrop-filter: blur(8px);
  opacity: 0; pointer-events: none; transition: opacity var(--dur) var(--ease);
  display: flex; align-items: flex-start; justify-content: center; padding-top: 14vh;
}
.search-ov.is-open { opacity: 1; pointer-events: auto; }
.search-box { width: 100%; max-width: 680px; padding: 0 2rem; }
.search-in { display: flex; align-items: center; gap: 1rem; border-bottom: 1px solid var(--xj-ink); padding-bottom: 1rem; }
.search-in input { flex: 1; border: 0; background: transparent; font: inherit; font-size: var(--fs-25); font-family: var(--font-song); }
.search-in input:focus { outline: none; }
.search-hint { margin-top: var(--sp-5); font-family: var(--font-hei); font-size: var(--fs-12); color: var(--xj-ink-70); letter-spacing: 0.1em; }
.search-res { margin-top: 2rem; display: flex; flex-direction: column; }
.search-res a { padding: var(--sp-4) 0; border-bottom: var(--hair); display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; }
.search-res a:hover { color: var(--xj-vermilion); }
.search-res .sr-type { font-family: var(--font-hei); font-size: 10px; letter-spacing: 0.2em; color: var(--xj-ink-70); flex-shrink: 0; }

/* --------------------------------------------------------------------------
   13. 数据 / 表格 / 流程
   -------------------------------------------------------------------------- */
.tbl { width: 100%; border-collapse: collapse; font-size: var(--fs-14); }
.tbl th, .tbl td { text-align: left; padding: 1rem var(--sp-5); border-bottom: var(--hair); vertical-align: top; }
.tbl th { font-family: var(--font-hei); font-size: var(--fs-12); font-weight: 400; letter-spacing: 0.16em; color: var(--xj-ink-70); }
.tbl td { color: var(--xj-ink-70); }
.tbl tr:hover td { background: var(--xj-primary-wash); }
.tbl td b { color: var(--xj-ink); font-weight: 400; }

.stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2rem; padding: var(--sp-10) 0; border-block: var(--hair); }
.stat { display: flex; flex-direction: column; gap: 0.5rem; }
.stat-n { font-family: var(--font-latin); font-size: var(--fs-39); color: var(--xj-primary-deep); line-height: 1; }
.stat-l { font-family: var(--font-hei); font-size: var(--fs-12); letter-spacing: 0.14em; color: var(--xj-ink-70); line-height: 1.6; }

.flow { display: flex; align-items: stretch; gap: 0; overflow-x: auto; }
.flow-step { flex: 1; min-width: 150px; padding: var(--sp-6) var(--sp-6); border-left: var(--hair); position: relative; }
.flow-step:last-child { border-right: var(--hair); }
.flow-n { font-family: var(--font-latin); font-size: var(--fs-12); color: var(--xj-vermilion); letter-spacing: 0.16em; }
.flow-t { font-size: var(--fs-14); margin: 0.5rem 0 var(--sp-2); }
.flow-d { font-size: var(--fs-12); color: var(--xj-ink-70); line-height: 1.7; }
.flow-step::after { content: ""; position: absolute; right: -4px; top: 50%; width: 7px; height: 1px; background: var(--xj-ink-16); z-index: 2; }

/* 架构图：五层 */
.layer { border: var(--hair); padding: 1.75rem; display: grid; grid-template-columns: 200px 1fr; gap: 2rem; align-items: start; }
.layer + .layer { border-top: 0; }
.layer-tag { font-family: var(--font-hei); font-size: var(--fs-12); letter-spacing: 0.16em; color: var(--xj-ink-70); }
.layer-name { font-size: var(--fs-20); margin-top: var(--sp-2); }
.layer-body { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* Agent 名录 */
.agent-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--xj-ink-08); border: var(--hair); }
.agent { background: var(--xj-paper); padding: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-1); }
.agent-n { font-family: var(--font-latin); font-size: 10px; color: var(--xj-ink-70); letter-spacing: 0.14em; }
.agent-t { font-size: var(--fs-14); }
.agent-d { font-size: 11px; color: var(--xj-ink-70); line-height: 1.6; }
.agent-cat { font-family: var(--font-hei); font-size: var(--fs-11); letter-spacing: 0.16em; color: var(--xj-vermilion); margin-top: auto; padding-top: 0.5rem; }

/* --------------------------------------------------------------------------
   14. 页脚
   -------------------------------------------------------------------------- */
.site-foot { background: var(--xj-paper-sink); border-top: var(--hair); padding: 4.5rem 0 2rem; margin-top: 2rem; }
.foot-top { display: grid; grid-template-columns: 1.3fr repeat(5, 1fr); gap: 2.25rem; }
.foot-brand p { font-size: var(--fs-12); color: var(--xj-ink-70); line-height: 1.8; margin-top: var(--sp-5); max-width: 22em; }
.foot-h { font-family: var(--font-hei); font-size: var(--fs-12); letter-spacing: 0.18em; color: var(--xj-ink-70); margin-bottom: 1rem; }
.foot-list li { margin-bottom: var(--sp-2); }
.foot-list a { font-size: var(--fs-12); color: var(--xj-ink-70); transition: color var(--dur) var(--ease); }
.foot-list a:hover { color: var(--xj-vermilion); }
.foot-bot {
  margin-top: 3.5rem; padding-top: var(--sp-6); border-top: var(--hair);
  display: flex; flex-wrap: wrap; gap: var(--sp-5) var(--sp-10); justify-content: space-between;
  font-family: var(--font-hei); font-size: 11px; color: var(--xj-ink-70); line-height: 1.8;
}
.foot-bot a:hover { color: var(--xj-vermilion); }

/* --------------------------------------------------------------------------
   15. 动效：渐显 + 微位移，克制、无弹跳
   -------------------------------------------------------------------------- */
@keyframes fadeUp { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.reveal { opacity: 0; }
.reveal.is-in { animation: fadeUp 700ms var(--ease) forwards; }
.d1 { animation-delay: 60ms; } .d2 { animation-delay: 140ms; } .d3 { animation-delay: 220ms; }
.d4 { animation-delay: 300ms; } .d5 { animation-delay: 380ms; } .d6 { animation-delay: 460ms; }

/* --------------------------------------------------------------------------
   16. 响应式
   设计口径：三档断点 1200 / 900 / 640。
   - 1200：内容过宽伤行长，先收窄栅格与留白
   -900：  导航折为抽屉，多列网格降为两列，横向轴改为纵向
   - 640：  手机基线，所有多列归一，装饰性视觉隐藏，触控目标放大到 44px
   -------------------------------------------------------------------------- */

/* --- 1200：收窄栅格 --- */
@media (max-width: 1024px) {
  /* 窄一档：间距整体降一档，而不是随手填一个数。
     降档规则：--sp-mod 120→80，--sp-par 32→28，--sp-hero 200→128。
     写死 1.8rem 这种离格值，下一次有人调间距就会对不上。 */
  :root { --sp-par: 1.75rem; --sp-mod: var(--sp-20); --sp-hero: var(--sp-32); }
  .grid { gap: var(--sp-6); }
  .wrap { padding: 0 var(--sp-10); }
  /* Hero 字号：原来这里写死 var(--fs-49)，那会把根上的 clamp 直接掐死——
     视口 ≤1200 时流体字号根本不生效，新设计只在超宽屏看得见，
     而超宽屏恰恰是最不需要大字的那一档。
     降档靠降 clamp 的上限，不是靠换掉 clamp。 */
  :root { --fs-hero: clamp(2.3125rem, 1.25rem + 2.2vw, 3.75rem); }
  .layer { grid-template-columns: 170px 1fr; }
}

@media (max-width: 1024px) {
  .nav { display: none; }
  .nav-toggle { display: grid; }
  .col-3, .col-4 { grid-column: span 6; }
  .agent-grid, .ing-grid { grid-template-columns: repeat(2, 1fr); }
  .foot-top { grid-template-columns: 1fr 1fr 1fr; }
  .shichen { grid-template-columns: repeat(2, 1fr); }
  .layer { grid-template-columns: 1fr; gap: 1rem; }
  .sku-grid { grid-template-columns: repeat(2, 1fr); }
  .tier { grid-template-columns: repeat(2, 1fr); }
  .hou { grid-template-columns: repeat(3, 1fr); }
}

/* --- 900：平板 --- */
@media (max-width: 1024px) {
  .grid { gap: var(--sp-6); }
  .col-5, .col-6, .col-7, .col-8, .col-9 { grid-column: span 12; }
  .col-3, .col-4 { grid-column: span 6; }
  .push-grid { grid-template-columns: 1fr; gap: var(--sp-10); }
  .push-title { font-size: var(--fs-31); }
  .push-prod { font-size: var(--fs-20); }
  .hero-meta { grid-template-columns: repeat(2, 1fr); }
  .grid-9 { grid-template-columns: repeat(2, 1fr); }
  .hou { grid-template-columns: 1fr; }
  .stat-row { grid-template-columns: repeat(2, 1fr); gap: var(--sp-6); }
  /* 二十四节气时轴：横向滚动改纵向列表，避免小屏内嵌滚动陷阱 */
  .timeline { overflow-x: visible; padding: var(--sp-6) 0; }
  .timeline-track {
    min-width: 0; flex-direction: column; padding-top: 0;
    display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px;
    background: var(--xj-ink-08); border: var(--hair);
  }
  .timeline-track::before { display: none; }
  /* 五食辰轴：两列 */
  .shichen { grid-template-columns: repeat(2, 1fr); }
  .shichen-item { padding: 1.5rem var(--sp-5); }
  .table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  table { min-width: 640px; }
}

/* --- 640：手机基线 --- */
@media (max-width: 640px) {
  /* 手机档：再降一档。--sp-mod 80→56，--sp-hero 128→56，--sp-par 28→24。
     手机上模块间距不必给到 120 —— 屏幕高度是最稀缺的资源。 */
  :root { --sp-mod: 3.5rem; --sp-hero: 3.5rem; --sp-par: var(--sp-6); }
  .wrap { padding: 0 var(--sp-6); }

  /* 横向溢出总兜底：任何子元素都不得撑破视口 */
  html, body { max-width: 100%; overflow-x: hidden; }
  img, svg, video { max-width: 100%; height: auto; }

  /* 640 档原来写死 h1/.hero h1 为 var(--fs-31) —— 这与 1200 档刚修好的
     做法自相矛盾：那里改成"降clamp 的上限"，这里却把 clamp 整个掐死。
     后果是 ≤640px 时 --fs-hero 完全失效，而且 641px(37px) → 640px(31px)
     出现 6px 跳变断崖。
     规矩是同一条：降档靠降 clamp 的上限，不是靠换掉 clamp。 */
  :root { --fs-hero: clamp(1.9375rem, 1.05rem + 4.4vw, 2.875rem); }
  h2 { font-size: var(--fs-25); }
  h3 { font-size: var(--fs-20); }
  .hero { padding-bottom: 3rem; }
  .hero-art { display: none; }
  .hero-in { text-align: left; }
  .hero-meta { grid-template-columns: 1fr 1fr; gap: var(--sp-5); }
  .btn-row .btn { flex: 1 1 100%; text-align: center; }

  /* 所有多列归一 */
  .grid-9, .hou, .tier, .sku-grid, .shichen, .agent-grid, .ing-grid,
  .form-grid, .foot-top, .stat-row, .timeline-track { grid-template-columns: 1fr; }
  .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9 { grid-column: span 12; }

  /* 触控目标不小于 44px */
  .btn { padding: var(--sp-4) var(--sp-6); min-height: 44px; display: inline-flex; align-items: center; }
  .cell { padding: var(--sp-6) var(--sp-5); }
  .nav-toggle { width: 44px; height: 44px; }
  .chat-fab { width: 52px; height: 52px; }
  .cell, .card, .brand-item, .shichen-item { min-height: 44px; }

  .chat-panel { right: 0.8rem; left: 0.8rem; width: auto; bottom: 0.8rem; }
  .chat-fab { right: 0.8rem; bottom: 0.8rem; }
  .search-ov .search-box { width: calc(100% - 2.8rem); }

  .brand-row { flex-direction: column; }
  .brand-item { padding: var(--sp-6) var(--sp-5); }

  .layer { padding: var(--sp-6) var(--sp-5); }
  .hou-item, .tier-item { padding: var(--sp-6) var(--sp-5); }

  .push-title { font-size: var(--fs-31); }
  .push-why { font-size: var(--fs-14); padding-left: 1rem; }

  table { min-width: 560px; font-size: var(--fs-12); }
  .table-scroll::after {
    content: "← 左右滑动查看完整表格"; display: block; margin-top: var(--sp-2);
    font-size: var(--fs-12); color: var(--xj-ink-70);
  }

  /* 流程轴：横向滚动改纵向堆叠，不留内嵌滚动陷阱 */
  .flow { flex-direction: column; overflow-x: visible; }
  .flow-step { min-width: 0; border-left: var(--hair); border-right: var(--hair); border-bottom: 0; padding: var(--sp-5) var(--sp-5); }
  .flow-step:last-child { border-bottom: var(--hair); }
  .flow-step::after { display: none; }

  /* 水印缩小，避免在窄屏糊住内容 */
  .wm-tr { width: 180px; opacity: 0.05; top: 2%; right: -6%; }
  .wm-bl { width: 150px; opacity: 0.04; bottom: 1%; left: -8%; }
}

/* 超窄屏 380px 以下：五食辰与时间轴进一步压缩 */
@media (max-width: 640px) {
  .wrap { padding: 0 1rem; }
  .hero-meta { grid-template-columns: 1fr; }
  .stat-row { grid-template-columns: 1fr; }
}

/* 触屏设备取消 hover 位移效果，避免"粘住"的错位感 */
@media (hover: none) {
  .card:hover { transform: none; }
  .card:hover .card-hover-line { width: 0; }
  .card-visual .ink-wash { transform: none !important; }
}

/* --------------------------------------------------------------------------
   17. 无障碍与降级
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; }
}
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--xj-ink); color: var(--xj-paper); padding: var(--sp-3) var(--sp-5); font-size: var(--fs-14);
}
.skip-link:focus { left: 1rem; top: 1rem; }
:focus-visible { outline: 2px solid var(--xj-primary); outline-offset: 3px; }

@media print {
  .site-head, .site-foot, .chat-fab, .chat-panel, .search-ov { display: none !important; }
  body { background: #fff; }
}

/* ==========================================================================
   Hero 四时态对比稿（设计决策稿专用）
   四态并排：宽屏 2×2，手机单列。不用横向滑动——四块要看的是差异，
   滑动会把「并排比较」这个动作毁掉。
   ========================================================================== */
.hc-grid{
  display:grid;grid-template-columns:repeat(2,1fr);
  gap: var(--sp-6);
}
.hc{
  /* 组件级动态色：生成器按节气在行内注入 --hc / --hc-sub。
     这里必须给默认值 —— 行内样式万一缺失，没有默认值时
     var(--hc) 会让整条声明失效（边框变无、文字颜色继承），
     页面看着"少了一块"却没有任何报错。
     缺省取当季主色，与 --xj-primary 同源。 */
  --hc: var(--xj-primary);
  --hc-sub: var(--xj-mist);
  background:var(--xj-paper);border:1px solid var(--xj-ink-16);
  border-top:3px solid var(--hc);
  padding: 1.75rem var(--sp-6) var(--sp-6);
  display:flex;flex-direction:column;
}
.hc-top{
  display:flex;align-items:baseline;gap: var(--sp-3);
  padding-bottom: var(--sp-4);margin-bottom: var(--sp-4);
  border-bottom:1px solid var(--xj-ink-16);
}
.hc-season{
  font-family:var(--font-song);font-size:var(--fs-31);line-height:1;
  color:var(--hc);letter-spacing:.05em;
}
.hc-term{font-size:13px;letter-spacing:.14em;color:var(--xj-ink-70)}
.hc-hou{margin-left:auto;font-size:11px;letter-spacing:.1em;color:var(--xj-ink-70)}

/* 色名署名：这是全案传统色的可追溯入口 */
.hc-color{
  display:flex;align-items:center;gap: var(--sp-2);flex-wrap:wrap;
  font-size:11px;color:var(--xj-ink-70);margin-bottom: var(--sp-6);
}
.hc-dot{
  width:9px;height:9px;background:var(--hc);
  border:1px solid rgba(43,42,38,.15);border-radius:50%;
}
.hc-dot-s{background:var(--hc-sub);margin-left:.5rem}
.hc-color b{font-weight:bold;color:var(--xj-ink-70);font-size:12px}

.hc-title{
  margin: 0 0 var(--sp-4);font-family:var(--font-song);
  font-size:var(--fs-25);line-height:1.42;font-weight:400;letter-spacing:.02em;
}
.hc-title em{font-style:normal;color:var(--hc)}

.hc-why{margin: 0 0 var(--sp-6);font-size:13px;line-height:1.9;color:var(--xj-ink-70)}

/* 当季主推：与线上首页同一份数据，不是另编一套 */
.hc-push{
  background:var(--xj-paper-raise);border-left:2px solid var(--hc);
  padding: 1rem var(--sp-4);margin-bottom: var(--sp-6);
}
.hc-brand{
  margin: var(--sp-1) 0 var(--sp-2);font-family:var(--font-song);
  font-size:20px;color:var(--xj-ink);
}
.hc-push-why{margin: .5rem 0 0;line-height:1.8;color:var(--xj-ink-70)}

.hc-note{
  margin-top:auto;padding-top: var(--sp-4);border-top:1px dashed var(--xj-ink-16);
}
.hc-note .hc-why{font-size:12px;line-height:1.85;margin-bottom:.6rem}
.hc-dir{
  margin: 0;font-size:12px;line-height:1.85;color:var(--xj-ink-70);
  background:var(--xj-paper-raise);padding: var(--sp-3) var(--sp-3);
}
.hc-dir b{color:var(--xj-ink)}

@media (max-width: 1024px){
  .hc-grid{grid-template-columns:1fr;gap:1rem}
  .hc{padding:1.4rem 1.2rem 1.2rem}
  .hc-title{font-size:var(--fs-20);line-height:1.4}
  .hc-season{font-size:24px}
}
@media (max-width:640px){
  .hc-top{flex-wrap:wrap;gap:.4rem .7rem}
  .hc-hou{margin-left: 0;flex-basis:100%}
  .hc-title{font-size:21px}
  .hc-brand{font-size:18px}
}

/* ==========================================================================
   顶栏窄屏收纳（实测发现）
   390px / 360px 下 .head-tools 里的登录 + 搜索 + 语言 + AI导购 四个
   加起来 116px 放不下，被祖先 overflow 裁掉——页面不溢出，但内容被切。
   这类"看着没事其实少了东西"的症状，只能靠量发现。
   处置：窄屏只留 搜索 + 汉堡，登录与 AI 入口移进抽屉。
   ========================================================================== */
@media (max-width: 640px) {
  .head-tools { gap: 0.5rem; flex-shrink: 1; min-width: 0; }
  /* 语言切换与 AI 导购：次要，收进抽屉 */
  .head-tools > .lang,
  .head-tools > a[href*="ai/"] { display: none; }
  /* 图标按钮不小于触控底线 44px。原来写 40px，会被 min 值吃掉，等于没写。 */
  .head-tools .icon-btn,
  .head-tools .nav-toggle { width: var(--tap-min); height: var(--tap-min); }
  .head-login {
    font-size: 11px; padding: 0.5rem var(--sp-2); letter-spacing: 0.04em;
    white-space: nowrap;
  }
}
@media (max-width: 640px) {
  /* 极窄：登录也收进抽屉，顶栏只留两个按钮 */
  .head-tools > .head-login { display: none; }
}

/* --- 窄屏专属入口：JS 会搬进 .nav 末尾，这里只给样式 --- */
@media (max-width: 640px) {
  .nav-extra-a {
    display: block; padding: 1rem 0; font-size: var(--fs-16);
    border-bottom: 1px solid var(--xj-ink-08); color: var(--xj-ink);
  }
  .nav-extra-lang {
    display: block; padding: 1rem 0; font-family: var(--font-latin);
    font-size: var(--fs-14); letter-spacing: 0.1em; color: var(--xj-ink-70);
  }
  /* 搬进 nav 后由 nav 的 flex column 排布，不再需要额外容器样式 */
  .nav-extra { display: contents; }
}

/* ==========================================================================
   栅格里的卡片默认列宽（实测发现的结构性 bug）
   问题：<div class="grid"><a class="card"> 这种写法，.card 没有 col-* 类，
   在 12 列栅格里只占 1 格（1/12 宽），卡片被压到 112px，内容溢出。
   全站 55 处中招（jieqi/changjing/coop 等），**桌面端也是错的**，
   只是桌面端溢出不明显，看起来像"卡片窄了点"。
   处置：在 CSS 层兜住——直接子元素是卡片时默认 span 4（桌面 3 列），
   窄屏再收到 span 12。不用改 55 处 HTML。
   ========================================================================== */
.grid > .card,
.grid > a.card,
.grid > .sku,
.grid > .cell { grid-column: span 4; }

@media (max-width: 1024px) {
  .grid > .card, .grid > a.card,
  .grid > .sku, .grid > .cell { grid-column: span 6; }
}
@media (max-width: 640px) {
  .grid > .card, .grid > a.card,
  .grid > .sku, .grid > .cell { grid-column: span 12; }
}

/* --- 搜索面板窄屏（实测：input 超 78px）--- */
/* flex 项目默认 min-width:auto，不加 min-width:0 就缩不到内容宽度以下。
   placeholder「搜节气、搜食材、搜场景」+ fs-25 在 360 视口必然撑破。 */
.search-in input { min-width: 0; }
@media (max-width: 640px) {
  .search-ov { padding-top: 4rem; }
  .search-box { padding: 0 var(--sp-5); }
  .search-in { gap: var(--sp-2); }
  .search-in input { font-size: var(--fs-18); }
  .search-hint { font-size: 11px; letter-spacing: 0.04em; }
}

/* --- 首页「六类权重」内层栅格（实测：360px 下压成 28px 单字竖排）--- */
.w-grid > div { grid-column: span 4; }
@media (max-width: 1024px) { .w-grid > div { grid-column: span 6; } }
@media (max-width: 640px) { .w-grid > div { grid-column: span 12; } }

/* ==========================================================================
   前台智能表单（B 任务）
   --------------------------------------------------------------------------
   与中台那套 .ad-form 分开写：前台是素纸白底、宋体为主，
   中台是深底、信息密度优先。两套视觉不同，共用一套样式反而两头别扭。
   这里只加智能表单真正需要的东西。
   ========================================================================== */

/* ---- 字段提示：识别结果的落点 ---- */
.fld-tip {
  display: block;
  margin-top: var(--sp-2);
  font-size: 0.78rem;
  line-height: 1.6;
  letter-spacing: 0.01em;
  color: var(--xj-ink-70);
}
.fld-tip[hidden] { display: none; }
.fld-tip.is-ok { color: var(--xj-ok); }
.fld-tip.is-err { color: var(--xj-vermilion, #A8392E); }
.fld.is-bad input,
.fld.is-bad select,
.fld.is-bad textarea {
  border-bottom-color: var(--xj-vermilion, #A8392E) !important;
}

/* ---- 归人编号展示 ---- */
.xj-ujid-box {
  margin-top: var(--sp-6);
  padding: var(--sp-5) var(--sp-5);
  border: 1px solid var(--xj-ink-16);
  border-left: 3px solid var(--xj-vermilion, #A8392E);
  background: rgba(247, 244, 236, 0.7);
}
.xj-ujid-l {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  color: var(--xj-ink-70);
}
.xj-ujid-v {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-latin, "Cormorant Garamond", serif);
  font-size: clamp(1.5rem, 4vw, 2rem);
  letter-spacing: 0.1em;
  color: var(--xj-ink, #2B2A26);
  word-break: break-all;
}
.xj-ujid-s {
  margin: 0 0 var(--sp-4);
  font-size: 0.78rem;
  line-height: 1.7;
  color: var(--xj-ink-70);
}

/* ---- 表单级提示条（成功/失败） ---- */
.xj-form-msg {
  margin-top: var(--sp-4);
  padding: 0.75rem var(--sp-4);
  font-size: 0.85rem;
  line-height: 1.7;
  /* 原来写的是 var(--xj-ink-38, #A9A499)：
     --xj-ink-38 是 rgba(43,42,38,0.38) 的淡墨，而 #A9A499 是不透明的浅灰，
     两者色相和明度都不同。一旦令牌缺失（这正是 #21 任务踩过的静默失效），
     边框会从一根几乎看不见的淡线突然变成明显的实线。
     令牌要么存在，要么明着坏——不要留一个"看起来能用"的假兜底。 */
  border-left: 3px solid var(--xj-ink-38);
  background: var(--xj-ink-04);
}
.xj-form-msg.is-ok {
  border-left-color: var(--xj-ok);
  background: var(--xj-ok-wash);
}
.xj-form-msg.is-err {
  border-left-color: var(--xj-vermilion, #A8392E);
  background: rgba(168, 57, 46, 0.06);
}
.xj-form-msg[hidden] { display: none; }

/* ---- 粘贴识别成功的轻微提示（不打断输入） ---- */
@keyframes xjTipIn {
  from { opacity: 0; transform: translateY(-3px); }
  to { opacity: 1; transform: none; }
}
.fld-tip.is-ok { animation: xjTipIn 0.22s ease-out; }

/* ==========================================================================
   模块开关的前端表现（C 任务）
   --------------------------------------------------------------------------
   两件事在这里定型：
     · 未开放模块的提示页 —— 它要看起来像"我们收起来了"，
       不能像"出错了"。404 的语气和"暂时收回"的语气是两种东西。
     · 页脚的模块条 —— 访客少了入口时，有个地方能看到现在开着什么。
   ========================================================================== */

/* ---- 未开放模块提示 ---- */
[data-mod-closed] { position: relative; }
.mod-closed {
  /* 占满一屏但不强行 100vh —— 手机上 100vh 会把地址栏算进去，
     页面会多出一截空白。用 min-height 加一点余量即可。 */
  min-height: 58vh;
  display: flex;
  align-items: center;
  padding: var(--sp-24) 0;
}
.mod-closed-in { max-width: var(--maxw-reading); }
.mod-closed .eyebrow {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-hei);
  font-size: var(--fs-12);
  letter-spacing: 0.18em;
  color: var(--xj-vermilion);
}
.mod-closed-h {
  margin: 0 0 var(--sp-5);
  font-family: var(--font-song);
  font-size: var(--fs-display);
  font-weight: 400;
  line-height: var(--lh-title);
  letter-spacing: 0.01em;
}
.mod-closed-p {
  margin: 0 0 var(--sp-10);
  font-size: var(--fs-lede);
  line-height: var(--lh-loose);
  color: var(--xj-ink-70);
  /* 中文长句不用 max-width 卡，靠父容器的 reading 宽度即可 */
}
.mod-closed-links {
  padding-top: var(--sp-6);
  border-top: var(--hair);
  margin-bottom: var(--sp-8);
}
.mod-closed-links .tiny { margin: 0 0 var(--sp-3); }
.mod-closed-links a { margin: 0 var(--sp-2) var(--sp-2) 0; }
.mod-closed-act { display: flex; gap: var(--sp-3); flex-wrap: wrap; }

/* ---- 页脚模块条 ---- */
.foot-mods {
  margin-top: var(--sp-6);
  padding-top: var(--sp-4);
  border-top: var(--hair);
}
.foot-mods-t {
  margin: 0 0 var(--sp-2);
  font-family: var(--font-hei);
  font-size: var(--fs-11);
  letter-spacing: 0.16em;
  color: var(--xj-ink-70);
}
.foot-mods-l { margin: 0; line-height: 1.9; }
.foot-mods-l a {
  font-family: var(--font-hei);
  font-size: var(--fs-12);
  color: var(--xj-ink-70);
  margin-right: var(--sp-3);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color var(--dur-1) var(--ease),
              border-color var(--dur-1) var(--ease);
}
.foot-mods-l a:hover,
.foot-mods-l a:focus-visible {
  color: var(--xj-vermilion);
  border-bottom-color: var(--xj-vermilion);
}

/* ---- 文字型工具按钮（顶栏）：AI 之外的模块入口 ---- */
.icon-btn-txt {
  width: auto;
  min-width: 44px;            /* 触控热区不小于 44（视觉可以窄，热区不行） */
  padding: 0 var(--sp-2);
  font-family: var(--font-hei);
  font-size: var(--fs-12);
  letter-spacing: 0.06em;
  white-space: nowrap;
}

/* ==========================================================================
   触控目标保底（包容性）
   --------------------------------------------------------------------------
   标准是两档，别混：
     WCAG 2.2 SC 2.5.8 (AA)  24×24 CSS px   —— 合规底线，低于它就是点不准
     Apple HIG / WCAG AAA    44×44 CSS px   —— 推荐值
   水平导航这类"密集但不常点"的地方做到 24 即可；
   独立控件（发送、关闭、开关）应当做到 44。
   视觉尺寸和热区尺寸是两件事：视觉可以做小，热区不能。
   ========================================================================== */

/* 节气条的次要链接：原来只有 21px 高，手指很难点中。
   两个字的短链接（"时令""场景"）原来只有 22px 宽，同样低于 24 底线。
   这里宽度和高度都补到触控底线 —— 视觉上带一点内边距也不难看，
   比"看着紧凑但点不中"要好。 */
.jieqi-links a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  min-width: var(--tap-min);
  padding: 0 var(--sp-2);
}

/* AI 对话：发送键原来没有尺寸，图标塌成 12×2 —— 等于点不到。
   图标按钮必须显式给尺寸，不能让 SVG 自己撑。 */
.chat-input button {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-min);
  height: var(--tap-min);
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--xj-vermilion);
  cursor: pointer;
  border-radius: var(--r-sm);
  transition: background var(--dur-1) var(--ease);
}
.chat-input button:hover,
.chat-input button:focus-visible {
  background: var(--xj-vermilion-wash);
  outline: none;
}
.chat-input button svg { width: 20px; height: 20px; }
.chat-input { padding-right: var(--sp-3); }   /* 给 44 的按钮留位置 */

/* 对话关闭键：32×22 → 至少 44×44 */
.chat-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-min);
  height: var(--tap-min);
  margin: calc(-1 * var(--sp-2)) calc(-1 * var(--sp-2)) 0 0;
  border: 0;
  background: transparent;
  color: var(--xj-ink-52);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  border-radius: var(--r-sm);
}
.chat-close:hover,
.chat-close:focus-visible {
  color: var(--xj-vermilion);
  background: var(--xj-ink-04);
  outline: none;
}
.chat-head .ai-tag { margin-left: auto; }

/* 对话底部说明原来 10px，低于刻度下限。中文 10px 已经读不动了。 */
.chat-note { font-size: var(--fs-11); line-height: 1.7; }

/* ---- 归人编号卡（会员页） ----
   刻意做得素：它不是一张"会员卡"，是一张告知卡——
   告诉用户这台设备记着什么、这东西凭什么可信、怎么清掉。
   给它加阴影和渐变会让人误以为它是某种凭证。 */
.xj-id-card {
  margin-top: var(--sp-6);
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--xj-ink-16);
  border-left: 3px solid var(--xj-vermilion);
  background: var(--xj-paper-raise);
  max-width: 30rem;
}
.xj-id-card[hidden] { display: none; }
.xj-id-l { font-size: var(--fs-12); color: var(--xj-ink-70); letter-spacing: .04em; }
.xj-id-v {
  font-family: var(--font-latin);
  font-size: var(--fs-31);
  line-height: var(--lh-tight);
  letter-spacing: .04em;
  margin: var(--sp-1) 0 var(--sp-2);
  font-variant-numeric: tabular-nums;
}
.xj-id-s { font-size: var(--fs-12); line-height: var(--lh-body); color: var(--xj-ink-70); margin-bottom: var(--sp-3); }
.xj-id-s b { font-weight: 500; color: var(--xj-ink); }

/* ==========================================================================
   每月一礼（订阅卡与礼盒）
   --------------------------------------------------------------------------
   刻意做成"合约"的样子，不像"促销"。
   理由：这四条线是周期性履约方案，用户要判断的是
   "每月要花多少、什么时候开始、赠什么"——这些是条款，不是诱惑。
   所以：价格最大最醒目，赠品次之，不做倒计时、不做"仅限今日"。
   ========================================================================== */
.plan-line { padding: var(--sp-hero) 0 var(--sp-8); }
.plan-line + .plan-line { border-top: 1px solid var(--xj-ink-08); }

.plan-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  margin-top: var(--sp-8);
  border: 1px solid var(--xj-ink-16);
  background: var(--xj-paper-raise);
}
.plan {
  padding: var(--sp-5) var(--sp-4);
  border-left: 1px solid var(--xj-ink-16);
}
.plan:first-child { border-left: 0; }
.plan-hd {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-2);
}
.plan-name { font-size: var(--fs-16); font-weight: 500; }
.plan-cyc {
  font-size: var(--fs-12); color: var(--xj-ink-70);
  font-variant-numeric: tabular-nums;
}
/* 价格是这一页的主角。字号取 --fs-31：够大，但不超过全站 h1 的量级，
   免得四个线的价格互相打架、没有主次。 */
.plan-price {
  font-family: var(--font-latin);
  font-size: var(--fs-39);
  line-height: 1.1;
  letter-spacing: .01em;
  margin: var(--sp-3) 0 var(--sp-2);
  font-variant-numeric: tabular-nums;
}
.plan-price small { font-size: var(--fs-16); margin-right: 2px; color: var(--xj-ink-70); }
.plan-spec { font-size: var(--fs-13); line-height: var(--lh-snug); color: var(--xj-ink-70); }
.plan-gift {
  font-size: var(--fs-12); line-height: var(--lh-snug);
  color: var(--xj-ink-70); margin-top: var(--sp-2);
  padding-top: var(--sp-2);
  border-top: 1px dashed var(--xj-ink-16);
}

.line-seal {
  aspect-ratio: 1; max-width: 168px; margin-left: auto;
  display: grid; place-items: center;
  border: 1px solid var(--xj-ink-16);
  font-family: var(--font-song);
  font-size: var(--fs-61);
  line-height: 1;
  color: var(--xj-ink-08);
  background: var(--xj-paper-raise);
}

.redeem-list { display: grid; gap: 0; border-top: 1px solid var(--xj-ink-16); }
.redeem-item {
  display: grid; grid-template-columns: 7rem 1fr; gap: var(--sp-4);
  align-items: baseline;
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--xj-ink-16);
}
.redeem-l { font-size: var(--fs-18); }
.redeem-d { font-size: var(--fs-14); color: var(--xj-ink-70); }

.xie-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-4); }
.xie-card {
  padding: var(--sp-5);
  border: 1px solid var(--xj-ink-16);
  background: var(--xj-paper-raise);
  /* 蟹季是秋天，用暖墨做左侧标记，跟时令呼应 */
  border-left: 3px solid var(--xj-vermilion);
}
.xie-hd { display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap; }
.xie-name { font-size: var(--fs-18); font-weight: 500; }
.xie-tier {
  font-size: var(--fs-12); color: var(--xj-paper-raise);
  background: var(--xj-vermilion);
  padding: 1px var(--sp-2);
}
.xie-spec {
  font-family: var(--font-latin);
  font-size: var(--fs-25);
  margin: var(--sp-3) 0 var(--sp-1);
  font-variant-numeric: tabular-nums;
}
.xie-ratio { font-size: var(--fs-13); color: var(--xj-ink-70); }
.xie-gift { font-size: var(--fs-13); color: var(--xj-ink-70); margin-top: var(--sp-1); }
.xie-foot {
  font-size: var(--fs-12); color: var(--xj-ink-70);
  margin-top: var(--sp-3); padding-top: var(--sp-2);
  border-top: 1px dashed var(--xj-ink-16);
}

@media (max-width: 1024px) {
  .plan-grid { grid-template-columns: repeat(2, 1fr); }
  .plan:nth-child(odd) { border-left: 0; }
  .plan:nth-child(n+3) { border-top: 1px solid var(--xj-ink-16); }
  .xie-grid { grid-template-columns: 1fr; }
  .line-seal { margin: var(--sp-6) 0 0; }
}
@media (max-width: 640px) {
  .plan-grid { grid-template-columns: 1fr; }
  .plan { border-left: 0; border-top: 1px solid var(--xj-ink-16); }
  .plan:first-child { border-top: 0; }
  .redeem-item { grid-template-columns: 1fr; gap: var(--sp-1); }
}

/* ---- 场景页的两轴并置 ----
   时令（纵向）与五食辰（横向）是同一件事的两个方向。
   做成两张对开的卡，而不是并排两段文字——
   它们的关系是"同一问题的两个坐标轴"，视觉上就该像坐标轴那样对等。 */
.axis-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  margin-top: var(--sp-6);
  border: 1px solid var(--xj-ink-16);
  max-width: 40rem;
}
.axis {
  padding: var(--sp-4) var(--sp-5);
  border-left: 1px solid var(--xj-ink-16);
  display: block;
  transition: background var(--dur-1) ease;
}
.axis:first-child { border-left: 0; }
.axis:hover { background: var(--xj-paper-raise); }
.axis-k {
  display: block;
  font-size: var(--fs-12);
  color: var(--xj-ink-70);
  letter-spacing: .06em;
}
.axis-v {
  display: block;
  font-size: var(--fs-25);
  line-height: var(--lh-title);
  margin: var(--sp-1) 0 var(--sp-2);
}
.axis-n { display: block; font-size: var(--fs-13); color: var(--xj-ink-70); }
@media (max-width: 640px) {
  .axis-row { grid-template-columns: 1fr; }
  .axis { border-left: 0; border-top: 1px solid var(--xj-ink-16); }
  .axis:first-child { border-top: 0; }
}

/* ---- 定价未定的礼卡位 ----
   跟"模块关闭"那种"暂时没有开放"要长得不一样：
   关闭是拿掉了（在页脚说明），这里是还在、只是价格没定。
   所以用虚线框而不是实线，实线会让人以为是可买的。 */
.plan.is-pending {
  grid-column: 1 / -1;
  border: 1px dashed var(--xj-ink-16);
  border-left: 3px dashed var(--xj-ink-38);
  background: transparent;
}
.plan-pending {
  font-size: var(--fs-18);
  color: var(--xj-ink-70);
  margin: var(--sp-2) 0 var(--sp-3);
}

/* ==========================================================================
   刚须胡须鸡 · 日龄轴与准入标准
   --------------------------------------------------------------------------
   日龄轴刻意做成一条横向刻度带，像一把尺：
   这条轴是**可检测、可标价**的，用图表的形式表达比用列表更准——
   列表读出来是"有五个档"，尺读出来是"从 130 到 300 天，一步步抬上来"。
   ========================================================================== */
.age-axis {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  border-top: 1px solid var(--xj-ink-16);
}
.age-row {
  padding: var(--sp-4) var(--sp-3) var(--sp-3) 0;
  border-left: 1px solid var(--xj-ink-16);
  position: relative;
}
.age-row:first-child { border-left: 0; padding-left: 0; }
.age-row::before {
  /* 刻度点：越往后越高，视觉上直接读出"日龄在涨" */
  content: "";
  position: absolute;
  top: calc(var(--sp-2) * -1);
  left: 0;
  width: 5px; height: 5px;
  background: var(--xj-vermilion);
}
.age-row:first-child::before { left: 0; }
.age-d {
  display: block;
  font-family: var(--font-latin);
  font-size: var(--fs-31);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.age-d small { font-size: var(--fs-13); color: var(--xj-ink-70); margin-left: 3px; }
.age-n { display: block; font-size: var(--fs-16); margin-top: var(--sp-1); }
.age-c { display: block; font-size: var(--fs-12); color: var(--xj-ink-70); margin-top: var(--sp-1); }

.rules {
  margin: 0; padding: 0 0 0 var(--sp-6);
  display: grid; gap: var(--sp-3);
}
.rules li { font-size: var(--fs-14); line-height: var(--lh-body); color: var(--xj-ink-70); }
.rules li::marker { color: var(--xj-vermilion); font-variant-numeric: tabular-nums; }

.std-wrap { overflow-x: auto; }
.std { width: 100%; border-collapse: collapse; min-width: 40rem; }
.std th, .std td {
  text-align: left;
  padding: var(--sp-3) var(--sp-3);
  border-bottom: 1px solid var(--xj-ink-08);
  font-size: var(--fs-13);
  vertical-align: top;
}
.std th {
  font-weight: 500;
  color: var(--xj-ink-70);
  border-bottom-color: var(--xj-ink-16);
  white-space: nowrap;
}
.std td { color: var(--xj-ink-70); line-height: var(--lh-snug); }
.std td b { color: var(--xj-ink); font-weight: 500; }
/* 拒收红线单独着色：这列是"我们不收什么"，
   整页最容易记住的就是它，不该和别的列长得一样。 */
.std .std-no { color: var(--xj-vermilion); }

@media (max-width: 640px) {
  .age-axis { grid-template-columns: repeat(2, 1fr); row-gap: var(--sp-4); }
  .age-row:nth-child(odd) { border-left: 0; padding-left: 0; }
  .age-row:nth-child(even) { padding-left: var(--sp-3); }
}

/* ==========================================================================
   繁离 · 品牌宪章
   --------------------------------------------------------------------------
   宪章刻意用「短句 + 大留白」，不做成条款列表。
   理由：条款是给执行看的，宪章是给人记住的——
   「离不是离别，是附丽」这种句子，挤在密集条款里就没人记得了。
   ========================================================================== */
.charter {
  margin: 0; padding: 0; list-style: none;
  display: grid; grid-template-columns: repeat(2, 1fr);
  column-gap: var(--sp-8);
  counter-reset: ch;
}
.charter li {
  counter-increment: ch;
  display: grid;
  grid-template-columns: 2.4rem 1fr;   /* 序号栏 */
  align-items: baseline;
  gap: var(--sp-2);
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--xj-ink-08);
}
.charter li:nth-last-child(-n+2) { border-bottom: 0; }
.ch-n {
  font-family: var(--font-song);
  font-size: var(--fs-18);
  color: var(--xj-vermilion);
  line-height: 1;
}
.ch-t { font-size: var(--fs-16); line-height: var(--lh-body); }

.box-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  margin-top: var(--sp-8);
  border: 1px solid var(--xj-ink-16);
  background: var(--xj-paper-raise);
}
.box {
  padding: var(--sp-4);
  border-left: 1px solid var(--xj-ink-16);
  border-top: 1px solid var(--xj-ink-16);
  display: grid; gap: var(--sp-1);
}
.box:nth-child(3n+1) { border-left: 0; }
.box:nth-child(-n+3) { border-top: 0; }
.box-n { font-size: var(--fs-16); font-weight: 500; }
.box-p {
  font-family: var(--font-latin);
  font-size: var(--fs-25);
  font-variant-numeric: tabular-nums;
  color: var(--xj-vermilion);
}
.box-c { font-size: var(--fs-13); color: var(--xj-ink-70); }
.box-t { font-size: var(--fs-12); color: var(--xj-ink-70); }

.ch-quota { color: var(--xj-ink-70); font-variant-numeric: tabular-nums; white-space: nowrap; }

@media (max-width: 1024px) {
  .charter { grid-template-columns: 1fr; }
  .charter li { border-bottom: 1px solid var(--xj-ink-08) !important; }
  .charter li:last-child { border-bottom: 0 !important; }
  .box-grid { grid-template-columns: repeat(2, 1fr); }
  .box:nth-child(3n+1) { border-left: 1px solid var(--xj-ink-16); }
  .box:nth-child(odd) { border-left: 0; }
  .box:nth-child(-n+2) { border-top: 0; }
}
@media (max-width: 640px) {
  .box-grid { grid-template-columns: 1fr; }
  .box { border-left: 0 !important; }
  .box:first-child { border-top: 0; }
}

/* --------------------------------------------------------------------------
   在售状态：运行期收可见性
   --------------------------------------------------------------------------
   商品卡是静态生成的（首屏与 SEO），上下架是运行期的运营动作。
   两者对撞时，规则是：**内容留着，入口收掉**。
   理由是商品详情页有外部深链（微信、搜索、社媒），
   直接 404 等于把已经发出去的链接作废；
   而把卡片收起并标明状态，是电商的常规做法，也更诚实——
   用户还能知道"这个东西存在，只是现在不卖"。

   拿不到在售清单时按"全部在售"处理：少收一件货比整页空掉安全。 */
.sku { position: relative; }
.sku.is-offshelf { opacity: .45; }
.sku.is-offshelf .sku-visual { filter: grayscale(1); }
.sku-offnote {
  position: absolute; top: var(--sp-3); left: var(--sp-3);
  padding: 0.15em 0.5em; font-family: var(--font-hei); font-size: var(--fs-11);
  letter-spacing: 0.1em; color: var(--xj-ink-70);
  background: var(--xj-paper); border: 1px solid var(--xj-ink-16);
}

/* ==========================================================================
   商品卡：状态与去向（2026-10-05 内测加）
   ==========================================================================
   价格撤掉之后，卡片底部要回答两个问题：
     这东西现在能不能买？   → 在售 / 即将上架
     要买去哪？             → 鸡站·小灶在售 / 在小程序下单

   「即将上架」用虚线不用实心：实心=能买（那套 .flag 的既有约定），
   虚线=还没定。混用会让人以为虚线的那批也能下单。 */
.sku-where {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--fs-11);
  letter-spacing: .04em;
  color: var(--xj-ink-70);
  padding: .1rem .45rem;
  border: 1px solid var(--xj-line);
  border-radius: 1px;
}
.flag.is-soon {
  color: var(--xj-ink-70);
  background: transparent;
  border: 1px dashed currentColor;
  border-radius: 1px;
  padding: .1rem .45rem;
  font-size: var(--fs-11);
  white-space: nowrap;
}
/* 即将上架的卡片整体压低一档：不用降低透明度——
   透明度会让文字在浅底上读不清，而这一页的价值就是让人读得清。 */
.sku:has(.flag.is-soon) .sku-visual { filter: saturate(.55); }
.sku:has(.flag.is-soon) { background: var(--xj-paper-sink); }
/* :has() 不支持时的退路：加一个 is-soon 类也行，
   但页面上没有这个类，所以降级只是"视觉权重不够"，不影响可读性。 */

/* 候补卡：与「即将上架」同一套虚线语言。
 * 不用降低透明度——这一页的价值就是让人读清"在做什么"，
 * 读不清就等于没写。 */
.card.is-soon {
  background: var(--xj-paper-sink);
  border-style: dashed;
  border-color: var(--xj-line);
}
.card.is-soon .eyebrow { color: var(--xj-ink-70); }

/* ==========================================================================
   可读性兜底（2026-10-05 内测加）
   ==========================================================================
   为什么要有这一层：--xj-ink-38 是 2.1:1，xj.css 自己写着
   「仅装饰性线条与禁用态」。但实测有 8 类**真文字**在用它——
   时段、规格、注释、站名副标、chip、印章，还有**没有类名的裸 p**。

   按类名一个一个改会漏掉裸元素，所以兜底放在**元素类型**上：
   正文类元素一律不低于 62% 墨色（约 4.6:1，AA 达标）。
   装饰性元素（线条、边框、禁用态）不走这些标签，不受影响。

   这不是"加一层补丁"，是**把规矩落到选择器上**——
   跟权限矩阵那 30 个点位一个道理：写在文档里的规矩没人守，
   写进样式表的才守得住。
   ========================================================================== */
p, li, dd, dt, figcaption { color: var(--xj-ink-70); }
.tiny, .muted, .small { color: var(--xj-ink-70); }
.chip, .cell-time, .sku-spec, .sku-note, .logo-txt span {
  color: var(--xj-ink-70);
}

/* 兜底补第二层：span / b / i / a 这些行内元素。
 * 上一版只兜了 p/li/dd/dt，实测 .brand-group-head span 漏了（12px + 38%）。
 * 教训：**兜底层要按"所有会显示文字的元素"列，不按"正文元素"列**——
 * 上一版把"标签"当成了不该管的东西，结果标签也是字。 */
.brand-group-head span, .brand-group-head b { color: var(--xj-ink-70); }
span, b, i, em, strong { color: inherit; }
.hero-seal[style] { color: var(--xj-ink-70) !important; }

/* ==========================================================================
   B 侧实测清单 · 可读性兜底（2026-10-05）
   ==========================================================================
   这一段是**量出来的，不是推断出来的**。

   做法：起真服务 → 真实浏览器渲染 → 遍历所有叶子元素 →
        凡是「字号 ≤12.5px 且 前景色不透明度 < 0.55」的一律报出来 →
        按类名聚合。结果是 21 个类、约 500 处。

   为什么之前按类名一个一个改不完：
   · 改了 .cell-time 才发现 .sku-spec
   · 加了 p/li/dd 兜底才发现裸 <p>
   · 加了 span 兜底又冒出 317 处无类的 <b>
   每一轮都以为改完了，每一轮都还有下一批——
   因为"哪些元素用低透明度"这件事**没有清单，只有事实**。

   所以这一段是清单，不是补丁。
   规矩（对照 xj.css 第 208 行「--xj-ink-38 仅装饰性线条与禁用态」）：
     · **文字**（含 10–12px 的标签与注解）→ 墨色不低于 62%
     · **装饰**（线条、边框、禁用态、分隔块）→ 保持 38% 不动
   这条分界必须守住：全站调深会让层级塌掉，
   只调真文字才会让读得清。

   下面是实测出来的 21 个类，直接覆盖，不再逐个试。
   ========================================================================== */

/* —— 实测清单（类名来自 scan-tiny.py 的输出）—— */
.plan-cyc, .plan-gift, .xie-foot, .ing-desc, .box-t, .hou-desc,
.flag.is-soon, .sku-where, .sku-offnote, .tl-season-tag, .tl-date,
.ing-from, .lang, .foot-mods-t, .search-hint, .brand-group-note,
.trad-note, .flag.flag-soon, .tl-term, .tl-meta, .foot-h,
.foot-brand p, .site-foot p, .foot-ll p {
  color: var(--xj-ink-70);
}
/* 317 处无类 <b>：家族图谱与节气轴上的小标签。
   它们是"标签"但仍然是字——上一版把标签当成了不该管的东西，
   结果标签就是最读不清的那批。 */
b, strong, em { color: var(--xj-ink-70); }
.foot-h { color: var(--xj-ink-70); }

/* 但**装饰性**的仍然保持 38%：分隔线、边框、禁用态、装饰块。
   全站调深会让层级塌掉——那比读不清更糟，因为它把设计做平了。 */
.hair, .rule, [disabled], .ad-btn:disabled, .ico-dash, .sep {
  /* 保持原样，这里只是写明"这些不许跟着调深" */
  color: var(--xj-ink-38);
}

/* ==========================================================================
   可读性：纸色底上的文字（2026-10-05）
   ==========================================================================
   ⚠ 不要写成无差别的一刀切。
   上一版试过 `a, p, span { color: ink-70 }`，
   结果把深底反白字（AI 面板、hero 条）也改成墨色 —— 对比度 1.00:1，
   比改之前更糟。**没有区分底色的默认值不是默认值，是一刀切。**

   正确做法：只处理"底色是纸色"的那一类。
   深色区块数量很少、每次都会显式写出来，所以它们在下面单独声明。
   ========================================================================== */

/* 纸色底上的次要文字：从 2.1:1 提到 4.6:1（WCAG AA）。
   这些都是"文字"，不是线条也不是禁用态。 */
.jieqi-links a, .foot-brand p, .site-foot p, .foot-ll p, .foot-h,
.plan-cyc, .plan-gift, .xie-foot, .ing-desc, .ing-from, .box-t,
.hou-desc, .tl-season-tag, .tl-date, .tl-term, .tl-meta,
.lang, .foot-mods-t, .search-hint, .brand-group-note, .brand-group-head span,
.trad-note, .push-side, .ai-tag, .foot-bot, .flag-wip, .flag-soon,
.flag-tbd, .flag-chk, .trad-meta i, .sku-where, .sku-offnote,
.logo-txt span, .eyebrow, .cell-time, .sku-spec, .sku-note,
.hero-seal, .foot-c, .nav a, .crumbs a, .crumbs span {
  color: var(--xj-ink-70);
}

/* ==========================================================================
   「在线咨询」挂件（2026-10-05）
   ==========================================================================
   两种模式同一个位置：右下角。mode 没配时不渲染，所以这个类
   只在真接上的时候才出现在页面上。

   为什么不做成"一直显示、点了再说"：
   一个打不开的联系方式比没有更糟——访客会以为我们联系不上。 */
.xj-contact {
  position: fixed; right: 1.2rem; bottom: 1.2rem; z-index: 9000;
  display: flex; align-items: center; gap: .6rem;
  padding: .55rem .9rem .55rem .6rem;
  background: var(--xj-paper);
  border: 1px solid var(--xj-ink-16);
  border-radius: 2px;
  box-shadow: 0 2px 12px rgba(43, 42, 38, .10);
  text-decoration: none;
  transition: border-color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.xj-contact:hover { border-color: var(--xj-vermilion); transform: translateY(-1px); }
.xj-contact-ic {
  width: 26px; height: 26px; flex-shrink: 0;
  display: grid; place-items: center;
  font-size: 15px; line-height: 1;
  color: var(--xj-paper); background: var(--xj-vermilion);
  border-radius: 50%;
}
.xj-contact-tx { display: flex; flex-direction: column; line-height: 1.25; }
.xj-contact-tx b { font-size: var(--fs-14); font-weight: 400; color: var(--xj-ink); }
.xj-contact-tx i {
  font-style: normal; font-size: 10px; letter-spacing: .08em;
  color: var(--xj-ink-70);     /* 62%：10px 的字至少要 4.5:1 */
}
@media (max-width: 640px) {
  /* 手机上不缩成图标——那会让人不知道是什么。
     宁可占一行，也要点得准。 */
  .xj-contact { right: .8rem; bottom: .8rem; padding: .6rem .8rem; }
  .xj-contact-tx i { display: none; }   /* 副标在窄屏省掉，主标留着 */
}
@media (prefers-reduced-motion: reduce) {
  .xj-contact { transition: none; }
  .xj-contact:hover { transform: none; }
}

/* ==========================================================================
   移动端点击区（B4-6 实测后加，2026-10-05）
   ==========================================================================
   实测 20/79 个可点元素在移动端不足 44px。两类：
     ① .logo         站名链接，34px —— 误点会跳首页
     ② .arrow-link  "礼盒专区 →""二十四节气全览 →" 这类下一步入口，28px

   做法：给这两类补 **padding + 负 margin**。
   为什么不用固定 height：那会把行内链接的行高撑坏，
   在正文段落里出现时会把整段拉开。
   负 margin 把占位还回去，所以视觉上没变，只有可点区域变大。

   不要无差别给所有 a 加点击区——段落里的链接需要正常的行高，
   全部加高会让文字行之间出现空隙，正文会散。
   ========================================================================== */
@media (max-width: 640px), (pointer: coarse) {
  a.logo, .site-head .logo { padding: .5rem 0; }
  .arrow-link { padding: .55rem 0; }
  .chat-close, .icon-btn { min-width: 44px; min-height: 44px; }
  /* 补点击区但把视觉占位还回去——视觉不变，只有手指好点 */
  .logo { margin: -.5rem 0; }
}

/* 补最后一类：AI 面板里的建议项（实测 29px）。
 * 它们是"点一下就能问"的快捷入口，在移动端是主要交互方式，
 * 29px 手指点不准——而点错一次就是一次无效提问。 */
@media (max-width: 640px), (pointer: coarse) {
  .chat-panel .chip, .chat-sug, .chat-panel button {
    padding: .5rem .7rem; min-height: 40px;
  }
}

/* B4-6 逐条定位后补最后两类：
 *   43px  a.arrow-link         "二十四节气全览 →""礼盒专区 →"
 *   40px  button < .chat-quick  "今天吃什么""给爸爸送礼"这些快捷问
 * 两类都只差几像素，但它们是移动端的主要入口——差几像素就是误点的差别。 */
@media (max-width: 640px), (pointer: coarse) {
  .arrow-link { padding: .75rem 0; margin: -.15rem 0; }
  .chat-quick button {
    padding: .65rem .8rem; min-height: 44px;
  }
}

/* ==========================================================================
   留资表单（2026-10-27）
   --------------------------------------------------------------------------
   这套样式服务三处：内容页结尾、商品详情、合作意向。
   为什么要单独一套而不是复用 .card：
     .card 是"陈列用"的卡（带索引号、悬停位移、等高网格）。
     留资卡是"办事用"的卡，它不该有悬停动画——卡片一动，正在输入的人会分心。
   ========================================================================== */

.lead-sec { background: var(--xj-paper-sink); }

.lead-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: 3rem;
  align-items: start;
  padding: clamp(1.6rem, 4vw, 2.6rem);
  /* 覆盖 .card 的悬停：办正事的卡不跟着鼠标晃 */
  transform: none !important;
}
.lead-card:hover { transform: none; }

.lead-hd h3 {
  font-size: clamp(1.35rem, 2.6vw, 1.75rem);
  margin: .5rem 0 .8rem;
  line-height: 1.4;
}
.lead-sub { max-width: 34ch; line-height: 1.8; margin: 0; }

/* 蜜罐：人看不见，机器人会填。
   用 position 移出视口而不是 display:none——
   有些脚本会跳过 display:none 的字段，却不跳过"看不见但在布局里"的字段。 */
.lead-trap {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

.lead-note.is-bad { color: var(--xj-vermilion); }

/* 提交成功后的回执 */
.lead-done {
  border: 1px solid var(--xj-ink-08);
  background: var(--xj-paper);
  padding: clamp(1.4rem, 3vw, 2rem);
}
.lead-done-t {
  font-family: var(--font-song);
  font-size: var(--fs-20);
  margin: 0 0 .6rem;
}
.lead-done-b { margin: 0 0 .8rem; line-height: 1.8; }
.lead-done-n {
  font-family: var(--font-hei);
  font-size: var(--fs-12);
  letter-spacing: .1em;
  color: var(--xj-ink-70);
  margin: 0 0 .6rem;
}
.lead-done-n b { color: var(--xj-ink); letter-spacing: .04em; }

@media (max-width: 1024px) {
  .lead-card { grid-template-columns: 1fr; gap: 1.6rem; }
}

/* 表单里勾选同意那一行的链接：正文色 + 下划线，
   不给朱红——朱红在这套版里是"主行动"，滥用会稀释按钮的分量。 */
.check a { color: var(--xj-ink); text-decoration: underline; text-underline-offset: 2px; }

/* ==========================================================================
   商品页实拍图（2026-10-27）
   --------------------------------------------------------------------------
   放在「产地与吃法」左栏标题下面。只做三件事：
     1. 不裁切（每张图的比例都不一样，统一裁会切掉主体）
     2. 高度自适应，宽度跟随栏宽（桌面约 300px，移动端满宽）
     3. 图注用小字，不抢标题
   ========================================================================== */

.fact-fig {
  margin: 1.6rem 0 0;
  border: var(--hair);
  background: var(--xj-paper-sink);
}
.fact-fig img {
  display: block;
  width: 100%;
  height: auto;          /* 不裁切：cover 会把竖图切掉上下，商品图不能切 */
}
.fact-fig figcaption {
  font-family: var(--font-hei);
  font-size: var(--fs-12);
  letter-spacing: .1em;
  color: var(--xj-ink-70);
  padding: .7rem .9rem;
  border-top: var(--hair);
  line-height: 1.6;
}

/* ==========================================================================
   商品卡的"去哪买"（2026-10-27）
   --------------------------------------------------------------------------
   结构变了，说一下为什么：
     原来整张卡是一个 <a>，"鸡站·小灶在售"是卡里的一行 <span>，
     长得像链接（带箭头）但点不动——那是假承诺。
     要放进真的按钮，就必须把卡拆成"链接区 + 按钮区"：
     <a> 里不能再套 <a>，也不能放 <button>（HTML 规范不允许交互元素嵌套）。

   现在：
     div.sku
       a.sku-link   ← 图 + 名称 + 规格，点这里进商详
       div.sku-foot ← 状态 + 按钮，点这里开面板
   ========================================================================== */

.sku-link {
  display: flex; flex-direction: column; flex: 1;
  text-decoration: none; color: inherit;
  /* 焦点环交给键盘用户：整块链接区可 Tab 到 */
  outline-offset: -2px;
}
/* body 的下内边距交给 foot，避免两层 padding 叠加把卡撑高 */
.sku-body { padding: var(--sp-6) var(--sp-6) 0; }
.sku-foot {
  margin-top: 0;
  padding: 1rem var(--sp-6) var(--sp-6);
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}

/* 真的按钮。看起来要像"能点的字"，但要有可点的边界与反馈。 */
.sku-mp {
  appearance: none; background: none; border: 0; padding: 0;
  font-family: var(--font-song); font-size: var(--fs-12);
  color: var(--xj-ink);
  border-bottom: 1px solid var(--xj-ink-38);
  cursor: pointer; white-space: nowrap;
  transition: color 160ms var(--ease), border-color 160ms var(--ease);
}
.sku-mp:hover { color: var(--xj-vermilion); border-bottom-color: var(--xj-vermilion); }
.sku-mp:active { transform: translateY(1px); }
.sku-mp:focus-visible { outline: 2px solid var(--xj-vermilion); outline-offset: 3px; }
/* 小箭头：表示"点开有东西"，不是"跳走" */
.sku-mp::after { content: " ↑"; font-size: 10px; letter-spacing: 0; }

/* --------------------------------------------------------------------------
   面板：这款在哪个小程序卖
   -------------------------------------------------------------------------- */
.mp-sheet {
  position: fixed; inset: 0; z-index: 120;
  background: rgba(43, 42, 38, .34);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  animation: mpIn 220ms var(--ease-out) both;
}
.mp-sheet[hidden] { display: none; }
@keyframes mpIn { from { opacity: 0 } to { opacity: 1 } }

.mp-card {
  position: relative;
  background: var(--xj-paper-raise); border: var(--hair);
  width: 420px; max-width: 100%;
  padding: 36px 36px 28px;
  box-shadow: 0 24px 64px rgba(43, 42, 38, .18);
  animation: mpCardIn 260ms var(--ease-out) both;
}
@keyframes mpCardIn {
  from { opacity: 0; transform: translateY(10px) scale(.985) }
  to { opacity: 1; transform: none }
}

.mp-x {
  position: absolute; top: 12px; right: 12px;
  width: 32px; height: 32px; border: 0; background: none;
  font-size: 18px; line-height: 1; color: var(--xj-ink-52);
  cursor: pointer;
}
.mp-x:hover { color: var(--xj-ink); }

.mp-app {
  font-family: var(--font-hei); font-size: var(--fs-12);
  letter-spacing: .16em; color: var(--xj-vermilion); margin: 0 0 10px;
}
.mp-name { font-size: var(--fs-20); margin: 0 0 6px; letter-spacing: .02em; }
.mp-sub { font-size: var(--fs-12); color: var(--xj-ink-70); margin: 0 0 20px; }

.mp-code { text-align: center; margin: 0 0 16px; }
.mp-code img {
  width: 180px; height: 180px; display: block; margin: 0 auto;
  border: 1px solid var(--xj-ink-08); background: #fff;
}
.mp-hint {
  font-size: var(--fs-12); color: var(--xj-ink-70);
  line-height: 1.9; text-align: center; margin: 0 0 20px;
}

/* 没码时的降级：不留空框，直接把"怎么办"说清 */
.mp-fallback {
  border: 1px solid var(--xj-ink-08); background: var(--xj-paper);
  padding: 18px 18px 16px; margin: 0 0 20px;
}
.mp-fallback p { font-size: var(--fs-12); color: var(--xj-ink-70); line-height: 1.9; margin: 0; }
.mp-fallback b { color: var(--xj-ink); font-weight: 400; }

.mp-acts { display: flex; gap: 12px; align-items: center; }
.mp-acts .btn { flex: 1; justify-content: center; }

/* ==========================================================================
   V2 P3 · 首屏判定（2026-10-28）
   --------------------------------------------------------------------------
   h1 说的是"我们是谁"，这一行说的是"今天吃什么"。
   两件都得说，但顺序应该是先答案、后故事——所以它在 h1 上面。
   小字、朱点、单行，不抢 h1 的戏。
   ========================================================================== */
.hero-verdict {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  font-family: var(--font-hei); font-size: var(--fs-12);
  letter-spacing: .12em; color: var(--xj-vermilion);
  margin: 0 0 1.6rem;
}
.hero-verdict i {
  width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; flex: none;
}
.hero-verdict b { font-weight: 400; color: var(--xj-ink) }
.hero-verdict span { color: var(--xj-ink-52); letter-spacing: .04em }

/* ==========================================================================
   V2 P3 · 商品页证据链编号（2026-10-28）
   --------------------------------------------------------------------------
   产地、保存、吃法本来就是一条线：从哪来 → 怎么留 → 怎么吃。
   不编号时它们是三个并列的格子，读者要自己排顺序；
   编了号，眼睛会自动按 01→02→03 读下去。
   **证据的价值，一半取决于它是不是按顺序摆的。**
   ========================================================================== */
.cell-name i {
  font-style: normal;
  font-family: var(--font-latin);
  font-size: var(--fs-12);
  letter-spacing: .1em;
  color: var(--xj-ink-38);
  margin-right: .6em;
}
.eyebrow i.ev-no {
  font-style: normal;
  font-family: var(--font-latin);
  letter-spacing: .1em;
  color: var(--xj-ink-38);
  margin-right: .8em;
}

/* V2 P4 · 标题层级修正（2026-10-28）
   品牌分组的标题原来是 h4，而它上面是 h2——跳了一级。
   跳级对读屏软件意味着"这一段突然深了两层"，对 SEO 是结构信号混乱。
   改成语义正确的 h3，再用类名把字号压回原来的 16px：
   **语义和视觉分开，不要让字号绑架标签。** */
.brand-item h3.brand-item-h {
  font-size: var(--fs-16);
  letter-spacing: 0.06em;
  font-weight: 400;
  line-height: var(--lh-title, 1.5);
  margin: 0;
}

/* 同上：gl-block 的标题也跳级（h2 之后直接 h4），改 h3 并用类名保住字号 */
.gl-block h3.gl-block-h {
  font-size: var(--fs-16);
  font-weight: 400;
  line-height: var(--lh-title, 1.5);
  margin: 0 0 var(--sp-2);
  letter-spacing: 0.04em;
}

/* ==========================================================================
   V2 P5 · 提按要"变粗"（2026-10-28）
   --------------------------------------------------------------------------
   现在按下只有位移（translateY 1px）——像"贴纸滑了一下"。
   毛笔按下去，除了位置，**笔画是变粗的**，那是"力"。

   为什么用 inset box-shadow 而不是改 border-width：
     改 border 会撑开 1px，整排按钮跟着抖一下；
     inset 阴影只画在里面，不动布局。**手感要加，布局不能动。**
   ========================================================================== */
.btn:active,
.icon-btn:active,
.sku-mp:active {
  box-shadow: inset 0 0 0 1.5px rgba(43, 42, 38, .55);
}
.btn-solid:active,
.btn-seal:active {
  box-shadow: inset 0 0 0 1.5px rgba(0, 0, 0, .28);
}

/* ==========================================================================
   V2 P5 · 墨分五色（2026-10-28）
   --------------------------------------------------------------------------
   淡出不该用 opacity。墨加水，**色相不变、只是浓度变**；
   而 opacity 会把字混成灰白，看起来像"没加载完"。

   这里只替换"纸底上的次要文字"——因为实色只在固定底色上才成立。
   边框、遮罩、深底上的文字仍然用 alpha（它们混的底色不固定）。
   ========================================================================== */
:root {
  --xj-ink-70s: #686761;   /* 墨 70% 调纸 —— 次要正文 */
  --xj-ink-52s: #8D8B85;   /* 墨 52% —— 图注、辅助 */
  --xj-ink-38s: #A9A7A1;   /* 墨 38% —— 占位、编号 */
}
/* 只换 .muted：它是次要正文，一定落在纸底上。
   .tiny / .small 不换——它们也会出现在深底组件（气泡、主推带）里，
   换实色会变黑看不见。**能确定底色才换，不确定就留着 alpha。** */
.muted { color: var(--xj-ink-70s); }
.eyebrow i.ev-no, .cell-name i { color: var(--xj-ink-38s); }

/* ==========================================================================
   V2 P7 · 打印（2026-10-28）
   --------------------------------------------------------------------------
   这是个要印东西的行业：菜单、台牌、清单、报价单。
   而现在的页面打出来是"网页的截图"——底色费墨、导航还在、链接是蓝色。

   三条具体规矩：
     ① 去底色去阴影：一页 A4 省 30% 墨，而且黑字更清楚
     ② 链接后自动补 (URL)：纸上点不动，得把地址印出来
     ③ 不许把表格行/卡片从中间切断：断在半行上，读的人要拼
   ========================================================================== */
@media print {
  /* 交互件全部不印 */
  .site-head, .site-foot, .chat-fab, .chat-panel, nav.toc,
  .btn-row, .lead-card, .skip-link, .skel, .vi-paper::after { display: none !important; }

  html, body {
    background: #fff !important;
    color: #000 !important;
    font-size: 10.5pt;
  }
  /* 纸是白的，所有纸色底都换成白，省墨 */
  .card, .cell, .sku, section[style*="background"], .push-band {
    background: #fff !important;
    box-shadow: none !important;
    border-color: #999 !important;
  }
  .hero-art svg, .sku-visual svg { opacity: .8 }

  /* 链接补地址：只给正文里的外链补，导航与按钮已经隐藏了 */
  .prose a[href^="http"]::after,
  .foot-list a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 8pt;
    color: #666;
    word-break: break-all;
  }

  /* 不许从中间切断 */
  table, tr, .card, .cell, figure, .push-lead { break-inside: avoid; }
  h1, h2, h3 { break-after: avoid; }

  img { max-width: 100% !important; page-break-inside: avoid; }

  @page { margin: 16mm 14mm; }
}

/* ==========================================================================
   V2 P8 · 落款（2026-10-28）
   --------------------------------------------------------------------------
   印章是最后盖的。一开始就在那里的是"装饰"，读完了才落下来的是"落款"。
   只出现在有 .prose 的页面（文章、政策、长文），不铺全站。
   ========================================================================== */
.seal-sign {
  display: inline-flex; align-items: center; gap: .7rem;
  margin: 3.2rem 0 0;
  padding-top: 1.4rem;
  border-top: var(--hair);
  color: var(--xj-vermilion);
  opacity: 0;
  transform: scale(1.16) translateY(-4px);
  transition: opacity 420ms var(--ease-out), transform 520ms cubic-bezier(.2,.9,.3,1.2);
}
.seal-sign.is-set { opacity: 1; transform: scale(1) translateY(0) }
.seal-mark { width: 26px; height: 26px; display: block }
.seal-mark svg { width: 100%; height: 100%; display: block }
.seal-tx {
  font-family: var(--font-song);
  font-size: var(--fs-14);
  letter-spacing: .28em;
}
@media (prefers-reduced-motion: reduce) {
  .seal-sign { opacity: 1; transform: none; transition: none }
}

/* ==========================================================================
   V2 P8 · 实验四项的样式（2026-10-28）
   --------------------------------------------------------------------------
   全部挂在 .vi-exp 下：去掉这个类，四条一起关，不用改代码。
   为什么这么设计：这四条都能被感知，但也可能被当成 bug。
   给一个总开关，比"改错了一个个回滚"划算。
   ========================================================================== */

/* ⑪ 飞白：正文墨浓随滚动速度变（JS 写 --ink-density）
   用 color-mix 混墨而不是改 opacity——
   opacity 会让字发灰（那是"没加载完"的样子），
   而墨加水是**色相不变、浓度变**。 */
.vi-exp .prose p,
.vi-exp .prose li {
  color: color-mix(in srgb,
    var(--xj-ink) calc(var(--ink-density, 1) * 100%),
    var(--xj-paper));
  transition: color 180ms linear;
}

/* ⑫ 三远：三层微差
   山水画的散点透视——引文、正文、图注不在同一个"深度"上。
   注意只有 2–3px，不是视差（那要几十像素）。
   **察觉不到，但感觉有厚度。**
   滚动驱动，零 JS，不占主线程。 */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .vi-exp .prose > p {
      animation: yuan-near linear both;
      animation-timeline: view();
      animation-range: entry 14% cover 34%;
    }
    .vi-exp .prose > blockquote {
      animation: yuan-mid linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 28%;
    }
    .vi-exp .prose > figure {
      animation: yuan-far linear both;
      animation-timeline: view();
      animation-range: entry 6% cover 22%;
    }
    @keyframes yuan-near  { from { transform: translateY(2px) }  to { transform: none } }
    @keyframes yuan-mid   { from { transform: translateY(3.5px) } to { transform: none } }
    @keyframes yuan-far   { from { transform: translateY(5px) }  to { transform: none } }
  }
}

/* ⑬ 开片：读过的文章，标题左侧一道极淡的痕
   不是"已读"标记（那是功能），是视觉记忆。
   淡到 .42——扫过去只觉得"这行有点熟"，盯着看才发现有东西。 */
.vi-exp a.is-read .card-title::before,
.vi-exp a.is-read h2::before,
.vi-exp a.is-read h3::before {
  content: "";
  display: inline-block;
  width: 14px; height: 1px;
  margin-right: .6em;
  vertical-align: .35em;
  background: var(--xj-vermilion);
  opacity: .42;
}

/* ==========================================================================
   V2.1 #9 · 触屏 300ms 延迟（2026-10-28）
   --------------------------------------------------------------------------
   移动端浏览器为了判断"是点击还是双击缩放"，会在点击后等 300ms。
   这 300ms 是"手指按下去，界面没反应"的直接来源。
   touch-action: manipulation 告诉浏览器"这里不用等双击"，延迟归零。
   ========================================================================== */
a, button, [role="button"], input[type="submit"], .btn, .sku, .cell {
  touch-action: manipulation;
}

/* ==========================================================================
   V2.1 #5 · 图片渐进（2026-10-28）
   --------------------------------------------------------------------------
   弱网下图片是"白色方块"然后"啵"地出现，那一下很廉价。
   两个轻量做法合起来就够，不必上 base64 占位图（那会让 HTML 变大）：

     ① 纸色底：图片没到时那块是纸色，不是白块——**至少不像坏了**
     ② 淡入：到货后 320ms 淡进来，眼睛不会"被闪一下"

   为什么不做真正的 LQIP（内联 20px 模糊图）：
     全站 37 张图各带一段 base64，HTML 要多出几十 KB，
     而我们的首屏几乎没有照片（首页是线描）。
     为一个看不到首屏收益的东西付 HTML 体积，不划算。
   ========================================================================== */
img {
  background: var(--xj-paper-sink);
}
img[data-fade] {
  opacity: 0;
  transition: opacity 320ms var(--ease-out);
}
img[data-fade].is-loaded { opacity: 1 }

@media print {
  img[data-fade] { opacity: 1 !important }
}

/* ==========================================================================
   V2.1 #6 · 长文目录（2026-10-28）
   --------------------------------------------------------------------------
   挂在正文上方，两栏排版（宽屏）／单栏（窄屏）。
   不悬浮、不跟随——够用就好，不为"看起来专业"付布局风险。
   ========================================================================== */
.toc-inline {
  margin: 0 0 2.6rem;
  padding: 1.4rem 1.6rem;
  background: var(--xj-paper-raise);
  border-left: 2px solid var(--xj-vermilion);
}
.toc-inline-t {
  font-family: var(--font-hei); font-size: var(--fs-11);
  letter-spacing: .18em; color: var(--xj-vermilion);
  margin: 0 0 .9rem;
}
.toc-inline ol {
  margin: 0; padding: 0; list-style: none;
  columns: 2; column-gap: 2.4rem;
}
@media (max-width: 640px) { .toc-inline ol { columns: 1 } }
.toc-inline li { margin-bottom: .5rem; break-inside: avoid }
.toc-inline a {
  font-size: var(--fs-14); color: var(--xj-ink-70);
  text-decoration: none; border-bottom: 1px solid transparent;
  transition: color 160ms var(--ease), border-color 160ms var(--ease);
}
.toc-inline a:hover { color: var(--xj-vermilion); border-bottom-color: var(--xj-ink-16) }

/* 搜索结果键盘选中态（V2.1 #7） */
.search-res a.is-cur {
  background: var(--xj-vermilion-wash);
  outline: 1px solid rgba(168, 57, 46, .28);
  outline-offset: -1px;
}

/* 手机号实时校验（V2.1 #10）
   不占额外高度（absolute），否则输入框会被提示文字顶得跳一下。 */
.lead-phone-tip {
  display: block;
  position: absolute; right: 0; bottom: -1.5em;
  font-family: var(--font-hei); font-size: var(--fs-11);
  letter-spacing: .06em; color: var(--xj-ink-52);
  pointer-events: none;
}
.lead-phone-tip.is-ok { color: var(--xj-ok) }
.lead-phone-tip.is-bad { color: var(--xj-vermilion) }
/* 让提示有地方落 */
form[data-lead-form] .field { position: relative }

/* ==========================================================================
   V2.1 #11 · 首页的时间感（2026-10-28）
   --------------------------------------------------------------------------
   按一天里的时辰给首页叠一层极淡的色温——清晨偏青、正午无色、
   午后偏暖、傍晚偏赤、夜里偏墨。

   为什么用 multiply 而不是盖半透明色块：
     盖色块会把纸压灰（像蒙了层雾）；multiply 是"同一张纸，换了一种光"。
     这是印刷上的常识，屏幕上同样成立。

   为什么只给首页：
     内页要读字。任何叠色都会降低正文对比度，而在内页那是不可接受的代价。
   ========================================================================== */
body[data-home]::before {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 0;
  background: var(--day-tint, transparent);
  opacity: var(--day-alpha, 0);
  mix-blend-mode: multiply;
  transition: opacity 1.8s var(--ease-out);
}
/* 夜里那一档稍深一点，但仍极淡 */
html[data-day-hour="22"] body[data-home]::before,
html[data-day-hour="23"] body[data-home]::before { opacity: .04 }

@media (prefers-reduced-motion: reduce) {
  body[data-home]::before { transition: none }
}

/* ==========================================================================
   V2.1 #12 · 移动端自适应（2026-10-28）
   --------------------------------------------------------------------------
   实测出来的两个真问题（三个宽度 × 五个页面全扫）：
     · 横向溢出 0 处  → 基础响应式是好的，不用重做栅格
     · 触控目标偏小   → 导航与页脚的文字链接只有 21–28px 高，拇指点不准
     · 正文最小 11px  → 图注、脚注在手机上要眯眼

   两条修法都不是"放大"，是"扩热区"与"抬下限"：
     · 链接用 padding 把可点范围撑到 44px，字的字号和行距不变
     · 11px 抬到 12px（不是 14——那是另一套版式了）
   ========================================================================== */
@media (max-width: 640px) {
  /* 🔴 字号下限用"重定义令牌"来做，不逐个选择器改。
     11px 的字散在十几处（.tiny / .eyebrow / 编号 / 日期），
     逐个改一定漏；把令牌本身抬到 12px，谁用它谁就跟着抬。 */
  :root { --fs-11: 12px }

  /* 触控热区：只补"文字链接"这一类。
     卡片与图片本来就是大块，不需要补；补了反而会让它们互相压住。 */
  .jieqi-links a,
  .hero-verdict a,
  .nav a,
  .nav-extra-a,
  .foot-list a,
  .toc-inline a,
  .sku-mp,
  .head-login {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
  }
  .jieqi-links a { padding: 0 2px }

  /* 导航项：抽屉里本来就是整行，给足 44px */
  .nav > a,
  .nav-extra-a {
    display: flex; align-items: center;
    min-height: 44px;
    padding: 0 .2rem;
  }

  /* 页脚链接：一行一个，撑到 40px 够拇指点 */
  .foot-list a {
    display: flex; align-items: center;
    min-height: 40px;
  }
  .foot-list li { margin-bottom: 0 }

  /* 目录、正文里的行内链接：用 padding 扩热区，不撑开行距 */
  .toc-inline a {
    display: inline-flex; align-items: center;
    min-height: 40px;
  }

  /* 字号下限：11px 抬到 12px */
  .tiny, .sku-note, .foot-mods, .lead-phone-tip { font-size: 12px }
  .cell-brands .chip, .flag { font-size: 12px }

  /* 顶栏：给汉堡与搜索留足位置 */
  .icon-btn { min-width: 44px; min-height: 44px }
  .head-login { min-height: 44px; display: inline-flex; align-items: center }

  /* 正文行高略松一档，手机上更好读 */
  .prose p, .prose li { line-height: 1.85 }
}

/* 平板：比手机松一点，但不至于像桌面那么散 */
@media (min-width: 721px) and (max-width: 1024px) {
  /* 平板也是手指，只是屏幕宽些——热区按 36px 给，不是 28px */
  .foot-list a,
  .jieqi-links a,
  .hero-verdict a,
  .toc-inline a,
  .sku-mp,
  .nav > a {
    display: inline-flex; align-items: center;
    min-height: 36px;
  }
  .foot-list li { margin-bottom: 0 }
}

/* ==========================================================================
   V2.1 · CLS 修正：首屏 hero-meta 的"—"换行（2026-10-28）
   --------------------------------------------------------------------------
   实测：CLS 偶发 0.24，来源是首页 .hero-meta 的四个 dd。
   它们初值是"—"，JS 在节气与时辰算完后填成真实内容（"霜降第 6 天 · 距立冬 9 天"），
   在 390px 窄屏上撑成两行，把下面的 hero-art 和整个首屏推下去。

   **一次换行，整页跳一下。** 这比"慢 200ms"难受得多。

   修法：给这两个槽位预留一行的高度并禁止换行（超长省略）。
   宁可让"距立冬 9 天"被截成"距立冬 9…"，也不让整页抖。
   ========================================================================== */
.hero-meta dd {
  min-height: 1.7em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (max-width: 640px) {
  /* 手机上四栏并排本来就窄，改成两栏，每个字段有整行可用 */
  .hero-meta { display: grid; grid-template-columns: 1fr 1fr; gap: .9rem 1.2rem }
  .hero-meta dd { min-height: 1.6em }
}

/* 搜索的意图提示（L1 · 2026-10-28）
   一行，说"我理解成什么"+ 直达入口。
   不做长解释——搜索框里没人读长文。 */
.sr-intent {
  display: flex; align-items: baseline; gap: .8rem; flex-wrap: wrap;
  padding: .9rem 1rem; margin-bottom: .6rem;
  background: var(--xj-vermilion-wash);
  border-left: 2px solid var(--xj-vermilion);
  text-decoration: none;
}
.sr-intent b {
  font-weight: 400; font-size: var(--fs-14); color: var(--xj-ink);
  font-family: var(--font-song);
}
.sr-intent span {
  font-size: var(--fs-12); color: var(--xj-vermilion);
  letter-spacing: .04em;
}

/* 会话记忆（L2/L3 · 2026-10-28）
   两处痕迹，都很轻：
     .from-post  商详页上一行「你刚读的那篇里提过它」
     .seen-dot   商品卡角上一个点，表示"你看过这个牌子"
   不弹窗、不遮挡、不追问。**只在真有关联时出现。** */
.from-post {
  display: inline-block; margin-top: 1rem;
  padding: .5rem .9rem;
  background: var(--xj-vermilion-wash);
  border-left: 2px solid var(--xj-vermilion);
  font-size: var(--fs-12); color: var(--xj-ink-70);
  text-decoration: none; letter-spacing: .02em;
  max-width: 46ch;
}
.from-post b { font-weight: 400; color: var(--xj-ink) }
.from-post:hover b { color: var(--xj-vermilion) }

.seen-dot {
  position: absolute; top: .8rem; right: .8rem;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--xj-vermilion); opacity: .55;
}
.sku { position: relative }

/* ==========================================================================
   你最近看的（意图排序 · 2026-10-28）
   --------------------------------------------------------------------------
   不是推荐，是**把他刚看过的放回眼前**。
   所以样式要像"刚才那一页的延续"，不能像广告——
   所以用细边框 + 纸底，不用朱色、不用"猜你喜欢"这种话。
   ========================================================================== */
.recent-row {
  display: flex; gap: 1px;
  background: var(--xj-ink-08);
  border: var(--hair);
}
.recent-card {
  flex: 1 1 0; min-width: 0;
  padding: 1.1rem 1.2rem;
  background: var(--xj-paper);
  text-decoration: none;
  display: flex; flex-direction: column; gap: .4rem;
  transition: background 200ms var(--ease-out);
}
.recent-card:hover { background: var(--xj-paper-raise) }
.recent-n {
  font-size: var(--fs-14); color: var(--xj-ink); line-height: 1.4;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.recent-p {
  font-family: var(--font-latin); font-size: var(--fs-14);
  color: var(--xj-vermilion); letter-spacing: .02em;
}
@media (max-width: 640px) {
  .recent-row { flex-wrap: wrap }
  .recent-card { flex: 1 1 46% }
}

/* ==========================================================================
   收藏（L3 · 2026-10-28）
   --------------------------------------------------------------------------
   放在正文结束处，不是页面顶部——
   读到这儿的人才可能想"留着以后看"。
   样式要像一句旁注，不像一个 CTA 按钮。
   ========================================================================== */
.fav-box {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  margin: 2.4rem 0 0; padding-top: 1.2rem;
  border-top: var(--hair);
}
.fav-btn {
  display: inline-flex; align-items: center; gap: .5rem;
  background: none; border: var(--hair); padding: .55rem .9rem;
  font-family: var(--font-hei); font-size: var(--fs-12);
  letter-spacing: .08em; color: var(--xj-ink-70);
  cursor: pointer; transition: all 200ms var(--ease-out);
}
.fav-btn svg { width: 14px; height: 14px }
.fav-btn:hover { color: var(--xj-ink); border-color: var(--xj-ink-38) }
.fav-btn.is-on {
  color: var(--xj-vermilion);
  border-color: rgba(168, 57, 46, .4);
  background: var(--xj-vermilion-wash);
}
.fav-btn.is-on svg { fill: currentColor }
.fav-note { font-size: var(--fs-12); color: var(--xj-ink-52); letter-spacing: .02em }

/* ==========================================================================
   传给谁（L4 · 2026-10-28）
   --------------------------------------------------------------------------
   一句话说清"这篇适合发给谁"，比一个"分享"按钮有用。
   样式压得很低——它是内容的一部分，不是促销位。
   ========================================================================== */
.share-to {
  margin: 1.6rem 0 0;
  padding: 1.1rem 1.3rem;
  background: var(--xj-paper-sink);
  display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap;
}
.share-who {
  margin: 0; font-size: var(--fs-14); color: var(--xj-ink-70);
  letter-spacing: .02em;
}
.share-who b { font-weight: 400; color: var(--xj-ink); }
.share-btn {
  background: none; border: var(--hair); padding: .35rem .8rem;
  font-family: var(--font-hei); font-size: var(--fs-12);
  letter-spacing: .08em; color: var(--xj-ink-70); cursor: pointer;
  transition: all 200ms var(--ease-out);
}
.share-btn:hover { color: var(--xj-vermilion); border-color: rgba(168,57,46,.4) }
.share-done { font-size: var(--fs-12); color: var(--xj-vermilion); }

/* ==========================================================================
   手机端修复（2026-10-28 · 老谢反馈"排版乱了"）
   --------------------------------------------------------------------------
   三个错叠在一起：

   ① 导航条：.jieqi-bar-in 高度固定 38px，内部 flex 没设 nowrap。
      文字放不下就**逐字换行**，溢出但高度不变 → 六项糊成一团。
      修法：不换行 + 横向滚动（内容都在，手指能划）。

   ② 首屏主标题：clamp 的下限 2rem = 32px，390px 宽下折成三行，
      最后"酒"字孤零零一行。手机端降一档。

   ③ 右下角浮动"今天"按钮：position:fixed 压住了节气进度。
      手机端缩到 44px 内并让开底部安全区。

   为什么现在才发现：之前只在 1440px 桌面测过。
   **没在真机上量过，就等于没做。**
   ========================================================================== */

@media (max-width: 640px) {
  /* ① 导航条：横滑，不换行 */
  .jieqi-bar-in {
    gap: .85rem;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* 右侧留一点，最后一个字不贴着边 */
    padding-right: 1rem;
  }
  .jieqi-bar-in::-webkit-scrollbar { display: none; }
  .jieqi-now { white-space: nowrap; flex-shrink: 0; }
  .jieqi-links { flex-shrink: 0; gap: 1.1rem; }
  .jieqi-links a { white-space: nowrap; }

  /* ② 首屏主标题：降一档，避免孤字
     实测 390px 下 h1 是 33.96px、"霜降 · 草木黄落该封瓮了——冬至的酒"
     十五个字，折成三行，最后"酒"孤零零一行。
     降到约 26px 能两行收住。
     注意：这个 h1 **没有 class**，只能按标签选。 */
  h1 {
    font-size: clamp(1.5rem, 6.8vw, 1.85rem) !important;
    line-height: 1.38;
  }

  /* ③ 右下角 AI 入口（.chat-fab）
     52×52 写"问一句今天吃什么"七个字，在 52px 宽里被挤成"今天"，
     同时压住节气进度。手机端缩到 46 并让开安全区。
     不改 HTML——改宽度就够，文字自己会收敛。 */
  .chat-fab {
    /* 46 还是压住了"今日主推"那一行，再收一档到 40。
       低于 44px 会不满足触控标准，所以用 ::after 把点击区撑回 48——
       看得见的是 40，摸得到的是 48。 */
    width: 40px;
    height: 40px;
    font-size: 9px;
    line-height: 1.1;
    right: .6rem;
    bottom: calc(.6rem + env(safe-area-inset-bottom, 0px));
    padding: 3px;
    opacity: .9;
    position: fixed;
  }
  .chat-fab::after {
    content: "";
    position: absolute;
    inset: -4px;
    border-radius: 50%;
  }
  /* 40px 的块里塞七个字，结果被挤成"今天吃"——比不显示还糟。
     手机端只留一个字：把原文字隐藏，用 ::before 放一个"问"。
     一个"问"字自己就说明白了，而且不会糊。 */
  .chat-fab {
    font-size: 0 !important;
    letter-spacing: 0;
  }
  .chat-fab::before {
    content: "问";
    font-size: 15px;
    line-height: 1;
    display: block;
    text-align: center;
  }
  /* 40px 的块里塞七个字，结果被挤成"今天吃"——比不显示还糟。
     手机端只留一个字：把原文字隐藏，用 ::before 放一个"问"。
     一个"问"字自己就说明白了，而且不会糊。 */
  .chat-fab {
    font-size: 0 !important;
    letter-spacing: 0;
  }
  .chat-fab::before {
    content: "问";
    font-size: 15px;
    line-height: 1;
    display: block;
    text-align: center;
  }

  /* ⑥ 当季主推带的器皿图形（2026-10-28 修）
     那块是两栏：左文右图。手机上收成一栏后，图形占满整行、
     又排在文字后面，淡墨线直接压在商品名和按钮上——
     看着像"排版乱了"，其实是**这个图形在手机上没意义**。
     它在大屏是留白，在小屏是遮挡。手机端直接不显示。 */
  .push-grid { gap: 1.4rem; }
  .push-side-art { display: none; }
  .push-lead { position: relative; z-index: 2; }
  .push-title { font-size: 32px; line-height: 1.15; }
  .push-prod { font-size: 19px; margin-bottom: 1.1rem; }
  .push-why { font-size: 14px; line-height: 1.85; padding-left: .9rem; }

  /* ⑥ 当季主推带的器皿图形（2026-10-28 修）
     那块是两栏：左文右图。手机上收成一栏后，图形占满整行、
     又排在文字后面，淡墨线直接压在商品名和按钮上——
     看着像"排版乱了"，其实是**这个图形在手机上没意义**。
     它在大屏是留白，在小屏是遮挡。手机端直接不显示。 */
  .push-grid { gap: 1.4rem; }
  .push-side-art { display: none; }
  .push-lead { position: relative; z-index: 2; }
  .push-title { font-size: 32px; line-height: 1.15; }
  .push-prod { font-size: 19px; margin-bottom: 1.1rem; }
  .push-why { font-size: 14px; line-height: 1.85; padding-left: .9rem; }

  /* ⑤ 二十四节气时轴（2026-10-28 修）
     手机端本来是两列网格，但 .tl-item 里的季节标签和圆点
     都是 position:absolute; top:-4.4rem / -2.6rem ——
     它们绝对定位跑到 item 上方，两列网格里全部压在一起，
     于是"立春 / Li chun / 春"三层字糊成一片。

     修法：手机端全部改回静态流，标签在名字上面正常占位。 */
  .timeline { padding: var(--sp-5) 0; }
  .timeline-track { gap: 1px; }
  .tl-item {
    padding: .9rem .5rem;
    min-width: 0;
    text-align: center;
  }
  .tl-item::before { display: none; }   /* 横轴才需要圆点，纵向列表不需要 */
  .tl-season-tag {
    position: static;                   /* ← 关键：不再飞出容器 */
    display: block;
    margin: 0 0 .25rem;
    font-size: 10px;
    letter-spacing: .18em;
    opacity: .75;
  }
  .tl-name { font-size: 14px; line-height: 1.4; }
  .tl-date { display: block; margin-top: .15rem; font-size: 10px; line-height: 1.4; }

  /* ④ 横向卡片：右侧留白，别贴边被裁 */
  .rail, .scroll-x, [class*="rail"] {
    padding-right: 1.2rem;
    scroll-padding-left: 1.2rem;
  }
}

/* ==========================================================================
   三端适配 · 第一道防线（2026-10-28）
   --------------------------------------------------------------------------
   这一层**不改任何现有设计**，只做一件事：**不许撑破视口**。

   为什么先做这个：
     全站有 160 处固定 px 宽高、12 种断点。逐个改要几天，
     但"元素撑破视口 → 横向滚动条 → 内容被裁"这些**最刺眼的症状**，
     用 20 行就能拦住。**先止血，再治病。**

   它拦不住的：间距不匀、字号比例失衡、栅格列数在 iPad 上难看——
   那些要靠断点收敛和尺寸流体化，是第二步的事。
   ========================================================================== */

/* ① 盒模型统一：不统一的话，加 padding 就会撑破 */
*, *::before, *::after { box-sizing: border-box; }

/* ② 媒体不许超宽。这是 90% "手机上图片撑破" 的根因 */
img, svg, video, canvas, iframe, picture { max-width: 100%; height: auto; }
/* 但图标类 SVG 不该被 height:auto 拉变形 */
[class*="icon"] svg, [class*="-ic"] svg, .brand-mark svg { height: auto; }

/* ③ 表格单独处理：宁可横滑，不许把整页顶宽 */
table { max-width: 100%; }
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ④ flex / grid 的子项默认 min-width:auto，长单词和中文会把容器撑破。
      这一条能救掉大量"某一列突然变宽"的怪现象。 */
[class*="grid"] > *, [class*="-in"] > *, [class*="row"] > * { min-width: 0; }

/* ⑤ 长串英文 / URL 不许撑破（比如邮箱、openid、长标题） */
h1, h2, h3, p, li, td, .push-title, .tl-name { overflow-wrap: anywhere; }

/* ⑥ 视口单位在移动端会被地址栏高度干扰，用 dvh 兜底 */
.hero, [class*="full"] { min-height: auto; }
