@reservi/theme 1.3.3 → 1.4.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -4
- package/scripts/build-plain.mjs +49 -0
- package/src/components.css +123 -3
- package/src/plain.css +12 -0
- package/src/themes/index.css +1 -0
- package/src/themes/reservi.css +44 -0
- package/src/tokens.generated.css +74 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reservi/theme",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1-beta.1",
|
|
4
4
|
"description": "Tema de Reservi Calendar: design tokens (TailwindCSS 4 @theme) y estilos base.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,12 +25,15 @@
|
|
|
25
25
|
"*.css"
|
|
26
26
|
],
|
|
27
27
|
"files": [
|
|
28
|
-
"src"
|
|
28
|
+
"src",
|
|
29
|
+
"scripts"
|
|
29
30
|
],
|
|
30
31
|
"main": "./src/index.css",
|
|
31
32
|
"style": "./src/index.css",
|
|
32
33
|
"exports": {
|
|
33
34
|
".": "./src/index.css",
|
|
35
|
+
"./plain": "./src/plain.css",
|
|
36
|
+
"./tokens": "./src/tokens.generated.css",
|
|
34
37
|
"./theme.css": "./src/theme.css",
|
|
35
38
|
"./components.css": "./src/components.css",
|
|
36
39
|
"./template": "./src/theme-template.css",
|
|
@@ -49,10 +52,11 @@
|
|
|
49
52
|
"./themes/graphite": "./src/themes/graphite.css",
|
|
50
53
|
"./themes/solarized-light": "./src/themes/solarized-light.css",
|
|
51
54
|
"./themes/solarized-dark": "./src/themes/solarized-dark.css",
|
|
52
|
-
"./themes/contrast": "./src/themes/contrast.css"
|
|
55
|
+
"./themes/contrast": "./src/themes/contrast.css",
|
|
56
|
+
"./themes/reservi": "./src/themes/reservi.css"
|
|
53
57
|
},
|
|
54
58
|
"scripts": {
|
|
55
|
-
"build": "node -
|
|
59
|
+
"build": "node scripts/build-plain.mjs",
|
|
56
60
|
"lint": "node -e \"process.exit(0)\"",
|
|
57
61
|
"typecheck": "node -e \"process.exit(0)\""
|
|
58
62
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genera la variante "plain CSS" del tema a partir de la fuente de TailwindCSS 4.
|
|
3
|
+
*
|
|
4
|
+
* `theme.css` declara los design tokens en un bloque `@theme`, que solo
|
|
5
|
+
* entiende Tailwind 4. Los estilos de `components.css` no usan utilidades de
|
|
6
|
+
* Tailwind: leen las variables con `var(--color-rsv-*, fallback)`. Por tanto,
|
|
7
|
+
* para un consumidor con Tailwind 3 (o sin Tailwind) basta con declarar los
|
|
8
|
+
* mismos tokens en `:root`.
|
|
9
|
+
*
|
|
10
|
+
* Este script hace exactamente esa transformación, de modo que NO haya dos
|
|
11
|
+
* listas de tokens que mantener sincronizadas a mano.
|
|
12
|
+
*
|
|
13
|
+
* Salida: `src/tokens.generated.css`, que importa `plain.css`.
|
|
14
|
+
*/
|
|
15
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
import { dirname, join } from "node:path";
|
|
18
|
+
|
|
19
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const src = join(here, "..", "src");
|
|
21
|
+
|
|
22
|
+
const HEADER = `/**
|
|
23
|
+
* ARCHIVO GENERADO — no editar a mano.
|
|
24
|
+
* Fuente: src/theme.css · Generador: scripts/build-plain.mjs
|
|
25
|
+
*
|
|
26
|
+
* Misma lista de design tokens que el bloque \`@theme\` de Tailwind 4, pero
|
|
27
|
+
* declarados en \`:root\` para consumidores con Tailwind 3 o sin Tailwind.
|
|
28
|
+
*/
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
const theme = await readFile(join(src, "theme.css"), "utf8");
|
|
32
|
+
|
|
33
|
+
// Se descarta el comentario de cabecera original (habla de Tailwind 4) antes de
|
|
34
|
+
// comprobar que no queda ningun `@theme`: el comentario lo menciona.
|
|
35
|
+
let out = theme.replace(/^\/\*\*[\s\S]*?\*\/\s*/, "");
|
|
36
|
+
|
|
37
|
+
// `@theme { … }` → `:root { … }`. El bloque puede venir anidado dentro de un
|
|
38
|
+
// `@media (prefers-color-scheme: dark)`, que se conserva tal cual.
|
|
39
|
+
out = out.replace(/@theme(\s+(?:static|inline|reference|default))?\s*\{/g, ":root {");
|
|
40
|
+
|
|
41
|
+
if (out.includes("@theme")) {
|
|
42
|
+
throw new Error("build-plain: queda algun @theme sin transformar en theme.css");
|
|
43
|
+
}
|
|
44
|
+
if (!out.includes(":root {")) {
|
|
45
|
+
throw new Error("build-plain: no se encontro ningun bloque @theme en theme.css");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await writeFile(join(src, "tokens.generated.css"), HEADER + "\n" + out, "utf8");
|
|
49
|
+
console.log("@reservi/theme: src/tokens.generated.css generado desde src/theme.css");
|
package/src/components.css
CHANGED
|
@@ -16,6 +16,25 @@
|
|
|
16
16
|
flex-direction: column;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/* El area de vista reparte el alto disponible del root (flex column), de modo
|
|
20
|
+
que el cuerpo de timeGrid pueda scrollear cuando el root tiene alto fijo.
|
|
21
|
+
Con `height: "auto"` el calendario crece con su contenido. */
|
|
22
|
+
[data-rsv="view"] {
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
flex: 1 1 auto;
|
|
26
|
+
min-height: 0;
|
|
27
|
+
}
|
|
28
|
+
[data-rsv="root"][data-rsv-autoheight="true"] [data-rsv="view"] {
|
|
29
|
+
flex: 0 0 auto;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Hueco donde el framework anfitrion (React/Vue) pinta un render prop: no debe
|
|
33
|
+
introducir una caja propia que rompa el layout del evento o de la celda. */
|
|
34
|
+
[data-rsv="host"] {
|
|
35
|
+
display: contents;
|
|
36
|
+
}
|
|
37
|
+
|
|
19
38
|
/* Toolbar */
|
|
20
39
|
[data-rsv="toolbar-wrap"] {
|
|
21
40
|
display: flex;
|
|
@@ -348,6 +367,12 @@
|
|
|
348
367
|
outline: 2px solid var(--color-rsv-primary, #4f46e5);
|
|
349
368
|
outline-offset: 1px;
|
|
350
369
|
}
|
|
370
|
+
/* Selección múltiple (bulk ops): ctrl/cmd-click sobre un evento. */
|
|
371
|
+
[data-rsv="event"][data-rsv-selected="true"] {
|
|
372
|
+
outline: 2px solid var(--color-rsv-primary, #4f46e5);
|
|
373
|
+
outline-offset: 1px;
|
|
374
|
+
box-shadow: 0 0 0 3px var(--color-rsv-selection, #e8e8ff);
|
|
375
|
+
}
|
|
351
376
|
[data-rsv="day-number"] {
|
|
352
377
|
align-self: flex-end;
|
|
353
378
|
font-size: var(--text-rsv-sm, 0.8125rem);
|
|
@@ -373,6 +398,7 @@
|
|
|
373
398
|
border-radius: var(--radius-rsv-event, 0.375rem);
|
|
374
399
|
background: var(--rsv-event-bg, var(--color-rsv-event-1));
|
|
375
400
|
color: var(--rsv-event-fg, var(--color-rsv-event-fg, #fff));
|
|
401
|
+
border: 1px solid var(--rsv-event-border, transparent);
|
|
376
402
|
cursor: pointer;
|
|
377
403
|
overflow: hidden;
|
|
378
404
|
white-space: nowrap;
|
|
@@ -475,6 +501,8 @@
|
|
|
475
501
|
[data-rsv="timegrid"] {
|
|
476
502
|
display: flex;
|
|
477
503
|
flex-direction: column;
|
|
504
|
+
flex: 1 1 auto;
|
|
505
|
+
min-height: 0;
|
|
478
506
|
--rsv-tg-axis-width: 3.5rem;
|
|
479
507
|
}
|
|
480
508
|
[data-rsv="tg-header"],
|
|
@@ -511,6 +539,11 @@
|
|
|
511
539
|
display: grid;
|
|
512
540
|
grid-template-columns: var(--rsv-tg-axis-width) repeat(var(--rsv-tg-days, 7), minmax(0, 1fr));
|
|
513
541
|
overflow: auto;
|
|
542
|
+
/* Imprescindible para que un grid dentro de un flex column pueda encogerse
|
|
543
|
+
y por tanto scrollear en vez de desbordar al padre. */
|
|
544
|
+
flex: 1 1 auto;
|
|
545
|
+
min-height: 0;
|
|
546
|
+
align-content: start;
|
|
514
547
|
}
|
|
515
548
|
[data-rsv="tg-axis"] {
|
|
516
549
|
display: flex;
|
|
@@ -524,13 +557,25 @@
|
|
|
524
557
|
[data-rsv="tg-slot"][data-major="true"] {
|
|
525
558
|
border-top: 1px solid var(--color-rsv-border, #eee);
|
|
526
559
|
}
|
|
560
|
+
/**
|
|
561
|
+
* La etiqueta va centrada en su franja, no montada sobre la línea superior.
|
|
562
|
+
*
|
|
563
|
+
* Antes se subía con `top: -0.6em` y se le pintaba detrás un rectángulo opaco
|
|
564
|
+
* de `--color-rsv-bg` para tapar la línea que cruzaba el texto. Ese rectángulo
|
|
565
|
+
* asumía que el fondo real del eje era exactamente `--color-rsv-bg`, y se veía
|
|
566
|
+
* como una mancha en cuanto algo lo teñía (día actual, `surface`, franjas no
|
|
567
|
+
* laborables, o un token sobreescrito por la app).
|
|
568
|
+
*
|
|
569
|
+
* Centrada no cruza ningún borde, así que el rectángulo sobra y el problema
|
|
570
|
+
* desaparece en vez de taparse.
|
|
571
|
+
*/
|
|
527
572
|
[data-rsv="tg-slot-label"] {
|
|
528
573
|
position: absolute;
|
|
529
|
-
top:
|
|
574
|
+
top: 50%;
|
|
575
|
+
transform: translateY(-50%);
|
|
530
576
|
right: 0.35rem;
|
|
531
577
|
font-size: var(--text-rsv-xs, 0.75rem);
|
|
532
578
|
color: var(--color-rsv-muted, #777);
|
|
533
|
-
background: var(--color-rsv-bg, #fff);
|
|
534
579
|
}
|
|
535
580
|
[data-rsv="tg-col"] {
|
|
536
581
|
position: relative;
|
|
@@ -554,7 +599,24 @@
|
|
|
554
599
|
font-size: var(--text-rsv-xs, 0.75rem);
|
|
555
600
|
overflow: hidden;
|
|
556
601
|
box-sizing: border-box;
|
|
557
|
-
|
|
602
|
+
/* `borderColor` del evento si lo hay; si no, un tono del propio fondo. */
|
|
603
|
+
border: 1px solid
|
|
604
|
+
var(--rsv-event-border, color-mix(in oklch, var(--rsv-event-bg) 80%, black));
|
|
605
|
+
align-items: stretch;
|
|
606
|
+
white-space: normal;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/* Fantasma del rango que se esta seleccionando (`selectMirror`). */
|
|
610
|
+
[data-rsv="select-mirror"] {
|
|
611
|
+
position: absolute;
|
|
612
|
+
left: 0;
|
|
613
|
+
right: 0;
|
|
614
|
+
background: var(--color-rsv-selection, #e8e8ff);
|
|
615
|
+
border: 1px dashed var(--color-rsv-primary, #4f46e5);
|
|
616
|
+
border-radius: var(--radius-rsv-event, 0.375rem);
|
|
617
|
+
opacity: 0.7;
|
|
618
|
+
pointer-events: none;
|
|
619
|
+
z-index: 4;
|
|
558
620
|
}
|
|
559
621
|
[data-rsv="tg-nonbusiness"] {
|
|
560
622
|
position: absolute;
|
|
@@ -602,6 +664,10 @@
|
|
|
602
664
|
flex-direction: column;
|
|
603
665
|
}
|
|
604
666
|
[data-rsv="list-day-header"] {
|
|
667
|
+
display: flex;
|
|
668
|
+
align-items: baseline;
|
|
669
|
+
justify-content: space-between;
|
|
670
|
+
gap: 0.5rem;
|
|
605
671
|
position: sticky;
|
|
606
672
|
top: 0;
|
|
607
673
|
padding: 0.4rem 0.75rem;
|
|
@@ -615,6 +681,11 @@
|
|
|
615
681
|
[data-rsv="list-day"][data-today="true"] [data-rsv="list-day-header"] {
|
|
616
682
|
color: var(--color-rsv-primary, #4f46e5);
|
|
617
683
|
}
|
|
684
|
+
[data-rsv="list-day-side-text"] {
|
|
685
|
+
font-weight: 400;
|
|
686
|
+
font-size: var(--text-rsv-xs, 0.75rem);
|
|
687
|
+
color: var(--color-rsv-muted, #777);
|
|
688
|
+
}
|
|
618
689
|
[data-rsv="list-item"] {
|
|
619
690
|
display: flex;
|
|
620
691
|
align-items: center;
|
|
@@ -812,6 +883,55 @@
|
|
|
812
883
|
cursor: pointer;
|
|
813
884
|
}
|
|
814
885
|
|
|
886
|
+
/* Vista mensual con recursos como columnas anidadas por día. */
|
|
887
|
+
[data-rsv="resource-daygrid-month"] {
|
|
888
|
+
display: flex;
|
|
889
|
+
flex-direction: column;
|
|
890
|
+
}
|
|
891
|
+
[data-rsv="rdgm-week"] {
|
|
892
|
+
display: grid;
|
|
893
|
+
grid-template-columns: repeat(var(--rsv-rdgm-cols, 7), minmax(0, 1fr));
|
|
894
|
+
}
|
|
895
|
+
[data-rsv="rdgm-week"] [data-rsv="day"]:last-child {
|
|
896
|
+
border-right: none;
|
|
897
|
+
}
|
|
898
|
+
[data-rsv="rdgm-columns"] {
|
|
899
|
+
display: flex;
|
|
900
|
+
flex-direction: column;
|
|
901
|
+
gap: 0.2rem;
|
|
902
|
+
overflow: hidden;
|
|
903
|
+
}
|
|
904
|
+
[data-rsv="rdgm-col"] {
|
|
905
|
+
display: flex;
|
|
906
|
+
flex-direction: column;
|
|
907
|
+
gap: 0.1rem;
|
|
908
|
+
border-inline-start: 2px solid var(--color-rsv-border, #eee);
|
|
909
|
+
padding-inline-start: 0.2rem;
|
|
910
|
+
}
|
|
911
|
+
[data-rsv="rdgm-col-label"] {
|
|
912
|
+
font-size: 0.65rem;
|
|
913
|
+
font-weight: 600;
|
|
914
|
+
color: var(--color-rsv-muted, #777);
|
|
915
|
+
text-transform: uppercase;
|
|
916
|
+
letter-spacing: 0.02em;
|
|
917
|
+
}
|
|
918
|
+
[data-rsv="rdgm-col"] [data-rsv="event"] {
|
|
919
|
+
background: var(--rsv-event-bg, var(--color-rsv-event-1));
|
|
920
|
+
color: var(--rsv-event-fg, #fff);
|
|
921
|
+
border-radius: var(--radius-rsv-event, 0.375rem);
|
|
922
|
+
padding: 0.05rem 0.3rem;
|
|
923
|
+
font-size: var(--text-rsv-xs, 0.75rem);
|
|
924
|
+
cursor: pointer;
|
|
925
|
+
overflow: hidden;
|
|
926
|
+
white-space: nowrap;
|
|
927
|
+
text-overflow: ellipsis;
|
|
928
|
+
}
|
|
929
|
+
[data-rsv="rdgm-more"] {
|
|
930
|
+
font-size: 0.65rem;
|
|
931
|
+
color: var(--color-rsv-muted, #777);
|
|
932
|
+
cursor: pointer;
|
|
933
|
+
}
|
|
934
|
+
|
|
815
935
|
/* Eventos de fondo (display: background) */
|
|
816
936
|
[data-rsv="event"][data-display="background"] {
|
|
817
937
|
opacity: 0.25;
|
package/src/plain.css
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Punto de entrada "plain CSS" de Reservi Calendar: sin Tailwind.
|
|
3
|
+
*
|
|
4
|
+
* Uso (Tailwind 3, CSS Modules, PostCSS o un <link> suelto):
|
|
5
|
+
* @import "@reservi/theme/plain";
|
|
6
|
+
*
|
|
7
|
+
* Equivale a `@reservi/theme` pero declara los design tokens en `:root` en
|
|
8
|
+
* lugar de en un bloque `@theme` de TailwindCSS 4. Los estilos de componentes
|
|
9
|
+
* son los mismos: leen los tokens con `var(--color-rsv-*, fallback)`.
|
|
10
|
+
*/
|
|
11
|
+
@import "./tokens.generated.css";
|
|
12
|
+
@import "./components.css";
|
package/src/themes/index.css
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme "reservi" — claro, paleta de marca de Reservi.
|
|
3
|
+
*
|
|
4
|
+
* Los valores son los mismos hex de `tailwind.config.js` de reservi-frontend-v2.
|
|
5
|
+
* Se usa hex y no `oklch()` como el resto de themes a propósito: son colores de
|
|
6
|
+
* marca y la conversión introduce desviación; aquí pesa más la fidelidad.
|
|
7
|
+
*
|
|
8
|
+
* `--font-rsv-sans` NO se declara aquí: la fuente de la app (Urbanist) llega
|
|
9
|
+
* como variable de Next, así que la aporta el frontend vía `themeTokens`.
|
|
10
|
+
*/
|
|
11
|
+
[data-rsv-theme="reservi"] {
|
|
12
|
+
/* Superficies */
|
|
13
|
+
--color-rsv-bg: #fefefe;
|
|
14
|
+
--color-rsv-surface: #faf5fc;
|
|
15
|
+
--color-rsv-border: #efefef;
|
|
16
|
+
--color-rsv-muted: #5e636b;
|
|
17
|
+
--color-rsv-text: #1a1a1a;
|
|
18
|
+
|
|
19
|
+
/* Marca / acento */
|
|
20
|
+
--color-rsv-primary: #865e9b;
|
|
21
|
+
--color-rsv-primary-fg: #fefefe;
|
|
22
|
+
/* Translúcido a propósito: tiñe la columna del día actual sin tapar las
|
|
23
|
+
líneas de franja que se pintan debajo. */
|
|
24
|
+
--color-rsv-today: rgba(155, 135, 245, 0.1);
|
|
25
|
+
|
|
26
|
+
/* Eventos — mapeados a los estados de cita (`border-status-*`). */
|
|
27
|
+
--color-rsv-event-1: #865e9b; /* pendiente */
|
|
28
|
+
--color-rsv-event-2: #78b157; /* confirmada */
|
|
29
|
+
--color-rsv-event-3: #e1d25e; /* no-show */
|
|
30
|
+
--color-rsv-event-4: #d85353; /* cancelada */
|
|
31
|
+
--color-rsv-event-5: #bbbec2; /* completada */
|
|
32
|
+
/* Texto oscuro: la paleta de estados va de claro (#e1d25e, #bbbec2) a medio,
|
|
33
|
+
y un fg blanco sería ilegible sobre los dos claros. */
|
|
34
|
+
--color-rsv-event-fg: #141517;
|
|
35
|
+
|
|
36
|
+
/* Estados */
|
|
37
|
+
--color-rsv-now: #d85353;
|
|
38
|
+
--color-rsv-selection: #f6f0fa;
|
|
39
|
+
--color-rsv-nonbusiness: rgba(250, 250, 255, 0.5);
|
|
40
|
+
|
|
41
|
+
/* Geometría */
|
|
42
|
+
--radius-rsv: 8px;
|
|
43
|
+
--radius-rsv-event: 4px;
|
|
44
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ARCHIVO GENERADO — no editar a mano.
|
|
3
|
+
* Fuente: src/theme.css · Generador: scripts/build-plain.mjs
|
|
4
|
+
*
|
|
5
|
+
* Misma lista de design tokens que el bloque `@theme` de Tailwind 4, pero
|
|
6
|
+
* declarados en `:root` para consumidores con Tailwind 3 o sin Tailwind.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
:root {
|
|
10
|
+
/* Superficies */
|
|
11
|
+
--color-rsv-bg: oklch(1 0 0);
|
|
12
|
+
--color-rsv-surface: oklch(0.98 0 0);
|
|
13
|
+
--color-rsv-border: oklch(0.9 0 0);
|
|
14
|
+
--color-rsv-muted: oklch(0.55 0 0);
|
|
15
|
+
--color-rsv-text: oklch(0.2 0 0);
|
|
16
|
+
|
|
17
|
+
/* Marca / acento */
|
|
18
|
+
--color-rsv-primary: oklch(0.55 0.2 264);
|
|
19
|
+
--color-rsv-primary-fg: oklch(0.99 0 0);
|
|
20
|
+
--color-rsv-today: oklch(0.97 0.04 264);
|
|
21
|
+
|
|
22
|
+
/* Paleta categórica de eventos */
|
|
23
|
+
--color-rsv-event-1: oklch(0.6 0.18 264);
|
|
24
|
+
--color-rsv-event-2: oklch(0.65 0.17 150);
|
|
25
|
+
--color-rsv-event-3: oklch(0.7 0.17 60);
|
|
26
|
+
--color-rsv-event-4: oklch(0.62 0.2 20);
|
|
27
|
+
--color-rsv-event-5: oklch(0.6 0.16 320);
|
|
28
|
+
--color-rsv-event-fg: oklch(0.99 0 0);
|
|
29
|
+
|
|
30
|
+
/* Estados */
|
|
31
|
+
--color-rsv-now: oklch(0.6 0.22 20);
|
|
32
|
+
--color-rsv-selection: oklch(0.9 0.05 264);
|
|
33
|
+
--color-rsv-nonbusiness: oklch(0.96 0 0);
|
|
34
|
+
|
|
35
|
+
/* Tipografía */
|
|
36
|
+
--font-rsv-sans: ui-sans-serif, system-ui, sans-serif;
|
|
37
|
+
--text-rsv-xs: 0.75rem;
|
|
38
|
+
--text-rsv-sm: 0.8125rem;
|
|
39
|
+
--text-rsv-base: 0.875rem;
|
|
40
|
+
|
|
41
|
+
/* Geometría */
|
|
42
|
+
--radius-rsv: 0.5rem;
|
|
43
|
+
--radius-rsv-event: 0.375rem;
|
|
44
|
+
--spacing-rsv-slot: 2.5rem;
|
|
45
|
+
--spacing-rsv-gutter: 0.25rem;
|
|
46
|
+
|
|
47
|
+
/* Sombras y transición */
|
|
48
|
+
--shadow-rsv-pop: 0 4px 20px -4px oklch(0 0 0 / 0.2);
|
|
49
|
+
--ease-rsv: cubic-bezier(0.2, 0, 0, 1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Modo oscuro automático */
|
|
53
|
+
@media (prefers-color-scheme: dark) {
|
|
54
|
+
:root {
|
|
55
|
+
--color-rsv-bg: oklch(0.18 0.01 264);
|
|
56
|
+
--color-rsv-surface: oklch(0.22 0.01 264);
|
|
57
|
+
--color-rsv-border: oklch(0.3 0.01 264);
|
|
58
|
+
--color-rsv-text: oklch(0.95 0 0);
|
|
59
|
+
--color-rsv-muted: oklch(0.6 0 0);
|
|
60
|
+
--color-rsv-today: oklch(0.3 0.05 264);
|
|
61
|
+
--color-rsv-nonbusiness: oklch(0.2 0.01 264);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Modo oscuro por clase (.dark) para toggle manual */
|
|
66
|
+
.dark {
|
|
67
|
+
--color-rsv-bg: oklch(0.18 0.01 264);
|
|
68
|
+
--color-rsv-surface: oklch(0.22 0.01 264);
|
|
69
|
+
--color-rsv-border: oklch(0.3 0.01 264);
|
|
70
|
+
--color-rsv-text: oklch(0.95 0 0);
|
|
71
|
+
--color-rsv-muted: oklch(0.6 0 0);
|
|
72
|
+
--color-rsv-today: oklch(0.3 0.05 264);
|
|
73
|
+
--color-rsv-nonbusiness: oklch(0.2 0.01 264);
|
|
74
|
+
}
|