diff --git a/config/architecture-inventory.json b/config/architecture-inventory.json index 19c9aff..70444c7 100644 --- a/config/architecture-inventory.json +++ b/config/architecture-inventory.json @@ -309,13 +309,13 @@ "code_hotspots": [ { "path": "frontend/styles/styles.css", - "bytes": 360238, - "lines": 15385 + "bytes": 359673, + "lines": 15360 }, { "path": "frontend/styles/redesign-v2.css", - "bytes": 262113, - "lines": 8533 + "bytes": 262013, + "lines": 8531 }, { "path": "frontend/index.html", @@ -344,8 +344,8 @@ }, { "path": "frontend/styles/renovation.css", - "bytes": 83812, - "lines": 1550 + "bytes": 81205, + "lines": 1480 }, { "path": "frontend/pages/heaven/page.css", diff --git a/frontend/styles/redesign-v2.css b/frontend/styles/redesign-v2.css index 5948eb6..3ece2c1 100644 --- a/frontend/styles/redesign-v2.css +++ b/frontend/styles/redesign-v2.css @@ -5933,8 +5933,6 @@ body.sidebar-collapsed .status-bar { left: 64px; } #screenerView .quant-summary-pane .quant-universe-grid, #screenerView .quant-formula-summary, #screenerView .quant-execution-actions { grid-template-columns: 1fr; } - #screenerView .quant-score-row, - #screenerView .quant-filter-row { grid-template-columns: 1fr; } #screenerTrackingView { padding: 10px; } #screenerTrackingView .tracking-page-header { grid-template-columns: 1fr auto; } #screenerTrackingView .tracking-page-header > div { grid-column: 1 / -1; grid-row: 1; } diff --git a/frontend/styles/renovation.css b/frontend/styles/renovation.css index d54fff9..cba9cda 100644 --- a/frontend/styles/renovation.css +++ b/frontend/styles/renovation.css @@ -578,7 +578,6 @@ body[data-active-view="reviewWorkspaceView"] .workspace-view { .curated-library-pane { padding: 16px; } .curated-library-heading { min-height: 38px; } .curated-library-controls { margin: 10px 0 14px; } -.curated-strategy-list { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; } .curated-strategy-card { min-height: 190px; padding: 14px; } .curated-card-foot { min-height: 38px; gap: 8px; } .curated-card-actions { margin-left: auto; display: flex; align-items: center; gap: 6px; } @@ -638,8 +637,6 @@ body[data-active-view="reviewWorkspaceView"] .workspace-view { .sentiment-cycle-analysis { gap: 14px; margin-bottom: 18px; } .sentiment-trend-panel, .sentiment-components-panel { border: 1px solid var(--border); border-radius: var(--card-radius); background: #fff; box-shadow: var(--card-shadow); overflow: hidden; } -.sentiment-detail-toolbar { margin-top: 0; } - .auction-workspace-layout { gap: 14px; align-items: start; } .auction-main-workspace { border: 1px solid var(--border); border-radius: var(--card-radius); background: #fff; box-shadow: var(--card-shadow); overflow: hidden; } .auction-evidence-rail { display: grid; gap: 12px; border: 0; background: transparent; } @@ -667,8 +664,6 @@ body[data-active-view="reviewWorkspaceView"] .workspace-view { .review-workspace .journal-section { min-height: 410px; } .review-workspace .trade-journal-section, .review-workspace .notes-history-section { grid-column: 1 / 3; } -.review-workspace .workspace-section + .workspace-section { border-top: 1px solid var(--border); } - @media (max-width: 1280px) { .overview-strip { grid-template-columns: minmax(160px, 1.15fr) repeat(5, minmax(64px, .5fr)) minmax(150px, 1fr) 82px; padding: 0 10px; } .overview-strip .sentiment-block, @@ -726,49 +721,7 @@ body[data-active-view="reviewWorkspaceView"] .workspace-view { } @media (max-width: 720px) { - body, - body.sidebar-collapsed { - display: block; - min-height: 100dvh; - padding-bottom: calc(68px + env(safe-area-inset-bottom)); - } - - .app-header { - width: 100%; - height: 108px; - min-height: 108px; - position: relative; - display: flex; - align-items: flex-start; - padding: 8px 10px 0; - } - - .brand-block { height: 42px; } .brand-mark { width: 34px; height: 34px; } - .brand-block h1 { font-size: 16px; } - .header-actions { position: absolute; inset: 56px 10px auto; display: flex; justify-content: space-between; gap: 6px; } - .header-date-group { height: 42px; min-width: 0; flex: 1; } - .header-date-group .date-input { width: 104px; flex: 1; } - .header-actions > .icon-button { width: 40px; min-width: 40px; min-height: 42px; } - - .module-nav, - body.sidebar-collapsed .module-nav { - width: 100%; - height: calc(64px + env(safe-area-inset-bottom)); - min-height: 64px; - position: fixed; - inset: auto 0 0; - z-index: 45; - display: grid; - grid-template-columns: repeat(5, minmax(0, 1fr)); - align-items: stretch; - padding: 4px 4px max(4px, env(safe-area-inset-bottom)); - overflow: hidden; - border-top: 1px solid var(--border); - border-right: 0; - background: rgba(255, 255, 255, .98); - box-shadow: 0 -5px 18px rgba(16, 24, 40, .08); - } .module-nav .nav-brand, .module-nav .nav-group-label, @@ -781,7 +734,6 @@ body[data-active-view="reviewWorkspaceView"] .workspace-view { .module-nav .module-tab.mobile-primary-tab, body.sidebar-collapsed .module-nav .module-tab.mobile-primary-tab { display: flex; } - .app-main { width: 100%; min-height: calc(100dvh - 176px); margin: 0; padding: 10px 8px 20px; } .mobile-market-selector:not([hidden]) { margin-bottom: 8px; } .overview-strip { min-height: 108px; @@ -801,10 +753,6 @@ body[data-active-view="reviewWorkspaceView"] .workspace-view { .overview-strip .sentiment-block, .overview-strip .metric { min-height: 54px; } .overview-toggle { display: none; } - .workspace-view, - body[data-active-view="screenerView"] .workspace-view, - body[data-active-view="mentorView"] .workspace-view, - body[data-active-view="reviewWorkspaceView"] .workspace-view { padding: 0 0 76px; } } @media (prefers-reduced-motion: reduce) { @@ -950,12 +898,10 @@ body[data-active-view="reviewWorkspaceView"] .workspace-view { padding: 14px 16p .sentiment-cycle-state strong { display: block; margin: 4px 0 2px; color: var(--text-primary); font-size: 14px; } .sentiment-component-list { padding: 8px 14px 11px; } .sentiment-component-row { padding: 8px 0; } -.sentiment-detail-toolbar { margin-top: 0; } .sentiment-history-frame { max-height: none; } /* Ladder and pools use the same restrained hierarchy as the reference pages. */ .main-grid { grid-template-columns: minmax(0, 1fr) 310px; gap: 12px; } -.insight-rail { gap: 12px; } .rail-heading { min-height: 42px; } .ladder-workspace { grid-template-columns: minmax(0, 1fr) 320px; } .ladder-step { grid-template-columns: 118px minmax(0, 1fr) auto; } @@ -989,7 +935,6 @@ body[data-active-view="reviewWorkspaceView"] .workspace-view { padding: 14px 16p .screener-page-bar .screener-page-heading, .screener-page-bar .screener-mode-tabs { min-height: 45px; } .screener-mode-tabs button { min-width: 108px; min-height: 45px; padding: 0 16px; } -#screenerView .screener-strategy-view { gap: 12px; } #screenerView .screener-stepper { min-height: 48px; } #screenerView .screener-overview-grid { gap: 12px; } #screenerView .screener-runbar { min-height: 54px; } @@ -1016,14 +961,11 @@ body[data-active-view="reviewWorkspaceView"] .workspace-view { padding: 14px 16p .mentor-messages { padding: 18px; } .mentor-chat-form { min-height: 58px; padding: 8px 14px; } .mentor-chat-form textarea { height: 42px; min-height: 42px; max-height: 92px; padding: 9px 11px; resize: vertical; } -.mentor-chat-form .button { min-height: 38px; } - /* Review mirrors the approved daily workflow instead of equal-width form columns. */ .review-workspace { grid-template-columns: minmax(0, 1fr) 360px; grid-template-areas: "watch journal" "trades journal" "notes notes"; gap: 12px; background: transparent; } .review-workspace .watchlist-section { grid-area: watch; min-height: 0; } .review-workspace .journal-section { grid-area: journal; min-height: 0; } .review-workspace .trade-journal-section { grid-area: trades; min-height: 0; } -.review-workspace .notes-history-section { grid-area: notes; } .review-workspace .workspace-section { border: 1px solid var(--border); border-radius: var(--card-radius); box-shadow: var(--card-shadow); } .review-workspace .workspace-section + .workspace-section { border-top: 1px solid var(--border); } .journal-form textarea { min-height: 98px; } @@ -1205,8 +1147,6 @@ body[data-active-view="reviewWorkspaceView"] .overview-strip { display: grid; } background: #fff0ee; box-shadow: inset 0 -2px 0 var(--danger); } -.sentiment-stage-guide-grid article.current strong, -.sentiment-stage-guide-grid article.current small { color: var(--danger); } .sentiment-detail-toolbar { margin-top: 0; } /* Pool pages use the prototype's compact table-first proportions. */ @@ -1230,18 +1170,8 @@ body[data-active-view="reviewWorkspaceView"] .overview-strip { display: grid; } #screenerView .strategy-tracking-panel .result-toolbar { min-height: 42px; } /* Review mirrors the reference's compact two-column daily workflow. */ -.review-workspace { - grid-template-columns: minmax(0, 1fr) 360px; - grid-template-areas: "watch journal" "trades journal" "notes notes"; - align-items: start; - gap: 12px; -} .review-workspace .workspace-section { min-height: 0 !important; } .review-workspace .workspace-heading { min-height: 42px; padding: 8px 14px; } -.review-workspace .watchlist-section { grid-area: watch; } -.review-workspace .journal-section { grid-area: journal; } -.review-workspace .trade-journal-section { grid-area: trades; } -.review-workspace .notes-history-section { grid-area: notes; } .watchlist-section .workspace-table-frame { min-height: 0; } .watchlist-section .data-table tbody td { height: 41px; } .journal-form { padding: 13px 16px 14px; } diff --git a/frontend/styles/styles.css b/frontend/styles/styles.css index 06584bd..cfeeb7d 100644 --- a/frontend/styles/styles.css +++ b/frontend/styles/styles.css @@ -178,7 +178,6 @@ .curated-execution-bar { align-items: stretch; flex-direction: column; } .curated-data-status { margin-right: 0; } .quant-builder-pane { padding: 16px 12px; } - .quant-universe-grid { grid-template-columns: 1fr 1fr; } .quant-filter-row, .quant-score-row { grid-template-columns: minmax(0, 1fr) 92px 38px; } .quant-filter-row .quant-value-input, @@ -4392,7 +4391,6 @@ dialog::backdrop { @media (max-width: 900px) { .theme-library-layout { grid-template-columns: 230px minmax(0, 1fr); } - .auction-workspace-layout { grid-template-columns: 1fr; } .auction-evidence-rail { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); border-top: 1px solid var(--line); border-left: 0; } .auction-news-entry { grid-column: 1 / -1; border-top: 1px solid var(--line); } .market-feature-summary { grid-template-columns: repeat(4, minmax(105px, 1fr)); } @@ -4411,11 +4409,9 @@ dialog::backdrop { .auction-dataset-segments { min-width: 480px; } .auction-expectation-filterbar { align-items: stretch; flex-direction: column; } .auction-evidence-rail { display: block; } - .auction-unified-table-frame { min-height: 360px; max-height: none; } .market-feature-segments { width: 100%; height: auto; overflow-x: auto; } .market-feature-segments .segment { min-height: 38px; flex: 1 0 auto; } .market-feature-table-frame { max-height: none; } - .theme-library-layout { display: block; min-height: 0; } .theme-directory-panel { border-right: 0; border-bottom: 1px solid var(--line); } .theme-directory { max-height: 280px; } .theme-detail-empty { min-height: 260px; } @@ -4490,10 +4486,6 @@ body { box-shadow: 0 1px 0 rgba(23, 26, 31, 0.02); } -.brand-block { - gap: 10px; -} - .brand-block h1 { font-size: 17px; font-weight: 720; @@ -4837,12 +4829,6 @@ body.sidebar-collapsed .sidebar-collapse-button .lucide { } @media (max-width: 720px) { - html, - body { - min-width: 320px; - width: 100%; - } - body, body.sidebar-collapsed { display: block; @@ -4999,11 +4985,6 @@ body.sidebar-collapsed .sidebar-collapse-button .lucide { white-space: nowrap; } - .module-nav .module-tab .lucide { - width: 20px; - height: 20px; - } - .module-nav .module-tab.active, .module-nav .module-tab.mobile-active { background: transparent; @@ -7703,11 +7684,6 @@ body.sidebar-collapsed .sidebar-collapse-button .lucide { grid-template-columns: minmax(0, 1fr); } - .sentiment-trend-panel { - border-right: 0; - border-bottom: 1px solid var(--border); - } - .sentiment-chart-shell { height: 230px; } @@ -13712,7 +13688,6 @@ button.account-role-badge:focus-visible { outline: 2px solid var(--blue); outlin .auction-header-summary > div { align-items: flex-start; } .auction-workspace-layout { margin: 0 8px 8px; border-radius: 8px; } .auction-dataset-bar { overflow-x: auto; padding: 0 10px; } - .auction-dataset-segments { min-width: 430px; } .auction-dataset-segments .segment { min-height: 44px; padding: 0 11px; } .auction-expectation-filterbar { align-items: stretch; flex-direction: column; padding: 8px 10px; } .auction-expectation-controls { align-items: flex-start; flex-direction: column; gap: 6px; } diff --git a/tests/e2e/app-shell.spec.js b/tests/e2e/app-shell.spec.js index 39a3489..99920fa 100644 --- a/tests/e2e/app-shell.spec.js +++ b/tests/e2e/app-shell.spec.js @@ -1834,7 +1834,7 @@ test("stylesheet layers do not repeat identical rules in the same cascade contex visitRules(sheet.cssRules, href); } return Array.from(occurrences.entries()) - .filter(([, paths]) => new Set(paths).size > 1) + .filter(([, paths]) => paths.length > 1) .map(([rule, paths]) => ({ rule, paths })); }); diff --git a/tests/preservation_helpers.py b/tests/preservation_helpers.py index 1c20683..7cd7fce 100644 --- a/tests/preservation_helpers.py +++ b/tests/preservation_helpers.py @@ -29,11 +29,11 @@ RETIRED_FRONTEND_SOURCE_RANGES = ( ) AUDITED_FRONTEND_SOURCE_LINE_COUNT = 9283 -# CR-12 and CR-13 remove only declarations repeated by a later stylesheet -# layer under the same cascade context. Entries are either an exact retired -# fragment or an exact (source, replacement) pair when surrounding context is -# needed to identify one nested occurrence. Every other byte remains part of -# the accepted CSS baseline. +# CR-12 through CR-14 remove only declarations repeated by a later rule under +# the same cascade context. Entries are either an exact retired fragment or an +# exact (source, replacement) pair. Optional trailing values declare the source +# count and how many leading occurrences to transform when an identical later +# copy must remain. Every other byte remains part of the accepted CSS baseline. AUDITED_CSS_RETIREMENTS = { "styles.css": ( ".workspace-view.active-view {\n display: block;\n}\n\n", @@ -117,6 +117,55 @@ AUDITED_CSS_RETIREMENTS = { " .overview-strip .metric:nth-of-type(1) { grid-column: 2; grid-row: 1; }\n", " .overview-strip .metric:nth-of-type(3) { grid-column: 2; grid-row: 2; }\n", " .curated-strategy-list {\n grid-template-columns: 1fr;\n }\n\n", + " .quant-universe-grid { grid-template-columns: 1fr 1fr; }\n", + ( + " .auction-workspace-layout { grid-template-columns: 1fr; }\n", + "", + 2, + 1, + ), + ( + " .auction-unified-table-frame { min-height: 360px; max-height: none; }\n", + "", + 2, + 1, + ), + " .theme-library-layout { display: block; min-height: 0; }\n", + ( + ".brand-block {\n gap: 10px;\n}\n\n", + "", + 2, + 1, + ), + ( + " html,\n" + " body {\n" + " min-width: 320px;\n" + " width: 100%;\n" + " }\n\n", + "", + 2, + 1, + ), + ( + " .module-nav .module-tab .lucide {\n" + " width: 20px;\n" + " height: 20px;\n" + " }\n\n", + "", + 2, + 1, + ), + ( + " .sentiment-trend-panel {\n" + " border-right: 0;\n" + " border-bottom: 1px solid var(--border);\n" + " }\n\n", + "", + 2, + 1, + ), + " .auction-dataset-segments { min-width: 430px; }\n", ), "renovation.css": ( ".overview-strip .sentiment-block { padding-left: 0; }\n", @@ -124,6 +173,144 @@ AUDITED_CSS_RETIREMENTS = { '.overview-strip[data-overview-expanded="true"] .metric-value ' "{ font-size: 18px; }\n\n" ), + ( + ".curated-strategy-list { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }\n", + "", + 2, + 1, + ), + ( + ".sentiment-detail-toolbar { margin-top: 0; }\n\n", + "", + 2, + 1, + ), + ( + ".sentiment-detail-toolbar { margin-top: 0; }\n", + "", + 2, + 1, + ), + ".review-workspace .workspace-section + .workspace-section { border-top: 1px solid var(--border); }\n\n", + ( + " body,\n" + " body.sidebar-collapsed {\n" + " display: block;\n" + " min-height: 100dvh;\n" + " padding-bottom: calc(68px + env(safe-area-inset-bottom));\n" + " }\n\n", + "", + 2, + 1, + ), + ( + " .app-header {\n" + " width: 100%;\n" + " height: 108px;\n" + " min-height: 108px;\n" + " position: relative;\n" + " display: flex;\n" + " align-items: flex-start;\n" + " padding: 8px 10px 0;\n" + " }\n\n", + "", + 2, + 1, + ), + (" .brand-block { height: 42px; }\n", "", 2, 1), + (" .brand-block h1 { font-size: 16px; }\n", "", 2, 1), + ( + " .header-actions { position: absolute; inset: 56px 10px auto; display: flex; justify-content: space-between; gap: 6px; }\n", + "", + 2, + 1, + ), + ( + " .header-date-group { height: 42px; min-width: 0; flex: 1; }\n", + "", + 2, + 1, + ), + ( + " .header-date-group .date-input { width: 104px; flex: 1; }\n", + "", + 2, + 1, + ), + ( + " .header-actions > .icon-button { width: 40px; min-width: 40px; min-height: 42px; }\n", + "", + 2, + 1, + ), + ( + " .module-nav,\n" + " body.sidebar-collapsed .module-nav {\n" + " width: 100%;\n" + " height: calc(64px + env(safe-area-inset-bottom));\n" + " min-height: 64px;\n" + " position: fixed;\n" + " inset: auto 0 0;\n" + " z-index: 45;\n" + " display: grid;\n" + " grid-template-columns: repeat(5, minmax(0, 1fr));\n" + " align-items: stretch;\n" + " padding: 4px 4px max(4px, env(safe-area-inset-bottom));\n" + " overflow: hidden;\n" + " border-top: 1px solid var(--border);\n" + " border-right: 0;\n" + " background: rgba(255, 255, 255, .98);\n" + " box-shadow: 0 -5px 18px rgba(16, 24, 40, .08);\n" + " }\n\n", + "", + 2, + 1, + ), + ( + " .app-main { width: 100%; min-height: calc(100dvh - 176px); margin: 0; padding: 10px 8px 20px; }\n", + "", + 2, + 1, + ), + ( + " .workspace-view,\n" + ' body[data-active-view="screenerView"] .workspace-view,\n' + ' body[data-active-view="mentorView"] .workspace-view,\n' + ' body[data-active-view="reviewWorkspaceView"] .workspace-view { padding: 0 0 76px; }\n', + "", + 2, + 1, + ), + (".insight-rail { gap: 12px; }\n", "", 2, 1), + ("#screenerView .screener-strategy-view { gap: 12px; }\n", "", 2, 1), + (".mentor-chat-form .button { min-height: 38px; }\n\n", "", 2, 1), + ( + ".review-workspace .notes-history-section { grid-area: notes; }\n", + "", + 3, + 2, + ), + ( + ".sentiment-stage-guide-grid article.current strong,\n" + ".sentiment-stage-guide-grid article.current small { color: var(--danger); }\n", + "", + 2, + 1, + ), + ( + ".review-workspace {\n" + " grid-template-columns: minmax(0, 1fr) 360px;\n" + ' grid-template-areas: "watch journal" "trades journal" "notes notes";\n' + " align-items: start;\n" + " gap: 12px;\n" + "}\n", + "", + 2, + 1, + ), + (".review-workspace .watchlist-section { grid-area: watch; }\n", "", 2, 1), + (".review-workspace .journal-section { grid-area: journal; }\n", "", 2, 1), + (".review-workspace .trade-journal-section { grid-area: trades; }\n", "", 2, 1), ), "redesign-v2.css": ( "#dragonView .dragon-operation-table .dragon-col-reason { width: auto; }\n", @@ -148,6 +335,22 @@ AUDITED_CSS_RETIREMENTS = { " .overview-strip .metric-wide { display: none; }\n" " .overview-toggle { display: none; }\n" ), + ( + ( + " #screenerView .quant-summary-pane .quant-universe-grid,\n" + " #screenerView .quant-formula-summary,\n" + " #screenerView .quant-execution-actions { grid-template-columns: 1fr; }\n" + " #screenerView .quant-score-row,\n" + " #screenerView .quant-filter-row { grid-template-columns: 1fr; }\n" + " #screenerTrackingView { padding: 10px; }\n" + ), + ( + " #screenerView .quant-summary-pane .quant-universe-grid,\n" + " #screenerView .quant-formula-summary,\n" + " #screenerView .quant-execution-actions { grid-template-columns: 1fr; }\n" + " #screenerTrackingView { padding: 10px; }\n" + ), + ), ), } @@ -351,9 +554,13 @@ def assert_moved_asset_matches( ): original = (ORIGINAL_STATIC / original_relative).read_text(encoding="utf-8") for retired in AUDITED_CSS_RETIREMENTS.get(original_relative, ()): - source, replacement = retired if isinstance(retired, tuple) else (retired, "") - testcase.assertEqual(original.count(source), 1, source) - original = original.replace(source, replacement, 1) + source, replacement, *count_override = ( + retired if isinstance(retired, tuple) else (retired, "") + ) + expected_count = count_override[0] if count_override else 1 + replacement_count = count_override[1] if len(count_override) > 1 else 1 + testcase.assertEqual(original.count(source), expected_count, source) + original = original.replace(source, replacement, replacement_count) for replacement in AUDITED_CSS_REPLACEMENTS.get(original_relative, ()): source, target, *count_override = replacement expected_count = count_override[0] if count_override else 1