/* Fonleader AI 创作工作室 · 网页版样式
 * 无构建链：手写 CSS，全部走 CSS 变量，不依赖任何前端框架。
 * 视觉口径参照 Open-Generative-AI（MIT）的深色 + 青色体系，按我方产品调过。
 */

:root {
  --bg-app: #050505;
  --bg-panel: #0a0a0a;
  --bg-card: #141414;
  --bg-elevated: #18181c;
  --bg-input: #16161a;

  --text: #ffffff;
  --text-secondary: #a1a1aa;
  --text-muted: #52525b;

  --border: #27272a;
  --border-soft: rgba(255, 255, 255, 0.08);

  --accent: #22d3ee;
  --accent-hover: #06b6d4;
  --accent-soft: rgba(34, 211, 238, 0.1);
  --accent-border: rgba(34, 211, 238, 0.25);

  --danger: #ef4444;
  --ok: #22c55e;
  --warn: #f59e0b;

  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 16px;
  --radius-xl: 24px;
  --radius-full: 9999px;

  --font: "Inter", -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;

  --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.4);
  --shadow-pop: 0 20px 60px rgba(0, 0, 0, 0.7);
  --shadow-glow: 0 0 20px rgba(34, 211, 238, 0.25);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg-app);
  color: var(--text);
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

button { font-family: inherit; font-size: inherit; cursor: pointer; }
input, textarea, select { font-family: inherit; font-size: inherit; }

#app { height: 100%; }

.app-loading {
  display: flex;
  align-items: center;
  justify-content: center;
}

.boot {
  color: var(--text-muted);
  font-size: 13px;
}

/* ---------- 通用控件 ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 38px;
  padding: 0 18px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border-soft);
  background: var(--bg-input);
  color: var(--text);
  font-weight: 600;
  transition: background 0.15s, border-color 0.15s, opacity 0.15s;
  white-space: nowrap;
}

.btn:hover { background: #202026; }

.btn-primary {
  background: var(--accent);
  border-color: rgba(34, 211, 238, 0.3);
  color: #04191d;
  font-weight: 700;
}

.btn-primary:hover { background: var(--accent-hover); }

.btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--text-secondary);
  font-weight: 500;
}

.btn-ghost:hover { background: rgba(255, 255, 255, 0.06); color: var(--text); }

.btn:disabled,
.btn[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.btn:disabled:hover { background: var(--bg-input); }
.btn-primary:disabled:hover { background: var(--accent); }

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.field > label {
  font-size: 12px;
  color: var(--text-secondary);
  font-weight: 500;
}

.input {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg-input);
  color: var(--text);
  outline: none;
  transition: border-color 0.15s;
}

.input:focus { border-color: var(--accent-border); }
.input::placeholder { color: var(--text-muted); }

textarea.input {
  height: auto;
  min-height: 88px;
  padding: 10px 12px;
  resize: vertical;
  line-height: 1.6;
}

select.input {
  appearance: none;
  padding-right: 32px;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23a1a1aa' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
}

/* ---------- 登录页 ---------- */

.login-wrap {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background:
    radial-gradient(900px 500px at 20% 0%, rgba(34, 211, 238, 0.07), transparent 70%),
    radial-gradient(700px 400px at 90% 100%, rgba(168, 85, 247, 0.05), transparent 70%),
    var(--bg-app);
}

.login-card {
  width: 100%;
  max-width: 380px;
  padding: 32px;
  border-radius: var(--radius-xl);
  border: 1px solid var(--border-soft);
  background: linear-gradient(180deg, #18181c 0%, #0f0f12 100%);
  box-shadow: var(--shadow-pop);
}

.login-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 24px;
}

.login-mark {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--accent) 0%, #a855f7 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  color: #04191d;
  font-size: 16px;
}

.login-title { font-size: 16px; font-weight: 700; }
.login-sub { font-size: 12px; color: var(--text-muted); }

.login-card form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.login-error {
  display: none;
  padding: 10px 12px;
  border-radius: var(--radius);
  border: 1px solid rgba(239, 68, 68, 0.3);
  background: rgba(239, 68, 68, 0.1);
  color: #fca5a5;
  font-size: 13px;
  line-height: 1.5;
}

.login-error.show { display: block; }

.login-note {
  margin-top: 18px;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.6;
}

/* ---------- 注册页 ---------- */

/* 注册表单比登录表单多一行（验证码 + 发送按钮 + 合同勾选），
 * 卡片要放宽一点，否则验证码和按钮挤在一行会换行折成两行。 */
.login-card:has(.code-row) { max-width: 420px; }

.code-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}

.code-row .input { flex: 1; min-width: 0; }

.btn-code {
  flex: none;
  height: auto;
  padding: 0 14px;
  border-radius: var(--radius);
  font-size: 13px;
  font-weight: 600;
  background: var(--bg-input);
  border: 1px solid var(--border);
  color: var(--text-secondary);
}

.btn-code:hover:not(:disabled) { background: #202026; color: var(--text); }
.btn-code:disabled { opacity: 0.55; cursor: not-allowed; }

.code-hint {
  display: none;
  font-size: 11px;
  line-height: 1.55;
  color: var(--text-muted);
}

.code-hint.is-ok { display: block; color: #86efac; }

.agree-label {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  font-size: 12px;
  line-height: 1.65;
  color: var(--text-secondary);
  cursor: pointer;
}

.agree-box {
  flex: none;
  width: 15px;
  height: 15px;
  margin: 2px 0 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.agree-label a { color: var(--accent); text-decoration: none; }
.agree-label a:hover { text-decoration: underline; }

.login-note a { color: var(--accent); text-decoration: none; }
.login-note a:hover { text-decoration: underline; }

/* ---------- 合同正文页 ---------- */

/* 合同是纯文档页：窄栏、大行距，跟工作区的界面语言分开。
 * 正文宽度卡在 760px —— 超过这个宽度中文长段落读起来会掉行。 */
body.terms-body {
  height: auto;
  min-height: 100%;
  background: var(--bg-app);
}

.terms-doc {
  max-width: 760px;
  margin: 0 auto;
  padding: 28px 20px 72px;
}

.terms-nav {
  display: flex;
  gap: 16px;
  align-items: center;
  padding-bottom: 18px;
  margin-bottom: 28px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}

.terms-nav a { color: var(--text-secondary); text-decoration: none; }
.terms-nav a:hover { color: var(--accent); }

.terms-content {
  font-size: 14px;
  line-height: 1.85;
  color: var(--text-secondary);
}

.terms-content h1 {
  font-size: 20px;
  line-height: 1.5;
  color: var(--text);
  margin: 0 0 6px;
}

.terms-content h2 {
  font-size: 16px;
  line-height: 1.6;
  color: var(--text);
  margin: 0 0 22px;
  font-weight: 600;
}

.terms-content h3 {
  font-size: 15px;
  line-height: 1.6;
  color: var(--text);
  margin: 34px 0 12px;
  padding-top: 18px;
  border-top: 1px solid var(--border-soft);
}

.terms-content p { margin: 0 0 14px; }

.terms-content strong { color: var(--text); font-weight: 600; }

.terms-content blockquote {
  margin: 0 0 18px;
  padding: 12px 16px;
  border-left: 2px solid var(--accent-border);
  background: rgba(255, 255, 255, 0.025);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: 13px;
  line-height: 1.8;
}

.terms-content ol,
.terms-content ul { margin: 0 0 14px; padding-left: 22px; }

.terms-content li { margin: 0 0 8px; }
.terms-content li > ul { margin: 8px 0 0; }

/* 价目表（2026-10-22 补）。《收费与退款规则》里有套餐价目与加油包单价两张表。
 * 五列在手机上必然挤成一团，所以外面套一层横向滚动容器：
 * 表格保留 min-width 不被压变形，窄屏时整块左右滑，而不是把字挤成竖条。 */
.terms-table-wrap {
  margin: 0 0 18px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.terms-table {
  width: 100%;
  min-width: 480px;
  border-collapse: collapse;
  font-size: 13px;
  line-height: 1.7;
}

.terms-table th,
.terms-table td {
  padding: 9px 12px;
  border: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
}

.terms-table th {
  background: rgba(255, 255, 255, 0.035);
  color: var(--text);
  font-weight: 600;
  white-space: nowrap;
}

.terms-table td { color: var(--text-secondary); }

.terms-foot {
  margin-top: 40px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  font-size: 12px;
  color: var(--text-muted);
  word-break: break-all;
}

@media (max-width: 860px) {
  .login-card:has(.code-row) { max-width: 100%; }
  .terms-doc { padding: 20px 16px 56px; }
}

/* ---------- 主框架 ---------- */

.shell {
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.topbar {
  flex: none;
  height: 56px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 16px;
  border-bottom: 1px solid var(--border);
  background: var(--bg-panel);
}

.topbar-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-right: 12px;
  flex: none;
}

.topbar-mark {
  width: 26px;
  height: 26px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--accent) 0%, #a855f7 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  color: #04191d;
  font-size: 13px;
}

.topbar-name { font-size: 13px; font-weight: 700; letter-spacing: 0.02em; }

.nav {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}

.nav::-webkit-scrollbar { display: none; }

.nav-item {
  flex: none;
  height: 32px;
  padding: 0 13px;
  border-radius: var(--radius-full);
  border: none;
  background: transparent;
  color: var(--text-secondary);
  font-weight: 500;
  transition: background 0.15s, color 0.15s;
}

.nav-item:hover { background: rgba(255, 255, 255, 0.05); color: var(--text); }

.nav-item.active {
  background: var(--accent-soft);
  color: var(--accent);
  font-weight: 600;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}

.quota {
  display: flex;
  align-items: baseline;
  gap: 5px;
  height: 32px;
  padding: 0 13px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  background: var(--bg-input);
  white-space: nowrap;
}

.quota-label { font-size: 11px; color: var(--text-muted); }
.quota-value { font-size: 13px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }

.quota.is-low .quota-value { color: var(--warn); }
.quota.is-empty .quota-value { color: var(--danger); }

/* 文案次数徽标（2026-10-28）：与视觉点并列，用中性色区分 —— 视觉点是主消耗，文案是另一个账本，
 * 两者都用 accent 色会让客户以为是一个额度的两种写法。 */
.quota-text .quota-value { color: var(--text); }

.quota-text.is-low .quota-value { color: var(--warn); }
.quota-text.is-empty .quota-value { color: var(--danger); }

.account {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 4px 0 12px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  background: var(--bg-input);
  max-width: 220px;
}

.account-email {
  font-size: 12px;
  color: var(--text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-out {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-full);
  border: none;
  background: transparent;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, color 0.15s;
}

.account-out:hover { background: rgba(255, 255, 255, 0.08); color: var(--text); }

/* ---------- 工作区 ---------- */

.workspace {
  flex: 1;
  min-height: 0;
  display: flex;
  overflow: hidden;
}

.panel {
  flex: none;
  width: 320px;
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--border);
  background: var(--bg-panel);
  overflow-y: auto;
}

.panel-inner {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 18px 16px 24px;
}

.panel-head {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.panel-title { font-size: 14px; font-weight: 700; }
.panel-desc { font-size: 12px; color: var(--text-muted); line-height: 1.55; }

.panel-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}

.panel-actions .btn { width: 100%; height: 42px; }

.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.upload {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.upload-box {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 96px;
  padding: 12px;
  border-radius: var(--radius);
  border: 1px dashed var(--border);
  background: var(--bg-input);
  color: var(--text-muted);
  font-size: 12px;
  text-align: center;
  transition: border-color 0.15s, background 0.15s;
  cursor: pointer;
}

.upload-box:hover { border-color: var(--accent-border); background: var(--accent-soft); }

.upload-box.has-file { border-style: solid; border-color: var(--accent-border); padding: 8px; }

.upload-preview {
  width: 100%;
  max-height: 140px;
  object-fit: contain;
  border-radius: var(--radius-sm);
  display: block;
}

.upload-clear {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 22px;
  height: 22px;
  border-radius: var(--radius-full);
  border: none;
  background: rgba(0, 0, 0, 0.65);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  line-height: 1;
}

.upload-clear:hover { background: var(--danger); }

.hint {
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.55;
}

.hint.is-error { color: #fca5a5; }

/* ---------- 画布 ---------- */

.canvas {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background:
    radial-gradient(800px 400px at 50% 0%, rgba(34, 211, 238, 0.04), transparent 70%),
    var(--bg-app);
}

.canvas-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 20px;
}

.canvas-empty {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  text-align: center;
  padding: 24px;
}

.empty-cards {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 6px;
}

.empty-card {
  width: 62px;
  height: 78px;
  border-radius: 12px;
  border: 1px solid var(--border-soft);
  background: linear-gradient(160deg, #1c1c22 0%, #101014 100%);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  transition: transform 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);
  margin: 0 -7px;
}

.empty-card:nth-child(1) { transform: rotate(-12deg); }
.empty-card:nth-child(2) { transform: rotate(-4deg) translateY(-6px); border-radius: 999px; width: 62px; height: 62px; }
.empty-card:nth-child(3) { transform: rotate(6deg) translateY(-6px); }
.empty-card:nth-child(4) { transform: rotate(12deg); }

.canvas-empty:hover .empty-card:nth-child(1) { transform: rotate(-6deg); }
.canvas-empty:hover .empty-card:nth-child(2) { transform: rotate(0deg) translateY(-10px); }
.canvas-empty:hover .empty-card:nth-child(3) { transform: rotate(0deg) translateY(-10px); }
.canvas-empty:hover .empty-card:nth-child(4) { transform: rotate(6deg); }

.empty-title {
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1.3;
}

.empty-title em {
  display: block;
  font-style: normal;
  color: var(--accent);
  font-weight: 900;
}

.empty-sub {
  font-size: 13px;
  color: var(--text-muted);
  max-width: 420px;
  line-height: 1.6;
}

/* 结果网格 */

.results {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
}

.result {
  position: relative;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg-card);
  overflow: hidden;
  transition: border-color 0.15s;
}

.result:hover { border-color: var(--accent-border); }

.result-media {
  display: block;
  width: 100%;
  background: #000;
}

.result-media.is-image { aspect-ratio: 1 / 1; object-fit: cover; }
.result-media.is-video { aspect-ratio: 16 / 9; }

.result-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-top: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-muted);
}

.result-foot .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.result-btn {
  flex: none;
  height: 24px;
  padding: 0 9px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 500;
}

.result-btn:hover { border-color: var(--accent-border); color: var(--accent); }

.result-status {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: rgba(5, 5, 5, 0.86);
  backdrop-filter: blur(4px);
  font-size: 12px;
  color: var(--text-secondary);
  padding: 16px;
  text-align: center;
}

.result.is-done .result-status { display: none; }

.spinner {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.15);
  border-top-color: var(--accent);
  animation: spin 0.8s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

.result.is-failed .result-status { color: #fca5a5; }

/* 视频占位 */

.video-placeholder {
  aspect-ratio: 16 / 9;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #0d0d10;
  color: var(--text-muted);
  font-size: 12px;
}

/* ---------- 提示条 ---------- */

.toast-host {
  position: fixed;
  right: 16px;
  bottom: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 90;
  pointer-events: none;
}

.toast {
  max-width: 380px;
  padding: 10px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--border-soft);
  background: #1c1c22;
  box-shadow: var(--shadow-pop);
  font-size: 13px;
  line-height: 1.5;
  pointer-events: auto;
  animation: toast-in 0.2s ease-out;
}

.toast.is-error { border-color: rgba(239, 68, 68, 0.35); color: #fca5a5; }
.toast.is-ok { border-color: rgba(34, 197, 94, 0.35); color: #86efac; }

@keyframes toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---------- 窄屏 ---------- */

@media (max-width: 860px) {
  .workspace { flex-direction: column; }
  .panel {
    width: 100%;
    max-height: 52%;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
  .topbar-name { display: none; }
  .account-email { max-width: 90px; }
  /* 顶栏现在有两枚额度徽标（视觉 + 文案），窄屏收紧内边距；导航自己是 flex:1 + 横向滚动，
     会先被压缩，所以徽标不会被挤出屏幕。 */
  .quota { padding: 0 9px; gap: 4px; }
  .results { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  .canvas-body { padding: 12px; }
}

/* ------------------------------------------------------------------ *
 * 历史记录（2026-10-22）
 *
 * 复用 .results / .result / .result-media / .result-foot 那一套卡片，
 * 只额外加「筛选行」和「空态/加载态」两个小零件 —— 不另起一套卡片样式，
 * 否则同一个作品在「刚生成」和「历史里」会长成两个样子。
 * ------------------------------------------------------------------ */

.history-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.history-tabs {
  display: inline-flex;
  gap: 4px;
  padding: 3px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  background: var(--bg-panel);
}

.history-tab {
  height: 28px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 500;
}

.history-tab:hover { color: var(--text); }

.history-tab.is-active {
  background: var(--accent);
  color: #041013;
  font-weight: 600;
}

.history-bar .grow { flex: 1; }

.history-refresh {
  height: 28px;
  padding: 0 12px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-secondary);
  font-size: 12px;
}

.history-refresh:hover { border-color: var(--accent-border); color: var(--accent); }
.history-refresh:disabled { opacity: 0.5; }

.history-note {
  margin: 0 0 14px;
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.6;
}

.history-state {
  padding: 40px 20px;
  text-align: center;
  font-size: 13px;
  color: var(--text-muted);
}

.history-state.is-error { color: #fca5a5; }

/* 历史卡片里的状态角标：已成功的不标，只标「还在跑 / 失败」这两种需要客户注意的。 */
.result-badge {
  position: absolute;
  top: 8px;
  left: 8px;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.02em;
  background: rgba(5, 5, 5, 0.78);
  border: 1px solid var(--border);
  color: var(--text-secondary);
}

.result-badge.is-failed { color: #fca5a5; border-color: rgba(248, 113, 113, 0.4); }
.result-badge.is-running { color: var(--accent); border-color: var(--accent-border); }

.result-foot .result-meta {
  flex: none;
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
}

/* ------------------------------------------------------------------ *
 * 订阅与续费（2026-10-22）
 *
 * 复用现有令牌，不新增颜色。三档卡片与历史记录卡片同构：
 * 深色底 + 细边框，当前套餐用青色描边区分，不可点的按钮降低不透明度。
 * ------------------------------------------------------------------ */

.billing-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  margin: 14px 0 10px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
}

.billing-summary-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.billing-label {
  font-size: 11px;
  color: var(--text-muted);
}

.billing-value {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.billing-cycles {
  display: inline-flex;
  gap: 3px;
  margin-bottom: 12px;
  padding: 3px;
  border-radius: var(--radius-full);
  background: var(--bg-panel);
}

.billing-cycle {
  height: 28px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--radius-full);
  background: transparent;
  color: var(--text-secondary);
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
}

.billing-cycle:hover { color: var(--text); }

.billing-cycle.is-active {
  background: var(--accent);
  color: #041013;
  font-weight: 600;
}

.billing-plans {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px;
  margin-top: 12px;
}

.billing-plan {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
}

/* 当前套餐：青色描边 + 极淡青光底，一眼能认出「这张是我在用的」。 */
.billing-plan.is-current {
  border-color: var(--accent-border);
  background: var(--accent-soft);
}

.billing-plan-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.billing-plan-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
}

.billing-plan-badge {
  padding: 2px 8px;
  border-radius: var(--radius-full);
  border: 1px solid var(--accent-border);
  color: var(--accent);
  font-size: 10px;
  font-weight: 600;
}

.billing-plan-price {
  display: flex;
  align-items: baseline;
  gap: 4px;
}

.billing-plan-amount {
  font-size: 26px;
  font-weight: 700;
  color: var(--text);
  line-height: 1.1;
}

.billing-plan-unit {
  font-size: 11px;
  color: var(--text-muted);
}

.billing-plan-feats {
  flex: 1;
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.billing-plan-feats li {
  font-size: 12px;
  color: var(--text-secondary);
  line-height: 1.5;
}

/* 列表项前面加一个小圆点，避免纯文字挤成一坨。 */
.billing-plan-feats li::before {
  content: "·";
  margin-right: 6px;
  color: var(--accent);
  font-weight: 700;
}

.billing-plan-btn {
  height: 34px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg-elevated);
  color: var(--text);
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
}

.billing-plan-btn:hover:not(:disabled) {
  border-color: var(--accent-border);
  color: var(--accent);
}

/* 当前套餐的按钮做成主按钮：客户最常点的就是「续费」。 */
.billing-plan-btn.is-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #041013;
  font-weight: 600;
}

.billing-plan-btn.is-primary:hover:not(:disabled) {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  color: #041013;
}

/* 不支持中途升级：不能点的按钮必须一眼看出不能点，而不是点了没反应。 */
.billing-plan-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.billing-pay {
  margin-top: 16px;
}

/* ---------- 付款记录（2026-10-22） ----------
 * 客户自己的购买流水。放在购买区下面，默认折叠。
 * 口径：金额右对齐、状态用颜色区分（已支付绿、已退款灰），
 * 让客户一眼扫出「哪笔付成了」。
 */

.billing-records {
  margin-top: 16px;
}

.billing-records-bar {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.billing-records-bar .grow { flex: 1; }

.billing-records-head {
  min-width: 0;
}

.billing-records-list {
  margin-top: 12px;
}

/* 展开态由脚本控制 hidden；这里兜一道，防止别处的 display 规则把 [hidden] 覆盖掉，
 * 变成「点一下没反应、列表一直开着」。 */
.billing-records-list[hidden] { display: none; }

.pay-records {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pay-record {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
}

.pay-record-main {
  min-width: 0;
}

.pay-record-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pay-record-time {
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-muted);
}

.pay-record-side {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}

.pay-record-amount {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.pay-record-status {
  font-size: 11px;
  padding: 2px 8px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  white-space: nowrap;
}

.pay-record-status.is-paid {
  color: var(--ok);
  border-color: rgba(34, 197, 94, 0.35);
  background: rgba(34, 197, 94, 0.08);
}

.pay-record-status.is-refunded {
  color: var(--text-muted);
  border-color: var(--border);
  background: transparent;
}

/* 未付成的三态（2026-10-22 加）：都要一眼能看出「这笔没成」，
   但彼此要能区分 —— 「待支付」还有机会付、「支付失败」要重来、「已关闭」是超时作废。 */
.pay-record-status.is-pending {
  color: var(--warn, #b45309);
  border-color: rgba(180, 83, 9, 0.35);
  background: rgba(180, 83, 9, 0.08);
}

.pay-record-status.is-failed {
  color: var(--danger, #b91c1c);
  border-color: rgba(185, 28, 28, 0.35);
  background: rgba(185, 28, 28, 0.08);
}

.pay-record-status.is-closed {
  color: var(--text-muted);
  border-color: var(--border);
  background: transparent;
}

@media (max-width: 640px) {
  .pay-record {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .pay-record-side {
    width: 100%;
    justify-content: space-between;
  }
}

.billing-pay-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-card);
}

.billing-pay-head {
  text-align: center;
}

.billing-pay-title {
  font-size: 14px;
  font-weight: 700;
  color: var(--text);
}

.billing-pay-sub {
  margin-top: 4px;
  font-size: 11px;
  color: var(--text-muted);
  word-break: break-all;
}

/* 二维码白底：SVG 本身画了白底，这里再包一层是为了在深色页面上留出安静区，
   避免二维码贴着深色边框导致手机扫不出来。 */
.billing-qr {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 216px;
  height: 216px;
  padding: 8px;
  border-radius: var(--radius);
  background: #fff;
}

.billing-qr svg { display: block; }

.billing-status {
  font-size: 12px;
  color: var(--text-secondary);
}

.billing-status.is-error { color: #fca5a5; }

.billing-cancel {
  height: 30px;
  padding: 0 16px;
  border-radius: var(--radius-full);
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-secondary);
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
}

.billing-cancel:hover {
  border-color: var(--accent-border);
  color: var(--accent);
}

/* 首页带 ?plan= 进来时描出来的那一档。用虚线边框 + 青色，
   和「当前套餐」（实线 + 淡青底）区分开，避免客户把「想买的」当成「在用的」。 */
.billing-plan.is-wanted {
  border-color: var(--accent);
  border-style: dashed;
}

/* ------------------------------------------------------------------ *
 * 加油包（2026-10-22）
 *
 * 首页早就写着「额度不够可以加购加油包」，但站内一直没有购买入口，
 * 客户额度用完只会看到「请联系管理员」。这一块补上。
 * 视觉上比套餐区轻一档：不抢套餐的注意力，但又明显是能买的东西。
 * ------------------------------------------------------------------ */

.billing-topups {
  margin-top: 20px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

.billing-topup-head {
  margin-bottom: 10px;
}

/* ---------- 账号页（2026-10-22） ---------- */

.account-section-head {
  margin: 18px 0 10px;
}

/* 改密码表单：宽度收窄，跟整屏的表单区区分开，别让三个输入框横跨整个画布。 */
.account-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 360px;
}

.account-form .hint {
  min-height: 16px;
}

/* 账号信息（登录邮箱 / 账号名称）：两列自适应，窄屏自动折行。 */
.account-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  margin: 14px 0 10px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
}

.account-summary-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.account-summary-label {
  font-size: 11px;
  color: var(--text-muted);
}

.account-summary-value {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.account-section-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.account-section-sub {
  margin-top: 4px;
  font-size: 11px;
  line-height: 1.6;
  color: var(--text-muted);
}

.billing-topup-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.billing-topup-sub {
  margin-top: 4px;
  font-size: 11px;
  line-height: 1.6;
  color: var(--text-muted);
}

.billing-topup-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}

.billing-topup {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-card);
}

.billing-topup-points {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
}

.billing-topup-price {
  font-size: 12px;
  color: var(--text-secondary);
}

.billing-topup .billing-plan-btn {
  width: 100%;
  margin-top: 4px;
}

/* 联系客服：额度不足、支付未开通这些「客户必须找人」的场景都用这一行。
   以前站内只有一句「请联系管理员」，没有任何入口。 */
.support-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-panel);
  font-size: 12px;
  color: var(--text-secondary);
}

.support-line .support-label {
  color: var(--text-muted);
  font-size: 11px;
}

.support-line a {
  color: var(--accent);
  text-decoration: none;
}

.support-line a:hover { text-decoration: underline; }

.support-wechat {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-weight: 600;
  color: var(--text);
}

/* 微信二维码：点开才显示，不占常驻版面。白底是必须的，深色底扫不出来。 */
.support-qr {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 168px;
  height: 168px;
  margin-top: 8px;
  padding: 8px;
  border-radius: var(--radius);
  background: #fff;
}

.support-qr svg { display: block; }

/* ------------------------------------------------------------------ *
 * 手机端专项适配（2026-10-22）
 *
 * 这一段只修「明显缺陷」，不重做界面。原有的 860px 断点保留不动（平板与横屏手机
 * 还归它管），下面按 860 / 640 / 420 三档逐条补：
 *   ① iOS 输入框字号小于 16px 时，一聚焦就强制放大整页 —— 手机端必须抬到 16px；
 *   ② viewport-fit=cover 已开，但没消费安全区 —— 刘海 / 底部横条会压住顶栏与提示条；
 *   ③ 触摸目标多处低于 44px —— 手指点不准；
 *   ④ 手机地址栏会伸缩，100% 高度会导致底部被切 —— 用 dvh；
 *   ⑤ 640px 以下「上下两块各自滚动」很难用 —— 改成整页一条滚动。
 * ------------------------------------------------------------------ */

/* ① + ③：手机端所有输入控件字号 ≥16px，按钮触摸目标 ≥44px。
   只在窄屏生效，桌面端仍是 14px / 38px，版面不动。 */
@media (max-width: 860px) {
  .input,
  input,
  textarea,
  select {
    font-size: 16px;
  }

  /* 按钮本体抬到 44px；行内的小圆角按钮同样给足点按面积。
     用 min-height 而不是 height，文字换行时不会被截断。 */
  .btn,
  .btn-code {
    min-height: 44px;
  }

  .nav-item {
    min-height: 44px;
    padding: 0 16px;
  }

  /* 退出登录那个图标按钮原来只有 26×26，手指几乎点不到。 */
  .account-out {
    width: 44px;
    height: 44px;
  }

  /* 历史记录页里的两个小控件同理。 */
  .history-tab,
  .history-refresh {
    min-height: 44px;
  }
}

/* ②：消费安全区。顶栏左右留出刘海 / 圆角占位，提示条避开底部横条。
   max() 保证没有安全区时仍保留原本的内边距。 */
@supports (padding: max(0px)) {
  .topbar {
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
  }

  .toast-host {
    right: max(16px, env(safe-area-inset-right));
    bottom: max(16px, env(safe-area-inset-bottom));
  }

  .login-wrap {
    padding-top: max(24px, env(safe-area-inset-top));
    padding-bottom: max(24px, env(safe-area-inset-bottom));
    padding-left: max(24px, env(safe-area-inset-left));
    padding-right: max(24px, env(safe-area-inset-right));
  }

  .panel-inner {
    padding-bottom: max(24px, env(safe-area-inset-bottom));
  }
}

/* ④：手机浏览器地址栏收起 / 展开时，100% 高度会把底部内容顶出屏幕。
   dvh 跟着可视区变，老浏览器不支持 dvh 时自动退回上面那条 100%。 */
@supports (height: 100dvh) {
  html,
  body,
  #app,
  .shell {
    height: 100dvh;
  }
}

/* ⑤：640px 以下改成整页一条滚动。
   原来 .workspace 竖排后，上半（参数面板）最高 52%、下半（画布）各自独立滚动，
   手机上等于两个很矮的滚动区互相抢手势，很难用。这里把外壳与画布都放开，
   让整页跟着手指走 —— 这是手机上最自然的读法。 */
@media (max-width: 640px) {
  html,
  body,
  #app {
    height: auto;
    min-height: 100%;
  }

  .shell {
    height: auto;
    min-height: 100%;
    overflow: visible;
  }

  .workspace {
    flex: 1 1 auto;
    min-height: 0;
    overflow: visible;
  }

  .panel {
    max-height: none;
    overflow-y: visible;
  }

  .canvas {
    overflow: visible;
  }

  .canvas-body {
    overflow-y: visible;
    padding: 12px 12px calc(12px + env(safe-area-inset-bottom));
  }

  /* 画布空态原来靠 height:100% 撑满，整页滚动后 100% 就没有参照了，会给一个下限。 */
  .canvas-empty {
    height: auto;
    min-height: 56vh;
    padding: 32px 16px;
  }

  .login-wrap {
    height: auto;
    min-height: 100dvh;
    padding: 20px 16px;
  }

  .login-card {
    padding: 24px 20px;
  }

  .topbar {
    padding-left: max(12px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
  }
}

/* 420px 以下：再窄一点就把卡片压到单列，避免右侧永远留一条空白。 */
@media (max-width: 420px) {
  .results {
    grid-template-columns: 1fr;
  }

  .field-row {
    grid-template-columns: 1fr;
  }

  .topbar-brand {
    margin-right: 6px;
  }
}
