/* ════════════════════════════════════════════════════════════════
   TimeTrack · Premium Employee Skin v1.0 (2026-05-15)
   ----------------------------------------------------------------
   Sistema de componentes premium para el panel del empleado
   (app.html).  Filosofía: Linear/Stripe-tier.  Mobile-first.
   Tokens reusan los de style.css; aquí sólo añadimos NUEVAS
   composiciones que conviven con las existentes (.kpi, .card-soft,
   .table-wrap, .announce, .cal-day…).

   Carga DESPUÉS de style.css en app.html.
   ════════════════════════════════════════════════════════════════ */

:root {
  /* Premium accents · default atlantico (indigo → violet → fuchsia)
     v2.6.9 — Overrides themed más abajo para factorial/nimbus.
     `--pe-grad-3` (success green) y `--pe-grad-warm` se mantienen
     theme-agnostic (semánticos: success/warm independientes del primary). */
  --pe-grad-1: linear-gradient(135deg, #6366f1 0%, #8b5cf6 55%, #d946ef 100%);
  --pe-grad-2: linear-gradient(135deg, #06b6d4 0%, #6366f1 100%);
  --pe-grad-3: linear-gradient(135deg, #10b981 0%, #06b6d4 100%);
  --pe-grad-warm: linear-gradient(135deg, #f59e0b 0%, #ef4444 100%);
  --pe-grad-cool: linear-gradient(135deg, #0ea5e9 0%, #6366f1 100%);

  --pe-surface-glow: 0 0 0 1px rgba(var(--bs-primary-rgb), .12),
                     0 18px 40px -16px rgba(var(--bs-primary-rgb), .25),
                     0 4px 10px -4px rgba(0,0,0,.08);
  --pe-card-lift: 0 12px 32px -10px rgba(15,23,42,.16),
                  0 4px 12px -4px rgba(15,23,42,.10);

  --pe-radius-xl: 20px;
  --pe-radius-lg: 14px;
  --pe-radius-md: 10px;

  --pe-ease: cubic-bezier(.2, .9, .2, 1);
}
[data-bs-theme="dark"] {
  --pe-surface-glow: 0 0 0 1px rgba(255,255,255,.05),
                     0 18px 40px -16px rgba(0,0,0,.55),
                     0 4px 10px -4px rgba(0,0,0,.30);
  --pe-card-lift: 0 14px 32px -8px rgba(0,0,0,.60),
                  0 4px 12px -4px rgba(0,0,0,.40);
}

/* ════════════════════════════════════════════════════════════
   v2.6.9 · THEME-AWARE pe-grad-* (factorial / nimbus)
   ------------------------------------------------------------
   Estos gradients se usan en 14+ lugares (hero borders, eyebrow
   gradients, kpi value text bg-clip, vac-hero, day-card stripe,
   announce hover, cal-pro-wrap top, welcome-hero, plan-card etc).
   Hardcoded indigo→violet→fuchsia rompe la identidad del tema
   activo.  Reaplica per-theme para que cada paleta tenga su
   propia firma cromática consistente con --tt-grad-primary.
   ════════════════════════════════════════════════════════════ */
[data-color-theme="factorial"] {
  /* Rose → pink → fuchsia (warm side) */
  --pe-grad-1: linear-gradient(135deg, #f43f5e 0%, #ec4899 55%, #be185d 100%);
  --pe-grad-2: linear-gradient(135deg, #fb7185 0%, #f43f5e 100%);
  --pe-grad-cool: linear-gradient(135deg, #fda4af 0%, #f43f5e 100%);
}
[data-color-theme="factorial"][data-bs-theme="dark"] {
  /* Versión dark más vibrante para contraste sobre bg oscuro */
  --pe-grad-1: linear-gradient(135deg, #fb7185 0%, #f472b6 55%, #ec4899 100%);
  --pe-grad-2: linear-gradient(135deg, #fda4af 0%, #fb7185 100%);
  --pe-grad-cool: linear-gradient(135deg, #fecdd3 0%, #fb7185 100%);
}
[data-color-theme="nimbus"] {
  /* Cyan → teal → slate-cyan (cool tech side) */
  --pe-grad-1: linear-gradient(135deg, #06b6d4 0%, #0891b2 55%, #0e7490 100%);
  --pe-grad-2: linear-gradient(135deg, #22d3ee 0%, #06b6d4 100%);
  --pe-grad-cool: linear-gradient(135deg, #67e8f9 0%, #06b6d4 100%);
}
[data-color-theme="nimbus"][data-bs-theme="dark"] {
  /* Versión dark con luminosidad para contraste sobre bg navy */
  --pe-grad-1: linear-gradient(135deg, #67e8f9 0%, #22d3ee 55%, #06b6d4 100%);
  --pe-grad-2: linear-gradient(135deg, #a5f3fc 0%, #22d3ee 100%);
  --pe-grad-cool: linear-gradient(135deg, #cffafe 0%, #67e8f9 100%);
}

/* ─────────────────────────────────────────────────────────────
   SECTION HERO · cabecera premium con gradient sutil
   Reemplaza visualmente al .section-header básico cuando se
   añade la clase `.section-hero` al wrapper de cabecera.
   ───────────────────────────────────────────────────────────── */
.section-hero {
  position: relative;
  padding: 26px 28px;
  margin: -4px 0 24px;
  border-radius: var(--pe-radius-xl);
  background:
    radial-gradient(120% 90% at 0% 0%, rgba(var(--bs-primary-rgb), .10), transparent 60%),
    radial-gradient(80% 120% at 100% 100%, rgba(139,92,246, .08), transparent 65%),
    var(--tt-surface);
  border: 1px solid var(--bs-border-color);
  overflow: hidden;
  isolation: isolate;
}
.section-hero::before {
  /* Línea de acento gradient en el borde superior */
  content: '';
  position: absolute; inset: 0 0 auto 0;
  height: 2px;
  background: var(--pe-grad-1);
  opacity: .9;
}
.section-hero::after {
  /* Decoración floating discreta */
  content: '';
  position: absolute;
  top: -40px; right: -40px;
  width: 220px; height: 220px;
  background: var(--pe-grad-1);
  filter: blur(60px);
  opacity: .10;
  pointer-events: none;
  z-index: -1;
}
.section-hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: .6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--bs-primary);
  margin-bottom: 6px;
}
.section-hero-eyebrow .bi { font-size: .8125rem; }
.section-hero h1,
.section-hero .section-hero-title {
  font-size: 1.625rem;
  font-weight: 800;
  letter-spacing: -.025em;
  line-height: 1.15;
  margin: 0 0 6px;
  background: var(--pe-grad-1);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.section-hero .section-hero-sub {
  font-size: .9375rem;
  color: var(--bs-secondary-color);
  margin: 0;
  max-width: 64ch;
}
.section-hero .section-hero-actions {
  margin-top: 16px;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
}
@media (max-width: 575.98px) {
  .section-hero { padding: 18px 18px; border-radius: var(--pe-radius-lg); }
  .section-hero h1,
  .section-hero .section-hero-title { font-size: 1.25rem; }
  .section-hero .section-hero-sub { font-size: .8125rem; }
}

/* Versión "split" con stats a la derecha */
.section-hero.split { display: grid; gap: 20px; }
@media (min-width: 768px) {
  .section-hero.split {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    align-items: end;
  }
}
.section-hero-stats {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.section-hero-stat {
  text-align: right;
}
.section-hero-stat .v {
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.section-hero-stat .l {
  font-size: .6875rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 600;
  color: var(--bs-secondary-color);
  margin-top: 4px;
}

/* ─────────────────────────────────────────────────────────────
   KPI PRO · tarjeta KPI premium con halo, tabular nums y trend
   Compatible con .kpi existente; usar `.kpi.kpi-pro` para upgrade.
   ───────────────────────────────────────────────────────────── */
.kpi-pro {
  position: relative;
  background: var(--tt-surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--pe-radius-lg);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-height: 130px;
  isolation: isolate;
  transition: transform .25s var(--pe-ease),
              box-shadow .25s var(--pe-ease),
              border-color .25s var(--pe-ease);
}
.kpi-pro::before {
  /* Halo gradient detrás del icono */
  content: '';
  position: absolute;
  top: 14px; left: 14px;
  width: 64px; height: 64px;
  background: var(--pe-grad-1);
  border-radius: 50%;
  filter: blur(28px);
  opacity: .18;
  z-index: -1;
  transition: opacity .3s var(--pe-ease);
}
.kpi-pro:hover {
  transform: translateY(-2px);
  border-color: rgba(var(--bs-primary-rgb), .25);
  box-shadow: var(--pe-card-lift);
}
.kpi-pro:hover::before { opacity: .32; }
.kpi-pro .kpi-pro-head {
  display: flex;
  align-items: center;
  gap: 12px;
}
.kpi-pro .kpi-pro-icon {
  width: 44px; height: 44px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  font-size: 1.1rem;
  background: rgba(var(--bs-primary-rgb), .10);
  color: var(--bs-primary);
  flex-shrink: 0;
}
.kpi-pro .kpi-pro-icon.success { background: rgba(var(--bs-success-rgb), .10); color: var(--bs-success); }
.kpi-pro .kpi-pro-icon.warning { background: rgba(var(--bs-warning-rgb), .12); color: var(--bs-warning); }
.kpi-pro .kpi-pro-icon.danger  { background: rgba(var(--bs-danger-rgb), .10);  color: var(--bs-danger); }
.kpi-pro .kpi-pro-icon.info    { background: rgba(var(--bs-info-rgb), .10);    color: var(--bs-info); }
.kpi-pro .kpi-pro-icon.violet  { background: rgba(139,92,246,.12); color: #8b5cf6; }
[data-bs-theme="dark"] .kpi-pro .kpi-pro-icon.violet { background: rgba(139,92,246,.16); color: #a78bfa; }
.kpi-pro .kpi-pro-label {
  font-size: .6875rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 700;
  color: var(--bs-secondary-color);
}
.kpi-pro .kpi-pro-value {
  font-size: 1.75rem;
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--bs-body-color);
}
.kpi-pro .kpi-pro-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  font-size: .75rem;
  color: var(--bs-secondary-color);
  margin-top: auto;
}
.kpi-pro .kpi-pro-trend {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: .6875rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.kpi-pro .kpi-pro-trend.up   { background: rgba(var(--bs-success-rgb), .10); color: var(--bs-success); }
.kpi-pro .kpi-pro-trend.down { background: rgba(var(--bs-danger-rgb), .10);  color: var(--bs-danger); }
.kpi-pro .kpi-pro-trend.flat { background: rgba(var(--bs-secondary-rgb), .08); color: var(--bs-secondary-color); }
@media (max-width: 575.98px) {
  .kpi-pro { padding: 14px; min-height: 110px; gap: 10px; }
  .kpi-pro .kpi-pro-value { font-size: 1.375rem; }
  .kpi-pro .kpi-pro-icon { width: 38px; height: 38px; font-size: .95rem; }
}

/* ─────────────────────────────────────────────────────────────
   SCHEDULE WEEK · grid premium para Mi horario semanal
   v2.6.3: 1 columna SIEMPRE (cada día en su propia línea).  El
   day-card pasa a layout HORIZONTAL en ≥768px aprovechando todo
   el ancho disponible para meter head/hours/range/timeline en
   la misma fila.
   ───────────────────────────────────────────────────────────── */
.schedule-week {
  display: grid;
  gap: 10px;
  grid-template-columns: 1fr;   /* 1 día por línea, siempre */
}

.day-card {
  position: relative;
  background: var(--tt-surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--pe-radius-lg);
  padding: 16px 20px;
  overflow: hidden;
  transition: transform .25s var(--pe-ease),
              box-shadow .25s var(--pe-ease),
              border-color .25s var(--pe-ease);
  /* Mobile (<768px): stack vertical natural */
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ── Desktop / Tablet (≥768px) ── layout HORIZONTAL ─────────
   Grid de 4 columnas:
     · head     (auto, mínimo 140px)  → día + pill HOY
     · hours    (auto, mínimo 100px)  → "8h 0m" big number
     · range    (auto, ~150px)        → 09:00 → 17:00
     · timeline (1fr)                 → barra de progreso 24h fill
   Vertical-align center para que todo quede en el medio del row. */
@media (min-width: 768px) {
  .day-card {
    display: grid;
    grid-template-columns:
      minmax(140px, max-content)
      minmax(90px,  max-content)
      minmax(120px, max-content)
      minmax(0, 1fr);
    grid-template-areas: "head hours range timeline";
    align-items: center;
    gap: 22px;
    padding: 14px 22px;
  }
  .day-card-head        { grid-area: head; margin-bottom: 0 !important; }
  .day-card > .day-card-hours { grid-area: hours; }
  .day-card > .day-card-range { grid-area: range; }
  .day-card .day-timeline-wrap { grid-area: timeline; padding-bottom: 0; }
  .day-card .day-timeline { margin-top: 0; }
  /* En layout horizontal el range "09:00 → 17:00" ya está visible
     en la celda anterior → los ticks 0h/6h/.../24h son redundantes
     y además se clipearían con `.day-card{overflow:hidden}`. */
  .day-card .day-timeline-ticks { display: none; }
}

/* Cuando el día es "Libre" (free), no tiene range ni timeline → el
   grid sólo necesita 2 cols: head + "Libre". */
@media (min-width: 768px) {
  .day-card.free {
    grid-template-columns: minmax(140px, max-content) 1fr;
    grid-template-areas: "head hours";
  }
}

.day-card:hover {
  transform: translateY(-1px);
  box-shadow: var(--pe-card-lift);
  border-color: rgba(var(--bs-primary-rgb), .22);
}
.day-card.today {
  border-color: rgba(var(--bs-primary-rgb), .45);
  box-shadow: 0 0 0 3px rgba(var(--bs-primary-rgb), .12);
}
.day-card.today::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--pe-grad-1);
}
.day-card.free {
  background: linear-gradient(135deg, var(--tt-surface) 0%, rgba(var(--bs-secondary-rgb), .04) 100%);
}
.day-card.free .day-card-name { color: var(--bs-secondary-color); }
.day-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 0;
}
.day-card-name {
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -.015em;
  color: var(--bs-body-color);
  text-transform: capitalize;
}
.day-card-today-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: .625rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .08em;
  background: rgba(var(--bs-primary-rgb), .12);
  color: var(--bs-primary);
}
.day-card-hours {
  font-size: 1.25rem;
  font-weight: 800;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--bs-body-color);
}
.day-card.free .day-card-hours {
  font-size: .9375rem;
  color: var(--bs-secondary-color);
  font-weight: 600;
  letter-spacing: 0;
}
.day-card-range {
  font-size: .8125rem;
  color: var(--bs-secondary-color);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 8px;
}
.day-card-range .bi { font-size: .75rem; opacity: .7; }
.day-card-range .arrow { color: var(--bs-tertiary-color); }

/* Timeline strip 0–24h: barra horizontal con el bloque de horas */
.day-timeline {
  position: relative;
  height: 8px;
  margin-top: 14px;
  background: var(--bs-tertiary-bg);
  border-radius: 999px;
  overflow: hidden;
}
.day-timeline-fill {
  position: absolute;
  top: 0; bottom: 0;
  border-radius: 999px;
  background: var(--pe-grad-1);
  box-shadow: 0 0 12px rgba(var(--bs-primary-rgb), .35);
  /* width + left se inyectan inline en JS */
}
.day-timeline-ticks {
  position: absolute;
  inset: -8px 0 -10px;
  pointer-events: none;
  font-size: .625rem;
  color: var(--bs-tertiary-color);
  font-variant-numeric: tabular-nums;
}
.day-timeline-ticks span {
  position: absolute;
  bottom: -16px;
  transform: translateX(-50%);
}
.day-timeline-ticks span:first-child { transform: none; left: 0; }
.day-timeline-ticks span:last-child { transform: translateX(-100%); right: 0; left: auto; }
.day-timeline-wrap { padding-bottom: 18px; }

/* Schedule footer · resumen semanal */
.schedule-summary {
  margin-top: 18px;
  padding: 18px 22px;
  border-radius: var(--pe-radius-lg);
  background:
    radial-gradient(80% 120% at 100% 50%, rgba(var(--bs-primary-rgb), .14), transparent 60%),
    var(--tt-surface);
  border: 1px solid var(--bs-border-color);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.schedule-summary-label {
  font-size: .8125rem;
  color: var(--bs-secondary-color);
  font-weight: 600;
}
.schedule-summary-value {
  font-size: 1.875rem;
  font-weight: 800;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  background: var(--pe-grad-1);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.schedule-summary-extra {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
}
.schedule-summary-extra > div { text-align: right; }
.schedule-summary-extra .v {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--bs-body-color);
}
.schedule-summary-extra .l {
  font-size: .6875rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--bs-secondary-color);
  font-weight: 600;
}

/* ─────────────────────────────────────────────────────────────
   STAT RING · ring de progreso premium (vacaciones)
   ───────────────────────────────────────────────────────────── */
.stat-ring {
  position: relative;
  width: 144px; height: 144px;
  flex-shrink: 0;
}
.stat-ring svg {
  width: 100%; height: 100%;
  transform: rotate(-90deg);
}
.stat-ring .ring-track {
  fill: none;
  stroke: var(--bs-tertiary-bg);
  stroke-width: 14;
}
.stat-ring .ring-fill {
  fill: none;
  stroke: url(#peRingGrad);
  stroke-width: 14;
  stroke-linecap: round;
  transition: stroke-dashoffset .8s var(--pe-ease);
}

/* v2.6.10 — Ring gradient stops theme-aware.  El SVG `<stop>` no soporta
   `stop-color: var(--xxx)` cross-browser de forma fiable, pero SI soporta
   stop-color via CSS rule (selectores normales).  Aplicamos los stops
   per theme para que el ring de vacaciones tenga la firma cromática
   del tema activo (atlantico=indigo, factorial=rose, nimbus=cyan). */
.pe-ring-stop-1 { stop-color: #6366f1; }
.pe-ring-stop-2 { stop-color: #8b5cf6; }
.pe-ring-stop-3 { stop-color: #d946ef; }
[data-color-theme="factorial"] .pe-ring-stop-1 { stop-color: #f43f5e; }
[data-color-theme="factorial"] .pe-ring-stop-2 { stop-color: #ec4899; }
[data-color-theme="factorial"] .pe-ring-stop-3 { stop-color: #be185d; }
[data-color-theme="factorial"][data-bs-theme="dark"] .pe-ring-stop-1 { stop-color: #fb7185; }
[data-color-theme="factorial"][data-bs-theme="dark"] .pe-ring-stop-2 { stop-color: #f472b6; }
[data-color-theme="factorial"][data-bs-theme="dark"] .pe-ring-stop-3 { stop-color: #ec4899; }
[data-color-theme="nimbus"] .pe-ring-stop-1 { stop-color: #06b6d4; }
[data-color-theme="nimbus"] .pe-ring-stop-2 { stop-color: #0891b2; }
[data-color-theme="nimbus"] .pe-ring-stop-3 { stop-color: #0e7490; }
[data-color-theme="nimbus"][data-bs-theme="dark"] .pe-ring-stop-1 { stop-color: #67e8f9; }
[data-color-theme="nimbus"][data-bs-theme="dark"] .pe-ring-stop-2 { stop-color: #22d3ee; }
[data-color-theme="nimbus"][data-bs-theme="dark"] .pe-ring-stop-3 { stop-color: #06b6d4; }

.stat-ring-content {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
}
/* v2.6.10 — número grande con gradient text-clip premium theme-aware.
   Antes: heredaba `color: var(--bs-body-color)` (negro/oscuro flat).
   Ahora: bg-clip text con `var(--pe-grad-1)` (atlantico=indigo→fuchsia,
   factorial=rose→fuchsia, nimbus=cyan→teal).  Fallback `color` opaco
   en caso de que el browser no soporte background-clip:text. */
.stat-ring-value {
  font-size: 1.75rem;
  font-weight: 800;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  background: var(--pe-grad-1);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Fallback for browsers without bg-clip: text */
  -webkit-text-fill-color: transparent;
}
/* Fallback puro si el browser realmente no soporta nada de lo anterior */
@supports not (background-clip: text) {
  .stat-ring-value {
    color: var(--bs-primary);
    background: none;
  }
}
.stat-ring-label {
  font-size: .6875rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 600;
  color: var(--bs-secondary-color);
  margin-top: 4px;
}

/* Vacation hero (Vacaciones section) */
.vac-hero {
  display: grid;
  gap: 20px;
  grid-template-columns: 1fr;
  padding: 22px 24px;
  background:
    radial-gradient(70% 120% at 0% 50%, rgba(139,92,246, .14), transparent 60%),
    radial-gradient(70% 120% at 100% 50%, rgba(99,102,241, .12), transparent 60%),
    var(--tt-surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--pe-radius-xl);
  margin-bottom: 18px;
  position: relative;
  overflow: hidden;
}
.vac-hero::before {
  content: '';
  position: absolute; inset: 0 0 auto 0;
  height: 2px;
  background: var(--pe-grad-1);
}
@media (min-width: 768px) {
  .vac-hero { grid-template-columns: auto 1fr; align-items: center; gap: 28px; }
}
.vac-hero-stats {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.vac-hero-stats .stat-card {
  padding: 14px 16px;
  background: rgba(var(--bs-body-bg), .55);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--pe-radius-md);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
[data-bs-theme="dark"] .vac-hero-stats .stat-card {
  background: rgba(255,255,255,.025);
}
.vac-hero-stats .stat-card .v {
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -.025em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.vac-hero-stats .stat-card .l {
  font-size: .6875rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 600;
  color: var(--bs-secondary-color);
  margin-top: 4px;
}
.vac-hero-year {
  font-size: 1.0625rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}
.vac-hero-year .year-nav {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.vac-hero-year .year-nav .btn {
  width: 28px; height: 28px;
  padding: 0;
  display: grid; place-items: center;
  border-radius: 8px;
  border: 1px solid var(--bs-border-color);
  background: var(--tt-surface);
  color: var(--bs-body-color);
}
.vac-hero-year .year-nav .btn:hover {
  background: rgba(var(--bs-primary-rgb), .08);
  border-color: rgba(var(--bs-primary-rgb), .25);
}
/* v2.6.9 — eyebrow usa var(--tt-vac) theme-aware en lugar de violet
   hardcoded.  --tt-vac es theme-aware: atlantico=teal, factorial=rose,
   nimbus=cyan.  Fallback al violet original (#8b5cf6) si --tt-vac no
   está definido (defensivo en caso de admin.html sin themes loaded). */
.vac-hero-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: .6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--tt-vac, #8b5cf6);
  margin-bottom: 8px;
}
/* Dark: --tt-vac ya está reasignado por tema; el fallback violet
   solo dispara cuando no hay --tt-vac (sin themes cargados). */
[data-bs-theme="dark"] .vac-hero-eyebrow { color: var(--tt-vac, #a78bfa); }

@media (max-width: 575.98px) {
  .vac-hero { padding: 16px; border-radius: var(--pe-radius-lg); }
  .vac-hero-stats { gap: 8px; }
  .vac-hero-stats .stat-card { padding: 10px 12px; }
  .vac-hero-stats .stat-card .v { font-size: 1.1875rem; }
  .stat-ring { width: 112px; height: 112px; }
  .stat-ring-value { font-size: 1.375rem; }
}

/* ─────────────────────────────────────────────────────────────
   ACTIVITY ROW · fila premium para listas (recent entries, etc.)
   ───────────────────────────────────────────────────────────── */
.activity-row-pro {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 10px 12px;
  border-radius: 10px;
  border: 1px solid transparent;
  transition: background .15s var(--pe-ease),
              border-color .15s var(--pe-ease);
}
.activity-row-pro:hover {
  background: rgba(var(--bs-primary-rgb), .04);
  border-color: rgba(var(--bs-primary-rgb), .10);
}
.activity-row-pro + .activity-row-pro { margin-top: 4px; }
.activity-row-pro .icon-dot {
  width: 36px; height: 36px;
  border-radius: 10px;
  display: grid; place-items: center;
  background: rgba(var(--bs-primary-rgb), .10);
  color: var(--bs-primary);
  font-size: .95rem;
}
.activity-row-pro .icon-dot.success { background: rgba(var(--bs-success-rgb), .10); color: var(--bs-success); }
.activity-row-pro .icon-dot.warning { background: rgba(var(--bs-warning-rgb), .12); color: var(--bs-warning); }
.activity-row-pro .icon-dot.danger  { background: rgba(var(--bs-danger-rgb), .10); color: var(--bs-danger); }
.activity-row-pro .meta-main {
  font-weight: 600;
  font-size: .875rem;
  color: var(--bs-body-color);
}
.activity-row-pro .meta-sub {
  font-size: .75rem;
  color: var(--bs-secondary-color);
  font-variant-numeric: tabular-nums;
}
.activity-row-pro .meta-end {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: .875rem;
}

/* ─────────────────────────────────────────────────────────────
   ANNOUNCEMENT CARD PRO · comunicado premium
   ───────────────────────────────────────────────────────────── */
.announce-pro {
  position: relative;
  background: var(--tt-surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--pe-radius-lg);
  padding: 18px 20px;
  cursor: pointer;
  transition: transform .2s var(--pe-ease),
              box-shadow .2s var(--pe-ease),
              border-color .2s var(--pe-ease);
  overflow: hidden;
}
.announce-pro + .announce-pro { margin-top: 14px; }
.announce-pro::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--bs-tertiary-bg);
  transition: background .2s var(--pe-ease);
}
.announce-pro:hover {
  transform: translateY(-1px);
  border-color: rgba(var(--bs-primary-rgb), .25);
  box-shadow: var(--pe-card-lift);
}
.announce-pro:hover::before { background: var(--pe-grad-1); }
.announce-pro.pinned {
  background:
    radial-gradient(60% 100% at 0% 50%, rgba(var(--bs-warning-rgb), .08), transparent 60%),
    var(--tt-surface);
}
.announce-pro.pinned::before { background: var(--pe-grad-warm); }
.announce-pro-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 8px;
  align-items: flex-start;
}
.announce-pro-title {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -.015em;
  color: var(--bs-body-color);
  line-height: 1.35;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.announce-pro-title .bi-pin-fill {
  color: var(--bs-warning);
  font-size: .875rem;
  flex-shrink: 0;
}
.announce-pro-date {
  font-size: .75rem;
  color: var(--bs-secondary-color);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  white-space: nowrap;
  flex-shrink: 0;
}
.announce-pro-author {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: .75rem;
  color: var(--bs-secondary-color);
  margin-bottom: 8px;
}
.announce-pro-author .avatar-xs {
  width: 22px; height: 22px;
  border-radius: 50%;
  background: rgba(var(--bs-primary-rgb), .12);
  color: var(--bs-primary);
  font-size: .625rem;
  font-weight: 800;
  display: grid; place-items: center;
}
.announce-pro-body {
  font-size: .875rem;
  color: var(--bs-body-color);
  line-height: 1.55;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ─────────────────────────────────────────────────────────────
   CALENDAR PRO · upgrade del .cal-grid existente cuando se
   añade la clase `.cal-grid-pro` al grid
   ───────────────────────────────────────────────────────────── */
.cal-pro-wrap {
  position: relative;
  background: var(--tt-surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--pe-radius-xl);
  padding: 18px;
  overflow: hidden;
}
.cal-pro-wrap::before {
  content: '';
  position: absolute; inset: 0 0 auto 0;
  height: 2px;
  background: var(--pe-grad-1);
  opacity: .6;
}
.cal-pro-wrap .cal-grid { gap: 6px; }
.cal-pro-wrap .cal-head {
  font-size: .6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--bs-secondary-color);
  padding: 6px 0;
}
.cal-pro-wrap .cal-day {
  border-radius: var(--pe-radius-md);
  transition: background .15s var(--pe-ease),
              border-color .15s var(--pe-ease),
              transform .15s var(--pe-ease);
}
.cal-pro-wrap .cal-day:hover {
  background: rgba(var(--bs-primary-rgb), .04);
  border-color: rgba(var(--bs-primary-rgb), .14);
  transform: translateY(-1px);
}
.cal-pro-wrap .cal-day.today {
  background: rgba(var(--bs-primary-rgb), .08);
  border-color: rgba(var(--bs-primary-rgb), .35);
  box-shadow: 0 0 0 2px rgba(var(--bs-primary-rgb), .15);
}
.cal-pro-wrap .cal-day.today .num {
  color: var(--bs-primary);
  font-weight: 800;
}
.cal-pro-wrap .cal-day.muted { opacity: .35; }
.cal-pro-wrap .cal-day.holiday {
  background: linear-gradient(135deg, rgba(var(--bs-warning-rgb), .08) 0%, transparent 100%);
}

.cal-pro-legend {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--bs-border-color);
}
.cal-pro-legend .legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: .75rem;
  color: var(--bs-secondary-color);
  font-weight: 500;
}
.cal-pro-legend .legend-item .dot {
  width: 10px; height: 10px;
  border-radius: 3px;
  flex-shrink: 0;
}

/* ─────────────────────────────────────────────────────────────
   EMPTY STATE PRO · estado vacío premium con illustration
   ───────────────────────────────────────────────────────────── */
.empty-pro {
  text-align: center;
  padding: 56px 24px;
  border-radius: var(--pe-radius-lg);
  background:
    radial-gradient(60% 90% at 50% 0%, rgba(var(--bs-primary-rgb), .08), transparent 70%),
    var(--tt-surface);
  border: 1px dashed var(--bs-border-color);
  position: relative;
  overflow: hidden;
}
.empty-pro .empty-icon {
  width: 64px; height: 64px;
  margin: 0 auto 16px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(var(--bs-primary-rgb), .10);
  color: var(--bs-primary);
  font-size: 1.75rem;
  position: relative;
}
.empty-pro .empty-icon::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 1px solid rgba(var(--bs-primary-rgb), .15);
  animation: pePing 2s var(--pe-ease) infinite;
}
@keyframes pePing {
  0%   { transform: scale(1); opacity: 1; }
  100% { transform: scale(1.6); opacity: 0; }
}
.empty-pro h4 {
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: -.015em;
  margin: 0 0 6px;
  color: var(--bs-body-color);
}
.empty-pro p {
  font-size: .875rem;
  color: var(--bs-secondary-color);
  margin: 0;
  max-width: 36ch;
  margin-inline: auto;
}

/* SVG illustration variant: cuando TTui.emptyState pasa una key con
   illustration en el catálogo (clock/calendar/megaphone/folder/…),
   se renderiza .empty-pro-illust (120×120) en lugar del icon-dot.
   El SVG ya viene tinted con var(--bs-primary). */
.empty-pro .empty-pro-illust {
  width: 128px;
  height: 128px;
  margin: 0 auto 16px;
  display: grid;
  place-items: center;
  position: relative;
  filter: drop-shadow(0 8px 20px rgba(var(--bs-primary-rgb), .12));
  animation: peFloat 4s ease-in-out infinite;
}
.empty-pro .empty-pro-illust svg {
  width: 100%; height: 100%;
}
@keyframes peFloat {
  0%,100% { transform: translateY(0); }
  50%     { transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
  .empty-pro .empty-pro-illust { animation: none; }
}

/* Override legacy `.empty .title` / `.empty .subtitle` que aparecen en
   style.css (líneas 715-722, 8555-8565) cuando el mismo nodo trae
   ambas clases `.empty .empty-pro`.  Forzamos jerarquía premium. */
.empty.empty-pro { gap: 0; }
.empty.empty-pro h4 { font-size: 1rem; font-weight: 700; line-height: 1.35; }
.empty.empty-pro p  { font-size: .875rem; line-height: 1.5; }

/* ═════════════════════════════════════════════════════════════
   v2.6.3 · STATUS BADGES PREMIUM (SaaS / Stripe / Linear-tier)
   -------------------------------------------------------------
   Bug previo:
     · style.css L3136 ponía `box-shadow: 0 0 0 2px currentColor`
       en el dot → donut weird (halo = mismo color que el texto).
     · `color: var(--bs-danger-text-emphasis)` (muted maroon) sobre
       fondo rosa apagado → look genérico, no premium.

   Premium redesign:
     · Gradient sutil 135° en el fondo (depth)
     · Border-color con alpha 25% del tono (definición premium)
     · Dot solid + halo externo TRANSPARENTE low-alpha (glow real)
     · Glow saturado adicional sólo en variants activas (success,
       danger) para sensación de "live status"
     · Letter-spacing 0.06em (Stripe-tier typographic refinement)
     · `font-feature-settings: 'cv11', 'ss01'` (Inter ligatures)
     · Animación pulse sutil en el dot warning/pending
     · Dark mode: tonos más vibrantes (rose-300, emerald-300…)
   ═════════════════════════════════════════════════════════════ */
.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px 4px 10px;
  border-radius: 999px;
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  line-height: 1.45;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'cv11', 'ss01';
  white-space: nowrap;
  border: 1px solid var(--bs-border-color);
  background: var(--bs-tertiary-bg);
  color: var(--bs-secondary-color);
  transition:
    transform .15s var(--pe-ease),
    box-shadow .15s var(--pe-ease),
    background .15s var(--pe-ease);
}
/* Dot reset — anula box-shadow currentColor (efecto donut) de style.css */
.status-badge::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
  background: currentColor;
  box-shadow: none;
  opacity: 1;
}
.status-badge:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 10px -4px rgba(15, 23, 42, .12);
}
[data-bs-theme="dark"] .status-badge:hover {
  box-shadow: 0 4px 10px -4px rgba(0, 0, 0, .50);
}

/* ─── Variant: SUCCESS / APROBADA / CERRADA ─── */
.status-badge.success {
  background: linear-gradient(135deg,
    rgba(var(--bs-success-rgb), .14) 0%,
    rgba(var(--bs-success-rgb), .07) 100%);
  color: var(--bs-success);
  border-color: rgba(var(--bs-success-rgb), .28);
}
.status-badge.success::before {
  background: var(--bs-success);
  box-shadow:
    0 0 0 3px rgba(var(--bs-success-rgb), .18),
    0 0 6px rgba(var(--bs-success-rgb), .55);
}
[data-bs-theme="dark"] .status-badge.success {
  background: linear-gradient(135deg,
    rgba(var(--bs-success-rgb), .22) 0%,
    rgba(var(--bs-success-rgb), .12) 100%);
  color: #6ee7b7;
  border-color: rgba(var(--bs-success-rgb), .38);
}

/* ─── Variant: WARNING / PENDIENTE ─── */
.status-badge.warning {
  background: linear-gradient(135deg,
    rgba(var(--bs-warning-rgb), .16) 0%,
    rgba(var(--bs-warning-rgb), .08) 100%);
  color: #b45309;
  border-color: rgba(var(--bs-warning-rgb), .30);
}
.status-badge.warning::before {
  background: var(--bs-warning);
  box-shadow:
    0 0 0 3px rgba(var(--bs-warning-rgb), .22),
    0 0 6px rgba(var(--bs-warning-rgb), .55);
  animation: pulseDot 2.2s var(--pe-ease) infinite;
}
[data-bs-theme="dark"] .status-badge.warning {
  background: linear-gradient(135deg,
    rgba(var(--bs-warning-rgb), .22) 0%,
    rgba(var(--bs-warning-rgb), .12) 100%);
  color: #fcd34d;
  border-color: rgba(var(--bs-warning-rgb), .40);
}
@keyframes pulseDot {
  0%, 60%, 100% { transform: scale(1); }
  30%           { transform: scale(1.18); }
}
@media (prefers-reduced-motion: reduce) {
  .status-badge.warning::before { animation: none; }
}

/* ─── Variant: DANGER / RECHAZADA ─── */
.status-badge.danger {
  background: linear-gradient(135deg,
    rgba(var(--bs-danger-rgb), .14) 0%,
    rgba(var(--bs-danger-rgb), .07) 100%);
  color: var(--bs-danger);
  border-color: rgba(var(--bs-danger-rgb), .28);
}
.status-badge.danger::before {
  background: var(--bs-danger);
  box-shadow:
    0 0 0 3px rgba(var(--bs-danger-rgb), .20),
    0 0 6px rgba(var(--bs-danger-rgb), .50);
}
[data-bs-theme="dark"] .status-badge.danger {
  background: linear-gradient(135deg,
    rgba(var(--bs-danger-rgb), .22) 0%,
    rgba(var(--bs-danger-rgb), .12) 100%);
  color: #fca5a5;
  border-color: rgba(var(--bs-danger-rgb), .40);
}

/* ─── Variant: INFO ─── */
.status-badge.info {
  background: linear-gradient(135deg,
    rgba(var(--bs-info-rgb), .14) 0%,
    rgba(var(--bs-info-rgb), .07) 100%);
  color: var(--bs-info);
  border-color: rgba(var(--bs-info-rgb), .28);
}
.status-badge.info::before {
  background: var(--bs-info);
  box-shadow:
    0 0 0 3px rgba(var(--bs-info-rgb), .18),
    0 0 6px rgba(var(--bs-info-rgb), .50);
}
[data-bs-theme="dark"] .status-badge.info {
  background: linear-gradient(135deg,
    rgba(var(--bs-info-rgb), .22) 0%,
    rgba(var(--bs-info-rgb), .12) 100%);
  color: #93c5fd;
  border-color: rgba(var(--bs-info-rgb), .40);
}

/* ─── Variant: PRIMARY ─── */
.status-badge.primary {
  background: linear-gradient(135deg,
    rgba(var(--bs-primary-rgb), .14) 0%,
    rgba(var(--bs-primary-rgb), .07) 100%);
  color: var(--bs-primary);
  border-color: rgba(var(--bs-primary-rgb), .28);
}
.status-badge.primary::before {
  background: var(--bs-primary);
  box-shadow:
    0 0 0 3px rgba(var(--bs-primary-rgb), .18),
    0 0 6px rgba(var(--bs-primary-rgb), .50);
}
[data-bs-theme="dark"] .status-badge.primary {
  background: linear-gradient(135deg,
    rgba(var(--bs-primary-rgb), .24) 0%,
    rgba(var(--bs-primary-rgb), .14) 100%);
  color: #a5b4fc;
  border-color: rgba(var(--bs-primary-rgb), .42);
}

/* ─── Variant: MUTED / NEUTRAL ─── */
.status-badge.muted {
  background: var(--bs-tertiary-bg);
  color: var(--bs-secondary-color);
  border-color: var(--bs-border-color);
}
.status-badge.muted::before {
  background: var(--bs-secondary-color);
  opacity: .65;
  box-shadow: 0 0 0 3px var(--bs-border-color);
}
[data-bs-theme="dark"] .status-badge.muted {
  background: rgba(255, 255, 255, .04);
  color: var(--bs-secondary-color);
  border-color: rgba(255, 255, 255, .08);
}

/* ─── Tablas: tabular nums + cursor-help cuando hay tooltip ─── */
.table .status-badge {
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}
.status-badge[title] { cursor: help; }

/* ─────────────────────────────────────────────────────────────
   KPI LEGACY UPGRADE · halo + tabular-nums + hover-lift
   ---------------------------------------------------------
   No todas las secciones se migran a .kpi-pro (mantener compat).
   Estas reglas dan el FEEL premium a `.kpi` existente: gradient
   halo detrás del icono, hover-lift y números tabulares.  Cambio
   sólo visual, sin tocar el markup en JS.
   ───────────────────────────────────────────────────────────── */
.kpi {
  position: relative;
  isolation: isolate;
  transition: transform .25s var(--pe-ease),
              box-shadow .25s var(--pe-ease),
              border-color .25s var(--pe-ease);
}
.kpi::before {
  content: '';
  position: absolute;
  top: 14px; left: 14px;
  width: 60px; height: 60px;
  background: rgba(var(--bs-primary-rgb), .35);
  border-radius: 50%;
  filter: blur(28px);
  opacity: .14;
  z-index: -1;
  pointer-events: none;
  transition: opacity .3s var(--pe-ease);
}
.kpi:hover::before { opacity: .26; }
.kpi:hover {
  transform: translateY(-2px);
  box-shadow: var(--pe-card-lift);
  border-color: rgba(var(--bs-primary-rgb), .22);
}
.kpi .value {
  font-variant-numeric: tabular-nums;
  letter-spacing: -.025em;
}

/* Halo color por variante del icon — herencia automática para que el
   blur detrás del icon (success/warning/danger/info) matchee el tono. */
.kpi:has(.icon.success)::before { background: rgba(var(--bs-success-rgb), .38); }
.kpi:has(.icon.warning)::before { background: rgba(var(--bs-warning-rgb), .40); }
.kpi:has(.icon.danger)::before  { background: rgba(var(--bs-danger-rgb),  .38); }
.kpi:has(.icon.info)::before    { background: rgba(var(--bs-info-rgb),    .38); }
.kpi:has(.icon.purple)::before  { background: rgba(139,92,246, .40); }

/* ─────────────────────────────────────────────────────────────
   PILL PREMIUM · status pills más refinados
   ───────────────────────────────────────────────────────────── */
.pill-pro {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: .6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
}
.pill-pro.success { background: rgba(var(--bs-success-rgb), .12); color: var(--bs-success); }
.pill-pro.warning { background: rgba(var(--bs-warning-rgb), .14); color: var(--bs-warning); }
.pill-pro.danger  { background: rgba(var(--bs-danger-rgb), .12);  color: var(--bs-danger); }
.pill-pro.info    { background: rgba(var(--bs-info-rgb), .12);    color: var(--bs-info); }
.pill-pro.violet  { background: rgba(139,92,246, .14); color: #7c3aed; }
[data-bs-theme="dark"] .pill-pro.violet { color: #a78bfa; }
.pill-pro .bi { font-size: .7rem; }

/* ─────────────────────────────────────────────────────────────
   PUNCH CARD UPGRADE · refinado sutil del fichaje
   Usa la clase `.punch-card.punch-card-pro` para layer extra
   sin romper compat con la versión actual.

   v2.6.6 (fix contraste): el timer mantiene `color: #fff` que
   hereda de `.punch-card { color: #fff }` (style.css L481).
   La versión previa (v2.6.0) aplicaba un gradient text-fill
   violet→fuchsia via `background-clip:text` que en los temas
   Nimbus (cyan/teal) y Factorial (rose) bajaba el contraste
   a niveles ilegibles.  Ahora aplicamos sólo refinamiento
   tipográfico (tabular-nums, letter-spacing) + un text-shadow
   con doble capa que da depth premium sin perder legibilidad:
     · capa 1: drop sharp 1px,  rgba(0,0,0,.22) → leve sombra
     · capa 2: glow blur 16px,  rgba(0,0,0,.28) → halo de profundidad
   Pasa WCAG AAA (>7:1 contrast ratio) sobre los 3 temas:
     · Atlántico indigo  · Factorial rose  · Nimbus cyan
   ───────────────────────────────────────────────────────────── */
.punch-card-pro {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
.punch-card-pro::before {
  content: '';
  position: absolute;
  inset: -50% 0 50% -50%;
  background: var(--pe-grad-1);
  opacity: .07;
  filter: blur(80px);
  z-index: -1;
  pointer-events: none;
}
.punch-card-pro .timer {
  /* color: #fff hereda del padre .punch-card → restauración 1:1 del
     comportamiento previo a v2.6.0 (no override, sólo refinamos
     typography y depth). */
  font-variant-numeric: tabular-nums;
  letter-spacing: -.04em;
  text-shadow:
    0 1px 2px  rgba(0, 0, 0, .22),
    0 2px 16px rgba(0, 0, 0, .28);
}

/* ─────────────────────────────────────────────────────────────
   ANIMACIONES · stagger entrance suave
   ───────────────────────────────────────────────────────────── */
.pe-stagger > * {
  animation: peSlideUp .45s var(--pe-ease) backwards;
}
.pe-stagger > *:nth-child(1) { animation-delay: 30ms; }
.pe-stagger > *:nth-child(2) { animation-delay: 60ms; }
.pe-stagger > *:nth-child(3) { animation-delay: 90ms; }
.pe-stagger > *:nth-child(4) { animation-delay: 120ms; }
.pe-stagger > *:nth-child(5) { animation-delay: 150ms; }
.pe-stagger > *:nth-child(6) { animation-delay: 180ms; }
.pe-stagger > *:nth-child(7) { animation-delay: 210ms; }
.pe-stagger > *:nth-child(8) { animation-delay: 240ms; }
.pe-stagger > *:nth-child(n+9) { animation-delay: 270ms; }
@keyframes peSlideUp {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .pe-stagger > * { animation: none; }
}

/* ─────────────────────────────────────────────────────────────
   JORNADAS UPGRADE · banner pendiente premium + row spacing
   ───────────────────────────────────────────────────────────── */
.pending-banner-pro {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  border-radius: var(--pe-radius-lg);
  background: linear-gradient(135deg, rgba(var(--bs-warning-rgb), .10) 0%, rgba(var(--bs-warning-rgb), .04) 100%);
  border: 1px solid rgba(var(--bs-warning-rgb), .25);
  border-left-width: 3px;
  position: relative;
  overflow: hidden;
}
.pending-banner-pro::before {
  content: '';
  position: absolute;
  top: -50%; left: -10%;
  width: 200px; height: 200px;
  background: var(--bs-warning);
  filter: blur(80px);
  opacity: .08;
  pointer-events: none;
}
.pending-banner-pro .icon-wrap {
  width: 42px; height: 42px;
  border-radius: 12px;
  background: rgba(var(--bs-warning-rgb), .15);
  color: var(--bs-warning);
  display: grid; place-items: center;
  font-size: 1.1rem;
  flex-shrink: 0;
}
.pending-banner-pro .text-wrap { flex: 1; min-width: 0; }
.pending-banner-pro .text-wrap .title {
  font-weight: 700;
  font-size: .875rem;
  color: var(--bs-body-color);
  margin-bottom: 2px;
}
.pending-banner-pro .text-wrap .sub {
  font-size: .8125rem;
  color: var(--bs-secondary-color);
}

/* ─────────────────────────────────────────────────────────────
   DASHBOARD WELCOME PRO · saludo dinámico premium
   ───────────────────────────────────────────────────────────── */
.welcome-hero {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 20px 24px;
  margin-bottom: 18px;
  background:
    radial-gradient(70% 120% at 0% 0%, rgba(var(--bs-primary-rgb), .12), transparent 60%),
    var(--tt-surface);
  border: 1px solid var(--bs-border-color);
  border-radius: var(--pe-radius-xl);
  position: relative;
  overflow: hidden;
}
.welcome-hero::before {
  content: '';
  position: absolute; inset: 0 0 auto 0;
  height: 2px;
  background: var(--pe-grad-1);
}
.welcome-hero-avatar {
  width: 56px; height: 56px;
  border-radius: 50%;
  background: var(--pe-grad-1);
  color: #fff;
  display: grid; place-items: center;
  font-size: 1.25rem;
  font-weight: 800;
  letter-spacing: .01em;
  flex-shrink: 0;
  box-shadow: 0 6px 14px -4px rgba(var(--bs-primary-rgb), .45);
}
.welcome-hero-text { flex: 1; min-width: 0; }
.welcome-hero-greet {
  font-size: 1.375rem;
  font-weight: 800;
  letter-spacing: -.025em;
  color: var(--bs-body-color);
  line-height: 1.2;
}
.welcome-hero-date {
  font-size: .875rem;
  color: var(--bs-secondary-color);
  font-weight: 500;
  margin-top: 2px;
  /* v2.6.89 — Eliminado `text-transform: capitalize`: capitalizaba TODAS
     las palabras ("Domingo, 17 De Mayo De 2026"), pero en español los
     conectores "de" deben ir en minúscula. La capitalización del weekday
     (solo el primer carácter) se hace ahora en JS antes de asignar el
     textContent (admin.js + app.js), respetando reglas de cada locale. */
}
.welcome-hero-quick {
  display: flex;
  gap: 16px;
  flex-shrink: 0;
}
.welcome-hero-quick .qstat { text-align: right; }
.welcome-hero-quick .qstat .v {
  font-size: 1rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.02em;
}
.welcome-hero-quick .qstat .l {
  font-size: .625rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--bs-secondary-color);
  font-weight: 600;
}
@media (max-width: 575.98px) {
  .welcome-hero { padding: 16px; gap: 12px; }
  .welcome-hero-avatar { width: 44px; height: 44px; font-size: 1rem; }
  /* v2.6.89 — En mobile, el greeting puede contener un badge inline ("Admin
     [ADMINISTRADOR]") que en viewports < 400px provoca overflow/cramping
     o líneas con corte feo. Ajustes: (a) tamaño un poco menor para más
     respiro, (b) line-height generoso para que cuando el badge wrappee a
     una segunda línea no se solape con la fecha de abajo, (c) min-width:0
     en el texto contenedor para que ellipsis funcione si el nombre es muy
     largo. */
  .welcome-hero-greet { font-size: 1.0625rem; line-height: 1.35; }
  .welcome-hero-text { min-width: 0; }
  .welcome-hero-date { font-size: .8125rem; margin-top: 4px; }
  .welcome-hero-quick { display: none; }
}

/* ════════════════════════════════════════════════════════════
   v2.6.11 · SECTION HERO BRIDGE · cabecera premium SaaS
   ------------------------------------------------------------
   Aplica el look de `.section-hero` sobre el markup legacy
   `.section-header` SIN tocar HTML.  Scope universal (admin +
   employee panels) porque premium-employee.css se carga en ambos
   (admin.html línea 24, app.html línea 22).

   Componentes que añade:
     · Top gradient stripe (3px, --pe-grad-1, theme-aware)
     · Decoración floating glow blur detrás del título (::after)
     · Title con bg-clip text gradient (premium SaaS feel)
     · Sub con color secondary + tracking refinado
     · Padding generoso + border-radius lg
     · Opt-in eyebrow via `data-eyebrow="EQUIPO"` (futuro)

   Scope: SÓLO `.content > section > .section-header` para no
   afectar headers anidados en cards o modales.  Compat preservada
   con la rule existente `.content .section-header` de style.css.
   ════════════════════════════════════════════════════════════ */
.content > section > .section-header {
  position: relative;
  padding: 22px 24px;
  margin: 0 0 22px;
  /* v2.6.12 — Forzar column direction en el scope premium (.content > section).
     Estaba heredando `flex-direction: row + align-items: center` de style.css
     a partir de 768px, lo que hacía colapsar el título a ~280px en viewports
     1024-1399 cuando .actions tiene muchos controles (jornadas con 6 controles,
     turnos con 7). Patrón SaaS moderno (Linear/Stripe/Notion): título arriba
     en full-width, acciones debajo. En desktop ancho (≥1400px) recuperamos
     el layout horizontal title-left / actions-right vía media query abajo. */
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  flex-wrap: nowrap;
  gap: 12px;
  min-height: auto;
  background: linear-gradient(
    180deg,
    var(--tt-surface, var(--bs-body-bg)) 0%,
    color-mix(in srgb, var(--bs-primary) 2.5%, var(--tt-surface, var(--bs-body-bg))) 100%
  );
  border: 1px solid var(--bs-border-color);
  border-radius: 14px;
  overflow: hidden;
  isolation: isolate;
  transition: transform .25s var(--pe-ease, cubic-bezier(.2,.9,.2,1)),
              box-shadow .25s var(--pe-ease, cubic-bezier(.2,.9,.2,1)),
              border-color .25s var(--pe-ease, cubic-bezier(.2,.9,.2,1));
}
[data-bs-theme="dark"] .content > section > .section-header {
  background: linear-gradient(
    180deg,
    var(--tt-surface, var(--bs-body-bg)) 0%,
    color-mix(in srgb, var(--bs-primary) 6%, var(--tt-surface, var(--bs-body-bg))) 100%
  );
}

/* Top gradient stripe (premium signature) */
.content > section > .section-header::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--pe-grad-1, var(--tt-grad-primary, linear-gradient(135deg, var(--bs-primary), color-mix(in srgb, var(--bs-primary) 60%, #fff))));
  opacity: .92;
  z-index: 0;
}

/* Decoración floating glow detrás del título */
.content > section > .section-header::after {
  content: '';
  position: absolute;
  top: -50px;
  right: -50px;
  width: 220px;
  height: 220px;
  background: radial-gradient(
    closest-side,
    rgba(var(--bs-primary-rgb), .14) 0%,
    rgba(var(--bs-primary-rgb), 0) 75%
  );
  pointer-events: none;
  z-index: -1;
  filter: blur(6px);
}

/* v2.6.12 — Reset flex sizing for premium scope (column direction).
   El style.css:8987 aplica `flex: 1 1 260px` a `.section-header > div:first-child`
   pensando en ROW direction (basis=width). Al usar column direction en el
   scope premium, basis pasa a ser HEIGHT → reserva 260px verticales vacíos
   bajo el título. Aquí restauramos sizing natural.
   `!important` defensivo: este rule debe ganar sobre style.css:8987 (mismo
   nivel de specificity en algunas variantes legacy) y sobre cualquier rule
   añadida posteriormente que volviera a aplicar el patrón row direction.
   A ≥1400px (donde recuperamos row direction), la media query de abajo
   vuelve a aplicar flex: 1 1 auto correcto para horizontal. */
.content > section > .section-header > div:first-child {
  flex: 0 0 auto !important;
  min-width: 0;
  align-self: stretch;
}
.content > section > .section-header > .actions {
  flex: 0 0 auto !important;
  align-self: stretch;
}

/* v2.6.12 — Buttons / inputs as DIRECT children of section-header (no .actions
   wrapper) deben aparecer con tamaño natural en bottom-left, NO estirados a
   full-width como hace `align-items: stretch` por defecto en column direction.
   Afecta a sec-cobertura, sec-rotaciones, sec-marketplace, sec-ubicaciones,
   sec-bancohoras y similares cuyo HTML tiene `<button>` o `<select>` como
   hermano directo del título-div sin pasar por `.actions`. */
.content > section > .section-header > .btn,
.content > section > .section-header > button,
.content > section > .section-header > select,
.content > section > .section-header > input,
.content > section > .section-header > .form-select,
.content > section > .section-header > .form-control,
.content > section > .section-header > .btn-group,
.content > section > .section-header > .input-group {
  align-self: flex-start;
  flex: 0 0 auto;
}

/* v2.6.12 — Form controls dentro de `.actions`: Bootstrap aplica `width: 100%`
   por defecto a `.form-control` / `.form-select`. Eso, combinado con la
   `.actions` div ahora estirada a full-width por `align-items: stretch`,
   hacía que un solo input ocupara todo el row y forzara a los demás
   controles (botones) a wrappear a la siguiente línea verticalmente.
   Fix: width auto + min-width sensato para que respeten el flex inline. */
.content > section > .section-header > .actions > .form-control,
.content > section > .section-header > .actions > .form-select,
.content > section > .section-header > .actions > .input-group {
  width: auto;
  flex: 0 1 auto;
  max-width: 280px;
}
/* Inputs de tipo date/month tienen min-content más estrecho que su placeholder;
   forzamos ~180px para que "mayo de 2026" no se vea apretado. */
.content > section > .section-header > .actions > input[type="month"],
.content > section > .section-header > .actions > input[type="date"],
.content > section > .section-header > .actions > input[type="datetime-local"],
.content > section > .section-header > .actions > input[type="week"] {
  min-width: 180px;
}

/* Title premium: gradient text-clip theme-aware */
.content > section > .section-header > div:first-child > .section-title {
  font-size: 1.375rem;
  font-weight: 800;
  letter-spacing: -.028em;
  line-height: 1.15;
  background: var(--pe-grad-1, var(--tt-grad-primary, linear-gradient(135deg, var(--bs-primary), color-mix(in srgb, var(--bs-primary) 70%, #fff))));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  margin-bottom: 4px;
}
/* Fallback para browsers sin bg-clip:text */
@supports not (background-clip: text) {
  .content > section > .section-header > div:first-child > .section-title {
    color: var(--bs-primary);
    background: none;
  }
}

/* Sub refinado */
.content > section > .section-header > div:first-child > .section-sub {
  font-size: .875rem;
  color: var(--bs-secondary-color);
  margin: 0;
  letter-spacing: -.005em;
  line-height: 1.45;
  max-width: 64ch;
}

/* Quitar el underline de hover legacy de style.css que choca con gradient text */
.content > section > .section-header > div:first-child > .section-title::after {
  display: none !important;
}

/* Actions con z-index para quedar sobre la decoración */
.content > section > .section-header > .actions,
.content > section > .section-header .actions {
  position: relative;
  z-index: 1;
}

/* Eyebrow opt-in via [data-eyebrow] (sin cambios HTML, futuro) */
.content > section > .section-header[data-eyebrow] > div:first-child::before {
  content: attr(data-eyebrow);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: .6875rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--bs-primary);
  margin-bottom: 6px;
  padding-top: 4px;
}

/* Desktop: padding mayor + jerarquía visual reforzada */
@media (min-width: 768px) {
  .content > section > .section-header {
    padding: 26px 28px;
  }
  .content > section > .section-header > div:first-child > .section-title {
    font-size: 1.625rem;
  }
}
@media (min-width: 1200px) {
  .content > section > .section-header {
    padding: 30px 32px;
    margin-bottom: 26px;
  }
  .content > section > .section-header > div:first-child > .section-title {
    font-size: 1.75rem;
  }
  .content > section > .section-header > div:first-child > .section-sub {
    font-size: .9375rem;
  }
}

/* v2.6.12 — Desktop ancho (≥1400px): recuperar layout horizontal title-left
   / actions-right SOLO cuando hay espacio garantizado para evitar el bug
   del colapso. Por debajo, queda con flex-direction: column (default arriba). */
@media (min-width: 1400px) {
  .content > section > .section-header {
    flex-direction: row;
    align-items: flex-end;
    gap: 24px;
  }
  .content > section > .section-header > div:first-child {
    flex: 1 1 auto;
    min-width: 0;
  }
  .content > section > .section-header > .actions {
    flex-shrink: 0;
  }
}

/* Mobile compacto */
@media (max-width: 575.98px) {
  .content > section > .section-header {
    padding: 18px 20px;
    border-radius: 12px;
    margin-bottom: 18px;
  }
  .content > section > .section-header > div:first-child > .section-title {
    font-size: 1.125rem;
  }
  .content > section > .section-header > div:first-child > .section-sub {
    font-size: .8125rem;
  }
  .content > section > .section-header::after {
    width: 140px;
    height: 140px;
    top: -30px;
    right: -30px;
  }
}

/* Reduced motion: no transición */
@media (prefers-reduced-motion: reduce) {
  .content > section > .section-header {
    transition: none;
  }
}

/* ════════════════════════════════════════════════════════════
   v2.6.11 · BALANCE CARD PRO · theme-aware overtime/deficit banner
   ------------------------------------------------------------
   Reemplaza el card de balance en `renderProfile` (banco horas)
   que antes usaba colores teal/rose hardcoded (#0d9488 / #e11d48).
   Ahora usa --bs-success/--bs-danger con RGB para que respete
   atlántico/factorial/nimbus + dark mode automáticamente.
   ════════════════════════════════════════════════════════════ */
.balance-card-pro {
  position: relative;
  border-radius: 14px;
  overflow: hidden;
  isolation: isolate;
  border-left-width: 3px;
  border-left-style: solid;
}
.balance-card-pro.balance-up {
  background: rgba(var(--bs-success-rgb), .06);
  border-left-color: var(--bs-success);
}
.balance-card-pro.balance-down {
  background: rgba(var(--bs-danger-rgb), .06);
  border-left-color: var(--bs-danger);
}
[data-bs-theme="dark"] .balance-card-pro.balance-up {
  background: rgba(var(--bs-success-rgb), .12);
}
[data-bs-theme="dark"] .balance-card-pro.balance-down {
  background: rgba(var(--bs-danger-rgb), .12);
}

/* Icon halo: 44px gradient-ish con rgba para tinte */
.balance-card-pro-icon {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 12px;
  font-size: 1.3rem;
  flex-shrink: 0;
}
.balance-card-pro.balance-up .balance-card-pro-icon {
  background: rgba(var(--bs-success-rgb), .15);
  color: var(--bs-success);
}
.balance-card-pro.balance-down .balance-card-pro-icon {
  background: rgba(var(--bs-danger-rgb), .15);
  color: var(--bs-danger);
}

/* Tipografía interna */
.balance-card-pro-label {
  font-size: .65rem;
  text-transform: uppercase;
  letter-spacing: .06em;
  font-weight: 600;
  color: var(--bs-secondary-color);
  margin-bottom: 2px;
}
.balance-card-pro-value {
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -.025em;
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum';
  line-height: 1.15;
}
.balance-card-pro.balance-up .balance-card-pro-value {
  color: var(--bs-success);
}
.balance-card-pro.balance-down .balance-card-pro-value {
  color: var(--bs-danger);
}
.balance-card-pro-sub {
  font-size: .7rem;
  color: var(--bs-secondary-color);
  margin-top: 2px;
}

/* Mobile compacto */
@media (max-width: 575.98px) {
  .balance-card-pro-icon {
    width: 38px;
    height: 38px;
    font-size: 1.1rem;
  }
  .balance-card-pro-value { font-size: 1.25rem; }
}
