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>
89 lines
2.3 KiB
CSS
89 lines
2.3 KiB
CSS
@tailwind base;
|
|
@tailwind components;
|
|
@tailwind utilities;
|
|
|
|
/* Los colores viven acá una sola vez, en claro y oscuro. Antes cada elemento
|
|
repetía el par (bg-white dark:bg-gray-900, border-gray-200 dark:border-...)
|
|
a mano en cientos de lugares; cambiar un tono era buscar y reemplazar. */
|
|
@layer base {
|
|
:root {
|
|
--superficie: 255 255 255;
|
|
--elevado: 249 250 251;
|
|
--borde: 229 231 235;
|
|
--texto: 31 41 55;
|
|
--tenue: 107 114 128;
|
|
--fondo: 249 250 251;
|
|
}
|
|
|
|
.dark {
|
|
--superficie: 17 24 39;
|
|
--elevado: 24 33 51;
|
|
--borde: 42 52 70;
|
|
--texto: 229 231 235;
|
|
--tenue: 148 163 184;
|
|
--fondo: 9 13 22;
|
|
}
|
|
|
|
body {
|
|
background: rgb(var(--fondo));
|
|
color: rgb(var(--texto));
|
|
-webkit-font-smoothing: antialiased;
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
.card {
|
|
@apply bg-superficie border border-borde rounded-xl;
|
|
}
|
|
|
|
.input {
|
|
@apply w-full bg-superficie border border-borde text-texto rounded-lg px-3 py-2 text-sm
|
|
placeholder:text-tenue/60 outline-none transition-colors
|
|
focus:border-brand focus:ring-2 focus:ring-brand/20;
|
|
}
|
|
|
|
.label {
|
|
@apply block text-xs font-medium text-tenue mb-1;
|
|
}
|
|
|
|
.btn {
|
|
@apply inline-flex items-center justify-center gap-1.5 rounded-lg px-4 py-2 text-sm font-medium
|
|
transition-colors disabled:opacity-50 disabled:cursor-not-allowed;
|
|
}
|
|
.btn-primary {
|
|
@apply btn bg-brand text-white hover:bg-brand-dark;
|
|
}
|
|
.btn-ghost {
|
|
@apply btn text-tenue hover:text-texto hover:bg-elevado;
|
|
}
|
|
.btn-peligro {
|
|
@apply btn text-red-600 hover:bg-red-50 dark:hover:bg-red-950/40;
|
|
}
|
|
|
|
.badge {
|
|
@apply inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium;
|
|
}
|
|
.badge-ok {
|
|
@apply badge bg-green-100 text-green-700 dark:bg-green-500/15 dark:text-green-400;
|
|
}
|
|
.badge-alerta {
|
|
@apply badge bg-amber-100 text-amber-700 dark:bg-amber-500/15 dark:text-amber-400;
|
|
}
|
|
.badge-error {
|
|
@apply badge bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-400;
|
|
}
|
|
.badge-neutro {
|
|
@apply badge bg-elevado text-tenue;
|
|
}
|
|
|
|
.tab {
|
|
@apply px-3 py-1.5 rounded-full text-sm transition-colors whitespace-nowrap;
|
|
}
|
|
.tab-activo {
|
|
@apply tab bg-brand text-white;
|
|
}
|
|
.tab-inactivo {
|
|
@apply tab text-tenue hover:text-texto hover:bg-elevado;
|
|
}
|
|
}
|