/* TradingAgents Web — single stylesheet (no inline styles: CSP style-src 'self'). Mobile first. */

:root {
  color-scheme: light dark;
  --bg: #f3f5f8;
  --surface: #ffffff;
  --surface-2: #f7f9fb;
  --surface-3: #eef2f6;
  --border: #e1e6ed;
  --border-strong: #c9d1dc;
  --text: #16202c;
  --text-2: #36465a;
  --muted: #5d6a7e;
  --brand: #1d4ed8;
  --brand-hover: #1e40af;
  --brand-soft: #e9efff;
  --on-brand: #ffffff;
  --focus: #2563eb;
  --ok: #0c7a4a;
  --ok-soft: #e3f4eb;
  --warn: #8a5300;
  --warn-soft: #fff3de;
  --warn-border: #f1cf94;
  --err: #b42318;
  --err-soft: #fdeceb;
  --err-border: #f3b7b1;
  --info: #1d4ed8;
  --info-soft: #eaf0ff;
  --info-border: #bdd0fb;
  /* WCAG: text on .btn-danger ≥ 4.5:1; the favourite star is a text glyph, so ≥ 4.5:1 on every
     surface and soft tint; input borders ≥ 3:1 (UI components) */
  --on-err: #ffffff;
  --star: #8a5e00;
  --control-border: #838e9e;

  /* ratings: neutral, distinct hues (never red/green, which mean up/down in A-share charts) */
  --r-buy-bg: #1747b5; --r-buy-fg: #ffffff; --r-buy-bd: #1747b5;
  --r-ow-bg: #dfe8fd; --r-ow-fg: #173f9c; --r-ow-bd: #9fb8f5;
  --r-hold-bg: #eceff3; --r-hold-fg: #3a4555; --r-hold-bd: #c7cfd9;
  --r-uw-bg: #fdecd3; --r-uw-fg: #7a4300; --r-uw-bd: #eec27f;
  --r-sell-bg: #8a4100; --r-sell-fg: #ffffff; --r-sell-bd: #8a4100;
  --r-review-bg: #f1e8fc; --r-review-fg: #5a2d91; --r-review-bd: #b894e6;

  --ma20: #d97706;
  --ma60: #7c3aed;
  --marker: #1d4ed8;

  --radius: 12px;
  --radius-sm: 8px;
  --shadow: 0 1px 2px rgba(15, 23, 42, .05), 0 1px 3px rgba(15, 23, 42, .06);
  --shadow-lg: 0 10px 30px rgba(15, 23, 42, .14);
  --font: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: ui-monospace, "SFMono-Regular", "Cascadia Mono", Consolas, "Liberation Mono", monospace;
  --header-h: 56px;
}

/* Dark tokens live twice on purpose: once for the system preference (unless the saved
   theme pins light) and once for an explicitly saved dark theme. CSS has no way to share
   one declaration block between a media query and a plain selector. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0e1217;
    --surface: #161b22;
    --surface-2: #1b2129;
    --surface-3: #222933;
    --border: #2a323d;
    --border-strong: #3a4452;
    --text: #e6eaf0;
    --text-2: #c3cad4;
    --muted: #97a2b1;
    --brand: #6d9bff;
    --brand-hover: #8fb2ff;
    --brand-soft: #1b2a4a;
    --on-brand: #0b1220;
    --focus: #8fb2ff;
    --ok: #4fd39a;
    --ok-soft: #12291f;
    --warn: #f2b85b;
    --warn-soft: #2b2112;
    --warn-border: #5c4520;
    --err: #ff8a80;
    --err-soft: #331716;
    --err-border: #6a2c28;
    --info: #8fb2ff;
    --info-soft: #172240;
    --info-border: #2d437a;
    --on-err: #1f0a08;
    --star: #d99a00;
    --control-border: #67727f;

    --r-buy-bg: #5b8cff; --r-buy-fg: #08112a; --r-buy-bd: #5b8cff;
    --r-ow-bg: #1c2c52; --r-ow-fg: #a9c3ff; --r-ow-bd: #36508e;
    --r-hold-bg: #262d37; --r-hold-fg: #cdd4de; --r-hold-bd: #414b59;
    --r-uw-bg: #35260f; --r-uw-fg: #f5c77e; --r-uw-bd: #6b4b1b;
    --r-sell-bg: #e3953f; --r-sell-fg: #1d1203; --r-sell-bd: #e3953f;
    --r-review-bg: #2c1f42; --r-review-fg: #d2b6f7; --r-review-bd: #5f4690;

    --ma20: #f59e0b;
    --ma60: #a78bfa;
    --marker: #8fb2ff;
    --shadow: 0 1px 2px rgba(0, 0, 0, .3);
    --shadow-lg: 0 12px 32px rgba(0, 0, 0, .5);
  }
}

:root[data-theme="dark"] {
  --bg: #0e1217;
  --surface: #161b22;
  --surface-2: #1b2129;
  --surface-3: #222933;
  --border: #2a323d;
  --border-strong: #3a4452;
  --text: #e6eaf0;
  --text-2: #c3cad4;
  --muted: #97a2b1;
  --brand: #6d9bff;
  --brand-hover: #8fb2ff;
  --brand-soft: #1b2a4a;
  --on-brand: #0b1220;
  --focus: #8fb2ff;
  --ok: #4fd39a;
  --ok-soft: #12291f;
  --warn: #f2b85b;
  --warn-soft: #2b2112;
  --warn-border: #5c4520;
  --err: #ff8a80;
  --err-soft: #331716;
  --err-border: #6a2c28;
  --info: #8fb2ff;
  --info-soft: #172240;
  --info-border: #2d437a;
  --on-err: #1f0a08;
  --star: #d99a00;
  --control-border: #67727f;

  --r-buy-bg: #5b8cff; --r-buy-fg: #08112a; --r-buy-bd: #5b8cff;
  --r-ow-bg: #1c2c52; --r-ow-fg: #a9c3ff; --r-ow-bd: #36508e;
  --r-hold-bg: #262d37; --r-hold-fg: #cdd4de; --r-hold-bd: #414b59;
  --r-uw-bg: #35260f; --r-uw-fg: #f5c77e; --r-uw-bd: #6b4b1b;
  --r-sell-bg: #e3953f; --r-sell-fg: #1d1203; --r-sell-bd: #e3953f;
  --r-review-bg: #2c1f42; --r-review-fg: #d2b6f7; --r-review-bd: #5f4690;

  --ma20: #f59e0b;
  --ma60: #a78bfa;
  --marker: #8fb2ff;
  --shadow: 0 1px 2px rgba(0, 0, 0, .3);
  --shadow-lg: 0 12px 32px rgba(0, 0, 0, .5);
}

:root[data-theme="dark"] { color-scheme: dark; }
:root[data-theme="light"] { color-scheme: light; }

/* ---------------------------------------------------------------- base */

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-padding-top: calc(var(--header-h) + 12px); }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.6;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
}
a { color: var(--brand); text-decoration: none; text-underline-offset: 2px; }
a:hover { text-decoration: underline; }
h1, h2, h3, h4 { line-height: 1.3; margin: 0 0 .5em; color: var(--text); }
h1 { font-size: 1.5rem; font-weight: 700; letter-spacing: .01em; }
h2 { font-size: 1.1rem; font-weight: 650; }
h3 { font-size: 1rem; font-weight: 650; }
p { margin: 0 0 .75em; }
p:last-child { margin-bottom: 0; }
img, svg, canvas { max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 4px; }
::selection { background: var(--brand-soft); }

.muted { color: var(--muted); }
.small { font-size: .85rem; }
.nowrap { white-space: nowrap; }
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 12px; top: -60px; z-index: 100; padding: 8px 14px;
  background: var(--brand); color: var(--on-brand); border-radius: var(--radius-sm);
}
.skip-link:focus { top: 8px; }

.container { width: 100%; max-width: 1240px; margin: 0 auto; padding: 0 16px; }
.main { flex: 1; padding-top: 20px; padding-bottom: 40px; outline: none; }
.stack > * + * { margin-top: 14px; }

/* ---------------------------------------------------------------- header */

.site-header {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: saturate(160%) blur(10px);
  border-bottom: 1px solid var(--border);
}
.header-inner { display: flex; align-items: center; gap: 12px; min-height: var(--header-h); flex-wrap: wrap; }
.brand { display: inline-flex; align-items: center; gap: 8px; color: var(--text); font-weight: 700; white-space: nowrap; }
.brand:hover { text-decoration: none; }
.brand-mark {
  display: inline-grid; place-items: center; width: 30px; height: 30px; border-radius: 8px;
  background: var(--brand); color: var(--on-brand); font-size: .8rem; font-weight: 800; letter-spacing: .02em;
}
.brand-mark-lg { width: 44px; height: 44px; font-size: 1rem; border-radius: 11px; }
.brand-text { font-size: 1.02rem; }

.main-nav {
  order: 3; flex-basis: 100%; display: flex; gap: 2px; overflow-x: auto; scrollbar-width: none;
  margin: 0 -16px; padding: 0 12px 6px;
}
.main-nav::-webkit-scrollbar { display: none; }
.main-nav a {
  flex: none; padding: 7px 12px; border-radius: 999px; color: var(--text-2); font-size: .92rem; white-space: nowrap;
}
.main-nav a:hover { background: var(--surface-3); text-decoration: none; }
.main-nav a[aria-current="page"] { background: var(--brand-soft); color: var(--brand); font-weight: 600; }

.dropdown { position: relative; margin-left: auto; }
/* 新建分析 sits right before the account menu and takes over its push to the right edge */
.header-cta { margin-left: auto; flex: none; white-space: nowrap; }
.header-cta + .dropdown { margin-left: 0; }
.header-cta[aria-current="page"] { box-shadow: 0 0 0 2px var(--brand-soft); }
.dropdown > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  padding: 4px 8px 4px 4px; border-radius: 999px; border: 1px solid transparent;
}
.dropdown > summary::-webkit-details-marker { display: none; }
.dropdown > summary:hover, .dropdown[open] > summary { background: var(--surface-3); }
.avatar {
  display: inline-grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
  background: var(--surface-3); color: var(--text-2); font-weight: 700; font-size: .85rem; border: 1px solid var(--border);
}
.user-name { max-width: 9em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: .92rem; display: none; }
.dropdown-panel {
  position: absolute; right: 0; top: calc(100% + 6px); min-width: 180px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); box-shadow: var(--shadow-lg);
  display: grid; gap: 2px; z-index: 50;
}
.dropdown-panel a, .menu-button {
  display: block; width: 100%; text-align: left; padding: 8px 10px; border-radius: 6px; color: var(--text);
  background: none; border: 0; cursor: pointer; font-size: .92rem;
}
.dropdown-panel a:hover, .menu-button:hover { background: var(--surface-3); text-decoration: none; }
.dropdown-panel form { margin: 0; }

@media (min-width: 900px) {
  .header-inner { flex-wrap: nowrap; }
  .main-nav { order: 0; flex-basis: auto; margin: 0 0 0 16px; padding: 0; overflow: visible; }
  .user-name { display: inline; }
}
/* From 900 px the header no longer wraps. Let the navigation shrink and scroll sideways (its
   scrollbar stays hidden, as on phones) instead of pushing the account menu past the window: with
   模拟交易 on and a long 显示名称 the page scrolled horizontally at 900-1060 px. */
@media (min-width: 900px) {
  .main-nav { min-width: 0; overflow-x: auto; }
}

/* ---------------------------------------------------------------- footer */

.site-footer { border-top: 1px solid var(--border); background: var(--surface); padding: 18px 0 22px; }
.footer-inner p { margin: 0 0 4px; }
.disclaimer { color: var(--text-2); font-size: .9rem; }

/* ---------------------------------------------------------------- layout */

.page-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.page-head h1 { margin-bottom: 4px; }
.page-head p { margin: 0; }
.actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

.layout-main-side { display: grid; gap: 16px; align-items: start; }
.side-column { display: grid; gap: 16px; }
@media (min-width: 1024px) {
  .layout-main-side { grid-template-columns: minmax(0, 1fr) 340px; }
  .side-column { position: sticky; top: calc(var(--header-h) + 16px); }
}

.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 16px;
}
.card + .card, .card + section, section + .card { margin-top: 16px; }
.layout-main-side > .card + .card, .side-column > .card + .card { margin-top: 0; }
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.card-head h2 { margin: 0; }
@media (min-width: 720px) { .card { padding: 20px 22px; } }

/* ---------------------------------------------------------------- buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 38px;
  padding: 7px 16px; border-radius: var(--radius-sm); border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text); font-weight: 600; font-size: .92rem; line-height: 1.2;
  cursor: pointer; white-space: nowrap; text-decoration: none; user-select: none;
  transition: background-color .15s, border-color .15s, color .15s;
}
.btn:hover { text-decoration: none; background: var(--surface-3); }
/* Disabled buttons use explicit colours instead of opacity .5 (which left text at ~3.2:1). */
.btn:disabled, .btn.is-disabled {
  cursor: not-allowed; pointer-events: none;
  background: var(--surface-3); border-color: var(--border); color: var(--muted); filter: none;
}
.btn-primary { background: var(--brand); border-color: var(--brand); color: var(--on-brand); }
.btn-primary:hover { background: var(--brand-hover); border-color: var(--brand-hover); }
.btn-secondary { background: var(--surface); }
.btn-ghost { background: transparent; border-color: transparent; color: var(--text-2); }
.btn-ghost:hover { background: var(--surface-3); }
.btn-ghost:disabled, .btn-ghost.is-disabled { background: transparent; border-color: transparent; }
.btn-danger { background: var(--err); border-color: var(--err); color: var(--on-err); }
.btn-danger:hover { filter: brightness(.92); background: var(--err); }
.danger-text { color: var(--err); }
.btn-sm { min-height: 32px; padding: 5px 11px; font-size: .86rem; }
.btn-lg { min-height: 46px; padding: 10px 24px; font-size: 1rem; }
.btn-block { width: 100%; }
.icon-button {
  display: inline-grid; place-items: center; width: 32px; height: 32px; border-radius: 50%;
  border: 1px solid transparent; background: transparent; cursor: pointer; font-size: 1.15rem; color: var(--muted); line-height: 1;
}
.icon-button:hover { background: var(--surface-3); }
.star.is-on { color: var(--star); }
.inline-form { display: inline; margin: 0; }

/* ---------------------------------------------------------------- forms */

.field { display: grid; gap: 6px; margin: 0 0 16px; min-width: 0; }
.field.compact { margin-bottom: 0; }
fieldset.field { border: 0; padding: 0; }
label, legend { font-weight: 600; font-size: .92rem; color: var(--text); }
legend { padding: 0; margin-bottom: 8px; }
/* A field that is only text (分析师团队 since 2026-09-22): the heading of a <label>, with no control. */
.field-label { font-weight: 600; font-size: .92rem; color: var(--text); margin: 0; }
.hint { font-size: .82rem; color: var(--muted); margin: 0; line-height: 1.5; }
.clamp-3 { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

input[type="text"], input[type="search"], input[type="password"], input[type="date"], input:not([type]), select, textarea {
  width: 100%; min-height: 40px; padding: 8px 11px; border-radius: var(--radius-sm);
  border: 1px solid var(--control-border); background: var(--surface); color: var(--text); font-size: 1rem;
  transition: border-color .15s, box-shadow .15s;
}
textarea { resize: vertical; line-height: 1.5; font-family: var(--mono); font-size: .95rem; }
select { appearance: auto; }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--focus); box-shadow: 0 0 0 3px color-mix(in srgb, var(--focus) 25%, transparent); }
input::placeholder, textarea::placeholder { color: var(--muted); opacity: 1; }
input[type="checkbox"], input[type="radio"] { width: 18px; height: 18px; accent-color: var(--brand); margin: 0; flex: none; }

.field-row { display: grid; gap: 0 14px; }
@media (min-width: 640px) {
  .field-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .field-row.three { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px; }
}
.field-row.three { gap: 12px; }
.field-row.three .field input[data-custom-input] { margin-top: 6px; }

.form-card { padding-bottom: 20px; }
.form-actions { display: grid; gap: 8px; justify-items: start; margin-top: 8px; padding-top: 16px; border-top: 1px solid var(--border); }
@media (max-width: 639px) { .form-actions .btn { width: 100%; } }

.symbol-field input { font-size: 1.15rem; font-weight: 600; letter-spacing: .02em; min-height: 48px; }
.symbol-status { min-height: 1.5em; font-size: .9rem; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.symbol-status .sym-name { font-weight: 700; color: var(--text); }
.symbol-status .sym-error { color: var(--err); }
.symbol-status .sym-loading { color: var(--muted); }

.check-inline { display: inline-flex; align-items: center; gap: 8px; font-weight: 400; cursor: pointer; }

.segmented { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.segment { position: relative; cursor: pointer; font-weight: 400; }
.segment input { position: absolute; opacity: 0; inset: 0; width: 100%; height: 100%; cursor: pointer; }
.segment-body {
  display: grid; gap: 1px; text-align: center; padding: 9px 6px; border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm); background: var(--surface); transition: border-color .15s, background-color .15s;
}
.segment-body small { color: var(--muted); font-size: .78rem; }
.segment input:checked + .segment-body { border-color: var(--brand); background: var(--brand-soft); color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }
.segment input:focus-visible + .segment-body { outline: 3px solid var(--focus); outline-offset: 2px; }

.input-with-button { display: flex; gap: 8px; }
.input-with-button input { flex: 1; }

.quota-pill {
  display: inline-flex; align-items: baseline; gap: 4px; padding: 6px 14px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--border); font-size: .92rem; white-space: nowrap;
}
.quota-pill strong { font-size: 1.15rem; color: var(--brand); }
.quota-pill.is-empty strong { color: var(--err); }

/* ---------------------------------------------------------------- alerts & toasts */

.alert {
  border: 1px solid var(--info-border); background: var(--info-soft); color: var(--text);
  border-radius: var(--radius-sm); padding: 10px 14px; margin: 0 0 14px; font-size: .94rem;
}
.alert p { margin: 0 0 6px; }
.alert p:last-child { margin: 0; }
.alert form { margin-top: 8px; }
.alert-success { border-color: color-mix(in srgb, var(--ok) 35%, transparent); background: var(--ok-soft); }
.alert-warn { border-color: var(--warn-border); background: var(--warn-soft); }
.alert-error { border-color: var(--err-border); background: var(--err-soft); }
.alert-error > p:first-child, .failure-box h2 { color: var(--err); }
.failure-box h2 { font-size: 1.05rem; margin-bottom: 6px; }
.error-text { white-space: pre-wrap; word-break: break-word; font-family: var(--mono); font-size: .86rem; }
.compact-list { margin: 6px 0 0; padding-left: 1.2em; }
.compact-list li + li { margin-top: 2px; }
.notice { margin: -4px 0 12px; }

.toasts {
  position: fixed; z-index: 60; right: 16px; left: 16px; bottom: 16px; display: grid; gap: 8px; pointer-events: none;
}
@media (min-width: 640px) { .toasts { left: auto; width: 380px; } }
.toast {
  pointer-events: auto; display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-lg); animation: toast-in .2s ease-out;
}
.toast-body { flex: 1; min-width: 0; }
.toast-body a { font-weight: 600; }
.toast-success { border-left: 4px solid var(--ok); }
.toast-error { border-left: 4px solid var(--err); }
.toast-info { border-left: 4px solid var(--brand); }
.toast-warn { border-left: 4px solid var(--warn); }
.toast-close { border: 0; background: none; cursor: pointer; color: var(--muted); font-size: 1.1rem; line-height: 1; padding: 2px; }
@keyframes toast-in { from { transform: translateY(8px); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---------------------------------------------------------------- badges & chips */

.rating {
  display: inline-flex; align-items: center; justify-content: center; min-width: 3.2em; padding: 2px 10px;
  border-radius: 6px; font-weight: 700; font-size: .88rem; letter-spacing: .08em; border: 1px solid; white-space: nowrap;
}
.rating-sm { font-size: .78rem; padding: 0 7px; min-width: 2.8em; letter-spacing: .04em; }
.rating-lg { font-size: 1.25rem; padding: 6px 18px; border-radius: 10px; }
.rating-buy { background: var(--r-buy-bg); color: var(--r-buy-fg); border-color: var(--r-buy-bd); }
.rating-overweight { background: var(--r-ow-bg); color: var(--r-ow-fg); border-color: var(--r-ow-bd); }
.rating-hold { background: var(--r-hold-bg); color: var(--r-hold-fg); border-color: var(--r-hold-bd); }
.rating-underweight { background: var(--r-uw-bg); color: var(--r-uw-fg); border-color: var(--r-uw-bd); }
.rating-sell { background: var(--r-sell-bg); color: var(--r-sell-fg); border-color: var(--r-sell-bd); }
.rating-review { background: var(--r-review-bg); color: var(--r-review-fg); border-color: var(--r-review-bd); border-style: dashed; }

.status { display: inline-flex; align-items: center; gap: 6px; font-size: .84rem; color: var(--text-2); white-space: nowrap; }
.status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); flex: none; }
.status-queued .status-dot { background: transparent; border: 2px solid var(--muted); }
.status-running { color: var(--brand); font-weight: 600; }
.status-running .status-dot { background: var(--brand); animation: pulse 1.4s ease-in-out infinite; }
.status-done .status-dot { background: var(--ok); }
.status-failed { color: var(--err); font-weight: 600; }
.status-failed .status-dot { background: var(--err); }
.status-interrupted { color: var(--warn); }
.status-interrupted .status-dot { background: var(--warn); }
.status-cancelled .status-dot { background: var(--border-strong); }
@keyframes pulse { 50% { opacity: .35; } }

.symbol { font-family: var(--mono); font-size: .86em; color: var(--muted); font-weight: 500; letter-spacing: 0; }
.symbol-lg { font-size: .6em; vertical-align: middle; }
.tag-market { font-size: .74rem; padding: 0 6px; border-radius: 4px; background: var(--surface-3); color: var(--text-2); white-space: nowrap; }

.chip-list { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0; padding: 0; }
.chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface); font-size: .84rem; color: var(--text-2);
}
a.chip:hover { border-color: var(--brand); text-decoration: none; }
.chip.is-active { border-color: var(--brand); background: var(--brand-soft); color: var(--brand); font-weight: 600; }
/* the radar signal chips carry today's hit count: a selected signal with 0 is why the list did not change */
.chip .chip-count { margin-left: 5px; padding: 0 5px; border-radius: 8px; font-size: .72rem; font-weight: 600;
  background: color-mix(in srgb, currentColor 12%, transparent); }
.chip-ok { border-color: color-mix(in srgb, var(--ok) 40%, transparent); }
.chip-error { border-color: var(--err-border); background: var(--err-soft); color: var(--err); }
.chip-warn { border-color: var(--warn-border); background: var(--warn-soft); color: var(--warn); font-size: .78rem; }
.tag-list { display: flex; flex-wrap: wrap; gap: 6px; }
.tag { font-size: .82rem; color: var(--text-2); background: var(--surface-3); padding: 1px 8px; border-radius: 4px; }
.tag:hover { color: var(--brand); text-decoration: none; }

/* ---------------------------------------------------------------- lists */

.plain-list { list-style: none; margin: 0; padding: 0; }
.recent-item { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 9px 0; border-top: 1px solid var(--border); }
.recent-item:first-child { border-top: 0; padding-top: 2px; }
.recent-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font-weight: 500; }
.recent-meta { display: inline-flex; align-items: center; gap: 8px; flex: none; }

.job-mini-list { list-style: none; margin: 0 0 8px; padding: 0; display: grid; gap: 10px; }
.job-mini { padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2); }
.job-mini-head { display: flex; justify-content: space-between; gap: 8px; align-items: center; }
.job-mini-title { font-weight: 600; color: var(--text); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.job-mini-meta { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin: 2px 0 6px; }
.job-mini-current { margin: 4px 0 0; min-height: 1.3em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.grid-list { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }

.progress {
  -webkit-appearance: none; appearance: none; display: block; width: 100%; height: 8px; border: 0; border-radius: 999px;
  background: var(--surface-3); overflow: hidden; color: var(--brand);
}
.progress::-webkit-progress-bar { background: var(--surface-3); border-radius: 999px; }
.progress::-webkit-progress-value { background: var(--brand); border-radius: 999px; transition: width .4s ease; }
.progress::-moz-progress-bar { background: var(--brand); border-radius: 999px; }

meter { width: 100%; height: 10px; }

.empty { text-align: center; padding: 40px 16px; border: 1px dashed var(--border-strong); border-radius: var(--radius); background: var(--surface); }
.empty-title { font-weight: 650; font-size: 1.05rem; margin-bottom: 6px; }
.empty .btn { margin-top: 12px; }

/* ---------------------------------------------------------------- confirm popovers (details) */

.confirm { position: relative; display: inline-block; }
.confirm > summary { list-style: none; }
.confirm > summary::-webkit-details-marker { display: none; }
.confirm-panel {
  position: absolute; z-index: 30; top: calc(100% + 6px); left: 0; width: min(300px, calc(100vw - 32px));
  padding: 12px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg); font-size: .9rem; text-align: left; white-space: normal;
}
.confirm.align-right .confirm-panel { left: auto; right: 0; }
.confirm-panel p { margin: 0 0 10px; color: var(--text-2); }
.confirm-panel form { margin: 0; }
/* 团队管理 (manage_users.html): its 重设密码 / 禁用 / 删除 panels sit in the last column of a
   .table-wrap, whose overflow-x:auto clips vertically too — the panel was cut to the row's
   height and the scroller scrolled to it instead (owner report 2026-09-21, worse on phones).
   A fixed sheet escapes the scroller: centred on a desktop, a bottom sheet on a phone.
   z-index above the sticky header (40) and below the toasts (60). Escape and an outside
   click still close it (app.js details.confirm handling). */
.manage-table .confirm { position: static; }
.manage-table .confirm-panel {
  position: fixed; z-index: 45; top: 50%; left: 50%; right: auto; bottom: auto; transform: translate(-50%, -50%);
  width: min(380px, calc(100vw - 32px)); max-height: calc(100vh - 32px); overflow: auto;
}
@media (max-width: 720px) {
  .manage-table .confirm-panel { top: auto; left: 12px; right: 12px; bottom: 12px; transform: none; width: auto; max-height: calc(100vh - 24px); }
}
/* Every other confirm popover on a phone (owner report 2026-09-27: 研报库 删除 and 取消任务). Anchored to its
   button, a 300 px panel beside a button in the left half of a 375 px screen ran off the left edge: half the
   message showed, the 确认 button did not, and the page could not scroll to it. Below 720 px every confirm
   panel is the 团队管理 bottom sheet above. details.confirm[open] > .confirm-panel (0,3,1) outranks
   .confirm.align-right .confirm-panel (0,3,0) and the .bulk-bar / .radar-actions rules; panels that open in
   place on phones elsewhere keep their own, more specific rule. Wider screens keep the anchored
   popover, and app.js shifts it back inside the viewport when it would cross an edge. */
@media (max-width: 720px) {
  details.confirm[open] > .confirm-panel {
    position: fixed; z-index: 45; top: auto; left: 12px; right: 12px; bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    transform: none; width: auto; min-width: 0; max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px); overflow: auto;
  }
}
.rerun-panel form + form { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.rerun-panel label { display: block; margin-bottom: 6px; }

/* ---------------------------------------------------------------- tables */

/* position: relative so an absolutely positioned child (a .sr-only <caption>) is contained
   here instead of by the viewport, where its static position inside a wide table would
   give the whole page a horizontal scrollbar on a phone. */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 0 -4px; padding: 0 4px; position: relative; }
.table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.table th, .table td { padding: 8px 10px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; }
.table th { font-weight: 600; color: var(--muted); font-size: .82rem; white-space: nowrap; background: var(--surface-2); }
.table tbody tr:hover { background: var(--surface-2); }
.col-bar { min-width: 110px; }

/* ---------------------------------------------------------------- library */

.filter-card { padding: 12px; }
.filter-search { display: flex; gap: 8px; }
.filter-search input { flex: 1; }
.filter-search { flex-wrap: wrap; }
.filter-search input[type="search"] { min-width: 180px; }
.filter-body { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; color: var(--text-2); font-size: .9rem; min-height: 40px; }
.filter-note { margin: 8px 0 0; color: var(--text-2); font-size: .85rem; }
.filter-more { margin-top: 10px; }
.filter-more > summary { cursor: pointer; color: var(--text-2); font-size: .9rem; width: max-content; }
.filter-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); margin-top: 10px; align-items: end; }
.filter-fav { min-height: 40px; }
.filter-actions { display: flex; gap: 8px; margin-top: 12px; }

.report-list { list-style: none; margin: 16px 0 0; padding: 0; display: grid; gap: 10px; }
.report-list .card + .card { margin-top: 0; }
.report-row { display: grid; gap: 10px; padding: 12px 14px; }
.report-row-title { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.report-link { font-weight: 650; font-size: 1.02rem; color: var(--text); }
.report-row-meta { display: flex; flex-wrap: wrap; gap: 2px 14px; margin: 4px 0 0 40px; }
.report-row .tag-list { margin: 6px 0 0 40px; }
.report-row-side { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
@media (min-width: 720px) {
  .report-row { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
  .report-row-side { justify-content: flex-end; }
}

/* 研报库价格块 (owner request 2026-09-21, report library prices). Line one: the live price and,
   beside it, the change since analysis, the only coloured figure of the row (.q-up / .q-down under
   the row's market class, so 涨跌颜色 and US green-up apply). Line two: the quote state (filled dot
   = the market is trading) and the analysis-time price. Phones put the two prices side by side,
   analysis left and live right; from 900 px the block is a fixed-width column between the title and
   the chips, so the numbers change in place and nothing around them moves. */
.lib-price {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "label state" "ref now";
  align-items: end; gap: 2px 12px; min-width: 0; padding-top: 9px; border-top: 1px solid var(--surface-3);
  font-variant-numeric: tabular-nums;
}
.lib-meta, .lib-ref { display: contents; }
.lib-ref-label { grid-area: label; font-size: .78rem; color: var(--muted); }
.lib-ref-price { grid-area: ref; font-size: .92rem; color: var(--text-2); overflow-wrap: anywhere; }
.lib-state { grid-area: state; justify-self: end; display: inline-flex; align-items: center; gap: 5px; font-size: .78rem; color: var(--muted); white-space: nowrap; }
.lib-sep { display: none; }
.lib-now { grid-area: now; justify-self: end; display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: baseline; gap: 2px 8px; }
.lib-live { font-size: 1.2rem; font-weight: 650; color: var(--text); white-space: nowrap; }
.lib-chg { min-width: 4.4em; text-align: right; font-size: .92rem; font-weight: 650; color: var(--muted); white-space: nowrap; }
.lib-chg.q-up { color: var(--rise); }
.lib-chg.q-down { color: var(--fall); }
/* 期间除权除息: both prices shown, no change (the two are on different bases) */
.lib-chg.lib-flag { min-width: 0; padding: 1px 7px; border: 1px solid var(--warn-border); border-radius: 6px; background: var(--warn-soft); color: var(--warn); font-size: .76rem; font-weight: 600; }
/* before the first quote answer: a placeholder, not a dash that would read as "no price" */
.lib-price .is-pending { color: transparent; background: var(--surface-3); border-radius: 5px; }
.lib-live.is-pending { min-width: 4.6em; }
.lib-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; border: 1.5px solid var(--control-border); flex: none; }
.lib-dot.is-live { background: var(--ok); border-color: var(--ok); }
.lib-note { display: flex; align-items: center; gap: 6px; margin-top: 2px; }
@media (min-width: 720px) {
  .report-row > .report-row-side { grid-row: 1; grid-column: 2; }
  .report-row > .lib-price { grid-row: 2; grid-column: 1 / -1; }
}
@media (min-width: 900px) {
  .report-row { grid-template-columns: minmax(0, 1fr) auto auto; }
  .report-row > .lib-price { grid-row: 1; grid-column: 2; }
  .report-row > .report-row-side { grid-column: 3; }
  .lib-price { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; width: 15rem; padding-top: 0; border-top: 0; }
  .lib-meta { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 2px 6px; font-size: .78rem; color: var(--muted); }
  .lib-ref { display: inline-flex; align-items: baseline; gap: 4px; white-space: nowrap; }
  .lib-ref-label, .lib-ref-price, .lib-state { font-size: inherit; color: inherit; }
  .lib-sep { display: inline; color: var(--border-strong); }
  .lib-live { font-size: 1.25rem; }
}
.pagination { display: flex; align-items: center; justify-content: center; gap: 14px; margin-top: 18px; }

/* ---------------------------------------------------------------- report detail */

.breadcrumb { display: flex; gap: 8px; font-size: .88rem; color: var(--muted); margin-bottom: 10px; }
.report-head { display: grid; gap: 14px; }
.report-head-top { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; align-items: flex-start; }
.report-title h1 { margin: 0 0 4px; font-size: 1.6rem; }
/* the title links to the symbol's chart page: the name keeps the heading colour, the code and the
   chart glyph carry the affordance (owner, 2026-09-19: a black title looked unclickable) */
.symbol-link { color: inherit; text-decoration: none; }
.symbol-link .symbol-lg { color: var(--brand); }
.symbol-link-icon { width: .62em; height: .62em; margin-left: .32em; color: var(--brand); vertical-align: middle; }
.symbol-link:hover, .symbol-link:focus-visible { color: var(--brand); }
.symbol-link:hover .symbol-lg, .symbol-link:focus-visible .symbol-lg { text-decoration: underline; text-underline-offset: 3px; }
.symbol-link:hover .symbol-link-icon, .symbol-link:focus-visible .symbol-link-icon { color: var(--brand-hover); }
.meta-line { display: flex; flex-wrap: wrap; gap: 4px 14px; margin: 0; font-size: .9rem; }
.meta-line strong { color: var(--text); }
.report-verdict { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.kv-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 10px 18px; margin: 0; padding: 12px 0 0; border-top: 1px solid var(--border); }
.kv-grid dt, .kv-list dt { font-size: .78rem; color: var(--muted); }
.kv-grid dd { margin: 0; font-size: .92rem; word-break: break-word; }
.kv-list { margin: 0; display: grid; gap: 6px; }
.kv-list > div { display: flex; justify-content: space-between; gap: 12px; border-bottom: 1px dashed var(--border); padding-bottom: 5px; }
.kv-list > div:last-child { border-bottom: 0; }
.kv-list dd { margin: 0; text-align: right; }
.kv-inline { margin: 0 0 6px; }
.kv-inline div { display: flex; gap: 8px; }
.kv-inline dt { color: var(--muted); }
.kv-inline dd { margin: 0; font-weight: 600; }
.tag-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.inline-editor > summary { list-style: none; }
.inline-editor > summary::-webkit-details-marker { display: none; }
.inline-editor[open] > summary { display: none; }
.inline-editor-form { display: flex; gap: 8px; flex-wrap: wrap; }
.inline-editor-form input { flex: 1 1 220px; min-height: 34px; }
.report-actions { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding-top: 12px; border-top: 1px solid var(--border); }

.progress-card .percent { font-size: 1.3rem; font-weight: 700; color: var(--brand); font-variant-numeric: tabular-nums; }
.progress-card .current { margin: 10px 0 4px; font-weight: 500; min-height: 1.6em; color: var(--text-2); }
.progress-card.is-finished { padding-top: 10px; padding-bottom: 10px; }
.stages-details > summary { cursor: pointer; list-style: revert; padding: 4px 0; }
.inline-h { display: inline; font-size: 1rem; margin: 0; }
.stage-list { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 0; }
.stage {
  display: grid; grid-template-columns: 18px minmax(0, 1fr) auto;
  grid-template-areas: "dot label time" "dot detail detail" "dot lanes lanes";
  column-gap: 10px; padding: 7px 0; position: relative;
}
.stage + .stage::before { content: ""; position: absolute; left: 8px; top: -8px; height: 16px; border-left: 2px solid var(--border); }
.stage-dot { grid-area: dot; width: 16px; height: 16px; margin-top: 3px; border-radius: 50%; border: 2px solid var(--border-strong); background: var(--surface); }
.stage-label { grid-area: label; font-weight: 500; }
/* 泳道那一列很窄，而运行中的 detail 里带着模型给出的工具名（DESIGN-parallel-analysts §5.3）：
   一个没有断点的长 token 会把卡片撑破、整页横向滚动（手机上 34 个字符就够）。 */
.stage-detail { grid-area: detail; min-width: 0; overflow-wrap: anywhere; }
.stage-detail:empty { display: none; }
.stage-time { grid-area: time; font-variant-numeric: tabular-nums; }
/* 状态样式一律只落在**本行自己的**圆点与标签上（子选择器）：分析师组条目里嵌着四条泳道，
   写成后代选择器时「组失败」会把四条泳道连同已完成的那条一起涂红（DESIGN-parallel-analysts §7.3）。 */
.stage-done > .stage-dot { background: var(--ok); border-color: var(--ok); }
.stage-running > .stage-dot { border-color: var(--brand); background: var(--brand-soft); box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand) 18%, transparent); animation: pulse 1.4s ease-in-out infinite; }
.stage-running > .stage-label { color: var(--brand); font-weight: 650; }
.stage-failed > .stage-dot { background: var(--err); border-color: var(--err); }
.stage-failed > .stage-label { color: var(--err); }
.stage-skipped, .stage-pending { color: var(--muted); }
.stage-skipped > .stage-dot { border-style: dashed; }
/* 已中断：别的分析师失败时被掐断的泳道（DESIGN-parallel-analysts §5.2）——不是它自己的错，
   所以用虚线圆点（同 skipped）加 --warn 的标签，而不是 --err 的失败样式。 */
.stage-interrupted { color: var(--muted); }
.stage-interrupted > .stage-dot { border-style: dashed; }
.stage-interrupted > .stage-label { color: var(--warn); }
/* 分析师团队：一条组条目带四条泳道（DESIGN-parallel-analysts §7.3）。泳道之间不画竖向连接线——
   那条线表示「排着队」，而这四条正是同时在跑；改用卡片，让「并行」一眼可见。 */
.stage-lanes {
  grid-area: lanes; list-style: none; margin: 6px 0 2px; padding: 0;
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px;
  color: var(--text);   /* 组整体 skipped 时不把已完成的那条泳道也刷成灰的 */
}
.stage-lane {
  grid-template-columns: 14px minmax(0, 1fr) auto; padding: 6px 10px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2);
}
.stage-lane + .stage-lane::before { display: none; }
.stage-lane .stage-dot { width: 12px; height: 12px; margin-top: 4px; }
/* 只调字号：字重留给 .stage-running .stage-label（同样是两级选择器，写在这里会把它压掉） */
.stage-lane .stage-label { font-size: .92rem; }
@media (min-width: 480px) {
  .stage-lanes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 720px) {
  .stage-list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 28px; }
  .stage + .stage::before { display: none; }
  .stage-group { grid-column: 1 / -1; }
}
@media (min-width: 900px) {
  .stage-lanes { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.activity-title { margin: 14px 0 6px; color: var(--muted); }
.activity { list-style: none; margin: 0; padding: 0; max-height: 220px; overflow-y: auto; font-size: .84rem; border-top: 1px solid var(--border); }
.activity li { display: flex; gap: 10px; padding: 4px 0; border-bottom: 1px dashed var(--border); color: var(--text-2); }
.activity time { color: var(--muted); font-variant-numeric: tabular-nums; flex: none; }
.activity .ev-warning { color: var(--warn); }
.activity .ev-error { color: var(--err); }
.warnings-details { margin-top: 8px; }
.warnings-details > summary { cursor: pointer; color: var(--muted); }

/* minmax(0, 1fr): an implicit "auto" track would size to the K-line canvas, which the chart library
   in turn sizes from the track — a feedback loop that widened the whole page on phones. */
.report-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; margin-top: 16px; align-items: start; }
.section-nav {
  position: sticky; top: calc(var(--header-h) + 64px); z-index: 5; background: var(--bg);
  margin: 0 -16px; padding: 6px 16px; border-bottom: 1px solid var(--border);
}
.section-nav-title { display: none; }
.section-nav ol { list-style: none; display: flex; gap: 4px; overflow-x: auto; margin: 0; padding: 0; scrollbar-width: none; }
.section-nav ol::-webkit-scrollbar { display: none; }
.section-nav a { display: block; white-space: nowrap; padding: 5px 10px; border-radius: 999px; font-size: .86rem; color: var(--text-2); }
.section-nav a:hover { background: var(--surface-3); text-decoration: none; }
.section-nav a.is-missing { color: var(--muted); }
.section-nav a[aria-current="true"] { background: var(--brand-soft); color: var(--brand); font-weight: 600; }
@media (max-width: 899px) { .section-nav { top: calc(var(--header-h) + 38px); } }
@media (min-width: 1024px) {
  .report-layout { grid-template-columns: 200px minmax(0, 1fr); }
  .section-nav { top: calc(var(--header-h) + 16px); margin: 0; padding: 0; border: 0; background: transparent; }
  .section-nav-title { display: block; font-size: .8rem; color: var(--muted); margin: 0 0 6px 10px; font-weight: 600; }
  .section-nav ol { flex-direction: column; overflow: visible; }
  .section-nav a { border-radius: 6px; white-space: normal; }
  .section-nav a[aria-current="true"] { box-shadow: inset 3px 0 0 var(--brand); border-radius: 0 6px 6px 0; }
}
.report-body { min-width: 0; }
.report-body > .card + .card, .report-body > .group-title + .card { margin-top: 12px; }
.group-title { font-size: .85rem; color: var(--muted); font-weight: 600; letter-spacing: .08em; margin: 26px 0 0 4px; }
.section-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.section-title { font-size: 1.15rem; margin: 0; }
.report-section.is-missing .section-title { color: var(--muted); }
.report-section.is-updated { animation: section-flash 1.6s ease-out; }
@keyframes section-flash { from { box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 35%, transparent); } to { box-shadow: var(--shadow); } }
.debate > summary { cursor: pointer; display: flex; align-items: baseline; gap: 10px; list-style: none; }
.debate > summary::-webkit-details-marker { display: none; }
.debate > summary::before { content: "▸"; color: var(--muted); transition: transform .15s; display: inline-block; }
.debate[open] > summary::before { transform: rotate(90deg); }
.debate[open] > summary { margin-bottom: 10px; }
.debate-hint { margin-left: auto; }
.debate[open] .debate-hint { display: none; }
.placeholder { color: var(--muted); font-style: normal; }
.report-disclaimer { margin: 24px 0 0; padding: 12px 14px; border-radius: var(--radius-sm); background: var(--surface-3); color: var(--text-2); font-size: .86rem; }

/* min-width/overflow: the chart library writes a pixel width onto its own table; without this the
   canvas can push its container (and the page) wider than the viewport. */
.chart-card { min-width: 0; }
.chart-card .chart-box { height: 340px; width: 100%; min-width: 0; overflow: hidden; margin: 4px 0 6px; }
@media (min-width: 720px) { .chart-card .chart-box { height: 420px; } }
.chart-status { min-height: 1.4em; font-variant-numeric: tabular-nums; }
.chart-legend { display: inline-flex; flex-wrap: wrap; gap: 4px 12px; align-items: center; }
.legend-item::before { content: ""; display: inline-block; width: 14px; height: 3px; border-radius: 2px; vertical-align: middle; margin-right: 5px; background: currentColor; }
.legend-ma20::before { background: var(--ma20); }
.legend-ma60::before { background: var(--ma60); }
.legend-marker::before { width: 0; height: 0; border-radius: 0; background: none; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 7px solid var(--marker); }

/* long-form Chinese report typography */
.prose { max-width: 46em; font-size: 1rem; line-height: 1.85; color: var(--text); overflow-wrap: anywhere; }
.prose > :first-child { margin-top: 0; }
.prose p, .prose ul, .prose ol, .prose blockquote, .prose pre, .prose table { margin: 0 0 1em; }
.prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 { margin: 1.4em 0 .5em; line-height: 1.4; }
.prose h1 { font-size: 1.2rem; }
.prose h2 { font-size: 1.12rem; }
.prose h3 { font-size: 1.04rem; }
.prose h4, .prose h5, .prose h6 { font-size: 1rem; }
.prose ul, .prose ol { padding-left: 1.5em; }
.prose li + li { margin-top: .25em; }
.prose strong { font-weight: 650; color: var(--text); }
.prose blockquote { border-left: 3px solid var(--border-strong); padding: 2px 0 2px 14px; color: var(--text-2); }
.prose code { font-family: var(--mono); font-size: .88em; background: var(--surface-3); padding: 1px 5px; border-radius: 4px; }
.prose pre { background: var(--surface-3); padding: 12px 14px; border-radius: var(--radius-sm); overflow-x: auto; line-height: 1.5; }
.prose pre code { background: none; padding: 0; }
.prose hr { border: 0; border-top: 1px solid var(--border); margin: 1.5em 0; }
.prose a { word-break: break-all; }
.prose table { display: block; max-width: 100%; overflow-x: auto; border-collapse: collapse; font-size: .92rem; line-height: 1.55; -webkit-overflow-scrolling: touch; }
.prose th, .prose td { border: 1px solid var(--border); padding: 6px 10px; text-align: left; vertical-align: top; min-width: 5em; }
.prose th { background: var(--surface-2); font-weight: 600; white-space: nowrap; }
.prose tbody tr:nth-child(even) td { background: color-mix(in srgb, var(--surface-2) 60%, transparent); }

/* ---------------------------------------------------------------- compare & timeline */

.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); margin: 0 0 16px; overflow-x: auto; }
.tabs a { padding: 8px 14px; color: var(--text-2); border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; }
.tabs a:hover { text-decoration: none; color: var(--text); }
.tabs a[aria-current="page"] { color: var(--brand); border-bottom-color: var(--brand); font-weight: 600; }

.compare-picker { display: grid; gap: 12px; align-items: end; }
@media (min-width: 720px) { .compare-picker { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; } }
.compare-picker-actions { display: flex; gap: 8px; }
.compare-summary { display: grid; gap: 14px; align-items: center; }
@media (min-width: 900px) { .compare-summary { grid-template-columns: minmax(0, 1fr) 150px minmax(0, 1fr); } }
.compare-meta h2 { margin: 0 0 8px; font-size: 1.1rem; }
.compare-label { font-size: .8rem; font-weight: 700; color: var(--muted); letter-spacing: .1em; margin-bottom: 2px; }
.compare-verdict { margin-bottom: 10px; }
.compare-change { display: grid; justify-items: center; gap: 6px; text-align: center; }
.change { font-weight: 700; padding: 4px 12px; border-radius: 999px; background: var(--surface-3); }
.change-up { background: var(--r-ow-bg); color: var(--r-ow-fg); }
.change-down { background: var(--r-uw-bg); color: var(--r-uw-fg); }
.compare-section .section-title { margin-bottom: 10px; }
.compare-cols { display: grid; gap: 14px; }
@media (min-width: 900px) { .compare-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.compare-col { min-width: 0; padding: 12px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2); }
.compare-col .prose { font-size: .95rem; }
.compare-col-label { font-size: .8rem; font-weight: 700; color: var(--muted); margin-bottom: 8px; }
.compare-col .debate > summary::before { content: none; }

.inline-search { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.inline-search input { flex: 1 1 200px; width: auto; }
.symbol-choices { margin: 12px 0 4px; }
.rating-steps { list-style: none; margin: 0; padding: 0; display: flex; gap: 10px; overflow-x: auto; padding-bottom: 4px; }
.rating-step { flex: none; }
.rating-step-link {
  display: grid; justify-items: center; gap: 6px; padding: 10px 14px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text);
}
.rating-step-link:hover { border-color: var(--brand); text-decoration: none; }
.rating-step-date { font-size: .82rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.direction { font-size: .78rem; color: var(--muted); }
.direction-up { color: var(--r-ow-fg); font-weight: 600; }
.direction-down { color: var(--r-uw-fg); font-weight: 600; }

/* ---------------------------------------------------------------- batch & watchlist */

.batch-preview { display: grid; gap: 6px; }
.watch-picks { display: grid; gap: 6px 14px; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); margin-top: 8px; }
.watch-picks .check-inline { gap: 6px; }
.select-all { font-size: .88rem; }
.batch-card { margin-bottom: 16px; }

.watch-add-grid { display: grid; gap: 12px; align-items: start; }
@media (min-width: 900px) { .watch-add-grid { grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr) minmax(0, 1.5fr) auto; } .watch-add-submit { padding-top: 27px; } }
.toolbar { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; padding: 10px 14px; position: sticky; top: calc(var(--header-h) + 44px); z-index: 6; }
@media (min-width: 900px) { .toolbar { top: calc(var(--header-h) + 8px); } }
.watch-list { list-style: none; margin: 0; padding: 0; }
.watch-item { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px 12px; padding: 12px 0; border-top: 1px solid var(--border); align-items: start; }
.watch-item:first-child { border-top: 0; }
.watch-check { padding-top: 3px; }
.watch-title { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.watch-name { font-weight: 650; }
.watch-note { margin: 2px 0; color: var(--text-2); }
.watch-main p { margin: 2px 0 0; }
.watch-actions { grid-column: 2; display: flex; flex-wrap: wrap; gap: 6px; }
/* 现价 · 涨跌幅 · 行情时间 (owner 2026-10-07), filled by dashboard.js; the price follows the change's colour */
.watch-quote { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 2px 8px; font-variant-numeric: tabular-nums; }
.watch-price { font-weight: 650; }
.watch-quote .quote-asof { color: var(--muted); }
@media (min-width: 720px) {
  .watch-item { grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; }
  .watch-actions { grid-column: auto; justify-content: flex-end; }
}

/* ---------------------------------------------------------------- usage & account */

.stat-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); margin-bottom: 16px; }
.stat-grid .card + .card { margin-top: 0; }
.stat-label { font-size: .85rem; color: var(--muted); font-weight: 600; margin-bottom: 2px; }
.stat-value { font-size: 1.9rem; font-weight: 700; line-height: 1.2; margin-bottom: 8px; font-variant-numeric: tabular-nums; }
.stat-unit { font-size: .9rem; font-weight: 500; color: var(--muted); }
.account-grid { display: grid; gap: 16px; }
.account-grid .card + .card { margin-top: 0; }
@media (min-width: 900px) { .account-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .account-grid > :last-child { grid-column: 1 / -1; } }

/* ---------------------------------------------------------------- login & errors */

.page-login .site-header { position: static; }
.login-wrap { display: grid; place-items: center; min-height: calc(100vh - 220px); padding: 12px 0; }
.login-card { width: 100%; max-width: 400px; padding: 26px 24px; }
.login-brand { display: flex; align-items: center; gap: 14px; margin-bottom: 20px; }
.login-brand h1 { font-size: 1.3rem; margin: 0; }
.login-note { margin-top: 16px; text-align: center; }

.error-page { max-width: 560px; margin: 40px auto; text-align: center; padding: 36px 24px; }
.error-code { font-size: 3rem; font-weight: 800; color: var(--muted); margin: 0; line-height: 1; font-variant-numeric: tabular-nums; }
.error-page h1 { margin: 12px 0 8px; }
.error-message { color: var(--text-2); }
.error-page .actions { justify-content: center; margin-top: 18px; }

/* ---------------------------------------------------------------- 行情涨跌配色 */

/* Two neutral palettes; which one means "up" is decided by the saved up_color preference
   (DESIGN-extras §6). A 股/港股 default to 红涨绿跌, 美股 to 绿涨红跌; choosing 绿涨红跌
   makes all three markets agree. Never an inline style: the class carries the meaning. */
:root { --c-red: #c62828; --c-green: #0b7c4c; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { --c-red: #ff7a72; --c-green: #3fc98c; }
}
:root[data-theme="dark"] { --c-red: #ff7a72; --c-green: #3fc98c; }

:root { --rise: var(--c-red); --fall: var(--c-green); }
.market-us { --rise: var(--c-green); --fall: var(--c-red); }
:root[data-up-color="green"] { --rise: var(--c-green); --fall: var(--c-red); }
:root[data-up-color="green"] .market-us { --rise: var(--c-green); --fall: var(--c-red); }

.q-up { color: var(--rise); }
.q-down { color: var(--fall); }
.q-flat { color: var(--muted); }
.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.table th.num, .table td.num { text-align: right; }

/* ---------------------------------------------------------------- 指数条 */

.index-strip { margin: 0 0 16px; }
.index-list {
  list-style: none; margin: 0; padding: 4px; display: flex; gap: 4px; overflow-x: auto;
  scrollbar-width: none; background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.index-list::-webkit-scrollbar { display: none; }
.index-item {
  flex: 1 0 auto; min-width: 120px; display: grid; gap: 1px; padding: 7px 12px;
  border-radius: var(--radius-sm); line-height: 1.35;
}
.index-item + .index-item { border-left: 1px solid var(--border); border-radius: 0; }
.index-name { color: var(--text-2); font-size: .82rem; white-space: nowrap; }
.index-figures { display: flex; align-items: baseline; gap: 8px; font-variant-numeric: tabular-nums; }
.index-price { font-size: 1.02rem; font-weight: 700; }
.index-change { font-size: .86rem; font-weight: 600; }
.index-note:empty { display: none; }
.index-note { margin: 6px 0 0; }

/* ---------------------------------------------------------------- 首页行情与快讯 */

.main-column { display: grid; gap: 16px; align-content: start; min-width: 0; }
.main-column > .card + .card { margin-top: 0; }
/* A grid item's default min-width is its min-content width, which a nowrap table would push
   past the viewport; 0 lets the .table-wrap scroller do its job instead of the page. */
.layout-main-side > *, .main-column > * { min-width: 0; }

.quote-table th[scope="row"] { font-weight: 600; }
.quote-name { display: grid; gap: 0; min-width: 8em; }
.quote-name .symbol { display: block; font-weight: 400; }
.quote-name[data-status]::after { content: "（" attr(data-status) "）"; color: var(--muted); font-size: .8rem; font-weight: 400; }
.quote-actions { text-align: right; white-space: nowrap; }
.quote-note:empty { display: none; }
.quote-note { margin: 8px 0 0; }

.news-list { display: grid; gap: 0; }
.news-item { border-top: 1px solid var(--border); }
.news-item:first-child { border-top: 0; }
.news-item details { padding: 8px 0; }
.news-item summary { cursor: pointer; list-style: none; display: grid; gap: 2px; }
.news-item summary::-webkit-details-marker { display: none; }
.news-headline { font-weight: 600; color: var(--text); }
.news-item details[open] .news-headline { color: var(--brand); }
.news-summary { margin: 8px 0 4px; color: var(--text-2); font-size: .92rem; }
.news-item a { font-size: .88rem; }

.paper-list { display: grid; gap: 8px; }
.paper-card {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 2px 10px; padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2);
}
.paper-market { font-weight: 650; }
.paper-assets { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; }
.paper-line { font-size: .86rem; font-variant-numeric: tabular-nums; }
.paper-line:last-child { text-align: right; }

/* ---------------------------------------------------------------- 选股 */

.screen-stamp { margin: 0; font-variant-numeric: tabular-nums; }
.chip-row { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.screen-form { display: grid; gap: 12px; }
.screen-top { display: grid; gap: 12px; align-items: end; }
.screen-keyword { min-width: 0; }
.screen-submit { display: flex; gap: 8px; }
@media (min-width: 720px) {
  .screen-top { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) auto; }
}
.check-row { display: flex; flex-wrap: wrap; gap: 8px 16px; }
.range-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); margin: 10px 0 14px; }
.range-field { display: grid; gap: 4px; min-width: 0; }
.range-label { font-size: .86rem; font-weight: 600; }
.range-inputs { display: flex; align-items: center; gap: 6px; }
.range-inputs input { min-width: 0; min-height: 36px; font-size: .92rem; }
.range-inputs span { color: var(--muted); }

.screen-summary { margin: 14px 0 8px; }
.screen-summary p { margin: 0; }
.table-card { padding: 6px; }
.screen-table { font-size: .88rem; }
.screen-table th[scope="row"] { font-weight: 600; }
.screen-name { min-width: 8.5em; }
.screen-name .symbol { display: block; font-weight: 400; }
.screen-industry { white-space: nowrap; color: var(--text-2); }
.screen-actions { white-space: nowrap; text-align: right; }
.screen-actions .btn { padding-left: 8px; padding-right: 8px; }
.sort-link { display: inline-flex; align-items: center; gap: 2px; color: var(--muted); white-space: nowrap; }
.sort-link:hover { color: var(--brand); text-decoration: none; }
.sort-link.is-active { color: var(--brand); font-weight: 700; }
.sort-arrow { font-size: .78em; }
.sort-link.is-active .sort-arrow { opacity: 1; }

/* ---------------------------------------------------------------- 偏好设置 */

.pref-form { display: grid; gap: 4px; }
.pref-form .field-row { gap: 0 14px; }
.segmented-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pref-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-items: stretch; }

/* ---------------------------------------------------------------- motion & print */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
}

@media print {
  :root { color-scheme: light; --bg: #fff; --surface: #fff; --surface-2: #fff; --surface-3: #f2f2f2; --text: #000; --text-2: #222; --muted: #555; --border: #ccc; }
  body { font-size: 11pt; background: #fff; }
  .site-header, .site-footer .muted, .no-print, .toasts, .skip-link, .breadcrumb, .section-nav, .tabs, button, .btn { display: none !important; }
  .main { padding: 0; }
  .container { max-width: none; padding: 0; }
  .card { box-shadow: none; border: 0; padding: 0; margin: 0 0 14pt; }
  .report-layout { display: block; }
  .report-section { break-inside: auto; }
  .section-title, .group-title { break-after: avoid; }
  .prose { max-width: none; font-size: 10.5pt; line-height: 1.7; }
  .prose table { display: table; }
  .prose a { color: #000; }
  .progress-card.is-finished { display: none; }
  .rating { border: 1px solid #000 !important; color: #000 !important; background: #fff !important; }
  .chart-card .chart-box { height: 300px; }
  .debate > summary::before { content: none; }
  .report-disclaimer { background: none; border: 1px solid #ccc; }
}

/* ---------------------------------------------------------------- 研报导出与任务中心（DESIGN-extras §4 §7） */

/* Fake-engine runs: loud on purpose, and it stays when the page is printed. */
.fake-engine-banner {
  margin: 0 0 14px; padding: 12px 16px; border: 2px solid var(--err); border-left-width: 8px;
  border-radius: var(--radius-sm); background: var(--err-soft); color: var(--text); font-size: .94rem;
}
.fake-engine-banner p { margin: 0; }
.fake-engine-banner .fake-engine-title { margin: 0 0 4px; font-size: 1.15rem; font-weight: 800; color: var(--err); letter-spacing: .02em; }

.export-group { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.export-hint { flex-basis: 100%; order: 10; }

/* bulk selection bars (report library + task centre) */
.bulk-bar { margin: 16px 0 0; }
.bulk-bar .confirm { position: static; }
.bulk-bar .confirm-panel { left: auto; right: 14px; }
.bulk-format select { width: auto; min-height: 32px; padding: 3px 8px; font-size: .86rem; }
.bulk-note { flex: 1 1 200px; }
/* 删除所选 on the report library (owner request 2026-09-21): pushed to the far right past a thin
   divider so a slip off the primary 打包导出所选 cannot reach it; soft danger tint here, the solid
   .btn-danger is kept for the confirm inside its panel. The wrapper keeps divider and button on
   one line when the bar wraps; on a phone the wrap itself separates them, so no divider there. */
.bulk-danger { display: flex; align-items: center; gap: 14px; margin-left: auto; }
.bulk-danger::before { content: ""; width: 1px; height: 22px; background: var(--border); }
@media (max-width: 719px) { .bulk-danger::before { content: none; } }
.btn-danger-soft { background: var(--err-soft); border-color: var(--err-border); color: var(--err); }
.btn-danger-soft:hover { background: var(--err-soft); border-color: var(--err); }
.row-check { display: inline-flex; align-items: center; justify-content: center; width: 22px; flex: none; }
.report-list .report-row-meta, .report-list .report-row .tag-list { margin-left: 70px; }
@media (max-width: 719px) {
  .report-list .report-row-meta, .report-list .report-row .tag-list { margin-left: 0; }
}
/* 团队研报 / 全站研报 (docs/DESIGN-team-sharing.md §5): read-only rows have no checkbox and no star,
   so the meta line starts under the title, and the 作者 leads it */
.lib-scopes { margin: 0 0 12px; }
.report-list.is-shared .report-row-meta { margin-left: 0; }
.report-author strong { color: var(--text); font-weight: 600; }
/* the notice above somebody else's report (§4) */
.read-only-notice { margin: 0 0 12px; }

/* task centre: one compact figures strip, not a grid of cards */
.task-stats { margin: 0 0 14px; }
.task-stat-list {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 0; padding: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
.task-stat { padding: 10px 14px; border-top: 1px solid var(--border); min-width: 0; }
.task-stat:nth-child(-n+2) { border-top: 0; }
.task-stat:nth-child(even) { border-left: 1px solid var(--border); }
.task-stat:last-child { grid-column: 1 / -1; border-left: 0; }
.task-stat dt { font-size: .8rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.task-stat dd { margin: 2px 0 0; font-size: 1.35rem; font-weight: 700; line-height: 1.25; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
@media (min-width: 720px) {
  .task-stat-list { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .task-stat, .task-stat:nth-child(-n+2) { border-top: 0; }
  .task-stat:nth-child(even), .task-stat:last-child { border-left: 0; }
  .task-stat + .task-stat { border-left: 1px solid var(--border); }
  .task-stat:last-child { grid-column: auto; }
}
.task-stats-note { margin: 6px 2px 0; }

.task-tabs { margin-bottom: 12px; }
.tab-count { display: inline-block; min-width: 1.6em; padding: 0 6px; margin-left: 2px; border-radius: 999px; background: var(--surface-3); color: var(--text-2); font-size: .76rem; text-align: center; font-variant-numeric: tabular-nums; }
.tabs a[aria-current="page"] .tab-count { background: var(--brand-soft); color: var(--brand); }
.task-filters .filter-grid { margin-top: 0; }
.task-notice { margin: 12px 0 0; }

.task-table-card { margin-top: 12px; }
.task-table td, .task-table th { vertical-align: top; }
.task-table thead th { vertical-align: middle; }
.task-table tbody th { background: transparent; color: var(--text); font-size: .9rem; white-space: normal; }
.task-name { min-width: 9em; }
.task-name a { font-weight: 650; color: var(--text); }
.task-sub { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 6px; margin-top: 2px; font-weight: 400; }
.task-id { display: block; margin-top: 2px; font-family: var(--mono); font-size: .74rem; font-weight: 400; color: var(--muted); }
.task-table .col-check { width: 34px; padding-right: 0; }
.task-table .col-check input { margin-top: 2px; }
.task-table .col-progress { min-width: 130px; }
.task-progress { display: flex; align-items: center; gap: 8px; }
.task-progress .progress { flex: 1; min-width: 70px; }
.task-progress .num { min-width: 3em; }
.task-current { display: block; margin-top: 2px; max-width: 16em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.task-stopping { display: block; margin-top: 2px; }
.task-table .col-actions { text-align: right; white-space: nowrap; }
@media (max-width: 719px) {
  .task-table .col-optional { display: none; }
  .task-tabs a { padding: 8px 6px; }
  /* a tall wrapped bar must not stay pinned over the table on a phone */
  .bulk-bar { position: relative; top: auto; }
}

@media print {
  .bulk-bar, .task-filters, .task-tabs, .row-check, .task-table .col-check, .task-table .col-actions { display: none !important; }
  .fake-engine-banner { border-color: #000; background: #fff; }
  .fake-engine-banner .fake-engine-title { color: #000; }
}

/* ---------------------------------------------------------------- 模拟交易（DESIGN-extras §3） */

.paper-asof { margin: 0; font-variant-numeric: tabular-nums; }
.paper-tabs { margin-bottom: 14px; overflow-y: hidden; }
.tab-currency { margin-left: 6px; font-size: .76rem; color: var(--muted); font-weight: 400; }
.paper-suggestion p { margin: 0 0 4px; }
.paper-suggestion p:last-child { margin: 0; }

.paper-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 16px; margin: 0; }
.paper-stat { min-width: 0; }
.paper-stat dt { font-size: .8rem; color: var(--muted); }
.paper-stat dd { margin: 0; font-size: 1.02rem; font-weight: 650; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.paper-stat.is-main { grid-column: 1 / -1; }
.paper-stat.is-main dd { font-size: 1.55rem; font-weight: 700; line-height: 1.25; }
.stat-sub { display: block; font-size: .8rem; font-weight: 600; }
.paper-note { margin: 12px 0 0; padding: 6px 10px; border-radius: var(--radius-sm); background: var(--warn-soft); color: var(--warn); }
@media (min-width: 720px) {
  .paper-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .paper-stat.is-main { grid-column: auto; }
}
@media (min-width: 1100px) {
  .paper-stats { grid-template-columns: minmax(0, 1.35fr) repeat(5, minmax(0, 1fr)); align-items: end; }
}

/* The order form comes first in the markup, so a phone shows it before the tables. */
.paper-layout { display: grid; gap: 16px; align-items: start; margin-top: 16px; }
.paper-layout > * { min-width: 0; }
/* minmax(0, 1fr): an implicit "auto" track would grow to the nowrap tables' width and push the
   main column over the order form instead of letting .table-wrap scroll. */
.paper-side, .paper-main { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; align-content: start; min-width: 0; }
.paper-side > .card + .card, .paper-main > .card + .card { margin-top: 0; }
@media (min-width: 1024px) {
  .paper-layout { grid-template-columns: minmax(0, 1fr) 360px; }
  .paper-side { grid-column: 2; grid-row: 1; }
  .paper-main { grid-column: 1; grid-row: 1; }
}

.paper-order-form .field { margin-bottom: 14px; }
.paper-symbol-status { min-height: 1.4em; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.paper-symbol-status .sym-error { color: var(--err); }
.paper-sides .side-buy input:checked + .segment-body {
  border-color: var(--rise); color: var(--rise); box-shadow: inset 0 0 0 1px var(--rise);
  background: color-mix(in srgb, var(--rise) 10%, var(--surface));
}
.paper-sides .side-sell input:checked + .segment-body {
  border-color: var(--fall); color: var(--fall); box-shadow: inset 0 0 0 1px var(--fall);
  background: color-mix(in srgb, var(--fall) 10%, var(--surface));
}
.paper-order-hint { margin-top: 8px; }
.paper-fees { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
.paper-fees > summary { cursor: pointer; color: var(--text-2); font-size: .9rem; width: max-content; max-width: 100%; }
.fee-schedule { display: grid; gap: 6px; margin-top: 8px; }
.fee-schedule li { display: grid; }
.fee-name { font-weight: 600; font-size: .88rem; }

.side-tag {
  display: inline-block; padding: 0 7px; border-radius: 4px; border: 1px solid currentColor;
  font-size: .8rem; font-weight: 700; line-height: 1.5; white-space: nowrap;
}
.side-tag.side-buy { color: var(--rise); }
.side-tag.side-sell { color: var(--fall); }

.paper-confirm { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-soft), var(--shadow); }
.paper-confirm h2:focus { outline: none; }
.paper-confirm .alert { margin: 0 0 12px; }
.paper-confirm-line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; font-size: 1.02rem; margin-bottom: 12px; }
.paper-estimate { margin-bottom: 12px; font-variant-numeric: tabular-nums; }
.paper-estimate dt { font-size: .86rem; color: var(--text-2); }
.paper-estimate .fee-line dt { padding-left: 1em; color: var(--muted); font-size: .82rem; }
.paper-estimate .fee-line dd { color: var(--text-2); font-size: .86rem; }
.paper-estimate .is-strong dt, .paper-estimate .is-strong dd { font-weight: 700; color: var(--text); }
.paper-confirm-form { margin: 14px 0 8px; }
.paper-confirm-form .btn { white-space: normal; }
.paper-confirm-hint { margin-bottom: 8px; }

.paper-table { font-size: .88rem; }
.paper-table th, .paper-table td { vertical-align: top; padding-left: 8px; padding-right: 8px; }
.paper-name { font-weight: 600; min-width: 7.5em; }
.paper-name-text, .paper-name .symbol { display: block; }
.paper-name .symbol { font-weight: 400; }
.paper-name-link { color: inherit; text-decoration: none; display: block; }
.paper-name-link:hover, .paper-name-link:focus-visible { color: var(--brand); }
.paper-name-link:hover .paper-name-text, .paper-name-link:focus-visible .paper-name-text { text-decoration: underline; text-underline-offset: 3px; }
.cell-sub { display: block; font-size: .76rem; color: var(--muted); font-weight: 400; white-space: nowrap; }
.q-up .cell-sub, .q-down .cell-sub { color: inherit; }
/* a percentage under an amount is coloured by its own (rounded) sign, not the amount's */
.cell-sub.q-up { color: var(--rise); }
.cell-sub.q-down { color: var(--fall); }
.cell-sub.q-flat { color: var(--muted); }
.paper-actions { white-space: nowrap; text-align: right; }
.paper-actions .btn { padding-left: 8px; padding-right: 8px; }
.paper-status { min-width: 9em; }
.order-state { font-weight: 650; white-space: nowrap; }
.order-state.is-filled { color: var(--ok); }
.order-state.is-rejected { color: var(--err); }
.reject-reason { white-space: normal; color: var(--text-2); max-width: 16em; }
.order-flags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.order-flags .chip { padding: 0 7px; font-size: .74rem; }
.order-row.is-rejected > * { background: color-mix(in srgb, var(--err-soft) 45%, transparent); }
.paper-job { min-width: 6em; }
.fee-details > summary { cursor: pointer; list-style: none; font-size: .78rem; color: var(--muted); text-decoration: underline dotted; text-underline-offset: 3px; }
.fee-details > summary::-webkit-details-marker { display: none; }
.fee-breakdown { margin-top: 4px; display: grid; gap: 2px; font-size: .78rem; color: var(--text-2); }
.fee-breakdown li { display: flex; justify-content: space-between; gap: 10px; }
/* ------------------------------------------------------------------ 最终集成修正（final integration） */
/* 360 px: grid items default to min-width:auto, so a long table or name in the side column
   widened the whole page. */
.side-column > * { min-width: 0; }
/* 行情时间与状态（已收盘 / 交易中 / 港股延迟），在价格下方 */
.index-asof { font-size: .72rem; color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.quote-asof { font-variant-numeric: tabular-nums; }
.q-up .quote-asof, .q-down .quote-asof { color: var(--muted); }
/* 预计耗时与费用（按本人历史运行的中位数） */
.run-estimate:empty { display: none; }
.run-estimate { color: var(--text-2); }

/* symbol search suggestions (名称 / 拼音 / 英文名) */
.symbol-suggest { list-style: none; margin: 4px 0 0; padding: 4px; border: 1px solid var(--border-strong);
  border-radius: 8px; background: var(--surface); max-height: 420px; overflow-y: auto; }
.symbol-suggest[hidden] { display: none; }
.symbol-suggest .suggest-item { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; width: 100%;
  min-width: 0; padding: 8px 10px; border: 0; border-radius: 6px; background: transparent; color: var(--text);
  font: inherit; text-align: left; cursor: pointer; }
.symbol-suggest .suggest-item:hover, .symbol-suggest .suggest-item:focus-visible { background: var(--surface-3); }
.symbol-suggest .sym-name { font-weight: 700; overflow-wrap: anywhere; }
.symbol-status .sym-hint { color: var(--muted); }
.symbol-suggest .tag-fund { opacity: .75; }

/* ------------------------------------------------------------------ 机会雷达（DESIGN-radar §1） */
/* 选股 tabs: 条件选股 / 机会雷达 / 信号表现 (the .tabs rule paints them) */
.screen-tabs { margin-top: 4px; overflow-y: hidden; } /* the count pill is 1px taller than the line: no vertical scrollbar */
.radar-status { margin: 0 0 10px; }
.radar-ops-hint code { font-size: .8em; }
.radar-signal-chips { margin-bottom: 6px; }
.radar-chip-groups { display: grid; gap: 8px; }
.radar-chip-groups .chip-row { align-items: center; margin-bottom: 0; }
/* 名称 cell: risk / new / radar chips wrap under the name instead of widening the column */
.screen-name .chip, .screen-name .chip-warn { margin-top: 2px; }
.radar-table .screen-name { white-space: normal; max-width: 14em; }
.radar-table .screen-name .chip { display: inline-flex; margin-right: 2px; }
.radar-chip { padding: 0 8px; font-size: .74rem; }
.radar-risk-warn { border-color: var(--err-border); background: var(--err-soft); color: var(--err); font-size: .74rem; padding: 0 8px; }
.radar-risk-info { border-color: var(--border-strong); background: var(--surface-3); color: var(--text-2); font-size: .74rem; padding: 0 8px; }
/* 综合分 explanation: .cell-sub is nowrap by default, the addition must wrap */
.radar-table .radar-score-why { white-space: normal; min-width: 8em; max-width: 16em; }
/* 命中信号: one chip per signal, its odds in muted small text, the explanation below */
.radar-signals { min-width: 16em; max-width: 26em; white-space: normal; }
.radar-signals .radar-signal { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin: 0 8px 4px 0; }
.radar-signals .chip { flex-wrap: wrap; }
.radar-odds { font-size: .76rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.radar-why { margin: 4px 0 0; font-size: .8rem; color: var(--text-2); }
/* 关键价位: 突破 / 止损 / 压力 as a compact definition list; each dd carries its method as title */
.radar-levels { display: grid; gap: 2px; margin: 0; font-size: .82rem; white-space: nowrap; }
.radar-levels > div { display: flex; justify-content: space-between; gap: 8px; }
.radar-levels dt { color: var(--muted); font-weight: 400; }
.radar-levels dd { margin: 0; font-variant-numeric: tabular-nums; text-decoration: underline dotted; text-underline-offset: 3px; }
.radar-levels-note { margin: 8px 4px 0; }
.radar-table td, .radar-table tbody th { vertical-align: top; } /* the 名称 cell is a th: keep it on the row's first line */
.radar-table .col-check { width: 34px; padding-right: 0; }
.radar-table .col-check input { margin-top: 2px; }
.radar-actions { white-space: normal; min-width: 9em; }
.radar-actions .btn, .radar-actions .inline-form, .radar-actions .confirm { margin: 0 0 4px; }
.radar-actions .confirm-panel { min-width: 16em; }
.radar-stats-table th[scope="row"], .radar-runs-table th[scope="row"] { background: transparent; color: var(--text); font-size: .9rem; white-space: nowrap; }
.radar-any-row th, .radar-any-row td { border-top: 2px solid var(--border-strong); font-weight: 600; }
.radar-cold-start { color: var(--text-2); }
.radar-stats-table .radar-version { min-width: 8em; white-space: normal; font-size: .82rem; color: var(--text-2); }
.radar-terms { margin: 14px 0 0; }
@media (max-width: 719px) {
  .radar-table .col-optional, .radar-stats-table .col-optional { display: none; }
  .radar-signals { min-width: 12em; }
}

/* Paper short selling (DESIGN-paper-short §3): the side-tag colours, reused. 空头 / 开空 take the
   sell colour, 平空 the buy colour, 多头 the buy colour; the market class decides red/green. */
.side-tag.side-short { color: var(--fall); background: color-mix(in srgb, var(--fall) 10%, transparent); }
.side-tag.side-cover { color: var(--rise); background: color-mix(in srgb, var(--rise) 10%, transparent); }
.side-tag.side-long { color: var(--rise); }
.paper-short-line { margin: 10px 0 0; }
.paper-short-hint { margin-top: 6px; }
