/* ==========================================================================
   光屿 · 万算AI（9024）
   guangyu.css —— 站点皮肤层
   --------------------------------------------------------------------------
   只消费 design-system 的令牌，不写死任何色值 / 字号 / 圆角 / 间距。
   业务 JS 生成或依赖的全部类名在这里重新定义，DOM 钩子一个没动。

   气质：创造侧夜蓝 + 靛蓝强调。玻璃拟态保留（这是本站原生气质），
   但底/描边/模糊一律走 token。

   页面切换类名（三个视图各有各的开关，千万别混）：
     .page                 -> .active      （page-home / page-create）
     .gallery-detail-page  -> .show
     .result-page          -> .show
     .generating-overlay   -> .show
   ========================================================================== */

/* ==========================================================================
   0. 本站在共享令牌之上的两个派生量
   --gy-alt 是"图生视频"这一路用的第二强调色。原站是紫 (#7c3aed)，
   这里不用写死色值，而是从 --accent 与 --danger 混出来（≈#AE89BC 柔紫），
   既保住原站"青 vs 紫"的双路辨识，又完全落在令牌体系内。
   ========================================================================== */
.app-shell {
  --gy-alt: color-mix(in srgb, var(--accent) 62%, var(--danger));
  --gy-alt-soft: color-mix(in srgb, var(--gy-alt) 14%, transparent);
  --gy-alt-line: color-mix(in srgb, var(--gy-alt) 40%, transparent);
  --gy-glass: color-mix(in srgb, var(--surface) 78%, transparent);
  --gy-glass-line: color-mix(in srgb, var(--line-strong) 70%, transparent);
}

/* ==========================================================================
   1. 外壳与页面系统
   ========================================================================== */
.app-shell {
  position: relative;
  height: 100vh;
  height: 100dvh;
  max-width: var(--app-max);
  margin-inline: auto;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}
@media (min-width: 560px) {
  .app-shell { box-shadow: var(--shadow-xl); }
}

/* 环境底纹：极淡的网格 + 两团冷光，替代原站的固定渐变 */
.app-shell::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image:
    linear-gradient(color-mix(in srgb, var(--accent) 5%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--accent) 5%, transparent) 1px, transparent 1px);
  background-size: 40px 40px;
}
.app-shell::after {
  content: '';
  position: absolute;
  inset: -20% -30% auto -30%;
  height: 60%;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(ellipse at 28% 0%,
      color-mix(in srgb, var(--accent) 16%, transparent) 0%, transparent 62%),
    radial-gradient(ellipse at 76% 12%,
      color-mix(in srgb, var(--gy-alt) 12%, transparent) 0%, transparent 58%);
}

/* .page 用 absolute 叠放 —— 父级必须是定位上下文，否则三个视图会挤进同一条文档流 */
.app-body {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}

/* .page 用 absolute 叠放 —— 父级必须是定位上下文（.app-shell 已设 relative）。
   这里用 visibility 而非 display 切换，否则过渡动画不会执行。 */
.page {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  z-index: 0;
  transition: opacity var(--dur-3) var(--ease-out),
              transform var(--dur-3) var(--ease-out);
  transform: translateY(10px);
}
.page.active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
  z-index: 1;
}

.page-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  position: relative;
  z-index: 1;
}
.page-scroll::-webkit-scrollbar { display: none; }

/* 顶栏下面的滚动区要避开 sticky 顶栏的遮挡由 flex 天然保证 */
.page > .topbar { position: relative; z-index: 2; }

/* ==========================================================================
   2. 顶栏 / 品牌
   ========================================================================== */
.topbar {
  flex: 0 0 auto;
  gap: var(--s-3);
  padding-inline: var(--s-5);
}
.topbar__inner { display: flex; align-items: center; gap: var(--s-3); min-width: 0; }
.topbar__title {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: var(--fw-semi);
  text-align: left;
  letter-spacing: var(--ls-heading);
}

/* --- 标识：环形 + 无限符号，动效保留但幅度收敛 --- */
.logo-wrap { display: flex; align-items: center; gap: var(--s-3); min-width: 0; }
.logo-svg { width: 34px; height: 34px; flex: 0 0 auto; }
.logo-ring { fill: none; stroke-width: 2; stroke-linecap: round; }
.logo-ring-outer {
  stroke: var(--accent);
  stroke-dasharray: 80 50;
  animation: logoSpin 8s linear infinite;
  transform-origin: 18px 18px;
}
.logo-ring-inner {
  stroke: var(--gy-alt);
  stroke-width: 1.5;
  stroke-dasharray: 40 30;
  animation: logoSpin 6s linear infinite reverse;
  transform-origin: 18px 18px;
}
@keyframes logoSpin { to { transform: rotate(360deg); } }
.logo-infinity {
  fill: none;
  stroke: var(--accent-hi);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 60 60;
  animation: logoDraw 5s cubic-bezier(.45,0,.55,1) infinite;
}
@keyframes logoDraw {
  0%, 100% { stroke-dashoffset: 0; opacity: .85; }
  50% { stroke-dashoffset: -60; opacity: 1; }
}
.logo-flow-line { fill: none; stroke-linecap: round; stroke-width: 1.2; }
.logo-flow-1 { stroke: var(--accent); opacity: .45; stroke-dasharray: 6 14; animation: logoFlow 2.5s linear infinite; }
.logo-flow-2 { stroke: var(--gy-alt); opacity: .45; stroke-dasharray: 8 12; animation: logoFlow 3s linear infinite reverse; }
.logo-flow-3 { stroke: var(--accent); opacity: .28; stroke-dasharray: 4 16; animation: logoFlow 2s linear infinite; }
@keyframes logoFlow { to { stroke-dashoffset: -40; } }
.logo-glow { fill: var(--accent); opacity: .12; animation: logoPulse 4s cubic-bezier(.45,0,.55,1) infinite; }
@keyframes logoPulse { 0%, 100% { opacity: .10; } 50% { opacity: .20; } }
.logo-mirror { fill: var(--accent-hi); opacity: .10; }
.logo-frame-flash { fill: none; stroke: var(--accent-line); stroke-width: .5; stroke-dasharray: 2 8; }

.logo-text-wrap { display: flex; flex-direction: column; line-height: 1; min-width: 0; }
.logo-title {
  font-family: var(--font-display);
  font-size: var(--t-h2);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-heading);
  color: var(--ink);
  margin: 0;
}
.logo-subtitle {
  font-size: var(--t-micro);
  color: var(--faint);
  letter-spacing: var(--ls-caps);
  font-weight: var(--fw-medium);
  margin-top: 3px;
}

/* ==========================================================================
   3. 首页
   ========================================================================== */
/* 页面主张放在作品之上 —— 这样图片不必为了可读性被压暗 */
.home-head {
  padding: 0 var(--s-5) var(--s-5);
}
.home-headline {
  font-family: var(--font-display);
  font-size: var(--t-h1);
  font-weight: var(--fw-semi);
  line-height: var(--lh-heading);
  letter-spacing: var(--ls-display);
  color: var(--ink);
  margin: 0;
}
.home-sub {
  margin-top: var(--s-2);
  font-size: var(--t-sm);
  line-height: var(--lh-body);
  color: var(--muted);
  max-width: 30ch;
}

/* --- 主视觉：整幅作品 + 标题 + CTA + 指示点 --- */
.home-hero {
  margin: 0 var(--s-5) var(--s-5);
  border-radius: var(--r-lg);
  overflow: hidden;
  position: relative;
  aspect-ratio: 4 / 5;
  background: var(--surface-inset);
  border: 1px solid var(--line);
}
.hero-slides {
  position: absolute;
  inset: 0;
  display: flex;
  transition: transform var(--dur-4) var(--ease-soft);
}
/* 整屏轮播：每屏占满容器宽度。
   min-width:0 是必须的 —— flex 项默认 min-width:auto，会被
   .hero-compare-side 的 min-content（aspect-ratio 3/4 × 高度 ≈ 364px，
   两片合计 728px）撑破容器，导致分隔线跑到画面右侧。 */
.hero-slide {
  flex: 0 0 100%;
  min-width: 0;
  position: relative;
}
.hero-slide .media { width: 100%; height: 100%; border-radius: 0; }
.hero-slide .media > img { object-fit: cover; }

.hero-compare { display: flex; height: 100%; }
.hero-compare-side { flex: 1 1 0; min-width: 0; position: relative; overflow: hidden; }
.hero-compare-side .media { height: 100%; border-radius: 0; }
.hero-compare-side .media > img,
.hero-compare-side .media > video { width: 100%; height: 100%; object-fit: cover; }
.hero-compare-divider {
  position: absolute;
  left: 50%; top: 0; bottom: 0;
  width: 1px;
  background: var(--gy-glass-line);
  transform: translateX(-50%);
  z-index: 3;
}
.hero-compare-label {
  position: absolute;
  top: var(--s-3); left: var(--s-3);
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-full);
  font-size: var(--t-micro);
  font-weight: var(--fw-medium);
  color: var(--ink);
  background: var(--gy-glass);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--line);
  z-index: 4;
}
.hero-compare-side:last-child .hero-compare-label { left: auto; right: var(--s-3); }

/* 压罩只盖最底部一条，给 CTA 与指示点做底，不压暗作品本身 */
.home-hero::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 34%;
  z-index: 4;
  pointer-events: none;
  background: linear-gradient(to top,
    color-mix(in srgb, var(--bg) 82%, transparent) 0%,
    color-mix(in srgb, var(--bg) 42%, transparent) 52%,
    transparent 100%);
}
.home-hero-overlay {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-5);
}
.hero-create-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--tap-min);
  padding: 0 var(--s-5);
  border-radius: var(--r-full);
  background: var(--accent);
  color: var(--on-accent);
  font-size: var(--t-sm);
  font-weight: var(--fw-semi);
  transition: background var(--dur-2) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.hero-create-btn:hover { background: var(--accent-hi); }
.hero-create-btn:active { transform: scale(.97); }
.hero-create-btn .icon { width: 17px; height: 17px; }

.hero-dots {
  display: flex;
  gap: var(--s-2);
  align-self: center;
  margin-top: var(--s-1);
}
.hero-dots span {
  width: 6px; height: 6px;
  border-radius: var(--r-full);
  background: var(--line-strong);
  cursor: pointer;
  transition: background var(--dur-2) var(--ease-out),
              width var(--dur-2) var(--ease-out);
}
.hero-dots span.active { background: var(--accent); width: 18px; }

/* --- 两个入口 --------------------------------------------------------- */
.home-quick-actions {
  display: flex;
  gap: var(--s-3);
  margin: 0 var(--s-5) var(--s-6);
}
.quick-action {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-2);
  min-height: 132px;
  padding: var(--s-5) var(--s-4);
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  background: var(--surface);
  text-align: left;
  position: relative;
  overflow: hidden;
  transition: border-color var(--dur-2) var(--ease-out),
              transform var(--dur-1) var(--ease-out);
}
.quick-action:hover { border-color: var(--accent-line); }
.quick-action:active { transform: scale(.98); }
.quick-action::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
}
.quick-action .icon {
  width: 26px; height: 26px;
  margin-bottom: var(--s-1);
}
/* 图生图 —— 走品牌强调色 */
.cyan-action::before { background: var(--accent); }
.cyan-action .icon { color: var(--accent); }
/* 图生视频 —— 走第二强调色，保住原站双路辨识 */
.violet-action::before { background: var(--gy-alt); }
.violet-action .icon { color: var(--gy-alt); }

.quick-action-title {
  font-size: var(--t-h3);
  font-weight: var(--fw-semi);
  color: var(--ink);
  letter-spacing: var(--ls-heading);
}
.quick-action-desc {
  font-size: var(--t-xs);
  line-height: var(--lh-tight);
  color: var(--muted);
  max-width: 22ch;
}

/* --- 区块头 ----------------------------------------------------------- */
.home-section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  margin: 0 var(--s-5) var(--s-3);
}
.home-section-title {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--t-h3);
  font-weight: var(--fw-semi);
  letter-spacing: var(--ls-heading);
  color: var(--ink);
}
.home-section-title .icon { width: 17px; height: 17px; color: var(--accent); }

/* --- 作品库横滑 ------------------------------------------------------- */
.gallery-scroll {
  display: flex;
  gap: var(--s-3);
  margin: 0 0 var(--s-6);
  padding: 0 var(--s-5);
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.gallery-scroll::-webkit-scrollbar { display: none; }
.gallery-scroll > * { scroll-snap-align: start; }

.gallery-item {
  flex: 0 0 auto;
  width: 148px;
  border-radius: var(--r-md);
  overflow: hidden;
  position: relative;
  border: 1px solid var(--line);
  background: var(--surface-inset);
  padding: 0;
  text-align: left;
  transition: border-color var(--dur-2) var(--ease-out),
              transform var(--dur-1) var(--ease-out);
}
.gallery-item:hover { border-color: var(--accent-line); transform: translateY(-2px); }
.gallery-item:active { transform: scale(.97); }
.gallery-item-img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  display: block;
}
.gallery-item-play {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 42px; height: 42px;
  border-radius: var(--r-full);
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid color-mix(in srgb, var(--ink) 22%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  pointer-events: none;
}
.gallery-item-play .icon { width: 18px; height: 18px; }
.gallery-item-bottom {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--s-5) var(--s-3) var(--s-3);
  background: linear-gradient(to top,
    color-mix(in srgb, var(--bg) 92%, transparent) 0%, transparent 100%);
}
.gallery-item-title {
  font-size: var(--t-xs);
  font-weight: var(--fw-medium);
  color: var(--ink);
}

/* ==========================================================================
   4. 创作页
   ========================================================================== */
.mode-switcher {
  display: flex;
  gap: var(--s-1);
  margin: 0 var(--s-5) var(--s-5);
  padding: 3px;
  border-radius: var(--r-md);
  background: var(--surface-inset);
  border: 1px solid var(--line);
}
.mode-btn {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 38px;
  border-radius: var(--r-sm);
  font-size: var(--t-sm);
  font-weight: var(--fw-medium);
  color: var(--muted);
  transition: background var(--dur-2) var(--ease-out),
              color var(--dur-2) var(--ease-out);
}
.mode-btn .icon { width: 17px; height: 17px; }
.mode-btn:hover { color: var(--ink-2); }
.mode-btn.active-img {
  background: var(--accent-soft);
  color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent-line);
}
.mode-btn.active-video {
  background: var(--gy-alt-soft);
  color: var(--gy-alt);
  box-shadow: inset 0 0 0 1px var(--gy-alt-line);
}

/* --- 上传区 ----------------------------------------------------------- */
.upload-section { margin: 0 var(--s-5) var(--s-5); }
.upload-zone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  min-height: 168px;
  padding: var(--s-6) var(--s-5);
  border: 1px dashed var(--accent-line);
  border-radius: var(--r-lg);
  background: var(--surface-inset);
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: border-color var(--dur-2) var(--ease-out),
              background var(--dur-2) var(--ease-out);
}
.upload-zone:hover { border-color: var(--accent); background: var(--accent-soft); }
.upload-zone.video-mode { border-color: var(--gy-alt-line); }
.upload-zone.video-mode:hover { border-color: var(--gy-alt); background: var(--gy-alt-soft); }
.upload-zone.has-image {
  border-style: solid;
  border-color: var(--line-strong);
  padding: 0;
  min-height: 0;
  background: var(--surface-inset);
}
.upload-zone.has-image.video-mode { border-color: var(--gy-alt-line); }

.upload-icon {
  width: 44px; height: 44px;
  border-radius: var(--r-full);
  background: var(--accent-soft);
  color: var(--accent);
}
.upload-icon .icon { width: 22px; height: 22px; }
.upload-icon.violet { background: var(--gy-alt-soft); color: var(--gy-alt); }

.upload-title {
  font-size: var(--t-body);
  font-weight: var(--fw-semi);
  color: var(--ink);
}
.upload-hint {
  font-size: var(--t-xs);
  color: var(--faint);
}

.upload-preview {
  width: 100%;
  aspect-ratio: 4 / 3;
  position: relative;
}
.upload-preview-img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.upload-preview-overlay {
  position: absolute;
  inset: auto 0 0 0;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-4);
  background: linear-gradient(to top,
    color-mix(in srgb, var(--bg) 82%, transparent) 0%, transparent 100%);
}
.upload-preview-btn {
  min-height: 34px;
  padding: 0 var(--s-4);
  border-radius: var(--r-sm);
  font-size: var(--t-xs);
  font-weight: var(--fw-medium);
  border: 1px solid var(--line);
  transition: background var(--dur-2) var(--ease-out);
}
.btn-change { background: var(--gy-glass); color: var(--ink-2); backdrop-filter: blur(8px); }
.btn-change:hover { background: var(--surface-2); }
.btn-confirm { background: var(--accent); color: var(--on-accent); border-color: transparent; }
.btn-confirm:hover { background: var(--accent-hi); }

/* --- 表单区块 --------------------------------------------------------- */
.section-block { margin: 0 var(--s-5) var(--s-5); }
.section-title {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin-bottom: var(--s-3);
  font-size: var(--t-sm);
  font-weight: var(--fw-semi);
  color: var(--ink);
  letter-spacing: var(--ls-heading);
}
.section-title .icon { width: 15px; height: 15px; color: var(--accent); }
.section-title .req { color: var(--danger); }

.prompt-input {
  width: 100%;
  min-height: 68px;
  padding: var(--s-4);
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: var(--surface-inset);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--t-sm);
  line-height: var(--lh-body);
  resize: none;
  transition: border-color var(--dur-2) var(--ease-out);
}
.prompt-input::placeholder { color: var(--faint); }
.prompt-input:hover { border-color: var(--muted); }
.prompt-input:focus { border-color: var(--accent); }

/* --- 参数 ------------------------------------------------------------- */
.param-group { margin-bottom: var(--s-5); }
.param-group:last-child { margin-bottom: 0; }
.param-label {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--s-1);
  margin-bottom: var(--s-3);
  font-size: var(--t-sm);
  font-weight: var(--fw-medium);
  color: var(--ink-2);
}
.param-note {
  font-size: var(--t-micro);
  font-weight: var(--fw-normal);
  color: var(--faint);
}
.param-chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.param-chip {
  min-height: 34px;
  padding: 0 var(--s-4);
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--surface-inset);
  color: var(--muted);
  font-size: var(--t-sm);
  transition: border-color var(--dur-2) var(--ease-out),
              background var(--dur-2) var(--ease-out),
              color var(--dur-2) var(--ease-out);
}
.param-chip:hover { border-color: var(--line-strong); color: var(--ink-2); }
.param-chip:active { transform: scale(.97); }
.param-chip.active {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
}
.param-chip.active-violet {
  border-color: var(--gy-alt);
  background: var(--gy-alt-soft);
  color: var(--gy-alt);
}

.seed-row { display: flex; align-items: center; gap: var(--s-2); }
.seed-input {
  flex: 1;
  min-width: 0;
  min-height: 40px;
  padding: 0 var(--s-4);
  border-radius: var(--r-sm);
  border: 1px solid var(--line-strong);
  background: var(--surface-inset);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: var(--t-sm);
}
.seed-input::placeholder { color: var(--faint); font-family: var(--font-text); }
.seed-input:focus { border-color: var(--accent); }
.seed-random-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  min-height: 40px;
  padding: 0 var(--s-4);
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--surface-inset);
  color: var(--ink-2);
  font-size: var(--t-sm);
  transition: border-color var(--dur-2) var(--ease-out);
}
.seed-random-btn:hover { border-color: var(--line-strong); }
.seed-random-btn .icon { width: 15px; height: 15px; }

/* --- 主按钮 ----------------------------------------------------------- */
.generate-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  width: calc(100% - var(--s-5) * 2);
  margin: var(--s-6) var(--s-5) var(--s-7);
  min-height: 52px;
  padding: 0 var(--s-5);
  border-radius: var(--r-md);
  font-size: var(--t-h3);
  font-weight: var(--fw-semi);
  color: var(--on-accent);
  position: relative;
  overflow: hidden;
  background: var(--accent);
  transition: background var(--dur-2) var(--ease-out),
              transform var(--dur-1) var(--ease-out);
}
.generate-btn .icon { width: 19px; height: 19px; }
.generate-btn.img-mode:hover { background: var(--accent-hi); }
.generate-btn.video-mode { background: var(--gy-alt); }
.generate-btn.video-mode:hover { filter: brightness(1.08); }
.generate-btn:active { transform: scale(.985); }
.generate-btn::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at var(--ripple-x, 50%) var(--ripple-y, 50%),
    color-mix(in srgb, var(--ink) 18%, transparent), transparent 60%);
  opacity: 0;
  transition: opacity var(--dur-2) var(--ease-out);
  pointer-events: none;
}
.generate-btn:active::after { opacity: 1; }
.generate-btn[disabled] { opacity: .5; cursor: not-allowed; }
.generate-btn[disabled]:active { transform: none; }

/* ==========================================================================
   5. 生成中浮层
   ========================================================================== */
.generating-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-loading);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: var(--s-7) var(--s-6);
  max-width: var(--app-max);
  margin-inline: auto;
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity var(--dur-3) var(--ease-out);
}
.generating-overlay.show { opacity: 1; visibility: visible; pointer-events: auto; }

.gen-spinner-wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--s-6);
}
.gen-pulse-ring {
  position: absolute;
  width: 84px; height: 84px;
  border-radius: var(--r-full);
  border: 2px solid var(--gy-alt-line);
  animation: genPulse 2.4s var(--ease-out) infinite;
}
.gen-pulse-ring.cyan { border-color: var(--accent-line); }
@keyframes genPulse {
  0%, 100% { transform: scale(.82); opacity: .55; }
  50% { transform: scale(1.12); opacity: .12; }
}
.gen-spinner {
  width: 64px; height: 64px;
  border-radius: var(--r-full);
  border: 3px solid var(--gy-alt-soft);
  border-top-color: var(--gy-alt);
  animation: genSpin .85s linear infinite;
}
.gen-spinner.cyan {
  border-color: var(--accent-soft);
  border-top-color: var(--accent);
}
@keyframes genSpin { to { transform: rotate(360deg); } }

.gen-checkmark {
  display: none;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--s-6);
}
.gen-checkmark.show { display: flex; }
.gen-checkmark-circle {
  width: 64px; height: 64px;
  border-radius: var(--r-full);
  background: var(--success);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: genPop .4s var(--ease-spring);
}
@keyframes genPop { from { transform: scale(0); } to { transform: scale(1); } }
.gen-checkmark-icon {
  width: 28px; height: 28px;
  stroke: var(--bg);
  stroke-width: 3;
  fill: none;
  stroke-dasharray: 48;
  stroke-dashoffset: 48;
  animation: genDraw .4s .15s var(--ease-out) forwards;
}
@keyframes genDraw { to { stroke-dashoffset: 0; } }

.gen-title {
  font-family: var(--font-display);
  font-size: var(--t-h2);
  font-weight: var(--fw-semi);
  letter-spacing: var(--ls-heading);
  color: var(--ink);
  margin-bottom: var(--s-2);
}
.gen-subtitle {
  font-size: var(--t-sm);
  color: var(--muted);
  margin-bottom: var(--s-6);
  min-height: 20px;
  transition: opacity var(--dur-2) var(--ease-out);
}
.gen-subtitle.fade-out { opacity: 0; }
.gen-subtitle.fade-in { opacity: 1; }

.gen-progress {
  width: 100%; max-width: 280px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* 生成仪表：孔色 = 浮层底色（浮层是玻璃，孔跟着 --bg 走才不会凸出一块） */
.gen-gauge {
  margin-bottom: var(--s-5);
  --gauge-hole: var(--bg);
}
.gen-gauge__v {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: var(--fw-semi);
  color: var(--accent);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
}
.gen-progress-label {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
}
.gen-progress-header {
  display: flex;
  justify-content: space-between;
  margin-bottom: var(--s-2);
  font-size: var(--t-sm);
}
.gen-progress-label { color: var(--muted); }
.gen-progress-pct {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: var(--fw-semi);
  color: var(--gy-alt);
}
.gen-progress-pct.cyan { color: var(--accent); }
.gen-progress-pct.pop { animation: genPctPop .3s var(--ease-out); }
@keyframes genPctPop { 50% { transform: scale(1.18); } }

.gen-progress-track {
  width: 100%;
  height: 6px;
  border-radius: var(--r-full);
  background: var(--surface-inset);
  border: 1px solid var(--line);
  overflow: hidden;
}
.gen-progress-fill {
  position: relative;
  height: 100%;
  width: 0;
  border-radius: var(--r-full);
  background: var(--gy-alt);
  transition: width var(--dur-3) var(--ease-out);
}
.gen-progress-fill.cyan { background: var(--accent); }
.gen-progress-fill::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent,
    color-mix(in srgb, var(--ink) 26%, transparent), transparent);
  animation: genShimmer 1.4s linear infinite;
}
@keyframes genShimmer {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}
.gen-progress-fill-glow {
  position: absolute;
  right: 0; top: -2px;
  width: 12px; height: calc(100% + 4px);
  border-radius: var(--r-full);
  background: var(--gy-alt);
  filter: blur(4px);
  opacity: .6;
  animation: genGlow 1.6s cubic-bezier(.45,0,.55,1) infinite;
}
.gen-progress-fill.cyan .gen-progress-fill-glow { background: var(--accent); }
@keyframes genGlow { 0%, 100% { opacity: .3; } 50% { opacity: .8; } }

.gen-cancel {
  margin-top: var(--s-6);
  min-height: var(--tap-min);
  padding: 0 var(--s-6);
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-2);
  font-size: var(--t-sm);
  transition: background var(--dur-2) var(--ease-out);
}
.gen-cancel:hover { background: var(--surface-2); }

/* ==========================================================================
   6. 结果页
   ========================================================================== */
.result-page {
  position: fixed;
  inset: 0;
  z-index: var(--z-drawer);
  display: flex;
  flex-direction: column;
  max-width: var(--app-max);
  margin-inline: auto;
  background: var(--bg);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(16px);
  transition: opacity var(--dur-3) var(--ease-out),
              transform var(--dur-3) var(--ease-out);
}
.result-page.show {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
}
.result-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  min-height: calc(var(--header-h) + var(--safe-t));
  padding: var(--safe-t) var(--s-5) 0;
}
.result-back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tap-min);
  height: var(--tap-min);
  margin-inline: -10px;
  border-radius: var(--r-full);
  color: var(--ink-2);
  transition: background var(--dur-1) var(--ease-out);
}
.result-back:hover { background: var(--surface-2); color: var(--ink); }
.result-back .icon { width: 21px; height: 21px; }
.result-title {
  flex: 1;
  min-width: 0;
  font-size: var(--t-h3);
  font-weight: var(--fw-semi);
  letter-spacing: var(--ls-heading);
  color: var(--ink);
  text-align: center;
}
.result-action {
  min-height: 34px;
  padding: 0 var(--s-3);
  border-radius: var(--r-sm);
  font-size: var(--t-sm);
  font-weight: var(--fw-medium);
  color: var(--accent);
  transition: background var(--dur-2) var(--ease-out);
}
.result-action:hover { background: var(--accent-soft); }
.result-action.violet { color: var(--gy-alt); }
.result-action.violet:hover { background: var(--gy-alt-soft); }

.result-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--s-4) var(--s-5) var(--s-7);
  scrollbar-width: none;
}
.result-scroll::-webkit-scrollbar { display: none; }

.result-main-preview {
  width: 100%;
  aspect-ratio: 3 / 4;
  border-radius: var(--r-lg);
  overflow: hidden;
  margin-bottom: var(--s-4);
  background: var(--surface-inset);
  border: 1px solid var(--line);
  position: relative;
}
.result-main-img {
  width: 100%; height: 100%;
  object-fit: contain;
  background: var(--bg-sunken);
}

.result-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-2);
  margin-bottom: var(--s-5);
}
.result-thumb {
  aspect-ratio: 1;
  border-radius: var(--r-sm);
  overflow: hidden;
  cursor: pointer;
  border: 2px solid transparent;
  background: var(--surface-inset);
  transition: border-color var(--dur-2) var(--ease-out),
              transform var(--dur-1) var(--ease-out);
}
.result-thumb:hover { transform: translateY(-2px); }
.result-thumb.active { border-color: var(--accent); }
.result-thumb.active-violet { border-color: var(--gy-alt); }
.result-thumb-img { width: 100%; height: 100%; object-fit: cover; display: block; }

.result-info {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  padding: 0 var(--s-4);
  margin-bottom: var(--s-5);
}
.result-info-row {
  align-items: center;
}
.result-info-key { font-size: var(--t-sm); color: var(--muted); }
.result-info-val {
  font-size: var(--t-sm);
  color: var(--ink-2);
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.result-actions { display: flex; gap: var(--s-3); }
.btn-outline {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 46px;
  border-radius: var(--r-sm);
  border: 1px solid var(--accent-line);
  background: transparent;
  color: var(--accent);
  font-size: var(--t-sm);
  font-weight: var(--fw-semi);
  transition: background var(--dur-2) var(--ease-out);
}
.btn-outline:hover { background: var(--accent-soft); }
.btn-outline .icon { width: 17px; height: 17px; }
.btn-outline.violet { border-color: var(--gy-alt-line); color: var(--gy-alt); }
.btn-outline.violet:hover { background: var(--gy-alt-soft); }
.btn-solid {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 46px;
  border-radius: var(--r-sm);
  background: var(--accent);
  color: var(--on-accent);
  font-size: var(--t-sm);
  font-weight: var(--fw-semi);
  transition: background var(--dur-2) var(--ease-out);
}
.btn-solid:hover { background: var(--accent-hi); }
.btn-solid .icon { width: 17px; height: 17px; }
.btn-solid.violet { background: var(--gy-alt); }
.btn-solid.violet:hover { filter: brightness(1.08); }

/* ==========================================================================
   7. 作品详情页
   ========================================================================== */
.gallery-detail-page {
  position: fixed;
  inset: 0;
  z-index: var(--z-drawer);
  display: flex;
  flex-direction: column;
  max-width: var(--app-max);
  margin-inline: auto;
  background: var(--bg);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(16px);
  transition: opacity var(--dur-3) var(--ease-out),
              transform var(--dur-3) var(--ease-out);
}
.gallery-detail-page.show {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
}
.gallery-detail-scroll { padding: var(--s-4) var(--s-5) var(--s-8); }

.detail-compare { display: flex; gap: var(--s-3); margin-bottom: var(--s-5); }
.detail-card {
  flex: 1;
  min-width: 0;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--line);
  /* 视频失效兜底 .is-media-broken::after 是 absolute，需要定位上下文 */
  position: relative;
}
.detail-card-label {
  padding: var(--s-2) var(--s-3);
  font-size: var(--t-micro);
  font-weight: var(--fw-medium);
  letter-spacing: var(--ls-caps);
  color: var(--muted);
  border-bottom: 1px solid var(--line);
  background: var(--surface-2);
}
.detail-card-label-video { color: var(--gy-alt); }
.detail-card-img,
.detail-card-video {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  display: block;
  background: var(--surface-inset);
}

.detail-prompt-section {
  padding: var(--s-5);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface);
}
.detail-prompt-label {
  margin-bottom: var(--s-3);
  font-size: var(--t-sm);
  font-weight: var(--fw-semi);
  color: var(--ink);
  letter-spacing: var(--ls-heading);
}
.detail-prompt-text {
  font-size: var(--t-sm);
  line-height: var(--lh-body);
  color: var(--ink-2);
  white-space: pre-wrap;
  word-break: break-word;
  max-width: 36ch;
}

/* ==========================================================================
   8. 通知
   #toast 是原站自带的单例元素（showToast 加 .show），
   这里全部按 id 定位，避免与 components.css 的 .toast 组件互相打架。
   ========================================================================== */
#toast {
  position: fixed;
  /* 让开顶部的「演示数据」提示条（由 offline.js 注入，高约 36px），
     否则提示一出来就被压在它下面 */
  top: calc(var(--safe-t) + var(--s-8) + var(--s-4));
  left: 50%;
  transform: translateX(-50%) translateY(-12px);
  z-index: var(--z-toast);
  max-width: min(88vw, calc(var(--app-max) - 40px));
  padding: var(--s-3) var(--s-5);
  border-radius: var(--r-full);
  background: var(--surface-2);
  border: 1px solid var(--line-strong);
  box-shadow: var(--shadow-lg);
  color: var(--ink);
  font-size: var(--t-sm);
  font-weight: var(--fw-medium);
  text-align: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-3) var(--ease-out),
              transform var(--dur-3) var(--ease-out);
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ==========================================================================
   9. 图标 / 工具类
   ========================================================================== */
.icon {
  display: inline-block;
  vertical-align: middle;
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon-sm { width: 15px; height: 15px; }
.icon-lg { width: 26px; height: 26px; }

.hidden { display: none !important; }

/* 键盘可达的可点区域（图表面上不是 button 的那些） */
.tap-surface { cursor: pointer; }
.tap-surface:focus-visible { outline: 2px solid var(--line-focus); outline-offset: 3px; }

/* 底部作品集导航与内容之间留白（组件自带 padding，这里只调上边距） */
.portfolio-nav { margin-top: var(--s-6); }

/* ==========================================================================
   10. 窄屏 / 矮屏适配
   --------------------------------------------------------------------------
   首页把主张放到了作品之上，矮屏（<760px 高）会把主视觉的 CTA 挤出首屏。
   这里按高度收紧留白并改横构图 —— 不隐藏任何内容。
   ========================================================================== */
@media (max-height: 780px) {
  .home-head { padding-bottom: var(--s-4); }
  .home-headline { font-size: var(--t-h2); }
  .home-hero { aspect-ratio: 16 / 10; margin-bottom: var(--s-4); }
  .quick-action { min-height: 112px; padding: var(--s-4); }
  .quick-action-desc { display: none; }
}
@media (max-height: 620px) {
  .home-hero { aspect-ratio: 16 / 9; }
}

/* ==========================================================================
   11. 动效偏好
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .logo-ring-outer, .logo-ring-inner, .logo-infinity,
  .logo-flow-1, .logo-flow-2, .logo-flow-3, .logo-glow,
  .gen-pulse-ring, .gen-spinner, .gen-progress-fill::after,
  .gen-progress-fill-glow, .gen-checkmark-circle, .gen-checkmark-icon {
    animation: none !important;
  }
  .page, .result-page, .gallery-detail-page, .generating-overlay {
    transition: none !important;
    transform: none !important;
  }
}

/* ==========================================================================
   首页品牌语（原站以 inline style 写死，重构时丢失）
   原文样式：margin:0 20px 8px; font-size:12px; color:#64748b; font-weight:400
   此处改走令牌，颜色随主题；不写死 #64748b。
   ========================================================================== */
.home-tagline {
  margin: 0 var(--s-5) var(--s-2);
  font-size: var(--t-sm);
  font-weight: var(--fw-normal);
  letter-spacing: var(--ls-body);
  color: var(--muted);
}


/* ==========================================================================
   重构层 —— 按 xiao9qianduan 规范收口（精确命中版）
   --------------------------------------------------------------------------
   为什么写在各站自己的 CSS 里、不动共享层：
     共享层 7 站同步，改它会连带改到音纪（不在本次范围内）。
     各站 CSS 在 components.css 之后加载，覆盖一定生效。

   ⚠ 上一版我用了 `[class*='-card']` `[class*='__item']` `[class*='stat']`
     这类通配选择器，闯了三个祸，记录在此以免重蹈：
       1. `.glass` 命中了珠语首屏的 `<div class="glass hero-tag">`，
          把半透明标签刷成实色白块 —— 首屏大图上糊了一块白。
       2. `[class*='__item']` 命中润凯的 `.tab-item` / `.slider-item`，
          给它们强制加过渡，搅乱了它自己的跑马灯时序。
       3. `p, .desc, [class*='-desc'] { font-size: max(16px,1em) }` 一次性放大了
          大量本该更小的文字，各处换行崩坏。
     结论：**这个项目的类名体系没有统一命名法，通配选择器必然误伤。**
     改样式只能逐个类名精确写，改一条验一条。

   本文件只做三件低风险、可验证的事，都用精确类名。
   ========================================================================== */

:root {
  /* expo-out：前快后慢的减速。规范里所有 reveal / hover 都用它。 */
  --rf-ease: cubic-bezier(.16, 1, .3, 1);
}

/* ---------- 1. 缓动统一到 expo-out --------------------------------------
   只挑语义明确的"交互反馈"类名，不碰动画容器和列表项。 */
.btn,
.cta,
.chip,
.tab-btn,
.el-tab,
.sz-btn,
.ws-item,
.ws-rope,
.rope-swatch,
.ci,
.bc,
.stone-cat-ci,
.stone-cat-item {
  transition-timing-function: var(--rf-ease) !important;
}

/* ---------- 2. 数字等宽 -------------------------------------------------
   金额/颗数/百分比一变就左右跳，显业余。只命中数值语义的类。 */
.bp,
.bp *,
.bsz,
#sub,
#cnt,
.hero-stat-num,
.hero-stat-label,
.ring__num,
.progress__val,
.price,
.price *,
.amount,
.pay-num,
.order-num,
.stat-num,
.score,
.score-num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ---------- 3. 键盘焦点可见 ---------------------------------------------
   规范：focus 环必须即时出现，不做出现动画。 */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---------- 4. 【已移除】毛玻璃收口 ----------
   这里原先有一组规则，把 .glass-card / .feature-card / .poster-card 等 10 个类名
   强制刷成实色 + 细边框，依据是规范里"只有导航栏可以用毛玻璃"。

   删掉的原因 —— 实机量完之后，它在**这一站里一个正确目标都没有**：
     · 全站真正带 backdrop-filter 的元素共 13~19 个，逐个看过，全是
       顶栏 / 底栏 / 模态遮罩 / 悬浮在照片上的标签 —— 正是规范允许的那类"表层"。
     · 唯一被它刷实的 5 个 .glass-card 全是压在图上的叠层
       （.gallery-item-bottom、.cs-image-overlay），背后是照片，模糊是必要的。
     · 9033 的 .feature-card--dark（九宫格唯一的深色落点）被刷成白底白字。
     · !important 不看特异性，会连变体自己的 background/border/box-shadow
       一起压掉 —— 用一个没上过实机的猜想覆盖了 8 个类名的真实样式。

   教训：**"某个属性在 CSS 里出现 N 次"不等于"N 处滥用"**。
   前者是数声明，后者得数**真的渲染出来的元素**，还得看它背后是什么。
   -------------------------------------------------------------------------- */

/* ---------- 5. 【已移除】触控目标下限 ----------
   这里原先强制 .btn / .chip / .sz-btn 等类 min-height:44px，依据是规范里
   "可点击区域 ≥ 44px"。

   删掉的原因 —— 实测它同时抬高和压低，而且压过的是作者**显式写死**的值：
     · 珠语 .sz-btn 34 -> 44：尺码条是 44 宽 x 34 高的竖排，撑高后整条
       从 186px 变 236px，把珠子网格往下推。
     · 珠语 .chip 32 -> 44：色系药丸行 40 -> 69px。
     · 礼续 .chip--sm 26 -> 44：那是**非交互**的 <span> 标签，撑高纯属破坏。
     · 归家 .btn--lg 52 -> 44、礼续 .gen-btn 54 -> 44：主 CTA 被**压扁**。
   而在多数站点它根本是空操作 —— 共享层
       .btn { min-height: var(--tap-min) }      // tokens.css: --tap-min: 44px
   和各站的 .el-tab { min-height: var(--tap-min) } 早已满足 44px。

   根因：带 !important 的 min-height 会**双向**覆盖，不管作者写的值
   是比 44 大还是比 44 小。而这里每个小于 44 的元素都是有意为之
   （尺码条 44x34、药丸 32 高），不是没设计过。
   真要兜底，该用 `min-height: max(44px, <作者值>)` 这类"只抬高不压低"的写法 ——
   但 CSS 取不到"元素自己的原值"，所以宁可交给作者。
   -------------------------------------------------------------------------- */

