@charset "UTF-8";
/* =====================================================================
   hex-renamed  ·  custom.css
   ---------------------------------------------------------------------
   Tema oscuro + glassmorphism para WHMCS 8.1+  (base: Twenty-One)

   CSS puro, sin preprocesadores (RT-01). Bootstrap 4 se mantiene (RT-03).
   Este archivo se carga DESPUES de all.min.css y theme.min.css, por lo
   que sobrescribe al tema base por orden de cascada.

   NOTA DE ARQUITECTURA
   Los estilos del carrito/orderform NO viven aqui: viven en
   templates/orderforms/hex-renamed/css/orderform-custom.css.
   Motivo: common.tpl del orderform vuelve a cargar su propio all.min.css
   DESPUES de este archivo, por lo que cualquier regla de carrito escrita
   aqui seria pisada. Ver README.md > "Orden de carga del CSS".

   INDICE
     01. Tokens de diseño (:root)
     02. Base: body, tipografia, enlaces, scrollbar
     03. Superficies: glass, cards, paneles
     04. Botones
     05. Formularios y controles
     06. Navbar, topbar y cabecera
     07. Breadcrumb
     08. Sidebar y menus
     09. Tablas y listados
         09.b DataTables · 09.c Paginacion
         09.d Lista de servicios (clientarea.php?action=services)
     10. Alertas, badges y estados
     11. Homepage: isla de accesos
     12. Area de cliente
     13. Modales, dropdowns, popovers y tooltips
     14. Footer
     15. Accesibilidad (foco, area clickeable, reduced-motion)
     16. Responsive
         16.b Barrido de fondos claros · 16.c Listas en movil
     17. Utilidades del tema
     18. Movimiento (animaciones de entrada y microinteracciones)
   ===================================================================== */


/* =====================================================================
   01. TOKENS DE DISEÑO
   ---------------------------------------------------------------------
   Paleta alineada con la landing de HexServers (RF-02.2).
   Origen: src/lib/theme.js -> DEFAULT_THEME + PRIMARY_RAMP / ACCENT_RAMP.

     landing            aqui
     -----------------  ------------------------------------------
     primary  #5b8def   --accent          (azul, texto y bordes)
     hex-400  #7ca4f2   --accent-soft     (azul claro sobre cards)
     accent   #7a6ff0   --accent-2        (violeta)
     plasma-400 #9b93f4 --accent-2-soft
     background #07070a --bg
     surface  #0e0e13   --bg-elevated
     text     #e4e6ee   --text-secondary

   DOS DESVIACIONES DELIBERADAS RESPECTO A LA LANDING
   1. --accent-strong (#486fbd) no existe en la landing: alli el boton
      principal usa el degradado hex-500 -> hex-600 con texto blanco, que
      se queda en 3,2:1 y no pasa AA. Aqui se usa un azul un punto mas
      profundo, del mismo tono, que da 4,9:1 con texto blanco (RF-03.2).
   2. El cristal usa los valores del modo "sobrio" de la landing, que es
      el de fabrica: superficies planas, sin degradados ni halos.

   Contrastes verificados sobre --bg (#07070a):
     --text            #ffffff  -> 20.1:1  (AAA)
     --text-secondary  #cbd5e1  -> 13.4:1  (AAA)
     --text-tertiary   #94a3b8  ->  7.9:1  (AAA)
     --text-muted      #7c8aa0  ->  5.8:1  (AA)
     --accent          #5b8def  ->  6.2:1  (AA)
     --accent-soft     #7ca4f2  ->  8.6:1  (AAA)
     --accent-2        #7a6ff0  ->  5.1:1  (AA)
     --accent-strong   #486fbd  ->  4.9:1 con texto blanco encima (AA)
     --focus           #bfd3ff  -> 13.4:1 sobre fondo, 3.3:1 sobre accent

   Para volver al magenta original basta con cambiar los cuatro valores
   de --accent* ; nada mas en el archivo lleva colores a fuego.
   ===================================================================== */

:root {
    /* --- Controles nativos del navegador --------------------------
       EL FONDO BLANCO DE LOS DESPLEGABLES SALIA DE AQUI: DE NO ESTAR.

       Un <select> se pinta en dos partes. La caja cerrada la dibuja la
       pagina, y esa si la estilaba el tema. La lista que se despliega al
       pulsarla NO: es una ventana del sistema operativo, fuera del DOM,
       y el navegador la dibuja con el esquema de color que el documento
       declare. Sin declarar ninguno, el esquema es "light": lista blanca
       con texto gris claro encima -- casi ilegible -- en medio de un tema
       oscuro. Poner `background-color` a los <option> no lo arregla,
       porque no se esta pintando el fondo de las opciones sino el de la
       ventana que las contiene.

       `color-scheme: dark` se lo dice al navegador de una vez, y de paso
       arregla todo lo demas que dibuja el sistema y no se puede estilar:
       las barras de scroll, el relleno automatico de contraseñas, los
       calendarios de <input type="date"> y las casillas nativas.

       Va en :root para que valga en todo el tema. El carrito lo repite en
       su propia hoja, porque en la pagina del pedido este archivo puede
       no estar cargado (ver la nota de arquitectura arriba). */
    color-scheme: dark;

    /* --- Fondos -------------------------------------------------- */
    --bg:                 #07070a;   /* landing: --color-void */
    --bg-deep:            #000000;   /* listado de productos */
    --bg-elevated:        #0e0e13;   /* landing: --color-void-2 */
    --bg-card:            #12121a;   /* card de producto */
    --bg-card-hover:      #181822;

    /* --- Texto ---------------------------------------------------- */
    --text:               #ffffff;
    --text-secondary:     #cbd5e1;   /* slate-300 */
    --text-tertiary:      #94a3b8;   /* slate-400 */
    --text-muted:         #7c8aa0;   /* etiquetas pequeñas, sigue en AA */
    --text-disabled:      #64748b;   /* slate-500 (exento WCAG) */

    /* --- Acento principal: azul ----------------------------------- */
    --accent:             #5b8def;
    --accent-soft:        #7ca4f2;
    --accent-strong:      #486fbd;   /* relleno de boton, texto blanco 4.9:1 */
    --accent-hover:       #4b73c2;   /* hover del boton,  blanco 4.6:1 */
    --accent-active:      #3c5c9e;   /* pulsado,          blanco 6.5:1 */
    --accent-tint:        rgba(91, 141, 239, 0.12);
    --accent-tint-strong: rgba(91, 141, 239, 0.22);
    --accent-border:      rgba(91, 141, 239, 0.35);

    /* --- Acento secundario: violeta ------------------------------- */
    --accent-2:           #7a6ff0;
    --accent-2-soft:      #9b93f4;
    --accent-2-tint:      rgba(122, 111, 240, 0.14);

    /* --- Semanticos (siempre acompañados de icono, RF-09.4) -------- */
    --success:            #34d399;
    --success-tint:       rgba(52, 211, 153, 0.12);
    --warning:            #fbbf24;
    --warning-tint:       rgba(251, 191, 36, 0.12);
    --danger:             #f87171;
    --danger-tint:        rgba(248, 113, 113, 0.12);
    --info:               #7ca4f2;
    --info-tint:          rgba(124, 164, 242, 0.12);

    /* --- Cristal (valores del modo "sobrio" de la landing) --------- */
    --glass-bg:           rgba(255, 255, 255, 0.035);
    --glass-bg-strong:    rgba(255, 255, 255, 0.06);
    --glass-blur:         blur(16px);
    --glass-border:       1px solid rgba(255, 255, 255, 0.08);
    --glass-shadow:       0 1px 0 0 rgba(255, 255, 255, 0.04) inset,
                          0 18px 50px -28px rgba(0, 0, 0, 0.9);

    /* --- Bordes y separadores ------------------------------------- */
    --hairline:           rgba(255, 255, 255, 0.08);
    --hairline-soft:      rgba(255, 255, 255, 0.05);
    --hairline-strong:    rgba(255, 255, 255, 0.14);

    /* --- Foco (RF-03.6 / RF-09.2) ---------------------------------
       Azul muy claro, de la misma rampa que el acento. Sustituye al
       ambar anterior, que cumplia pero desentonaba en un tema azul.
       Contraste del anillo: 13.4:1 sobre el fondo y 3.3:1 sobre el
       relleno de los botones de acento, por encima del 3:1 que pide
       WCAG para indicadores no textuales. */
    --focus:              #bfd3ff;
    --focus-width:        3px;
    --focus-offset:       2px;

    /* --- Geometria (landing: rounded-xl / rounded-2xl) ------------ */
    --radius-sm:          8px;
    --radius:             12px;
    --radius-lg:          16px;
    --radius-pill:        999px;

    /* --- Area minima clickeable (RF-03.4 / RF-09) ----------------- */
    --tap-target:         44px;

    /* --- Tipografia (misma pila que la landing) ------------------- */
    --font-ui: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
               Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-display: "Space Grotesk", "Inter", ui-sans-serif, system-ui, sans-serif;
    --font-numeric: "Inter", "Segoe UI", system-ui, sans-serif;

    /* --- Transiciones --------------------------------------------- */
    --t-fast:             120ms ease;
    --t:                  180ms ease;
}


/* =====================================================================
   02. BASE
   ===================================================================== */

html {
    font-size: 16px;
    -webkit-text-size-adjust: 100%;
}

body,
body.primary-bg-color {
    background-color: var(--bg);
    /* Halos discretos, al nivel del modo "sobrio" de la landing. */
    background-image:
        radial-gradient(1100px 560px at 15% -10%, rgba(91, 141, 239, 0.10), transparent 62%),
        radial-gradient(900px 480px at 90% 2%,    rgba(122, 111, 240, 0.08), transparent 60%);
    background-attachment: fixed;
    background-repeat: no-repeat;
    color: var(--text-secondary);
    font-family: var(--font-ui);
    font-size: 0.9375rem;   /* 15px */
    line-height: 1.6;
    min-height: 100vh;
}

/* Rejilla de fondo de la landing (.backdrop-grid), muy atenuada. */
body::before {
    background-image:
        linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
    background-size: 64px 64px;
    content: "";
    height: 60vh;
    left: 0;
    -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, #000 35%, transparent 100%);
    mask-image: radial-gradient(ellipse 90% 70% at 50% 0%, #000 35%, transparent 100%);
    opacity: 0.5;
    pointer-events: none;
    position: fixed;
    right: 0;
    top: 0;
    /* z-index NEGATIVO a proposito: ver la nota de abajo. */
    z-index: -1;
}


/* El contenido va por encima de la rejilla.
   ---------------------------------------------------------------------
   OJO, AQUI HUBO UN BUG FEO. Antes esto era:

       .header, #main-body, ... { position: relative; z-index: 1; }

   con la rejilla en z-index: 0. Funcionaba para el fondo, pero ese
   `z-index: 1` convierte a #main-body en un CONTEXTO DE APILAMIENTO, y
   eso atrapa dentro a todo lo que lleve z-index, por alto que sea.

   Consecuencia: cualquier modal renderizado dentro de #main-body (el de
   "¿quitar este articulo?" del carrito, por ejemplo) quedaba por debajo
   de su propio .modal-backdrop, que Bootstrap cuelga de <body> con
   z-index 1040 y por tanto vive en el contexto raiz. El modal se veia
   -porque el backdrop es translucido- pero NO se podia pulsar nada, y la
   pantalla entera se quedaba oscurecida.

   Los modales del tema (#modalAjax, el selector de idioma) no lo sufrian
   porque footer.tpl los pinta FUERA de #main-body.

   La solucion es no crear el contexto: la rejilla se manda al fondo con
   z-index: -1 (sigue viendose, porque un hijo con z-index negativo pinta
   por encima del fondo de su ancestro) y el contenido ya no necesita
   z-index ninguno. .header conserva el suyo (1030) en la seccion 06.b,
   que es el que necesita la cabecera sticky. */
.header,
#main-body,
.master-breadcrumb,
#footer,
footer.footer { position: relative; }

/* El tema base pinta muchos bloques de blanco mediante estas clases. */
.primary-bg-color,
.secondary-bg-color,
#main-body,
#main-body .container {
    background-color: transparent;
}

/* Titulares en Space Grotesk, como la landing (.display). */
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
    color: var(--text);
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.02em;
}

h1, .h1 { font-size: 2rem; }
h2, .h2 { font-size: 1.5rem; }
h3, .h3 { font-size: 1.25rem; }
h4, .h4 { font-size: 1.0625rem; }

p { color: var(--text-secondary); }

small, .small { color: var(--text-tertiary); }

hr { border-top: 1px solid var(--hairline); }

a {
    color: var(--accent-soft);
    text-decoration: none;
    transition: color var(--t-fast);
}

a:hover,
a:focus {
    color: var(--text);
    text-decoration: underline;
}

code, kbd, pre, samp {
    font-family: "Cascadia Mono", "JetBrains Mono", Consolas, monospace;
}

code {
    background: rgba(255, 255, 255, 0.07);
    color: var(--accent-soft);
    border-radius: var(--radius-sm);
    padding: 0.15em 0.4em;
}

pre {
    background: var(--bg-elevated);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    color: var(--text-secondary);
    padding: 1rem;
}

::selection {
    background: var(--accent-tint-strong);
    color: var(--text);
}

/* Scrollbar en tono oscuro (Chromium/Edge + Firefox). */
* {
    scrollbar-color: rgba(255, 255, 255, 0.18) transparent;
    scrollbar-width: thin;
}

::-webkit-scrollbar        { width: 10px; height: 10px; }
::-webkit-scrollbar-track  { background: transparent; }
::-webkit-scrollbar-thumb  {
    background: rgba(255, 255, 255, 0.16);
    border: 2px solid transparent;
    background-clip: padding-box;
    border-radius: var(--radius-pill);
}
::-webkit-scrollbar-thumb:hover { background-color: rgba(255, 255, 255, 0.28); }


/* =====================================================================
   03. SUPERFICIES: GLASS, CARDS, PANELES
   ---------------------------------------------------------------------
   .hex-glass es la clase utilitaria; las reglas siguientes la aplican
   a los contenedores que Twenty-One ya genera (RF-02.3).
   ===================================================================== */

.hex-glass,
.card,
.panel,
.well,
#main-body .card,
#main-body .panel {
    background: var(--glass-bg);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--glass-shadow);
    color: var(--text-secondary);
}

/* Navegadores sin backdrop-filter: se compensa opacando el fondo para
   no perder contraste (RNF-02, Firefox antiguo). */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    .hex-glass,
    .card,
    .panel,
    .well,
    .header .navbar,
    .modal-content,
    .dropdown-menu {
        background: rgba(18, 18, 26, 0.96);
    }
}

.card-header,
.panel-heading {
    background: rgba(255, 255, 255, 0.04);
    border-bottom: 1px solid var(--hairline);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    color: var(--text);
    font-weight: 600;
}

.card-footer,
.panel-footer {
    background: rgba(255, 255, 255, 0.03);
    border-top: 1px solid var(--hairline);
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    color: var(--text-tertiary);
}

.card-title,
.panel-title { color: var(--text); }

.card-body,
.panel-body { color: var(--text-secondary); }

/* Twenty-One usa .card-columns en la home; ajustamos separacion. */
.card-columns .card { margin-bottom: 1.25rem; }

.list-group { background: transparent; }

.list-group-item {
    background: transparent;
    border-color: var(--hairline);
    color: var(--text-secondary);
}

.list-group-item-action:hover,
.list-group-item-action:focus {
    background: rgba(255, 255, 255, 0.06);
    color: var(--text);
}

.list-group-item.active {
    background: var(--accent-tint);
    border-color: var(--accent);
    color: var(--text);
}

.list-group-item.disabled,
.list-group-item:disabled {
    background: transparent;
    color: var(--text-disabled);
}


/* =====================================================================
   04. BOTONES
   ---------------------------------------------------------------------
   RF-03: minimalistas (sin degradados ni sombras duras), contraste AA,
   estados diferenciados y area minima de 44x44px.
   ===================================================================== */

.btn {
    background-image: none;          /* RF-03.1 sin degradados */
    border: 1px solid transparent;
    border-radius: var(--radius);
    box-shadow: none;                /* RF-03.1 sin sombras duras */
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1.25;
    min-height: var(--tap-target);   /* RF-03.4 */
    padding: 0.6875rem 1.125rem;
    text-shadow: none;
    transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}

.btn:hover { text-decoration: none; }

.btn:active { transform: translateY(1px); }

/* --- Centrado vertical de los botones que son <input> --------------
   EL BUG DEL BOTON «ACTUALIZAR» (clientarea.php?action=details)

   Ese boton no es un <button>, es
   `<input type="submit" class="btn btn-primary" value="Actualizar">`
   (clientareadetails.tpl). Y ahi esta la diferencia.

   La hoja del navegador trata los tres tipos de boton-input asi:

       input[type=submit], input[type=reset], input[type=button] {
           align-items: flex-start;      <- ARRIBA, no centrado
           text-align: center;
       }

   mientras que a <button> le pone `align-items: center`. Con la altura
   natural del texto da igual, porque la caja mide justo lo que mide la
   linea. Pero este tema le pide a `.btn` un area tactil minima de 44px
   (RF-03.4) y, en cuanto `min-height` estira la caja, el sobrante se va
   TODO abajo: el texto queda pegado al borde superior y el boton se ve
   descentrado.

   Se corrige declarando el centrado en el propio control. Los tres tipos
   van juntos porque el «Cancelar» de al lado es un `type="reset"` y
   descentrarse solo uno de los dos se notaria aun mas.

   No se toca `display`: en un input el contenido no forma un contexto
   flex al que se pueda entrar, `align-items` actua sobre la caja interna
   que ya crea el navegador. Cambiarlo a inline-flex no aporta nada y
   rompe el ancho automatico en Safari.
   ------------------------------------------------------------------- */
input.btn[type="submit"],
input.btn[type="reset"],
input.btn[type="button"],
input.btn[type="image"] {
    align-items: center;
    justify-content: center;
    text-align: center;
}

.btn.disabled,
.btn:disabled {
    background: rgba(255, 255, 255, 0.04);
    border-color: var(--hairline);
    color: var(--text-disabled);
    cursor: not-allowed;
    opacity: 1;
    transform: none;
}

/* Botones pequeños: se mantiene el area tactil aunque baje la fuente. */
.btn-sm,
.btn-group-sm > .btn {
    font-size: 0.8125rem;
    min-height: var(--tap-target);
    padding: 0.5rem 0.875rem;
}

.btn-lg,
.btn-group-lg > .btn {
    font-size: 1rem;
    min-height: 52px;
    padding: 0.875rem 1.5rem;
}

/* --- Primario: relleno de acento + texto blanco (5.9:1) ----------- */
.btn-primary,
.btn-success,
.hex-btn-primary {
    background-color: var(--accent-strong);
    border-color: var(--accent-strong);
    color: #ffffff;
}

.btn-primary:hover,
.btn-success:hover,
.hex-btn-primary:hover,
.btn-primary:focus,
.btn-success:focus,
.hex-btn-primary:focus {
    background-color: var(--accent-hover);
    border-color: var(--accent-hover);
    color: #ffffff;
}

.btn-primary:active,
.btn-primary:not(:disabled):not(.disabled):active,
.btn-success:not(:disabled):not(.disabled):active,
.hex-btn-primary:active {
    background-color: var(--accent-active);
    border-color: var(--accent-active);
    color: #ffffff;
}

/* --- Secundario / default: borde fino sobre fondo translucido ----- */
.btn-default,
.btn-secondary,
.btn-light,
.hex-btn-ghost {
    background-color: rgba(255, 255, 255, 0.05);
    border-color: var(--hairline-strong);
    color: var(--text);
}

.btn-default:hover,
.btn-secondary:hover,
.btn-light:hover,
.hex-btn-ghost:hover,
.btn-default:focus,
.btn-secondary:focus,
.btn-light:focus,
.hex-btn-ghost:focus {
    background-color: rgba(255, 255, 255, 0.11);
    border-color: rgba(255, 255, 255, 0.28);
    color: var(--text);
}

.btn-default:active,
.btn-secondary:not(:disabled):not(.disabled):active,
.hex-btn-ghost:active {
    background-color: rgba(255, 255, 255, 0.16);
}

/* --- Outline ------------------------------------------------------ */
.btn-outline-primary,
.btn-outline-secondary,
.btn-outline-light {
    background-color: transparent;
    border-color: var(--accent);
    color: var(--accent-soft);
}

.btn-outline-primary:hover,
.btn-outline-primary:focus,
.btn-outline-secondary:hover,
.btn-outline-secondary:focus,
.btn-outline-light:hover,
.btn-outline-light:focus {
    background-color: var(--accent-tint-strong);
    border-color: var(--accent);
    color: var(--text);
}

.btn-outline-primary:not(:disabled):not(.disabled):active {
    background-color: var(--accent-strong);
    border-color: var(--accent-strong);
    color: #ffffff;
}

/* --- Semanticos --------------------------------------------------- */
.btn-danger {
    background-color: #b02a37;
    border-color: #b02a37;
    color: #ffffff;
}
.btn-danger:hover,
.btn-danger:focus {
    background-color: #96222d;
    border-color: #96222d;
    color: #ffffff;
}

.btn-info {
    background-color: #1f6f8f;
    border-color: #1f6f8f;
    color: #ffffff;
}
.btn-info:hover,
.btn-info:focus {
    background-color: #195b75;
    border-color: #195b75;
    color: #ffffff;
}

.btn-warning {
    background-color: #8a5a00;
    border-color: #8a5a00;
    color: #ffffff;
}
.btn-warning:hover,
.btn-warning:focus {
    background-color: #714a00;
    border-color: #714a00;
    color: #ffffff;
}

/* --- Enlace-boton -------------------------------------------------- */
.btn-link {
    color: var(--accent-soft);
    min-height: var(--tap-target);
}
.btn-link:hover,
.btn-link:focus { color: var(--text); }

/* --- Grupos -------------------------------------------------------- */
.btn-group > .btn:not(:first-child),
.btn-group > .btn:not(:last-child) { border-radius: 0; }
.btn-group > .btn:first-child { border-radius: var(--radius) 0 0 var(--radius); }
.btn-group > .btn:last-child  { border-radius: 0 var(--radius) var(--radius) 0; }

/* Botones que solo llevan icono: se etiquetan para lectores de
   pantalla y se les garantiza el area tactil (RF-03.5 / RF-09.5). */
.btn .fa,
.btn .fas,
.btn .far,
.btn .fal,
.btn .fad,
.btn .fab { vertical-align: -0.05em; }


/* =====================================================================
   05. FORMULARIOS Y CONTROLES
   ===================================================================== */

label,
.control-label {
    color: var(--text);
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    margin-bottom: 0.375rem;
}

.form-control,
.custom-select,
select.form-control,
textarea.form-control {
    background-color: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius);
    box-shadow: none;
    color: var(--text);
    font-size: 0.9375rem;
    min-height: var(--tap-target);
    padding: 0.625rem 0.875rem;
    transition: border-color var(--t-fast), background-color var(--t-fast);
}

.form-control:hover,
.custom-select:hover { border-color: rgba(255, 255, 255, 0.28); }

.form-control:focus,
.custom-select:focus {
    background-color: rgba(255, 255, 255, 0.08);
    border-color: var(--accent);
    box-shadow: none;
    color: var(--text);
}

.form-control::placeholder { color: var(--text-tertiary); opacity: 1; }

.form-control:disabled,
.form-control[readonly] {
    background-color: rgba(255, 255, 255, 0.03);
    color: var(--text-disabled);
}

/* Opciones nativas de <select>.
   ---------------------------------------------------------------------
   Quien resuelve de verdad el desplegable en oscuro es `color-scheme: dark`
   (§ 01): la lista que se abre es una ventana del sistema, fuera del DOM,
   y ninguna regla de `option` la alcanza.

   Esto se queda como refuerzo para los navegadores que si aplican el color
   de las opciones, y se amplia a `select` a secas: la regla anterior pedia
   `.form-control` o `.custom-select`, asi que los <select> sin clase -- el
   de divisa de la barra colapsada del carrito, entre otros -- se quedaban
   fuera. */
select option,
select.form-control option,
.custom-select option {
    background-color: var(--bg-elevated);
    color: var(--text);
}

/* `color-scheme` tambien EN el control, no solo en :root.
   ---------------------------------------------------------------------
   Lo heredado de :root deberia bastar, pero se declara aqui ademas por
   dos motivos:

     - es la señal mas directa para el motor que dibuja la ventana del
       desplegable, que es la que salia blanca;
     - hay hojas de terceros (modulos, pasarelas) que meten
       `color-scheme: light` o `only light` en sus contenedores; declararlo
       en el propio control lo recupera sin tener que ir caso por caso.

   Si algun dia hace falta un control en claro a proposito -- el iframe de
   una pasarela de pago, por ejemplo -- se le pone `color-scheme: light` a
   ese elemento y gana por especificidad. */
select,
input,
textarea,
button { color-scheme: dark; }

.custom-select {
    /* Flecha propia en tono claro (la de Bootstrap es oscura). */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23b0b8c4'%3E%3Cpath d='M8 11.5 3.5 7h9z'/%3E%3C/svg%3E");
    background-position: right 0.75rem center;
    background-repeat: no-repeat;
    background-size: 14px 14px;
    padding-right: 2.25rem;
}

.input-group-text {
    background-color: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--hairline-strong);
    color: var(--text-secondary);
}

.form-text,
.help-block,
.field-help-text { color: var(--text-tertiary); }

.form-check-label,
.checkbox label,
.radio label { color: var(--text-secondary); font-weight: 400; }

/* Checkbox/radio nativos con el acento del tema. */
input[type="checkbox"],
input[type="radio"] {
    accent-color: var(--accent);
    height: 1.05rem;
    width: 1.05rem;
}

/* Validacion */
.has-error .form-control,
.form-control.is-invalid,
.is-invalid { border-color: var(--danger); }

.has-error .control-label,
.invalid-feedback,
.text-danger { color: var(--danger) !important; }

.valid-feedback,
.text-success { color: var(--success) !important; }


/* =====================================================================
   06. NAVBAR, TOPBAR Y CABECERA
   ---------------------------------------------------------------------
   RF-04. La cabecera es sticky y con efecto glass; en el listado de
   productos pasa a negro solido (ver seccion 06.d).
   ===================================================================== */

/* --- 06.a Topbar (barra de sesion) --------------------------------
   Igual que la cabecera: theme.min.css la pinta por id (#header .topbar,
   gris #404040), asi que hace falta el id para ganar la cascada. */
#header.header .topbar,
.header .topbar {
    background: rgba(255, 255, 255, 0.03);
    border-bottom: 1px solid var(--hairline-soft);
    font-size: 0.8125rem;
}

/* La fila entera centrada verticalmente. header.tpl ya no usa .d-flex ni
   .input-group aqui: la fila es .hex-topbar-row. Se conserva .d-flex en el
   selector por si alguien restaura el markup original. */
.header .topbar .hex-topbar-row,
.header .topbar .d-flex {
    align-items: center;
    display: flex;
    gap: 0.5rem;
    justify-content: space-between;
    min-height: 48px;
}

.header .topbar .hex-topbar-left,
.header .topbar .hex-topbar-right {
    align-items: center;
    display: flex;
    gap: 0.375rem;
    min-width: 0;   /* deja que el nombre largo se recorte con ellipsis */
}

.header .topbar .btn,
.header .topbar .input-group-text,
.header .topbar .btn-active-client {
    background: transparent;
    border: none;
    box-shadow: none;
    color: var(--text-tertiary);
    font-size: 0.8125rem;
    min-height: var(--tap-target);   /* RF-03.4, igual que el resto */
    padding: 0.25rem 0.625rem;
}

.header .topbar .btn:hover,
.header .topbar .btn:focus {
    color: var(--text);
    text-decoration: none;
}

/* Boton de notificaciones */
.header .topbar #accountNotifications {
    align-items: center;
    border-radius: var(--radius-sm);
    display: inline-flex;
    gap: 0.4375rem;
}

.header .topbar #accountNotifications:hover { background: rgba(255, 255, 255, 0.06); }

/* Bloque "Conectado como" ------------------------------------------
   Etiqueta + pastilla con el nombre del cliente + botones de icono.

   Los selectores empiezan por #header.header porque theme.min.css pinta
   este bloque con "header.header .topbar .active-client .btn ..." (hasta
   cinco clases) e incluso le mete un border-bottom punteado al nombre:
   con una sola clase perderiamos la cascada y volveria el subrayado. */
#header.header .topbar .hex-session-label,
.header .topbar .hex-session-label {
    color: var(--text-muted);
    flex: 0 0 auto;
    font-size: 0.8125rem;
    white-space: nowrap;
}

#header.header .topbar .hex-session-chip,
.header .topbar .hex-session-chip {
    align-items: center;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--hairline);
    border-radius: 999px;
    color: var(--text);
    display: inline-flex;
    font-size: 0.8125rem;
    font-weight: 600;
    gap: 0.375rem;
    line-height: 1.2;
    max-width: 26ch;
    min-height: 32px;
    min-width: 0;
    padding: 0.25rem 0.75rem;
    text-decoration: none;
    transition: background-color var(--t-fast), border-color var(--t-fast);
}

#header.header .topbar .hex-session-chip:hover,
#header.header .topbar .hex-session-chip:focus,
.header .topbar .hex-session-chip:hover,
.header .topbar .hex-session-chip:focus {
    background: rgba(255, 255, 255, 0.11);
    border-color: var(--hairline-strong);
    color: var(--text);
    text-decoration: none;
}

#header.header .topbar .hex-session-chip i,
.header .topbar .hex-session-chip i {
    color: var(--accent-soft);
    flex: 0 0 auto;
    font-size: 0.9375rem;
}

/* El nombre se recorta en vez de romper la fila. El border-bottom que
   theme.min.css pintaba aqui queda anulado de forma explicita. */
#header.header .topbar .hex-session-chip .hex-session-name,
.header .topbar .hex-session-chip .hex-session-name {
    border: 0;
    overflow: hidden;
    text-decoration: none;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Botones de icono (cambiar de cuenta, volver al admin) */
#header.header .topbar .hex-topbar-icon-btn,
.header .topbar .hex-topbar-icon-btn {
    align-items: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-tertiary);
    display: inline-flex;
    flex: 0 0 auto;
    font-size: 0.8125rem;
    gap: 0.375rem;
    justify-content: center;
    min-height: 32px;
    min-width: 32px;
    padding: 0.25rem 0.5rem;
    text-decoration: none;
    transition: background-color var(--t-fast), color var(--t-fast);
}

#header.header .topbar .hex-topbar-icon-btn:hover,
#header.header .topbar .hex-topbar-icon-btn:focus,
.header .topbar .hex-topbar-icon-btn:hover,
.header .topbar .hex-topbar-icon-btn:focus {
    background: rgba(255, 255, 255, 0.09);
    border-color: var(--hairline);
    color: var(--text);
    text-decoration: none;
}

#header.header .topbar .hex-return-to-admin,
.header .topbar .hex-return-to-admin { color: var(--accent-soft); }

@media (max-width: 575.98px) {
    #header.header .topbar .hex-session-chip,
    .header .topbar .hex-session-chip { max-width: 14ch; }
}

/* --- 06.b Cabecera glass (RF-04.5) --------------------------------
   El selector incluye #header porque theme.min.css pinta la cabecera
   por id: una clase suelta perderia la cascada y quedaria en blanco. */
#header.header,
.header {
    background: rgba(7, 7, 10, 0.72);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border-bottom: 1px solid var(--hairline-soft);  /* RF-04.4 */
    position: sticky;
    top: 0;
    z-index: 1030;
}

.header .navbar {
    background: transparent;
    border: none;
    padding: 0.5rem 0;
}

.header .navbar .container {
    align-items: center;
    display: flex;
}

/* Logo a la izquierda (RF-04.1) */
.navbar-brand {
    align-items: center;
    color: var(--text) !important;
    display: inline-flex;
    font-size: 1.125rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    margin-right: 1.5rem;
    min-height: var(--tap-target);   /* RF-03.4 tambien para el logo */
    padding: 0.25rem 0;
}

.navbar-brand .logo-img { max-height: 40px; width: auto; }

/* --- 06.c Menu principal ------------------------------------------ */
.main-navbar-wrapper {
    background: transparent;
    border-top: 1px solid var(--hairline-soft);
    padding: 0;
}

/* Menu centrado (RF-04.2). El TPL marca el bloque con .hex-nav-center. */
.main-navbar-wrapper .navbar-collapse { align-items: center; }

@media (min-width: 1200px) {
    .main-navbar-wrapper #nav.hex-nav-center {
        margin-left: auto !important;
        margin-right: auto !important;
    }
}

/* --- Items del menu -----------------------------------------------
   Mismo tratamiento que la navbar de la landing: pastilla de fondo al
   pasar por encima y pastilla tintada con aro para el item activo.

   Antes esto era un subrayado que aparecia de golpe en :hover y
   compartia regla con el estado activo, asi que al recorrer el menu
   parecia que el indicador de "donde estoy" iba saltando de un item a
   otro. Ahora hover y activo son dos cosas distintas: el fondo dice
   "estas encima" y el aro dice "estas aqui". */
#nav > li > a,
.navbar-nav > li > a,
.navbar-nav .nav-link {
    align-items: center;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-tertiary);
    display: inline-flex;
    font-size: 0.875rem;
    font-weight: 500;
    min-height: var(--tap-target);
    padding: 0.5rem 0.75rem !important;
    position: relative;
    transition: background-color var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}

#nav > li > a:hover,
#nav > li > a:focus,
.navbar-nav > li > a:hover,
.navbar-nav > li > a:focus {
    background: rgba(255, 255, 255, 0.06);
    color: var(--text);
    text-decoration: none;
}

#nav > li.active > a,
#nav > li > a.active {
    background: var(--accent-tint-strong);
    border-color: var(--accent-border);
    color: var(--text);
    font-weight: 600;
}

/* Separacion entre items, como el gap-1 de la landing. */
#nav > li { margin-right: 0.125rem; }

/* El caret de los dropdown no debe empujar el texto. */
#nav > li > a.dropdown-toggle::after {
    margin-left: 0.4375rem;
    opacity: 0.6;
    vertical-align: middle;
}

/* --- 06.d Acciones a la derecha (RF-04.3) ------------------------- */
.hex-nav-actions {
    align-items: center;
    display: flex;
    gap: 0.625rem;
    margin-left: auto;
}

.hex-nav-actions .btn { white-space: nowrap; }

/* Los selectores llevan .header .hex-nav-actions delante a proposito:
   theme.min.css define el color de los enlaces de la cabecera con dos
   clases, y una clase suelta no ganaria la cascada. */

/* Boton secundario (ej. Discord) */
.header .hex-nav-actions .btn.hex-btn-nav-secondary {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline-strong);
    color: var(--text);
}
.header .hex-nav-actions .btn.hex-btn-nav-secondary:hover,
.header .hex-nav-actions .btn.hex-btn-nav-secondary:focus {
    background: rgba(255, 255, 255, 0.11);
    border-color: rgba(255, 255, 255, 0.28);
    color: var(--text);
}

/* Boton primario con acento (ej. Login) */
.header .hex-nav-actions .btn.hex-btn-nav-primary {
    background: var(--accent-strong);
    border: 1px solid var(--accent-strong);
    color: #ffffff;
}
.header .hex-nav-actions .btn.hex-btn-nav-primary:hover,
.header .hex-nav-actions .btn.hex-btn-nav-primary:focus {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: #ffffff;
}

/* Menu de cuenta ("Hola, ...") -------------------------------------
   Antes colgaba de su propio <ul class="navbar-nav"> fuera de este
   grupo: heredaba el color apagado de los items del menu principal
   (--text-tertiary) y se alineaba con el menu, no con los botones, asi
   que quedaba mas bajo y translucido. Ahora es un item mas del grupo de
   acciones y se pinta como pastilla con el mismo alto que los botones. */
.hex-nav-actions .hex-nav-account {
    align-items: center;
    display: flex;
    flex-direction: row;
    list-style: none;
    margin: 0;
    padding: 0;
}

.hex-nav-actions .hex-nav-account > li { margin: 0; position: relative; }

.header .hex-nav-actions .hex-nav-account > li > a,
.header .hex-nav-actions .hex-nav-account > li > a.nav-link {
    align-items: center;
    background: transparent;
    border: 1px solid var(--hairline);
    /* Mismo radio que .btn para que case con Discord / Area del Cliente. */
    border-radius: var(--radius);
    color: var(--text-secondary);
    display: inline-flex;
    font-size: 0.875rem;
    font-weight: 500;
    gap: 0.25rem;
    line-height: 1.2;
    margin: 0;
    max-width: 22ch;
    min-height: var(--tap-target);
    overflow: hidden;
    padding: 0.5rem 0.75rem !important;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.header .hex-nav-actions .hex-nav-account > li > a:hover,
.header .hex-nav-actions .hex-nav-account > li > a:focus,
.header .hex-nav-actions .hex-nav-account > li.show > a {
    background: rgba(255, 255, 255, 0.08);
    border-color: var(--hairline-strong);
    color: var(--text);
    text-decoration: none;
}

/* El caret separado del texto y sin empujar la pastilla. */
.header .hex-nav-actions .hex-nav-account > li > a.dropdown-toggle::after {
    margin-left: 0.375rem;
    opacity: 0.6;
    vertical-align: middle;
}

/* El desplegable se ancla a la derecha de la pastilla para no salirse
   del viewport en pantallas justas. */
.hex-nav-actions .hex-nav-account .dropdown-menu {
    left: auto;
    min-width: 220px;
    right: 0;
}

@media (max-width: 1199.98px) {
    /* En movil el bloque de acciones se apila: la pastilla ocupa el ancho
       completo y el desplegable se alinea con ella. */
    .header .hex-nav-actions .hex-nav-account,
    .header .hex-nav-actions .hex-nav-account > li { width: 100%; }
    .header .hex-nav-actions .hex-nav-account > li > a {
        justify-content: center;
        max-width: none;
        width: 100%;
    }
}

/* --- Boton del carrito --------------------------------------------
   Heredaba el borde gris claro (#e5e5e5) y el radio de 3.75px del .btn
   del tema base, lo que le daba un aspecto anticuado. Se rehace como
   boton de icono cuadrado-redondeado, con el contador como pastilla
   superpuesta en la esquina. Los selectores llevan .header .toolbar
   delante para ganar a la regla base. */
.header .toolbar a.cart-btn,
.header .toolbar .cart-btn,
a.cart-btn {
    align-items: center;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius);
    box-shadow: none;
    color: var(--text-secondary);
    display: inline-flex;
    flex: 0 0 auto;
    height: var(--tap-target);
    justify-content: center;
    line-height: 1;
    max-height: var(--tap-target);   /* el .btn base añadia padding */
    max-width: var(--tap-target);
    min-height: var(--tap-target);
    min-width: var(--tap-target);
    overflow: visible;
    padding: 0 !important;
    position: relative;
    transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast);
    width: var(--tap-target);
}

/* El <li> que lo envuelve no debe estirarlo ni desplazarlo. */
.header .toolbar .nav-item {
    align-items: center;
    display: flex;
}

.header .toolbar a.cart-btn:hover,
.header .toolbar a.cart-btn:focus,
a.cart-btn:hover,
a.cart-btn:focus {
    background: rgba(255, 255, 255, 0.11);
    border-color: rgba(255, 255, 255, 0.26);
    color: var(--text);
}

.header .toolbar a.cart-btn > i,
a.cart-btn > i {
    font-size: 1.0625rem;
    line-height: 1;
    margin: 0;
}

/* El contador se superpone a la esquina superior derecha.
   background y color van con !important porque el markup de WHMCS le
   pone la clase .badge-info, y los chips de estado (seccion 10) la
   declaran con !important: sin esto el contador saldria como una
   pastilla azul translucida en vez de solida. */
.header .toolbar .cart-btn .badge,
.cart-btn .badge,
#cartItemCount {
    align-items: center;
    background: var(--accent-strong) !important;
    border: 2px solid var(--bg);
    border-radius: var(--radius-pill);
    color: #ffffff !important;
    display: inline-flex;
    font-family: var(--font-ui);
    font-size: 0.6875rem;
    font-weight: 700;
    height: 19px;
    justify-content: center;
    letter-spacing: 0;
    line-height: 1;
    min-width: 19px;
    padding: 0 0.3em;
    position: absolute;
    right: -7px;
    text-align: center;
    top: -7px;
}

/* El contador se muestra siempre, incluso en 0: el JS del carrito lo
   actualiza con jQuery('#cartItemCount').html(...) y necesita que el
   elemento exista en el DOM. Ocultarlo con {if $cartitemcount} en el
   TPL romperia la actualizacion al añadir un producto sin recargar. */

/* El botón hamburguesa del móvil, a juego con el del carrito. */
.header .toolbar .nav-item > button.nav-link {
    align-items: center;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius);
    color: var(--text-secondary);
    display: inline-flex;
    height: var(--tap-target);
    justify-content: center;
    padding: 0;
    width: var(--tap-target);
}

.header .toolbar .nav-item > button.nav-link:hover {
    background: rgba(255, 255, 255, 0.11);
    color: var(--text);
}

/* Buscador de la cabecera */
.header .search .form-control {
    background: rgba(255, 255, 255, 0.05);
    border-color: var(--hairline-strong);
}
.header .search .btn {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline-strong);
    border-right: none;
    color: var(--text-secondary);
}

/* --- 06.e RF-04.6: navbar negra solida en listado de productos ----
   La clase la aplica header.tpl sobre <body> cuando la plantilla en
   curso es la de productos del carrito. */
body.hex-page-products,
body.hex-page-products.primary-bg-color {
    background-color: var(--bg-deep);    /* RF-05.1 */
    background-image: none;
}

body.hex-page-products #header.header,
body.hex-page-products .header {
    background: #000000;                 /* RF-04.6 negro solido, sin glass */
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    border-bottom: 1px solid var(--hairline-soft);
}

body.hex-page-products .header .topbar { background: #000000; }


/* =====================================================================
   07. BREADCRUMB
   ===================================================================== */

.master-breadcrumb {
    background: transparent;
    border-bottom: 1px solid var(--hairline-soft);
    padding: 0.25rem 0;
}

.breadcrumb {
    background: transparent;
    font-size: 0.8125rem;
    margin: 0;
    padding: 0.5rem 0;
}

.breadcrumb-item,
.breadcrumb-item a { color: var(--text-muted); }
.breadcrumb-item a:hover { color: var(--accent-soft); text-decoration: none; }
.breadcrumb-item.active { color: var(--text-secondary); font-weight: 500; }

/* Separador propio: el "/" por defecto queda muy marcado. */
.breadcrumb-item + .breadcrumb-item::before {
    color: var(--text-disabled);
    content: "\203A";              /* › */
    padding: 0 0.5rem;
}


/* =====================================================================
   08. SIDEBAR Y MENUS
   ===================================================================== */

.sidebar .card,
.sidebar .panel,
.card-sidebar {
    background: var(--glass-bg);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--glass-shadow);
    margin-bottom: 1.25rem;
}

.sidebar .card-header,
.sidebar .panel-heading {
    background: rgba(255, 255, 255, 0.04);
    color: var(--text);
}

.sidebar .panel-title,
.card-sidebar .panel-title {
    font-size: 0.9375rem;
    margin: 0;
}

/* OJO: includes/sidebar.tpl emite DOS tipos de item y no se pueden
   tratar igual.

     a.list-group-item    -> item de menu. Lleva dentro
                             .sidebar-menu-item-wrapper con icono,
                             etiqueta e insignia. Se maqueta con flex.

     div.list-group-item  -> fila informativa (el panel "Informacion del
                             Ticket": Solicitante, Departamento, Estado…).
                             Aqui el contenido es texto suelto mas una
                             <span class="badge float-right">, es decir,
                             FLUJO NORMAL con un float.

   Poner `display: flex` a los dos (que es lo que se hacia antes) rompe
   el segundo: el float deja de tener efecto y cada trozo de texto pasa a
   ser un item flex sin separacion, asi que la etiqueta y el valor
   quedaban pegados ("SolicitanteRodrigo Nicolas"). */
/* LOS ITEMS DE MENU SON PASTILLAS, NO FILAS CON BORDE
   ---------------------------------------------------------------------
   Antes cada item era una fila a sangre con `border-color` en los cuatro
   lados, heredando el modelo de Bootstrap. Eso arrastraba un bug: el
   tema base pinta el item activo con

       .sidebar .list-group-item.active,
       .sidebar .list-group-item.active:hover,
       .sidebar .list-group-item.active:focus { border-color: #666; }

   y la regla propia solo redefinia `border-left-color`, asi que los otros
   tres lados se quedaban en **#666**. A eso se suma que Bootstrap le da
   `z-index: 2` al item activo y le devuelve el borde superior con
   `.list-group-item + .list-group-item.active { border-top-width: 1px }`.
   Resultado: una linea gris clara cruzando la lista por encima y por
   debajo del item seleccionado -- la raya que se veia debajo de «Activo»
   en el filtro de estado.

   Se podia parchear redefiniendo los cuatro `border-*-color`, pero el
   problema volveria con cualquier otra regla del tema base que toque
   bordes. Asi que los items pasan a no tener borde en absoluto: cada uno
   es una pastilla con su propio radio, separadas por margen, y el estado
   activo se marca con fondo tintado y una barra de acento dibujada con
   `::before`. Sin bordes no hay lineas que arreglar, y de paso es el
   patron que usan hoy las barras laterales de este tipo.

   La barra de acento en `::before` (y no en `border-left`) tiene un
   segundo motivo: al no ocupar sitio en el modelo de caja, todos los
   items comparten el mismo padding y las etiquetas quedan alineadas sin
   necesidad de reservar 3px transparentes en los que no estan activos.

   Los selectores llevan `#main-body` porque hay que ganarle a
   `.sidebar .list-group-item.active:hover`, que son cuatro clases. */
#main-body .sidebar .list-group,
#main-body .sidebar .list-group-flush { padding: 0.375rem; }

#main-body .sidebar .list-group-item {
    background: transparent;
    border: 0;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    min-height: var(--tap-target);
    /* La barra de acento se recorta contra las esquinas redondeadas. */
    overflow: hidden;
    padding: 0.5rem 0.75rem;
    position: relative;
    transition: background-color var(--t-fast), color var(--t-fast);
}

/* Items de menu: los que si son flex. */
#main-body .sidebar a.list-group-item,
#main-body .sidebar .list-group-item:has(.sidebar-menu-item-wrapper) {
    align-items: center;
    display: flex;
    margin-bottom: 2px;
}

#main-body .sidebar a.list-group-item:last-child { margin-bottom: 0; }

#main-body .sidebar a.list-group-item:hover,
#main-body .sidebar a.list-group-item:focus {
    background: rgba(255, 255, 255, 0.05);
    color: var(--text);
    text-decoration: none;
}

/* Filas informativas: etiqueta a la izquierda, valor a la derecha.
   Se usa flex con space-between porque los trozos de texto sueltos se
   convierten en items flex anonimos y el `gap` los separa, den igual las
   etiquetas que use WHMCS por dentro (que las genera en PHP). */
#main-body .sidebar div.list-group-item:not(:has(.sidebar-menu-item-wrapper)) {
    align-items: baseline;
    /* Estas NO son pastillas: son pares etiqueta/valor que se leen como
       una tabla, asi que conservan el filete de separacion y el radio a
       cero. Sin el, con los items ya sin borde, quedaban todas pegadas. */
    border-bottom: 1px solid var(--hairline-soft);
    border-radius: 0;
    column-gap: 0.75rem;
    display: flex;
    flex-wrap: wrap;
    font-size: 0.8125rem;
    justify-content: space-between;
    line-height: 1.45;
    margin-bottom: 0;
    padding-bottom: 0.625rem;
    padding-top: 0.625rem;
    row-gap: 0.125rem;
}

#main-body .sidebar div.list-group-item:not(:has(.sidebar-menu-item-wrapper)):last-child {
    border-bottom: 0;
}

/* El texto suelto es la etiqueta: se apaga para que el dato destaque. */
.sidebar div.list-group-item:not(:has(.sidebar-menu-item-wrapper)) {
    color: var(--text-tertiary);
}

/* WHMCS envuelve el valor en un <span>. Cuando existe, se lleva a la
   derecha y se resalta. Si el valor viniera como texto suelto, el
   space-between del contenedor ya lo coloca igual. */
.sidebar div.list-group-item:not(:has(.sidebar-menu-item-wrapper)) > span:not(.badge) {
    color: var(--text);
    font-weight: 600;
    min-width: 0;
    text-align: right;
    /* Sin `margin-left: auto`: el space-between del contenedor ya lo
       manda a la derecha, y el margen automatico se comia el espacio
       libre dejando la insignia fuera de la tarjeta. */
}

/* La insignia venia con .float-right, que dentro de un contenedor flex
   no hace nada. Ademas en el markup va ANTES del texto, asi que sin
   `order` se quedaba a la izquierda pisando la etiqueta. */
.sidebar div.list-group-item .badge,
.sidebar div.list-group-item .float-right {
    float: none !important;
    margin-left: 0.5rem;
    order: 99;
}

/* Sin :has() (navegadores viejos) las filas informativas se quedan en
   flujo normal, que es justo como las diseño WHMCS: el float-right sigue
   funcionando y no hay colision. Degradan bien. */

/* Item activo. Se listan tambien :hover y :focus porque el tema base los
   redefine con esas mismas pseudoclases y, sin ellas, el gris #666 le
   volvia al pasar el raton por encima. */
#main-body .sidebar .list-group-item.active,
#main-body .sidebar .list-group-item.active:hover,
#main-body .sidebar .list-group-item.active:focus {
    background: var(--accent-tint);
    border-color: transparent;
    color: var(--text);
    font-weight: 600;
}

/* Barra de acento del item activo: `::before` en vez de `border-left`,
   para que no ocupe sitio en la caja y no desplace la etiqueta. El
   `overflow: hidden` del item la recorta contra la esquina redondeada. */
#main-body .sidebar .list-group-item.active::before {
    background: var(--accent);
    bottom: 0;
    content: "";
    left: 0;
    position: absolute;
    top: 0;
    width: 3px;
}

/* Insignias de la barra lateral.
   `theme.css` las deja en `background-color:#fff; color:#666; width:28px`
   -- pastilla blanca del tema claro -- y la regla propia solo cubria las
   de los items de menu (.sidebar-menu-item-badge). Las de las filas
   informativas y las de las cabeceras seguian saliendo en blanco. */
#main-body .sidebar .list-group-item .badge,
#main-body .sidebar .card-header .badge {
    background: rgba(255, 255, 255, 0.1);
    color: var(--text-secondary);
    min-width: 28px;
    width: auto;
}

.card-minimise,
.panel-minimise { color: var(--text-tertiary); }


/* =====================================================================
   09. TABLAS Y LISTADOS
   ===================================================================== */

.table,
.table-striped > tbody > tr,
table { color: var(--text-secondary); }

.table thead th {
    background: rgba(255, 255, 255, 0.04);
    border-bottom: 1px solid var(--hairline);
    border-top: none;
    color: var(--text);
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.table thead th {
    padding: 0.75rem 1rem;
    white-space: nowrap;
}

.table td,
.table th {
    border-top: 1px solid var(--hairline-soft);
    padding: 0.8125rem 1rem;
    vertical-align: middle;
}

.table-striped tbody tr:nth-of-type(odd) { background-color: rgba(255, 255, 255, 0.025); }

.table-hover tbody tr:hover {
    background-color: rgba(255, 255, 255, 0.06);
    color: var(--text);
}

.table-bordered,
.table-bordered td,
.table-bordered th { border-color: var(--hairline); }

/* ---------------------------------------------------------------------
   09.b DataTables (listas del area de clientes)
   ---------------------------------------------------------------------
   Es la pieza que seguia viendose "vanilla": el wrapper, la cabecera de
   la tabla, la fila de "Sin Resultados", el buscador y el selector de
   entradas venian en blanco del CSS base. Se cubre todo aqui.

   Los selectores llevan #main-body delante porque las reglas del tema
   base combinan varias clases y una sola no ganaria la cascada.
   --------------------------------------------------------------------- */

#main-body .dataTables_wrapper {
    background: transparent;
    color: var(--text-secondary);
}

/* Barra superior generada por el dom '<"listtable"fit>pl' */
#main-body .dataTables_wrapper .listtable {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: space-between;
    margin-bottom: 0.875rem;
}

#main-body .dataTables_wrapper .dataTables_info,
#main-body .dataTables_wrapper .dataTables_length,
#main-body .dataTables_wrapper .dataTables_length label,
#main-body .dataTables_wrapper .dataTables_filter,
#main-body .dataTables_wrapper .dataTables_filter label {
    color: var(--text-muted);
    font-size: 0.8125rem;
    margin: 0;
}

/* Buscador y selector de entradas */
#main-body .dataTables_wrapper .dataTables_filter input,
#main-body .dataTables_wrapper .dataTables_length select {
    background-color: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius);
    box-shadow: none;
    color: var(--text);
    margin-left: 0.5rem;
    /* Mismo criterio que la paginacion (§ 09.c): 38px con raton, area
       tactil completa en pantallas tactiles. Con 44px fijos el selector
       de «Ver [10] entradas» pesaba mas que la linea de texto que lo
       acompaña. */
    min-height: 38px;
    padding: 0.375rem 0.75rem;
}

@media (pointer: coarse) {
    #main-body .dataTables_wrapper .dataTables_filter input,
    #main-body .dataTables_wrapper .dataTables_length select {
        min-height: var(--tap-target);
    }
}

#main-body .dataTables_wrapper .dataTables_filter input:focus,
#main-body .dataTables_wrapper .dataTables_length select:focus {
    background-color: rgba(255, 255, 255, 0.08);
    border-color: var(--accent);
    outline: none;
}

#main-body .dataTables_wrapper .dataTables_filter input::placeholder { color: var(--text-tertiary); }
#main-body .dataTables_wrapper .dataTables_length select option {
    background-color: var(--bg-elevated);
    color: var(--text);
}

/* La tabla en si.
   ---------------------------------------------------------------------
   theme.min.css la enmarca con `.table-list { border: 1px solid #ddd;
   border-radius: 4px }`. Sobre fondo negro ese #ddd es un marco casi
   blanco alrededor de la lista de servicios. Aqui se baja al filete mas
   tenue del sistema y el radio se iguala al de las esquinas de la
   cabecera (que ya usan --radius mas abajo), que con 4px no encajaban. */
#main-body table.dataTable,
#main-body .table-list {
    background: transparent;
    border: 1px solid var(--hairline-soft);
    border-collapse: separate;
    border-radius: var(--radius);
    border-spacing: 0;
    color: var(--text-secondary);
    width: 100%;
}

#main-body table.dataTable thead th,
#main-body table.dataTable thead td,
#main-body .table-list thead th {
    background: rgba(255, 255, 255, 0.04);
    border-bottom: 1px solid var(--hairline);
    border-top: none;
    color: var(--text);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    padding: 0.8125rem 1rem;
    text-transform: uppercase;
}

#main-body table.dataTable thead th:first-child { border-radius: var(--radius) 0 0 0; }
#main-body table.dataTable thead th:last-child  { border-radius: 0 var(--radius) 0 0; }

#main-body table.dataTable tbody td,
#main-body .table-list tbody td {
    background: transparent;
    border-top: 1px solid var(--hairline-soft);
    color: var(--text-secondary);
    padding: 0.8125rem 1rem;
    vertical-align: middle;
}

#main-body table.dataTable tbody tr { background: transparent; }

#main-body table.dataTable tbody tr:hover td {
    background: rgba(255, 255, 255, 0.045);
    color: var(--text);
}

/* Las filas son clickables (onclick en el <tr>). */
#main-body table.dataTable.table-list tbody tr { cursor: pointer; }

#main-body table.dataTable tbody td strong { color: var(--text); }

/* Fila de "Sin Resultados": era una banda blanca. */
#main-body table.dataTable tbody td.dataTables_empty,
#main-body .dataTables_wrapper .dataTables_empty {
    background: transparent;
    color: var(--text-muted);
    font-size: 0.875rem;
    padding: 2.25rem 1rem;
    text-align: center;
}

/* Flechas de ordenacion: las del base son imagenes claras. */
#main-body table.dataTable thead .sorting,
#main-body table.dataTable thead .sorting_asc,
#main-body table.dataTable thead .sorting_desc {
    background-image: none;
    cursor: pointer;
    position: relative;
}

/* HAY QUE APAGAR EL ::before DEL BASE, NO SOLO REDIBUJAR EL ::after.
   ---------------------------------------------------------------------
   DataTables no pinta UNA flecha: pinta DOS caracteres de texto, uno por
   pseudo-elemento, y los dos EN POSICION ABSOLUTA (css/all.css):

       th.sorting::before { position:absolute; right:10px; bottom:50%;
                            content:"▲"; opacity:.125 }
       th.sorting::after  { position:absolute; right:10px; top:50%;
                            content:"▼"; opacity:.125 }

   ...y le mete al <th> un `padding-right: 26px` para hacerles sitio.

   La version anterior de este bloque solo tocaba el `::after`, y ademas
   no le quitaba el `position: absolute`. Resultado: el «▲» del `::before`
   seguia vivo y la mascara del `::after` seguia clavada a 10px del borde
   derecho, encima del texto. En una cabecera de tabla ancha con esos 26px
   de reserva pasaba desapercibido; en las pastillas de la lista de
   servicios (§ 09.d), que son estrechas, las dos flechas se montaban
   sobre la ultima letra y sobresalian por arriba.

   Asi que aqui: se apaga el `::before` y el `::after` vuelve al flujo
   normal (`position: static`), que es donde el `margin-left` y el
   `vertical-align` de abajo tienen sentido.

   Se dibuja con mascara SVG y no con el glifo de Font Awesome: el glifo
   obliga a acertar el nombre de la familia ("Font Awesome 5 Pro" / "5
   Free" / "6 Pro") y cuando no coincide salen recuadros vacios, que es
   lo que se veia entre PRODUCTO/SERVICIO, LISTA DE PRECIOS, etc.
   Las variables --hex-icon-* las define hex-icons.css. */
#main-body table.dataTable thead .sorting::before,
#main-body table.dataTable thead .sorting_asc::before,
#main-body table.dataTable thead .sorting_desc::before {
    content: none;
    display: none;
}

#main-body table.dataTable thead .sorting::after,
#main-body table.dataTable thead .sorting_asc::after,
#main-body table.dataTable thead .sorting_desc::after {
    background-color: currentColor;
    bottom: auto;
    color: var(--text-disabled);
    content: "";
    display: inline-block;
    /* El base fija `font-size: .8em` y `line-height: 9px`; como la caja
       se mide en `em`, sin esto el icono sale un 20% mas pequeño de lo
       previsto y con un interlineado que descoloca la linea base. */
    font-size: inherit;
    height: 0.875em;
    line-height: 1;
    margin-left: 0.5rem;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
    opacity: 0.9;
    position: static;          /* el base: absolute + right:10px + top:50% */
    right: auto;
    top: auto;
    vertical-align: -0.15em;
    width: 0.875em;
}

/* El `padding-right: 26px` que el base reservaba para las dos flechas
   absolutas no hace falta anularlo aparte: la regla de `thead th` de mas
   arriba ya declara el `padding` completo en forma abreviada, y al llevar
   #main-body gana al selector del base aunque este tenga mas clases. */

#main-body table.dataTable thead .sorting::after {
    -webkit-mask-image: var(--hex-icon-sort);
    mask-image: var(--hex-icon-sort);
}

#main-body table.dataTable thead .sorting_asc::after {
    color: var(--accent-soft);
    -webkit-mask-image: var(--hex-icon-sort-asc);
    mask-image: var(--hex-icon-sort-asc);
}

#main-body table.dataTable thead .sorting_desc::after {
    color: var(--accent-soft);
    -webkit-mask-image: var(--hex-icon-sort-desc);
    mask-image: var(--hex-icon-sort-desc);
}

/* ---------------------------------------------------------------------
   09.c Paginacion (DataTables y Bootstrap)
   ---------------------------------------------------------------------
   Los "Anterior / Siguiente" del base son dos cajas blancas pegadas con
   borde gris. Aqui pasan a botones sueltos con el mismo lenguaje que el
   resto: fondo de cristal, borde fino y radio de 12px.

   ---------------------------------------------------------------------
   SEGUNDA PASADA: PESO VISUAL Y PAGINAS DE UNA SOLA HOJA

   Dos problemas que solo se ven cuando la lista es corta:

     1. Tres cajas grandes («Anterior», «1», «Siguiente») de 44px de alto
        con 14px de relleno lateral pesaban mas que la propia lista cuando
        esta tenia un solo servicio. El area tactil de 44px (RF-03.4) es
        innegociable EN TACTIL, pero con raton no aporta nada: se baja a
        38px y se restaura con `@media (pointer: coarse)`, que es la
        consulta correcta para esto -- pregunta por el dispositivo
        apuntador, no por el ancho de la ventana, asi que una tablet
        grande conserva el area completa y un portatil estrecho no.

     2. CON UNA SOLA PAGINA, LA PAGINACION SOBRA. DataTables la pinta
        igual: «Anterior» y «Siguiente» deshabilitados y un unico «1».
        Tres controles que no llevan a ninguna parte. Se oculta el bloque
        entero cuando los dos extremos estan deshabilitados, que es
        exactamente la definicion de "no hay mas paginas".
   --------------------------------------------------------------------- */

#main-body .dataTables_wrapper .dataTables_paginate {
    display: flex;
    gap: 0.25rem;
    justify-content: flex-end;
    margin-top: 1rem;
    padding: 0;
}

/* Una sola pagina -> no se pinta nada. En un navegador sin `:has()` la
   regla se descarta y se ve la paginacion de siempre: sobra, no rompe. */
#main-body .dataTables_wrapper .dataTables_paginate:has(.previous.disabled):has(.next.disabled) {
    display: none;
}

/* Y por lo mismo, el selector de «Ver [10] entradas»: si todo cabe en una
   pagina, cambiar cuantas se muestran no hace nada. Se mira el estado de
   la paginacion desde el wrapper porque los dos bloques son hermanos.

   Para volver a mostrarlo siempre, borra esta regla. */
#main-body .dataTables_wrapper:has(.dataTables_paginate .previous.disabled):has(.dataTables_paginate .next.disabled) .dataTables_length {
    display: none;
}

#main-body .dataTables_wrapper .dataTables_paginate .paginate_button,
#main-body .dataTables_wrapper .dataTables_paginate a {
    align-items: center;
    background: rgba(255, 255, 255, 0.05) !important;
    border: 1px solid var(--hairline) !important;
    border-radius: var(--radius-pill) !important;
    box-shadow: none !important;
    color: var(--text-secondary) !important;
    cursor: pointer;
    display: inline-flex;
    font-size: 0.8125rem;
    font-weight: 600;
    justify-content: center;
    margin: 0 !important;
    min-height: 38px;
    min-width: 38px;
    padding: 0.375rem 0.8125rem !important;
    transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}

/* En pantallas tactiles se recupera el area minima completa. */
@media (pointer: coarse) {
    #main-body .dataTables_wrapper .dataTables_paginate .paginate_button,
    #main-body .dataTables_wrapper .dataTables_paginate a {
        min-height: var(--tap-target);
        min-width: var(--tap-target);
    }
}

#main-body .dataTables_wrapper .dataTables_paginate .paginate_button:hover {
    background: rgba(255, 255, 255, 0.11) !important;
    border-color: rgba(255, 255, 255, 0.26) !important;
    color: var(--text) !important;
}

#main-body .dataTables_wrapper .dataTables_paginate .paginate_button.current {
    background: var(--accent-strong) !important;
    border-color: var(--accent-strong) !important;
    color: #ffffff !important;
}

/* Deshabilitado: WCAG exime a los controles inactivos, pero "Anterior"
   con --text-disabled se quedaba en 4.2:1 y no se leia. Con --text-muted
   sube a 5.5:1 y se sigue distinguiendo del activo por el fondo plano y
   el borde mas tenue. */
#main-body .dataTables_wrapper .dataTables_paginate .paginate_button.disabled,
#main-body .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover {
    background: transparent !important;
    border-color: var(--hairline) !important;
    color: var(--text-muted) !important;
    cursor: default;
}

/* Paginacion de Bootstrap (otras listas del area de clientes). */
.pagination {
    display: flex;
    gap: 0.375rem;
}

.pagination .page-link {
    align-items: center;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius) !important;
    color: var(--text-secondary);
    display: flex;
    font-size: 0.8125rem;
    font-weight: 600;
    justify-content: center;
    min-height: var(--tap-target);
    min-width: var(--tap-target);
}

.pagination .page-link:hover {
    background: rgba(255, 255, 255, 0.11);
    border-color: rgba(255, 255, 255, 0.26);
    color: var(--text);
}

.pagination .page-item.active .page-link {
    background: var(--accent-strong);
    border-color: var(--accent-strong);
    color: #ffffff;
}

.pagination .page-item.disabled .page-link {
    background: transparent;
    border-color: var(--hairline);
    color: var(--text-muted);
}


/* ---------------------------------------------------------------------
   09.d LISTA DE SERVICIOS  (clientarea.php?action=services)
   ---------------------------------------------------------------------
   Solo aplica a `.hex-services-table`, que es la clase que añade
   clientareaproducts.tpl. El resto de listas del area de clientes
   (facturas, tickets, dominios...) se quedan como estaban.

   POR QUE NO VALIA LA REJILLA DE CINCO COLUMNAS

   El primer intento mantuvo la cabecera de columnas y puso las filas en
   una rejilla de cinco pistas. Arreglaba el desbordamiento, pero se veia
   mal por dos motivos:

     1. LAS ETIQUETAS NO CUADRABAN CON SUS VALORES. La cabecera es una
        `<tr>` sin relleno; cada fila-tarjeta lleva `padding: 0.625rem
        0.875rem` mas 1px de borde. Es decir, los cinco rotulos salian
        desplazados ~15px a la izquierda de la columna que rotulaban. En
        una tabla plana no se nota; sobre tarjetas con borde canta.
     2. SEGUIA SIENDO UNA TABLA. Cinco columnas de texto de 13px, todas
        del mismo peso, es exactamente el aspecto "de listado de 2010"
        que se queria quitar.

   EL DISEÑO DE AHORA: TARJETA DE DOS ALTURAS

   Cada servicio es una tarjeta con jerarquia real:

     ┌────────────────────────────────────────────────┐
     │ [ssl]  Minecraft - 8GB          [Activo]  ›    │
     │        mc.ejemplo.com                          │
     │        ──────────────────────────────────      │
     │        12.000 CLP            Vence 12/09/26    │
     │        Mensual                                 │
     └────────────────────────────────────────────────┘

   Arriba lo que identifica el servicio y su estado; abajo, separados por
   un filete, los datos de facturacion, que son consulta y no navegacion.
   Se monta con `grid-template-areas`, asi que reordenar es cambiar el
   dibujo de las areas y nada mas.

   QUE NO SE PUEDE TOCAR (y por eso el markup conserva cinco celdas)

     1. `filterColumn="4"` y el `table.order(...)` de la plantilla apuntan
        a la columna por INDICE: el filtro por estado de la barra lateral
        se rompe si se fusionan o reordenan celdas.
     2. La celda del icono SSL lleva `data-element-id` / `data-type` /
        `data-domain`, que lee el JS del nucleo de WHMCS.
     3. DataTables cuenta las columnas del <thead>.

   Sigue siendo una <table> en el HTML. Solo cambia como se pinta, asi que
   DataTables ordena, filtra y pagina igual.

   Y SIGUE SIN PODER DESBORDAR: las pistas son `minmax(0, 1fr)` y `auto`,
   que se encogen. El algoritmo de tablas no lo hacia -- no admite que una
   columna baje de su ancho minimo -- y por eso la lista se salia de la
   pantalla entre 768px y 1200px, que es donde la columna de contenido es
   mas estrecha porque el sidebar se lleva un tercio.
   --------------------------------------------------------------------- */

/* La tabla deja de tener maquetacion de tabla.

   OJO CON EL SELECTOR: aqui va `table.hex-services-table` y no
   `.hex-services-table` a secas. § 09.b pinta el marco de las listas con
   `#main-body table.dataTable`, que al llevar el nombre de etiqueta gana
   por especificidad a una sola clase; sin el `table.` delante, la lista
   se quedaba con el borde y el fondo de aquella regla encima de estos. */
#main-body table.hex-services-table,
#main-body table.hex-services-table > thead,
#main-body table.hex-services-table > tbody {
    display: block;
    width: 100%;
}

#main-body table.hex-services-table {
    background: transparent;
    border: none;
    border-collapse: separate;
    border-radius: 0;
    border-spacing: 0;
}

/* Anula los anchos en linea que DataTables escribe en los <th> al
   inicializarse: los calcula con el algoritmo de tablas, que aqui ya no
   se usa. */
#main-body table.hex-services-table > thead > tr > th,
#main-body table.hex-services-table > tbody > tr > td {
    min-width: 0;
    width: auto !important;
}


/* --- La cabecera, convertida en barra de ordenacion -----------------
   En una lista de tarjetas no hay columnas que encabezar, pero los <th>
   son el UNICO control de ordenacion que da DataTables: el click va
   sobre ellos. Asi que se quedan y se pintan como pastillas.

   La flecha de orden ya la dibuja § 09.b con mascara SVG sobre
   `.sorting` / `.sorting_asc` / `.sorting_desc`, que son las clases que
   pone DataTables. Aqui solo se les da forma de pastilla.
   -------------------------------------------------------------------- */
/* `display: block` NO es decorativo: un <caption> es `display: table-caption`
   por defecto, y al ser la tabla `display: block` el navegador lo envuelve en
   una caja de tabla anonima que se ajusta al contenido en vez de ocupar el
   ancho. Con eso, «ORDENAR POR» se partia en dos lineas contra el borde
   izquierdo. Como bloque ocupa la fila entera y no se parte. */
#main-body table.hex-services-table > caption {
    caption-side: top;
    color: var(--text-muted);
    display: block;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    padding: 0 0 0.375rem;
    text-align: left;
    text-transform: uppercase;
    width: 100%;
}

#main-body table.hex-services-table > thead > tr {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    margin-bottom: 0.75rem;
}

#main-body table.hex-services-table > thead > tr > th {
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-pill);
    color: var(--text-tertiary);
    display: inline-flex;
    align-items: center;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0;
    padding: 0.3125rem 0.75rem;
    text-transform: none;
    transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast);
    white-space: nowrap;
}

#main-body table.hex-services-table > thead > tr > th:hover {
    background: rgba(255, 255, 255, 0.09);
    border-color: var(--hairline-strong);
    color: var(--text);
}

/* La flecha, dentro de una pastilla, va mas pegada al texto que en una
   cabecera de tabla. El resto de su dibujo (mascara SVG, tamaño, color)
   lo hereda de § 09.b, que es tambien donde se apaga el «▲» absoluto que
   trae DataTables por su cuenta. */
#main-body table.hex-services-table > thead > tr > th::after {
    margin-left: 0.375rem;
}

/* La pastilla por la que se esta ordenando ahora mismo. Pueden ser DOS a
   la vez: clientareaproducts.tpl pide `table.order([1,'asc'],[4,'asc'])`,
   o sea orden por producto y, a igualdad, por estado. */
#main-body table.hex-services-table > thead > tr > th.sorting_asc,
#main-body table.hex-services-table > thead > tr > th.sorting_desc {
    background: var(--accent-tint);
    border-color: var(--accent-border);
    color: var(--text);
}

/* Las esquinas redondeadas que § 09.b le pone al primer y ultimo <th>
   son para una cabecera de tabla; aqui cada uno es una pastilla. */
#main-body table.hex-services-table > thead > tr > th:first-child,
#main-body table.hex-services-table > thead > tr > th:last-child {
    border-radius: var(--radius-pill);
}

/* La columna del icono SSL no tiene titulo: no hay nada por lo que
   ordenar, asi que no se pinta pastilla.

   Se apunta con `:first-child` y NO con `:empty`. Al inicializarse,
   DataTables inyecta un `<div class="dataTables_sizing">` dentro de las
   celdas para medirlas; mientras esta ahi la celda no esta vacia y
   `:empty` no casaria, dejando una pastilla en blanco al principio de la
   barra. La primera columna es la del icono siempre -- el orden de las
   cinco columnas esta fijado por `filterColumn` (ver la nota de arriba). */
#main-body table.hex-services-table > thead > tr > th:first-child { display: none; }


/* --- La tarjeta -----------------------------------------------------
   Las areas se declaran una sola vez aqui y se redibujan en las media
   queries. Cada celda solo dice en que area vive.
   -------------------------------------------------------------------- */
#main-body table.hex-services-table > tbody > tr {
    background: var(--glass-bg);
    border: var(--glass-border);
    border-radius: var(--radius);
    column-gap: 0.875rem;
    cursor: pointer;
    display: grid;
    grid-template-areas:
        "ssl main  status"
        "ssl sep   sep"
        "ssl price due";
    grid-template-columns: auto minmax(0, 1fr) auto;
    margin-bottom: 0.5rem;
    padding: 0.875rem 1rem;
    row-gap: 0.625rem;
    transition: background-color var(--t-fast), border-color var(--t-fast);
}

/* El filete entre las dos alturas de la tarjeta.
   ---------------------------------------------------------------------
   Es un area propia de la rejilla («sep») y no un `border-top` en las
   celdas de abajo. Motivo: importe y vencimiento son DOS items de rejilla
   con `column-gap` entre ellos, asi que dos `border-top` darian dos
   trazos cortados por el hueco del medio en vez de una linea. Como area,
   la linea cruza entera y el `row-gap` le deja el mismo aire arriba y
   abajo. */
#main-body table.hex-services-table > tbody > tr::before {
    background: var(--hairline-soft);
    content: "";
    grid-area: sep;
    height: 1px;
}

#main-body table.hex-services-table > tbody > tr:hover {
    background: var(--glass-bg-strong);
    border-color: var(--hairline-strong);
}

/* Las celdas no tienen ni relleno, ni marco, ni fondo propio: la tarjeta
   es la fila, y quien reparte el aire es el `padding` + `gap` de la
   rejilla.

   OJO CON EL `table.` DE ESTOS SELECTORES. Es lo que hacia falta para
   ganarle a § 09.b, que escribe

       #main-body table.dataTable tbody td            -> (1, 1, 4)
       #main-body table.dataTable tbody tr:hover td   -> (1, 2, 4)

   El nombre de etiqueta `table` cuenta como un componente mas. Sin el,
   estas reglas se quedaban en (1,1,3) / (1,2,3) y PERDIAN: las celdas
   conservaban `padding: 0.8125rem 1rem` y, al pasar el raton, un fondo
   propio -- que es lo que se veia como rectangulos claros sueltos dentro
   de la tarjeta en lugar de iluminarse la tarjeta entera.

   `color: inherit` en el estado hover por lo mismo: aquella regla tambien
   pone `color: var(--text)`, y sin esto el ciclo de facturacion y el
   rotulo del vencimiento pasaban de gris a blanco al apuntar, perdiendo
   la jerarquia justo cuando se esta mirando la fila. */
#main-body table.hex-services-table > tbody > tr > td,
#main-body table.hex-services-table > tbody > tr:hover > td {
    background: transparent;
    border: none;
    color: inherit;
    padding: 0;
}

/* --- Celda 1: icono de estado SSL ------------------------------------
   Ocupa las dos filas de la tarjeta, alineado con el nombre.

   CUANDO NINGUN SERVICIO TIENE ICONO, LA COLUMNA DESAPARECE. En una
   tienda sin dominios eso es siempre, y un carril vacio de 22px a la
   izquierda de cada tarjeta parece un fallo. El `:has()` mira la tabla
   entera: si no hay ni una sola <img> en esa columna, se cambia el dibujo
   de areas por uno de dos columnas. En un navegador sin `:has()` la regla
   se descarta y queda el carril: es feo, no roto.
   -------------------------------------------------------------------- */
#main-body table.hex-services-table .hex-service__ssl {
    align-self: start;
    grid-area: ssl;
    line-height: 0;
    padding-top: 0.125rem;
    text-align: center;
}

#main-body table.hex-services-table .hex-service__ssl img {
    height: auto;
    max-width: 20px;
}

#main-body table.hex-services-table:not(:has(.hex-service__ssl img)) > tbody > tr {
    grid-template-areas:
        "main  status"
        "sep   sep"
        "price due";
    grid-template-columns: minmax(0, 1fr) auto;
}

#main-body table.hex-services-table:not(:has(.hex-service__ssl img)) .hex-service__ssl {
    display: none;
}

/* --- Celda 2: nombre del servicio y dominio -------------------------- */
#main-body table.hex-services-table .hex-service__main {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    grid-area: main;
    min-width: 0;
}

#main-body table.hex-services-table .hex-service__name {
    color: var(--text);
    font-size: 0.9375rem;
    font-weight: 600;
    line-height: 1.35;
    overflow-wrap: anywhere;
}

#main-body table.hex-services-table .hex-service__domain {
    align-items: center;
    align-self: flex-start;   /* que el subrayado del hover no cruce toda la fila */
    color: var(--text-tertiary);
    display: inline-flex;
    font-size: 0.8125rem;
    gap: 0.375rem;
    max-width: 100%;
    overflow-wrap: anywhere;
    text-decoration: none;
}

#main-body table.hex-services-table .hex-service__domain:hover {
    color: var(--accent-soft);
    text-decoration: underline;
}

#main-body table.hex-services-table .hex-service__domain i {
    flex: 0 0 auto;
    font-size: 0.75em;
}

/* --- Celda 5: estado + flecha ----------------------------------------
   Va arriba a la derecha, en la misma linea que el nombre: el estado es
   lo primero que se busca al abrir la lista.
   -------------------------------------------------------------------- */
#main-body table.hex-services-table .hex-service__status {
    align-items: center;
    align-self: start;
    display: flex;
    gap: 0.625rem;
    grid-area: status;
    justify-content: flex-end;
}

#main-body table.hex-services-table .hex-service__chevron {
    color: var(--text-disabled);
    flex: 0 0 auto;
    font-size: 0.875rem;
    transition: color var(--t-fast), transform var(--t-fast);
}

#main-body table.hex-services-table > tbody > tr:hover .hex-service__chevron {
    color: var(--accent-soft);
    transform: translateX(2px);
}

/* --- Celdas 3 y 4: importe y vencimiento -----------------------------
   Segunda altura de la tarjeta. El filete que la separa lo pone el
   `::before` de la fila (area «sep»), no estas celdas.
   -------------------------------------------------------------------- */
#main-body table.hex-services-table .hex-service__price,
#main-body table.hex-services-table .hex-service__due {
    display: flex;
    flex-direction: column;
    gap: 0.0625rem;
}

#main-body table.hex-services-table .hex-service__price { grid-area: price; }

#main-body table.hex-services-table .hex-service__due {
    grid-area: due;
    text-align: right;
}

#main-body table.hex-services-table .hex-service__amount {
    color: var(--text);
    font-size: 0.9375rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.25;
}

#main-body table.hex-services-table .hex-service__due-date {
    color: var(--text-secondary);
    font-size: 0.8125rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1.25;
}

#main-body table.hex-services-table .hex-service__cycle {
    color: var(--text-muted);
    font-size: 0.75rem;
}

/* Rotulo de la celda de vencimiento. La etiqueta sale de `data-label`,
   que rellena tablelist.tpl leyendo el <thead>, asi que no hay texto que
   traducir aqui. Sin el, «12/09/2026» a secas no dice de que fecha es. */
#main-body table.hex-services-table .hex-service__due::after {
    color: var(--text-muted);
    content: attr(data-label);
    font-size: 0.75rem;
    order: -1;
}

/* --- Fila de «Sin resultados» ---------------------------------------
   No es una tarjeta de datos: se pinta como caja vacia punteada.
   -------------------------------------------------------------------- */
#main-body table.hex-services-table > tbody > tr:has(> td.dataTables_empty) {
    background: transparent;
    border-style: dashed;
    cursor: default;
    display: block;
}

/* Al pasar a `display: block` el `::before` del filete deja de ser un
   item de rejilla y quedaria como una raya suelta encima del mensaje. */
#main-body table.hex-services-table > tbody > tr:has(> td.dataTables_empty)::before {
    display: none;
}

#main-body table.hex-services-table > tbody > tr > td.dataTables_empty {
    color: var(--text-muted);
    padding: 2rem 1rem;
    text-align: center;
}

/* --- Movil ----------------------------------------------------------
   Por debajo de 576px el estado no cabe al lado del nombre en un movil
   estrecho, asi que baja a su propia linea, alineado a la izquierda con
   el resto. El importe y el vencimiento pasan a una sola columna.

   PARA QUE ESTE BLOQUE MANDE, § 16.c EXCLUYE ESTA TABLA: todos sus
   selectores llevan `table.table-list:not(.hex-services-table)`. Sin esa
   exclusion no habria forma de ganarle -- § 16.c escribe
   `#main-body .dataTables_wrapper table.table-list > tbody > tr`, que es
   mas especifico Y aparece mas abajo en el archivo.
   -------------------------------------------------------------------- */
@media (max-width: 575.98px) {
    #main-body table.hex-services-table > tbody > tr {
        grid-template-areas:
            "ssl main"
            "ssl status"
            "sep sep"
            "price price"
            "due  due";
        grid-template-columns: auto minmax(0, 1fr);
        padding: 0.875rem;
        row-gap: 0.5rem;
    }

    #main-body table.hex-services-table:not(:has(.hex-service__ssl img)) > tbody > tr {
        grid-template-areas:
            "main"
            "status"
            "sep"
            "price"
            "due";
        grid-template-columns: minmax(0, 1fr);
    }

    #main-body table.hex-services-table .hex-service__status {
        justify-content: flex-start;
        margin-top: 0.125rem;
    }

    /* El chevron sobra en movil: la tarjeta entera es el objetivo tactil
       y ahi no hay puntero al que responder. */
    #main-body table.hex-services-table .hex-service__chevron { display: none; }

    /* Importe y vencimiento pasan a lineas «etiqueta -> valor», que es lo
       que mejor se lee en una columna estrecha. */
    #main-body table.hex-services-table .hex-service__price,
    #main-body table.hex-services-table .hex-service__due {
        align-items: baseline;
        flex-direction: row;
        gap: 0.5rem;
        justify-content: space-between;
        text-align: left;
    }

    #main-body table.hex-services-table .hex-service__price::before {
        color: var(--text-muted);
        content: attr(data-label);
        flex: 0 0 auto;
        font-size: 0.75rem;
    }

    /* En escritorio el rotulo va encima del valor (`order: -1`); aqui, en
       una fila, tiene que ir delante. */
    #main-body table.hex-services-table .hex-service__due::after {
        flex: 0 0 auto;
        margin-right: auto;
    }

    #main-body table.hex-services-table .hex-service__cycle { margin-left: auto; }

    /* La barra de ordenacion se puede desplazar en horizontal en lugar de
       partirse en tres lineas de pastillas. */
    #main-body table.hex-services-table > thead > tr {
        -webkit-overflow-scrolling: touch;
        flex-wrap: nowrap;
        overflow-x: auto;
        padding-bottom: 0.25rem;
    }

    #main-body table.hex-services-table > thead > tr > th { flex: 0 0 auto; }
}


/* =====================================================================
   10. ALERTAS, BADGES Y ESTADOS
   ---------------------------------------------------------------------
   RF-09.4: color + icono + texto. Los iconos se inyectan con ::before
   para que ningun mensaje dependa solo del color.
   ===================================================================== */

.alert {
    background: var(--bg-elevated);
    border: 1px solid var(--hairline);
    border-left-width: 3px;
    border-radius: var(--radius);
    color: var(--text-secondary);
    padding: 0.875rem 1rem;
}

.alert .alert-link { color: var(--text); text-decoration: underline; }

.alert-success { background: var(--success-tint); border-left-color: var(--success); color: var(--text); }
.alert-info    { background: var(--info-tint);    border-left-color: var(--info);    color: var(--text); }
.alert-warning { background: var(--warning-tint); border-left-color: var(--warning); color: var(--text); }
.alert-danger  { background: var(--danger-tint);  border-left-color: var(--danger);  color: var(--text); }

/* Icono automatico salvo que la alerta ya traiga uno en el markup.
   ---------------------------------------------------------------------
   Antes se dibujaba con el glifo de Font Awesome:

       .alert-warning::before { content: "\f071"; font-family: "Font Awesome 5 Pro" }

   Eso obliga a acertar con el nombre exacto de la familia, que cambia
   entre versiones de WHMCS (5 Pro / 5 Free / 6 Pro). Cuando no coincide
   el navegador no dibuja nada y la alerta se queda sin icono — que es lo
   que pasaba en viewticket (aviso) y en el carrito (exito).

   Ahora se usa la misma tecnica que hex-icons.css: un SVG de Lucide como
   mascara. No depende de ninguna fuente y hereda el color con
   currentColor. Las variables --hex-icon-* las define hex-icons.css. */
.alert::before {
    background-color: currentColor;
    content: "";
    display: inline-block;
    flex: 0 0 auto;
    height: 1.125em;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
    margin-right: 0.5rem;
    vertical-align: -0.2em;
    width: 1.125em;
}

.alert-success::before {
    color: var(--success);
    -webkit-mask-image: var(--hex-icon-success);
    mask-image: var(--hex-icon-success);
}
.alert-info::before {
    color: var(--info);
    -webkit-mask-image: var(--hex-icon-info);
    mask-image: var(--hex-icon-info);
}
.alert-warning::before {
    color: var(--warning);
    -webkit-mask-image: var(--hex-icon-warning);
    mask-image: var(--hex-icon-warning);
}
.alert-danger::before {
    color: var(--danger);
    -webkit-mask-image: var(--hex-icon-danger);
    mask-image: var(--hex-icon-danger);
}

/* Una alerta sin tipo (solo .alert) no tiene mascara: sin esto quedaria
   un cuadrado relleno de currentColor. */
.alert:not(.alert-success):not(.alert-info):not(.alert-warning):not(.alert-danger)::before {
    display: none;
}

/* Cuando la alerta abre con un titulo (alert.tpl con `title`), el icono
   es inline y el <h2> de bloque lo empuja a su propia linea. Flotandolo
   se queda junto al titulo. */
.alert:has(> h2)::before {
    float: left;
    margin-top: 0.125em;
}

/* Si el TPL ya inserta un <i>, evitamos el icono duplicado. */
.alert > i:first-child ~ *,
.alert:has(> i:first-child)::before { content: none; }

.badge {
    border-radius: var(--radius-pill);
    font-weight: 700;
    letter-spacing: 0.02em;
    padding: 0.35em 0.65em;
}

.badge-primary { background: var(--accent-strong); color: #ffffff; }

/* Las variantes semanticas de .badge y .label se definen junto a los
   chips de estado, justo debajo, para no repetir los mismos colores en
   dos sitios. */

/* ---------------------------------------------------------------------
   Chips de estado (servicios, facturas, tickets, dominios)
   ---------------------------------------------------------------------
   El tema base los pinta como pastillas de color saturado con texto
   blanco encima: "Pagada" sobre verde daba 2,5:1 y "Impaga" sobre rojo
   3,9:1, ambos por debajo de AA. Aqui pasan a fondo tintado y texto del
   propio color, que es como se ven el resto de estados del tema y sube
   el contraste por encima de 4,5:1 en todos los casos.

   Se listan los estados de WHMCS uno a uno en vez de usar [class*=] para
   no capturar por accidente clases ajenas de modulos de terceros.

   OJO CON LA DOBLE CLASE  (bug del panel de tickets recientes)
   Estos selectores estaban escritos como `.status.status-closed`, es
   decir, exigiendo las DOS clases. Los chips que salen de una plantilla
   del tema si las llevan (`<span class="label status status-closed">`,
   ver supportticketslist.tpl), pero los que genera WHMCS en PHP para los
   paneles del dashboard llevan solo una:

       <span class="label status-closed">Cerrado</span>

   Al no casar, se quedaban con el color de `theme.css`
   (`.status-closed { background-color: #87939f }`): una pastilla gris
   claro con texto blanco, del tema claro original, en medio del panel
   oscuro de «Tickets recientes».

   Por eso los selectores pasan a ser de UNA sola clase (`.status-closed`
   en vez de `.status.status-closed`): asi cubren las dos formas de markup.
   Es seguro hacerlo, porque son exactamente las clases a las que
   `theme.css` ya les pinta un fondo de color: cualquier elemento que case
   con ellas ya lo estaba dibujando el tema base como pastilla de estado.
   --------------------------------------------------------------------- */

.status,
.label,
span.status,
td .status {
    border-radius: var(--radius-pill);
    display: inline-block;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    padding: 0.25em 0.7em;
}

/* --- Verde: todo va bien ------------------------------------------- */
.status-active,
.status-paid,
.status-completed,
.status-delivered,
.status-answered,
.label-success,
.badge-success {
    background: var(--success-tint) !important;
    color: var(--success) !important;
}

/* --- Ambar: requiere atencion -------------------------------------- */
.status-pending,
.status-unpaid,
.status-draft,
.status-open,
.status-onhold,
.status-customer-reply,
.status-pending-transfer,
.status-pending-registration,
.label-warning,
.badge-warning {
    background: var(--warning-tint) !important;
    color: var(--warning) !important;
}

/* --- Rojo: problema o fin de vida ---------------------------------- */
.status-cancelled,
.status-terminated,
.status-suspended,
.status-overdue,
.status-expired,
.status-fraud,
.status-inprogress,
.label-danger,
.badge-danger {
    background: var(--danger-tint) !important;
    color: var(--danger) !important;
}

/* --- Neutro: informativo o cerrado --------------------------------- */
.status-closed,
.status-refunded,
.status-collections,
.status-inactive,
.status-transferred-away,
.label-default,
.badge-secondary {
    background: rgba(255, 255, 255, 0.08) !important;
    color: var(--text-secondary) !important;
}

.status-info,
.label-info,
.badge-info { background: var(--info-tint) !important; color: var(--info) !important; }

.progress { background: rgba(255, 255, 255, 0.07); border-radius: var(--radius-pill); }
.progress-bar { background-color: var(--accent-strong); }


/* =====================================================================
   11. HOMEPAGE: ISLA DE ACCESOS
   ---------------------------------------------------------------------
   RF-07. Bloque insertado al principio de homepage.tpl. Cada tarjeta es
   un <a> que envuelve todo el contenido (RF-07.4), de modo que toda la
   superficie es clickeable y accesible por teclado en un solo tab-stop.
   ===================================================================== */

.hex-access-island {
    background: var(--glass-bg);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--glass-shadow);
    margin: 1.5rem 0 2rem;
    padding: 1.5rem;
}

.hex-access-island__title {
    color: var(--text);
    font-size: 1.125rem;
    font-weight: 700;
    letter-spacing: 0.01em;
    margin: 0 0 0.25rem;
}

.hex-access-island__subtitle {
    color: var(--text-tertiary);
    font-size: 0.875rem;
    margin: 0 0 1.25rem;
}

/* Grid responsive: 4 col desktop / 3 col laptop / 2 tablet / 1 movil
   (RF-07.5, RF-08.1). */
.hex-access-grid {
    display: grid;
    gap: 0.875rem;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 576px)  { .hex-access-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* auto-fit y no `repeat(6, ...)`: el numero de accesos se edita en
   includes/access-island.tpl ($hexAccessItems), y con un numero fijo de
   columnas quitar uno dejaba un hueco al final de la fila. Asi las
   tarjetas se reparten el ancho sean cinco, seis o las que haya. */
@media (min-width: 992px)  { .hex-access-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); } }

.hex-access-card {
    align-items: center;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    color: var(--text-secondary);
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    justify-content: center;
    min-height: 116px;
    padding: 1.125rem 0.75rem;
    text-align: center;
    text-decoration: none;
    transition: background-color var(--t), border-color var(--t), transform var(--t);
}

.hex-access-card:hover,
.hex-access-card:focus-visible {
    background: rgba(255, 255, 255, 0.09);
    border-color: var(--accent);
    color: var(--text);
    text-decoration: none;
    transform: translateY(-2px);
}

.hex-access-card__icon {
    align-items: center;
    color: var(--accent-soft);
    display: flex;
    font-size: 1.5rem;
    height: 2.25rem;
    justify-content: center;
    line-height: 1;
    transition: color var(--t);
    width: 2.25rem;
}

.hex-access-card:hover .hex-access-card__icon { color: var(--text); }

.hex-access-card__label {
    color: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    line-height: 1.3;
}

.hex-access-card__badge {
    background: var(--accent-strong);
    border-radius: var(--radius-pill);
    color: #ffffff;
    font-size: 0.6875rem;
    font-weight: 700;
    padding: 0.1em 0.45em;
}


/* =====================================================================
   12. AREA DE CLIENTE
   ===================================================================== */

/* Botonera de iconos de la home de Twenty-One (.action-icon-btns). */
.action-icon-btns > div > a {
    align-items: center;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    color: var(--text-secondary);
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    justify-content: center;
    min-height: 120px;
    padding: 1.125rem 0.75rem;
    text-align: center;
    transition: background-color var(--t), border-color var(--t), transform var(--t);
}

.action-icon-btns > div > a:hover,
.action-icon-btns > div > a:focus-visible {
    background: rgba(255, 255, 255, 0.09);
    border-color: var(--accent);
    color: var(--text);
    text-decoration: none;
    transform: translateY(-2px);
}

.action-icon-btns .ico-container {
    color: var(--accent-soft);
    font-size: 1.5rem;
    margin: 0;
}

.action-icon-btns > div > a:hover .ico-container { color: var(--text); }

/* ---------------------------------------------------------------------
   12.a Tiles de estadisticas (clientareahome.tpl)
   ---------------------------------------------------------------------
   theme.min.css los pinta de #f8f8f8 con una barra de color abajo. Aqui
   pasan a ser cuatro cards planas: cifra grande en la tipografia de
   titulares, etiqueta pequeña en mayusculas y una linea de acento que
   solo se enciende al pasar por encima.

   Los selectores llevan #main-body delante a proposito: las reglas del
   tema base usan dos clases y una clase suelta no ganaria la cascada.
   --------------------------------------------------------------------- */

#main-body .tiles .row { gap: 0.75rem 0; }

#main-body .tiles .tile,
#main-body .tiles a.tile {
    align-items: flex-start;
    background: var(--glass-bg);
    border: var(--glass-border);
    border-radius: var(--radius);
    box-shadow: none;
    color: var(--text-tertiary);
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    justify-content: center;
    margin: 0 0.375rem;
    min-height: 104px;
    overflow: hidden;
    padding: 1.125rem 1.25rem;
    position: relative;
    text-decoration: none;
    transition: background-color var(--t), border-color var(--t);
}

#main-body .tiles .tile:hover,
#main-body .tiles .tile:focus-visible {
    background: var(--glass-bg-strong);
    border-color: var(--hairline-strong);
    color: var(--text-tertiary);
    text-decoration: none;
}

/* El icono pasa a marca de agua en la esquina, sin robar protagonismo. */
#main-body .tiles .tile > i {
    color: var(--text);
    font-size: 1.25rem;
    opacity: 0.16;
    position: absolute;
    right: 1rem;
    top: 1rem;
    transition: opacity var(--t), color var(--t);
}

#main-body .tiles .tile:hover > i { color: var(--accent-soft); opacity: 0.5; }

#main-body .tiles .tile .stat {
    color: var(--text);
    font-family: var(--font-display);
    font-size: 1.875rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.1;
}

#main-body .tiles .tile .title {
    color: var(--text-muted);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

/* La barra de color inferior se convierte en subrayado de acento. */
#main-body .tiles .tile .highlight {
    background: var(--accent) !important;
    bottom: 0;
    height: 2px;
    left: 0;
    opacity: 0;
    position: absolute;
    right: 0;
    transition: opacity var(--t);
}

#main-body .tiles .tile:hover .highlight { opacity: 1; }


/* ---------------------------------------------------------------------
   12.b Paneles del dashboard (.client-home-cards)
   ---------------------------------------------------------------------
   Eran los recuadros blancos del area de clientes. El tema base tiñe la
   cabecera de blanco y le pone un borde de color por card-accent-*;
   aqui la cabecera es transparente con una linea fina debajo y el color
   del acento queda como un punto discreto junto al titulo.
   --------------------------------------------------------------------- */

#main-body .client-home-cards .card,
#main-body .active-products-services .card,
#main-body .client-home-panels .card {
    background: var(--glass-bg);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--glass-shadow);
    margin-bottom: 1.25rem;
    overflow: hidden;
}

#main-body .client-home-cards .card .card-header,
#main-body .primary-content .card > .card-header,
#main-body .card > .card-header {
    background: transparent;
    border-bottom: 1px solid var(--hairline);
    border-radius: 0;
    color: var(--text);
    padding: 0.875rem 1.125rem;
}

#main-body .card > .card-header .card-title,
#main-body .card > .card-header h3 {
    color: var(--text);
    font-family: var(--font-display);
    font-size: 0.9375rem;
    font-weight: 700;
    letter-spacing: -0.01em;
}

#main-body .card > .card-header .card-title > i:first-child {
    color: var(--accent-soft);
    margin-right: 0.25rem;
}

#main-body .client-home-cards .card .card-body,
#main-body .primary-content .card > .card-body {
    color: var(--text-secondary);
    padding: 1.125rem;
}

#main-body .client-home-cards .card .card-footer,
#main-body .primary-content .card > .card-footer {
    background: transparent;
    border-top: 1px solid var(--hairline);
    color: var(--text-muted);
    font-size: 0.8125rem;
    padding: 0.625rem 1.125rem;
}

/* Una card-footer vacia no debe dejar una franja suelta. */
#main-body .card > .card-footer:empty { display: none; }

/* Los bordes de color de card-accent-* se sustituyen por el hairline. */
#main-body .card[class*="card-accent-"] {
    border-color: rgba(255, 255, 255, 0.08);
    border-top-color: rgba(255, 255, 255, 0.08);
}

/* Botones pequeños de la cabecera de panel (bg-color-*). */
#main-body .card-header .btn[class*="bg-color-"],
#main-body .card-header .btn-xs {
    align-items: center;
    background: rgba(255, 255, 255, 0.06) !important;
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius-sm);
    color: var(--text) !important;
    display: inline-flex;
    font-size: 0.75rem;
    font-weight: 600;
    gap: 0.375rem;
    min-height: var(--tap-target);   /* RF-03.4 */
    padding: 0.25rem 0.875rem;
}

/* `.hex-panel__action` va en la lista porque el markup nuevo ya no le
   cuelga la clase `bg-color-<color>` del panel: ese color venia del tema
   claro y aqui el boton de la cabecera es siempre neutro con hover de
   acento. Ver clientareahome.tpl. */
#main-body .card-header .btn[class*="bg-color-"]:hover,
#main-body .card-header .btn[class*="bg-color-"]:focus-visible,
#main-body .hex-panel__action:hover,
#main-body .hex-panel__action:focus-visible {
    background: var(--accent-strong) !important;
    border-color: var(--accent-strong);
    color: #ffffff !important;
    text-decoration: none;
}

/* Listas dentro de los paneles (anuncios, tickets recientes, accesos...).
   ---------------------------------------------------------------------
   ESTA REGLA LLEVABA `display:flex; flex-direction:column` Y ERA LA CAUSA
   DEL LISTADO DE TICKETS ROTO.

   El contenido de estos items no siempre sale de una plantilla: en los
   paneles del dashboard lo genera WHMCS en PHP como HTML de flujo normal.
   El de «Tickets recientes», por ejemplo, es tal cual:

       <span class="label status-closed pull-right">Cerrado</span>
       #VNL-141200 - Pago transferencia<br>
       <small>Ultima actualizacion: ...</small>

   Al convertir el item en contenedor flex pasaban tres cosas a la vez:
     1. el `pull-right` (y cualquier float) se ignora -- los hijos de un
        flex container no flotan --, asi que el chip dejaba de ir a la
        derecha y se colocaba ARRIBA, en su orden del DOM;
     2. con `flex-direction: column` y el `align-items: stretch` que va
        por defecto, ese chip se estiraba a TODO el ancho del panel: de
        ahi las barras grises con «Cerrado» centrado;
     3. los nodos de texto suelto y los `<br>` se convierten en items
        anonimos, que con `justify-content: center` se solapaban entre si
        cuando el panel se queda mas corto que su contenido.

   La solucion es no tocar el modo de formato: flujo en bloque, que es
   para lo que ese HTML esta escrito. El ritmo vertical se consigue con
   padding, y el area pulsable minima con `min-height` + `line-height`,
   sin necesidad de centrar con flexbox.

   Los items que SI salen de una plantilla del tema y necesitan flex lo
   piden por su cuenta (`.hex-panel__item`, § 12.e). */
#main-body .client-home-cards .card .list-group-item,
#main-body .primary-content .card .list-group-item {
    background: transparent;
    border-color: var(--hairline-soft);
    border-left: none;
    border-right: none;
    color: var(--text-secondary);
    /* flow-root y no block: crea un contexto de formato propio, asi el
       chip flotante de la derecha queda contenido dentro del item y no se
       derrama sobre el siguiente cuando el asunto del ticket es corto.
       En un navegador que no conozca el valor la declaracion se descarta
       y el item se queda con el `display:block` de Bootstrap, que es el
       comportamiento anterior: se degrada solo. */
    display: flow-root;
    min-height: var(--tap-target);   /* RF-03.4 */
    padding: 0.75rem 1.125rem;
}

/* El chip de estado vuelve a la derecha, alineado con la primera linea.
   `pull-right` es de Bootstrap 3 y no existe en el 4, asi que el float lo
   pone esta regla: WHMCS sigue emitiendo esa clase en el HTML de los
   paneles. */
#main-body .client-home-cards .card .list-group-item > .label,
#main-body .client-home-cards .card .list-group-item > .status,
#main-body .primary-content .card .list-group-item > .label,
#main-body .primary-content .card .list-group-item > .status {
    float: right;
    margin: 0 0 0.25rem 0.75rem;
    max-width: 45%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Segunda linea de los items generados por WHMCS (fecha de ultima
   respuesta, importes...). En el HTML llega como <small> detras de un
   <br>, asi que se le da su propio bloque en vez de dejarlo pegado. */
#main-body .client-home-cards .card .list-group-item > small,
#main-body .primary-content .card .list-group-item > small {
    color: var(--text-muted);
    display: block;
    font-size: 0.75rem;
    margin-top: 0.125rem;
}

#main-body .card .list-group-item-action:hover {
    background: rgba(255, 255, 255, 0.05);
    color: var(--text);
}

#main-body .card .list-group-item small { color: var(--text-muted); }

/* ---------------------------------------------------------------------
   12.c Sidebar del area de clientes
   --------------------------------------------------------------------- */

/* --- Columna lateral vacia: se colapsa -------------------------------
   POR QUE HACE FALTA

   header.tpl decide si dibuja la columna lateral preguntandole al objeto
   de PHP:

       {if !$inShoppingCart && ($primarySidebar->hasChildren() || ...)}
           <div class="col-lg-4 col-xl-3"> ... </div>

   Y ese objeto NO sabe nada de los filtros de includes/sidebar.tpl, que
   son de la capa de plantilla. Asi que al retirar «Su Informacion»,
   «Contactos» y «Accesos directos» puede quedar una columna que existe,
   ocupa un tercio del ancho y no contiene nada -- con el contenido
   principal apretado en los dos tercios restantes.

   Se resuelve aqui y no en el .tpl porque el HTML ya esta escrito cuando
   se sabe el resultado: `:not(:has(.card))` pregunta por lo unico que
   importa, que es si quedo alguna tarjeta dentro.

   No se usa `:empty`: la columna nunca esta vacia de verdad, lleva los
   dos <div class="sidebar"> y los saltos de linea de la plantilla.

   En un navegador sin `:has()` la regla se descarta y se ve la columna
   vacia: es feo, no roto.
   -------------------------------------------------------------------- */
#main-body .row > [class*="col-lg-4"]:not(:has(.card)) {
    display: none;
}

#main-body .row > [class*="col-lg-4"]:not(:has(.card)) + .primary-content {
    flex: 0 0 100%;
    max-width: 100%;
}

#main-body .sidebar .card-sidebar .card-header {
    background: transparent;
    border-bottom: 1px solid var(--hairline);
}

#main-body .sidebar .sidebar-menu-item-wrapper {
    align-items: center;
    display: flex;
    gap: 0.625rem;
    width: 100%;
}

/* Columna de icono de ancho fijo: sin esto cada glifo mide lo suyo y
   las etiquetas del menu arrancan a alturas y sangrados distintos. El
   ancho es el mismo que .fa-fw (1.25em) para que un item con icono y
   otro sin el se lean como una sola columna. */
#main-body .sidebar .sidebar-menu-item-icon-wrapper {
    align-items: center;
    color: var(--text-muted);
    display: flex;
    flex: 0 0 1.25rem;
    justify-content: center;
    line-height: 1;
    width: 1.25rem;
}

#main-body .sidebar .sidebar-menu-item-icon-wrapper > i {
    font-size: 0.9375rem;
    text-align: center;
    width: 1.25rem;
}

/* Los items sin icono se alinean con los que si lo tienen. */
#main-body .sidebar .sidebar-menu-item-wrapper > .sidebar-menu-item-label:first-child {
    padding-left: 1.875rem;   /* 1.25rem de icono + 0.625rem de gap */
}

#main-body .sidebar .list-group-item.active .sidebar-menu-item-icon-wrapper,
#main-body .sidebar .list-group-item:hover .sidebar-menu-item-icon-wrapper {
    color: var(--accent-soft);
}

#main-body .sidebar .sidebar-menu-item-label {
    flex: 1 1 auto;
    font-size: 0.875rem;
    min-width: 0;
}

#main-body .sidebar .sidebar-menu-item-badge { flex: 0 0 auto; }

#main-body .sidebar .sidebar-menu-item-badge .badge {
    background: rgba(255, 255, 255, 0.1);
    color: var(--text-secondary);
}

#main-body .sidebar .list-group-item.active .badge {
    background: var(--accent-tint-strong);
    color: var(--accent-soft);
}

/* Cuerpo de los paneles del sidebar (informacion del ticket,
   destinatarios CC, notas...).
   ---------------------------------------------------------------------
   Estos bloques no salen de una plantilla: los genera WHMCS en PHP como
   HTML suelto (`$item->getBodyHtml()`), asi que el markup varia de un
   panel a otro. Por eso las reglas van sobre el contenedor y no sobre
   clases concretas: se normaliza el ritmo vertical, se alinean los pares
   etiqueta/valor y se impide que los grupos de formulario se salgan de
   la tarjeta (el input de "Añadir correo" desbordaba por la derecha
   porque .input-group no encoge sin un min-width:0 explicito). */

#main-body .sidebar .card-sidebar .card-body {
    color: var(--text-secondary);
    font-size: 0.8125rem;
    line-height: 1.5;
    padding: 0.875rem 1rem;
}

#main-body .sidebar .card-sidebar .card-body > *:last-child { margin-bottom: 0; }

/* Pares etiqueta / valor: la etiqueta a la izquierda, el dato a la
   derecha, y si no caben en una linea el dato baja alineado a la
   izquierda en lugar de quedar colgando. */
#main-body .sidebar .card-sidebar .card-body .row {
    align-items: baseline;
    gap: 0.25rem 0.75rem;
    margin-left: 0;
    margin-right: 0;
}

/* Se conservan los canales (gutters) de Bootstrap reducidos, NO a cero:
   con `padding: 0` las dos columnas quedaban pegadas y la etiqueta se
   comia el valor. Y nada de `word-break: break-word`, que partia por la
   mitad palabras como "Responder" en los botones estrechos del panel. */
#main-body .sidebar .card-sidebar .card-body .row > [class*="col-"] {
    min-width: 0;
    overflow-wrap: break-word;   /* solo parte lo que no cabe de ninguna forma */
    padding-left: 0.375rem;
    padding-right: 0.375rem;
}

#main-body .sidebar .card-sidebar .card-body .row > [class*="col-"]:first-child { padding-left: 0; }
#main-body .sidebar .card-sidebar .card-body .row > [class*="col-"]:last-child  { padding-right: 0; }

#main-body .sidebar .card-sidebar .card-body label,
#main-body .sidebar .card-sidebar .card-body strong,
#main-body .sidebar .card-sidebar .card-body dt {
    color: var(--text-tertiary);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    margin-bottom: 0.125rem;
    text-transform: uppercase;
}

#main-body .sidebar .card-sidebar .card-body dd {
    color: var(--text);
    margin-bottom: 0.625rem;
}

/* Formularios dentro del sidebar: ancho completo y sin desbordes. */
#main-body .sidebar .card-sidebar .card-body .input-group {
    flex-wrap: nowrap;
    width: 100%;
}

#main-body .sidebar .card-sidebar .card-body .input-group > .form-control {
    min-width: 0;               /* sin esto el input no encoge y desborda */
}

#main-body .sidebar .card-sidebar .card-body .input-group > .input-group-append > .btn,
#main-body .sidebar .card-sidebar .card-body .input-group > .btn {
    flex: 0 0 auto;
    white-space: nowrap;
}

#main-body .sidebar .card-sidebar .card-body .form-control,
#main-body .sidebar .card-sidebar .card-body .btn { font-size: 0.8125rem; }

/* Botones de accion del panel (Responder / Cerrar ticket).
   ---------------------------------------------------------------------
   WHMCS los mete en dos columnas dentro del cuerpo del panel. En una
   barra lateral estrecha cada boton se queda con ~90px y la etiqueta se
   partia por la mitad ("Respond / er").

   Se apilan a ancho completo: en una columna de sidebar es lo que toca,
   y ademas el area pulsable pasa a ser comoda. */
#main-body .sidebar .card-sidebar .card-body .btn {
    align-items: center;
    display: inline-flex;
    gap: 0.375rem;
    justify-content: center;
    min-height: var(--tap-target);
    overflow-wrap: normal;
    white-space: normal;
    word-break: normal;
}

#main-body .sidebar .card-sidebar .card-body .row > [class*="col-"] > .btn,
#main-body .sidebar .card-sidebar .card-body .btn-block { width: 100%; }

/* Si los botones vienen en una fila de columnas, la fila se apila. */
#main-body .sidebar .card-sidebar .card-body .row:has(> [class*="col-"] > .btn) {
    display: grid;
    gap: 0.5rem;
    grid-template-columns: minmax(0, 1fr);
}

#main-body .sidebar .card-sidebar .card-body .row:has(> [class*="col-"] > .btn) > [class*="col-"] {
    flex: 1 1 100%;
    max-width: 100%;
    padding: 0;
}

/* Botones agrupados (.btn-group) dentro del panel: tambien apilados. */
#main-body .sidebar .card-sidebar .card-body .btn-group {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    width: 100%;
}

#main-body .sidebar .card-sidebar .card-body .btn-group > .btn {
    border-radius: var(--radius-sm) !important;
    width: 100%;
}

/* Filas tipo "valor + boton de quitar" (destinatarios CC): el icono a la
   derecha y el texto ocupando el resto, en vez de un float que dejaba el
   icono suelto en su propia linea. */
#main-body .sidebar .card-sidebar .card-body .row > [class*="col-"] > a > i,
#main-body .sidebar .card-sidebar .card-body a > i.fa-minus-circle {
    color: var(--danger);
    vertical-align: middle;
}

#main-body .sidebar .card-sidebar .card-body .row:empty { display: none; }

/* ---------------------------------------------------------------------
   12.c-bis Ficha del servicio (clientareaproductdetails)
   ---------------------------------------------------------------------
   theme.min.css pinta este bloque con:

       div.product-details div.product-icon { background-color: #efefef }
       .product-status-active               { background-color: #46A546 }
       .product-status-text                 { color: #fff }

   Es decir, un recuadro gris claro con el nombre del producto en blanco
   encima (ilegible sobre el tema oscuro) y una franja de color a todo lo
   ancho debajo. Aqui se desmonta: la pastilla del icono usa el tinte de
   acento, el nombre recupera el color del texto y el estado pasa a ser un
   chip con un punto de color, que ocupa lo que mide y no una banda.

   Los selectores llevan #main-body delante porque las reglas del tema
   base usan `div.product-details div.product-icon` (0,2,2).
   --------------------------------------------------------------------- */

#main-body .hex-service-hero {
    align-items: center;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-lg);
    display: flex;
    gap: 1rem;
    padding: 1.125rem;
}

/* Anula el color de fondo que theme.min.css asigna por estado: el estado
   ya se comunica con el chip, no tiñendo la tarjeta entera. */
#main-body .hex-service-hero.product-status-pending,
#main-body .hex-service-hero.product-status-active,
#main-body .hex-service-hero.product-status-suspended,
#main-body .hex-service-hero.product-status-terminated,
#main-body .hex-service-hero.product-status-cancelled,
#main-body .hex-service-hero.product-status-fraud {
    background-color: rgba(255, 255, 255, 0.03);
}

#main-body .hex-service-hero .hex-service-icon {
    align-items: center;
    background: var(--accent-tint);
    border: 1px solid var(--accent-border);
    border-radius: var(--radius);
    color: var(--accent-soft);
    display: flex;
    flex: 0 0 auto;
    font-size: 1.5rem;
    height: 64px;
    justify-content: center;
    width: 64px;
}

#main-body .hex-service-hero .hex-service-titles { min-width: 0; }

#main-body .hex-service-hero .hex-service-name {
    color: var(--text);
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin: 0;
    overflow-wrap: anywhere;
}

#main-body .hex-service-hero .hex-service-group {
    color: var(--text-tertiary);
    font-size: 0.8125rem;
    margin: 0.125rem 0 0.5rem;
}

/* Chip de estado. El color lo hereda del contenedor
   .product-status-<estado> mediante --hex-status. */
#main-body .hex-service-hero .hex-service-status.product-status-text {
    align-items: center;
    background: color-mix(in srgb, var(--hex-status, var(--text-tertiary)) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--hex-status, var(--text-tertiary)) 40%, transparent);
    border-radius: var(--radius-pill);
    color: var(--hex-status, var(--text-secondary));
    display: inline-flex;
    font-size: 0.75rem;
    font-weight: 700;
    gap: 0.4375rem;
    letter-spacing: 0.04em;
    padding: 0.25rem 0.625rem;
    text-transform: uppercase;
}

#main-body .hex-service-hero .hex-service-status-dot {
    background: var(--hex-status, var(--text-tertiary));
    border-radius: 50%;
    flex: 0 0 auto;
    height: 7px;
    width: 7px;
}

#main-body .hex-service-hero.product-status-active     { --hex-status: var(--success); }
#main-body .hex-service-hero.product-status-pending    { --hex-status: var(--warning); }
#main-body .hex-service-hero.product-status-suspended  { --hex-status: var(--info); }
#main-body .hex-service-hero.product-status-terminated,
#main-body .hex-service-hero.product-status-cancelled  { --hex-status: var(--text-tertiary); }
#main-body .hex-service-hero.product-status-fraud      { --hex-status: var(--danger); }

/* color-mix no esta en navegadores antiguos; ahi el chip se queda con el
   fondo de respaldo y sigue siendo legible gracias al punto de color. */
@supports not (background: color-mix(in srgb, red 10%, transparent)) {
    #main-body .hex-service-hero .hex-service-status.product-status-text {
        background: rgba(255, 255, 255, 0.06);
        border-color: var(--hairline-strong);
    }
}

/* --- Datos de facturacion ------------------------------------------ */
#main-body .hex-service-facts {
    display: grid;
    gap: 0.75rem 1.25rem;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    margin: 0;
}

#main-body .hex-service-facts .hex-service-fact { min-width: 0; }
#main-body .hex-service-facts .hex-service-fact--wide { grid-column: 1 / -1; }

#main-body .hex-service-facts dt {
    color: var(--text-tertiary);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    margin: 0 0 0.125rem;
    text-transform: uppercase;
}

#main-body .hex-service-facts dd {
    color: var(--text);
    font-size: 0.9375rem;
    font-weight: 600;
    margin: 0;
    overflow-wrap: anywhere;
}

/* --- Panel de pestañas del servicio ---------------------------------
   theme.min.css le pone `background-color:#fff` y un borde #ddd, y la
   plantilla base ademas le colgaba la utilidad `bg-white` de Bootstrap
   (que es !important y no se puede pisar desde CSS). La utilidad se
   quito del .tpl; el fondo lo pone esta regla. */
#main-body div.product-details-tab-container,
#main-body .product-details-tab-container {
    background-color: rgba(255, 255, 255, 0.02);
    /* El borde del tema base es `1px solid #ddd`: sobre fondo negro es un
       marco casi blanco que se come el texto de dentro. Se baja al
       filete mas tenue del sistema (5 % de blanco) y se apoya en un
       fondo levemente elevado para marcar el panel sin el marco. */
    border: 1px solid var(--hairline-soft);
    border-radius: 0 0 var(--radius) var(--radius);
    border-top: 0;
    color: var(--text-secondary);
    padding: 1.25rem;
}

#main-body .product-details-tab-container strong { color: var(--text); }

/* --- Botonera del servicio ------------------------------------------ */
#main-body .product-actions-wrapper .btn-block {
    justify-content: center;
    min-height: var(--tap-target);
}

@media (max-width: 575.98px) {
    #main-body .hex-service-hero {
        align-items: flex-start;
        flex-direction: column;
    }
    #main-body .hex-service-facts { grid-template-columns: minmax(0, 1fr); }
}

/* ---------------------------------------------------------------------
   12.d Contenedores de tabla del area de clientes
   --------------------------------------------------------------------- */

#main-body .table-container,
#main-body .tab-content,
#main-body .panel-body,
#main-body .well {
    background: transparent;
    color: var(--text-secondary);
}

#main-body .card > .table-container > .table { margin-bottom: 0; }

#main-body .card > .table-container > .table > tbody > tr:last-child > td {
    border-bottom: none;
}

.client-alerts li a {
    color: var(--text-secondary);
    display: flex;
    gap: 0.5rem;
    min-height: var(--tap-target);
    padding: 0.5rem 0.75rem;
}
.client-alerts li a:hover { background: rgba(255, 255, 255, 0.06); color: var(--text); }

/* Nav de pestañas del area de cliente */
.nav-tabs {
    border-bottom: 1px solid var(--hairline);
}

.nav-tabs .nav-link {
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    color: var(--text-tertiary);
    font-weight: 600;
    min-height: var(--tap-target);
}

.nav-tabs .nav-link:hover { border-bottom-color: var(--hairline-strong); color: var(--text); }

.nav-tabs .nav-link.active {
    background: transparent;
    border-bottom-color: var(--accent);   /* subrayado de acento */
    color: var(--text);
}


/* =====================================================================
   12.e SISTEMA DE TICKETS
   ---------------------------------------------------------------------
   Listado, hilo de conversacion y formulario de respuesta. El tema base
   los deja como tablas y bloques planos con bordes grises; aqui el hilo
   pasa a leerse como una conversacion, con las respuestas del equipo
   marcadas por un filete de acento.
   ===================================================================== */

/* --- Listado de tickets -------------------------------------------- */

#main-body #tableTicketsList .ticket-number {
    color: var(--text-muted);
    display: inline-block;
    font-size: 0.75rem;
    font-weight: 600;
    margin-right: 0.5rem;
    min-width: 3.5rem;
}

#main-body #tableTicketsList .ticket-subject {
    color: var(--text-secondary);
    font-weight: 500;
}

/* Sin leer: el tema base solo lo pone en negrita. Se le añade un punto
   de acento para que se distinga de un vistazo. */
#main-body #tableTicketsList .ticket-subject.unread {
    color: var(--text);
    font-weight: 700;
    position: relative;
}

#main-body #tableTicketsList .ticket-subject.unread::before {
    background: var(--accent);
    border-radius: 50%;
    content: "";
    display: inline-block;
    height: 6px;
    margin-right: 0.4375rem;
    vertical-align: middle;
    width: 6px;
}

/* El enlace ocupa toda la celda con margen negativo + padding, para que
   el area pulsable sea la fila entera y no solo la altura del texto. */
#main-body #tableTicketsList a.border-left {
    align-items: center;
    border-left: none !important;   /* el base metia un borde gris suelto */
    color: inherit;
    display: flex;
    flex-wrap: wrap;
    margin: -0.8125rem -1rem;
    min-height: var(--tap-target);
    padding: 0.8125rem 1rem;
    text-decoration: none;
}

#main-body #tableTicketsList a.border-left:hover .ticket-subject { color: var(--accent-soft); }

/* Estado con color propio del departamento (style inline del TPL). */
#main-body .status-custom {
    border-radius: var(--radius-pill);
    color: #ffffff;
    font-size: 0.75rem;
    font-weight: 700;
    padding: 0.25em 0.7em;
}

/* --- Cabecera del ticket ------------------------------------------- */

#main-body .view-ticket > .card-body:first-child {
    border-bottom: 1px solid var(--hairline);
}

#main-body .view-ticket .card-title {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: space-between;
    margin: 0;
}

#main-body .view-ticket .ticket-actions {
    display: flex;
    float: none !important;
    gap: 0.5rem;
    margin: 0 !important;
}

#main-body .view-ticket .ticket-actions .btn {
    font-size: 0.8125rem;
    min-height: var(--tap-target);
}

/* --- Hilo de la conversacion --------------------------------------- */

#main-body .view-ticket .ticket-reply {
    background: var(--bg-card);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    overflow: hidden;
}

/* Respuestas del equipo: filete de acento a la izquierda. */
#main-body .view-ticket .ticket-reply.staff {
    background: rgba(91, 141, 239, 0.05);
    border-color: var(--accent-border);
    border-left: 3px solid var(--accent);
}

#main-body .view-ticket .posted-by {
    align-items: center;
    background: rgba(255, 255, 255, 0.03);
    border-bottom: 1px solid var(--hairline-soft);
    color: var(--text-muted);
    display: flex;
    flex-wrap: wrap;
    font-size: 0.8125rem;
    gap: 0.5rem;
    padding: 0.75rem 1rem;
}

#main-body .view-ticket .posted-by-name {
    color: var(--text);
    font-weight: 600;
}

#main-body .view-ticket .posted-on { color: var(--text-muted); }

#main-body .view-ticket .requestor-badge {
    background: rgba(255, 255, 255, 0.08);
    border-radius: var(--radius-pill);
    color: var(--text-secondary);
    float: none !important;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    margin-left: auto;
    padding: 0.25em 0.7em;
    text-transform: uppercase;
}

#main-body .view-ticket .ticket-reply.staff .requestor-badge {
    background: var(--accent-tint-strong);
    color: var(--accent-soft);
}

#main-body .view-ticket .message {
    color: var(--text-secondary);
    line-height: 1.65;
    padding: 1rem !important;
}

#main-body .view-ticket .message hr { border-top-color: var(--hairline); }

#main-body .view-ticket .message img { border-radius: var(--radius-sm); max-width: 100%; }

#main-body .view-ticket .message pre,
#main-body .view-ticket .message code {
    background: rgba(0, 0, 0, 0.35);
    border-radius: var(--radius-sm);
}

#main-body .view-ticket .message blockquote {
    border-left: 3px solid var(--hairline-strong);
    color: var(--text-tertiary);
    margin: 0.75rem 0;
    padding-left: 0.875rem;
}

/* --- Adjuntos ------------------------------------------------------- */

#main-body .view-ticket .attachments {
    border-top: 1px solid var(--hairline-soft);
    color: var(--text-tertiary);
    font-size: 0.8125rem;
    padding: 0.875rem 1rem !important;
}

#main-body .view-ticket .attachments strong { color: var(--text-secondary); }

#main-body .attachment-list {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    list-style: none;
    margin: 0.625rem 0 0;
    padding: 0;
}

#main-body .attachment-list li { margin: 0; }

#main-body .attachment-list a,
#main-body .attachment-list > li > span {
    align-items: center;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    display: inline-flex;
    gap: 0.5rem;
    min-height: var(--tap-target);
    padding: 0.4375rem 0.75rem;
    text-decoration: none;
    transition: background-color var(--t-fast), border-color var(--t-fast);
}

#main-body .attachment-list a:hover {
    background: rgba(255, 255, 255, 0.1);
    border-color: var(--hairline-strong);
    color: var(--text);
}

#main-body .attachment-list figure {
    color: var(--accent-soft);
    margin: 0;
}

#main-body .attachment-list .caption {
    font-size: 0.8125rem;
    max-width: 18ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- Valoracion de la respuesta ------------------------------------- */

#main-body .view-ticket .rating {
    align-items: center;
    display: flex;
    gap: 0.1875rem;
}

#main-body .view-ticket .rating .star {
    color: var(--text-disabled);
    cursor: pointer;
    font-size: 1rem;
    transition: color var(--t-fast);
}

/* Estrella rellena por mascara. Con el glifo de Font Awesome, si el
   nombre de la familia no coincide, la valoracion se quedaba en blanco. */
#main-body .view-ticket .rating .star::before {
    background-color: currentColor;
    content: "";
    display: inline-block;
    height: 1em;
    -webkit-mask-image: var(--hex-icon-star-filled);
    mask-image: var(--hex-icon-star-filled);
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-size: contain;
    mask-size: contain;
    vertical-align: -0.135em;
    width: 1em;
}

#main-body .view-ticket .rating .star.active,
#main-body .view-ticket .rating .star:hover { color: var(--warning); }

#main-body .view-ticket .rated {
    color: var(--text-muted);
    font-size: 0.75rem;
    margin-left: 0.5rem;
}

/* --- Editor Markdown (respuesta de ticket, nuevo ticket) -------------
   OJO CON LOS NOMBRES DE CLASE
   WHMCS no usa EasyMDE/SimpleMDE aqui, sino **bootstrap-markdown**
   (`element.markdown({...})` en scripts.js). Eso significa que NO existen
   .CodeMirror ni .editor-toolbar: el editor real es

       div.md-editor
         > div.btn-toolbar          (barra de botones)
         > textarea.markdown-editor (el campo)
         > div.md-preview           (la vista previa)
         > div.markdown-editor-status

   Los estilos anteriores apuntaban a las clases de EasyMDE, por eso el
   recuadro de respuesta seguia saliendo blanco.

   Ademas theme.min.css pinta el textarea, la vista previa y la barra con
   `background-color: #fff !important`, asi que hace falta !important
   para ganarle. */

#main-body .md-editor {
    background: transparent;
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius);
    overflow: hidden;              /* que los hijos respeten el radio */
}

#main-body .md-editor.active {
    border-color: var(--accent-border);
    box-shadow: 0 0 0 3px var(--accent-tint);
}

#main-body .md-editor > .btn-toolbar,
#main-body .md-editor > .md-header {
    background-color: rgba(255, 255, 255, 0.04) !important;
    border-bottom: 1px solid var(--hairline);
    margin: 0;
    padding: 0.375rem 0.5rem;
}

#main-body .md-editor > textarea.markdown-editor,
#main-body .md-editor > textarea,
#main-body .md-editor > .md-preview {
    background-color: rgba(255, 255, 255, 0.03) !important;
    border: none !important;
    border-radius: 0;
    box-shadow: none;
    color: var(--text) !important;
    font-family: var(--font-ui);
    font-size: 0.9375rem;
    line-height: 1.6;
    padding: 0.875rem 1rem !important;
    resize: vertical;
}

#main-body .md-editor > textarea:focus {
    background-color: rgba(255, 255, 255, 0.05) !important;
    outline: none;
}

#main-body .md-editor > textarea::placeholder { color: var(--text-muted); }

/* Botones de la barra de herramientas. bootstrap-markdown los pinta como
   .btn-default de Bootstrap 3, que aqui quedaban en blanco. */
#main-body .md-editor .btn-toolbar .btn,
#main-body .md-editor .md-header .btn {
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    box-shadow: none;
    color: var(--text-tertiary);
    min-height: 32px;
    padding: 0.25rem 0.5rem;
}

#main-body .md-editor .btn-toolbar .btn:hover,
#main-body .md-editor .btn-toolbar .btn:focus,
#main-body .md-editor .btn-toolbar .btn.active,
#main-body .md-editor .md-header .btn:hover {
    background: rgba(255, 255, 255, 0.08);
    border-color: var(--hairline);
    color: var(--text);
}

#main-body .md-editor .btn-toolbar .btn-group { margin-right: 0.375rem; }

/* Pie con el contador de lineas/palabras y el aviso de autoguardado. */
#main-body .md-editor > .md-footer,
#main-body .markdown-editor-status {
    background-color: rgba(255, 255, 255, 0.04) !important;
    border-top: 1px solid var(--hairline);
    color: var(--text-muted);
    font-size: 0.75rem;
    padding: 0.375rem 0.75rem;
}

/* La vista previa renderiza HTML: hereda la tipografia del tema. */
#main-body .md-editor > .md-preview,
#main-body .markdown-content { color: var(--text-secondary); }

#main-body .md-preview h1,
#main-body .md-preview h2,
#main-body .md-preview h3,
#main-body .md-preview h4,
#main-body .markdown-content h1,
#main-body .markdown-content h2,
#main-body .markdown-content h3,
#main-body .markdown-content h4 { color: var(--text); }

#main-body .md-preview pre,
#main-body .md-preview code,
#main-body .markdown-content pre,
#main-body .markdown-content code {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-sm);
    color: var(--accent-soft);
}

#main-body .md-preview blockquote,
#main-body .markdown-content blockquote {
    border-left: 3px solid var(--hairline-strong);
    color: var(--text-tertiary);
}

/* Modo pantalla completa: el plugin lo fuerza a blanco con !important. */
#main-body .md-editor.md-fullscreen-mode,
#main-body .md-editor.md-fullscreen-mode .md-input,
#main-body .md-editor.md-fullscreen-mode .md-preview {
    background: var(--bg) !important;
    color: var(--text) !important;
}

/* Selector de archivo del adjunto */
#main-body .custom-file,
#main-body .custom-file-input,
#main-body .custom-file-label {
    height: var(--tap-target);
}

#main-body .custom-file-label {
    align-items: center;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius) 0 0 var(--radius);
    color: var(--text-tertiary);
    display: flex;
    font-size: 0.875rem;
    padding: 0.5rem 0.875rem;
}

#main-body .custom-file-label::after {
    background: rgba(255, 255, 255, 0.08);
    border-left: 1px solid var(--hairline);
    color: var(--text-secondary);
    height: calc(var(--tap-target) - 2px);
    line-height: 1.9;
}

#main-body .attachment-group .input-group-append .btn {
    border-radius: 0 var(--radius) var(--radius) 0;
    min-height: var(--tap-target);
}


/* ---------------------------------------------------------------------
   12.e Dashboard del area de clientes  (remake)
   ---------------------------------------------------------------------
   Estilos de las tres piezas nuevas de clientareahome.tpl:

       .hex-dash-hero     -> includes/dashboard-hero.tpl
       .hex-metrics       -> includes/dashboard-metrics.tpl
       .hex-quicklinks    -> includes/dashboard-metrics.tpl
       .hex-panel*        -> clientareahome.tpl

   El bloque 12.a (`.tiles`) se conserva pero YA NO SE USA en el
   dashboard: lo sustituye `.hex-metrics`. Se deja porque es el estilo que
   recuperaria el tema si alguien revierte clientareahome.tpl a la version
   de Twenty-One.

   Superficies planas, sin degradados ni halos, igual que el resto del
   tema (ver la nota de las dos desviaciones en § 01). Lo que hace que
   esto no se parezca a Twenty-One no es el color: es la jerarquia
   tipografica, el aire entre bloques y que el acento aparezca solo en la
   accion principal y en los detalles pequeños.
   --------------------------------------------------------------------- */

/* --- Cabecera: saludo, estado y CTA -------------------------------- */
#main-body .hex-dash-hero {
    align-items: flex-end;
    background: var(--glass-bg);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--radius-lg);
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem 1.5rem;
    justify-content: space-between;
    margin-bottom: 1.25rem;
    padding: 1.625rem 1.5rem;
}

#main-body .hex-dash-hero__text { min-width: 0; }

#main-body .hex-dash-hero__eyebrow {
    color: var(--accent-soft);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    margin: 0 0 0.375rem;
    text-transform: uppercase;
}

#main-body .hex-dash-hero__title {
    color: var(--text);
    font-family: var(--font-display);
    /* clamp en vez de una media query: el titulo es la unica pieza del
       dashboard cuyo tamaño escala de verdad con el ancho. */
    font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.125rem);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.15;
    margin: 0;
}

#main-body .hex-dash-hero__summary {
    color: var(--text-tertiary);
    font-size: 0.9375rem;
    margin: 0.5rem 0 0;
    max-width: 52ch;
}

#main-body .hex-dash-hero__summary strong {
    color: var(--text);
    font-weight: 700;
}

#main-body .hex-dash-hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.625rem;
}

#main-body .hex-dash-hero__cta {
    align-items: center;
    border-radius: var(--radius);
    display: inline-flex;
    font-size: 0.875rem;
    font-weight: 600;
    gap: 0.5rem;
    min-height: var(--tap-target);   /* RF-03.4 */
    padding: 0.5rem 1.125rem;
    text-decoration: none;
    transition: background-color var(--t), border-color var(--t), color var(--t);
    white-space: nowrap;
}

#main-body .hex-dash-hero__cta--primary {
    background: var(--accent-strong);   /* blanco encima: 4,9:1 */
    border: 1px solid var(--accent-strong);
    color: #ffffff;
}

#main-body .hex-dash-hero__cta--primary:hover,
#main-body .hex-dash-hero__cta--primary:focus-visible {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
    color: #ffffff;
    text-decoration: none;
}

#main-body .hex-dash-hero__cta--ghost {
    background: transparent;
    border: 1px solid var(--hairline-strong);
    color: var(--text-secondary);
}

#main-body .hex-dash-hero__cta--ghost:hover,
#main-body .hex-dash-hero__cta--ghost:focus-visible {
    background: rgba(255, 255, 255, 0.06);
    border-color: var(--accent-border);
    color: var(--text);
    text-decoration: none;
}

/* HTML que inyectan los modulos de addon entre las metricas y los
   paneles. No se le da estilo -- es HTML ajeno --, solo separacion, que
   antes no tenia ninguna y quedaba pegado al bloque de arriba. */
#main-body .hex-addon-slot { margin-bottom: 1.25rem; }

/* --- Rejilla de metricas -------------------------------------------
   `auto-fit` con un minimo de 13rem: cuatro tarjetas en escritorio, dos
   en tablet, una en movil, sin media queries y sin dejar un hueco al
   final de la fila si se añade o se quita una. */
#main-body .hex-metrics {
    display: grid;
    gap: 0.75rem;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    margin-bottom: 0.875rem;
}

#main-body .hex-metric {
    background: var(--glass-bg);
    border: var(--glass-border);
    border-radius: var(--radius);
    color: var(--text-tertiary);
    display: block;
    overflow: hidden;
    padding: 1.125rem 1.125rem 1rem;
    position: relative;
    text-decoration: none;
    transition: background-color var(--t), border-color var(--t);
}

#main-body .hex-metric:hover,
#main-body .hex-metric:focus-visible {
    background: var(--glass-bg-strong);
    border-color: var(--hairline-strong);
    text-decoration: none;
}

/* Linea inferior del tono de la tarjeta, que solo se enciende al pasar
   por encima. Es el unico resto del `.highlight` de Twenty-One, y ahora
   el color significa algo: lo hereda de --hex-tone. */
#main-body .hex-metric::after {
    background: var(--hex-tone, var(--accent));
    bottom: 0;
    content: "";
    height: 2px;
    left: 0;
    opacity: 0;
    position: absolute;
    right: 0;
    transition: opacity var(--t);
}

#main-body .hex-metric:hover::after,
#main-body .hex-metric:focus-visible::after { opacity: 1; }

#main-body .hex-metric__icon {
    align-items: center;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-sm);
    color: var(--hex-tone, var(--accent-soft));
    display: inline-flex;
    font-size: 0.9375rem;
    height: 32px;
    justify-content: center;
    margin-bottom: 0.75rem;
    width: 32px;
}

#main-body .hex-metric__value {
    color: var(--text);
    display: block;
    font-family: var(--font-display);
    font-size: 2rem;
    font-weight: 700;
    letter-spacing: -0.035em;
    line-height: 1;
}

#main-body .hex-metric__label {
    color: var(--text-secondary);
    display: block;
    font-size: 0.8125rem;
    font-weight: 600;
    margin-top: 0.3125rem;
}

/* Linea de estado. El icono va SIEMPRE acompañando al texto: el tono de
   color es refuerzo, nunca la unica señal (RF-09.4). */
#main-body .hex-metric__note {
    align-items: center;
    color: var(--hex-tone, var(--text-muted));
    display: flex;
    font-size: 0.75rem;
    font-weight: 600;
    gap: 0.3125rem;
    margin-top: 0.5rem;
}

#main-body .hex-metric--ok   { --hex-tone: var(--success); }
#main-body .hex-metric--warn { --hex-tone: var(--warning); }
#main-body .hex-metric--info { --hex-tone: var(--accent-soft); }
#main-body .hex-metric--idle { --hex-tone: var(--text-muted); }

/* En la tarjeta apagada el icono no se tiñe: se queda neutro para que el
   contraste de la cifra siga siendo lo primero que se lee. */
#main-body .hex-metric--idle .hex-metric__icon { color: var(--text-tertiary); }

/* --- Franja de saldo a favor ----------------------------------------
   Entre la rejilla de metricas y los accesos rapidos. Una sola fila:
   icono, etiqueta + explicacion, importe y el boton de añadir fondos.

   El importe usa `tabular-nums` y `margin-left: auto` para que quede
   pegado al boton y siempre a la misma altura optica, aunque cambie el
   numero de digitos.
   -------------------------------------------------------------------- */
#main-body .hex-balance {
    align-items: center;
    background: var(--glass-bg);
    border: var(--glass-border);
    border-radius: var(--radius);
    display: flex;
    flex-wrap: wrap;
    gap: 0.875rem;
    margin-bottom: 1rem;
    padding: 0.875rem 1.125rem;
}

#main-body .hex-balance__icon {
    align-items: center;
    background: var(--accent-tint);
    border-radius: var(--radius-sm);
    color: var(--accent-soft);
    display: inline-flex;
    flex: 0 0 auto;
    font-size: 1rem;
    height: 2.25rem;
    justify-content: center;
    width: 2.25rem;
}

#main-body .hex-balance__text {
    display: flex;
    flex-direction: column;
    gap: 0.0625rem;
    min-width: 0;
}

#main-body .hex-balance__label {
    color: var(--text);
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.3;
}

#main-body .hex-balance__note {
    color: var(--text-muted);
    font-size: 0.75rem;
    line-height: 1.35;
}

#main-body .hex-balance__value {
    color: var(--text);
    font-size: 1.25rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
    margin-left: auto;
    white-space: nowrap;
}

#main-body .hex-balance__cta {
    align-items: center;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius);
    color: var(--text-secondary);
    display: inline-flex;
    flex: 0 0 auto;
    font-size: 0.8125rem;
    font-weight: 600;
    gap: 0.4375rem;
    justify-content: center;
    min-height: 38px;
    padding: 0 0.875rem;
    text-decoration: none;
    transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}

#main-body .hex-balance__cta:hover,
#main-body .hex-balance__cta:focus {
    background: rgba(255, 255, 255, 0.11);
    border-color: rgba(255, 255, 255, 0.26);
    color: var(--text);
    text-decoration: none;
}

@media (pointer: coarse) {
    #main-body .hex-balance__cta { min-height: var(--tap-target); }
}

/* En movil el importe pasa a linea propia, alineado a la izquierda con
   el resto; si no, se comprime contra el boton. */
@media (max-width: 575.98px) {
    #main-body .hex-balance { gap: 0.625rem; }
    #main-body .hex-balance__text { flex: 1 1 auto; }
    #main-body .hex-balance__value {
        flex: 1 1 100%;
        font-size: 1.375rem;
        margin-left: 0;
        order: 3;
    }
    #main-body .hex-balance__cta { flex: 1 1 100%; order: 4; }
}


/* --- Accesos secundarios ------------------------------------------- */
#main-body .hex-quicklinks {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1.5rem;
}

#main-body .hex-quicklink {
    align-items: center;
    background: transparent;
    border: 1px solid var(--hairline);
    border-radius: var(--radius-pill);
    color: var(--text-tertiary);
    display: inline-flex;
    font-size: 0.8125rem;
    font-weight: 600;
    gap: 0.5rem;
    min-height: var(--tap-target);   /* RF-03.4 */
    padding: 0.375rem 1rem;
    text-decoration: none;
    transition: background-color var(--t), border-color var(--t), color var(--t);
}

#main-body .hex-quicklink > i { color: var(--text-muted); font-size: 0.9375rem; }

#main-body .hex-quicklink:hover,
#main-body .hex-quicklink:focus-visible {
    background: rgba(255, 255, 255, 0.06);
    border-color: var(--accent-border);
    color: var(--text);
    text-decoration: none;
}

#main-body .hex-quicklink:hover > i { color: var(--accent-soft); }

/* --- Paneles del dashboard -----------------------------------------
   El fondo, el borde y el radio ya los pone la regla de § 12.b, que sigue
   apuntando a `.client-home-cards .card`. Aqui va solo lo que cambia por
   el markup nuevo. */
#main-body .hex-dash-columns {
    display: grid;
    gap: 0 1.25rem;
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* La cabecera pasa a ser una fila de tres piezas. En la base era un <h3>
   con un `float-right` dentro, que en titulos de dos lineas dejaba el
   boton descolgado del texto. */
#main-body .hex-panel__header {
    align-items: center;
    display: flex;
    gap: 0.75rem;
}

#main-body .hex-panel__icon {
    align-items: center;
    background: var(--accent-tint);
    border: 1px solid var(--accent-border);
    border-radius: var(--radius-sm);
    color: var(--accent-soft);
    display: inline-flex;
    flex: 0 0 auto;
    font-size: 0.875rem;
    height: 28px;
    justify-content: center;
    width: 28px;
}

#main-body .hex-panel__title {
    flex: 1 1 auto;
    min-width: 0;
}

#main-body .hex-panel__action { flex: 0 0 auto; }

#main-body .hex-panel__badge {
    background: rgba(255, 255, 255, 0.1);
    color: var(--text-secondary);
    margin-left: 0.375rem;
    vertical-align: 0.1em;
}

/* Items de lista de los paneles.
   ---------------------------------------------------------------------
   NO se convierten en contenedor flex, a proposito: la etiqueta de cada
   hijo puede venir de WHMCS como HTML de flujo (chip + asunto + <br> +
   <small>), y flexbox lo rompe. Ver la nota larga en § 12.b.

   El icono y el badge se colocan con `inline-block` y `float`, que
   conviven con ese HTML sin cambiar su modo de formato. */
#main-body .hex-panel__item-icon {
    color: var(--text-muted);
    display: inline-block;
    margin-right: 0.5rem;
    text-align: center;
    width: 1.25rem;
}

#main-body .hex-panel__item:hover .hex-panel__item-icon { color: var(--accent-soft); }

#main-body .hex-panel__item-badge {
    background: rgba(255, 255, 255, 0.1);
    color: var(--text-secondary);
    float: right;
    margin-left: 0.75rem;
}

#main-body .hex-panel__item.active .hex-panel__item-badge {
    background: var(--accent-tint-strong);
    color: var(--accent-soft);
}

/* El asunto de cada ticket / factura, que llega como texto suelto, se
   queda en el color de titulo para que destaque sobre la fecha. */
#main-body .hex-panel__list .hex-panel__item { color: var(--text); }
#main-body .hex-panel__list .hex-panel__item small { color: var(--text-muted); }

/* Caja con scroll de los paneles que traen varias filas (tickets
   recientes, ultimas facturas).
   ---------------------------------------------------------------------
   Es la SEGUNDA causa del listado de tickets roto. `theme.css` trae:

       .client-home-cards .list-group {
           max-height: 170px;
           overflow: auto;
           border-top:    1px solid #ddd !important;
           border-bottom: 1px solid #ddd !important;
       }

   Dos problemas. Uno, esos 170px estan calculados para las filas de
   `padding: 4px 10px` del tema claro; con el area pulsable de 44px que
   pide RF-03.4 no entran ni cuatro filas, asi que la cuarta se quedaba
   cortada por la mitad -- media linea de texto asomando por debajo del
   borde, que es lo que se veia en el panel de tickets. Y dos, esos
   bordes `#ddd !important` son dos lineas casi blancas cruzando el panel
   oscuro.

   Se sube el alto a 22rem (cinco filas completas y media, de modo que
   quede claro que hay mas y se puede desplazar) y los bordes pasan al
   filete del tema. El `!important` es obligatorio aqui: el del tema base
   tambien lo lleva y no se gana por especificidad. */
#main-body .client-home-cards .list-group,
#main-body .hex-panel__list {
    border-bottom: 1px solid var(--hairline) !important;
    border-radius: 0;
    border-top: 1px solid var(--hairline) !important;
    max-height: 22rem;
    overflow-y: auto;
}

/* Si la lista es lo ultimo del panel, el borde de abajo se solapa con el
   de la propia tarjeta y se ve una linea doble. */
#main-body .client-home-cards .list-group:last-child,
#main-body .hex-panel__list:last-child {
    border-bottom: 0 !important;
}

/* =====================================================================
   Servicios activos: rejilla de tarjetas
   ---------------------------------------------------------------------
   Panel `div[menuitemname="Active Products/Services"]` del dashboard.
   El markup de cada servicio sale de includes/active-products-services-item.tpl
   (ver la cabecera de ese archivo); aqui va la parte visual.

   DE FILAS A TARJETAS
   `theme.css` deja el panel como una pila de filas flex de ancho completo:
   con cuatro servicios ocupaba media pantalla y, al ser el panel a ancho
   completo, cada fila arrastraba el ojo de un extremo al otro con 40 cm de
   vacio entre el nombre y los botones. Ahora la lista es una rejilla
   `auto-fill` de tarjetas de 17 rem: en escritorio entran cuatro (justo el
   maximo que WHMCS pinta de entrada, ver mas abajo) en una sola banda, y
   baja a dos y a una sola columna segun el ancho, sin media queries.

   TRES CAPAS DE MARKUP QUE NO SE PUEDEN CAMBIAR DESDE LA PLANTILLA
   1. El envoltorio `.list-group-item` lo pone WHMCS al meter cada tarjeta
      como hijo del panel. Se neutraliza (sin fondo, sin borde, sin
      padding) y la superficie de tarjeta la dibuja `.div-service-item`.
   2. `theme.css` oculta los items a partir del quinto
      (`.list-group-item:nth-child(n+5) { display: none }`) y el boton
      «ver mas» del pie los va mostrando de ocho en ocho poniendoles
      `display: block` en linea. Un `display: block` en un hijo de grid se
      blockifica igual, asi que la rejilla lo absorbe sin tocar nada.
   3. js/whmcs.js escribe DOS estilos EN LINEA que hay que anular, y a un
      estilo en linea solo se le gana con `!important`:
        - `border-bottom: 1px solid #ddd` sobre el ultimo item visible
          (separador del tema claro: una raya casi blanca cruzando el
          panel oscuro, y ademas en rejilla caia en mitad de la banda);
        - un `width` en pixeles sobre `.div-service-status`, calculado
          para que los chips de todas las FILAS quedasen alineados en
          columna. Sin filas no hay nada que alinear y ese ancho fijo
          recortaba el texto del chip.
   ===================================================================== */

/* La lista deja de ser una pila y pasa a ser la rejilla.
   Los `!important` de `overflow` / `max-height` / bordes responden a los
   `!important` que ya traen `theme.css` y la regla de la caja con scroll
   de aqui arriba: en este panel no hay scroll interno ni filetes. */
#main-body .client-home-cards div[menuitemname="Active Products/Services"] .list-group,
#main-body .primary-content div[menuitemname="Active Products/Services"] .list-group {
    border-bottom: 0 !important;
    border-top: 0 !important;
    display: grid;
    gap: 0.75rem;
    /* El `min()` evita el desbordamiento horizontal cuando el contenedor
       es mas estrecho que los 17 rem del minimo (movil pequeño). */
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
    max-height: none !important;
    overflow: visible !important;
    /* Los laterales igualan el padding de la cabecera del panel para que
       las tarjetas alineen con el titulo. */
    padding: 1rem 1.125rem 1.125rem;
}

/* El envoltorio que pone WHMCS: pura celda de rejilla. */
#main-body .client-home-cards div[menuitemname="Active Products/Services"] .list-group-item,
#main-body .primary-content div[menuitemname="Active Products/Services"] .list-group-item {
    background: transparent;
    border: 0 !important;   /* anula el separador en linea de whmcs.js */
    display: block;
    min-height: 0;
    padding: 0;
}

#main-body .client-home-cards div[menuitemname="Active Products/Services"] .list-group-item:hover,
#main-body .primary-content div[menuitemname="Active Products/Services"] .list-group-item:hover {
    background: transparent;
}

/* --- La tarjeta ---------------------------------------------------- */
#main-body .hex-service-card {
    background: var(--glass-bg);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    height: 100%;
    padding: 0.875rem;
    transition: background-color var(--t), border-color var(--t), transform var(--t);
}

#main-body .hex-service-card:hover {
    background: var(--glass-bg-strong);
    border-color: var(--accent-border);
    transform: translateY(-2px);
}

/* Franja 1: rotulo del grupo + chip de estado. */
#main-body .hex-service-card__top {
    align-items: center;
    display: flex;
    gap: 0.5rem;
    min-height: 1.25rem;
}

#main-body .hex-service-card__group {
    color: var(--text-muted);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    text-transform: uppercase;
    white-space: nowrap;
}

/* `width: auto !important` -> contra el ancho en pixeles que whmcs.js
   escribe en linea (ver la nota 3 de la cabecera). El del chip es contra
   `theme.css`, que por debajo de 768 px lo clava a 3 rem con ellipsis:
   en una tarjeta hay sitio de sobra para el texto completo. */
#main-body .hex-service-card .div-service-status {
    flex: 0 0 auto;
    margin-left: auto;
    text-align: right;
    width: auto !important;
}

#main-body .hex-service-card .div-service-status .label:not(.label-placeholder) {
    width: auto !important;
}

/* Franja 2: nombre del producto + dominio o IP. Crece para empujar las
   acciones al pie, de modo que todas las tarjetas de la banda alineen sus
   botones aunque una tenga dominio y otra no. */
#main-body .hex-service-card .div-service-name {
    flex: 1 1 auto;
    justify-content: center;
    margin-left: 0;
    margin-right: 0;
}

#main-body .div-service-name .font-weight-bold {
    color: var(--text);
    font-size: 0.9375rem;
    letter-spacing: -0.01em;
    line-height: 1.3;
}

/* La IP o el dominio en cifras tabulares: son datos que se leen y se
   copian, no prosa. */
#main-body .div-service-name .text-domain {
    color: var(--text-tertiary);
    font-size: 0.8125rem;
    font-variant-numeric: tabular-nums;
    margin-top: 0.125rem;
}

/* Franja 3: acciones. `theme.css` las manda a la derecha con
   `margin-left: auto`, que en columna las empujaria fuera de la tarjeta. */
#main-body .hex-service-card .div-service-buttons {
    align-items: center;
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    margin-left: 0;
    margin-top: auto;
}

#main-body .hex-service-card .div-service-buttons .btn {
    border-radius: var(--radius-sm);
    font-size: 0.75rem;
    padding: 0.4rem 0.7rem;
}

/* Los botones de modulo reparten el ancho disponible; «ver detalles»
   ocupa el resto de la fila para que no queden huecos raros cuando un
   servicio trae un solo boton. */
#main-body .hex-service-card .div-service-buttons .btn-group-secondary,
#main-body .hex-service-card .div-service-buttons .btn-view-details {
    flex: 1 1 auto;
}

/* Solo el boton principal del grupo se estira: el `.btn-group` anidado
   que cuelga a su derecha es el desplegable del caret y se queda con su
   ancho natural. */
#main-body .hex-service-card .div-service-buttons .btn-group-secondary > .btn { flex: 1 1 auto; }

#main-body .hex-service-card .btn-view-details {
    background: transparent;
    border: 1px solid var(--hairline-strong);
    color: var(--text-secondary);
}

#main-body .hex-service-card .btn-view-details:hover {
    background: var(--accent-tint);
    border-color: var(--accent-border);
    color: var(--accent-soft);
}

@media (max-width: 991.98px) {
    #main-body .hex-dash-columns { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 575.98px) {
    #main-body .hex-dash-hero {
        align-items: stretch;
        padding: 1.25rem 1.125rem;
    }
    #main-body .hex-dash-hero__actions { flex-direction: column; }
    #main-body .hex-dash-hero__cta { justify-content: center; }
    #main-body .hex-metric { padding: 1rem; }
    #main-body .hex-metric__value { font-size: 1.75rem; }
}


/* ---------------------------------------------------------------------
   12.f Registro de cliente (register.php)
   ---------------------------------------------------------------------
   EL BUG DE LOS CAMPOS EN BLANCO

   `theme.css` trae su propia hoja de formularios para esta pagina, colgada
   del id del contenedor:

       #registration .field,
       #registration .form-control {
           background: #fff;
           color: #626262;
           border: 1px solid #DDD;
           height: 36px;
       }

   Un id y una clase: (1,1,0). Las reglas de formulario de este tema son
   `.form-control` a secas, (0,1,0), asi que perdian por especificidad y
   TODOS los campos de register.php salian blancos con texto gris -- no
   solo los que llevaban `class="field"` sin `form-control`, que era la
   primera sospecha.

   La unica forma de ganar es escribir desde el mismo id. De ahi que todo
   este bloque vaya prefijado con `#registration`. Ojo al copiar reglas de
   aqui a otra seccion: fuera de esta pagina el prefijo sobra.

   Ademas del color, se aprovecha para subir el alto de 36px a los 44 del
   area pulsable minima del tema (RF-03.4).
   --------------------------------------------------------------------- */

#registration .field,
#registration .form-control,
#registration select.field,
#registration textarea.field {
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius-sm);
    color: var(--text);
    font-size: 0.9375rem;
    height: var(--tap-target);
    transition: background-color var(--t-fast), border-color var(--t-fast);
    width: 100%;
}

#registration textarea.field,
#registration textarea.form-control { height: auto; min-height: 96px; padding-top: 0.625rem; }

#registration .field::placeholder,
#registration .form-control::placeholder { color: var(--text-muted); opacity: 1; }

#registration .field:focus,
#registration .form-control:focus {
    background: rgba(255, 255, 255, 0.07);
    border-color: var(--accent);
    box-shadow: none;
    color: var(--text);
}

/* El desplegable de pais es largo: sin esto las opciones salen con el
   fondo blanco del sistema. */
#registration select.field option,
#registration select.form-control option {
    background-color: var(--bg-elevated);
    color: var(--text);
}

#registration .field[disabled],
#registration .field[readonly],
#registration .form-control[disabled],
#registration .form-control[readonly] {
    background-color: rgba(255, 255, 255, 0.02);
    color: var(--text-disabled);
}

/* Pastilla del icono. `theme.css` la fija a 36px de alto para cuadrar con
   el campo viejo; al subir el campo a 44 hay que subirla tambien o el
   icono queda alto. */
#registration .prepend-icon .field-icon {
    height: var(--tap-target);
    line-height: var(--tap-target);
    width: 42px;
}

#registration .prepend-icon .field { padding-left: 42px; }
#registration .field-icon i { color: var(--text-muted); }

/* El icono se enciende con el campo. `:focus-within` sobre el contenedor
   porque la etiqueta es hermana anterior del input y no hay combinador
   que suba de un hermano al otro. */
#registration .prepend-icon:focus-within .field-icon i { color: var(--accent-soft); }

#registration .field-help-text { color: var(--text-tertiary); font-size: 0.75rem; }

#registration label { color: var(--text-secondary); }

/* --- Estructura de la pagina ---------------------------------------
   Columna de 860px centrada. Un formulario a 1900px de ancho pone el
   campo y su vecino a medio metro de distancia y se pierde el hilo. */
#main-body .hex-register {
    margin: 0 auto;
    max-width: 860px;
}

#main-body .hex-register__head {
    margin-bottom: 1.75rem;
    text-align: center;
}

#main-body .hex-register__eyebrow {
    color: var(--accent-soft);
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    margin: 0 0 0.5rem;
    text-transform: uppercase;
}

#main-body .hex-register__title {
    color: var(--text);
    font-family: var(--font-display);
    font-size: clamp(1.625rem, 1.2rem + 1.6vw, 2.25rem);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.15;
    margin: 0;
}

#main-body .hex-register__sub {
    color: var(--text-tertiary);
    font-size: 0.9375rem;
    margin: 0.625rem 0 0;
}

#main-body .hex-register__sub a { color: var(--accent-soft); font-weight: 600; }

/* --- Bloques del formulario ---------------------------------------- */
#main-body .hex-register-section {
    background: var(--glass-bg);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: var(--glass-border);
    border-radius: var(--radius-lg);
    margin-bottom: 1rem;
    padding: 1.5rem;
}

#main-body .hex-register-section__head {
    align-items: center;
    display: flex;
    gap: 0.75rem;
    margin-bottom: 1.25rem;
}

/* Numero de paso. Es decorativo (`aria-hidden` en la plantilla): el orden
   ya lo da el DOM, y leerlo en voz alta antes de cada titulo solo estorba. */
#main-body .hex-register-section__num {
    align-items: center;
    background: var(--accent-tint);
    border: 1px solid var(--accent-border);
    border-radius: 50%;
    color: var(--accent-soft);
    display: inline-flex;
    flex: 0 0 auto;
    font-family: var(--font-display);
    font-size: 0.8125rem;
    font-weight: 700;
    height: 28px;
    justify-content: center;
    width: 28px;
}

#main-body .hex-register-section__title {
    color: var(--text);
    font-family: var(--font-display);
    font-size: 1.0625rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin: 0;
}

#main-body .hex-register-section__hint {
    color: var(--text-muted);
    font-size: 0.8125rem;
    margin: -0.75rem 0 1.25rem;
}

#main-body .hex-register-section .form-group { margin-bottom: 1rem; }
#main-body .hex-register-section .row > [class*="col-"]:last-child .form-group { margin-bottom: 0; }

/* --- Contraseña: generar + medidor de fuerza ------------------------ */
#main-body .hex-register-pw {
    align-items: center;
    border-top: 1px solid var(--hairline-soft);
    display: flex;
    flex-wrap: wrap;
    gap: 0.875rem;
    margin-top: 0.25rem;
    padding-top: 1rem;
}

#main-body .hex-register-pw .btn {
    align-items: center;
    display: inline-flex;
    flex: 0 0 auto;
    gap: 0.4375rem;
    min-height: 38px;
}

#main-body .hex-register-pw .password-strength-meter {
    flex: 1 1 220px;
    min-width: 0;
}

#main-body .hex-register-pw .progress { height: 6px; margin-bottom: 0.375rem; }

#main-body .hex-register-pw #passwordStrengthTextLabel {
    color: var(--text-muted);
    font-size: 0.75rem;
    margin: 0;
}

/* --- Alta en la lista de correo ------------------------------------ */
#main-body .hex-register-optin {
    align-items: flex-start;
    display: flex;
    gap: 0.875rem;
}

#main-body .hex-register-optin > label {
    cursor: pointer;
    display: block;
    margin: 0;
}

#main-body .hex-register-optin__title {
    color: var(--text);
    display: block;
    font-weight: 600;
    margin-bottom: 0.125rem;
}

#main-body .hex-register-optin__text {
    color: var(--text-tertiary);
    display: block;
    font-size: 0.8125rem;
}

/* --- Pie: condiciones + enviar -------------------------------------- */
#main-body .hex-register-submit {
    align-items: center;
    background: var(--glass-bg);
    border: var(--glass-border);
    border-radius: var(--radius-lg);
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    justify-content: space-between;
    padding: 1.25rem 1.5rem;
}

#main-body .hex-register-tos {
    align-items: flex-start;
    color: var(--text-secondary);
    cursor: pointer;
    display: flex;
    flex: 1 1 280px;
    font-size: 0.875rem;
    gap: 0.625rem;
    margin: 0;
}

/* La casilla es un item flex normal.
   ---------------------------------------------------------------------
   `position: static` y `margin-left: 0` son la red de seguridad del bug
   de la casilla que se salia de la caja: si alguien vuelve a ponerle
   `form-check-input` al input (Bootstrap la declara `position: absolute;
   margin-left: -1.25rem`), aqui se neutraliza. Ver la nota de
   clientregister.tpl. */
#main-body .hex-register-tos input {
    flex: 0 0 auto;
    margin-left: 0;
    margin-top: 0.2em;
    position: static;
}
#main-body .hex-register-tos > span { min-width: 0; }
#main-body .hex-register-tos a { color: var(--accent-soft); }

#main-body .hex-register-submit__btn {
    flex: 0 0 auto;
    min-height: var(--tap-target);
    min-width: 220px;
}

@media (max-width: 575.98px) {
    #main-body .hex-register-section { padding: 1.125rem; }
    #main-body .hex-register-submit { padding: 1.125rem; }
    #main-body .hex-register-submit__btn { min-width: 0; width: 100%; }
}


/* =====================================================================
   13. MODALES, DROPDOWNS, POPOVERS Y TOOLTIPS
   ===================================================================== */

.modal-backdrop.show { opacity: 0.7; }

/* El fondo iba al 86 % y con desenfoque: sobre una pagina oscura el
   dialogo se leia como una mancha, no como una ventana. Se sube al 98 %
   para que tenga borde propio y se distinga de lo que hay detras. */
.modal-content {
    background: rgba(16, 16, 22, 0.98);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius-lg);
    box-shadow: 0 24px 56px rgba(0, 0, 0, 0.7);
    color: var(--text-secondary);
}

/* Bootstrap ancla los modales arriba; con la cabecera sticky del tema el
   dialogo aparecia pegado (y a veces por debajo) del header. Se centran
   verticalmente sin tocar el markup, que viene de WHMCS. */
.modal.show .modal-dialog {
    align-items: center;
    display: flex;
    min-height: calc(100% - 3.5rem);
}

.modal.show .modal-dialog > .modal-content { width: 100%; }

.modal-header,
.modal-footer { border-color: var(--hairline); }
.modal-title  { color: var(--text); }

.modal-header .close,
.close {
    color: var(--text-secondary);
    opacity: 1;
    text-shadow: none;
    min-height: var(--tap-target);
    min-width: var(--tap-target);
}
.close:hover { color: var(--text); opacity: 1; }

/* El menu era casi ilegible: el fondo dejaba pasar la pagina y el tema
   base pinta los enlaces de #444 (gris oscuro sobre fondo oscuro). Se
   sube la opacidad del fondo y se fuerza el color del texto con la
   especificidad suficiente para ganar a la regla base. */
.dropdown-menu {
    background: rgba(14, 14, 19, 0.98);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border: 1px solid var(--hairline-strong);
    border-radius: var(--radius);
    box-shadow: 0 16px 40px -12px rgba(0, 0, 0, 0.85);
    padding: 0.375rem;
}

/* Sin backdrop-filter el fondo debe ser totalmente opaco. */
@supports not ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
    .dropdown-menu { background: #0e0e13; }
}

#nav .dropdown-menu > li > a,
#nav .dropdown-menu .dropdown-item,
.navbar-nav .dropdown-menu > li > a,
.navbar-nav .dropdown-menu .dropdown-item,
.dropdown-menu > li > a,
.dropdown-menu .dropdown-item {
    background: transparent;
    border-radius: var(--radius-sm);
    color: var(--text-secondary) !important;
    display: flex;
    align-items: center;
    font-size: 0.875rem;
    font-weight: 500;
    min-height: var(--tap-target);
    padding: 0.5rem 0.75rem !important;
    white-space: nowrap;
}

#nav .dropdown-menu > li > a:hover,
#nav .dropdown-menu .dropdown-item:hover,
.navbar-nav .dropdown-menu > li > a:hover,
.navbar-nav .dropdown-menu .dropdown-item:hover,
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus,
.dropdown-menu .dropdown-item:hover,
.dropdown-menu .dropdown-item:focus {
    background: rgba(255, 255, 255, 0.08);
    color: var(--text) !important;
    text-decoration: none;
}

/* Los <li> que envuelven a .dropdown-item no deben pintar nada. */
.dropdown-menu > li.dropdown-item {
    background: transparent;
    display: block;
    min-height: 0;
    padding: 0 !important;
}

.dropdown-menu > li.dropdown-item > a { width: 100%; }

.dropdown-menu .dropdown-item > i,
.dropdown-menu > li > a > i {
    color: var(--text-muted);
    margin-right: 0.5rem;
    width: 1rem;
}

.dropdown-menu .dropdown-item:hover > i,
.dropdown-menu > li > a:hover > i { color: var(--accent-soft); }

.dropdown-divider { border-color: var(--hairline); }

/* --- Popovers ------------------------------------------------------
   theme.min.css los pinta blancos y ademas les fija la pila de fuentes
   del sistema (-apple-system, Segoe UI...), asi que el texto no salia en
   Inter como el resto del tema. El popover de notificaciones va todavia
   mas lejos: se cuelga de <body> con la clase .popover-user-notifications
   y fuerza "Open Sans".

   Se declaran con !important porque el popover vive fuera de #main-body
   y no hay ningun ancestro con el que ganar especificidad de forma
   limpia; ademas Bootstrap le escribe estilos en linea al posicionarlo. */
.popover,
.popover-user-notifications {
    background-color: rgba(14, 14, 19, 0.96) !important;
    border: var(--glass-border);
    -webkit-backdrop-filter: var(--glass-blur);
    backdrop-filter: var(--glass-blur);
    border-radius: var(--radius);
    box-shadow: var(--glass-shadow);
    color: var(--text-secondary);
    font-family: var(--font-ui) !important;
    font-size: 0.875rem;
}

.popover-header {
    background: rgba(255, 255, 255, 0.05);
    border-bottom-color: var(--hairline);
    color: var(--text);
    font-family: var(--font-ui);
    font-size: 0.9375rem;
    font-weight: 600;
}

.popover-body,
.popover-user-notifications .popover-body { color: var(--text-secondary); }

/* La flecha se pinta con dos triangulos superpuestos (borde + relleno);
   hay que teñir los cuatro lados porque el popover se coloca arriba,
   abajo, a izquierda o a derecha segun el espacio disponible. */
.popover .arrow::after {
    border-top-color: rgba(14, 14, 19, 0.96);
    border-bottom-color: rgba(14, 14, 19, 0.96);
    border-left-color: rgba(14, 14, 19, 0.96);
    border-right-color: rgba(14, 14, 19, 0.96);
}
.popover .arrow::before {
    border-top-color: var(--hairline-strong);
    border-bottom-color: var(--hairline-strong);
    border-left-color: var(--hairline-strong);
    border-right-color: var(--hairline-strong);
}

/* --- Popover de notificaciones de la topbar ------------------------ */
.popover-user-notifications {
    border-color: var(--hairline-strong) !important;
    min-width: 320px;
    padding: 0.25rem;
}

.popover-user-notifications .popover-body { padding: 0; }

.popover-user-notifications ul li {
    border-bottom: 1px solid var(--hairline-soft);
    min-height: 0;              /* el base reservaba 66px de alto fijo */
    padding: 0;
}

.popover-user-notifications ul li:last-child { border-bottom: 0; }

/* El markup base flota el icono a la izquierda y compensa el texto con
   un margin-left de 40px: si el mensaje ocupa dos lineas, la segunda se
   mete debajo del icono. Se pasa a flex y el margen deja de hacer falta. */
.popover-user-notifications ul li a {
    align-items: flex-start;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    display: flex;
    font-size: 0.8125rem;
    gap: 0.625rem;
    line-height: 1.45;
    padding: 0.625rem 0.75rem;
}

.popover-user-notifications ul li a:hover {
    background-color: rgba(255, 255, 255, 0.06);
    color: var(--text);
    text-decoration: none;
}

.popover-user-notifications ul li i.fas,
.popover-user-notifications ul li i.far {
    flex: 0 0 auto;
    float: none;                /* el base lo flotaba */
    font-size: 1rem;
    padding-top: 0.125rem;
}

.popover-user-notifications ul li .message { margin-left: 0; }

.popover-user-notifications ul li.none {
    color: var(--text-tertiary);
    font-size: 0.8125rem;
    padding: 0.75rem;
    text-align: center;
}

.tooltip-inner {
    background: var(--bg-elevated);
    border: 1px solid var(--hairline);
    color: var(--text);
}


/* =====================================================================
   14. FOOTER
   ===================================================================== */

#footer,
footer.footer {
    background: rgba(0, 0, 0, 0.35);
    border-top: 1px solid var(--hairline-soft);
    color: var(--text-tertiary);
    margin-top: 3rem;
    padding: 2rem 0;
}

#footer a,
footer.footer a { color: var(--text-secondary); }
#footer a:hover,
footer.footer a:hover { color: var(--text); }

.footer-language-select .btn,
#footer .btn { min-height: var(--tap-target); }


/* =====================================================================
   15. ACCESIBILIDAD
   ---------------------------------------------------------------------
   RF-03.3 / RF-03.6 / RF-09.2. Anillo de foco azul claro (#bfd3ff),
   de la misma rampa que el acento: 13.4:1 sobre el fondo y 3.3:1 sobre
   el relleno de los botones de acento, asi que se ve sobre cualquier
   superficie del tema y cumple el 3:1 que pide WCAG para indicadores
   no textuales.
   ===================================================================== */

/* Se elimina el outline solo cuando el foco viene del raton. */
:focus:not(:focus-visible) { outline: none; }

a:focus-visible,
button:focus-visible,
.btn:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
.hex-access-card:focus-visible,
.list-group-item:focus-visible,
.dropdown-item:focus-visible {
    outline: var(--focus-width) solid var(--focus);
    outline-offset: var(--focus-offset);
    border-radius: var(--radius-sm);
}

/* Bootstrap 4 anula el outline con box-shadow: lo neutralizamos. */
.btn:focus,
.btn.focus,
.form-control:focus,
.custom-select:focus { box-shadow: none; }

/* Fallback para navegadores sin :focus-visible. */
@supports not selector(:focus-visible) {
    a:focus,
    button:focus,
    .btn:focus,
    input:focus,
    select:focus,
    textarea:focus {
        outline: var(--focus-width) solid var(--focus);
        outline-offset: var(--focus-offset);
    }
}

/* Salto al contenido principal para usuarios de teclado. */
.hex-skip-link {
    background: var(--accent-strong);
    border-radius: 0 0 var(--radius) 0;
    color: #ffffff;
    font-weight: 700;
    left: 0;
    padding: 0.75rem 1.25rem;
    position: absolute;
    top: -100px;
    z-index: 2000;
    transition: top var(--t);
}

.hex-skip-link:focus {
    color: #ffffff;
    outline: var(--focus-width) solid var(--focus);
    outline-offset: calc(var(--focus-offset) * -1);
    text-decoration: none;
    top: 0;
}

.sr-only-focusable:focus {
    background: var(--accent-strong);
    color: #ffffff;
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
        transition-duration: 0.01ms !important;
    }
    .hex-access-card:hover,
    .action-icon-btns > div > a:hover { transform: none; }
}

/* Modo de alto contraste: se refuerzan los bordes que en glass son
   deliberadamente tenues. */
@media (prefers-contrast: more) {
    :root {
        --glass-bg:      rgba(255, 255, 255, 0.10);
        --hairline:      rgba(255, 255, 255, 0.28);
        --hairline-soft: rgba(255, 255, 255, 0.20);
        --text-secondary: #d4dae3;
    }
}


/* =====================================================================
   16. RESPONSIVE
   ---------------------------------------------------------------------
   RF-08. No se usan escalas forzadas (transform/zoom): se ajustan
   tamaños y columnas reales para mantener la legibilidad (RF-08.5).
   ===================================================================== */

@media (max-width: 1199.98px) {
    /* El menu colapsado se muestra como panel glass debajo del header. */
    .main-navbar-wrapper .navbar-collapse {
        background: rgba(14, 14, 19, 0.94);
        -webkit-backdrop-filter: var(--glass-blur);
        backdrop-filter: var(--glass-blur);
        border: var(--glass-border);
        border-radius: var(--radius);
        margin: 0.5rem 0 0.75rem;
        padding: 0.5rem;
    }

    .hex-nav-actions {
        flex-wrap: wrap;
        margin: 0.5rem 0 0;
        width: 100%;
    }
    .hex-nav-actions .btn { flex: 1 1 0; }
    /* La pastilla de cuenta ocupa su propia fila encima de los botones. */
    .hex-nav-actions .hex-nav-account { flex: 1 1 100%; }
}

@media (max-width: 767.98px) {
    html { font-size: 15px; }

    h1, .h1 { font-size: 1.625rem; }
    h2, .h2 { font-size: 1.3125rem; }
    h3, .h3 { font-size: 1.125rem; }

    .header { position: static; }   /* evita robar alto util en movil */

    .hex-access-island { padding: 1.125rem; }

    .card-columns { column-count: 1; }

    /* Tablas que ya vienen envueltas en .table-responsive desde la
       plantilla (factura, nota de cobro, estado de los servidores): el
       scroll horizontal lo pone Bootstrap; aqui solo el desplazamiento
       con inercia en iOS.

       Las LISTAS del area de clientes (servicios, tickets, facturas...)
       no usan esta clase y se resuelven de otra forma: ver § 16.c. */
    .table-responsive { -webkit-overflow-scrolling: touch; }
}

@media (max-width: 575.98px) {
    .btn-block + .btn-block { margin-top: 0.5rem; }
    .hex-access-card { min-height: 100px; }

    /* El contenedor de Bootstrap deja 15px a cada lado. En un movil de
       375px eso son 30 de los 375 solo en aire lateral; se baja a 12. */
    #main-body > .container { padding-left: 0.75rem; padding-right: 0.75rem; }
}


/* =====================================================================
   16.c LISTAS DEL AREA DE CLIENTES EN MOVIL
   ---------------------------------------------------------------------
   POR QUE LAS TABLAS SE SALIAN DE LA PANTALLA

   includes/tablelist.tpl pasaba `"responsive": true` a DataTables. Esa
   opcion es de la extension Responsive, que es un paquete aparte, y NO
   viene en el bundle: `js/scripts.js` no contiene ni una vez la cadena
   "responsive" ni ninguna de las clases que genera (dtr-control,
   dtr-details, dtr-title). La opcion no hacia nada.

   Asi que las tablas nunca colapsaron columnas: en un movil de 375px,
   «Mis Productos y Servicios» pintaba cinco columnas a su ancho natural
   (unos 640px), se salia de la pantalla y arrastraba con ella el resto
   del layout, que es lo que se veia -- bloques de anchos distintos y
   cabeceras cortadas por la derecha.

   COMO SE RESUELVE SIN LA EXTENSION

   Por debajo de 768px cada fila pasa a ser una tarjeta y cada celda a
   una linea «etiqueta -> valor». La etiqueta sale de
   `content: attr(data-label)`; el atributo lo rellena tablelist.tpl
   leyendo el <thead>, y lo vuelve a hacer en cada `draw` porque paginar
   u ordenar reconstruye las filas.

   Es CSS puro (RT-01), no añade dependencias y funciona igual en las
   nueve listas que incluyen tablelist.tpl, sin tocar ninguna de ellas.

   Y COMO RED DE SEGURIDAD

   Cualquier tabla que NO pase por tablelist.tpl (las que genera un modulo
   de terceros, por ejemplo) se queda con scroll horizontal propio. Nunca
   es tan comodo como las tarjetas, pero garantiza que ninguna tabla
   pueda volver a romper el ancho de la pagina.

   UNA EXCEPCION: LA LISTA DE SERVICIOS

   Todos los selectores de esta seccion llevan
   `table.table-list:not(.hex-services-table)`. La lista de servicios
   (clientarea.php?action=services) tiene su propio tratamiento completo
   -- escritorio y movil -- en § 09.d, porque con cinco columnas el
   formato generico «una linea por celda» daba una tarjeta demasiado
   larga. El `:not()` es lo que deja que aquellas reglas manden: sin el,
   las de aqui ganarian por especificidad y por orden de aparicion.

   Si añades una regla nueva a esta seccion, copiale el `:not()`.
   ===================================================================== */

/* Red de seguridad: cualquier tabla dentro de un contenedor del area de
   clientes se desplaza dentro de su caja, no fuera de ella. */
#main-body .table-container,
#main-body .dataTables_wrapper {
    max-width: 100%;
}

@media (max-width: 767.98px) {

    /* --- Tablas que NO son .table-list: scroll horizontal ----------- */
    #main-body .table-container {
        -webkit-overflow-scrolling: touch;
        overflow-x: auto;
    }

    /* --- Barra superior e inferior de DataTables -------------------- */
    #main-body .dataTables_wrapper .listtable {
        gap: 0.5rem;
        justify-content: flex-start;
    }

    #main-body .dataTables_wrapper .dataTables_filter,
    #main-body .dataTables_wrapper .dataTables_filter label { width: 100%; }
    #main-body .dataTables_wrapper .dataTables_filter input { width: 100%; margin-left: 0; }

    /* theme.css le mete `padding: 9px 10px 40px` por debajo de 600px. Esos
       40px al pie eran el hueco negro que quedaba entre «Viendo 0 a 0 de 0
       entradas» y la tabla. */
    #main-body .dataTables_wrapper .dataTables_info {
        padding: 0 !important;
        text-align: left;
    }

    /* Pie: contador de entradas y paginacion, uno debajo del otro y
       centrados. Con los floats del tema base quedaban descolgados a la
       derecha y con un salto de linea en medio. */
    #main-body .dataTables_wrapper .dataTables_length,
    #main-body .dataTables_wrapper .dataTables_paginate {
        float: none;
        justify-content: center;
        text-align: center;
        width: 100%;
    }

    #main-body .dataTables_wrapper .dataTables_paginate {
        flex-wrap: wrap;
        margin-top: 0.875rem;
    }

    #main-body .dataTables_wrapper .dataTables_length { margin-top: 0.875rem; }

    /* --- Filas como tarjetas ---------------------------------------- */
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table),
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody,
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr,
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td {
        display: block;
        width: 100% !important;   /* el tema base fija width:100% en la tabla */
    }

    /* La cabecera se va: su contenido pasa a ser la etiqueta de cada
       celda. `clip` y no `display:none` porque DataTables lee el <thead>
       para ordenar y para saber cuantas columnas hay. */
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > thead {
        clip: rect(0 0 0 0);
        height: 1px;
        overflow: hidden;
        position: absolute;
        width: 1px;
    }

    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) {
        border: 0;
        margin: 0 !important;
    }

    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr {
        background: var(--glass-bg);
        border: var(--glass-border);
        border-radius: var(--radius);
        margin-bottom: 0.625rem;
        padding: 0.25rem 0;
    }

    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr:hover {
        background: var(--glass-bg-strong);
    }

    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td {
        align-items: baseline;
        border: 0;
        border-bottom: 1px solid var(--hairline-soft);
        display: flex;
        gap: 0.75rem;
        justify-content: space-between;
        /* Las celdas traen `text-center` de la plantilla, que en formato
           de tarjeta descoloca el valor respecto a su etiqueta. */
        text-align: right;
        padding: 0.5rem 0.875rem !important;
    }

    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td:last-child {
        border-bottom: 0;
    }

    /* La etiqueta, a la izquierda. */
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td::before {
        color: var(--text-muted);
        content: attr(data-label);
        flex: 0 0 auto;
        font-size: 0.6875rem;
        font-weight: 700;
        letter-spacing: 0.06em;
        max-width: 45%;
        text-align: left;
        text-transform: uppercase;
    }

    /* Columnas sin titulo (el icono SSL de servicios es un <th></th>
       vacio): sin etiqueta y a lo ancho, en lugar de dejar un hueco. */
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td[data-label=""]::before,
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td:not([data-label])::before {
        display: none;
    }

    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td[data-label=""] {
        justify-content: flex-start;
        text-align: left;
    }

    /* Una celda de icono sin icono no debe ocupar una linea entera.
       -----------------------------------------------------------------
       Se usa :not(:has(*)) y NO :empty. La celda del icono SSL sale de un
       {if} de Smarty: cuando no hay nada que pintar no queda vacia, queda
       con los saltos de linea y la sangria de la plantilla dentro, y
       :empty no casa si hay un solo espacio.

       En un navegador sin :has() la regla entera se descarta y la celda
       se ve como una linea vacia de 35px. Es feo, no roto. */
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td[data-label=""]:not(:has(*)) {
        display: none;
    }

    /* La fila de «Sin resultados» no es una tarjeta de datos. */
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td.dataTables_empty {
        border: 0;
        justify-content: center;
        text-align: center;
    }

    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td.dataTables_empty::before {
        display: none;
    }

    /* El nombre del producto es el titulo de la tarjeta: se saca de la
       fila etiqueta/valor y se pone arriba, a tamaño legible. */
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td > strong {
        color: var(--text);
        font-size: 0.9375rem;
    }

    /* En las tarjetas ya no hay columna estrecha que justifique cortar el
       texto: se deja envolver. */
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td,
    #main-body .dataTables_wrapper table.table-list:not(.hex-services-table) > tbody > tr > td a {
        overflow-wrap: anywhere;
        white-space: normal;
    }
}


/* =====================================================================
   16.b BARRIDO DE FONDOS CLAROS HEREDADOS
   ---------------------------------------------------------------------
   Twenty-One esta pensado para fondo blanco y siembra fondos claros por
   todo el CSS: #fff, #f5f5f5, #f6f6f6, #f8f8f8, #efefef... Cada uno de
   ellos es una pagina que aparece como un recuadro blanco con texto
   claro encima.

   Esta seccion los recoge en bloque, ordenados por pagina. Se hizo un
   barrido automatico de theme.css buscando toda regla con un fondo de
   la lista de arriba y cruzandolo con lo que ya cubria este archivo; lo
   que sigue es el resto.

   AVISO SOBRE LAS UTILIDADES DE BOOTSTRAP
   `bg-white` y `bg-light` llevan !important, asi que NO se pueden pisar
   desde aqui: hay que quitarlas de la plantilla. Ya se hizo en
   clientareaproductdetails.tpl, includes/domain-search.tpl,
   includes/sidebar.tpl y orderforms/.../domainregister.tpl. Si aparece
   otra pagina en blanco, busca primero esas dos clases en su .tpl.
   ===================================================================== */

/* --- Anuncios ------------------------------------------------------- */
#main-body .announcements .announcement article {
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid var(--hairline-soft);
    border-radius: var(--radius);
    color: var(--text-secondary);
    padding: 1rem 1.125rem;
}

#main-body .announcements .announcement + .announcement {
    border-top: 1px solid var(--hairline-soft);
    margin-top: 1.5rem;
    padding-top: 1.5rem;
}

#main-body .announcements .announcement h1 {
    font-size: 1.25rem;
    font-weight: 700;
    margin-bottom: 0.375rem;
}

#main-body .announcements .announcement h1 a { color: var(--text); }
#main-body .announcements .announcement h1 a:hover { color: var(--accent-soft); }

/* --- Base de conocimientos ------------------------------------------ */
#main-body .kb-category a,
#main-body .kb-article-item {
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
}

#main-body .kb-category a:hover,
#main-body .kb-article-item:hover {
    background-color: rgba(255, 255, 255, 0.06);
    color: var(--text);
}

/* --- Avisos de verificacion de email -------------------------------- */
#main-body .verification-banner,
.verification-banner {
    background-color: var(--warning-tint);
    border: 1px solid var(--hairline);
    border-left: 3px solid var(--warning);
    border-radius: var(--radius);
    color: var(--text-secondary);
}

/* --- Invitaciones y cambio de cuenta -------------------------------- */
#main-body .invite-box,
#main-body .continue-container,
#main-body .select-account a:hover {
    background-color: rgba(255, 255, 255, 0.04);
    border-color: var(--hairline);   /* el base lo deja en #eee */
    border-radius: var(--radius);
    color: var(--text-secondary);
}

#main-body .select-account a {
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
}

/* --- Seguridad: codigos de respaldo del 2FA ------------------------- */
#main-body .twofa-setup .backup-code {
    background-color: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-sm);
    color: var(--text);
    font-family: var(--font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
}

#main-body .twofa-setup .activation-msg {
    border: 1px dashed var(--hairline-strong);
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
}

#main-body .twofa-module {
    background-color: rgba(255, 255, 255, 0.03);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    color: var(--text-secondary);
}

/* --- Valoracion de tickets ------------------------------------------ */
#main-body .ticketfeedbackstaffcont {
    background-color: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    color: var(--text-secondary);
}

/* --- Metodos de pago y pagos masivos -------------------------------- */
#main-body div.credit-card {
    background-color: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    color: var(--text-secondary);
}

#main-body tr.masspay-total td {
    background-color: rgba(255, 255, 255, 0.06);
    color: var(--text);
}

/* --- Mejoras de producto (upgrade) ---------------------------------- */
#main-body .upgrade .product-to-be-upgraded {
    background-color: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    color: var(--text-secondary);
}

/* --- Bloques promocionales de WHMCS --------------------------------- */
#main-body .promo-container,
#main-body .promo-banner {
    background-color: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    color: var(--text-secondary);
}

/* =====================================================================
   Pestañas responsive (`.responsive-tabs-sm`)
   ---------------------------------------------------------------------
   El mismo widget en seis paginas: detalles del producto, contactos del
   dominio, gestion masiva de dominios y tres del store (order, ox,
   spamexperts). Se arregla aqui, en CSS, y quedan las seis a la vez: no
   hace falta tocar ningun .tpl.

   POR DEBAJO DE 768 px EL TEMA BASE MONTA UNA CARPETA DE ARCHIVADOR
   `theme.css` no apila las pestañas y ya esta: dibuja una pestaña de
   carpeta, con la lista mas estrecha que el panel y un "conector" que
   une una con otro. Traducido a numeros:

       .responsive-tabs-sm            { width: 90%; border-radius: 4px 4px 4px 0 }
       .responsive-tabs-sm .nav-item  { margin-left: 5px; width: 100% }
       .responsive-tabs-sm .nav-item a{ padding: 7px 15px !important }

   Tres problemas, y los tres se ven en un movil:

     1. La lista mide el 90 % y el panel de contenido el 100 %: los
        bordes no coinciden por ningun lado.
     2. Cada item mide el 100 % del <ul> Y ADEMAS se desplaza 5 px a la
        derecha, asi que se sale 5 px por fuera del borde derecho de su
        propio contenedor. Es el desbordamiento que se veia: las filas
        cruzando la esquina redondeada.
     3. `padding: 7px 15px` deja filas de ~30 px de alto. RF-03.4 pide
        44 px, y aqui son el unico modo de cambiar de pestaña.

   A eso se sumaba el `.responsive-tabs-sm-connector`, cinco pixeles de
   #fff y #ddd cuyo unico trabajo es dibujar el recorte de la carpeta.
   Ese lenguaje visual no existe en este tema: aqui todo son tarjetas
   planas con filete tenue.

   QUE SE HACE EN SU LUGAR
   Por debajo de 768 px las pestañas pasan a ser una **tarjeta selector**
   a ancho completo: filas de 44 px, separador entre ellas, y la activa
   con fondo de acento y un filete de acento a la izquierda (con
   `box-shadow: inset`, no `border-left`, para que no desplace el texto
   al cambiar de pestaña). Debajo, el panel de contenido como segunda
   tarjeta independiente.

   Se eligio la pila vertical y no una tira horizontal con scroll porque
   las etiquetas en español son largas («Opciones Configurables») y hay
   paginas con seis pestañas: en horizontal la mitad quedarian fuera de
   pantalla sin nada que lo indique.

   LOS `!important` SON OBLIGATORIOS
   No son por comodidad: `theme.css` marca como `!important` justo las
   propiedades que hay que cambiar (`padding`, `border-radius`,
   `border-bottom`, `margin-right` y el `background-color` de la activa),
   y a un `!important` solo se le gana con otro.
   ===================================================================== */

/* Escritorio: el hover del tema base es #f7f7f7. */
#main-body .responsive-tabs-sm .nav-item a:hover {
    background-color: rgba(255, 255, 255, 0.06);
    color: var(--text);
}

@media (max-width: 767.98px) {

    /* El conector sobra: sin carpeta no hay recorte que dibujar. Basta
       con subir la especificidad (`#main-body` + clase) porque el
       `display: block` del tema base no lleva `!important`. */
    #main-body .responsive-tabs-sm-connector { display: none; }

    /* La lista, a ancho completo y como tarjeta cerrada.
       `overflow: hidden` recorta el fondo de la fila activa contra las
       esquinas redondeadas; sin el, el color se desborda por las cuatro
       puntas. */
    #main-body .responsive-tabs-sm {
        background: var(--glass-bg);
        border: 1px solid var(--hairline);
        border-radius: var(--radius);
        margin: 0 0 0.75rem;
        overflow: hidden;
        width: 100%;
    }

    /* El `margin-left: 5px` del tema base es la causa del desbordamiento
       (ver punto 2 de la cabecera). */
    #main-body .responsive-tabs-sm .nav-item {
        border-bottom: 1px solid var(--hairline-soft) !important;
        border-radius: 0 !important;
        margin: 0 !important;
        width: 100%;
    }

    #main-body .responsive-tabs-sm .nav-item:last-child {
        border-bottom: 0 !important;
        border-radius: 0 !important;
    }

    /* Fila pulsable completa: 44 px de alto (RF-03.4) e icono y texto
       alineados con `gap`, en vez del `&nbsp;` del markup base. */
    #main-body .responsive-tabs-sm .nav-item a,
    #main-body .responsive-tabs-sm .nav-item:first-child a,
    #main-body .responsive-tabs-sm .nav-item:last-child a {
        align-items: center;
        border-radius: 0 !important;
        color: var(--text-tertiary);
        display: flex;
        font-weight: 600;
        gap: 0.625rem;
        margin: 0 !important;
        min-height: var(--tap-target);
        padding: 0.75rem 1rem !important;
        width: 100%;
    }

    #main-body .responsive-tabs-sm .nav-item a i {
        color: var(--text-muted);
        flex: 0 0 auto;
    }

    /* Pestaña activa: tinte de acento + filete de acento a la izquierda.
       El filete va como `box-shadow: inset` y no como `border-left`
       porque un borde ocupa sitio y desplazaria el texto 3 px cada vez
       que se cambia de pestaña. */
    #main-body .responsive-tabs-sm .nav-item a.active {
        background-color: var(--accent-tint) !important;
        box-shadow: inset 3px 0 0 0 var(--accent);
        color: var(--text);
    }

    #main-body .responsive-tabs-sm .nav-item a.active i { color: var(--accent-soft); }

    /* El panel de contenido deja de ser la "hoja" pegada a la carpeta y
       pasa a ser una tarjeta independiente: recupera el borde de arriba
       y las cuatro esquinas. En escritorio sigue unido a las pestañas,
       que es donde eso si tiene sentido. */
    #main-body div.product-details-tab-container,
    #main-body .product-details-tab-container {
        border-radius: var(--radius);
        border-top: 1px solid var(--hairline-soft);
        padding: 1rem;
    }
}

/* --- Contenido de las pestañas del servicio en movil -----------------
   Dentro de cada pestaña, los datos vienen como pares en una fila de
   Bootstrap partida 5/7:

       <div class="row">
         <div class="col-sm-5 text-right"><strong>Dominio</strong></div>
         <div class="col-sm-7 text-left">micosa.cl</div>
       </div>

   El prefijo es `sm`, asi que por debajo de 576 px las dos columnas
   pasan a ancho completo... pero `text-right` y `text-left` se quedan
   puestos. Resultado: la etiqueta pegada al borde derecho y su valor
   pegado al izquierdo, en zigzag, trece veces seguidas.

   Aqui se apilan como pares etiqueta/valor, igual que la rejilla
   `.hex-service-facts` de la tarjeta de arriba, para que las dos mitades
   de la pagina se lean igual.

   El `!important` responde al de las utilidades de Bootstrap
   (`.text-right { text-align: right !important }`, en theme.min.css).

   Se apunta a `.col-sm-5` / `.col-sm-7` y no a `.row > *` a proposito:
   la pestaña de uso de recursos monta su propia rejilla con
   `.col-sm-10.offset-sm-1` y `.col-sm-6` para los diales, y no debe
   entrar por aqui. */
@media (max-width: 575.98px) {
    #main-body .product-details-tab-container .row > .col-sm-5,
    #main-body .product-details-tab-container .row > .col-sm-7 {
        padding-left: 0;
        padding-right: 0;
        text-align: left !important;
    }

    #main-body .product-details-tab-container .row > .col-sm-5 {
        padding-top: 0.625rem;
    }

    #main-body .product-details-tab-container .row > .col-sm-5 strong {
        color: var(--text-muted);
        font-size: 0.75rem;
        font-weight: 700;
        letter-spacing: 0.04em;
        text-transform: uppercase;
    }

    /* El valor cierra el par, asi que es quien lleva el separador. */
    #main-body .product-details-tab-container .row > .col-sm-7 {
        border-bottom: 1px solid var(--hairline-soft);
        color: var(--text);
        font-variant-numeric: tabular-nums;
        padding-bottom: 0.625rem;
        /* Los nombres de servidor y las listas de IP no tienen espacios
           donde partir: sin esto desbordan a lo ancho. */
        overflow-wrap: break-word;
        word-break: break-word;
    }
}

/* --- Buscador de dominios de la portada ------------------------------
   La plantilla ya no lleva `bg-white` (ver aviso de arriba). */
.home-domain-search {
    background: rgba(255, 255, 255, 0.03);
    border-bottom: 1px solid var(--hairline-soft);
    border-top: 1px solid var(--hairline-soft);
    color: var(--text-secondary);
}

.home-domain-search h2 { color: var(--text); }
.home-domain-search .tld-logos { color: var(--text-tertiary); }

.home-domain-search .input-group-wrapper {
    background-color: transparent;
}

/* --- Paginas de precios de dominios ---------------------------------
   El sitio no vende dominios hoy, pero estas paginas siguen siendo
   accesibles por URL y quedaban en blanco. */
#main-body .featured-tld {
    background-color: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--hairline);
    border-radius: var(--radius);
    color: var(--text-secondary);
}

#main-body .featured-tld .price {
    background-color: rgba(255, 255, 255, 0.06);
    color: var(--text);
}

#main-body .domain-pricing .tld-pricing-header,
#main-body .domain-pricing .tld-pricing-header div:nth-child(odd),
#main-body .domain-pricing .tld-pricing-header .col-xs-2,
#main-body .domain-pricing .tld-pricing-header .col-sm-4 {
    background-color: rgba(255, 255, 255, 0.05);
    color: var(--text-secondary);
}

/* --- Controles de formulario personalizados --------------------------
   .custom-control-label::before es el cuadrado/circulo de los checkbox
   y radios "custom" de Bootstrap: en blanco sobre fondo oscuro parecian
   siempre marcados. */
#main-body .custom-control-label::before,
.custom-control-label::before {
    background-color: rgba(255, 255, 255, 0.08);
    border-color: var(--hairline-strong);
}

.custom-control-input:checked ~ .custom-control-label::before {
    background-color: var(--accent-strong);
    border-color: var(--accent-strong);
}

.custom-control-input:focus ~ .custom-control-label::before {
    box-shadow: 0 0 0 3px var(--accent-tint);
}

/* --- Campos validados ------------------------------------------------
   Bootstrap le pone al campo valido/invalido un `background` compuesto
   (el icono de tick o de aspa MAS `#fff`), asi que al validar un select
   o un input este se volvia blanco de golpe. Se conserva el icono y se
   devuelve el fondo del tema. */
#main-body .form-control.is-valid,
#main-body .form-control.is-invalid,
#main-body .custom-select.is-valid,
#main-body .custom-select.is-invalid,
#main-body .was-validated .form-control:valid,
#main-body .was-validated .form-control:invalid,
#main-body .was-validated .custom-select:valid,
#main-body .was-validated .custom-select:invalid {
    background-color: rgba(255, 255, 255, 0.05);
    color: var(--text);
}

#main-body .form-control.is-valid,
#main-body .custom-select.is-valid,
#main-body .was-validated .form-control:valid,
#main-body .was-validated .custom-select:valid { border-color: var(--success); }

#main-body .form-control.is-invalid,
#main-body .custom-select.is-invalid,
#main-body .was-validated .form-control:invalid,
#main-body .was-validated .custom-select:invalid { border-color: var(--danger); }

/* --- Consumo facturable ----------------------------------------------
   clientareaproductusagebilling.tpl usa la clase
   .table-solid-bottom-border-light-gray, que trae un borde #dee2e6. */
#main-body table.table-solid-bottom-border-light-gray,
#main-body table.table-solid-bottom-border-light-gray td,
#main-body table.table-solid-bottom-border-light-gray th {
    border-color: var(--hairline) !important;
}

/* --- Piezas sueltas -------------------------------------------------- */
#main-body .img-thumbnail,
.img-thumbnail {
    background-color: rgba(255, 255, 255, 0.04);
    border-color: var(--hairline);
}

.input-group .btn-reveal-pw:hover,
.input-group .btn-reveal-pw:active {
    background-color: rgba(255, 255, 255, 0.09);
    color: var(--text);
}

.modal-localisation .item-selector .item:hover {
    background-color: rgba(255, 255, 255, 0.08);
    color: var(--text);
}


/* =====================================================================
   17. UTILIDADES DEL TEMA
   ===================================================================== */

/* Campo de formulario que no se pide al cliente pero que sigue en el DOM.
   ---------------------------------------------------------------------
   La usa clientregister.tpl (y checkout.tpl del carrito, con su copia en
   orderform-custom.css) sobre la COLUMNA del campo, nunca sobre el input.

   Por que no se borra el input directamente: StatesDropdown.js sustituye
   #state por un <select> segun el pais y el checkout recalcula impuestos
   leyendo estos campos. Si desaparecen del HTML, ese JS se queda sin sus
   ganchos; oculto sigue funcionando y no molesta a nadie.

   `!important` porque el JS de WHMCS llama a .show() sobre algunos de
   estos bloques al cambiar de pais, y .show() escribe un style inline. */
.hex-field-hidden { display: none !important; }

.hex-surface {
    background: var(--bg-card);
    border-radius: var(--radius);
}

.hex-divider {
    background: var(--hairline);
    border: none;
    height: 1px;
    margin: 1.5rem 0;
}

.hex-text-muted     { color: var(--text-tertiary) !important; }
.hex-text-accent    { color: var(--accent-soft) !important; }
.hex-text-primary   { color: var(--text) !important; }

.text-muted { color: var(--text-tertiary) !important; }

.hex-eyebrow {
    color: var(--text-tertiary);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

/* Titulo grande a dos lineas (RF-05.2). */
.hex-display {
    color: var(--text);
    font-size: clamp(1.875rem, 1.2rem + 2.6vw, 3rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.12;
    margin: 0;
}

.hex-display .hex-display__line { display: block; }
.hex-display .hex-display__accent { color: var(--accent-soft); }


/* =====================================================================
   18. MOVIMIENTO
   ---------------------------------------------------------------------
   Animaciones de entrada y microinteracciones. CSS puro (RT-01): no hace
   falta ninguna libreria ni ninguna version concreta de Bootstrap --
   Bootstrap solo aporta sus propias transiciones de modal y colapso, que
   aqui no se tocan.

   TRES REGLAS QUE SE SIGUEN EN TODO EL BLOQUE

   1. Nada se mueve mas de 10px ni dura mas de 320ms. Una animacion de
      entrada es un acento, no un espectaculo: si el usuario la nota
      conscientemente, sobra.

   2. Solo se animan `opacity` y `transform`. Son las dos unicas
      propiedades que el navegador puede componer sin recalcular la
      maquetacion, asi que no hay reflow ni tirones en movil.

   3. Todo lleva `animation-fill-mode: both`. Es lo que garantiza que, si
      la animacion no llega a ejecutarse (pestaña en segundo plano,
      motor sin soporte, `prefers-reduced-motion`), el elemento se quede
      en su estado FINAL -- visible -- y no en el inicial. Sin esto, un
      `opacity: 0` de arranque puede dejar media pagina en blanco.

   PREFERENCIA DE MOVIMIENTO REDUCIDO
   No hay que repetirla aqui: § 15 ya declara
   `animation-duration: 0.01ms !important` para todo bajo
   `prefers-reduced-motion: reduce`. Con `fill-mode: both`, eso deja el
   resultado final pintado de inmediato y sin movimiento.
   ===================================================================== */

@keyframes hexRise {
    from { opacity: 0; transform: translate3d(0, 10px, 0); }
    to   { opacity: 1; transform: none; }
}

@keyframes hexFade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes hexPop {
    from { opacity: 0; transform: scale(0.96); }
    to   { opacity: 1; transform: none; }
}

/* Deslizamiento lateral corto, para listas verticales. */
@keyframes hexSlideIn {
    from { opacity: 0; transform: translate3d(-8px, 0, 0); }
    to   { opacity: 1; transform: none; }
}

/* --- Utilidades ----------------------------------------------------
   Para markup propio del tema. Se pueden poner a mano en cualquier .tpl.
   ------------------------------------------------------------------- */
.hex-anim-rise  { animation: hexRise 280ms ease-out both; }
.hex-anim-fade  { animation: hexFade 220ms ease-out both; }
.hex-anim-pop   { animation: hexPop 200ms ease-out both; }

/* Escalonado. Se aplica sobre el CONTENEDOR y afecta a sus hijos
   directos; el tope son seis porque a partir de ahi el retardo
   acumulado ya se percibe como lentitud. */
.hex-anim-stagger > *              { animation: hexRise 280ms ease-out both; }
.hex-anim-stagger > *:nth-child(1) { animation-delay: 0ms; }
.hex-anim-stagger > *:nth-child(2) { animation-delay: 40ms; }
.hex-anim-stagger > *:nth-child(3) { animation-delay: 80ms; }
.hex-anim-stagger > *:nth-child(4) { animation-delay: 120ms; }
.hex-anim-stagger > *:nth-child(5) { animation-delay: 160ms; }
.hex-anim-stagger > *:nth-child(n+6) { animation-delay: 200ms; }

/* --- Entrada del contenido de la pagina ---------------------------- */
#main-body .primary-content > .card,
#main-body .hex-dash-panels > .card,
#main-body .hex-register-section,
#main-body .hex-register-submit,
#main-body .table-container {
    animation: hexRise 300ms ease-out both;
}

/* --- Dashboard: metricas y accesos rapidos -------------------------
   Estas dos rejillas son lo primero que se ve al entrar al area de
   clientes, asi que son las unicas que llevan escalonado real. */
#main-body .hex-metrics > .hex-metric,
#main-body .hex-quicklinks > .hex-quicklink {
    animation: hexRise 280ms ease-out both;
}

/* La franja de saldo entra despues de las metricas, que es el orden en
   que se leen. */
#main-body .hex-balance {
    animation: hexRise 280ms ease-out both;
    animation-delay: 170ms;
}

#main-body .hex-metrics > .hex-metric:nth-child(1),
#main-body .hex-quicklinks > .hex-quicklink:nth-child(1) { animation-delay: 30ms; }
#main-body .hex-metrics > .hex-metric:nth-child(2),
#main-body .hex-quicklinks > .hex-quicklink:nth-child(2) { animation-delay: 70ms; }
#main-body .hex-metrics > .hex-metric:nth-child(3),
#main-body .hex-quicklinks > .hex-quicklink:nth-child(3) { animation-delay: 110ms; }
#main-body .hex-metrics > .hex-metric:nth-child(4),
#main-body .hex-quicklinks > .hex-quicklink:nth-child(4) { animation-delay: 150ms; }
#main-body .hex-quicklinks > .hex-quicklink:nth-child(n+5) { animation-delay: 190ms; }

/* --- Lista de servicios --------------------------------------------
   Las filas se repintan en cada `draw` de DataTables (paginar, ordenar,
   filtrar), asi que la animacion se vuelve a disparar sola y ademas
   sirve de acuse de recibo del filtro. Se deja MUY corta por eso mismo:
   se ve varias veces por sesion. */
#main-body .hex-services-table > tbody > tr {
    animation: hexSlideIn 200ms ease-out both;
}

#main-body .hex-services-table > tbody > tr:nth-child(1) { animation-delay: 0ms; }
#main-body .hex-services-table > tbody > tr:nth-child(2) { animation-delay: 25ms; }
#main-body .hex-services-table > tbody > tr:nth-child(3) { animation-delay: 50ms; }
#main-body .hex-services-table > tbody > tr:nth-child(4) { animation-delay: 75ms; }
#main-body .hex-services-table > tbody > tr:nth-child(n+5) { animation-delay: 100ms; }

/* --- Avisos --------------------------------------------------------
   Un mensaje que aparece de golpe se lee como parte del layout; con la
   entrada se lee como respuesta a lo que se acaba de hacer. */
#main-body .alert,
#main-body .hex-flash { animation: hexPop 220ms ease-out both; }

/* --- Microinteracciones --------------------------------------------
   Los elementos clickables ya tenian `transition` de color en sus
   secciones. Aqui se les añade un desplazamiento minimo, que es lo que
   da la sensacion de respuesta. Nunca escala: escalar un elemento con
   texto lo deja borroso hasta que termina la animacion. */
#main-body .hex-metric,
#main-body .hex-quicklink,
#main-body .hex-access-card {
    transition: background-color var(--t-fast), border-color var(--t-fast),
                color var(--t-fast), transform var(--t-fast);
}

#main-body .hex-metric:hover,
#main-body .hex-quicklink:hover { transform: translateY(-2px); }

#main-body .hex-metric:active,
#main-body .hex-quicklink:active { transform: translateY(0); }

/* La flecha de los enlaces de accion acompaña al cursor. */
#main-body .hex-panel__action i,
#main-body .btn .fa-arrow-right { transition: transform var(--t-fast); }
#main-body .hex-panel__action:hover i,
#main-body .btn:hover .fa-arrow-right { transform: translateX(2px); }

/* Item de la barra lateral: la barra de acento crece en lugar de
   aparecer. El `::before` y su color los define § 08. */
#main-body .sidebar .list-group-item::before {
    transform-origin: center top;
    transition: transform var(--t-fast), opacity var(--t-fast);
}

/* Spinner de carga de las listas: se atenua al entrar en lugar de
   parpadear. */
#tableLoading { animation: hexFade 200ms ease-out both; }

/* --- Excepciones ---------------------------------------------------
   Bloques que NO se animan a la entrada, a proposito:

     - la cabecera y el pie, que estan siempre y moverlos marearia;
     - los modales, que ya traen su propia transicion de Bootstrap y
       encadenar dos da un rebote raro;
     - cualquier cosa dentro de un popover o un tooltip, por lo mismo.
   ------------------------------------------------------------------- */
.modal .card,
.modal .table-container,
.popover .card,
.tooltip .card { animation: none; }
