/* ==========================================================================
   GestionaPública — Panel de gestión municipal
   Topbar compartida inyectada por nav.js + contenido por página.
   ========================================================================== */

/* ==========================================================================
   TOPBAR
   ========================================================================== */

.topbar {
  position: sticky; top: 0; z-index: 80;
  height: var(--topbar-h);
  background: color-mix(in srgb, var(--bg-elev) 92%, transparent);
  backdrop-filter: blur(14px) saturate(160%);
  border-bottom: 1px solid var(--border);
}
/* Medidas calcadas de la barra de GestionaFitness: 64 px de alto, 24 px de
   aire a los lados, símbolo de 36 y la marca a 17 px en peso 800. Es lo que
   hace que la navegación se lea de un vistazo en vez de pedir que la busques. */
/* La barra va a todo el ancho, como la de GestionaFitness: el contenido de la
   página sigue centrado en --maxw, pero la navegación aprovecha la pantalla
   entera. En un monitor grande es la diferencia entre que quepan las seis
   secciones o no. */
.topbar-in {
  width: 100%; height: 100%;
  padding: 0 24px; display: flex; align-items: center; gap: 12px;
}

.tb-brand { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.tb-brand:hover { text-decoration: none; }
/* El símbolo va suelto, sin pastilla de color detrás: el aro amarillo ya es
   una forma cerrada y meterlo dentro de un cuadrado le quita aire. */
.tb-logo {
  width: 36px; height: 36px; flex: 0 0 auto;
  display: grid; place-items: center;
  filter: drop-shadow(0 3px 10px rgba(252, 169, 5, .28));
}
.tb-name {
  font-size: 1.0625rem; font-weight: 800;
  color: var(--text); letter-spacing: -.02em; line-height: 1.1;
}
.tb-name-b { color: var(--accent); }

/* Nombre del ente. Va aquí, entre la navegación y los iconos, y no bajo el
   logotipo: GestionaPública es la marca común a todos los ayuntamientos y el
   cliente es quien cambia. Mismo sitio y mismo formato que el nombre del
   centro en GestionaFitness. */
.tb-ente {
  flex: 0 0 auto; max-width: 240px; padding: 0 8px;
  display: flex; flex-direction: column; justify-content: center; gap: 1px;
  font-size: .8125rem; font-weight: 600; color: var(--text-soft);
  line-height: 1.25; overflow: hidden;
}
.tb-ente-n { display: block; }

/* Ejercicio presupuestario, en la segunda línea del bloque del ente. Discreto
   y siempre visible: no es una acción, es el marco temporal de lo económico.
   La temporada deportiva es otra cosa y se elige en su pantalla. */
.tb-ejercicio {
  font-size: .6875rem; font-weight: 500; color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; cursor: default;
}

.tb-nav { display: flex; gap: 2px; flex: 1 1 auto; margin-left: 16px; overflow-x: auto; scrollbar-width: none; }
.tb-nav::-webkit-scrollbar { display: none; }
.tb-link {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 13px; border-radius: var(--r-sm);
  color: var(--text-soft); font-size: .875rem; font-weight: 500;
  white-space: nowrap; transition: all .14s; position: relative;
}
.tb-link:hover { background: var(--bg-card-hover); color: var(--text); text-decoration: none; }
.tb-link.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.tb-link .ic { font-size: 1rem; }
.tb-link .n-badge {
  min-width: 17px; height: 17px; padding: 0 5px;
  background: var(--danger); color: #fff; border-radius: 99px;
  font-size: .62rem; font-weight: 700; display: grid; place-items: center;
}

.tb-right { display: flex; align-items: center; gap: 7px; flex: 0 0 auto; }
.tb-btn {
  width: 34px; height: 34px; border-radius: var(--r-sm);
  border: 1px solid var(--border); background: var(--bg-card); color: var(--text-soft);
  display: grid; place-items: center; cursor: pointer; font-size: .9rem; transition: all .14s;
}
.tb-btn:hover { background: var(--bg-card-hover); color: var(--text); }
/* Solo el avatar, como en GestionaFitness. El nombre completo iba en una
   pastilla de siglo y medio de ancho que es justo lo que le faltaba a la
   navegación; sigue estando en el `title` y en el menú que se abre al pulsar. */
.tb-user {
  width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center; cursor: pointer;
  border: 2px solid color-mix(in srgb, var(--accent) 35%, transparent);
  background: var(--bg-card); transition: all .14s;
}
.tb-user:hover { border-color: var(--accent); }
.tb-user .gp-avatar { background: none; color: var(--accent); }

/* Accesos de solo icono de la derecha */
.tb-icono { position: relative; text-decoration: none; }
.tb-icono:hover { text-decoration: none; }
.tb-icono.active { background: var(--accent-soft); color: var(--accent); border-color: transparent; }
.tb-icono .n-badge {
  position: absolute; top: -5px; right: -5px;
  min-width: 16px; height: 16px; padding: 0 4px;
  background: var(--danger); color: #fff; border-radius: 99px;
  font-size: .6rem; font-weight: 700; display: grid; place-items: center;
  border: 2px solid var(--bg-elev);
}
.tb-sep { width: 1px; height: 20px; background: var(--border); margin: 0 3px; flex: 0 0 auto; }

/* En pantalla ancha estas secciones ya están a la derecha como icono: en el
   menú desplegable solo estorbarían duplicadas. */
.tb-link.solo-movil { display: none; }

/* Franja estrecha: entre 1400 y 1700 px las seis secciones no caben con el
   aire completo y «Económico», la última, se quedaba cortada contra el borde
   del carrusel. Se recortan unos píxeles a cada enlace en lugar de esconder
   ninguno. Por encima de 1700 se respetan las medidas exactas de
   GestionaFitness. */
@media (max-width: 1700px) {
  .tb-link { padding: 7px 9px; gap: 5px; }
}
@media (max-width: 1520px) {
  .tb-ente { max-width: 150px; }
}
/* Justo por encima del corte del menú móvil (1400) el nombre del ente es lo
   único que queda por recortar: entre eso y perder «Económico», se recorta el
   nombre, que además está entero en el `title`. */
@media (max-width: 1470px) {
  .tb-ente { max-width: 96px; }
}

/* Menú móvil.
   Por debajo de 1400 px las seis secciones con etiqueta ya no caben junto al
   nombre del ente y los accesos de la derecha. Antes que dejarlas a medio
   cortar en un carrusel horizontal sin barra visible, se pliegan al menú
   desplegable, donde se ven todas de una vez. */
/* Calificado con .tb-right por el mismo motivo que los iconos: si no, la
   regla de alineación de .tb-btn lo vuelve a mostrar y el botón de menú
   aparecía también en escritorio, al lado de la navegación completa. */
.tb-right .tb-burger { display: none; }
@media (max-width: 1400px) {
  .tb-nav { position: fixed; top: var(--topbar-h); left: 0; right: 0; z-index: 79;
    background: var(--bg-elev); border-bottom: 1px solid var(--border);
    flex-direction: column; padding: 10px; gap: 2px; overflow: visible;
    box-shadow: var(--shadow-lg); display: none; }
  .tb-nav.open { display: flex; }
  .tb-link { padding: 11px 14px; font-size: .9rem; }
  .tb-link.solo-movil { display: flex; }
  .tb-right .tb-burger { display: grid; }
  .tb-name { display: none; }
  /* Con el menú desplegable ya se llega a todo: los iconos sueltos sobran.
     Va calificado con .tb-right a propósito: más abajo, la regla que alinea
     los SVG del set redefine el display de .tb-btn fuera de toda media query
     y, a igualdad de especificidad, ganaba por ir después. El resultado era
     que estos iconos no se escondían nunca en pantalla estrecha. */
  .tb-right .tb-icono, .tb-right .tb-sep { display: none; }
}
@media (max-width: 620px) {
  /* En un móvil no cabe el nombre del ente junto al avatar, y de los dos el
     que hace falta para saber dónde estás es el del usuario. El ejercicio se
     va con él: en esa anchura estorba más de lo que informa. */
  .tb-ente { display: none; }
}

/* ==========================================================================
   LAYOUT
   ========================================================================== */

.page { max-width: var(--maxw); margin: 0 auto; padding: 22px 20px 60px; }

.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 20px;
}
.page-head h1 { font-size: 1.5rem; letter-spacing: -.025em; }
.page-head .ph-sub { font-size: .84rem; color: var(--text-muted); margin-top: 3px; }
.page-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

.grid { display: grid; gap: 14px; }
.grid.kpis  { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.grid.c2    { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid.c3    { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid.c2-1  { grid-template-columns: 2fr 1fr; }
.grid.c1-2  { grid-template-columns: 1fr 2fr; }
@media (max-width: 1020px) {
  .grid.c2, .grid.c3, .grid.c2-1, .grid.c1-2 { grid-template-columns: 1fr; }
}

.chart-box { height: 260px; position: relative; }
.chart-box.sm { height: 200px; }
.chart-box.lg { height: 320px; }

/* ==========================================================================
   TABLAS EN TARJETA
   ========================================================================== */

.table-card {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--r); overflow: hidden;
}
.table-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 16px; border-bottom: 1px solid var(--border); flex-wrap: wrap;
}
.table-wrap { overflow-x: auto; max-height: 68vh; }
.table-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 11px 16px; border-top: 1px solid var(--border);
  font-size: .8rem; color: var(--text-muted); flex-wrap: wrap;
}

.toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.search-box { position: relative; flex: 1 1 240px; max-width: 340px; }
.search-box input { padding-left: 34px; }
.search-box::before {
  content: ""; position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  width: 16px; height: 16px; opacity: .7; pointer-events: none;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236f7c8f' stroke-width='2' stroke-linecap='round'><circle cx='11' cy='11' r='6.5'/><path d='m16 16 4.5 4.5'/></svg>") center / contain no-repeat;
}

.pager { display: flex; align-items: center; gap: 5px; }
.pager button {
  min-width: 30px; height: 30px; padding: 0 8px;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--bg-card); color: var(--text-soft);
  font-size: .78rem; font-weight: 600; cursor: pointer;
}
.pager button:hover:not(:disabled) { background: var(--bg-card-hover); color: var(--text); }
.pager button.active { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.pager button:disabled { opacity: .4; cursor: not-allowed; }

/* ==========================================================================
   FEED DE ACTIVIDAD
   ========================================================================== */

.feed { display: flex; flex-direction: column; }
.feed-item { display: flex; gap: 11px; padding: 11px 0; }
.feed-item + .feed-item { border-top: 1px solid var(--border-soft); }
.feed-ic {
  width: 30px; height: 30px; border-radius: 8px; flex: 0 0 auto;
  display: grid; place-items: center; font-size: .82rem;
  background: var(--bg-card-hover); color: var(--text-soft);
}
.feed-ic.signup  { background: var(--accent-soft); color: var(--accent); }
.feed-ic.cancel  { background: var(--danger-soft); color: var(--danger); }
.feed-ic.payment { background: var(--info-soft);   color: var(--info); }
.feed-ic.booking { background: var(--purple-soft); color: var(--purple); }
.feed-ic.contact { background: var(--warn-soft);   color: var(--warn); }
.feed-txt  { font-size: .83rem; line-height: 1.4; }
.feed-time { font-size: .71rem; color: var(--text-muted); margin-top: 2px; }

/* ==========================================================================
   HORARIOS — parrilla semanal
   ========================================================================== */

.book-grid {
  display: grid;
  grid-template-columns: 150px repeat(auto-fit, minmax(76px, 1fr));
  border: 1px solid var(--border); border-radius: var(--r);
  overflow: hidden; background: var(--bg-card); min-width: 900px;
}
.bg-head {
  background: var(--bg-elev); padding: 10px 6px; text-align: center;
  font-size: .75rem; font-weight: 650; color: var(--text-soft);
  border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 3;
}
.bg-head.today { color: var(--accent); }
.bg-head small { display: block; font-size: .66rem; color: var(--text-muted); font-weight: 500; }
.bg-hour {
  background: var(--bg-elev); border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border-soft);
  font-size: .68rem; color: var(--text-muted); text-align: right;
  padding: 4px 7px 0 0; font-variant-numeric: tabular-nums;
  position: sticky; left: 0; z-index: 2;
}
.bg-cell {
  border-bottom: 1px solid var(--border-soft); border-right: 1px solid var(--border-soft);
  min-height: 34px; padding: 2px; position: relative; transition: background .12s;
}
.bg-cell:hover { background: var(--bg-card-hover); }
.bg-cell.drop { background: var(--accent-soft); box-shadow: inset 0 0 0 2px var(--accent); }
.bg-cell.selected { box-shadow: inset 0 0 0 2px var(--accent); }

.bg-block {
  position: absolute; left: 2px; right: 2px; top: 2px;
  border-radius: 6px; padding: 5px 7px; overflow: hidden;
  color: #fff; font-size: .72rem; line-height: 1.25; cursor: grab;
  box-shadow: var(--shadow-sm); z-index: 1;
  border-left: 3px solid rgba(255,255,255,.5);
}
.bg-block:active { cursor: grabbing; }
.bg-block .b-name { font-weight: 650; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bg-block .b-meta { opacity: .88; font-size: .66rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bg-block .b-cap  { opacity: .95; font-size: .64rem; margin-top: 2px; font-variant-numeric: tabular-nums; }
.bg-block.inactive { opacity: .45; }
.bg-block:hover { filter: brightness(1.08); z-index: 5; }

/* Paleta de actividades */
.palette {
  display: flex; gap: 7px; flex-wrap: wrap; padding: 12px;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--r);
}
.pal-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; border-radius: var(--r-pill);
  font-size: .8rem; font-weight: 600; color: #fff;
  cursor: grab; user-select: none; transition: transform .12s;
  box-shadow: var(--shadow-sm);
}
.pal-chip:hover  { transform: translateY(-1px); }
.pal-chip:active { cursor: grabbing; }
.pal-chip .p-dur { font-size: .68rem; opacity: .82; font-weight: 500; }

/* ==========================================================================
   RESERVAS — tarjetas de clase del día
   ========================================================================== */

.session-card {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--r); padding: 14px; position: relative;
  border-left: 3px solid var(--act, var(--accent)); transition: all .15s;
}
.session-card:hover { border-color: var(--border-strong); }
.session-card.cancelled { opacity: .55; }
.session-card.cancelled .sc-name { text-decoration: line-through; }
.sc-top { display: flex; align-items: flex-start; gap: 12px; }
.sc-time {
  font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums;
  flex: 0 0 auto; line-height: 1.1;
}
.sc-time small { display: block; font-size: .68rem; color: var(--text-muted); font-weight: 500; }
.sc-name { font-size: .95rem; font-weight: 650; }
.sc-meta { font-size: .74rem; color: var(--text-muted); margin-top: 2px; display: flex; gap: 4px 11px; flex-wrap: wrap; }
.sc-occ  { margin-top: 11px; }
.sc-occ .o-nums { display: flex; justify-content: space-between; font-size: .74rem; margin-bottom: 5px; }
.sc-occ .o-nums b { font-variant-numeric: tabular-nums; }

.attendee {
  display: flex; align-items: center; gap: 10px; padding: 9px 0;
}
.attendee + .attendee { border-top: 1px solid var(--border-soft); }
.attendee .a-actions { margin-left: auto; display: flex; gap: 5px; flex: 0 0 auto; }
.att-btn {
  width: 30px; height: 30px; border-radius: 7px;
  border: 1px solid var(--border); background: var(--bg-card);
  cursor: pointer; font-size: .8rem; transition: all .14s;
}
.att-btn:hover { background: var(--bg-card-hover); }
.att-btn.on-yes { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.att-btn.on-no  { background: var(--danger); border-color: var(--danger); color: #fff; }

/* ==========================================================================
   FICHA DE SOCIO (modal ancho con pestañas)
   ========================================================================== */

.member-head {
  display: flex; align-items: center; gap: 14px; padding-bottom: 16px;
  border-bottom: 1px solid var(--border); margin-bottom: 16px;
}
.member-head .mh-name { font-size: 1.12rem; font-weight: 700; }
.member-head .mh-sub  { font-size: .8rem; color: var(--text-muted); }
.member-head .mh-right { margin-left: auto; text-align: right; }

.mini-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 9px; margin-bottom: 16px; }
.mini-stat {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--r-sm); padding: 10px; text-align: center;
}
.mini-stat .ms-v { font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.mini-stat .ms-l { font-size: .66rem; color: var(--text-muted); margin-top: 1px; }
@media (max-width: 620px) { .mini-stats { grid-template-columns: repeat(2, 1fr); } }

.dl { display: grid; grid-template-columns: 132px 1fr; gap: 8px 12px; font-size: .85rem; }
.dl dt { color: var(--text-muted); font-size: .78rem; }
.dl dd { margin: 0; font-weight: 500; }
@media (max-width: 520px) { .dl { grid-template-columns: 1fr; gap: 2px 0; } .dl dd { margin-bottom: 8px; } }

/* ==========================================================================
   AJUSTES
   ========================================================================== */

/* Misma composición que la configuración de GestionaFitness y GestionaSocios:
   cabecera centrada, submenú en pastilla horizontal y las secciones en una
   columna estrecha y centrada.

   Lo estrecho es deliberado: un formulario de ajustes a 1440 px obliga a
   barrer la pantalla con la vista de un extremo a otro para leer una línea. */

/* Esta pantalla se sale del ancho general: manda `.setup-page`. */
.page.page-setup { max-width: none; padding: 0; }

.setup-page {
  max-width: 1060px;
  margin: 0 auto;
  padding: 34px 20px 80px;
}

/* ── Cabecera ─────────────────────────────────────────────────────────── */
.setup-header { text-align: center; margin-bottom: 26px; }
.setup-badge {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 15px; margin-bottom: 14px;
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: var(--r-pill);
  font-size: .8rem; font-weight: 600; color: var(--accent);
}
.setup-header h1 {
  font-size: clamp(1.6rem, 3.6vw, 2.3rem);
  font-weight: 800; letter-spacing: -.03em; line-height: 1.15;
}
/* El degradado del logotipo, que es lo que ata la pantalla a la marca. Sin
   `display:inline-block` a propósito: en un móvil estrecho el título tiene
   que poder partir en dos líneas. */
.setup-header .gradient-text {
  background: var(--brand-grad);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
}
.setup-header p {
  font-size: .95rem; color: var(--text-soft);
  max-width: 560px; margin: 9px auto 0;
}

/* ── Submenú horizontal ───────────────────────────────────────────────────
   Siete secciones caben en un monitor, pero no en un portátil estrecho, así
   que la pastilla se desplaza y aparecen flechas cuando hace falta. Sin
   ellas, las últimas secciones quedarían escondidas sin ninguna pista. */
.setup-tabs-wrap {
  position: relative;
  margin: 0 auto 26px;
  display: flex; justify-content: center;
  max-width: 100%;
}
.setup-tabs {
  display: flex; gap: 4px;
  width: fit-content; max-width: 100%;
  padding: 6px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
  overflow-x: auto;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.setup-tabs::-webkit-scrollbar { display: none; }

.setup-tab {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 17px;
  border: 0; background: transparent;
  border-radius: var(--r-pill);
  font-family: inherit; font-size: .865rem; font-weight: 550;
  color: var(--text-soft);
  white-space: nowrap; cursor: pointer;
  transition: background .14s, color .14s;
  flex: 0 0 auto;
}
.setup-tab:hover { background: var(--bg-card-hover); color: var(--text); }
.setup-tab.active {
  background: var(--accent); color: var(--accent-text); font-weight: 650;
  box-shadow: 0 2px 10px color-mix(in srgb, var(--accent) 32%, transparent);
}
.setup-tab > span:first-child { display: inline-flex; font-size: 0; }

/* Cuando el submenú va pegado al menú principal (Trabajadores) y no dentro de
   una portada de ajustes, se le da aire por arriba y por abajo y se hace algo
   más grande: en qué sección estás tiene que leerse antes que el título y que
   los indicadores, y para eso necesita quedar aislado de los dos. */
.setup-tabs-wrap.destacado { margin: 14px auto 42px; }
.setup-tabs-wrap.destacado .setup-tabs { padding: 7px; box-shadow: var(--shadow-sm); }
.setup-tabs-wrap.destacado .setup-tab { padding: 10px 19px; font-size: .9rem; }

/* Flechas de desplazamiento. Solo se enseñan si la pastilla no cabe entera:
   las pinta y las esconde el JS midiendo el ancho real. */
.tabs-arrow {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; border-radius: 50%;
  display: none; place-items: center;
  border: 1px solid var(--border); background: var(--bg-elev);
  color: var(--text-soft); cursor: pointer; z-index: 2;
  box-shadow: var(--shadow-sm);
  transition: color .14s, border-color .14s, opacity .14s;
}
.tabs-arrow.show { display: grid; }
.tabs-arrow:hover { color: var(--text); border-color: var(--border-strong); }
.tabs-arrow[disabled] { opacity: .3; cursor: default; }
.tabs-arrow.left  { left: -6px; }
.tabs-arrow.right { right: -6px; }

/* Difuminado en los bordes: dice «esto sigue» sin ocupar sitio. El degradado
   sale del color de la PASTILLA (--bg-elev), no del de la página: con el de
   la página quedaba una mancha más oscura sobre el propio submenú. */
.setup-tabs-wrap.overflowing::before,
.setup-tabs-wrap.overflowing::after {
  content: ""; position: absolute; top: 1px; bottom: 1px; width: 42px;
  pointer-events: none; z-index: 1; border-radius: var(--r-pill);
}
.setup-tabs-wrap.overflowing::before {
  left: 0; background: linear-gradient(90deg, var(--bg-elev) 45%, transparent);
}
.setup-tabs-wrap.overflowing::after {
  right: 0; background: linear-gradient(270deg, var(--bg-elev) 45%, transparent);
}

/* ── Secciones ────────────────────────────────────────────────────────────
   Tarjeta con cabecera teñida y cuerpo con aire, como las de GestionaFitness. */
.setup-section {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  overflow: hidden;
  margin-bottom: 18px;
}
.setup-section:last-child { margin-bottom: 0; }

.setup-section-header {
  display: flex; align-items: center; gap: 12px;
  padding: 17px 22px;
  background: var(--bg-elev);
  border-bottom: 1px solid var(--border);
}
.setup-section-icon {
  width: 38px; height: 38px; flex: 0 0 auto;
  border-radius: var(--r-sm);
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
  color: var(--accent);
  display: grid; place-items: center; font-size: 0;
}
.setup-section-title { font-size: 1.02rem; font-weight: 700; letter-spacing: -.01em; }
.setup-section-sub { font-size: .8rem; color: var(--text-muted); font-weight: 500; margin-top: 2px; }
/* Los botones de la sección van en su cabecera, a la derecha: es donde se
   buscan y así no hay que bajar hasta el final de una tabla larga. */
.setup-section-actions {
  display: flex; align-items: center; gap: 8px; flex: 0 0 auto; flex-wrap: wrap;
  justify-content: flex-end;
}
.setup-section-body { padding: 22px; }

@media (max-width: 760px) {
  .setup-page { padding: 22px 14px 60px; }
  .setup-tabs { border-radius: var(--r-lg); }
  .setup-section-body { padding: 16px; }
  .setup-section-header { padding: 14px 16px; }
}

/* Zonas de la agrupación territorial: etiqueta con su aspa para quitarla.
   No son pulsables como los chips de filtro, solo el aspa lo es. */
.gp-chips .gp-chip:has(.chip-x) { cursor: default; padding-right: 6px; }
.chip-x {
  display: inline-grid; place-items: center;
  width: 18px; height: 18px; margin-left: 2px; padding: 0;
  border: 0; border-radius: 50%;
  background: transparent; color: var(--text-muted);
  cursor: pointer; transition: background .14s, color .14s;
}
.chip-x:hover { background: var(--danger-soft); color: var(--danger); }

/* Importes dentro de una tabla: alineados a la derecha y con cifras de ancho
   fijo, para poder compararlos de un vistazo columna abajo. */
.num-input { text-align: right; font-variant-numeric: tabular-nums; }

/* ==========================================================================
   AYUDA PLEGADA DE CATEGORÍAS
   Quien da de alta a un trabajador no tiene por qué saber en qué categoría
   encaja. La explicación va debajo del selector, plegada.
   ========================================================================== */

.cat-guia { margin-top: 8px; font-size: .8rem; }
.cat-guia > summary {
  cursor: pointer; color: var(--accent); font-weight: 600; font-size: .78rem;
  list-style: none; padding: 4px 0;
}
.cat-guia > summary::-webkit-details-marker { display: none; }
.cat-guia > summary::before { content: '▸ '; }
.cat-guia[open] > summary::before { content: '▾ '; }
.cat-guia ul { margin: 8px 0 0; padding-left: 16px; }
.cat-guia li { margin-bottom: 9px; line-height: 1.5; color: var(--text-soft); }
.cat-guia li > div { color: var(--text-muted); font-size: .76rem; margin-top: 2px; }
.cat-guia .gp-badge { margin-left: 4px; }
.cat-guia-sg {
  margin-top: 12px; padding: 11px 13px;
  background: var(--bg-elev); border: 1px solid var(--border-soft);
  border-radius: var(--r-sm); font-size: .76rem; color: var(--text-soft);
}
.cat-guia-sg ul { margin-top: 6px; }
.cat-guia-sg li { font-size: .75rem; margin-bottom: 5px; }

/* ==========================================================================
   CONSUMO DE PERSONAL QUE LLEGA DE GESTIONAFITNESS
   Dos barras finas en la fila de la instalación: horas y coste de la
   adjudicataria sobre el tope que le fija el pliego.
   ========================================================================== */

.gf-cap { display: flex; flex-direction: column; gap: 5px; min-width: 128px; }
.gf-cap-row { display: flex; align-items: center; gap: 7px; }
.gf-cap-k {
  width: 11px; flex: 0 0 auto; text-align: center;
  font-size: .64rem; font-weight: 700; color: var(--text-muted);
}
.gf-cap-row .gp-bar { flex: 1 1 auto; height: 6px; }
.gf-cap-v {
  width: 34px; flex: 0 0 auto; text-align: right;
  font-size: .68rem; font-weight: 650; font-variant-numeric: tabular-nums;
  color: var(--text-soft);
}
/* Salto al panel de GestionaFitness, bajo el nombre de la adjudicataria */
.gp-btn.gf-cap-go {
  margin-top: 4px; padding: 3px 7px; font-size: .66rem;
  color: var(--accent); white-space: nowrap;
}
.gp-btn.gf-cap-go:hover { background: var(--accent-soft); color: var(--accent); }

/* ==========================================================================
   BUSINESS INTELLIGENCE
   Rejilla de rankings: seis indicadores a la vez, cada uno con sus cinco
   primeros. Separados por líneas y no por tarjetas sueltas, como el panel de
   comparación de GestionaFitness: son cortes del mismo dato, no seis fichas.
   ========================================================================== */

/* ── Fichas comparativas ──────────────────────────────────────────────────
   Una tarjeta por instalación, con la misma anatomía que las del panel de
   comparación de GestionaFitness: cabecera, tira de cifras y rejilla de
   gráficas separadas por líneas de un píxel. Las gráficas no llevan números;
   el dato sale en el tooltip al pasar el ratón. */
.bc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(560px, 1fr));
  gap: 20px;
}
.bc-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.bc-card-header {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 14px 18px;
  background: var(--bg-elev);
  border-bottom: 1px solid var(--border);
}
.bc-card-name { font-weight: 700; font-size: .97rem; flex: 1 1 auto; min-width: 0; }

.bc-mini-kpis { display: flex; border-bottom: 1px solid var(--border); }
.bc-kpi {
  flex: 1; padding: 11px 12px; text-align: center;
  border-right: 1px solid var(--border-soft);
}
.bc-kpi:last-child { border-right: 0; }
.bc-kpi-val {
  font-size: 1.18rem; font-weight: 800; color: var(--accent);
  font-variant-numeric: tabular-nums; letter-spacing: -.02em;
}
.bc-kpi-lbl {
  font-size: .67rem; color: var(--text-muted); margin-top: 2px;
  text-transform: uppercase; letter-spacing: .04em; font-weight: 600;
}

/* Rejilla 2×3. El fondo del contenedor hace de línea divisoria: un borde por
   celda dejaría dobles líneas en los cruces. */
.bc-charts {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 1px; background: var(--border);
}
.bc-chart-cell { background: var(--bg-elev); padding: 13px 15px; }
.bc-chart-label {
  font-size: .71rem; font-weight: 700; color: var(--text-soft);
  text-transform: uppercase; letter-spacing: .03em;
  margin-bottom: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bc-chart-h { position: relative; height: 150px; }
/* Leyenda bajo cada gráfica: qué es cada color y cuánto vale. El porcentaje
   lo añade el tooltip al pasar por encima. */
.bc-chart-lg { margin-top: 9px; }
.bc-chart-lg:empty { display: none; }
.bc-chart-lg .gp-legend { gap: 4px 12px; font-size: .68rem; }
.bc-chart-lg .gp-legend .lg b { margin-left: 3px; }
.bc-chart-eje {
  margin-top: 7px; font-size: .64rem; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .03em;
}
.bc-vacio {
  height: 100%; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 6px;
  color: var(--text-muted); font-size: .72rem; opacity: .55;
}
.bc-card-footer {
  padding: 9px 18px; border-top: 1px solid var(--border-soft);
  display: flex; justify-content: flex-end; background: var(--bg-elev);
}

@media (max-width: 700px) {
  .bc-grid { grid-template-columns: 1fr; }
  .bc-charts { grid-template-columns: 1fr; }
}

/* 380 px de mínimo para que en escritorio salgan tres columnas: son seis
   indicadores y así llenan dos filas exactas, sin celda vacía al final. */
.bi-rankings {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--r);
  overflow: hidden;
}
.bi-rank { background: var(--bg-elev); padding: 15px 17px; }
.bi-rank-h {
  display: flex; align-items: center; gap: 7px;
  font-size: .76rem; font-weight: 700; letter-spacing: .02em;
  text-transform: uppercase; color: var(--text-muted);
  margin-bottom: 12px;
}
.bi-rank-h .gp-i { color: var(--accent); }

.color-dot {
  width: 16px; height: 16px; border-radius: 4px; flex: 0 0 auto;
  border: 1px solid rgba(255,255,255,.14);
}
input[type=color].gp-input { padding: 3px; height: 40px; cursor: pointer; }

/* ==========================================================================
   LOGIN
   ========================================================================== */

/* ==========================================================================
   Varios
   ========================================================================== */

.stat-line { display: flex; align-items: center; gap: 9px; padding: 8px 0; font-size: .85rem; }
.stat-line + .stat-line { border-top: 1px solid var(--border-soft); }
.stat-line .sl-dot { width: 9px; height: 9px; border-radius: 3px; flex: 0 0 auto; }
.stat-line .sl-val { margin-left: auto; font-weight: 650; font-variant-numeric: tabular-nums; }

.month-nav { display: flex; align-items: center; gap: 5px; }
.month-nav .mn-label {
  min-width: 132px; text-align: center; font-size: .88rem; font-weight: 650;
  text-transform: capitalize;
}

@media print {
  .topbar, .page-actions, .toolbar, .tb-nav { display: none !important; }
  .page { padding: 0; }
  .gp-card, .table-card { border: 1px solid #ddd; break-inside: avoid; }
}

/* ==========================================================================
   FICHA 360º DE INSTALACIÓN — el submenú por instalación
   ========================================================================== */

.f360 {
  display: grid; grid-template-columns: 224px 1fr;
  gap: 18px; align-items: start;
}
@media (max-width: 1000px) { .f360 { grid-template-columns: 1fr; } }

.f360-nav {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--r); padding: 8px; position: sticky; top: 80px;
}
@media (max-width: 1000px) {
  .f360-nav { position: static; display: flex; gap: 4px; overflow-x: auto; padding: 8px; }
}
.f360-nav button {
  width: 100%; text-align: left; padding: 9px 12px; border: 0;
  border-radius: var(--r-sm); background: none; color: var(--text-soft);
  font-size: .86rem; font-weight: 550; cursor: pointer; transition: all .13s;
  display: flex; align-items: center; gap: 9px; white-space: nowrap;
}
.f360-nav button:hover  { background: var(--bg-card-hover); color: var(--text); }
.f360-nav button.active { background: var(--accent-soft); color: var(--accent); font-weight: 650; }
.f360-nav button .n-badge {
  margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: 99px; font-size: .64rem; font-weight: 700;
  display: grid; place-items: center;
  background: var(--border-strong); color: var(--text);
}
.f360-nav button .n-badge.alert { background: var(--danger); color: #fff; }
.f360-nav button .n-badge.warn  { background: var(--warn); color: #3a2500; }

/* Fila de datos clave en la cabecera de la ficha */
.f360-kpis {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 10px; margin-bottom: 16px;
}
.f360-kpi {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--r-sm); padding: 11px 13px;
}
.f360-kpi .k-l { font-size: .68rem; color: var(--text-muted); text-transform: uppercase;
  letter-spacing: .05em; font-weight: 650; }
.f360-kpi .k-v { font-size: 1.05rem; font-weight: 700; margin-top: 3px; font-variant-numeric: tabular-nums; }
.f360-kpi .k-s { font-size: .7rem; color: var(--text-muted); margin-top: 1px; }

/* ==========================================================================
   PARRILLA DE RESERVAS (espacios × horas)
   ========================================================================== */

/* El contenedor es quien desplaza y quien pone el marco. La rejilla no puede
   llevar `overflow:hidden` —lo traía de `.table-card`— porque eso recortaba
   las últimas horas del día y además convertía a la propia rejilla en el
   contenedor de desplazamiento, con lo que la columna fija de espacios dejaba
   de pegarse a la izquierda.

   El alto está acotado a propósito. La fila de horas y la columna de espacios
   se quedan fijas porque se pegan al borde de ESTE contenedor, y para eso el
   contenedor tiene que desplazarse él, no la página: con la página haciendo
   el scroll, la cabecera de horas se perdía por arriba justo cuando hacía
   falta —al reservar en una instalación de las últimas, sin saber a qué hora
   corresponde la casilla que estás pulsando—. */
.res-scroll {
  overflow: auto; -webkit-overflow-scrolling: touch;
  max-height: calc(100vh - var(--topbar-h) - 210px);
  min-height: 320px;
  overscroll-behavior: contain;
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--r);
}
.res-grid { overflow: visible; }
/* Barras de desplazamiento visibles con el ratón: si no, no se ve que hay
   más día a la derecha ni más instalaciones abajo. */
.res-scroll::-webkit-scrollbar { width: 10px; height: 10px; }
.res-scroll::-webkit-scrollbar-track { background: var(--border-soft); }
.res-scroll::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 999px; }
.res-scroll::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }
.res-scroll::-webkit-scrollbar-corner { background: var(--border-soft); }

.res-grid .rg-head {
  background: var(--bg-elev); padding: 9px 6px; text-align: center;
  font-size: .72rem; font-weight: 650; color: var(--text-soft);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 5;
  font-variant-numeric: tabular-nums;
}
/* La esquina —la celda vacía sobre los nombres— se pega por los dos lados y
   va por encima de todo: si no, la cruzan las horas y los nombres. */
.res-grid .rg-esquina { left: 0; z-index: 7; }
.res-grid .rg-space {
  background: var(--bg-elev); border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border-soft);
  padding: 7px 10px; position: sticky; left: 0; z-index: 4;
}
/* La franja con el nombre de la instalación cruza toda la rejilla. Lo que se
   pega a la izquierda es su CONTENIDO: la franja es tan ancha como su celda y
   no tiene margen para desplazarse ella misma. */
.res-grid .rg-inst { position: static; z-index: 3; }
.res-grid .rg-inst-in {
  position: sticky; left: 10px; width: max-content;
  align-items: baseline;
}
.res-grid .rg-space .s-n { font-size: .78rem; font-weight: 600; }
.res-grid .rg-space .s-i { font-size: .66rem; color: var(--text-muted); }
.res-grid .rg-cell {
  border-bottom: 1px solid var(--border-soft); border-right: 1px solid var(--border-soft);
  min-height: 38px; padding: 3px; cursor: pointer; transition: background .12s;
}
.res-grid .rg-cell:hover { background: var(--bg-card-hover); }
.res-grid .rg-cell .c-in {
  height: 100%; border-radius: 5px; padding: 3px 5px;
  font-size: .66rem; line-height: 1.3; overflow: hidden;
}
.res-grid .rg-cell.libre    .c-in { background: transparent; }
.res-grid .rg-cell.ocupada  .c-in { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.res-grid .rg-cell.pendiente .c-in { background: var(--warn-soft); color: var(--warn); font-weight: 600; }
.res-grid .rg-cell.bloqueada .c-in {
  background: repeating-linear-gradient(45deg, var(--border-soft) 0 5px, transparent 5px 10px);
  color: var(--text-muted);
}
/* Solicitud de club sin resolver: ni libre ni confirmada. Se marca con borde
   discontinuo para que se lea "esto está en el aire" de un vistazo. */
.res-grid .rg-cell.solicitada .c-in {
  background: var(--purple-soft); color: var(--purple);
  border: 1px dashed var(--purple); font-weight: 600;
}
/* Fuera del horario de apertura. NO es una franja libre: no existe. Sin
   cursor de mano y con fondo apagado, para que nadie intente reservarla. */
.res-grid .rg-cell.cerrada {
  background: var(--bg-elev); cursor: not-allowed;
  background-image: repeating-linear-gradient(45deg,
    var(--border-soft) 0 1px, transparent 1px 7px);
  opacity: .55;
}
.res-grid .rg-cell.cerrada:hover { background-color: var(--bg-elev); }
.res-grid .rg-cell.pasada { opacity: .45; cursor: default; }

/* Con paso de 30 minutos la columna de la media se atenúa: así la hora en
   punto sigue siendo la referencia visual al recorrer la parrilla. */
.res-grid .rg-head.media { color: var(--text-muted); font-weight: 500; opacity: .75; }

/* Rótulo con el nombre de quien ocupa la franja (club, servicio, ciudadano).
   Solo aparece en la primera franja de la reserva. */
.res-grid .rg-cell .c-in { display: flex; align-items: center; gap: 3px; }
.res-grid .rg-cell .c-lb {
  font-size: .6rem; font-weight: 600; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}

/* Cuadraditos de la leyenda */
.lg-box { width: 12px; height: 12px; border-radius: 3px; display: inline-block; flex: 0 0 auto; }
.lg-box.lg-sol     { background: var(--purple-soft); border: 1px dashed var(--purple); }
.lg-box.lg-cerrado { background: var(--bg-elev); border: 1px solid var(--border);
  background-image: repeating-linear-gradient(45deg, var(--border-soft) 0 1px, transparent 1px 5px); }

/* ==========================================================================
   Varios del panel municipal
   ========================================================================== */

/* Cabecera de sección dentro de la ficha */
.sec-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin: 0 0 12px; flex-wrap: wrap;
}
.sec-head h3 { font-size: .98rem; font-weight: 650; }
.sec-head .sh-sub { font-size: .76rem; color: var(--text-muted); margin-top: 2px; }

/* Tarjeta de instalación en el listado */
.inst-row-ico {
  width: 34px; height: 34px; border-radius: 9px; flex: 0 0 auto;
  display: grid; place-items: center; font-size: 1rem;
  background: var(--accent-soft); color: var(--accent);
}

/* Comparativa directa vs indirecta */
.vs-box {
  display: grid; grid-template-columns: 1fr auto 1fr; gap: 14px; align-items: center;
}
.vs-side { text-align: center; padding: 14px; border-radius: var(--r); background: var(--bg-card); border: 1px solid var(--border); }
.vs-side .v-l { font-size: .72rem; color: var(--text-muted); font-weight: 650; text-transform: uppercase; letter-spacing: .04em; }
.vs-side .v-v { font-size: 1.5rem; font-weight: 700; margin: 5px 0 2px; font-variant-numeric: tabular-nums; }
.vs-side .v-s { font-size: .72rem; color: var(--text-muted); }
.vs-mid { font-size: .8rem; color: var(--text-muted); font-weight: 700; }
@media (max-width: 640px) { .vs-box { grid-template-columns: 1fr; } .vs-mid { display: none; } }

/* ==========================================================================
   Ajustes para iconos vectoriales
   Los contenedores estaban dimensionados con font-size para emoji; con SVG
   hay que alinear con flex y quitar el tamaño de fuente.
   ========================================================================== */

.gp-notice .n-ico,
.gp-empty .e-ico,
.info-row .ir-ic,
.row-card .rc-ico,
.recibo .rc-ico,
.inst-card .ic-ico,
.menu-item .mi-ic,
.feed-item .feed-ic,
.stat-line > span:first-child,
.attendee .gp-avatar,
.pay-ok .po-ic {
  display: inline-flex; align-items: center; justify-content: center;
  line-height: 0;
}
.gp-notice .n-ico     { font-size: 0; margin-top: 1px; }
.gp-empty .e-ico      { font-size: 0; color: var(--text-muted); opacity: .75; margin-bottom: 12px; }
.info-row .ir-ic      { font-size: 0; margin-top: 2px; }
.pay-ok .po-ic        { font-size: 0; }
.auth-logo            { font-size: 0; color: #fff; }
.hd-logo              { font-size: 0; color: #fff; }
.hd-btn               { font-size: 0; }
.tabbar button .ic    { font-size: 0; }

/* Los badges con icono necesitan alinear el SVG con el texto */
.gp-badge .gp-i, .gp-regimen .gp-i, .gp-chip .gp-i { margin-right: 1px; }
.gp-btn .gp-i { margin-right: -2px; }
.gp-btn.icon .gp-i { margin: 0; }

/* Iconos vectoriales en la topbar y en la navegación de secciones */
.tb-logo, .tb-btn, .tb-link .ic { font-size: 0; }
.tb-link .ic, .tb-btn { display: inline-flex; align-items: center; justify-content: center; }
.f360-nav button > span:first-child,
.gp-kpi .k-ico, .gc-kpi .k-ico,
.gp-facility-head .fh-ico, .gp-meter .m-ico,
.gp-doc .d-ico, .inst-row-ico, .login-logo-icon,
.setup-section-icon {
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 0; line-height: 0;
}
.gp-doc .d-ico, .gc-doc .d-ico { font-size: .58rem; font-weight: 700; letter-spacing: .02em; }
.gp-timeline .tl-title .gp-i { vertical-align: -0.2em; }

/* Base del propio SVG: cuando va suelto dentro de un texto necesita bajar un
   poco respecto a la línea base, y nunca debe encogerse dentro de un flex. */
.gp-i { vertical-align: -0.18em; flex: 0 0 auto; }
.gp-i * { vector-effect: non-scaling-stroke; }

/* Contenedores que quedaban por normalizar */
.res-grid .rg-cell .c-in,
.gp-titular,
.gp-tabs button > span:first-child {
  display: inline-flex; align-items: center; justify-content: center; line-height: 0;
}
.res-grid .rg-cell .c-in { font-size: .68rem; }
.gp-titular { font-size: 0; }
.bonif-chip .gp-i { margin-right: 2px; vertical-align: -0.2em; }

/* ==========================================================================
   EDITOR DE TRAMOS HORARIOS
   Un día puede abrir en dos turnos (mañana y tarde).
   ========================================================================== */

.horario-edit td { vertical-align: top; }
.horario-edit .tramos { display: flex; flex-direction: column; gap: 6px; }
/* Con dos botones por fila (partir y quitar) el ancho va justo dentro de la
   columna del modal: de ahí los campos de hora más estrechos y el hueco
   mínimo entre piezas. */
.tramo { display: flex; align-items: center; gap: 4px; }
.tramo .gp-input[type="time"] { width: 92px; flex: 0 0 auto; padding-left: 8px; padding-right: 4px; }
.tramo .t-sep { color: var(--text-muted); font-size: .82rem; margin: 0 1px; }
.tramo .gp-btn.xs {
  padding: 4px 6px; font-size: .7rem; line-height: 1;
  display: inline-flex; align-items: center; gap: 4px;
}
.tramo .gp-btn.xs.icon { padding: 4px; width: auto; height: auto; }
.gp-btn.xs {
  padding: 5px 9px; font-size: .74rem; border-radius: 7px;
  display: inline-flex; align-items: center; gap: 5px;
}
.tramo input:disabled, .gp-btn.xs:disabled { opacity: .45; cursor: not-allowed; }

/* Las tijeras van en la propia fila, junto a la papelera, y en amarillo:
   partir un tramo es la acción habitual y la papelera la excepcional, así que
   es la que lleva el color. Deshabilitadas cuando el tramo es muy corto para
   partirlo, para que no haya que pulsar para enterarse. */
/* Calificado con .gp-btn: si no, el gris de .gp-btn.ghost gana por
   especificidad y las tijeras salen del mismo color que la papelera. */
.gp-btn.tramo-split { color: var(--accent); }
.gp-btn.tramo-split:hover:not(:disabled) { background: var(--accent-soft); color: var(--accent); }
.tramo .gp-btn.xs:disabled { opacity: .3; }

/* ==========================================================================
   TRABAJADORES
   Plantilla municipal, cuadrantes y control de jornada.
   ========================================================================== */

.f360-body { min-width: 0; }

.trab-grid { grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); }

.trab-card {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--r); padding: 14px; cursor: pointer;
  transition: border-color .15s, transform .15s;
}
.trab-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.trab-card.inactivo { opacity: .62; }
.trab-card .tc-head { display: flex; align-items: center; gap: 11px; }
.trab-card .tc-name { font-weight: 650; font-size: .92rem; letter-spacing: -.01em; }
.trab-card .tc-cat  { font-size: .74rem; color: var(--text-muted); margin-top: 2px; }
.trab-card .tc-dot {
  width: 9px; height: 9px; border-radius: 50%; background: var(--ok);
  flex: 0 0 auto; box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 22%, transparent);
}
.trab-card .tc-meta { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 11px; }
.trab-card .tc-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--border-soft);
  font-size: .72rem; color: var(--text-muted); min-width: 0;
}
.trab-card .tc-foot span { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }

.perm-card { border-left: 3px solid var(--warn); }

/* Listas de definición de la ficha */
.gp-dl { display: grid; grid-template-columns: auto 1fr; gap: 7px 16px; margin: 0; }
.gp-dl dt { font-size: .76rem; color: var(--text-muted); }
.gp-dl dd { font-size: .82rem; font-weight: 600; margin: 0; text-align: right; }

@media (max-width: 560px) {
  .trab-grid { grid-template-columns: 1fr; }
  .gp-dl { grid-template-columns: 1fr; gap: 2px 0; }
  .gp-dl dd { text-align: left; margin-bottom: 8px; }
}

/* ==========================================================================
   CONTROL DE JORNADA
   --------------------------------------------------------------------------
   Misma estructura que los checks de GestionaFitness: una tarjeta por
   persona con lo que lleva del mes, y al entrar, su mes día a día.
   ========================================================================== */
.ck-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
}
.pfilter { display: flex; gap: 6px; flex-wrap: wrap; flex: 1; }
.pfilter-btn {
  padding: 6px 14px; border-radius: 99px;
  font-size: .78rem; font-weight: 500; color: var(--text-soft);
  background: var(--bg-card); border: 1px solid var(--border);
  cursor: pointer; font-family: inherit; transition: var(--transition, .15s);
}
.pfilter-btn:hover { border-color: var(--border-strong); color: var(--text); }
.pfilter-btn.active {
  background: var(--accent); border-color: var(--accent);
  color: var(--accent-text); font-weight: 700;
}

.ck-grid { grid-template-columns: repeat(auto-fill, minmax(258px, 1fr)); }
.ck-card {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius, 14px); padding: 14px 16px; cursor: pointer;
  transition: border-color .15s, transform .15s;
}
.ck-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.ck-card.alerta { border-color: var(--danger); }
.ck-nums { display: flex; gap: 6px; margin-top: 12px; }
.ck-nums > div {
  flex: 1; text-align: center; padding: 7px 4px;
  background: var(--bg-input); border-radius: 9px; min-width: 0;
}
.ck-nums b { display: block; font-size: .95rem; font-weight: 800; }
.ck-nums span { font-size: .66rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }

.ck-head {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius, 14px); padding: 14px 18px; margin-bottom: 14px;
}
.ck-dias tbody tr.ck-finde td { background: var(--border-soft); }
.ck-dias tbody tr.ck-alerta td { background: rgba(249, 115, 22, .07); }

/* ==========================================================================
   HOJA DE CONTROL DE AUSENCIAS
   --------------------------------------------------------------------------
   Rejilla persona × día del mes, como la hoja de control de GestionaFitness.
   El nombre queda fijo a la izquierda al desplazar en horizontal, que es lo
   que permite leer la fila cuando el mes tiene 31 columnas.
   ========================================================================== */
.hc-meses { display: flex; gap: 5px; flex-wrap: wrap; margin-bottom: 12px; }
.hc-meses .pfilter-btn { padding: 5px 11px; font-size: .74rem; }

.hc-leyenda { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-bottom: 12px; }
.hc-lg { display: inline-flex; align-items: center; gap: 6px; font-size: .72rem; color: var(--text-soft); }
.hc-lg i { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }
.hc-lg i.hueco { background: none; border: 1.5px dashed var(--text-muted); }

.hc-wrap {
  overflow-x: auto; border: 1px solid var(--border);
  border-radius: var(--radius, 14px); background: var(--bg-card);
}
.hc-cab, .hc-fila { display: flex; align-items: center; min-width: max-content; }
.hc-cab { border-bottom: 1px solid var(--border); background: var(--bg-elev); }
.hc-fila { border-bottom: 1px solid var(--border-soft); min-height: 34px; }
.hc-fila:last-child { border-bottom: none; }
.hc-fila:hover { background: var(--bg-card-hover); }

.hc-nombre {
  position: sticky; left: 0; z-index: 3;
  flex: 0 0 210px; max-width: 210px;
  display: flex; align-items: center; gap: 8px;
  padding: 5px 12px; font-size: .78rem; font-weight: 600;
  background: var(--bg-elev); border-right: 1px solid var(--border);
  min-width: 0;
}
.hc-fila .hc-nombre { background: var(--bg-elev); }

.hc-celdas { display: flex; }
.hc-dia {
  flex: 0 0 28px; text-align: center; padding: 4px 0; line-height: 1.15;
  border-right: 1px solid var(--border-soft);
}
.hc-dia b { display: block; font-size: .68rem; font-weight: 700; }
.hc-dia span { font-size: .58rem; color: var(--text-muted); }
.hc-dia.finde b, .hc-dia.finde span { color: var(--info, #38bdf8); }
.hc-dia.hoy { box-shadow: inset 0 -2px 0 var(--accent); }

.hc-celda {
  flex: 0 0 28px; height: 34px; cursor: pointer; box-sizing: border-box;
  display: flex; align-items: center; justify-content: center;
  border-right: 1px solid var(--border-soft);
  font-size: .56rem; font-weight: 800;
  transition: background .12s;
}
.hc-celda:hover { background: var(--bg-card-hover); box-shadow: inset 0 0 0 1px var(--accent); }
.hc-celda.finde { background: var(--border-soft); }
/* Hoy se marca con una línea vertical, no con un recuadro: un recuadro por
   fila convierte la columna en una escalera de cajas y tapa las ausencias. */
.hc-celda.hoy { border-right-color: var(--accent); background: rgba(252, 169, 5, .07); }
.hc-celda.llena { color: #0b1220; text-shadow: 0 1px 2px rgba(0, 0, 0, .18); }
.hc-celda.llena.pedido { background: none !important; border: 1.5px dashed currentColor; text-shadow: none; }

/* Selector de tipo dentro del modal de ausencia */
.hc-tipos { display: flex; flex-wrap: wrap; gap: 6px; }
.hc-tipo {
  padding: 6px 12px; border-radius: 99px; cursor: pointer; font-family: inherit;
  font-size: .76rem; font-weight: 600; color: var(--text-soft);
  background: var(--bg-input); border: 1.5px solid var(--border);
}
.hc-tipo:hover { border-color: var(--c); color: var(--text); }
.hc-tipo.on { background: var(--c); border-color: var(--c); color: #0b1220; }

/* Tarjeta de solicitud pendiente */
.sol-card {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  background: var(--bg-card); border: 1px solid var(--border);
  border-left: 3px solid var(--c); border-radius: var(--radius, 14px);
  padding: 13px 16px; margin-bottom: 9px;
}

@media (max-width: 720px) {
  .hc-nombre { flex-basis: 148px; max-width: 148px; }
}

/* ==========================================================================
   MENSAJERÍA INTERNA
   --------------------------------------------------------------------------
   Lista de conversaciones + hilo, como cualquier mensajería. La altura se fija
   al alto de la ventana menos la topbar y el submenú, porque un chat que
   crece hacia abajo obliga a desplazar la página entera para escribir.
   ========================================================================== */
.chat-layout {
  display: grid; grid-template-columns: 320px 1fr; gap: 14px;
  height: calc(100vh - var(--topbar-h) - 260px); min-height: 440px;
}

/* min-width: 0 en los dos hijos del grid: sin esto, un nombre o una vista
   previa largos ensanchan la columna por encima del 1fr y en móvil la página
   entera se desplaza en horizontal. */
.chat-lista, .chat-panel { min-width: 0; }

.chat-lista {
  display: flex; flex-direction: column; min-height: 0;
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius, 14px); overflow: hidden;
}
.chat-lista-top { padding: 12px; border-bottom: 1px solid var(--border); flex: 0 0 auto; }
.chat-nueva { width: 100%; justify-content: center; }
.chat-lista-top .pfilter { gap: 5px; }
.chat-lista-top .pfilter-btn { padding: 4px 10px; font-size: .72rem; }
.chat-convs { flex: 1; overflow-y: auto; min-height: 0; }

.chat-conv {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 13px; cursor: pointer; min-width: 0;
  border-bottom: 1px solid var(--border-soft);
  transition: background .14s;
}
.chat-conv:hover { background: var(--bg-card-hover); }
.chat-conv.activa { background: var(--bg-card-hover); box-shadow: inset 3px 0 0 var(--accent); }
.chat-prev { font-size: .74rem; color: var(--text-muted); margin-top: 2px; }
.chat-prev .gp-i { vertical-align: -1px; }
.chat-badge {
  flex: 0 0 auto; min-width: 19px; height: 19px; padding: 0 6px;
  display: grid; place-items: center; border-radius: 99px;
  background: var(--accent); color: var(--accent-text);
  font-size: .68rem; font-weight: 800;
}

.chat-panel {
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius, 14px);
}
.chat-head {
  display: flex; align-items: center; gap: 11px; flex: 0 0 auto;
  padding: 11px 15px; border-bottom: 1px solid var(--border);
}
.chat-volver { display: none; }

.chat-mensajes {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 18px; display: flex; flex-direction: column; gap: 9px;
}

/* Con pocos mensajes, la conversación se pega abajo, como en cualquier
   mensajería. Se hace con margin-top en el primer hijo y no con
   justify-content: flex-end, que en una columna con scroll deja inalcanzable
   lo que se desborda por arriba. */
.chat-mensajes > :first-child { margin-top: auto; }

.chat-vacio {
  flex: 1; display: flex; flex-direction: column; gap: 7px;
  align-items: center; justify-content: center; text-align: center; padding: 30px;
}
.chat-vacio .e-ico { color: var(--text-muted); }

.chat-dia { display: flex; justify-content: center; margin: 8px 0 2px; }
.chat-dia span {
  font-size: .68rem; font-weight: 600; color: var(--text-muted);
  background: var(--bg-input); border-radius: 99px; padding: 3px 12px;
  text-transform: capitalize;
}

.chat-b { display: flex; flex-direction: column; max-width: min(72%, 520px); }
.chat-b.suyo { align-self: flex-start; }
.chat-b.mio  { align-self: flex-end; align-items: flex-end; }
.chat-bub { padding: 9px 13px; border-radius: 14px; }
.chat-b.suyo .chat-bub {
  background: var(--bg-input); border: 1px solid var(--border);
  border-bottom-left-radius: 4px;
}
.chat-b.mio .chat-bub {
  background: var(--accent); color: var(--accent-text);
  border-bottom-right-radius: 4px;
}
.chat-txt { font-size: .86rem; line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
.chat-dif {
  font-size: .66rem; font-weight: 700; opacity: .8;
  display: flex; align-items: center; gap: 4px; margin-bottom: 4px;
  padding-bottom: 4px; border-bottom: 1px solid currentColor;
}
.chat-meta {
  font-size: .66rem; color: var(--text-muted);
  margin-top: 3px; padding: 0 4px;
  display: inline-flex; align-items: center; gap: 4px;
}
.chat-tics { display: inline-flex; color: var(--text-muted); }
.chat-tics.leido { color: #38bdf8; }

.chat-barra {
  flex: 0 0 auto; display: flex; align-items: flex-end; gap: 8px;
  padding: 11px 14px; border-top: 1px solid var(--border);
}
.chat-barra .gp-textarea {
  flex: 1; min-height: 40px; max-height: 130px; resize: none;
  padding: 9px 12px; line-height: 1.45;
}

@media (max-width: 900px) {
  /* En móvil no caben las dos columnas: se enseña la lista, y al abrir una
     conversación el hilo la tapa entera con su botón de volver. */
  .chat-layout { grid-template-columns: 1fr; height: auto; }
  .chat-lista { max-height: 46vh; }
  .chat-panel { min-height: 60vh; }
  .chat-volver { display: inline-flex; }
}

/* ==========================================================================
   COLOR E IMAGEN DE UNA ACTIVIDAD
   --------------------------------------------------------------------------
   La vista previa se enseña ya atenuada y con su franja de color: el gestor
   elige mirando lo que va a ver el ciudadano en la app, no la foto suelta.
   ========================================================================== */
.color-input { width: 52px; padding: 3px; height: 36px; cursor: pointer; flex: 0 0 auto; }
.color-swatch {
  width: 20px; height: 20px; border-radius: 6px; padding: 0;
  border: 1.5px solid var(--border-strong); cursor: pointer;
  transition: transform .12s;
}
.color-swatch:hover { transform: scale(1.18); }

.act-media { border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }

.act-media .am-prev,
.act-media .am-empty { position: relative; height: 112px; }
.act-media .am-prev { background-size: cover; background-position: center; }

/* La misma capa que la tarjeta de la app en modo oscuro */
.act-media .am-prev::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(10,16,28,.84) 0%, rgba(10,16,28,.76) 58%, rgba(10,16,28,.62) 100%);
  backdrop-filter: saturate(.75) blur(1.5px);
  -webkit-backdrop-filter: saturate(.75) blur(1.5px);
}
html[data-theme="light"] .act-media .am-prev::after {
  background: linear-gradient(90deg, rgba(255,255,255,.9) 0%, rgba(255,255,255,.84) 58%, rgba(255,255,255,.72) 100%);
}
/* La franja de color, igual que en la app */
.act-media .am-prev::before,
.act-media .am-empty::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--act, var(--accent)); z-index: 2;
}

.act-media .am-txt { position: relative; z-index: 1; padding: 15px 17px; }
.act-media .am-name { font-weight: 700; font-size: .95rem; color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.7); }
.act-media .am-meta { font-size: .74rem; color: rgba(255,255,255,.85); margin-top: 2px; text-shadow: 0 1px 3px rgba(0,0,0,.7); }
html[data-theme="light"] .act-media .am-name { color: var(--text); text-shadow: 0 1px 3px rgba(255,255,255,.95); }
html[data-theme="light"] .act-media .am-meta { color: var(--text-soft); text-shadow: 0 1px 3px rgba(255,255,255,.95); }

.act-media .am-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 7px; color: var(--text-muted); font-size: .78rem; text-align: center; padding: 0 16px;
  background: var(--bg-input);
}
.act-media .am-empty .gp-i { opacity: .5; }

.act-media .am-actions {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 10px 12px; border-top: 1px solid var(--border);
}
/* El botón de subir es un <label> con el input dentro: se comporta como botón */
.act-media .am-actions label.gp-btn { cursor: pointer; }

/* Miniatura en los listados del panel, para reconocer la actividad de un
   vistazo sin tener que abrir su ficha. */
.act-thumb {
  width: 34px; height: 24px; border-radius: 5px; flex: 0 0 auto;
  background-size: cover; background-position: center;
  border: 1px solid var(--border);
}

/* ==========================================================================
   EXPEDIENTES · tarjeta plegable
   --------------------------------------------------------------------------
   Con miles de expedientes, uno que ocupa media pantalla hace la lista
   irrecorrible. Arriba queda lo justo para localizarlo —número, estado, tipo
   y objeto— y el resto se abre al pulsar.
   ========================================================================== */
.exp-card {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius, 14px); margin-bottom: 10px;
  transition: border-color .15s, background .15s;
}
.exp-card:hover { border-color: var(--border-strong); }
.exp-card.abierto { border-color: var(--accent); background: var(--bg-card-hover); }

.exp-head {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 13px 15px; cursor: pointer; min-width: 0;
}
.exp-head:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; border-radius: var(--radius, 14px); }

.exp-flecha {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 20px; height: 20px; margin-top: 1px;
  color: var(--text-muted); transition: transform .18s, color .18s;
}
.exp-card.abierto .exp-flecha { transform: rotate(90deg); color: var(--accent); }

/* Plazo consumido en la cabecera: fina y sin la cifra dentro, para que no
   compita con el objeto del expediente. La versión gruesa vive dentro del
   desplegable, que es donde se va a leer con detenimiento. */
.exp-plazo { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.exp-plazo .gp-bar { flex: 1 1 auto; height: 4px; }
.exp-plazo .gp-xs { flex: 0 0 auto; font-variant-numeric: tabular-nums; }

.exp-detalle {
  padding: 0 15px 14px 46px;
  border-top: 1px solid var(--border-soft);
  margin-top: 2px; padding-top: 13px;
  animation: expAbrir .16s ease;
}
@keyframes expAbrir { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }

@media (max-width: 620px) {
  /* En móvil el botón no cabe al lado del texto: baja a su propia línea */
  .exp-head { flex-wrap: wrap; }
  .exp-head > .gp-btn { margin-left: 31px; }
  .exp-detalle { padding-left: 15px; }
}

/* Expedientes de la empresa en la cabecera de su conversación: un atajo a
   su ficha sin salir del canal. */
.emp-exp {
  display: flex; gap: 6px; flex-wrap: wrap;
  padding: 9px 15px; border-bottom: 1px solid var(--border-soft);
}
.emp-exp .gp-badge { text-decoration: none; }
.emp-exp .gp-badge:hover { border-color: var(--accent); color: var(--accent); }

/* Cupos de una persona en su ficha. Van arriba, fuera de las pestañas: lo
   primero que se pregunta al abrir la ficha de alguien es cuántos días le
   quedan, no en qué turno está. */
.cupos-fila {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px;
}
.cupo-box {
  background: var(--bg-input); border-radius: var(--r-sm); padding: 11px 13px; min-width: 0;
}
.cupo-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.cupo-lab { font-size: .7rem; color: var(--text-muted); font-weight: 650;
  text-transform: uppercase; letter-spacing: .04em; }
.cupo-num { font-size: .78rem; color: var(--text-soft); white-space: nowrap; }
.cupo-num b { font-size: 1.15rem; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.cupo-box .gp-bar { margin-top: 7px; }
.cupo-pie { font-size: .68rem; color: var(--text-muted); margin-top: 5px; }

/* ==========================================================================
   PUBLICACIÓN Y SELECCIÓN EN BLOQUE
   --------------------------------------------------------------------------
   Un gestor da de alta la temporada entera —veinte o treinta grupos— antes de
   que nada salga en la app. Por eso el alta nace sin publicar y hay que poder
   publicarlo todo de una vez cuando está revisado.
   ========================================================================== */
.gp-table th.col-check, .gp-table td.col-check { width: 34px; padding-right: 0; }
.gp-table td.col-check input, .gp-table th.col-check input {
  cursor: pointer; accent-color: var(--accent);
}

/* Lo que no está publicado se apaga: se ve que está ahí pero que no cuenta */
.gp-table tr.sin-publicar td { opacity: .55; }
.gp-table tr.sin-publicar td.col-check,
.gp-table tr.sin-publicar td:last-child,
.gp-table tr.sin-publicar td:nth-last-child(2) { opacity: 1; }

.sel-barra {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  border-radius: var(--radius, 14px); padding: 10px 14px; margin-bottom: 12px;
}

/* Interruptor pequeño para la columna de publicación */
.gp-switch.sm { transform: scale(.82); transform-origin: left center; }

/* --------------------------------------------------------------------------
   Bloque de eliminación de la ficha
   Plegado por defecto y separado del formulario por una línea: eliminar un
   cursillo no puede estar al lado de «Guardar». El desplegable es en sí mismo
   el primer freno — hay que abrirlo para ver el botón.
   -------------------------------------------------------------------------- */
.zona-peligro {
  margin-top: 6px; padding-top: 14px;
  border-top: 1px dashed var(--border);
}
.zona-peligro > summary {
  cursor: pointer; list-style: none;
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .82rem; font-weight: 600; color: var(--danger);
  padding: 4px 2px;
}
.zona-peligro > summary::-webkit-details-marker { display: none; }
.zona-peligro > summary:hover { text-decoration: underline; }
.zona-peligro .zp-cuerpo {
  margin-top: 10px; padding: 12px 14px;
  background: var(--danger-soft); border-radius: var(--radius, 14px);
}
.zona-peligro .zp-cuerpo p { margin: 0 0 10px; line-height: 1.5; }

/* Lista de consecuencias del borrado: cada línea, un daño concreto */
.lista-danos {
  margin: 0; padding-left: 18px;
  font-size: .82rem; line-height: 1.65; color: var(--text);
}
.lista-danos li { margin-bottom: 3px; }
.lista-danos li::marker { color: var(--danger); }

/* --------------------------------------------------------------------------
   Barra de temporada
   La programación deportiva va por temporada, no por año natural, así que la
   pantalla tiene que decir en todo momento dentro de cuál se está trabajando.
   Va encima de los indicadores porque no es un filtro más: es el marco de
   todo lo que hay debajo.
   -------------------------------------------------------------------------- */
.temp-bar {
  display: flex; align-items: flex-end; flex-wrap: wrap; gap: 14px 22px;
  padding: 14px 18px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius, 14px);
}
/* El color del borde dice de un vistazo en qué momento está la temporada */
.temp-bar.planificacion { border-left-color: var(--warn); }
.temp-bar.activa        { border-left-color: var(--ok); }
.temp-bar.cerrada       { border-left-color: var(--border); opacity: .92; }

.temp-bar .tb-sel { min-width: 240px; }
.temp-bar .tb-sel .gp-label { display: block; margin-bottom: 4px; }
.temp-bar .tb-info {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 14px;
  padding-bottom: 8px;
}
.temp-bar .tb-acc { display: flex; gap: 8px; margin-left: auto; padding-bottom: 4px; }

@media (max-width: 720px) {
  .temp-bar { align-items: stretch; }
  .temp-bar .tb-sel { min-width: 0; width: 100%; }
  .temp-bar .tb-acc { margin-left: 0; }
}

/* ==========================================================================
   ENCUESTAS DE SATISFACCIÓN
   Mismo formato que GestionaFitness: tarjeta por encuesta con su participación
   y su nota, y resultados desglosados por pregunta.
   ========================================================================== */
.enc-grid {
  display: grid; gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
}
.enc-card {
  background: var(--bg-card); border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius, 14px); padding: 15px 17px;
}
/* Solo las abiertas llevan color: son las que aún admiten respuestas */
.enc-card.abierta { border-left-color: var(--ok); }
.enc-card .enc-cifra { margin-top: 12px; }
.enc-card .enc-cifra b { font-size: 1.35rem; font-variant-numeric: tabular-nums; }
.enc-card .enc-nota {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 11px; padding-top: 11px; border-top: 1px solid var(--border-soft);
}
.enc-card .enc-acc { gap: 7px; margin-top: 12px; }

.enc-num {
  font-size: 1.05rem; font-weight: 700; color: var(--text);
  font-variant-numeric: tabular-nums;
}
.enc-num.ok     { color: var(--ok); }
.enc-num.warn   { color: var(--warn); }
.enc-num.danger { color: var(--danger); }

/* Estrellas de solo lectura. El icono es el mismo lleno o vacío: lo que
   cambia es el relleno, así no bailan de tamaño al pintarse. */
.estrellas { display: inline-flex; gap: 1px; }
.estrellas .est { display: inline-flex; color: var(--border-strong); }
.estrellas .est.on { color: #f5b301; fill: #f5b301; }
.estrellas .est.on svg { fill: #f5b301; }

/* Selector de tipo de valoración en el alta */
.tipo-enc {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 14px; border-radius: var(--r-sm);
  background: var(--bg-input); border: 1px solid var(--border);
  color: var(--text-soft); font-size: .84rem; cursor: pointer; transition: all .14s;
}
.tipo-enc:hover { background: var(--bg-card-hover); color: var(--text); }
.tipo-enc.active {
  background: var(--accent-soft); border-color: var(--accent); color: var(--text);
}

/* Editor de preguntas */
.enc-item {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--r-sm); padding: 11px 12px; margin-bottom: 9px;
}
.enc-item .gp-check { font-size: .78rem; }

/* Resultados por pregunta */
.res-item {
  padding: 14px 0; border-bottom: 1px solid var(--border-soft);
}
.res-item:last-child { border-bottom: 0; }
.res-coment {
  background: var(--bg-card); border-left: 2px solid var(--accent);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  padding: 8px 11px; margin-bottom: 6px;
  font-size: .82rem; color: var(--text-soft); font-style: italic;
}
.res-coment::before { content: '“'; }
.res-coment::after  { content: '”'; }

/* Reparto de notas: sin él, una media de 3,5 puede ser todo el mundo en el 3
   y el 4, o media clase en el 1 y media en el 5. */
.rep-barras { display: flex; align-items: flex-end; gap: 4px; height: 54px; margin-top: 10px; }
.rep-col { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: 3px; }
.rep-b {
  width: 100%; height: 38px; display: flex; align-items: flex-end;
  background: var(--border-soft); border-radius: 3px; overflow: hidden;
}
.rep-b > i { width: 100%; background: var(--accent); border-radius: 3px; min-height: 2px; }

/* Tramos del NPS en una sola barra */
.nps-barra {
  display: flex; height: 26px; border-radius: var(--r-pill); overflow: hidden;
  background: var(--border-soft);
}
.nps-barra > i {
  display: flex; align-items: center; justify-content: center;
  font-size: .7rem; font-weight: 700; color: #fff; font-style: normal;
  transition: width .3s;
}
.nps-barra > i.det { background: var(--danger); }
.nps-barra > i.pas { background: var(--text-muted); }
.nps-barra > i.pro { background: var(--ok); }

/* ==========================================================================
   REPARTO DEL TOPE DEL PLIEGO POR ÁREAS
   ========================================================================== */
.areas-pliego {
  border: 1px solid var(--border); border-radius: var(--radius, 14px);
  background: var(--bg-card);
}
.areas-pliego > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; gap: 7px;
  padding: 11px 14px; font-size: .84rem; font-weight: 600; color: var(--text-soft);
}
.areas-pliego > summary::-webkit-details-marker { display: none; }
.areas-pliego > summary:hover { color: var(--text); }
.areas-pliego[open] > summary { border-bottom: 1px solid var(--border-soft); color: var(--text); }
.areas-pliego .ap-cuerpo { padding: 12px 14px 14px; }
.areas-pliego .ap-cuerpo > p { margin: 0 0 12px; line-height: 1.5; }

/* Una línea por área: el bloque ocupa el ancho del modal, así que caben el
   desplegable y las dos cifras sin apretar. Los rótulos van dentro de cada
   campo, y las cajas se alinean por abajo para que el desplegable quede a la
   altura de los números. */
.ap-fila {
  display: grid; grid-template-columns: minmax(170px, 1fr) 150px 170px 32px;
  grid-template-areas: 'area horas coste quitar';
  gap: 7px 10px; align-items: end;
  padding: 9px 10px; margin-bottom: 8px;
  background: var(--bg-input); border-radius: var(--r-sm);
}
/* En pantalla estrecha vuelve a dos líneas: antes que encoger el desplegable
   hasta que no se lea el área, se parte. */
@media (max-width: 900px) {
  .ap-fila {
    grid-template-columns: 1fr 1fr 32px;
    grid-template-areas: 'area area quitar' 'horas coste .';
  }
}
.ap-fila .ap-sel    { grid-area: area; }
.ap-fila .ap-area   { min-width: 0; }
.ap-fila .ap-quitar { grid-area: quitar; }
.ap-fila .ap-campo:nth-of-type(2) { grid-area: horas; }
.ap-fila .ap-campo:nth-of-type(3) { grid-area: coste; }
.ap-campo { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.ap-fila .gp-input { text-align: right; font-variant-numeric: tabular-nums; }
.ap-suma {
  padding-top: 10px; border-top: 1px solid var(--border-soft);
  display: flex; flex-direction: column; gap: 3px;
}


/* ==========================================================================
   REQUERIMIENTOS A LA ADJUDICATARIA
   ========================================================================== */
.req-lista { display: flex; flex-direction: column; gap: 10px; }
.req-fila {
  display: flex; gap: 14px; flex-wrap: wrap; align-items: flex-start;
  padding: 13px 15px;
  background: var(--bg-card); border: 1px solid var(--border);
  border-left: 3px solid var(--border-strong);
  border-radius: var(--radius, 14px);
}
/* El color del canto es el plazo: es lo primero que hay que ver */
.req-fila.warn   { border-left-color: var(--warn); }
.req-fila.danger { border-left-color: var(--danger); }
.req-fila.ok     { border-left-color: var(--ok); }
.req-fila .req-acc { gap: 6px; flex: 0 0 auto; }
.req-doc {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: var(--r-sm);
  background: var(--ok-soft); color: var(--ok);
  font-size: .72rem;
}

/* ==========================================================================
   SEGUIMIENTO DEL CONTRATO
   --------------------------------------------------------------------------
   Tabla de doble entrada: los compromisos que ofertó la adjudicataria contra
   los años del contrato. La primera columna se queda fija al desplazar en
   horizontal, porque una casilla marcada sin ver de qué mejora es no dice
   nada; y las celdas son altas a propósito, que ahí abajo va la nota con lo
   que se hizo de verdad.
   ========================================================================== */
.sg-avance { padding: 11px 13px; background: var(--bg-elev); border-radius: var(--r-sm); }

.sg-scroll { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--r-sm); }
.sg-tabla {
  width: 100%; border-collapse: separate; border-spacing: 0;
  font-size: .84rem; background: var(--bg-card);
}
.sg-tabla th, .sg-tabla td {
  border-bottom: 1px solid var(--border-soft); vertical-align: top; text-align: left;
}

/* --- Columna del compromiso: fija a la izquierda --- */
.sg-tabla .sg-titulo {
  position: sticky; left: 0; z-index: 2;
  width: 320px; min-width: 260px; max-width: 380px;
  padding: 10px 12px; background: var(--bg-card);
  border-right: 1px solid var(--border);
}
.sg-tabla thead .sg-titulo { z-index: 4; background: var(--bg-elev); }

/* --- Cabecera de años --- */
.sg-tabla thead th {
  position: sticky; top: 0; z-index: 3;
  background: var(--bg-elev); padding: 9px 10px;
  font-size: .74rem; font-weight: 650; color: var(--text-soft);
  text-transform: uppercase; letter-spacing: .04em;
  border-bottom: 1px solid var(--border);
}
.sg-tabla .sg-anio { width: 170px; min-width: 150px; text-align: center; }
.sg-natural, .sg-hoy { display: block; font-weight: 500; letter-spacing: 0; text-transform: none; }
.sg-natural { font-size: .72rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.sg-hoy { font-size: .66rem; color: var(--accent); }
/* La anualidad en curso es sobre la que se está marcando: se tiñe la columna
   entera para no tener que contar cabeceras cada vez. */
.sg-tabla thead th.actual { color: var(--accent); }
.sg-tabla td.actual, .sg-tabla th.actual { background: var(--accent-soft); }

/* --- Fila de bloque --- */
.sg-bloque > * { background: var(--bg-card-hover); border-top: 1px solid var(--border); }
.sg-bloque .sg-titulo { background: var(--bg-card-hover); }
.sg-b-nombre {
  font-weight: 700; font-size: .8rem; letter-spacing: .03em;
  text-transform: uppercase; color: var(--text);
}
.sg-b-cuenta { padding: 10px; text-align: center; }

/* --- Ítems --- */
.sg-item .sg-titulo { padding: 11px 12px 11px 22px; }
.sg-i-nombre { font-weight: 600; line-height: 1.35; }
.sg-i-nombre.ok::before {
  content: ""; display: inline-block; width: 6px; height: 6px; border-radius: 50%;
  background: var(--ok); margin-right: 7px; vertical-align: middle;
}
.sg-item.vacio td { padding: 9px 12px 9px 22px; }

/* Los botones de la fila solo aparecen al pasar por encima: con cinco iconos
   fijos por línea, la tabla parecía una barra de herramientas y no un cuadro
   de seguimiento. En táctil no hay hover, así que ahí se quedan siempre. */
.sg-acc { display: flex; gap: 2px; flex: 0 0 auto; opacity: 0; transition: opacity .12s; }
.sg-acc .gp-btn { padding: 3px 6px; font-size: .72rem; line-height: 1.2; }
.sg-tabla tr:hover .sg-acc, .sg-acc:focus-within { opacity: 1; }
@media (hover: none) { .sg-acc { opacity: 1; } }

/* --- Celda de una anualidad --- */
.sg-celda { padding: 9px 8px; text-align: center; }
.sg-celda.ok { background: var(--ok-soft); }
.sg-celda.ok.actual { background: color-mix(in srgb, var(--ok-soft) 70%, var(--accent-soft)); }
.sg-chk { display: block; }
.sg-chk input {
  width: 19px; height: 19px; accent-color: var(--ok); cursor: pointer; margin: 0;
}
.sg-chk input:disabled { cursor: not-allowed; opacity: .5; }
.sg-fecha {
  margin-top: 4px; font-size: .7rem; color: var(--ok);
  font-weight: 600; font-variant-numeric: tabular-nums;
}
/* La nota va debajo del check y se recorta a tres líneas: el texto completo
   está en el `title` y se abre entero al pulsarla. Sin el recorte, una nota
   larga estiraba la fila y descolocaba toda la columna. */
.sg-nota {
  width: 100%; margin-top: 5px; padding: 4px 6px;
  border: 1px dashed var(--border); border-radius: var(--r-sm);
  background: none; color: var(--text-soft); cursor: pointer;
  font: inherit; font-size: .72rem; line-height: 1.3; text-align: left;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.sg-nota:hover { border-color: var(--accent); color: var(--text); border-style: solid; }
.sg-nota.vacia { color: var(--text-muted); text-align: center; }
.sg-nota.estatica { border-style: none; cursor: default; padding: 4px 0; }

@media (max-width: 700px) {
  .sg-tabla .sg-titulo { width: 200px; min-width: 180px; }
  .sg-tabla .sg-anio { width: 140px; min-width: 130px; }
}

/* ==========================================================================
   CICLO DE VIDA CON DOCUMENTOS POR FASE
   Cada hito de la línea del tiempo es la carpeta de su fase: se pulsa y a la
   derecha aparece lo que hay dentro y el botón para adjuntar.
   ========================================================================== */
.gp-timeline.con-docs .gp-tl-item[data-fase] {
  cursor: pointer; border-radius: var(--r-sm);
  padding: 6px 10px 12px; margin-left: -10px;
  transition: background .14s;
}
/* El punto de la línea se recoloca: la tarjeta se ha desplazado 10 px a la
   izquierda para ganar el área pulsable, y el punto tiene que seguir cayendo
   sobre el hilo vertical. */
.gp-timeline.con-docs .gp-tl-item[data-fase]::before { left: -12px; }
.gp-timeline.con-docs .gp-tl-item[data-fase]:hover { background: var(--bg-card-hover); }
.gp-timeline.con-docs .gp-tl-item.sel {
  background: var(--accent-soft);
  box-shadow: inset 2px 0 0 var(--accent);
}
.gp-timeline.con-docs .gp-tl-item[data-fase]:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 1px;
}
/* Las fases que aún no han llegado se atenúan, pero se pueden abrir: se puede
   ir dejando preparado lo que ya se tiene. */
.gp-timeline.con-docs .gp-tl-item.pending .tl-title,
.gp-timeline.con-docs .gp-tl-item.pending .tl-desc { opacity: .62; }

.tl-docs {
  display: inline-flex; align-items: center; gap: 5px;
  margin-top: 6px; padding: 2px 8px; border-radius: var(--r-pill);
  background: var(--bg-card); border: 1px solid var(--border);
  font-size: .7rem; color: var(--text-soft);
}
.tl-docs.vacio { color: var(--text-muted); border-style: dashed; }
.tl-docs svg { opacity: .8; }

/* Panel de la fase */
#panel-fase .sec-head h3 { display: flex; align-items: center; gap: 7px; }
.fase-docs { display: flex; flex-direction: column; gap: 7px; }
.fase-doc {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: var(--r-sm);
  background: var(--bg-card); border: 1px solid var(--border);
}
.fase-doc .d-ico {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: var(--r-sm);
  display: grid; place-items: center;
  font-size: .58rem; font-weight: 800; letter-spacing: .04em;
  background: var(--danger-soft); color: var(--danger);
}
.fase-doc .d-ico.doc { background: var(--info-soft); color: var(--info); }

/* Botón de solo icono en el pie de un modal. Va pegado a la izquierda, lejos
   de Guardar: es una acción que casi nunca se usa y que no se deshace. */
.gp-modal-foot .gp-btn.solo-icono {
  margin-right: auto; padding: 7px 10px; color: var(--text-muted);
}
.gp-modal-foot .gp-btn.solo-icono:hover {
  color: var(--danger); background: var(--danger-soft);
}

/* Fila de documento de una fase: el bloque de la izquierda abre el archivo */
.fase-doc .fd-abrir {
  display: flex; align-items: center; gap: 10px; flex: 1 1 auto; min-width: 0;
  background: none; border: 0; padding: 0; margin: 0;
  color: inherit; text-align: left; font: inherit; cursor: pointer;
}
.fase-doc .fd-abrir > span { display: block; }
.fase-doc .fd-abrir .gp-small { display: block; }
.fase-doc .fd-abrir .gp-xs { display: block; margin-top: 1px; }
.fase-doc:hover { border-color: var(--border-strong); }
.fase-doc .fd-abrir:hover .gp-small { color: var(--accent); }
.fase-doc .fd-abrir:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r-sm); }

/* Prórroga en la línea del tiempo: informativa, no se pulsa. El punto va en
   morado, el mismo del estado «Prorrogado», para que se lea de un vistazo que
   ahí el contrato se estiró. */
.gp-timeline .gp-tl-item.prorroga::before {
  background: var(--purple); border-color: var(--purple);
}
.gp-timeline .gp-tl-item.prorroga .tl-title {
  display: inline-flex; align-items: center; gap: 6px; color: var(--purple);
}

/* Selector de tipo de prórroga: dos opciones con su explicación, porque la
   diferencia entre una y otra no cabe en una palabra. */
.tipo-pr {
  display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
  padding: 11px 13px; border-radius: var(--r-sm);
  background: var(--bg-input); border: 1px solid var(--border);
  transition: all .14s;
}
.tipo-pr:hover { background: var(--bg-card-hover); }
.tipo-pr.active { background: var(--accent-soft); border-color: var(--accent); }
.tipo-pr input { margin-top: 3px; accent-color: var(--accent); flex: 0 0 auto; }
.tipo-pr > span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tipo-pr b { font-size: .85rem; }

/* Lista de instalaciones del expediente. A ancho completo del modal caben en
   varias columnas: en una sola, sesenta y dos instalaciones son un scroll
   interminable para marcar tres. */
.inst-lista {
  max-height: 210px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: var(--r); padding: 10px 12px;
  display: grid; gap: 2px 18px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  align-content: start;
}
.inst-lista .gp-check { padding: 4px 0; align-items: center; }
.inst-lista .gp-check span { min-width: 0; }
.inst-lista .gp-check .gp-xs { display: block; }

/* ==========================================================================
   AVISOS: SEMÁFORO DE VIGENCIA
   Un aviso caducado que sigue marcado como publicado no está haciendo nada.
   Tiene que verse sin abrir la ficha, porque es justo lo que se le escapa al
   gestor: la gente leyendo un mes que la piscina cierra tres días.
   ========================================================================== */
.aviso-card { border-left: 3px solid var(--border-strong); }
.aviso-card.activo     { border-left-color: var(--ok); }
.aviso-card.caducado   { border-left-color: var(--danger); }
.aviso-card.programado { border-left-color: var(--warn); }
.aviso-card.caducado .gp-bold,
.aviso-card.caducado .gp-soft { opacity: .6; }

.av-estado {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .72rem; font-weight: 650; color: var(--text-muted);
}
.av-estado i {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--border-strong); flex: 0 0 auto;
}
.av-estado.ok     { color: var(--ok); }
.av-estado.ok i   { background: var(--ok); box-shadow: 0 0 0 3px var(--ok-soft); }
.av-estado.danger { color: var(--danger); }
.av-estado.danger i { background: var(--danger); box-shadow: 0 0 0 3px var(--danger-soft); }
.av-estado.warn   { color: var(--warn); }
.av-estado.warn i { background: var(--warn); box-shadow: 0 0 0 3px var(--warn-soft); }

/* ==========================================================================
   CARTEL DEL QR
   Fondo blanco siempre, también en tema oscuro: un QR en negativo lo leen
   algunos móviles y otros no, y el que no lo lee es el del vecino que se
   planta delante del tablón.
   ========================================================================== */
.qr-cartel {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 18px; border-radius: var(--r);
  background: #fff; border: 1px solid var(--border);
}
.qr-caja { line-height: 0; }
.qr-caja svg { display: block; width: 240px; height: 240px; }
.qr-url {
  font-size: .72rem; color: #333; text-align: center;
  word-break: break-all; max-width: 260px;
}
.qr-cartel .gp-xs { color: #666; }
