From 15f7c8660dc03b02b7be33df92344b29754be028 Mon Sep 17 00:00:00 2001 From: OoO Date: Tue, 5 May 2026 22:14:47 +0800 Subject: [PATCH] fix(observability): serve CSS from Flask static path --- docs/guides/observability_ui_governance.md | 2 + scripts/check_observability_pages.py | 38 + scripts/check_observability_ui.py | 13 + web/static/css/observability-system.css | 847 +++++++++++++++++++++ 4 files changed, 900 insertions(+) create mode 100644 web/static/css/observability-system.css diff --git a/docs/guides/observability_ui_governance.md b/docs/guides/observability_ui_governance.md index f69515f..4d1ae7a 100644 --- a/docs/guides/observability_ui_governance.md +++ b/docs/guides/observability_ui_governance.md @@ -68,6 +68,7 @@ Guard 會檢查: - Topbar 是否仍載入觀測台 CSS 與健康 indicator。 - 10 個觀測頁的 `active_page`、側欄 URL、側欄 label、`momo-observability-mode` 掛載清單是否一一對齊。 - 10 個側欄 URL 是否都在 `routes/admin_observability_routes.py` 有對應 Flask route。 +- `static/css/observability-system.css` 與實際 Flask static 服務用的 `web/static/css/observability-system.css` 必須一致。 ### 2. Production 10 頁 HTTP 巡檢 @@ -84,6 +85,7 @@ python3 scripts/check_observability_pages.py - 不得出現 framework / database exception 文案。 - 每頁必須包含自己的核心標題與內容 marker。 - 每頁必須載入 `momo-observability-mode`、`observability-system.css` 與 topbar AI 觀測台 indicator。 +- `/static/css/observability-system.css` 必須能線上 200 載入,且包含核心觀測台 token/class。 - HTML 不能小到像空殼頁或錯誤 fallback。 ```bash diff --git a/scripts/check_observability_pages.py b/scripts/check_observability_pages.py index f97d3fc..50d9b93 100644 --- a/scripts/check_observability_pages.py +++ b/scripts/check_observability_pages.py @@ -49,6 +49,20 @@ GLOBAL_REQUIRED_MARKERS = [ "momo-obs-link", ] +ASSET_CHECKS = [ + ( + "/static/css/observability-system.css", + "觀測台 CSS", + [ + "--obs-title-size", + "--obs-value-size", + ".momo-observability-mode", + ".obs-chart-frame", + ".obs-modal-preview", + ], + ), +] + ERROR_NEEDLES = [ "Traceback", "UndefinedError", @@ -118,6 +132,30 @@ def main() -> int: else: print(f"- {label}: HTTP {status}, issues=none") + for path, label, markers in ASSET_CHECKS: + try: + status, body = fetch_page(args.base_url, path, args.timeout) + except urllib.error.HTTPError as exc: + print(f"- {label}: HTTP {exc.code}, FAIL") + failed = True + continue + except Exception as exc: + print(f"- {label}: {type(exc).__name__}: {exc}, FAIL") + failed = True + continue + + missing_markers = [marker for marker in markers if marker not in body] + if status != 200 or missing_markers: + issues = [] + if status != 200: + issues.append("bad_status") + if missing_markers: + issues.append(f"missing_asset_markers={missing_markers}") + print(f"- {label}: HTTP {status}, issues={issues}, FAIL") + failed = True + else: + print(f"- {label}: HTTP {status}, markers=ok") + if failed: print("Observability page smoke: FAIL") return 1 diff --git a/scripts/check_observability_ui.py b/scripts/check_observability_ui.py index 55fdf30..05e94f7 100644 --- a/scripts/check_observability_ui.py +++ b/scripts/check_observability_ui.py @@ -44,6 +44,7 @@ OBSERVABILITY_NAV_ITEMS = [ ] CSS_PATH = Path("static/css/observability-system.css") +WEB_CSS_PATH = Path("web/static/css/observability-system.css") SHELL_PATH = Path("templates/components/_ewoooc_shell.html") BASE_PATH = Path("templates/ewoooc_base.html") ROUTE_PATH = Path("routes/admin_observability_routes.py") @@ -192,6 +193,18 @@ def scan_css() -> list[str]: if snippet not in text: findings.append(f"{CSS_PATH}: missing required token/class `{snippet}`") + web_path = ROOT / WEB_CSS_PATH + if not web_path.exists(): + findings.append( + f"{WEB_CSS_PATH}: missing mirrored CSS served by Flask static route" + ) + else: + web_text = web_path.read_text(encoding="utf-8") + if web_text != text: + findings.append( + f"{WEB_CSS_PATH}: must match {CSS_PATH} so production /static CSS is in sync" + ) + return findings diff --git a/web/static/css/observability-system.css b/web/static/css/observability-system.css new file mode 100644 index 0000000..140b5b0 --- /dev/null +++ b/web/static/css/observability-system.css @@ -0,0 +1,847 @@ +/* + * AI 觀測台共用視覺系統 + * 只在 ewoooc_base.html 的 .momo-observability-mode 啟用,避免污染一般後台頁。 + * + * Governance: + * - 新增觀測頁時,優先使用本檔 token / utility class,不要在 template 內重建一套 hero/table/card。 + * - 標題與 KPI 數字使用 --obs-title-size / --obs-value-size,不要再硬寫超大 clamp。 + * - 圖表容器使用 .obs-chart-frame 系列;只有資料百分比 width 可保留 inline style。 + * - 視覺語言固定為暖色焦糖系、Noto Sans TC、點陣方格;禁止回到紫色、純黑、Times/Georgia。 + */ +.momo-observability-mode { + --obs-ink: var(--momo-ink, #302720); + --obs-muted: var(--momo-muted, #8b8077); + --obs-paper: var(--momo-paper, #fff8ef); + --obs-accent: var(--momo-accent, #c96442); + --obs-accent-soft: rgba(201, 100, 66, 0.12); + --obs-line: rgba(86, 64, 48, 0.14); + --obs-card: rgba(255, 252, 246, 0.92); + --obs-green: #4f8a5b; + --obs-amber: #b8792f; + --obs-red: #b94b45; + --obs-blue: #4f6f8f; + --obs-radius-lg: 24px; + --obs-radius-md: 18px; + --obs-shadow: 0 18px 44px rgba(70, 46, 28, 0.09); + --obs-dot: + radial-gradient(circle, rgba(201, 100, 66, 0.18) 1px, transparent 1.3px); + --obs-title-size: clamp(1.9rem, 3.2vw, 2.75rem); + --obs-value-size: clamp(1.45rem, 2.8vw, 2.25rem); +} + +.momo-observability-mode .momo-content { + background: + var(--obs-dot), + radial-gradient(circle at 8% 4%, rgba(201, 100, 66, 0.12), transparent 24rem), + radial-gradient(circle at 100% 20%, rgba(79, 111, 143, 0.11), transparent 26rem), + linear-gradient(180deg, rgba(255, 248, 239, 0.65), rgba(255, 253, 248, 0.96)); + background-size: 18px 18px, auto, auto, auto; + color: var(--obs-ink); + font-family: 'Noto Sans TC', 'Inter', sans-serif; +} + +.momo-observability-mode .momo-content::before { + content: ""; + position: fixed; + inset: 64px 0 auto 260px; + height: 180px; + pointer-events: none; + background: linear-gradient(180deg, rgba(255, 248, 239, 0.92), rgba(255, 248, 239, 0)); + z-index: 0; +} + +.momo-observability-mode .container-fluid, +.momo-observability-mode .obs-warroom, +.momo-observability-mode .agent-page, +.momo-observability-mode .biz-warroom, +.momo-observability-mode .runtime-page, +.momo-observability-mode .calls-page, +.momo-observability-mode .gov-page, +.momo-observability-mode .gate-page, +.momo-observability-mode .rag-page, +.momo-observability-mode .quality-page, +.momo-observability-mode .ppt-page { + position: relative; + z-index: 1; +} + +.momo-observability-mode .container-fluid > h2:first-child { + position: relative; + margin-bottom: 1.1rem !important; + padding: 1.2rem 1.25rem; + border: 1px solid var(--obs-line); + border-radius: 24px; + background: + radial-gradient(circle at 16% 10%, rgba(201, 100, 66, 0.16), transparent 20rem), + linear-gradient(135deg, rgba(255, 248, 239, 0.96), rgba(255, 255, 255, 0.76)); + box-shadow: 0 18px 42px rgba(70, 46, 28, 0.08); + color: var(--obs-ink); + font-family: 'Noto Sans TC', 'Inter', sans-serif; + font-size: var(--obs-title-size); + letter-spacing: -0.045em; +} + +.momo-observability-mode .container-fluid > h2:first-child small { + display: block; + margin-top: 0.3rem; + color: var(--obs-muted) !important; + font-family: 'Noto Sans TC', sans-serif; + font-size: 0.88rem; + font-weight: 500; + letter-spacing: 0; +} + +.momo-observability-mode .card { + border: 1px solid var(--obs-line); + border-radius: 22px; + background: var(--obs-card); + box-shadow: 0 14px 34px rgba(70, 46, 28, 0.07); + overflow: hidden; +} + +.momo-observability-mode .card-header { + border-bottom: 1px solid var(--obs-line); + background: linear-gradient(90deg, rgba(255, 248, 239, 0.92), rgba(255, 255, 255, 0.72)) !important; + color: var(--obs-ink); + font-weight: 800; +} + +.momo-observability-mode .card-body { + color: var(--obs-ink); +} + +.momo-observability-mode .card-footer { + border-top: 1px solid var(--obs-line); + background: rgba(255, 248, 239, 0.56); +} + +.momo-observability-mode .text-muted { + color: var(--obs-muted) !important; +} + +.momo-observability-mode h3, +.momo-observability-mode h4, +.momo-observability-mode h5 { + letter-spacing: -0.035em; +} + +.momo-observability-mode h1, +.momo-observability-mode h2, +.momo-observability-mode h3, +.momo-observability-mode h4, +.momo-observability-mode h5, +.momo-observability-mode h6 { + color: var(--obs-ink); + font-family: 'Noto Sans TC', 'Inter', sans-serif !important; + font-weight: 850; +} + +.momo-observability-mode .obs-title, +.momo-observability-mode .agent-title, +.momo-observability-mode .biz-command h1, +.momo-observability-mode .runtime-title, +.momo-observability-mode .calls-title, +.momo-observability-mode .gov-title, +.momo-observability-mode .gate-title, +.momo-observability-mode .rag-title, +.momo-observability-mode .quality-title, +.momo-observability-mode .ppt-title { + max-width: 780px; + font-family: 'Noto Sans TC', 'Inter', sans-serif !important; + font-size: clamp(1.9rem, 3.2vw, 2.75rem) !important; + line-height: 1.12 !important; + letter-spacing: -0.045em !important; + font-weight: 860 !important; +} + +.momo-observability-mode .obs-hero, +.momo-observability-mode .agent-hero, +.momo-observability-mode .biz-command, +.momo-observability-mode .runtime-hero, +.momo-observability-mode .calls-hero, +.momo-observability-mode .gov-hero, +.momo-observability-mode .gate-hero, +.momo-observability-mode .rag-hero, +.momo-observability-mode .quality-hero, +.momo-observability-mode .ppt-hero { + position: relative; + overflow: hidden; + border: 1px solid rgba(201, 100, 66, 0.16) !important; + border-radius: 28px !important; + box-shadow: var(--obs-shadow) !important; + padding-top: clamp(1.05rem, 2vw, 1.65rem) !important; + padding-bottom: clamp(1.05rem, 2vw, 1.65rem) !important; +} + +.momo-observability-mode .obs-hero::after, +.momo-observability-mode .agent-hero::after, +.momo-observability-mode .biz-command::after, +.momo-observability-mode .runtime-hero::after, +.momo-observability-mode .calls-hero::after, +.momo-observability-mode .gov-hero::after, +.momo-observability-mode .gate-hero::after, +.momo-observability-mode .rag-hero::after, +.momo-observability-mode .quality-hero::after, +.momo-observability-mode .ppt-hero::after, +.momo-observability-mode .obs-panel::after, +.momo-observability-mode .agent-panel::after, +.momo-observability-mode .biz-panel::after, +.momo-observability-mode .runtime-panel::after, +.momo-observability-mode .calls-panel::after, +.momo-observability-mode .gov-panel::after, +.momo-observability-mode .gate-panel::after, +.momo-observability-mode .rag-panel::after, +.momo-observability-mode .quality-panel::after, +.momo-observability-mode .ppt-panel::after { + content: ""; + position: absolute; + inset: auto 0 0 auto; + width: 220px; + height: 120px; + pointer-events: none; + opacity: 0.46; + background-image: var(--obs-dot); + background-size: 12px 12px; + mask-image: linear-gradient(135deg, transparent, #000); +} + +.momo-observability-mode .obs-kicker, +.momo-observability-mode .agent-kicker, +.momo-observability-mode .biz-kicker, +.momo-observability-mode .runtime-kicker, +.momo-observability-mode .calls-kicker, +.momo-observability-mode .gov-kicker, +.momo-observability-mode .gate-kicker, +.momo-observability-mode .rag-kicker, +.momo-observability-mode .quality-kicker, +.momo-observability-mode .ppt-kicker, +.momo-observability-mode [class$="-label"] { + color: color-mix(in srgb, var(--obs-accent) 74%, var(--obs-muted)) !important; + font-size: 0.74rem !important; + font-weight: 850 !important; + letter-spacing: 0.11em !important; + text-transform: uppercase; +} + +.momo-observability-mode .obs-subtitle, +.momo-observability-mode .agent-subtitle, +.momo-observability-mode .biz-command p, +.momo-observability-mode .runtime-subtitle, +.momo-observability-mode .calls-subtitle, +.momo-observability-mode .gov-subtitle, +.momo-observability-mode .gate-subtitle, +.momo-observability-mode .rag-subtitle, +.momo-observability-mode .quality-subtitle, +.momo-observability-mode .ppt-subtitle { + color: color-mix(in srgb, var(--obs-ink) 62%, var(--obs-muted)) !important; + font-size: 0.94rem !important; + line-height: 1.68 !important; + letter-spacing: 0 !important; +} + +.momo-observability-mode .obs-signal, +.momo-observability-mode .agent-signal, +.momo-observability-mode .biz-signal, +.momo-observability-mode .runtime-signal, +.momo-observability-mode .calls-signal, +.momo-observability-mode .gov-signal, +.momo-observability-mode .gate-signal, +.momo-observability-mode .rag-signal, +.momo-observability-mode .quality-signal, +.momo-observability-mode .ppt-signal, +.momo-observability-mode .obs-panel, +.momo-observability-mode .agent-panel, +.momo-observability-mode .biz-panel, +.momo-observability-mode .runtime-panel, +.momo-observability-mode .calls-panel, +.momo-observability-mode .gov-panel, +.momo-observability-mode .gate-panel, +.momo-observability-mode .rag-panel, +.momo-observability-mode .quality-panel, +.momo-observability-mode .ppt-panel, +.momo-observability-mode .obs-table-shell, +.momo-observability-mode [class$="-table-shell"] { + position: relative; + border: 1px solid var(--obs-line) !important; + border-radius: var(--obs-radius-lg) !important; + background: + linear-gradient(180deg, rgba(255, 252, 247, 0.96), rgba(255, 248, 241, 0.9)), + var(--obs-dot) !important; + background-size: auto, 14px 14px !important; + box-shadow: var(--obs-shadow) !important; +} + +.momo-observability-mode .obs-signal-value, +.momo-observability-mode .agent-value, +.momo-observability-mode .biz-signal .value, +.momo-observability-mode .runtime-value, +.momo-observability-mode .calls-value, +.momo-observability-mode .gov-value, +.momo-observability-mode .gate-value, +.momo-observability-mode .rag-value, +.momo-observability-mode .quality-value, +.momo-observability-mode .ppt-value { + font-size: clamp(1.55rem, 3vw, 2.25rem) !important; + line-height: 1.05 !important; + letter-spacing: -0.055em !important; + font-weight: 900 !important; +} + +.momo-observability-mode .obs-panel-title, +.momo-observability-mode .agent-panel-title, +.momo-observability-mode .biz-panel-head h3, +.momo-observability-mode .runtime-panel-title, +.momo-observability-mode .calls-panel-title, +.momo-observability-mode .gov-panel-title, +.momo-observability-mode .gate-panel-title, +.momo-observability-mode .rag-panel-title, +.momo-observability-mode .quality-panel-title, +.momo-observability-mode .ppt-panel-title, +.momo-observability-mode [class$="-table-title"] h3 { + font-size: clamp(1.05rem, 2vw, 1.45rem) !important; + line-height: 1.25 !important; + letter-spacing: -0.035em !important; +} + +.momo-observability-mode code, +.momo-observability-mode .momo-mono, +.momo-observability-mode table td, +.momo-observability-mode table th { + font-variant-numeric: tabular-nums; +} + +.momo-observability-mode .table { + --bs-table-bg: transparent; + --bs-table-striped-bg: rgba(255, 248, 239, 0.46); + color: var(--obs-ink); + margin-bottom: 0; + font-size: 0.9rem; +} + +.momo-observability-mode .table thead, +.momo-observability-mode .table-light { + --bs-table-bg: rgba(255, 248, 239, 0.9); + color: var(--obs-muted); + font-size: 0.74rem; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.momo-observability-mode .table td, +.momo-observability-mode .table th { + border-color: rgba(86, 64, 48, 0.1); + vertical-align: middle; + padding: 0.78rem 0.82rem; +} + +.momo-observability-mode .table-responsive { + border-radius: 18px; + overflow-x: auto; +} + +.momo-observability-mode table code, +.momo-observability-mode .biz-table code { + color: #7c402e; + background: rgba(201, 100, 66, 0.08); + border-radius: 0.45rem; + padding: 0.12rem 0.36rem; +} + +.momo-observability-mode .biz-panel-body.table-responsive { + max-width: 100%; + overflow-x: auto; +} + +.momo-observability-mode .biz-table { + min-width: 760px; + max-width: 100%; +} + +.momo-observability-mode .biz-table td, +.momo-observability-mode .biz-table th { + overflow-wrap: anywhere; +} + +.momo-observability-mode .biz-table td:nth-child(3), +.momo-observability-mode .biz-table td:last-child { + max-width: 220px; +} + +.momo-observability-mode .btn { + border-radius: 999px; + font-weight: 760; + letter-spacing: -0.01em; + min-height: 2.25rem; + padding-inline: 0.9rem; + box-shadow: none; + transition: transform 160ms ease, box-shadow 160ms ease, background-color 160ms ease; +} + +.momo-observability-mode .btn-primary, +.momo-observability-mode .btn-warning, +.momo-observability-mode .btn-success { + border-color: var(--obs-accent) !important; + background: var(--obs-accent) !important; + color: #fff8ef !important; +} + +.momo-observability-mode .btn-outline-primary, +.momo-observability-mode .btn-outline-secondary, +.momo-observability-mode .btn-outline-info, +.momo-observability-mode .btn-outline-warning, +.momo-observability-mode .btn-outline-danger, +.momo-observability-mode .btn-outline-success { + border-color: rgba(201, 100, 66, 0.34) !important; + color: var(--obs-accent) !important; + background: rgba(255, 255, 255, 0.5); +} + +.momo-observability-mode .btn:hover { + transform: translateY(-1px); + box-shadow: 0 10px 22px rgba(201, 100, 66, 0.14); +} + +.momo-observability-mode .badge.bg-secondary, +.momo-observability-mode .badge.bg-primary, +.momo-observability-mode .badge.bg-info { + background: rgba(79, 111, 143, 0.14) !important; + color: var(--obs-blue) !important; +} + +.momo-observability-mode .badge.bg-warning { + background: rgba(184, 121, 47, 0.14) !important; + color: var(--obs-amber) !important; +} + +.momo-observability-mode .badge.bg-danger { + background: rgba(185, 75, 69, 0.14) !important; + color: var(--obs-red) !important; +} + +.momo-observability-mode .badge.bg-success { + background: rgba(79, 138, 91, 0.14) !important; + color: var(--obs-green) !important; +} + +.momo-observability-mode .alert { + border-radius: 18px; + border-color: rgba(184, 121, 47, 0.24); + background: rgba(184, 121, 47, 0.08); + color: var(--obs-amber); +} + +.momo-observability-mode .obs-empty, +.momo-observability-mode .agent-empty, +.momo-observability-mode .biz-empty, +.momo-observability-mode .runtime-empty, +.momo-observability-mode .calls-empty, +.momo-observability-mode .gov-empty, +.momo-observability-mode .gate-empty, +.momo-observability-mode .rag-empty, +.momo-observability-mode .quality-empty, +.momo-observability-mode .ppt-empty, +.momo-observability-mode .text-center.text-muted { + border: 1px dashed rgba(201, 100, 66, 0.24); + border-radius: 16px; + background: + linear-gradient(135deg, rgba(255, 248, 239, 0.74), rgba(255, 252, 247, 0.82)), + var(--obs-dot); + background-size: auto, 14px 14px; +} + +.momo-observability-mode canvas { + max-width: 100%; +} + +/* Data surface polish: tables, matrices, lists */ +.momo-observability-mode .obs-table-shell, +.momo-observability-mode [class$="-table-shell"], +.momo-observability-mode .table-responsive { + background: + linear-gradient(180deg, rgba(255, 252, 247, 0.96), rgba(255, 248, 241, 0.9)), + var(--obs-dot); + background-size: auto, 14px 14px; +} + +.momo-observability-mode .table { + border-collapse: separate; + border-spacing: 0; +} + +.momo-observability-mode .table thead th { + position: relative; + background: rgba(255, 243, 232, 0.92) !important; + color: #7a5b4d !important; + border-bottom: 1px solid rgba(201, 100, 66, 0.18) !important; + font-size: 0.72rem; + font-weight: 850; + white-space: nowrap; +} + +.momo-observability-mode .table tbody tr { + transition: background-color 140ms ease, transform 140ms ease; +} + +.momo-observability-mode .table tbody tr:hover { + background: rgba(201, 100, 66, 0.045); +} + +.momo-observability-mode .table tbody td { + color: color-mix(in srgb, var(--obs-ink) 88%, var(--obs-muted)); +} + +.momo-observability-mode .table td small, +.momo-observability-mode .table td .text-muted { + line-height: 1.45; +} + +.momo-observability-mode .table td:last-child { + max-width: 360px; +} + +.momo-observability-mode .table td:last-child small, +.momo-observability-mode .table td:last-child .text-muted { + display: inline-block; + max-width: 100%; + overflow-wrap: anywhere; +} + +.momo-observability-mode .agent-table-shell .table td, +.momo-observability-mode .agent-table-shell .table th { + text-align: center; +} + +.momo-observability-mode .agent-table-shell .table td:first-child, +.momo-observability-mode .agent-table-shell .table th:first-child { + text-align: left; + min-width: 190px; +} + +.momo-observability-mode .agent-card, +.momo-observability-mode .rec-card, +.momo-observability-mode .fix-card, +.momo-observability-mode .root-card, +.momo-observability-mode .episode-card, +.momo-observability-mode .biz-decision-card, +.momo-observability-mode .obs-route-card { + box-shadow: 0 10px 24px rgba(70, 46, 28, 0.055); +} + +.momo-observability-mode .agent-card:hover, +.momo-observability-mode .rec-card:hover, +.momo-observability-mode .fix-card:hover, +.momo-observability-mode .root-card:hover, +.momo-observability-mode .episode-card:hover, +.momo-observability-mode .biz-decision-card:hover, +.momo-observability-mode .obs-route-card:hover { + transform: translateY(-1px); + box-shadow: 0 16px 32px rgba(70, 46, 28, 0.09); +} + +.momo-observability-mode .progress, +.momo-observability-mode .agent-meter { + background: rgba(86, 64, 48, 0.09) !important; + box-shadow: inset 0 1px 2px rgba(70, 46, 28, 0.08); +} + +.momo-observability-mode .progress-bar { + background: linear-gradient(90deg, var(--obs-accent), #e3a65b) !important; +} + +.momo-observability-mode .form-control, +.momo-observability-mode .form-select { + border-color: rgba(201, 100, 66, 0.18); + border-radius: 14px; + background-color: rgba(255, 252, 247, 0.88); + color: var(--obs-ink); +} + +.momo-observability-mode .form-control:focus, +.momo-observability-mode .form-select:focus { + border-color: rgba(201, 100, 66, 0.52); + box-shadow: 0 0 0 0.2rem rgba(201, 100, 66, 0.12); +} + +.momo-observability-mode .badge { + border-radius: 999px; + font-weight: 850; + letter-spacing: -0.01em; + padding: 0.36em 0.62em; +} + +.momo-observability-mode .obs-chart-frame { + height: 250px; + min-height: 220px; +} + +.momo-observability-mode .obs-chart-frame-tall { + height: 260px; +} + +.momo-observability-mode .obs-chart-frame-slim { + height: 86px; + min-height: 72px; +} + +.momo-observability-mode .obs-progress-xs { + height: 6px; +} + +.momo-observability-mode .obs-progress-sm { + height: 8px; +} + +.momo-observability-mode .obs-modal-preview { + border: 1px solid rgba(201, 100, 66, 0.14); + border-radius: 14px; + background: + linear-gradient(135deg, rgba(255, 252, 247, 0.94), rgba(255, 248, 241, 0.84)), + var(--obs-dot); + background-size: auto, 13px 13px; +} + +.momo-observability-mode .quality-distribution-cell { + width: 200px; +} + +.momo-observability-mode .budget-input { + width: 110px; + max-width: 100%; +} + +.momo-observability-mode .alert-input { + width: 80px; + max-width: 100%; +} + +/* Cross-page layout hardening */ +.momo-observability-mode .momo-content { + overflow-x: hidden; +} + +.momo-observability-mode .obs-warroom, +.momo-observability-mode .agent-page, +.momo-observability-mode .biz-warroom, +.momo-observability-mode .runtime-page, +.momo-observability-mode .calls-page, +.momo-observability-mode .gov-page, +.momo-observability-mode .gate-page, +.momo-observability-mode .rag-page, +.momo-observability-mode .quality-page, +.momo-observability-mode .ppt-page, +.momo-observability-mode .container-fluid { + max-width: 1480px; + margin-inline: auto; +} + +.momo-observability-mode .obs-grid, +.momo-observability-mode .agent-grid, +.momo-observability-mode .biz-layout, +.momo-observability-mode .runtime-grid, +.momo-observability-mode .calls-grid, +.momo-observability-mode .gov-grid, +.momo-observability-mode .gate-grid, +.momo-observability-mode .rag-grid, +.momo-observability-mode .quality-grid, +.momo-observability-mode .ppt-grid { + gap: 1rem !important; +} + +.momo-observability-mode .obs-command-strip, +.momo-observability-mode .agent-command, +.momo-observability-mode .biz-signal-grid, +.momo-observability-mode .runtime-command, +.momo-observability-mode .calls-command, +.momo-observability-mode .gov-command, +.momo-observability-mode .gate-command, +.momo-observability-mode .rag-command, +.momo-observability-mode .quality-command, +.momo-observability-mode .ppt-command { + align-items: stretch; +} + +.momo-observability-mode .obs-signal, +.momo-observability-mode .agent-signal, +.momo-observability-mode .biz-signal, +.momo-observability-mode .runtime-signal, +.momo-observability-mode .calls-signal, +.momo-observability-mode .gov-signal, +.momo-observability-mode .gate-signal, +.momo-observability-mode .rag-signal, +.momo-observability-mode .quality-signal, +.momo-observability-mode .ppt-signal { + min-width: 0; +} + +.momo-observability-mode .obs-panel-body, +.momo-observability-mode .agent-panel-body, +.momo-observability-mode .biz-panel-body, +.momo-observability-mode .runtime-panel-body, +.momo-observability-mode .calls-panel-body, +.momo-observability-mode .gov-panel-body, +.momo-observability-mode .gate-panel-body, +.momo-observability-mode .rag-panel-body, +.momo-observability-mode .quality-panel-body, +.momo-observability-mode .ppt-panel-body { + min-width: 0; +} + +.momo-observability-mode [class$="-panel-head"], +.momo-observability-mode [class$="-table-title"] { + min-width: 0; +} + +.momo-observability-mode [class$="-panel-head"] > div, +.momo-observability-mode [class$="-table-title"] > div { + min-width: 0; +} + +.momo-observability-mode [class$="-panel-head"] p, +.momo-observability-mode [class$="-table-title"] p, +.momo-observability-mode .text-muted { + overflow-wrap: anywhere; +} + +.momo-observability-mode .obs-route-card, +.momo-observability-mode .agent-card, +.momo-observability-mode .biz-decision-card, +.momo-observability-mode .rec-card, +.momo-observability-mode .fix-card, +.momo-observability-mode .root-card { + min-width: 0; + transition: transform 160ms ease, box-shadow 160ms ease, border-color 160ms ease; +} + +.momo-observability-mode .obs-route-card:focus-visible, +.momo-observability-mode .btn:focus-visible, +.momo-observability-mode .form-control:focus-visible, +.momo-observability-mode .form-select:focus-visible { + outline: 3px solid rgba(201, 100, 66, 0.28); + outline-offset: 2px; +} + +.momo-observability-mode .alert { + overflow-wrap: anywhere; +} + +.momo-observability-mode .modal-content { + border: 1px solid var(--obs-line); + border-radius: 24px; + background: var(--obs-paper); + box-shadow: 0 24px 70px rgba(70, 46, 28, 0.18); +} + +.momo-observability-mode .modal-header, +.momo-observability-mode .modal-footer { + border-color: var(--obs-line); +} + +@media (max-width: 1180px) { + .momo-observability-mode .obs-grid, + .momo-observability-mode .agent-grid, + .momo-observability-mode .biz-layout, + .momo-observability-mode .runtime-grid, + .momo-observability-mode .calls-grid, + .momo-observability-mode .gov-grid, + .momo-observability-mode .gate-grid, + .momo-observability-mode .rag-grid, + .momo-observability-mode .quality-grid, + .momo-observability-mode .ppt-grid { + grid-template-columns: 1fr !important; + } + + .momo-observability-mode .obs-command-strip, + .momo-observability-mode .agent-command, + .momo-observability-mode .biz-signal-grid, + .momo-observability-mode .runtime-command, + .momo-observability-mode .calls-command, + .momo-observability-mode .gov-command, + .momo-observability-mode .gate-command, + .momo-observability-mode .rag-command, + .momo-observability-mode .quality-command, + .momo-observability-mode .ppt-command { + grid-template-columns: repeat(2, minmax(0, 1fr)) !important; + } +} + +@media (max-width: 768px) { + .momo-observability-mode .container-fluid { + padding-left: 0.7rem; + padding-right: 0.7rem; + } + + .momo-observability-mode .momo-content { + padding-left: 0.85rem; + padding-right: 0.85rem; + } + + .momo-observability-mode .table-responsive, + .momo-observability-mode .card-body.p-0 { + overflow-x: auto; + } + + .momo-observability-mode .obs-title, + .momo-observability-mode .agent-title, + .momo-observability-mode .biz-command h1, + .momo-observability-mode .runtime-title, + .momo-observability-mode .calls-title, + .momo-observability-mode .gov-title, + .momo-observability-mode .gate-title, + .momo-observability-mode .rag-title, + .momo-observability-mode .quality-title, + .momo-observability-mode .ppt-title { + font-size: clamp(1.8rem, 10vw, 2.45rem) !important; + } + + .momo-observability-mode .obs-command-strip, + .momo-observability-mode .agent-command, + .momo-observability-mode .biz-signal-grid, + .momo-observability-mode .runtime-command, + .momo-observability-mode .calls-command, + .momo-observability-mode .gov-command, + .momo-observability-mode .gate-command, + .momo-observability-mode .rag-command, + .momo-observability-mode .quality-command, + .momo-observability-mode .ppt-command { + grid-template-columns: 1fr !important; + } + + .momo-observability-mode .obs-hero, + .momo-observability-mode .agent-hero, + .momo-observability-mode .biz-command, + .momo-observability-mode .runtime-hero, + .momo-observability-mode .calls-hero, + .momo-observability-mode .gov-hero, + .momo-observability-mode .gate-hero, + .momo-observability-mode .rag-hero, + .momo-observability-mode .quality-hero, + .momo-observability-mode .ppt-hero { + border-radius: 22px !important; + } + + .momo-observability-mode .obs-panel, + .momo-observability-mode .agent-panel, + .momo-observability-mode .biz-panel, + .momo-observability-mode .runtime-panel, + .momo-observability-mode .calls-panel, + .momo-observability-mode .gov-panel, + .momo-observability-mode .gate-panel, + .momo-observability-mode .rag-panel, + .momo-observability-mode .quality-panel, + .momo-observability-mode .ppt-panel, + .momo-observability-mode [class$="-table-shell"] { + border-radius: 20px !important; + } + + .momo-observability-mode .table { + font-size: 0.84rem; + } + + .momo-observability-mode .btn { + min-height: 2.45rem; + } + + .momo-observability-mode .momo-content::before { + left: 0; + } +}