Files
Sybil-2/web/src/index.css
T
buzzert ef3d79c428 Add persistent agent messaging and shared chat bubbles
Connect Sybil to the Pi root conversation with authenticated REST and WebSocket
APIs, persistent read state, and a dedicated agent tab. Keep optimistic messages
stable through delivery and retries, and animate arrivals without losing the
reader's scroll position.

Share bubble styling with regular chats and remove the obsolete admission sender.
Reject malformed upstream receipts and WebSocket upgrade requests, with regression
coverage and updated API documentation.

Validated with 51 web tests, 44 server tests, both production builds, desktop/mobile
bubble comparisons, and 11 browser animation and scrolling checks.
2026-10-14 12:20:11 -07:00

653 lines
14 KiB
CSS

@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Orbitron:wght@700;800;900&display=swap");
@tailwind base;
@tailwind components;
@tailwind utilities;
@font-face {
font-family: "StalinistOne";
src: url("/StalinistOne-Regular.ttf") format("truetype");
font-weight: 400;
font-style: normal;
font-display: swap;
}
:root {
color-scheme: dark;
--safe-area-top: env(safe-area-inset-top, 0px);
--safe-area-right: env(safe-area-inset-right, 0px);
--safe-area-bottom: env(safe-area-inset-bottom, 0px);
--safe-area-left: env(safe-area-inset-left, 0px);
--background: 235 45% 4%;
--foreground: 258 36% 96%;
--muted: 246 30% 13%;
--muted-foreground: 247 18% 68%;
--border: 251 35% 20%;
--input: 252 42% 24%;
--ring: 258 92% 70%;
--primary: 264 93% 66%;
--primary-foreground: 265 55% 98%;
--secondary: 244 32% 14%;
--secondary-foreground: 254 38% 94%;
--accent: 188 86% 50%;
--accent-foreground: 230 45% 8%;
--radius: 0px;
}
* {
@apply border-border;
scrollbar-color: hsl(263 92% 68% / 0.42) transparent;
scrollbar-width: thin;
}
html,
body,
#app {
height: 100%;
width: 100%;
}
@supports (height: 100dvh) {
html,
body,
#app {
height: 100dvh;
}
}
body {
@apply bg-background text-foreground antialiased;
background-color: hsl(var(--background));
background-image:
linear-gradient(90deg, hsl(187 92% 49% / 0.08), transparent 24%, hsl(264 92% 59% / 0.12) 74%, transparent),
linear-gradient(180deg, hsl(250 60% 16% / 0.68), hsl(235 45% 4%) 48%, hsl(235 54% 3%));
font-family: "Inter", "Avenir Next", "Segoe UI", sans-serif;
overflow: hidden;
overscroll-behavior: none;
}
button,
input,
select,
textarea {
font: inherit;
color-scheme: dark;
border-radius: var(--radius);
}
::selection {
background: hsl(264 92% 68% / 0.45);
color: hsl(258 36% 98%);
}
.sybil-wordmark {
font-family: "StalinistOne", "Orbitron", "Inter", sans-serif;
font-weight: 400;
letter-spacing: 0;
line-height: 1;
}
.app-grid-surface {
background-image:
linear-gradient(hsl(244 48% 20% / 0.18) 1px, transparent 1px),
linear-gradient(90deg, hsl(244 48% 20% / 0.14) 1px, transparent 1px);
background-size: 48px 48px;
}
.app-safe-frame {
padding: var(--safe-area-top) var(--safe-area-right) var(--safe-area-bottom) var(--safe-area-left);
}
.app-safe-pad {
padding:
max(1rem, var(--safe-area-top))
max(1rem, var(--safe-area-right))
max(1rem, var(--safe-area-bottom))
max(1rem, var(--safe-area-left));
}
.app-search-safe-pad {
padding:
max(1.5rem, var(--safe-area-top))
max(0.75rem, var(--safe-area-right))
max(1.5rem, var(--safe-area-bottom))
max(0.75rem, var(--safe-area-left));
}
.chat-settings-header {
padding:
calc(0.5rem + var(--safe-area-top))
max(0.75rem, var(--safe-area-right))
0.5rem
max(0.75rem, var(--safe-area-left));
}
.chat-settings-content {
padding:
1rem
max(1rem, var(--safe-area-right))
max(1.5rem, var(--safe-area-bottom))
max(1rem, var(--safe-area-left));
scroll-padding-block: 1rem;
}
.chat-settings-error {
padding:
0.75rem
max(1rem, var(--safe-area-right))
max(0.75rem, var(--safe-area-bottom))
max(1rem, var(--safe-area-left));
}
@media (min-width: 768px) {
.chat-settings-header,
.chat-settings-content {
padding: 1.25rem;
}
.chat-settings-error {
padding: 0.75rem 1.25rem;
}
.app-search-safe-pad {
padding:
max(1.5rem, var(--safe-area-top))
max(1.5rem, var(--safe-area-right))
max(1.5rem, var(--safe-area-bottom))
max(1.5rem, var(--safe-area-left));
}
}
@media (horizontal-viewport-segments: 2) {
.workspace-shell {
display: grid;
grid-template-columns:
calc(env(viewport-segment-width 0 0) - var(--safe-area-left))
calc(env(viewport-segment-width 1 0) - var(--safe-area-right));
column-gap: calc(env(viewport-segment-left 1 0) - env(viewport-segment-right 0 0));
}
.workspace-sidebar {
position: static;
width: 100%;
max-width: none;
transform: none;
}
.workspace-content {
min-width: 0;
touch-action: auto;
}
.workspace-sidebar-backdrop,
.workspace-sidebar-trigger {
display: none;
}
}
.glass-panel {
background:
linear-gradient(180deg, hsl(243 42% 12% / 0.88), hsl(236 48% 5% / 0.92)),
hsl(236 48% 6%);
box-shadow:
inset 0 1px 0 hsl(252 90% 86% / 0.08),
0 14px 36px hsl(240 80% 2% / 0.28);
}
/* Shared by regular chats and the persistent agent transcript. */
.message-bubble {
min-width: 0;
padding: 13px 17px;
border: 1px solid hsl(256 37% 57% / .18);
border-radius: 18px 18px 18px 5px;
background: linear-gradient(150deg, hsl(251 36% 15% / .93), hsl(244 35% 11% / .93));
box-shadow: 0 3px 12px hsl(239 55% 2% / .13);
font-size: 14px;
line-height: 1.68;
overflow-wrap: anywhere;
}
.message-bubble--user {
border-color: hsl(266 80% 72% / .3);
border-radius: 18px 18px 5px 18px;
background: linear-gradient(135deg, hsl(264 59% 33% / .86), hsl(259 58% 26% / .9));
color: hsl(265 55% 97%);
}
.message-bubble .md-content {
font-size: inherit;
line-height: inherit;
}
@media (max-width: 767px) {
.message-bubble {
padding: 11px 14px;
}
}
.tool-call-stack-shell {
perspective: 900px;
transform-style: preserve-3d;
isolation: isolate;
}
.tool-call-stack-card {
transform: translate3d(var(--tool-stack-x, 0), var(--tool-stack-y, 0), var(--tool-stack-z, 0)) scale(var(--tool-stack-scale, 1));
transform-origin: top left;
opacity: var(--tool-stack-opacity, 1);
transition:
opacity 180ms ease,
transform 300ms cubic-bezier(0.2, 0.8, 0.22, 1);
will-change: transform, opacity;
}
.tool-call-stack-shell-layout-a {
animation: tool-call-stack-height-a 340ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.tool-call-stack-shell-layout-b {
animation: tool-call-stack-height-b 340ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.tool-call-stack-card-layout-a {
animation: tool-call-stack-layout-a 340ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.tool-call-stack-card-layout-b {
animation: tool-call-stack-layout-b 340ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
}
.tool-call-stack-card-surface {
transform-origin: top left;
}
.tool-call-stack-card-glass {
backdrop-filter: none;
}
.tool-call-stack-card-enter {
animation: tool-call-stack-drop-in 320ms cubic-bezier(0.18, 0.95, 0.28, 1) backwards;
animation-delay: var(--tool-stack-delay, 0ms);
}
.tool-call-stack-toggle {
border: 1px solid hsl(188 82% 70% / 0.36);
background:
linear-gradient(180deg, hsl(230 36% 16% / 0.96), hsl(238 48% 7% / 0.96)),
hsl(236 48% 8%);
color: hsl(186 92% 86%);
box-shadow:
inset 0 1px 0 hsl(180 100% 88% / 0.08),
0 8px 22px hsl(235 72% 2% / 0.42);
transition:
border-color 160ms ease,
color 160ms ease,
transform 160ms ease,
filter 160ms ease;
}
.tool-call-stack-toggle:hover {
border-color: hsl(188 92% 74% / 0.62);
color: hsl(184 100% 92%);
filter: brightness(1.08);
}
.tool-call-stack-toggle:focus-visible {
outline: 2px solid hsl(188 92% 72% / 0.9);
outline-offset: 2px;
}
@keyframes tool-call-stack-height-a {
from {
height: var(--tool-stack-from-height);
}
to {
height: var(--tool-stack-to-height);
}
}
@keyframes tool-call-stack-height-b {
from {
height: var(--tool-stack-from-height);
}
to {
height: var(--tool-stack-to-height);
}
}
@keyframes tool-call-stack-layout-a {
from {
opacity: var(--tool-stack-from-opacity, 1);
transform: var(--tool-stack-from-transform);
}
to {
opacity: var(--tool-stack-to-opacity, 1);
transform: var(--tool-stack-to-transform);
}
}
@keyframes tool-call-stack-layout-b {
from {
opacity: var(--tool-stack-from-opacity, 1);
transform: var(--tool-stack-from-transform);
}
to {
opacity: var(--tool-stack-to-opacity, 1);
transform: var(--tool-stack-to-transform);
}
}
@keyframes tool-call-stack-drop-in {
from {
opacity: 0.72;
transform: translate3d(0, -0.65rem, 120px) scale(1.025) rotateX(3deg);
}
to {
opacity: 1;
transform: translate3d(0, 0, 0) scale(1) rotateX(0);
}
}
@media (prefers-reduced-motion: reduce) {
.tool-call-stack-card {
transition: none;
}
.tool-call-stack-shell-layout-a,
.tool-call-stack-shell-layout-b,
.tool-call-stack-card-layout-a,
.tool-call-stack-card-layout-b,
.tool-call-stack-card-enter {
animation: none;
}
}
.streaming-assistant-slot {
display: grid;
min-width: 0;
min-height: 1.82em;
align-items: start;
}
.streaming-assistant-layer {
grid-area: 1 / 1;
min-width: 0;
transform-origin: top left;
}
.ephemeral-thinking-trace {
position: relative;
z-index: 1;
color: hsl(252 35% 88% / 0.8);
font-style: italic;
opacity: 0.78;
filter: saturate(0.72);
will-change: opacity, transform, filter;
}
.ephemeral-thinking-trace-enter {
animation: ephemeral-thinking-trace-enter 200ms cubic-bezier(0.2, 0.78, 0.24, 1) both;
}
.ephemeral-thinking-trace-exit {
pointer-events: none;
animation: ephemeral-thinking-trace-exit 220ms cubic-bezier(0.4, 0, 0.8, 0.28) both;
}
.streaming-assistant-answer {
position: relative;
z-index: 2;
animation: streaming-assistant-answer-enter 180ms cubic-bezier(0.2, 0.78, 0.24, 1) both;
}
@keyframes ephemeral-thinking-trace-enter {
from {
opacity: 0;
filter: saturate(0.72) blur(1px);
transform: translate3d(0, 0.32rem, 0);
}
to {
opacity: 0.78;
filter: saturate(0.72) blur(0);
transform: translate3d(0, 0, 0);
}
}
@keyframes ephemeral-thinking-trace-exit {
from {
opacity: 0.78;
filter: saturate(0.72) blur(0);
transform: translate3d(0, 0, 0);
}
to {
opacity: 0;
filter: saturate(0.72) blur(1px);
transform: translate3d(0, -0.32rem, 0);
}
}
@keyframes streaming-assistant-answer-enter {
from {
opacity: 0;
transform: translate3d(0, 0.18rem, 0);
}
to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
@media (prefers-reduced-motion: reduce) {
.ephemeral-thinking-trace-enter,
.ephemeral-thinking-trace-exit,
.streaming-assistant-answer {
animation: none;
transform: none;
}
.ephemeral-thinking-trace-exit {
opacity: 0;
}
}
.md-content {
word-break: break-word;
}
.md-content > :first-child {
margin-top: 0;
}
.md-content > :last-child {
margin-bottom: 0;
}
.md-table-scroll {
max-width: 100%;
margin: 0.35rem 0 1rem;
overflow-x: auto;
overflow-y: hidden;
border: 1px solid hsl(var(--border) / 0.86);
border-radius: var(--radius);
background: hsl(246 34% 10% / 0.76);
box-shadow: inset 0 1px 0 hsl(258 80% 88% / 0.06);
}
.md-content table {
width: max-content;
min-width: 100%;
border-collapse: separate;
border-spacing: 0;
font-size: 0.94em;
line-height: 1.48;
}
.md-table-scroll::-webkit-scrollbar {
height: 0.45rem;
}
.md-table-scroll::-webkit-scrollbar-thumb {
border-radius: var(--radius);
background: hsl(263 78% 72% / 0.34);
}
.md-content th,
.md-content td {
padding: 0.48rem 0.7rem;
border-right: 1px solid hsl(var(--border) / 0.72);
border-bottom: 1px solid hsl(var(--border) / 0.7);
text-align: left;
vertical-align: top;
word-break: normal;
}
.md-content th:last-child,
.md-content td:last-child {
border-right: 0;
}
.md-content tr:last-child td {
border-bottom: 0;
}
.md-content th {
background: hsl(251 40% 15% / 0.92);
color: hsl(258 36% 98%);
font-weight: 700;
white-space: nowrap;
}
.md-content td {
color: hsl(258 34% 94% / 0.96);
}
.md-content tbody tr:nth-child(odd) td {
background: hsl(242 32% 10% / 0.58);
}
.md-content tbody tr:nth-child(even) td {
background: hsl(252 36% 13% / 0.46);
}
.md-content tbody tr:hover td {
background: hsl(263 46% 20% / 0.48);
}
.md-content p + p {
margin-top: 0.85rem;
}
.md-content h1,
.md-content h2,
.md-content h3 {
line-height: 1.25;
margin-top: 1.2rem;
margin-bottom: 0.45rem;
font-weight: 700;
}
.md-content h1 {
font-size: 1.45rem;
}
.md-content h2 {
font-size: 1.25rem;
}
.md-content h3 {
font-size: 1.1rem;
}
.md-content ul,
.md-content ol {
margin-top: 0.85rem;
margin-bottom: 0.85rem;
margin-left: 0;
padding-left: 0;
list-style: none;
}
.md-content li > ul,
.md-content li > ol {
margin-top: 0.3rem;
padding-left: 1.35rem;
}
.md-content ul > li {
position: relative;
padding-left: 1.1rem;
}
.md-content ul > li::before {
content: "";
position: absolute;
left: 0;
top: 0.76em;
width: 0.36rem;
height: 0.36rem;
border-radius: 9999px;
background: hsl(188 86% 62%);
box-shadow:
0 0 0 2px hsl(188 86% 62% / 0.12),
0 0 10px hsl(188 86% 62% / 0.42);
transform: translateY(-50%);
}
.md-content li + li {
margin-top: 0.3rem;
}
.md-content code {
background: hsl(249 40% 10% / 0.78);
border-radius: var(--radius);
padding: 0.05rem 0.3rem;
font-size: 0.86em;
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
}
.md-content pre {
overflow-x: auto;
border: 1px solid hsl(253 31% 29% / 0.72);
border-radius: var(--radius);
background: hsl(249 40% 10% / 0.82);
padding: 0.75rem;
box-shadow: inset 0 1px 0 hsl(258 80% 88% / 0.05);
}
.md-content pre code {
display: block;
background: transparent;
border-radius: 0;
padding: 0;
font-size: 0.88em;
line-height: 1.55;
white-space: pre;
}
.md-content a {
color: hsl(269 88% 76%);
text-decoration: underline;
}
.md-cite-token {
display: inline-flex;
align-items: center;
border-radius: var(--radius);
border: 1px solid hsl(274 40% 55%);
background: hsl(277 33% 21%);
color: hsl(304 42% 96%);
font-size: 0.72rem;
line-height: 1;
padding: 0.12rem 0.38rem;
vertical-align: baseline;
}