@import url("./typography.css?v=20260908-1");
/* ───────── 空间层 ─────────
   一间悬浮着 AI 工作台的房间。两处在用：
     · suite.html   —— 内部技术页，整屏直接摆出来
     · solutions.html —— 顶屏，跟着滚动一层层长出来
   所以这套样式必须只有一份。页面各自的差异（尺寸、进场方式、放哪几块面板）
   在各自的 CSS 里覆盖，不要往这里加 if。 */

/* 内部试验页：样式就地写，先不进 pages.css，免得污染正式页面 */

/* ───────── 相机 ─────────
   .cam 是镜头，.world 由 JS 每帧旋转（这就是「转头」），
   .rig 只负责把整个场景按屏幕大小等比缩放
   （scale3d 三轴一起缩，z 深度才不会走样，透视跟着缩，投影结果完全一致）。 */
.cam {
  /* --k 是整个场景的缩放倍数，由 JS 按屏幕尺寸算好写进来。
     CSS 自己算不了：calc(100vw / 1500) 得到的还是长度，不是倍数。 */
  --k: 1;
  --ink: #f6f3ec;
  --dim: rgba(246, 243, 236, 0.78);
  --faint: rgba(246, 243, 236, 0.56);
  --gp: #c2a166;
  --edge: rgba(255, 255, 255, 0.16);
  --mx: 50%; --my: 42%;
  position: relative;
  height: 100svh;
  min-height: 34rem;
  overflow: hidden;
  background: #05080f;
  perspective: calc(1560px * var(--k));
  perspective-origin: 50% 47%;
  opacity: 0;
  transition: opacity 1.2s ease;
}
.cam.is-ready { opacity: 1; }
.world, .rig { position: absolute; inset: 0; transform-style: preserve-3d; }
.rig { transform: scale3d(var(--k), var(--k), var(--k)); }

/* ───────── 环境：一间有纵深的房间，不是一张贴在后面的图 ─────────
   照片挂在 z = -980。透视把它缩到六成左右，200% 正好铺满还多出一圈余量，
   那一圈是留给相机转动的：转到最大角度时也不会露出照片的边。
   （挂得更远并不会更好看——投影缩得更小，就得开更大的倍数，画面反而被裁得更狠。） */
.env {
  position: absolute; left: 50%; top: 50%;
  width: 200%; height: 200%;
  transform: translate(-50%, -50%) translateZ(-980px);
  background: #05080f url('../assets/site/suite.jpg') center / cover no-repeat;
}
.env::after {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(120% 80% at 50% 46%, rgba(5, 8, 15, 0) 28%, rgba(5, 8, 15, 0.6) 100%),
    linear-gradient(180deg, rgba(5, 8, 15, 0.5), rgba(5, 8, 15, 0.1) 40%, rgba(5, 8, 15, 0.74));
}

/* 三团挂在中景的空气光：一团窗外的冷光，两团房间里台灯的暖光。
   它们和照片、和面板都不在同一个深度，相机一动三者速度全不一样——
   「你在房间里」这个感觉是这么来的，不是靠给面板加阴影。 */
.glow { position: absolute; left: 50%; top: 50%; border-radius: 50%; pointer-events: none; }
.g1 { width: 1180px; height: 800px; margin: -400px 0 0 -590px;
      transform: translate3d(-30px, -130px, -800px);
      background: radial-gradient(closest-side, rgba(124, 158, 224, 0.22), rgba(124, 158, 224, 0)); }
.g2 { width: 660px; height: 560px; margin: -280px 0 0 -330px;
      transform: translate3d(-640px, 130px, -660px);
      background: radial-gradient(closest-side, rgba(232, 178, 108, 0.2), rgba(232, 178, 108, 0)); }
.g3 { width: 680px; height: 580px; margin: -290px 0 0 -340px;
      transform: translate3d(680px, 150px, -700px);
      background: radial-gradient(closest-side, rgba(232, 178, 108, 0.22), rgba(232, 178, 108, 0)); }
/* 跟着鼠标走的那一层薄空气，挂在更近一点的地方 */
.air {
  position: absolute; left: 50%; top: 50%;
  width: 150%; height: 150%;
  transform: translate(-50%, -50%) translateZ(-500px);
  background: radial-gradient(46% 40% at var(--mx) var(--my), rgba(122, 152, 214, 0.17), transparent 68%);
  pointer-events: none;
}
/* 中枢打在地上的一小片光。躺平放（rotateX 78°），所以它是「地面」不是「墙」 */
.pool {
  position: absolute; left: 50%; top: 50%;
  width: 1500px; height: 900px; margin: -450px 0 0 -750px;
  transform: translate3d(20px, 468px, -250px) rotateX(78deg);
  background: radial-gradient(closest-side, rgba(194, 161, 102, 0.14), rgba(194, 161, 102, 0.04) 55%, rgba(194, 161, 102, 0));
  pointer-events: none;
}
/* 空气里的浮尘：位置由 JS 撒，z 从 -700 铺到 +500。
   近的一颗相机一动就横扫过去，远的几乎不动——这是最便宜也最有效的纵深提示。 */
.motes { position: absolute; inset: 0; transform-style: preserve-3d; pointer-events: none; }
.motes span {
  position: absolute; left: 50%; top: 50%;
  width: var(--s); height: var(--s); border-radius: 50%;
  background: rgba(246, 243, 236, 0.75);
  box-shadow: 0 0 6px rgba(214, 226, 255, 0.5);
  animation: mote var(--dur) ease-in-out var(--dly) infinite alternate;
  transform: translate3d(var(--x), var(--y), var(--z));
}
@keyframes mote {
  from { transform: translate3d(var(--x), var(--y), var(--z)); opacity: var(--o1); }
  to   { transform: translate3d(calc(var(--x) + var(--dx)), calc(var(--y) + var(--dy)), var(--z)); opacity: var(--o2); }
}

/* ───────── 中枢 ─────────
   悬在工作台后上方的那颗核。三个环各自的倾角不同、转速不同、方向不同，
   都是真的在三维里转（父层 preserve-3d），不是画上去的椭圆。 */
.core {
  /* cz 不能太深：中枢离工作台越远，连线就越接近正对镜头，投影出来只剩一个点 */
  --cx: 14px; --cy: -284px; --cz: -260px;
  position: absolute; left: 50%; top: 50%;
  width: 300px; height: 300px; margin: -150px 0 0 -150px;
  transform: translate3d(var(--cx), var(--cy), var(--cz));
  transform-style: preserve-3d;
  pointer-events: none;
  transition: opacity 0.6s ease, filter 0.6s ease;
}
.c-halo {
  position: absolute; left: 50%; top: 50%; width: 440px; height: 440px; margin: -220px 0 0 -220px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(194, 161, 102, 0.2), rgba(140, 160, 220, 0.07) 46%, rgba(0, 0, 0, 0) 72%);
  animation: halo 6.5s ease-in-out infinite;
}
.c-ring {
  position: absolute; inset: var(--in, 0);
  transform-style: preserve-3d;
  transform: rotateX(var(--tilt)) rotateZ(var(--roll, 0deg));
}
/* 一圈很淡的轨道，让环的形状随时看得见，不用等亮弧转过来 */
.c-ring::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  border: 1px solid rgba(194, 161, 102, 0.16);
}
.c-ring i { position: absolute; inset: 0; transform-style: preserve-3d; animation: coreSpin var(--dur) linear infinite; animation-direction: var(--dir, normal); }
/* 圆锥渐变 + 圆环遮罩 ＝ 一道会转的亮弧。用 border 是做不出渐变的。
   遮罩只盖在这一层，所以轨道上那颗节点（::after）不会被一起裁掉。 */
.c-ring i::before {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(from 0deg,
    rgba(194, 161, 102, 0) 0deg, rgba(194, 161, 102, 0.75) 66deg,
    rgba(246, 243, 236, 0.98) 102deg, rgba(194, 161, 102, 0.3) 150deg, rgba(194, 161, 102, 0) 238deg);
  -webkit-mask: radial-gradient(closest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
  mask: radial-gradient(closest-side, transparent calc(100% - 2px), #000 calc(100% - 2px));
}
/* 轨道上跑着的一颗节点。它在转，所以人一眼能看出这几个环是立体的 */
.c-ring i::after {
  content: ""; position: absolute; right: -3px; top: 50%;
  width: 6px; height: 6px; margin-top: -3px; border-radius: 50%;
  background: #f6f3ec; box-shadow: 0 0 12px rgba(246, 243, 236, 0.95), 0 0 24px rgba(194, 161, 102, 0.7);
}
@keyframes coreSpin { to { transform: rotateZ(360deg); } }
@keyframes halo { 0%, 100% { opacity: 0.62; transform: scale(1); } 50% { opacity: 1; transform: scale(1.06); } }

/* 中枢到各模块的连线。面板在世界里的坐标是写死的，所以线也是死的，
   JS 算一次角度和长度就完事，不用每帧重算。 */
.links { position: absolute; inset: 0; transform-style: preserve-3d; pointer-events: none; }
.link {
  position: absolute; left: 50%; top: 50%;
  width: var(--L); height: 1.5px; margin-top: -0.75px;
  transform-origin: 0 50%;
  transform: translate3d(var(--cx), var(--cy), var(--cz)) rotateY(var(--b)) rotateZ(var(--a));
  background: linear-gradient(90deg, rgba(236, 216, 176, 0.95), rgba(194, 161, 102, 0.45) 52%, rgba(194, 161, 102, 0.12));
  box-shadow: 0 0 7px rgba(194, 161, 102, 0.55);
  opacity: calc(0.85 * var(--o, 1));
  transition: opacity 0.6s ease;
}
/* 沿着线跑的那一小段亮光：这是「中枢在给三个岗位发东西」唯一的说明，不用写字 */
.link::after {
  content: ""; position: absolute; top: -1.5px; left: 0; width: 62px; height: 4px; border-radius: 4px;
  background: linear-gradient(90deg, rgba(246, 243, 236, 0), rgba(255, 252, 244, 1), rgba(246, 243, 236, 0));
  box-shadow: 0 0 14px rgba(246, 243, 236, 0.8);
  animation: flow 4.2s linear var(--d, 0s) infinite;
}
@keyframes flow {
  0%   { transform: translateX(-62px); opacity: 0; }
  12%  { opacity: 1; }
  86%  { opacity: 1; }
  100% { transform: translateX(var(--L)); opacity: 0; }
}

/* ───────── 面板通用 ─────────
   每块面板只声明自己在世界里的坐标和朝向，位移由变量拼装，
   悬停时只改 --hz（往相机方向走一步），不碰其他任何值。 */
[data-panel] {
  position: absolute; left: 50%; top: 50%;
  transform:
    translate(-50%, -50%)
    translate3d(var(--px, 0px), var(--py, 0px), calc(var(--pz, 0px) + var(--hz, 0px)))
    rotateY(var(--ry, 0deg)) rotateX(var(--rx, 0deg));
  transform-style: preserve-3d;
  transition: transform 0.85s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.6s ease, filter 0.6s ease;
  color: var(--ink);
}
.glass {
  background:
    linear-gradient(158deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.02) 42%, rgba(255, 255, 255, 0.05)),
    rgba(8, 13, 26, 0.44);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  backdrop-filter: blur(22px) saturate(150%);
  border: 1px solid var(--edge);
  border-radius: 18px;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.2),
    inset 0 0 40px rgba(255, 255, 255, 0.03),
    0 40px 90px -40px rgba(0, 0, 0, 0.9);
}
/* 玻璃上那道跟着鼠标走的高光。放伪元素上，不影响里面的字 */
.glass::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(150% 120% at var(--mx) var(--my), rgba(255, 255, 255, 0.11), transparent 55%);
  opacity: 0.85;
}
.glass > * { position: relative; }

/* Phase 2：指哪一块，哪一块走近、变大、变清楚；其余的往后退半步 */
@media (hover: hover) and (pointer: fine) {
  [data-panel]:hover { --hz: 68px; }
  .cam.is-hover [data-panel]:not(:hover) { opacity: 0.6; filter: saturate(0.85); }
  .cam.is-hover .core { opacity: 0.5; }
}

/* ───────── 左：导航 ───────── */
.rail { --px: -540px; --py: -6px; --pz: -190px; --ry: 21deg; --rx: 2deg; width: 214px; padding: 10px; }
/* 这两块正好挂在房间两盏台灯前面，会被灯冲白，所以背衬压深一档 */
.rail.glass, .notes.glass { background:
  linear-gradient(158deg, rgba(255,255,255,0.1), rgba(255,255,255,0.02) 42%, rgba(255,255,255,0.05)),
  rgba(7, 12, 24, 0.54); }
.rail a {
  display: block; padding: 10px 12px; border-radius: 11px;
  color: var(--dim); text-decoration: none; font-size: 14px; line-height: 1.5;
  transition: background 0.35s ease, color 0.35s ease;
}
.rail a:hover { color: var(--ink); background: rgba(255, 255, 255, 0.08); }
.rail a.on { color: var(--ink); background: rgba(194, 161, 102, 0.17); box-shadow: inset 0 0 0 1px rgba(194, 161, 102, 0.36); }

/* ───────── 中：工作台 ───────── */
.deck { --px: 26px; --py: 18px; --pz: 40px; --ry: -1deg; width: 748px; padding: 20px 20px 22px; }
/* 工作台正好压在窗外最亮的一段城市上，所以它比别的玻璃再深一档 */
.deck.glass { background:
  linear-gradient(158deg, rgba(255,255,255,0.1), rgba(255,255,255,0.02) 42%, rgba(255,255,255,0.05)),
  rgba(7, 12, 24, 0.56); }
.d-head { display: flex; align-items: center; gap: 13px; margin-bottom: 17px; }
.d-head .logo { width: 38px; height: 38px; border-radius: 10px; display: grid; place-items: center; background: rgba(255,255,255,0.07); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.13); }
.d-head .logo img { width: 21px; height: 21px; object-fit: contain; }
.d-head h1 { font-size: 19px; font-weight: 600; letter-spacing: 0.01em; margin: 0; line-height: 1.2; }
.chip {
  margin-left: auto; white-space: nowrap;
  font-size: 11.5px; color: rgba(246, 243, 236, 0.8);
  border: 1px solid rgba(255, 255, 255, 0.18); border-radius: 999px; padding: 5px 12px;
  display: inline-flex; align-items: center; gap: 7px;
}
.chip i { width: 5px; height: 5px; border-radius: 50%; background: #83d8a6; display: block; box-shadow: 0 0 8px #83d8a6; }

.mods { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 13px; }
.mod {
  position: relative;
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 13px; padding: 14px 14px 15px;
  cursor: pointer;
  transform-style: preserve-3d;
  transition: transform 0.75s cubic-bezier(0.16, 1, 0.3, 1), background 0.4s ease,
              border-color 0.4s ease, opacity 0.5s ease, filter 0.5s ease;
}
.mod:hover { background: rgba(255, 255, 255, 0.095); border-color: rgba(194, 161, 102, 0.42); transform: translateZ(34px); }
.mod:focus-visible { outline: 2px solid var(--gp); outline-offset: 4px; }
.m-key { display: block; font-size: 10.5px; letter-spacing: 0.14em; color: rgba(194, 161, 102, 0.95); margin-bottom: 7px; font-family:var(--tevo-cjk); }
.mod h2 { font-size: 14.5px; font-weight: 600; margin: 0; line-height: 1.35; }
/* 右上角那个十字：告诉人这块能点开，省掉一句「点击查看详情」 */
.m-plus {
  position: absolute; right: 12px; top: 13px; width: 13px; height: 13px;
  opacity: 0.5; transition: opacity 0.3s ease, transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.m-plus::before, .m-plus::after {
  content: ""; position: absolute; left: 50%; top: 50%; background: var(--gp);
}
.m-plus::before { width: 11px; height: 1px; margin: -0.5px 0 0 -5.5px; }
.m-plus::after  { width: 1px; height: 11px; margin: -5.5px 0 0 -0.5px; }
.mod:hover .m-plus { opacity: 1; }
.mod.is-focus .m-plus { opacity: 1; transform: rotate(45deg); }

.viz { margin-top: 11px; display: grid; gap: 6px; font-family:var(--tevo-cjk); }
.vb { display: flex; align-items: center; gap: 7px; font-size: 11px; color: var(--dim); }
.vb > span:first-child { width: 26px; flex: none; }
.vb .g { flex: 1; height: 3px; border-radius: 2px; background: rgba(255, 255, 255, 0.14); overflow: hidden; }
.vb .g i { display: block; height: 100%; width: var(--w, 60%); background: var(--gp); border-radius: 2px; }
.vb b { font-size: 11.5px; color: var(--ink); font-weight: 600; }
.vl { display: flex; align-items: center; gap: 7px; font-size: 11px; line-height: 1.6; color: var(--dim); }
.vl::before { content: ""; width: 7px; height: 7px; border-radius: 2px; flex: none; border: 1px solid rgba(255, 255, 255, 0.32); }
.vl.ok::before { background: rgba(131, 216, 166, 0.9); border-color: transparent; }
.vl.no::before { background: rgba(216, 149, 131, 0.9); border-color: transparent; }

/* 展开的说明挂在模块下方浮着——不撑开格子，所以整块工作台不会跳。
   说明比模块本身宽：一栏宽度里中文几乎每行都在断，读着累。
   三块各自贴边，不会跑出工作台外面。 */
.mod:nth-child(1) .m-more { left: 0; }
.mod:nth-child(2) .m-more { left: -36%; }
.mod:nth-child(3) .m-more { left: -72%; }
.m-more {
  position: absolute; width: 172%; right: auto; top: calc(100% + 11px);
  padding: 14px 15px 15px; border-radius: 13px;
  background: linear-gradient(158deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.03)), rgba(9, 14, 28, 0.68);
  -webkit-backdrop-filter: blur(22px); backdrop-filter: blur(22px);
  border: 1px solid rgba(194, 161, 102, 0.34);
  box-shadow: 0 30px 60px -30px rgba(0, 0, 0, 0.9);
  transform: translateZ(26px) translateY(-10px);
  opacity: 0; pointer-events: none; visibility: hidden;
  transition: opacity 0.5s ease, transform 0.6s cubic-bezier(0.16, 1, 0.3, 1), visibility 0.5s;
  font-size: 12px; line-height: 1.9; color: var(--dim);
}
.m-more p { margin: 0 0 8px; }
.m-more .edge { color: var(--ink); }
.m-more .edge b { color: var(--gp); font-weight: 600; }
.m-more a { color: var(--gp); text-decoration: none; font-size: 12px; }
.m-more a:hover { text-decoration: underline; }
.mod.is-focus .m-more { opacity: 1; pointer-events: auto; visibility: visible; transform: translateZ(26px) translateY(0); }
.mod.is-focus { background: rgba(255, 255, 255, 0.1); border-color: rgba(194, 161, 102, 0.6); transform: translateZ(46px) scale(1.04); z-index: 3; }
.cam.is-focus .mod:not(.is-focus) { opacity: 0.24; filter: blur(2.5px); }
.cam.is-focus .rail, .cam.is-focus .notes { opacity: 0.3; filter: blur(2px); }
.cam.is-focus .fde { opacity: 0.16; filter: blur(2px); }
.cam.is-focus .dock, .cam.is-focus .edge-card { opacity: 0.22; filter: blur(2px); --hz: -70px; }
.cam.is-focus .core { opacity: 0.28; filter: blur(3px); }
.cam.is-focus .link { opacity: 0.12; }

/* 底下那条横的：四阶段交付 */
.fde {
  margin-top: 13px; padding: 12px 14px; border-radius: 13px;
  background: rgba(255, 255, 255, 0.045); border: 1px solid rgba(255, 255, 255, 0.09);
  display: flex; align-items: center; gap: 14px;
  transition: opacity 0.5s ease, filter 0.5s ease;
}
.fde .f-t { flex: none; font-size: 13px; font-weight: 600; }
.fde ol { list-style: none; margin: 0; padding: 0; display: flex; gap: 8px; flex: 1; }
.fde li {
  flex: 1; font-size: 11px; color: var(--dim); padding: 6px 8px; border-radius: 8px;
  background: rgba(255, 255, 255, 0.05); text-align: center; white-space: nowrap;
}
.fde li em { font-style: normal; color: rgba(194, 161, 102, 0.9); font-family:var(--tevo-cjk); margin-right: 5px; font-size: 10px; }

/* ───────── 右：说明 ───────── */
.notes { --px: 562px; --py: -58px; --pz: -240px; --ry: -23deg; --rx: 3deg; width: 246px; padding: 16px 16px 17px; }
.notes h2 { font-size: 14px; font-weight: 600; margin: 0 0 2px; }
.notes .n-sub { margin: 0 0 12px; font-size: 11px; color: var(--faint); }
.notes p.n-b { margin: 0; font-size: 12px; line-height: 1.9; color: var(--dim); }
.notes p.n-b b { color: var(--ink); font-weight: 500; }
.n-div { height: 1px; background: rgba(255, 255, 255, 0.12); margin: 13px 0 11px; }
.n-list { list-style: none; margin: 0 0 11px; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 5px 10px; }
.n-list li { font-size: 11px; color: var(--dim); display: flex; align-items: center; gap: 6px; }
.n-list li::before { content: ""; width: 3px; height: 3px; border-radius: 50%; background: var(--gp); flex: none; }
.notes a { color: var(--gp); text-decoration: none; font-size: 12px; }
.notes a:hover { text-decoration: underline; }

/* ───────── 前景：联络条 + 最重的那句话 ───────── */
.dock { --px: 8px; --py: 288px; --pz: 330px; --rx: -9deg; border-radius: 999px; padding: 7px; }
.dock ul { list-style: none; margin: 0; padding: 0; display: flex; align-items: center; gap: 3px; }
.dock a {
  display: block; padding: 8px 17px; border-radius: 999px; white-space: nowrap;
  color: var(--dim); text-decoration: none; font-size: 12.5px;
  transition: background 0.3s ease, color 0.3s ease;
}
.dock a:hover { color: var(--ink); background: rgba(255, 255, 255, 0.1); }
.dock a.lead { color: #101725; background: var(--ink); font-weight: 500; }
.dock a.lead:hover { background: #fff; }

.edge-card { --px: -452px; --py: 292px; --pz: 246px; --ry: 9deg; --rx: -6deg; width: 262px; padding: 13px 15px; border-radius: 14px; }
.edge-card span { display: block; font-size: 10.5px; letter-spacing: 0.12em; color: rgba(194, 161, 102, 0.95); margin-bottom: 6px; font-family:var(--tevo-cjk); }
.edge-card p { margin: 0; font-size: 12.5px; line-height: 1.75; color: var(--ink); }

/* ───────── 贴在屏幕上的东西（不进 3D） ───────── */
.mark-note, .scroll-cue {
  position: absolute; z-index: 4; font-size: 11.5px; letter-spacing: 0.07em;
  color: rgba(246, 243, 236, 0.44); font-family:var(--tevo-cjk);
}
.mark-note { right: 2.2rem; bottom: 1.5rem; }
.scroll-cue {
  left: 50%; bottom: 1.3rem; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 5px;
}
.scroll-cue i { display: block; width: 1px; height: 22px; background: linear-gradient(rgba(246,243,236,0), rgba(246,243,236,0.5)); animation: cue 2.6s ease-in-out infinite; }
@keyframes cue { 0%, 100% { opacity: 0.3; transform: scaleY(0.6); transform-origin: top; } 50% { opacity: 1; transform: scaleY(1); } }

/* ───────── 进场：房间先亮，中枢再点起来，面板最后从深处飞进来 ───────── */
.cam:not(.is-in) [data-panel] { opacity: 0; --hz: -320px; }
.cam:not(.is-in) .env { opacity: 0; transform: translate(-50%, -50%) translateZ(-980px) scale(1.06); }
.cam:not(.is-in) .core { opacity: 0; transform: translate3d(var(--cx), var(--cy), calc(var(--cz) - 420px)); }
.cam:not(.is-in) .link { opacity: 0; }
.cam:not(.is-in) .motes { opacity: 0; }
.env { transition: opacity 1.6s ease, transform 2.4s cubic-bezier(0.16, 1, 0.3, 1); }
.core { transition: opacity 1.4s ease 0.5s, transform 1.8s cubic-bezier(0.16, 1, 0.3, 1) 0.4s, filter 0.6s ease; }
.link { transition: opacity 1.2s ease 1.3s; }
.motes { transition: opacity 2s ease 0.8s; }
[data-panel] { transition-delay: var(--d, 0s); }
.deck { --d: 0.5s; } .rail { --d: 0.7s; } .notes { --d: 0.8s; }
.dock { --d: 0.95s; } .edge-card { --d: 1.05s; }
/* 进场跑完就把延迟清掉，否则悬停也要等半秒才反应 */
.cam.is-settled [data-panel] { transition-delay: 0s; }
.cam.is-settled .core { transition-delay: 0s; }

/* ───────── 窄屏：不做 3D，摊平了照样能读 ───────── */
@media (max-width: 1080px), (max-height: 620px) {
  .cam { height: auto; min-height: 0; padding: 6.5rem 1.1rem 3rem; perspective: none; background: #070c16; }
  .world, .rig { position: relative; inset: auto; transform: none !important; transform-style: flat; }
  .rig { display: grid; gap: 1rem; max-width: 34rem; margin: 0 auto; }
  .env { position: fixed; inset: 0; width: 100%; height: 100%; transform: none; opacity: 0.5; }
  .env::after { background: linear-gradient(180deg, rgba(5,8,15,0.8), rgba(5,8,15,0.62) 40%, rgba(5,8,15,0.92)); }
  .air, .glow, .pool, .motes, .links { display: none; }
  .core { position: relative; left: auto; top: auto; margin: 0 auto; width: 170px; height: 170px; transform: none !important; opacity: 1 !important; }
  .c-halo { width: 240px; height: 240px; margin: -120px 0 0 -120px; }
  [data-panel] { position: relative; left: auto; top: auto; width: auto; transform: none !important; opacity: 1 !important; }
  .mods { grid-template-columns: 1fr; }
  .fde { flex-direction: column; align-items: flex-start; gap: 9px; }
  .fde ol { width: 100%; }
  .fde li { font-size: 10.5px; padding: 6px 4px; }
  .m-more { position: relative; left: auto; right: auto; top: auto; margin-top: 10px; transform: none !important;
            display: none; opacity: 1; visibility: visible; pointer-events: auto; }
  .mod.is-focus .m-more { display: block; }
  .cam.is-focus .mod:not(.is-focus), .cam.is-focus .rail, .cam.is-focus .notes, .cam.is-focus .fde,
  .cam.is-focus .core { opacity: 1; filter: none; }
  .dock { border-radius: 14px; }
  .dock ul { flex-wrap: wrap; justify-content: center; }
  .mark-note, .scroll-cue { position: static; display: block; text-align: center; margin: 1rem auto 0; transform: none; }
  .scroll-cue i { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .world { transition: none; }
  [data-panel], .mod, .m-more { transition-duration: 0.01ms; }
  .scroll-cue i, .c-ring i, .c-halo, .motes span, .link::after { animation: none; }
}

/* ───────── 页面下半：给你看的说明 ───────── */
body.suite-page main { padding-top: 0; }
.lab-note { padding: 1.2rem 1.4rem; background: var(--bg-deep); font-size: 0.94rem; line-height: 1.95; color: var(--navy-soft); }
.lab-note b { color: var(--navy); }
.lab-note + .lab-note { margin-top: 1rem; }
.lab-wrap { padding: 4.5rem 0 1rem; }
