/* Vista "Oportunidades" (usuario registrado) — maqueta visual, capa propia sobre portal.css
   (reusa variables de color: --portal-border, --portal-muted, --portal-text). Acento propio
   indigo/violeta (distinto del azul de marketing) para diferenciar la experiencia de
   producto/dashboard de la landing pública — igual que en la referencia. */

:root {
  --dash-primary: #188CC3;
  --dash-primary-dark: #4338ca;
  --dash-ok: #16a34a;
  --dash-ok-bg: #f0fdf4;
  --dash-warn: #f59e0b;
  --dash-warn-bg: #fffbeb;
  --dash-info: #3b82f6;
  --dash-info-bg: #eff6ff;
  --dash-bad: #ef4444;
  --dash-bad-bg: #fef2f2;
}

.dash-body {
  background: #f8f9fc;
}

/* ---- Header ---- */
.dash-header {
  background: #fff;
  border-bottom: 1px solid var(--portal-border);
}

.dash-nav {
  max-width: 1180px;
  margin: 0 auto;
  position: relative;
  display: flex;
  align-items: center;
  gap: 40px;
  padding: 14px 30px;
}

.dash-logo {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 19px;
  font-weight: 800;
  color: var(--portal-text);
  flex-shrink: 0;
}

.dash-logo img {
  width: 120px;
}

.dash-logo-dot {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: conic-gradient(from 180deg, #188CC3, #06b6d4, #f59e0b, #188CC3);
  display: inline-block;
}

.dash-nav-links {
  display: flex;
  gap: 26px;
  flex: 1 1 auto;
  flex-wrap: wrap;
}

.dash-nav-links a {
  font-size: 1rem;
  font-weight: 400;
  color: var(--portal-muted);
  padding: 20px 2px 16px;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
}

.dash-nav-links a.active {
  color: var(--dash-primary);
  border-bottom-color: var(--dash-primary);
}

.dash-nav-actions {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-shrink: 0;
}

.dash-nav-toggle {
  display: none;
  flex-direction: column;
  gap: 4px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px;
}

.dash-nav-toggle span {
  width: 22px;
  height: 2px;
  background: var(--portal-text);
  border-radius: 2px;
}

/* Bug real detectado: con 4 ítems (Oportunidades/Cómo usar nuestra plataforma/Preguntas
   frecuentes/Contáctenos) el nav no cabía en pantallas angostas y se salía del viewport —
   antes quedaba invisible (recortado por overflow-x:hidden global, que también rompía
   `position: sticky`); al quitar ese overflow global quedó expuesto como scroll horizontal
   real. Colapsa a menú hamburguesa igual que el header de marketing (partials/header.php). */
@media (max-width: 860px) {
  .dash-nav-toggle {
    display: flex;
  }

  /* Pedido explícito del owner (solo vista móvil, el diseño de computador queda igual): en
     desktop .dash-nav-links (flex:1 1 auto) es lo que empuja .dash-nav-actions al extremo
     derecho -- acá arriba, en este mismo breakpoint, .dash-nav-links pasa a position:absolute
     y sale del flujo flex, así que ese empuje deja de existir y el botón de usuario/Ingresar
     quedaba pegado junto al ícono de hamburguesa en vez de al extremo derecho del header.
     margin-left:auto reemplaza ese empuje directamente en el elemento que debe llegar al borde. */
  .dash-nav-actions {
    margin-left: auto;
  }

  /* Pedido explícito del owner (solo vista móvil): el margin-top negativo de
     .dash-welcome-text (-100px en index.php, -70px en oportunidades.php, inline por página)
     existe para compensar el alto real del mockup en desktop -- en mobile, con el título en
     varias líneas por su font-size fijo (sin escalar), ese mismo offset empuja el bloque hasta
     encima del header, superponiéndolo (bug real detectado). !important es necesario acá
     porque un `style` inline solo se puede vencer con esa especificidad. */
  .dash-welcome-text {
    margin-top: 0 !important;
  }

  /* Pedido explícito del owner (solo vista móvil): ocultar la mascota ilustrada de Preguntas
     frecuentes/Contáctenos -- selector por src en vez de una clase nueva, ya que
     .dash-mascot-img también la usan index.php/oportunidades.php (esas SÍ deben seguir
     mostrándose en móvil, no se tocan acá). El contenedor .dash-mascot vacío no deja hueco
     (flex-shrink:0 sin contenido no reserva espacio). */
  img[src*="/faq.png"],
  img[src*="/contactenos.png"] {
    display: none;
  }

  .dash-nav-links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: #fff;
    border-bottom: 1px solid var(--portal-border);
    flex-direction: column;
    gap: 0;
    display: none;
    z-index: 20;
  }

  .dash-nav-links.open {
    display: flex;
  }

  .dash-nav-links a {
    padding: 14px 20px;
    border-top: 1px solid var(--portal-border);
    border-bottom: none;
  }

  .dash-nav-links a.active {
    border-top-color: var(--dash-primary);
  }
}

@media (max-width: 480px) {
  .dash-nav {
    gap: 14px;
    padding: 12px 16px;
  }

  .dash-logo {
    font-size: 16px;
  }

  .dash-nav-actions {
    gap: 10px;
  }

  .dash-user-name {
    display: none;
  }

  .dash-user-dropdown {
    right: -12px;
    width: 240px;
  }
}

/* Pedido explícito del owner: ocultar el botón de notificaciones del usuario logueado -- vía
   CSS (no se borra el markup de partials/header_app.php) para no perder el feature completo
   si se quiere reactivar más adelante. */
.dash-bell-btn {
  display: none;
  position: relative;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--portal-text);
  padding: 6px;
}

.dash-bell-badge {
  position: absolute;
  top: 0;
  right: 0;
  background: var(--dash-bad);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  border-radius: 999px;
  min-width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 3px;
}

.dash-user {
  position: relative;
}

.dash-user-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--portal-text);
  padding: 4px;
}

.dash-user-avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--dash-primary);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.dash-user-avatar.guest {
  background: #e5e7eb;
  color: #9ca3af;
}

.dash-user-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 50%;
  display: block;
}

.dash-btn-ingresar {
  background: var(--dash-primary);
  color: #fff;
  border: none;
  border-radius: 6px;
  padding: 6px 22px;
  font-size: 16px;
  font-weight: 200;
  white-space: nowrap;
}

.dash-btn-ingresar:hover {
  background: var(--dash-primary-dark);
}

.dash-user-name {
  font-size: 13.5px;
  font-weight: 600;
}

.dash-user-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  width: 270px;
  background: #fff;
  border: 1px solid var(--portal-border);
  border-radius: 12px;
  box-shadow: 0 12px 30px rgba(17, 24, 39, .12);
  padding: 8px;
  z-index: 30;
}

.dash-user-dropdown.open {
  display: block;
}

.dash-user-dropdown-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 8px;
  border-radius: 8px;
  color: var(--portal-text);
  font-size: 12px;
}

.dash-user-dropdown-item strong {
  display: block;
  font-size: 13px;
  font-weight: 600;
}

.dash-user-dropdown-item:hover {
  background: #f3f4f6;
}

.dash-user-dropdown-item.danger {
  color: var(--dash-bad);
  border-top: 1px solid var(--portal-border);
  margin-top: 4px;
  padding-top: 12px;
}

.dash-user-dropdown-item.danger svg {
  color: var(--dash-bad);
}

/* ---- Layout general ---- */
.dash-container {
  max-width: 1180px;
  margin: 0 auto;
  padding: 28px 30px 60px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.dash-card {
  background: #fff;
  border: 1px solid var(--portal-border);
  border-radius: 6px;
  padding: 22px;
}

/* ---- Bienvenida ---- */
.dash-welcome {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 10px 4px 4px;
}

.dash-welcome h1 {
  font-size: 26px;
  font-weight: 800;
  margin: 0 0 6px;
}

.dash-welcome-sub {
  font-size: 15px;
  font-weight: 700;
  color: var(--dash-primary);
  margin: 0 0 8px;
}

.dash-welcome-desc {
  font-size: 1.1rem;
  color: var(--portal-muted);
  max-width: 480px;
  margin: 0;
  line-height: 1.6;
}

.dash-mascot {
  flex-shrink: 0;
}

/* ---- Progreso ---- */
.dash-progress-card {
  display: flex;
  align-items: center;
  gap: 30px;
  flex-wrap: wrap;
}

.dash-progress-left {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.dash-ring-wrap {
  position: relative;
  display: inline-flex;
}

.dash-ring-center {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.dash-ring-pct {
  font-size: 22px;
  font-weight: 800;
  color: var(--dash-primary);
}

.dash-ring-pct.small {
  font-size: 12px;
}

/* Pedido explícito del owner: el círculo de afinidad de la calificación en oportunidad.php
   mide 3 veces el tamaño ya usado en otras tarjetas (64px -> 192px, ver progressRing() ahí) --
   el porcentaje adentro necesita su propio tamaño de fuente, proporcional al nuevo diámetro. */
.dash-ring-pct.xl {
  font-size: 40px;
}

.dash-ring-caption {
  font-size: 11px;
  color: var(--portal-muted);
  text-align: center;
  line-height: 1.3;
}

.dash-ring-caption.small {
  font-size: 10px;
  margin-top: 2px;
}

/* Ícono de información junto a "afinidad estimada" (tarjetas de oportunidad, oportunidades.php)
   -- pedido explícito del owner: tooltip tipo globo al pasar el mouse, fondo #188CC3 y letra
   blanca. CSS puro (:hover/:focus, sin JS) -- mismo criterio "sin librería" del resto del
   proyecto; funciona también por teclado vía tabindex+:focus. */
.dash-info-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 12px;
  height: 12px;
  margin-left: 1px;
  color: var(--portal-muted);
  cursor: help;
  vertical-align: middle;
}

.dash-info-icon svg {
  width: 100%;
  height: 100%;
}

.dash-info-tooltip {
  position: absolute;
  bottom: calc(100% + 9px);
  left: 50%;
  transform: translateX(-50%);
  width: 190px;
  background: #188CC3;
  color: #fff;
  font-size: 11px;
  font-weight: 400;
  line-height: 1.4;
  padding: 8px 10px;
  border-radius: 6px;
  text-align: left;
  opacity: 0;
  visibility: hidden;
  transition: opacity .15s;
  pointer-events: none;
  z-index: 20;
}

/* Colita del globo -- mismo color que el fondo del tooltip, apuntando hacia el ícono. */
.dash-info-tooltip::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: #188CC3;
}

.dash-info-icon:hover .dash-info-tooltip,
.dash-info-icon:focus .dash-info-tooltip {
  opacity: 1;
  visibility: visible;
}

.dash-progress-middle {
  flex: 1 1 260px;
  min-width: 220px;
}

.dash-progress-middle h3 {
  font-size: 15px;
  font-weight: 700;
  margin: 0 0 8px;
}

.dash-progress-middle p {
  font-size: 12.5px;
  color: var(--portal-muted);
  line-height: 1.6;
  margin: 0 0 16px;
}

.dash-progress-actions {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}

.dash-btn-primary {
  background: var(--dash-primary);
  color: #fff;
  border: none;
  border-radius: 10px;
  padding: 10px 18px;
  font-size: 13px;
  font-weight: 200;
  text-align: left;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 2px;
  line-height: 1.3;
}

.dash-btn-primary small {
  font-weight: 500;
  font-size: 11px;
  opacity: .85;
}

.dash-btn-primary:hover {
  background: var(--dash-primary-dark);
}

.dash-link {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--dash-primary);
  white-space: nowrap;
}

.dash-link-sm {
  font-size: 12px;
  font-weight: 600;
  color: var(--dash-primary);
}

.dash-progress-right {
  flex: 1 1 260px;
  min-width: 220px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  border-left: 1px solid var(--portal-border);
  padding-left: 24px;
}

.dash-bullet {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 12px;
  color: var(--portal-text);
  line-height: 1.5;
}

.dash-bullet svg {
  flex-shrink: 0;
  margin-top: 1px;
}

@media (max-width: 900px) {
  .dash-progress-right {
    border-left: none;
    padding-left: 0;
    border-top: 1px solid var(--portal-border);
    padding-top: 16px;
  }

  /* Pedido explícito del owner (solo vista móvil): el anillo de "% con resultado concluyente"
     y su leyenda (.dash-ring-caption) quedan centrados en su propia fila -- .dash-progress-card
     ya wrappea en este breakpoint, pero .dash-progress-left (flex-shrink:0, sin ancho propio)
     solo ocupaba el ancho de su contenido y quedaba pegado al borde izquierdo de esa fila.
     width:100% lo estira a todo el ancho disponible; align-items:center (ya fijo en el propio
     elemento) centra el anillo y la leyenda dentro de esa fila completa. */
  .dash-progress-left {
    width: 100%;
  }
}

/* ---- Preferencias ---- */
.dash-prefs-card {
  display: flex;
  gap: 30px;
  flex-wrap: wrap;
}

.dash-prefs-main {
  flex: 1 1 400px;
}

.dash-prefs-title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
}

.dash-prefs-title h3 {
  font-size: 14.5px;
  font-weight: 700;
  margin: 0;
  flex: 1 1 auto;
}

.dash-prefs-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

.dash-pref-item {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.dash-pref-item svg {
  flex-shrink: 0;
  margin-top: 2px;
}

.dash-pref-label {
  display: block;
  font-size: 11px;
  color: var(--portal-muted);
  margin-bottom: 2px;
}

.dash-pref-item strong {
  font-size: 13px;
}

.dash-prefs-notif {
  flex: 0 1 260px;
  border-left: 1px solid var(--portal-border);
  padding-left: 24px;
}

.dash-prefs-notif p {
  font-size: 12px;
  color: var(--portal-muted);
  line-height: 1.6;
  margin: 8px 0 8px;
}

@media (max-width: 760px) {
  .dash-prefs-grid {
    grid-template-columns: 1fr;
  }

  .dash-prefs-notif {
    border-left: none;
    padding-left: 0;
    border-top: 1px solid var(--portal-border);
    padding-top: 16px;
  }
}

.dash-icon-circle {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.dash-icon-circle.ok {
  background: var(--dash-ok-bg);
  color: var(--dash-ok);
}

.dash-icon-circle.warn {
  background: var(--dash-warn-bg);
  color: var(--dash-warn);
}

.dash-icon-circle.info {
  background: var(--dash-info-bg);
  color: var(--dash-info);
}

.dash-icon-circle.bad {
  background: var(--dash-bad-bg);
  color: var(--dash-bad);
}

/* ---- Filtrar / Buscar ---- */
.dash-actions-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.dash-action-card {
  display: flex;
  align-items: center;
  gap: 12px;
  background: #fff;
  border: 1px solid var(--portal-border);
  border-radius: 12px;
  padding: 16px 18px;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  margin-bottom: 10px;
}

.dash-action-card:hover {
  border-color: var(--dash-primary);
}

.dash-action-text {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.dash-action-text strong {
  font-size: 13.5px;
}

.dash-action-text small {
  font-size: 11.5px;
  color: var(--portal-muted);
}

@media (max-width: 760px) {
  .dash-actions-row {
    grid-template-columns: 1fr;
  }
}

/* ---- Resumen por estado ---- */
.dash-status-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

.dash-status-card {
  background: #fff;
  border: 1px solid var(--portal-border);
  border-radius: 12px;
  padding: 16px 18px;
  display: flex;
  gap: 12px;
  align-items: flex-start;
  cursor: pointer;
  transition: border-color .15s, box-shadow .15s;
}

.dash-status-card:hover {
  border-color: var(--dash-primary);
}

/* Pedido explícito del owner: la tarjeta en la que se dio clic filtra el listado -- box-shadow
   inset en vez de engrosar el border, así no desplaza el resto de la grilla al activarse. */
.dash-status-card.active {
  border-color: var(--dash-primary);
  box-shadow: inset 0 0 0 2px var(--dash-primary);
}

/* Pedido explícito del owner: mensaje "Mostrando X de Y resultados" + enlace "Mostrar todos"
   al filtrar por una tarjeta de dash-status-row -- arranca oculto vía style="display:none"
   inline (nunca el atributo `hidden`, que un `display` de autor como este ya vuelve inerte). */
.dash-filtro-status-msg {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--dash-info-bg);
  border: 1px solid #bfdbfe;
  border-radius: 8px;
  padding: 10px 16px;
  font-size: 13px;
  color: var(--portal-text);
}

.dash-filtro-status-msg a {
  margin-left: auto;
  color: var(--dash-primary);
  font-weight: 600;
  white-space: nowrap;
}

.dash-status-card strong {
  display: block;
  font-size: 14px;
  margin-bottom: 4px;
}

.dash-status-card p {
  font-size: 11.5px;
  color: var(--portal-muted);
  margin: 0;
  line-height: 1.5;
}

@media (max-width: 900px) {
  .dash-status-row {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 480px) {
  .dash-status-row {
    grid-template-columns: 1fr;
  }
}

/* ---- Orden / disclaimer ---- */
.dash-sort-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 4px 2px;
}

.dash-afinidad-note {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  color: var(--portal-muted);
}

.dash-sort-select {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--portal-text);
}

.dash-sort-select select {
  border: 1px solid var(--portal-border);
  border-radius: 8px;
  padding: 7px 10px;
  font-family: inherit;
  font-size: 12.5px;
}

/* ---- Grupos + tarjetas de oportunidad ---- */
.dash-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.dash-group-header {
  display: flex;
  align-items: center;
  gap: 10px;
}

.dash-group-header h3 {
  font-size: 14.5px;
  font-weight: 700;
  margin: 0;
}

.dash-job-card {
  background: #fff;
  border: 1px solid var(--portal-border);
  border-radius: 12px;
  padding: 10px 18px;
  display: flex;
  align-items: center;
  gap: 16px;
}

.dash-job-ring {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 64px;
}

.dash-ring-dash {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 6px solid #e5e7eb;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--portal-muted);
  font-weight: 700;
}

.dash-job-main {
  flex: 1 1 auto;
  min-width: 0;
}

.dash-job-top {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}

.dash-job-titulo {
  font-size: 1.1rem;
  font-weight: 600;
  margin-top: -10px;
}

/* Pedido explícito del owner: en la vista de usuario registrado (oportunidades.php), el título
   va debajo del badge de estado, con salto de línea -- flex-basis:100% funciona porque
   .dash-job-top ya es flex-wrap:wrap (mismo truco que .dash-job-ubicacion debajo de
   .dash-job-entidad). Scoped a .dash-job-top -- en index.php/oportunidades.php (invitados y el
   modal de filtro rápido) el título vive suelto, sin badge al lado, y no debe cambiar. */
.dash-job-top .dash-job-titulo {
  flex-basis: 100%;
}

/* Pedido explícito de seguimiento: class="dash-job-sep" (y el resto de la línea de ubicación)
   ya no anida dentro de .dash-job-entidad -- .dash-job-ubicacion es ahora un sibling real que
   sigue inmediatamente en el DOM, no un hijo de tres niveles de profundidad. */
.dash-job-entidad {
  font-size: 1rem;
  color: var(--portal-muted);
}

.dash-job-ubicacion {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-bottom: 6px;
}

.dash-job-sep {
  opacity: .5;
}

.dash-job-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: 1rem;
  color: var(--portal-muted);
}

.dash-job-nota {
  color: var(--dash-bad);
  font-weight: 600;
}

.dash-tag {
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  border-radius: 999px;
  margin-left: -10px;
  padding: 4px 10px;
  letter-spacing: .3px;
}

.dash-tag.ok {
  background: var(--dash-ok-bg);
  color: var(--dash-ok);
}

.dash-tag.warn {
  background: var(--dash-warn-bg);
  color: var(--dash-warn);
}

.dash-tag.info {
  background: var(--dash-info-bg);
  color: var(--dash-info);
}

.dash-tag.bad {
  background: var(--dash-bad-bg);
  color: var(--dash-bad);
}

.dash-tag.muted {
  background: #f3f4f6;
  color: var(--portal-muted);
  text-transform: none;
  font-weight: 600;
}

.dash-job-link {
  font-size: 1.1rem;
  font-weight: 300;
  color: var(--dash-primary);
  white-space: nowrap;
  text-align: right;
}

/* Pedido explícito del owner: "Curso recomendado" debajo del link "Ver oportunidad", solo
   cuando el OPEC tiene al menos uno asignado (ver CursoRepository::cursosPorOpecIds()) --
   envuelve el link + la lista de cursos en una columna propia para poder apilarlos sin romper
   el centrado vertical del resto de la tarjeta (.dash-job-card sigue align-items:center).
   Pedido explícito de seguimiento: ambos alineados a la derecha (align-items:flex-end fija el
   borde derecho de cada línea al mismo punto vertical; text-align:right es además explícito
   en cada uno, por si alguno queda con un ancho propio que no haga evidente el align-items del
   contenedor). */
.dash-job-actions {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
  gap: 4px;
  /* Pedido explícito de seguimiento: al extremo derecho del CONTENEDOR (.dash-job-card), no
     solo alineados entre sí -- margin-left:auto empuja este bloque hasta el borde derecho
     disponible dentro del flex row de la tarjeta, sin depender de que .dash-job-main sea el
     único elemento que crece para "empujarlo" indirectamente. */
  margin-left: auto;
  /* Pedido explícito de seguimiento: "Ver oportunidad" al top / "Curso recomendado" al bottom
     del contenedor -- align-self:stretch hace que este bloque tome el alto completo de la fila
     (.dash-job-card sigue align-items:center para .dash-job-ring/.dash-job-main, sin tocarlos),
     y justify-content:space-between separa sus dos hijos a los extremos. Con un solo hijo (sin
     curso asignado) space-between no tiene nada contra qué repartir y el link simplemente queda
     arriba, que es el resultado correcto en ambos casos. */
  justify-content: space-between;
  align-self: stretch;
}

.dash-job-cursos {
  text-align: right;
}

/* Pedido explícito de seguimiento: salto de línea entre la etiqueta "Curso recomendado:" y el
   nombre del curso -- display:block la separa del link que le sigue en el DOM sin usar <br>. */
.dash-job-cursos-label {
  display: block;
  font-size: 0.7rem;
  font-weight: 400;
  text-transform: uppercase;
  color: var(--portal-muted);
  margin-bottom: -2px;
}

.dash-job-cursos a {
  font-size: 0.9rem;
  text-transform: uppercase;
  color: var(--dash-primary);
  font-weight: 600;
}

@media (max-width: 640px) {
  .dash-job-card {
    flex-wrap: wrap;
  }

  /* Pedido explícito del owner (solo vista móvil): el anillo (.dash-job-ring) pasa a compartir
     fila con "Ver oportunidad"/"Curso recomendado"/nombre de curso (.dash-job-actions), en el
     extremo izquierdo -- antes quedaba arriba junto al título (.dash-job-main), dejando esa
     segunda fila vacía a la izquierda. order fuerza a .dash-job-main a ocupar toda la primera
     fila (flex-basis:100%) y a .dash-job-ring/.dash-job-actions a compartir la segunda;
     margin-left:auto (ya fijo en .dash-job-actions desde desktop, sin tocar acá) empuja las
     acciones al extremo derecho de esa fila, dejando el anillo en el extremo izquierdo por
     descarte -- ya no necesita su propio width:100% (dejaría de compartir fila con el anillo). */
  .dash-job-main {
    order: 1;
    flex-basis: 100%;
  }

  .dash-job-ring {
    order: 2;
  }

  .dash-job-actions {
    order: 3;
    /* flex-basis:0 (no "auto") -- clave del fix. Con basis:auto, el navegador decide si el
       item cabe en la fila del anillo usando su tamaño "hipotético" SIN encoger (básicamente
       el ancho natural del texto más largo, ej. el nombre del curso) -- ese ancho no cabía
       junto al anillo y flex-wrap lo mandaba entero a su propia fila nueva, ANTES de que
       flex-shrink pudiera actuar (el encogimiento solo ajusta ítems ya asignados a una fila,
       no decide a cuál fila pertenecen). Con basis:0, el tamaño hipotético usado para esa
       decisión es 0 (cabe trivialmente), y flex-grow:1 recién después lo expande para llenar
       el resto de la fila del anillo -- ahí el texto largo sí hace wrap interno con normalidad. */
    flex: 1 1 0;
    min-width: 0;
    width: auto;
    margin-left: 0;
    align-items: flex-end;
  }
}

/* ---- Banner CTA (pendientes de verificar) ---- */
.dash-cta-banner {
  background: var(--dash-warn-bg);
  border: 1px solid #fde68a;
  border-radius: 12px;
  padding: 14px 18px;
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.dash-cta-text {
  flex: 1 1 260px;
}

.dash-cta-text strong {
  display: block;
  font-size: 13px;
  margin-bottom: 3px;
}

.dash-cta-text p {
  font-size: 11.5px;
  color: var(--portal-muted);
  margin: 0;
}

.dash-btn-cta {
  background: var(--dash-warn);
  color: #fff;
  border: none;
  border-radius: 999px;
  padding: 10px 18px;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
}

.dash-btn-cta:hover {
  background: #d97706;
}

/* ---- Banner publicitario de curso recomendado (oportunidad.php, debajo de "Descripción del
   cargo") -- pedido explícito del owner: solo se renderiza si la OPEC tiene curso asignado
   (ver CursoRepository::cursosPorOpecIds()), tarjeta completa clickeable a la URL del curso. */
.dash-curso-banner {
  display: flex;
  align-items: center;
  gap: 16px;
  /* Pedido explícito del owner: #188CC3 (--dash-primary) como color principal, a la izquierda
     -- 90deg (izquierda a derecha, sin diagonal) y dominante hasta el 60% del ancho, en vez del
     degradado 135deg a partes iguales que tenía antes. */
  background: linear-gradient(90deg, var(--dash-primary) 0%, var(--dash-primary) 60%, var(--dash-primary-dark) 100%);
  border-radius: 12px;
  padding: 18px 22px;
  color: #fff;
  text-decoration: none;
  flex-wrap: wrap;
  transition: transform .15s, box-shadow .15s;
}

.dash-curso-banner:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 30px rgba(24, 140, 195, .35);
}

/* Pedido explícito del owner: el ícono SVG genérico se reemplazó por el logo ggblanco.png
   (212x60, apaisado -- no un glyph cuadrado) -- ya no tiene sentido el círculo de fondo
   pensado para un ícono pequeño; el logo se apoya directo sobre el degradado. */
.dash-curso-banner-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
}

.dash-curso-banner-icon img {
  height: 32px;
  width: auto;
  display: block;
}

.dash-curso-banner-text {
  flex: 1 1 220px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.dash-curso-banner-nombre {
  font-size: 15.5px;
  font-weight: 700;
}

/* Pedido explícito del owner: la etiqueta "CURSO RECOMENDADO..." (línea aparte, arriba del
   título) se retiró -- "(RECOMENDADO)" ahora vive junto al título, en la misma línea. */
.dash-curso-banner-tag {
  font-size: 11px;
  font-weight: 700;
  opacity: .85;
  white-space: nowrap;
}

/* Pedido explícito del owner: máximo 3 renglones -- line-clamp en vez del truncado a una sola
   línea que tenía antes (white-space:nowrap + ellipsis). */
.dash-curso-banner-desc {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 12.5px;
  opacity: .9;
  line-height: 1.4;
}

/* Pedido explícito del owner: columna a la derecha del banner con el logo ggblanco.png arriba
   y el precio debajo -- "Ver curso ›" se retiró (la tarjeta completa ya es un <a>, no hace
   falta un CTA de texto aparte). Pedido de seguimiento: imagen y precio centrados
   horizontalmente entre sí dentro de la columna (antes flex-start, alineados a la izquierda). */
.dash-curso-banner-precio-col {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

.dash-curso-banner-valor {
  font-size: 1.1rem;
  font-weight: 400;
  background: rgba(255, 255, 255, .18);
  padding: 6px 12px;
  border-radius: 6px;
  white-space: nowrap;
}

/* ---- Aviso de privacidad al pie del listado (oportunidades.php) ---- */
.dash-security-notice {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  padding: 6px 4px;
  font-size: 12px;
  color: var(--portal-muted);
}

.dash-security-notice span {
  display: flex;
  align-items: center;
  gap: 8px;
}

.dash-security-notice svg {
  flex-shrink: 0;
}


@media (max-width: 640px) {
  .dash-welcome {
    flex-direction: column;
    text-align: center;
  }

  .dash-welcome-desc {
    max-width: none;
  }

  /* Pedido explícito del owner (solo vista móvil): el logo (.dash-curso-banner-icon) queda al
     lado izquierdo del precio (.dash-curso-banner-valor), en fila -- antes esta columna
     (.dash-curso-banner-precio-col) los apilaba verticalmente (logo arriba, precio abajo,
     centrados entre sí), pedido explícito de una pasada anterior para desktop; row + center
     alinea ambos horizontalmente sin tocar ese comportamiento en pantallas más anchas. */
  .dash-curso-banner-precio-col {
    flex-direction: row;
    align-items: center;
  }
}

/* ==== Home (index.php) — invitado, búsqueda + chips + resultados + sidebar ==== */

.dash-accent-text {
  color: var(--dash-primary);
}

.dash-welcome h1 {
  font-size: 30px;
  font-weight: 800;
  line-height: 1.25;
  margin: 0 0 14px;
}

.dash-welcome-desc {
  line-height: 1.6;
}

.dash-mascot {
  position: relative;
}

.dash-mascot-img {
  display: block;
  width: 440px;
  height: auto;
}

@media (max-width: 640px) {
  .dash-mascot-img {
    width: 320px;
  }
}

.dash-searchbar {
  display: flex;
  align-items: center;
  gap: 10px;
  background: #fff;
  border: 1px solid var(--portal-border);
  border-radius: 12px;
  padding: 14px 18px;
  box-shadow: 0 4px 14px rgba(17, 24, 39, .05);
}

.dash-searchbar input {
  flex: 1 1 auto;
  border: none;
  outline: none;
  font-size: 13.5px;
  font-family: inherit;
  color: var(--portal-text);
}

.dash-chips-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.dash-chip {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  background: #fff;
  border: 1px solid var(--portal-border);
  border-radius: 6px;
  padding: 10px 16px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--portal-text);
  cursor: pointer;
}

/* Pedido explícito del owner: la lista desplegable de cada filtro (Dónde quieres trabajar/
   Nivel profesional/Rango salarial/Importación) debe abrirse al hacer clic sobre el propio
   class="dash-chip" y quedar proporcional en ancho y alineada a ese mismo contenedor -- un
   <select> nativo no permite controlar ni el ancho ni la posición de su popup (lo renderiza el
   sistema operativo), así que el <select> real queda oculto (sigue existiendo para no tocar la
   lógica de poblado/lectura de valores ya existente vía $().val()/.append()) y se reemplaza
   visualmente por .dash-chip-label + .dash-chip-dropdown, construida en JS a partir de las
   <option> del select en el momento de abrir (ver toggleChipDropdown()). */
.dash-chip select {
  display: none;
}

.dash-chip-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dash-chip-caret {
  flex-shrink: 0;
  color: var(--portal-muted);
  transition: transform .15s;
}

.dash-chip.open .dash-chip-caret {
  transform: rotate(180deg);
}

.dash-chip-dropdown {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: 100%;
  max-height: 280px;
  overflow-y: auto;
  background: #fff;
  border: 1px solid var(--portal-border);
  border-radius: 8px;
  box-shadow: 0 12px 30px rgba(17, 24, 39, .12);
  padding: 6px;
  z-index: 25;
}

.dash-chip.open .dash-chip-dropdown {
  display: block;
}

.dash-chip-option {
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--portal-text);
  cursor: pointer;
  white-space: normal;
  word-break: break-word;
}

.dash-chip-option:hover {
  background: #f3f4f6;
}

.dash-chip-option.active {
  background: var(--dash-info-bg);
  color: var(--dash-primary);
  font-weight: 700;
}

.dash-chip-btn {
  background: none;
}

.dash-chip-btn:hover,
.dash-chip:hover,
.dash-chip.open {
  border-color: var(--dash-primary);
}

.dash-btn-aplicar-filtro {
  margin-left: auto;
  background: var(--dash-primary);
  color: #fff;
  border: none;
  border-radius: 6px;
  padding: 10px 20px;
  font-size: 12.5px;
  font-weight: 700;
  cursor: pointer;
}

.dash-btn-aplicar-filtro:hover {
  background: var(--dash-primary-dark);
}

.dash-more-filters {
  margin-top: -4px;
}

.dash-more-filters-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}

@media (max-width: 760px) {
  .dash-more-filters-grid {
    grid-template-columns: 1fr;
  }
}

.dash-results-layout {
  display: grid;
  grid-template-columns: 1fr 320px;
  gap: 24px;
  align-items: start;
}

.dash-results-col {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

.dash-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.dash-job-icon {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.dash-tag.sm {
  padding: 3px 9px;
  font-size: 9.5px;
  margin-bottom: 6px;
  display: inline-block;
}

.dash-btn-vermas {
  align-self: center;
  display: flex;
  align-items: center;
  gap: 8px;
  background: #fff;
  border: 1px solid var(--portal-border);
  border-radius: 999px;
  padding: 10px 22px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--portal-text);
  cursor: pointer;
  margin-top: 6px;
}

/* Pedido explícito del owner: class="dash-sort-select" reordena las tarjetas de cada grupo vía
   CSS `order` (ver oportunidades.php) -- este botón vive como último hijo de .dash-group pero
   nace con `order` default (0), el mismo que la primera tarjeta tras un reorden; sin este
   order alto quedaría intercalado entre tarjetas en vez de fijo al final. */
.dash-group-vermas {
  order: 9999;
}

.dash-btn-vermas:hover {
  border-color: var(--dash-primary);
  color: var(--dash-primary);
}

.dash-sidebar-cta {
  background: #fff;
  border: 1px solid var(--portal-border);
  border-radius: 6px;
  padding: 24px;
  /* Sticky, no fixed — pedido explícito del owner (corrigiendo un intento anterior con
     `fixed`, que la desprendía de su posición inicial): arranca en su lugar normal dentro
     del grid; al hacer scroll se "pega" al top y queda visible; al volver arriba, regresa
     sola a su posición inicial. `top` deja espacio para que no quede pegada bajo el header. */
  position: sticky;
  top: 16px;
  max-height: calc(100vh - 106px);
  overflow-y: auto;
}


.dash-icon-circle.sparkle {
  background: #eef2ff;
  width: 44px;
  height: 44px;
  margin-bottom: 12px;
}

.dash-sidebar-cta h3 {
  font-size: 16px;
  font-weight: 800;
  margin: 0 0 8px;
  line-height: 1.3;
}

.dash-sidebar-cta>p {
  font-size: 12.5px;
  color: var(--portal-muted);
  line-height: 1.6;
  margin: 0 0 18px;
}

.dash-sidebar-bullets {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 20px;
}

.dash-btn-primary.full {
  width: 100%;
  padding: 10px;
  font-size: 1rem;
  text-align: center;
  align-items: center;
}

@media (max-width: 980px) {
  .dash-results-layout {
    grid-template-columns: 1fr;
  }

  /* Pedido explícito del owner (solo vista móvil): .dash-sidebar-cta pasa a mostrarse ANTES
     que .dash-results-col -- ambos son hijos directos de .dash-results-layout (grid, ver
     arriba), así que order (grid respeta order igual que flex) reordena visualmente sin tocar
     el DOM/markup de index.php ni oportunidad.php (los únicos dos que usan este patrón). */
  .dash-sidebar-cta {
    order: -1;
    position: static;
    width: auto;
    max-height: none;
    overflow-y: visible;
  }
}

/* ---- Contáctenos (contactenos.php): formulario + datos de contacto en 2 columnas ---- */
.dash-contact-layout {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: 24px;
  align-items: start;
}

.dash-contact-form-card h3,
.dash-contact-info-card h3 {
  font-size: 16px;
  font-weight: 800;
  margin: 0 0 18px;
}

.dash-contact-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.dash-contact-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

.dash-contact-info-list {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-bottom: 22px;
}

.dash-contact-whatsapp {
  width: 100%;
  justify-content: center;
}

@media (max-width: 980px) {
  .dash-contact-layout {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 560px) {
  .dash-contact-form-row {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 640px) {
  .dash-welcome h1 {
    font-size: 24px;
  }

  .dash-searchbar {
    padding: 12px 14px;
  }
}

/* ==== Footer de la app (index.php / oportunidades.php) — azul principal, 4 columnas ==== */
.dash-footer {
  background: #188CC3;
  color: #fff;
  margin-top: 30px;
}

.dash-footer-top {
  max-width: 1180px;
  margin: 0 auto;
  padding: 34px 30px 22px;
  display: grid;
  grid-template-columns: 1fr 1.4fr 1fr 1fr;
  gap: 24px;
}

.dash-footer-logo {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 18px;
  font-weight: 800;
  color: #fff;
  flex-shrink: 0;
}

/* Pedido explícito del owner: en móvil el logo del footer cambia de imagen (ver <picture> +
   <source media> en footer_app.php) -- .dash-footer-logo-img ahora vive en el <picture>
   (display:inline por default del user-agent, sin tamaño propio), así que el <img> real
   adentro necesita las mismas reglas para no depender de que el <picture> resuelva el
   porcentaje por su cuenta. */
.dash-footer-logo-img,
.dash-footer-logo-img img {
  width: 100%;
  height: auto;
  display: block;
}

/* Mismo tratamiento tipográfico que el h1 del hero ("Encuentra oportunidades para ti") —
   peso 800, line-height ajustado — pedido explícito del owner, escalado a un tamaño que
   quepa cómodo en una columna angosta del footer en vez del tamaño completo de un h1. */
.dash-footer-tagline {
  font-size: 1.6rem;
  font-weight: 200;
  line-height: 1.35;
  color: #fff;
  margin: 0;
}

.dash-footer-col {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: flex-start;
}

.dash-footer-col a {
  font-size: 14px;
  font-weight: 200;
  color: rgba(255, 255, 255, .85);
}

.dash-footer-col a:hover {
  color: #fff;
}

.dash-footer-whatsapp {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #25d366;
  color: #04220f;
  font-weight: 700;
  font-size: 12.5px;
  padding: 9px 16px;
  border-radius: 6px;
  flex-shrink: 0;
}

.dash-footer-whatsapp:hover {
  background: #1fb855;
}

.dash-footer-bottom {
  max-width: 1180px;
  margin: 0 auto;
  padding: 16px 30px;
  border-top: 1px solid rgba(255, 255, 255, .2);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px;
  font-size: 11.5px;
  color: rgba(255, 255, 255, .75);
}

@media (max-width: 760px) {
  .dash-footer-top {
    grid-template-columns: 1fr 1fr;
  }

  .dash-footer-bottom {
    flex-direction: column;
  }
}

@media (max-width: 480px) {
  .dash-footer-top {
    grid-template-columns: 1fr;
  }
}

/* ==== Login (maqueta) ==== */
.dash-login-container {
  display: flex;
  justify-content: center;
  padding-top: 60px;
  padding-bottom: 60px;
}

.dash-login-card {
  width: 100%;
  max-width: 420px;
  text-align: center;
}

.dash-login-title {
  font-size: 22px;
  font-weight: 800;
  margin: 0 0 8px;
}

.dash-login-sub {
  font-size: 13px;
  color: var(--portal-muted);
  line-height: 1.6;
  margin: 0 0 24px;
}

.dash-login-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-align: left;
}

.dash-login-form .portal-filtro-field label {
  font-size: 11.5px;
}

.dash-login-form .portal-filtro-field input {
  padding: 10px 12px;
}

.dash-login-footer {
  font-size: 12.5px;
  color: var(--portal-muted);
  margin: 18px 0 0;
}

/* ---- Google Sign-In (registro.php) — el botón lo dibuja Google (renderButton), acá solo se
   centra su wrapper y se arma el separador "o regístrate con tu correo". ---- */
.dash-google-btn-wrap {
  display: flex;
  justify-content: center;
  margin-bottom: 18px;
}

.dash-login-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
  color: var(--portal-muted);
  font-size: 12px;
}

.dash-login-divider::before,
.dash-login-divider::after {
  content: '';
  flex: 1 1 auto;
  height: 1px;
  background: var(--portal-border);
}

/* ---- Modal de confirmación (registro.php / login.php, reusable por cualquier vista) ----
   `display:none` por default + `.is-open{display:flex}` — nunca el atributo `hidden`, que
   perdería contra cualquier `display` propio de una clase con más especificidad (bug ya
   documentado en otras partes de este proyecto). */
.dash-modal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, .55);
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 20px;
}

.dash-modal-overlay.is-open {
  display: flex;
}

.dash-modal-dialog {
  background: #fff;
  border-radius: 14px;
  padding: 10px 16px;
  max-width: 420px;
  width: 100%;
  text-align: center;
}

.dash-modal-icon {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: #eef2ff;
  color: var(--dash-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 18px;
}

.dash-modal-title {
  font-size: 1.2rem;
  font-weight: 200;
  margin: 0 0 10px;
}

.dash-modal-desc {
  font-size: 13.5px;
  color: var(--portal-muted);
  line-height: 1.6;
  margin: 0 0 24px;
}

/* ---- Variante ancha/alta del modal, para listas de resultados (ej. filtro rápido de
   oportunidades.php) en vez de un mensaje corto centrado. ---- */
.dash-modal-dialog-resultados {
  max-width: 680px;
  text-align: left;
  max-height: 82vh;
  display: flex;
  flex-direction: column;
}

.dash-modal-resultados-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
  flex-shrink: 0;
}

.dash-modal-resultados-header strong {
  font-size: 14px;
}

.dash-modal-cerrar {
  background: none;
  border: none;
  font-size: 22px;
  line-height: 1;
  color: var(--portal-muted);
  cursor: pointer;
  padding: 4px 8px;
}

.dash-modal-cerrar:hover {
  color: var(--portal-text);
}

.dash-modal-dialog-resultados .dash-list {
  overflow-y: auto;
}

/* ==== Registro (maqueta, registro.php) — 2 columnas: imagen a la izquierda, formulario a la
   derecha (pedido explícito del owner), en vez del card centrado único que usa login.php. La
   card del formulario reusa .dash-login-card/.dash-login-* tal cual — solo cambia el
   contenedor que la envuelve. ==== */

/* El color de la mitad derecha (#fff) vive en el propio .dash-container (pedido explícito
   del owner — antes estaba en .dash-register-form-col) vía un modificador scoped
   .dash-register-page, para no tocar el .dash-container base que reusan todas las demás
   vistas del portal. El padding horizontal de .dash-container es simétrico (30px cada lado),
   así que el 50% del gradiente coincide exactamente con el borde real entre las dos columnas
   del grid de abajo, sin necesidad de recalcular nada. La izquierda queda transparent — sigue
   mostrando el mismo fondo que ya tenía .dash-body, sin tocarlo. */
/* Pantalla completa, sin header/footer (pedido explícito del owner — se dejaron de incluir
   en registro.php) — .dash-container base trae max-width:1180px + margin:0 auto + su propio
   padding, todo eso se anula acá para que ocupe el 100% del alto y ancho reales de la
   pantalla. flex-direction:column ya viene del .dash-container base; .dash-register-layout
   es su único hijo, así que min-height:100vh alcanza para que las 2 columnas cubran toda la
   pantalla verticalmente también. */
.dash-register-page {
  background: linear-gradient(to right, transparent 50%, #fff 50%);
  max-width: none;
  width: 100%;
  min-height: 100vh;
  margin: 0;
  padding: 0;
}

.dash-register-page .dash-register-layout {
  min-height: 100vh;
  padding: 0;
}

.dash-register-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  align-items: stretch;
  min-height: 560px;
  padding: 30px 0 60px;
}

.dash-register-image-col {
  border-radius: 0px;
  padding: 0;
  display: flex;
  align-items: flex-end;
}

.dash-register-image {
  display: block;
  width: 100%;
  height: auto;
}

.dash-register-form-col {
  padding: 0;
  display: flex;
  align-items: center;
}

/* Card del formulario sin el padding/borde que trae .dash-card/.dash-login-card por default
   (pedido explícito del owner: ninguna de las 2 columnas debe tener padding ni espacio entre
   ellas). Ancho: pedido explícito de seguimiento — en vista de computador el contenido de la
   columna 2 queda centrado con max-width:500px (antes era 100% sin límite); `margin:0 auto`
   en un hijo de un flex en fila (.dash-register-form-col, align-items:center) lo centra
   horizontalmente sin necesitar justify-content en el padre. En mobile, 500px nunca llega a
   limitar el ancho real del viewport, así que ahí se sigue viendo a ancho completo. */
.dash-register-form-col .dash-card {
  width: 100%;
  max-width: 500px;
  margin: 0 auto;
  padding: 0;
  border: none;
  border-radius: 0;
}

@media (max-width: 860px) {
  .dash-register-layout {
    grid-template-columns: 1fr;
    min-height: 0;
    padding-top: 10px;
  }

  /* El split izquierda/derecha del fondo solo tiene sentido con las 2 columnas lado a lado —
     apiladas (imagen arriba, formulario abajo) cortaría cada sección por la mitad con un
     borde vertical blanco/transparente sin ningún sentido visual. */
  .dash-register-page {
    background: #fff;
  }
}

.dash-password-field {
  position: relative;
}

.dash-password-field input {
  padding-right: 40px;
}

.dash-password-toggle {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 5px;
  cursor: pointer;
  color: var(--portal-muted);
  display: flex;
  align-items: center;
}

.dash-password-toggle:hover {
  color: var(--dash-primary);
}

.dash-field-hint {
  font-size: 11px;
  color: var(--portal-muted);
  line-height: 1.5;
  margin: 6px 0 0;
}

/* ==== Detalle de oportunidad (oportunidad.php) ==== */
.dash-back-link {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--portal-muted);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.dash-back-link:hover {
  color: var(--dash-primary);
}

.dash-detalle-header {
  display: flex;
  gap: 18px;
  align-items: flex-start;
}

.dash-detalle-titulo {
  font-size: 2rem;
  font-weight: 400;
  margin: 8px 0 6px;
  line-height: 1.3;
}

.dash-detalle-cta {
  margin-top: 16px;
}

.dash-section-title {
  font-size: 1rem;
  text-transform: uppercase;
  font-weight: 400;
  margin: 0 0 14px;
}

/* ---- Foto de perfil (mi_perfil.php) -- el <input type="file"> real queda hidden en el
   markup; este botón/thumbnail es el único control visible, con un overlay de cámara que
   aparece al pasar el mouse. ---- */
.dash-avatar-uploader {
  margin-bottom: 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.dash-avatar-thumb {
  position: relative;
  width: 176px;
  height: 176px;
  border-radius: 50%;
  overflow: hidden;
  border: none;
  padding: 0;
  cursor: pointer;
  background: var(--dash-primary);
  color: #fff;
  font-size: 60px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}

.dash-avatar-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.dash-avatar-overlay {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, .5);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity .15s ease;
}

.dash-avatar-thumb:hover .dash-avatar-overlay,
.dash-avatar-thumb:focus-visible .dash-avatar-overlay {
  opacity: 1;
}

/* ---- Listas de registros editables con tarjetas (mi_formacion_academica.php y análogas:
   experiencia laboral, etc.) ---- */
.dash-item-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 18px;
}

.dash-item-card {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  border: 1px solid var(--portal-border);
  border-radius: 10px;
  padding: 14px 16px;
}

.dash-item-card-main strong {
  display: block;
  font-size: 13.5px;
  margin-bottom: 2px;
}

.dash-item-card-main span {
  display: block;
  font-size: 12px;
  color: var(--portal-muted);
}

.dash-item-card-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}

.dash-item-card-edit,
.dash-item-card-view,
.dash-item-card-delete {
  background: none;
  border: none;
  color: var(--portal-muted);
  cursor: pointer;
  padding: 4px;
  flex-shrink: 0;
  border-radius: 6px;
}

.dash-item-card-edit:hover,
.dash-item-card-view:hover {
  color: var(--dash-primary);
  background: rgba(24, 140, 195, 0.1);
}

.dash-item-card-delete:hover {
  color: var(--dash-bad);
  background: var(--dash-bad-bg);
}

/* ---- Upload drag-and-drop (mi_documentos_soporte.php) -- zona clicable + drag/drop + paste,
   <input type="file"> real oculto (mismo criterio que .dash-avatar-uploader: el control
   nativo nunca es lo que el usuario ve/toca). ---- */
.doc-upload-zone {
  border: 2px dashed var(--portal-border);
  border-radius: 10px;
  padding: 28px 16px;
  text-align: center;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}

.doc-upload-zone:hover,
.doc-upload-zone.is-dragover {
  border-color: var(--dash-primary);
  background: rgba(24, 140, 195, 0.05);
}

.doc-upload-zone-icon {
  color: var(--portal-muted);
  margin-bottom: 8px;
}

.doc-upload-zone.is-dragover .doc-upload-zone-icon,
.doc-upload-zone.has-file .doc-upload-zone-icon {
  color: var(--dash-primary);
}

.doc-upload-zone-text {
  font-size: 13px;
  color: var(--portal-text);
  margin: 0 0 4px;
}

.doc-upload-zone-hint {
  font-size: 11.5px;
  color: var(--portal-muted);
  margin: 0;
}

.doc-upload-filename {
  font-size: 13px;
  font-weight: 600;
  color: var(--dash-primary);
  margin: 0 0 4px;
  word-break: break-all;
}

.dash-btn-agregar {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: none;
  border: 1px dashed var(--dash-primary);
  color: var(--dash-primary);
  border-radius: 8px;
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
}

.dash-btn-agregar:hover {
  background: #eef2ff;
}

.dash-detalle-prosa {
  font-size: 1.1rem;
  color: var(--portal-text);
  line-height: 1.30;
}

.dash-req-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}

.dash-req-item {
  font-size: 13px;
  line-height: 1.6;
}

.dash-req-item .label {
  display: block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .3px;
  color: var(--portal-muted);
  margin-bottom: 3px;
}

.dash-funcion-grupo {
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--portal-muted);
  margin: 16px 0 8px;
  letter-spacing: .3px;
}

.dash-funcion-grupo:first-child {
  margin-top: 0;
}

.dash-funcion-item {
  font-size: 1.1rem;
  padding: 8px 10px;
  border-radius: 8px;
  margin-bottom: 6px;
  line-height: 1.30;
}

.dash-ubicacion-badge {
  display: inline-block;
  font-size: 12px;
  font-weight: 600;
  background: var(--dash-info-bg);
  color: var(--dash-info);
  padding: 5px 11px;
  border-radius: 999px;
  margin: 0 6px 6px 0;
}

.dash-detalle-empty {
  text-align: center;
  padding: 60px 20px;
}