orbital-ds 0.6.0 → 0.7.0

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/AGENTS.md CHANGED
@@ -58,3 +58,23 @@ Si `pnpm check:ds` falla, **corrige la causa**; no lo desactives ni lo rodees.
58
58
 
59
59
  Copia `themes/qratia.css` (o `zyro.css`), cambia valores, no quites ninguno, añade
60
60
  `<tema>.fonts.css` con el `@import url()` de sus fuentes y ejecuta `pnpm check:ds`.
61
+
62
+ ## Estándar de integración (cómo debe ajustarse una app)
63
+
64
+ Para que una app (o un agente que la edite) use orbital-ds sin romper nada:
65
+
66
+ 1. **La marca vive solo en `brand.css`.** Ninguna regla de color propia fuera de ese fichero; jamás se edita el paquete.
67
+ 2. **Solo variables públicas.** Nada de variables privadas de un tema (por ejemplo `--zw-*`): se renombran sin aviso de versión mayor. Usa `--ds-*` y los tokens del contrato.
68
+ 3. **Sin `!important` ni selectores propios** para vencer a la librería (lateral, raíl, botones). Si algo no se puede ajustar con un token, es un hueco de la librería: abre un issue.
69
+ 4. **El tema se elige con un solo `@import`** (o `pnpm theme`). Los temas con ámbito (`*.scoped.css`) son solo para un banco de pruebas; la marca (`brand.css`) gana siempre, también sobre ellos.
70
+ 5. **Patrón de página.** La cabecera lleva solo botón de menú, título y, siempre visibles, idioma y tema (y avisos si la app los tiene). El subtítulo y las acciones de la vista van al inicio del contenido, centrado en un ancho máximo; solo un lienzo (mapa, kanban, editor) ocupa todo el ancho.
71
+ 6. **Cada tema se documenta y se elige informado.** Lee `orbital-ds/themes/<tema>.guide.md` y su ficha `<tema>.meta.json` (esencia, gesto firma, paleta, accesibilidad, qué valores son aproximados) antes de usar o ajustar un tema.
72
+ 7. **Comprueba antes de dar algo por bueno:** `pnpm exec orbital-ds-doctor --css src/brand.css` y el `verify` de la app.
73
+
74
+ ### Accesibilidad (WCAG 2.2)
75
+
76
+ - **Mínimo exigible: AA.** Texto 4,5:1; texto grande y controles 3:1. `pnpm check:ds` falla si un par principal de texto sobre su superficie (texto/fondo, tarjeta, popover, primario, secundario, lateral, destructivo) o un texto de estado (info, danger, warning, success, neutral) baja de 4,5:1.
77
+ - **Objetivo: AAA en el texto del cuerpo** (7:1 para texto/fondo y texto/tarjeta). Se mide con `pnpm check:ds -- --aaa` y avisa, no falla: WCAG no aconseja exigir AAA a todo el sitio. Hoy todos los temas lo cumplen.
78
+ - **Excepciones declaradas, nunca silenciosas.** Si un tema no puede cumplir un par (el azul de marca de Twitter con texto blanco da 3:1), lo declara en su ficha, en `a11y.exceptions`, con su porqué; el doctor lo muestra como aviso.
79
+ - **Foco siempre visible** (anillo de 3:1 como mínimo) y sin que otro elemento lo tape.
80
+ - **Una marca nueva debe volver a pasar el doctor.** Cambiar `--primary` obliga a revisar `--primary-foreground`, `--link` y `--ring`.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "package": "orbital-ds",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "engine": "@base-ui/react",
5
5
  "docs": [
6
6
  "README.md",
@@ -1256,6 +1256,7 @@
1256
1256
  ],
1257
1257
  "slots": [
1258
1258
  "tooltip",
1259
+ "tooltip-arrow",
1259
1260
  "tooltip-content",
1260
1261
  "tooltip-provider",
1261
1262
  "tooltip-trigger"
package/contract.json CHANGED
@@ -1,162 +1,168 @@
1
- {
2
- "version": 3,
3
- "descripcion": "Contrato de tema de orbital-ds: todo tema (themes/*.css) debe definir estos tokens en :root. Nombres en inglés estándar; los de shadcn sin prefijo; los propios con --ds-. baseTheme es el tema aplicado siempre (los demás se aplican encima, con ámbito).",
4
- "root": [
5
- "radius",
6
- "background",
7
- "foreground",
8
- "card",
9
- "card-foreground",
10
- "popover",
11
- "popover-foreground",
12
- "primary",
13
- "primary-foreground",
14
- "secondary",
15
- "secondary-foreground",
16
- "muted",
17
- "muted-foreground",
18
- "accent",
19
- "accent-foreground",
20
- "destructive",
21
- "destructive-foreground",
22
- "border",
23
- "input",
24
- "ring",
25
- "chart-1",
26
- "chart-2",
27
- "chart-3",
28
- "chart-4",
29
- "chart-5",
30
- "sidebar",
31
- "sidebar-foreground",
32
- "sidebar-primary",
33
- "sidebar-primary-foreground",
34
- "sidebar-accent",
35
- "sidebar-accent-foreground",
36
- "sidebar-border",
37
- "sidebar-ring",
38
- "danger",
39
- "danger-soft",
40
- "warning",
41
- "warning-soft",
42
- "success",
43
- "success-soft",
44
- "info",
45
- "info-soft",
46
- "neutral",
47
- "neutral-soft",
48
- "link",
49
- "link-hover",
50
- "inset",
51
- "inset-foreground",
52
- "brand",
53
- "brand-bright"
54
- ],
55
- "fonts": [
56
- "ds-font-sans"
57
- ],
58
- "dark": {
59
- "descripcion": "Recomendados en .dark (si faltan, el tema hereda el valor claro y doctor avisa).",
60
- "avisar_si_falta": [
61
- "background",
62
- "foreground",
63
- "card",
64
- "card-foreground",
65
- "popover",
66
- "popover-foreground",
67
- "primary",
68
- "primary-foreground",
69
- "muted",
70
- "muted-foreground",
71
- "border",
72
- "input",
73
- "ring",
74
- "danger",
75
- "warning",
76
- "success",
77
- "info",
78
- "link"
79
- ]
80
- },
81
- "baseTheme": "qratia",
82
- "brand": {
83
- "descripcion": "Grupo ESTABLE de variables que una app suele personalizar en su fichero de marca (brand.css). Renombrar o quitar una es versión MAYOR. Todas están también en `root` salvo las --ds-*.",
84
- "tokens": [
85
- {
86
- "name": "primary",
87
- "example": "oklch(0.55 0.2 260)",
88
- "about": "color de acción principal (botones, foco)"
89
- },
90
- {
91
- "name": "primary-foreground",
92
- "example": "#ffffff",
93
- "about": "texto sobre el color principal (comprueba el contraste)"
94
- },
95
- {
96
- "name": "ring",
97
- "example": "oklch(0.55 0.2 260)",
98
- "about": "anillo de foco; suele ir igual que primary"
99
- },
100
- {
101
- "name": "link",
102
- "example": "oklch(0.5 0.15 260)",
103
- "about": "texto de enlace: más oscuro que primary para tener contraste"
104
- },
105
- {
106
- "name": "link-hover",
107
- "example": "oklch(0.42 0.13 260)",
108
- "about": "enlace al pasar el ratón"
109
- },
110
- {
111
- "name": "brand",
112
- "example": "oklch(0.7 0.13 220)",
113
- "about": "acento de marca (detalles, selección)"
114
- },
115
- {
116
- "name": "brand-bright",
117
- "example": "oklch(0.8 0.13 220)",
118
- "about": "acento de marca sobre fondos oscuros"
119
- },
120
- {
121
- "name": "sidebar-primary",
122
- "example": "oklch(0.8 0.13 220)",
123
- "about": "acento dentro del sidebar"
124
- },
125
- {
126
- "name": "sidebar-primary-foreground",
127
- "example": "#04121c",
128
- "about": "texto sobre el acento del sidebar"
129
- },
130
- {
131
- "name": "sidebar-accent-foreground",
132
- "example": "oklch(0.85 0.1 220)",
133
- "about": "texto del destino activo del sidebar"
134
- },
135
- {
136
- "name": "accent-foreground",
137
- "example": "oklch(0.5 0.15 260)",
138
- "about": "texto sobre superficies de acento suave"
139
- },
140
- {
141
- "name": "chart-1",
142
- "example": "oklch(0.55 0.2 260)",
143
- "about": "primera serie de las gráficas: la marca"
144
- },
145
- {
146
- "name": "radius",
147
- "example": "12px",
148
- "about": "redondez base (en temas cuya rampa deriva de ella)"
149
- },
150
- {
151
- "name": "ds-font-sans",
152
- "example": "'Inter', system-ui, sans-serif",
153
- "about": "fuente del cuerpo (carga la fuente en tu app)"
154
- },
155
- {
156
- "name": "ds-font-display",
157
- "example": "'Sora', system-ui, sans-serif",
158
- "about": "fuente de los titulares"
159
- }
160
- ]
161
- }
162
- }
1
+ {
2
+ "version": 4,
3
+ "descripcion": "Contrato de tema de orbital-ds: todo tema (themes/*.css) debe definir estos tokens en :root. Nombres en inglés estándar; los de shadcn sin prefijo; los propios con --ds-. baseTheme es el tema aplicado siempre (los demás se aplican encima, con ámbito).",
4
+ "root": [
5
+ "radius",
6
+ "background",
7
+ "foreground",
8
+ "card",
9
+ "card-foreground",
10
+ "popover",
11
+ "popover-foreground",
12
+ "primary",
13
+ "primary-foreground",
14
+ "secondary",
15
+ "secondary-foreground",
16
+ "muted",
17
+ "muted-foreground",
18
+ "accent",
19
+ "accent-foreground",
20
+ "destructive",
21
+ "destructive-foreground",
22
+ "border",
23
+ "input",
24
+ "ring",
25
+ "chart-1",
26
+ "chart-2",
27
+ "chart-3",
28
+ "chart-4",
29
+ "chart-5",
30
+ "sidebar",
31
+ "sidebar-foreground",
32
+ "sidebar-primary",
33
+ "sidebar-primary-foreground",
34
+ "sidebar-accent",
35
+ "sidebar-accent-foreground",
36
+ "sidebar-border",
37
+ "sidebar-ring",
38
+ "danger",
39
+ "danger-soft",
40
+ "warning",
41
+ "warning-soft",
42
+ "success",
43
+ "success-soft",
44
+ "info",
45
+ "info-soft",
46
+ "neutral",
47
+ "neutral-soft",
48
+ "link",
49
+ "link-hover",
50
+ "inset",
51
+ "inset-foreground",
52
+ "brand",
53
+ "brand-bright",
54
+ "ds-sidebar-icon",
55
+ "ds-sidebar-icon-stroke",
56
+ "ds-sidebar-rail-w",
57
+ "ds-sidebar-rail-item",
58
+ "ds-sidebar-logo",
59
+ "ds-sidebar-sep-inset"
60
+ ],
61
+ "fonts": [
62
+ "ds-font-sans"
63
+ ],
64
+ "dark": {
65
+ "descripcion": "Recomendados en .dark (si faltan, el tema hereda el valor claro y doctor avisa).",
66
+ "avisar_si_falta": [
67
+ "background",
68
+ "foreground",
69
+ "card",
70
+ "card-foreground",
71
+ "popover",
72
+ "popover-foreground",
73
+ "primary",
74
+ "primary-foreground",
75
+ "muted",
76
+ "muted-foreground",
77
+ "border",
78
+ "input",
79
+ "ring",
80
+ "danger",
81
+ "warning",
82
+ "success",
83
+ "info",
84
+ "link"
85
+ ]
86
+ },
87
+ "baseTheme": "qratia",
88
+ "brand": {
89
+ "descripcion": "Grupo ESTABLE de variables que una app suele personalizar en su fichero de marca (brand.css). Renombrar o quitar una es versión MAYOR. Todas están también en `root` salvo las --ds-*.",
90
+ "tokens": [
91
+ {
92
+ "name": "primary",
93
+ "example": "oklch(0.55 0.2 260)",
94
+ "about": "color de acción principal (botones, foco)"
95
+ },
96
+ {
97
+ "name": "primary-foreground",
98
+ "example": "#ffffff",
99
+ "about": "texto sobre el color principal (comprueba el contraste)"
100
+ },
101
+ {
102
+ "name": "ring",
103
+ "example": "oklch(0.55 0.2 260)",
104
+ "about": "anillo de foco; suele ir igual que primary"
105
+ },
106
+ {
107
+ "name": "link",
108
+ "example": "oklch(0.5 0.15 260)",
109
+ "about": "texto de enlace: más oscuro que primary para tener contraste"
110
+ },
111
+ {
112
+ "name": "link-hover",
113
+ "example": "oklch(0.42 0.13 260)",
114
+ "about": "enlace al pasar el ratón"
115
+ },
116
+ {
117
+ "name": "brand",
118
+ "example": "oklch(0.7 0.13 220)",
119
+ "about": "acento de marca (detalles, selección)"
120
+ },
121
+ {
122
+ "name": "brand-bright",
123
+ "example": "oklch(0.8 0.13 220)",
124
+ "about": "acento de marca sobre fondos oscuros"
125
+ },
126
+ {
127
+ "name": "sidebar-primary",
128
+ "example": "oklch(0.8 0.13 220)",
129
+ "about": "acento dentro del sidebar"
130
+ },
131
+ {
132
+ "name": "sidebar-primary-foreground",
133
+ "example": "#04121c",
134
+ "about": "texto sobre el acento del sidebar"
135
+ },
136
+ {
137
+ "name": "sidebar-accent-foreground",
138
+ "example": "oklch(0.85 0.1 220)",
139
+ "about": "texto del destino activo del sidebar"
140
+ },
141
+ {
142
+ "name": "accent-foreground",
143
+ "example": "oklch(0.5 0.15 260)",
144
+ "about": "texto sobre superficies de acento suave"
145
+ },
146
+ {
147
+ "name": "chart-1",
148
+ "example": "oklch(0.55 0.2 260)",
149
+ "about": "primera serie de las gráficas: la marca"
150
+ },
151
+ {
152
+ "name": "radius",
153
+ "example": "12px",
154
+ "about": "redondez base (en temas cuya rampa deriva de ella)"
155
+ },
156
+ {
157
+ "name": "ds-font-sans",
158
+ "example": "'Inter', system-ui, sans-serif",
159
+ "about": "fuente del cuerpo (carga la fuente en tu app)"
160
+ },
161
+ {
162
+ "name": "ds-font-display",
163
+ "example": "'Sora', system-ui, sans-serif",
164
+ "about": "fuente de los titulares"
165
+ }
166
+ ]
167
+ }
168
+ }
package/dist/styles.css CHANGED
@@ -134,6 +134,7 @@
134
134
  */
135
135
  --ds-z-raised: 10;
136
136
  --ds-z-sticky: 20;
137
+ --ds-z-sidebar: 21; /* por encima de la cabecera sticky: su filete no debe quedar tapado */
137
138
  --ds-z-overlay: 50;
138
139
 
139
140
  --ds-motion-fast: 100ms;
@@ -192,6 +193,12 @@
192
193
  --ds-sidebar-shadow: var(--ds-shadow-raised);
193
194
  --ds-sidebar-ring: 1px;
194
195
  --ds-sidebar-edge: 0 solid transparent;
196
+ --ds-sidebar-rail-w: 4rem; /* ancho del lateral contraído (raíl de iconos) */
197
+ --ds-sidebar-rail-item: 2.5rem; /* lado del botón de cada destino en el raíl */
198
+ --ds-sidebar-icon: 1.125rem; /* tamaño de los iconos del lateral */
199
+ --ds-sidebar-icon-stroke: 2; /* grosor del trazo de esos iconos */
200
+ --ds-sidebar-logo: 2rem; /* ficha del logo y del avatar del lateral */
201
+ --ds-sidebar-sep-inset: 0rem; /* margen lateral de los separadores (negativo = de borde a borde) */
195
202
  --ds-sidebar-item-radius: var(--ds-radius-md);
196
203
  --ds-sidebar-item-h: 2.5rem;
197
204
 
@@ -433,15 +440,27 @@
433
440
  * TAMAÑO Y ALINEACIÓN DE LA NAVEGACIÓN (los `!important` baten a las
434
441
  * utilidades que el primitivo trae escritas).
435
442
  * EXPANDIDO: filas de altura `--ds-sidebar-item-h` con icono de 18px.
436
- * COLAPSADO: botón de 40px y padding lateral de 12px → icono centrado en el
437
- * raíl de 64px.
443
+ * COLAPSADO: botón cuadrado de `--ds-sidebar-rail-item` con el icono centrado,
444
+ * sin etiqueta, y el botón centrado en el raíl (`--ds-sidebar-rail-w`).
438
445
  */
439
446
  [data-sidebar='menu-button'] {
440
447
  min-height: var(--ds-sidebar-item-h);
441
448
  }
442
449
  [data-sidebar='menu-button'] svg {
443
- width: 1.125rem !important;
444
- height: 1.125rem !important;
450
+ width: var(--ds-sidebar-icon) !important;
451
+ height: var(--ds-sidebar-icon) !important;
452
+ stroke-width: var(--ds-sidebar-icon-stroke);
453
+ }
454
+ /* Logo / avatar del lateral (botones lg: marca y cuenta) */
455
+ [data-sidebar='menu-button'][data-size='lg'] > :first-child {
456
+ width: var(--ds-sidebar-logo);
457
+ height: var(--ds-sidebar-logo);
458
+ flex: 0 0 var(--ds-sidebar-logo);
459
+ }
460
+ /* Separadores: alineados con las filas (0) o de borde a borde (negativo) */
461
+ [data-slot='sidebar-separator'] {
462
+ margin-inline: var(--ds-sidebar-sep-inset);
463
+ width: auto;
445
464
  }
446
465
 
447
466
  [data-collapsible='icon'] [data-slot='sidebar-header'],
@@ -449,14 +468,19 @@
449
468
  [data-collapsible='icon'] [data-slot='sidebar-group'] {
450
469
  padding-inline: 0.75rem;
451
470
  }
471
+ /* Raíl: tecla cuadrada, centrada, con el icono centrado dentro y sin etiqueta */
452
472
  [data-collapsible='icon'] [data-sidebar='menu-button'] {
453
- width: 2.5rem !important;
454
- height: 2.5rem !important;
455
- padding: 0.6875rem !important; /* (40−18)/2: icono centrado */
473
+ width: var(--ds-sidebar-rail-item) !important;
474
+ height: var(--ds-sidebar-rail-item) !important;
475
+ min-height: var(--ds-sidebar-rail-item);
476
+ padding: 0 !important;
477
+ gap: 0;
478
+ justify-content: center;
479
+ margin-inline: auto;
456
480
  }
457
- /* Botones lg (marca, cuenta): dentro va una ficha de 32px → 4px de aire. */
458
- [data-collapsible='icon'] [data-sidebar='menu-button'][data-size='lg'] {
459
- padding: 0.25rem !important;
481
+ [data-collapsible='icon'] [data-sidebar='menu-button'] > span:last-child:not(:first-child),
482
+ [data-collapsible='icon'] [data-sidebar='menu-button'][data-size='lg'] > :not(:first-child) {
483
+ display: none;
460
484
  }
461
485
 
462
486
  /*
@@ -24,6 +24,14 @@
24
24
  --ds-font-sans: 'Rubik', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
25
25
  --ds-font-display: var(--ds-font-sans);
26
26
  --ds-font-mono: ui-monospace, 'SF Mono', Menlo, monospace;
27
+
28
+ /* Lateral: iconos, raíl, logo y separadores (cada tema fija su forma y tamaño) */
29
+ --ds-sidebar-icon: 1.25rem;
30
+ --ds-sidebar-icon-stroke: 2;
31
+ --ds-sidebar-rail-w: 4.5rem;
32
+ --ds-sidebar-rail-item: 2.75rem;
33
+ --ds-sidebar-logo: 2.25rem;
34
+ --ds-sidebar-sep-inset: 0rem;
27
35
  --ds-heading-tracking: normal;
28
36
 
29
37
  /* Color: lienzo azulado, tinta índigo, acento periwinkle + naranja cálido */
@@ -43,7 +51,7 @@
43
51
  --muted-foreground: #6b6d96;
44
52
  --accent: rgba(55, 132, 247, 0.14);
45
53
  --accent-foreground: #2a64c4;
46
- --destructive: #e5484d;
54
+ --destructive: #d04246;
47
55
  --destructive-foreground: #ffffff;
48
56
 
49
57
  --border: rgba(35, 36, 80, 0.08);
@@ -65,15 +73,15 @@
65
73
  --sidebar-border: rgba(35, 36, 80, 0.07);
66
74
  --sidebar-ring: #5f6ec9;
67
75
 
68
- --danger: #c7343a;
76
+ --danger: #bb3137;
69
77
  --danger-soft: rgba(229, 72, 77, 0.12);
70
- --warning: #9a5b00;
78
+ --warning: #955800;
71
79
  --warning-soft: rgba(251, 178, 50, 0.24);
72
- --success: #0a7d55;
80
+ --success: #097650;
73
81
  --success-soft: rgba(29, 184, 122, 0.14);
74
- --info: #2a64c4;
82
+ --info: #2962c0;
75
83
  --info-soft: rgba(55, 132, 247, 0.14);
76
- --neutral: #6b6d96;
84
+ --neutral: #616389;
77
85
  --neutral-soft: rgba(35, 36, 80, 0.07);
78
86
 
79
87
  --link: #2a64c4;
@@ -18,12 +18,20 @@
18
18
  */
19
19
 
20
20
  /* ── VARIABLES · PIEL CLARA ──────────────────────────────────────────────── */
21
- :root[data-theme='friendly'] {
21
+ :root:where([data-theme='friendly']) {
22
22
  --radius: 8px;
23
23
 
24
24
  --ds-font-sans: 'Rubik', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
25
25
  --ds-font-display: var(--ds-font-sans);
26
26
  --ds-font-mono: ui-monospace, 'SF Mono', Menlo, monospace;
27
+
28
+ /* Lateral: iconos, raíl, logo y separadores (cada tema fija su forma y tamaño) */
29
+ --ds-sidebar-icon: 1.25rem;
30
+ --ds-sidebar-icon-stroke: 2;
31
+ --ds-sidebar-rail-w: 4.5rem;
32
+ --ds-sidebar-rail-item: 2.75rem;
33
+ --ds-sidebar-logo: 2.25rem;
34
+ --ds-sidebar-sep-inset: 0rem;
27
35
  --ds-heading-tracking: normal;
28
36
 
29
37
  /* Color: lienzo azulado, tinta índigo, acento periwinkle + naranja cálido */
@@ -43,7 +51,7 @@
43
51
  --muted-foreground: #6b6d96;
44
52
  --accent: rgba(55, 132, 247, 0.14);
45
53
  --accent-foreground: #2a64c4;
46
- --destructive: #e5484d;
54
+ --destructive: #d04246;
47
55
  --destructive-foreground: #ffffff;
48
56
 
49
57
  --border: rgba(35, 36, 80, 0.08);
@@ -65,15 +73,15 @@
65
73
  --sidebar-border: rgba(35, 36, 80, 0.07);
66
74
  --sidebar-ring: #5f6ec9;
67
75
 
68
- --danger: #c7343a;
76
+ --danger: #bb3137;
69
77
  --danger-soft: rgba(229, 72, 77, 0.12);
70
- --warning: #9a5b00;
78
+ --warning: #955800;
71
79
  --warning-soft: rgba(251, 178, 50, 0.24);
72
- --success: #0a7d55;
80
+ --success: #097650;
73
81
  --success-soft: rgba(29, 184, 122, 0.14);
74
- --info: #2a64c4;
82
+ --info: #2962c0;
75
83
  --info-soft: rgba(55, 132, 247, 0.14);
76
- --neutral: #6b6d96;
84
+ --neutral: #616389;
77
85
  --neutral-soft: rgba(35, 36, 80, 0.07);
78
86
 
79
87
  --link: #2a64c4;
@@ -137,7 +145,7 @@
137
145
  }
138
146
 
139
147
  /* ── VARIABLES · PIEL OSCURA («noche índigo») ────────────────────────────── */
140
- :root[data-theme='friendly'].dark {
148
+ :where(:root[data-theme='friendly']).dark {
141
149
  --background: #16173b;
142
150
  --foreground: #ecedfa;
143
151
 
@@ -210,7 +218,7 @@
210
218
  /* ── PERSONALIDAD ────────────────────────────────────────────────────────────
211
219
  * Sin capa: gana a las utilidades de los componentes. Solo variables.
212
220
  */
213
- :root[data-theme='friendly'] {
221
+ :root:where([data-theme='friendly']) {
214
222
  /* Botones: píldora en mayúsculas con espaciado, y brillo de color debajo */
215
223
  [data-slot='button'] {
216
224
  border-radius: 9999px;
@@ -14,6 +14,14 @@
14
14
  /* Tipografía: Instrument Sans (fuentes en qratia.fonts.css) */
15
15
  --ds-font-sans: 'Instrument Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
16
16
  --ds-font-mono: ui-monospace, 'SF Mono', Menlo, monospace;
17
+
18
+ /* Lateral: iconos, raíl, logo y separadores (cada tema fija su forma y tamaño) */
19
+ --ds-sidebar-icon: 1.125rem;
20
+ --ds-sidebar-icon-stroke: 2;
21
+ --ds-sidebar-rail-w: 4rem;
22
+ --ds-sidebar-rail-item: 2.5rem;
23
+ --ds-sidebar-logo: 2rem;
24
+ --ds-sidebar-sep-inset: 0rem;
17
25
 
18
26
  /*
19
27
  * Dos sombras de tarjeta: reposo y realce al señalar, EN CAPAS y TINTADAS con
@@ -8,12 +8,20 @@
8
8
  * DESIGN.md. Las utilidades de Tailwind se derivan en styles.css (@theme).
9
9
  */
10
10
 
11
- :root[data-theme='qratia'] {
11
+ :root:where([data-theme='qratia']) {
12
12
  --radius: 0.625rem;
13
13
 
14
14
  /* Tipografía: Instrument Sans (fuentes en qratia.fonts.css) */
15
15
  --ds-font-sans: 'Instrument Sans', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
16
16
  --ds-font-mono: ui-monospace, 'SF Mono', Menlo, monospace;
17
+
18
+ /* Lateral: iconos, raíl, logo y separadores (cada tema fija su forma y tamaño) */
19
+ --ds-sidebar-icon: 1.125rem;
20
+ --ds-sidebar-icon-stroke: 2;
21
+ --ds-sidebar-rail-w: 4rem;
22
+ --ds-sidebar-rail-item: 2.5rem;
23
+ --ds-sidebar-logo: 2rem;
24
+ --ds-sidebar-sep-inset: 0rem;
17
25
 
18
26
  /*
19
27
  * Dos sombras de tarjeta: reposo y realce al señalar, EN CAPAS y TINTADAS con
@@ -161,7 +169,7 @@
161
169
  --sidebar-ring: oklch(0.711 0.129 219);
162
170
  }
163
171
 
164
- :root[data-theme='qratia'].dark {
172
+ :where(:root[data-theme='qratia']).dark {
165
173
  /*
166
174
  * Gris elevado, no negro. Un fondo casi negro con texto claro produce halación
167
175
  * y en jornadas de revisión eso cansa. Conserva los tres niveles de superficie.