Files
soft_usite/orchestrator/tailwind.config.js
T
Lizandro GuarnizoandClaude Sonnet 5 d8f9acd1f8 feat(studio): rediseño con design tokens, pantalla de consumo y rename a Studio
El SPA pasa a llamarse uMind Studio y vive en /studio (el nombre
"Orquestador" no le decía nada al cliente final, que ahora es quien lo usa).

Diseño:
- Los colores viven una sola vez como variables CSS + clases semánticas
  (.card, .input, .btn-*, .badge-*). Antes cada elemento repetía el par
  claro/oscuro a mano en cientos de lugares y cambiar un tono era buscar
  y reemplazar.
- darkMode pasa de 'media' a 'class' con toggle propio persistido: el
  usuario elige, no el sistema operativo. Se aplica antes de montar la
  app para que no parpadee.
- Componentes compartidos (UiModal, UiBadge, UiEmptyState) donde antes
  había markup duplicado inline.

Nueva pantalla de consumo (/tenants/:id/uso): filtros por fecha con
atajos, total del período, pendiente de facturar, barra contra el tope
del plan, desglose por tipo y gráfico por día. El gráfico son divs con
altura porcentual — no vale traer una librería de charts para esto.

Rename:
- /studio y /portal/studio; /orchestrator redirige 301 conservando la
  ruta interna, así los enlaces guardados siguen funcionando. Los assets
  del bundle quedan exentos (el `base` de Vite sigue en /orchestrator/):
  redirigirlos rompería el SPA.
- El submódulo sembrado migra el mismo registro buscando por las tres
  URLs históricas (/app/umind → /orchestrator → /studio) en vez de
  dejar entradas duplicadas en el menú.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 12:02:54 -05:00

44 lines
1.4 KiB
JavaScript

export default {
content: ['./index.html', './src/**/*.{vue,js}'],
// 'class' (y no 'media') para que el toggle del header pueda ganarle al
// sistema operativo. La clase la pone lib/tema.js antes de montar la app.
darkMode: 'class',
theme: {
extend: {
colors: {
// Mismo verde de marca que ya usa el widget embebible de uMind.
brand: {
DEFAULT: '#8eb02f',
dark: '#719026',
light: '#a8c94f',
},
// Superficies y texto salen de variables CSS (ver style.css) para no
// repetir el par claro/oscuro en cada elemento.
superficie: 'rgb(var(--superficie) / <alpha-value>)',
elevado: 'rgb(var(--elevado) / <alpha-value>)',
borde: 'rgb(var(--borde) / <alpha-value>)',
texto: 'rgb(var(--texto) / <alpha-value>)',
tenue: 'rgb(var(--tenue) / <alpha-value>)',
},
fontFamily: {
sans: ['Inter', 'system-ui', '-apple-system', 'Segoe UI', 'sans-serif'],
},
keyframes: {
aparecer: {
'0%': { opacity: '0', transform: 'translateY(4px)' },
'100%': { opacity: '1', transform: 'translateY(0)' },
},
escalar: {
'0%': { opacity: '0', transform: 'scale(.97)' },
'100%': { opacity: '1', transform: 'scale(1)' },
},
},
animation: {
aparecer: 'aparecer .2s ease-out',
escalar: 'escalar .15s ease-out',
},
},
},
plugins: [],
}