@netzi/tokens 0.1.0-beta.10

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.
@@ -0,0 +1,1426 @@
1
+ /* ===========================================================
2
+ @netzi/tokens — Design tokens (CSS custom properties)
3
+
4
+ ARCHIVO GENERADO desde la fuente DTCG (formato del W3C Design Tokens
5
+ Community Group, 2025.10): no se edita a mano. Un test comprueba que no se
6
+ desincronizan.
7
+
8
+ Ejes de tema (los aplica NetziThemeService sobre <html>):
9
+ [data-theme=dark] → tema OSCURO (default: claro)
10
+ [data-theme=light] → claro también en una sección dentro de una oscura
11
+ [data-preset=...] → color primario (blue|green|purple|orange|red|cyan)
12
+ [data-contrast=high] → más contraste (bordes/texto); sin el atributo
13
+ sigue a prefers-contrast: more, y normal lo fija
14
+ [data-glass=on] → capas flotantes de cristal (translúcidas)
15
+ [data-ambient=on] → fondo ambiental bajo el contenido
16
+ [data-density=compact] → controles más compactos
17
+ dir=rtl → de derecha a izquierda (CSS usa props lógicas)
18
+ prefers-reduced-motion → las duraciones de desplazamiento (move) se anulan
19
+ print → papel: los ejes oscuro, cristal y ambiental no aplican
20
+ (van en @media not print); sin sombras ni movimiento
21
+ --netzi-font-sans inline → familia tipográfica
22
+
23
+ OVERRIDE (white-label por app): redefine cualquier token en tu propio scope.
24
+ Las actualizaciones de este paquete cambian SOLO los defaults.
25
+ =========================================================== */
26
+
27
+ :root {
28
+ /* Capa 1 — PRIMITIVOS. Valores de marca y escalas, iguales en todos los temas. Los semánticos
29
+ y los de componente se apoyan en ellos. */
30
+ /* Colores de marca para RELLENO: saturados, para que un fondo, un punto de estado o una barra
31
+ de gráfica se vean. Como texto sobre una superficie clara no llegan al mínimo; para lo que
32
+ se lee está su variante text (capa semántica). */
33
+ --netzi-blue: #0ba5ff;
34
+ --netzi-blue-dark: #0476c2;
35
+ --netzi-green: #0ae972;
36
+ --netzi-purple: #8c4cff;
37
+ --netzi-red: #ff6b6b;
38
+ --netzi-yellow: #f0c040;
39
+ /* Forma: radios de esquina, la materia prima de los radios por papel (capa semántica:
40
+ control, surface, pill). La densidad compacta los reduce. */
41
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa --netzi-radius-surface-sm
42
+ (paneles de un control, avisos, tarjetas compactas). Deprecado en @netzi/tokens
43
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
44
+ --netzi-radius: 8px;
45
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa --netzi-radius-control
46
+ (controles y piezas pequeñas). Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como
47
+ pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
48
+ --netzi-radius-sm: 6px;
49
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa --netzi-radius-surface
50
+ (tarjetas, diálogos, paneles). Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como
51
+ pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
52
+ --netzi-radius-lg: 10px;
53
+ /* Del todo redondeado (#220): la materia prima de --netzi-radius-pill. La densidad compacta
54
+ no lo toca. Interna: no llegó a publicarse como pública (#228). */
55
+ --netzi-radius-full: 9999px;
56
+ /* Espaciado de layout (base 4px): la materia prima de los espaciados por papel (capa
57
+ semántica: related, group, stack, inset, section, page). Pública solo mientras convive su
58
+ desuso (#228). La densidad compacta reduce los pasos medios y grandes. */
59
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa 0, que no necesita token.
60
+ Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como pronto en @netzi/tokens
61
+ 0.1.0-beta.11, cuando pasa a interna. */
62
+ --netzi-space-0: 0;
63
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): sin papel propio (2px no es
64
+ un paso del ritmo de layout); entre piezas de un mismo elemento usa --netzi-space-related.
65
+ Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como pronto en @netzi/tokens
66
+ 0.1.0-beta.11, cuando pasa a interna. */
67
+ --netzi-space-1: 2px;
68
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa --netzi-space-related
69
+ (piezas de un mismo elemento). Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como
70
+ pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
71
+ --netzi-space-2: 4px;
72
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa --netzi-space-group
73
+ (elementos hermanos de un grupo). Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como
74
+ pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
75
+ --netzi-space-3: 8px;
76
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa --netzi-space-stack
77
+ (grupos apilados) o --netzi-space-inset-sm (relleno compacto). Deprecado en @netzi/tokens
78
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
79
+ --netzi-space-4: 12px;
80
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa --netzi-space-inset
81
+ (relleno de una tarjeta o un panel). Deprecado en @netzi/tokens 0.1.0-beta.10; se retira
82
+ como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
83
+ --netzi-space-5: 16px;
84
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa --netzi-space-inset-lg
85
+ (relleno de un diálogo o un panel grande). Deprecado en @netzi/tokens 0.1.0-beta.10; se
86
+ retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
87
+ --netzi-space-6: 24px;
88
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa --netzi-space-section
89
+ (entre secciones de una página). Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como
90
+ pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
91
+ --netzi-space-7: 32px;
92
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa --netzi-space-page (entre
93
+ regiones de una página y su margen). Deprecado en @netzi/tokens 0.1.0-beta.10; se retira
94
+ como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
95
+ --netzi-space-8: 48px;
96
+ /* Escala tipográfica: la materia prima de los estilos de texto (typography, capa semántica).
97
+ Pública solo mientras convive su desuso (#228). */
98
+ /* Escala tipográfica (#51) para el texto que NO es un control: líneas secundarias, pies,
99
+ metadatos, títulos. Ratio cercano a 1.15 y md = 14px, que es el 100 % de la escala (el
100
+ panel de ajustes divide entre 14). Todos escalan con el ajuste de accesibilidad; la
101
+ densidad compacta no los toca: el texto no se encoge, se encoge el aire. */
102
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el tamaño de su papel,
103
+ --netzi-typography-caption-font-size (#155), o su estilo de texto entero,
104
+ --netzi-typography-caption. Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como pronto
105
+ en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
106
+ --netzi-font-size-xs: calc(11px * var(--netzi-font-scale, 1));
107
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el tamaño de su papel,
108
+ --netzi-typography-body-sm-font-size (#155), o su estilo de texto entero,
109
+ --netzi-typography-body-sm. Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como pronto
110
+ en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
111
+ --netzi-font-size-sm: calc(12.5px * var(--netzi-font-scale, 1));
112
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el tamaño de su papel,
113
+ --netzi-typography-body-ui-font-size (#155), o su estilo de texto entero,
114
+ --netzi-typography-body-ui. Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como pronto
115
+ en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
116
+ --netzi-font-size-md: calc(14px * var(--netzi-font-scale, 1));
117
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el tamaño de su papel,
118
+ --netzi-typography-body-font-size (#155), o su estilo de texto entero,
119
+ --netzi-typography-body. Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como pronto en
120
+ @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
121
+ --netzi-font-size-lg: calc(16px * var(--netzi-font-scale, 1));
122
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el tamaño de su papel,
123
+ --netzi-typography-title-font-size (#155), o su estilo de texto entero,
124
+ --netzi-typography-title. Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como pronto
125
+ en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
126
+ --netzi-font-size-xl: calc(18px * var(--netzi-font-scale, 1));
127
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el tamaño de su papel,
128
+ --netzi-typography-headline-font-size (#155), o su estilo de texto entero,
129
+ --netzi-typography-headline. Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como
130
+ pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
131
+ --netzi-font-size-2xl: calc(22px * var(--netzi-font-scale, 1));
132
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el tamaño de su papel,
133
+ --netzi-typography-display-font-size (#155), o su estilo de texto entero,
134
+ --netzi-typography-display. Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como pronto
135
+ en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
136
+ --netzi-font-size-3xl: calc(28px * var(--netzi-font-scale, 1));
137
+ /* Peso. Los cinco cortes que trae la fuente cargada (fonts.css); otro valor se sintetiza y se
138
+ ve peor. */
139
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el estilo de texto de su
140
+ papel (--netzi-typography-body, --netzi-typography-body-sm). Deprecado en @netzi/tokens
141
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
142
+ --netzi-font-weight-regular: 400;
143
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): sin estilo propio; usa el
144
+ estilo de texto de su papel (--netzi-typography-body). Deprecado en @netzi/tokens
145
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
146
+ --netzi-font-weight-medium: 500;
147
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el estilo de texto de su
148
+ papel (--netzi-typography-title-sm, --netzi-typography-caption). Deprecado en @netzi/tokens
149
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
150
+ --netzi-font-weight-semibold: 600;
151
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el estilo de texto de su
152
+ papel (--netzi-typography-title, --netzi-typography-headline). Deprecado en @netzi/tokens
153
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
154
+ --netzi-font-weight-bold: 700;
155
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el estilo de texto de su
156
+ papel, --netzi-typography-display. Deprecado en @netzi/tokens 0.1.0-beta.10; se retira como
157
+ pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
158
+ --netzi-font-weight-extrabold: 800;
159
+ /* Interlineado sin unidad: none para lo que mide una línea, tight para títulos, normal para
160
+ texto corriente, relaxed para lectura larga. Materia prima de los estilos de texto
161
+ (typography); pública solo mientras convive su desuso (#228). */
162
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): sin estilo propio; cada
163
+ estilo de texto trae su interlineado (--netzi-typography-caption). Deprecado en
164
+ @netzi/tokens 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando
165
+ pasa a interna. */
166
+ --netzi-line-height-none: 1;
167
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el estilo de texto de su
168
+ papel (--netzi-typography-title, --netzi-typography-caption). Deprecado en @netzi/tokens
169
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
170
+ --netzi-line-height-tight: 1.25;
171
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): usa el estilo de texto de su
172
+ papel (--netzi-typography-body, --netzi-typography-body-sm). Deprecado en @netzi/tokens
173
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
174
+ --netzi-line-height-normal: 1.5;
175
+ /* deprecated: Escala primitiva, en desuso para las apps (#228): sin estilo propio; cada
176
+ estilo de texto trae su interlineado (--netzi-typography-body). Deprecado en @netzi/tokens
177
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11, cuando pasa a interna. */
178
+ --netzi-line-height-relaxed: 1.65;
179
+ /* Capa 2 — SEMÁNTICOS. Papeles (superficie, texto, borde, primario, estado) con los valores
180
+ del tema por defecto: claro, contraste normal y preset azul. Los ejes de tema (themes/) los
181
+ redefinen. */
182
+ /* Los colores de marca PARA TEXTO: su versión legible, oscurecida en claro y aclarada en
183
+ oscuro solo donde hace falta. Si lo que pintas se lee, va el text; si es relleno, el de
184
+ marca (el verde de relleno daba 1.63:1 como texto). */
185
+ --netzi-blue-text: #076aa3;
186
+ /* Los colores de marca para lo NO textual que comunica un estado (#189): la estrella marcada,
187
+ el punto de presencia, el icono de un resultado sobre su velo, el borde de un campo
188
+ inválido. Llegan a 3:1 (WCAG 1.4.11) sobre cada superficie y sobre su propio velo (el veil
189
+ del estado); el crudo no llega en claro (azul 2.08:1, verde 1.33, amarillo 1.41, rojo 2.15
190
+ en el peor fondo) y el text cumple de sobra pero se aleja del color. Es el tono más cercano
191
+ al crudo que llega; en oscuro, el crudo tal cual. */
192
+ --netzi-blue-graphic: #0e84cd;
193
+ --netzi-green-text: #05773a;
194
+ --netzi-green-graphic: #069047;
195
+ --netzi-yellow-text: #7d6421;
196
+ --netzi-yellow-graphic: #9d7a0c;
197
+ --netzi-red-text: #a34444;
198
+ --netzi-red-graphic: #df464b;
199
+ --netzi-purple-text: #743fd4;
200
+ /* Alias de estado: el mismo color con el nombre de lo que significa. Existen porque toda app
201
+ los da por hechos, y un token que no existe muere en silencio (la declaración entera se
202
+ descarta sin aviso). Son referencias, no copias, para que sigan al color aunque cambie.
203
+ Mismo reparto que la marca: el raíz es RELLENO y el text es lo que se lee. */
204
+ --netzi-info: var(--netzi-blue);
205
+ --netzi-success: var(--netzi-green);
206
+ --netzi-warning: var(--netzi-yellow);
207
+ --netzi-danger: var(--netzi-red);
208
+ /* Superficies de contenido, de la más clara a la más marcada. */
209
+ --netzi-surface: #ffffff;
210
+ --netzi-surface-2: #f4f6f8;
211
+ --netzi-surface-3: #eef1f4;
212
+ /* Texto: tres niveles con papeles DISTINTOS, no tres grados de gris intercambiables. text es
213
+ el texto principal; text-2 es CUALQUIER texto secundario legible (rótulos, ayudas, pies,
214
+ metadatos, placeholders) y es el suelo de 4.5:1; text-3 es lo NO textual (iconos
215
+ decorativos, separadores, chevrons, líneas, estados deshabilitados) y cumple 3:1, no 4.5:1.
216
+ El papel de cada uno lo fija su contrato de contraste y lo comprueba el build: si lo que
217
+ pintas se lee, va text-2. */
218
+ --netzi-text: #1c252e;
219
+ --netzi-text-2: #5c6b78;
220
+ /* NO vale para texto legible (3:1, SC 1.4.11). Es el tono de lo que acompaña: chevrons,
221
+ separadores, iconos decorativos, la barra de redimensionar, el brillo del esqueleto de
222
+ carga y los estados deshabilitados. La regla existe porque con 45 archivos usándolo
223
+ indistintamente el kit entero se quedó por debajo del mínimo sin que nadie lo notara. */
224
+ --netzi-text-3: #7a8996;
225
+ /* Radios por papel (#228): el de lo que se pulsa, el de una superficie y el de lo del todo
226
+ redondeado. Apuntan a la escala de forma, así que la densidad compacta los reduce (salvo la
227
+ píldora); se redeclaran en cada elemento con densidad propia. */
228
+ /* Del todo redondeado: píldoras, puntos, avatares e interruptores; en una pieza cuadrada, un
229
+ círculo. Sustituye a los 999px y 50% sueltos (#220). La densidad no lo toca. */
230
+ --netzi-radius-pill: var(--netzi-radius-full);
231
+ /* Color PRIMARIO, themeable por preset (eje preset); por defecto, el azul de marca. */
232
+ --netzi-primary: var(--netzi-blue);
233
+ /* El relleno de lo marcado en checkbox, radio y toggle: frente a cualquier superficie, no
234
+ solo al fondo de la página (#147). Lleva on-primary-dark encima. */
235
+ --netzi-primary-dark: var(--netzi-blue-dark);
236
+ /* El relleno del primario al pasar el puntero, con la MISMA tinta encima (on-primary). No es
237
+ primary-dark: ese es el fondo de lo que lleva blanco (pulgar, marca del checkbox), y la
238
+ tinta oscura sobre él se quedaba en 3.93:1 en azul y 4.0:1 en rojo (#68). Cada preset
239
+ declara el suyo: más oscuro que su primario, pero sin bajar de 4.5:1 con su tinta. */
240
+ --netzi-primary-hover: #0a8fdd;
241
+ /* El relleno del primario PRESIONADO (#156), con la misma tinta encima (on-primary). Es su
242
+ hover con la capa de presionado (state.pressed.opacity, 12 %) del color que se aleja de su
243
+ tinta: blanco si la tinta es oscura, negro si es blanca. No lleva la capa de texto de los
244
+ demás controles porque sobre un relleno de marca acerca el fondo a la tinta y la dejaba en
245
+ 3.8:1; así el presionado se distingue del hover y la tinta no baja de 4.5:1 en ningún
246
+ preset ni tema. Cada preset declara el suyo. */
247
+ --netzi-primary-pressed: #279ce1;
248
+ /* El primario PARA TEXTO (enlaces, ítem activo del menú, cifras destacadas). Cada preset y
249
+ cada tema lo redefinen: el crudo no llega a 4.5:1 sobre superficie clara. */
250
+ --netzi-primary-text: #076ba6;
251
+ /* El primario para lo NO textual que tiene que verse (#140): el relleno de una barra de
252
+ progreso, el anillo de carga del rail, la barra de navegación. Llega a 3:1 (WCAG 1.4.11)
253
+ sobre cada superficie y sobre el tinte del primario, que es el fondo del ítem activo. El
254
+ crudo no llega en claro con azul (2.15:1), verde (1.36), naranja (1.78), rojo (2.51) ni
255
+ cian (1.92), y primary-text cumple de sobra pero se aleja del color de marca: este es el
256
+ tono más cercano al primario que llega, calibrado por preset y por tema. Algo que LATE en
257
+ opacidad no vale con este: en el valle del latido baja de 3:1, y por eso esos indicadores
258
+ van con primary-text. */
259
+ --netzi-primary-graphic: #0987d2;
260
+ /* La TINTA sobre el relleno del primario: cada preset usa la que cumple sobre SU color, no
261
+ una fija (el blanco sobre el azul da 2.68:1 y la tinta oscura 7.05:1). */
262
+ --netzi-on-primary: #04121f;
263
+ /* Lo que va ENCIMA de primary-dark: el pulgar del interruptor, la marca del checkbox, el
264
+ punto del radio. Blanco en todos los presets: el primario oscuro es lo bastante oscuro para
265
+ que el blanco pase de 3:1 (el mínimo de un control) en cada uno. on-primary no sirve para
266
+ esto: sobre el azul claro tiene que ser casi negro, y un pulgar negro sobre un interruptor
267
+ azul se ve raro. */
268
+ --netzi-on-primary-dark: #ffffff;
269
+ /* Tinta sobre un relleno de color de marca (verde, rojo, amarillo…): todos son claros, así
270
+ que la oscura es la que cumple. El blanco daba 2.78:1 sobre el rojo del contador de
271
+ notificaciones. */
272
+ --netzi-on-accent: #04121f;
273
+ /* Estados de interacción como UN sistema (#156, criterio B.7): una capa translúcida por
274
+ estado, que se pinta ENCIMA del fondo del control sin cambiarlo, con su opacidad. La capa
275
+ es del color del texto (text), así que oscurece en claro y aclara en oscuro, y la etiqueta
276
+ en text sigue a 4.5:1 sobre cada superficie con cualquier capa encima: el build lo
277
+ comprueba. El orden de las opacidades es el del gesto, de menos a más: hover 8 %, foco 12
278
+ %, presionado 12 % y arrastrado 16 %. Las opacidades van aparte (state.*.opacity) para la
279
+ plataforma que pinta la capa con su propio color; en CSS la capa ya es un color
280
+ (--netzi-state-pressed) y se pinta como imagen de fondo, que no se anima: aparece al
281
+ instante, también con movimiento reducido y con el dedo. Un control con fondo de marca no
282
+ lleva capa: tiene su propio color presionado (primary.pressed). El foco, además, conserva
283
+ su anillo (focus-ring), que es lo que exige WCAG 2.4.7; el seleccionado es el tinte del
284
+ primario. */
285
+ --netzi-state-hover-opacity: 0.08;
286
+ --netzi-state-focus-opacity: 0.12;
287
+ --netzi-state-pressed-opacity: 0.12;
288
+ --netzi-state-dragged-opacity: 0.16;
289
+ /* El tratamiento de lo DESHABILITADO: una sola opacidad sobre el control entero (antes había
290
+ seis, de 0.3 a 0.8). Un control deshabilitado no recibe el foco de teclado ni actúa, pero
291
+ el lector de pantalla lo lee y lo anuncia como no disponible (disabled o aria-disabled).
292
+ WCAG no pide contraste a lo deshabilitado; aun así su texto en text se queda a 3:1 sobre
293
+ cada superficie, para que se vea que está ahí: el build lo comprueba. */
294
+ --netzi-state-disabled-opacity: 0.6;
295
+ /* Fondo de la página. */
296
+ --netzi-bg: #f7f9fb;
297
+ /* Bordes. */
298
+ --netzi-border: #eaedf0;
299
+ --netzi-border-2: #dce0e5;
300
+ /* Elevación (#220): cuánto se despega una pieza de lo que tiene debajo, con nombre de
301
+ intención y de menos a más. En la web se pinta con sombra (y con el borde de cada pieza:
302
+ una sombra nunca es lo único que separa una capa); en papel no hay ninguna. Cada plataforma
303
+ la pinta a su manera, con el mismo nivel. */
304
+ /* Base: pegado a su superficie, sin sombra. Para devolver a cero una pieza que hereda
305
+ elevación. */
306
+ --netzi-elevation-base: 0 0 rgba(0, 0, 0, 0);
307
+ /* Elevado: una pieza levantada sobre su propia superficie, como el pulgar de un interruptor o
308
+ de un deslizador, la pastilla del segmentado o una tecla. */
309
+ --netzi-elevation-raised: 0 1px 2px rgba(145, 158, 171, 0.16);
310
+ /* Flotante: algo pequeño y suelto que flota sobre el contenido, como el tooltip, la etiqueta
311
+ de una gráfica, el enlace «Ir al contenido» o la esfera del reloj. */
312
+ --netzi-elevation-floating:
313
+ 0 0 2px rgba(145, 158, 171, 0.2), 0 12px 24px -4px rgba(145, 158, 171, 0.12);
314
+ /* Modal: las capas que se abren encima del contenido y lo apartan, como los desplegables, los
315
+ menús, el aviso, los diálogos y los paneles laterales. */
316
+ --netzi-elevation-modal:
317
+ 0 0 2px rgba(145, 158, 171, 0.2), 0 16px 40px -8px rgba(145, 158, 171, 0.24);
318
+ /* Espaciado por papel (#228), de lo más cercano a lo más lejano: cuanto más relacionadas dos
319
+ cosas, menos aire entre ellas (proximidad). Apuntan a la escala primitiva de base 4px; la
320
+ densidad compacta reduce desde stack hacia arriba, y por eso esos se redeclaran en cada
321
+ elemento con densidad propia. */
322
+ /* Entre piezas de un mismo elemento: icono y texto, los chips de una lista, una rejilla de
323
+ muestras, un campo y su ayuda. */
324
+ --netzi-space-related: var(--netzi-space-2);
325
+ /* Entre elementos hermanos de un grupo: los botones de una barra, la cabecera de un bloque y
326
+ lo que tiene debajo. */
327
+ --netzi-space-group: var(--netzi-space-3);
328
+ /* Familias y escala de letra: papeles, no pasos. La app puede cambiar la familia en línea
329
+ sobre la raíz; la escala la cambia el ajuste de tamaño de letra. */
330
+ /* Familia tipográfica del texto. La app puede cambiarla en línea sobre la raíz. */
331
+ --netzi-font-sans:
332
+ 'Plus Jakarta Sans', 'Plus Jakarta Sans Fallback', -apple-system, system-ui, sans-serif;
333
+ /* Familia monoespaciada: código, identificadores y cifras que se comparan columna a columna. */
334
+ --netzi-font-mono: 'Fira Code', 'Fira Code Fallback', ui-monospace, monospace;
335
+ /* Escala global del tamaño de letra (1 = 100 %). Los tamaños con fontScale la multiplican; la
336
+ cambia el panel de ajustes (ajuste de accesibilidad). */
337
+ --netzi-font-scale: 1;
338
+ /* Estilos de texto (#220): familia, tamaño, peso, interlineado y espaciado entre letras
339
+ juntos, con el nombre de su papel; cada paso de la escala tiene al menos uno. En CSS cada
340
+ uno sale como el atajo font (que no incluye el espaciado), su -letter-spacing aparte y su
341
+ -font-size, el tamaño solo, para quien pone el peso y el interlineado por su cuenta (#155).
342
+ Todo escala con el ajuste de tamaño de letra: el tamaño porque es el de la escala y el
343
+ espaciado porque el estilo lleva fontScale. */
344
+ /* Cifras grandes y portadas: 3xl, extrabold, apretado. */
345
+ --netzi-typography-display: var(--netzi-font-weight-extrabold) var(--netzi-font-size-3xl) /
346
+ var(--netzi-line-height-tight) var(--netzi-font-sans);
347
+ --netzi-typography-display-letter-spacing: calc(-0.5px * var(--netzi-font-scale, 1));
348
+ --netzi-typography-display-font-size: var(--netzi-font-size-3xl);
349
+ /* Títulos de página: 2xl, bold, apretado. */
350
+ --netzi-typography-headline: var(--netzi-font-weight-bold) var(--netzi-font-size-2xl) /
351
+ var(--netzi-line-height-tight) var(--netzi-font-sans);
352
+ --netzi-typography-headline-letter-spacing: calc(-0.2px * var(--netzi-font-scale, 1));
353
+ --netzi-typography-headline-font-size: var(--netzi-font-size-2xl);
354
+ /* Títulos de sección: xl, bold, apretado. */
355
+ --netzi-typography-title: var(--netzi-font-weight-bold) var(--netzi-font-size-xl) /
356
+ var(--netzi-line-height-tight) var(--netzi-font-sans);
357
+ --netzi-typography-title-letter-spacing: 0;
358
+ --netzi-typography-title-font-size: var(--netzi-font-size-xl);
359
+ /* Texto destacado y títulos de tarjeta: lg, semibold, apretado. */
360
+ --netzi-typography-title-sm: var(--netzi-font-weight-semibold) var(--netzi-font-size-lg) /
361
+ var(--netzi-line-height-tight) var(--netzi-font-sans);
362
+ --netzi-typography-title-sm-letter-spacing: 0;
363
+ --netzi-typography-title-sm-font-size: var(--netzi-font-size-lg);
364
+ /* Texto corrido (#219, ADR 0015): párrafos, descripciones de bloque y contenido que se lee
365
+ como prosa. lg (16 px, política 17 § 4), regular, interlineado normal. */
366
+ --netzi-typography-body: var(--netzi-font-weight-regular) var(--netzi-font-size-lg) /
367
+ var(--netzi-line-height-normal) var(--netzi-font-sans);
368
+ --netzi-typography-body-letter-spacing: 0;
369
+ --netzi-typography-body-font-size: var(--netzi-font-size-lg);
370
+ /* Texto de interfaz (#219, ADR 0015): opciones de menú y de lista, pestañas, celdas de tabla
371
+ y mensajes breves, lo que se recorre con la vista más que leerse. md (14 px), regular,
372
+ interlineado normal. */
373
+ --netzi-typography-body-ui: var(--netzi-font-weight-regular) var(--netzi-font-size-md) /
374
+ var(--netzi-line-height-normal) var(--netzi-font-sans);
375
+ --netzi-typography-body-ui-letter-spacing: 0;
376
+ --netzi-typography-body-ui-font-size: var(--netzi-font-size-md);
377
+ /* Líneas secundarias, pistas, pies y celdas compactas: sm, regular, interlineado normal. */
378
+ --netzi-typography-body-sm: var(--netzi-font-weight-regular) var(--netzi-font-size-sm) /
379
+ var(--netzi-line-height-normal) var(--netzi-font-sans);
380
+ --netzi-typography-body-sm-letter-spacing: 0;
381
+ --netzi-typography-body-sm-font-size: var(--netzi-font-size-sm);
382
+ /* Metadatos y etiquetas cortas: xs, semibold, apretado y algo abierto (en mayúsculas, el
383
+ text-transform lo pone quien lo usa). */
384
+ --netzi-typography-caption: var(--netzi-font-weight-semibold) var(--netzi-font-size-xs) /
385
+ var(--netzi-line-height-tight) var(--netzi-font-sans);
386
+ --netzi-typography-caption-letter-spacing: calc(0.5px * var(--netzi-font-scale, 1));
387
+ --netzi-typography-caption-font-size: var(--netzi-font-size-xs);
388
+ /* Movimiento: duraciones por intención (#151). instant para la respuesta a una pulsación,
389
+ fast para el hover y los cambios de color, base para lo que se despliega o gira, slow para
390
+ los paneles y capas que entran. Son las de los fundidos: no cambian con movimiento
391
+ reducido. Lo que desplaza, gira, escala o cambia la geometría usa las de move, que con
392
+ movimiento reducido se anulan. flash y loop no son cambios de estado y quedan fuera de esa
393
+ escala (#214). */
394
+ --netzi-duration-instant: 100ms;
395
+ --netzi-duration-fast: 150ms;
396
+ --netzi-duration-base: 200ms;
397
+ --netzi-duration-slow: 280ms;
398
+ /* Un aviso que se enciende, se deja ver y se apaga solo, sin que nadie lo cierre (el destello
399
+ de error de un ítem del menú). Largo a propósito: tiene que dar tiempo a verlo. */
400
+ --netzi-duration-flash: 1400ms;
401
+ /* Bucles (#214): la duración de UNA vuelta de una animación infinita, no la de un cambio de
402
+ estado. spin para el giro de un indicador de carga; orbit para el anillo que recorre el
403
+ borde de un ítem o de una pestaña que carga; pulse para el latido de opacidad que sustituye
404
+ al giro con movimiento reducido; sweep para la barra de progreso indeterminada; shine para
405
+ el brillo del skeleton. No cambian con movimiento reducido: cada hoja quita o sustituye su
406
+ bucle en su propia regla. */
407
+ --netzi-duration-loop-spin: 700ms;
408
+ --netzi-duration-loop-orbit: 1100ms;
409
+ --netzi-duration-loop-pulse: 1200ms;
410
+ --netzi-duration-loop-sweep: 1200ms;
411
+ --netzi-duration-loop-shine: 1300ms;
412
+ /* Duraciones del DESPLAZAMIENTO (#151): transform, translate, rotate, scale, la posición y la
413
+ geometría (alturas, filas de rejilla, márgenes). Valen lo mismo que fast, base y slow, pero
414
+ con prefers-reduced-motion se anulan en un solo sitio (themes/motion) y lo que las usa
415
+ salta sin moverse, mientras los fundidos de color y opacidad conservan su duración. */
416
+ --netzi-duration-move-fast: var(--netzi-duration-fast);
417
+ --netzi-duration-move-base: var(--netzi-duration-base);
418
+ --netzi-duration-move-slow: var(--netzi-duration-slow);
419
+ /* Movimiento: curvas por intención (#151). standard para lo que cambia sin entrar ni salir
420
+ (la de ease de CSS), enter para lo que aparece (frena al llegar), exit para lo que se va
421
+ (acelera al irse), settle para lo que llega, se pasa un poco y se asienta (un rebote
422
+ sutil). Para los bucles (#214): swing para lo que va y vuelve, arrancando y frenando en
423
+ cada vuelta (la de ease-in-out: latidos, barridos, brillos), y spin para lo que gira sin
424
+ fin a velocidad constante (la de linear). */
425
+ --netzi-ease-standard: cubic-bezier(0.25, 0.1, 0.25, 1);
426
+ --netzi-ease-enter: cubic-bezier(0.16, 1, 0.3, 1);
427
+ --netzi-ease-exit: cubic-bezier(0.4, 0, 1, 1);
428
+ --netzi-ease-settle: cubic-bezier(0.34, 1.45, 0.5, 1);
429
+ --netzi-ease-swing: cubic-bezier(0.42, 0, 0.58, 1);
430
+ --netzi-ease-spin: cubic-bezier(0, 0, 1, 1);
431
+ /* MEDIDA legible del texto corrido (#213, criterio C.9): el ancho máximo de un párrafo, una
432
+ descripción o un aviso, para que cada línea se quede en unos 40 a 75 caracteres (64 de
433
+ mediana) en cualquier ancho de ventana. Se aplica al TEXTO (max-inline-size en el párrafo),
434
+ nunca a la página ni a la sección: el hueco junto al texto lo llenan el contenido auxiliar,
435
+ las acciones, otro panel, la rejilla o la prosa en columnas entre párrafos; un párrafo no
436
+ se parte en columnas, y una descripción corta puede dejar hueco. En em, que escala con el
437
+ tamaño de letra del propio párrafo, y NO en ch: el ch es el ancho del cero de la fuente que
438
+ pinta en ese momento, y el de la fuente de respaldo mide un 21 % menos que el de Plus
439
+ Jakarta Sans, así que al llegar la fuente de marca cada párrafo acotado cambiaba de ancho y
440
+ rehacía sus líneas (C.12). Solo CSS: el formato DTCG no admite em, y en móvil la medida la
441
+ dan los paneles y las clases de tamaño. */
442
+ --netzi-measure: 33em;
443
+ /* Capas de apilamiento (#215): el z-index de lo que se pinta encima de otra cosa sale de
444
+ aquí, con nombre de intención y en este orden, de abajo arriba. Un componente no escribe
445
+ números sueltos: dentro de su propia capa solo usa -1, 0 o 1, o un escalón sobre su capa
446
+ con calc(). Los huecos entre valores dejan sitio a la app sin tener que mover la escala. */
447
+ /* El contenido de la página: el punto de partida. */
448
+ --netzi-layer-content: 0;
449
+ /* Pegajoso: encabezados y columnas fijas que se quedan quietos mientras el contenido desplaza
450
+ por debajo (la tabla de datos). */
451
+ --netzi-layer-sticky: 2;
452
+ /* Barra: lo del marco de la app que pasa por encima del contenido, como el botón de plegar el
453
+ menú lateral o la barra de carga. Una barra fija de la app va aquí, por encima de lo
454
+ pegajoso. */
455
+ --netzi-layer-bar: 20;
456
+ /* Flotante del marco: submenús del menú lateral plegado y menús contextuales anclados al
457
+ contenido. Por debajo del velo: un modal los tapa. */
458
+ --netzi-layer-flyout: 50;
459
+ /* Velo: lo que apaga la página detrás de un panel lateral que se abre por encima (el menú
460
+ lateral en el móvil, que va un escalón por encima de su velo). */
461
+ --netzi-layer-scrim: 80;
462
+ /* Modal: diálogos y paneles laterales, con su velo dentro. */
463
+ --netzi-layer-modal: 100;
464
+ /* Desplegable: paneles anclados a un control (select, fecha, hora, autocompletado, popover,
465
+ cron) y la paleta de comandos. Por encima del modal: la paleta de comandos se abre sobre
466
+ cualquier diálogo. Dentro de un modal o de un panel lateral, un desplegable ya va en la
467
+ capa de su contenedor. */
468
+ --netzi-layer-dropdown: 120;
469
+ /* Aviso: el toast, que tiene que verse aunque haya un modal o un desplegable abiertos. */
470
+ --netzi-layer-toast: 200;
471
+ /* Tooltip: la etiqueta de lo que tiene el puntero o el foco, encima de cualquier capa
472
+ interactiva. */
473
+ --netzi-layer-tooltip: 300;
474
+ /* Bloqueante: la pantalla que impide usar la app hasta que se resuelve algo (sin conexión).
475
+ Tapa todo lo anterior. */
476
+ --netzi-layer-blocking: 1000;
477
+ /* Tope: lo que nunca puede quedar tapado, como el enlace «Ir al contenido» cuando recibe el
478
+ foco. */
479
+ --netzi-layer-top: 10000;
480
+ /* TAMAÑOS DE VENTANA con nombre (#157, ADR 0016, criterio C.8): los cortes de ancho de la
481
+ ventana en los que cambia el diseño, siempre los mismos en el kit y en las apps. Cada
482
+ valor, salvo reflow, es el ancho en el que EMPIEZA ese tamaño: compacto (menos de 600, un
483
+ panel), medio (600 a 839, uno o dos), expandido (840 a 1199, dos), grande (1200 a 1599,
484
+ dos, con el menú lateral completo) y extragrande (1600 o más, hasta tres). Una var() no
485
+ vale dentro de @media: en las hojas se escribe el número del token en forma de rango,
486
+ (width < 600px) o (width >= 600px), y un guardián del kit rechaza cualquier otro corte de
487
+ ventana. Lo que depende de su propia caja y no de la ventana usa una consulta de contenedor
488
+ con nombre. */
489
+ /* Ancho de reflujo: por debajo (teléfonos de 320 y 360 px y el zoom al 400 % de WCAG 1.4.10)
490
+ lo que va en fila dentro de un panel flotante se apila. Es un corte dentro de compacto, no
491
+ un tamaño de ventana: no cambia el número de paneles. */
492
+ --netzi-window-reflow: 375px;
493
+ /* Empieza el tamaño medio: uno o dos paneles, y el menú lateral adaptable (netzi-layout con
494
+ adaptive) pasa de cajón a riel. */
495
+ --netzi-window-medium: 600px;
496
+ /* Empieza el tamaño expandido: dos paneles, lista y detalle a la vez. */
497
+ --netzi-window-expanded: 840px;
498
+ /* Empieza el tamaño grande: dos paneles, y el menú lateral adaptable vuelve a ir completo,
499
+ con sus etiquetas. */
500
+ --netzi-window-large: 1200px;
501
+ /* Empieza el tamaño extragrande: hasta tres paneles (lista, detalle y uno de apoyo). */
502
+ --netzi-window-extra-large: 1600px;
503
+ /* Capa 3 — DE COMPONENTE. Tokens con un uso concreto: capas flotantes, velo modal, indicador
504
+ de foco, pulgar de los interruptores y medidas de los controles. */
505
+ /* El pulgar de un interruptor o de un deslizador. OPACO y literal a propósito: iba con
506
+ surface, y dentro de un panel de cristal esa superficie es un tinte translúcido, así que el
507
+ pulgar salía como un agujero oscuro con un aro. Blanco en los dos temas, como el de
508
+ cualquier sistema. */
509
+ --netzi-thumb: #ffffff;
510
+ /* Capas FLOTANTES: las que se pintan ENCIMA del contenido (topbar, sidebar, paneles anclados,
511
+ modal, drawer, menús, tooltips y toasts). Por defecto son exactamente la superficie opaca
512
+ de siempre; el eje glass las convierte en cristal sin que ningún componente tenga que
513
+ enterarse. Los valores van literales, no como referencia a surface, porque el cristal los
514
+ redefine y una referencia cruzada crearía un ciclo de custom properties. */
515
+ --netzi-float-bg: #ffffff;
516
+ --netzi-float-border: #eaedf0;
517
+ --netzi-float-border-2: #dce0e5;
518
+ /* Superficies ANIDADAS dentro de una capa flotante (una tarjeta en el drawer, la burbuja de
519
+ un comentario, el hover de un botón). Sin cristal son las de siempre; con cristal, tintes
520
+ translúcidos. Los paneles las re-escopan como surface para que todo lo que llevan dentro
521
+ las herede. */
522
+ --netzi-float-surface: #ffffff;
523
+ --netzi-float-surface-2: #f4f6f8;
524
+ --netzi-float-surface-3: #eef1f4;
525
+ --netzi-float-filter: none;
526
+ /* La MISMA cadena que float-filter, en identidad: el punto del que parte la entrada de un
527
+ panel de cristal y al que llega su salida. El desenfoque se anima de 0 a su valor, porque
528
+ un fundido por opacity apaga el cristal justo mientras entra. Mismo orden de funciones que
529
+ el token real: si no coinciden, no se interpola. */
530
+ --netzi-float-filter-identity: saturate(1) contrast(1) brightness(1) blur(0);
531
+ --netzi-float-glow: 0 0 rgba(0, 0, 0, 0);
532
+ /* VELO de las capas modales: lo que se pinta DETRÁS de un modal, un drawer o la paleta de
533
+ comandos para apagar el contenido. Es un token porque cada componente lo llevaba escrito a
534
+ mano y no coincidían. */
535
+ --netzi-scrim: rgba(8, 12, 20, 0.28);
536
+ --netzi-scrim-filter: blur(1px);
537
+ /* Controles. py y px son el relleno interior; h, px y fs por tamaño (sm, md, lg) dan una
538
+ altura FIJA para que todos los campos y el botón midan lo mismo y alineen en fila. Las
539
+ alturas y los tamaños de letra escalan con font-scale (ajuste de accesibilidad) para no
540
+ recortar el texto. La densidad compacta los reduce. */
541
+ --netzi-control-py: 12px;
542
+ --netzi-control-px: 14px;
543
+ --netzi-control-px-sm: 12px;
544
+ --netzi-control-px-md: 14px;
545
+ --netzi-control-px-lg: 16px;
546
+ --netzi-control-h-sm: calc(36px * var(--netzi-font-scale, 1));
547
+ --netzi-control-h-md: calc(44px * var(--netzi-font-scale, 1));
548
+ --netzi-control-h-lg: calc(52px * var(--netzi-font-scale, 1));
549
+ --netzi-control-fs-sm: calc(13.5px * var(--netzi-font-scale, 1));
550
+ --netzi-control-fs-md: calc(15px * var(--netzi-font-scale, 1));
551
+ --netzi-control-fs-lg: calc(16px * var(--netzi-font-scale, 1));
552
+ /* Objetivo táctil mínimo (#100): lado mínimo de lo que se toca con el dedo (WCAG 2.5.5). Con
553
+ puntero táctil los controles no bajan de aquí, ni en tamaño sm ni con densidad compacta. */
554
+ --netzi-touch-target: 44px;
555
+ /* Separación táctil mínima (#210): hueco entre las zonas de toque de dos objetivos vecinos
556
+ con puntero táctil (política 17, criterio A.5), medido entre zonas y no entre los dibujos.
557
+ Cada componente la usa en su media pointer coarse; con ratón no cambia nada. Las piezas de
558
+ un control segmentado se tocan y quedan fuera. */
559
+ --netzi-touch-gap: 8px;
560
+ /* Paleta CATEGÓRICA de las gráficas (#175): ocho colores para ocho series, sin repetirse, en
561
+ el orden en que se asignan. Fija y no themeable por preset a propósito: si la serie 1 fuera
562
+ el primario, con el preset verde o rojo chocaría con la serie del mismo tono, que era justo
563
+ el fallo de la paleta anterior (azul repetido en las series 1 y 6). Elegida para que los
564
+ pares se distingan también con protanopia, deuteranopia y tritanopia (simulación de Machado
565
+ 2009; distancia mínima en OKLab de 10 sin daltonismo y 7 con él en claro, 8,9 y 6,2 en
566
+ oscuro), alternando la luminosidad donde el tono se confunde. Cada color llega a 3:1 (WCAG
567
+ 1.4.11) sobre cada superficie, en claro y en oscuro: el build lo comprueba. El color no
568
+ basta solo: netzi-chart añade forma de marcador, trazo y trama por serie (WCAG 1.4.1). */
569
+ /* Serie 1: azul. */
570
+ --netzi-chart-1: #0072b2;
571
+ /* Serie 2: naranja quemado. */
572
+ --netzi-chart-2: #bd582d;
573
+ /* Serie 3: verde azulado. */
574
+ --netzi-chart-3: #2d968c;
575
+ /* Serie 4: vino. */
576
+ --netzi-chart-4: #7b2c51;
577
+ /* Serie 5: oliva. */
578
+ --netzi-chart-5: #4d5200;
579
+ /* Serie 6: índigo. */
580
+ --netzi-chart-6: #35468d;
581
+ /* Serie 7: rosa rojizo. */
582
+ --netzi-chart-7: #a73b50;
583
+ /* Serie 8: pizarra. */
584
+ --netzi-chart-8: #555f7b;
585
+ /* Fondo ambiental: manchas de color suaves DEBAJO del contenido, que el layout pinta bajo bg.
586
+ Sin el eje ambient, none. */
587
+ --netzi-ambient: none;
588
+ }
589
+
590
+ :root,
591
+ [data-theme] {
592
+ --netzi-info-text: var(--netzi-blue-text);
593
+ --netzi-info-graphic: var(--netzi-blue-graphic);
594
+ /* El velo del 14 % del gráfico de su estado: el fondo redondo de un icono de estado
595
+ (netzi-result, netzi-connection-guard). El gráfico se mide sobre él, compuesto sobre cada
596
+ superficie, en su contrato. */
597
+ --netzi-info-veil: color-mix(in srgb, var(--netzi-info-graphic) 14%, transparent);
598
+ --netzi-success-text: var(--netzi-green-text);
599
+ --netzi-success-graphic: var(--netzi-green-graphic);
600
+ --netzi-success-veil: color-mix(in srgb, var(--netzi-success-graphic) 14%, transparent);
601
+ --netzi-warning-text: var(--netzi-yellow-text);
602
+ --netzi-warning-graphic: var(--netzi-yellow-graphic);
603
+ --netzi-warning-veil: color-mix(in srgb, var(--netzi-warning-graphic) 14%, transparent);
604
+ --netzi-danger-text: var(--netzi-red-text);
605
+ --netzi-danger-graphic: var(--netzi-red-graphic);
606
+ --netzi-danger-veil: color-mix(in srgb, var(--netzi-danger-graphic) 14%, transparent);
607
+ /* Sinónimo de surface, que es el nombre canónico (#216): el primer escalón de la escala no
608
+ lleva número. */
609
+ /* deprecated: Usa surface (--netzi-surface). Deprecado en @netzi/tokens 0.1.0-beta.10; se
610
+ retira como pronto en @netzi/tokens 0.1.0-beta.11. */
611
+ --netzi-surface-1: var(--netzi-surface);
612
+ /* Sinónimo de text, que es el nombre canónico (#216). */
613
+ /* deprecated: Usa text (--netzi-text). Deprecado en @netzi/tokens 0.1.0-beta.10; se retira
614
+ como pronto en @netzi/tokens 0.1.0-beta.11. */
615
+ --netzi-text-1: var(--netzi-text);
616
+ }
617
+
618
+ :root,
619
+ [data-density] {
620
+ /* Controles y piezas pequeñas dentro de una superficie: botones, campos, ítems de menú,
621
+ celdas, iconos en caja. */
622
+ --netzi-radius-control: var(--netzi-radius-sm);
623
+ /* Superficies: tarjetas, diálogos, popovers, paneles y la paleta de comandos. */
624
+ --netzi-radius-surface: var(--netzi-radius-lg);
625
+ /* Superficies pequeñas o pegadas a un control: el panel de un select, una fecha o una hora,
626
+ un aviso, una tarjeta compacta. */
627
+ --netzi-radius-surface-sm: var(--netzi-radius);
628
+ /* Sinónimo del radio medio (#216), que hoy es el de una superficie pequeña (#228). */
629
+ /* deprecated: Usa radius.surface.sm (--netzi-radius-surface-sm). Deprecado en @netzi/tokens
630
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11. */
631
+ --netzi-radius-md: var(--netzi-radius-surface-sm);
632
+ /* Entre grupos apilados dentro de un panel o un formulario: campos, filas, columnas. */
633
+ --netzi-space-stack: var(--netzi-space-4);
634
+ /* Relleno interior de un contenedor. */
635
+ /* El de una tarjeta o un panel. */
636
+ --netzi-space-inset: var(--netzi-space-5);
637
+ /* El de un contenedor compacto: un panel flotante, un aviso, una sección dentro de un panel. */
638
+ --netzi-space-inset-sm: var(--netzi-space-4);
639
+ /* El de un diálogo, un panel lateral o una tarjeta grande. */
640
+ --netzi-space-inset-lg: var(--netzi-space-6);
641
+ /* Entre secciones de una página. */
642
+ --netzi-space-section: var(--netzi-space-7);
643
+ /* Entre las regiones grandes de una página y como su margen en pantallas anchas. */
644
+ --netzi-space-page: var(--netzi-space-8);
645
+ }
646
+
647
+ :root,
648
+ [data-preset] {
649
+ /* Tintes del primario, derivados del preset. El suave (10 %) es para superficies grandes, una
650
+ fila resaltada o un panel, y aguanta primary-text encima justo. El marcado (22 %) es para
651
+ piezas pequeñas, un chip o una píldora, donde el suave se pierde contra el fondo (1.13:1
652
+ sobre surface-3); su tinta es text, NO primary-text, que sobre él se queda en 3.9:1. Por
653
+ eso el suave no se puede subir sin más: es el techo del otro. */
654
+ --netzi-primary-tint: color-mix(in srgb, var(--netzi-primary) 10%, transparent);
655
+ --netzi-primary-tint-strong: color-mix(in srgb, var(--netzi-primary) 22%, transparent);
656
+ }
657
+
658
+ :root,
659
+ [data-theme],
660
+ [data-contrast] {
661
+ /* La capa de hover: el puntero encima. Los controles que ya pintaban su hover con una
662
+ superficie (surface-2) o con el hover del primario lo conservan; la capa es para lo nuevo y
663
+ para quien pinte sus propios controles. */
664
+ --netzi-state-hover: color-mix(in srgb, var(--netzi-text) 8%, transparent);
665
+ /* La capa de foco: para lo que se enfoca DENTRO de un compuesto (la opción activa de una
666
+ lista que se recorre con flechas). El foco de un control siempre lleva además su anillo
667
+ (focus-ring). */
668
+ --netzi-state-focus: color-mix(in srgb, var(--netzi-text) 12%, transparent);
669
+ /* La capa de presionado: mientras el dedo o el botón del ratón están abajo. Se suma al hover
670
+ (en táctil, a lo que haya), y se ve en menos de 100 ms porque no se anima. */
671
+ --netzi-state-pressed: color-mix(in srgb, var(--netzi-text) 12%, transparent);
672
+ /* La capa de arrastrado: la pieza que se lleva con el puntero (la pestaña que se reordena). */
673
+ --netzi-state-dragged: color-mix(in srgb, var(--netzi-text) 16%, transparent);
674
+ /* Sombras: los nombres de antes de la escala de elevación, en desuso (#220). Apuntan a su
675
+ nivel y se redeclaran en cada sección con tema o contraste propios, como el anillo de foco,
676
+ para que sigan al tema donde se usen. */
677
+ /* deprecated: Usa elevation.floating (--netzi-elevation-floating). Deprecado en @netzi/tokens
678
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11. */
679
+ --netzi-shadow: var(--netzi-elevation-floating);
680
+ /* deprecated: Usa elevation.raised (--netzi-elevation-raised). Deprecado en @netzi/tokens
681
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11. */
682
+ --netzi-shadow-sm: var(--netzi-elevation-raised);
683
+ /* deprecated: Usa elevation.modal (--netzi-elevation-modal). Deprecado en @netzi/tokens
684
+ 0.1.0-beta.10; se retira como pronto en @netzi/tokens 0.1.0-beta.11. */
685
+ --netzi-shadow-lg: var(--netzi-elevation-modal);
686
+ }
687
+
688
+ :root,
689
+ [data-theme],
690
+ [data-preset] {
691
+ /* El fondo de lo SELECCIONADO o activo (la opción elegida, el ítem actual del menú): el tinte
692
+ suave del primario, el mismo de siempre. El color no basta solo: lo elegido lleva además su
693
+ marca (aria-selected, aria-current o aria-pressed, y un indicador que no es solo color). */
694
+ --netzi-state-selected: var(--netzi-primary-tint);
695
+ /* Tinte de acento: alias histórico del tinte del primario. */
696
+ --netzi-tint: var(--netzi-primary-tint);
697
+ /* El indicador de FOCO: contorno o borde del control enfocado. Tiene que llegar a 3:1 sobre
698
+ el fondo (WCAG 1.4.11) y el primario no llega en claro con azul, verde, naranja ni cian
699
+ (#76): se apoya en el primario para texto, que cada preset y cada tema calibran. Se declara
700
+ también en cada elemento con tema o preset propios (redeclareOn): una variable que usa otra
701
+ se resuelve donde se declara, y una sección oscura dentro de una página clara heredaría el
702
+ anillo claro. */
703
+ --netzi-focus-ring: var(--netzi-primary-text);
704
+ }
705
+
706
+ :root,
707
+ [data-theme],
708
+ [data-contrast],
709
+ [data-glass] {
710
+ /* El PULGAR de las barras de desplazamiento finas del kit (la tabla de datos, #117), sobre un
711
+ carril transparente: lo que se ve es el pulgar contra la superficie, y es lo que se
712
+ arrastra, así que pide 3:1 (WCAG 1.4.11). Las barras superpuestas (móvil, macOS) se pintan
713
+ ENCIMA de las filas, así que también se mide sobre el tinte del primario (fila seleccionada
714
+ o con el puntero encima): ahí text-3 se quedaba en 2.4–2.98:1, y por eso es text-2. El modo
715
+ de alto contraste, que se pone en la raíz, lo sube con él. Se declara también en cada
716
+ elemento con tema propio (redeclareOn), como el anillo de foco: una sección oscura dentro
717
+ de una página clara heredaría el pulgar claro. */
718
+ --netzi-scrollbar-thumb: var(--netzi-text-2);
719
+ }
720
+
721
+ /* Eje MODO (data-theme). Sin el atributo, claro: los valores de las capas. dark los redefine. */
722
+
723
+ @media not print {
724
+ [data-theme='light'] {
725
+ /* El valor por defecto puesto en un elemento: los de las capas otra vez, para una sección
726
+ dentro de otra con data-theme. */
727
+ --netzi-blue-text: #076aa3;
728
+ --netzi-blue-graphic: #0e84cd;
729
+ --netzi-green-text: #05773a;
730
+ --netzi-green-graphic: #069047;
731
+ --netzi-purple-text: #743fd4;
732
+ --netzi-red-text: #a34444;
733
+ --netzi-red-graphic: #df464b;
734
+ --netzi-yellow-text: #7d6421;
735
+ --netzi-yellow-graphic: #9d7a0c;
736
+ --netzi-surface-2: #f4f6f8;
737
+ --netzi-surface-3: #eef1f4;
738
+ --netzi-surface: #ffffff;
739
+ --netzi-text-2: #5c6b78;
740
+ --netzi-text-3: #7a8996;
741
+ --netzi-text: #1c252e;
742
+ --netzi-primary-dark: var(--netzi-blue-dark);
743
+ --netzi-primary-hover: #0a8fdd;
744
+ --netzi-primary-pressed: #279ce1;
745
+ --netzi-primary-text: #076ba6;
746
+ --netzi-primary-graphic: #0987d2;
747
+ --netzi-primary-tint: color-mix(in srgb, var(--netzi-primary) 10%, transparent);
748
+ --netzi-primary-tint-strong: color-mix(in srgb, var(--netzi-primary) 22%, transparent);
749
+ --netzi-on-accent: #04121f;
750
+ --netzi-bg: #f7f9fb;
751
+ --netzi-border-2: #dce0e5;
752
+ --netzi-border: #eaedf0;
753
+ --netzi-elevation-raised: 0 1px 2px rgba(145, 158, 171, 0.16);
754
+ --netzi-elevation-floating:
755
+ 0 0 2px rgba(145, 158, 171, 0.2), 0 12px 24px -4px rgba(145, 158, 171, 0.12);
756
+ --netzi-elevation-modal:
757
+ 0 0 2px rgba(145, 158, 171, 0.2), 0 16px 40px -8px rgba(145, 158, 171, 0.24);
758
+ --netzi-float-bg: #ffffff;
759
+ --netzi-float-border-2: #dce0e5;
760
+ --netzi-float-border: #eaedf0;
761
+ --netzi-float-surface-2: #f4f6f8;
762
+ --netzi-float-surface-3: #eef1f4;
763
+ --netzi-float-surface: #ffffff;
764
+ --netzi-float-filter: none;
765
+ --netzi-float-glow: 0 0 rgba(0, 0, 0, 0);
766
+ --netzi-scrim: rgba(8, 12, 20, 0.28);
767
+ --netzi-chart-1: #0072b2;
768
+ --netzi-chart-2: #bd582d;
769
+ --netzi-chart-3: #2d968c;
770
+ --netzi-chart-4: #7b2c51;
771
+ --netzi-chart-5: #4d5200;
772
+ --netzi-chart-6: #35468d;
773
+ --netzi-chart-7: #a73b50;
774
+ --netzi-chart-8: #555f7b;
775
+ --netzi-ambient: none;
776
+ }
777
+
778
+ [data-theme='dark'] {
779
+ /* Tema OSCURO. Sobre fondo oscuro casi todos los colores de marca sirven crudos como texto;
780
+ solo el rojo y el morado piden un punto de luz para llegar al mínimo. Por lo mismo, el
781
+ gráfico de cada estado (#189) es su crudo. El tinte del primario sube un poco de alfa. */
782
+ --netzi-bg: #0d1117;
783
+ --netzi-surface: #161b22;
784
+ --netzi-surface-2: #0d1117;
785
+ --netzi-surface-3: #21262d;
786
+ --netzi-border: #21262d;
787
+ --netzi-border-2: #30363d;
788
+ --netzi-float-bg: #161b22;
789
+ --netzi-float-border: #21262d;
790
+ --netzi-float-border-2: #30363d;
791
+ --netzi-float-surface: #161b22;
792
+ --netzi-float-surface-2: #0d1117;
793
+ --netzi-float-surface-3: #21262d;
794
+ --netzi-blue-text: #0ba5ff;
795
+ --netzi-blue-graphic: var(--netzi-blue);
796
+ --netzi-green-text: #0ae972;
797
+ --netzi-green-graphic: var(--netzi-green);
798
+ --netzi-yellow-text: #f0c040;
799
+ --netzi-yellow-graphic: var(--netzi-yellow);
800
+ --netzi-red-text: #ff7272;
801
+ --netzi-red-graphic: var(--netzi-red);
802
+ --netzi-purple-text: #ac7eff;
803
+ --netzi-primary-text: #0da6ff;
804
+ --netzi-primary-graphic: #0ba5ff;
805
+ --netzi-primary-tint: color-mix(in srgb, var(--netzi-primary) 15%, transparent);
806
+ --netzi-primary-tint-strong: color-mix(in srgb, var(--netzi-primary) 28%, transparent);
807
+ --netzi-text: #ffffff;
808
+ --netzi-text-2: #8b949e;
809
+ --netzi-text-3: #6e7681;
810
+ /* La paleta de las gráficas en oscuro: mismos tonos, aclarados hasta 3:1 sobre la
811
+ superficie más clara del tema (surface-3). */
812
+ --netzi-chart-1: #3d9df0;
813
+ --netzi-chart-2: #e37b51;
814
+ --netzi-chart-3: #52ddd8;
815
+ --netzi-chart-4: #c062a0;
816
+ --netzi-chart-5: #cfa726;
817
+ --netzi-chart-6: #5c7ec7;
818
+ --netzi-chart-7: #d55444;
819
+ --netzi-chart-8: #9aa4b2;
820
+ --netzi-on-accent: #04121f;
821
+ --netzi-elevation-raised: 0 1px 2px rgba(0, 0, 0, 0.4);
822
+ --netzi-elevation-floating: 0 1px 2px rgba(0, 0, 0, 0.3), 0 12px 28px -6px rgba(0, 0, 0, 0.45);
823
+ --netzi-elevation-modal: 0 1px 2px rgba(0, 0, 0, 0.4), 0 20px 50px -10px rgba(0, 0, 0, 0.6);
824
+ }
825
+
826
+ [data-theme='dark'] :where([data-preset]:not([data-theme])) {
827
+ --netzi-primary-tint: color-mix(in srgb, var(--netzi-primary) 15%, transparent);
828
+ --netzi-primary-tint-strong: color-mix(in srgb, var(--netzi-primary) 28%, transparent);
829
+ }
830
+ }
831
+
832
+ /* Eje PRESET (data-preset): el color primario. Sin el atributo, azul (el de las capas). Cada
833
+ contexto con mode además del preset es la combinación de los dos: gana a cada eje por
834
+ separado. */
835
+
836
+ [data-preset='green'] {
837
+ --netzi-primary: #0ae972;
838
+ --netzi-primary-dark: #079b4e;
839
+ --netzi-primary-hover: #07a352;
840
+ --netzi-primary-pressed: #25ae67;
841
+ --netzi-primary-text: #05793b;
842
+ --netzi-primary-graphic: #06984a;
843
+ --netzi-on-primary: #04121f;
844
+ }
845
+
846
+ @media not print {
847
+ [data-preset='green'] :where([data-theme='light']:not([data-preset])) {
848
+ --netzi-primary-dark: #079b4e;
849
+ --netzi-primary-hover: #07a352;
850
+ --netzi-primary-pressed: #25ae67;
851
+ --netzi-primary-text: #05793b;
852
+ --netzi-primary-graphic: #06984a;
853
+ }
854
+ }
855
+
856
+ [data-preset='purple'] {
857
+ /* El morado es el ÚNICO preset donde la tinta oscura no cumple (4.13): se queda en blanco,
858
+ que sí (4.57). La regla es la que cumpla sobre su color. */
859
+ --netzi-primary: #8c4cff;
860
+ --netzi-primary-dark: #6a2fd6;
861
+ --netzi-primary-hover: #6a2fd6;
862
+ --netzi-primary-pressed: #5d29bc;
863
+ --netzi-primary-text: #7841db;
864
+ --netzi-primary-graphic: #8c4cff;
865
+ --netzi-on-primary: #ffffff;
866
+ }
867
+
868
+ @media not print {
869
+ [data-preset='purple'] :where([data-theme='light']:not([data-preset])) {
870
+ --netzi-primary-dark: #6a2fd6;
871
+ --netzi-primary-hover: #6a2fd6;
872
+ --netzi-primary-pressed: #5d29bc;
873
+ --netzi-primary-text: #7841db;
874
+ --netzi-primary-graphic: #8c4cff;
875
+ }
876
+ }
877
+
878
+ [data-preset='orange'] {
879
+ --netzi-primary: #f0a020;
880
+ --netzi-primary-dark: #bf780a;
881
+ --netzi-primary-hover: #c97e0a;
882
+ --netzi-primary-pressed: #cf8d27;
883
+ --netzi-primary-text: #8e5e13;
884
+ --netzi-primary-graphic: #b47718;
885
+ --netzi-on-primary: #04121f;
886
+ }
887
+
888
+ @media not print {
889
+ [data-preset='orange'] :where([data-theme='light']:not([data-preset])) {
890
+ --netzi-primary-dark: #bf780a;
891
+ --netzi-primary-hover: #c97e0a;
892
+ --netzi-primary-pressed: #cf8d27;
893
+ --netzi-primary-text: #8e5e13;
894
+ --netzi-primary-graphic: #b47718;
895
+ }
896
+ }
897
+
898
+ [data-preset='red'] {
899
+ --netzi-primary: #ff5630;
900
+ --netzi-primary-dark: #d63916;
901
+ --netzi-primary-hover: #eb4a25;
902
+ --netzi-primary-pressed: #ed603f;
903
+ --netzi-primary-text: #b53d22;
904
+ --netzi-primary-graphic: #e34d2b;
905
+ --netzi-on-primary: #04121f;
906
+ }
907
+
908
+ @media not print {
909
+ [data-preset='red'] :where([data-theme='light']:not([data-preset])) {
910
+ --netzi-primary-dark: #d63916;
911
+ --netzi-primary-hover: #eb4a25;
912
+ --netzi-primary-pressed: #ed603f;
913
+ --netzi-primary-text: #b53d22;
914
+ --netzi-primary-graphic: #e34d2b;
915
+ }
916
+ }
917
+
918
+ [data-preset='cyan'] {
919
+ --netzi-primary: #00b8d9;
920
+ --netzi-primary-dark: #0892ab;
921
+ --netzi-primary-hover: #0892ab;
922
+ --netzi-primary-pressed: #269fb5;
923
+ --netzi-primary-text: #007287;
924
+ --netzi-primary-graphic: #008ea8;
925
+ --netzi-on-primary: #04121f;
926
+ }
927
+
928
+ @media not print {
929
+ [data-preset='cyan'] :where([data-theme='light']:not([data-preset])) {
930
+ --netzi-primary-dark: #0892ab;
931
+ --netzi-primary-hover: #0892ab;
932
+ --netzi-primary-pressed: #269fb5;
933
+ --netzi-primary-text: #007287;
934
+ --netzi-primary-graphic: #008ea8;
935
+ }
936
+
937
+ [data-theme='dark'][data-preset='green'] {
938
+ --netzi-primary-text: #0ae972;
939
+ --netzi-primary-graphic: #0ae972;
940
+ }
941
+
942
+ [data-theme='dark'][data-preset='purple'] {
943
+ /* El morado oscuro de claro (#6a2fd6) se hunde en el fondo oscuro (2.7:1): un interruptor
944
+ encendido apenas se distinguía de la tarjeta. */
945
+ --netzi-primary-text: #ad80ff;
946
+ --netzi-primary-graphic: #9255ff;
947
+ --netzi-primary-dark: #824ff3;
948
+ --netzi-primary-hover: #7d48f2;
949
+ --netzi-primary-pressed: #6e3fd5;
950
+ }
951
+
952
+ [data-theme='dark'][data-preset='orange'] {
953
+ --netzi-primary-text: #f0a020;
954
+ --netzi-primary-graphic: #f0a020;
955
+ }
956
+
957
+ [data-theme='dark'][data-preset='red'] {
958
+ --netzi-primary-text: #ff6a49;
959
+ --netzi-primary-graphic: #ff5630;
960
+ }
961
+
962
+ [data-theme='dark'][data-preset='cyan'] {
963
+ --netzi-primary-text: #00b8d9;
964
+ --netzi-primary-graphic: #00b8d9;
965
+ }
966
+ }
967
+
968
+ /* Eje CONTRASTE (data-contrast): bordes y texto más marcados. Cada nivel de texto toma el valor
969
+ del nivel de encima, así que text-3 pasa de 3:1 a más de 4.5:1 y el modo cumple incluso donde
970
+ alguien lo haya usado para texto, que es justo lo que se espera de un modo de alto contraste.
971
+ El borde fuerte (border-2) llega a 3:1 sobre cada superficie, como el borde de un control
972
+ (WCAG 1.4.11). Sin el atributo en la página, sigue al sistema (#150): con prefers-contrast
973
+ more aplica el alto, y data-contrast='normal' lo deja fuera a mano. */
974
+
975
+ [data-contrast='high'] {
976
+ --netzi-border: #c9cfd6;
977
+ --netzi-border-2: #828b94;
978
+ --netzi-text-2: #2a333c;
979
+ --netzi-text-3: #5c6b78;
980
+ --netzi-float-border: #c9cfd6;
981
+ --netzi-float-border-2: #828b94;
982
+ --netzi-elevation-raised: 0 1px 2px rgba(99, 115, 129, 0.3);
983
+ }
984
+
985
+ @media not print {
986
+ [data-contrast='high'] :where([data-theme='light']:not([data-contrast])) {
987
+ --netzi-border-2: #828b94;
988
+ --netzi-border: #c9cfd6;
989
+ --netzi-text-2: #2a333c;
990
+ --netzi-text-3: #5c6b78;
991
+ --netzi-float-border-2: #828b94;
992
+ --netzi-float-border: #c9cfd6;
993
+ --netzi-elevation-raised: 0 1px 2px rgba(99, 115, 129, 0.3);
994
+ }
995
+ }
996
+
997
+ @media (prefers-contrast: more) {
998
+ :root:where(:not([data-contrast])) {
999
+ /* Lo mismo cuando lo pide el sistema y nadie fija data-contrast. */
1000
+ --netzi-border: #c9cfd6;
1001
+ --netzi-border-2: #828b94;
1002
+ --netzi-text-2: #2a333c;
1003
+ --netzi-text-3: #5c6b78;
1004
+ --netzi-float-border: #c9cfd6;
1005
+ --netzi-float-border-2: #828b94;
1006
+ --netzi-elevation-raised: 0 1px 2px rgba(99, 115, 129, 0.3);
1007
+ }
1008
+ }
1009
+
1010
+ @media not print {
1011
+ @media (prefers-contrast: more) {
1012
+ :root:where(:not([data-contrast])) :where([data-theme='light']:not([data-contrast])) {
1013
+ --netzi-border-2: #828b94;
1014
+ --netzi-border: #c9cfd6;
1015
+ --netzi-text-2: #2a333c;
1016
+ --netzi-text-3: #5c6b78;
1017
+ --netzi-float-border-2: #828b94;
1018
+ --netzi-float-border: #c9cfd6;
1019
+ --netzi-elevation-raised: 0 1px 2px rgba(99, 115, 129, 0.3);
1020
+ }
1021
+ }
1022
+ }
1023
+
1024
+ @media not print {
1025
+ [data-theme='dark'][data-contrast='high'] {
1026
+ --netzi-border: #3a434d;
1027
+ --netzi-border-2: #68717b;
1028
+ --netzi-text-2: #aab4bf;
1029
+ --netzi-text-3: #8b949e;
1030
+ --netzi-float-border: #3a434d;
1031
+ --netzi-float-border-2: #68717b;
1032
+ }
1033
+ }
1034
+
1035
+ @media not print {
1036
+ @media (prefers-contrast: more) {
1037
+ [data-theme='dark']:not([data-contrast]):where(:not([data-contrast] *)) {
1038
+ /* Lo mismo cuando lo pide el sistema y nadie fija data-contrast. */
1039
+ --netzi-border: #3a434d;
1040
+ --netzi-border-2: #68717b;
1041
+ --netzi-text-2: #aab4bf;
1042
+ --netzi-text-3: #8b949e;
1043
+ --netzi-float-border: #3a434d;
1044
+ --netzi-float-border-2: #68717b;
1045
+ }
1046
+ }
1047
+ }
1048
+
1049
+ /* Eje CRISTAL (data-glass): las capas flotantes, translúcidas, con el fondo desenfocado y
1050
+ saturado por detrás. Solo afecta a lo que FLOTA sobre el contenido; las superficies de
1051
+ contenido siguen opacas, porque ahí el cristal solo resta. Sobre cristal el texto se lee
1052
+ contra lo que haya debajo, que cambia al desplazar: el peor caso es negro puro debajo en
1053
+ claro y blanco puro en oscuro. El suelo no lo pone solo el alfa: el filtro ACOTA el fondo
1054
+ antes de componerlo (saturate aviva el color, contrast comprime el rango hacia el gris medio,
1055
+ brightness lo empuja al tono de la capa, blur lo difumina), y por eso basta un alfa mucho más
1056
+ bajo, con el que se ve lo de detrás. Lo mide el test de contraste modelando la cadena entera:
1057
+ tocar cualquiera de las funciones o el alfa mueve el veredicto. Quien pide menos
1058
+ transparencia, o un navegador sin backdrop-filter, recibe la superficie opaca de siempre. */
1059
+
1060
+ @media not print {
1061
+ [data-glass='on'] {
1062
+ /* Alfa 0.44, brillo 1.25 y 10 px de desenfoque, para que se vea lo que hay debajo (el
1063
+ usuario eligió el más abierto de cinco niveles). Lo anidado en un panel de cristal
1064
+ también es vidrio: tintes OSCUROS que se alejan de la lámina a la misma distancia que las
1065
+ superficies opacas que imitan; más fuertes las tarjetas salían como placas grises.
1066
+ Oscurecer resta contraste al texto, y por eso text-2 sube aquí dos niveles, en TODA la
1067
+ página y con literales: declararlo por capa como referencia no se reinvalidaba al cambiar
1068
+ de tema en caliente. La LENTE del canto (opt-in, data-glass-lens) es un anillo con su
1069
+ propio desenfoque para que el canto parezca tener espesor; cuesta una segunda capa de
1070
+ backdrop-filter. El filo especular (glow) da luz arriba y sombra abajo: el canto de una
1071
+ pieza de vidrio; no toca ni el alfa ni el filtro. */
1072
+ --netzi-float-bg: rgba(255, 255, 255, 0.44);
1073
+ --netzi-float-border: rgba(255, 255, 255, 0.7);
1074
+ --netzi-float-border-2: rgba(255, 255, 255, 0.85);
1075
+ --netzi-float-surface: rgba(28, 37, 46, 0.02);
1076
+ --netzi-float-surface-2: rgba(28, 37, 46, 0.045);
1077
+ --netzi-float-surface-3: rgba(28, 37, 46, 0.075);
1078
+ --netzi-float-filter: saturate(200%) contrast(0.6) brightness(1.25) blur(10px);
1079
+ --netzi-float-lens: blur(18px) invert(0.18) brightness(1.1) saturate(1.3) hue-rotate(-10deg)
1080
+ contrast(2);
1081
+ --netzi-float-lens-size: 5px;
1082
+ --netzi-float-glow:
1083
+ inset 0 1px 0 rgba(255, 255, 255, 0.75), inset 0 -1px 0 rgba(11, 22, 34, 0.07);
1084
+ --netzi-text-2: #2a333c;
1085
+ --netzi-text-3: #5c6b78;
1086
+ }
1087
+
1088
+ [data-glass='on'] :where([data-theme='light']:not([data-glass])) {
1089
+ --netzi-float-bg: rgba(255, 255, 255, 0.44);
1090
+ --netzi-float-border-2: rgba(255, 255, 255, 0.85);
1091
+ --netzi-float-border: rgba(255, 255, 255, 0.7);
1092
+ --netzi-float-surface-2: rgba(28, 37, 46, 0.045);
1093
+ --netzi-float-surface-3: rgba(28, 37, 46, 0.075);
1094
+ --netzi-float-surface: rgba(28, 37, 46, 0.02);
1095
+ --netzi-float-filter: saturate(200%) contrast(0.6) brightness(1.25) blur(10px);
1096
+ --netzi-float-lens: blur(18px) invert(0.18) brightness(1.1) saturate(1.3) hue-rotate(-10deg)
1097
+ contrast(2);
1098
+ --netzi-float-glow:
1099
+ inset 0 1px 0 rgba(255, 255, 255, 0.75), inset 0 -1px 0 rgba(11, 22, 34, 0.07);
1100
+ --netzi-text-2: #2a333c;
1101
+ --netzi-text-3: #5c6b78;
1102
+ }
1103
+
1104
+ [data-theme='dark'][data-glass='on'] {
1105
+ /* En oscuro los tintes van hacia el negro, que aquí MEJORA el contraste del texto claro.
1106
+ Alfa 0.12 y brillo 0.56: el texto primario queda en 4.5:1 con un plano blanco debajo y el
1107
+ secundario, subido dos niveles, en 3:1. La sombra del canto inferior es más marcada, el
1108
+ velo se hunde y la lente invierte menos, para no convertir el canto en un halo blanco. */
1109
+ --netzi-float-bg: rgba(22, 27, 34, 0.12);
1110
+ --netzi-float-border: rgba(255, 255, 255, 0.14);
1111
+ --netzi-float-border-2: rgba(255, 255, 255, 0.22);
1112
+ --netzi-float-surface: rgba(0, 0, 0, 0.12);
1113
+ --netzi-float-surface-2: rgba(0, 0, 0, 0.22);
1114
+ --netzi-float-surface-3: rgba(0, 0, 0, 0.32);
1115
+ --netzi-float-filter: saturate(200%) contrast(0.6) brightness(0.56) blur(10px);
1116
+ --netzi-float-glow: inset 0 1px 0 rgba(255, 255, 255, 0.12), inset 0 -1px 0 rgba(0, 0, 0, 0.35);
1117
+ --netzi-float-lens: blur(18px) invert(0.12) brightness(1.05) saturate(1.3) hue-rotate(-10deg)
1118
+ contrast(1.7);
1119
+ --netzi-text-2: #d8dee6;
1120
+ --netzi-text-3: #aab4bf;
1121
+ --netzi-scrim: rgba(2, 5, 10, 0.45);
1122
+ }
1123
+ }
1124
+
1125
+ @media not print {
1126
+ @media (prefers-reduced-transparency: reduce) {
1127
+ [data-glass='on'] {
1128
+ /* Quien pide menos transparencia recibe la superficie opaca de siempre. */
1129
+ --netzi-float-bg: #ffffff;
1130
+ --netzi-float-border: #eaedf0;
1131
+ --netzi-float-border-2: #dce0e5;
1132
+ --netzi-float-surface: #ffffff;
1133
+ --netzi-float-surface-2: #f4f6f8;
1134
+ --netzi-float-surface-3: #eef1f4;
1135
+ --netzi-float-filter: none;
1136
+ --netzi-float-glow: 0 0 rgba(0, 0, 0, 0);
1137
+ --netzi-scrim-filter: none;
1138
+ }
1139
+
1140
+ [data-glass='on'] :where([data-theme='light']:not([data-glass])) {
1141
+ --netzi-float-bg: #ffffff;
1142
+ --netzi-float-border-2: #dce0e5;
1143
+ --netzi-float-border: #eaedf0;
1144
+ --netzi-float-surface-2: #f4f6f8;
1145
+ --netzi-float-surface-3: #eef1f4;
1146
+ --netzi-float-surface: #ffffff;
1147
+ --netzi-float-filter: none;
1148
+ --netzi-float-glow: 0 0 rgba(0, 0, 0, 0);
1149
+ }
1150
+
1151
+ [data-theme='dark'][data-glass='on'] {
1152
+ --netzi-float-bg: #161b22;
1153
+ --netzi-float-border: #21262d;
1154
+ --netzi-float-border-2: #30363d;
1155
+ --netzi-float-surface: #161b22;
1156
+ --netzi-float-surface-2: #0d1117;
1157
+ --netzi-float-surface-3: #21262d;
1158
+ }
1159
+ }
1160
+ }
1161
+
1162
+ @media not print {
1163
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
1164
+ [data-glass='on'] {
1165
+ /* Sin backdrop-filter no hay desenfoque, y una capa translúcida sin desenfocar lo que hay
1166
+ debajo es texto sobre ruido: se degrada a opaco entero. */
1167
+ --netzi-float-bg: #ffffff;
1168
+ --netzi-float-border: #eaedf0;
1169
+ --netzi-float-border-2: #dce0e5;
1170
+ --netzi-float-surface: #ffffff;
1171
+ --netzi-float-surface-2: #f4f6f8;
1172
+ --netzi-float-surface-3: #eef1f4;
1173
+ }
1174
+
1175
+ [data-glass='on'] :where([data-theme='light']:not([data-glass])) {
1176
+ --netzi-float-bg: #ffffff;
1177
+ --netzi-float-border-2: #dce0e5;
1178
+ --netzi-float-border: #eaedf0;
1179
+ --netzi-float-surface-2: #f4f6f8;
1180
+ --netzi-float-surface-3: #eef1f4;
1181
+ --netzi-float-surface: #ffffff;
1182
+ }
1183
+
1184
+ [data-theme='dark'][data-glass='on'] {
1185
+ --netzi-float-bg: #161b22;
1186
+ --netzi-float-border: #21262d;
1187
+ --netzi-float-border-2: #30363d;
1188
+ --netzi-float-surface: #161b22;
1189
+ --netzi-float-surface-2: #0d1117;
1190
+ --netzi-float-surface-3: #21262d;
1191
+ }
1192
+ }
1193
+ }
1194
+
1195
+ /* Eje FONDO AMBIENTAL (data-ambient): manchas de color suaves debajo del contenido, con el
1196
+ primario del preset y dos de marca, que le dan al cristal algo que desenfocar. Los
1197
+ porcentajes son bajos a propósito: el texto se sigue leyendo encima (text-3 sobre la mancha
1198
+ más fuerte, 4.4:1 en claro y 4.6:1 en oscuro). En alto contraste se apaga. */
1199
+
1200
+ @media not print {
1201
+ [data-ambient='on'] {
1202
+ --netzi-ambient:
1203
+ radial-gradient(
1204
+ 55% 45% at 8% 0%,
1205
+ color-mix(in srgb, var(--netzi-primary) 16%, transparent),
1206
+ transparent 70%
1207
+ ),
1208
+ radial-gradient(
1209
+ 45% 40% at 100% 100%,
1210
+ color-mix(in srgb, var(--netzi-purple) 12%, transparent),
1211
+ transparent 70%
1212
+ ),
1213
+ radial-gradient(
1214
+ 35% 30% at 70% 10%,
1215
+ color-mix(in srgb, var(--netzi-green) 8%, transparent),
1216
+ transparent 70%
1217
+ );
1218
+ }
1219
+
1220
+ [data-ambient='on'] :where([data-preset]:not([data-ambient])) {
1221
+ --netzi-ambient:
1222
+ radial-gradient(
1223
+ 55% 45% at 8% 0%,
1224
+ color-mix(in srgb, var(--netzi-primary) 16%, transparent),
1225
+ transparent 70%
1226
+ ),
1227
+ radial-gradient(
1228
+ 45% 40% at 100% 100%,
1229
+ color-mix(in srgb, var(--netzi-purple) 12%, transparent),
1230
+ transparent 70%
1231
+ ),
1232
+ radial-gradient(
1233
+ 35% 30% at 70% 10%,
1234
+ color-mix(in srgb, var(--netzi-green) 8%, transparent),
1235
+ transparent 70%
1236
+ );
1237
+ }
1238
+
1239
+ [data-ambient='on'] :where([data-theme='light']:not([data-ambient])) {
1240
+ --netzi-ambient:
1241
+ radial-gradient(
1242
+ 55% 45% at 8% 0%,
1243
+ color-mix(in srgb, var(--netzi-primary) 16%, transparent),
1244
+ transparent 70%
1245
+ ),
1246
+ radial-gradient(
1247
+ 45% 40% at 100% 100%,
1248
+ color-mix(in srgb, var(--netzi-purple) 12%, transparent),
1249
+ transparent 70%
1250
+ ),
1251
+ radial-gradient(
1252
+ 35% 30% at 70% 10%,
1253
+ color-mix(in srgb, var(--netzi-green) 8%, transparent),
1254
+ transparent 70%
1255
+ );
1256
+ }
1257
+
1258
+ [data-theme='dark'][data-ambient='on'] {
1259
+ --netzi-ambient:
1260
+ radial-gradient(
1261
+ 55% 45% at 8% 0%,
1262
+ color-mix(in srgb, var(--netzi-primary) 22%, transparent),
1263
+ transparent 70%
1264
+ ),
1265
+ radial-gradient(
1266
+ 45% 40% at 100% 100%,
1267
+ color-mix(in srgb, var(--netzi-purple) 18%, transparent),
1268
+ transparent 70%
1269
+ ),
1270
+ radial-gradient(
1271
+ 35% 30% at 70% 10%,
1272
+ color-mix(in srgb, var(--netzi-green) 10%, transparent),
1273
+ transparent 70%
1274
+ );
1275
+ }
1276
+
1277
+ [data-theme='dark'][data-ambient='on'] :where([data-preset]:not([data-theme], [data-ambient])) {
1278
+ --netzi-ambient:
1279
+ radial-gradient(
1280
+ 55% 45% at 8% 0%,
1281
+ color-mix(in srgb, var(--netzi-primary) 22%, transparent),
1282
+ transparent 70%
1283
+ ),
1284
+ radial-gradient(
1285
+ 45% 40% at 100% 100%,
1286
+ color-mix(in srgb, var(--netzi-purple) 18%, transparent),
1287
+ transparent 70%
1288
+ ),
1289
+ radial-gradient(
1290
+ 35% 30% at 70% 10%,
1291
+ color-mix(in srgb, var(--netzi-green) 10%, transparent),
1292
+ transparent 70%
1293
+ );
1294
+ }
1295
+
1296
+ [data-contrast='high'][data-ambient='on'] {
1297
+ /* En alto contraste no hay manchas: el fondo vuelve a ser liso. */
1298
+ --netzi-ambient: none;
1299
+ }
1300
+
1301
+ [data-contrast='high'][data-ambient='on']
1302
+ :where([data-preset]:not([data-contrast], [data-ambient])) {
1303
+ --netzi-ambient: none;
1304
+ }
1305
+
1306
+ [data-contrast='high'][data-ambient='on']
1307
+ :where([data-theme='light']:not([data-contrast], [data-ambient])) {
1308
+ --netzi-ambient: none;
1309
+ }
1310
+ }
1311
+
1312
+ @media not print {
1313
+ @media (prefers-contrast: more) {
1314
+ [data-ambient='on']:not([data-contrast]):where(:not([data-contrast] *)) {
1315
+ /* Lo mismo cuando lo pide el sistema y nadie fija data-contrast. */
1316
+ --netzi-ambient: none;
1317
+ }
1318
+
1319
+ [data-ambient='on']:not([data-contrast]):where(:not([data-contrast] *))
1320
+ :where([data-preset]:not([data-contrast], [data-ambient])) {
1321
+ --netzi-ambient: none;
1322
+ }
1323
+
1324
+ [data-ambient='on']:not([data-contrast]):where(:not([data-contrast] *))
1325
+ :where([data-theme='light']:not([data-contrast], [data-ambient])) {
1326
+ --netzi-ambient: none;
1327
+ }
1328
+ }
1329
+ }
1330
+
1331
+ /* Eje DENSIDAD (data-density): controles, radios y espaciado más ajustados (los pasos finos no
1332
+ cambian). La tipografía no se toca: se encoge el aire, no la letra. */
1333
+
1334
+ [data-density='compact'] {
1335
+ --netzi-control-py: 8px;
1336
+ --netzi-control-px: 11px;
1337
+ --netzi-control-px-sm: 10px;
1338
+ --netzi-control-px-md: 11px;
1339
+ --netzi-control-px-lg: 13px;
1340
+ --netzi-control-h-sm: calc(32px * var(--netzi-font-scale, 1));
1341
+ --netzi-control-h-md: calc(40px * var(--netzi-font-scale, 1));
1342
+ --netzi-control-h-lg: calc(46px * var(--netzi-font-scale, 1));
1343
+ --netzi-radius: 6px;
1344
+ --netzi-radius-sm: 5px;
1345
+ --netzi-radius-lg: 8px;
1346
+ --netzi-space-4: 10px;
1347
+ --netzi-space-5: 12px;
1348
+ --netzi-space-6: 20px;
1349
+ --netzi-space-7: 28px;
1350
+ --netzi-space-8: 40px;
1351
+ }
1352
+
1353
+ /* Entorno PUNTERO TÁCTIL (media pointer coarse): ningún control por debajo del objetivo táctil
1354
+ (#100). Más 2 px porque el borde de 1 px del contenedor no le quita al campo que se toca;
1355
+ cada densidad parte de su propia base, que con la letra más grande es la que manda. Va
1356
+ después de la densidad para ganarle con la misma especificidad. */
1357
+
1358
+ @media (pointer: coarse) {
1359
+ :root {
1360
+ --netzi-control-h-sm: max(
1361
+ calc(var(--netzi-touch-target) + 2px),
1362
+ calc(36px * var(--netzi-font-scale, 1))
1363
+ );
1364
+ --netzi-control-h-md: max(
1365
+ calc(var(--netzi-touch-target) + 2px),
1366
+ calc(44px * var(--netzi-font-scale, 1))
1367
+ );
1368
+ }
1369
+
1370
+ [data-density='compact'] {
1371
+ --netzi-control-h-sm: max(
1372
+ calc(var(--netzi-touch-target) + 2px),
1373
+ calc(32px * var(--netzi-font-scale, 1))
1374
+ );
1375
+ --netzi-control-h-md: max(
1376
+ calc(var(--netzi-touch-target) + 2px),
1377
+ calc(40px * var(--netzi-font-scale, 1))
1378
+ );
1379
+ }
1380
+ }
1381
+
1382
+ /* Entorno MOVIMIENTO REDUCIDO (media prefers-reduced-motion reduce, #151, WCAG 2.3.3): las
1383
+ duraciones del desplazamiento se anulan aquí, en un solo sitio, y lo que se desplaza, gira o
1384
+ escala salta a su estado final. Van a 0.01 ms y no a 0 para que transitionend y animationend
1385
+ sigan llegando a quien los espera. Los fundidos (las duraciones sin move) no cambian: un
1386
+ cambio de color u opacidad no es movimiento. */
1387
+
1388
+ @media (prefers-reduced-motion: reduce) {
1389
+ :root {
1390
+ --netzi-duration-move-fast: 0.01ms;
1391
+ --netzi-duration-move-base: 0.01ms;
1392
+ --netzi-duration-move-slow: 0.01ms;
1393
+ }
1394
+ }
1395
+
1396
+ /* Entorno IMPRESIÓN (media print, #176): el papel es claro, opaco y quieto. El tema oscuro, el
1397
+ cristal y el fondo ambiental vuelven a su valor por defecto (resets): cada bloque que los
1398
+ fija va en el CSS dentro de @media not print, así que al imprimir no aplica y sale el claro y
1399
+ opaco de siempre, con el preset, el contraste y la densidad intactos. En papel un fondo
1400
+ oscuro gasta tinta y el navegador lo quita a medias, y un vidrio desenfoca lo que no se va a
1401
+ ver. Las sombras desaparecen, porque en papel no despegan nada y salen como manchas grises;
1402
+ el velo de las capas modales no desenfoca; y las duraciones bajan a 0.01 ms para que nada se
1403
+ imprima a medio camino. */
1404
+
1405
+ @media print {
1406
+ :root,
1407
+ [data-contrast='high'] {
1408
+ --netzi-elevation-floating: 0 0 rgba(0, 0, 0, 0);
1409
+ --netzi-elevation-raised: 0 0 rgba(0, 0, 0, 0);
1410
+ --netzi-elevation-modal: 0 0 rgba(0, 0, 0, 0);
1411
+ --netzi-scrim-filter: none;
1412
+ --netzi-duration-instant: 0.01ms;
1413
+ --netzi-duration-fast: 0.01ms;
1414
+ --netzi-duration-base: 0.01ms;
1415
+ --netzi-duration-slow: 0.01ms;
1416
+ --netzi-duration-flash: 0.01ms;
1417
+ --netzi-duration-loop-spin: 0.01ms;
1418
+ --netzi-duration-loop-orbit: 0.01ms;
1419
+ --netzi-duration-loop-pulse: 0.01ms;
1420
+ --netzi-duration-loop-sweep: 0.01ms;
1421
+ --netzi-duration-loop-shine: 0.01ms;
1422
+ --netzi-duration-move-fast: 0.01ms;
1423
+ --netzi-duration-move-base: 0.01ms;
1424
+ --netzi-duration-move-slow: 0.01ms;
1425
+ }
1426
+ }