:root { color: var(--text-primary); background: var(--bg-page); font-family: var(--font-system); } body { margin: 0; min-width: 320px; background: var(--bg-page); } #ops-center-root { min-height: 100vh; } /* ---- 应用外壳:左侧固定导航 + 内容区,宽度对齐主后台侧边栏(248px) ---- */ .ops-shell { display: grid; min-height: 100vh; grid-template-columns: 248px minmax(0, 1fr); } .ops-sidebar { display: flex; flex-direction: column; gap: var(--space-5); border-right: 1px solid var(--border); background: var(--bg-card); padding: var(--space-5) var(--space-3); } .ops-brand { display: flex; align-items: center; gap: var(--space-3); padding: 0 var(--space-2); } .ops-brand > span { display: inline-grid; width: 36px; height: 36px; place-items: center; border-radius: var(--radius-control); background: var(--primary); color: var(--active-contrast, #fff); font-size: 13px; font-weight: 800; } .ops-brand strong { display: block; font-size: 16px; line-height: 1.25; } .ops-brand small { color: var(--text-tertiary); font-size: 11px; } .ops-nav { display: grid; gap: var(--space-2); } .ops-nav button { display: flex; width: 100%; height: 38px; align-items: center; gap: var(--space-3); border: 0; border-radius: var(--radius-control); background: transparent; color: var(--text-secondary); cursor: pointer; padding: 0 var(--space-3); text-align: left; transition: background var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard); } .ops-nav button:hover { background: var(--primary-hover); color: var(--text-primary); } /* active 优先级必须高于 hover:hover 到别的项时当前页仍要保持高亮底色 */ .ops-nav button.is-active, .ops-nav button.is-active:hover { background: var(--primary-surface); color: var(--primary); font-weight: 700; } .ops-main { min-width: 0; background: var(--bg-page); } /* ---- 页面骨架 ---- */ .ops-page { display: grid; gap: var(--space-5); padding: var(--space-6); } .ops-view { display: grid; gap: var(--space-5); } .ops-kpi-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } .ops-status { display: inline-flex; height: 28px; align-items: center; border: 1px solid var(--success-border); border-radius: 999px; background: var(--success-surface); color: var(--success); font-size: 12px; font-weight: 700; padding: 0 var(--space-3); } .ops-status.is-loading { border-color: var(--info-border); background: var(--info-surface); color: var(--info); } .ops-alert { border: 1px solid var(--warning-border); border-radius: var(--radius-card); background: var(--warning-surface); color: var(--warning); font-weight: 700; padding: var(--space-3) var(--space-4); } .ops-pool-actions, .ops-config-actions { display: flex; align-items: center; gap: var(--space-2); white-space: nowrap; } .ops-config-actions { justify-content: flex-end; } .ops-pool-adjustment-form { display: contents; } .ops-pool-adjustment-content { display: grid; gap: var(--space-4); padding-top: var(--space-4) !important; } .ops-pool-adjustment-metrics { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 0; } .ops-pool-adjustment-note { border: 1px solid var(--info-border); border-radius: var(--radius-control); background: var(--info-surface); color: var(--info); font-size: 13px; font-weight: 700; padding: var(--space-3); } /* ---- 幸运礼物配置弹窗 ---- */ .MuiDialog-paper.ops-config-dialog-paper { width: 94vw; max-width: 1520px; height: 92vh; max-height: 92vh; margin: var(--space-4); overflow: hidden; } .ops-config-form { display: flex; min-height: 0; height: 100%; flex-direction: column; } .ops-config-title { display: grid; flex: 0 0 auto; gap: var(--space-1); padding: var(--space-4) var(--space-6) var(--space-3); } .ops-config-title small { color: var(--text-tertiary); font-size: 12px; font-weight: 700; } .ops-config-summary { display: grid; flex: 0 0 auto; grid-template-columns: repeat(7, minmax(0, 1fr)); margin: 0; padding: 0 var(--space-6) var(--space-3); } .ops-config-dialog-content { display: flex; min-height: 0; flex: 1 1 auto; flex-direction: column; overflow: hidden !important; background: var(--bg-card); padding: 0 !important; } .ops-config-validation { display: grid; max-height: 112px; flex: 0 0 auto; gap: var(--space-2); overflow-y: auto; margin: var(--space-3) var(--space-4) 0; border: 1px solid var(--danger-border, #fecaca); border-radius: var(--radius-control); background: var(--danger-surface, #fef2f2); color: var(--danger, #dc2626); padding: var(--space-3) var(--space-4); } .ops-config-validation:focus-visible { outline: 2px solid var(--danger, #dc2626); outline-offset: 2px; } .ops-config-validation ul { display: grid; gap: 2px; margin: 0; padding-left: 20px; } .ops-config-metric { display: grid; min-width: 0; gap: 2px; border-left: 1px solid var(--border); padding: var(--space-1) var(--space-3); } .ops-config-metric:first-child { border-left: 0; padding-left: 0; } .ops-config-metric dt { overflow: hidden; color: var(--text-tertiary); font-size: 11px; font-weight: 800; text-overflow: ellipsis; white-space: nowrap; } .ops-config-metric dd { overflow: hidden; margin: 0; color: var(--text-primary); font-size: 13px; font-weight: 800; line-height: 1.25; text-overflow: ellipsis; white-space: nowrap; } .ops-config-layout { display: grid; min-height: 0; height: 100%; flex: 1 1 auto; grid-template-columns: clamp(500px, 40vw, 620px) minmax(0, 1fr); overflow: hidden; } .ops-config-params { display: grid; min-width: 0; min-height: 0; grid-template-columns: 92px minmax(0, 1fr); overflow: hidden; border-right: 1px solid var(--border); } .ops-config-section-nav { display: flex; min-width: 0; flex-direction: column; gap: var(--space-1); overflow-y: auto; border-right: 1px solid var(--border); background: var(--bg-card-strong, #f8fafc); padding: var(--space-3) var(--space-2); } .ops-config-section-nav strong { color: var(--text-tertiary); font-size: 11px; letter-spacing: 0.04em; padding: var(--space-1) var(--space-2) var(--space-2); } .ops-config-section-nav button { min-height: 34px; border: 0; border-left: 2px solid transparent; border-radius: var(--radius-control); background: transparent; color: var(--text-secondary); cursor: pointer; font: inherit; font-size: 13px; font-weight: 800; padding: 0 var(--space-2); text-align: left; transition: background var(--motion-fast) var(--ease-standard), border-color var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard); } .ops-config-section-nav button:hover { background: var(--primary-hover); } .ops-config-section-nav button.is-active { border-left-color: var(--primary); background: var(--primary-surface); color: var(--primary); } .ops-config-section-list { min-width: 0; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: var(--space-3) var(--space-4) var(--space-6); scroll-behavior: smooth; } .ops-config-section { display: grid; gap: var(--space-3); border: 0; border-bottom: 1px solid var(--border); border-radius: 0; background: var(--bg-card); padding: var(--space-3) 0 var(--space-5); } .ops-config-section + .ops-config-section { padding-top: var(--space-5); } .ops-config-section:last-child { border-bottom: 0; } .ops-config-section h3 { margin: 0; color: var(--text-primary); font-size: 15px; line-height: 1.3; } .ops-config-section__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); } .ops-config-section__head span { border-radius: var(--radius-pill); background: var(--warning-surface); color: var(--warning); font-size: 11px; font-weight: 800; padding: 3px var(--space-2); white-space: nowrap; } .ops-config-section__head span.is-ok { background: var(--success-surface); color: var(--success); } .ops-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); } .ops-form-grid__wide { grid-column: 1 / -1; } .ops-config-enabled-field { min-height: var(--control-height); justify-content: space-between; margin: 0 !important; border: 1px solid var(--border); border-radius: var(--radius-control); padding: 0 var(--space-3); } .ops-config-enabled-field .MuiFormControlLabel-label { color: var(--text-secondary); font-size: 13px; font-weight: 700; } .ops-field-note { margin: 0; color: var(--text-tertiary); font-size: 12px; line-height: 1.5; } .ops-jackpot-flow { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1px; overflow: hidden; border: 1px solid var(--border); border-radius: var(--radius-control); background: var(--border); } .ops-jackpot-flow > div { display: grid; align-content: start; gap: 4px; background: var(--bg-card-strong, #f8fafc); padding: var(--space-2) var(--space-3); } .ops-jackpot-flow strong { color: var(--text-primary); font-size: 12px; } .ops-jackpot-flow span { color: var(--text-secondary); font-size: 11px; line-height: 1.5; } .ops-field-label { display: inline-flex; min-width: 0; align-items: center; gap: 4px; border-radius: 3px; cursor: help; white-space: nowrap; } /* OutlinedInput 会在 notch 的 legend 中复制一次 label;保留其宽度计算,但隐藏复制品, * 避免同一个说明入口在键盘 Tab 顺序中出现两次。 */ .MuiOutlinedInput-notchedOutline legend .ops-field-label { visibility: hidden; } .ops-field-help-trigger { display: inline-flex; width: 16px; height: 16px; flex: 0 0 16px; align-items: center; justify-content: center; border-radius: 50%; color: var(--text-tertiary); font-size: 14px; transition: background var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard); } .ops-field-label:hover .ops-field-help-trigger, .ops-field-label:focus-visible .ops-field-help-trigger { background: var(--primary-hover); color: var(--primary); } .ops-field-label:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--primary-border, #93c5fd); } /* Tooltip 通过 portal 渲染,必须用自身 class 承载完整排版;字段内只保留问号,不牺牲表单密度。 */ .MuiTooltip-tooltip.ops-field-help-tooltip { max-width: min(420px, calc(100vw - 32px)); border: 1px solid rgb(148 163 184 / 32%); border-radius: var(--radius-control); background: #0f172a; box-shadow: 0 16px 40px rgb(15 23 42 / 28%); color: #f8fafc; padding: var(--space-3) var(--space-4); } .ops-field-help-content { display: grid; gap: var(--space-2); } .ops-field-help-content > strong { color: #ffffff; font-size: 13px; line-height: 1.4; } .ops-field-help-content dl { display: grid; gap: 7px; margin: 0; } .ops-field-help-content dl > div { display: grid; grid-template-columns: 56px minmax(0, 1fr); align-items: start; gap: var(--space-2); } .ops-field-help-content dt { color: #93c5fd; font-size: 12px; font-weight: 800; line-height: 1.55; } .ops-field-help-content dd { margin: 0; color: #e2e8f0; font-size: 12px; line-height: 1.55; } .ops-stage-designer { display: grid; min-width: 0; min-height: 0; align-content: start; overflow-y: auto; overscroll-behavior: contain; border: 0; border-radius: 0; background: var(--bg-card); } .ops-stage-tabs { position: sticky; z-index: 3; top: 0; display: grid; min-width: 0; min-height: 64px; grid-template-columns: repeat(3, minmax(0, 1fr)); border-bottom: 1px solid var(--border); background: var(--bg-card); padding: 0 var(--space-4); } .ops-stage-tab { display: grid; min-width: 0; min-height: 64px; align-content: center; gap: 3px; border: 0; border-bottom: 2px solid transparent; border-radius: 0; background: transparent; color: var(--text-secondary); cursor: pointer; padding: var(--space-2) var(--space-3); text-align: left; transition: background var(--motion-fast) var(--ease-standard), border-color var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard); } .ops-stage-tab__name { display: flex; min-width: 0; align-items: baseline; justify-content: space-between; gap: var(--space-2); } .ops-stage-tab__name strong { color: inherit; font-size: 13px; } .ops-stage-tab__name small, .ops-stage-tab__metrics { overflow: hidden; color: var(--text-tertiary); font-size: 11px; font-weight: 700; text-overflow: ellipsis; white-space: nowrap; } .ops-stage-tab.is-warn .ops-stage-tab__name small { color: var(--warning); } .ops-stage-tab:hover { background: var(--primary-hover); } .ops-stage-tab.is-active { border-bottom-color: var(--primary); color: var(--text-primary); } /* 阶段有问题(概率未闭合 / RTP 偏离)时 tab 下划线转告警色,切换前就能看到哪个阶段需要处理 */ .ops-stage-tab.is-warn { color: var(--warning); } .ops-stage-tab.is-active.is-warn { border-bottom-color: var(--warning); color: var(--warning); } .ops-stage-stack { display: grid; gap: var(--space-3); padding: 0 var(--space-4) var(--space-6); } .ops-stage-block__head { position: sticky; z-index: 2; top: 64px; display: flex; min-height: 58px; align-items: center; justify-content: space-between; gap: var(--space-3); border-bottom: 1px solid var(--border); background: var(--bg-card); padding: var(--space-2) 0; } .ops-stage-block__summary { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); } .ops-stage-block__head h3 { margin: 0; font-size: 15px; } .ops-stage-thresholds { display: grid; grid-template-columns: auto repeat(2, minmax(140px, 220px)); align-items: center; gap: var(--space-3); justify-content: end; padding: var(--space-1) 0; } .ops-stage-thresholds > span { color: var(--text-tertiary); font-size: 12px; font-weight: 800; } .ops-stage-threshold-rule { display: grid; grid-column: 2 / -1; gap: 2px; min-width: 0; border-left: 3px solid var(--primary); background: var(--bg-card-strong, #f8fafc); padding: var(--space-2) var(--space-3); } .ops-stage-threshold-rule strong { color: var(--text-primary); font-size: 13px; } .ops-stage-threshold-rule small { color: var(--text-secondary); font-size: 12px; line-height: 1.5; } .ops-tier-table { display: grid; min-width: 0; overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-card); background: var(--bg-card); } .ops-tier-head, .ops-tier-row { display: grid; box-sizing: border-box; min-width: 590px; grid-template-columns: minmax(100px, 1fr) minmax(124px, 1fr) 96px 64px 56px; align-items: center; gap: var(--space-2); } .ops-tier-head { min-height: 34px; border-bottom: 1px solid var(--row-border); background: var(--bg-card-strong, #f8fafc); color: var(--text-tertiary); font-size: 12px; font-weight: 900; padding: 0 var(--space-3); } .ops-tier-head span:nth-child(n + 3) { text-align: center; } /* 奖档表头允许自然换行,说明图标不会在窄弹窗中挤到相邻列。 */ .ops-tier-head .ops-field-label { justify-content: center; line-height: 1.2; text-align: center; white-space: normal; } .ops-tier-row { border-bottom: 1px solid var(--row-border); padding: 6px var(--space-3); } .ops-tier-row:last-child { border-bottom: 0; } .ops-tier-cell { display: flex; min-width: 0; align-items: center; } .ops-tier-cell > .MuiFormControl-root { width: 100%; } .ops-tier-cell--center { justify-content: center; } .ops-config-dialog-actions { min-height: 60px; flex: 0 0 auto; border-top: 1px solid var(--border); background: var(--bg-card); padding: var(--space-2) var(--space-6); } /* ---- 响应式 ---- */ @media (max-width: 1279px) { .ops-config-summary { grid-template-columns: repeat(4, minmax(0, 1fr)); row-gap: var(--space-2); } .ops-config-dialog-content { overflow-y: auto !important; } .ops-config-layout { height: auto; min-height: 100%; grid-template-columns: minmax(0, 1fr); overflow: visible; } .ops-config-params { min-height: auto; grid-template-columns: 112px minmax(0, 1fr); overflow: visible; border-right: 0; border-bottom: 1px solid var(--border); } .ops-config-section-nav { position: sticky; top: 0; max-height: 100%; align-self: start; } .ops-config-section-list, .ops-stage-designer { min-height: auto; overflow: visible; } .ops-stage-designer { border-top: var(--space-2) solid var(--bg-page); } } @media (max-width: 960px) { .ops-shell { grid-template-columns: 1fr; } .ops-sidebar { min-height: auto; } .ops-nav, .ops-kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @media (max-width: 767px) { .MuiDialog-paper.ops-config-dialog-paper { width: 100vw; max-width: none; height: 100dvh; max-height: 100dvh; margin: 0; border-radius: 0; } .ops-config-title { padding: var(--space-3) var(--space-4) var(--space-2); } .ops-config-summary { display: flex; gap: 0; overflow-x: auto; padding: 0 var(--space-4) var(--space-2); } .ops-config-metric { min-width: 124px; } .ops-config-params { grid-template-columns: minmax(0, 1fr); } .ops-config-section-nav { z-index: 4; display: flex; max-width: 100vw; flex-direction: row; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--border); padding: var(--space-2); } .ops-config-section-nav strong { display: none; } .ops-config-section-nav button { min-width: 72px; flex: 0 0 auto; border-left: 0; border-bottom: 2px solid transparent; text-align: center; } .ops-config-section-nav button.is-active { border-bottom-color: var(--primary); } .ops-config-section-list { padding: var(--space-2) var(--space-3) var(--space-5); } .ops-form-grid { grid-template-columns: minmax(0, 1fr); } .ops-jackpot-flow { grid-template-columns: minmax(0, 1fr); } .ops-stage-tabs { display: flex; max-width: 100vw; overflow-x: auto; padding: 0 var(--space-2); } .ops-stage-tab { min-width: 180px; flex: 1 0 180px; } .ops-stage-stack { padding: 0 var(--space-3) var(--space-5); } .ops-stage-block__head { align-items: flex-start; flex-wrap: wrap; } .ops-stage-block__summary { align-items: flex-start; flex-direction: column; gap: var(--space-1); } .ops-stage-thresholds { grid-template-columns: repeat(2, minmax(0, 1fr)); justify-content: stretch; } .ops-stage-thresholds > span { grid-column: 1 / -1; } .ops-stage-threshold-rule { grid-column: 1 / -1; } /* 小屏保留完整列头并让表格横向滚动,控件同时有阶段+行号标签,避免一列卡片失去字段关系。 */ .ops-tier-head, .ops-tier-row { min-width: 600px; } .ops-config-dialog-actions { min-height: 56px; padding: var(--space-2) var(--space-4) max(var(--space-2), env(safe-area-inset-bottom)); } } @media (max-width: 640px) { .ops-page { padding: var(--space-4); } .ops-nav, .ops-kpi-grid, .ops-pool-adjustment-metrics { grid-template-columns: 1fr; } } @media (prefers-reduced-motion: reduce) { .ops-nav button, .ops-config-section-nav button, .ops-stage-tab { transition: none; } .ops-config-section-list { scroll-behavior: auto; } }