diff --git a/ui/static/index.html b/ui/static/index.html index 00dc4b1..9d217ec 100644 --- a/ui/static/index.html +++ b/ui/static/index.html @@ -1005,6 +1005,245 @@ 100% { background: transparent; } } .copy-flash { animation: copyFlash .6s ease; } + +/* ════════════════════════════════════════════════════════════════════ + ═══════════════ UI UPGRADE — PR-1 (theme, blocks, fx) ═══════════ + ════════════════════════════════════════════════════════════════════ */ + +/* 5 themes via [data-theme] on . The default (no attr) stays parchment. */ +html[data-theme="dark"] { + --parchment: #1a1a1b; --ivory: #232324; --white: #2a2a2c; --sand: #33322f; + --near-black: #ece9e0; --dark-surface: #0f0f10; + --terracotta: #e08a66; --coral: #f09878; + --charcoal: #d6d3cb; --olive: #b5b1a6; --stone: #8e8a80; --silver: #65625b; + --border-cream: #2a2a2c; --border-warm: #36352f; --border-dark: #0b0b0c; + --ring-warm: #3c3b36; +} +html[data-theme="forest"] { + --parchment: #edf2ec; --ivory: #f6f9f4; --white: #ffffff; --sand: #d8e0d4; + --near-black: #14211c; --dark-surface: #223028; + --terracotta: #5f8d6a; --coral: #7aa882; + --charcoal: #304038; --olive: #4f6056; --stone: #778478; --silver: #a7b5a6; + --border-cream: #dbe2d7; --border-warm: #c7d1c1; --border-dark: #2a3a32; + --ring-warm: #bccbbb; --success: #3e7c4a; --warning: #a2722b; +} +html[data-theme="ocean"] { + --parchment: #eaf1f6; --ivory: #f4f8fb; --white: #ffffff; --sand: #d7e2ec; + --near-black: #0f1c2a; --dark-surface: #1b2c40; + --terracotta: #3d7fa8; --coral: #5a97bd; + --charcoal: #2d4762; --olive: #4e6882; --stone: #78879a; --silver: #aab6c4; + --border-cream: #d9e3ec; --border-warm: #c4d2de; --border-dark: #203449; + --ring-warm: #b9c7d4; +} +html[data-theme="sunset"] { + --parchment: #fbefe4; --ivory: #fff6ec; --white: #ffffff; --sand: #f2dec7; + --near-black: #2d1a12; --dark-surface: #4a2a1c; + --terracotta: #d94e3d; --coral: #ef7950; + --charcoal: #5e3725; --olive: #8b5234; --stone: #a57a5f; --silver: #c9a992; + --border-cream: #f1dcc3; --border-warm: #e4c8a8; --border-dark: #5a2e1a; + --ring-warm: #debfa1; +} + +/* Smooth theme transition on color-ish properties */ +html, body, .sidebar, .nav, .page, .phase-card, .kb-card, .exp-card, .ext-card, .modal, +.btn, .cfg-input, .cfg-select, .sidebar-section, .sidebar-logs { + transition: background-color .35s ease, color .35s ease, border-color .35s ease; +} + +/* Custom background layer (body::before so content stays crisp) */ +body { + position: relative; + --bg-image: none; + --bg-blur: 0px; + --bg-opacity: 0.35; +} +body::before { + content: ""; + position: fixed; inset: 0; z-index: -1; + background-image: var(--bg-image); + background-size: cover; background-position: center; background-repeat: no-repeat; + filter: blur(var(--bg-blur)); + opacity: var(--bg-opacity); + pointer-events: none; + transform: scale(1.05); /* avoid blurred edges */ + transition: opacity .3s, filter .3s; +} +body.has-bg { background-color: transparent; } +body.has-bg .nav, body.has-bg .sidebar, +body.has-bg .phase-card, body.has-bg .modal, body.has-bg .exp-card, +body.has-bg .kb-card, body.has-bg .ext-card { + backdrop-filter: saturate(1.15) blur(8px); + background-color: color-mix(in srgb, var(--ivory) 85%, transparent); +} + +/* ── Collapsible sidebar blocks ───────────────────────────────────── */ +.sidebar-section.collapsible { padding: 0; cursor: default; } +.sidebar-section.collapsible > .sbs-head { + display: flex; align-items: center; justify-content: space-between; + padding: 14px 20px; cursor: pointer; user-select: none; + border-bottom: 1px solid transparent; + transition: background .15s, border-color .2s; +} +.sidebar-section.collapsible > .sbs-head:hover { background: rgba(0,0,0,.025); } +.sidebar-section.collapsible > .sbs-head .sbs-title { + font-size: .72rem; font-weight: 700; letter-spacing: .06em; + text-transform: uppercase; color: var(--stone); + display: flex; align-items: center; gap: 8px; +} +.sidebar-section.collapsible > .sbs-head .sbs-icon { font-size: .9rem; opacity: .85; } +.sidebar-section.collapsible > .sbs-head .sbs-chev { + color: var(--stone); font-size: .75rem; + transition: transform .25s cubic-bezier(.4,0,.2,1); +} +.sidebar-section.collapsible.open > .sbs-head .sbs-chev { transform: rotate(90deg); } +.sidebar-section.collapsible > .sbs-body { + overflow: hidden; max-height: 0; + transition: max-height .3s cubic-bezier(.4,0,.2,1); +} +.sidebar-section.collapsible.open > .sbs-body { max-height: 2000px; } +.sidebar-section.collapsible > .sbs-body > .sbs-inner { padding: 4px 20px 18px; } +.sidebar-section.collapsible.open > .sbs-head { + border-bottom-color: var(--border-cream); + background: color-mix(in srgb, var(--terracotta) 6%, transparent); +} + +/* Theme swatches */ +.theme-swatches { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; margin-top: 4px; } +.theme-swatch { + aspect-ratio: 1; border-radius: 10px; cursor: pointer; border: 2px solid transparent; + position: relative; transition: transform .18s, border-color .18s, box-shadow .18s; +} +.theme-swatch:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,.15); } +.theme-swatch.active { border-color: var(--terracotta); box-shadow: 0 0 0 2px color-mix(in srgb, var(--terracotta) 30%, transparent); } +.theme-swatch .label { + position: absolute; bottom: -18px; left: 0; right: 0; text-align: center; + font-size: .65rem; color: var(--stone); font-weight: 600; +} +.theme-swatch[data-theme="parchment"] { background: linear-gradient(135deg, #f5f4ed 50%, #c96442 50%); } +.theme-swatch[data-theme="dark"] { background: linear-gradient(135deg, #1a1a1b 50%, #e08a66 50%); } +.theme-swatch[data-theme="forest"] { background: linear-gradient(135deg, #edf2ec 50%, #5f8d6a 50%); } +.theme-swatch[data-theme="ocean"] { background: linear-gradient(135deg, #eaf1f6 50%, #3d7fa8 50%); } +.theme-swatch[data-theme="sunset"] { background: linear-gradient(135deg, #fbefe4 50%, #d94e3d 50%); } +.theme-swatches { padding-bottom: 22px; } + +/* Background controls */ +.bg-controls { display: flex; flex-direction: column; gap: 10px; } +.bg-controls .row { display: flex; align-items: center; gap: 8px; font-size: .74rem; color: var(--ink-light); } +.bg-controls input[type="range"] { + flex: 1; accent-color: var(--terracotta); height: 4px; +} +.bg-drop { + border: 1.5px dashed var(--border-warm); border-radius: 8px; + padding: 14px; text-align: center; cursor: pointer; + font-size: .8rem; color: var(--stone); + transition: border-color .2s, background .2s, color .2s; +} +.bg-drop:hover, .bg-drop.dragover { + border-color: var(--terracotta); background: color-mix(in srgb, var(--terracotta) 4%, transparent); + color: var(--terracotta); +} +.bg-preview { + width: 100%; aspect-ratio: 16/9; border-radius: 8px; + background-size: cover; background-position: center; + border: 1px solid var(--border-warm); + display: none; +} +.bg-preview.has-image { display: block; } + +/* Phase card running-pulse animation */ +@keyframes phasePulse { + 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--terracotta) 40%, transparent); } + 50% { box-shadow: 0 0 0 8px color-mix(in srgb, var(--terracotta) 0%, transparent); } +} +.phase-card.running { + animation: phasePulse 1.6s ease-in-out infinite; + border-color: var(--terracotta) !important; +} + +/* Fade-in for freshly rendered data blocks */ +@keyframes fadeInUp { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } } +.fade-in-up { animation: fadeInUp .35s ease both; } + +/* Button ripple */ +.btn { position: relative; overflow: hidden; } +.btn .ripple { + position: absolute; border-radius: 50%; + background: color-mix(in srgb, currentColor 35%, transparent); + transform: scale(0); animation: rippleFx .55s ease-out; + pointer-events: none; +} +@keyframes rippleFx { + to { transform: scale(2.5); opacity: 0; } +} + +/* ── Toast notification system ─────────────────────────────────────── */ +.toast-stack { + position: fixed; bottom: 20px; right: 20px; z-index: 3000; + display: flex; flex-direction: column; gap: 10px; pointer-events: none; + max-width: 360px; +} +.toast { + background: var(--ivory); color: var(--near-black); + border-left: 4px solid var(--terracotta); + padding: 12px 16px 12px 14px; border-radius: 8px; + box-shadow: 0 8px 24px rgba(0,0,0,.18); + font-size: .86rem; line-height: 1.4; + pointer-events: auto; cursor: pointer; + animation: toastIn .3s cubic-bezier(.34,1.56,.64,1); + display: flex; align-items: flex-start; gap: 10px; +} +.toast.closing { animation: toastOut .25s ease forwards; } +.toast .toast-icon { flex-shrink: 0; font-size: 1.1rem; margin-top: 1px; } +.toast .toast-body { flex: 1; } +.toast .toast-title { font-weight: 600; margin-bottom: 2px; font-size: .88rem; } +.toast.info { border-left-color: #3d7fa8; } +.toast.success { border-left-color: var(--success); } +.toast.warn { border-left-color: var(--warning); } +.toast.error { border-left-color: var(--error); } +@keyframes toastIn { from { opacity: 0; transform: translateX(24px); } to { opacity: 1; transform: translateX(0); } } +@keyframes toastOut { to { opacity: 0; transform: translateX(24px); } } + +/* ── Command palette (Cmd+K) ──────────────────────────────────────── */ +.cmdp-backdrop { + position: fixed; inset: 0; z-index: 2500; + background: rgba(0,0,0,.45); backdrop-filter: blur(6px); + display: none; align-items: flex-start; justify-content: center; + padding-top: 14vh; +} +.cmdp-backdrop.visible { display: flex; animation: fadeInUp .18s; } +.cmdp { + width: min(560px, 92vw); + background: var(--ivory); border-radius: 12px; + box-shadow: 0 24px 72px rgba(0,0,0,.35); + overflow: hidden; max-height: 70vh; display: flex; flex-direction: column; +} +.cmdp-input { + border: none; outline: none; background: transparent; + padding: 18px 22px; font-size: 1.05rem; color: var(--near-black); + border-bottom: 1px solid var(--border-cream); + font-family: var(--font-sans); +} +.cmdp-list { flex: 1; overflow-y: auto; padding: 6px 0; } +.cmdp-item { + display: flex; align-items: center; gap: 12px; + padding: 10px 22px; cursor: pointer; font-size: .9rem; + color: var(--ink-light); +} +.cmdp-item:hover, .cmdp-item.sel { + background: color-mix(in srgb, var(--terracotta) 10%, transparent); + color: var(--near-black); +} +.cmdp-item .cmdp-ic { width: 22px; text-align: center; } +.cmdp-item .cmdp-hint { margin-left: auto; font-size: .72rem; color: var(--stone); font-family: var(--font-mono); } +.cmdp-empty { padding: 24px; text-align: center; color: var(--stone); font-size: .86rem; } + +/* ── Keyboard shortcuts cheatsheet ────────────────────────────────── */ +.kbd { display: inline-block; padding: 1px 6px; font-family: var(--font-mono); + font-size: .72rem; border: 1px solid var(--border-warm); + border-bottom-width: 2px; border-radius: 4px; background: var(--parchment); color: var(--ink); } +.shortcut-grid { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; font-size: .84rem; } +.shortcut-grid > div:nth-child(odd) { text-align: right; } + @@ -1018,38 +1257,109 @@