/* AI 绘图工作台 —— 视觉规范实现。
   色板/字体/断点数值来自 docs/superpowers/specs/2026-07-17-ai-image-studio-design.md §5
   及 task-4 brief「视觉规范」一节，均以 CSS 变量集中声明，避免散落魔法值。 */

:root {
  --bg: #0b0e14;
  --panel: #131722;
  --border: rgba(255, 255, 255, .08);
  --radius: 12px;
  --text: #e6e9f0;
  --text-secondary: #8b93a7;
  --accent-grad: linear-gradient(135deg, #7c5cff, #38bdf8);
  --error-bg: rgba(248, 81, 73, .15);
  --error-text: #ff7b72;
  --font: system-ui, -apple-system, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
}

/* 全屏查看（Lightbox）打开期间锁定背景滚动（Task 7 事件里 openLightbox/close 钩子切换）。 */
body.scroll-locked { overflow: hidden; }

button, input, textarea { font-family: inherit; }

/* ---------- 顶栏 ---------- */

.topbar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border);
}

.topbar::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--accent-grad);
  opacity: .6;
}

.site-name {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

#keyBtn {
  padding: 8px 16px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, .04);
  color: var(--text);
  cursor: pointer;
  font-size: .85rem;
  transition: background-color .15s;
  white-space: nowrap;
}

#keyBtn:hover { background: rgba(255, 255, 255, .09); }

/* ---------- 主布局：桌面两栏，≤900px 单栏（面板依源码顺序在上） ---------- */

.layout {
  display: grid;
  grid-template-columns: 500px 1fr;
  gap: 28px;
  max-width: 1600px;
  margin: 28px auto;
  padding: 0 28px;
}

@media (max-width: 900px) {
  /* 移动端保持放大前的原始间距——桌面这版只做"放大"，移动端不跟着一起放大内边距。 */
  .layout {
    grid-template-columns: 1fr;
    gap: 20px;
    margin: 20px auto;
    padding: 0 24px;
  }
  .panel, .stage { padding: 20px; }
  #resultArea { min-height: 360px; }
}

.panel, .stage {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 12px 32px -16px rgba(0, 0, 0, .6);
}

/* ---------- 参数面板：字段纵向排布，label 紧贴其后的控件 ---------- */

.panel {
  display: flex;
  flex-direction: column;
}

.panel > label {
  margin: 18px 0 8px;
  font-size: .9rem;
  font-weight: 600;
  color: var(--text-secondary);
}

.panel > label:first-child { margin-top: 0; }

.panel > small {
  display: block;
  margin: -4px 0 0;
  color: var(--text-secondary);
  font-size: .78rem;
}

#promptInput {
  width: 100%;
  min-height: 160px;
  padding: 12px;
  resize: vertical;
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  font-size: 1rem;
}

#promptInput::placeholder { color: var(--text-secondary); }

#promptInput:focus, #customRow input:focus, #keyInput:focus {
  outline: 2px solid #7c5cff;
  outline-offset: 1px;
}

/* ---------- 比例芯片 + segmented 控件：共享底色/边框/hover/选中/禁用语言 ---------- */

.chip, .seg {
  border: 1px solid var(--border);
  border-radius: 10px;
  background: rgba(255, 255, 255, .04);
  color: var(--text);
  cursor: pointer;
  transition: background-color .15s, border-color .15s, opacity .15s, transform .15s;
}

.chip:hover:not(.selected):not(:disabled),
.seg:hover:not(.selected):not(:disabled) {
  background: rgba(255, 255, 255, .09);
}

.chip:active:not(:disabled), .seg:active:not(:disabled) {
  transform: scale(.96);
}

.chip.selected, .seg.selected {
  border-color: transparent;
  font-weight: 600;
  background-image: linear-gradient(var(--panel), var(--panel)), var(--accent-grad);
  background-origin: border-box;
  background-clip: padding-box, border-box;
}

.seg:disabled, .chip:disabled {
  opacity: .45;
  cursor: not-allowed;
}

#ratioGrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 8px;
}

.chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 56px;
  padding: 8px 4px;
  font-size: .78rem;
}

.chip-shape {
  background: rgba(255, 255, 255, .35);
  border-radius: 2px;
}

.chip.selected .chip-shape { background: rgba(255, 255, 255, .9); }

#tierSeg, #qualitySeg, #countSeg {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.seg {
  padding: 8px 18px;
  font-size: .85rem;
}

/* ---------- Custom 行：flex 环绕，customErr 用 flex-basis 独占一行 ----------
   自定义尺寸（customRow，像素 宽×高）与自定义比例（customRatioRow，比例份数 宽:高）
   结构与交互一致，共用同一套布局/输入框/label 样式，仅错误文案容器分开
   （customErr 是逐条红字列表，customRatioErr 是 computeSize 抛出的单条 Error）。 */

#customRow, #customRatioRow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

#customRow[hidden], #customRatioRow[hidden] { display: none; }

#customRow label, #customRatioRow label {
  color: var(--text-secondary);
  font-size: .85rem;
}

#customRow input[type="number"], #customRatioRow input[type="number"] {
  width: 96px;
  padding: 8px 10px;
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: .9rem;
}

/* 自定义比例的份数输入框只需 1~99 两位数，比像素输入框窄一些。 */
#customRatioRow input[type="number"] { width: 64px; }

.custom-x { color: var(--text-secondary); }

#customErr, #customRatioErr {
  flex-basis: 100%;
  color: var(--error-text);
  font-size: .82rem;
}

#customErr .err-line { margin-top: 2px; }
#customErr .err-line:first-child { margin-top: 0; }

/* ---------- 尺寸预览 + 生成按钮 ---------- */

#sizePreview {
  margin: 14px 0 4px;
  color: var(--text-secondary);
  font-size: .88rem;
  min-height: 1.3em;
}

#generateBtn {
  width: 100%;
  margin-top: 8px;
  padding: 14px;
  border: none;
  border-radius: 10px;
  background: var(--accent-grad);
  color: var(--text);
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: .02em;
  cursor: pointer;
  box-shadow: 0 8px 24px -8px rgba(124, 92, 255, .5);
  transition: filter .15s, opacity .15s, transform .15s;
}

#generateBtn:hover:not(:disabled) { filter: brightness(1.08); }
#generateBtn:active:not(:disabled) { transform: scale(.98); }
#generateBtn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }

/* 并发上限提示：仅在 3 个任务同时在飞时出现，不设 display（div 默认 block），
   隐藏靠原生 [hidden] 即可，无需类似 #customRow 的显式覆盖（那是因为它有 ID
   选择器的 display:flex 规则在跟 [hidden] 抢优先级，这里没有）。 */
#dispatchHint {
  margin-top: 8px;
  color: var(--text-secondary);
  font-size: .78rem;
  text-align: center;
}

/* ---------- 结果区 ---------- */

.stage {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

#errorBar {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--error-bg);
  color: var(--error-text);
  border-radius: 10px;
  padding: 12px 16px;
  font-size: .9rem;
}

/* ID 选择器的 display:flex 特异性高于 UA 的 [hidden]{display:none}，须显式覆盖
   （与 #customRow 同一坑，见 style.css 中 #customRow[hidden] 的先例）。 */
#errorBar[hidden] { display: none; }

.error-text { flex: 1; }

.error-close {
  flex-shrink: 0;
  padding: 0 4px;
  border: none;
  background: none;
  color: inherit;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  opacity: .75;
  transition: opacity .15s;
}

.error-close:hover { opacity: 1; }

#resultArea {
  flex: 1;
  min-height: 560px;
  display: flex;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: rgba(255, 255, 255, .02);
  padding: 16px;
  overflow: auto;
}

.placeholder {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: var(--text-secondary);
  font-size: .95rem;
}

/* ---------- 结果网格：n=1 单张大图，n>1 两列（骨架占位与最终结果共用同一网格外形） ---------- */

.result-grid {
  flex: 1;
  display: grid;
  gap: 12px;
  align-content: start;
}

.result-grid--single { grid-template-columns: 1fr; }
.result-grid--multi { grid-template-columns: repeat(2, 1fr); }

@media (max-width: 640px) {
  .result-grid--multi { grid-template-columns: 1fr; }
}

@keyframes skeleton-pulse {
  0%, 100% { opacity: .5; }
  50% { opacity: 1; }
}

.skeleton-tile {
  border-radius: 10px;
  background-image: var(--accent-grad);
  opacity: .5;
  animation: skeleton-pulse 1.4s ease-in-out infinite;
}

.result-tile {
  position: relative;
  border-radius: 10px;
  overflow: hidden;
  background: rgba(0, 0, 0, .2);
}

.result-grid--single .result-tile { max-height: 640px; }

.result-tile img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  cursor: zoom-in;
}

.tile-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  padding: 10px;
  background: linear-gradient(to top, rgba(0, 0, 0, .55), transparent 45%);
  opacity: 0;
  transition: opacity .15s;
  /* overlay 用 inset:0 铺满整个 tile（视觉上只在悬停时露出渐变角标），但作为绝对定位
     元素，它在 img 之上一直吃着整块 tile 的指针事件——不加这行，.result-tile img 上
     声明的 cursor:zoom-in 永远显示不出来（悬浮其上的实际是这层）。 */
  cursor: zoom-in;
}

.result-tile:hover .tile-overlay,
.result-tile:focus-within .tile-overlay {
  opacity: 1;
}

.tile-download {
  padding: 6px 12px;
  border-radius: 8px;
  background: rgba(0, 0, 0, .55);
  color: var(--text);
  font-size: .8rem;
  text-decoration: none;
  transition: background-color .15s, transform .15s;
  cursor: pointer; /* 显式声明，避免继承自 .tile-overlay 的 zoom-in 盖过链接本该有的指针光标 */
}

.tile-download:hover { background: rgba(0, 0, 0, .75); }
.tile-download:active { transform: scale(.95); }

/* ---------- 派发任务模式：resultArea 内的任务卡片流（Task 8b）----------
   一次派发对应一张卡片，最新的用 insertBefore 插到最前面；未完成时 body 是骨架，
   成功后替换成结果图网格（复用上面的 .result-grid 系列类），失败则整块 body 移除，
   错误文案直接写进 header 的状态文字里。 */
.task-stream {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.task-card {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  background: rgba(255, 255, 255, .02);
}

.task-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
  font-size: .9rem;
  font-weight: 600;
}

.task-status--error { color: var(--error-text); font-weight: 500; }

.task-dismiss {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, .06);
  color: var(--text);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color .15s;
}

.task-dismiss:hover { background: rgba(255, 255, 255, .12); }

/* .task-dismiss 有显式 display:flex（居中 "×"），与 #customRow 同一坑：
   须显式覆盖 [hidden]，否则隐藏态仍会以 flex 布局显示一个空按钮。 */
.task-dismiss[hidden] { display: none; }

.task-params {
  margin-bottom: 6px;
  color: var(--text-secondary);
  font-size: .8rem;
}

.task-prompt {
  margin-bottom: 12px;
  color: var(--text-secondary);
  font-size: .82rem;
  line-height: 1.4;
}

.task-warn {
  margin-top: 10px;
  padding: 8px 10px;
  background: var(--error-bg);
  color: var(--error-text);
  border-radius: 8px;
  font-size: .78rem;
}

/* ---------- 历史记录 ---------- */

.history {
  max-width: 1280px;
  margin: 0 auto 40px;
  padding: 0 24px;
}

.history h2 {
  margin: 0 0 16px;
  font-size: 1.1rem;
  color: var(--text);
}

#gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 12px;
}

#galleryEmpty { color: var(--text-secondary); font-size: .9rem; }

.gallery-item {
  position: relative;
  aspect-ratio: 1 / 1;
  margin: 0;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: rgba(255, 255, 255, .02);
  cursor: pointer;
}

.gallery-item img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.gallery-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  padding: 8px;
  background: linear-gradient(to top, rgba(0, 0, 0, .78), transparent 55%);
  color: var(--text);
  font-size: .72rem;
  line-height: 1.35;
  text-align: left;
  opacity: 0;
  transition: opacity .15s;
}

.gallery-item:hover .gallery-overlay,
.gallery-item:focus-visible .gallery-overlay {
  opacity: 1;
}

.gallery-item:focus-visible {
  outline: 2px solid #7c5cff;
  outline-offset: 2px;
}

/* ---------- 弹窗（keyDialog / viewDialog 通用样式；viewDialog 专属尺寸见下） ---------- */

/* padding 落在 .dialog-body（而非 dialog 元素本身），使弹窗内任何一次点击的 target
   都落在某个子元素上，绝不等于 dialog 自身——这是「点击背景关闭」判定
   `e.target === dialog` 成立的结构前提（否则点击 dialog 自身的 padding 区域也会
   被误判成背景点击）。 */
dialog {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0;
  width: 90vw;
  max-width: 420px;
  box-shadow: 0 24px 64px -12px rgba(0, 0, 0, .7);
}

.dialog-body {
  position: relative;
  padding: 24px;
}

dialog::backdrop { background: rgba(0, 0, 0, .6); }

dialog h2 { margin: 0 0 16px; font-size: 1.1rem; }

/* ---------- × 关闭按钮：viewDialog / lightbox 共用形状与交互，背景色按各自背景适配对比度 ---------- */

.close-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  color: var(--text);
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color .15s, transform .15s;
}

.close-btn:active { transform: scale(.94); }

/* viewDialog 的关闭按钮悬浮在大图上方——深色半透明底，与 .tile-download 同一处理，
   保证在任意亮度的生成图片上都能看清（浅色芯片在浅色图片上会糊成一片）。 */
#viewDialog .close-btn {
  position: absolute;
  top: 12px;
  right: 12px;
  background: rgba(0, 0, 0, .55);
}

#viewDialog .close-btn:hover { background: rgba(0, 0, 0, .75); }

/* ---------- 左右切换按钮：viewDialog / lightbox 通用，垂直居中于弹窗左右边缘 ----------
   与 .close-btn 同一形状语言（圆形、40→44px 加大到满足 ≥44px 触达面积），按各自
   背景选深/浅两种半透明底，disabled 态只调透明度不隐藏（两端到头仍看得见按钮本身，
   hidden 态才真正消失——hidden 专用于"上下文只有 1 张图"这种整体不需要导航的场景）。 */
.nav-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  border-radius: 50%;
  color: var(--text);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color .15s, opacity .15s;
}

.nav-btn:active:not(:disabled) { transform: translateY(-50%) scale(.92); }
.nav-btn:disabled { opacity: .3; cursor: not-allowed; }

/* 同 .task-dismiss：显式 display:flex 须显式覆盖 [hidden]。 */
.nav-btn[hidden] { display: none; }

.nav-btn--prev { left: 12px; }
.nav-btn--next { right: 12px; }

#viewDialog .nav-btn { background: rgba(0, 0, 0, .55); }
#viewDialog .nav-btn:hover:not(:disabled) { background: rgba(0, 0, 0, .75); }

#lightbox .nav-btn { background: rgba(255, 255, 255, .1); }
#lightbox .nav-btn:hover:not(:disabled) { background: rgba(255, 255, 255, .18); }
#lightbox .nav-btn--prev { left: 16px; }
#lightbox .nav-btn--next { right: 16px; }

#keyDialog label {
  display: block;
  margin-bottom: 6px;
  font-size: .85rem;
  color: var(--text-secondary);
}

#keyInput {
  width: 100%;
  padding: 10px 12px;
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-size: .9rem;
}

.dialog-hint {
  margin: 10px 0 20px;
  color: var(--text-secondary);
  font-size: .8rem;
}

.dialog-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

.dialog-actions-right { display: flex; gap: 8px; }

.btn-plain, .btn-primary {
  padding: 8px 16px;
  border-radius: 8px;
  border: 1px solid var(--border);
  cursor: pointer;
  font-size: .85rem;
  transition: background-color .15s, opacity .15s, transform .15s;
}

.btn-plain:active, .btn-primary:active { transform: scale(.96); }

.btn-plain {
  background: transparent;
  color: var(--text);
}

.btn-plain:hover { background: rgba(255, 255, 255, .06); }

.btn-danger { color: var(--error-text); }

.btn-primary {
  border: none;
  background: var(--accent-grad);
  color: var(--text);
  font-weight: 600;
}

.btn-primary:hover { filter: brightness(1.08); }

/* ---------- viewDialog：大图 + 完整提示词（可滚动）+ 参数行 + 下载/复用/删除 ---------- */

#viewDialog {
  width: 92vw;
  max-width: 640px;
}

#viewImage {
  display: block;
  width: 100%;
  max-height: 55vh;
  margin-bottom: 16px;
  border-radius: 10px;
  background: rgba(0, 0, 0, .3);
  object-fit: contain;
  cursor: zoom-in;
}

#viewPrompt {
  max-height: 140px;
  margin-bottom: 12px;
  padding: 10px 12px;
  overflow-y: auto;
  background: rgba(255, 255, 255, .04);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: .88rem;
  line-height: 1.5;
  white-space: pre-wrap;
}

#viewMeta {
  margin-bottom: 18px;
  color: var(--text-secondary);
  font-size: .82rem;
}

#viewDownloadBtn {
  display: inline-block;
  text-decoration: none;
}

/* ---------- 全屏查看（Lightbox）：结果图 / 查看弹窗大图点击后网页内全屏放大 ----------
   用 <dialog> 而非普通 fixed div：showModal() 让它落入浏览器"顶层"，保证从已打开的
   viewDialog 内点大图时也一定盖在 viewDialog 之上（普通 div 无论 z-index 多高都盖不过
   顶层的 <dialog>）；同时顺带获得 ESC 关闭与"关闭后自动归还焦点"这两条原生行为。 */
#lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  margin: 0;
  padding: 0;
  border: none;
  background: rgba(0, 0, 0, .92);
  cursor: zoom-out;
}

/* 用 [open] 限定 display:flex，避免作者规则的优先级压过 UA 表的
   `dialog:not([open]){display:none}`，导致弹窗关闭后仍被强制显示。 */
#lightbox[open] {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 显式 width/height（而非 max-width/max-height）：生成图的原始像素可能远小于 96vw/96vh
   （例如 1K 档位），只设上限不会主动放大，"尽可能大"就落空了。这里固定盒子尺寸为
   96vw×96vh，交给 object-fit:contain 去缩放实际图片内容（按宽高比放大或缩小），
   多余空间露出 lightbox 自身的近黑底色，是看图应用常见的留白效果。 */
#lightbox img {
  width: 96vw;
  height: 96vh;
  object-fit: contain;
  cursor: zoom-out;
}

/* lightbox 背景本身已接近全黑，关闭按钮改用浅色半透明底，与 viewDialog 内浮在图片上的
   深色芯片相反——同一形状语言（.close-btn），按各自背景选对比度更高的一侧。 */
#lightbox .close-btn {
  position: absolute;
  top: 16px;
  right: 16px;
  background: rgba(255, 255, 255, .1);
}

#lightbox .close-btn:hover { background: rgba(255, 255, 255, .18); }
