:root {
  --bg: #171b22;
  --panel: #20252e;
  --panel-2: #292f3a;
  --ink: #dce3ed;
  --muted: #a0adbf;
  --line: #394353;
  --accent: #3978d6;
  --accent-ink: #ffffff;
  --accent-soft: #233753;
  --ok: #79c99c;
  --ok-soft: #213b30;
  --warn: #e9bd70;
  --warn-soft: #40351f;
  --bad: #f39098;
  --bad-soft: #432830;
  --info: #8dbdff;
  --info-soft: #24364e;
  --shadow: 0 8px 28px rgba(0,0,0,.2);
  --radius: 10px;
  --font: "Microsoft YaHei UI", "Microsoft YaHei", "PingFang SC", "Noto Sans SC", system-ui, sans-serif;
  color-scheme: dark;
}
.factory-head { margin-bottom: 20px; }
.factory-head h1 { font-size: 26px; margin-bottom: 6px; }
.factory-summary { display: grid; grid-template-columns: repeat(4,1fr); gap: 12px; margin-bottom: 20px; }
.factory-summary b { display: block; font-size: 28px; }
.factory-summary span { display: block; color: var(--muted); font-size: 12px; }
.factory-start { margin-bottom: 24px; }
.factory-entry { text-align: left; cursor: pointer; color: var(--ink); }
.factory-entry:hover { border-color: var(--accent); }
.factory-entry h2 { margin-bottom: 10px; }
.factory-list { margin-top: 12px; }
.factory-section { margin-top: 20px; }
.factory-grid { display: grid; grid-template-columns: repeat(auto-fill,minmax(240px,1fr)); gap: 16px; }
.factory-art { width: 100%; height: 260px; object-fit: contain; background: var(--panel-2); border-radius: 6px; }
.factory-ref { width: 100px; height: 100px; object-fit: contain; }
.factory-placeholder { height: 150px; display: grid; place-items: center; background: var(--panel-2); padding: 12px; overflow-wrap: anywhere; }
.factory-script { white-space: pre-wrap; font: inherit; max-height: 420px; overflow: auto; }
.factory-video { max-height: 480px; max-width: 100%; }
#fc-form fieldset { border: 0; padding: 0; margin: 0; display: grid; gap: 16px; min-width: 0; }
#fc-form textarea { min-height: 100px; }
/* Long scripts need a reading area independent of the number of imported episodes. */
textarea[data-key="script"], #fc-form textarea[data-f="script"], #sc-text {
  min-height: max(360px, 55vh) !important;
  height: 55vh;
  line-height: 1.85;
  padding: 14px 16px;
  resize: vertical;
}
#fc-metrics { margin-top: 12px; }
.factory-item textarea { min-height: 90px; }
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body { background: var(--bg); color: var(--ink); font: 14px/1.6 var(--font); }
a { color: #8dbdff; text-underline-offset: 3px; }
::selection { background: #345581; color: #f0f4fa; }
* { scrollbar-width: thin; scrollbar-color: #4a5568 var(--bg); }
:focus-visible { outline: 2px solid #8dbdff; outline-offset: 3px; }
input::placeholder, textarea::placeholder { color: #8996aa; opacity: 1; }
input[type=checkbox], input[type=radio] { accent-color: var(--accent); }
[hidden] { display: none !important; }
button, input, textarea, select { font: inherit; color: inherit; }
h1, h2, h3 { margin: 0; line-height: 1.3; }
h2 { font-size: 18px; }
h3 { font-size: 15px; }
p { margin: 0 0 8px; }
.muted { color: var(--muted); }
.small { font-size: 12px; }
.hidden { display: none !important; }
.row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.spacer { flex: 1; }
.stack { display: grid; gap: 12px; align-content: start; }

/* buttons & inputs */
.btn { border: 1px solid var(--line); background: var(--panel); padding: 7px 14px; border-radius: 8px; cursor: pointer; white-space: nowrap; }
.btn:hover { border-color: var(--muted); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.btn.primary:hover { filter: brightness(1.05); }
.btn.ghost { border-color: transparent; background: transparent; }
.btn.danger { color: var(--bad); }
.btn.big { padding: 11px 22px; font-size: 15px; }
input:not([type]), input[type=text], input[type=number], input[type=password], input[type=search], input[type=email], input[type=url], textarea, select {
  width: 100%; border: 1px solid var(--line); background: var(--panel); border-radius: 8px; padding: 8px 10px; outline: none;
}
input:focus, textarea:focus, select:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
textarea { resize: vertical; min-height: 120px; line-height: 1.7; }
label.field { display: grid; gap: 4px; align-content: start; }
label.field > span { font-size: 12px; color: var(--muted); }
.multi-preference { display: grid; gap: 8px; align-content: start; }
.multi-preference > span { font-size: 12px; color: var(--muted); }
.multi-preference details { border: 1px solid var(--line); border-radius: 8px; padding: 10px; background: var(--panel); }
.multi-preference summary { cursor: pointer; }
.multi-options { max-height: 260px; overflow: auto; margin: 10px 0; }
.multi-options [data-multi-group] { margin-bottom: 12px; }
.multi-selected { gap: 6px; }
.multi-preference input[type=search] { width: 100%; padding: 8px; border: 1px solid var(--line); border-radius: 6px; background: var(--bg); margin-top: 10px; }
#portal, #portal > section { display: grid; gap: 16px; }
#portal [data-account] + [data-account] { margin-top: 10px; }
#portal [data-user] { margin-top: 14px; }
#portal summary { cursor: pointer; }
#portal [data-job-state] { margin-top: 12px; overflow-wrap: anywhere; }

/* layout */
.topbar { height: 56px; display: flex; align-items: center; gap: 16px; padding: 0 18px; border-bottom: 1px solid var(--line); background: var(--panel); position: sticky; top: 0; z-index: 5; }
.brand { font-weight: 700; font-size: 16px; display: flex; gap: 8px; align-items: center; }
.brand-mark { width: 26px; height: 26px; border-radius: 7px; background: var(--accent); color: #fff; display: grid; place-items: center; font-size: 14px; }
.project-title { font-weight: 600; }
.budget { display: grid; gap: 2px; min-width: 190px; }
.budget-bar { height: 6px; background: var(--panel-2); border-radius: 99px; overflow: hidden; }
.budget-bar > div { height: 100%; background: var(--ok); }
.pill { font-size: 12px; padding: 2px 10px; border-radius: 99px; background: var(--panel-2); color: var(--muted); border: 1px solid var(--line); }

.shell { display: grid; grid-template-columns: 210px 1fr; height: calc(100vh - 56px); }
.sidebar { border-right: 1px solid var(--line); padding: 14px 10px; overflow: auto; background: var(--panel); }
.sidebar h3 { font-size: 12px; color: var(--muted); padding: 0 8px 8px; font-weight: 600; }
.ep { display: block; width: 100%; text-align: left; padding: 9px 10px; border-radius: 8px; border: 0; background: transparent; cursor: pointer; margin-bottom: 2px; }
.ep:hover { background: var(--panel-2); }
.ep.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.ep .sub { display: block; font-size: 12px; color: var(--muted); font-weight: 400; }
.main { overflow: auto; padding: 20px 28px 90px; }

/* steps */
.steps { display: flex; gap: 6px; margin-bottom: 18px; border-bottom: 1px solid var(--line); }
.step { border: 0; background: transparent; padding: 10px 14px; cursor: pointer; color: var(--muted); border-bottom: 2px solid transparent; margin-bottom: -1px; display: flex; gap: 6px; align-items: center; }
.step .n { width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; font-size: 12px; background: var(--panel-2); }
.step.active { color: var(--ink); border-bottom-color: var(--accent); font-weight: 600; }
.step.active .n { background: var(--accent); color: #fff; }
.step.done .n { background: var(--ok); color: #fff; }
.step .badge { font-size: 11px; background: var(--warn-soft); color: var(--warn); border-radius: 99px; padding: 0 7px; }

.card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius); padding: 18px; box-shadow: var(--shadow); }
/* A card that folds (作品页的画风、出图要求、人物设定图…): the title line is the switch, ▸ turns when open; folded, the
   card is only its title (a folded grid card kept a gap below it). The back office styles its own (.admin-content). */
#app details.card > summary { cursor: pointer; list-style: none; display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; font-weight: 600; }
#app details.card > summary::-webkit-details-marker { display: none; }
#app details.card > summary::before { content: "▸"; color: var(--muted); transition: transform .15s; flex: none; }
#app details.card[open] > summary::before { transform: rotate(90deg); color: var(--accent); }
#app details.card > summary .muted, #app details.guided-auto > summary { font-weight: normal; }
#app details.card:not([open]) { display: block; padding-top: 14px; padding-bottom: 14px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
@media (max-width: 1000px) { .grid-2, .grid-3 { grid-template-columns: 1fr; } }
.option { cursor: default; display: grid; gap: 8px; align-content: start; }
.option .tag { justify-self: start; }
.tag { font-size: 12px; padding: 1px 8px; border-radius: 6px; background: var(--ok-soft); color: var(--ok); }
.tag.paid { background: var(--warn-soft); color: var(--warn); }

/* status chips */
.st { font-size: 12px; padding: 1px 8px; border-radius: 6px; white-space: nowrap; }
.st-DRAFT, .st-READY { background: var(--panel-2); color: var(--muted); }
.st-QUEUED, .st-GENERATING { background: var(--info-soft); color: var(--info); }
.st-REVIEW { background: var(--warn-soft); color: var(--warn); }
.st-APPROVED { background: var(--ok-soft); color: var(--ok); }
.st-REJECTED, .st-FAILED { background: var(--bad-soft); color: var(--bad); }

/* storyboard table */
table.board { width: 100%; border-collapse: collapse; font-size: 13px; }
.board th { text-align: left; color: var(--muted); font-weight: 500; padding: 8px; border-bottom: 1px solid var(--line); position: sticky; top: 0; background: var(--panel); }
.board td { padding: 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
.board td.num { color: var(--muted); width: 44px; }
.board .dlg { color: var(--accent); }

/* progress */
.task-progress { margin-bottom: 20px; overflow-wrap: anywhere; }
.task-progress li { margin: 8px 0; }
.factory-entry.current-work { border-color: #6c9fec; box-shadow: inset 3px 0 #6c9fec; }
.task-pulse { height: 7px; border-radius: 8px; background: linear-gradient(90deg, var(--panel-2), #6694f2, #a18bee, var(--panel-2)); background-size: 200% 100%; animation: task-pulse 2s linear infinite; }
@keyframes task-pulse { to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .task-pulse { animation: none; } }
.progress { display: flex; height: 12px; border-radius: 99px; overflow: hidden; background: var(--panel-2); }
.progress > div { height: 100%; }
.legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12px; color: var(--muted); }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: 3px; margin-right: 5px; vertical-align: -1px; }
.dots { display: flex; flex-wrap: wrap; gap: 6px; }
.dot { width: 34px; height: 26px; border-radius: 6px; display: grid; place-items: center; font-size: 11px; }

.steps-guide { counter-reset: g; display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
.steps-guide li { counter-increment: g; display: grid; grid-template-columns: 28px 1fr; gap: 10px; align-items: start; }
.steps-guide li::before { content: counter(g); width: 24px; height: 24px; border-radius: 50%; background: var(--accent-soft); color: var(--accent); display: grid; place-items: center; font-weight: 700; font-size: 12px; }
code, .code { font-family: Consolas, "Cascadia Mono", monospace; background: var(--panel-2); border-radius: 5px; padding: 1px 6px; font-size: 12px; }

/* review grid */
.review-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 14px; }
.shot { background: var(--panel); border: 2px solid var(--line); border-radius: var(--radius); overflow: hidden; cursor: pointer; position: relative; display: flex; flex-direction: column; }
.shot img { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; display: block; background: var(--panel-2); }
.shot .meta { padding: 8px 10px; display: grid; gap: 4px; font-size: 12px; }
.shot .cap { color: var(--muted); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.shot.pass { border-color: var(--ok); }
.shot.reject { border-color: var(--bad); }
.shot .mark { position: absolute; top: 8px; right: 8px; font-size: 12px; font-weight: 700; padding: 2px 9px; border-radius: 99px; color: #fff; background: var(--ok); }
.shot.reject .mark { background: var(--bad); }
.shot.reject img { filter: grayscale(.7) opacity(.75); }
.shot .zoom { position: absolute; top: 8px; left: 8px; font-size: 12px; padding: 2px 8px; border-radius: 99px; background: rgba(0,0,0,.55); color: #fff; border: 0; cursor: zoom-in; }
.shot textarea { min-height: 54px; font-size: 12px; margin-top: 4px; }
.footer-bar { position: fixed; left: 210px; right: 0; bottom: 0; padding: 12px 28px; background: var(--panel); border-top: 1px solid var(--line); display: flex; gap: 14px; align-items: center; z-index: 4; }

/* export */
.export-preview { max-height: 70vh; overflow: auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel-2); text-align: center; }
.export-preview img { width: 360px; max-width: 100%; display: block; margin: 0 auto; }
table.stats { width: 100%; border-collapse: collapse; font-size: 13px; }
.stats th, .stats td { padding: 7px 8px; border-bottom: 1px solid var(--line); text-align: right; }
.stats th:first-child, .stats td:first-child { text-align: left; }
.stats th { color: var(--muted); font-weight: 500; }

/* welcome */
.welcome { max-width: 920px; margin: 0 auto; padding: 48px 24px; display: grid; gap: 22px; }
.welcome h1 { font-size: 26px; }
.recent { display: grid; gap: 6px; }
.recent button { text-align: left; }

/* modal, toast, lightbox */
.overlay { position: fixed; inset: 0; background: rgba(0,0,0,.45); display: grid; place-items: center; z-index: 20; padding: 20px; }
.modal { background: var(--panel); border-radius: 14px; width: min(640px, 100%); max-height: 90vh; overflow: auto; padding: 22px; display: grid; gap: 14px; box-shadow: 0 20px 60px rgba(0,0,0,.3); }
.lightbox img { max-width: 92vw; max-height: 90vh; border-radius: 8px; }
.toasts { position: fixed; right: 18px; bottom: 18px; display: grid; gap: 8px; z-index: 30; max-width: 420px; }
.toast { background: var(--ink); color: var(--bg); padding: 10px 14px; border-radius: 10px; box-shadow: var(--shadow); white-space: pre-wrap; }
.toast.err { background: var(--bad); color: #fff; }
/* 新版本提示 (ui.js): a bar at the top until the page is reloaded */
.web-updated { position: fixed; top: 8px; left: 50%; transform: translateX(-50%); z-index: 1000; display: flex; gap: 12px;
  align-items: center; flex-wrap: wrap; max-width: calc(100vw - 32px); padding: 10px 14px; border-radius: 10px;
  background: var(--ink); color: var(--bg); box-shadow: var(--shadow); }
.busy { display: flex; gap: 10px; align-items: center; padding: 10px 14px; border-radius: 10px; background: var(--info-soft); color: var(--info); margin-bottom: 14px; }
.spinner { width: 16px; height: 16px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip { font-size: 12px; background: var(--panel-2); border-radius: 6px; padding: 2px 8px; }
.empty { text-align: center; padding: 40px; color: var(--muted); }

/* desktop batch view */
.seg { display: inline-flex; border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.seg button { border: 0; background: var(--panel); padding: 8px 14px; cursor: pointer; display: grid; line-height: 1.3; }
.seg button small { font-size: 11px; color: var(--muted); }
.seg button + button { border-left: 1px solid var(--line); }
.seg button.on { background: var(--accent); color: #fff; }
.seg button.on small { color: #fff; opacity: .85; }
.seg button:disabled { opacity: .45; cursor: not-allowed; }
.prompt-box { white-space: pre-wrap; background: var(--panel-2); border-radius: 8px; padding: 12px; max-height: 320px; overflow: auto; font-size: 12px; margin: 0; }
.dropzone { border: 2px dashed var(--line); border-radius: 10px; padding: 18px; text-align: center; color: var(--muted); }
.dropzone.over { border-color: var(--accent); background: var(--accent-soft); color: var(--ink); }
.cut-editor { display: grid; grid-template-columns: minmax(0, 360px) 1fr; gap: 16px; align-items: start; }
.cut-wrap { position: relative; border-radius: 8px; overflow: hidden; background: var(--panel-2); }
.cut-wrap img { display: block; width: 100%; height: auto; }
.cut-wrap svg { position: absolute; inset: 0; width: 100%; height: 100%; touch-action: none; }
.cutline { stroke: #ff2d2d; stroke-width: 2; pointer-events: none; }
.cuthit { stroke: transparent; stroke-width: 18; cursor: grab; }
.cut-wrap line[data-axis="x"].cuthit { cursor: ew-resize; }
.cut-wrap line[data-axis="y"].cuthit { cursor: ns-resize; }

.chip-btn { border: 0; cursor: pointer; font: inherit; color: inherit; }
.chip-btn:hover { background: var(--accent-soft); color: var(--accent); }
.video-preview { width: 100%; max-height: 70vh; background: #000; border-radius: 8px; }
/* Global factory entry: independent of the comic editor. */
.global-main { max-width: 1400px; margin: 0 auto; padding: 28px; }
.topbar { background: #1c2028; box-shadow: 0 1px 0 rgba(128,151,189,.06); }
.brand { letter-spacing: .5px; }
.brand::before { content: ''; width: 8px; height: 22px; border-radius: 3px; background: linear-gradient(180deg,#78acff,#9c7cea); }
.topbar .btn { background: transparent; border-radius: 5px; }
.btn, .factory-entry { transition: border-color .16s, background-color .16s, box-shadow .16s; }
.btn:hover { background-color: var(--panel-2); }
.btn.primary { background: linear-gradient(115deg,#2868bc,#6854b5); border-color: #688acb; }
.factory-start .factory-entry { position: relative; overflow: hidden; background: linear-gradient(145deg,#242d3b,#20252e 70%); border-top: 2px solid #6c9fec; }
.factory-start .factory-entry:nth-child(2) { border-top-color: #a18bee; }
.factory-start .factory-entry:nth-child(3) { border-top-color: #6abfba; }
.factory-entry:hover { box-shadow: 0 6px 22px rgba(0,0,0,.25), inset 0 0 0 1px rgba(122,165,236,.16); }
.factory-summary .card { box-shadow: none; background: #1c222b; }
.factory-summary b { color: #a9c7f5; font-variant-numeric: tabular-nums; }
input[type=text], input[type=number], input[type=password], input[type=search], input[type=email], input[type=url], textarea, select { background: #181e27; border-radius: 5px; }
.toast { background: #293649; color: var(--ink); border: 1px solid #536681; }
.toast.err { background: var(--bad-soft); color: var(--bad); border-color: #87505a; }
.step.done .n, .shot .mark { color: #12261b; }
@media (max-width: 600px) { .global-main { padding: 18px 14px; } .topbar { gap: 8px; padding: 0 12px; } }
.factory-three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
@media (max-width: 900px) { .factory-three { grid-template-columns: 1fr; } }

.brand-logo { display: block; border-radius: 8px; flex-shrink: 0; }
.brand:has(.brand-logo)::before { display: none; }
.portal-brand { display: flex; align-items: center; gap: 14px; }

/* Huimu / unfolded canvas identity */
.topbar { height: auto; min-height: 88px; padding: 12px 26px; gap: 22px; background: #191d25; }
.brand { gap: 14px; min-width: 194px; color: #fff1d6; flex-shrink: 0; }
.brand-logo { border-radius: 0; overflow: visible; }
.brand-copy { display: flex; flex-direction: column; gap: 5px; }
.brand-name { font-family: "STZhongsong", "Noto Serif SC", "Songti SC", "SimSun", serif; font-size: 34px; font-weight: 600; line-height: 1.12; letter-spacing: 5px; color: #fff1d6; }
.brand-tagline { font-family: var(--font, sans-serif); font-size: 10px; font-weight: 400; line-height: 1.4; letter-spacing: 2px; color: #a4a8b3; }
.portal-brand { gap: 20px; margin: 20px 0 36px; padding-bottom: 28px; border-bottom: 1px solid #34353f; }
.portal-brand .brand-name { font-size: 52px; letter-spacing: 8px; }
.portal-brand .brand-tagline { font-size: 12px; letter-spacing: 2px; }
@media (max-width: 640px) {
 .topbar { padding: 10px 14px; gap: 10px; flex-wrap: wrap; min-height: 78px; }
 .brand { min-width: 160px; gap: 10px; }
 .brand > .brand-logo { width: 46px; height: 46px; }
 .brand-name { font-size: 28px; }
 .brand-tagline { font-size: 9px; letter-spacing: 1px; }
 .topbar .btn { padding: 8px 10px; font-size: 12px; }
 .topbar [data-workspace-label] { width: 100%; order: 3; }
 .portal-brand > .brand-logo { width: 64px; height: 64px; }
 .portal-brand .brand-name { font-size: 40px; }
 .portal-brand .brand-tagline { font-size: 10px; }
}

.support-text { white-space: pre-wrap; overflow-wrap: anywhere; max-height: 360px; overflow: auto; line-height: 1.7; }
.support-doc summary { overflow-wrap: anywhere; }

/* Silver future identity: angular monogram, restrained cold highlight. */
.brand-name { font-family: "Microsoft YaHei", "PingFang SC", sans-serif; font-weight: 800; letter-spacing: 3px; color: #f4f7fb; }
.brand { color: #f4f7fb; }
.portal-brand .brand-name { letter-spacing: 5px; }
.brand-tagline { color: #aeb9c8; }
.brand-logo path { transform:none; transition:opacity .35s ease; }
.brand:hover .brand-logo path, .portal-brand:hover .brand-logo path { transform:none; }
.brand-logo { transition:filter .35s ease,transform .35s ease; }
.brand:hover .brand-logo, .portal-brand:hover .brand-logo { filter:drop-shadow(0 0 7px #b7e7ff33); transform:translateY(-1px); }
.brand-intro .brand-logo path { animation:none; }
.brand-intro .brand-logo .brand-core { animation: metal-reveal .85s cubic-bezier(.16,1,.3,1) both; }
.brand-intro .brand-logo .brand-edge { animation: metal-edge 1.1s ease-out both; }
.brand-intro .brand-logo .brand-signal { animation: signal-reveal .7s .3s ease-out both; }
@keyframes metal-reveal { from { opacity:0; clip-path:inset(100% 0 0); } to { opacity:1; clip-path:inset(0); } }
@keyframes metal-edge { from { opacity:0; } 45% { opacity:1; } to { opacity:.8; } }
@keyframes signal-reveal { from { opacity:0; transform:translateX(-10px); } to { opacity:1; transform:none; } }
@media (prefers-reduced-motion: reduce) { .brand-logo,.brand-logo path { animation:none!important; transition:none!important; transform:none!important; } }

.series-next{border-color:var(--accent,#7ab5ff)}
.series-previews{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.series-previews img{width:100%;height:220px;object-fit:contain;background:#13171d;border-radius:8px}@media(max-width:650px){.series-previews{grid-template-columns:repeat(2,minmax(0,1fr))}.series-previews img{height:180px}}

audio{width:100%;max-width:620px;color-scheme:dark}

.usage-panel{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:16px;padding:16px 0;border-top:1px solid var(--border,#354052);margin-top:16px}.usage-panel progress{width:100%;accent-color:#a797ff}.usage-panel p{margin:7px 0}

.factory-video{display:block;width:100%;max-height:65vh;min-height:180px;background:#080b10;border-radius:12px;margin:12px 0}

/* Paged comics (漫画): four creation entries, layout preview and exported page gallery. */
.factory-four { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
@media (max-width: 1100px) { .factory-four { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .factory-four { grid-template-columns: 1fr; } }
/* Colour follows the business, not the position: entries can be hidden by the administrator. */
.factory-start #fc-manga { border-top-color: #e3a86c; }
.factory-start #fc-images { border-top-color: #6c9fec; }
.factory-start #fc-digital { border-top-color: #a18bee; }
.factory-start #fc-comic { border-top-color: #6abfba; }
.factory-entry .tag { margin: -4px 0 8px; display: inline-block; }
.manga-options { flex-wrap: wrap; gap: 8px 18px; }
.manga-preview img { display: block; max-width: 100%; max-height: 70vh; margin: 0 auto; background: #fff; border-radius: 4px; box-shadow: 0 4px 18px rgba(0,0,0,.35); }
.manga-preview .row { flex-wrap: wrap; gap: 8px; }
.manga-pages { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.manga-pages a { display: flex; flex-direction: column; gap: 4px; align-items: center; text-decoration: none; }
.manga-pages img { width: 100%; height: auto; background: #fff; border-radius: 3px; box-shadow: 0 2px 10px rgba(0,0,0,.3); }

/* Back office points table: compact recharge inputs. */
form[data-recharge] { flex-wrap: nowrap; gap: 8px; }
form[data-recharge] input[name=amount] { width: 120px; }
form[data-recharge] input[name=note] { width: 220px; }
[data-section="dashboard"] progress { width: 100%; height: 12px; accent-color: #6c9fec; }
#dash-days { width: auto; }

/* Sign-in / sign-up (frontend/src/auth/AuthPanel.jsx): one centred card, one form; errors stay by what they are about. */
.auth-wrap { display: flex; justify-content: center; padding: 24px 0; }
.auth-card { width: 100%; max-width: 440px; min-width: 0; box-sizing: border-box; overflow-wrap: anywhere; }
.auth-card .auth-title { margin: 0; }
.auth-switch { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; padding: 4px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); }
.auth-switch button { border: 0; border-radius: 7px; padding: 8px 0; background: transparent; color: var(--muted); font: inherit; font-weight: 600; cursor: pointer; }
.auth-switch button[aria-pressed="true"] { background: var(--panel); color: var(--ink); box-shadow: 0 1px 3px rgba(0, 0, 0, .25); }
.auth-bonus { margin: 0; }
.auth-form { min-width: 0; }
.auth-field { display: grid; gap: 4px; min-width: 0; }
.auth-field > label { font-size: 12px; color: var(--muted); }
.auth-input { position: relative; min-width: 0; }
.auth-input input { box-sizing: border-box; width: 100%; }
.auth-input input.auth-secret { padding-right: 40px; }
.auth-eye { position: absolute; top: calc(50% - 16px); right: 4px; display: grid; place-items: center; width: 32px; height: 32px; border: 0; border-radius: 6px; background: transparent; color: var(--muted); cursor: pointer; }
.auth-eye:hover, .auth-eye[aria-pressed="true"] { color: var(--ink); }
.auth-eye:focus-visible, .auth-switch button:focus-visible, .auth-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.auth-code { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: center; }
.auth-send { min-width: 104px; }
.auth-note { margin: 0; min-height: 0; }
.auth-note:empty { display: none; }
.auth-error { margin: 0; color: var(--bad); font-size: 13px; }
.auth-ok { margin: 0; padding: 8px 10px; border-radius: 8px; background: var(--ok-soft); color: var(--ok); }
.auth-agree { display: flex; gap: 6px; align-items: flex-start; font-size: 13px; }
.auth-agree input { width: auto; margin-top: 3px; }
.auth-submit { width: 100%; padding: 10px 14px; }
.auth-tip { font-size: 12px; color: var(--muted); }
.auth-tip > summary { cursor: pointer; width: max-content; }
.auth-tip > p { margin: 4px 0 0; }
.auth-more p { margin: 4px 0; }
.auth-link { border: 0; padding: 0; background: none; color: var(--accent); font: inherit; font-weight: 600; cursor: pointer; }
.auth-link:hover { text-decoration: underline; }
@media (max-width: 480px) {
  .auth-wrap { padding: 12px 0; }
  .auth-card { padding: 14px; }
}

/* Back-office status line: floats at the top of the screen so a save far down the page is always acknowledged. */
#message:not(:empty) {
  position: fixed; top: 14px; left: 50%; transform: translateX(-50%); z-index: 1000;
  max-width: min(760px, calc(100vw - 32px)); margin: 0; padding: 10px 16px; border-radius: var(--radius);
  background: var(--panel-2); color: var(--ink); border: 1px solid var(--accent); box-shadow: var(--shadow);
}

/* ---- Design system (docs/DESIGN_SYSTEM.md): one main task and one main button per screen ---- */
:root {
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 24px; --space-6: 32px; --space-7: 48px;
  --text-xs: 12px; --text-sm: 13px; --text-md: 14px; --text-lg: 16px; --text-xl: 20px; --text-2xl: 28px; --text-3xl: 40px;
  --radius-sm: 6px; --radius-lg: 16px; --radius-pill: 999px;
  --danger: #e5737d; --danger-soft: #3e2429; --success: var(--ok); --success-soft: var(--ok-soft);
  --focus: #8dbdff;
}
/* Destructive actions are outlined red, never the main (filled) button of a screen. */
.btn.danger { color: var(--danger); border-color: #7a3b43; background: transparent; }
.btn.danger:hover { background: var(--danger-soft); border-color: var(--danger); }
.btn.secondary { background: var(--panel-2); }
.btn.link { border: 0; background: transparent; padding: 0; color: var(--info); text-decoration: underline; text-underline-offset: 3px; }
.btn.xl { padding: 14px 28px; font-size: var(--text-lg); border-radius: 12px; }
/* Empty state: what is missing and the one thing to do about it. */
.empty-state { display: grid; justify-items: center; gap: var(--space-3); padding: var(--space-6) var(--space-4); text-align: center; color: var(--muted); }
.empty-state b { color: var(--ink); font-size: var(--text-lg); }
/* Loading */
.spinner { width: 18px; height: 18px; border: 2px solid var(--line); border-top-color: var(--info); border-radius: 50%; display: inline-block; animation: spin .9s linear infinite; vertical-align: middle; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation: none; } }
/* Status badges */
.badge { display: inline-block; font-size: var(--text-xs); padding: 1px 8px; border-radius: var(--radius-pill); background: var(--panel-2); color: var(--muted); }
.badge.ok { background: var(--ok-soft); color: var(--ok); } .badge.warn { background: var(--warn-soft); color: var(--warn); }
.badge.bad { background: var(--danger-soft); color: var(--danger); } .badge.info { background: var(--info-soft); color: var(--info); }
/* Choice cards (wizard steps, type pickers): the whole card is the control. */
.choices { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--space-3); }
.choice { text-align: left; border: 1px solid var(--line); background: var(--panel); border-radius: 12px; padding: var(--space-4); cursor: pointer; color: var(--ink); display: grid; gap: var(--space-1); }
.choice:hover { border-color: var(--muted); }
.choice[aria-pressed="true"] { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent) inset; background: var(--accent-soft); }
.choice b { font-size: var(--text-lg); } .choice span { color: var(--muted); font-size: var(--text-sm); }
/* Progress steps: ✓ done, ● now, ○ later. */
/* Only ol.steps: the workbench's tab bar (div.steps > button.step) keeps its own style. */
ol.steps { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); align-items: center; list-style: none; padding: 0; margin: 0; border: 0; }
ol.steps li { color: var(--muted); } ol.steps li.done { color: var(--ok); } ol.steps li.now { color: var(--ink); font-weight: 600; }
ol.steps li + li::before { content: "→"; color: var(--line); margin-right: var(--space-4); }

/* ---- Guided mode (web/guided.js, v4 §41-62): one idea box, one main button, the next step always visible ---- */
.guided { max-width: 1080px; display: grid; gap: var(--space-5); align-content: start; }
.guided h1 { font-size: var(--text-2xl); }
.guided-hero { gap: var(--space-4); padding: var(--space-6); }
.guided-hero h1 { font-size: var(--text-3xl); }
.guided-hero textarea { font-size: var(--text-lg); min-height: 96px; }
.guided-kinds .btn { border-color: var(--line); }
.guided-works { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--space-3); }
.guided-work { display: grid; gap: var(--space-2); text-align: left; cursor: pointer; color: var(--ink); }
.guided-work:hover, .guided-thumb:hover { border-color: var(--accent); }
.guided-running { border-color: var(--info); }
.guided-onboarding { border-color: var(--accent); }
.guided-wizard { gap: var(--space-4); }
.guided-wizard h1:focus { outline: none; }
.guided-nav { border-top: 1px solid var(--line); padding-top: var(--space-4); }
.guided-summary { display: grid; gap: var(--space-2); margin: 0; }
.guided-summary div { display: grid; grid-template-columns: 88px 1fr; gap: var(--space-3); }
.guided-summary dt { color: var(--muted); }
.guided-summary dd { margin: 0; overflow-wrap: anywhere; }
.guided-cost { font-size: var(--text-lg); margin: 0; }
.warn-text { color: var(--warn); }
.guided-auto summary, .guided-wizard details summary { cursor: pointer; }
.guided-auto ul { margin: var(--space-3) 0; padding-left: 20px; }
.guided-head h1 { overflow-wrap: anywhere; }
.guided-steps { font-size: var(--text-lg); }
.guided-stages { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-2); }
.guided-stages li { color: var(--muted); } .guided-stages li.done { color: var(--ok); } .guided-stages li.now { color: var(--ink); font-weight: 600; }
.guided-next { border-color: var(--accent); }
.guided-next-title { font-size: var(--text-xl); }
.guided-next p, .guided-error p { margin: 0; }
/* The finished states (导出 / 下载 / 播放): one 48–72px bar — state, info icon, one main button and a small 更多 whose
   groups (other downloads, export again / 修改作品, sharing and submission) open on their own full-width line */
.guided-next-bar { padding-top: 8px; padding-bottom: 8px; gap: 6px; }
.guided-next-bar .next-bar { flex-wrap: wrap; align-items: center; gap: 6px 10px; min-height: 32px; }
.guided-next-bar .guided-next-title { font-size: var(--text-lg); }
.guided-next-bar .next-bar > .btn { padding-top: 6px; padding-bottom: 6px; white-space: nowrap; }
.guided-next-bar .next-more > summary { cursor: pointer; white-space: nowrap; }
.guided-next-bar .next-more[open] { flex: 1 1 100%; }
.guided-next-bar .next-more > .stack { margin-top: var(--space-2); }
.guided-next-bar .next-group > .row { flex-wrap: wrap; gap: 6px; }
.guided-error { border-color: var(--warn); }
.guided-locked { border-color: var(--warn); }
.guided-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--space-3); }
.guided-unit { gap: var(--space-2); padding: var(--space-3); }
.guided-unit.marked { border-color: var(--danger); }
.guided-unit p { margin: 0; overflow-wrap: anywhere; }
.guided-thumb { display: block; padding: 0; border: 1px solid transparent; border-radius: var(--radius-sm); background: var(--panel-2); cursor: zoom-in; }
.guided-thumb img { display: block; width: 100%; height: 240px; object-fit: contain; border-radius: var(--radius-sm); }
/* 免费修手: original and repaired side by side */
.guided-fix { border-top: 1px solid var(--line, #ddd); padding-top: 8px; }
.guided-repair-tool { display: grid; grid-template-columns: auto 1fr; gap: 2px 6px; align-items: start; }
.guided-repair-tool .muted { grid-column: 2; }
.guided-fix-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.guided-fix-pair img { display: block; width: 100%; height: 160px; object-fit: contain; background: var(--panel-2); border-radius: var(--radius-sm); }
.guided-fix-pair .guided-thumb img { height: 160px; }
/* Character sheets on the work page */
.guided-masters { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; }
.guided-master { margin: 0; display: flex; flex-direction: column; gap: 6px; }
.guided-master img { display: block; width: 100%; height: 260px; object-fit: contain; border-radius: var(--radius-sm); background: var(--panel-2); }
.guided-master figcaption { display: flex; flex-direction: column; gap: 4px; }
.guided-master textarea, #gd-image-notes, #fc-image-notes { width: 100%; box-sizing: border-box; }
.guided-master figcaption .row { flex-wrap: wrap; gap: 6px; }
.guided-actions .btn { flex: 1; padding: 6px 8px; }
.guided-actions .btn[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
.guided-actions .btn[data-gd-redo][aria-pressed="true"], .guided-actions .btn[data-gd-edit][aria-pressed="true"] { border-color: var(--danger); background: var(--danger-soft); }
.guided-unit textarea { min-height: 64px; }
/* 给作品起名 / 改名: the name as a title */
.guided-name { border-color: var(--accent); gap: var(--space-2); }
.guided-name label b { font-size: var(--text-lg, 1.1rem); }
.guided-name-input { font-size: var(--text-2xl, 1.5rem); font-weight: 700; padding: 10px 14px; width: 100%; box-sizing: border-box; }
.guided-rename .guided-name-input, .guided-name .row .guided-name-input { flex: 1 1 260px; min-width: 0; width: auto; }
/* 按页审核的成品图: clear buttons over each balloon / narration box (点气泡改字) */
.page-view { position: relative; display: block; border-radius: var(--radius-sm); overflow: hidden; background: var(--panel-2); }
.page-view img { display: block; width: 100%; height: auto; cursor: zoom-in; }
.page-edit-float, .page-edit-float:hover { position: absolute; top: 4px; right: 4px; z-index: 3; display: grid; place-items: center; width: 40px; min-width: 40px; height: 40px; min-height: 40px; padding: 0; color: #fff; background: transparent; border: 0; border-radius: 50%; box-shadow: none; cursor: pointer; }
.page-edit-symbol { display: grid; place-items: center; width: 30px; height: 30px; font-size: 19px; line-height: 1; background: rgba(24, 32, 46, .58); border: 1px solid #ffffff70; border-radius: 50%; box-shadow: 0 1px 4px #0003; pointer-events: none; }
.page-edit-label { position: absolute; top: 100%; right: 3px; padding: 3px 7px; border-radius: 4px; background: #18202ee6; color: #fff; font-size: 12px; white-space: nowrap; opacity: 0; visibility: hidden; pointer-events: none; }
.page-edit-float:hover .page-edit-label, .page-edit-float:focus-visible .page-edit-label { opacity: 1; visibility: visible; }
.page-edit-float:focus-visible { outline: 3px solid var(--accent); outline-offset: -3px; }
@media (pointer: coarse) { .page-edit-float, .page-edit-float:hover { width: 44px; min-width: 44px; height: 44px; min-height: 44px; } }
.page-edit-hint { text-align: center; }
.generation-service { position: static; padding: 10px 14px; border: 1px solid var(--border); border-left: 3px solid #dca746; border-radius: 8px; background: var(--panel); }
.generation-service summary { cursor: pointer; }
.generation-service p { margin: 9px 0; }
.page-spot { position: absolute; padding: 0; border: 2px dashed transparent; border-radius: 40%; background: transparent; cursor: text; }
.page-spot:hover, .page-spot:focus-visible { border-color: var(--accent); background: rgba(80, 140, 255, .12); }
.page-spot.on { border-color: var(--accent); border-style: solid; }
.guided-grid:has(.guided-page-card) { grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); align-items: start; }
.guided-page-card:not(.is-editing) .page-view { width: 100%; max-width: 240px; margin-inline: auto; }
.guided-bookend:has(details[open]) { grid-column: 1 / -1; }
/* 封面与末页 gallery (client/BookendGallery.jsx): small pictures in one row, the reading pages' corner pencil */
.bookend-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 168px)); gap: var(--space-3); align-items: start; }
.bookend-tile { margin: 0; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.bookend-tile .page-view img { width: 100%; height: 220px; object-fit: contain; }
.bookend-tile figcaption { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; }
.bookend-gallery[aria-busy="true"] { opacity: .75; }
.bookend-gallery-note { margin: 0; }
@media (max-width: 600px) {
  .bookend-gallery { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2); }
  .bookend-tile .page-view img { height: 140px; }
}
/* 按页审核: one card a page, the page picture whole (2:3) */
.guided-page-card .guided-thumb img, .guided-page-card .factory-placeholder { height: auto; aspect-ratio: 2 / 3; width: 100%; }
.guided-page-card .factory-placeholder { display: grid; place-items: center; }
.guided-page-panel { border-top: 1px solid var(--line); padding-top: var(--space-2); display: flex; flex-direction: column; gap: 4px; }
/* 编辑这一页: one box per panel, every field full width */
.guided-page-editor-panel { margin: 0; min-width: 0; }
.guided-page-editor textarea { width: 100%; resize: vertical; }
.guided-page-editor .row label { display: inline-flex; align-items: center; gap: 4px; }
/* The page being edited takes the whole row: the page beside its editor, the page kept in sight below the top bar */
.guided-page-card.is-editing { grid-column: 1 / -1; }
.guided-page-split { display: grid; grid-template-columns: minmax(260px, 400px) minmax(0, 1fr); gap: var(--space-4); align-items: start; }
.guided-page-split > .stack:first-child { position: sticky; top: 100px; }
/* The creation pages scroll the window: their main must not be a scroll box of its own (.main's overflow: auto made it
   one, and nothing inside could stick — e.g. the page beside its editor). Clipped sideways only. */
#app > .global-main, .global-main:has(> #portal) { overflow-x: clip; overflow-y: visible; }
@media (max-width: 760px) { .guided-page-split { grid-template-columns: 1fr; } .guided-page-split > .stack:first-child { position: static; } }
.guided-actions .btn[data-gd-page-redo][aria-pressed="true"], .guided-actions .btn[data-gd-page-edit][aria-pressed="true"] { border-color: var(--danger); background: var(--danger-soft); }
.guided-board { margin: var(--space-3) 0 0; padding-left: 20px; display: grid; gap: var(--space-1); }
@media (max-width: 600px) {
  .guided-hero { padding: var(--space-4); }
  .guided-hero h1 { font-size: var(--text-2xl); }
  .guided h1 { font-size: var(--text-xl); }
  .guided-thumb img { height: 200px; }
  .guided-grid, .guided-works { grid-template-columns: 1fr; }
  .guided-top .muted.small { display: none; }
}
/* Public product page for visitors (portal_web/portal.js landing, v4 §9) */
.landing { max-width: 960px; margin: 0 auto; gap: var(--space-5); }
/* 登录 sits on the brand's line at the right (it had a line of its own above the headline); the brand is 48px from the
   top of .global-main (28px padding + 20px margin) and 80px tall, 38px / 64px on phones */
.global-main:has(> #portal) { position: relative; }
.landing > .landing-login { position: absolute; top: 68px; right: 28px; }
.landing-title { font-size: var(--text-3xl); line-height: 1.25; text-wrap: balance; }
.landing-sub { font-size: var(--text-lg); margin: 0; }
.landing textarea { font-size: var(--text-lg); min-height: 96px; }
.landing-flow { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3); }
@media (max-width: 800px) { .landing-flow { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 600px) { .landing > .landing-login { top: 50px; right: 14px; } }
@media (max-width: 480px) { .landing-flow .card { padding: 12px 14px; } .landing-title { font-size: var(--text-2xl); } }
/* Below the work page's sticky tab strip */
#fc-script, #fc-review-heading, #fc-export, #gd-export, #gd-edit-work, #gd-masters, #gd-story { scroll-margin-top: 56px; }
/* Cost dashboard (portal_web/costs.js, administrator only) */
.cost-cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3); margin-bottom: var(--space-4); }
.cost-big { font-size: var(--text-2xl); }
.cost-controls { margin-bottom: var(--space-4); }
.cost-controls input[type=date] { width: auto; }
#costs-body table.stats, .cost-modal table.stats { display: block; overflow-x: auto; max-width: 100%; }
.cost-bar-cell { width: 28%; min-width: 80px; }
.cost-bar { display: block; height: 10px; border-radius: var(--radius-pill); background: linear-gradient(90deg, #2868bc, #6854b5); min-width: 2px; }
.cost-runs .chip { display: inline-block; margin: 2px 0; }
.cost-modal { width: min(1200px, 100%); }
#cost-fixed input { min-width: 90px; }
@media (max-width: 1000px) { .cost-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .cost-cards { grid-template-columns: 1fr; } }
/* Guided import (novel / script) and whole works */
.guided-source { margin-bottom: var(--space-2); }
.guided-preview { border-color: var(--accent); }
.guided-chapters { margin: 0; padding-left: 20px; display: grid; gap: 2px; max-height: 280px; overflow: auto; }
.guided-chapters-choice { margin-top: var(--space-2); }
/* Guided style step: the exact look inside a family */
.guided-substyles { border-top: 1px solid var(--line); padding-top: var(--space-4); }
.guided-substyles h3 { margin: 0; font-size: var(--text-lg); }
.choices.compact { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: var(--space-2); }
.choices.compact .choice { padding: var(--space-3); }
.choices.compact .choice b { font-size: var(--text-md); }

/* Searchable style chooser and optional image tooltip. */
.style-menu{position:relative;border:1px solid var(--border,#394553);border-radius:8px;padding:12px;background:var(--panel,#1c222c)}
.style-options{display:flex;flex-direction:column;gap:4px;max-height:330px;overflow:auto;padding-top:10px}.style-options .btn{text-align:left;white-space:normal}.style-options strong{padding:12px 4px 4px}
.style-tooltip{position:fixed;z-index:99999;pointer-events:none;background:#141a23;border:1px solid #7789a8;box-shadow:0 8px 32px #0009;padding:6px;border-radius:10px;width:260px}.style-tooltip img{display:block;width:100%;max-height:340px;object-fit:contain}
.legal-text { max-height: none; }

/* 帮助 · 用户反馈 · 关于 · 协议 on every portal page */
.site-footer { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 18px; margin: 32px 0 12px; font-size: 13px; }
.site-footer a { color: var(--muted); }

/* 修改作品: the first page of the chosen layout */
.gd-layout-preview { width: 100%; max-width: 320px; border-radius: 8px; border: 1px solid var(--line); }

/* 用户反馈 screenshots */
.report-shot { width: 96px; height: 96px; object-fit: cover; border-radius: 6px; border: 1px solid var(--line); }

/* 排版样式面板 (typeset.js): three small groups, chips that stay where they are */
.ts-panel { display: grid; gap: 10px; }
.ts-group { border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; display: grid; gap: 6px; }
.ts-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.ts-row > span { min-width: 3.5em; }
.ts-chips { display: flex; flex-wrap: wrap; gap: 4px; }

/* 按钮反馈 (app.js btnBusy / portal.js portalBusy): pressed at once, a spinner until the answer is in */
button:active:not(:disabled), .btn:active { transform: translateY(1px); }
.btn.is-busy, button.is-busy { position: relative; opacity: 1; cursor: progress; transform: translateY(1px);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, .35); filter: saturate(.85); }
.btn.is-busy::before, button.is-busy::before { content: ""; display: inline-block; width: 1em; height: 1em;
  margin-right: .45em; vertical-align: -.15em; border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; animation: btn-spin .7s linear infinite; }
@keyframes btn-spin { to { transform: rotate(360deg); } }
/* 操作即时反馈 (ui.js): a thin bar at the top while a request someone started is on its way */
#net-progress { position: fixed; top: 0; left: 0; right: 0; z-index: 2000; height: 3px; pointer-events: none; opacity: 0;
  background: linear-gradient(90deg, transparent 0, var(--info) 30%, #b9a7ff 60%, transparent 100%); background-size: 40% 100%;
  background-repeat: no-repeat; transition: opacity .15s; }
#net-progress.on { opacity: 1; animation: net-run 1.1s ease-in-out infinite; }
@keyframes net-run { from { background-position: -40% 0; } to { background-position: 140% 0; } }
html.net-busy, html.net-busy * { cursor: progress; }
@media (prefers-reduced-motion: reduce) { #net-progress.on { animation-duration: 3s; } }
/* 维护公告 (ui.js maintenanceNotice): one narrow line above the page, blue announced / yellow updating; its explanation
   opens under it in the flow (never over the work) and scrolls in itself when long. No animation. */
.maint-bar { position: relative; z-index: 6; border-bottom: 1px solid currentColor; font-size: var(--text-md, 14px); }
.maint-bar.maint-announce { background: var(--info-soft); color: var(--info); }
.maint-bar.maint-active { background: var(--warn-soft); color: var(--warn); }
.maint-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; width: 100%; padding: 6px 18px; border: 0;
  background: none; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.maint-line:focus-visible { outline: 2px solid var(--focus, currentColor); outline-offset: -2px; }
.maint-text { color: var(--ink); }
.maint-when { font-size: var(--text-sm, 13px); opacity: .85; }
.maint-more { margin-left: auto; font-size: var(--text-sm, 13px); text-decoration: underline; }
.maint-detail { max-height: 40vh; overflow: auto; overscroll-behavior: contain; padding: 0 18px 8px; font-size: var(--text-sm, 13px); color: var(--ink); }
.maint-detail p { margin: 0 0 6px; max-width: 72ch; }
@media (max-width: 600px) {
  .maint-line { padding: 5px 12px; font-size: var(--text-sm, 13px); }
  .maint-detail { max-height: 30vh; padding: 0 12px 8px; }
}
/* What an update held back, said beside the button that asked (app.js maintenanceHeld); gone when the update ends. */
.maint-near { display: inline-block; margin: 4px 8px; padding: 2px 8px; border-radius: var(--radius-sm, 6px);
  background: var(--warn-soft); color: var(--warn); font-size: var(--text-sm, 13px); }
/* 涂抹消除 (factory.js openEraser) */
.eraser-overlay { position: fixed; inset: 0; z-index: 1000; background: rgba(0, 0, 0, .65); display: flex; align-items: center; justify-content: center; padding: 12px; }
.eraser-box { background: var(--panel); border-radius: 12px; padding: 14px; max-width: 96vw; max-height: 96vh; overflow: auto; }
.eraser-stage { position: relative; align-self: center; line-height: 0; }
.eraser-stage img { display: block; max-width: min(90vw, 900px); max-height: 68vh; user-select: none; }
.eraser-stage canvas { position: absolute; inset: 0; width: 100%; height: 100%; touch-action: none; cursor: crosshair; }
.retouch-panel { border: 1px dashed var(--line); border-radius: 8px; padding: 8px 10px; }
.retouch-panel label { display: flex; gap: 8px; align-items: center; }
.retouch-panel input[type="range"] { flex: 1; }
/* 预览加载中 (factory.js showPreview): the old page dims under a spinner until the new one has arrived */
.preview-frame { position: relative; display: block; min-height: 120px; }
.preview-frame > img { display: block; max-width: 100%; transition: opacity .15s; }
.preview-frame.preview-loading > img { opacity: .35; }
.preview-frame.preview-loading::after { content: "正在排版…"; position: absolute; left: 50%; top: 40%; transform: translate(-50%, -50%);
  padding: 8px 14px 8px 36px; border-radius: 999px; background: rgba(0, 0, 0, .65); color: #fff; font-size: 14px; white-space: nowrap; }
.preview-frame.preview-loading::before { content: ""; position: absolute; left: 50%; top: 40%; z-index: 1; width: 16px; height: 16px;
  margin: -8px 0 0 -62px; border: 2px solid #fff; border-right-color: transparent; border-radius: 50%; animation: btn-spin .7s linear infinite; }
@media (prefers-reduced-motion: reduce) { .btn.is-busy::before, button.is-busy::before { animation-duration: 2s; } }
/* 作品分享页: the reading link of a finished work */
.share-box { border: 1px dashed var(--line); border-radius: 8px; padding: 8px 10px; }
.share-box input[readonly] { width: 100%; box-sizing: border-box; }

/* 气泡语气: one row per balloon of the page shown */
.tone-row { justify-content: space-between; gap: 8px; }
.tone-line { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Long back-office lists (画风模块 / 画风管理): a toolbar, folded groups with a clear header, one line per entry */
.list-tools { flex-wrap: wrap; gap: 8px; }
.list-tools input[type="search"] { flex: 1 1 260px; min-width: 0; }
a.btn { text-decoration: none; color: inherit; display: inline-flex; align-items: center; }
a.btn.link { text-decoration: underline; color: var(--info); }
.name-row { flex-wrap: nowrap; gap: 8px; }
.name-row input { flex: 1 1 auto; min-width: 0; }
.list-tools { align-items: center; }
.list-tools select { width: auto; flex: 0 0 auto; max-width: 100%; }
.list-tools input[type="search"] { width: auto; }
.list-tools .list-count { margin-left: auto; }
.list-busy { opacity: .55; transition: opacity .15s; pointer-events: none; }
.notice-line.notice-bad { background: var(--bad-soft); border-left-color: var(--bad); }
/* One compact row per record (作品管理, React): what it is on the left, its actions on the right. */
.work-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; padding: 12px 14px; box-shadow: none; }
.work-row:hover { border-color: #4a5d7a; }
.work-row .work-main { flex: 1 1 380px; min-width: 0; display: grid; gap: 4px; }
.work-row .work-main > .row { gap: 8px; align-items: center; flex-wrap: wrap; }
.work-row .work-main p { margin: 0; }
.work-row .work-name { font-size: 15px; }
.work-row .work-actions { gap: 6px; flex-wrap: wrap; }
.work-row .work-actions .btn { padding: 5px 11px; font-size: 13px; }
.work-row .rename-box { flex-basis: 100%; gap: 8px; flex-wrap: wrap; padding-top: 10px; border-top: 1px solid var(--line); }
.work-row .rename-box input { flex: 1 1 240px; min-width: 0; }
.group-box { padding: 0; overflow: clip; }
.group-box > .group-head { position: sticky; top: 0; z-index: 2; padding: 10px 14px; background: var(--panel-2); border-bottom: 1px solid var(--line); font-size: var(--text-lg, 1.05rem); }
.group-box[open] > .group-head { border-left: 4px solid var(--accent); }
.group-box > .stack { padding: 10px 14px 14px; }

/* Back office: a stable module rail keeps navigation visible while long editors scroll. */
.admin-shell { display:grid; grid-template-columns:208px minmax(0,1fr); gap:20px; align-items:start; margin-top:18px; }
.backoffice .portal-brand { gap:10px; margin:2px 0 18px; padding-bottom:12px; }
.backoffice .portal-brand > .brand-logo { width:40px; height:40px; }
.backoffice .portal-brand .brand-name { font-size:24px; letter-spacing:3px; }
.backoffice .portal-brand .brand-tagline { font-size:10px; letter-spacing:1px; }
.admin-page-head { position:sticky; top:0; z-index:15; margin:-6px -8px 0; padding:8px; background:rgba(23,27,34,.96); border-bottom:1px solid var(--line); backdrop-filter:blur(10px); }
.admin-page-head h1 { font-size:22px; letter-spacing:.01em; }
.admin-content { min-width:0; }
.admin-content-loading { opacity:.7; pointer-events:none; transition:opacity .15s ease; }
.admin-content-loading::before { content:"正在加载…"; position:sticky; top:66px; z-index:10; display:block; width:max-content; margin:0 auto -30px; padding:7px 14px; border:1px solid var(--line); border-radius:999px; background:var(--panel); box-shadow:0 8px 24px #0006; color:var(--ink); font-size:14px; }
.admin-opening { justify-content:center; min-height:180px; color:var(--muted); }
.admin-content > [data-section] { display:grid; gap:14px; align-content:start; }
#admin-nav-root { display:contents; }  /* the rail's React root: the rail itself is the grid item, free to stick */
.admin-nav { position:sticky; top:68px; max-height:calc(100vh - 80px); overflow:auto; padding:8px; border:1px solid var(--line); border-radius:12px; background:#1c222b; }
.admin-nav-group { display:grid; gap:3px; padding:7px 0 11px; border-bottom:1px solid var(--line); }
.admin-nav-group:last-child { border-bottom:0; }
.admin-nav-group > b { padding:2px 9px 5px; color:var(--muted); font-size:11px; font-weight:600; letter-spacing:.1em; }
.admin-nav .btn { width:100%; text-align:left; border-color:transparent; background:transparent; padding:7px 10px; white-space:normal; }
.admin-nav .btn:hover { background:var(--panel-2); color:#fff; }
.admin-nav .btn.primary { background:var(--accent-soft); border-color:#40618c; color:#dceeff; box-shadow:inset 3px 0 #75adff; }
.admin-content > [data-section] > .card { box-shadow:none; }
/* 保存不用翻到底 (user 2026-10-05): any back-office form's last row with its main button stays at the bottom of the
   screen while the form is in view. */
.admin-content form > .row:last-child:has(> .btn.primary, > button.primary) { position:sticky; bottom:0; z-index:5; padding:10px 0; background:var(--panel); border-top:1px solid var(--line); }
/* 折叠卡片的边界 (user 2026-10-05: "都不知道分来的边界在哪"): a clear header row with an arrow, the open one marked. */
.admin-content details.card:not(.group-box) > summary { list-style:none; display:flex; align-items:center; gap:8px; margin:-6px -8px; padding:6px 8px; border-radius:8px; font-weight:600; }
.admin-content details.card:not(.group-box) > summary::-webkit-details-marker { display:none; }
.admin-content details.card:not(.group-box) > summary::before { content:"▸"; color:var(--muted); transition:transform .15s; flex:none; }
.admin-content details.card:not(.group-box)[open] > summary::before { transform:rotate(90deg); color:var(--accent); }
.admin-content details.card:not(.group-box) > summary:hover { background:var(--panel-2); }
.admin-content details.card:not(.group-box)[open] { border-color:#4a5d7a; }
.admin-content details.card:not(.group-box)[open] > summary { margin-bottom:10px; padding-bottom:10px; border-bottom:1px solid var(--line); border-radius:8px 8px 0 0; }
.admin-content .ai-category-nav { position:sticky; top:58px; z-index:8; padding:8px; border:1px solid var(--line); border-radius:10px; background:#1c222b; }
.admin-content .ai-category { scroll-margin-top:132px; }
.admin-content .ai-category > summary { font-size:17px; padding:5px 0; }
.admin-content .ai-category[open] > summary { margin-bottom:12px; border-bottom:1px solid var(--line); }
.admin-content .task-row > summary { cursor:pointer; display:flex; gap:10px; align-items:center; justify-content:space-between; flex-wrap:wrap; }
.admin-content .task-row[open] > summary { margin-bottom:10px; }
.admin-content .task-row [data-note] { align-items:end; }
.admin-content .task-row [data-note] .field { flex:1 1 280px; }
@media(max-width:840px) { .admin-shell { grid-template-columns:minmax(0,1fr); gap:12px; } .admin-nav { position:sticky; top:58px; z-index:12; display:flex; gap:8px; max-height:120px; overflow:auto; } .admin-nav-group { display:flex; gap:4px; padding:0; border:0; flex:none; align-items:center; } .admin-nav-group>b { display:none; } .admin-nav .btn { width:auto; white-space:nowrap; } }
/* Wallet actions need room: at desktop widths keep a scrollable table, on narrower screens use account cards. */
.admin-content section[data-section="wallets"] table.stats { display:block; max-width:100%; overflow-x:auto; }
.admin-content [data-wallet] code { overflow-wrap:anywhere; }
.admin-content [data-topup] { display:grid; grid-template-columns:repeat(2,minmax(120px,1fr)); min-width:280px; max-width:440px; }
.admin-content [data-topup] input { min-width:0; width:100%; }
.admin-content [data-topup] button { grid-column:1/-1; justify-self:start; }
@media(max-width:1100px) {
  .admin-content section[data-section="wallets"] table.stats:has([data-wallet]) thead { display:none; }
  .admin-content section[data-section="wallets"] table.stats:has([data-wallet]) tbody { display:grid; gap:12px; }
  .admin-content [data-wallet] { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:4px 12px; padding:12px; border:1px solid var(--line); border-radius:12px; background:var(--panel); }
  .admin-content [data-wallet] td { display:block; min-width:0; padding:4px 0; border:0; text-align:left; }
  .admin-content [data-wallet] td:first-child,.admin-content [data-wallet] td:nth-child(6),.admin-content [data-wallet] td:nth-child(7) { grid-column:1/-1; }
  .admin-content [data-wallet] td:nth-child(2)::before { content:'角色 · '; color:var(--muted); }
  .admin-content [data-wallet] td:nth-child(3)::before { content:'可用 · '; color:var(--muted); }
  .admin-content [data-wallet] td:nth-child(4)::before { content:'冻结 · '; color:var(--muted); }
  .admin-content [data-wallet] td:nth-child(5)::before { content:'实收 · '; color:var(--muted); }
  .admin-content [data-topup] { max-width:none; }
}
@media(max-width:600px) { .admin-content [data-wallet] { grid-template-columns:repeat(2,minmax(0,1fr)); } .admin-content [data-topup] { min-width:0; grid-template-columns:repeat(2,minmax(0,1fr)); } }
.block-row { padding: 8px 12px; }
.block-row > summary { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; }
.block-row .block-words { flex-basis: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.block-row[open] .block-words { display: none; }
.block-row[open] { border-color: var(--accent); }
/* 画风管理: what was filled in / saved, at the top of the style being edited */
.notice-line { margin: 0 0 8px; padding: 10px 12px; border-radius: 8px; background: var(--accent-soft); border-left: 4px solid var(--accent); }
/* 图片加载中 / 加载失败 (typeset.js watchPictures): never an empty gap that looks like a missing picture */
img.img-loading { background: linear-gradient(90deg, var(--panel-2) 25%, var(--accent-soft) 50%, var(--panel-2) 75%);
  background-size: 200% 100%; animation: img-loading 1.2s linear infinite; min-height: 96px; min-width: 96px; color: transparent; }
button img.img-loading, summary img.img-loading, .brand-logo.img-loading { min-height: 0; min-width: 0; }
img.img-failed { background: var(--panel-2); outline: 1px dashed var(--line); outline-offset: -1px; min-height: 48px; }
@keyframes img-loading { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) { img.img-loading { animation: none; } }
/* 列表排序 (portal.js sortableTables): a clickable header shows which way the rows run */
th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
th.sortable::after { content: " ⇅"; color: var(--muted); font-size: .85em; }
th.sortable[data-sorted="asc"]::after { content: " ▲"; color: var(--accent); }
th.sortable[data-sorted="desc"]::after { content: " ▼"; color: var(--accent); }
/* 停止并删除: a quieter red link next to 停止生成 */
.danger-text { color: var(--bad); }
/* 发到抖音: one QR code per group of 30 pages */
.douyin-parts { gap: 16px; align-items: flex-start; }
.douyin-qr { margin: 0; text-align: center; }
.douyin-qr div { width: 168px; height: 168px; background: #fff; padding: 6px; border-radius: 8px; }
.douyin-qr svg { width: 100%; height: 100%; display: block; }
/* 扫书雷达: every row opens the book (user 2026-10-02: the text cursor made it look not clickable) */
.radar-table tr[data-radar-book] { cursor: pointer; }
.radar-table tr[data-radar-book]:hover, .radar-table tr[data-radar-book]:focus-visible { background: var(--accent-soft); outline: none; }
.radar-table tr[data-radar-book] td { user-select: none; }
.radar-table .radar-open { white-space: nowrap; pointer-events: none; }
/* 检查画风模块: the sentence, its plan, and the chosen way (按方案修正 / 保留 / 先不处理) */
.audit-row .audit-quote { margin: 0; padding: 4px 12px; border-left: 3px solid var(--line); color: var(--ink); }
.audit-row ul { margin: 0; padding-left: 20px; display: grid; gap: 4px; }
.audit-row .btn[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
.audit-row[data-audit-choice="fix"] { border-color: var(--accent); }
/* 插入剧情 (guided.js gdInsertBox): where, the words, how many pages */
/* 导入人物设定: the other work's characters, picked by tapping (gdCastBox, Wizard.jsx CastBox) */
.guided-cast-list { display: flex; flex-wrap: wrap; gap: 8px; }
.guided-cast-pick { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 132px; height: auto; padding: 8px; white-space: normal; text-align: center; }
.guided-cast-pick img { width: 104px; height: 104px; object-fit: cover; border-radius: 6px; }
.guided-insert .btn[aria-pressed="true"], .guided-next-chapter .btn[aria-pressed="true"], .guided-ab .btn[aria-pressed="true"], .guided-cast .btn[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
/* 画风选择 (guided.js gdStepStyle, the wizard and 换个画风): each look with its preview */
.choice .look-thumb { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; border-radius: 8px; background: var(--panel-2); }
/* 页面图排队时 (guided.js gdBindPageImages): not the browser's broken-picture mark, only the card's placeholder */
.page-view img:not([src]) { visibility: hidden; aspect-ratio: 3 / 4; }
/* React islands (app.js island): their node adds no box of its own, the page's layout goes on through it */
.island { display: contents; }
/* 漫画投稿 (client/Submit.jsx): the platforms side by side, one column on a phone */
.submit-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--space-3); }
.submit-platform ul { margin: 4px 0 0; padding-left: 20px; }
.submit-row { flex-wrap: wrap; }
@media (max-width: 640px) { .submit-grid { grid-template-columns: 1fr; } }
/* 可收起的面板 (admin ui/controls.jsx Panel): the title line folds the card; figures sit at its right */
.panel > summary { flex-wrap: wrap; }
.panel-title { font-weight: 600; }
.panel-extra { margin-left: auto; font-weight: 600; }
.panel-count { margin-left: 4px; }
.panel:not([open]) { padding-bottom: 12px; }
.panel-tools { gap: 6px; flex-wrap: nowrap; }
/* 导出设置 (guided.js gdExportRows): folded to one line saying what is chosen; opened, one row of segmented buttons per
   choice with the labels lined up */
.gd-export-settings { border: 1px solid var(--line); border-radius: 10px; background: var(--panel-2); }
.gd-export-settings > summary { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; padding: 8px 12px; cursor: pointer; list-style: none; font-size: 13px; }
.gd-export-settings > summary::-webkit-details-marker { display: none; }
.gd-export-edit { margin-left: auto; color: var(--accent); white-space: nowrap; }
.gd-export-edit::after { content: "修改 ▾"; }
.gd-export-settings[open] .gd-export-edit::after { content: "收起 ▴"; }
.gd-export-settings[open] > summary { border-bottom: 1px solid var(--line); }
.gd-export-rows { gap: 8px; padding: 10px 12px; }
.gd-export-group { min-width: 0; margin: 0; padding: 12px; border: 1px solid var(--line, #364151); border-radius: 10px; }
.gd-export-group legend { padding: 0 8px; font-size: 14px; font-weight: 700; color: var(--text, #e4eaf2); }
.gd-export-row { align-items: center; }
.gd-export-row .seg { flex-wrap: wrap; }
.gd-export-row .seg button { padding: 5px 10px; font-size: 13px; }
.gd-export-row > .muted { flex-basis: 100%; padding-left: calc(4.5em + 8px); font-size: 12px; }
.gd-export-label { min-width: 4.5em; color: var(--muted); }
@media (max-width: 640px) { .gd-export-row > .muted { padding-left: 0; } }
/* 业务功能开放 (admin Features.jsx): one compact card per module, side by side; the listed accounts in columns */
.access-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: var(--space-3); align-items: start; }
.access-card { padding: 14px 16px; gap: 8px; box-shadow: none; background: var(--panel-2); }
.access-card .field select { width: 100%; }
.access-card > .row:last-child { justify-content: flex-end; }
.access-accounts input[type="search"] { flex: 1; min-width: 140px; }
.access-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 4px 12px; max-height: 220px; overflow: auto;
  padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel); }
.access-list label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* 手机顶栏 (≤640px): the brand, 绘幕点 and 我的 / 通知 on one line; switching mode, 获取更多绘幕点, help and the back
   office as small links on a short second line — every button wrapping made the bar about 175px tall. The items come
   from app.js / guided.js and portal-bridge.js. */
@media (max-width: 640px) {
  .topbar { min-height: 0; padding: 8px 12px; gap: 4px 8px; flex-wrap: wrap; }
  .topbar::after { content: ""; flex-basis: 100%; height: 0; order: 2; }
  .topbar .brand { min-width: 0; gap: 8px; }
  .topbar .brand > .brand-logo { width: 32px; height: 32px; }
  .topbar .brand-name { font-size: 20px; letter-spacing: 2px; }
  .topbar .brand-tagline, .topbar > .muted.small { display: none; }
  .topbar > .btn { order: 1; padding: 6px 10px; font-size: 13px; }
  .topbar > :is(#gd-advanced, #to-guided, a[href="/credits"], [data-help-link], [data-portal-link]) {
    order: 3; padding: 4px 0; border: 0; background: none; font-size: 12px; color: var(--accent); text-decoration: underline; }
  .topbar > [data-workspace-label] { order: 4; }
}

/* One source-pixel editor for full comic pages and uploaded photos. */
.business-entries { display:grid; grid-template-columns:repeat(auto-fit,minmax(230px,1fr)); gap:14px; }
.business-entries .factory-entry { text-align:left; height:100%; }
.retouch-modal { width:min(1160px,96vw); max-width:1160px; max-height:94dvh; overflow:auto; padding:24px; }
.retouch-editor { min-width:0; }
.retouch-editor h2 { margin:0; }
.retouch-tools { border:0; margin:0; padding:0; min-width:0; }
.retouch-savebar { position:sticky; top:0; z-index:2; background:var(--surface,#20252d); padding:10px 0; border-bottom:1px solid var(--border); }
.retouch-tools input[type=number] { max-width:90px; }
.retouch-tools input[type=color] { width:48px; height:38px; padding:2px; }
.retouch-viewport { overflow:auto; max-height:64dvh; background:#101419; border:1px solid var(--border); border-radius:10px; overscroll-behavior:contain; }
.retouch-stage { position:relative; min-width:25%; max-width:none; margin-inline:auto; line-height:0; }
.retouch-stage img,.retouch-stage svg { position:absolute; inset:0; width:100%; height:100%; display:block; object-fit:fill; }
.retouch-stage svg { touch-action:none; cursor:crosshair; }
.retouch-stage svg.is-browsing { touch-action:pan-x pan-y; cursor:grab; }
.retouch-compare { display:grid; grid-template-columns:1fr 1fr; gap:14px; align-items:start; }
.retouch-compare figure { margin:0; min-width:0; }
.retouch-compare img { display:block; width:100%; height:auto; max-height:66dvh; object-fit:contain; background:#101419; border-radius:8px; }
.retouch-compare figcaption { padding:8px 0; }
.retouch-operation-list { max-height:200px; overflow:auto; list-style:none; padding:0; }
.retouch-photo-list { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,240px)); gap:14px; }
.retouch-photo { display:flex; flex-direction:column; gap:10px; text-align:left; cursor:pointer; }
.retouch-photo img { width:100%; aspect-ratio:3/4; object-fit:contain; background:#101419; border-radius:8px; }
.retouch-editor textarea { flex:1; width:100%; }
.retouch-editor [role=alert] { color:#ff9292; }
.retouch-element-toolbar { gap:6px; padding:8px 10px; border:1px solid var(--border); border-radius:8px; }
.retouch-element-toolbar .row { flex-wrap:wrap; gap:6px 12px; }
.retouch-element-toolbar label { display:inline-flex; gap:6px; align-items:center; }
.retouch-element-toolbar input[type=range] { width:120px; }
.retouch-element-toolbar input[type=number] { width:64px; }
@media(max-width:600px) {
  .retouch-element-toolbar .btn, .retouch-element-toolbar select { min-height:40px; }
  .retouch-element-toolbar label { flex:1 1 100%; }
  .retouch-element-toolbar input[type=range] { flex:1; width:auto; }
  .retouch-modal { width:100vw; max-width:100vw; max-height:100dvh; border-radius:0; padding:16px; }
  .retouch-overlay { padding:0; }
  .retouch-tools .btn { padding:8px 10px; font-size:14px; }
  .retouch-compare { gap:8px; }
  .business-entries { grid-template-columns:1fr; }
}

/* 头像与昵称 (services/avatars.py; ui.js avatarHtml, frontend/src/ui/controls.jsx Avatar): a glyph on a coloured disc.
   The 昵称 beside it in the top bar is cut with an ellipsis, so a long one never widens or wraps the bar. */
.avatar { display: inline-flex; align-items: center; justify-content: center; width: 1.7em; height: 1.7em; flex: none; border-radius: 50%; font-size: 1em; line-height: 1; vertical-align: middle; user-select: none; }
.avatar.big { font-size: 1.6em; }
.topbar [data-my-settings] { display: inline-flex; align-items: center; gap: 6px; max-width: 16em; }
.account-called { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.avatar-choices { display: flex; flex-wrap: wrap; gap: 10px; border: 0; padding: 0; margin: 0; }
.avatar-choices legend { padding: 0; margin-bottom: 6px; color: var(--muted); font-size: var(--text-sm); }
.avatar-choices label { position: relative; cursor: pointer; border-radius: 50%; }
.avatar-choices input { position: absolute; inset: 0; opacity: 0; cursor: pointer; margin: 0; }
.avatar-choices input:checked + .avatar { outline: 3px solid var(--accent); outline-offset: 2px; }
.avatar-choices input:focus-visible + .avatar { outline: 3px solid var(--info); outline-offset: 2px; }
@media (max-width: 600px) { .topbar [data-my-settings] { max-width: 9.5em; } }
.motion-productions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.motion-production{display:flex;flex-direction:column;gap:8px;text-align:left;cursor:pointer}
.motion-production[aria-pressed="true"]{border-color:#78a9ff;background:#223650;box-shadow:0 0 0 1px #78a9ff}
.motion-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.motion-screen{max-height:520px;width:min(100%,360px);aspect-ratio:9/16;background:#111;overflow:hidden;display:flex;align-items:center;justify-content:center;margin:auto;border-radius:12px}
.motion-screen.landscape{width:min(100%,720px);aspect-ratio:16/9}.motion-screen.square{width:min(100%,520px);aspect-ratio:1}
.motion-screen img,.motion-screen video{width:100%;height:100%;object-fit:contain}
.motion-timeline{display:flex;overflow:auto;gap:8px;padding:8px 0}.motion-timeline button{flex-shrink:0}.motion-timeline [aria-pressed="true"]{border-color:#78a9ff;background:#223650}
.motion-playing{animation-duration:var(--motion-seconds);animation-timing-function:linear;animation-fill-mode:forwards}
.motion-playing.zoom_in{animation-name:motion-zoom-in}.motion-playing.zoom_out{animation-name:motion-zoom-out}
.motion-playing.pan_left{animation-name:motion-left}.motion-playing.pan_right{animation-name:motion-right}.motion-playing.pan_up{animation-name:motion-up}.motion-playing.pan_down{animation-name:motion-down}
@keyframes motion-zoom-in{from{transform:scale(1)}to{transform:scale(1.1)}}@keyframes motion-zoom-out{from{transform:scale(1.1)}to{transform:scale(1)}}
@keyframes motion-left{from{transform:scale(1.12) translateX(4%)}to{transform:scale(1.12) translateX(-4%)}}@keyframes motion-right{from{transform:scale(1.12) translateX(-4%)}to{transform:scale(1.12) translateX(4%)}}
@keyframes motion-up{from{transform:scale(1.12) translateY(4%)}to{transform:scale(1.12) translateY(-4%)}}@keyframes motion-down{from{transform:scale(1.12) translateY(-4%)}to{transform:scale(1.12) translateY(4%)}}
@media(max-width:640px){.motion-productions,.motion-fields{grid-template-columns:1fr}}

/* 作品页分区 (guided.js gdWorkSections, client/Work.jsx WorkTabs): the one strip that sticks, about 44px; it scrolls
   sideways on a phone rather than wrapping. The top bar scrolls away on a work page. */
body:has(.work-nav) .topbar { position:static; }
.work-nav { position:sticky; top:0; z-index:6; display:flex; align-items:center; gap:8px; min-height:44px; padding:0 4px; background:var(--bg); border-bottom:1px solid var(--line); }
.work-tabs { display:flex; flex:1 1 auto; min-width:0; overflow-x:auto; scrollbar-width:none; }
.work-tabs::-webkit-scrollbar { display:none; }
.work-tabs [role="tab"] { flex:0 0 auto; height:44px; padding:0 14px; border:0; border-bottom:2px solid transparent; background:transparent; color:var(--muted); font:inherit; white-space:nowrap; cursor:pointer; }
.work-tabs [role="tab"]:hover { color:var(--ink); }
.work-tabs [role="tab"].on { color:var(--ink); border-bottom-color:var(--accent); font-weight:600; }
.work-tabs [role="tab"]:focus-visible { outline:2px solid var(--focus); outline-offset:-2px; }
.work-nav .page-issues { flex:0 0 auto; }
.work-section[hidden], .page-issues[hidden] { display:none !important; }
/* 续章 / 插入剧情 / 对比版本: one row of small entries; the one opened takes the row */
.work-tools { display:flex; flex-wrap:wrap; gap:8px; align-items:flex-start; }
.work-tools .guided-insert, .work-tools .guided-next-chapter, .work-tools .guided-ab,
.work-tool-slot:has(.guided-insert, .guided-next-chapter, .guided-ab) { flex:1 1 100%; }
/* 整部作品页 (series.js renderSeriesWorkspace, client/SeriesWorkspace.jsx): one compact line a chapter; its text,
   previews and video open under it. The shared blocks under the island show with their section. */
.series-slot[hidden] { display:none !important; }
.series-toolbar { flex-wrap:wrap; gap:8px; align-items:center; }
.series-rows { list-style:none; margin:0; padding:0; display:grid; gap:6px; }
.series-row { padding:8px 12px; }
.series-row-main { display:flex; flex-wrap:wrap; align-items:center; gap:8px; min-height:36px; }
.series-row-pick { display:inline-flex; align-items:center; gap:8px; min-width:0; overflow-wrap:anywhere; }
.series-row-info { white-space:nowrap; }
.series-row-more > summary { cursor:pointer; color:var(--muted); font-size:var(--text-xs); margin-top:4px; }
.series-row-more > .stack { margin-top:8px; }
.series-script, .series-notes { white-space:pre-wrap; overflow-wrap:anywhere; max-height:420px; overflow:auto; margin:0; }
.series-exports { list-style:none; margin:0; padding:0; display:grid; gap:6px; }
@media (max-width:640px) {
  .series-row-info { white-space:normal; flex:1 1 100%; order:3; }
  .series-toolbar .spacer { flex-basis:100%; }
}
/* 提醒小图标 (guided.js gdAlert): the shape and the label say which kind as well as the colour */
.page-alerts, .page-issues { display:inline-flex; align-items:center; gap:6px; margin-left:auto; }
.work-nav [data-generation-service-icon] { flex:0 0 auto; margin-left:0; padding-right:4px; }
.alert-tip { display:inline-flex; }
.alert-icon { position:relative; display:inline-grid; place-items:center; width:22px; height:22px; padding:0; border:1px solid currentColor; font:700 13px/1 var(--font); cursor:pointer; }
.alert-icon.bad { color:var(--danger); background:var(--danger-soft); border-radius:50%; }
.alert-icon.warn { color:var(--warn); background:var(--warn-soft); border-radius:3px; }
.alert-icon.info { color:var(--info); background:var(--info-soft); border-radius:50%; border-style:dashed; }
.alert-icon:focus-visible { outline:2px solid var(--focus); outline-offset:2px; }
.alert-count { position:absolute; top:-7px; right:-9px; min-width:15px; height:15px; padding:0 3px; border:1px solid currentColor; border-radius:var(--radius-pill); background:var(--panel); font-size:10px; line-height:13px; }
.alert-pop { position:fixed; z-index:19; width:min(340px, calc(100vw - 24px)); max-height:min(420px, 60vh); overflow:auto; padding:12px 14px; gap:8px; background:var(--panel); color:var(--ink); border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow); overflow-wrap:anywhere; text-align:left; font-weight:400; }
.alert-pop[hidden] { display:none !important; }
.alert-pop p { margin:0; }
.alert-pop .row { flex-wrap:wrap; gap:6px; }
.page-issues-list .row { align-items:baseline; gap:4px 12px; margin-bottom:8px; }
@media (pointer:coarse) { .alert-icon { width:26px; height:26px; } }
/* A page card: its number and hints on one line, one main 修改 and a small 更多 */
.page-head { flex-wrap:nowrap; gap:6px; }
.page-head > b, .page-head > .badge { flex:0 0 auto; }
.page-actions { flex-wrap:wrap; align-items:flex-start; gap:6px; }
.page-actions > .btn { flex:1 1 auto; }
.card-more > summary { list-style:none; cursor:pointer; padding:6px 10px; border:1px solid var(--line); border-radius:8px; }
.card-more > summary::-webkit-details-marker { display:none; }
.card-more[open] { flex:1 1 100%; }
.card-more-body { margin-top:8px; }
.card-more-body .guided-actions { flex-wrap:wrap; }
.audiobook-studio { max-width:1180px; margin:auto; }
.audiobook-studio h1 { font-size:1.65rem; }
.audiobook-studio .field { min-width:0; }
.audio-source { white-space:pre-wrap; overflow-wrap:anywhere; }
.audio-episodes { padding:4px; }
.audio-segment summary { overflow-wrap:anywhere; cursor:pointer; }
.audiobook-studio video { max-width:100%; width:100%; max-height:65vh; background:#10131b; border-radius:10px; }
.audiobook-studio audio { max-width:100%; }
.audio-segment-image { max-width:100%; max-height:400px; object-fit:contain; }
.audio-save { position:sticky; bottom:8px; z-index:4; border-color:var(--accent,#749ee9); padding:10px 14px; display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:6px 12px; box-shadow:0 3px 16px #0004; }
.audio-save .row { gap:6px; }
@media(max-width:600px) { .audiobook-studio h1 { font-size:1.3rem; } .audiobook-studio .motion-fields { grid-template-columns:1fr; } .audiobook-studio .audio-save .btn { flex:1 1 auto; padding:7px 10px; font-size:13px; } .audio-save { bottom:4px; padding:8px; } }

/* 统一工作台 (root design 2026-10-13). The page head (workbench.js wbTopbar): the brand — a button home away from the
   home — 帮助与反馈 and 我的账户, one line on a phone too; the wallet and the account's links are in its menu. */
.guided-top { min-height:0; padding:8px 20px; gap:10px; }
.guided-top .brand > .brand-logo { width:40px; height:40px; }
.guided-top .brand-name { font-size:24px; letter-spacing:3px; }
.wb-home { background:none; border:0; padding:0; font:inherit; text-align:left; cursor:pointer; }
.wb-home:focus-visible { outline:2px solid var(--focus); outline-offset:4px; border-radius:6px; }
/* A small menu (details[data-wb-menu] in the shell, client/SeriesWorkspace.jsx Menu): its box opens under its button,
   right-aligned, inside the window; a long one scrolls inside, the page under it keeps its place. */
.wb-menu { position:relative; display:inline-flex; }
.wb-menu > summary { list-style:none; cursor:pointer; white-space:nowrap; }
.wb-menu > summary::-webkit-details-marker { display:none; }
.wb-menu-pop { position:absolute; top:calc(100% + 6px); right:0; z-index:20; min-width:200px; max-width:min(320px, calc(100vw - 24px)); max-height:min(420px, 70vh);
  overflow:auto; padding:8px; gap:6px; background:var(--panel); color:var(--ink); border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow); }
.wb-menu-pop[hidden] { display:none !important; }
.wb-menu-pop > .btn, .wb-menu-pop > a.btn { width:100%; justify-content:flex-start; min-height:36px; white-space:normal; text-align:left; }
.topbar .wb-menu-pop [data-my-settings] { max-width:none; }
/* A work's and a whole work's head line: the way back, the title (a phone may wrap it once), the pencil and the badges. */
.work-head { flex-wrap:wrap; align-items:center; gap:4px 10px; }
.work-head h1 { margin:0; min-width:0; font-size:clamp(18px, 4.6vw, 26px); line-height:1.25; }
.work-back { white-space:nowrap; font-size:var(--text-sm); }
.icon-btn { text-decoration:none; padding:2px 6px; min-width:28px; min-height:28px; }
/* The one status line (gdNextBox, gdErrorBox, gdProgress, gdSeriesNextBox, gdSeriesProgress): state, coloured icon, one
   main button and a small 更多 that opens on its own full-width line. */
.guided-next-slim { padding-top:8px; padding-bottom:8px; gap:6px; }
.guided-next-slim .next-bar { flex-wrap:wrap; align-items:center; gap:6px 10px; min-height:32px; }
.guided-next-slim .guided-next-title { font-size:var(--text-lg); overflow-wrap:anywhere; }
.guided-next-slim .next-bar > .btn { padding-top:6px; padding-bottom:6px; white-space:nowrap; }
.guided-next-slim .next-more > summary { cursor:pointer; white-space:nowrap; }
.guided-next-slim .next-more[open] { flex:1 1 100%; }
.guided-next-slim .next-more > .stack, .guided-next-slim .next-more > .row { margin-top:var(--space-2); }
.guided-next-slim .next-more > .row, .guided-next-slim .next-group > .row { flex-wrap:wrap; gap:6px; }
.progress-now { min-width:0; overflow-wrap:anywhere; }
.progress-mini { width:72px; height:8px; vertical-align:middle; }
@media (max-width:640px) {
  .guided-top { padding:6px 12px; gap:6px 8px; }
  .guided-top::after { content:none; }
  .guided-top > [data-help-link] { order:1; }
  .guided-top > .wb-menu { order:2; }
  .guided-top .brand-name { font-size:20px; letter-spacing:2px; }
  .guided-top .brand > .brand-logo { width:32px; height:32px; }
  .series-toolbar .wb-menu-pop { left:0; right:auto; }
  .guided-steps { font-size:var(--text-sm); }
  .guided-next-slim .next-bar > .btn { flex:1 1 auto; }
}
@media (pointer:coarse) {
  .wb-menu > summary, .wb-menu > [data-menu-toggle], .work-head .icon-btn, .work-back { min-height:40px; min-width:40px; }
  .wb-menu-pop > .btn, .wb-menu-pop > a.btn { min-height:44px; }
}
.page-editor-tabs { display:flex; align-items:center; gap:6px; overflow-x:auto; padding:2px 0 6px; max-width:100%; }
.page-editor-tabs > .btn { flex:0 0 auto; white-space:nowrap; }
.guided-page-editor-panel { min-width:0; margin:0; }
.guided-page-editor textarea { min-height:0; }
