diff --git a/web/routes/temas/+page.svelte b/web/routes/temas/+page.svelte
index de5f3cbc4..07bb33c01 100644
--- a/web/routes/temas/+page.svelte
+++ b/web/routes/temas/+page.svelte
@@ -1,12 +1,12 @@
diff --git a/web/routes/temas/_lib/untitled-ui.ts b/web/routes/temas/_lib/grafito.ts
similarity index 80%
rename from web/routes/temas/_lib/untitled-ui.ts
rename to web/routes/temas/_lib/grafito.ts
index 648738ad1..8f6268f96 100644
--- a/web/routes/temas/_lib/untitled-ui.ts
+++ b/web/routes/temas/_lib/grafito.ts
@@ -1,5 +1,5 @@
/**
- * Untitled UI — tema para activeUIX / Eidos.
+ * Grafito — tema para activeUIX / Eidos (paleta derivada de Untitled UI, variada).
*
* Reproduce el lenguaje visual de https://www.untitledui.com con el
* sistema de theming canónico de Eidos: NO inventa variants ni roles
@@ -31,7 +31,11 @@
* escalas no coincide con los roles, y el validador de Eidos lo
* rechazaría.)
*/
-import { createThemeBaseEidosConfig } from '$uix/eidos/lib/themes/base'
+import {
+ createThemeBaseEidosConfig,
+ THEME_BASE_LIGHT_COLOR_SCALES,
+ THEME_BASE_DARK_COLOR_SCALES
+} from '$uix/eidos/lib/themes/base'
import type { ColorScale, ColorRoleMap, EidosConfig } from '$uix/eidos/lib/config-types'
const s = (
@@ -65,6 +69,10 @@ const s = (
// ── Escalas — modo claro ──────────────────────────────────────────────
// prettier-ignore
const LIGHT = {
+ // Hereda la paleta base del framework (31 escalas Radix). Grafito sobreescribe
+ // abajo las escalas de marca (carbon, gray, violet, blue + intents UUI-tuned) y
+ // hereda las demás → ~32 escalas en la paleta del tema.
+ ...THEME_BASE_LIGHT_COLOR_SCALES,
// Carbon — grafito casi negro. Primario monocromo (Vercel / Linear style).
// 9 = sólido oscuro del botón; con slots.contrast='1' el texto (step 1)
// queda casi blanco. En dark la escala se invierte y todo encaja solo.
@@ -95,6 +103,8 @@ const LIGHT = {
// 10 = `-500` (más claro para hover sobre oscuro).
// prettier-ignore
const DARK = {
+ ...THEME_BASE_DARK_COLOR_SCALES,
+ // ── Escalas de marca Grafito (dark) ──
// Carbon invertido: 1 = casi negro, 9 = botón claro, contrast(1) = oscuro.
carbon: s('#0b0c0e','#131418','#1b1c20','#232428','#2c2d32','#3a3b41','#565760','#7c7d86','#f4f4f6','#ffffff','#cdced4','#fbfbfc'),
gray: s('#0c111d','#101828','#1d2939','#243144','#2c3a4f','#344054','#475467','#5d6b7e','#667085','#98a2b3','#ced5de','#f5f6f8'),
@@ -109,18 +119,17 @@ const DARK = {
// ── Mapeo role → escala (los 9 roles canónicos de Eidos) ──────────────
const ROLES: ColorRoleMap = {
- // Carbon monocromo. `slots.contrast: '1'` hace que el texto sobre el
- // sólido sea el step 1 — casi blanco en claro, casi negro en oscuro —
- // invirtiéndose solo con el modo (el step 9 también se invierte).
+ // Solo la JERARQUÍA se mapea explícitamente (decisión de marca). Carbon
+ // monocromo: `slots.contrast: '1'` hace que el texto sobre el sólido sea el
+ // step 1 — casi blanco en claro, casi negro en oscuro — invirtiéndose con el
+ // modo (el step 9 también se invierte).
primary: { scale: 'carbon', slots: { contrast: '1' } },
secondary: 'violet',
- tertiary: 'blue',
- neutral: 'gray',
- affirm: 'teal',
- fulfill: 'green',
- risk: 'amber',
- threat: 'red',
- loss: 'plum'
+ tertiary: 'blue'
+ // Los 6 intents (neutral + affirm/fulfill/risk/threat/loss) NO se cablean:
+ // auto-derivan de la paleta por la convención del libro
+ // (gray/teal/green/amber/red/plum — todas presentes arriba), identidad = step 9.
+ // Un tema puede overridear un intent mapeándolo explícitamente.
}
// ── Superficies / contenido / bordes / focus ──────────────────────────
@@ -253,19 +262,19 @@ const base = createThemeBaseEidosConfig({
})
/**
- * Config completo del tema Untitled UI. Se pasa a
- * `ActiveEidos.create({ config: untitledUiConfig, theme: 'untitled-ui' })`.
+ * Config completo del tema Grafito. Se pasa a
+ * `ActiveEidos.create({ config: grafitoConfig, theme: 'grafito' })`.
*/
-export const untitledUiConfig: EidosConfig = {
+export const grafitoConfig: EidosConfig = {
primitives: base.primitives,
recipes: base.recipes,
semantics: { color: { roles: ROLES } },
themes: {
- 'untitled-ui-light': {
+ 'grafito-light': {
color: { scales: LIGHT, ...LIGHT_SEMANTICS },
shadow: LIGHT_SHADOW
},
- 'untitled-ui-dark': {
+ 'grafito-dark': {
color: { scales: DARK, ...DARK_SEMANTICS },
shadow: DARK_SHADOW
}
@@ -281,30 +290,35 @@ export interface ThemeRoleInfo {
readonly note: string
}
-/** Los 9 roles canónicos, con la escala Untitled UI a la que mapean. */
-export const THEME_ROLES: readonly ThemeRoleInfo[] = [
+/** Roles de JERARQUÍA — alias explícito a una escala de la paleta (marca). Los
+ * intents NO van aquí: auto-derivan de la paleta por convención (ver THEME_INTENTS). */
+export const THEME_HIERARCHY: readonly ThemeRoleInfo[] = [
{ role: 'primary', scale: 'carbon', label: 'Primary', note: 'Carbón · grafito #1F2024' },
- { role: 'secondary', scale: 'violet', label: 'Secondary', note: 'Brand UUI · violeta #7F56D9' },
- { role: 'tertiary', scale: 'blue', label: 'Tertiary', note: 'Acento · azul #1570EF' },
- { role: 'neutral', scale: 'gray', label: 'Neutral', note: 'Gris frío Untitled UI' },
- { role: 'affirm', scale: 'teal', label: 'Affirm', note: 'Positivo ligero · teal' },
- { role: 'fulfill', scale: 'green', label: 'Fulfill', note: 'Éxito / completado · verde' },
- { role: 'risk', scale: 'amber', label: 'Risk', note: 'Aviso · warning #DC6803' },
- { role: 'threat', scale: 'red', label: 'Threat', note: 'Error / peligro · #D92D20' },
- { role: 'loss', scale: 'plum', label: 'Loss', note: 'Pérdida grave · violeta sombrío' }
+ { role: 'secondary', scale: 'violet', label: 'Secondary', note: 'Violeta de marca #7F56D9' },
+ { role: 'tertiary', scale: 'blue', label: 'Tertiary', note: 'Azul acento #1570EF' }
]
-/** Escalas físicas del theme, en orden de presentación. */
-export const THEME_SCALES: readonly { name: string; label: string }[] = [
- { name: 'carbon', label: 'Carbon' },
- { name: 'violet', label: 'Violet · brand' },
- { name: 'blue', label: 'Blue' },
- { name: 'gray', label: 'Gray' },
- { name: 'teal', label: 'Teal' },
- { name: 'green', label: 'Success' },
- { name: 'amber', label: 'Warning' },
- { name: 'red', label: 'Error' },
- { name: 'plum', label: 'Plum · grave' }
+/**
+ * La paleta COMPLETA del tema (~32 escalas), derivada de las claves de `LIGHT`
+ * para no desincronizarse. Etiquetada por NOMBRE DE COLOR — nunca por intent
+ * (los intents son una capa semántica encima; ver THEME_INTENTS).
+ */
+export const THEME_SCALES: readonly { name: string; label: string }[] = Object.keys(LIGHT)
+ .sort()
+ .map((name) => ({ name, label: name }))
+
+/**
+ * Los 6 intents y la escala de la paleta de la que **auto-derivan** (convención
+ * del libro). El tema NO los cablea — el engine los rellena por nombre,
+ * identidad = step 9. Esto son solo metadatos para documentar el mapeo en el demo.
+ */
+export const THEME_INTENTS: readonly { role: string; label: string; scale: string; note: string }[] = [
+ { role: 'neutral', label: 'Neutral', scale: 'gray', note: 'Sin valencia · gris de trabajo' },
+ { role: 'affirm', label: 'Affirm', scale: 'teal', note: 'Positivo ligero · teal' },
+ { role: 'fulfill', label: 'Fulfill', scale: 'green', note: 'Éxito / completado · verde' },
+ { role: 'risk', label: 'Risk', scale: 'amber', note: 'Aviso · ámbar' },
+ { role: 'threat', label: 'Threat', scale: 'red', note: 'Error / peligro · rojo' },
+ { role: 'loss', label: 'Loss', scale: 'plum', note: 'Pérdida grave · violeta sombrío' }
]
export const COLOR_STEPS = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] as const
diff --git a/web/routes/temas/untitled-ui/+layout.ts b/web/routes/temas/grafito/+layout.ts
similarity index 100%
rename from web/routes/temas/untitled-ui/+layout.ts
rename to web/routes/temas/grafito/+layout.ts
diff --git a/web/routes/temas/untitled-ui/+layout@.svelte b/web/routes/temas/grafito/+layout@.svelte
similarity index 84%
rename from web/routes/temas/untitled-ui/+layout@.svelte
rename to web/routes/temas/grafito/+layout@.svelte
index b56893b62..cbb1af7e9 100644
--- a/web/routes/temas/untitled-ui/+layout@.svelte
+++ b/web/routes/temas/grafito/+layout@.svelte
@@ -1,6 +1,6 @@
+
+{#snippet plusIcon()}
+
+{/snippet}
+
+{#snippet arrowIcon()}
+
+{/snippet}
+
+
+
+ Tema para activeUIX sobre el sistema de theming de Eidos. Primario carbón
+ monocromo, tipografía Inter, paleta derivada de Untitled UI (31 escalas), radios de 8px,
+ sombras en capas. Los 3 roles de jerarquía aliasan la paleta; los 6 intents auto-derivan por
+ la convención del libro — sin inventar variants ni roles nuevos.
+ Grafito
+
Fundamentos
+ + ++ Tres capas: la Paleta (escalas, directamente usables) → los + Roles de jerarquía la aliasan → los Intents auto-derivan + de la paleta por la convención del libro (identidad = step 9). Los componentes pueden + override su color a cualquier escala. Los 9 roles son canon fijo; el tema solo trae la + paleta y mapea la jerarquía. +
+Paleta · escalas de 12 pasos
+Cada paso es directamente usable — p. ej. var(--scale-teal-10).
{hex[`${sc.name}-9`] ?? `--scale-${sc.name}-9`}
+ Roles de jerarquía · alias explícito a una escala
+{h.scale}
+ Intents · auto-derivados de la paleta (convención del libro)
+{it.scale}
+ Superficies, contenido y bordes
+default
+ raised
+ muted
+ primary
+ secondary
+ strong
+ Inter para display y texto. Named styles del sistema (hero → caption + code).
+--style-{t.key}
+ Primitivas estables del tema. La escala base es de 4px; controles a 8px de radio.
+Spacing
+ {#each SPACE as k} +--space-{k}
+
+ Radius
+Sizes · control-height
+ {#each SIZES as k} +var(--size-{k}-control-height)
+ Shadows
+Dos ejes ortogonales que se multiplican. Cámbialos en la barra superior y mira cómo reaccionan estas métricas y el specimen en vivo.
+Densidad · {axis.density}
+Ritmo de layout (espacio) + altura de control. La tipografía NO cambia con la densidad.
+--space-4{axis.space4 || '—'}--control-height-md{axis.ctrlMd || '—'}Scaling · {axis.scaling}%
+Zoom global (paridad Radix) — escala TODO proporcionalmente, incluida la tipografía. No toca radio, borde ni sombra.
+--font-size-md{axis.fontMd || '—'}--space-4 × scaling{axis.space4 || '—'}Specimen en vivo
++ Texto de cuerpo: escala con scaling, estable bajo densidad. +
+Componentes
+ + + + + +Pills de estado en los 4 chip-variants y la paleta completa de roles.
+Colores (soft)
+Variants
+Field, Select, Checkbox, Radio, Switch y Slider con el aspecto del tema.
+Selección
+ + + +Switch & Slider
+ + + +Banners por intent, progreso, avatares y tarjetas.
+Progress
+ +Avatares
+Variantes line y pills. Indicador animado, foco con anillo carbón, activo en color primario.
+Line
+Pills
+Accordion (outline) — apertura única, chevron y foco coherentes con el tema.
+ActiveEidos.create({ config }): se remapean los 9 roles a paletas
+ y se ajustan primitivas estables (tipografía, radio, sombra).
+ contrast.
+ Toggle suelto y toggle-group (segmentado, single + multiple). Activo en color primario.
+Toggle
+Toggle group · segmentado
+Barra de herramientas con botones, separador y grupo segmentado.
+Popover y dialog — paneles portaleados con la superficie, borde y sombra del tema.
+Sistema
+ + +
+ La capa perceptual está activa: cada interacción emite una señal con familia + intent que se
+ materializa en sonido (earcon), haptic (Vibration API) y una
+ reacción visual data-event-* teñida por el intent del tema.
+ Pulsa los botones — en un navegador con gesto de usuario sonarán.
+
Intents perceptuales
+
+ El motor (EngineSemantic) se cablea en el layout vía
+ createActiveUix({ events: { sound, haptic, components } }) con
+ los packs sema por componente. Sonido y haptic son opt-in; aquí están encendidos.
+
- Tema para activeUIX sobre el sistema de theming de Eidos. Primario carbón - monocromo, tipografía Inter, grises fríos, radios de 8px, sombras en capas y anillos de foco - suaves — los 9 roles canónicos retintados, sin inventar variants ni roles nuevos. -
-Los 9 roles canónicos mapeados a las paletas de Untitled UI. El theme retinta; los roles son canon fijo del framework.
-Roles semánticos
-Escalas físicas · 12 pasos
- {#each THEME_SCALES as sc} -{hex[`${sc.name}-9`] ?? `--scale-${sc.name}-9`}
- Superficies, contenido y bordes
-default
- raised
- muted
- primary
- secondary
- strong
- Inter para display y texto. Named styles del sistema (hero → caption + code).
---style-{t.key}
- Primitivas estables del tema. La escala base es de 4px; controles a 8px de radio.
-Spacing
- {#each SPACE as k} ---space-{k}
-
- Radius
-Sizes · control-height
- {#each SIZES as k} -var(--size-{k}-control-height)
- Shadows
-6 variants · 9 roles · 5 tamaños · estados. El primario es carbón; el texto sobre sólidos de color resuelve a blanco.
-Variants
-Roles e intents
-Tamaños
-Con icono y estados
-Pills de estado en los 4 chip-variants y la paleta completa de roles.
-Colores (soft)
-Variants
-Field, Select, Checkbox, Radio, Switch y Slider con el aspecto del tema.
-Selección
- - - -Switch & Slider
- - - -Banners por intent, progreso, avatares y tarjetas.
-Progress
- -Avatares
-Variantes line y pills. Indicador animado, foco con anillo carbón, activo en color primario.
-Line
-Pills
-Accordion (outline) — apertura única, chevron y foco coherentes con el tema.
-ActiveEidos.create({ config }): se remapean los 9 roles a paletas
- y se ajustan primitivas estables (tipografía, radio, sombra).
- contrast.
- Toggle suelto y toggle-group (segmentado, single + multiple). Activo en color primario.
-Toggle
-Toggle group · segmentado
-Barra de herramientas con botones, separador y grupo segmentado.
-Popover y dialog — paneles portaleados con la superficie, borde y sombra del tema.
-Dropdown, menubar, context menu y tooltip — todos portaleados, con la sombra del tema.
-Menubar
-
- La capa perceptual está activa: cada interacción emite una señal con familia + intent que se
- materializa en sonido (earcon), haptic (Vibration API) y una
- reacción visual data-event-* teñida por el intent del tema.
- Pulsa los botones — en un navegador con gesto de usuario sonarán.
-
Intents perceptuales
-
- El motor (EngineSemantic) se cablea en el layout vía
- createActiveUix({ events: { sound, haptic, components } }) con
- los packs sema por componente. Sonido y haptic son opt-in; aquí están encendidos.
-