:root {
  --bg: #0b0b0d;
  --txt: #f2f2f3;
  --muted: #9b9ba2;
  --faint: #6a6a72;
  --panel: rgba(22, 22, 24, .72);
  --panel-solid: #161618;
  --panel-border: rgba(255, 255, 255, .07);
  --input: #161618;
  --input-border: rgba(255, 255, 255, .08);
  --btn: #202023;
  --btn-h: #2a2a2e;
  --btn-border: rgba(255, 255, 255, .09);
  --danger: #f5616b;
  --ok: #7ddea0;
  --wait: #d6aa78;
  --ease: cubic-bezier(.23, 1, .32, 1);
}

* { box-sizing: border-box; }
html { color-scheme: dark; background: var(--bg); -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--txt);
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", "PingFang SC", "Microsoft YaHei", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--txt); text-decoration: none; }
a:hover { color: #fff; }
button, input, select, textarea { font: inherit; color: inherit; }

/* 顶部暖光晕，对标对照页 */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(680px 320px at 50% -8%, rgba(146, 110, 74, .30), transparent 68%),
    radial-gradient(520px 300px at 50% -2%, rgba(90, 78, 66, .18), transparent 70%);
}

/* ——— 登录 / 注册 ———
   两栏：左栏品牌 + 一句话 + 一帧画面 + 底栏数据；右栏表单面板。
   深色底上的层次靠光不靠影：边缘用「内亮外暗」双线，物体往外洇一点有颜色的光，不用黑色投影。
   颗粒放在最上层做 dithering，把大面积渐变的台阶抖掉。窄屏（<920px）左栏整栏隐藏。 */
:root {
  --auth-sans: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Noto Sans", "Microsoft YaHei", Helvetica, Arial, sans-serif;
  --auth-serif: "Instrument Serif", Georgia, "Times New Roman", serif;
  --auth-mono: Consolas, "SF Mono", Menlo, monospace;
  --auth-panel: #141418;
  --auth-input: #0d0d10;
  --auth-warm-txt: #e8d3b4;
  --auth-edge: inset 0 1px 0 rgba(255, 255, 255, .07), inset 0 0 0 1px rgba(255, 255, 255, .04), 0 0 0 1px rgba(0, 0, 0, .6), 0 1px 0 rgba(0, 0, 0, .35);
  --auth-grain: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.6'/%3E%3C/svg%3E");
}
@font-face { font-family: Inter; font-style: normal; font-weight: 400 600; font-display: optional; src: url("/portal/fonts/inter-latin.woff2") format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: Inter; font-style: normal; font-weight: 400 600; font-display: optional; src: url("/portal/fonts/inter-latin-ext.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Instrument Serif"; font-style: normal; font-weight: 400; font-display: optional; src: url("/portal/fonts/instrument-serif-latin.woff2") format("woff2"); }
@font-face { font-family: "Instrument Serif"; font-style: italic; font-weight: 400; font-display: optional; src: url("/portal/fonts/instrument-serif-italic-latin.woff2") format("woff2"); }

body.is-auth {
  display: block;
  padding: 0;
  overflow-x: hidden;
  overflow-y: auto;
  background: #0b0b0d;
  font-family: var(--auth-sans);
  text-rendering: optimizeLegibility;
}
body.is-auth :focus-visible { outline: 2px solid rgba(214, 170, 120, .6); outline-offset: 2px; border-radius: 6px; }
/* 只有一束光：左上，收小、压淡；不加暗角、不加第二束（多了就分层成块） */
body.is-auth::before {
  position: fixed;
  background: radial-gradient(640px 460px at 6% -8%, rgba(146, 110, 74, .12), transparent 72%);
}
/* 颗粒在最上层：抖掉所有渐变的台阶。overlay 对纯白纯黑无效，文字不受影响 */
body.is-auth::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background: var(--auth-grain);
  background-size: 240px 240px;
  opacity: .06;
  mix-blend-mode: overlay;
}
.auth-wrap {
  position: relative;
  z-index: 1;
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  max-width: 1680px;
  margin: 0 auto;
}

/* —— 左栏 —— */
.auth-side {
  position: relative;
  padding: 40px 56px 34px;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
.auth-side::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 1px;
  background: linear-gradient(180deg, transparent 0%, rgba(255, 255, 255, .065) 20%, rgba(255, 255, 255, .065) 80%, transparent 100%);
}
.auth-side .brand { text-align: left; margin: 0; }
.auth-side .brand .mark { margin: 0; }
.auth-side .brand .mark .word { font-size: 19px; }
.auth-pitch { margin: 72px 0 0; max-width: 620px; }
.auth-pitch .eyebrow {
  font: 11px/1 var(--auth-mono);
  letter-spacing: .26em;
  color: var(--faint);
  text-transform: uppercase;
  margin: 0 0 20px 1px;
}
.auth-pitch h1 {
  margin: 0 0 16px;
  font: 500 clamp(30px, 2.75vw, 44px)/1.1 var(--auth-sans);
  letter-spacing: -.028em;
  color: var(--txt);
  white-space: nowrap;
  font-feature-settings: "ss01", "cv11";
}
.auth-pitch h1 em { font: italic 400 1.08em/1 var(--auth-serif); letter-spacing: 0; color: var(--txt); }
.auth-pitch h1 .dot { color: var(--wait); }
.auth-pitch p { margin: 0; color: var(--muted); font-size: 15px; line-height: 1.8; max-width: 460px; }

/* 一帧画面：全部是 CSS 渐变，不是图片 */
.auth-frame-wrap { position: relative; flex: 1 1 auto; min-height: 220px; max-height: 400px; margin: 36px 0 22px; max-width: 560px; }
.auth-frame-wrap::before {
  content: "";
  position: absolute;
  inset: -12% -9%;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(58% 52% at 30% 26%, rgba(150, 170, 212, .07), transparent 72%),
    radial-gradient(46% 46% at 78% 78%, rgba(200, 214, 255, .04), transparent 72%);
  filter: blur(26px);
}
.auth-frame { position: absolute; inset: 0; z-index: 1; border-radius: 14px; overflow: hidden; background: #0b0d12; box-shadow: var(--auth-edge); }
.auth-frame > * { position: absolute; }
.auth-frame .scene { inset: 0; background: linear-gradient(158deg, #0c0e15 0%, #12151e 46%, #0a0b0f 100%); }
.auth-frame .beam {
  left: 19%; top: -25%; width: 8%; height: 150%; transform: skewX(-17deg);
  background: linear-gradient(180deg, rgba(150, 170, 212, 0) 0%, rgba(150, 170, 212, .17) 28%, rgba(150, 170, 212, .11) 70%, rgba(150, 170, 212, 0) 100%);
  filter: blur(7px);
  animation: auth-drift 40s ease-in-out infinite;
}
.auth-frame .beam2 {
  left: 27%; top: -25%; width: 2%; height: 150%; transform: skewX(-17deg);
  background: linear-gradient(180deg, transparent, rgba(190, 205, 240, .22) 35%, rgba(190, 205, 240, .10) 75%, transparent);
  filter: blur(2px);
  animation: auth-drift 40s ease-in-out infinite;
}
.auth-frame .glow {
  right: 21%; bottom: 27%; width: 150px; height: 90px; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(200, 214, 255, .26), rgba(200, 214, 255, .06) 60%, transparent);
  filter: blur(10px);
  animation: auth-breathe 9s ease-in-out infinite;
}
.auth-frame .floor { left: 0; right: 0; bottom: 0; height: 38%; background: linear-gradient(180deg, transparent, rgba(255, 255, 255, .028)); }
.auth-frame .grain { inset: -40px; background: var(--auth-grain); background-size: 240px 240px; opacity: .12; mix-blend-mode: overlay; animation: auth-grain 1s steps(6) infinite; }
.auth-frame .vig { inset: 0; background: radial-gradient(120% 100% at 50% 50%, transparent 55%, rgba(0, 0, 0, .4) 100%); }
.auth-frame .bar { left: 0; right: 0; height: 5.5%; background: #050507; }
.auth-frame .bar.t { top: 0; }
.auth-frame .bar.b { bottom: 0; }
.auth-frame .meta { top: 9%; right: 16px; font: 500 11px/1 var(--auth-sans); letter-spacing: .12em; color: rgba(255, 255, 255, .55); font-variant-numeric: tabular-nums; }
.auth-frame .caption {
  left: 18px; bottom: 62px; max-width: 66%;
  padding-left: 11px; border-left: 2px solid var(--wait);
  font-size: 12.5px; line-height: 1.65; color: rgba(255, 255, 255, .74);
}
.auth-frame .caption small { display: block; margin-top: 4px; font-size: 11px; color: rgba(255, 255, 255, .4); }
.auth-frame .hud {
  left: 0; right: 0; bottom: 5.5%; height: 84px; padding: 0 16px 12px;
  display: flex; align-items: flex-end; gap: 12px;
  background: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, .28) 45%, rgba(0, 0, 0, .62) 100%);
  font-size: 12px; color: rgba(255, 255, 255, .7);
}
.auth-frame .hud .id { font-family: var(--auth-mono); color: rgba(255, 255, 255, .55); }
.auth-frame .hud .t { margin-left: auto; font-family: var(--auth-mono); font-variant-numeric: tabular-nums; color: var(--auth-warm-txt); }
.auth-frame .prog { left: 0; right: 0; bottom: 5.5%; height: 2px; background: rgba(255, 255, 255, .08); }
.auth-frame .prog i { display: block; height: 100%; width: 40%; background: var(--wait); box-shadow: 0 0 10px rgba(214, 170, 120, .55); animation: auth-grow 9s var(--ease) infinite; }
.auth-frame .pill { display: inline-flex; align-items: center; gap: 5px; padding: 1px 8px; border-radius: 999px; font-size: 11.5px; font-weight: 600; white-space: nowrap; }
.auth-frame .pill i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; display: inline-block; }
.auth-frame .p-gen { background: rgba(214, 170, 120, .18); color: var(--wait); }
.auth-frame .p-gen i { animation: auth-blink 1.4s ease-in-out infinite; }
/* 底栏：一行静态英文小字，和顶部眉题同一种排法（等宽、大写、拉开字距） */
.auth-foot {
  display: grid;
  gap: 7px;
  font: 11px/1.6 var(--auth-mono);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--faint);
  max-width: 560px;
}
.auth-foot .steps { color: var(--muted); }
.auth-foot .steps i { font-style: normal; color: var(--wait); margin: 0 8px; opacity: .8; }
.auth-foot .facts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.auth-foot .sep { width: 3px; height: 3px; border-radius: 50%; background: rgba(255, 255, 255, .18); }
@keyframes auth-drift { 0%, 100% { translate: 0 0; } 50% { translate: 3% 0; } }
@keyframes auth-breathe { 0%, 100% { opacity: .85; } 50% { opacity: 1; } }
@keyframes auth-grain {
  0% { transform: translate(0, 0); } 20% { transform: translate(-18px, 12px); } 40% { transform: translate(14px, -20px); }
  60% { transform: translate(-10px, -8px); } 80% { transform: translate(20px, 16px); } 100% { transform: translate(0, 0); }
}
@keyframes auth-grow { 0% { width: 8%; } 70% { width: 76%; } 100% { width: 93%; } }
@keyframes auth-blink { 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) {
  .auth-frame .grain, .auth-frame .prog i, .auth-frame .beam, .auth-frame .beam2, .auth-frame .glow, .auth-frame .p-gen i { animation: none !important; }
}

/* —— 右栏 —— */
.auth-main { display: flex; align-items: center; justify-content: center; padding: 44px 32px; position: relative; }
/* 语言切换沿用下面 body.is-auth .lang-switch 的固定右上角定位 */
.stack { position: relative; width: 100%; max-width: 404px; z-index: 1; }
/* 表单面板：平色，双线边，顶部一段暖色高光；没有黑影 */
.card {
  position: relative;
  z-index: 1;
  isolation: isolate;
  background: var(--auth-panel);
  border: none;
  border-radius: 16px;
  padding: 36px 34px 30px;
  box-shadow: var(--auth-edge);
}
.card::after {
  content: "";
  position: absolute;
  inset: -30px -26px;
  z-index: -1;
  pointer-events: none;
  border-radius: 30px;
  background: radial-gradient(70% 55% at 50% 0%, rgba(214, 170, 120, .06), transparent 70%);
  filter: blur(22px);
}
.card::before {
  content: "";
  position: absolute;
  left: 22px; right: 22px; top: 0; height: 1px;
  z-index: 1;
  background: linear-gradient(90deg, transparent, rgba(214, 170, 120, .38), transparent);
}
.brand { text-align: center; margin-bottom: 26px; }
.mark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 0;
  vertical-align: middle;
}
.brand .mark { margin-bottom: 18px; }
.mark .word {
  display: inline-block;
  padding: 0;
  border: 0;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, .96) 0%,
    rgba(255, 255, 255, .62) 38%,
    rgba(186, 190, 198, .38) 52%,
    rgba(255, 255, 255, .86) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: rgba(255, 255, 255, .82);
  -webkit-text-fill-color: transparent;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: .16em;
  line-height: 1.15;
  filter:
    drop-shadow(0 1px 0 rgba(255, 255, 255, .5))
    drop-shadow(0 8px 16px rgba(0, 0, 0, .32));
}
.mark .prod {
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .18em;
  color: var(--muted);
}
.card .brand { text-align: left; margin-bottom: 26px; }
.card .brand .m-brand { display: none; }
.card .brand h1 { margin: 0 0 6px; font-size: 22px; font-weight: 600; letter-spacing: -.01em; }
.card .brand p { font-size: 13.5px; color: var(--muted); margin: 0; max-width: none; line-height: 1.6; }
.field { margin-bottom: 16px; }
.field > label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 12.5px;
  color: var(--muted);
  margin: 0 2px 7px;
  letter-spacing: .01em;
}
.field > label .caps { font-size: 11.5px; color: var(--wait); display: none; }
.field.caps-on > label .caps { display: inline; }
.control { position: relative; display: flex; align-items: center; }
.control input,
.app-main input[type=text],
.app-main input[type=password],
.app-main select,
.app-main textarea {
  width: 100%;
  background: var(--input);
  border: 1px solid var(--input-border);
  border-radius: 11px;
  color: var(--txt);
  outline: none;
  transition: border-color .15s var(--ease), background .15s var(--ease);
}
/* 输入框比面板再暗一档，1px 内阴影表示「凹」 */
.control input {
  height: 42px;
  padding: 0 42px 0 13px;
  font-size: 14px;
  border-radius: 10px;
  background: var(--auth-input);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, .3);
  transition: border-color .15s var(--ease), box-shadow .15s var(--ease);
}
.control input[type=password] { letter-spacing: .12em; }
.control input::placeholder,
.app-main textarea::placeholder { color: var(--faint); }
.control input:focus {
  border-color: rgba(214, 170, 120, .5);
  background: var(--auth-input);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, .3), 0 0 0 3px rgba(214, 170, 120, .08);
}
.control input:focus-visible { outline: none; }
.app-main input:focus,
.app-main select:focus,
.app-main textarea:focus {
  border: 1px solid transparent;
  background:
    linear-gradient(var(--input), var(--input)) padding-box,
    linear-gradient(120deg, rgba(255, 255, 255, .38), rgba(214, 170, 120, .45) 48%, rgba(255, 255, 255, .12)) border-box;
}
.toggle {
  position: absolute;
  right: 7px;
  width: 30px;
  height: 30px;
  border: none;
  background: transparent;
  color: var(--faint);
  cursor: pointer;
  border-radius: 7px;
  display: grid;
  place-items: center;
  padding: 0;
  transition: color .15s, background .15s;
}
.toggle:hover { color: var(--muted); background: rgba(255, 255, 255, .05); }
.toggle:active { transform: scale(.97); }
.toggle svg { display: block; }
.field.invalid .control input { border-color: rgba(245, 97, 107, .55); background: var(--auth-input); }
.field.invalid .control input:focus { box-shadow: inset 0 1px 1px rgba(0, 0, 0, .3), 0 0 0 3px rgba(245, 97, 107, .10); }
.msg { display: none; font-size: 12px; color: var(--danger); margin: 6px 2px 0; }
.field.invalid .msg { display: block; }
/* 主按钮：深色；两个框都填了才亮成暖色 */
.btn-wide {
  width: 100%;
  height: 42px;
  margin-top: 16px;
  cursor: pointer;
  background: var(--btn);
  border: 1px solid var(--btn-border);
  border-radius: 10px;
  color: var(--muted);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: .04em;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05);
  transition: transform .12s var(--ease), background .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
.btn-wide:hover { background: var(--btn-h); border-color: rgba(255, 255, 255, .16); color: var(--txt); }
.btn-wide.ready { background: rgba(214, 170, 120, .13); border-color: rgba(214, 170, 120, .42); color: var(--auth-warm-txt); }
.btn-wide.ready:hover { background: rgba(214, 170, 120, .19); border-color: rgba(214, 170, 120, .6); color: #f3e6d2; }
.btn-wide:active { transform: translateY(1px); }
.btn-wide:disabled { opacity: .6; cursor: not-allowed; transform: none; }
.btn-wide.busy { position: relative; color: transparent !important; }
.btn-wide.busy::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 16px; height: 16px;
  margin: -8px 0 0 -8px;
  border: 2px solid rgba(214, 170, 120, .25);
  border-top-color: var(--wait);
  border-radius: 50%;
  animation: auth-spin .7s linear infinite;
}
@keyframes auth-spin { to { transform: rotate(360deg); } }
/* 错误：一行字紧贴字段，不弹框 */
.alert {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 0 2px;
  margin: -6px 0 14px;
  border: 0;
  background: transparent;
  color: var(--danger);
  font-size: 12.5px;
  line-height: 1.5;
}
.alert::before {
  content: "";
  flex: none;
  width: 14px; height: 14px;
  margin-top: 2px;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  background:
    linear-gradient(currentColor, currentColor) 50% 3.5px / 1.5px 5px no-repeat,
    linear-gradient(currentColor, currentColor) 50% 9.5px / 1.5px 1.5px no-repeat;
}
.foot {
  margin-top: 18px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12.5px;
  color: var(--faint);
  letter-spacing: .01em;
  text-align: left;
}
.foot a { color: var(--muted); border-bottom: 1px solid transparent; }
.foot a:hover { color: var(--txt); border-bottom-color: rgba(255, 255, 255, .3); }
.foot .lock { opacity: 0; transition: opacity .3s var(--ease); }
.foot .lock.show { opacity: 1; }
/* Turnstile 是 iframe，里面自带一圈浅灰边框改不了；用 clip-path 往里裁 2px 把它裁掉。外面不再加边。 */
.cf-box {
  width: 100%;
  height: 52px;
  margin: 2px 0 0;
  overflow: hidden;
  border-radius: 10px;
  background: var(--auth-input);
  border: 0;
  line-height: 0;
  clip-path: inset(2px round 10px);
}
.cf-box .cf-turnstile {
  margin: 0;
  width: 125%;
  transform: scale(0.8);
  transform-origin: top left;
}
.cf-box iframe {
  border: 0 !important;
  outline: 0 !important;
}
/* 登录连续输错后才出验证码：上面一行小字说明为什么 */
.cf-why { margin: 6px 0 2px; }
.alert.cf-alert a { color: inherit; text-decoration: underline; text-underline-offset: 2px; margin-left: 4px; }
/* 蜜罐：真人看不见、点不到；机器人会填。不能用 display:none（部分机器人会跳过隐藏字段） */
.hp { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }
/* —— 窄屏：左栏整栏隐藏，卡顶出品牌 —— */
@media (max-width: 920px) {
  .auth-wrap { grid-template-columns: 1fr; }
  .auth-side { display: none; }
  .auth-main { min-height: 100vh; padding: 28px 18px 40px; }
  .card { padding: 30px 24px 26px; }
  .card .brand .m-brand { display: block; margin-bottom: 30px; }
  .card .brand .m-brand .mark { margin: 0; }
  .card .brand .m-brand .mark .word { font-size: 18px; }
}


/* ——— 内页 ——— */
.app-bar {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 14px 40px;
  border-bottom: 1px solid var(--panel-border);
  background: rgba(12, 12, 14, .72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.app-bar .mark {
  margin-bottom: 0;
  white-space: nowrap;
}
.app-bar .mark .word {
  font-size: 16px;
  letter-spacing: .14em;
}
.app-bar nav { display: flex; gap: 6px; }
.app-bar nav a {
  color: var(--muted);
  padding: 6px 10px;
  border-radius: 8px;
  font-size: 13px;
}
.app-bar nav a:hover { color: var(--txt); background: rgba(255, 255, 255, .04); }
.app-bar nav a.on { color: var(--txt); background: rgba(255, 255, 255, .06); }
.app-bar .sp { flex: 1; }
.app-bar .who { color: var(--muted); margin-right: 4px; font-size: 13px; }
.app-bar .lang-switch { margin-right: 10px; display: inline-flex; gap: 2px; }
.lang-switch a {
  color: var(--faint);
  font-size: 12px;
  padding: 6px 8px;
  border-radius: 8px;
}
.lang-switch a:hover { color: var(--txt); background: rgba(255, 255, 255, .04); }
.lang-switch a.on { color: var(--txt); }
body.is-auth .lang-switch {
  position: fixed;
  top: 16px;
  right: 18px;
  z-index: 6;
}
.app-bar .out { color: var(--faint); font-size: 13px; padding: 6px 10px; border-radius: 8px; }
.app-bar .out:hover { color: var(--txt); background: rgba(255, 255, 255, .04); }
.app-bar .api-doc-btn {
  color: #e8d3b4;
  font-size: 13px;
  padding: 6px 10px;
  border-radius: 8px;
  border: 1px solid rgba(214, 170, 120, .32);
  background: rgba(214, 170, 120, .10);
  margin-right: 8px;
  white-space: nowrap;
}
.app-bar .api-doc-btn:hover { background: rgba(214, 170, 120, .18); color: #f3e6d2; }
.app-bar .api-doc-btn.on { background: rgba(214, 170, 120, .22); color: #fff; }
.api-doc .kv {
  display: grid;
  grid-template-columns: 7.5em 1fr auto;
  gap: 8px;
  align-items: center;
  margin: 12px 0 0;
}
.api-doc .kv .k { color: var(--muted); font-size: 12px; }
.api-doc .kv .v { font-family: Consolas, "SF Mono", Menlo, monospace; font-size: 13px; word-break: break-all; }
.api-doc .kv-acts { display: inline-flex; gap: 6px; }
.api-doc .ops { display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 0; }
.api-doc textarea.doc {
  width: 100%;
  min-height: 280px;
  margin-top: 14px;
  font: 12px/1.55 Consolas, "SF Mono", Menlo, monospace;
}
/* 完整文档页：凭证下面一条「插件源码」下载栏，左说明右动作。后台没填地址时整条不渲染 */
.api-doc .pack {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin: 16px 0 0;
  padding: 12px 14px;
  border: 1px solid var(--panel-border);
  border-radius: 12px;
  background: rgba(255, 255, 255, .02);
}
.api-doc .pack-copy { min-width: 0; }
.api-doc .pack-k { margin: 0; font-size: 13.5px; font-weight: 600; letter-spacing: .01em; }
.api-doc .pack-d { margin: 4px 0 0; color: var(--muted); font-size: 12.5px; line-height: 1.5; }
.api-doc .pack-acts { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.api-doc .pack-pin {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 0 10px;
  border-radius: 10px;
  border: 1px solid var(--input-border);
  color: var(--muted);
  font-size: 12px;
}
.api-doc .pack-pin b { color: var(--txt); font: 600 13px/1 Consolas, "SF Mono", Menlo, monospace; }
.api-doc .pack-go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  padding: 0 14px;
  border-radius: 10px;
  color: #f3e6d2;
  background: rgba(214, 170, 120, .10);
  border: 1px solid rgba(214, 170, 120, .28);
  font-size: 13px;
  white-space: nowrap;
  transition: background .15s var(--ease), border-color .15s var(--ease), transform .12s var(--ease);
}
.api-doc .pack-go:hover { background: rgba(214, 170, 120, .18); border-color: rgba(214, 170, 120, .5); color: #fff; }
.api-doc .pack-go:active { transform: scale(.97); }

.site-notice {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 40;
  width: min(360px, calc(100vw - 32px));
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 14px 12px;
  background: #1e1c19;
  border: 1px solid rgba(232, 211, 180, .4);
  border-radius: 14px;
  color: #f4efe6;
}
.site-notice[hidden] { display: none !important; }
.site-notice-hd {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.site-notice-hd b { font-size: 12px; font-weight: 600; letter-spacing: .06em; color: #e8d3b4; }
.site-notice p { margin: 0; font-size: 14px; line-height: 1.55; color: #f4efe6; }
.site-notice-x {
  flex: none;
  min-height: 28px;
  padding: 0 10px;
  border: 1px solid rgba(232, 211, 180, .35);
  border-radius: 8px;
  background: transparent;
  color: #f4efe6;
  cursor: pointer;
  font-size: 12px;
}
.site-notice-x:hover { background: rgba(255, 255, 255, .06); color: #fff; }

.app-main {
  position: relative;
  z-index: 1;
  max-width: 1600px;
  width: 100%;
  margin: 0 auto;
  padding: 28px 40px 48px;
}

.page-head { margin: 0 0 20px; }
.page-head h2 { margin: 0; font-size: 22px; font-weight: 600; letter-spacing: .2px; }
.page-head .sub { margin: 8px 0 0; color: var(--muted); font-size: 13px; }
.log-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}
.cards.log-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 420px; }
.log-panel { padding: 8px 12px 4px; }
.log-table th, .log-table td { padding: 8px 10px; vertical-align: middle; }
.log-plus { color: var(--ok); font-weight: 600; }
.log-minus { color: var(--danger); font-weight: 600; }
.page-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 16px; }
.live-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin: 6px 0 10px;
}
.cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin-bottom: 18px;
}
/* 「同时最多生成 N 条」那句。空文本时不能留出空行，否则卡片和下面的面板之间
   会莫名多出一段间距——元素是常驻的（轮询只改 textContent），只能靠 :empty 收掉。 */
.lane-note { margin: -8px 0 16px; font-size: 13px; }
.lane-note:empty { display: none; }
.stat {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 14px;
  padding: 16px 18px;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
.stat .n { font-size: 28px; font-weight: 600; letter-spacing: .3px; }
.stat .l { color: var(--muted); font-size: 12px; margin-top: 4px; letter-spacing: .4px; }
/* 出片页：三张统计卡收成标题下一条说明，高度留给提示词框。
   只认 .cards.stats-line，图库 / 兑换 / 明细仍用上面的卡片。 */
.page-head-create { margin: 0 0 8px; }
.cards.stats-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0;
  max-width: none;
  margin: 0 0 16px;
  padding: 0 0 12px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--panel-border);
  border-radius: 0;
}
.cards.stats-line .stat {
  flex: 0 0 auto;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 0 22px 0 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.cards.stats-line .stat + .stat {
  padding-left: 22px;
  border-left: 1px solid var(--panel-border);
}
.cards.stats-line .stat .n {
  font-size: 15px;
  letter-spacing: 0;
  line-height: 1.2;
}
.cards.stats-line .stat .l {
  margin-top: 0;
  font-size: 12.5px;
}
.cards.stats-line .stat .n.is-zero { color: var(--faint); }
.cards.stats-line + .lane-note { margin: 0 0 14px; }
#compose .compose-head { margin: 0 0 10px; }
#promptBox {
  min-height: 176px;
  padding: 14px 16px;
  line-height: 1.65;
  border-radius: 12px;
  background: #121214;
}
#promptBox:focus {
  background:
    linear-gradient(#121214, #121214) padding-box,
    linear-gradient(120deg, rgba(255, 255, 255, .38), rgba(214, 170, 120, .45) 48%, rgba(255, 255, 255, .12)) border-box;
}

.panel {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 16px;
  padding: 20px 20px 18px;
  margin-bottom: 16px;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
/* backdrop-filter 会自成一层。下拉绝对定位出面板后，会被后面的「最近任务」盖住。 */
#compose {
  position: relative;
  z-index: 5;
  overflow: visible;
}
.panel h3 { margin: 0 0 14px; font-size: 15px; font-weight: 600; }
.compose-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 16px;
  flex-wrap: wrap;
  margin: 0 0 14px;
}
.compose-head h3 { margin: 0; }
.help-jump {
  display: inline-flex;
  align-items: center;
  min-height: 32px;
  padding: 0 12px;
  border-radius: 999px;
  border: 1px solid rgba(214, 170, 120, .42);
  background: rgba(214, 170, 120, .10);
  color: #e8d3b4;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .02em;
  text-decoration: none;
}
.help-jump:hover {
  color: #fff;
  background: rgba(214, 170, 120, .20);
  border-color: rgba(214, 170, 120, .75);
}
.help-jump:focus-visible {
  outline: 2px solid rgba(214, 170, 120, .6);
  outline-offset: 2px;
}
.panel.live { border-left: 3px solid var(--wait); }
.panel.live-ok { border-left-color: var(--ok); }
.panel.live-bad { border-left-color: var(--danger); }
.panel.live-wait { border-left-color: var(--wait); }

.app-main textarea {
  min-height: 88px;
  padding: 12px 14px;
  resize: vertical;
  line-height: 1.55;
}
.app-main select {
  height: 40px;
  padding: 0 12px;
  width: auto;
  min-width: 132px;
}
.app-main option { background: #161618; color: #f2f2f3; }
.toolbar .pick { position: relative; min-width: 148px; z-index: 1; }
.toolbar .pick.open { z-index: 6; }
.toolbar .pick select {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}
.toolbar .pick-btn {
  position: relative;
  width: 100%;
  height: 40px;
  padding: 0 32px 0 12px;
  background: var(--input);
  border: 1px solid var(--input-border);
  border-radius: 11px;
  color: var(--txt);
  text-align: left;
  cursor: pointer;
}
.toolbar .pick-btn::after {
  content: "";
  position: absolute;
  right: 12px;
  top: 50%;
  width: 8px;
  height: 8px;
  margin-top: -6px;
  border-right: 1.5px solid var(--muted);
  border-bottom: 1.5px solid var(--muted);
  transform: rotate(45deg);
}
.toolbar .pick.open .pick-btn,
.toolbar .pick-btn:focus {
  border-color: rgba(214, 170, 120, .5);
  box-shadow: 0 0 0 3px rgba(214, 170, 120, .08);
  outline: none;
}
.toolbar .pick-menu {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 8px);
  z-index: 40;
  margin: 0;
  padding: 0;
  overflow: hidden;
  list-style: none;
  background: #111113;
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 10px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, .45);
}
.toolbar .pick-menu[hidden] { display: none; }
.toolbar .pick-menu li {
  padding: 9px 12px;
  border-radius: 0;
  color: var(--txt);
  font-size: 13px;
  cursor: pointer;
  background: transparent;
}
.toolbar .pick-menu li + li { border-top: 1px solid rgba(255, 255, 255, .04); }
.toolbar .pick-menu li.is-on,
.toolbar .pick-menu li:hover {
  color: #f3e6d2;
  background: rgba(214, 170, 120, .12);
}
.toolbar .pick-menu li.is-dead,
.toolbar .pick-menu li.is-dead:hover {
  color: var(--faint);
  background: transparent;
  cursor: default;
}
.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-top: 14px;
}
.toolbar label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--muted);
  font-size: 13px;
}
.credit-hint {
  margin: 14px 0 0;
  font-size: 13px;
  font-weight: 600;
  color: #f5d547;
  line-height: 1.5;
}
/* 设置页收口成单一档位时，模型/时长不出下拉，用这个只读块占位 */
.fixed-opt {
  display: inline-block;
  padding: 7px 12px;
  border: 1px solid var(--line, rgba(255,255,255,.12));
  border-radius: 8px;
  color: var(--text, #eee);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}
/* 切到 2.0 Fast 把 30 秒降到 15 时的说明，只在真降级了才出现 */
.dur-note {
  margin: 8px 0 0;
  font-size: 12.5px;
  color: #f5d547;
  line-height: 1.5;
}
.ref-block { margin-top: 14px; }
.ref-block p { margin: 0 0 8px; color: var(--muted); font-size: 13px; }
.ref-block .ref-face { color: #e8d3b4; font-weight: 600; }
/* 视频盾开关：一行，勾选框 + 名字 + 灰色小字说明。默认不勾；服务端在提示词前接前置词，用户看不到那段 */
.shield-opt {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 14px 0 0;
  font-size: 13px;
  color: var(--txt);
  cursor: pointer;
  user-select: none;
}
.shield-opt input { width: 15px; height: 15px; margin: 0; accent-color: #f5d547; cursor: pointer; }
.shield-opt .shield-name { font-weight: 600; }
.shield-opt .shield-sub { color: var(--muted); font-size: 12.5px; }
/* 失败单「修改」态：表单顶上一行说明 + 右侧「取消修改」。跟 .flash 同一套暖色，不做图标不做动画 */
.edit-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 12px;
  padding: 10px 12px;
  border: 1px solid rgba(214, 170, 120, .35);
  background: rgba(214, 170, 120, .08);
  border-radius: 10px;
  font-size: 13px;
  color: #e8d3b4;
  line-height: 1.5;
}
.edit-bar b { font-weight: 600; font-family: Consolas, "SF Mono", Menlo, monospace; font-size: 12.5px; }
.edit-bar .sp { flex: 1; }
.edit-bar a { color: var(--muted); font-size: 12.5px; white-space: nowrap; }
.edit-bar a:hover { color: var(--txt); }
/* 原任务的参考图已被 48 小时清扫时的一句说明，放在缩略图下面 */
.ref-block .ref-expired { margin: 10px 0 0; font-size: 12.5px; color: var(--muted); }
.ref-gallery { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.ref-thumb {
  width: 110px;
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  padding: 6px;
  background: var(--input);
  text-align: center;
}
.ref-thumb img {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: 6px;
  display: block;
  margin: 0 auto 6px;
}
.ref-thumb .nm {
  font-size: 11px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-bottom: 6px;
}

.gal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(460px, 1fr));
  gap: 14px;
  margin-bottom: 16px;
}
.gal-card {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 16px;
  overflow: hidden;
  display: grid;
  grid-template-columns: 152px minmax(0, 1fr);
  align-items: stretch;
}
.gal-pic {
  position: relative;
  background: #111;
  min-height: 152px;
}
.gal-pic a { display: block; width: 100%; height: 100%; cursor: zoom-in; }
.gal-pic img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 200ms var(--ease), filter 160ms var(--ease);
}
.gal-pic img.is-on { opacity: 1; }
.gal-view {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: rgba(0, 0, 0, .72);
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms var(--ease), visibility 0s linear 220ms;
}
.gal-view.is-on {
  visibility: visible;
  opacity: 1;
  pointer-events: auto;
  transition: opacity 220ms var(--ease), visibility 0s;
}
.gal-view img {
  max-width: min(92vw, 920px);
  max-height: 86vh;
  object-fit: contain;
  border-radius: 10px;
  opacity: 0;
  transform: scale(.96);
  transition: opacity 220ms var(--ease), transform 220ms var(--ease);
}
.gal-view.is-on img.is-on { opacity: 1; transform: scale(1); }
.gal-view-x {
  position: absolute;
  top: 16px;
  right: 16px;
}
.gal-st {
  position: absolute;
  left: 8px;
  top: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  background: rgba(0, 0, 0, .72);
  color: #fff;
}
.gal-st.is-ok { background: #1a5c38; color: #fff; }
.gal-st.is-warn { background: #8a2a32; color: #fff; }
.gal-kind {
  position: absolute;
  left: 8px;
  bottom: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  background: rgba(0, 0, 0, .55);
  color: #e8d3b4;
}
/* 图库项编号：API 提交 gallery_ids 用这个数。右下角，和左下角的类别标签对称 */
.gal-id {
  position: absolute;
  right: 8px;
  bottom: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  background: rgba(0, 0, 0, .55);
  color: var(--muted);
  cursor: help;
}
.kind-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.kind-row button {
  min-height: 34px;
  padding: 0 14px;
  border-radius: 999px;
}
.kind-row button.on {
  border-color: rgba(214, 170, 120, .7);
  background: rgba(214, 170, 120, .12);
  color: #e8d3b4;
  font-weight: 600;
}
.gal-fields .span-full { grid-column: 1 / -1; }
.gal-file-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
}
.gal-file-hid {
  position: absolute;
  left: -9999px;
  width: 0;
  height: 0;
  opacity: 0;
}
.gal-meta {
  padding: 10px 12px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.gal-meta-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 8px;
}
.gal-meta-grid .span-full { grid-column: 1 / -1; }
.gal-meta label, .gal-fields label {
  display: grid;
  gap: 3px;
  font-size: 12px;
  color: var(--muted);
}
.gal-meta input, .gal-fields input[type=text] {
  height: 32px;
  padding: 0 10px;
}
.gal-fields {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
}
.gal-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: auto;
}
/* 图库：图上的遮罩——处理中转圈 + 用时，排队中第几位。只在这两个状态显示，不挡住点图放大。 */
.gal-ov {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px;
  text-align: center;
  background: rgba(10, 10, 12, .62);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  color: #f2f2f3;
  pointer-events: none;
}
.gal-card[data-status="converting"] .gal-ov,
.gal-card[data-status="queued"] .gal-ov { display: flex; }
/* 遮罩已经把状态写在正中间了，角上的小标签在模糊层底下只剩一团糊，这两个状态下不显示 */
.gal-card[data-status="converting"] .gal-st,
.gal-card[data-status="queued"] .gal-st,
.gal-card[data-status="converting"] .gal-kind,
.gal-card[data-status="queued"] .gal-kind { display: none; }
.gal-card[data-status="queued"] .gal-ov { background: rgba(10, 10, 12, .5); }
.gal-ov-ring {
  display: none;
  width: 22px; height: 22px;
  border: 2px solid rgba(255, 255, 255, .18);
  border-top-color: #e8d3b4;
  border-radius: 50%;
  animation: galspin .8s linear infinite;
}
.gal-card[data-status="converting"] .gal-ov-ring { display: block; }
.gal-ov-t { font-size: 13px; font-weight: 600; letter-spacing: .2px; }
.gal-ov-s { font-size: 12px; color: rgba(255, 255, 255, .72); font-variant-numeric: tabular-nums; min-height: 1em; }
.gal-card[data-status="queued"] .gal-ov-t { color: #e8d3b4; }

/* 图库：底部进度条——几张在转、几张排队、当前用时。转完显示两秒「全部完成」再收起。 */
.gal-prog {
  position: fixed;
  left: 50%;
  bottom: 22px;
  z-index: 70;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px 9px 14px;
  border-radius: 999px;
  background: #1c1c1f;
  border: 1px solid rgba(214, 170, 120, .4);
  color: #e8d3b4;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .06);
  animation: galprogin 220ms var(--ease);
}
.gal-prog[hidden] { display: none; }
.gal-prog-ring {
  width: 14px; height: 14px;
  border: 2px solid rgba(232, 211, 180, .25);
  border-top-color: #e8d3b4;
  border-radius: 50%;
  animation: galspin .8s linear infinite;
}
.gal-prog-s { color: var(--muted); font-weight: 500; font-variant-numeric: tabular-nums; }
.gal-prog-s:empty { display: none; }
.gal-prog.is-done { border-color: rgba(125, 222, 160, .4); color: #7ddea0; }
.gal-prog.is-done .gal-prog-ring { display: none; }
@keyframes galprogin { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }

/* 图库：状态真变了的那张卡闪一下暖色边（其它卡不动，不再整页重建） */
.gal-card.is-changed { animation: galchanged 900ms var(--ease); }
@keyframes galchanged {
  0% { box-shadow: 0 0 0 0 rgba(214, 170, 120, 0); }
  25% { box-shadow: 0 0 0 2px rgba(214, 170, 120, .55); }
  100% { box-shadow: 0 0 0 0 rgba(214, 170, 120, 0); }
}
.btn.is-busy { opacity: .7; pointer-events: none; }
.btn.is-busy::after {
  content: "";
  width: 12px; height: 12px; margin-left: 8px;
  border: 2px solid rgba(255,255,255,.25);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: galspin .7s linear infinite;
}
@keyframes galspin { to { transform: rotate(360deg); } }
.gal-modal {
  position: fixed; inset: 0; z-index: 40;
  background: rgba(0,0,0,.55);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.gal-modal[hidden] { display: none; }
.gal-modal-box {
  width: min(720px, 100%);
  max-height: 80vh;
  overflow: auto;
  background: var(--panel-solid);
  border: 1px solid var(--panel-border);
  border-radius: 16px;
  padding: 18px;
}
.gal-modal-box h3 { margin: 0 0 8px; }
.gal-pick-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 10px; }
.gal-pick-item {
  border: 1px solid var(--panel-border);
  background: var(--input);
  border-radius: 12px;
  padding: 8px;
  color: inherit;
  cursor: pointer;
  display: grid;
  gap: 6px;
  text-align: center;
}
.gal-pick-item img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 8px; }
.gal-pick-item.is-on { border-color: rgba(214,170,120,.7); }
.gal-pick-st { font-size: 11px; color: var(--muted); font-weight: 600; }
.gal-pick-item:disabled { opacity: .45; cursor: not-allowed; }
.gal-modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  padding: 0 12px;
  border: 1px solid var(--btn-border);
  border-radius: 10px;
  background: var(--btn);
  color: var(--txt);
  text-decoration: none;
  cursor: pointer;
  font-size: 13px;
  transition: background .15s var(--ease), border-color .15s var(--ease), transform .12s var(--ease);
}
.btn:hover { background: var(--btn-h); border-color: rgba(255, 255, 255, .16); color: var(--txt); }
.btn:active { transform: scale(.97); }
.btn-danger { border-color: rgba(245, 97, 107, .4); color: var(--danger); }
.btn-danger:hover { background: rgba(245, 97, 107, .12); color: var(--danger); }
.btn-go { min-height: 40px; padding: 0 18px; font-weight: 600; letter-spacing: .3px; margin-left: auto; }
.btn-submit {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .08) 0%, rgba(255, 255, 255, 0) 46%),
    #222226;
  color: #f2f2f3;
  border: 1px solid rgba(255, 255, 255, .10);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .16),
    inset 0 -1px 0 rgba(0, 0, 0, .38),
    0 1px 2px rgba(0, 0, 0, .4);
  text-shadow: 0 0 16px rgba(255, 255, 255, .16);
  transition: background .15s var(--ease), border-color .15s var(--ease), box-shadow .15s var(--ease), transform .12s var(--ease), color .15s var(--ease);
}
.btn-submit:hover {
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .12) 0%, rgba(255, 255, 255, 0) 50%),
    #2a2a2f;
  color: #fff;
  border-color: rgba(255, 255, 255, .16);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .22),
    inset 0 -1px 0 rgba(0, 0, 0, .32),
    0 4px 14px rgba(0, 0, 0, .35);
}
.job-acts {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex-wrap: nowrap;
  margin: 0;
}
.job-acts form.inline { display: inline-flex; margin: 0; }

/* 任务行动作按钮只有这一个尺寸：停止 / 复制全文 / 重新生成 / 删除 / 重取 / 打开视频 / 下载。
   必须排在 .btn 后面——原来 .btn-stop 写在文件上半部分（.live-meta 旁边），
   跟 .btn 同特异性但更靠前，min-height / padding / font-size 三条全被 .btn 盖掉，
   于是停止键按 36px 渲染、同一行的复制和重试是 26px，用户看到的就是两套尺寸。 */
.btn-sm,
.btn-stop,
.job-acts .btn {
  min-height: 28px;
  height: 28px;
  padding: 0 10px;
  font-size: 12px;
  border-radius: 7px;
}
/* 受理后不给停，按钮位置换成一句说明。高度跟按钮对齐，那一行才不会忽高忽低。 */
.job-note {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  font-size: 12px;
  color: var(--muted);
}

.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
th, td {
  padding: 11px 10px;
  text-align: left;
  border-bottom: 1px solid rgba(255, 255, 255, .05);
  font-size: 13px;
  vertical-align: top;
}
th { color: var(--faint); font-weight: 600; font-size: 12px; letter-spacing: .4px; }
td.wrap { overflow-wrap: anywhere; word-break: break-word; }
.err-preview { white-space: nowrap; }
tr.is-on td { background: rgba(214, 170, 120, .08); }
tr:last-child td { border-bottom: 0; }

.pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 12px;
}
.s-active { background: rgba(125, 222, 160, .14); color: var(--ok); }
.s-captcha { background: rgba(245, 97, 107, .14); color: var(--danger); }
.s-exhausted { background: rgba(214, 170, 120, .16); color: var(--wait); }
.s-dead { background: rgba(255, 255, 255, .06); color: var(--muted); }

.muted { color: var(--muted); }
.warn { color: var(--danger); }
/* 操作结果提示。跟后台 soglog/theme.css 的 .flash 保持同一套：屏幕中央浮层，
   2.8 秒后自己淡出（JS 在 portal_footer()）。原来是正文里的横条，会把下面的内容
   顶下去，用户点完停止得先找它在哪。改成浮层后不占版面，也不用手动关。 */
.flash {
  position: fixed;
  left: 50%;
  top: 46%;
  z-index: 80;
  transform: translate(-50%, -50%);
  max-width: 420px;
  width: calc(100% - 32px);
  margin: 0;
  background: #1c1c1f;
  border: 1px solid rgba(214, 170, 120, .4);
  color: #e8d3b4;
  padding: 14px 16px;
  border-radius: 12px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, .45);
  white-space: pre-wrap;
  line-height: 1.5;
  transition: opacity .25s ease;
}
.flash.flash-err {
  border-color: rgba(245, 97, 107, .4);
  color: var(--danger);
}
/* 确认层：替代浏览器原生 confirm()（白框、样式改不了）。JS 在 soglog/adminlib.php page_footer()，
   portal_footer 末尾也走它。所有 onsubmit/onclick="return confirm(...)" 自动走这里。
   跟 .flash / .gal-modal 同一套色板。 */
.confirm-ov {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0);
  transition: background .16s var(--ease);
}
.confirm-ov.is-in { background: rgba(0, 0, 0, .62); -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); }
.confirm-box {
  position: relative;
  z-index: 1;
  width: min(420px, 100%);
  background: #1c1c1f;
  border: 1px solid rgba(214, 170, 120, .4);
  border-radius: 14px;
  padding: 20px 20px 16px;
  box-shadow: 0 18px 40px rgba(0, 0, 0, .55), 0 0 0 1px rgba(0, 0, 0, .6);
  transform: translateY(6px) scale(.98);
  opacity: 0;
  transition: transform .16s var(--ease), opacity .16s var(--ease);
}
.confirm-ov.is-in .confirm-box { transform: none; opacity: 1; }
.confirm-msg {
  margin: 0;
  color: #e8d3b4;
  font-size: 14px;
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-word;
}
.confirm-acts {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
}
.confirm-acts .btn { min-height: 36px; padding: 0 16px; }
.confirm-ok {
  background: var(--btn-h);
  border-color: rgba(255, 255, 255, .16);
  font-weight: 600;
}
.confirm-ok:hover { background: #323238; color: #fff; }
form.inline { display: inline; }
.player { padding: 0; overflow: hidden; background: #000; }
.player video { display: block; width: 100%; max-height: calc(100vh - 170px); background: #000; }

.asset-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px;
}
.asset-card {
  background: var(--panel);
  border: 1px solid var(--panel-border);
  border-radius: 16px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.asset-preview {
  display: block;
  position: relative;
  width: 100%;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  background: #000;
  flex: 0 0 auto;
}
.asset-preview video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  pointer-events: none;
}
.asset-body {
  padding: 12px 14px 14px;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.asset-id { font-weight: 600; font-size: 13px; margin-bottom: 4px; }
.asset-meta { font-size: 12px; }
.asset-prompt {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--muted);
  line-height: 1.45;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.asset-acts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
  margin-top: auto;
  padding-top: 12px;
}
.asset-acts .btn,
.asset-acts form {
  min-width: 0;
}
.asset-acts form { display: flex; }
.asset-acts .btn {
  width: 100%;
  min-height: 32px;
  padding: 0 4px;
  font-size: 12px;
}
.asset-acts .btn[disabled],
.asset-acts .btn[aria-disabled="true"] {
  opacity: .45;
  pointer-events: none;
}
.asset-time { font-size: 12px; margin-top: 10px; }
.pager { display: flex; align-items: center; gap: 12px; margin-top: 20px; }

/* 卡密兑换 */
.redeem-form { display: flex; gap: 10px; align-items: stretch; }
.redeem-form input[type=text] {
  flex: 1;
  min-width: 0;
  height: 44px;
  padding: 0 14px;
  font: 500 16px/1 Consolas, "SF Mono", Menlo, monospace;
  letter-spacing: .12em;
  text-transform: uppercase;
  background: var(--input);
  color: var(--txt);
  border: 1px solid var(--input-border);
  border-radius: 10px;
  outline: none;
}
.redeem-form input[type=text]::placeholder { letter-spacing: .06em; font-weight: 400; color: var(--faint); font-size: 14px; text-transform: none; font-family: inherit; }
.redeem-form input[type=text]:focus { border-color: rgba(214, 170, 120, .5); box-shadow: 0 0 0 3px rgba(214, 170, 120, .08); }
.redeem-form .redeem-go { min-height: 44px; padding: 0 20px; font-size: 14px; border-radius: 10px; }
.redeem-form .redeem-go.ready { background: rgba(214, 170, 120, .13); border-color: rgba(214, 170, 120, .42); color: #e8d3b4; }
.redeem-form .redeem-go.ready:hover { background: rgba(214, 170, 120, .19); border-color: rgba(214, 170, 120, .6); }
.redeem-small { font-size: 12.5px; color: var(--faint); margin: 10px 0 0; }
.redeem-h3 { margin: 0 0 12px; font-size: 15px; font-weight: 600; }
.redeem-table th, .redeem-table td { padding: 10px; vertical-align: middle; }
.redeem-code { font-family: Consolas, "SF Mono", Menlo, monospace; letter-spacing: .04em; color: var(--muted); }
@media (max-width: 640px) { .redeem-form { flex-direction: column; } }

/* 兑换页「购买卡密」：左商品列表 + 三步，右二维码（随选中商品切换）。左侧暖色边表示"这是入口"。
   数据来自后台「卡密 → 在线购买入口」；没配就整块不渲染。 */
.buy { display: grid; grid-template-columns: minmax(0, 1fr) 190px; gap: 20px; align-items: start; border-left: 3px solid var(--wait); }
.buy-title { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.buy-title h3 { margin: 0; font-size: 15px; font-weight: 600; }
.buy-sub { color: var(--muted); font-size: 13px; }
.buy-items { display: grid; gap: 8px; margin: 0 0 14px; }
.buy-item { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--panel-border); border-radius: 10px; background: rgba(255, 255, 255, .02); cursor: pointer; transition: border-color .15s var(--ease), background .15s var(--ease); }
.buy-item:hover { background: rgba(255, 255, 255, .04); }
.buy-item.on { border-color: rgba(214, 170, 120, .55); background: rgba(214, 170, 120, .08); }
.buy-item .nm { flex: 1; min-width: 0; }
.buy-item .nm b { display: block; font-weight: 600; font-size: 14px; }
.buy-item .nm span { display: block; font-size: 12.5px; color: var(--muted); margin-top: 2px; }
.buy-item .pr { font-size: 18px; font-weight: 600; color: #e8d3b4; white-space: nowrap; }
.buy-item .btn { min-height: 32px; padding: 0 14px; font-size: 13px; }
.buy-steps { margin: 0; padding: 0; list-style: none; display: grid; gap: 8px; }
.buy-steps li { display: flex; gap: 10px; align-items: flex-start; font-size: 13.5px; }
.buy-steps .no { flex: none; width: 22px; height: 22px; border-radius: 50%; border: 1px solid rgba(214, 170, 120, .45); color: #e8d3b4; font-size: 12px; display: inline-flex; align-items: center; justify-content: center; margin-top: 1px; }
.buy-steps .cur { color: #e8d3b4; }
.buy-side { display: grid; gap: 10px; justify-items: center; text-align: center; align-content: start; position: sticky; top: 16px; }
.buy-qr { width: 150px; height: 150px; padding: 10px; background: #fff; border-radius: 12px; }
.buy-qr svg { width: 100%; height: 100%; display: block; shape-rendering: crispEdges; }
.buy-qr-cap { font-size: 12px; color: var(--muted); margin-top: -4px; }
.buy-qr-cap b { color: var(--txt); font-weight: 500; }
.buy-note { grid-column: 1 / -1; margin: 2px 0 0; font-size: 12.5px; color: var(--faint); }
/* 出片页次数不足时的入口（credit-hint 里的一条链接） */
.buy-cta { color: #e8d3b4; text-decoration: underline; text-underline-offset: 3px; }
.buy-cta:hover { color: #f3e6d2; }
@media (max-width: 640px) {
  .buy { grid-template-columns: 1fr; gap: 14px; }
  .buy-side { display: none; }           /* 手机扫不了自己的屏幕，各商品的「去购买」就够了 */
  .buy-item { flex-wrap: wrap; }
  .buy-item .btn { flex-basis: 100%; }
}

/* 维护页（portal_maintenance_render）：平的深色，不加纹理不加渐变 */
.mt-body { margin: 0; background: #0c0c0e; }
.mt-page { min-height: 100vh; display: grid; place-items: center; padding: 48px 24px; }
.mt-card { width: min(420px, 100%); }
.mt-brand { font-size: 12px; letter-spacing: .3em; color: #b9b0a1; margin-bottom: 22px; font-weight: 600; }
.mt-card h1 { margin: 0 0 10px; font-size: 24px; line-height: 1.25; font-weight: 600; letter-spacing: -.01em; }
.mt-text { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.65; }
.mt-meta { margin-top: 14px; font-size: 13px; color: var(--faint); line-height: 1.7; }
.mt-meta b { color: var(--txt); font-weight: 500; }
.mt-acts { margin-top: 20px; display: flex; gap: 14px; align-items: center; }
.mt-retry { min-height: 36px; padding: 0 16px; font-size: 13.5px; border-radius: 9px; }
.mt-lang { font-size: 12.5px; color: var(--faint); }
.mt-lang:hover { color: var(--txt); }

.help h2, .help h3 { margin: 18px 0 8px; font-weight: 600; }
.help h2 { margin-top: 0; font-size: 22px; }
.help h3 { font-size: 15px; color: var(--txt); }
.help p, .help li { color: var(--muted); }
.help b { color: var(--txt); font-weight: 600; }
.help code {
  background: rgba(255, 255, 255, .06);
  padding: 1px 6px;
  border-radius: 5px;
  color: #e8d3b4;
}
.help a { color: #e8d3b4; text-decoration: underline; text-underline-offset: 2px; }
.help-must {
  margin: 14px 0 22px;
  padding: 14px 16px 12px;
  border-radius: 12px;
  background: rgba(214, 170, 120, .10);
  border: 1px solid rgba(214, 170, 120, .38);
  box-shadow: inset 3px 0 0 #d6aa78;
}
.help-must .k {
  margin: 0 0 10px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .12em;
  color: #e8d3b4;
}
.help-must ol {
  margin: 0;
  padding-left: 20px;
  display: grid;
  gap: 12px;
}
.help-must li { color: var(--txt); line-height: 1.65; }
.help-must li b { color: #fff; }
.help-must .d { display: block; margin-top: 4px; color: var(--muted); font-size: 13px; font-weight: 400; }
.help-no {
  margin: 10px 0 12px;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgba(245, 97, 107, .08);
  border: 1px solid rgba(245, 97, 107, .28);
}
.help-no .k { margin: 0 0 8px; font-size: 12.5px; font-weight: 700; color: var(--danger); }
.help-no ul { margin: 0; padding-left: 18px; display: grid; gap: 6px; }
.help-no li { color: #c9c4be; font-size: 13px; }
/* 说明页：提示词示范 */
.help .tpl-box { margin: 10px 0 12px; }
.help pre.tpl {
  margin: 0;
  max-height: 340px;
  overflow: auto;
  padding: 12px 14px;
  background: rgba(255, 255, 255, .04);
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 10px;
  color: var(--txt);
  font-family: inherit;
  font-size: 13px;
  line-height: 1.75;
  white-space: pre-wrap;
  word-break: break-word;
}
.help .tpl-acts { display: flex; align-items: center; gap: 12px; margin-top: 8px; flex-wrap: wrap; }
.help .tpl-note { font-size: 12.5px; color: var(--muted); opacity: 0; transition: opacity .2s; }
.help .tpl-note.show { opacity: 1; }
/* 说明页：内容规范 */
.help ul.rules li { margin: 4px 0; }

/* 分享页：左边链接 / 文案 / 怎么发，右边海报 */
.share { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 16px; align-items: start; }
.share-side { position: sticky; top: 16px; }
.share .panel h3 { margin: 0 0 12px; font-size: 15px; font-weight: 600; }
.share-link { border-left: 3px solid var(--wait); }
.link-row { display: flex; gap: 10px; align-items: stretch; margin: 6px 0 12px; }
.link-box { flex: 1; min-width: 0; display: flex; align-items: center; height: 46px; padding: 0 14px; background: var(--input); border: 1px solid var(--input-border); border-radius: 10px; font: 500 15px/1 Consolas, "SF Mono", Menlo, monospace; letter-spacing: .02em; color: #e8d3b4; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.share-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.share-acts .btn { display: inline-flex; align-items: center; gap: 6px; }
.share-toast { font-size: 12.5px; color: var(--ok); opacity: 0; transition: opacity .2s; margin-left: 4px; }
.share-toast.show { opacity: 1; }
.share-text { margin: 0; padding: 12px 14px; background: rgba(255, 255, 255, .03); border: 1px solid var(--panel-border); border-radius: 10px; color: var(--muted); font-family: inherit; font-size: 13px; line-height: 1.7; white-space: pre-wrap; word-break: break-word; }
.share-hint { margin: 10px 0 0; font-size: 12.5px; color: var(--faint); }
.share-tips { margin: 0; padding-left: 18px; color: var(--muted); font-size: 13px; display: grid; gap: 4px; }
.share-poster { display: grid; gap: 10px; justify-items: center; }
.share-poster .poster { width: 100%; max-width: 300px; border-radius: 14px; display: block; box-shadow: 0 18px 50px rgba(0, 0, 0, .45); }
.share-poster-btn { width: 100%; }
.poster-cap { margin: 0; font-size: 12px; color: var(--faint); text-align: center; }
.poster-cap.m { display: none; }
@media (max-width: 720px) {
  .share { grid-template-columns: 1fr; }
  .share-side { position: static; order: -1; }
  .link-row { flex-direction: column; }
  .share-acts .btn { flex: 1 1 calc(50% - 4px); }
  .poster-cap.d { display: none; }
  .poster-cap.m { display: block; }
}

@media (max-width: 720px) {
  .app-bar {
    flex-wrap: wrap;
    padding: 10px 16px;
    gap: 8px 10px;
  }
  .app-bar .mark .word { font-size: 15px; letter-spacing: .1em; }
  .app-bar .mark .prod { font-size: 12px; letter-spacing: .12em; }
  .app-bar nav a {
    min-height: 40px;
    display: inline-flex;
    align-items: center;
    padding: 0 10px;
  }
  .app-bar .who {
    max-width: 36vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .app-bar .out { min-height: 40px; display: inline-flex; align-items: center; }
  .app-bar .api-doc-btn { min-height: 40px; display: inline-flex; align-items: center; }
  .api-doc .kv { grid-template-columns: 1fr; }
  .api-doc .pack { flex-direction: column; align-items: stretch; }
  .api-doc .pack-acts { justify-content: flex-start; flex-wrap: wrap; }
  .site-notice { right: 12px; bottom: 12px; }
  .app-main { padding: 18px 14px 36px; }
  .card { padding: 32px 22px 24px; }
  .cards { grid-template-columns: 1fr; }
  .cards.stats-line { display: flex; }
  .cards.stats-line .stat,
  .cards.stats-line .stat + .stat { padding: 0 12px 0 0; }
  .cards.stats-line .stat + .stat { padding-left: 12px; }
  #promptBox { min-height: 152px; }
  .cards.log-cards { grid-template-columns: 1fr 1fr; max-width: none; }
  .log-head { flex-wrap: wrap; }
  .asset-grid, .gal-grid { grid-template-columns: 1fr; }
  .gal-card { grid-template-columns: 1fr; }
  .gal-pic { min-height: 0; }
  .gal-pic img { height: auto; aspect-ratio: 1; }
  .btn-go { margin-left: 0; width: 100%; }
  .toolbar label { width: 100%; }
  .toolbar select,
  .toolbar .pick { flex: 1; min-width: 0; width: 100%; }
  .control input,
  .app-main textarea,
  .app-main select,
  .gal-meta input,
  .gal-fields input { font-size: 16px; }
  .table-wrap { -webkit-overflow-scrolling: touch; }
}

@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: var(--btn-h); }
  .gal-pic a:hover img.is-on { filter: brightness(1.08); }
  .btn-submit:hover {
    background:
      linear-gradient(180deg, rgba(255, 255, 255, .12) 0%, rgba(255, 255, 255, 0) 50%),
      #2a2a2f;
    color: #fff;
  }
}

@media (prefers-reduced-motion: reduce) {
  .btn, .btn-wide, .toggle, .control input { transition: none; }
  .gal-pic img { transition: none; opacity: 1; filter: none; }
  .gal-view, .gal-view img { transition: none; transform: none; }
}
