读取策略配置
\n正在读取登录状态、账号配置和当前状态。
\n \ndiff --git a/web/strategy-switch-console/app.css b/web/strategy-switch-console/app.css new file mode 100644 index 0000000..f776e1d --- /dev/null +++ b/web/strategy-switch-console/app.css @@ -0,0 +1,1309 @@ +:root { + --bg: #f5f6f8; + --surface: #ffffff; + --soft: #eef1f4; + --ink: #16191f; + --muted: #66707c; + --line: #dce1e7; + --line-strong: #b8c2cc; + --accent: #136f63; + --accent-ink: #ffffff; + --danger: #b54137; + --lb: #0f766e; + --ib: #2f5f9f; + --sw: #9b4153; + --ft: #94651f; + --qmt: #b45309; + --bn: #f0b90b; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, + "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; + } + + * { + box-sizing: border-box; + } + + html { + min-height: 100%; + background: var(--bg); + } + + body { + margin: 0; + min-height: 100svh; + background: + linear-gradient(180deg, #fbfcfd 0, #eef2f5 100%); + color: var(--ink); + letter-spacing: 0; + } + + button, + select, + input { + font: inherit; + letter-spacing: 0; + } + + button { + cursor: pointer; + } + + a { + color: inherit; + } + + button:focus-visible, + select:focus-visible, + input:focus-visible, + a:focus-visible { + outline: 3px solid color-mix(in srgb, var(--platform-color, var(--accent)) 24%, transparent); + outline-offset: 2px; + } + + [hidden] { + display: none !important; + } + + h1, + h2, + h3, + p { + margin: 0; + } + + .topbar { + min-height: 72px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; + padding: 17px 28px; + border-bottom: 1px solid var(--line); + background: rgba(250, 251, 252, 0.88); + backdrop-filter: blur(14px); + position: sticky; + top: 0; + z-index: 20; + } + + .brand { + display: grid; + gap: 3px; + min-width: 0; + } + + h1 { + font-size: 22px; + line-height: 1.12; + font-weight: 780; + overflow-wrap: anywhere; + } + + .brand p { + color: var(--muted); + font-size: 13px; + line-height: 1.4; + } + + .top-actions { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 10px; + flex-wrap: wrap; + } + + .auth-status { + max-width: 260px; + overflow: hidden; + text-overflow: ellipsis; + } + + .shell { + width: min(1160px, calc(100vw - 36px)); + margin: 0 auto; + padding: 22px 0 32px; + display: grid; + gap: 16px; + } + + body.app-loading .shell { + display: none; + } + + body:not(.app-loading) .boot-screen { + display: none; + } + + .boot-screen { + width: min(680px, calc(100vw - 36px)); + min-height: calc(100svh - 72px); + margin: 0 auto; + display: grid; + align-items: center; + padding: 34px 0; + } + + .boot-panel { + display: grid; + gap: 13px; + padding: 8px 0; + } + + .boot-kicker { + color: var(--accent); + font-size: 12px; + line-height: 1.2; + font-weight: 800; + text-transform: uppercase; + } + + .boot-panel h2 { + color: var(--ink); + font-size: clamp(28px, 5vw, 44px); + line-height: 1.04; + font-weight: 820; + } + + .boot-panel p { + color: var(--muted); + font-size: 14px; + line-height: 1.5; + max-width: 520px; + } + + .loading-track { + width: 100%; + height: 5px; + overflow: hidden; + border-radius: 999px; + background: #dde4ea; + } + + .loading-track::before { + content: ""; + display: block; + width: 42%; + height: 100%; + border-radius: inherit; + background: var(--accent); + animation: loading-sweep 1.05s ease-in-out infinite; + } + + .pill, + .btn { + min-height: 36px; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 7px; + border: 1px solid var(--line); + background: var(--surface); + color: var(--muted); + text-decoration: none; + white-space: nowrap; + font-size: 13px; + font-weight: 740; + box-shadow: 0 1px 0 rgba(22, 25, 31, 0.03); + } + + .pill { + padding: 0 12px; + border-radius: 999px; + } + + .pill.ready { + border-color: rgba(19, 111, 99, 0.28); + background: #eff9f6; + color: var(--accent); + } + + .btn { + padding: 0 13px; + border-radius: 8px; + transition: border-color 150ms ease, background 150ms ease, transform 150ms ease; + } + + .btn:hover { + transform: translateY(-1px); + border-color: var(--line-strong); + background: #fafbfc; + } + + .lang-toggle { + min-width: 42px; + padding: 0 10px; + } + + .mode button { + border: 0; + border-radius: 6px; + background: transparent; + color: var(--muted); + font-weight: 760; + transition: background 150ms ease, color 150ms ease; + } + + .mode button.active { + background: #ffffff; + color: var(--ink); + box-shadow: 0 1px 7px rgba(22, 25, 31, 0.08); + } + + .platform-strip { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 8px; + } + + .platform-button { + min-width: 0; + min-height: 52px; + display: grid; + grid-template-columns: auto 1fr; + align-items: center; + gap: 8px; + padding: 8px 10px; + border: 1px solid var(--line); + border-left: 4px solid var(--platform-color); + border-radius: 8px; + background: var(--surface); + color: var(--ink); + text-align: left; + transition: + transform 150ms ease, + border-color 150ms ease, + background 150ms ease, + box-shadow 150ms ease; + } + + .platform-button:hover { + transform: translateY(-1px); + border-color: var(--line-strong); + } + + .platform-button.active { + border-color: var(--platform-color); + background: + linear-gradient(180deg, color-mix(in srgb, var(--platform-color) 7%, white), #ffffff 68%); + box-shadow: 0 14px 30px rgba(22, 25, 31, 0.09); + } + + .platform-button[data-platform="longbridge"] { + --platform-color: var(--lb); + } + + .platform-button[data-platform="ibkr"] { + --platform-color: var(--ib); + } + + .platform-button[data-platform="schwab"] { + --platform-color: var(--sw); + } + + .platform-button[data-platform="firstrade"] { + --platform-color: var(--ft); + } + + .platform-button[data-platform="qmt"] { + --platform-color: var(--qmt); + } + + .platform-button[data-platform="binance"] { + --platform-color: var(--bn); + } + + .execution-cash-policy-section { + grid-template-columns: 1fr; + } + + .execution-cash-policy-heading { + grid-column: 1 / -1; + margin: 0; + font-size: 13px; + font-weight: 780; + color: var(--ink); + } + + .execution-cash-policy-note { + grid-column: 1 / -1; + margin: 0; + color: var(--muted); + font-size: 12px; + line-height: 1.45; + } + + .execution-cash-policy-grid { + grid-column: 1 / -1; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14px; + align-items: start; + } + + .policy-block-muted .selection-meta { + color: var(--danger); + } + + @media (max-width: 720px) { + .execution-cash-policy-grid { + grid-template-columns: 1fr; + } + } + + .mark { + width: 32px; + height: 32px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 8px; + background: color-mix(in srgb, var(--platform-color) 12%, white); + color: var(--platform-color); + font-size: 11px; + font-weight: 840; + transition: background 150ms ease, color 150ms ease; + } + + .platform-button.active .mark { + background: var(--platform-color); + color: #ffffff; + } + + .platform-copy { + min-width: 0; + display: grid; + gap: 3px; + } + + .platform-copy strong { + font-size: 13px; + line-height: 1.18; + overflow-wrap: anywhere; + } + + .platform-strip .platform-copy span, + .platform-strip .platform-copy small { + display: none; + } + + .platform-copy span { + color: var(--muted); + font-size: 12px; + line-height: 1.35; + overflow-wrap: anywhere; + } + + .platform-copy small { + color: var(--platform-color); + font-size: 11px; + line-height: 1.25; + font-weight: 780; + overflow-wrap: anywhere; + } + + .switch-surface { + display: grid; + grid-template-columns: minmax(0, 1.04fr) minmax(320px, 0.96fr); + gap: 18px; + align-items: stretch; + } + + .switch-surface.summary-hidden { + grid-template-columns: minmax(0, 1fr); + } + + .switch-panel, + .summary-panel { + min-width: 0; + border: 1px solid var(--line); + border-radius: 8px; + background: var(--surface); + box-shadow: 0 14px 34px rgba(22, 25, 31, 0.07); + } + + .switch-panel { + display: grid; + gap: 20px; + padding: 22px; + } + + .panel-head { + display: grid; + gap: 5px; + } + + .eyebrow { + color: var(--muted); + font-size: 12px; + line-height: 1.2; + font-weight: 780; + text-transform: uppercase; + } + + .panel-head h2 { + font-size: clamp(24px, 3vw, 34px); + line-height: 1.08; + font-weight: 820; + overflow-wrap: anywhere; + } + + .quick-form { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + align-items: start; + gap: 16px 14px; + } + + .control-block { + display: grid; + grid-template-rows: auto 48px minmax(20px, auto); + align-content: start; + gap: 8px; + min-width: 0; + color: var(--muted); + font-size: 12px; + font-weight: 760; + } + + .form-section { + grid-column: 1 / -1; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + align-items: start; + gap: 14px; + } + + .form-section + .form-section { + padding-top: 16px; + border-top: 1px solid var(--line); + } + + .section-wide { + grid-column: 1 / -1; + } + + .mode-block { + grid-column: 1 / -1; + } + + select, + input { + width: 100%; + min-width: 0; + height: 48px; + padding: 0 13px; + border: 1px solid var(--line); + border-radius: 8px; + background: #ffffff; + color: var(--ink); + outline: none; + font-size: 14px; + font-weight: 680; + overflow: hidden; + padding-right: 42px; + text-overflow: ellipsis; + transition: border-color 150ms ease, box-shadow 150ms ease; + } + + select:focus, + input:focus { + border-color: var(--platform-color, var(--accent)); + box-shadow: 0 0 0 3px rgba(19, 111, 99, 0.12); + } + + input::placeholder { + color: #9aa3ad; + opacity: 1; + } + + .selection-meta { + min-height: 20px; + color: var(--muted); + font-size: 12px; + line-height: 1.45; + overflow-wrap: anywhere; + } + + .mode { + height: 48px; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 4px; + padding: 4px; + border: 1px solid var(--line); + border-radius: 8px; + background: var(--soft); + } + + .mode button { + font-size: 13px; + } + + .run-area { + display: grid; + gap: 10px; + padding-top: 2px; + } + + .public-note { + color: var(--muted); + font-size: 14px; + line-height: 1.55; + max-width: 560px; + } + + .run-button { + min-height: 56px; + border: 0; + border-radius: 8px; + background: var(--platform-color, var(--accent)); + color: var(--accent-ink); + font-size: 16px; + font-weight: 820; + transition: transform 150ms ease, filter 150ms ease, opacity 150ms ease; + } + + .run-button:hover:not(:disabled) { + transform: translateY(-1px); + filter: brightness(0.92); + } + + .run-button:disabled { + opacity: 0.48; + cursor: not-allowed; + transform: none; + } + + .action-note { + min-height: 20px; + color: var(--muted); + font-size: 13px; + line-height: 1.45; + } + + .action-note.warning { + color: var(--danger); + font-weight: 720; + } + + .summary-panel { + display: grid; + grid-template-rows: auto 1fr auto; + overflow: hidden; + } + + .summary-head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 16px; + border-bottom: 1px solid var(--line); + } + + .summary-head h2 { + font-size: 15px; + line-height: 1.2; + font-weight: 800; + } + + .summary-list { + margin: 0; + padding: 8px 16px; + display: grid; + gap: 0; + } + + .summary-row { + display: grid; + grid-template-columns: 128px minmax(0, 1fr); + gap: 12px; + padding: 10px 0; + border-bottom: 1px solid #eef1f4; + align-items: start; + } + + .summary-row:last-child { + border-bottom: 0; + } + + .summary-row.pending { + margin: 0 -16px; + padding-inline: 13px 16px; + border-left: 3px solid var(--platform-color, var(--accent)); + background: color-mix(in srgb, var(--platform-color, var(--accent)) 6%, #ffffff); + } + + .summary-label { + color: var(--muted); + font-size: 12px; + line-height: 1.4; + font-weight: 760; + } + + .summary-value { + margin: 0; + min-width: 0; + color: var(--ink); + font-size: 13px; + line-height: 1.45; + font-weight: 680; + overflow-wrap: anywhere; + } + + .summary-row.pending .summary-value { + color: var(--platform-color, var(--accent)); + font-weight: 800; + } + + .summary-status { + min-height: 24px; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0 9px; + border: 1px solid rgba(19, 111, 99, 0.28); + border-radius: 999px; + background: #eff9f6; + color: var(--accent); + font-size: 12px; + line-height: 1.2; + font-weight: 800; + white-space: nowrap; + } + + .summary-status.disabled { + border-color: rgba(181, 65, 55, 0.32); + background: #fff1ef; + color: var(--danger); + } + + .summary-status.neutral { + border-color: var(--line); + background: #f6f7f8; + color: var(--muted); + } + + .summary-row.pending .summary-status { + font-weight: 840; + } + + .summary-actions { + display: flex; + gap: 10px; + flex-wrap: wrap; + padding: 15px 16px; + border-top: 1px solid var(--line); + background: #fbfcfd; + } + + .toast { + min-height: 20px; + color: var(--accent); + font-size: 13px; + line-height: 1.45; + } + + .quiet { + color: var(--muted); + } + + /* Modern visual polish layer: keeps the existing markup and behavior intact. */ + :root { + --bg: #f4f8fb; + --surface: rgba(255, 255, 255, 0.94); + --soft: #f1f5f8; + --ink: #101725; + --muted: #617083; + --line: #d9e2ea; + --line-strong: #b8c7d4; + --accent: #08796f; + --accent-ink: #ffffff; + --danger: #b54137; + --radius-lg: 22px; + --radius-md: 16px; + --shadow-soft: 0 18px 48px rgba(16, 23, 37, 0.08); + --shadow-panel: 0 22px 70px rgba(25, 45, 68, 0.11); + } + + body { + position: relative; + overflow-x: hidden; + background: + radial-gradient(circle at 14% 0%, rgba(8, 121, 111, 0.12), transparent 34%), + radial-gradient(circle at 86% 4%, rgba(47, 95, 159, 0.11), transparent 32%), + linear-gradient(180deg, #fbfdff 0%, var(--bg) 55%, #eef4f8 100%); + } + + body::before { + content: ""; + position: fixed; + inset: 0; + z-index: -1; + pointer-events: none; + opacity: 0.42; + background-image: + linear-gradient(rgba(8, 121, 111, 0.07) 1px, transparent 1px), + linear-gradient(90deg, rgba(47, 95, 159, 0.055) 1px, transparent 1px), + linear-gradient(135deg, transparent 0 44%, rgba(8, 121, 111, 0.08) 45% 46%, transparent 47% 100%); + background-size: 72px 72px, 72px 72px, 340px 190px; + -webkit-mask-image: linear-gradient(180deg, #000 0, rgba(0, 0, 0, 0.72) 260px, transparent 680px); + mask-image: linear-gradient(180deg, #000 0, rgba(0, 0, 0, 0.72) 260px, transparent 680px); + } + + .topbar { + width: min(1400px, calc(100vw - 28px)); + min-height: 88px; + margin: 10px auto 0; + padding: 18px 22px; + top: 10px; + border: 1px solid rgba(210, 222, 232, 0.9); + border-radius: var(--radius-lg); + background: rgba(255, 255, 255, 0.82); + box-shadow: 0 14px 42px rgba(22, 35, 53, 0.08); + backdrop-filter: blur(22px); + } + + .brand { + grid-template-columns: 46px minmax(0, 1fr); + column-gap: 12px; + align-items: center; + } + + .brand::before { + content: "↗"; + grid-row: 1 / 3; + width: 44px; + height: 44px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 50%; + background: + radial-gradient(circle at 34% 28%, rgba(255, 255, 255, 0.88), transparent 28%), + linear-gradient(135deg, #0b8a80, #075f62 72%); + color: #ffffff; + font-size: 22px; + font-weight: 860; + box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25), 0 10px 24px rgba(8, 121, 111, 0.22); + } + + h1 { + font-size: clamp(24px, 2vw, 30px); + letter-spacing: -0.03em; + } + + .brand p { + color: #66758a; + font-size: 13px; + } + + .btn, + .pill { + min-height: 40px; + border-color: rgba(203, 215, 226, 0.9); + border-radius: 12px; + background: rgba(255, 255, 255, 0.82); + color: #45566b; + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.75), 0 8px 20px rgba(22, 35, 53, 0.05); + } + + .btn:hover { + border-color: rgba(145, 163, 181, 0.86); + background: #ffffff; + box-shadow: 0 12px 24px rgba(22, 35, 53, 0.08); + } + + .shell { + width: min(1400px, calc(100vw - 36px)); + padding: 12px 0 42px; + gap: 12px; + } + + .platform-strip { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 8px; + padding: 10px 12px; + border: 1px solid rgba(210, 222, 232, 0.85); + border-radius: var(--radius-lg); + background: rgba(255, 255, 255, 0.74); + box-shadow: var(--shadow-soft); + backdrop-filter: blur(16px); + } + + .platform-button { + position: relative; + min-height: 52px; + gap: 8px; + padding: 8px 28px 8px 8px; + border: 1px solid rgba(207, 218, 229, 0.9); + border-left: 1px solid rgba(207, 218, 229, 0.9); + border-radius: var(--radius-md); + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(250, 252, 254, 0.9)); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85); + } + + .platform-button:hover { + transform: translateY(-2px); + border-color: color-mix(in srgb, var(--platform-color) 34%, var(--line)); + box-shadow: 0 14px 28px rgba(22, 35, 53, 0.08); + } + + .platform-button.active { + border-color: color-mix(in srgb, var(--platform-color) 58%, var(--line)); + background: + radial-gradient(circle at 12% 18%, color-mix(in srgb, var(--platform-color) 16%, transparent), transparent 42%), + linear-gradient(180deg, #ffffff, color-mix(in srgb, var(--platform-color) 5%, #ffffff)); + box-shadow: 0 16px 34px color-mix(in srgb, var(--platform-color) 18%, transparent); + } + + .platform-button.active::after { + content: "✓"; + position: absolute; + top: 50%; + right: 8px; + width: 18px; + height: 18px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 50%; + background: var(--platform-color); + color: #ffffff; + font-size: 11px; + font-weight: 880; + transform: translateY(-50%); + box-shadow: 0 8px 18px color-mix(in srgb, var(--platform-color) 24%, transparent); + } + + .mark { + width: 32px; + height: 32px; + border-radius: 10px; + background: color-mix(in srgb, var(--platform-color) 10%, #f7fafc); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--platform-color) 10%, transparent); + } + + .platform-button.active .mark { + background: linear-gradient(135deg, var(--platform-color), color-mix(in srgb, var(--platform-color) 72%, #052f36)); + box-shadow: 0 12px 24px color-mix(in srgb, var(--platform-color) 22%, transparent); + } + + .platform-copy strong { + color: #121a28; + font-size: 13px; + letter-spacing: -0.015em; + } + + .platform-copy span, + .platform-copy small { + line-height: 1.35; + } + + .switch-surface { + grid-template-columns: minmax(0, 1.56fr) minmax(390px, 0.94fr); + gap: 14px; + align-items: start; + } + + .switch-panel, + .summary-panel { + border: 1px solid rgba(210, 222, 232, 0.92); + border-radius: var(--radius-lg); + background: rgba(255, 255, 255, 0.86); + box-shadow: var(--shadow-panel); + backdrop-filter: blur(18px); + } + + .switch-panel { + gap: 18px; + padding: 24px; + } + + .panel-head { + padding-bottom: 2px; + } + + .eyebrow { + color: #64748b; + font-size: 12px; + letter-spacing: 0.04em; + } + + .panel-head h2 { + color: #111827; + font-size: clamp(31px, 3vw, 42px); + letter-spacing: -0.045em; + } + + .public-note { + max-width: 720px; + color: #53657a; + font-size: 15px; + } + + .public-preview { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 12px; + margin-top: 4px; + } + + .public-preview-card { + min-width: 0; + display: grid; + gap: 6px; + padding: 16px; + border: 1px solid rgba(212, 223, 234, 0.86); + border-radius: var(--radius-md); + background: + linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(247, 250, 252, 0.88)); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.86); + } + + .public-preview-card strong { + color: #152033; + font-size: 14px; + line-height: 1.3; + font-weight: 800; + } + + .public-preview-card span { + color: #64748b; + font-size: 12px; + line-height: 1.5; + } + + .quick-form { + gap: 14px; + } + + .form-section { + position: relative; + gap: 14px 16px; + padding: 16px; + border: 1px solid rgba(215, 225, 235, 0.86); + border-radius: var(--radius-md); + background: + linear-gradient(90deg, color-mix(in srgb, var(--platform-color, var(--accent)) 5%, transparent), transparent 32%), + linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(250, 252, 254, 0.88)); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.84); + } + + .form-section + .form-section { + padding-top: 16px; + border-top: 1px solid rgba(215, 225, 235, 0.86); + } + + .control-block { + grid-template-rows: auto 46px minmax(20px, auto); + gap: 8px; + color: #53657a; + font-size: 12px; + line-height: 1.25; + font-weight: 790; + } + + .control-block > span:first-child { + color: #293548; + } + + select, + input, + .mode { + min-height: 46px; + border-color: rgba(207, 219, 230, 0.92); + border-radius: 12px; + background: rgba(255, 255, 255, 0.92); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 8px 20px rgba(22, 35, 53, 0.035); + } + + select, + input { + height: 46px; + color: #172033; + font-size: 14px; + font-weight: 700; + } + + select:disabled, + input:disabled { + background: rgba(241, 245, 249, 0.72); + color: #7d8da1; + box-shadow: none; + } + + .mode { + height: 46px; + background: rgba(238, 244, 248, 0.9); + } + + .mode button { + border-radius: 9px; + color: #5c6e84; + font-size: 13px; + font-weight: 800; + } + + .mode button.active { + background: #ffffff; + color: var(--platform-color, var(--accent)); + box-shadow: 0 10px 20px rgba(22, 35, 53, 0.08); + } + + .selection-meta { + color: #758397; + font-size: 12px; + } + + .run-area { + gap: 10px; + padding-top: 2px; + } + + .run-button { + width: 100%; + min-height: 58px; + border-radius: 12px; + background: + linear-gradient(135deg, var(--platform-color, var(--accent)), color-mix(in srgb, var(--platform-color, var(--accent)) 76%, #042e35)); + box-shadow: 0 18px 36px color-mix(in srgb, var(--platform-color, var(--accent)) 24%, transparent); + letter-spacing: 0.02em; + } + + .run-button:hover:not(:disabled) { + filter: none; + box-shadow: 0 22px 42px color-mix(in srgb, var(--platform-color, var(--accent)) 30%, transparent); + } + + .run-button:disabled { + box-shadow: none; + } + + .action-note { + color: #53657a; + font-size: 13px; + } + + .toast { + grid-column: 1 / -1; + color: var(--platform-color, var(--accent)); + font-weight: 720; + } + + .summary-panel { + position: sticky; + top: 112px; + overflow: hidden; + } + + .summary-head { + padding: 24px 24px 18px; + border-bottom-color: rgba(218, 227, 236, 0.9); + } + + .summary-head h2 { + color: #111827; + font-size: 22px; + letter-spacing: -0.03em; + } + + .summary-list { + padding: 4px 24px 18px; + } + + .summary-row { + grid-template-columns: 132px minmax(0, 1fr); + gap: 14px; + padding: 14px 0; + border-bottom-color: rgba(229, 236, 242, 0.96); + } + + .summary-label { + color: #66758a; + font-size: 12px; + font-weight: 790; + } + + .summary-value { + color: #263244; + font-size: 13px; + font-weight: 700; + } + + .summary-row.pending { + margin: 0 -24px; + padding-inline: 21px 24px; + border-left: 3px solid var(--platform-color, var(--accent)); + background: + linear-gradient(90deg, color-mix(in srgb, var(--platform-color, var(--accent)) 9%, #ffffff), rgba(255, 255, 255, 0.72)); + } + + .summary-status { + min-height: 26px; + border-color: color-mix(in srgb, var(--platform-color, var(--accent)) 26%, #d9e2ea); + background: color-mix(in srgb, var(--platform-color, var(--accent)) 9%, #ffffff); + color: var(--platform-color, var(--accent)); + } + + .summary-actions { + padding: 16px 24px 24px; + border-top-color: rgba(218, 227, 236, 0.9); + background: transparent; + } + + @media (max-width: 820px) { + .platform-strip { + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 6px; + padding: 8px 10px; + } + + .platform-copy strong { + font-size: 12px; + } + + .switch-surface { + grid-template-columns: 1fr; + } + + .summary-panel { + position: static; + } + + .public-preview { + grid-template-columns: 1fr; + } + } + + + @media (max-width: 540px) { + .platform-strip { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 5px; + padding: 6px 8px; + } + .platform-button { + min-height: 40px; + gap: 5px; + padding: 5px 7px; + } + .mark { + width: 26px; + height: 26px; + font-size: 10px; + } + .platform-copy strong { + font-size: 11px; + } + } + + @media (max-width: 680px) { + .topbar { + position: static; + align-items: flex-start; + flex-direction: column; + padding: 18px; + } + + .top-actions { + justify-content: flex-start; + width: 100%; + } + + .boot-screen { + width: min(100% - 28px, 680px); + min-height: calc(100svh - 122px); + padding-top: 22px; + } + + .shell { + width: min(100% - 28px, 1160px); + padding-top: 18px; + } + + .platform-strip, + .quick-form, + .form-section { + grid-template-columns: 1fr; + } + + .platform-strip { + grid-template-columns: repeat(5, minmax(68px, 1fr)); + gap: 6px; + padding: 8px; + overflow-x: auto; + } + + .platform-button { + min-height: 48px; + padding-inline: 8px 24px; + } + + .platform-copy strong { + font-size: 11px; + } + + .mode-block, + .section-wide { + grid-column: auto; + } + + .switch-panel { + padding: 18px; + } + + .summary-row { + grid-template-columns: 1fr; + gap: 3px; + } + + .run-area { + grid-template-columns: 1fr; + } + + select { + font-size: 13px; + } + } + + @media (prefers-reduced-motion: no-preference) { + .platform-strip, + .switch-surface { + animation: rise-in 260ms ease both; + } + + .switch-surface { + animation-delay: 60ms; + } + + @keyframes rise-in { + from { + opacity: 0; + transform: translateY(8px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + @keyframes loading-sweep { + from { + transform: translateX(-110%); + } + to { + transform: translateX(260%); + } + } + } + + @media (prefers-reduced-motion: reduce) { + .loading-track::before { + animation: none; + transform: translateX(0); + } + } \ No newline at end of file diff --git a/web/strategy-switch-console/app_css.js b/web/strategy-switch-console/app_css.js new file mode 100644 index 0000000..c5cf043 --- /dev/null +++ b/web/strategy-switch-console/app_css.js @@ -0,0 +1,2 @@ +// Generated — CSS asset +export const APP_CSS = ":root {\n --bg: #f5f6f8;\n --surface: #ffffff;\n --soft: #eef1f4;\n --ink: #16191f;\n --muted: #66707c;\n --line: #dce1e7;\n --line-strong: #b8c2cc;\n --accent: #136f63;\n --accent-ink: #ffffff;\n --danger: #b54137;\n --lb: #0f766e;\n --ib: #2f5f9f;\n --sw: #9b4153;\n --ft: #94651f;\n --qmt: #b45309;\n --bn: #f0b90b;\n font-family:\n Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,\n \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif;\n }\n\n * {\n box-sizing: border-box;\n }\n\n html {\n min-height: 100%;\n background: var(--bg);\n }\n\n body {\n margin: 0;\n min-height: 100svh;\n background:\n linear-gradient(180deg, #fbfcfd 0, #eef2f5 100%);\n color: var(--ink);\n letter-spacing: 0;\n }\n\n button,\n select,\n input {\n font: inherit;\n letter-spacing: 0;\n }\n\n button {\n cursor: pointer;\n }\n\n a {\n color: inherit;\n }\n\n button:focus-visible,\n select:focus-visible,\n input:focus-visible,\n a:focus-visible {\n outline: 3px solid color-mix(in srgb, var(--platform-color, var(--accent)) 24%, transparent);\n outline-offset: 2px;\n }\n\n [hidden] {\n display: none !important;\n }\n\n h1,\n h2,\n h3,\n p {\n margin: 0;\n }\n\n .topbar {\n min-height: 72px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n padding: 17px 28px;\n border-bottom: 1px solid var(--line);\n background: rgba(250, 251, 252, 0.88);\n backdrop-filter: blur(14px);\n position: sticky;\n top: 0;\n z-index: 20;\n }\n\n .brand {\n display: grid;\n gap: 3px;\n min-width: 0;\n }\n\n h1 {\n font-size: 22px;\n line-height: 1.12;\n font-weight: 780;\n overflow-wrap: anywhere;\n }\n\n .brand p {\n color: var(--muted);\n font-size: 13px;\n line-height: 1.4;\n }\n\n .top-actions {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 10px;\n flex-wrap: wrap;\n }\n\n .auth-status {\n max-width: 260px;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .shell {\n width: min(1160px, calc(100vw - 36px));\n margin: 0 auto;\n padding: 22px 0 32px;\n display: grid;\n gap: 16px;\n }\n\n body.app-loading .shell {\n display: none;\n }\n\n body:not(.app-loading) .boot-screen {\n display: none;\n }\n\n .boot-screen {\n width: min(680px, calc(100vw - 36px));\n min-height: calc(100svh - 72px);\n margin: 0 auto;\n display: grid;\n align-items: center;\n padding: 34px 0;\n }\n\n .boot-panel {\n display: grid;\n gap: 13px;\n padding: 8px 0;\n }\n\n .boot-kicker {\n color: var(--accent);\n font-size: 12px;\n line-height: 1.2;\n font-weight: 800;\n text-transform: uppercase;\n }\n\n .boot-panel h2 {\n color: var(--ink);\n font-size: clamp(28px, 5vw, 44px);\n line-height: 1.04;\n font-weight: 820;\n }\n\n .boot-panel p {\n color: var(--muted);\n font-size: 14px;\n line-height: 1.5;\n max-width: 520px;\n }\n\n .loading-track {\n width: 100%;\n height: 5px;\n overflow: hidden;\n border-radius: 999px;\n background: #dde4ea;\n }\n\n .loading-track::before {\n content: \"\";\n display: block;\n width: 42%;\n height: 100%;\n border-radius: inherit;\n background: var(--accent);\n animation: loading-sweep 1.05s ease-in-out infinite;\n }\n\n .pill,\n .btn {\n min-height: 36px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 7px;\n border: 1px solid var(--line);\n background: var(--surface);\n color: var(--muted);\n text-decoration: none;\n white-space: nowrap;\n font-size: 13px;\n font-weight: 740;\n box-shadow: 0 1px 0 rgba(22, 25, 31, 0.03);\n }\n\n .pill {\n padding: 0 12px;\n border-radius: 999px;\n }\n\n .pill.ready {\n border-color: rgba(19, 111, 99, 0.28);\n background: #eff9f6;\n color: var(--accent);\n }\n\n .btn {\n padding: 0 13px;\n border-radius: 8px;\n transition: border-color 150ms ease, background 150ms ease, transform 150ms ease;\n }\n\n .btn:hover {\n transform: translateY(-1px);\n border-color: var(--line-strong);\n background: #fafbfc;\n }\n\n .lang-toggle {\n min-width: 42px;\n padding: 0 10px;\n }\n\n .mode button {\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: var(--muted);\n font-weight: 760;\n transition: background 150ms ease, color 150ms ease;\n }\n\n .mode button.active {\n background: #ffffff;\n color: var(--ink);\n box-shadow: 0 1px 7px rgba(22, 25, 31, 0.08);\n }\n\n .platform-strip {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 8px;\n }\n\n .platform-button {\n min-width: 0;\n min-height: 52px;\n display: grid;\n grid-template-columns: auto 1fr;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border: 1px solid var(--line);\n border-left: 4px solid var(--platform-color);\n border-radius: 8px;\n background: var(--surface);\n color: var(--ink);\n text-align: left;\n transition:\n transform 150ms ease,\n border-color 150ms ease,\n background 150ms ease,\n box-shadow 150ms ease;\n }\n\n .platform-button:hover {\n transform: translateY(-1px);\n border-color: var(--line-strong);\n }\n\n .platform-button.active {\n border-color: var(--platform-color);\n background:\n linear-gradient(180deg, color-mix(in srgb, var(--platform-color) 7%, white), #ffffff 68%);\n box-shadow: 0 14px 30px rgba(22, 25, 31, 0.09);\n }\n\n .platform-button[data-platform=\"longbridge\"] {\n --platform-color: var(--lb);\n }\n\n .platform-button[data-platform=\"ibkr\"] {\n --platform-color: var(--ib);\n }\n\n .platform-button[data-platform=\"schwab\"] {\n --platform-color: var(--sw);\n }\n\n .platform-button[data-platform=\"firstrade\"] {\n --platform-color: var(--ft);\n }\n\n .platform-button[data-platform=\"qmt\"] {\n --platform-color: var(--qmt);\n }\n\n .platform-button[data-platform=\"binance\"] {\n --platform-color: var(--bn);\n }\n\n .execution-cash-policy-section {\n grid-template-columns: 1fr;\n }\n\n .execution-cash-policy-heading {\n grid-column: 1 / -1;\n margin: 0;\n font-size: 13px;\n font-weight: 780;\n color: var(--ink);\n }\n\n .execution-cash-policy-note {\n grid-column: 1 / -1;\n margin: 0;\n color: var(--muted);\n font-size: 12px;\n line-height: 1.45;\n }\n\n .execution-cash-policy-grid {\n grid-column: 1 / -1;\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 14px;\n align-items: start;\n }\n\n .policy-block-muted .selection-meta {\n color: var(--danger);\n }\n\n @media (max-width: 720px) {\n .execution-cash-policy-grid {\n grid-template-columns: 1fr;\n }\n }\n\n .mark {\n width: 32px;\n height: 32px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 8px;\n background: color-mix(in srgb, var(--platform-color) 12%, white);\n color: var(--platform-color);\n font-size: 11px;\n font-weight: 840;\n transition: background 150ms ease, color 150ms ease;\n }\n\n .platform-button.active .mark {\n background: var(--platform-color);\n color: #ffffff;\n }\n\n .platform-copy {\n min-width: 0;\n display: grid;\n gap: 3px;\n }\n\n .platform-copy strong {\n font-size: 13px;\n line-height: 1.18;\n overflow-wrap: anywhere;\n }\n\n .platform-strip .platform-copy span,\n .platform-strip .platform-copy small {\n display: none;\n }\n\n .platform-copy span {\n color: var(--muted);\n font-size: 12px;\n line-height: 1.35;\n overflow-wrap: anywhere;\n }\n\n .platform-copy small {\n color: var(--platform-color);\n font-size: 11px;\n line-height: 1.25;\n font-weight: 780;\n overflow-wrap: anywhere;\n }\n\n .switch-surface {\n display: grid;\n grid-template-columns: minmax(0, 1.04fr) minmax(320px, 0.96fr);\n gap: 18px;\n align-items: stretch;\n }\n\n .switch-surface.summary-hidden {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .switch-panel,\n .summary-panel {\n min-width: 0;\n border: 1px solid var(--line);\n border-radius: 8px;\n background: var(--surface);\n box-shadow: 0 14px 34px rgba(22, 25, 31, 0.07);\n }\n\n .switch-panel {\n display: grid;\n gap: 20px;\n padding: 22px;\n }\n\n .panel-head {\n display: grid;\n gap: 5px;\n }\n\n .eyebrow {\n color: var(--muted);\n font-size: 12px;\n line-height: 1.2;\n font-weight: 780;\n text-transform: uppercase;\n }\n\n .panel-head h2 {\n font-size: clamp(24px, 3vw, 34px);\n line-height: 1.08;\n font-weight: 820;\n overflow-wrap: anywhere;\n }\n\n .quick-form {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n align-items: start;\n gap: 16px 14px;\n }\n\n .control-block {\n display: grid;\n grid-template-rows: auto 48px minmax(20px, auto);\n align-content: start;\n gap: 8px;\n min-width: 0;\n color: var(--muted);\n font-size: 12px;\n font-weight: 760;\n }\n\n .form-section {\n grid-column: 1 / -1;\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n align-items: start;\n gap: 14px;\n }\n\n .form-section + .form-section {\n padding-top: 16px;\n border-top: 1px solid var(--line);\n }\n\n .section-wide {\n grid-column: 1 / -1;\n }\n\n .mode-block {\n grid-column: 1 / -1;\n }\n\n select,\n input {\n width: 100%;\n min-width: 0;\n height: 48px;\n padding: 0 13px;\n border: 1px solid var(--line);\n border-radius: 8px;\n background: #ffffff;\n color: var(--ink);\n outline: none;\n font-size: 14px;\n font-weight: 680;\n overflow: hidden;\n padding-right: 42px;\n text-overflow: ellipsis;\n transition: border-color 150ms ease, box-shadow 150ms ease;\n }\n\n select:focus,\n input:focus {\n border-color: var(--platform-color, var(--accent));\n box-shadow: 0 0 0 3px rgba(19, 111, 99, 0.12);\n }\n\n input::placeholder {\n color: #9aa3ad;\n opacity: 1;\n }\n\n .selection-meta {\n min-height: 20px;\n color: var(--muted);\n font-size: 12px;\n line-height: 1.45;\n overflow-wrap: anywhere;\n }\n\n .mode {\n height: 48px;\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 4px;\n padding: 4px;\n border: 1px solid var(--line);\n border-radius: 8px;\n background: var(--soft);\n }\n\n .mode button {\n font-size: 13px;\n }\n\n .run-area {\n display: grid;\n gap: 10px;\n padding-top: 2px;\n }\n\n .public-note {\n color: var(--muted);\n font-size: 14px;\n line-height: 1.55;\n max-width: 560px;\n }\n\n .run-button {\n min-height: 56px;\n border: 0;\n border-radius: 8px;\n background: var(--platform-color, var(--accent));\n color: var(--accent-ink);\n font-size: 16px;\n font-weight: 820;\n transition: transform 150ms ease, filter 150ms ease, opacity 150ms ease;\n }\n\n .run-button:hover:not(:disabled) {\n transform: translateY(-1px);\n filter: brightness(0.92);\n }\n\n .run-button:disabled {\n opacity: 0.48;\n cursor: not-allowed;\n transform: none;\n }\n\n .action-note {\n min-height: 20px;\n color: var(--muted);\n font-size: 13px;\n line-height: 1.45;\n }\n\n .action-note.warning {\n color: var(--danger);\n font-weight: 720;\n }\n\n .summary-panel {\n display: grid;\n grid-template-rows: auto 1fr auto;\n overflow: hidden;\n }\n\n .summary-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 16px;\n border-bottom: 1px solid var(--line);\n }\n\n .summary-head h2 {\n font-size: 15px;\n line-height: 1.2;\n font-weight: 800;\n }\n\n .summary-list {\n margin: 0;\n padding: 8px 16px;\n display: grid;\n gap: 0;\n }\n\n .summary-row {\n display: grid;\n grid-template-columns: 128px minmax(0, 1fr);\n gap: 12px;\n padding: 10px 0;\n border-bottom: 1px solid #eef1f4;\n align-items: start;\n }\n\n .summary-row:last-child {\n border-bottom: 0;\n }\n\n .summary-row.pending {\n margin: 0 -16px;\n padding-inline: 13px 16px;\n border-left: 3px solid var(--platform-color, var(--accent));\n background: color-mix(in srgb, var(--platform-color, var(--accent)) 6%, #ffffff);\n }\n\n .summary-label {\n color: var(--muted);\n font-size: 12px;\n line-height: 1.4;\n font-weight: 760;\n }\n\n .summary-value {\n margin: 0;\n min-width: 0;\n color: var(--ink);\n font-size: 13px;\n line-height: 1.45;\n font-weight: 680;\n overflow-wrap: anywhere;\n }\n\n .summary-row.pending .summary-value {\n color: var(--platform-color, var(--accent));\n font-weight: 800;\n }\n\n .summary-status {\n min-height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0 9px;\n border: 1px solid rgba(19, 111, 99, 0.28);\n border-radius: 999px;\n background: #eff9f6;\n color: var(--accent);\n font-size: 12px;\n line-height: 1.2;\n font-weight: 800;\n white-space: nowrap;\n }\n\n .summary-status.disabled {\n border-color: rgba(181, 65, 55, 0.32);\n background: #fff1ef;\n color: var(--danger);\n }\n\n .summary-status.neutral {\n border-color: var(--line);\n background: #f6f7f8;\n color: var(--muted);\n }\n\n .summary-row.pending .summary-status {\n font-weight: 840;\n }\n\n .summary-actions {\n display: flex;\n gap: 10px;\n flex-wrap: wrap;\n padding: 15px 16px;\n border-top: 1px solid var(--line);\n background: #fbfcfd;\n }\n\n .toast {\n min-height: 20px;\n color: var(--accent);\n font-size: 13px;\n line-height: 1.45;\n }\n\n .quiet {\n color: var(--muted);\n }\n\n /* Modern visual polish layer: keeps the existing markup and behavior intact. */\n :root {\n --bg: #f4f8fb;\n --surface: rgba(255, 255, 255, 0.94);\n --soft: #f1f5f8;\n --ink: #101725;\n --muted: #617083;\n --line: #d9e2ea;\n --line-strong: #b8c7d4;\n --accent: #08796f;\n --accent-ink: #ffffff;\n --danger: #b54137;\n --radius-lg: 22px;\n --radius-md: 16px;\n --shadow-soft: 0 18px 48px rgba(16, 23, 37, 0.08);\n --shadow-panel: 0 22px 70px rgba(25, 45, 68, 0.11);\n }\n\n body {\n position: relative;\n overflow-x: hidden;\n background:\n radial-gradient(circle at 14% 0%, rgba(8, 121, 111, 0.12), transparent 34%),\n radial-gradient(circle at 86% 4%, rgba(47, 95, 159, 0.11), transparent 32%),\n linear-gradient(180deg, #fbfdff 0%, var(--bg) 55%, #eef4f8 100%);\n }\n\n body::before {\n content: \"\";\n position: fixed;\n inset: 0;\n z-index: -1;\n pointer-events: none;\n opacity: 0.42;\n background-image:\n linear-gradient(rgba(8, 121, 111, 0.07) 1px, transparent 1px),\n linear-gradient(90deg, rgba(47, 95, 159, 0.055) 1px, transparent 1px),\n linear-gradient(135deg, transparent 0 44%, rgba(8, 121, 111, 0.08) 45% 46%, transparent 47% 100%);\n background-size: 72px 72px, 72px 72px, 340px 190px;\n -webkit-mask-image: linear-gradient(180deg, #000 0, rgba(0, 0, 0, 0.72) 260px, transparent 680px);\n mask-image: linear-gradient(180deg, #000 0, rgba(0, 0, 0, 0.72) 260px, transparent 680px);\n }\n\n .topbar {\n width: min(1400px, calc(100vw - 28px));\n min-height: 88px;\n margin: 10px auto 0;\n padding: 18px 22px;\n top: 10px;\n border: 1px solid rgba(210, 222, 232, 0.9);\n border-radius: var(--radius-lg);\n background: rgba(255, 255, 255, 0.82);\n box-shadow: 0 14px 42px rgba(22, 35, 53, 0.08);\n backdrop-filter: blur(22px);\n }\n\n .brand {\n grid-template-columns: 46px minmax(0, 1fr);\n column-gap: 12px;\n align-items: center;\n }\n\n .brand::before {\n content: \"↗\";\n grid-row: 1 / 3;\n width: 44px;\n height: 44px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n background:\n radial-gradient(circle at 34% 28%, rgba(255, 255, 255, 0.88), transparent 28%),\n linear-gradient(135deg, #0b8a80, #075f62 72%);\n color: #ffffff;\n font-size: 22px;\n font-weight: 860;\n box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.25), 0 10px 24px rgba(8, 121, 111, 0.22);\n }\n\n h1 {\n font-size: clamp(24px, 2vw, 30px);\n letter-spacing: -0.03em;\n }\n\n .brand p {\n color: #66758a;\n font-size: 13px;\n }\n\n .btn,\n .pill {\n min-height: 40px;\n border-color: rgba(203, 215, 226, 0.9);\n border-radius: 12px;\n background: rgba(255, 255, 255, 0.82);\n color: #45566b;\n box-shadow: 0 1px 0 rgba(255, 255, 255, 0.75), 0 8px 20px rgba(22, 35, 53, 0.05);\n }\n\n .btn:hover {\n border-color: rgba(145, 163, 181, 0.86);\n background: #ffffff;\n box-shadow: 0 12px 24px rgba(22, 35, 53, 0.08);\n }\n\n .shell {\n width: min(1400px, calc(100vw - 36px));\n padding: 12px 0 42px;\n gap: 12px;\n }\n\n .platform-strip {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 8px;\n padding: 10px 12px;\n border: 1px solid rgba(210, 222, 232, 0.85);\n border-radius: var(--radius-lg);\n background: rgba(255, 255, 255, 0.74);\n box-shadow: var(--shadow-soft);\n backdrop-filter: blur(16px);\n }\n\n .platform-button {\n position: relative;\n min-height: 52px;\n gap: 8px;\n padding: 8px 28px 8px 8px;\n border: 1px solid rgba(207, 218, 229, 0.9);\n border-left: 1px solid rgba(207, 218, 229, 0.9);\n border-radius: var(--radius-md);\n background:\n linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(250, 252, 254, 0.9));\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85);\n }\n\n .platform-button:hover {\n transform: translateY(-2px);\n border-color: color-mix(in srgb, var(--platform-color) 34%, var(--line));\n box-shadow: 0 14px 28px rgba(22, 35, 53, 0.08);\n }\n\n .platform-button.active {\n border-color: color-mix(in srgb, var(--platform-color) 58%, var(--line));\n background:\n radial-gradient(circle at 12% 18%, color-mix(in srgb, var(--platform-color) 16%, transparent), transparent 42%),\n linear-gradient(180deg, #ffffff, color-mix(in srgb, var(--platform-color) 5%, #ffffff));\n box-shadow: 0 16px 34px color-mix(in srgb, var(--platform-color) 18%, transparent);\n }\n\n .platform-button.active::after {\n content: \"✓\";\n position: absolute;\n top: 50%;\n right: 8px;\n width: 18px;\n height: 18px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n background: var(--platform-color);\n color: #ffffff;\n font-size: 11px;\n font-weight: 880;\n transform: translateY(-50%);\n box-shadow: 0 8px 18px color-mix(in srgb, var(--platform-color) 24%, transparent);\n }\n\n .mark {\n width: 32px;\n height: 32px;\n border-radius: 10px;\n background: color-mix(in srgb, var(--platform-color) 10%, #f7fafc);\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--platform-color) 10%, transparent);\n }\n\n .platform-button.active .mark {\n background: linear-gradient(135deg, var(--platform-color), color-mix(in srgb, var(--platform-color) 72%, #052f36));\n box-shadow: 0 12px 24px color-mix(in srgb, var(--platform-color) 22%, transparent);\n }\n\n .platform-copy strong {\n color: #121a28;\n font-size: 13px;\n letter-spacing: -0.015em;\n }\n\n .platform-copy span,\n .platform-copy small {\n line-height: 1.35;\n }\n\n .switch-surface {\n grid-template-columns: minmax(0, 1.56fr) minmax(390px, 0.94fr);\n gap: 14px;\n align-items: start;\n }\n\n .switch-panel,\n .summary-panel {\n border: 1px solid rgba(210, 222, 232, 0.92);\n border-radius: var(--radius-lg);\n background: rgba(255, 255, 255, 0.86);\n box-shadow: var(--shadow-panel);\n backdrop-filter: blur(18px);\n }\n\n .switch-panel {\n gap: 18px;\n padding: 24px;\n }\n\n .panel-head {\n padding-bottom: 2px;\n }\n\n .eyebrow {\n color: #64748b;\n font-size: 12px;\n letter-spacing: 0.04em;\n }\n\n .panel-head h2 {\n color: #111827;\n font-size: clamp(31px, 3vw, 42px);\n letter-spacing: -0.045em;\n }\n\n .public-note {\n max-width: 720px;\n color: #53657a;\n font-size: 15px;\n }\n\n .public-preview {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 12px;\n margin-top: 4px;\n }\n\n .public-preview-card {\n min-width: 0;\n display: grid;\n gap: 6px;\n padding: 16px;\n border: 1px solid rgba(212, 223, 234, 0.86);\n border-radius: var(--radius-md);\n background:\n linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(247, 250, 252, 0.88));\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.86);\n }\n\n .public-preview-card strong {\n color: #152033;\n font-size: 14px;\n line-height: 1.3;\n font-weight: 800;\n }\n\n .public-preview-card span {\n color: #64748b;\n font-size: 12px;\n line-height: 1.5;\n }\n\n .quick-form {\n gap: 14px;\n }\n\n .form-section {\n position: relative;\n gap: 14px 16px;\n padding: 16px;\n border: 1px solid rgba(215, 225, 235, 0.86);\n border-radius: var(--radius-md);\n background:\n linear-gradient(90deg, color-mix(in srgb, var(--platform-color, var(--accent)) 5%, transparent), transparent 32%),\n linear-gradient(180deg, rgba(255, 255, 255, 0.96), rgba(250, 252, 254, 0.88));\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.84);\n }\n\n .form-section + .form-section {\n padding-top: 16px;\n border-top: 1px solid rgba(215, 225, 235, 0.86);\n }\n\n .control-block {\n grid-template-rows: auto 46px minmax(20px, auto);\n gap: 8px;\n color: #53657a;\n font-size: 12px;\n line-height: 1.25;\n font-weight: 790;\n }\n\n .control-block > span:first-child {\n color: #293548;\n }\n\n select,\n input,\n .mode {\n min-height: 46px;\n border-color: rgba(207, 219, 230, 0.92);\n border-radius: 12px;\n background: rgba(255, 255, 255, 0.92);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 8px 20px rgba(22, 35, 53, 0.035);\n }\n\n select,\n input {\n height: 46px;\n color: #172033;\n font-size: 14px;\n font-weight: 700;\n }\n\n select:disabled,\n input:disabled {\n background: rgba(241, 245, 249, 0.72);\n color: #7d8da1;\n box-shadow: none;\n }\n\n .mode {\n height: 46px;\n background: rgba(238, 244, 248, 0.9);\n }\n\n .mode button {\n border-radius: 9px;\n color: #5c6e84;\n font-size: 13px;\n font-weight: 800;\n }\n\n .mode button.active {\n background: #ffffff;\n color: var(--platform-color, var(--accent));\n box-shadow: 0 10px 20px rgba(22, 35, 53, 0.08);\n }\n\n .selection-meta {\n color: #758397;\n font-size: 12px;\n }\n\n .run-area {\n gap: 10px;\n padding-top: 2px;\n }\n\n .run-button {\n width: 100%;\n min-height: 58px;\n border-radius: 12px;\n background:\n linear-gradient(135deg, var(--platform-color, var(--accent)), color-mix(in srgb, var(--platform-color, var(--accent)) 76%, #042e35));\n box-shadow: 0 18px 36px color-mix(in srgb, var(--platform-color, var(--accent)) 24%, transparent);\n letter-spacing: 0.02em;\n }\n\n .run-button:hover:not(:disabled) {\n filter: none;\n box-shadow: 0 22px 42px color-mix(in srgb, var(--platform-color, var(--accent)) 30%, transparent);\n }\n\n .run-button:disabled {\n box-shadow: none;\n }\n\n .action-note {\n color: #53657a;\n font-size: 13px;\n }\n\n .toast {\n grid-column: 1 / -1;\n color: var(--platform-color, var(--accent));\n font-weight: 720;\n }\n\n .summary-panel {\n position: sticky;\n top: 112px;\n overflow: hidden;\n }\n\n .summary-head {\n padding: 24px 24px 18px;\n border-bottom-color: rgba(218, 227, 236, 0.9);\n }\n\n .summary-head h2 {\n color: #111827;\n font-size: 22px;\n letter-spacing: -0.03em;\n }\n\n .summary-list {\n padding: 4px 24px 18px;\n }\n\n .summary-row {\n grid-template-columns: 132px minmax(0, 1fr);\n gap: 14px;\n padding: 14px 0;\n border-bottom-color: rgba(229, 236, 242, 0.96);\n }\n\n .summary-label {\n color: #66758a;\n font-size: 12px;\n font-weight: 790;\n }\n\n .summary-value {\n color: #263244;\n font-size: 13px;\n font-weight: 700;\n }\n\n .summary-row.pending {\n margin: 0 -24px;\n padding-inline: 21px 24px;\n border-left: 3px solid var(--platform-color, var(--accent));\n background:\n linear-gradient(90deg, color-mix(in srgb, var(--platform-color, var(--accent)) 9%, #ffffff), rgba(255, 255, 255, 0.72));\n }\n\n .summary-status {\n min-height: 26px;\n border-color: color-mix(in srgb, var(--platform-color, var(--accent)) 26%, #d9e2ea);\n background: color-mix(in srgb, var(--platform-color, var(--accent)) 9%, #ffffff);\n color: var(--platform-color, var(--accent));\n }\n\n .summary-actions {\n padding: 16px 24px 24px;\n border-top-color: rgba(218, 227, 236, 0.9);\n background: transparent;\n }\n\n @media (max-width: 820px) {\n .platform-strip {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 6px;\n padding: 8px 10px;\n }\n\n .platform-copy strong {\n font-size: 12px;\n }\n\n .switch-surface {\n grid-template-columns: 1fr;\n }\n\n .summary-panel {\n position: static;\n }\n\n .public-preview {\n grid-template-columns: 1fr;\n }\n }\n\n\n @media (max-width: 540px) {\n .platform-strip {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 5px;\n padding: 6px 8px;\n }\n .platform-button {\n min-height: 40px;\n gap: 5px;\n padding: 5px 7px;\n }\n .mark {\n width: 26px;\n height: 26px;\n font-size: 10px;\n }\n .platform-copy strong {\n font-size: 11px;\n }\n }\n\n @media (max-width: 680px) {\n .topbar {\n position: static;\n align-items: flex-start;\n flex-direction: column;\n padding: 18px;\n }\n\n .top-actions {\n justify-content: flex-start;\n width: 100%;\n }\n\n .boot-screen {\n width: min(100% - 28px, 680px);\n min-height: calc(100svh - 122px);\n padding-top: 22px;\n }\n\n .shell {\n width: min(100% - 28px, 1160px);\n padding-top: 18px;\n }\n\n .platform-strip,\n .quick-form,\n .form-section {\n grid-template-columns: 1fr;\n }\n\n .platform-strip {\n grid-template-columns: repeat(5, minmax(68px, 1fr));\n gap: 6px;\n padding: 8px;\n overflow-x: auto;\n }\n\n .platform-button {\n min-height: 48px;\n padding-inline: 8px 24px;\n }\n\n .platform-copy strong {\n font-size: 11px;\n }\n\n .mode-block,\n .section-wide {\n grid-column: auto;\n }\n\n .switch-panel {\n padding: 18px;\n }\n\n .summary-row {\n grid-template-columns: 1fr;\n gap: 3px;\n }\n\n .run-area {\n grid-template-columns: 1fr;\n }\n\n select {\n font-size: 13px;\n }\n }\n\n @media (prefers-reduced-motion: no-preference) {\n .platform-strip,\n .switch-surface {\n animation: rise-in 260ms ease both;\n }\n\n .switch-surface {\n animation-delay: 60ms;\n }\n\n @keyframes rise-in {\n from {\n opacity: 0;\n transform: translateY(8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n @keyframes loading-sweep {\n from {\n transform: translateX(-110%);\n }\n to {\n transform: translateX(260%);\n }\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .loading-track::before {\n animation: none;\n transform: translateX(0);\n }\n }"; diff --git a/web/strategy-switch-console/index.html b/web/strategy-switch-console/index.html index 203caf0..73bdf86 100644 --- a/web/strategy-switch-console/index.html +++ b/web/strategy-switch-console/index.html @@ -6,1317 +6,7 @@
选平台、目标账号和策略,一次执行完成切换。
\n正在读取登录状态、账号配置和当前状态。
\n \n登录后查看账号配置。
\n\n允许融资与预留现金覆盖不能同时生效。
\nA 股 QMT 不使用 margin / 平台预留现金;现金约束在策略参数 execution_cash_reserve_ratio 内配置。
\n登录后才可执行切换。
\n \n选平台、目标账号和策略,一次执行完成切换。
\n正在读取登录状态、账号配置和当前状态。
\n \n登录后查看账号配置。
\n\n允许融资与预留现金覆盖不能同时生效。
\nA 股 QMT 不使用 margin / 平台预留现金;现金约束在策略参数 execution_cash_reserve_ratio 内配置。
\n登录后才可执行切换。
\n \n