/* 首屏 / 连接中加载动画（2×2×2 立方体群，像魔方一样转层）。
 *
 * 放在 public/ 而不是 src/：index.html 的 splash 在 React 之前就要用这套样式，
 * Vite dev 对 /src/*.css 返回的是 JS 包装模块（要 ?direct 才是原始 CSS），
 * 而 ?direct 进 vite build 的结果不确定；public/ 下 dev 按 text/css 原样返回、
 * build 原样拷到 dist/ 根，dev 与 prod 都确定可用。
 *
 * 唯一一份：splash（index.html）与 React 组件（RubikLoader）共用同一套类名。
 * 单块立方体（.glass-cube*，空对话首屏用）不在这里，它仍归 globals.css。
 */

.xr-load {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
}

/* ── 2×2×2 立方体群 ───────────────────────────────────── */

.xr-load-scene {
  /* 固定 3/4 视角，让「转层」看得清；不能 overflow:hidden，转出去的那层会超出外框 */
  perspective: 700px;
}

.xr-load-block {
  --rubik-cube: 30px;
  --rubik-gap: 2px;
  position: relative;
  width: calc(var(--rubik-cube) * 2 + var(--rubik-gap));
  height: calc(var(--rubik-cube) * 2 + var(--rubik-gap));
  transform: rotateX(-24deg) rotateY(-32deg);
  transform-style: preserve-3d;
}

/* 8 块。原点即大方块中心，所以下面的 rotateY/rotateX 天然绕大方块自己的轴转 */
.xr-load-cube {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--rubik-cube);
  height: var(--rubik-cube);
  margin: calc(var(--rubik-cube) / -2) 0 0 calc(var(--rubik-cube) / -2);
  transform: translate3d(var(--x), var(--y), var(--z));
  transform-style: preserve-3d;
}

.xr-load-cube > i {
  position: absolute;
  inset: 0;
  /* 直角：用户点名不要倒角 */
  border-radius: 0;
  border: 1px solid rgba(64, 158, 255, 0.85);
  background: linear-gradient(
    135deg,
    rgba(224, 242, 254, 0.42) 0%,
    rgba(147, 197, 253, 0.36) 45%,
    rgba(96, 165, 250, 0.3) 100%
  );
  box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.3);
}

.xr-load-cube > i:nth-child(1) {
  transform: rotateY(0deg) translateZ(calc(var(--rubik-cube) / 2));
}
.xr-load-cube > i:nth-child(2) {
  transform: rotateY(90deg) translateZ(calc(var(--rubik-cube) / 2));
}
.xr-load-cube > i:nth-child(3) {
  transform: rotateY(180deg) translateZ(calc(var(--rubik-cube) / 2));
}
.xr-load-cube > i:nth-child(4) {
  transform: rotateY(270deg) translateZ(calc(var(--rubik-cube) / 2));
}
.xr-load-cube > i:nth-child(5) {
  transform: rotateX(90deg) translateZ(calc(var(--rubik-cube) / 2));
}
.xr-load-cube > i:nth-child(6) {
  transform: rotateX(-90deg) translateZ(calc(var(--rubik-cube) / 2));
}

/* 转层：水平层 = y=+16 那 4 块（绕 Y 轴），竖直层 = x=+16 那 4 块（绕 X 轴）。
 * 绕固定轴逐段累加，一个周期净变换 = 单位阵（转出去 → 停 → 再转回），循环无缝。
 *
 * ── 铁律：两轴在时间上不许重叠 ──────────────────────────
 * 一块绕哪个轴转，是按它的「基础坐标」写死在 :nth-child 里的（下面的坐标表）。
 * 但 rotate 是在 translate 之**后**作用于该块的，所以一块身上一旦挂着 90°，
 * 它的实际位置就换到了别的坐标上 —— 此时「x=+16 那 4 块」已经不再等于 5/6/8。
 * 如果竖直层恰好在这个时刻开始转，参与者集合就与写死的分配对不上：
 * 该转的没转、不该转的被拽走，看上去就像多复制了几个方块过去。
 *
 * 所以：Y 层整段（0–37.5%）竖直层必须全程 0°，竖直层整段（50–87.5%）水平层
 * 全程 0°。任何两轴同时非零的时刻都不允许存在。以后要加第三、第四次转层，
 * 同样要串行排队，不能交叉。
 *
 * 角度表（8s = 8 段 × 12.5%，每段 1s）：
 *   0%    θy 0    θx 0
 *   12.5% θy 90   θx 0     ← 水平层转出去
 *   25%   θy 90   θx 0     ← 停
 *   37.5% θy 0    θx 0     ← 水平层转回来
 *   50%   θy 0    θx 0
 *   62.5% θy 0    θx 90    ← 竖直层转出去
 *   75%   θy 0    θx 90    ← 停
 *   87.5% θy 0    θx 0     ← 竖直层转回来
 *   100%  θy 0    θx 0
 */

/* 两层都参与（7/8）：任一时刻只有一轴非零，所以直接叠两个 rotate 即可 */
@keyframes xr-rubik-yx {
  0%,
  100% {
    transform: rotateY(0deg) rotateX(0deg) translate3d(var(--x), var(--y), var(--z));
  }
  12.5% {
    transform: rotateY(90deg) rotateX(0deg) translate3d(var(--x), var(--y), var(--z));
  }
  25% {
    transform: rotateY(90deg) rotateX(0deg) translate3d(var(--x), var(--y), var(--z));
  }
  37.5%,
  50% {
    transform: rotateY(0deg) rotateX(0deg) translate3d(var(--x), var(--y), var(--z));
  }
  62.5%,
  75% {
    transform: rotateY(0deg) rotateX(90deg) translate3d(var(--x), var(--y), var(--z));
  }
  87.5% {
    transform: rotateY(0deg) rotateX(0deg) translate3d(var(--x), var(--y), var(--z));
  }
}

/* 只参与水平层（θx 全程为 0）；50% 之后整段静止 */
@keyframes xr-rubik-y {
  0%,
  100% {
    transform: rotateY(0deg) translate3d(var(--x), var(--y), var(--z));
  }
  12.5%,
  25% {
    transform: rotateY(90deg) translate3d(var(--x), var(--y), var(--z));
  }
  37.5% {
    transform: rotateY(0deg) translate3d(var(--x), var(--y), var(--z));
  }
}

/* 只参与竖直层（θy 全程为 0）；50% 之前整段静止 */
@keyframes xr-rubik-x {
  0%,
  50% {
    transform: rotateX(0deg) translate3d(var(--x), var(--y), var(--z));
  }
  62.5%,
  75% {
    transform: rotateX(90deg) translate3d(var(--x), var(--y), var(--z));
  }
  87.5%,
  100% {
    transform: rotateX(0deg) translate3d(var(--x), var(--y), var(--z));
  }
}

/* 坐标（偏移 = (30 + 2) / 2 = 16px）与动画分配：
 *   1,2  (-16,-16,±16)  不动
 *   3,4  (-16,+16,±16)  xr-rubik-y   ← 水平层
 *   5,6  (+16,-16,±16)  xr-rubik-x   ← 竖直层
 *   7,8  (+16,+16,±16)  xr-rubik-yx  ← 两层都参与 */
.xr-load-cube:nth-child(1) { --x: -16px; --y: -16px; --z: -16px; }
.xr-load-cube:nth-child(2) { --x: -16px; --y: -16px; --z: 16px; }
.xr-load-cube:nth-child(3) { --x: -16px; --y: 16px; --z: -16px; animation: xr-rubik-y 8s cubic-bezier(0.65, 0, 0.35, 1) infinite; }
.xr-load-cube:nth-child(4) { --x: -16px; --y: 16px; --z: 16px; animation: xr-rubik-y 8s cubic-bezier(0.65, 0, 0.35, 1) infinite; }
.xr-load-cube:nth-child(5) { --x: 16px; --y: -16px; --z: -16px; animation: xr-rubik-x 8s cubic-bezier(0.65, 0, 0.35, 1) infinite; }
.xr-load-cube:nth-child(6) { --x: 16px; --y: -16px; --z: 16px; animation: xr-rubik-x 8s cubic-bezier(0.65, 0, 0.35, 1) infinite; }
.xr-load-cube:nth-child(7) { --x: 16px; --y: 16px; --z: -16px; animation: xr-rubik-yx 8s cubic-bezier(0.65, 0, 0.35, 1) infinite; }
.xr-load-cube:nth-child(8) { --x: 16px; --y: 16px; --z: 16px; animation: xr-rubik-yx 8s cubic-bezier(0.65, 0, 0.35, 1) infinite; }

/* ── 标识行 + 文案 ────────────────────────────────────── */

.xr-load-id {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}

.xr-load-logo {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  object-fit: contain;
}

.xr-load-word {
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Consolas, Menlo, monospace;
  font-size: 14px;
  line-height: 1;
  letter-spacing: 0.42em;
  /* monospace + 大字距会在末尾多出一格，缩进半格才真正居中 */
  text-indent: 0.42em;
  color: rgba(64, 158, 255, 0.72);
}

/* 状态文案：正文字体（等宽小字在 11px 下笔画会糊），15px/500 是改造前 splash 文案的
 * 原值。line-height:1 必须留：跳动的点用 translateY 位移、不改行高，文字才不会跟着抖。 */
.xr-load-copy {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: inherit;
  font-size: 15px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.01em;
  color: rgba(10, 10, 10, 0.72);
}

/* 省略号位置的三个点，依次跳起。定宽 3 点，不会像逐字出点那样撑动行宽。
 * currentColor 跟着 .xr-load-copy 的文案色走，亮/暗都不必另写覆盖。 */
.xr-load-dots {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  flex-shrink: 0;
  /* 视觉中线比行盒中心略高一点点 */
  transform: translateY(-1px);
}

.xr-load-dots > i {
  width: 4px;
  height: 4px;
  border-radius: 9999px;
  background: currentColor;
  animation: xr-load-dot 1.2s ease-in-out infinite;
}

.xr-load-dots > i:nth-child(2) {
  animation-delay: 0.16s;
}

.xr-load-dots > i:nth-child(3) {
  animation-delay: 0.32s;
}

@keyframes xr-load-dot {
  0%,
  100% {
    transform: translateY(0);
    opacity: 0.4;
  }
  30% {
    transform: translateY(-3px);
    opacity: 1;
  }
}

/* ── 暗色 ────────────────────────────────────────────── */

.dark .xr-load-cube > i {
  border-color: rgba(121, 187, 255, 0.85);
  background: linear-gradient(
    135deg,
    rgba(56, 189, 248, 0.26) 0%,
    rgba(14, 165, 233, 0.2) 50%,
    rgba(2, 132, 199, 0.16) 100%
  );
  box-shadow:
    inset 0 0 10px rgba(125, 211, 252, 0.28),
    0 0 12px rgba(56, 189, 248, 0.28);
}

.dark .xr-load-word {
  color: rgba(121, 187, 255, 0.8);
}

.dark .xr-load-copy {
  color: rgba(255, 255, 255, 0.72);
}
