@higinio/design-mcp 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,30 +1,27 @@
1
- /* ==========================================================================
2
- CELESTE CLÁSICA — Framework CSS v2.0
1
+ /* ============================================================
2
+ Celeste Clásica — Design Tokens v2.0
3
3
  Sistema de diseño de Higinio Sosa · light-first
4
4
  Fuente de verdad: DESIGN-celeste-clasica.md
5
- Uso: enlazar este archivo antes de cualquier estilo propio y aplicar
6
- la clase .celeste-reset al <body>. Tema: data-theme="light|dark" en <html>.
7
- ========================================================================== */
5
+ Uso: importar ANTES de cualquier estilo propio.
6
+ Los componentes consumen SOLO aliases semánticos, nunca hex.
7
+ ============================================================ */
8
8
 
9
9
  @import url("https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,600;0,9..144,700;1,9..144,600&family=Public+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&family=IBM+Plex+Mono:wght@400;500&display=swap");
10
10
 
11
- /* --------------------------------------------------------------------------
12
- 1. TOKENS (§13)
13
- -------------------------------------------------------------------------- */
14
11
  :root {
15
- /* == Primitivos: primario == */
12
+ /* == Primitivos: primario (Azul Acero) == */
16
13
  --primary-50: #f2f6fa; --primary-100: #dfe9f2; --primary-200: #c3d5e6;
17
14
  --primary-300: #a0c0d4; --primary-400: #87a8c7; --primary-500: #7192ba;
18
15
  --primary-600: #5d7ba3; --primary-700: #4d6588; --primary-800: #40536e;
19
16
  --primary-900: #31343e;
20
17
 
21
- /* == Primitivos: neutrales == */
18
+ /* == Primitivos: neutrales (Gris Azulado) == */
22
19
  --neutral-0: #ffffff; --neutral-50: #f7f8fa; --neutral-100: #eef0f3;
23
20
  --neutral-200: #dcdfe5; --neutral-300: #b8bdc7; --neutral-400: #8a8f9c;
24
21
  --neutral-500: #666b78; --neutral-600: #4d5160; --neutral-700: #3d414e;
25
22
  --neutral-800: #31343e; --neutral-900: #22242b;
26
23
 
27
- /* == Primitivos: semánticos (ramp de 3) == */
24
+ /* == Primitivos: semánticos (ramp de 3: sólido / fondo / texto AA) == */
28
25
  --success-500: #3d9970; --success-100: #e2f3ec; --success-text: #2b6e50;
29
26
  --warning-500: #c9922e; --warning-100: #faf1de; --warning-text: #8a651c;
30
27
  --danger-500: #c04d4d; --danger-100: #f9e7e7; --danger-text: #8f3232;
@@ -47,10 +44,7 @@
47
44
  --accent-active: var(--primary-700);
48
45
  --accent-soft: var(--primary-50);
49
46
  --accent-soft-strong: var(--primary-100);
50
- --link: var(--primary-700);
51
- --overlay: rgba(49, 52, 62, .5);
52
- --tooltip-bg: var(--neutral-900);
53
- --tooltip-text: #ffffff;
47
+ --link: var(--primary-700); /* AA ~6:1 — texto de links y ghost; primary-500 solo para UI */
54
48
 
55
49
  /* == Tipografía == */
56
50
  --font-display: "Fraunces", Georgia, serif;
@@ -66,7 +60,7 @@
66
60
  --weight-regular: 400; --weight-medium: 500; --weight-semibold: 600; --weight-bold: 700;
67
61
  --measure: 65ch;
68
62
 
69
- /* == Espaciado == */
63
+ /* == Espaciado (escala base 4px) == */
70
64
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
71
65
  --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px;
72
66
  --space-12: 48px; --space-16: 64px; --space-20: 80px; --space-24: 96px;
@@ -76,7 +70,7 @@
76
70
  --control-height-sm: 36px; --control-height-md: 44px; --control-height-lg: 52px;
77
71
  --gutter: 24px; --gutter-mobile: 16px;
78
72
 
79
- /* == Radios, bordes y sombras == */
73
+ /* == Radios, bordes y sombras (teñidas de tinta, nunca negro puro) == */
80
74
  --radius-sm: 6px; --radius-md: 10px; --radius-lg: 14px;
81
75
  --radius-xl: 20px; --radius-full: 9999px;
82
76
  --border-width: 1px;
@@ -89,7 +83,6 @@
89
83
  /* == Focus == */
90
84
  --ring: 0 0 0 3px rgba(113,146,186,.25);
91
85
  --ring-color: rgba(113,146,186,.25);
92
- --ring-danger: 0 0 0 3px rgba(192,77,77,.22);
93
86
 
94
87
  /* == Motion == */
95
88
  --duration-instant: 100ms; --duration-fast: 150ms; --duration-base: 200ms;
@@ -98,11 +91,49 @@
98
91
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
99
92
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1); /* moverse de A a B en pantalla */
100
93
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
94
+ --stagger-step: 30ms;
101
95
 
102
96
  color-scheme: light;
103
- }
104
97
 
105
- /* Modo oscuro (§15.6, extendido con aliases derivados) */
98
+ --overlay: rgba(49, 52, 62, .5);
99
+ --tooltip-bg: var(--neutral-900);
100
+ --tooltip-text: #ffffff;
101
+ --ring-danger: 0 0 0 3px rgba(192,77,77,.22);
102
+
103
+ --action-bg: var(--primary-700);
104
+ --action-hover: var(--primary-800);
105
+ --action-active: var(--primary-900);
106
+ --text-on-action: var(--text-on-primary);
107
+ --control-border: var(--neutral-400);
108
+ --placeholder: var(--text-muted);
109
+ --selection-bg: var(--action-bg);
110
+ --selection-text: var(--text-on-action);
111
+ --font-ui-heading: var(--font-body);
112
+ --text-ui-title: 2rem;
113
+ --touch-target: 44px;
114
+ --focus-color: var(--accent);
115
+ --text-display-fluid: clamp(2.75rem, 1.7rem + 3vw, 4.75rem);
116
+ --border-hover: var(--neutral-500);
117
+ --text-on-danger: #ffffff;
118
+
119
+ /* Series categóricas: orden estable; acompañar con etiqueta o forma. */
120
+ --chart-1: #4a8cc1;
121
+ --chart-2: #853f63;
122
+ --chart-3: #129a92;
123
+ --chart-4: #8e4031;
124
+ --chart-5: #5b975e;
125
+ --chart-6: #8a600a;
126
+ --chart-7: #857bc1;
127
+ /* Ritmo de contenido y formularios. */
128
+ --field-gap: 6px;
129
+ --heading-gap: var(--space-2);
130
+ --content-gap: var(--space-4);
131
+ --card-content-gap: var(--space-4);
132
+ --card-group-gap: var(--space-6);
133
+
134
+ }
135
+
136
+ /* == Modo oscuro (variante) — alternar data-theme en <html> == */
106
137
  [data-theme="dark"] {
107
138
  --bg: #16181e;
108
139
  --surface: #1d2028;
@@ -119,31 +150,58 @@
119
150
  --accent-soft: rgba(113,146,186,.12);
120
151
  --accent-soft-strong: rgba(113,146,186,.18);
121
152
  --text-on-primary: #16181e;
122
- --text-on-primary-solid: #a0c0d4;
123
153
  --link: #a0c0d4;
124
- --overlay: rgba(0, 0, 0, .6);
125
- --tooltip-bg: #e6e9ee;
126
- --tooltip-text: #31343e;
127
154
  --success-500: #5cbf93; --success-100: #12291f; --success-text: #7fd4ae;
128
155
  --warning-500: #e0ad4d; --warning-100: #2b2210; --warning-text: #ecc57e;
129
156
  --danger-500: #e07777; --danger-100: #2e1515; --danger-text: #eb9e9e;
130
157
  --info-500: #87a8c7; --info-100: #1a2430; --info-text: #a0c0d4;
131
158
  --ring: 0 0 0 3px rgba(160,192,212,.3);
132
- --ring-danger: 0 0 0 3px rgba(224,119,119,.25);
159
+ --ring-color: rgba(160,192,212,.3);
133
160
  --shadow-sm: 0 1px 2px rgba(0,0,0,.35);
134
161
  --shadow-md: 0 4px 12px rgba(0,0,0,.45);
135
162
  --shadow-lg: 0 12px 32px rgba(0,0,0,.55);
136
163
  color-scheme: dark;
164
+
165
+ --text-on-primary-solid: #a0c0d4;
166
+ --overlay: rgba(0, 0, 0, .6);
167
+ --tooltip-bg: #e6e9ee;
168
+ --tooltip-text: #31343e;
169
+ --ring-danger: 0 0 0 3px rgba(224,119,119,.25);
170
+
171
+ --selection-bg: var(--action-bg);
172
+ --selection-text: var(--text-on-action);
173
+ --action-bg: var(--accent);
174
+ --action-hover: var(--accent-hover);
175
+ --action-active: var(--accent-active);
176
+ --control-border: var(--text-muted);
177
+ --border-hover: var(--text-secondary);
178
+ --text-on-danger: #16181e;
179
+ --focus-color: var(--accent);
180
+
181
+ /* Series categóricas: orden estable; acompañar con etiqueta o forma. */
182
+ --chart-1: #5798ce;
183
+ --chart-2: #a0587c;
184
+ --chart-3: #2aa79e;
185
+ --chart-4: #aa5849;
186
+ --chart-5: #67a369;
187
+ --chart-6: #946a1c;
188
+ --chart-7: #877cc3;
189
+ }
190
+
191
+ /* == Accesibilidad del movimiento == */
192
+
193
+ @media (prefers-reduced-motion: reduce) {
194
+ :root {
195
+ --duration-instant: 0ms; --duration-fast: 0ms; --duration-base: 0ms;
196
+ --duration-slow: 0ms; --duration-page: 0ms; --stagger-step: 0ms;
197
+ }
137
198
  }
138
199
 
139
- /* --------------------------------------------------------------------------
140
- 2. BASE (§6, §11.5, §13)
141
- -------------------------------------------------------------------------- */
142
200
  *, *::before, *::after { box-sizing: border-box; }
143
201
 
144
202
  /* Focus ring global de teclado — especificidad cero vía :where() */
145
203
  :where(a, button, [role="button"], input, select, textarea, summary, [tabindex]):focus-visible {
146
- outline: 2px solid var(--primary-500);
204
+ outline: 2px solid var(--focus-color);
147
205
  outline-offset: 2px;
148
206
  border-radius: 2px;
149
207
  }
@@ -180,17 +238,10 @@
180
238
  .celeste-reset h6 { font-size: var(--text-base); line-height: var(--leading-base); }
181
239
  .celeste-reset p { max-width: var(--measure); margin: 0 0 1em; }
182
240
  .celeste-reset table { font-variant-numeric: tabular-nums; }
183
- .celeste-reset ::placeholder { color: var(--text-disabled); }
241
+ .celeste-reset ::placeholder { color: var(--placeholder); }
184
242
  .celeste-reset ::selection { background: rgba(113,146,186,.25); }
185
243
 
186
- @media (prefers-reduced-motion: reduce) {
187
- *, *::before, *::after {
188
- animation-duration: 0.01ms !important;
189
- animation-iteration-count: 1 !important;
190
- transition-duration: 0.01ms !important;
191
- scroll-behavior: auto !important;
192
- }
193
- }
244
+
194
245
 
195
246
  /* --------------------------------------------------------------------------
196
247
  3. LAYOUT — contenedor, grid 12 col (§14)
@@ -238,12 +289,12 @@
238
289
  /* Gating de hover (§11.5): los hover que mueven/elevan (transform, box-shadow) van
239
290
  dentro de @media (hover: hover) and (pointer: fine) — en touch el tap dispara
240
291
  hovers falsos que se quedan pegados. Los hover de solo color/fondo quedan fuera. */
241
- .btn--primary { background: var(--accent); color: var(--text-on-primary); }
242
- .btn--primary:hover:not(:disabled) { background: var(--accent-hover); }
292
+ .btn--primary { background: var(--action-bg); color: var(--text-on-action); }
293
+ .btn--primary:hover:not(:disabled) { background: var(--action-hover); }
243
294
  @media (hover: hover) and (pointer: fine) {
244
295
  .btn--primary:hover:not(:disabled) { box-shadow: var(--shadow-sm); }
245
296
  }
246
- .btn--primary:active:not(:disabled) { background: var(--accent-active); box-shadow: none; }
297
+ .btn--primary:active:not(:disabled) { background: var(--action-active); box-shadow: none; }
247
298
  .btn--primary:disabled { background: var(--border); color: var(--text-disabled); box-shadow: none; }
248
299
 
249
300
  .btn--secondary { background: var(--surface); border-color: var(--border-strong); color: var(--text-primary); }
@@ -261,7 +312,7 @@
261
312
  .btn--ghost:active:not(:disabled) { background: var(--accent-soft-strong); }
262
313
  .btn--ghost:disabled { background: var(--border); color: var(--text-disabled); }
263
314
 
264
- .btn--danger { background: var(--danger-500); color: #fff; }
315
+ .btn--danger { background: var(--danger-500); color: var(--text-on-danger); }
265
316
  .btn--danger:hover:not(:disabled) { background: color-mix(in srgb, var(--danger-500) 92%, #000); }
266
317
  .btn--danger:active:not(:disabled) { background: color-mix(in srgb, var(--danger-500) 86%, #000); }
267
318
  .btn--danger:disabled { opacity: .5; }
@@ -302,7 +353,7 @@
302
353
  .field { display: flex; flex-direction: column; gap: 6px; }
303
354
  .field__label { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--text-secondary); }
304
355
  .field__help { font-size: var(--text-sm); color: var(--text-muted); }
305
- .field__error { font-size: var(--text-sm); color: var(--danger-500); display: inline-flex; align-items: center; gap: 6px; }
356
+ .field__error { font-size: var(--text-sm); color: var(--danger-text); display: inline-flex; align-items: center; gap: 6px; }
306
357
  .field__error svg { width: 14px; height: 14px; flex: none; }
307
358
  /* Campo obligatorio (§10.4): asterisco decorativo; el input lleva required/aria-required */
308
359
  .field--required .field__label::after { content: " *"; color: var(--danger-500); }
@@ -310,14 +361,14 @@
310
361
  .input, .textarea, .select {
311
362
  width: 100%; font-family: var(--font-body); font-size: var(--text-base);
312
363
  color: var(--text-primary); background: var(--surface);
313
- border: var(--border-width) solid var(--border-strong); border-radius: var(--radius-sm);
364
+ border: var(--border-width) solid var(--control-border); border-radius: var(--radius-sm);
314
365
  transition: border-color var(--duration-fast) var(--ease-out),
315
366
  box-shadow var(--duration-fast) var(--ease-out);
316
367
  }
317
368
  .input, .select { height: var(--control-height-md); padding: 0 14px; }
318
369
  .input:hover:not(:disabled):not(:focus),
319
370
  .textarea:hover:not(:disabled):not(:focus),
320
- .select:hover:not(:disabled):not(:focus) { border-color: var(--text-disabled); }
371
+ .select:hover:not(:disabled):not(:focus) { border-color: var(--border-hover); }
321
372
  .input:focus, .textarea:focus, .select:focus {
322
373
  outline: none; border-color: var(--accent); box-shadow: var(--ring);
323
374
  }
@@ -335,7 +386,7 @@
335
386
  .input-icon .input { padding-left: 40px; }
336
387
 
337
388
  .textarea { min-height: 96px; padding: 12px 14px; resize: vertical; line-height: var(--leading-base); }
338
- .textarea-counter { font-size: var(--text-xs); color: var(--text-disabled); text-align: right; }
389
+ .textarea-counter { font-size: var(--text-xs); color: var(--text-muted); text-align: right; }
339
390
 
340
391
  .select-wrap { position: relative; }
341
392
  .select { appearance: none; padding-right: 38px; cursor: pointer; }
@@ -371,7 +422,7 @@
371
422
  background: var(--surface); color: var(--text-primary);
372
423
  font-weight: var(--weight-semibold); box-shadow: var(--shadow-xs);
373
424
  }
374
- .segmented input:focus-visible + label { outline: 2px solid var(--primary-500); outline-offset: 2px; }
425
+ .segmented input:focus-visible + label { outline: 2px solid var(--focus-color); outline-offset: 2px; }
375
426
 
376
427
  .slider-row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 10px; }
377
428
  .slider-row .slider-label { font-size: var(--text-sm); color: var(--text-secondary); }
@@ -408,7 +459,7 @@
408
459
  }
409
460
  .checkbox__box {
410
461
  width: 20px; height: 20px; flex: none; display: grid; place-items: center;
411
- background: var(--surface); border: 2px solid var(--border-strong); border-radius: 4px;
462
+ background: var(--surface); border: 2px solid var(--control-border); border-radius: 4px;
412
463
  transition: background-color var(--duration-fast) var(--ease-out),
413
464
  border-color var(--duration-fast) var(--ease-out);
414
465
  }
@@ -418,7 +469,7 @@
418
469
  stroke-dasharray: 20; stroke-dashoffset: 20;
419
470
  transition: stroke-dashoffset var(--duration-base) var(--ease-spring);
420
471
  }
421
- .checkbox:hover .checkbox__box { border-color: var(--primary-400); }
472
+ .checkbox:hover .checkbox__box { border-color: var(--focus-color); }
422
473
  .checkbox input:checked ~ .checkbox__box { background: var(--accent); border-color: var(--accent); }
423
474
  .checkbox input:checked ~ .checkbox__box svg { stroke-dashoffset: 0; }
424
475
  .checkbox input:focus-visible ~ .checkbox__box { box-shadow: var(--ring); }
@@ -435,7 +486,7 @@
435
486
 
436
487
  .radio__dot {
437
488
  width: 20px; height: 20px; flex: none; display: grid; place-items: center;
438
- background: var(--surface); border: 2px solid var(--border-strong); border-radius: var(--radius-full);
489
+ background: var(--surface); border: 2px solid var(--control-border); border-radius: var(--radius-full);
439
490
  transition: background-color var(--duration-fast) var(--ease-out),
440
491
  border-color var(--duration-fast) var(--ease-out);
441
492
  }
@@ -444,7 +495,7 @@
444
495
  background: var(--text-on-primary); transform: scale(0);
445
496
  transition: transform var(--duration-base) var(--ease-spring);
446
497
  }
447
- .radio:hover .radio__dot { border-color: var(--primary-400); }
498
+ .radio:hover .radio__dot { border-color: var(--focus-color); }
448
499
  .radio input:checked ~ .radio__dot { background: var(--accent); border-color: var(--accent); }
449
500
  .radio input:checked ~ .radio__dot::after { transform: scale(1); }
450
501
  .radio input:focus-visible ~ .radio__dot { box-shadow: var(--ring); }
@@ -634,7 +685,7 @@
634
685
  }
635
686
  .alert > svg { width: 20px; height: 20px; flex: none; margin-top: 1px; }
636
687
  .alert__title { font-weight: var(--weight-semibold); margin: 0 0 2px; }
637
- .alert__body { opacity: .92; margin: 0; }
688
+ .alert__body { margin: 0; }
638
689
  .alert__close {
639
690
  margin-left: auto; flex: none; display: grid; place-items: center;
640
691
  width: 24px; height: 24px; border: 0; border-radius: var(--radius-sm);
@@ -774,10 +825,14 @@
774
825
  background: var(--surface); border: var(--border-width) solid var(--border);
775
826
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
776
827
  opacity: 0; transform: translateY(-4px); pointer-events: none;
777
- transition: opacity 160ms var(--ease-out), transform 160ms var(--ease-out);
828
+ transition: opacity var(--duration-fast) var(--ease-out), transform var(--duration-fast) var(--ease-out);
829
+
830
+ visibility: hidden;
831
+
832
+ display: none;
778
833
  }
779
834
  .menu--right { left: auto; right: 0; }
780
- .menu.is-open { opacity: 1; transform: none; pointer-events: auto; }
835
+ .menu.is-open { opacity: 1; transform: none; pointer-events: auto; visibility: visible; display: block; }
781
836
  .menu__item {
782
837
  display: flex; align-items: center; gap: 10px; width: 100%;
783
838
  padding: 9px 12px; border: 0; border-radius: var(--radius-sm);
@@ -787,7 +842,7 @@
787
842
  }
788
843
  .menu__item:hover { background: var(--bg); }
789
844
  .menu__item svg { width: 16px; height: 16px; color: var(--text-muted); flex: none; }
790
- .menu__item--danger, .menu__item--danger svg { color: var(--danger-500); }
845
+ .menu__item--danger, .menu__item--danger svg { color: var(--danger-text); }
791
846
  .menu__item--danger:hover { background: var(--danger-100); }
792
847
  .menu__sep { height: var(--border-width); background: var(--border); margin: 6px 4px; }
793
848
 
@@ -855,6 +910,32 @@
855
910
  .stat__delta--up { color: var(--success-text); }
856
911
  .stat__delta--down { color: var(--danger-text); }
857
912
 
913
+ /* Chip de métrica (§10.22): rótulo y valor en una pastilla de una línea */
914
+ .metric-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
915
+ .metric-chip {
916
+ display: inline-flex; align-items: center; gap: var(--space-2);
917
+ padding: var(--space-1) var(--space-3);
918
+ border: var(--border-width) solid var(--border); border-radius: var(--radius-full);
919
+ background: var(--surface);
920
+ font-family: var(--font-body); font-size: var(--text-sm); line-height: 1.5;
921
+ color: var(--text-secondary); white-space: nowrap;
922
+ }
923
+ .metric-chip svg { width: 16px; height: 16px; flex: none; color: var(--text-muted); }
924
+ .metric-chip__value {
925
+ font-weight: var(--weight-semibold); color: var(--link);
926
+ font-variant-numeric: tabular-nums;
927
+ }
928
+ button.metric-chip {
929
+ min-height: var(--control-height-md); padding-inline: var(--space-4);
930
+ cursor: pointer; text-align: left;
931
+ transition: background-color var(--duration-fast) var(--ease-out),
932
+ border-color var(--duration-fast) var(--ease-out),
933
+ transform var(--duration-instant) var(--ease-out);
934
+ }
935
+ button.metric-chip:hover { background: var(--accent-soft); border-color: var(--accent); }
936
+ button.metric-chip:active { background: var(--accent-soft-strong); transform: scale(.98); }
937
+ button.metric-chip:focus-visible { outline: 2px solid var(--focus-color); outline-offset: 2px; }
938
+
858
939
  .pagination { display: flex; align-items: center; gap: 4px; list-style: none; padding: 0; margin: 0; }
859
940
  .pagination__btn {
860
941
  display: inline-grid; place-items: center;
@@ -903,7 +984,7 @@
903
984
  .sidebar__item {
904
985
  display: flex; align-items: center; gap: 10px;
905
986
  padding: 10px 12px; border-radius: var(--radius-md);
906
- font-size: var(--text-sm); font-weight: var(--weight-medium);
987
+ font-family: var(--font-body); font-size: var(--text-sm); font-weight: var(--weight-medium);
907
988
  color: var(--text-secondary); text-decoration: none; border: 0; background: transparent;
908
989
  cursor: pointer; text-align: left; width: 100%;
909
990
  transition: background-color var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
@@ -913,6 +994,68 @@
913
994
  .sidebar__item.is-active { background: var(--accent-soft-strong); color: var(--link); }
914
995
  .sidebar__item.is-active svg { color: var(--accent); }
915
996
 
997
+ /* Grupos con rótulo dentro del sidebar */
998
+ .sidebar__group { display: flex; flex-direction: column; gap: 2px; }
999
+ .sidebar__group + .sidebar__group { margin-top: var(--space-4); }
1000
+ .sidebar__group-label {
1001
+ padding: 0 12px var(--space-1);
1002
+ font-size: var(--text-xs); font-weight: var(--weight-semibold);
1003
+ text-transform: uppercase; letter-spacing: var(--tracking-label);
1004
+ color: var(--text-muted); white-space: nowrap;
1005
+ }
1006
+ .sidebar__label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1007
+
1008
+ /* Sidebar contraíble (§10.24): expandido 260 px, riel de iconos de 64 px.
1009
+ El ancho cambia sin transición; solo los rótulos se funden con opacity y transform. */
1010
+ .sidebar--collapsible .sidebar__label {
1011
+ transition: opacity var(--duration-fast) var(--ease-out),
1012
+ transform var(--duration-fast) var(--ease-out);
1013
+ }
1014
+ .sidebar__toggle { margin-top: auto; }
1015
+ .sidebar.is-collapsed { width: 64px; padding-inline: var(--space-3); }
1016
+ .sidebar.is-collapsed .sidebar__item { position: relative; justify-content: center; padding-inline: 0; }
1017
+ .sidebar.is-collapsed .sidebar__toggle svg { transform: rotate(180deg); }
1018
+ .sidebar.is-collapsed .sidebar__group + .sidebar__group { margin-top: var(--space-2); }
1019
+ /* En el riel, el rótulo de grupo es un separador de 1 px; su texto sigue en el árbol de accesibilidad */
1020
+ .sidebar.is-collapsed .sidebar__group-label {
1021
+ height: 1px; padding: 0; margin: 0 var(--space-2) var(--space-2);
1022
+ overflow: hidden; color: transparent; background: var(--border);
1023
+ }
1024
+ /* Oculto a la vista pero accesible (patrón de .u-visually-hidden) */
1025
+ .sidebar.is-collapsed .sidebar__label,
1026
+ .sidebar.is-collapsed .sidebar__group:first-child > .sidebar__group-label {
1027
+ position: absolute; width: 1px; height: 1px; margin: -1px;
1028
+ clip-path: inset(50%); overflow: hidden; white-space: nowrap;
1029
+ }
1030
+ .sidebar.is-collapsed .sidebar__label {
1031
+ border-radius: var(--radius-sm); background: var(--tooltip-bg); color: var(--tooltip-text);
1032
+ font-size: var(--text-xs); line-height: 16px;
1033
+ pointer-events: none; z-index: 70;
1034
+ opacity: 0; transform: translateX(-4px);
1035
+ }
1036
+ /* Tooltip del riel: el propio rótulo aparece a la derecha del ítem, también con teclado */
1037
+ .sidebar.is-collapsed .sidebar__item:focus-visible .sidebar__label {
1038
+ left: calc(100% + 8px); top: calc(50% - 14px); width: auto; height: auto;
1039
+ margin: 0; padding: 6px 10px; clip-path: none; overflow: visible;
1040
+ opacity: 1; transform: none; transition-delay: 400ms;
1041
+ }
1042
+ /* Por hover solo con puntero real — en touch quedaría pegado tras el tap */
1043
+ @media (hover: hover) and (pointer: fine) {
1044
+ .sidebar.is-collapsed .sidebar__item:hover .sidebar__label {
1045
+ left: calc(100% + 8px); top: calc(50% - 14px); width: auto; height: auto;
1046
+ margin: 0; padding: 6px 10px; clip-path: none; overflow: visible;
1047
+ opacity: 1; transform: none; transition-delay: 400ms;
1048
+ }
1049
+ }
1050
+ /* Por debajo de 768 px la navegación vive en un Drawer --left (§10.29), que abre el botón ☰
1051
+ .sidebar-trigger (combinado con .icon-btn); desde 768 px el sidebar es fijo y el botón sobra */
1052
+ @media (max-width: 767px) {
1053
+ .sidebar--collapsible { display: none; }
1054
+ }
1055
+ @media (min-width: 768px) {
1056
+ .sidebar-trigger { display: none; }
1057
+ }
1058
+
916
1059
  .tabs { display: flex; gap: var(--space-6); border-bottom: var(--border-width) solid var(--border); }
917
1060
  .tabs__tab {
918
1061
  padding: 12px 4px; margin-bottom: -1px;
@@ -960,11 +1103,11 @@
960
1103
  width: 100%; height: var(--control-height-md); padding: 0 14px;
961
1104
  font-family: var(--font-body); font-size: var(--text-base);
962
1105
  color: var(--text-primary); background: var(--surface);
963
- border: var(--border-width) solid var(--border-strong); border-radius: var(--radius-sm);
1106
+ border: var(--border-width) solid var(--control-border); border-radius: var(--radius-sm);
964
1107
  transition: border-color var(--duration-fast) var(--ease-out),
965
1108
  box-shadow var(--duration-fast) var(--ease-out);
966
1109
  }
967
- .combobox__input:hover:not(:disabled):not(:focus) { border-color: var(--text-disabled); }
1110
+ .combobox__input:hover:not(:disabled):not(:focus) { border-color: var(--border-hover); }
968
1111
  .combobox__input:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
969
1112
  .combobox__input:disabled { background: var(--surface-alt); color: var(--text-disabled); cursor: not-allowed; }
970
1113
  .combobox__list {
@@ -1002,12 +1145,12 @@
1002
1145
  width: 100%; height: var(--control-height-md); padding: 0 40px;
1003
1146
  font-family: var(--font-body); font-size: var(--text-base);
1004
1147
  color: var(--text-primary); background: var(--surface);
1005
- border: var(--border-width) solid var(--border-strong); border-radius: var(--radius-sm);
1148
+ border: var(--border-width) solid var(--control-border); border-radius: var(--radius-sm);
1006
1149
  transition: border-color var(--duration-fast) var(--ease-out),
1007
1150
  box-shadow var(--duration-fast) var(--ease-out);
1008
1151
  }
1009
1152
  .search__input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
1010
- .search__input:hover:not(:focus) { border-color: var(--text-disabled); }
1153
+ .search__input:hover:not(:focus) { border-color: var(--border-hover); }
1011
1154
  .search__input:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
1012
1155
  .search__clear {
1013
1156
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
@@ -1070,8 +1213,12 @@
1070
1213
  transform-origin: top left; opacity: 0; transform: scale(.96); pointer-events: none;
1071
1214
  transition: opacity var(--duration-base) var(--ease-out),
1072
1215
  transform var(--duration-base) var(--ease-out);
1216
+
1217
+ visibility: hidden;
1218
+
1219
+ display: none;
1073
1220
  }
1074
- .popover.is-open .popover__panel { opacity: 1; transform: none; pointer-events: auto; }
1221
+ .popover.is-open .popover__panel { opacity: 1; transform: none; pointer-events: auto; visibility: visible; display: block; }
1075
1222
  .popover--right .popover__panel { left: auto; right: 0; transform-origin: top right; }
1076
1223
 
1077
1224
  /* ButtonGroup (§10.31) */
@@ -1096,11 +1243,11 @@
1096
1243
  width: 100%; height: var(--control-height-md); padding: 0 40px 0 14px;
1097
1244
  font-family: var(--font-body); font-size: var(--text-base);
1098
1245
  color: var(--text-primary); background: var(--surface);
1099
- border: var(--border-width) solid var(--border-strong); border-radius: var(--radius-sm);
1246
+ border: var(--border-width) solid var(--control-border); border-radius: var(--radius-sm);
1100
1247
  transition: border-color var(--duration-fast) var(--ease-out),
1101
1248
  box-shadow var(--duration-fast) var(--ease-out);
1102
1249
  }
1103
- .datepicker__input:hover:not(:disabled):not(:focus) { border-color: var(--text-disabled); }
1250
+ .datepicker__input:hover:not(:disabled):not(:focus) { border-color: var(--border-hover); }
1104
1251
  .datepicker__input:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
1105
1252
  .datepicker__input:disabled { background: var(--surface-alt); color: var(--text-disabled); cursor: not-allowed; }
1106
1253
  .datepicker__icon {
@@ -1115,8 +1262,12 @@
1115
1262
  transform-origin: top left; opacity: 0; transform: scale(.96); pointer-events: none;
1116
1263
  transition: opacity var(--duration-base) var(--ease-out),
1117
1264
  transform var(--duration-base) var(--ease-out);
1265
+
1266
+ visibility: hidden;
1267
+
1268
+ display: none;
1118
1269
  }
1119
- .datepicker.is-open .datepicker__calendar { opacity: 1; transform: none; pointer-events: auto; }
1270
+ .datepicker.is-open .datepicker__calendar { opacity: 1; transform: none; pointer-events: auto; visibility: visible; display: block; }
1120
1271
  .datepicker--right .datepicker__calendar { left: auto; right: 0; transform-origin: top right; }
1121
1272
 
1122
1273
  .calendar { width: 15.75rem; }
@@ -1128,6 +1279,7 @@
1128
1279
  .calendar__weekdays,
1129
1280
  .calendar__grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
1130
1281
  .calendar__weekdays { margin-bottom: 4px; }
1282
+ .calendar__week { display: contents; }
1131
1283
  .calendar__weekday {
1132
1284
  display: flex; align-items: center; justify-content: center; height: 28px;
1133
1285
  font-size: var(--text-xs); font-weight: var(--weight-medium); color: var(--text-muted);
@@ -1142,7 +1294,7 @@
1142
1294
  color var(--duration-fast) var(--ease-out);
1143
1295
  }
1144
1296
  .calendar__day:hover:not(:disabled):not(.calendar__day--selected) { background: var(--accent-soft); }
1145
- .calendar__day--outside { color: var(--text-disabled); }
1297
+ .calendar__day--outside { color: var(--text-muted); }
1146
1298
  .calendar__day--today { font-weight: var(--weight-semibold); box-shadow: inset 0 0 0 1px var(--border-strong); }
1147
1299
  .calendar__day--selected { background: var(--accent); color: var(--text-on-primary); font-weight: var(--weight-semibold); }
1148
1300
  .calendar__day:disabled { color: var(--text-disabled); cursor: not-allowed; }
@@ -1260,3 +1412,168 @@
1260
1412
  .u-mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
1261
1413
  .u-muted { color: var(--text-muted); }
1262
1414
  .u-measure { max-width: var(--measure); }
1415
+
1416
+ /* CONTRATOS COMPARTIDOS GENERADOS */
1417
+ /* Contratos comunes de interacción; la identidad y los valores viven en tokens.css. */
1418
+ .grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
1419
+ .grid > *, .field, .card { min-inline-size: 0; }
1420
+ .stack, .card__content, .form-stack, .text-group { display: flex; flex-direction: column; align-items: stretch; }
1421
+ .stack, .card__content { gap: var(--content-gap); }
1422
+ .stack--tight, .text-group { gap: var(--heading-gap); }
1423
+ .stack--cards { gap: var(--card-group-gap); }
1424
+ .form-stack { gap: var(--form-gap); }
1425
+ .cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
1426
+ .card { display: flex; flex-direction: column; gap: var(--card-content-gap); }
1427
+ .field { gap: var(--field-gap); }
1428
+ .field__label, .field__help, .field__error, .field > :is(label, p, span, div) { margin-block: 0; }
1429
+ :where(.field + .field, .field + .btn, .field + .cluster) { margin-block-start: var(--form-gap); }
1430
+ :where(.card + .card) { margin-block-start: var(--card-group-gap); }
1431
+ .stack > *, .card__content > *, .form-stack > *, .text-group > *, .grid > .card,
1432
+ .card > :is(h1, h2, h3, h4, h5, h6, p), .text-group > :is(h1, h2, h3, h4, h5, h6, p),
1433
+ .stack > :is(h1, h2, h3, h4, h5, h6, p) { margin-block: 0; }
1434
+ .form-stack > .field { margin-block: 0; }
1435
+ .btn {
1436
+ block-size: auto;
1437
+ min-block-size: var(--control-height-md);
1438
+ max-inline-size: 100%;
1439
+ white-space: normal;
1440
+ line-height: 1.35;
1441
+ text-align: center;
1442
+ }
1443
+ .btn--sm { min-block-size: var(--control-height-sm, 36px); }
1444
+ .btn--lg { min-block-size: var(--control-height-lg, 52px); }
1445
+ .btn--primary, .icon-btn--primary, .calendar__day--selected, .pagination__btn.is-active {
1446
+ background: var(--action-bg);
1447
+ color: var(--text-on-action);
1448
+ }
1449
+ .btn--primary:hover:not(:disabled), .icon-btn--primary:hover:not(:disabled) { background: var(--action-hover); color: var(--text-on-action); }
1450
+ .btn--primary:active:not(:disabled), .icon-btn--primary:active:not(:disabled) { background: var(--action-active); color: var(--text-on-action); }
1451
+ .input, .textarea, .select, .combobox__input, .search__input, .datepicker__input {
1452
+ max-inline-size: 100%;
1453
+ caret-color: var(--focus-color);
1454
+ }
1455
+ .input, .select, .combobox__input, .search__input, .datepicker__input {
1456
+ block-size: auto; min-block-size: var(--control-height-md);
1457
+ padding-block: var(--space-2); line-height: 1.5;
1458
+ }
1459
+ :is(.input, .textarea, .select, .combobox__input, .search__input, .datepicker__input):not(.input--error, .input--success, .textarea--error, [aria-invalid="true"]) { border-color: var(--control-border); }
1460
+ .input:hover:not(:disabled):not(:focus):not(.input--error, .input--success, [aria-invalid="true"]), .textarea:hover:not(:disabled):not(:focus):not(.textarea--error, [aria-invalid="true"]),
1461
+ .select:hover:not(:disabled):not(:focus), .combobox__input:hover:not(:disabled):not(:focus),
1462
+ .search__input:hover:not(:focus), .datepicker__input:hover:not(:disabled):not(:focus) { border-color: var(--border-hover); }
1463
+ .input:focus-visible, .textarea:focus-visible, .select:focus-visible,
1464
+ .combobox__input:focus-visible, .search__input:focus-visible, .datepicker__input:focus-visible {
1465
+ outline: 2px solid var(--focus-color);
1466
+ outline-offset: 2px;
1467
+ }
1468
+ .input[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--danger-text, var(--danger)); }
1469
+ .input.input--error, .textarea.textarea--error,
1470
+ .input.input--error:hover:not(:disabled):not(:focus), .textarea.textarea--error:hover:not(:disabled):not(:focus),
1471
+ :is(.input, .textarea, .select, .combobox__input, .search__input, .datepicker__input)[aria-invalid="true"]:hover:not(:disabled):not(:focus) {
1472
+ border-color: var(--danger-text, var(--danger));
1473
+ }
1474
+ .input.input--success, .input.input--success:hover:not(:disabled):not(:focus) { border-color: var(--success-text, var(--success)); }
1475
+ .pagination { max-inline-size: 100%; flex-wrap: wrap; row-gap: var(--space-2); }
1476
+ .pagination__ellipsis { color: var(--text-muted); }
1477
+ .step--current .step__marker { color: var(--link); border-color: var(--focus-color); }
1478
+ .checkbox input:focus-visible ~ .checkbox__box,
1479
+ .radio input:focus-visible ~ .radio__dot,
1480
+ .switch input:focus-visible ~ .switch__track {
1481
+ outline: 2px solid var(--focus-color);
1482
+ outline-offset: 2px;
1483
+ }
1484
+ input.checkbox, input.radio { border-color: var(--control-border); }
1485
+ input.checkbox:hover, input.radio:hover { border-color: var(--focus-color); }
1486
+ input.checkbox:checked, input.checkbox:indeterminate, input.radio:checked { border-color: var(--focus-color); }
1487
+ .switch__track { background: var(--control-border); }
1488
+ .tabs { max-inline-size: 100%; overflow-x: auto; }
1489
+ .tabs__tab { flex-shrink: 0; }
1490
+ .segmented { max-inline-size: 100%; block-size: auto; min-block-size: var(--control-height-md); overflow-x: auto; }
1491
+ .segmented label { padding-block: var(--space-2); }
1492
+ .stat__row, .breadcrumbs, .check-row { flex-wrap: wrap; row-gap: var(--space-2); }
1493
+ .progress-row, .slider-row { flex-wrap: wrap; gap: var(--space-2); }
1494
+ .stat__value { max-inline-size: 100%; white-space: normal; overflow-wrap: anywhere; }
1495
+ .file-upload, .file-upload__label { min-inline-size: 0; max-inline-size: 100%; }
1496
+ .file-upload__button { max-inline-size: 100%; white-space: normal; text-align: center; }
1497
+ .file-upload__hint { overflow-wrap: anywhere; }
1498
+ .table-scroll { max-inline-size: 100%; overflow-x: auto; overscroll-behavior-inline: contain; }
1499
+ .popover__panel, .datepicker__calendar, .combobox__list {
1500
+ max-inline-size: calc(100vw - 2rem);
1501
+ max-block-size: min(32rem, 70dvh);
1502
+ overflow: auto;
1503
+ }
1504
+ .file-upload__input:focus-visible + .file-upload__label { outline: 2px solid var(--focus-color); outline-offset: 2px; }
1505
+ .calendar { max-inline-size: calc(100vw - 2rem); }
1506
+ .ui-title, :is(h1, h2, h3, h4, h5, h6).ui-title, [data-mode="operate"] :is(h1, h2, h3) {
1507
+ font-family: var(--font-ui-heading);
1508
+ letter-spacing: 0;
1509
+ line-height: 1.3;
1510
+ font-weight: var(--weight-semibold);
1511
+ }
1512
+ .ui-title, :is(h1, h2, h3, h4, h5, h6).ui-title, [data-mode="operate"] h1 { font-size: var(--text-ui-title); }
1513
+ [data-mode="operate"] h2 { font-size: var(--text-xl); }
1514
+ [data-mode="operate"] h3 { font-size: var(--text-lg); }
1515
+ .display, .reading-title, :is(h1, h2, h3, h4, h5, h6):is(.display, .reading-title) {
1516
+ font-family: var(--font-display);
1517
+ font-size: var(--text-display-fluid);
1518
+ line-height: 1.08;
1519
+ letter-spacing: var(--tracking-display);
1520
+ text-wrap: balance;
1521
+ }
1522
+ :where(.celeste-reset, .salvia-reset, .bruma-reset, .nocturna-reset, body[data-system]) {
1523
+ scrollbar-color: var(--control-border) var(--bg);
1524
+ }
1525
+ ::selection,
1526
+ .celeste-reset ::selection, .salvia-reset ::selection, .bruma-reset ::selection {
1527
+ background: var(--selection-bg); color: var(--selection-text);
1528
+ }
1529
+ ::placeholder { color: var(--placeholder); opacity: 1; }
1530
+ :where(a) { text-underline-offset: .2em; text-decoration-thickness: .08em; }
1531
+ .skip-link {
1532
+ position: fixed; inset-block-start: var(--space-2); inset-inline-start: var(--space-2);
1533
+ z-index: 1000; padding: var(--space-3) var(--space-4);
1534
+ background: var(--action-bg); color: var(--text-on-action);
1535
+ border-radius: var(--radius-sm); transform: translateY(-180%);
1536
+ }
1537
+ .skip-link:focus { transform: none; outline: 2px solid var(--focus-color); outline-offset: 2px; }
1538
+ [data-tooltip]::before, [data-tooltip]::after { display: none; }
1539
+ [data-tooltip]:focus-visible::before, [data-tooltip]:focus-visible::after { display: block; }
1540
+ .has-tooltip .tooltip { display: none; }
1541
+ .has-tooltip:has(:focus-visible) .tooltip { display: block; opacity: 1; transform: translate(-50%, 0); }
1542
+ @media (hover: hover) and (pointer: fine) {
1543
+ [data-tooltip]:hover::before, [data-tooltip]:hover::after { display: block; }
1544
+ .has-tooltip:hover .tooltip { display: block; }
1545
+ }
1546
+ @media (pointer: coarse) {
1547
+ .btn, .icon-btn, .segmented label, .pagination button,
1548
+ .tag__close, .search__clear, .toast__close, .check-row,
1549
+ .checkbox:not(input), .radio:not(input), .switch:not(input) {
1550
+ min-block-size: var(--touch-target);
1551
+ min-inline-size: var(--touch-target);
1552
+ }
1553
+ }
1554
+ @media (max-width: 479px) {
1555
+ .btn-group { flex-wrap: wrap; }
1556
+ .modal { max-inline-size: calc(100vw - 2rem); }
1557
+ .stepper { flex-direction: column; align-items: stretch; gap: var(--space-4); }
1558
+ .step { flex-direction: row; align-items: center; gap: var(--space-3); text-align: start; min-inline-size: 0; }
1559
+ .step__label { overflow-wrap: anywhere; }
1560
+ .step__connector { display: none; }
1561
+ }
1562
+ @media (prefers-reduced-motion: reduce) {
1563
+ html, html:focus-within { scroll-behavior: auto; }
1564
+ .spinner, .skeleton, .skeleton::after,
1565
+ .progress--indeterminate .progress__bar, .alert.is-leaving, .toast.is-leaving { animation: none; }
1566
+ .progress--indeterminate .progress__bar { transform: none; }
1567
+ .btn, .icon-btn, .card--interactive, .slider::-webkit-slider-thumb { transform: none; }
1568
+ .btn:active:not(:disabled), .icon-btn:active:not(:disabled), .card--interactive:hover { transform: none; }
1569
+ .btn, .icon-btn { transition: background-color 80ms linear, color 80ms linear; }
1570
+ .menu, .popover__panel, .datepicker__calendar, .link::after { transition: none; }
1571
+ .progress__bar, .progress-ring__value, .accordion__content, .accordion__body { transition: none; }
1572
+ }
1573
+ @media (forced-colors: active) {
1574
+ input.switch, .switch__track { border: 1px solid CanvasText; background: Canvas; }
1575
+ input.switch::after, .switch__track::after { background: CanvasText; }
1576
+ input.switch:checked, .switch input:checked ~ .switch__track { border-color: Highlight; }
1577
+ input.switch:checked::after, .switch input:checked ~ .switch__track::after { background: Highlight; }
1578
+ .checkbox__box, .radio__dot { border-color: CanvasText; }
1579
+ }