globals.css513 lines · main
1@import 'config/tailwind.config.css';
2@import './../../../packages/studio/ui/build/css/themes/classic-dark.css';
3@import 'config/typography.css';
4
5@source '../pages/**/*.{js,ts,jsx,tsx}';
6@source '../components/**/*.{js,ts,jsx,tsx}';
7@source './../../../packages/studio/ui/src/**/*.{tsx,ts,js}';
8@source './../../../packages/studio/ui-patterns/src/**/*.{tsx,ts,js}';
9
10@theme {
11 --text-grid: 13px;
12
13 --color-typography-body-light: hsl(var(--foreground-light));
14 --color-typography-body-dark: hsl(var(--foreground-light));
15 --color-typography-body-secondary-light: hsl(var(--foreground-lighter));
16 --color-typography-body-secondary-dark: hsl(var(--foreground-lighter));
17 --color-typography-body-strong-light: hsl(var(--foreground-default));
18 --color-typography-body-strong-dark: hsl(var(--foreground-default));
19 --color-typography-body-faded-light: hsl(var(--foreground-muted));
20 --color-typography-body-faded-dark: hsl(var(--foreground-muted));
21
22 --color-table-body-light: hsl(var(--background-default));
23 --color-table-body-dark: hsl(var(--background-default));
24 --color-table-header-light: hsl(var(--background-surface-100));
25 --color-table-header-dark: hsl(var(--background-surface-100));
26 --color-table-footer-light: hsl(var(--background-surface-100));
27 --color-table-footer-dark: hsl(var(--background-surface-100));
28 --color-table-border-light: hsl(var(--border-default));
29 --color-table-border-dark: hsl(var(--border-default));
30
31 --color-panel-body-light: hsl(var(--background-surface-100));
32 --color-panel-body-dark: hsl(var(--background-surface-100));
33 --color-panel-header-light: hsl(var(--background-surface-100));
34 --color-panel-header-dark: hsl(var(--background-surface-100));
35 --color-panel-footer-light: hsl(var(--background-surface-100));
36 --color-panel-footer-dark: hsl(var(--background-surface-100));
37 --color-panel-border-light: hsl(var(--border-default));
38 --color-panel-border-dark: hsl(var(--border-default));
39 --color-panel-border-interior-light: hsl(var(--border-muted));
40 --color-panel-border-interior-dark: hsl(var(--border-muted));
41 --color-panel-border-hover-light: hsl(var(--border-muted));
42 --color-panel-border-hover-dark: hsl(var(--border-muted));
43
44 --animate-shimmer: shimmer 2s infinite linear;
45 --animate-badge-shimmer: badge-shimmer 3s ease-in-out infinite;
46 --animate-badge-pulse: badge-pulse 3s ease-in-out infinite;
47 --animate-chevron-up: chevron-up 2s ease-in-out infinite;
48 --animate-sway: sway 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
49 --animate-marketplace-featured-progress: marketplace-featured-progress linear forwards;
50}
51
52@keyframes shimmer {
53 0% {
54 background-position: -1000px 0;
55 }
56 100% {
57 background-position: 1000px 0;
58 }
59}
60
61@keyframes badge-shimmer {
62 0% {
63 transform: rotate(-45deg) translateX(-100%);
64 opacity: 0;
65 }
66 10% {
67 opacity: 1;
68 }
69 40% {
70 opacity: 1;
71 }
72 50% {
73 transform: rotate(-45deg) translateX(100%);
74 opacity: 0;
75 }
76 100% {
77 transform: rotate(-45deg) translateX(100%);
78 opacity: 0;
79 }
80}
81
82@keyframes badge-pulse {
83 0%,
84 100% {
85 opacity: 1;
86 }
87 50% {
88 opacity: 0.8;
89 }
90}
91
92@keyframes chevron-up {
93 0%,
94 100% {
95 opacity: 0.2;
96 }
97 50% {
98 opacity: 1;
99 }
100}
101
102@keyframes sway {
103 0%,
104 100% {
105 transform: rotate(-10deg) scale(1.5) translateY(4rem);
106 }
107 50% {
108 transform: rotate(10deg) scale(1.5) translateY(2rem);
109 }
110}
111
112@keyframes marketplace-featured-progress {
113 from {
114 transform: scaleX(0);
115 }
116 to {
117 transform: scaleX(1);
118 }
119}
120
121:root {
122 --chart-1: var(--brand-default);
123 --chart-2: 173 58% 39%;
124 --chart-3: 197 37% 24%;
125 --chart-4: 43 74% 66%;
126 --chart-5: 27 87% 67%;
127 --chart-blue: 217 91% 60%;
128 --chart-warning: hsl(var(--warning-default));
129 --chart-destructive: hsl(var(--destructive-default));
130 --sidebar-background: var(--background-dash-sidebar);
131 --sidebar-foreground: var(--foreground-default);
132 --sidebar-primary: var(--foreground-default);
133 --sidebar-primary-foreground: var(--warning-default);
134 --sidebar-accent: var(--background-selection);
135 --sidebar-accent-foreground: var(--foreground-default);
136 --sidebar-border: var(--border-default);
137 --sidebar-ring: 217.2 91.2% 59.8%;
138 --header-height: 3rem;
139}
140
141[data-theme='dark'],
142.dark {
143 --chart-1: var(--brand-default);
144 --chart-2: 160 60% 45%;
145 --chart-3: 30 80% 55%;
146 --chart-4: 280 65% 60%;
147 --chart-5: 340 75% 55%;
148 --chart-blue: 217 91% 65%;
149 --chart-warning: hsl(var(--warning-default));
150 --chart-destructive: hsl(var(--destructive-default));
151 --sidebar-background: var(--background-dash-sidebar);
152 --sidebar-foreground: var(--foreground-default);
153 --sidebar-primary: var(--foreground-default);
154 --sidebar-primary-foreground: var(--warning-default);
155 --sidebar-accent: var(--background-selection);
156 --sidebar-accent-foreground: var(--foreground-default);
157 --sidebar-border: var(--border-default);
158 --sidebar-ring: 217.2 91.2% 59.8%;
159}
160
161@layer base {
162 *,
163 ::after,
164 ::before,
165 ::backdrop,
166 ::file-selector-button {
167 border-color: hsl(var(--border-default, currentColor));
168 }
169
170 /* Global affordance: every interactive element shows pointer on hover.
171 Tailwind v4 no longer ships default cursor: pointer on buttons. */
172 button:not(:disabled),
173 a[href],
174 [role='button']:not([aria-disabled='true']),
175 summary,
176 label[for],
177 select:not(:disabled),
178 input[type='submit']:not(:disabled),
179 input[type='button']:not(:disabled),
180 input[type='reset']:not(:disabled),
181 input[type='checkbox']:not(:disabled),
182 input[type='radio']:not(:disabled) {
183 cursor: pointer;
184 }
185
186 button:disabled,
187 [role='button'][aria-disabled='true'] {
188 cursor: not-allowed;
189 }
190}
191
192html,
193body,
194#__next,
195.main {
196 @apply bg-dash-sidebar relative;
197 @apply text-foreground;
198 @apply overflow-x-clip;
199 -moz-osx-font-smoothing: grayscale;
200 -webkit-font-smoothing: antialiased;
201 overscroll-behavior: none;
202}
203
204* {
205 box-sizing: border-box;
206}
207
208.form-group .form-text,
209.Form .form-text {
210 @apply text-foreground-lighter;
211}
212
213.form-group input,
214.form-group input[type='text'],
215.form-group input[type='email'],
216.form-group input[type='url'],
217.form-group input[type='password'],
218.form-group input[type='number'],
219.form-group input[type='date'],
220.form-group input[type='datetime-local'],
221.form-group input[type='month'],
222.form-group input[type='search'],
223.form-group input[type='tel'],
224.form-group input[type='time'],
225.form-group input[type='week'],
226.form-group input[multiple],
227.form-group textarea,
228.form-group select,
229input.form-control,
230.form-control input,
231.form-control textarea {
232 @apply block;
233 @apply box-border;
234 /* @apply w-full ; */
235 @apply rounded-md;
236 @apply shadow-xs;
237 @apply transition-all;
238 @apply text-foreground;
239 @apply border;
240 @apply focus:shadow-md;
241
242 @apply focus:border-stronger;
243 @apply focus:ring-border-overlay;
244
245 @apply bg-studio;
246 @apply border-strong border;
247
248 @apply outline-hidden;
249 @apply focus:ring-2 focus:ring-current;
250}
251
252.form-group input,
253.form-group select,
254.form-group textarea {
255 @apply px-4 py-2;
256}
257
258.form-group input:focus,
259.form-group input[type='text']:focus,
260.form-group input[type='email']:focus,
261.form-group input[type='url']:focus,
262.form-group input[type='password']:focus,
263.form-group input[type='number']:focus,
264.form-group input[type='date']:focus,
265.form-group input[type='datetime-local']:focus,
266.form-group input[type='month']:focus,
267.form-group input[type='search']:focus,
268.form-group input[type='tel']:focus,
269.form-group input[type='time']:focus,
270.form-group input[type='week']:focus,
271.form-group input[multiple]:focus,
272.form-group textarea:focus,
273.form-group select:focus,
274.form-group input:focus .form-control:focus {
275 box-shadow: 0 0 0 2px rgba(62, 207, 142, 0.1);
276}
277
278/* icons in date / time inputs */
279.dark input[type='date']::-webkit-calendar-picker-indicator,
280.dark input[type='datetime-local']::-webkit-calendar-picker-indicator,
281.dark input[type='time']::-webkit-calendar-picker-indicator {
282 filter: invert(0.8);
283}
284
285input.is-invalid {
286 @apply bg-red-100;
287 @apply border border-red-700;
288 @apply focus:ring-red-500;
289 @apply placeholder:text-red-600;
290}
291
292input::placeholder {
293 @apply text-foreground-lighter;
294}
295
296.form-group input::placeholder {
297 @apply text-foreground-lighter;
298}
299
300.billing-input-fixed {
301 @apply w-full appearance-none rounded-sm border bg-gray-700 py-2 px-3 leading-tight text-gray-300 shadow-sm;
302}
303
304.input-mono {
305 input,
306 textarea {
307 @apply font-mono;
308 }
309}
310
311.input-sm {
312 input,
313 textarea {
314 @apply text-sm;
315 }
316}
317
318.input-xs {
319 input,
320 textarea {
321 @apply text-xs;
322 }
323}
324
325input[type='radio'] {
326 @apply p-0;
327}
328
329input[type='number'] {
330 -moz-appearance: textfield; /* Firefox, Not included in tailwind styles reset */
331}
332
333/* TODO: It doesnt' work, need to check */
334.hide-scrollbar {
335 scrollbar-width: none; /* Firefox */
336 -ms-overflow-style: none; /* Internet Explorer 10+ */
337}
338
339.hide-scrollbar::-webkit-scrollbar {
340 width: 0;
341 height: 0;
342 display: none;
343}
344
345div[data-radix-portal]:not(.portal--toast) {
346 z-index: 2147483646 !important;
347}
348
349.billing-compute-radio {
350 label {
351 @apply items-center justify-between;
352 &:last-child {
353 opacity: 100 !important;
354 }
355 }
356}
357
358.recharts-tooltip-cursor {
359 @apply fill-transparent;
360}
361
362.expandable-tr {
363 display: grid;
364 grid-template-columns: repeat(5, 1fr);
365}
366
367.expanded-row-content {
368 display: grid;
369 grid-column: 1/-1;
370 justify-content: flex-start;
371}
372
373.multi-select {
374 button {
375 display: block;
376 width: 100%;
377 }
378}
379
380@media (prefers-color-scheme: dark) {
381 html {
382 color-scheme: dark;
383 }
384}
385
386.text-area-resize-none {
387 textarea {
388 @apply resize-none;
389 }
390}
391
392.capitalize-sentence:first-letter {
393 text-transform: capitalize;
394}
395
396.input-clear {
397 input {
398 @apply pr-7;
399 }
400}
401
402/* to do: remove this CSS and do the same thing in a reusable tooltip component */
403[data-radix-popper-content-wrapper] {
404 @apply z-50!;
405}
406
407.settings-container {
408 @apply mx-auto max-w-4xl xl:max-w-6xl;
409}
410
411.react-grid-item.react-grid-placeholder {
412 @apply bg-brand-500!;
413}
414
415.react-grid-item > .react-resizable-handle::after {
416 content: '';
417 position: absolute;
418 right: 3px !important;
419 bottom: 3px !important;
420 width: 6px !important;
421 height: 6px !important;
422 @apply border-strong! dark:border-r-2! dark:border-b-2! dark:border-overlay!;
423}
424
425@keyframes typewriter {
426 from {
427 width: 0;
428 }
429}
430
431@keyframes blink-caret {
432 50% {
433 border-color: transparent;
434 }
435}
436
437/*
438 * Briven brand override — Phase 4 of BACKEND_FORK_BRIEF.md
439 * Replaces Supabase's green (--brand-default 153 60 53) with briven's
440 * brand green (#00e87a = 151.7 100 46). Source of truth lives in
441 * packages/config/tailwind/theme.css (--color-primary). HSL form is
442 * used here to integrate with Studio's existing theme variable shape.
443 */
444[data-theme='classic-dark'],
445.classic-dark,
446[data-theme='dark'],
447.dark,
448:root {
449 --brand-default: 151.7deg 100% 45.5%;
450 --brand-link: 151.7deg 100% 45.5%;
451 --brand-600: 151.7deg 90% 60%;
452 --brand-500: 151.7deg 80% 35%;
453 --brand-400: 151.7deg 70% 22%;
454 --brand-300: 151.7deg 60% 13%;
455 --brand-200: 151.7deg 50% 8%;
456
457 /* Phase 5 screen 3 — extend brand override to absolute scale tokens
458 * (--color-brand-700..1000) so Tailwind utilities like bg-brand-900
459 * resolve to briven green rather than upstream's supabase HSL. */
460 --color-brand-700: hsla(151.7, 70%, 38%, 1);
461 --color-brand-800: hsla(151.7, 85%, 42%, 1);
462 --color-brand-900: hsla(151.7, 100%, 45.5%, 1);
463 --color-brand-1000: hsla(151.7, 90%, 50%, 1);
464}
465
466/*
467 * Briven typography override — Phase 5 (screen 2: project home, applies
468 * chrome-wide because the layout components are shared). Force mono
469 * across the app to match the terminal aesthetic of the control plane
470 * (apps/web). Headings render lowercase per BRAND.md §3.
471 *
472 * `var(--font-mono)` resolves to Studio's existing fallback stack
473 * (Source Code Pro -> Office Code Pro -> Menlo -> monospace). When the
474 * Geist Mono webfont lands in Phase 6+, it slots into --font-custom-mono
475 * and propagates through this override.
476 */
477:root {
478 --font-sans: var(
479 --font-geist-mono,
480 'Geist Mono',
481 'JetBrains Mono',
482 'Source Code Pro',
483 Menlo,
484 monospace
485 );
486 --font-mono: var(
487 --font-geist-mono,
488 'Geist Mono',
489 'JetBrains Mono',
490 'Source Code Pro',
491 Menlo,
492 monospace
493 );
494}
495
496body,
497button,
498input,
499select,
500textarea {
501 font-family: var(--font-mono);
502}
503
504/* Lowercase all chrome headings — matches lowercase brand voice. Decorative
505 * <h*> inside marketing strings can opt out with .normal-case if needed. */
506h1:not(.normal-case),
507h2:not(.normal-case),
508h3:not(.normal-case),
509h4:not(.normal-case),
510h5:not(.normal-case),
511h6:not(.normal-case) {
512 text-transform: lowercase;
513}