/* Auto Researcher — design system v3 ("Nymphéas")
   Layout: one calm reading column; phases on a rail, the current decision as the hero, outputs as cards.
   Palette after Monet's water lilies: mist paper and violet-ink type; pond blue marks progress and links,
   lilac marks work in motion, low-sun gold marks "your decision". No signal green anywhere in the chrome.

   Rules for every component below:
   - Colour. Gold (--gate, --gate-soft, --highlight) appears only where the user can act now, plus a thin gold
     rule on records of decisions the user already made. --warn (rust) is for real cautions only: ethics or
     high risk, GPU server offline, a skipped experiment, a sample flag, failed soft checks, budget near its cap.
     Inconclusive, untested, paused, demo and to-do states are neutral (surface-2/3, text-2, border-strong;
     dashed when the state is provisional). Charts and mini-bars use only --series-1…4. No green token exists.
   - Type. var(--display) for page and section titles, var(--font) for all UI text and numbers (add
     font-variant-numeric: tabular-nums for figures). var(--mono) only for code, hypothesis, dataset and job IDs,
     and citation keys. Eyebrow labels are sans in sentence case; English alone adds uppercase and tracking
     (see the :lang(en) rule under "workspace").
   - Wrapping. Headings balance, body copy wraps "pretty" (no one-character last lines). Fixed-copy Chinese
     headings go through the `phrases` filter so they break between clauses (.ph). */
:root {
  --bg: #f4f5f9;
  --surface: #ffffff;
  --surface-2: #eef1f7;
  --surface-3: #e2e7f0;
  --text: #262a4a;
  --text-2: #4b5072;
  --muted: #6c7193;
  --border: #e0e4ee;
  --border-strong: #cbd2e1;
  --accent: #3e66a3;
  --accent-2: #2f5791;
  --accent-soft: #e6edf8;
  --accent-ink: #ffffff;
  --glow: #8a7fd6;
  /* lilac ink and wash for work in motion (the 进行中 pill), matching the run card's dot and eyebrow */
  --glow-ink: #5b4fae;
  --glow-soft: #eeebfa;
  /* the outline of a decision option (dusk mixes in --muted so the container stays visible) */
  --opt-border: var(--border-strong);
  --success: #3e66a3;
  --success-soft: #e6edf8;
  --gate: #86610f;
  --gate-soft: #fbf1d6;
  --highlight: #e9bd5f;
  /* warn is rust, well apart from the decision gold and from the rose of danger */
  --warn: #9c4c2a;
  --warn-soft: #f6e6dc;
  --danger: #b84b66;
  --danger-soft: #f8e3e9;
  --code-bg: #eef1f7;
  /* chart series: pond, lilac, rose, slate (engine/subjects.py _PALETTE uses the same values) */
  --series-1: #5679b4;
  --series-2: #8f7fc8;
  --series-3: #d9798c;
  --series-4: #7d8599;
  --shadow: 0 1px 2px rgba(38, 42, 74, .05), 0 8px 24px rgba(38, 42, 74, .06);
  --shadow-lg: 0 2px 6px rgba(38, 42, 74, .05), 0 30px 80px rgba(52, 62, 110, .16);
  --radius: 14px;
  --radius-sm: 9px;
  --font: "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif;
  /* CJK has no glyphs in these monospace fonts: fall back to a sans face, not the browser's serif default */
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Code", Consolas, "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif;
  --serif: "Iowan Old Style", "Palatino Linotype", Georgia, "Songti SC", "SimSun", serif;
  /* page and section titles: Instrument Serif for Latin, Noto Serif SC (loaded in base.html) for Chinese */
  --display: "Instrument Serif", "Noto Serif SC", "Songti SC", "STSong", Georgia, serif;
  --ease: cubic-bezier(.2, .8, .2, 1);
  color-scheme: light;
}
/* Chinese UI: Noto Serif SC first, so Latin letters and digits in headlines match the CJK weight.
   English keeps Instrument Serif; landing.css sets its own --display for the public pages. */
html:lang(zh) { --display: "Noto Serif SC", "Songti SC", "STSong", Georgia, serif; }
/* Night: the same pond at dusk — deep blue-violet water, moonlit text, the gold kept for decisions */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #10121c; --surface: #171a28; --surface-2: #1d2133; --surface-3: #272c42;
    --text: #e9eaf4; --text-2: #b9bdd3; --muted: #8a8fab; --border: #23283b; --border-strong: #33394f;
    --accent: #8fb0ea; --accent-2: #a9c3f0; --accent-soft: #1f2a45; --accent-ink: #0d1020; --glow: #b4a6ee;
    --glow-ink: #c4b9f3; --glow-soft: #25223d;
    --success: #8fb0ea; --success-soft: #1f2a45; --gate: #f0cb74; --gate-soft: #2d2715; --highlight: #f0cb74;
    --warn: #ee9878; --warn-soft: #34211b; --danger: #f08ba0; --danger-soft: #331b24; --code-bg: #1d2133;
    --series-1: #5679b4; --series-2: #8f7fc8; --series-3: #d9798c; --series-4: #7d8599;
    --shadow: 0 1px 2px rgba(0, 0, 0, .35); --shadow-lg: 0 24px 60px rgba(0, 0, 0, .5);
    /* decision options keep a visible container at dusk */
    --opt-border: color-mix(in srgb, var(--muted) 45%, var(--border-strong));
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --opt-border: color-mix(in srgb, var(--muted) 45%, var(--border-strong));
  --bg: #10121c; --surface: #171a28; --surface-2: #1d2133; --surface-3: #272c42;
  --text: #e9eaf4; --text-2: #b9bdd3; --muted: #8a8fab; --border: #23283b; --border-strong: #33394f;
  --accent: #8fb0ea; --accent-2: #a9c3f0; --accent-soft: #1f2a45; --accent-ink: #0d1020; --glow: #b4a6ee;
  --glow-ink: #c4b9f3; --glow-soft: #25223d;
  --success: #8fb0ea; --success-soft: #1f2a45; --gate: #f0cb74; --gate-soft: #2d2715; --highlight: #f0cb74;
  --warn: #ee9878; --warn-soft: #34211b; --danger: #f08ba0; --danger-soft: #331b24; --code-bg: #1d2133;
  --series-1: #5679b4; --series-2: #8f7fc8; --series-3: #d9798c; --series-4: #7d8599;
  --shadow: 0 1px 2px rgba(0, 0, 0, .35); --shadow-lg: 0 24px 60px rgba(0, 0, 0, .5);
  color-scheme: dark;
}

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; background: var(--bg); color: var(--text); font: 15px/1.6 var(--font); -webkit-font-smoothing: antialiased; overflow-x: hidden; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }
h1, h2, h3, h4 { line-height: 1.2; margin: 0 0 .5em; letter-spacing: -.02em; font-weight: 600; text-wrap: balance; }
h1 { font-size: 2rem; } h2 { font-size: 1.4rem; } h3 { font-size: 1.05rem; } h4 { font-size: .95rem; }
/* Page-level titles share the homepage's display serif; everything inside the UI stays in the sans */
.page-head h1, .compose-title, .ws-title h1, .focus-title, .drawer-head h2, .auth-card h2 { font-family: var(--display); font-weight: 500; letter-spacing: -.005em; }
p { margin: 0 0 .9em; }
/* body copy: no one-character / one-word last lines; headings keep balance (pretty would split CJK words) */
p, li, dd, figcaption, .alert, .lead { text-wrap: pretty; }
code, pre { font-family: var(--mono); font-size: .86em; }
code { background: var(--code-bg); padding: .1em .35em; border-radius: 5px; }
pre { background: var(--code-bg); padding: 12px 14px; border-radius: var(--radius-sm); overflow-x: auto; line-height: 1.5; }
pre code { background: none; padding: 0; }
img { max-width: 100%; }
::selection { background: var(--highlight); color: #1a1400; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

.container { width: 100%; max-width: 1120px; margin: 0 auto; padding-inline: 20px; }
.container.narrow { max-width: 760px; }
.container.read { max-width: 860px; }
.muted { color: var(--muted); }
.small { font-size: .87rem; }
.tiny { font-size: .78rem; }
.mono { font-family: var(--mono); font-feature-settings: "zero" 0; }
.num { font-variant-numeric: tabular-nums; }
.row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.row.between { justify-content: space-between; }
.stack > * + * { margin-top: 12px; }
.grid { display: grid; gap: 16px; }
.grid.cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid.cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 900px) { .grid.cols-3, .grid.cols-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .grid.cols-2, .grid.cols-3, .grid.cols-4 { grid-template-columns: 1fr; } }
.hidden { display: none !important; }
/* eyebrow labels: sans, sentence case; English adds uppercase and tracking (the :lang(en) rule below) */
.kicker, .eyebrow-mono { font: 600 .74rem/1.4 var(--font); color: var(--muted); margin-bottom: 8px; }
.hl { background: linear-gradient(transparent 58%, var(--highlight) 58%, var(--highlight) 92%, transparent 92%); color: inherit; padding-inline: .08em; }

/* ---------- motion ---------- */
@keyframes rise { from { transform: translateY(8px); opacity: .001; } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--c, var(--glow)) 55%, transparent); } 70% { box-shadow: 0 0 0 9px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
@keyframes blink { 50% { opacity: .35; } }
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@keyframes flow { to { background-position: 28px 0; } }
@keyframes breathe { 50% { box-shadow: 0 0 0 1px color-mix(in srgb, var(--highlight) 70%, transparent), 0 10px 40px color-mix(in srgb, var(--highlight) 22%, transparent); } }
.rise { animation: rise .5s var(--ease) both; }
.rise:nth-child(2) { animation-delay: .05s; } .rise:nth-child(3) { animation-delay: .1s; } .rise:nth-child(4) { animation-delay: .15s; }
.shimmer { background: linear-gradient(90deg, var(--text-2) 0%, var(--text-2) 40%, var(--glow) 50%, var(--text-2) 60%, var(--text-2) 100%);
  background-size: 200% 100%; -webkit-background-clip: text; background-clip: text; color: transparent; animation: shimmer 2.8s linear infinite; }
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } .shimmer { color: var(--text-2); background: none; } }

/* ---------- nav ---------- */
/* anchors (/#pricing) land below the 56px sticky bar */
html { scroll-padding-top: 72px; }
/* opaque: no body text, gold button or chart bar ever reads through the bar */
.nav { position: sticky; top: env(safe-area-inset-top, 0px); z-index: 30; background: var(--bg);
  -webkit-backdrop-filter: none; backdrop-filter: none; border-bottom: 1px solid color-mix(in srgb, var(--border) 70%, transparent); }
.nav .container { display: flex; align-items: center; gap: 26px; height: 56px; }
.brand { display: flex; align-items: center; gap: 9px; font-weight: 600; color: var(--text); letter-spacing: -.01em; white-space: nowrap; }
.brand:hover { text-decoration: none; }
.brand .logo { width: 24px; height: 24px; flex: none; }
.nav-links { display: flex; gap: 22px; flex: 1; }
.nav-links a { color: var(--text-2); font-size: .9rem; }
.nav-links a:hover, .nav-links a.on { color: var(--text); text-decoration: none; }
.nav-links a.on { font-weight: 600; }
.nav-right { display: flex; gap: 8px; align-items: center; }
.nav form { margin: 0; }
.m-only { display: none; }
/* the phone menu of public pages (base.html); hidden on wider screens, where the links sit in the bar */
.nav-menu { display: none; }
.nav-menu > summary { list-style: none; cursor: pointer; gap: 5px; }
.nav-menu > summary::-webkit-details-marker { display: none; }
.nav-menu .chev { transition: transform .15s; }
.nav-menu[open] > summary { background: var(--surface-2); }
.nav-menu[open] .chev { transform: rotate(180deg); }
.nav-menu .menu-pop { min-width: 220px; top: calc(100% + 8px); }
.nav-menu .menu-pop a, .nav-menu .menu-pop button { min-height: 44px; font-size: .95rem; }
.nav-menu .menu-pop form { margin: 0; }
@media (max-width: 760px) {
  .nav .container { gap: 10px; justify-content: space-between; }
  .nav-links:not(.in-app) { display: none; }
  /* in the app, phones keep one compact '← 我的研究' (not on the dashboard, nor on a study page, whose header has one) */
  .nav-links.in-app { flex: 1; gap: 0; min-width: 0; }
  .nav-links.in-app a { font-size: .875rem; white-space: nowrap; }
  .nav-links.in-app a.on, .nav-links.in-app a.ws-skip { display: none; }
  .m-only { display: inline; }
  .nav-menu { display: block; }
  .nav .nav-collapse { display: none; }
  /* comfortable tap targets; the 56px bar has room for 40px */
  .nav .btn.sm { height: 40px; padding: 0 14px; }
}
/* Narrow phones: the logo alone stands for the brand only where the name does not fit (the link keeps its
   aria-label). English labels are longer, so the English bar gives the name up first. */
@media (max-width: 420px) { html:lang(en) .nav .brand-name { display: none; } .nav-right { gap: 4px; } }
@media (max-width: 359px) { .nav .brand-name { display: none; } }
/* the app bar holds more buttons (new study, sign out) and gives the name up earlier */
@media (max-width: 560px) { .nav.in-app .brand-name { display: none; } }

/* ---------- buttons ---------- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 7px; height: 38px; padding: 0 16px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); font: 500 .9rem var(--font); cursor: pointer;
  white-space: nowrap; transition: background .15s, border-color .15s, transform .08s, box-shadow .15s; }
.btn:hover { background: var(--surface-2); text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn.disabled { opacity: .5; cursor: not-allowed; }
.btn.primary { background: var(--text); border-color: var(--text); color: var(--bg); }
.btn.primary:hover { background: color-mix(in srgb, var(--text) 86%, var(--accent)); }
.btn.signal { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn.gate { background: var(--highlight); border-color: var(--highlight); color: #1a1400; font-weight: 600; }
.btn.gate:hover { box-shadow: 0 6px 22px color-mix(in srgb, var(--highlight) 45%, transparent); }
.btn.danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, var(--border)); }
.btn.danger:hover { background: var(--danger-soft); }
.btn.ghost { border-color: transparent; background: transparent; }
.btn.ghost:hover { background: var(--surface-2); }
.btn.sm { height: 31px; padding: 0 12px; font-size: .84rem; }
.btn.lg { height: 48px; padding: 0 24px; font-size: 1rem; }
.btn.icon { width: 36px; padding: 0; }
/* inline SVG icons (re-run arrow, menu chevron) in place of text glyphs that render as specks */
.btn .ico { flex: none; vertical-align: -2px; }
.btn .spin, .spinner { width: 14px; height: 14px; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin .8s linear infinite; display: inline-block; flex: none; }

/* ---------- badges / chips ---------- */
.badge { display: inline-flex; align-items: center; gap: 6px; height: 22px; padding: 0 9px; border-radius: 999px; font: 500 .74rem var(--font);
  background: var(--surface-2); color: var(--text-2); white-space: nowrap; }
.badge.accent, .badge.success, .badge.done { background: var(--accent-soft); color: var(--accent); }
/* work in motion is lilac, like the run card's dot and eyebrow; pond blue stays for progress and links */
.badge.running { background: var(--glow-soft); color: var(--glow-ink); }
.badge.warn { background: var(--warn-soft); color: var(--warn); }
/* paused, skipped and outline are neutral states, never the decision gold or the warn rust */
.badge.paused { background: var(--surface-3); color: var(--text-2); }
.badge.skipped { background: var(--surface-2); color: var(--text-2); }
.badge.skipped .dot { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; }
.badge.outline { background: transparent; color: var(--text-2); box-shadow: inset 0 0 0 1px var(--border-strong); }
.badge.danger, .badge.failed { background: var(--danger-soft); color: var(--danger); }
/* stopped is the user's choice, not a failure: neutral grey */
.badge.stopped { background: var(--surface-3); color: var(--text-2); }
.badge.stopped .dot { background: var(--muted); }
.badge.gate, .badge.waiting { background: var(--gate-soft); color: var(--gate); }
.badge .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.badge.running .dot, .badge.waiting .dot { animation: blink 1.4s ease-in-out infinite; }
/* one quiet demo marker per screen: dashed and neutral */
.pill-demo { background: transparent; color: var(--text-2); border: 1px dashed var(--border-strong); }
/* ' · ' separators (render.seps / MSEP): a dot with its own margins, which the sans would otherwise collapse.
   The dot is drawn (the glyph stays in the text for copying), so it sits centred whatever font renders the line. */
.msep { display: inline-block; width: .2em; height: .2em; margin-inline: .45em; border-radius: 50%; background: currentColor;
  vertical-align: middle; overflow: hidden; text-indent: 1em; white-space: nowrap; opacity: .75; }
.badge .msep { margin-inline: .35em; }
/* a phrase that never breaks inside: a decision name, a counter, a parenthetical aside */
.nw { white-space: nowrap; }
.chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.chip { border: 1px solid var(--border-strong); background: var(--surface); color: var(--text-2); border-radius: 999px; padding: 4px 12px;
  font: .84rem var(--font); cursor: pointer; transition: border-color .15s, color .15s, background .15s; }
.chip:hover { border-color: var(--text); color: var(--text); }

/* ---------- forms ---------- */
label { display: block; font-weight: 600; font-size: .88rem; margin-bottom: 6px; }
.hint { font-weight: 400; color: var(--muted); font-size: .8rem; }
.field { margin-bottom: 16px; }
input[type=text], input[type=email], input[type=password], input[type=number], input[type=date], select, textarea {
  width: 100%; padding: 10px 12px; border: 1px solid var(--border-strong); border-radius: 10px; background: var(--surface); color: var(--text);
  font: inherit; transition: border-color .15s, box-shadow .15s; }
textarea { min-height: 84px; resize: vertical; line-height: 1.55; }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--text); box-shadow: 0 0 0 4px color-mix(in srgb, var(--text) 8%, transparent); }
.check { display: flex; gap: 9px; align-items: flex-start; font-weight: 400; }
.check input { margin-top: 4px; accent-color: var(--accent); }
.alert { padding: 11px 14px; border-radius: 10px; background: var(--surface-2); font-size: .9rem; }
.alert.danger { background: var(--danger-soft); color: var(--danger); }
.alert.warn { background: var(--warn-soft); color: var(--warn); }
.alert.success { background: var(--success-soft); color: var(--success); }
/* only for a decision the user can make now */
.alert.gate { background: var(--gate-soft); color: var(--gate); }

/* ---------- generic content (stage readers) ---------- */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 20px; box-shadow: var(--shadow); }
.card.flat { box-shadow: none; background: var(--surface-2); border-color: transparent; }
.card.tight { padding: 14px 16px; }
.block { margin-top: 22px; }
/* Stage readers: every section heading is one level and one style, whether it is a direct child of a block, sits in
   a grid column or titles a card. Card sub-sections (h4) are a step smaller. Markdown (.prose) keeps its own. */
.block:not(.prose) > h3, .block:not(.prose) > div > h3, .block .card > h3 {
  font: 600 1rem/1.35 var(--font); color: var(--text); letter-spacing: 0; text-transform: none; margin: 0 0 10px;
  display: flex; gap: 8px; align-items: center; }
:is(.block.card, .block .card) h4 { font: 600 .875rem/1.3 var(--font); color: var(--text-2); letter-spacing: 0; margin: 16px 0 6px; }
/* the research brief's title: the most important sentence of the study, above the section headings */
.brief-title { font: 600 1.2rem/1.4 var(--font); color: var(--text); letter-spacing: -.005em; margin: 0 0 6px; }
/* a decision the user already made: quiet, with the thin gold rule the glossary allows for past decisions */
.decision-record { padding: 10px 14px; border-radius: 10px; background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--highlight); font-size: .88rem; line-height: 1.55; color: var(--text); }
.decision-record .dr-k { color: var(--text-2); }
.decision-record .dr-note { color: var(--text-2); }
/* reader takeaways: one plain line per result before any table */
.takeaway-line { font-size: 1rem; line-height: 1.6; }
.takeaway-line + .prose { margin-top: 10px; }
.takeaway .list > li { font-size: .92rem; line-height: 1.6; }
.answers > li { line-height: 1.55; }
.answers > li .muted { margin-bottom: 2px; }
.reader-facts { margin-top: 4px; }
.reader-facts .fact .v.route { font-size: .98rem; line-height: 1.4; }
.reopen .btn { margin-bottom: 6px; }
.gpu-note { margin: 10px 0 0; }
/* a key–value list whose labels are as wide as the longest one (labels are short phrases, not single words) */
.kv.auto { grid-template-columns: fit-content(45%) minmax(0, 1fr); }
@media (max-width: 560px) { .kv.auto { grid-template-columns: minmax(0, 1fr); } }
.list { list-style: none; padding: 0; margin: 0; }
.list > li { padding: 10px 0; border-top: 1px solid var(--border); }
.list > li:first-child { border-top: 0; padding-top: 2px; }
.kv { display: grid; grid-template-columns: 130px 1fr; gap: 6px 16px; font-size: .9rem; margin: 0; }
@media (max-width: 560px) { .kv { grid-template-columns: 1fr; } }
.kv dt { color: var(--muted); }
.kv dd { margin: 0; }
.prose { font-size: .96rem; line-height: 1.72; }
.prose h1 { font-size: 1.5rem; }
.prose h2 { font-size: 1.15rem; margin-top: 1.7em; }
.prose h3 { font-size: 1rem; margin-top: 1.3em; }
.prose ul, .prose ol { padding-left: 1.3em; }
.prose li + li { margin-top: .25em; }
.prose blockquote { margin: 1em 0; padding: 8px 14px; border-left: 3px solid var(--border-strong); background: var(--surface-2); color: var(--text-2); border-radius: 0 8px 8px 0; }
.prose blockquote p:last-child { margin: 0; }
/* Tables: full width inside a scroll wrapper (.table-wrap > .table-scroll, added by templates and render.md_html).
   project.js marks a wrapper that really scrolls (.scrolls): a right-edge fade until the end, and a swipe hint. */
.table-wrap { position: relative; margin: .6em 0; }
.table-scroll { overflow-x: auto; overscroll-behavior-x: contain; }
.prose table, table.data { border-collapse: collapse; width: 100%; font-size: .87rem; margin: 0; }
.prose th, .prose td, table.data th, table.data td { border-bottom: 1px solid var(--border); padding: 7px 10px; text-align: left; vertical-align: top; }
.prose th, table.data th { font: 600 .8rem/1.4 var(--font); text-transform: none; letter-spacing: 0; color: var(--text-2);
  white-space: nowrap; border-bottom-color: var(--border-strong); }
table.data td.mono, table.data .nowrap, .verdict { white-space: nowrap; }
.prose .num, table.data .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.data abbr { text-decoration: none; cursor: help; }
.table-wrap.scrolls:not(.at-end)::after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 28px; pointer-events: none;
  background: linear-gradient(to right, transparent, var(--table-bg, var(--bg))); }
.card .table-wrap { --table-bg: var(--surface); }
.card.flat .table-wrap { --table-bg: var(--surface-2); }
.table-hint { display: none; margin: 4px 0 0; font-size: .76rem; color: var(--muted); }
.table-wrap.scrolls + .table-hint { display: block; }
/* comparisons on phones: a stacked list, so p and d_z are always visible */
.cmp-list { display: none; }
.cmp-list .f { white-space: nowrap; }
@media (max-width: 640px) { .cmp-table, .cmp-table + .table-hint { display: none !important; } .cmp-list { display: block; } }
/* the results chart keeps its text at a readable size on phones: it scrolls sideways instead of shrinking.
   project.js marks it like a wide table (.scrolls / .at-end): the right edge fades until the end, and a hint
   line under it says it scrolls. */
.chart-scroll { margin: 22px 0 0; padding: 12px; overflow-x: auto; overscroll-behavior-x: contain; color: var(--text); }
.chart-scroll img { display: block; width: 100%; border: 0; padding: 0; }
.chart-scroll.scrolls:not(.at-end) { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent); }
.chart-scroll.scrolls + .table-hint { display: block; }
@media (max-width: 640px) { .chart-scroll img { min-width: 480px; } }
details.stats > summary { cursor: pointer; }
.prose img { display: block; margin: 1em auto; background: var(--surface); border-radius: 10px; padding: 8px; border: 1px solid var(--border); }
/* ---------- paper, simulated review, venues, submission package ---------- */
/* The paper reads like a paper: the UI sans for the body at a comfortable measure (about 75 Latin or 36 CJK
   characters a line), the display serif for its title and sections. Citation keys are small pond-blue chips. */
/* 34em, not 66ch: the ch unit of this sans is narrow, so 66ch ran to 90–95 characters a line */
.paper { font-family: var(--font); font-size: 1rem; line-height: 1.75; max-width: 34em; }
.paper h1 { font: 500 clamp(1.4rem, 1.1rem + 1.4vw, 1.75rem)/1.25 var(--display); letter-spacing: -.005em; margin: .3em 0 .7em; }
.paper h2 { font: 500 1.3rem/1.3 var(--display); letter-spacing: 0; margin-top: 1.6em; }
.paper h3 { font: 600 1rem/1.4 var(--font); letter-spacing: 0; }
.paper-actions { gap: 8px; }
.paper-note { margin: 8px 0 0; }
.paper-checks { margin: 14px 0 0; max-width: 34em; }
.paper-checks + .paper { margin-top: 12px; }
.cites { white-space: nowrap; }
.cite { font: 500 .8em/1 var(--mono); padding: .15em .42em; border-radius: 5px; background: var(--accent-soft); color: var(--accent); vertical-align: .06em; }
.cites .cite + .cite { margin-left: .3em; }
.cite:hover { text-decoration: none; background: var(--accent); color: var(--accent-ink); }
.cite.bad { color: var(--danger); background: var(--danger-soft); text-decoration: line-through; }
/* the readiness notice (rust) and plain inline links inside readers */
.readiness p { margin: 0; }
.readiness .btn { margin-top: 10px; }
.link-btn { display: inline; padding: 0; border: 0; background: none; font: inherit; color: var(--accent); cursor: pointer; }
.link-btn:hover { text-decoration: underline; text-underline-offset: 3px; }
/* simulated review: the verdict in tone colours (never the decision gold), one rubric line whose units never split */
.review-note { margin-bottom: 10px; }
.review-head { display: flex; flex-wrap: wrap; gap: 6px 12px; align-items: center; }
.review-actions { margin-top: 12px; gap: 8px; }
.review-card > .row { flex-wrap: nowrap; align-items: flex-start; gap: 8px; }
.review-card > .row .badge { flex: none; }
.review-card .rubric { margin: 6px 0 8px; line-height: 1.6; }
.rubric span { white-space: nowrap; }
.rubric .rb-main { color: var(--text); font-weight: 600; }
.review-meta .prose { margin-top: 8px; }
.review-revised { margin: 10px 0 0; }
/* venues: a calm card per recommendation; the current target carries the pond-blue badge */
.venue-guide { margin: 0 0 4px; }
.venue-top { display: flex; gap: 8px 14px; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }
.venue-title { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; min-width: 0; }
.venue-name { font-size: 1.05rem; margin-right: 2px; }
.venue-fit { font-size: .87rem; color: var(--text-2); white-space: nowrap; }
.venue-fit b { font-size: 1.05rem; color: var(--accent); }
.venue-full { margin: 4px 0 10px; }
.venue-why { margin-top: 10px; }
.venue-plan { margin: 0; }
.venue-foot { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; margin-top: 12px; }
.venue-card.current { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 40%, transparent); }
/* switching the target is not destructive: the in-page confirmation is neutral, not the rose of delete / stop */
.venue-foot .confirm-inline { margin: 0; border: 1px solid var(--border-strong); background: var(--surface); max-width: 46em; }
/* submission package: checklist first and full width, then the letter and the disclosure side by side */
.sub-downloads { gap: 8px; }
.sub-target .small { display: block; margin-top: 2px; }
.sub-head { gap: 8px; margin-bottom: 6px; }
.sub-head h3 { font: 600 1rem/1.35 var(--font); letter-spacing: 0; margin: 0; }
.sub-checklist > .tiny { margin: 0 0 8px; }
.checklist > li { padding: 10px 0; }
.checklist .check { gap: 10px; font-size: .9rem; margin: 0; cursor: pointer; }
.checklist .check input { flex: none; width: 16px; height: 16px; margin: 3px 0 0; cursor: pointer; }
.checklist .check input:disabled { cursor: default; }
.ck-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ck-line { display: flex; flex-wrap: wrap; gap: 4px 8px; align-items: center; }
.ck-item { color: var(--text); }
.ck-note { font-size: .8rem; line-height: 1.5; color: var(--muted); }
.checklist li:has(input:checked) .ck-item { color: var(--muted); text-decoration: line-through; text-decoration-color: var(--border-strong); }
.checklist li.na .ck-item { color: var(--text-2); }
.checklist li.na .check { cursor: default; }
.sub-texts { align-items: stretch; }
.sub-text { display: flex; flex-direction: column; }
.sub-text .sub-caution { margin: -2px 0 8px; }
.sub-text blockquote { margin: 0; padding: 8px 14px; border-left: 3px solid var(--border-strong); background: var(--surface); border-radius: 0 8px 8px 0; color: var(--text-2); }
.sub-text .prose blockquote { background: var(--surface); }
.timeline > li b { font-weight: 600; }
.score { display: inline-grid; place-items: center; width: 52px; height: 52px; border-radius: 50%; font: 600 1.15rem var(--font); font-variant-numeric: tabular-nums; background: var(--accent-soft); color: var(--accent); }
/* verdicts: supported pond blue, refuted rose; inconclusive and untested are neutral (never warn or gold) */
.verdict { font-weight: 600; }
.verdict.supported { color: var(--accent); } .verdict.refuted { color: var(--danger); } .verdict.inconclusive { color: var(--text-2); } .verdict.untested { color: var(--muted); }
/* quality checks: a collapsed footnote under the output (partials/evals.html) */
details.evals { margin-top: 32px; padding-top: 14px; border-top: 1px solid var(--border); }
.evals > summary { list-style: none; cursor: pointer; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; font-size: .86rem; color: var(--text-2); }
.evals > summary::-webkit-details-marker { display: none; }
.evals > summary::before { content: ""; width: 6px; height: 6px; margin: 0 4px 0 2px; border: solid var(--muted); border-width: 0 1.5px 1.5px 0;
  transform: rotate(-45deg); transition: transform .2s var(--ease); }
.evals[open] > summary::before { transform: rotate(45deg); }
.evals > summary:hover { color: var(--text); }
.evals-t { font-weight: 600; }
.evals > summary .msep { margin-inline: 0; }
.evals-s { color: var(--muted); }
.evals-s.bad { color: var(--danger); }
.evals-hint { margin: 8px 0 12px; }
.evals-fail { color: var(--danger); }
.evals details { border: 1px solid var(--border); border-radius: 10px; padding: 10px 14px; background: var(--surface); }
.evals details + details { margin-top: 8px; }
.evals details summary { cursor: pointer; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; font-size: .88rem; }
.evals ul { margin: 8px 0 0; padding-left: 18px; font-size: .86rem; color: var(--text-2); }
.vchecks { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.vcheck { font-size: .74rem; padding: 2px 8px; border-radius: 6px; background: var(--success-soft); color: var(--success); }
.vcheck.fail { background: var(--danger-soft); color: var(--danger); }
.vcheck.soft.fail { background: var(--warn-soft); color: var(--warn); }
.sources { margin-top: 6px; }
.source { display: grid; grid-template-columns: 40px 1fr; gap: 8px; padding: 10px 6px; border-top: 1px solid var(--border); font-size: .88rem; }
.source:first-child { border-top: 0; }
.source .k { font: 600 .8rem var(--mono); color: var(--accent); }
.source .ttl { font-weight: 600; }
.source:target, .source.flash { background: var(--accent-soft); border-radius: 8px; border-top-color: transparent; }
/* the sources hint sits on its own line under the summary, never trailing the count */
.sources-hint { display: block; margin-top: 4px; }
.lit-kw-hint { margin: 0 0 4px; }
/* reproducibility checks: the badge keeps its distance from the item it labels */
.checks .badge { margin-right: 8px; }
.progress { height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.progress i { display: block; height: 100%; background: var(--accent); transition: width .4s; }
.bfts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin-top: 12px; }
@media (max-width: 560px) { .bfts { grid-template-columns: 1fr 1fr; } }
.bfts div { border: 1px solid var(--border); border-radius: 9px; padding: 8px 10px; font-size: .8rem; }
.bfts div.on { border-color: var(--accent); background: var(--accent-soft); }
.bfts div.ok { border-color: transparent; background: var(--success-soft); color: var(--success); }
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 16px; overflow-x: auto; }
.tabs button { background: none; border: 0; border-bottom: 2px solid transparent; padding: 9px 12px; font: 500 .88rem var(--font); color: var(--muted); cursor: pointer; white-space: nowrap; }
.tabs button.on { color: var(--text); border-bottom-color: var(--text); }
.toast { position: fixed; left: 50%; bottom: calc(20px + env(safe-area-inset-bottom, 0px)); transform: translateX(-50%); z-index: 100; max-width: calc(100vw - 32px);
  padding: 11px 18px; border-radius: 999px; background: var(--text); color: var(--bg); box-shadow: var(--shadow-lg); font-size: .88rem; animation: rise .25s var(--ease); }
.toast.error { background: var(--danger); color: #fff; }
.skeleton { height: 14px; border-radius: 6px; background: linear-gradient(90deg, var(--surface-2), var(--surface-3), var(--surface-2)); background-size: 200% 100%; animation: shimmer 1.4s infinite; }
.empty { text-align: center; padding: 56px 20px; }
.meter { height: 6px; background: var(--surface-3); border-radius: 3px; overflow: hidden; }
.meter i { display: block; height: 100%; background: var(--accent); border-radius: 3px; }
.meter.warn i { background: var(--warn); } .meter.danger i { background: var(--danger); }

/* ---------- decision card (partials/gate.html) ----------
   Gold only on what the user acts on now: the checked option, its radio dot and the submit button. 终止研究 is
   rose and dashed, set apart from the way forward. Costs and "what happens next" are quiet text-2 / muted. */
.gate-card { margin: 0; }
.gate-card > .kicker, .gate-card > h3 { display: none; }
.gate-findings { margin: 14px 0 0; padding-left: 18px; }
.gate-block { margin-top: 16px; }
.gate-block .row { margin-top: 8px; }
.gate-block p { margin: 8px 0 0; }
.gate-upload { margin-top: 12px; }
.gate-options { display: grid; gap: 10px; margin: 18px 0 14px; }
.gate-opt { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 12px; align-items: start; padding: 14px 16px; border: 1px solid var(--opt-border);
  border-radius: 12px; background: var(--surface); cursor: pointer; font-weight: 400; margin: 0; transition: border-color .15s, background .15s; }
.gate-opt:hover { border-color: color-mix(in srgb, var(--highlight) 70%, var(--border-strong)); }
/* `> input[name=option]`: a pre-checked GPU tier inside a card never lights the card up */
.gate-opt:has(> input[name=option]:checked) { border-color: var(--highlight); background: var(--gate-soft); box-shadow: inset 0 0 0 1px var(--highlight); }
.gate-opt:has(> input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
/* unavailable: the radio and the title fade; the description (often the only price information) stays readable */
.gate-opt.disabled { opacity: 1; cursor: not-allowed; }
.gate-opt.disabled > input, .gate-opt.disabled .opt-title { opacity: .5; }
.gate-opt.disabled:hover { border-color: var(--opt-border); }
.gate-opt > input[type=radio] { appearance: none; -webkit-appearance: none; width: 18px; height: 18px; margin: 2px 0 0; border: 1.5px solid var(--muted); border-radius: 50%;
  background: var(--surface); box-shadow: none; cursor: inherit; transition: border-width .12s, border-color .12s; }
.gate-opt > input[type=radio]:checked { border: 5px solid var(--gate); }
.gate-opt > input[type=radio]:focus { box-shadow: none; }
.opt-body { display: block; min-width: 0; }
.opt-title { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: .95rem; font-weight: 600; line-height: 1.4; color: var(--text); }
.opt-title .badge { height: 20px; padding: 0 8px; font-size: .72rem; }
/* on the gold-washed checked card the badge needs its own ground to stay visible */
.opt-title .badge.gate { background: var(--surface); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--highlight) 75%, transparent); }
.opt-desc { display: block; margin-top: 2px; font-size: .85rem; line-height: 1.5; color: var(--muted); text-wrap: pretty; }
.opt-cost { display: block; margin-top: 6px; font-size: .8rem; line-height: 1.45; color: var(--text-2); font-variant-numeric: tabular-nums; }
.opt-over { display: block; margin-top: 6px; font-size: .82rem; line-height: 1.45; color: var(--warn); font-variant-numeric: tabular-nums; }
/* 终止研究: rose, dashed, a little apart from the options that move the study forward */
.gate-opt.danger { margin-top: 8px; border-style: dashed; border-color: color-mix(in srgb, var(--danger) 45%, var(--border-strong)); }
.gate-opt.danger .opt-title { color: var(--danger); }
.gate-opt.danger:hover { border-color: color-mix(in srgb, var(--danger) 55%, var(--border-strong)); }
.gate-opt.danger:has(> input[name=option]:checked) { border-color: var(--danger); background: var(--danger-soft); box-shadow: inset 0 0 0 1px var(--danger); }
.gate-opt.danger > input[type=radio]:checked { border-color: var(--danger); }
.tier-select { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.tier-select label { font-weight: 400; display: inline-flex; gap: 7px; align-items: center; border: 1px solid var(--border-strong); border-radius: 14px; padding: 5px 12px;
  font-size: .8rem; line-height: 1.35; margin: 0; color: var(--text-2); background: var(--surface); font-variant-numeric: tabular-nums; }
.tier-select label:has(input:checked) { border-color: var(--text-2); color: var(--text); }
.tier-select label.over > span { color: var(--warn); }
.tier-select input { margin: 0; accent-color: var(--gate); flex: none; }
.gate-scope { margin: -4px 0 12px; }
.gate-raise { margin: 0 0 14px; }
.gate-raise input[type=number] { max-width: 180px; font-variant-numeric: tabular-nums; }
.gate-raise .hint { margin-top: 6px; }
/* the note: one quiet line until an option that sends work back makes it required */
.gate-note { margin: 0 0 16px; }
.gate-note > summary { cursor: pointer; font-size: .88rem; font-weight: 600; color: var(--text-2); padding: 4px 0; list-style-position: inside; }
.gate-note > summary .hint { font-weight: 400; margin-left: 8px; }
.gate-note.required > summary { color: var(--text); }
.gate-note textarea { margin-top: 8px; min-height: 72px; }
.gate-confirm { margin: 0 0 14px; padding: 14px 16px; border-radius: 12px; border: 1px dashed var(--danger); background: var(--danger-soft); color: var(--text); }
.gate-confirm p { margin: 0 0 10px; font-size: .9rem; }
.gate-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
/* the submit says what the choice does, so it may wrap on phones rather than overflow */
.gate-submit { white-space: normal; height: auto; min-height: 48px; padding-block: 10px; text-align: center; line-height: 1.35; max-width: 100%; }
.gate-next { margin: 10px 0 0; font-size: .84rem; line-height: 1.55; color: var(--text-2); max-width: 46em; text-wrap: pretty; }
.gate-alert { margin-top: 14px; }
.gate-alert .link-btn { margin-left: 4px; }

/* ---------- workspace ---------- */
.ws-top { padding: 22px 0 6px; }
.ws-top .back { font-size: .85rem; color: var(--muted); }
.ws-title { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-top: 8px; }
/* the title is the idea's first sentence: 3 lines at most (2 on phones), the full text on hover or tap */
.ws-title h1 { font-size: clamp(1.45rem, 2.9vw, 2rem); line-height: 1.18; margin: 0; max-width: 34em; display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; cursor: pointer; }
.ws-title h1.open { display: block; -webkit-line-clamp: unset; line-clamp: none; }
@media (max-width: 640px) { .ws-title h1 { font-size: 1.3rem; -webkit-line-clamp: 2; line-clamp: 2; } }
/* 更多 is outlined (not ghost): the only way to downloads, stop and delete */
.menu-btn { gap: 6px; color: var(--text-2); }
.menu-btn .chev { flex: none; transition: transform .15s; }
.menu-btn[aria-expanded="true"] .chev { transform: rotate(180deg); }
/* in-page confirmation for stop and delete (never a native dialog) */
.confirm-inline { flex-basis: 100%; margin: 8px 0 0; padding: 12px 14px; border-radius: 12px; border: 1px dashed var(--danger); background: var(--danger-soft);
  color: var(--text); font-size: .86rem; line-height: 1.5; }
.confirm-inline p { margin: 0 0 10px; }
.confirm-inline .row { gap: 8px; }
.menu-pop:has(.confirm-inline) { width: min(300px, calc(100vw - 32px)); }
.menu-pop .confirm-inline { margin: 4px; }
.menu-pop .confirm-inline .btn { display: inline-flex; width: auto; height: 31px; padding: 0 12px; border-radius: 999px; border: 1px solid var(--border-strong);
  background: var(--surface); font-size: .84rem; }
.menu-pop .confirm-inline .btn.danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, var(--border)); }
.menu-pop .confirm-inline .btn.ghost { border-color: transparent; background: transparent; }
.ws-meta { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; margin-top: 10px; color: var(--muted); font-size: .84rem; }
.menu { position: relative; }
.menu-pop { position: absolute; right: 0; top: calc(100% + 6px); z-index: 20; min-width: 200px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-lg); padding: 6px; animation: rise .18s var(--ease); }
.menu-pop a, .menu-pop button { display: flex; width: 100%; gap: 8px; align-items: center; padding: 8px 10px; border: 0; background: none; border-radius: 8px; color: var(--text);
  font: .88rem var(--font); cursor: pointer; text-align: left; }
.menu-pop a:hover, .menu-pop button:hover { background: var(--surface-2); text-decoration: none; }
.menu-pop .danger { color: var(--danger); }
.menu-pop hr { border: 0; border-top: 1px solid var(--border); margin: 5px 4px; }

/* ---------- budget: header meter, popover, banner, forecast line, cost table ----------
   Pond blue for spend, rust from 80% of the cap, rose from 95%. Never gold (money is not a decision) or green.
   Amounts use the UI sans with tabular figures. */
/* the bar hangs below the row (negative margin), so the label lines up with the badges beside it */
.spend { display: inline-flex; flex-direction: column; gap: 5px; padding: 2px 0; margin-bottom: -9px; border: 0; background: none; font: inherit;
  color: var(--text-2); cursor: pointer; text-align: left; font-variant-numeric: tabular-nums; border-radius: 4px; }
.spend:hover .spend-text, .spend[aria-expanded="true"] .spend-text { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
.spend:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
/* the inset ring keeps the empty track visible on the dusk palette */
.spend-bar { display: block; width: 100%; min-width: 140px; height: 4px; border-radius: 2px; background: var(--surface-3); box-shadow: inset 0 0 0 1px var(--border-strong); overflow: hidden; }
.spend-bar i { display: block; height: 100%; min-width: 0; border-radius: 2px; background: var(--accent); transition: width .4s var(--ease); }
.spend.warn .spend-bar i { background: var(--warn); }
.spend.danger .spend-bar i { background: var(--danger); }
.spend.danger .spend-text { color: var(--danger); }
.ws-meta { position: relative; }
@media (max-width: 640px) { .ws-count { display: none; } }
.budget-pop { position: absolute; left: 0; top: calc(100% + 16px); z-index: 25; width: min(400px, 100%); padding: 16px 16px 12px; border-radius: 14px;
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-lg); color: var(--text); font-size: .88rem; animation: rise .18s var(--ease); }
.budget-pop .bp-line { margin: 0 0 4px; font-weight: 600; font-variant-numeric: tabular-nums; }
.budget-pop .bp-note { margin: 0 0 10px; font-size: .8rem; line-height: 1.55; color: var(--muted); }
.bp-form { margin: 4px 0 10px; }
.bp-form label { font-size: .82rem; margin-bottom: 6px; }
.bp-row { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.bp-row input[type=number] { width: 130px; padding: 6px 10px; font-variant-numeric: tabular-nums; }
.bp-form .hint { margin-top: 6px; }
.bp-err { margin-top: 6px; font-size: .8rem; color: var(--danger); }
.bp-row input[aria-invalid="true"] { border-color: var(--danger); }
.bp-costs { border-top: 1px solid var(--border); padding-top: 8px; }
.bp-costs > summary { cursor: pointer; font-size: .84rem; color: var(--text-2); }
.budget-alert { margin-top: 12px; display: flex; gap: 8px 14px; align-items: center; flex-wrap: wrap; font-size: .86rem; }
.budget-alert > span { flex: 1 1 260px; }
.ws-meta + .budget-alert { margin-top: 20px; }
.budget-line { margin: 16px 0 0; font-size: .84rem; color: var(--text-2); font-variant-numeric: tabular-nums; }
.cost-table { margin: 8px 0 4px; font-size: .82rem; }
.cost-table th, .cost-table td { padding: 6px 6px; }
.cost-table td:nth-child(2) { white-space: nowrap; }
.cost-table .r { text-align: right; white-space: nowrap; }
.cost-table td { font-variant-numeric: tabular-nums; }
.cost-table tfoot td { font-weight: 600; border-bottom: 0; }
.cost-table .badge { height: 18px; padding: 0 6px; font-size: .68rem; }
.cost-foot { margin: 4px 0 0; font-size: .76rem; color: var(--muted); }
.fact .v.money { font-family: var(--font); font-variant-numeric: tabular-nums; }
.feed .ev.budget .ic { background: var(--warn); }

.rail { list-style: none; margin: 18px 0 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; }
.phase { position: relative; padding-right: 14px; }
.phase::before { content: ""; position: absolute; left: 30px; right: 4px; top: 14px; height: 2px; background: var(--border-strong); border-radius: 2px; }
.phase:last-child::before { display: none; }
.phase.done::before { background: var(--accent); }
.phase.active::before { background: linear-gradient(90deg, var(--accent) 0 30%, var(--border-strong) 30%); }
.phase-node { position: relative; z-index: 1; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; font: 600 .8rem var(--font);
  font-variant-numeric: tabular-nums; background: var(--surface); border: 1.5px solid var(--border-strong); color: var(--muted); }
.phase.done .phase-node { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.phase.active .phase-node { border-color: var(--accent); color: var(--accent); --c: var(--glow); animation: pulse 2s infinite; }
.phase.decide .phase-node { background: var(--highlight); border-color: var(--highlight); color: #1a1400; --c: var(--highlight); animation: pulse 2s infinite; }
.phase.failed .phase-node { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }
/* stopped and paused: grey, no pulse; a skipped experiment: a dashed hollow node with a dash, not a check */
.phase.stopped .phase-node { background: var(--surface-3); border-color: var(--border-strong); color: var(--muted); }
.phase.paused .phase-node { background: var(--surface-2); border-color: var(--border-strong); color: var(--text-2); }
.phase.done.skipped .phase-node { background: var(--surface); border: 1.5px dashed var(--muted); color: var(--muted); }
.phase-text { margin-top: 10px; }
.phase-text b { display: block; font-size: .95rem; }
.phase.todo .phase-text b { color: var(--muted); font-weight: 500; }
.phase-text span { display: block; font-size: .78rem; color: var(--muted); line-height: 1.35; margin-top: 2px; }
.phase.decide .phase-text span { color: var(--gate); font-weight: 600; }
.phase.stopped .phase-text span, .phase.paused .phase-text span { color: var(--text-2); font-weight: 600; }
.phase-dots { display: flex; gap: 4px; margin-top: 8px; }
.phase-dots i { width: 14px; height: 4px; border-radius: 2px; background: var(--surface-3); }
.phase-dots i.done { background: var(--accent); }
.phase-dots i.skipped { background: transparent; box-shadow: inset 0 0 0 1px var(--muted); }
.phase-dots i.running { background: var(--glow); animation: blink 1.2s infinite; }
.phase-dots i.waiting { background: var(--highlight); }
.phase-dots i.failed { background: var(--danger); }
.phase-dots i.stopped { background: var(--border-strong); }
.is-paused .phase-dots i, .is-paused .dcard .st, .is-paused .pulse-dot, .is-paused .shimmer { animation: none; }
/* where the study is, in one line (phones), and the all-done line that replaces the rail on phones */
.rail-now, .rail-summary { display: none; }
.rail-now { margin: 10px 0 0; font-size: .84rem; line-height: 1.45; color: var(--text-2); font-variant-numeric: tabular-nums; }
.rail-now.decide > span:not(.msep) { color: var(--gate); font-weight: 600; }
/* rose only for a failure; a stop the user chose reads grey, as on desktop */
.rail-now.failed > span:not(.msep) { color: var(--danger); font-weight: 600; }
.rail-now.stopped > span:not(.msep), .rail-now.paused > span:not(.msep) { color: var(--text-2); font-weight: 600; }
.rail-summary { margin: 14px 0 0; font-size: .88rem; font-weight: 600; color: var(--accent); word-break: keep-all; overflow-wrap: anywhere; }
/* a skipped experiment is not 'all complete': neutral, no check mark */
.rail-summary.skipped { color: var(--text-2); }
@media (max-width: 640px) {
  .rail { grid-template-columns: repeat(4, minmax(0, 1fr)); row-gap: 0; margin-top: 14px; }
  .phase { padding-right: 0; }
  .phase-text, .phase-dots { display: none; }
  .phase.todo .phase-node { opacity: .5; }
  .rail-now { display: block; }
  .rail.all-done { display: none; }
  .rail-summary { display: block; }
}

.focus { position: relative; margin-top: 26px; border-radius: 20px; padding: 26px 28px; background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow); animation: rise .5s var(--ease) both; }
.focus.decide { border-color: color-mix(in srgb, var(--highlight) 80%, var(--border)); animation: rise .5s var(--ease) both, breathe 3.2s ease-in-out .5s infinite; }
.focus.failed { border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); }
.focus.done { background: linear-gradient(160deg, var(--accent-soft), var(--surface) 55%); }
.focus-eyebrow { display: flex; align-items: center; gap: 8px; font: 600 .8rem/1.4 var(--font); color: var(--muted); }
.focus.decide .focus-eyebrow { color: var(--gate); }
.focus.failed .focus-eyebrow { color: var(--danger); }
.pulse-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--highlight); --c: var(--highlight); animation: pulse 1.8s infinite; flex: none; }
.focus-title { font-size: clamp(1.4rem, 2.7vw, 1.85rem); line-height: 1.22; margin: 10px 0 6px; max-width: 30em; }
/* clauses from the `phrases` filter: the heading breaks between them, never mid-word */
.focus-title .ph { display: inline-block; }
.focus-sub { color: var(--text-2); margin: 0; max-width: 46em; text-wrap: pretty; }
/* phones: the rail above already says where the study is; the running eyebrow keeps just 进行中 */
@media (max-width: 640px) { .focus.run .eb-where { display: none; } }
/* run card: lilac means work in motion; with reduced motion the dot is simply static */
.pulse-dot.run { background: var(--glow); --c: var(--glow); }
.live-line { margin-top: 16px; display: flex; gap: 10px; align-items: flex-start; font: .9rem/1.5 var(--font); padding: 11px 14px; border-radius: 10px; background: var(--surface-2); min-height: 44px; overflow: hidden; }
.live-line .txt { min-width: 0; white-space: normal; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.live-line .txt.swap { animation: rise .35s var(--ease); }
.focus-meta { display: flex; gap: 6px 16px; flex-wrap: wrap; align-items: baseline; margin-top: 14px; font-size: .84rem; color: var(--muted); }
.focus-meta b { color: var(--text); font-weight: 500; }
.focus .focus-meta .open-link { margin: 0; }
.focus-note { margin: 12px 0 0; font-size: .82rem; line-height: 1.55; color: var(--muted); max-width: 46em; text-wrap: pretty; }
.focus-sub + .focus-note { margin-top: 6px; }
.run-actions { display: flex; gap: 8px 14px; align-items: center; flex-wrap: wrap; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--border); }
.run-hint { flex: 1 1 260px; font-size: .78rem; line-height: 1.5; color: var(--muted); }
@media (prefers-reduced-motion: reduce) { .spinner, .btn .spin { border-right-color: currentColor; opacity: .55; } }
/* paused and stopped: neutral cards, no gold and no pulse */
.focus.stopped { border-color: var(--border-strong); }
.focus-actions { margin-top: 16px; }
.focus-error { white-space: pre-wrap; margin-top: 12px; }
.focus-costs { margin-top: 18px; padding-top: 10px; border-top: 1px solid var(--border); }
.focus-costs > summary { cursor: pointer; font-size: .84rem; color: var(--text-2); }
/* done: what was produced, the next step, then the details */
.focus.done .done-title { margin-top: 2px; font-size: .92rem; }
.done-alert { margin-top: 14px; max-width: 46em; }
.done-takeaway { margin-top: 10px; font-size: .95rem; line-height: 1.65; }
.done-takeaway p:last-child { margin-bottom: 0; }
.done-actions { margin-top: 18px; gap: 10px; }
.done-todo { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--border); }
.done-todo h3 { margin: 0 0 8px; font: 600 .95rem/1.4 var(--font); letter-spacing: 0; }
.done-todo ul { margin: 0 0 10px; padding-left: 18px; font-size: .88rem; }
.done-todo li + li { margin-top: 4px; }
.done-todo li .muted { font-size: .82rem; }
.done-todo p { margin: 0; font-size: .84rem; color: var(--text-2); }
.focus .done-todo .open-link { margin: 0 0 12px; }
@media (max-width: 560px) { .done-actions > .btn { flex: 1 1 100%; } }
/* fact tiles: numbers in the UI sans with tabular figures; inconclusive and untested are neutral, not muted */
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-top: 18px; }
.fact { padding: 12px 14px; border-radius: 12px; background: var(--surface-2); min-width: 0; }
/* break-word: a long name wraps between words, never mid-word ('Neurocomputi / ng') */
.fact .v { font: 600 1.25rem/1.3 var(--font); font-variant-numeric: tabular-nums; letter-spacing: -.01em; overflow-wrap: break-word; }
.fact .v .unit { color: var(--muted); font-weight: 500; }
.fact .l { font-size: .78rem; color: var(--muted); margin-top: 2px; text-wrap: pretty; }
.fact .d { font-size: .8rem; line-height: 1.45; color: var(--text-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.fact .v.supported, .fact .v.accent { color: var(--accent); } .fact .v.refuted, .fact .v.danger { color: var(--danger); }
.fact .v.inconclusive, .fact .v.untested { color: var(--text-2); }
/* named tiles: the label names the thing, the value follows */
.facts.named .fact { display: flex; flex-direction: column; gap: 4px; }
.facts.named .fact .l { margin: 0; order: -1; }
.facts.named .fact .v { font-size: 1.15rem; }
.fact-link { font: inherit; color: inherit; text-align: left; border: 0; cursor: pointer; transition: background .15s; }
.fact-link:hover, .fact-link:focus-visible { background: var(--surface-3); }
.fact-link .l, .fact-link .v { display: block; }
.fact-link .d { color: var(--accent); }
/* one tile alone (the stopped card's spend): its natural width, not the whole card */
.facts.solo { grid-template-columns: minmax(0, 260px); }
@media (max-width: 560px) {
  .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .facts > .fact:last-child:nth-child(odd) { grid-column: 1 / -1; }
  /* the venue name gets a row of its own; the tiles after it stay paired */
  .facts.named > .fact.wide { grid-column: 1 / -1; }
  .facts.named > .fact.wide ~ .fact:last-child:nth-child(odd) { grid-column: auto; }
  .facts.named > .fact.wide ~ .fact:last-child:nth-child(even) { grid-column: 1 / -1; }
  .facts.solo { grid-template-columns: minmax(0, 1fr); }
}
.facts-note { margin: 8px 0 0; font-size: .78rem; color: var(--muted); }
.facts-tips { margin-top: 14px; }
.facts-tips .kicker { margin-bottom: 4px; }
.facts-tips ul { margin: 0; padding-left: 18px; font-size: .87rem; color: var(--text-2); }
.plan-brief { display: grid; gap: 6px; margin: 14px 0 0; font-size: .88rem; line-height: 1.5; color: var(--text-2); }
.plan-brief b { color: var(--text); font-weight: 600; margin-right: 4px; }
.plan-brief .mono { font-size: .84em; }
.focus .open-link { display: inline-flex; gap: 6px; margin-top: 14px; font-size: .86rem; color: var(--text-2); cursor: pointer; background: none; border: 0; padding: 0; font-family: inherit; }
.focus .open-link:hover { color: var(--text); text-decoration: underline; text-underline-offset: 3px; }
.focus .link-btn { display: inline; padding: 0; border: 0; background: none; font: inherit; color: var(--accent); cursor: pointer; }
.focus .link-btn:hover { text-decoration: underline; text-underline-offset: 3px; }
/* clarifying questions: each its own group, a hairline between, a muted n/N counter */
.focus .questions { margin-top: 22px; }
.focus .questions .field { margin: 0; padding: 22px 0; border-top: 1px solid var(--border); }
.focus .questions .field:first-child { border-top: 0; padding-top: 0; }
.focus .questions .field:last-child { padding-bottom: 0; }
.focus .questions .field label { font-size: .98rem; }
.focus .questions .q-num { font: 500 .78rem var(--font); font-variant-numeric: tabular-nums; color: var(--muted); margin-right: 8px; }
.focus .questions .q-why { margin: -2px 0 8px; }
.focus .questions .q-chips { margin: 0 0 8px; }
.focus .questions textarea { min-height: 56px; }
.focus .questions + input + .gate-actions { margin-top: 22px; }
@media (max-width: 560px) { .focus { padding: 20px 18px; border-radius: 16px; } }

.section-label { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin: 40px 0 14px; }
.section-label h2 { font-size: 1.05rem; margin: 0; }
.deliverables { display: grid; gap: 22px; }
.dphase { display: grid; grid-template-columns: 92px 1fr; gap: 14px; }
.dphase > .ph { font: 600 .76rem var(--font); color: var(--muted); padding-top: 14px; }
.dgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 10px; }
.dphase.upcoming > .ph { padding-top: 7px; opacity: .7; }
/* one row per phase: no phase has more than 4 steps, so 4 equal columns never leave an orphan */
@media (min-width: 900px) {
  .dphase { grid-template-columns: 1fr; gap: 8px; }
  .dphase > .ph, .dphase.upcoming > .ph { padding-top: 0; }
  .dgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 641px) and (max-width: 899px) { .dgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.dupcoming { display: flex; flex-wrap: wrap; gap: 8px; }
/* not started yet: the same look as a pending card (solid hairline, muted ink); still opens the step's blurb */
.dchip { font: inherit; font-size: .84rem; color: var(--muted); background: transparent; border: 1px solid var(--border); border-radius: 999px;
  padding: 5px 13px; cursor: pointer; transition: color .15s, border-color .15s, background .15s; }
.dchip:hover { color: var(--text); border-color: var(--border-strong); background: var(--surface); }
/* Eyebrow labels are sans in sentence case. English alone gets small capitals with tracking; Chinese has no case
   and reads best untracked. Section headings (.block > h3) and table headers are not eyebrows. */
:lang(en) :is(.kicker, .eyebrow-mono, .focus-eyebrow, .dphase > .ph, .feed .grp, .loop-line .who) { text-transform: uppercase; letter-spacing: .06em; font-size: .72rem; }
@media (max-width: 640px) { .dphase { grid-template-columns: 1fr; gap: 6px; } .dphase > .ph { padding-top: 0; } }
.dcard { position: relative; display: flex; flex-direction: column; gap: 8px; text-align: left; padding: 14px 16px; min-height: 112px; border-radius: 14px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); font: inherit; cursor: pointer; transition: transform .18s var(--ease), box-shadow .18s, border-color .18s; }
.dcard:hover { transform: translateY(-2px); box-shadow: var(--shadow); border-color: var(--border-strong); }
.dcard.pending { background: transparent; border-style: solid; border-color: var(--border); color: var(--muted); }
.dcard.running { border-color: color-mix(in srgb, var(--glow) 60%, var(--border)); }
.dcard.waiting { border-color: color-mix(in srgb, var(--highlight) 85%, var(--border)); background: linear-gradient(160deg, var(--gate-soft), var(--surface) 70%); }
.dcard.failed { border-color: color-mix(in srgb, var(--danger) 45%, var(--border)); }
/* stopped where the study stopped: grey and dashed, never gold */
.dcard.stopped { border-style: dashed; border-color: var(--border-strong); }
/* the status dot follows the title text, so a wrapped title never pushes it to the card's edge */
.dcard .top { display: block; }
.dcard .t { font-weight: 600; font-size: .92rem; text-wrap: pretty; }
/* an empty inline box drawn by its padding (not an inline-block): no line can break between it and the last word */
.dcard .st { display: inline; padding: 4px; margin-left: 8px; font-size: 0; line-height: 0; position: relative; top: -.3rem;
  border-radius: 50%; background: var(--surface-3); }
.dcard.done .st { background: var(--accent); }
.dcard.skipped .st { background: transparent; box-shadow: inset 0 0 0 1.5px var(--muted); }
.dcard.skipped .t { color: var(--muted); }
.dcard.stopped .st { background: var(--border-strong); }
.dcard.running .st { background: var(--glow); --c: var(--glow); animation: pulse 1.8s infinite; }
.dcard.waiting .st { background: var(--highlight); --c: var(--highlight); animation: pulse 1.8s infinite; }
.dcard.failed .st { background: var(--danger); }
.dcard .d { font-size: .84rem; color: var(--text-2); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-wrap: pretty; }
.dcard .m { font: .76rem/1.45 var(--font); font-variant-numeric: tabular-nums; color: var(--muted); margin-top: auto; text-wrap: pretty; }
/* what a finished step spent: its own line, never an amount wrapped onto a line by itself */
.dcard .m .cost { display: block; white-space: nowrap; }
/* phones: full-width cards size to their content, without the blank band of the fixed height */
@media (max-width: 640px) { .dcard { min-height: 0; } }
.dcard .big { font: 600 1.9rem/1 var(--font); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.dcard .big .unit { font: 500 .8rem var(--font); color: var(--muted); margin-left: 6px; letter-spacing: 0; }
.dcard .viz { display: flex; align-items: center; gap: 10px; }
/* one colour per condition, as in the reader's chart (lilac is C1 on both); a gap between the models */
.minibars { display: flex; align-items: flex-end; gap: 3px; height: 34px; }
.minibars i { width: 8px; border-radius: 2px 2px 0 0; background: var(--series-1); opacity: .9; }
.minibars i.gap { width: 5px; background: transparent; }
.minibars i.s1 { background: var(--series-2); } .minibars i.s2 { background: var(--series-3); } .minibars i.s3 { background: var(--series-4); }
.vpills { display: flex; gap: 5px; flex-wrap: wrap; }
.vpill { font: 500 .74rem var(--font); padding: 2px 8px; border-radius: 6px; background: var(--surface-2); color: var(--text-2); }
.vpill.supported { background: var(--success-soft); color: var(--success); } .vpill.refuted { background: var(--danger-soft); color: var(--danger); }
.vpill.inconclusive { background: transparent; color: var(--text-2); border: 1px dashed var(--border-strong); padding: 1px 7px; }
.dring { --p: 0; width: 46px; height: 46px; border-radius: 50%; background: conic-gradient(var(--accent) calc(var(--p) * 1%), var(--surface-3) 0); display: grid; place-items: center; flex: none; }
.dring b { width: 36px; height: 36px; border-radius: 50%; background: var(--surface); display: grid; place-items: center; font: 600 .95rem var(--font); font-variant-numeric: tabular-nums; }

.activity { margin: 34px 0 60px; }
.activity > details > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--surface); font-size: .88rem; }
.activity > details > summary::-webkit-details-marker { display: none; }
.activity > details > summary .last { color: var(--muted); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.activity > details[open] > summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
/* a plain label and an explicit "show all / hide" with a chevron that turns */
.activity summary .lbl { flex: none; font-weight: 600; color: var(--text-2); }
.activity summary .more { flex: none; display: inline-flex; align-items: center; gap: 5px; font-size: .78rem; color: var(--muted); white-space: nowrap; }
.activity summary .o { display: none; }
.activity details[open] summary .o { display: inline; }
.activity details[open] summary .c { display: none; }
.activity .chev { transition: transform .2s var(--ease); }
.activity details[open] .chev { transform: rotate(180deg); }
.activity summary:hover .more { color: var(--accent); }
@media (max-width: 560px) {
  .activity > details > summary { flex-wrap: wrap; row-gap: 4px; }
  .activity > details > summary .last { order: 3; flex-basis: 100%; }
  .activity summary .more { margin-left: auto; }
}
.feed { list-style: none; margin: 0; padding: 6px 14px 14px; border: 1px solid var(--border); border-top: 0; border-radius: 0 0 12px 12px; background: var(--surface); max-height: 460px; overflow-y: auto; }
.feed .grp { font: 600 .74rem var(--font); color: var(--muted); padding: 12px 0 4px; }
.feed .ev { display: grid; grid-template-columns: 62px 14px 1fr; gap: 8px; align-items: baseline; font-size: .84rem; padding: 3px 0; }
.feed .ev .ts { font: .74rem var(--font); font-variant-numeric: tabular-nums; color: var(--muted); }
.feed .ev .ic { width: 7px; height: 7px; border-radius: 50%; background: var(--border-strong); align-self: center; }
.feed .ev.success .ic { background: var(--accent); } .feed .ev.warn .ic { background: var(--warn); } .feed .ev.error .ic { background: var(--danger); } .feed .ev.gate .ic { background: var(--highlight); }
.feed .ev.new { animation: rise .35s var(--ease); }

.drawer-scrim { position: fixed; inset: 0; z-index: 60; background: color-mix(in srgb, var(--text) 28%, transparent); backdrop-filter: blur(2px); animation: rise .2s; }
.drawer { position: fixed; top: 0; right: 0; bottom: 0; z-index: 61; width: min(760px, 94vw); background: var(--bg); border-left: 1px solid var(--border); box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column; animation: slidein .32s var(--ease); padding-top: env(safe-area-inset-top, 0px); }
@keyframes slidein { from { transform: translateX(40px); opacity: .001; } }
/* Step reader. Head: kicker + title, the actions, then one status line (badge, time, cost) that never wraps;
   a hairline separates it from the scrolling body. Foot: previous / position / next, always visible. */
.drawer-head { flex: none; display: flex; flex-wrap: wrap; gap: 4px 12px; align-items: flex-start; justify-content: space-between;
  padding: 18px 24px 12px; border-bottom: 1px solid var(--border); background: var(--bg); position: relative; z-index: 3; }
.drawer-title { flex: 1 1 0; min-width: 0; }
.drawer-head .kicker { margin-bottom: 2px; }
.drawer-head h2 { font-size: 1.6rem; margin: 2px 0 2px; }
.drawer-actions { flex: none; display: flex; gap: 6px; align-items: center; }
.drawer-meta { flex: 1 0 100%; display: flex; align-items: center; gap: 10px; min-width: 0; white-space: nowrap; overflow: hidden;
  font-size: .84rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.drawer-meta > .badge { flex: none; }
.drawer-meta > span:not(.badge) { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.drawer-meta > span:not(.badge) + span:not(.badge)::before { content: "·"; margin-right: 10px; color: var(--border-strong); }
/* no top padding: the sticky wait bar then sits flush under the head, with nothing scrolling past above it */
.drawer-body { flex: 1; overflow-y: auto; padding: 0 24px 40px; overscroll-behavior: contain; }
.drawer-blurb { margin: 14px 0 0; }
/* re-run: what it resets and costs, then the note; the open form is the confirmation */
.rerun { margin: 14px 0 4px; }
.rerun-t { font: 600 .95rem/1.4 var(--font); letter-spacing: 0; margin: 0 0 4px; }
.rerun-impact { margin: 0 0 12px; font-size: .88rem; color: var(--text-2); }
.rerun .field { margin-bottom: 12px; }
.rerun textarea { min-height: 72px; }
.rerun-facts { margin: 0 0 12px; padding-left: 18px; font-size: .84rem; color: var(--text-2); }
.rerun-facts li + li { margin-top: 2px; }
.rerun-over { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; margin-bottom: 12px; }
.rerun-over > span { flex: 1 1 16em; }
.rerun-actions { gap: 8px; }
/* a waiting step: the one gold call to action, kept in view while the output scrolls under it. The sticky part
   is an opaque band in the drawer's own background, so nothing shows above the bar or around its corners and
   no heading is cut in half under it. */
.wait-wrap { position: sticky; top: 0; z-index: 2; background: var(--bg); padding: 12px 0 10px; }
.wait-wrap.block { margin-top: 10px; }
.wait-bar { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; padding: 10px 14px;
  border-radius: 10px; background: var(--gate-soft); color: var(--gate); border: 1px solid color-mix(in srgb, var(--highlight) 45%, var(--bg));
  font-size: .9rem; box-shadow: 0 6px 14px -10px color-mix(in srgb, var(--text) 30%, transparent); }
.wait-bar .txt { flex: 1 1 12em; min-width: 0; }
#focus { scroll-margin-top: 72px; }
.drawer-foot { flex: none; display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); align-items: center; gap: 8px;
  padding: 8px 16px calc(8px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--border); background: var(--bg); }
.dnav { display: block; min-width: 0; max-width: 100%; padding: 7px 10px; border: 0; border-radius: var(--radius-sm); background: transparent;
  font: 500 .86rem/1.4 var(--font); color: var(--text-2); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  justify-self: start; text-align: left; transition: background .15s, color .15s; }
.dnav.next { justify-self: end; text-align: right; }
.dnav:hover { background: var(--surface-2); color: var(--accent); }
.dnav-pos { font-size: .78rem; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 640px) {
  .drawer { width: 100vw; border-left: 0; }
  .drawer-head, .drawer-body { padding-inline: 16px; }
  .drawer-head { padding-top: 12px; padding-bottom: 10px; }
  .drawer-head .kicker { display: none; }
  .drawer-head h2 { font-size: 1.3rem; margin: 2px 0 0; }
  /* phones: the position stays (it is the only one); the links drop their 上一步： / 下一步： prefix to fit */
  .drawer-foot { display: flex; justify-content: space-between; align-items: center; gap: 6px; padding-inline: 8px; }
  .dnav { flex: 0 1 auto; }
  .dnav-k { display: none; }
}

/* ---------- composer (new research) ---------- */
/* block padding only: the inline 20px gutter comes from .container */
.compose-wrap { padding-block: 64px 40px; }
@media (max-width: 640px) { .compose-wrap { padding-block: 32px 28px; } }
.compose-title { font-size: clamp(2.2rem, 5.2vw, 3.3rem); text-align: center; margin-bottom: 10px; }
.compose-sub { text-align: center; color: var(--muted); margin-bottom: 26px; }
/* demo is neutral; the dashed badge is the screen's one demo marker */
.compose-demo, .compose-error { margin-bottom: 14px; }
/* the badge in its own column, so the sentence's second line never starts under it */
.compose-demo { display: flex; align-items: flex-start; gap: 10px; color: var(--text-2); line-height: 1.6; }
.compose-demo .badge { flex: none; height: 20px; margin: 1px 0 0; }
.compose-demo > span:last-child { text-wrap: balance; }
.composer { background: var(--surface); border: 1px solid var(--border-strong); border-radius: 22px; box-shadow: var(--shadow-lg); padding: 8px; transition: box-shadow .2s, border-color .2s; }
.composer:focus-within { border-color: var(--text); }
.composer textarea { border: 0; box-shadow: none; background: transparent; font-size: 1.08rem; padding: 14px 14px 6px; min-height: 96px; resize: none; }
.composer textarea:focus { box-shadow: none; }
/* settings wrap on the left; the send button keeps the bottom-right corner */
.composer-bar { display: flex; align-items: flex-end; gap: 6px; padding: 6px 6px 4px; }
.bar-opts { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; flex: 1; min-width: 0; }
.composer .send { flex: none; }
@media (max-width: 640px) { .composer-bar { flex-wrap: wrap; align-items: center; } .bar-opts { display: contents; } }
.pill-select { display: inline-flex; align-items: center; gap: 4px; margin: 0; padding: 0 4px 0 11px; height: 32px; border-radius: 999px; background: var(--surface-2); font: 500 .8rem var(--font); color: var(--muted); }
.pill-select select, .pill-select input { border: 0; background: transparent; padding: 0 6px; height: 30px; width: auto; font: 500 .82rem var(--font); color: var(--text); box-shadow: none; }
.pill-select input { width: 58px; font-variant-numeric: tabular-nums; -moz-appearance: textfield; appearance: textfield; }
.pill-select input::-webkit-inner-spin-button, .pill-select input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.pill-select select:focus, .pill-select input:focus { box-shadow: none; }
.pill-select:focus-within { box-shadow: inset 0 0 0 1px var(--border-strong); }
.pill-select.invalid { background: var(--danger-soft); color: var(--danger); }
/* demo budget: a fixed value, not a field */
.pill-static { padding-right: 12px; cursor: default; }
.pill-static .pill-v { padding-left: 6px; font: 500 .82rem var(--font); color: var(--text); }
.more-toggle { display: inline-flex; align-items: center; gap: 4px; height: 32px; padding: 0 6px 0 8px; border: 0; border-radius: 999px; background: transparent;
  color: var(--muted); font: 500 .8rem var(--font); cursor: pointer; }
.more-toggle:hover { color: var(--text); background: var(--surface-2); }
.more-toggle .chev { transition: transform .15s; }
.more-toggle[aria-expanded="true"] { color: var(--text); }
.more-toggle[aria-expanded="true"] .chev { transform: rotate(180deg); }
.composer .send { margin-left: auto; height: 40px; padding: 0 14px 0 18px; border: 0; border-radius: 999px; background: var(--text); color: var(--bg);
  display: inline-flex; align-items: center; gap: 6px; font: 600 .88rem var(--font); cursor: pointer; white-space: nowrap; transition: transform .15s, opacity .15s; }
.composer .send:hover { transform: translateY(-1px); }
.composer .send svg { transition: transform .15s; }
.composer .send:hover svg { transform: translateX(2px); }
.composer .send.busy { opacity: .6; cursor: progress; }
.composer-note { margin: 2px 12px 8px; font-size: .76rem; line-height: 1.6; color: var(--muted); }
.composer-more { border-top: 1px solid var(--border); margin: 6px 6px 0; padding: 14px 8px 6px; }
.composer-more .more-lead { margin: 0 0 12px; font-size: .8rem; color: var(--muted); }
/* labels may wrap to two lines; the fields still line up */
.composer-more .grid { row-gap: 0; align-items: end; }
.composer-more select { height: 46px; }
.composer-more .check { margin: 0; }
.examples { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 20px; }
.examples .chip { text-wrap: balance; }
@media (max-width: 640px) { .examples .chip { border-radius: 14px; padding: 8px 14px; } }
.mini-flow { list-style: none; margin: 46px auto 0; padding: 0; display: flex; justify-content: center; align-items: center; flex-wrap: wrap; gap: 8px 6px; font-size: .84rem; color: var(--muted); }
.mini-flow li { display: inline-flex; align-items: center; gap: 6px; }
.mini-flow .n { font: 600 .74rem var(--font); font-variant-numeric: tabular-nums; width: 20px; height: 20px; border-radius: 50%; display: inline-grid; place-items: center; background: var(--surface-3); color: var(--text-2); }
.mini-flow .sep { width: 18px; height: 1px; background: var(--border-strong); }
.compose-foot { max-width: 40em; margin: 12px auto 0; text-align: center; font-size: .8rem; line-height: 1.7; color: var(--muted); }
@media (max-width: 640px) {
  .mini-flow { margin-top: 32px; } .composer .send { padding: 0 12px 0 16px; }
  /* phones: a clean 2 × 2, with no connector that leads nowhere */
  .mini-flow { display: grid; grid-template-columns: repeat(2, max-content); justify-content: center; gap: 10px 28px; }
  .mini-flow .sep { display: none; }
}

/* ---------- dashboard ---------- */
.page-head { padding: 34px 0 18px; display: flex; justify-content: space-between; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
.page-head h1 { margin: 0 0 8px; font-size: 2.3rem; }
.status-strip { display: flex; gap: 8px; flex-wrap: wrap; }
.attention { display: grid; gap: 10px; margin-bottom: 30px; }
.attn { display: flex; gap: 14px; align-items: center; padding: 14px 18px; border-radius: 14px; background: linear-gradient(120deg, var(--gate-soft), var(--surface) 75%);
  border: 1px solid color-mix(in srgb, var(--highlight) 75%, var(--border)); color: var(--text); }
.attn:hover { text-decoration: none; box-shadow: var(--shadow); }
.attn .t { font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attn .g { font-size: .82rem; color: var(--gate); }
.attn .go { margin-left: auto; font-weight: 600; font-size: .86rem; white-space: nowrap; }
.plist { border: 1px solid var(--border); border-radius: 16px; background: var(--surface); overflow: hidden; margin-bottom: 60px; }
.prow { display: grid; grid-template-columns: minmax(0, 1fr) 150px 110px 130px; gap: 18px; align-items: center; padding: 16px 20px; color: var(--text); border-top: 1px solid var(--border); transition: background .15s; }
.prow:first-child { border-top: 0; }
.prow:hover { background: var(--surface-2); text-decoration: none; }
.dash-empty p { max-width: 36em; margin-inline: auto; text-wrap: balance; }
.prow.head { padding-top: 10px; padding-bottom: 10px; font-size: .75rem; font-weight: 600; color: var(--muted); }
.prow.head:hover { background: none; }
.prow .t { display: block; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prow .s { display: block; margin-top: 2px; font-size: .82rem; line-height: 1.5; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prow .s .badge { height: 18px; padding: 0 7px; font-size: .7rem; margin-left: 4px; vertical-align: 1px; }
.prow .spend-m { display: none; font-variant-numeric: tabular-nums; }
.prow .r { font: .82rem var(--font); font-variant-numeric: tabular-nums; color: var(--text-2); text-align: right; white-space: nowrap; }
.pcap { display: block; margin-top: 6px; font-size: .74rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pbar { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; }
.pbar i { height: 5px; border-radius: 3px; background: var(--surface-3); }
.pbar i.done { background: var(--accent); } .pbar i.active { background: linear-gradient(90deg, var(--glow), var(--surface-3)); background-size: 28px 100%; animation: flow 1.2s linear infinite; }
.pbar i.decide { background: var(--highlight); } .pbar i.failed { background: var(--danger); }
/* stopped and paused: grey, never gold, never moving; --muted stays visible on the dusk track too */
.pbar i.stopped, .pbar i.paused { background: var(--muted); }
@media (max-width: 760px) {
  .prow { grid-template-columns: minmax(0, 1fr) auto; }
  .prow .r, .prow .b, .prow.head { display: none; }
  .prow.head + .prow { border-top: 0; }
  .prow .spend-m { display: block; }
}

/* ---------- public sections (enterprise page) ---------- */
.section { padding: 76px 0; }
.section.tight { padding: 44px 0; }
.loop-line { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; counter-reset: s; }
@media (max-width: 820px) { .loop-line { grid-template-columns: 1fr 1fr; } }
.loop-line > div { padding: 18px; border-radius: 16px; background: var(--surface); border: 1px solid var(--border); }
.loop-line .who { font: 500 .7rem var(--mono); text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.loop-line h4 { margin: 6px 0 4px; font-size: 1rem; }
.loop-line p { font-size: .86rem; color: var(--text-2); margin: 0; }
.footer { padding: 30px 0 40px; border-top: 1px solid var(--border); color: var(--muted); font-size: .84rem; }
.footer .row { gap: 10px; }
.footer-links { display: flex; flex-wrap: wrap; gap: 8px 22px; margin-bottom: 16px; }
.footer-links a { color: var(--text-2); }
.footer-links a:hover { color: var(--text); }

/* ---------- auth (sign-up, sign-in, password help) ---------- */
.auth-wrap { min-height: calc(100vh - 56px); display: grid; place-items: center; padding: 32px 16px; }
.auth-card { width: 100%; max-width: 420px; padding: 32px; border-radius: 20px; }
.auth-card h2 { font-size: 2rem; margin-bottom: 8px; }
.auth-sub { color: var(--text-2); font-size: .92rem; margin-bottom: 16px; }
.auth-demo { margin: -4px 0 16px; font-size: .8rem; line-height: 1.6; color: var(--muted); }
.auth-demo .badge { height: 20px; margin-right: 4px; vertical-align: 1px; }
.auth-alert { margin-bottom: 14px; }
.auth-label { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin-bottom: 6px; }
.auth-label label { margin: 0; }
.auth-submit { width: 100%; margin-top: 4px; }
.auth-switch { margin: 18px 0 0; text-align: center; font-size: .87rem; color: var(--muted); }
.auth-contact { padding: 12px 14px; border-radius: 10px; background: var(--surface-2); font-size: .92rem; overflow-wrap: anywhere; }
.auth-contact .muted { display: block; font-size: .78rem; }
/* phones: the card sits near the top, not floating mid-screen */
@media (max-width: 640px) {
  .auth-wrap { min-height: auto; place-items: start center; padding: 40px 16px; }
  .auth-card { padding: 24px; }
}

/* ---------- error page ---------- */
.error-page h1 { font: 500 clamp(1.8rem, 4.4vw, 2.4rem)/1.2 var(--display); margin-bottom: 10px; }
.error-page .kicker { font-variant-numeric: tabular-nums; }
.error-page .btn { margin-top: 10px; }
