/* styles.css —— CatsUp app 壳样式。created 2026-09-06 by Claude Fable 5.1
   z band 表（家族约定：z 数字只在这里）：menu 300 / notice 400 / help 500 / err 900 */
:root {
  --bg: #f2f0ea;
  --panel: #ffffff;
  --ink: #2a2a2a;
  --muted: #8a8780;
  --line: #ddd9d0;
  --accent: #2b6cb0;
  --accent-soft: #e3edf9;
  --danger: #c0392b;
  /* HUD 的几个面（日间；夜间见下面 .ui-night）：弱玻璃 / 实一点的玻璃 / 工具条输入与开关的底 / 文字类 HUD 的描边光晕 / 悬停底 / 细边 */
  --glass: rgba(255,255,255,.55);
  --glass-strong: rgba(255,255,255,.75);
  --field: #fff;
  --halo: #fff;
  --halo-soft: rgba(255,255,255,.9);
  --hover: rgba(0,0,0,.06);
  --edge: rgba(0,0,0,.12);
  --tool-ink: #444;
  --hud-text: #4a4a4a;
  --readout: #2b2b2b;
  --menu-hover: #f3f0ea;
  --z-drawer: 150;   /* 底部抽屉（物品栏）：非模态，HUD 之上、参考窗 / 弹出菜单之下 */
  --z-window: 200;   /* 参考窗：HUD（5）之上、弹出菜单（300）之下——它自己的 ＋ 菜单要盖在它上面 */
  --z-menu: 300;
  --z-notice: 400;
  --z-help: 500;
  --z-err: 900;
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --drawer-h: 0px;   /* 底部抽屉现在占多高（main.ts 量出来写）：贴底的 HUD 都让出这么多（user 2026-10-25「物品栏弹起来时会把小窗顶到上面，然后其他的hud也一样」） */
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; overflow: hidden; background: var(--bg); color: var(--ink);
  font-family: system-ui, -apple-system, "PingFang SC", "Noto Sans CJK SC", sans-serif; font-size: 14px;
  touch-action: manipulation; -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; overscroll-behavior: none; }
[hidden] { display: none !important; }
button { font: inherit; color: inherit; }
.ico { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; display: block; }
svg.ico use { color: inherit; }

#app { position: relative; height: 100%; }
#stage { position: absolute; inset: 0; }
#board { position: absolute; inset: 0; width: 100%; height: 100%; touch-action: none; cursor: default;   /* 普通箭头（user 10-27「能不能不要用十字鼠标style，大屏幕上很容易找不到」） */ display: block; }

/* HUD（user 2026-09-06「hud 在视口里面…以后转 VR 会无疼」；2026-09-07 二稿：更游戏化——顶上空、左右两根竖栏、
   栏=弱玻璃无边框，文字（状态/版本）无背景只描白边；画布满屏，空白全部透给场景） */
.hud { position: absolute; z-index: 5; display: flex; align-items: center; gap: 2px; padding: 4px;
  background: var(--glass); border-radius: 12px; box-shadow: 0 1px 6px rgba(0,0,0,.05);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.hud-rail { flex-direction: column; gap: 2px; padding: 4px; }
/* 左柱：☰ 叠在工具上、撤销/重做叠在工具下，整柱左居中（user 2026-09-07 终形：「工具居中，三条杠 stack 在工具上面不分离，undo redo stack 在工具下面」）*/
.hud-rail-tools { left: calc(10px + var(--safe-left)); top: calc((100% - var(--drawer-h) - 18px) / 2); transform: translateY(-50%); max-height: calc(100vh - 38px - var(--safe-top) - var(--safe-bottom) - var(--drawer-h)); overflow-y: auto; scrollbar-width: none; }   /* 15 个钮 ≈ 720 px：iPad mini 竖屏放得下、横屏（744 px 高）要能滚 */
.hud-rail-tools::-webkit-scrollbar { display: none; }
.hud-rail-tools > .tb-btn { width: 48px; }
.rail-tools { display: flex; flex-direction: column; gap: 2px; }
/* 右柱已撤（2026-10-21 user：全部在一侧，像 WeebPaint）；视图 = 右上角导航 gizmo（Blender / Unity 式） */
.hud-gizmo { position: absolute; z-index: 5; right: calc(8px + var(--safe-right)); top: calc(8px + var(--safe-top)); display: flex; flex-direction: column; align-items: center; gap: 0; }   /* ☰ / gizmo / 手 + 放大镜 贴着（user 2026-10-25「贴着」） */
.gizmo-svg { width: var(--gizmo-w, 96px); height: var(--gizmo-w, 96px); touch-action: none; cursor: grab; user-select: none; -webkit-user-select: none; filter: drop-shadow(0 1px 2px var(--halo-soft)); }
.gizmo-svg:active { cursor: grabbing; }
.gizmo-btns { display: flex; flex-direction: column; gap: 2px; padding: 3px; border-radius: 10px; background: var(--glass); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.gizmo-btn { width: 34px; height: 34px; display: grid; place-items: center; border: 0; border-radius: 8px; background: transparent; color: var(--ink); cursor: pointer; }
.gizmo-btn .ico { width: 20px; height: 20px; }
.gizmo-btn:hover { background: var(--hover); }
.gizmo-btn.on { background: var(--accent-soft); color: var(--accent); }
.gizmo-btn { touch-action: none; }
.gizmo-btn.dragging { background: var(--accent-soft); color: var(--accent); }
/* 视图侧挂件条（2026-10-24 Opus）：gizmo 拖柄下面另一组；第一个 = 吸附；角标 = 轴锁（颜色同三色轴） */
/* ☰ 在上、手 + 放大镜在下（user 2026-10-25「汉堡，手和放大镜，上下挪一下。给gizmos留出空间」「手和放大镜可以大一些，占满gizmos的行宽」）：
   gizmo 本体不被压、方框裁到轴端小球最远处（view-gizmo.ts fitBox，--gizmo-w）；☰ 一行靠右（还是右上角那颗）；手 + 放大镜一行、各占半宽、比 34 px 高一点 */
.gizmo-top { width: var(--gizmo-w, 96px); display: flex; justify-content: flex-end; gap: 4px; }   /* 参考窗 + 视图两颗：各带一块毛玻璃底（user 10-30「汉堡系的几个没有背景的按钮也改成带背景的吧，和其他的统一一下」——改掉 10-25「三条杠背景拿掉」） */
.gizmo-top .gizmo-btn { background: var(--glass); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
.gizmo-top .gizmo-btn:hover { background: var(--hover); }
.gizmo-top .gizmo-btn.on, .gizmo-top .gizmo-btn.is-open { background: var(--accent-soft); color: var(--accent); }
.gizmo-nav[hidden] { display: none; }
.gizmo-nav { flex-direction: row; width: var(--gizmo-w, 96px); gap: 4px; padding: 0; background: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
.gizmo-nav .gizmo-btn { flex: 1; width: auto; height: 42px; background: var(--glass); }
.gizmo-nav .gizmo-btn .ico { width: 24px; height: 24px; }
.gizmo-widgets { margin-top: 10px; align-self: flex-end; flex-direction: row; }   /* 别的钮靠右对齐（user「另外的按钮比如gridlock右对齐」）；横着排（user 10-30「吸附和xray能不能横着摆，会不会更省空间？因为上面也是横着摆的」） */
.gizmo-snap { position: relative; }
.gizmo-snaplock { position: absolute; right: 1px; bottom: 1px; width: 12px; height: 12px; pointer-events: none; background: var(--panel); border-radius: 3px; }
.gizmo-snaplock .ico { width: 12px; height: 12px; }
.gizmo-subdiv { position: absolute; right: -2px; top: -3px; padding: 0 2px; border-radius: 4px; font: 700 9px/12px system-ui, sans-serif; color: var(--ink); background: var(--panel); pointer-events: none; font-variant-numeric: tabular-nums; }   /* 吸附细分（硬表面；v0.17.61） */
.gizmo-snap:not(.on) .gizmo-subdiv { opacity: .55; }
.gizmo-badge { position: absolute; left: 1px; top: 1px; min-width: 13px; height: 13px; padding: 0 2px; border-radius: 7px; font: 700 9px/13px system-ui, sans-serif; color: #fff; background: #555; pointer-events: none; }
.gizmo-badge[data-axis="x"] { background: #d9342b; }
.gizmo-badge[data-axis="y"] { background: #2e8b57; }
.gizmo-badge[data-axis="z"] { background: #1e6fd9; }
/* 文字类 HUD：无背景、白描边（游戏字幕式），指针穿透 */
.hud-text { position: absolute; z-index: 5; pointer-events: none; font-size: 12px; color: var(--hud-text); line-height: 1.45;
  text-shadow: 0 0 2px var(--halo), 0 0 2px var(--halo), 0 0 4px var(--halo), 0 1px 3px var(--halo-soft); }
.hud-bl { bottom: calc(26px + var(--safe-bottom) + var(--drawer-h)); left: calc(10px + var(--safe-left)); max-width: min(62vw, 720px); }
.hud-br { bottom: calc(10px + var(--safe-bottom) + var(--drawer-h)); right: calc(10px + var(--safe-right)); display: flex; flex-direction: column; align-items: flex-end; gap: 2px; max-width: min(60vw, 560px); }
/* 底部工具选项条（tool-config 表生成；当前工具没选项就整条隐藏）：左下、提示行之上；右下留给数值小窗 */
/* 上下文选项那一段（2026-10-25 晚：并进右下参数小窗，user「参数小窗就是上下文选项条，全搬进去」） */
.vcb-strip { display: flex; align-items: center; gap: 10px; font-size: 13px; flex-wrap: wrap; justify-content: flex-end; }
.vcb-params { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.vcb-params-title { font-size: 12px; color: var(--muted); }
.vcb-params-note { font-size: 11px; color: var(--muted); max-width: 22em; line-height: 1.35; }
.vcb-params-fields, .vcb-params-buttons { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.strip-action.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
/* 面包屑（#25）：左上角，进了组 / 组件才出现 */
/* 编辑模式下拉框（刀 ③；user「切换编辑模式还是左上下拉框」）：嵌纸面、像能按，同左上横排 */
.mode-select { height: 30px; padding: 0 8px; border: 1px solid var(--edge); border-radius: 8px; background: var(--glass-strong); font: inherit; font-size: 13px; color: inherit; }
/* 表面工具上下文条的 chip：材质色块 + 吸色开关 */
.strip-action.on { background: var(--accent); color: #fff; border-color: var(--accent); }
.strip-chip { display: inline-flex; align-items: center; gap: 6px; }
.strip-swatch { width: 16px; height: 16px; border-radius: 4px; border: 1px solid rgba(0,0,0,.2); background-size: cover; background-position: center; }
/* 定稿（ai-docs/20261024-finalize.md）：角标 + 护栏 ① 界面灰掉 */
.sheet-form { display: contents; }
.sheet-user { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }   /* 账号字段只给密码管理器看（口令 sheet 真表单） */
.sheet-check { display: flex; align-items: flex-start; gap: 8px; font-size: 13px; color: var(--muted, #666); margin: 6px 0 2px; line-height: 1.35; }
.sheet-check input { margin-top: 2px; }
.lock-badge { font-size: 12px; color: var(--accent); padding: 2px 8px; border: 1px solid var(--accent); border-radius: 999px; background: var(--glass-strong); align-self: center; display: inline-flex; align-items: center; gap: 4px; }
.lock-badge .ico { width: 14px; height: 14px; }
/* 演示锁（周账 F-124）护栏 ①：工具区灰掉；视图挂件 / ☰ / 工作台下拉照旧（看和玩不锁） */
body.doc-locked .hud-rail-tools, body.doc-locked #toolStrip, body.doc-locked #selBar, body.doc-locked #vcb, body.doc-locked .left-dial { pointer-events: none; opacity: .45; }
/* 左上横排：没有底板，嵌在纸面里；按下 / 悬停才显出可按（user 10-24） */
.hud-topstack { position: absolute; z-index: 5; left: calc(10px + var(--safe-left)); top: calc(8px + var(--safe-top)); display: flex; flex-direction: column; align-items: flex-start; gap: 6px; max-width: calc(100vw - 150px - var(--safe-left) - var(--safe-right)); pointer-events: none; }   /* 左上一列：右边给视图 gizmo 让位；空白处不挡画布 */
.hud-topstack > * { pointer-events: auto; }
.hud-topstack > .hud { position: static; margin-left: 66px; max-width: calc(100% - 66px); }   /* 上下文条 / 面包屑：第二、三排缩到左柱右边（左柱居中、短屏时顶到上面，不缩会压住它；user「再不济也是左柱子右边靠着」） */
.hud-topleft { display: flex; align-items: center; gap: 4px; }
/* 上方正中那颗按钮（FM154：「和嵌入的那些汉堡符号一样低调……enter webxr 这种半灰的感觉，不抢眼」）：没底板、半灰字，悬停才实一点 */
.walk-bar { position: absolute; z-index: 6; top: calc(12px + var(--safe-top)); left: 50%; transform: translateX(-50%); }
.walk-bar[hidden] { display: none; }
.walk-btn { border: 0; background: transparent; color: var(--muted); font: 500 14px/1 system-ui, sans-serif; padding: 10px 14px; border-radius: 9px; cursor: pointer; opacity: .8; filter: drop-shadow(0 1px 1px var(--halo-soft)); }
.walk-btn:hover { background: var(--hover); opacity: 1; color: var(--ink); }
.hud-topleft .tb-btn { width: 40px; height: 40px; background: var(--glass); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }   /* 左上 ☰ / 保存 / 层级 / 物件：毛玻璃底，和工作台下拉、右上那几颗统一（user 10-30「汉堡系的几个没有背景的按钮也改成带背景的吧」） */
.hud-topleft .tb-btn:hover { background: var(--hover); }
.hud-topleft .tb-btn:active, .hud-topleft .tb-btn.is-open { background: var(--accent-soft); color: var(--accent); }
.hud-crumbs { gap: 4px; padding: 4px 10px; font-size: 13px; flex-wrap: wrap; }   /* 住进 .hud-topstack 第三排 */
.crumb { border: 0; background: transparent; font: inherit; color: var(--accent); cursor: pointer; padding: 4px 4px; border-radius: 6px; }
.crumb:hover { background: var(--hover); }
.crumb.current { color: var(--ink); cursor: default; font-weight: 600; }
.crumb-sep { color: var(--muted); }
.crumb-toggle { margin-left: 6px; border: 1px solid var(--line); background: transparent; font: inherit; font-size: 13px; color: var(--muted); cursor: pointer; padding: 3px 8px; border-radius: 999px; }
.crumb-toggle.on { background: var(--accent); border-color: var(--accent); color: #fff; }
/* 网格芯片（0.11 ⑤）：网格开着才露出，右下角、版本号上方；点开 = 格距 / 细分 / 关 */
/* 选区浮条（#19）：顶居中；选中东西且没在手势中才出现；项 = HUD 编辑动作表 */
/* 上下文条里工具段与选区段之间的竖分隔（A25，2026-10-24 Opus；顶部选区浮条 .hud-selbar 已并入上下文条） */
.bar-sep { width: 1px; align-self: stretch; margin: 4px 2px; background: var(--line); }
.selbar-btn { display: inline-flex; align-items: center; gap: 4px; min-height: 36px; padding: 0 10px; border: 0; border-radius: 9px; background: transparent; font: inherit; font-size: 12px; color: var(--ink); cursor: pointer; }
.selbar-btn .ico { width: 18px; height: 18px; }
.selbar-btn:hover { background: var(--hover); }
.selbar-btn:active { background: var(--accent-soft); color: var(--accent); }
.selbar-btn.danger { color: var(--danger); }
#ctxAnchor { position: fixed; width: 0; height: 0; pointer-events: none; }
/* 数值小窗（SU Measurements）：右下、版本角标之上；键盘往上展开 */
.hud-vcb { right: calc(10px + var(--safe-right)); bottom: calc(10px + var(--safe-bottom) + var(--drawer-h)); max-width: min(560px, calc(100vw - 96px)); flex-direction: column; align-items: stretch; gap: 4px; padding: 4px 8px; font-size: 13px; }
.vcb-label { color: var(--muted); font-size: 11px; text-align: right; }
.vcb-field { font: inherit; color: inherit; min-width: 120px; min-height: 32px; border: 1px solid var(--edge); border-radius: 8px; background: var(--field); padding: 4px 10px; text-align: right; font-variant-numeric: tabular-nums; cursor: pointer; }
.vcb-field.typing { border-color: var(--accent); color: var(--accent); }
.vcb-pad { display: flex; flex-direction: column; gap: 4px; padding-top: 4px; }
.vcb-row { display: flex; gap: 4px; }
.vcb-pad-units { display: flex; flex-direction: column; gap: 4px; }
.vcb-pad-units:empty { display: none; }
.vcb-key { flex: 1; min-width: 44px; min-height: 40px; border: 0; border-radius: 8px; background: var(--hover); color: inherit; font: inherit; font-size: 16px; cursor: pointer; }
.vcb-key:active { background: var(--accent-soft); color: var(--accent); }
.vcb-key.primary { background: var(--accent); color: #fff; }
.vcb-key.wide { flex: 3; }
.strip-field { display: inline-flex; align-items: center; gap: 6px; }
.strip-label { color: var(--muted); font-size: 12px; }
.strip-select { font: inherit; color: inherit; border: 1px solid var(--edge); border-radius: 8px; background: var(--field); padding: 4px 8px; min-height: 32px; }
/* 下拉标准件（src/app/ui/select-field.ts，2026-10-24 Opus；照 WeebPaint C6）：按钮钮面 = 当前项 + 右下角小三角（「有三角 = 有菜单」） */
.select-field { display: inline-flex; align-items: center; gap: 6px; position: relative; padding-right: 16px; cursor: pointer; text-align: left; }
.select-field-icon .ico { width: 16px; height: 16px; }
.select-field-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.select-field-caret { position: absolute; right: 5px; bottom: 5px; width: 0; height: 0; border-left: 4px solid transparent; border-top: 4px solid transparent; border-right: 4px solid currentColor; border-bottom: 4px solid currentColor; opacity: .55; }
.strip-number { display: inline-flex; align-items: center; gap: 2px; }
.strip-step { width: 32px; height: 32px; border: 0; border-radius: 8px; background: var(--hover); color: inherit; cursor: pointer; font-size: 16px; }
.strip-step:active { background: var(--accent-soft); color: var(--accent); }
.strip-value { min-width: 40px; text-align: center; font-variant-numeric: tabular-nums; border: 0; background: none; font: inherit; color: inherit; padding: 4px 2px; border-radius: 6px; cursor: text; }
.strip-value:hover { background: var(--hover); }
.strip-input { width: 84px; height: 28px; box-sizing: border-box; border: 1px solid var(--accent); border-radius: 6px; padding: 0 6px; font: inherit; font-variant-numeric: tabular-nums; text-align: center; background: var(--panel, #fff); color: inherit; }
.strip-input.bad { border-color: var(--danger); }
.strip-toggle { min-height: 32px; padding: 0 12px; border: 1px solid var(--edge); border-radius: 8px; background: var(--field); color: inherit; cursor: pointer; }
.strip-toggle.on { background: var(--accent-soft); color: var(--accent); border-color: transparent; }   /* 开关 = 一颗钮，字 = 选项名，亮 = 开（v0.17.61） */
.strip-icon-action { width: 36px; padding: 0; display: inline-grid; place-items: center; }   /* 只画图标的动作钮（删除 = 垃圾桶） */
.strip-icon-action .ico { width: 20px; height: 20px; }
.selbar-btn.icon-only { padding: 0 8px; }
.strip-icon-toggle { width: 34px; height: 32px; display: grid; place-items: center; padding: 0; border: 1px solid var(--edge); border-radius: 8px; background: var(--field); color: var(--muted); cursor: pointer; }   /* 图标开关（拾取 点 / 边 / 面，2026-10-28 Opus） */
.strip-icon-toggle + .strip-icon-toggle { margin-left: 2px; }
.strip-icon-toggle .ico { width: 22px; height: 22px; }
.strip-icon-toggle.on { background: var(--accent-soft); color: var(--accent); border-color: transparent; }
.strip-action { min-height: 32px; padding: 0 12px; border: 1px solid var(--edge); border-radius: 8px; background: var(--field); color: inherit; cursor: pointer; font: inherit; }   /* 工具的动作钮（user 10-24「轴是工具…归工具管」） */
.strip-action:disabled { opacity: .45; cursor: default; }
.tb-btn { width: 40px; height: 40px; display: grid; place-items: center; border: 0; border-radius: 9px; background: transparent; cursor: pointer; color: var(--ink); }
.tb-btn:hover { background: var(--hover); }
.tb-btn:active, .tb-btn.is-open { background: var(--accent-soft); color: var(--accent); }
.tb-btn:disabled { opacity: .3; cursor: default; background: transparent; }
.tb-danger { color: var(--danger); }

.tool { width: 48px; height: 46px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  border: 0; border-radius: 9px; background: transparent; cursor: pointer; color: var(--tool-ink); padding: 0; }
.tool .ico { width: 22px; height: 22px; }
.tool-label { font-size: 10px; line-height: 1; color: var(--muted); }
.tool:hover { background: var(--hover); }
.tool.active { background: var(--accent); color: #fff; }
.tool.active .tool-label { color: #e7f0fb; }
/* 最近用过的非钉工具（≤ 2 格，屏幕矮就 0 格）；和钉死的长一样，只是会变 */
.rail-sep { height: 6px; }   /* 左柱分组：只留空隙，不画线（user 10-24「|线不要试试」） */
.tool { position: relative; }
.tool-badge { position: absolute; right: 2px; top: 2px; min-width: 13px; height: 13px; padding: 0 2px; border-radius: 4px; font: 700 9px/13px system-ui, sans-serif; color: #fff; background: #d9822b; pointer-events: none; }   /* 在另一种做法上（controller/second-mode.ts；user 10-30「也许icon上面要有区分披露」） */
.tool-flyout { position: absolute; right: 3px; bottom: 3px; width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 5px solid var(--ink); }   /* SU 小三角：点角 / 长按 / 右键 = 弹出整组 */
.rail-more { width: 48px; height: 20px; display: grid; place-items: center; border: 0; border-radius: 6px; background: transparent; color: var(--ink); cursor: pointer; }   /* 矮的「…」展开条：弹整组（黑色，不用小箭头） */
.rail-more .ico { width: 16px; height: 16px; }
.rail-more:hover { background: var(--hover); }

#marquee { position: fixed; z-index: 5; border: 1px dashed #666; background: rgba(43,108,176,.08); pointer-events: none; }
/* 套索（选区「空处拖：套索」；2026-10-28 Opus）：和框同一个样子，盖在画布上、点不着 */
#lasso { position: fixed; z-index: 5; pointer-events: none; overflow: visible; }
#lasso polygon { fill: rgba(43,108,176,.08); stroke: #666; stroke-width: 1; stroke-dasharray: 4 3; }
#tip { position: fixed; z-index: var(--z-notice); padding: 2px 7px; font-size: 12px; background: var(--panel); color: var(--ink);
  border: 1px solid #888; border-radius: 4px; pointer-events: none; white-space: nowrap; }
/* 状态行=RPG 对话框：最多两行，超出省略（user 2026-09-07「左下角的状态显示…相当于 rpg 游戏的对话，超出了怎么办」）*/
#hint { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; white-space: normal; overflow-wrap: anywhere; }
.build { color: var(--muted); font-variant-numeric: tabular-nums; }
.hud-build { bottom: calc(8px + var(--safe-bottom) + var(--drawer-h)); left: calc(12px + var(--safe-left)); font-size: 11px; line-height: 1; opacity: .8; white-space: nowrap; }   /* 版本号：页面最左下角（2026-10-26）；左柱底下留 18 px 给它 */
/* 血槽位读数（A28）：手势 dims / 选中面积 / 边长，大一号、tabular */
.readout { display: block; font-size: 15px; font-weight: 600; color: var(--readout); font-variant-numeric: tabular-nums; text-align: right; margin-bottom: 2px; }
.hud-br { text-align: right; }

/* 调试日志 sheet（debug-log-sheet.ts；WeebPaint diag-log 同款）：<pre> 豁免全局 user-select:none，长按/拖选可复制 */
.debug-log-sheet { width: min(720px, 100%); }
.debug-log-pre { max-height: 50vh; overflow: auto; margin: 0 0 4px; padding: 8px; border-radius: 8px; font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  white-space: pre-wrap; word-break: break-word; text-align: left; background: rgba(127,127,127,.12); touch-action: pan-y;
  -webkit-touch-callout: default; -webkit-user-select: text; user-select: text; cursor: text; }

/* 弹出菜单 */
.popup-menu { position: fixed; z-index: var(--z-menu); min-width: 220px; max-width: min(92vw, 360px); max-height: calc(100vh - 12px); overflow-y: auto; padding: 6px; background: var(--panel);
  border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 8px 28px rgba(0,0,0,.14); }
.menu-item { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 40px; padding: 6px 10px; border: 0; border-radius: 7px;
  background: transparent; text-align: left; cursor: pointer; }
.menu-item:hover { background: var(--menu-hover); }
.menu-item:disabled { opacity: .45; cursor: default; }
.menu-item .ico, .ico-gap { width: 20px; height: 20px; flex: 0 0 20px; }
.menu-label { flex: 1; white-space: nowrap; }
.menu-hint { font-size: 11px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 46%; flex: 0 1 auto; }   /* 长提示单行截断：换行会把标签挤歪（user 10-24「汉堡菜单里面的对齐崩了」） */
.menu-section-label { font-size: 11px; color: var(--muted); padding: 10px 10px 2px; user-select: none; letter-spacing: .06em; opacity: .85; }   /* 抄 WeebPaint styles.css（票 2） */
.menu-check { color: var(--accent); }
.menu-sep { height: 1px; margin: 4px 6px; background: var(--line); }
/* ☰ tab 制（A30，2026-10-24 Opus；抄 WeebPaint styles.css .menu-tabs）：图标 + 小字一排，定宽面板里均分 */
.popup-menu.has-tabs { width: min(92vw, 300px); }
.popup-menu.has-tabs .menu-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }   /* 定宽面板：长标签省略，不撑出去 */
.menu-tabs { display: flex; gap: 2px; padding: 2px 2px 4px; border-bottom: 1px solid var(--line); margin-bottom: 4px; }
.menu-tab { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 1px; padding: 4px 2px; background: transparent; border: none; border-radius: 6px; color: var(--muted); cursor: pointer; font: inherit; font-size: 11px; line-height: 1.2; }
.menu-tab span { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.menu-tab .ico { width: 18px; height: 18px; }
.menu-tab.on { color: var(--accent); background: var(--accent-soft); }

/* 通知栈（底部居中；一条栈一个样式） */
#noticeStack { position: fixed; left: 50%; bottom: calc(40px + var(--safe-bottom) + var(--drawer-h)); transform: translateX(-50%); z-index: var(--z-notice);
  display: flex; flex-direction: column; gap: 8px; align-items: center; pointer-events: none; width: min(92vw, 560px); }   /* 定宽：fixed 元素 shrink-to-fit 会在长句 + 按钮时坍成 min-content（中文逐字折行，v0.5.2 崩溃通知截图） */
.toast { pointer-events: auto; display: flex; align-items: center; gap: 10px; padding: 9px 10px 9px 14px; border-radius: 10px; max-width: 100%;
  background: #2f2f2f; color: #fff; box-shadow: 0 6px 20px rgba(0,0,0,.2); font-size: 13px; }
.toast-info { background: #24405e; }
.toast-warning { background: #7a4d00; }
.toast-error { background: #7a1f16; }
.toast-text { flex: 1; }
.toast-actions { display: flex; gap: 6px; }
.toast-btn { padding: 5px 10px; border: 1px solid rgba(255,255,255,.4); border-radius: 6px; background: transparent; color: #fff; cursor: pointer; white-space: nowrap; }
.toast-btn.primary { background: #fff; color: #222; border-color: #fff; }
.toast-x { border: 0; background: transparent; color: rgba(255,255,255,.7); font-size: 18px; line-height: 1; cursor: pointer; padding: 0 4px; }

/* 帮助 sheet */
.sheet-backdrop { position: fixed; inset: 0; z-index: var(--z-help); background: rgba(0,0,0,.25); display: grid; place-items: center; padding: 16px; }
.sheet { width: min(560px, 100%); max-height: 86vh; overflow: auto; background: var(--panel); border-radius: 14px; box-shadow: 0 12px 40px rgba(0,0,0,.25); padding: 10px 16px 16px; touch-action: pan-y; }
.sheet-head { display: flex; align-items: center; justify-content: space-between; font-weight: 600; margin-bottom: 6px; }
/* 底部抽屉（竖屏：大面板从屏幕底下抽上来，不占左右；user 10-24「我还是习惯ipad竖屏，所以物品栏弹出来应该在屏幕底下」） */
.sheet-backdrop.bottom { place-items: end center; padding: 0; }
.drawer { position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-drawer); display: flex; justify-content: center; pointer-events: none; }   /* 非模态：抽屉外面照常能画 */
.drawer[hidden] { display: none; }
.drawer > .sheet { pointer-events: auto; box-shadow: 0 -4px 24px rgba(0,0,0,.18); }
.sheet.sheet-bottom { width: min(720px, 100%); border-radius: 14px 14px 0 0; padding-bottom: calc(16px + var(--safe-bottom)); max-height: 60vh; }
/* 手册（md-lite） */
.md section + section { margin-top: 10px; }
.md h3 { margin: 8px 0 4px; font-size: 14px; }
.md h4 { margin: 8px 0 2px; font-size: 12px; color: var(--muted); }
.md p { margin: 4px 0; font-size: 13px; line-height: 1.5; }
.md ul { margin: 4px 0 4px 18px; padding: 0; font-size: 13px; line-height: 1.5; }
.md code { font-size: 12px; background: rgba(0,0,0,.05); padding: 0 4px; border-radius: 4px; }
.kv { display: grid; grid-template-columns: max-content 1fr; gap: 6px 14px; margin: 0; font-size: 13px; }
.kv dt { color: var(--accent); font-weight: 600; white-space: nowrap; }
.kv dd { margin: 0; color: #444; }

/* 早期错误条 */
.err-banner { position: fixed; left: 0; right: 0; top: 0; z-index: var(--z-err); padding: 10px 14px; background: #b3261e; color: #fff; font-size: 13px; white-space: pre-wrap; }

@media (max-width: 640px) {
  .tool { width: 44px; height: 42px; }
  .tool-label { display: none; }
  .hud-bl { max-width: min(80vw, 720px); }
}
@media (max-height: 560px) {
  .hud-rail-tools { gap: 0; }
  .tool { height: 38px; } .tool-label { display: none; }
}

/* ---- 宿主自己在图库/sheet 里用到的 token ---- */
:root {
  --bg-0: #f4f4f2;
  --bg-1: #ebebe8;
  --paper: #ffffff;
  --ink-muted: #7a7a76;
  --line-strong: #c4c4bf;
  --overlay: rgba(0,0,0,.28);
  --font-ui: system-ui, -apple-system, 'Segoe UI', 'PingFang SC', 'Noto Sans CJK SC', sans-serif;
  --z-busy: 700;
}
/* ---- @internal/gallery / workbench-elements 需要的宿主 token（2026-09-20 转正纪元；包只用 var()，值归宿主） ---- */
:root {
  --bg-soft: #ececea;
  --enc: #c98a00;
  --info: #4c7fb5;
  --ink-soft: #6b6b66;
  --shadow: 0 12px 40px rgba(0,0,0,.25);
  --tile-aspect: 1 / 1;
  --tile-min: 148px;
  --tile-min-narrow: 120px;
  --warn: #b7791f;
  --z-modal: 600;
  --z-overlay: 250;   /* 图库全屏：在 HUD(5) 之上、菜单(300) 之下 */
  --z-popover: var(--z-menu);
  --z-toast: var(--z-notice);
}

/* ---- 转正纪元（2026-09-20）：标题胶囊 / 图库容器 / sheet 模态 / busy ---- */
/* smart save 钮（三条杠下面，对齐 WeebPaint topSaveBtn；user 2026-09-20「最顶上那个 title 意义不明，可以不要」）：
   状态全交给 [data-state]，按钮永远可点（synced 的灰只是「没什么可存」的视觉，不是禁用）。 */
#btnSave { position: relative; }
#btnSave[data-state="none"] { opacity: .45; }
#btnSave[data-state="local-only"], #btnSave[data-state="cloud-off"] { color: var(--muted); }
#btnSave[data-state="dirty"] { color: var(--accent); }
#btnSave[data-state="dirty"]::after { content: ""; position: absolute; right: 7px; top: 7px; width: 7px; height: 7px; border-radius: 50%; background: #b7791f; }
#btnSave[data-state="unpushed"] { color: #b7791f; }
#btnSave[data-state="synced"] { color: #2f7d4f; }
#btnSave[data-state="saving"] .ico { animation: save-pulse 1s ease-in-out infinite; }
@keyframes save-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
.gallery-full { position: fixed; inset: 0; z-index: var(--z-overlay); display: flex; flex-direction: column; background: var(--bg-0); color: var(--ink); font-family: var(--font-ui); }
.gallery-full[hidden] { display: none; }
.gallery-chrome { display: flex; align-items: center; gap: 6px; padding: max(env(safe-area-inset-top, 0px), 8px) 12px 8px; border-bottom: 1px solid var(--line); }
.gallery-chrome-title { font-weight: 600; }
.gallery-chrome .top-spacer { flex: 1 1 auto; }
.gallery-trashbar { display: flex; gap: 8px; padding: 8px 14px; border-bottom: 1px solid var(--line); }
.gallery-trashbar[hidden] { display: none; }
.gallery-homebar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 8px 14px; border-bottom: 1px solid var(--line); font-size: 13px; }
.gallery-homebar[hidden] { display: none; }
.gallery-homebar-text { flex: 1 1 240px; min-width: 0; }
.gallery-homebar .sheet-choice { flex: 0 0 auto; width: auto; }
.gallery-mount { flex: 1 1 auto; overflow: auto; padding: 0 0 12px; display: flex; flex-direction: column; min-height: 0; }
.sheet-modal { width: min(440px, 100%); }
.sheet-title { margin: 4px 0 8px; font-size: 16px; font-weight: 600; }
.sheet-message { margin: 0 0 10px; font-size: 14px; color: #4a4a4a; white-space: pre-wrap; }
.sheet-message.warning { color: #b7791f; }
.sheet-input { width: 100%; box-sizing: border-box; padding: 9px 12px; border: 1px solid var(--line-strong); border-radius: 10px; font: inherit; font-size: 15px; margin-bottom: 8px; }
.sheet-error { margin: 0 0 8px; font-size: 13px; color: var(--danger); }
.sheet-choices { display: flex; flex-direction: column; gap: 8px; margin: 6px 0 4px; }
.sheet-choice { padding: 10px 14px; border-radius: 10px; border: 1px solid var(--line-strong); background: var(--paper); color: inherit; font: inherit; text-align: left; cursor: pointer; }
.sheet-choice.primary { background: var(--accent); color: #fff; border-color: transparent; }
.sheet-choice.danger { color: var(--danger); }
/* 表单 sheet（openFormSheet；导出模型…）：一行 = 标签 + 分段单选钮（2026-10-28 Opus） */
.sheet-form { gap: 10px; }
.sheet-field { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.sheet-field-label { color: var(--muted); font-size: 13px; min-width: 3em; }
.sheet-seg { display: flex; gap: 4px; flex-wrap: wrap; }
.sheet-seg button { padding: 6px 12px; border-radius: 8px; border: 1px solid var(--line-strong); background: var(--paper); color: inherit; font: inherit; font-size: 13px; cursor: pointer; }
.sheet-seg button[aria-checked="true"] { background: var(--accent-soft); color: var(--accent); border-color: var(--accent); }
.sheet-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }
.busy-overlay { position: fixed; inset: 0; z-index: var(--z-busy); background: rgba(0,0,0,.25); display: grid; place-items: center; cursor: default; }
.busy-overlay[hidden] { display: none; }
/* 同步闸门（工单 C，2026-11-03）：本机那份摆着、罩住、不接输入。层级 = 通知（400）之上、面板（500）之下——库的冲突面要能盖在罩子上。
   开头 120 ms 不显形：核对很快（目标 < 300 ms）时看不出闪了一下；输入从第一帧就锁了，钮也已经在。 */
.sync-gate { position: fixed; inset: 0; z-index: 450; display: grid; place-items: center; padding: 16px; background: rgba(0,0,0,.18); -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px); animation: sync-gate-in .16s ease-out .12s both; }
.sync-gate[hidden] { display: none; }
.sync-gate-card { width: min(360px, 92vw); text-align: center; }
.sync-gate-card .sheet-actions { justify-content: center; flex-wrap: wrap; }
.sync-gate-note { opacity: .75; font-size: 12px; }
.sync-gate-spinner { width: 22px; height: 22px; margin: 6px auto 10px; border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; opacity: .55; animation: sync-gate-spin .8s linear infinite; }
.sync-gate-spinner[hidden] { display: none; }
@keyframes sync-gate-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes sync-gate-spin { to { transform: rotate(360deg); } }
.busy-card { width: min(320px, 90vw); text-align: center; }

/* 材质面板（贴图纪元 2026-10-21）：油漆桶蘸什么 */
.swatch-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 8px; padding: 12px 16px; max-height: 50vh; overflow: auto; }
.swatch { position: relative; aspect-ratio: 1; border-radius: 8px; border: 2px solid rgba(0,0,0,.12); cursor: pointer; padding: 0; min-height: 56px; }
.swatch.active { border-color: #2b6cb0; box-shadow: 0 0 0 2px rgba(43,108,176,.35); }
.swatch-label { position: absolute; left: 0; right: 0; bottom: 0; font-size: 11px; line-height: 1.3; padding: 2px 0; background: rgba(255,255,255,.78); color: #222; border-radius: 0 0 6px 6px; }
/* B43 尺度参考（2026-10-25 Opus）：跟指针提示框第二行，只有字的深浅（scale-tip.ts） */
#tip .tip-ref { margin-top: 1px; font-size: 11px; color: var(--muted); }
#tip .tip-measure { font-weight: 700; font-variant-numeric: tabular-nums; }
#tip .tip-sign { font-size: 9px; margin-left: 1px; vertical-align: super; line-height: 0; }
#tip .tip-snap { margin-left: 6px; font-size: 11px; color: var(--muted); }
#tip .tip-ref .sep { opacity: .35; }
/* 弹出菜单的「纯文字说明」（B43 参考页）和下拉行（当前值 ▾） */
.menu-note { padding: 3px 12px; font-size: 11.5px; line-height: 1.45; color: var(--muted); white-space: normal; max-width: 300px; }
.menu-field .menu-value { position: relative; max-width: 52%; flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; padding: 3px 20px 3px 8px; border: 1px solid rgba(0,0,0,.14); border-radius: 6px; }
.menu-field .menu-value::after { content: ""; position: absolute; right: 7px; top: 50%; margin-top: -2px; border: 4px solid transparent; border-top-color: currentColor; border-bottom-width: 0; opacity: .6; }
.menu-field.is-open .menu-value { border-color: var(--accent); color: var(--accent); }
/* 一行并排几个小控件（popup-menu inline；尺度参考那一行：看哪些 ▾ · 最多 ▾ · 适用范围与出处）。带页签的 ☰ 定宽 300：字小一号、边距收紧，放不下时第一个下拉自己省略 */
.menu-inline { display: flex; flex-wrap: nowrap; align-items: center; gap: 4px; padding: 4px 2px 4px 6px; white-space: nowrap; }
.menu-inline .menu-chip { width: auto; min-width: 0; min-height: 32px; padding: 0; flex: 0 1 auto; }
.menu-inline .menu-chip.menu-field .menu-value { max-width: none; font-size: 12px; padding: 3px 16px 3px 6px; }
.menu-inline .menu-chip-btn { flex: 0 0 auto; gap: 6px; padding: 2px 4px; font-size: 12px; text-decoration: underline; text-underline-offset: 3px; }
.menu-inline .menu-chip-btn .menu-hint { text-decoration: none; }
/* 下拉层（choice-layer.ts：下拉行的单选 / 下拉多选）：比普通菜单紧一点、长了自己滚 */
.popup-menu.choice-layer { min-width: 180px; max-height: min(70vh, 520px); overflow-y: auto; }
.popup-menu.choice-layer .menu-item { min-height: 30px; padding: 3px 10px; }
.popup-menu.choice-layer .ms-clear { color: var(--muted); }
/* 子菜单（2026-10-27 Opus）：行尾一个向右的小三角（同下拉行 ▾ 的画法，不用字形）；开着的那一行保持高亮 */
.menu-sub .menu-sub-mark { flex: 0 0 auto; width: 0; height: 0; margin-right: 2px; border: 4px solid transparent; border-left-color: currentColor; border-right-width: 0; opacity: .6; }
.menu-sub.is-open { background: var(--menu-hover); }
.popup-menu.choice-layer.submenu .menu-item { min-height: 40px; padding: 6px 10px; }   /* 子菜单的行和普通菜单一样高（下拉层那层更紧） */

/* 步行 FPS 的触屏操作层（吃鸡式，纪元账本 FM142；src/app/touch-controls.ts）：左半屏摇杆、右半屏转头、右下跳 / 蹲、上方两颗低调的 */
.touch-ctl { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.touch-ctl[hidden] { display: none; }
.tc-zone { position: absolute; top: 15%; bottom: 0; pointer-events: auto; touch-action: none; }
.tc-left { left: 0; width: 50%; }
.tc-right { right: 0; width: 50%; }
.tc-base { position: absolute; left: 0; top: 0; border-radius: 50%; border: 2px solid rgba(255,255,255,.75); background: rgba(0,0,0,.12); box-shadow: 0 1px 4px rgba(0,0,0,.25); pointer-events: none; }
.tc-knob { position: absolute; left: 0; top: 0; width: 48px; height: 48px; border-radius: 50%; background: rgba(255,255,255,.85); box-shadow: 0 1px 4px rgba(0,0,0,.3); pointer-events: none; }
.tc-knob.is-dash { background: var(--accent); }
.tc-base.is-idle, .tc-knob.is-idle { opacity: .45; }   /* 没按的时候：左下角淡淡的一个，告诉你往哪按 */
.tc-btn { position: absolute; width: 64px; height: 64px; border-radius: 50%; border: 2px solid rgba(255,255,255,.8); background: rgba(0,0,0,.18); color: #fff; font: 600 16px/1 system-ui, sans-serif; pointer-events: auto; touch-action: none; text-shadow: 0 1px 2px rgba(0,0,0,.5); }
.tc-btn.is-on { background: var(--accent); }
.tc-jump { right: calc(24px + var(--safe-right)); bottom: calc(110px + var(--safe-bottom)); }
.tc-crouch { right: calc(100px + var(--safe-right)); bottom: calc(40px + var(--safe-bottom)); width: 52px; height: 52px; font-size: 14px; }
.tc-crawl { right: calc(30px + var(--safe-right)); bottom: calc(40px + var(--safe-bottom)); width: 52px; height: 52px; font-size: 14px; }
.tc-top { position: absolute; top: calc(12px + var(--safe-top)); border: 0; background: transparent; color: var(--muted); font: 500 14px/1 system-ui, sans-serif; padding: 10px 14px; border-radius: 9px; pointer-events: auto; opacity: .8; filter: drop-shadow(0 1px 1px rgba(255,255,255,.9)); }
.tc-leave { left: 50%; transform: translateX(calc(-100% - 6px)); }   /* 正中两侧（FPS 里正中那颗「继续走」不露） */
.tc-edit { left: 50%; transform: translateX(6px); }
/* 要等的大活的细进度条（ui/work-bar.ts；MoonSinger .render-bar 同款，账本 UX7）：顶边 3 px，不占版面、不弹框；条纹用 transform 动（主线程卡住也动） */
.work-bar { position: fixed; left: 0; right: 0; top: var(--safe-top, 0px); height: 3px; z-index: 60; pointer-events: none; overflow: hidden; background: var(--accent-soft); }
.work-bar[hidden] { display: none; }
.work-bar .wb-run { position: absolute; top: 0; bottom: 0; left: 0; width: 35%; background: var(--accent); animation: wb-slide 1.1s ease-in-out infinite; will-change: transform; }
@keyframes wb-slide { from { transform: translateX(-100%); } to { transform: translateX(290%); } }
@media (prefers-reduced-motion: reduce) { .work-bar .wb-run { animation: none; width: 100%; opacity: .6; } }
/* 键名芯片（MFD；app/mfd.ts，账本 UX19）：提示行上面一排固定槽位；能点的芯片带底、只显示的（修饰键）是描边 */
.mfd { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; pointer-events: auto; text-shadow: none; flex-wrap: wrap; }
.mfd[hidden] { display: none; }
.mfd-slot { display: flex; gap: 4px; }
.mfd-slot.empty { display: none; }
/* 低调（user 10-28 晚「chip做的和马后炮一样视觉上低调可以吗」）：和右下「刚才：」同一档——灰小字、没有白底胶囊；键名 = 描边小框不是黑底；亮 = 只换强调色 */
.mfd-chip { display: inline-flex; align-items: center; gap: 4px; padding: 2px 6px 2px 3px; border-radius: 6px; border: 1px solid transparent; background: transparent; color: var(--muted); font: inherit; font-size: 12px; line-height: 1.3; }
.mfd-chip.pressable { cursor: pointer; border-color: var(--line); }
.mfd-chip.pressable:active { background: var(--accent-soft); }
.mfd-chip kbd { font: 600 10px/1 system-ui, sans-serif; padding: 2px 4px; border-radius: 4px; border: 1px solid var(--line-strong); background: transparent; color: var(--muted); }
.mfd-chip.nokeys { padding: 4px 9px; }   /* 没键盘（笔 / 手指）：不印键名，只剩意思；手指要点得中 */
.mfd-chip.on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }   /* 锁着的轴 / 按着或锁住的修饰键 */
.mfd-chip.on kbd { color: var(--accent); border-color: var(--accent); }
.mfd-toggle { border: 0; background: transparent; border-radius: 6px; font: inherit; font-size: 12px; padding: 4px 6px; cursor: pointer; color: var(--muted); }
.mfd-toggle[hidden] { display: none; }
/* 指令板（ui/command-board.ts；UX 心智模型 §8 补 4）：浮在画面上、按住标题拖、长按标题归位；手机竖屏 = 底部不锁屏抽屉（和物品栏同一个位置） */
/* 常驻浮窗（ui/floating-window.ts + ui/menu-window.ts；2026-10-30 Opus：视图 / 物件，user 10-29「我建议是视图 物体 都做成可以常驻的浮窗吧，只有主菜单是菜单型的」）：
   z 序归 floating-window（内联 z-index = --z-window + 栈位）；里面的菜单 = 弹出菜单同一份画法，去掉自己的定位 / 外框 */
.float-win { position: fixed; top: 64px; right: 16px; width: min(92vw, 300px); max-height: 72vh; display: flex; flex-direction: column; background: var(--panel, #fff);
  border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 6px 24px rgba(0,0,0,.16); overflow: hidden; }
.float-win[hidden] { display: none; }
.float-head { display: flex; align-items: center; gap: 8px; padding: 6px 8px 6px 12px; cursor: grab; touch-action: none; user-select: none; border-bottom: 1px solid var(--line, #ddd); }
.float-title { flex: 1; font-weight: 600; font-size: 13px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.float-close { margin-left: auto; border: 0; background: none; font-size: 18px; line-height: 1; cursor: pointer; color: var(--muted); padding: 2px 6px; border-radius: 6px; }
.float-close:hover { background: var(--menu-hover); }
.float-win .float-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 6px; }
/* 层级浮窗（hierarchy-window.ts；0.18 I1）：一行 = 小三角 · 名字 · [锁] · 小眼睛 · …，缩进 = padding-left；没起名（四位码）= 等宽淡色（MoonSinger 同款） */
.float-win .tree-body { padding: 4px 2px; }
.tree-row { display: flex; align-items: center; gap: 2px; min-height: 32px; border-radius: 6px; user-select: none; -webkit-user-select: none; }
.tree-row:hover { background: var(--hover); }
.tree-row.is-selected { background: var(--accent); color: #fff; }
.tree-row.is-here > .tree-name { font-weight: 700; }
.tree-row.is-hidden > .tree-name { opacity: .45; }
.tree-caret { width: 22px; height: 28px; flex: none; border: 0; padding: 0; background: none; color: inherit; font-size: 11px; }
.tree-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.tree-name.is-unnamed { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; opacity: .55; }
.tree-row.is-hidden > .tree-name.is-unnamed { opacity: .3; }
.tree-eye, .tree-more { width: 30px; height: 30px; flex: none; border: 0; padding: 5px; border-radius: 6px; background: none; color: inherit; }
.tree-eye .ico, .tree-more .ico, .tree-lock .ico { width: 18px; height: 18px; }
.tree-lock { display: inline-flex; opacity: .6; }
.tree-kind { display: inline-flex; flex: none; opacity: .65; margin-right: 2px; }   /* 种类小图标（user 10-30「每个物体能显示自己的type as icon」） */
.tree-kind .ico { width: 15px; height: 15px; }
.tree-count { flex: none; font-size: 12px; color: var(--muted); padding: 2px 6px; font-variant-numeric: tabular-nums; border: 0; background: none; font-family: inherit; border-radius: 6px; cursor: pointer; }
.tree-count:hover { background: var(--menu-hover); }
.tree-row.in-band { box-shadow: inset 3px 0 0 var(--muted); }   /* 手风琴摊开的那一组（合成行 + 那几份）：同一深度、左边一条竖线圈住——不是缩进，不是孩子 */   /* 「×N」合成行（user 10-30「collapse同实例变成 x几」） */
.tree-row.is-selected .tree-count, .tree-row.is-selected .tree-kind { color: inherit; opacity: .9; }
/* 浮窗标题 = 下拉（user 10-30「窗口名字就是下拉」）：「层级 ▾」，点开换页；只占标题那一小块，不拖窗 */
/* 一键藏起所有窗（ui/hide-windows.ts；四指轻点 / \ 键）：窗口自己的开关不动，样式藏掉 */
html.windows-hidden .float-win, html.windows-hidden .board, html.windows-hidden wp-reference-window { display: none !important; }
.float-title-menu { flex: 0 1 auto; display: inline-flex; align-items: center; gap: 4px; border: 0; background: none; color: inherit; font: inherit; padding: 2px 6px; margin-left: -6px; border-radius: 6px; cursor: pointer; }
.float-title-menu:hover { background: var(--hover); }
/* 标题是下拉的窗：下拉只占字那么宽、关闭钮靠右，中间空着的那段 = 拖把（user 10-30「dropdown占满整个width那窗口没法拖动了」：下拉本身不起拖，占满就没地方抓）。 */
.float-title-caret { font-size: 11px; opacity: .7; }
/* 层级拖拽（0.18 I3，ui/tree-drag.ts）：放进去 = 整行描边；插入 = 一条带缩进的线 + 父亲那行淡底；拖着的那行变淡 */
.tree-pane { position: relative; }
.tree-row { -webkit-touch-callout: none; touch-action: pan-y; }
.tree-pane.is-dragging .tree-row { cursor: grabbing; }
.tree-row.is-drag-source { opacity: .45; }
.tree-row.is-drop-into { box-shadow: inset 0 0 0 2px var(--accent); }
.tree-row.is-drop-parent { background: var(--accent-soft, var(--hover)); }
.tree-drop-line { position: absolute; right: 4px; height: 2px; border-radius: 1px; background: var(--accent); pointer-events: none; }
.tree-drop-line::before { content: ""; position: absolute; left: -4px; top: -3px; width: 8px; height: 8px; border-radius: 50%; border: 2px solid var(--accent); background: var(--bg, #fff); box-sizing: border-box; }
/* 层级窗第二页「资源」（0.18 I10）：组件 / 材质清点 + 清理没人用的组件 */
.res-head { font-size: 12px; color: var(--muted); padding: 8px 6px 2px; }
.res-row { gap: 6px; padding: 0 6px; min-height: 28px; }
.res-row.is-orphan > .tree-name { opacity: .5; }
.res-meta { flex: none; font-size: 12px; color: var(--muted); }
.res-row.is-orphan > .res-meta { color: var(--warn, var(--muted)); }
.res-swatch { width: 14px; height: 14px; flex: none; border-radius: 3px; border: 1px solid var(--line); }
.res-foot { padding: 8px 4px 4px; display: flex; flex-direction: column; gap: 6px; }
.res-purge { min-height: 32px; border-radius: 8px; border: 1px solid var(--line); background: var(--panel, transparent); color: inherit; font: inherit; font-size: 13px; padding: 4px 10px; }
.res-purge:disabled { opacity: .5; }
.res-note { font-size: 12px; color: var(--muted); line-height: 1.4; }
.float-menu .menu-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }   /* 定宽浮窗：长标签省略（同 .popup-menu.has-tabs） */
.board { position: fixed; z-index: 240; width: 300px; max-height: 70vh; display: flex; flex-direction: column; background: var(--panel, #fff); border-radius: 12px; box-shadow: 0 6px 24px rgba(0,0,0,.18); overflow: hidden; }
.board-head { display: flex; align-items: center; gap: 8px; padding: 8px 10px; cursor: grab; touch-action: none; user-select: none; border-bottom: 1px solid var(--line, #ddd); }
.board-title { flex: 1; font-weight: 600; font-size: 13px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-close { border: 0; background: none; font-size: 18px; line-height: 1; cursor: pointer; color: var(--muted); padding: 0 4px; }
.board-body { overflow: auto; padding: 8px 10px; display: flex; flex-direction: column; gap: 8px; }
.board-params:empty { display: none; }
.board-params .vcb-params { align-items: stretch; }
.board-params .vcb-params-fields, .board-params .vcb-params-buttons { justify-content: flex-start; }
.board-params .vcb-params-note { max-width: none; }
.board-list { display: flex; flex-direction: column; gap: 4px; }
.board-cmd { text-align: left; padding: 7px 10px; border-radius: 8px; border: 1px solid var(--line-strong); background: var(--paper); color: inherit; font: inherit; font-size: 13px; cursor: pointer; }
.board-cmd:disabled { opacity: .5; cursor: default; }
.board-note { font-size: 12px; color: var(--muted); }
.board.board-drawer { left: 0 !important; right: 0; top: auto !important; bottom: 0; width: auto; max-height: 50vh; border-radius: 14px 14px 0 0; }
.board.board-drawer .board-head { cursor: default; }
/* 软选择：半径竖滑条（WeebPaint 左栏同款，放在左柱右边、竖着居中；只在用得上时露）+ 画布上的半径圈 */
.left-dial { position: fixed; z-index: 6; left: calc(76px + var(--safe-left, 0px)); top: 50%; transform: translateY(-50%); display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 8px 4px; width: 40px; box-sizing: border-box;
  background: color-mix(in srgb, var(--panel) 80%, transparent); -webkit-backdrop-filter: blur(16px) saturate(180%); backdrop-filter: blur(16px) saturate(180%); border: 1px solid var(--line); border-radius: 12px; box-shadow: 0 6px 20px rgba(0,0,0,.12); }   /* 左栏 dial = WeebPaint .left-sidebar 那张卡片（left-dial.ts；2026-10-29 Opus） */
.left-dial[hidden], .left-dial-slot[hidden] { display: none; }
.left-dial-slot { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.left-dial-label { color: var(--muted); line-height: 0; user-select: none; }
/* 自己画的竖滑条（ui/vslider.ts）：一根细轨 + 墨色填充 + 圆钮；--p = 0..1（下 → 上） */
.vslider { position: relative; width: 28px; height: 120px; touch-action: none; cursor: ns-resize; outline: none; --thumb: 20px; }
.vslider-track { position: absolute; left: 50%; top: calc(var(--thumb) / 2); bottom: calc(var(--thumb) / 2); width: 4px; transform: translateX(-50%); border-radius: 2px; background: var(--line); overflow: hidden; }
.vslider-fill { position: absolute; left: 0; right: 0; bottom: 0; height: calc(var(--p) * 100%); background: var(--ink); }
.vslider-thumb { position: absolute; left: 50%; width: var(--thumb); height: var(--thumb); transform: translateX(-50%); bottom: calc(var(--p) * (100% - var(--thumb))); border-radius: 50%; background: var(--panel); border: 2px solid var(--ink); box-sizing: border-box; box-shadow: 0 1px 4px rgba(0,0,0,.25); }
.vslider:focus-visible .vslider-thumb { box-shadow: 0 0 0 3px var(--accent-soft), 0 1px 4px rgba(0,0,0,.25); }
.vslider-bubble { position: absolute; left: calc(100% + 14px); bottom: calc(var(--p) * (100% - var(--thumb)) - 4px); white-space: nowrap; padding: 4px 8px; border-radius: 8px; background: var(--ink); color: var(--panel); font-size: 12px; font-variant-numeric: tabular-nums; pointer-events: none; box-shadow: 0 2px 8px rgba(0,0,0,.2); }
.vslider-bubble[hidden] { display: none; }
#softRing { position: fixed; z-index: 5; pointer-events: none; overflow: visible; }
#softRing circle { fill: none; stroke: var(--accent, #2b6cb0); stroke-width: 1.5; stroke-dasharray: 5 4; opacity: .8; }
/* 扩 / 缩选区的拖动条（app/sel-grow-bar.ts）：低调小胶囊，出在点的那一下下面 */
.selgrow { position: fixed; z-index: 30; display: flex; align-items: center; gap: 6px; padding: 4px 8px; border-radius: 999px; background: color-mix(in srgb, var(--panel, #fff) 88%, transparent); border: 1px solid var(--line); box-shadow: 0 2px 8px rgba(0,0,0,.08); font-size: 12px; color: var(--muted); user-select: none; }
.selgrow[hidden] { display: none; }
.selgrow-btn { width: 26px; height: 26px; border: 1px solid var(--line); border-radius: 999px; background: transparent; color: var(--ink); font: inherit; font-size: 15px; line-height: 1; cursor: pointer; }
.selgrow-track { position: relative; width: 90px; height: 22px; border-radius: 999px; background: var(--line); touch-action: none; cursor: ew-resize; }
.selgrow-knob { position: absolute; left: 50%; top: 50%; width: 18px; height: 18px; margin: -9px 0 0 -9px; border-radius: 999px; background: var(--accent, #2b6cb0); }
.selgrow-label { min-width: 52px; text-align: center; }

/* 界面夜间那套（Tron 账本 T147 / T167；2026-10-30 Claude Opus 5.5）：画风的纸是深色（preset/colors.ts isDarkPaper，现在 = Tron）时 body 挂 .ui-night——
   HUD / 浮窗 / 指令板 / 弹出菜单 / 提示框一起换（面板底、图标、字、描边光晕），不逐个手调；图库 / 模态对话框不跟（它们不在画布上，和这个模型的画风无关）。 */
body.ui-night :is(.hud, .hud-text, .hud-gizmo, .hud-topstack, .walk-bar, .float-win, .board, .left-dial, .popup-menu, .menu-panel, .selgrow, #tip, .tc-top) {
  --bg: #0b0f14; --panel: #1a1f26; --ink: #e6e9ee; --muted: #9aa3ad; --line: #3a414b; --line-strong: #4a525d;
  --accent: #5aa9ff; --accent-soft: rgba(90,169,255,.18);
  --glass: rgba(16,20,26,.62); --glass-strong: rgba(16,20,26,.82); --field: #232932; --halo: #000; --halo-soft: rgba(0,0,0,.85);
  --hover: rgba(255,255,255,.08); --edge: rgba(255,255,255,.16); --tool-ink: #d6dbe1; --hud-text: #cfd5dc; --readout: #eef1f4; --menu-hover: rgba(255,255,255,.08);
  --paper: #1a1f26; --bg-0: #151a20; --bg-1: #1d232b; --bg-soft: #1d232b; --ink-muted: #9aa3ad; --ink-soft: #b3bac2;
  color: var(--ink);
}
