diff --git a/frontend/assets/chat-empty-icon.png b/frontend/assets/chat-empty-icon.png new file mode 100644 index 0000000..106fbd1 Binary files /dev/null and b/frontend/assets/chat-empty-icon.png differ diff --git a/frontend/assets/ergou-avatar.png b/frontend/assets/ergou-avatar.png new file mode 100644 index 0000000..106fbd1 Binary files /dev/null and b/frontend/assets/ergou-avatar.png differ diff --git a/frontend/css/auth.css b/frontend/css/auth.css new file mode 100644 index 0000000..5c5ba51 --- /dev/null +++ b/frontend/css/auth.css @@ -0,0 +1,227 @@ +.entry-screen { + position: fixed; + inset: 0; + z-index: 50; + overflow: hidden; + background: + radial-gradient(circle at 64% 24%, color-mix(in oklch, var(--blue) 46%, transparent), transparent 28%), + radial-gradient(circle at 20% 78%, color-mix(in oklch, var(--green) 34%, transparent), transparent 34%), + linear-gradient(135deg, oklch(14% 0.04 232), oklch(18% 0.05 178) 48%, oklch(11% 0.038 250)); + color: oklch(96% 0.018 190); + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(280px, 390px); + gap: clamp(24px, 5vw, 76px); + align-items: end; + padding: clamp(24px, 6vw, 78px); + transition: transform 0.72s cubic-bezier(0.74, 0, 0.2, 1), opacity 0.72s ease; +} + +.entry-screen.leaving { + transform: translateY(-102%); + opacity: 0.42; +} + +.entry-grid, +.entry-scan, +.entry-orbit, +.entry-particles { + position: absolute; + inset: 0; + pointer-events: none; +} + +.entry-grid { + background: + linear-gradient(color-mix(in oklch, white 7%, transparent) 1px, transparent 1px), + linear-gradient(90deg, color-mix(in oklch, white 7%, transparent) 1px, transparent 1px); + background-size: 72px 72px; + mask-image: radial-gradient(circle at 58% 46%, black, transparent 76%); +} + +.entry-scan { + width: 42%; + background: linear-gradient(90deg, transparent, color-mix(in oklch, var(--blue) 24%, transparent), transparent); + animation: scan-drift 5.6s linear infinite; + opacity: 0.68; +} + +.entry-orbit { + inset: 7% 12% 10% auto; + width: min(58vw, 720px); + aspect-ratio: 1; + border-radius: 50%; + border: 1px solid color-mix(in oklch, white 13%, transparent); + animation: orbit-spin 18s linear infinite; +} + +.entry-orbit::before, +.entry-orbit::after, +.entry-orbit span { + content: ""; + position: absolute; + inset: 9%; + border: 1px solid color-mix(in oklch, var(--green) 16%, transparent); + border-radius: 50%; +} + +.entry-orbit::after { + inset: 22%; + border-color: color-mix(in oklch, var(--blue) 20%, transparent); +} + +.entry-orbit span { + width: 9px; + height: 9px; + inset: 17% auto auto 68%; + border: 0; + background: oklch(87% 0.1 186); + box-shadow: 0 0 24px color-mix(in oklch, var(--blue) 72%, transparent); +} + +.entry-orbit span:nth-child(2) { + inset: 58% auto auto 18%; + background: oklch(86% 0.11 154); +} + +.entry-orbit span:nth-child(3) { + inset: 76% auto auto 72%; + background: oklch(92% 0.08 74); +} + +.entry-particles span { + position: absolute; + width: 2px; + height: 44px; + border-radius: 999px; + background: linear-gradient(180deg, transparent, color-mix(in oklch, white 58%, transparent)); + animation: particle-rise 4.6s linear infinite; + opacity: 0.55; +} + +.entry-particles span:nth-child(1) { left: 12%; top: 82%; animation-delay: -1.1s; } +.entry-particles span:nth-child(2) { left: 26%; top: 66%; animation-delay: -2.4s; } +.entry-particles span:nth-child(3) { left: 39%; top: 76%; animation-delay: -0.6s; } +.entry-particles span:nth-child(4) { left: 50%; top: 84%; animation-delay: -3.2s; } +.entry-particles span:nth-child(5) { left: 64%; top: 70%; animation-delay: -1.8s; } +.entry-particles span:nth-child(6) { left: 78%; top: 80%; animation-delay: -2.8s; } +.entry-particles span:nth-child(7) { left: 88%; top: 58%; animation-delay: -0.3s; } +.entry-particles span:nth-child(8) { left: 18%; top: 44%; animation-delay: -3.8s; } +.entry-particles span:nth-child(9) { left: 72%; top: 36%; animation-delay: -1.5s; } +.entry-particles span:nth-child(10) { left: 92%; top: 72%; animation-delay: -4.2s; } + +.entry-copy, +.entry-hud, +.entry-lift { + position: relative; + z-index: 1; +} + +.entry-copy { + max-width: 760px; + align-self: center; +} + +.entry-brand { + display: inline-flex; + align-items: center; + gap: 12px; + margin-bottom: 24px; +} + +.entry-brand span { + color: color-mix(in oklch, white 72%, transparent); + font-weight: 800; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.entry-copy h1 { + max-width: 850px; + margin: 10px 0 18px; + font-size: clamp(3.2rem, 8vw, 8rem); + line-height: 0.92; + letter-spacing: 0; +} + +.entry-lead { + max-width: 58ch; + margin: 0; + color: color-mix(in oklch, white 70%, transparent); + font-size: 1.02rem; + line-height: 1.8; +} + +.entry-hud { + align-self: center; + border: 1px solid color-mix(in oklch, white 18%, transparent); + border-radius: var(--radius); + background: color-mix(in oklch, oklch(12% 0.04 236) 72%, transparent); + backdrop-filter: blur(18px); + box-shadow: 0 26px 90px color-mix(in oklch, black 38%, transparent); + overflow: hidden; +} + +.entry-hud div { + padding: 18px; + border-top: 1px solid color-mix(in oklch, white 12%, transparent); +} + +.entry-hud div:first-child { + border-top: 0; +} + +.entry-hud span { + color: color-mix(in oklch, white 56%, transparent); + font-size: 0.76rem; +} + +.entry-hud strong { + display: block; + margin-top: 8px; + font-size: 1.05rem; +} + +.entry-lift { + position: absolute; + left: 50%; + bottom: 24px; + transform: translateX(-50%); + min-width: 154px; + min-height: 48px; + border: 1px solid color-mix(in oklch, white 24%, transparent); + border-radius: 999px; + background: color-mix(in oklch, white 10%, transparent); + color: oklch(96% 0.018 190); + backdrop-filter: blur(16px); + display: inline-flex; + align-items: center; + justify-content: center; + gap: 10px; + box-shadow: 0 14px 42px color-mix(in oklch, black 24%, transparent); + animation: lift-pulse 1.6s ease-in-out infinite; +} + +.entry-lift:hover { + border-color: color-mix(in oklch, var(--blue) 54%, white 14%); + background: color-mix(in oklch, var(--blue) 22%, transparent); +} + +@keyframes scan-drift { + from { transform: translateX(-55vw) skewX(-16deg); } + to { transform: translateX(122vw) skewX(-16deg); } +} + +@keyframes orbit-spin { + to { transform: rotate(360deg); } +} + +@keyframes particle-rise { + from { transform: translateY(60px); opacity: 0; } + 20% { opacity: 0.58; } + to { transform: translateY(-180px); opacity: 0; } +} + +@keyframes lift-pulse { + 0%, 100% { transform: translateX(-50%) translateY(0); } + 50% { transform: translateX(-50%) translateY(-7px); } +} diff --git a/frontend/css/base.css b/frontend/css/base.css index aa793bc..927025a 100644 --- a/frontend/css/base.css +++ b/frontend/css/base.css @@ -1,15 +1,15 @@ :root { - --bg: oklch(96% 0.014 142); - --surface: oklch(99% 0.006 142); - --surface-soft: oklch(97.5% 0.011 142); - --surface-raised: oklch(100% 0.004 142); - --ink: oklch(22% 0.025 148); - --muted: oklch(49% 0.027 148); - --line: oklch(89% 0.018 142); - --line-strong: oklch(80% 0.026 142); + --bg: oklch(96.5% 0.012 156); + --surface: oklch(99% 0.004 156); + --surface-soft: oklch(97.2% 0.01 156); + --surface-raised: oklch(100% 0.003 156); + --ink: oklch(22% 0.025 158); + --muted: oklch(48% 0.025 166); + --line: oklch(88% 0.017 160); + --line-strong: oklch(77% 0.034 168); --green: oklch(48% 0.105 154); - --green-dark: oklch(38% 0.092 154); - --blue: oklch(49% 0.105 230); + --green-dark: oklch(36% 0.092 154); + --blue: oklch(51% 0.112 222); --coral: oklch(53% 0.135 34); --amber: oklch(55% 0.12 72); --success-bg: oklch(93% 0.035 151); @@ -46,7 +46,8 @@ body { } button, -textarea { +textarea, +input { font: inherit; } @@ -61,17 +62,25 @@ button:disabled { button:focus-visible, textarea:focus-visible, +input:focus-visible, summary:focus-visible { outline: 3px solid color-mix(in oklch, var(--green) 42%, transparent); outline-offset: 2px; } -.shell { +.app-root { width: 100vw; height: 100vh; height: 100dvh; min-height: 0; overflow: hidden; +} + +.shell { + width: 100%; + height: 100%; + min-height: 0; + overflow: hidden; display: grid; grid-template-columns: 248px 1fr; } @@ -81,8 +90,10 @@ summary:focus-visible { min-height: 0; overflow-y: auto; padding: 22px 16px; - background: oklch(23% 0.032 148); - color: oklch(96% 0.014 142); + background: + linear-gradient(180deg, color-mix(in oklch, oklch(20% 0.034 160) 96%, var(--green) 4%), oklch(18% 0.026 166)), + oklch(20% 0.034 160); + color: oklch(96% 0.014 154); display: flex; flex-direction: column; gap: 24px; @@ -97,13 +108,14 @@ summary:focus-visible { } .brand-mark { - width: 42px; - height: 42px; + width: 46px; + height: 46px; border-radius: var(--radius); - background: oklch(90% 0.055 138); - color: oklch(23% 0.032 148); + background: linear-gradient(135deg, oklch(91% 0.06 154), oklch(88% 0.05 218)); + color: oklch(21% 0.032 160); display: grid; place-items: center; + font-size: 0.9rem; font-weight: 800; } diff --git a/frontend/css/chat.css b/frontend/css/chat.css index 53f8551..2263d6c 100644 --- a/frontend/css/chat.css +++ b/frontend/css/chat.css @@ -19,9 +19,15 @@ .empty-state { max-width: 460px; + padding: 28px; + border: 1px solid var(--line); + border-radius: var(--radius); + background: color-mix(in oklch, var(--surface-raised) 84%, transparent); + backdrop-filter: blur(10px); margin: auto; text-align: center; color: var(--muted); + box-shadow: 0 16px 44px color-mix(in oklch, var(--ink) 8%, transparent); } .empty-state p { @@ -53,19 +59,22 @@ background: var(--surface-soft); } -.empty-state i { - width: 54px; - height: 54px; - display: inline-grid; - place-items: center; - border-radius: var(--radius); - background: #e6efe7; - color: var(--green); - font-size: 1.5rem; +.empty-state-icon { + width: 96px; + height: 96px; + border: 1px solid color-mix(in oklch, var(--blue) 28%, var(--line)); + border-radius: 24px; + display: inline-block; + object-fit: cover; + object-position: center; + background: var(--surface-soft); + box-shadow: + 0 12px 30px rgba(34, 44, 38, 0.14), + 0 0 0 8px color-mix(in oklch, var(--blue) 7%, transparent); } .empty-state h3 { - margin: 16px 0 8px; + margin: 8px 0; color: var(--ink); } @@ -96,6 +105,16 @@ justify-content: flex-end; } +.agent-role-avatar { + width: 26px; + height: 26px; + border: 1px solid color-mix(in oklch, var(--blue) 22%, var(--line)); + border-radius: 8px; + object-fit: cover; + object-position: center; + box-shadow: 0 4px 12px color-mix(in oklch, var(--ink) 10%, transparent); +} + .message-role button, .icon-danger, .history-drawer header button { @@ -111,10 +130,11 @@ padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--radius); - background: var(--surface); + background: color-mix(in oklch, var(--surface) 94%, transparent); line-height: 1.65; overflow-wrap: anywhere; box-shadow: 0 3px 16px rgba(34, 44, 38, 0.05); + backdrop-filter: blur(8px); } .from-user .message-bubble { diff --git a/frontend/css/overlays.css b/frontend/css/overlays.css index d7fd3fd..8b7df63 100644 --- a/frontend/css/overlays.css +++ b/frontend/css/overlays.css @@ -104,6 +104,21 @@ border-radius: 999px; } +.composer textarea { + overflow: hidden !important; + scrollbar-width: none !important; +} + +.composer textarea::-webkit-scrollbar { + width: 0; + height: 0; + display: none; +} + +.composer textarea::-webkit-scrollbar-thumb { + background: transparent; +} + .skeleton-stack { padding: var(--space-md); display: grid; diff --git a/frontend/css/responsive.css b/frontend/css/responsive.css index 2ac7c2a..c02fa70 100644 --- a/frontend/css/responsive.css +++ b/frontend/css/responsive.css @@ -54,3 +54,112 @@ padding: 0 10px; } } + +@media (max-width: 760px) { + .entry-screen { + grid-template-columns: 1fr; + overflow-y: auto; + align-items: center; + } + + .entry-copy h1 { + font-size: clamp(3rem, 16vw, 5rem); + } + + .entry-hud { + display: none; + } +} + +@media (max-width: 560px) { + .entry-screen { + padding: 22px; + } + + .entry-copy { + align-self: center; + } + + .entry-lead { + font-size: 0.95rem; + } + + .shell { + grid-template-columns: 1fr; + grid-template-rows: auto 1fr; + } + + .rail { + max-height: 72px; + overflow: hidden; + padding: 10px 12px; + flex-direction: row; + align-items: center; + gap: 12px; + } + + .brand { + min-width: 54px; + padding: 0; + border-bottom: 0; + } + + .nav-list { + display: flex; + flex: 1; + overflow-x: auto; + } + + .nav-list button, + .secondary-action, + .danger-action { + min-width: 42px; + } + + .rail-actions { + margin-top: 0; + display: flex; + gap: 8px; + } + + .rail-actions .secondary-action, + .rail-actions .danger-action { + width: 42px; + padding: 0; + flex: 0 0 42px; + } + + .workspace { + height: calc(100dvh - 72px); + grid-template-rows: auto 1fr; + } + + .topbar { + align-items: flex-start; + flex-direction: column; + } + + .topbar-status { + width: 100%; + overflow-x: auto; + } + + .chat-stream, + .panel-view { + padding: 14px; + } + + .composer { + margin: 0 14px 14px; + } + + .section-head, + .review-item header { + flex-direction: column; + } + + .table-row { + grid-template-columns: minmax(120px, 1fr) 56px 44px 42px; + gap: 8px; + } +} diff --git a/frontend/css/trace-composer.css b/frontend/css/trace-composer.css index 27619fb..8afd6c1 100644 --- a/frontend/css/trace-composer.css +++ b/frontend/css/trace-composer.css @@ -88,12 +88,22 @@ .composer textarea { width: 100%; max-height: 180px; - min-height: 42px; + min-height: 46px; + line-height: 1.35; resize: none; + overflow: hidden; + scrollbar-width: none; + appearance: none; border: 0; outline: 0; - padding: 10px 0; + padding: 13px 0 10px; background: transparent; color: var(--ink); } +.composer textarea::-webkit-scrollbar { + width: 0; + height: 0; + display: none; +} + diff --git a/frontend/css/workspace.css b/frontend/css/workspace.css index 0176748..ddb76a4 100644 --- a/frontend/css/workspace.css +++ b/frontend/css/workspace.css @@ -7,13 +7,18 @@ overflow: hidden; display: grid; grid-template-rows: 76px 1fr; - background: var(--surface-soft); + background: + linear-gradient(135deg, color-mix(in oklch, var(--green) 7%, transparent), transparent 34%), + linear-gradient(45deg, transparent 54%, color-mix(in oklch, var(--blue) 6%, transparent)), + repeating-linear-gradient(90deg, color-mix(in oklch, var(--ink) 4%, transparent) 0 1px, transparent 1px 56px), + repeating-linear-gradient(0deg, color-mix(in oklch, var(--ink) 3%, transparent) 0 1px, transparent 1px 56px), + var(--surface-soft); } .topbar { padding: 16px 28px; border-bottom: 1px solid var(--line); - background: color-mix(in oklch, var(--surface-raised) 88%, transparent); + background: color-mix(in oklch, var(--surface-raised) 90%, transparent); backdrop-filter: blur(12px); display: flex; align-items: center; diff --git a/frontend/index.html b/frontend/index.html index 3baa46b..e36bbfd 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -4,7 +4,7 @@