/* ================= 无忧传媒 · 工作作品板块 =================
   整体：黑色画廊 + 商业设计特辑。
   沿用网站现有的黑色背景、细线、字体与自定义光标，不引入任何依赖。

   几条不能违反的规矩（用户明确要求，也是这个板块的设计前提）：
   · 作品保持原色，**文字一律放在图片之外** —— 素材里已经有大量中文标题，
     再叠一层网页文字就糊了
   · 用大小、排列、留白建立节奏，**不要把 60 张图塞进同一种卡片**
   · 主次要清楚：主视觉最大最完整，上线系列突出，易拉宝与补充物料不能压过它们
   · 完整海报保持原比例；局部预览与完整查看必须区分（.wy-crop 那段就是干这个的）
   · 大图查看层 z-index 必须低于自定义光标（95），否则光标会被压在下面
   · 面向 HR 的页面上**不出现制作说明、开发说明、原始文件编号**

   尺寸集中在下面 :root 的变量里，调节奏改这里。 */

:root{
  --wy-rollup-h:66vh;                    /* 易拉宝高度上限（要求 60–68vh），宽度按原比例算 */
  --wy-launch-h:clamp(300px,42vh,520px); /* 上线主组统一高度 */
  --wy-ease:var(--ease-out);
}

.wy-section{
  position:relative;
  padding:0;
  background:var(--black-absolute);
  border-bottom:1px solid var(--border);
  z-index:4;
}
.wy-inner{max-width:1560px;margin:0 auto;padding:clamp(40px,6vh,90px) var(--gutter)}
/* 开场：**sticky 舞台**（一屏高）与"扩展段"（spacer）分开两个容器。
   ⚠️ 一定不要把案例的滚动距离折进开场里：实测那样两段会抢同一段滚动，
   案例在开场还没扩展完时就跑完了。 */
.wy-open-pin{
  position:sticky;
  top:0;
  display:flex;
  align-items:center;
  min-height:0;
  overflow:hidden;
}
.wy-open-spacer{pointer-events:none}
/* 案例在场时把开场的文案与海报收干净：它们就在同一屏的位置，
   不收会从案例层的空隙里透出来（截图里左边堆叠的文案就是这么来的）。
   用 visibility 收而不是 display:none —— 后者会让布局跳动。 */
.wy-section.is-case-live .wy-open-side,
.wy-section.is-case-live .wy-open-row{
  visibility:hidden;
}

/* ---------- 通用小件 ---------- */
.wy-kicker{
  margin:0 0 10px;
  font-family:var(--font-ui);
  font-size:11px;
  letter-spacing:.24em;
  color:var(--accent);
}
.wy-name{
  margin:0 0 14px;
  font-family:var(--font-display-cn,'Noto Serif SC',serif);
  font-weight:700;
  font-size:clamp(30px,3.4vw,54px);
  line-height:1.14;
  letter-spacing:-.02em;
  color:var(--text-primary);
}
.wy-sub{
  margin:0;
  font-size:13px;
  letter-spacing:.06em;
  color:var(--text-secondary);
}
.wy-sub + .wy-sub{margin-top:5px}
/* 职责概述：一行，替代原来那张重复的岗位表格 */
.wy-brief{
  margin:20px 0 0;
  max-width:34ch;
  font-size:14px;
  line-height:2;
  color:var(--text-secondary);
}

/* 部分标题：细线 + 编号，压在板块顶部 */
.wy-part{
  margin:clamp(40px,5.5vh,72px) 0 clamp(22px,3.2vh,40px);
  padding-top:22px;
  border-top:1px solid var(--border);
  display:grid;
  grid-template-columns:auto minmax(0,1fr);
  gap:clamp(16px,2.4vw,40px);
  align-items:baseline;
}
.wy-part-no{
  font-family:var(--font-ui);
  font-size:12px;
  letter-spacing:.2em;
  color:var(--accent);
}
.wy-part-title{
  margin:0;
  font-family:var(--font-display-cn,'Noto Serif SC',serif);
  font-weight:700;
  font-size:clamp(22px,2.3vw,34px);
  letter-spacing:-.01em;
  color:var(--text-primary);
}
.wy-part-note{
  grid-column:2;
  margin:8px 0 0;
  max-width:52ch;
  font-size:14px;
  line-height:1.95;
  color:var(--text-secondary);
}

/* ================= 一、开场：左侧信息 + 右侧五张海报组合 =================
   左约 1/3、右约 2/3；组合中央那张最高、向两侧逐级后退。
   两侧文字与海报组合**共用一个视觉中心**（grid 里左右两块都垂直居中）。 */
.wy-open{
  display:grid;
  grid-template-columns:minmax(0,32fr) minmax(0,68fr);
  gap:clamp(28px,4vw,80px);
  align-items:center;
}
.wy-open-row{
  display:grid;
  grid-template-columns:repeat(5,minmax(0,1fr));
  gap:clamp(8px,1.1vw,20px);
  align-items:center;
  /* 五张 + 说明文字都要落在一屏里（sticky 舞台就一屏高），超了会被裁掉。
     ⚠️ 2026-09-22 用户反馈"空的地方太大"：原来是 clamp(220px,34vh,420px)，
        1600×1000 实测中央那张只有 **340px** 高，上方还空 ~300px。
        海报组合本身约 384px 高、而 sticky 舞台有 1000px，空间足够。
        现在放到 `clamp(260px,56vh,580px)`：1000px 视口下中央 560px 高，
        整组约 604px（含说明），仍在舞台里、不裁切（.wy-open-pin 有 overflow:hidden）。 */
  --wy-open-h:clamp(260px,56vh,580px);
}
.wy-open-card{
  display:block;
  margin:0;
  padding:0;
  border:0;
  background:none;
  text-align:left;
  transition:transform .42s var(--wy-ease);
}
.wy-open-card figure{margin:0}
.wy-open-card img{
  width:100%;
  height:var(--wy-open-h);
  object-fit:cover;          /* 组合里只露一截是刻意的（这是海报墙，不是完整展示） */
  object-position:top center;
  display:block;
  background:var(--graphite);
}
/* 中央最高，向两侧逐级后退 */
.wy-open-card[data-depth="0"]{z-index:5}
.wy-open-card[data-depth="±1"]{z-index:3}
.wy-open-card[data-depth="-1"],.wy-open-card[data-depth="1"]{z-index:3}
.wy-open-card[data-depth="-2"],.wy-open-card[data-depth="2"]{z-index:1}
.wy-open-card[data-depth="-1"] img,.wy-open-card[data-depth="1"] img{height:calc(var(--wy-open-h) * .84)}
.wy-open-card[data-depth="-2"] img,.wy-open-card[data-depth="2"] img{height:calc(var(--wy-open-h) * .68)}
.wy-open-card[data-depth="-1"],.wy-open-card[data-depth="1"]{opacity:.94}
.wy-open-card[data-depth="-2"],.wy-open-card[data-depth="2"]{opacity:.82}
.wy-open-card.is-center img{height:var(--wy-open-h)}
/* 鼠标经过：只轻微上移 + 文字亮起。不旋转、不液化（用户明确要求） */
.wy-open-card:hover,.wy-open-card:focus-visible{transform:translateY(-8px)}
.wy-open-cap{
  display:block;
  margin-top:10px;
  font-size:11px;
  letter-spacing:.04em;
  color:var(--text-secondary);
  transition:color .42s var(--wy-ease);
}
.wy-open-cap i{
  display:block;
  font-style:normal;
  font-size:10px;
  letter-spacing:.18em;
  margin-bottom:3px;
  opacity:.7;
}
.wy-open-card:hover .wy-open-cap,.wy-open-card:focus-visible .wy-open-cap{color:var(--text-primary)}

/* 缺项时的空位：宁可画出来，也不要静默留白（见 wuyou.js 的 img()） */
.wy-missing{
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:6px;
  min-height:120px;
  padding:12px;
  border:1px dashed rgba(255,255,255,.28);
  background:rgba(255,80,80,.06);
  color:var(--text-secondary);
  font-size:11px;
  line-height:1.6;
  text-align:center;
}
.wy-missing b{color:#FF8A8A;font-weight:500;word-break:break-all}

/* ---------- 逐字错峰揭示（只用于短标题；正文按行出现） ----------
   从行内遮罩向上进入，位移约 20px。 */
[data-char-reveal]{display:block}
[data-char-reveal] .wy-ch{
  display:inline-block;
  transform:translateY(20px);
  opacity:0;
  transition:transform var(--wy-char-dur,.62s) var(--wy-ease), opacity var(--wy-char-dur,.62s) var(--wy-ease);
  transition-delay:calc(var(--wy-char-i,0) * 55ms);
}
[data-char-reveal].is-in .wy-ch{transform:translateY(0);opacity:1}
[data-char-reveal] .wy-ch-mask{display:inline-block;overflow:hidden;vertical-align:bottom}
/* 正文按行出现（不做打字机） */
[data-line-reveal] > *{
  opacity:0;
  transform:translateY(10px);
  transition:opacity .5s var(--wy-ease),transform .5s var(--wy-ease);
}
[data-line-reveal].is-in > *{opacity:1;transform:none}
[data-line-reveal].is-in > *:nth-child(2){transition-delay:.08s}
[data-line-reveal].is-in > *:nth-child(3){transition-delay:.16s}
[data-line-reveal].is-in > *:nth-child(4){transition-delay:.24s}

/* ================= 开场 → 主视觉：滚动驱动的舞台扩展 =================
   三层：暗化背景（cover，铺满但不拉伸）/ 完整原作（contain，绝不裁切）/ 遮罩。

   ⚠️ 扩展用的是 **FLIP**（先量、再反推、后播放）：
   把那一帧的尺寸与位置**精确设成中央海报当时的矩形**，再用一个 2D 缩放
   把它拉到满屏。这样"舞台是从那张海报里长出来的"，而不是两层各淡各的 ——
   之前那样在宽高比切换的一瞬间会出现一次很硬的跳，这就是"衔接不优雅"的主因。
   缩放包住的是**展示层**，里面的图始终 contain，所以过程中永远不会被拉伸。

   形状变化只用 transform / clip-path / opacity，每帧不读 DOM 尺寸。 */
/* ⚠️ 层级必须让**扩展舞台压在案例层之上**：扩展的后半段舞台是不透明的，
   案例标题/导航在它底下淡入；等舞台淡出时案例已经就位，中间没有"露馅"的空档。
   反过来（案例在上）会看到舞台先淡出、案例后淡入，中间闪一下 —— 这就是"衔接不优雅"。 */
.wy-stage{
  position:fixed;
  inset:0;
  z-index:8;                 /* 低于自定义光标 95，高于案例层 7 */
  opacity:0;
  pointer-events:none;
  visibility:hidden;
  will-change:opacity;
}
.wy-stage.is-live{visibility:visible}
.wy-stage-veil{
  position:absolute;
  left:0;
  top:0;
  width:var(--wy-frame-w, 300px);
  height:var(--wy-frame-h, 480px);
  overflow:hidden;
  --wy-expand:0;
  /* FLIP：先摆到"中央海报"当时的位置与大小，再用一个 2D 缩放拉到满屏。
     缩放包住的是**展示层**，里面的图始终 contain，所以过程中永远不会被拉伸。 */
  transform:translate3d(var(--wy-frame-x, 0px), var(--wy-frame-y, 0px), 0)
            scale(var(--wy-frame-sx, 1), var(--wy-frame-sy, 1));
  transform-origin:0 0;
  clip-path:inset(0 round calc((1 - var(--wy-expand)) * 12px));
  will-change:transform,clip-path;
  pointer-events:none;
}
.wy-stage-bg img{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  object-fit:cover;          /* 只负责铺满背景，不要求完整 */
  filter:brightness(.34) saturate(.9);
  transform:scale(1.06);
}
.wy-stage-fg{
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:clamp(16px,4vh,56px) clamp(16px,4vw,72px);
}
.wy-stage-fg img{
  max-width:100%;
  max-height:100%;
  width:auto;
  height:auto;
  object-fit:contain;        /* 原作完整展示，绝不裁切 */
  display:block;
}
/* 开场组合在扩展过程中收拢成"局部窗口" */
.wy-open-row{
  transition:none;
  will-change:transform,opacity;
}
.wy-page.is-expanding .wy-open-card:not(.is-center){opacity:0} /* 外围退到两侧由 JS 写 transform */
@media(prefers-reduced-motion:reduce){
  .wy-stage{position:absolute}          /* 减少动效时不固定，直接铺在这一段上 */
  .wy-stage-veil{clip-path:none}
  [data-char-reveal] .wy-ch,
  [data-line-reveal] > *{opacity:1;transform:none;transition:none}
}

/* ================= 二、重点案例：《恋爱单选题》：固定舞台 + 四幕 =================
   一个有限长度的滚动区（.wy-case-scroll）只提供"滚多少"，
   画面由挂在 body 上的 .wy-case 用 position:fixed 呈现。
   ⚠️ 挂 body 而不是板块里：`.wy-section` 有 position/z-index，会形成层叠上下文，
   fixed 放进去就不再相对视口定位（这个坑在查看层上踩过）。

   只动 transform / opacity / 遮罩；每帧不读 DOM 尺寸。
   --wy-case-in 由 JS 写：0 = 还没进案例，1 = 完全在场（叠层转场用）。 */
.wy-case-scroll{height:600vh}      /* JS 会按幕数覆盖成准确高度 */
.wy-case{
  position:fixed;
  inset:0;
  z-index:7;
  /* ⚠️ 收起时**不能只写 display:none**：那样这一层完全不合成，
     滚动途中会出现"案例没画出来、下面开场的文案与海报透出来"的空档
     （用户截图里左边那堆堆叠的文案、右边透出的海报就是这个）。
     用 visibility + opacity 的方式"收"，层还在、只是不可见、也不吃事件；
     真正要彻底移出命中测试时，靠下面那条 display:none（仅用于调试开关）。 */
  visibility:hidden;
  opacity:0;
  pointer-events:none;
  --wy-case-in:0;
  /* 左上项目名块占掉的垂直区间：top 用和 `.wy-case-head` 完全相同的那条 clamp，
     高度取"编号 + 标题 + 英文行 + 各自外边距"的实测值（三种视口都是 91–93px）。
     ⚠️ 两者必须一起改：改了 `.wy-case-head` 的 top/字号，这里要同步。
     第一幕左栏用它做 padding-top，才不会钻到项目名底下（2026-09-23 用户报的文字重叠）。 */
  --wy-head-top:clamp(24px,5vh,64px);
  --wy-head-h:91px;
  --wy-head-safe:calc(var(--wy-head-top) + var(--wy-head-h) + 14px);
}
.wy-case.is-live{visibility:visible;opacity:1;pointer-events:auto}
/* ⚠️ 收起时，**层里任何东西都不许再参与命中测试**。
   只写容器那一条是不够的：paintCase 会给"当前这一幕"的子元素写**行内**
   visibility:visible + pointer-events:auto，而行内值会盖掉容器上的收起样式 ——
   于是整层看着没了、里面的按钮却还在命中测试里，
   把人物剧场 / 赛事与运营那些板块的点击全部截走
   （实测滚到剧场时 elementFromPoint(800,500) 命中的是案例里的横幅）。
   JS 那边已经让行内值跟着 is-live 走；这里再用 !important 钉一道，
   以后谁再往层里加元素都不会把这个洞捅回来。 */
.wy-case:not(.is-live) *,
.wy-case:not(.is-live){visibility:hidden!important;pointer-events:none!important}
/* 底色必须**不透明**：案例是全屏舞台，下面任何东西都不该透出来 */
.wy-case::before{
  content:'';
  position:absolute;
  inset:0;
  background:var(--black-absolute);
  z-index:0;
  pointer-events:none;
}
/* 两侧的透明区域不该吃事件：只有真正可点的东西才接收 */
.wy-case-backdrop,.wy-case-head,.wy-case-stage{pointer-events:none}
/* ⚠️ 幕内的可点元素**只在当前这一幕**里可点（.is-active 由 paintCase 按四舍五入的幕号打）。
   原来这里对 .wy-cc 一律给 auto，于是相邻幕即使 opacity:0（|rel| = 0.999 时仍算在场），
   它的卡片照样留在命中测试里、把后一幕的点击截走 —— 实测 03 幕正中命中 04 幕的 .wy-more-sub。
   补充物料面板不在 .wy-scene 里，单独放行。 */
.wy-case-nav-item,.wy-shot,.wy-more-btn,.wy-case-skip,.wy-more-panel .wy-cc{pointer-events:auto}
.wy-scene.is-active .wy-cc,
.wy-scene.is-active .wy-kv-figure,
.wy-scene.is-active .wy-report-shot{pointer-events:auto}
.wy-case-inner{position:absolute;inset:0;z-index:1;will-change:transform}
.wy-case-backdrop{
  position:absolute;
  inset:-8%;
  z-index:0;
  pointer-events:none;
  /* 两层叠加：**第一层是实心黑**，保证任何情况下都不透底（这是全屏舞台，
     下面开场的文案/海报透出来会显得页面堆叠错乱）；
     第二层才是跟着当前幕换色的极淡色光，只落在背景上。 */
  background:radial-gradient(70% 60% at 50% 45%, rgba(5,5,6,0) 0%, rgba(5,5,6,0) 72%), var(--black-absolute);
  transition:background .6s var(--ease-out);
}

/* 左上固定项目名 */
.wy-case-head{
  position:absolute;
  left:var(--gutter);
  top:clamp(24px,5vh,64px);      /* ⚠️ 与 .wy-case 上的 --wy-head-top 必须一致 */
  z-index:30;
  pointer-events:none;
}
.wy-case-no{
  display:block;
  margin-bottom:10px;
  font-family:var(--font-ui);
  font-size:11px;
  letter-spacing:.24em;
  color:var(--accent);
}
.wy-case-title{
  margin:0;
  font-family:var(--font-display-cn,'Noto Serif SC',serif);
  font-weight:700;
  font-size:clamp(24px,2.6vw,40px);
  letter-spacing:-.01em;
  color:var(--text-primary);
}
.wy-case-kind{
  margin:8px 0 0;
  font-family:var(--font-ui);
  font-size:10px;
  letter-spacing:.28em;
  color:var(--text-secondary);
}

/* 幕容器 */
.wy-case-stage{
  position:absolute;
  /* ⚠️ 2026-09-22 用户反馈"空的地方太大"：原来是 `88/150` 上下 inset，
     1600×1000 实测吃掉 280px，舞台只剩 720px，主视觉 KV 也只能到 900×683、
     居中后左右各空 ~285px。现在收到 `72/80`，舞台 1466×≈848，KV 能放到约 1069×789。 */
  inset:clamp(48px,7.2vh,72px) var(--gutter) clamp(56px,8vh,80px);
  /* 幕内容压在氛围带（z=1）**之上**：长图只是背景质感，不能盖住前景作品 */
  z-index:12;
  perspective:1600px;
}
.wy-scene{
  position:absolute;
  inset:0;
  display:flex;
  align-items:center;
  justify-content:center;
  opacity:0;
  visibility:hidden;
  will-change:transform,opacity;
}
.wy-scene.is-active{visibility:visible}

/* ---------- 01 主视觉：不对称版式 ----------
   ⚠️ 2026-09-22 用户反馈"空的地方太大"，这一幕有两处原因：
     ① 原来 24/66/10，中栏只有 904px，KV 受宽度限制、高到不了舞台高度；
        改成 18/78/4 后中栏 ≈1075px。左栏仍有 248px（文字最小宽约 220px），不会挤坏。
     ② 网格是 `align-items:center`，中栏只有内容高（704px），舞台却有 848px；
        KV 的 `max-height:100%` 于是只到 704px。改成中栏自己撑满这一格
        （`.wy-scene-media{align-self:stretch}`），KV 才能长到约 1070×789。
     另：第一幕的图已换成 view 档（1800×1366），否则它到 900px 就到顶了。 */
.wy-scene[data-scene="kv"]{
  display:grid;
  grid-template-columns:minmax(0,18fr) minmax(0,78fr) minmax(0,4fr);
  gap:clamp(20px,3vw,56px);
  /* ⚠️ 原来是 `align-items:stretch`（等价于默认值）。stretch 会让左栏撑满整格、
     文字从舞台顶边 y=72 就开始排 —— 而左上项目名块正好压在 y=50→143 上，
     于是"恋爱单选题"标题、英文行和说明段前两行叠在一起（2026-09-23 用户截图报的重叠）。
     改成 start 只为让左栏能靠 padding-top 往下让位；中栏由下面那条
     `.wy-scene[data-scene="kv"] .wy-scene-media{align-self:stretch}` 单独撑满，
     主视觉 KV 的尺寸一分不变。 */
  align-items:start;
  /* ⚠️ `align-items:start` 之后，网格**整块**会被 align-content:normal(=stretch→居中)
     在舞台里垂直居中，于是左栏顶部会额外下移 (舞台高 − 内容高)/2 ≈ 88px，
     项目名与说明段之间白白空出一大条（实测说明段跑到 y=229，而项目名下沿只有 141）。
     用 align-content:start 把网格贴回舞台顶边，让 padding-top 说了算。 */
  align-content:start;
  justify-items:stretch;
}
/* ⚠️ 第一幕左栏必须让开左上项目名块，否则文字互相压住。
   `align-self:start` 也是必需的：.wy-scene 是 `align-items:center` 的 flex 容器，
   不加这条，这一栏会在舞台里被垂直居中，文字会落到 y=229（项目名下沿才 141），
   中间白白空出 88px —— 光有 padding-top 是不够的（实测过）。
   143px 是无变量时的兜底（= 项目名块实测下沿），宁可多让一点也不重叠。 */
.wy-scene[data-scene="kv"] .wy-scene-side{
  align-self:start;
  padding-top:var(--wy-head-safe,143px);
}
.wy-scene-side{max-width:34ch}
.wy-scene-desc{
  margin:0 0 20px;
  font-size:14px;
  line-height:2;
  color:var(--text-secondary);
}
.wy-scene-duty{
  margin:0;padding:0;list-style:none;
  border-top:1px solid var(--border);
}
.wy-scene-duty li{
  padding:9px 0;
  border-bottom:1px solid var(--border);
  font-size:13px;
  line-height:1.7;
  color:var(--text-primary);
}
.wy-scene-duty li span{
  display:block;
  font-size:11px;
  letter-spacing:.14em;
  color:var(--text-secondary);
}
.wy-scene-media{display:flex;align-items:center;justify-content:center;min-width:0}
/* 主视觉那一幕让中栏**撑满这一格**（其余幕不受影响）：
   否则网格的 align-items:center 会把中栏压成内容高，KV 的 max-height:100% 也就跟着变矮。 */
.wy-scene[data-scene="kv"] .wy-scene-media{align-self:stretch}
.wy-kv-figure{
  margin:0;padding:0;border:0;background:none;display:block;
  max-width:100%;max-height:100%;
  transition:transform .4s var(--wy-ease);
}
.wy-kv-figure:hover,.wy-kv-figure:focus-visible{transform:translateY(-6px)}
.wy-kv-figure img{
  display:block;
  max-width:100%;
  /* ⚠️ 2026-09-22：原来是 `max-height:calc(100vh - clamp(210px,30vh,330px))`，
     在 1000px 视口下被卡到 704px —— 舞台明明有 848px，KV 却停在 704，上下各空一截。
     这个公式是**旧舞台 inset** 时代的产物，改了 inset 之后它就对不上了。
     现在改成跟着中栏高度走：中栏已 `align-self:stretch`，图占满高度、宽度按比例自适应。 */
  max-height:100%;
  width:auto;height:auto;
  object-fit:contain;
  background:transparent;
}

/* ---------- 02 上线系列：中央居中、两侧从后方展开 ---------- */
.wy-launch-row{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:clamp(14px,2vw,40px);
  transform-style:preserve-3d;
  width:100%;height:100%;
}
.wy-launch-slot{transform-style:preserve-3d;will-change:transform,opacity}
.wy-cc{
  margin:0;padding:0;border:0;background:none;
  display:flex;flex-direction:column;align-items:center;
  transition:transform .38s var(--wy-ease);
}
.wy-cc:hover,.wy-cc:focus-visible{transform:translateY(-6px)}
.wy-cc img{
  display:block;
  height:clamp(265px,50vh,600px);
  width:auto;
  background:var(--graphite);
}
.wy-launch-slot[data-rel="0"] .wy-cc img{height:clamp(310px,60vh,715px)}
.wy-cc-cap{
  display:block;margin-top:10px;
  font-size:12px;color:var(--text-secondary);
  transition:color .38s var(--wy-ease);
}
.wy-cc:hover .wy-cc-cap{color:var(--text-primary)}

/* ---------- 03 线下物料：易拉宝沿弧线陈列 ----------
   （2026-09-22 删掉了「横幅」「手举牌」两组规则：那两个子舞台已从结构里移除。
     横幅那一层原先 visibility:visible + opacity:0 + pointer-events:auto，
     盖在易拉宝上截走点击 —— 详见 components/wuyou.js 数据区的注释。） */
.wy-scene[data-scene="material"]{display:block}
.wy-substage{
  position:absolute;
  inset:0;
  display:flex;
  flex-direction:column;
  align-items:center;
  justify-content:center;
  gap:clamp(14px,2.4vh,30px);
  will-change:transform,opacity;
}
.wy-sub-label{
  margin:0;
  font-size:12px;
  letter-spacing:.16em;
  color:var(--text-secondary);
}
/* 易拉宝沿弧线：居中那张正对观众 */
.wy-rollup-arc{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:clamp(10px,1.6vw,30px);
  transform-style:preserve-3d;
  width:100%;
}
.wy-arc-slot{transform-style:preserve-3d;will-change:transform,opacity}
.wy-arc-slot .wy-cc img{height:clamp(275px,60vh,690px);width:auto}
.wy-arc-slot .wy-cc-cap{display:none}      /* 幕内小步不重复加大标题 */

/* ---------- 长图氛围带（战报）----------
   1:8 的超长图不适合"一屏一屏读"。这里把它铺成背景里的一条横向长图，
   随滚动缓缓平移，两端化开、整体压暗 —— 氛围为主，不要求看清内容。
   它不占额外的滚动距离（用户明确说快速滑过就行）。

   ⚠️ 图必须是**按带子比例裁好的** scroller 变体（2360→2880 宽，1.82:1），
   不能再拿 `view`（1100×9047）直接铺：那等于把图放到 3168×26055，
   字体全糊，而且窗口只露出整图的一小条。 */
.wy-case-scroller{
  position:absolute;
  left:0;right:0;
  top:50%;
  height:clamp(205px,39vh,480px);
  transform:translateY(-50%);
  overflow:hidden;
  z-index:1;
  pointer-events:none;
  opacity:0;
  transition:opacity .7s var(--ease-out);
  -webkit-mask:linear-gradient(90deg,transparent 0,#000 12%,#000 88%,transparent 100%);
          mask:linear-gradient(90deg,transparent 0,#000 12%,#000 88%,transparent 100%);
}
.wy-case-scroller img{
  position:absolute;
  left:0;
  top:50%;
  height:auto;
  width:auto;
  max-width:none;
  transform-origin:0 50%;
  /* 定位与位移分成两层：JS 每帧写 translate3d，这里用 translateY(-50%) 定位。
     写在同一层的话每帧都会把居中那一下覆盖掉。 */
  translate:0 -50%;
  will-change:transform;
  filter:brightness(.42) saturate(.85);
}
.wy-case-scroller::after{
  content:'';
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,rgba(5,5,6,.85) 0%,rgba(5,5,6,.2) 30%,rgba(5,5,6,.2) 70%,rgba(5,5,6,.85) 100%);
}

/* ---------- 04 延展与战报 ----------
   ⚠️ 原来写的是 `1fr + 320px`：宽屏下 1fr 被拉得很大，中间就空出一大片
   （用户截图里那一大块黑）。改成"上面一对作品 + 下面一条通栏长图带"，
   版面被填满，长图也真正用上了。 */
.wy-more-layout{
  display:flex;
  flex-direction:column;
  gap:clamp(18px,2.6vh,34px);
  width:100%;
}
.wy-more-sub{
  display:flex;
  align-items:flex-end;
  justify-content:center;
  gap:clamp(18px,2.6vw,50px);
}
.wy-more-sub .wy-cc img{height:clamp(230px,41vh,505px)}
.wy-more-sub .wy-cc[data-cap*="封面"] img{height:clamp(190px,32vh,380px)}

/* ---------- 长图带：氛围为主 ----------
   战报原图是 1:8 的超长图。这里**不要求看清内容**：横向压成一条带、
   两端化开、叠一层压暗，只做质感；看完整内容点开查看层。
   这样既用上了素材，又不用为它单独加一屏滚动距离（用户明确说了快速滑过就行）。 */
.wy-more-report{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:10px;
  width:100%;
}
.wy-report-shot{
  margin:0;padding:0;border:0;background:none;display:block;
  width:100%;max-width:1180px;text-align:left;
}
.wy-report-band{
  display:block;
  position:relative;
  overflow:hidden;
  /* 宽度 1187 时 ≈ 3.66:1，**与 band 素材 2360×644 的比例一致**
     （裁切区间就是按这个比例挑的），所以 cover 的缩放系数是 1.0：
     屏幕上看到的是裁切原样，既不放大也不缩小。
     ⚠️ 高度上限不能太小：原来源图裁切定得随意（620 高）而带子只有 172 高，
     cover 会把图缩到 0.52 倍，字全糊；同时 43% 的画面被裁掉只留一片粉底。
     现在高度和裁切比例对齐，再用 19vh 给窄屏留退路。 */
  height:clamp(215px,37vh,375px);
  border-radius:10px;
  -webkit-mask:linear-gradient(90deg,transparent 0,#000 3.2%,#000 96.8%,transparent 100%);
          mask:linear-gradient(90deg,transparent 0,#000 3.2%,#000 96.8%,transparent 100%);
}
.wy-report-band img{
  /* ⚠️ 这里曾经是 `width:100%; height:auto; transform:translateY(-1%)`。
     战报原图是 1:8.2 的超长图，按宽度撑满 1180px 会变成 1180×9706，
     窗口只露出整图高度的 1.4% —— 截到的是 logo 上方一片粉，
     而且 640 的 thumb 被放大到 1180（≈1.84 倍）字体全糊。
     现在用按带子比例裁好的 band 变体（2360×966，2.44:1），cover 铺满带子。
     ⚠️ 不要用 min-width:100% + min-height:100% 去"铺满"：
     两个 min 会**同时**生效，图片被放到 2374×972（2.4 倍）再裁，
     大字直接糊出带子。cover 才是"等比放大到刚好盖住"。 */
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  max-width:none;
  object-fit:cover;
  /* 缩放系数 1.0（比例对上了），所以这里不用躲裁切，居中即可 */
  object-position:50% 50%;
  display:block;
}
.wy-report-veil{
  position:absolute;
  inset:0;
  background:linear-gradient(180deg,rgba(5,5,6,.30) 0%,rgba(5,5,6,.55) 60%,rgba(5,5,6,.92) 100%);
  pointer-events:none;
}
.wy-report-hint{
  position:absolute;
  left:clamp(14px,2vw,30px);
  bottom:clamp(10px,1.6vh,18px);
  display:inline-flex;
  align-items:center;
  gap:9px;
  font-size:12px;
  letter-spacing:.1em;
  color:var(--accent);
  text-shadow:0 1px 6px rgba(0,0,0,.6);
}
.wy-report-hint::before{content:'';width:22px;height:1px;background:currentColor}
.wy-more-note{
  margin:0;
  max-width:1180px;
  font-size:12px;
  line-height:1.85;
  color:var(--text-secondary);
}
.wy-more-note b{color:var(--text-primary);font-weight:500}

/* ---------- 底部：章节导航 + 子进度 + 工具 ---------- */
.wy-case-foot{
  position:absolute;
  left:var(--gutter);right:var(--gutter);
  bottom:clamp(18px,3.6vh,44px);
  z-index:30;
  display:flex;
  align-items:center;
  gap:clamp(14px,2vw,32px);
  padding-top:16px;
  border-top:1px solid var(--border);
}
.wy-case-nav{display:flex;gap:clamp(10px,1.6vw,28px);flex-wrap:wrap}
.wy-case-nav-item{
  display:flex;align-items:baseline;gap:8px;
  padding:6px 2px;
  border:0;background:none;
  font-size:12px;
  color:var(--text-secondary);
  border-bottom:1px solid transparent;
  transition:color .3s var(--wy-ease),border-color .3s var(--wy-ease);
}
.wy-case-nav-item i{font-style:normal;font-size:10px;letter-spacing:.16em;opacity:.7}
.wy-case-nav-item:hover,.wy-case-nav-item:focus-visible{color:var(--text-primary)}
.wy-case-nav-item.is-active{color:var(--text-primary);border-bottom-color:var(--accent)}
/* 子进度条（wy-case-sub / -dot）随 03 幕的两小步一起删除：那一幕现在只有一步，
   底部再挂一行"易拉宝"只是重复舞台里已有的小标题。 */
.wy-case-tools{margin-left:auto;display:flex;gap:10px;align-items:center}
.wy-case-skip{
  padding:11px 18px;border:1px solid rgba(255,255,255,.22);
  font-size:12px;letter-spacing:.08em;color:var(--text-primary);
  background:rgba(5,5,6,.5);
  white-space:nowrap;
  transition:border-color .28s var(--wy-ease);
}
.wy-case-skip:hover,.wy-case-skip:focus-visible{border-color:rgba(255,255,255,.42)}

/* ---------- 补充物料面板：按钮打开，不占滚动距离 ---------- */
.wy-more-panel{
  position:fixed;inset:0;z-index:88;
  background:rgba(3,3,4,.97);
  overflow:auto;
  padding:clamp(24px,4vh,56px) var(--gutter) clamp(40px,6vh,80px);
}
.wy-more-panel[hidden]{display:none}
.wy-more-panel-head{
  display:flex;align-items:baseline;gap:20px;
  margin-bottom:clamp(20px,3.4vh,40px);
  padding-bottom:18px;border-bottom:1px solid var(--border);
}
.wy-more-panel-head h4{
  margin:0;
  font-family:var(--font-display-cn,'Noto Serif SC',serif);
  font-weight:700;font-size:clamp(20px,2vw,30px);color:var(--text-primary);
}
.wy-more-panel-head .wy-viewer-btn{margin-left:auto}
.wy-more-panel-body .wy-more-group + .wy-more-group{margin-top:clamp(24px,3.4vh,46px)}

/* 通用物料容器（面板里沿用） */
.wy-rollups{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(170px,1fr));
  gap:clamp(16px,2.4vw,38px);
}
.wy-rollups .wy-cc img{height:clamp(275px,50vh,600px);width:auto;max-width:100%}
.wy-banners{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(14px,2vw,28px);
}
.wy-banners .wy-cc{align-items:flex-start}
.wy-banners .wy-cc img{width:100%;height:auto}

/* 通用“点开看大图”的按钮 */
.wy-shot{
  margin:0;padding:0;border:0;background:none;display:block;text-align:left;
  transition:transform .42s var(--wy-ease);
}
.wy-shot:hover,.wy-shot:focus-visible{transform:translateY(-6px)}
.wy-shot img{display:block;background:var(--graphite)}
.wy-mat-label{
  display:flex;align-items:baseline;gap:12px;
  margin:0 0 16px;font-size:12px;letter-spacing:.16em;color:var(--text-secondary);
}
.wy-mat-label::after{content:'';flex:1;height:1px;background:var(--border)}

/* ================= 叠层转场：章节之间 =================
   进入案例时旧舞台轻微收拢（不是"跳走"）；离开案例进入人物剧场时同样收拢，
   新画面从下方覆盖上来 —— 由 talent.js 写 --wy-stack-out。 */
.wy-stack-out{
  transform-origin:50% 50%;
  transform:scale(var(--wy-stack-out, 1));
  will-change:transform;
}

/* ================= 大图查看层 =================
   ⚠️ z-index 必须低于自定义光标（95），否则光标被压在查看层下面。
   两种模式（模式由素材清单的 mode 字段给出，**不靠横竖猜**）：
     · fit   —— 普通作品：完整居中，宽高都受可用视口限制，第一眼看见全图
     · width —— 长图：按可读宽度展开，允许纵向滚动 */
.wy-viewer{
  position:fixed;
  inset:0;
  z-index:90;
  display:none;
  background:rgba(3,3,4,.96);
  backdrop-filter:blur(3px);
}
.wy-viewer.is-open{display:block}
.wy-viewer-scroll{
  position:absolute;
  inset:0;
  overflow:auto;
  overscroll-behavior:contain;    /* 长图内部正常滚动，滚到头不让外层跟着动 */
  -webkit-overflow-scrolling:touch;
  padding:clamp(20px,3.4vh,56px) clamp(16px,3vw,56px) 92px;
}
.wy-viewer-img{
  display:block;
  margin:0 auto;
  background:transparent;
}

/* fit：完整居中，宽高都不超过可用区域 */
.wy-viewer[data-mode="fit"] .wy-viewer-scroll{
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden;
}
.wy-viewer[data-mode="fit"] .wy-viewer-img{
  width:auto;
  height:auto;
  max-width:100%;
  max-height:100%;
  object-fit:contain;
}
/* 放大细看：切到实际像素宽度，允许滚动 —— 不默认放大到超出屏幕 */
.wy-viewer[data-mode="fit"].is-zoom .wy-viewer-scroll{
  display:block;
  overflow:auto;
}
.wy-viewer[data-mode="fit"].is-zoom .wy-viewer-img{
  width:var(--wy-view-w,1200px);
  max-width:100%;
  max-height:none;
}
/* width：长图按可读宽度展开，纵向滚动 */
.wy-viewer[data-mode="width"] .wy-viewer-img{
  width:min(100%,var(--wy-view-w,1200px));
  height:auto;
}

.wy-viewer-bar{
  position:absolute;
  left:0;right:0;bottom:0;
  display:flex;
  align-items:center;
  gap:18px;
  padding:16px clamp(16px,3vw,56px);
  background:linear-gradient(180deg,transparent,rgba(3,3,4,.92));
  pointer-events:none;
}
.wy-viewer-bar > *{pointer-events:auto}
.wy-viewer-cap{
  margin:0;
  font-size:13px;
  color:var(--text-secondary);
}
.wy-viewer-cap b{color:var(--text-primary);font-weight:500}
.wy-viewer-tools{margin-left:auto;display:flex;gap:10px;align-items:center}
.wy-viewer-btn{
  padding:10px 16px;
  border:1px solid var(--border);
  font-size:12px;
  letter-spacing:.06em;
  color:var(--text-secondary);
  background:rgba(5,5,6,.6);
  transition:color .3s var(--wy-ease),border-color .3s var(--wy-ease);
}
.wy-viewer-btn:hover,.wy-viewer-btn:focus-visible{color:var(--text-primary);border-color:rgba(255,255,255,.34)}
.wy-viewer-btn[disabled],.wy-viewer-btn[hidden]{display:none}
.wy-viewer-close{
  position:absolute;
  top:clamp(16px,3vh,34px);
  right:clamp(16px,3vw,56px);
  z-index:2;
}

/* 中窄屏：案例第一幕改成"文字在上、主视觉在下"。
   ⚠️ 为什么必须改版面（2026-09-23 实测）：`.wy-case-head` 那个项目名块宽 238px
   （左上 `left:var(--gutter)`），而第一幕中栏的左边界在 1280 宽下是 x=289 ——
   项目名块右边界 292 伸进图里 3px，窄一点会更明显。
   换成上下两行后，正文占满整宽（说明段少折一行），主视觉仍占满整幅宽度。 */
@media(max-width:1300px){
  .wy-scene[data-scene="kv"]{
    grid-template-columns:minmax(0,1fr);
    grid-template-rows:auto minmax(0,1fr);
    row-gap:clamp(16px,2.4vh,30px);
  }
  /* ⚠️ `align-self:start` 在单栏下同样是必需的：左栏跨两行、比轨道矮，
     不钉住就会被 `.wy-scene` 的 align-items:center 在块方向居中，
     文字整体上移 ~8px 顶到项目名里。
     让位改用 margin-top：padding 会把整栏（含底部）一起撑高，margin 只推内容。 */
  .wy-scene[data-scene="kv"] .wy-scene-side{max-width:none;padding-top:0;align-self:start;margin-top:var(--wy-head-safe,143px)}
  .wy-scene[data-scene="kv"] .wy-scene-desc{max-width:54ch}
}
/* ================= 窄屏 ================= */
@media(max-width:1100px){
  .wy-open{grid-template-columns:1fr;gap:38px}
  .wy-open-row{grid-template-columns:repeat(3,minmax(0,1fr))}
  .wy-open-card:nth-child(2),.wy-open-card:nth-child(3){margin-top:0}
  .wy-kv{grid-template-columns:1fr}
  .wy-kv-side{padding-top:0}
  .wy-report{grid-template-columns:1fr}
  .wy-report-window{max-width:320px}
  .wy-rollups{max-width:none}
  .wy-rollups .wy-shot img{height:clamp(330px,58vh,640px);max-width:100%}
}
@media(max-width:760px){
  .wy-open-row{grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
  .wy-open-card:nth-child(3){display:none}      /* 窄屏只留两张，不做挤压 */
  .wy-launch-main,.wy-launch-sub{gap:14px}
  .wy-launch-card img{height:clamp(210px,34vh,320px)}
  .wy-launch-sub .wy-launch-card img{height:170px}
  .wy-rollups{grid-template-columns:repeat(2,minmax(0,1fr))}
  .wy-rollups .wy-shot img{height:clamp(240px,40vh,380px)}
  .wy-banners{grid-template-columns:1fr}
  .wy-part{grid-template-columns:1fr}
  .wy-part-note{grid-column:1}
}
/* 减少动效：把入场与悬停位移全部关掉 */
@media(prefers-reduced-motion:reduce){
  .wy-launch-card{opacity:1;transform:none;transition:none}
  .wy-open-card,.wy-shot{transition:none}
  .wy-open-card:hover,.wy-open-card:focus-visible,
  .wy-shot:hover,.wy-shot:focus-visible{transform:none}
}
