/* SplatApp 前端主题：Kuromi 水彩纸艺。
   视觉基调对齐 gaussian-kuromi-ppt/style.css 的品牌色，背景用水彩插画
   （web/assets/kuromi-studio.webp，见 vendor/tweakpane/SOURCES.md 的采样记录）。
   3D 画布保持深色：高斯泼溅需要暗底才能看清粒子，这里按 PPT 的做法加奶白描边当画框。 */

@font-face {
  font-family: 'StoryHand';
  src: url('/fonts/storyhand-subset.woff2') format('woff2');
  font-display: swap;
  font-weight: 400;
}

:root {
  /* 品牌色（与 gaussian-kuromi-ppt 一致） */
  --bg: #fff8e7;
  --bg-soft: #fffaf0;
  --surface: #fffaf0;
  --surface-2: #f3ead9;
  --border: #d6c6ad;
  --border-strong: #a98d73;
  --text-1: #63402f;
  --text-2: #5a4b49;
  --text-3: #8b786a;
  --accent: #9178b0;
  --accent-2: #d8a2b5;
  --gold: #e5bc60;
  --lavender: #e9def0;
  --pink: #f1d8da;
  --frame: #3a3130;
  --ok: #4f8f5e;
  --warn: #c98a2b;
  --err: #c2495a;

  /* 旧变量名继续可用（app.js 与部分规则仍引用） */
  --panel: var(--surface);
  --panel-2: var(--surface-2);
  --line: var(--border);
  --text: var(--text-1);
  --muted: var(--text-3);

  --radius: 16px;
  --shadow: 0 7px 0 #b9a18d12, 0 3px 14px #63402f14;
  --font-sans: 'Noto Sans CJK SC', 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', system-ui, sans-serif;
  --font-display: 'StoryHand', 'AR PL UKai CN', serif;
}

* { box-sizing: border-box; }

/* 纸面底色只在 html 上；body 必须透明，否则 body 自身的背景会盖住
   z-index 为负的 body::before/::after（插画与纱），壁纸将完全不可见。 */
html { background: var(--bg); height: 100%; }
body {
  margin: 0; height: 100%;
  background: transparent; color: var(--text-1);
  font: 14px/1.5 var(--font-sans);
  display: flex; flex-direction: column; min-height: 0;
}

/* 背景插画铺满视口，上面压一层很淡的暖色纱，兼顾可读性与可见度 */
body::before {
  content: ''; position: fixed; inset: 0; z-index: -2;
  background-image: image-set(url('/assets/kuromi-studio.webp') type('image/webp'),
                              url('/assets/kuromi-studio.jpg') type('image/jpeg'));
  background-position: center top; background-size: cover; background-repeat: no-repeat;
}
body::after {
  content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(ellipse at 6% 4%, #fff8e726, #fff8e70f 55%, #fff8e73d 100%),
    linear-gradient(180deg, #fff8e70f, #fff8e726);
}

header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 20px; border-bottom: 2px solid var(--border);
  background: linear-gradient(180deg, #fffaf0cc, #fff8e7a6);
  backdrop-filter: blur(16px) saturate(1.1);
}
h1 {
  margin: 0; font-size: 19px; font-weight: 400; letter-spacing: 1px;
  font-family: var(--font-display); color: var(--text-1);
  display: flex; align-items: center; gap: 10px;
}
h1::before {
  content: ''; width: 46px; height: 5px; border-radius: 40% 15% 45% 15%;
  background: var(--gold); transform: rotate(-2deg); opacity: .75;
}
h1 .sub, h2 .sub { color: var(--text-3); font-family: var(--font-sans); font-weight: 400; font-size: 12px; margin-left: 6px; }
h2 { margin: 0 0 10px; font-size: 15px; font-weight: 400; font-family: var(--font-display); color: var(--text-1); }

.pill {
  padding: 4px 12px; border-radius: 999px; font-size: 12px;
  background: var(--surface-2); border: 2px solid var(--border); color: var(--text-3);
}
.pill.ok { color: var(--ok); border-color: #a9c9a9; background: #eef6ea; }
.pill.bad { color: var(--err); border-color: #e0b3bb; background: #fbeef0; }

main {
  display: grid; grid-template-columns: 320px 1fr 380px;
  gap: 14px; padding: 14px; flex: 1; min-height: 0;
}

.panel {
  background: #fffaf0b8; border: 2px solid var(--border);
  border-radius: 22px 15px 20px 13px; padding: 14px; overflow: auto; min-height: 0;
  box-shadow: var(--shadow); backdrop-filter: blur(16px) saturate(1.1);
}
.panel:nth-child(2) { border-radius: 15px 22px 13px 20px; }
.panel.viewer { display: flex; flex-direction: column; overflow: hidden; }
.block { margin-bottom: 18px; padding-bottom: 16px; border-bottom: 2px dashed var(--border); }
.block:last-child { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }
.task-history-heading { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.task-history-heading span { font-size: 12px; color: var(--text-3); }
.task-history { max-height: 280px; overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.task-row { width: 100%; flex-shrink: 0; text-align: left; font: inherit; padding: 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); color: var(--text-1); cursor: pointer; }
.task-row strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
.task-row span, .task-row small { display: block; margin-top: 4px; font-size: 11px; color: var(--text-3); }
.task-row[data-status=running] span { color: var(--accent); }
.task-row[data-status=failed] span { color: var(--err); }
.task-row[aria-pressed=true] { border-color: var(--accent); background: var(--lavender); }
.task-row:focus-visible, .task-history:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.task-entry { position: relative; flex-shrink: 0; }
.task-entry:has(.task-retry:not([hidden])) .task-row { padding-bottom: 42px; }
.task-retry { position: absolute; right: 8px; bottom: 8px; font-size: 11px; padding: 3px 10px; }
.retry-prompt { margin: 10px 0; padding: 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); font-size: 12px; }
.retry-prompt p { margin: 0 0 8px; overflow-wrap: anywhere; }

/* 拖拽区 */
.drop {
  display: flex; flex-direction: column; gap: 4px; align-items: center;
  padding: 22px 12px; border: 2px dashed var(--border-strong); border-radius: 17px 11px 15px 10px;
  background: var(--surface); cursor: pointer; transition: .15s; text-align: center;
}
.drop:hover, .drop.over { border-color: var(--accent); background: var(--lavender); }
.drop strong { font-size: 13px; color: var(--text-1); }
.drop span { font-size: 11.5px; color: var(--text-3); }
.fileinfo { margin-top: 8px; font-size: 12px; color: var(--accent); word-break: break-all; }

/* 质量档位 */
.quals { display: flex; flex-direction: column; gap: 8px; }
.quals label {
  display: flex; align-items: flex-start; gap: 9px; cursor: pointer;
  padding: 9px 11px; border: 2px solid var(--border); border-radius: 14px 10px 13px 9px;
  background: var(--surface); transform: rotate(-.4deg);
}
.quals label:nth-child(even) { transform: rotate(.5deg); }
.quals label:has(input:checked) { border-color: var(--accent); background: var(--lavender); }
.quals input { margin-top: 3px; accent-color: var(--accent); }
.quals span { display: flex; flex-direction: column; font-size: 13px; }
.quals em { font-style: normal; font-size: 11px; color: var(--text-3); }

.go {
  width: 100%; padding: 12px; font-size: 14px; font-weight: 600; cursor: pointer;
  color: var(--bg-soft); border: 2px solid var(--border-strong); border-radius: 999px;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 4px 0 #a98d7340;
}
.go:hover:not(:disabled) { filter: brightness(1.05); }
.go:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }
.hint { font-size: 11px; color: var(--text-3); margin: 10px 0 0; }

/* 进度 */
.stage { font-size: 15px; font-weight: 600; color: var(--accent); margin-bottom: 8px; }
.bar { height: 10px; border-radius: 99px; background: var(--surface-2); border: 1px solid var(--border); overflow: hidden; }
.fill { height: 100%; width: 0; border-radius: 99px;
        background: linear-gradient(90deg, var(--accent), var(--accent-2)); transition: width .4s; }
.row { display: flex; justify-content: space-between; font-size: 12px; color: var(--text-3); margin-top: 5px; }
.msg { font-size: 12px; color: var(--text-2); margin-top: 8px; min-height: 18px; }
.log {
  margin-top: 10px; max-height: 240px; overflow: auto; font-size: 11px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px;
  padding: 8px; color: var(--text-2); white-space: pre-wrap; word-break: break-all;
}
.stats { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px; font-size: 12px; color: var(--text-1); }
.stats b { color: var(--text-3); font-weight: 400; }
.dl {
  display: inline-block; margin-top: 12px; padding: 9px 16px; border-radius: 999px;
  background: var(--lavender); color: var(--text-1); border: 2px solid var(--border-strong);
  text-decoration: none; font-size: 13px;
}
.dl:hover { background: var(--pink); }

.cam-bar {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  margin: 0 0 10px; flex: 0 0 auto;
}
.cam-label { font-size: 12px; color: var(--text-3); margin-right: 2px; }
.cbtn {
  padding: 4px 11px; border-radius: 999px; cursor: pointer;
  background: var(--surface); color: var(--text-2); border: 2px solid var(--border);
  font-size: 12px; font-family: inherit; line-height: 1.5;
}
.cbtn:hover { background: var(--lavender); color: var(--text-1); }
.cbtn.on { background: var(--accent); border-color: var(--accent); color: var(--bg-soft); }
.cbtn:disabled { opacity: .4; cursor: not-allowed; }
.view-options { display: flex; flex-wrap: wrap; gap: 8px 16px; margin-bottom: 10px; font-size: 11px; color: var(--text-3); }
.view-options label { display: flex; align-items: center; gap: 5px; cursor: pointer; }
.view-options input { accent-color: var(--accent); }
.fx-master {
  display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;
  padding: 8px 11px; border: 2px solid var(--border); border-radius: 13px 9px 12px 8px;
  background: var(--surface); font-size: 12px; color: var(--text-1);
}
.fx-master label { display: flex; align-items: center; gap: 7px; cursor: pointer; }
.fx-master input { accent-color: var(--accent); }
.fx-master span { font-size: 11px; color: var(--text-3); }
.fx-panel {
  flex: 0 0 auto; margin-bottom: 10px; border: 2px solid var(--border);
  border-radius: 15px 11px 14px 10px; background: var(--surface);
}
.fx-panel summary { padding: 8px 11px; font-size: 12px; color: var(--text-1); cursor: pointer; font-family: var(--font-display); }
.fx-panel summary span { color: var(--text-3); font-size: 11px; margin-left: 8px; font-family: var(--font-sans); }
.fx-hint { margin: 8px 11px 10px; font-size: 11px; color: var(--text-3); }
.cam-readout {
  font-size: 11px; color: var(--text-3);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
#camPlaneState { margin-left: auto; }
.cam-readout + .cam-readout { margin-left: 12px; }
.cam-readout.on { color: var(--accent); }

/* Tweakpane 主题：覆盖 --tp-* 让参数面板并入纸艺卡片（变量名取自发行 bundle 实测） */
.fx-pane-theme {
  --tp-base-background-color: transparent;
  --tp-base-shadow-color: transparent;
  --tp-base-border-radius: 12px;
  --tp-base-font-family: var(--font-sans);
  --tp-blade-border-radius: 8px;
  --tp-container-background-color: #f3ead9cc;
  --tp-container-background-color-hover: #ece0ca;
  --tp-container-background-color-active: #e5d7bd;
  --tp-container-background-color-focus: #e5d7bd;
  --tp-container-foreground-color: var(--text-1);
  --tp-input-background-color: #fffaf0;
  --tp-input-background-color-hover: #ffffff;
  --tp-input-background-color-active: #f7efdd;
  --tp-input-background-color-focus: #f7efdd;
  --tp-input-foreground-color: var(--text-1);
  --tp-label-foreground-color: var(--text-3);
  --tp-button-background-color: var(--lavender);
  --tp-button-background-color-hover: #ded0ec;
  --tp-button-background-color-active: #cfbddf;
  --tp-button-background-color-focus: #ded0ec;
  --tp-button-foreground-color: var(--text-1);
  --tp-groove-foreground-color: #ded0ba;
  --tp-monitor-background-color: var(--surface-2);
  --tp-monitor-foreground-color: var(--text-2);
  padding: 0 2px 4px;
}
/* 容器模式下 Tweakpane 不套 .tp-dfwv，但根视图仍会自带折叠标题；这里不需要二次标题。 */
.fx-pane-theme .tp-rotv { background: none; box-shadow: none; }
.fx-pane-theme .tp-rotv_b { display: none; }
.fx-pane-theme .tp-rotv_c { padding-top: 4px; }
/* 滑块是 div 轨道 + 旋钮，不是原生 range：轨道用凹纸槽，旋钮用品牌紫。 */
.fx-pane-theme .tp-sldv_t {
  background-color: #e6d9c1; border-radius: 999px; height: 6px; overflow: hidden;
}
.fx-pane-theme .tp-sldv_k {
  background-color: var(--accent); box-shadow: 0 0 0 1px #ffffff88;
}
.fx-pane-theme .tp-sldv_t:focus-visible,
.fx-pane-theme .tp-lstv_s:focus-visible,
.fx-pane-theme .tp-btnv_b:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px;
}
/* 数值输入的等宽右侧文本框贴住品牌底色 */
.fx-pane-theme .tp-sldtxtv_s {
  border-radius: 6px;
}
/* 总开关关闭 / 无模型：面板整体降噪，并阻断指针（Tweakpane 的 tp-v-disabled 已含 pointer-events:none） */
.fx-pane-theme .tp-rotv.tp-v-disabled { opacity: .55; }

/* 预览 */
.canvas-wrap {
  position: relative; flex: 1; min-height: 0; border-radius: 14px; overflow: hidden;
  background: #1b1719; border: 5px solid var(--bg-soft);
  box-shadow: 0 8px 22px #63402f2e;
}
.canvas-wrap canvas { display: block; }
.canvas-wrap canvas:focus { outline: none; }
.viewer-info {
  position: absolute; top: 12px; left: 12px; z-index: 2; pointer-events: none;
  white-space: pre-line; font: 12px/1.8 monospace; color: #ffeede;
  background: #241f22dd; padding: 9px 13px; border: 1px solid #a98d73aa; border-radius: 10px;
}
.viewer-info[hidden] { display: none; }
/* 3D 视窗全屏：只放大中间视窗，相机、粒子特效和键盘快捷键保持可用。
   :fullscreen 放在容器上，Esc 由浏览器直接退出；工具栏默认收起为浮层按钮，不挤压画面。
   展开的工具栏从 52px 起排，给右上角 控制/收起工具 按钮留出可点击的空档（两者不可重叠）。 */
.viewer-toolbar { display: flex; flex-direction: column; flex: 0 0 auto; min-height: 0; }
.fs-toggle { position: absolute; top: 10px; right: 10px; z-index: 4; display: none; }
.panel.viewer:fullscreen {
  padding: 0; border: 0; border-radius: 0; background: var(--frame); overflow: hidden;
}
.panel.viewer:fullscreen .canvas-wrap { border: 0; border-radius: 0; box-shadow: none; }
.panel.viewer:fullscreen .viewer-toolbar {
  display: none; position: absolute; top: 52px; right: 10px; z-index: 5;
  width: min(680px, calc(100vw - 20px)); max-height: calc(100vh - 62px);
  overflow-y: auto; padding: 12px; background: #fffaf0f5;
  border: 2px solid var(--border-strong); border-radius: 16px; box-shadow: 0 12px 32px #0009;
}
.panel.viewer:fullscreen .viewer-toolbar.expanded { display: flex; }
body.has-fullscreen { overflow: hidden; }
body.has-fullscreen .fs-toggle:not([hidden]) { display: block; }
/* Fullscreen API 生效时隐藏页头/侧栏，避免全屏元素之外出现滚动条 */
body.has-fullscreen > header { display: none; }
body.has-fullscreen > main { height: 100vh; flex: 0 0 auto; }
body.has-fullscreen > main > .panel:not(.viewer) { display: none; }
.viewer-focus-status {
  position: absolute; left: 12px; bottom: 10px; z-index: 2; pointer-events: none;
  color: #ffeede; background: #241f22cc; border-radius: 5px; font-size: 11px; padding: 5px 8px;
}
.viewer-focus-status:empty { display: none; }
.keyboard-help { margin: 8px 0; color: var(--text-3); font-size: 12px; line-height: 1.7; }
.keyboard-help summary { cursor: pointer; }
.keyboard-help p { margin: 5px 0; }
.empty {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  color: #ffeedecc; font-size: 13px; text-align: center; padding: 20px;
}

@media (max-width: 1450px) {
  main { grid-template-columns: 260px minmax(360px, 1fr) 290px; }
}
@media (max-width: 1100px) {
  main { height: auto; flex: 0 0 auto; grid-template-columns: 1fr 1fr; }
  .panel.viewer { grid-column: 1 / -1; order: 3; height: 75vh; min-height: 520px; }
}
@media (max-width: 600px) {
  main { grid-template-columns: minmax(0, 1fr); padding: 8px; }
  .panel.viewer { grid-column: auto; order: 3; padding: 10px; height: 80vh; min-height: 580px; }
}
