# REFACTORIZACIÓN_PLAN.md
**Proyecto:** lostalo.sgecr  
**Fase:** 1 y 2 — Análisis completo + Plan  
**Fecha:** 2026-04-09  
**Estado:** LISTO PARA REVISIÓN antes de aplicar cambios

---

## 1. RESUMEN EJECUTIVO

| Métrica | Valor |
|---|---|
| Archivos CSS (proyecto) | 26 propios + 2 vendor |
| Archivos JS (proyecto) | 10 propios + 4 vendor |
| Selectores JS protegidos identificados | 31 |
| Bloques CSS duplicados detectados | ~15 archivos repiten el mismo `:root`, `body`, `main`, `.container_report` |
| Build pipeline / SCSS | ❌ No existe — CSS puro únicamente |
| @imports entre CSS propios | ❌ Ninguno — cada página carga su CSS en `<link>` |
| nav.php CSS | Inline `<style>` — completamente autónomo |

---

## 2. ANÁLISIS DE DESIGN REFERENCE

### 2.1 Paleta de colores exacta (extraída de imágenes)

| Token | Hex | Uso |
|---|---|---|
| `--clr-primary` | `#2B4EC8` | Underline tab activo, título de página, borde activo nav |
| `--clr-accent-link` | `#3F7CDB` | Labels de encabezados de tabla, texto de links en filas |
| `--clr-badge-pending-bg` | `#FFF8E1` | Badge "Pendiente" — fondo |
| `--clr-badge-pending-text` | `#D97706` | Badge "Pendiente" — texto |
| `--clr-header-top` | `#0F1B4C` | Barra superior (imagen 2 — banda azul oscuro) |
| `--clr-page-bg` | `#FFFFFF` | Fondo del contenido principal |
| `--clr-body-bg` | `#F5F6FA` | Background general de página |
| `--clr-text-primary` | `#111827` | Texto principal, títulos |
| `--clr-text-muted` | `#6B7280` | Texto secundario, breadcrumb |
| `--clr-border-row` | `#E5E7EB` | Separadores de filas (dashed) |
| `--clr-delete` | `#EF4444` | Ícono eliminar |
| `--clr-tab-inactive` | `#6B7280` | Tab no activo |

### 2.2 Tipografía

| Elemento | Tamaño | Peso | Color |
|---|---|---|---|
| H1 página | `28–34px` | `700–800` | `#111827` |
| H2 sección | `20px` | `700` | `#111827` |
| Breadcrumb | `13px` | `400` | `#6B7280` |
| Tab activo | `14px` | `700` | `#111827` |
| Tab inactivo | `14px` | `400` | `#6B7280` |
| `th` tabla | `12px` | `500` | `#3F7CDB` |
| `td` tabla | `13–14px` | `400` | `#1F2937` |
| Badge | `11–12px` | `500` | según estado |

### 2.3 Espaciado y forma

- **Botones:** `border-radius: 9999px`, outline style, borde `1.5px`
- **Cards/contenedores:** `border-radius: 8px`, `box-shadow: 0 1px 3px rgba(0,0,0,.08)`
- **Separadores de fila:** `border-bottom: 1px dashed #E5E7EB` (no sólido)
- **Padding de celdas:** `td { padding: 14px 8px }`
- **Tab underline activo:** `border-bottom: 2.5px solid #2B4EC8`
- **Input/select:** `border-radius: 8px`, borde `1px solid #D1D5DB`

---

## 3. SELECTORES PROTEGIDOS (NO RENOMBRAR)

### 3.1 IDs usados por JS — INTOCABLES

```
#usersTable          → usuarios.js: XLSX.utils.table_to_book(), html2canvas()
#addModal            → usuarios.js, oficinas_admin.js: style.display
#editModal           → usuarios.js, oficinas_admin.js: style.display
#addForm             → usuarios.js, oficinas_admin.js: addEventListener('submit')
#editForm            → usuarios.js, oficinas_admin.js: addEventListener('submit')
#typeSelect          → usuarios.js: addEventListener('change')
#group_id_emp        → usuarios.js: style.display
#group_id_externo    → usuarios.js: style.display
#group_edit_id_emp   → usuarios.js: style.display
#group_edit_id_externo → usuarios.js: style.display
#id_emp              → usuarios.js: getElementById
#edit_id_emp         → usuarios.js: getElementById
#id_externo          → usuarios.js: getElementById
#edit_id_externo     → usuarios.js: getElementById
#pageInfo            → usuarios.js: textContent
#prevPage            → usuarios.js: disabled
#nextPage            → usuarios.js: disabled
#tempPassMsg         → usuarios.js: textContent
#bajaForm            → baja.js: getElementById
#btnGuardar          → baja.js: disabled
#mensajeError        → baja.js: textContent
#tablaBajas          → baja.js: querySelector
#tablaPendientes     → solicitudesBajas.js: querySelector
#btnBuscarPend       → solicitudesBajas.js: addEventListener
#fInicio #fFin       → solicitudesBajas.js: .value
#idEmp #tipoBaja     → solicitudesBajas.js: .value
#oficinasTable       → oficinas_admin.js: querySelector
#add_submit          → oficinas_admin.js: disabled
#edit_submit         → oficinas_admin.js: disabled
#primary-menu        → nav.php: getElementById (overlay)
#loading-indicator   → solicitudesBajas.js: creado dinámicamente
```

### 3.2 Clases usadas por JS — INTOCABLES

```
.edit-btn            → usuarios.js: innerHTML generado dinámicamente
.toggle-btn          → usuarios.js: innerHTML generado dinámicamente
.approve             → solicitudesBajas.js: classList.contains('approve')
.reject              → solicitudesBajas.js: class en innerHTML
.nav-toggle          → nav.php JS: querySelector
.nav-close           → nav.php JS: querySelector
.nav-menu            → nav.php JS: querySelector
.nav-item            → nav.php JS: querySelectorAll + classList.remove('open')
.nav-link            → nav.php JS: closest('.nav-link') + setAttribute
.menu-open           → nav.php JS: header.classList.toggle('menu-open')
.lock-scroll         → nav.php JS: document.body.classList.toggle('lock-scroll')
.open                → nav.php JS: item.classList.toggle('open')
.scrolled            → nav.php JS: header.classList.add/remove('scrolled')
.submenu             → nav.php JS: item.querySelector('.submenu')
.nav-wrap            → nav.php: ID y clase del overlay
.nav-toggle-bar      → nav.php: barras del hamburger
.disabled            → nav.php: nav-item.disabled
.hidden              → reporteMarcas.js: modal.classList.add/remove('hidden')
.hidden              → resumenMarcas.js: modal.classList.add/remove('hidden')
.scrolled            → titulos_script.js: header.classList.add/remove('scrolled')
.editMarca           → reporteMarcas.js: e.target.classList.contains('editMarca')
```

### 3.3 Selectores usados en PHP/HTML — NO RENOMBRAR

```
.active              → nav.php: PHP condicional para destacar página actual
.container_report    → usado en 12+ archivos PHP de vistas
.inner-container_report → usado en vistas
.container           → login.css, index.css, styles_baja.css
.form-group          → modal.css + login.css + styles_baja.css
.pagination          → empleados.css, feriados.css, usuarios.css, tipos.css...
.actions             → empleados.css, feriados.css, usuarios.css, tipos.css...
.message             → empleados.css, feriados.css, usuarios.css...
.popup-modal         → modal.css
.popup-content       → modal.css
.close-btn           → modal.css
.employees-table     → empleados.css
.users-table         → usuarios.css
.holidays-table      → feriados.css
.button-container    → buttons.css, styles_baja.css
```

---

## 4. CSS QUE SÍ SE PUEDE REFACTORIZAR

### 4.1 Propiedades modificables sin riesgo (CONSERVADOR)

En estos archivos **solo se cambian valores**, nunca selectores:

| Propiedad | Actual | Nueva (design ref) |
|---|---|---|
| `--primary-color` en `:root` | `#2563eb` | `#2B4EC8` |
| `--background-color` | `#F2F2F2` | `#F5F6FA` |
| `--border-color` | `#e5e7eb` | `#E5E7EB` (igual) |
| `--text-color` | `#1f2937` | `#111827` |
| `body font-family` | `sans-serif` (genérico) | `'Inter', system-ui, sans-serif` |
| `body font-size` | `14px` | `14px` (igual) |
| `th color` | `var(--text-color)` | `#3F7CDB` |
| `th background-color` | `rgba(245,245,245,1)` | `transparent` |
| `td border-bottom` | `1px solid var(--border-color)` | `1px dashed #E5E7EB` |
| `td padding` | `0.4rem` | `12px 8px` |
| `button border-radius` | `9999px` ✅ (ya está) | Conservar |
| `button background` hover | `#1f2937` | `#2B4EC8` |
| `pagination .active bg` | `#2563eb` | `#2B4EC8` |
| `.container_report border-radius` | `8px` ✅ | Conservar |
| `h1 font-size` | `28px` | `28–32px` |

### 4.2 Archivos con duplicación masiva (candidatos a consolidar)

Estos 12 archivos tienen **bloques idénticos** de `:root`, `body`, `main`, `.container_report`, `.inner-container_report`, `.actions`, `.pagination`, `.message`:

```
empleados.css, usuarios.css, feriados.css, tipos.css, oficinas.css,
externos.css, mantenimiento.css, accesoweb.css, dialibre.css,
estilo_solicitudesbaja.css, saldo_vacaciones.css, admin_usuarios.css
```

La única diferencia entre ellos es el **ancho de columnas de tabla** (nth-child).

---

## 5. CONFLICTOS DETECTADOS

### 5.1 Doble definición de `:root --primary-color`

- **Archivos de página:** `--primary-color: #2563eb` (Tailwind blue-600)
- **nav.php inline:** `--primary-color: #0056b3` (azul más oscuro)

→ La nav tiene scope propio (`<style>` dentro de `<header>`), no contamina las páginas.  
→ **Riesgo: BAJO** — son scopes diferentes.

### 5.2 `button` sobreescrito en múltiples archivos

`buttons.css` define el botón global. `index.css`, `styles_baja.css`, `estilo_solicitudesbaja.css` también definen `button {}`. El orden de carga determina cuál gana.

→ **Riesgo: MEDIO** — al consolidar hay que mantener el orden de especificidad.

### 5.3 `label` definida en 4 lugares

`modal.css` define `label { font-weight: bold }`, `index.css` define `label { font-weight: 500 }`, `login.css` usa `font-weight: 500`. Conflicto menor.

### 5.4 `input` global demasiado agresivo

`estilo_solicitudesbaja.css` y `styles_baja.css` definen `input, select { width: 100% }` que rompe layouts si carga junto a otros CSS.

---

## 6. ESTADO DE ARCHIVOS CSS

| Archivo | Líneas | Duplicación | Tipo |
|---|---|---|---|
| `empleados.css` | ~240 | ALTA (body/main/container_report) | Página |
| `usuarios.css` | ~239 | ALTA | Página |
| `feriados.css` | ~213 | ALTA | Página |
| `tipos.css` | ~similar | ALTA | Página |
| `oficinas.css` | ~similar | ALTA | Página |
| `estilo_solicitudesbaja.css` | ~136 | ALTA | Página |
| `styles_baja.css` | ~212 | MEDIA | Página |
| `buttons.css` | ~40 | BAJA | Compartido |
| `modal.css` | ~45 | BAJA | Compartido |
| `styles_tablas.css` | ~55 | BAJA | Compartido |
| `styles_admin.css` | ~105 | MEDIA | Compartido |
| `login.css` | ~290 | BAJA (scoped) | Auth |
| `auth_forms.css` | ~120 | BAJA (scoped) | Auth |
| `estilo_titulos.css` | ~42 | BAJA | Compartido |
| `fonts.css` | mínimo | — | Fuentes |
| `index.css` | ~156 | ALTA | Página |
| `nav.php <style>` | ~530 | N/A (inline) | Nav global |

---

## 7. ARCHIVOS FUERA DE ALCANCE

No tocar:
- `flatpickr.min.css` — vendor
- `all.min.css` — FontAwesome icons
- `vendor/dompdf*/html.css` — vendor PDF
- CSS inline en `nav.php` — funcional, gestionado por su propio JS

---

## 8. HALLAZGOS CRÍTICOS

1. **`nav.php` es 100% self-contained** — tiene `<style>` + `<script>` propios. Cualquier refactorización del CSS global NO afecta la navegación.

2. **No hay build pipeline** — no existe `package.json` con webpack/vite/parcel para compilar SCSS. Esto significa que SCSS requeriría instalar tooling desde cero.

3. **Los 12 archivos "página" son casi clones** — la única variación real son los anchos de columna (`nth-child`) y algún ajuste de `.inner-container_report { width: X% }`.

4. **`login.css` es el CSS mejor estructurado** — usa variables propias bien nombradas, es completamente scoped al login. Es el modelo a seguir.

5. **`buttons.css` ya implementa el estilo del design reference** — `border-radius: 9999px`, `border: 1px solid #1f2937`, hover `background: #1f2937`. Solo necesita actualizar el color hover a `#2B4EC8`.

---

*Siguiente paso: ver RECOMENDACIONES.md para decisiones de arquitectura.*
