diff --git a/core/http/react-ui/src/App.css b/core/http/react-ui/src/App.css index 27825b98a..2f433f2d9 100644 --- a/core/http/react-ui/src/App.css +++ b/core/http/react-ui/src/App.css @@ -47,8 +47,8 @@ /* Footer */ .app-footer { - background: var(--color-bg-secondary); - border-top: 1px solid var(--color-border-subtle); + background: transparent; + border-top: 1px solid var(--color-border-divider); padding: var(--spacing-md) var(--spacing-lg); margin-top: auto; } @@ -61,7 +61,17 @@ } .app-footer-version { - font-size: 0.75rem; + font-size: var(--text-xs); + color: var(--color-text-muted); +} + +.app-footer-version a { + color: var(--color-text-muted); + text-decoration: none; + transition: color 150ms; +} + +.app-footer-version a:hover { color: var(--color-text-secondary); } @@ -76,29 +86,29 @@ display: flex; align-items: center; gap: 4px; - font-size: 0.75rem; - color: var(--color-text-secondary); + font-size: var(--text-xs); + color: var(--color-text-muted); text-decoration: none; transition: color 150ms; } .app-footer-links a:hover { - color: var(--color-primary); + color: var(--color-text-secondary); } .app-footer-copyright { - font-size: 0.6875rem; + font-size: var(--text-xs); color: var(--color-text-muted); } .app-footer-copyright a { - color: var(--color-text-secondary); + color: var(--color-text-muted); text-decoration: none; transition: color 150ms; } .app-footer-copyright a:hover { - color: var(--color-primary); + color: var(--color-text-secondary); } /* Mobile header */ @@ -198,12 +208,12 @@ } .sidebar-section-title { - padding: var(--spacing-xs) var(--spacing-sm) 2px; - font-size: 0.625rem; - font-weight: 600; + padding: var(--spacing-sm) var(--spacing-sm) var(--spacing-xs); + font-size: var(--text-xs); + font-weight: var(--font-weight-semibold); text-transform: uppercase; - letter-spacing: 0.05em; - color: var(--color-text-muted); + letter-spacing: 0.08em; + color: var(--color-text-secondary); white-space: nowrap; overflow: hidden; } @@ -221,15 +231,20 @@ } .sidebar-section-toggle:hover { - color: var(--color-text-secondary); + color: var(--color-text-primary); } .sidebar-section-chevron { font-size: 0.5rem; - transition: transform var(--duration-fast); + opacity: 0.6; + transition: transform var(--duration-fast), opacity var(--duration-fast); flex-shrink: 0; } +.sidebar-section-toggle:hover .sidebar-section-chevron { + opacity: 1; +} + .sidebar-section-toggle.open .sidebar-section-chevron { transform: rotate(90deg); } @@ -238,26 +253,27 @@ display: flex; align-items: center; gap: var(--spacing-sm); - padding: 6px var(--spacing-sm); + padding: 8px var(--spacing-md) 8px var(--spacing-sm); color: var(--color-text-secondary); text-decoration: none; - font-size: 0.8125rem; - transition: all var(--duration-fast) var(--ease-default); + font-size: var(--text-sm); + font-weight: var(--font-weight-medium); + transition: color var(--duration-fast), background var(--duration-fast), border-color var(--duration-fast); border-left: 3px solid transparent; white-space: nowrap; overflow: hidden; } -.nav-item:hover { +.nav-item:hover:not(.active) { color: var(--color-text-primary); - background: var(--color-primary-light); + background: var(--color-surface-hover); } .nav-item.active { color: var(--color-primary); background: var(--color-primary-light); border-left-color: var(--color-primary); - font-weight: 500; + font-weight: var(--font-weight-semibold); } .nav-icon { @@ -377,19 +393,24 @@ } .sidebar-collapse-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; background: none; border: none; color: var(--color-text-muted); cursor: pointer; - padding: 4px; - border-radius: var(--radius-sm); - font-size: 0.75rem; - transition: color var(--duration-fast); + border-radius: var(--radius-md); + font-size: var(--text-sm); + transition: color var(--duration-fast), background var(--duration-fast); flex-shrink: 0; } .sidebar-collapse-btn:hover { color: var(--color-text-primary); + background: var(--color-surface-hover); } /* Collapsed sidebar (desktop only) */ @@ -474,7 +495,7 @@ .operation-item { display: flex; align-items: center; - gap: var(--spacing-sm); + gap: var(--spacing-md); padding: var(--spacing-xs) 0; } @@ -482,17 +503,25 @@ display: flex; align-items: center; gap: var(--spacing-sm); - flex: 1; + flex: 2 1 0; + min-width: 0; +} + +.operation-info > .operation-text { + flex: 1 1 auto; min-width: 0; } .operation-spinner { - width: 14px; - height: 14px; - border: 2px solid var(--color-border-subtle); + width: 16px; + height: 16px; + flex-shrink: 0; + box-sizing: border-box; + border: 2px solid var(--color-border-default); border-top-color: var(--color-primary); border-radius: 50%; animation: spin 0.8s linear infinite; + display: inline-block; } .operation-text { @@ -509,18 +538,39 @@ } .operation-bar-container { - flex: 1; - height: 3px; - background: var(--color-bg-tertiary); - border-radius: 2px; + flex: 0 1 160px; + min-width: 80px; + height: 4px; + background: var(--color-surface-sunken); + border-radius: var(--radius-full); overflow: hidden; } .operation-bar { height: 100%; background: var(--color-primary); - border-radius: 2px; - transition: width 300ms ease; + border-radius: var(--radius-full); + transition: width 300ms var(--ease-default); +} + +/* Inline install indicator — used in table rows (Models, Backends) */ +.inline-install { + display: flex; + flex-direction: column; + gap: 2px; + min-width: 0; +} +.inline-install__row { + display: flex; + align-items: center; + gap: var(--spacing-sm); + min-width: 0; +} +.inline-install__label { + font-size: var(--text-xs); + color: var(--color-primary); + font-weight: var(--font-weight-medium); + white-space: nowrap; } .operation-cancel { @@ -767,7 +817,7 @@ /* Common page styles */ .page { - padding: var(--spacing-xl); + padding: var(--spacing-xl) var(--spacing-xl) var(--spacing-2xl); max-width: 1200px; margin: 0 auto; width: 100%; @@ -779,83 +829,531 @@ } .page-title { - font-size: 1.5rem; - font-weight: 600; + font-size: var(--text-2xl); + font-weight: var(--font-weight-semibold); + letter-spacing: -0.015em; + line-height: var(--leading-tight); margin-bottom: var(--spacing-xs); + color: var(--color-text-primary); } .page-subtitle { - font-size: 0.875rem; + font-size: var(--text-sm); color: var(--color-text-secondary); + line-height: var(--leading-normal); } /* Cards */ .card { - background: var(--color-bg-secondary); + background: var(--color-surface-raised); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-lg); - padding: var(--spacing-md); + padding: var(--spacing-lg); + box-shadow: var(--shadow-subtle), var(--shadow-inset-top); transition: border-color var(--duration-fast), box-shadow var(--duration-fast), transform var(--duration-fast); } .card:hover { border-color: var(--color-border-default); - box-shadow: var(--shadow-sm); + box-shadow: var(--shadow-md), var(--shadow-inset-top); transform: translateY(-1px); } .card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: var(--spacing-lg); +} + +/* Form rows — consistent label+control rhythm */ +.form-row { + display: flex; + align-items: center; + justify-content: space-between; gap: var(--spacing-md); + padding: var(--spacing-md) 0; + border-bottom: 1px solid var(--color-border-divider); +} +.form-row:last-child { + border-bottom: none; +} +.form-row__label { + display: flex; + flex-direction: column; + gap: 2px; + min-width: 0; + flex: 1; +} +.form-row__label-text { + font-size: var(--text-sm); + font-weight: var(--font-weight-medium); + color: var(--color-text-primary); +} +.form-row__hint { + font-size: var(--text-xs); + color: var(--color-text-secondary); + line-height: var(--leading-snug); +} +.form-row__control { + flex-shrink: 0; +} + +.form-group__title { + display: flex; + align-items: center; + gap: var(--spacing-sm); + font-size: var(--text-xs); + font-weight: var(--font-weight-semibold); + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--color-text-secondary); + padding: var(--spacing-md) 0 var(--spacing-sm); + border-bottom: 1px solid var(--color-border-divider); + margin-bottom: var(--spacing-md); +} +.form-group__title i { + color: var(--color-primary); + font-size: var(--text-sm); +} +.form-group__body { + padding-bottom: var(--spacing-md); +} +.form-group__body:last-child { + padding-bottom: var(--spacing-lg); +} +.form-group__actions { + display: flex; + gap: var(--spacing-sm); + padding: var(--spacing-md) 0 var(--spacing-lg); + border-top: 1px solid var(--color-border-divider); + margin-top: var(--spacing-md); +} + +/* Form layout grids */ +.form-grid { + display: grid; + gap: var(--spacing-md); +} +.form-grid-2col { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: var(--spacing-md); +} +.form-grid-3col { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: var(--spacing-md); +} +@media (max-width: 720px) { + .form-grid-2col, .form-grid-3col { + grid-template-columns: 1fr; + } +} + +.form-field { + display: flex; + flex-direction: column; + gap: 6px; + min-width: 0; +} +.form-field__label { + font-size: var(--text-xs); + font-weight: var(--font-weight-medium); + color: var(--color-text-secondary); + text-transform: uppercase; + letter-spacing: 0.04em; +} +.form-field__hint { + font-size: var(--text-xs); + color: var(--color-text-muted); + line-height: var(--leading-snug); +} + +/* Button modifiers */ +.btn-full { + width: 100%; +} + +/* Progress bar */ +.progress-bar { + width: 100%; + height: 24px; + border-radius: var(--radius-full); + background: var(--color-surface-sunken); + overflow: hidden; + border: 1px solid var(--color-border-subtle); +} +.progress-bar__fill { + height: 100%; + background: var(--color-primary); + display: flex; + align-items: center; + justify-content: center; + font-size: var(--text-xs); + font-weight: var(--font-weight-semibold); + color: var(--color-primary-text); + transition: width 300ms var(--ease-default); + white-space: nowrap; + padding: 0 var(--spacing-sm); +} +.progress-bar__fill--error { + background: var(--color-error); +} + +/* Log tail viewport */ +.log-tail { + max-height: 180px; + overflow: auto; + background: var(--color-surface-sunken); + border: 1px solid var(--color-border-subtle); + border-radius: var(--radius-md); + padding: var(--spacing-sm) var(--spacing-md); + font-family: 'JetBrains Mono', monospace; + font-size: var(--text-xs); + line-height: var(--leading-snug); + color: var(--color-text-secondary); +} +.log-tail__line { + padding: 1px 0; +} +.log-tail__line--error { + color: var(--color-error); +} + +/* Result quote (TTS / Sound prompt echo) */ +.result-quote { + padding: var(--spacing-md); + background: var(--color-surface-sunken); + border: 1px solid var(--color-border-subtle); + border-radius: var(--radius-md); + color: var(--color-text-secondary); + font-style: italic; + text-align: center; + line-height: var(--leading-normal); +} + +/* Data table — used by Quantize jobs list, Traces, etc. */ +.data-table { + width: 100%; + border-collapse: collapse; + font-size: var(--text-sm); +} +.data-table th { + text-align: left; + padding: var(--spacing-sm) var(--spacing-md); + font-size: var(--text-xs); + font-weight: var(--font-weight-semibold); + text-transform: uppercase; + letter-spacing: 0.04em; + color: var(--color-text-secondary); + border-bottom: 1px solid var(--color-border-default); + background: var(--color-surface-sunken); +} +.data-table td { + padding: var(--spacing-sm) var(--spacing-md); + border-bottom: 1px solid var(--color-border-divider); + vertical-align: middle; + color: var(--color-text-primary); +} +.data-table tbody tr { + transition: background var(--duration-fast); +} +.data-table tbody tr:hover { + background: var(--color-surface-hover); +} +.data-table tbody tr.is-selected { + background: var(--color-primary-light); +} +.data-table tbody tr:last-child td { + border-bottom: none; +} +.data-table__actions { + display: flex; + gap: var(--spacing-xs); + justify-content: flex-end; +} +.data-table__truncate { + max-width: 280px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* Quantize page */ +.quantize-page__header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: var(--spacing-md); +} +.quantize-form { + margin-bottom: var(--spacing-lg); +} +.quantize-form__quant-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--spacing-sm); +} +.quantize-form__quant-row > :only-child { + grid-column: 1 / -1; +} +@media (max-width: 520px) { + .quantize-form__quant-row { + grid-template-columns: 1fr; + } +} +.quantize-progress-card { + margin-bottom: var(--spacing-lg); +} +.quantize-progress-card__header { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: var(--spacing-md); + margin-bottom: var(--spacing-md); +} +.quantize-progress-card__title { + display: flex; + align-items: center; + gap: var(--spacing-sm); + margin: 0; + font-size: var(--text-base); + color: var(--color-text-primary); +} +.quantize-progress-card__title i { + color: var(--color-primary); +} +.quantize-progress-card__status { + display: flex; + align-items: center; + gap: var(--spacing-sm); + margin-bottom: var(--spacing-md); + flex-wrap: wrap; +} +.quantize-progress-card__message { + font-size: var(--text-sm); + color: var(--color-text-secondary); +} +.quantize-progress-card .progress-bar { + margin-bottom: var(--spacing-md); +} +.quantize-import-card { + margin-bottom: var(--spacing-lg); +} +.quantize-import-card__title { + display: flex; + align-items: center; + gap: var(--spacing-sm); + margin: 0 0 var(--spacing-md); + font-size: var(--text-base); + color: var(--color-text-primary); +} +.quantize-import-card__title i { + color: var(--color-primary); +} +.quantize-import-card__row { + display: flex; + gap: var(--spacing-sm); + flex-wrap: wrap; + align-items: center; +} +.quantize-import-card__name { + flex: 1; + min-width: 220px; + max-width: 320px; +} +.quantize-jobs { + padding: 0; + overflow: hidden; +} +.quantize-jobs__title { + display: flex; + align-items: center; + gap: var(--spacing-sm); + margin: 0; + padding: var(--spacing-md) var(--spacing-lg); + border-bottom: 1px solid var(--color-border-divider); + font-size: var(--text-base); + color: var(--color-text-primary); +} +.quantize-jobs__title i { + color: var(--color-primary); +} +.quantize-jobs__scroll { + overflow-x: auto; +} + +/* Segmented control (Sound mode toggle etc.) */ +.segmented { + display: inline-flex; + padding: 3px; + background: var(--color-surface-sunken); + border: 1px solid var(--color-border-subtle); + border-radius: var(--radius-md); + margin-bottom: var(--spacing-md); + gap: 2px; +} +.segmented__item { + display: inline-flex; + align-items: center; + gap: var(--spacing-xs); + padding: 6px var(--spacing-md); + background: transparent; + color: var(--color-text-secondary); + border: none; + border-radius: var(--radius-sm); + font-family: inherit; + font-size: var(--text-xs); + font-weight: var(--font-weight-medium); + cursor: pointer; + transition: background var(--duration-fast), color var(--duration-fast); +} +.segmented__item:hover { + color: var(--color-text-primary); +} +.segmented__item.is-active { + background: var(--color-surface-raised); + color: var(--color-primary); + box-shadow: var(--shadow-subtle); +} + +/* Inline checkbox row */ +.checkbox-row { + display: inline-flex; + align-items: center; + gap: var(--spacing-sm); + padding: 10px var(--spacing-md); + font-size: var(--text-sm); + color: var(--color-text-primary); + background: var(--color-surface-sunken); + border: 1px solid var(--color-border-subtle); + border-radius: var(--radius-md); + cursor: pointer; + user-select: none; + transition: border-color var(--duration-fast); + margin-bottom: var(--spacing-md); +} +.checkbox-row:hover { + border-color: var(--color-border-default); +} +.checkbox-row input[type="checkbox"] { + accent-color: var(--color-primary); + cursor: pointer; +} + +/* Audio result wrapper (TTS/Sound) */ +.audio-result { + display: flex; + flex-direction: column; + align-items: stretch; + gap: var(--spacing-md); + width: 100%; + max-width: 480px; +} +.audio-result__player { + width: 100%; +} +.audio-result__actions { + display: flex; + gap: var(--spacing-sm); + justify-content: center; +} + +/* Media empty state */ +.media-empty { + text-align: center; + color: var(--color-text-muted); + padding: var(--spacing-xl) var(--spacing-md); +} +.media-empty__icon { + display: block; + font-size: 2.75rem; + margin-bottom: var(--spacing-md); + opacity: 0.35; +} +.media-empty p { + font-size: var(--text-sm); + margin: 0; } /* Buttons */ .btn { display: inline-flex; align-items: center; + justify-content: center; gap: var(--spacing-xs); - padding: var(--spacing-sm) var(--spacing-md); + padding: 0.5rem var(--spacing-md); + min-height: 36px; border-radius: var(--radius-md); - font-size: 0.875rem; + font-size: var(--text-sm); font-family: inherit; - font-weight: 500; + font-weight: var(--font-weight-medium); + letter-spacing: 0.005em; cursor: pointer; - border: none; - transition: background var(--duration-fast) var(--ease-default), color var(--duration-fast) var(--ease-default), border-color var(--duration-fast) var(--ease-default), box-shadow var(--duration-fast) var(--ease-default); + border: 1px solid transparent; + transition: background var(--duration-fast) var(--ease-default), color var(--duration-fast) var(--ease-default), border-color var(--duration-fast) var(--ease-default), box-shadow var(--duration-fast) var(--ease-default), transform var(--duration-fast) var(--ease-default); text-decoration: none; + white-space: nowrap; +} + +.btn:focus-visible { + outline: none; + box-shadow: 0 0 0 3px var(--color-border-focus); +} + +/* Global focus ring — any interactive that isn't a .btn */ +:where(a, button, input, select, textarea, [tabindex]:not([tabindex="-1"])):focus-visible { + outline: 2px solid var(--color-border-focus); + outline-offset: 2px; + border-radius: var(--radius-sm); } .btn-primary { background: var(--color-primary); color: var(--color-primary-text); + box-shadow: var(--shadow-subtle); } -.btn-primary:hover { +.btn-primary:hover:not(:disabled) { background: var(--color-primary-hover); + box-shadow: var(--shadow-sm); } .btn-secondary { - background: var(--color-bg-tertiary); + background: var(--color-surface-raised); color: var(--color-text-primary); - border: 1px solid var(--color-border-default); + border-color: var(--color-border-default); } -.btn-secondary:hover { +.btn-secondary:hover:not(:disabled) { border-color: var(--color-border-strong); background: var(--color-primary-light); + color: var(--color-primary); +} + +.btn-ghost { + background: transparent; + color: var(--color-text-secondary); + border-color: transparent; +} +.btn-ghost:hover:not(:disabled) { + background: var(--color-surface-hover); + color: var(--color-text-primary); } .btn-danger { background: var(--color-error-light); color: var(--color-error); - border: 1px solid rgba(239, 68, 68, 0.2); + border-color: var(--color-error-border); } -.btn-danger:hover { - background: rgba(239, 68, 68, 0.2); +.btn-danger:hover:not(:disabled) { + background: var(--color-error); + color: var(--color-text-inverse); + border-color: var(--color-error); } .btn-sm { - padding: var(--spacing-xs) var(--spacing-sm); - font-size: 0.8125rem; + padding: 0.35rem var(--spacing-sm); + min-height: 30px; + font-size: var(--text-xs); } .btn:active:not(:disabled) { @@ -867,41 +1365,118 @@ cursor: not-allowed; } +/* Toggle switch */ +.toggle { + position: relative; + display: inline-block; + width: 38px; + height: 22px; + cursor: pointer; + flex-shrink: 0; +} +.toggle input { + position: absolute; + opacity: 0; + width: 0; + height: 0; +} +.toggle__track { + position: absolute; + inset: 0; + border-radius: var(--radius-full); + background: var(--color-toggle-off); + transition: background var(--duration-normal) var(--ease-default); +} +.toggle__thumb { + position: absolute; + top: 2px; + left: 2px; + width: 18px; + height: 18px; + border-radius: var(--radius-full); + background: #ffffff; + box-shadow: var(--shadow-sm); + transition: transform var(--duration-normal) var(--ease-default); +} +.toggle--on .toggle__track { + background: var(--color-toggle-on); +} +.toggle--on .toggle__thumb { + transform: translateX(16px); +} +.toggle:hover:not(.toggle--disabled) .toggle__track { + filter: brightness(1.08); +} +.toggle:focus-within .toggle__track { + box-shadow: 0 0 0 3px var(--color-border-focus); +} +.toggle--disabled { + cursor: not-allowed; + opacity: 0.5; +} + /* Inputs */ .input { - background: var(--color-bg-tertiary); + background: var(--color-surface-raised); color: var(--color-text-primary); border: 1px solid var(--color-border-default); border-radius: var(--radius-md); - padding: var(--spacing-sm); - font-size: 0.875rem; + padding: var(--spacing-sm) var(--spacing-md); + font-size: var(--text-sm); font-family: inherit; outline: none; width: 100%; - transition: border-color var(--duration-fast); + transition: border-color var(--duration-fast), box-shadow var(--duration-fast), background var(--duration-fast); +} +.input::placeholder { + color: var(--color-text-muted); +} +.input:hover:not(:disabled):not(:focus) { + border-color: var(--color-border-strong); } .input:focus { - border-color: var(--color-border-strong); - box-shadow: 0 0 0 2px var(--color-primary-light); + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-light); +} +.input:disabled { + background: var(--color-surface-sunken); + color: var(--color-text-muted); + cursor: not-allowed; +} +select.input { + cursor: pointer; + padding-right: var(--spacing-xl); } .textarea { - background: var(--color-bg-tertiary); + background: var(--color-surface-raised); color: var(--color-text-primary); border: 1px solid var(--color-border-default); border-radius: var(--radius-md); - padding: var(--spacing-sm); - font-size: 0.875rem; + padding: var(--spacing-sm) var(--spacing-md); + font-size: var(--text-sm); font-family: inherit; outline: none; width: 100%; resize: vertical; min-height: 80px; - transition: border-color var(--duration-fast); + line-height: var(--leading-normal); + transition: border-color var(--duration-fast), box-shadow var(--duration-fast); +} +.textarea::placeholder { + color: var(--color-text-muted); +} +.textarea:hover:not(:disabled):not(:focus) { + border-color: var(--color-border-strong); } .textarea:focus { - border-color: var(--color-border-strong); - box-shadow: 0 0 0 2px var(--color-primary-light); + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-light); +} +.textarea:disabled { + background: var(--color-surface-sunken); + color: var(--color-text-muted); + cursor: not-allowed; } /* CodeMirror editor wrapper */ @@ -1249,20 +1824,24 @@ } .filter-btn { - padding: var(--spacing-xs) var(--spacing-sm); - background: var(--color-bg-tertiary); + padding: 6px var(--spacing-md); + background: var(--color-surface-raised); color: var(--color-text-secondary); - border: 1px solid var(--color-border-subtle); + border: 1px solid var(--color-border-default); border-radius: var(--radius-full); cursor: pointer; - font-size: 0.75rem; + font-size: var(--text-xs); + font-weight: var(--font-weight-medium); font-family: inherit; + box-shadow: var(--shadow-subtle); transition: all var(--duration-fast); } .filter-btn:hover { border-color: var(--color-primary-border); color: var(--color-primary); + transform: translateY(-1px); + box-shadow: var(--shadow-sm); } .filter-btn.active { @@ -1446,12 +2025,6 @@ to { opacity: 1; transform: translateY(0); } } -@keyframes completionGlow { - 0% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.2); } - 50% { box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1); } - 100% { box-shadow: 0 0 0 0 rgba(59, 130, 246, 0); } -} - /* Page route transitions */ .page-transition { animation: fadeIn 200ms ease; @@ -1462,11 +2035,6 @@ min-width: 0; } -/* Completion glow on streaming finish */ -.chat-message-new .chat-message-content { - animation: completionGlow 600ms ease-out; -} - /* Chat-specific styles */ .chat-layout { display: flex; @@ -1519,24 +2087,27 @@ .chat-list-item { display: flex; align-items: flex-start; - gap: var(--spacing-xs); - padding: var(--spacing-sm); + gap: var(--spacing-sm); + padding: var(--spacing-sm) var(--spacing-md); border-radius: var(--radius-md); cursor: pointer; - font-size: 0.8125rem; + font-size: var(--text-sm); color: var(--color-text-secondary); - transition: background var(--duration-fast), color var(--duration-fast), transform var(--duration-fast); + border-left: 3px solid transparent; + transition: background var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast); margin-bottom: 2px; } -.chat-list-item:hover { - background: var(--color-primary-light); - transform: translateX(2px); +.chat-list-item:hover:not(.active) { + background: var(--color-surface-hover); + color: var(--color-text-primary); } .chat-list-item.active { background: var(--color-primary-light); color: var(--color-primary); + border-left-color: var(--color-primary); + font-weight: var(--font-weight-medium); } .chat-list-item-info { @@ -1790,15 +2361,14 @@ display: flex; gap: var(--spacing-sm); align-items: flex-end; - background: var(--color-bg-tertiary); + background: var(--color-surface-raised); border: 1px solid var(--color-border-default); border-radius: var(--radius-lg); padding: var(--spacing-xs); transition: border-color var(--duration-fast), box-shadow var(--duration-fast); } .chat-input-wrapper:focus-within { - border-color: var(--color-primary-border); - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.12), 0 0 12px rgba(59, 130, 246, 0.06); + border-color: var(--color-primary); } .chat-attach-btn { @@ -2029,26 +2599,30 @@ .chat-empty-suggestions { display: flex; flex-wrap: wrap; - gap: var(--spacing-xs); + gap: var(--spacing-sm); justify-content: center; margin-bottom: var(--spacing-lg); - max-width: 500px; + max-width: 520px; } .chat-empty-suggestion { - padding: var(--spacing-xs) var(--spacing-md); - background: var(--color-bg-tertiary); - border: 1px solid var(--color-border-subtle); + padding: 8px var(--spacing-md); + background: var(--color-surface-raised); + border: 1px solid var(--color-border-default); border-radius: var(--radius-full); - font-size: 0.8125rem; + font-size: var(--text-sm); + font-weight: var(--font-weight-medium); font-family: inherit; color: var(--color-text-secondary); cursor: pointer; + box-shadow: var(--shadow-subtle), var(--shadow-inset-top); transition: all var(--duration-fast); } .chat-empty-suggestion:hover { border-color: var(--color-primary-border); color: var(--color-primary); - background: var(--color-bg-secondary); + background: var(--color-surface-raised); + transform: translateY(-1px); + box-shadow: var(--shadow-sm), var(--shadow-inset-top); } .chat-empty-hints { display: flex; @@ -2418,7 +2992,6 @@ } .chat-client-mcp-status-connected { background: var(--color-success); - box-shadow: 0 0 4px rgba(34, 197, 94, 0.5); } .chat-client-mcp-status-connecting { background: var(--color-warning); @@ -2698,9 +3271,9 @@ /* Studio tabs */ .studio-tabs { display: flex; - gap: 0; + gap: var(--spacing-xs); border-bottom: 1px solid var(--color-border-subtle); - padding: 0 var(--spacing-xl); + padding: var(--spacing-sm) var(--spacing-xl) 0; background: var(--color-bg-primary); position: sticky; top: 0; @@ -2710,15 +3283,17 @@ .studio-tab { display: flex; align-items: center; - gap: 6px; + gap: var(--spacing-xs); background: none; border: none; - padding: var(--spacing-sm) var(--spacing-md); - font-size: 0.8125rem; + padding: 10px var(--spacing-md); + font-size: var(--text-sm); font-family: inherit; + font-weight: var(--font-weight-medium); color: var(--color-text-secondary); cursor: pointer; border-bottom: 2px solid transparent; + margin-bottom: -1px; transition: color var(--duration-fast), border-color var(--duration-fast); } @@ -2729,37 +3304,64 @@ .studio-tab-active { color: var(--color-primary); border-bottom-color: var(--color-primary); - font-weight: 500; + font-weight: var(--font-weight-semibold); } /* Two-column layout for media generation pages */ .media-layout { display: grid; - grid-template-columns: minmax(320px, 400px) 1fr; + grid-template-columns: minmax(320px, 420px) 1fr; gap: var(--spacing-lg); padding: var(--spacing-xl); - max-width: 1200px; + max-width: 1280px; margin: 0 auto; width: 100%; align-items: start; } +@media (max-width: 900px) { + .media-layout { + grid-template-columns: 1fr; + } +} + .media-controls { - background: var(--color-bg-secondary); + background: var(--color-surface-raised); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-lg); padding: var(--spacing-lg); + box-shadow: var(--shadow-subtle); position: sticky; top: var(--spacing-lg); } +.media-controls .form-group { + margin-bottom: var(--spacing-md); +} +.media-controls .form-grid-2col, +.media-controls .form-grid-3col { + margin-bottom: var(--spacing-md); +} +.media-controls .form-grid-2col .form-group, +.media-controls .form-grid-3col .form-group { + margin-bottom: 0; +} .media-controls .page-header { - margin-bottom: var(--spacing-md); - padding: 0; + margin-bottom: var(--spacing-lg); + padding-bottom: var(--spacing-md); + border-bottom: 1px solid var(--color-border-divider); } .media-controls .page-title { - font-size: 1.125rem; + font-size: var(--text-lg); + font-weight: var(--font-weight-semibold); + display: flex; + align-items: center; + gap: var(--spacing-sm); +} + +.media-controls .page-title i { + color: var(--color-accent); } .media-preview { @@ -3429,72 +4031,75 @@ flex-direction: column; align-items: center; justify-content: center; - max-width: 48rem; + max-width: 52rem; margin: 0 auto; - padding: var(--spacing-xl); + padding: var(--spacing-2xl) var(--spacing-xl); width: 100%; + gap: var(--spacing-md); } .home-hero { text-align: center; - padding: var(--spacing-md) 0; + padding: var(--spacing-sm) 0 var(--spacing-md); } .home-logo { - width: 80px; + width: 72px; height: auto; - margin: 0 auto var(--spacing-sm); + margin: 0 auto; display: block; } /* Home resource bar - prominent */ .home-resource-bar { width: 100%; - max-width: 380px; - padding: var(--spacing-sm) var(--spacing-md); - background: var(--color-bg-secondary); + max-width: 420px; + padding: var(--spacing-md) var(--spacing-lg); + background: var(--color-surface-raised); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-lg); - margin-bottom: var(--spacing-md); + box-shadow: var(--shadow-subtle); } .home-resource-bar-header { display: flex; align-items: center; - gap: var(--spacing-xs); - font-size: 0.8125rem; + gap: var(--spacing-sm); + font-size: var(--text-sm); color: var(--color-text-secondary); - margin-bottom: var(--spacing-xs); + margin-bottom: var(--spacing-sm); } .home-resource-label { - font-weight: 500; + font-weight: var(--font-weight-medium); + color: var(--color-text-primary); } .home-resource-pct { margin-left: auto; font-family: 'JetBrains Mono', monospace; - font-weight: 500; + font-weight: var(--font-weight-medium); + font-size: var(--text-xs); } .home-resource-track { width: 100%; height: 6px; - background: var(--color-bg-tertiary); - border-radius: 3px; + background: var(--color-surface-sunken); + border-radius: var(--radius-full); overflow: hidden; } .home-resource-fill { height: 100%; - border-radius: 3px; + border-radius: var(--radius-full); transition: width 500ms ease; } .home-cluster-status { display: flex; align-items: center; gap: var(--spacing-xs); - font-size: 0.75rem; + font-size: var(--text-xs); color: var(--color-text-muted); - margin-top: var(--spacing-xs); + margin-top: var(--spacing-sm); } .home-cluster-dot { width: 6px; height: 6px; - border-radius: 50%; + border-radius: var(--radius-full); background: var(--color-success); display: inline-block; } @@ -3502,17 +4107,17 @@ /* Home chat card */ .home-chat-card { width: 100%; - background: var(--color-bg-secondary); + background: var(--color-surface-raised); border: 1px solid var(--color-border-subtle); - border-radius: var(--radius-lg); - padding: var(--spacing-md); - margin-bottom: var(--spacing-md); + border-radius: var(--radius-xl); + padding: var(--spacing-lg); + box-shadow: var(--shadow-md); } .home-model-row { display: flex; align-items: center; gap: var(--spacing-sm); - margin-bottom: var(--spacing-sm); + margin-bottom: var(--spacing-md); } .home-file-tags { display: flex; @@ -3523,12 +4128,12 @@ .home-file-tag { display: inline-flex; align-items: center; - gap: 4px; - padding: 2px 8px; - background: var(--color-bg-tertiary); + gap: 6px; + padding: 4px 10px; + background: var(--color-surface-sunken); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-full); - font-size: 0.75rem; + font-size: var(--text-xs); color: var(--color-text-secondary); } .home-file-tag button { @@ -3539,17 +4144,20 @@ padding: 0; font-size: 0.625rem; } +.home-file-tag button:hover { + color: var(--color-error); +} /* Home input container */ .home-input-container { - background: var(--color-bg-tertiary); + background: var(--color-surface-sunken); border: 1px solid var(--color-border-default); border-radius: var(--radius-lg); transition: border-color var(--duration-fast), box-shadow var(--duration-fast); } .home-input-container:focus-within { - border-color: var(--color-primary-border); - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.12), 0 0 12px rgba(59, 130, 246, 0.06); + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-light); } .home-textarea { width: 100%; @@ -3557,13 +4165,13 @@ color: var(--color-text-primary); border: none; border-radius: var(--radius-lg) var(--radius-lg) 0 0; - padding: var(--spacing-sm) var(--spacing-md); - font-size: 0.875rem; + padding: var(--spacing-md); + font-size: var(--text-base); font-family: inherit; outline: none; resize: none; - min-height: 80px; - line-height: 1.5; + min-height: 84px; + line-height: var(--leading-normal); } .home-textarea::placeholder { color: var(--color-text-muted); @@ -3571,8 +4179,9 @@ .home-input-footer { display: flex; align-items: center; - padding: var(--spacing-xs) var(--spacing-sm); - border-top: 1px solid var(--color-border-subtle); + gap: var(--spacing-sm); + padding: var(--spacing-xs) var(--spacing-sm) var(--spacing-xs) var(--spacing-md); + border-top: 1px solid var(--color-border-divider); } .home-attach-buttons { display: flex; @@ -3583,33 +4192,36 @@ border: none; color: var(--color-text-muted); cursor: pointer; - padding: 4px 8px; - font-size: 0.875rem; - border-radius: var(--radius-sm); - transition: color var(--duration-fast); + padding: 6px 8px; + font-size: var(--text-sm); + border-radius: var(--radius-md); + transition: color var(--duration-fast), background var(--duration-fast); } .home-attach-btn:hover { color: var(--color-primary); + background: var(--color-primary-light); } .home-input-hint { flex: 1; text-align: center; - font-size: 0.6875rem; + font-size: var(--text-xs); color: var(--color-text-muted); + letter-spacing: 0.02em; } .home-send-btn { display: flex; align-items: center; justify-content: center; - width: 32px; - height: 32px; + width: 34px; + height: 34px; background: var(--color-primary); color: var(--color-primary-text); border: none; - border-radius: 50%; - font-size: 0.8125rem; + border-radius: var(--radius-full); + font-size: var(--text-sm); cursor: pointer; - transition: background var(--duration-fast), transform 100ms; + box-shadow: var(--shadow-sm); + transition: background var(--duration-fast), transform 100ms, box-shadow var(--duration-fast); flex-shrink: 0; } .home-send-btn:hover:not(:disabled) { @@ -3630,27 +4242,29 @@ flex-wrap: wrap; gap: var(--spacing-sm); justify-content: center; - margin: var(--spacing-md) 0; } .home-link-btn { display: inline-flex; align-items: center; gap: var(--spacing-xs); - padding: var(--spacing-xs) var(--spacing-md); - background: var(--color-bg-tertiary); + padding: 8px var(--spacing-md); + background: var(--color-surface-raised); color: var(--color-text-secondary); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-full); - font-size: 0.8125rem; + font-size: var(--text-xs); + font-weight: var(--font-weight-medium); font-family: inherit; cursor: pointer; text-decoration: none; + box-shadow: var(--shadow-subtle); transition: all var(--duration-fast); } .home-link-btn:hover { border-color: var(--color-primary-border); color: var(--color-primary); transform: translateY(-1px); + box-shadow: var(--shadow-sm); } /* Home loaded models */ @@ -3658,24 +4272,25 @@ display: flex; flex-wrap: wrap; align-items: center; - gap: var(--spacing-xs); - padding: var(--spacing-sm); - background: var(--color-bg-secondary); + gap: var(--spacing-sm); + padding: var(--spacing-sm) var(--spacing-md); + background: var(--color-surface-raised); border: 1px solid var(--color-border-subtle); border-radius: var(--radius-lg); - font-size: 0.8125rem; + font-size: var(--text-xs); color: var(--color-text-secondary); width: 100%; + box-shadow: var(--shadow-subtle); } .home-loaded-dot { - width: 6px; - height: 6px; - border-radius: 50%; + width: 8px; + height: 8px; + border-radius: var(--radius-full); background: var(--color-success); } .home-loaded-text { - font-weight: 500; - margin-right: var(--spacing-xs); + font-weight: var(--font-weight-medium); + color: var(--color-text-primary); } .home-loaded-list { display: flex; @@ -3685,11 +4300,13 @@ .home-loaded-item { display: inline-flex; align-items: center; - gap: 4px; - padding: 2px 8px; - background: var(--color-bg-tertiary); + gap: 6px; + padding: 3px 10px; + background: var(--color-surface-sunken); + border: 1px solid var(--color-border-divider); border-radius: var(--radius-full); - font-size: 0.75rem; + font-size: var(--text-xs); + font-family: 'JetBrains Mono', monospace; } .home-loaded-item button { background: none; @@ -3721,20 +4338,23 @@ padding: var(--spacing-xl) 0; } .home-wizard-hero h1 { - font-size: 1.5rem; - font-weight: 600; + font-size: var(--text-2xl); + font-weight: var(--font-weight-semibold); + letter-spacing: -0.015em; margin-bottom: var(--spacing-sm); + color: var(--color-text-primary); } .home-wizard-hero p { color: var(--color-text-secondary); - font-size: 0.9375rem; + font-size: var(--text-base); + line-height: var(--leading-normal); } .home-wizard-steps { margin-bottom: var(--spacing-xl); } .home-wizard-steps h2 { - font-size: 1.125rem; - font-weight: 600; + font-size: var(--text-lg); + font-weight: var(--font-weight-semibold); margin-bottom: var(--spacing-md); } .home-wizard-step { diff --git a/core/http/react-ui/src/App.jsx b/core/http/react-ui/src/App.jsx index f06fe788d..d646f1749 100644 --- a/core/http/react-ui/src/App.jsx +++ b/core/http/react-ui/src/App.jsx @@ -65,7 +65,7 @@ export default function App() {