@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); } }