create-lexy 0.6.1 → 0.6.3

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.
Files changed (93) hide show
  1. package/README.md +7 -2
  2. package/assets/fonts/{OFL-NotoSans.txt → LICENSE-Geist.txt} +4 -5
  3. package/assets/fonts/geist-mono-variable-italic.woff2 +0 -0
  4. package/assets/fonts/geist-mono-variable.woff2 +0 -0
  5. package/assets/fonts/geist-sans-variable-italic.woff2 +0 -0
  6. package/assets/fonts/geist-sans-variable.woff2 +0 -0
  7. package/assets/r/accordion.json +3 -3
  8. package/assets/r/alert-dialog.json +3 -3
  9. package/assets/r/app-accordion.json +1 -1
  10. package/assets/r/app-dialog.json +3 -3
  11. package/assets/r/app-header-bar.json +2 -2
  12. package/assets/r/app-sidebar.json +2 -2
  13. package/assets/r/avatar.json +3 -3
  14. package/assets/r/badge.json +3 -3
  15. package/assets/r/brand-background.json +1 -1
  16. package/assets/r/breadcrumb.json +3 -3
  17. package/assets/r/button-group.json +3 -3
  18. package/assets/r/button.json +3 -3
  19. package/assets/r/calendar.json +2 -2
  20. package/assets/r/card.json +3 -3
  21. package/assets/r/chart.json +2 -2
  22. package/assets/r/checkbox.json +2 -2
  23. package/assets/r/combobox.json +3 -3
  24. package/assets/r/command.json +3 -3
  25. package/assets/r/confirmacion.json +1 -1
  26. package/assets/r/counter-badge.json +3 -3
  27. package/assets/r/crm-desk.json +1 -1
  28. package/assets/r/crm-detalle-caso.json +5 -5
  29. package/assets/r/date-picker.json +1 -1
  30. package/assets/r/dialog.json +3 -3
  31. package/assets/r/dropdown-menu.json +3 -3
  32. package/assets/r/empty.json +2 -2
  33. package/assets/r/feature-card.json +3 -3
  34. package/assets/r/form.json +3 -3
  35. package/assets/r/header-bar.json +2 -2
  36. package/assets/r/input.json +3 -3
  37. package/assets/r/intake-wizard.json +1 -1
  38. package/assets/r/label.json +3 -3
  39. package/assets/r/logo.json +2 -2
  40. package/assets/r/menubar.json +3 -3
  41. package/assets/r/navigation-menu.json +3 -3
  42. package/assets/r/pagination.json +2 -2
  43. package/assets/r/popover.json +3 -3
  44. package/assets/r/profile-card.json +3 -3
  45. package/assets/r/progress.json +2 -2
  46. package/assets/r/radio-group.json +2 -2
  47. package/assets/r/registry.json +47 -47
  48. package/assets/r/scroll-area.json +2 -2
  49. package/assets/r/searchbox.json +3 -3
  50. package/assets/r/select.json +3 -3
  51. package/assets/r/separator.json +2 -2
  52. package/assets/r/sheet.json +2 -2
  53. package/assets/r/sidebar.json +3 -3
  54. package/assets/r/skeleton.json +2 -2
  55. package/assets/r/slider.json +3 -3
  56. package/assets/r/snippet.json +3 -3
  57. package/assets/r/spinner.json +2 -2
  58. package/assets/r/status-dot.json +3 -3
  59. package/assets/r/switch.json +3 -3
  60. package/assets/r/table.json +3 -3
  61. package/assets/r/tabs.json +3 -3
  62. package/assets/r/tag.json +3 -3
  63. package/assets/r/textarea.json +3 -3
  64. package/assets/r/toaster.json +3 -3
  65. package/assets/r/tooltip.json +3 -3
  66. package/assets/r/tree.json +3 -3
  67. package/assets/registry-version +1 -1
  68. package/assets/theme/lexy-theme.css +562 -112
  69. package/dist/index.js +590 -276
  70. package/package.json +4 -2
  71. package/templates/.claude/skills/lexy-design/SKILL.md +189 -0
  72. package/templates/.claude/skills/lexy-dev/SKILL.md +168 -0
  73. package/templates/.claude/skills/lexy-mock-data/SKILL.md +50 -0
  74. package/templates/.github/copilot-instructions.md +50 -0
  75. package/templates/.mcp.json +8 -0
  76. package/templates/AGENTS.md +243 -0
  77. package/templates/CLAUDE.md +61 -0
  78. package/templates/ai/IMPLEMENTATION-PROTOCOL.md +148 -0
  79. package/templates/ai/PRODUCTION-CLEANUP.md +17 -0
  80. package/templates/ai/PROJECT-CONTEXT.md +65 -0
  81. package/templates/ai/README.md +19 -0
  82. package/templates/ai/TECHNICAL-USAGE.md +220 -0
  83. package/templates/ai/pautas/arquitectura-informacion-ux.md +243 -0
  84. package/templates/ai/pautas/buenas-practicas.md +236 -0
  85. package/templates/ai/pautas/calidad-industria.md +109 -0
  86. package/templates/ai/pautas/diseno-cliente.md +136 -0
  87. package/templates/ai/pautas/diseno-crm-lexy.md +109 -0
  88. package/templates/ai/pautas/patrones-de-codigo.md +234 -0
  89. package/templates/ai/pautas/recetas-layout.md +419 -0
  90. package/templates/ai/pautas/sistema-visual.md +197 -0
  91. package/templates/ai/pautas/ux-writing.md +214 -0
  92. package/templates/scripts/check-geometry.mjs +139 -0
  93. package/assets/fonts/noto-sans-latin.woff2 +0 -0
@@ -11,49 +11,132 @@
11
11
  */
12
12
 
13
13
  /*
14
- * Noto Sans (variable, SIL OFL) tipografía principal de Lexy, auto-hospedada
15
- * para garantizar un render idéntico en todos los sistemas (Windows, Linux,
16
- * macOS). Es muy cercana a Segoe UI, aunque algo más geométrica y con mayor
17
- * avance horizontal; se ajusta con size-adjust y un tracking sutil (ver
18
- * @layer base) para igualar densidad y tamaño aparente. Un solo woff2 variable
19
- * cubre los pesos 400–700. Licencia en /fonts/OFL-NotoSans.txt.
14
+ * Geist Sans y Geist Mono (variables, SIL OFL) son las fuentes de texto de
15
+ * Lexy. Switzer se reserva para display. Se auto-hospedan para garantizar un
16
+ * render idéntico en todos los sistemas.
20
17
  */
21
18
  @font-face {
22
- font-family: "Noto Sans";
19
+ font-family: "Geist Sans";
23
20
  font-style: normal;
24
- font-weight: 400 700;
21
+ font-weight: 100 900;
25
22
  font-display: swap;
26
- size-adjust: 96%;
27
- src: url("/fonts/noto-sans-latin.woff2") format("woff2");
23
+ src: url("/fonts/geist-sans-variable.woff2") format("woff2");
24
+ }
25
+
26
+ @font-face {
27
+ font-family: "Geist Sans";
28
+ font-style: italic;
29
+ font-weight: 100 900;
30
+ font-display: swap;
31
+ src: url("/fonts/geist-sans-variable-italic.woff2") format("woff2");
32
+ }
33
+
34
+ @font-face {
35
+ font-family: "Geist Mono";
36
+ font-style: normal;
37
+ font-weight: 100 900;
38
+ font-display: swap;
39
+ src: url("/fonts/geist-mono-variable.woff2") format("woff2");
40
+ }
41
+
42
+ @font-face {
43
+ font-family: "Geist Mono";
44
+ font-style: italic;
45
+ font-weight: 100 900;
46
+ font-display: swap;
47
+ src: url("/fonts/geist-mono-variable-italic.woff2") format("woff2");
48
+ }
49
+
50
+ /*
51
+ * Fuentes de exploración y display. Se auto-hospedan en assets/fonts/.
52
+ * Licencias responsabilidad de quien las usa: Neue Montreal (Pangram Pangram,
53
+ * free personal use), Satoshi y Switzer
54
+ * (Fontshare/Indian Type Foundry). Los rangos font-weight mapean los 4 pesos
55
+ * del theme (400/500/600/700) a las caras reales disponibles, sin sintetizar.
56
+ *
57
+ * Neue Montreal — Regular (100–500) + Semibold (600–900).
58
+ */
59
+ @font-face {
60
+ font-family: "Neue Montreal";
61
+ font-style: normal;
62
+ font-weight: 100 500;
63
+ font-display: swap;
64
+ src: url("/fonts/neue-montreal-regular.woff2") format("woff2");
65
+ }
66
+ @font-face {
67
+ font-family: "Neue Montreal";
68
+ font-style: normal;
69
+ font-weight: 600 900;
70
+ font-display: swap;
71
+ src: url("/fonts/neue-montreal-semibold.woff2") format("woff2");
72
+ }
73
+
74
+ /* Satoshi — Regular (100–400) + Medium (500) + Bold (600–900). */
75
+ @font-face {
76
+ font-family: "Satoshi";
77
+ font-style: normal;
78
+ font-weight: 100 400;
79
+ font-display: swap;
80
+ src: url("/fonts/satoshi-regular.woff2") format("woff2");
81
+ }
82
+ @font-face {
83
+ font-family: "Satoshi";
84
+ font-style: normal;
85
+ font-weight: 500;
86
+ font-display: swap;
87
+ src: url("/fonts/satoshi-medium.woff2") format("woff2");
88
+ }
89
+ @font-face {
90
+ font-family: "Satoshi";
91
+ font-style: normal;
92
+ font-weight: 600 900;
93
+ font-display: swap;
94
+ src: url("/fonts/satoshi-bold.woff2") format("woff2");
95
+ }
96
+
97
+ /* Switzer — variable, cubre todos los pesos en un archivo. */
98
+ @font-face {
99
+ font-family: "Switzer";
100
+ font-style: normal;
101
+ font-weight: 100 900;
102
+ font-display: swap;
103
+ src: url("/fonts/switzer-variable.woff2") format("woff2");
28
104
  }
29
105
 
30
106
  @theme {
31
107
  /* ── Color ──
32
- Valores cromáticos alineados con LexyDesign (src/app/tokens.css), la fuente
33
- de verdad de la marca, que sigue Fluent 2. Se conserva la NOMENCLATURA
34
- shadcn/Tailwind (tokens semánticos consumidos como bg-primary,
35
- text-muted-foreground, …): solo cambian los hex, no los nombres. El token
36
- Fluent de origen se anota a la derecha de cada valor. */
108
+ Atmósfera canónica: Blanco nítido. El canvas y las superficies desaparecen
109
+ visualmente para que el contenido lidere; la jerarquía se construye con
110
+ tinta limpia, grises neutros y marca concentrada en acciones y estados.
111
+ Se conserva la nomenclatura semántica shadcn/Tailwind. */
37
112
 
38
113
  /* ── Superficies y texto ── */
39
- --color-background: #ffffff; /* blanco absoluto */
40
- --color-foreground: #242424; /* Fluent NeutralForeground1 */
41
- --color-card: #fdfdfe; /* superficie casi blanca, con un matiz frío mínimo */
42
- --color-card-foreground: #242424;
114
+ --color-background: #ffffff; /* canvas canónico */
115
+ --color-foreground: #202124; /* tinta principal */
116
+ --color-foreground-secondary: #4f5157; /* texto de apoyo con contraste estable */
117
+ --color-foreground-faint: #8a8d97; /* metadata no esencial; ≥3:1, solo tamaños grandes — DEC-009 */
118
+ --color-card: #ffffff; /* la superficie no tiñe el canvas */
119
+ --color-card-foreground: #202124;
43
120
  --color-popover: #ffffff;
44
- --color-popover-foreground: #242424;
121
+ --color-popover-foreground: #202124;
122
+ --color-surface-subtle: #f7f7f8; /* chrome y separación de primer nivel */
123
+ --color-surface-muted: #f1f1f3; /* selección neutral y agrupación secundaria */
124
+ --color-surface-raised: #ffffff; /* popovers y superficies realmente elevadas */
125
+ --color-surface-container: #fafafb; /* zona de contención: agrupa regiones del documento por tono, radio y aire en lugar de hairlines — DEC-014 */
45
126
 
46
- /* ── Acción ── */
127
+ /* ── Acción · Marca funcional ──
128
+ El índigo aparece cuando comunica acción, foco o selección. No se usa para
129
+ teñir el canvas ni como decoración editorial. */
47
130
  --color-primary: #4648d4; /* índigo de marca · Fluent BrandBackground */
48
131
  --color-primary-foreground: #ffffff;
49
- --color-primary-hover: #4b41e1; /* Fluent BrandBackgroundHover */
132
+ --color-primary-hover: #3d3fc0; /* la presión oscurece, no cambia de matiz — DEC-009 */
50
133
  --color-primary-active: #313396; /* Fluent BrandBackgroundPressed */
51
- --color-secondary: #f5f5f5; /* Fluent NeutralBackground3 */
52
- --color-secondary-foreground: #424242; /* Fluent NeutralForeground2 */
53
- --color-accent: #ebf3fc; /* tinte de marca · Fluent BrandBackground2 */
54
- --color-accent-foreground: #4648d4; /* Fluent BrandForeground1 */
55
- --color-muted: #f5f5f5; /* Fluent NeutralBackground3 */
56
- --color-muted-foreground: #616161; /* Fluent NeutralForeground3 */
134
+ --color-secondary: var(--color-surface-subtle); /* alias: la escalera DEC-006 es fuente única */
135
+ --color-secondary-foreground: var(--color-foreground-secondary);
136
+ --color-accent: #f0f0fb; /* presencia de marca de baja intensidad */
137
+ --color-accent-foreground: #4648d4;
138
+ --color-muted: var(--color-surface-muted); /* alias: la escalera DEC-006 es fuente única */
139
+ --color-muted-foreground: #696c75; /* AA sobre blanco, muted y sidebar — DEC-009 */
57
140
 
58
141
  /* ── Marca ── */
59
142
  --color-brand-navy: #0b013c; /* navy/ink del wordmark Lexy (HeaderBar surface navy) */
@@ -61,109 +144,263 @@
61
144
  --color-brand-indigo-deep: #4429cc; /* índigo profundo de marca (superficies expresivas) */
62
145
 
63
146
  /* ── Bordes y foco ── */
64
- --color-border: #d1d1d1; /* Fluent NeutralStroke1 */
65
- --color-input: #d1d1d1;
147
+ --color-border-subtle: #ececef; /* separación editorial y cards planas */
148
+ --color-border: #dedee3; /* controles y estructura persistente */
149
+ --color-border-strong: #c9cad0; /* campos y límites que deben ser inequívocos */
150
+ --color-input: #c9cad0;
66
151
  --color-ring: #4648d4; /* Fluent BrandStroke1 */
67
152
 
68
- /* ── Radiuscontrato de geometría: `rounded` en controles,
69
- `rounded-md`/`lg` en superficies. Todo deriva de la perilla --radius;
70
- los valores preservan los defaults de Tailwind (4/6/8px). ── */
71
- --radius: 0.25rem; /* 4px · controles */
72
- --radius-sm: var(--radius);
73
- --radius-md: calc(var(--radius) + 0.125rem); /* 6px · superficies */
74
- --radius-lg: calc(var(--radius) + 0.25rem); /* 8px · superficies grandes */
75
-
76
- /* ── Sidebar shadcn ── */
77
- --color-sidebar: #ffffff; /* = background: la navegación comparte superficie con la página */
78
- --color-sidebar-foreground: #242424;
153
+ /* ── Geometríauna forma por rol (DEC-010, refina DEC-003).
154
+ La escala numérica se asigna mediante aliases de rol: 4px para piezas
155
+ mini; 6px para campos, todos los botones, navegación y opciones de
156
+ menú; 8px para flotantes compactas; 10px para cards; 14px
157
+ para overlays y 20px para media y paneles hero. Todos los botones
158
+ comparten la misma base de 6px, sin excepciones por jerarquía o tamaño. ── */
159
+ --radius-sm: 0.125rem; /* 2px · elementos mini (<32px) */
160
+ --radius: 0.25rem; /* 4px · checkbox y piezas compactas */
161
+ --radius-interactive: 0.375rem; /* 6px · base compartida por controles rectangulares */
162
+ --radius-control: var(--radius-interactive); /* input, textarea, select y searchbox */
163
+ --radius-button: var(--radius-interactive); /* todos los botones y tamaños */
164
+ --radius-button-lg: var(--radius-button); /* todos los tamaños de botón comparten 6px */
165
+ --radius-menu-item: var(--radius-interactive); /* opción dentro de menú o command */
166
+ --radius-nav-item: var(--radius-interactive); /* tabs, navegación y sidebar */
167
+ --radius-md: 0.5rem; /* 8px · superficies flotantes compactas */
168
+ --radius-lg: 0.625rem; /* 10px · cards y superficies grandes */
169
+ --radius-xl: 0.875rem; /* 14px · overlays de cambio de contexto (dialog, sheet) */
170
+ --radius-2xl: 1.25rem; /* 20px · media y paneles hero */
171
+ --radius-full: 9999px; /* avatares, dots, toggles y conteos circulares */
172
+
173
+ /* ── Iconografía — el tamaño declara función, no el archivo de origen.
174
+ El glifo y su caja interactiva son decisiones independientes: botones
175
+ y navegación conservan un glifo óptico de 16px dentro de controles de
176
+ 32–40px. Los iconos de objeto mantienen su significado al cambiar el
177
+ estado; color y badges comunican el estado por separado. ── */
178
+ --icon-size-inline: 1rem; /* 16px · texto, botones, navegación y adornos */
179
+ --icon-size-control: 1rem; /* 16px · acción exclusivamente icono */
180
+ --icon-size-object: 1rem; /* 16px · tipo de documento dentro de caja de 32px */
181
+ --icon-size-feature: 1.5rem; /* 24px · empty state o comunicación excepcional */
182
+
183
+ /* ── Elevación semántica — solo para superficies que realmente flotan.
184
+ El tinte navy es una firma consciente registrada en DEC-010: aparece
185
+ únicamente al elevar, nunca como profundidad permanente de controles. ── */
186
+ --shadow-raised: 0 1px 2px rgb(11 1 60 / 0.06), 0 2px 8px rgb(11 1 60 / 0.04);
187
+ --shadow-overlay: 0 8px 24px rgb(11 1 60 / 0.10), 0 2px 8px rgb(11 1 60 / 0.06);
188
+
189
+ /* ── Sidebar — chrome tenue con marca concentrada en interacción.
190
+ Recupera la intención del Kickoff original (lavanda + índigo en navegación)
191
+ sin convertir toda la superficie en un bloque de color. ── */
192
+ --color-sidebar: var(--color-background);
193
+ --color-sidebar-foreground: var(--color-foreground);
79
194
  --color-sidebar-primary: #4648d4;
80
195
  --color-sidebar-primary-foreground: #ffffff;
81
- --color-sidebar-accent: #ededfb;
82
- --color-sidebar-accent-foreground: #4648d4;
83
- --color-sidebar-border: #d1d1d1;
196
+ --color-sidebar-hover: color-mix(in oklab, var(--color-primary) 5%, var(--color-sidebar));
197
+ --color-sidebar-accent: color-mix(in oklab, var(--color-primary) 10%, var(--color-sidebar));
198
+ --color-sidebar-accent-foreground: var(--color-primary);
199
+ --color-sidebar-border: var(--color-border-subtle);
84
200
  --color-sidebar-ring: #4648d4;
85
201
 
86
- /* ── Series de datos (charts) ──
87
- Paleta categórica anclada en el índigo de marca, pensada para que series
88
- contiguas se distingan sin competir. Se consumen vía la prop `color` del
89
- ChartConfig (color: "var(--color-chart-1)") o como bg-chart-1 en Tailwind. */
90
- --color-chart-1: #4648d4; /* índigo de marca */
91
- --color-chart-2: #0f6cbd; /* azul de comunicación */
92
- --color-chart-3: #1aab8a; /* teal */
93
- --color-chart-4: #f7630c; /* naranja */
94
- --color-chart-5: #b14ad1; /* magenta */
95
-
96
- /* ── Estados semánticos (paleta Fluent 2) ── */
97
- --color-destructive: #d13438; /* Fluent PaletteRedBackground3 */
202
+ /* ── Series de datos (charts) — DEC-009.
203
+ Paleta categórica propia y vívida. Los datos nunca reutilizan el índigo
204
+ de acción ni los hex semánticos: una serie no debe parecer accionable
205
+ ni leerse como advertencia (el naranja vivo quedó libre al mover el
206
+ warning tipográfico a #9f5400). Se consumen vía la prop `color` del
207
+ ChartConfig (color: "var(--color-chart-1)") o como bg-chart-1. */
208
+ --color-chart-1: #2f80ed; /* azul vivo */
209
+ --color-chart-2: #1aab8a; /* teal vivo */
210
+ --color-chart-3: #f7630c; /* naranja vivo */
211
+ --color-chart-4: #b14ad1; /* magenta vivo */
212
+ --color-chart-5: #e23f74; /* rosa vivo */
213
+
214
+ /* ── Estados semánticos — base vívida + paso -strong para tipografía.
215
+ La base (dots, rellenos, tintes de chips) es vívida; el paso -strong
216
+ garantiza AA cuando el estado se escribe como texto sobre claro. ── */
217
+ --color-destructive: #d13438; /* vívido y AA a la vez (4.9:1) */
98
218
  --color-destructive-foreground: #ffffff;
99
- --color-success: #107c10; /* Fluent PaletteGreenBackground3 */
219
+ --color-success: #16a34a; /* verde vívido · dots, rellenos y tintes */
220
+ --color-success-strong: #107c10; /* texto de éxito sobre claro (5.4:1) */
100
221
  --color-success-foreground: #ffffff;
101
- --color-warning: #f7630c; /* Fluent StatusWarningBackground3 */
222
+ --color-warning: #f59e0b; /* ámbar vívido · dots, rellenos y tintes */
223
+ --color-warning-strong: #9f5400; /* texto de advertencia sobre claro (5.6:1) */
102
224
  --color-warning-foreground: #ffffff;
103
225
  --color-info: #0f6cbd; /* azul de comunicación Fluent 2 */
104
226
  --color-info-foreground: #ffffff;
105
227
 
106
- /* ── Tipografía — rampa oficial de Fluent 2 (Microsoft), nomenclatura
107
- Tailwind. Cada tamaño viene pareado con su line-height (px de
108
- referencia). Los tamaños de cuerpo (xs–lg) usan tracking nativo
109
- (normal); a partir de los titulares (xl–5xl) se aplica un tracking
110
- negativo progresivo para cerrar el espaciado óptico, igual que la
111
- rampa de Display/Title de Fluent. ── */
112
- --text-xs: 0.75rem; /* 12 / 16 · Caption */
228
+ /* ── Tipografía — ritmo canónico Material 3 (DEC-002), podada a escalones
229
+ con oficio (DEC-015): cuerpo 12/16, 14/20 y 16/24; títulos 22/28,
230
+ 24/32 y 32/40. Geist Sans y tracking negativo progresivo que escala
231
+ con el tamaño. ── */
232
+ --text-xs: 0.75rem; /* 12 / 16 · Body small */
113
233
  --text-xs--line-height: 1rem;
114
- --text-xs--letter-spacing: normal;
115
- --text-sm: 0.875rem; /* 14 / 20 · Body */
234
+ /* Tracking levemente positivo en tamaños chicos: la neo-grotesca (Switzer)
235
+ trae espaciado ajustado pensado para display; en texto pequeño se beneficia
236
+ de un poco de aire. Graduado: más chico = un pelín más. */
237
+ --text-xs--letter-spacing: 0.01em;
238
+ --text-sm: 0.875rem; /* 14 / 20 · Body medium / Label large */
116
239
  --text-sm--line-height: 1.25rem;
117
- --text-sm--letter-spacing: normal;
118
- --text-base: 1rem; /* 16 / 22 · Body large */
119
- --text-base--line-height: 1.375rem;
120
- --text-base--letter-spacing: normal;
121
- --text-lg: 1.25rem; /* 20 / 26 · Subtitle */
122
- --text-lg--line-height: 1.625rem;
123
- --text-lg--letter-spacing: normal;
124
- --text-xl: 1.5rem; /* 24 / 32 · Title 3 */
240
+ --text-sm--letter-spacing: 0.005em;
241
+ --text-base: 1rem; /* 16 / 24 · Body large */
242
+ --text-base--line-height: 1.5rem;
243
+ --text-base--letter-spacing: -0.003em;
244
+ --text-lg: 1.375rem; /* 22 / 28 · Title large */
245
+ --text-lg--line-height: 1.75rem;
246
+ --text-lg--letter-spacing: -0.018em;
247
+ --text-xl: 1.5rem; /* 24 / 32 · Headline small */
125
248
  --text-xl--line-height: 2rem;
126
- --text-xl--letter-spacing: -0.01em;
127
- --text-2xl: 1.75rem; /* 28 / 36 · Title 2 */
128
- --text-2xl--line-height: 2.25rem;
129
- --text-2xl--letter-spacing: -0.014em;
130
- --text-3xl: 2rem; /* 32 / 40 · Title 1 */
249
+ --text-xl--letter-spacing: -0.019em;
250
+ /* 28 sin oficio — DEC-015: fuera de la rampa activa (reserva editorial en :root). */
251
+ --text-2xl: initial;
252
+ --text-2xl--line-height: initial;
253
+ --text-2xl--letter-spacing: initial;
254
+ --text-3xl: 2rem; /* 32 / 40 · Headline large */
131
255
  --text-3xl--line-height: 2.5rem;
132
- --text-3xl--letter-spacing: -0.018em;
133
- --text-4xl: 2.5rem; /* 40 / 52 · Large title */
134
- --text-4xl--line-height: 3.25rem;
135
- --text-4xl--letter-spacing: -0.022em;
136
- --text-5xl: 4.25rem; /* 68 / 92 · Display */
137
- --text-5xl--line-height: 5.75rem;
138
- --text-5xl--letter-spacing: -0.028em;
256
+ --text-3xl--letter-spacing: -0.022em;
257
+ /* Display 36/45/57 sin oficio en producto — DEC-015: no generan utilidades;
258
+ sus valores viven como reserva editorial en :root, al final del archivo. */
259
+ --text-4xl: initial;
260
+ --text-4xl--line-height: initial;
261
+ --text-4xl--letter-spacing: initial;
262
+ --text-5xl: initial;
263
+ --text-5xl--line-height: initial;
264
+ --text-5xl--letter-spacing: initial;
265
+ --text-6xl: initial;
266
+ --text-6xl--line-height: initial;
267
+ --text-6xl--letter-spacing: initial;
139
268
 
140
- /* ── Pesos estándar de Fluent/Segoe UI. ── */
269
+ /* ── Pesos funcionales compatibles con los roles de Material 3. ── */
141
270
  --font-weight-normal: 400;
142
271
  --font-weight-medium: 500;
143
272
  --font-weight-semibold: 600;
144
273
  --font-weight-bold: 700;
145
274
 
146
- /* ── Fuente ──
147
- Noto Sans (auto-hospedada, OFL) es la única fuente de marca; se carga vía
148
- @font-face, así el render es idéntico en todos los sistemas. Los genéricos
149
- finales solo actúan si el woff2 no llegara a cargar. */
150
- --font-sans: "Noto Sans", system-ui, -apple-system, BlinkMacSystemFont,
275
+ /* ── Fuentes ──
276
+ Geist Sans y Geist Mono se auto-hospedan con licencia OFL. Los genéricos
277
+ finales solo actúan si los archivos no llegaran a cargar. */
278
+ --font-sans: "Geist Sans", system-ui, -apple-system, BlinkMacSystemFont,
151
279
  Roboto, "Helvetica Neue", Arial, sans-serif;
280
+ --font-mono: "Geist Mono", ui-monospace, SFMono-Regular, Menlo, Monaco,
281
+ Consolas, "Liberation Mono", monospace;
282
+ /* Display: heros y superficies gráficas; nunca cuerpo ni UI. */
283
+ --font-display: "Switzer", var(--font-sans);
284
+
285
+ /* ── Roles tipográficos — asignación semántica (DEC-012).
286
+ La escala numérica sigue siendo la fuente de los valores; estos tokens
287
+ fijan qué combinación de tamaño, ritmo, tracking y peso corresponde a
288
+ cada función. Dos roles pueden compartir tamaño sin compartir jerarquía. */
289
+ --type-page-title-size: var(--text-3xl);
290
+ --type-page-title-line-height: var(--text-3xl--line-height);
291
+ --type-page-title-letter-spacing: var(--text-3xl--letter-spacing);
292
+ --type-page-title-weight: var(--font-weight-semibold);
293
+
294
+ --type-dialog-title-size: var(--text-xl);
295
+ --type-dialog-title-line-height: var(--text-xl--line-height);
296
+ --type-dialog-title-letter-spacing: var(--text-xl--letter-spacing);
297
+ --type-dialog-title-weight: var(--font-weight-semibold);
298
+
299
+ /* Subnivel de documento entre sección (16) y página (32) — DEC-015 */
300
+ --type-subsection-title-size: var(--text-lg);
301
+ --type-subsection-title-line-height: var(--text-lg--line-height);
302
+ --type-subsection-title-letter-spacing: var(--text-lg--letter-spacing);
303
+ --type-subsection-title-weight: var(--font-weight-semibold);
304
+
305
+ --type-section-title-size: var(--text-base);
306
+ --type-section-title-line-height: var(--text-base--line-height);
307
+ --type-section-title-letter-spacing: var(--text-base--letter-spacing);
308
+ --type-section-title-weight: var(--font-weight-semibold);
309
+
310
+ --type-item-title-size: var(--text-base);
311
+ --type-item-title-line-height: var(--text-base--line-height);
312
+ --type-item-title-letter-spacing: var(--text-base--letter-spacing);
313
+ --type-item-title-weight: var(--font-weight-medium);
314
+
315
+ --type-body-size: var(--text-base);
316
+ --type-body-line-height: var(--text-base--line-height);
317
+ --type-body-letter-spacing: var(--text-base--letter-spacing);
318
+ --type-body-weight: var(--font-weight-normal);
319
+
320
+ --type-supporting-size: var(--text-sm);
321
+ --type-supporting-line-height: var(--text-sm--line-height);
322
+ --type-supporting-letter-spacing: var(--text-sm--letter-spacing);
323
+ --type-supporting-weight: var(--font-weight-normal);
324
+
325
+ --type-action-label-size: var(--text-sm);
326
+ --type-action-label-line-height: var(--text-sm--line-height);
327
+ --type-action-label-letter-spacing: var(--text-sm--letter-spacing);
328
+ --type-action-label-weight: var(--font-weight-medium);
329
+
330
+ /* Cifras: montos, plazos, RUT, fechas — DEC-015 */
331
+ --type-data-size: var(--text-sm);
332
+ --type-data-line-height: var(--text-sm--line-height);
333
+ --type-data-letter-spacing: var(--text-sm--letter-spacing);
334
+ --type-data-weight: var(--font-weight-medium);
335
+
336
+ --type-meta-size: var(--text-xs);
337
+ --type-meta-line-height: var(--text-xs--line-height);
338
+ --type-meta-letter-spacing: var(--text-xs--letter-spacing);
339
+ --type-meta-weight: var(--font-weight-normal);
340
+
341
+ /* ── Movimiento y respuesta — DEC-007.
342
+ La duración responde a la distancia conceptual del cambio: presión,
343
+ estado local, reorganización u overlay. Sin rebotes ni ceremonia. ── */
344
+ --duration-instant: 80ms; /* hover y reconocimiento inmediato */
345
+ --duration-fast: 120ms; /* presión y controles locales */
346
+ --duration-normal: 180ms; /* cambio de estado o reorganización */
347
+ --duration-overlay: 220ms; /* diálogo, sheet y cambio de contexto */
348
+ /* Tramos largos para transiciones amplias de contenido o vista (Material 3
349
+ medium/long). No para controles: un botón nunca dura 300ms — la contención
350
+ de DEC-007 se mantiene reservando estos tramos a cambios de superficie. */
351
+ --duration-emphasized: 300ms; /* M3 medium2 · shared axis / fade through */
352
+ --duration-long: 500ms; /* M3 long2 · cambio de vista completo */
353
+ --ease-standard: cubic-bezier(0.2, 0, 0, 1); /* M3 Standard */
354
+ --ease-enter: cubic-bezier(0, 0, 0, 1); /* M3 Standard decelerate */
355
+ --ease-exit: cubic-bezier(0.3, 0, 1, 1); /* M3 Standard accelerate */
356
+ /* Par "emphasized" de Material 3 — el "sale rápido, aterriza suave" para
357
+ reorganizaciones amplias. Entrada = decelerate; salida = accelerate. Se
358
+ usan solo en transiciones de contenido grandes, nunca en controles. */
359
+ --ease-emphasized-decelerate: cubic-bezier(0.05, 0.7, 0.1, 1); /* M3 Emphasized decelerate */
360
+ --ease-emphasized-accelerate: cubic-bezier(0.3, 0, 0.8, 0.15); /* M3 Emphasized accelerate */
361
+
362
+ /* ── "Fluid" — la firma de movimiento de Lexy (un paso más allá de Material).
363
+ Momentum con voluntad: respuesta inmediata a la presión + cola larga que
364
+ desacelera como algo deslizándose sobre hielo. Perfil de mínimo-jerk, el
365
+ del movimiento humano natural — se siente propio, no mecánico. Springs
366
+ aproximados con linear() (física en CSS, sin JS).
367
+ · glide → sin overshoot; seguro para opacidad y tamaño.
368
+ · slip → overshoot leve ~4% ("casi se resbala"); solo transform, en
369
+ momentos con firma. Nunca en opacidad (se recorta en 1).
370
+ Se usan con moderación: la contención de DEC-007 sigue mandando. */
371
+ --duration-fluid: 380ms;
372
+ --ease-fluid-glide: linear(0, 0.0754 4.2%, 0.2275 8.3%, 0.3908 12.5%, 0.5372 16.7%, 0.6575 20.8%, 0.7513 25%, 0.8222 29.2%, 0.8743 33.3%, 0.912 37.5%, 0.9389 41.7%, 0.9579 45.8%, 0.9711 50%, 0.9803 54.2%, 0.9866 58.3%, 0.9909 62.5%, 0.9939 66.7%, 0.9959 70.8%, 0.9972 75%, 0.9982 79.2%, 0.9988 83.3%, 0.9992 87.5%, 0.9995 91.7%, 0.9996 95.8%, 1);
373
+ --ease-fluid-slip: linear(0, 0.1199 4.2%, 0.3591 8.3%, 0.601 12.5%, 0.7928 16.7%, 0.922 20.8%, 0.9959 25%, 1.0296 29.2%, 1.0384 33.3%, 1.0342 37.5%, 1.0251 41.7%, 1.0157 45.8%, 1.0083 50%, 1.0032 54.2%, 1.0003 58.3%, 0.9989 62.5%, 0.9985 66.7%, 0.9987 70.8%, 0.999 75%, 0.9994 79.2%, 0.9997 83.3%, 0.9999 87.5%, 1 91.7%, 1 95.8%, 1);
374
+
375
+ /* ── Densidad de acción — DEC-008.
376
+ Los botones son compactos sin reducir el área de lectura ni densificar
377
+ formularios completos. La geometría permanece estable durante loading. ── */
378
+ --control-height-sm: 2rem; /* 32px */
379
+ --control-height: 2.25rem; /* 36px */
380
+ --control-height-lg: 2.5rem; /* 40px */
152
381
 
153
382
  /* ── Animaciones (Accordion de Radix) ── */
154
- --animate-accordion-down: accordion-down 0.2s ease-out;
155
- --animate-accordion-up: accordion-up 0.2s ease-out;
156
-
157
- /* ── Spacing semántico de layout ──
158
- Mismos valores que LexyDesign (Fluent 2 / tailwind.config.ts), con naming
159
- Tailwind. Se consumen como gap-gutter, p-section-gap, max-w-container, etc.
160
- La unidad base sigue siendo la escala numérica de Tailwind (múltiplos de
161
- 4px); estos tokens añaden vocabulario intencional para layouts. */
162
- --spacing-stack-sm: 0.5rem; /* 8px · separación entre items pequeños */
163
- --spacing-stack-md: 1rem; /* 16px · separación entre grupos */
164
- --spacing-stack-lg: 2rem; /* 32px · separación entre secciones */
383
+ --animate-accordion-down: accordion-down var(--duration-normal) var(--ease-standard);
384
+ --animate-accordion-up: accordion-up var(--duration-normal) var(--ease-standard);
385
+
386
+ /* ── Jerarquía por proximidad (DEC-012).
387
+ El nombre describe la relación, no el valor. Menor distancia = una misma
388
+ idea; mayor distancia = cambio de grupo, sección o región. La rampa usa
389
+ el grid de 8px y reserva 4px para pares tipográficos inseparables. */
390
+ --spacing-coupled: 0.25rem; /* 4px · título + metadata inmediata */
391
+ --spacing-related: 0.5rem; /* 8px · título + supporting text */
392
+ --spacing-grouped: 1rem; /* 16px · elementos de una misma unidad */
393
+ --spacing-item-gap: 1.5rem; /* 24px · items hermanos sin contenedor */
394
+ --spacing-separated: 2rem; /* 32px · secciones distintas */
395
+ --spacing-region: 3rem; /* 48px · regiones mayores de página */
396
+
397
+ /* Alias históricos: conservan compatibilidad, pero las composiciones nuevas
398
+ deben expresar la relación con coupled/related/grouped/separated/region. */
399
+ --spacing-stack-sm: var(--spacing-related);
400
+ --spacing-stack-md: var(--spacing-grouped);
401
+ --spacing-stack-lg: var(--spacing-separated);
165
402
  --spacing-gutter: 1.5rem; /* 24px · margen interior de columna */
166
- --spacing-section-gap: 2.5rem; /* 40px · separación entre bloques de página */
403
+ --spacing-section-gap: var(--spacing-separated);
167
404
  --spacing-page-bottom: 8rem; /* 128px · padding inferior de página */
168
405
 
169
406
  /* ── Márgenes de contenedor ── */
@@ -181,9 +418,222 @@
181
418
  --breakpoint-lg: 64rem; /* 1024px · umbral columnas master-detail */
182
419
  }
183
420
 
421
+ /* ── Reserva editorial (DEC-015) ──
422
+ Escalones display sin oficio en producto: no generan utilidades text-*.
423
+ Sobreviven como variables para la bitácora y superficies de marca. Si un
424
+ rol los reclama, vuelven al @theme. */
425
+ :root {
426
+ --text-2xl: 1.75rem; /* 28 / 36 · Headline medium */
427
+ --text-2xl--line-height: 2.25rem;
428
+ --text-2xl--letter-spacing: -0.021em;
429
+ --text-4xl: 2.25rem; /* 36 / 44 · Display small */
430
+ --text-4xl--line-height: 2.75rem;
431
+ --text-4xl--letter-spacing: -0.024em;
432
+ --text-5xl: 2.8125rem; /* 45 / 52 · Display medium */
433
+ --text-5xl--line-height: 3.25rem;
434
+ --text-5xl--letter-spacing: -0.028em;
435
+ --text-6xl: 3.5625rem; /* 57 / 64 · Display large */
436
+ --text-6xl--line-height: 4rem;
437
+ --text-6xl--letter-spacing: -0.033em;
438
+ }
439
+
184
440
  @layer utilities {
185
441
  .hide-scrollbar::-webkit-scrollbar { display: none; }
186
442
  .hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
443
+
444
+ .lexy-state-enter {
445
+ animation: lexy-state-enter var(--duration-normal) var(--ease-enter) both;
446
+ }
447
+
448
+ /* ── Patrones de transición Material 3 (Nivel 2) ──
449
+ Recetas reutilizables de choreography, solo CSS. Entrada con
450
+ emphasized-decelerate, salida con emphasized-accelerate (M3). El
451
+ "container transform" se omite a propósito: requiere FLIP/JS, fuera del
452
+ alcance de tokens+CSS. Todas se anulan con prefers-reduced-motion. */
453
+
454
+ /* Fade — cambio simple de opacidad (contenido relacionado). */
455
+ .lexy-fade-in { animation: lexy-fade-in var(--duration-normal) var(--ease-standard) both; }
456
+ .lexy-fade-out { animation: lexy-fade-out var(--duration-fast) var(--ease-exit) both; }
457
+
458
+ /* Fade through — sin relación espacial: saliente se desvanece encogiendo,
459
+ entrante aparece creciendo desde 92% (destinos no jerárquicos). */
460
+ .lexy-fade-through-in { animation: lexy-fade-through-in var(--duration-emphasized) var(--ease-emphasized-decelerate) both; }
461
+ .lexy-fade-through-out { animation: lexy-fade-through-out var(--duration-fast) var(--ease-emphasized-accelerate) both; }
462
+
463
+ /* Shared axis X — relación horizontal (avanzar/retroceder). Reverse invierte
464
+ la dirección para el gesto contrario. */
465
+ .lexy-shared-x-in { animation: lexy-shared-x-in var(--duration-emphasized) var(--ease-emphasized-decelerate) both; }
466
+ .lexy-shared-x-in-reverse { animation: lexy-shared-x-in-reverse var(--duration-emphasized) var(--ease-emphasized-decelerate) both; }
467
+ .lexy-shared-x-out { animation: lexy-shared-x-out var(--duration-fast) var(--ease-emphasized-accelerate) both; }
468
+ .lexy-shared-x-out-reverse { animation: lexy-shared-x-out-reverse var(--duration-fast) var(--ease-emphasized-accelerate) both; }
469
+
470
+ /* Shared axis Y — relación jerárquica vertical (entrar/salir de un nivel). */
471
+ .lexy-shared-y-in { animation: lexy-shared-y-in var(--duration-emphasized) var(--ease-emphasized-decelerate) both; }
472
+ .lexy-shared-y-out { animation: lexy-shared-y-out var(--duration-fast) var(--ease-emphasized-accelerate) both; }
473
+ }
474
+
475
+ /* Roles compuestos: la única API de asignación tipográfica del registry
476
+ (DEC-012 + DEC-015). Evitan reconstruir un rol con text-* + leading-* +
477
+ tracking-* + font-*. Viven en la capa components para que una utilidad
478
+ puntual pueda matizar un rol (font-medium como énfasis, tracking-widest,
479
+ tabular-nums) sin reconstruirlo. */
480
+ @layer components {
481
+ .type-page-title,
482
+ .type-dialog-title,
483
+ .type-subsection-title,
484
+ .type-section-title,
485
+ .type-item-title,
486
+ .type-body,
487
+ .type-supporting,
488
+ .type-action-label,
489
+ .type-data,
490
+ .type-meta {
491
+ font-family: var(--font-sans);
492
+ }
493
+
494
+ .type-page-title {
495
+ font-family: var(--font-display);
496
+ font-size: var(--type-page-title-size);
497
+ line-height: var(--type-page-title-line-height);
498
+ letter-spacing: var(--type-page-title-letter-spacing);
499
+ font-weight: var(--type-page-title-weight);
500
+ }
501
+
502
+ .type-dialog-title {
503
+ font-size: var(--type-dialog-title-size);
504
+ line-height: var(--type-dialog-title-line-height);
505
+ letter-spacing: var(--type-dialog-title-letter-spacing);
506
+ font-weight: var(--type-dialog-title-weight);
507
+ }
508
+
509
+ .type-section-title {
510
+ font-size: var(--type-section-title-size);
511
+ line-height: var(--type-section-title-line-height);
512
+ letter-spacing: var(--type-section-title-letter-spacing);
513
+ font-weight: var(--type-section-title-weight);
514
+ }
515
+
516
+ .type-item-title {
517
+ font-size: var(--type-item-title-size);
518
+ line-height: var(--type-item-title-line-height);
519
+ letter-spacing: var(--type-item-title-letter-spacing);
520
+ font-weight: var(--type-item-title-weight);
521
+ }
522
+
523
+ .type-body {
524
+ font-size: var(--type-body-size);
525
+ line-height: var(--type-body-line-height);
526
+ letter-spacing: var(--type-body-letter-spacing);
527
+ font-weight: var(--type-body-weight);
528
+ }
529
+
530
+ .type-supporting {
531
+ font-size: var(--type-supporting-size);
532
+ line-height: var(--type-supporting-line-height);
533
+ letter-spacing: var(--type-supporting-letter-spacing);
534
+ font-weight: var(--type-supporting-weight);
535
+ }
536
+
537
+ .type-action-label {
538
+ font-size: var(--type-action-label-size);
539
+ line-height: var(--type-action-label-line-height);
540
+ letter-spacing: var(--type-action-label-letter-spacing);
541
+ font-weight: var(--type-action-label-weight);
542
+ }
543
+
544
+ .type-subsection-title {
545
+ font-size: var(--type-subsection-title-size);
546
+ line-height: var(--type-subsection-title-line-height);
547
+ letter-spacing: var(--type-subsection-title-letter-spacing);
548
+ font-weight: var(--type-subsection-title-weight);
549
+ }
550
+
551
+ .type-data {
552
+ font-size: var(--type-data-size);
553
+ line-height: var(--type-data-line-height);
554
+ letter-spacing: var(--type-data-letter-spacing);
555
+ font-weight: var(--type-data-weight);
556
+ font-variant-numeric: tabular-nums;
557
+ }
558
+
559
+ .type-meta {
560
+ font-size: var(--type-meta-size);
561
+ line-height: var(--type-meta-line-height);
562
+ letter-spacing: var(--type-meta-letter-spacing);
563
+ font-weight: var(--type-meta-weight);
564
+ }
565
+ }
566
+
567
+ @media (prefers-reduced-motion: reduce) {
568
+ .lexy-state-enter,
569
+ .lexy-fade-in,
570
+ .lexy-fade-out,
571
+ .lexy-fade-through-in,
572
+ .lexy-fade-through-out,
573
+ .lexy-shared-x-in,
574
+ .lexy-shared-x-in-reverse,
575
+ .lexy-shared-x-out,
576
+ .lexy-shared-x-out-reverse,
577
+ .lexy-shared-y-in,
578
+ .lexy-shared-y-out {
579
+ animation: none;
580
+ }
581
+ }
582
+
583
+ @keyframes lexy-state-enter {
584
+ from {
585
+ opacity: 0;
586
+ transform: translateY(2px) scale(0.99);
587
+ }
588
+ to {
589
+ opacity: 1;
590
+ transform: translateY(0) scale(1);
591
+ }
592
+ }
593
+
594
+ /* ── Keyframes de los patrones Material 3 (Nivel 2) ── */
595
+ @keyframes lexy-fade-in {
596
+ from { opacity: 0; }
597
+ to { opacity: 1; }
598
+ }
599
+ @keyframes lexy-fade-out {
600
+ from { opacity: 1; }
601
+ to { opacity: 0; }
602
+ }
603
+
604
+ @keyframes lexy-fade-through-in {
605
+ from { opacity: 0; transform: scale(0.92); }
606
+ to { opacity: 1; transform: scale(1); }
607
+ }
608
+ @keyframes lexy-fade-through-out {
609
+ from { opacity: 1; transform: scale(1); }
610
+ to { opacity: 0; transform: scale(0.92); }
611
+ }
612
+
613
+ @keyframes lexy-shared-x-in {
614
+ from { opacity: 0; transform: translateX(30px); }
615
+ to { opacity: 1; transform: translateX(0); }
616
+ }
617
+ @keyframes lexy-shared-x-in-reverse {
618
+ from { opacity: 0; transform: translateX(-30px); }
619
+ to { opacity: 1; transform: translateX(0); }
620
+ }
621
+ @keyframes lexy-shared-x-out {
622
+ from { opacity: 1; transform: translateX(0); }
623
+ to { opacity: 0; transform: translateX(-30px); }
624
+ }
625
+ @keyframes lexy-shared-x-out-reverse {
626
+ from { opacity: 1; transform: translateX(0); }
627
+ to { opacity: 0; transform: translateX(30px); }
628
+ }
629
+
630
+ @keyframes lexy-shared-y-in {
631
+ from { opacity: 0; transform: translateY(30px); }
632
+ to { opacity: 1; transform: translateY(0); }
633
+ }
634
+ @keyframes lexy-shared-y-out {
635
+ from { opacity: 1; transform: translateY(0); }
636
+ to { opacity: 0; transform: translateY(-30px); }
187
637
  }
188
638
 
189
639
  @keyframes accordion-down {
@@ -200,22 +650,22 @@
200
650
  el entrypoint CSS porque debe ir antes de @import "tailwindcss". */
201
651
  @layer base {
202
652
  :root {
203
- --sidebar-background: 210 40% 98%;
204
- --sidebar-foreground: 0 0% 14%;
653
+ --sidebar-background: 240 7% 97%;
654
+ --sidebar-foreground: 225 6% 13%;
205
655
  --sidebar-primary: 239 62% 55%;
206
656
  --sidebar-primary-foreground: 0 0% 100%;
207
- --sidebar-accent: 239 63% 96%;
657
+ --sidebar-accent: 239 63% 94%;
208
658
  --sidebar-accent-foreground: 239 62% 55%;
209
- --sidebar-border: 0 0% 82%;
659
+ --sidebar-border: 240 9% 93%;
210
660
  --sidebar-ring: 239 62% 55%;
211
661
  }
212
662
 
213
663
  html {
214
664
  font-family: var(--font-sans);
215
665
  font-weight: var(--font-weight-normal);
216
- /* Noto Sans tiene mayor avance horizontal; un tracking negativo sutil
217
- compacta su densidad y la acerca al ritmo de Segoe UI. */
218
- letter-spacing: -0.007em;
666
+ /* Cuerpo con el tracking sutil de Linear (−0.05px a 16px). Los titulares
667
+ reciben su rampa negativa vía --text-*--letter-spacing. */
668
+ letter-spacing: -0.003em;
219
669
  -webkit-font-smoothing: antialiased;
220
670
  -moz-osx-font-smoothing: grayscale;
221
671
  }