/* ============================================================
   necROmantic — Modern layout (navbar + hero slider, no sidebar)
   Extends themes/necromantic/css/unknown.css — tokens are inherited.
   ============================================================ */

:root {
    --font-display: "Cinzel", "Alegreya Sans", serif;
    --nav-height: 84px;
    --scrim-hero:
        linear-gradient(0deg, rgba(8, 5, 16, 0.92) 0%, rgba(8, 5, 16, 0.55) 42%, rgba(8, 5, 16, 0.25) 70%, rgba(8, 5, 16, 0.5) 100%);
}

.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.skip-link {
    position: absolute;
    left: 8px;
    top: -60px;
    z-index: 1000;
    background: var(--gold);
    color: var(--text-on-accent);
    padding: 10px 16px;
    border-radius: 10px;
    font-weight: 700;
    transition: top 0.2s ease;
}
.skip-link:focus {
    top: 8px;
    text-decoration: none;
}

/* The base theme (flux.css) locks html/body to a fixed 100vh app-shell
   with overflow:hidden, meant for the old sidebar layout's internal
   scrolling pane. This theme is a normal, page-scrolling document, so
   that mechanic is invalid here and must be fully overridden. */
html.theme-modern-doc {
    height: auto;
    min-height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
}
html.theme-modern-doc body.theme-modern {
    height: auto;
    min-height: 100%;
    display: block;
    overflow: visible;
}

/* Every raw <button> in the base theme gets a generic hand-point icon
   (button::before, flux.css) meant for old CP action buttons. Our nav
   buttons, toggles and dots supply their own icon (or none) explicitly,
   so it must not leak in here. */
body.theme-modern button::before {
    content: none;
}

/* ── Navbar ────────────────────────────────────────────────── */
#site-header-modern {
    position: sticky;
    top: 0;
    z-index: 200;
    background: var(--grad-header);
    box-shadow: var(--shadow-header);
}

.header-modern__bar {
    min-height: var(--nav-height);
    padding: 10px 28px;
    display: flex;
    align-items: center;
    gap: 22px;
}

.header-modern__bar #logo-link {
    display: inline-flex;
    align-items: center;
    gap: 14px;
    text-decoration: none !important;
}
.header-modern__bar #logo-mark {
    width: 54px;
    height: 54px;
    object-fit: contain;
    filter: var(--shadow-logo);
}
.header-modern__bar #logo-text .logo-nec,
.header-modern__bar #logo-text .logo-mantic {
    font-family: var(--font-display);
    font-size: 22px;
    font-weight: 700;
    color: var(--text-logo);
}
.header-modern__bar #logo-text .logo-ro {
    font-family: var(--font-display);
    font-size: 22px;
    font-weight: 900;
    color: var(--gold);
    text-shadow: 0 0 16px var(--alpha-gold-42);
}
.header-modern__bar #logo-text .logo-tagline {
    display: block;
    font-size: 7pt;
    color: var(--text-logo-tagline);
    letter-spacing: 2px;
    text-transform: uppercase;
    margin-top: 3px;
}

#nav-toggle {
    display: none;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 40px;
    height: 40px;
    margin-left: auto;
    border-radius: 10px;
    background: var(--alpha-white-05);
    cursor: pointer;
}
#nav-toggle span {
    display: block;
    width: 20px;
    height: 2px;
    margin: 0 auto;
    background: var(--text-heading2);
    transition: transform 0.25s ease, opacity 0.2s ease;
}
#nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
#nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
#nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

#primary-nav {
    flex: 1;
    display: flex;
    justify-content: center;
}
.primary-nav__list {
    list-style: none;
    display: flex;
    align-items: center;
    gap: 4px;
    margin: 0;
    padding: 0;
}
.primary-nav__item { position: relative; }

.nav-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    border-radius: 12px;
    background: transparent;
    color: var(--text-heading2);
    font-family: var(--font-display);
    font-size: 9.5pt;
    letter-spacing: 0.3px;
    cursor: pointer;
    text-decoration: none !important;
    transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease, transform 0.15s ease;
}
.nav-link i:not(.nav-caret) { color: var(--gold); font-size: 9pt; }
.nav-link:hover,
.nav-link:focus-visible {
    background: var(--alpha-gold-12);
    color: var(--text-link-hover);
    transform: translateY(-1px);
}
.nav-caret { font-size: 7pt; margin-left: 2px; transition: transform 0.2s ease; opacity: 0.8; }
.has-dropdown:hover .nav-caret,
.has-dropdown.is-open .nav-caret { transform: rotate(180deg); }

.dropdown-panel {
    position: absolute;
    /* necROmantic 2026-07-29: pegado al elemento del menu, sin los 8px de separacion que
       habia antes. Esos 8px eran un hueco muerto: el desplegable se abre al pasar el raton,
       y al cruzarlo se salia del area activa y el menu se cerraba solo. */
    top: calc(100%);
    left: 0;
    min-width: 240px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px;
    border-radius: 18px;
    background: var(--grad-sidebar-card);
    box-shadow: var(--shadow-card);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity 0.16s ease, transform 0.16s ease, visibility 0.16s;
    z-index: 210;
}
.dropdown-panel--right { left: auto; right: 0; }
.dropdown-panel__meta {
    padding: 6px 10px 10px;
    margin-bottom: 6px;
    font-size: 8pt;
    color: var(--text-muted);
}
.has-dropdown:hover .dropdown-panel,
.has-dropdown.is-open .dropdown-panel {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}
.dropdown-link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 10px;
    border-radius: 10px;
    color: var(--text-primary);
    font-size: 9pt;
    text-decoration: none !important;
    transition: background 0.15s ease, color 0.15s ease, padding-left 0.15s ease;
}
.dropdown-link i { color: var(--gold); width: 16px; text-align: center; }
.dropdown-link:hover {
    background: var(--alpha-gold-12);
    color: var(--text-link-hover);
    padding-left: 14px;
}

.header-modern__actions {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-shrink: 0;
}

/* necROmantic 2026-07-29: el chip de cuenta tiene que ser un contenedor posicionado.
   Su .dropdown-panel es position:absolute, y sin esto el ancestro posicionado mas cercano
   pasaba a ser #site-header-modern (que es sticky, y sticky cuenta como posicionado). El
   panel se anclaba entonces a la cabecera entera: caia a los 84px del navbar en vez de a los
   60px del boton, 24px mas abajo, y el right:0 de --right lo alineaba al borde de la pagina
   en lugar de al del chip. Los menus de navegacion no lo sufrian porque
   .primary-nav__item ya lleva position: relative. */
.account-chip { position: relative; }

.account-chip__trigger {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 14px;
    border-radius: 999px;
    background: var(--surface-header-account);
    color: var(--text-header-account);
    font-size: 9pt;
    cursor: pointer;
}
.account-chip__trigger i.fa-circle-user { color: var(--gold); font-size: 12pt; }
.account-chip__name { font-weight: 700; color: var(--text-heading2); }

.btn-primary,
.btn-ghost {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    border-radius: 999px;
    font-size: 9pt;
    font-weight: 700;
    letter-spacing: 0.2px;
    text-decoration: none !important;
    transition: transform 0.18s ease, box-shadow 0.22s ease, background 0.22s ease, border-color 0.22s ease;
    white-space: nowrap;
}
.btn-primary {
    background: var(--grad-primary-button);
    color: var(--text-on-accent);
    box-shadow: 0 10px 22px var(--alpha-gold-20);
}
.btn-primary:hover {
    background: var(--grad-primary-button-hover);
    transform: translateY(-2px);
    box-shadow: var(--shadow-button-hover);
    color: var(--text-on-accent-strong);
}
.btn-ghost {
    background: var(--alpha-white-05);
    color: var(--text-heading2);
}
.btn-ghost:hover {
    color: var(--text-link-hover);
    transform: translateY(-2px);
    background: var(--alpha-gold-08);
}
.btn-lg { padding: 14px 26px; font-size: 10.5pt; }

/* ── Full-width content (no sidebar) ──────────────────────── */
#site-content-full {
    width: 100%;
    min-width: 0;
    padding: 18px 28px 0;
}

#site-content-full #content-panel {
    max-width: 1240px;
    width: 100%;
    margin: 4px auto 0;
    padding: 24px 28px;
    background: var(--bg-content);
    border-radius: 26px;
    box-shadow: var(--shadow-content);
    min-height: 0;
}

/* The homepage builds its own hero/sections full-bleed — the module
   pages (account, ranking, item db, ...) keep the card surface above. */
body.is-homepage #site-content-full #content-panel {
    padding: 0;
    background: transparent;
    border: 0;
    box-shadow: none;
}

/* ── Hero slider ───────────────────────────────────────────── */
/* necROmantic 2026-07-29: el carrusel ya no vive dentro de #content-panel (ver header.php
   y main/heroslider.php). Va a sangre y pegado a la barra superior, asi que aqui se le
   quitan el margen negativo con el que antes se escapaba del panel y las esquinas
   redondeadas. Se centra solo y se corta a 1920px en pantallas muy anchas. */
.hero-slider {
    position: relative;
    /* OJO: el <body> de este tema es un contenedor flex en columna, asi que el carrusel es
       un item flex. Con "margin: 0 auto" el margen automatico se come el espacio libre y
       anula el estirado, y como TODO el contenido interior va en position:absolute el ancho
       natural resultante es 0 (carrusel invisible). Por eso hace falta width:100% explicito,
       igual que lo llevan #site-content-full y #content-panel. */
    width: 100%;
    margin: 0 auto;
    max-width: 1920px;
    height: min(74vh, 620px);
    min-height: 380px;
    overflow: hidden;
    border-radius: 0;
    box-shadow: var(--shadow-content);
}

.hero-slider__track { position: relative; width: 100%; height: 100%; }

/* necROmantic 2026-07-30: el cambio de diapositiva pasaba por el fondo de la pagina.
   Habia dos causas. Una: "visibility" cambiaba de valor pero no estaba en la lista de
   transition, asi que se aplicaba de golpe y la saliente desaparecia en el fotograma 0
   mientras la entrante subia de 0 a 1 durante un segundo sobre el fondo desnudo. Dos:
   aunque las dos se fundieran a la vez, en el punto medio ambas estarian al 50% y el
   fondo se colaria por debajo igualmente.
   Solucion: la saliente NO se funde. La marca .is-leaving (la pone modern.js) la deja
   opaca justo debajo mientras la entrante la cubre, y se retira cuando el fundido ya
   ha terminado. Como las imagenes del slider son opacas, en ningun momento hay un
   pixel del fondo a la vista. Si se toca la duracion de aqui hay que tocar tambien
   la opcion "fade" del carrusel en modern.js: las dos deben coincidir. */
.hero-slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    visibility: hidden;
    z-index: 0;
    /* el "0s linear 1s" retrasa el ocultado hasta que acaba el fundido, para que la
       diapositiva siga pintandose mientras dura */
    transition: opacity 1s ease, visibility 0s linear 1s;
}
.hero-slide.is-active {
    opacity: 1;
    visibility: visible;
    z-index: 2;
    transition: opacity 1s ease, visibility 0s;
}
.hero-slide.is-leaving {
    opacity: 1;
    visibility: visible;
    z-index: 1;
    transition: none;
}

.hero-slide img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transform: scale(1.05);
    animation: heroKenBurns 14s ease-in-out infinite alternate;
}
@keyframes heroKenBurns {
    from { transform: scale(1.05) translate(0, 0); }
    to   { transform: scale(1.16) translate(-1.5%, -1.5%); }
}

.hero-slide__scrim {
    position: absolute;
    inset: 0;
    background:
        var(--scrim-hero);
}

.hero-slide__content {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    max-width: 900px;
    margin: 0 auto;
    padding: 0 40px 56px;
    text-align: center;
}

.hero-kicker {
    display: inline-block;
    padding: 6px 14px;
    border-radius: 999px;
    background: var(--grad-silver-chip);
    color: var(--gold);
    font-size: 8pt;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    opacity: 0;
    animation: heroFadeUp 0.8s ease 0.15s forwards;
}

.hero-title {
    font-family: var(--font-display);
    font-size: clamp(26px, 4vw, 46px);
    line-height: 1.12;
    margin: 16px 0 14px;
    color: var(--text-hero-title);
    text-shadow: 0 6px 30px rgba(0,0,0,0.55);
    border: 0;
    padding: 0;
    opacity: 0;
    animation: heroFadeUp 0.8s ease 0.28s forwards;
}

.hero-text {
    max-width: 62ch;
    margin: 0 auto;
    color: var(--text-hero-intro);
    font-size: 11pt;
    opacity: 0;
    animation: heroFadeUp 0.8s ease 0.4s forwards;
}

.hero-cta {
    margin-top: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 14px;
    flex-wrap: wrap;
    opacity: 0;
    animation: heroFadeUp 0.8s ease 0.52s forwards;
}

@keyframes heroFadeUp {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: translateY(0); }
}

.hero-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 5;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--surface-header-account);
    color: var(--text-heading2);
    cursor: pointer;
    backdrop-filter: blur(6px);
    transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.hero-nav:hover { background: var(--alpha-gold-16);  transform: translateY(-50%) scale(1.06); }
.hero-nav--prev { left: 20px; }
.hero-nav--next { right: 20px; }

.hero-dots {
    position: absolute;
    left: 0; right: 0;
    bottom: 18px;
    z-index: 5;
    display: flex;
    justify-content: center;
    gap: 9px;
}
.hero-dot {
    width: 9px; height: 9px;
    border-radius: 50%;
    background: var(--alpha-silver-42);
    cursor: pointer;
    padding: 0;
    transition: background 0.2s ease, transform 0.2s ease, width 0.2s ease;
}
.hero-dot.is-active {
    background: var(--gold);
    width: 24px;
    border-radius: 6px;
    box-shadow: 0 0 12px var(--alpha-gold-42);
}

/* ── Rates strip ───────────────────────────────────────────── */
.rates-strip {
    margin: 22px 0 0;
    padding: 16px 22px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 14px 30px;
    border-radius: 20px;
    background: var(--grad-hero);
    box-shadow: inset 0 1px 0 var(--alpha-white-04);
}
.rates-strip__item {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    font-size: 9.5pt;
    color: var(--text-panel-soft);
}
.rates-strip__item i { color: var(--gold); font-size: 11pt; }
.rates-strip__item strong { color: var(--text-heading2); }

/* ── Generic section blocks ───────────────────────────────── */
.section-block { margin: 46px 0; }
.section-heading { max-width: 720px; margin: 0 auto 26px; text-align: center; }
.section-kicker {
    display: inline-block;
    color: var(--gold);
    font-size: 8pt;
    letter-spacing: 1.6px;
    text-transform: uppercase;
    margin-bottom: 8px;
}
.section-title {
    font-family: var(--font-display);
    font-size: 22px;
    color: var(--text-heading2);
    border: 0;
    padding: 0;
    margin: 0 0 8px;
    text-shadow: 0 0 14px var(--alpha-bronze-24);
}
.section-intro { color: var(--text-muted); font-size: 9.5pt; }
.section-empty { text-align: center; color: var(--text-muted); padding: 20px 0; }

/* ── Feature grid ──────────────────────────────────────────── */
.feature-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 18px;
}
.feature-card {
    padding: 22px;
    border-radius: 22px;
    background: var(--grad-sidebar-card);
    box-shadow: var(--shadow-card);
    transition: transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s ease;
}
.feature-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-card), 0 0 24px var(--alpha-gold-16);
}
.feature-card__icon {
    width: 46px; height: 46px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 14px;
    margin-bottom: 14px;
    background: var(--alpha-gold-12);
    color: var(--gold);
    font-size: 16pt;
    transition: transform 0.25s ease;
}
.feature-card:hover .feature-card__icon { transform: rotate(-6deg) scale(1.08); }
.feature-card__title {
    font-family: var(--font-display);
    font-size: 12pt;
    color: var(--text-heading2);
    border: 0; padding: 0; margin: 0 0 8px;
    text-transform: none;
    letter-spacing: 0;
}
.feature-card__text { color: var(--text-muted); font-size: 9pt; line-height: 1.55; margin: 0; }

/* ── Steps ─────────────────────────────────────────────────── */
.steps-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 18px;
}
.step-card {
    position: relative;
    padding: 24px 22px 22px;
    border-radius: 22px;
    background: var(--alpha-gold-12);
    text-align: center;
}
.step-card__number {
    width: 40px; height: 40px;
    margin: 0 auto 12px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--grad-primary-button);
    color: var(--text-on-accent);
    font-family: var(--font-display);
    font-weight: 900;
    font-size: 13pt;
    box-shadow: 0 8px 20px var(--alpha-gold-24);
}
.step-card__title {
    font-family: var(--font-display);
    font-size: 11pt;
    color: var(--text-heading2);
    border: 0; padding: 0; margin: 0 0 6px;
    text-transform: none;
}
.step-card__text { color: var(--text-muted); font-size: 8.8pt; margin: 0; }

/* ── News grid ─────────────────────────────────────────────── */
.news-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
}
.news-card {
    padding: 20px;
    border-radius: 20px;
    background: var(--bg-content);
    box-shadow: var(--shadow-soft);
}
.news-card__title { font-family: var(--font-display); font-size: 11.5pt; color: var(--text-heading); margin: 0 0 6px; border: 0; padding: 0; }
.news-card__meta { font-size: 7.8pt; color: var(--text-muted); margin-bottom: 8px; }
.news-card__body { font-size: 9pt; color: var(--text-primary); line-height: 1.55; }
.news-card__modified { font-size: 7.5pt; color: var(--text-muted); margin-top: 8px; }
.news-card__link { display: inline-block; margin-top: 10px; font-size: 8.5pt; color: var(--gold); }
.news-card__link:hover { color: var(--text-link-hover); }

/* ── Footer ────────────────────────────────────────────────── */
#site-footer-modern {
    margin: 40px -28px 0;
    padding: 40px 28px 24px;
    background: var(--grad-footer);
}
.footer-modern__grid {
    max-width: 1240px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: 1.4fr repeat(3, 1fr);
    gap: 24px;
}
.footer-modern__col h4 {
    font-family: var(--font-display);
    font-size: 9.5pt;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--gold);
    margin: 0 0 12px;
}
.footer-modern__col a {
    display: block;
    padding: 5px 0;
    color: var(--text-footer);
    font-size: 9pt;
    text-decoration: none !important;
}
.footer-modern__col a:hover { color: var(--text-footer-link); padding-left: 4px; }
.footer-brand {
    font-family: var(--font-display);
    font-size: 17px;
    margin-bottom: 10px;
}
.footer-modern__brand p { color: var(--text-footer); font-size: 8.8pt; line-height: 1.6; max-width: 40ch; }

.footer-modern__bottom {
    max-width: 1240px;
    margin: 28px auto 0;
    padding-top: 18px;
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 8pt;
    color: var(--text-footer);
}
.footer-modern__bottom a { color: var(--text-footer-link); }

/* ── Motion sensitivity ────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    .hero-slide img { animation: none; transform: none; }
    .hero-kicker, .hero-title, .hero-text, .hero-cta { animation: none; opacity: 1; }
    .feature-card, .btn-primary, .btn-ghost, .hero-nav, .news-nav { transition: none; }
}

/* ── Responsive ────────────────────────────────────────────── */
@media (max-width: 1080px) {
    .feature-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .steps-grid { grid-template-columns: 1fr; }
    .news-grid { grid-template-columns: 1fr; }
    .footer-modern__grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 900px) {
    #nav-toggle { display: flex; }
    #primary-nav {
        position: fixed;
        top: var(--nav-height);
        left: 0; right: 0;
        bottom: 0;
        background: var(--bg-header);
        padding: 16px;
        overflow-y: auto;
        transform: translateX(-100%);
        transition: transform 0.25s ease;
        z-index: 199;
        justify-content: flex-start;
    }
    #primary-nav.is-open { transform: translateX(0); }
    .primary-nav__list { flex-direction: column; align-items: stretch; width: 100%; gap: 6px; }
    .nav-link { width: 100%; justify-content: flex-start; }
    .dropdown-panel {
        position: static;
        opacity: 1; visibility: visible; transform: none;
        display: none;
        box-shadow: none;
        margin: 4px 0 4px 14px;
    }
    .has-dropdown.is-open .dropdown-panel { display: flex; }
    .account-chip__name { display: none; }
    .hero-slider { margin: 0; border-radius: 0; } /* necROmantic 2026-07-29: a sangre tambien en movil */
    #site-content-full { padding: 14px 18px 0; }
    .header-modern__bar { padding: 10px 18px; }
}

@media (max-width: 640px) {
    .feature-grid { grid-template-columns: 1fr; }
    .footer-modern__grid { grid-template-columns: 1fr; }
    .hero-cta { flex-direction: column; align-items: stretch; }
    .hero-cta .btn-lg { justify-content: center; }
    #site-footer-modern { margin: 32px -18px 0; padding: 32px 18px 20px; }
}

/* ==========================================================================
   necROmantic 2026-07-28 — Estado del servidor dentro del desplegable
   "Informacion": tres LEDs (login / personajes / mapas) y el numero de
   jugadores conectados ahora mismo.

   El dato lo aporta necromantic_modern_server_status() en header.php, cacheado
   en fichero con el TTL de ServerStatusCache. El contador excluye a los
   vendedores en @autotrade y a los companions @helpme (`online` = 2 en la BD).

   Para revertir: borrar este bloque y el bloque .server-status-mini de
   header.php (el desplegable vuelve a mostrar solo los enlaces).
   ========================================================================== */
.server-status-mini {
    padding: 10px 10px 12px;
    margin-bottom: 8px;
    border-bottom: 1px solid var(--alpha-white-05, rgba(255, 255, 255, 0.06));
}
.server-status-mini__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 10px;
}
.server-status-mini__title {
    font-family: var(--font-display);
    font-size: 8.4pt;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-heading2);
}
.server-status-mini__players {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
    font-size: 8.2pt;
    color: var(--text-muted);
    white-space: nowrap;
}
.server-status-mini__players i { color: var(--gold); font-size: 8pt; }
.server-status-mini__players strong {
    color: var(--gold);
    font-size: 10pt;
    font-weight: 700;
}
.server-status-mini__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.server-status-mini__row {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 8.6pt;
    color: var(--text-primary);
}
.server-status-mini__name { flex: 1 1 auto; }
.server-status-mini__state {
    font-size: 7.8pt;
    color: var(--text-muted);
    white-space: nowrap;
}

/* necROmantic 2026-08-23 — toda la region es un enlace a /character/online/.
   El <a> NO envuelve el bloque: la pagina se pasa por tidy con output-xhtml y ahi un
   <a> no puede contener <div>/<ul>/<li>. Va superpuesto (inset: 0) sobre el contenedor,
   que para eso pasa a position: relative.

   El resalte se pinta sobre el CONTENEDOR (:hover / :focus-within), no sobre el <a>:
   si el fondo lo pusiera el enlace, al estar por encima teñiria el texto de los LEDs.

   Oro de verdad: la rampa --aq-gold-* de themes/necromantic/css/unknown.css (:root).
   El --gold del tema NO vale aqui, que en esta piel es rosa-magenta. */
.server-status-mini--linked {
    position: relative;
    border-radius: 8px;
    transition: background 140ms ease, box-shadow 140ms ease;
}
.server-status-mini__link {
    position: absolute;
    inset: 0;
    z-index: 2;
    border-radius: inherit;
    text-decoration: none;
}
.server-status-mini--linked:hover,
.server-status-mini--linked:focus-within {
    background: linear-gradient(180deg, var(--aq-gold-soft), transparent 78%);
    box-shadow: inset 0 0 0 1px var(--aq-gold-mid), 0 0 14px var(--aq-gold-glow);
}
.server-status-mini--linked:hover .server-status-mini__title,
.server-status-mini--linked:focus-within .server-status-mini__title {
    color: var(--aq-gold-light);
}
.server-status-mini--linked:hover .server-status-mini__players strong,
.server-status-mini--linked:focus-within .server-status-mini__players strong,
.server-status-mini--linked:hover .server-status-mini__players i,
.server-status-mini--linked:focus-within .server-status-mini__players i {
    color: var(--aq-gold-light);
}
.server-status-mini--linked:hover .server-status-mini__players span,
.server-status-mini--linked:focus-within .server-status-mini__players span,
.server-status-mini--linked:hover .server-status-mini__name,
.server-status-mini--linked:focus-within .server-status-mini__name {
    color: var(--aq-gold);
}

@media (prefers-reduced-motion: reduce) {
    .server-status-mini--linked { transition: none; }
}

/* El LED en si: circulo con halo. El "latido" solo se anima si el servidor
   esta arriba, y se desactiva para quien pida menos movimiento. */
.status-led {
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    display: inline-block;
    position: relative;
}
.status-led--up {
    background: #35d07f;
    box-shadow: 0 0 6px 1px rgba(53, 208, 127, 0.75);
    animation: necro-led-pulse 2.4s ease-in-out infinite;
}
.status-led--down {
    background: #e2504a;
    box-shadow: 0 0 6px 1px rgba(226, 80, 74, 0.6);
}
.status-led--up + .server-status-mini__name { color: var(--text-primary); }
.status-led--down ~ .server-status-mini__state { color: #e2504a; }

@keyframes necro-led-pulse {
    0%, 100% { box-shadow: 0 0 5px 1px rgba(53, 208, 127, 0.55); }
    50%      { box-shadow: 0 0 9px 2px rgba(53, 208, 127, 0.95); }
}

@media (prefers-reduced-motion: reduce) {
    .status-led--up { animation: none; }
}

/* ==========================================================================
   necROmantic 2026-07-28 — Bloque "Estado del servidor" de la portada.
   Reutiliza .status-led (definido mas arriba, junto al panel del menu).
   Para revertir: borrar este bloque y la <section class="section-block--status">
   de themes/necromantic-modern/main/index.php.
   ========================================================================== */
.status-grid {
    display: grid;
    grid-template-columns: minmax(200px, 260px) 1fr;
    gap: 18px;
    align-items: stretch;
}
.status-players {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 14px;
    padding: 26px 18px;
    border-radius: 18px;
    background: var(--grad-sidebar-card);
    box-shadow: var(--shadow-card);
    text-align: center;
}
.status-players__ring {
    position: relative;
    width: 104px;
    height: 104px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background:
        radial-gradient(circle at 50% 50%, rgba(53, 208, 127, 0.10), transparent 65%);
    border: 2px solid var(--alpha-gold-42, rgba(214, 178, 96, 0.42));
    box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.28);
}
.status-players__value {
    font-family: var(--font-display);
    font-size: 30pt;
    font-weight: 700;
    line-height: 1;
    color: var(--gold);
    text-shadow: 0 0 18px var(--alpha-gold-42, rgba(214, 178, 96, 0.42));
}
.status-players__label { display: flex; flex-direction: column; gap: 2px; }
.status-players__label strong {
    font-size: 10pt;
    color: var(--text-heading2);
    font-family: var(--font-display);
    letter-spacing: 0.02em;
}
.status-players__label span { font-size: 8.4pt; color: var(--text-muted); }

.status-servers {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.status-card {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px 18px;
    border-radius: 16px;
    background: var(--grad-sidebar-card);
    box-shadow: var(--shadow-card);
    border-left: 3px solid transparent;
    transition: border-color 0.2s ease, transform 0.2s ease;
}
.status-card.is-up { border-left-color: #35d07f; }
.status-card.is-down { border-left-color: #e2504a; }
.status-card:hover { transform: translateX(3px); }
.status-card__icon {
    flex: 0 0 auto;
    width: 34px;
    text-align: center;
    font-size: 15pt;
    color: var(--gold);
}
.status-card__body { flex: 1 1 auto; min-width: 0; }
.status-card__title {
    margin: 0 0 2px;
    font-family: var(--font-display);
    font-size: 11pt;
    color: var(--text-heading2);
}
.status-card__desc { margin: 0; font-size: 8.6pt; color: var(--text-muted); }
.status-card__state {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-size: 8.8pt;
    white-space: nowrap;
    color: var(--text-muted);
}
.status-card.is-up .status-card__state { color: #35d07f; }
.status-card.is-down .status-card__state { color: #e2504a; }

@media (max-width: 720px) {
    .status-grid { grid-template-columns: 1fr; }
    .status-card__desc { display: none; }
}

/* ==========================================================================
   necROmantic 2026-07-28 — Enlaces en las tarjetas de "Tres pasos" y bloque
   de hardware del servidor (portada, debajo de las noticias).
   Revertir: borrar este bloque + la <section class="section-block--hardware">
   y el <a class="step-card__cta"> de themes/necromantic-modern/main/index.php.
   ========================================================================== */
.step-card__cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 14px;
    padding: 9px 16px;
    border-radius: 999px;
    background: var(--alpha-gold-12, rgba(214, 178, 96, 0.12));
    border: 1px solid var(--alpha-gold-42, rgba(214, 178, 96, 0.42));
    color: var(--gold);
    font-size: 8.8pt;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-decoration: none !important;
    transition: background 0.16s ease, transform 0.16s ease, box-shadow 0.16s ease;
}
.step-card__cta:hover {
    background: var(--gold);
    color: var(--text-on-accent);
    transform: translateY(-1px);
    box-shadow: 0 6px 18px var(--alpha-gold-42, rgba(214, 178, 96, 0.42));
}
.step-card__cta i { font-size: 8.4pt; }

.hardware-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 16px;
}
.hardware-card {
    position: relative;
    padding: 22px 18px 20px;
    border-radius: 18px;
    background: var(--grad-sidebar-card);
    box-shadow: var(--shadow-card);
    text-align: center;
    overflow: hidden;
    transition: transform 0.2s ease;
}
.hardware-card::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--gold), transparent);
    opacity: 0.55;
}
.hardware-card:hover { transform: translateY(-3px); }
.hardware-card__icon {
    font-size: 19pt;
    color: var(--gold);
    margin-bottom: 12px;
    display: block;
}
.hardware-card__value {
    font-family: var(--font-display);
    font-size: 17pt;
    font-weight: 700;
    line-height: 1.1;
    color: var(--text-heading2);
}
.hardware-card__label {
    font-size: 9pt;
    color: var(--gold);
    margin-top: 3px;
    letter-spacing: 0.02em;
}
.hardware-card__note {
    margin: 9px 0 0;
    font-size: 8.2pt;
    line-height: 1.5;
    color: var(--text-muted);
}
.hardware-foot {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 18px auto 0;
    max-width: 760px;
    font-size: 8.8pt;
    line-height: 1.6;
    color: var(--text-muted);
    text-align: left;
}
.hardware-foot i { color: #35d07f; margin-top: 3px; flex: 0 0 auto; }

@media (max-width: 560px) {
    .hardware-foot { text-align: center; flex-direction: column; align-items: center; }
    .hardware-foot i { margin-top: 0; }
}

/* ==========================================================================
   necROmantic 2026-07-28 — Carrusel de noticias de la portada.
   Mismo comportamiento que el slider principal (initCarousel en modern.js).
   Las diapositivas se apilan en la MISMA celda de grid: asi el contenedor
   adopta la altura de la noticia mas larga y no pega saltos al pasar de una
   a otra, que es el problema clasico de hacerlo con position:absolute.
   ========================================================================== */
.news-slider { position: relative; }
.news-slider__track {
    display: grid;
    border-radius: 18px;
    background: var(--grad-sidebar-card);
    box-shadow: var(--shadow-card);
    overflow: hidden;
}
.news-slide {
    grid-area: 1 / 1;
    padding: 28px 74px;
    opacity: 0;
    visibility: hidden;
    transform: translateY(6px);
    transition: opacity 0.35s ease, transform 0.35s ease, visibility 0.35s;
    pointer-events: none;
}
.news-slide.is-active {
    opacity: 1;
    visibility: visible;
    transform: none;
    pointer-events: auto;
}
.news-slide__meta {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 8.2pt;
    color: var(--text-muted);
    margin-bottom: 10px;
}
.news-slide__meta i { color: var(--gold); }
.news-slide__author::before { content: "·"; margin-right: 9px; }
.news-slide__title {
    margin: 0 0 12px;
    font-family: var(--font-display);
    font-size: 15pt;
    line-height: 1.25;
    color: var(--text-heading2);
}
/* necROmantic 2026-08-02: las diapositivas se apilan en la MISMA celda de grid, asi que la
   altura del carrusel es la de la noticia mas larga -- y esa altura la paga la portada
   entera, aunque se este viendo una noticia corta. Con un articulo de fondo (la guia de
   mercenarios pasa de 19 KB) la portada se estiraba varias pantallas. El cuerpo se acota
   aqui y hace su propio scroll: las noticias cortas ni se enteran (no llegan al tope) y las
   largas se leen enteras sin deformar la portada. El articulo completo sigue estando en
   /news/, donde no hay tope ninguno. */
.news-slide__body {
    font-size: 9.4pt;
    line-height: 1.65;
    color: var(--text-primary);
    max-height: min(560px, 62vh);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: var(--alpha-bronze-24) transparent;
    /* Aire a la derecha para que el texto no quede pegado a la barra de scroll. */
    padding-right: 6px;
}
.news-slide__body::-webkit-scrollbar { width: 8px; }
.news-slide__body::-webkit-scrollbar-track { background: transparent; }
.news-slide__body::-webkit-scrollbar-thumb {
    background: var(--alpha-bronze-24);
    border-radius: 8px;
}
.news-slide__body p:last-child { margin-bottom: 0; }
.news-slide__body img { max-width: 100%; height: auto; border-radius: 10px; }
.news-slide__modified { margin-top: 10px; font-size: 7.8pt; color: var(--text-muted); }
.news-slide__link {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-top: 14px;
    color: var(--gold);
    font-size: 8.8pt;
    font-weight: 600;
    text-decoration: none !important;
}
.news-slide__link:hover { text-decoration: underline !important; }

/* Flechas: mismas que las del slider principal.
   IMPORTANTE: el :hover TIENE que repetir el translateY(-50%). flux.css trae un
   `button:hover { transform: translateY(-1px) }` global que, si aqui no se declara
   transform, SUSTITUYE al centrado de la regla base y tira la flecha hacia abajo
   media altura. .hero-nav ya lo resolvia asi; esto solo replica su solucion. */
.news-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 5;
    width: 44px;
    height: 44px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--surface-header-account);
    color: var(--text-heading2);
    cursor: pointer;
    backdrop-filter: blur(6px);
    transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.news-nav:hover {
    background: var(--alpha-gold-16);
    transform: translateY(-50%) scale(1.06);
}
.news-nav--prev { left: 14px; }
.news-nav--next { right: 14px; }

.news-dots {
    display: flex;
    justify-content: center;
    gap: 8px;
    margin-top: 16px;
    flex-wrap: wrap;
}
.news-dot {
    width: 9px;
    height: 9px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--alpha-white-05, rgba(255, 255, 255, 0.22));
    cursor: pointer;
    transition: background 0.16s ease, transform 0.16s ease, width 0.16s ease;
}
.news-dot:hover { background: var(--alpha-gold-42, rgba(214, 178, 96, 0.42)); }
.news-dot.is-active {
    width: 22px;
    border-radius: 999px;
    background: var(--gold);
}

@media (max-width: 720px) {
    .news-slide { padding: 22px 56px; }
    .news-nav { width: 38px; height: 38px; }
    .news-nav--prev { left: 6px; }
    .news-nav--next { right: 6px; }
}

/* ── Pie anclado al fondo del viewport ─────────────────────────
   En paginas con poco contenido (un listado vacio, por ejemplo) el
   pie subia hasta quedar colgado justo debajo de la tarjeta y
   dejaba media pantalla vacia por debajo. El documento pasa a ser
   una columna flexible de altura completa y el margen automatico
   del pie absorbe el espacio sobrante, sin estirar la tarjeta.   */
html.theme-modern-doc body.theme-modern {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
}

#site-content-full {
    display: flex;
    flex-direction: column;
    flex: 1 0 auto;
}

/* El hueco entre la tarjeta y el pie lo pone ahora el contenido:
   asi el margen superior del pie queda libre para el 'auto'.     */
#site-content-full #content-panel { margin-bottom: 40px; }
#site-footer-modern { margin-top: auto; }

@media (max-width: 640px) {
    #site-content-full #content-panel { margin-bottom: 32px; }
    #site-footer-modern { margin-top: auto; }
}

/* ══════════════════════════════════════════════════════════════
   necROmantic 2026-07-30 — Barra superior mas compacta
   Con "Cuenta" fuera de la barra y "Cómo se entra aquí" dentro de Información
   quedan menos elementos, pero aun asi se aprieta todo un poco para que la
   navegacion no se parta en pantallas de portatil.
   ══════════════════════════════════════════════════════════════ */
:root { --nav-height: 66px; }              /* antes 84px */

.header-modern__bar {
    min-height: var(--nav-height);
    padding: 6px 20px;                     /* antes 10px 28px */
    gap: 14px;                             /* antes 22px */
}

/* Logo: mas pequeno y sin el eslogan, que era la linea que mas alto anadia. */
.header-modern__bar #logo-mark { width: 42px; height: 42px; }
.header-modern__bar #logo-link { gap: 10px; }
.header-modern__bar #logo-text .logo-nec,
.header-modern__bar #logo-text .logo-mantic,
.header-modern__bar #logo-text .logo-ro { font-size: 18px; }
.header-modern__bar #logo-text .logo-tagline { display: none; }

/* Enlaces de navegacion: menos aire horizontal y letra algo menor. */
.primary-nav__list { gap: 2px; }
.nav-link {
    padding: 8px 10px;
    font-size: 9pt;
    border-radius: 10px;
}
.nav-link i:not(.nav-caret) { font-size: 8.5pt; }
.nav-caret { font-size: 6.5pt; }

/* El chip de cuenta, en linea con el resto. */
.account-chip__trigger { padding: 7px 12px; font-size: 8.5pt; }
.account-chip__trigger i.fa-circle-user { font-size: 11pt; }

/* ── A 1300px o menos: fuera el logo ──────────────────────────
   Es el elemento que mas ancho ocupa y el unico prescindible: el icono de
   "Inicio" del menu ya lleva a la portada. */
@media (max-width: 1300px) {
    /* Tiene que ser .header-modern__bar #logo-link, no solo #logo-link: la regla base usa
       clase + id y es mas especifica, asi que ganaria aunque este fuera del media query. */
    .header-modern__bar #logo-link { display: none; }
    .header-modern__bar { padding: 6px 14px; gap: 10px; }
    #primary-nav { justify-content: flex-start; }
    .nav-link { padding: 8px 8px; }
}

/* ══════════════════════════════════════════════════════════════
   necROmantic 2026-08-05 — Página de acceso
   Aqui vivia un parche de 60 lineas que sacaba a .generic-form-table del modelo
   de tabla y lo centraba todo (`body.page-account-login #content-panel {
   text-align: center }`), porque la plantilla compartida de themes/default/
   pintaba el acceso como una tabla de etiquetas y campos.
   Ya no: themes/necromantic/account/login.php es un override propio con el
   componente .lgn (unknown.css), asi que el parche sobraba — y de hecho estorbaba,
   porque el centrado heredado alcanzaba a las etiquetas, a las pistas y a la
   columna de ayuda. La pagina se estiliza entera desde su componente.
   ══════════════════════════════════════════════════════════════ */

/* ==========================================================================
   necROmantic 2026-07-30 — Widget "Quien esta detras" de la portada.
   Pareja del contenido de /sobre-mi/ (tema padre, componente .about-*). Aqui
   solo esta la version compacta de portada. Sin bordes: el bloque se separa
   con fondo y sombra, como el resto del sitio.
   ========================================================================== */
.about-widget {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 24px 26px;
    border-radius: 22px;
    background: var(--grad-hero);
    box-shadow: var(--shadow-card), inset 0 1px 0 var(--alpha-white-05);
}

.about-widget__mark {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--alpha-gold-12);
    color: var(--gold);
    font-size: 17pt;
    box-shadow: 0 0 22px var(--alpha-gold-16), inset 0 1px 0 var(--alpha-white-06);
}

.about-widget__body { min-width: 0; }

.about-widget__title {
    /* El .section-kicker de encima ya trae su propio margin-bottom: aqui no se suma otro. */
    margin: 0 0 8px;
    font-family: var(--font-display);
    font-size: 20px;
    line-height: 1.15;
    color: var(--text-hero-title);
    border: 0;
    padding: 0;
}

.about-widget__text {
    margin: 0;
    max-width: 78ch;
    font-size: 9.4pt;
    line-height: 1.7;
    color: var(--text-hero-intro);
}

.about-widget__text strong { color: var(--text-heading2); }

.about-widget__cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    /* Hermano del cuerpo: se va al hueco de la derecha del panel. */
    flex: 0 0 auto;
    margin-left: auto;
    padding: 9px 18px;
    border-radius: 999px;
    background: var(--alpha-gold-12);
    color: var(--gold);
    font-size: 8.8pt;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-decoration: none !important;
    box-shadow: inset 0 0 0 1px var(--alpha-gold-42);
    transition: background 0.16s ease, transform 0.16s ease, box-shadow 0.16s ease;
}

.about-widget__cta:hover {
    background: var(--gold);
    color: var(--text-on-accent);
    transform: translateY(-1px);
    box-shadow: 0 6px 18px var(--alpha-gold-42);
}

.about-widget__cta i { font-size: 8.4pt; }

@media (max-width: 560px) {
    .about-widget { flex-direction: column; align-items: flex-start; gap: 14px; padding: 20px; }
    .about-widget__cta { margin-left: 0; }
}

/* ══════════════════════════════════════════════════════════════
   necROmantic 2026-08-01 — Rework del menú de la barra
   ══════════════════════════════════════════════════════════════
   Tres problemas de fondo:

   1. NO SE VEÍA DÓNDE ESTABAS. La barra no marcaba la sección actual, así que con
      siete categorías había que mirar la URL o el título para orientarse. Ahora el
      enlace activo lleva un filo inferior y fondo propio, y su categoría padre también
      se marca aunque el desplegable esté cerrado (el header pone .is-current y
      .has-current).
   2. TODO SE MOVÍA AL SEÑALAR: los enlaces subían 1px y los del desplegable se
      desplazaban 4px a la derecha. Fuera: ahora solo se iluminan. Un menú que se mueve
      bajo el cursor obliga a recolocar el ojo en cada pasada.
   3. El desplegable de las últimas categorías se salía por la derecha de la ventana.
      Se alinean al borde derecho las dos últimas.
   ══════════════════════════════════════════════════════════════ */

.nav-link {
    position: relative;
    font-size: 0.86rem;
    border: 1px solid transparent;
    transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

/* Sin transform: solo luz. */
.nav-link:hover,
.nav-link:focus-visible {
    background: var(--alpha-gold-12);
    border-color: var(--alpha-gold-24, var(--alpha-gold-12));
    color: var(--text-link-hover);
    transform: none;
}

/* --- Sección actual --- */

.nav-link.is-current {
    background: var(--alpha-gold-12);
    color: var(--text-link-hover);
}

/* Filo inferior: la marca de "estás aquí". Se dibuja con ::after para no alterar la
   caja del enlace y que no baile nada al activarse. */
.nav-link.is-current::after {
    content: "";
    position: absolute;
    left: 14px;
    right: 14px;
    bottom: 3px;
    height: 2px;
    border-radius: 2px;
    background: var(--gold);
}

.nav-link.is-current i:not(.nav-caret) { color: var(--text-link-hover); }

/* Una categoría cuyo desplegable contiene la página actual se marca aunque esté
   cerrada: si no, al entrar en "Objetos" la barra no decía nada. */
.has-dropdown.has-current > .nav-link { color: var(--text-link-hover); }

/* --- Desplegable --- */

.dropdown-panel {
    min-width: 250px;
    max-width: min(320px, calc(100vw - 32px));
    padding: 8px;
    border: 1px solid var(--alpha-gold-12);
}

/* Las dos últimas categorías abren hacia la izquierda o se salen de la ventana. */
.primary-nav__item:nth-last-child(-n+2) .dropdown-panel { left: auto; right: 0; }

/* Punta que ancla el panel a su botón: sin ella el desplegable flota suelto. */
.dropdown-panel::before {
    content: "";
    position: absolute;
    top: -5px;
    left: 22px;
    width: 10px;
    height: 10px;
    transform: rotate(45deg);
    background: var(--grad-sidebar-card);
    border-left: 1px solid var(--alpha-gold-12);
    border-top: 1px solid var(--alpha-gold-12);
}

.primary-nav__item:nth-last-child(-n+2) .dropdown-panel::before { left: auto; right: 22px; }

/* necROmantic 2026-09-07: el interruptor que js/modern.js le pone a los grupos cuya
   cabecera es un enlace SOLO existe en móvil. En escritorio el submenú se abre al señalar
   y el botón sería un mando de más; se declara oculto aquí, fuera de toda media query,
   para que el estado por omisión sea "no está" y solo lo encienda el bloque de 900 px. */
.dropdown-group__toggle { display: none; }

/* necROmantic 2026-09-07: y el del chip de cuenta, igual. La regla de arriba solo cubre
   las categorías de la barra (.primary-nav__item), así que el panel del chip —que también
   cuelga del borde derecho— dibujaba su punta a 22 px del borde IZQUIERDO: un rombo suelto
   en mitad del panel, apuntando a nada. Se ve en escritorio y en móvil. */
.account-chip .dropdown-panel::before { left: auto; right: 22px; }

.dropdown-panel__title {
    margin: 2px 0 6px;
    padding: 4px 10px;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.dropdown-link {
    font-size: 0.85rem;
    border: 1px solid transparent;
    /* Sin padding-left en el hover: desplazaba el texto bajo el cursor. */
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.dropdown-link:hover,
.dropdown-link:focus-visible {
    background: var(--alpha-gold-12);
    border-color: var(--alpha-gold-12);
    color: var(--text-link-hover);
    padding-left: 10px;
}

.dropdown-link.is-current {
    background: var(--alpha-gold-12);
    color: var(--text-link-hover);
}

/* Marca lateral en la entrada activa del desplegable. */
.dropdown-link.is-current::before {
    content: "";
    position: absolute;
    left: 2px;
    top: 50%;
    width: 3px;
    height: 16px;
    margin-top: -8px;
    border-radius: 2px;
    background: var(--gold);
}

.dropdown-link { position: relative; }

@media (prefers-reduced-motion: reduce) {
    .nav-link,
    .dropdown-link,
    .dropdown-panel { transition: none; }
    .nav-caret { transition: none; }
}

/* ══════════════════════════════════════════════════════════════
   necROmantic 2026-08-01 — Zona de acciones de la barra
   ══════════════════════════════════════════════════════════════
   El chip de cuenta era una pastilla plana: sin borde, sin estado al señalar (no había
   NI UNA regla :hover para .account-chip__trigger), sin marca de abierto y con un icono
   genérico. Y sin sesión, "Entrar" y "Crear cuenta" vivían escondidas dentro de ese
   desplegable — las dos únicas cosas que un visitante nuevo necesita, a un clic y sin
   ninguna pista de que estaban ahí.

   Ahora: sin sesión salen como botones (el de entrar destacado); con sesión, el chip
   lleva la imagen de cuenta del jugador —la misma que subió en su ficha—, borde propio
   y estados de señalado, foco y abierto.
   ══════════════════════════════════════════════════════════════ */

.header-modern__actions { gap: 8px; }

/* --- Botones de la barra (sin sesión) --- */

.hdr-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border: 1px solid var(--alpha-gold-24, rgba(223, 160, 198, 0.24));
    border-radius: 999px;
    color: var(--text-heading2);
    font-family: var(--font-display);
    font-size: 0.84rem;
    font-weight: 600;
    white-space: nowrap;
    text-decoration: none !important;
    transition: background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}

.hdr-btn i { color: var(--gold); font-size: 0.82rem; }

.hdr-btn:hover,
.hdr-btn:focus-visible {
    background: var(--alpha-gold-12);
    border-color: var(--gold);
    color: var(--text-link-hover);
}

/* El de entrar manda: relleno sólido para que se distinga del secundario de un vistazo. */
.hdr-btn--primary {
    background: var(--gold);
    border-color: var(--gold);
    color: var(--bg-content);
}

.hdr-btn--primary i { color: var(--bg-content); }

.hdr-btn--primary:hover,
.hdr-btn--primary:focus-visible {
    background: var(--gold);
    color: var(--bg-content);
    filter: brightness(1.1);
}

/* --- Chip de cuenta (con sesión) --- */

.account-chip__trigger {
    gap: 10px;
    padding: 6px 14px 6px 6px;
    border: 1px solid var(--alpha-gold-24, rgba(223, 160, 198, 0.24));
    font-size: 0.84rem;
    transition: background 0.18s ease, border-color 0.18s ease;
}

.account-chip__trigger:hover,
.account-chip__trigger:focus-visible,
.account-chip.is-open .account-chip__trigger {
    background: var(--alpha-gold-12);
    border-color: var(--gold);
}

/* La imagen de cuenta, o la inicial si no ha subido ninguna. */
.account-chip__avatar {
    width: 30px;
    height: 30px;
    flex: 0 0 auto;
    border-radius: 50%;
    object-fit: cover;
    display: block;
}

.account-chip__avatar--letter {
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(150deg, var(--accent-purple), var(--gold));
    color: var(--bg-content);
    font-family: var(--font-display);
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1;
}

.account-chip__name {
    font-weight: 700;
    color: var(--text-heading2);
    max-width: 16ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 1080px) {
    /* El texto de los botones sobra antes que el icono: se queda el icono solo. */
    .hdr-btn span { display: none; }
    .hdr-btn { padding: 9px 12px; }
}

@media (prefers-reduced-motion: reduce) {
    .hdr-btn,
    .account-chip__trigger { transition: none; }
}

/* ══════════════════════════════════════════════════════════════
   necROmantic 2026-08-01 — Submenús anidados en los desplegables
   ══════════════════════════════════════════════════════════════
   "Información" había crecido a quince entradas sueltas en una sola columna. Ahora tres
   de ellas son grupos (Mercado, Base de datos, Rankings) que abren un panel lateral.

   Se despliegan por CSS, con :hover y :focus-within — sin JavaScript. El JS de la barra
   solo gobierna el primer nivel, y el :focus-within hace que funcione con teclado: al
   tabular dentro del grupo, el panel se queda abierto.
   ══════════════════════════════════════════════════════════════ */

.dropdown-group { position: relative; }

.dropdown-link--group {
    width: 100%;
    background: transparent;
    border: 1px solid transparent;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

.dropdown-group__caret {
    margin-left: auto;
    font-size: 0.62rem;
    opacity: 0.7;
    transition: transform 0.18s ease;
}

.dropdown-group:hover > .dropdown-link--group,
.dropdown-group:focus-within > .dropdown-link--group {
    background: var(--alpha-gold-12);
    border-color: var(--alpha-gold-12);
    color: var(--text-link-hover);
}

.dropdown-group:hover .dropdown-group__caret,
.dropdown-group:focus-within .dropdown-group__caret { transform: translateX(2px); }

/* Un desplegable con grupos NO se alinea al borde derecho aunque sea de las últimas
   categorías: necesita el espacio de su derecha para el submenú. Pisa a la regla
   :nth-last-child(-n+2) de más arriba.
   La clase la pone el header cuando la categoría tiene grupos. Se hizo así, y no con
   :has(.dropdown-group), para no jugarse la colocación a que el navegador soporte :has():
   si fallara, el panel se quedaría pegado al borde derecho y el submenú se saldría de la
   pantalla. Una clase la entiende cualquier navegador. */
.primary-nav__item:nth-last-child(-n+2) .dropdown-panel--groups {
    left: 0;
    right: auto;
}

.primary-nav__item:nth-last-child(-n+2) .dropdown-panel--groups::before {
    left: 22px;
    right: auto;
}

/* Panel lateral: sale por la DERECHA del grupo, que es hacia donde se avanza al leer.
   Para que quepa, el desplegable que contiene grupos se ancla por su izquierda al botón
   (regla de abajo) en vez de al borde derecho: así queda toda la mitad derecha libre
   para el submenú. */
.dropdown-subpanel {
    position: absolute;
    top: -8px;
    left: calc(100% + 6px);
    min-width: 220px;
    max-width: min(280px, calc(100vw - 32px));
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 8px;
    border: 1px solid var(--alpha-gold-12);
    border-radius: 16px;
    background: var(--grad-sidebar-card);
    box-shadow: var(--shadow-card);
    opacity: 0;
    visibility: hidden;
    transform: translateX(-6px);
    transition: opacity 0.16s ease, transform 0.16s ease, visibility 0.16s;
    z-index: 220;
}

.dropdown-group:hover > .dropdown-subpanel,
.dropdown-group:focus-within > .dropdown-subpanel {
    opacity: 1;
    visibility: visible;
    transform: translateX(0);
}

/* Una categoría cuya página actual vive dentro de un grupo también se marca. */
.dropdown-group.has-current > .dropdown-link--group { color: var(--text-link-hover); }

/* necROmantic 2026-08-07 (usuario) — el submenú de "Mi cuenta" abre hacia la IZQUIERDA.
   El desplegable del chip de cuenta está anclado al borde derecho de la ventana
   (.dropdown-panel--right), así que a su derecha no queda sitio: un submenú lateral como
   el de "Información" se saldría de la pantalla. Aquí se invierte todo lo que tiene lado:
   de qué borde cuelga el panel, hacia dónde entra al aparecer y hacia dónde apunta y se
   desplaza la flecha del grupo (que además es un chevron-left en el HTML).

   La clase va en el grupo y no en el subpanel a propósito: una sola marca gobierna las
   tres cosas, y el HTML del submenú queda idéntico al de los demás. */
.dropdown-group--left > .dropdown-subpanel {
    left: auto;
    right: calc(100% + 6px);
    transform: translateX(6px);
}

.dropdown-group--left:hover > .dropdown-subpanel,
.dropdown-group--left:focus-within > .dropdown-subpanel { transform: translateX(0); }

.dropdown-group--left:hover .dropdown-group__caret,
.dropdown-group--left:focus-within .dropdown-group__caret { transform: translateX(-2px); }

/* En pantallas estrechas no hay sitio a los lados: el grupo se despliega hacia abajo,
   dentro del propio panel, en lugar de volar fuera de la ventana. */
@media (max-width: 860px) {
    .dropdown-subpanel {
        position: static;
        min-width: 0;
        max-width: none;
        margin: 4px 0 4px 14px;
        padding: 4px 0 4px 10px;
        border: 0;
        border-left: 1px solid var(--alpha-gold-12);
        border-radius: 0;
        background: transparent;
        box-shadow: none;
        transform: none;
        display: none;
    }
    .dropdown-group:hover > .dropdown-subpanel,
    .dropdown-group:focus-within > .dropdown-subpanel { display: flex; }
    .dropdown-group__caret { transform: rotate(90deg); }

    /* Aquí ya no hay izquierda ni derecha: el submenú se despliega hacia abajo dentro del
       propio panel, así que el desplazamiento lateral sobra. Hace falta decirlo porque las
       reglas de .dropdown-group--left son más específicas que el transform: none de arriba.
       La flecha gira al revés que la de los otros grupos: es un chevron-left, y girándolo
       90° como los demás quedaría apuntando hacia arriba en vez de hacia abajo. */
    .dropdown-group--left > .dropdown-subpanel,
    .dropdown-group--left:hover > .dropdown-subpanel,
    .dropdown-group--left:focus-within > .dropdown-subpanel { transform: none; }
    .dropdown-group--left .dropdown-group__caret,
    .dropdown-group--left:hover .dropdown-group__caret,
    .dropdown-group--left:focus-within .dropdown-group__caret { transform: rotate(-90deg); }
}

@media (prefers-reduced-motion: reduce) {
    .dropdown-subpanel,
    .dropdown-group__caret { transition: none; }
}

/* ============================================================================
   Conmutador de idioma
   necROmantic 2026-08-02: parte del proyecto de web bilingüe. Son enlaces, no un
   <select>, para que funcionen sin JavaScript y se puedan abrir en otra pestaña.
   Usa los mismos tokens que .hdr-btn para que no parezca un añadido.
   ============================================================================ */

.lang-switch {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 2px;
    border: 1px solid var(--alpha-gold-24, rgba(223, 160, 198, 0.24));
    border-radius: 999px;
}

.lang-switch__opt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    padding: 5px 9px;
    border-radius: 999px;
    color: var(--text-heading2);
    font-family: var(--font-display);
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    line-height: 1;
    text-decoration: none !important;
    transition: background 0.18s ease, color 0.18s ease;
}

.lang-switch__opt:hover,
.lang-switch__opt:focus-visible {
    background: var(--alpha-gold-12);
    color: var(--text-link-hover);
}

/* El idioma activo va relleno: se distingue de un vistazo cuál de los dos se está viendo. */
.lang-switch__opt.is-current {
    background: var(--gold);
    color: var(--bg-content);
    cursor: default;
}

/* En pantallas estrechas la barra ya va justa: el selector se queda, pero más compacto. */
@media (max-width: 720px) {
    .lang-switch__opt { min-width: 28px; padding: 5px 7px; font-size: 0.7rem; }
}

/* Aviso de contenido sin traducir. necROmantic 2026-08-02. */
.news-card__untranslated,
.cms-page__untranslated {
    margin: 0 0 14px;
    padding: 8px 12px;
    border-left: 3px solid var(--gold);
    background: var(--alpha-gold-12);
    border-radius: 0 6px 6px 0;
    font-size: 0.82rem;
    opacity: 0.9;
}

/* ============================================================================
   necROmantic 2026-08-05 · Avisos de "entra un jugador" + refresco en vivo
   ============================================================================
   Segunda version, por peticion del usuario: "que se queden en la zona superior
   acumulados con una X de cierre hasta que el visitante lo cierre o que duren 60
   segundos, que no desaparezcan con Alpha de forma automatica solo por haber
   llegado arriba".

   O sea que ya NO son globos que viajan y se desvanecen al llegar arriba: son
   avisos que se apilan en la esquina superior, se leen con calma y se van solo
   cuando alguien los cierra o cuando cumplen su minuto. La animacion que queda es
   la de ENTRADA (aparecer) y la de SALIDA (al cerrarse), nunca una desaparicion
   por el mero hecho de haber subido.

   El contenedor no captura clics (pointer-events:none) pero cada aviso SI
   (pointer-events:auto): asi la columna flota sobre la pagina sin robar un solo
   clic a lo que haya debajo, y la X sigue siendo pulsable. */

.jbub {
    position: fixed;
    left: 18px;
    top: calc(var(--nav-height) + 12px);
    width: 300px;
    max-height: calc(100vh - var(--nav-height) - 24px);
    z-index: 900;
    pointer-events: none;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    overflow: hidden;
}

.jbub__item {
    pointer-events: auto;
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 8px 10px 8px 14px;
    border-radius: 999px;
    border: 1px solid rgba(212, 175, 55, 0.45);
    background: rgba(18, 12, 28, 0.92);
    backdrop-filter: blur(4px);
    color: #f3ead8;
    font-size: 9.5pt;
    line-height: 1.25;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
    /* Solo ENTRADA. Al terminar se queda quieto y opaco hasta que lo cierren. */
    animation: jbub-in 260ms ease-out;
}

/* Estado de salida: lo pone el JS al cerrar (X o los 60 s) y quita el nodo cuando
   acaba la transicion. Es la UNICA via por la que un aviso se desvanece. */
.jbub__item--out {
    opacity: 0;
    transform: translateX(-18px);
    transition: opacity 220ms ease-in, transform 220ms ease-in;
}

@keyframes jbub-in {
    from { opacity: 0; transform: translateX(-18px); }
    to   { opacity: 1; transform: translateX(0); }
}

/* Icono de la clase, a la izquierda del nombre. Tamano fijo y flex-shrink:0 para que
   un icono que tarde en cargar no descuadre la fila ni la encoja. */
.jbub__icon {
    width: 26px;
    height: 26px;
    flex: 0 0 26px;
    object-fit: contain;
    image-rendering: pixelated;   /* son sprites; el suavizado los emborrona */
}

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

.jbub__name {
    font-family: var(--font-display);
    color: var(--gold, #d4af37);
    font-weight: 700;
}

/* El nivel, discreto: informa sin competir con el nombre. */
.jbub__lv {
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 999px;
    background: rgba(212, 175, 55, 0.16);
    color: #e9dcc0;
    font-size: 8pt;
    font-weight: 600;
    letter-spacing: 0.02em;
}

/* La X. Boton de verdad (<button>), no un span con onclick: asi entra en el orden de
   tabulacion, responde a Enter y Espacio y los lectores de pantalla lo anuncian. */
.jbub__close {
    flex: 0 0 auto;
    width: 24px;
    height: 24px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: #b9ac93;
    font-size: 13pt;
    line-height: 1;
    cursor: pointer;
    transition: background-color 140ms ease, color 140ms ease;
}

.jbub__close:hover,
.jbub__close:focus-visible {
    background: rgba(212, 175, 55, 0.18);
    color: #f3ead8;
}

/* En pantallas estrechas el lateral estorba: se centra y se estrecha. */
@media (max-width: 720px) {
    .jbub {
        left: 50%;
        transform: translateX(-50%);
        width: min(84vw, 320px);
        align-items: stretch;
    }
}

/* Quien pide menos movimiento no recibe deslizamientos. Los avisos siguen
   apareciendo, apilandose y cerrandose igual: lo que se quita es el viaje. */
@media (prefers-reduced-motion: reduce) {
    .jbub__item {
        animation: none;
    }
    .jbub__item--out {
        transform: none;
        transition: opacity 160ms linear;
    }
}

/* Marca discreta de "esto se acaba de actualizar solo", para que un numero que
   cambia sin que nadie toque nada no parezca un error de lectura. */
.is-live-bump {
    animation: live-bump 620ms ease-out;
}

@keyframes live-bump {
    0%   { transform: scale(1);    }
    35%  { transform: scale(1.18); }
    100% { transform: scale(1);    }
}

@media (prefers-reduced-motion: reduce) {
    .is-live-bump { animation: none; }
}

/* ============================================================================
 * necROmantic 2026-08-07 (usuario) — "Personajes" despliega la lista de personajes
 * ============================================================================
 * Tercer nivel del menú: chip de cuenta → "Mi cuenta" → "Personajes" → cada personaje,
 * con su icono de clase, su nombre y su nivel base.
 *
 * Reutiliza .dropdown-group--left tal cual, así que hereda de dónde cuelga, hacia dónde
 * entra y hacia dónde apunta la flecha. Aquí solo va lo que es propio de una fila de
 * personaje: que quepan tres cosas en una línea sin apretarse.
 *
 * El nivel se alinea a la derecha con margin-left:auto y NO con un ancho fijo, porque
 * "Nv. 9" y "Nv. 175" no miden lo mismo y una columna fija dejaría a uno de los dos
 * descolocado. */
.dropdown-subpanel--chars { min-width: 240px; }

/* ============================================================================
 * TERCER NIVEL: las secciones de cada personaje (necROmantic 2026-08-29)
 * ============================================================================
 * Peticion del usuario: desde el nodo del personaje, ir directo a cada seccion de su ficha.
 *
 * Casi todo lo hereda: el grupo lleva tambien `--left`, asi que las reglas de arriba ya lo
 * despliegan hacia la izquierda, con su transicion y su flecha. Aqui solo va lo que cambia por
 * estar UN NIVEL MAS ADENTRO.
 *
 * La fila del personaje pasa a ser cabecera de grupo y por eso necesita sitio para la flecha: sin
 * el `padding-right` el chevron se monta sobre el "Nv. 119".
 */
.dropdown-group--char > .dropdown-link--char { padding-right: 22px; }

/* La flecha, vertical al centro de una fila que es mas alta que las demas (icono de clase de
   24 px). El `position: absolute` cuelga del enlace, que ya es el contexto de posicionamiento de
   los carets del resto del menu. */
.dropdown-group--char > .dropdown-link--char .dropdown-group__caret {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
}

.dropdown-group--char:hover > .dropdown-link--char .dropdown-group__caret,
.dropdown-group--char:focus-within > .dropdown-link--char .dropdown-group__caret {
    transform: translateY(-50%) translateX(-2px);
}

/* Nueve secciones entran de sobra en una columna; se le pone tope de altura por si algun dia son
   mas, para que el panel no se salga por abajo en una pantalla corta. */
.dropdown-subpanel--secs {
    min-width: 210px;
    max-height: min(70vh, 460px);
    overflow-y: auto;
    z-index: 230;   /* por encima del panel de personajes del que cuelga */
}

.dropdown-link--sec {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.86rem;
}

/* En estrecho los tres niveles se apilan hacia abajo (regla general de @media 860px). Con tres
   sangrias seguidas el texto se iria al centro de la pantalla, asi que el ultimo nivel no sangra
   otra vez: le basta con la linea de la izquierda para leerse como hijo. */
@media (max-width: 860px) {
    .dropdown-subpanel--secs { margin-left: 8px; padding-left: 8px; }
}

.dropdown-link--char {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* 24px es el tamaño nativo de los iconos de clase del cliente (data/jobs/icons/): así no
   se reescalan y no salen borrosos. El flex-shrink evita que un nombre largo los estruje. */
.dropdown-link__jobicon {
    width: 24px;
    height: 24px;
    flex: 0 0 24px;
    object-fit: contain;
    image-rendering: pixelated;
}

/* El nombre cede sitio antes que el nivel: si no cabe, se corta el nombre -- que se sigue
   reconociendo por el principio -- y no el número, que sin su última cifra miente. */
.dropdown-link__charname {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dropdown-link__charlv {
    flex: 0 0 auto;
    margin-left: auto;
    font-size: 0.75rem;
    font-style: normal;
    opacity: 0.75;
}

/* El hover del enlace mete padding-left para desplazar el texto; en una fila de tres piezas
   eso movería el icono fuera de sitio, así que aquí se compensa con el mismo número. */
.dropdown-link--char:hover,
.dropdown-link--char:focus-visible { padding-left: 10px; }

/* ============================================================================
 * necROmantic 2026-08-07 (usuario) — cifras a la derecha de cada sección
 * ============================================================================
 * Minutos de automatización, nivel de jugador, días de racha, personajes y almacén.
 *
 * margin-left:auto las empuja al borde derecho sin tocar el ancho de nada: la fila ya es
 * flex por .dropdown-link, así que la etiqueta ocupa lo que necesite y la cifra se queda
 * pegada al lado contrario.
 *
 * font-variant-numeric: tabular-nums para que "8" y "120" no bailen de ancho al cambiar,
 * que es lo que hace que un menú con cifras vivas parezca que tiembla. */
.navbadge {
    flex: 0 0 auto;
    margin-left: auto;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: 0.72rem;
    font-style: normal;
    font-weight: 600;
    line-height: 1.5;
    font-variant-numeric: tabular-nums;
    border: 1px solid transparent;
    background: var(--alpha-gold-12);
    color: var(--text-link-hover);
}

/* El caret del grupo va DESPUÉS de la cifra, así que la cifra no puede comerse su hueco. */
.dropdown-link--group .navbadge { margin-right: 6px; }

/* Los cuatro estados de la racha, con el mismo vocabulario que escribe el NPC:
   green = fichado hoy · blue = salvado por un protector · red = racha rota ·
   pending = aún no ha cubierto los 15 minutos de hoy.
   Se usan los tokens del tema y no colores sueltos, para que funcione en claro y en oscuro. */
.navbadge--green   { background: rgba(64, 192, 96, 0.18);  color: #6ee08a; border-color: rgba(64, 192, 96, 0.35); }
.navbadge--blue    { background: rgba(80, 150, 240, 0.18); color: #8ab6ff; border-color: rgba(80, 150, 240, 0.35); }
.navbadge--red     { background: rgba(226, 74, 74, 0.18);  color: #ff9090; border-color: rgba(226, 74, 74, 0.35); }
.navbadge--pending { background: rgba(226, 168, 74, 0.18); color: #ffc978; border-color: rgba(226, 168, 74, 0.35); }

/* La cuota en pausa (hay un automatismo en marcha) se marca igual que en la ficha: no es un
   error, es que ese número no está subiendo ahora mismo. */
.navbadge--pausa   { background: rgba(160, 120, 220, 0.18); color: #c9a0ff; border-color: rgba(160, 120, 220, 0.35); }

@media (prefers-color-scheme: light) {
    .navbadge--green   { color: #1d7a3a; }
    .navbadge--blue    { color: #1f5fb0; }
    .navbadge--red     { color: #b02626; }
    .navbadge--pending { color: #9a6410; }
    .navbadge--pausa   { color: #6b3fb0; }
}

/* necROmantic 2026-08-13 -- Acompañantes (/character/<id>/): elementales y homunculo.
   ============================================================================
   LA VITRINA. Cada criatura en su urna de cristal, iluminada por dentro con SU
   propio color, sobre un pedestal. Todo por clases y tokens; ni un color suelto
   fuera de las variables de tema de cada elemento. */

.elecare { margin: 2.25rem 0; }
/* El <h2> de la seccion se retiro el 2026-08-26: el titulo lo pone ahora la cabecera
   del plegable (.fold__title en unknown.css). */
.elecare-empty { color: #9b91c4; margin: 0 0 1.15rem; font-size: .9rem; }
.elecare-empty.is-hidden { display: none; }
.elecare-empty.is-online { color: #d7ab3f; }

.elecare-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
	gap: 1.4rem;
}

/* necROmantic 2026-08-13 (peticion del usuario): CON EL PERSONAJE DENTRO DEL JUEGO, a media luz.

   No es decoracion. Mientras se juega manda la partida: esta pagina no puede escribir, y lo que lee
   es lo ultimo que se guardo -- el personaje vive en la memoria del map-server. Un panel apagado y
   quieto cuenta eso mejor que un aviso, y el aviso sigue arriba a plena luz
   (.elecare-empty.is-online), que es justo lo que hay que poder leer.

   Se apaga la REJILLA y no la seccion entera por eso mismo: el titulo y la explicacion tienen que
   quedar legibles. El JS ademas deja de sondear mientras dure, asi que tampoco parpadea nada. */
.elecare-grid.is-ingame { opacity: .33; }

/* --- El color de cada criatura ------------------------------------------------
   Un solo token por tarjeta (--glow) y de el cuelga TODO: el halo de la urna, el
   filo del cristal, la barra, el nombre. Cambiar un elemento de color es tocar
   una linea, y ninguna pieza se puede quedar descolgada. */
.elecare-card            { --glow: #8f8fa8; --glow-soft: rgba(143,143,168,.30); }
.elecare-card.el-agni    { --glow: #ff7a3d; --glow-soft: rgba(255,122,61,.34); }
.elecare-card.el-aqua    { --glow: #4fb6f0; --glow-soft: rgba(79,182,240,.34); }
.elecare-card.el-ventus  { --glow: #6fe3b5; --glow-soft: rgba(111,227,181,.32); }
.elecare-card.el-tera    { --glow: #d2a25a; --glow-soft: rgba(210,162,90,.32); }
.elecare-card.el-homun   { --glow: #b58ce0; --glow-soft: rgba(181,140,224,.32); }
/* necROmantic 2026-09-03 (peticion del usuario): la tarjeta de la PAPELERA -- un homunculo
   borrado por error que todavia se puede recuperar. Ambar y no morado como el homunculo vivo:
   la tarjeta tiene que leerse como un aviso antes de leer una sola palabra. */
.elecare-card.el-trash   { --glow: #e0b24a; --glow-soft: rgba(224,178,74,.30); }
/* El sprite va apagado porque la criatura NO ESTA: pintarla igual que a las vivas seria decir
   que sigue ahi. Vuelve a color al pasar por encima, que es cuando el jugador la esta mirando. */
.elecare-card.el-trash .elecare-sprite { filter: grayscale(1); opacity: .55; }
.elecare-card.el-trash:hover .elecare-sprite { filter: grayscale(.25); opacity: .85; }
.elecare-trash-when { margin: .35rem 0 0; font-size: .78rem; opacity: .7; }
/* Ya rescatada: se queda en pantalla con el mensaje, apagada y sin invitar a nada mas. Desaparece
   sola en la siguiente lectura del panel. */
.elecare-card.is-done { opacity: .6; }
.elecare-card.is-done .elecare-btn { display: none; }

.elecare-card {
	position: relative;
	display: flex;
	flex-direction: column;
	/* Que todas las de una fila midan lo mismo: la rejilla ya las estira, pero sin esto el
	   contenido manda y quedaban escalonadas. */
	height: 100%;
	border-radius: 1rem;
	overflow: hidden;
	background: linear-gradient(180deg, rgba(26,18,48,.92) 0%, rgba(8,5,16,.96) 100%);
	box-shadow:
		0 2px 4px rgba(0,0,0,.4),
		0 12px 28px rgba(0,0,0,.32),
		inset 0 0 0 1px rgba(178,150,255,.16);
	/* Sin desplazamiento al señalar (peticion del usuario): la tarjeta se ilumina y nada mas.
	   Con cuatro o cinco en rejilla, moverlas hacia arriba hacia saltar la fila entera. */
	transition: box-shadow .22s ease;
}
.elecare-card:hover {
	box-shadow:
		0 4px 8px rgba(0,0,0,.45),
		0 22px 46px rgba(0,0,0,.45),
		inset 0 0 0 1px var(--glow-soft);
}

/* --- LA URNA ---------------------------------------------------------------- */
.elecare-screen {
	position: relative;
	aspect-ratio: 1 / 1;
	display: flex;
	align-items: flex-end;
	justify-content: center;
	padding: 1rem 1rem 1.6rem;
	/* Tres capas: el halo del elemento detras de la criatura, la penumbra del
	   fondo y la vinyeta que cierra los bordes. Sin la vinyeta la urna parece un
	   recorte; con ella, un espacio con profundidad. */
	background:
		radial-gradient(58% 48% at 50% 62%, var(--glow-soft), transparent 70%),
		radial-gradient(120% 80% at 50% -10%, rgba(255,255,255,.09), transparent 60%),
		linear-gradient(180deg, rgba(38,26,66,.95) 0%, rgba(8,5,16,1) 100%);
}
/* El cristal: un filo de luz arriba y un reflejo diagonal muy tenue. */
.elecare-screen::before {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: linear-gradient(115deg, rgba(255,255,255,.07) 0%, transparent 38%);
	box-shadow: inset 0 1px 0 rgba(255,255,255,.13), inset 0 -30px 40px -30px #000;
}
/* EL PEDESTAL. Una losa con su brillo: es lo que convierte "un sprite sobre un
   fondo" en "una pieza expuesta". */
.elecare-screen::after {
	content: "";
	position: absolute;
	left: 50%;
	bottom: .75rem;
	transform: translateX(-50%);
	width: 62%;
	height: .85rem;
	border-radius: 50%;
	background:
		radial-gradient(50% 100% at 50% 50%, var(--glow-soft), transparent 72%),
		rgba(0,0,0,.55);
	filter: blur(2px);
}

.elecare-sprite {
	position: relative;
	z-index: 1;
	/* width/height al 100 % y no max-*: con `max-` el navegador solo ENCOGE lo que se pasa, asi
	   que un Agni pequeño (88x82) se quedaba de miniatura al lado de un Ventus grande (334x356) y
	   la vitrina parecia descuadrada. Dando medida completa, `contain` escala en los dos sentidos
	   y las 33 criaturas ocupan su urna por igual, cada una con su proporcion intacta. */
	/* ABSOLUTO, y esto es lo que cierra el asunto: con la imagen en el flujo normal era ELLA la
	   que fijaba la altura de la urna, asi que el `aspect-ratio` no llegaba a mandar nunca y cada
	   vitrina medía lo que midiera su criatura. Sacandola del flujo, la urna es cuadrada siempre y
	   la criatura se ajusta dentro. */
	/* La caja ocupa la urna entera y el hueco se hace con PADDING, no con las cuatro pegadas.
	   Con `inset` a los cuatro lados y tamaño automatico, una imagen -- que es un elemento
	   reemplazado -- conserva su tamaño intrinseco y se ancla arriba a la izquierda: object-fit
	   no llega a mandar nunca. Dandole medida completa y `border-box`, `contain` escala dentro del
	   hueco y `center bottom` la apoya en el pedestal. */
	position: absolute;
	inset: 0;
	box-sizing: border-box;
	width: 100%;
	height: 100%;
	padding: 2.2rem 1rem 1.5rem;
	object-fit: contain;
	object-position: center bottom;
	image-rendering: pixelated;  /* pixel art: sin esto el navegador lo emborrona al escalar */
	filter: drop-shadow(0 3px 5px rgba(0,0,0,.55)) drop-shadow(0 0 12px var(--glow-soft));
	animation: elecare-float 5.5s ease-in-out infinite;
}
/* Flota un pelin. Muy poco: es una criatura expuesta, no un globo. */
@keyframes elecare-float { 50% { transform: translateY(-3px); } }

/* --- El icono de una mascota (necROmantic 2026-08-13, informe del usuario: "si el icono debe ser
   pequeno no quiero que se vea estirado") -------------------------------------------------------
   Una mascota se ilustra con el icono de su huevo, y un icono de objeto mide 24x24 REALES. La
   regla de arriba esta hecha para sprites de criatura de cientos de pixeles: da medida completa a
   la urna, asi que estiraba esos 24 pixeles hasta ocho veces su tamano. `object-fit: contain`
   evitaba la deformacion -- la proporcion nunca se rompio -- pero un dibujo de 24 puntos ampliado
   x8 se ve como una mancha, y eso es lo que se lee como "estirado".
   Aqui se le da una caja fija de 96 px, que es 24 x CUATRO EXACTOS. El entero es la parte que
   importa: con `image-rendering: pixelated` un factor entero copia cada pixel el mismo numero de
   veces y el dibujo sale nitido; con 3,7 el navegador tiene que repartir medios pixeles y vuelve
   la mancha.
   Se centra con `margin` y NO con `transform`, aunque sea mas corto: la animacion de flotar que
   hereda de .elecare-sprite usa transform, y las dos se pisarian -- el icono daria un salto
   lateral a mitad de cada ciclo. */
.elecare-icon {
	inset: auto 0 1.6rem;
	width: 96px;
	height: 96px;
	margin-inline: auto;
	padding: 0;
	object-fit: contain;
}


/* --- Pastilla de estado y grado ---------------------------------------------- */
.elecare-pill,
.elecare-badge {
	position: absolute;
	top: .7rem;
	z-index: 2;
	padding: .25rem .6rem;
	border-radius: 999px;
	font-size: .68rem;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	background: rgba(8,5,16,.72);
	box-shadow: inset 0 0 0 1px rgba(178,150,255,.20);
	backdrop-filter: blur(3px);
}
.elecare-pills {
	position: absolute;
	top: .7rem; left: .7rem;
	z-index: 2;
	display: flex;
	flex-wrap: wrap;
	gap: .3rem;
}
.elecare-pill { position: static; display: inline-flex; align-items: center; gap: .4rem; }
.elecare-pill::before {
	content: "";
	width: .42rem; height: .42rem;
	border-radius: 50%;
	background: currentColor;
	box-shadow: 0 0 6px currentColor;
}

/* LOS BOCADILLOS, sobre la criatura y no en una etiqueta.
   Van en el tercio superior de la urna, que es el hueco que las siluetas dejan libre: casi todas
   se apoyan abajo, asi que ahi arriba no tapan nada. Y por delante del sprite, para que un
   Senor elemental que llene la caja no se los coma. */
.elecare-says {
	position: absolute;
	top: 16%;
	left: 50%;
	transform: translateX(-50%);
	z-index: 3;
	display: flex;
	align-items: flex-end;
	pointer-events: none;
	animation: elecare-say 2.6s ease-in-out infinite;
}
/* Un balanceo minimo: en el juego el globo aparece y desaparece, y algo de vida evita que
   parezca una calcomania pegada. */
@keyframes elecare-say { 50% { transform: translateX(-50%) translateY(-3px); } }

/* Caja CUADRADA e igual para todos. Los de emotion.act tienen proporciones muy distintas entre
   si -- unos son un globo ancho y otros una gota alta -- asi que con `width: auto` cada uno salia
   de un ancho y el amontonamiento quedaba descuadrado: el solapamiento es un margen fijo y solo
   cuadra si todas las piezas miden lo mismo.
   `contain` mantiene la proporcion de cada dibujo dentro de esa caja comun, sin deformar ninguno. */
.elecare-emote {
	width: 2.1rem;
	height: 2.1rem;
	object-fit: contain;
	object-position: center bottom;
	image-rendering: pixelated;
	filter: drop-shadow(0 2px 3px rgba(0,0,0,.55));
}

/* AMONTONADOS, no en fila (peticion del usuario). Con varias necesidades a la vez los globos se
   pisan y se ladean, como cuando una criatura suelta varias cosas seguidas: el de delante tapa
   un trozo del de detras y se ve que hay mas de uno de un vistazo.
   El desorden es FIJO por posicion, no aleatorio: asi la tarjeta no baila en cada refresco, que
   es cada pocos segundos. */
.elecare-says .elecare-emote:not(:first-child) { margin-left: -.95rem; }
.elecare-says .elecare-emote:nth-child(1) { transform: rotate(-7deg) translateY(2px); z-index: 3; }
.elecare-says .elecare-emote:nth-child(2) { transform: rotate(5deg)  translateY(-4px); z-index: 2; }
.elecare-says .elecare-emote:nth-child(3) { transform: rotate(-3deg) translateY(1px);  z-index: 1; }
.elecare-badge { right: .7rem; color: #cdc4ee; font-weight: 600; letter-spacing: .04em; }

/* El color va POR PASTILLA y no por tarjeta: una criatura puede estar hambrienta, sucia y
   enfadada a la vez, y con el color heredado del estado "dominante" las tres se pintaban igual. */
.elecare-pill.p-ok     { color: #63c58a; }
.elecare-pill.p-hungry { color: #e0b24a; }
.elecare-pill.p-mess,
.elecare-pill.p-upset  { color: #e2726a; }

/* --- Los datos ---------------------------------------------------------------- */
.elecare-body {
	padding: 1rem 1.05rem 1.1rem;
	display: flex;
	flex-direction: column;
	gap: .6rem;
	background: linear-gradient(180deg, rgba(255,255,255,.028), transparent 40%);
}
.elecare-name {
	margin: 0;
	font-size: 1.12rem;
	line-height: 1.15;
	letter-spacing: .01em;
	text-shadow: 0 0 14px var(--glow-soft);
}
.elecare-sub { margin: -.25rem 0 0; font-size: .78rem; color: #9b91c4; letter-spacing: .04em; }

.elecare-bar { display: flex; flex-direction: column; gap: .25rem; }
.elecare-bar > span { display: flex; justify-content: space-between; align-items: baseline; }
.elecare-bar b { font-size: .68rem; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: #8d84b8; }
.elecare-bar i { font-style: normal; font-size: .78rem; color: #cdc4ee; }
.elecare-track {
	height: .34rem;
	border-radius: 999px;
	background: rgba(0,0,0,.45);
	box-shadow: inset 0 0 0 1px rgba(178,150,255,.14);
	overflow: hidden;
}
.elecare-fill {
	display: block;
	height: 100%;
	border-radius: 999px;
	background: linear-gradient(90deg, var(--glow), #fff6);
	box-shadow: 0 0 8px var(--glow-soft);
	transition: width .5s cubic-bezier(.2,.7,.3,1);
}
.elecare-fill.is-low { background: linear-gradient(90deg, #e2726a, #fff4); box-shadow: 0 0 8px rgba(226,114,106,.4); }

.elecare-mood {
	margin: .1rem 0 0;
	padding: .55rem .65rem;
	font-size: .84rem;
	line-height: 1.45;
	color: #b6adda;
	border-radius: .5rem;
	background: rgba(8,5,16,.45);
	box-shadow: inset 0 0 0 1px rgba(178,150,255,.12);
}

/* Los botones, pegados abajo: asi quedan alineados entre tarjetas aunque el texto del estado
   ocupe una linea en una y tres en otra. */
.elecare-body { flex: 1; }
.elecare-actions { display: flex; gap: .6rem; flex-wrap: wrap; margin-top: auto; padding-top: .5rem; }
.elecare-btn {
	flex: 1 1 auto;
	padding: .55rem .8rem;
	font: inherit;
	font-weight: 600;
	letter-spacing: .02em;
	cursor: pointer;
	color: #ece8ff;
	border: 1px solid rgba(178,150,255,.30);
	background: rgba(140,110,225,.14);
	border-radius: .5rem;
	transition: background .16s ease, border-color .16s ease, box-shadow .16s ease, transform .1s ease;
}
.elecare-btn:hover {
	background: var(--glow-soft);
	border-color: var(--glow);
	box-shadow: 0 0 14px var(--glow-soft);
}
.elecare-btn:active { transform: translateY(1px); }

.elecare-msg { margin: 0; min-height: 1.05em; font-size: .8rem; color: #e2726a; }

/* EL AVISO, RODEANDO LA FICHA ENTERA.
   Antes era un `box-shadow: inset` sobre la tarjeta, y por eso solo se veia por abajo: una
   sombra interior la pinta el elemento sobre SU fondo, y encima van la urna y el cuerpo con los
   suyos, que la tapan. Solo asomaba por la franja donde el fondo de la tarjeta quedaba a la
   vista. Se resuelve con una capa propia por delante de todo: mismo radio, sin capturar clics, y
   es su borde el que late. */
.elecare-card::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 5;
	border: 2px solid transparent;
	border-radius: inherit;
	pointer-events: none;
	transition: border-color .3s ease;
}
@keyframes elecare-breathe {
	0%, 100% { border-color: rgba(226,114,106,.28); }
	50%      { border-color: rgba(226,114,106,.95); }
}
.elecare-card.is-poop::after,
.elecare-card.is-angry::after { animation: elecare-breathe 2.8s ease-in-out infinite; }
.elecare-card.is-hungry::after { border-color: rgba(224,178,74,.42); }

@media (prefers-reduced-motion: reduce) {
	.elecare-card, .elecare-card::after, .elecare-sprite, .elecare-says, .elecare-fill, .elecare-btn { animation: none; transition: none; }
	.elecare-card.is-poop::after, .elecare-card.is-angry::after { border-color: rgba(226,114,106,.8); }
}

/* ══════════════════════════════════════════════════════════════════════════════
   necROmantic 2026-09-07 — PASADA DE MÓVIL (petición del usuario)
   ══════════════════════════════════════════════════════════════════════════════

   Va al final de modern.css a propósito: modern.css carga DESPUÉS de unknown.css,
   así que desde aquí se pueden corregir componentes del tema padre (.pnav, .fold)
   sin tocar sus bloques ni duplicar reglas para el escritorio.

   Lo que se arregla, medido a 390 px de ancho (Pixel/iPhone en vertical):

   1. EL ANCHO ÚTIL ERA EL 69% DE LA PANTALLA. La cadena de rellenos sumaba:
      viewport 390 → #site-content-full (−36) → #content-panel (−56) → .pnav (−24)
      o .fold__body (−27) = 269 px para el contenido. Ahora: 390 → 390 → 366 → 366.
      Detalle que hacía falta saber: el `#content-panel { padding: 20px 18px }` que
      unknown.css tiene en su @media de 640 px estaba MUERTO, porque
      `#site-content-full #content-panel` (dos ids) de este mismo fichero le gana
      siempre por especificidad, dentro y fuera de media queries.

   2. LA BARRA SUPERIOR TENÍA 178 px DE VACÍO A LA IZQUIERDA. El logo entero se
      retira a partir de 1300 px (regla de arriba) y nada ocupaba su sitio. Vuelve
      solo la marca, sin el texto.

   3. LOS BOTONES DE LA BARRA NO MEDÍAN LO MISMO NI TENÍAN EL CONTENIDO CENTRADO:
      hamburguesa 40×40, selector de idioma 67×27 y los redondos 42×33; la fila se
      leía escalonada. Y la hamburguesa se llevaba del navegador un
      `border: 2px outset` (marco verde oliva) que además, con el relleno heredado
      de 10px/16px y box-sizing: border-box, dejaba su caja de contenido en 4 px:
      las tres barras se salían 6 px hacia la derecha y NO estaban centradas.

   4. EL PANEL DE NAVEGACIÓN ERA TRANSLÚCIDO. --bg-header lleva alfa (f2), así que
      con el menú abierto se leía el texto de la página por debajo de los enlaces.

   5. LOS GRUPOS DEL MENÚ (WOE, Mercado, Base de datos, Rankings) se desplegaban
      solo con :hover / :focus-within. En un móvil no hay puntero: se abrían o no
      según cómo interpretara el navegador el toque. Ahora los abre el JS con una
      clase, y el :hover se queda para el ratón.

   6. TEMBLORES AL TOCAR. Varios componentes mueven el contenido con :hover
      (padding-left en los enlaces del desplegable y del pie, translateY en las
      tarjetas). En una pantalla táctil el :hover se queda pegado tras el toque, así
      que el texto se desplazaba y se quedaba desplazado. Se anulan con
      @media (hover: none), que es la consulta correcta: mira el dispositivo, no el
      ancho, así que un portátil estrecho conserva sus animaciones.

   7. EL TÍTULO DE UN PLEGABLE SE PINTABA ENCIMA DE SU PASTILLA. .fold__title lleva
      min-width: 0 para que el subtítulo pueda recortarse, pero eso deja que la caja
      encoja por debajo de su texto — y el texto, que no se parte, se dibuja fuera.
      Se veía en "Compañero" contra la pastilla "SIN CONVOCAR".

   Para revertir: borrar este bloque entero. No hay nada suyo más arriba.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ──────────────────────────────────────────────────────────────────────────────
   1. BARRA SUPERIOR — una sola fila de piezas del mismo tamaño
   El corte es 900 px porque es donde la barra pasa a hamburguesa (regla de arriba).
   ────────────────────────────────────────────────────────────────────────────── */
@media (max-width: 900px) {

    /* Alto común de todo lo que se toca en la barra. 40 px es el suelo cómodo con
       el dedo; por debajo de eso se falla el objetivo. */
    :root { --hdr-tap: 40px; }

    .header-modern__bar { gap: 8px; padding: 6px 10px; }

    /* La marca vuelve, sin el texto ni el eslogan: llena el hueco de la izquierda,
       es el enlace a portada y no le quita sitio a nada.
       Hace falta `.header-modern__bar #logo-link` (clase + id) para ganarle a la
       regla de 1300 px, que usa esa misma pareja. */
    .header-modern__bar #logo-link { display: inline-flex; margin-right: auto; }
    .header-modern__bar #logo-text { display: none; }
    .header-modern__bar #logo-mark { width: 36px; height: 36px; }

    /* El `margin-left: auto` de la hamburguesa tiene que irse: con el logo delante
       empujando (margin-right: auto) habría DOS márgenes automáticos y se repartirían
       el hueco, dejando el botón en mitad de la barra. */
    #nav-toggle {
        margin-left: 0;
        width: var(--hdr-tap);
        height: var(--hdr-tap);
        padding: 0;
        border: 0;
        align-items: center;
        justify-content: center;
        border-radius: 12px;
    }
    /* Con la caja ya centrada por flex, el `margin: 0 auto` de las barras sobra
       (y era justamente lo que las descuadraba cuando la caja de contenido medía
       menos que ellas). */
    #nav-toggle span:not(.sr-only) { margin: 0; }

    .header-modern__actions { gap: 6px; }

    /* Selector de idioma: mismo alto que sus vecinos y cada opción con su propio
       objetivo táctil. Antes medía 27 px de alto y sus opciones 21. */
    .lang-switch { height: var(--hdr-tap); padding: 3px; }
    .lang-switch__opt {
        min-width: 34px;
        height: 100%;
        padding: 0 9px;
        font-size: 0.74rem;
    }

    /* Botones de visitante (crear cuenta / entrar): en móvil ya son solo icono,
       así que son cuadrados perfectos con el icono centrado. */
    .hdr-btn {
        width: var(--hdr-tap);
        height: var(--hdr-tap);
        padding: 0;
        gap: 0;
        justify-content: center;
    }

    /* Chip de cuenta: el nombre está oculto en móvil, así que queda imagen + galón.
       Relleno asimétrico a propósito — la imagen es un círculo y aporta su propio
       aire óptico por la izquierda. */
    .account-chip__trigger {
        height: var(--hdr-tap);
        padding: 0 9px 0 4px;
        gap: 6px;
        justify-content: center;
    }
    .account-chip__avatar { width: 32px; height: 32px; }
}

/* ──────────────────────────────────────────────────────────────────────────────
   2. PANEL DE NAVEGACIÓN DESPLEGADO
   ────────────────────────────────────────────────────────────────────────────── */
@media (max-width: 900px) {

    /* Opaco. --bg-header lleva alfa f2 y se leía la página por debajo del menú.
       --bg-sidebar es el gris violeta sólido del tema; ningún color literal aquí. */
    #primary-nav {
        background: var(--bg-sidebar);
        padding: 10px 12px 28px;
        overscroll-behavior: contain;
    }

    .primary-nav__list { gap: 2px; }

    .nav-link {
        min-height: 46px;
        padding: 10px 12px;
        border-radius: 12px;
    }

    /* El galón, al borde derecho. Pegado al texto parecía parte de la palabra, y
       encima quedaba a distinta altura que el de los grupos, que sí va a la derecha. */
    .nav-link .nav-caret { margin-left: auto; margin-right: 0; }

    /* La marca de "estás aquí" es un filo INFERIOR de lado a lado: pensada para una
       barra horizontal. En columna se leía como un separador suelto entre dos
       secciones. Pasa a filo IZQUIERDO, que es la misma marca que ya llevan los
       grupos abiertos: una sola convención en todo el panel. */
    .nav-link.is-current::after {
        left: 5px;
        right: auto;
        top: 10px;
        bottom: 10px;
        width: 3px;
        height: auto;
    }

    /* El desplegable deja de ser una tarjeta dentro de otra tarjeta: aquí no flota
       sobre nada, así que su fondo, su marco, su punta y su min-width de 250 px solo
       quitaban ancho y metían ruido. Queda una lista sangrada con su línea guía.
       La línea va por box-shadow y no por `border`: el sitio no lleva bordes visibles
       y además así no altera la caja.

       Acotado a #primary-nav A PROPOSITO: ver el bloque del chip de cuenta, justo
       debajo. */
    #primary-nav .dropdown-panel {
        min-width: 0;
        max-width: none;
        margin: 2px 0 8px 10px;
        padding: 2px 0 2px 10px;
        border: 0;
        border-radius: 0;
        background: none;
        box-shadow: inset 1px 0 0 var(--alpha-gold-12);
    }
    /* La punta ancla el panel flotante a su botón. Apilado, es un rombo suelto. */
    #primary-nav .dropdown-panel::before { display: none; }

    .dropdown-link { min-height: 44px; }

    /* ── El menú del chip de cuenta ─────────────────────────────────────────
       ESTO ESTABA ROTO ANTES DE ESTA PASADA. La regla de apilado de arriba
       (`.dropdown-panel { position: static }`, en el bloque de 900 px) selecciona
       CUALQUIER desplegable, y el del chip de cuenta no vive dentro de #primary-nav:
       vive en .header-modern__actions, que es la fila de botones de la barra. Al
       volverse estático dejaba de flotar y se metía DENTRO de la barra como un
       hermano más: la barra crecía de 66 px a más de 400, el logo y la hamburguesa
       se iban al centro de la pantalla y el menú quedaba encajado en la cabecera.

       Aquí se le devuelve su sitio: sigue flotando, colgado del borde derecho de su
       propio chip, con el ancho que quepa y con desplazamiento propio si la lista es
       más larga que la pantalla (que lo es: son ocho entradas y tres niveles). */
    .account-chip .dropdown-panel {
        position: absolute;
        top: calc(100% + 6px);
        left: auto;
        right: 0;
        min-width: 0;
        width: min(320px, calc(100vw - 16px));
        max-width: none;
        margin: 0;
        max-height: calc(100dvh - var(--nav-height) - 24px);
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    /* Entre 861 y 900 px la barra ya es de hamburguesa pero los submenús seguían
       siendo paneles flotantes (su regla estática empieza en 860): se salían de la
       pantalla. Se repite aquí el apilado para que no quede esa franja. */
    .dropdown-subpanel {
        position: static;
        min-width: 0;
        max-width: none;
        margin: 2px 0 4px 12px;
        padding: 2px 0 2px 10px;
        border: 0;
        border-radius: 0;
        background: none;
        box-shadow: inset 1px 0 0 var(--alpha-gold-12);
        transform: none;
        display: none;
    }
    .dropdown-group--left > .dropdown-subpanel { transform: none; }

    /* El galón, apuntando hacia abajo también en la franja de 861-900 px: la regla que
       lo gira vive en el bloque de 860, y ahí la barra ya era de hamburguesa pero el
       galón seguía señalando a un lado, hacia donde ya no se abre nada. */
    .dropdown-group__caret { transform: rotate(90deg); }
    .dropdown-group--left .dropdown-group__caret { transform: rotate(-90deg); }

    /* ── EN ESTRECHO MANDA .is-open Y NADA MÁS ────────────────────────────────
       necROmantic 2026-09-07 (segundo aviso del usuario: "se expanden bien pero no se
       llegan a contraer").

       La regla de 860 px abre el submenú con `.dropdown-group:hover` y con
       `:focus-within`. Al TOCAR el botón de desplegar, el botón se queda con el foco
       — que es lo que hace cualquier navegador al pulsar un <button> —, así que
       `:focus-within` seguía cierto y el submenú se quedaba abierto: el segundo toque
       quitaba `.is-open` y no pasaba nada visible. Lo mismo con el `:hover` pegado,
       que en táctil no se va hasta que tocas otra cosa.

       Aquí, con el menú apilado, esas dos aperturas automáticas sobran: hay un botón
       de verdad para cada grupo. Se anulan, y `.is-open` queda como único mando.

       OJO AL ORDEN: `.dropdown-group:focus-within > .dropdown-subpanel` y
       `.dropdown-group.is-open > .dropdown-subpanel` tienen LA MISMA especificidad
       (tres), así que quien gana es la última escrita. Esta tiene que ir antes. */
    .dropdown-group:hover > .dropdown-subpanel,
    .dropdown-group:focus-within > .dropdown-subpanel { display: none; }

    /* La clase la pone js/modern.js al tocar la cabecera del grupo. Con :hover solo,
       en una pantalla táctil el grupo se abría o no según el navegador.

       OJO con las tres propiedades de visibilidad: el submenú nace con
       `opacity: 0; visibility: hidden` para poder fundirse al salir volando en
       escritorio, y ESO NO LO TOCA la regla de 860 px, que solo cambia el `display`.
       Sin repetirlas aquí el grupo se abría — ocupaba su alto, con su línea guía y
       todo — pero por dentro no se veía ni un enlace. */
    .dropdown-group.is-open > .dropdown-subpanel {
        display: flex;
        opacity: 1;
        visibility: visible;
        transform: none;
    }

    /* El galón de un grupo es un chevron horizontal al que la regla de 860 px da un
       cuarto de vuelta para que apunte hacia abajo = "aquí hay más". Abierto tiene que
       apuntar hacia arriba, o sea media vuelta más. Los grupos --left llevan un
       chevron-left, así que su giro va al revés en los dos estados. */
    .dropdown-group.is-open > .dropdown-link--group .dropdown-group__caret {
        transform: rotate(-90deg);
    }
    .dropdown-group--left.is-open > .dropdown-link--group .dropdown-group__caret {
        transform: rotate(90deg);
    }

    /* ── Grupos cuya cabecera es un ENLACE: el nombre navega, la flecha despliega ──
       necROmantic 2026-09-07, petición del usuario. "Mi Cuenta", cada sección de la
       ficha y cada personaje son <a href> a propósito: llevan a una página. En móvil
       eso dejaba su submenú inalcanzable — se veían las opciones un instante y el
       navegador ya se estaba yendo a la ficha.

       Ahora la fila tiene dos objetivos: el enlace, que ocupa lo que sobra, y un botón
       de verdad a su derecha con la flecha dentro. El botón lo fabrica js/modern.js y
       marca el grupo con .has-toggle; sin JavaScript no aparece, y el enlace se
       comporta como siempre.

       El submenú se va a su propia línea con flex-basis 100%: por eso la fila puede ser
       flex sin que el desplegado se meta al lado del botón. */
    .dropdown-group.has-toggle {
        display: flex;
        flex-wrap: wrap;
        align-items: stretch;
    }
    /* `flex: 1 1 0` y `width: auto` A LA VEZ, y las dos hacen falta: .dropdown-link--group
       lleva `width: 100%` de serie (lo necesita cuando es un <button> suelto), y con
       `flex-basis: auto` esa anchura se convierte en el tamaño hipotético del ítem — o sea
       la fila entera —, así que el botón no cabía en la línea y se iba debajo del enlace,
       pequeño y suelto. Con base 0 el enlace ocupa lo que sobre y el botón se queda a su
       derecha, a la altura de la fila. */
    .dropdown-group.has-toggle > .dropdown-link--group {
        flex: 1 1 0;
        width: auto;
        min-width: 0;
    }
    /* `flex: 1 1 100%` y no `0 0 100%`: el submenú lleva `margin-left: 12px` para
       sangrarse, y flex-basis NO cuenta los márgenes. Con base fija se quedaba 12 px
       más ancho que su línea y se salía del panel — 12 px por nivel, acumulados, así
       que en el tercero (las secciones de cada personaje) el botón quedaba cortado
       contra el borde. Con flex-shrink a 1 la línea lo encoge esos 12 px. */
    .dropdown-group.has-toggle > .dropdown-subpanel { flex: 1 1 100%; }

    /* La flecha decorativa que va DENTRO del enlace sobra: ya la lleva el botón, y con
       las dos se leería como si hubiera dos mandos. En escritorio sigue siendo la
       única, porque allí el botón está oculto y el submenú se abre al señalar. */
    .dropdown-group.has-toggle > .dropdown-link--group .dropdown-group__caret { display: none; }
    /* Ese hueco lo reservaba la fila de personaje para la flecha que ya no está. */
    .dropdown-group--char.has-toggle > .dropdown-link--char { padding-right: 8px; }

    .dropdown-group__toggle {
        display: flex;
        flex: 0 0 46px;
        align-items: center;
        justify-content: center;
        margin-left: 4px;
        padding: 0;
        border: 0;
        border-radius: 10px;
        background: var(--alpha-white-05);
        color: var(--text-heading2);
        cursor: pointer;
        transition: background 0.16s ease, color 0.16s ease;
    }
    .dropdown-group__toggle i {
        font-size: 0.74rem;
        transition: transform 0.2s ease;
    }
    .dropdown-group__toggle:hover,
    .dropdown-group__toggle:focus-visible {
        background: var(--alpha-gold-12);
        color: var(--text-link-hover);
    }
    .dropdown-group__toggle:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
    .dropdown-group.is-open > .dropdown-group__toggle {
        background: var(--alpha-gold-12);
        color: var(--text-link-hover);
    }
    .dropdown-group.is-open > .dropdown-group__toggle i { transform: rotate(180deg); }

    /* Con el menú abierto, el fondo ya no se arrastra por detrás del panel.

       Tiene que ir en <html> y con las dos clases: en este tema el elemento que
       desplaza es <html> (`html.theme-modern-doc { overflow-y: auto }`, arriba), y
       `html.theme-modern-doc body.theme-modern { overflow: visible }` — dos elementos
       y dos clases — le gana a cualquier `body.nav-open`. La clase la ponen a la vez
       en <html> y en <body> desde js/modern.js. */
    html.theme-modern-doc.nav-open { overflow: hidden; }
}

/* ──────────────────────────────────────────────────────────────────────────────
   3. CADENA DE RELLENOS DEL CONTENIDO
   El corte es 640 px: teléfono en vertical. Una tableta a 800 px sigue con el
   diseño de escritorio, que ahí sí le cabe.
   ────────────────────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {

    /* Fuera el marco exterior entero: en un teléfono no separa nada de nada, solo
       estrecha la columna 36 px. */
    #site-content-full { padding: 0; }

    /* La tarjeta pasa a ocupar el ancho completo. Sin relleno alrededor no tiene
       sentido redondearle las esquinas: se cortarían contra el borde de la pantalla.
       El margen de arriba es lo único que la separa de la barra. */
    #site-content-full #content-panel {
        margin: 0 auto 24px;
        padding: 12px;
        border-radius: 0;
    }

    /* La portada no tiene tarjeta: su #content-panel es transparente y sin relleno
       (regla body.is-homepage de más arriba, que gana por especificidad a la de aquí
       encima). Sus secciones SÍ son tarjetas, y sin los 18 px que ponía
       #site-content-full se quedaban pegadas al filo de la pantalla, con las esquinas
       redondeadas cortadas. Se le devuelven los laterales — y solo los laterales: el
       carrusel va a sangre y vive fuera de este contenedor. */
    body.is-homepage #site-content-full #content-panel { padding: 0 12px; }

    /* Mosaico de secciones de la ficha (.pnav): deja de ser una tarjeta. Con el
       relleno a 0 las baldosas tocarían el filo de su propio fondo, que es
       exactamente lo que hace que una tarjeta parezca rota; y las baldosas ya traen
       su propio cristal, así que el de debajo no aportaba nada. */
    .pnav {
        margin: 16px 0 4px;
        padding: 0;
        background: none;
        box-shadow: none;
    }
    .pnav__head { margin: 0 0 10px; }

    /* "Mostrar todo" / "Contraer todo" es la salida del filtro, no una sección más:
       con un número impar de baldosas se quedaba a media fila, huérfano al lado de
       un hueco. Fila entera. */
    .pnav__all { grid-column: 1 / -1; }

    /* Cuerpo de los plegables: el relleno lateral se va (el vertical se queda, es lo
       que separa el contenido de la línea de la cabecera) y la cabecera se acerca
       para que las dos columnas queden alineadas. */
    .fold__body { padding-left: 0; padding-right: 0; }
    .fold__head { padding-left: 0.6rem; padding-right: 0.6rem; }

    /* El título encoge por debajo de su propio texto (lleva min-width: 0, que hace
       falta para que el subtítulo se recorte con puntos suspensivos) y su texto, que
       no se parte, se dibujaba FUERA de la caja: en "Compañero" se pintaba por encima
       de la pastilla "SIN CONVOCAR".

       La cura es que la caja recorte lo que se salga, y que la pastilla ceda sitio
       antes que el título — al revés de lo que hacía (`flex: 0 0 auto`, intocable).
       Se probó a bajar la pastilla a una segunda línea con flex-wrap, y quedaba peor:
       las pastillas cortas (un número) seguían cabiendo arriba y las largas no, así
       que el galón acababa en mitad de la fila en unos plegables y al final en otros.
       Con el ancho que gana la página en esta misma pasada (269 → 366 px) no llega a
       recortarse ningún título de los que hay. */
    .fold__title { overflow: hidden; }
    .fold__tag {
        flex: 0 1 auto;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Pestañas de módulo y barra de acciones: eran de 28 y 24 px de alto. */
    .submenu__link  { min-height: 38px; }
    .page-menu-item { min-height: 36px; }

    /* El menú de acciones de cada ficha de personaje (el "⋯" de /account/view/) se
       abría FUERA DE LA PANTALLA: la regla de 620 px de unknown.css lo ancla por su
       izquierda (`right: auto; left: 0`) y ese botón vive en el extremo derecho de la
       tarjeta, así que el panel de 210 px arrancaba en x=324 y se salía 144 px — que
       además no se podían alcanzar, porque quien los recortaba era
       `html.theme-modern-doc { overflow-x: hidden }`. Vuelve a colgar del borde
       derecho, que es lo que hace la regla base, con tope para que quepa siempre.
       Es de la misma familia que el fallo del menú de cuenta: un desplegable que en
       móvil no llevaba a ninguna parte. */
    .chc__menu-panel {
        right: 0;
        left: auto;
        max-width: calc(100vw - 26px);
    }

    /* La tabla de invitaciones de /account/view/ es la ÚNICA de todo el panel que no
       cabe en un móvil: cinco columnas, 596 px, dentro de un cuerpo de 364. Y no se
       podía llegar a lo que sobraba, porque quien la recortaba era
       `html.theme-modern-doc { overflow-x: hidden }`: dos columnas invisibles y sin
       forma de alcanzarlas. Venía de antes de la pasada de móvil (con la columna a
       298 px se perdía todavía más).

       El scroll se le pone A LA TABLA y no a `.fold__body`: dentro del plegable viven
       los menús de objeto, y un `overflow` en el cuerpo los recortaría — está avisado
       en el bloque de .fold de unknown.css. */
    .invites-table {
        display: block;
        overflow-x: auto;
        overscroll-behavior-x: contain;
    }
}

/* ──────────────────────────────────────────────────────────────────────────────
   4. PIE
   ────────────────────────────────────────────────────────────────────────────── */
@media (max-width: 640px) {

    /* El margen negativo existía para escaparse del relleno de #site-content-full.
       Ese relleno ya no está, así que un margen negativo aquí sacaría el pie fuera
       de la pantalla y aparecería barra horizontal. */
    #site-footer-modern {
        margin: 24px 0 0;
        padding: 11px;
    }

    /* Una sola columna dejaba una tira de 15 enlaces y ~700 px de pie que no se
       acaba nunca. En dos columnas se lee de un vistazo y ocupa la mitad.

       Se hace con columnas de texto (columns) y NO con la rejilla: con `grid` los
       tres bloques de enlaces se reparten en filas, y como no miden lo mismo
       (6 enlaces, 3 y 5) quedaba un hueco muerto al lado del mas corto. Las columnas
       de texto reparten el contenido EQUILIBRANDO alto, se ajustan solas si algun dia
       se anade o se quita un bloque, y `break-inside: avoid` impide que una lista se
       parta por la mitad entre columna y columna. */
    .footer-modern__grid {
        display: block;
        columns: 2;
        column-gap: 14px;
    }
    .footer-modern__col {
        break-inside: avoid;
        margin: 0 0 14px;
    }
    /* El texto de marca necesita el ancho entero; los bloques de enlaces no. */
    .footer-modern__brand { column-span: all; }
    .footer-modern__brand p { max-width: none; }

    .footer-brand { font-size: 15px; margin-bottom: 6px; }
    .footer-modern__col h4 { margin: 0 0 6px; font-size: 8.6pt; }
    .footer-modern__col a { padding: 5px 0; font-size: 8.8pt; }

    .footer-modern__bottom {
        margin-top: 16px;
        padding-top: 12px;
        gap: 4px;
    }
}

/* ──────────────────────────────────────────────────────────────────────────────
   5. NADA SE MUEVE AL TOCAR
   (hover: none) = el dispositivo no tiene puntero. Es la consulta correcta aquí:
   en táctil el :hover se queda PEGADO después del toque, así que un desplazamiento
   pensado como reacción momentánea se convierte en un texto descolocado que ya no
   vuelve a su sitio.
   ────────────────────────────────────────────────────────────────────────────── */
@media (hover: none) {

    /* Y el del propio botón de desplegar: encendido es lo que dice "esto está abierto",
       así que un :hover pegado tras el toque lo dejaba mintiendo en un grupo cerrado.
       El estado abierto lo pinta `.dropdown-group.is-open > .dropdown-group__toggle`,
       que con tres clases le gana a esta. */
    .dropdown-group__toggle:hover {
        background: var(--alpha-white-05);
        color: var(--text-heading2);
    }

    /* El realce de la cabecera de un grupo se quedaba encendido después del toque, en
       un grupo que ya estaba cerrado: parecía que seguía abierto. Quien dice "abierto"
       es .is-open, y ese sí se pinta (regla del bloque de 900 px). */
    .dropdown-group:hover > .dropdown-link--group,
    .dropdown-group:focus-within > .dropdown-link--group {
        background: transparent;
        border-color: transparent;
        color: inherit;
    }
    .dropdown-group.is-open > .dropdown-link--group {
        color: var(--text-link-hover);
    }

    /* Estos tres mueven el texto con padding-left: se repite el valor de reposo. */
    .dropdown-link:hover        { padding-left: 10px; }
    .dropdown-link--char:hover  { padding-left: 10px; }
    .footer-modern__col a:hover { padding-left: 0; }

    /* Y estos levantan la caja. */
    .nav-link:hover,
    .btn-primary:hover,
    .btn-ghost:hover,
    .about-widget__cta:hover,
    .feature-card:hover,
    .news-card:hover,
    .pnav__tile:hover { transform: none; }
}
