/* ============================================================
   SCHOOLARYX — Components CSS
   Todos los componentes UI del tema
   ============================================================ */

/* ======================================================
   CARDS
   ====================================================== */
.card {
  background: var(--sx-card-bg);
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius-lg);
  box-shadow: none;
  transition: var(--transition);
  overflow: hidden;
}

.card:hover { box-shadow: none; }

/* Deja que los menús dropdown de acciones (rich-table por fila) escapen del
   recorte de .card (overflow:hidden). El card-header es transparente, así que
   no afecta a las esquinas redondeadas. */
.card.sx-card-overflow { overflow: visible; }

.card-header {
  background: transparent;
  border-bottom: 1px solid var(--sx-border-color);
  padding: 1rem 1.25rem;
  font-family: var(--font-display);
  font-size: 1rem;
  color: var(--sx-text-heading);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* El padding se expone como variable para que quien necesite salirse de él
   (.sx-table-flush, en pages.css) lo cancele con el valor exacto en vez de
   repetir un 1.25rem que podría divergir de este. */
.card-body { --sx-card-pad: 1.25rem; padding: var(--sx-card-pad); }
.card-footer {
  background: transparent;
  border-top: 1px solid var(--sx-border-color);
  padding: 0.875rem 1.25rem;
  font-size: 0.8rem;
  color: var(--sx-text-muted);
}

/* Card color headers */
.card-header--primary { background: var(--sx-primary); color: #fff; }
.card-header--success { background: var(--sx-success); color: #fff; }
.card-header--danger  { background: var(--sx-danger);  color: #fff; }
.card-header--warning { background: var(--sx-warning); color: var(--sx-dark); }
.card-header--info    { background: var(--sx-info);    color: var(--sx-dark); }
.card-header--dark    { background: var(--sx-dark);    color: #fff; }
.card-header--purple  { background: var(--sx-purple);  color: #fff; }

/* Stat card */
.sx-stat-card {
  position: relative;
  overflow: hidden;
}
a.sx-stat-card { transition: border-color .2s ease; }
a.sx-stat-card:hover { border-color: var(--sx-primary); }
a.sx-stat-card:focus-visible { outline: 2px solid var(--sx-primary); outline-offset: 2px; }
.sx-stat-card__icon {
  width: 52px;
  height: 52px;
  border-radius: var(--radius);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  flex-shrink: 0;
}
.sx-stat-card__value {
  font-family: var(--font-display);
  font-size: 2rem;
  line-height: 1;
  color: var(--sx-text-heading);
}
.sx-stat-card__label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--sx-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.sx-stat-card__trend {
  font-size: 0.78rem;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  padding: 0.15rem 0.5rem;
  border-radius: var(--radius-pill);
}
.sx-stat-card__trend--up   { background: var(--sx-success-light); color: var(--sx-success-dark); }
.sx-stat-card__trend--down { background: var(--sx-danger-light);  color: var(--sx-danger-dark); }

/* Card colapsable */
.card-collapsible .card-header { cursor: pointer; user-select: none; }
.card-collapsible .card-header .collapse-icon { margin-left: auto; transition: transform 0.25s; }
.card-collapsible .card-header[aria-expanded="false"] .collapse-icon { transform: rotate(-90deg); }

/* Card overlay con gradiente */
.card-overlay { position: relative; overflow: hidden; }
.card-overlay .card-img-overlay {
  background: linear-gradient(to top, rgba(48,47,59,0.85) 0%, transparent 60%);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

/* ======================================================
   BUTTONS
   ====================================================== */
.btn:focus,
.btn:focus-visible,
.btn-check:focus + .btn,
.btn.focus {
  outline: none !important;
  box-shadow: none !important;
}

.btn {
  font-family: var(--font-body);
  font-weight: 700;
  border-radius: var(--radius);
  padding: 0.5rem 1.25rem;
  font-size: 0.875rem;
  transition: var(--transition-fast);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  border: 2px solid transparent;
  cursor: pointer;
  white-space: nowrap;
}

/* Tamaños */
.btn-sm {
  padding: 0.3rem 0.8rem;
  font-size: 0.78rem;
  border-radius: var(--radius-sm);
  border-width: 1.5px;
}
.btn-lg {
  padding: 0.7rem 1.75rem;
  font-size: 1rem;
  border-radius: var(--radius-lg);
}
.btn-xl {
  padding: 0.9rem 2.2rem;
  font-size: 1.1rem;
  border-radius: var(--radius-lg);
}
/* Botón redondo solo-ícono */
.btn-icon {
  width: 38px;
  height: 38px;
  padding: 0;
  border-radius: var(--radius);
  font-size: 1rem;
}
.btn-icon.btn-sm { width: 30px; height: 30px; font-size: 0.85rem; border-radius: var(--radius-sm); }
.btn-icon.btn-lg { width: 48px; height: 48px; font-size: 1.2rem; border-radius: var(--radius-lg); }
.btn-icon-circle { border-radius: 50% !important; }

/* Chevron de "abrir detalle": un control SIN caja, para filas colapsables.
   Sigue siendo <button> (teclado, foco, aria-expanded); solo se le quita el
   marco, que junto a un botón de verdad hacía ruido y parecía otra acción.

   No usa .btn-link: el de Bootstrap pinta --bs-link-color (#0d6efd), el azul
   genérico que el tema NO remapea. */
.sx-det-toggle {
  border: 0;
  background: none;
  padding: 0 .35rem;
  line-height: 1;
  color: var(--sx-text-muted);
  transition: var(--transition);
}
.sx-det-toggle:hover,
.sx-det-toggle[aria-expanded="true"] { color: var(--sx-primary); }
.sx-det-toggle:focus-visible {
  outline: 2px solid var(--sx-primary);
  outline-offset: 2px;
  border-radius: var(--radius-xs);
}

/* Colores sólidos */
.btn-primary    { background: var(--sx-primary);  border-color: var(--sx-primary);  color: #fff; }
.btn-primary:hover  { background: var(--sx-primary-dark); border-color: var(--sx-primary-dark); color: #fff; }
.btn-primary:active,
.btn-primary:focus,
.btn-primary.active,
.btn-primary:not(:disabled):not(.disabled):active,
.show > .btn-primary.dropdown-toggle {
  background: var(--sx-primary-dark) !important;
  border-color: var(--sx-primary-dark) !important;
  color: #fff !important;
  box-shadow: none !important;
}
.btn-primary:disabled,
.btn-primary.disabled {
  background: var(--sx-primary) !important;
  border-color: var(--sx-primary) !important;
  color: #fff !important;
  opacity: .55 !important;
  box-shadow: none !important;
}

.btn-success    { background: var(--sx-success); border-color: var(--sx-success); color: #fff; }
.btn-success:hover  { background: var(--sx-success-dark); border-color: var(--sx-success-dark); color: #fff; }

.btn-danger     { background: var(--sx-danger);  border-color: var(--sx-danger);  color: #fff; }
.btn-danger:hover   { background: var(--sx-danger-dark); border-color: var(--sx-danger-dark); color: #fff; }

.btn-warning    { background: var(--sx-warning); border-color: var(--sx-warning); color: var(--sx-dark); }
.btn-warning:hover  { background: var(--sx-warning-dark); border-color: var(--sx-warning-dark); color: var(--sx-dark); }

.btn-info       { background: var(--sx-info);    border-color: var(--sx-info);    color: var(--sx-dark); }
.btn-info:hover     { background: var(--sx-info-dark); border-color: var(--sx-info-dark); color: var(--sx-dark); }

.btn-purple     { background: var(--sx-purple);  border-color: var(--sx-purple);  color: #fff; }
.btn-purple:hover   { background: var(--sx-purple-dark); border-color: var(--sx-purple-dark); color: #fff; }

.btn-dark       { background: var(--sx-dark);    border-color: var(--sx-dark);    color: #fff; }
.btn-dark:hover     { background: var(--sx-dark-2); border-color: var(--sx-dark-2); color: #fff; }

.btn-secondary  { background: #e8eaf0; border-color: #e8eaf0; color: var(--sx-text-body); }
.btn-secondary:hover { background: #dde0ea; border-color: #dde0ea; color: var(--sx-text-heading); }

/* Outline buttons */
.btn-outline-primary  { border-color: var(--sx-primary);  color: var(--sx-primary);  background: transparent; }
.btn-outline-primary:hover,
.btn-outline-primary:active,
.btn-outline-primary:focus,
.btn-outline-primary.active,
.btn-outline-primary:not(:disabled):not(.disabled):active,
.show > .btn-outline-primary.dropdown-toggle {
  background: var(--sx-primary) !important;
  border-color: var(--sx-primary) !important;
  color: #fff !important;
  box-shadow: none !important;
}

/* btn-check seleccionado (segmentos): Bootstrap usa --bs-* genérico → forzar marca */
.btn-check:checked + .btn-outline-primary,
.btn-check:active   + .btn-outline-primary {
  background: var(--sx-primary) !important;
  border-color: var(--sx-primary) !important;
  color: #fff !important;
  box-shadow: none !important;
}

.btn-outline-secondary { border-color: #c4c4c4; color: var(--sx-text-body); background: transparent; }
.btn-outline-secondary:hover,
.btn-outline-secondary:active,
.btn-outline-secondary:focus,
.btn-outline-secondary.active,
.btn-outline-secondary:not(:disabled):not(.disabled):active,
.show > .btn-outline-secondary.dropdown-toggle {
  background: var(--sx-dark-2) !important;
  border-color: var(--sx-dark-2) !important;
  color: #fff !important;
  box-shadow: none !important;
}

.btn-outline-success  { border-color: var(--sx-success);  color: var(--sx-success);  background: transparent; }
.btn-outline-success:hover  { background: var(--sx-success);  color: #fff; }

.btn-outline-danger   { border-color: var(--sx-danger);   color: var(--sx-danger);   background: transparent; }
.btn-outline-danger:hover   { background: var(--sx-danger);   color: #fff; }

.btn-outline-warning  { border-color: var(--sx-warning);  color: var(--sx-warning-dark); background: transparent; }
.btn-outline-warning:hover  { background: var(--sx-warning);  color: var(--sx-dark); }

.btn-outline-info     { border-color: var(--sx-info);     color: var(--sx-info-dark);    background: transparent; }
.btn-outline-info:hover     { background: var(--sx-info);     color: var(--sx-dark); }

.btn-outline-purple   { border-color: var(--sx-purple);   color: var(--sx-purple);   background: transparent; }
.btn-outline-purple:hover   { background: var(--sx-purple);   color: #fff; }

.btn-outline-dark     { border-color: var(--sx-dark);     color: var(--sx-dark);     background: transparent; }
.btn-outline-dark:hover     { background: var(--sx-dark);     color: #fff; }

/* Soft buttons */
.btn-soft-primary { background: var(--sx-primary-light); color: var(--sx-primary); border-color: transparent; }
.btn-soft-primary:hover { background: var(--sx-primary); color: #fff; }

.btn-soft-success { background: var(--sx-success-light); color: var(--sx-success-dark); border-color: transparent; }
.btn-soft-success:hover { background: var(--sx-success); color: #fff; }

.btn-soft-danger  { background: var(--sx-danger-light);  color: var(--sx-danger);  border-color: transparent; }
.btn-soft-danger:hover  { background: var(--sx-danger);  color: #fff; }

.btn-soft-warning { background: var(--sx-warning-light); color: var(--sx-warning-dark); border-color: transparent; }
.btn-soft-warning:hover { background: var(--sx-warning); color: var(--sx-dark); }

.btn-soft-info    { background: var(--sx-info-light);    color: var(--sx-info-dark);    border-color: transparent; }
.btn-soft-info:hover    { background: var(--sx-info);    color: var(--sx-dark); }

/* No shadow on focus/active */
.btn:focus, .btn:active, .btn:focus-visible { box-shadow: none !important; outline: none !important; }

/* Loading state */
.btn.loading { pointer-events: none; opacity: 0.75; }

/* ======================================================
   BADGES
   ====================================================== */
.badge {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.68rem;
  padding: 0.3em 0.65em;
  border-radius: var(--radius-pill);
  letter-spacing: 0.02em;
}

.badge-primary { background: var(--sx-primary);  color: #fff; }
.badge-success { background: var(--sx-success);  color: #fff; }
.badge-danger  { background: var(--sx-danger);   color: #fff; }
.badge-warning { background: var(--sx-warning);  color: var(--sx-dark); }
.badge-info    { background: var(--sx-info);     color: var(--sx-dark); }
.badge-purple  { background: var(--sx-purple);   color: #fff; }
.badge-dark    { background: var(--sx-dark);     color: #fff; }
.badge-secondary { background: #e8eaf0; color: var(--sx-text-body); }

/* Chips de estándares por sección: un poco más grandes y legibles. */
#dtClassStandards .badge { font-size: 0.8rem; padding: 0.35em 0.7em; }

/* Soft badges */
.badge-soft-primary { background: var(--sx-primary-light); color: var(--sx-primary); }
.badge-soft-success { background: var(--sx-success-light); color: var(--sx-success-dark); }
.badge-soft-danger  { background: var(--sx-danger-light);  color: var(--sx-danger-dark); }
.badge-soft-warning { background: var(--sx-warning-light); color: var(--sx-warning-dark); }
.badge-soft-info    { background: var(--sx-info-light);    color: var(--sx-info-dark); }
.badge-soft-purple  { background: var(--sx-purple-light);  color: var(--sx-purple-dark); }
/* El fondo va por token: en hex fijo (#eceef3) quedaba claro también en tema
   oscuro, y como el texto sí seguía a --sx-text-body salía claro sobre claro. */
.badge-soft-secondary { background: var(--sx-border-color); color: var(--sx-text-body, #5b6275); }

/* Solid badges (paleta schoolaryx). Texto oscuro en los claros (info/warning). */
.sx-badge-primary   { background: var(--sx-primary);  color: #fff; }
.sx-badge-success   { background: var(--sx-success);  color: #fff; }
.sx-badge-danger    { background: var(--sx-danger);   color: #fff; }
.sx-badge-info      { background: var(--sx-info);     color: var(--sx-dark); }
.sx-badge-warning   { background: var(--sx-warning);  color: var(--sx-dark); }
.sx-badge-purple    { background: var(--sx-purple);   color: #fff; }
.sx-badge-secondary { background: var(--sx-text-muted); color: #fff; }

/* ======================================================
   ALERTS
   ====================================================== */
.alert {
  border: none;
  border-left: 4px solid transparent;
  border-radius: var(--radius);
  padding: 1rem 1.25rem;
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
}
/* Variante "contenido adicional" (título + texto + hr + texto): bloque vertical
   en vez de flex, con borde fino. Para alerts tipo Bootstrap additional content. */
.alert.alert-block {
  display: block;
  border-left-width: 1px;
}
.alert.alert-block > :last-child { margin-bottom: 0; }
.alert-icon { font-size: 1.25rem; flex-shrink: 0; margin-top: 0.05rem; }
.alert-title { font-weight: 800; font-size: 0.9rem; margin-bottom: 0.25rem; }
.alert-text { font-size: 0.875rem; padding-top: 6px; }
.alert-dismiss {
  margin-left: auto;
  background: none;
  border: none;
  opacity: 0.6;
  cursor: pointer;
  padding: 0;
  font-size: 1rem;
  line-height: 1;
  transition: var(--transition-fast);
}
.alert-dismiss:hover { opacity: 1; }

.alert-primary { background: var(--sx-primary-light); color: var(--sx-primary-dark); border-left-color: var(--sx-primary); }
.alert-success { background: var(--sx-success-light); color: var(--sx-success-dark); border-left-color: var(--sx-success); }
.alert-danger  { background: var(--sx-danger-light);  color: var(--sx-danger-dark);  border-left-color: var(--sx-danger); }
.alert-warning { background: var(--sx-warning-light); color: var(--sx-warning-dark); border-left-color: var(--sx-warning); }
.alert-info    { background: var(--sx-info-light);    color: var(--sx-info-dark);    border-left-color: var(--sx-info); }
.alert-purple  { background: var(--sx-purple-light);  color: var(--sx-purple-dark);  border-left-color: var(--sx-purple); }

/* ======================================================
   FORMS
   ====================================================== */
.form-label {
  font-weight: 700;
  font-size: 0.8rem;
  color: var(--sx-text-heading);
  margin-bottom: 0.35rem;
  display: block;
}
.form-label .required { color: var(--sx-danger); margin-left: 3px; }

.form-control, .form-select {
  background: var(--sx-card-bg);
  border: 1.5px solid var(--sx-border-color);
  border-radius: var(--radius);
  padding: 0.5rem 0.85rem;
  line-height: 1.5;
  height: calc(1.5em + 1rem + 3px);
  font-family: var(--font-body);
  font-size: 0.875rem;
  color: var(--sx-text-body);
  transition: var(--transition-fast);
  box-shadow: none !important;
  width: 100%;
  -webkit-appearance: none;
  appearance: none;
}
.form-control[type="password"] { letter-spacing: 1px; }
.form-control[type="password"]::placeholder { line-height: normal; }
textarea.form-control { height: auto; }
select.form-select { height: calc(1.5em + 1rem + 3px); }

.form-control:focus, .form-select:focus {
  border-color: #bdbdbd !important;
  box-shadow: none !important;
  outline: none !important;
  background: var(--sx-card-bg);
  color: var(--sx-text-body);
}

.form-control::placeholder { color: var(--sx-text-muted); }

.form-control:disabled, .form-control[readonly],
.form-select:disabled {
  background: var(--sx-body-bg);
  color: var(--sx-text-muted);
  cursor: not-allowed;
  opacity: 0.7;
}

.form-control.is-valid   { border-color: var(--sx-success); }
.form-control.is-invalid,
.form-select.is-invalid,
textarea.is-invalid { border-color: var(--sx-danger); }
.form-control.is-valid:focus   { box-shadow: none !important; border-color: var(--sx-success) !important; }
.form-control.is-invalid:focus,
.form-select.is-invalid:focus,
textarea.is-invalid:focus { box-shadow: none !important; border-color: var(--sx-danger) !important; }

/* Quitar el ícono SVG por defecto de Bootstrap en estado inválido: el tema usa
   solo borde rojo + mensaje (como la página de referencia). Ese ícono además
   choca con los campos que ya tienen ícono propio (.form-control-icon). */
.form-control.is-invalid,
.form-select.is-invalid,
textarea.is-invalid {
  background-image: none !important;
  padding-right: 0.875rem !important;
}
.form-control-icon.is-invalid,
textarea.form-control-icon.is-invalid { padding-left: 2.5rem !important; }

/* Checkbox / radio inválidos: borde danger en el control y label en danger.
   (Switches y checks requeridos: aceptar términos, elegir una opción, etc.) */
.form-check-input.is-invalid {
  border-color: var(--sx-danger) !important;
}
.form-check-input.is-invalid:focus {
  border-color: var(--sx-danger) !important;
  box-shadow: none !important;
}
.form-check-input.is-invalid ~ .form-check-label { color: var(--sx-danger-dark); }

/* Etiqueta de un campo requerido inválido: color de peligro (lo aplica el
   validador, global y por-paso, vía la clase sx-invalid-label en el <label>). */
.form-label.sx-invalid-label,
label.sx-invalid-label { color: var(--sx-danger-dark) !important; }

/* Select2: el <select> original queda oculto, asi que pintamos su contenedor.
   Select2 inserta .select2-container como hermano inmediato del <select>.
   El !important + los estados focus/open ganan al borde primario del tema. */
select.is-invalid + .select2-container .select2-selection,
select.is-invalid + .select2-container--focus .select2-selection,
select.is-invalid + .select2-container--open .select2-selection {
  border-color: var(--sx-danger) !important;
}

/* Centra verticalmente la "x" de limpiar (allowClear) en select2 múltiples.
   El contenedor necesita position:relative para anclar la "x" absoluta. */
.select2-container--default .select2-selection--multiple { position: relative; }
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
  padding-right: 1.6rem; /* deja espacio para la "x" y evita solape con los chips */
}
.select2-container--default .select2-selection--multiple .select2-selection__clear {
  position: absolute;
  top: 50%;
  right: 0.6rem;
  transform: translateY(-50%);
  margin: 0;
  padding: 0;
  line-height: 1;
  height: auto;
}

.valid-feedback   { font-size: 0.78rem; color: var(--sx-success-dark); }
.invalid-feedback { font-size: 0.78rem; color: var(--sx-danger-dark); }

.form-text { font-size: 0.78rem; color: var(--sx-text-muted); margin-top: 0.3rem; }

/* Textarea */
textarea.form-control { resize: vertical; min-height: 100px; }

/* Input Group */
.input-group .input-group-text {
  /* background: var(--sx-body-bg); */
  border: 1.5px solid var(--sx-border-color);
  border-radius: var(--radius);
  color: var(--sx-text-muted);
  font-size: 0.875rem;
  padding: 0.5rem 0.875rem;
}
.input-group .btn { border-width: 1.5px !important; }
.input-group .form-control:not(:first-child) { border-left: none; border-radius: 0 var(--radius) var(--radius) 0; }
.input-group .form-control:not(:last-child)  { border-right: none; border-radius: var(--radius) 0 0 var(--radius); }
.input-group .input-group-text:first-child   { border-right: none; border-radius: var(--radius) 0 0 var(--radius); }
.input-group .input-group-text:last-child    { border-left: none; border-radius: 0 var(--radius) var(--radius) 0; }
.input-group:focus-within .input-group-text,
.input-group:focus-within .btn-outline-secondary {
  border-color: #bdbdbd !important;
}

/* Checkbox & Radio */
.form-check-input {
  width: 1.15em;
  height: 1.15em;
  border: 2px solid var(--sx-border-color);
  border-radius: var(--radius-xs);
  cursor: pointer;
  transition: var(--transition-fast);
}
.form-check-input:checked {
  background-color: var(--sx-primary);
  border-color: var(--sx-primary);
}
.form-check-input[type="radio"] { border-radius: 50%; }
.form-check-input:focus {
  box-shadow: none !important;
  border-color: #bdbdbd;
  outline: none;
}
.form-check-label {
  cursor: pointer;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--sx-text-body);
}

/* Switch — estado on/off claro: ✕ en gris (off) y ✓ en verde (on) dentro del
   knob; el track cambia de color. Sigue visible aunque esté deshabilitado. */
.form-switch .form-check-input {
  width: 2.6em;
  height: 1.3em;
  border-radius: var(--radius-pill);
  background-color: var(--sx-text-muted);
  border-color: var(--sx-text-muted);
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3cpath d='M-1.2 -1.2 L1.2 1.2 M1.2 -1.2 L-1.2 1.2' stroke='%23939393' stroke-width='0.9' stroke-linecap='round'/%3e%3c/svg%3e");
}
.form-switch .form-check-input:checked {
  background-color: var(--sx-success);
  border-color: var(--sx-success);
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3cpath d='M-1.5 0 L-0.3 1.2 L1.6 -1.3' fill='none' stroke='%236fc191' stroke-width='1' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
}
/* Estado indeterminado (p. ej. el checkbox "Todos" con selección parcial): usa
   el color de marca, NO el azul por defecto de Bootstrap. Así: gris=off,
   naranja=parcial, verde=todo. Solo checkbox: un radio sin ninguna opción
   marcada también matchea :indeterminate por spec del navegador (grupo sin
   selección), y ahí NO debe verse como "marcado" — se dejaría el naranja en
   radios que en realidad están vacíos. */
.form-check-input[type="checkbox"]:indeterminate {
  background-color: var(--sx-primary);
  border-color: var(--sx-primary);
}
.form-switch .form-check-input:indeterminate {
  background-color: var(--sx-primary);
  border-color: var(--sx-primary);
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23fff'/%3e%3cpath d='M-1.4 0 L1.4 0' stroke='%23939393' stroke-width='0.9' stroke-linecap='round'/%3e%3c/svg%3e");
}
.form-switch .form-check-input:disabled {
  opacity: 0.7;        /* deshabilitado pero el estado/ícono sigue visible */
  cursor: not-allowed;
}
.form-switch .form-check-label { margin-left: 0.5rem; }

/* Range */
.form-range::-webkit-slider-thumb {
  background: var(--sx-primary);
}
.form-range::-webkit-slider-runnable-track {
  background: var(--sx-border-color);
  border-radius: var(--radius-pill);
  height: 6px;
}
.form-range:focus { outline: none; }

/* Floating labels */
.form-floating > .form-control,
.form-floating > .form-select {
  height: calc(3.2rem + 2px);
  padding: 1rem 0.875rem 0.25rem;
}
.form-floating > label {
  color: var(--sx-text-muted);
  font-size: 0.875rem;
}

/* Select nativo */
.form-select {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%239395a5' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 12px 12px;
  padding-right: 2.25rem;
  cursor: pointer;
}

/* ======================================================
   MODALS
   ====================================================== */
.modal-content {
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius-xl);
  box-shadow: none;
  background: var(--sx-card-bg);
}
.modal-header {
  border-bottom: 1px solid var(--sx-border-color);
  padding: 1.25rem 1.5rem;
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
}
.modal-title {
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--sx-text-heading);
}
.modal-body { padding: 1.5rem; }
.modal-footer {
  border-top: 1px solid var(--sx-border-color);
  padding: 1rem 1.5rem;
  border-radius: 0 0 var(--radius-xl) var(--radius-xl);
}
.btn-close {
  background-size: 0.75em;
  opacity: 0.5;
  border-radius: var(--radius-sm);
}
.btn-close:hover { opacity: 1; background-color: var(--sx-body-bg); }

/* Modal animación slide */
.modal.modal-slide .modal-dialog {
  transform: translateY(-30px);
  transition: transform 0.3s ease;
}
.modal.modal-slide.show .modal-dialog { transform: translateY(0); }

/* ======================================================
   TABS
   ====================================================== */
.nav-tabs {
  border-bottom: 4px solid var(--sx-border-color);
  gap: 0.15rem;
}
.nav-tabs li,
.nav-tabs .nav-item { margin-bottom: 0rem; }
.nav-tabs .nav-link {
  border: none;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  color: var(--sx-text-muted);
  font-weight: 700;
  font-size: 0.875rem;
  padding: 0.6rem 1.1rem;
  position: relative;
  transition: var(--transition-fast);
}
.nav-tabs .nav-link::after {
  content: '';
  position: absolute;
  bottom: -3px;
  left: 0; right: 0;
  height: 4px;
  background: var(--sx-primary);
  transform: scaleX(0);
  transition: transform 0.2s ease;
  z-index: 2;
}
.nav-tabs .nav-link:hover { color: var(--sx-primary); background: var(--sx-primary-light); }
.nav-tabs .nav-link.active {
  color: var(--sx-primary);
  background: var(--sx-primary-light);
  border-color: transparent;
}
.nav-tabs .nav-link.active::after { transform: scaleX(1); }

/* Nav pills */
.nav-pills .nav-link {
  border-radius: var(--radius-pill);
  color: var(--sx-text-body);
  font-weight: 700;
  font-size: 0.875rem;
  padding: 0.45rem 1rem;
  transition: var(--transition-fast);
}
.nav-pills .nav-link:hover { background: var(--sx-primary-light); color: var(--sx-primary); }
.nav-pills .nav-link.active { background: var(--sx-primary); color: #fff; }

/* Tabs con íconos */
.nav-link .bi { margin-right: 0.4rem; }

/* ======================================================
   ACCORDION
   ====================================================== */
.accordion-item {
  background: var(--sx-card-bg);
  border: 1px solid var(--sx-border-color) !important;
  border-radius: var(--radius) !important;
  margin-bottom: 0.5rem;
  overflow: hidden;
}
.accordion-button {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--sx-text-heading);
  background: var(--sx-card-bg);
  padding: 1rem 1.25rem;
  border: none;
  box-shadow: none !important;
}
.accordion-button:not(.collapsed) {
  color: var(--sx-primary);
  background: var(--sx-primary-light);
  box-shadow: none;
}
.accordion-button::after {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%239395a5'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
}
.accordion-button:not(.collapsed)::after {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ec774b'%3e%3cpath fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/%3e%3c/svg%3e");
}
.accordion-body {
  padding: 1rem 1.25rem;
  font-size: 0.875rem;
  color: var(--sx-text-body);
  border-top: 1px solid var(--sx-border-color);
}
.accordion-flush .accordion-item { border-radius: 0 !important; border-left: none; border-right: none; }
.accordion-flush .accordion-item:first-child { border-top: none; }

/* ======================================================
   PROGRESS
   ====================================================== */
.progress {
  background: var(--sx-border-color);
  border-radius: var(--radius-pill);
  height: 10px;
  overflow: hidden;
}
.progress-bar {
  border-radius: var(--radius-pill);
  transition: width 0.6s ease;
  font-size: 0.65rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.progress-thin { height: 4px; }
.progress-md   { height: 8px; }
.progress-lg   { height: 14px; }

.bg-primary { background: var(--sx-primary) !important; }
.text-primary { color: var(--sx-primary) !important; }
.border-primary { border-color: var(--sx-primary) !important; }
.link-primary { color: var(--sx-primary) !important; }
.link-primary:hover, .link-primary:focus { color: var(--sx-primary-dark) !important; }
.bg-success { background: var(--sx-success) !important; }
.bg-danger  { background: var(--sx-danger)  !important; }
.bg-warning { background: var(--sx-warning) !important; }
.bg-info    { background: var(--sx-info)    !important; }
.bg-purple  { background: var(--sx-purple)  !important; }
.bg-dark    { background: var(--sx-dark)    !important; }

/* ======================================================
   SPINNERS
   ====================================================== */
.spinner-border {
  border-width: 3px;
  width: 2rem;
  height: 2rem;
}
.spinner-border-sm { width: 1.1rem; height: 1.1rem; border-width: 2px; }
.spinner-grow-sm   { width: 1rem;   height: 1rem; }

.spinner-border.text-primary { color: var(--sx-primary) !important; }
.spinner-border.text-success { color: var(--sx-success) !important; }
.spinner-border.text-danger  { color: var(--sx-danger)  !important; }
.spinner-border.text-warning { color: var(--sx-warning) !important; }
.spinner-border.text-info    { color: var(--sx-info)    !important; }
.spinner-border.text-purple  { color: var(--sx-purple)  !important; }

/* ======================================================
   TOASTS
   ====================================================== */
.toast {
  background: var(--sx-card-bg);
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius-lg);
  box-shadow: none;
  min-width: 300px;
  font-size: 0.875rem;
}
.toast-header {
  background: transparent;
  border-bottom: 1px solid var(--sx-border-color);
  padding: 0.75rem 1rem;
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--sx-text-heading);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.toast-body { padding: 0.875rem 1rem; color: var(--sx-text-body); font-size: 0.95rem; }
/* z-index sobre el topbar (1030) para que el toast salga arriba del todo.
   transform: el contenedor vive en su PROPIA capa GPU; así, al aparecer/animar
   el toast, Chrome lo compone encima sin re-rasterizar (parpadear) el topbar que
   queda debajo. El contenedor no tiene descendientes position:fixed, así que el
   containing-block que crea el transform no afecta a nada. */
.toast-container { z-index: 1090; transform: translateZ(0); will-change: transform; }

/* Variantes de toast */
.toast-success .toast-header { color: var(--sx-success-dark); }
.toast-danger  .toast-header { color: var(--sx-danger-dark); }
.toast-warning .toast-header { color: var(--sx-warning-dark); }
.toast-info    .toast-header { color: var(--sx-info-dark); }

/* Barra de progreso del toast (cuenta regresiva del tiempo de vida). */
.toast { position: relative; overflow: hidden; }
.toast-progress {
  position: absolute;
  left: 0;
  bottom: 0;
  height: 3px;
  width: 100%;
  background: var(--sx-primary);
  border-bottom-left-radius: var(--radius-lg);
}
.toast-progress-success { background: var(--sx-success); }
.toast-progress-danger  { background: var(--sx-danger); }
.toast-progress-warning { background: var(--sx-warning); }
.toast-progress-info    { background: var(--sx-info); }

/* Modal de confirmación de borrado: arriba-centro en vez de centrado vertical. */
.modal-dialog.sx-modal-top {
  margin-top: 4.5rem;
  margin-bottom: auto;
}

/* Fix: cuando un <form> envuelve header+body+footer dentro de un modal
   scrollable, Bootstrap recorta el footer (el form es el unico hijo flex y
   desborda .modal-content). display:contents devuelve header/body/footer como
   hijos directos de .modal-content y restaura el scroll + footer fijo. */
.modal-dialog-scrollable > .modal-content > form { display: contents; }

/* Advertencia reforzada en confirmaciones de borrado (no hay vuelta atras). */
.sx-confirm-danger-warning {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  padding: 0.85rem 1rem;
  border-radius: var(--radius-sm);
  background: var(--sx-danger-light);
  border-left: 4px solid var(--sx-danger);
  color: var(--sx-danger-dark);
}
.sx-confirm-danger-warning i {
  font-size: 1.35rem;
  line-height: 1.2;
  color: var(--sx-danger);
  flex-shrink: 0;
}
.sx-confirm-danger-warning strong { font-weight: 700; }
.sx-confirm-danger-warning span { font-size: 0.85rem; opacity: 0.9; }

/* Selector de idioma del topbar: bandera arriba, etiqueta debajo. */
.sx-lang-menu .dropdown-item { padding: 0.6rem 0.75rem; font-weight: 600; }
.sx-lang-menu .dropdown-item img { box-shadow: var(--shadow-sm); }
.sx-lang-menu .dropdown-item span { font-size: 0.8rem; }

/* ======================================================
   TOOLTIPS & POPOVERS
   ====================================================== */
.tooltip .tooltip-inner {
  background: var(--sx-dark);
  border-radius: var(--radius-sm);
  font-size: 0.78rem;
  font-family: var(--font-body);
  font-weight: 600;
  padding: 0.35rem 0.7rem;
  max-width: 200px;
}
.tooltip .tooltip-arrow::before { border-top-color: var(--sx-dark); }

.popover {
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius-lg);
  box-shadow: none;
  font-family: var(--font-body);
  font-size: 0.875rem;
  background: var(--sx-card-bg);
}
.popover-header {
  background: var(--sx-body-bg);
  border-bottom: 1px solid var(--sx-border-color);
  font-weight: 800;
  font-size: 0.9rem;
  color: var(--sx-text-heading);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  padding: 0.75rem 1rem;
}
.popover-body { padding: 0.875rem 1rem; color: var(--sx-text-body); }

/* ======================================================
   PAGINATION
   ====================================================== */
.pagination {
  --bs-pagination-focus-box-shadow: none;
  --bs-pagination-color: var(--sx-text-body);
  --bs-pagination-bg: var(--sx-card-bg);
  --bs-pagination-border-color: var(--sx-border-color);
  --bs-pagination-hover-color: #fff;
  --bs-pagination-hover-bg: var(--sx-primary);
  --bs-pagination-hover-border-color: var(--sx-primary);
  --bs-pagination-active-color: #fff;
  --bs-pagination-active-bg: var(--sx-primary);
  --bs-pagination-active-border-color: var(--sx-primary);
  --bs-pagination-disabled-color: var(--sx-text-muted);
  --bs-pagination-disabled-bg: var(--sx-card-bg);
  --bs-pagination-disabled-border-color: var(--sx-border-color);
  gap: 0.2rem;
  align-items: center;
}
.page-link {
  border: 1.5px solid var(--sx-border-color);
  border-radius: var(--radius-sm) !important;
  font-weight: 700;
  font-size: 0.8rem;
  padding: 0.4rem 0.75rem;
  transition: var(--transition-fast);
}
.page-item.active .page-link { color: #fff !important; }
.page-item.disabled .page-link { opacity: 0.4; pointer-events: none; }

/* Paginación redondeada */
.pagination-rounded .page-link { border-radius: 50% !important; width: 36px; height: 36px; padding: 0; display: flex; align-items: center; justify-content: center; }

/* ======================================================
   LIST GROUP
   ====================================================== */
.list-group-item {
  background: var(--sx-card-bg);
  border: 1px solid var(--sx-border-color);
  padding: 0.75rem 1.1rem;
  color: var(--sx-text-body);
  font-size: 0.875rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  transition: var(--transition-fast);
}
.list-group-item:first-child { border-radius: var(--radius) var(--radius) 0 0; }
.list-group-item:last-child  { border-radius: 0 0 var(--radius) var(--radius); }
.list-group-item:only-child  { border-radius: var(--radius); }
/* flush = edge-to-edge dentro de un .card: sin esquinas propias (las da el .card). */
.list-group-flush > .list-group-item:first-child,
.list-group-flush > .list-group-item:last-child,
.list-group-flush > .list-group-item:only-child { border-radius: 0; }
.list-group-item + .list-group-item { border-top: none; }
.list-group-item.active { background: var(--sx-primary-light); color: var(--sx-primary); border-color: var(--sx-primary); font-weight: 700; }
.list-group-item-action:hover { background: var(--sx-body-bg); cursor: pointer; }

/* ======================================================
   TABLES
   ====================================================== */
.table {
  font-size: 0.875rem;
  color: var(--sx-text-body);
  --bs-table-bg: transparent;
  --bs-table-color: var(--sx-text-body);
}
.table thead th {
  font-family: var(--font-body);
  font-weight: bold;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--sx-text-muted);
  border-bottom: 2px solid var(--sx-border-color);
  padding: 0.9rem 1rem;
  background: var(--sx-body-bg);
  white-space: nowrap;
}
.table td {
  padding: 0.65rem 1rem;
  border-bottom: 1px solid var(--sx-border-color);
  vertical-align: middle;
}
.table tbody tr:last-child td { border-bottom: none; }
/* Collapsible Row Tables (.sx-lvl): TODAS las filas conservan su border-bottom,
   incluida la última (la regla global :last-child la quitaría). El !important
   gana a `.table tbody tr:last-child td` (mayor especificidad) para que ninguna
   fila quede sin borde. Aplica al nivel raíz y a las tablas anidadas hijas. */
.sx-lvl > tbody > tr > td,
.sx-lvl > tbody > tr:last-child > td { border-bottom: 1px solid var(--sx-border-color) !important; }
/* La primera columna de toda tabla siempre alineada a la izquierda (text-start),
   aún si el módulo aplica .text-center a sus columnas. */
.table thead th:first-child,
.table tbody td:first-child { text-align: left !important; }
/* Hijos DIRECTOS, no descendientes: con `.table-hover tbody tr:hover td` el
   hover se colaba en cualquier tabla anidada dentro de una celda (el desglose
   por escuela de Salud, sin ir más lejos), porque sus filas también son
   descendientes de la tabla de fuera. Para una tabla normal el resultado es el
   mismo — tbody siempre cuelga de table y td de tr — así que esto solo corta la
   fuga. */
.table-hover > tbody > tr:hover > td { background: var(--sx-row-hover); }
.table-striped tbody tr:nth-of-type(odd) td { background: rgba(248,249,252,0.7); }
.table > :not(caption) > * > * { box-shadow: none; }

/* Selección múltiple + borrado masivo (sx-bulk-delete.js) */
.sx-bulk-col { width: 1px; white-space: nowrap; text-align: center; }
.table > :not(caption) > * > .sx-bulk-col { padding-left: 1rem; padding-right: 1rem; }
.sx-bulk-col .form-check-input { margin: 0; cursor: pointer; float: none; width: 1.1rem; height: 1.1rem; flex: none; vertical-align: middle; }
.alert.sx-bulk-warn { display: flex; align-items: flex-start; gap: 0.6rem; }
.alert.sx-bulk-warn .flex-grow-1 { min-width: 0; }

/* Celda de icono UNIFICADA en tablas (regla global, helper sa_icon_cell()) */
.sx-icon-cell { display: inline-flex; align-items: center; gap: 0.5rem; }
.sx-icon-cell > i { font-size: 1.05rem; line-height: 1; color: var(--sx-text-heading); }
.sx-icon-cell > code { font-size: 0.8em; }

/* Avatar circular (tablas, p.ej. usuarios) */
.sx-avatar {
  width: 34px;
  height: 34px;
  min-width: 34px;
  border-radius: 50%;
  object-fit: cover;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.78rem;
  font-weight: 700;
  color: #fff;
  text-transform: uppercase;
  line-height: 1;
  border: 2px solid var(--sx-card-bg);
  box-shadow: 0 0 0 1px var(--sx-border-color);
}
.sx-avatar--initials { letter-spacing: 0.02em; background: var(--sx-primary); }

/* Avatar en tabla */
.table-avatar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.table-avatar-img {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--sx-primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  font-weight: 800;
  flex-shrink: 0;
}

/* ======================================================
   DROPDOWNS
   ====================================================== */
.dropdown-menu {
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius-lg);
  box-shadow: none;
  padding: 0.5rem;
  font-size: 0.875rem;
  background: var(--sx-card-bg);
  animation: dropFade 0.15s ease;
}
.dropdown-item {
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.875rem;
  color: var(--sx-text-body);
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  transition: var(--transition-fast);
}
.dropdown-item:hover { background: var(--sx-primary-light); color: var(--sx-primary); }
.dropdown-item.active, .dropdown-item:active { background: var(--sx-primary); color: #fff; }
.dropdown-divider { border-color: var(--sx-border-color); margin: 0.35rem 0; }
.dropdown-header {
  font-size: 0.68rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--sx-text-muted);
  padding: 0.5rem 0.875rem 0.25rem;
}

/* ======================================================
   WELCOME BANNER
   ====================================================== */
.sx-welcome-banner {
  background: var(--gradient-primary);
  border-radius: var(--radius-xl);
  padding: 1.75rem 2rem;
  color: #fff;
  position: relative;
  overflow: hidden;
  margin-bottom: 1.5rem;
}
.sx-welcome-banner::before {
  content: '';
  position: absolute;
  right: -30px;
  top: -40px;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  background: rgba(255,255,255,0.08);
}
.sx-welcome-banner::after {
  content: '';
  position: absolute;
  right: 60px;
  bottom: -50px;
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: rgba(255,255,255,0.06);
}
.sx-welcome-banner h2 {
  font-family: var(--font-display);
  color: #fff;
  font-size: 1.75rem;
  margin-bottom: 0.35rem;
  text-transform: uppercase;
}
.sx-welcome-banner p { color: rgba(255,255,255,0.85); margin-bottom: 0; }

/* Banner compacto (dashboard): menos alto, avatar + saludo + botón */
.sx-welcome-banner--compact { padding: 1rem 1.5rem; margin-bottom: 1.25rem; }
.sx-welcome-banner--compact h2 { font-size: 1.35rem; margin-bottom: 0.1rem; }
.sx-welcome-banner--compact p { font-size: 0.85rem; }
.sx-welcome-avatar {
  width: 54px; height: 54px; border-radius: 50%; flex-shrink: 0;
  object-fit: cover; display: inline-flex; align-items: center; justify-content: center;
  border: 2px solid rgba(255,255,255,0.6);
  box-shadow: 0 0 0 3px rgba(255,255,255,0.18);
}
.sx-welcome-avatar--initials {
  background: rgba(255,255,255,0.2); color: #fff;
  font-size: 1.25rem; font-weight: 700; font-family: var(--font-display);
}

/* Badge para el banner de bienvenida (fecha/hora en vivo, año académico).
   Translúcido sobre el degradado, texto blanco. */
.sx-welcome-badge {
  background: rgba(255,255,255,0.18);
  color: #fff;
  border: 1px solid rgba(255,255,255,0.28);
  font-weight: 600;
  white-space: nowrap;
}
.sx-welcome-badge i { opacity: 0.9; }

/* ======================================================
   WIDGET VARIOS
   ====================================================== */

/* Activity feed */
.sx-activity-feed { list-style: none; padding: 0; }
.sx-activity-item {
  display: flex;
  gap: 0.875rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--sx-border-color);
}
.sx-activity-item:last-child { border-bottom: none; }
.sx-activity-icon {
  width: 36px;
  height: 36px;
  border-radius: var(--radius);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  flex-shrink: 0;
}
.sx-activity-content { flex: 1; }
.sx-activity-text { font-size: 0.8rem; font-weight: 600; color: var(--sx-text-body); margin-bottom: 0.15rem; }
.sx-activity-time { font-size: 0.72rem; color: var(--sx-text-muted); }

/* Countdown widget */
.sx-countdown {
  display: flex;
  gap: 1rem;
  justify-content: center;
}
.sx-countdown-unit {
  text-align: center;
  min-width: 60px;
}
.sx-countdown-value {
  font-family: var(--font-display);
  font-size: 2.5rem;
  color: var(--sx-primary);
  line-height: 1;
  display: block;
}
.sx-countdown-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--sx-text-muted);
  letter-spacing: 0.05em;
}

/* Quote widget */
.sx-quote {
  border-left: 4px solid var(--sx-primary);
  padding: 1rem 1.25rem;
  background: var(--sx-primary-light);
  border-radius: 0 var(--radius) var(--radius) 0;
}
.sx-quote-text {
  font-style: italic;
  font-size: 0.9rem;
  color: var(--sx-text-body);
  margin-bottom: 0.5rem;
}
.sx-quote-author { font-size: 0.78rem; font-weight: 800; color: var(--sx-primary); }

/* ======================================================
   FILE UPLOAD
   ====================================================== */
.sx-dropzone {
  border: 2px dashed var(--sx-border-color);
  border-radius: var(--radius-lg);
  padding: 2.5rem 1.5rem;
  text-align: center;
  cursor: pointer;
  transition: var(--transition-fast);
  background: var(--sx-body-bg);
}
.sx-dropzone:hover,
.sx-dropzone.drag-over {
  border-color: var(--sx-primary);
  background: var(--sx-primary-light);
}
.sx-dropzone-icon {
  font-size: 2.5rem;
  color: var(--sx-primary);
  margin-bottom: 0.75rem;
  display: block;
}
.sx-dropzone-title {
  font-weight: 700;
  color: var(--sx-text-heading);
  font-size: 0.95rem;
  margin-bottom: 0.25rem;
}
.sx-dropzone-sub { font-size: 0.8rem; color: var(--sx-text-muted); }

/* ======================================================
   AUTH PAGES
   ====================================================== */
.sx-auth-page {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.sx-auth-brand {
  background: var(--gradient-dark);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 3rem;
  position: relative;
  overflow: hidden;
}
.sx-auth-brand::before {
  content: '';
  position: absolute;
  top: -80px; right: -80px;
  width: 300px; height: 300px;
  border-radius: 50%;
  background: rgba(236,119,75,0.12);
}
.sx-auth-brand::after {
  content: '';
  position: absolute;
  bottom: -60px; left: -60px;
  width: 250px; height: 250px;
  border-radius: 50%;
  background: rgba(116,206,228,0.1);
}
.sx-auth-form {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  background: var(--sx-body-bg);
}
.sx-auth-form-inner { width: 100%; max-width: 420px; }

/* Password strength */
.sx-password-strength {
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--sx-border-color);
  overflow: hidden;
  margin-top: 0.5rem;
}
.sx-password-strength-bar {
  height: 100%;
  border-radius: var(--radius-pill);
  transition: width 0.4s ease, background 0.4s ease;
}

@media (max-width: 767.98px) {
  .sx-auth-page { grid-template-columns: 1fr; }
  .sx-auth-brand { display: none; }
}

/* ======================================================
   ICONS PAGE
   ====================================================== */
.sx-icon-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 0.75rem; }
.sx-icon-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 1rem 0.5rem;
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius);
  cursor: pointer;
  transition: var(--transition-fast);
  background: var(--sx-card-bg);
}
.sx-icon-item:hover { border-color: var(--sx-primary); background: var(--sx-primary-light); color: var(--sx-primary); }
.sx-icon-item .bi { font-size: 1.5rem; }
.sx-icon-item span { font-size: 0.65rem; color: var(--sx-text-muted); text-align: center; word-break: break-all; }
.sx-icon-item:hover span { color: var(--sx-primary); }

/* ======================================================
   SECTION TITLES (en páginas de componentes)
   ====================================================== */
.sx-section-title {
  font-family: var(--font-display);
  font-size: 1.1rem;
  color: var(--sx-text-heading);
  margin-bottom: 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 2px solid var(--sx-border-color);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.sx-section-title .bi { color: var(--sx-primary); }

/* ======================================================
   DARK MODE OVERRIDES
   ====================================================== */
[data-theme="dark"] .card,
[data-theme="dark"] .list-group-item,
[data-theme="dark"] .modal-content,
[data-theme="dark"] .dropdown-menu,
[data-theme="dark"] .toast,
[data-theme="dark"] .popover,
[data-theme="dark"] .accordion-button,
[data-theme="dark"] .accordion-item,
[data-theme="dark"] .page-link { background: var(--sx-card-bg); border-color: var(--sx-border-color); }

[data-theme="dark"] .form-control,
[data-theme="dark"] .form-select { background: var(--sx-dark-2); border-color: var(--sx-border-color); color: var(--sx-text-body); }

[data-theme="dark"] .input-group .input-group-text { background: var(--sx-dark-3); }

[data-theme="dark"] .table thead th { background: var(--sx-dark-2); }
[data-theme="dark"] .sx-dropzone { background: var(--sx-dark-2); }
[data-theme="dark"] .sx-auth-form { background: var(--sx-dark-2); }

/* ======================================================
   INPUT CON ÍCONO INTERNO
   ====================================================== */
.sx-input-icon {
  position: relative;
}
.sx-input-icon .form-control {
  padding-left: 2.6rem;
}
.sx-input-icon .form-control.icon-right {
  padding-left: 0.85rem;
  padding-right: 2.6rem;
}
.sx-input-icon .form-control.icon-both {
  padding-left: 2.6rem;
  padding-right: 2.6rem;
}
.sx-input-icon .sx-icon-left,
.sx-input-icon .sx-icon-right {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  color: var(--sx-text-muted);
  font-size: 1rem;
  pointer-events: none;
  z-index: 5;
}
.sx-input-icon .sx-icon-left  { left: 0.8rem; }
.sx-input-icon .sx-icon-right { right: 0.8rem; pointer-events: auto; cursor: pointer; }

/* ======================================================
   DATATABLES — toolbar, tabla y paginación (tema unificado)
   ====================================================== */
.dataTables_wrapper { font-family: var(--font-body); }
/* Sin margen en la tabla (global, para todas las DataTables). */
table.dataTable { margin: 0 !important; }

/* Indicador de carga (processing): el spinner de 4 puntos viene de la
   integración bootstrap5 de DataTables en azul Bootstrap por defecto —
   recoloreado a la marca. El texto "Procesando..." se vacía en sx-datatables.js
   (language.processing = ''), así que solo se ven los puntos. */
div.dataTables_processing > div:last-child > div {
  background: var(--sx-primary) !important;
}

/*
 * Sin margen lateral tampoco. Las filas de controles de DataTables (buscador,
 * "mostrar N", info y paginación) son .row de Bootstrap, que trae margen
 * izquierdo/derecho NEGATIVO (-.5 * gutter = -.75rem) y el padding equivalente
 * en sus columnas. Resultado: sobresalían 12px por cada lado respecto de la
 * tabla, que va a ras del card.
 *
 * Se anula la gutter en vez del margen: poniendo margin:0 a secas quedaría el
 * padding de las columnas y los controles se irían 12px hacia DENTRO — el mismo
 * desalineo al revés. Con la gutter a 0 caen los dos a la vez.
 */
.dataTables_wrapper > .row { --bs-gutter-x: 0; }

/* Fila de controles superior (longitud + búsqueda): separada de la tabla */
.dataTables_wrapper > .row:first-child {
  align-items: center;
  padding-bottom: 0.9rem;
  margin-bottom: 0;
  border-bottom: 1px solid var(--sx-border-color);
}
.dataTables_length label,
.dataTables_filter label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  margin-bottom: 0;
  white-space: nowrap;
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--sx-text-muted);
}
.dataTables_filter label { justify-content: flex-end; }
.dataTables_filter input { flex: 0 1 240px; }

.dataTables_length select,
.dataTables_filter input {
  border: 1.5px solid var(--sx-border-color) !important;
  border-radius: var(--radius) !important;
  padding: 0.4rem 0.75rem !important;
  font-family: var(--font-body) !important;
  font-size: 0.8rem !important;
  color: var(--sx-text-body) !important;
  background-color: var(--sx-card-bg) !important;
  box-shadow: none !important;
  outline: none !important;
  transition: var(--transition-fast);
}
.dataTables_length select:focus,
.dataTables_filter input:focus {
  border-color: var(--sx-primary) !important;
  box-shadow: 0 0 0 3px rgba(var(--sx-primary-rgb), 0.12) !important;
  outline: none !important;
}

@media (max-width: 575.98px) {
  .dataTables_filter label { justify-content: flex-start; }
  .dataTables_filter input { flex: 1 1 auto; }
}

/* Fila inferior (info + paginación): separada de la tabla, alineada */
.dataTables_wrapper > .row:last-child {
  align-items: center;
  padding-top: 0.9rem;
  margin-top: 0;
  border-top: 1px solid var(--sx-border-color);
}
.dataTables_info {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--sx-text-muted);
  padding-top: 0 !important;
}
.dataTables_paginate { display: flex; justify-content: flex-end; }
.dataTables_paginate .pagination { margin-bottom: 0; flex-wrap: wrap; }

/* Botones de exportación (dt-buttons) */
.dt-buttons .btn {
  font-size: 0.8rem !important;
  padding: 0.4rem 0.875rem !important;
  border-radius: var(--radius-sm) !important;
  font-weight: 700 !important;
  margin-right: 0.35rem !important;
}

/* Paginación compacta */
.dataTables_paginate .paginate_button {
  font-size: 0.8rem !important;
  border-radius: var(--radius-sm) !important;
  background: var(--sx-card-bg) !important;
  color: var(--sx-text-body) !important;
  margin: 0 0.1rem !important;
  transition: var(--transition-fast) !important;
  cursor: pointer;
}
/* Default: texto normal (sin !important para que los estados específicos ganen) */
.dataTables_paginate .paginate_button .page-link {
  color: var(--sx-text-body);
}
/* Activo: fondo primario, texto blanco */
.dataTables_paginate .paginate_button.current,
.dataTables_paginate .paginate_button.current:hover {
  background: var(--sx-primary) !important;
  border-color: var(--sx-primary) !important;
}
.dataTables_paginate .paginate_button.current .page-link,
.dataTables_paginate .paginate_button.current:hover .page-link {
  color: #fff !important;
}
/* Hover números: fondo primario, texto blanco */
.dataTables_paginate .paginate_button:not(.previous):not(.next):not(.current):not(.disabled):hover {
  background: var(--sx-primary) !important;
  border-color: var(--sx-primary) !important;
}
.dataTables_paginate .paginate_button:not(.previous):not(.next):not(.current):not(.disabled):hover .page-link {
  color: #fff !important;
}
/* Hover Anterior/Siguiente: solo borde naranja, texto oscuro */
.dataTables_paginate .paginate_button.previous:hover,
.dataTables_paginate .paginate_button.next:hover {
  background: var(--sx-card-bg) !important;
  border-color: var(--sx-primary) !important;
}
.dataTables_paginate .paginate_button.previous:hover .page-link,
.dataTables_paginate .paginate_button.next:hover .page-link {
  color: #fff !important;
}
.dataTables_paginate .paginate_button.disabled,
.dataTables_paginate .paginate_button.disabled:hover {
  opacity: 0.4 !important;
  cursor: not-allowed !important;
  background: var(--sx-card-bg) !important;
  color: var(--sx-text-muted) !important;
}
.dataTables_paginate .paginate_button.disabled .page-link,
.dataTables_paginate .paginate_button.disabled:hover .page-link {
  color: var(--sx-text-body) !important;
}
/* ======================================================
   KANBAN BOARD
   ====================================================== */
.sx-kanban-board {
  display: flex;
  gap: 1.25rem;
  padding-bottom: 1rem;
  align-items: flex-start;
}
.sx-kanban-col {
  /* Reparten por igual el ancho completo del row. */
  flex: 1 1 0;
  min-width: 0;
  background: var(--sx-card-bg);
  border-radius: var(--radius-lg);
  border: 1px solid var(--sx-border-color);
  display: flex;
  flex-direction: column;
}
/* En pantallas estrechas vuelven a ancho fijo con scroll horizontal. */
@media (max-width: 768px) {
  .sx-kanban-board { overflow-x: auto; }
  .sx-kanban-col { flex: 0 0 260px; min-width: 260px; }
}
.sx-kanban-col__header {
  padding: 1rem 1rem 0.75rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--sx-border-color);
}
.sx-kanban-col__title {
  font-weight: 800;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--sx-text-heading);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.sx-kanban-col__body {
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  min-height: 60px;
}
.sx-kanban-card {
  background: var(--sx-card-bg);
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius);
  padding: 0.875rem;
  cursor: grab;
  transition: var(--transition-fast);
}
.sx-kanban-card:active { cursor: grabbing; opacity: 0.85; }
.sx-kanban-card__title { font-weight: 700; font-size: 0.875rem; color: var(--sx-text-heading); margin-bottom: 0.5rem; }
.sx-kanban-card__meta { font-size: 0.75rem; color: var(--sx-text-muted); display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.sx-kanban-card.sortable-ghost { opacity: 0.4; background: var(--sx-primary-light); border: 2px dashed var(--sx-primary); }
/* Cabecera de tarjeta: título + acciones (editar/eliminar al hover) */
.sx-kanban-card__top { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.5rem; }
.sx-kanban-card__top .sx-kanban-card__title { margin-bottom: 0.5rem; flex: 1; min-width: 0; }
.sx-kanban-card__actions { display: flex; gap: 0.15rem; opacity: 0; transition: var(--transition-fast); flex-shrink: 0; }
.sx-kanban-card:hover .sx-kanban-card__actions { opacity: 1; }
.sx-kanban-card__btn {
  border: none; background: none; padding: 0.1rem 0.25rem; line-height: 1;
  color: var(--sx-text-muted); border-radius: var(--radius-xs); cursor: pointer; font-size: 0.8rem;
}
.sx-kanban-card__btn:hover { color: var(--sx-primary); background: var(--sx-primary-light); }
.sx-kanban-card__btn .bi-trash:hover,
.sx-kanban-card__btn:hover .bi-trash { color: var(--sx-danger, #c0392b); }
/* Placeholder de columna vacía: aviso "sin tareas" */
.sx-kanban-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 1.5rem 0.75rem;
  border: 1px dashed var(--sx-border-color);
  border-radius: var(--radius);
  color: var(--sx-text-muted);
  font-size: 0.8rem;
  text-align: center;
}
.sx-kanban-empty .bi { font-size: 1.5rem; opacity: 0.55; }

/* ======================================================
   MODAL PERFIL — avatar con borde
   ====================================================== */
.sx-profile-avatar {
  width: 88px; height: 88px; border-radius: 50%;
  object-fit: cover; display: inline-flex; align-items: center; justify-content: center;
  border: 3px solid var(--sx-card-bg);
  box-shadow: 0 0 0 3px var(--sx-primary);
}
.sx-profile-avatar--initials {
  background: var(--sx-primary); color: #fff;
  font-size: 1.75rem; font-weight: 700; font-family: var(--font-display);
}

/* ======================================================
   PERMISSION OVERRIDES — matriz de permisos por módulo
   ====================================================== */
.po-group { border: 1px solid var(--sx-border-color); border-radius: var(--radius); overflow: hidden; }
.po-group__head {
  display: flex; align-items: center;
  background: var(--sx-body-bg); padding: 0.5rem 0.75rem;
  font-weight: 700; font-size: 0.85rem; color: var(--sx-text-heading);
  border-bottom: 1px solid var(--sx-border-color);
}
.po-table td { vertical-align: middle; }
.po-matrix { max-height: 60vh; overflow-y: auto; }
/* Color del tri-estado según selección */
.po-state--on  { border-color: var(--sx-green, #2e7d32); color: var(--sx-green, #2e7d32); font-weight: 600; }
.po-state--off { border-color: var(--sx-danger, #c0392b); color: var(--sx-danger, #c0392b); font-weight: 600; }

/* ======================================================
   CHAT APP
   ====================================================== */
.sx-chat-layout {
  display: flex;
  height: calc(100vh - var(--topbar-height) - 3rem);
  gap: 0;
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--sx-card-bg);
}
.sx-chat-sidebar {
  width: 300px;
  flex-shrink: 0;
  border-right: 1px solid var(--sx-border-color);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.sx-chat-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.sx-chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 1.25rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.sx-chat-bubble {
  max-width: 68%;
  padding: 0.75rem 1rem;
  border-radius: var(--radius-lg);
  font-size: 0.875rem;
  line-height: 1.5;
}
.sx-chat-bubble--in {
  background: var(--sx-body-bg);
  border: 1px solid var(--sx-border-color);
  color: var(--sx-text-body);
  align-self: flex-start;
  border-bottom-left-radius: var(--radius-xs);
}
.sx-chat-bubble--out {
  background: var(--sx-primary);
  color: #fff;
  align-self: flex-end;
  border-bottom-right-radius: var(--radius-xs);
}
.sx-chat-input-area {
  border-top: 1px solid var(--sx-border-color);
  padding: 1rem;
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
}
.sx-chat-contact {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  cursor: pointer;
  transition: var(--transition-fast);
  border-bottom: 1px solid var(--sx-border-color);
}
.sx-chat-contact:hover, .sx-chat-contact.active { background: var(--sx-primary-light); }
.sx-chat-avatar {
  width: 42px; height: 42px;
  border-radius: 50%;
  background: var(--sx-primary);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 0.85rem;
  flex-shrink: 0;
  position: relative;
}
.sx-chat-avatar .sx-online {
  position: absolute; bottom: 1px; right: 1px;
  width: 10px; height: 10px;
  border-radius: 50%;
  border: 2px solid var(--sx-card-bg);
  background: var(--sx-success);
}

/* ======================================================
   FILE MANAGER
   ====================================================== */
.sx-fm-layout {
  display: flex;
  gap: 1.25rem;
  align-items: flex-start;
}
.sx-fm-sidebar {
  width: 220px;
  flex-shrink: 0;
}
.sx-fm-main { flex: 1; }
.sx-fm-tree-item {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.45rem 0.75rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 0.875rem;
  color: var(--sx-text-body);
  transition: var(--transition-fast);
}
.sx-fm-tree-item:hover, .sx-fm-tree-item.active {
  background: var(--sx-primary-light);
  color: var(--sx-primary);
}
.sx-fm-file-card {
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius);
  padding: 1rem;
  text-align: center;
  cursor: pointer;
  transition: var(--transition-fast);
  background: var(--sx-card-bg);
  position: relative;
}
.sx-fm-file-card:hover { border-color: var(--sx-primary); background: var(--sx-primary-light); }
.sx-fm-file-card .sx-fm-icon { font-size: 2.5rem; margin-bottom: 0.5rem; display: block; }
.sx-fm-file-card .sx-fm-name { font-size: 0.8rem; font-weight: 700; color: var(--sx-text-heading); word-break: break-all; }
.sx-fm-file-card .sx-fm-size { font-size: 0.72rem; color: var(--sx-text-muted); }

/* ======================================================
   PROFILE PAGES
   ====================================================== */
.sx-profile-header {
  background: var(--gradient-dark);
  border-radius: var(--radius-xl);
  padding: 2rem 2rem 0;
  margin-bottom: 0;
  position: relative;
  overflow: hidden;
}
.sx-profile-header::before {
  content: '';
  position: absolute; top: -60px; right: -60px;
  width: 220px; height: 220px; border-radius: 50%;
  background: rgba(236,119,75,0.12);
}
.sx-profile-avatar {
  width: 90px; height: 90px;
  border-radius: 50%;
  border: 4px solid rgba(255,255,255,0.25);
  object-fit: cover;
  flex-shrink: 0;
}
.sx-profile-avatar-initials {
  width: 90px; height: 90px;
  border-radius: 50%;
  border: 4px solid rgba(255,255,255,0.25);
  background: var(--sx-primary);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-size: 2rem;
  flex-shrink: 0;
}
.sx-profile-name { font-family: var(--font-display); color: #fff; font-size: 1.75rem; margin-bottom: 0.25rem; }
.sx-profile-role { color: rgba(255,255,255,0.75); font-size: 0.875rem; }
.sx-profile-tabs { border-top: 1px solid rgba(255,255,255,0.12); margin-top: 1.5rem; }
.sx-profile-tabs .nav-link {
  color: rgba(255,255,255,0.6) !important;
  border: none !important;
  border-radius: 0 !important;
  padding: 0.75rem 1.25rem;
  font-weight: 700;
  font-size: 0.875rem;
}
.sx-profile-tabs .nav-link:hover { color: rgba(255,255,255,0.9) !important; background: transparent !important; }
.sx-profile-tabs .nav-link.active {
  color: #fff !important;
  background: transparent !important;
  border-bottom: 3px solid var(--sx-primary) !important;
}
.sx-profile-tabs .nav-link::after { display: none; }

/* ============================================================
   DASHBOARD (Super Admin) — charts + secciones interactivas
   ============================================================ */
.sx-dashboard-chart-card .card-body { min-height: 200px; }
.sx-dashboard-chart-card .card-title { color: var(--sx-text-heading); }
.sx-chart { width: 100%; }
.sx-chart .apexcharts-tooltip {
  background: var(--sx-card-bg) !important;
  border-color: var(--sx-border-color) !important;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
  color: var(--sx-text-body);
}
.sx-chart .apexcharts-tooltip-title {
  background: var(--sx-body-bg) !important;
  border-color: var(--sx-border-color) !important;
  color: var(--sx-text-heading);
  font-weight: 700;
}
.sx-chart .apexcharts-tooltip-text-y-label,
.sx-chart .apexcharts-tooltip-text-y-value { color: var(--sx-text-body); }
.sx-chart .apexcharts-legend-text { color: var(--sx-text-muted) !important; }
.sx-dashboard-chart-card .alert { border-radius: 10px; }

/* ===========================================================================
   Estilos movidos desde public/portal/_header.php (regla: nada de <style> inline)
   NOTA: el selector original era un `body { ... }` DESNUDO. components.css se
   carga en TODA la app, así que se renombró a `.sx-portal-body` para no cambiar
   el fondo global. Requiere que <body> del portal lleve class="sx-portal-body".
   =========================================================================== */
.sx-portal-body { background: var(--sx-bg, #f4f6fb); }
.sx-portal-main { max-width: 1100px; margin: 0 auto; padding: 1.5rem 1rem 3rem; }
.sx-portal-card { background: #fff; border: 1px solid rgba(0,0,0,.075); border-radius: .75rem; }

/* ===========================================================================
   TARJETA DE REPORTE (lanzador) — usada en app/reports.php.
   Enlace tipo tarjeta: círculo de icono (badge-soft-*), título + descripción y
   chevron a la derecha. Solo tokens sx; hover con realce de borde.
   =========================================================================== */
.sx-report-card {
  display: flex;
  align-items: center;
  gap: .85rem;
  height: 100%;
  padding: 1rem;
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius-lg, .75rem);
  background: var(--sx-card-bg);
  color: var(--sx-text-body);
  text-decoration: none;
  font: inherit;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  transition: var(--transition, all .25s ease);
}
.sx-report-card:hover {
  border-color: rgba(var(--sx-primary-rgb), .55);
  transform: translateY(-2px);
  color: var(--sx-text-body);
}
.sx-report-card.active {
  border-color: var(--sx-primary);
}
.sx-report-card__icon {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm, .5rem);
  font-size: 1.35rem;
}
.sx-report-card__body { display: flex; flex-direction: column; min-width: 0; }
.sx-report-card__title { font-weight: 700; color: var(--sx-text-heading); line-height: 1.2; }
.sx-report-card__desc { font-size: .82rem; color: var(--sx-text-muted); margin-top: .15rem; }
.sx-report-card__go { margin-left: auto; color: var(--sx-text-muted); transition: var(--transition, all .25s ease); }
.sx-report-card:hover .sx-report-card__go { color: var(--sx-primary); transform: translateX(2px); }

/* ======================================================
   ASISTENCIA (attendance.php, view-class/day-attendance)
   ====================================================== */
.sx-att-table > tbody > tr > td { vertical-align: middle; padding-top: .8rem; padding-bottom: .8rem; }
.sx-att-clname { font-weight: 700; color: var(--sx-text-heading); line-height: 1.2; }
.sx-att-rate { display: flex; align-items: center; gap: .5rem; min-width: 132px; }
.sx-att-rate .progress { flex: 1; height: 7px; }
.sx-att-rate__pct { font-family: var(--font-display); font-weight: 700; font-size: .8rem; min-width: 34px; text-align: right; }
.sx-att-chips { display: flex; gap: .3rem; flex-wrap: wrap; }
.sx-att-chips .badge { font-weight: 700; }
.sx-att-teacher { display: inline-flex; align-items: center; gap: .5rem; }
.sx-att-teacher__nm { font-weight: 600; color: var(--sx-text-body); }
/* Control segmentado (filtro por estado): pista clara + pill activo. */
.sx-seg { display: inline-flex; background: var(--sx-body-bg); border: 1px solid var(--sx-border-color); border-radius: var(--radius); padding: 3px; gap: 2px; }
.sx-seg button, .sx-seg .btn-check + label { font-family: var(--font-body); font-weight: 800; font-size: .78rem; line-height: 1; border: 0; background: transparent; color: var(--sx-text-muted); padding: .4rem .7rem; border-radius: calc(var(--radius) - 3px); cursor: pointer; display: inline-flex; align-items: center; gap: .35rem; transition: var(--transition-fast, all .15s ease); }
.sx-seg button:hover, .sx-seg .btn-check + label:hover { color: var(--sx-text-body); }
.sx-seg button.on, .sx-seg .btn-check:checked + label { background: var(--sx-card-bg); color: var(--sx-text-heading); box-shadow: 0 1px 3px rgba(0,0,0,.10); }
.sx-seg .btn-check:checked + .sx-seg__primary { background: var(--sx-primary); color: #fff; }
.sx-seg .btn-check:checked + .sx-seg__sky { background: var(--sx-sky); color: #fff; }
.sx-seg .btn-check:checked + .sx-seg__purple { background: var(--sx-purple); color: #fff; }
.sx-seg__primary > i { color: var(--sx-primary); }
.sx-seg__sky > i { color: var(--sx-sky-dark); }
.sx-seg__purple > i { color: var(--sx-purple-dark); }
.sx-seg .btn-check:checked + label > i { color: inherit; }
.sx-seg__dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.sx-att-actions { display: flex; gap: .35rem; justify-content: center; }
/* Header: mismo color que las demás celdas (--sx-text-body), solo en negrita. */
.sx-att-table > thead > tr > th { font-weight: bold;}
/* Tabla a ras del card: sin padding del card-body y SIN márgenes en tabla/paginación/select/búsqueda. */
.sx-att-card > .card-body { padding: 0; }
.sx-att-card .table { margin-bottom: 0; }

/* Filas de controles de DataTables (arriba: length+search, abajo: info+paginación):
   alineadas con el TEXTO de las celdas y con aire vertical para no pegarse a los
   bordes del card. El 1rem no es arbitrario: es el mismo padding lateral que
   .table thead th / tbody td (ver arriba), así que buscador, paginación y primera
   columna caen todos en la misma línea vertical.
   Antes esto era .25rem y funcionaba de casualidad: la gutter de Bootstrap añadía
   .75rem a las columnas de la fila. Al anular la gutter (más arriba) para quitar el
   margen lateral, esos .75rem desaparecieron y los controles se descolgaron a 4px;
   ahora el valor dice lo que hace y no depende de la gutter. */
.sx-att-card .dataTables_wrapper > .row:first-child { padding: .85rem 1rem !important; margin: 0 !important; }
.sx-att-card .dataTables_wrapper > .row:last-child { padding: .85rem 1rem !important; margin: 0 !important; }
.sx-att-card .dataTables_length,
.sx-att-card .dataTables_filter,
.sx-att-card .dataTables_info,
.sx-att-card .dataTables_paginate,
.sx-att-card .pagination { margin: 0 !important; }
.sx-att-card .dataTables_length,
.sx-att-card .dataTables_filter,
.sx-att-card .dataTables_info,
.sx-att-card .dataTables_paginate { padding: 0 !important; }
.sx-att-card .sx-transcript-empty { padding: 2.5rem 1.1rem; }

/* Pie del card a ras (p. ej. el botón Guardar bajo una tabla flush): separa del
   contenido con el borde del tema. No se usa la utilidad .border-top de Bootstrap
   porque pinta con --bs-border-color, que el tema no remapea — daría el gris
   genérico y no seguiría el modo oscuro. */
.sx-att-foot { border-top: 1px solid var(--sx-border-color); }

/* ======================================================
   FULLCALENDAR — barra de controles (Hoy / ‹ › / Mes·Semana·Día·Lista).
   Compartido a propósito: lo usan app/calendar y la pestaña Calendario de
   app/courses, y por defecto FullCalendar los pinta en su azul marino, que no
   es de la paleta. Va sobre `.fc` porque FullCalendar pone esa clase en el
   PROPIO elemento de montaje (no en un hijo) — sirve para los dos calendarios
   sin duplicar reglas ni acoplarse a un id.

   Se sobreescriben sus VARIABLES en vez de sus selectores: son las que usan
   todas sus reglas internas, así que no hace falta un solo !important.
   ====================================================== */
.fc {
  /* Fondo de la rejilla. FullCalendar trae --fc-page-bg-color:#fff fijo, así que
     en modo oscuro las celdas quedaban blancas. */
  --fc-page-bg-color: var(--sx-card-bg);
  --fc-neutral-bg-color: var(--sx-body-bg);
  --fc-neutral-text-color: var(--sx-text-muted);

  --fc-button-bg-color: var(--sx-card-bg);
  --fc-button-border-color: var(--sx-border-color);
  --fc-button-text-color: var(--sx-text-body);
  --fc-button-hover-bg-color: var(--sx-body-bg);
  --fc-button-hover-border-color: var(--sx-border-color);
  --fc-button-active-bg-color: var(--sx-primary);
  --fc-button-active-border-color: var(--sx-primary);
}
.fc .fc-button {
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: .8rem;
  font-weight: 700;
  padding: .35rem .75rem;
  box-shadow: none !important; /* su focus ring propio es azul de Bootstrap */
  /* SIN transition (ni var(--transition), que es `all .25s ease`). Estos botones
     sacan su color de custom properties encadenadas
     (--fc-button-bg-color → --sx-card-bg): con una transición sobre
     background-color, al cambiar a modo oscuro el botón se queda clavado en el
     color del tema anterior —medido: la variable ya valía #2d2c38 y seguía
     pintando blanco, incluso acotando la transición a las propiedades sueltas—.
     Sin ella, el cambio de tema entra al instante y el hover se siente igual. */
}
/* El texto: FullCalendar tiene UNA sola variable para los tres estados, así que
   el activo —fondo de marca— necesita su color aparte o quedaría gris sobre
   naranja. Vale el #fff literal: es texto sobre color, el caso que la guía
   permite. */
.fc .fc-button-primary:not(:disabled).fc-button-active,
.fc .fc-button-primary:not(:disabled):active { color: #fff; }
.fc .fc-button-primary:focus-visible {
  outline: 2px solid var(--sx-primary);
  outline-offset: 2px;
}
/* Grupo Mes·Semana·Día·Lista: se pegan entre sí, redondeando solo los extremos. */
.fc .fc-button-group > .fc-button:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.fc .fc-button-group > .fc-button:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.fc .fc-toolbar-title { font-family: var(--font-display); font-size: 1.1rem; font-weight: 700; color: var(--sx-text-heading); }

/* ======================================================
   CALENDARIO — barra lateral (leyenda de colores + próximos).
   Compartida por app/calendar y la pestaña Calendario de app/courses. Estaba en
   el <style> inline de calendar.php, donde la pestaña no podía alcanzarla.
   ====================================================== */
.cal-legend { display: flex; flex-direction: column; gap: .4rem; }
.cal-legend-item { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.cal-legend-dot {
  width: .8rem; height: .8rem; flex: 0 0 auto;
  border-radius: var(--radius-circle);
  border: 2px solid var(--sx-card-bg);
  box-shadow: 0 0 0 1px var(--sx-border-color);
}
.cal-legend-txt {
  font-size: .75rem; color: var(--sx-text-body);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Próximos: el avatar de fecha (.sx-avatar--date) + hora + título + el tipo.
   Mismo componente que la lista de teacher-profile. */
.cal-upcoming { display: flex; flex-direction: column; max-height: 30rem; overflow-y: auto; }
.cal-up-item {
  display: flex; align-items: center; gap: .75rem;
  width: 100%; text-align: left;
  background: none; border: 0;
  border-bottom: 1px solid var(--sx-border-color);
  padding: .7rem .9rem;
  transition: var(--transition);
}
.cal-up-item:last-child { border-bottom: 0; }
.cal-up-item:hover { background: var(--sx-row-hover); }
/* min-width:0 para que el texto largo se recorte en vez de estirar la fila. */
.cal-up-body { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; gap: 1px; }
.cal-up-hours { font-size: .7rem; color: var(--sx-text-muted); }
.cal-up-title {
  font-size: .82rem; font-weight: 600; color: var(--sx-text-heading);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-up-class {
  font-size: .68rem; color: var(--sx-text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-up-kind { flex: 0 0 auto; font-size: .62rem; align-self: flex-start; }

/* ======================================================
   OJO PARA VER LA CONTRASEÑA — lo inyecta assets/js/sx-password-toggle.js
   dentro del .form-icon del campo. El icono de la IZQUIERDA (.form-icon > i)
   lleva pointer-events:none y z-index:5, asi que este va por encima y si
   recibe clics.
   ====================================================== */
.sx-pw-eye {
  position: absolute;
  top: 50%;
  right: 0.6rem;
  transform: translateY(-50%);
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: var(--radius-circle);
  color: var(--sx-text-muted);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
  transition: var(--transition);
}
.sx-pw-eye:hover { color: var(--sx-primary); background: var(--sx-primary-light); }
.sx-pw-eye:focus { outline: none; color: var(--sx-primary); }
/* Hueco para que el texto de la clave no pase por debajo del ojo. */
.sx-pw-has-eye { padding-right: 2.6rem !important; }

/* ======================================================
   CRITERIOS DE CONTRASEÑA — lista en vivo bajo el campo
   Marcado: <ul data-sx-pw-criteria="idInput"><li data-rule="len">…
   Las clases las conmuta assets/js/sx-password-criteria.js.
   Usan en auth/change-password.php y auth/reset-password.php.
   ====================================================== */
.sx-pw-criteria {
  list-style: none;
  margin: .5rem 0 0;
  padding: .6rem .7rem;
  background: var(--sx-body-bg);
  border: 1px solid var(--sx-border-color);
  border-radius: var(--radius);
  font-size: .72rem;
  /* Dos columnas: son 4 criterios cortos y en una sola fila vertical ocupaban
     media tarjeta. Grid y no columns/float para que las filas se alineen. */
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .15rem .7rem;
}
.sx-pw-criteria li {
  display: flex;
  align-items: center;
  gap: .35rem;
  /* El color por defecto es el de "no cumple": el estado neutro (is-pending)
     y el de cumplido (is-ok) lo sobreescriben abajo. */
  color: var(--sx-danger);
  line-height: 1.6;
}
.sx-pw-criteria li > i { font-size: .8rem; flex: 0 0 auto; }
/* Todavía sin escribir nada: gris, no rojo. Marcar en rojo lo que la persona
   aún no ha tenido ocasión de teclear es hostil. */
.sx-pw-criteria li.is-pending { color: var(--sx-text-muted); }
.sx-pw-criteria li.is-ok { color: var(--sx-success); }

/* ============================================================
   BOTÓN CIRCULAR DE SOLO ÍCONO (.sx-btn-circle)
   ============================================================
   Se combina con los .btn-* del repo (que ya están sobre --sx-*): la clase solo
   cambia la FORMA, nunca el color. Así `btn btn-primary sx-btn-circle` sigue
   siendo naranja de marca y respeta el branding por escuela.

   Cuadrado exacto vía aspect-ratio + ancho mínimo, en vez de padding calculado:
   el ícono no siempre mide lo mismo (bi-trash y bi-x-lg no son iguales de
   anchos) y con padding los botones salían ovalados de distinto tamaño.

   OJO: sin texto, el botón no tiene nombre accesible. Todo uso lleva
   aria-label + title — está en el markup de cada botón, no aquí, porque el
   texto es bilingüe y sale de $t. */
.sx-btn-circle {
  border-radius: var(--radius-circle);
  aspect-ratio: 1 / 1;
  min-width: 2.5rem;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}
.sx-btn-circle > i { margin: 0 !important; }

/* ============================================================
   AVATAR DE FECHA (.sx-avatar.sx-avatar--date)
   ============================================================
   El cuadrado redondeado con el día grande y el mes debajo:

     <span class="sx-avatar sx-avatar--date" style="background:<color>">
       <span class="sx-avatar__day">21</span>
       <span class="sx-avatar__mon">JUL</span>
     </span>

   Variante del .sx-avatar de siempre: hereda el anillo y la sombra, y solo
   cambia forma (cuadrado redondeado en vez de círculo), tamaño y disposición.
   Nació repetido a mano con seis estilos en línea en teacher-profile.php; está
   aquí para que el calendario y esa página no se separen con el tiempo.

   El COLOR lo pone quien lo usa (inline o por clase), porque cada pantalla lo
   tiñe por algo distinto: teacher-profile por hash del título, el calendario por
   materia. Lo que NO se hereda del .sx-avatar es el `color:#fff` fijo: sobre una
   materia amarilla (#f2c917 es real) el texto desaparece. Quien lo pinta decide
   también el color del texto por luminancia — ver readableText() en calendar.js. */
.sx-avatar--date {
  width: 48px;
  height: 48px;
  min-width: 48px;
  flex-direction: column;
  justify-content: center;
  border-radius: var(--radius);
  text-transform: none;
  gap: 1px;
}
.sx-avatar--date .sx-avatar__day { font-size: 1.05rem; font-weight: 700; line-height: 1; }
.sx-avatar--date .sx-avatar__mon { font-size: .65rem; font-weight: 700; text-transform: uppercase; line-height: 1; letter-spacing: .03em; }

/* ============================================================
   AVISO EN EL TOPBAR (impersonación / "actuar como admin de escuela")
   ============================================================
   Centrado ABSOLUTO respecto al topbar (`.sx-topbar` ya es position:fixed,
   sirve de contenedor) — así queda al 100% del centro real sin importar el
   ancho del logo/buscador a la izquierda ni de los íconos a la derecha, en
   vez de acomodarse al flujo flex normal (que antes lo dejaba descentrado y
   lo recortaba con ellipsis en anchos comunes). Para que nunca se solape con
   el buscador, `.sx-topbar--has-notice` (topbar.php) lo oculta mientras el
   aviso esté activo — el resto del ancho libre es de sobra para el aviso.
   Siempre visible mientras dure el modo (no se puede cerrar). El botón
   "volver" es SIEMPRE solo-ícono (ver topbar.php) para no sumar un ancho
   variable de texto. */
.sx-topbar__notice {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  max-width: min(90vw, 38rem);
  padding: 0.4rem 0.4rem 0.4rem 0.8rem;
  background: var(--sx-warning-light);
  border: 1px solid var(--sx-warning);
  border-radius: var(--radius-pill);
}
.sx-topbar__notice__icon { color: var(--sx-warning-dark); font-size: 1rem; flex-shrink: 0; }
.sx-topbar__notice__text {
  color: var(--sx-warning-dark);
  font-size: 0.8rem;
  min-width: 0;
}
.sx-topbar__notice .btn { flex-shrink: 0; }
.sx-topbar--has-notice .sx-topbar__search { display: none; }

/* Botón flotante "volver arriba" (layout_footer.php, admin/ y app/).
   Oculto por defecto; el JS lo muestra al bajar el scroll. */
.sx-scroll-top {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  width: 2.75rem;
  height: 2.75rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: var(--radius-circle);
  background: var(--sx-primary);
  color: #fff;
  font-size: 1.15rem;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(0.5rem);
  transition: var(--transition-fast);
  z-index: 1040;
}
.sx-scroll-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.sx-scroll-top:hover { background: var(--sx-primary-dark); color: #fff; }
