@zhouchangui/math-ati 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -0
- package/bin/math-ati.js +136 -5
- package/dist/assets/{index--Um9OfFu.css → index-CJkqklO7.css} +1 -1
- package/dist/assets/index-w2k_4Owd.js +22 -0
- package/dist/index.html +2 -2
- package/package.json +7 -4
- package/prompts/grading.system.md +3 -1
- package/prompts/knowledge-structure.system.md +75 -0
- package/prompts/knowledge-summarize.system.md +13 -1
- package/prompts/pdf-grading.system.md +4 -1
- package/prompts/pdf-recheck.system.md +2 -0
- package/prompts/practice-answers.system.md +154 -0
- package/prompts/practice-coverage-repair.system.md +112 -0
- package/prompts/practice-generate.system.md +45 -5
- package/prompts/practice-rules.md +61 -0
- package/server/fileStore.js +9 -2
- package/server/index.js +48 -0
- package/server/knowledgeExtractor.js +218 -59
- package/server/knowledgeFeedback.js +69 -0
- package/server/practiceGenerator.js +78 -83
- package/server/practiceReviewer.js +24 -0
- package/server/practiceService.js +2 -2
- package/server/promptStore.js +14 -0
- package/dist/assets/index-CS-PgjYi.js +0 -22
package/AGENTS.md
CHANGED
|
@@ -260,6 +260,8 @@ Generation for blind-spot repair should use `knowledgePointIds` from weak points
|
|
|
260
260
|
- Use HTML for printable practice papers. Do not generate Markdown practice papers.
|
|
261
261
|
- Use `process_log.jsonl` and job events for progress; do not rely only on console logs.
|
|
262
262
|
- When adding or changing APIs, modules, data models, or workflow behavior, update `.agents/story/` as well as this file if the change affects future agents.
|
|
263
|
+
- 测试不要直接在开发目录里跑。e2e、回归、临时脚本的输出和 workspace 放到外部 workspace(`$HOME/math-ati-workspace`)或系统临时目录里,避免在项目根目录留下 `run-*`、`--chapters` 之类的垃圾文件。
|
|
264
|
+
- Curriculum package (`build:curriculum`) must stay under npm publish size limits. The source images are high-quality scans (300–450 KB each, 325 pages) that would exceed npm's ~200 MB publish limit if copied as-is. All images copied into the package via `copyTree` must be compressed through ImageMagick (`magick <src> -strip -quality 55 <dst>`), which strips metadata and re-encodes to quality 55 (~70–100 KB per page). The `copyChapterImages` path (source_pages per chapter) uses quality 65 for local working copies; `copyTree` (image-root) uses quality 55 to keep the shared reference tree below 60 MB. Publish fails with `413 Payload Too Large` if the package exceeds ~200 MB.
|
|
263
265
|
|
|
264
266
|
## Upaseo Assets
|
|
265
267
|
|
package/bin/math-ati.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execFile, spawn } from 'node:child_process';
|
|
3
3
|
import { constants } from 'node:fs';
|
|
4
|
-
import { access, cp, mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { access, cp, lstat, mkdir, readdir, readFile, rm, symlink, writeFile } from 'node:fs/promises';
|
|
5
5
|
import { createRequire } from 'node:module';
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import path from 'node:path';
|
|
@@ -141,8 +141,37 @@ async function curriculumDataRootFromDir(dir) {
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
async function localCurriculumPackageRoot(packageName) {
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
// C 端 users install the curriculum package through a number of layouts:
|
|
145
|
+
// 1. math-ati init drops it under `~/.math-ati/curriculum-cache/<id>/...`
|
|
146
|
+
// 2. `npm i -g @zhouchangui/math-ati-curriculum-rj-7a` lands it in the
|
|
147
|
+
// global npm prefix's node_modules, which `npm root -g` reports.
|
|
148
|
+
// 3. Some wrappers place it under a sibling `math-ati-curriculum-wrapper`
|
|
149
|
+
// next to the main package (e.g. inside `<prefix>/lib/node_modules/`).
|
|
150
|
+
// 4. The developer install lands it next to the main package in
|
|
151
|
+
// `<packageRoot>/node_modules/...`.
|
|
152
|
+
// 5. Optional deps declared on the main package get hoisted next to it.
|
|
153
|
+
// We probe all of these so C 端 users do not need to run any extra
|
|
154
|
+
// `npm install` step beyond `math-ati init`.
|
|
155
|
+
const candidates = [];
|
|
156
|
+
candidates.push(path.join(curriculumCacheRoot(), 'node_modules', ...packageName.split('/')));
|
|
157
|
+
candidates.push(path.join(packageRoot, 'node_modules', ...packageName.split('/')));
|
|
158
|
+
try {
|
|
159
|
+
const npmRoot = (await execFileAsync('npm', ['root', '-g'], { maxBuffer: 1024 * 1024 * 4 })).stdout.toString().trim();
|
|
160
|
+
if (npmRoot) {
|
|
161
|
+
candidates.push(path.join(npmRoot, ...packageName.split('/')));
|
|
162
|
+
}
|
|
163
|
+
} catch {
|
|
164
|
+
// npm not available or failed — fall through.
|
|
165
|
+
}
|
|
166
|
+
if (process.env.NODE_PATH) {
|
|
167
|
+
for (const dir of process.env.NODE_PATH.split(path.delimiter)) {
|
|
168
|
+
candidates.push(path.join(dir, ...packageName.split('/')));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
for (const candidate of candidates) {
|
|
172
|
+
if (await exists(path.join(candidate, 'package.json'))) return candidate;
|
|
173
|
+
}
|
|
174
|
+
// Final fallback: ask Node to resolve from the CLI's package.json.
|
|
146
175
|
try {
|
|
147
176
|
return path.dirname(requireFromCli.resolve(`${packageName}/package.json`));
|
|
148
177
|
} catch {
|
|
@@ -186,7 +215,15 @@ async function resolveCurriculumDataRoot(flags) {
|
|
|
186
215
|
const packageName = packageNameFromSpec(spec);
|
|
187
216
|
let curriculumPackageRoot = await localCurriculumPackageRoot(packageName);
|
|
188
217
|
let installed = false;
|
|
189
|
-
if
|
|
218
|
+
// Only re-install if the locally-resolved package either does not exist or
|
|
219
|
+
// is missing the data tree. Falling through to npm install when the local
|
|
220
|
+
// copy is otherwise complete would route to the npm registry, which may
|
|
221
|
+
// ship an older version that overwrites our newer image-root/ bundle.
|
|
222
|
+
if (curriculumPackageRoot) {
|
|
223
|
+
const localDataRoot = await curriculumDataRootFromPackageRoot(curriculumPackageRoot);
|
|
224
|
+
if (!localDataRoot) curriculumPackageRoot = null;
|
|
225
|
+
}
|
|
226
|
+
if (!curriculumPackageRoot) {
|
|
190
227
|
curriculumPackageRoot = await installCurriculumPackage(spec, packageName);
|
|
191
228
|
installed = true;
|
|
192
229
|
}
|
|
@@ -223,18 +260,88 @@ async function initWorkspace(argv) {
|
|
|
223
260
|
force: Boolean(flags.force) || !hadData
|
|
224
261
|
});
|
|
225
262
|
await writeCurriculumReceipt(workspaceDir, curriculum);
|
|
263
|
+
// Link the curriculum-bundled imageRoot into the workspace so the server
|
|
264
|
+
// (and any extension that needs raw page images, e.g. knowledge extract)
|
|
265
|
+
// can resolve every chapter.imageFolder without a host-level image root.
|
|
266
|
+
// The published curriculum package now ships `image-root/<folder>/...`
|
|
267
|
+
// alongside `data/`, making C 端 installs self-contained.
|
|
268
|
+
const linkResult = await linkImageRoot(workspaceDir, curriculum);
|
|
226
269
|
const envLocal = path.join(workspaceDir, '.env.local');
|
|
227
270
|
const envExample = path.join(workspaceDir, '.env.local.example');
|
|
228
271
|
if (!(await exists(envLocal)) && (await exists(envExample))) {
|
|
229
272
|
await writeFile(envLocal, await readFile(envExample, 'utf8'), 'utf8');
|
|
230
273
|
}
|
|
274
|
+
// Fail fast if any chapter still has no source pages after init — this
|
|
275
|
+
// catches C 端 installs where the curriculum data was copied but the
|
|
276
|
+
// imageRoot is missing or the wrapper-structure lookup regressed.
|
|
277
|
+
const missing = await findChaptersWithoutSourcePages(workspaceDir);
|
|
278
|
+
if (missing.length) {
|
|
279
|
+
throw new Error(`chapters_missing_source_pages:${missing.length}:${missing.slice(0, 5).join(',')}`);
|
|
280
|
+
}
|
|
231
281
|
console.log(`[math-ati.init] workspace=${workspaceDir}`);
|
|
232
282
|
console.log(`[math-ati.init] data=${path.join(workspaceDir, 'data')}`);
|
|
233
283
|
console.log(`[math-ati.init] curriculum=${curriculum.packageName || curriculum.source}`);
|
|
234
284
|
console.log(`[math-ati.init] curriculumSource=${curriculum.source}`);
|
|
285
|
+
console.log(`[math-ati.init] imageRoot=${linkResult.target}`);
|
|
235
286
|
console.log('[math-ati.init] edit .env.local, then run: math-ati start --open');
|
|
236
287
|
}
|
|
237
288
|
|
|
289
|
+
// Locate the published curriculum package's image-root tree. The package
|
|
290
|
+
// layout can vary depending on how the user installed the curriculum
|
|
291
|
+
// (legacy flat, npm wrapper install, or a `--curriculum-dir` checkout),
|
|
292
|
+
// so we probe a small set of candidate paths and return the first one
|
|
293
|
+
// that contains a chapter image folder.
|
|
294
|
+
async function findCurriculumImageRoot(curriculumSource) {
|
|
295
|
+
const candidates = [
|
|
296
|
+
path.join(curriculumSource, 'curriculum', DEFAULT_CURRICULUM_ID, 'image-root'),
|
|
297
|
+
path.join(curriculumSource, 'image-root'),
|
|
298
|
+
path.join(curriculumSource, '..', 'image-root')
|
|
299
|
+
];
|
|
300
|
+
for (const candidate of candidates) {
|
|
301
|
+
if (await exists(candidate)) {
|
|
302
|
+
const entries = await readdir(candidate).catch(() => []);
|
|
303
|
+
if (entries.length) return candidate;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async function linkImageRoot(workspaceDir, curriculum) {
|
|
310
|
+
const target = path.join(workspaceDir, 'image-root');
|
|
311
|
+
if (await exists(target)) {
|
|
312
|
+
const stat = await lstat(target).catch(() => null);
|
|
313
|
+
if (stat?.isSymbolicLink() || stat?.isDirectory()) {
|
|
314
|
+
return { target, linked: stat?.isSymbolicLink() ? 'reused' : 'exists' };
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
const imageRootSource = await findCurriculumImageRoot(curriculum.source);
|
|
318
|
+
if (!imageRootSource) {
|
|
319
|
+
throw new Error('image_root_missing_in_curriculum:no image-root/ found in package');
|
|
320
|
+
}
|
|
321
|
+
await rm(target, { recursive: true, force: true });
|
|
322
|
+
await symlink(imageRootSource, target, 'dir');
|
|
323
|
+
return { target, source: imageRootSource, linked: 'created' };
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
async function findChaptersWithoutSourcePages(workspaceDir) {
|
|
327
|
+
const chaptersPath = path.join(workspaceDir, 'data', 'global', 'chapters.json');
|
|
328
|
+
if (!(await exists(chaptersPath))) return [];
|
|
329
|
+
const chapters = JSON.parse(await readFile(chaptersPath, 'utf8').catch(() => '[]'));
|
|
330
|
+
const missing = [];
|
|
331
|
+
for (const chapter of chapters || []) {
|
|
332
|
+
const dir = path.join(workspaceDir, 'data', 'chapters', chapter.id, 'source_pages');
|
|
333
|
+
if (!(await exists(dir))) {
|
|
334
|
+
missing.push(chapter.id);
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
const files = await readdir(dir).catch(() => []);
|
|
338
|
+
if (!files.some((file) => /\.(png|jpe?g|webp)$/i.test(file))) {
|
|
339
|
+
missing.push(chapter.id);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return missing;
|
|
343
|
+
}
|
|
344
|
+
|
|
238
345
|
function workspaceFromArgs(args) {
|
|
239
346
|
return path.resolve(args[0] || process.cwd());
|
|
240
347
|
}
|
|
@@ -269,6 +376,11 @@ async function startServer(argv) {
|
|
|
269
376
|
}
|
|
270
377
|
|
|
271
378
|
const url = `http://127.0.0.1:${port}`;
|
|
379
|
+
// The server reads MATH_AGENT_IMAGE_ROOT to resolve chapter.imageFolder
|
|
380
|
+
// back to raw page images. We default to the workspace's image-root
|
|
381
|
+
// symlink that init creates from the published curriculum package; if the
|
|
382
|
+
// user has provided their own image root, that takes precedence.
|
|
383
|
+
const imageRoot = process.env.MATH_AGENT_IMAGE_ROOT || path.join(dataDir, '..', 'image-root');
|
|
272
384
|
const server = spawn(process.execPath, [path.join(packageRoot, 'server', 'index.js')], {
|
|
273
385
|
cwd: packageRoot,
|
|
274
386
|
stdio: 'inherit',
|
|
@@ -276,7 +388,8 @@ async function startServer(argv) {
|
|
|
276
388
|
...process.env,
|
|
277
389
|
PORT: port,
|
|
278
390
|
MATH_AGENT_DATA_DIR: dataDir,
|
|
279
|
-
MATH_AGENT_ENV_FILE: envFile
|
|
391
|
+
MATH_AGENT_ENV_FILE: envFile,
|
|
392
|
+
MATH_AGENT_IMAGE_ROOT: imageRoot
|
|
280
393
|
}
|
|
281
394
|
});
|
|
282
395
|
if (flags.open) setTimeout(() => openBrowser(url), 900);
|
|
@@ -316,6 +429,21 @@ async function doctor(argv) {
|
|
|
316
429
|
} catch {
|
|
317
430
|
// Missing data is reported by hasData.
|
|
318
431
|
}
|
|
432
|
+
// Per-chapter coverage: list any chapter whose source_pages is empty or
|
|
433
|
+
// missing. C 端 installs should report 0 here; non-zero means the
|
|
434
|
+
// image-root link or the curriculum data copy is broken.
|
|
435
|
+
const chaptersIndexPath = path.join(dataDir, 'global', 'chapters.json');
|
|
436
|
+
const chapterIds = (await readFile(chaptersIndexPath, 'utf8').then((t) => JSON.parse(t)).catch(() => []))
|
|
437
|
+
.map((chapter) => chapter.id);
|
|
438
|
+
const chaptersMissingSourcePages = [];
|
|
439
|
+
for (const id of chapterIds) {
|
|
440
|
+
const pagesDir = path.join(dataDir, 'chapters', id, 'source_pages');
|
|
441
|
+
const files = await readdir(pagesDir).catch(() => []);
|
|
442
|
+
if (!files.some((file) => /\.(png|jpe?g|webp)$/i.test(file))) {
|
|
443
|
+
chaptersMissingSourcePages.push(id);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
const imageRoot = process.env.MATH_AGENT_IMAGE_ROOT || path.join(dataDir, '..', 'image-root');
|
|
319
447
|
console.log(JSON.stringify({
|
|
320
448
|
packageRoot,
|
|
321
449
|
dataDir,
|
|
@@ -325,6 +453,9 @@ async function doctor(argv) {
|
|
|
325
453
|
curriculumReceipt: await exists(path.join(dataDir, 'global', 'curriculum.json')),
|
|
326
454
|
chapterDirectoryCount,
|
|
327
455
|
sourcePageCount,
|
|
456
|
+
chaptersMissingSourcePages,
|
|
457
|
+
imageRoot,
|
|
458
|
+
imageRootResolved: await exists(imageRoot),
|
|
328
459
|
node: process.version
|
|
329
460
|
}, null, 2));
|
|
330
461
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{color:#17201c;background:#eef2ef;font-family:Inter,PingFang SC,Microsoft YaHei,Arial,sans-serif;font-size:16px;--surface: #fffdf8;--surface-muted: #f5f7f2;--surface-cool: #edf4f0;--border: #d4ddd5;--border-strong: #b9c6be;--text-soft: #5f6c64;--text-muted: #738077;--green: #1f6455;--green-dark: #16483d;--green-soft: #dcece5;--rust: #91442f;--rust-soft: #f4ded1;--yellow-soft: #ece7bd;--danger: #872d23;--danger-soft: #f8d8d2}*{box-sizing:border-box}body{margin:0}button,input,textarea,select{font:inherit}button{min-height:38px;border:1px solid var(--border-strong);border-radius:6px;background:var(--surface);color:#17201c;padding:0 12px;display:inline-flex;align-items:center;justify-content:center;gap:8px;cursor:pointer;transition:background .14s ease,border-color .14s ease,color .14s ease,box-shadow .14s ease}.button-link,.entry-action-button{min-height:38px;border:1px solid var(--border-strong);border-radius:6px;color:#17201c;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:0 12px}button.primary{color:#fff;background:var(--green);border-color:var(--green)}button:hover:not(:disabled),.button-link:hover,.entry-action-button:hover{border-color:var(--green);background:var(--surface-cool)}button.primary:hover:not(:disabled){background:var(--green-dark);border-color:var(--green-dark)}button:focus-visible,.button-link:focus-visible,.entry-action-button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline:2px solid rgba(31,100,85,.28);outline-offset:2px}button:disabled,input:disabled,textarea:disabled,select:disabled{opacity:.55;cursor:not-allowed}input,textarea,select{width:100%;border:1px solid var(--border-strong);border-radius:6px;background:#fff;color:#17201c;min-height:38px;padding:8px 10px}textarea{min-height:72px;resize:vertical}h1,h2,h3,h4,p{margin:0}h1{font-size:32px;line-height:1.15}h2{font-size:22px}h3{font-size:18px}h4{font-size:15px}.app-shell{max-width:1480px;margin:0 auto;padding:24px}.app-header{display:flex;justify-content:space-between;align-items:center;gap:18px;margin-bottom:18px}.app-title-button{min-height:0;border:0;background:transparent;padding:0;color:inherit;justify-content:flex-start;text-align:left}.app-title-button:hover:not(:disabled){background:transparent;color:var(--green)}.profile-open-button{flex:0 0 auto}.settings-menu-wrap{position:relative;flex:0 0 auto}.settings-menu{position:absolute;top:calc(100% + 8px);right:0;z-index:40;min-width:150px;display:grid;gap:4px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);box-shadow:0 18px 42px #16221d2e;padding:6px}.settings-menu button{width:100%;justify-content:flex-start;border-color:transparent;background:transparent}.settings-menu button:hover{border-color:var(--border);background:var(--surface-cool)}.app-header p,.workflow-head p,.section-heading p,.card-note{color:var(--text-muted);margin-top:5px}.eyebrow{color:var(--rust);font-size:12px;text-transform:uppercase;letter-spacing:0;font-weight:700}.toast{background:var(--green-dark);color:#fff;border-radius:6px;padding:10px 12px;margin-bottom:14px}.workspace{display:grid;grid-template-columns:292px minmax(0,1fr);gap:18px;align-items:start}.nav-collapsed .workspace{grid-template-columns:64px minmax(0,1fr)}.chapter-nav{position:sticky;top:16px;height:calc(100vh - 48px);overflow:hidden;border:1px solid var(--border);border-radius:8px;background:var(--surface);display:flex;flex-direction:column;box-shadow:0 10px 24px #24312a0f}.chapter-nav-head{min-height:54px;padding:10px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;gap:8px}.chapter-nav-list{padding:8px;overflow:auto;display:grid;gap:5px}.chapter-nav-item{width:100%;justify-content:flex-start;min-height:42px;padding:6px 8px;background:transparent;border-color:transparent}.chapter-nav.collapsed .chapter-nav-head,.chapter-nav.collapsed .chapter-nav-item{justify-content:center}.chapter-nav-item.selected{border-color:var(--green);background:var(--green-soft)}.chapter-index{width:24px;flex:0 0 auto;color:var(--rust);font-weight:700;font-size:12px}.chapter-name{flex:1;min-width:0;text-align:left;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.chapter-status,.flow-status{flex:0 0 auto;border-radius:999px;background:#e4e9e2;color:#536057;padding:3px 8px;font-size:12px;white-space:nowrap}.chapter-status.in_progress,.flow-status.generated,.flow-status.previewed,.flow-status.printed,.flow-status.submitted,.flow-status.pdf_received{background:#f2d9c8;color:#7f3a23}.chapter-status.review_due,.flow-status.graded,.flow-status.needs_review{background:var(--yellow-soft);color:#645600}.chapter-status.mastered,.flow-status.archived{background:#cfe8da;color:var(--green)}.flow-status.failed,.flow-status.failed_generate,.flow-status.failed_grade{background:var(--danger-soft);color:var(--danger)}.flow-status.available{background:var(--green-soft);color:var(--green)}.flow-status.missing{background:#fff6d7;color:#7a5a0f}.flow-status.missing_source,.flow-status.unavailable{background:#e7ece8;color:var(--text-muted)}.icon-button{width:38px;padding:0}.chapter-workspace{min-width:0}.panel{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:18px;margin-bottom:16px;box-shadow:0 10px 24px #24312a0d}.chapter-summary{display:grid;grid-template-columns:minmax(250px,1fr) minmax(400px,1.2fr);gap:16px;align-items:end}.stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}.stats-grid.compact{grid-template-columns:repeat(5,minmax(0,1fr))}.stat-tile{border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:12px}.stat-tile span{color:var(--text-muted);font-size:13px}.stat-tile strong{display:block;margin-top:6px;font-size:22px}.knowledge-map-panel{display:grid;gap:16px}.knowledge-map-head{display:flex;justify-content:space-between;gap:16px;align-items:start}.knowledge-view-tabs{display:inline-flex;gap:4px;padding:4px;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted)}.knowledge-view-tabs button{min-height:34px;border-color:transparent;background:transparent;white-space:nowrap}.knowledge-view-tabs button.selected{color:var(--green);border-color:var(--green);background:#fff;font-weight:700}.knowledge-map-summary{display:flex;flex-wrap:wrap;gap:10px;color:var(--text-soft);font-size:13px}.knowledge-map-summary span{display:inline-flex;align-items:center;gap:6px}.knowledge-filter-group{display:inline-flex;gap:4px;padding:2px;border:1px solid var(--border);border-radius:999px;background:var(--surface-muted)}.knowledge-filter-group button{min-height:26px;border-radius:999px;border-color:transparent;background:transparent;padding:0 10px;font-size:12px}.knowledge-filter-group button.selected{color:#fff;background:var(--green);border-color:var(--green)}.legend-dot{width:10px;height:10px;border:1px solid var(--border-strong);border-radius:999px;background:#fff}.legend-dot.mastered{background:#bfe1cf;border-color:var(--green)}.legend-dot.needs_review{background:var(--yellow-soft);border-color:#c6b85d}.knowledge-wall{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px}.knowledge-card{min-height:132px;display:grid;align-content:space-between;gap:10px;border:1px solid var(--border);border-radius:8px;padding:12px;background:#fff}.knowledge-card.mastered{border-color:#94bca8;background:#edf7f1}.knowledge-card.needs_review{border-color:#d7cb76;background:#fff9d9}.knowledge-card.uncovered{background:#fff}.knowledge-card strong{display:block;line-height:1.35}.knowledge-card span{color:var(--text-muted);font-size:12px}.knowledge-card p{color:var(--text-soft);font-size:13px;line-height:1.55}.knowledge-card-foot{display:flex;justify-content:space-between;gap:8px;align-items:center}.knowledge-card-foot small{color:var(--text-muted)}.knowledge-market-layout{display:block}.knowledge-market-board{position:relative;display:grid;grid-template-columns:repeat(auto-fill,minmax(82px,1fr));grid-auto-flow:dense;gap:1px;padding:4px;border:0;border-radius:8px;background:#20342e}.knowledge-market-tile{--tile-bg: #fffdf8;--tile-fg: #17201c;--tile-muted: #627167;position:relative;min-height:54px;display:grid;place-items:center;gap:2px;padding:6px;border-radius:3px;text-align:center;color:var(--tile-fg);background:var(--tile-bg);border:0;box-shadow:none}.knowledge-market-tile:hover:not(:disabled){z-index:40;background:var(--tile-bg);border-color:transparent;filter:brightness(.96)}.knowledge-market-tile:focus-visible{z-index:40;outline:2px solid rgba(31,100,85,.42);outline-offset:1px}.knowledge-market-tile strong{width:100%;font-size:12.5px;line-height:1.22;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.knowledge-hover-card span{color:var(--tile-muted);font-size:11px;line-height:1.1}.knowledge-market-tile.mastered{--tile-bg: #1f9d5b;--tile-fg: #ffffff;--tile-muted: rgba(255, 255, 255, .82)}.knowledge-market-tile.needs_review{--tile-bg: #f3dc61;--tile-fg: #17201c;--tile-muted: #5d612f}.knowledge-market-tile.review-low{--tile-bg: #f8e986;--tile-muted: #667044}.knowledge-market-tile.review-mid{--tile-bg: #efd347;--tile-muted: #5b5f2b}.knowledge-market-tile.review-high{--tile-bg: #d49a22;--tile-muted: #443a17}.knowledge-market-tile.uncovered{--tile-bg: #fffdf8;--tile-fg: #17201c;--tile-muted: #738077}.knowledge-hover-card{position:absolute;left:0;top:calc(100% + 6px);z-index:80;width:min(320px,70vw);display:none;gap:7px;border:1px solid var(--border-strong);border-radius:8px;background:#fffdf8;color:#17201c;box-shadow:0 18px 46px #16221d42;padding:12px;text-align:left}.knowledge-market-tile:hover .knowledge-hover-card,.knowledge-market-tile:focus-visible .knowledge-hover-card{display:grid}.knowledge-hover-card strong{font-size:15px;line-height:1.35;display:block}.knowledge-hover-card em{color:var(--text-soft);font-style:normal;font-size:13px;line-height:1.55}.knowledge-hover-card>span{color:var(--text-muted);font-size:12px}.knowledge-image-board{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px}.knowledge-page-card{display:grid;grid-template-columns:110px minmax(0,1fr);gap:12px;border:1px solid var(--border);border-radius:8px;background:#fff;padding:10px}.knowledge-page-card img{width:100%;height:150px;object-fit:cover;object-position:top;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted)}.knowledge-page-card strong{display:block;margin-bottom:3px}.knowledge-page-card p{color:var(--text-muted);font-size:13px;margin-bottom:8px}.page-point-list{display:flex;flex-wrap:wrap;gap:6px}.point-pill{border:1px solid var(--border-strong);border-radius:999px;background:#fff;padding:4px 8px;color:var(--text-soft);font-size:12px}.point-pill.mastered{border-color:#94bca8;background:#edf7f1;color:var(--green)}.point-pill.needs_review{border-color:#d7cb76;background:#fff9d9;color:#645600}.flow-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:10px}.active-paper-panel,.result-panel{display:grid;gap:14px;align-content:start}.workflow-entry-card{width:100%;min-height:72px;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;justify-content:stretch;text-align:left;padding:12px 14px;gap:14px;background:#fff;border:1px solid var(--border-strong);border-radius:6px}.workflow-entry-card.disabled{background:#f1f4f0;border-color:var(--border)}.workflow-head,.section-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.section-heading{justify-content:flex-start;margin-bottom:12px}.section-heading svg{color:var(--green);margin-top:1px}.subtle-icon-button{width:34px;min-height:34px;margin-left:auto;padding:0;border-color:transparent;background:transparent;color:var(--text-muted)}.subtle-icon-button:hover:not(:disabled){border-color:var(--border);background:var(--surface-cool);color:var(--green)}.overview-actions{display:grid;gap:12px}.practice-entry-strip{display:grid;gap:10px;padding:14px}.practice-entry-strip .section-heading{margin-bottom:0}.practice-entry-strip .workflow-entry-card{min-height:60px;padding:12px;background:#fbfdf9}.practice-entry-strip .workflow-entry-card>div:first-child strong{font-size:15px}.practice-entry-strip .workflow-entry-card small{display:none}.practice-overview-progress{display:grid;gap:12px;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:14px}.progress-copy{display:flex;align-items:baseline;justify-content:space-between;gap:12px}.progress-copy span,.workflow-entry-card small{color:var(--text-muted);font-size:13px}.progress-copy strong{font-size:18px}.progress-track{height:8px;overflow:hidden;border-radius:999px;background:#dfe7e1}.progress-track span{display:block;height:100%;border-radius:inherit;background:var(--green)}.progress-stat-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.progress-stat-grid .stat-tile{padding:10px}.progress-stat-grid .stat-tile strong{font-size:20px}.practice-stat-line{display:flex;flex-wrap:wrap;gap:8px}.practice-stat-line span{border:1px solid var(--border);border-radius:999px;background:#fff;color:var(--text-soft);font-size:12px;padding:5px 9px}.workflow-entry-card>div:first-child{min-width:0;display:grid;gap:3px}.workflow-entry-card>div:first-child strong{font-size:16px}.entry-action-cluster{min-width:max-content;display:flex;align-items:center;justify-content:flex-end;gap:10px}.entry-action-button{min-width:104px;color:#fff;background:var(--green);border-color:var(--green);font-weight:700;white-space:nowrap;padding:0 12px 0 14px;box-shadow:0 4px 10px #1f645524;transition:background .14s ease,border-color .14s ease,color .14s ease,box-shadow .14s ease,transform .14s ease}.entry-action-button svg{margin-right:-3px}.entry-action-button:hover{color:#fff;background:var(--green-dark);border-color:var(--green-dark);box-shadow:0 6px 14px #1f645533;transform:translateY(-1px)}.entry-action-button.disabled{color:var(--text-muted);background:#e7ece8;border-color:var(--border);box-shadow:none;pointer-events:none}.extract-workspace{display:grid;gap:16px;scroll-margin-top:16px}.extract-compact-panel{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;padding:12px 14px}.extract-init-copy{min-width:0;display:grid;gap:3px}.extract-init-copy strong{font-size:15px}.extract-init-copy span{color:var(--text-muted);font-size:13px;line-height:1.4}.extract-init-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px}.extract-init-chip{border:1px solid var(--border);border-radius:999px;background:#fff;color:var(--text-soft);font-size:12px;line-height:1;padding:6px 8px;white-space:nowrap}.extract-hero-panel{display:flex;align-items:center;gap:14px}.extract-hero-panel p,.extract-status-panel p,.extract-source-panel p{color:var(--text-muted);margin-top:5px}.extract-status-panel,.extract-source-panel{display:grid;gap:14px}.extract-profile-summary{display:grid;gap:10px;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted);padding:12px}.extract-profile-summary strong{color:var(--text);font-size:14px}.extract-profile-summary p{color:var(--text-muted);font-size:13px;line-height:1.5;margin:0}.extract-profile-summary .extract-init-actions{justify-content:flex-start}.extract-actions{display:flex;flex-wrap:wrap;align-items:center;gap:10px}.extract-source-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px}.extract-source-grid a{display:grid;gap:7px;color:inherit;text-decoration:none;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted);padding:8px}.extract-source-grid img{width:100%;aspect-ratio:3 / 4;object-fit:cover;object-position:top;border:1px solid var(--border);border-radius:6px;background:#fff}.extract-source-grid span{overflow:hidden;color:var(--text-soft);font-size:12px;white-space:nowrap;text-overflow:ellipsis}.extract-profile-dialog{width:min(720px,calc(100vw - 40px))}.extract-profile-fields{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.extract-focus-list{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.extract-focus-list>.field-label{flex:0 0 100%}.check-pill,.check-row{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--border);border-radius:999px;background:#fff;padding:7px 10px;color:#17201c;font-size:13px}.check-row{width:fit-content;margin-top:12px;border-radius:6px}.check-pill input,.check-row input{width:auto;min-height:0}.destructive-note{margin-top:12px;border:1px solid #d8aaa2;border-radius:6px;background:#fff7f5;color:var(--danger);padding:10px 12px;font-size:13px;line-height:1.55}.practice-workspace{display:grid;gap:16px}.workspace-title-panel{display:flex;align-items:center;gap:14px;min-height:96px}.workspace-title-panel button{flex:0 0 auto}.workspace-title-panel p{color:var(--text-muted);margin-top:5px}.paper-workspace-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,360px);gap:18px;align-items:start}.paper-main-column,.practice-side-rail{display:grid;gap:16px;align-content:start}.practice-side-rail{position:sticky;top:18px}.paper-toolbar{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.paper-toolbar p{color:var(--text-muted);margin-top:5px}.paper-toolbar-side{display:grid;gap:10px;justify-items:end;flex:0 0 auto}.paper-mode-switch{display:inline-grid;grid-template-columns:repeat(2,minmax(72px,1fr));gap:4px;padding:4px;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted)}.paper-mode-switch button{min-height:32px;border-color:transparent;background:transparent;padding:0 10px;white-space:nowrap}.paper-mode-switch button.selected{border-color:var(--green);background:#fff;color:var(--green);font-weight:700}.paper-preview-frame{height:min(78vh,900px);min-height:620px;border:1px solid var(--border);border-radius:8px;background:#f8faf7;overflow:hidden}.paper-preview-frame iframe{width:100%;height:100%;border:0;display:block;background:#fff}.create-practice-panel,.workflow-controls{display:grid;gap:12px}.workflow-controls{grid-template-columns:minmax(320px,1fr) minmax(150px,210px);align-items:end;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted);padding:12px}label{display:grid;gap:6px;color:#4b574f;font-size:13px}.field-hint{color:var(--text-muted);font-size:12px}.duration-field{display:grid;gap:6px}.field-label{color:#4b574f;font-size:13px;font-weight:700}.duration-options{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.duration-option{min-height:40px;padding:0 8px;white-space:nowrap;background:#fff}.duration-option.selected{border-color:var(--green);background:var(--green-soft);color:var(--green);font-weight:700}.first-round-progress{display:grid;gap:8px;padding:11px 12px;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted)}.first-round-progress .progress-copy strong{font-size:16px}.first-round-progress p{color:var(--text-muted);font-size:12px;line-height:1.5}.practice-links{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.paper-action-bar{display:grid;grid-template-columns:minmax(280px,1.35fr) minmax(150px,1fr) minmax(170px,1fr);gap:8px}.paper-page-switch{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);gap:6px;align-items:center;min-height:38px}.paper-page-switch button{min-height:38px;padding:0 10px}.paper-page-switch span{color:var(--text-muted);font-size:13px;font-weight:700;white-space:nowrap}.upload-strip{display:grid;gap:10px;padding:12px;border:1px solid var(--border);border-radius:8px;background:#fff}.upload-strip p{color:var(--text-muted);font-size:13px;margin-top:3px}.upload-strip .button-link{justify-self:start}.upload-file-actions{display:flex;flex-wrap:wrap;gap:8px}.upload-strip .danger-subtle{justify-self:start;color:var(--danger);border-color:#d8aaa2;background:#fff7f5}.upload-strip .danger-subtle:hover:not(:disabled){color:var(--danger);border-color:var(--danger);background:var(--danger-soft)}.full-width{width:100%}.card-note{border-left:3px solid var(--border-strong);padding-left:10px;font-size:13px}.job-line{display:grid;gap:8px;grid-column:1 / -1;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:9px 10px;color:#4b574f}.job-line-current{display:flex;align-items:center;gap:8px;min-width:0}.job-line-current span{min-width:0;overflow-wrap:anywhere}.job-progress-track{height:6px;overflow:hidden;border-radius:999px;background:#dfe7e1}.job-progress-track span{display:block;height:100%;border-radius:inherit;background:var(--green);transition:width .22s ease}.job-events{display:grid;gap:5px;margin:0;padding-left:24px;color:#6c746c;font-size:12px;line-height:1.45}.job-events li{overflow-wrap:anywhere}.job-line.failed{background:#fff0ed;color:var(--danger)}.job-line.failed .job-progress-track span{background:var(--danger)}.job-failure-hint{border-top:1px solid #ecc5bf;color:#8f3326;font-size:12px;line-height:1.45;padding-top:8px}.spin{animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.result-button,.result-actions{justify-self:start}.result-actions{display:flex;flex-wrap:wrap;gap:8px}.modal-backdrop{position:fixed;inset:0;z-index:50;display:grid;place-items:center;background:#17201c5c;padding:24px}.modal-panel{width:min(920px,100%);max-height:min(820px,calc(100vh - 48px));overflow:auto;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);box-shadow:0 24px 70px #15251f47;padding:16px}.modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:12px}.modal-panel .result-panel{border:0;box-shadow:none;padding:0}.profile-dialog{width:min(720px,100%);display:grid;gap:12px}.settings-dialog{width:min(680px,100%);display:grid;gap:12px}.profile-form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.profile-dialog label,.settings-dialog label{display:grid;gap:6px}.profile-dialog textarea{min-height:82px}.inline-check{display:flex!important;grid-template-columns:none;align-items:center;gap:8px;color:var(--text-muted)}.inline-check input{width:auto}.settings-status,.settings-path,.form-error{border:1px solid var(--border);border-radius:6px;padding:9px 10px;font-size:14px}.settings-status.configured{background:var(--green-soft);color:var(--green-dark)}.settings-status.missing,.form-error{background:var(--peach);color:var(--rust)}.settings-path{background:var(--surface-muted);color:var(--text-muted);word-break:break-all}.modal-actions{display:flex;justify-content:flex-end;gap:8px;padding-top:4px}.artifact-links{margin-top:12px;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:10px}.artifact-links h4{margin-bottom:8px}.artifact-links div{display:flex;flex-wrap:wrap;gap:8px}.artifact-links a{border:1px solid var(--border-strong);border-radius:999px;color:var(--green);background:var(--surface);padding:5px 10px;text-decoration:none;font-size:13px}.history-list{display:grid;gap:8px}.history-select-row{width:100%;display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px 10px;justify-content:stretch;text-align:left;border:1px solid var(--border);background:var(--surface-muted);padding:10px;min-height:62px}.history-select-row.selected{border-color:var(--green);background:var(--green-soft)}.history-select-row .flow-status{align-self:start}.history-select-row strong,.history-select-row span,.history-select-row small{min-width:0}.history-select-row strong,.history-select-row div>span{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.history-select-row small{grid-column:2;color:var(--text-muted)}.history-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto auto;gap:8px;align-items:center;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:10px}.history-row strong,.history-row span{display:block}.history-row div>span{color:var(--text-muted);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.empty-state{border:1px dashed var(--border-strong);border-radius:6px;color:var(--text-muted);padding:18px;background:var(--surface-muted)}.grading-table{display:grid;gap:8px;margin-top:12px}.grading-row{display:grid;grid-template-columns:60px 90px minmax(0,1fr);gap:10px;align-items:start;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:10px;text-align:left;width:100%}.grading-row p{color:#4b574f}.grading-row.selected{border-color:var(--green);background:var(--green-soft)}.grading-detail-card{display:grid;gap:8px;margin-top:12px;border:1px solid var(--border-strong);border-radius:8px;background:#fff;padding:12px}.grading-detail-card p{color:#4b574f}.weak-points{margin-top:14px;display:flex;flex-wrap:wrap;gap:8px;align-items:center}.weak-points h4{width:100%}.weak-points span{border-radius:999px;background:var(--rust-soft);color:#7f3a23;padding:4px 9px;font-size:12px}.weak-points p{color:var(--text-muted)}@media(max-width:1080px){.workspace,.nav-collapsed .workspace,.chapter-summary,.flow-grid,.paper-workspace-grid{grid-template-columns:1fr}.practice-side-rail{position:static}.chapter-nav{position:static;height:auto;max-height:320px}.chapter-nav.collapsed{max-height:54px}.chapter-nav.collapsed .chapter-nav-list{display:none}}@media(max-width:760px){.app-shell{padding:14px}.app-header,.workflow-head,.paper-toolbar,.workspace-title-panel{display:grid}.stats-grid,.stats-grid.compact,.practice-links,.paper-action-bar,.workflow-controls,.history-row,.profile-form-grid,.grading-row,.progress-copy,.extract-compact-panel,.workflow-entry-card{grid-template-columns:1fr}.extract-init-actions{justify-content:flex-start}.progress-stat-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.progress-copy{display:grid}.history-select-row small{grid-column:1}}
|
|
1
|
+
:root{color:#17201c;background:#eef2ef;font-family:Inter,PingFang SC,Microsoft YaHei,Arial,sans-serif;font-size:16px;--surface: #fffdf8;--surface-muted: #f5f7f2;--surface-cool: #edf4f0;--border: #d4ddd5;--border-strong: #b9c6be;--text-soft: #5f6c64;--text-muted: #738077;--green: #1f6455;--green-dark: #16483d;--green-soft: #dcece5;--rust: #91442f;--rust-soft: #f4ded1;--yellow-soft: #ece7bd;--danger: #872d23;--danger-soft: #f8d8d2}*{box-sizing:border-box}body{margin:0}button,input,textarea,select{font:inherit}button{min-height:38px;border:1px solid var(--border-strong);border-radius:6px;background:var(--surface);color:#17201c;padding:0 12px;display:inline-flex;align-items:center;justify-content:center;gap:8px;cursor:pointer;transition:background .14s ease,border-color .14s ease,color .14s ease,box-shadow .14s ease}.button-link,.entry-action-button{min-height:38px;border:1px solid var(--border-strong);border-radius:6px;color:#17201c;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:0 12px}button.primary{color:#fff;background:var(--green);border-color:var(--green)}button:hover:not(:disabled),.button-link:hover,.entry-action-button:hover{border-color:var(--green);background:var(--surface-cool)}button.primary:hover:not(:disabled){background:var(--green-dark);border-color:var(--green-dark)}button:focus-visible,.button-link:focus-visible,.entry-action-button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline:2px solid rgba(31,100,85,.28);outline-offset:2px}button:disabled,input:disabled,textarea:disabled,select:disabled{opacity:.55;cursor:not-allowed}input,textarea,select{width:100%;border:1px solid var(--border-strong);border-radius:6px;background:#fff;color:#17201c;min-height:38px;padding:8px 10px}textarea{min-height:72px;resize:vertical}h1,h2,h3,h4,p{margin:0}h1{font-size:32px;line-height:1.15}h2{font-size:22px}h3{font-size:18px}h4{font-size:15px}.app-shell{max-width:1480px;margin:0 auto;padding:24px}.app-header{display:flex;justify-content:space-between;align-items:center;gap:18px;margin-bottom:18px}.app-title-button{min-height:0;border:0;background:transparent;padding:0;color:inherit;justify-content:flex-start;text-align:left}.app-title-button:hover:not(:disabled){background:transparent;color:var(--green)}.profile-open-button{flex:0 0 auto}.settings-menu-wrap{position:relative;flex:0 0 auto}.settings-menu{position:absolute;top:calc(100% + 8px);right:0;z-index:40;min-width:150px;display:grid;gap:4px;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);box-shadow:0 18px 42px #16221d2e;padding:6px}.settings-menu button{width:100%;justify-content:flex-start;border-color:transparent;background:transparent}.settings-menu button:hover{border-color:var(--border);background:var(--surface-cool)}.app-header p,.workflow-head p,.section-heading p,.card-note{color:var(--text-muted);margin-top:5px}.eyebrow{color:var(--rust);font-size:12px;text-transform:uppercase;letter-spacing:0;font-weight:700}.toast{background:var(--green-dark);color:#fff;border-radius:6px;padding:10px 12px;margin-bottom:14px}.workspace{display:grid;grid-template-columns:292px minmax(0,1fr);gap:18px;align-items:start}.nav-collapsed .workspace{grid-template-columns:64px minmax(0,1fr)}.chapter-nav{position:sticky;top:16px;height:calc(100vh - 48px);overflow:hidden;border:1px solid var(--border);border-radius:8px;background:var(--surface);display:flex;flex-direction:column;box-shadow:0 10px 24px #24312a0f}.chapter-nav-head{min-height:54px;padding:10px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;gap:8px}.chapter-nav-list{padding:8px;overflow:auto;display:grid;gap:5px}.chapter-nav-item{width:100%;justify-content:flex-start;min-height:42px;padding:6px 8px;background:transparent;border-color:transparent}.chapter-nav.collapsed .chapter-nav-head,.chapter-nav.collapsed .chapter-nav-item{justify-content:center}.chapter-nav-item.selected{border-color:var(--green);background:var(--green-soft)}.chapter-index{width:24px;flex:0 0 auto;color:var(--rust);font-weight:700;font-size:12px}.chapter-name{flex:1;min-width:0;text-align:left;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.chapter-status,.flow-status{flex:0 0 auto;border-radius:999px;background:#e4e9e2;color:#536057;padding:3px 8px;font-size:12px;white-space:nowrap}.chapter-status.in_progress,.flow-status.generated,.flow-status.previewed,.flow-status.printed,.flow-status.submitted,.flow-status.pdf_received{background:#f2d9c8;color:#7f3a23}.chapter-status.review_due,.flow-status.graded,.flow-status.needs_review{background:var(--yellow-soft);color:#645600}.chapter-status.mastered,.flow-status.archived{background:#cfe8da;color:var(--green)}.flow-status.failed,.flow-status.failed_generate,.flow-status.failed_grade{background:var(--danger-soft);color:var(--danger)}.flow-status.available{background:var(--green-soft);color:var(--green)}.flow-status.missing{background:#fff6d7;color:#7a5a0f}.flow-status.missing_source,.flow-status.unavailable{background:#e7ece8;color:var(--text-muted)}.icon-button{width:38px;padding:0}.chapter-workspace{min-width:0}.panel{background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:18px;margin-bottom:16px;box-shadow:0 10px 24px #24312a0d}.chapter-summary{display:grid;grid-template-columns:minmax(250px,1fr) minmax(400px,1.2fr);gap:16px;align-items:end}.stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}.stats-grid.compact{grid-template-columns:repeat(5,minmax(0,1fr))}.stat-tile{border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:12px}.stat-tile span{color:var(--text-muted);font-size:13px}.stat-tile strong{display:block;margin-top:6px;font-size:22px}.knowledge-map-panel{display:grid;gap:16px}.knowledge-map-head{display:flex;justify-content:space-between;gap:16px;align-items:start}.knowledge-view-tabs{display:inline-flex;gap:4px;padding:4px;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted)}.knowledge-view-tabs button{min-height:34px;border-color:transparent;background:transparent;white-space:nowrap}.knowledge-view-tabs button.selected{color:var(--green);border-color:var(--green);background:#fff;font-weight:700}.knowledge-map-summary{display:flex;flex-wrap:wrap;gap:10px;color:var(--text-soft);font-size:13px}.knowledge-map-summary span{display:inline-flex;align-items:center;gap:6px}.knowledge-filter-group{display:inline-flex;gap:4px;padding:2px;border:1px solid var(--border);border-radius:999px;background:var(--surface-muted)}.knowledge-filter-group button{min-height:26px;border-radius:999px;border-color:transparent;background:transparent;padding:0 10px;font-size:12px}.knowledge-filter-group button.selected{color:#fff;background:var(--green);border-color:var(--green)}.legend-dot{width:10px;height:10px;border:1px solid var(--border-strong);border-radius:999px;background:#fff}.legend-dot.mastered{background:#bfe1cf;border-color:var(--green)}.legend-dot.needs_review{background:var(--yellow-soft);border-color:#c6b85d}.knowledge-wall{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px}.knowledge-card{min-height:132px;display:grid;align-content:space-between;gap:10px;border:1px solid var(--border);border-radius:8px;padding:12px;background:#fff}.knowledge-card.mastered{border-color:#94bca8;background:#edf7f1}.knowledge-card.needs_review{border-color:#d7cb76;background:#fff9d9}.knowledge-card.uncovered{background:#fff}.knowledge-card strong{display:block;line-height:1.35}.knowledge-card span{color:var(--text-muted);font-size:12px}.knowledge-card p{color:var(--text-soft);font-size:13px;line-height:1.55}.knowledge-card-foot{display:flex;justify-content:space-between;gap:8px;align-items:center}.knowledge-card-foot small{color:var(--text-muted)}.knowledge-market-layout{display:block}.knowledge-market-board{position:relative;display:grid;grid-template-columns:repeat(auto-fill,minmax(82px,1fr));grid-auto-flow:dense;gap:1px;padding:4px;border:0;border-radius:8px;background:#20342e}.knowledge-market-tile{--tile-bg: #fffdf8;--tile-fg: #17201c;--tile-muted: #627167;position:relative;min-height:54px;display:grid;place-items:center;gap:2px;padding:6px;border-radius:3px;text-align:center;color:var(--tile-fg);background:var(--tile-bg);border:0;box-shadow:none}.knowledge-market-tile:hover:not(:disabled){z-index:40;background:var(--tile-bg);border-color:transparent;filter:brightness(.96)}.knowledge-market-tile:focus-visible{z-index:40;outline:2px solid rgba(31,100,85,.42);outline-offset:1px}.knowledge-market-tile strong{width:100%;font-size:12.5px;line-height:1.22;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.knowledge-hover-card span{color:var(--tile-muted);font-size:11px;line-height:1.1}.knowledge-market-tile.mastered{--tile-bg: #1f9d5b;--tile-fg: #ffffff;--tile-muted: rgba(255, 255, 255, .82)}.knowledge-market-tile.needs_review{--tile-bg: #f3dc61;--tile-fg: #17201c;--tile-muted: #5d612f}.knowledge-market-tile.review-low{--tile-bg: #f8e986;--tile-muted: #667044}.knowledge-market-tile.review-mid{--tile-bg: #efd347;--tile-muted: #5b5f2b}.knowledge-market-tile.review-high{--tile-bg: #d49a22;--tile-muted: #443a17}.knowledge-market-tile.uncovered{--tile-bg: #fffdf8;--tile-fg: #17201c;--tile-muted: #738077}.knowledge-hover-card{position:absolute;left:0;top:calc(100% + 6px);z-index:80;width:min(320px,70vw);display:none;gap:7px;border:1px solid var(--border-strong);border-radius:8px;background:#fffdf8;color:#17201c;box-shadow:0 18px 46px #16221d42;padding:12px;text-align:left}.knowledge-market-tile:hover .knowledge-hover-card,.knowledge-market-tile:focus-visible .knowledge-hover-card{display:grid}.knowledge-hover-card strong{font-size:15px;line-height:1.35;display:block}.knowledge-hover-card em{color:var(--text-soft);font-style:normal;font-size:13px;line-height:1.55}.knowledge-hover-card>span{color:var(--text-muted);font-size:12px}.knowledge-image-board{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px}.knowledge-page-card{display:grid;grid-template-columns:110px minmax(0,1fr);gap:12px;border:1px solid var(--border);border-radius:8px;background:#fff;padding:10px}.knowledge-page-card img{width:100%;height:150px;object-fit:cover;object-position:top;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted)}.knowledge-page-card strong{display:block;margin-bottom:3px}.knowledge-page-card p{color:var(--text-muted);font-size:13px;margin-bottom:8px}.page-point-list{display:flex;flex-wrap:wrap;gap:6px}.point-pill{border:1px solid var(--border-strong);border-radius:999px;background:#fff;padding:4px 8px;color:var(--text-soft);font-size:12px}.point-pill.mastered{border-color:#94bca8;background:#edf7f1;color:var(--green)}.point-pill.needs_review{border-color:#d7cb76;background:#fff9d9;color:#645600}.flow-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:10px}.active-paper-panel,.result-panel{display:grid;gap:14px;align-content:start}.workflow-entry-card{width:100%;min-height:72px;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;justify-content:stretch;text-align:left;padding:12px 14px;gap:14px;background:#fff;border:1px solid var(--border-strong);border-radius:6px}.workflow-entry-card.disabled{background:#f1f4f0;border-color:var(--border)}.workflow-head,.section-heading{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.section-heading{justify-content:flex-start;margin-bottom:12px}.section-heading svg{color:var(--green);margin-top:1px}.subtle-icon-button{width:34px;min-height:34px;margin-left:auto;padding:0;border-color:transparent;background:transparent;color:var(--text-muted)}.subtle-icon-button:hover:not(:disabled){border-color:var(--border);background:var(--surface-cool);color:var(--green)}.overview-actions{display:grid;gap:12px}.practice-entry-strip{display:grid;gap:10px;padding:14px}.practice-entry-strip .section-heading{margin-bottom:0}.practice-entry-strip .workflow-entry-card{min-height:60px;padding:12px;background:#fbfdf9}.practice-entry-strip .workflow-entry-card>div:first-child strong{font-size:15px}.practice-entry-strip .workflow-entry-card small{display:none}.practice-overview-progress{display:grid;gap:12px;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:14px}.progress-copy{display:flex;align-items:baseline;justify-content:space-between;gap:12px}.progress-copy span,.workflow-entry-card small{color:var(--text-muted);font-size:13px}.progress-copy strong{font-size:18px}.progress-track{height:8px;overflow:hidden;border-radius:999px;background:#dfe7e1}.progress-track span{display:block;height:100%;border-radius:inherit;background:var(--green)}.progress-stat-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.progress-stat-grid .stat-tile{padding:10px}.progress-stat-grid .stat-tile strong{font-size:20px}.practice-stat-line{display:flex;flex-wrap:wrap;gap:8px}.practice-stat-line span{border:1px solid var(--border);border-radius:999px;background:#fff;color:var(--text-soft);font-size:12px;padding:5px 9px}.workflow-entry-card>div:first-child{min-width:0;display:grid;gap:3px}.workflow-entry-card>div:first-child strong{font-size:16px}.entry-action-cluster{min-width:max-content;display:flex;align-items:center;justify-content:flex-end;gap:10px}.entry-action-button{min-width:104px;color:#fff;background:var(--green);border-color:var(--green);font-weight:700;white-space:nowrap;padding:0 12px 0 14px;box-shadow:0 4px 10px #1f645524;transition:background .14s ease,border-color .14s ease,color .14s ease,box-shadow .14s ease,transform .14s ease}.entry-action-button svg{margin-right:-3px}.entry-action-button:hover{color:#fff;background:var(--green-dark);border-color:var(--green-dark);box-shadow:0 6px 14px #1f645533;transform:translateY(-1px)}.entry-action-button.disabled{color:var(--text-muted);background:#e7ece8;border-color:var(--border);box-shadow:none;pointer-events:none}.extract-workspace{display:grid;gap:16px;scroll-margin-top:16px}.extract-compact-panel{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;padding:12px 14px}.extract-init-copy{min-width:0;display:grid;gap:3px}.extract-init-copy strong{font-size:15px}.extract-init-copy span{color:var(--text-muted);font-size:13px;line-height:1.4}.extract-init-actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:8px}.extract-init-chip{border:1px solid var(--border);border-radius:999px;background:#fff;color:var(--text-soft);font-size:12px;line-height:1;padding:6px 8px;white-space:nowrap}.extract-hero-panel{display:flex;align-items:center;gap:14px}.extract-hero-panel p,.extract-status-panel p,.extract-source-panel p{color:var(--text-muted);margin-top:5px}.extract-status-panel,.extract-source-panel{display:grid;gap:14px}.extract-profile-summary{display:grid;gap:10px;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted);padding:12px}.extract-profile-summary strong{color:var(--text);font-size:14px}.extract-profile-summary p{color:var(--text-muted);font-size:13px;line-height:1.5;margin:0}.extract-profile-summary .extract-init-actions{justify-content:flex-start}.extract-actions{display:flex;flex-wrap:wrap;align-items:center;gap:10px}.extract-source-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px}.extract-source-grid a{display:grid;gap:7px;color:inherit;text-decoration:none;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted);padding:8px}.extract-source-grid img{width:100%;aspect-ratio:3 / 4;object-fit:cover;object-position:top;border:1px solid var(--border);border-radius:6px;background:#fff}.extract-source-grid span{overflow:hidden;color:var(--text-soft);font-size:12px;white-space:nowrap;text-overflow:ellipsis}.extract-profile-dialog{width:min(720px,calc(100vw - 40px))}.extract-profile-fields{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.extract-focus-list{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.extract-focus-list>.field-label{flex:0 0 100%}.check-pill,.check-row{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--border);border-radius:999px;background:#fff;padding:7px 10px;color:#17201c;font-size:13px}.check-row{width:fit-content;margin-top:12px;border-radius:6px}.check-pill input,.check-row input{width:auto;min-height:0}.destructive-note{margin-top:12px;border:1px solid #d8aaa2;border-radius:6px;background:#fff7f5;color:var(--danger);padding:10px 12px;font-size:13px;line-height:1.55}.practice-workspace{display:grid;gap:16px}.practice-workspace-head{display:flex;align-items:center;padding:0 0 4px}.back-to-overview{font-size:14px;color:var(--green);border:1px solid var(--border);padding:6px 16px 6px 12px}.back-to-overview:hover{background:var(--green-soft);border-color:var(--green)}.workspace-title-panel{display:flex;align-items:center;gap:14px;min-height:96px}.workspace-title-panel button{flex:0 0 auto}.workspace-title-panel p{color:var(--text-muted);margin-top:5px}.paper-workspace-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,360px);gap:18px;align-items:start}.paper-main-column,.practice-side-rail{display:grid;gap:16px;align-content:start}.practice-side-rail{position:sticky;top:18px}.paper-toolbar{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.paper-toolbar p{color:var(--text-muted);margin-top:5px}.paper-toolbar-side{display:grid;gap:10px;justify-items:end;flex:0 0 auto}.paper-mode-switch{display:inline-grid;grid-template-columns:repeat(2,minmax(72px,1fr));gap:4px;padding:4px;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted)}.paper-mode-switch button{min-height:32px;border-color:transparent;background:transparent;padding:0 10px;white-space:nowrap}.paper-mode-switch button.selected{border-color:var(--green);background:#fff;color:var(--green);font-weight:700}.paper-preview-frame{height:min(78vh,900px);min-height:620px;border:1px solid var(--border);border-radius:8px;background:#f8faf7;overflow:hidden}.paper-preview-frame iframe{width:100%;height:100%;border:0;display:block;background:#fff}.create-practice-panel,.workflow-controls{display:grid;gap:12px}.workflow-controls{grid-template-columns:minmax(320px,1fr) minmax(150px,210px);align-items:end;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted);padding:12px}label{display:grid;gap:6px;color:#4b574f;font-size:13px}.field-hint{color:var(--text-muted);font-size:12px}.duration-field{display:grid;gap:6px}.field-label{color:#4b574f;font-size:13px;font-weight:700}.duration-options{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.duration-option{min-height:40px;padding:0 8px;white-space:nowrap;background:#fff}.duration-option.selected{border-color:var(--green);background:var(--green-soft);color:var(--green);font-weight:700}.first-round-progress{display:grid;gap:8px;padding:11px 12px;border:1px solid var(--border);border-radius:8px;background:var(--surface-muted)}.first-round-progress .progress-copy strong{font-size:16px}.first-round-progress p{color:var(--text-muted);font-size:12px;line-height:1.5}.practice-links{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.paper-action-bar{display:grid;grid-template-columns:minmax(280px,1.35fr) minmax(150px,1fr) minmax(170px,1fr);gap:8px}.paper-page-switch{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);gap:6px;align-items:center;min-height:38px}.paper-page-switch button{min-height:38px;padding:0 10px}.paper-page-switch span{color:var(--text-muted);font-size:13px;font-weight:700;white-space:nowrap}.upload-strip{display:grid;gap:10px;padding:12px;border:1px solid var(--border);border-radius:8px;background:#fff}.upload-strip p{color:var(--text-muted);font-size:13px;margin-top:3px}.upload-strip .button-link{justify-self:start}.upload-file-actions{display:flex;flex-wrap:wrap;gap:8px}.upload-strip .danger-subtle{justify-self:start;color:var(--danger);border-color:#d8aaa2;background:#fff7f5}.upload-strip .danger-subtle:hover:not(:disabled){color:var(--danger);border-color:var(--danger);background:var(--danger-soft)}.full-width{width:100%}.card-note{border-left:3px solid var(--border-strong);padding-left:10px;font-size:13px}.job-line{display:grid;gap:8px;grid-column:1 / -1;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:9px 10px;color:#4b574f}.job-line-current{display:flex;align-items:center;gap:8px;min-width:0}.job-line-current span{min-width:0;overflow-wrap:anywhere}.job-progress-track{height:6px;overflow:hidden;border-radius:999px;background:#dfe7e1}.job-progress-track span{display:block;height:100%;border-radius:inherit;background:var(--green);transition:width .22s ease}.job-events{display:grid;gap:5px;margin:0;padding-left:24px;color:#6c746c;font-size:12px;line-height:1.45}.job-events li{overflow-wrap:anywhere}.job-line.failed{background:#fff0ed;color:var(--danger)}.job-line.failed .job-progress-track span{background:var(--danger)}.job-failure-hint{border-top:1px solid #ecc5bf;color:#8f3326;font-size:12px;line-height:1.45;padding-top:8px}.spin{animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.result-button,.result-actions{justify-self:start}.result-actions{display:flex;flex-wrap:wrap;gap:8px}.modal-backdrop{position:fixed;inset:0;z-index:50;display:grid;place-items:center;background:#17201c5c;padding:24px}.modal-panel{width:min(920px,100%);max-height:min(820px,calc(100vh - 48px));overflow:auto;border:1px solid var(--border-strong);border-radius:8px;background:var(--surface);box-shadow:0 24px 70px #15251f47;padding:16px}.modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;margin-bottom:12px}.modal-panel .result-panel{border:0;box-shadow:none;padding:0}.profile-dialog{width:min(720px,100%);display:grid;gap:12px}.settings-dialog{width:min(680px,100%);display:grid;gap:12px}.profile-form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.profile-dialog label,.settings-dialog label{display:grid;gap:6px}.profile-dialog textarea{min-height:82px}.inline-check{display:flex!important;grid-template-columns:none;align-items:center;gap:8px;color:var(--text-muted)}.inline-check input{width:auto}.settings-status,.settings-path,.form-error{border:1px solid var(--border);border-radius:6px;padding:9px 10px;font-size:14px}.settings-status.configured{background:var(--green-soft);color:var(--green-dark)}.settings-status.missing,.form-error{background:var(--peach);color:var(--rust)}.settings-path{background:var(--surface-muted);color:var(--text-muted);word-break:break-all}.modal-actions{display:flex;justify-content:flex-end;gap:8px;padding-top:4px}.artifact-links{margin-top:12px;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:10px}.artifact-links h4{margin-bottom:8px}.artifact-links div{display:flex;flex-wrap:wrap;gap:8px}.artifact-links a{border:1px solid var(--border-strong);border-radius:999px;color:var(--green);background:var(--surface);padding:5px 10px;text-decoration:none;font-size:13px}.history-list{display:grid;gap:8px}.history-select-row{width:100%;display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px 10px;justify-content:stretch;text-align:left;border:1px solid var(--border);background:var(--surface-muted);padding:10px;min-height:62px}.history-select-row.selected{border-color:var(--green);background:var(--green-soft)}.history-select-row .flow-status{align-self:start}.history-select-row strong,.history-select-row span,.history-select-row small{min-width:0}.history-select-row strong,.history-select-row div>span{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.history-select-row small{grid-column:2;color:var(--text-muted)}.history-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto auto;gap:8px;align-items:center;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:10px}.history-row strong,.history-row span{display:block}.history-row div>span{color:var(--text-muted);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.empty-state{border:1px dashed var(--border-strong);border-radius:6px;color:var(--text-muted);padding:18px;background:var(--surface-muted)}.grading-table{display:grid;gap:8px;margin-top:12px}.grading-row{display:grid;grid-template-columns:60px 90px minmax(0,1fr);gap:10px;align-items:start;border:1px solid var(--border);border-radius:6px;background:var(--surface-muted);padding:10px;text-align:left;width:100%}.grading-row p{color:#4b574f}.grading-row.selected{border-color:var(--green);background:var(--green-soft)}.grading-detail-card{display:grid;gap:8px;margin-top:12px;border:1px solid var(--border-strong);border-radius:8px;background:#fff;padding:12px}.grading-detail-card p{color:#4b574f}.weak-points{margin-top:14px;display:flex;flex-wrap:wrap;gap:8px;align-items:center}.weak-points h4{width:100%}.weak-points span{border-radius:999px;background:var(--rust-soft);color:#7f3a23;padding:4px 9px;font-size:12px}.weak-points p{color:var(--text-muted)}@media(max-width:1080px){.workspace,.nav-collapsed .workspace,.chapter-summary,.flow-grid,.paper-workspace-grid{grid-template-columns:1fr}.practice-side-rail{position:static}.chapter-nav{position:static;height:auto;max-height:320px}.chapter-nav.collapsed{max-height:54px}.chapter-nav.collapsed .chapter-nav-list{display:none}}@media(max-width:760px){.app-shell{padding:14px}.app-header,.workflow-head,.paper-toolbar,.workspace-title-panel{display:grid}.stats-grid,.stats-grid.compact,.practice-links,.paper-action-bar,.workflow-controls,.history-row,.profile-form-grid,.grading-row,.progress-copy,.extract-compact-panel,.workflow-entry-card{grid-template-columns:1fr}.extract-init-actions{justify-content:flex-start}.progress-stat-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.progress-copy{display:grid}.history-select-row small{grid-column:1}}.setup-wizard{display:flex;align-items:center;justify-content:center;min-height:100vh;min-height:100dvh;padding:24px 16px;background:linear-gradient(160deg,#eef2ef,#edf4f0,#e8efe6)}.setup-card{width:100%;max-width:600px;background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:0 4px 24px #17201c14;padding:32px 28px;display:flex;flex-direction:column;gap:20px}.setup-head{text-align:center}.setup-head h1{margin:0 0 8px;font-size:1.5rem;color:var(--green-dark);letter-spacing:.02em}.setup-head p{margin:0;color:var(--text-soft);font-size:.95rem;line-height:1.5}.setup-section-title{margin:0 0 12px;font-size:1.05rem;font-weight:600;color:var(--green);padding-bottom:8px;border-bottom:1px solid var(--green-soft)}.setup-section{display:flex;flex-direction:column;gap:12px}.setup-card .profile-form-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px}.setup-card label{display:flex;flex-direction:column;gap:4px}.setup-card .field-label{font-size:.85rem;font-weight:500;color:var(--text-soft)}.setup-card input,.setup-card textarea{border:1px solid var(--border);border-radius:6px;padding:8px 10px;font-size:.95rem;background:var(--surface-muted);color:inherit;transition:border-color .14s ease}.setup-card input:focus,.setup-card textarea:focus{border-color:var(--green);outline:none;background:var(--surface)}.setup-card textarea{min-height:64px;resize:vertical}.setup-hint{margin:0;font-size:.85rem;color:var(--text-muted);line-height:1.5}.setup-hint code{background:var(--green-soft);padding:1px 5px;border-radius:4px;font-size:.8rem}.setup-actions{display:flex;justify-content:center;padding-top:4px}.setup-submit{min-width:160px;padding:10px 28px;font-size:1.05rem;font-weight:600}@media(max-width:520px){.setup-card .profile-form-grid{grid-template-columns:1fr}.setup-card{padding:24px 18px}}
|