/* 作者: 陈涛 (Alan Chen) <1315333@qq.com>
   05 幕「手机里的计划」样式（design-v2.md §二十四.2 契约）。

   契约约束：
     · 选择器**全部**以 .act05 作用域（.act05 / .act05-xxx），不写全局 id；
     · 禁止 position:fixed；禁止 backdrop-filter（全页只允许两处，都归页面：顶栏与手机壳）；
     · 每帧只动 transform / opacity / filter —— 所有随进度变化的量都由 act05.js 写行内样式，
       这里只负责静止形态。

   色板取页面的 CSS 变量；模块在 mount() 时按 palette 参数补一份兜底
   （--a05-gold 等），所以这份 CSS 在没有页面变量的 harness 里也成立。 */

/* ══════════════ 〇、兜底色（页面变量缺席时用，harness 需要） ══════════════ */
.act05, .act05-screen, .act05-lin {
  --a05-paper: var(--paper, #FBF8F3);
  --a05-ink:   var(--ink,   #0F1F3D);
  --a05-body:  var(--body,  #3B4A63);
  --a05-muted: var(--muted, #7C8AA5);
  --a05-gold:  var(--gold,  #F2C879);
  --a05-coral: var(--coral, #FF8A5B);
  --a05-teal:  var(--teal,  #2FA88C);
  --a05-serif: var(--serif, 'Instrument Serif', 'Serif Fallback', Georgia, serif);
  --a05-sans:  var(--sans,  'Inter', 'Sans Fallback', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif);
}

/* ══════════════ 一、舞台 ══════════════
   #a05-stage 铺满 .stage（页面给的舞台），绝对定位，不参与布局流。
   幕的可见性由页面的幕层门控（visibility）管，这里不写 display。 */
.act05#a05-stage {
  position: absolute; inset: 0; overflow: hidden;
  font-family: var(--a05-sans); pointer-events: none;
  contain: paint;
}

/* 两级层：外壳吃滚动视差，内胆吃指针视差 */
.act05 .act05-ly { position: absolute; inset: -7% -5%; will-change: transform; contain: paint; }
.act05 .act05-ly > .in { position: absolute; inset: 0; will-change: transform; }

/* ── 露台的灯：三盏，各自呼吸。只动 transform/opacity ── */
.act05 .act05-lamp {
  position: absolute; border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle,
    color-mix(in srgb, var(--a05-gold) 78%, transparent) 0%,
    color-mix(in srgb, var(--a05-gold) 34%, transparent) 30%,
    color-mix(in srgb, var(--a05-coral) 12%, transparent) 56%, transparent 74%);
  will-change: transform, opacity;
  animation: a05-breathe 6.4s ease-in-out infinite alternate;
}
@keyframes a05-breathe { from { transform: scale(1); opacity: .84 } to { transform: scale(1.045); opacity: 1 } }
.act05 #a05-lamp1 { left: 60%; top: 44%; width: 18vw; height: 18vw; opacity: .60; animation-duration: 7.2s }
.act05 #a05-lamp2 { left: 14%; top: 2%;  width: 34vw; height: 34vw; opacity: .24; animation-duration: 9.4s; animation-delay: -2.1s }
.act05 #a05-lamp3 { left: 2%;  top: 66%; width: 18vw; height: 18vw; opacity: .20; animation-duration: 8.1s; animation-delay: -3.6s }

/* ── 雾廊：黄昏的一层暖雾。opacity 由 JS 按进度写，静止态 0 ── */
.act05 .act05-mist {
  opacity: 0;
  background:
    radial-gradient(52% 16% at 22% 16%, rgba(255,247,235,.44) 0%, rgba(255,240,225,.19) 44%, transparent 78%),
    radial-gradient(38% 13% at 52% 13%, rgba(255,236,214,.30) 0%, transparent 76%),
    radial-gradient(22% 20% at 64% 40%, rgba(255,232,205,.24) 0%, transparent 74%);
}

/* ── 文字的底（§二十.1 / §二十二.7.5）：桌面只压左栏，不满宽 ── */
.act05 .act05-scrim {
  position: absolute; inset: 0 42% 0 0; pointer-events: none; opacity: 0;
  background: linear-gradient(96deg,
    rgba(15,31,61,.56) 0%, rgba(15,31,61,.38) 44%, rgba(15,31,61,.10) 78%, transparent 100%);
}

/* ── Lin 的落点锚：0×0、不可见、不吃指针；只为让 CSS 决定这一幕的顾问位置 ── */
.act05 .act05-linslot {
  /* 63% 那一版与主句/副句的盒子在同一条带上（1280 实测 sub×lin 相交 80×27）。
     压到 76%：顾问落在画面下方、手机左下角旁边，与左栏三行文字纵向彻底错开。
     横向的最后 16px 由 JS 量着手机的真实矩形再推（视口一变落点就跟着变）。
     §二十五：76% → 81%。76% 只让开了**头像**那一个矩形；顾问那一组真正占的是
     「气泡 + 标签 + 头像」的并集，气泡往左探到 x=364，正压在辅助行 #a05-aux 上
     （1728×962 实测：aux 墨迹 [121,737,527,756]，顾问组 [364,731,700,811]，间隙 −24.7）。
     81% = 779px，辅助行静息底沿 766 —— 让出 13px。JS 那一步（groupRect 的让位）
     只有在气泡此刻量得到时才补推，量不到时靠这一条兜底，两条是冗余不是重复。 */
  position: absolute; left: 41%; top: 81%; width: 0; height: 0;
  pointer-events: none; visibility: hidden;
}

/* ── 前景：暗角 + 2% 噪声（预烘 SVG，不用 backdrop-filter） ── */
.act05 .act05-fore {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(30% 30% at 86% 20%, rgba(242,200,121,.11) 0%, transparent 74%),
    radial-gradient(118% 90% at 50% 46%, transparent 44%, rgba(10,18,38,.48) 100%);
}
.act05 .act05-fore::after {
  content: ""; position: absolute; inset: 0; opacity: .035; mix-blend-mode: overlay;
  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='.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ══════════════ 二、文案（桌面左栏） ══════════════ */
.act05 .act05-copy {
  position: absolute; left: 7vw; top: 50%; transform: translateY(-50%);
  width: min(47vw, 780px); z-index: 2;
}
/* width:max-content —— 让盒子等于墨迹：780px 宽的块级标题盒会一路伸到画面中央，
   重叠检测按盒子算就会报「主句压住顾问卡」，而画面上两者相距 40px。
   盒子收成 max-content 之后，检测读到的就是真正的字。 */
.act05 .act05-h1 {
  margin: 0; width: max-content; max-width: min(47vw, 780px);
  font-family: var(--a05-serif); font-weight: 400; color: #fff;
  text-shadow: 0 2px 30px rgba(10,18,38,.55), 0 1px 3px rgba(10,18,38,.28);
  font-size: clamp(44px, 5.15vw, 92px); line-height: 1.02; letter-spacing: -.018em;
  white-space: nowrap;
}
.act05 .act05-h1 > span { display: block; opacity: 0; will-change: transform, opacity }
.act05 .act05-l2 { color: var(--a05-gold) }
.act05 .act05-sub {
  margin: 20px 0 0; font-family: var(--a05-serif); font-style: italic;
  font-size: clamp(19px, 1.62vw, 27px); line-height: 1.3; color: #fff; opacity: 0;
  text-shadow: 0 2px 26px rgba(10,18,38,.6), 0 1px 3px rgba(10,18,38,.3);
  will-change: transform, opacity;
}
/* 主句可以铺满左栏（它上方没有别的东西），副句与辅助行不行：Lin 的气泡从 40% 起，
   780px 宽的辅助行会一路顶到它身上。这两行单独收窄。 */
.act05 .act05-sub, .act05 .act05-aux { width: max-content; max-width: min(32vw, 520px) }
.act05 .act05-aux {
  margin: 16px 0 0; font-size: 15px; line-height: 1.5; color: rgba(255,255,255,.76); opacity: 0;
  text-shadow: 0 1px 18px rgba(10,18,38,.55); will-change: transform, opacity;
}

/* ══════════════ 三、手机屏里的收据 ══════════════
   屏的 CSS 盒在桌面是 282×592（手机壳 300×610 减去 9px 内嵌），
   手机端是 58vw×min(117.5vw,52dvh) 减去 7px —— 两档差着 25%。
   所以屏内**一切尺寸都写成 calc(N * var(--u))**，--u 由 JS 按实际屏盒算出来
   （k = min(w/282, h/592)），一套规则同时成立于两档，不必为手机再抄一份数字。
   文字另有下限（max(...px, ...)）：等比缩到 6.9px 就不是「看得懂」了。 */
.act05-screen.app {
  position: absolute; inset: 0; padding: 0; font-family: var(--a05-sans);
  font-size: calc(12 * var(--u, 1px)); color: var(--a05-body);
  opacity: 0; pointer-events: none; will-change: opacity;
}
.act05-screen.app * { pointer-events: inherit }

.act05-screen .act05-apphead { padding: calc(40 * var(--u)) calc(16 * var(--u)) calc(8 * var(--u)) }
.act05-screen .act05-apphead b {
  display: block; font-size: max(12px, calc(15 * var(--u))); font-weight: 500;
  color: var(--a05-ink); letter-spacing: -.01em;
}
.act05-screen .act05-apphead i {
  display: block; font-style: normal; color: var(--a05-muted);
  font-size: max(9.5px, calc(11 * var(--u))); margin-top: calc(3 * var(--u));
}
.act05-screen .act05-apphead i em { font-style: normal; color: var(--a05-coral) }

.act05-screen .act05-papercut {
  position: absolute; left: calc(10 * var(--u)); right: calc(10 * var(--u));
  top: calc(78 * var(--u)); bottom: calc(10 * var(--u)); overflow: hidden;
}
.act05-screen .act05-paper {
  position: absolute; left: 0; right: 0; top: 0; will-change: transform;
  background: linear-gradient(180deg, #fff 0%, #FEFCF8 100%);
  border-radius: 0 0 calc(3 * var(--u)) calc(3 * var(--u));
  box-shadow: 0 calc(14 * var(--u)) calc(30 * var(--u)) rgba(15,31,61,.16);
}
/* 纸顶的锯齿撕口 —— 收据的身份就在这一排齿上 */
.act05-screen .act05-paper::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: calc(7 * var(--u));
  background: repeating-linear-gradient(90deg, #fff 0 calc(5 * var(--u)), transparent calc(5 * var(--u)) calc(10 * var(--u)));
  -webkit-mask: radial-gradient(calc(4 * var(--u)) calc(5 * var(--u)) at calc(5 * var(--u)) 0, transparent 98%, #000) repeat-x 0 0 / calc(10 * var(--u)) calc(7 * var(--u));
          mask: radial-gradient(calc(4 * var(--u)) calc(5 * var(--u)) at calc(5 * var(--u)) 0, transparent 98%, #000) repeat-x 0 0 / calc(10 * var(--u)) calc(7 * var(--u));
}
/* 纸底的撕口：收据是一张**短条**，底下留白是它应有的样子，不是没画完。
   有了这排齿，短纸看起来是撕下来的一截，而不是「内容没加载完」。 */
.act05-screen .act05-paper::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: calc(-6 * var(--u));
  height: calc(6 * var(--u));
  background: linear-gradient(180deg, #FEFCF8, #FBF6EE);
  -webkit-mask: radial-gradient(calc(4 * var(--u)) calc(5 * var(--u)) at calc(5 * var(--u)) calc(6 * var(--u)), transparent 98%, #000) repeat-x 0 0 / calc(10 * var(--u)) calc(6 * var(--u));
          mask: radial-gradient(calc(4 * var(--u)) calc(5 * var(--u)) at calc(5 * var(--u)) calc(6 * var(--u)), transparent 98%, #000) repeat-x 0 0 / calc(10 * var(--u)) calc(6 * var(--u));
}
.act05-screen .act05-paperinner {
  position: relative; padding: calc(17 * var(--u)) calc(11 * var(--u)) calc(18 * var(--u));
  will-change: transform;
}
.act05-screen .act05-rhead {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 0 calc(2 * var(--u)) calc(11 * var(--u));
  border-bottom: 1px dashed rgba(15,31,61,.18);
}
.act05-screen .act05-rhead b {
  font-size: max(8.5px, calc(10 * var(--u))); font-weight: 500; letter-spacing: .13em;
  color: var(--a05-muted); text-transform: uppercase; white-space: nowrap;
}
.act05-screen .act05-rhead span {
  font-size: max(8.5px, calc(10 * var(--u))); letter-spacing: .06em; color: var(--a05-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ── 行：默认不在流里。「行是长出来的」而不是「先摆好再点亮」 ── */
.act05-screen .act05-row {
  display: none; align-items: center; gap: calc(8 * var(--u));
  /* 上下各 11u（原 7u）：五行只占了纸的一半、屏下方空出三分之一，看着像「没加载完」。
     行距是把纸撑长最便宜的手段 —— 21px 的缩略图也跟着不那么挤。 */
  padding: calc(11 * var(--u)) calc(2 * var(--u)); position: relative;
  border-bottom: 1px solid rgba(15,31,61,.055); will-change: transform, opacity;
}
.act05-screen .act05-row.on { display: flex }
.act05-screen .act05-row .th {
  width: calc(30 * var(--u)); height: calc(30 * var(--u)); flex: 0 0 calc(30 * var(--u));
  border-radius: calc(8 * var(--u)); overflow: hidden;
  /* 图没到位（还在懒加载 / 某一档素材 404，§十七.4.8 有前科）时，这里是一块
     纸色的空缩略图，而不是一个破图框。 */
  background: linear-gradient(150deg, #EFE7DA, #DCD2C2);
  box-shadow: 0 calc(2 * var(--u)) calc(6 * var(--u)) rgba(15,31,61,.14);
  will-change: transform; transition: transform .22s ease-out;
}
/* font-size:0 + color:transparent：alt 文案留在无障碍树里（读屏照读），但**不渲染**。
   缩略图只有 21–30px，图一 404 这一格就会挤出半行「Arrivals hall at Shang…」，
   整张收据当场变形 —— 实测 harness 里五行全是这样。 */
.act05-screen .act05-row .th img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  font-size: 0; color: transparent;
}
.act05-screen .act05-row .tm {
  font-size: max(8px, calc(9 * var(--u))); letter-spacing: .06em; color: var(--a05-muted);
  font-variant-numeric: tabular-nums; width: calc(32 * var(--u)); flex: 0 0 calc(32 * var(--u)); text-align: right;
}
.act05-screen .act05-row .k { flex: 1 1 auto; min-width: 0 }
.act05-screen .act05-row .k b {
  display: block; font-size: max(9.5px, calc(11.5 * var(--u))); font-weight: 500; color: var(--a05-ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.act05-screen .act05-row .k small {
  display: block; font-size: max(8px, calc(9.5 * var(--u))); color: var(--a05-muted); margin-top: calc(1 * var(--u));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 完成点：JS 会整条重写 transform，所以垂直居中不能用 translateY(-50%)
   —— 用 margin-top 让「居中」不占 transform，scale 才独占它。 */
.act05-screen .act05-row .ok {
  position: absolute; left: calc(-6 * var(--u)); top: 50%; margin-top: calc(-2 * var(--u));
  width: calc(4 * var(--u)); height: calc(4 * var(--u)); border-radius: 50%;
  background: var(--a05-teal); transform: scale(0); will-change: transform;
  box-shadow: 0 0 0 calc(3 * var(--u)) rgba(47,168,140,.18);
}
/* 打印头：落行时横扫一次的柔光。静置 opacity 0（不亮时不进墨迹盒） */
.act05-screen .act05-row .fx {
  position: absolute; left: calc(-4 * var(--u)); right: calc(-4 * var(--u)); top: 0; bottom: 0;
  pointer-events: none; opacity: 0; will-change: transform, opacity;
  background: linear-gradient(100deg, transparent 0%, rgba(242,200,121,.66) 46%, rgba(255,255,255,.9) 52%, transparent 78%);
}

/* 点睛动作全部走 CSS 动画：在页面的 scrub 渲染回调里创建 GSAP 补间会踩
   immediateRender 的坑（已被样机记录），class 一加一收就没有这个洞。 */
.act05-screen .act05-row.hit .fx { animation: a05-sweep .52s ease-out 1 }
.act05-screen .act05-row.hit .ok { animation: a05-pop .52s cubic-bezier(.34,1.56,.64,1) 1 }
/* 纸抖每落一行都要重放一次。重放不用「删 class → 读 offsetWidth 强制重排 → 再加」
   那一套（那是一次真实的 layout）：两个同效果的 class 交替，动画自然重启。 */
.act05-screen .act05-paperinner.hit  { animation: a05-jolt .42s cubic-bezier(.34,1.8,.64,1) 1 }
.act05-screen .act05-paperinner.hit2 { animation: a05-jolt2 .42s cubic-bezier(.34,1.8,.64,1) 1 }
@keyframes a05-sweep {
  0%   { transform: translateX(-108%); opacity: 0 }
  12%  { opacity: .95 }
  100% { transform: translateX(108%); opacity: 0 }
}
@keyframes a05-pop { from { transform: scale(0) } to { transform: scale(1) } }
@keyframes a05-jolt  { from { transform: translateY(calc(-3.2 * var(--u))) } to { transform: translateY(0) } }
@keyframes a05-jolt2 { from { transform: translateY(calc(-3.2 * var(--u))) } to { transform: translateY(0) } }

/* ── 总计与脚注：也进/出文档流，纸的底边跟着内容长 ── */
.act05-screen .act05-rtotal {
  display: none; align-items: center; justify-content: space-between;
  margin-top: calc(13 * var(--u)); padding: calc(13 * var(--u)) calc(2 * var(--u)) 0;
  border-top: 1px dashed rgba(15,31,61,.22); opacity: 0; will-change: transform, opacity;
}
.act05-screen .act05-rtotal.on { display: flex }
.act05-screen .act05-rtotal .lb {
  font-size: max(8.5px, calc(10 * var(--u))); letter-spacing: .12em; text-transform: uppercase;
  color: var(--a05-muted); white-space: nowrap;
}
.act05-screen .act05-rnote {
  display: none; margin-top: calc(6 * var(--u)); padding: 0 calc(2 * var(--u));
  font-size: max(7.5px, calc(9 * var(--u))); color: var(--a05-muted); opacity: 0; letter-spacing: .02em;
}
.act05-screen .act05-rnote.on { display: block }

/* ── 滚轮数字：一列 = 1em 高的窗口 + 一条 [0…9,0] 的字条 ──
   translateY = -(pos mod 10) em。字条末尾多补一个 "0"，pos 从 9.99 绕回 0 时
   窗口里前后是同一个字形，那一帧的跳变肉眼看不见。 */
.act05-screen .act05-odo {
  display: inline-flex; align-items: baseline; font-variant-numeric: tabular-nums;
  font-weight: 500; color: var(--a05-ink);
}
.act05-screen .act05-odo .cur, .act05-screen .act05-odo .sep { display: inline-block }
.act05-screen .act05-odo .col { display: inline-block; height: 1em; line-height: 1; overflow: hidden; vertical-align: baseline }
.act05-screen .act05-odo .col i { display: block; height: 1em; line-height: 1; font-style: normal; text-align: center }
.act05-screen .act05-odo .strip { display: block; will-change: transform, filter }
/* 前导零列不显示："$80" 不写成 "$0,080" */
.act05-screen .act05-odo .col.hid, .act05-screen .act05-odo .sep.hid { display: none }
.act05-screen .act05-row .act05-odo { font-size: max(9.5px, calc(12 * var(--u))) }
.act05-screen .act05-rtotal .act05-odo { font-size: max(15px, calc(22 * var(--u))); letter-spacing: -.01em }

/* ── 桌面微交互（§二十一.4）：悬停一行，缩略图抬一下、行底浮出一条金线 ── */
.act05-screen .act05-row.hov .th { transform: scale(1.08) }
.act05-screen .act05-row.hov::after {
  content: ""; position: absolute; left: calc(-2 * var(--u)); right: calc(-2 * var(--u)); bottom: -1px;
  height: 1px; background: var(--a05-gold); opacity: .85;
}

/* ══════════════ 四、共享元素 Lin 上的两个槽 ══════════════
   .act05-lin 这个 class 由 JS 在幕内加到 shared.lin 的元素上，dispose 时摘掉。
   页面自己的文字块被 .act05-lin-off 收起来（运行时打的标记，与页面结构无关）。 */
.act05-lin .act05-lin-off { display: none !important }
/* 「正在输入」的点与那一句话**叠在同一个网格格子里**：盒子按两者中较高的那个撑开，
   于是从点换成句子时卡片一个像素都不跳。
   上一版把句子做成 position:absolute —— 它不撑盒子，卡片按 22px 高的点定高，
   句子当场溢出卡片外（桌面实测三行字挂在卡片下面）。 */
.act05-lin .act05-lin-slot {
  flex: 1 1 auto; min-width: 0; display: grid;
  grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto;
  width: 238px; max-width: 100%; row-gap: 3px;
}
.act05-lin .act05-lin-name {
  grid-row: 1; font-size: 11px; font-weight: 500; color: var(--a05-ink); letter-spacing: .01em;
}
.act05-lin .act05-lin-name em { font-style: normal; color: var(--a05-teal); font-weight: 400 }
.act05-lin .act05-lin-dots {
  grid-row: 2; grid-column: 1; display: flex; gap: 4px; align-items: center; height: 22px;
}
.act05-lin .act05-lin-dots i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--a05-muted);
  animation: a05-typ 1.05s ease-in-out infinite; will-change: transform, opacity;
}
.act05-lin .act05-lin-dots i:nth-child(2) { animation-delay: .14s }
.act05-lin .act05-lin-dots i:nth-child(3) { animation-delay: .28s }
@keyframes a05-typ { 0%,60%,100% { transform: translateY(0); opacity: .42 } 30% { transform: translateY(-4px); opacity: 1 } }
.act05-lin .act05-lin-say {
  grid-row: 2; grid-column: 1; margin: 0; align-self: center;
  font-family: var(--a05-serif); font-style: italic; font-size: 16px; line-height: 1.32;
  color: var(--a05-ink); opacity: 0; transform-origin: 0 50%; will-change: transform, opacity;
}
/* 「正在输入 → 弹出」：两个状态由 JS 切 class，弹出那一下是 CSS 动画 */
.act05-lin.act05-said .act05-lin-dots { opacity: 0 }
.act05-lin.act05-said .act05-lin-say { opacity: 1 }
.act05-lin.act05-said.act05-pop .act05-lin-say { animation: a05-say .55s cubic-bezier(.34,1.56,.64,1) 1 }
@keyframes a05-say {
  from { opacity: 0; transform: translateY(7px) scale(.94) }
  to   { opacity: 1; transform: translateY(0) scale(1) }
}

/* ══════════════ 五、手机端（§十六.2 三槽 / §二十 层级） ══════════════
   顶槽 title：顶栏之下 → 26vh；中槽 media：26–70vh（手机②，页面拥有）；
   底槽 text：70–92vh（Lin 一行）。
   §二十.1「一屏只有一主一次一辅」：主 = 44px 主句；次 = 手机②；辅 = Lin 那一行。
   所以副句与辅助行在手机上不出现 —— 它们会让 Level 3 变成两行。 */
@media (max-width: 900px) {
  .act05 .act05-scrim {
    inset: 0 0 auto 0; height: 42svh;
    background: linear-gradient(180deg, rgba(15,31,61,.60) 0%, rgba(15,31,61,.38) 48%, transparent 100%);
  }
  /* 底槽也要一块底：Lin 那一行压在露台栏杆上，白字会糊 */
  .act05 .act05-scrim::after {
    content: ""; position: absolute; left: 0; right: 0; top: 42svh; height: 58svh;
    background: linear-gradient(180deg, transparent 0%, rgba(15,31,61,.30) 52%, rgba(15,31,61,.56) 100%);
  }
  /* top 原来是 8.2svh：390×844 上 = 69.2px，而正片的顶栏底沿在 65px
     （--hdrH 由页面主脚本量出来写进 :root，手机上按钮+安全区实测 65），
     §十六.3 要墨迹顶 ≥ 顶栏底 + 8 = 73 —— 主句整行压在顶栏底下 3.8px
     （实测 p 0.74–0.86 共 7 帧全红，motion_check 的 check6 也点了这一条）。
     取两者较大的一个：视口高时仍是 8.2svh 的呼吸感，顶栏一高就让开它。
     主句字号由 fitHeadline() 按「真实墨迹宽 + 手机②上沿」现算，顶槽起点下移
     之后它会自己收字号，不会因此撞到手机②。 */
  .act05 .act05-copy {
    left: 5.6vw; right: 5.6vw; width: auto;
    top: max(8.2svh, calc(var(--hdrH, 52px) + 20px)); transform: none;
  }
  /* 主句在手机上必须是**两行**（一句一行，§二十.1「主句 ≤ 2 行」）。
     nowrap 保证「一句一行」，字号由 act05.js 的 fitHeadline() 量出来写进 --a05-h1
     （真实墨迹宽 + 手机②上沿两个上限，30–44px，document.fonts.ready 后再算一次）。
     为什么不写死 44px：`font-display: optional` 之下有一半冷加载全程用兜底字体
     （§十七.4.2），两套字体宽度不同；五档手机行宽也不同。一旦某一档放不下，
     写死的那版就是两句各折两行、共四行，第三四行整个钻进手机②底下
     —— 用裸 Georgia 排版的那次实测就是这样，屏上只剩「Pric / incl」，
     §十六.5 的「标题 × 手机」当场红。
     兜底 36px 是「JS 没跑」时的保守值（两套字体在 360 档都放得下）。 */
  .act05 .act05-h1 {
    font-size: var(--a05-h1, 36px); line-height: 1.05; letter-spacing: -.015em;
    white-space: nowrap; width: auto; max-width: none;
  }
  /* 最后一道：缩到 30px 仍放不下时宁可裁掉行尾，也不许折行钻到手机底下
     （fitHeadline() 同时会往 __errs 记一条，不让它悄悄裁） */
  .act05 .act05-h1 > span { display: block; overflow: hidden; text-overflow: clip }
  .act05 .act05-sub, .act05 .act05-aux { display: none }
  /* 底槽（70–92svh）里的那一行：Lin。锚点放 76svh，卡片高 ≈ 26px，落在槽内。 */
  .act05 .act05-linslot { left: 5.6vw; top: 76svh }
  .act05 #a05-lamp1 { width: 74vw; height: 74vw }
  .act05 #a05-lamp2 { width: 38vw; height: 38vw }
  .act05 #a05-lamp3 { width: 46vw; height: 46vw }

  /* 216px 宽的屏里，时间列要吃掉 32*--u，代价是每一行的名字都被截成 "Hospit…"。
     名字比时刻重要（§二十.4「同一屏去冗余」）：手机上砍掉时间列。 */
  .act05-screen .act05-row .tm { display: none }
  .act05-screen .act05-rnote, .act05-screen .act05-rnote.on { display: none }

  /* Lin 在手机上是**一行小字**，不是卡片（§二十.4：同一屏最多一张卡，那张卡是手机②）。
     页面那个节点的玻璃底/边/影在幕内被这条规则收掉，dispose 时随 class 一起消失。 */
  .act05-lin {
    background: none !important; border: 0 !important; box-shadow: none !important;
    backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
    padding: 0 !important;
  }
  .act05-lin .act05-lin-slot { width: auto; row-gap: 0 }
  .act05-lin .act05-lin-name { display: none }
  .act05-lin .act05-lin-dots { grid-row: 1; height: 22px }
  .act05-lin .act05-lin-dots i { width: 5px; height: 5px; background: rgba(251,248,243,.72) }
  .act05-lin .act05-lin-say {
    grid-row: 1; font-size: 17px; font-style: normal; font-family: var(--a05-sans);
    color: color-mix(in srgb, var(--a05-paper) 88%, transparent);
    text-shadow: 0 1px 16px rgba(10,18,38,.6);
  }
}

/* ══════════════ 六、reduced-motion：静态可读 ══════════════
   不跑呼吸、不跑打字点、不跑点睛动作；终态由 JS 的 renderStatic() 落好。 */
@media (prefers-reduced-motion: reduce) {
  .act05 .act05-lamp, .act05-lin .act05-lin-dots i { animation: none }
  .act05-screen .act05-row.hit .fx, .act05-screen .act05-row.hit .ok,
  .act05-screen .act05-paperinner.hit, .act05-screen .act05-paperinner.hit2,
  .act05-lin.act05-pop .act05-lin-say { animation: none }
}
.act05-static .act05-lamp, .act05-lin.act05-static .act05-lin-dots i { animation: none }
