From daac8b2e5483551baed50e47e21d8bb62e141cb1 Mon Sep 17 00:00:00 2001
From: dev
Date: Thu, 4 Jun 2026 20:49:01 +0200
Subject: [PATCH] feat(temas/color): subtle intent harmonization (slider,
default 12%)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Canonical intents (red/green/...) can clash next to a brand color. Replace the
harmonize on/off toggle with a slider (0 = pure canonical -> 0.35 strong), default
a SUBTLE 12%: intents lean toward the brand enough to feel cohesive but stay
recognizable (red is still red). Verified: green seed -> threat #e35013 at 12%
(warmer red), pure #e5484d at 0. Also clarified that "La paleta" is the FIXED
library (does not derive from the seed; the seed derives the roles) to resolve the
recurring confusion. RFC §6.2 notes the subtle-default guidance.
Co-Authored-By: Claude Opus 4.8 (1M context)
---
src/uix/eidos/COLOR_ENGINE_RFC.md | 5 ++++-
web/routes/temas/color/+page.svelte | 25 ++++++++++++++++++-------
2 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/src/uix/eidos/COLOR_ENGINE_RFC.md b/src/uix/eidos/COLOR_ENGINE_RFC.md
index 8a598d04f..60b809483 100644
--- a/src/uix/eidos/COLOR_ENGINE_RFC.md
+++ b/src/uix/eidos/COLOR_ENGINE_RFC.md
@@ -326,7 +326,10 @@ expone con un input de color por fila + «auto» para volver a derivado.
**Los 6 intents NO se derivan** — son hues canónicos del libro (un error es rojo
siempre). `harmonize(color, toward, amount)` (M3 `blend.harmonize`) los empuja hacia
-la marca un % si el builder quiere cohesión — opt-in, conserva L y C.
+la marca un % si el builder quiere cohesión — opt-in, conserva L y C. Un valor
+**sutil (~10-15%)** hace que los intents se sientan de la familia **sin perder su
+lectura** (rojo sigue rojo); el builder de `/temas/color` lo usa como default (slider
+0 = canónico puro → fuerte). Resuelve el "los intents puros chirrían con la marca".
**Caveat del +60°**: la rotación de Material puede caer cerca de un intent según el
primary (p. ej. `purple + 60° = H6 ≈ red/threat`). Por eso el tema base afinó su
diff --git a/web/routes/temas/color/+page.svelte b/web/routes/temas/color/+page.svelte
index 51884eb03..7990887e6 100644
--- a/web/routes/temas/color/+page.svelte
+++ b/web/routes/temas/color/+page.svelte
@@ -118,7 +118,9 @@
let seedHex = $state('#8e4ec6')
let builderVariant = $state('tonal')
- let harmonizeIntents = $state(false)
+ // Subtle by default: intents lean toward the brand enough to feel cohesive but
+ // stay recognizable (red is still red). 0 = pure canonical. (M3 harmonize.)
+ let harmonizeAmount = $state(0.12)
// Per-role overrides the designer pinned (role → hex). Empty = fully derived.
let overrides = $state>({})
@@ -184,11 +186,12 @@
for (const { role, seed } of schemeSeeds) {
if (role !== 'neutralVariant') emitRole(parts, role, seed, bg)
}
- if (harmonizeIntents) {
+ if (harmonizeAmount > 0) {
for (const intent of INTENTS) {
if (intent === 'neutral') continue
const baseHex = activeScales[CANONICAL_INTENT_SCALES[intent]]?.['9']
- if (baseHex) emitRole(parts, intent, harmonize(parseColor(baseHex), seedOklch, 0.22), bg)
+ if (baseHex)
+ emitRole(parts, intent, harmonize(parseColor(baseHex), seedOklch, harmonizeAmount), bg)
}
}
return parts.join(';')
@@ -252,8 +255,9 @@
con su pick on-solid (APCA), y aplica el tema a TODA la página en vivo
(override de --primitive-{'{role}'}-* en .root → reproyecta toda
la jerarquía + el chrome neutral; en una app real sería setCssVariables). La
- librería de 31 escalas y los 6 intents canónicos NO cambian — salvo que actives
- harmonize intents (los empuja hacia la temperatura del seed). Y puedes
+ librería de 31 escalas NO cambia. Los 6 intents se armonizan suavemente
+ hacia la marca (slider; 0 = canónico puro) para que no se sientan desentonados, sin perder su
+ lectura — rojo sigue siendo rojo. Y puedes
fijar cualquier rol con su propio color (el input de cada fila); los demás
se siguen derivando del seed.
@@ -276,8 +280,9 @@
{/each}
@@ -332,7 +337,9 @@
Escalas funcionales (1-2 fondos · 3-5 componente · 6-8 bordes · 9 sólido ·
10 hover · 11-12 texto). El representativo de cada escala es el
paso 9. La paleta la trae el tema; el framework envía estas 31 (valores
- Radix exactos, listos para autoría OKLCH).
+ Radix exactos, listos para autoría OKLCH). Es la librería fija de
+ referencia — el seed del builder NO la cambia: deriva los roles (arriba),
+ que son escalas generadas nuevas, no miembros de esta lista.