/* ==========================================================================
   VELMO · components.css — Design system, capa de COMPONENTES
   Fase 1 del PLAN_REDISENO_UI.md · depende de theme.css
   --------------------------------------------------------------------------
   POR QUE TODO LLEVA PREFIJO .v-
   Los tres ficheros definen .btn, .card y .wrap con valores DISTINTOS entre
   si (.card padding 20px en index, 18px en enterprise, 8px en admin;
   .wrap max-width 940/1100/1150px). Redefinirlos aqui descolocaria las tres
   paginas a la vez, y la Fase 1 se cierra con "ninguna vista se descoloca".

   Por eso esta hoja NO pisa ninguna clase existente: crea la familia nueva
   .v-* en paralelo. La adopcion (sustituir .card por .v-card, .pill/.tag/
   .tp/.est por .v-badge) se hace pagina a pagina en la Fase 4, viendo el
   resultado en cada vista.

   NO renombrar ni reutilizar: .hidden .active .on .open las muta el JS.
   ========================================================================== */


/* ==========================================================================
   1. BOTONES
   ========================================================================== */
.v-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-2);
  border:1.5px solid transparent; border-radius:var(--r-md);
  padding:10px var(--sp-4); min-height:40px;
  font-family:inherit; font-size:var(--fs-sm); font-weight:var(--fw-bold);
  line-height:1; white-space:nowrap; cursor:pointer;
  background:#fff; color:var(--navy); border-color:var(--line);
  transition:background var(--t-fast) var(--ease),
             border-color var(--t-fast) var(--ease),
             color var(--t-fast) var(--ease),
             box-shadow var(--t-fast) var(--ease);
}
.v-btn:hover{ border-color:var(--gold); }
.v-btn:active{ transform:translateY(1px); }
.v-btn:disabled,.v-btn[aria-disabled="true"]{ opacity:.55; cursor:default; transform:none; }
.v-btn:disabled:hover{ border-color:var(--line); }

.v-btn--primary{ background:var(--gold); color:var(--navy); border-color:var(--gold); }
.v-btn--primary:hover{ background:var(--gold-d); border-color:var(--gold-d); color:#fff; }

.v-btn--navy{ background:var(--navy); color:#fff; border-color:var(--navy); }
.v-btn--navy:hover{ background:var(--navy2); border-color:var(--navy2); color:#fff; }

.v-btn--ghost{ background:transparent; color:var(--navy); border-color:var(--line); }
.v-btn--ghost:hover{ background:#faf7ef; border-color:var(--gold); }

.v-btn--danger{ background:#fff; color:var(--danger); border-color:#f0c9c9; }
.v-btn--danger:hover{ background:var(--dangerbg); border-color:var(--danger); }

.v-btn--sm{ min-height:32px; padding:6px var(--sp-3); font-size:var(--fs-xs); }
.v-btn--lg{ min-height:48px; padding:13px var(--sp-5); font-size:var(--fs-md); }
.v-btn--block{ width:100%; }

/* Grupo de acciones alineado a la derecha de una cabecera */
.v-actions{ display:flex; flex-wrap:wrap; gap:var(--sp-2); align-items:center; }


/* ==========================================================================
   2. TARJETA
   ========================================================================== */
.v-card{
  background:var(--card);
  border:1px solid var(--line);
  border-radius:var(--r-lg);
  box-shadow:var(--shadow-sm);
  padding:var(--sp-4);
}
.v-card--flush{ padding:0; overflow:hidden; }      /* para meter una tabla a sangre */
.v-card--raised{ box-shadow:var(--shadow); }

.v-card__head{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--sp-3); flex-wrap:wrap;
  margin:0 0 var(--sp-3);
}
.v-card--flush .v-card__head{ padding:var(--sp-4) var(--sp-4) var(--sp-3); margin:0; }

.v-card__title{
  margin:0; font-size:var(--fs-lg); font-weight:var(--fw-bold);
  color:var(--navy); line-height:var(--lh-tight);
  display:flex; align-items:center; gap:var(--sp-2); min-width:0;
}
.v-card__sub{ margin:var(--sp-1) 0 0; font-size:var(--fs-sm); color:var(--muted); }

/* Cifra de dashboard */
.v-stat__label{ font-size:var(--fs-xs); font-weight:var(--fw-bold); color:var(--muted);
                text-transform:uppercase; letter-spacing:.04em; }
.v-stat__value{ font-size:var(--fs-2xl); font-weight:var(--fw-black); color:var(--navy);
                line-height:var(--lh-tight); margin-top:var(--sp-1); }
.v-stat__value--ok{ color:var(--ok); }
.v-stat__value--warn{ color:var(--warn); }
.v-stat__value--danger{ color:var(--danger); }


/* ==========================================================================
   3. BADGES — familia unica
   Absorbe .tp (tipo de servicio), .tag (estado incidencia), .pill (recibo) y
   .est (estado de cobro). Mismos colores exactos que las cuatro familias
   antiguas, para que la migracion de la Fase 4 no cambie ningun color.
   ========================================================================== */
.v-badge{
  display:inline-flex; align-items:center; gap:var(--sp-1);
  font-size:var(--fs-xs); font-weight:var(--fw-black); line-height:1.6;
  padding:3px 10px; border-radius:var(--r-pill); white-space:nowrap;
  background:var(--neutralbg); color:var(--muted);
}
.v-badge--ok{      background:var(--okbg);      color:var(--ok); }
.v-badge--warn{    background:var(--warnbg);    color:var(--warn); }
.v-badge--danger{  background:var(--dangerbg);  color:var(--danger); }
.v-badge--info{    background:var(--infobg);    color:var(--info); }
.v-badge--neutral{ background:var(--neutralbg); color:var(--muted); }
.v-badge--brand{   background:var(--navy);      color:var(--gold); }
.v-badge--solid{   background:var(--danger);    color:#fff; }        /* = .tag.urg */

/* Tonos de servicio que no encajan en la escala de estado */
.v-badge--purple{ background:#f3ecfb; color:#6b3fa0; }               /* consultoria */
.v-badge--green{  background:#eef7f0; color:#2a7d5f; }               /* alquiler    */

/* Punto de color para semaforos (sustituye a .g/.y/.r/.n de enterprise) */
.v-dot{ width:9px; height:9px; border-radius:50%; display:inline-block; flex:0 0 auto;
        background:var(--muted); }
.v-dot--ok{ background:var(--ok); }
.v-dot--warn{ background:var(--warn); }
.v-dot--danger{ background:var(--danger); }


/* ==========================================================================
   4. TABLA
   En movil pasa a tarjetas apiladas leyendo data-label de cada <td>.
   Es el mismo patron que admin.html ya usa con exito dentro de .card.
   ========================================================================== */
.v-table{ width:100%; border-collapse:collapse; font-size:var(--fs-sm); }
.v-table th,.v-table td{
  padding:10px var(--sp-3); text-align:left; vertical-align:middle;
  border-bottom:1px solid var(--line);
}
.v-table thead th{
  font-size:var(--fs-xs); font-weight:var(--fw-black); color:var(--muted);
  text-transform:uppercase; letter-spacing:.04em; white-space:nowrap;
  background:#fafbfe; border-bottom:1.5px solid var(--line);
  position:sticky; top:0; z-index:var(--z-sticky);
}
.v-table tbody tr:hover{ background:#fafbfe; }
.v-table tbody tr:last-child td{ border-bottom:0; }
.v-table .v-num{ text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap; }

/* Envoltorio con scroll horizontal en pantallas intermedias */
.v-table-wrap{ overflow-x:auto; -webkit-overflow-scrolling:touch; }

@media (max-width:760px){
  .v-table--cards thead{ display:none; }
  .v-table--cards,
  .v-table--cards tbody,
  .v-table--cards tr,
  .v-table--cards td{ display:block; width:auto; }
  .v-table--cards tr{
    background:var(--card); border:1px solid var(--line); border-radius:var(--r-md);
    box-shadow:var(--shadow-sm); margin:0 0 var(--sp-3); padding:var(--sp-2) var(--sp-3);
  }
  .v-table--cards td{ border:0!important; padding:5px 2px!important; text-align:left!important; }
  .v-table--cards td::before{
    content:attr(data-label); display:block;
    font-size:var(--fs-xs); font-weight:var(--fw-bold); color:var(--muted);
    text-transform:uppercase; letter-spacing:.03em; margin-bottom:2px;
  }
  .v-table--cards td[data-label=""]::before,
  .v-table--cards td:not([data-label])::before{ display:none; }
}


/* ==========================================================================
   5. AGRUPACION POR COMUNIDAD  (lo que pide el rediseno: propiedades
   agrupadas y plegables, con los indicadores a la vista)
   Usa <details>/<summary> nativos: sin JS, accesible y sin romper nada.
   ========================================================================== */
.v-group{
  background:var(--card); border:1px solid var(--line);
  border-radius:var(--r-lg); box-shadow:var(--shadow-sm);
  margin-bottom:var(--sp-3); overflow:hidden;
}
.v-group__head{
  display:flex; align-items:center; gap:var(--sp-3); flex-wrap:wrap;
  padding:var(--sp-3) var(--sp-4); cursor:pointer; list-style:none;
  transition:background var(--t-fast) var(--ease);
}
.v-group__head::-webkit-details-marker{ display:none; }
.v-group__head:hover{ background:#fafbfe; }

.v-group__caret{
  flex:0 0 auto; width:16px; color:var(--muted);
  transition:transform var(--t-base) var(--ease);
}
.v-group[open] .v-group__caret{ transform:rotate(90deg); }

.v-group__name{
  font-size:var(--fs-md); font-weight:var(--fw-bold); color:var(--navy);
  min-width:0; flex:1 1 220px;                 /* min-width:0 = regla anti-desborde */
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.v-group__count{
  font-size:var(--fs-xs); font-weight:var(--fw-bold); color:var(--muted);
  background:var(--neutralbg); border-radius:var(--r-pill); padding:3px 10px;
}
.v-group__meta{ display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap; }
.v-group__body{ padding:0 var(--sp-4) var(--sp-3); border-top:1px solid var(--line); }


/* ==========================================================================
   6. FORMULARIOS
   ========================================================================== */
.v-field{ display:block; margin-bottom:var(--sp-3); min-width:0; }
.v-label{
  display:block; margin-bottom:var(--sp-1);
  font-size:var(--fs-xs); font-weight:var(--fw-bold); color:var(--muted);
  text-transform:uppercase; letter-spacing:.03em;
}
.v-input,.v-select,.v-textarea{
  width:100%; box-sizing:border-box;
  font-family:inherit; font-size:var(--fs-md);  /* 16px: evita el zoom de iOS */
  color:var(--ink); background:#fff;
  border:1.5px solid var(--line); border-radius:var(--r-sm);
  padding:10px var(--sp-3); min-height:42px;
  transition:border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.v-input:focus,.v-select:focus,.v-textarea:focus{
  border-color:var(--gold); box-shadow:0 0 0 3px rgba(194,161,94,.18); outline:none;
}
.v-input:disabled,.v-select:disabled,.v-textarea:disabled{ background:#f7f8fb; color:var(--muted); }
.v-textarea{ min-height:96px; resize:vertical; line-height:var(--lh-base); }
.v-hint{ display:block; margin-top:var(--sp-1); font-size:var(--fs-xs); color:var(--muted); }
.v-hint--error{ color:var(--danger); }

/* Barra de filtros / buscador */
.v-toolbar{
  display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-2);
  margin-bottom:var(--sp-3);
}
.v-search{ position:relative; flex:1 1 260px; min-width:0; }
.v-search .v-input{ padding-left:38px; }
.v-search__ico{
  position:absolute; left:12px; top:50%; transform:translateY(-50%);
  width:16px; height:16px; color:var(--muted); pointer-events:none;
}


/* ==========================================================================
   7. AVISOS  (sustituye a los alert() nativos en la Fase 5)
   ========================================================================== */
.v-alert{
  display:flex; gap:var(--sp-3); align-items:flex-start;
  padding:var(--sp-3) var(--sp-4); border-radius:var(--r-md);
  border:1px solid var(--line); border-left-width:4px;
  background:var(--neutralbg); color:var(--ink);
  font-size:var(--fs-sm); line-height:var(--lh-base);
}
.v-alert--ok{     background:var(--okbg);     border-color:var(--ok);     color:#14563a; }
.v-alert--warn{   background:var(--warnbg);   border-color:var(--warn);   color:#7a4c0b; }
.v-alert--danger{ background:var(--dangerbg); border-color:var(--danger); color:#7d2929; }
.v-alert--info{   background:var(--infobg);   border-color:var(--info);   color:#1e3870; }
.v-alert__ico{ flex:0 0 auto; width:18px; height:18px; margin-top:1px; }


/* ==========================================================================
   8. MODAL
   ========================================================================== */
.v-modal{
  position:fixed; inset:0; z-index:var(--z-modal);
  display:flex; align-items:center; justify-content:center;
  padding:var(--sp-4);
  background:rgba(27,42,74,.45);
  overflow-y:auto;
}
.v-modal__box{
  background:var(--card); border-radius:var(--r-xl); box-shadow:var(--shadow-lg);
  width:100%; max-width:560px; max-height:90vh; overflow:auto;
}
.v-modal__head{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-3);
  padding:var(--sp-4); border-bottom:1px solid var(--line);
}
.v-modal__title{ margin:0; font-size:var(--fs-lg); font-weight:var(--fw-bold); color:var(--navy); }
.v-modal__body{ padding:var(--sp-4); }
.v-modal__foot{
  display:flex; justify-content:flex-end; gap:var(--sp-2); flex-wrap:wrap;
  padding:var(--sp-3) var(--sp-4); border-top:1px solid var(--line); background:#fafbfe;
}
.v-modal__x{
  border:0; background:transparent; color:var(--muted); cursor:pointer;
  font-size:var(--fs-xl); line-height:1; padding:0 var(--sp-1);
}
.v-modal__x:hover{ color:var(--danger); }

@media (max-width:560px){
  .v-modal{ padding:0; align-items:flex-end; }
  .v-modal__box{ max-width:none; border-radius:var(--r-xl) var(--r-xl) 0 0; max-height:94vh; }
  .v-modal__foot .v-btn{ flex:1 1 auto; }
}


/* ==========================================================================
   9. MIGA DE PAN  (admin ya tiene #crumb y setCrumb(): se reutilizan)
   ========================================================================== */
.v-crumb{
  display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap;
  font-size:var(--fs-sm); color:var(--muted); margin-bottom:var(--sp-2);
}
.v-crumb a{ color:var(--muted); text-decoration:none; }
.v-crumb a:hover{ color:var(--navy); text-decoration:underline; }
.v-crumb__sep{ color:var(--line); }
.v-crumb__now{ color:var(--navy); font-weight:var(--fw-bold); }


/* ==========================================================================
   10. PAGINACION
   ========================================================================== */
.v-pager{ display:flex; align-items:center; gap:var(--sp-1); flex-wrap:wrap;
          justify-content:center; margin-top:var(--sp-4); }
.v-pager__btn{
  min-width:36px; min-height:36px; padding:0 var(--sp-2);
  display:inline-flex; align-items:center; justify-content:center;
  border:1.5px solid var(--line); border-radius:var(--r-sm); background:#fff;
  color:var(--navy); font-size:var(--fs-sm); font-weight:var(--fw-bold);
  font-family:inherit; cursor:pointer;
}
.v-pager__btn:hover{ border-color:var(--gold); }
.v-pager__btn[aria-current="page"]{ background:var(--navy); border-color:var(--navy); color:#fff; }
.v-pager__btn:disabled{ opacity:.45; cursor:default; }
.v-pager__info{ font-size:var(--fs-xs); color:var(--muted); margin:0 var(--sp-2); }


/* ==========================================================================
   11. ESTADO VACIO
   ========================================================================== */
.v-empty{
  text-align:center; padding:var(--sp-6) var(--sp-4); color:var(--muted);
}
.v-empty__ico{ width:40px; height:40px; color:var(--line); margin:0 auto var(--sp-3); display:block; }
.v-empty__title{ font-size:var(--fs-md); font-weight:var(--fw-bold); color:var(--navy);
                 margin:0 0 var(--sp-1); }
.v-empty__text{ font-size:var(--fs-sm); margin:0 0 var(--sp-4); }


/* ==========================================================================
   12. CARGANDO
   ========================================================================== */
.v-spinner{
  width:18px; height:18px; border-radius:50%; display:inline-block;
  border:2px solid var(--line); border-top-color:var(--gold);
  animation:v-spin .7s linear infinite;
}
@keyframes v-spin{ to{ transform:rotate(360deg); } }

.v-skeleton{
  background:linear-gradient(90deg,#eef1f6 25%,#f6f8fb 37%,#eef1f6 63%);
  background-size:400% 100%; border-radius:var(--r-sm);
  animation:v-shimmer 1.4s ease infinite; min-height:14px;
}
@keyframes v-shimmer{ 0%{background-position:100% 0} 100%{background-position:0 0} }


/* ==========================================================================
   13. REJILLA Y UTILIDADES MINIMAS
   min-width:0 en todos los hijos: es la regla que cerro la auditoria de
   desbordes en movil (ver memoria velmo-auditoria-desbordes-movil).
   ========================================================================== */
.v-grid{ display:grid; gap:var(--sp-3); }
.v-grid>*{ min-width:0; }
.v-grid--2{ grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); }
.v-grid--3{ grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); }
.v-grid--4{ grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); }

.v-row{ display:flex; align-items:center; gap:var(--sp-2); flex-wrap:wrap; min-width:0; }
.v-spacer{ flex:1 1 auto; }
.v-muted{ color:var(--muted); }
.v-nowrap{ white-space:nowrap; }
.v-truncate{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
.v-sr-only{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}


/* ==========================================================================
   14. SIDEBAR DE NAVEGACION (Fase 2 — inyectado por web/velmo-nav.js)
   Solo lo usan admin.html y enterprise.html. index.html conserva sus chips
   sticky con IntersectionObserver (portal del vecino, mayoritariamente
   movil) — ver §3.5 de PORTAL/PLAN_REDISENO_UI.md.

   El script lo inyecta como PRIMER hijo de #app, así que hereda el
   .hidden de #app sin CSS aparte: no se ve en login/loading/denied.

   Navy + dorado: mismo maridaje que ya usaba .tp.administracion en
   admin.html (fondo #1B2A4A, texto #c2a15e) — no es una paleta nueva,
   es aplicar a un componente grande un pareo que ya existía a pequeña
   escala en este mismo código.
   ========================================================================== */
:root{ --v-nav-w:248px; --v-nav-bp:900px; }

.v-nav{
  position:fixed; inset:0 auto 0 0; width:var(--v-nav-w); z-index:var(--z-nav);
  background:var(--navy); color:rgba(255,255,255,.86);
  display:flex; flex-direction:column;
  box-shadow:2px 0 0 rgba(0,0,0,.04);
}
.v-nav__brand{
  flex:0 0 auto; display:flex; align-items:center; gap:var(--sp-2);
  padding:var(--sp-4) var(--sp-4) var(--sp-3); cursor:pointer;
  border-bottom:1px solid rgba(255,255,255,.10);
}
.v-nav__brand img{ height:34px; flex:0 0 auto; }
.v-nav__brand-txt{ min-width:0; line-height:1.25; }
.v-nav__brand-title{ font-size:13px; font-weight:800; color:#fff; }
.v-nav__brand-sub{ font-size:10.5px; font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--gold); }

.v-nav__body{ flex:1 1 auto; overflow-y:auto; padding:var(--sp-3) var(--sp-2); }
.v-nav__group-label{
  padding:var(--sp-4) var(--sp-3) var(--sp-1); font-size:10.5px; font-weight:800;
  letter-spacing:.08em; text-transform:uppercase; color:rgba(255,255,255,.42);
}
.v-nav__group-label:first-child{ padding-top:var(--sp-2); }

.v-nav__item{
  display:flex; align-items:center; gap:var(--sp-2); width:100%;
  padding:9px var(--sp-3); margin:1px 0; border:0; background:transparent;
  border-radius:var(--r-sm); border-left:3px solid transparent;
  color:rgba(255,255,255,.82); font:inherit; font-size:13.5px; font-weight:600;
  text-align:left; text-decoration:none; cursor:pointer; line-height:1.3;
}
.v-nav__item:hover{ background:rgba(255,255,255,.07); color:#fff; }
.v-nav__item.active{
  background:rgba(194,161,94,.16); border-left-color:var(--gold); color:#fff;
}
.v-nav__item.active .v-nav__ico{ color:var(--gold); }
.v-nav__item--accent{ background:rgba(194,161,94,.12); }
.v-nav__ico{ flex:0 0 auto; width:18px; height:18px; color:rgba(255,255,255,.55); }
.v-nav__label{ flex:1 1 auto; min-width:0; }
.v-nav__badge{
  flex:0 0 auto; background:var(--gold); color:var(--navy); font-size:11px;
  font-weight:800; border-radius:var(--r-pill); padding:1px 7px; line-height:1.5;
}

.v-nav__foot{
  flex:0 0 auto; padding:var(--sp-2); border-top:1px solid rgba(255,255,255,.10);
}

/* El botón hamburguesa y el fondo de cierre: solo existen por debajo del punto
   de corte (ver JS, que los crea igualmente en escritorio pero display:none
   los oculta aquí). */
.v-nav-toggle{
  display:none; position:fixed; top:12px; left:12px; z-index:calc(var(--z-nav) + 1);
  width:40px; height:40px; align-items:center; justify-content:center;
  background:var(--navy); color:#fff; border:0; border-radius:var(--r-sm);
  box-shadow:var(--shadow);
}
.v-nav-toggle svg{ width:20px; height:20px; }
/* z-index por DEBAJO del sidebar (var(--z-nav)): el backdrop cubre toda la
   pantalla y solo tiene que oscurecer el contenido, no puede quedar encima
   del propio panel o le roba los clics a sus botones (bug real, cazado al
   verificar esta fase: el toggle se apagaba pero la vista nunca cambiaba). */
.v-nav-backdrop{ display:none; position:fixed; inset:0; z-index:calc(var(--z-nav) - 1);
  background:rgba(15,23,42,.45); }

/* Escritorio: el contenido de #app se corre a la derecha del sidebar fijo.
   Se aplica a #app (no a body): así login/loading/denied, que no son hijos
   del mismo flujo que el sidebar, no se ven afectados. */
body.v-has-nav #app{ padding-left:var(--v-nav-w); }
body.v-has-nav .topbar{ display:none; }

@media (max-width:900px){
  .v-nav{
    transform:translateX(-100%); transition:transform var(--t-base) var(--ease);
    box-shadow:var(--shadow-lg);
  }
  body.v-nav--open .v-nav{ transform:translateX(0); }
  .v-nav-toggle{ display:flex; }
  /* Con el panel abierto, la hamburguesa quedaría encima del logo del propio
     sidebar (los dos nacen en la misma esquina). Se oculta: ya hay tres formas
     de cerrar (tocar fuera, Esc, elegir una sección) sin ese botón. */
  body.v-nav--open .v-nav-toggle{ display:none; }
  body.v-has-nav.v-nav--open .v-nav-backdrop{ display:block; }
  /* En móvil el sidebar es off-canvas: no reserva hueco, y el botón hamburguesa
     ya ocupa la esquina donde antes estaba el logo del topbar oculto. */
  body.v-has-nav #app{ padding-left:0; padding-top:56px; }
}
