main
css 222 lines 6.81 KB
Raw
1 @import 'tailwindcss';
2 @plugin '@tailwindcss/typography';
3
4 @custom-variant dark (&:where(.dark, .dark *));
5
6 /* Self-hosted fonts — no external CDN dependency */
7 @font-face {
8 font-family: 'Manrope';
9 font-style: normal;
10 font-weight: 500 800;
11 font-display: swap;
12 src: url('/fonts/manrope-latin.woff2') format('woff2');
13 unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
14 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
15 U+FEFF, U+FFFD;
16 }
17
18 @font-face {
19 font-family: 'Open Sans';
20 font-style: normal;
21 font-weight: 400 700;
22 font-display: swap;
23 src: url('/fonts/opensans-latin.woff2') format('woff2');
24 unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
25 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
26 U+FEFF, U+FFFD;
27 }
28
29 @theme {
30 /* Fonts — Tailwind v4 tokens: --font-* maps to font-* utility */
31 --font-display: 'Manrope', sans-serif;
32 --font-sans: 'Open Sans', sans-serif;
33
34 /* Radius — match React frontend tokens (only xl needed; lg/base omitted to avoid doc page breakage) */
35 --radius-xl: 1.75rem;
36
37 /* Primary: cyan/teal from relay */
38 --color-primary: oklch(75% 0.14 195);
39 --color-primary-light: oklch(80% 0.14 195);
40
41 /* Map CSS custom properties to Tailwind color tokens for opacity modifier support */
42 --color-background: var(--background);
43 --color-foreground: var(--foreground);
44 --color-secondary: var(--secondary);
45 --color-border: var(--border);
46 --color-text-muted: var(--text-muted);
47 }
48
49 /* Layout tokens */
50 :root {
51 --header-h: 6.5rem; /* 104px — matches sticky header outer height (py-5 + py-2 + content) */
52 --gradient-primary-fade: linear-gradient(to right, oklch(75% 0.14 195 / 0.55), transparent);
53 }
54
55 /* Hero & landing page custom properties (not in @theme — used via var() in inline styles) */
56 :root {
57 --background: oklch(97% 0.005 250);
58 --foreground: oklch(25% 0.02 250);
59 --secondary: oklch(92% 0.01 250);
60 --border: oklch(90% 0.01 250);
61 --text-muted: oklch(55% 0.03 250);
62 --accent-orange: oklch(60% 0.2 35);
63 --accent-magenta: oklch(50% 0.22 350);
64 --neon-cyan: oklch(75% 0.14 195);
65 --hero-grid-dot: oklch(75% 0.14 195 / 0.18);
66 --hero-gradient-start: var(--accent-orange);
67 --hero-gradient-mid: var(--neon-cyan);
68 --hero-gradient-end: var(--accent-magenta);
69 --hero-terminal-bg: linear-gradient(160deg, oklch(19% 0.005 250 / 0.98), oklch(14% 0.008 250 / 0.98));
70 --hero-terminal-border: oklch(75% 0.14 195 / 0.22);
71 --hero-terminal-foreground: oklch(98% 0.01 0);
72 --hero-terminal-accent: var(--neon-cyan);
73 --hero-terminal-shadow: oklch(15% 0 0 / 0.18);
74 }
75
76 .dark {
77 --background: oklch(15% 0 0);
78 --foreground: oklch(98% 0.01 0);
79 --secondary: oklch(25% 0.02 195);
80 --border: oklch(100% 0 0 / 0.1);
81 --text-muted: oklch(65% 0.02 0);
82 --accent-orange: oklch(65% 0.2 35);
83 --accent-magenta: oklch(55% 0.25 350);
84 --neon-cyan: oklch(80% 0.14 195);
85 --hero-grid-dot: oklch(80% 0.14 195 / 0.22);
86 --hero-gradient-start: var(--neon-cyan);
87 --hero-gradient-mid: var(--accent-magenta);
88 --hero-gradient-end: var(--accent-orange);
89 --hero-terminal-bg: linear-gradient(160deg, oklch(19% 0 0 / 0.78), oklch(12% 0.01 250 / 0.88));
90 --hero-terminal-border: oklch(80% 0.14 195 / 0.3);
91 --hero-terminal-foreground: oklch(98% 0.01 0);
92 --hero-terminal-accent: var(--neon-cyan);
93 --hero-terminal-shadow: oklch(0% 0 0 / 0.28);
94 }
95
96 /* Global border color reset (matches React frontend) */
97 @layer base {
98 * {
99 border-color: var(--border);
100 }
101 }
102
103 /* Base styles */
104 body {
105 font-family: var(--font-sans);
106 color: oklch(25% 0.02 250);
107 background:
108 radial-gradient(circle at top center, oklch(75% 0.14 195 / 0.16), transparent 36%),
109 radial-gradient(circle at 12% 18%, oklch(60% 0.2 35 / 0.08), transparent 22%),
110 linear-gradient(180deg, oklch(100% 0 0) 0%, oklch(97% 0.005 250) 54%, oklch(95% 0.005 250) 100%);
111 background-attachment: fixed;
112 }
113
114 .dark body {
115 color: oklch(90% 0.005 250);
116 background:
117 radial-gradient(circle at top center, oklch(80% 0.14 195 / 0.16), transparent 32%),
118 radial-gradient(circle at 82% 10%, oklch(55% 0.25 350 / 0.12), transparent 20%),
119 linear-gradient(180deg, oklch(16% 0 0) 0%, oklch(13% 0.01 250) 54%, oklch(11% 0.01 250) 100%);
120 background-attachment: fixed;
121 }
122
123 h1, h2, h3, h4, h5, h6 {
124 font-family: var(--font-display);
125 letter-spacing: -0.03em;
126 }
127
128 /* Prose overrides */
129 .prose {
130 font-family: var(--font-sans);
131 }
132
133 .prose :where(h1, h2, h3, h4, h5, h6):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
134 font-family: var(--font-display);
135 letter-spacing: -0.03em;
136 }
137
138 /* Prose links — primary cyan */
139 .prose :where(a):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
140 color: var(--color-primary);
141 text-decoration: underline;
142 text-underline-offset: 2px;
143 }
144
145 .dark .prose :where(a):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
146 color: var(--color-primary-light);
147 }
148
149 /* Inline code */
150 .prose :where(code):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
151 background-color: oklch(92% 0.02 195 / 0.3);
152 padding: 0.125rem 0.375rem;
153 border-radius: 0.25rem;
154 font-size: 0.875em;
155 border: 1px solid oklch(75% 0.14 195 / 0.15);
156 }
157
158 .dark .prose :where(code):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
159 background-color: oklch(75% 0.14 195 / 0.1);
160 border-color: oklch(75% 0.14 195 / 0.2);
161 }
162
163 /* Reset inline code styles inside code blocks */
164 .prose :where(pre code):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
165 background-color: transparent;
166 padding: 0;
167 border-radius: 0;
168 border: none;
169 font-size: inherit;
170 }
171
172 /* Code blocks — relay terminal aesthetic */
173 .prose :where(pre):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
174 background-color: oklch(20% 0.005 250);
175 border-radius: 0.75rem;
176 overflow-x: auto;
177 padding: 0.75rem 1rem;
178 border: 1px solid oklch(100% 0 0 / 0.05);
179 }
180
181 /* When wrapped by copy-code action, move radius/border to wrapper */
182 [data-copy-wrapper] {
183 border-radius: 0.75rem;
184 overflow: hidden;
185 border: 1px solid oklch(100% 0 0 / 0.05);
186 background-color: oklch(20% 0.005 250);
187 }
188
189 .dark [data-copy-wrapper] {
190 border-color: oklch(100% 0 0 / 0.1);
191 background-color: oklch(14% 0.008 250);
192 }
193
194 [data-copy-wrapper] pre {
195 border-radius: 0 !important;
196 border: none !important;
197 }
198
199 .dark .prose :where(pre):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
200 background-color: oklch(14% 0.008 250);
201 border-color: oklch(100% 0 0 / 0.1);
202 }
203
204 /* Blockquote — primary cyan left border */
205 .prose :where(blockquote):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
206 border-left-color: var(--color-primary);
207 }
208
209 /* Dark mode table borders */
210 .dark .prose :where(th, td):not(:where([class~='not-prose'], [class~='not-prose'] *)) {
211 border-color: oklch(100% 0 0 / 0.1);
212 }
213
214 /* Code block scrollbar */
215 .prose pre::-webkit-scrollbar {
216 height: 6px;
217 }
218
219 .prose pre::-webkit-scrollbar-thumb {
220 background: oklch(50% 0.02 250);
221 border-radius: 3px;
222 }