:root{
    color-scheme: light dark;
    --pad:28px;
    --bg:#fbfbfd; --bg-2:#f4f4f7;
    --ink:#14161b; --muted:#5d6472; --faint:#9aa1ad;
    --card:#ffffff; --border:rgba(17,24,39,.09);
    --shadow-1:0 1px 2px rgba(17,24,39,.05), 0 10px 30px -18px rgba(17,24,39,.22);
    --shadow-2:0 2px 6px rgba(17,24,39,.07), 0 26px 50px -22px rgba(17,24,39,.34);
    /* 整屏虚化背景的"小画布 + 放大"参数（详见 .bg img 的注释）：
       --bg-scale 同时决定小画布尺寸（160%/scale）与等效模糊半径（52px/scale） */
    --bg-scale:10; --bg-blur:5.2px;
    /* 极光层同理（详见 .aurora-layer 的注释）：盒子缩放后磨糊半径同比缩小 */
    --aurora-scale:8; --aurora-blur:3.75px;
    /* 预览卡片「高光扫过」的总开关：0=关 / 1=开。
       ⚠️ 参考视频里只有「倾斜 + 阴影随倾」两件事，并没有高光，这一档属于额外加戏，
          所以默认关闭。想开就改这一个数（深色主题下建议同时把 .poster::after 里的白压低）。
          角度 / 缩放 / 阴影位移的参数在 JS 的 TILT 常量里，不在这里。 */
    --tilt-shine:0;
    /* 顶部栏「滚动边缘效果」的下沿延伸长度（见 .site-header 注释），调它就够 */
    --se-fade:44px;
    /* 缩略图「激活」阴影：必须收得比 .rail 的 padding-bottom 浅。
       .rail 是横向滚动容器（overflow-x:auto 会把另一轴强制成 hidden），
       阴影一旦长过容器底边就会被齐平裁断，在圆点上方留下一条横线。
       另外 transform:scale() 会把阴影一起放大，算余量时别忘了这 0.07。 */
    --shadow-thumb-active:0 3px 8px -4px rgba(17,24,39,.16), 0 8px 18px -10px rgba(17,24,39,.34);
    --chip:color-mix(in srgb,var(--card) 66%,transparent);
    --grain:.34; --aurora-blend:normal; --aurora-opacity:.55;
    /* 当前项目的主题色（由 JS 覆盖） */
    --a1:#6f6cf6; --a2:#bd6ae0;
    --b1:transparent; --b2:transparent; --b3:transparent;
  }
  [data-theme="dark"]{
    --bg:#0b0c10; --bg-2:#12141b;
    --ink:#f2f4f8; --muted:#c3c9d4; --faint:#8e96a4;
    --card:#161922; --border:rgba(255,255,255,.12);
    --shadow-1:0 1px 2px rgba(0,0,0,.4), 0 12px 34px -18px rgba(0,0,0,.7);
    --shadow-2:0 2px 8px rgba(0,0,0,.5), 0 30px 60px -22px rgba(0,0,0,.8);
    --shadow-thumb-active:0 3px 8px -4px rgba(0,0,0,.42), 0 8px 18px -10px rgba(0,0,0,.62);
    --chip:color-mix(in srgb,var(--card) 62%,transparent);
    --grain:.24; --aurora-blend:screen; --aurora-opacity:.78;
  }
  *{box-sizing:border-box;margin:0;padding:0;}
  html{-webkit-tap-highlight-color:transparent;scroll-behavior:smooth;}
  body{
    font-family:"Inter",system-ui,-apple-system,"PingFang SC","Microsoft YaHei",Segoe UI,Roboto,sans-serif;
    background:var(--bg);color:var(--ink);line-height:1.6;
    -webkit-font-smoothing:antialiased;min-height:100vh;overflow-x:hidden;
    transition:background .4s ease,color .4s ease;
  }
  ::selection{background:color-mix(in srgb,var(--a1) 26%,transparent);}
  a{color:inherit;text-decoration:none;}
  img{display:block;}
  button{font:inherit;color:inherit;border:0;background:none;cursor:pointer;}
  .wrap{width:100%;max-width:1220px;margin:0 auto;padding-left:var(--pad);padding-right:var(--pad);}
  .sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;}

  /* ── 顶部悬浮导航：下沿用「滚动边缘效果」，不画边框 ─────────────
     原实现是 `backdrop-filter` 压在这条 68px 上 + 一条 1px 的 border-bottom，
     滚过内容时那条硬线很扎眼。现在改成 iOS 的 Scroll Edge Effect：
     在条的下方铺一层**比条更高**的玻璃带，它的模糊与底色都靠 mask 向下渐隐 ——
       ① ::before  大半径模糊（14px），mask 让它只在上段实、往下淡出；
       ② ::after   小半径模糊（5px）+ 底色渐变，铺满整条过渡带。
     两层叠在一起才是"渐进模糊"；**单层 blur 加蒙版只会得到"整体变淡"，边缘仍是一个台阶**。
     ⚠️ mask 与 backdrop-filter 必须写在**同一个元素**上。放到父子两层是不行的：
        父级的 mask 裁的是父级自己的绘制结果，管不到子级 backdrop-filter 采到的那层背景。
     ⚠️ 这两层是绝对定位元素，会画在静态定位的 .wrap 之上 → .wrap 必须 position:relative;z-index:1，
        否则品牌名与导航会被玻璃带盖住（半透明，看着只是"发灰一点"，很容易忽略）。
     ⚠️ 下沿多出来的 --se-fade 会盖住页面内容，所以两层都必须 pointer-events:none，
        否则页头下方这 44px 内的链接/按钮全部点不动。 */
  .site-header{
    position:fixed;top:0;left:0;right:0;z-index:60;
  }
  .site-header::before,
  .site-header::after{
    content:"";position:absolute;left:0;right:0;top:0;
    height:calc(100% + var(--se-fade));
    pointer-events:none;
    -webkit-backdrop-filter:blur(var(--se-blur)) saturate(var(--se-sat));
            backdrop-filter:blur(var(--se-blur)) saturate(var(--se-sat));
    -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 var(--se-hold),transparent 100%);
            mask-image:linear-gradient(180deg,#000 0%,#000 var(--se-hold),transparent 100%);
  }
  .site-header::before{--se-blur:14px;--se-sat:160%;--se-hold:26%;}
  .site-header::after{
    --se-blur:6px;--se-sat:150%;--se-hold:48%;
    background:linear-gradient(180deg,
      color-mix(in srgb,var(--bg) 92%,transparent) 0%,
      color-mix(in srgb,var(--bg) 78%,transparent) 58%,
      color-mix(in srgb,var(--bg) 30%,transparent) 84%,
      transparent 100%);
    opacity:.86;transition:opacity .35s ease;
  }
  /* 离开页首后把底色压实一点（用 opacity 过渡，渐变本身没法平滑过渡） */
  .site-header.scrolled::after{opacity:1;}
  .site-header .wrap{position:relative;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:18px;height:68px;}
  .brand{display:flex;align-items:center;gap:10px;font-weight:600;letter-spacing:.2px;}
  .brand .mark{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;color:var(--ink);}
  .brand .mark svg{width:24px;height:24px;}
  .brand b{font-family:"Space Grotesk",sans-serif;font-size:1.02rem;}
  .header-right{display:flex;align-items:center;gap:26px;}
  .nav{display:flex;align-items:center;gap:28px;font-size:.9rem;}
  .nav a{position:relative;color:var(--muted);font-weight:500;transition:color .25s;}
  .nav a::after{content:"";position:absolute;left:0;right:0;bottom:-6px;height:2px;border-radius:2px;
    background:linear-gradient(90deg,var(--a1),var(--a2));transform:scaleX(0);transform-origin:left;transition:transform .3s ease;}
  .nav a:hover{color:var(--ink);}
  .nav a:hover::after,.nav a.current::after{transform:scaleX(1);}
  .nav a.current{color:var(--ink);}
  /* 白天/黑夜切换按钮：projects/Day-night-toggle-button 的适配版（元素定义见 assets/theme-switch.js） */
  .theme-switch{
    position:relative;flex:none;width:49px;height:19px;display:inline-block;
    border-radius:9.5px;cursor:pointer;-webkit-tap-highlight-color:transparent;
  }
  .theme-switch:focus-visible{outline:2px solid var(--a1);outline-offset:3px;}

  /* ══ 舞台：整屏虚化背景 + 右侧预览卡片 + 浮在上面的文案与轮播 ══ */
  .stage{
    position:relative;isolation:isolate;overflow:hidden;
    min-height:100vh;min-height:100svh;
    display:flex;flex-direction:column;
    padding-top:76px;
  }
  /* 1. 整屏虚化背景：同一张预览图大范围模糊后铺满，两个槽位交叉淡入
     ⚠️ 不要写成「给整屏元素加 filter:blur(52px)」—— 滤镜区域一大，栅格器就会把它
        按 512 设备像素一块切开渲染，块边界上的 clamp 采样会在背景上留下一条**贯穿全高的
        竖直接缝**（先是一段被压平的色带，再接一个一两级的台阶）。手机上尤其明显，
        因为 ColorPicker 那种"大片平滑渐变"的底图最容易把它显出来。
     正解：**先在小画布上模糊，再由合成器放大**。小画布 = 视口的 16%（160%/10），
        模糊半径只有 5.2px —— 画布本身不到一个栅格块，放大 10× 又相当于一次低通，
        接缝根本无从产生；等效到屏幕仍是 52px，观感与原来完全一致（且省一大截 GPU）。
     ⚠️ 小画布的**放大后尺寸要取 160% 视口**，不能图省事写 100%：`object-fit:cover`
        的取景只跟"盒子的宽高比"有关，放大倍数不会改变取景，所以多出来的 60%
        正好变成四周的余量，把模糊在边缘采到透明像素而发白的老毛病一并解决；
        而真正决定"看到图像哪一块"的仍是外层 `.bg` 的 `scale(1.15)`，取景与改前一致。 */
  .bg-stack{position:absolute;inset:0;z-index:0;}
  .bg{position:absolute;inset:0;opacity:0;will-change:opacity,transform;
    transition:opacity 1s ease,transform 1.35s cubic-bezier(.2,.75,.3,1);}
  .bg.in:not(.active){transition:none;opacity:0;
    transform:scale(1.23) translate3d(calc(var(--dir,1) * 1.8%),0,0);}
  .bg.out{opacity:0;transform:scale(1.18) translate3d(calc(var(--dir,1) * -1.8%),0,0);
    transition:opacity .8s ease,transform 1.05s ease;}
  .bg.active{opacity:1;transform:scale(1.15) translate3d(0,0,0);}
  .bg img{position:absolute;left:50%;top:50%;
    width:calc(160% / var(--bg-scale));height:calc(160% / var(--bg-scale));
    transform:translate(-50%,-50%) scale(var(--bg-scale));
    object-fit:cover;object-position:50% 42%;
    filter:blur(var(--bg-blur)) saturate(1.25);}
  [data-theme="light"] .bg img{filter:blur(var(--bg-blur)) saturate(1.15) brightness(1.04);}
  [data-theme="dark"] .bg img{filter:blur(var(--bg-blur)) saturate(1.1) brightness(.52);}

  /* 2. 项目色极光：给预览图蒙一层该项目的色彩
     ⚠️ 与 .bg 同理，`::before` 上的 blur(30px) 也不要直接压在一个比视口还大的盒子上
        （原 `inset:-8% -6%` = 1308×2937 设备像素，跨好几个栅格块）。
        这里用**等价缩放**：盒子整体缩到 1/--aurora-scale 再放大回来，
        渐变全用百分比定位，所以颜色分布**几何完全不变**，
        而模糊半径同比例缩小（30/scale）→ 屏幕效果一致，栅格尺寸掉进一个块以内。 */
  .aurora{position:absolute;inset:0;z-index:1;pointer-events:none;overflow:hidden;}
  .aurora-layer{position:absolute;left:50%;top:50%;
    width:calc(112% / var(--aurora-scale));height:calc(116% / var(--aurora-scale));
    transform:translate(-50%,-50%) scale(var(--aurora-scale));
    opacity:0;transition:opacity 1.15s ease;
    mix-blend-mode:var(--aurora-blend);}
  .aurora-layer.active{opacity:var(--aurora-opacity);}
  .aurora-layer::before{
    content:"";position:absolute;inset:0;
    background:
      radial-gradient(46% 50% at 16% 20%, var(--b1), transparent 68%),
      radial-gradient(50% 46% at 74% 24%, var(--b2), transparent 66%),
      radial-gradient(58% 58% at 48% 96%, var(--b3), transparent 70%),
      radial-gradient(42% 42% at 96% 74%, var(--b1), transparent 72%),
      /* 最后一条专门兜住最下沿：预览图底部往往是留白，虚化后发白，靠它把颜色一直送到页脚分割线 */
      radial-gradient(90% 44% at 50% 108%, var(--b3), transparent 82%);
    filter:blur(var(--aurora-blur)) saturate(125%);
  }

  /* 3. 可读性蒙版：背景已虚化，只在左侧与顶部轻压；**底部不压**，背景色才能一路铺到页脚分割线 */
  .scrim{position:absolute;inset:0;z-index:2;pointer-events:none;
    background:
      linear-gradient(100deg,
        color-mix(in srgb,var(--bg) 94%,transparent) 0%,
        color-mix(in srgb,var(--bg) 84%,transparent) 20%,
        color-mix(in srgb,var(--bg) 46%,transparent) 40%,
        color-mix(in srgb,var(--bg) 12%,transparent) 58%,
        transparent 74%),
      linear-gradient(180deg,
        color-mix(in srgb,var(--bg) 84%,transparent) 0%,
        color-mix(in srgb,var(--bg) 30%,transparent) 12%,
        transparent 22%);
  }
  .aurora-grain{position:absolute;inset:0;z-index:2;opacity:var(--grain);mix-blend-mode:soft-light;pointer-events:none;
    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='.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
    background-size:140px 140px;}

  /* 4. 文案列（两个槽位叠在同一个网格单元里，只亮激活的那个） */
  .stage-wrap{position:relative;z-index:3;flex:1;display:grid;align-items:center;padding-top:16px;padding-bottom:10px;}
  .stage-main{display:grid;grid-template-columns:minmax(0,520px) minmax(0,1fr);
    align-items:center;gap:36px;}
  .copy-stack{display:grid;align-items:center;}
  .copy{grid-area:1/1;opacity:0;pointer-events:none;will-change:opacity,transform;
    transition:opacity .5s ease,transform .72s cubic-bezier(.2,.78,.3,1);}
  .copy.in:not(.active){transition:none;opacity:0;transform:translateX(calc(var(--dir,1) * 52px));}
  .copy.out{opacity:0;transform:translateX(calc(var(--dir,1) * -74px));
    transition:opacity .3s ease,transform .52s cubic-bezier(.4,0,.7,.2);}
  .copy.active{opacity:1;transform:none;pointer-events:auto;}

  /* 5. 右侧清晰的预览卡片（靠右放，尺寸克制造型，不与左侧文字抢位） */
  .art-stack{display:grid;align-items:center;justify-items:end;min-width:0;}
  .art{grid-area:1/1;position:relative;width:min(100%,560px,calc(66vh - 40px));
    pointer-events:none;will-change:opacity,transform;
    transition:opacity .5s ease,transform .82s cubic-bezier(.16,.86,.3,1);}
  .art.in:not(.active){
    transition:none;opacity:0;
    transform:perspective(1500px) translateX(calc(var(--dir,1) * 68px))
      rotateY(calc(var(--dir,1) * 16deg)) rotateX(6deg) rotate(-2deg) scale(.95);
  }
  .art.out{
    opacity:0;
    transform:perspective(1500px) translateX(calc(var(--dir,1) * -68px))
      rotateY(calc(var(--dir,1) * -16deg)) rotateX(6deg) rotate(-2deg) scale(.95);
    transition:opacity .42s ease,transform .62s cubic-bezier(.5,0,.75,.2);
  }
  .art.active{
    opacity:1;pointer-events:auto;
    transform:perspective(1500px) translateX(0) rotateY(-8deg) rotateX(4deg) rotate(-2.2deg) scale(1);
  }
  /* 预览卡片本体。⚠️ 鼠标跟随倾斜必须加在**这一层**，不能加在外层 .art：
     .art 的 transform 已经被三件事占满 —— .in/.out（进场方位）、.active（静态姿态）、
     以及那条 .82s 的过渡曲线。tilt 写进去既会被覆盖，又会被过渡拖出明显迟滞。
     这里只读 --rx/--ry/--tscale（由 JS 逐帧写），只改 transform，不触发布局。 */
  .poster{position:relative;display:block;border-radius:18px;padding:10px;background:var(--card);
    border:1px solid color-mix(in srgb,var(--card) 55%,var(--border));
    /* 阴影随倾角：原来的 0 / 44px / 14px 换成带 --shx/--shy 的算式。
       卡片被抬起的那一侧离地，影子要往反方向跑，所以位移量由 JS 取负号传进来。
       触摸设备上两个变量缺省为 0，算式退化成改动前的原值（逐字节相同）。 */
    box-shadow:
      var(--shx,0px) calc(44px + var(--shy,0px)) 90px -44px rgba(24,18,60,.5),
      calc(var(--shx,0px) * .6) calc(14px + var(--shy,0px) * .6) 34px -20px rgba(24,18,60,.34);}
  /* 3D 层只在精确指针设备上才需要挂 —— 带 transform 的子树会被提为独立合成层，
     实测会让卡片内部高对比边缘出现不到 1 级的亚像素重采样差异（145/3.1M 像素）。
     触摸设备根本不会写 --rx/--ry，那就干脆别加，保证手机端与改动前逐像素一致。 */
  @media (hover:hover) and (pointer:fine) and (prefers-reduced-motion: no-preference){
    .poster{transform:perspective(1500px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg)) scale(var(--tscale,1));}
  }
  .poster img{width:100%;aspect-ratio:16/10;object-fit:cover;border-radius:10px;background:var(--bg-2);}
  /* 高光扫过：光斑中心跟着鼠标走，由 --tilt-shine 开关（默认 0 = 完全不出现）。
     用 mix-blend-mode:soft-light 而不是直接叠白，才不会把预览图洗灰。
     .poster 带 transform，本身就是层叠上下文，混合范围只会限制在卡片内部。 */
  .poster::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
    background:radial-gradient(240px 240px at var(--mx,50%) var(--my,50%),
      rgba(255,255,255,.62), rgba(255,255,255,0) 72%);
    mix-blend-mode:soft-light;opacity:0;transition:opacity .3s ease;}
  .poster.hot::after{opacity:calc(var(--tilt-shine) * .95);}

  .eyebrow{display:flex;align-items:center;gap:14px;font-size:.72rem;letter-spacing:.3em;
    text-transform:uppercase;font-weight:600;color:var(--muted);margin-bottom:16px;}
  .eyebrow .rule{width:66px;height:1px;background:linear-gradient(90deg,currentColor,transparent);}
  .slide-title{font-family:"Space Grotesk",sans-serif;font-weight:700;letter-spacing:-1.2px;
    font-size:clamp(1.85rem,3.5vw,2.95rem);line-height:1.06;}
  /* 标题第一行 + 原创/非原创标签同行 —— 标签不再单独占一行 */
  .slide-title .title-top{display:flex;align-items:center;gap:14px;flex-wrap:wrap;}
  .slide-title .en{color:var(--ink);}
  .slide-title .cn{display:block;background:linear-gradient(100deg,var(--a1),var(--a2));
    -webkit-background-clip:text;background-clip:text;color:transparent;padding-bottom:.06em;}
  [data-theme="dark"] .slide-title .cn{filter:brightness(1.22) saturate(1.05);}

  /* 原创 / 非原创 标签：非原创是可点击外链按钮（点击跳原项目），原创只是标识 */
  .title-badge{display:inline-flex;align-items:center;gap:5px;flex:none;
    padding:5px 11px;border-radius:999px;line-height:1;letter-spacing:0;white-space:nowrap;
    font-family:"Inter",system-ui,-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;
    font-size:.72rem;font-weight:600;
    background:var(--chip);border:1px solid var(--border);color:var(--muted);
    backdrop-filter:blur(8px) saturate(140%);
    transition:color .22s,border-color .22s,background .22s,transform .22s;}
  .title-badge svg{width:12px;height:12px;flex:none;}
  [data-theme="dark"] .title-badge.original{color:#dbe0e8;}
  a.title-badge{color:var(--a1);border-color:color-mix(in srgb,var(--a1) 40%,var(--border));}
  a.title-badge svg:last-child{opacity:.72;transition:transform .22s,opacity .22s;}
  a.title-badge:hover{color:var(--ink);background:var(--card);transform:translateY(-1px);
    border-color:color-mix(in srgb,var(--ink) 26%,var(--border));}
  a.title-badge:hover svg:last-child{opacity:1;transform:translate(2px,-2px);}
  a.title-badge:focus-visible{outline:2px solid var(--a1);outline-offset:2px;}

  .lede{margin-top:16px;color:var(--muted);font-size:.98rem;max-width:44ch;
    display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;}

  .cta{display:inline-flex;align-items:center;gap:9px;margin-top:22px;padding:12px 22px;
    border-radius:999px;color:#fff;font-weight:600;font-size:.92rem;
    background:linear-gradient(100deg,var(--a1),var(--a2));
    box-shadow:0 16px 34px -14px color-mix(in srgb,var(--a1) 78%,transparent);
    transition:transform .26s cubic-bezier(.2,.7,.3,1),box-shadow .26s;}
  .cta:hover{transform:translateY(-2px);box-shadow:0 22px 40px -14px color-mix(in srgb,var(--a1) 88%,transparent);}
  .cta svg{width:16px;height:16px;transition:transform .26s;}
  .cta:hover svg{transform:translateX(4px);}

  /* 页码（原来这里还有一条横着的进度条，现已迁到下方圆点指示器上，见 .dots） */
  .meter{display:flex;align-items:center;gap:14px;margin-top:26px;}
  .meter .num{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.8rem;
    letter-spacing:.08em;color:var(--muted);font-variant-numeric:tabular-nums;}
  .meter .num b{color:var(--ink);font-weight:600;}

  /* ── 浮在预览图上的轮播带（无底色、无分割线） ───── */
  .band{position:relative;z-index:3;margin-top:auto;}
  .band-inner{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:16px;
    padding-top:10px;padding-bottom:2px;}
  .nav-btn{width:42px;height:42px;border-radius:50%;flex:none;
    background:color-mix(in srgb,var(--card) 82%,transparent);border:1px solid var(--border);
    backdrop-filter:blur(12px) saturate(150%);box-shadow:var(--shadow-1);
    display:grid;place-items:center;color:var(--muted);
    transition:transform .25s cubic-bezier(.2,.7,.3,1),color .25s,box-shadow .25s;}
  .nav-btn:hover{color:var(--ink);transform:scale(1.08);box-shadow:var(--shadow-2);}
  .nav-btn:active{transform:scale(.95);}
  .nav-btn svg{width:18px;height:18px;}
  /* padding-bottom 必须 ≥ 缩略图阴影的可见下探量（含 scale 放大后的增量），
     否则阴影被容器齐平裁断成一条硬线 —— 实测 24px 是「阴影可见 + 不留空档」的临界值 */
  .rail{display:flex;align-items:center;justify-content:center;gap:14px;
    overflow-x:auto;overflow-y:hidden;padding:8px 4px 24px;
    scrollbar-width:none;-ms-overflow-style:none;}
  .rail::-webkit-scrollbar{display:none;}
  .thumb{flex:0 0 auto;width:142px;padding:7px;border-radius:15px;text-align:left;
    border:1px solid var(--border);
    background:color-mix(in srgb,var(--card) 84%,transparent);
    backdrop-filter:blur(12px) saturate(150%);
    transition:transform .5s cubic-bezier(.2,.8,.3,1),background .3s ease,border-color .3s ease,box-shadow .3s ease;}
  .thumb img{width:100%;aspect-ratio:16/10;object-fit:cover;border-radius:9px;
    filter:saturate(.9);transition:filter .35s ease;}
  .thumb .t-title{display:block;margin-top:8px;font-size:.8rem;font-weight:600;color:var(--muted);
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:color .3s;}
  .thumb .t-sub{display:block;font-size:.71rem;color:var(--faint);white-space:nowrap;
    overflow:hidden;text-overflow:ellipsis;transition:color .3s;}
  /* 缩略图两行都同时放着 en / cn，由 CSS 决定谁是主标题、谁是副标题：
     桌面/平板 = 英文名 + 中文名；窄屏换过来（122px 的卡里英文名会被截断） */
  .thumb .t-cn,.thumb .s-en{display:none;}
  .thumb:hover{background:color-mix(in srgb,var(--card) 94%,transparent);}
  .thumb.active{transform:scale(1.07);background:var(--card);z-index:2;
    border-color:color-mix(in srgb,var(--a1) 42%,var(--border));box-shadow:var(--shadow-thumb-active);}
  .thumb.active img{filter:none;}
  .thumb.active .t-title{color:var(--ink);}
  .thumb.active .t-sub{color:var(--a1);}
  .thumb:focus-visible,.nav-btn:focus-visible{outline:2px solid var(--a1);outline-offset:2px;}

  /* 页面指示器 = 倒计时进度条本体。
     激活项是一条 20px 的小长条（"轨道"），里面的 <i> 是进度填充：
     10s 内从左往右填满，正好与自动播放同步 —— 填满的瞬间就换页。
     ⚠️ 所以激活项**不能**再直接把 linear-gradient 写在 background 上（原来就是这么写的），
     那样填充就看不出来了；渐变必须挪到 <i> 里。
     颜色与原来那条进度条完全一致（同一个 linear-gradient(90deg,var(--a1),var(--a2))）。 */
  .dots{display:flex;justify-content:center;gap:7px;padding-bottom:14px;}
  .dots button{position:relative;width:6px;height:6px;border-radius:999px;overflow:hidden;
    background:color-mix(in srgb,var(--ink) 22%,transparent);
    box-shadow:0 0 0 1px color-mix(in srgb,var(--bg) 40%,transparent);
    padding:0;transition:width .35s cubic-bezier(.2,.7,.3,1),background .3s;}
  .dots button:hover{background:color-mix(in srgb,var(--ink) 38%,transparent);}
  .dots button.active{width:20px;}
  /* 填充：overflow:hidden 会把矩形填充裁成圆角，所以不用另写 border-radius */
  .dots button i{position:absolute;inset:0;transform-origin:left;transform:scaleX(0);
    background:linear-gradient(90deg,var(--a1),var(--a2));}
  .dots button i.run{animation:meterFill 10s linear forwards;}
  /* 只有"正在倒计时的那一条"会塌回去，其它本来就没填过；给个短过渡让换页时收得自然些 */
  .dots button i:not(.run){transition:transform .3s cubic-bezier(.2,.7,.3,1);}
  @keyframes meterFill{from{transform:scaleX(0);}to{transform:scaleX(1);}}

  /* ── 页脚（分割线就在这里，舞台背景一路铺到这条线） ── */
  .site-footer{border-top:1px solid var(--border);padding:34px 0 48px;scroll-margin-top:80px;}
  .site-footer .wrap{display:flex;flex-wrap:wrap;gap:16px;align-items:flex-start;justify-content:space-between;}
  .site-footer .about{max-width:56ch;color:var(--muted);font-size:.88rem;}
  .site-footer .about b{color:var(--ink);font-weight:600;}
  .site-footer .meta{display:flex;flex-direction:column;align-items:flex-end;gap:10px;color:var(--muted);font-size:.83rem;}

  /* ── 响应式 ─────────────────────────────────────── */
  @media (max-width:1180px){
    .bg img{object-position:58% 42%;}
  }
  @media (max-width:980px){
    .stage{padding-top:70px;}
    .stage-main{grid-template-columns:minmax(0,1fr);gap:22px;}
    /* 单列后内容整块在剩余空间里垂直居中 —— 否则下面会留出一大段死区 */
    .stage-wrap{align-items:center;padding-top:14px;}
    .art-stack{justify-items:center;}
    .art{width:min(100%,420px,calc(46vh - 24px));}
    .art.active{transform:perspective(1400px) translateX(0) rotateY(-5deg) rotateX(3deg) rotate(-1.5deg) scale(1);}
    .art.in:not(.active){transform:perspective(1400px) translateX(calc(var(--dir,1) * 52px)) rotateY(calc(var(--dir,1) * 12deg)) rotateX(4deg) scale(.95);}
    .art.out{transform:perspective(1400px) translateX(calc(var(--dir,1) * -52px)) rotateY(calc(var(--dir,1) * -12deg)) rotateX(4deg) scale(.95);}
    /* 文案铺满整行，蒙版改成上下加重，保证任何一行都读得清；底沿留色 */
    .scrim{background:
      linear-gradient(180deg,
        color-mix(in srgb,var(--bg) 88%,transparent) 0%,
        color-mix(in srgb,var(--bg) 74%,transparent) 34%,
        color-mix(in srgb,var(--bg) 56%,transparent) 62%,
        color-mix(in srgb,var(--bg) 46%,transparent) 100%);}
    .rail{justify-content:flex-start;}
  }
  /* 窄屏竖屏（手机）：卡片铺满文案列宽、与文字同左缘，并去掉那点旋转 ——
     居中的小斜卡在手机上既不齐整又浪费宽度。平板不适用：720 以上满宽会把舞台撑出视口 */
  @media (max-width:720px) and (orientation:portrait){
    .art-stack{justify-items:stretch;}
    .art{width:auto;}
    .art.active{transform:none;}
    .art.in:not(.active){transform:translateX(calc(var(--dir,1) * 44px)) scale(.97);}
    .art.out{transform:translateX(calc(var(--dir,1) * -44px)) scale(.97);}
    /* 窄屏换一套更浅的阴影，但仍要保留 --shx/--shy 算式：手机上不启用倾斜，
       两个变量缺省为 0，算式退化成原来写死的那两个值 */
    .poster{border-radius:16px;padding:8px;
      box-shadow:
        var(--shx,0px) calc(26px + var(--shy,0px)) 54px -34px rgba(24,18,60,.5),
        calc(var(--shx,0px) * .6) calc(10px + var(--shy,0px) * .6) 24px -16px rgba(24,18,60,.32);}
  }
  @media (max-width:720px){
    :root{--pad:18px;}
    .stage{padding-top:62px;}
    .stage-wrap{padding-top:8px;padding-bottom:8px;}
    .stage-main{gap:18px;}
    .eyebrow{display:none;}          /* 手机上省掉装饰行，首屏更紧凑 */
    .nav{gap:18px;font-size:.85rem;}
    .header-right{gap:16px;}
    .slide-title{letter-spacing:-.8px;font-size:clamp(1.62rem,7vw,2.05rem);}
    .slide-title .title-top{gap:9px;}
    .title-badge{padding:4px 9px;font-size:.68rem;}
    .lede{font-size:.93rem;margin-top:12px;}
    .cta{margin-top:16px;padding:11px 20px;}
    .meter{margin-top:18px;}
    .band-inner{grid-template-columns:minmax(0,1fr);gap:6px;padding-top:8px;}
    .nav-btn{display:none;}
    .rail{gap:10px;padding-top:8px;padding-bottom:24px;}
    .thumb{width:122px;padding:6px;}
    /* 窄屏把主副标题对调：主=中文名，副=英文名（英文名放在 .8rem 的主标题里会被截断） */
    .thumb .t-en,.thumb .s-cn{display:none;}
    .thumb .t-cn,.thumb .s-en{display:inline;}
    .thumb.active{transform:scale(1.05);}
    .dots{padding-bottom:10px;}
    .site-footer .meta{align-items:flex-start;}
  }
  @media (max-width:520px){
    .nav{display:none;}
  }
  /* 横屏矮视口（手机横握 / 矮窗口）：回到左右两栏，卡片才不会被挤到首屏之外；
     标题、行距、缩略图一起收小，把整页压进一屏 */
  @media (max-width:980px) and (orientation:landscape) and (max-height:560px){
    .stage{padding-top:58px;}
    .stage-wrap{padding-top:4px;}
    .stage-main{grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:24px;}
    .art-stack{justify-items:center;}
    .art{width:min(100%,calc(58vh - 20px));}
    .art.active{transform:none;}
    .eyebrow{display:none;}
    .slide-title{font-size:clamp(1.4rem,2.4vw,1.9rem);letter-spacing:-.6px;}
    .lede{-webkit-line-clamp:2;font-size:.9rem;margin-top:10px;}
    .cta{margin-top:12px;padding:10px 18px;font-size:.88rem;}
    .meter{margin-top:12px;}
    .band-inner{grid-template-columns:auto minmax(0,1fr) auto;gap:12px;padding-top:6px;}
    .nav-btn{display:grid;width:36px;height:36px;}
    .rail{gap:10px;padding-top:6px;padding-bottom:22px;}
    .thumb{width:110px;padding:5px;}
    .thumb .t-en,.thumb .s-cn{display:none;}   /* 110px 的卡：主标题换成中文名 */
    .thumb .t-cn,.thumb .s-en{display:inline;}
    .dots{padding-bottom:8px;}
  }
  @media (prefers-reduced-motion:reduce){
    html{scroll-behavior:auto;}
    .copy,.bg,.aurora-layer,.thumb{transition:none !important;}
    /* 减弱动效时不做"扫过去"的动画，但指示器还得看得出是哪一个 —— 直接填满 */
    .dots button i{transition:none;}
    .dots button.active i{animation:none;transform:scaleX(1);}
  }
