/* ==========================================================================
   时光邮局 TIME POST OFFICE · 品牌设计系统
   色板严格取自《时光邮局完整商业方案 v2.0》P50「暖金记忆系统」
   ========================================================================== */

/* ── 1. 设计令牌 ───────────────────────────────────────────────────────── */

:root {
  /* VI 主色 */
  --paper:      #F5F0E6;  /* 暖米白 · 底色 */
  --gold:       #B8863B;  /* 赭石金 · 强调 */
  --ink:        #3A2E25;  /* 深棕 · 主字 */
  --green:      #6B8E6B;  /* 墨绿 · 点缀 */

  /* 派生色：纸面层次 */
  --paper-lift:  #FAF6EE;
  --paper-deep:  #EFE8D9;
  --paper-sink:  #E9E0CD;

  /* 派生色：以下四个都按 WCAG AA（≥4.5:1）实测选定，纸色底上的实测值写在注释里 */
  --ink-soft:  #6B5A4A;  /* 次级文字 · 纸底 5.8:1 */
  --ink-faint: #736353;  /* 三级文字与提示 · 纸底 5.1:1，深纸底 4.8:1 */
  --gold-ink:  #8A6023;  /* 赭石金 · 小字专用 4.9:1 */
  --green-ink: #4A6B4A;  /* 墨绿 · 小字专用 5.2:1 */

  --line:      #E2D8C3;
  --line-soft: #EDE4D2;

  --danger:    #A8443A;
  --danger-bg: #F7EBE8;

  /* 字体：标题衬线求「敬意与印刷感」，正文无衬线求「清晰与温度」 */
  --font-serif: "Songti SC", "STSong", "Source Han Serif SC", "Noto Serif SC",
                "SimSun", "宋体", Georgia, serif;
  --font-sans:  "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB",
                "Source Han Sans SC", "Noto Sans SC", -apple-system,
                BlinkMacSystemFont, "Segoe UI", sans-serif;

  /* 排版尺度 */
  --fs-hero:   clamp(2.1rem, 5.2vw, 3.9rem);
  --fs-h2:     clamp(1.6rem, 3.2vw, 2.35rem);
  --fs-h3:     clamp(1.15rem, 2vw, 1.4rem);
  --fs-body:   1rem;
  --fs-small:  0.875rem;
  --fs-tiny:   0.78rem;

  --wrap:        1160px;
  --wrap-narrow: 800px;
  --radius:      4px;   /* 克制的圆角，印刷物不该像 App */
  --radius-lg:   8px;

  --shadow-sm: 0 1px 2px rgba(58, 46, 37, .05);
  --shadow:    0 6px 22px rgba(58, 46, 37, .07);
  --shadow-lg: 0 18px 48px rgba(58, 46, 37, .11);

  --ease: cubic-bezier(.22, .61, .36, 1);
}

/* ── 2. 重置 ───────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.85;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* 纸纹：用 SVG 湍流生成，无外部图片依赖 */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .55;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)' opacity='.05'/%3E%3C/svg%3E");
}

body > * { position: relative; z-index: 1; }

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; }

h1, h2, h3, h4 {
  font-family: var(--font-serif);
  font-weight: 600;
  line-height: 1.35;
  margin: 0 0 .6em;
  letter-spacing: .01em;
}

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

ul { margin: 0; padding: 0; list-style: none; }

:focus-visible {
  outline: 2px solid var(--gold-ink);
  outline-offset: 3px;
  border-radius: 2px;
}

/* 跳到主内容：键盘可达性 */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper-lift);
  padding: .7em 1.2em;
  z-index: 999;
}
.skip-link:focus { left: 0; }

/* ── 3. 布局原语 ───────────────────────────────────────────────────────── */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: 22px;
}
.wrap--narrow { max-width: var(--wrap-narrow); }

.section { padding: clamp(3.4rem, 7vw, 6rem) 0; }
.section--tight { padding: clamp(2.4rem, 5vw, 3.6rem) 0; }
.section--deep  { background: var(--paper-deep); }
.section--lift  { background: var(--paper-lift); }
.section--ink   { background: var(--ink); color: var(--paper); }
.section--ink h2, .section--ink h3 { color: var(--paper-lift); }

/* 章节头 */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: .6em;
  font-size: var(--fs-tiny);
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--gold-ink);
  margin-bottom: .9rem;
}
.eyebrow::before {
  content: '';
  width: 26px;
  height: 1px;
  background: var(--gold);
}
.section--ink .eyebrow { color: var(--gold); }

.section-title {
  font-size: var(--fs-h2);
  margin-bottom: .5em;
  max-width: 22em;
}
.section-sub {
  color: var(--ink-soft);
  max-width: 42em;
  margin-bottom: 2.4rem;
  font-size: 1.02rem;
}
.section--ink .section-sub { color: #CFC2AE; }
.section-head--center { text-align: center; }
.section-head--center .section-title,
.section-head--center .section-sub { margin-inline: auto; }
.section-head--center .eyebrow::before { display: none; }

/* 装饰性分隔：胶片齿孔 */
.film-rule {
  height: 10px;
  background-image: repeating-linear-gradient(
    90deg,
    var(--line) 0 6px,
    transparent 6px 18px
  );
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

/* ── 4. 按钮与徽章 ─────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55em;
  padding: .82em 1.9em;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: .95rem;
  font-weight: 500;
  letter-spacing: .04em;
  cursor: pointer;
  transition: background .25s var(--ease), color .25s var(--ease),
              border-color .25s var(--ease), transform .25s var(--ease);
  text-align: center;
}
.btn:hover { transform: translateY(-1px); }

.btn--primary {
  background: var(--ink);
  color: var(--paper-lift);
}
.btn--primary:hover { background: #4A3B2E; }

.btn--gold {
  background: var(--gold);
  color: #FFFDF8;
}
.btn--gold:hover { background: var(--gold-ink); }

.btn--ghost {
  border-color: var(--ink);
  color: var(--ink);
}
.btn--ghost:hover { background: var(--ink); color: var(--paper-lift); }

.btn--light {
  border-color: rgba(245, 240, 230, .45);
  color: var(--paper-lift);
}
.btn--light:hover { background: var(--paper-lift); color: var(--ink); border-color: var(--paper-lift); }

.btn--block { width: 100%; }
.btn--sm { padding: .55em 1.2em; font-size: .85rem; }

.btn-row { display: flex; flex-wrap: wrap; gap: .9rem; }

.tier {
  display: inline-block;
  font-size: var(--fs-tiny);
  letter-spacing: .12em;
  padding: .22em .7em;
  border: 1px solid currentColor;
  border-radius: 2px;
  line-height: 1.6;
}
.tier-lead     { color: var(--green-ink); }
.tier-main     { color: var(--gold-ink); }
.tier-plus     { color: var(--ink-soft); }
.tier-flagship { color: var(--danger); }

.tag {
  display: inline-block;
  font-size: var(--fs-tiny);
  color: var(--ink-soft);
  background: var(--paper-deep);
  border: 1px solid var(--line);
  padding: .2em .7em;
  border-radius: 2px;
}

/* ── 5. 记忆邮戳 ───────────────────────────────────────────────────────── */

.postmark {
  color: var(--gold);
  width: 100%;
  height: auto;
}
.postmark--ink { color: var(--ink); }

.postmark-badge {
  display: inline-grid;
  place-items: center;
  width: 84px;
  height: 84px;
  color: var(--gold);
  flex-shrink: 0;
}
.postmark-badge--sm { width: 58px; height: 58px; }
.postmark-badge--lg { width: 128px; height: 128px; }

/* 盖章动效：首屏邮戳落入 */
@keyframes stamp-in {
  0%   { opacity: 0; transform: scale(2.1) rotate(-16deg); }
  60%  { opacity: .9; transform: scale(.94) rotate(2deg); }
  80%  { transform: scale(1.03) rotate(-1deg); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}
.stamp-in {
  animation: stamp-in .95s var(--ease) .35s both;
}

/* ── 6. 站点导航 ───────────────────────────────────────────────────────── */

.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: rgba(245, 240, 230, .9);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.site-header.is-stuck {
  border-bottom-color: var(--line);
  box-shadow: var(--shadow-sm);
}

.nav {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  min-height: 74px;
}

.brand {
  display: flex;
  align-items: center;
  gap: .7rem;
  margin-right: auto;
  flex-shrink: 0;
}
.brand__mark { width: 40px; height: 40px; color: var(--gold); }
.brand__text { display: flex; flex-direction: column; line-height: 1.15; }
.brand__cn {
  font-family: var(--font-serif);
  font-size: 1.16rem;
  font-weight: 600;
  letter-spacing: .16em;
}
.brand__en {
  font-size: .58rem;
  letter-spacing: .3em;
  color: var(--ink-faint);
  text-transform: uppercase;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 1.9rem;
}
.nav__link {
  font-size: .95rem;
  letter-spacing: .04em;
  padding: .3em 0;
  border-bottom: 1px solid transparent;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.nav__link:hover { color: var(--gold-ink); }
.nav__link.is-active {
  color: var(--gold-ink);
  border-bottom-color: var(--gold);
}

.nav__toggle {
  display: none;
  width: 42px;
  height: 42px;
  background: none;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
  padding: 10px 9px;
}
.nav__toggle span {
  display: block;
  height: 1.5px;
  background: var(--ink);
  margin: 4px 0;
  transition: transform .3s var(--ease), opacity .25s var(--ease);
}
.nav__toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

/* ── 7. 首屏：全出血影像 ───────────────────────────────────────────────── */

/*
 * 首屏用一张老式放映机的照片打底，文字直接压在画面上。
 * 压层是两层叠加：纵向渐变压暗保证上下边缘的文字可读，
 * 左上角的径向渐变再压一次，避免亮部吃掉标题。
 */
.hero {
  position: relative;
  isolation: isolate;
  display: grid;
  align-items: center;
  min-height: clamp(580px, 92vh, 900px);
  padding: clamp(3.4rem, 7vw, 5.5rem) 0 clamp(2.6rem, 5vw, 4rem);
  background: #1B1510;
  color: var(--paper-lift);
  overflow: hidden;
}
.hero__media {
  position: absolute;
  inset: 0;
  /*
   * 首屏层序（由下往上）：
   *   照片 -6 → 压暗层 -5 → 锥形光柱 -4 → 胶片瑕疵 -3 → 片门暗角 -2 → 浮尘 -1
   *   → 文字（静态，自动在最上）→ 胶片颗粒 0
   */
  z-index: -6;
}
.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 44%;
}
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  /* 必须低于光柱与浮尘：亮部压在 74% 的暗层下面就没有意义了 */
  z-index: -5;
  background:
    linear-gradient(180deg,
      rgba(18, 13, 9, .74) 0%,
      rgba(18, 13, 9, .40) 32%,
      rgba(18, 13, 9, .58) 70%,
      rgba(18, 13, 9, .93) 100%),
    radial-gradient(135% 85% at 20% 44%, rgba(18, 13, 9, .70) 0%, rgba(18, 13, 9, .06) 70%);
}

/* 首屏内的文字：全部走浅色 */
.hero__kicker,
.hero__title,
.hero__lead,
.hero__hook { color: var(--paper-lift); }

.hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: end;
  width: 100%;
}
.hero__kicker {
  font-size: var(--fs-tiny);
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 1.5rem;
}
.hero__title {
  font-size: var(--fs-hero);
  line-height: 1.26;
  letter-spacing: .02em;
  margin-bottom: 1.4rem;
  text-shadow: 0 2px 30px rgba(0, 0, 0, .45);
  max-width: 18em;
}
.hero__title em {
  font-style: normal;
  color: #E4C07A;
  position: relative;
}
/* 手绘下划线 */
.hero__title em::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: .02em;
  height: .32em;
  background: linear-gradient(90deg, rgba(184, 134, 59, .55), rgba(184, 134, 59, .06));
  z-index: -1;
  border-radius: 2px;
}
.hero__lead {
  font-size: clamp(1rem, 1.4vw, 1.1rem);
  color: #DED3C0;
  max-width: 34em;
  margin-bottom: 1.9rem;
}
.hero__hook {
  font-family: var(--font-serif);
  font-size: 1.06rem;
  color: var(--paper-lift);
  padding-left: 1.1rem;
  margin-bottom: 2.2rem;
  position: relative;
}
.hero__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 1.2rem 2.6rem;
  margin-top: 2.8rem;
  padding-top: 1.8rem;
  position: relative;
}
/* 分隔线放在伪元素上：直接在容器上做 scaleX 会把里面的文字横向压扁 */
.hero__facts::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: rgba(245, 240, 230, .2);
  transform-origin: center;
}
.hero__fact strong {
  display: block;
  font-family: var(--font-serif);
  font-size: 1.3rem;
  line-height: 1.4;
  color: var(--paper-lift);
}
.hero__fact span {
  font-size: var(--fs-tiny);
  color: #A99B87;
  letter-spacing: .06em;
}

/* 右下角的记忆邮戳，像盖在照片上 */
.hero__seal {
  display: grid;
  justify-items: center;
  gap: 1rem;
  padding-bottom: .6rem;
}
.hero__seal .postmark-badge { color: rgba(232, 214, 180, .92); }
.hero__seal-caption {
  font-size: .62rem;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: #A99B87;
  text-align: center;
  line-height: 1.9;
  margin: 0;
}

/* 首屏底部的下滑提示 */
.hero__scroll {
  position: absolute;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  display: grid;
  justify-items: center;
  gap: .5rem;
  font-size: .6rem;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: #9C8F7C;
}
.hero__scroll::after {
  content: '';
  width: 1px;
  height: 34px;
  background: linear-gradient(180deg, var(--gold), transparent);
}

/* ── 7.1 首屏动效 ──────────────────────────────────────────────────────── */

/*
 * 动效的灵感全部来自首屏那张照片：老式放映机投出的一道光柱。
 * 所以做的是「胶片在走、空气里有尘、光在轻微闪」，而不是通用的弹跳缩放。
 *
 * 两条硬约束：
 *   1. 基础状态一律是「可见」，动画只负责把它从隐藏演到可见。
 *      动画完全没跑（老浏览器、脚本报错、JS 被禁）时内容也不会消失。
 *   2. 全部挂在 html.has-js 下，并由文件末尾的 prefers-reduced-motion 统一关闭。
 */

/* 入场：自下而上浮起 + 淡入 */
@keyframes hero-rise {
  from { opacity: 0; transform: translate3d(0, 26px, 0); }
  to   { opacity: 1; transform: none; }
}
.has-js .hero-seq {
  animation: hero-rise .9s var(--ease) both;
  animation-delay: var(--d, 0s);
}

/* 标题按行擦除揭示，比整块淡入更像照片在显影 */
@keyframes hero-unveil {
  from { opacity: 0; clip-path: inset(0 100% 0 0); transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; clip-path: inset(0 0 0 0);    transform: none; }
}
.hero__line { display: block; }
.has-js .hero__line {
  animation: hero-unveil 1.05s var(--ease) both;
  animation-delay: var(--d, 0s);
}

/* 标题下划线从左往右画出来 */
@keyframes hero-rule-draw {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
.hero__title em::after { transform-origin: left center; }
.has-js .hero__title em::after {
  animation: hero-rule-draw 1s var(--ease) both;
  animation-delay: 1.05s;
}

/* 承诺行左侧金线由上往下长出 */
@keyframes hero-bar-grow {
  from { transform: scaleY(0); }
  to   { transform: scaleY(1); }
}
.hero__hook::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--gold);
  transform-origin: top center;
}
.has-js .hero__hook::before {
  animation: hero-bar-grow .8s var(--ease) both;
  animation-delay: .96s;
}

/* 底部事实行：内容浮起，顶部分隔线从中间展开 */
@keyframes hero-facts-line {
  from { opacity: 0; transform: scaleX(.15); }
  to   { opacity: 1; transform: scaleX(1); }
}
.has-js .hero__facts {
  animation: hero-rise .9s var(--ease) both;
  animation-delay: 1.02s;
}
.has-js .hero__facts::before {
  animation: hero-facts-line 1s var(--ease) both;
  animation-delay: 1.15s;
}

/* 邮戳等文字落定后再盖下去。
   基础 .stamp-in 是无条件的，这里只在有 JS 时把延迟并入编排；
   无 JS 时盖印会立刻完成，同样停在「已盖上」的状态。 */
.has-js .hero .stamp-in { animation-delay: 1.35s; }

/* 下滑提示：整体淡入，竖线反复伸缩，像在等人往下走 */
@keyframes hero-scroll-line {
  0%, 100% { transform: scaleY(.35); opacity: .35; }
  45%      { transform: scaleY(1);   opacity: 1; }
}
.hero__scroll::after { transform-origin: top center; }
.has-js .hero__scroll { animation: hero-rise 1s var(--ease) 1.6s both; }
.has-js .hero__scroll::after {
  animation: hero-scroll-line 2.4s ease-in-out 2.4s infinite;
}

/*
 * 放映机闪烁。
 * 照片本身就是老式放映机投出的光柱，让亮度极轻微跳动会读成「胶片在走片」。
 * 幅度刻意压在 5% 以内——再大就不像放映机，像页面出故障了。
 */
@keyframes projector-flicker {
  0%, 100% { opacity: 1; }
  7%       { opacity: .955; }
  9%       { opacity: 1; }
  33%      { opacity: .975; }
  35%      { opacity: 1; }
  61%      { opacity: .95; }
  64%      { opacity: 1; }
  86%      { opacity: .98; }
  88%      { opacity: 1; }
}
/* 闪烁的声明在 7.2 节「仿真放映」里，与片门抖动合并挂在同一个元素上 */

/*
 * 光柱里的浮尘。
 * 颗粒参数由页面按固定数组生成（不用随机数），保证每次刷新位置一致、也便于微调。
 * 只动 transform 与 opacity，全部在合成层完成，不触发布局。
 */
.beam-dust {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;
}
.beam-dust i {
  position: absolute;
  /*
   * 浮尘的位置也改成「在光柱里的相对位置」而不是屏幕坐标：
   *   --xf  0 = 光柱可见跨度的左端，1 = 可见跨度的镜头端
   *   --fy  -1 = 光柱下缘，0 = 中线，1 = 上缘
   * 由 --beam-mid-* 与 --beam-half-* 插值算出实际坐标，
   * 于是窗口一缩放，颗粒依然落在光柱里，不会被留在原地变成「黑暗里的亮点」。
   */
  --f: calc(1 - var(--beam-k) * var(--xf, .5));
  --m: calc(var(--beam-mid-lens) + (var(--beam-mid-far) - var(--beam-mid-lens)) * var(--f));
  --h: calc(var(--beam-half-lens) + (var(--beam-half-far) - var(--beam-half-lens)) * var(--f));
  left: calc(var(--beam-x-end) * var(--xf, .5));
  top: calc(var(--m) + var(--h) * var(--fy, 0));
  width: var(--s, 3px);
  height: var(--s, 3px);
  border-radius: 50%;
  /*
   * 粒子不能只用「实心小点」：早先直径 2~5px、渐变在 70% 处就透明，
   * 实际可见核心只有 1~3px，在 1400px 宽的画面上就是个针尖，等于看不见。
   * 现在改成「亮核 + 柔晕」，光晕一直铺到盒子边缘，所以可见直径就等于 --s。
   */
  background: radial-gradient(circle,
    rgba(255, 250, 232, .98) 0%,
    rgba(248, 236, 206, .74) 34%,
    rgba(245, 232, 205, .26) 62%,
    rgba(245, 232, 205, 0) 100%);
  opacity: 0;
  will-change: transform, opacity;
}
.has-js .beam-dust i {
  animation: dust-float var(--dur, 18s) linear var(--delay, 0s) infinite;
}
/*
 * 浮尘只在光柱里才看得见，所以上升幅度由 --rise 控制且普遍偏小：
 * 早先固定上升 88vh，颗粒早就飘出光柱之外还在发亮，那不符合物理。
 * 离镜头越远的颗粒处光柱越高，可以给更大的 --rise。
 *
 * 中间那一段「先暗一下、再亮过基准、然后回落」是刻意的：
 * 尘埃在飘动中转到某个角度才会反光，亮一下又暗下去 —— 这正是丁达尔效应里
 * 颗粒一闪一闪的来源。匀速淡入淡出是不会有这个感觉的。
 */
@keyframes dust-float {
  0%   { opacity: 0; transform: translate3d(0, 0, 0) scale(.5); }
  9%   { opacity: var(--o, .5); }
  34%  { opacity: calc(var(--o, .5) * .68);
         transform: translate3d(calc(var(--dx, 18px) * .55), calc(var(--rise, 14vh) * -.33), 0) scale(.85); }
  50%  { opacity: calc(var(--o, .5) * 1.9);   /* 反光的一瞬 */
         transform: translate3d(var(--dx, 18px), calc(var(--rise, 14vh) * -.5), 0) scale(1.2); }
  68%  { opacity: calc(var(--o, .5) * .78);
         transform: translate3d(calc(var(--dx, 18px) * 1.45), calc(var(--rise, 14vh) * -.75), 0) scale(.95); }
  88%  { opacity: var(--o, .5); }
  100% { opacity: 0;
         transform: translate3d(calc(var(--dx, 18px) * 2), calc(var(--rise, 14vh) * -1), 0) scale(.6); }
}

/*
 * 颗粒抖动：真实胶片每一格颗粒都在变。
 * 用 steps(1) 做硬切换而不是平滑位移——平滑看起来像雾在飘，硬切才像颗粒在跳。
 * inset 留出 14% 余量，位移时不会露出边缘。只作用于首屏，其他影像带不跑。
 */
@keyframes grain-jump {
  0%   { transform: translate3d(0, 0, 0); }
  25%  { transform: translate3d(-5%, 3%, 0); }
  50%  { transform: translate3d(4%, -5%, 0); }
  75%  { transform: translate3d(-3%, -4%, 0); }
  100% { transform: translate3d(5%, 5%, 0); }
}
.has-js .hero.grain::before {
  inset: -14%;
  animation: grain-jump 1.15s steps(1) infinite;
}

/* 首屏下方那条齿孔缓慢左移，暗示胶片在走片 */
@keyframes sprocket-run {
  from { background-position-x: 0; }
  to   { background-position-x: -26px; }
}
.has-js .hero + .sprockets { animation: sprocket-run 1.6s linear infinite; }

/* ── 7.2 仿真放映 ──────────────────────────────────────────────────────── */

/*
 * 把整个首屏当成一格正在放映的胶片来处理，而不只是让照片明暗跳一下。
 *
 * 模拟的是真实放映时会被肉眼察觉的五件事：
 *   1. 片门抖动 —— 每换一格画面，投出来的影像会轻微跳一下，且是离散的跳动
 *   2. 片门暗角 —— 投影光斑四周的亮度衰减，形成一圈柔和的暗边
 *   3. 垂直划痕 —— 胶片走片时被刮出的细亮线，缓慢横向漂移、忽明忽暗
 *   4. 尘点毛发 —— 附着在片基上的灰尘，闪一下就没了
 *   5. 光斑呼吸 —— 光柱本身的亮度起伏
 *
 * 幅度全部刻意压小。这套东西一旦明显，就从「放映」变成「故障」了。
 * 参数集中在 .hero 的自定义属性里，想调只改这一处。
 */
.hero {
  --weave-scale: 1.006;   /* 片门抖动的基础放大，必须 >1，否则位移时会露出边缘 */
  --weave-nudge: 0.7px;   /* 抖动幅度 */
  --scratch-strength: 1;  /* 划痕强度倍率 */
  --beam-strength: 1;     /* 锥形光柱强度倍率，调 0 即关闭 */
  /*
   * 镜头在首屏里的位置（按 object-fit: cover 的映射反推）：
   *   横向 ≈ 0.489 ×（容器高/容器宽）+ 0.5
   * 这个值随容器高宽比变化，CSS 算不出来，由 main.js 的 initHeroBeam() 实时写入。
   * 下面这些是 1440×900 下的参考值，作为 JS 未运行时的兜底。
   */
  --lens-x: 78%;
  --lens-y: 35%;
  /* 镜头孔径在首屏里的上下边 —— 光柱近端这条平边的高度就取自这里 */
  --aperture-top: 29.8%;
  --aperture-bot: 40.2%;
  /* 光柱远端（画面左缘）的上下边 */
  --beam-far-top: 3.4%;
  --beam-far-bot: 72.4%;
  /*
   * 光柱中线与半高在「镜头端」和「远端」两处的值。
   * 亮度带与浮尘不写死屏幕坐标，而是给出自己在光柱上的相对位置，
   * 由这四个值线性插值算出实际坐标 —— 这样几何一变，它们跟着一起走。
   */
  --beam-mid-lens: 35%;
  --beam-half-lens: 5.2%;
  --beam-mid-far: 37.88%;
  --beam-half-far: 34.54%;
  /*
   * 光柱在画面里实际可见的跨度。竖屏时镜头的渲染位置会超过 100%（被裁到画面外），
   * 此时可见跨度一直延伸到画面左缘。亮度带与浮尘按这个跨度分布，
   * 而不是按镜头位置的比例 —— 否则会被一起推到画面外面。
   */
  --beam-x-end: 78%;
  --beam-k: 1;
  --beam-softness: 18px;  /* 边缘柔化半径 */
}

/*
 * 1. 片门抖动。
 * 用 steps(1, end) 让每段保持起始值再硬跳 —— 真实放映的抖动是离散的，
 * 用平滑插值会变成「画面在飘」，那就不是放映机了。
 * 0.5s × 12 格 ≈ 24 帧/秒。
 */
@keyframes gate-weave {
  0%    { transform: translate3d(0, 0, 0) scale(var(--weave-scale)); }
  8.3%  { transform: translate3d(calc(var(--weave-nudge) * -.9), calc(var(--weave-nudge) * .8), 0) scale(var(--weave-scale)); }
  16.6% { transform: translate3d(calc(var(--weave-nudge) * .8), calc(var(--weave-nudge) * -.9), 0) scale(var(--weave-scale)); }
  25%   { transform: translate3d(calc(var(--weave-nudge) * 1), calc(var(--weave-nudge) * .6), 0) scale(var(--weave-scale)); }
  33.3% { transform: translate3d(calc(var(--weave-nudge) * -.6), calc(var(--weave-nudge) * -.8), 0) scale(var(--weave-scale)); }
  41.6% { transform: translate3d(calc(var(--weave-nudge) * .5), calc(var(--weave-nudge) * 1), 0) scale(var(--weave-scale)); }
  50%   { transform: translate3d(calc(var(--weave-nudge) * -1), calc(var(--weave-nudge) * .5), 0) scale(var(--weave-scale)); }
  58.3% { transform: translate3d(calc(var(--weave-nudge) * .9), calc(var(--weave-nudge) * -.6), 0) scale(var(--weave-scale)); }
  66.6% { transform: translate3d(calc(var(--weave-nudge) * -.5), calc(var(--weave-nudge) * .9), 0) scale(var(--weave-scale)); }
  75%   { transform: translate3d(calc(var(--weave-nudge) * .6), calc(var(--weave-nudge) * -1), 0) scale(var(--weave-scale)); }
  83.3% { transform: translate3d(calc(var(--weave-nudge) * -.9), calc(var(--weave-nudge) * -.5), 0) scale(var(--weave-scale)); }
  91.6% { transform: translate3d(calc(var(--weave-nudge) * .8), calc(var(--weave-nudge) * .8), 0) scale(var(--weave-scale)); }
  100%  { transform: translate3d(0, 0, 0) scale(var(--weave-scale)); }
}
.has-js .hero__media img {
  animation:
    projector-flicker 6.5s linear infinite,
    gate-weave .5s steps(1, end) infinite;
}

/*
 * 2. 片门暗角：投影光斑四周的衰减。
 * 这是静态处理而不是动画 —— 放映时暗角一直在，只是随光强微微变化，
 * 变化交给光斑呼吸去做就够了。
 */
.proj-gate {
  position: absolute;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  border-radius: 4px;
  box-shadow:
    inset 0 0 22px 5px rgba(10, 7, 5, .42),
    inset 0 0 140px 44px rgba(10, 7, 5, .38);
}

/* 缺陷层（划痕与尘点）：属于投出来的影像本身，所以压在暗角之下、光斑之上 */
.proj {
  position: absolute;
  inset: 0;
  z-index: -3;
  overflow: hidden;
  pointer-events: none;
}

/*
 * 3. 垂直划痕。
 * 基础状态是 opacity: 0 —— 这类纯装饰的瑕疵，没有动画时「不出现」才是正确表现，
 * 与内容元素「基础状态必须可见」的规则不同。
 */
.proj__scratch {
  position: absolute;
  top: -6%;
  bottom: -6%;
  left: var(--x, 20%);
  width: 1px;
  opacity: 0;
  background: linear-gradient(180deg,
    transparent 0%,
    rgba(255, 246, 228, .55) 14%,
    rgba(255, 246, 228, .3) 86%,
    transparent 100%);
}
.has-js .proj__scratch {
  animation: scratch-run var(--dur, 14s) linear var(--delay, 0s) infinite;
}
@keyframes scratch-run {
  0%   { opacity: 0; }
  5%   { opacity: calc(.5 * var(--scratch-strength)); transform: translateX(0); }
  38%  { opacity: calc(.2 * var(--scratch-strength)); transform: translateX(11px); }
  60%  { opacity: calc(.44 * var(--scratch-strength)); transform: translateX(-9px); }
  76%  { opacity: 0; }
  100% { opacity: 0; transform: translateX(0); }
}

/*
 * 4. 尘点与毛发：附着在片基上，投出来时闪一下。
 * 用长时间轴 + 极短的可见窗口，让它是「偶尔闪过」而不是「一直在那」。
 */
.proj__speck {
  position: absolute;
  left: var(--x, 30%);
  top: var(--y, 30%);
  width: var(--w, 7px);
  height: var(--h, 5px);
  border-radius: 42% 58% 50% 50%;
  background: rgba(255, 244, 220, .6);
  opacity: 0;
}
.has-js .proj__speck {
  animation: speck-flash var(--dur, 8s) linear var(--delay, 0s) infinite;
}
@keyframes speck-flash {
  0%, 95.4% { opacity: 0; }
  95.8%     { opacity: .85; }
  97.4%     { opacity: .7; }
  98%       { opacity: 0; }
  100%      { opacity: 0; }
}

/*
 * 3. 梯形光柱。
 *
 * 这是整个「仿真放映」里最要紧的一层。
 *
 * 关键几何：真实的镜头有孔径（一小片圆形开口），光束是从一个「面」射出的，不是从一个点。
 * 所以近端必须是与镜头等高的**平直边**，整体是梯形。早先用 conic-gradient 从顶点出发，
 * 近端必然收敛成一个尖点，看起来像锥子而不是光束 —— 这是错的。
 *
 * 几何是从原图量出来再按 object-fit: cover 的实际映射算的：
 *   源图 1920x824，镜头在源图 (71%, 35%)，镜头孔径纵向约占 10% 图高
 *   光束向左张开、略向下倾，源图左端的半高约为 34.5% 图高（约 12° 半张角）
 * 换算到容器百分比，梯形四个角是：
 *   近端上 (78%, 29.8%)  →  远端上 (0%, 3.4%)
 *   远端下 (0%, 72.4%)   →  近端下 (78%, 40.2%)
 * 近端这条 29.8%~40.2% 的竖直边就是镜头孔径，高度与镜头吻合。
 *
 * 柔边为什么用「父级 filter + 子级 clip-path」而不是直接在 clip-path 上做：
 * clip-path 的裁剪发生在 filter 之后，先模糊再裁剪会把柔化的边重新切成硬边。
 * 反过来把模糊放在父级，父级的 filter 作用于已经裁剪好的子树，边就是柔的。
 */
.proj__beam {
  position: absolute;
  inset: 0;
  /*
   * 注意：这一层必须是 .hero 的直接子元素，不能放进 .proj 里面。
   * .proj 带 position: absolute + z-index，本身构成层叠上下文，
   * 光柱一旦嵌进去，mix-blend-mode: screen 就只会和 .proj 内部（空的）混合，
   * 不会与照片做加色混合 —— 光柱会退化成一层半透明色块，而不是光。
   */
  z-index: -4;
  pointer-events: none;
  mix-blend-mode: screen;
  /*
   * 透明度与摆动挂在这一层，模糊挂在内层 —— 这个分层是性能要求，不是风格选择：
   * filter 会作用于整棵子树，子树里只要有任何东西在动，模糊就得逐帧重算。
   * 全屏尺寸的模糊每帧重算足以把低端机拖到掉帧。
   * 现在模糊层的内容完全静止，浏览器可以把它缓存成纹理；
   * 外层动的是 opacity 与 transform，都在合成层完成，几乎不花代价。
   */
  transform-origin: var(--lens-x) var(--lens-y);
}
.has-js .proj__beam {
  animation:
    beam-flicker 6.5s linear infinite,     /* 快速的明暗闪动，与画面闪烁同频 */
    beam-sway 17s ease-in-out infinite alternate;  /* 极缓的摆向，像机身在轻微震动 */
}
/* 模糊层：内容完全静止，只负责把梯形的硬边揉软 */
.proj__beam__blur {
  position: absolute;
  inset: 0;
  filter: blur(var(--beam-softness, 18px));
}
/* 光束本体：梯形裁剪 + 沿长度方向的衰减 */
.proj__beam__shape {
  position: absolute;
  inset: 0;
  clip-path: polygon(
    var(--lens-x) var(--aperture-top),
    0% var(--beam-far-top),
    0% var(--beam-far-bot),
    var(--lens-x) var(--aperture-bot)
  );
  background:
    /* 亮纹：光阑造成的疏密，让光看起来有结构而不是一片平涂。
       这些亮纹仍用 conic 从孔径中心发散 —— 在梯形内部，它们自然收在孔径处，不会露出尖角。
       强度同样按「看得出来」定：低于 .15 在这层亮度上等于没有。 */
    conic-gradient(from 0deg at var(--lens-x) var(--lens-y),
      rgba(255, 246, 224, 0) 0deg,
      rgba(255, 246, 224, 0) 258deg,
      rgba(255, 246, 224, calc(.26 * var(--beam-strength))) 262deg,
      rgba(255, 246, 224, 0) 267deg,
      rgba(255, 246, 224, calc(.18 * var(--beam-strength))) 275deg,
      rgba(255, 246, 224, 0) 280deg,
      rgba(255, 246, 224, 0) 360deg),
    /* 沿长度方向的衰减：近镜头最亮，越远越淡；左端被画面切掉，所以不收到 0 */
    linear-gradient(to left,
      rgba(255, 240, 208, calc(.5 * var(--beam-strength))) 0%,
      rgba(255, 240, 208, calc(.4 * var(--beam-strength))) 34%,
      rgba(255, 232, 190, calc(.28 * var(--beam-strength))) 70%,
      rgba(255, 232, 190, calc(.22 * var(--beam-strength))) 100%);
}
/* 镜头口的高光。用 ellipse 而不是 circle：圆形半径只能是长度，
   写成百分比是无效语法，会让整条 background 被丢弃 —— 这个坑踩过一次。 */
.proj__beam__hot {
  position: absolute;
  left: var(--lens-x);
  top: var(--lens-y);
  width: 9%;
  aspect-ratio: 1.5;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(ellipse 50% 50% at 50% 50%,
    rgba(255, 250, 232, calc(.62 * var(--beam-strength))) 0%,
    rgba(255, 242, 206, calc(.22 * var(--beam-strength))) 45%,
    rgba(255, 240, 200, 0) 100%);
}
/* 光强与画面闪烁同步：画面亮的时候光柱也亮一点 */
@keyframes beam-flicker {
  0%, 100% { opacity: .93; }
  7%       { opacity: 1; }
  33%      { opacity: .87; }
  61%      { opacity: .97; }
  86%      { opacity: 1; }
}
/* 摆向：以镜头为轴心极缓地左右偏一点点，像机身没放稳。
   幅度必须很小 —— 偏多了就像在摇头，不是光在动 */
@keyframes beam-sway {
  from { transform: rotate(-.16deg); }
  to   { transform: rotate(.16deg); }
}

/*
 * 丁达尔效应：光柱内部缓慢漂移的密度。
 *
 * 真实的光束之所以能被看见，是因为空气中的尘埃在散射光；尘埃密度不均匀，
 * 光柱上就会浮着一团团忽明忽暗的亮带，并且随空气缓慢移动。
 * 这一层就是那些亮带。
 *
 * 每个亮带不写死屏幕坐标，而是给出自己在光柱上的相对位置：
 *   --bN-f  0 = 贴着镜头，1 = 光柱远端
 *   --bN-y  -1 = 光柱下缘，0 = 中线，1 = 上缘
 * 实际坐标由 --beam-mid-lens/far 与 --beam-half-lens/far 插值算出，
 * 因此窗口一缩放、光柱一动，亮带自己就跟着走，不会飘到光外面去。
 *
 * 独立成层、且**不加模糊**：它自己带 transform 动效，若再叠一层 filter，
 * 模糊同样会被逐帧重算。所以柔和感靠渐变本身完成；
 * clip-path 只作为兜底 —— 亮斑的范围在设计上就没有碰到梯形边界。
 */
.proj__beam-flow {
  position: absolute;
  inset: 0;
  z-index: -4;
  pointer-events: none;
  mix-blend-mode: screen;
  clip-path: polygon(
    var(--lens-x) var(--aperture-top),
    0% var(--beam-far-top),
    0% var(--beam-far-bot),
    var(--lens-x) var(--aperture-bot)
  );

  --bm: var(--beam-mid-lens);
  --bd: calc(var(--beam-mid-far) - var(--beam-mid-lens));
  --hl: var(--beam-half-lens);
  --hd: calc(var(--beam-half-far) - var(--beam-half-lens));

  --b1-f: calc(1 - var(--beam-k) * var(--b1-xf));
  --b2-f: calc(1 - var(--beam-k) * var(--b2-xf));
  --b3-f: calc(1 - var(--beam-k) * var(--b3-xf));
  --b4-f: calc(1 - var(--beam-k) * var(--b4-xf));
  /*
   * 亮带做成「横向长、纵向扁」的椭圆，读起来才是沿光束方向的疏密条纹；
   * 圆形斑点会像一团团晕，不是丁达尔效应里的那种条带感。
   *
   * 位置与尺寸都是按「整条亮带（含 100% 半径处）都落在光柱内」定的：
   * 镜头端光柱只有 10.4% 高（29.8%~40.2%），越靠近镜头的亮带必须越扁越短，
   * 否则 clip-path 会切在还有亮度的地方，那道硬边就是「边缘突兀」的来源。
   * 所以越靠右的亮带 rx / ry 越小：26×15 → 24×14 → 20×11 → 14×8。
   */
  --b1-xf: .10; --b1-y: -.22;
  --b2-xf: .32; --b2-y: -.10;
  --b3-xf: .55; --b3-y: .00;
  --b4-xf: .76; --b4-y: -.04;

  --b1-m: calc(var(--bm) + var(--bd) * var(--b1-f));
  --b1-h: calc(var(--hl) + var(--hd) * var(--b1-f));
  --b2-m: calc(var(--bm) + var(--bd) * var(--b2-f));
  --b2-h: calc(var(--hl) + var(--hd) * var(--b2-f));
  --b3-m: calc(var(--bm) + var(--bd) * var(--b3-f));
  --b3-h: calc(var(--hl) + var(--hd) * var(--b3-f));
  --b4-m: calc(var(--bm) + var(--bd) * var(--b4-f));
  --b4-h: calc(var(--hl) + var(--hd) * var(--b4-f));

  --b1-x: calc(var(--beam-x-end) * var(--b1-xf));
  --b2-x: calc(var(--beam-x-end) * var(--b2-xf));
  --b3-x: calc(var(--beam-x-end) * var(--b3-xf));
  --b4-x: calc(var(--beam-x-end) * var(--b4-xf));

  --b1-cy: calc(var(--b1-m) + var(--b1-h) * var(--b1-y));
  --b2-cy: calc(var(--b2-m) + var(--b2-h) * var(--b2-y));
  --b3-cy: calc(var(--b3-m) + var(--b3-h) * var(--b3-y));
  --b4-cy: calc(var(--b4-m) + var(--b4-h) * var(--b4-y));

  /*
   * 每个亮带用五段衰减，而不是「中心高、到 72% 骤降为 0」的两段式。
   * 两段式的线性斜坡在收尾处斜率突变，会产生马赫带——看上去就是一圈明显的边。
   * 下面这组近似高斯：0 → .82 → .52 → .22 → 0，两端都是平缓收口。
   *
   * 强度：光柱本体把暗部从 29 抬到 142，亮带要在这个基础上拉出可见的差，
   * alpha 低于 .3 基本察觉不到（早先给到 .13~.20，实测等于没做）。
   */
  background:
    radial-gradient(26% 15% at var(--b1-x) var(--b1-cy),
      rgba(255, 246, 220, calc(.46 * var(--beam-strength))) 0%,
      rgba(255, 246, 220, calc(.38 * var(--beam-strength))) 22%,
      rgba(255, 246, 220, calc(.24 * var(--beam-strength))) 45%,
      rgba(255, 246, 220, calc(.10 * var(--beam-strength))) 68%,
      rgba(255, 246, 220, 0) 100%),
    radial-gradient(24% 14% at var(--b2-x) var(--b2-cy),
      rgba(255, 246, 220, calc(.38 * var(--beam-strength))) 0%,
      rgba(255, 246, 220, calc(.31 * var(--beam-strength))) 22%,
      rgba(255, 246, 220, calc(.20 * var(--beam-strength))) 45%,
      rgba(255, 246, 220, calc(.08 * var(--beam-strength))) 68%,
      rgba(255, 246, 220, 0) 100%),
    radial-gradient(20% 11% at var(--b3-x) var(--b3-cy),
      rgba(255, 246, 220, calc(.44 * var(--beam-strength))) 0%,
      rgba(255, 246, 220, calc(.36 * var(--beam-strength))) 22%,
      rgba(255, 246, 220, calc(.23 * var(--beam-strength))) 45%,
      rgba(255, 246, 220, calc(.10 * var(--beam-strength))) 68%,
      rgba(255, 246, 220, 0) 100%),
    radial-gradient(14% 8% at var(--b4-x) var(--b4-cy),
      rgba(255, 246, 220, calc(.34 * var(--beam-strength))) 0%,
      rgba(255, 246, 220, calc(.28 * var(--beam-strength))) 22%,
      rgba(255, 246, 220, calc(.18 * var(--beam-strength))) 45%,
      rgba(255, 246, 220, calc(.07 * var(--beam-strength))) 68%,
      rgba(255, 246, 220, 0) 100%);
}
.has-js .proj__beam-flow { animation: beam-flow 18s ease-in-out infinite alternate; }
/*
 * 用 alternate 来回摆而不是循环平移：亮带不是无缝贴图，
 * 单向循环一定会在回卷的那一帧「跳」一下。来回摆没有这个接缝。
 *
 * 幅度与时长是按「看得出来」定的：-14% 在 1425px 宽下约 200px 位移，
 * 18 秒走完约 11px/秒，是能察觉的缓慢漂移。
 * 早先给的是 -5% / 34 秒（约 2px/秒），实测确认等于静止。
 */
@keyframes beam-flow {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-14%, 2.6%, 0); }
}

/* ── 7.3 光落在字上 ────────────────────────────────────────────────────── */

/*
 * 让首屏标题看起来是被那束光照亮的。
 *
 * 做法是把一条暖色渐变用 background-clip: text 裁进字形里，渐变的位置引用
 * --lens-x（也就是光柱近端的位置）。于是光柱随窗口移动时，
 * 字上「被照亮的那一段」跟着移动 —— 光与字共用同一套几何，
 * 不是两个各自为政的装饰。
 *
 * 渐变方向与光柱一致：越靠镜头越亮越白，越远越偏暗偏暖。
 *
 * 对比度是要守住的：标题背后是光柱抬亮过的区域（亮度约 0.07~0.11），
 * 所以渐变最暗的一端也压在 L≈0.76 以上，实测对比度 5.7:1 起步，
 * 不影响阅读。想再戏剧化一点可以往下压，但要同步复核对比度。
 *
 * 整块包在 @supports 里：background-clip: text 不被支持时，
 * 会退回上面写好的实心颜色，而不是变成一片透明的字。
 */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .hero__title,
  .hero__title em,
  .hero__hook {
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
  .hero__title {
    background-image: linear-gradient(94deg,
      #EDE1C6 0%,
      #F6EBD4 calc(var(--lens-x) * .20),
      #FCF4E2 calc(var(--lens-x) * .45),
      #FFFCF3 calc(var(--lens-x) * .70));
  }
  /* 关键词那一行用更暖的金调，仍然是被光照亮的那一段最亮 */
  .hero__title em {
    background-image: linear-gradient(94deg,
      #E9CE9C 0%,
      #F3DCAE calc(var(--lens-x) * .20),
      #FBEBC8 calc(var(--lens-x) * .45),
      #FFFAE6 calc(var(--lens-x) * .70));
  }
  /* 承诺行更克制：它字号小，明暗差大了会伤可读性 */
  .hero__hook {
    background-image: linear-gradient(94deg,
      #D8CCB6 0%,
      #E9DDC6 calc(var(--lens-x) * .20),
      #F7EDDC calc(var(--lens-x) * .45),
      #FFF9EE calc(var(--lens-x) * .70));
  }
}

/*
 * 字周围的暖色光晕，模拟光打在字上之后的散射。
 * 用 drop-shadow 而不是 text-shadow：前者作用于裁剪后的字形轮廓，
 * 与 background-clip: text 配合不会出现「阴影盖在渐变字上」的糊感。
 */
.hero__title {
  filter: drop-shadow(0 0 30px rgba(255, 220, 160, .26));
}

/*
 * 入场动画的兜底：3.2 秒后（由 header 内联脚本加 .hero-settled）把首屏内容强制显示。
 *
 * 防的是一种罕见但后果严重的组合：has-js 已经打上（初始隐藏生效），
 * 但 CSS 动画因故没跑（极端省流设置、某些阅读模式、扩展干预），
 * 结果首屏文字永久不可见。正常跑完时这条不产生任何视觉变化。
 *
 * 注意 .hero__scroll 不重置 transform —— 它的基础值是 translateX(-50%)，重置会跑偏。
 */
.hero-settled .hero__kicker,
.hero-settled .hero__line,
.hero-settled .hero__lead,
.hero-settled .hero__hook,
.hero-settled .hero__facts,
.hero-settled .hero .btn-row,
.hero-settled .hero .stamp-in {
  animation: none !important;
  opacity: 1 !important;
  clip-path: none !important;
  transform: none !important;
}
.hero-settled .hero__scroll {
  animation: none !important;
  opacity: 1 !important;
}
.hero-settled .hero__hook::before,
.hero-settled .hero__facts::before {
  animation: none !important;
  opacity: 1 !important;
  transform: none !important;
}

/* ── 8. 卡片 ───────────────────────────────────────────────────────────── */

.grid { display: grid; gap: 1.6rem; }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.card {
  background: var(--paper-lift);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.9rem 1.7rem;
  transition: transform .3s var(--ease), box-shadow .3s var(--ease), border-color .3s var(--ease);
}
.card--hover:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow);
  border-color: var(--paper-sink);
}
.card__title { font-size: var(--fs-h3); margin-bottom: .5rem; }
.card__text { color: var(--ink-soft); font-size: .95rem; }

/* 三板块：内容策划 / 影像采集 / 成片交付 */
.pillar__no {
  font-family: var(--font-serif);
  font-size: .9rem;
  letter-spacing: .2em;
  color: var(--gold-ink);
  display: block;
  margin-bottom: .8rem;
}

/* 产品卡 */
.product-card {
  display: flex;
  flex-direction: column;
  background: var(--paper-lift);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.7rem 1.5rem;
  position: relative;
  transition: transform .3s var(--ease), box-shadow .3s var(--ease), border-color .3s var(--ease);
}
.product-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow);
  border-color: var(--gold);
}
.product-card--featured { border-color: var(--gold); }
.product-card__ribbon {
  position: absolute;
  top: -1px;
  right: 1.2rem;
  background: var(--gold);
  color: #FFFDF8;
  font-size: var(--fs-tiny);
  letter-spacing: .1em;
  padding: .18em .7em;
}
.product-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .6rem;
  margin-bottom: 1rem;
}
.product-card__name {
  font-family: var(--font-serif);
  font-size: 1.22rem;
  font-weight: 600;
  margin: 0;
}
.product-card__price {
  font-family: var(--font-serif);
  font-size: 1.85rem;
  color: var(--ink);
  line-height: 1.2;
  margin-bottom: .3rem;
}
.product-card__price small {
  font-size: .82rem;
  font-family: var(--font-sans);
  color: var(--ink-faint);
  margin-left: .35em;
}
.product-card__note {
  font-size: var(--fs-tiny);
  color: var(--danger);
  margin-bottom: .7rem;
}
.product-card__format {
  font-size: .92rem;
  color: var(--gold-ink);
  margin-bottom: 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px dashed var(--line);
}
.product-card__list {
  font-size: .9rem;
  color: var(--ink-soft);
  flex: 1;
}
.product-card__list li {
  padding-left: 1.15em;
  position: relative;
  margin-bottom: .45em;
  line-height: 1.7;
}
.product-card__list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .72em;
  width: 6px;
  height: 1px;
  background: var(--gold);
}
.product-card__foot {
  margin-top: 1.4rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--line-soft);
  font-size: var(--fs-tiny);
  color: var(--ink-faint);
}

/* 案例卡 */
.case-card {
  display: flex;
  flex-direction: column;
  background: var(--paper-lift);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .3s var(--ease), box-shadow .3s var(--ease);
}
.case-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.case-card__media {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--paper-sink);
  overflow: hidden;
}
.case-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .6s var(--ease);
}
.case-card:hover .case-card__media img { transform: scale(1.04); }
.case-card__stamp {
  position: absolute;
  right: 10px;
  bottom: 10px;
  width: 52px;
  height: 52px;
  color: rgba(245, 240, 230, .9);
  opacity: .88;
}
.case-card__body { padding: 1.3rem 1.4rem 1.5rem; flex: 1; display: flex; flex-direction: column; }
.case-card__cat {
  font-size: var(--fs-tiny);
  letter-spacing: .14em;
  color: var(--gold-ink);
  margin-bottom: .55rem;
}
.case-card__title {
  font-family: var(--font-serif);
  font-size: 1.1rem;
  margin: 0 0 .6rem;
  line-height: 1.5;
}
.case-card__meta {
  font-size: var(--fs-tiny);
  color: var(--ink-faint);
  margin-top: auto;
  padding-top: .9rem;
  display: flex;
  gap: .8rem;
  flex-wrap: wrap;
}

/* 案例封面缺失时的占位 */
.media-placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  gap: .6rem;
  color: var(--ink-faint);
  background:
    repeating-linear-gradient(45deg, var(--paper-deep) 0 12px, var(--paper-sink) 12px 24px);
  font-size: var(--fs-tiny);
  letter-spacing: .16em;
  text-align: center;
  padding: 1rem;
}

/* ── 9. 空状态 ─────────────────────────────────────────────────────────── */

.empty-state {
  border: 1px dashed var(--line);
  border-radius: var(--radius);
  background: var(--paper-lift);
  padding: 2.6rem 1.8rem;
  text-align: center;
}
.empty-state__title {
  font-family: var(--font-serif);
  font-size: 1.2rem;
  margin-bottom: .6rem;
}
.empty-state__text {
  color: var(--ink-soft);
  font-size: .95rem;
  max-width: 34em;
  margin: 0 auto 1.6rem;
}
.empty-state .postmark-badge { margin: 0 auto 1.2rem; }

/* ── 10. 流程时间轴 ────────────────────────────────────────────────────── */

.sop-stage {
  font-size: var(--fs-tiny);
  letter-spacing: .18em;
  color: var(--gold-ink);
  padding: .3em 0;
  border-bottom: 1px solid var(--line);
  margin: 2.2rem 0 1.4rem;
}
.sop-stage:first-of-type { margin-top: 0; }

.timeline { position: relative; }
.timeline::before {
  content: '';
  position: absolute;
  left: 21px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: var(--line);
}
.sop-list { display: grid; gap: 1.5rem; }
.sop-item {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 1.3rem;
  align-items: start;
}
.sop-item__no {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--paper);
  border: 1px solid var(--gold);
  color: var(--gold-ink);
  font-family: var(--font-serif);
  font-size: .9rem;
  position: relative;
  z-index: 1;
}
.sop-item__head {
  display: flex;
  align-items: baseline;
  gap: .8rem;
  flex-wrap: wrap;
  margin-bottom: .25rem;
}
.sop-item__title { font-family: var(--font-serif); font-size: 1.08rem; font-weight: 600; }
.sop-item__days {
  font-size: var(--fs-tiny);
  color: var(--ink-faint);
  letter-spacing: .06em;
}
.sop-item__text { color: var(--ink-soft); font-size: .93rem; }

/* 情感四幕 */
.acts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1.1rem; }
.act {
  border-top: 2px solid var(--gold);
  padding-top: 1.1rem;
}
.act__no { font-size: var(--fs-tiny); letter-spacing: .18em; color: var(--ink-faint); }
.act__name {
  font-family: var(--font-serif);
  font-size: 1.35rem;
  margin: .25rem 0 .5rem;
}
.act__text { font-size: .9rem; color: var(--ink-soft); }

/* ── 11. 数字与团队 ───────────────────────────────────────────────────── */

.stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1.4rem;
}
.stat { text-align: center; }
.stat__num {
  font-family: var(--font-serif);
  font-size: clamp(2rem, 4vw, 2.9rem);
  line-height: 1.1;
  color: var(--gold);
}
.section--ink .stat__num { color: var(--gold); }
.stat__label {
  font-size: var(--fs-small);
  color: var(--ink-soft);
  letter-spacing: .06em;
}
.section--ink .stat__label { color: #CFC2AE; }

.team-list { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); }
.team-row {
  display: grid;
  grid-template-columns: 132px 96px minmax(0, 1fr);
  gap: 1.2rem;
  background: var(--paper-lift);
  padding: 1.05rem 1.3rem;
  align-items: baseline;
}
.team-row__name { font-family: var(--font-serif); font-size: 1.02rem; }
.team-row__count { color: var(--gold-ink); font-size: .95rem; letter-spacing: .04em; }
.team-row__detail { color: var(--ink-soft); font-size: .9rem; }

/* ── 12. 人群与场景 ───────────────────────────────────────────────────── */

.audience {
  border-left: 2px solid var(--line);
  padding-left: 1.3rem;
  transition: border-color .3s var(--ease);
}
.audience:hover { border-left-color: var(--gold); }
.audience__name { font-family: var(--font-serif); font-size: 1.08rem; margin-bottom: .35rem; }
.audience__who { font-size: var(--fs-tiny); color: var(--ink-faint); margin-bottom: .6rem; letter-spacing: .06em; }
.audience__quote {
  font-family: var(--font-serif);
  font-size: .95rem;
  color: var(--gold-ink);
  margin-top: .8rem;
}

.scene-tags { display: flex; flex-wrap: wrap; gap: .6rem; margin-top: 1.6rem; }

/* ── 13. 价格对照表 ───────────────────────────────────────────────────── */

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.price-table {
  width: 100%;
  min-width: 720px;
  border-collapse: collapse;
  font-size: .92rem;
  background: var(--paper-lift);
}
.price-table th,
.price-table td {
  border: 1px solid var(--line);
  padding: .95rem 1rem;
  text-align: left;
  vertical-align: top;
}
.price-table thead th {
  background: var(--paper-deep);
  font-family: var(--font-serif);
  font-weight: 600;
  font-size: .95rem;
  letter-spacing: .04em;
  white-space: nowrap;
}
.price-table tbody th {
  background: var(--paper-deep);
  font-weight: 400;
  color: var(--ink-soft);
  font-size: var(--fs-small);
  white-space: nowrap;
  width: 108px;
}
.price-table .is-price {
  font-family: var(--font-serif);
  font-size: 1.2rem;
  white-space: nowrap;
}
.price-table tr.is-recommended td,
.price-table tr.is-recommended th { background: #FBF4E6; }
.price-table tr.is-recommended tbody { background: #FBF4E6; }

/* ── 14. FAQ ───────────────────────────────────────────────────────────── */

.faq-list { border-top: 1px solid var(--line); }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item__q {
  width: 100%;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.2rem;
  background: none;
  border: 0;
  padding: 1.35rem .2rem;
  cursor: pointer;
  text-align: left;
  font-family: var(--font-serif);
  font-size: 1.06rem;
  color: var(--ink);
  transition: color .2s var(--ease);
}
.faq-item__q:hover { color: var(--gold-ink); }
.faq-item__icon {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  margin-top: .48em;
  position: relative;
}
.faq-item__icon::before,
.faq-item__icon::after {
  content: '';
  position: absolute;
  background: var(--gold);
  transition: transform .3s var(--ease), opacity .3s var(--ease);
}
.faq-item__icon::before { left: 0; right: 0; top: 7.5px; height: 1px; }
.faq-item__icon::after  { top: 0; bottom: 0; left: 7.5px; width: 1px; }
.faq-item.is-open .faq-item__icon::after { transform: scaleY(0); opacity: 0; }

/* 折叠态同样只在 JS 可用时生效，避免无脚本时答案被永久藏起来 */
.faq-item__a {
  overflow: hidden;
  transition: height .35s var(--ease);
}
.has-js .faq-item__a { height: 0; }
.has-js.js-fallback .faq-item__a { height: auto !important; }
.faq-item__a-inner {
  padding: 0 2.6rem 1.5rem .2rem;
  color: var(--ink-soft);
  font-size: .95rem;
}

/*
 * 全量问答页（faq.php）。
 * 语义上每个问题是一个 <h2>（有利于 AI 与搜索引擎识别问答结构），
 * 外观则要与首页那份折叠列表完全一致，所以把 h2 的默认边距与字号压掉。
 */
.faq-list--all { list-style: none; margin: 0; padding: 0; }
.faq-item__heading { margin: 0; font-size: 1rem; font-weight: 400; }

/* ── 15. 表单 ──────────────────────────────────────────────────────────── */

.form { display: grid; gap: 1.15rem; }
.form__row { display: grid; gap: 1.15rem; }
.form__row--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.field { display: flex; flex-direction: column; gap: .45rem; }
.field__label {
  font-size: var(--fs-small);
  color: var(--ink-soft);
  letter-spacing: .04em;
}
.field__label .req { color: var(--danger); margin-left: .2em; }
.field__hint { font-size: var(--fs-tiny); color: var(--ink-faint); }

.input, .textarea, .select {
  width: 100%;
  font: inherit;
  font-size: .95rem;
  color: var(--ink);
  background: var(--paper-lift);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: .72em .9em;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(184, 134, 59, .13);
}
.textarea { min-height: 130px; resize: vertical; line-height: 1.7; }
.select { appearance: none; background-image: none; cursor: pointer; }

.field.has-error .input,
.field.has-error .textarea,
.field.has-error .select { border-color: var(--danger); }
.field__error { font-size: var(--fs-tiny); color: var(--danger); }

.alert {
  border-radius: var(--radius);
  padding: 1rem 1.2rem;
  font-size: .93rem;
  margin-bottom: 1.6rem;
}
.alert--ok   { background: #EDF3EC; border: 1px solid #C6D8C4; color: #3B5A3B; }
.alert--err  { background: var(--danger-bg); border: 1px solid #E3C4BE; color: #7E332B; }

/* 联系方式列表 */
.contact-list { display: grid; gap: 1.1rem; }
.contact-item { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: 1rem; align-items: baseline; }
.contact-item__label { font-size: var(--fs-small); color: var(--ink-faint); letter-spacing: .08em; }
.contact-item__value { font-size: .98rem; word-break: break-all; }
.contact-item__value .placeholder-note {
  color: var(--danger);
  font-size: var(--fs-tiny);
  display: block;
  margin-top: .15rem;
}

/* ── 16. 子页头 ────────────────────────────────────────────────────────── */

.page-hero {
  padding: clamp(2.8rem, 6vw, 4.6rem) 0 clamp(2rem, 4vw, 3rem);
  border-bottom: 1px solid var(--line);
  background: var(--paper-deep);
}
.page-hero__title { font-size: clamp(1.8rem, 4vw, 2.7rem); margin-bottom: .7rem; }
.page-hero__lead { color: var(--ink-soft); max-width: 46em; font-size: 1.03rem; }

.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  gap: .55rem;
  font-size: var(--fs-tiny);
  color: var(--ink-faint);
  margin-bottom: 1.3rem;
}
.breadcrumb a:hover { color: var(--gold-ink); }
.breadcrumb span::before { content: '/'; margin-right: .55rem; color: var(--line); }

/* 影像版子页头：文字压在照片上，比纯色底更有分量 */
.page-hero--media {
  position: relative;
  isolation: isolate;
  display: grid;
  align-items: end;
  min-height: clamp(320px, 44vh, 460px);
  padding: clamp(3rem, 6vw, 4.4rem) 0 clamp(2.2rem, 4vw, 3rem);
  background: #1B1510;
  color: var(--paper-lift);
  border-bottom: 0;
}
.page-hero__media { position: absolute; inset: 0; z-index: -2; }
.page-hero__media img { width: 100%; height: 100%; object-fit: cover; }
.page-hero--media::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgba(18, 13, 9, .52) 0%, rgba(18, 13, 9, .86) 100%);
}
.page-hero--media .page-hero__title { color: var(--paper-lift); }
.page-hero--media .page-hero__lead { color: #CFC2AE; }
.page-hero--media .breadcrumb,
.page-hero--media .breadcrumb a { color: #9C8F7C; }
.page-hero--media .breadcrumb span::before { color: rgba(245, 240, 230, .3); }
.page-hero--media .eyebrow { color: var(--gold); }

/* ── 17. CTA 区块 ──────────────────────────────────────────────────────── */

.cta-band {
  background: var(--ink);
  color: var(--paper);
  padding: clamp(3rem, 6vw, 4.6rem) 0;
  text-align: center;
  position: relative;
  overflow: hidden;
}
.cta-band__mark {
  width: 72px;
  height: 72px;
  color: var(--gold);
  margin: 0 auto 1.6rem;
  opacity: .9;
}
.cta-band__title {
  font-family: var(--font-serif);
  font-size: clamp(1.5rem, 3.4vw, 2.15rem);
  color: var(--paper-lift);
  margin-bottom: .7rem;
}
.cta-band__text { color: #CFC2AE; max-width: 36em; margin: 0 auto 2rem; }
.cta-band .btn-row { justify-content: center; }

/* ── 18. 页脚 ──────────────────────────────────────────────────────────── */

.site-footer {
  background: var(--ink);
  color: #B9AB98;
  padding: clamp(2.8rem, 5vw, 4rem) 0 1.8rem;
  font-size: .9rem;
}
.site-footer a:hover { color: var(--gold); }
.footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) repeat(2, minmax(0, 1fr));
  gap: 2.6rem;
  padding-bottom: 2.4rem;
  border-bottom: 1px solid rgba(245, 240, 230, .13);
}
.footer__brand { display: flex; align-items: center; gap: .8rem; margin-bottom: 1.1rem; }
.footer__brand .brand__cn { color: var(--paper-lift); letter-spacing: .16em; font-family: var(--font-serif); font-size: 1.16rem; }
.footer__brand .brand__en { color: #A99B87; font-size: .58rem; letter-spacing: .3em; text-transform: uppercase; }
.footer__brand .brand__mark { color: var(--gold); width: 40px; height: 40px; }
.footer__slogan {
  font-family: var(--font-serif);
  color: var(--paper-lift);
  font-size: 1.02rem;
  margin-bottom: .9rem;
  line-height: 1.7;
}
.footer__tags { color: #A99B87; font-size: var(--fs-tiny); letter-spacing: .1em; }
.footer__title {
  color: var(--paper-lift);
  font-family: var(--font-serif);
  font-size: .98rem;
  margin-bottom: 1.1rem;
  letter-spacing: .08em;
}
.footer__links { display: grid; gap: .65rem; }
.footer__bottom {
  padding-top: 1.6rem;
  display: flex;
  flex-wrap: wrap;
  gap: .8rem 1.6rem;
  justify-content: space-between;
  font-size: var(--fs-tiny);
  color: #A99B87;
}
.footer__bottom a { color: #A99B87; }

/* ── 19. 滚动渐显 ──────────────────────────────────────────────────────── */

/*
 * 初始隐藏状态只在 <html class="has-js"> 时生效（该 class 由 header 里的
 * 内联脚本在首次绘制前加上）。这样 JS 被禁用或加载失败时，内容依然是可见的，
 * 不会出现整页空白的灾难性退化。
 * .js-fallback 是内联脚本的兜底：主脚本 3 秒内没接管就强制显示全部内容。
 */

.reveal {
  transition: opacity .7s var(--ease), transform .7s var(--ease);
}
.has-js .reveal {
  opacity: 0;
  transform: translateY(22px);
}
.has-js .reveal.is-visible {
  opacity: 1;
  transform: none;
}
.has-js.js-fallback .reveal {
  opacity: 1 !important;
  transform: none !important;
}

/* 返回顶部 */
.to-top {
  position: fixed;
  right: 20px;
  bottom: 20px;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  background: var(--paper-lift);
  border: 1px solid var(--line);
  border-radius: 50%;
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity .3s var(--ease), transform .3s var(--ease), visibility .3s;
  z-index: 50;
  color: var(--gold-ink);
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: none; }
.to-top:hover { background: var(--ink); color: var(--paper-lift); border-color: var(--ink); }

/* ── 20. 分页 ──────────────────────────────────────────────────────────── */

.pager {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: .5rem;
  margin-top: 2.8rem;
  flex-wrap: wrap;
}
.pager a, .pager span {
  min-width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  padding: 0 .7em;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: .9rem;
  background: var(--paper-lift);
  transition: background .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.pager a:hover { border-color: var(--gold); color: var(--gold-ink); }
.pager .is-current { background: var(--ink); color: var(--paper-lift); border-color: var(--ink); }
.pager .is-disabled { opacity: .4; }

/* ── 21. 筛选条 ────────────────────────────────────────────────────────── */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: .55rem;
  margin-bottom: 2.2rem;
  padding-bottom: 1.6rem;
  border-bottom: 1px solid var(--line);
}
.filter-chip {
  font-size: var(--fs-small);
  padding: .42em 1.05em;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--ink-soft);
  background: var(--paper-lift);
  transition: all .22s var(--ease);
}
.filter-chip:hover { border-color: var(--gold); color: var(--gold-ink); }
.filter-chip.is-active {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper-lift);
}
.filter-chip .count { opacity: .6; font-size: .85em; margin-left: .35em; }

/* ── 22. 案例详情 ──────────────────────────────────────────────────────── */

.case-hero__cover {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--paper-lift);
}
.case-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1.2rem;
  padding: 1.5rem 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin: 1.8rem 0 2.4rem;
}
.case-meta__label { font-size: var(--fs-tiny); color: var(--ink-faint); letter-spacing: .1em; margin-bottom: .2rem; }
.case-meta__value { font-size: .98rem; }

.prose { color: var(--ink-soft); font-size: 1rem; }
.prose h2 { font-size: 1.35rem; color: var(--ink); margin: 2.2rem 0 .8rem; }
.prose h3 { font-size: 1.12rem; color: var(--ink); margin: 1.8rem 0 .7rem; }
.prose ul { margin: 0 0 1.2rem; }
.prose li { padding-left: 1.2em; position: relative; margin-bottom: .5em; }
.prose li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .78em;
  width: 6px;
  height: 1px;
  background: var(--gold);
}
.prose img { border-radius: var(--radius); margin: 1.4rem 0; border: 1px solid var(--line); }

/* 案例图集 */
.gallery { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .9rem; margin-top: 1.6rem; }
.gallery__item {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--paper-deep);
}
.gallery__item img { width: 100%; height: 100%; object-fit: cover; }

/* ── 23. 视频外链 ──────────────────────────────────────────────────────── */

.video-frame {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--ink);
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--line);
}
.video-frame iframe { width: 100%; height: 100%; border: 0; display: block; }

/* ── 24. 选型建议 ──────────────────────────────────────────────────────── */

.pick-guide { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); }
.pick-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 1.4rem;
  background: var(--paper-lift);
  padding: 1.2rem 1.4rem;
}
.pick-row__if { font-size: .95rem; }
.pick-row__then { font-size: .95rem; color: var(--gold-ink); }

/* ── 25. 影像与编辑式版式 ─────────────────────────────────────────────── */

/*
 * 这一节是版面的主角。整站靠「浅色纸面」与「深色影像」交替出现来制造节奏：
 * 纸面段负责阅读，影像段负责情绪。所有照片都来自品牌方案自带的素材，
 * 深色、暖调、胶片质感，正好是 VI 里「胶片温度 · 老照片质感」要的东西。
 */

/*
 * 深色影像上下文。
 *
 * 只要容器的背景是照片或深棕（首屏、影像带、影像版子页头、深色章节），
 * 内部文字一律换成浅色系。这些容器自己就声明了上下文，标记里不必再挂类名——
 * 早期版本要求手写 .on-dark，结果影像带里的 .eyebrow 仍是深金色 #8A6023，
 * 压在深色照片上几乎看不见。
 *
 * 用 :is() 分组，权重取参数中最高者，足以压过基础组件样式。
 */
.hero,
.band,
.page-hero--media,
.section--ink,
.line-card,
.on-dark { color: var(--paper-lift); }

:is(.hero, .band, .page-hero--media, .section--ink, .line-card, .on-dark)
  :is(h1, h2, h3, h4, .section-title, .card__title, .band__quote) {
  color: var(--paper-lift);
}

:is(.hero, .band, .page-hero--media, .section--ink, .line-card, .on-dark)
  :is(p, .section-sub, .card__text, .act__text, .stat__label, .sop-item__text) {
  color: #C6B9A4;
}

:is(.hero, .band, .page-hero--media, .section--ink, .line-card, .on-dark)
  :is(.eyebrow) {
  color: var(--gold);
}

:is(.hero, .band, .page-hero--media, .section--ink, .line-card, .on-dark)
  :is(.band__cite, .act__no, .sop-item__days, .figure__caption, .field__hint) {
  color: #A99B87;
}

/* 深色底上的卡片与标签改用半透明描边，避免出现一块突兀的浅色方块 */
:is(.band, .section--ink, .on-dark, .hero) :is(.card) {
  background: rgba(245, 240, 230, .06);
  border-color: rgba(245, 240, 230, .16);
}
:is(.band, .section--ink, .on-dark, .hero) :is(.card--hover):hover {
  background: rgba(245, 240, 230, .1);
  border-color: rgba(184, 134, 59, .5);
}
:is(.band, .section--ink, .on-dark) :is(.tag) {
  background: rgba(245, 240, 230, .08);
  border-color: rgba(245, 240, 230, .2);
  color: #C6B9A4;
}
:is(.band, .section--ink, .on-dark) :is(.btn--ghost) {
  border-color: rgba(245, 240, 230, .5);
  color: var(--paper-lift);
}
:is(.band, .section--ink, .on-dark) :is(.btn--ghost):hover {
  background: var(--paper-lift);
  color: var(--ink);
  border-color: var(--paper-lift);
}
:is(.band, .section--ink, .on-dark) :is(.editorial-num) { color: rgba(245, 240, 230, .2); }

/* 深色底上的 .act 用浅色分隔线 */
:is(.band, .section--ink, .on-dark) :is(.act) { border-top-color: var(--gold); }
:is(.band, .section--ink, .on-dark) :is(.act__name) { color: var(--paper-lift); }

/* 深色底上的服务承诺清单 */
:is(.band, .section--ink, .on-dark) :is(.pledge) { color: #C6B9A4; }

/* 深色底上的数据条 */
:is(.band, .section--ink, .on-dark) :is(.chart-bars__value) { color: var(--paper-lift); }
:is(.band, .section--ink, .on-dark) :is(.chart-bars__label) {
  color: #A99B87;
  border-top-color: rgba(245, 240, 230, .18);
}

/*
 * 胶片颗粒：叠在深色影像上，去掉数码感。
 *
 * 这里刻意不去动子元素的 position / z-index —— 早期版本写过 `.grain > *`，
 * 结果把 `.hero__media`、`.hero__scroll` 的绝对定位一并覆盖成 relative，
 * 全出血图片直接塌掉（同权重、后定义者胜）。
 * 现在只靠层叠上下文分层：影像 -2、压层 -1、颗粒 0、正文按文档顺序在其上。
 * .grain 自身有 isolation:isolate，负 z-index 不会漏到元素背景之外。
 */
.grain { position: relative; isolation: isolate; }
.grain::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: .38;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* 通栏影像区块 */
.band {
  position: relative;
  isolation: isolate;
  display: grid;
  align-items: center;
  min-height: clamp(400px, 58vh, 620px);
  padding: clamp(3.6rem, 8vw, 6.4rem) 0;
  color: var(--paper-lift);
  overflow: hidden;
  background: #1B1510;
}
.band__media { position: absolute; inset: 0; z-index: -2; }
.band__media img { width: 100%; height: 100%; object-fit: cover; }
.band::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg, rgba(18, 13, 9, .78) 0%, rgba(18, 13, 9, .5) 40%, rgba(18, 13, 9, .8) 100%);
}
/* 文字偏左时，左侧再压暗一层 */
.band--left::after {
  background:
    linear-gradient(96deg, rgba(18, 13, 9, .93) 0%, rgba(18, 13, 9, .78) 40%, rgba(18, 13, 9, .22) 82%),
    linear-gradient(180deg, rgba(18, 13, 9, .3), rgba(18, 13, 9, .3));
}
.band--center::after {
  background: radial-gradient(120% 100% at 50% 50%, rgba(18, 13, 9, .58) 0%, rgba(18, 13, 9, .9) 100%);
}
.band__inner { width: 100%; }
.band--tall { min-height: clamp(480px, 72vh, 720px); }
.band--short { min-height: clamp(300px, 42vh, 420px); }

/* 影像区块里的引用句 */
.band__quote {
  font-family: var(--font-serif);
  font-size: clamp(1.4rem, 3.4vw, 2.3rem);
  line-height: 1.6;
  letter-spacing: .02em;
  color: var(--paper-lift);
  margin: 0 0 1.4rem;
  max-width: 26em;
  text-shadow: 0 2px 24px rgba(0, 0, 0, .5);
}
.band__cite {
  font-size: var(--fs-small);
  letter-spacing: .16em;
  color: #A99B87;
}

/* 左右分栏：一侧影像，一侧文字 */
.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.8rem, 5vw, 4.2rem);
  align-items: center;
}
.split--media-right .split__media { order: 2; }
.split--top { align-items: start; }

/* 带金色描边偏移的图片框，印刷品里常见的处理 */
.figure {
  position: relative;
  margin: 0;
}
.figure img {
  display: block;
  width: 100%;
  border-radius: var(--radius);
}
.figure--frame { outline: 1px solid rgba(184, 134, 59, .55); outline-offset: 12px; }
.figure--stamp { overflow: hidden; border-radius: var(--radius); }

.figure__caption {
  margin-top: 1.5rem;
  font-size: var(--fs-tiny);
  letter-spacing: .1em;
  color: var(--ink-faint);
}

/* 记忆邮戳盖在照片上 */
.stamp-mark {
  position: absolute;
  right: 20px;
  bottom: 20px;
  width: clamp(72px, 9vw, 104px);
  height: auto;
  color: rgba(240, 226, 200, .9);
  transform: rotate(-8deg);
  mix-blend-mode: screen;
  opacity: .92;
  pointer-events: none;
}

/* 胶片齿孔：上下两排圆孔，用来做影像区与纸面区的过渡 */
.sprockets {
  height: 18px;
  background-color: #17110D;
  background-image: radial-gradient(circle at 9px 9px, rgba(245, 240, 230, .26) 3.6px, transparent 4px);
  background-size: 26px 18px;
  background-repeat: repeat-x;
}

/* 横向胶片带：可滑动的照片条 */
.filmstrip { background: #17110D; padding-bottom: 12px; }
.filmstrip__track {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  padding: 12px 0;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(245, 240, 230, .3) transparent;
}
.filmstrip__track::-webkit-scrollbar { height: 6px; }
.filmstrip__track::-webkit-scrollbar-thumb { background: rgba(245, 240, 230, .28); border-radius: 3px; }
.filmstrip__item {
  flex: 0 0 auto;
  height: clamp(180px, 26vw, 250px);
  scroll-snap-align: center;
}
.filmstrip__item img {
  height: 100%;
  width: auto;
  display: block;
}
.filmstrip__caption {
  color: var(--ink-faint);
  font-size: var(--fs-tiny);
  letter-spacing: .1em;
  padding: 0 0 6px;
}

/* 影像卡片：图在上，文字在下 */
.photo-card {
  display: flex;
  flex-direction: column;
  background: var(--paper-lift);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .35s var(--ease), box-shadow .35s var(--ease), border-color .35s var(--ease);
}
.photo-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow);
  border-color: var(--paper-sink);
}
.photo-card__media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--paper-sink);
}
.photo-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .7s var(--ease);
}
.photo-card:hover .photo-card__media img { transform: scale(1.05); }
.photo-card__media--wide { aspect-ratio: 16 / 9; }
.photo-card__media--tall { aspect-ratio: 3 / 4; }
.photo-card__body { padding: 1.4rem 1.5rem 1.6rem; flex: 1; display: flex; flex-direction: column; gap: .5rem; }
.photo-card__title {
  font-family: var(--font-serif);
  font-size: 1.14rem;
  margin: 0;
  line-height: 1.5;
}
.photo-card__text { font-size: .92rem; color: var(--ink-soft); margin: 0; }
.photo-card__foot {
  margin-top: auto;
  padding-top: 1rem;
  font-size: var(--fs-tiny);
  letter-spacing: .12em;
  color: var(--gold-ink);
}

/* 图上的角标 */
.media-badge {
  position: absolute;
  left: 0;
  top: 1.1rem;
  background: rgba(24, 18, 14, .82);
  color: var(--paper-lift);
  font-size: var(--fs-tiny);
  letter-spacing: .14em;
  padding: .3em .9em;
  backdrop-filter: blur(4px);
}

/* 产线选择：两张大图并排 */
.line-picker { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.4rem; }
.line-card {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: clamp(320px, 42vw, 420px);
  padding: 1.8rem;
  border-radius: var(--radius);
  overflow: hidden;
  color: var(--paper-lift);
  background: #1B1510;
}
.line-card__media { position: absolute; inset: 0; z-index: -2; }
.line-card__media img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .8s var(--ease);
}
.line-card:hover .line-card__media img { transform: scale(1.04); }
.line-card::after {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(18, 13, 9, .18) 0%, rgba(18, 13, 9, .55) 46%, rgba(18, 13, 9, .93) 100%);
}
.line-card__label {
  font-size: var(--fs-tiny);
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .6rem;
}
.line-card__title {
  font-family: var(--font-serif);
  font-size: clamp(1.25rem, 2.2vw, 1.6rem);
  margin: 0 0 .7rem;
  color: var(--paper-lift);
}
.line-card__text { font-size: .93rem; color: #CFC2AE; margin: 0 0 1.2rem; }
.line-card__facts {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem 1.2rem;
  font-size: var(--fs-tiny);
  color: #A99B87;
  letter-spacing: .06em;
}

/* 数据条形图：用公开数据做的市场图 */
.chart-bars {
  display: flex;
  align-items: flex-end;
  gap: clamp(.8rem, 3vw, 2.4rem);
  height: clamp(200px, 30vw, 280px);
  padding-top: 1rem;
}
.chart-bars__item {
  flex: 1;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: .6rem;
  text-align: center;
}
.chart-bars__value {
  font-family: var(--font-serif);
  font-size: clamp(1rem, 1.8vw, 1.3rem);
  line-height: 1.2;
}
.chart-bars__bar {
  background: linear-gradient(180deg, var(--gold) 0%, rgba(184, 134, 59, .38) 100%);
  border-radius: 2px 2px 0 0;
  min-height: 6px;
}
.chart-bars__label {
  font-size: var(--fs-tiny);
  letter-spacing: .1em;
  color: var(--ink-faint);
  padding-top: .7rem;
  border-top: 1px solid var(--line);
}

/* 编辑式编号：大号衬线数字 */
.editorial-num {
  font-family: var(--font-serif);
  font-size: clamp(2.4rem, 5vw, 3.4rem);
  line-height: 1;
  color: var(--line);
  display: block;
  margin-bottom: -.3em;
}

/* 引文块 */
.pullquote {
  border-left: 2px solid var(--gold);
  padding: .2rem 0 .2rem 1.4rem;
  font-family: var(--font-serif);
  font-size: clamp(1.05rem, 2vw, 1.3rem);
  line-height: 1.75;
  color: var(--ink);
  margin: 0;
}

/* 影像上的文字容器：给足留白，避免贴着图片边缘 */
.band__content { max-width: 40em; }
.band__content--center { margin-inline: auto; text-align: center; }

/* 服务承诺清单 */
.pledge-list { display: grid; gap: .9rem; }
.pledge {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: .9rem;
  align-items: start;
  font-size: .95rem;
}
.pledge::before {
  content: '';
  width: 22px;
  height: 22px;
  margin-top: .28em;
  border: 1px solid var(--gold);
  border-radius: 50%;
  background:
    linear-gradient(45deg, transparent 44%, var(--gold) 44% 52%, transparent 52%) no-repeat 5px 7px / 12px 6px,
    linear-gradient(-45deg, transparent 44%, var(--gold) 44% 52%, transparent 52%) no-repeat 4px 6px / 6px 8px;
}

/* ── 26. 反垃圾：蜜罐字段 ──────────────────────────────────────────────── */

/* 真人看不见，也不会聚焦到；只有自动填表的机器人会把它填上 */
.hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ── 27. 响应式 ────────────────────────────────────────────────────────── */

@media (max-width: 1024px) {
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .acts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hero__inner { grid-template-columns: 1fr; }
  .hero__seal { display: none; }
  .nav__links { gap: 1.3rem; }
  .split { gap: 2.4rem; }
  .editorial-num { font-size: 2.6rem; }
}

@media (max-width: 860px) {
  .nav__toggle { display: block; margin-left: auto; }
  .nav__links {
    position: fixed;
    inset: 74px 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--paper-lift);
    border-bottom: 1px solid var(--line);
    box-shadow: var(--shadow);
    padding: .6rem 0 1.2rem;
    max-height: calc(100vh - 74px);
    overflow-y: auto;
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .25s var(--ease), transform .25s var(--ease), visibility .25s;
  }
  .nav__links.is-open { opacity: 1; visibility: visible; transform: none; }
  .nav__link {
    padding: .95rem 22px;
    border-bottom: 1px solid var(--line-soft);
    font-size: 1rem;
  }
  .nav__link.is-active { border-bottom-color: var(--line-soft); background: var(--paper-deep); }
  .nav .btn { margin: .8rem 22px 0; }

  .grid--3, .grid--2 { grid-template-columns: 1fr; }
  .footer__top { grid-template-columns: 1fr; gap: 2rem; }
  .team-row { grid-template-columns: 1fr; gap: .25rem; }
  .pick-row { grid-template-columns: 1fr; gap: .5rem; }
  .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .form__row--2 { grid-template-columns: 1fr; }
  .contact-item { grid-template-columns: 1fr; gap: .2rem; }

  /* 影像版式在窄屏收成单栏，影像统一放到文字上方 */
  .split { grid-template-columns: 1fr; gap: 2rem; }
  .split--media-right .split__media { order: 0; }
  .line-picker { grid-template-columns: 1fr; }
  .line-card { min-height: 300px; }
  .band { min-height: auto; }
  .band--tall { min-height: auto; }
  .band__quote { font-size: 1.35rem; }
  .figure--frame { outline-offset: 8px; }
  .pullquote { padding-left: 1.1rem; }

  /*
   * 窄屏（竖屏或小屏）时镜头被 cover 裁到画面外，光柱成为「从画面右侧外射入」：
   * 下面这组是 768×1024 下的参考值，仅在 JS 未运行时生效 ——
   * 正常情况由 main.js 的 initHeroBeam() 按真实尺寸实时覆盖。
   */
  .hero {
    --lens-x: 107%;
    --beam-strength: 0.85;
    --beam-far-top: 12%;
    --beam-far-bot: 61.9%;
    --beam-mid-far: 36.94%;
    --beam-half-far: 24.93%;
    --beam-x-end: 100%;
    --beam-k: .935;   /* 100 ÷ 107，把相对位置换算成插值系数 */
    --beam-softness: 14px;
  }
}

@media (max-width: 560px) {
  body { line-height: 1.8; }
  .wrap { padding-inline: 18px; }
  /* 桌面上用来控制断行的 <br>，窄屏下取消硬换行 */
  .only-desktop { display: none; }
  .grid--4, .acts, .stats { grid-template-columns: 1fr; }
  .stats { gap: 1.9rem; }
  .hero__facts { gap: 1.5rem 2rem; }
  .gallery { grid-template-columns: 1fr; }
  .card { padding: 1.5rem 1.25rem; }
  .sop-item { grid-template-columns: 36px minmax(0, 1fr); gap: 1rem; }
  .sop-item__no { width: 36px; height: 36px; font-size: .82rem; }
  .timeline::before { left: 17px; }
  .faq-item__a-inner { padding-right: 1rem; }
  .to-top { right: 14px; bottom: 14px; }

  /* 影像版式：窄屏进一步压低高度，避免图占满整屏 */
  .hero { min-height: 0; padding-top: 3rem; }
  .hero__title { font-size: clamp(1.7rem, 8vw, 2.2rem); }
  .band { padding: 2.8rem 0; }
  .band__quote { font-size: 1.2rem; }
  .chart-bars { height: 180px; gap: .6rem; }
  .filmstrip__item { height: 150px; }
  .stamp-mark { width: 64px; right: 12px; bottom: 12px; }
  .line-card { min-height: 260px; padding: 1.4rem; }
  .split { gap: 1.6rem; }
  .editorial-num { font-size: 2.2rem; }
  /* 窄屏画面面积小，浮尘同步减量，避免合成层数量无谓增加 */
  .beam-dust i:nth-child(n+12) { display: none; }
  /* 小屏上同样的像素位移看起来更明显，片门抖动收一档 */
  .hero { --weave-nudge: 0.5px; }
}

/* ── 28. 动效降级 ──────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    /* 必须同时清零延迟：入场动画用了 fill-mode: both，
       只压时长的话元素会在延迟期间停在「隐藏」那一帧，反而更难看清内容 */
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  /* 放在 .has-js 规则之后，同权重下后者生效 */
  .has-js .reveal { opacity: 1; transform: none; }
  .stamp-in { animation: none; }

  /* 纯装饰的循环动效直接关掉，而不是让它「瞬间跑完」 */
  .hero__media img,
  .beam-dust i,
  .proj__scratch,
  .proj__speck,
  .proj__beam,
  .proj__beam-flow,
  .has-js .hero.grain::before,
  .has-js .hero + .sprockets,
  .has-js .hero__scroll::after { animation: none !important; }
  .beam-dust { display: none; }
  /* 划痕与尘点没有动画时本就不该出现（基础状态就是 opacity: 0），这里只是写明意图 */
  .proj__scratch,
  .proj__speck { opacity: 0 !important; }
}
