mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
* style: add subtle teal tint to dark mode surfaces Replace neutral gray surfaces with a teal-tinted palette across the app and website, giving Paseo a warmer, more recognizable feel. App uses a restrained tint (G-R ~3), website is slightly stronger (G-R ~6) as a brand showcase. * fix(opencode): handle message.part.delta events for assistant text streaming OpenCode v2 streams assistant text via `message.part.delta` events (with field "text" or "reasoning"), but the translator only handled `message.part.updated`. This caused assistant messages to be silently dropped during live streaming. * feat: show agent short ID in tab context menu and tooltip (#161) Add agent short ID to the "Copy agent id" menu item as trailing hint text and to the tab tooltip next to the title. Add leading icons to all workspace tab context menu items. * add batch close rpc for workspace tabs
343 lines
7.3 KiB
CSS
343 lines
7.3 KiB
CSS
@import "tailwindcss";
|
|
|
|
@keyframes voice-bar {
|
|
0% { transform: scaleY(1); }
|
|
100% { transform: scaleY(0.3); }
|
|
}
|
|
|
|
/* Title font - centralized for easy changes */
|
|
.font-title {
|
|
font-family: inherit;
|
|
}
|
|
|
|
/* Inline code styling - scoped to prose content */
|
|
.prose :not(pre) > code {
|
|
background-color: var(--color-muted);
|
|
padding: 0.125rem 0.375rem;
|
|
border-radius: 0.25rem;
|
|
font-size: 0.875em;
|
|
}
|
|
|
|
/* Markdown rendering styles for /changelog */
|
|
.changelog-markdown {
|
|
color: rgba(250, 250, 250, 0.82);
|
|
line-height: 1.7;
|
|
}
|
|
|
|
.changelog-markdown h1 {
|
|
color: var(--color-foreground);
|
|
font-size: 2rem;
|
|
line-height: 1.2;
|
|
font-weight: 600;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.changelog-markdown h2 {
|
|
color: var(--color-foreground);
|
|
font-size: 1.5rem;
|
|
line-height: 1.3;
|
|
font-weight: 600;
|
|
margin-top: 2rem;
|
|
margin-bottom: 0.75rem;
|
|
padding-bottom: 0.5rem;
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
.changelog-markdown h3 {
|
|
color: var(--color-foreground);
|
|
font-size: 1.125rem;
|
|
line-height: 1.4;
|
|
font-weight: 600;
|
|
margin-top: 1.5rem;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.changelog-markdown p {
|
|
margin-top: 0.5rem;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.changelog-markdown ul {
|
|
list-style: disc;
|
|
margin-left: 1.25rem;
|
|
margin-top: 0.75rem;
|
|
margin-bottom: 0.75rem;
|
|
display: grid;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.changelog-markdown li {
|
|
padding-left: 0.125rem;
|
|
}
|
|
|
|
.changelog-markdown a {
|
|
color: var(--color-foreground);
|
|
text-decoration: underline;
|
|
text-underline-offset: 2px;
|
|
}
|
|
|
|
.changelog-markdown a:hover {
|
|
color: rgba(250, 250, 250, 0.8);
|
|
}
|
|
|
|
/* Blog post prose styles — adapted from moboudra.com */
|
|
.blog-prose {
|
|
color: rgba(250, 250, 250, 0.82);
|
|
line-height: 1.8;
|
|
font-size: 1.125rem;
|
|
}
|
|
|
|
.blog-prose h1,
|
|
.blog-prose h2,
|
|
.blog-prose h3 {
|
|
color: var(--color-foreground);
|
|
font-weight: 600;
|
|
text-decoration: underline;
|
|
text-decoration-color: color-mix(in srgb, var(--color-primary) 50%, transparent);
|
|
text-decoration-thickness: 2px;
|
|
text-underline-offset: 4px;
|
|
}
|
|
|
|
.blog-prose h1,
|
|
.blog-prose h2 {
|
|
font-size: 1.5rem;
|
|
line-height: 1.3;
|
|
margin-top: 2.5rem;
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
|
|
.blog-prose h3 {
|
|
font-size: 1.25rem;
|
|
line-height: 1.4;
|
|
margin-top: 2rem;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.blog-prose p {
|
|
margin-top: 1rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.blog-prose a {
|
|
color: var(--color-foreground);
|
|
text-decoration: underline;
|
|
text-underline-offset: 2px;
|
|
}
|
|
|
|
.blog-prose a:hover {
|
|
color: var(--color-primary);
|
|
}
|
|
|
|
.blog-prose ul,
|
|
.blog-prose ol {
|
|
margin-top: 1rem;
|
|
margin-bottom: 1rem;
|
|
padding-left: 1.5rem;
|
|
}
|
|
|
|
.blog-prose ul {
|
|
list-style: disc;
|
|
}
|
|
|
|
.blog-prose ol {
|
|
list-style: decimal;
|
|
}
|
|
|
|
.blog-prose li {
|
|
margin-top: 0.25rem;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.blog-prose blockquote {
|
|
border-left: 3px solid var(--color-border);
|
|
padding-left: 1rem;
|
|
color: rgba(250, 250, 250, 0.6);
|
|
margin-top: 1rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.blog-prose pre {
|
|
background-color: var(--color-card);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 0.5rem;
|
|
padding: 1rem;
|
|
overflow-x: auto;
|
|
margin-top: 1rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.blog-prose :not(pre) > code {
|
|
background-color: var(--color-muted);
|
|
padding: 0.125rem 0.375rem;
|
|
border-radius: 0.25rem;
|
|
font-size: 0.875em;
|
|
}
|
|
|
|
.blog-prose img {
|
|
max-width: 100%;
|
|
border-radius: 0.5rem;
|
|
margin-top: 1rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.blog-prose hr {
|
|
border-color: var(--color-border);
|
|
margin-top: 2rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
@theme {
|
|
--color-background: #101615;
|
|
--color-foreground: #fafafa;
|
|
--color-muted: #252B2A;
|
|
--color-muted-foreground: #A8ADAC;
|
|
--color-card: #171D1C;
|
|
--color-border: #252B2A;
|
|
--color-primary: #3b82f6;
|
|
--color-primary-foreground: #ffffff;
|
|
--color-secondary: #252B2A;
|
|
--color-secondary-foreground: #fafafa;
|
|
|
|
/* Mockup palette (from app unistyles theme) */
|
|
--color-mock-surface0: #181B1A;
|
|
--color-mock-surface1: #1E2120;
|
|
--color-mock-surface2: #272A29;
|
|
--color-mock-surface3: #434645;
|
|
--color-mock-sidebar: #141716;
|
|
--color-mock-fg: #fafafa;
|
|
--color-mock-fg-muted: #A1A5A4;
|
|
--color-mock-border: #272A29;
|
|
--color-mock-border-accent: #313433;
|
|
--color-mock-accent: #20744A;
|
|
--color-mock-green: #22c55e;
|
|
--color-mock-green-400: #4ade80;
|
|
--color-mock-red: #ef4444;
|
|
--color-mock-amber: #f59e0b;
|
|
--color-mock-blue: #3b82f6;
|
|
--color-mock-zinc500: #71717a;
|
|
--color-mock-zinc600: #52525b;
|
|
--color-mock-diff-add: rgba(46, 160, 67, 0.15);
|
|
--color-mock-diff-remove: rgba(248, 81, 73, 0.1);
|
|
|
|
/* Syntax highlighting */
|
|
--color-syn-keyword: #ff7b72;
|
|
--color-syn-comment: #8b949e;
|
|
--color-syn-string: #a5d6ff;
|
|
--color-syn-number: #79c0ff;
|
|
--color-syn-function: #d2a8ff;
|
|
--color-syn-tag: #7ee787;
|
|
--color-syn-property: #79c0ff;
|
|
--color-syn-variable: #c9d1d9;
|
|
--color-syn-punctuation: #c9d1d9;
|
|
--color-syn-operator: #79c0ff;
|
|
|
|
--animate-flutter-left: flutter-left 0.6s ease-in-out infinite;
|
|
--animate-flutter-right: flutter-right 0.6s ease-in-out infinite;
|
|
--animate-float: float 8s ease-in-out infinite;
|
|
--animate-flutter-body: flutter-body 0.5s ease-in-out infinite;
|
|
--animate-synced-snake-dot: synced-snake-dot 950ms linear infinite;
|
|
}
|
|
|
|
/* Synced loader — 6-dot snake animation matching the real app.
|
|
Each dot runs this keyframe with a staggered delay so that at any moment
|
|
up to 4 dots are visible at decreasing opacity (head=1, trail=0.72/0.46/0.22).
|
|
steps(1,end) keeps each opacity level solid for its full 1/6-cycle slot. */
|
|
@keyframes synced-snake-dot {
|
|
0% { opacity: 1; animation-timing-function: steps(1, end); }
|
|
16.667% { opacity: 0.72; animation-timing-function: steps(1, end); }
|
|
33.333% { opacity: 0.46; animation-timing-function: steps(1, end); }
|
|
50% { opacity: 0.22; animation-timing-function: steps(1, end); }
|
|
66.667% { opacity: 0; animation-timing-function: steps(1, end); }
|
|
83.333% { opacity: 0; animation-timing-function: steps(1, end); }
|
|
}
|
|
|
|
@keyframes flutter-left {
|
|
0%,
|
|
100% {
|
|
transform: rotateY(0deg) rotateZ(0deg);
|
|
}
|
|
50% {
|
|
transform: rotateY(50deg) rotateZ(-5deg);
|
|
}
|
|
}
|
|
|
|
@keyframes flutter-right {
|
|
0%,
|
|
100% {
|
|
transform: rotateY(0deg) rotateZ(0deg);
|
|
}
|
|
50% {
|
|
transform: rotateY(-50deg) rotateZ(5deg);
|
|
}
|
|
}
|
|
|
|
@keyframes flutter-body {
|
|
0%,
|
|
100% {
|
|
transform: translateY(0) rotate(0deg);
|
|
}
|
|
50% {
|
|
transform: translateY(-2px) rotate(-3deg);
|
|
}
|
|
}
|
|
|
|
@keyframes float-1 {
|
|
0% {
|
|
transform: translate(0, 0) rotate(0deg);
|
|
}
|
|
20% {
|
|
transform: translate(12px, -18px) rotate(5deg);
|
|
}
|
|
40% {
|
|
transform: translate(-8px, -30px) rotate(-3deg);
|
|
}
|
|
60% {
|
|
transform: translate(-15px, -12px) rotate(2deg);
|
|
}
|
|
80% {
|
|
transform: translate(5px, 8px) rotate(-4deg);
|
|
}
|
|
100% {
|
|
transform: translate(0, 0) rotate(0deg);
|
|
}
|
|
}
|
|
|
|
@keyframes float-2 {
|
|
0% {
|
|
transform: translate(0, 0) rotate(0deg);
|
|
}
|
|
15% {
|
|
transform: translate(-10px, -12px) rotate(-4deg);
|
|
}
|
|
35% {
|
|
transform: translate(8px, -25px) rotate(3deg);
|
|
}
|
|
55% {
|
|
transform: translate(15px, -8px) rotate(-2deg);
|
|
}
|
|
75% {
|
|
transform: translate(-5px, 10px) rotate(5deg);
|
|
}
|
|
100% {
|
|
transform: translate(0, 0) rotate(0deg);
|
|
}
|
|
}
|
|
|
|
@keyframes float-3 {
|
|
0% {
|
|
transform: translate(0, 0) rotate(0deg);
|
|
}
|
|
25% {
|
|
transform: translate(18px, -10px) rotate(3deg);
|
|
}
|
|
50% {
|
|
transform: translate(5px, -35px) rotate(-5deg);
|
|
}
|
|
75% {
|
|
transform: translate(-12px, -15px) rotate(4deg);
|
|
}
|
|
100% {
|
|
transform: translate(0, 0) rotate(0deg);
|
|
}
|
|
}
|