feat: complete M3 Web UI Enhancement milestone with include/exclude cards, fuzzy matching, mobile responsive design, and performance optimization

- Include/exclude cards feature complete with 300+ card knowledge base and intelligent fuzzy matching
- Enhanced visual validation with warning icons and performance benchmarks (100% pass rate)
- Mobile responsive design with bottom-floating controls, two-column layout, and horizontal scroll prevention
- Dark theme confirmation modal for fuzzy matches with card preview and alternatives
- Dual architecture support for web UI staging system and CLI direct build paths
- All M3 checklist items completed: fuzzy match modal, enhanced algorithm, summary panel, mobile responsive, Playwright tests
This commit is contained in:
matt 2025-09-09 18:15:30 -07:00
parent 0516260304
commit cfcc01db85
37 changed files with 3837 additions and 162 deletions

View file

@ -65,7 +65,7 @@
--blue-main: #1565c0; /* balanced blue */
}
*{box-sizing:border-box}
html,body{height:100%}
html,body{height:100%; overflow-x:hidden; max-width:100vw;}
body {
font-family: system-ui, Arial, sans-serif;
margin: 0;
@ -74,6 +74,7 @@ body {
display: flex;
flex-direction: column;
min-height: 100vh;
width: 100%;
}
/* Honor HTML hidden attribute across the app */
[hidden] { display: none !important; }
@ -84,7 +85,7 @@ body {
.top-banner{ min-height: var(--banner-h); }
.top-banner .top-inner{ margin:0; padding:.5rem 0; display:grid; grid-template-columns: var(--sidebar-w) 1fr; align-items:center; }
.top-banner h1{ font-size: 1.1rem; margin:0; padding-left: 1rem; }
.banner-status{ color: var(--muted); font-size:.9rem; text-align:left; padding-left: 1.5rem; padding-right: 1.5rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%; }
.banner-status{ color: var(--muted); font-size:.9rem; text-align:left; padding-left: 1.5rem; padding-right: 1.5rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:100%; min-height:1.2em; }
.banner-status.busy{ color:#fbbf24; }
.health-dot{ width:10px; height:10px; border-radius:50%; display:inline-block; background:#10b981; box-shadow:0 0 0 2px rgba(16,185,129,.25) inset; }
.health-dot[data-state="bad"]{ background:#ef4444; box-shadow:0 0 0 2px rgba(239,68,68,.3) inset; }
@ -125,7 +126,14 @@ body.nav-collapsed .top-banner .top-inner{ padding-left: .5rem; padding-right: .
.sidebar{ transform: translateX(-100%); visibility: hidden; }
body:not(.nav-collapsed) .layout{ grid-template-columns: var(--sidebar-w) 1fr; }
body:not(.nav-collapsed) .sidebar{ transform: translateX(0); visibility: visible; }
.content{ padding: .9rem .8rem; }
.content{ padding: .9rem .6rem; max-width: 100vw; box-sizing: border-box; overflow-x: hidden; }
}
/* Additional mobile spacing for bottom floating controls */
@media (max-width: 720px) {
.content {
padding-bottom: 6rem !important; /* Extra bottom padding to account for floating controls */
}
}
.brand h1{ display:none; }
@ -290,10 +298,36 @@ small, .muted{ color: var(--muted); }
.stage-nav .name { font-size:12px; }
/* Build controls sticky box tweaks */
.build-controls { top: calc(var(--banner-offset, 48px) + 6px); }
@media (max-width: 720px){
.build-controls {
position: sticky;
top: calc(var(--banner-offset, 48px) + 6px);
z-index: 100;
background: linear-gradient(180deg, rgba(15,17,21,.98), rgba(15,17,21,.92));
backdrop-filter: blur(8px);
border: 1px solid var(--border);
border-radius: 10px;
margin: 0.5rem 0;
box-shadow: 0 4px 12px rgba(0,0,0,.25);
}
@media (max-width: 1024px){
:root { --banner-offset: 56px; }
.build-controls { position: sticky; border-radius: 8px; margin-left: 0; margin-right: 0; }
.build-controls {
position: fixed !important; /* Fixed to viewport instead of sticky */
bottom: 0 !important; /* Anchor to bottom of screen */
left: 0 !important;
right: 0 !important;
top: auto !important; /* Override top positioning */
border-radius: 0 !important; /* Remove border radius for full width */
margin: 0 !important; /* Remove margins for full edge-to-edge */
padding: 0.5rem !important; /* Reduced padding */
box-shadow: 0 -6px 20px rgba(0,0,0,.4) !important; /* Upward shadow */
border-left: none !important;
border-right: none !important;
border-bottom: none !important; /* Remove bottom border */
background: linear-gradient(180deg, rgba(15,17,21,.99), rgba(15,17,21,.95)) !important;
z-index: 1000 !important; /* Higher z-index to ensure it's above content */
}
}
@media (min-width: 721px){
:root { --banner-offset: 48px; }
@ -347,3 +381,128 @@ img.lqip.loaded { filter: blur(0); opacity: 1; }
/* Virtualization wrapper should mirror grid to keep multi-column flow */
.virt-wrapper { display: grid; }
/* Mobile responsive fixes for horizontal scrolling issues */
@media (max-width: 768px) {
/* Prevent horizontal overflow */
html, body {
overflow-x: hidden !important;
width: 100% !important;
max-width: 100vw !important;
}
/* Fix modal layout on mobile */
.modal {
padding: 10px !important;
box-sizing: border-box;
}
.modal-content {
width: 100% !important;
max-width: calc(100vw - 20px) !important;
box-sizing: border-box !important;
overflow-x: hidden !important;
}
/* Force single column for include/exclude grid */
.include-exclude-grid {
display: flex !important;
flex-direction: column !important;
gap: 1rem !important;
}
/* Fix basics grid */
.basics-grid {
grid-template-columns: 1fr !important;
gap: 1rem !important;
}
/* Ensure all inputs and textareas fit properly */
.modal input,
.modal textarea,
.modal select {
width: 100% !important;
max-width: 100% !important;
box-sizing: border-box !important;
min-width: 0 !important;
}
/* Fix chips containers */
.modal [id$="_chips_container"] {
max-width: 100% !important;
overflow-x: hidden !important;
word-wrap: break-word !important;
}
/* Ensure fieldsets don't overflow */
.modal fieldset {
max-width: 100% !important;
box-sizing: border-box !important;
overflow-x: hidden !important;
}
/* Fix any inline styles that might cause overflow */
.modal fieldset > div,
.modal fieldset > div > div {
max-width: 100% !important;
overflow-x: hidden !important;
}
}
@media (max-width: 480px) {
.modal-content {
padding: 12px !important;
margin: 5px !important;
}
.modal fieldset {
padding: 8px !important;
margin: 6px 0 !important;
}
/* Enhanced mobile build controls */
.build-controls {
flex-direction: column !important;
gap: 0.25rem !important; /* Reduced gap */
align-items: stretch !important;
padding: 0.5rem !important; /* Reduced padding */
}
/* Two-column grid layout for mobile build controls */
.build-controls {
display: grid !important;
grid-template-columns: 1fr 1fr !important; /* Two equal columns */
grid-gap: 0.25rem !important;
align-items: stretch !important;
}
.build-controls form {
display: contents !important; /* Allow form contents to participate in grid */
width: auto !important;
}
.build-controls button {
flex: none !important;
padding: 0.4rem 0.5rem !important; /* Much smaller padding */
font-size: 12px !important; /* Smaller font */
min-height: 36px !important; /* Smaller minimum height */
line-height: 1.2 !important;
width: 100% !important; /* Full width within grid cell */
box-sizing: border-box !important;
white-space: nowrap !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
}
/* Hide non-essential elements on mobile to keep it clean */
.build-controls .sep,
.build-controls .replace-toggle,
.build-controls label[style*="margin-left"] {
display: none !important;
}
.build-controls .sep {
display: none !important; /* Hide separators on mobile */
}
}