Thin 6px scrollbars using design tokens (--border, --muted-foreground) so they blend properly in both light and dark mode. Uses standard scrollbar-width/scrollbar-color plus WebKit pseudo-elements for cross-browser coverage.
530 lines
14 KiB
CSS
530 lines
14 KiB
CSS
@font-face {
|
|
font-family: 'Geist Sans';
|
|
src: url('/fonts/Geist-Variable.woff2') format('woff2');
|
|
font-weight: 100 900;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'Geist Mono';
|
|
src: url('/fonts/GeistMono-Variable.woff2') format('woff2');
|
|
font-weight: 100 900;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'Playfair Display';
|
|
src: url('/fonts/PlayfairDisplay-Variable.woff2') format('woff2');
|
|
font-weight: 400 900;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: 'Playfair Display';
|
|
src: url('/fonts/PlayfairDisplay-VariableItalic.woff2') format('woff2');
|
|
font-weight: 400 900;
|
|
font-style: italic;
|
|
font-display: swap;
|
|
}
|
|
|
|
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
@layer base {
|
|
:root {
|
|
/* Core palette — Indigo brand */
|
|
--background: 0 0% 99%;
|
|
--foreground: 240 6% 10%;
|
|
|
|
--card: 0 0% 100%;
|
|
--card-foreground: 240 6% 10%;
|
|
|
|
--popover: 0 0% 100%;
|
|
--popover-foreground: 240 6% 10%;
|
|
|
|
--primary: 239 84% 67%;
|
|
--primary-foreground: 0 0% 100%;
|
|
|
|
--secondary: 240 5% 96%;
|
|
--secondary-foreground: 240 4% 16%;
|
|
|
|
--muted: 240 5% 93%;
|
|
--muted-foreground: 240 4% 46%;
|
|
|
|
--accent: 226 100% 97%;
|
|
--accent-foreground: 239 84% 67%;
|
|
|
|
--destructive: 0 84% 60%;
|
|
--destructive-foreground: 0 0% 100%;
|
|
|
|
--border: 240 6% 90%;
|
|
--input: 240 6% 90%;
|
|
--ring: 239 84% 67%;
|
|
|
|
--radius: 0.375rem;
|
|
|
|
/* Extended indigo scale */
|
|
--indigo-50: 226 100% 97%;
|
|
--indigo-100: 228 96% 93%;
|
|
--indigo-200: 232 92% 86%;
|
|
--indigo-300: 235 88% 78%;
|
|
--indigo-400: 237 86% 72%;
|
|
--indigo-500: 239 84% 67%;
|
|
--indigo-600: 243 75% 59%;
|
|
--indigo-700: 245 58% 51%;
|
|
--indigo-800: 244 47% 42%;
|
|
--indigo-900: 242 47% 34%;
|
|
|
|
/* Status tokens — active */
|
|
--status-active-bg: 210 100% 95%;
|
|
--status-active-fg: 210 100% 40%;
|
|
--status-active-border: 210 100% 80%;
|
|
--status-active-dot: 210 100% 50%;
|
|
|
|
/* Status tokens — success */
|
|
--status-success-bg: 142 72% 94%;
|
|
--status-success-fg: 142 72% 29%;
|
|
--status-success-border: 142 72% 80%;
|
|
--status-success-dot: 142 72% 45%;
|
|
|
|
/* Status tokens — warning */
|
|
--status-warning-bg: 38 92% 95%;
|
|
--status-warning-fg: 38 92% 30%;
|
|
--status-warning-border: 38 92% 80%;
|
|
--status-warning-dot: 38 92% 50%;
|
|
|
|
/* Status tokens — error */
|
|
--status-error-bg: 0 84% 95%;
|
|
--status-error-fg: 0 84% 40%;
|
|
--status-error-border: 0 84% 80%;
|
|
--status-error-dot: 0 84% 50%;
|
|
|
|
/* Status tokens — neutral */
|
|
--status-neutral-bg: 240 5% 96%;
|
|
--status-neutral-fg: 240 4% 46%;
|
|
--status-neutral-border: 240 6% 90%;
|
|
--status-neutral-dot: 240 4% 46%;
|
|
|
|
/* Status tokens — urgent */
|
|
--status-urgent-bg: 270 91% 95%;
|
|
--status-urgent-fg: 270 91% 40%;
|
|
--status-urgent-border: 270 91% 80%;
|
|
--status-urgent-dot: 270 91% 55%;
|
|
|
|
/* Terminal tokens (always-dark aesthetic) */
|
|
--terminal-bg: 240 6% 7%;
|
|
--terminal-fg: 120 100% 80%;
|
|
--terminal-muted: 240 5% 55%;
|
|
--terminal-border: 240 4% 16%;
|
|
--terminal-selection: 239 84% 67%;
|
|
--terminal-system: 240 5% 55%;
|
|
--terminal-tool: 217 91% 60%;
|
|
--terminal-result: 142 72% 45%;
|
|
--terminal-error: 0 84% 60%;
|
|
--terminal-cursor: 120 100% 65%;
|
|
--terminal-selection-bg: 239 84% 67% / 0.25;
|
|
--terminal-link: 217 91% 70%;
|
|
--terminal-warning: 38 92% 60%;
|
|
--terminal-line-number: 240 5% 35%;
|
|
--terminal-ansi-black: 240 6% 7%;
|
|
--terminal-ansi-red: 0 84% 60%;
|
|
--terminal-ansi-green: 142 72% 45%;
|
|
--terminal-ansi-yellow: 38 92% 60%;
|
|
--terminal-ansi-blue: 217 91% 60%;
|
|
--terminal-ansi-magenta: 270 91% 65%;
|
|
--terminal-ansi-cyan: 195 80% 55%;
|
|
--terminal-ansi-white: 240 5% 85%;
|
|
|
|
/* Diff tokens */
|
|
--diff-add-bg: 142 72% 94%;
|
|
--diff-add-fg: 142 72% 29%;
|
|
--diff-add-border: 142 72% 80%;
|
|
--diff-remove-bg: 0 84% 95%;
|
|
--diff-remove-fg: 0 84% 40%;
|
|
--diff-remove-border: 0 84% 80%;
|
|
--diff-hunk-bg: 226 100% 97%;
|
|
|
|
/* Shadow tokens */
|
|
--shadow-xs: 0 1px 2px hsl(0 0% 0% / 0.04);
|
|
--shadow-sm: 0 1px 3px hsl(0 0% 0% / 0.06), 0 1px 2px hsl(0 0% 0% / 0.04);
|
|
--shadow-md: 0 4px 6px hsl(0 0% 0% / 0.06), 0 2px 4px hsl(0 0% 0% / 0.04);
|
|
--shadow-lg: 0 10px 15px hsl(0 0% 0% / 0.06), 0 4px 6px hsl(0 0% 0% / 0.04);
|
|
--shadow-xl: 0 20px 25px hsl(0 0% 0% / 0.08), 0 8px 10px hsl(0 0% 0% / 0.04);
|
|
|
|
/* Transition & animation tokens */
|
|
--duration-instant: 50ms;
|
|
--duration-fast: 100ms;
|
|
--duration-normal: 200ms;
|
|
--duration-slow: 350ms;
|
|
--duration-glacial: 500ms;
|
|
--ease-default: cubic-bezier(0.2, 0, 0, 1);
|
|
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
|
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
|
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
|
|
/* Spacing tokens */
|
|
--space-section: 2rem;
|
|
--space-section-lg: 3rem;
|
|
|
|
/* Background atmosphere */
|
|
--bg-gradient: radial-gradient(ellipse 80% 60% at 50% -10%, hsl(239 84% 67% / 0.04), transparent 70%);
|
|
|
|
/* Z-index scale */
|
|
--z-base: 0;
|
|
--z-raised: 1;
|
|
--z-sticky: 10;
|
|
--z-sidebar: 20;
|
|
--z-dropdown: 30;
|
|
--z-overlay: 40;
|
|
--z-modal: 50;
|
|
--z-toast: 60;
|
|
--z-command: 70;
|
|
--z-tooltip: 80;
|
|
}
|
|
|
|
.dark {
|
|
--background: 240 6% 7%;
|
|
--foreground: 240 5% 96%;
|
|
|
|
--card: 240 5% 11%;
|
|
--card-foreground: 240 5% 96%;
|
|
|
|
--popover: 240 5% 16%;
|
|
--popover-foreground: 240 5% 96%;
|
|
|
|
--primary: 239 84% 67%;
|
|
--primary-foreground: 0 0% 100%;
|
|
|
|
--secondary: 240 4% 16%;
|
|
--secondary-foreground: 240 5% 96%;
|
|
|
|
--muted: 240 4% 16%;
|
|
--muted-foreground: 240 5% 65%;
|
|
|
|
--accent: 239 40% 16%;
|
|
--accent-foreground: 239 84% 75%;
|
|
|
|
--destructive: 0 63% 31%;
|
|
--destructive-foreground: 0 0% 100%;
|
|
|
|
--border: 240 4% 16%;
|
|
--input: 240 4% 16%;
|
|
--ring: 239 84% 67%;
|
|
|
|
/* Surface level 3 for command palette */
|
|
--surface-3: 240 5% 21%;
|
|
|
|
/* Status tokens — dark mode */
|
|
--status-active-bg: 210 100% 12%;
|
|
--status-active-fg: 210 100% 70%;
|
|
--status-active-border: 210 100% 25%;
|
|
--status-active-dot: 210 100% 50%;
|
|
|
|
--status-success-bg: 142 72% 10%;
|
|
--status-success-fg: 142 72% 65%;
|
|
--status-success-border: 142 72% 22%;
|
|
--status-success-dot: 142 72% 45%;
|
|
|
|
--status-warning-bg: 38 92% 10%;
|
|
--status-warning-fg: 38 92% 65%;
|
|
--status-warning-border: 38 92% 22%;
|
|
--status-warning-dot: 38 92% 50%;
|
|
|
|
--status-error-bg: 0 84% 12%;
|
|
--status-error-fg: 0 84% 65%;
|
|
--status-error-border: 0 84% 25%;
|
|
--status-error-dot: 0 84% 50%;
|
|
|
|
--status-neutral-bg: 240 4% 16%;
|
|
--status-neutral-fg: 240 5% 65%;
|
|
--status-neutral-border: 240 4% 22%;
|
|
--status-neutral-dot: 240 5% 50%;
|
|
|
|
--status-urgent-bg: 270 91% 12%;
|
|
--status-urgent-fg: 270 91% 70%;
|
|
--status-urgent-border: 270 91% 25%;
|
|
--status-urgent-dot: 270 91% 55%;
|
|
|
|
/* Terminal tokens — dark mode */
|
|
--terminal-bg: 240 5% 11%;
|
|
--terminal-fg: 120 100% 80%;
|
|
--terminal-muted: 240 5% 55%;
|
|
--terminal-border: 240 4% 16%;
|
|
--terminal-selection: 239 84% 67%;
|
|
--terminal-system: 240 5% 55%;
|
|
--terminal-tool: 217 91% 60%;
|
|
--terminal-result: 142 72% 45%;
|
|
--terminal-error: 0 84% 60%;
|
|
--terminal-cursor: 120 100% 65%;
|
|
--terminal-selection-bg: 239 84% 67% / 0.25;
|
|
--terminal-link: 217 91% 70%;
|
|
--terminal-warning: 38 92% 60%;
|
|
--terminal-line-number: 240 5% 35%;
|
|
--terminal-ansi-black: 240 6% 7%;
|
|
--terminal-ansi-red: 0 84% 60%;
|
|
--terminal-ansi-green: 142 72% 45%;
|
|
--terminal-ansi-yellow: 38 92% 60%;
|
|
--terminal-ansi-blue: 217 91% 60%;
|
|
--terminal-ansi-magenta: 270 91% 65%;
|
|
--terminal-ansi-cyan: 195 80% 55%;
|
|
--terminal-ansi-white: 240 5% 85%;
|
|
|
|
/* Diff tokens — dark mode */
|
|
--diff-add-bg: 142 72% 10%;
|
|
--diff-add-fg: 142 72% 65%;
|
|
--diff-add-border: 142 72% 22%;
|
|
--diff-remove-bg: 0 84% 12%;
|
|
--diff-remove-fg: 0 84% 65%;
|
|
--diff-remove-border: 0 84% 25%;
|
|
--diff-hunk-bg: 239 40% 16%;
|
|
|
|
/* Background atmosphere — dark mode */
|
|
--bg-gradient: radial-gradient(ellipse 80% 60% at 50% -10%, hsl(239 84% 67% / 0.06), transparent 70%);
|
|
|
|
/* Shadow tokens — dark mode (inset highlights + ambient glow) */
|
|
--shadow-xs: none;
|
|
--shadow-sm: inset 0 1px 0 hsl(0 0% 100% / 0.04);
|
|
--shadow-md: inset 0 1px 0 hsl(0 0% 100% / 0.05), 0 2px 8px hsl(0 0% 0% / 0.3);
|
|
--shadow-lg: inset 0 1px 0 hsl(0 0% 100% / 0.06), 0 4px 16px hsl(0 0% 0% / 0.4);
|
|
--shadow-xl: inset 0 1px 0 hsl(0 0% 100% / 0.06), 0 8px 32px hsl(0 0% 0% / 0.5);
|
|
}
|
|
}
|
|
|
|
/* Keyframes */
|
|
@keyframes status-pulse {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.4; }
|
|
}
|
|
|
|
@keyframes shimmer {
|
|
0% { background-position: -200% 0; }
|
|
100% { background-position: 200% 0; }
|
|
}
|
|
|
|
@keyframes graph-layer-enter {
|
|
from { opacity: 0; transform: translateY(4px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
/* Global focus-visible styles */
|
|
*:focus-visible {
|
|
outline: 2px solid hsl(var(--ring));
|
|
outline-offset: 2px;
|
|
border-radius: var(--radius);
|
|
}
|
|
|
|
*:focus:not(:focus-visible) {
|
|
outline: none;
|
|
}
|
|
|
|
input:focus-visible,
|
|
textarea:focus-visible,
|
|
select:focus-visible {
|
|
outline: none;
|
|
box-shadow: 0 0 0 2px hsl(var(--background)), 0 0 0 4px hsl(var(--ring));
|
|
}
|
|
|
|
/* Reduced motion */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
*, *::before, *::after {
|
|
animation-duration: 0.01ms !important;
|
|
transition-duration: 0.01ms !important;
|
|
}
|
|
}
|
|
|
|
/* Custom scrollbars */
|
|
* {
|
|
scrollbar-width: thin;
|
|
scrollbar-color: hsl(var(--border)) transparent;
|
|
}
|
|
|
|
*:hover {
|
|
scrollbar-color: hsl(var(--muted-foreground) / 0.35) transparent;
|
|
}
|
|
|
|
::-webkit-scrollbar {
|
|
width: 6px;
|
|
height: 6px;
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
background: transparent;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
background-color: hsl(var(--border));
|
|
border-radius: 3px;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb:hover {
|
|
background-color: hsl(var(--muted-foreground) / 0.5);
|
|
}
|
|
|
|
::-webkit-scrollbar-corner {
|
|
background: transparent;
|
|
}
|
|
|
|
@layer base {
|
|
* {
|
|
@apply border-border;
|
|
}
|
|
body {
|
|
@apply bg-background text-foreground;
|
|
margin: 0;
|
|
min-width: 320px;
|
|
height: 100vh;
|
|
overflow: hidden;
|
|
background-image: var(--bg-gradient);
|
|
background-attachment: fixed;
|
|
}
|
|
}
|
|
|
|
/* Noise texture overlay */
|
|
body::before {
|
|
content: '';
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: -1;
|
|
opacity: 0.015;
|
|
pointer-events: none;
|
|
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
|
background-repeat: repeat;
|
|
background-size: 256px 256px;
|
|
}
|
|
|
|
.dark body::before {
|
|
opacity: 0.03;
|
|
}
|
|
|
|
/* Notion-style page link blocks inside the editor */
|
|
.page-link-block {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
width: 100%;
|
|
padding: 0.2rem 0.25rem;
|
|
border-radius: 0.25rem;
|
|
cursor: pointer;
|
|
color: hsl(var(--foreground));
|
|
font-size: 0.9375rem;
|
|
line-height: 1.4;
|
|
transition: background-color 0.15s;
|
|
}
|
|
|
|
.page-link-block:hover {
|
|
background-color: hsl(var(--muted));
|
|
}
|
|
|
|
.page-link-block svg {
|
|
color: hsl(var(--muted-foreground));
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Block selection highlight */
|
|
.ProseMirror .block-selected {
|
|
background-color: hsl(var(--primary) / 0.08);
|
|
border-radius: 0.25rem;
|
|
box-shadow: 0.375rem 0 0 hsl(var(--primary) / 0.08), -0.375rem 0 0 hsl(var(--primary) / 0.08);
|
|
}
|
|
.dark .ProseMirror .block-selected {
|
|
background-color: hsl(var(--primary) / 0.12);
|
|
box-shadow: 0.375rem 0 0 hsl(var(--primary) / 0.12), -0.375rem 0 0 hsl(var(--primary) / 0.12);
|
|
}
|
|
|
|
/* Hide cursor and text selection during block selection mode */
|
|
.ProseMirror.has-block-selection {
|
|
caret-color: transparent;
|
|
}
|
|
.ProseMirror.has-block-selection *::selection {
|
|
background: transparent;
|
|
}
|
|
|
|
/* Notion-style placeholder on empty blocks */
|
|
.ProseMirror .is-empty::before {
|
|
color: hsl(var(--muted-foreground));
|
|
content: attr(data-placeholder);
|
|
float: left;
|
|
height: 0;
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* Table wrapper overflow */
|
|
.ProseMirror .tableWrapper { overflow-x: auto; margin: 1em 0; }
|
|
|
|
/* Cell positioning for resize handles */
|
|
.ProseMirror table td, .ProseMirror table th { position: relative; min-width: 50px; vertical-align: top; }
|
|
|
|
/* Column resize handle */
|
|
.ProseMirror .column-resize-handle { position: absolute; right: -2px; top: 0; bottom: -2px; width: 4px; background-color: hsl(var(--primary) / 0.4); pointer-events: none; z-index: 20; }
|
|
|
|
/* Resize cursor */
|
|
.ProseMirror.resize-cursor { cursor: col-resize; }
|
|
|
|
/* Selected cell highlight */
|
|
.ProseMirror td.selectedCell, .ProseMirror th.selectedCell { background-color: hsl(var(--primary) / 0.08); }
|
|
.dark .ProseMirror td.selectedCell, .dark .ProseMirror th.selectedCell { background-color: hsl(var(--primary) / 0.15); }
|
|
|
|
/* Inline code styling — remove prose backtick pseudo-elements */
|
|
.ProseMirror :not(pre) > code {
|
|
background-color: hsl(var(--muted));
|
|
padding: 0.15em 0.35em;
|
|
border-radius: 0.25rem;
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
font-size: 0.875em;
|
|
}
|
|
.ProseMirror :not(pre) > code::before,
|
|
.ProseMirror :not(pre) > code::after {
|
|
content: none;
|
|
}
|
|
.dark .ProseMirror :not(pre) > code {
|
|
background-color: hsl(var(--muted));
|
|
}
|
|
|
|
/* Code block styling */
|
|
.ProseMirror pre {
|
|
background-color: hsl(var(--muted));
|
|
padding: 1rem;
|
|
border-radius: 0.375rem;
|
|
overflow-x: auto;
|
|
}
|
|
.ProseMirror pre code {
|
|
background: none;
|
|
padding: 0;
|
|
border-radius: 0;
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
font-size: 0.875em;
|
|
color: inherit;
|
|
}
|
|
.ProseMirror pre code::before,
|
|
.ProseMirror pre code::after {
|
|
content: none;
|
|
}
|
|
|
|
@layer utilities {
|
|
.card-hover-lift {
|
|
transition: transform var(--duration-normal) var(--ease-out),
|
|
box-shadow var(--duration-normal) var(--ease-out);
|
|
}
|
|
.card-hover-lift:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: var(--shadow-md);
|
|
}
|
|
|
|
.glow-active {
|
|
box-shadow: 0 0 8px hsl(var(--status-active-dot) / 0.4);
|
|
}
|
|
.glow-success {
|
|
box-shadow: 0 0 8px hsl(var(--status-success-dot) / 0.4);
|
|
}
|
|
.glow-error {
|
|
box-shadow: 0 0 8px hsl(var(--status-error-dot) / 0.4);
|
|
}
|
|
.glow-warning {
|
|
box-shadow: 0 0 8px hsl(var(--status-warning-dot) / 0.4);
|
|
}
|
|
}
|